{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://adiaui.dev/a2ui/v0_9/adiaui_catalog.json",
  "catalogId": "https://adiaui.dev/a2ui/v0_9/adiaui_catalog.json",
  "title": "AdiaUI Catalog",
  "description": "AdiaUI component catalog. A2UI protocol v0.9. Freestanding — all common-type references are inlined into `$defs` so this document can be loaded directly into an LLM prompt with no network fetches.",
  "components": {
    "A2UIRoot": {
      "title": "A2UIRoot",
      "description": "A2UI protocol surface. Connects to a stream source (SSE, WebSocket, JSONL, MCP) and renders A2UI messages as AdiaUI components via the `@adia-ai/a2ui-utils` renderer.",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "active": {
          "description": "True while the stream is connected and receiving messages.",
          "type": "boolean",
          "default": false
        },
        "batch": {
          "description": "Batch renderer updates via requestAnimationFrame for large fan-in.",
          "type": "boolean",
          "default": false
        },
        "component": {
          "const": "A2UIRoot"
        },
        "doc": {
          "description": "Author-driven mode — set to an array of A2UI messages and the renderer resets + replays them. No network/transport involvement. Setting to a new array triggers a full re-render. Use this for editors, previews, tests, and any static-doc authoring loop. When both `src` and `doc` are set, `doc` wins (the stream is not opened). Pass as a JS property; not reflected to an attribute.",
          "type": "array"
        },
        "loading": {
          "description": "True while the stream is connecting.",
          "type": "boolean",
          "default": false
        },
        "src": {
          "description": "Stream source URL (endpoint for SSE/WebSocket, file path for JSONL, tool-call target for MCP).",
          "type": "string",
          "default": ""
        },
        "transport": {
          "description": "Stream transport to use.",
          "type": "string",
          "enum": [
            "sse",
            "ws",
            "websocket",
            "jsonl",
            "mcp"
          ],
          "default": "sse"
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [],
        "category": "container",
        "composes": [],
        "events": {
          "a2ui-action": {
            "description": "Fired when a child element with [data-action] is clicked. detail: { name, sourceComponentId, context }"
          },
          "a2ui-closed": {
            "description": "Fired when the stream ends."
          },
          "a2ui-connected": {
            "description": "Fired when the stream is established."
          },
          "a2ui-error": {
            "description": "Fired when the stream errors. detail: { error }"
          },
          "a2ui-message": {
            "description": "Fired for each A2UI message received. detail: { message }"
          },
          "doc-replaced": {
            "description": "Fired after a full doc reset + replay in author-driven mode. detail: { count }"
          }
        },
        "examples": [],
        "keywords": [
          "a2ui",
          "protocol",
          "renderer",
          "stream",
          "surface",
          "sse",
          "websocket",
          "jsonl",
          "mcp"
        ],
        "name": "A2UIRoot",
        "related": [
          "canvas",
          "inspector"
        ],
        "slots": {
          "default": {
            "description": "The rendered surface. Children are stamped by the A2UI renderer."
          }
        },
        "states": [
          {
            "description": "Default, ready to connect.",
            "name": "idle"
          },
          {
            "description": "Stream is connecting.",
            "name": "loading"
          },
          {
            "description": "Stream is connected and receiving messages.",
            "name": "active"
          }
        ],
        "status": "stable",
        "synonyms": {
          "a2ui-root": [
            "a2ui-canvas-host",
            "a2ui-mount",
            "doc-root"
          ]
        },
        "tag": "a2ui-root",
        "tokens": {},
        "traits": [],
        "version": 1
      }
    },
    "Accordion": {
      "title": "Accordion",
      "description": "Accordion container managing single or multiple open states across\na collection of <accordion-item-ui> children. Each item carries its\nown [open] reflected state; the accordion host coordinates exclusive\nopening when [multiple] is unset (default single-open mode). Use\ninside settings pages, FAQ blocks, or any progressive-disclosure\npattern where one-level collapsible groups suffice — for arbitrary\nhierarchy use <tree-ui>; for in-page view switching use <tabs-ui>.\n",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "component": {
          "const": "Accordion"
        },
        "multiple": {
          "description": "Allow multiple panels to be open simultaneously",
          "type": "boolean",
          "default": false
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [],
        "category": "container",
        "composes": [
          "icon-ui"
        ],
        "events": {
          "toggle": {
            "description": "Fired when the accordion panel opens or closes (single-pane accordion-ui dispatch — multi-pane group emits the same event per child).",
            "detail": {
              "open": {
                "description": "New open state of the panel.",
                "type": "boolean"
              }
            }
          }
        },
        "examples": [
          {
            "description": "Settings panel with accordion sections for profile, notifications, and privacy configuration.",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"Card\",\n    \"children\": [\n      \"hdr\",\n      \"body\",\n      \"ftr\"\n    ]\n  },\n  {\n    \"id\": \"hdr\",\n    \"component\": \"Header\",\n    \"slots\": {\n      \"heading\": \"Settings\",\n      \"description\": \"Manage your account preferences and configuration.\"\n    }\n  },\n  {\n    \"id\": \"body\",\n    \"component\": \"Section\",\n    \"children\": [\n      \"accordion\"\n    ]\n  },\n  {\n    \"id\": \"accordion\",\n    \"component\": \"Accordion\",\n    \"attrs\": {\n      \"type\": \"multiple\"\n    },\n    \"children\": [\n      \"sec-profile\",\n      \"sec-notifications\",\n      \"sec-privacy\"\n    ]\n  },\n  {\n    \"id\": \"sec-profile\",\n    \"component\": \"AccordionItem\",\n    \"attrs\": {\n      \"text\": \"Profile\",\n      \"icon\": \"user\"\n    },\n    \"children\": [\n      \"profile-form\"\n    ]\n  },\n  {\n    \"id\": \"profile-form\",\n    \"component\": \"Column\",\n    \"attrs\": {\n      \"gap\": \"md\"\n    },\n    \"children\": [\n      \"profile-name\",\n      \"profile-email\",\n      \"profile-bio\"\n    ]\n  },\n  {\n    \"id\": \"profile-name\",\n    \"component\": \"Input\",\n    \"attrs\": {\n      \"label\": \"Display Name\",\n      \"placeholder\": \"Enter your name\",\n      \"value\": \"Jane Doe\"\n    }\n  },\n  {\n    \"id\": \"profile-email\",\n    \"component\": \"Input\",\n    \"attrs\": {\n      \"label\": \"Email\",\n      \"type\": \"email\",\n      \"placeholder\": \"you@example.com\",\n      \"value\": \"jane@example.com\"\n    }\n  },\n  {\n    \"id\": \"profile-bio\",\n    \"component\": \"TextArea\",\n    \"attrs\": {\n      \"label\": \"Bio\",\n      \"placeholder\": \"Tell us about yourself\",\n      \"rows\": 3\n    }\n  },\n  {\n    \"id\": \"sec-notifications\",\n    \"component\": \"AccordionItem\",\n    \"attrs\": {\n      \"text\": \"Notifications\",\n      \"icon\": \"bell\"\n    },\n    \"children\": [\n      \"notif-options\"\n    ]\n  },\n  {\n    \"id\": \"notif-options\",\n    \"component\": \"Column\",\n    \"attrs\": {\n      \"gap\": \"md\"\n    },\n    \"children\": [\n      \"notif-email\",\n      \"notif-push\",\n      \"notif-marketing\"\n    ]\n  },\n  {\n    \"id\": \"notif-email\",\n    \"component\": \"Row\",\n    \"attrs\": {\n      \"justify\": \"between\",\n      \"align\": \"center\"\n    },\n    \"children\": [\n      \"notif-email-label\",\n      \"notif-email-toggle\"\n    ]\n  },\n  {\n    \"id\": \"notif-email-label\",\n    \"component\": \"Text\",\n    \"attrs\": {\n      \"variant\": \"body\"\n    },\n    \"content\": \"Email notifications\"\n  },\n  {\n    \"id\": \"notif-email-toggle\",\n    \"component\": \"Toggle\",\n    \"attrs\": {\n      \"checked\": true\n    }\n  },\n  {\n    \"id\": \"notif-push\",\n    \"component\": \"Row\",\n    \"attrs\": {\n      \"justify\": \"between\",\n      \"align\": \"center\"\n    },\n    \"children\": [\n      \"notif-push-label\",\n      \"notif-push-toggle\"\n    ]\n  },\n  {\n    \"id\": \"notif-push-label\",\n    \"component\": \"Text\",\n    \"attrs\": {\n      \"variant\": \"body\"\n    },\n    \"content\": \"Push notifications\"\n  },\n  {\n    \"id\": \"notif-push-toggle\",\n    \"component\": \"Toggle\",\n    \"attrs\": {\n      \"checked\": true\n    }\n  },\n  {\n    \"id\": \"notif-marketing\",\n    \"component\": \"Row\",\n    \"attrs\": {\n      \"justify\": \"between\",\n      \"align\": \"center\"\n    },\n    \"children\": [\n      \"notif-marketing-label\",\n      \"notif-marketing-toggle\"\n    ]\n  },\n  {\n    \"id\": \"notif-marketing-label\",\n    \"component\": \"Text\",\n    \"attrs\": {\n      \"variant\": \"body\"\n    },\n    \"content\": \"Marketing emails\"\n  },\n  {\n    \"id\": \"notif-marketing-toggle\",\n    \"component\": \"Toggle\",\n    \"attrs\": {\n      \"checked\": false\n    }\n  },\n  {\n    \"id\": \"sec-privacy\",\n    \"component\": \"AccordionItem\",\n    \"attrs\": {\n      \"text\": \"Privacy\",\n      \"icon\": \"lock\"\n    },\n    \"children\": [\n      \"privacy-options\"\n    ]\n  },\n  {\n    \"id\": \"privacy-options\",\n    \"component\": \"Column\",\n    \"attrs\": {\n      \"gap\": \"md\"\n    },\n    \"children\": [\n      \"priv-profile-vis\",\n      \"priv-activity\",\n      \"priv-data\"\n    ]\n  },\n  {\n    \"id\": \"priv-profile-vis\",\n    \"component\": \"Row\",\n    \"attrs\": {\n      \"justify\": \"between\",\n      \"align\": \"center\"\n    },\n    \"children\": [\n      \"priv-profile-label\",\n      \"priv-profile-toggle\"\n    ]\n  },\n  {\n    \"id\": \"priv-profile-label\",\n    \"component\": \"Text\",\n    \"attrs\": {\n      \"variant\": \"body\"\n    },\n    \"content\": \"Public profile\"\n  },\n  {\n    \"id\": \"priv-profile-toggle\",\n    \"component\": \"Toggle\",\n    \"attrs\": {\n      \"checked\": true\n    }\n  },\n  {\n    \"id\": \"priv-activity\",\n    \"component\": \"Row\",\n    \"attrs\": {\n      \"justify\": \"between\",\n      \"align\": \"center\"\n    },\n    \"children\": [\n      \"priv-activity-label\",\n      \"priv-activity-toggle\"\n    ]\n  },\n  {\n    \"id\": \"priv-activity-label\",\n    \"component\": \"Text\",\n    \"attrs\": {\n      \"variant\": \"body\"\n    },\n    \"content\": \"Show activity status\"\n  },\n  {\n    \"id\": \"priv-activity-toggle\",\n    \"component\": \"Toggle\",\n    \"attrs\": {\n      \"checked\": false\n    }\n  },\n  {\n    \"id\": \"priv-data\",\n    \"component\": \"Row\",\n    \"attrs\": {\n      \"justify\": \"between\",\n      \"align\": \"center\"\n    },\n    \"children\": [\n      \"priv-data-label\",\n      \"priv-data-toggle\"\n    ]\n  },\n  {\n    \"id\": \"priv-data-label\",\n    \"component\": \"Text\",\n    \"attrs\": {\n      \"variant\": \"body\"\n    },\n    \"content\": \"Allow analytics collection\"\n  },\n  {\n    \"id\": \"priv-data-toggle\",\n    \"component\": \"Toggle\",\n    \"attrs\": {\n      \"checked\": true\n    }\n  },\n  {\n    \"id\": \"ftr\",\n    \"component\": \"Footer\",\n    \"children\": [\n      \"save-btn\"\n    ]\n  },\n  {\n    \"id\": \"save-btn\",\n    \"component\": \"Button\",\n    \"attrs\": {\n      \"variant\": \"primary\"\n    },\n    \"content\": \"Save Changes\"\n  }\n]",
            "name": "accordion-settings"
          },
          {
            "description": "Frequently asked questions presented in an accordion layout with expandable question/answer items.",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"Card\",\n    \"children\": [\n      \"hdr\",\n      \"body\"\n    ]\n  },\n  {\n    \"id\": \"hdr\",\n    \"component\": \"Header\",\n    \"children\": [\n      \"title\",\n      \"desc\"\n    ]\n  },\n  {\n    \"id\": \"title\",\n    \"component\": \"Text\",\n    \"slot\": \"heading\",\n    \"variant\": \"section\",\n    \"textContent\": \"Frequently Asked Questions\"\n  },\n  {\n    \"id\": \"desc\",\n    \"component\": \"Text\",\n    \"slot\": \"description\",\n    \"variant\": \"caption\",\n    \"textContent\": \"Find answers to common questions about our platform.\"\n  },\n  {\n    \"id\": \"body\",\n    \"component\": \"Section\",\n    \"children\": [\n      \"col-wrap\"\n    ]\n  },\n  {\n    \"id\": \"accordion\",\n    \"component\": \"Accordion\",\n    \"children\": [\n      \"q1\",\n      \"q2\",\n      \"q3\",\n      \"q4\",\n      \"q5\"\n    ]\n  },\n  {\n    \"id\": \"q1\",\n    \"component\": \"AccordionItem\",\n    \"text\": \"What is included in the free plan?\",\n    \"children\": [\n      \"a1\"\n    ]\n  },\n  {\n    \"id\": \"a1\",\n    \"component\": \"Text\",\n    \"variant\": \"body\",\n    \"textContent\": \"The free plan includes up to 3 projects, 1 GB of storage, and access to community support forums.\"\n  },\n  {\n    \"id\": \"q2\",\n    \"component\": \"AccordionItem\",\n    \"text\": \"Can I upgrade or downgrade at any time?\",\n    \"children\": [\n      \"a2\"\n    ]\n  },\n  {\n    \"id\": \"a2\",\n    \"component\": \"Text\",\n    \"variant\": \"body\",\n    \"textContent\": \"Yes, you can change your plan at any time. When upgrading, you'll be charged a prorated amount.\"\n  },\n  {\n    \"id\": \"q3\",\n    \"component\": \"AccordionItem\",\n    \"text\": \"How does billing work for teams?\",\n    \"children\": [\n      \"a3\"\n    ]\n  },\n  {\n    \"id\": \"a3\",\n    \"component\": \"Text\",\n    \"variant\": \"body\",\n    \"textContent\": \"Team billing is per-seat. You're charged for each active team member on a monthly or annual basis.\"\n  },\n  {\n    \"id\": \"q4\",\n    \"component\": \"AccordionItem\",\n    \"text\": \"Do you offer refunds?\",\n    \"children\": [\n      \"a4\"\n    ]\n  },\n  {\n    \"id\": \"a4\",\n    \"component\": \"Text\",\n    \"variant\": \"body\",\n    \"textContent\": \"We offer a full refund within 30 days of purchase. After 30 days, we provide prorated refunds for annual plans.\"\n  },\n  {\n    \"id\": \"q5\",\n    \"component\": \"AccordionItem\",\n    \"text\": \"Is my data secure?\",\n    \"children\": [\n      \"a5\"\n    ]\n  },\n  {\n    \"id\": \"a5\",\n    \"component\": \"Text\",\n    \"variant\": \"body\",\n    \"textContent\": \"We use AES-256 encryption at rest, TLS 1.3 in transit, and are SOC 2 Type II certified.\"\n  },\n  {\n    \"id\": \"col-wrap\",\n    \"component\": \"Column\",\n    \"children\": [\n      \"accordion\"\n    ],\n    \"gap\": \"4\"\n  }\n]",
            "name": "faq-accordion"
          }
        ],
        "keywords": [
          "accordion",
          "options",
          "faq",
          "questions",
          "help",
          "support",
          "knowledge-base",
          "collapse",
          "expand"
        ],
        "name": "UIAccordion",
        "related": [
          "accordion-item",
          "input",
          "text-area",
          "toggle",
          "button"
        ],
        "slots": {
          "default": {
            "description": "accordion-item-ui children"
          }
        },
        "states": [
          {
            "description": "Default, ready for interaction.",
            "name": "idle"
          }
        ],
        "status": "stable",
        "synonyms": {
          "accordion": [
            "accordion",
            "faq",
            "settings"
          ],
          "collapse": [
            "accordion",
            "faq",
            "drawer"
          ],
          "expand": [
            "accordion",
            "faq",
            "drawer"
          ],
          "faq": [
            "faq",
            "accordion"
          ],
          "help": [
            "faq",
            "accordion",
            "tooltip"
          ],
          "knowledge-base": [
            "faq",
            "accordion"
          ],
          "options": [
            "settings",
            "radio",
            "segmented",
            "accordion"
          ],
          "questions": [
            "faq",
            "accordion"
          ],
          "support": [
            "faq",
            "accordion",
            "chat"
          ]
        },
        "tag": "accordion-ui",
        "tokens": {},
        "traits": [],
        "version": 1
      }
    },
    "AccordionItem": {
      "title": "AccordionItem",
      "description": "Child of <accordion-ui>. One collapsible section with header + body. Use inside <accordion-ui> only.",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "component": {
          "const": "AccordionItem"
        },
        "open": {
          "description": "Whether the section is expanded.",
          "type": "boolean",
          "default": false
        },
        "text": {
          "description": "Header text — the clickable label that toggles the section.",
          "type": "string"
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [],
        "category": "layout",
        "composes": [],
        "events": {
          "toggle": {
            "description": "Fired when the section opens or closes.",
            "detail": {
              "open": {
                "description": "New open state.",
                "type": "boolean"
              }
            }
          }
        },
        "examples": [],
        "keywords": [
          "accordion-item",
          "collapsible",
          "disclosure",
          "expand",
          "collapse-row",
          "section-toggle"
        ],
        "name": "UIAccordionItem",
        "related": [
          "Accordion",
          "Card"
        ],
        "slots": {
          "action": {
            "description": "§206 (v0.5.7): action buttons inside a custom header (e.g. Copy /\nDownload / settings). Children placed at `[slot=\"action\"]` (or\n`[slot=\"actions\"]`, or marked `[data-no-toggle]`) are excluded from\nthe toggle-on-click cascade — clicking them fires their own handler\nwithout also toggling the section."
          },
          "body": {
            "description": "The section's collapsible content. Renders below the header; hidden when `[open]` is unset. Author-fills with prose, lists, embedded forms, or any rich markup the panel needs."
          },
          "header": {
            "description": "Custom header content. By default `[text]` renders as a plain header\nlabel, but a `[slot=\"header\"]` override lets consumers author rich\nheaders (icon + title + action buttons + caret)."
          }
        },
        "states": [],
        "status": "stable",
        "synonyms": {
          "accordion-item": [
            "collapsible-row",
            "disclosure-row",
            "expansion-panel",
            "expander"
          ]
        },
        "tag": "accordion-item-ui",
        "tokens": {},
        "traits": [],
        "version": 1
      }
    },
    "ActionItem": {
      "title": "ActionItem",
      "description": "Child of <action-list-ui>. One actionable row — icon + label, forwards activation to the parent action-list.",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "component": {
          "const": "ActionItem"
        },
        "disabled": {
          "description": "Disables click + keyboard activation; aria-disabled is set.",
          "type": "boolean",
          "default": false
        },
        "icon": {
          "description": "Leading icon name (Phosphor).",
          "type": "string"
        },
        "text": {
          "description": "Action label.",
          "type": "string"
        },
        "value": {
          "description": "Identifier passed to the action-list change/activate handlers.",
          "type": "string"
        },
        "variant": {
          "description": "Visual variant (default | accent | danger).",
          "type": "string",
          "default": "default"
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [],
        "category": "navigation",
        "composes": [],
        "events": {},
        "examples": [],
        "keywords": [
          "action-item",
          "command-row",
          "inline-action",
          "list-action",
          "action-list-row"
        ],
        "name": "UIActionItem",
        "related": [
          "ActionList",
          "MenuItem",
          "Button"
        ],
        "slots": {
          "icon": {
            "description": "Override the [icon] glyph with a custom slotted element (custom icon-ui, image, avatar). Mutually exclusive with the [icon] attribute — slot child wins."
          }
        },
        "states": [],
        "status": "stable",
        "synonyms": {
          "action-item": [
            "command-item",
            "inline-command",
            "action-row"
          ]
        },
        "tag": "action-item-ui",
        "tokens": {},
        "traits": [],
        "version": 1
      }
    },
    "ActionList": {
      "title": "ActionList",
      "description": "Inline list of command actions with keyboard navigation. Fires action event when an item is clicked or activated via keyboard.",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "component": {
          "const": "ActionList"
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [],
        "category": "navigation",
        "composes": [
          "icon-ui"
        ],
        "events": {
          "action": {
            "description": "Fired on action.",
            "detail": {
              "item": {
                "description": "The triggering list-item element.",
                "type": "object"
              },
              "text": {
                "description": "Item text content or [text] attribute.",
                "type": "string"
              },
              "value": {
                "description": "Item value attribute (preferred over text for stable IDs).",
                "type": "string"
              }
            }
          }
        },
        "examples": [
          {
            "description": "Basic ActionList usage",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"Card\",\n    \"children\": [\n      \"sec\"\n    ]\n  },\n  {\n    \"id\": \"sec\",\n    \"component\": \"Section\",\n    \"children\": [\n      \"comp\"\n    ]\n  },\n  {\n    \"id\": \"comp\",\n    \"component\": \"ActionList\"\n  }\n]",
            "name": "basic-action-list"
          }
        ],
        "keywords": [
          "actionlist",
          "action-list",
          "action",
          "list"
        ],
        "name": "UIActionList",
        "related": [
          "ActionItem",
          "Menu",
          "Button"
        ],
        "slots": {
          "default": {
            "description": "Holds the list's `<action-item-ui>` children (the action items)."
          }
        },
        "states": [
          {
            "description": "Default, ready for interaction.",
            "name": "idle"
          }
        ],
        "status": "stable",
        "synonyms": {
          "action-list": [
            "command-list",
            "action-rows",
            "command-rows"
          ]
        },
        "tag": "action-list-ui",
        "tokens": {},
        "traits": [],
        "version": 1
      }
    },
    "AdminCommand": {
      "title": "AdminCommand",
      "description": "Module-tier command palette wrapper — wraps a native <dialog> and the\ninner <command-ui>. Owns the keyboard shortcut listener, focus\nmanagement, and dismiss handlers. Reflects [open].\n\nSits inside <admin-shell> as a direct child. The host wires\n[data-command-trigger] elements to <admin-command>.show() via lookup.\n\nThis is the bespoke web-component replacement for the legacy\n<dialog data-command> shape per ADR-0023. The legacy shape was\nretired in v0.4.0 per ADR-0024 and is no longer recognized.\n",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "component": {
          "const": "AdminCommand"
        },
        "no-shortcut": {
          "description": "Opts out of the keyboard listener entirely. Use when the host\nwires its own shortcut handling, or when the palette should be\nmouse-only.\n",
          "type": "boolean",
          "default": false
        },
        "open": {
          "description": "Reflected — set while the dialog is showing. Synced with both\nprogrammatic .show()/.hide() and native dialog close events\n(esc key, backdrop click).\n",
          "type": "boolean",
          "default": false
        },
        "shortcut": {
          "description": "Keyboard shortcut binding. \"cmd+k\" responds only on Mac\n(metaKey); \"ctrl+k\" responds only when ctrlKey; \"both\" (default)\nresponds to either, which is the canonical AdiaUI behavior for\ncross-platform Cmd+K affordance.\n",
          "type": "string",
          "enum": [
            "both",
            "cmd+k",
            "ctrl+k"
          ],
          "default": "both"
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [],
        "category": "interaction",
        "composes": [],
        "events": {
          "command-select": {
            "description": "Forwarded from the inner <command-ui> when an option is chosen. Detail mirrors the inner event's detail.",
            "detail": {
              "value": "string"
            }
          }
        },
        "examples": [],
        "keywords": [
          "admin-command",
          "command-palette",
          "palette",
          "cmd-k",
          "keyboard-shortcut",
          "quickaction"
        ],
        "name": "AdminCommand",
        "related": [
          "AdminShell",
          "AdminSidebar",
          "Command"
        ],
        "slots": {
          "default": {
            "description": "Default slot — the inner <command-ui> (and any other content inside the dialog). Authors typically place exactly one <command-ui placeholder=\"…\">."
          }
        },
        "states": [
          {
            "description": "Default, palette closed.",
            "name": "idle"
          },
          {
            "description": "Dialog is showing; first input has focus.",
            "attribute": "open",
            "name": "open"
          }
        ],
        "status": "stable",
        "synonyms": {
          "cmd-k": [
            "ctrl-k",
            "command-shortcut"
          ],
          "command-palette": [
            "palette",
            "quick-action",
            "omnibox"
          ]
        },
        "tag": "admin-command",
        "tokens": {},
        "traits": [],
        "version": 1
      }
    },
    "AdminContent": {
      "title": "AdminContent",
      "description": "Module-tier shell main-column container. CSS-only — no behavior, no\nJS. Sits inside <admin-shell> as the center column between leading\nand trailing sidebars. Authors compose chrome bars + scroll surface\nvia slot vocabulary.\n\nThis is the bespoke replacement for the legacy raw <main> element\ninside admin-shell per ADR-0023. The legacy shape was retired in\nv0.4.0 per ADR-0024 and is no longer recognized.\n",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "component": {
          "const": "AdminContent"
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [],
        "category": "layout",
        "composes": [],
        "events": {},
        "examples": [],
        "keywords": [
          "admin-content",
          "main",
          "center-column",
          "workspace"
        ],
        "name": "AdminContent",
        "related": [
          "AdminShell",
          "AdminSidebar",
          "AdminTopbar",
          "AdminStatusbar",
          "AdminScroll",
          "AdminPage"
        ],
        "slots": {
          "default": {
            "description": "Default content — typically <admin-topbar slot=\"header\">, an <admin-scroll> wrapping content, and an optional <admin-statusbar slot=\"footer\">."
          },
          "footer": {
            "description": "Bottom chrome bar — typically <admin-statusbar>."
          },
          "header": {
            "description": "Top chrome bar — typically <admin-topbar>."
          }
        },
        "states": [
          {
            "description": "Default, the only state.",
            "name": "idle"
          }
        ],
        "status": "stable",
        "synonyms": {
          "main": [
            "content",
            "center",
            "workspace"
          ]
        },
        "tag": "admin-content",
        "tokens": {},
        "traits": [],
        "version": 1
      }
    },
    "AdminEntityItem": {
      "title": "AdminEntityItem",
      "description": "Module-tier shell identity row. CSS-only — no behavior, no JS.\nA composable icon + label + badge unit: a leading icon (or avatar),\na truncating label, and an optional trailing badge that travel\ntogether as one slottable element.\n\nUse it wherever a shell surface shows an entity identity — workspace\nidentity in an <admin-topbar slot=\"header\">, user identity in an\n<admin-statusbar>, the leading item of a breadcrumb, a flyout header,\nor a user row. Inside a collapsible <admin-sidebar> the label and\nbadge hide when the rail collapses; the icon survives — so the same\nmarkup works expanded and collapsed without authoring two shapes.\n\nGeometry mirrors <select-ui>'s trigger row: [slot=\"icon\"] is fixed\n(like [slot=\"leading\"]), [slot=\"label\"] flexes + truncates (like\n[slot=\"display\"]), [slot=\"badge\"] is fixed trailing (like\n[slot=\"caret\"]).\n",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "component": {
          "const": "AdminEntityItem"
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [],
        "category": "layout",
        "composes": [],
        "events": {},
        "examples": [],
        "keywords": [
          "admin-entity-item",
          "entity-item",
          "identity-row",
          "workspace-identity",
          "user-identity",
          "icon-label-badge"
        ],
        "name": "AdminEntityItem",
        "related": [
          "AdminTopbar",
          "AdminStatusbar",
          "AdminSidebar",
          "Select",
          "Badge",
          "Icon"
        ],
        "slots": {
          "default": {
            "description": "Default content — unslotted children flow inline. Prefer the named slots for the canonical icon + label + badge composition."
          },
          "badge": {
            "description": "Optional trailing chip — environment (staging / beta) or role badge. Fixed width. Hidden when a collapsible sidebar collapses."
          },
          "icon": {
            "description": "Leading visual — wrap an <icon-ui> glyph in <span slot=\"icon\"> (canonical: <span slot=\"icon\"><icon-ui name=\"…\"></icon-ui></span>, mirrors the <nav-item-ui> [slot=\"icon\"] convention so the entity icon visually aligns with a column of nav-item icons beneath in the same sidebar). For an avatar, place <img slot=\"icon\"> directly — img gets a circular crop and avatar sizing (no wrapper needed). Fixed width; survives sidebar collapse."
          },
          "label": {
            "description": "Primary text. Flexes to fill the remaining width and truncates with an ellipsis. Hidden when a collapsible sidebar collapses."
          }
        },
        "states": [
          {
            "description": "Default, the only state.",
            "name": "idle"
          }
        ],
        "status": "stable",
        "synonyms": {
          "entity-item": [
            "identity-row",
            "entity-row",
            "identity-item"
          ]
        },
        "tag": "admin-entity-item",
        "tokens": {},
        "traits": [],
        "version": 1
      }
    },
    "AdminPage": {
      "title": "AdminPage",
      "description": "Module-tier page wrapper. CSS-only — no behavior, no JS. Provides\nthe page-content-root container query (named `page-content`) so\ndescendants can adapt to available content width (sidebars expanded\nvs collapsed) instead of viewport width. Stamps the sticky-band\nlayout: <admin-page-header> + <admin-page-body> + optional footer.\n\nReplaces the legacy <article data-content-root> shape per ADR-0023.\n",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "component": {
          "const": "AdminPage"
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [],
        "category": "layout",
        "composes": [],
        "events": {},
        "examples": [],
        "keywords": [
          "admin-page",
          "page-content",
          "container-query-host"
        ],
        "name": "AdminPage",
        "related": [
          "AdminShell",
          "AdminContent",
          "AdminScroll",
          "AdminPageHeader",
          "AdminPageBody"
        ],
        "slots": {
          "default": {
            "description": "Default — typically <admin-page-header> + <admin-page-body>."
          },
          "body": {
            "description": "Centered reading column (alternate slot for the body band)."
          },
          "footer": {
            "description": "Sticky bottom band."
          },
          "header": {
            "description": "Sticky top band (alternate slot for the header band)."
          }
        },
        "states": [
          {
            "description": "Default, the only state.",
            "name": "idle"
          }
        ],
        "status": "stable",
        "synonyms": {
          "page-content": [
            "content-area",
            "content-root",
            "document-region"
          ]
        },
        "tag": "admin-page",
        "tokens": {},
        "traits": [],
        "version": 1
      }
    },
    "AdminPageBody": {
      "title": "AdminPageBody",
      "description": "Module-tier page-body band. CSS-only — no behavior, no JS.\nScrollable centered body inside <admin-page>. Owns full-width\nscroll sizing; wraps an inner <section-ui> or raw <section> for\nthe centered reading column.\n",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "component": {
          "const": "AdminPageBody"
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [],
        "category": "layout",
        "composes": [],
        "events": {},
        "examples": [],
        "keywords": [
          "admin-page-body",
          "page-body",
          "centered-body"
        ],
        "name": "AdminPageBody",
        "related": [
          "AdminPage",
          "AdminPageHeader",
          "Section"
        ],
        "slots": {
          "default": {
            "description": "Default — typically <section-ui> or <section> with the page content. Full-bleed content (iframes, split panes) can sit directly here to opt out of the centered column."
          }
        },
        "states": [
          {
            "description": "Default, the only state.",
            "name": "idle"
          }
        ],
        "status": "stable",
        "synonyms": {
          "page-body": [
            "content-body",
            "document-body"
          ]
        },
        "tag": "admin-page-body",
        "tokens": {},
        "traits": [],
        "version": 1
      }
    },
    "AdminPageFooter": {
      "title": "AdminPageFooter",
      "description": "Module-tier page-footer band. CSS-only — no behavior, no JS.\nSticky BOTTOM band inside <admin-page> — the bottom-anchored\ncounterpart of <admin-page-header>. Owns full-width concerns\n(sticky position, border-top, background); wraps an inner\n<footer-ui> for the centered reading column (max-width, gutter,\nrhythm). Use for persistent page-level chrome — a save / action\nbar, pagination, or legal strip. For shell-tier status chrome\nspanning the whole shell, use <admin-statusbar> instead.\n",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "component": {
          "const": "AdminPageFooter"
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [],
        "category": "layout",
        "composes": [],
        "events": {},
        "examples": [],
        "keywords": [
          "admin-page-footer",
          "page-footer",
          "sticky-footer",
          "save-bar",
          "action-bar"
        ],
        "name": "AdminPageFooter",
        "related": [
          "AdminPage",
          "AdminPageHeader",
          "AdminPageBody",
          "AdminStatusbar",
          "Footer"
        ],
        "slots": {
          "default": {
            "description": "Default — <footer-ui> with footer content (actions, meta, pagination, legal). Raw <footer> works for the CSS rhythm but drops named slots (no <footer-ui> shadow-DOM slot routing)."
          }
        },
        "states": [
          {
            "description": "Default, the only state.",
            "name": "idle"
          }
        ],
        "status": "stable",
        "synonyms": {
          "page-footer": [
            "content-footer",
            "document-footer",
            "action-bar",
            "save-bar"
          ]
        },
        "tag": "admin-page-footer",
        "tokens": {},
        "traits": [],
        "version": 1
      }
    },
    "AdminPageHeader": {
      "title": "AdminPageHeader",
      "description": "Module-tier page-header band. CSS-only — no behavior, no JS.\nSticky top band inside <admin-page>. Owns full-width concerns\n(sticky position, border-bottom, background); wraps an inner\n<header-ui> for the centered reading column (max-width, gutter,\nrhythm). Do NOT use a raw <header> element — slot-named regions\n(action, description, icon, heading) are silently ignored without\n<header-ui>'s shadow-DOM slot routing.\n",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "component": {
          "const": "AdminPageHeader"
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [],
        "category": "layout",
        "composes": [],
        "events": {},
        "examples": [],
        "keywords": [
          "admin-page-header",
          "sticky-header",
          "page-band"
        ],
        "name": "AdminPageHeader",
        "related": [
          "AdminPage",
          "AdminPageBody",
          "Header"
        ],
        "slots": {
          "default": {
            "description": "Default — <header-ui> with title + actions (slot=\"action\"). Raw <header> works for the CSS rhythm but drops named slots."
          }
        },
        "states": [
          {
            "description": "Default, the only state.",
            "name": "idle"
          }
        ],
        "status": "stable",
        "synonyms": {
          "sticky-header": [
            "page-titlebar",
            "top-band"
          ]
        },
        "tag": "admin-page-header",
        "tokens": {},
        "traits": [],
        "version": 1
      }
    },
    "AdminScroll": {
      "title": "AdminScroll",
      "description": "Module-tier shell scroll surface. CSS-only — no behavior, no JS.\nSits inside <admin-content> as the central scrollable region.\nSingle-axis scroll (vertical), scroll-contained so wheel/touch\nevents don't propagate to the document.\n\nReplaces the legacy <section> child of <main> at shell-tier per\nADR-0023.\n",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "component": {
          "const": "AdminScroll"
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [],
        "category": "layout",
        "composes": [],
        "events": {},
        "examples": [],
        "keywords": [
          "admin-scroll",
          "scroll-region",
          "scroll-container"
        ],
        "name": "AdminScroll",
        "related": [
          "AdminShell",
          "AdminContent",
          "AdminPage"
        ],
        "slots": {
          "default": {
            "description": "Scrollable content — typically <admin-page> wrapping the page-tier sticky bands + body."
          }
        },
        "states": [
          {
            "description": "Default, the only state.",
            "name": "idle"
          }
        ],
        "status": "stable",
        "synonyms": {
          "scroll-region": [
            "scroll-area",
            "viewport-content"
          ]
        },
        "tag": "admin-scroll",
        "tokens": {},
        "traits": [],
        "version": 1
      }
    },
    "AdminSidebar": {
      "title": "AdminSidebar",
      "description": "Module-tier shell sidebar — owns resize, snap-to-collapsed, persistence,\nand the [collapsed] reflected attribute. Sits inside <admin-shell> as\nslot=\"leading\" or slot=\"trailing\". Authors compose chrome bars + content\ninside via slot vocabulary.\n\nThis is the bespoke web-component replacement for the legacy\n<aside data-sidebar> shape per ADR-0023. The legacy shape was\nretired in v0.4.0 per ADR-0024 and is no longer recognized.\n",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "collapsed": {
          "description": "Reflected — set when the sidebar's measured width is at or below\n96px. Consumers query this to style \"collapsed mode\" without\nduplicating threshold math.\n",
          "type": "boolean",
          "default": false
        },
        "collapsible": {
          "description": "Opts in to programmatic collapse — toggle button wiring + the\n.toggle() / .collapse() / .expand() public methods.\n",
          "type": "boolean",
          "default": false
        },
        "component": {
          "const": "AdminSidebar"
        },
        "min-width": {
          "description": "Optional override for the snap-floor width. Defaults to reading\nCSS min-width via getComputedStyle.\n",
          "type": "string",
          "default": ""
        },
        "name": {
          "description": "Identifier for localStorage namespacing. Defaults to slot value\n(\"leading\" or \"trailing\"). Override when running multiple sidebars\nwith the same slot.\n",
          "type": "string",
          "default": ""
        },
        "resizable": {
          "description": "Opts in to drag-to-resize behavior. Author supplies a child\n[data-resize] element as the drag handle.\n",
          "type": "boolean",
          "default": false
        },
        "resizing": {
          "description": "Reflected — set during an active pointer-drag on the resize handle.\nUseful for suppressing transitions while dragging.\n",
          "type": "boolean",
          "default": false
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [],
        "category": "layout",
        "composes": [],
        "events": {
          "sidebar-resize": {
            "description": "Bubbles when an active pointer-drag releases.",
            "detail": {
              "name": "string",
              "width": "number"
            }
          },
          "sidebar-toggle": {
            "description": "Bubbles when sidebar collapses or expands.",
            "detail": {
              "expanded": "boolean",
              "name": "string"
            }
          }
        },
        "examples": [],
        "keywords": [
          "admin-sidebar",
          "sidebar",
          "aside",
          "rail",
          "panel",
          "leading",
          "trailing",
          "inspector",
          "nav"
        ],
        "name": "AdminSidebar",
        "related": [
          "AdminShell",
          "AdminCommand",
          "Aside",
          "Nav",
          "NavGroup",
          "NavItem"
        ],
        "slots": {
          "default": {
            "description": "Default content — typically a <nav-ui> for navigation, or a list / tree for the trailing inspector pattern."
          },
          "footer": {
            "description": "Bottom chrome bar (user select, status indicator, etc.)."
          },
          "header": {
            "description": "Top chrome bar (workspace select, breadcrumb, etc.)."
          }
        },
        "states": [
          {
            "description": "Default, expanded.",
            "name": "idle"
          },
          {
            "description": "Sidebar width is at or below the snap threshold; CSS container queries flip child layout to icon-only mode.",
            "attribute": "collapsed",
            "name": "collapsed"
          },
          {
            "description": "Active pointer-drag in progress.",
            "attribute": "resizing",
            "name": "resizing"
          }
        ],
        "status": "stable",
        "synonyms": {
          "collapsed": [
            "minimized",
            "narrow",
            "icon-only"
          ],
          "sidebar": [
            "aside",
            "rail",
            "panel"
          ]
        },
        "tag": "admin-sidebar",
        "tokens": {},
        "traits": [],
        "version": 1
      }
    },
    "AdminStatusbar": {
      "title": "AdminStatusbar",
      "description": "Module-tier shell bottom chrome bar. CSS-only — no behavior, no JS.\nSame shape as <admin-topbar> (icon + heading + description + action\nclusters via slot vocabulary), conventionally used for read-only\nstatus — connection state, sync indicator, footer metadata.\n\nReplaces legacy <footer-ui> usage at shell-tier per ADR-0023. The\nlegacy shape was retired in v0.4.0 per ADR-0024 and is no longer\nrecognized; new code uses <admin-statusbar> for shell-tier chrome\n(use <footer-ui> for primitive containers like Card / Drawer /\nModal).\n",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "component": {
          "const": "AdminStatusbar"
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [],
        "category": "layout",
        "composes": [],
        "events": {},
        "examples": [],
        "keywords": [
          "admin-statusbar",
          "statusbar",
          "footer-bar",
          "app-footer",
          "status-line"
        ],
        "name": "AdminStatusbar",
        "related": [
          "AdminShell",
          "AdminContent",
          "AdminTopbar",
          "AdminEntityItem",
          "Footer"
        ],
        "slots": {
          "description": {
            "description": "Secondary metadata."
          },
          "default": {
            "description": "Default content — status text or inline children."
          },
          "action": {
            "description": "Trailing control cluster."
          },
          "action-leading": {
            "description": "Leading control cluster."
          },
          "heading": {
            "description": "Primary label."
          },
          "icon": {
            "description": "Leading glyph (icon-ui or img)."
          }
        },
        "states": [
          {
            "description": "Default, the only state.",
            "name": "idle"
          }
        ],
        "status": "stable",
        "synonyms": {
          "statusbar": [
            "status-line",
            "footer-bar",
            "app-footer"
          ]
        },
        "tag": "admin-statusbar",
        "tokens": {},
        "traits": [],
        "version": 1
      }
    },
    "AdminTopbar": {
      "title": "AdminTopbar",
      "description": "Module-tier shell top chrome bar. CSS-only — no behavior, no JS.\nSits at the top of <admin-content>, <admin-sidebar>, or any chrome\nregion. Provides the canonical icon + heading + description +\naction-clusters layout via slot vocabulary.\n\nReplaces the legacy <header-ui> usage at shell-tier per ADR-0023.\nThe legacy shape was retired in v0.4.0 per ADR-0024 and is no\nlonger recognized; new code uses <admin-topbar> for shell-tier\nchrome bars (use <header-ui> for primitive containers like Card /\nDrawer / Modal).\n",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "component": {
          "const": "AdminTopbar"
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [],
        "category": "layout",
        "composes": [],
        "events": {},
        "examples": [],
        "keywords": [
          "admin-topbar",
          "topbar",
          "chrome-bar",
          "app-header",
          "shell-header"
        ],
        "name": "AdminTopbar",
        "related": [
          "AdminShell",
          "AdminContent",
          "AdminSidebar",
          "AdminStatusbar",
          "AdminEntityItem",
          "Header"
        ],
        "slots": {
          "description": {
            "description": "Secondary metadata. Muted + smaller font."
          },
          "default": {
            "description": "Default content — typically a breadcrumb, page title, or ad-hoc inline children. Use named slots for canonical clusters."
          },
          "action": {
            "description": "Trailing control cluster (buttons, menus, etc.). The first [slot=\"action\"] child pushes itself + siblings to the end; subsequent siblings flow with gap."
          },
          "action-leading": {
            "description": "Leading control cluster (back button, menu trigger, etc.). Pairs with [slot=\"action\"] for dual-cluster chrome."
          },
          "heading": {
            "description": "Primary label. Medium-weight + strong fg."
          },
          "icon": {
            "description": "Leading glyph (icon-ui or img). Muted color, flex-aligned."
          }
        },
        "states": [
          {
            "description": "Default, the only state.",
            "name": "idle"
          }
        ],
        "status": "stable",
        "synonyms": {
          "topbar": [
            "appbar",
            "app-header",
            "header-bar",
            "navbar"
          ]
        },
        "tag": "admin-topbar",
        "tokens": {},
        "traits": [],
        "version": 1
      }
    },
    "AgentArtifact": {
      "title": "AgentArtifact",
      "description": "Inline container for structured agent artifacts (A2UI, JSON, tickets, code). Renders inside <chat-thread-ui> message bodies or <inspector-ui> panes as a labeled, optionally collapsible block with content-type-aware rendering. Use for agent-emitted structured payloads; for free-text agent output use <text-ui> or <richtext-ui> instead.",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "title": {
          "description": "Header title.",
          "type": "string",
          "default": ""
        },
        "collapsed": {
          "description": "Start collapsed.",
          "type": "boolean",
          "default": false
        },
        "component": {
          "const": "AgentArtifact"
        },
        "icon": {
          "description": "icon-ui name in header.",
          "type": "string",
          "default": ""
        },
        "kind": {
          "description": "Badge label; value is normalized to uppercase before rendering.",
          "type": "string",
          "default": ""
        },
        "tone": {
          "description": "neutral | accent | warning | danger",
          "type": "string",
          "default": "neutral"
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [],
        "category": "agent",
        "composes": [
          "icon-ui",
          "badge-ui"
        ],
        "events": {
          "artifact-toggle": {
            "description": "Fired on artifact-toggle.",
            "detail": {
              "collapsed": {
                "description": "New collapsed state after the toggle.",
                "type": "boolean"
              }
            }
          }
        },
        "examples": [
          {
            "description": "Artifact with a code body and two actions.",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"AgentArtifact\",\n    \"title\": \"product-card\",\n    \"kind\": \"A2UI\",\n    \"icon\": \"layout\"\n  }\n]",
            "name": "basic"
          }
        ],
        "keywords": [
          "artifact",
          "container",
          "inline",
          "preview",
          "attachment"
        ],
        "name": "UIAgentArtifact",
        "related": [
          "card-ui",
          "code-ui"
        ],
        "slots": {
          "default": {
            "description": "Default slot — primary child content."
          },
          "primary": {
            "description": "Child content region for the `primary` slot."
          },
          "secondary": {
            "description": "Child content region for the `secondary` slot."
          }
        },
        "states": [
          {
            "description": "Default, ready for interaction.",
            "name": "idle"
          }
        ],
        "status": "stable",
        "synonyms": {
          "artifact": [
            "agent-artifact",
            "tool-output",
            "agent-output",
            "tool-result"
          ]
        },
        "tag": "agent-artifact-ui",
        "tokens": {},
        "traits": [],
        "version": 1
      }
    },
    "AgentFeedbackBar": {
      "title": "AgentFeedbackBar",
      "description": "Agent-response feedback bar — thumbs up / thumbs down rating row\nplus an optional Save action, rendered beneath an LLM-generated\nmessage. Composes <button-ui> children for the affordances; emits\n`feedback` event with detail.{value, action} on rating. Sits as the\ntrailing chrome of a chat message bubble or alongside an\n<agent-trace-ui> step — used in chat-shell, gen-ui canvas, and\ninspector flows.\n",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "component": {
          "const": "AgentFeedbackBar"
        },
        "disabled": {
          "description": "Disable all actions.",
          "type": "boolean",
          "default": false
        },
        "saveIcon": {
          "description": "Save button icon.",
          "type": "string",
          "default": "bookmark-simple"
        },
        "saveLabel": {
          "description": "Save button text; empty hides it.",
          "type": "string",
          "default": ""
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [],
        "category": "agent",
        "composes": [
          "button-ui"
        ],
        "events": {
          "feedback-rate": {
            "description": "Fired on feedback-rate.",
            "detail": {
              "rating": {
                "description": "Rating value selected by the user.",
                "type": "number"
              }
            }
          },
          "feedback-save": {
            "description": "Fired on feedback-save."
          }
        },
        "examples": [
          {
            "description": "Thumbs + save",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"AgentFeedbackBar\",\n    \"saveLabel\": \"Save pattern\"\n  }\n]",
            "name": "basic"
          }
        ],
        "keywords": [
          "feedback",
          "thumbs",
          "rating",
          "save",
          "bookmark"
        ],
        "name": "UIAgentFeedbackBar",
        "related": [
          "agent-suggestions-ui",
          "agent-trace-ui"
        ],
        "slots": {
          "default": {
            "description": "Default slot — primary child content."
          }
        },
        "states": [
          {
            "description": "Default, ready for interaction.",
            "name": "idle"
          },
          {
            "description": "Non-interactive; dimmed.",
            "attribute": "disabled",
            "name": "disabled"
          }
        ],
        "status": "stable",
        "synonyms": {
          "feedback-bar": [
            "agent-feedback",
            "response-feedback",
            "thumbs-bar",
            "rating-bar"
          ]
        },
        "tag": "agent-feedback-bar-ui",
        "tokens": {},
        "traits": [],
        "version": 1
      }
    },
    "AgentQuestions": {
      "title": "AgentQuestions",
      "description": "Multi-choice clarifying-question card emitted by an agent when it\nneeds disambiguation before proceeding. Renders the question prompt\n+ a slotted list of <button-ui> answer chips (or radio-style cards\nwhen [multi] is set for multi-select). The submit button fires\n`answer` with detail.{value(s)} once the user confirms. Use for\nagentic clarification turns — not generic form input (use\n<field-ui> + form primitives for that).\n",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "component": {
          "const": "AgentQuestions"
        },
        "helper": {
          "description": "Helper text.",
          "type": "string",
          "default": ""
        },
        "multi": {
          "description": "Allow multi-select.",
          "type": "boolean",
          "default": false
        },
        "question": {
          "description": "Headline question.",
          "type": "string",
          "default": ""
        },
        "submitLabel": {
          "description": "Submit button label (multi mode).",
          "type": "string",
          "default": "Continue"
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [],
        "category": "agent",
        "composes": [
          "button-ui"
        ],
        "events": {
          "questions-answer": {
            "description": "Fired on questions-answer.",
            "detail": {
              "option": {
                "description": "The full selected option object.",
                "type": "object"
              },
              "selected": {
                "description": "Array of selected option IDs.",
                "type": "array"
              }
            }
          }
        },
        "examples": [
          {
            "description": "Three-option clarifying question",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"AgentQuestions\",\n    \"question\": \"Which direction fits best?\"\n  }\n]",
            "name": "basic"
          }
        ],
        "keywords": [
          "questions",
          "choices",
          "options",
          "multiple choice",
          "elicit",
          "clarify"
        ],
        "name": "UIAgentQuestions",
        "related": [
          "agent-suggestions-ui",
          "agent-reasoning-ui"
        ],
        "slots": {
          "default": {
            "description": "Default slot — primary child content."
          }
        },
        "states": [
          {
            "description": "Default, ready for interaction.",
            "name": "idle"
          }
        ],
        "status": "stable",
        "synonyms": {
          "questions": [
            "clarifying-questions",
            "agent-prompt",
            "disambiguation"
          ]
        },
        "tag": "agent-questions-ui",
        "tokens": {},
        "traits": [],
        "version": 1
      }
    },
    "AgentReasoning": {
      "title": "AgentReasoning",
      "description": "Agent inner monologue + pipeline viewer with steps, thoughts, plans, and iterations.",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "collapsed": {
          "description": "Start collapsed.",
          "type": "boolean",
          "default": false
        },
        "component": {
          "const": "AgentReasoning"
        },
        "heading": {
          "description": "Fallback summary label.",
          "type": "string",
          "default": ""
        },
        "noAutocollapse": {
          "description": "Disable auto-collapse after finish().",
          "type": "boolean",
          "default": false
        },
        "status": {
          "description": "Drives the status icon — idle, active (spinner), done (check), error (warning).",
          "type": "string",
          "enum": [
            "idle",
            "active",
            "done",
            "error"
          ],
          "default": "active"
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [],
        "category": "agent",
        "composes": [
          "timeline-ui",
          "timeline-item-ui"
        ],
        "events": {
          "reasoning-finish": {
            "description": "Fired on reasoning-finish.",
            "detail": {
              "status": {
                "description": "Whether reasoning was resolved.",
                "type": "boolean"
              },
              "summary": {
                "description": "Summary label text rendered after finish.",
                "type": "string"
              }
            }
          },
          "reasoning-step-toggle": {
            "description": "Fired on reasoning-step-toggle.",
            "detail": {
              "stepId": {
                "description": "ID of the toggled reasoning step (matches data-step-id).",
                "type": "string"
              }
            }
          },
          "reasoning-toggle": {
            "description": "Fired on reasoning-toggle.",
            "detail": {
              "collapsed": {
                "description": "Whether the reasoning section is now collapsed.",
                "type": "boolean"
              }
            }
          }
        },
        "examples": [
          {
            "description": "Agent reasoning with a plan and three steps.",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"AgentReasoning\",\n    \"heading\": \"Analyzing request\"\n  }\n]",
            "name": "basic"
          }
        ],
        "keywords": [
          "reasoning",
          "thinking",
          "agent",
          "chain of thought",
          "cot",
          "monologue",
          "plan",
          "iteration"
        ],
        "name": "UIAgentReasoning",
        "related": [
          "agent-trace-ui",
          "pipeline-status-ui"
        ],
        "slots": {
          "default": {
            "description": "Default slot — primary child content."
          }
        },
        "states": [
          {
            "description": "Default, ready for interaction.",
            "name": "idle"
          }
        ],
        "status": "stable",
        "synonyms": {
          "chain-of-thought-ui": "agent-reasoning-ui",
          "cot-ui": "agent-reasoning-ui"
        },
        "tag": "agent-reasoning-ui",
        "tokens": {},
        "traits": [],
        "version": 1
      }
    },
    "AgentSuggestions": {
      "title": "AgentSuggestions",
      "description": "Row of follow-up suggestion chips presented under an agent response.\nEach suggestion is a <button-ui> child the user can tap to send the\ntext back as the next prompt. Composes <button-ui> with chip-style\nvisual treatment; the variant + size props cascade to children. Use\nto lower input friction at the bottom of a chat response; not for\npermanent navigation (that's <nav-ui>).\n",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "component": {
          "const": "AgentSuggestions"
        },
        "disabled": {
          "description": "Disable all chips.",
          "type": "boolean",
          "default": false
        },
        "size": {
          "description": "sm | md",
          "type": "string",
          "default": "sm"
        },
        "variant": {
          "description": "outline | ghost | subtle",
          "type": "string",
          "default": "outline"
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [],
        "category": "agent",
        "composes": [
          "button-ui"
        ],
        "events": {
          "suggestion-select": {
            "description": "Fired on suggestion-select.",
            "detail": {
              "index": {
                "description": "Index of the selected suggestion.",
                "type": "number"
              },
              "label": {
                "description": "Suggestion label text.",
                "type": "string"
              },
              "prompt": {
                "description": "Suggestion prompt content.",
                "type": "string"
              }
            }
          }
        },
        "examples": [
          {
            "description": "Three follow-up chips",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"AgentSuggestions\"\n  }\n]",
            "name": "basic"
          }
        ],
        "keywords": [
          "suggestions",
          "chips",
          "follow-up",
          "quick replies"
        ],
        "name": "UIAgentSuggestions",
        "related": [
          "agent-questions-ui",
          "agent-feedback-bar-ui"
        ],
        "slots": {
          "default": {
            "description": "Default slot — primary child content."
          }
        },
        "states": [
          {
            "description": "Default, ready for interaction.",
            "name": "idle"
          },
          {
            "description": "Non-interactive; dimmed.",
            "attribute": "disabled",
            "name": "disabled"
          }
        ],
        "status": "stable",
        "synonyms": {
          "suggestions": [
            "follow-ups",
            "follow-up-chips",
            "prompts",
            "completions"
          ]
        },
        "tag": "agent-suggestions-ui",
        "tokens": {},
        "traits": [],
        "version": 1
      }
    },
    "AgentTrace": {
      "title": "AgentTrace",
      "description": "Collapsible metrics + training-feedback panel for an agent turn. Shows reasoning steps, tool calls, latency, and token counts with a thumbs-up/down feedback affordance. Use inside <chat-thread-ui> message bodies for expert/debug views; hide by default in user-facing chat.",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "collapsed": {
          "description": "Hide the trace body. Default-visible disclosure (matches the agent-* family — agent-reasoning, agent-artifact). Set to opt out.",
          "type": "boolean",
          "default": false
        },
        "component": {
          "const": "AgentTrace"
        },
        "label": {
          "description": "Fallback summary label.",
          "type": "string",
          "default": ""
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [],
        "category": "agent",
        "composes": [],
        "events": {
          "trace-toggle": {
            "description": "Fired on trace-toggle.",
            "detail": {
              "collapsed": {
                "description": "Whether the trace is now collapsed.",
                "type": "boolean"
              }
            }
          }
        },
        "examples": [
          {
            "description": "Trace with pills and a 3-col metric grid.",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"AgentTrace\"\n  }\n]",
            "name": "basic"
          }
        ],
        "keywords": [
          "trace",
          "metrics",
          "confidence",
          "telemetry",
          "training feedback"
        ],
        "name": "UIAgentTrace",
        "related": [
          "agent-reasoning-ui",
          "agent-feedback-bar-ui"
        ],
        "slots": {
          "default": {
            "description": "Default slot — primary child content."
          }
        },
        "states": [
          {
            "description": "Default, ready for interaction.",
            "name": "idle"
          }
        ],
        "status": "stable",
        "synonyms": {
          "trace": [
            "agent-trace",
            "reasoning-trace",
            "tool-trace",
            "agent-log"
          ]
        },
        "tag": "agent-trace-ui",
        "tokens": {},
        "traits": [],
        "version": 1
      }
    },
    "Alert": {
      "title": "Alert",
      "description": "Inline alert banner — a persistent, in-flow notice with icon +\ntitle + description + optional dismiss + slotted action. Variants\nmap to semantic severity (info / success / warning / danger).\nDistinct from <toast-ui> (transient global notification with\nauto-dismiss) and from <empty-state-ui> (zero-data placeholder).\nUse alert-ui for inline contextual notices the user should see\nbefore continuing — form-level errors, banner-style status,\ninline upgrade prompts.\n",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "title": {
          "description": "Bold headline rendered as the first line of the alert content. Pair with [description] for the canonical \"banner\" pattern (headline + body). When [title] or [description] is set, the [text] prop is ignored.",
          "type": "string",
          "default": ""
        },
        "description": {
          "description": "Body text rendered as the second line of the alert content, below [title]. May be used alone (without [title]) for a single muted-body message.",
          "type": "string",
          "default": ""
        },
        "amount": {
          "description": "Dunning mode only — the unpaid amount as a decimal major-unit number (`24.50`, not minor units like `2450`). Formatted via `Intl.NumberFormat` using [currency] and [lang]. Ignored when [pattern] is not `dunning`.",
          "type": "number",
          "default": 0
        },
        "cardLast4": {
          "description": "Dunning mode only — last 4 digits of the declined card. Rendered as \"ending 4242\". Ignored when [pattern] is not `dunning`. Attribute spelling: `card-last4`.",
          "type": "string",
          "default": ""
        },
        "closable": {
          "description": "Whether a close button is displayed. Alias [dismissible] is also accepted (same semantics, different spelling — the corpus and many libraries use both; both map to the same state).",
          "type": "boolean",
          "default": false
        },
        "component": {
          "const": "Alert"
        },
        "currency": {
          "description": "Dunning mode only — ISO 4217 currency code driving the `Intl.NumberFormat` style=\"currency\" rendering. Defaults to `USD`.",
          "type": "string",
          "default": "USD"
        },
        "dismissible": {
          "description": "Public alias for [closable] — same semantics. Both attributes render the close button. Use whichever spelling matches your authoring style.",
          "type": "boolean",
          "default": false
        },
        "dueAt": {
          "description": "Dunning mode only — ISO 8601 due / failed-at timestamp. Formatted via `Intl.DateTimeFormat`. Ignored when [pattern] is not `dunning`. Attribute spelling: `due-at`.",
          "type": "string",
          "default": ""
        },
        "icon": {
          "description": "Icon identifier displayed before the message content",
          "type": "string",
          "default": ""
        },
        "pattern": {
          "description": "Domain pattern mode. Default is empty (standard alert). Setting `pattern=\"dunning\"` switches to billing dunning render mode — stamps a formatted amount + due-date + decline-reason from props and re-dispatches descendant `[data-dunning-action]` button clicks as a unified `dunning-action` event. Spec: SPEC-006.",
          "type": "string",
          "enum": [
            "",
            "dunning"
          ],
          "default": ""
        },
        "reason": {
          "description": "Dunning mode only — decline reason. Drives the leading icon (declined → `x-circle`, expired → `clock`, insufficient → `wallet`, network → `wifi-slash`). One of: `declined`, `expired`, `insufficient`, `network`, or empty.",
          "type": "string",
          "enum": [
            "",
            "declined",
            "expired",
            "insufficient",
            "network"
          ],
          "default": ""
        },
        "text": {
          "description": "Single-line alert message. For two-line \"headline + body\" alerts, use [title] + [description] instead. For rich content (links, formatting), use the [slot=\"content\"] slot.",
          "type": "string",
          "default": ""
        },
        "variant": {
          "description": "Semantic color variant.",
          "type": "string",
          "enum": [
            "default",
            "info",
            "success",
            "warning",
            "danger",
            "muted",
            "neutral"
          ],
          "default": "default"
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [
          {
            "fix": "<alert-ui pattern=\"dunning\" variant=\"danger\">",
            "why": "Dunning is always a failure surface; info mis-signals severity.",
            "wrong": "<alert-ui pattern=\"dunning\" variant=\"info\">"
          },
          {
            "fix": "<alert-ui pattern=\"dunning\" amount=\"24.50\" currency=\"USD\" due-at=\"2026-05-20\">",
            "why": "Amount baked into title defeats Intl formatting + telemetry.",
            "wrong": "<alert-ui pattern=\"dunning\" title=\"Payment failed $24.50\">"
          }
        ],
        "category": "container",
        "composes": [],
        "events": {
          "close": {
            "description": "Fired when the close button is clicked"
          },
          "dunning-action": {
            "description": "Dunning pattern only — fired when a descendant button with `[data-dunning-action]` is clicked. Detail shape `{ action, amount, currency, dueAt }`; the action string is the value of the `data-dunning-action` attribute (typically `\"update\"` or `\"retry\"`)."
          }
        },
        "examples": [
          {
            "description": "Single alert component with icon and dismiss action.",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"Alert\",\n    \"variant\": \"info\",\n    \"icon\": \"info-circle\",\n    \"title\": \"System Update\",\n    \"description\": \"A new version is available. Please refresh to get the latest features.\",\n    \"dismissible\": true\n  }\n]",
            "name": "alert-banner"
          },
          {
            "description": "Card with error alert and a retry button for error state display.",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"Card\",\n    \"children\": [\n      \"sec\",\n      \"ftr\"\n    ]\n  },\n  {\n    \"id\": \"sec\",\n    \"component\": \"Section\",\n    \"children\": [\n      \"alert\"\n    ]\n  },\n  {\n    \"id\": \"alert\",\n    \"component\": \"Alert\",\n    \"variant\": \"error\",\n    \"title\": \"Something went wrong\",\n    \"description\": \"We encountered an error while loading the data. Please try again.\"\n  },\n  {\n    \"id\": \"ftr\",\n    \"component\": \"Footer\",\n    \"children\": [\n      \"retry\"\n    ]\n  },\n  {\n    \"id\": \"retry\",\n    \"component\": \"Button\",\n    \"text\": \"Retry\",\n    \"icon\": \"refresh\",\n    \"variant\": \"primary\"\n  }\n]",
            "name": "error-state"
          },
          {
            "description": "Billing dunning banner — declined card with retry + update-card actions (SPEC-006).",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"Alert\",\n    \"pattern\": \"dunning\",\n    \"variant\": \"danger\",\n    \"amount\": 24.5,\n    \"currency\": \"USD\",\n    \"dueAt\": \"2026-05-20T00:00:00Z\",\n    \"cardLast4\": \"4242\",\n    \"reason\": \"declined\",\n    \"children\": [\"btn-update\", \"btn-retry\"]\n  },\n  {\n    \"id\": \"btn-update\",\n    \"component\": \"Button\",\n    \"text\": \"Update payment method\",\n    \"variant\": \"primary\",\n    \"slot\": \"actions\"\n  },\n  {\n    \"id\": \"btn-retry\",\n    \"component\": \"Button\",\n    \"text\": \"Retry charge\",\n    \"variant\": \"outline\",\n    \"slot\": \"actions\"\n  }\n]",
            "name": "dunning-payment-failed"
          }
        ],
        "keywords": [
          "alert",
          "inbox",
          "mailbox",
          "message",
          "snackbar",
          "popup",
          "modal",
          "dialog",
          "banner",
          "warning",
          "error",
          "success",
          "info",
          "confirm",
          "notification",
          "announce"
        ],
        "name": "UIAlert",
        "related": [
          "button"
        ],
        "slots": {
          "action": {
            "description": "Optional trailing action button (e.g. \"Refresh\", \"Status page\"). Right-aligned in the flex layout. See system-banners pattern for examples."
          },
          "actions": {
            "description": "Dunning pattern only — action button stack (typically two `<button-ui>` with `data-dunning-action=\"update\"` and `data-dunning-action=\"retry\"`). Sits below the formatted message in the col layout when `pattern=\"dunning\"`."
          },
          "close": {
            "description": "Close button. Stamped automatically when `closable` is set; the stamped element is `<button-ui slot=\"close\" icon=\"x\" variant=\"ghost\" size=\"sm\">`. Override by passing a custom `slot=\"close\"` button."
          },
          "content": {
            "description": "Alert body. For single-line text use the `text=` attribute (alert.js stamps a `<span slot=\"content\">` automatically). For rich content with title + description, wrap in `<col-ui slot=\"content\">` — the alert root is `display: flex` row, so multiple bare children would lay out side-by-side instead of stacking."
          },
          "leading": {
            "description": "Leading icon. Stamped automatically from the `icon=` attribute; consumers can override by passing a custom `<icon-ui slot=\"leading\">`."
          }
        },
        "states": [
          {
            "description": "Default, ready for interaction.",
            "name": "idle"
          }
        ],
        "status": "stable",
        "synonyms": {
          "alert": [
            "alert",
            "banner",
            "toast",
            "notification"
          ],
          "announce": [
            "alert",
            "banner",
            "cta"
          ],
          "banner": [
            "alert",
            "cta",
            "hero",
            "cookie"
          ],
          "confirm": [
            "alert",
            "cookie",
            "consent"
          ],
          "dialog": [
            "drawer",
            "alert",
            "popover",
            "panel"
          ],
          "error": [
            "alert",
            "error",
            "toast",
            "empty"
          ],
          "inbox": [
            "notification",
            "alert",
            "toast",
            "message",
            "email",
            "mail",
            "folder"
          ],
          "info": [
            "alert",
            "toast",
            "notification",
            "tooltip"
          ],
          "mailbox": [
            "notification",
            "alert",
            "message"
          ],
          "message": [
            "chat",
            "notification",
            "toast",
            "alert"
          ],
          "modal": [
            "drawer",
            "alert",
            "popover",
            "panel"
          ],
          "notification": [
            "notification",
            "toast",
            "alert",
            "badge"
          ],
          "popup": [
            "toast",
            "notification",
            "alert",
            "popover",
            "drawer"
          ],
          "snackbar": [
            "toast",
            "notification",
            "alert"
          ],
          "success": [
            "alert",
            "toast",
            "notification"
          ],
          "warning": [
            "alert",
            "error",
            "toast"
          ]
        },
        "tag": "alert-ui",
        "tokens": {},
        "traits": [],
        "version": 1
      }
    },
    "AppShell": {
      "title": "AppShell",
      "description": "Embedded multi-surface shell — composes a primary [app] surface with secondary\n[panel=\"<name>\"] surfaces the consumer provides, arranging them responsively.\nPeer of <admin-shell>. Content-agnostic: it orchestrates whatever [app] +\n[panel] children it is given (it owns layout, not content), so any embedded app\nsupplies its own surfaces.\n\n>=760px the open panel is an EQUAL 50/50 column beside the app and the frame\ngrows to fit; <760px it is a cover sheet that slides up over the app (identity\ntransform at rest, so popovers inside still anchor). Clean attribute contract\n(ADR-0024, no data-*): [app], [panel=\"<name>\"], trigger [opens=\"<name>\"],\n[close]; reflects [panel] on the shell + [active] on the open panel.\n",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "component": {
          "const": "AppShell"
        },
        "panel": {
          "description": "The open panel's name (empty / absent = none). Reflected state. Set it by\nclicking an [opens=\"<name>\"] trigger, dispatching an `embed:open` event, or\ncalling .open(name) / .close() / .toggle(name).\n",
          "type": "string"
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [],
        "category": "layout",
        "composes": [],
        "events": {
          "embed:change": {
            "description": "Fired after the open panel changes.",
            "detail": {
              "panel": "string"
            }
          },
          "embed:open": {
            "description": "Request to open or toggle a panel (consumed by the shell).",
            "detail": {
              "panel": "string"
            }
          }
        },
        "examples": [],
        "keywords": [
          "embed",
          "shell",
          "layout",
          "panel",
          "multi-pane",
          "cover-sheet",
          "app-shell"
        ],
        "name": "EmbedShell",
        "related": [
          "AdminShell",
          "Frame",
          "Drawer"
        ],
        "slots": {
          "default": {
            "description": "Document-order children: one [app] primary surface + any number of [panel=\"<name>\"] secondary surfaces. The shell always shows [app] and reveals the open [panel] (50/50 column >=760px, cover sheet <760px). Triggers ([opens], [close]) may live anywhere inside."
          }
        },
        "states": [
          {
            "description": "No panel open — the app fills the frame.",
            "name": "idle"
          },
          {
            "description": "A panel is open ([panel=\"<name>\"] reflected; the panel carries [active]).",
            "name": "open"
          }
        ],
        "status": "draft",
        "synonyms": {
          "embed": [
            "embedded",
            "shell",
            "app-shell",
            "multi-pane"
          ],
          "panel": [
            "pane",
            "sheet",
            "drawer"
          ]
        },
        "tag": "embed-shell",
        "tokens": {},
        "traits": [
          "resizable"
        ],
        "version": 1
      }
    },
    "Aside": {
      "title": "Aside",
      "description": "Side region — styled by closest container parent (AppShell / Drawer / Card).\nHolds nav rails, secondary actions, or supplementary content. CSS-only slot\nstub: no own behavior; the container parent reads `[collapsible]` and\n`[width]` to wire collapse + width. For interactive resize / collapse\nbehavior, compose with `<pane-ui>` inside: aside = semantic role,\npane = resizable / collapsible primitive.\n",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "collapsible": {
          "description": "Marks the aside as collapsible. The container parent (AppShell, Drawer)\nreads this and wires the toggle affordance + ARIA + state. The aside\nitself ships no collapse logic.\n",
          "type": "boolean",
          "default": false
        },
        "component": {
          "const": "Aside"
        },
        "width": {
          "description": "Token-bound width hint. The container parent reads this to set the\naside column width — `rail` (compact icon-only nav), `panel` (full\nnav text), `wide` (workspace pane). Empty string defers to parent default.\n",
          "type": "string",
          "enum": [
            "",
            "rail",
            "panel",
            "wide"
          ],
          "default": ""
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [],
        "category": "container",
        "composes": [],
        "events": {},
        "examples": [
          {
            "description": "Card laid out as a header / aside / section, with the aside holding a nav list.",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"Card\",\n    \"children\": [\"hdr\", \"side\", \"main\"]\n  },\n  {\n    \"id\": \"hdr\",\n    \"component\": \"Header\",\n    \"children\": [\"title\"]\n  },\n  {\n    \"id\": \"title\",\n    \"component\": \"Text\",\n    \"slot\": \"heading\",\n    \"textContent\": \"Settings\"\n  },\n  {\n    \"id\": \"side\",\n    \"component\": \"Aside\",\n    \"width\": \"rail\",\n    \"children\": [\"nav\"]\n  },\n  {\n    \"id\": \"nav\",\n    \"component\": \"List\",\n    \"children\": []\n  },\n  {\n    \"id\": \"main\",\n    \"component\": \"Section\",\n    \"children\": []\n  }\n]",
            "name": "card-with-side-nav"
          }
        ],
        "keywords": [
          "aside",
          "sidebar",
          "rail",
          "panel",
          "side-region",
          "nav-rail"
        ],
        "name": "UIAside",
        "related": [
          "app-shell",
          "drawer",
          "pane",
          "section",
          "header"
        ],
        "slots": {
          "default": {
            "description": "Default slot — primary child content (typically `<list-ui>`, `<tree-ui>`, or app-nav primitives)."
          }
        },
        "states": [
          {
            "description": "Default, ready for interaction.",
            "name": "idle"
          }
        ],
        "status": "stable",
        "synonyms": {
          "aside": [
            "side-region",
            "side-panel-slot",
            "secondary-rail"
          ]
        },
        "tag": "aside-ui",
        "tokens": {},
        "traits": [],
        "version": 1
      }
    },
    "Avatar": {
      "title": "Avatar",
      "description": "User-portrait primitive with an image → initials → icon fallback\nchain. Resolves the leading [src] image; on load failure falls back\nto [text]-derived initials; on missing text falls back to a slotted\nor default <icon-ui>. Use for user identity in chat surfaces,\nmember tables, statusbar account chips, comment threads. Pair via\n<avatar-group-ui> for stacked / overflowed sets.\n",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "component": {
          "const": "Avatar"
        },
        "icon": {
          "description": "Phosphor icon name shown instead of initials when `src`/`text` are empty.",
          "type": "string",
          "default": ""
        },
        "shape": {
          "description": "Avatar shape",
          "type": "string",
          "enum": [
            "circle",
            "square"
          ],
          "default": "circle"
        },
        "size": {
          "description": "Avatar size — canonical scale.",
          "type": "string",
          "enum": [
            "xs",
            "sm",
            "md",
            "lg",
            "xl"
          ],
          "default": "md"
        },
        "src": {
          "description": "Image source URL. Falls back to initials on error.",
          "type": "string",
          "default": ""
        },
        "text": {
          "description": "Display string (full name or initials). Initials derive from spaces — first letter of each word, max 2.",
          "type": "string",
          "default": ""
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [],
        "category": "display",
        "composes": [
          "icon-ui"
        ],
        "events": {},
        "examples": [
          {
            "description": "Chat interface with message bubbles containing avatar and text pairs, plus an input footer.",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"Card\",\n    \"children\": [\n      \"hdr\",\n      \"sec\",\n      \"ftr\"\n    ]\n  },\n  {\n    \"id\": \"hdr\",\n    \"component\": \"Header\",\n    \"children\": [\n      \"title\"\n    ]\n  },\n  {\n    \"id\": \"title\",\n    \"component\": \"Text\",\n    \"slot\": \"heading\",\n    \"textContent\": \"Chat\"\n  },\n  {\n    \"id\": \"sec\",\n    \"component\": \"Section\",\n    \"children\": [\n      \"messages\"\n    ]\n  },\n  {\n    \"id\": \"messages\",\n    \"component\": \"Column\",\n    \"gap\": \"3\",\n    \"children\": [\n      \"msg1\",\n      \"msg2\",\n      \"msg3\",\n      \"msg4\"\n    ]\n  },\n  {\n    \"id\": \"msg1\",\n    \"component\": \"Row\",\n    \"gap\": \"2\",\n    \"children\": [\n      \"a1\",\n      \"t1\"\n    ]\n  },\n  {\n    \"id\": \"a1\",\n    \"component\": \"Avatar\",\n    \"name\": \"User\",\n    \"size\": \"sm\"\n  },\n  {\n    \"id\": \"t1\",\n    \"component\": \"Text\",\n    \"variant\": \"body\",\n    \"textContent\": \"Hello! Can you help me with something?\"\n  },\n  {\n    \"id\": \"msg2\",\n    \"component\": \"Row\",\n    \"gap\": \"2\",\n    \"children\": [\n      \"a2\",\n      \"t2\"\n    ]\n  },\n  {\n    \"id\": \"a2\",\n    \"component\": \"Avatar\",\n    \"name\": \"Assistant\",\n    \"size\": \"sm\"\n  },\n  {\n    \"id\": \"t2\",\n    \"component\": \"Text\",\n    \"variant\": \"body\",\n    \"textContent\": \"Of course! I'd be happy to help. What do you need?\"\n  },\n  {\n    \"id\": \"msg3\",\n    \"component\": \"Row\",\n    \"gap\": \"2\",\n    \"children\": [\n      \"a3\",\n      \"t3\"\n    ]\n  },\n  {\n    \"id\": \"a3\",\n    \"component\": \"Avatar\",\n    \"name\": \"User\",\n    \"size\": \"sm\"\n  },\n  {\n    \"id\": \"t3\",\n    \"component\": \"Text\",\n    \"variant\": \"body\",\n    \"textContent\": \"I need to build a dashboard layout.\"\n  },\n  {\n    \"id\": \"msg4\",\n    \"component\": \"Row\",\n    \"gap\": \"2\",\n    \"children\": [\n      \"a4\",\n      \"t4\"\n    ]\n  },\n  {\n    \"id\": \"a4\",\n    \"component\": \"Avatar\",\n    \"name\": \"Assistant\",\n    \"size\": \"sm\"\n  },\n  {\n    \"id\": \"t4\",\n    \"component\": \"Text\",\n    \"variant\": \"body\",\n    \"textContent\": \"Great choice! Let me suggest some patterns for that.\"\n  },\n  {\n    \"id\": \"ftr\",\n    \"component\": \"Footer\",\n    \"children\": [\n      \"input-row\"\n    ]\n  },\n  {\n    \"id\": \"input-row\",\n    \"component\": \"Row\",\n    \"gap\": \"2\",\n    \"children\": [\n      \"chat-input\",\n      \"send-btn\"\n    ]\n  },\n  {\n    \"id\": \"chat-input\",\n    \"component\": \"Input\",\n    \"placeholder\": \"Type a message...\"\n  },\n  {\n    \"id\": \"send-btn\",\n    \"component\": \"Button\",\n    \"text\": \"Send\",\n    \"icon\": \"send\",\n    \"variant\": \"primary\"\n  }\n]",
            "name": "chat-interface"
          },
          {
            "description": "Email inbox list with selectable rows showing checkbox, sender avatar, subject, preview text, and time badge.",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"Card\",\n    \"children\": [\n      \"sec\"\n    ]\n  },\n  {\n    \"id\": \"sec\",\n    \"component\": \"Section\",\n    \"children\": [\n      \"list\"\n    ]\n  },\n  {\n    \"id\": \"list\",\n    \"component\": \"Column\",\n    \"gap\": \"1\",\n    \"children\": [\n      \"m1\",\n      \"m2\",\n      \"m3\",\n      \"m4\"\n    ]\n  },\n  {\n    \"id\": \"m1\",\n    \"component\": \"Row\",\n    \"gap\": \"3\",\n    \"align\": \"center\",\n    \"children\": [\n      \"cb1\",\n      \"av1\",\n      \"body1\",\n      \"meta1\"\n    ]\n  },\n  {\n    \"id\": \"cb1\",\n    \"component\": \"CheckBox\"\n  },\n  {\n    \"id\": \"av1\",\n    \"component\": \"Avatar\",\n    \"text\": \"Sarah Chen\",\n    \"size\": \"sm\"\n  },\n  {\n    \"id\": \"body1\",\n    \"component\": \"Column\",\n    \"gap\": \"0\",\n    \"grow\": true,\n    \"children\": [\n      \"subj1\",\n      \"prev1\"\n    ]\n  },\n  {\n    \"id\": \"subj1\",\n    \"component\": \"Text\",\n    \"weight\": \"semibold\",\n    \"textContent\": \"Q4 Planning Review\"\n  },\n  {\n    \"id\": \"prev1\",\n    \"component\": \"Text\",\n    \"color\": \"muted\",\n    \"textContent\": \"Here are the updated projections for next quarter...\"\n  },\n  {\n    \"id\": \"meta1\",\n    \"component\": \"Column\",\n    \"gap\": \"1\",\n    \"align\": \"end\",\n    \"children\": [\n      \"time1\",\n      \"b1\"\n    ]\n  },\n  {\n    \"id\": \"time1\",\n    \"component\": \"Text\",\n    \"color\": \"muted\",\n    \"textContent\": \"10:42 AM\"\n  },\n  {\n    \"id\": \"b1\",\n    \"component\": \"Badge\",\n    \"color\": \"primary\",\n    \"textContent\": \"New\"\n  },\n  {\n    \"id\": \"m2\",\n    \"component\": \"Row\",\n    \"gap\": \"3\",\n    \"align\": \"center\",\n    \"children\": [\n      \"cb2\",\n      \"av2\",\n      \"body2\",\n      \"time2\"\n    ]\n  },\n  {\n    \"id\": \"cb2\",\n    \"component\": \"CheckBox\"\n  },\n  {\n    \"id\": \"av2\",\n    \"component\": \"Avatar\",\n    \"text\": \"Alex Kim\",\n    \"size\": \"sm\"\n  },\n  {\n    \"id\": \"body2\",\n    \"component\": \"Column\",\n    \"gap\": \"0\",\n    \"grow\": true,\n    \"children\": [\n      \"subj2\",\n      \"prev2\"\n    ]\n  },\n  {\n    \"id\": \"subj2\",\n    \"component\": \"Text\",\n    \"weight\": \"semibold\",\n    \"textContent\": \"Design Review Feedback\"\n  },\n  {\n    \"id\": \"prev2\",\n    \"component\": \"Text\",\n    \"color\": \"muted\",\n    \"textContent\": \"Great work on the new components. A few notes...\"\n  },\n  {\n    \"id\": \"time2\",\n    \"component\": \"Text\",\n    \"color\": \"muted\",\n    \"textContent\": \"9:15 AM\"\n  },\n  {\n    \"id\": \"m3\",\n    \"component\": \"Row\",\n    \"gap\": \"3\",\n    \"align\": \"center\",\n    \"children\": [\n      \"cb3\",\n      \"av3\",\n      \"body3\",\n      \"time3\"\n    ]\n  },\n  {\n    \"id\": \"cb3\",\n    \"component\": \"CheckBox\"\n  },\n  {\n    \"id\": \"av3\",\n    \"component\": \"Avatar\",\n    \"text\": \"Tom Wright\",\n    \"size\": \"sm\"\n  },\n  {\n    \"id\": \"body3\",\n    \"component\": \"Column\",\n    \"gap\": \"0\",\n    \"grow\": true,\n    \"children\": [\n      \"subj3\",\n      \"prev3\"\n    ]\n  },\n  {\n    \"id\": \"subj3\",\n    \"component\": \"Text\",\n    \"textContent\": \"CI Pipeline Update\"\n  },\n  {\n    \"id\": \"prev3\",\n    \"component\": \"Text\",\n    \"color\": \"muted\",\n    \"textContent\": \"The new build system is deployed and running...\"\n  },\n  {\n    \"id\": \"time3\",\n    \"component\": \"Text\",\n    \"color\": \"muted\",\n    \"textContent\": \"Yesterday\"\n  },\n  {\n    \"id\": \"m4\",\n    \"component\": \"Row\",\n    \"gap\": \"3\",\n    \"align\": \"center\",\n    \"children\": [\n      \"cb4\",\n      \"av4\",\n      \"body4\",\n      \"time4\"\n    ]\n  },\n  {\n    \"id\": \"cb4\",\n    \"component\": \"CheckBox\"\n  },\n  {\n    \"id\": \"av4\",\n    \"component\": \"Avatar\",\n    \"text\": \"Emma Davis\",\n    \"size\": \"sm\"\n  },\n  {\n    \"id\": \"body4\",\n    \"component\": \"Column\",\n    \"gap\": \"0\",\n    \"grow\": true,\n    \"children\": [\n      \"subj4\",\n      \"prev4\"\n    ]\n  },\n  {\n    \"id\": \"subj4\",\n    \"component\": \"Text\",\n    \"textContent\": \"Team Offsite Planning\"\n  },\n  {\n    \"id\": \"prev4\",\n    \"component\": \"Text\",\n    \"color\": \"muted\",\n    \"textContent\": \"Let's finalize the agenda for next month's offsite...\"\n  },\n  {\n    \"id\": \"time4\",\n    \"component\": \"Text\",\n    \"color\": \"muted\",\n    \"textContent\": \"Monday\"\n  }\n]",
            "name": "email-inbox"
          }
        ],
        "keywords": [
          "avatar",
          "member",
          "people",
          "team",
          "roster",
          "directory",
          "contacts",
          "staff",
          "social",
          "profile",
          "user"
        ],
        "name": "UIAvatar",
        "related": [
          "input",
          "button",
          "check-box",
          "badge",
          "avatar-group"
        ],
        "slots": {
          "icon": {
            "description": "Phosphor icon rendered inside the avatar circle (system-event avatars)"
          },
          "img": {
            "description": "Avatar image element"
          },
          "initials": {
            "description": "Initials text span"
          }
        },
        "states": [
          {
            "description": "Default, ready for interaction.",
            "name": "idle"
          }
        ],
        "status": "stable",
        "synonyms": {
          "avatar": [
            "user",
            "profile",
            "avatar",
            "group"
          ],
          "contacts": [
            "team",
            "avatar",
            "group",
            "user",
            "profile"
          ],
          "directory": [
            "team",
            "avatar",
            "group",
            "table",
            "data"
          ],
          "member": [
            "user",
            "profile",
            "avatar",
            "team",
            "activity"
          ],
          "people": [
            "user",
            "profile",
            "avatar",
            "team",
            "group"
          ],
          "profile": [
            "user",
            "profile",
            "avatar",
            "settings"
          ],
          "roster": [
            "team",
            "activity",
            "avatar",
            "group",
            "leaderboard"
          ],
          "social": [
            "social",
            "post",
            "avatar",
            "testimonial"
          ],
          "staff": [
            "team",
            "avatar",
            "group",
            "user"
          ],
          "team": [
            "team",
            "activity",
            "avatar",
            "group",
            "leaderboard",
            "project",
            "board",
            "kanban"
          ],
          "user": [
            "user",
            "profile",
            "avatar",
            "login"
          ]
        },
        "tag": "avatar-ui",
        "tokens": {},
        "traits": [],
        "version": 1
      }
    },
    "AvatarGroup": {
      "title": "AvatarGroup",
      "description": "Cluster of overlapping <avatar-ui> children. Stacks the first `max` avatars with a negative inline-start margin; if more children are present, renders a +N overflow indicator.",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "component": {
          "const": "AvatarGroup"
        },
        "max": {
          "description": "Maximum avatars to show before the +N overflow indicator.",
          "type": "number",
          "default": 5
        },
        "size": {
          "description": "Forwards to each child <avatar-ui> (xs|sm|md|lg|xl). Empty uses the per-avatar size.",
          "type": "string"
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [],
        "category": "feedback",
        "composes": [],
        "events": {},
        "examples": [],
        "keywords": [
          "avatar-group",
          "avatar-stack",
          "user-group",
          "facepile",
          "people-stack",
          "overflow-avatars"
        ],
        "name": "UIAvatarGroup",
        "related": [
          "Avatar",
          "Tag"
        ],
        "slots": {},
        "states": [],
        "status": "stable",
        "synonyms": {
          "avatar-group": [
            "facepile",
            "user-stack",
            "people-pile",
            "avatar-pile"
          ]
        },
        "tag": "avatar-group-ui",
        "tokens": {},
        "traits": [],
        "version": 1
      }
    },
    "Badge": {
      "title": "Badge",
      "description": "Inline pill-shaped badge — READ-ONLY status flag, count, or\nnotification dot. Text rendered via CSS `attr(text)`. Distinct from\n<tag-ui>, which is INTERACTIVE / removable and fires a `remove`\nevent. Use badge-ui for status flags (Beta / New / Deprecated),\nnotification counts, and unread indicators; use tag-ui for filter\nchips or user-managed labels.\n",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "component": {
          "const": "Badge"
        },
        "icon": {
          "description": "Optional leading icon (any registered name). Use icon=\"dot\" for chart-legend / status-pip chips. Inherits the variant's foreground color so the dot matches the label.",
          "type": "string",
          "default": ""
        },
        "size": {
          "description": "Badge size",
          "type": "string",
          "enum": [
            "xs",
            "sm",
            "md",
            "lg",
            "xl"
          ],
          "default": "md"
        },
        "status": {
          "description": "Semantic status shorthand. Auto-maps to variant and sets text. `new` → success \"New\"; `updated` → info \"Updated\"; `deprecated` → warning \"Deprecated\"; `removed` → danger \"Removed\"; `beta` → accent \"Beta\". Use `variant` + `text` directly for custom chips.",
          "type": "string",
          "enum": [
            "new",
            "updated",
            "deprecated",
            "removed",
            "beta"
          ],
          "default": ""
        },
        "text": {
          "description": "Badge text content. Falls back to existing textContent.",
          "type": "string",
          "default": ""
        },
        "textContent": {
          "description": "Badge display text. Renderer routes this to the `text` attribute via CSS attr(text) on ::after.",
          "$ref": "#/$defs/DynamicString"
        },
        "tone": {
          "description": "Fill style — orthogonal to [variant]. Badge defaults to `muted`\n(quiet metadata is the primitive's identity — counts, IDs, status\npills in dense rows). Three values:\n  - `muted` (default) — tinted bg + scheme-paired text. Same as\n    the existing family-variant rules.\n  - `solid` — saturated bg + on-strong text. Use for hero badges\n    where the badge IS the state (e.g. a single inline error). The\n    existing `primary` variant is a shortcut for accent + solid.\n  - `outline` — transparent bg + family-colored border + family-\n    colored text. Lightest visual weight; good in dense data rows.\nVocabulary mirrors `<tag-ui>` (which defaults to solid, given its\ndifferent role as filter / autocomplete chip).\n",
          "type": "string",
          "enum": [
            "muted",
            "solid",
            "outline"
          ],
          "default": "muted"
        },
        "variant": {
          "description": "Semantic color variant.",
          "type": "string",
          "enum": [
            "default",
            "accent",
            "info",
            "success",
            "warning",
            "danger",
            "primary",
            "muted",
            "neutral"
          ],
          "default": "default"
        }
      },
      "required": [
        "component",
        "text"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [],
        "category": "display",
        "composes": [
          "icon-ui"
        ],
        "events": {},
        "examples": [
          {
            "description": "Horizontal chart legend — Row of Badges with icon=\"dot\". Each badge's variant supplies the dot color. CANONICAL PATTERN: do NOT compose legends as Row(Row(Badge[text=●], Text), …) — that produces rows-of-rows markup. Use one Badge[icon=dot, text=label, variant=color] per series instead.",
            "a2ui": "[\n  {\n    \"id\": \"legend\",\n    \"component\": \"Row\",\n    \"gap\": \"3\",\n    \"align\": \"center\",\n    \"children\": [\n      \"l1\",\n      \"l2\",\n      \"l3\",\n      \"l4\"\n    ]\n  },\n  {\n    \"id\": \"l1\",\n    \"component\": \"Badge\",\n    \"icon\": \"dot\",\n    \"text\": \"Organic\",\n    \"variant\": \"accent\",\n    \"size\": \"sm\"\n  },\n  {\n    \"id\": \"l2\",\n    \"component\": \"Badge\",\n    \"icon\": \"dot\",\n    \"text\": \"Direct\",\n    \"variant\": \"success\",\n    \"size\": \"sm\"\n  },\n  {\n    \"id\": \"l3\",\n    \"component\": \"Badge\",\n    \"icon\": \"dot\",\n    \"text\": \"Referral\",\n    \"variant\": \"warning\",\n    \"size\": \"sm\"\n  },\n  {\n    \"id\": \"l4\",\n    \"component\": \"Badge\",\n    \"icon\": \"dot\",\n    \"text\": \"Social\",\n    \"variant\": \"info\",\n    \"size\": \"sm\"\n  }\n]",
            "name": "chart-legend"
          },
          {
            "description": "Card with categorized list of bookmark items featuring icon, title, and badge.",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"Card\",\n    \"children\": [\n      \"hdr\",\n      \"sec\"\n    ]\n  },\n  {\n    \"id\": \"hdr\",\n    \"component\": \"Header\",\n    \"children\": [\n      \"title\"\n    ]\n  },\n  {\n    \"id\": \"title\",\n    \"component\": \"Text\",\n    \"slot\": \"heading\",\n    \"textContent\": \"Bookmarks\",\n    \"variant\": \"section\"\n  },\n  {\n    \"id\": \"sec\",\n    \"component\": \"Section\",\n    \"children\": [\n      \"categories\"\n    ]\n  },\n  {\n    \"id\": \"categories\",\n    \"component\": \"Column\",\n    \"children\": [\n      \"cat-label-dev\",\n      \"item1\",\n      \"item2\",\n      \"cat-label-design\",\n      \"item3\"\n    ],\n    \"gap\": \"2\"\n  },\n  {\n    \"id\": \"cat-label-dev\",\n    \"component\": \"Text\",\n    \"variant\": \"caption\",\n    \"textContent\": \"Development\"\n  },\n  {\n    \"id\": \"item1\",\n    \"component\": \"Row\",\n    \"children\": [\n      \"icon1\",\n      \"title1\",\n      \"badge1\"\n    ],\n    \"gap\": \"2\"\n  },\n  {\n    \"id\": \"icon1\",\n    \"component\": \"Icon\",\n    \"name\": \"code\"\n  },\n  {\n    \"id\": \"title1\",\n    \"component\": \"Text\",\n    \"textContent\": \"GitHub Repository\"\n  },\n  {\n    \"id\": \"badge1\",\n    \"component\": \"Badge\",\n    \"text\": \"Pinned\",\n    \"variant\": \"default\"\n  },\n  {\n    \"id\": \"item2\",\n    \"component\": \"Row\",\n    \"children\": [\n      \"icon2\",\n      \"title2\",\n      \"badge2\"\n    ],\n    \"gap\": \"2\"\n  },\n  {\n    \"id\": \"icon2\",\n    \"component\": \"Icon\",\n    \"name\": \"file-text\"\n  },\n  {\n    \"id\": \"title2\",\n    \"component\": \"Text\",\n    \"textContent\": \"API Documentation\"\n  },\n  {\n    \"id\": \"badge2\",\n    \"component\": \"Badge\",\n    \"text\": \"New\",\n    \"variant\": \"info\"\n  },\n  {\n    \"id\": \"cat-label-design\",\n    \"component\": \"Text\",\n    \"variant\": \"caption\",\n    \"textContent\": \"Design\"\n  },\n  {\n    \"id\": \"item3\",\n    \"component\": \"Row\",\n    \"children\": [\n      \"icon3\",\n      \"title3\",\n      \"badge3\"\n    ],\n    \"gap\": \"2\"\n  },\n  {\n    \"id\": \"icon3\",\n    \"component\": \"Icon\",\n    \"name\": \"palette\"\n  },\n  {\n    \"id\": \"title3\",\n    \"component\": \"Text\",\n    \"textContent\": \"Figma Project\"\n  },\n  {\n    \"id\": \"badge3\",\n    \"component\": \"Badge\",\n    \"text\": \"3\",\n    \"variant\": \"default\"\n  }\n]",
            "name": "bookmark-list"
          },
          {
            "description": "Dashboard with KPI stat grid and two chart cards.",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"Column\",\n    \"children\": [\n      \"header-row\",\n      \"kpi-grid\",\n      \"chart-grid\"\n    ],\n    \"gap\": \"4\"\n  },\n  {\n    \"id\": \"header-row\",\n    \"component\": \"Row\",\n    \"children\": [\n      \"dash-title\",\n      \"dash-actions\"\n    ]\n  },\n  {\n    \"id\": \"dash-title\",\n    \"component\": \"Text\",\n    \"textContent\": \"Dashboard\",\n    \"variant\": \"title\"\n  },\n  {\n    \"id\": \"dash-actions\",\n    \"component\": \"Row\",\n    \"children\": [\n      \"export-btn\"\n    ],\n    \"gap\": \"2\"\n  },\n  {\n    \"id\": \"export-btn\",\n    \"component\": \"Button\",\n    \"text\": \"Export\",\n    \"variant\": \"outline\",\n    \"size\": \"sm\",\n    \"icon\": \"download\"\n  },\n  {\n    \"id\": \"kpi-grid\",\n    \"component\": \"Grid\",\n    \"children\": [\n      \"k1\",\n      \"k2\",\n      \"k3\",\n      \"k4\"\n    ],\n    \"columns\": \"4\"\n  },\n  {\n    \"id\": \"k1\",\n    \"component\": \"Card\",\n    \"children\": [\n      \"k1h\",\n      \"k1s\"\n    ]\n  },\n  {\n    \"id\": \"k1h\",\n    \"component\": \"Header\",\n    \"children\": [\n      \"k1l\"\n    ]\n  },\n  {\n    \"id\": \"k1l\",\n    \"component\": \"Text\",\n    \"slot\": \"heading\",\n    \"textContent\": \"Revenue\",\n    \"variant\": \"label\"\n  },\n  {\n    \"id\": \"k1s\",\n    \"component\": \"Section\",\n    \"children\": [\n      \"k1v\",\n      \"k1b\"\n    ]\n  },\n  {\n    \"id\": \"k1v\",\n    \"component\": \"Text\",\n    \"textContent\": \"$48.2k\",\n    \"variant\": \"title\"\n  },\n  {\n    \"id\": \"k1b\",\n    \"component\": \"Badge\",\n    \"text\": \"+12.5%\",\n    \"variant\": \"success\",\n    \"size\": \"sm\"\n  },\n  {\n    \"id\": \"k2\",\n    \"component\": \"Card\",\n    \"children\": [\n      \"k2h\",\n      \"k2s\"\n    ]\n  },\n  {\n    \"id\": \"k2h\",\n    \"component\": \"Header\",\n    \"children\": [\n      \"k2l\"\n    ]\n  },\n  {\n    \"id\": \"k2l\",\n    \"component\": \"Text\",\n    \"slot\": \"heading\",\n    \"textContent\": \"Users\",\n    \"variant\": \"label\"\n  },\n  {\n    \"id\": \"k2s\",\n    \"component\": \"Section\",\n    \"children\": [\n      \"k2v\",\n      \"k2b\"\n    ]\n  },\n  {\n    \"id\": \"k2v\",\n    \"component\": \"Text\",\n    \"textContent\": \"2,340\",\n    \"variant\": \"title\"\n  },\n  {\n    \"id\": \"k2b\",\n    \"component\": \"Badge\",\n    \"text\": \"+8%\",\n    \"variant\": \"success\",\n    \"size\": \"sm\"\n  },\n  {\n    \"id\": \"k3\",\n    \"component\": \"Card\",\n    \"children\": [\n      \"k3h\",\n      \"k3s\"\n    ]\n  },\n  {\n    \"id\": \"k3h\",\n    \"component\": \"Header\",\n    \"children\": [\n      \"k3l\"\n    ]\n  },\n  {\n    \"id\": \"k3l\",\n    \"component\": \"Text\",\n    \"slot\": \"heading\",\n    \"textContent\": \"Bounce\",\n    \"variant\": \"label\"\n  },\n  {\n    \"id\": \"k3s\",\n    \"component\": \"Section\",\n    \"children\": [\n      \"k3v\",\n      \"k3b\"\n    ]\n  },\n  {\n    \"id\": \"k3v\",\n    \"component\": \"Text\",\n    \"textContent\": \"24.3%\",\n    \"variant\": \"title\"\n  },\n  {\n    \"id\": \"k3b\",\n    \"component\": \"Badge\",\n    \"text\": \"-3.1%\",\n    \"variant\": \"danger\",\n    \"size\": \"sm\"\n  },\n  {\n    \"id\": \"k4\",\n    \"component\": \"Card\",\n    \"children\": [\n      \"k4h\",\n      \"k4s\"\n    ]\n  },\n  {\n    \"id\": \"k4h\",\n    \"component\": \"Header\",\n    \"children\": [\n      \"k4l\"\n    ]\n  },\n  {\n    \"id\": \"k4l\",\n    \"component\": \"Text\",\n    \"slot\": \"heading\",\n    \"textContent\": \"Session\",\n    \"variant\": \"label\"\n  },\n  {\n    \"id\": \"k4s\",\n    \"component\": \"Section\",\n    \"children\": [\n      \"k4v\",\n      \"k4b\"\n    ]\n  },\n  {\n    \"id\": \"k4v\",\n    \"component\": \"Text\",\n    \"textContent\": \"4m 23s\",\n    \"variant\": \"title\"\n  },\n  {\n    \"id\": \"k4b\",\n    \"component\": \"Badge\",\n    \"text\": \"+15s\",\n    \"variant\": \"info\",\n    \"size\": \"sm\"\n  },\n  {\n    \"id\": \"chart-grid\",\n    \"component\": \"Grid\",\n    \"children\": [\n      \"ch1\",\n      \"ch2\"\n    ],\n    \"columns\": \"2\"\n  },\n  {\n    \"id\": \"ch1\",\n    \"component\": \"Card\",\n    \"children\": [\n      \"ch1h\",\n      \"ch1s\"\n    ]\n  },\n  {\n    \"id\": \"ch1h\",\n    \"component\": \"Header\",\n    \"children\": [\n      \"ch1t\"\n    ]\n  },\n  {\n    \"id\": \"ch1t\",\n    \"component\": \"Text\",\n    \"slot\": \"heading\",\n    \"textContent\": \"Revenue\",\n    \"variant\": \"section\"\n  },\n  {\n    \"id\": \"ch1s\",\n    \"component\": \"Section\",\n    \"children\": [\n      \"ch1-chart\"\n    ]\n  },\n  {\n    \"id\": \"ch1-chart\",\n    \"component\": \"Chart\",\n    \"type\": \"bar\",\n    \"x\": \"month\",\n    \"y\": \"revenue\"\n  },\n  {\n    \"id\": \"ch2\",\n    \"component\": \"Card\",\n    \"children\": [\n      \"ch2h\",\n      \"ch2s\"\n    ]\n  },\n  {\n    \"id\": \"ch2h\",\n    \"component\": \"Header\",\n    \"children\": [\n      \"ch2t\"\n    ]\n  },\n  {\n    \"id\": \"ch2t\",\n    \"component\": \"Text\",\n    \"slot\": \"heading\",\n    \"textContent\": \"Users\",\n    \"variant\": \"section\"\n  },\n  {\n    \"id\": \"ch2s\",\n    \"component\": \"Section\",\n    \"children\": [\n      \"ch2-chart\"\n    ]\n  },\n  {\n    \"id\": \"ch2-chart\",\n    \"component\": \"Chart\",\n    \"type\": \"line\",\n    \"x\": \"month\",\n    \"y\": \"users\"\n  }\n]",
            "name": "chart-dashboard"
          }
        ],
        "keywords": [
          "badge",
          "chip",
          "label",
          "tag",
          "pill",
          "gamification",
          "notification",
          "legend",
          "status",
          "pip",
          "marker"
        ],
        "name": "UIBadge",
        "related": [
          "button",
          "grid",
          "chart",
          "check-box",
          "avatar"
        ],
        "slots": {},
        "states": [
          {
            "description": "Default, ready for interaction.",
            "name": "idle"
          }
        ],
        "status": "stable",
        "synonyms": {
          "badge": [
            "badge",
            "showcase",
            "tag",
            "label"
          ],
          "chip": [
            "badge",
            "tag",
            "input"
          ],
          "gamification": [
            "leaderboard",
            "badge",
            "progress"
          ],
          "label": [
            "badge",
            "tag",
            "divider",
            "label"
          ],
          "notification": [
            "notification",
            "toast",
            "alert",
            "badge"
          ],
          "pill": [
            "badge",
            "tag"
          ],
          "tag": [
            "tag",
            "input",
            "badge"
          ]
        },
        "tag": "badge-ui",
        "tokens": {},
        "traits": [],
        "version": 1
      }
    },
    "BillingOverview": {
      "title": "BillingOverview",
      "description": "Module-tier billing dashboard that stitches the seven Wave A+B\nbilling primitives into the canonical \"all-billing-on-one-page\"\nsurface — current plan + status header, a KPI strip (monthly\nspend · seats · next invoice), an optional dunning banner when the\naccount is past-due, a plan-picker section for in-app plan changes,\na payment-method-list section, and an invoice-history section.\n\nData-driven via the `account` property — an aggregate snapshot of\nthe customer's billing state ({plan, status, billingCycle,\ncurrentSpend, seats, nextInvoiceDate, paymentMethods[],\ninvoices[], dunning?}). The composite stamps a fixed five-region\nskeleton once on first connect — header · kpis · dunning ·\nplan-picker · payment-methods · invoice-history — then mutates\nper-region nodes via id-keyed in-place diff on every property\nchange. Children primitives (plan-picker, payment-method-list,\ninvoice-history, alert-ui) are stamped as composed tags; this\ncomposite owns the orchestration, not the row chrome.\n\nHigher-level account-action event surfaces consumer-actionable\nintents from descendant primitives. Children carrying\n[data-account-action=\"X\"] or descendant events\n(`plan-action`, `payment-action`, `invoice-action`, `dunning-action`)\nare normalised into a single `account-action` event with\n`detail.action` ∈ {change-plan, add-payment-method, pay-now,\ndownload-invoice, update-card, retry, custom}. The composite\ndoes NOT mutate the data source; consumers wire `account-action`\nagainst their billing backend.\n\nDisplay surface. Extends UIElement, not UIFormElement — child\nprimitives are individually form-bearing (plan-picker,\npayment-method-list) while the host is not.\n\nSpec: docs/specs/implementation-ready/SPEC-004-billing-overview.md.\n",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "account": {
          "description": "Aggregate billing snapshot — source of truth for the whole\ndashboard. Shape:\n  {plan: {id, name, price, cycle, currency, status},\n   status: \"active\" | \"trialing\" | \"past_due\" | \"canceled\" | \"paused\",\n   billingCycle: \"month\" | \"year\",\n   currentSpend: number,\n   seats: {used: number, total: number},\n   nextInvoiceDate: ISO 8601 date string,\n   paymentMethods: [...],          // forwarded to payment-method-list\n   invoices: [...],                // forwarded to invoice-history\n   plans?: [...],                  // forwarded to plan-picker; omitted when planSection is \"hidden\"\n   dunning?: {amount, currency, dueAt, cardLast4?, reason?}}\nNull + no `data-stream-src` renders the empty state.\n",
          "type": "object",
          "default": null
        },
        "component": {
          "const": "BillingOverview"
        },
        "currency": {
          "description": "Default ISO 4217 currency for all amount formatting. Overridable\nper-record (plan.currency, invoice.currency, etc.).\n",
          "type": "string",
          "default": "USD"
        },
        "data-stream-src": {
          "description": "Optional endpoint returning the full account snapshot. On\nsuccessful load, `account` is replaced and a `load` event fires;\non failure an `error` event fires.\n",
          "type": "string",
          "default": ""
        },
        "loading": {
          "description": "Renders skeleton placeholders in the header + KPI strip while\ndata is fetching. Sets aria-busy on the host. Forwarded to\nchild composites that accept [loading] (plan-picker,\npayment-method-list, invoice-history).\n",
          "$ref": "#/$defs/DynamicBoolean"
        },
        "locale": {
          "description": "Locale for Intl.NumberFormat (currency) and Intl.DateTimeFormat\n(dates). Defaults to document.documentElement.lang (or \"en-US\"\nwhen absent).\n",
          "type": "string",
          "default": ""
        },
        "variant": {
          "description": "Layout variant. `full` shows every section. `compact` collapses\nthe plan-picker section and renders only the KPI strip + payment\nmethods + invoice history (the canonical \"settings billing\"\nshape). `enterprise` hides plan-picker entirely (no self-serve\nplan changes) and keeps the rest.\n",
          "type": "string",
          "enum": [
            "full",
            "compact",
            "enterprise"
          ],
          "default": "full"
        }
      },
      "required": [
        "component",
        "account"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [
          {
            "fix": "{\"component\": \"BillingOverview\", \"account\":\n  {\"plan\": {\"id\":\"p_pro\",\"name\":\"Pro\",\"price\":48,\"cycle\":\"month\",\"currency\":\"USD\",\"status\":\"active\"},\n   \"status\": \"active\",\n   \"billingCycle\": \"month\",\n   \"currentSpend\": 48,\n   \"seats\": {\"used\": 4, \"total\": 10},\n   \"nextInvoiceDate\": \"2026-06-01\",\n   \"paymentMethods\": [...],\n   \"invoices\": [...]}}\n",
            "why": "Missing the required `account` prop. The composite renders the\nempty state. A dashboard without data has nothing to show.\n",
            "wrong": "{\"component\": \"BillingOverview\"}\n"
          },
          {
            "fix": "Render the BillingOverview composite on its own route\n(typically `/settings/billing` or `/billing`).\n",
            "why": "The dashboard is a route, not a modal. Modal traps focus + clips\ncontent; the composite is designed for the full /billing page.\n",
            "wrong": "{\"component\": \"Modal\", \"children\":\n  [{\"component\": \"BillingOverview\", \"account\": {...}}]}\n"
          },
          {
            "fix": "Provide a dunning object alongside the past_due status:\n<billing-overview-ui account='{\"status\":\"past_due\",\"dunning\":{\"amount\":48,\"currency\":\"USD\",\"dueAt\":\"2026-05-20\"}}'></billing-overview-ui>\n",
            "why": "Past-due status without an `account.dunning` payload. The\ncomposite cannot render the dunning banner (it needs amount +\ndue-at + currency to format the alert message).\n",
            "wrong": "<billing-overview-ui account='{\"status\":\"past_due\"}'></billing-overview-ui>\n"
          },
          {
            "fix": "Either pass `account.plans` OR set `variant=\"compact\"` to hide\nthe plan-picker section entirely.\n",
            "why": "`variant=full` requires `account.plans` so the plan-picker\nsection has rows to render. Without plans, the section renders\nits own empty-state and looks broken.\n",
            "wrong": "<billing-overview-ui variant=\"full\" account='{\"plan\":{...},\"status\":\"active\"}'></billing-overview-ui>\n"
          }
        ],
        "category": "container",
        "composes": [
          "card-ui",
          "stat-ui",
          "tag-ui",
          "text-ui",
          "alert-ui",
          "plan-picker-ui",
          "payment-method-list-ui",
          "invoice-history-ui",
          "button-ui",
          "icon-ui"
        ],
        "events": {
          "account-action": {
            "description": "Unified account-action event — normalises every actionable\nintent from descendant primitives into a single bubbling event.\nHandler can act on `detail.action` without subscribing to four\ndifferent child event names. Bubbles.\n",
            "detail": {
              "action": {
                "description": "One of \"change-plan\" | \"add-payment-method\" | \"pay-now\" |\n\"download-invoice\" | \"update-card\" | \"retry\" | \"select-plan\"\n| \"remove-payment-method\" | \"set-default-payment-method\" |\nor any consumer-defined value carried on a descendant\n[data-account-action] attribute.\n",
                "type": "string"
              },
              "payload": {
                "description": "Forwarded detail from the originating event (e.g. the\ninvoice record, the plan id, the dunning amount). Shape\nvaries by source.\n",
                "type": "object"
              },
              "source": {
                "description": "The originating primitive — \"plan-picker\" | \"payment-method-list\"\n| \"invoice-history\" | \"alert-dunning\" | \"header\" | \"custom\".\n",
                "type": "string"
              }
            }
          },
          "error": {
            "description": "Fired when a `data-stream-src` fetch fails. Bubbles.\n",
            "detail": {
              "reason": {
                "description": "One of `fetch-failed`.",
                "type": "string"
              }
            }
          },
          "load": {
            "description": "Fired when `data-stream-src` finishes a successful fetch and\n`account` is populated. Bubbles.\n",
            "detail": {
              "account": {
                "description": "The loaded account snapshot.",
                "type": "object"
              }
            }
          }
        },
        "examples": [
          {
            "description": "Active Pro plan with 4 saved cards + 3 invoices.",
            "a2ui": "[\n  {\n    \"id\": \"bo-pro\",\n    \"component\": \"BillingOverview\",\n    \"variant\": \"full\",\n    \"currency\": \"USD\",\n    \"account\": {\n      \"plan\": {\n        \"id\": \"p_pro\",\n        \"name\": \"Pro\",\n        \"price\": 48,\n        \"cycle\": \"month\",\n        \"currency\": \"USD\",\n        \"status\": \"active\"\n      },\n      \"status\": \"active\",\n      \"billingCycle\": \"month\",\n      \"currentSpend\": 48,\n      \"seats\": {\"used\": 4, \"total\": 10},\n      \"nextInvoiceDate\": \"2026-06-01\",\n      \"plans\": [],\n      \"paymentMethods\": [],\n      \"invoices\": []\n    }\n  }\n]\n",
            "name": "active-pro-account"
          },
          {
            "description": "Past-due account with dunning banner above plan section.",
            "a2ui": "[\n  {\n    \"id\": \"bo-past-due\",\n    \"component\": \"BillingOverview\",\n    \"variant\": \"full\",\n    \"currency\": \"USD\",\n    \"account\": {\n      \"plan\": {\n        \"id\": \"p_pro\",\n        \"name\": \"Pro\",\n        \"price\": 48,\n        \"cycle\": \"month\",\n        \"currency\": \"USD\",\n        \"status\": \"past_due\"\n      },\n      \"status\": \"past_due\",\n      \"billingCycle\": \"month\",\n      \"currentSpend\": 48,\n      \"seats\": {\"used\": 4, \"total\": 10},\n      \"nextInvoiceDate\": \"2026-05-20\",\n      \"dunning\": {\n        \"amount\": 48,\n        \"currency\": \"USD\",\n        \"dueAt\": \"2026-05-20\",\n        \"cardLast4\": \"4242\",\n        \"reason\": \"declined\"\n      },\n      \"plans\": [],\n      \"paymentMethods\": [],\n      \"invoices\": []\n    }\n  }\n]\n",
            "name": "past-due-account"
          }
        ],
        "keywords": [
          "billing",
          "overview",
          "dashboard",
          "account",
          "subscription",
          "plan",
          "invoice",
          "payment-method",
          "usage",
          "dunning",
          "past-due"
        ],
        "name": "UIBillingOverview",
        "related": [
          "PlanPicker",
          "PaymentMethodList",
          "InvoiceHistory",
          "InvoiceDetail",
          "PaymentMethodForm",
          "Alert",
          "Stat"
        ],
        "slots": {
          "after-invoice-history": {
            "description": "Optional content slotted below the invoice-history section\n(e.g. tax-document download row, billing-contact form).\n"
          },
          "before-plan-picker": {
            "description": "Optional content slotted above the plan-picker section (e.g. a\npromo banner, an annual-savings callout).\n"
          },
          "empty": {
            "description": "Custom empty-state content when there's no account snapshot\nAND no data-stream-src. Falls back to a default empty-state\nmessage.\n"
          },
          "header-actions": {
            "description": "Optional action row in the dashboard header (top-right). Used\nfor consumer-authored \"Contact sales\", \"Cancel subscription\",\netc. The composite NEVER stamps a default toolbar.\n"
          }
        },
        "states": [
          {
            "description": "Default — account rendered, ready for interaction.",
            "name": "idle"
          },
          {
            "description": "A `data-stream-src` fetch is in flight or [loading] is set.",
            "attribute": "loading",
            "name": "loading"
          },
          {
            "description": "No account snapshot + no data-stream-src.",
            "attribute": "empty",
            "name": "empty"
          },
          {
            "description": "Account is past-due (computed from `account.status === \"past_due\"`).\nStamps the dunning banner if `account.dunning` is present.\n",
            "attribute": "past-due",
            "name": "past-due"
          },
          {
            "description": "Account is trialing (computed from `account.status === \"trialing\"`).\n",
            "attribute": "trial",
            "name": "trial"
          },
          {
            "description": "Last `data-stream-src` fetch failed.",
            "attribute": "error",
            "name": "error"
          }
        ],
        "status": "experimental",
        "synonyms": {
          "account": [
            "subscription",
            "membership"
          ],
          "billing": [
            "subscription",
            "account-billing"
          ],
          "overview": [
            "dashboard",
            "summary"
          ]
        },
        "tag": "billing-overview-ui",
        "tokens": {
          "--billing-overview-bg": {
            "description": "Host page background. Defaults to transparent.",
            "default": "transparent"
          },
          "--billing-overview-gap": {
            "description": "Vertical gap between dashboard sections.",
            "default": "var(--a-space-5)"
          },
          "--billing-overview-header-gap": {
            "description": "Gap between the plan title block and the status badge cluster.",
            "default": "var(--a-space-3)"
          },
          "--billing-overview-kpi-columns": {
            "description": "Grid column template for the KPI strip. Falls back to a 3-column\nauto-fit when narrowed below 40rem (container query).\n",
            "default": "repeat(3, minmax(0, 1fr))"
          },
          "--billing-overview-kpi-gap": {
            "description": "Gap between KPI stat cards.",
            "default": "var(--a-space-3)"
          },
          "--billing-overview-meta-fg": {
            "description": "Foreground color for secondary metadata in the header.",
            "default": "var(--a-fg-muted)"
          },
          "--billing-overview-px": {
            "description": "Horizontal padding around dashboard content.",
            "default": "var(--a-space-5)"
          },
          "--billing-overview-py": {
            "description": "Vertical padding around dashboard content.",
            "default": "var(--a-space-5)"
          },
          "--billing-overview-section-heading-fg": {
            "description": "Foreground color for section heading labels.",
            "default": "var(--a-fg)"
          },
          "--billing-overview-section-heading-size": {
            "description": "Font size for section heading labels.",
            "default": "var(--a-text-base, 1rem)"
          },
          "--billing-overview-section-heading-weight": {
            "description": "Font weight for section heading labels.",
            "default": "var(--a-weight-semibold, 600)"
          },
          "--billing-overview-section-radius": {
            "description": "Section card corner radius.",
            "default": "var(--a-radius-lg)"
          }
        },
        "traits": [],
        "version": 1
      }
    },
    "Block": {
      "title": "Block",
      "description": "Generic padded / margined content wrapper. Applies a configurable\npadding + margin scale via [padding] / [margin] attribute props,\nmapping to the canonical spacing tokens. Use as a lightweight\nspacing wrapper when <section-ui> would imply chrome the parent\ncontainer doesn't own. Not a layout primitive (no flex / grid) —\nfor layout use <col-ui> / <row-ui> / <stack-ui> / <grid-ui>.\n",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "component": {
          "const": "Block"
        },
        "margin": {
          "description": "Margin size (none/xs/sm/md/lg/xl). Accepts `@bp` notation: margin=\"none sm@md\" = no margin below md, sm from md up.",
          "type": "string",
          "enum": [
            "none",
            "xs",
            "sm",
            "md",
            "lg",
            "xl"
          ],
          "default": "none"
        },
        "padding": {
          "description": "Padding amount (none/xs/sm/md/lg/xl → spacing tokens). Accepts `@bp` notation: padding=\"sm md@lg\" = sm below lg, md from lg up.",
          "type": "string",
          "enum": [
            "none",
            "xs",
            "sm",
            "md",
            "lg",
            "xl"
          ],
          "default": "md"
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [],
        "category": "layout",
        "composes": [],
        "events": {},
        "examples": [
          {
            "description": "Basic Block usage",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"Block\",\n    \"children\": [\n      \"child1\",\n      \"child2\"\n    ]\n  },\n  {\n    \"id\": \"child1\",\n    \"component\": \"Text\",\n    \"textContent\": \"First item\"\n  },\n  {\n    \"id\": \"child2\",\n    \"component\": \"Text\",\n    \"textContent\": \"Second item\"\n  }\n]",
            "name": "basic-block"
          }
        ],
        "keywords": [
          "block",
          "code",
          "snippet",
          "syntax",
          "programming",
          "ide",
          "terminal",
          "editor",
          "developer"
        ],
        "name": "UIBlock",
        "related": [
          "Section",
          "Col",
          "Row",
          "Stack"
        ],
        "slots": {},
        "states": [
          {
            "description": "Default, ready for interaction.",
            "name": "idle"
          }
        ],
        "status": "stable",
        "synonyms": {
          "code": [
            "code",
            "block",
            "markdown",
            "editor"
          ],
          "developer": [
            "api",
            "key",
            "code",
            "block"
          ],
          "editor": [
            "markdown",
            "editor",
            "code",
            "block"
          ],
          "ide": [
            "code",
            "block",
            "markdown",
            "editor",
            "split"
          ],
          "programming": [
            "code",
            "block",
            "markdown"
          ],
          "snippet": [
            "code",
            "block"
          ],
          "syntax": [
            "code",
            "block"
          ],
          "terminal": [
            "code",
            "block",
            "command"
          ]
        },
        "tag": "block-ui",
        "tokens": {
          "--block-padding": {
            "description": "Override padding value"
          }
        },
        "traits": [],
        "version": 1
      }
    },
    "Blockquote": {
      "title": "Blockquote",
      "description": "Styled quotation block with a left visual indicator (border rule) +\nitalic body text + optional `cite` attribution line. Use for pull-quotes,\ntestimonials, or inline citations within prose. The default visual\nfollows the prose typography family — pair with `<text-ui>` body\nvariants inside, or pass raw text in the default slot. The optional\n[cite] attribute (or [slot=cite]) renders a small attribution line\nbelow the quote prefixed with an em-dash. Semantic blockquote element\nwith `role=\"blockquote\"` implied via tag name (do NOT wrap in a native\n`<blockquote>` — that produces nested-blockquote semantics).\n",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "cite": {
          "description": "Source attribution shown beneath the quote (small, muted, em-dash\nprefix). For richer attribution (links, multi-line), use the\n`[slot=\"cite\"]` content slot instead — when both are set, the slot\ncontent wins. Plain-string convenience prop for the common case.\n",
          "type": "string",
          "default": ""
        },
        "component": {
          "const": "Blockquote"
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [],
        "category": "display",
        "composes": [],
        "events": {},
        "examples": [
          {
            "description": "Pull-quote with em-dash attribution.",
            "a2ui": "[\n  {\n    \"id\": \"q\",\n    \"component\": \"Blockquote\",\n    \"cite\": \"Steve Jobs, Stanford Commencement, 2005\",\n    \"content\": \"Stay hungry. Stay foolish.\"\n  }\n]\n",
            "name": "default"
          },
          {
            "description": "Blockquote with a linked citation via slot.",
            "a2ui": "[\n  {\n    \"id\": \"q\",\n    \"component\": \"Blockquote\",\n    \"children\": [\"body\", \"src\"]\n  },\n  {\n    \"id\": \"body\",\n    \"component\": \"Text\",\n    \"textContent\": \"The best way to predict the future is to invent it.\"\n  },\n  {\n    \"id\": \"src\",\n    \"component\": \"Link\",\n    \"slot\": \"cite\",\n    \"href\": \"https://en.wikipedia.org/wiki/Alan_Kay\",\n    \"text\": \"Alan Kay (1971)\"\n  }\n]\n",
            "name": "rich-attribution"
          }
        ],
        "keywords": [
          "blockquote",
          "quote",
          "pull-quote",
          "quotation",
          "testimonial",
          "citation",
          "cite"
        ],
        "name": "UIBlockquote",
        "related": [
          "text",
          "link",
          "card"
        ],
        "slots": {
          "default": {
            "description": "The quote body. Plain text or composed `<text-ui>` / inline elements."
          },
          "cite": {
            "description": "Optional citation override. Use for rich attribution (linked source,\nperson + role pairing) where [cite] string is insufficient.\n"
          }
        },
        "states": [
          {
            "description": "Default, ready for reading.",
            "name": "idle"
          }
        ],
        "status": "stable",
        "synonyms": {
          "quote": [
            "blockquote",
            "quotation",
            "pull-quote"
          ],
          "testimonial": [
            "blockquote",
            "quote"
          ]
        },
        "tag": "blockquote-ui",
        "tokens": {
          "--blockquote-cite-fg": {
            "description": "Citation text color (muted).",
            "default": "var(--a-fg-muted)"
          },
          "--blockquote-cite-size": {
            "description": "Citation font size.",
            "default": "var(--a-ui-sm)"
          },
          "--blockquote-fg": {
            "description": "Quote text color.",
            "default": "var(--a-fg-subtle)"
          },
          "--blockquote-pad-block": {
            "description": "Vertical padding inside the blockquote.",
            "default": "var(--a-space-2)"
          },
          "--blockquote-pad-inline": {
            "description": "Inline padding between the rule and the quote text.",
            "default": "var(--a-space-3)"
          },
          "--blockquote-rule-color": {
            "description": "Color of the left indicator rule.",
            "default": "var(--a-border-strong)"
          },
          "--blockquote-rule-width": {
            "description": "Width of the left indicator rule.",
            "default": "2px"
          }
        },
        "traits": [],
        "version": 1
      }
    },
    "Breadcrumb": {
      "title": "Breadcrumb",
      "description": "Breadcrumb trail with auto-inserted separators. Supports a leading icon (first child) and an overflow popover that collapses middle crumbs into a `…` menu.",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "collapse": {
          "description": "Collapse middle crumbs into a `…` overflow popover when there are 4+ items.",
          "type": "boolean",
          "default": false
        },
        "collapseKeepLeading": {
          "description": "Number of leading items to keep visible when [collapse] is active. The first item (often a home/icon link) sits before the overflow popover.",
          "type": "number",
          "default": 1
        },
        "collapseKeepTrailing": {
          "description": "Number of trailing items to keep visible when [collapse] is active. The last item is always the current page.",
          "type": "number",
          "default": 2
        },
        "component": {
          "const": "Breadcrumb"
        },
        "separator": {
          "description": "Character or string rendered between breadcrumb items via CSS ::before.",
          "type": "string",
          "default": "/"
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [],
        "category": "navigation",
        "composes": [
          "menu-ui",
          "button-ui",
          "menu-item-ui"
        ],
        "events": {},
        "examples": [
          {
            "description": "Breadcrumb navigation component with 3 levels: Home, Products, and Detail.",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"Breadcrumb\",\n    \"children\": [\n      \"b1\",\n      \"b2\",\n      \"b3\"\n    ]\n  },\n  {\n    \"id\": \"b1\",\n    \"component\": \"Text\",\n    \"textContent\": \"Home\",\n    \"href\": \"/\"\n  },\n  {\n    \"id\": \"b2\",\n    \"component\": \"Text\",\n    \"textContent\": \"Products\",\n    \"href\": \"/products\"\n  },\n  {\n    \"id\": \"b3\",\n    \"component\": \"Text\",\n    \"textContent\": \"Product Detail\",\n    \"active\": true\n  }\n]",
            "name": "breadcrumb-nav"
          }
        ],
        "keywords": [
          "breadcrumb",
          "navigation",
          "navbar",
          "breadcrumbs",
          "back"
        ],
        "name": "UIBreadcrumb",
        "related": [
          "AdminTopbar",
          "Nav",
          "Tabs"
        ],
        "slots": {},
        "states": [
          {
            "description": "Default, ready for interaction.",
            "name": "idle"
          }
        ],
        "status": "stable",
        "synonyms": {
          "back": [
            "breadcrumb",
            "nav",
            "pagination"
          ],
          "breadcrumbs": [
            "breadcrumb",
            "nav"
          ],
          "navbar": [
            "nav",
            "menu",
            "sidebar",
            "breadcrumb"
          ],
          "navigation": [
            "nav",
            "sidebar",
            "breadcrumb",
            "tabs",
            "menu",
            "pagination"
          ]
        },
        "tag": "breadcrumb-ui",
        "tokens": {},
        "traits": [],
        "version": 1
      }
    },
    "Button": {
      "title": "Button",
      "description": "Clickable button with text, icon, and variant support. Supports submit type for forms.",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "type": {
          "description": "HTML button type (button, submit, reset)",
          "type": "string",
          "default": "button"
        },
        "aria-label": {
          "description": "Accessible label for screen readers. Auto-set from `text` when text is non-empty; meaningful override for icon-only buttons.",
          "$ref": "#/$defs/DynamicString"
        },
        "color": {
          "description": "Semantic intent — composes with [variant]. `<button-ui variant=\"solid\" color=\"danger\">` = filled destructive action; `<button-ui variant=\"outline\" color=\"success\">` = outlined success affordance.",
          "type": "string",
          "enum": [
            "default",
            "accent",
            "info",
            "success",
            "warning",
            "danger"
          ],
          "default": ""
        },
        "component": {
          "const": "Button"
        },
        "disabled": {
          "description": "Disables interaction and prevents click/press events",
          "type": "boolean",
          "default": false
        },
        "icon": {
          "description": "Leading Phosphor icon name (rendered before text).",
          "type": "string",
          "default": ""
        },
        "icon-trailing": {
          "description": "Trailing Phosphor icon name (rendered after text). Use for forward affordances like \"Next →\" / wizards / pagination / product tours where the caret points away from the label.",
          "type": "string",
          "default": ""
        },
        "size": {
          "description": "Sizing scale (xs/sm/md/lg/xl).",
          "type": "string",
          "enum": [
            "xs",
            "sm",
            "md",
            "lg",
            "xl"
          ],
          "default": "md"
        },
        "stretch": {
          "description": "Makes the button stretch to fill the parent's width",
          "type": "boolean",
          "default": false
        },
        "text": {
          "description": "Button text, rendered via CSS attr(text) on ::after",
          "type": "string",
          "default": ""
        },
        "textContent": {
          "description": "Button label. Renderer routes this to the `text` attribute, which is rendered via CSS attr(text) on ::after and mirrored to aria-label.",
          "$ref": "#/$defs/DynamicString"
        },
        "variant": {
          "description": "Visual style — `solid` (default fill), `outline`, `ghost`. `default` / `primary` are aliases of `solid`. Style is independent of semantic intent — to express destructive / success / info / warning intent, set [color=\"…\"] alongside.\nFor **inline navigation** (Terms of Service, Privacy Policy, footer links, \"Sign in\" / \"Sign up\" cross-page affordances) use `<link-ui>` instead — it carries proper `<a href>` semantics, keyboard handling (Enter only, no Space), middle-click open-new-tab, and screen-reader announces \"link\" instead of \"button\". Mixing navigation and action affordances under the same primitive is a category error fixed at this junction.",
          "type": "string",
          "enum": [
            "default",
            "solid",
            "outline",
            "ghost",
            "primary"
          ],
          "default": "solid"
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [
          {
            "description": "Beginning text= with a symbol that icon= already renders. icon=\"plus\" paints a Phosphor \"+\" glyph; text=\"+ New Item\" then renders the literal \"+\" too, so the symbol appears twice ([+ icon] [+ New Item]).",
            "right": "<button-ui text=\"New Claim\" icon=\"plus\" variant=\"primary\"></button-ui>\n",
            "rule": "Do not repeat the icon's glyph in text=. The icon provides the symbol; text= carries only the words. Applies to plus / minus / x / check / arrow icons.",
            "wrong": "<button-ui text=\"+ New Claim\" icon=\"plus\" variant=\"primary\"></button-ui>\n"
          }
        ],
        "category": "action",
        "composes": [
          "icon-ui"
        ],
        "events": {
          "press": {
            "description": "Fired on complete press (pointer up or Enter/Space)"
          }
        },
        "examples": [],
        "keywords": [
          "button",
          "action",
          "cta",
          "submit",
          "click",
          "primary-action",
          "ghost-button",
          "icon-button"
        ],
        "name": "UIButton",
        "related": [
          "Link"
        ],
        "slots": {
          "icon-trailing": {
            "description": "Trailing icon, after the label. Stamped from the `icon-trailing` prop, or slot a custom `<icon-ui slot=\"icon-trailing\">` directly (the consumer's element wins over the prop-stamped one). Sized to --content-height."
          },
          "leading": {
            "description": "Icon container (start), sized to --content-height"
          },
          "trailing": {
            "description": "Icon container (end), sized to --content-height"
          }
        },
        "states": [
          {
            "description": "Default, ready for interaction.",
            "name": "idle"
          },
          {
            "description": "Non-interactive; dimmed.",
            "attribute": "disabled",
            "name": "disabled"
          },
          {
            "description": "Keyboard focus ring.",
            "name": "focused",
            "selector": ":focus-visible"
          },
          {
            "description": "Pointer over; affordance.",
            "name": "hover",
            "selector": ":hover"
          },
          {
            "description": "Active pointer down.",
            "name": "pressed",
            "selector": ":active"
          }
        ],
        "status": "stable",
        "synonyms": {
          "button": [
            "btn",
            "action-button",
            "click-target",
            "control"
          ],
          "submit": [
            "form-submit",
            "primary-action"
          ]
        },
        "tag": "button-ui",
        "tokens": {
          "--button-background": {
            "description": "Override background color"
          },
          "--button-border-color": {
            "description": "Override border color"
          },
          "--button-content-height": {
            "description": "Override icon slot height"
          },
          "--button-font-size": {
            "description": "Override font size"
          },
          "--button-font-weight": {
            "description": "Override font weight"
          },
          "--button-foreground": {
            "description": "Override text color"
          },
          "--button-padding": {
            "description": "Override base padding"
          },
          "--button-radius": {
            "description": "Override border radius"
          },
          "--density": {
            "description": "Inherited multiplier for padding"
          }
        },
        "traits": [
          "pressable",
          "focusable"
        ],
        "version": 1
      }
    },
    "CalendarGrid": {
      "title": "CalendarGrid",
      "description": "Substrate primitive — a single-month calendar grid (month nav + day cells + keyboard nav). Renders inline; no trigger, no popover. Used as a substrate by calendar-picker-ui (popover wrapper), date-range-picker-ui (two side-by-side grids), and datetime-picker-ui (one grid + time pane). For a complete date-picker affordance (trigger + popover + form participation), use calendar-picker-ui.",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "component": {
          "const": "CalendarGrid"
        },
        "disabled": {
          "description": "Disables all interaction.",
          "type": "boolean",
          "default": false
        },
        "max": {
          "description": "Maximum selectable date in ISO format (YYYY-MM-DD).",
          "type": "string",
          "default": ""
        },
        "min": {
          "description": "Minimum selectable date in ISO format (YYYY-MM-DD).",
          "type": "string",
          "default": ""
        },
        "month": {
          "description": "Displayed month (YYYY-MM) used when no value is selected — shows a specific month independent of selection. A selected value always takes precedence. Used by date-range-picker to show its end pane one month ahead of the start.",
          "type": "string",
          "default": ""
        },
        "rangeEnd": {
          "description": "End of a date range (ISO YYYY-MM-DD). See `rangeStart` for the full contract.",
          "type": "string",
          "default": ""
        },
        "rangeStart": {
          "description": "Start of a date range (ISO YYYY-MM-DD). When both rangeStart and rangeEnd are set + ordered, day cells strictly between the endpoints get `[data-in-range]` stamped for visual continuity. Used by `<date-range-picker-ui>` which pushes the same from/to onto both calendar panes. Endpoints themselves render via the `value` prop's `[data-selected]` state.",
          "type": "string",
          "default": ""
        },
        "readonly": {
          "description": "Blocks selection but allows month navigation.",
          "type": "boolean",
          "default": false
        },
        "value": {
          "description": "Selected date in ISO format (YYYY-MM-DD).",
          "type": "string",
          "default": ""
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [
          {
            "fix": "{\"component\": \"CalendarPicker\", \"name\": \"birthdate\"}\n",
            "why": "CalendarGrid is a substrate primitive — it does not participate in\nforms. The `name` attribute has no effect. Use CalendarPicker\n(form-associated) for single-date input.\n",
            "wrong": "{\"component\": \"CalendarGrid\", \"name\": \"birthdate\"}\n"
          }
        ],
        "category": "input",
        "composes": [],
        "events": {
          "change": {
            "description": "User selected a date. detail.value is the ISO string."
          },
          "input": {
            "description": "Focus moved between days during keyboard nav. detail.focusDate is the ISO string."
          }
        },
        "examples": [],
        "keywords": [
          "calendar",
          "date",
          "grid",
          "month",
          "day-picker",
          "substrate"
        ],
        "name": "UICalendarGrid",
        "related": [
          "CalendarPicker",
          "DateRangePicker",
          "DatetimePicker"
        ],
        "slots": {},
        "states": [
          {
            "description": "Pointer-events off, reduced opacity, no selection.",
            "attribute": "disabled",
            "name": "disabled"
          },
          {
            "description": "Navigation allowed, selection blocked.",
            "attribute": "readonly",
            "name": "readonly"
          }
        ],
        "status": "stable",
        "synonyms": {
          "calendar": [
            "calendar",
            "date"
          ],
          "grid": [
            "grid",
            "calendar"
          ]
        },
        "tag": "calendar-grid-ui",
        "tokens": {
          "--calendar-grid-day-bg-hover": {
            "description": "Background on hover (non-selected, non-outside, non-disabled).",
            "default": "var(--a-bg-hover)"
          },
          "--calendar-grid-day-bg-selected": {
            "description": "Background of the selected day cell.",
            "default": "var(--a-accent)"
          },
          "--calendar-grid-day-fg-selected": {
            "description": "Text color of the selected day cell.",
            "default": "var(--a-accent-fg)"
          },
          "--calendar-grid-day-size": {
            "description": "Square cell size for day buttons.",
            "default": "2rem"
          },
          "--calendar-grid-day-today-color": {
            "description": "Accent color used for the today-indicator dot + numeral tint.",
            "default": "var(--a-accent)"
          },
          "--calendar-grid-width": {
            "description": "Grid container width.",
            "default": "16rem"
          }
        },
        "traits": [],
        "version": 1
      }
    },
    "CalendarPicker": {
      "title": "CalendarPicker",
      "description": "Date picker with trigger button and popover calendar grid. Form-associated input emitting ISO date string via change events; supports min/max and disabled-date masks. Use for single-date input in forms; for date ranges compose two pickers or use a dedicated range component.",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "required": {
          "description": "Required for validation",
          "type": "boolean",
          "default": false
        },
        "component": {
          "const": "CalendarPicker"
        },
        "disabled": {
          "description": "Disables interaction",
          "type": "boolean",
          "default": false
        },
        "format": {
          "description": "Display format for the selected date",
          "type": "string",
          "enum": [
            "short",
            "long",
            "iso"
          ],
          "default": "short"
        },
        "label": {
          "description": "Label text displayed above the trigger",
          "type": "string",
          "default": ""
        },
        "max": {
          "description": "Maximum selectable date in ISO format (YYYY-MM-DD)",
          "type": "string",
          "default": ""
        },
        "min": {
          "description": "Minimum selectable date in ISO format (YYYY-MM-DD)",
          "type": "string",
          "default": ""
        },
        "name": {
          "description": "Form field name",
          "type": "string",
          "default": ""
        },
        "open": {
          "description": "Whether the calendar popover is open",
          "type": "boolean",
          "default": false
        },
        "placeholder": {
          "description": "Placeholder text when no date is selected",
          "type": "string",
          "default": "Select date..."
        },
        "placement": {
          "description": "Popover placement relative to the trigger. Default `bottom` centers the calendar panel under the trigger (ADR-0034 Rule 2 — calendar panel wider than trigger).",
          "type": "string",
          "enum": [
            "top",
            "bottom",
            "left",
            "right",
            "top-start",
            "top-end",
            "bottom-start",
            "bottom-end"
          ],
          "default": "bottom"
        },
        "value": {
          "description": "Selected date (ISO string)",
          "type": "string",
          "default": ""
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [],
        "category": "input",
        "composes": [],
        "events": {
          "change": {
            "description": "Fired when a date is selected"
          }
        },
        "examples": [
          {
            "description": "Date and time picker form with calendar picker and time selects.",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"Card\",\n    \"children\": [\n      \"sec\"\n    ]\n  },\n  {\n    \"id\": \"sec\",\n    \"component\": \"Section\",\n    \"children\": [\n      \"col\"\n    ]\n  },\n  {\n    \"id\": \"col\",\n    \"component\": \"Column\",\n    \"children\": [\n      \"name\",\n      \"cal\",\n      \"btn\"\n    ],\n    \"gap\": \"4\"\n  },\n  {\n    \"id\": \"name\",\n    \"component\": \"Input\",\n    \"label\": \"Event Name\"\n  },\n  {\n    \"id\": \"cal\",\n    \"component\": \"CalendarPicker\",\n    \"label\": \"Date\"\n  },\n  {\n    \"id\": \"btn\",\n    \"component\": \"Button\",\n    \"text\": \"Schedule\",\n    \"variant\": \"primary\"\n  }\n]",
            "name": "date-picker"
          },
          {
            "description": "Date range selection form with start/end calendar pickers, quick-pick badges, and apply button.",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"Card\",\n    \"children\": [\n      \"hdr\",\n      \"sec\",\n      \"ftr\"\n    ]\n  },\n  {\n    \"id\": \"hdr\",\n    \"component\": \"Header\",\n    \"children\": [\n      \"title\"\n    ]\n  },\n  {\n    \"id\": \"title\",\n    \"component\": \"Text\",\n    \"slot\": \"heading\",\n    \"textContent\": \"Select Dates\",\n    \"variant\": \"section\"\n  },\n  {\n    \"id\": \"sec\",\n    \"component\": \"Section\",\n    \"children\": [\n      \"fields\"\n    ]\n  },\n  {\n    \"id\": \"fields\",\n    \"component\": \"Column\",\n    \"children\": [\n      \"calendars-row\",\n      \"quick-picks\"\n    ],\n    \"gap\": \"4\"\n  },\n  {\n    \"id\": \"calendars-row\",\n    \"component\": \"Row\",\n    \"children\": [\n      \"start-cal\",\n      \"end-cal\"\n    ],\n    \"gap\": \"3\"\n  },\n  {\n    \"id\": \"start-cal\",\n    \"component\": \"CalendarPicker\",\n    \"label\": \"Start Date\",\n    \"name\": \"startDate\"\n  },\n  {\n    \"id\": \"end-cal\",\n    \"component\": \"CalendarPicker\",\n    \"label\": \"End Date\",\n    \"name\": \"endDate\"\n  },\n  {\n    \"id\": \"quick-picks\",\n    \"component\": \"Row\",\n    \"children\": [\n      \"pick-today\",\n      \"pick-week\",\n      \"pick-month\",\n      \"pick-quarter\"\n    ],\n    \"gap\": \"2\"\n  },\n  {\n    \"id\": \"pick-today\",\n    \"component\": \"Badge\",\n    \"textContent\": \"Today\"\n  },\n  {\n    \"id\": \"pick-week\",\n    \"component\": \"Badge\",\n    \"textContent\": \"This Week\"\n  },\n  {\n    \"id\": \"pick-month\",\n    \"component\": \"Badge\",\n    \"textContent\": \"This Month\"\n  },\n  {\n    \"id\": \"pick-quarter\",\n    \"component\": \"Badge\",\n    \"textContent\": \"This Quarter\"\n  },\n  {\n    \"id\": \"ftr\",\n    \"component\": \"Footer\",\n    \"children\": [\n      \"apply-btn\"\n    ]\n  },\n  {\n    \"id\": \"apply-btn\",\n    \"component\": \"Button\",\n    \"text\": \"Apply\",\n    \"variant\": \"primary\"\n  }\n]",
            "name": "date-range-picker"
          }
        ],
        "keywords": [
          "calendarpicker",
          "calendar-picker",
          "calendar",
          "picker"
        ],
        "name": "UICalendarPicker",
        "related": [
          "input",
          "button",
          "badge"
        ],
        "slots": {
          "calendar": {
            "description": "Popover container for the month grid"
          },
          "label": {
            "description": "Label element above the trigger"
          },
          "trigger": {
            "description": "Combobox button that opens the calendar popover"
          }
        },
        "states": [
          {
            "description": "Default, ready for interaction.",
            "name": "idle"
          },
          {
            "description": "Non-interactive; dimmed.",
            "attribute": "disabled",
            "name": "disabled"
          }
        ],
        "status": "stable",
        "synonyms": {
          "tags": [
            "DateTimeInput",
            "DatePicker"
          ]
        },
        "tag": "calendar-picker-ui",
        "tokens": {},
        "traits": [],
        "version": 1
      }
    },
    "Canvas": {
      "title": "Canvas",
      "description": "A2UI rendering surface — the canonical mount point that consumes a\nDocStore / A2UI document and renders the component tree from it.\nThe runtime's <a2ui-root> typically wraps a canvas-ui internally\nfor the preview pane in <editor-canvas>. Use for embedding live\nA2UI output inside a custom editor, playground, or preview surface;\nnot for generic in-page canvases (use HTML <canvas> for drawing).\n",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "theme": {
          "description": "Component property: theme.",
          "type": "string",
          "default": ""
        },
        "component": {
          "const": "Canvas"
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [],
        "category": "agent",
        "composes": [],
        "events": {
          "canvas-interaction": {
            "description": "Fired on canvas interactions (focus, blur, pointer events). Dispatched at canvas.js:50 + :167."
          }
        },
        "examples": [
          {
            "description": "Basic Canvas usage",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"Card\",\n    \"children\": [\n      \"sec\"\n    ]\n  },\n  {\n    \"id\": \"sec\",\n    \"component\": \"Section\",\n    \"children\": [\n      \"comp\"\n    ]\n  },\n  {\n    \"id\": \"comp\",\n    \"component\": \"Canvas\"\n  }\n]",
            "name": "basic-canvas"
          }
        ],
        "keywords": [
          "canvas"
        ],
        "name": "UICanvas",
        "related": [
          "A2uiRoot",
          "GenRoot",
          "EditorCanvas"
        ],
        "slots": {
          "default": {
            "description": "Default slot — primary child content."
          }
        },
        "states": [
          {
            "description": "Default, ready for interaction.",
            "name": "idle"
          }
        ],
        "status": "stable",
        "synonyms": {
          "tags": [
            "render-surface",
            "a2ui-host"
          ]
        },
        "tag": "canvas-ui",
        "tokens": {},
        "traits": [],
        "version": 1
      }
    },
    "Card": {
      "title": "Card",
      "description": "Bordered container with header, body, and footer sections. The nested <header> activates a 3-column grid when any direct [slot=\"icon|heading|description|action\"] child is present (icon column | heading + description stack | action column). Slot-gating uses :has(> [slot=\"…\"]) (direct-child only) so a nested slot inside a composite child — e.g. <avatar-ui> owning an internal <icon-ui slot=\"icon\"> — does not falsely activate the icon column. The nested <footer> flex-rows with a [slot=\"description\"] + [slot=\"action\"] space-between pattern; multiple <section> siblings stack as the body.",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "component": {
          "const": "Card"
        },
        "draggable": {
          "description": "Enables drag handle + cursor:grab. Wires the draggable trait; dispatches drag-end.",
          "type": "boolean",
          "default": false
        },
        "elevation": {
          "description": "Shadow depth 0-3",
          "type": "number",
          "enum": [
            0,
            1,
            2,
            3
          ],
          "default": 1
        },
        "padding": {
          "description": "Interior padding scale (overrides --card-padding). Accepts the named scale (none/xs/sm/md/lg/xl) or a numeric rung (\"1\"…\"16\").",
          "type": "string",
          "default": "md"
        },
        "raw": {
          "description": "Strips background, border, and shadow. Parent owns the surface. Content structure still applies.",
          "type": "boolean",
          "default": false
        },
        "size": {
          "description": "Card scale. Controls inset, radius, gap, and font sizes. Default (empty) = md.",
          "type": "string",
          "enum": [
            "sm",
            "md",
            "lg"
          ],
          "default": ""
        },
        "variant": {
          "description": "Visual style. `outlined` (alias `outline`) draws a border with no shadow; `filled` uses a tinted canvas surface; `ghost` drops border + shadow.",
          "type": "string",
          "enum": [
            "default",
            "outlined",
            "outline",
            "filled",
            "ghost"
          ],
          "default": "default"
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [],
        "category": "container",
        "composes": [],
        "events": {},
        "examples": [
          {
            "description": "Chat interface with message bubbles containing avatar and text pairs, plus an input footer.",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"Card\",\n    \"children\": [\n      \"hdr\",\n      \"sec\",\n      \"ftr\"\n    ]\n  },\n  {\n    \"id\": \"hdr\",\n    \"component\": \"Header\",\n    \"children\": [\n      \"title\"\n    ]\n  },\n  {\n    \"id\": \"title\",\n    \"component\": \"Text\",\n    \"slot\": \"heading\",\n    \"textContent\": \"Chat\"\n  },\n  {\n    \"id\": \"sec\",\n    \"component\": \"Section\",\n    \"children\": [\n      \"messages\"\n    ]\n  },\n  {\n    \"id\": \"messages\",\n    \"component\": \"Column\",\n    \"gap\": \"3\",\n    \"children\": [\n      \"msg1\",\n      \"msg2\",\n      \"msg3\",\n      \"msg4\"\n    ]\n  },\n  {\n    \"id\": \"msg1\",\n    \"component\": \"Row\",\n    \"gap\": \"2\",\n    \"children\": [\n      \"a1\",\n      \"t1\"\n    ]\n  },\n  {\n    \"id\": \"a1\",\n    \"component\": \"Avatar\",\n    \"name\": \"User\",\n    \"size\": \"sm\"\n  },\n  {\n    \"id\": \"t1\",\n    \"component\": \"Text\",\n    \"variant\": \"body\",\n    \"textContent\": \"Hello! Can you help me with something?\"\n  },\n  {\n    \"id\": \"msg2\",\n    \"component\": \"Row\",\n    \"gap\": \"2\",\n    \"children\": [\n      \"a2\",\n      \"t2\"\n    ]\n  },\n  {\n    \"id\": \"a2\",\n    \"component\": \"Avatar\",\n    \"name\": \"Assistant\",\n    \"size\": \"sm\"\n  },\n  {\n    \"id\": \"t2\",\n    \"component\": \"Text\",\n    \"variant\": \"body\",\n    \"textContent\": \"Of course! I'd be happy to help. What do you need?\"\n  },\n  {\n    \"id\": \"msg3\",\n    \"component\": \"Row\",\n    \"gap\": \"2\",\n    \"children\": [\n      \"a3\",\n      \"t3\"\n    ]\n  },\n  {\n    \"id\": \"a3\",\n    \"component\": \"Avatar\",\n    \"name\": \"User\",\n    \"size\": \"sm\"\n  },\n  {\n    \"id\": \"t3\",\n    \"component\": \"Text\",\n    \"variant\": \"body\",\n    \"textContent\": \"I need to build a dashboard layout.\"\n  },\n  {\n    \"id\": \"msg4\",\n    \"component\": \"Row\",\n    \"gap\": \"2\",\n    \"children\": [\n      \"a4\",\n      \"t4\"\n    ]\n  },\n  {\n    \"id\": \"a4\",\n    \"component\": \"Avatar\",\n    \"name\": \"Assistant\",\n    \"size\": \"sm\"\n  },\n  {\n    \"id\": \"t4\",\n    \"component\": \"Text\",\n    \"variant\": \"body\",\n    \"textContent\": \"Great choice! Let me suggest some patterns for that.\"\n  },\n  {\n    \"id\": \"ftr\",\n    \"component\": \"Footer\",\n    \"children\": [\n      \"input-row\"\n    ]\n  },\n  {\n    \"id\": \"input-row\",\n    \"component\": \"Row\",\n    \"gap\": \"2\",\n    \"children\": [\n      \"chat-input\",\n      \"send-btn\"\n    ]\n  },\n  {\n    \"id\": \"chat-input\",\n    \"component\": \"Input\",\n    \"placeholder\": \"Type a message...\"\n  },\n  {\n    \"id\": \"send-btn\",\n    \"component\": \"Button\",\n    \"text\": \"Send\",\n    \"icon\": \"send\",\n    \"variant\": \"primary\"\n  }\n]",
            "name": "chat-interface"
          },
          {
            "description": "Command palette card with search input and a list of command options.",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"Card\",\n    \"children\": [\n      \"hdr\",\n      \"sec\"\n    ]\n  },\n  {\n    \"id\": \"hdr\",\n    \"component\": \"Header\",\n    \"children\": [\n      \"search\"\n    ]\n  },\n  {\n    \"id\": \"search\",\n    \"component\": \"Input\",\n    \"placeholder\": \"Type a command or search...\",\n    \"icon\": \"search\"\n  },\n  {\n    \"id\": \"sec\",\n    \"component\": \"Section\",\n    \"children\": [\n      \"options\"\n    ]\n  },\n  {\n    \"id\": \"options\",\n    \"component\": \"Column\",\n    \"gap\": \"1\",\n    \"children\": [\n      \"opt1\",\n      \"opt2\",\n      \"opt3\",\n      \"opt4\",\n      \"opt5\"\n    ]\n  },\n  {\n    \"id\": \"opt1\",\n    \"component\": \"Row\",\n    \"gap\": \"2\",\n    \"children\": [\n      \"i1\",\n      \"l1\"\n    ]\n  },\n  {\n    \"id\": \"i1\",\n    \"component\": \"Icon\",\n    \"name\": \"file\"\n  },\n  {\n    \"id\": \"l1\",\n    \"component\": \"Text\",\n    \"textContent\": \"Open File\"\n  },\n  {\n    \"id\": \"opt2\",\n    \"component\": \"Row\",\n    \"gap\": \"2\",\n    \"children\": [\n      \"i2\",\n      \"l2\"\n    ]\n  },\n  {\n    \"id\": \"i2\",\n    \"component\": \"Icon\",\n    \"name\": \"gear\"\n  },\n  {\n    \"id\": \"l2\",\n    \"component\": \"Text\",\n    \"textContent\": \"Settings\"\n  },\n  {\n    \"id\": \"opt3\",\n    \"component\": \"Row\",\n    \"gap\": \"2\",\n    \"children\": [\n      \"i3\",\n      \"l3\"\n    ]\n  },\n  {\n    \"id\": \"i3\",\n    \"component\": \"Icon\",\n    \"name\": \"palette\"\n  },\n  {\n    \"id\": \"l3\",\n    \"component\": \"Text\",\n    \"textContent\": \"Change Theme\"\n  },\n  {\n    \"id\": \"opt4\",\n    \"component\": \"Row\",\n    \"gap\": \"2\",\n    \"children\": [\n      \"i4\",\n      \"l4\"\n    ]\n  },\n  {\n    \"id\": \"i4\",\n    \"component\": \"Icon\",\n    \"name\": \"users\"\n  },\n  {\n    \"id\": \"l4\",\n    \"component\": \"Text\",\n    \"textContent\": \"Manage Users\"\n  },\n  {\n    \"id\": \"opt5\",\n    \"component\": \"Row\",\n    \"gap\": \"2\",\n    \"children\": [\n      \"i5\",\n      \"l5\"\n    ]\n  },\n  {\n    \"id\": \"i5\",\n    \"component\": \"Icon\",\n    \"name\": \"sign-out\"\n  },\n  {\n    \"id\": \"l5\",\n    \"component\": \"Text\",\n    \"textContent\": \"Sign Out\"\n  }\n]",
            "name": "command-palette"
          }
        ],
        "keywords": [
          "card",
          "ecommerce",
          "shop",
          "store",
          "marketplace",
          "catalog",
          "overview",
          "summary",
          "grid",
          "photos",
          "pictures",
          "gallery",
          "portfolio",
          "responsive"
        ],
        "name": "UICard",
        "related": [
          "avatar",
          "input",
          "button",
          "alert",
          "skeleton"
        ],
        "slots": {
          "description": {
            "description": "Secondary metadata — grid row 2 beneath the heading inside `<header>`, or a period/caption line beneath a metric inside `<footer>` (e.g. \"Jan – Mar 2024\"). Also accepts bare `<p>` / `<small>` / body-variant `<text-ui>` as direct children without slot=\"description\". Triggers space-between layout in the footer when combined with slot=\"action\"."
          },
          "action": {
            "description": "Trailing control cluster inside `<header>` (icon-buttons, menu trigger, more-options) or the primary action cluster inside `<footer>` (e.g. Save, Confirm). Aligns to the flex-end edge in both contexts. Pair with slot=\"action-leading\" for dual-cluster footers."
          },
          "action-leading": {
            "description": "Leading control cluster — inline-start edge of the header or footer. In the header: back button, breadcrumb context, or workspace switcher, before the icon/heading column. In the footer: secondary action (e.g. Back) opposite the primary cluster."
          },
          "heading": {
            "description": "Primary title — grid row 1 inside `<header>`, or the prominent metric value inside `<footer>` (trend-stat / KPI pattern). Also accepts bare `<h1>`–`<h6>` tags as direct children without slot=\"heading\". A slot=\"heading\" wrapper can contain inline badges or metadata alongside the title text."
          },
          "icon": {
            "description": "Leading icon for the card header — status, brand, or type marker. Placed in column 1 of the 3-column header grid when present; heading + description shift to column 2. Use `<icon-ui name=\"…\">`, `<avatar-ui>`, or any inline icon element as a DIRECT child of the `<header>` with slot=\"icon\" (not inside a wrapper — direct-child only, per the :has(> [slot=\"icon\"]) gate)."
          },
          "media": {
            "description": "Full-bleed media region — placed before the first `<header>` or `<section>` as the card's hero image / video / illustration slot. Stretches edge-to-edge (negative margin equal to the card's inset); first-child `[slot=\"media\"]` gets zero border-radius on the top corners so it sits flush with the card border."
          }
        },
        "states": [
          {
            "description": "Default, ready for interaction.",
            "name": "idle"
          }
        ],
        "status": "stable",
        "synonyms": {
          "catalog": [
            "product",
            "card",
            "image",
            "grid",
            "inventory"
          ],
          "ecommerce": [
            "product",
            "pricing",
            "inventory",
            "card",
            "image",
            "grid"
          ],
          "gallery": [
            "image",
            "gallery",
            "card",
            "grid"
          ],
          "grid": [
            "table",
            "data",
            "card",
            "image",
            "feature",
            "grid"
          ],
          "marketplace": [
            "product",
            "pricing",
            "card",
            "image",
            "grid",
            "search",
            "filter"
          ],
          "overview": [
            "dashboard",
            "metric",
            "stat",
            "card"
          ],
          "photos": [
            "image",
            "gallery",
            "card",
            "grid"
          ],
          "pictures": [
            "image",
            "gallery",
            "card",
            "grid"
          ],
          "portfolio": [
            "image",
            "gallery",
            "card",
            "grid",
            "feature"
          ],
          "responsive": [
            "split",
            "sidebar",
            "grid",
            "card"
          ],
          "shop": [
            "product",
            "pricing",
            "inventory",
            "card"
          ],
          "store": [
            "product",
            "pricing",
            "inventory",
            "card",
            "image"
          ],
          "summary": [
            "dashboard",
            "metric",
            "stat",
            "card"
          ],
          "tags": [
            "ErrorContainer"
          ]
        },
        "tag": "card-ui",
        "tokens": {
          "--card-background": {
            "description": "Override surface background"
          },
          "--card-border-color": {
            "description": "Override border color"
          },
          "--card-description-color": {
            "description": "Override description color"
          },
          "--card-divider-color": {
            "description": "Override divider border color"
          },
          "--card-heading-color": {
            "description": "Override heading color"
          },
          "--card-heading-size": {
            "description": "Override heading text size"
          },
          "--card-inset": {
            "description": "Override --inset for all children"
          },
          "--card-radius": {
            "description": "Override border radius"
          },
          "--card-shadow": {
            "description": "Override box-shadow"
          },
          "--card-text-color": {
            "description": "Override body text color"
          },
          "--card-text-size": {
            "description": "Override body text size"
          }
        },
        "traits": [],
        "version": 1
      }
    },
    "Chart": {
      "title": "Chart",
      "description": "Declarative SVG chart supporting 18 types: bar, line, pie, donut, radar, sparkline, segments, area, scatter, radial-bar, gauge, stacked-bar, grouped-bar, multi-line, funnel, treemap, sankey, and composed.",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "type": {
          "description": "Chart type. All 18 enum values have dedicated render paths in chart.js.",
          "type": "string",
          "enum": [
            "bar",
            "line",
            "pie",
            "donut",
            "radar",
            "sparkline",
            "segments",
            "area",
            "scatter",
            "radial-bar",
            "gauge",
            "stacked-bar",
            "grouped-bar",
            "multi-line",
            "funnel",
            "treemap",
            "sankey",
            "composed"
          ],
          "default": "bar"
        },
        "color": {
          "description": "Color scheme",
          "type": "string",
          "enum": [
            "accent",
            "success",
            "warning",
            "danger",
            "info"
          ],
          "default": ""
        },
        "component": {
          "const": "Chart"
        },
        "data": {
          "description": "JS property (set programmatically — `el.data = [...]`). An array of plain objects; each object's keys are named by the `x` and `y` attributes — e.g. `<chart-ui x=\"month\" y=\"revenue\">` consumes `[{month:'Jan', revenue:3200}, {month:'Feb', revenue:4100}]`. The Chart.js `{labels, datasets}` envelope is NOT chart-ui's API — passing it (or any non-array value) renders an empty chart. May also be supplied declaratively as a JSON-array `data=\"[…]\"` attribute, hydrated once at connect. Custom accessor on the element class, not a reflected attribute.",
          "$ref": "#/$defs/DynamicStringList"
        },
        "format": {
          "description": "Number-format mode applied to axis labels + value overlays + donut total + gauge value + treemap value + funnel value + internal tooltip. `abbr` is the legacy 1.2K / 3M format; `decimal` fixes 2 decimals; `currency` prefixes via `--chart-currency-prefix` token (default \"$\"); `percent` multiplies × 100 and adds a % suffix.",
          "type": "string",
          "enum": [
            "abbr",
            "decimal",
            "currency",
            "percent"
          ],
          "default": "abbr"
        },
        "hideAverage": {
          "description": "When true, suppress the overlaid average line",
          "type": "boolean",
          "default": false
        },
        "hideGrid": {
          "description": "Hide gridlines",
          "type": "boolean",
          "default": false
        },
        "hideValues": {
          "description": "Hide value labels",
          "type": "boolean",
          "default": false
        },
        "loading": {
          "description": "Show a skeleton placeholder instead of the chart body. Set to true while data is being fetched; clear once data arrives. Preserves the element's aspect-ratio dimensions so the skeleton occupies the same space the chart will fill. Parity with stat-ui[loading] and table-ui[loading] (§FB-12, v0.6.27).",
          "type": "boolean",
          "default": false
        },
        "radius": {
          "description": "Bar corner radius (null = let CSS tokens decide)",
          "type": "number",
          "default": null
        },
        "size": {
          "description": "Chart size",
          "type": "string",
          "enum": [
            "sm",
            "md",
            "lg"
          ],
          "default": ""
        },
        "smooth": {
          "description": "Line smoothing factor",
          "type": "number",
          "default": 0.4
        },
        "x": {
          "description": "Data key for x-axis (category) values",
          "type": "string",
          "default": ""
        },
        "y": {
          "description": "Y-axis key(s), comma-separated for multi-series",
          "type": "string",
          "default": ""
        }
      },
      "required": [
        "component",
        "type"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [],
        "category": "agent",
        "composes": [],
        "events": {
          "chart-hover": {
            "description": "Fires when the pointer enters a datum (bar / dot / slice). Detail includes {label, value, pct, series, slot, pointerX, pointerY}. Only re-fires when the hovered datum changes — moving inside the same datum is quiet."
          },
          "chart-leave": {
            "description": "Fires when the pointer leaves the plot area or a previously-hovered datum with no new one entering."
          },
          "chart-select": {
            "description": "Fires on click of a datum with the same detail shape as chart-hover."
          },
          "legend-update": {
            "description": "Fires when the chart's internal legend payload regenerates (datum\nlabel/value re-aggregate). Signal-only — no detail payload.\nUsed by chart-legend-ui to mirror state when wired via [for].\n"
          }
        },
        "examples": [
          {
            "description": "Dashboard with KPI stat grid and two chart cards.",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"Column\",\n    \"children\": [\n      \"header-row\",\n      \"kpi-grid\",\n      \"chart-grid\"\n    ],\n    \"gap\": \"4\"\n  },\n  {\n    \"id\": \"header-row\",\n    \"component\": \"Row\",\n    \"children\": [\n      \"dash-title\",\n      \"dash-actions\"\n    ]\n  },\n  {\n    \"id\": \"dash-title\",\n    \"component\": \"Text\",\n    \"textContent\": \"Dashboard\",\n    \"variant\": \"title\"\n  },\n  {\n    \"id\": \"dash-actions\",\n    \"component\": \"Row\",\n    \"children\": [\n      \"export-btn\"\n    ],\n    \"gap\": \"2\"\n  },\n  {\n    \"id\": \"export-btn\",\n    \"component\": \"Button\",\n    \"text\": \"Export\",\n    \"variant\": \"outline\",\n    \"size\": \"sm\",\n    \"icon\": \"download\"\n  },\n  {\n    \"id\": \"kpi-grid\",\n    \"component\": \"Grid\",\n    \"children\": [\n      \"k1\",\n      \"k2\",\n      \"k3\",\n      \"k4\"\n    ],\n    \"columns\": \"4\"\n  },\n  {\n    \"id\": \"k1\",\n    \"component\": \"Card\",\n    \"children\": [\n      \"k1h\",\n      \"k1s\"\n    ]\n  },\n  {\n    \"id\": \"k1h\",\n    \"component\": \"Header\",\n    \"children\": [\n      \"k1l\"\n    ]\n  },\n  {\n    \"id\": \"k1l\",\n    \"component\": \"Text\",\n    \"slot\": \"heading\",\n    \"textContent\": \"Revenue\",\n    \"variant\": \"label\"\n  },\n  {\n    \"id\": \"k1s\",\n    \"component\": \"Section\",\n    \"children\": [\n      \"k1v\",\n      \"k1b\"\n    ]\n  },\n  {\n    \"id\": \"k1v\",\n    \"component\": \"Text\",\n    \"textContent\": \"$48.2k\",\n    \"variant\": \"title\"\n  },\n  {\n    \"id\": \"k1b\",\n    \"component\": \"Badge\",\n    \"text\": \"+12.5%\",\n    \"variant\": \"success\",\n    \"size\": \"sm\"\n  },\n  {\n    \"id\": \"k2\",\n    \"component\": \"Card\",\n    \"children\": [\n      \"k2h\",\n      \"k2s\"\n    ]\n  },\n  {\n    \"id\": \"k2h\",\n    \"component\": \"Header\",\n    \"children\": [\n      \"k2l\"\n    ]\n  },\n  {\n    \"id\": \"k2l\",\n    \"component\": \"Text\",\n    \"slot\": \"heading\",\n    \"textContent\": \"Users\",\n    \"variant\": \"label\"\n  },\n  {\n    \"id\": \"k2s\",\n    \"component\": \"Section\",\n    \"children\": [\n      \"k2v\",\n      \"k2b\"\n    ]\n  },\n  {\n    \"id\": \"k2v\",\n    \"component\": \"Text\",\n    \"textContent\": \"2,340\",\n    \"variant\": \"title\"\n  },\n  {\n    \"id\": \"k2b\",\n    \"component\": \"Badge\",\n    \"text\": \"+8%\",\n    \"variant\": \"success\",\n    \"size\": \"sm\"\n  },\n  {\n    \"id\": \"k3\",\n    \"component\": \"Card\",\n    \"children\": [\n      \"k3h\",\n      \"k3s\"\n    ]\n  },\n  {\n    \"id\": \"k3h\",\n    \"component\": \"Header\",\n    \"children\": [\n      \"k3l\"\n    ]\n  },\n  {\n    \"id\": \"k3l\",\n    \"component\": \"Text\",\n    \"slot\": \"heading\",\n    \"textContent\": \"Bounce\",\n    \"variant\": \"label\"\n  },\n  {\n    \"id\": \"k3s\",\n    \"component\": \"Section\",\n    \"children\": [\n      \"k3v\",\n      \"k3b\"\n    ]\n  },\n  {\n    \"id\": \"k3v\",\n    \"component\": \"Text\",\n    \"textContent\": \"24.3%\",\n    \"variant\": \"title\"\n  },\n  {\n    \"id\": \"k3b\",\n    \"component\": \"Badge\",\n    \"text\": \"-3.1%\",\n    \"variant\": \"danger\",\n    \"size\": \"sm\"\n  },\n  {\n    \"id\": \"k4\",\n    \"component\": \"Card\",\n    \"children\": [\n      \"k4h\",\n      \"k4s\"\n    ]\n  },\n  {\n    \"id\": \"k4h\",\n    \"component\": \"Header\",\n    \"children\": [\n      \"k4l\"\n    ]\n  },\n  {\n    \"id\": \"k4l\",\n    \"component\": \"Text\",\n    \"slot\": \"heading\",\n    \"textContent\": \"Session\",\n    \"variant\": \"label\"\n  },\n  {\n    \"id\": \"k4s\",\n    \"component\": \"Section\",\n    \"children\": [\n      \"k4v\",\n      \"k4b\"\n    ]\n  },\n  {\n    \"id\": \"k4v\",\n    \"component\": \"Text\",\n    \"textContent\": \"4m 23s\",\n    \"variant\": \"title\"\n  },\n  {\n    \"id\": \"k4b\",\n    \"component\": \"Badge\",\n    \"text\": \"+15s\",\n    \"variant\": \"info\",\n    \"size\": \"sm\"\n  },\n  {\n    \"id\": \"chart-grid\",\n    \"component\": \"Grid\",\n    \"children\": [\n      \"ch1\",\n      \"ch2\"\n    ],\n    \"columns\": \"2\"\n  },\n  {\n    \"id\": \"ch1\",\n    \"component\": \"Card\",\n    \"children\": [\n      \"ch1h\",\n      \"ch1s\"\n    ]\n  },\n  {\n    \"id\": \"ch1h\",\n    \"component\": \"Header\",\n    \"children\": [\n      \"ch1t\"\n    ]\n  },\n  {\n    \"id\": \"ch1t\",\n    \"component\": \"Text\",\n    \"slot\": \"heading\",\n    \"textContent\": \"Revenue\",\n    \"variant\": \"section\"\n  },\n  {\n    \"id\": \"ch1s\",\n    \"component\": \"Section\",\n    \"children\": [\n      \"ch1-chart\"\n    ]\n  },\n  {\n    \"id\": \"ch1-chart\",\n    \"component\": \"Chart\",\n    \"type\": \"bar\",\n    \"x\": \"month\",\n    \"y\": \"revenue\"\n  },\n  {\n    \"id\": \"ch2\",\n    \"component\": \"Card\",\n    \"children\": [\n      \"ch2h\",\n      \"ch2s\"\n    ]\n  },\n  {\n    \"id\": \"ch2h\",\n    \"component\": \"Header\",\n    \"children\": [\n      \"ch2t\"\n    ]\n  },\n  {\n    \"id\": \"ch2t\",\n    \"component\": \"Text\",\n    \"slot\": \"heading\",\n    \"textContent\": \"Users\",\n    \"variant\": \"section\"\n  },\n  {\n    \"id\": \"ch2s\",\n    \"component\": \"Section\",\n    \"children\": [\n      \"ch2-chart\"\n    ]\n  },\n  {\n    \"id\": \"ch2-chart\",\n    \"component\": \"Chart\",\n    \"type\": \"line\",\n    \"x\": \"month\",\n    \"y\": \"users\"\n  }\n]",
            "name": "chart-dashboard"
          }
        ],
        "keywords": [
          "chart",
          "stats",
          "statistics",
          "kpi",
          "figures",
          "analytics",
          "reporting",
          "insights",
          "monitor",
          "monitoring",
          "telemetry",
          "observability",
          "performance",
          "graph",
          "visualization",
          "plot",
          "diagram",
          "histogram",
          "pie",
          "bar-chart",
          "line-chart",
          "crm",
          "poll"
        ],
        "name": "UIChart",
        "related": [
          "button",
          "grid",
          "badge"
        ],
        "slots": {
          "title": {
            "description": "Chart title element"
          },
          "canvas": {
            "description": "Chart rendering area"
          },
          "empty": {
            "description": "Shown in place of the SVG when `.data` is empty or missing. Typically an `<empty-state-ui>` with icon + heading + description + optional action. Visibility is CSS-toggled via `[data-has-data]` on the host — authors don't need to manage it imperatively."
          }
        },
        "states": [
          {
            "description": "Default, ready for interaction.",
            "name": "idle"
          },
          {
            "description": "No data — the empty slot (if provided) is rendered; otherwise the chart area renders nothing. Host carries [data-has-data] only when data is present.",
            "name": "empty"
          }
        ],
        "status": "stable",
        "synonyms": {
          "analytics": [
            "chart",
            "dashboard",
            "metric",
            "stat",
            "leaderboard"
          ],
          "bar-chart": [
            "chart",
            "dashboard"
          ],
          "crm": [
            "dashboard",
            "table",
            "data",
            "user",
            "profile",
            "chart"
          ],
          "diagram": [
            "chart",
            "dashboard"
          ],
          "figures": [
            "stat",
            "metric",
            "chart"
          ],
          "graph": [
            "chart",
            "dashboard"
          ],
          "histogram": [
            "chart",
            "dashboard"
          ],
          "insights": [
            "chart",
            "dashboard",
            "metric",
            "stat"
          ],
          "kpi": [
            "stat",
            "metric",
            "dashboard",
            "chart"
          ],
          "line-chart": [
            "chart",
            "dashboard"
          ],
          "monitor": [
            "dashboard",
            "metric",
            "stat",
            "chart",
            "progress"
          ],
          "monitoring": [
            "dashboard",
            "metric",
            "stat",
            "chart",
            "progress"
          ],
          "observability": [
            "dashboard",
            "metric",
            "chart",
            "stat"
          ],
          "performance": [
            "dashboard",
            "metric",
            "chart",
            "stat",
            "progress"
          ],
          "pie": [
            "chart",
            "dashboard"
          ],
          "plot": [
            "chart",
            "dashboard"
          ],
          "poll": [
            "form",
            "radio",
            "chart"
          ],
          "reporting": [
            "chart",
            "dashboard",
            "metric",
            "stat",
            "table",
            "data"
          ],
          "statistics": [
            "stat",
            "metric",
            "dashboard",
            "chart"
          ],
          "stats": [
            "stat",
            "metric",
            "dashboard",
            "chart"
          ],
          "telemetry": [
            "dashboard",
            "metric",
            "chart",
            "stat"
          ],
          "visualization": [
            "chart",
            "dashboard",
            "metric"
          ]
        },
        "tag": "chart-ui",
        "tokens": {},
        "traits": [],
        "version": 1
      }
    },
    "ChartLegend": {
      "title": "ChartLegend",
      "description": "Standalone legend primitive for the AdiaUI chart family. Renders a row of badge-ui chips (swatch + label) that are keyboard-focusable and click-toggleable. Composes with chart-ui via [for] id-ref (auto-mirror) or via explicit [items] JSON.",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "items": {
          "description": "JSON array of {key, label, slot?, pct?} legend items. Takes precedence over [for] when both are provided.",
          "type": "string",
          "default": ""
        },
        "component": {
          "const": "ChartLegend"
        },
        "for": {
          "description": "id-ref of a chart-ui / heatmap-ui to mirror series from.",
          "type": "string",
          "default": ""
        },
        "onToggle": {
          "description": "Series-toggle mode emitted via the `toggle` event. `hide` removes the series from the render; `opacity` fades it. Wired via [for] on chart-ui.",
          "type": "string",
          "enum": [
            "hide",
            "opacity"
          ],
          "default": "hide"
        },
        "position": {
          "description": "Layout hint — drives flex-direction. Actual placement follows DOM order.",
          "type": "string",
          "enum": [
            "top",
            "bottom",
            "left",
            "right"
          ],
          "default": "bottom"
        },
        "shape": {
          "description": "Swatch shape. Maps to badge-ui's icon for dot/square variants.",
          "type": "string",
          "enum": [
            "dot",
            "square",
            "line",
            "dashed"
          ],
          "default": "dot"
        },
        "static": {
          "description": "When set, rows are non-interactive <span>s (no click, no toggle).",
          "type": "boolean",
          "default": false
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [],
        "category": "agent",
        "composes": [
          "badge-ui",
          "swatch-ui"
        ],
        "events": {
          "toggle": {
            "description": "Fires on row click (non-static). Detail: {key, active, mode}. `active` is the new state (true=visible). Consumers (or chart-ui via [for]) wire this to series visibility.",
            "detail": {
              "active": {
                "description": "New visibility state (true = visible).",
                "type": "boolean"
              },
              "key": {
                "description": "Series key identifier.",
                "type": "string"
              },
              "mode": {
                "description": "Visibility mode (default \"hide\").",
                "type": "string"
              }
            }
          }
        },
        "examples": [
          {
            "description": "Standalone legend with explicit items array.",
            "a2ui": "[\n  {\n    \"id\": \"legend\", \"component\": \"ChartLegend\",\n    \"shape\": \"dot\",\n    \"items\": \"[{\\\"key\\\":\\\"revenue\\\",\\\"label\\\":\\\"Revenue\\\",\\\"slot\\\":0},{\\\"key\\\":\\\"users\\\",\\\"label\\\":\\\"Users\\\",\\\"slot\\\":1}]\"\n  }\n]",
            "name": "standalone-with-items"
          },
          {
            "description": "Legend mirrors a named chart's series data.",
            "a2ui": "[\n  {\n    \"id\": \"root\", \"component\": \"Column\",\n    \"children\": [\"chart\", \"legend\"]\n  },\n  {\n    \"id\": \"chart\", \"component\": \"Chart\",\n    \"type\": \"multi-line\", \"x\": \"month\", \"y\": \"revenue,users\"\n  },\n  {\n    \"id\": \"legend\", \"component\": \"ChartLegend\",\n    \"for\": \"chart\",\n    \"shape\": \"line\",\n    \"position\": \"bottom\"\n  }\n]",
            "name": "mirror-chart-by-id"
          }
        ],
        "keywords": [
          "legend",
          "chart-legend",
          "series",
          "key",
          "swatch",
          "chart",
          "graph",
          "visualization"
        ],
        "name": "UIChartLegend",
        "related": [
          "chart",
          "badge",
          "heatmap"
        ],
        "slots": {
          "default": {
            "description": "Normally empty — the primitive renders its own rows. Authors who want fully custom markup can provide their own children with [data-row] and [data-key] attributes; the primitive won't wipe them if [items] is empty and [for] is unset."
          }
        },
        "states": [
          {
            "description": "Default, ready for interaction.",
            "name": "idle"
          },
          {
            "description": "Rows are <button>s. Default unless [static].",
            "name": "interactive"
          },
          {
            "description": "Rows are <span>s. No click handler, no toggle affordance.",
            "name": "static"
          }
        ],
        "status": "stable",
        "synonyms": {
          "chart": [
            "chart-legend",
            "legend"
          ],
          "legend": [
            "chart-legend"
          ]
        },
        "tag": "chart-legend-ui",
        "tokens": {},
        "traits": [],
        "version": 1
      }
    },
    "ChatComposer": {
      "title": "ChatComposer",
      "description": "Module-tier chat composer wrapper — replaces legacy <chat-input-ui\ndata-chat-input> direct child of <chat-shell> per ADR-0023.\nForwards submit events as 'composer-submit', propagates [disabled]\nto the inner input, provides slot vocabulary for future composer\nsurfaces (file attach, autocomplete, model picker).\n\nSits inside <chat-shell> as the input region (typically inside or\nalongside the footer). Authors place an inner <chat-input-ui>\n(or input-ui / textarea-ui) as the primary input.\n",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "component": {
          "const": "ChatComposer"
        },
        "disabled": {
          "description": "Reflected — set by the host while streaming, or by application\ncode. Propagated to the inner input element automatically.\n",
          "type": "boolean",
          "default": false
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [],
        "category": "input",
        "composes": [],
        "events": {
          "composer-submit": {
            "description": "Bubbles when the inner input fires its 'submit' event. Detail mirrors the inner event's detail (typically text + model).",
            "detail": {
              "model": "string",
              "text": "string"
            }
          }
        },
        "examples": [],
        "keywords": [
          "chat-composer",
          "chat-input",
          "composer",
          "message-input",
          "conversation-input"
        ],
        "name": "ChatComposer",
        "related": [
          "ChatShell",
          "ChatThread",
          "ChatInput",
          "Input",
          "Textarea"
        ],
        "slots": {
          "default": {
            "description": "Default — primary input child (typically <chat-input-ui>; <input-ui> also works — both emit a `submit` event on Enter without Shift)."
          },
          "attach": {
            "description": "Future — attachment trigger button (paperclip icon to upload)."
          },
          "leading": {
            "description": "Leading controls — autocomplete trigger, voice input, etc."
          },
          "trailing": {
            "description": "Trailing controls — model picker, send button override, etc."
          }
        },
        "states": [
          {
            "description": "Default, accepting input.",
            "name": "idle"
          },
          {
            "description": "Input is disabled (typically during LLM streaming).",
            "attribute": "disabled",
            "name": "disabled"
          }
        ],
        "status": "stable",
        "synonyms": {
          "composer": [
            "message-input",
            "chat-input",
            "conversation-input"
          ]
        },
        "tag": "chat-composer",
        "tokens": {},
        "traits": [],
        "version": 1
      }
    },
    "ChatEmpty": {
      "title": "ChatEmpty",
      "description": "Module-tier chat empty state. CSS-only — no behavior, no JS. Sits\nas the first child of <chat-thread> as the empty state placeholder.\nVisibility is driven by <chat-thread>'s [empty] reflected attribute\nvia CSS (no JS toggling needed) — when messages arrive, the parent\nthread loses [empty] and CSS hides this stub.\n\nReplaces the legacy <empty-state-ui data-chat-empty> child of the\nmessages container per ADR-0023. The legacy shape was retired in\nv0.4.0 per ADR-0024 and is no longer recognized.\n",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "component": {
          "const": "ChatEmpty"
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [],
        "category": "feedback",
        "composes": [],
        "events": {},
        "examples": [],
        "keywords": [
          "chat-empty",
          "empty-state",
          "placeholder",
          "no-messages"
        ],
        "name": "ChatEmpty",
        "related": [
          "ChatShell",
          "ChatThread",
          "EmptyState"
        ],
        "slots": {
          "default": {
            "description": "Empty state content — typically an icon + heading + description. Authors compose with <empty-state-ui> as a child, or supply inline content directly."
          }
        },
        "states": [
          {
            "description": "Default, visible.",
            "name": "idle"
          },
          {
            "description": "Hidden via parent <chat-thread>:not([empty]) selector.",
            "name": "hidden"
          }
        ],
        "status": "stable",
        "synonyms": {
          "chat-empty": [
            "empty-state",
            "placeholder",
            "no-conversations"
          ]
        },
        "tag": "chat-empty",
        "tokens": {},
        "traits": [],
        "version": 1
      }
    },
    "ChatHeader": {
      "title": "ChatHeader",
      "description": "Module-tier chat header chrome bar. CSS-only — no behavior, no JS.\nSits at the top of <chat-shell> or inside a <chat-sidebar>. Holds\nthe chat name, status indicator, and action clusters via slot\nvocabulary.\n\nReplaces the legacy <header> with [data-chat-name] / [data-chat-status]\ndata-attribute children per ADR-0023. The legacy shape was retired\nin v0.4.0 per ADR-0024 and is no longer recognized; new code uses\n<chat-header> with <chat-status> as a slotted child.\n",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "component": {
          "const": "ChatHeader"
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [],
        "category": "layout",
        "composes": [],
        "events": {},
        "examples": [],
        "keywords": [
          "chat-header",
          "chat-titlebar",
          "chrome-bar",
          "app-header"
        ],
        "name": "ChatHeader",
        "related": [
          "ChatShell",
          "ChatStatus",
          "ChatThread",
          "ChatComposer"
        ],
        "slots": {
          "default": {
            "description": "Default — typically [slot=\"name\"] + [slot=\"status\"] children, or ad-hoc inline content."
          },
          "action": {
            "description": "Trailing control cluster (settings, share, clear conversation)."
          },
          "action-leading": {
            "description": "Leading control cluster (back button, conversation switcher)."
          },
          "name": {
            "description": "Primary chat label (model name, conversation title, etc.)."
          },
          "status": {
            "description": "Status indicator — typically <chat-status> showing connection / streaming state."
          }
        },
        "states": [
          {
            "description": "Default, the only state.",
            "name": "idle"
          }
        ],
        "status": "stable",
        "synonyms": {
          "chat-header": [
            "titlebar",
            "app-header",
            "navbar"
          ]
        },
        "tag": "chat-header",
        "tokens": {},
        "traits": [],
        "version": 1
      }
    },
    "ChatInput": {
      "title": "ChatInput",
      "description": "Composable chat input bar — a self-contained chat-message composer\nthat stamps its OWN inner structure (textarea + model picker + send\nbutton) when authored as a bare `<chat-input-ui>` tag.\n\nIMPORTANT (closes the 2026-05-14 redundant-send-button class): the\ncomponent stamps a built-in send button (paper-plane-right icon,\nprimary variant). DO NOT add a separate Button sibling for \"send\" —\nthe user gets two send buttons. The submit event fires on Enter or\nsend-button click; `detail` is `{ text, model }`.\n\nInner stamped structure (default):\n  <chat-input-ui>\n    <textarea-ui placeholder=\"Type a message...\" rows=\"1\"></textarea-ui>\n    <div slot=\"toolbar\">\n      <select-ui slot=\"model\" placeholder=\"Model\">...</select-ui>\n      <button-ui icon=\"paper-plane-right\" variant=\"primary\" slot=\"send\"></button-ui>\n    </div>\n  </chat-input-ui>\n\nLayout:\n  ┌──────────────────────────────────┐\n  │  textarea (grows vertically)     │\n  ├──────────────────────────────────┤\n  │  [model ▾]           [⏎ send]   │  ← toolbar (model picker + built-in send)\n  └──────────────────────────────────┘\n\nComposite wrapper, not a form field itself. The inner textarea-ui\nis form-associated via UIFormElement and submits through the parent\nform. `chat-input-ui`'s `disabled` / `placeholder` props propagate\nto the inner textarea.\n\nFor module-tier composer surfaces (slot vocabulary for file attach,\nautocomplete, trailing/leading controls), wrap inside\n`<chat-composer>` — see ChatComposer for the module-tier shape.\n",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "component": {
          "const": "ChatInput"
        },
        "disabled": {
          "description": "Disable the entire input. Textarea becomes contenteditable=false;\nsend button disabled.\n",
          "type": "boolean",
          "default": false
        },
        "loading": {
          "description": "In-flight / streaming state. Send button disabled, submit events\nsuppressed, but textarea stays editable so the user can draft a\nfollow-up while the model is still responding.\n",
          "type": "boolean",
          "default": false
        },
        "model": {
          "description": "Currently selected model value (reflected, two-way with inner\n`<select-ui slot=\"model\">`). Empty when no model picker is shown.\n",
          "type": "string",
          "default": ""
        },
        "models": {
          "description": "JSON array of model options for the inner model picker —\n[{value, label}] or [{label, options: [...]}] groups. Empty array\nhides the model picker.\n",
          "type": "array",
          "default": []
        },
        "placeholder": {
          "description": "Textarea placeholder. Defaults to \"Type a message...\".",
          "type": "string",
          "default": "Type a message..."
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [
          {
            "description": "Adding a separate Button(primary) sibling next to ChatInput for \"send\". The component stamps its own send button (paper-plane-right icon). Two send buttons render side-by-side, confusing users."
          },
          {
            "description": "Stamping a Select next to ChatInput for model picker. The component has a built-in model picker driven by the `models` prop. Set `models=[{value, label}, ...]` instead of stamping a separate Select."
          },
          {
            "description": "Wrapping ChatInput inside <field-ui label=\"...\"> for label association. ChatInput is a composite container, not a form field. For a labeled composer surface, use <chat-composer> + slot label markup."
          }
        ],
        "category": "agent",
        "composes": [],
        "events": {
          "submit": {
            "description": "Fires when the user presses Enter (without Shift) in the textarea OR clicks the built-in send button. Unconditional — there is no [submit-on-enter] opt-in or opt-out attribute; Enter→submit is delegated from the inner <textarea-ui> which always emits a `submit` event on Enter without Shift. The composer suppresses submission while `[loading]` is set.",
            "detail": {
              "model": {
                "description": "Currently selected model value (empty if no model picker).",
                "type": "string"
              },
              "text": {
                "description": "Submitted message text from the inner textarea.",
                "type": "string"
              }
            }
          }
        },
        "examples": [
          {
            "description": "Minimal chat input — placeholder, no model picker. Sits inside a chat shell footer.",
            "a2ui": "[\n  {\"id\": \"root\", \"component\": \"ChatInput\", \"placeholder\": \"Ask me anything...\"}\n]",
            "name": "basic-chat-input"
          },
          {
            "description": "Chat input with model selection. The `models` prop drives the built-in model picker — DO NOT add a separate Select sibling.",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"ChatInput\",\n    \"placeholder\": \"Type a message...\",\n    \"model\": \"claude-opus-4-7\",\n    \"models\": [\n      {\"value\": \"claude-opus-4-7\", \"label\": \"Claude Opus 4.7\"},\n      {\"value\": \"claude-haiku-4-5\", \"label\": \"Claude Haiku 4.5\"},\n      {\"value\": \"claude-sonnet-4-5\", \"label\": \"Claude Sonnet 4.5\"}\n    ]\n  }\n]",
            "name": "chat-input-with-models"
          },
          {
            "description": "Streaming response state. `[loading]` reflects on the host; send button disables; textarea stays editable so the user can draft a follow-up while the LLM is responding.",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"ChatInput\",\n    \"placeholder\": \"Drafting follow-up while streaming...\",\n    \"loading\": true\n  }\n]",
            "name": "chat-input-loading-state"
          },
          {
            "description": "Full chat shell — header + thread + ChatInput in the footer. Note: ChatInput is the sole footer child; no separate send button.",
            "a2ui": "[\n  {\"id\": \"root\", \"component\": \"ChatShell\", \"children\": [\"header\", \"thread\", \"input\"]},\n  {\"id\": \"header\", \"component\": \"ChatHeader\", \"title\": \"Chat\"},\n  {\"id\": \"thread\", \"component\": \"ChatThread\"},\n  {\"id\": \"input\", \"component\": \"ChatInput\", \"placeholder\": \"Send a message...\"}\n]",
            "name": "chat-shell-with-chat-input"
          }
        ],
        "keywords": [
          "chat-input",
          "chat",
          "message-input",
          "composer",
          "send-message",
          "conversation",
          "prompt",
          "submit"
        ],
        "name": "UIChatInput",
        "related": [
          "ChatShell",
          "ChatThread",
          "ChatComposer",
          "ChatHeader",
          "TextArea",
          "Input"
        ],
        "slots": {
          "model": {
            "description": "Override slot for the model picker. Most authors should NOT override this — set the `models` prop instead."
          },
          "send": {
            "description": "Override slot for the send button only. The default stamped send button has `[icon=\"paper-plane-right\"] [variant=\"primary\"]`. Most authors should NOT override this — the built-in send button IS the send control. Adding a separate Button sibling for \"send\" duplicates this functionality."
          },
          "toolbar": {
            "description": "Override slot for the entire toolbar row (model picker + send button). Most authors should NOT override this — the built-in toolbar handles model selection + send. Use this only when custom toolbar layout is required."
          }
        },
        "states": [
          {
            "description": "Default, accepting input. Send button enabled when textarea has content.",
            "name": "idle"
          },
          {
            "description": "Input fully disabled (typically during initial form setup).",
            "attribute": "disabled",
            "name": "disabled"
          },
          {
            "description": "LLM is responding. Send button disabled + submit events suppressed, but textarea stays editable for follow-up drafts.",
            "attribute": "loading",
            "name": "loading"
          }
        ],
        "status": "stable",
        "synonyms": {
          "message-input": [
            "conversation-input",
            "prompt-input",
            "send-bar"
          ]
        },
        "tag": "chat-input-ui",
        "tokens": {},
        "traits": [],
        "version": 1
      }
    },
    "ChatShell": {
      "title": "ChatShell",
      "description": "Behavior-only chat orchestrator (LLM-streaming module). Canonical\nauthoring shape uses cluster-namespaced bespoke children —\n<chat-thread> as the message scroll surface (containing <chat-empty>\nas the empty-state slot), <chat-composer> wrapping the input\nprimitive, and optional <chat-header> / <chat-sidebar> / <chat-status>\nchrome. The shell wires LLM streaming, markdown rendering, code-block\nupgrades, and the proxy-url integration path; each bespoke child owns\nits own [streaming] / [empty] / [disabled] state-as-attribute\nsemantics per ADR-0023.\n\nLegacy data-attribute shapes (<section data-chat-messages>,\n<chat-input-ui data-chat-input>, <empty-state-ui data-chat-empty>,\n<header data-chat-name>) were RETIRED in v0.4.0 per ADR-0024 and\nare no longer recognized. Consumers must use the bespoke vocabulary.\n",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "component": {
          "const": "ChatShell"
        },
        "model": {
          "description": "Model identifier.",
          "type": "string",
          "default": ""
        },
        "provider": {
          "description": "LLM provider name (anthropic | openai | google | stub).",
          "type": "string",
          "default": ""
        },
        "proxyUrl": {
          "description": "API proxy endpoint for LLM calls; enables self-contained chat without external wiring.",
          "type": "string",
          "default": ""
        },
        "streaming": {
          "description": "Active streaming indicator; toggled while a response is being received. Propagated to <chat-thread>[streaming] and <chat-composer>[disabled].",
          "type": "boolean",
          "default": false
        },
        "system": {
          "description": "System prompt prepended to conversations.",
          "type": "string",
          "default": ""
        },
        "thinking": {
          "description": "Enable Anthropic extended-thinking mode.",
          "type": "boolean",
          "default": false
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [],
        "category": "container",
        "composes": [
          "code-ui"
        ],
        "events": {
          "abort": {
            "description": "Fired when the user aborts an in-flight request."
          },
          "chunk": {
            "description": "Fired for each streaming chunk.",
            "detail": {
              "snapshot": "string",
              "text": "string"
            }
          },
          "clear": {
            "description": "Fired when the conversation is cleared."
          },
          "done": {
            "description": "Fired when a response completes.",
            "detail": {
              "stopReason": "string",
              "text": "string",
              "usage": "object"
            }
          },
          "error": {
            "description": "Fired on any LLM / network error.",
            "detail": {
              "error": "Error"
            }
          },
          "message": {
            "description": "Fired after each message (user or assistant) is appended.",
            "detail": {
              "content": "string",
              "id": "string",
              "role": "string"
            }
          },
          "submit": {
            "description": "Fired on user message submit (before LLM call begins). Forwarded from <chat-composer>'s composer-submit event.",
            "detail": {
              "model": "string",
              "text": "string"
            }
          },
          "thinking": {
            "description": "Fired when the model emits extended-thinking content.",
            "detail": {
              "text": "string"
            }
          }
        },
        "examples": [],
        "keywords": [
          "chat-shell",
          "chat",
          "llm",
          "streaming",
          "conversation",
          "agent",
          "assistant"
        ],
        "name": "ChatShell",
        "related": [
          "ChatThread",
          "ChatComposer",
          "ChatEmpty",
          "ChatHeader",
          "ChatSidebar",
          "ChatStatus",
          "ChatInput",
          "Code"
        ],
        "slots": {
          "default": {
            "description": "Bespoke children compose here in document order — typically <chat-thread> (with optional <chat-empty> inside) for the message surface, then <chat-composer> wrapping a <chat-input-ui> for the input. Optional <chat-header>, <chat-sidebar slot=\"leading|trailing\">, <chat-status>."
          }
        },
        "states": [
          {
            "description": "No active request.",
            "name": "idle"
          },
          {
            "description": "An LLM request is in-flight; child <chat-thread>[streaming] + <chat-composer>[disabled] propagate from this attribute.",
            "attribute": "streaming",
            "name": "streaming"
          }
        ],
        "status": "stable",
        "synonyms": {
          "chat": [
            "conversation",
            "messages",
            "thread",
            "assistant",
            "agent"
          ]
        },
        "tag": "chat-shell",
        "tokens": {},
        "traits": [],
        "version": 1
      }
    },
    "ChatSidebar": {
      "title": "ChatSidebar",
      "description": "Module-tier chat-cluster sidebar — owns resize, snap-to-collapsed,\npersistence, and the [collapsed] reflected attribute. Sits inside\n<chat-shell> as slot=\"leading\" (conversation history rail) or\nslot=\"trailing\" (artifacts/citations panel). Mirrors the admin-sidebar\nshape — same 4 concerns, cluster-namespaced for the chat family.\n\nThis is the chat-cluster equivalent of <admin-sidebar> per ADR-0023.\n<chat-shell> doesn't currently have a legacy sidebar shape (chat is\ntypically a single-pane experience), so <chat-sidebar> is purely\nforward-looking — for chat apps that want conversation-history or\ninspector rails.\n",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "collapsed": {
          "description": "Reflected — set when the sidebar's measured width is at or below\n96px. Consumers query this to style \"collapsed mode\" without\nduplicating threshold math.\n",
          "type": "boolean",
          "default": false
        },
        "collapsible": {
          "description": "Opts in to programmatic collapse — toggle button wiring + the\n.toggle() / .collapse() / .expand() public methods.\n",
          "type": "boolean",
          "default": false
        },
        "component": {
          "const": "ChatSidebar"
        },
        "min-width": {
          "description": "Optional override for the snap-floor width. Defaults to reading\nCSS min-width via getComputedStyle.\n",
          "type": "string",
          "default": ""
        },
        "name": {
          "description": "Identifier for localStorage namespacing. Defaults to slot value\n(\"leading\" or \"trailing\"). Override when running multiple sidebars\nwith the same slot.\n",
          "type": "string",
          "default": ""
        },
        "resizable": {
          "description": "Opts in to drag-to-resize behavior. Author supplies a child\n[data-resize] element as the drag handle.\n",
          "type": "boolean",
          "default": false
        },
        "resizing": {
          "description": "Reflected — set during an active pointer-drag on the resize handle.\nUseful for suppressing transitions while dragging.\n",
          "type": "boolean",
          "default": false
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [],
        "category": "layout",
        "composes": [],
        "events": {
          "sidebar-resize": {
            "description": "Bubbles when an active pointer-drag releases.",
            "detail": {
              "name": "string",
              "width": "number"
            }
          },
          "sidebar-toggle": {
            "description": "Bubbles when sidebar collapses or expands.",
            "detail": {
              "expanded": "boolean",
              "name": "string"
            }
          }
        },
        "examples": [],
        "keywords": [
          "chat-sidebar",
          "chat-sidebar",
          "conversation-history",
          "chat-rail",
          "sidebar",
          "leading",
          "trailing",
          "inspector"
        ],
        "name": "ChatSidebar",
        "related": [
          "ChatShell",
          "ChatComposer",
          "ChatHeader",
          "List",
          "Nav"
        ],
        "slots": {
          "default": {
            "description": "Default content — typically a <nav-ui> for navigation, or a list / tree for the trailing inspector pattern."
          },
          "footer": {
            "description": "Bottom chrome bar (user select, status indicator, etc.)."
          },
          "header": {
            "description": "Top chrome bar (workspace select, breadcrumb, etc.)."
          }
        },
        "states": [
          {
            "description": "Default, expanded.",
            "name": "idle"
          },
          {
            "description": "Sidebar width is at or below the snap threshold; CSS container queries flip child layout to icon-only mode.",
            "attribute": "collapsed",
            "name": "collapsed"
          },
          {
            "description": "Active pointer-drag in progress.",
            "attribute": "resizing",
            "name": "resizing"
          }
        ],
        "status": "stable",
        "synonyms": {
          "collapsed": [
            "minimized",
            "narrow",
            "icon-only"
          ],
          "sidebar": [
            "aside",
            "rail",
            "panel"
          ]
        },
        "tag": "chat-sidebar",
        "tokens": {},
        "traits": [],
        "version": 1
      }
    },
    "ChatStatus": {
      "title": "ChatStatus",
      "description": "Module-tier chat status indicator. CSS-only — no behavior, no JS.\nConveys connection / streaming state via inline content. Typically\nslotted into <chat-header slot=\"status\"> or used inline.\n\nReplaces the legacy <span data-chat-status> shape per ADR-0023.\n",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "component": {
          "const": "ChatStatus"
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [],
        "category": "feedback",
        "composes": [],
        "events": {},
        "examples": [],
        "keywords": [
          "chat-status",
          "status-indicator",
          "connection-status",
          "streaming-indicator"
        ],
        "name": "ChatStatus",
        "related": [
          "ChatShell",
          "ChatHeader",
          "ChatThread"
        ],
        "slots": {
          "default": {
            "description": "Status content — text, icon, dot indicator, etc. Authors set content directly; the host (chat-shell) updates innerText during streaming via legacy [data-chat-status] selector OR via querySelector('chat-status') for the bespoke shape."
          }
        },
        "states": [
          {
            "description": "Default, the only state.",
            "name": "idle"
          }
        ],
        "status": "stable",
        "synonyms": {
          "chat-status": [
            "connection-indicator",
            "streaming-status"
          ]
        },
        "tag": "chat-status",
        "tokens": {},
        "traits": [],
        "version": 1
      }
    },
    "ChatThread": {
      "title": "ChatThread",
      "description": "Module-tier chat message thread container — replaces legacy\n<section data-chat-messages> per ADR-0023. Owns scroll-to-bottom\non new message (with user-scroll-up suspension), [streaming] and\n[empty] reflected attributes, and a stable target for the host's\nmessage rendering pipeline.\n\nSits inside <chat-shell> as the central scroll surface. Authors compose <chat-empty> as an optional first child for the empty state; message children are appended dynamically by the host.\n",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "component": {
          "const": "ChatThread"
        },
        "empty": {
          "description": "Reflected — set when zero message children. Drives the\n<chat-empty> visibility via CSS — no JS toggling needed.\n",
          "type": "boolean",
          "default": true
        },
        "streaming": {
          "description": "Reflected — set by the host while an LLM response is streaming.\nConsumers can style streaming-mode (e.g. cursor blink) via\n:has(chat-thread[streaming]) or attribute selectors.\n",
          "type": "boolean",
          "default": false
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [],
        "category": "container",
        "composes": [],
        "events": {},
        "examples": [],
        "keywords": [
          "chat-thread",
          "message-list",
          "conversation",
          "thread",
          "scroll-surface"
        ],
        "name": "ChatThread",
        "related": [
          "ChatShell",
          "ChatEmpty",
          "ChatComposer",
          "ChatSidebar"
        ],
        "slots": {
          "default": {
            "description": "Default — message children (typically appended dynamically by <chat-shell>'s rendering pipeline) plus an optional first <chat-empty> sibling for the empty state."
          }
        },
        "states": [
          {
            "description": "Default, no streaming.",
            "name": "idle"
          },
          {
            "description": "Host is actively streaming an LLM response.",
            "attribute": "streaming",
            "name": "streaming"
          },
          {
            "description": "Zero message children — empty state visible.",
            "attribute": "empty",
            "name": "empty"
          }
        ],
        "status": "stable",
        "synonyms": {
          "message-list": [
            "messages",
            "message-stream"
          ],
          "tags": [
            "Chat",
            "conversation",
            "chat-log",
            "message-thread"
          ],
          "thread": [
            "conversation",
            "dialogue",
            "chat-log",
            "transcript"
          ]
        },
        "tag": "chat-thread",
        "tokens": {},
        "traits": [],
        "version": 1
      }
    },
    "Check": {
      "title": "Check",
      "description": "Checkbox primitive — the host IS the control (per ADR-0025, no\nnative <input> wrapped underneath). Form-bearing via UIFormElement:\n[name], [value], [checked] (reflect), [indeterminate], [required],\n[disabled]. Wrap in <field-ui label=\"…\" hint=\"…\"> for the canonical\nlabeled stack, or set inline [label] / [hint] props. Distinct from\n<switch-ui> (binary on/off toggle) — use check-ui for opt-in lists\nand form acknowledgements, switch-ui for setting-style toggles.\n",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "required": {
          "description": "Marks as required",
          "type": "boolean",
          "default": false
        },
        "checked": {
          "description": "Whether the checkbox is checked",
          "type": "boolean",
          "default": false
        },
        "component": {
          "const": "Check"
        },
        "disabled": {
          "description": "Disables the checkbox",
          "type": "boolean",
          "default": false
        },
        "hint": {
          "description": "Help text below the label",
          "type": "string",
          "default": ""
        },
        "indeterminate": {
          "description": "Indeterminate state (dash indicator). Cleared on toggle.",
          "type": "boolean",
          "default": false
        },
        "label": {
          "description": "Label text beside the checkbox",
          "type": "string",
          "default": ""
        },
        "name": {
          "description": "Form field name",
          "type": "string",
          "default": ""
        },
        "value": {
          "description": "Form value (submitted as 'on' when checked)",
          "type": "string",
          "default": ""
        }
      },
      "required": [
        "component",
        "label"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [
          {
            "description": "Wrapping a check-ui in field-ui. The widget already self-labels.",
            "right": "<check-ui label=\"I agree to the Terms of Service\"></check-ui>\n",
            "rule": "Use [label] on check-ui directly; do not wrap in field-ui.",
            "wrong": "<field-ui inline label=\"Agree\">\n  <check-ui></check-ui>\n</field-ui>\n"
          }
        ],
        "category": "layout",
        "composes": [],
        "events": {
          "change": {
            "description": "Fired when checked state changes"
          }
        },
        "examples": [
          {
            "description": "Basic Check usage",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"Card\",\n    \"children\": [\n      \"sec\"\n    ]\n  },\n  {\n    \"id\": \"sec\",\n    \"component\": \"Section\",\n    \"children\": [\n      \"comp\"\n    ]\n  },\n  {\n    \"id\": \"comp\",\n    \"component\": \"Check\",\n    \"label\": \"Example Check\"\n  }\n]",
            "name": "basic-check"
          }
        ],
        "keywords": [
          "check"
        ],
        "name": "UICheck",
        "related": [
          "Switch",
          "Radio",
          "Field"
        ],
        "slots": {
          "box": {
            "description": "Visual checkbox indicator"
          },
          "label": {
            "description": "Label text beside the checkbox"
          }
        },
        "states": [
          {
            "description": "Default, ready for interaction.",
            "name": "idle"
          },
          {
            "description": "Non-interactive; dimmed.",
            "attribute": "disabled",
            "name": "disabled"
          }
        ],
        "status": "stable",
        "synonyms": {
          "checkbox": [
            "check",
            "tickbox",
            "boolean-input"
          ]
        },
        "tag": "check-ui",
        "tokens": {
          "--check-box-background": {
            "description": "Unchecked background"
          },
          "--check-box-border-color": {
            "description": "Unchecked border color"
          },
          "--check-box-radius": {
            "description": "Checkbox border radius"
          },
          "--check-box-size": {
            "description": "Checkbox indicator size"
          },
          "--check-checked-background": {
            "description": "Checked/indeterminate background"
          },
          "--check-checked-border-color": {
            "description": "Checked/indeterminate border"
          },
          "--check-checked-foreground": {
            "description": "Checkmark/dash color"
          }
        },
        "traits": [],
        "version": 1
      }
    },
    "Code": {
      "title": "Code",
      "description": "Inline or block code display with optional language label and copy button. Renders preformatted text with monospace font and code-block tokens; syntax highlighting is opt-in via the language attribute. Use for code snippets in documentation, chat, or artifact panes; for editable code use <richtext-ui> with a code variant.",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "required": {
          "description": "Form constraint — submission blocks if the editor is empty",
          "type": "boolean",
          "default": false
        },
        "bare": {
          "description": "Omit the header chrome (label + copy button); for embedded editor surfaces",
          "type": "boolean",
          "default": false
        },
        "component": {
          "const": "Code"
        },
        "disabled": {
          "description": "Disables input and excludes from form submission",
          "type": "boolean",
          "default": false
        },
        "editable": {
          "description": "Editable CodeMirror instance (vs read-only display)",
          "type": "boolean",
          "default": false
        },
        "inline": {
          "description": "Inline code (vs block)",
          "type": "boolean",
          "default": false
        },
        "language": {
          "description": "Language hint for syntax highlighting",
          "type": "string",
          "default": ""
        },
        "lineNumbers": {
          "description": "Show line number gutter alongside the code",
          "type": "boolean",
          "default": false
        },
        "name": {
          "description": "Form-control name — submitted with the enclosing form when `editable` is set",
          "type": "string",
          "default": ""
        },
        "placeholder": {
          "description": "Placeholder text shown when the editor is empty (editable mode only)",
          "type": "string",
          "default": ""
        },
        "readonly": {
          "description": "Blocks input but still submits with the form",
          "type": "boolean",
          "default": false
        },
        "text": {
          "description": "Code text content",
          "type": "string",
          "default": ""
        },
        "textContent": {
          "description": "Code body text. Renderer routes this to the `text` attribute, reactively re-rendered into the <pre><code> block.",
          "$ref": "#/$defs/DynamicString"
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [],
        "category": "display",
        "composes": [],
        "events": {
          "change": {
            "description": "Fired on blur if the buffer changed since focus (editable mode); detail.value is the final buffer.",
            "detail": {
              "value": {
                "description": "Editor contents at blur.",
                "type": "string"
              }
            }
          },
          "input": {
            "description": "Fired on every doc change (editable mode); detail.value is the current buffer.",
            "detail": {
              "value": {
                "description": "Current editor contents.",
                "type": "string"
              }
            }
          },
          "language-load-error": {
            "description": "Fired when CodeMirror's dynamic language-mode or core bundle fails to load.\ndetail.phase is \"core\" (fatal — component falls back to static pre+code) or\n\"language\" (recoverable — editor mounts in plain-text mode).\n",
            "detail": {
              "error": {
                "description": "The underlying load failure.",
                "type": "object"
              },
              "language": {
                "description": "Present when phase is \"language\" — the language slug that failed.",
                "type": "string"
              },
              "phase": {
                "description": "Either \"core\" or \"language\".",
                "type": "string"
              }
            }
          },
          "save": {
            "description": "Fired on Mod+S keybind (editable mode); detail.value is the current buffer. Cancelable — call event.preventDefault() to suppress the host page's save handling.",
            "detail": {
              "value": {
                "description": "Editor contents at the moment of save.",
                "type": "string"
              }
            }
          }
        },
        "examples": [
          {
            "description": "Code display block with syntax highlighting, language label, and a copy-to-clipboard button.",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"Card\",\n    \"children\": [\n      \"hdr\",\n      \"body\"\n    ]\n  },\n  {\n    \"id\": \"hdr\",\n    \"component\": \"Header\",\n    \"slots\": {\n      \"heading\": \"Example\",\n      \"action\": \"copy-btn\"\n    },\n    \"children\": [\n      \"lang-badge\"\n    ]\n  },\n  {\n    \"id\": \"lang-badge\",\n    \"component\": \"Badge\",\n    \"attrs\": {\n      \"variant\": \"default\"\n    },\n    \"content\": \"TypeScript\"\n  },\n  {\n    \"id\": \"copy-btn\",\n    \"component\": \"Button\",\n    \"attrs\": {\n      \"variant\": \"ghost\",\n      \"icon\": \"copy\",\n      \"size\": \"sm\",\n      \"aria-label\": \"Copy code\"\n    }\n  },\n  {\n    \"id\": \"body\",\n    \"component\": \"Section\",\n    \"children\": [\n      \"code\"\n    ]\n  },\n  {\n    \"id\": \"code\",\n    \"component\": \"Code\",\n    \"attrs\": {\n      \"language\": \"typescript\",\n      \"showLineNumbers\": true\n    },\n    \"content\": \"import { render } from '@a2ui/core';\\n\\nconst App = () => {\\n  return render({\\n    component: 'Card',\\n    children: ['Hello, world!']\\n  });\\n};\"\n  }\n]",
            "name": "code-block"
          }
        ],
        "keywords": [
          "code",
          "snippet",
          "syntax",
          "programming",
          "ide",
          "terminal",
          "editor",
          "document",
          "api",
          "developer"
        ],
        "name": "UICode",
        "related": [
          "badge",
          "button"
        ],
        "slots": {
          "default": {
            "description": "Raw text fallback when the text property is not set. Two authoring shapes:\n(a) HTML-entity-escaped text (`&lt;nav-ui&gt;`) — same constraint as `<pre><code>`,\nsince the HTML parser treats unescaped tags as child elements; or\n(b) a `<template>` child whose `innerHTML` carries the literal source —\nescape-free authoring path. Indentation is dedented from the wrapper\ncolumn so the template's inner block reads at column 0. (v0.5.x §329)\n"
          }
        },
        "states": [
          {
            "description": "Default, ready for interaction.",
            "name": "idle"
          },
          {
            "description": "Editor is disabled — blocks input and excludes from form submission.",
            "name": "disabled"
          },
          {
            "description": "Editor blocks input but still submits with the form.",
            "name": "readonly"
          },
          {
            "description": "Editor has a validation error (e.g. `required` and empty). Reflects as `aria-invalid=\"true\"`.",
            "name": "invalid"
          }
        ],
        "status": "stable",
        "synonyms": {
          "api": [
            "api",
            "key",
            "table",
            "code"
          ],
          "code": [
            "code",
            "block",
            "markdown",
            "editor"
          ],
          "developer": [
            "api",
            "key",
            "code",
            "block"
          ],
          "document": [
            "markdown",
            "editor",
            "code"
          ],
          "editor": [
            "markdown",
            "editor",
            "code",
            "block"
          ],
          "ide": [
            "code",
            "block",
            "markdown",
            "editor",
            "split"
          ],
          "programming": [
            "code",
            "block",
            "markdown"
          ],
          "snippet": [
            "code",
            "block"
          ],
          "syntax": [
            "code",
            "block"
          ],
          "terminal": [
            "code",
            "block",
            "command"
          ]
        },
        "tag": "code-ui",
        "tokens": {},
        "traits": [],
        "version": 1
      }
    },
    "Col": {
      "title": "Col",
      "description": "Flex column layout primitive — vertical stack of children with\n[gap] / [align] / [justify] / [grow]. The most common layout\nprimitive in the repo. Use <col-ui> for vertical stacks, <row-ui>\nfor horizontal rows, <stack-ui> for overlay (children stack on top\nof each other in a grid), <grid-ui> for 2D grids. Composes inside\n<section-ui> for in-card layout; do NOT use as a child of\n<header-ui> / <footer-ui> (the chrome scope already lays out\nslots).\n",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "align": {
          "description": "Cross-axis alignment (start/center/end/stretch). Accepts `@bp` notation: align=\"stretch center@sm\" applies stretch below sm, center from sm up.",
          "type": "string",
          "default": "stretch"
        },
        "component": {
          "const": "Col"
        },
        "gap": {
          "description": "Gap between children. Two grammars: a NAMED scale (xs/sm/md/lg/xl) and an integer space-rung (\"0\"…\"10\", \"12\", \"16\", mapped to --a-space-N). The named scale is parametric (half + half·--a-gap-k, = 4/8/12/16/20px at the default k=1); the integer rungs are literal / k-independent. At k=1 the two coincide: xs=1, sm=2, md=3, lg=4, xl=5. Accepts `@bp` notation: gap=\"2 4@md\" = 2 below md, 4 from md upward.",
          "type": "string",
          "default": "md"
        },
        "grow": {
          "description": "Fills remaining space in a flex parent (e.g. inside a Row). CSS-only attribute via :scope[grow] in col.css.",
          "type": "boolean",
          "default": false
        },
        "justify": {
          "description": "Main-axis justify (start/center/end/space-between/space-around). Accepts `@bp` notation: justify=\"start space-between@md\".",
          "type": "string",
          "default": "start"
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [],
        "category": "layout",
        "composes": [],
        "events": {},
        "examples": [
          {
            "description": "Chat interface with message bubbles containing avatar and text pairs, plus an input footer.",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"Card\",\n    \"children\": [\n      \"hdr\",\n      \"sec\",\n      \"ftr\"\n    ]\n  },\n  {\n    \"id\": \"hdr\",\n    \"component\": \"Header\",\n    \"children\": [\n      \"title\"\n    ]\n  },\n  {\n    \"id\": \"title\",\n    \"component\": \"Text\",\n    \"slot\": \"heading\",\n    \"textContent\": \"Chat\"\n  },\n  {\n    \"id\": \"sec\",\n    \"component\": \"Section\",\n    \"children\": [\n      \"messages\"\n    ]\n  },\n  {\n    \"id\": \"messages\",\n    \"component\": \"Column\",\n    \"gap\": \"3\",\n    \"children\": [\n      \"msg1\",\n      \"msg2\",\n      \"msg3\",\n      \"msg4\"\n    ]\n  },\n  {\n    \"id\": \"msg1\",\n    \"component\": \"Row\",\n    \"gap\": \"2\",\n    \"children\": [\n      \"a1\",\n      \"t1\"\n    ]\n  },\n  {\n    \"id\": \"a1\",\n    \"component\": \"Avatar\",\n    \"name\": \"User\",\n    \"size\": \"sm\"\n  },\n  {\n    \"id\": \"t1\",\n    \"component\": \"Text\",\n    \"variant\": \"body\",\n    \"textContent\": \"Hello! Can you help me with something?\"\n  },\n  {\n    \"id\": \"msg2\",\n    \"component\": \"Row\",\n    \"gap\": \"2\",\n    \"children\": [\n      \"a2\",\n      \"t2\"\n    ]\n  },\n  {\n    \"id\": \"a2\",\n    \"component\": \"Avatar\",\n    \"name\": \"Assistant\",\n    \"size\": \"sm\"\n  },\n  {\n    \"id\": \"t2\",\n    \"component\": \"Text\",\n    \"variant\": \"body\",\n    \"textContent\": \"Of course! I'd be happy to help. What do you need?\"\n  },\n  {\n    \"id\": \"msg3\",\n    \"component\": \"Row\",\n    \"gap\": \"2\",\n    \"children\": [\n      \"a3\",\n      \"t3\"\n    ]\n  },\n  {\n    \"id\": \"a3\",\n    \"component\": \"Avatar\",\n    \"name\": \"User\",\n    \"size\": \"sm\"\n  },\n  {\n    \"id\": \"t3\",\n    \"component\": \"Text\",\n    \"variant\": \"body\",\n    \"textContent\": \"I need to build a dashboard layout.\"\n  },\n  {\n    \"id\": \"msg4\",\n    \"component\": \"Row\",\n    \"gap\": \"2\",\n    \"children\": [\n      \"a4\",\n      \"t4\"\n    ]\n  },\n  {\n    \"id\": \"a4\",\n    \"component\": \"Avatar\",\n    \"name\": \"Assistant\",\n    \"size\": \"sm\"\n  },\n  {\n    \"id\": \"t4\",\n    \"component\": \"Text\",\n    \"variant\": \"body\",\n    \"textContent\": \"Great choice! Let me suggest some patterns for that.\"\n  },\n  {\n    \"id\": \"ftr\",\n    \"component\": \"Footer\",\n    \"children\": [\n      \"input-row\"\n    ]\n  },\n  {\n    \"id\": \"input-row\",\n    \"component\": \"Row\",\n    \"gap\": \"2\",\n    \"children\": [\n      \"chat-input\",\n      \"send-btn\"\n    ]\n  },\n  {\n    \"id\": \"chat-input\",\n    \"component\": \"Input\",\n    \"placeholder\": \"Type a message...\"\n  },\n  {\n    \"id\": \"send-btn\",\n    \"component\": \"Button\",\n    \"text\": \"Send\",\n    \"icon\": \"send\",\n    \"variant\": \"primary\"\n  }\n]",
            "name": "chat-interface"
          },
          {
            "description": "Command palette card with search input and a list of command options.",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"Card\",\n    \"children\": [\n      \"hdr\",\n      \"sec\"\n    ]\n  },\n  {\n    \"id\": \"hdr\",\n    \"component\": \"Header\",\n    \"children\": [\n      \"search\"\n    ]\n  },\n  {\n    \"id\": \"search\",\n    \"component\": \"Input\",\n    \"placeholder\": \"Type a command or search...\",\n    \"icon\": \"search\"\n  },\n  {\n    \"id\": \"sec\",\n    \"component\": \"Section\",\n    \"children\": [\n      \"options\"\n    ]\n  },\n  {\n    \"id\": \"options\",\n    \"component\": \"Column\",\n    \"gap\": \"1\",\n    \"children\": [\n      \"opt1\",\n      \"opt2\",\n      \"opt3\",\n      \"opt4\",\n      \"opt5\"\n    ]\n  },\n  {\n    \"id\": \"opt1\",\n    \"component\": \"Row\",\n    \"gap\": \"2\",\n    \"children\": [\n      \"i1\",\n      \"l1\"\n    ]\n  },\n  {\n    \"id\": \"i1\",\n    \"component\": \"Icon\",\n    \"name\": \"file\"\n  },\n  {\n    \"id\": \"l1\",\n    \"component\": \"Text\",\n    \"textContent\": \"Open File\"\n  },\n  {\n    \"id\": \"opt2\",\n    \"component\": \"Row\",\n    \"gap\": \"2\",\n    \"children\": [\n      \"i2\",\n      \"l2\"\n    ]\n  },\n  {\n    \"id\": \"i2\",\n    \"component\": \"Icon\",\n    \"name\": \"gear\"\n  },\n  {\n    \"id\": \"l2\",\n    \"component\": \"Text\",\n    \"textContent\": \"Settings\"\n  },\n  {\n    \"id\": \"opt3\",\n    \"component\": \"Row\",\n    \"gap\": \"2\",\n    \"children\": [\n      \"i3\",\n      \"l3\"\n    ]\n  },\n  {\n    \"id\": \"i3\",\n    \"component\": \"Icon\",\n    \"name\": \"palette\"\n  },\n  {\n    \"id\": \"l3\",\n    \"component\": \"Text\",\n    \"textContent\": \"Change Theme\"\n  },\n  {\n    \"id\": \"opt4\",\n    \"component\": \"Row\",\n    \"gap\": \"2\",\n    \"children\": [\n      \"i4\",\n      \"l4\"\n    ]\n  },\n  {\n    \"id\": \"i4\",\n    \"component\": \"Icon\",\n    \"name\": \"users\"\n  },\n  {\n    \"id\": \"l4\",\n    \"component\": \"Text\",\n    \"textContent\": \"Manage Users\"\n  },\n  {\n    \"id\": \"opt5\",\n    \"component\": \"Row\",\n    \"gap\": \"2\",\n    \"children\": [\n      \"i5\",\n      \"l5\"\n    ]\n  },\n  {\n    \"id\": \"i5\",\n    \"component\": \"Icon\",\n    \"name\": \"sign-out\"\n  },\n  {\n    \"id\": \"l5\",\n    \"component\": \"Text\",\n    \"textContent\": \"Sign Out\"\n  }\n]",
            "name": "command-palette"
          }
        ],
        "keywords": [
          "column",
          "col"
        ],
        "name": "UICol",
        "related": [
          "avatar",
          "input",
          "button",
          "empty-state",
          "skeleton"
        ],
        "slots": {
          "default": {
            "description": "Default slot — primary child content."
          }
        },
        "states": [
          {
            "description": "Default, ready for interaction.",
            "name": "idle"
          }
        ],
        "status": "stable",
        "synonyms": {
          "column": [
            "col",
            "vstack",
            "vertical-stack",
            "vbox"
          ]
        },
        "tag": "col-ui",
        "tokens": {},
        "traits": [],
        "version": 1
      }
    },
    "ColorInput": {
      "title": "ColorInput",
      "description": "Compact form-bearing color input — opens a popover-anchored\n`<color-picker-ui>` from an inline swatch button. §302 (v0.5.12,\nFEEDBACK-29 re-bucket from v0.6.0). Canonicalizes the USAGE.md §221f\nOption B recipe (popover + button + color-picker) into a single\nform-associated tag for inline form contexts (settings drawer \"source\ncolor\" field, swatch-row inline-edit, etc.).",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "baseHue": {
          "description": "Reference hue (degrees) for the hueDriftMax constraint, forwarded to inner picker. Default NaN — picker falls back to its hue at first commit.",
          "type": "number",
          "default": "NaN"
        },
        "component": {
          "const": "ColorInput"
        },
        "disabled": {
          "description": "Disables the trigger button + suppresses popover.",
          "type": "boolean",
          "default": false
        },
        "format": {
          "description": "Output format for the value property + event detail. Hex (`#rrggbb`) or OKLCH (`oklch(L C H)`).",
          "type": "string",
          "enum": [
            "hex",
            "oklch"
          ],
          "default": "hex"
        },
        "hueDriftMax": {
          "description": "Generation constraint forwarded to inner picker — maximum allowed signed-shortest-path hue deviation (degrees) from baseHue. Default NaN (no constraint).",
          "type": "number",
          "default": "NaN"
        },
        "maxChroma": {
          "description": "Generation constraint forwarded to the inner `<color-picker-ui>` (v0.5.13\n§-TBD, FB-33 §1). Clamp the OKLCH chroma channel to at most this value.\nDefault Infinity (no constraint).\n",
          "type": "number",
          "default": "Infinity"
        },
        "maxL": {
          "description": "Generation constraint forwarded to inner picker — clamp OKLCH lightness to at most this value (0..1). Default 1.",
          "type": "number",
          "default": 1
        },
        "minL": {
          "description": "Generation constraint forwarded to inner picker — clamp OKLCH lightness to at least this value (0..1). Default 0.",
          "type": "number",
          "default": 0
        },
        "name": {
          "description": "Form field name.",
          "type": "string",
          "default": ""
        },
        "open": {
          "description": "Reflects the popover's open state. Set programmatically to open/close the picker without a click.",
          "type": "boolean",
          "default": false
        },
        "placement": {
          "description": "Popover placement relative to the trigger. Default `bottom` centers the color-picker panel under the swatch button (ADR-0034 Rule 2 — panel wider than trigger).",
          "type": "string",
          "enum": [
            "top",
            "bottom",
            "left",
            "right",
            "top-start",
            "top-end",
            "bottom-start",
            "bottom-end"
          ],
          "default": "bottom"
        },
        "value": {
          "description": "Current color as a string in the active [format].",
          "type": "string",
          "default": "#3b82f6"
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [],
        "category": "input",
        "composes": [
          "button-ui",
          "popover-ui",
          "color-picker-ui"
        ],
        "events": {
          "change": {
            "description": "Fired when the color is committed (pointerup / Enter / picker close). Bubbles from inner picker.",
            "detail": {
              "c": {
                "description": "Parsed OKLCH chroma scalar.",
                "type": "number"
              },
              "h": {
                "description": "Parsed OKLCH hue scalar (degrees, NaN ok for achromatic).",
                "type": "number"
              },
              "hex": {
                "description": "Hex form (`#rrggbb`).",
                "type": "string"
              },
              "l": {
                "description": "Parsed OKLCH lightness scalar (0..1). v0.5.13 §-TBD (FB-33 §1-adjacent).",
                "type": "number"
              },
              "oklch": {
                "description": "OKLCH string (`oklch(L C H)`).",
                "type": "string"
              },
              "value": {
                "description": "Color in the active [format] (hex or oklch).",
                "type": "string"
              }
            }
          },
          "input": {
            "description": "Fired during continuous drag of the inner picker. Bubbles from inner picker.",
            "detail": {
              "c": {
                "type": "number"
              },
              "h": {
                "type": "number"
              },
              "hex": {
                "type": "string"
              },
              "l": {
                "type": "number"
              },
              "oklch": {
                "type": "string"
              },
              "value": {
                "description": "Color in the active [format].",
                "type": "string"
              }
            }
          }
        },
        "examples": [
          {
            "description": "Inline compact color input — popover-anchored picker on click.",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"ColorInput\",\n    \"name\": \"brand\",\n    \"value\": \"#3b82f6\"\n  }\n]",
            "name": "color-input-basic"
          },
          {
            "description": "Compact picker exposing OKLCH value form.",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"ColorInput\",\n    \"name\": \"accent\",\n    \"format\": \"oklch\",\n    \"value\": \"oklch(0.7 0.15 220)\"\n  }\n]",
            "name": "color-input-oklch"
          }
        ],
        "keywords": [
          "color-input",
          "color",
          "input",
          "picker",
          "swatch",
          "inline",
          "compact"
        ],
        "name": "UIColorInput",
        "related": [
          "color-picker",
          "popover",
          "button",
          "swatch"
        ],
        "slots": {},
        "states": [
          {
            "description": "Default, ready for interaction.",
            "name": "idle"
          },
          {
            "description": "Popover is open; picker visible.",
            "attribute": "open",
            "name": "open"
          },
          {
            "description": "Non-interactive; dimmed.",
            "attribute": "disabled",
            "name": "disabled"
          }
        ],
        "status": "stable",
        "synonyms": {
          "color-field": [
            "color-input"
          ],
          "inline-color-picker": [
            "color-input"
          ]
        },
        "tag": "color-input-ui",
        "tokens": {
          "--color-input-swatch-size": {
            "description": "Diameter (em) of the inline swatch circle inside the trigger button. Default 1em."
          }
        },
        "traits": [],
        "version": 1
      }
    },
    "ColorPicker": {
      "title": "ColorPicker",
      "description": "OKLCH-native color picker with 2D area and H/C/L sliders. Form-associated input emitting OKLCH color strings; canonical color authoring surface in the AdiaUI token system. Use for color input in design tools or theming UIs; for simple color swatches use <swatch-ui> or <color-input-ui> instead.",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "baseHue": {
          "description": "Reference hue (degrees) for the [hue-drift-max] constraint. Default\nNaN — falls back to the picker's hue at first commit so the consumer\ncan pre-seed the picker and constrain drift from that initial value.\n",
          "type": "number",
          "default": "NaN"
        },
        "component": {
          "const": "ColorPicker"
        },
        "disabled": {
          "description": "Disables all interaction",
          "type": "boolean",
          "default": false
        },
        "format": {
          "description": "Output format for the value property",
          "type": "string",
          "enum": [
            "hex",
            "oklch"
          ],
          "default": "hex"
        },
        "hueDriftMax": {
          "description": "Generation constraint — maximum allowed signed-shortest-path hue\ndeviation (degrees) from [base-hue] (or the first-committed hue\nif [base-hue] is unset). Default NaN (no constraint). Wrap-aware\nso a drift of 350 degrees resolves as -10.\n",
          "type": "number",
          "default": "NaN"
        },
        "maxChroma": {
          "description": "Generation constraint (v0.4.9 §99h, FEEDBACK-02 #7) — clamp the\nOKLCH chroma channel to at most this value before commit. Out-of-\nbound mutations round-trip to the nearest in-bound equivalent +\nfire `constraint-clamp`. Default Infinity (no constraint).\n",
          "type": "number",
          "default": "Infinity"
        },
        "maxL": {
          "description": "Generation constraint — clamp OKLCH lightness to at most this value (0..1). Default 1 (no constraint).",
          "type": "number",
          "default": 1
        },
        "minL": {
          "description": "Generation constraint — clamp OKLCH lightness to at least this value (0..1). Default 0 (no constraint).",
          "type": "number",
          "default": 0
        },
        "name": {
          "description": "Form field name",
          "type": "string",
          "default": ""
        },
        "value": {
          "description": "Current color as hex string",
          "type": "string",
          "default": "#3b82f6"
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [],
        "category": "input",
        "composes": [
          "slider-ui"
        ],
        "events": {
          "change": {
            "description": "Fired on every color change"
          },
          "constraint-clamp": {
            "description": "Fired immediately before `change` / `input` when one or more\nconsumer-declared constraints (max-chroma / max-l / min-l /\nhue-drift-max) clamped a channel away from the user-requested\nvalue. detail.clamps is an array of axis-specific clamp records.\n",
            "detail": {
              "clamps": {
                "description": "Array of `{ axis, requested, clamped, reason }` objects. axis is\none of \"l\" / \"c\" / \"h\". reason names the triggering constraint\nprop. Empty arrays are never emitted.\n",
                "type": "array"
              }
            }
          },
          "input": {
            "description": "Fired during continuous interaction (drag)"
          }
        },
        "examples": [
          {
            "description": "Color picker card with a color picker component for selecting colors with swatches.",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"Card\",\n    \"children\": [\n      \"sec\"\n    ]\n  },\n  {\n    \"id\": \"sec\",\n    \"component\": \"Section\",\n    \"children\": [\n      \"cp\"\n    ]\n  },\n  {\n    \"id\": \"cp\",\n    \"component\": \"ColorPicker\",\n    \"value\": \"#6366f1\"\n  }\n]",
            "name": "color-picker-demo"
          },
          {
            "description": "Color picker with swatch selection in a card.",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"Card\",\n    \"children\": [\n      \"sec\"\n    ]\n  },\n  {\n    \"id\": \"sec\",\n    \"component\": \"Section\",\n    \"children\": [\n      \"cp\"\n    ]\n  },\n  {\n    \"id\": \"cp\",\n    \"component\": \"ColorPicker\",\n    \"value\": \"#3b82f6\"\n  }\n]",
            "name": "color-picker-panel"
          }
        ],
        "keywords": [
          "colorpicker",
          "color-picker",
          "color",
          "picker"
        ],
        "name": "UIColorPicker",
        "related": [
          "grid",
          "button"
        ],
        "slots": {},
        "states": [
          {
            "description": "Default, ready for interaction.",
            "name": "idle"
          },
          {
            "description": "Non-interactive; dimmed.",
            "attribute": "disabled",
            "name": "disabled"
          }
        ],
        "status": "stable",
        "synonyms": {
          "color-picker": [
            "color-canvas",
            "color-surface",
            "swatch-picker"
          ]
        },
        "tag": "color-picker-ui",
        "tokens": {},
        "traits": [],
        "version": 1
      }
    },
    "Combobox": {
      "title": "Combobox",
      "description": "Typeahead-filterable single-select primitive — the constrained-choice\ncombobox per WAI-APG \"Combobox With List Autocomplete (manual\nselection)\". The committed value MUST come from the options list\nunless `[free-text]` is set. Distinct from `<select-ui searchable>`\n(button-first dropdown) and `<autocomplete-input-ui>` (free-form).\nForm-bearing via UIFormElement: `[name]`, `[value]`, `[required]`,\n`[disabled]`, fires `change`. Options via native `<option>` /\n`<optgroup>` children OR programmatic `.options` array.\n",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "required": {
          "description": "Marks the field as required for form validation",
          "type": "boolean",
          "default": false
        },
        "clearable": {
          "description": "Renders an `x` clear button when value is set",
          "type": "boolean",
          "default": false
        },
        "component": {
          "const": "Combobox"
        },
        "creatable": {
          "description": "Implies `[free-text]`; on Enter with unmatched typed text fires a\n`create` event with detail.value so the consumer can run a\nbackend create-then-refresh-options flow.",
          "type": "boolean",
          "default": false
        },
        "disabled": {
          "description": "Disables interaction and dims the control",
          "type": "boolean",
          "default": false
        },
        "error": {
          "description": "Validation error message",
          "type": "string",
          "default": ""
        },
        "filter-mode": {
          "description": "Client-side filter algorithm.",
          "type": "string",
          "enum": [
            "substring",
            "prefix",
            "fuzzy"
          ],
          "default": "substring"
        },
        "free-text": {
          "description": "Allow typed text not in the options list. Blurs the distinction\nwith <autocomplete-input-ui>; prefer the dedicated primitive\nunless the value model truly needs both modes (tag-with-suggestions,\nemail-with-recent-recipients).",
          "type": "boolean",
          "default": false
        },
        "highlight-match": {
          "description": "Wraps the matched substring in `<mark>` inside option labels",
          "type": "boolean",
          "default": true
        },
        "hint": {
          "description": "Caption text below the field; wires `aria-describedby` on the host\nso screen readers announce it as a description.",
          "type": "string",
          "default": ""
        },
        "label": {
          "description": "Inline label rendered above the field. Wrap with <field-ui> for\nproper `<label for>` association in form-row compositions.",
          "type": "string",
          "default": ""
        },
        "loading": {
          "description": "Shows a loading spinner inside the popover; consumer drives async fetch",
          "type": "boolean",
          "default": false
        },
        "max-options": {
          "description": "Cap on rendered options. Overflow shows a \"scroll for more\" hint",
          "type": "number",
          "default": 100
        },
        "max-visible-items": {
          "description": "How many option rows are visible before the listbox scrolls — the menu height hugs N rows instead of growing to the 18rem fallback. Distinct from max-options (the render cap). 0 disables.",
          "type": "number",
          "default": 10
        },
        "name": {
          "description": "Form control name for form data submission",
          "type": "string",
          "default": ""
        },
        "open": {
          "description": "Reflects popover open / closed state",
          "type": "boolean",
          "default": false
        },
        "options": {
          "description": "Programmatic option list. Array of {value, label, disabled?, group?} or grouped {label, options:[…]}. Alternative to declarative <option> / <optgroup> children.",
          "$ref": "#/$defs/DynamicStringList"
        },
        "placeholder": {
          "description": "Placeholder text in the input when value is empty",
          "type": "string",
          "default": "Select..."
        },
        "readonly": {
          "description": "Prevents selection changes while keeping the field focusable + popover-open allowed",
          "type": "boolean",
          "default": false
        },
        "size": {
          "description": "Sizing scale via universal `[size]` attribute system. Matches Input + Select sizing tokens so a Combobox rendered alongside either feels coherent in a form row.",
          "type": "string",
          "enum": [
            "sm",
            "md",
            "lg"
          ],
          "default": "md"
        },
        "value": {
          "description": "Currently selected option value. Must be a member of `options[].value` unless `[free-text]` is set. With declarative <option> children, a child carrying the native `selected` attribute sets the initial value when this attribute is absent.",
          "type": "string",
          "default": ""
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [
          {
            "fix": "{\"component\": \"Combobox\", \"value\": \"us\", \"options\": [{\"value\": \"us\", \"label\": \"United States\"}]}\n",
            "why": "`value` is \"xx\" but only \"us\" is in options. With free-text:false (default), this is an invalid\nmid-state — set value: \"us\" or add an option with value: \"xx\".\n",
            "wrong": "{\"component\": \"Combobox\", \"value\": \"xx\", \"options\": [{\"value\": \"us\", \"label\": \"United States\"}]}\n"
          },
          {
            "fix": "{\"component\": \"SegmentedControl\", \"options\": [{\"value\": \"a\", \"label\": \"A\"}, {\"value\": \"b\", \"label\": \"B\"}]}\n",
            "why": "Only 2 options. Combobox is overkill — use SegmentedControl or Radio.\n",
            "wrong": "{\"component\": \"Combobox\", \"options\": [{\"value\": \"a\", \"label\": \"A\"}, {\"value\": \"b\", \"label\": \"B\"}]}\n"
          },
          {
            "fix": "{\"component\": \"MultiSelect\", \"options\": [...]}\n",
            "why": "Combobox is single-select. Multi-select goes through MultiSelect.\n",
            "wrong": "{\"component\": \"Combobox\", \"multiple\": true, \"options\": [...]}\n"
          }
        ],
        "category": "input",
        "composes": [
          "icon-ui"
        ],
        "events": {
          "change": {
            "description": "Fired when value is committed — option clicked, Enter on active\noption, or programmatic `.value =`. Detail.option resolves to the\nmatching `{label,value,...}` or null in free-text/cleared paths.",
            "detail": {
              "option": {
                "description": "Resolved option object or null when free-text / cleared.",
                "type": "object"
              },
              "source": {
                "description": "One of `click` / `keyboard` / `programmatic`.",
                "type": "string"
              },
              "value": {
                "description": "Committed value.",
                "type": "string"
              }
            }
          },
          "close": {
            "description": "Popover closed.",
            "detail": {
              "reason": {
                "description": "One of `escape` / `outside` / `select` / `blur`.",
                "type": "string"
              }
            }
          },
          "create": {
            "description": "Fired when `[creatable]` is set and the user presses Enter on\ntyped text that doesn't match any option. Consumer wires this to\na backend create flow and then refreshes `.options`.",
            "detail": {
              "value": {
                "description": "The typed text the user is trying to create.",
                "type": "string"
              }
            }
          },
          "input": {
            "description": "Fired on each keystroke (filter typing); not a commit. Detail carries the typed query.",
            "detail": {
              "query": {
                "description": "Lowercased filter query.",
                "type": "string"
              },
              "value": {
                "description": "Current input text (the user's typed query).",
                "type": "string"
              }
            }
          },
          "invalid": {
            "description": "Fired when `[free-text]` is false and the user presses Enter on\ntyped text that doesn't match any option. The value is NOT\ncommitted; the input is restored to the last committed value.",
            "detail": {
              "query": {
                "description": "The unmatched typed text.",
                "type": "string"
              }
            }
          },
          "open": {
            "description": "Popover opened.",
            "detail": {
              "trigger": {
                "description": "One of `click` / `keyboard` / `typing`.",
                "type": "string"
              }
            }
          }
        },
        "examples": [
          {
            "description": "Country picker — canonical declarative <option> children inside a <field-ui>.",
            "a2ui": "[\n  {\"id\": \"root\", \"component\": \"Card\", \"children\": [\"sec\"]},\n  {\"id\": \"sec\", \"component\": \"Section\", \"children\": [\"country\"]},\n  {\n    \"id\": \"country\",\n    \"component\": \"Combobox\",\n    \"name\": \"country\",\n    \"label\": \"Country\",\n    \"placeholder\": \"Select country…\",\n    \"options\": [\n      {\"value\": \"us\", \"label\": \"United States\"},\n      {\"value\": \"gb\", \"label\": \"United Kingdom\"},\n      {\"value\": \"de\", \"label\": \"Germany\"},\n      {\"value\": \"fr\", \"label\": \"France\"},\n      {\"value\": \"es\", \"label\": \"Spain\"}\n    ],\n    \"value\": \"us\"\n  }\n]",
            "name": "country-picker"
          },
          {
            "description": "Tag picker with create-new affordance — fires `create` event on unmatched Enter.",
            "a2ui": "[\n  {\"id\": \"root\", \"component\": \"Card\", \"children\": [\"sec\"]},\n  {\"id\": \"sec\", \"component\": \"Section\", \"children\": [\"tag\"]},\n  {\n    \"id\": \"tag\",\n    \"component\": \"Combobox\",\n    \"name\": \"tag\",\n    \"label\": \"Tag\",\n    \"creatable\": true,\n    \"placeholder\": \"Pick or create a tag…\",\n    \"options\": [\n      {\"value\": \"bug\", \"label\": \"bug\"},\n      {\"value\": \"feature\", \"label\": \"feature\"},\n      {\"value\": \"chore\", \"label\": \"chore\"}\n    ]\n  }\n]",
            "name": "creatable-tag-picker"
          }
        ],
        "keywords": [
          "combobox",
          "autocomplete",
          "typeahead",
          "select",
          "filter",
          "picker",
          "country-picker",
          "timezone-picker",
          "member-picker"
        ],
        "name": "UICombobox",
        "related": [
          "select",
          "search",
          "input",
          "field"
        ],
        "slots": {
          "default": {
            "description": "Native <option> / <optgroup> children for declarative authoring"
          },
          "empty": {
            "description": "Custom no-matches content (defaults to \"No matches\")"
          },
          "footer": {
            "description": "Footer area inside the popover (e.g. \"Press Enter to create…\" affordance)"
          },
          "loading": {
            "description": "Custom loading content (defaults to a spinner)"
          },
          "prefix": {
            "description": "Leading icon / element inside the input chrome"
          },
          "suffix": {
            "description": "Trailing icon / element (defaults to `caret-down`)"
          }
        },
        "states": [
          {
            "description": "Closed; not focused.",
            "name": "idle"
          },
          {
            "description": "Input focused; popover closed.",
            "attribute": ":focus-within",
            "name": "focused"
          },
          {
            "description": "Popover visible; filtered options listed.",
            "attribute": "open",
            "name": "open"
          },
          {
            "description": "Spinner shown; options stale (consumer-driven async fetch).",
            "attribute": "loading",
            "name": "loading"
          },
          {
            "description": "Non-interactive; dimmed.",
            "attribute": "disabled",
            "name": "disabled"
          },
          {
            "description": "Focusable + popover-open allowed; commits blocked.",
            "attribute": "readonly",
            "name": "readonly"
          }
        ],
        "status": "stable",
        "synonyms": {
          "autocomplete": [
            "combobox",
            "typeahead",
            "suggest"
          ],
          "combobox": [
            "autocomplete",
            "typeahead",
            "filter",
            "picker"
          ],
          "picker": [
            "combobox",
            "select",
            "dropdown"
          ],
          "typeahead": [
            "combobox",
            "autocomplete",
            "search"
          ]
        },
        "tag": "combobox-ui",
        "tokens": {
          "--combobox-bg": {
            "description": "Input background color"
          },
          "--combobox-fg": {
            "description": "Input text color"
          },
          "--combobox-match-bg": {
            "description": "Background for `<mark>` spans that highlight matched substrings"
          },
          "--combobox-option-bg-active": {
            "description": "Background for the currently active (arrow-navigated) option"
          },
          "--combobox-option-bg-selected": {
            "description": "Background for the currently committed option"
          },
          "--combobox-option-fg-active": {
            "description": "Foreground for the currently active option"
          },
          "--combobox-popover-bg": {
            "description": "Popover background color"
          },
          "--combobox-popover-border": {
            "description": "Popover border color"
          },
          "--combobox-popover-radius": {
            "description": "Popover border radius"
          },
          "--combobox-popover-shadow": {
            "description": "Popover elevation shadow"
          },
          "--combobox-radius": {
            "description": "Input border radius"
          }
        },
        "traits": [],
        "version": 1
      }
    },
    "Command": {
      "title": "Command",
      "description": "Searchable command palette primitive — combobox-style search input\nplus a scrollable list of <option value> items grouped by\n<optgroup label>. Content-only; does NOT own the dialog or the\nCmd+K shortcut. For canonical Cmd+K palettes wrap in <admin-command>\nat the shell tier, which provides the native <dialog> + focus\nmanagement + cross-platform Cmd+K listener. Distinct from <menu-ui>\n(small popover action menu, not searchable) and <modal-ui> (generic\ncentered dialog).\n",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "component": {
          "const": "Command"
        },
        "open": {
          "description": "Whether the command palette is visible",
          "type": "boolean",
          "default": false
        },
        "placeholder": {
          "description": "Placeholder text for the search input",
          "type": "string",
          "default": "Type a command..."
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [],
        "category": "container",
        "composes": [],
        "events": {
          "dismiss": {
            "description": "Fired when Escape is pressed"
          },
          "select": {
            "description": "Fired when an item is selected. detail: { value, label, category }. `category` is the parent `<optgroup label=\"…\">` label, or empty string when the item is a direct child of `<command-ui>` with no group.\n",
            "detail": {
              "category": {
                "description": "Parent optgroup label (empty string when item has no group).",
                "type": "string"
              },
              "label": {
                "description": "Item label text.",
                "type": "string"
              },
              "value": {
                "description": "Item value attribute.",
                "type": "string"
              }
            }
          }
        },
        "examples": [
          {
            "description": "Basic Command usage",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"Card\",\n    \"children\": [\n      \"sec\"\n    ]\n  },\n  {\n    \"id\": \"sec\",\n    \"component\": \"Section\",\n    \"children\": [\n      \"comp\"\n    ]\n  },\n  {\n    \"id\": \"comp\",\n    \"component\": \"Command\",\n    \"placeholder\": \"Enter command...\"\n  }\n]",
            "name": "basic-command"
          }
        ],
        "keywords": [
          "command",
          "assistant",
          "copilot",
          "ai",
          "prompt",
          "console",
          "menu",
          "terminal",
          "search",
          "find",
          "lookup",
          "autocomplete",
          "typeahead",
          "spotlight",
          "omnibar",
          "combobox",
          "palette",
          "shortcut",
          "hotkey",
          "keyboard",
          "keybinding"
        ],
        "name": "UICommand",
        "related": [
          "AdminCommand",
          "Menu",
          "Modal",
          "Search"
        ],
        "slots": {
          "empty": {
            "description": "Empty state shown when no items match"
          },
          "footer": {
            "description": "Keyboard hint bar"
          },
          "list": {
            "description": "Container for command items and groups"
          }
        },
        "states": [
          {
            "description": "Default, ready for interaction.",
            "name": "idle"
          }
        ],
        "status": "stable",
        "synonyms": {
          "ai": [
            "chat",
            "streaming",
            "response",
            "command"
          ],
          "assistant": [
            "chat",
            "streaming",
            "response",
            "command"
          ],
          "autocomplete": [
            "search",
            "command",
            "palette",
            "tag"
          ],
          "combobox": [
            "search",
            "command",
            "select"
          ],
          "command": [
            "command",
            "palette",
            "kbd",
            "shortcut"
          ],
          "console": [
            "dashboard",
            "table",
            "data",
            "sidebar",
            "command"
          ],
          "copilot": [
            "chat",
            "streaming",
            "response",
            "command"
          ],
          "find": [
            "search",
            "filter",
            "command"
          ],
          "hotkey": [
            "kbd",
            "shortcut",
            "command"
          ],
          "keybinding": [
            "kbd",
            "shortcut",
            "command"
          ],
          "keyboard": [
            "kbd",
            "shortcut",
            "command"
          ],
          "lookup": [
            "search",
            "filter",
            "command"
          ],
          "menu": [
            "nav",
            "sidebar",
            "popover",
            "menu",
            "command"
          ],
          "omnibar": [
            "command",
            "palette",
            "search"
          ],
          "palette": [
            "color",
            "picker",
            "command",
            "palette"
          ],
          "prompt": [
            "chat",
            "streaming",
            "command",
            "palette"
          ],
          "search": [
            "search",
            "filter",
            "command",
            "palette"
          ],
          "shortcut": [
            "kbd",
            "shortcut",
            "command"
          ],
          "spotlight": [
            "command",
            "palette",
            "search"
          ],
          "tags": [
            "CommandPalette"
          ],
          "terminal": [
            "code",
            "block",
            "command"
          ],
          "typeahead": [
            "search",
            "command",
            "palette"
          ]
        },
        "tag": "command-ui",
        "tokens": {},
        "traits": [],
        "version": 1
      }
    },
    "ConfirmDialog": {
      "title": "ConfirmDialog",
      "description": "Non-destructive yes/no confirmation dialog — a thin composite over\n<modal-ui> that pre-stamps the canonical confirm shape: header (title\n+ optional icon), body (description + optional rich slot), and\nfooter (cancel + confirm buttons). Wires Cancel-default focus,\nconfirm / cancel / close events, and the [loading] in-flight state.\n\nUse confirm-dialog-ui for benign questions: \"Save changes?\", \"Switch\ntheme?\", \"Apply preset?\". For irreversible destructive operations\n(delete account, drop database, deploy to prod) use <alert-dialog-ui>\ninstead — it carries role=\"alertdialog\", danger chrome, and the\noptional typed-name speed-bump.\n\nComposed primitive: <modal-ui> owns the native <dialog>, focus trap,\nbackdrop, and Escape-dismiss. confirm-dialog-ui decorates; it does\nnot reimplement.\n\nSpec: docs/specs/implementation-ready/SPEC-049-confirm-dialog-yes-no.md.\n",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "title": {
          "description": "Dialog title; rendered in the modal header via <modal-ui>[text]\nand announced through aria-labelledby on the inner <dialog>.\n",
          "type": "string",
          "default": ""
        },
        "description": {
          "description": "Body description; rendered as a paragraph above any default-slot\ncontent. Wired as the aria-describedby target.\n",
          "type": "string",
          "default": ""
        },
        "cancel-text": {
          "description": "Cancel button label. Defaults to \"Cancel\".",
          "type": "string",
          "default": "Cancel"
        },
        "component": {
          "const": "ConfirmDialog"
        },
        "confirm-text": {
          "description": "Primary action button label. Defaults to \"Confirm\".",
          "type": "string",
          "default": "Confirm"
        },
        "confirm-variant": {
          "description": "Tone of the confirm button. \"primary\" (default) for the typical\naffirmative-action case; \"ghost\" when both choices are roughly\nbalanced and a tonal primary would over-weight the affirmative.\n",
          "type": "string",
          "enum": [
            "primary",
            "ghost"
          ],
          "default": "primary"
        },
        "icon": {
          "description": "Optional Phosphor icon glyph stamped in the header. Opt-in —\nconsumer supplies the name (e.g. \"info\", \"question\"). When\nempty, no icon disc renders.\n",
          "type": "string",
          "default": ""
        },
        "loading": {
          "description": "In-flight state. When set, both buttons disable and the confirm\nbutton shows a spinner — the consumer toggles [loading] off and\ncloses via [open]=false when the underlying action resolves.\n",
          "type": "boolean",
          "default": false
        },
        "open": {
          "description": "Mirrors <modal-ui>[open]. Setting to true opens the dialog with\nentry animation; setting to false animates close.\n",
          "type": "boolean",
          "default": false
        },
        "size": {
          "description": "Forwarded to <modal-ui>[size]. sm = ~24rem, md = ~32rem,\nlg = ~48rem. Confirm dialogs default to sm.\n",
          "type": "string",
          "enum": [
            "sm",
            "md",
            "lg"
          ],
          "default": "sm"
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [
          {
            "description": "Re-deriving the confirm shape from a raw <modal-ui> instead of using ConfirmDialog. The header/body/footer triplet, the Cancel-default focus, and the confirm/cancel event wiring all need to be re-authored, and the WAI-APG contract drifts per consumer.",
            "right": "<confirm-dialog-ui open\n  title=\"Save changes?\"\n  description=\"Save changes before closing?\"\n  confirm-text=\"Save\"\n  cancel-text=\"Discard\">\n</confirm-dialog-ui>\n",
            "rule": "Reach for ConfirmDialog (not raw Modal) for non-destructive yes/no prompts. The composite owns the contract.",
            "wrong": "<modal-ui open size=\"sm\" text=\"Save?\">\n  <p>Save changes before closing?</p>\n  <footer>\n    <button-ui variant=\"ghost\" text=\"Discard\"></button-ui>\n    <button-ui variant=\"primary\" text=\"Save\"></button-ui>\n  </footer>\n</modal-ui>\n"
          },
          {
            "description": "Using ConfirmDialog for destructive irreversible operations. The primary-toned confirm button reads as benign and primes the user to click through; the WAI-APG `alertdialog` role + danger chrome live in AlertDialog for that reason.",
            "right": "<alert-dialog-ui open\n  title=\"Delete project?\"\n  description=\"This is permanent.\"\n  confirm-text=\"Delete\">\n</alert-dialog-ui>\n",
            "rule": "Destructive intent → AlertDialog. Non-destructive intent → ConfirmDialog. The tag name carries the semantic; do not cross the streams.",
            "wrong": "<confirm-dialog-ui open\n  title=\"Delete project?\"\n  description=\"This is permanent.\"\n  confirm-text=\"Delete\">\n</confirm-dialog-ui>\n"
          }
        ],
        "category": "feedback",
        "composes": [
          "modal-ui",
          "button-ui",
          "icon-ui",
          "text-ui"
        ],
        "events": {
          "cancel": {
            "description": "Fired when the user activates the cancel button, presses Escape,\nor clicks the backdrop. Bubbles.\n",
            "detail": {}
          },
          "close": {
            "description": "Re-emitted from the underlying <modal-ui> when the dialog\nfinishes closing via any path. Bubbles.\n",
            "detail": {}
          },
          "confirm": {
            "description": "Fired when the user activates the confirm button. Bubbles.\nConsumer wires the actual action handler off this event.\n",
            "detail": {}
          }
        },
        "examples": [],
        "keywords": [
          "confirm",
          "confirm-dialog",
          "dialog",
          "confirmation",
          "yes-no",
          "ok-cancel",
          "save-confirm",
          "prompt",
          "dialog-modal"
        ],
        "name": "ConfirmDialog",
        "related": [
          "Modal",
          "AlertDialog",
          "Button",
          "Icon",
          "Text"
        ],
        "slots": {
          "description": {
            "description": "Override the stamped description line below the heading. Author-fills with richer markup when the [description] attribute isn't enough."
          },
          "default": {
            "description": "Optional rich content rendered above the description — supplementary\nlists, hints, or markup the [description] string can't carry.\n"
          },
          "body": {
            "description": "Dialog body region (between header and footer). For rich content — paragraphs, lists, embedded form fields. Distinct from [slot=\"default\"] which sits above [description] in the header region."
          },
          "footer": {
            "description": "Wholesale override of the stamped footer (Cancel / Confirm action cluster). Use only for full custom-footer markup; otherwise the host's [cancel-text] / [confirm-text] / [confirm-variant] attrs drive the default footer rendering."
          },
          "header": {
            "description": "Wholesale override of the stamped header (icon + heading + description cluster). Use only when full custom-header markup is needed; otherwise prefer the granular icon/heading/description slot overrides."
          },
          "heading": {
            "description": "Override the stamped heading. Author-fillable when richer markup than the plain [text] string is needed (inline links, code spans, etc.)."
          },
          "icon": {
            "description": "Override the [icon] glyph with a custom node (e.g. a colored\n<icon-ui>, an image, or arbitrary markup). Mutually exclusive\nwith [icon]; if a slot child is present, the [icon] attribute\nis ignored.\n"
          }
        },
        "states": [
          {
            "description": "Default — closed, no <dialog> in the top layer.",
            "name": "idle"
          },
          {
            "description": "Visible in the top layer; focus trapped; Cancel focused by default.",
            "attribute": "open",
            "name": "open"
          },
          {
            "description": "Both buttons disabled; confirm shows spinner.",
            "attribute": "loading",
            "name": "loading"
          }
        ],
        "status": "stable",
        "synonyms": {
          "cancel": [
            "dismiss",
            "back",
            "no"
          ],
          "confirm": [
            "confirmation",
            "prompt",
            "ok",
            "yes"
          ],
          "dialog": [
            "modal",
            "popup"
          ]
        },
        "tag": "confirm-dialog-ui",
        "tokens": {
          "--confirm-dialog-confirm-bg": {
            "description": "Confirm-button background under [confirm-variant=\"primary\"].\nDefaults to var(--a-accent-bg). When [confirm-variant=\"ghost\"]\nthe button uses transparent background regardless of this token.\n"
          },
          "--confirm-dialog-icon-bg": {
            "description": "Optional header-icon disc background. Defaults to var(--a-bg-muted)."
          },
          "--confirm-dialog-icon-fg": {
            "description": "Optional header-icon glyph color. Defaults to var(--a-fg)."
          }
        },
        "traits": [],
        "version": 1
      }
    },
    "ContextMenu": {
      "title": "ContextMenu",
      "description": "Right-click activated menu — the OS-native context-menu pattern as a\nweb component. Distinct from `menu-ui` (which is button-triggered):\nsame item shape (`menu-item-ui` children), different trigger surface\n(`contextmenu` event), and pointer-anchored positioning instead of\nelement-anchored. Pattern: WAI-APG Menu.\n\nTwo binding modes:\n **A. Wrap.** Default-slot child becomes the target:\n `<context-menu-ui><my-table>...</my-table>...items</context-menu-ui>`.\n **B. Selector.** Point at one or more existing elements via [for]:\n `<context-menu-ui for=\"#my-table\">...items</context-menu-ui>`.\n\nOn `contextmenu` event on a target: `preventDefault()`, position the\nmenu at the pointer coords, show via Popover API. Touch long-press\n(configurable via [long-press-ms]) does the same. Shift+F10 / Menu\nkey opens at the focused target's center for keyboard users.\n",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "component": {
          "const": "ContextMenu"
        },
        "for": {
          "description": "CSS selector(s) for target element(s). Empty = use default-slot child.",
          "type": "string",
          "default": ""
        },
        "long-press-ms": {
          "description": "Long-press duration (ms) on touch devices to open the menu.",
          "type": "number",
          "default": 500
        },
        "open": {
          "description": "Programmatic open state. Set true to open at target center.",
          "type": "boolean",
          "default": false
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [
          {
            "fix": "Wrap a target: `<context-menu-ui><my-target></my-target>...items</context-menu-ui>` OR point at one: `<context-menu-ui for=\"#my-target\">...items</context-menu-ui>`.",
            "why": "No target binding — the menu never opens.",
            "wrong": "<context-menu-ui>...just items...</context-menu-ui>"
          }
        ],
        "category": "container",
        "composes": [
          "menu-item-ui"
        ],
        "events": {
          "context-menu-close": {
            "description": "Fired when the menu closes (item-select / outside-click / Escape).",
            "detail": {
              "reason": {
                "description": "\"select\" | \"outside\" | \"escape\"",
                "type": "string"
              }
            }
          },
          "context-menu-open": {
            "description": "Fired when the menu opens (right-click / long-press / keyboard).",
            "detail": {
              "target": {
                "description": "The target element the menu was opened on.",
                "type": "Element"
              },
              "x": {
                "description": "Pointer x coord (viewport-relative); null for keyboard activation.",
                "type": "number"
              },
              "y": {
                "description": "Pointer y coord; null for keyboard activation.",
                "type": "number"
              }
            }
          },
          "context-menu-select": {
            "description": "Fired when an item is activated. Same shape as menu-ui's `action` event.",
            "detail": {
              "text": {
                "description": "Selected item's text.",
                "type": "string"
              },
              "value": {
                "description": "Selected item's value.",
                "type": "string"
              }
            }
          }
        },
        "examples": [
          {
            "description": "Right-click a file row for Open / Rename / Delete.",
            "a2ui": "[\n  { \"id\": \"root\", \"component\": \"ContextMenu\", \"children\": [\"target\", \"item-open\", \"item-rename\", \"div\", \"item-delete\"] },\n  { \"id\": \"target\", \"component\": \"Text\", \"textContent\": \"Right-click me\" },\n  { \"id\": \"item-open\",   \"component\": \"MenuItem\", \"value\": \"open\",   \"text\": \"Open\" },\n  { \"id\": \"item-rename\", \"component\": \"MenuItem\", \"value\": \"rename\", \"text\": \"Rename\" },\n  { \"id\": \"div\",         \"component\": \"MenuDivider\" },\n  { \"id\": \"item-delete\", \"component\": \"MenuItem\", \"value\": \"delete\", \"text\": \"Delete\", \"variant\": \"danger\" }\n]\n",
            "name": "file-actions"
          }
        ],
        "keywords": [
          "context-menu",
          "right-click",
          "menu",
          "popup-menu"
        ],
        "name": "UIContextMenu",
        "related": [
          "menu",
          "menu-item",
          "popover"
        ],
        "slots": {
          "default": {
            "description": "Two-purpose slot: the wrapped target element (mode A — first\nnon-menu-item-ui child) AND the menu-item-ui items. Items are\npromoted to the popover surface on open.\n"
          }
        },
        "states": [
          {
            "description": "Default. Menu closed; trigger listeners attached.",
            "name": "idle"
          },
          {
            "description": "Menu visible at pointer position; focus inside.",
            "attribute": "open",
            "name": "open"
          }
        ],
        "status": "stable",
        "synonyms": {
          "popup-menu": [
            "menu",
            "context-menu"
          ],
          "right-click": [
            "context-menu"
          ]
        },
        "tag": "context-menu-ui",
        "tokens": {
          "--context-menu-bg": {
            "description": "Menu surface background color.",
            "default": "var(--a-bg-subtle)"
          },
          "--context-menu-border": {
            "description": "Menu surface border color.",
            "default": "var(--a-border-subtle)"
          },
          "--context-menu-radius": {
            "description": "Menu surface border radius.",
            "default": "var(--a-radius-md)"
          },
          "--context-menu-shadow": {
            "description": "Menu surface shadow.",
            "default": "var(--a-shadow-lg)"
          }
        },
        "traits": [],
        "version": 1
      }
    },
    "DashboardLayout": {
      "title": "DashboardLayout",
      "description": "Module-tier dashboard-body composite. Crystallizes the recurring\n\"toolbar + KPI grid + chart area + table\" dashboard layout into a\nsingle primitive with four named regions (toolbar / kpis / charts /\ntable) plus an optional aside column. Each region is filled by\nconsumer-supplied <card-ui>s; the composite owns band sizing,\nresponsive breakpoints, and a [density] knob that propagates to\nevery descendant primitive via the parametric --a-density cascade.\n\nSits inside an <admin-page-body>; replaces the hand-rolled\n<col-ui gap=\"4\"> + nested <grid-ui> + <card-ui> chains every\nanalytics consumer reinvents today. Per ADR-0033 (Light-DOM\nsubstrate) — slot= attributes are decorative metadata; CSS rules\nmatch `:scope > [slot=\"X\"]` to position bands in DOM order.\n\nSpec: docs/specs/implementation-ready/SPEC-018-dashboard-layout.md.\n",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "chart-split": {
          "description": "Chart-band column split. Empty string = single full-width chart;\n`2` = two equal columns; `2:1` / `3:2` / `3:1` = asymmetric\nratios. Collapses to single column at narrow widths (≤48em).\n",
          "type": "string",
          "enum": [
            "",
            "2",
            "2:1",
            "3:2",
            "3:1"
          ],
          "default": ""
        },
        "component": {
          "const": "DashboardLayout"
        },
        "density": {
          "description": "Spacing scale — propagates --a-density to descendant primitives\nvia CSS custom-property cascade. Empty string inherits whatever\ndensity is in effect on an ancestor (the default — respects an\napp-level density theme). `compact` / `comfortable` / `spacious`\nexplicitly override.\n",
          "type": "string",
          "enum": [
            "",
            "comfortable",
            "compact",
            "spacious"
          ],
          "default": ""
        },
        "gap": {
          "description": "Override band-to-band vertical gap. Empty string = the\ndensity-modulated default (--a-space-4 at comfortable). Numeric\n`1`..`6` selects the corresponding --a-space-N step.\n",
          "type": "string",
          "default": ""
        },
        "kpi-columns": {
          "description": "Target column count for the KPI band at desktop width. Range 2-6;\nout-of-range values fall back to 4. Container-query collapse\nreduces this at narrower widths (≤48em → 2; ≤32em → 1).\n",
          "type": "string",
          "enum": [
            "2",
            "3",
            "4",
            "5",
            "6"
          ],
          "default": "4"
        },
        "loading": {
          "description": "Marks the composite as data-loading. Sets aria-busy=true on the\nhost and dims slotted children to 60% opacity with pointer-events\nsuppressed. Skeletons inside slotted cards continue to render\nnormally; the dim is on top of them.\n",
          "type": "boolean",
          "default": false
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [
          {
            "description": "Child without a [slot] attribute. Lands in the implicit default\nregion and breaks the band layout. Every direct child MUST\ndeclare its slot — toolbar / kpis / charts / table / aside.\n",
            "right": "<dashboard-layout-ui>\n  <card-ui slot=\"kpis\">...</card-ui>\n</dashboard-layout-ui>\n",
            "rule": "Every direct child of dashboard-layout-ui declares its slot.\n",
            "wrong": "<dashboard-layout-ui>\n  <card-ui><!-- no slot -->...</card-ui>\n</dashboard-layout-ui>\n"
          },
          {
            "description": "Nested DashboardLayout. Two density containers fight over the\n--a-density cascade. The inner one re-creates a 2-column layout\ninside a charts band, which is incoherent.\n",
            "right": "<tabs-ui>\n  <tab-panel-ui><dashboard-layout-ui>...</dashboard-layout-ui></tab-panel-ui>\n  <tab-panel-ui><dashboard-layout-ui>...</dashboard-layout-ui></tab-panel-ui>\n</tabs-ui>\n",
            "rule": "For nested dashboards, use sibling DashboardLayouts switched by\nTabs — not DashboardLayout inside DashboardLayout.\n",
            "wrong": "<dashboard-layout-ui>\n  <dashboard-layout-ui slot=\"charts\">...</dashboard-layout-ui>\n</dashboard-layout-ui>\n"
          },
          {
            "description": "kpi-columns out of range. Eight cards in a row is too narrow\nto be legible at typical container widths; the container-query\ncollapse (≤48em → 2 cols, ≤32em → 1 col) won't help when N is\nalready that large at desktop.\n",
            "right": "<dashboard-layout-ui kpi-columns=\"4\">...</dashboard-layout-ui>\n",
            "rule": "kpi-columns ∈ {2,3,4,5,6}. Split into 2 rows of 4 by composing\n2 DashboardLayouts vertically if 8 cards are truly necessary.\n",
            "wrong": "<dashboard-layout-ui kpi-columns=\"8\">...</dashboard-layout-ui>\n"
          }
        ],
        "category": "layout",
        "composes": [
          "card-ui",
          "grid-ui",
          "row-ui",
          "stat-ui",
          "chart-ui",
          "table-ui"
        ],
        "events": {
          "density-change": {
            "description": "Fired when [density] changes (programmatic or via setDensity()).\nBubbles; detail.density carries the new value.\n",
            "detail": {
              "density": {
                "description": "The new density value (comfortable / compact / spacious).",
                "type": "string"
              }
            }
          },
          "region-empty": {
            "description": "Fired when a slot transitions from having content to being empty\n(consumer-driven removal of the last child for that slot).\nUseful for parent-level adjust-layout logic.\n",
            "detail": {
              "region": {
                "description": "The slot name that became empty (toolbar / kpis / charts / table / aside).",
                "type": "string"
              }
            }
          }
        },
        "examples": [
          {
            "description": "KPI-strip + 2:1 chart split + table band inside an admin page.\n",
            "a2ui": "[\n  {\n    \"id\": \"dash-1\",\n    \"component\": \"DashboardLayout\",\n    \"density\": \"\",\n    \"kpiColumns\": \"4\",\n    \"chartSplit\": \"2:1\",\n    \"children\": [\"dash-toolbar\", \"dash-kpis\", \"dash-charts\", \"dash-table\"]\n  },\n  {\n    \"id\": \"dash-toolbar\",\n    \"component\": \"Row\",\n    \"slot\": \"toolbar\"\n  },\n  {\n    \"id\": \"dash-kpis\",\n    \"component\": \"Group\",\n    \"slot\": \"kpis\"\n  },\n  {\n    \"id\": \"dash-charts\",\n    \"component\": \"Group\",\n    \"slot\": \"charts\"\n  },\n  {\n    \"id\": \"dash-table\",\n    \"component\": \"Card\",\n    \"slot\": \"table\"\n  }\n]\n",
            "name": "canonical-analytics-dashboard"
          },
          {
            "description": "Six-KPI dashboard at compact density (power-user view).\n",
            "a2ui": "[\n  {\n    \"id\": \"dash-2\",\n    \"component\": \"DashboardLayout\",\n    \"density\": \"compact\",\n    \"kpiColumns\": \"6\"\n  }\n]\n",
            "name": "compact-six-kpi"
          },
          {
            "description": "Dashboard with a sticky aside column carrying a live activity feed.\n",
            "a2ui": "[\n  {\n    \"id\": \"dash-3\",\n    \"component\": \"DashboardLayout\",\n    \"chartSplit\": \"2\",\n    \"children\": [\"d3-aside\"]\n  },\n  {\n    \"id\": \"d3-aside\",\n    \"component\": \"Card\",\n    \"slot\": \"aside\"\n  }\n]\n",
            "name": "with-aside-feed"
          }
        ],
        "keywords": [
          "dashboard",
          "dashboard-layout",
          "analytics",
          "kpi-grid",
          "chart-area",
          "dashboard-body",
          "admin-dashboard",
          "reporting",
          "metrics-page",
          "layout-container"
        ],
        "name": "UIDashboardLayout",
        "related": [
          "AdminPageBody",
          "AdminPage",
          "Card",
          "Grid",
          "Stat",
          "Chart",
          "Table",
          "DateRangeSelector"
        ],
        "slots": {
          "aside": {
            "description": "Optional right-side panel (e.g., live activity feed). When set,\npromotes the host to a 2-column grid with the aside as a sticky\nright column on desktop. Collapses when empty.\n"
          },
          "charts": {
            "description": "Chart band — wrapper containing 1-3 <card-ui> with <chart-ui>.\n[chart-split] drives the grid columns. Collapses when empty.\n"
          },
          "kpis": {
            "description": "KPI band — typically a wrapper element containing N <card-ui>\ninstances each with one <stat-ui>. The composite drives the\ngrid template via [kpi-columns]. Collapses when empty.\n"
          },
          "table": {
            "description": "Table band — typically a single <card-ui slot=\"table\"> containing\n<table-ui> and optional <pagination-ui> in the footer. Full-bleed\nacross the main column. Collapses when empty.\n"
          },
          "toolbar": {
            "description": "Top band — filter chips, segmented date range, global controls.\nTypically a single <row-ui> or <date-range-selector-ui> (SPEC-019).\nCollapses when empty (no row reserved).\n"
          }
        },
        "states": [
          {
            "description": "Default; all regions interactive.",
            "name": "idle"
          },
          {
            "description": "Data fetch in progress; aria-busy=true; content dimmed.",
            "attribute": "loading",
            "name": "loading"
          },
          {
            "description": "Compact-density variant; tighter band gaps + density cascade.",
            "attribute": "density",
            "name": "compact"
          },
          {
            "description": "Spacious-density variant; looser band gaps + density cascade.",
            "attribute": "density",
            "name": "spacious"
          }
        ],
        "status": "experimental",
        "synonyms": {
          "charts": [
            "chart-area",
            "viz",
            "graphs"
          ],
          "dashboard": [
            "analytics",
            "report",
            "overview",
            "metrics"
          ],
          "kpi": [
            "metric",
            "stat",
            "measure"
          ],
          "layout": [
            "container",
            "grid",
            "frame",
            "shell"
          ],
          "tags": [
            "DashboardLayout",
            "Dashboard",
            "AnalyticsDashboard",
            "MetricsDashboard"
          ]
        },
        "tag": "dashboard-layout-ui",
        "tokens": {
          "--dashboard-layout-aside-width": {
            "description": "Aside column width when [slot=\"aside\"] is present.",
            "default": "20em"
          },
          "--dashboard-layout-chart-gap": {
            "description": "Inter-card gap inside the chart band.",
            "default": "var(--a-space-4)"
          },
          "--dashboard-layout-gap": {
            "description": "Band-to-band vertical gap.",
            "default": "var(--a-space-4)"
          },
          "--dashboard-layout-kpi-gap": {
            "description": "Inter-card gap inside the KPI band.",
            "default": "var(--a-space-2)"
          },
          "--dashboard-layout-padding": {
            "description": "Outer padding around the composite.",
            "default": "0"
          }
        },
        "traits": [],
        "version": 1
      }
    },
    "DateRangePicker": {
      "title": "DateRangePicker",
      "description": "Compound form primitive for selecting a start + end date pair with optional named preset shortcuts (\"Today\", \"Last 7 days\", \"This month\", ...). Default presentation is a trigger button showing the formatted range; on activation a popover opens with two synchronized calendar panes + a preset side rail. Composes <calendar-picker-ui> twice; emits {from, to} ISO 8601 dates. Optional comparison-range mode emits a secondary range for analytics surfaces.",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "required": {
          "description": "Required for validation when inside a `<form>`.",
          "type": "boolean",
          "default": false
        },
        "compareValue": {
          "description": "Comparison range when `[comparison]` is set. Same `{from, to}` shape as `value`.",
          "$ref": "#/$defs/DynamicString"
        },
        "comparison": {
          "description": "Enable comparison-range mode. Renders a second preset cluster and emits a secondary range under `<name>-compare`.",
          "type": "boolean",
          "default": false
        },
        "component": {
          "const": "DateRangePicker"
        },
        "disabled": {
          "description": "Block all interaction. Trigger remains rendered but does not open the popover.",
          "type": "boolean",
          "default": false
        },
        "format": {
          "description": "Trigger button date format. `short`: `Jan 1, 2026`; `long`: `January 1, 2026`; `iso`: `2026-01-01`.",
          "type": "string",
          "enum": [
            "short",
            "long",
            "iso"
          ],
          "default": "short"
        },
        "max": {
          "description": "Latest selectable ISO date (inclusive). Days after are disabled in both panes.",
          "type": "string",
          "default": ""
        },
        "min": {
          "description": "Earliest selectable ISO date (inclusive). Days before are disabled in both panes.",
          "type": "string",
          "default": ""
        },
        "name": {
          "description": "Form field name for form data submission. The selected range serializes as JSON `{\"from\":\"...\",\"to\":\"...\"}` under this key.",
          "type": "string",
          "default": ""
        },
        "noPresets": {
          "description": "Hide the preset side rail.",
          "type": "boolean",
          "default": false
        },
        "open": {
          "description": "Whether the popover is currently open.",
          "type": "boolean",
          "default": false
        },
        "placeholder": {
          "description": "Text shown in the trigger when the value is empty.",
          "type": "string",
          "default": "Select range"
        },
        "placement": {
          "description": "Popover placement relative to the trigger. Default `bottom` centers the two-calendar panel under the trigger (ADR-0034 Rule 2 — ~800px panel >> trigger).",
          "type": "string",
          "enum": [
            "top",
            "bottom",
            "left",
            "right",
            "top-start",
            "top-end",
            "bottom-start",
            "bottom-end"
          ],
          "default": "bottom"
        },
        "readonly": {
          "description": "Block edits; allow keyboard navigation for screen-reader inspection.",
          "type": "boolean",
          "default": false
        },
        "value": {
          "description": "Selected range as `{from, to}` ISO 8601 dates. Null when empty. Emitted on commit.",
          "$ref": "#/$defs/DynamicString"
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [
          {
            "fix": "{\"component\": \"DateRangePicker\", \"value\": {\"from\": \"2026-01-01\", \"to\": \"2026-01-31\"}}\n",
            "why": "`value` is a string, not an object. The contract is `{from, to}` ISO 8601 dates.\n",
            "wrong": "{\"component\": \"DateRangePicker\", \"value\": \"2026-01-01 to 2026-01-31\"}\n"
          },
          {
            "fix": "{\"component\": \"DateRangePicker\", \"value\": {\"from\": \"2026-01-01\", \"to\": \"2026-12-31\"}}\n",
            "why": "Reversed range — `to < from`. This fires `invalid` and never commits.\n",
            "wrong": "{\"component\": \"DateRangePicker\", \"value\": {\"from\": \"2026-12-31\", \"to\": \"2026-01-01\"}}\n"
          },
          {
            "fix": "Use <date-range-picker-ui>.\n",
            "why": "This is the pattern the primitive replaces. Reinvents linked-pane behavior,\nmisses preset rail, has no a11y range-announcement.\n",
            "wrong": "Two adjacent <calendar-picker-ui> instances + JS synchronization.\n"
          }
        ],
        "category": "input",
        "composes": [
          "calendar-grid-ui",
          "button-ui",
          "popover-ui",
          "text-ui",
          "divider-ui"
        ],
        "events": {
          "change": {
            "description": "Fired when the range commits (both `from` AND `to` selected, OR a preset clicked).",
            "detail": {
              "compareValue": "object",
              "presetLabel": "string",
              "value": "object"
            }
          },
          "close": {
            "description": "Popover closed (without commit, or after commit).",
            "detail": {
              "reason": "string"
            }
          },
          "input": {
            "description": "Fired during selection — e.g. user clicked `from` but has not yet picked `to`.",
            "detail": {
              "value": "object"
            }
          },
          "invalid": {
            "description": "A constraint failed (out of range, end < start).",
            "detail": {
              "reason": "string",
              "value": "object"
            }
          },
          "open": {
            "description": "Popover opened (user clicked the trigger or pressed Enter / Space).",
            "detail": {
              "trigger": "string"
            }
          }
        },
        "examples": [
          {
            "description": "Form-field-wrapped picker with default presets.",
            "a2ui": "[\n  {\n    \"id\": \"field\",\n    \"component\": \"Field\",\n    \"label\": \"Report period\",\n    \"children\": [\"dr\"]\n  },\n  {\n    \"id\": \"dr\",\n    \"component\": \"DateRangePicker\",\n    \"name\": \"report-period\",\n    \"min\": \"2026-01-01\",\n    \"max\": \"2026-12-31\"\n  }\n]\n",
            "name": "canonical"
          },
          {
            "description": "Analytics-surface picker with comparison range enabled.",
            "a2ui": "[\n  {\n    \"id\": \"dr\",\n    \"component\": \"DateRangePicker\",\n    \"name\": \"period\",\n    \"comparison\": true,\n    \"value\": {\"from\": \"2026-05-01\", \"to\": \"2026-05-31\"},\n    \"compareValue\": {\"from\": \"2026-04-01\", \"to\": \"2026-04-30\"}\n  }\n]\n",
            "name": "comparison"
          },
          {
            "description": "Custom-only picker with the preset rail hidden.",
            "a2ui": "[\n  {\n    \"id\": \"dr\",\n    \"component\": \"DateRangePicker\",\n    \"name\": \"period\",\n    \"noPresets\": true\n  }\n]\n",
            "name": "no-presets"
          }
        ],
        "keywords": [
          "daterangepicker",
          "date-range-picker",
          "date-range",
          "range",
          "daterange",
          "period",
          "reporting-period"
        ],
        "name": "UIDateRangePicker",
        "related": [
          "calendar-picker",
          "popover",
          "field",
          "button"
        ],
        "slots": {
          "footer": {
            "description": "Optional footer area below the calendars (e.g., \"Apply\" / \"Cancel\" buttons for explicit-commit flows)."
          },
          "presets": {
            "description": "Custom preset content replacing the default preset rail."
          },
          "trigger": {
            "description": "Custom trigger replacement. When omitted, a default `<button-ui>` is stamped."
          }
        },
        "states": [
          {
            "description": "Closed, no pending selection.",
            "name": "idle"
          },
          {
            "description": "Popover open, user has not yet clicked a start date.",
            "attribute": "open",
            "name": "open-pending-from"
          },
          {
            "description": "Start clicked, awaiting end click; hover preview active.",
            "attribute": "open",
            "name": "open-pending-to"
          },
          {
            "description": "Both ends clicked, awaiting Apply (only in explicit-commit mode with `footer` slot).",
            "attribute": "open",
            "name": "open-committed"
          },
          {
            "description": "Non-interactive; dimmed.",
            "attribute": "disabled",
            "name": "disabled"
          },
          {
            "description": "Read-only; trigger keyboard-focusable but popover does not open.",
            "attribute": "readonly",
            "name": "readonly"
          }
        ],
        "status": "experimental",
        "synonyms": {
          "period": [
            "date-range",
            "range",
            "reporting-period"
          ],
          "range": [
            "date-range",
            "period",
            "report-period"
          ],
          "tags": [
            "DateRangePicker",
            "DateRange",
            "DateRangeInput"
          ]
        },
        "tag": "date-range-picker-ui",
        "tokens": {
          "--date-range-picker-bg": {
            "description": "Host background.",
            "default": "var(--a-bg)"
          },
          "--date-range-picker-popover-bg": {
            "description": "Popover background.",
            "default": "var(--a-bg-subtle)"
          },
          "--date-range-picker-popover-border": {
            "description": "Popover border color.",
            "default": "var(--a-border-subtle)"
          },
          "--date-range-picker-popover-radius": {
            "description": "Popover border radius.",
            "default": "var(--a-radius-lg)"
          },
          "--date-range-picker-popover-shadow": {
            "description": "Popover box shadow.",
            "default": "var(--a-shadow-lg)"
          },
          "--date-range-picker-preset-bg": {
            "description": "Preset row background (idle).",
            "default": "transparent"
          },
          "--date-range-picker-preset-bg-hover": {
            "description": "Preset row background on hover.",
            "default": "var(--a-bg-hover)"
          },
          "--date-range-picker-preview-bg": {
            "description": "In-range preview background (between from and pending to).",
            "default": "var(--a-accent-muted)"
          },
          "--date-range-picker-px": {
            "description": "Horizontal popover padding.",
            "default": "var(--a-space-3)"
          },
          "--date-range-picker-py": {
            "description": "Vertical popover padding.",
            "default": "var(--a-space-2)"
          },
          "--date-range-picker-selected-bg": {
            "description": "Selected day-cell background (cascaded into the inner calendar via --calendar-picker-day-bg-selected).",
            "default": "var(--a-accent)"
          },
          "--date-range-picker-selected-fg": {
            "description": "Selected day-cell foreground.",
            "default": "var(--a-accent-fg)"
          }
        },
        "traits": [],
        "version": 1
      }
    },
    "DateRangeSelector": {
      "title": "DateRangeSelector",
      "description": "Page-level \"current time window\" chooser for dashboards. A module-tier\ncomposite that pairs a preset chip-row (Today / 7d / 30d / 90d / QTD /\nYTD / Custom) with an embedded <date-range-picker-ui> and broadcasts\nthe active range to every range-aware panel on the page.\n\nOne chooser, one event bus, every panel follows. The composite owns\nthe range value, resolves preset keys to ISO 8601 from/to pairs, and\nemits a `range-change` CustomEvent on the configured broadcast target\n(default `document`). It also writes `data-range-from` /\n`data-range-to` to that target so CSS-only subscribers can match\nattribute selectors.\n\nUse for dashboard toolbars (typically <dashboard-layout-ui slot=\"toolbar\">\nor <admin-page-header slot=\"action\">). For card-local per-panel\ncomparison overlays, set [broadcast=\"self\"] so the secondary instance\nscopes to its host.\n\nSpec: docs/specs/implementation-ready/SPEC-019-date-range-selector-global.md.\n",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "aria-label": {
          "description": "Accessible name for the toolbar group (role=group). Defaults to\n\"Time period\"; override when multiple range selectors sit on the\nsame page (e.g., \"Primary range\" / \"Comparison range\").\n",
          "type": "string",
          "default": "Time period"
        },
        "broadcast": {
          "description": "Broadcast scope. `document` fires `range-change` on\n`document.documentElement` AND writes `data-range-from` /\n`data-range-to` there (page-global). `self` fires on the host and\nwrites the same attributes to the host (scoped subscribers).\n`none` suppresses broadcast entirely; only the host-level `change`\nevent fires.\n",
          "type": "string",
          "enum": [
            "document",
            "self",
            "none"
          ],
          "default": "document"
        },
        "component": {
          "const": "DateRangeSelector"
        },
        "from": {
          "description": "Start of the resolved range, ISO-8601 date (YYYY-MM-DD). Read-only\noutput — set by the composite when value resolves or when the\nembedded picker commits a custom range. Consumers read this after\n`range-change`.\n",
          "$ref": "#/$defs/DynamicString"
        },
        "presets": {
          "description": "Override the preset chip list as a comma-separated subset of the\n`value` enum. Order matters. `custom` is optional but recommended\nas the trailing chip. Unknown keys are ignored at runtime.\n",
          "type": "string",
          "default": "today,7d,30d,90d,qtd,ytd,custom"
        },
        "to": {
          "description": "End of the resolved range, ISO-8601 date. Same read-only output\nsemantics as `from`.\n",
          "$ref": "#/$defs/DynamicString"
        },
        "value": {
          "description": "Active preset key. Drives the chip-row selection and re-resolves\nthe from/to range on change. `custom` defers to the embedded\npicker's value (consumer-supplied from/to).\n",
          "$ref": "#/$defs/DynamicString"
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [
          {
            "description": "Two document-broadcasters on the same page. The late mounter wins\nsilently for the data-range-* attributes on <html>, and CSS-only\nsubscribers see flicker as the attributes are rewritten.\n",
            "right": "<date-range-selector-ui broadcast=\"document\"></date-range-selector-ui>\n<date-range-selector-ui broadcast=\"self\"></date-range-selector-ui>\n",
            "rule": "Pick ONE global broadcaster; route secondary instances via\nbroadcast=\"self\" so they emit only on the host.\n",
            "wrong": "<date-range-selector-ui broadcast=\"document\"></date-range-selector-ui>\n<date-range-selector-ui broadcast=\"document\"></date-range-selector-ui>\n"
          },
          {
            "description": "Using DateRangeSelector for single-date selection. The composite\nresolves a range; the picker UI exposes two-pane selection. For\nsingle-date use <input-ui type=\"date\"> or <calendar-picker-ui>.\n",
            "right": "<input-ui type=\"date\" name=\"d\"></input-ui>\n",
            "rule": "Range chooser → DateRangeSelector. Single-date chooser → input-ui\ntype=date or calendar-picker-ui.\n",
            "wrong": "<date-range-selector-ui value=\"today\"></date-range-selector-ui>\n<!-- The selector still resolves a range (from=today, to=today). -->\n"
          },
          {
            "description": "Custom selected with no from/to. The composite falls back to the\nprevious resolved range, which may be empty on first mount —\nconsumers see mystery behavior.\n",
            "right": "<date-range-selector-ui value=\"custom\" from=\"2026-05-01\" to=\"2026-05-07\"></date-range-selector-ui>\n",
            "rule": "value=\"custom\" requires either declarative from/to or a follow-on\nsetRange(\"custom\", from, to) call before the chooser is meaningful.\n",
            "wrong": "<date-range-selector-ui value=\"custom\"></date-range-selector-ui>\n"
          },
          {
            "description": "Unknown preset key. The composite resolves to the default (\"7d\")\nand the consumer sees an unexpected range.\n",
            "right": "<date-range-selector-ui value=\"qtd\"></date-range-selector-ui>\n",
            "rule": "Use documented enum keys only — today, 7d, 30d, 90d, qtd, ytd,\ncustom. Quarter-to-date is `qtd`.\n",
            "wrong": "<date-range-selector-ui value=\"lastQuarter\"></date-range-selector-ui>\n"
          }
        ],
        "category": "input",
        "composes": [
          "date-range-picker-ui",
          "segmented-ui",
          "segment-ui",
          "button-ui",
          "text-ui"
        ],
        "events": {
          "change": {
            "description": "Alias of range-change, fires on the host element only (UIFormElement\nconvention). When [name] is set, the form value is the colon-pair\n\"{from}:{to}\".\n",
            "detail": {
              "from": "string",
              "to": "string",
              "value": "string"
            }
          },
          "range-change": {
            "description": "Fired when the resolved range changes — preset clicked, custom\nrange applied, or programmatic setRange(). Fires on the broadcast\ntarget per [broadcast]. Guaranteed once per resolved range; never\nfires for in-progress picker interactions.\n",
            "detail": {
              "from": "string",
              "preset": "string",
              "to": "string",
              "value": "string"
            }
          }
        },
        "examples": [
          {
            "description": "Page-global selector in a dashboard toolbar; charts subscribe to range-change on document.",
            "a2ui": "[\n  {\n    \"id\": \"dr-global\",\n    \"component\": \"DateRangeSelector\",\n    \"value\": \"30d\",\n    \"presets\": \"today,7d,30d,90d,qtd,ytd,custom\",\n    \"broadcast\": \"document\"\n  }\n]\n",
            "name": "dashboard-toolbar-global"
          },
          {
            "description": "Card-local secondary picker broadcasting only on the host (no document writes).",
            "a2ui": "[\n  {\n    \"id\": \"dr-overlay\",\n    \"component\": \"DateRangeSelector\",\n    \"broadcast\": \"self\",\n    \"presets\": \"7d,30d,90d\"\n  }\n]\n",
            "name": "scoped-self-broadcast"
          },
          {
            "description": "Form-participating selector emitting a colon-pair value on submit.",
            "a2ui": "[\n  {\n    \"id\": \"dr-form\",\n    \"component\": \"DateRangeSelector\",\n    \"name\": \"period\",\n    \"value\": \"ytd\"\n  }\n]\n",
            "name": "form-participating"
          }
        ],
        "keywords": [
          "date-range-selector",
          "date-range",
          "range-selector",
          "period-selector",
          "time-window",
          "dashboard-range",
          "period",
          "global-range",
          "range-bus",
          "timeframe"
        ],
        "name": "DateRangeSelector",
        "related": [
          "DateRangePicker",
          "Segmented",
          "Segment",
          "Button",
          "Text",
          "DashboardLayout",
          "AdminPageHeader"
        ],
        "slots": {
          "default": {
            "description": "The composite stamps its own chip row + picker; children placed in\nthe default slot are ignored. Use prefix/suffix slots for label\ntext or auxiliary controls.\n"
          },
          "prefix": {
            "description": "Optional leading content (e.g., a \"Period:\" caption). Renders\nbefore the chip row.\n"
          },
          "suffix": {
            "description": "Optional trailing content (e.g., a comparison-mode toggle).\nRenders after the picker.\n"
          }
        },
        "states": [
          {
            "description": "Default — preset chip selected, custom picker closed.",
            "name": "idle"
          },
          {
            "description": "Custom preset active; embedded picker is exposed for editing.",
            "attribute": "value",
            "name": "custom"
          },
          {
            "description": "Embedded picker popover is open (reflected from <date-range-picker-ui>).",
            "attribute": "picker-open",
            "name": "picker-open"
          },
          {
            "description": "Non-interactive; chips + picker dimmed; pointer-events suppressed.",
            "attribute": "disabled",
            "name": "disabled"
          }
        ],
        "status": "experimental",
        "synonyms": {
          "period": [
            "range",
            "timeframe",
            "reporting-period"
          ],
          "range": [
            "period",
            "timeframe",
            "window"
          ],
          "selector": [
            "chooser",
            "picker"
          ],
          "tags": [
            "DateRangeSelector",
            "RangeSelector",
            "PeriodSelector",
            "TimeWindow"
          ]
        },
        "tag": "date-range-selector-ui",
        "tokens": {
          "--date-range-selector-gap": {
            "description": "Inline gap between prefix slot, chip row, picker, readout, and suffix slot.",
            "default": "var(--a-space-3)"
          },
          "--date-range-selector-picker-trigger-py": {
            "description": "Vertical padding on the embedded picker trigger (cascades into the inner button-ui).",
            "default": "var(--a-space-2)"
          },
          "--date-range-selector-readout-fg": {
            "description": "Resolved-range readout foreground color.",
            "default": "var(--a-fg-muted)"
          },
          "--date-range-selector-readout-size": {
            "description": "Resolved-range readout font size.",
            "default": "var(--a-font-size-sm)"
          }
        },
        "traits": [],
        "version": 1
      }
    },
    "DatetimePicker": {
      "title": "DatetimePicker",
      "description": "Single-control date + time selection. Trigger button opens a popover with a `<calendar-picker-ui>` on the left + a `<time-picker-ui>` on the right; commit emits a full ISO 8601 datetime string (\"YYYY-MM-DDTHH:mm\" or with seconds). Composes the two underlying primitives — never wraps a native `<input type=\"datetime-local\">` (per ADR-0025). Form-associated under one `name`. SPEC-038.",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "required": {
          "description": "Required for validation when inside a `<form>`.",
          "type": "boolean",
          "default": false
        },
        "component": {
          "const": "DatetimePicker"
        },
        "disabled": {
          "description": "Block all interaction. Trigger remains rendered but does not open the popover.",
          "type": "boolean",
          "default": false
        },
        "format": {
          "description": "Trigger button date format. `short`: `Jan 1, 2026 14:30`; `long`: `January 1, 2026 14:30`; `iso`: full ISO string.",
          "type": "string",
          "enum": [
            "short",
            "long",
            "iso"
          ],
          "default": "short"
        },
        "hourcycle": {
          "description": "Hour cycle for the time pane. Empty (default) derives from the\ndocument locale. `h12` forces a 12-hour cycle with an AM/PM\n(meridiem) segment; `h23` forces 24-hour cycle.\n",
          "type": "string",
          "enum": [
            "",
            "h12",
            "h23"
          ],
          "default": ""
        },
        "locale": {
          "description": "BCP-47 locale tag used to derive hour-cycle when `hour-cycle` is empty. Falls back to `<html lang>` then to browser default.",
          "type": "string",
          "default": ""
        },
        "max": {
          "description": "Latest selectable ISO 8601 datetime (inclusive). Days after are disabled in the calendar pane; times after are rejected by the time pane on the same day.",
          "type": "string",
          "default": ""
        },
        "min": {
          "description": "Earliest selectable ISO 8601 datetime (inclusive). Days before are disabled in the calendar pane; times before are rejected by the time pane on the same day.",
          "type": "string",
          "default": ""
        },
        "name": {
          "description": "Form field name. The ISO 8601 datetime is submitted under this key when the picker is inside a `<form>`.",
          "type": "string",
          "default": ""
        },
        "open": {
          "description": "Whether the popover is currently open.",
          "type": "boolean",
          "default": false
        },
        "placeholder": {
          "description": "Text shown in the trigger when the value is empty.",
          "type": "string",
          "default": "Select date and time"
        },
        "placement": {
          "description": "Popover placement relative to the trigger. Default `bottom` centers the calendar+time panel under the trigger (ADR-0034 Rule 2 — ~600px panel >> trigger).",
          "type": "string",
          "enum": [
            "top",
            "bottom",
            "left",
            "right",
            "top-start",
            "top-end",
            "bottom-start",
            "bottom-end"
          ],
          "default": "bottom"
        },
        "precision": {
          "description": "Time-pane precision. `minute` (default) emits `HH:mm`; `second` exposes the seconds segment and emits `HH:mm:ss`.",
          "type": "string",
          "enum": [
            "minute",
            "second"
          ],
          "default": "minute"
        },
        "readonly": {
          "description": "Block edits; allow keyboard navigation for screen-reader inspection.",
          "type": "boolean",
          "default": false
        },
        "step": {
          "description": "Per-Arrow-keypress increment in seconds for the time pane. 60 = minute precision (default), 900 = 15-minute, 1 = second precision.",
          "type": "number",
          "default": 60
        },
        "value": {
          "description": "Current value as ISO 8601 datetime (\"YYYY-MM-DDTHH:mm\" or \"YYYY-MM-DDTHH:mm:ss\"). Empty when no value selected.",
          "$ref": "#/$defs/DynamicString"
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [
          {
            "fix": "{\"component\": \"DatetimePicker\", \"value\": \"2026-05-24T00:00\"}\n",
            "why": "`value` is a date-only string — no time component. The contract requires\na full ISO 8601 datetime including the `T` and time segment.\n",
            "wrong": "{\"component\": \"DatetimePicker\", \"value\": \"2026-05-24\"}\n"
          },
          {
            "fix": "{\"component\": \"DatetimePicker\", \"value\": \"2026-05-24T14:30\"}\n",
            "why": "`value` is a time-only string — no date component. Use `<TimePicker>` for\ntime-only selection or supply the date portion.\n",
            "wrong": "{\"component\": \"DatetimePicker\", \"value\": \"14:30\"}\n"
          },
          {
            "fix": "{\"component\": \"DatetimePicker\", \"name\": \"field-name\"}\n",
            "why": "Nesting a native datetime-local input violates ADR-0025 and bypasses\nElementInternals form participation.\n",
            "wrong": "{\"component\": \"DatetimePicker\", \"children\": [\n  {\"component\": \"Input\", \"type\": \"datetime-local\"}\n]}\n"
          },
          {
            "fix": "<datetime-picker-ui name=\"appointment\"></datetime-picker-ui>\n",
            "why": "Hand-rolled date + free-form time composition is the pattern this primitive\nreplaces. It misses the coordinated popover, the per-segment Spinbutton\na11y model, and unified form participation.\n",
            "wrong": "<calendar-picker-ui></calendar-picker-ui>\n<input-ui type=\"text\" placeholder=\"HH:mm\"></input-ui>\n"
          }
        ],
        "category": "input",
        "composes": [
          "calendar-grid-ui",
          "time-picker-ui",
          "button-ui",
          "popover-ui",
          "divider-ui"
        ],
        "events": {
          "change": {
            "description": "Fired when the value commits (date picked + time edited, OR Apply clicked in explicit-commit mode).",
            "detail": {
              "source": "string",
              "value": "string"
            }
          },
          "close": {
            "description": "Popover closed (without commit, or after commit).",
            "detail": {
              "reason": "string"
            }
          },
          "input": {
            "description": "Fired during partial selection (date picked but time still pending, or vice versa).",
            "detail": {
              "value": "string"
            }
          },
          "invalid": {
            "description": "A constraint failed (out of range, parse error).",
            "detail": {
              "reason": "string",
              "value": "string"
            }
          },
          "open": {
            "description": "Popover opened (user clicked the trigger or pressed Enter / Space).",
            "detail": {
              "trigger": "string"
            }
          }
        },
        "examples": [
          {
            "description": "Form-field-wrapped picker with min/max bounds.",
            "a2ui": "[\n  {\n    \"id\": \"field\",\n    \"component\": \"Field\",\n    \"label\": \"Appointment\",\n    \"children\": [\"dt\"]\n  },\n  {\n    \"id\": \"dt\",\n    \"component\": \"DatetimePicker\",\n    \"name\": \"appointment\",\n    \"min\": \"2026-01-01T00:00\",\n    \"max\": \"2026-12-31T23:59\"\n  }\n]\n",
            "name": "canonical"
          },
          {
            "description": "Log-cursor picker with second precision.",
            "a2ui": "[\n  {\n    \"id\": \"dt\",\n    \"component\": \"DatetimePicker\",\n    \"name\": \"log-cursor\",\n    \"precision\": \"second\",\n    \"step\": 1,\n    \"value\": \"2026-05-24T14:30:45\"\n  }\n]\n",
            "name": "second-precision"
          },
          {
            "description": "Cron editor with forced 24-hour cycle.",
            "a2ui": "[\n  {\n    \"id\": \"dt\",\n    \"component\": \"DatetimePicker\",\n    \"name\": \"cron\",\n    \"hourCycle\": \"h23\"\n  }\n]\n",
            "name": "forced-24h"
          },
          {
            "description": "Read-only datetime for inspection only.",
            "a2ui": "[\n  {\n    \"id\": \"dt\",\n    \"component\": \"DatetimePicker\",\n    \"readonly\": true,\n    \"value\": \"2026-05-24T14:30\"\n  }\n]\n",
            "name": "readonly"
          }
        ],
        "keywords": [
          "datetimepicker",
          "datetime-picker",
          "datetime",
          "date-time",
          "dateandtime",
          "appointment",
          "schedule",
          "timestamp"
        ],
        "name": "UIDatetimePicker",
        "related": [
          "calendar-picker",
          "time-picker",
          "date-range-picker",
          "popover",
          "field",
          "button"
        ],
        "slots": {
          "footer": {
            "description": "Optional Apply / Cancel buttons for explicit-commit flows. Spans both panes below the calendar + time area."
          },
          "trigger": {
            "description": "Custom trigger replacement. When omitted, a default `<button-ui>` is stamped."
          }
        },
        "states": [
          {
            "description": "Closed, no pending selection.",
            "name": "idle"
          },
          {
            "description": "Popover open, no calendar pick yet.",
            "attribute": "open",
            "name": "open-pending-date"
          },
          {
            "description": "Date picked; time pane is the next focus target.",
            "attribute": "open",
            "name": "open-pending-time"
          },
          {
            "description": "Both panes set; awaiting Apply (explicit-commit mode only).",
            "attribute": "open",
            "name": "open-committed"
          },
          {
            "description": "Non-interactive; dimmed.",
            "attribute": "disabled",
            "name": "disabled"
          },
          {
            "description": "Read-only; trigger keyboard-focusable but popover does not open.",
            "attribute": "readonly",
            "name": "readonly"
          }
        ],
        "status": "experimental",
        "synonyms": {
          "appointment": [
            "datetime",
            "meeting",
            "schedule"
          ],
          "datetime": [
            "date-time",
            "timestamp",
            "appointment",
            "schedule"
          ],
          "tags": [
            "DateTimePicker",
            "DateTimeInput",
            "DatetimeInput",
            "Timestamp"
          ]
        },
        "tag": "datetime-picker-ui",
        "tokens": {
          "--datetime-picker-bg": {
            "description": "Host background.",
            "default": "var(--a-bg)"
          },
          "--datetime-picker-divider": {
            "description": "Pane divider color.",
            "default": "var(--a-border-subtle)"
          },
          "--datetime-picker-duration": {
            "description": "Open/close transition duration.",
            "default": "var(--a-duration-fast)"
          },
          "--datetime-picker-easing": {
            "description": "Open/close transition easing.",
            "default": "var(--a-easing)"
          },
          "--datetime-picker-fg": {
            "description": "Host text color.",
            "default": "var(--a-fg)"
          },
          "--datetime-picker-popover-bg": {
            "description": "Popover background.",
            "default": "var(--a-bg-subtle)"
          },
          "--datetime-picker-popover-border": {
            "description": "Popover border color.",
            "default": "var(--a-border-subtle)"
          },
          "--datetime-picker-popover-gap": {
            "description": "Gap between calendar pane and time pane.",
            "default": "var(--a-space-3)"
          },
          "--datetime-picker-popover-padding": {
            "description": "Popover internal padding.",
            "default": "var(--a-space-3)"
          },
          "--datetime-picker-popover-radius": {
            "description": "Popover border radius.",
            "default": "var(--a-radius-lg)"
          },
          "--datetime-picker-popover-shadow": {
            "description": "Popover box shadow.",
            "default": "var(--a-shadow-lg)"
          },
          "--datetime-picker-px": {
            "description": "Horizontal popover padding.",
            "default": "var(--a-space-3)"
          },
          "--datetime-picker-py": {
            "description": "Vertical popover padding.",
            "default": "var(--a-space-2)"
          },
          "--datetime-picker-trigger-min-width": {
            "description": "Default trigger min-width — sized so the formatted date+time fits without truncation.",
            "default": "16em"
          }
        },
        "traits": [],
        "version": 1
      }
    },
    "DemoToggle": {
      "title": "DemoToggle",
      "description": "Side-by-side comparison primitive — header bar with a switch + two child slots (\"on\" / \"off\"); toggling the switch swaps which slot is visible. Used on trait detail pages to show \"with trait\" vs \"without trait\" on the same chrome. data-mode=\"overlay\" stacks the slots on the same coordinates so layout never shifts.",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "component": {
          "const": "DemoToggle"
        },
        "initial": {
          "description": "Initial state when [state] is not set on connect (\"on\" | \"off\").",
          "type": "string",
          "enum": [
            "on",
            "off"
          ],
          "default": "off"
        },
        "labelOff": {
          "description": "Header label rendered when state is \"off\".",
          "type": "string",
          "default": "Off"
        },
        "labelOn": {
          "description": "Header label rendered when state is \"on\".",
          "type": "string",
          "default": "On"
        },
        "state": {
          "description": "Current toggle state (\"on\" | \"off\"). Reflected as data-state on the host.",
          "type": "string",
          "enum": [
            "",
            "on",
            "off"
          ],
          "default": ""
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [],
        "category": "container",
        "composes": [
          "switch-ui"
        ],
        "events": {
          "change": {
            "description": "Fired when the toggle flips. detail contains { state }.",
            "detail": {
              "state": {
                "description": "New toggle state.",
                "type": "boolean"
              }
            }
          }
        },
        "examples": [
          {
            "description": "Compare a trait-bearing surface against the bare control on the same chrome.",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"DemoToggle\",\n    \"labelOn\": \"With shimmer-loading\",\n    \"labelOff\": \"Without shimmer-loading\",\n    \"initial\": \"off\",\n    \"children\": [\"off\", \"on\"]\n  },\n  {\n    \"id\": \"off\",\n    \"component\": \"Card\",\n    \"slot\": \"off\",\n    \"children\": [\"off-section\"]\n  },\n  {\n    \"id\": \"off-section\",\n    \"component\": \"Section\",\n    \"children\": [\"off-text\"]\n  },\n  {\n    \"id\": \"off-text\",\n    \"component\": \"Text\",\n    \"textContent\": \"Bare surface — no trait attached.\"\n  },\n  {\n    \"id\": \"on\",\n    \"component\": \"Card\",\n    \"slot\": \"on\",\n    \"children\": [\"on-section\"]\n  },\n  {\n    \"id\": \"on-section\",\n    \"component\": \"Section\",\n    \"children\": [\"on-text\"]\n  },\n  {\n    \"id\": \"on-text\",\n    \"component\": \"Text\",\n    \"textContent\": \"Same surface, with trait attached.\"\n  }\n]",
            "name": "with-without-trait"
          }
        ],
        "keywords": [
          "demo",
          "toggle",
          "compare",
          "comparison",
          "trait",
          "before-after",
          "a-b",
          "switch"
        ],
        "name": "UIDemoToggle",
        "related": [
          "Switch",
          "Card"
        ],
        "slots": {
          "bar": {
            "description": "Internal header bar (auto-stamped). Hosts the embedded switch + label."
          },
          "off": {
            "description": "Surface rendered when state is \"off\" (the \"without trait\" variant)."
          },
          "on": {
            "description": "Surface rendered when state is \"on\" (the \"with trait\" variant)."
          }
        },
        "states": [
          {
            "description": "Default, ready for interaction.",
            "name": "idle"
          },
          {
            "description": "On slot is active; bar leans accent.",
            "attribute": "data-state",
            "name": "on"
          },
          {
            "description": "Off slot is active; bar is neutral.",
            "attribute": "data-state",
            "name": "off"
          }
        ],
        "status": "stable",
        "synonyms": {
          "compare": [
            "demo-toggle",
            "segmented"
          ],
          "switch": [
            "demo-toggle",
            "toggle-group"
          ]
        },
        "tag": "demo-toggle-ui",
        "tokens": {
          "--demo-toggle-bar-bg": {
            "description": "Header bar background (accent when state=on)"
          },
          "--demo-toggle-bar-fg": {
            "description": "Header bar foreground"
          },
          "--demo-toggle-bg": {
            "description": "Stage background"
          },
          "--demo-toggle-border": {
            "description": "Border color"
          },
          "--demo-toggle-radius": {
            "description": "Outer border-radius"
          },
          "--demo-toggle-stage-padding": {
            "description": "Inner padding around each slot"
          }
        },
        "traits": [],
        "version": 1
      }
    },
    "DescriptionList": {
      "title": "DescriptionList",
      "description": "Semantic key-value list (dl/dt/dd). Preserves native HTML semantics for screen readers and SSR. Layout supports stacked (default) or inline.",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "items": {
          "description": "Optional JSON array of {term, description} — alternative to declarative <dt>/<dd> children",
          "$ref": "#/$defs/DynamicStringList"
        },
        "align": {
          "description": "Alignment for inline layout. `start` (default): term and value pack to the term column edge. `between`: term left, value right-aligned with `text-align: end`. `stretch`: value fills the remaining track width (e.g. for a `<slider-ui>` / `<select-ui>` / `<color-picker-ui>` as `<dd>` that should span the full row). Sets `justify-self: stretch` and `width: 100%` on `dd` so block-level form controls inside reach the column edge rather than shrink-wrapping to content.\n",
          "type": "string",
          "enum": [
            "start",
            "between",
            "stretch"
          ],
          "default": "start"
        },
        "component": {
          "const": "DescriptionList"
        },
        "layout": {
          "description": "stacked: term above description. inline: term and description on one row.",
          "type": "string",
          "enum": [
            "stacked",
            "inline"
          ],
          "default": "stacked"
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [],
        "category": "display",
        "composes": [],
        "events": {},
        "examples": [],
        "keywords": [
          "description list",
          "key value",
          "metadata",
          "specs",
          "properties",
          "summary",
          "details",
          "dl"
        ],
        "name": "UIDescriptionList",
        "related": [
          "List",
          "Field",
          "Section"
        ],
        "slots": {},
        "states": [
          {
            "description": "Default, ready for interaction.",
            "name": "idle"
          }
        ],
        "status": "stable",
        "synonyms": {
          "description-list": [
            "description list",
            "key value list",
            "spec list",
            "metadata list",
            "property list"
          ]
        },
        "tag": "description-list-ui",
        "tokens": {},
        "traits": [],
        "version": 1
      }
    },
    "Divider": {
      "title": "Divider",
      "description": "Horizontal or vertical divider with optional label — a semantic\nrule between content groups. Set [vertical] for column dividers\n(typically inside <row-ui>); set [label] for a labeled-rule pattern\nwhere the divider carries a short caption (e.g. \"OR\" between auth\nmethods, \"Today\" between message groups). Distinct from\n<hr data-nav-divider> (which is a CSS hook used by <nav-ui> for nav\nsection separation, not a primitive).\n",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "component": {
          "const": "Divider"
        },
        "label": {
          "description": "Center label text",
          "type": "string",
          "default": ""
        },
        "vertical": {
          "description": "Vertical orientation",
          "type": "boolean",
          "default": false
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [],
        "category": "display",
        "composes": [],
        "events": {},
        "examples": [
          {
            "description": "Settings page with profile, notifications, and appearance sections as cards.",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"Column\",\n    \"children\": [\n      \"page-title\",\n      \"profile\",\n      \"notif\",\n      \"appearance\",\n      \"save-footer\"\n    ],\n    \"gap\": \"4\"\n  },\n  {\n    \"id\": \"page-title\",\n    \"component\": \"Text\",\n    \"textContent\": \"Settings\",\n    \"variant\": \"title\"\n  },\n  {\n    \"id\": \"profile\",\n    \"component\": \"Card\",\n    \"children\": [\n      \"p-hdr\",\n      \"p-sec\"\n    ]\n  },\n  {\n    \"id\": \"p-hdr\",\n    \"component\": \"Header\",\n    \"children\": [\n      \"p-title\"\n    ]\n  },\n  {\n    \"id\": \"p-title\",\n    \"component\": \"Text\",\n    \"slot\": \"heading\",\n    \"textContent\": \"Profile\",\n    \"variant\": \"section\"\n  },\n  {\n    \"id\": \"p-sec\",\n    \"component\": \"Section\",\n    \"children\": [\n      \"p-col\"\n    ]\n  },\n  {\n    \"id\": \"p-col\",\n    \"component\": \"Column\",\n    \"children\": [\n      \"p-upload\",\n      \"p-name\",\n      \"p-email\"\n    ],\n    \"gap\": \"4\"\n  },\n  {\n    \"id\": \"p-upload\",\n    \"component\": \"Upload\",\n    \"label\": \"Profile Photo\",\n    \"accept\": \"image/*\"\n  },\n  {\n    \"id\": \"p-name\",\n    \"component\": \"Input\",\n    \"label\": \"Full Name\",\n    \"name\": \"name\",\n    \"placeholder\": \"Your name\"\n  },\n  {\n    \"id\": \"p-email\",\n    \"component\": \"Input\",\n    \"label\": \"Email\",\n    \"name\": \"email\",\n    \"type\": \"email\",\n    \"placeholder\": \"you@example.com\"\n  },\n  {\n    \"id\": \"notif\",\n    \"component\": \"Card\",\n    \"children\": [\n      \"n-hdr\",\n      \"n-sec\"\n    ]\n  },\n  {\n    \"id\": \"n-hdr\",\n    \"component\": \"Header\",\n    \"children\": [\n      \"n-title\"\n    ]\n  },\n  {\n    \"id\": \"n-title\",\n    \"component\": \"Text\",\n    \"slot\": \"heading\",\n    \"textContent\": \"Notifications\",\n    \"variant\": \"section\"\n  },\n  {\n    \"id\": \"n-sec\",\n    \"component\": \"Section\",\n    \"children\": [\n      \"n-col\"\n    ]\n  },\n  {\n    \"id\": \"n-col\",\n    \"component\": \"Column\",\n    \"children\": [\n      \"n-email\",\n      \"n-div\",\n      \"n-push\"\n    ],\n    \"gap\": \"4\"\n  },\n  {\n    \"id\": \"n-email\",\n    \"component\": \"Row\",\n    \"children\": [\n      \"n-email-label\",\n      \"n-email-toggle\"\n    ]\n  },\n  {\n    \"id\": \"n-email-label\",\n    \"component\": \"Text\",\n    \"variant\": \"body\",\n    \"textContent\": \"Email notifications\"\n  },\n  {\n    \"id\": \"n-email-toggle\",\n    \"component\": \"Toggle\",\n    \"name\": \"email-notif\",\n    \"label\": \"Email notifications\"\n  },\n  {\n    \"id\": \"n-div\",\n    \"component\": \"Divider\"\n  },\n  {\n    \"id\": \"n-push\",\n    \"component\": \"Row\",\n    \"children\": [\n      \"n-push-label\",\n      \"n-push-toggle\"\n    ]\n  },\n  {\n    \"id\": \"n-push-label\",\n    \"component\": \"Text\",\n    \"variant\": \"body\",\n    \"textContent\": \"Push notifications\"\n  },\n  {\n    \"id\": \"n-push-toggle\",\n    \"component\": \"Toggle\",\n    \"name\": \"push-notif\",\n    \"label\": \"Push notifications\"\n  },\n  {\n    \"id\": \"appearance\",\n    \"component\": \"Card\",\n    \"children\": [\n      \"a-hdr\",\n      \"a-sec\"\n    ]\n  },\n  {\n    \"id\": \"a-hdr\",\n    \"component\": \"Header\",\n    \"children\": [\n      \"a-title\"\n    ]\n  },\n  {\n    \"id\": \"a-title\",\n    \"component\": \"Text\",\n    \"slot\": \"heading\",\n    \"textContent\": \"Appearance\",\n    \"variant\": \"section\"\n  },\n  {\n    \"id\": \"a-sec\",\n    \"component\": \"Section\",\n    \"children\": [\n      \"a-col\"\n    ]\n  },\n  {\n    \"id\": \"a-col\",\n    \"component\": \"Column\",\n    \"children\": [\n      \"a-theme\",\n      \"a-density\"\n    ],\n    \"gap\": \"4\"\n  },\n  {\n    \"id\": \"a-theme\",\n    \"component\": \"Select\",\n    \"label\": \"Theme\",\n    \"name\": \"theme\",\n    \"placeholder\": \"Choose theme...\"\n  },\n  {\n    \"id\": \"a-density\",\n    \"component\": \"Select\",\n    \"label\": \"Density\",\n    \"name\": \"density\",\n    \"placeholder\": \"Choose density...\"\n  },\n  {\n    \"id\": \"save-footer\",\n    \"component\": \"Footer\",\n    \"children\": [\n      \"save-row\"\n    ]\n  },\n  {\n    \"id\": \"save-row\",\n    \"component\": \"Row\",\n    \"children\": [\n      \"cancel-btn\",\n      \"save-btn\"\n    ],\n    \"gap\": \"2\",\n    \"justify\": \"end\"\n  },\n  {\n    \"id\": \"cancel-btn\",\n    \"component\": \"Button\",\n    \"text\": \"Cancel\",\n    \"variant\": \"ghost\"\n  },\n  {\n    \"id\": \"save-btn\",\n    \"component\": \"Button\",\n    \"text\": \"Save Changes\",\n    \"variant\": \"primary\"\n  }\n]",
            "name": "settings-page"
          },
          {
            "description": "Horizontal divider with a centered label text, commonly used to separate sections or as an 'or' separator.",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"Row\",\n    \"attrs\": {\n      \"align\": \"center\",\n      \"gap\": \"md\"\n    },\n    \"children\": [\n      \"line-left\",\n      \"label\",\n      \"line-right\"\n    ]\n  },\n  {\n    \"id\": \"line-left\",\n    \"component\": \"Divider\",\n    \"attrs\": {\n      \"flex\": 1\n    }\n  },\n  {\n    \"id\": \"label\",\n    \"component\": \"Text\",\n    \"attrs\": {\n      \"variant\": \"caption\",\n      \"muted\": true\n    },\n    \"content\": \"or continue with\"\n  },\n  {\n    \"id\": \"line-right\",\n    \"component\": \"Divider\",\n    \"attrs\": {\n      \"flex\": 1\n    }\n  }\n]",
            "name": "divider-label"
          }
        ],
        "keywords": [
          "divider",
          "label",
          "layout",
          "separator",
          "spacer"
        ],
        "name": "UIDivider",
        "related": [
          "upload",
          "input",
          "toggle",
          "select",
          "button"
        ],
        "slots": {},
        "states": [
          {
            "description": "Default, ready for interaction.",
            "name": "idle"
          }
        ],
        "status": "stable",
        "synonyms": {
          "divider": [
            "divider",
            "label",
            "split"
          ],
          "label": [
            "badge",
            "tag",
            "divider",
            "label"
          ],
          "layout": [
            "split",
            "sidebar",
            "drawer",
            "tabs",
            "divider",
            "bleed"
          ],
          "separator": [
            "divider",
            "label"
          ],
          "spacer": [
            "divider",
            "label",
            "bleed"
          ]
        },
        "tag": "divider-ui",
        "tokens": {},
        "traits": [],
        "version": 1
      }
    },
    "Drawer": {
      "title": "Drawer",
      "description": "Slide-out panel anchored to a viewport edge. Uses native <dialog> for focus trap, Escape dismiss, and ::backdrop. Panel is a flex column that scrolls as a whole — the header and footer stick to the top/bottom of the panel when the body overflows. Authors can compose content with either card-ui-style bare tags (<header>, <section>, <footer>) or explicit [slot=\"header|body|footer\"] attributes; multiple <section> siblings are allowed and stack in author order between the sticky header and footer. The header activates a card-ui-aligned 3-column grid (icon | heading+description | action+close) when any direct [slot=\"icon|heading|description|action\"] child is present.",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "component": {
          "const": "Drawer"
        },
        "open": {
          "description": "Controls visibility. When false, backdrop and panel are removed from DOM.",
          "type": "boolean",
          "default": false
        },
        "permanent": {
          "description": "When true, hide close button and suppress backdrop/Escape dismiss",
          "type": "boolean",
          "default": false
        },
        "side": {
          "description": "Anchor side",
          "type": "string",
          "enum": [
            "left",
            "right",
            "top",
            "bottom"
          ],
          "default": "right"
        },
        "size": {
          "description": "Panel width/height",
          "type": "string",
          "enum": [
            "sm",
            "md",
            "lg"
          ],
          "default": "md"
        },
        "text": {
          "description": "Title text displayed in the drawer header",
          "type": "string",
          "default": ""
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [
          {
            "description": "Replacing a drawer's children wholesale — `drawer.innerHTML = '…'` — wipes the internal <dialog> part UIDrawer stamps and tracks. render() re-stamps and re-binds the dialog defensively (FEEDBACK-30), but the authored header/section/footer skeleton is still destroyed on every mutation, and any consumer-held reference to a former child is stale.",
            "right": "<drawer-ui><header>Title</header><section id=\"body\"></section></drawer-ui>\n<!-- mutate a stable inner element, never the component host -->\ndocument.getElementById('body').innerHTML = renderFields(claim);\n",
            "rule": "Never set .innerHTML on a UIElement component host. Keep <header>/<section>/<footer> as persistent children and mutate the content of a plain inner element instead.",
            "wrong": "drawer.innerHTML = `<header>${title}</header><section>${body}</section>`;\n"
          }
        ],
        "category": "container",
        "composes": [],
        "events": {
          "close": {
            "description": "Fired when the drawer closes via any path (close button, backdrop, Escape key, or programmatic `.open = false`). The `detail.reason` field distinguishes which.",
            "detail": {
              "reason": {
                "description": "`'escape'` (Escape key) / `'backdrop'` (backdrop click) / `'close-button'` ([slot=\"close\"] button click) / `'programmatic'` (consumer set `.open = false` from JS). Defaults to `'programmatic'` when no event-driven path captured a reason. Added v0.5.3 §156 per FEEDBACK-06 §2.",
                "type": "string",
                "enum": [
                  "escape",
                  "backdrop",
                  "close-button",
                  "programmatic"
                ]
              }
            }
          },
          "opened": {
            "description": "Fired after the drawer finishes its open transition — scheduled `--drawer-duration` ms after `showModal()` + `[data-open]`. Lets Playwright (and any consumer code waiting for the drawer to be fully open and interactive) listen for an event instead of guessing with a fixed timeout. Cancelled if the drawer closes before the open transition completes, so a rapid close→open never fires a stale `opened`. Added per FEEDBACK-27."
          }
        },
        "examples": [
          {
            "description": "Card with a trigger button that opens a Drawer side panel containing a form with inputs and actions.",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"Card\",\n    \"children\": [\n      \"card-hdr\",\n      \"card-body\",\n      \"drawer\"\n    ]\n  },\n  {\n    \"id\": \"card-hdr\",\n    \"component\": \"Header\",\n    \"slots\": {\n      \"heading\": \"Projects\",\n      \"description\": \"Manage your active projects.\",\n      \"action\": \"trigger-btn\"\n    }\n  },\n  {\n    \"id\": \"trigger-btn\",\n    \"component\": \"Button\",\n    \"attrs\": {\n      \"variant\": \"primary\",\n      \"icon\": \"plus\",\n      \"triggers\": \"drawer\"\n    },\n    \"content\": \"New Project\"\n  },\n  {\n    \"id\": \"card-body\",\n    \"component\": \"Section\",\n    \"children\": [\n      \"empty\"\n    ]\n  },\n  {\n    \"id\": \"empty\",\n    \"component\": \"EmptyState\",\n    \"attrs\": {\n      \"icon\": \"folder\",\n      \"heading\": \"No projects yet\",\n      \"description\": \"Create your first project to get started.\"\n    }\n  },\n  {\n    \"id\": \"drawer\",\n    \"component\": \"Drawer\",\n    \"attrs\": {\n      \"side\": \"right\",\n      \"title\": \"Create Project\"\n    },\n    \"children\": [\n      \"drawer-hdr\",\n      \"drawer-body\",\n      \"drawer-ftr\"\n    ]\n  },\n  {\n    \"id\": \"drawer-hdr\",\n    \"component\": \"Header\",\n    \"slots\": {\n      \"heading\": \"New Project\",\n      \"description\": \"Fill in the details to create a new project.\"\n    }\n  },\n  {\n    \"id\": \"drawer-body\",\n    \"component\": \"Section\",\n    \"children\": [\n      \"drawer-form\"\n    ]\n  },\n  {\n    \"id\": \"drawer-form\",\n    \"component\": \"Column\",\n    \"attrs\": {\n      \"gap\": \"md\"\n    },\n    \"children\": [\n      \"field-name\",\n      \"field-desc\",\n      \"field-category\",\n      \"field-visibility\"\n    ]\n  },\n  {\n    \"id\": \"field-name\",\n    \"component\": \"Input\",\n    \"attrs\": {\n      \"label\": \"Project Name\",\n      \"placeholder\": \"My Awesome Project\",\n      \"required\": true\n    }\n  },\n  {\n    \"id\": \"field-desc\",\n    \"component\": \"TextArea\",\n    \"attrs\": {\n      \"label\": \"Description\",\n      \"placeholder\": \"Describe your project...\",\n      \"rows\": 4\n    }\n  },\n  {\n    \"id\": \"field-category\",\n    \"component\": \"Select\",\n    \"attrs\": {\n      \"label\": \"Category\",\n      \"placeholder\": \"Select a category\",\n      \"options\": [\n        {\n          \"label\": \"Web Application\",\n          \"value\": \"web\"\n        },\n        {\n          \"label\": \"Mobile App\",\n          \"value\": \"mobile\"\n        },\n        {\n          \"label\": \"API Service\",\n          \"value\": \"api\"\n        },\n        {\n          \"label\": \"Library\",\n          \"value\": \"library\"\n        }\n      ]\n    }\n  },\n  {\n    \"id\": \"field-visibility\",\n    \"component\": \"Select\",\n    \"attrs\": {\n      \"label\": \"Visibility\",\n      \"placeholder\": \"Select visibility\",\n      \"options\": [\n        {\n          \"label\": \"Public\",\n          \"value\": \"public\"\n        },\n        {\n          \"label\": \"Private\",\n          \"value\": \"private\"\n        },\n        {\n          \"label\": \"Team Only\",\n          \"value\": \"team\"\n        }\n      ]\n    }\n  },\n  {\n    \"id\": \"drawer-ftr\",\n    \"component\": \"Footer\",\n    \"children\": [\n      \"drawer-actions\"\n    ]\n  },\n  {\n    \"id\": \"drawer-actions\",\n    \"component\": \"Row\",\n    \"attrs\": {\n      \"gap\": \"sm\"\n    },\n    \"children\": [\n      \"cancel-btn\",\n      \"create-btn\"\n    ]\n  },\n  {\n    \"id\": \"cancel-btn\",\n    \"component\": \"Button\",\n    \"attrs\": {\n      \"variant\": \"outline\"\n    },\n    \"content\": \"Cancel\"\n  },\n  {\n    \"id\": \"create-btn\",\n    \"component\": \"Button\",\n    \"attrs\": {\n      \"variant\": \"primary\"\n    },\n    \"content\": \"Create Project\"\n  }\n]",
            "name": "drawer-panel"
          }
        ],
        "keywords": [
          "drawer",
          "popup",
          "modal",
          "dialog",
          "panel",
          "hamburger",
          "sidebar",
          "layout",
          "collapse",
          "expand"
        ],
        "name": "UIDrawer",
        "related": [
          "button",
          "empty-state",
          "input",
          "text-area",
          "select"
        ],
        "slots": {
          "description": {
            "description": "Direct child of <header> — grid row 2, spans the heading + action columns. Also accepts bare <p> / <small> tags."
          },
          "action": {
            "description": "Direct child of <header> — placed in the grid's last column alongside the stamped close button. Flex container for badge + button combinations. In <footer>, self-aligns to the trailing (inline-end) edge; pair with `action-leading` for dual-cluster footers."
          },
          "action-leading": {
            "description": "Direct child of <footer> — leading (inline-start) action cluster. Used for dual-cluster footers where a destructive or secondary action sits on the opposite edge from the primary trailing cluster (e.g. Delete ↔ Cancel/Save, Back ↔ Cancel/Next). Replaces the legacy <span data-spacer> hack."
          },
          "backdrop": {
            "description": "Scrim overlay behind the drawer (stamped by the component)."
          },
          "body": {
            "description": "Scrollable content region. Accepts one or more bare <section> tags or [slot=\"body\"] elements; multi-section stacks are mounted in author order and share the panel's scroll context. [bleed] removes section padding; [padding] adds a canvas-scrim background for hero regions."
          },
          "close": {
            "description": "Close button inside the header — stamped automatically unless [permanent]. Participates in the header's action-column grid via the :is([slot=\"action\"], [slot=\"close\"]) union selector."
          },
          "footer": {
            "description": "Optional sticky action row pinned to the bottom of the panel. Only mounted if the author supplies a bare <footer> tag or [slot=\"footer\"]. Inner [slot=\"description\"] + [slot=\"action\"] triggers space-between layout, matching card-ui footer semantics."
          },
          "header": {
            "description": "Title bar — pinned to the top of the panel via position:sticky. Accepts either a bare <header> tag or [slot=\"header\"]. When any direct child has [slot=\"icon|heading|description|action\"], the header activates a card-ui-aligned 3-column grid; otherwise renders as a block with the close button appended."
          },
          "heading": {
            "description": "Direct child of <header> — grid row 1. Also accepts bare <h1>-<h6> tags. Renders as a flex container, so inline badges/metadata sit alongside the title. If the drawer has a [text] attribute and no author-supplied heading, a <span slot=\"heading\" data-stamped> is stamped with the text value."
          },
          "icon": {
            "description": "Direct child of <header> — placed in column 1 of the card-ui grid. Spans two rows when a [slot=\"description\"] sibling is present so the icon aligns with the heading."
          },
          "panel": {
            "description": "Sliding panel container (stamped by the component)."
          }
        },
        "states": [
          {
            "description": "Default, ready for interaction.",
            "name": "idle"
          }
        ],
        "status": "stable",
        "synonyms": {
          "collapse": [
            "accordion",
            "faq",
            "drawer"
          ],
          "dialog": [
            "drawer",
            "alert",
            "popover",
            "panel"
          ],
          "drawer": [
            "drawer",
            "sidebar",
            "panel"
          ],
          "expand": [
            "accordion",
            "faq",
            "drawer"
          ],
          "hamburger": [
            "nav",
            "menu",
            "sidebar",
            "drawer"
          ],
          "layout": [
            "split",
            "sidebar",
            "drawer",
            "tabs",
            "divider",
            "bleed"
          ],
          "modal": [
            "drawer",
            "alert",
            "popover",
            "panel"
          ],
          "panel": [
            "tabs",
            "drawer",
            "panel",
            "split"
          ],
          "popup": [
            "toast",
            "notification",
            "alert",
            "popover",
            "drawer"
          ],
          "sidebar": [
            "sidebar",
            "nav",
            "drawer"
          ]
        },
        "tag": "drawer-ui",
        "tokens": {},
        "traits": [],
        "version": 1
      }
    },
    "EditorCanvas": {
      "title": "EditorCanvas",
      "description": "Module-tier editor canvas surface — replaces legacy <div data-canvas>\ninside <editor-shell> per ADR-0023. Owns scroll/zoom container\nsemantics, [empty] and [focused] reflected attributes, and a stable\ntarget for the host's content rendering pipeline.\n\nSits as the central content region inside <editor-shell>, between\nthe optional <editor-sidebar slot=\"leading\"> and <editor-sidebar\nslot=\"trailing\">. Authors compose <editor-canvas-empty> as an\noptional first child for the empty state; canvas content children\n(artboards, document body, etc.) are appended either statically or\ndynamically by the host.\n",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "component": {
          "const": "EditorCanvas"
        },
        "empty": {
          "description": "Reflected — set when zero non-<editor-canvas-empty> children.\nDrives the <editor-canvas-empty> visibility via parent CSS —\nno JS toggling needed.\n",
          "type": "boolean",
          "default": true
        },
        "focused": {
          "description": "Reflected — set when canvas claims focus ownership (programmatic\n.focus() call or toolbar full-screen toggle).\n",
          "type": "boolean",
          "default": false
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [],
        "category": "container",
        "composes": [],
        "events": {},
        "examples": [],
        "keywords": [
          "editor-canvas",
          "canvas",
          "workspace",
          "artboard",
          "editor-surface"
        ],
        "name": "EditorCanvas",
        "related": [
          "EditorShell",
          "EditorCanvasEmpty",
          "EditorCanvasToolbar",
          "EditorToolbar",
          "EditorSidebar"
        ],
        "slots": {
          "default": {
            "description": "Default — canvas content (artboards, document body, blocks, etc.) plus an optional first <editor-canvas-empty> sibling for the empty state."
          }
        },
        "states": [
          {
            "description": "Default canvas mode.",
            "name": "idle"
          },
          {
            "description": "Zero content children — empty state visible.",
            "attribute": "empty",
            "name": "empty"
          },
          {
            "description": "Canvas is the focus surface.",
            "attribute": "focused",
            "name": "focused"
          }
        ],
        "status": "stable",
        "synonyms": {
          "editor-canvas": [
            "canvas",
            "workspace",
            "artboard",
            "design-surface"
          ]
        },
        "tag": "editor-canvas",
        "tokens": {},
        "traits": [],
        "version": 1
      }
    },
    "EditorCanvasEmpty": {
      "title": "EditorCanvasEmpty",
      "description": "Module-tier editor canvas empty state. CSS-only — no behavior, no\nJS. Sits as the first child of <editor-canvas> as the empty state\nplaceholder. Visibility is driven by <editor-canvas>'s [empty]\nreflected attribute via CSS (no JS toggling) — when content arrives,\nthe parent canvas loses [empty] and CSS hides this stub.\n\nReplaces ad-hoc empty-state placement inside the legacy\n<div data-canvas> per ADR-0023.\n",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "component": {
          "const": "EditorCanvasEmpty"
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [],
        "category": "feedback",
        "composes": [],
        "events": {},
        "examples": [],
        "keywords": [
          "editor-canvas-empty",
          "empty-state",
          "placeholder",
          "no-content",
          "canvas-empty"
        ],
        "name": "EditorCanvasEmpty",
        "related": [
          "EditorShell",
          "EditorCanvas",
          "EmptyState"
        ],
        "slots": {
          "default": {
            "description": "Empty state content — typically <empty-state-ui> with a \"Create new...\" prompt or onboarding affordance."
          }
        },
        "states": [
          {
            "description": "Default, visible.",
            "name": "idle"
          },
          {
            "description": "Hidden via parent <editor-canvas>:not([empty]) selector.",
            "name": "hidden"
          }
        ],
        "status": "stable",
        "synonyms": {
          "editor-canvas-empty": [
            "empty-state",
            "placeholder",
            "no-document"
          ]
        },
        "tag": "editor-canvas-empty",
        "tokens": {},
        "traits": [],
        "version": 1
      }
    },
    "EditorCanvasToolbar": {
      "title": "EditorCanvasToolbar",
      "description": "Module-tier canvas toolbar — chrome bar that sits at the top of\n<editor-canvas>, above the content body. Holds view-mode tabs\n(preview / schema / DOM, etc.), breadcrumbs, or trailing actions\nscoped to the canvas region. CSS-only — no behavior, no JS.\n\nReplaces the ad-hoc <div data-view-strip> pattern used by editor\nconsumers. Sits flush against the inside top of <editor-canvas>\nand is sticky to the canvas scroll surface, so tabs stay visible\nwhile the canvas body scrolls.\n\nDistinct from <editor-toolbar>: that is app-scope (top of\n<editor-shell>, document-wide actions), while\n<editor-canvas-toolbar> is canvas-scope (top of <editor-canvas>,\nview-mode affordances).\n",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "component": {
          "const": "EditorCanvasToolbar"
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [],
        "category": "layout",
        "composes": [],
        "events": {},
        "examples": [],
        "keywords": [
          "editor-canvas-toolbar",
          "canvas-toolbar",
          "canvas-header",
          "view-strip",
          "view-tabs",
          "canvas-tabs",
          "tab-strip"
        ],
        "name": "EditorCanvasToolbar",
        "related": [
          "EditorShell",
          "EditorCanvas",
          "EditorToolbar",
          "EditorStatusbar",
          "Tabs"
        ],
        "slots": {
          "title": {
            "description": "Optional leading title cluster."
          },
          "default": {
            "description": "Default — ad-hoc inline content (typically a <tabs-ui> with view-mode tabs, or a breadcrumb / segmented control)."
          },
          "action": {
            "description": "Trailing action cluster (view-mode toggles, overflow menu)."
          },
          "action-leading": {
            "description": "Leading action cluster (back, view switcher, breadcrumb)."
          }
        },
        "states": [
          {
            "description": "Default, the only state.",
            "name": "idle"
          }
        ],
        "status": "stable",
        "synonyms": {
          "editor-canvas-toolbar": [
            "canvas-toolbar",
            "canvas-header",
            "view-strip",
            "view-tabs",
            "tab-strip"
          ]
        },
        "tag": "editor-canvas-toolbar",
        "tokens": {},
        "traits": [],
        "version": 1
      }
    },
    "EditorShell": {
      "title": "EditorShell",
      "description": "Behavior-only editor shell for design-tool / code-editor / canvas\nlayouts. Canonical authoring shape uses cluster-namespaced bespoke\nchildren — <editor-toolbar> at the top, <editor-sidebar\nslot=\"leading|trailing\"> rails wrapping <pane-ui resizable>,\n<editor-canvas> as the central work surface (optionally containing\n<editor-canvas-toolbar> + <editor-canvas-empty>), and\n<editor-statusbar> at the bottom. The shell coordinates the family,\npropagates [focus-mode] to children's [full-screen] / [focused],\nand lets each child own its own state-as-attribute semantics per\nADR-0023.\n\nLegacy data-attribute shapes (<header>, <div data-editor-body>,\n<pane-ui data-left|data-right>, <div data-canvas>, <footer>,\n<span data-spacer>) were RETIRED in v0.4.0 per ADR-0024 and are no\nlonger recognized. Consumers must use the bespoke vocabulary.\n",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "component": {
          "const": "EditorShell"
        },
        "focusMode": {
          "description": "Reflected — when set, the shell enters distraction-free mode and\npropagates a matching [full-screen] / [focused] state to its\nbespoke children (editor-toolbar gains [full-screen], editor-canvas\ngains [focused]). Typically toggled by a [data-toolbar-action]\nbutton inside <editor-toolbar>.\n",
          "type": "boolean",
          "default": false
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [],
        "category": "container",
        "composes": [],
        "events": {},
        "examples": [],
        "keywords": [
          "editor-shell",
          "editor",
          "design-tool",
          "code-editor",
          "canvas-shell",
          "workspace-shell",
          "editing-surface"
        ],
        "name": "EditorShell",
        "related": [
          "EditorToolbar",
          "EditorCanvas",
          "EditorCanvasToolbar",
          "EditorCanvasEmpty",
          "EditorSidebar",
          "EditorStatusbar",
          "Pane",
          "AdminShell",
          "ChatShell"
        ],
        "slots": {
          "default": {
            "description": "Bespoke children compose here in document order — <editor-toolbar>, <editor-sidebar slot=\"leading\">, <editor-canvas>, <editor-sidebar slot=\"trailing\">, <editor-statusbar>. The shell's grid layout reads child tag selectors to place them; no slot= attribute is needed on the children themselves except for the leading / trailing sidebar discriminator."
          }
        },
        "states": [
          {
            "description": "Default editing mode.",
            "name": "idle"
          },
          {
            "description": "Distraction-free mode active; chrome children dim or hide per their own [full-screen] / [focused] rules.",
            "attribute": "focus-mode",
            "name": "focus-mode"
          }
        ],
        "status": "stable",
        "synonyms": {
          "editor-shell": [
            "design-tool-shell",
            "code-editor-shell",
            "workspace-shell",
            "canvas-shell"
          ]
        },
        "tag": "editor-shell",
        "tokens": {},
        "traits": [],
        "version": 1
      }
    },
    "EditorSidebar": {
      "title": "EditorSidebar",
      "description": "Module-tier editor-cluster sidebar — wraps <pane-ui resizable>\n(the primitive that owns drag) and adds [collapsed] reflected\nstate, localStorage persistence (adia-editor-sidebar-{name}),\nand .toggle() / .collapse() / .expand() public API.\n\nSits inside <editor-shell> as slot=\"leading\" (navigator pane) or\nslot=\"trailing\" (inspector pane). Mirrors the cluster-namespace\nshape from <admin-sidebar> and <chat-sidebar>, but DELEGATES to\n<pane-ui> for resize rather than reimplementing it (per\nbespoke-shell-children skill §When NOT to promote — pane primitive\nalready owns this concern).\n\nThis is the FIRST bespoke shell child that delegates rather than\nduplicates a primitive's behavior. Pattern is: cluster-namespace +\nstate-as-attribute + persistence at the bespoke tier; physical\ndrag at the primitive tier.\n",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "collapsed": {
          "description": "Reflected — set when inner <pane-ui> width is at or below 96px snap threshold.",
          "type": "boolean",
          "default": false
        },
        "collapsible": {
          "description": "Reflected CSS-state marker — declares this sidebar's collapse\naffordance is exposed to authors (matching the <admin-sidebar>\nconvention). The .toggle() / .collapse() / .expand() public API\nis always callable; [collapsible] is the attribute consumers\nkey CSS rules off (e.g. showing a toggle button when present).\nSet on the canonical demos in editor-sidebar.examples.html.\n",
          "type": "boolean",
          "default": false
        },
        "component": {
          "const": "EditorSidebar"
        },
        "name": {
          "description": "Alias for [persist]; kept for v0.4.x back-compat. Deprecated —\nnew code should use [persist]. If both are set, [persist] wins.\n",
          "type": "string",
          "default": ""
        },
        "persist": {
          "description": "localStorage key suffix. When set, the sidebar persists its pane\nwidth across reloads under `adia-editor-sidebar-{persist}`.\nPreferred over the [name] alias kept for v0.4.x back-compat.\nDefaults to [name] then [slot] if neither set.\n",
          "type": "string",
          "default": ""
        },
        "resizing": {
          "description": "Reflected — set during an active pointer-drag of the pane's\nresize handle. Used to disable transitions and visual treatments\nthat would feel laggy during drag.\n",
          "type": "boolean",
          "default": false
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [],
        "category": "layout",
        "composes": [],
        "events": {
          "sidebar-toggle": {
            "description": "Bubbles when .toggle() / .collapse() / .expand() is called.",
            "detail": {
              "expanded": "boolean",
              "name": "string"
            }
          }
        },
        "examples": [],
        "keywords": [
          "editor-sidebar",
          "navigator-pane",
          "inspector-pane",
          "editor-rail",
          "sidebar",
          "leading",
          "trailing"
        ],
        "name": "EditorSidebar",
        "related": [
          "EditorShell",
          "EditorCanvas",
          "Pane",
          "AdminSidebar",
          "ChatSidebar"
        ],
        "slots": {
          "default": {
            "description": "Default — the inner <pane-ui resizable> wrapper. Authors compose header / section / footer inside the pane as usual."
          }
        },
        "states": [
          {
            "description": "Default expanded state.",
            "name": "idle"
          },
          {
            "description": "Inner pane is at or below the snap threshold.",
            "attribute": "collapsed",
            "name": "collapsed"
          }
        ],
        "status": "stable",
        "synonyms": {
          "editor-sidebar": [
            "navigator",
            "inspector",
            "editor-rail",
            "side-panel"
          ]
        },
        "tag": "editor-sidebar",
        "tokens": {},
        "traits": [],
        "version": 1
      }
    },
    "EditorStatusbar": {
      "title": "EditorStatusbar",
      "description": "Module-tier editor statusbar — bottom chrome bar inside\n<editor-shell>. CSS-only, no behavior, no JS. Holds save/sync\nstate, zoom indicator, cursor position, and tertiary actions\nvia slot vocabulary.\n\nReplaces the legacy <footer> with positional content per ADR-0023.\n",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "component": {
          "const": "EditorStatusbar"
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [],
        "category": "layout",
        "composes": [],
        "events": {},
        "examples": [],
        "keywords": [
          "editor-statusbar",
          "statusbar",
          "bottom-bar",
          "editor-footer"
        ],
        "name": "EditorStatusbar",
        "related": [
          "EditorShell",
          "EditorToolbar",
          "EditorCanvas"
        ],
        "slots": {
          "default": {
            "description": "Default — ad-hoc inline content (legacy positional layout)."
          },
          "action": {
            "description": "Trailing action cluster (e.g., toggle full-screen)."
          },
          "cursor": {
            "description": "Cursor position / selection indicator."
          },
          "status": {
            "description": "Save/sync state indicator."
          },
          "zoom": {
            "description": "Zoom level indicator."
          }
        },
        "states": [
          {
            "description": "Default, the only state.",
            "name": "idle"
          }
        ],
        "status": "stable",
        "synonyms": {
          "editor-statusbar": [
            "statusbar",
            "footer-bar",
            "bottom-bar"
          ]
        },
        "tag": "editor-statusbar",
        "tokens": {},
        "traits": [],
        "version": 1
      }
    },
    "EditorToolbar": {
      "title": "EditorToolbar",
      "description": "Module-tier editor toolbar — replaces legacy <header> chrome bar\ninside <editor-shell> per ADR-0023. Owns the [full-screen] reflected\nattribute (set when host enters focus mode), click-bubble for\n[data-toolbar-action] buttons, and slot vocabulary routing.\n\nSits at the top of <editor-shell>. Authors compose actions + status\nvia slot vocabulary. Replaces the legacy <header> chrome bar per\nADR-0023; the legacy shape was retired in v0.4.0 per ADR-0024 and\nis no longer recognized.\n",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "component": {
          "const": "EditorToolbar"
        },
        "fullScreen": {
          "description": "Reflected — set when editor is in distraction-free / focus mode.",
          "type": "boolean",
          "default": false
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [],
        "category": "layout",
        "composes": [],
        "events": {
          "toolbar-action": {
            "description": "Bubbles when a child element with [data-toolbar-action] is clicked. Detail carries the action name from the clicked element's attribute.",
            "detail": {
              "name": "string"
            }
          }
        },
        "examples": [],
        "keywords": [
          "editor-toolbar",
          "editor-titlebar",
          "editor-chrome",
          "app-header",
          "editor-actions"
        ],
        "name": "EditorToolbar",
        "related": [
          "EditorShell",
          "EditorCanvas",
          "EditorSidebar",
          "EditorStatusbar"
        ],
        "slots": {
          "title": {
            "description": "Editor / document title cluster."
          },
          "default": {
            "description": "Default — ad-hoc inline content (legacy positional layout)."
          },
          "action": {
            "description": "Trailing action cluster (settings, share, more)."
          },
          "action-leading": {
            "description": "Leading action cluster (back, switcher, undo/redo)."
          },
          "status": {
            "description": "Status indicator (saving, dirty, synced, etc.)."
          }
        },
        "states": [
          {
            "description": "Default editor mode.",
            "name": "idle"
          },
          {
            "description": "Distraction-free / focus mode active.",
            "attribute": "full-screen",
            "name": "full-screen"
          }
        ],
        "status": "stable",
        "synonyms": {
          "editor-toolbar": [
            "editor-header",
            "app-header",
            "navbar",
            "titlebar"
          ]
        },
        "tag": "editor-toolbar",
        "tokens": {},
        "traits": [],
        "version": 1
      }
    },
    "Embed": {
      "title": "Embed",
      "description": "Responsive sandboxed <iframe> wrapper — renders external content at\na constrained [aspect] ratio with optional [width] / [height] override.\nThe iframe is created in light DOM with safe sandbox attributes;\nauthors do NOT slot an <iframe> directly. Use for YouTube / Vimeo /\nFigma embeds in articles, marketing pages, or chat responses; not\nfor arbitrary cross-origin app integrations (use the platform's own\nSDK / portal instead).\n",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "aspect": {
          "description": "CSS aspect-ratio (e.g. 16/9)",
          "type": "string",
          "default": ""
        },
        "component": {
          "const": "Embed"
        },
        "height": {
          "description": "Iframe height. Plain numbers treated as pixels.",
          "type": "string",
          "default": "400"
        },
        "src": {
          "description": "URL to load in the iframe",
          "type": "string",
          "default": ""
        },
        "width": {
          "description": "Iframe width. Any CSS width value.",
          "type": "string",
          "default": "100%"
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [],
        "category": "agent",
        "composes": [],
        "events": {},
        "examples": [
          {
            "description": "Card wrapping an embedded iframe for video or map content with a descriptive header.",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"Card\",\n    \"children\": [\n      \"hdr\",\n      \"body\",\n      \"caption-sec\"\n    ]\n  },\n  {\n    \"id\": \"hdr\",\n    \"component\": \"Header\",\n    \"slots\": {\n      \"heading\": \"Product Demo\",\n      \"description\": \"Watch a 3-minute walkthrough of our core features.\"\n    }\n  },\n  {\n    \"id\": \"body\",\n    \"component\": \"Section\",\n    \"children\": [\n      \"video\"\n    ]\n  },\n  {\n    \"id\": \"video\",\n    \"component\": \"Embed\",\n    \"attrs\": {\n      \"src\": \"https://www.youtube.com/embed/dQw4w9WgXcQ\",\n      \"type\": \"video\",\n      \"aspectRatio\": \"16:9\",\n      \"title\": \"Product demo video\",\n      \"allowFullscreen\": true\n    }\n  },\n  {\n    \"id\": \"caption-sec\",\n    \"component\": \"Section\",\n    \"children\": [\n      \"caption\"\n    ]\n  },\n  {\n    \"id\": \"caption\",\n    \"component\": \"Text\",\n    \"attrs\": {\n      \"variant\": \"caption\",\n      \"muted\": true\n    },\n    \"content\": \"Duration: 3:24 · Last updated January 2025\"\n  }\n]",
            "name": "embed-content"
          },
          {
            "description": "Video player with embed area, seek slider, and playback controls.",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"Card\",\n    \"children\": [\n      \"vid\",\n      \"controls\"\n    ]\n  },\n  {\n    \"id\": \"vid\",\n    \"component\": \"Section\",\n    \"children\": [\n      \"embed\"\n    ]\n  },\n  {\n    \"id\": \"embed\",\n    \"component\": \"Embed\",\n    \"src\": \"https://example.com/video\",\n    \"aspect\": \"16/9\"\n  },\n  {\n    \"id\": \"controls\",\n    \"component\": \"Section\",\n    \"children\": [\n      \"seek\",\n      \"btns\"\n    ]\n  },\n  {\n    \"id\": \"seek\",\n    \"component\": \"Slider\",\n    \"value\": 25,\n    \"max\": 100\n  },\n  {\n    \"id\": \"btns\",\n    \"component\": \"Row\",\n    \"children\": [\n      \"play\",\n      \"vol\",\n      \"time\"\n    ],\n    \"justify\": \"between\",\n    \"align\": \"center\"\n  },\n  {\n    \"id\": \"play\",\n    \"component\": \"Button\",\n    \"icon\": \"play\",\n    \"variant\": \"ghost\"\n  },\n  {\n    \"id\": \"vol\",\n    \"component\": \"Button\",\n    \"icon\": \"speaker-high\",\n    \"variant\": \"ghost\"\n  },\n  {\n    \"id\": \"time\",\n    \"component\": \"Text\",\n    \"variant\": \"caption\",\n    \"textContent\": \"2:30 / 10:00\"\n  }\n]",
            "name": "video-player"
          }
        ],
        "keywords": [
          "embed",
          "media",
          "video",
          "youtube",
          "vimeo",
          "stream",
          "integration",
          "iframe",
          "widget",
          "third-party"
        ],
        "name": "UIEmbed",
        "related": [
          "slider",
          "button"
        ],
        "slots": {
          "iframe": {
            "description": "Sandboxed <iframe> element (allow-scripts allow-same-origin)"
          }
        },
        "states": [
          {
            "description": "Default, ready for interaction.",
            "name": "idle"
          }
        ],
        "status": "stable",
        "synonyms": {
          "embed": [
            "embed",
            "content",
            "video",
            "iframe"
          ],
          "iframe": [
            "embed",
            "content"
          ],
          "integration": [
            "api",
            "key",
            "embed",
            "data",
            "import"
          ],
          "media": [
            "image",
            "video",
            "music",
            "player",
            "gallery",
            "embed"
          ],
          "stream": [
            "video",
            "player",
            "streaming",
            "embed"
          ],
          "third-party": [
            "embed",
            "content"
          ],
          "video": [
            "video",
            "player",
            "embed"
          ],
          "vimeo": [
            "video",
            "player",
            "embed"
          ],
          "widget": [
            "embed",
            "weather",
            "widget"
          ],
          "youtube": [
            "video",
            "player",
            "embed"
          ]
        },
        "tag": "embed-ui",
        "tokens": {},
        "traits": [],
        "version": 1
      }
    },
    "EmptyState": {
      "title": "EmptyState",
      "description": "Placeholder for empty views with icon, heading, description, and action slot. Renders centered inside lists, tables, panes, or cards when no data is present. Use as a zero-state inside containers; for app-loading shells use <skeleton-ui> instead.",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "description": {
          "description": "Secondary descriptive text below the heading",
          "type": "string",
          "default": ""
        },
        "component": {
          "const": "EmptyState"
        },
        "heading": {
          "description": "Primary heading text. Uses 'heading' instead of 'title' to avoid native tooltip.",
          "type": "string",
          "default": ""
        },
        "icon": {
          "description": "Icon name displayed above the heading",
          "type": "string",
          "default": ""
        },
        "minimal": {
          "description": "§223 (v0.5.9). Single-line muted layout — drops centered-column chrome\n(no vertical padding, no row-stack, no icon-size bump). Useful for\ninline empty-table-row / inline empty-list / placeholder cells where\nthe full-canvas placeholder is too prominent.",
          "type": "boolean",
          "default": false
        },
        "variant": {
          "description": "Semantic color variant. Use `danger` or `warning` for full-section error states where the data cannot be shown (API failure, permission error) — the centered layout mirrors the empty state but uses danger/ warning tones. Leave unset (default) for the canonical zero-data case.",
          "type": "string",
          "enum": [
            "default",
            "danger",
            "warning"
          ],
          "default": "default"
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [],
        "category": "display",
        "composes": [
          "icon-ui"
        ],
        "events": {},
        "examples": [
          {
            "description": "Empty state component with icon, heading, description, and call-to-action button.",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"EmptyState\",\n    \"children\": [\n      \"content\"\n    ]\n  },\n  {\n    \"id\": \"content\",\n    \"component\": \"Column\",\n    \"align\": \"center\",\n    \"gap\": \"3\",\n    \"children\": [\n      \"icon\",\n      \"heading\",\n      \"desc\",\n      \"cta\"\n    ]\n  },\n  {\n    \"id\": \"icon\",\n    \"component\": \"Icon\",\n    \"name\": \"inbox\",\n    \"size\": \"xl\"\n  },\n  {\n    \"id\": \"heading\",\n    \"component\": \"Text\",\n    \"variant\": \"heading\",\n    \"textContent\": \"No items yet\"\n  },\n  {\n    \"id\": \"desc\",\n    \"component\": \"Text\",\n    \"variant\": \"body\",\n    \"textContent\": \"Get started by creating your first item. It only takes a moment.\"\n  },\n  {\n    \"id\": \"cta\",\n    \"component\": \"Button\",\n    \"text\": \"Create Item\",\n    \"icon\": \"plus\",\n    \"variant\": \"primary\"\n  }\n]",
            "name": "empty-state"
          },
          {
            "description": "Card with a trigger button that opens a Drawer side panel containing a form with inputs and actions.",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"Card\",\n    \"children\": [\n      \"card-hdr\",\n      \"card-body\",\n      \"drawer\"\n    ]\n  },\n  {\n    \"id\": \"card-hdr\",\n    \"component\": \"Header\",\n    \"slots\": {\n      \"heading\": \"Projects\",\n      \"description\": \"Manage your active projects.\",\n      \"action\": \"trigger-btn\"\n    }\n  },\n  {\n    \"id\": \"trigger-btn\",\n    \"component\": \"Button\",\n    \"attrs\": {\n      \"variant\": \"primary\",\n      \"icon\": \"plus\",\n      \"triggers\": \"drawer\"\n    },\n    \"content\": \"New Project\"\n  },\n  {\n    \"id\": \"card-body\",\n    \"component\": \"Section\",\n    \"children\": [\n      \"empty\"\n    ]\n  },\n  {\n    \"id\": \"empty\",\n    \"component\": \"EmptyState\",\n    \"attrs\": {\n      \"icon\": \"folder\",\n      \"heading\": \"No projects yet\",\n      \"description\": \"Create your first project to get started.\"\n    }\n  },\n  {\n    \"id\": \"drawer\",\n    \"component\": \"Drawer\",\n    \"attrs\": {\n      \"side\": \"right\",\n      \"title\": \"Create Project\"\n    },\n    \"children\": [\n      \"drawer-hdr\",\n      \"drawer-body\",\n      \"drawer-ftr\"\n    ]\n  },\n  {\n    \"id\": \"drawer-hdr\",\n    \"component\": \"Header\",\n    \"slots\": {\n      \"heading\": \"New Project\",\n      \"description\": \"Fill in the details to create a new project.\"\n    }\n  },\n  {\n    \"id\": \"drawer-body\",\n    \"component\": \"Section\",\n    \"children\": [\n      \"drawer-form\"\n    ]\n  },\n  {\n    \"id\": \"drawer-form\",\n    \"component\": \"Column\",\n    \"attrs\": {\n      \"gap\": \"md\"\n    },\n    \"children\": [\n      \"field-name\",\n      \"field-desc\",\n      \"field-category\",\n      \"field-visibility\"\n    ]\n  },\n  {\n    \"id\": \"field-name\",\n    \"component\": \"Input\",\n    \"attrs\": {\n      \"label\": \"Project Name\",\n      \"placeholder\": \"My Awesome Project\",\n      \"required\": true\n    }\n  },\n  {\n    \"id\": \"field-desc\",\n    \"component\": \"TextArea\",\n    \"attrs\": {\n      \"label\": \"Description\",\n      \"placeholder\": \"Describe your project...\",\n      \"rows\": 4\n    }\n  },\n  {\n    \"id\": \"field-category\",\n    \"component\": \"Select\",\n    \"attrs\": {\n      \"label\": \"Category\",\n      \"placeholder\": \"Select a category\",\n      \"options\": [\n        {\n          \"label\": \"Web Application\",\n          \"value\": \"web\"\n        },\n        {\n          \"label\": \"Mobile App\",\n          \"value\": \"mobile\"\n        },\n        {\n          \"label\": \"API Service\",\n          \"value\": \"api\"\n        },\n        {\n          \"label\": \"Library\",\n          \"value\": \"library\"\n        }\n      ]\n    }\n  },\n  {\n    \"id\": \"field-visibility\",\n    \"component\": \"Select\",\n    \"attrs\": {\n      \"label\": \"Visibility\",\n      \"placeholder\": \"Select visibility\",\n      \"options\": [\n        {\n          \"label\": \"Public\",\n          \"value\": \"public\"\n        },\n        {\n          \"label\": \"Private\",\n          \"value\": \"private\"\n        },\n        {\n          \"label\": \"Team Only\",\n          \"value\": \"team\"\n        }\n      ]\n    }\n  },\n  {\n    \"id\": \"drawer-ftr\",\n    \"component\": \"Footer\",\n    \"children\": [\n      \"drawer-actions\"\n    ]\n  },\n  {\n    \"id\": \"drawer-actions\",\n    \"component\": \"Row\",\n    \"attrs\": {\n      \"gap\": \"sm\"\n    },\n    \"children\": [\n      \"cancel-btn\",\n      \"create-btn\"\n    ]\n  },\n  {\n    \"id\": \"cancel-btn\",\n    \"component\": \"Button\",\n    \"attrs\": {\n      \"variant\": \"outline\"\n    },\n    \"content\": \"Cancel\"\n  },\n  {\n    \"id\": \"create-btn\",\n    \"component\": \"Button\",\n    \"attrs\": {\n      \"variant\": \"primary\"\n    },\n    \"content\": \"Create Project\"\n  }\n]",
            "name": "drawer-panel"
          }
        ],
        "keywords": [
          "emptystate",
          "empty-state",
          "empty",
          "state"
        ],
        "name": "UIEmptyState",
        "related": [
          "button",
          "drawer",
          "input",
          "text-area",
          "select"
        ],
        "slots": {
          "description": {
            "description": "Override slot for the description text. Use for multi-paragraph or richly-marked-up explanatory copy."
          },
          "action": {
            "description": "User-provided action element (e.g. button) displayed below the description"
          },
          "heading": {
            "description": "Override slot for the heading text. Use when richer markup than the plain [heading] attribute is needed (line breaks, inline links, bold emphasis)."
          },
          "icon": {
            "description": "Override slot for the [icon] glyph. Use when the attribute-driven Phosphor icon isn't enough (e.g., custom SVG, illustration, or a styled icon-ui with non-default weight). Mutually exclusive with [icon]."
          }
        },
        "states": [
          {
            "description": "Default, ready for interaction.",
            "name": "idle"
          }
        ],
        "status": "stable",
        "synonyms": {
          "empty-state": [
            "zero-state",
            "no-data",
            "placeholder",
            "empty"
          ]
        },
        "tag": "empty-state-ui",
        "tokens": {
          "--empty-state-action-mt": {
            "description": "Top margin for the action slot"
          },
          "--empty-state-desc-fg": {
            "description": "Description text color"
          },
          "--empty-state-desc-size": {
            "description": "Description font size"
          },
          "--empty-state-gap": {
            "description": "Gap between stacked elements"
          },
          "--empty-state-heading-fg": {
            "description": "Heading text color"
          },
          "--empty-state-heading-size": {
            "description": "Heading font size"
          },
          "--empty-state-heading-weight": {
            "description": "Heading font weight"
          },
          "--empty-state-icon-fg": {
            "description": "Icon color"
          },
          "--empty-state-icon-size": {
            "description": "Icon size"
          },
          "--empty-state-px": {
            "description": "Horizontal padding"
          },
          "--empty-state-py": {
            "description": "Vertical padding"
          }
        },
        "traits": [],
        "version": 1
      }
    },
    "Feed": {
      "title": "Feed",
      "description": "Shared top-layer feed channel. Per docs/specs/feed-channel.md (SPEC-FEED-CHANNEL-001). Per-position singletons mounted lazily into document.body via Popover API; consumers post via the static API (`UIFeed.post()`) or the global 'feed' CustomEvent.",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "component": {
          "const": "Feed"
        },
        "max": {
          "description": "Cap on simultaneously visible items per lane",
          "type": "number",
          "default": 5
        },
        "position": {
          "description": "Lane the feed renders into",
          "type": "string",
          "enum": [
            "top-left",
            "top-center",
            "top-right",
            "bottom-left",
            "bottom-center",
            "bottom-right",
            "inline"
          ],
          "default": "bottom-right"
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [],
        "category": "container",
        "composes": [
          "button-ui",
          "feed-item-ui"
        ],
        "events": {
          "close": {
            "description": "Fired on per-item dismissal (manual close, swipe, or auto-timeout). Bubbles."
          }
        },
        "examples": [],
        "keywords": [
          "feed",
          "notification-feed",
          "activity-stream",
          "toast-stack",
          "alert-stack",
          "snackbar-stack",
          "notification-channel"
        ],
        "name": "UIFeedContainer",
        "related": [
          "FeedItem",
          "Toast",
          "Alert"
        ],
        "slots": {},
        "states": {},
        "status": "stable",
        "synonyms": {
          "feed": [
            "notification-feed",
            "toast-feed",
            "alert-feed",
            "activity-feed",
            "snackbar-stack"
          ]
        },
        "tag": "feed-ui",
        "tokens": {},
        "traits": [],
        "version": 1
      }
    },
    "FeedItem": {
      "title": "FeedItem",
      "description": "Atomic feed entry inside a `<feed-ui>` lane. Three dismiss policies are inferred from the prop shape — auto-fade (duration > 0 + no action), sticky-dismissible (duration null/0), action-required (duration null/0 + action; future phase). Posted via `UIFeed.post()` rather than authored directly.",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "action": {
          "description": "Label of an inline action button (the \"deep-link\" / \"undo\" pattern).\nPair with `onAction` callback in `UIFeed.post()` — click invokes the\ncallback then auto-dismisses. Empty string renders no action button.\n",
          "type": "string",
          "default": ""
        },
        "component": {
          "const": "FeedItem"
        },
        "dismissible": {
          "description": "Render an x close button (default true for sticky, false for auto-fade)",
          "type": "boolean",
          "default": false
        },
        "duration": {
          "description": "Auto-fade timer in ms; null/0 = sticky (requires user input)",
          "type": "number",
          "default": 4000
        },
        "heading": {
          "description": "Optional emphasis line above text",
          "type": "string",
          "default": ""
        },
        "icon": {
          "description": "Optional leading icon name",
          "type": "string",
          "default": ""
        },
        "text": {
          "description": "Body copy",
          "type": "string",
          "default": ""
        },
        "variant": {
          "description": "Semantic variant",
          "type": "string",
          "enum": [
            "default",
            "info",
            "success",
            "warning",
            "danger"
          ],
          "default": "default"
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [],
        "category": "feedback",
        "composes": [],
        "events": {
          "close": {
            "description": "Fired after the item finishes its exit animation"
          }
        },
        "examples": [],
        "keywords": [
          "feed-item",
          "notification",
          "toast-row",
          "alert-row",
          "feed-entry",
          "notification-card"
        ],
        "name": "UIFeedItem",
        "related": [
          "Feed",
          "Toast",
          "Alert"
        ],
        "slots": {
          "body": {
            "description": "Default content slot (also accepts the `text` / `heading` props)"
          }
        },
        "states": {},
        "status": "stable",
        "synonyms": {
          "feed-item": [
            "notification-row",
            "toast-entry",
            "feed-row",
            "alert-item"
          ]
        },
        "tag": "feed-item-ui",
        "tokens": {},
        "traits": [],
        "version": 1
      }
    },
    "Field": {
      "title": "Field",
      "description": "Labeled field wrapper. Composes a <label for=\"…\"> with a form control (input-ui, select-ui, textarea-ui, etc.) placed in the default slot, plus optional [slot=\"trailing\"] and [slot=\"action\"] regions. Auto-mints an id on the slotted control when missing so clicking the label focuses the control — an accessibility upgrade over setting label=\"…\" on the control directly, which has no [for] binding. Two layouts — stacked (default) and inline (the `inline` mode attribute collapses everything to a single row).",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "required": {
          "description": "Renders a \"*\" marker on the label. Does not itself enforce validation — the slotted control's own `required` attr does that; this is a visual signal only.",
          "type": "boolean",
          "default": false
        },
        "align": {
          "description": "Label alignment within its grid area. `start` (default) — label is left-aligned (leading edge). `end` — label is right-aligned (trailing edge), useful when stacking several `<field-ui>` in a form and aligning labels flush to the control column for better scanability.",
          "type": "string",
          "enum": [
            "start",
            "end"
          ],
          "default": "start"
        },
        "component": {
          "const": "Field"
        },
        "hint": {
          "description": "Help text rendered below the control in caption style. Wired into the slotted control's aria-describedby so screen readers announce it. Suppressed when `error` is set.",
          "type": "string",
          "default": ""
        },
        "inline": {
          "description": "Lay out label, trailing, control, and action on a single row instead of the stacked default (mode attribute — changes grid geometry, not tokens). Hint/error still render on their own row below.",
          "type": "boolean",
          "default": false
        },
        "label": {
          "description": "Label text rendered in the label row.",
          "type": "string",
          "default": ""
        }
      },
      "required": [
        "component",
        "label"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [
          {
            "description": "Wrapping a check-ui (or switch-ui / radio-ui / toggle-ui) in field-ui. The widget already carries its own visible [label] via the CSS attr() pattern; field-ui adds a redundant label row and the inline-mode `justify-self: end` rule for compact controls pushes the widget to the right edge of the row, breaking the expected \"checkbox-left, label-right\" consent-row layout.",
            "right": "<check-ui label=\"I agree to the Terms of Service\"></check-ui>\n",
            "rule": "Small self-labeling widgets MUST NOT be wrapped in field-ui.",
            "wrong": "<field-ui inline>\n  <check-ui label=\"I agree to the Terms of Service\"></check-ui>\n</field-ui>\n"
          },
          {
            "description": "Using field-ui[inline] around a switch-ui to build a settings row. The settings-row layout (label-left, control-right) IS the switch-ui's own [label] rendering — field-ui adds no value and breaks the layout via the `justify-self: end` rule for compact widgets.",
            "right": "<switch-ui label=\"Email notifications\"></switch-ui>\n",
            "rule": "Use the widget's own [label] attribute for settings + consent rows. field-ui is for wide-control rows only.",
            "wrong": "<field-ui inline label=\"Email notifications\">\n  <switch-ui></switch-ui>\n</field-ui>\n"
          }
        ],
        "category": "form",
        "composes": [],
        "events": {},
        "examples": [
          {
            "description": "A simple stacked email field with a trailing \"Required\" hint and a clear-button action adjacent to the input.",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"Field\",\n    \"label\": \"Email\",\n    \"children\": [\"email\", \"hint\", \"clear\"]\n  },\n  { \"id\": \"email\", \"component\": \"Input\", \"type\": \"email\", \"value\": \"you@example.com\" },\n  { \"id\": \"hint\",  \"component\": \"Text\",  \"slot\": \"trailing\", \"text\": \"Required\" },\n  { \"id\": \"clear\", \"component\": \"Button\", \"slot\": \"action\", \"icon\": \"x\", \"variant\": \"ghost\" }\n]",
            "name": "stacked-email-field"
          },
          {
            "description": "An inline search field — label beside the input, with a trailing keyboard-shortcut hint.",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"Field\",\n    \"label\": \"Search\",\n    \"inline\": true,\n    \"children\": [\"q\", \"kbd\"]\n  },\n  { \"id\": \"q\",   \"component\": \"Input\", \"type\": \"search\", \"placeholder\": \"Type…\" },\n  { \"id\": \"kbd\", \"component\": \"Kbd\",   \"slot\": \"trailing\", \"text\": \"⌘K\" }\n]",
            "name": "inline-search-field"
          }
        ],
        "keywords": [
          "field",
          "form",
          "label",
          "input",
          "wrapper"
        ],
        "name": "UIField",
        "related": [
          "input",
          "select",
          "textarea",
          "slider",
          "range"
        ],
        "slots": {
          "default": {
            "description": "The form control — a WIDE control like input-ui, select-ui, textarea-ui, slider-ui, range-ui, calendar-picker-ui, color-picker-ui, upload-ui, otp-input-ui. Auto-id'd for the label's [for] binding.\nDO NOT wrap small self-labeling widgets here. check-ui, switch-ui, radio-ui, toggle-ui all carry their own [label] attribute that renders inline next to the control — wrapping them in field-ui produces broken layouts (settings-row `justify-self: end` rule pushes the control to the trailing edge, away from the label that field-ui stamps; the widget's own label then renders again on the right, creating a doubled / right-justified affordance). See anti_patterns below for the canonical alternatives."
          },
          "action": {
            "description": "Button adjacent to the control for inline actions (clear, reset, help popover)."
          },
          "error": {
            "description": "Override slot for error markup richer than the plain [error] attribute string. Rendered below the control with danger-text styling. Mutually exclusive with [error]."
          },
          "hint": {
            "description": "Override slot for hint markup richer than the plain [hint] attribute string (inline links, code spans, abbreviations). Rendered below the control at body-subtle typography. Mutually exclusive with [hint]."
          },
          "trailing": {
            "description": "Secondary text or badge aligned with the label in the stacked layout (right-aligned) or between label and control in the inline layout."
          }
        },
        "states": [
          {
            "description": "Default, ready for interaction.",
            "name": "idle"
          }
        ],
        "status": "stable",
        "synonyms": {
          "form": [
            "field",
            "label",
            "input"
          ],
          "label": [
            "field",
            "form"
          ]
        },
        "tag": "field-ui",
        "tokens": {
          "--field-error-color": {
            "description": "Error text color (also drives the required-marker color)."
          },
          "--field-error-size": {
            "description": "Error text size."
          },
          "--field-gap": {
            "description": "Gap between rows/cells of the field grid."
          },
          "--field-hint-color": {
            "description": "Hint text color."
          },
          "--field-hint-size": {
            "description": "Hint text size."
          },
          "--field-label-color": {
            "description": "Label foreground color."
          },
          "--field-label-size": {
            "description": "Label font size."
          },
          "--field-label-weight": {
            "description": "Label font weight."
          },
          "--field-required-color": {
            "description": "Color of the `*` required marker on the label."
          },
          "--field-trailing-color": {
            "description": "Trailing text color."
          },
          "--field-trailing-size": {
            "description": "Trailing text size."
          }
        },
        "traits": [],
        "version": 1
      }
    },
    "Fields": {
      "title": "Fields",
      "description": "Container for a group of <field-ui> children, laid out on a shared 6-column grid. Each <field-ui> spans the full row by default; opt into a narrower span via [rows=\"1..6\"]. Setting [inline] on the host propagates the inline mode to every direct <field-ui> child so a whole sub-form can switch label-position without per-field edits. The grid alignment lets siblings on the same row line up cleanly — consistent label columns + consistent control columns — without the wrap-flex jitter of <row-ui wrap>.",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "columns": {
          "description": "Number of grid columns the row uses. Defaults to 6 — common multiples (1/2/3/6) divide cleanly. <field-ui rows=\"N\"> spans `N` of these columns. Override per-instance for tighter 4-column or wider 12-column compositions.",
          "type": "number",
          "default": 6
        },
        "component": {
          "const": "Fields"
        },
        "inline": {
          "description": "Propagate the inline layout mode to every direct <field-ui> child. Equivalent to authoring `inline` on each child but drives the whole group from one place. Toggle is reactive — flipping the attribute on the host re-syncs all children.",
          "type": "boolean",
          "default": false
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [
          {
            "description": "Don't wrap <field-ui> children in <row-ui wrap> when grid alignment is desired. row-ui is flex-wrap, which lets each field size to its content — labels and controls won't share a column with siblings.",
            "severity": "high"
          },
          {
            "description": "Don't set `inline` on individual <field-ui> children when the whole group should switch — set it on the parent <fields-ui> and let the propagation handle every child.",
            "severity": "medium"
          }
        ],
        "category": "form",
        "composes": [
          "field-ui"
        ],
        "events": {},
        "examples": [
          {
            "description": "A 3-up stacked field row — Status / Priority / Group — each taking 2 of 6 columns. Equivalent to a Bootstrap \"col-md-4\" pattern (12-col grid, span 4) but with chat-ui's 6-col default.",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"Fields\",\n    \"children\": [\"status\", \"priority\", \"group\"]\n  },\n  { \"id\": \"status\",   \"component\": \"Field\", \"label\": \"Status\",   \"rows\": 2, \"children\": [\"status-sel\"] },\n  { \"id\": \"priority\", \"component\": \"Field\", \"label\": \"Priority\", \"rows\": 2, \"children\": [\"priority-sel\"] },\n  { \"id\": \"group\",    \"component\": \"Field\", \"label\": \"Group\",    \"rows\": 2, \"children\": [\"group-sel\"] },\n  { \"id\": \"status-sel\",   \"component\": \"Select\", \"value\": \"todo\" },\n  { \"id\": \"priority-sel\", \"component\": \"Select\", \"value\": \"0\" },\n  { \"id\": \"group-sel\",    \"component\": \"Select\", \"value\": \"\" }\n]",
            "name": "three-up-stacked"
          },
          {
            "description": "An inline form — every field renders label-beside-control. Single [inline] on the host drives all children.",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"Fields\",\n    \"inline\": true,\n    \"children\": [\"q\", \"kind\"]\n  },\n  { \"id\": \"q\",    \"component\": \"Field\", \"label\": \"Search\", \"children\": [\"q-input\"] },\n  { \"id\": \"kind\", \"component\": \"Field\", \"label\": \"Kind\",   \"children\": [\"kind-sel\"] },\n  { \"id\": \"q-input\", \"component\": \"Input\", \"type\": \"search\" },\n  { \"id\": \"kind-sel\", \"component\": \"Select\", \"value\": \"all\" }\n]",
            "name": "inline-search-form"
          }
        ],
        "keywords": [
          "fields",
          "form",
          "grid",
          "layout",
          "group"
        ],
        "name": "UIFields",
        "related": [
          "field",
          "input",
          "select",
          "textarea"
        ],
        "slots": {
          "default": {
            "description": "<field-ui> children. Non-field children (separators, headings) are placed in the grid too — span them by setting `style=\"grid-column: 1 / -1\"` for full-width content. Nested <fields-ui> works (an outer 6-col grid hosting inner 3-col grids inside a single cell)."
          }
        },
        "states": [
          {
            "description": "Default, ready for interaction.",
            "name": "idle"
          }
        ],
        "status": "stable",
        "synonyms": {
          "form": [
            "fields",
            "group",
            "layout"
          ]
        },
        "tag": "fields-ui",
        "tokens": {
          "--fields-column-gap": {
            "description": "Override the column-gap independently of row-gap."
          },
          "--fields-gap": {
            "description": "Gap between adjacent fields (row + column)."
          },
          "--fields-row-gap": {
            "description": "Override the row-gap independently of column-gap."
          }
        },
        "traits": [],
        "version": 1
      }
    },
    "Footer": {
      "title": "Footer",
      "description": "Footer — styled by closest container parent (Card / Drawer / Modal / Page / AppShell). Contains actions, pagination, or summary. Typically holds Buttons.",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "component": {
          "const": "Footer"
        },
        "justify": {
          "description": "Horizontal alignment of children",
          "type": "string",
          "enum": [
            "start",
            "end",
            "center",
            "between"
          ],
          "default": "end"
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [],
        "category": "container",
        "composes": [],
        "events": {},
        "examples": [
          {
            "description": "Chat interface with message bubbles containing avatar and text pairs, plus an input footer.",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"Card\",\n    \"children\": [\n      \"hdr\",\n      \"sec\",\n      \"ftr\"\n    ]\n  },\n  {\n    \"id\": \"hdr\",\n    \"component\": \"Header\",\n    \"children\": [\n      \"title\"\n    ]\n  },\n  {\n    \"id\": \"title\",\n    \"component\": \"Text\",\n    \"slot\": \"heading\",\n    \"textContent\": \"Chat\"\n  },\n  {\n    \"id\": \"sec\",\n    \"component\": \"Section\",\n    \"children\": [\n      \"messages\"\n    ]\n  },\n  {\n    \"id\": \"messages\",\n    \"component\": \"Column\",\n    \"gap\": \"3\",\n    \"children\": [\n      \"msg1\",\n      \"msg2\",\n      \"msg3\",\n      \"msg4\"\n    ]\n  },\n  {\n    \"id\": \"msg1\",\n    \"component\": \"Row\",\n    \"gap\": \"2\",\n    \"children\": [\n      \"a1\",\n      \"t1\"\n    ]\n  },\n  {\n    \"id\": \"a1\",\n    \"component\": \"Avatar\",\n    \"name\": \"User\",\n    \"size\": \"sm\"\n  },\n  {\n    \"id\": \"t1\",\n    \"component\": \"Text\",\n    \"variant\": \"body\",\n    \"textContent\": \"Hello! Can you help me with something?\"\n  },\n  {\n    \"id\": \"msg2\",\n    \"component\": \"Row\",\n    \"gap\": \"2\",\n    \"children\": [\n      \"a2\",\n      \"t2\"\n    ]\n  },\n  {\n    \"id\": \"a2\",\n    \"component\": \"Avatar\",\n    \"name\": \"Assistant\",\n    \"size\": \"sm\"\n  },\n  {\n    \"id\": \"t2\",\n    \"component\": \"Text\",\n    \"variant\": \"body\",\n    \"textContent\": \"Of course! I'd be happy to help. What do you need?\"\n  },\n  {\n    \"id\": \"msg3\",\n    \"component\": \"Row\",\n    \"gap\": \"2\",\n    \"children\": [\n      \"a3\",\n      \"t3\"\n    ]\n  },\n  {\n    \"id\": \"a3\",\n    \"component\": \"Avatar\",\n    \"name\": \"User\",\n    \"size\": \"sm\"\n  },\n  {\n    \"id\": \"t3\",\n    \"component\": \"Text\",\n    \"variant\": \"body\",\n    \"textContent\": \"I need to build a dashboard layout.\"\n  },\n  {\n    \"id\": \"msg4\",\n    \"component\": \"Row\",\n    \"gap\": \"2\",\n    \"children\": [\n      \"a4\",\n      \"t4\"\n    ]\n  },\n  {\n    \"id\": \"a4\",\n    \"component\": \"Avatar\",\n    \"name\": \"Assistant\",\n    \"size\": \"sm\"\n  },\n  {\n    \"id\": \"t4\",\n    \"component\": \"Text\",\n    \"variant\": \"body\",\n    \"textContent\": \"Great choice! Let me suggest some patterns for that.\"\n  },\n  {\n    \"id\": \"ftr\",\n    \"component\": \"Footer\",\n    \"children\": [\n      \"input-row\"\n    ]\n  },\n  {\n    \"id\": \"input-row\",\n    \"component\": \"Row\",\n    \"gap\": \"2\",\n    \"children\": [\n      \"chat-input\",\n      \"send-btn\"\n    ]\n  },\n  {\n    \"id\": \"chat-input\",\n    \"component\": \"Input\",\n    \"placeholder\": \"Type a message...\"\n  },\n  {\n    \"id\": \"send-btn\",\n    \"component\": \"Button\",\n    \"text\": \"Send\",\n    \"icon\": \"send\",\n    \"variant\": \"primary\"\n  }\n]",
            "name": "chat-interface"
          },
          {
            "description": "Card with error alert and a retry button for error state display.",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"Card\",\n    \"children\": [\n      \"sec\",\n      \"ftr\"\n    ]\n  },\n  {\n    \"id\": \"sec\",\n    \"component\": \"Section\",\n    \"children\": [\n      \"alert\"\n    ]\n  },\n  {\n    \"id\": \"alert\",\n    \"component\": \"Alert\",\n    \"variant\": \"error\",\n    \"title\": \"Something went wrong\",\n    \"description\": \"We encountered an error while loading the data. Please try again.\"\n  },\n  {\n    \"id\": \"ftr\",\n    \"component\": \"Footer\",\n    \"children\": [\n      \"retry\"\n    ]\n  },\n  {\n    \"id\": \"retry\",\n    \"component\": \"Button\",\n    \"text\": \"Retry\",\n    \"icon\": \"refresh\",\n    \"variant\": \"primary\"\n  }\n]",
            "name": "error-state"
          }
        ],
        "keywords": [
          "footer"
        ],
        "name": "UIFooter",
        "related": [
          "avatar",
          "input",
          "button",
          "alert",
          "table"
        ],
        "slots": {
          "description": {
            "description": "Caption or period text rendered beneath slot=\"heading\" — small, muted. Triggers space-between layout when combined with slot=\"action\". Also accepts bare <p> / <small> elements as direct children without slot=\"description\"."
          },
          "default": {
            "description": "Default slot — primary child content. Typically flat <button-ui> children laid out by the `justify` prop. Prefer flat children; a nested <row-ui> double-applies layout and breaks the chrome's gap."
          },
          "action": {
            "description": "Trailing action cluster — self-aligns to the inline-end edge of the footer. Pair with slot=\"action-leading\" for dual-cluster footers (e.g. Back on the left, Save on the right). Activated by card-ui, drawer-ui, and modal-ui @scope rules."
          },
          "action-leading": {
            "description": "Leading action cluster — self-aligns to the inline-start edge of the footer. Typically a Back or secondary action that needs to sit opposite the primary cluster. Activated by drawer-ui @scope; also works in card-ui footers via the same slot selector."
          },
          "heading": {
            "description": "Metric or period label — rendered prominently at the leading edge of the footer chrome (e.g. \"$12.4k\" / \"Jan – Mar 2024\"). When present the parent's @scope switches to a heading + description layout. Pairs with slot=\"description\" for a caption line below the value (trend-stat footer pattern). Activated by card-ui and drawer-ui @scope rules."
          }
        },
        "states": [
          {
            "description": "Default, ready for interaction.",
            "name": "idle"
          }
        ],
        "status": "stable",
        "synonyms": {
          "footer": [
            "footer-bar",
            "footer-row",
            "bottom-bar"
          ]
        },
        "tag": "footer-ui",
        "tokens": {},
        "traits": [],
        "version": 1
      }
    },
    "Frame": {
      "title": "Frame",
      "description": "Sticky-header / scrolling-body / sticky-footer layout frame — the\nchrome-less app-shell skeleton. A flex column that fills its parent's\nblock size: a native <header> child pins to the top, a <footer> child\npins to the bottom, and the <section> child scrolls between them (the\nonly region with overflow). Regions are positioned by tag + DOM order, OR any\nelement can take a region role via slot=\"header|body|footer\" (a CSS [slot] match,\nnot native projection — ADR-0033) — e.g. <section slot=\"header\"> as a pinned rail.\nAll three are OPTIONAL, so the common shape is just <section> + <footer>. Use for\ntab / panel content\nwhere actions stay visible while the body scrolls. Distinct from <card-ui>\n(adds border + elevation + a rich header grid), <drawer-ui> / <modal-ui>\n(add a backdrop + dismiss), and the page shells (<admin-page> / <page-ui>) —\nthose layer chrome over this same region contract. Requires a definite-height\nparent (a flex/grid chain rooted at a viewport height) for the section to\nscroll; in a content-sized parent it collapses to its content (no scroll,\nnot broken).\n",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "component": {
          "const": "Frame"
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [],
        "category": "layout",
        "composes": [],
        "events": {},
        "examples": [
          {
            "description": "Scrolling body with a pinned footer action bar (no header).",
            "a2ui": "[\n  { \"id\": \"root\", \"component\": \"Frame\", \"children\": [\"body\", \"actions\"] },\n  { \"id\": \"body\", \"component\": \"Section\", \"children\": [\"copy\"] },\n  { \"id\": \"copy\", \"component\": \"Text\", \"variant\": \"body\", \"textContent\": \"Scrollable panel content.\" },\n  { \"id\": \"actions\", \"component\": \"Footer\", \"children\": [\"save\"] },\n  { \"id\": \"save\", \"component\": \"Button\", \"text\": \"Save\", \"variant\": \"primary\" }\n]",
            "name": "panel-with-footer"
          }
        ],
        "keywords": [
          "frame",
          "panel",
          "layout",
          "scroll",
          "sticky",
          "footer",
          "header",
          "shell",
          "app",
          "sheet"
        ],
        "name": "UIFrame",
        "related": [
          "Card",
          "Drawer",
          "Modal",
          "Col"
        ],
        "slots": {
          "body": {
            "description": "The scrolling region — the only one with overflow. The native `<section>` child takes this role by tag + DOM order; any element can opt in via `slot=\"body\"`. Scrolls between the pinned header and footer (requires a definite-height parent)."
          },
          "footer": {
            "description": "Pinned bottom region — typically an action bar kept visible while the body scrolls. The native `<footer>` child takes this role by tag + DOM order; any element can opt in via `slot=\"footer\"`. Optional."
          },
          "header": {
            "description": "Pinned top region — stays fixed while the body scrolls. The native `<header>` child takes this role by tag + DOM order; any element can opt in via `slot=\"header\"` (a CSS [slot] match in Light DOM, not native projection — ADR-0033), e.g. `<section slot=\"header\">` as a pinned rail. Optional."
          }
        },
        "states": [
          {
            "description": "Default, ready for interaction.",
            "name": "idle"
          }
        ],
        "status": "stable",
        "synonyms": {
          "panel": [
            "panel",
            "frame",
            "sheet"
          ],
          "scroll": [
            "scroll",
            "frame",
            "body"
          ],
          "shell": [
            "shell",
            "frame",
            "app"
          ]
        },
        "tag": "frame-ui",
        "tokens": {},
        "traits": [],
        "version": 1
      }
    },
    "GenRoot": {
      "title": "GenRoot",
      "description": "Composition shell for chat + canvas generative UI. Manages layout modes\n(chat-only / split / canvas-only) and delegates a unified API across\nchild chat-ui, canvas-ui, and inspector-ui elements.\n",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "component": {
          "const": "GenRoot"
        },
        "inspector": {
          "description": "Show the inspector pane (for debugging generated A2UI).",
          "type": "boolean",
          "default": false
        },
        "mode": {
          "description": "Layout mode — chat-only, 50/50 split, or canvas-only.",
          "type": "string",
          "enum": [
            "chat",
            "split",
            "canvas"
          ],
          "default": "chat"
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [],
        "category": "layout",
        "composes": [
          "chat-thread-ui",
          "canvas-ui",
          "inspector-ui"
        ],
        "events": {},
        "examples": [],
        "keywords": [
          "gen-ui",
          "generative-ui",
          "chat-canvas",
          "agent-shell"
        ],
        "name": "GenRoot",
        "related": [
          "AppShell",
          "Chat"
        ],
        "slots": {
          "default": {
            "description": "Author supplies chat-ui, canvas-ui, and optional inspector-ui children."
          }
        },
        "states": [
          {
            "description": "Default mode=chat.",
            "name": "idle"
          }
        ],
        "status": "stable",
        "synonyms": {
          "gen-root": [
            "gen-ui-root",
            "gen-ui-mount",
            "generative-root"
          ]
        },
        "tag": "gen-root",
        "tokens": {},
        "traits": [],
        "version": 1
      }
    },
    "Grid": {
      "title": "Grid",
      "description": "CSS grid layout primitive. Supports [columns=\"1..6\"] for equal columns, [columns=\"auto-fill\"|\"auto-fit\"] for responsive density, and a per-child [span=\"2..6\"|\"full\"] attribute for asymmetric layouts. Both [columns] and [gap] accept responsive `@bp` notation for viewport-driven layout: columns=\"1 2@sm 4@lg\" gives 1 column on xs, 2 from sm, 4 from lg/xl. Compose a 2:1 split as columns=\"3\" + span=\"2\"; 3:2 as columns=\"5\" + span=\"3\" + span=\"2\".",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "align": {
          "description": "Block-axis alignment of grid items (start/center/end/stretch) via align-items — e.g. vertically centering a text column against a visual in a 2-column hero. Sets grid-item alignment, NOT text alignment.",
          "type": "string",
          "default": "stretch"
        },
        "columnGap": {
          "description": "Column gap override",
          "type": "string",
          "default": ""
        },
        "columns": {
          "description": "Number of equal columns (1–6), \"auto-fill\", or \"auto-fit\". Accepts responsive `@bp` notation: \"1 2@sm 4@lg\" = 1 on xs, 2 from sm, 4 from lg/xl. Unannotated value is the mobile-first base.",
          "type": "string",
          "default": "3"
        },
        "component": {
          "const": "Grid"
        },
        "gap": {
          "description": "Grid gap (row + column). Two grammars: a NAMED scale (xs/sm/md/lg/xl, parametric via --a-gap-k — 4/8/12/16/20px at k=1) and an integer space-rung (\"0\"…\"10\", \"12\", \"16\", literal). At k=1 they coincide: xs=1, sm=2, md=3, lg=4, xl=5. Responsive `@bp` notation supported: \"2 4@md\" = 2 below md, 4 from md upward.",
          "type": "string",
          "default": "md"
        },
        "justify": {
          "description": "Inline-axis alignment of grid items (start/center/end/stretch) via justify-items. Default stretch (items fill their column track).",
          "type": "string",
          "default": "stretch"
        },
        "minColumnWidth": {
          "description": "Minimum track width for columns=\"auto-fit\"/\"auto-fill\" (any CSS length, e.g. \"240px\", \"16rem\"). Sets the minmax() floor so cards don't shrink below it before wrapping; unset uses the 12rem default. No effect on numeric columns.",
          "type": "string",
          "default": ""
        },
        "rowGap": {
          "description": "Row gap override",
          "type": "string",
          "default": ""
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [],
        "category": "layout",
        "composes": [],
        "events": {},
        "examples": [
          {
            "description": "Dashboard with KPI stat grid and two chart cards.",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"Column\",\n    \"children\": [\n      \"header-row\",\n      \"kpi-grid\",\n      \"chart-grid\"\n    ],\n    \"gap\": \"4\"\n  },\n  {\n    \"id\": \"header-row\",\n    \"component\": \"Row\",\n    \"children\": [\n      \"dash-title\",\n      \"dash-actions\"\n    ]\n  },\n  {\n    \"id\": \"dash-title\",\n    \"component\": \"Text\",\n    \"textContent\": \"Dashboard\",\n    \"variant\": \"title\"\n  },\n  {\n    \"id\": \"dash-actions\",\n    \"component\": \"Row\",\n    \"children\": [\n      \"export-btn\"\n    ],\n    \"gap\": \"2\"\n  },\n  {\n    \"id\": \"export-btn\",\n    \"component\": \"Button\",\n    \"text\": \"Export\",\n    \"variant\": \"outline\",\n    \"size\": \"sm\",\n    \"icon\": \"download\"\n  },\n  {\n    \"id\": \"kpi-grid\",\n    \"component\": \"Grid\",\n    \"children\": [\n      \"k1\",\n      \"k2\",\n      \"k3\",\n      \"k4\"\n    ],\n    \"columns\": \"4\"\n  },\n  {\n    \"id\": \"k1\",\n    \"component\": \"Card\",\n    \"children\": [\n      \"k1h\",\n      \"k1s\"\n    ]\n  },\n  {\n    \"id\": \"k1h\",\n    \"component\": \"Header\",\n    \"children\": [\n      \"k1l\"\n    ]\n  },\n  {\n    \"id\": \"k1l\",\n    \"component\": \"Text\",\n    \"slot\": \"heading\",\n    \"textContent\": \"Revenue\",\n    \"variant\": \"label\"\n  },\n  {\n    \"id\": \"k1s\",\n    \"component\": \"Section\",\n    \"children\": [\n      \"k1v\",\n      \"k1b\"\n    ]\n  },\n  {\n    \"id\": \"k1v\",\n    \"component\": \"Text\",\n    \"textContent\": \"$48.2k\",\n    \"variant\": \"title\"\n  },\n  {\n    \"id\": \"k1b\",\n    \"component\": \"Badge\",\n    \"text\": \"+12.5%\",\n    \"variant\": \"success\",\n    \"size\": \"sm\"\n  },\n  {\n    \"id\": \"k2\",\n    \"component\": \"Card\",\n    \"children\": [\n      \"k2h\",\n      \"k2s\"\n    ]\n  },\n  {\n    \"id\": \"k2h\",\n    \"component\": \"Header\",\n    \"children\": [\n      \"k2l\"\n    ]\n  },\n  {\n    \"id\": \"k2l\",\n    \"component\": \"Text\",\n    \"slot\": \"heading\",\n    \"textContent\": \"Users\",\n    \"variant\": \"label\"\n  },\n  {\n    \"id\": \"k2s\",\n    \"component\": \"Section\",\n    \"children\": [\n      \"k2v\",\n      \"k2b\"\n    ]\n  },\n  {\n    \"id\": \"k2v\",\n    \"component\": \"Text\",\n    \"textContent\": \"2,340\",\n    \"variant\": \"title\"\n  },\n  {\n    \"id\": \"k2b\",\n    \"component\": \"Badge\",\n    \"text\": \"+8%\",\n    \"variant\": \"success\",\n    \"size\": \"sm\"\n  },\n  {\n    \"id\": \"k3\",\n    \"component\": \"Card\",\n    \"children\": [\n      \"k3h\",\n      \"k3s\"\n    ]\n  },\n  {\n    \"id\": \"k3h\",\n    \"component\": \"Header\",\n    \"children\": [\n      \"k3l\"\n    ]\n  },\n  {\n    \"id\": \"k3l\",\n    \"component\": \"Text\",\n    \"slot\": \"heading\",\n    \"textContent\": \"Bounce\",\n    \"variant\": \"label\"\n  },\n  {\n    \"id\": \"k3s\",\n    \"component\": \"Section\",\n    \"children\": [\n      \"k3v\",\n      \"k3b\"\n    ]\n  },\n  {\n    \"id\": \"k3v\",\n    \"component\": \"Text\",\n    \"textContent\": \"24.3%\",\n    \"variant\": \"title\"\n  },\n  {\n    \"id\": \"k3b\",\n    \"component\": \"Badge\",\n    \"text\": \"-3.1%\",\n    \"variant\": \"danger\",\n    \"size\": \"sm\"\n  },\n  {\n    \"id\": \"k4\",\n    \"component\": \"Card\",\n    \"children\": [\n      \"k4h\",\n      \"k4s\"\n    ]\n  },\n  {\n    \"id\": \"k4h\",\n    \"component\": \"Header\",\n    \"children\": [\n      \"k4l\"\n    ]\n  },\n  {\n    \"id\": \"k4l\",\n    \"component\": \"Text\",\n    \"slot\": \"heading\",\n    \"textContent\": \"Session\",\n    \"variant\": \"label\"\n  },\n  {\n    \"id\": \"k4s\",\n    \"component\": \"Section\",\n    \"children\": [\n      \"k4v\",\n      \"k4b\"\n    ]\n  },\n  {\n    \"id\": \"k4v\",\n    \"component\": \"Text\",\n    \"textContent\": \"4m 23s\",\n    \"variant\": \"title\"\n  },\n  {\n    \"id\": \"k4b\",\n    \"component\": \"Badge\",\n    \"text\": \"+15s\",\n    \"variant\": \"info\",\n    \"size\": \"sm\"\n  },\n  {\n    \"id\": \"chart-grid\",\n    \"component\": \"Grid\",\n    \"children\": [\n      \"ch1\",\n      \"ch2\"\n    ],\n    \"columns\": \"2\"\n  },\n  {\n    \"id\": \"ch1\",\n    \"component\": \"Card\",\n    \"children\": [\n      \"ch1h\",\n      \"ch1s\"\n    ]\n  },\n  {\n    \"id\": \"ch1h\",\n    \"component\": \"Header\",\n    \"children\": [\n      \"ch1t\"\n    ]\n  },\n  {\n    \"id\": \"ch1t\",\n    \"component\": \"Text\",\n    \"slot\": \"heading\",\n    \"textContent\": \"Revenue\",\n    \"variant\": \"section\"\n  },\n  {\n    \"id\": \"ch1s\",\n    \"component\": \"Section\",\n    \"children\": [\n      \"ch1-chart\"\n    ]\n  },\n  {\n    \"id\": \"ch1-chart\",\n    \"component\": \"Chart\",\n    \"type\": \"bar\",\n    \"x\": \"month\",\n    \"y\": \"revenue\"\n  },\n  {\n    \"id\": \"ch2\",\n    \"component\": \"Card\",\n    \"children\": [\n      \"ch2h\",\n      \"ch2s\"\n    ]\n  },\n  {\n    \"id\": \"ch2h\",\n    \"component\": \"Header\",\n    \"children\": [\n      \"ch2t\"\n    ]\n  },\n  {\n    \"id\": \"ch2t\",\n    \"component\": \"Text\",\n    \"slot\": \"heading\",\n    \"textContent\": \"Users\",\n    \"variant\": \"section\"\n  },\n  {\n    \"id\": \"ch2s\",\n    \"component\": \"Section\",\n    \"children\": [\n      \"ch2-chart\"\n    ]\n  },\n  {\n    \"id\": \"ch2-chart\",\n    \"component\": \"Chart\",\n    \"type\": \"line\",\n    \"x\": \"month\",\n    \"y\": \"users\"\n  }\n]",
            "name": "chart-dashboard"
          },
          {
            "description": "Two-column dashboard with quick actions (buttons) and system status (progress bars).",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"Grid\",\n    \"children\": [\n      \"c1\",\n      \"c2\"\n    ],\n    \"columns\": \"2\"\n  },\n  {\n    \"id\": \"c1\",\n    \"component\": \"Card\",\n    \"children\": [\n      \"c1h\",\n      \"c1s\"\n    ]\n  },\n  {\n    \"id\": \"c1h\",\n    \"component\": \"Header\",\n    \"children\": [\n      \"c1t\"\n    ]\n  },\n  {\n    \"id\": \"c1t\",\n    \"component\": \"Text\",\n    \"slot\": \"heading\",\n    \"textContent\": \"Quick Actions\",\n    \"variant\": \"section\"\n  },\n  {\n    \"id\": \"c1s\",\n    \"component\": \"Section\",\n    \"children\": [\n      \"c1col\"\n    ]\n  },\n  {\n    \"id\": \"c1col\",\n    \"component\": \"Column\",\n    \"children\": [\n      \"b1\",\n      \"b2\",\n      \"b3\"\n    ]\n  },\n  {\n    \"id\": \"b1\",\n    \"component\": \"Button\",\n    \"text\": \"New Project\",\n    \"variant\": \"solid\",\n    \"iconLeading\": \"plus\"\n  },\n  {\n    \"id\": \"b2\",\n    \"component\": \"Button\",\n    \"text\": \"Invite Member\",\n    \"variant\": \"outline\",\n    \"iconLeading\": \"users\"\n  },\n  {\n    \"id\": \"b3\",\n    \"component\": \"Button\",\n    \"text\": \"View Reports\",\n    \"variant\": \"ghost\",\n    \"iconLeading\": \"chart\"\n  },\n  {\n    \"id\": \"c2\",\n    \"component\": \"Card\",\n    \"children\": [\n      \"c2h\",\n      \"c2s\"\n    ]\n  },\n  {\n    \"id\": \"c2h\",\n    \"component\": \"Header\",\n    \"children\": [\n      \"c2t\"\n    ]\n  },\n  {\n    \"id\": \"c2t\",\n    \"component\": \"Text\",\n    \"slot\": \"heading\",\n    \"textContent\": \"System Status\",\n    \"variant\": \"section\"\n  },\n  {\n    \"id\": \"c2s\",\n    \"component\": \"Section\",\n    \"children\": [\n      \"c2col\"\n    ]\n  },\n  {\n    \"id\": \"c2col\",\n    \"component\": \"Column\",\n    \"children\": [\n      \"p1\",\n      \"p2\",\n      \"p3\"\n    ]\n  },\n  {\n    \"id\": \"p1\",\n    \"component\": \"Progress\",\n    \"value\": \"92\",\n    \"label\": \"CPU\"\n  },\n  {\n    \"id\": \"p2\",\n    \"component\": \"Progress\",\n    \"value\": \"67\",\n    \"label\": \"Memory\"\n  },\n  {\n    \"id\": \"p3\",\n    \"component\": \"Progress\",\n    \"value\": \"34\",\n    \"label\": \"Disk\"\n  }\n]",
            "name": "dashboard"
          }
        ],
        "keywords": [
          "grid",
          "ecommerce",
          "marketplace",
          "catalog",
          "columns",
          "photos",
          "pictures",
          "gallery",
          "portfolio",
          "responsive"
        ],
        "name": "UIGrid",
        "related": [
          "button",
          "badge",
          "chart",
          "progress",
          "color-picker"
        ],
        "slots": {
          "default": {
            "description": "Default slot — primary child content."
          }
        },
        "states": [
          {
            "description": "Default, ready for interaction.",
            "name": "idle"
          }
        ],
        "status": "stable",
        "synonyms": {
          "catalog": [
            "product",
            "card",
            "image",
            "grid",
            "inventory"
          ],
          "columns": [
            "split",
            "grid",
            "table"
          ],
          "ecommerce": [
            "product",
            "pricing",
            "inventory",
            "card",
            "image",
            "grid"
          ],
          "gallery": [
            "image",
            "gallery",
            "card",
            "grid"
          ],
          "grid": [
            "table",
            "data",
            "card",
            "image",
            "feature",
            "grid"
          ],
          "marketplace": [
            "product",
            "pricing",
            "card",
            "image",
            "grid",
            "search",
            "filter"
          ],
          "photos": [
            "image",
            "gallery",
            "card",
            "grid"
          ],
          "pictures": [
            "image",
            "gallery",
            "card",
            "grid"
          ],
          "portfolio": [
            "image",
            "gallery",
            "card",
            "grid",
            "feature"
          ],
          "responsive": [
            "split",
            "sidebar",
            "grid",
            "card"
          ]
        },
        "tag": "grid-ui",
        "tokens": {},
        "traits": [],
        "version": 1
      }
    },
    "Header": {
      "title": "Header",
      "description": "Header — styled by closest container parent (Card / Drawer / Modal / Page / AppShell). Contains heading text and optional action slot.",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "component": {
          "const": "Header"
        },
        "padding": {
          "description": "Bare attribute — enables default header padding. The container parent's own `padding` prop sets the scale.",
          "type": "boolean",
          "default": false
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [],
        "category": "container",
        "composes": [],
        "events": {},
        "examples": [
          {
            "description": "Chat interface with message bubbles containing avatar and text pairs, plus an input footer.",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"Card\",\n    \"children\": [\n      \"hdr\",\n      \"sec\",\n      \"ftr\"\n    ]\n  },\n  {\n    \"id\": \"hdr\",\n    \"component\": \"Header\",\n    \"children\": [\n      \"title\"\n    ]\n  },\n  {\n    \"id\": \"title\",\n    \"component\": \"Text\",\n    \"slot\": \"heading\",\n    \"textContent\": \"Chat\"\n  },\n  {\n    \"id\": \"sec\",\n    \"component\": \"Section\",\n    \"children\": [\n      \"messages\"\n    ]\n  },\n  {\n    \"id\": \"messages\",\n    \"component\": \"Column\",\n    \"gap\": \"3\",\n    \"children\": [\n      \"msg1\",\n      \"msg2\",\n      \"msg3\",\n      \"msg4\"\n    ]\n  },\n  {\n    \"id\": \"msg1\",\n    \"component\": \"Row\",\n    \"gap\": \"2\",\n    \"children\": [\n      \"a1\",\n      \"t1\"\n    ]\n  },\n  {\n    \"id\": \"a1\",\n    \"component\": \"Avatar\",\n    \"name\": \"User\",\n    \"size\": \"sm\"\n  },\n  {\n    \"id\": \"t1\",\n    \"component\": \"Text\",\n    \"variant\": \"body\",\n    \"textContent\": \"Hello! Can you help me with something?\"\n  },\n  {\n    \"id\": \"msg2\",\n    \"component\": \"Row\",\n    \"gap\": \"2\",\n    \"children\": [\n      \"a2\",\n      \"t2\"\n    ]\n  },\n  {\n    \"id\": \"a2\",\n    \"component\": \"Avatar\",\n    \"name\": \"Assistant\",\n    \"size\": \"sm\"\n  },\n  {\n    \"id\": \"t2\",\n    \"component\": \"Text\",\n    \"variant\": \"body\",\n    \"textContent\": \"Of course! I'd be happy to help. What do you need?\"\n  },\n  {\n    \"id\": \"msg3\",\n    \"component\": \"Row\",\n    \"gap\": \"2\",\n    \"children\": [\n      \"a3\",\n      \"t3\"\n    ]\n  },\n  {\n    \"id\": \"a3\",\n    \"component\": \"Avatar\",\n    \"name\": \"User\",\n    \"size\": \"sm\"\n  },\n  {\n    \"id\": \"t3\",\n    \"component\": \"Text\",\n    \"variant\": \"body\",\n    \"textContent\": \"I need to build a dashboard layout.\"\n  },\n  {\n    \"id\": \"msg4\",\n    \"component\": \"Row\",\n    \"gap\": \"2\",\n    \"children\": [\n      \"a4\",\n      \"t4\"\n    ]\n  },\n  {\n    \"id\": \"a4\",\n    \"component\": \"Avatar\",\n    \"name\": \"Assistant\",\n    \"size\": \"sm\"\n  },\n  {\n    \"id\": \"t4\",\n    \"component\": \"Text\",\n    \"variant\": \"body\",\n    \"textContent\": \"Great choice! Let me suggest some patterns for that.\"\n  },\n  {\n    \"id\": \"ftr\",\n    \"component\": \"Footer\",\n    \"children\": [\n      \"input-row\"\n    ]\n  },\n  {\n    \"id\": \"input-row\",\n    \"component\": \"Row\",\n    \"gap\": \"2\",\n    \"children\": [\n      \"chat-input\",\n      \"send-btn\"\n    ]\n  },\n  {\n    \"id\": \"chat-input\",\n    \"component\": \"Input\",\n    \"placeholder\": \"Type a message...\"\n  },\n  {\n    \"id\": \"send-btn\",\n    \"component\": \"Button\",\n    \"text\": \"Send\",\n    \"icon\": \"send\",\n    \"variant\": \"primary\"\n  }\n]",
            "name": "chat-interface"
          },
          {
            "description": "Command palette card with search input and a list of command options.",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"Card\",\n    \"children\": [\n      \"hdr\",\n      \"sec\"\n    ]\n  },\n  {\n    \"id\": \"hdr\",\n    \"component\": \"Header\",\n    \"children\": [\n      \"search\"\n    ]\n  },\n  {\n    \"id\": \"search\",\n    \"component\": \"Input\",\n    \"placeholder\": \"Type a command or search...\",\n    \"icon\": \"search\"\n  },\n  {\n    \"id\": \"sec\",\n    \"component\": \"Section\",\n    \"children\": [\n      \"options\"\n    ]\n  },\n  {\n    \"id\": \"options\",\n    \"component\": \"Column\",\n    \"gap\": \"1\",\n    \"children\": [\n      \"opt1\",\n      \"opt2\",\n      \"opt3\",\n      \"opt4\",\n      \"opt5\"\n    ]\n  },\n  {\n    \"id\": \"opt1\",\n    \"component\": \"Row\",\n    \"gap\": \"2\",\n    \"children\": [\n      \"i1\",\n      \"l1\"\n    ]\n  },\n  {\n    \"id\": \"i1\",\n    \"component\": \"Icon\",\n    \"name\": \"file\"\n  },\n  {\n    \"id\": \"l1\",\n    \"component\": \"Text\",\n    \"textContent\": \"Open File\"\n  },\n  {\n    \"id\": \"opt2\",\n    \"component\": \"Row\",\n    \"gap\": \"2\",\n    \"children\": [\n      \"i2\",\n      \"l2\"\n    ]\n  },\n  {\n    \"id\": \"i2\",\n    \"component\": \"Icon\",\n    \"name\": \"gear\"\n  },\n  {\n    \"id\": \"l2\",\n    \"component\": \"Text\",\n    \"textContent\": \"Settings\"\n  },\n  {\n    \"id\": \"opt3\",\n    \"component\": \"Row\",\n    \"gap\": \"2\",\n    \"children\": [\n      \"i3\",\n      \"l3\"\n    ]\n  },\n  {\n    \"id\": \"i3\",\n    \"component\": \"Icon\",\n    \"name\": \"palette\"\n  },\n  {\n    \"id\": \"l3\",\n    \"component\": \"Text\",\n    \"textContent\": \"Change Theme\"\n  },\n  {\n    \"id\": \"opt4\",\n    \"component\": \"Row\",\n    \"gap\": \"2\",\n    \"children\": [\n      \"i4\",\n      \"l4\"\n    ]\n  },\n  {\n    \"id\": \"i4\",\n    \"component\": \"Icon\",\n    \"name\": \"users\"\n  },\n  {\n    \"id\": \"l4\",\n    \"component\": \"Text\",\n    \"textContent\": \"Manage Users\"\n  },\n  {\n    \"id\": \"opt5\",\n    \"component\": \"Row\",\n    \"gap\": \"2\",\n    \"children\": [\n      \"i5\",\n      \"l5\"\n    ]\n  },\n  {\n    \"id\": \"i5\",\n    \"component\": \"Icon\",\n    \"name\": \"sign-out\"\n  },\n  {\n    \"id\": \"l5\",\n    \"component\": \"Text\",\n    \"textContent\": \"Sign Out\"\n  }\n]",
            "name": "command-palette"
          }
        ],
        "keywords": [
          "header"
        ],
        "name": "UIHeader",
        "related": [
          "avatar",
          "input",
          "button",
          "skeleton",
          "alert"
        ],
        "slots": {
          "description": {
            "description": "Secondary metadata — grid row 2 beneath the heading, spanning the heading and action columns. Also accepts bare <p> / <small> / body-variant <text-ui> as direct children without slot=\"description\". Renders muted + small."
          },
          "default": {
            "description": "Default slot — primary child content. When no named slot= attributes are used, all children flow here as a block. Most card/drawer/modal usages prefer the named vocabulary below so the parent's @scope grid activates."
          },
          "action": {
            "description": "Trailing control cluster — placed in the last column of the parent container's header grid. Use for icon-buttons, menu triggers, or badge/button combinations. The first [slot=\"action\"] child pushes itself to the grid's end; subsequent siblings flow with gap."
          },
          "heading": {
            "description": "Primary title — grid row 1 of the header grid. Also accepts bare <h1>–<h6> tags as direct children without slot=\"heading\". Renders at title weight + size per the parent's @scope. A slot=\"heading\" wrapper element can contain inline badges or metadata alongside the title text."
          },
          "icon": {
            "description": "Leading icon column — placed in column 1 of the parent container's header grid (card-ui / drawer-ui / modal-ui / page-ui). Use <icon-ui name=\"...\">, <avatar-ui>, or any inline icon element. The grid activates only when this slot is present; without it the heading spans the full width."
          }
        },
        "states": [
          {
            "description": "Default, ready for interaction.",
            "name": "idle"
          }
        ],
        "status": "stable",
        "synonyms": {
          "header": [
            "header-bar",
            "header-row",
            "top-bar",
            "chrome-top"
          ]
        },
        "tag": "header-ui",
        "tokens": {},
        "traits": [],
        "version": 1
      }
    },
    "Heatmap": {
      "title": "Heatmap",
      "description": "Grid heatmap with 5-bucket data ramp — supports day-grid (GitHub contributions), matrix, and density modes.",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "type": {
          "description": "Heatmap type",
          "type": "string",
          "enum": [
            "day-grid",
            "matrix",
            "density"
          ],
          "default": "matrix"
        },
        "aspect": {
          "description": "Aspect ratio",
          "type": "string",
          "enum": [
            "square",
            "wide"
          ],
          "default": "wide"
        },
        "colorScheme": {
          "description": "Color ramp",
          "type": "string",
          "enum": [
            "accent",
            "success",
            "warning",
            "danger",
            "info",
            "data-ramp"
          ],
          "default": "data-ramp"
        },
        "cols": {
          "description": "Column count",
          "type": "number",
          "default": 12
        },
        "component": {
          "const": "Heatmap"
        },
        "noLegend": {
          "description": "Hide the Less/More legend strip",
          "type": "boolean",
          "default": false
        },
        "rows": {
          "description": "Row count",
          "type": "number",
          "default": 7
        },
        "scale": {
          "description": "Value-to-bucket scale",
          "type": "string",
          "enum": [
            "linear",
            "log",
            "quantile"
          ],
          "default": "linear"
        },
        "startDate": {
          "description": "ISO start date; labels months in day-grid mode",
          "type": "string",
          "default": ""
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [],
        "category": "data-display",
        "composes": [],
        "events": {
          "cell-click": {
            "description": "Fired on cell click. detail carries the cell's row + column indices + value."
          },
          "cell-hover": {
            "description": "Fired on cell hover. detail carries the cell's row + column indices + value."
          },
          "chart-hover": {
            "description": "Canonical chart-hover shape — same detail as cell-hover. Re-emitted\nalongside cell-hover so consumers wiring a pointer-follow tooltip via\ntooltip-ui[follows=pointer] can listen for one event-name regardless\nof chart kind (chart-ui + heatmap-ui both emit it).\n"
          },
          "chart-leave": {
            "description": "Signal-only counterpart to chart-hover. Fires when the pointer leaves\nthe heatmap grid. Detail-free — receivers should clear their hover\nstate on receipt.\n"
          },
          "chart-select": {
            "description": "Canonical chart-select shape — same detail as cell-click. Re-emitted\nalongside cell-click for chart-kind-agnostic listeners.\n"
          }
        },
        "examples": [
          {
            "description": "Basic 7x12 matrix heatmap with random data.",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"Card\",\n    \"children\": [\n      \"sec\"\n    ]\n  },\n  {\n    \"id\": \"sec\",\n    \"component\": \"Section\",\n    \"children\": [\n      \"hm\"\n    ]\n  },\n  {\n    \"id\": \"hm\",\n    \"component\": \"Heatmap\",\n    \"type\": \"matrix\",\n    \"rows\": 7,\n    \"cols\": 12,\n    \"colorScheme\": \"data-ramp\"\n  }\n]",
            "name": "basic-heatmap"
          }
        ],
        "keywords": [
          "heatmap",
          "heat-map",
          "density",
          "matrix",
          "contribution",
          "calendar",
          "grid",
          "intensity",
          "activity"
        ],
        "name": "UIHeatmap",
        "related": [
          "chart",
          "calendar-picker"
        ],
        "slots": {
          "title": {
            "description": "Child content region for the `title` slot."
          }
        },
        "states": [
          {
            "description": "Default, ready for interaction.",
            "name": "idle"
          }
        ],
        "status": "stable",
        "synonyms": {
          "activity": [
            "heatmap",
            "calendar",
            "contribution"
          ],
          "contribution": [
            "heatmap",
            "calendar",
            "activity"
          ],
          "density": [
            "heatmap",
            "matrix"
          ]
        },
        "tag": "heatmap-ui",
        "tokens": {},
        "traits": [],
        "version": 1
      }
    },
    "Icon": {
      "title": "Icon",
      "description": "SVG icon from the icon registry. Renders inline SVG from getIcon() lookups with size + color token support; the canonical icon primitive throughout AdiaUI. Use for all icon needs; do not embed raw SVG or image-based icons in composed components.",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "component": {
          "const": "Icon"
        },
        "label": {
          "description": "Accessible label. Sets role=img and aria-label.",
          "type": "string",
          "default": ""
        },
        "name": {
          "description": "Icon name from registry",
          "type": "string",
          "default": ""
        },
        "size": {
          "description": "Icon size. Accepts the named scale (`xs` 12px / `sm` 14px / `md` 16px / `lg` 20px / `xl` 32px / `2xl` 48px / `3xl` 64px / `4xl` 96px / `fill` 100% of parent) or a free-form pixel / rem / em value as a string (\"48\", \"3rem\", \"1.25em\"). Overrides the inherited `--a-icon-size` from the universal `[size]` system on ancestors.",
          "type": "string",
          "default": ""
        },
        "weight": {
          "description": "Icon weight — selects the Phosphor weight variant (thin/light/regular/bold/fill/duotone).",
          "type": "string",
          "enum": [
            "thin",
            "light",
            "regular",
            "bold",
            "fill",
            "duotone"
          ],
          "default": "regular"
        }
      },
      "required": [
        "component",
        "name"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [],
        "category": "display",
        "composes": [],
        "events": {},
        "examples": [
          {
            "description": "Command palette card with search input and a list of command options.",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"Card\",\n    \"children\": [\n      \"hdr\",\n      \"sec\"\n    ]\n  },\n  {\n    \"id\": \"hdr\",\n    \"component\": \"Header\",\n    \"children\": [\n      \"search\"\n    ]\n  },\n  {\n    \"id\": \"search\",\n    \"component\": \"Input\",\n    \"placeholder\": \"Type a command or search...\",\n    \"icon\": \"search\"\n  },\n  {\n    \"id\": \"sec\",\n    \"component\": \"Section\",\n    \"children\": [\n      \"options\"\n    ]\n  },\n  {\n    \"id\": \"options\",\n    \"component\": \"Column\",\n    \"gap\": \"1\",\n    \"children\": [\n      \"opt1\",\n      \"opt2\",\n      \"opt3\",\n      \"opt4\",\n      \"opt5\"\n    ]\n  },\n  {\n    \"id\": \"opt1\",\n    \"component\": \"Row\",\n    \"gap\": \"2\",\n    \"children\": [\n      \"i1\",\n      \"l1\"\n    ]\n  },\n  {\n    \"id\": \"i1\",\n    \"component\": \"Icon\",\n    \"name\": \"file\"\n  },\n  {\n    \"id\": \"l1\",\n    \"component\": \"Text\",\n    \"textContent\": \"Open File\"\n  },\n  {\n    \"id\": \"opt2\",\n    \"component\": \"Row\",\n    \"gap\": \"2\",\n    \"children\": [\n      \"i2\",\n      \"l2\"\n    ]\n  },\n  {\n    \"id\": \"i2\",\n    \"component\": \"Icon\",\n    \"name\": \"gear\"\n  },\n  {\n    \"id\": \"l2\",\n    \"component\": \"Text\",\n    \"textContent\": \"Settings\"\n  },\n  {\n    \"id\": \"opt3\",\n    \"component\": \"Row\",\n    \"gap\": \"2\",\n    \"children\": [\n      \"i3\",\n      \"l3\"\n    ]\n  },\n  {\n    \"id\": \"i3\",\n    \"component\": \"Icon\",\n    \"name\": \"palette\"\n  },\n  {\n    \"id\": \"l3\",\n    \"component\": \"Text\",\n    \"textContent\": \"Change Theme\"\n  },\n  {\n    \"id\": \"opt4\",\n    \"component\": \"Row\",\n    \"gap\": \"2\",\n    \"children\": [\n      \"i4\",\n      \"l4\"\n    ]\n  },\n  {\n    \"id\": \"i4\",\n    \"component\": \"Icon\",\n    \"name\": \"users\"\n  },\n  {\n    \"id\": \"l4\",\n    \"component\": \"Text\",\n    \"textContent\": \"Manage Users\"\n  },\n  {\n    \"id\": \"opt5\",\n    \"component\": \"Row\",\n    \"gap\": \"2\",\n    \"children\": [\n      \"i5\",\n      \"l5\"\n    ]\n  },\n  {\n    \"id\": \"i5\",\n    \"component\": \"Icon\",\n    \"name\": \"sign-out\"\n  },\n  {\n    \"id\": \"l5\",\n    \"component\": \"Text\",\n    \"textContent\": \"Sign Out\"\n  }\n]",
            "name": "command-palette"
          },
          {
            "description": "Empty state component with icon, heading, description, and call-to-action button.",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"EmptyState\",\n    \"children\": [\n      \"content\"\n    ]\n  },\n  {\n    \"id\": \"content\",\n    \"component\": \"Column\",\n    \"align\": \"center\",\n    \"gap\": \"3\",\n    \"children\": [\n      \"icon\",\n      \"heading\",\n      \"desc\",\n      \"cta\"\n    ]\n  },\n  {\n    \"id\": \"icon\",\n    \"component\": \"Icon\",\n    \"name\": \"inbox\",\n    \"size\": \"xl\"\n  },\n  {\n    \"id\": \"heading\",\n    \"component\": \"Text\",\n    \"variant\": \"heading\",\n    \"textContent\": \"No items yet\"\n  },\n  {\n    \"id\": \"desc\",\n    \"component\": \"Text\",\n    \"variant\": \"body\",\n    \"textContent\": \"Get started by creating your first item. It only takes a moment.\"\n  },\n  {\n    \"id\": \"cta\",\n    \"component\": \"Button\",\n    \"text\": \"Create Item\",\n    \"icon\": \"plus\",\n    \"variant\": \"primary\"\n  }\n]",
            "name": "empty-state"
          }
        ],
        "keywords": [
          "icon"
        ],
        "name": "UIIcon",
        "related": [
          "input",
          "empty-state",
          "button",
          "badge",
          "slider"
        ],
        "slots": {},
        "states": [
          {
            "description": "Default, ready for interaction.",
            "name": "idle"
          }
        ],
        "status": "stable",
        "synonyms": {
          "icon": [
            "glyph",
            "phosphor-icon",
            "ui-icon",
            "symbol"
          ]
        },
        "tag": "icon-ui",
        "tokens": {},
        "traits": [],
        "version": 1
      }
    },
    "Image": {
      "title": "Image",
      "description": "Lazy-loading image with skeleton fallback. Shows skeleton while loading, falls back on error.",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "alt": {
          "description": "Alt text for the image.",
          "type": "string",
          "default": ""
        },
        "component": {
          "const": "Image"
        },
        "fallback": {
          "description": "Fallback image URL on error",
          "type": "string",
          "default": ""
        },
        "fit": {
          "description": "Object-fit mode",
          "type": "string",
          "enum": [
            "cover",
            "contain",
            "fill",
            "none"
          ],
          "default": "cover"
        },
        "height": {
          "description": "CSS height",
          "type": "string",
          "default": ""
        },
        "radius": {
          "description": "Border radius token",
          "type": "string",
          "enum": [
            "sm",
            "md",
            "lg",
            "full"
          ],
          "default": ""
        },
        "raw": {
          "description": "Strip chrome (no background, no radius) for edge-to-edge rendering.",
          "type": "boolean",
          "default": false
        },
        "size": {
          "description": "Size preset — e.g. 'full' fills the container width and height.",
          "type": "string",
          "default": ""
        },
        "src": {
          "description": "Image source URL.",
          "type": "string",
          "default": ""
        },
        "width": {
          "description": "CSS width",
          "type": "string",
          "default": ""
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [],
        "category": "display",
        "composes": [
          "skeleton-ui"
        ],
        "events": {},
        "examples": [
          {
            "description": "Design system settings page with brand header, photo upload section, bleed/margin controls, and approval workflow.",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"Card\",\n    \"children\": [\n      \"hdr\",\n      \"photo-sec\",\n      \"settings-sec\",\n      \"ftr\"\n    ]\n  },\n  {\n    \"id\": \"hdr\",\n    \"component\": \"Header\",\n    \"children\": [\n      \"hdr-title\",\n      \"hdr-desc\"\n    ]\n  },\n  {\n    \"id\": \"hdr-title\",\n    \"component\": \"Text\",\n    \"slot\": \"heading\",\n    \"textContent\": \"Bleed Design Settings\",\n    \"variant\": \"section\"\n  },\n  {\n    \"id\": \"hdr-desc\",\n    \"component\": \"Text\",\n    \"slot\": \"description\",\n    \"textContent\": \"Configure bleed margins, upload artwork, and preview before approval.\",\n    \"variant\": \"body\"\n  },\n  {\n    \"id\": \"photo-sec\",\n    \"component\": \"Section\",\n    \"children\": [\n      \"photo-col\"\n    ]\n  },\n  {\n    \"id\": \"photo-col\",\n    \"component\": \"Column\",\n    \"children\": [\n      \"photo-label\",\n      \"photo-img\",\n      \"photo-btn\"\n    ],\n    \"gap\": \"3\"\n  },\n  {\n    \"id\": \"photo-label\",\n    \"component\": \"Text\",\n    \"textContent\": \"Artwork Upload\",\n    \"variant\": \"label\"\n  },\n  {\n    \"id\": \"photo-img\",\n    \"component\": \"Image\",\n    \"src\": \"https://picsum.photos/400/200\",\n    \"aspect\": \"2/1\"\n  },\n  {\n    \"id\": \"photo-btn\",\n    \"component\": \"Button\",\n    \"text\": \"Upload Photo\",\n    \"variant\": \"secondary\"\n  },\n  {\n    \"id\": \"settings-sec\",\n    \"component\": \"Section\",\n    \"children\": [\n      \"settings-col\"\n    ]\n  },\n  {\n    \"id\": \"settings-col\",\n    \"component\": \"Column\",\n    \"children\": [\n      \"bleed-mode\",\n      \"bleed-margin\",\n      \"bleed-unit\",\n      \"approved\"\n    ],\n    \"gap\": \"4\"\n  },\n  {\n    \"id\": \"bleed-mode\",\n    \"component\": \"Select\",\n    \"label\": \"Bleed Mode\",\n    \"name\": \"bleed-mode\",\n    \"placeholder\": \"Select mode...\"\n  },\n  {\n    \"id\": \"bleed-margin\",\n    \"component\": \"Input\",\n    \"label\": \"Bleed Margin\",\n    \"name\": \"bleed-margin\",\n    \"type\": \"number\",\n    \"placeholder\": \"e.g. 3\"\n  },\n  {\n    \"id\": \"bleed-unit\",\n    \"component\": \"Select\",\n    \"label\": \"Unit\",\n    \"name\": \"bleed-unit\",\n    \"placeholder\": \"mm\"\n  },\n  {\n    \"id\": \"approved\",\n    \"component\": \"CheckBox\",\n    \"label\": \"Approved for production\",\n    \"name\": \"approved\"\n  },\n  {\n    \"id\": \"ftr\",\n    \"component\": \"Footer\",\n    \"children\": [\n      \"preview-btn\",\n      \"apply-btn\"\n    ]\n  },\n  {\n    \"id\": \"preview-btn\",\n    \"component\": \"Button\",\n    \"text\": \"Preview\",\n    \"variant\": \"secondary\"\n  },\n  {\n    \"id\": \"apply-btn\",\n    \"component\": \"Button\",\n    \"text\": \"Apply\",\n    \"variant\": \"primary\"\n  }\n]",
            "name": "bleed-design-settings"
          },
          {
            "description": "Image upload card with drag-and-drop zone and a 3-column preview grid of placeholder image cards. Footer holds cancel and upload action buttons.",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"Card\",\n    \"children\": [\n      \"hdr\",\n      \"sec\",\n      \"ftr\"\n    ]\n  },\n  {\n    \"id\": \"hdr\",\n    \"component\": \"Header\",\n    \"children\": [\n      \"title\"\n    ]\n  },\n  {\n    \"id\": \"title\",\n    \"component\": \"Text\",\n    \"slot\": \"heading\",\n    \"variant\": \"section\",\n    \"textContent\": \"Upload Images\"\n  },\n  {\n    \"id\": \"sec\",\n    \"component\": \"Section\",\n    \"children\": [\n      \"col\"\n    ]\n  },\n  {\n    \"id\": \"col\",\n    \"component\": \"Column\",\n    \"gap\": \"4\",\n    \"children\": [\n      \"uploader\",\n      \"preview-grid\"\n    ]\n  },\n  {\n    \"id\": \"uploader\",\n    \"component\": \"Upload\",\n    \"accept\": \"image/*\",\n    \"multiple\": true,\n    \"hint\": \"Drag images here or click to browse\"\n  },\n  {\n    \"id\": \"preview-grid\",\n    \"component\": \"Grid\",\n    \"columns\": \"3\",\n    \"gap\": \"3\",\n    \"children\": [\n      \"preview-1\",\n      \"preview-2\",\n      \"preview-3\"\n    ]\n  },\n  {\n    \"id\": \"preview-1\",\n    \"component\": \"Card\",\n    \"variant\": \"outlined\",\n    \"children\": [\n      \"img-1\"\n    ]\n  },\n  {\n    \"id\": \"img-1\",\n    \"component\": \"Image\",\n    \"src\": \"\",\n    \"alt\": \"Preview 1\",\n    \"height\": \"120px\",\n    \"fit\": \"cover\",\n    \"radius\": \"sm\"\n  },\n  {\n    \"id\": \"preview-2\",\n    \"component\": \"Card\",\n    \"variant\": \"outlined\",\n    \"children\": [\n      \"img-2\"\n    ]\n  },\n  {\n    \"id\": \"img-2\",\n    \"component\": \"Image\",\n    \"src\": \"\",\n    \"alt\": \"Preview 2\",\n    \"height\": \"120px\",\n    \"fit\": \"cover\",\n    \"radius\": \"sm\"\n  },\n  {\n    \"id\": \"preview-3\",\n    \"component\": \"Card\",\n    \"variant\": \"outlined\",\n    \"children\": [\n      \"img-3\"\n    ]\n  },\n  {\n    \"id\": \"img-3\",\n    \"component\": \"Image\",\n    \"src\": \"\",\n    \"alt\": \"Preview 3\",\n    \"height\": \"120px\",\n    \"fit\": \"cover\",\n    \"radius\": \"sm\"\n  },\n  {\n    \"id\": \"ftr\",\n    \"component\": \"Footer\",\n    \"children\": [\n      \"ftr-actions\"\n    ]\n  },\n  {\n    \"id\": \"ftr-actions\",\n    \"component\": \"Row\",\n    \"gap\": \"2\",\n    \"children\": [\n      \"cancel-btn\",\n      \"upload-btn\"\n    ]\n  },\n  {\n    \"id\": \"cancel-btn\",\n    \"component\": \"Button\",\n    \"text\": \"Cancel\",\n    \"variant\": \"ghost\"\n  },\n  {\n    \"id\": \"upload-btn\",\n    \"component\": \"Button\",\n    \"text\": \"Upload\",\n    \"variant\": \"primary\"\n  }\n]",
            "name": "file-upload-gallery"
          }
        ],
        "keywords": [
          "image",
          "ecommerce",
          "store",
          "marketplace",
          "catalog",
          "grid",
          "upload",
          "attach",
          "dropzone",
          "photos",
          "pictures",
          "gallery",
          "portfolio",
          "lightbox",
          "media",
          "instagram",
          "assets"
        ],
        "name": "UIImage",
        "related": [
          "button",
          "select",
          "input",
          "check-box",
          "upload"
        ],
        "slots": {
          "img": {
            "description": "Stamped <img> element"
          }
        },
        "states": [
          {
            "description": "Default, ready for interaction.",
            "name": "idle"
          }
        ],
        "status": "stable",
        "synonyms": {
          "assets": [
            "data",
            "table",
            "file",
            "image",
            "gallery"
          ],
          "attach": [
            "file",
            "upload",
            "image"
          ],
          "catalog": [
            "product",
            "card",
            "image",
            "grid",
            "inventory"
          ],
          "dropzone": [
            "file",
            "upload",
            "image",
            "import"
          ],
          "ecommerce": [
            "product",
            "pricing",
            "inventory",
            "card",
            "image",
            "grid"
          ],
          "gallery": [
            "image",
            "gallery",
            "card",
            "grid"
          ],
          "grid": [
            "table",
            "data",
            "card",
            "image",
            "feature",
            "grid"
          ],
          "instagram": [
            "social",
            "post",
            "image",
            "gallery"
          ],
          "lightbox": [
            "image",
            "gallery",
            "caption"
          ],
          "marketplace": [
            "product",
            "pricing",
            "card",
            "image",
            "grid",
            "search",
            "filter"
          ],
          "media": [
            "image",
            "video",
            "music",
            "player",
            "gallery",
            "embed"
          ],
          "photos": [
            "image",
            "gallery",
            "card",
            "grid"
          ],
          "pictures": [
            "image",
            "gallery",
            "card",
            "grid"
          ],
          "portfolio": [
            "image",
            "gallery",
            "card",
            "grid",
            "feature"
          ],
          "store": [
            "product",
            "pricing",
            "inventory",
            "card",
            "image"
          ],
          "upload": [
            "file",
            "upload",
            "image",
            "import",
            "data"
          ]
        },
        "tag": "image-ui",
        "tokens": {},
        "traits": [],
        "version": 1
      }
    },
    "InlineEdit": {
      "title": "InlineEdit",
      "description": "Click-to-edit text in place. Renders as static text until clicked /\nfocused + Enter, then becomes editable. Enter or blur commits; Escape\ncancels and restores the original value. Form-participating.\n\nUse for editable titles, breadcrumb labels, table-cell text fields,\ndraft document names — any case where a user expects to edit text\nwithout opening a separate dialog or input. Distinct from `<input-ui>`\n(always-editable chrome) and from `<field-ui>` (stacked label + input\ncomposition). inline-edit reads as text in static state.\n",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "commit": {
          "description": "When to commit pending edits. `blur` (default) — saves on focusout\nor Enter. `enter` — Enter saves, blur cancels (returns to original).\n`manual` — only programmatic `commitEdit()` saves.\n",
          "type": "string",
          "enum": [
            "blur",
            "enter",
            "manual"
          ],
          "default": "blur"
        },
        "component": {
          "const": "InlineEdit"
        },
        "editing": {
          "description": "Reflected state — `true` when the element is actively being edited.\nToggles automatically on click / Enter / blur / Escape; rarely set\nby consumers. Listen to `edit-start` / `edit-end` events instead.\n",
          "type": "boolean",
          "default": false
        },
        "placeholder": {
          "description": "Hint text shown when the value is empty (inline-edit reads this in the static state).",
          "type": "string",
          "default": "Click to edit"
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [
          {
            "fix": "<inline-edit-ui value=\"Title\" name=\"title\"> — reads as text in static state; chrome only appears while editing.",
            "why": "Ghost variant still renders input chrome (border on focus). Looks like a control, not text.",
            "wrong": "<input-ui value=\"Title\" name=\"title\" variant=\"ghost\">"
          },
          {
            "fix": "<inline-edit-ui value=\"Title\">",
            "why": "No state machine — no commit/cancel semantics, no form participation, no a11y wiring.",
            "wrong": "<text-ui contenteditable>Title</text-ui>"
          }
        ],
        "category": "form",
        "composes": [],
        "events": {
          "cancel": {
            "description": "Fired when Escape (or blur with commit=enter) restores the original. Bubbles."
          },
          "change": {
            "description": "Fired after a successful commit. detail = { value, oldValue }. Bubbles."
          },
          "edit-end": {
            "description": "Fired when leaving edit mode. detail = { committed: boolean }. Bubbles."
          },
          "edit-start": {
            "description": "Fired when entering edit mode. Bubbles."
          }
        },
        "examples": [
          {
            "description": "A draft document title that becomes editable on click.",
            "a2ui": "[{ \"id\": \"title\", \"component\": \"InlineEdit\", \"value\": \"Untitled draft\" }]\n",
            "name": "editable-title"
          }
        ],
        "keywords": [
          "inline-edit",
          "editable",
          "click-to-edit",
          "rename",
          "edit-in-place"
        ],
        "name": "UIInlineEdit",
        "related": [
          "input",
          "field",
          "text"
        ],
        "slots": {},
        "states": [
          {
            "description": "Static — text reads as plain text with a hover hint.",
            "name": "idle"
          },
          {
            "description": "Hover affordance — subtle background tint signals editability.",
            "name": "hover"
          },
          {
            "description": "contenteditable — host is the input surface; outline + caret.",
            "name": "editing"
          },
          {
            "description": "Value is empty and not editing — placeholder text renders.",
            "name": "empty"
          },
          {
            "description": "Locked; click + keyboard activation are no-ops.",
            "name": "disabled"
          }
        ],
        "status": "stable",
        "synonyms": {
          "inline-edit": [
            "editable",
            "click-to-edit",
            "edit-in-place",
            "rename-in-place"
          ]
        },
        "tag": "inline-edit-ui",
        "tokens": {
          "--inline-edit-bg-edit": {
            "description": "Background while editing.",
            "default": "var(--a-bg)"
          },
          "--inline-edit-bg-hover": {
            "description": "Background tint on hover (idle state).",
            "default": "var(--a-bg-muted)"
          },
          "--inline-edit-outline": {
            "description": "Outline color in the editing state.",
            "default": "var(--a-accent-strong)"
          },
          "--inline-edit-placeholder": {
            "description": "Placeholder text color in empty-static state.",
            "default": "var(--a-fg-subtle)"
          },
          "--inline-edit-px": {
            "description": "Horizontal padding (inner gutter so hover tint reads as a pill, not a flush block).",
            "default": "var(--a-space-1)"
          },
          "--inline-edit-py": {
            "description": "Vertical padding.",
            "default": "var(--a-space-0-5)"
          },
          "--inline-edit-radius": {
            "description": "Border-radius for the hover / editing chrome.",
            "default": "var(--a-radius-sm)"
          }
        },
        "traits": [],
        "version": 1
      }
    },
    "InlineMessage": {
      "title": "InlineMessage",
      "description": "In-flow message glyph + text used in form-field rows for validation\nfeedback, hint copy, and inline confirmations. Distinguished from\n<alert-ui> (banner / surface-bearing notice) by carrying no surface\nfill, no border, no padding box — severity is foreground color +\nicon only. Variants map to severity (info / success / warning /\ndanger). Nests inside <field-ui>, <col-ui>, <row-ui> without\nbreaking field rhythm. Non-interactive annotation only.\n",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "component": {
          "const": "InlineMessage"
        },
        "icon": {
          "description": "Phosphor glyph override; each [variant] ships a sensible default (info / check-circle / warning / x-circle).",
          "$ref": "#/$defs/DynamicString"
        },
        "live": {
          "description": "Sets `aria-live` on the host for dynamic message updates. Empty = no live region (static annotation).",
          "type": "string",
          "enum": [
            "",
            "polite",
            "assertive"
          ],
          "default": ""
        },
        "text": {
          "description": "Single-line message text. Default-slot content wins when present.",
          "$ref": "#/$defs/DynamicString"
        },
        "variant": {
          "description": "Semantic severity tone — drives icon + foreground color. Default carries no leading icon (pure hint copy).",
          "$ref": "#/$defs/DynamicString"
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [],
        "category": "feedback",
        "composes": [
          "icon-ui"
        ],
        "events": {},
        "examples": [
          {
            "description": "Email field with a danger inline-message under the input.",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"Field\",\n    \"label\": \"Email\",\n    \"children\": [\n      \"input\",\n      \"msg\"\n    ]\n  },\n  {\n    \"id\": \"input\",\n    \"component\": \"Input\",\n    \"type\": \"email\"\n  },\n  {\n    \"id\": \"msg\",\n    \"component\": \"InlineMessage\",\n    \"variant\": \"danger\",\n    \"text\": \"Email address is required\"\n  }\n]",
            "name": "field-validation"
          },
          {
            "description": "Password field with a muted hint (default variant, no icon).",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"Field\",\n    \"label\": \"Password\",\n    \"children\": [\n      \"input\",\n      \"hint\"\n    ]\n  },\n  {\n    \"id\": \"input\",\n    \"component\": \"Input\",\n    \"type\": \"password\"\n  },\n  {\n    \"id\": \"hint\",\n    \"component\": \"InlineMessage\",\n    \"text\": \"At least 8 characters\"\n  }\n]",
            "name": "password-hint"
          },
          {
            "description": "Username field with a polite live-region success confirmation.",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"Field\",\n    \"label\": \"Username\",\n    \"children\": [\n      \"input\",\n      \"msg\"\n    ]\n  },\n  {\n    \"id\": \"input\",\n    \"component\": \"Input\"\n  },\n  {\n    \"id\": \"msg\",\n    \"component\": \"InlineMessage\",\n    \"variant\": \"success\",\n    \"live\": \"polite\",\n    \"text\": \"Username is available\"\n  }\n]",
            "name": "username-success"
          }
        ],
        "keywords": [
          "inline",
          "message",
          "hint",
          "helper",
          "validation",
          "error",
          "field-error",
          "helper-text",
          "error-text",
          "form-feedback",
          "status",
          "notice"
        ],
        "name": "UIInlineMessage",
        "related": [
          "alert",
          "field",
          "input",
          "text"
        ],
        "slots": {
          "default": {
            "description": "Message body — text or inline DOM (e.g. <link-ui>, <kbd-ui>). Wins over the [text] attribute when present. Stays inline so the message reads as one annotation line under the field."
          },
          "leading": {
            "description": "Leading icon slot. Stamped automatically from [icon] or the variant's default glyph. Consumer-provided <icon-ui slot=\"leading\"> is preserved across [variant] changes (never overwritten)."
          }
        },
        "states": [
          {
            "description": "Default, ready for screen-reader pickup.",
            "name": "idle"
          }
        ],
        "status": "stable",
        "synonyms": {
          "error": [
            "error",
            "alert",
            "validation"
          ],
          "helper": [
            "hint",
            "help",
            "tooltip"
          ],
          "hint": [
            "hint",
            "tooltip",
            "help"
          ],
          "message": [
            "alert",
            "notification",
            "hint"
          ],
          "notice": [
            "alert",
            "banner",
            "hint"
          ],
          "validation": [
            "validation",
            "error",
            "alert"
          ]
        },
        "tag": "inline-message-ui",
        "tokens": {},
        "traits": [],
        "version": 1
      }
    },
    "Input": {
      "title": "Input",
      "description": "Text input field with contenteditable surface. Supports prefix/suffix icons, label, form participation, and a `type=\"number\"` mode that renders [+]/[-] stepper buttons, numeric input filtering, and ARIA spinbutton semantics — no native `<input type=\"number\">` under the hood. Password type uses a native `<input>` (only path that still wraps native, for `-webkit-text-security` disc masking).",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "type": {
          "description": "Input type. `password` wraps a native `<input>` for disc masking; `number` renders a contenteditable + stepper buttons (no native input). All other types use plain contenteditable.",
          "type": "string",
          "enum": [
            "text",
            "email",
            "password",
            "number",
            "tel",
            "url",
            "search",
            "date",
            "datetime-local",
            "time",
            "month",
            "week",
            "color"
          ],
          "default": "text"
        },
        "required": {
          "description": "Marks the field as required for form validation. Sets aria-required.",
          "type": "boolean",
          "default": false
        },
        "autocomplete": {
          "description": "Browser autofill behavior per HTML autocomplete spec. Routed via setAttribute to the host element. Common values: off, on, cc-number, cc-exp, cc-csc, cc-name, email, username, current-password, new-password, one-time-code, given-name, family-name, street-address, postal-code.",
          "$ref": "#/$defs/DynamicString"
        },
        "component": {
          "const": "Input"
        },
        "disabled": {
          "description": "Disables interaction, removes contenteditable, and dims the control",
          "type": "boolean",
          "default": false
        },
        "error": {
          "description": "Validation error message. Set automatically by constraint validation or manually via setInvalid().",
          "type": "string",
          "default": ""
        },
        "inputmode": {
          "description": "Mobile keyboard hint per HTML inputmode spec. Routed via setAttribute to the host element. Values: text, decimal, numeric, tel, search, email, url.",
          "$ref": "#/$defs/DynamicString"
        },
        "label": {
          "description": "Inline label rendered as a leading caption inside the input chrome, between any prefix and the value. Wires aria-labelledby on the editable surface. For stacked label / hint / error compositions, wrap with field-ui.",
          "type": "string",
          "default": ""
        },
        "locale": {
          "description": "BCP-47 locale tag for `type=\"number\"`, e.g. `de-DE`, `fr-FR`, `en-IN`. When set, the input accepts both `.` AND the locale's decimal separator (e.g. `,` in de-DE), uses `Intl.NumberFormat` for display, and groups thousands on blur (e.g. en-US `1,234,567.89`, de-DE `1.234.567,89`). On focus, the input reverts to ungrouped form for easy editing. `.value` always stores the ungrouped, locale-decimal form so `Number(#toCanonical(v))` round-trips. Default empty = en-US-equivalent path (no behavior change).",
          "type": "string",
          "default": ""
        },
        "max": {
          "description": "Maximum numeric value. Applies when `type=\"number\"`. Clamps + drives aria-valuemax + the [+] button's disabled state.",
          "type": "number",
          "default": null
        },
        "maxlength": {
          "description": "Maximum character length for validation",
          "type": "number",
          "default": null
        },
        "min": {
          "description": "Minimum numeric value. Applies when `type=\"number\"`. Clamps + drives aria-valuemin + the [-] button's disabled state.",
          "type": "number",
          "default": null
        },
        "minlength": {
          "description": "Minimum character length for validation",
          "type": "number",
          "default": null
        },
        "name": {
          "description": "Form control name for form data submission",
          "type": "string",
          "default": ""
        },
        "pattern": {
          "description": "Regex pattern for validation. Tested as ^(?:pattern)$ against the value.",
          "type": "string",
          "default": ""
        },
        "placeholder": {
          "description": "Placeholder text shown when the input is empty, via ::before content",
          "type": "string",
          "default": ""
        },
        "precision": {
          "description": "Decimal places to display + clamp to, when `type=\"number\"`. Overrides the implicit decimal-count from `step` — e.g. `step=1 precision=2` formats \"10.00\".",
          "type": "number",
          "default": null
        },
        "prefix": {
          "description": "Prefix text or icon rendered before the text surface (e.g., unit label, search icon)",
          "type": "string",
          "default": ""
        },
        "raw": {
          "description": "Strips visual chrome (border, background) from the input",
          "type": "boolean",
          "default": false
        },
        "readonly": {
          "description": "Prevents editing while keeping the field focusable. Sets contenteditable=false.",
          "type": "boolean",
          "default": false
        },
        "step": {
          "description": "Stepper increment for `type=\"number\"`. Drives ↑/↓ ArrowUp/Down + [+]/[-] button magnitude. Also determines decimal-count for value formatting unless `precision` is set.",
          "type": "number",
          "default": 1
        },
        "suffix": {
          "description": "Suffix text rendered after the text surface (e.g., unit like 'kg')",
          "type": "string",
          "default": ""
        },
        "throttle": {
          "description": "§220 (v0.5.9, FEEDBACK-14 §3). Trailing-debounce on the `input`\nevent in milliseconds. When > 0, value mutates immediately + the UI\nstays responsive, but `input` dispatch is collapsed so only the\nfinal value in the throttle window emits. Useful for expensive\n`input`-driven computation (palette regen, large list filter,\nserver-side autocomplete). `change` fires unthrottled on blur /\nEnter / stepper commit; any pending `input` flushes before `change`\nso consumers see input→input→…→input→change ordering. Default 0\npreserves synchronous emission.",
          "type": "number",
          "default": 0
        },
        "value": {
          "description": "Current input value, synced with contenteditable text surface. For `type=\"number\"`, this is the formatted numeric string; read `el.valueAsNumber` for the parsed Number.",
          "type": "string",
          "default": ""
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [],
        "category": "input",
        "composes": [
          "button-ui",
          "icon-ui"
        ],
        "events": {
          "change": {
            "description": "Fired on blur, Enter, or a stepper-button click (bubbles)"
          },
          "input": {
            "description": "Fired on each keystroke or stepper-button increment (bubbles)"
          },
          "submit": {
            "description": "Fired when Enter commits the value."
          }
        },
        "examples": [
          {
            "description": "Number input with [+]/[-] stepper buttons, min/max bounds, and a quantity label. Use for product quantity, item count, or any bounded integer input.",
            "a2ui": "[\n  {\"id\": \"root\", \"component\": \"Field\", \"label\": \"Quantity\",\n   \"children\": [\"qty\"]},\n  {\"id\": \"qty\", \"component\": \"Input\", \"type\": \"number\",\n   \"name\": \"quantity\", \"value\": \"1\", \"min\": 0, \"max\": 99, \"step\": 1}\n]",
            "name": "quantity-stepper"
          },
          {
            "description": "Currency number input with $ prefix, 2-decimal precision, and step 0.01. The stepper buttons increment by one cent.",
            "a2ui": "[\n  {\"id\": \"root\", \"component\": \"Field\", \"label\": \"Price\",\n   \"children\": [\"price\"]},\n  {\"id\": \"price\", \"component\": \"Input\", \"type\": \"number\",\n   \"name\": \"price\", \"value\": \"9.99\", \"min\": 0, \"step\": 0.01,\n   \"precision\": 2, \"prefix\": \"$\"}\n]",
            "name": "price-with-currency"
          },
          {
            "description": "Weight number input with a kg suffix and 0.1 step for decigram precision.",
            "a2ui": "[\n  {\"id\": \"root\", \"component\": \"Field\", \"label\": \"Weight\",\n   \"children\": [\"weight\"]},\n  {\"id\": \"weight\", \"component\": \"Input\", \"type\": \"number\",\n   \"name\": \"weight\", \"value\": \"70\", \"min\": 0, \"max\": 500,\n   \"step\": 0.1, \"suffix\": \"kg\"}\n]",
            "name": "weight-with-unit"
          },
          {
            "description": "Percent number input bounded 0..100 with a % suffix.",
            "a2ui": "[\n  {\"id\": \"root\", \"component\": \"Field\", \"label\": \"Discount\",\n   \"children\": [\"pct\"]},\n  {\"id\": \"pct\", \"component\": \"Input\", \"type\": \"number\",\n   \"name\": \"discount\", \"value\": \"25\", \"min\": 0, \"max\": 100,\n   \"step\": 5, \"suffix\": \"%\"}\n]",
            "name": "percent-bounded"
          },
          {
            "description": "Number input allowing negative values, e.g. temperature offset.",
            "a2ui": "[\n  {\"id\": \"root\", \"component\": \"Field\", \"label\": \"Temperature offset\",\n   \"children\": [\"temp\"]},\n  {\"id\": \"temp\", \"component\": \"Input\", \"type\": \"number\",\n   \"name\": \"temp\", \"value\": \"0\", \"min\": -100, \"max\": 100,\n   \"step\": 1, \"suffix\": \"°C\"}\n]",
            "name": "temperature-negative"
          },
          {
            "description": "Chat interface with message bubbles containing avatar and text pairs, plus an input footer.",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"Card\",\n    \"children\": [\n      \"hdr\",\n      \"sec\",\n      \"ftr\"\n    ]\n  },\n  {\n    \"id\": \"hdr\",\n    \"component\": \"Header\",\n    \"children\": [\n      \"title\"\n    ]\n  },\n  {\n    \"id\": \"title\",\n    \"component\": \"Text\",\n    \"slot\": \"heading\",\n    \"textContent\": \"Chat\"\n  },\n  {\n    \"id\": \"sec\",\n    \"component\": \"Section\",\n    \"children\": [\n      \"messages\"\n    ]\n  },\n  {\n    \"id\": \"messages\",\n    \"component\": \"Column\",\n    \"gap\": \"3\",\n    \"children\": [\n      \"msg1\",\n      \"msg2\",\n      \"msg3\",\n      \"msg4\"\n    ]\n  },\n  {\n    \"id\": \"msg1\",\n    \"component\": \"Row\",\n    \"gap\": \"2\",\n    \"children\": [\n      \"a1\",\n      \"t1\"\n    ]\n  },\n  {\n    \"id\": \"a1\",\n    \"component\": \"Avatar\",\n    \"name\": \"User\",\n    \"size\": \"sm\"\n  },\n  {\n    \"id\": \"t1\",\n    \"component\": \"Text\",\n    \"variant\": \"body\",\n    \"textContent\": \"Hello! Can you help me with something?\"\n  },\n  {\n    \"id\": \"msg2\",\n    \"component\": \"Row\",\n    \"gap\": \"2\",\n    \"children\": [\n      \"a2\",\n      \"t2\"\n    ]\n  },\n  {\n    \"id\": \"a2\",\n    \"component\": \"Avatar\",\n    \"name\": \"Assistant\",\n    \"size\": \"sm\"\n  },\n  {\n    \"id\": \"t2\",\n    \"component\": \"Text\",\n    \"variant\": \"body\",\n    \"textContent\": \"Of course! I'd be happy to help. What do you need?\"\n  },\n  {\n    \"id\": \"msg3\",\n    \"component\": \"Row\",\n    \"gap\": \"2\",\n    \"children\": [\n      \"a3\",\n      \"t3\"\n    ]\n  },\n  {\n    \"id\": \"a3\",\n    \"component\": \"Avatar\",\n    \"name\": \"User\",\n    \"size\": \"sm\"\n  },\n  {\n    \"id\": \"t3\",\n    \"component\": \"Text\",\n    \"variant\": \"body\",\n    \"textContent\": \"I need to build a dashboard layout.\"\n  },\n  {\n    \"id\": \"msg4\",\n    \"component\": \"Row\",\n    \"gap\": \"2\",\n    \"children\": [\n      \"a4\",\n      \"t4\"\n    ]\n  },\n  {\n    \"id\": \"a4\",\n    \"component\": \"Avatar\",\n    \"name\": \"Assistant\",\n    \"size\": \"sm\"\n  },\n  {\n    \"id\": \"t4\",\n    \"component\": \"Text\",\n    \"variant\": \"body\",\n    \"textContent\": \"Great choice! Let me suggest some patterns for that.\"\n  },\n  {\n    \"id\": \"ftr\",\n    \"component\": \"Footer\",\n    \"children\": [\n      \"input-row\"\n    ]\n  },\n  {\n    \"id\": \"input-row\",\n    \"component\": \"Row\",\n    \"gap\": \"2\",\n    \"children\": [\n      \"chat-input\",\n      \"send-btn\"\n    ]\n  },\n  {\n    \"id\": \"chat-input\",\n    \"component\": \"Input\",\n    \"placeholder\": \"Type a message...\"\n  },\n  {\n    \"id\": \"send-btn\",\n    \"component\": \"Button\",\n    \"text\": \"Send\",\n    \"icon\": \"send\",\n    \"variant\": \"primary\"\n  }\n]",
            "name": "chat-interface"
          },
          {
            "description": "Command palette card with search input and a list of command options.",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"Card\",\n    \"children\": [\n      \"hdr\",\n      \"sec\"\n    ]\n  },\n  {\n    \"id\": \"hdr\",\n    \"component\": \"Header\",\n    \"children\": [\n      \"search\"\n    ]\n  },\n  {\n    \"id\": \"search\",\n    \"component\": \"Input\",\n    \"placeholder\": \"Type a command or search...\",\n    \"icon\": \"search\"\n  },\n  {\n    \"id\": \"sec\",\n    \"component\": \"Section\",\n    \"children\": [\n      \"options\"\n    ]\n  },\n  {\n    \"id\": \"options\",\n    \"component\": \"Column\",\n    \"gap\": \"1\",\n    \"children\": [\n      \"opt1\",\n      \"opt2\",\n      \"opt3\",\n      \"opt4\",\n      \"opt5\"\n    ]\n  },\n  {\n    \"id\": \"opt1\",\n    \"component\": \"Row\",\n    \"gap\": \"2\",\n    \"children\": [\n      \"i1\",\n      \"l1\"\n    ]\n  },\n  {\n    \"id\": \"i1\",\n    \"component\": \"Icon\",\n    \"name\": \"file\"\n  },\n  {\n    \"id\": \"l1\",\n    \"component\": \"Text\",\n    \"textContent\": \"Open File\"\n  },\n  {\n    \"id\": \"opt2\",\n    \"component\": \"Row\",\n    \"gap\": \"2\",\n    \"children\": [\n      \"i2\",\n      \"l2\"\n    ]\n  },\n  {\n    \"id\": \"i2\",\n    \"component\": \"Icon\",\n    \"name\": \"gear\"\n  },\n  {\n    \"id\": \"l2\",\n    \"component\": \"Text\",\n    \"textContent\": \"Settings\"\n  },\n  {\n    \"id\": \"opt3\",\n    \"component\": \"Row\",\n    \"gap\": \"2\",\n    \"children\": [\n      \"i3\",\n      \"l3\"\n    ]\n  },\n  {\n    \"id\": \"i3\",\n    \"component\": \"Icon\",\n    \"name\": \"palette\"\n  },\n  {\n    \"id\": \"l3\",\n    \"component\": \"Text\",\n    \"textContent\": \"Change Theme\"\n  },\n  {\n    \"id\": \"opt4\",\n    \"component\": \"Row\",\n    \"gap\": \"2\",\n    \"children\": [\n      \"i4\",\n      \"l4\"\n    ]\n  },\n  {\n    \"id\": \"i4\",\n    \"component\": \"Icon\",\n    \"name\": \"users\"\n  },\n  {\n    \"id\": \"l4\",\n    \"component\": \"Text\",\n    \"textContent\": \"Manage Users\"\n  },\n  {\n    \"id\": \"opt5\",\n    \"component\": \"Row\",\n    \"gap\": \"2\",\n    \"children\": [\n      \"i5\",\n      \"l5\"\n    ]\n  },\n  {\n    \"id\": \"i5\",\n    \"component\": \"Icon\",\n    \"name\": \"sign-out\"\n  },\n  {\n    \"id\": \"l5\",\n    \"component\": \"Text\",\n    \"textContent\": \"Sign Out\"\n  }\n]",
            "name": "command-palette"
          }
        ],
        "keywords": [
          "input",
          "field",
          "chip",
          "tag"
        ],
        "name": "UIInput",
        "related": [
          "avatar",
          "button",
          "table",
          "pagination",
          "check-box"
        ],
        "slots": {
          "leading": {
            "description": "Leading affordance slot, inside the field chrome, before the\nvalue. Sized to chrome height. Author `<button-ui slot=\"leading\"\nicon=\"...\" variant=\"ghost\" size=\"sm\">` (or any inline element)\nfor inline actions before the value — e.g. a link-icon button\nnext to a URL input. Wired §199 v0.5.7."
          },
          "text": {
            "description": "Contenteditable text surface for user input"
          },
          "trailing": {
            "description": "Trailing affordance slot, inside the field chrome, after the\nvalue (and after [slot=\"suffix\"] if present). Sized to chrome\nheight. Author `<button-ui slot=\"trailing\" icon=\"...\"\nvariant=\"ghost\" size=\"sm\" aria-label=\"...\">` for inline actions\nlike copy / clear / open-in-modal. For trailing text/icon\nlabels (e.g. \"Light\" in a theme picker), use the `suffix` prop\ninstead — affordance slots are for interactive buttons, not\ntext. Wired §199 v0.5.7."
          }
        },
        "states": [
          {
            "description": "Default, ready for interaction.",
            "name": "idle"
          },
          {
            "description": "Non-interactive; dimmed.",
            "attribute": "disabled",
            "name": "disabled"
          },
          {
            "description": "Keyboard focus ring.",
            "name": "focused",
            "selector": ":focus-visible"
          }
        ],
        "status": "stable",
        "synonyms": {
          "chip": [
            "badge",
            "tag",
            "input"
          ],
          "field": [
            "form",
            "create",
            "input"
          ],
          "input": [
            "form",
            "create",
            "tag",
            "input"
          ],
          "tag": [
            "tag",
            "input",
            "badge"
          ],
          "tags": [
            "TextField"
          ]
        },
        "tag": "input-ui",
        "tokens": {
          "--density": {
            "description": "Inherited multiplier for padding"
          },
          "--input-background": {
            "description": "Override default background color"
          },
          "--input-border-color": {
            "description": "Override default border color"
          },
          "--input-border-width": {
            "description": "Override border width"
          },
          "--input-content-height": {
            "description": "Override icon slot and text surface height"
          },
          "--input-disabled-opacity": {
            "description": "Override disabled state opacity"
          },
          "--input-error-border-color": {
            "description": "Override error state border color"
          },
          "--input-focus-border-color": {
            "description": "Override focus state border color"
          },
          "--input-focus-ring": {
            "description": "Override focus ring color"
          },
          "--input-font-family": {
            "description": "Override font family"
          },
          "--input-font-size": {
            "description": "Override font size"
          },
          "--input-font-weight": {
            "description": "Override font weight"
          },
          "--input-foreground": {
            "description": "Override default text color"
          },
          "--input-hover-border-color": {
            "description": "Override hover state border color"
          },
          "--input-line-height": {
            "description": "Override line height"
          },
          "--input-padding": {
            "description": "Override base padding (density-scaled)"
          },
          "--input-placeholder-color": {
            "description": "Override placeholder text color"
          },
          "--input-radius": {
            "description": "Override border radius"
          },
          "--input-transition": {
            "description": "Override transition timing"
          }
        },
        "traits": [
          "focusable"
        ],
        "version": 1
      }
    },
    "Inspector": {
      "title": "Inspector",
      "description": "Developer-tools pane for inspecting A2UI runtime state — composes\n<tabs-ui> + <code-ui> to show the live document JSON, rendered\nHTML, and event log for the bound <canvas-ui> / <a2ui-root>. The\nright-pane inspector of the a2ui-editor app. Use inside an\n<editor-sidebar slot=\"trailing\"> for debugging A2UI playgrounds;\nnot for end-user inspector panes (build those bespoke with\n<field-ui> + form rows per the editor-inspector-pane recipe in\npatterns-recipes.md).\n",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "component": {
          "const": "Inspector"
        },
        "value": {
          "description": "Active tab. One of 'catalog', 'surface', 'messages', 'code'.",
          "type": "string",
          "default": "surface"
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [],
        "category": "agent",
        "composes": [
          "tabs-ui",
          "tab-ui",
          "code-ui"
        ],
        "events": {},
        "examples": [
          {
            "description": "Basic Inspector usage",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"Card\",\n    \"children\": [\n      \"sec\"\n    ]\n  },\n  {\n    \"id\": \"sec\",\n    \"component\": \"Section\",\n    \"children\": [\n      \"comp\"\n    ]\n  },\n  {\n    \"id\": \"comp\",\n    \"component\": \"Inspector\"\n  }\n]",
            "name": "basic-inspector"
          }
        ],
        "keywords": [
          "inspector"
        ],
        "name": "UIInspector",
        "related": [
          "A2uiRoot",
          "EditorSidebar",
          "Code",
          "Tabs"
        ],
        "slots": {
          "default": {
            "description": "Default slot — primary child content."
          }
        },
        "states": [
          {
            "description": "Default, ready for interaction.",
            "name": "idle"
          }
        ],
        "status": "stable",
        "synonyms": {
          "tags": [
            "object-inspector",
            "property-grid",
            "record-detail",
            "devtools-pane"
          ]
        },
        "tag": "inspector-ui",
        "tokens": {},
        "traits": [],
        "version": 1
      }
    },
    "IntegrationCard": {
      "title": "IntegrationCard",
      "description": "Single-tile primitive representing one third-party integration (Slack, GitHub, Stripe, …). Shows the provider logo + name + description + status pill + a single primary action button whose label and variant are derived from `status`. Composes into a grid via the SPEC-063 integrations-page composite. One tile = one provider; the button variant is computed from `status`, not a separate prop. Distinct from <option-card-ui> (a single-select radio with no status / async action) and <card-ui> (the generic bordered surface this specializes).",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "description": {
          "description": "One-line description of what the integration does.",
          "type": "string",
          "default": ""
        },
        "component": {
          "const": "IntegrationCard"
        },
        "disabled": {
          "description": "Disables the action button.",
          "type": "boolean",
          "default": false
        },
        "error-message": {
          "description": "When `status=\"error\"`, the message to show below the description. Ignored for other statuses.",
          "$ref": "#/$defs/DynamicString"
        },
        "logo": {
          "description": "Logo URL (preferred — renders as <img>) or icon name (renders as <icon-ui>). URLs are sniffed by presence of `/`.",
          "type": "string",
          "default": ""
        },
        "name": {
          "description": "Display name shown as the card title. Required.",
          "type": "string",
          "default": ""
        },
        "provider": {
          "description": "Provider key — `slack`, `github`, etc. — used for analytics + a11y label. Required.",
          "type": "string",
          "default": ""
        },
        "status": {
          "description": "Current connection state — drives the button label, variant, and visibility. `available` shows a primary `Connect`; `connected` shows an outline `Configure`; `error` shows an outline `Retry`; `pending` shows a non-interactive spinner; `coming-soon` hides the button.",
          "$ref": "#/$defs/DynamicString"
        }
      },
      "required": [
        "component",
        "provider",
        "name"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [
          {
            "fix": "{\"component\": \"IntegrationCard\", \"provider\": \"slack\",\n \"name\": \"Slack\", \"status\": \"available\"}\n",
            "why": "Manually slotting a Button bypasses the card's status-driven\nbutton semantics. The card renders its own button AND the\nslotted one, producing two actions side-by-side.\n",
            "wrong": "{\"component\": \"IntegrationCard\", \"provider\": \"slack\",\n \"children\": [{\"component\": \"Button\", \"label\": \"Connect\"}]}\n"
          },
          {
            "fix": "{\"component\": \"IntegrationCard\", \"provider\": \"slack\",\n \"name\": \"Slack\", \"logo\": \"/slack.svg\", \"status\": \"available\"}\n",
            "why": "Re-implements IntegrationCard with primitives. Loses status\nbadge semantics, accessible-name wiring, and the typed\nconnect/configure events.\n",
            "wrong": "{\"component\": \"Card\", \"children\": [\n  {\"component\": \"Image\", \"src\": \"/slack.svg\"},\n  {\"component\": \"Text\", \"value\": \"Slack\"},\n  {\"component\": \"Button\", \"label\": \"Connect\"}]}\n"
          }
        ],
        "category": "display",
        "composes": [
          "icon-ui",
          "badge-ui",
          "button-ui"
        ],
        "events": {
          "configure": {
            "description": "Fired when the user clicks the action button while `status=\"connected\"`.",
            "detail": {
              "provider": {
                "description": "The provider key for this card.",
                "type": "string"
              }
            }
          },
          "connect": {
            "description": "Fired when the user clicks the action button while `status=\"available\"`.",
            "detail": {
              "provider": {
                "description": "The provider key for this card.",
                "type": "string"
              }
            }
          },
          "disconnect": {
            "description": "Fired when the consumer wires a `<menu-ui slot=\"actions\">` overflow with a `disconnect` item. The card does not stamp this menu — it bubbles whatever consumer markup dispatches.",
            "detail": {
              "provider": {
                "description": "The provider key for this card.",
                "type": "string"
              }
            }
          },
          "retry": {
            "description": "Fired when the user clicks the action button while `status=\"error\"`.",
            "detail": {
              "provider": {
                "description": "The provider key for this card.",
                "type": "string"
              }
            }
          }
        },
        "examples": [
          {
            "description": "Available integration with logo, description, and primary Connect button.",
            "a2ui": "{\n  \"id\": \"card-slack\",\n  \"component\": \"IntegrationCard\",\n  \"provider\": \"slack\",\n  \"name\": \"Slack\",\n  \"logo\": \"/integrations/slack.svg\",\n  \"description\": \"Send AI replies and notifications to channels.\",\n  \"status\": \"available\"\n}",
            "name": "available"
          },
          {
            "description": "Connected integration with success badge and outline Configure button.",
            "a2ui": "{\n  \"id\": \"card-github\",\n  \"component\": \"IntegrationCard\",\n  \"provider\": \"github\",\n  \"name\": \"GitHub\",\n  \"logo\": \"/integrations/github.svg\",\n  \"description\": \"Sync issues and pull requests.\",\n  \"status\": \"connected\"\n}",
            "name": "connected"
          },
          {
            "description": "Error integration with danger badge, error message, and Retry button.",
            "a2ui": "{\n  \"id\": \"card-stripe\",\n  \"component\": \"IntegrationCard\",\n  \"provider\": \"stripe\",\n  \"name\": \"Stripe\",\n  \"description\": \"Charge customers and reconcile invoices.\",\n  \"status\": \"error\",\n  \"error-message\": \"Token expired — re-authenticate.\"\n}",
            "name": "error"
          },
          {
            "description": "Coming-soon integration with no action button.",
            "a2ui": "{\n  \"id\": \"card-zapier\",\n  \"component\": \"IntegrationCard\",\n  \"provider\": \"zapier\",\n  \"name\": \"Zapier\",\n  \"description\": \"Trigger Zaps from AdiaUI events.\",\n  \"status\": \"coming-soon\"\n}",
            "name": "coming-soon"
          }
        ],
        "keywords": [
          "integration",
          "connect",
          "provider",
          "slack",
          "github",
          "stripe",
          "oauth",
          "third-party",
          "settings",
          "integrations",
          "card",
          "tile"
        ],
        "name": "UIIntegrationCard",
        "related": [
          "card",
          "badge",
          "button",
          "menu"
        ],
        "slots": {
          "default": {
            "description": "Optional override for the description. When a non-empty default slot is provided it supersedes the `description` prop."
          },
          "actions": {
            "description": "Optional secondary actions — typically a <menu-ui> overflow carrying `Reauthenticate` / `Disconnect` entries. Collapses when empty."
          }
        },
        "states": [
          {
            "description": "Default — `[status=\"available\"]`.",
            "name": "idle"
          },
          {
            "description": "Ready to connect.",
            "attribute": "status=\"available\"",
            "name": "available"
          },
          {
            "description": "Linked — success-tinted border, check badge, outline `Configure` button.",
            "attribute": "status=\"connected\"",
            "name": "connected"
          },
          {
            "description": "Connection failed — danger-tinted border, error message visible, outline `Retry` button.",
            "attribute": "status=\"error\"",
            "name": "error"
          },
          {
            "description": "Awaiting response — button shows spinner, non-interactive.",
            "attribute": "status=\"pending\"",
            "name": "pending"
          },
          {
            "description": "Listed but not yet enabled — opacity reduced, button hidden, \"Coming soon\" badge shown.",
            "attribute": "status=\"coming-soon\"",
            "name": "coming-soon"
          },
          {
            "description": "Non-interactive; dimmed.",
            "attribute": "disabled",
            "name": "disabled"
          }
        ],
        "status": "stable",
        "synonyms": {
          "connect": [
            "integration",
            "oauth",
            "connection"
          ],
          "integration": [
            "integration",
            "connect",
            "provider",
            "third-party"
          ],
          "oauth": [
            "integration",
            "connect",
            "auth"
          ],
          "provider": [
            "integration",
            "third-party",
            "service"
          ],
          "settings": [
            "settings",
            "integration",
            "account"
          ]
        },
        "tag": "integration-card-ui",
        "tokens": {
          "--integration-card-bg": {
            "description": "Card background. Defaults to `--a-bg`."
          },
          "--integration-card-border": {
            "description": "Card border color. Defaults to `--a-border`."
          },
          "--integration-card-description-fg": {
            "description": "Description text color."
          },
          "--integration-card-error-fg": {
            "description": "Error-message text color (used when `status=\"error\"`)."
          },
          "--integration-card-gap": {
            "description": "Vertical rhythm between header / body / footer."
          },
          "--integration-card-heading-fg": {
            "description": "Provider name color."
          },
          "--integration-card-logo-size": {
            "description": "Logo square dimension. Defaults to `--a-space-7`."
          },
          "--integration-card-px": {
            "description": "Horizontal padding. Defaults to `--a-space-4`."
          },
          "--integration-card-py": {
            "description": "Vertical padding. Defaults to `--a-space-4`."
          },
          "--integration-card-radius": {
            "description": "Card corner radius. Defaults to `--a-radius-md`."
          }
        },
        "traits": [],
        "version": 1
      }
    },
    "IntegrationsPage": {
      "title": "IntegrationsPage",
      "description": "Module-tier Settings page composite — a searchable, category-grouped\ngrid of <integration-card-ui> tiles (SPEC-062). Owns the\n`integrations` array, the search-filter state, the category /\nstatus grouping, the responsive grid breakpoints, and the empty-state\ncopy. Card-level events (`connect` / `configure` / `disconnect` /\n`retry`) bubble up unchanged with `provider` in detail; the page also\nemits `search` (debounced) and a top-bar `filter-change` when the\nuser picks a status chip.\n\nLives in `packages/web-modules/settings/integrations-page/` per the\nthree-tier architecture — composes multiple primitives, holds layout\nresponsibility, consumed by the settings shell. Replaces the\nhand-rolled `settings/integrations` HTML template per consumer.\n\nSpec: docs/specs/implementation-ready/SPEC-063-integrations-page.md\n",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "component": {
          "const": "IntegrationsPage"
        },
        "group-by": {
          "description": "How to bucket cards into sections. `category` groups by the per-item\n`category` key; `status` groups by connection state; `none` renders\na single ungrouped grid.\n",
          "type": "string",
          "enum": [
            "category",
            "status",
            "none"
          ],
          "default": "category"
        },
        "integrations": {
          "description": "Array of integration descriptors — each item conforms to the\nSPEC-062 <integration-card-ui> prop shape:\n`{ provider, name, logo?, description?, status, category?,\nerror-message? }`. Empty array renders the empty-state slot.\n",
          "$ref": "#/$defs/DynamicStringList"
        },
        "loading": {
          "description": "Renders a skeleton grid (6 tiles) instead of cards. Driven by the\nconsumer while the integrations payload is in flight.\n",
          "$ref": "#/$defs/DynamicBoolean"
        },
        "search-placeholder": {
          "description": "Placeholder copy for the built-in search input. Defaults to\n\"Search integrations\".\n",
          "type": "string",
          "default": "Search integrations"
        },
        "status-filter": {
          "description": "Optional status filter — restricts the visible cards to one status.\n`all` (default) shows everything; the rest restrict to that status\nbucket. Reflects so consumers can deep-link.\n",
          "$ref": "#/$defs/DynamicString"
        }
      },
      "required": [
        "component",
        "integrations"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [
          {
            "fix": "{\"component\": \"IntegrationsPage\", \"integrations\": [\n  {\"provider\": \"slack\", \"name\": \"Slack\", \"status\": \"available\"}\n]}\n",
            "why": "Slotted cards are ignored — the page generates cards from the\n`integrations` prop. The page renders empty.\n",
            "wrong": "{\"component\": \"IntegrationsPage\", \"children\": [\n  {\"component\": \"IntegrationCard\", \"provider\": \"slack\", \"name\": \"Slack\"}\n]}\n"
          },
          {
            "fix": "{\"component\": \"IntegrationsPage\", \"integrations\": [\n  {\"provider\": \"slack\", \"name\": \"Slack\", \"status\": \"available\"}\n]}\n",
            "why": "Re-implements the page composite with primitives. Loses search,\ngrouping, and empty-state semantics.\n",
            "wrong": "{\"component\": \"Page\", \"children\": [\n  {\"component\": \"Grid\", \"children\": [\n    {\"component\": \"IntegrationCard\", \"provider\": \"slack\", \"name\": \"Slack\"}\n  ]}\n]}\n"
          }
        ],
        "category": "container",
        "composes": [
          "integration-card-ui",
          "grid-ui",
          "search-ui",
          "segmented-ui",
          "segment-ui",
          "text-ui"
        ],
        "events": {
          "configure": {
            "description": "Bubbled from a child <integration-card-ui> while `status=\"connected\"`.",
            "detail": {
              "provider": {
                "description": "The provider key of the card that fired.",
                "type": "string"
              }
            }
          },
          "connect": {
            "description": "Bubbled from a child <integration-card-ui> when its primary button is pressed while `status=\"available\"`.",
            "detail": {
              "provider": {
                "description": "The provider key of the card that fired.",
                "type": "string"
              }
            }
          },
          "disconnect": {
            "description": "Bubbled from a child card's overflow menu disconnect item.",
            "detail": {
              "provider": {
                "description": "The provider key of the card that fired.",
                "type": "string"
              }
            }
          },
          "filter-change": {
            "description": "User clicked a status filter chip in the top bar.",
            "detail": {
              "status": {
                "description": "The newly-selected status filter (`all` resets).",
                "type": "string"
              }
            }
          },
          "retry": {
            "description": "Bubbled from a child <integration-card-ui> while `status=\"error\"`.",
            "detail": {
              "provider": {
                "description": "The provider key of the card that fired.",
                "type": "string"
              }
            }
          },
          "search": {
            "description": "Debounced search input change.",
            "detail": {
              "query": {
                "description": "The current search query (lower-cased, trimmed).",
                "type": "string"
              }
            }
          }
        },
        "examples": [
          {
            "description": "Full integrations page grouped by category (default).",
            "a2ui": "[\n  {\n    \"id\": \"page\",\n    \"component\": \"IntegrationsPage\",\n    \"group-by\": \"category\",\n    \"integrations\": [\n      {\"provider\": \"slack\",  \"name\": \"Slack\",  \"logo\": \"/integrations/slack.svg\",\n       \"description\": \"Notifications and replies in channels.\",\n       \"status\": \"connected\", \"category\": \"Communication\"},\n      {\"provider\": \"github\", \"name\": \"GitHub\", \"logo\": \"/integrations/github.svg\",\n       \"description\": \"Sync issues and pull requests.\",\n       \"status\": \"available\", \"category\": \"Developer Tools\"},\n      {\"provider\": \"stripe\", \"name\": \"Stripe\", \"logo\": \"/integrations/stripe.svg\",\n       \"description\": \"Charge customers and reconcile invoices.\",\n       \"status\": \"error\", \"category\": \"Payments\",\n       \"error-message\": \"Token expired — re-authenticate.\"}\n    ]\n  }\n]\n",
            "name": "category-grouped"
          },
          {
            "description": "Loading state — 6 skeleton tiles, no cards.",
            "a2ui": "[{\"id\": \"page\", \"component\": \"IntegrationsPage\", \"loading\": true}]\n",
            "name": "loading-skeleton"
          },
          {
            "description": "Empty state — no integrations available.",
            "a2ui": "[{\"id\": \"page\", \"component\": \"IntegrationsPage\", \"integrations\": []}]\n",
            "name": "empty-data"
          }
        ],
        "keywords": [
          "integrations",
          "integration",
          "settings",
          "settings-page",
          "connections",
          "third-party",
          "oauth",
          "providers",
          "app-directory",
          "marketplace"
        ],
        "name": "UIIntegrationsPage",
        "related": [
          "IntegrationCard",
          "Grid",
          "Search",
          "Segmented",
          "Page"
        ],
        "slots": {
          "empty": {
            "description": "Optional override for the empty-state copy. When supplied, replaces\nthe built-in \"No integrations match\" / \"No integrations available\"\nmessages.\n"
          },
          "header": {
            "description": "Optional page header (kicker / title / subtitle). Overrides the\ndefault rendering — when supplied the composite stamps no\nbuilt-in heading.\n"
          }
        },
        "states": [
          {
            "description": "Default; renders all groups matching the current filter.",
            "name": "idle"
          },
          {
            "description": "Skeleton grid; cards hidden.",
            "attribute": "loading",
            "name": "loading"
          },
          {
            "description": "Search query yields zero cards.",
            "attribute": "data-empty-search",
            "name": "empty-search"
          },
          {
            "description": "`integrations` array is empty.",
            "attribute": "data-empty-data",
            "name": "empty-data"
          }
        ],
        "status": "stable",
        "synonyms": {
          "integrations": [
            "integration",
            "connections",
            "apps",
            "providers"
          ],
          "marketplace": [
            "integrations",
            "app-directory",
            "apps"
          ],
          "oauth": [
            "integration",
            "connection",
            "auth"
          ],
          "settings": [
            "settings",
            "account",
            "admin"
          ]
        },
        "tag": "integrations-page-ui",
        "tokens": {
          "--integrations-page-bg": {
            "description": "Page background. Defaults to `var(--a-bg)`.",
            "default": "var(--a-bg)"
          },
          "--integrations-page-card-gap": {
            "description": "Gap inside the grid between cards.",
            "default": "var(--a-space-4)"
          },
          "--integrations-page-fg": {
            "description": "Primary foreground. Defaults to `var(--a-fg)`.",
            "default": "var(--a-fg)"
          },
          "--integrations-page-fg-muted": {
            "description": "Secondary foreground for empty-state copy + section meta.",
            "default": "var(--a-fg-muted)"
          },
          "--integrations-page-gap": {
            "description": "Vertical gap between toolbar / sections / empty-state.",
            "default": "var(--a-space-5)"
          },
          "--integrations-page-grid-min": {
            "description": "Minimum card width for the auto-fill grid track.",
            "default": "var(--a-space-12)"
          },
          "--integrations-page-px": {
            "description": "Horizontal padding around the page.",
            "default": "var(--a-space-5)"
          },
          "--integrations-page-py": {
            "description": "Vertical padding around the page.",
            "default": "var(--a-space-5)"
          },
          "--integrations-page-section-gap": {
            "description": "Vertical gap between sibling category sections.",
            "default": "var(--a-space-6)"
          },
          "--integrations-page-section-heading-fg": {
            "description": "Section heading color.",
            "default": "var(--a-fg-strong)"
          },
          "--integrations-page-section-heading-size": {
            "description": "Section heading font size.",
            "default": "var(--a-ui-sm)"
          },
          "--integrations-page-section-heading-weight": {
            "description": "Section heading font weight.",
            "default": "var(--a-weight-medium)"
          }
        },
        "traits": [],
        "version": 1
      }
    },
    "InvoiceDetail": {
      "title": "InvoiceDetail",
      "description": "Module-tier page composite that renders a single invoice — header\n(number + status badge + dates), line-items table, totals block,\ncustomer + remit-to blocks, and a slot-driven action toolbar.\nThe canonical invoice layout shared by billing-enabled products\nso totals math, status-badge color mapping, and action-toolbar\norder do not drift across surfaces.\n\nData-driven via the `invoice` property OR a `data-stream-src`\nendpoint. The composite stamps a six-region skeleton once on\nfirst connect — header · meta · parties · lines · totals ·\nfooter — then mutates per-region nodes via id-keyed in-place\ndiff on every property change. The status badge color maps\nfrom `invoice.status` (paid → success, past-due → warning,\nvoid → muted, open/draft → default). Action buttons are\nconsumer-slotted into `header-actions` per spec OD-002 (always\nslot, never stamp a default toolbar).\n\nPrint-friendly: an internal `@media print` branch hides the\naction toolbar + zeroes the page padding. The composite is a\ndisplay surface — extends UIElement, not UIFormElement.\n\nSpec: docs/specs/implementation-ready/SPEC-007-invoice-detail-page.md.\n",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "component": {
          "const": "InvoiceDetail"
        },
        "currency": {
          "description": "ISO 4217 currency code for amount formatting via\nIntl.NumberFormat. Overridable per-record via invoice.currency.\n",
          "type": "string",
          "default": "USD"
        },
        "data-stream-src": {
          "description": "Optional endpoint returning the invoice record (universal\ndata-stream-* trait). On successful load, `invoice` is\nreplaced and a `load` event fires; on failure an `error`\nevent fires.\n",
          "type": "string",
          "default": ""
        },
        "density": {
          "description": "Line-items table row density. `compact` for tightly-packed\ninvoices with many line items; `standard` for typical invoices.\nForwarded to the embedded <table-ui density>.\n",
          "type": "string",
          "enum": [
            "compact",
            "standard"
          ],
          "default": "standard"
        },
        "invoice": {
          "description": "The invoice record. Source of truth for the rendered page.\nShape: {number, status, issuedAt, dueAt, customer:{name,email},\nremitTo?:{name,address?}, lines:[{description,qty,unitAmount,\namount}], subtotal, tax, discount?, total, currency,\nnotes?:string}. Null + no data-stream-src renders the empty\nstate.\n",
          "type": "object",
          "default": null
        },
        "loading": {
          "description": "Renders skeleton placeholders for header + line-items + totals\nwhile a data-stream-src fetch is in flight. Sets aria-busy\non the host. Data updates suppressed while [loading] is set.\n",
          "$ref": "#/$defs/DynamicBoolean"
        },
        "locale": {
          "description": "Locale for Intl.NumberFormat (amounts) and Intl.DateTimeFormat\n(issued/due). Defaults to document.documentElement.lang (or\n\"en-US\" when absent).\n",
          "type": "string",
          "default": ""
        },
        "printable": {
          "description": "Includes the @media print branch — hides the action toolbar\nand zeroes page padding so the printed output is invoice-only.\nSet [printable] to false on screens where the invoice is\nembedded inside a larger surface and printing should not be\na first-class action.\n",
          "type": "boolean",
          "default": true
        },
        "status": {
          "description": "Mirrors invoice.status. Drives the status badge `variant`\nmapping (paid → success, past-due → warning, void → muted,\nopen/draft → default). When set independently of `invoice`,\nthe host status reflection wins for CSS — useful when the\nhost wraps an invoice without a status field.\n",
          "$ref": "#/$defs/DynamicString"
        }
      },
      "required": [
        "component",
        "invoice"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [
          {
            "fix": "{\"component\": \"InvoiceDetail\", \"invoice\":\n  {\"lines\": [...], \"subtotal\": 24, \"total\": 24.5, \"currency\": \"USD\"}}\n",
            "why": "Line items belong on `invoice.lines`, not the host. Without\nthe wrapping `invoice` object, totals + currency are unwired\nand the composite renders the empty state.\n",
            "wrong": "{\"component\": \"InvoiceDetail\", \"lines\": [...]}\n"
          },
          {
            "fix": "Open the invoice via <a href=\"/invoices/INV-001234\"> route\nnavigation; render the InvoiceDetail composite on that route.\n",
            "why": "Invoices are routes, not modals. Modal traps focus + clips\non long content; the composite is designed for full-page\nlayout.\n",
            "wrong": "{\"component\": \"Modal\", \"children\":\n  [{\"component\": \"InvoiceDetail\", \"invoice\": {...}}]}\n"
          },
          {
            "fix": "<invoice-detail-ui status=\"paid\"></invoice-detail-ui>\n",
            "why": "`settled` is not in the status enum. Unknown statuses fall\nback to the default badge variant; the consumer surface\nloses the semantic color mapping.\n",
            "wrong": "<invoice-detail-ui status=\"settled\"></invoice-detail-ui>\n"
          }
        ],
        "category": "container",
        "composes": [
          "card-ui",
          "table-ui",
          "stat-ui",
          "tag-ui",
          "button-ui",
          "text-ui",
          "icon-ui",
          "empty-state-ui"
        ],
        "events": {
          "error": {
            "description": "Fired when a data-stream-src fetch fails OR when the host is\nasked to print but window.print is unavailable. Bubbles.\n",
            "detail": {
              "reason": {
                "description": "One of `fetch-failed`, `print-unavailable`.",
                "type": "string"
              }
            }
          },
          "invoice-action": {
            "description": "Fired when a header-action button carrying\n[data-invoice-action] is activated. Consumers wire this to\ndownload / send / pay / void flows. Bubbles.\n",
            "detail": {
              "action": {
                "description": "The data-invoice-action value (download, send, pay, etc.).",
                "type": "string"
              },
              "invoiceNumber": {
                "description": "invoice.number at the time of activation.",
                "type": "string"
              }
            }
          },
          "line-item-click": {
            "description": "Fired when a line-item row is clicked. Bubbles.\n",
            "detail": {
              "index": {
                "description": "0-based row index within invoice.lines.",
                "type": "integer"
              },
              "lineItem": {
                "description": "The clicked invoice.lines[index] record.",
                "type": "object"
              }
            }
          },
          "load": {
            "description": "Fired when a data-stream-src fetch resolves and the invoice\nrecord is populated. Bubbles.\n",
            "detail": {
              "invoiceNumber": {
                "description": "The loaded invoice.number.",
                "type": "string"
              }
            }
          }
        },
        "examples": [
          {
            "description": "A paid invoice with two line items + slotted actions.",
            "a2ui": "[\n  {\n    \"id\": \"inv-paid\",\n    \"component\": \"InvoiceDetail\",\n    \"status\": \"paid\",\n    \"currency\": \"USD\",\n    \"invoice\": {\n      \"number\": \"INV-001234\",\n      \"status\": \"paid\",\n      \"issuedAt\": \"2026-05-01\",\n      \"dueAt\": \"2026-05-15\",\n      \"customer\": {\"name\": \"Acme Co.\", \"email\": \"billing@acme.test\"},\n      \"lines\": [\n        {\"description\": \"Pro plan — May\", \"qty\": 1, \"unitAmount\": 24.00, \"amount\": 24.00},\n        {\"description\": \"Add-on — Audit log retention\", \"qty\": 1, \"unitAmount\": 0.50, \"amount\": 0.50}\n      ],\n      \"subtotal\": 24.50,\n      \"tax\": 0,\n      \"total\": 24.50,\n      \"currency\": \"USD\"\n    },\n    \"children\": [\"btn-download\"]\n  },\n  {\"id\": \"btn-download\", \"component\": \"Button\",\n   \"text\": \"Download\", \"slot\": \"header-actions\"}\n]\n",
            "name": "paid-invoice"
          },
          {
            "description": "Open invoice awaiting payment + Pay CTA.",
            "a2ui": "[\n  {\n    \"id\": \"inv-open\",\n    \"component\": \"InvoiceDetail\",\n    \"status\": \"open\",\n    \"currency\": \"USD\",\n    \"invoice\": {\n      \"number\": \"INV-001235\",\n      \"status\": \"open\",\n      \"issuedAt\": \"2026-05-10\",\n      \"dueAt\": \"2026-05-24\",\n      \"customer\": {\"name\": \"Globex Corp.\", \"email\": \"ap@globex.test\"},\n      \"lines\": [\n        {\"description\": \"Team seats × 5\", \"qty\": 5, \"unitAmount\": 10.00, \"amount\": 50.00}\n      ],\n      \"subtotal\": 50.00,\n      \"tax\": 5.00,\n      \"total\": 55.00,\n      \"currency\": \"USD\"\n    },\n    \"children\": [\"btn-pay-open\"]\n  },\n  {\"id\": \"btn-pay-open\", \"component\": \"Button\",\n   \"text\": \"Pay $55\", \"variant\": \"primary\",\n   \"slot\": \"header-actions\"}\n]\n",
            "name": "open-invoice"
          }
        ],
        "keywords": [
          "invoice",
          "invoice-detail",
          "billing",
          "receipt",
          "bill",
          "statement",
          "payment",
          "line-items",
          "charges",
          "totals",
          "paid",
          "past-due",
          "void"
        ],
        "name": "UIInvoiceDetail",
        "related": [
          "Card",
          "Table",
          "Stat",
          "Tag",
          "Button",
          "EmptyState",
          "PlanPicker"
        ],
        "slots": {
          "customer-block": {
            "description": "Override the default customer block. When unset, the composite\nrenders a default block from invoice.customer.\n"
          },
          "footer": {
            "description": "Optional content below the totals — payment instructions,\nterms, fine print.\n"
          },
          "header-actions": {
            "description": "Action toolbar slotted into the top-right of the invoice\nheader — Download, Send, Pay, etc. Consumer-owned per\nSPEC-007 OD-002 (the composite NEVER stamps a default\ntoolbar; action sets vary too much across products).\nButtons carrying [data-invoice-action] dispatch the host's\n`invoice-action` event on activation.\n"
          },
          "remit-to-block": {
            "description": "Override the default remit-to block. When unset, the composite\nrenders a default block from invoice.remitTo if present.\n"
          }
        },
        "states": [
          {
            "description": "Default — invoice rendered, ready for interaction.",
            "name": "idle"
          },
          {
            "description": "A data-stream-src fetch is in flight.",
            "attribute": "loading",
            "name": "loading"
          },
          {
            "description": "No invoice + no data-stream-src.",
            "attribute": "empty",
            "name": "empty"
          },
          {
            "description": "Last data-stream-src fetch failed.",
            "attribute": "error",
            "name": "error"
          }
        ],
        "status": "experimental",
        "synonyms": {
          "invoice": [
            "bill",
            "receipt",
            "statement"
          ],
          "line-items": [
            "charges",
            "entries"
          ],
          "payment": [
            "charge",
            "billing"
          ]
        },
        "tag": "invoice-detail-ui",
        "tokens": {
          "--invoice-detail-amount-fg": {
            "description": "Color for monetary amounts in the totals stack.",
            "default": "var(--a-fg)"
          },
          "--invoice-detail-bg": {
            "description": "Host page background. Defaults to transparent.",
            "default": "transparent"
          },
          "--invoice-detail-line-amount-align": {
            "description": "Text-align for the rightmost amount column in the lines table.\n`end` for typical right-aligned numerics.\n",
            "default": "end"
          },
          "--invoice-detail-meta-fg": {
            "description": "Color for the secondary header metadata (issued / due).",
            "default": "var(--a-fg-muted)"
          },
          "--invoice-detail-page-padding": {
            "description": "Inset around the invoice content area.",
            "default": "var(--a-space-5)"
          },
          "--invoice-detail-section-gap": {
            "description": "Vertical gap between header, parties, lines, totals.",
            "default": "var(--a-space-5)"
          },
          "--invoice-detail-status-badge-radius": {
            "description": "Status badge corner radius.",
            "default": "var(--a-radius-md)"
          },
          "--invoice-detail-total-size": {
            "description": "Font size for the grand total line.",
            "default": "var(--a-text-2xl, 1.5rem)"
          },
          "--invoice-detail-total-weight": {
            "description": "Font weight for the grand total line.",
            "default": "var(--a-weight-bold, 700)"
          },
          "--invoice-detail-totals-width": {
            "description": "Width of the right-aligned totals stack. Clamps to 100% on\nnarrow viewports.\n",
            "default": "min(360px, 100%)"
          }
        },
        "traits": [],
        "version": 1
      }
    },
    "InvoiceHistory": {
      "title": "InvoiceHistory",
      "description": "Canonical billing-list composite — a pre-configured <table-ui> with\ninvoice-shaped columns (number, issued, due, amount, status, actions),\nstatus-badge cell renderer (paid/open/past-due/void/draft → semantic\nbadge variant), currency cell renderer, optional search + filter\nchips via <table-toolbar-ui>, and a row-click that navigates to the\ninvoice detail page.\n\nWraps <table-ui> with billing-shaped columns + cell renderers + a\nCSV-export toolbar. Consumer passes invoices[]; the composite owns\ncolumn shape, status-to-badge mapping, currency formatting, date\nformatting, and navigation. Sibling to SPEC-007 (invoice detail).\n\nEach invoice record: {id, number, status, issuedAt, dueAt, amount,\ncurrency}. status MUST be one of \"draft\" | \"open\" | \"paid\" |\n\"past-due\" | \"void\"; unknown values fall back to a neutral badge.\n\nSpec: docs/specs/implementation-ready/SPEC-008-invoice-history-table.md.\n",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "component": {
          "const": "InvoiceHistory"
        },
        "currency": {
          "description": "Default ISO 4217 currency code for amount formatting. Overridable\nper-row via invoices[].currency.\n",
          "type": "string",
          "default": "USD"
        },
        "data-stream-src": {
          "description": "Optional endpoint returning the `invoices` array (universal\ndata-stream-* trait). On successful load, `invoices` is replaced\nand a `load` event fires; on failure an `error` event fires.\n",
          "type": "string",
          "default": ""
        },
        "density": {
          "description": "Row density, forwarded to <table-ui>. `compact` for dense lists,\n`standard` for default rows, `comfortable` for spacious rows.\n",
          "type": "string",
          "enum": [
            "compact",
            "standard",
            "comfortable"
          ],
          "default": "standard"
        },
        "exportable": {
          "description": "When set, the default toolbar carries an \"Export CSV\" button.\nConsumers overriding the toolbar via slot=\"toolbar\" can omit\nthis and stamp their own export affordance.\n",
          "type": "boolean",
          "default": true
        },
        "filter": {
          "description": "Active status filter — narrows visible rows to a single status\nbucket. Empty string = show all. Mirrors the toolbar chip-group\nselection state.\n",
          "$ref": "#/$defs/DynamicString"
        },
        "hrefPattern": {
          "description": "URL template for row-click navigation. The literal `{number}` is\nreplaced with the invoice's number on click. Defaults to\n`/invoices/{number}`.\n",
          "type": "string",
          "default": "/invoices/{number}"
        },
        "invoices": {
          "description": "Array of invoice records. Source of truth for the rendered rows.\nShape per record: {id, number, status, issuedAt, dueAt, amount,\ncurrency?}. status must be one of \"draft\" | \"open\" | \"paid\" |\n\"past-due\" | \"void\". Empty array renders the empty-state.\n",
          "$ref": "#/$defs/DynamicStringList"
        },
        "loading": {
          "description": "Forwarded to <table-ui> — renders skeleton rows instead of data\nwhile a fetch is in flight.\n",
          "$ref": "#/$defs/DynamicBoolean"
        },
        "locale": {
          "description": "Locale for Intl.NumberFormat (amount) and Intl.DateTimeFormat\n(issuedAt / dueAt). Defaults to document.documentElement.lang\n(or \"en-US\" when absent).\n",
          "type": "string",
          "default": ""
        },
        "paginate": {
          "description": "Rows per page, forwarded to <table-ui>. 0 = show all rows.\n",
          "type": "number",
          "default": 25
        },
        "selectable": {
          "description": "When set, enables row selection via a leading checkbox column on\nthe underlying <table-ui> (bulk-action surface).\n",
          "type": "boolean",
          "default": false
        }
      },
      "required": [
        "component",
        "invoices"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [
          {
            "fix": "<invoice-history-ui .invoices=\"${rows}\"></invoice-history-ui>\n",
            "why": "Hand-rolled billing list. Reinvents the canonical composite,\ndrifts on status-badge mapping, currency formatting, and\ndate format.\n",
            "wrong": "<table-ui sortable>\n  <col-def key=\"number\" label=\"Invoice\"></col-def>\n  <col-def key=\"status\" label=\"Status\"></col-def>\n</table-ui>\n"
          },
          {
            "fix": "<invoice-history-ui .invoices=\"${rows}\"></invoice-history-ui>\n",
            "why": "Columns are owned by the composite. Custom columns belong on a\ndifferent <table-ui> composition.\n",
            "wrong": "<invoice-history-ui .columns=\"${customColumns}\"\n                    .invoices=\"${rows}\"></invoice-history-ui>\n"
          }
        ],
        "category": "display",
        "composes": [
          "table-ui",
          "table-toolbar-ui",
          "badge-ui",
          "button-ui",
          "empty-state-ui",
          "pagination-ui"
        ],
        "events": {
          "error": {
            "description": "Fired when a `data-stream-src` fetch fails. Bubbles.\n",
            "detail": {
              "reason": {
                "description": "One of `fetch-failed`.",
                "type": "string"
              }
            }
          },
          "invoice-export": {
            "description": "Fired when the default \"Export CSV\" toolbar button is pressed.\nDetail carries the generated blob; consumers may preventDefault\nto suppress the default download. Bubbles.\n",
            "detail": {
              "blob": {
                "description": "The generated text/csv Blob.",
                "type": "object"
              },
              "rowCount": {
                "description": "Number of rows in the export.",
                "type": "integer"
              }
            }
          },
          "invoice-filter-change": {
            "description": "Fired when the status filter changes via the toolbar chip group.\nBubbles.\n",
            "detail": {
              "filter": {
                "description": "New status filter value (empty string = all).",
                "type": "string",
                "enum": [
                  "",
                  "draft",
                  "open",
                  "paid",
                  "past-due",
                  "void"
                ]
              },
              "previous": {
                "description": "Previous filter value.",
                "type": "string"
              }
            }
          },
          "invoice-row-click": {
            "description": "Fired when an invoice row is activated (mouse click or keyboard\nEnter / Space). Listener can preventDefault() to suppress the\ndefault `window.location.assign(href)` navigation. Bubbles.\n",
            "detail": {
              "href": {
                "description": "Resolved navigation URL.",
                "type": "string"
              },
              "invoice": {
                "description": "The invoice record under the clicked row.",
                "type": "object"
              }
            }
          },
          "invoice-selection-change": {
            "description": "Fired when row selection changes (only when `selectable` is set).\nBubbles.\n",
            "detail": {
              "selected": {
                "description": "Array of selected invoice records.",
                "type": "array"
              }
            }
          },
          "load": {
            "description": "Fired when `data-stream-src` finishes a successful fetch and\n`invoices` is populated. Bubbles.\n",
            "detail": {
              "count": {
                "description": "Number of invoices loaded.",
                "type": "integer"
              }
            }
          }
        },
        "examples": [
          {
            "description": "6-column billing list with status badges, currency formatting, and pagination.",
            "a2ui": "[\n  {\n    \"id\": \"inv-hist-1\",\n    \"component\": \"InvoiceHistory\",\n    \"currency\": \"USD\",\n    \"paginate\": 25,\n    \"invoices\": [\n      {\"id\":\"i1\",\"number\":\"INV-001234\",\"status\":\"paid\",\"issuedAt\":\"2026-05-01\",\"dueAt\":\"2026-05-15\",\"amount\":24.50},\n      {\"id\":\"i2\",\"number\":\"INV-001235\",\"status\":\"open\",\"issuedAt\":\"2026-05-08\",\"dueAt\":\"2026-05-22\",\"amount\":24.50},\n      {\"id\":\"i3\",\"number\":\"INV-001236\",\"status\":\"past-due\",\"issuedAt\":\"2026-04-15\",\"dueAt\":\"2026-04-29\",\"amount\":24.50}\n    ]\n  }\n]\n",
            "name": "canonical"
          },
          {
            "description": "Server-streamed invoices via data-stream-src.",
            "a2ui": "[\n  {\n    \"id\": \"inv-hist-stream\",\n    \"component\": \"InvoiceHistory\",\n    \"data-stream-src\": \"/api/invoices\",\n    \"currency\": \"USD\",\n    \"paginate\": 50\n  }\n]\n",
            "name": "streamed"
          }
        ],
        "keywords": [
          "invoice",
          "invoices",
          "billing",
          "invoice-history",
          "invoice-list",
          "payments-history",
          "receipt",
          "receipts",
          "statement",
          "statements",
          "subscription",
          "charges",
          "past-due",
          "paid",
          "billing-list",
          "billing-table",
          "download-invoice",
          "export-invoices"
        ],
        "name": "InvoiceHistory",
        "related": [
          "Table",
          "TableToolbar",
          "Badge",
          "Button",
          "EmptyState",
          "Pagination"
        ],
        "slots": {
          "empty": {
            "description": "Custom empty-state content when `invoices` is empty. Falls back\nto a default <empty-state-ui icon=\"receipt\"> when omitted.\n"
          },
          "toolbar": {
            "description": "Optional pre-table action toolbar — overrides the default\n<table-toolbar-ui> + export button stamp. Use when the host\nsurface needs custom actions (e.g. \"New invoice\", \"Reconcile\").\n"
          }
        },
        "states": [
          {
            "description": "Default — rows rendered, ready for interaction.",
            "name": "idle"
          },
          {
            "description": "A `data-stream-src` fetch is in flight.",
            "attribute": "loading",
            "name": "loading"
          },
          {
            "description": "No invoices to render (computed from invoices.length).",
            "attribute": "empty",
            "name": "empty"
          },
          {
            "description": "Last `data-stream-src` fetch failed.",
            "attribute": "error",
            "name": "error"
          }
        ],
        "status": "experimental",
        "synonyms": {
          "billing": [
            "invoice",
            "payment",
            "subscription"
          ],
          "history": [
            "log",
            "audit",
            "record",
            "timeline"
          ],
          "invoice": [
            "bill",
            "statement",
            "receipt"
          ],
          "receipts": [
            "invoices",
            "billing"
          ],
          "statement": [
            "invoice",
            "bill"
          ]
        },
        "tag": "invoice-history-ui",
        "tokens": {
          "--invoice-history-amount-fg": {
            "description": "Amount cell foreground.",
            "default": "var(--a-fg-strong, var(--a-fg))"
          },
          "--invoice-history-amount-font": {
            "description": "Font family for tabular amounts; defaults to the mono stack.",
            "default": "var(--a-font-mono)"
          },
          "--invoice-history-bg": {
            "description": "Host background. Defaults to transparent.",
            "default": "transparent"
          },
          "--invoice-history-date-fg": {
            "description": "Secondary metadata (issued / due dates) foreground.",
            "default": "var(--a-fg-muted)"
          },
          "--invoice-history-filter-gap": {
            "description": "Gap between status-filter chips.",
            "default": "var(--a-space-2)"
          },
          "--invoice-history-gap": {
            "description": "Vertical gap between toolbar / table / pagination regions.",
            "default": "var(--a-space-3)"
          },
          "--invoice-history-row-min-height": {
            "description": "Forwarded as `--table-row-h` to <table-ui>; row minimum height.",
            "default": "var(--table-row-h, 3rem)"
          },
          "--invoice-history-toolbar-gap": {
            "description": "Gap between toolbar clusters (title · filter chips · export).",
            "default": "var(--a-space-3)"
          }
        },
        "traits": [],
        "version": 1
      }
    },
    "Kbd": {
      "title": "Kbd",
      "description": "Keyboard key cap. Purely decorative, content from innerHTML — typically a single key or short chord like \"⌘K\" or \"Ctrl+Shift+P\". Use inline in menu items, tooltips, command hints, and shortcut documentation.",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "component": {
          "const": "Kbd"
        },
        "size": {
          "description": "Sizing scale: sm, md (default), lg.",
          "type": "string",
          "enum": [
            "sm",
            "md",
            "lg"
          ],
          "default": ""
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [],
        "category": "display",
        "composes": [],
        "events": {},
        "examples": [
          {
            "description": "Card displaying a grid of keyboard shortcut rows with key badges and descriptions.",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"Card\",\n    \"children\": [\n      \"hdr\",\n      \"sec\"\n    ]\n  },\n  {\n    \"id\": \"hdr\",\n    \"component\": \"Header\",\n    \"children\": [\n      \"title\"\n    ]\n  },\n  {\n    \"id\": \"title\",\n    \"component\": \"Text\",\n    \"slot\": \"heading\",\n    \"textContent\": \"Keyboard Shortcuts\"\n  },\n  {\n    \"id\": \"sec\",\n    \"component\": \"Section\",\n    \"children\": [\n      \"grid\"\n    ]\n  },\n  {\n    \"id\": \"grid\",\n    \"component\": \"Grid\",\n    \"columns\": 1,\n    \"gap\": \"2\",\n    \"children\": [\n      \"r1\",\n      \"r2\",\n      \"r3\",\n      \"r4\",\n      \"r5\",\n      \"r6\"\n    ]\n  },\n  {\n    \"id\": \"r1\",\n    \"component\": \"Row\",\n    \"children\": [\n      \"k1\",\n      \"d1\"\n    ]\n  },\n  {\n    \"id\": \"k1\",\n    \"component\": \"Kbd\",\n    \"text\": \"Ctrl+K\"\n  },\n  {\n    \"id\": \"d1\",\n    \"component\": \"Text\",\n    \"textContent\": \"Open command palette\"\n  },\n  {\n    \"id\": \"r2\",\n    \"component\": \"Row\",\n    \"children\": [\n      \"k2\",\n      \"d2\"\n    ]\n  },\n  {\n    \"id\": \"k2\",\n    \"component\": \"Kbd\",\n    \"text\": \"Ctrl+S\"\n  },\n  {\n    \"id\": \"d2\",\n    \"component\": \"Text\",\n    \"textContent\": \"Save current file\"\n  },\n  {\n    \"id\": \"r3\",\n    \"component\": \"Row\",\n    \"children\": [\n      \"k3\",\n      \"d3\"\n    ]\n  },\n  {\n    \"id\": \"k3\",\n    \"component\": \"Kbd\",\n    \"text\": \"Ctrl+Z\"\n  },\n  {\n    \"id\": \"d3\",\n    \"component\": \"Text\",\n    \"textContent\": \"Undo last action\"\n  },\n  {\n    \"id\": \"r4\",\n    \"component\": \"Row\",\n    \"children\": [\n      \"k4\",\n      \"d4\"\n    ]\n  },\n  {\n    \"id\": \"k4\",\n    \"component\": \"Kbd\",\n    \"text\": \"Ctrl+Shift+P\"\n  },\n  {\n    \"id\": \"d4\",\n    \"component\": \"Text\",\n    \"textContent\": \"Toggle preview\"\n  },\n  {\n    \"id\": \"r5\",\n    \"component\": \"Row\",\n    \"children\": [\n      \"k5\",\n      \"d5\"\n    ]\n  },\n  {\n    \"id\": \"k5\",\n    \"component\": \"Kbd\",\n    \"text\": \"Ctrl+N\"\n  },\n  {\n    \"id\": \"d5\",\n    \"component\": \"Text\",\n    \"textContent\": \"Create new document\"\n  },\n  {\n    \"id\": \"r6\",\n    \"component\": \"Row\",\n    \"children\": [\n      \"k6\",\n      \"d6\"\n    ]\n  },\n  {\n    \"id\": \"k6\",\n    \"component\": \"Kbd\",\n    \"text\": \"Esc\"\n  },\n  {\n    \"id\": \"d6\",\n    \"component\": \"Text\",\n    \"textContent\": \"Close dialog\"\n  }\n]",
            "name": "kbd-shortcuts"
          }
        ],
        "keywords": [
          "kbd",
          "command",
          "shortcut",
          "hotkey",
          "keyboard",
          "keybinding"
        ],
        "name": "UIKbd",
        "related": [
          "grid"
        ],
        "slots": {
          "default": {
            "description": "Key label text"
          }
        },
        "states": [
          {
            "description": "Default, ready for interaction.",
            "name": "idle"
          }
        ],
        "status": "stable",
        "synonyms": {
          "command": [
            "command",
            "palette",
            "kbd",
            "shortcut"
          ],
          "hotkey": [
            "kbd",
            "shortcut",
            "command"
          ],
          "keybinding": [
            "kbd",
            "shortcut",
            "command"
          ],
          "keyboard": [
            "kbd",
            "shortcut",
            "command"
          ],
          "shortcut": [
            "kbd",
            "shortcut",
            "command"
          ],
          "tags": [
            "Keyboard"
          ]
        },
        "tag": "kbd-ui",
        "tokens": {},
        "traits": [],
        "version": 1
      }
    },
    "Link": {
      "title": "Link",
      "description": "Inline navigation primitive — semantic `<a href>` wrapper. Use for\ncross-page navigation, footer / Terms-of-Service / Privacy-Policy\ninline references, \"Sign in\" / \"Sign up\" cross-page links, and any\naffordance whose purpose is to take the user somewhere (not to\nperform an action).\n\nSibling of `<button-ui>` — they have separate semantics and must\nnot be substituted for each other:\n\n| Affordance                | Use            |\n|---------------------------|----------------|\n| Submit form               | `<button-ui>`  |\n| Trigger action / modal    | `<button-ui>`  |\n| Copy to clipboard         | `<button-ui>`  |\n| Open modal / drawer       | `<button-ui>`  |\n| Navigate to another page  | `<link-ui>`    |\n| Open external URL         | `<link-ui>`    |\n| Anchor jump (#section)    | `<link-ui>`    |\n| Inline reference in prose | `<link-ui>`    |\n\nRenders `<a href=\"…\">` internally so middle-click open-in-new-tab,\nright-click context menu, hover URL preview, search-engine\ncrawlability, and bookmark-ability all work without any custom\nwiring. ARIA role is \"link\" (set automatically by `<a>` element).\n",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "block": {
          "description": "Stretches the link to fill its container; useful for standalone link rows.",
          "type": "boolean",
          "default": false
        },
        "component": {
          "const": "Link"
        },
        "disabled": {
          "description": "Suppresses navigation + applies muted styling. Sets aria-disabled.",
          "type": "boolean",
          "default": false
        },
        "href": {
          "description": "Destination URL or anchor. Required for SEO / middle-click / hover preview semantics. If omitted, the link still dispatches the `press` event (so it can be wired through the A2UI action handler system via `handler: \"navigate\"`), but loses native link behaviors.",
          "type": "string",
          "default": ""
        },
        "icon": {
          "description": "Optional leading icon (Phosphor name). Use sparingly — most inline links don't need an icon. For \"open in new tab\" affordance, the `target=\"_blank\"` attribute auto-renders a trailing arrow-up-right glyph; the `icon` prop is for leading semantic icons.",
          "type": "string",
          "default": ""
        },
        "rel": {
          "description": "Explicit `rel` attribute. Defaults to `noopener noreferrer` when `target=\"_blank\"` is set without an explicit rel.",
          "type": "string",
          "default": ""
        },
        "target": {
          "description": "Anchor target — same semantics as HTML `<a target>`. Use `_blank` to open in new tab; the implementation automatically adds `rel=\"noopener noreferrer\"` for `_blank` to prevent tab-napping / privacy leaks.",
          "type": "string",
          "enum": [
            "",
            "_self",
            "_blank",
            "_parent",
            "_top"
          ],
          "default": ""
        },
        "text": {
          "description": "Visible link text. Falls back to default-slot content if unset.",
          "type": "string",
          "default": ""
        },
        "variant": {
          "description": "Visual treatment. `default` underlines on rest + hover (standard link affordance). `subtle` underlines only on hover (for tighter designs where always-underlined would be noisy). `quiet` drops the link color and matches surrounding text color (used for footer-link rows where the link affordance is implied by context, not by color).",
          "type": "string",
          "enum": [
            "default",
            "subtle",
            "quiet"
          ],
          "default": "default"
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [
          "❌ `<button-ui variant=\"link\">` — was removed. Migrate to `<link-ui>` if the affordance is navigation, or to `<button-ui variant=\"ghost\">` if the affordance is an action that wants understated styling.",
          "❌ `<link-ui>` with no `href` AND no `press` handler — a link to nowhere is a bug. Either set `href` or wire a navigate action handler.",
          "❌ `<link-ui>` for form submission — submission is a button concern. Use `<button-ui type=\"submit\">`."
        ],
        "category": "content",
        "composes": [],
        "events": {
          "press": {
            "description": "Bubbles when the link is activated by click or Enter. Detail: `{ href, target }`. Fires BEFORE the browser's native navigation so handlers can `preventDefault()` and route through the A2UI action handler system. If no handler intercepts, native navigation proceeds.",
            "detail": {
              "href": {
                "description": "Link href attribute.",
                "type": "string"
              },
              "target": {
                "description": "Link target attribute (e.g. _blank).",
                "type": "string"
              }
            }
          }
        },
        "examples": [
          {
            "title": "Inline link in a sentence",
            "code": "<text-ui>\n  I agree to the\n  <link-ui text=\"Terms of Service\" href=\"/terms\"></link-ui>\n  and\n  <link-ui text=\"Privacy Policy\" href=\"/privacy\"></link-ui>.\n</text-ui>\n"
          },
          {
            "title": "External link with new-tab target",
            "code": "<link-ui text=\"Read the spec\" href=\"https://example.com/spec\" target=\"_blank\"></link-ui>\n"
          },
          {
            "title": "Footer link row",
            "code": "<row-ui justify=\"center\" gap=\"2\">\n  <link-ui text=\"Already have an account?\" variant=\"quiet\" href=\"/signin\"></link-ui>\n  <link-ui text=\"Sign in\" href=\"/signin\"></link-ui>\n</row-ui>\n"
          }
        ],
        "keywords": [
          "link",
          "anchor",
          "navigation",
          "hyperlink",
          "href",
          "navigate",
          "route",
          "url"
        ],
        "name": "UILink",
        "related": [
          "Button",
          "NavItem",
          "Breadcrumb"
        ],
        "slots": {
          "default": {
            "description": "Link text content when the `text` prop is unused."
          }
        },
        "states": [
          {
            "description": "Default rest state — underlined (or per variant).",
            "name": "idle"
          },
          {
            "description": "Color shifts to `--a-link-hover`.",
            "name": "hover"
          },
          {
            "description": "Auto-styled via `:visited` pseudo when navigating to a previously-visited URL.",
            "name": "visited"
          },
          {
            "description": "Suppressed activation; muted text color; aria-disabled.",
            "name": "disabled"
          }
        ],
        "status": "stable",
        "synonyms": {
          "Link": [
            "Anchor",
            "Hyperlink",
            "NavLink"
          ]
        },
        "tag": "link-ui",
        "tokens": {
          "--link-fg": {
            "description": "Resting link color. Default `var(--a-link)`."
          },
          "--link-fg-hover": {
            "description": "Hover-state color. Default `var(--a-link-hover)`."
          },
          "--link-fg-visited": {
            "description": "Visited-state color. Default `var(--a-link-visited)`."
          },
          "--link-underline-offset": {
            "description": "Distance between baseline and underline. Default `2px`."
          }
        },
        "traits": [],
        "version": 1
      }
    },
    "List": {
      "title": "List",
      "description": "Styled flat list with optional row dividers and icons — each row\nis a <list-item-ui> child. Selectable mode via [selectable] +\n[selectedKey] / `select` event. Composes <icon-ui> for row leading\nglyphs. Distinct from <nav-ui> (sidebar navigation, route-aware),\n<tree-ui> (hierarchical with arbitrary nesting), and <table-ui>\n(tabular data with columns). Use list-ui for non-navigable,\nnon-tabular vertical rows — comment lists, file lists, message\nstreams outside chat-shell.\n",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "component": {
          "const": "List"
        },
        "contained": {
          "description": "Add inline padding to list items so content aligns with surrounding\ncard/section insets. Pairs with [divider] — combining `[divider]\n[contained]` gives full-width borders between items but inset\ncontent. Without contained, [divider] items have `padding-inline: 0`\nso content sits at the list-ui edges (canonical edge-to-edge style).\n",
          "type": "boolean",
          "default": false
        },
        "divider": {
          "description": "Show dividers between items",
          "type": "boolean",
          "default": false
        },
        "selectable": {
          "description": "Enable selection on child listitems (roving tabindex + aria-selected).",
          "type": "boolean",
          "default": false
        },
        "selectedKey": {
          "description": "ID (or data-key) of the currently-selected child listitem.",
          "type": "string",
          "default": ""
        },
        "spacing": {
          "description": "Item spacing",
          "type": "string",
          "default": "md"
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [],
        "category": "layout",
        "composes": [
          "icon-ui"
        ],
        "events": {
          "selection-change": {
            "description": "Fired on selection-change.",
            "detail": {
              "key": {
                "description": "New selection key.",
                "type": "string"
              },
              "previousKey": {
                "description": "Previously selected key.",
                "type": "string"
              }
            }
          }
        },
        "examples": [
          {
            "description": "Basic List usage",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"Card\",\n    \"children\": [\n      \"sec\"\n    ]\n  },\n  {\n    \"id\": \"sec\",\n    \"component\": \"Section\",\n    \"children\": [\n      \"comp\"\n    ]\n  },\n  {\n    \"id\": \"comp\",\n    \"component\": \"List\"\n  }\n]",
            "name": "basic-list"
          }
        ],
        "keywords": [
          "list",
          "listing",
          "bookmark",
          "favorite",
          "save",
          "pin",
          "star"
        ],
        "name": "UIList",
        "related": [
          "ListItem",
          "Tree",
          "Nav",
          "Table"
        ],
        "slots": {},
        "states": [
          {
            "description": "Default, ready for interaction.",
            "name": "idle"
          }
        ],
        "status": "stable",
        "synonyms": {
          "bookmark": [
            "bookmark",
            "list",
            "favorite"
          ],
          "favorite": [
            "bookmark",
            "list"
          ],
          "listing": [
            "table",
            "data",
            "list"
          ],
          "pin": [
            "bookmark",
            "list"
          ],
          "save": [
            "bookmark",
            "list",
            "favorite"
          ],
          "star": [
            "bookmark",
            "list",
            "leaderboard"
          ]
        },
        "tag": "list-ui",
        "tokens": {},
        "traits": [],
        "version": 1
      }
    },
    "ListItem": {
      "title": "ListItem",
      "description": "Child of <list-ui>. One list item with optional icon + text + description, plus arbitrary slotted content (cards, rows). Use inside <list-ui> only.",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "description": {
          "description": "Secondary line below the primary text. Subtle color.",
          "type": "string"
        },
        "component": {
          "const": "ListItem"
        },
        "icon": {
          "description": "Optional leading icon name (Phosphor).",
          "type": "string"
        },
        "text": {
          "description": "Primary text. Renders as semibold inline body.",
          "type": "string"
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [],
        "category": "layout",
        "composes": [],
        "events": {},
        "examples": [],
        "keywords": [
          "list-item",
          "list-row",
          "list-entry",
          "item-row",
          "row"
        ],
        "name": "UIListItem",
        "related": [
          "List",
          "NavItem",
          "MenuItem",
          "TreeItem"
        ],
        "slots": {
          "description": {
            "description": "Override slot for richer description markup than the plain [description] attribute string (inline links, code spans, multiple lines). Renders beneath the primary text at body-subtle typography."
          },
          "action": {
            "description": "Trailing action affordance on the row (typically a `<button-ui>`). Promotes the row's grid from 2-column (icon | content) to 3-column (icon | content | action), right-aligned + vertically centered across both content rows. Used by `<onboarding-checklist-ui>` item rows and any consumer that needs an end-aligned action button on a list-item."
          },
          "icon": {
            "description": "Override the [icon] glyph with a custom slotted element (e.g. a colored <icon-ui>, an image, or an avatar-ui). Mutually exclusive with the [icon] attribute — slot child wins if both are present."
          }
        },
        "states": [],
        "status": "stable",
        "synonyms": {
          "list-item": [
            "row",
            "entry",
            "list-row",
            "item"
          ]
        },
        "tag": "list-item-ui",
        "tokens": {},
        "traits": [],
        "version": 1
      }
    },
    "ListWindow": {
      "title": "ListWindow",
      "description": "Virtualized / windowed list primitive. Renders only the visible slice of a large items[] array (chat threads, feeds, log streams, nav lists, search-result panes) — typically ≤50 DOM rows regardless of the underlying collection size. Composes a `render`-function prop OR a slotted <template> for row materialization; ships a fixed-size fast-path (constant-time index→offset math) and a variable-size measurement fallback. Distinct from <list-ui> (renders every child, preferred for short lists < 50 items) and <table-ui> (tabular data with columns). Use list-window-ui when items.length is large enough that rendering every row would block the main thread or stutter scroll.",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "items": {
          "description": "The items to virtualize. Required for prop-driven authoring; ignored when data-stream-src is set.",
          "type": "array",
          "default": []
        },
        "component": {
          "const": "ListWindow"
        },
        "direction": {
          "description": "Scroll axis — vertical (default) or horizontal carousel.",
          "type": "string",
          "enum": [
            "vertical",
            "horizontal"
          ],
          "default": "vertical"
        },
        "estimatedSize": {
          "description": "Initial guess for variable-height rows. Used until the first measurement pass refines the offset cache.",
          "type": "number",
          "default": 48
        },
        "itemSize": {
          "description": "Fixed item height in pixels. When > 0, uses the constant-time fast path (avoids per-row measurement).",
          "type": "number",
          "default": 0
        },
        "itemSizeRem": {
          "description": "Fixed item height in rem. Useful for typographic-scale rows that should track the body type.",
          "type": "number",
          "default": 0
        },
        "loading": {
          "description": "Render skeleton rows in the visible window. Sets aria-busy=\"true\" on the host.",
          "type": "boolean",
          "default": false
        },
        "overscan": {
          "description": "Rows to render above + below the visible window. 0–20 is reasonable; > 50 negates the windowing benefit.",
          "type": "number",
          "default": 3
        },
        "pinBottom": {
          "description": "When appending items, keep scroll pinned to the bottom (chat-thread / log-tail pattern).",
          "type": "boolean",
          "default": false
        },
        "startIndex": {
          "description": "Index to scroll to on mount. Useful for restoring scroll position on remount.",
          "type": "number",
          "default": 0
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [
          {
            "fix": "{ \"component\": \"ListWindow\", \"items\": [/* 10000 items */], \"item-size\": 48 }\n",
            "why": "Rendering 10k items into <list-ui> blows up the DOM and main thread. Scroll\njank, mount lag, and memory pressure all degrade.\n",
            "wrong": "{ \"component\": \"List\", \"items\": [/* 10000 items */] }\n"
          },
          {
            "fix": "Wrap in a container with a height, or set style=\"height:480px\" on the\nListWindow itself.\n",
            "why": "Without a height bound, the scroll container has no viewport, so the windowing\nmath reports \"all items visible\" and the whole list mounts.\n",
            "wrong": "{ \"component\": \"ListWindow\", \"items\": [/* … */] }\n(with no parent height + no item-size + no estimated-size)\n"
          },
          {
            "fix": "{ \"component\": \"ListWindow\", \"overscan\": 5, \"items\": [/* … */] }\n",
            "why": "Overscan=200 materializes 200 rows above + below the viewport. That defeats\nthe entire point of windowing.\n",
            "wrong": "{ \"component\": \"ListWindow\", \"overscan\": 200, \"items\": [/* … */] }\n"
          }
        ],
        "category": "display",
        "composes": [
          "skeleton-ui"
        ],
        "events": {
          "item-click": {
            "description": "Fired when a rendered row is clicked.",
            "detail": {
              "index": {
                "description": "Item index in the full items[] array.",
                "type": "number"
              },
              "item": {
                "description": "The clicked item (full item-shape from items[])."
              }
            }
          },
          "measure": {
            "description": "Fired when a variable-height row is measured. Useful for instrumenting the offset cache.",
            "detail": {
              "height": {
                "description": "Measured row height in pixels.",
                "type": "number"
              },
              "index": {
                "description": "Index of the row that was measured.",
                "type": "number"
              }
            }
          },
          "range-change": {
            "description": "Fired when the visible row range (start/end indices) changes due to scroll.",
            "detail": {
              "items": {
                "description": "The items currently materialized in the window.",
                "type": "array"
              },
              "endIndex": {
                "description": "Last rendered row index (exclusive).",
                "type": "number"
              },
              "startIndex": {
                "description": "First rendered row index.",
                "type": "number"
              }
            }
          },
          "scroll-end": {
            "description": "Fired when the user scrolls to the bottom (within 1 viewport). Use for infinite-load patterns.",
            "detail": {
              "index": {
                "description": "Last visible row index.",
                "type": "number"
              }
            }
          },
          "scroll-start": {
            "description": "Fired when the user scrolls to the top (within 1 viewport). Use for \"load older\" patterns.",
            "detail": {
              "index": {
                "description": "First visible row index.",
                "type": "number"
              }
            }
          }
        },
        "examples": [
          {
            "description": "Virtualized chat-thread message list with declarative <template> rows.",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"Card\",\n    \"children\": [\"thread\"]\n  },\n  {\n    \"id\": \"thread\",\n    \"component\": \"ListWindow\",\n    \"item-size\": 56,\n    \"overscan\": 5,\n    \"pin-bottom\": true\n  }\n]",
            "name": "chat-thread-list"
          },
          {
            "description": "SSE-streamed JSONL log tail with sticky-bottom pin.",
            "a2ui": "[\n  {\n    \"id\": \"logs\",\n    \"component\": \"ListWindow\",\n    \"item-size\": 24,\n    \"pin-bottom\": true\n  }\n]",
            "name": "log-tail-stream"
          }
        ],
        "keywords": [
          "list-window",
          "virtualized",
          "windowed",
          "virtual-scroll",
          "infinite-scroll",
          "large-list",
          "feed",
          "chat-thread",
          "log-stream",
          "10k-rows"
        ],
        "name": "UIListWindow",
        "related": [
          "List",
          "ListItem",
          "Feed",
          "ChatThread",
          "Table"
        ],
        "slots": {
          "default": {
            "description": "A single <template> element used to clone rows (declarative-template authoring). Mutually exclusive with the render prop."
          },
          "after": {
            "description": "Sticky-bottom content (composer, \"load older\" button)."
          },
          "before": {
            "description": "Sticky-top content (filter chips, summary stat)."
          },
          "empty": {
            "description": "Custom empty-state content when items.length === 0."
          },
          "loading": {
            "description": "Custom skeleton row template; falls back to <skeleton-ui> when omitted."
          }
        },
        "states": [
          {
            "description": "Default — rendering and reconciling normally.",
            "name": "idle"
          },
          {
            "description": "Skeleton rows; data fetch in flight.",
            "attribute": "loading",
            "name": "loading"
          },
          {
            "description": "items.length === 0.",
            "attribute": "empty",
            "name": "empty"
          },
          {
            "description": "First-mount measurement pass on variable-height rows; suppresses scroll-end events.",
            "attribute": "measuring",
            "name": "measuring"
          },
          {
            "description": "Pointer events blocked.",
            "attribute": "disabled",
            "name": "disabled"
          }
        ],
        "status": "stable",
        "synonyms": {
          "infinite-scroll": [
            "virtualized",
            "virtual-scroll",
            "list-window"
          ],
          "large-list": [
            "virtualized",
            "list-window"
          ],
          "virtual-scroll": [
            "virtualized",
            "windowed",
            "list-window"
          ],
          "virtualized": [
            "virtual-scroll",
            "windowed",
            "list-window"
          ],
          "windowed": [
            "virtualized",
            "virtual-scroll",
            "list-window"
          ]
        },
        "tag": "list-window-ui",
        "tokens": {
          "--list-window-bg": {
            "description": "Host background (defaults to --a-bg)."
          },
          "--list-window-overscan-bg": {
            "description": "Visible buffer rows background — transparent by default."
          },
          "--list-window-row-gap": {
            "description": "Row spacing in the visible window (defaults to --a-space-1)."
          },
          "--list-window-sentinel-size": {
            "description": "Top + bottom IntersectionObserver-target sentinel size (defaults to --a-space-2)."
          }
        },
        "traits": [],
        "version": 1
      }
    },
    "LoadingOverlay": {
      "title": "LoadingOverlay",
      "description": "Container-scoped busy overlay. Covers a positioned parent region with a centered spinner (auto-stamped) or slotted indicator (skeleton-ui, progress-ui, custom) while async work is in flight. Wires aria-busy onto the parent on connect; applies a [delay] grace window to avoid flash on fast loads. For viewport-scoped / route loaders use a dedicated route-loader pattern; for submit-button busy use <button-ui loading>.",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "active": {
          "description": "When set, overlay is visible and the parent container is marked aria-busy. Toggle from consumer code; default hidden.",
          "$ref": "#/$defs/DynamicBoolean"
        },
        "component": {
          "const": "LoadingOverlay"
        },
        "delay": {
          "description": "Suppress the overlay until this many ms elapse. Prevents flash on fast loads. Default 200ms.",
          "$ref": "#/$defs/DynamicNumber"
        },
        "label": {
          "description": "Accessible operation name used by the host aria-label and forwarded to the auto-stamped spinner.",
          "$ref": "#/$defs/DynamicString"
        },
        "variant": {
          "description": "Backdrop treatment — default (muted scrim), transparent (no backdrop fill — useful with full-area skeleton indicators), blur (light scrim with backdrop-filter blur).",
          "$ref": "#/$defs/DynamicString"
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [
          {
            "fix": "{\"component\": \"Card\", \"children\": [\n  {\"component\": \"LoadingOverlay\", \"active\": true},\n  {\"component\": \"Table\", \"data-stream-src\": \"...\"}\n]}\n",
            "why": "LoadingOverlay is container-scoped. Attaching it directly to Page\ncovers the entire viewport but lacks the route-loader's wiring\n(skeleton routing, route-level animation). Use the route loader.\n",
            "wrong": "{\"component\": \"Page\", \"children\": [\n  {\"component\": \"LoadingOverlay\", \"active\": true}\n]}\n"
          },
          {
            "fix": "{\"component\": \"Modal\", \"open\": true, \"loading\": true}\n",
            "why": "Modal owns its own busy state and focus trap; nesting a\nLoadingOverlay introduces two competing inert toggles.\n",
            "wrong": "{\"component\": \"Modal\", \"open\": true, \"children\": [\n  {\"component\": \"LoadingOverlay\", \"active\": true}\n]}\n"
          },
          {
            "fix": "{\"component\": \"Form\", \"children\": [\n  {\"component\": \"Button\", \"text\": \"Submitting\", \"type\": \"submit\", \"loading\": true, \"disabled\": true}\n]}\n",
            "why": "A form-submit affordance belongs on the button itself, not as an\noverlay over the entire form region. Use Button[loading].\n",
            "wrong": "{\"component\": \"Form\", \"children\": [\n  {\"component\": \"Button\", \"text\": \"Submit\", \"type\": \"submit\"},\n  {\"component\": \"LoadingOverlay\", \"active\": true}\n]}\n"
          }
        ],
        "category": "feedback",
        "composes": [],
        "events": {},
        "examples": [
          {
            "description": "Card containing a table that loads on mount; the overlay covers the card's body while data streams.",
            "a2ui": "[\n  {\n    \"id\": \"card\",\n    \"component\": \"Card\",\n    \"children\": [\"sec\"]\n  },\n  {\n    \"id\": \"sec\",\n    \"component\": \"Section\",\n    \"children\": [\"overlay\", \"table\"]\n  },\n  {\n    \"id\": \"overlay\",\n    \"component\": \"LoadingOverlay\",\n    \"active\": true,\n    \"label\": \"Loading orders…\"\n  },\n  {\n    \"id\": \"table\",\n    \"component\": \"Table\",\n    \"data-stream-src\": \"/api/orders\"\n  }\n]",
            "name": "card-with-loading-table"
          },
          {
            "description": "Skeleton-shaped placeholder overlay using the transparent variant — slot a stack of <Skeleton> rows.",
            "a2ui": "[\n  {\n    \"id\": \"ov\",\n    \"component\": \"LoadingOverlay\",\n    \"active\": true,\n    \"variant\": \"transparent\",\n    \"label\": \"Loading content…\",\n    \"children\": [\"sk-stack\"]\n  },\n  {\n    \"id\": \"sk-stack\",\n    \"component\": \"Column\",\n    \"gap\": \"2\",\n    \"children\": [\"sk1\", \"sk2\", \"sk3\"]\n  },\n  {\n    \"id\": \"sk1\",\n    \"component\": \"Skeleton\",\n    \"width\": \"100%\",\n    \"height\": \"1rem\"\n  },\n  {\n    \"id\": \"sk2\",\n    \"component\": \"Skeleton\",\n    \"width\": \"80%\",\n    \"height\": \"1rem\"\n  },\n  {\n    \"id\": \"sk3\",\n    \"component\": \"Skeleton\",\n    \"width\": \"60%\",\n    \"height\": \"1rem\"\n  }\n]",
            "name": "skeleton-overlay"
          },
          {
            "description": "Overlay with the default 200ms grace window. If the underlying load resolves in less than 200ms, the overlay never paints.",
            "a2ui": "[\n  {\n    \"id\": \"ov\",\n    \"component\": \"LoadingOverlay\",\n    \"active\": true,\n    \"delay\": 200,\n    \"label\": \"Loading\"\n  }\n]",
            "name": "fast-load-no-flash"
          }
        ],
        "keywords": [
          "loading",
          "overlay",
          "busy",
          "spinner",
          "skeleton",
          "placeholder",
          "feedback",
          "progress",
          "indicator",
          "wait"
        ],
        "name": "UILoadingOverlay",
        "related": [
          "Spinner",
          "Skeleton",
          "Progress",
          "Card",
          "Table",
          "Modal"
        ],
        "slots": {
          "default": {
            "description": "Busy indicator content — <spinner-ui>, <skeleton-ui>, <progress-ui>, or custom. If empty, a centered <spinner-ui size=\"lg\"> is auto-stamped."
          }
        },
        "states": [
          {
            "description": "Default, hidden. Parent interactive.",
            "name": "idle"
          },
          {
            "description": "Overlay visible; parent has aria-busy=\"true\".",
            "attribute": "active",
            "name": "active"
          }
        ],
        "status": "stable",
        "synonyms": {
          "busy": [
            "loading",
            "overlay",
            "busy",
            "spinner"
          ],
          "loader": [
            "loading",
            "overlay",
            "spinner"
          ],
          "loading": [
            "loading",
            "overlay",
            "busy",
            "spinner",
            "skeleton"
          ],
          "overlay": [
            "loading",
            "overlay",
            "busy"
          ],
          "spinner": [
            "loading",
            "overlay",
            "spinner"
          ]
        },
        "tag": "loading-overlay-ui",
        "tokens": {
          "--loading-overlay-bg": {
            "description": "Backdrop fill color. Default uses the generic neutral scrim token.",
            "default": "var(--a-scrim-default)"
          },
          "--loading-overlay-duration": {
            "description": "Fade in / fade out duration.",
            "default": "var(--a-duration)"
          },
          "--loading-overlay-easing": {
            "description": "Fade easing curve.",
            "default": "var(--a-easing-out)"
          },
          "--loading-overlay-gap": {
            "description": "Vertical gap between the indicator and any sibling content (e.g. label, skeleton stack).",
            "default": "var(--a-space-3)"
          },
          "--loading-overlay-radius": {
            "description": "Backdrop corner radius. Matches the parent surface by default.",
            "default": "var(--a-radius-md)"
          },
          "--loading-overlay-z": {
            "description": "Stacking order. Sits above sibling content, below modal-ui (which uses ::backdrop on top-layer dialog).",
            "default": "50"
          }
        },
        "traits": [],
        "version": 1
      }
    },
    "Mark": {
      "title": "Mark",
      "description": "Highlighted inline text — token-driven theme-aware wrapper around the\nnative `<mark>` semantic. Use for search-result match highlighting,\ndiff additions in prose, \"new since last visit\" emphasis, and any\ninline text that needs a visual rail without changing its weight.\n\nDistinct from `<text-ui strong>` (semantic emphasis via weight) and\nfrom `<tag-ui>` (block-shaped pill chrome). mark-ui keeps the inline\ntext flow intact — same line-height, same baseline — just paints a\nbackground highlight behind the matched span.\n",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "component": {
          "const": "Mark"
        },
        "variant": {
          "description": "Highlight color variant. Default `warning` is the conventional yellow-marker tone.",
          "type": "string",
          "enum": [
            "warning",
            "info",
            "success",
            "danger",
            "muted"
          ],
          "default": "warning"
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [
          {
            "fix": "<mark-ui>matched</mark-ui> — same semantic role but theme-aware.",
            "why": "Native <mark> uses UA default (yellow-on-white) that doesn't adapt to theme — invisible in dark mode + jarring in light mode.",
            "wrong": "<mark>matched</mark>"
          }
        ],
        "category": "typography",
        "composes": [],
        "events": {},
        "examples": [
          {
            "description": "Highlight the search query within a result title.",
            "a2ui": "[\n  { \"id\": \"row\", \"component\": \"Row\", \"children\": [\"pre\", \"mk\", \"post\"] },\n  { \"id\": \"pre\", \"component\": \"Text\", \"textContent\": \"Quarterly \" },\n  { \"id\": \"mk\",  \"component\": \"Mark\", \"textContent\": \"revenue\" },\n  { \"id\": \"post\", \"component\": \"Text\", \"textContent\": \" report — Q4 2025\" }\n]\n",
            "name": "search-match"
          }
        ],
        "keywords": [
          "mark",
          "highlight",
          "search-match",
          "emphasis"
        ],
        "name": "UIMark",
        "related": [
          "text",
          "tag"
        ],
        "slots": {
          "default": {
            "description": "The text content to highlight (plain text or inline elements)."
          }
        },
        "states": [
          {
            "description": "Default — highlighted background painted behind the slotted text.",
            "name": "idle"
          }
        ],
        "status": "stable",
        "synonyms": {
          "highlight": [
            "mark",
            "emphasis"
          ],
          "search-match": [
            "mark",
            "highlight"
          ]
        },
        "tag": "mark-ui",
        "tokens": {
          "--mark-bg": {
            "description": "Background color of the highlight.",
            "default": "var(--a-warning-muted)"
          },
          "--mark-fg": {
            "description": "Foreground (text) color inside the highlight.",
            "default": "var(--a-warning-text)"
          },
          "--mark-px": {
            "description": "Horizontal padding around the highlighted text.",
            "default": "var(--a-space-0-5)"
          },
          "--mark-radius": {
            "description": "Border radius of the highlight box.",
            "default": "var(--a-radius-xs)"
          }
        },
        "traits": [],
        "version": 1
      }
    },
    "Menu": {
      "title": "Menu",
      "description": "Dropdown action menu with roving focus and keyboard navigation. Uses Popover API.",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "component": {
          "const": "Menu"
        },
        "gap": {
          "description": "Gap in px",
          "type": "number",
          "default": 4
        },
        "open": {
          "description": "Controls visibility via popover API",
          "type": "boolean",
          "default": false
        },
        "placement": {
          "description": "Preferred position relative to the anchor element",
          "type": "string",
          "enum": [
            "bottom-start",
            "bottom-end",
            "top-start",
            "top-end"
          ],
          "default": "bottom-start"
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [],
        "category": "container",
        "composes": [
          "icon-ui"
        ],
        "events": {
          "action": {
            "description": "Fired when a menu item is activated. Detail contains the triggering element.",
            "detail": {
              "text": {
                "description": "Menu item text.",
                "type": "string"
              },
              "value": {
                "description": "Menu item value.",
                "type": "string"
              }
            }
          }
        },
        "examples": [
          {
            "description": "Basic Menu usage",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"Card\",\n    \"children\": [\n      \"sec\"\n    ]\n  },\n  {\n    \"id\": \"sec\",\n    \"component\": \"Section\",\n    \"children\": [\n      \"comp\"\n    ]\n  },\n  {\n    \"id\": \"comp\",\n    \"component\": \"Menu\"\n  }\n]",
            "name": "basic-menu"
          }
        ],
        "keywords": [
          "menu",
          "navigation",
          "navbar",
          "hamburger",
          "dropdown",
          "popover",
          "context-menu",
          "right-click"
        ],
        "name": "UIMenu",
        "related": [
          "MenuItem",
          "MenuDivider",
          "Popover",
          "Command",
          "Button"
        ],
        "slots": {
          "default": {
            "description": "Menu items with role=\"menuitem\" and optional <hr> dividers"
          },
          "trigger": {
            "description": "Required. Focusable element that opens the menu when activated. Exactly one child must have slot=\"trigger\" — typically <button-ui>, but any focusable element works. Without it the menu cannot open via keyboard or pointer. Lives in light DOM; the items are hoisted to a top-layer popover on open."
          }
        },
        "states": [
          {
            "description": "Default, ready for interaction.",
            "name": "idle"
          }
        ],
        "status": "stable",
        "synonyms": {
          "context-menu": [
            "popover",
            "menu"
          ],
          "dropdown": [
            "popover",
            "menu",
            "select",
            "form"
          ],
          "hamburger": [
            "nav",
            "menu",
            "sidebar",
            "drawer"
          ],
          "menu": [
            "nav",
            "sidebar",
            "popover",
            "menu",
            "command"
          ],
          "navbar": [
            "nav",
            "menu",
            "sidebar",
            "breadcrumb"
          ],
          "navigation": [
            "nav",
            "sidebar",
            "breadcrumb",
            "tabs",
            "menu",
            "pagination"
          ],
          "popover": [
            "popover",
            "menu",
            "tooltip"
          ],
          "right-click": [
            "popover",
            "menu"
          ]
        },
        "tag": "menu-ui",
        "tokens": {},
        "traits": [],
        "version": 1
      }
    },
    "MenuDivider": {
      "title": "MenuDivider",
      "description": "Visual separator between groups of `<menu-item-ui>` rows. Renders as a horizontal rule with role=\"separator\".",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "component": {
          "const": "MenuDivider"
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [],
        "category": "navigation",
        "composes": [],
        "events": {},
        "examples": [],
        "keywords": [
          "menu-divider",
          "separator",
          "menu-rule"
        ],
        "name": "UIMenuDivider",
        "related": [
          "Menu",
          "MenuItem",
          "Divider"
        ],
        "slots": {},
        "states": [],
        "status": "stable",
        "synonyms": {
          "menu-divider": [
            "menu-separator",
            "menu-rule",
            "popover-divider"
          ]
        },
        "tag": "menu-divider-ui",
        "tokens": {},
        "traits": [],
        "version": 1
      }
    },
    "MenuItem": {
      "title": "MenuItem",
      "description": "Child of `<menu-ui>`. One actionable row inside a menu, with optional leading icon + label + value.",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "component": {
          "const": "MenuItem"
        },
        "disabled": {
          "description": "Disabled state — blocks pointer + keyboard activation.",
          "type": "boolean",
          "default": false
        },
        "icon": {
          "description": "Optional leading Phosphor icon name.",
          "type": "string",
          "default": ""
        },
        "text": {
          "description": "Item label text.",
          "type": "string",
          "default": ""
        },
        "value": {
          "description": "Stable identifier emitted via the parent menu's `select` event.",
          "type": "string",
          "default": ""
        },
        "variant": {
          "description": "Semantic variant.",
          "type": "string",
          "enum": [
            "default",
            "danger"
          ],
          "default": "default"
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [],
        "category": "navigation",
        "composes": [],
        "events": {},
        "examples": [],
        "keywords": [
          "menu-item",
          "menu-row",
          "popover-action",
          "dropdown-item"
        ],
        "name": "UIMenuItem",
        "related": [
          "Menu",
          "MenuDivider",
          "Button",
          "NavItem"
        ],
        "slots": {
          "icon": {
            "description": "Custom leading element override; falls through to `[icon]` prop if not slotted."
          },
          "text": {
            "description": "Custom label content; falls through to `[text]` prop if not slotted."
          }
        },
        "states": [],
        "status": "stable",
        "synonyms": {
          "menu-item": [
            "dropdown-item",
            "menu-row",
            "popover-action"
          ]
        },
        "tag": "menu-item-ui",
        "tokens": {},
        "traits": [],
        "version": 1
      }
    },
    "MenuLabel": {
      "title": "MenuLabel",
      "description": "Non-interactive group heading inside a `<menu-ui>` — a small uppercase kicker that names the group of `<menu-item-ui>` rows beneath it. Renders with role=\"presentation\" so the menu's roving focus skips it.",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "component": {
          "const": "MenuLabel"
        },
        "text": {
          "description": "The group label. Stamped into a `<span slot=\"text\">`; consumer-provided slot content wins.",
          "type": "string",
          "default": ""
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [],
        "category": "navigation",
        "composes": [],
        "events": {},
        "examples": [],
        "keywords": [
          "menu-label",
          "menu-group",
          "section-header",
          "menu-heading"
        ],
        "name": "UIMenuLabel",
        "related": [
          "Menu",
          "MenuItem",
          "MenuDivider"
        ],
        "slots": {
          "text": {
            "description": "Custom label content; falls through to the `[text]` prop if not slotted."
          }
        },
        "states": [],
        "status": "stable",
        "synonyms": {
          "menu-label": [
            "menu-group-label",
            "menu-section-header",
            "menu-heading"
          ]
        },
        "tag": "menu-label-ui",
        "tokens": {},
        "traits": [],
        "version": 1
      }
    },
    "Modal": {
      "title": "Modal",
      "description": "Centered dialog overlay using native <dialog> — same portal /\nbackdrop / focus-trap / Escape-dismiss primitives as <drawer-ui>,\nbut anchored to the viewport center with size presets. Canonical\ninner shape mirrors drawer / card: <header> + one or more <section>\n+ optional <footer>. The header stamps a built-in title bar from\n[text] plus an auto-close button (unless [permanent]). Use modal-ui\nfor centered confirmations, destructive prompts, transient previews,\nand short focused interactions; use <drawer-ui> instead for\nedge-anchored multi-field editors and mobile sheet patterns.\n",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "component": {
          "const": "Modal"
        },
        "open": {
          "description": "Controls overlay visibility. Setting to true opens the surface with entry animation.",
          "type": "boolean",
          "default": false
        },
        "permanent": {
          "description": "When true, suppress backdrop click and Escape key dismissal of the overlay",
          "type": "boolean",
          "default": false
        },
        "size": {
          "description": "Width preset. sm=24rem, md=32rem, lg=48rem, full=95vw.",
          "type": "string",
          "enum": [
            "sm",
            "md",
            "lg",
            "xl"
          ],
          "default": "md"
        },
        "text": {
          "description": "Aria label applied to the surface element for accessibility",
          "type": "string",
          "default": ""
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [],
        "category": "container",
        "composes": [],
        "events": {
          "close": {
            "description": "Fired when the overlay is dismissed via backdrop click, Escape key, popover toggle, or programmatic hide(). Bubbles."
          }
        },
        "examples": [
          {
            "description": "Basic Modal usage",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"Card\",\n    \"children\": [\n      \"sec\"\n    ]\n  },\n  {\n    \"id\": \"sec\",\n    \"component\": \"Section\",\n    \"children\": [\n      \"comp\"\n    ]\n  },\n  {\n    \"id\": \"comp\",\n    \"component\": \"Modal\",\n    \"text\": \"Example Modal\"\n  }\n]",
            "name": "basic-modal"
          }
        ],
        "keywords": [
          "modal"
        ],
        "name": "UIModal",
        "related": [
          "Drawer",
          "Card",
          "Popover",
          "AdminCommand"
        ],
        "slots": {
          "default": {
            "description": "Content placed inside the modal surface. Accepts any elements (card-ui, command-ui, custom markup)."
          },
          "body": {
            "description": "Main body region for prose, forms, or arbitrary content. Sits between header and footer; scrolls when content overflows."
          },
          "footer": {
            "description": "Optional footer region rendered below the body, typically for action buttons. Author-fills with Confirm / Cancel buttons or similar trailing affordances."
          },
          "header": {
            "description": "Optional header region rendered above the body. Author-fillable with title + supporting markup. CSS positions it at the top of the modal surface with consistent padding + the dismiss-close affordance."
          }
        },
        "states": [
          {
            "description": "Default, ready for interaction.",
            "name": "idle"
          }
        ],
        "status": "stable",
        "synonyms": {
          "tags": [
            "Dialog"
          ]
        },
        "tag": "modal-ui",
        "tokens": {
          "--modal-backdrop": {
            "description": "Override backdrop color (dialog mode)"
          },
          "--modal-background": {
            "description": "Override surface background color"
          },
          "--modal-border-color": {
            "description": "Override surface border color"
          },
          "--modal-duration": {
            "description": "Override open/close animation duration"
          },
          "--modal-easing-in": {
            "description": "Override entry animation easing curve"
          },
          "--modal-easing-out": {
            "description": "Override exit animation easing curve"
          },
          "--modal-radius": {
            "description": "Override surface border radius"
          },
          "--modal-shadow": {
            "description": "Override surface box shadow"
          }
        },
        "traits": [],
        "version": 1
      }
    },
    "Nav": {
      "title": "Nav",
      "description": "Navigation rail. Consolidates the prior `app-nav-ui` + `section-nav-ui`\npair per ADR-0015 § Nav consolidation. [variant] drives visual\ntreatment; behavior is unified.\n\nDefault variant (\"primary\") is the app-sidebar nav: ResizeObserver\ncollapses to icon-only below 96px, groups open a popover when\ncollapsed. [variant=\"section\"] is a subnav rail with quieter chrome\nand a [heading] kicker rendered via CSS.\n",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "collapsed": {
          "description": "Primary-variant only. Force icon-only collapse regardless of viewport width.",
          "type": "boolean",
          "default": false
        },
        "component": {
          "const": "Nav"
        },
        "divider": {
          "description": "Auto-place dividers between adjacent groups + items.",
          "type": "boolean",
          "default": false
        },
        "heading": {
          "description": "Optional kicker label. Section variant renders it via ::before; primary uses it as aria-label only.",
          "type": "string",
          "default": ""
        },
        "variant": {
          "description": "Visual treatment. primary = app sidebar; section = subnav rail.",
          "type": "string",
          "enum": [
            "primary",
            "section"
          ],
          "default": "primary"
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [],
        "category": "layout",
        "composes": [
          "nav-group-ui",
          "nav-item-ui",
          "icon-ui",
          "popover-ui"
        ],
        "events": {
          "nav-select": {
            "description": "Bubbles from <nav-item-ui> children when one is selected. Detail: { item, text, value }.",
            "detail": {
              "item": {
                "description": "Selected nav-item element.",
                "type": "object"
              },
              "text": {
                "description": "Item text content.",
                "type": "string"
              },
              "value": {
                "description": "Item value attribute.",
                "type": "string"
              }
            }
          }
        },
        "examples": [
          {
            "description": "App sidebar nav with groups + items.",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"Nav\",\n    \"children\": [\"g1\", \"i1\"]\n  },\n  {\n    \"id\": \"g1\",\n    \"component\": \"NavGroup\",\n    \"text\": \"Settings\",\n    \"icon\": \"gear\",\n    \"children\": [\"g1i1\"]\n  },\n  {\n    \"id\": \"g1i1\",\n    \"component\": \"NavItem\",\n    \"text\": \"General\",\n    \"value\": \"/settings/general\"\n  },\n  {\n    \"id\": \"i1\",\n    \"component\": \"NavItem\",\n    \"text\": \"Profile\",\n    \"icon\": \"user\",\n    \"value\": \"/profile\"\n  }\n]",
            "name": "primary"
          },
          {
            "description": "Subnav rail with heading.",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"Nav\",\n    \"variant\": \"section\",\n    \"heading\": \"On this page\",\n    \"children\": [\"i1\", \"i2\"]\n  },\n  {\n    \"id\": \"i1\",\n    \"component\": \"NavItem\",\n    \"text\": \"Overview\",\n    \"value\": \"#overview\"\n  },\n  {\n    \"id\": \"i2\",\n    \"component\": \"NavItem\",\n    \"text\": \"API\",\n    \"value\": \"#api\"\n  }\n]",
            "name": "section"
          }
        ],
        "keywords": [
          "nav",
          "navigation",
          "sidebar",
          "menu",
          "links"
        ],
        "name": "UINav",
        "related": [
          "NavGroup",
          "NavItem",
          "Tabs",
          "Breadcrumb",
          "AdminSidebar"
        ],
        "slots": {
          "default": {
            "description": "Primary slot — accepts <nav-group-ui> + <nav-item-ui> children, plus <hr data-nav-divider> for hand-placed dividers."
          }
        },
        "states": [
          {
            "description": "Default, not collapsed.",
            "name": "idle"
          },
          {
            "description": "Primary variant when [collapsed] or container width <= 96px.",
            "name": "collapsed"
          }
        ],
        "status": "stable",
        "synonyms": {
          "nav": [
            "sidebar",
            "side-nav",
            "navigation-rail",
            "primary-nav",
            "section-nav"
          ]
        },
        "tag": "nav-ui",
        "tokens": {},
        "traits": [],
        "version": 1
      }
    },
    "NavGroup": {
      "title": "NavGroup",
      "description": "Collapsible labeled group of <nav-item-ui> children inside <nav-ui>.\nConsolidates the prior `app-nav-group-ui` + `section-nav-group-ui`\nper ADR-0015 § Nav consolidation.\n\nWhen the parent <nav-ui> is collapsed (primary variant), clicking the\ngroup opens a popover with its children instead of toggling inline\nexpansion. Inline click + keyboard (Enter/Space) toggle is supported\nwhen [collapsible] (default true).\n",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "badge": {
          "description": "Optional trailing badge (count, label).",
          "type": "string",
          "default": ""
        },
        "collapsible": {
          "description": "When true, the header row toggles the open state on click/keyboard.",
          "type": "boolean",
          "default": true
        },
        "component": {
          "const": "NavGroup"
        },
        "icon": {
          "description": "Optional leading icon name (resolved via <icon-ui>).",
          "type": "string",
          "default": ""
        },
        "open": {
          "description": "Inline-expanded state. Toggled by header click when [collapsible].",
          "type": "boolean",
          "default": false
        },
        "text": {
          "description": "Visible group label.",
          "type": "string",
          "default": ""
        },
        "variant": {
          "description": "Visual treatment. Default ('') renders as a primary-rail group (icon row, caret, collapsible). 'section' renders the header as a static kicker label with always-visible children. When the parent <nav-ui> carries variant=\"section\", this group inherits it via CSS cascade unless an explicit variant is set on the group.",
          "type": "string",
          "enum": [
            "",
            "section"
          ],
          "default": ""
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [],
        "category": "layout",
        "composes": [
          "icon-ui",
          "badge-ui",
          "nav-item-ui"
        ],
        "events": {
          "group-toggle": {
            "description": "Fired when the header toggles via click/keyboard. Detail: { text, open }.",
            "detail": {
              "open": {
                "description": "Whether the group is now open.",
                "type": "boolean"
              },
              "text": {
                "description": "Group label text.",
                "type": "string"
              }
            }
          }
        },
        "examples": [],
        "keywords": [
          "nav",
          "navigation",
          "group",
          "sidebar",
          "menu"
        ],
        "name": "UINavGroup",
        "related": [
          "Nav",
          "NavItem",
          "Accordion"
        ],
        "slots": {
          "default": {
            "description": "Children — typically <nav-item-ui> rows."
          },
          "header": {
            "description": "Optional custom header. Auto-generated when missing."
          },
          "icon": {
            "description": "Override the leading [icon] glyph in the auto-generated header with a custom slotted element. Mutually exclusive with the [icon] attribute."
          }
        },
        "states": [
          {
            "description": "Default. Children hidden.",
            "name": "closed"
          },
          {
            "description": "Children visible inline.",
            "name": "open"
          }
        ],
        "status": "stable",
        "synonyms": {
          "nav-group": [
            "nav-section",
            "sidebar-group",
            "menu-group"
          ]
        },
        "tag": "nav-group-ui",
        "tokens": {},
        "traits": [],
        "version": 1
      }
    },
    "NavItem": {
      "title": "NavItem",
      "description": "Single navigation link inside <nav-ui> (optionally nested under\n<nav-group-ui>). Consolidates the prior `app-nav-item-ui` +\n`section-nav-item-ui` per ADR-0015 § Nav consolidation.\n\nSupports icon, label, optional badge, selected/disabled state, and\nkeyboard activation (Enter/Space). Selection is managed by the parent\n<nav-ui>; clicking or activating an item calls nav.select(this) and\nbubbles a `nav-select` event.\n",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "badge": {
          "description": "Optional trailing badge.",
          "type": "string",
          "default": ""
        },
        "component": {
          "const": "NavItem"
        },
        "disabled": {
          "description": "Suppresses click/keyboard activation; greyed visually.",
          "type": "boolean",
          "default": false
        },
        "icon": {
          "description": "Optional leading icon name.",
          "type": "string",
          "default": ""
        },
        "selected": {
          "description": "Set by the parent <nav-ui>'s select() method.",
          "type": "boolean",
          "default": false
        },
        "text": {
          "description": "Visible item label.",
          "type": "string",
          "default": ""
        },
        "value": {
          "description": "Identifier — typically a route or anchor.",
          "type": "string",
          "default": ""
        },
        "variant": {
          "description": "Visual treatment. Default ('') renders as a primary-rail item (reserved icon space, in-icon selected accent). 'section' renders flat — no icon space when absent, left-edge accent bar for selected. When the parent <nav-ui> carries variant=\"section\", this item inherits it via CSS cascade unless an explicit variant is set.",
          "type": "string",
          "enum": [
            "",
            "section"
          ],
          "default": ""
        }
      },
      "required": [
        "component",
        "text"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [],
        "category": "layout",
        "composes": [
          "icon-ui",
          "badge-ui"
        ],
        "events": {
          "nav-select": {
            "description": "Bubbles when the item is activated. Detail: { item, text, value }.",
            "detail": {
              "item": {
                "description": "The nav-item element itself.",
                "type": "object"
              },
              "text": {
                "description": "Item text content.",
                "type": "string"
              },
              "value": {
                "description": "Item value attribute.",
                "type": "string"
              }
            }
          }
        },
        "examples": [],
        "keywords": [
          "nav",
          "navigation",
          "item",
          "link",
          "sidebar"
        ],
        "name": "UINavItem",
        "related": [
          "Nav",
          "NavGroup",
          "Button",
          "Tab"
        ],
        "slots": {
          "default": {
            "description": "Optional override of the default icon + text + badge stamping."
          },
          "icon": {
            "description": "Override the leading [icon] glyph with a custom slotted element (custom icon-ui, image, avatar). Mutually exclusive with the [icon] attribute — slot child wins."
          }
        },
        "states": [
          {
            "description": "Default.",
            "name": "idle"
          },
          {
            "description": "aria-current=page.",
            "name": "selected"
          },
          {
            "description": "Suppressed activation.",
            "name": "disabled"
          }
        ],
        "status": "stable",
        "synonyms": {
          "nav-item": [
            "nav-link",
            "sidebar-item",
            "menu-link"
          ]
        },
        "tag": "nav-item-ui",
        "tokens": {},
        "traits": [],
        "version": 1
      }
    },
    "Noodles": {
      "title": "Noodles",
      "description": "SVG connection lines (noodles) between children with declared ports. Supports bezier, step, and straight curves.",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "animated": {
          "description": "Flowing dash animation on noodles",
          "type": "boolean",
          "default": false
        },
        "color": {
          "description": "Noodle stroke color. Defaults to --a-accent",
          "type": "string",
          "default": ""
        },
        "component": {
          "const": "Noodles"
        },
        "curve": {
          "description": "Noodle curve style",
          "type": "string",
          "enum": [
            "bezier",
            "step",
            "straight"
          ],
          "default": "bezier"
        },
        "editable": {
          "description": "Allow interactive creation/deletion of connections via drag",
          "type": "boolean",
          "default": false
        },
        "port-size": {
          "description": "Port indicator dot size in pixels",
          "type": "number",
          "default": 10
        },
        "portSize": {
          "description": "Port indicator size",
          "type": "number",
          "default": 10
        },
        "readonly": {
          "description": "View-only mode; disables drag/edit while keeping connections visible",
          "type": "boolean",
          "default": false
        },
        "show-ports": {
          "description": "Show port indicator dots. Defaults to true when editable",
          "type": "boolean",
          "default": false
        },
        "showPorts": {
          "description": "Show port indicators",
          "type": "boolean",
          "default": false
        },
        "stroke-width": {
          "description": "Stroke width in pixels",
          "type": "number",
          "default": 2
        },
        "strokeWidth": {
          "description": "Line stroke width",
          "type": "number",
          "default": 2
        },
        "tension": {
          "description": "Bezier control point distance (0-1). Higher = wider curves",
          "type": "number",
          "default": 0.5
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [],
        "category": "agent",
        "composes": [],
        "events": {
          "noodle-connect": {
            "description": "Fired when a connection is created. detail: { id, from, to, fromPort, toPort }",
            "detail": {
              "from": {
                "description": "Source node ID.",
                "type": "string"
              },
              "fromPort": {
                "description": "Source port identifier.",
                "type": "string"
              },
              "id": {
                "description": "Connection ID.",
                "type": "string"
              },
              "to": {
                "description": "Target node ID.",
                "type": "string"
              },
              "toPort": {
                "description": "Target port identifier.",
                "type": "string"
              }
            }
          },
          "noodle-disconnect": {
            "description": "Fired when a connection is removed. detail: { id, from, to, fromPort, toPort }",
            "detail": {
              "from": {
                "description": "Source node ID.",
                "type": "string"
              },
              "fromPort": {
                "description": "Source port identifier.",
                "type": "string"
              },
              "id": {
                "description": "Connection ID.",
                "type": "string"
              },
              "to": {
                "description": "Target node ID.",
                "type": "string"
              },
              "toPort": {
                "description": "Target port identifier.",
                "type": "string"
              }
            }
          },
          "noodle-drag": {
            "description": "Fired during drag-to-connect. detail: { from, fromPort, x, y, reconnect }"
          }
        },
        "examples": [
          {
            "description": "Basic Noodles usage",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"Card\",\n    \"children\": [\n      \"sec\"\n    ]\n  },\n  {\n    \"id\": \"sec\",\n    \"component\": \"Section\",\n    \"children\": [\n      \"comp\"\n    ]\n  },\n  {\n    \"id\": \"comp\",\n    \"component\": \"Noodles\"\n  }\n]",
            "name": "basic-noodles"
          }
        ],
        "keywords": [
          "noodles"
        ],
        "name": "UINoodles",
        "related": [
          "Canvas",
          "EditorCanvas"
        ],
        "slots": {},
        "states": [
          {
            "description": "Default, ready for interaction.",
            "name": "idle"
          },
          {
            "description": "Non-interactive; dimmed.",
            "attribute": "disabled",
            "name": "disabled"
          }
        ],
        "status": "stable",
        "synonyms": {
          "noodles": [
            "connection-curve",
            "wire",
            "edge-line",
            "bezier-wire"
          ]
        },
        "tag": "noodles-ui",
        "tokens": {
          "--noodles-duration": {
            "description": "Transition duration for noodle animations"
          },
          "--noodles-easing": {
            "description": "Easing function for noodle animations"
          }
        },
        "traits": [],
        "version": 1
      }
    },
    "NotificationPreferences": {
      "title": "NotificationPreferences",
      "description": "Page-level Settings composite: a matrix of notification types (rows)\n× delivery channels (columns: in-app, email, SMS) with a binary\n<check-ui> in each cell and an optional <switch-ui> column-header\nmaster toggle for bulk-flipping a channel across every row.\n\nForm-bearing — the composite extends UIFormElement and serializes its\ncurrent preferences shape as JSON on `value`. Per first-principle #2\n(\"save is the consumer's job\"), the composite does NOT mutate the\npassed-in `preferences` array; it emits a typed `change` event per\ncell toggle and a `bulk-toggle` event per column-header switch, and\nexposes the staged JSON via the form value so a host <form> submit\ncarries it through ElementInternals.\n\nChannels are columns; types are rows (the smaller-set / larger-set\ninvariant — channels are 3-5 in the wild, types are 10-50). Layout\nrenders as a semantic ARIA grid (`role=\"table\"`/`row`/`cell`/\n`rowheader`/`columnheader`) — NOT native `<table>` (per the HTML\nparser strip rule, table-content tags would foster-parent out of a\ncustom-element subtree).\n\nSpec: docs/specs/implementation-ready/SPEC-064-notification-preferences.md.\n",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "channelEnabled": {
          "description": "Map of channel-key → master-toggle boolean for the column-header\n<switch-ui>. When omitted, master toggles default to `true` for\nevery channel. Independent of cell values — toggling the master\noff does NOT auto-update the cells; the host receives a\n`bulk-toggle` event and updates `preferences` itself.\n",
          "type": "object",
          "default": {}
        },
        "channels": {
          "description": "Column definitions — one record per delivery channel. Each\ncarries a stable `key`, a `label` (the column header), and an\noptional `icon` name (Phosphor — defaults to no icon when\nabsent). Example: [{key:\"in-app\", label:\"In-app\", icon:\"chat-circle\"},\n{key:\"email\", label:\"Email\", icon:\"envelope\"}]. Empty array\nrenders nothing (the matrix needs at least one column).\n",
          "$ref": "#/$defs/DynamicStringList"
        },
        "component": {
          "const": "NotificationPreferences"
        },
        "disabled": {
          "description": "All cells + master toggles become non-interactive.",
          "type": "boolean",
          "default": false
        },
        "group-by": {
          "description": "Row-grouping mode. `none` (default) renders all rows in one\nblock. `group` renders one section per unique `preferences[].group`\nvalue with a header row above each section.\n",
          "type": "string",
          "enum": [
            "none",
            "group"
          ],
          "default": "none"
        },
        "loading": {
          "description": "Renders a skeleton matrix overlay. Cells become non-interactive\nand dim while loading.\n",
          "type": "boolean",
          "default": false
        },
        "preferences": {
          "description": "Matrix data — one row per notification type. Each record carries\na stable `key`, a `label`, optional `description` (rendered under\nthe label), optional `group` (when `group-by=\"group\"`), and a\n`channels` map keyed by channel key with boolean values.\nExample: {key:\"mentions\", label:\"Mentions\", channels:{\"in-app\":true,\nemail:false, sms:false}}. Empty array renders the empty state.\n",
          "$ref": "#/$defs/DynamicStringList"
        }
      },
      "required": [
        "component",
        "preferences",
        "channels"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [
          {
            "fix": "<notification-preferences-ui id=\"prefs\"></notification-preferences-ui>\n<script>\n  document.querySelector('#prefs').channels = [\n    {key:'email', label:'Email'}\n  ];\n  document.querySelector('#prefs').preferences = [\n    {key:'mentions', label:'Mentions', channels:{email:true}},\n    {key:'replies',  label:'Replies',  channels:{email:false}}\n  ];\n</script>\n",
            "why": "Cells are generated from the `preferences` matrix. Slotted\nswitches are ignored and the host renders empty.\n",
            "wrong": "<notification-preferences-ui>\n  <switch-ui label=\"Email mentions\"></switch-ui>\n  <switch-ui label=\"Email replies\"></switch-ui>\n</notification-preferences-ui>\n"
          },
          {
            "fix": "<notification-preferences-ui id=\"prefs\"></notification-preferences-ui>\n<script>/* set channels + preferences here */</script>\n",
            "why": "Re-implements the matrix in raw HTML — loses the typed\n`change` / `bulk-toggle` event contract, the column-master\nswitch, the group-by support, and the consistent token-driven\nvisual treatment. Worse, table-content tags inside a custom\nelement subtree are foster-parented out of the DOM by the HTML\nparser — they silently vanish.\n",
            "wrong": "<table>\n  <thead><tr><th></th><th>Email</th></tr></thead>\n  <tbody>\n    <tr><th>Mentions</th><td><check-ui></check-ui></td></tr>\n  </tbody>\n</table>\n"
          }
        ],
        "category": "container",
        "composes": [
          "check-ui",
          "switch-ui",
          "icon-ui",
          "text-ui",
          "empty-state-ui"
        ],
        "events": {
          "bulk-toggle": {
            "description": "Fired when the user toggles a column-header <switch-ui>.\nBubbles. Mirrors `change` shape but for the column master —\nhost applies the bulk change to its own `preferences` data.\n",
            "detail": {
              "channel": {
                "description": "The `key` of the channel column whose master flipped.",
                "type": "string"
              },
              "enabled": {
                "description": "The new desired master state.",
                "type": "boolean"
              }
            }
          },
          "change": {
            "description": "Fired when the user toggles a cell <check-ui>. Bubbles. The\ncomposite emits this with the previous state — the host must\napply the new state to its own data and re-pass `preferences`\nfor the cell to visually update.\n",
            "detail": {
              "channel": {
                "description": "The `key` of the channel column whose cell flipped.",
                "type": "string"
              },
              "enabled": {
                "description": "The new desired state (true = opted in).",
                "type": "boolean"
              },
              "row": {
                "description": "The `key` of the notification type whose cell flipped.",
                "type": "string"
              }
            }
          }
        },
        "examples": [
          {
            "description": "Three channels (in-app / email / SMS) × four notification types.",
            "a2ui": "[\n  {\n    \"id\": \"np-default\",\n    \"component\": \"NotificationPreferences\",\n    \"name\": \"notifications\",\n    \"channels\": [\n      {\"key\": \"in-app\", \"label\": \"In-app\", \"icon\": \"chat-circle\"},\n      {\"key\": \"email\",  \"label\": \"Email\",  \"icon\": \"envelope\"},\n      {\"key\": \"sms\",    \"label\": \"SMS\",    \"icon\": \"device-mobile\"}\n    ],\n    \"preferences\": [\n      {\"key\": \"mentions\", \"label\": \"Mentions\",\n       \"channels\": {\"in-app\": true, \"email\": true,  \"sms\": false}},\n      {\"key\": \"comments\", \"label\": \"Comments\",\n       \"channels\": {\"in-app\": true, \"email\": false, \"sms\": false}},\n      {\"key\": \"releases\", \"label\": \"Releases\",\n       \"channels\": {\"in-app\": false,\"email\": true,  \"sms\": false}},\n      {\"key\": \"security\", \"label\": \"Security alerts\",\n       \"channels\": {\"in-app\": true, \"email\": true,  \"sms\": true}}\n    ]\n  }\n]\n",
            "name": "default"
          },
          {
            "description": "Same matrix grouped by category via group-by=\"group\".",
            "a2ui": "[\n  {\n    \"id\": \"np-grouped\",\n    \"component\": \"NotificationPreferences\",\n    \"name\": \"notifications\",\n    \"groupBy\": \"group\",\n    \"channels\": [\n      {\"key\": \"in-app\", \"label\": \"In-app\"},\n      {\"key\": \"email\",  \"label\": \"Email\"}\n    ],\n    \"preferences\": [\n      {\"key\": \"mentions\", \"label\": \"Mentions\", \"group\": \"Activity\",\n       \"channels\": {\"in-app\": true, \"email\": true}},\n      {\"key\": \"comments\", \"label\": \"Comments\", \"group\": \"Activity\",\n       \"channels\": {\"in-app\": true, \"email\": false}},\n      {\"key\": \"digest\",   \"label\": \"Weekly digest\", \"group\": \"Summaries\",\n       \"channels\": {\"in-app\": false, \"email\": true}}\n    ]\n  }\n]\n",
            "name": "grouped"
          }
        ],
        "keywords": [
          "notification-preferences",
          "notifications",
          "preferences",
          "opt-in",
          "opt-out",
          "alerts",
          "channels",
          "in-app",
          "email",
          "sms",
          "subscriptions",
          "notification-settings"
        ],
        "name": "UINotificationPreferences",
        "related": [
          "Check",
          "Switch",
          "Table",
          "EmptyState",
          "Icon",
          "Text"
        ],
        "slots": {
          "empty": {
            "description": "Custom empty-state copy shown when `preferences` is empty. Falls\nback to a default <empty-state-ui> when not provided.\n"
          },
          "footer": {
            "description": "Optional content below the matrix — e.g. a global Save Changes\nbutton row or fine-print disclaimer. Falls back to nothing.\n"
          },
          "header": {
            "description": "Optional content above the matrix — e.g. a page title, intro\ncopy, or per-page save row. Falls back to nothing when empty.\n"
          }
        },
        "states": [
          {
            "description": "Default — matrix rendered, ready for interaction.",
            "name": "idle"
          },
          {
            "description": "Skeleton overlay while data loads.",
            "attribute": "loading",
            "name": "loading"
          },
          {
            "description": "All toggles non-interactive.",
            "attribute": "disabled",
            "name": "disabled"
          },
          {
            "description": "No notification types configured.",
            "attribute": "empty",
            "name": "empty"
          }
        ],
        "status": "stable",
        "synonyms": {
          "channels": [
            "delivery",
            "destinations"
          ],
          "notifications": [
            "alerts",
            "messages",
            "updates"
          ],
          "preferences": [
            "settings",
            "opt-ins",
            "subscriptions"
          ]
        },
        "tag": "notification-preferences-ui",
        "tokens": {
          "--notification-preferences-bg": {
            "description": "Host background.",
            "default": "var(--a-bg)"
          },
          "--notification-preferences-border": {
            "description": "Row separator color.",
            "default": "var(--a-border-subtle)"
          },
          "--notification-preferences-channel-width": {
            "description": "Minimum column width for each channel cell.",
            "default": "var(--a-space-9)"
          },
          "--notification-preferences-group-fg": {
            "description": "Group-heading label color.",
            "default": "var(--a-fg-muted)"
          },
          "--notification-preferences-px": {
            "description": "Host horizontal padding.",
            "default": "var(--a-space-5)"
          },
          "--notification-preferences-py": {
            "description": "Host vertical padding.",
            "default": "var(--a-space-5)"
          },
          "--notification-preferences-radius": {
            "description": "Outer matrix container radius.",
            "default": "var(--a-radius-md)"
          },
          "--notification-preferences-row-bg": {
            "description": "Even-row zebra background.",
            "default": "var(--a-bg-muted)"
          },
          "--notification-preferences-row-label-min": {
            "description": "Minimum row-label column width.",
            "default": "12rem"
          },
          "--notification-preferences-row-px": {
            "description": "Per-cell horizontal padding.",
            "default": "var(--a-space-3)"
          },
          "--notification-preferences-row-py": {
            "description": "Per-row vertical padding.",
            "default": "var(--a-space-3)"
          }
        },
        "traits": [],
        "version": 1
      }
    },
    "NumberFormat": {
      "title": "NumberFormat",
      "description": "Display a numeric value with locale-aware formatting — currency,\npercentage, compact (1.2K / 3.4M), unit, or plain decimal. Wraps\n`Intl.NumberFormat`. Distinct from `<input-ui type=\"number\">`\n(an INPUT primitive); this is a DISPLAY primitive — read-only, no\nform participation, no keyboard handling. Pair with `<stat-ui>` for\nKPI surfaces or use standalone inline within prose.\n",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "compactDisplay": {
          "description": "When [notation=\"compact\"], controls the compact-form length.\n`short` = \"1.2M\" (default); `long` = \"1.2 million\".\n",
          "type": "string",
          "enum": [
            "short",
            "long"
          ],
          "default": "short"
        },
        "component": {
          "const": "NumberFormat"
        },
        "currency": {
          "description": "ISO 4217 currency code (e.g. \"USD\", \"EUR\", \"JPY\"). Required when\n[number-style=\"currency\"]; ignored otherwise.\n",
          "type": "string",
          "default": ""
        },
        "locale": {
          "description": "BCP-47 locale tag for the formatter. Empty defaults to the\ndocument locale (`<html lang>`) then to browser default.\n",
          "type": "string",
          "default": ""
        },
        "maximumFractionDigits": {
          "description": "Maximum fractional digits (0–20). Default `2` for decimal/\ncurrency/percent, `1` for compact notation.\n",
          "type": "number",
          "default": 2
        },
        "minimumFractionDigits": {
          "description": "Minimum fractional digits (0–20). Padded with trailing zeros.\nUseful for currency display to force \".00\" suffix.\n",
          "type": "number",
          "default": 0
        },
        "notation": {
          "description": "`Intl.NumberFormat` `notation` option. `standard` is the\nthousands-grouped form (1,234,567); `compact` is the abbreviated\nform (1.2M); `scientific` and `engineering` are the exponent\nforms. Defaults to `standard`.\n",
          "type": "string",
          "enum": [
            "standard",
            "compact",
            "scientific",
            "engineering"
          ],
          "default": "standard"
        },
        "numberStyle": {
          "description": "`Intl.NumberFormat` `style` option. `decimal` (default) renders a\nplain number with locale-aware grouping. `currency` requires\n[currency] to be set. `percent` formats 0–1 as 0%–100%. `unit`\nrequires [unit] to be set (e.g. \"kilobyte\", \"celsius\").\n",
          "type": "string",
          "enum": [
            "decimal",
            "currency",
            "percent",
            "unit"
          ],
          "default": "decimal"
        },
        "signDisplay": {
          "description": "`Intl.NumberFormat` `signDisplay` option. `auto` (default) shows\n\"−\" for negatives only; `always` shows \"+\" / \"−\"; `exceptZero`\nshows sign for non-zero only; `never` hides signs.\n",
          "type": "string",
          "enum": [
            "auto",
            "always",
            "exceptZero",
            "never"
          ],
          "default": "auto"
        },
        "unit": {
          "description": "`Intl.NumberFormat` unit identifier (e.g. \"kilometer-per-hour\",\n\"celsius\", \"byte\"). Required when [number-style=\"unit\"]; ignored\notherwise. See MDN's NumberFormat docs for the valid set.\n",
          "type": "string",
          "default": ""
        },
        "value": {
          "description": "The numeric value to format. Empty string or non-numeric value\nrenders nothing.\n",
          "type": "number",
          "default": 0
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [
          {
            "fix": "<number-format-ui value=\"0.5\" number-style=\"percent\"></number-format-ui>\n",
            "why": "Renders \"5,000%\" — Intl.NumberFormat percent style multiplies the\ninput by 100. value=50 means \"5000%\".\n",
            "wrong": "<number-format-ui value=\"50\" number-style=\"percent\"></number-format-ui>\n"
          },
          {
            "fix": "<number-format-ui value=\"9.99\" number-style=\"currency\" currency=\"USD\"></number-format-ui>\n",
            "why": "Missing [currency] code. Renders nothing rather than producing\nmalformed currency output.\n",
            "wrong": "<number-format-ui value=\"9.99\" number-style=\"currency\"></number-format-ui>\n"
          }
        ],
        "category": "display",
        "composes": [],
        "events": {},
        "examples": [
          {
            "description": "Plain locale-grouped number — default style.",
            "a2ui": "[\n  {\n    \"id\": \"n\",\n    \"component\": \"NumberFormat\",\n    \"value\": 1234567.89\n  }\n]\n",
            "name": "decimal"
          },
          {
            "description": "USD currency display.",
            "a2ui": "[\n  {\n    \"id\": \"n\",\n    \"component\": \"NumberFormat\",\n    \"value\": 1299.99,\n    \"numberStyle\": \"currency\",\n    \"currency\": \"USD\"\n  }\n]\n",
            "name": "currency"
          },
          {
            "description": "Fraction → percent (0.876 → 87.6%).",
            "a2ui": "[\n  {\n    \"id\": \"n\",\n    \"component\": \"NumberFormat\",\n    \"value\": 0.876,\n    \"numberStyle\": \"percent\",\n    \"maximumFractionDigits\": 1\n  }\n]\n",
            "name": "percent"
          },
          {
            "description": "Compact-form (1.2M, 3.4K).",
            "a2ui": "[\n  {\n    \"id\": \"n\",\n    \"component\": \"NumberFormat\",\n    \"value\": 1234567,\n    \"notation\": \"compact\"\n  }\n]\n",
            "name": "compact"
          }
        ],
        "keywords": [
          "number-format",
          "format",
          "currency",
          "percent",
          "percentage",
          "compact",
          "number",
          "locale",
          "intl"
        ],
        "name": "UINumberFormat",
        "related": [
          "stat",
          "text",
          "badge",
          "input"
        ],
        "slots": {},
        "states": [
          {
            "description": "Default, displaying the formatted value.",
            "name": "idle"
          }
        ],
        "status": "stable",
        "synonyms": {
          "currency": [
            "number-format",
            "money",
            "price"
          ],
          "number": [
            "number-format",
            "format"
          ],
          "percent": [
            "number-format",
            "percentage"
          ]
        },
        "tag": "number-format-ui",
        "tokens": {},
        "traits": [],
        "version": 1
      }
    },
    "OnboardingChecklist": {
      "title": "OnboardingChecklist",
      "description": "Module-tier onboarding checklist — a progressive setup-step widget\n(\"Getting started\" card seen in Stripe / Linear / Vercel dashboards).\nComposes <progress-ui> (top fill bar), <list-ui> + <list-item-ui>\n(the step rows), <check-ui> (per-item completion checkbox), and\noptional <button-ui> (per-item action CTA).\n\nOwns the data model (items: array of {id, label, description, href,\ndone}), the persistence contract (storage-key writes a JSON blob to\nlocalStorage / sessionStorage), the auto-computed progress display,\nand the dismiss-on-complete behavior. Items are data, not slotted\nmarkup — host wiring uses stable per-item ids, not DOM positions.\n\nUse for the \"card of optional setup tasks\" case; use <step-progress-ui>\nfor horizontal multi-screen wizards where the user is locked into\nlinear progression.\n",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "title": {
          "description": "Header label above the progress bar. Defaults to \"Get started\".",
          "type": "string",
          "default": "Get started"
        },
        "items": {
          "description": "Step list — each item is { id, label, description?, href?, done? }. Required, non-empty.",
          "$ref": "#/$defs/DynamicStringList"
        },
        "collapsed": {
          "description": "Initial / current collapsed state — hides the item list, keeps progress + header visible.",
          "$ref": "#/$defs/DynamicBoolean"
        },
        "collapsible": {
          "description": "Show a top-right collapse toggle.",
          "type": "boolean",
          "default": true
        },
        "component": {
          "const": "OnboardingChecklist"
        },
        "dismiss-on-complete": {
          "description": "Auto-hide the widget when all items are done.",
          "type": "boolean",
          "default": true
        },
        "storage": {
          "description": "Persistence backend when storage-key is set.",
          "type": "string",
          "enum": [
            "local",
            "session",
            "none"
          ],
          "default": "local"
        },
        "storage-key": {
          "description": "localStorage key for per-item completion persistence. Empty string disables storage (ephemeral).",
          "type": "string",
          "default": ""
        },
        "value": {
          "description": "Completion map mapping item id to boolean. When set, host owns state and storage attributes are ignored.",
          "type": "object",
          "default": {}
        }
      },
      "required": [
        "component",
        "items"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [
          {
            "fix": "{ \"component\": \"OnboardingChecklist\", \"items\": [{ \"id\": \"x\", \"label\": \"Step 1\" }] }\n",
            "why": "Empty checklist — renders an empty card.\n",
            "wrong": "{ \"component\": \"OnboardingChecklist\", \"items\": [] }\n"
          },
          {
            "fix": "{ \"component\": \"OnboardingChecklist\", \"items\": [\n  { \"id\": \"a\", \"label\": \"Step A\" }, { \"id\": \"b\", \"label\": \"Step B\" }\n] }\n",
            "why": "Items missing `id`. The component cannot persist completion\nwithout stable per-item identifiers.\n",
            "wrong": "{ \"component\": \"OnboardingChecklist\", \"items\": [\n  { \"label\": \"Step A\" }, { \"label\": \"Step B\" }\n] }\n"
          }
        ],
        "category": "feedback",
        "composes": [],
        "events": {
          "onboarding-complete": {
            "description": "Fired when all items become done.",
            "detail": {
              "value": {
                "description": "The completion map at the moment of full completion.",
                "type": "object"
              }
            }
          },
          "onboarding-dismiss": {
            "description": "Fired when the widget collapses or auto-dismisses on completion.",
            "detail": {
              "reason": {
                "description": "Why the widget was dismissed.",
                "type": "string",
                "enum": [
                  "collapsed",
                  "complete"
                ]
              }
            }
          },
          "onboarding-step-action": {
            "description": "Fired when the user clicks an item's action CTA.",
            "detail": {
              "href": {
                "description": "The href of the CTA (may be empty when host wires the click elsewhere).",
                "type": "string"
              },
              "id": {
                "description": "The id of the step whose CTA was clicked.",
                "type": "string"
              }
            }
          },
          "onboarding-step-complete": {
            "description": "Fired when a step transitions from undone to done.",
            "detail": {
              "id": {
                "description": "The id of the step that just completed.",
                "type": "string"
              },
              "value": {
                "description": "Snapshot of the full completion map after the change.",
                "type": "object"
              }
            }
          }
        },
        "examples": [
          {
            "description": "Three-step dashboard setup card.",
            "a2ui": "[\n  {\n    \"id\": \"onb-1\",\n    \"component\": \"OnboardingChecklist\",\n    \"storageKey\": \"acme:onboarding:v1\",\n    \"items\": [\n      { \"id\": \"profile\", \"label\": \"Complete your profile\", \"description\": \"Add a photo and bio\", \"href\": \"/settings/profile\" },\n      { \"id\": \"team\",    \"label\": \"Invite your team\",      \"description\": \"Add at least one teammate\", \"href\": \"/settings/team\" },\n      { \"id\": \"connect\", \"label\": \"Connect a data source\", \"description\": \"Hook up the first integration\", \"href\": \"/integrations\" }\n    ]\n  }\n]\n",
            "name": "basic-checklist"
          }
        ],
        "keywords": [
          "onboarding",
          "checklist",
          "getting-started",
          "setup",
          "steps",
          "progress",
          "getting started"
        ],
        "name": "UIOnboardingChecklist",
        "related": [
          "Check",
          "List",
          "ListItem",
          "Progress",
          "Button",
          "StepProgress"
        ],
        "slots": {
          "description": {
            "description": "Optional subtitle / supporting prose rendered beneath the header. Renders at body-subtle typography. Use for richer markup than the plain [description] attribute string."
          },
          "complete": {
            "description": "Content shown when all items are done and dismiss-on-complete is false."
          },
          "footer": {
            "description": "Optional footer content (e.g. \"Skip for now\" link / button)."
          },
          "header": {
            "description": "Custom title region above the progress bar. Overrides the default [title] attribute label."
          }
        },
        "states": [
          {
            "description": "Some items incomplete; widget visible and expanded.",
            "name": "idle"
          },
          {
            "description": "Item list hidden; header + progress visible.",
            "attribute": "collapsed",
            "name": "collapsed"
          },
          {
            "description": "All items done. Behavior depends on dismiss-on-complete.",
            "attribute": "data-complete",
            "name": "complete"
          },
          {
            "description": "Widget removed from layout after collapse or auto-dismiss.",
            "attribute": "hidden",
            "name": "dismissed"
          }
        ],
        "status": "stable",
        "synonyms": {
          "checklist": [
            "todo",
            "task-list",
            "steps"
          ],
          "getting-started": [
            "onboarding",
            "setup",
            "welcome"
          ],
          "onboarding": [
            "getting-started",
            "setup",
            "welcome",
            "kickoff"
          ],
          "setup": [
            "onboarding",
            "getting-started",
            "configuration"
          ]
        },
        "tag": "onboarding-checklist-ui",
        "tokens": {
          "--onboarding-checklist-bg": {
            "description": "Card background. Defaults to elevated canvas tier.",
            "default": "var(--a-canvas-1)"
          },
          "--onboarding-checklist-border": {
            "description": "Outer border.",
            "default": "1px solid var(--a-border-subtle)"
          },
          "--onboarding-checklist-fg": {
            "description": "Primary foreground color.",
            "default": "var(--a-fg)"
          },
          "--onboarding-checklist-fg-muted": {
            "description": "Secondary foreground color for descriptions + meta.",
            "default": "var(--a-fg-muted)"
          },
          "--onboarding-checklist-gap": {
            "description": "Gap between header / progress / items / footer.",
            "default": "var(--a-space-3)"
          },
          "--onboarding-checklist-progress-fill": {
            "description": "Progress-bar fill color (forwarded to inner <progress-ui> via --progress-fill).",
            "default": "var(--a-accent)"
          },
          "--onboarding-checklist-px": {
            "description": "Inline (left/right) padding.",
            "default": "var(--a-space-4)"
          },
          "--onboarding-checklist-py": {
            "description": "Block (top/bottom) padding.",
            "default": "var(--a-space-4)"
          },
          "--onboarding-checklist-radius": {
            "description": "Outer card radius.",
            "default": "var(--a-radius-lg)"
          },
          "--onboarding-checklist-shadow": {
            "description": "Card elevation.",
            "default": "var(--a-shadow-sm)"
          }
        },
        "traits": [],
        "version": 1
      }
    },
    "OptionCard": {
      "title": "OptionCard",
      "description": "Selectable card with radio semantics. A \"rich radio\" — single-select one of N where each option carries a heading, optional description, and optional leading icon. Siblings sharing a `name` form a radiogroup. The whole card is the click target; a CSS-rendered radio circle in the top-left signals state. Form-associated, so `name=value` submits with the parent form when checked.",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "description": {
          "description": "Description text. Stamped into a [slot=\"description\"] span when no slotted description is provided.",
          "type": "string",
          "default": ""
        },
        "required": {
          "description": "Marks the radiogroup as requiring a selection for form validation.",
          "type": "boolean",
          "default": false
        },
        "checked": {
          "description": "Whether this card is currently selected.",
          "type": "boolean",
          "default": false
        },
        "component": {
          "const": "OptionCard"
        },
        "disabled": {
          "description": "Disables interaction and dims the card.",
          "type": "boolean",
          "default": false
        },
        "heading": {
          "description": "Heading text. Stamped into a [slot=\"heading\"] span when no slotted heading is provided.",
          "type": "string",
          "default": ""
        },
        "icon": {
          "description": "Optional Phosphor icon name. Stamped as a leading <icon-ui slot=\"icon\"> when set.",
          "type": "string",
          "default": ""
        },
        "layout": {
          "description": "Internal layout. `default` puts the indicator on the left and the icon adjacent. `tile` stacks vertically — icon top-left, indicator top-right, heading + description below — for hero pickers (source / role / plan tiles) where the icon is a primary brand cue.",
          "type": "string",
          "enum": [
            "default",
            "tile"
          ],
          "default": "default"
        },
        "name": {
          "description": "Form control name. Siblings sharing a name form a radiogroup.",
          "type": "string",
          "default": ""
        },
        "value": {
          "description": "Form value submitted when checked (defaults to `on` if empty).",
          "type": "string",
          "default": ""
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [],
        "category": "input",
        "composes": [
          "icon-ui"
        ],
        "events": {
          "change": {
            "description": "Fired when this card becomes selected (bubbles)."
          }
        },
        "examples": [
          {
            "description": "A four-option pick-one for \"what brings you here\" — radio-card behavior with heading + description per option.",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"Column\",\n    \"gap\": \"2\",\n    \"children\": [\"build\", \"explore\", \"migrate\", \"evaluate\"]\n  },\n  {\n    \"id\": \"build\",\n    \"component\": \"OptionCard\",\n    \"name\": \"use-case\",\n    \"value\": \"build\",\n    \"checked\": true,\n    \"heading\": \"I'm building a product\",\n    \"description\": \"Spinning up a new project — design, ship, iterate.\"\n  },\n  {\n    \"id\": \"explore\",\n    \"component\": \"OptionCard\",\n    \"name\": \"use-case\",\n    \"value\": \"explore\",\n    \"heading\": \"I'm exploring the product\",\n    \"description\": \"Kicking the tires before bringing a team along.\"\n  },\n  {\n    \"id\": \"migrate\",\n    \"component\": \"OptionCard\",\n    \"name\": \"use-case\",\n    \"value\": \"migrate\",\n    \"heading\": \"I'm migrating from another tool\",\n    \"description\": \"Moving an existing workspace and want a smooth port.\"\n  },\n  {\n    \"id\": \"evaluate\",\n    \"component\": \"OptionCard\",\n    \"name\": \"use-case\",\n    \"value\": \"evaluate\",\n    \"heading\": \"I'm evaluating for my team\",\n    \"description\": \"Comparing options and want to dig into specifics.\"\n  }\n]",
            "name": "use-case-picker"
          }
        ],
        "keywords": [
          "option",
          "card",
          "radio",
          "select",
          "choice",
          "picker",
          "tier",
          "plan",
          "onboarding",
          "registration"
        ],
        "name": "UIOptionCard",
        "related": [
          "radio",
          "card",
          "check",
          "segmented"
        ],
        "slots": {
          "description": {
            "description": "Rich description content. Overrides the `description` attribute when present."
          },
          "default": {
            "description": "Spillover content revealed only when the card is checked — typically a follow-up form field (e.g. a textarea on an \"Other\" option, conditional inputs that depend on the selection). Aligns with the heading/description column; hidden via `display: none` when not checked."
          },
          "action": {
            "description": "CTA slot for `layout=\"tile\"` — a button-ui anchored to the card's bottom edge and stretched full-width, so a row of tile cards keeps their CTAs aligned regardless of body length (plan-picker-style pickers)."
          },
          "heading": {
            "description": "Rich heading content. Overrides the `heading` attribute when present."
          },
          "icon": {
            "description": "Custom icon element. Overrides the `icon` attribute when present."
          }
        },
        "states": [
          {
            "description": "Default, ready for interaction.",
            "name": "idle"
          },
          {
            "description": "Pointer over a non-checked card.",
            "name": "hover",
            "selector": ":not([checked]):not([disabled]):hover"
          },
          {
            "description": "Selected — accent border, tinted background, filled radio circle.",
            "attribute": "checked",
            "name": "checked"
          },
          {
            "description": "Non-interactive; dimmed.",
            "attribute": "disabled",
            "name": "disabled"
          },
          {
            "description": "Keyboard focus ring.",
            "name": "focused",
            "selector": ":focus-visible"
          }
        ],
        "status": "stable",
        "synonyms": {
          "picker": [
            "option-card",
            "radio",
            "select"
          ],
          "radio": [
            "option-card",
            "radio",
            "select"
          ],
          "tier": [
            "option-card",
            "card",
            "plan"
          ]
        },
        "tag": "option-card-ui",
        "tokens": {
          "--option-card-bg": {
            "description": "Default background."
          },
          "--option-card-bg-checked": {
            "description": "Background when checked."
          },
          "--option-card-bg-hover": {
            "description": "Hover background (non-checked)."
          },
          "--option-card-border": {
            "description": "Default border color."
          },
          "--option-card-border-checked": {
            "description": "Border color when checked."
          },
          "--option-card-border-hover": {
            "description": "Hover border color (non-checked)."
          },
          "--option-card-desc-color": {
            "description": "Description text color."
          },
          "--option-card-desc-line-height": {
            "description": "Description line height."
          },
          "--option-card-desc-size": {
            "description": "Description font size."
          },
          "--option-card-disabled-opacity": {
            "description": "Opacity multiplier when disabled."
          },
          "--option-card-duration": {
            "description": "Transition duration for hover / checked state changes."
          },
          "--option-card-easing": {
            "description": "Transition easing."
          },
          "--option-card-focus-ring": {
            "description": "Focus ring (box-shadow value)."
          },
          "--option-card-gap-x": {
            "description": "Horizontal gap between indicator (and icon) and content."
          },
          "--option-card-gap-y": {
            "description": "Vertical gap between heading and description."
          },
          "--option-card-heading-color": {
            "description": "Heading text color."
          },
          "--option-card-heading-color-checked": {
            "description": "Heading text color when the card is checked (defaults to `--a-fg-strong` so the selected card reads with extra emphasis on top of the bg/border state)."
          },
          "--option-card-heading-size": {
            "description": "Heading font size."
          },
          "--option-card-heading-weight": {
            "description": "Heading font weight."
          },
          "--option-card-icon-color": {
            "description": "Leading icon color when the card is not checked."
          },
          "--option-card-icon-color-checked": {
            "description": "Leading icon color when the card is checked."
          },
          "--option-card-icon-size": {
            "description": "Leading icon size (sets `--a-icon-size` on the slotted icon-ui)."
          },
          "--option-card-padding-block": {
            "description": "Vertical padding inside the card."
          },
          "--option-card-padding-inline": {
            "description": "Horizontal padding inside the card."
          },
          "--option-card-radio-bg": {
            "description": "Indicator background when not checked."
          },
          "--option-card-radio-border": {
            "description": "Indicator border when not checked."
          },
          "--option-card-radio-dot": {
            "description": "Inner dot color when checked."
          },
          "--option-card-radio-fill": {
            "description": "Indicator fill color when checked."
          },
          "--option-card-radio-size": {
            "description": "Diameter of the indicator circle."
          },
          "--option-card-radius": {
            "description": "Card corner radius."
          }
        },
        "traits": [
          "focusable"
        ],
        "version": 1
      }
    },
    "OtpInput": {
      "title": "OtpInput",
      "description": "One-time password input with individual digit boxes. Auto-advances on entry, backs up on delete.",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "component": {
          "const": "OtpInput"
        },
        "disabled": {
          "description": "Disables interaction",
          "type": "boolean",
          "default": false
        },
        "length": {
          "description": "Number of digit boxes",
          "type": "number",
          "default": 6
        },
        "name": {
          "description": "Form field name",
          "type": "string",
          "default": ""
        },
        "value": {
          "description": "Current OTP value",
          "type": "string",
          "default": ""
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [],
        "category": "input",
        "composes": [],
        "events": {
          "change": {
            "description": "Fired alongside `input` on every digit change. Provides form-bearing-primitive event-shape parity (every UIFormElement emits `change` with `detail.value`).",
            "detail": {
              "value": {
                "description": "Combined digits at the moment of the change.",
                "type": "string"
              }
            }
          },
          "complete": {
            "description": "Fired exactly once when the user fills the last digit slot. detail.value is the combined string.",
            "detail": {
              "value": {
                "description": "Combined digits (e.g. \"123456\").",
                "type": "string"
              }
            }
          },
          "input": {
            "description": "Fired on every digit change. detail.value is the current combined string.",
            "detail": {
              "value": {
                "description": "Combined digits at the moment of the change.",
                "type": "string"
              }
            }
          }
        },
        "examples": [
          {
            "description": "OTP verification form with code input and submit button.",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"Card\",\n    \"children\": [\n      \"hdr\",\n      \"sec\"\n    ]\n  },\n  {\n    \"id\": \"hdr\",\n    \"component\": \"Header\",\n    \"children\": [\n      \"title\",\n      \"desc\"\n    ]\n  },\n  {\n    \"id\": \"title\",\n    \"component\": \"Text\",\n    \"slot\": \"heading\",\n    \"textContent\": \"Verify Your Identity\"\n  },\n  {\n    \"id\": \"desc\",\n    \"component\": \"Text\",\n    \"slot\": \"description\",\n    \"textContent\": \"Enter the 6-digit code sent to your email.\"\n  },\n  {\n    \"id\": \"sec\",\n    \"component\": \"Section\",\n    \"children\": [\n      \"col\"\n    ]\n  },\n  {\n    \"id\": \"col\",\n    \"component\": \"Column\",\n    \"children\": [\n      \"otp\",\n      \"btn\"\n    ],\n    \"gap\": \"4\",\n    \"align\": \"center\"\n  },\n  {\n    \"id\": \"otp\",\n    \"component\": \"OtpInput\",\n    \"length\": 6\n  },\n  {\n    \"id\": \"btn\",\n    \"component\": \"Button\",\n    \"text\": \"Verify\",\n    \"variant\": \"primary\"\n  }\n]",
            "name": "otp-form"
          },
          {
            "description": "OTP verification card with 6-digit code input, resend link, and a primary verify button in the footer. Richer than otp-form: includes resend affordance and card footer.",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"Card\",\n    \"children\": [\n      \"hdr\",\n      \"sec\",\n      \"ftr\"\n    ]\n  },\n  {\n    \"id\": \"hdr\",\n    \"component\": \"Header\",\n    \"children\": [\n      \"title\",\n      \"desc\"\n    ]\n  },\n  {\n    \"id\": \"title\",\n    \"component\": \"Text\",\n    \"slot\": \"heading\",\n    \"variant\": \"section\",\n    \"textContent\": \"Verify Your Identity\"\n  },\n  {\n    \"id\": \"desc\",\n    \"component\": \"Text\",\n    \"slot\": \"description\",\n    \"variant\": \"caption\",\n    \"textContent\": \"Enter the 6-digit code sent to your device\"\n  },\n  {\n    \"id\": \"sec\",\n    \"component\": \"Section\",\n    \"children\": [\n      \"col\"\n    ]\n  },\n  {\n    \"id\": \"col\",\n    \"component\": \"Column\",\n    \"gap\": \"4\",\n    \"align\": \"center\",\n    \"children\": [\n      \"otp\",\n      \"resend-row\"\n    ]\n  },\n  {\n    \"id\": \"otp\",\n    \"component\": \"OtpInput\",\n    \"length\": 6,\n    \"name\": \"otp-code\"\n  },\n  {\n    \"id\": \"resend-row\",\n    \"component\": \"Row\",\n    \"gap\": \"1\",\n    \"align\": \"center\",\n    \"children\": [\n      \"resend-label\",\n      \"resend-btn\"\n    ]\n  },\n  {\n    \"id\": \"resend-label\",\n    \"component\": \"Text\",\n    \"variant\": \"caption\",\n    \"color\": \"muted\",\n    \"textContent\": \"Didn't receive a code?\"\n  },\n  {\n    \"id\": \"resend-btn\",\n    \"component\": \"Button\",\n    \"text\": \"Resend\",\n    \"variant\": \"ghost\",\n    \"size\": \"sm\"\n  },\n  {\n    \"id\": \"ftr\",\n    \"component\": \"Footer\",\n    \"children\": [\n      \"verify-btn\"\n    ]\n  },\n  {\n    \"id\": \"verify-btn\",\n    \"component\": \"Button\",\n    \"text\": \"Verify\",\n    \"variant\": \"primary\",\n    \"block\": true\n  }\n]",
            "name": "otp-verification"
          }
        ],
        "keywords": [
          "otpinput",
          "otp-input",
          "otp",
          "input"
        ],
        "name": "UIOtpInput",
        "related": [
          "button"
        ],
        "slots": {
          "field": {
            "description": "Container for the digit input boxes and optional separator"
          }
        },
        "states": [
          {
            "description": "Default, ready for interaction.",
            "name": "idle"
          },
          {
            "description": "Non-interactive; dimmed.",
            "attribute": "disabled",
            "name": "disabled"
          }
        ],
        "status": "stable",
        "synonyms": {
          "tags": [
            "OTP"
          ]
        },
        "tag": "otp-input-ui",
        "tokens": {},
        "traits": [],
        "version": 1
      }
    },
    "Page": {
      "title": "Page",
      "description": "Page container. Holds page-level chrome — header / content / footer —\nand manages max-width clamps, padding scale, optional scroll-container,\nand an optional sticky-header sentinel. Compose with the slot\nprimitives (`<header-ui>`, `<section-ui>`, `<footer-ui>`); the page's\n@scope rules style them. Drop in directly, or nest inside an\n`<admin-shell>`'s main column.\n",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "component": {
          "const": "Page"
        },
        "maxWidth": {
          "description": "Token-bound max-width clamp. `prose` (65ch) for reading pages,\n`narrow` (80ch) for tight forms, `wide` (1080px) for data-rich\npages, `full` for unconstrained. Empty defers to parent / 100%.\nCentered horizontally via `margin-inline: auto`.\n",
          "type": "string",
          "enum": [
            "",
            "prose",
            "narrow",
            "wide",
            "full"
          ],
          "default": ""
        },
        "padding": {
          "description": "Page-padding scale from the spacing system. Accepts `0`–`8`\n(mapped to `--a-space-N`). Empty (no value) applies the\n`--page-padding` token; `0` removes padding.\n",
          "type": "string",
          "default": ""
        },
        "scroll": {
          "description": "Sets the page as a scroll container. `overflow-y: auto`, full\nheight, contained overscroll. Use when the page IS the scroll\nsurface (standalone pages); leave off when nested inside a parent\nthat already manages scroll (e.g. inside an `<admin-shell>`'s\nmain `<section>`).\n",
          "type": "boolean",
          "default": false
        },
        "stickyHeader": {
          "description": "Installs an IntersectionObserver sentinel before the first\n`<header>` / `<header-ui>` child. When the sentinel scrolls out\nof view the page gains `[data-header-stuck]`, which the CSS\nuses to add a border + shadow to the header. No-op when no\nheader is present.\n",
          "type": "boolean",
          "default": false
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [],
        "category": "container",
        "composes": [],
        "events": {},
        "examples": [
          {
            "description": "Reading page with sticky header, 65ch column, padding scale 6.",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"Page\",\n    \"stickyHeader\": true,\n    \"maxWidth\": \"prose\",\n    \"padding\": \"6\",\n    \"children\": [\"hdr\", \"body\"]\n  },\n  {\n    \"id\": \"hdr\",\n    \"component\": \"Header\",\n    \"children\": [\"title\"]\n  },\n  {\n    \"id\": \"title\",\n    \"component\": \"Text\",\n    \"variant\": \"display\",\n    \"textContent\": \"Reading Page\"\n  },\n  {\n    \"id\": \"body\",\n    \"component\": \"Section\",\n    \"children\": []\n  }\n]",
            "name": "prose-page"
          },
          {
            "description": "Wide-clamp dashboard page acting as a scroll container.",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"Page\",\n    \"scroll\": true,\n    \"maxWidth\": \"wide\",\n    \"padding\": \"4\",\n    \"children\": [\"hdr\", \"body\"]\n  },\n  {\n    \"id\": \"hdr\",\n    \"component\": \"Header\",\n    \"children\": []\n  },\n  {\n    \"id\": \"body\",\n    \"component\": \"Section\",\n    \"children\": []\n  }\n]",
            "name": "dashboard-page"
          }
        ],
        "keywords": [
          "page",
          "layout",
          "container",
          "scroll",
          "sticky-header",
          "max-width",
          "padding",
          "prose-page",
          "dashboard-page"
        ],
        "name": "UIPage",
        "related": [
          "app-shell",
          "card",
          "section",
          "header",
          "footer"
        ],
        "slots": {
          "default": {
            "description": "Composes from the slot primitives — `<header-ui>` (page header),\n`<section-ui>` (main content), optional `<footer-ui>`. Native\n`<header>` / `<section>` / `<footer>` also work; the @scope rules\ntarget both via `:where(header, header-ui)`.\n"
          }
        },
        "states": [
          {
            "description": "Default, ready for interaction.",
            "name": "idle"
          },
          {
            "description": "Header has scrolled past the sentinel; visual cue applied.",
            "name": "header-stuck"
          }
        ],
        "status": "stable",
        "synonyms": {
          "page": [
            "page-container",
            "route-surface",
            "content-surface"
          ]
        },
        "tag": "page-ui",
        "tokens": {},
        "traits": [],
        "version": 1
      }
    },
    "Pagination": {
      "title": "Pagination",
      "description": "Page navigation with prev/next buttons, page numbers, and ellipsis. Emits page-change events when buttons are clicked; visible page-number range is automatically truncated for high page counts. Use below tables, card grids, or list views; for cursor-based pagination use a custom load-more <button-ui> instead.",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "component": {
          "const": "Pagination"
        },
        "page": {
          "description": "Current active page number.",
          "type": "number",
          "default": 1
        },
        "siblings": {
          "description": "Number of page buttons to show on each side of the current page.",
          "type": "number",
          "default": 1
        },
        "size": {
          "description": "Universal size — threads through to every nested `<button-ui size=…>`\nso pagination honors the substrate's 24/30/36 px size system\n(with [density] modifier). Default `md` matches `<button-ui>`'s\ndefault; pass `size=\"sm\"` for a denser numbered row.\n",
          "type": "string",
          "enum": [
            "sm",
            "md",
            "lg"
          ],
          "default": "md"
        },
        "total": {
          "description": "Total number of pages.",
          "type": "number",
          "default": 1
        },
        "variant": {
          "description": "Visual variant — `default` (ghost buttons w/ hover bg) or `button` (1×1 bordered cells; active page filled).",
          "type": "string",
          "enum": [
            "default",
            "button"
          ],
          "default": "default"
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [],
        "category": "navigation",
        "composes": [
          "button-ui",
          "icon-ui"
        ],
        "events": {
          "page-change": {
            "description": "Fired when a page button is clicked. detail contains { page }.",
            "detail": {
              "page": {
                "description": "New page number.",
                "type": "number"
              }
            }
          }
        },
        "examples": [
          {
            "description": "Card with header containing title and search input, table component, and pagination footer.",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"Card\",\n    \"size\": \"lg\",\n    \"children\": [\n      \"hdr\",\n      \"sec\",\n      \"ftr\"\n    ]\n  },\n  {\n    \"id\": \"hdr\",\n    \"component\": \"Header\",\n    \"children\": [\n      \"title-row\"\n    ]\n  },\n  {\n    \"id\": \"title-row\",\n    \"component\": \"Row\",\n    \"children\": [\n      \"title\",\n      \"search\"\n    ],\n    \"gap\": \"4\"\n  },\n  {\n    \"id\": \"title\",\n    \"component\": \"Text\",\n    \"slot\": \"heading\",\n    \"textContent\": \"Data Table\",\n    \"variant\": \"section\"\n  },\n  {\n    \"id\": \"search\",\n    \"component\": \"Input\",\n    \"placeholder\": \"Search...\",\n    \"type\": \"search\",\n    \"name\": \"search\"\n  },\n  {\n    \"id\": \"sec\",\n    \"component\": \"Section\",\n    \"children\": [\n      \"tbl\"\n    ]\n  },\n  {\n    \"id\": \"tbl\",\n    \"component\": \"Table\",\n    \"sortable\": true\n  },\n  {\n    \"id\": \"ftr\",\n    \"component\": \"Footer\",\n    \"children\": [\n      \"pager\"\n    ]\n  },\n  {\n    \"id\": \"pager\",\n    \"component\": \"Pagination\",\n    \"total\": 10,\n    \"page\": 1\n  }\n]",
            "name": "data-table-view"
          },
          {
            "description": "Row with centered pagination component for navigating paged content.",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"Row\",\n    \"justify\": \"center\",\n    \"children\": [\n      \"pager\"\n    ]\n  },\n  {\n    \"id\": \"pager\",\n    \"component\": \"Pagination\",\n    \"total\": 10,\n    \"page\": 1\n  }\n]",
            "name": "pagination-nav"
          }
        ],
        "keywords": [
          "pagination",
          "navigation",
          "back",
          "paginate",
          "paging"
        ],
        "name": "UIPagination",
        "related": [
          "input",
          "table"
        ],
        "slots": {},
        "states": [
          {
            "description": "Default, ready for interaction.",
            "name": "idle"
          }
        ],
        "status": "stable",
        "synonyms": {
          "back": [
            "breadcrumb",
            "nav",
            "pagination"
          ],
          "navigation": [
            "nav",
            "sidebar",
            "breadcrumb",
            "tabs",
            "menu",
            "pagination"
          ],
          "paginate": [
            "pagination",
            "nav",
            "table"
          ],
          "paging": [
            "pagination",
            "nav"
          ]
        },
        "tag": "pagination-ui",
        "tokens": {},
        "traits": [],
        "version": 1
      }
    },
    "Pane": {
      "title": "Pane",
      "description": "Collapsible, resizable content panel — drag-resize handle on the\ninner edge when [side=\"leading\"] / [side=\"trailing\"], [resizable]\nopt-in. Used standalone for resizable two-pane layouts, or wrapped\nby <editor-sidebar> / <admin-sidebar> which DELEGATE drag to the\ninner pane-ui rather than reimplementing it. See pane.yaml's\na2ui.rules for the full composition contract.\n",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "collapsed": {
          "description": "Component property: collapsed.",
          "type": "boolean",
          "default": false
        },
        "component": {
          "const": "Pane"
        },
        "maxWidth": {
          "description": "Component property: maxWidth.",
          "type": "number",
          "default": 9999
        },
        "minWidth": {
          "description": "Component property: minWidth.",
          "type": "number",
          "default": 200
        },
        "resizable": {
          "description": "Component property: resizable.",
          "type": "boolean",
          "default": false
        },
        "side": {
          "description": "Opts a pane into horizontal-sibling chrome: suppresses the default\nfour-sided border and moves the resize grabber to the inner edge\n(right edge for `leading`, left edge for `trailing`). Also flips the\nresize-drag direction so `trailing` panes grow when dragged leftward.\nUnset keeps the pane-intrinsic chrome (full border, right-edge\ngrabber when resizable).\n",
          "type": "string",
          "enum": [
            "",
            "leading",
            "trailing"
          ],
          "default": ""
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [],
        "category": "layout",
        "composes": [
          "icon-ui"
        ],
        "events": {
          "toggle": {
            "description": "Fired when the pane's collapsed state flips (via button press, keyboard, or programmatic toggle()). Bubbles."
          }
        },
        "examples": [
          {
            "description": "Split pane with TextArea for editing markdown on the left and a preview card on the right.",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"Row\",\n    \"children\": [\n      \"left\",\n      \"right\"\n    ]\n  },\n  {\n    \"id\": \"left\",\n    \"component\": \"Pane\",\n    \"resizable\": true,\n    \"width\": \"50%\",\n    \"children\": [\n      \"editor-card\"\n    ]\n  },\n  {\n    \"id\": \"editor-card\",\n    \"component\": \"Card\",\n    \"children\": [\n      \"ed-hdr\",\n      \"ed-sec\"\n    ]\n  },\n  {\n    \"id\": \"ed-hdr\",\n    \"component\": \"Header\",\n    \"children\": [\n      \"ed-title\"\n    ]\n  },\n  {\n    \"id\": \"ed-title\",\n    \"component\": \"Text\",\n    \"slot\": \"heading\",\n    \"textContent\": \"Editor\"\n  },\n  {\n    \"id\": \"ed-sec\",\n    \"component\": \"Section\",\n    \"children\": [\n      \"textarea\"\n    ]\n  },\n  {\n    \"id\": \"textarea\",\n    \"component\": \"TextArea\",\n    \"placeholder\": \"Write your markdown here...\",\n    \"rows\": 20\n  },\n  {\n    \"id\": \"right\",\n    \"component\": \"Pane\",\n    \"resizable\": true,\n    \"width\": \"50%\",\n    \"children\": [\n      \"preview-card\"\n    ]\n  },\n  {\n    \"id\": \"preview-card\",\n    \"component\": \"Card\",\n    \"children\": [\n      \"pv-hdr\",\n      \"pv-sec\"\n    ]\n  },\n  {\n    \"id\": \"pv-hdr\",\n    \"component\": \"Header\",\n    \"children\": [\n      \"pv-title\"\n    ]\n  },\n  {\n    \"id\": \"pv-title\",\n    \"component\": \"Text\",\n    \"slot\": \"heading\",\n    \"textContent\": \"Preview\"\n  },\n  {\n    \"id\": \"pv-sec\",\n    \"component\": \"Section\",\n    \"children\": [\n      \"preview-text\"\n    ]\n  },\n  {\n    \"id\": \"preview-text\",\n    \"component\": \"Text\",\n    \"variant\": \"body\",\n    \"textContent\": \"Rendered markdown will appear here...\"\n  }\n]",
            "name": "markdown-editor"
          },
          {
            "description": "Row with two resizable Pane components for left/right panel layout.",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"Row\",\n    \"children\": [\n      \"left\",\n      \"right\"\n    ]\n  },\n  {\n    \"id\": \"left\",\n    \"component\": \"Pane\",\n    \"resizable\": true,\n    \"width\": \"50%\",\n    \"children\": [\n      \"ltxt\"\n    ]\n  },\n  {\n    \"id\": \"ltxt\",\n    \"component\": \"Text\",\n    \"variant\": \"body\",\n    \"textContent\": \"Left panel content\"\n  },\n  {\n    \"id\": \"right\",\n    \"component\": \"Pane\",\n    \"resizable\": true,\n    \"width\": \"50%\",\n    \"children\": [\n      \"rtxt\"\n    ]\n  },\n  {\n    \"id\": \"rtxt\",\n    \"component\": \"Text\",\n    \"variant\": \"body\",\n    \"textContent\": \"Right panel content\"\n  }\n]",
            "name": "split-pane"
          }
        ],
        "keywords": [
          "pane"
        ],
        "name": "UIPane",
        "related": [
          "text-area"
        ],
        "slots": {
          "caret": {
            "description": "Collapse caret inside the header. Auto-stamped as `<icon-ui slot=\"caret\" name=\"caret-right\">` (rotates on `[collapsed]`). Supply your own `slot=\"caret\"` child in the header to customize — adopt-or-stamp honors a declarative caret instead of stamping."
          },
          "header": {
            "description": "Auto-created header element with label text and toggle arrow"
          }
        },
        "states": [
          {
            "description": "Default, ready for interaction.",
            "name": "idle"
          }
        ],
        "status": "stable",
        "synonyms": {
          "tags": [
            "split-pane",
            "side-panel",
            "resizable-panel",
            "detail-pane",
            "list-pane",
            "context-pane",
            "Panel",
            "Pane"
          ]
        },
        "tag": "pane-ui",
        "tokens": {},
        "traits": [],
        "version": 1
      }
    },
    "PasswordStrength": {
      "title": "PasswordStrength",
      "description": "Visual strength indicator for password inputs — 4-segment bar (weak /\nfair / good / strong) computed from a heuristic combining length,\ncharacter-class diversity, and repeat-pattern penalty. Pairs with\n`<input-ui type=\"password\">` via JS:\n  input.addEventListener('input', e => meter.value = e.target.value)\nRead-only display primitive — no form participation. Emits a\n`score-change` event when the bucket changes so consumers can gate\na submit button on `detail.satisfied` (score ≥ min-score).\n\n**Security note:** [value] is held as a JS property only, NOT\nreflected to a DOM attribute. The element stamps the bar + label\nfrom the property; the password never appears in the rendered HTML.\nDo not set the value via setAttribute (it will be no-op).\n",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "component": {
          "const": "PasswordStrength"
        },
        "minScore": {
          "description": "Minimum acceptable score (0–3). The `score-change` event's\n`detail.satisfied` boolean reflects whether the current score\nmeets this threshold. Useful for gating a submit button.\n",
          "type": "number",
          "default": 2
        },
        "showLabel": {
          "description": "Display the textual score label (\"Weak\" / \"Fair\" / \"Good\" /\n\"Strong\") below the bar. Defaults to true.\n",
          "type": "boolean",
          "default": true
        },
        "value": {
          "description": "The password string to score. JS-property only — NOT reflected\nto a DOM attribute (so the password never leaks into rendered\nHTML). Wire to an input via `input.addEventListener('input', e =>\nmeter.value = e.target.value)`.\n",
          "$ref": "#/$defs/DynamicString"
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [
          {
            "fix": "<password-strength-ui id=\"m\"></password-strength-ui>\n<script>document.getElementById('m').value = pwd;</script>\n",
            "why": "`value` is JS-property only; the attribute is ignored. The\npassword also shouldn't be authored into HTML at all (server\ntemplate / static page) — that defeats the purpose.\n",
            "wrong": "<password-strength-ui value=\"hunter2\"></password-strength-ui>\n"
          }
        ],
        "category": "display",
        "composes": [],
        "events": {
          "score-change": {
            "description": "Fired when the computed score crosses a bucket boundary (not on every keystroke). Detail carries the new score + label + satisfied flag.",
            "detail": {
              "label": "string",
              "satisfied": "boolean",
              "score": "number"
            }
          }
        },
        "examples": [
          {
            "description": "Standard pairing with input-ui[type=password] via input listener.",
            "a2ui": "[\n  {\n    \"id\": \"field\",\n    \"component\": \"Field\",\n    \"label\": \"Password\",\n    \"children\": [\"pwd\", \"meter\"]\n  },\n  {\n    \"id\": \"pwd\",\n    \"component\": \"Input\",\n    \"type\": \"password\",\n    \"name\": \"password\"\n  },\n  {\n    \"id\": \"meter\",\n    \"component\": \"PasswordStrength\"\n  }\n]\n",
            "name": "paired-with-input"
          }
        ],
        "keywords": [
          "password-strength",
          "strength-meter",
          "password",
          "strength",
          "meter",
          "security"
        ],
        "name": "UIPasswordStrength",
        "related": [
          "input",
          "field",
          "progress"
        ],
        "slots": {
          "default": {
            "description": "Optional area for requirements checklist content (e.g. <ul> of \"at least 8 characters\", \"mixed case\", etc.)."
          }
        },
        "states": [
          {
            "description": "Default — no value set, all segments grey.",
            "name": "idle"
          },
          {
            "description": "Value present; segments lit per score 0..3.",
            "attribute": "data-score",
            "name": "scored"
          }
        ],
        "status": "stable",
        "synonyms": {
          "password": [
            "password-strength",
            "strength-meter"
          ],
          "strength": [
            "password-strength",
            "meter"
          ]
        },
        "tag": "password-strength-ui",
        "tokens": {
          "--password-strength-color-fair": {
            "description": "Color for score=1 lit segments.",
            "default": "var(--a-warning-bg)"
          },
          "--password-strength-color-good": {
            "description": "Color for score=2 lit segments.",
            "default": "var(--a-info-bg)"
          },
          "--password-strength-color-strong": {
            "description": "Color for score=3 lit segments.",
            "default": "var(--a-success-bg)"
          },
          "--password-strength-color-weak": {
            "description": "Color for score=0 lit segments.",
            "default": "var(--a-danger-bg)"
          },
          "--password-strength-gap": {
            "description": "Gap between segments.",
            "default": "var(--a-space-1)"
          },
          "--password-strength-label-fg": {
            "description": "Label text color.",
            "default": "var(--a-fg-muted)"
          },
          "--password-strength-label-size": {
            "description": "Label font size.",
            "default": "var(--a-ui-sm)"
          },
          "--password-strength-radius": {
            "description": "Segment border radius.",
            "default": "var(--a-radius-full)"
          },
          "--password-strength-segment-bg": {
            "description": "Unlit segment background (track color).",
            "default": "var(--a-canvas-1-scrim)"
          },
          "--password-strength-segment-height": {
            "description": "Height of each bar segment.",
            "default": "4px"
          }
        },
        "traits": [],
        "version": 1
      }
    },
    "PaymentMethodForm": {
      "title": "PaymentMethodForm",
      "description": "Form-participating composite for capturing a payment method —\ncard number, expiry, CVC, name on card, billing address (optional),\nand country. The form chrome + structured validation + a single\nnormalized emit event; it does NOT integrate with Stripe Elements\nor a tokenization SDK directly (consumer responsibility).\n\nEach sub-field is a <field-ui> wrapper around an <input-ui> (or\n<select-ui> for country). Card number is Luhn-validated; expiry is\nparsed as MM/YY with month + year bounds; CVC is 3-4 digits.\nBrand detection (visa / mastercard / amex / discover) runs against\na small regex map and surfaces via the `change` event detail.\n\nForm value is a JSON-encoded payload of normalized field values\nserialized through ElementInternals under [name] (default\n\"paymentMethod\"). On submit, the host fires\n`submit-payment-method` with a flat detail\n`{ token, last4, brand, expMonth, expYear, name, country }`.\n`token` is a synthetic local-mode token (sha-like opaque string);\nconsumers integrating with a real processor handle tokenization\nin their own submit listener using `last4` / `brand` / etc.\n\nSpec: docs/specs/implementation-ready/SPEC-009-payment-method-form.md.\n",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "required": {
          "description": "Form-validation gate. When set, an empty composite fails\ncheckValidity() with \"Payment method required.\".\n",
          "type": "boolean",
          "default": false
        },
        "autofocus": {
          "description": "When set, the first sub-field (Name on card) receives focus on\nfirst connect. Convention parity with native form elements.\n",
          "type": "boolean",
          "default": false
        },
        "component": {
          "const": "PaymentMethodForm"
        },
        "countries": {
          "description": "Allowed billing countries, ISO 3166-1 alpha-2 codes. Drives\nthe <select-ui> dropdown's options. Empty array uses a\ndefault short list (US, CA, GB, DE, FR, AU).\n",
          "$ref": "#/$defs/DynamicStringList"
        },
        "default-country": {
          "description": "Default selected country (ISO 3166-1 alpha-2). Falls back to\nthe first entry in `countries` (or \"US\" when empty).\n",
          "type": "string",
          "default": "US"
        },
        "disabled": {
          "description": "Forwarded to every sub-control. Pointer-events:none on the\ncomposite host as a belt-and-suspenders.\n",
          "$ref": "#/$defs/DynamicBoolean"
        },
        "error": {
          "description": "Externally-set error message (e.g. server-rejected card). When\nnon-empty, the composite renders an <alert-ui variant=\"danger\">\nat the top of the form and sets aria-invalid=true on the host.\n",
          "$ref": "#/$defs/DynamicString"
        },
        "name": {
          "description": "Form field name. The composite's serialized form value lives\nunder this key in any wrapping <form>. Defaults to\n\"paymentMethod\".\n",
          "type": "string",
          "default": "paymentMethod"
        },
        "prefill": {
          "description": "JSON-encoded prefill payload `{last4, brand, expMonth, expYear,\nname, country}`. When set, the summary row renders with the\nsaved-card chrome and the rest of the form is hidden behind an\n\"Edit card\" button. Useful for \"update saved payment method\"\nflows.\n",
          "type": "string",
          "default": ""
        },
        "require-billing-address": {
          "description": "When set, renders the billing-address sub-fields (address line\n1, optional line 2, postal code). When unset, only postal code\n+ country are collected for the address-verification check.\n",
          "type": "boolean",
          "default": false
        },
        "value": {
          "description": "Resolved payment-method token. Read-only externally — the\ncomposite writes it after a successful tokenize() call. Setting\nthis to a non-empty string is treated as \"prefilled from a\nsaved payment method\" and renders the form in\nread-only-summary mode (last4 + brand + expiry shown).\n",
          "$ref": "#/$defs/DynamicString"
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [
          {
            "fix": "<payment-method-form-ui name=\"paymentMethod\" required></payment-method-form-ui>\n",
            "why": "Raw card digits in `value`. The composite's value is the\ntokenized output, never the input. Raw digits leak through\nreflection back to the attribute and end up in DOM snapshots /\nbrowser history / analytics.\n",
            "wrong": "<payment-method-form-ui value=\"4242 4242 4242 4242\"></payment-method-form-ui>\n"
          },
          {
            "fix": "<payment-method-form-ui aria-label=\"Card details\"></payment-method-form-ui>\n",
            "why": "PaymentMethodForm IS itself a labeled field group; nesting in\nField duplicates the label and breaks the internal grid\nlayout. Field's auto-id stamping confuses the composite's\nfirst-focusable lookup.\n",
            "wrong": "<field-ui label=\"Card details\">\n  <payment-method-form-ui></payment-method-form-ui>\n</field-ui>\n"
          },
          {
            "fix": "<form>\n  <payment-method-form-ui id=\"pm\"></payment-method-form-ui>\n  <button-ui type=\"submit\" text=\"Save\"></button-ui>\n</form>\n<script>\n  form.addEventListener('submit', async (e) => {\n    e.preventDefault();\n    const detail = await pm.tokenize();\n    // Hand `detail.last4` / `detail.brand` to your processor SDK\n    // to mint a real token; POST the resulting token to /charge.\n  });\n</script>\n",
            "why": "Posting the form's serialized token directly to /charge skips\ntokenization — the synthetic local-mode token is opaque but\nNOT a real payment token. A real processor must mint the\ntoken before the charge call.\n",
            "wrong": "<form>\n  <payment-method-form-ui></payment-method-form-ui>\n  <button-ui type=\"submit\" text=\"Save\"></button-ui>\n</form>\n<script>\n  form.addEventListener('submit', (e) => fetch('/charge', { body: new FormData(form) }));\n</script>\n"
          }
        ],
        "category": "input",
        "composes": [
          "field-ui",
          "input-ui",
          "select-ui",
          "alert-ui",
          "icon-ui",
          "button-ui"
        ],
        "events": {
          "change": {
            "description": "Fired on every sub-field input. Detail carries a snapshot of\nthe current form validity + detected card brand. Bubbles.\n",
            "detail": {
              "brand": {
                "description": "Detected brand (`visa` / `mastercard` / `amex` / `discover` / `unknown`).",
                "type": "string"
              },
              "valid": {
                "description": "Whether the form currently passes all constraints.",
                "type": "boolean"
              }
            }
          },
          "payment-method-error": {
            "description": "Fired when tokenize() fails — either constraint validation\nsurfaced one or more field errors, or a Luhn / expiry / CVC\ncheck failed. Bubbles.\n",
            "detail": {
              "code": {
                "description": "Error code — one of `validation-failed`, `card-invalid`, `expired`, `cvc-invalid`.",
                "type": "string"
              },
              "field": {
                "description": "Field name that surfaced the error (`cardNumber` / `expiry` / `cvc` / `name` / `postalCode` / `country` / null).",
                "type": "string"
              },
              "message": {
                "description": "Human-readable error message.",
                "type": "string"
              }
            }
          },
          "submit-payment-method": {
            "description": "Fired when tokenize() resolves — either via an outer <form>\nsubmission or an explicit tokenize() call. Detail carries the\nnormalized payload that downstream code POSTs to the billing\nservice. Bubbles.\n",
            "detail": {
              "brand": {
                "description": "Detected brand — `visa`, `mastercard`, `amex`, `discover`, or `unknown`.",
                "type": "string"
              },
              "country": {
                "description": "ISO 3166-1 alpha-2 billing country.",
                "type": "string"
              },
              "expMonth": {
                "description": "Expiry month (1-12).",
                "type": "integer"
              },
              "expYear": {
                "description": "Expiry year (4-digit).",
                "type": "integer"
              },
              "last4": {
                "description": "Last 4 digits of the card number.",
                "type": "string"
              },
              "name": {
                "description": "Name on card.",
                "type": "string"
              },
              "token": {
                "description": "Synthetic local-mode token (sha-like opaque string).",
                "type": "string"
              }
            }
          }
        },
        "examples": [
          {
            "description": "Empty form, all sub-fields visible, required.",
            "a2ui": "[\n  {\n    \"id\": \"pm-1\",\n    \"component\": \"PaymentMethodForm\",\n    \"name\": \"paymentMethod\",\n    \"required\": true\n  }\n]\n",
            "name": "default"
          },
          {
            "description": "Edit-saved-card flow — summary row renders with the saved\ncard; \"Edit card\" CTA reveals the full form.\n",
            "a2ui": "[\n  {\n    \"id\": \"pm-2\",\n    \"component\": \"PaymentMethodForm\",\n    \"name\": \"paymentMethod\",\n    \"prefill\": \"{\\\"last4\\\":\\\"4242\\\",\\\"brand\\\":\\\"visa\\\",\\\"expMonth\\\":12,\\\"expYear\\\":2027,\\\"name\\\":\\\"Pat Doe\\\",\\\"country\\\":\\\"US\\\"}\"\n  }\n]\n",
            "name": "prefilled-saved-card"
          },
          {
            "description": "Full form including billing address lines + postal + country.\n",
            "a2ui": "[\n  {\n    \"id\": \"pm-3\",\n    \"component\": \"PaymentMethodForm\",\n    \"name\": \"paymentMethod\",\n    \"requireBillingAddress\": true,\n    \"countries\": [\"US\", \"CA\", \"GB\", \"DE\"]\n  }\n]\n",
            "name": "with-billing-address"
          }
        ],
        "keywords": [
          "payment-method",
          "card",
          "billing",
          "checkout",
          "card-capture",
          "payment",
          "credit-card",
          "debit-card",
          "save-payment-method",
          "update-payment-method",
          "add-card"
        ],
        "name": "UIPaymentMethodForm",
        "related": [
          "Form",
          "Field",
          "Input",
          "Select",
          "Alert",
          "PlanPicker",
          "Button"
        ],
        "slots": {
          "legal": {
            "description": "Optional content rendered below the form fields — typically a\nterms-of-storage acknowledgement string with link(s).\n"
          }
        },
        "states": [
          {
            "description": "Default; ready for input.",
            "name": "idle"
          },
          {
            "description": "tokenize() in flight.",
            "attribute": "tokenizing",
            "name": "tokenizing"
          },
          {
            "description": "A field-level or host-level error is present.",
            "attribute": "error",
            "name": "error"
          },
          {
            "description": "A saved payment method is displayed; form is hidden.",
            "attribute": "prefilled",
            "name": "prefilled"
          },
          {
            "description": "All sub-fields non-interactive.",
            "attribute": "disabled",
            "name": "disabled"
          }
        ],
        "status": "experimental",
        "synonyms": {
          "billing": [
            "billing-info",
            "payment-method",
            "card"
          ],
          "card": [
            "payment-card",
            "credit-card",
            "debit-card"
          ],
          "payment-method": [
            "card",
            "card-on-file",
            "billing"
          ]
        },
        "tag": "payment-method-form-ui",
        "tokens": {
          "--payment-method-form-alert-mb": {
            "description": "Margin-block-end on the host-level error alert.",
            "default": "var(--a-space-3)"
          },
          "--payment-method-form-brand-icon-size": {
            "description": "Inline brand-badge icon size in the card-number suffix.",
            "default": "1.25em"
          },
          "--payment-method-form-disabled-opacity": {
            "description": "Opacity applied to the host when [disabled].",
            "default": "var(--a-opacity-disabled, 0.5)"
          },
          "--payment-method-form-gap": {
            "description": "Gap between rows of the form grid.",
            "default": "var(--a-space-3)"
          },
          "--payment-method-form-grid-template": {
            "description": "Grid-template-areas for the field layout. Defaults to a\n4-row template — name spans both columns, card number spans\nboth, expiry + cvc share row 3, country + postal share row 4.\nAddress rows append when `require-billing-address` is set.\n",
            "default": "\"name name\" \"card card\" \"expiry cvc\" \"country postal\""
          },
          "--payment-method-form-legal-fg": {
            "description": "Foreground color of the slotted legal copy.",
            "default": "var(--a-fg-muted)"
          },
          "--payment-method-form-legal-size": {
            "description": "Font size of the slotted legal copy.",
            "default": "var(--a-text-xs, 0.75rem)"
          },
          "--payment-method-form-summary-bg": {
            "description": "Background of the saved-card summary row.",
            "default": "var(--a-bg-muted)"
          },
          "--payment-method-form-summary-border": {
            "description": "Border on the saved-card summary row.",
            "default": "1px solid var(--a-border)"
          },
          "--payment-method-form-summary-px": {
            "description": "Horizontal padding inside the saved-card summary row.",
            "default": "var(--a-space-4)"
          },
          "--payment-method-form-summary-py": {
            "description": "Vertical padding inside the saved-card summary row.",
            "default": "var(--a-space-3)"
          },
          "--payment-method-form-summary-radius": {
            "description": "Corner radius on the saved-card summary row.",
            "default": "var(--a-radius-md)"
          }
        },
        "traits": [],
        "version": 1
      }
    },
    "PaymentMethodList": {
      "title": "PaymentMethodList",
      "description": "Compound billing primitive that renders the user's saved payment\nmethods (cards, bank accounts, wallets) as a vertical list with one\nrow designated as the default. Each row shows a brand mark, the\nlast-4 / account identifier, an optional expiry, and per-row actions\n(set-default / edit / remove). A trailing \"Add payment method\" CTA\nemits `add` so consumers can route the consumer flow.\n\nDefault is a strict 1-of-N radiogroup — exactly one row carries the\ndefault state when the list is non-empty. The primitive does NOT\nmutate the data source; all changes flow as events (`change`,\n`add`, `remove`, `select`) and the consumer applies the side\neffect against their billing API.\n\nSpec: docs/specs/implementation-ready/SPEC-010-payment-method-list.md.\n",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "add-icon": {
          "description": "Phosphor icon name for the add CTA.",
          "type": "string",
          "default": "plus"
        },
        "add-label": {
          "description": "Label for the trailing add CTA.",
          "type": "string",
          "default": "Add payment method"
        },
        "component": {
          "const": "PaymentMethodList"
        },
        "disabled": {
          "description": "Block all interaction; rows remain visible.",
          "type": "boolean",
          "default": false
        },
        "methods": {
          "description": "Array of saved payment-method records. Source of truth for the\nrendered rows. Shape per record:\n{id, brand, last4?, expiry?, holder?, type, default?, status?}.\nEmpty array renders the empty-state.\n",
          "$ref": "#/$defs/DynamicStringList"
        },
        "name": {
          "description": "Form field name for the default-method id. Serialized via\nElementInternals; mirrors UIFormElement conventions.\n",
          "type": "string",
          "default": ""
        },
        "no-add": {
          "description": "Hide the trailing \"Add payment method\" CTA (read-only flow,\ncheckout drawer, etc.).\n",
          "type": "boolean",
          "default": false
        },
        "no-remove": {
          "description": "Hide per-row remove buttons.",
          "type": "boolean",
          "default": false
        },
        "value": {
          "description": "Id of the row currently marked default (the form value). When\nboth `value` and `methods[].default` are set, `value` wins and\nthe primitive emits `change` to reconcile.\n",
          "$ref": "#/$defs/DynamicString"
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [
          {
            "fix": "<payment-method-list-ui methods='[\n  {\"id\":\"pm_1\",\"default\":true},\n  {\"id\":\"pm_2\"}\n]'></payment-method-list-ui>\n",
            "why": "Two rows marked default. The primitive clears all but the first\nand emits a corrective `change` event; this is wasted round-trips.\nSource of truth should mark exactly one row.\n",
            "wrong": "<payment-method-list-ui methods='[\n  {\"id\":\"pm_1\",\"default\":true},\n  {\"id\":\"pm_2\",\"default\":true}\n]'></payment-method-list-ui>\n"
          },
          {
            "fix": "<payment-method-list-ui methods=\"...\"></payment-method-list-ui>\n",
            "why": "Reinvents 1-of-N default semantics. Drops radiogroup a11y.\nRe-derives the brand-icon dictionary per consumer.\n",
            "wrong": "A <col-ui> of bespoke <card-ui> rows with manual radio markup\nand a per-row \"make default\" button.\n"
          },
          {
            "fix": "<payment-method-list-ui methods='[{\"id\":\"pm_1\",\"brand\":\"discover\",\"type\":\"card\"}]'>\n</payment-method-list-ui>\n",
            "why": "\"discover-it\" is a card product, not a brand from the enumerated\nset. The primitive renders the generic credit-card fallback.\n",
            "wrong": "<payment-method-list-ui methods='[{\"id\":\"pm_1\",\"brand\":\"discover-it\",\"type\":\"card\"}]'>\n</payment-method-list-ui>\n"
          }
        ],
        "category": "input",
        "composes": [
          "card-ui",
          "button-ui",
          "icon-ui",
          "tag-ui",
          "text-ui",
          "empty-state-ui"
        ],
        "events": {
          "add": {
            "description": "Fired when the user activates the trailing add CTA. Consumer\nroutes to its add-method flow (drawer / modal / page). Bubbles.\n"
          },
          "change": {
            "description": "Fired when the default method changes — via row activation or\nprogrammatic value set. Bubbles.\n",
            "detail": {
              "method": {
                "description": "The full method record now marked default.",
                "type": "object"
              },
              "previous": {
                "description": "Id of the previous default (empty string when none).",
                "type": "string"
              },
              "value": {
                "description": "Id of the new default.",
                "type": "string"
              }
            }
          },
          "remove": {
            "description": "Fired when the user activates a row's remove affordance. Consumer\nremoves the method on its end and writes back via `.remove(id)`\nor by mutating `methods`. Bubbles.\n",
            "detail": {
              "id": {
                "description": "Method id targeted for removal.",
                "type": "string"
              },
              "method": {
                "description": "The full method record.",
                "type": "object"
              }
            }
          },
          "select": {
            "description": "Fired when the user activates a row without changing the default\n(e.g. an \"Edit\" action). Bubbles.\n",
            "detail": {
              "id": {
                "description": "Method id.",
                "type": "string"
              },
              "method": {
                "description": "The full method record.",
                "type": "object"
              }
            }
          }
        },
        "examples": [
          {
            "description": "Saved payment methods in a billing settings panel.",
            "a2ui": "[\n  {\n    \"id\": \"pml-settings\",\n    \"component\": \"PaymentMethodList\",\n    \"name\": \"default-method\",\n    \"value\": \"pm_1\",\n    \"methods\": [\n      {\"id\":\"pm_1\",\"brand\":\"visa\",\"last4\":\"4242\",\"expiry\":\"2027-05-01\",\"holder\":\"Ada Lovelace\",\"type\":\"card\",\"default\":true},\n      {\"id\":\"pm_2\",\"brand\":\"mastercard\",\"last4\":\"0009\",\"expiry\":\"2026-06-01\",\"holder\":\"Ada Lovelace\",\"type\":\"card\"},\n      {\"id\":\"pm_3\",\"brand\":\"ach\",\"last4\":\"6789\",\"holder\":\"Chase ••6789\",\"type\":\"bank\"}\n    ]\n  }\n]\n",
            "name": "settings-list"
          },
          {
            "description": "Checkout-drawer picker — no add CTA; read-only-ish.",
            "a2ui": "[\n  {\n    \"id\": \"pml-checkout\",\n    \"component\": \"PaymentMethodList\",\n    \"name\": \"checkout-method\",\n    \"noAdd\": true,\n    \"methods\": [\n      {\"id\":\"pm_1\",\"brand\":\"visa\",\"last4\":\"4242\",\"expiry\":\"2027-05-01\",\"type\":\"card\",\"default\":true},\n      {\"id\":\"pm_2\",\"brand\":\"mastercard\",\"last4\":\"0009\",\"expiry\":\"2026-06-01\",\"type\":\"card\"}\n    ]\n  }\n]\n",
            "name": "checkout-drawer"
          }
        ],
        "keywords": [
          "payment-method",
          "payment-methods",
          "saved-cards",
          "billing",
          "cards",
          "payment-card",
          "credit-card",
          "default-card",
          "wallet",
          "bank-account",
          "ach",
          "method-list"
        ],
        "name": "PaymentMethodList",
        "related": [
          "PlanPicker",
          "Card",
          "Button",
          "Tag",
          "Icon",
          "EmptyState"
        ],
        "slots": {
          "add": {
            "description": "Custom add-CTA replacement. When absent the primitive stamps a\ndefault `<button-ui variant=\"outline\" icon=\"plus\">`. Hidden\nentirely when `[no-add]` is set.\n"
          },
          "empty": {
            "description": "Custom empty-state shown when `methods` is empty. Falls back to a\ndefault <empty-state-ui icon=\"credit-card\"> when omitted.\n"
          }
        },
        "states": [
          {
            "description": "Default — rows rendered, ready for interaction.",
            "name": "idle"
          },
          {
            "description": "No methods to render.",
            "attribute": "empty",
            "name": "empty"
          },
          {
            "description": "All rows non-interactive.",
            "attribute": "disabled",
            "name": "disabled"
          }
        ],
        "status": "experimental",
        "synonyms": {
          "card": [
            "credit-card",
            "debit-card",
            "payment-method"
          ],
          "payment": [
            "billing",
            "charge"
          ],
          "saved": [
            "stored"
          ]
        },
        "tag": "payment-method-list-ui",
        "tokens": {
          "--payment-method-list-add-justify": {
            "description": "Justification of the trailing add CTA row.",
            "default": "flex-start"
          },
          "--payment-method-list-bg": {
            "description": "Host background. Defaults to transparent.",
            "default": "transparent"
          },
          "--payment-method-list-brand-frame": {
            "description": "Brand-mark frame background.",
            "default": "var(--a-bg-strong)"
          },
          "--payment-method-list-brand-radius": {
            "description": "Brand-mark frame radius.",
            "default": "var(--a-radius-md)"
          },
          "--payment-method-list-brand-size": {
            "description": "Brand-mark frame size.",
            "default": "2.5rem"
          },
          "--payment-method-list-disabled-opacity": {
            "description": "Opacity applied when the host is disabled.",
            "default": 0.5
          },
          "--payment-method-list-gap": {
            "description": "Gap between rows.",
            "default": "var(--a-space-2)"
          },
          "--payment-method-list-row-bg": {
            "description": "Default row background.",
            "default": "var(--a-bg)"
          },
          "--payment-method-list-row-bg-default": {
            "description": "Background tint applied to the default row.",
            "default": "var(--a-accent-muted)"
          },
          "--payment-method-list-row-bg-hover": {
            "description": "Row hover background.",
            "default": "var(--a-bg-muted)"
          },
          "--payment-method-list-row-border": {
            "description": "Row border.",
            "default": "1px solid var(--a-border-subtle)"
          },
          "--payment-method-list-row-border-default": {
            "description": "Border on the default row.",
            "default": "1px solid var(--a-accent)"
          },
          "--payment-method-list-row-gap": {
            "description": "Gap between brand mark, meta, and actions cells.",
            "default": "var(--a-space-3)"
          },
          "--payment-method-list-row-px": {
            "description": "Row horizontal padding.",
            "default": "var(--a-space-4)"
          },
          "--payment-method-list-row-py": {
            "description": "Row vertical padding.",
            "default": "var(--a-space-3)"
          },
          "--payment-method-list-row-radius": {
            "description": "Row corner radius.",
            "default": "var(--a-radius-lg)"
          }
        },
        "traits": [
          "focusable"
        ],
        "version": 1
      }
    },
    "PipelineStatus": {
      "title": "PipelineStatus",
      "description": "Single updating pipeline status indicator showing current step and progress. Renders inline as a status pill with optional progress bar; updates via the status property. Use for long-running agent or build pipelines; for multi-step wizards use <stepper-ui> instead.",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "complete": {
          "description": "Component property: complete.",
          "type": "boolean",
          "default": false
        },
        "component": {
          "const": "PipelineStatus"
        },
        "message": {
          "description": "Component property: message.",
          "type": "string",
          "default": ""
        },
        "stage": {
          "description": "Component property: stage.",
          "type": "string",
          "default": ""
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [],
        "category": "agent",
        "composes": [],
        "events": {},
        "examples": [
          {
            "description": "Basic PipelineStatus usage",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"Card\",\n    \"children\": [\n      \"sec\"\n    ]\n  },\n  {\n    \"id\": \"sec\",\n    \"component\": \"Section\",\n    \"children\": [\n      \"comp\"\n    ]\n  },\n  {\n    \"id\": \"comp\",\n    \"component\": \"PipelineStatus\"\n  }\n]",
            "name": "basic-pipeline-status"
          },
          {
            "description": "Pipeline status with a prominent stage label for the current step.",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"PipelineStatus\",\n    \"stage\": \"Building catalog\",\n    \"message\": \"Reading 100 patterns from disk...\"\n  }\n]",
            "name": "stage"
          },
          {
            "description": "Pipeline status with a secondary progress message updated as the stage advances.",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"PipelineStatus\",\n    \"stage\": \"Running evals\",\n    \"message\": \"32 / 100 intents scored...\"\n  }\n]",
            "name": "message"
          },
          {
            "description": "Pipeline status marked complete; indicator switches to success state.",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"PipelineStatus\",\n    \"stage\": \"Done\",\n    \"message\": \"All 100 intents passed\",\n    \"complete\": true\n  }\n]",
            "name": "complete"
          }
        ],
        "keywords": [
          "pipelinestatus",
          "pipeline-status",
          "pipeline",
          "status"
        ],
        "name": "UIPipelineStatus",
        "related": [
          "AgentTrace",
          "Stepper",
          "StepProgress"
        ],
        "slots": {
          "default": {
            "description": "Default slot — primary child content."
          }
        },
        "states": [
          {
            "description": "Default, ready for interaction.",
            "name": "idle"
          }
        ],
        "status": "stable",
        "synonyms": {
          "tags": [
            "job-status",
            "deploy-status",
            "pipeline-indicator"
          ]
        },
        "tag": "pipeline-status-ui",
        "tokens": {},
        "traits": [],
        "version": 1
      }
    },
    "PlanPicker": {
      "title": "PlanPicker",
      "description": "A form-participating chooser of one of N billing plans. The canonical\nplan-card grid used by both in-app upgrade modals and marketing\npricing pages (SPEC-012 composes this primitive as its core), so\nbenefit copy, pricing strings, recommendation highlighting, and the\nbilling-cycle toggle never drift between surfaces.\n\nEach plan record carries a stable id, name, optional tagline + icon,\na per-cycle price object, a feature list, and optional flags\n(recommended, rank, disabled). One plan may carry recommended:true\n(accent border + tinted bg + shadow); a host-level `current` id\nmarks the user's current plan (muted bg, \"Current plan\" tag, no\nChoose CTA, contextual \"Upgrade\"/\"Downgrade\" labels on siblings).\n\nLayout is grid by default (marketing surfaces) and `layout=\"list\"`\nfor in-app settings panels. The optional `cycle-toggle` boolean\nrenders an internal <segmented-ui> that swaps prices between\nmonthly and annual cycles in place across every card.\n\nSpec: docs/specs/implementation-ready/SPEC-011-plan-picker-in-app-upgrade.md.\n",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "component": {
          "const": "PlanPicker"
        },
        "currency": {
          "description": "Default ISO 4217 currency code for price rendering. Overridable\nper-price via plans[].prices[cycle].currency.\n",
          "type": "string",
          "default": "USD"
        },
        "current": {
          "description": "Id of the user's CURRENT plan. When set, that card renders with\na muted background, a \"Current plan\" <tag-ui>, and either no CTA\nor a \"Manage\" CTA. Other plans receive contextual upgrade /\ndowngrade CTA labels derived from rank. Unknown ids fail\nsilently (no anchor row).\n",
          "$ref": "#/$defs/DynamicString"
        },
        "cycle": {
          "description": "Active billing cycle. Drives which `plans[].prices[cycle]` value\nrenders across every card simultaneously. Toggle via the in-host\n`cycle-toggle` (when set) or programmatically via setCycle().\n",
          "$ref": "#/$defs/DynamicString"
        },
        "cycle-toggle": {
          "description": "When set, the primitive renders an internal <segmented-ui> with\nMonthly / Annual options above the plan grid. When unset, the\nconsumer drives [cycle] externally (e.g. from a parent toolbar).\n",
          "type": "boolean",
          "default": false
        },
        "data-stream-src": {
          "description": "Optional endpoint returning the `plans` array (universal\ndata-stream-* trait). On successful load, `plans` is replaced\nand a `load` event fires; on failure an `error` event fires.\n",
          "type": "string",
          "default": ""
        },
        "disabled": {
          "description": "Block all interaction across the picker.",
          "type": "boolean",
          "default": false
        },
        "layout": {
          "description": "Card layout. `grid` (auto-fit columns, minimum 16rem) for\nmarketing surfaces. `list` (single column rows) for in-app\nsettings panels.\n",
          "type": "string",
          "enum": [
            "grid",
            "list"
          ],
          "default": "grid"
        },
        "locale": {
          "description": "Locale for Intl.NumberFormat (price) and cycle labels. Defaults\nto document.documentElement.lang (or \"en-US\" when absent).\n",
          "type": "string",
          "default": ""
        },
        "name": {
          "description": "Form field name for the selected plan id. Mirrors UIFormElement\nconventions; serialized via ElementInternals.\n",
          "type": "string",
          "default": ""
        },
        "plans": {
          "description": "Array of plan records. Source of truth for the rendered cards.\nShape per record: {id, name, tagline?, prices: {monthly: {amount,\ncurrency?, unit?, note?}, annual?: {...}}, features?: string[],\ncta?: string, recommended?: boolean, rank?: number, icon?: string,\ndisabled?: boolean}. Empty array renders the empty-state.\n",
          "$ref": "#/$defs/DynamicStringList"
        },
        "value": {
          "description": "Currently selected plan id (form value). Read-write — both the\nform submission key and the [checked] gate on the matching\n<option-card-ui>.\n",
          "$ref": "#/$defs/DynamicString"
        }
      },
      "required": [
        "component",
        "plans"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [
          {
            "fix": "<plan-picker-ui plans='[\n  {\"id\":\"p1\",\"name\":\"Free\",\"prices\":{\"monthly\":{\"amount\":0}}},\n  {\"id\":\"p2\",\"name\":\"Pro\",\"prices\":{\"monthly\":{\"amount\":20}}}\n]'></plan-picker-ui>\n",
            "why": "`price` is a top-level shortcut not in the schema. Prices are\nkeyed by cycle (monthly / annual). Without a cycle key, the\ncycle toggle has nothing to switch and annual pricing is\ninvisible to consumers.\n",
            "wrong": "<plan-picker-ui plans='[\n  {\"id\":\"p1\",\"name\":\"Free\",\"price\":0},\n  {\"id\":\"p2\",\"name\":\"Pro\",\"price\":20}\n]'></plan-picker-ui>\n"
          },
          {
            "fix": "<plan-picker-ui plans='[\n  {\"id\":\"t\",\"name\":\"Team\",\"prices\":{\"monthly\":{\"amount\":10}}},\n  {\"id\":\"p\",\"name\":\"Pro\",\"recommended\":true,\"prices\":{\"monthly\":{\"amount\":20}}}\n]'></plan-picker-ui>\n",
            "why": "Two recommended plans cancel each other visually — there is no\n\"the\" recommendation. Pick one.\n",
            "wrong": "<plan-picker-ui plans='[\n  {\"id\":\"t\",\"name\":\"Team\",\"recommended\":true,\"prices\":{\"monthly\":{\"amount\":10}}},\n  {\"id\":\"p\",\"name\":\"Pro\",\"recommended\":true,\"prices\":{\"monthly\":{\"amount\":20}}}\n]'></plan-picker-ui>\n"
          },
          {
            "fix": "<plan-picker-ui plans=\"...\" cycle-toggle></plan-picker-ui>\n",
            "why": "Reinvents the radiogroup keyboard model and the cycle-toggle\nsemantics; pricing strings drift between this surface and the\nmarketing pricing page that uses the canonical primitive.\n",
            "wrong": "A <col-ui> of bespoke <card-ui> plan cards with manual radio\nmarkup and a per-plan cycle pill.\n"
          }
        ],
        "category": "input",
        "composes": [
          "option-card-ui",
          "segmented-ui",
          "segment-ui",
          "button-ui",
          "icon-ui",
          "text-ui",
          "tag-ui",
          "empty-state-ui"
        ],
        "events": {
          "change": {
            "description": "Fired when the selected plan id changes — either via user click\nor programmatic value set. Bubbles.\n",
            "detail": {
              "cycle": {
                "description": "Active billing cycle.",
                "type": "string"
              },
              "previous": {
                "description": "Previous plan id (empty string when none).",
                "type": "string"
              },
              "value": {
                "description": "New plan id.",
                "type": "string"
              }
            }
          },
          "cycle-change": {
            "description": "Fired when the active billing cycle changes (cycle-toggle\nclick or programmatic setCycle). Bubbles.\n",
            "detail": {
              "cycle": {
                "description": "New cycle.",
                "type": "string",
                "enum": [
                  "monthly",
                  "annual"
                ]
              },
              "previous": {
                "description": "Previous cycle.",
                "type": "string"
              }
            }
          },
          "error": {
            "description": "Fired when a `data-stream-src` fetch fails OR when a user tries\nto select a `disabled: true` plan. Bubbles.\n",
            "detail": {
              "reason": {
                "description": "One of `fetch-failed`, `plan-disabled`.",
                "type": "string"
              }
            }
          },
          "load": {
            "description": "Fired when `data-stream-src` finishes a successful fetch and\n`plans` is populated. Bubbles.\n",
            "detail": {
              "count": {
                "description": "Number of plans loaded.",
                "type": "integer"
              }
            }
          },
          "select": {
            "description": "Fired when the user activates a plan's CTA button — the\ncommitting action that consumers wire to a checkout / upgrade\nflow. Distinct from `change` (selection without commit). Bubbles.\n",
            "detail": {
              "cycle": {
                "description": "Active billing cycle at commit.",
                "type": "string"
              },
              "value": {
                "description": "Plan id being committed.",
                "type": "string"
              }
            }
          }
        },
        "examples": [
          {
            "description": "In-app upgrade modal with three plans + annual default + cycle toggle.",
            "a2ui": "[\n  {\n    \"id\": \"pp-upgrade\",\n    \"component\": \"PlanPicker\",\n    \"name\": \"plan\",\n    \"current\": \"plan_team\",\n    \"cycle\": \"annual\",\n    \"cycleToggle\": true,\n    \"plans\": [\n      {\"id\":\"plan_free\",\"name\":\"Free\",\"prices\":{\"monthly\":{\"amount\":0}},\"features\":[\"3 projects\",\"Community support\"],\"rank\":1},\n      {\"id\":\"plan_team\",\"name\":\"Team\",\"prices\":{\"monthly\":{\"amount\":10,\"unit\":\"seat\"},\"annual\":{\"amount\":8,\"unit\":\"seat\",\"note\":\"billed annually\"}},\"features\":[\"Unlimited projects\",\"Email support\"],\"rank\":2},\n      {\"id\":\"plan_pro\",\"name\":\"Pro\",\"prices\":{\"monthly\":{\"amount\":25,\"unit\":\"seat\"},\"annual\":{\"amount\":20,\"unit\":\"seat\",\"note\":\"billed annually\"}},\"features\":[\"Everything in Team\",\"Priority support\"],\"recommended\":true,\"rank\":3}\n    ]\n  }\n]\n",
            "name": "in-app-upgrade"
          },
          {
            "description": "Settings-page plan picker — single-column list inside a card.",
            "a2ui": "[\n  {\n    \"id\": \"pp-settings\",\n    \"component\": \"PlanPicker\",\n    \"name\": \"plan\",\n    \"current\": \"plan_team\",\n    \"layout\": \"list\",\n    \"plans\": [\n      {\"id\":\"plan_team\",\"name\":\"Team\",\"prices\":{\"monthly\":{\"amount\":10,\"unit\":\"seat\"}},\"features\":[\"Unlimited projects\"],\"rank\":2},\n      {\"id\":\"plan_pro\",\"name\":\"Pro\",\"prices\":{\"monthly\":{\"amount\":25,\"unit\":\"seat\"}},\"features\":[\"Everything in Team\",\"Priority support\"],\"recommended\":true,\"rank\":3}\n    ]\n  }\n]\n",
            "name": "settings-list"
          }
        ],
        "keywords": [
          "plan-picker",
          "plans",
          "pricing",
          "upgrade",
          "billing",
          "tier",
          "tiers",
          "subscription",
          "subscribe",
          "paywall",
          "choose-plan",
          "select-plan",
          "plan-selection"
        ],
        "name": "PlanPicker",
        "related": [
          "OptionCard",
          "Segmented",
          "Segment",
          "Tag",
          "Button",
          "Card",
          "EmptyState",
          "Skeleton"
        ],
        "slots": {
          "empty": {
            "description": "Custom empty-state shown when `plans` is empty. Falls back to a\ndefault <empty-state-ui> when not provided.\n"
          },
          "footer": {
            "description": "Optional content below the plan grid (compare-plans link, FAQ,\nfine print).\n"
          },
          "header": {
            "description": "Optional content above the plan grid (e.g. a <header> with a\ntitle and a custom cycle toggle). When absent and\n`cycle-toggle` is set, the primitive stamps its own toggle.\n"
          }
        },
        "states": [
          {
            "description": "Default — plans rendered, ready for interaction.",
            "name": "idle"
          },
          {
            "description": "A `data-stream-src` fetch is in flight.",
            "attribute": "loading",
            "name": "loading"
          },
          {
            "description": "No plans to render.",
            "attribute": "empty",
            "name": "empty"
          },
          {
            "description": "Last `data-stream-src` fetch failed.",
            "attribute": "error",
            "name": "error"
          },
          {
            "description": "All cards non-interactive.",
            "attribute": "disabled",
            "name": "disabled"
          }
        ],
        "status": "experimental",
        "synonyms": {
          "plan": [
            "tier",
            "subscription",
            "package"
          ],
          "pricing": [
            "plan",
            "price",
            "tier"
          ],
          "upgrade": [
            "plan-change",
            "subscribe",
            "choose-plan"
          ]
        },
        "tag": "plan-picker-ui",
        "tokens": {
          "--plan-picker-bg": {
            "description": "Host background. Defaults to transparent.",
            "default": "transparent"
          },
          "--plan-picker-card-bg": {
            "description": "Card background (cascades to option-card --option-card-bg).",
            "default": "var(--a-bg)"
          },
          "--plan-picker-card-bg-current": {
            "description": "Current-plan card background.",
            "default": "var(--a-bg-muted)"
          },
          "--plan-picker-card-bg-recommended": {
            "description": "Recommended-card background.",
            "default": "var(--a-accent-muted)"
          },
          "--plan-picker-card-border": {
            "description": "Default card border.",
            "default": "1px solid var(--a-border)"
          },
          "--plan-picker-card-border-recommended": {
            "description": "Recommended-card accent border.",
            "default": "2px solid var(--a-accent)"
          },
          "--plan-picker-card-px": {
            "description": "Card horizontal padding.",
            "default": "var(--a-space-5)"
          },
          "--plan-picker-card-py": {
            "description": "Card vertical padding.",
            "default": "var(--a-space-5)"
          },
          "--plan-picker-card-radius": {
            "description": "Card corner radius.",
            "default": "var(--a-radius-lg)"
          },
          "--plan-picker-card-shadow-recommended": {
            "description": "Shadow elevation on the recommended card.",
            "default": "var(--a-shadow-md)"
          },
          "--plan-picker-cycle-fg": {
            "description": "Per-unit / cycle suffix color (e.g. \"/month\").",
            "default": "var(--a-fg-muted)"
          },
          "--plan-picker-feature-icon-fg": {
            "description": "Feature-row check icon color.",
            "default": "var(--a-accent)"
          },
          "--plan-picker-features-gap": {
            "description": "Gap between feature list rows.",
            "default": "var(--a-space-2)"
          },
          "--plan-picker-grid-gap": {
            "description": "Gap between plan cards in grid layout.",
            "default": "var(--a-space-4)"
          },
          "--plan-picker-grid-min": {
            "description": "Minimum column width in auto-fit grid.",
            "default": "16rem"
          },
          "--plan-picker-price-fg": {
            "description": "Price color.",
            "default": "var(--a-fg-strong, var(--a-fg))"
          },
          "--plan-picker-price-size": {
            "description": "Price font size.",
            "default": "var(--a-text-3xl, 1.875rem)"
          },
          "--plan-picker-toggle-justify": {
            "description": "Justification of the internal cycle toggle row. `center` for\nmarketing layouts; `start` for in-app settings panels.\n",
            "default": "center"
          }
        },
        "traits": [
          "focusable"
        ],
        "version": 1
      }
    },
    "Popover": {
      "title": "Popover",
      "description": "Popover using Popover API + CSS Anchor Positioning. Triggers: click, hover, manual.",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "component": {
          "const": "Popover"
        },
        "gap": {
          "description": "Pixel offset between the anchor and the popover",
          "type": "number",
          "default": 4
        },
        "open": {
          "description": "Controls visibility via showPopover()/hidePopover()",
          "type": "boolean",
          "default": false
        },
        "placement": {
          "description": "Popover placement",
          "type": "string",
          "enum": [
            "top",
            "bottom",
            "left",
            "right",
            "top-start",
            "top-end",
            "bottom-start",
            "bottom-end"
          ],
          "default": "bottom"
        },
        "trigger": {
          "description": "Trigger mode",
          "type": "string",
          "enum": [
            "click",
            "hover",
            "manual"
          ],
          "default": "click"
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [],
        "category": "container",
        "composes": [],
        "events": {},
        "examples": [
          {
            "description": "Popover component demo showing a trigger button that opens a floating content panel with text.",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"Card\",\n    \"children\": [\n      \"sec\"\n    ]\n  },\n  {\n    \"id\": \"sec\",\n    \"component\": \"Section\",\n    \"children\": [\n      \"pop\"\n    ]\n  },\n  {\n    \"id\": \"pop\",\n    \"component\": \"Popover\",\n    \"trigger\": \"click\",\n    \"placement\": \"bottom\",\n    \"children\": [\n      \"trigger\",\n      \"content\"\n    ]\n  },\n  {\n    \"id\": \"trigger\",\n    \"component\": \"Button\",\n    \"slot\": \"trigger\",\n    \"text\": \"Open Popover\",\n    \"variant\": \"outline\"\n  },\n  {\n    \"id\": \"content\",\n    \"component\": \"Text\",\n    \"slot\": \"content\",\n    \"textContent\": \"This is the popover content. It can contain any elements.\"\n  }\n]",
            "name": "popover-demo"
          },
          {
            "description": "Button that triggers a Popover containing a list of menu action items.",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"Popover\",\n    \"attrs\": {\n      \"placement\": \"bottom-end\"\n    },\n    \"children\": [\n      \"trigger\",\n      \"menu-content\"\n    ]\n  },\n  {\n    \"id\": \"trigger\",\n    \"component\": \"Button\",\n    \"attrs\": {\n      \"variant\": \"outline\",\n      \"icon\": \"more-horizontal\",\n      \"aria-label\": \"More actions\"\n    }\n  },\n  {\n    \"id\": \"menu-content\",\n    \"component\": \"Column\",\n    \"attrs\": {\n      \"gap\": \"xs\",\n      \"padding\": \"sm\"\n    },\n    \"children\": [\n      \"menu-edit\",\n      \"menu-duplicate\",\n      \"menu-share\",\n      \"menu-div\",\n      \"menu-delete\"\n    ]\n  },\n  {\n    \"id\": \"menu-edit\",\n    \"component\": \"Button\",\n    \"attrs\": {\n      \"variant\": \"ghost\",\n      \"icon\": \"edit\",\n      \"full\": true,\n      \"align\": \"start\"\n    },\n    \"content\": \"Edit\"\n  },\n  {\n    \"id\": \"menu-duplicate\",\n    \"component\": \"Button\",\n    \"attrs\": {\n      \"variant\": \"ghost\",\n      \"icon\": \"copy\",\n      \"full\": true,\n      \"align\": \"start\"\n    },\n    \"content\": \"Duplicate\"\n  },\n  {\n    \"id\": \"menu-share\",\n    \"component\": \"Button\",\n    \"attrs\": {\n      \"variant\": \"ghost\",\n      \"icon\": \"share\",\n      \"full\": true,\n      \"align\": \"start\"\n    },\n    \"content\": \"Share\"\n  },\n  {\n    \"id\": \"menu-div\",\n    \"component\": \"Divider\"\n  },\n  {\n    \"id\": \"menu-delete\",\n    \"component\": \"Button\",\n    \"attrs\": {\n      \"variant\": \"danger\",\n      \"icon\": \"trash\",\n      \"full\": true,\n      \"align\": \"start\"\n    },\n    \"content\": \"Delete\"\n  }\n]",
            "name": "popover-menu"
          }
        ],
        "keywords": [
          "popover",
          "popup",
          "modal",
          "dialog",
          "menu",
          "dropdown",
          "actions",
          "tooltip",
          "hint",
          "context-menu",
          "right-click"
        ],
        "name": "UIPopover",
        "related": [
          "button",
          "divider"
        ],
        "slots": {
          "content": {
            "description": "Popover body — any interactive content. Hoisted to the top-layer via :popover-open when shown. Positioned via the Popover API + CSS Anchor Positioning per [placement] / [gap]; no manual positioning required."
          },
          "trigger": {
            "description": "Focusable element that opens the popover when activated. Typically <button-ui>, but any focusable element works (button, a link with href). MUST be focusable for keyboard accessibility — bare <span> or <div> children will not respond to keyboard activation. Positioned at the anchor point per [placement]."
          }
        },
        "states": [
          {
            "description": "Default, ready for interaction.",
            "name": "idle"
          }
        ],
        "status": "stable",
        "synonyms": {
          "actions": [
            "toolbar",
            "button",
            "popover"
          ],
          "context-menu": [
            "popover",
            "menu"
          ],
          "dialog": [
            "drawer",
            "alert",
            "popover",
            "panel"
          ],
          "dropdown": [
            "popover",
            "menu",
            "select",
            "form"
          ],
          "hint": [
            "tooltip",
            "button",
            "popover"
          ],
          "menu": [
            "nav",
            "sidebar",
            "popover",
            "menu",
            "command"
          ],
          "modal": [
            "drawer",
            "alert",
            "popover",
            "panel"
          ],
          "popover": [
            "popover",
            "menu",
            "tooltip"
          ],
          "popup": [
            "toast",
            "notification",
            "alert",
            "popover",
            "drawer"
          ],
          "right-click": [
            "popover",
            "menu"
          ],
          "tooltip": [
            "tooltip",
            "button",
            "popover"
          ]
        },
        "tag": "popover-ui",
        "tokens": {},
        "traits": [],
        "version": 1
      }
    },
    "Preview": {
      "title": "Preview",
      "description": "Live code + render in one frame, from a single source. Wrap any authored AdiaUI markup: the same HTML renders LIVE in a stage and appears beside (or below) it as escaped, syntax-highlighted, copyable source via a nested <code-ui>. The code can never drift from the render — it IS the render's source. Batteries-included + HTML-first by construction: write one block of HTML, no inline styles, no JS wiring, and both panes appear. Use it for every component/recipe example so the primary snippet is always real, copyable HTML shown next to the working component.",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "codeFirst": {
          "description": "Show the code pane before (above / left of) the render pane. Default is render-first.",
          "type": "boolean",
          "default": false
        },
        "component": {
          "const": "Preview"
        },
        "language": {
          "description": "Language hint forwarded to the nested <code-ui> for syntax highlighting. Demos are HTML, so this defaults to `html`.",
          "type": "string",
          "default": "html"
        },
        "layout": {
          "description": "Pane arrangement. Defaults to `split` — render and code side-by-side in a responsive 2-column grid that collapses to stacked on narrow widths (a bare `<preview-ui>` stamps `layout=\"split\"` on connect). Use `stack` to force the render stacked above the code; the docs auto-apply `stack` to wide self-framing demos (card / shell / table) that read cramped at half width. The `rows` attribute is a separate gallery mode and overrides this.",
          "type": "string",
          "enum": [
            "split",
            "stack"
          ],
          "default": ""
        },
        "rows": {
          "description": "Gallery mode — treat each direct child as a SEPARATE example and lay each out as its own `[render | code]` row (live sample left, its own source right), stacked with dividers. Without `rows`, the whole slotted markup is one render + one code block. An optional `data-preview-label` on a child surfaces a caption above that row's sample.",
          "type": "boolean",
          "default": false
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [],
        "category": "display",
        "composes": [],
        "events": {},
        "examples": [],
        "keywords": [
          "preview",
          "example",
          "demo",
          "code-preview",
          "live-preview",
          "playground",
          "codepen"
        ],
        "name": "UIPreview",
        "related": [
          "Code",
          "Card"
        ],
        "slots": {
          "default": {
            "description": "The authored markup to preview. Captured verbatim on connect: re-parsed into the live render stage AND shown literally in the code pane. Any valid AdiaUI HTML — one element or many siblings."
          }
        },
        "states": [
          {
            "description": "Default, the only state.",
            "name": "idle"
          }
        ],
        "status": "stable",
        "synonyms": {
          "preview": [
            "example",
            "demo",
            "sandbox",
            "live-preview"
          ]
        },
        "tag": "preview-ui",
        "tokens": {},
        "traits": [],
        "version": 1
      }
    },
    "Progress": {
      "title": "Progress",
      "description": "Progress indicator with bar (default) or spinner variant. Value < 0 marks indeterminate state showing animated activity instead of a fill. Use inside <progress-row-ui> for labeled task lists or standalone for global loading indicators; for percent-complete inline displays use <stat-ui> instead.",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "component": {
          "const": "Progress"
        },
        "value": {
          "description": "Current progress. 0..max (or 0..1 when max omitted). null = indeterminate (legacy -1 accepted for back-compat).",
          "type": "number",
          "default": null
        },
        "variant": {
          "description": "Render mode — `bar` (default) or `spinner`. For fill color set the `--progress-fill` token (defaults to `--a-accent`); there is no variant-as-color (use the token).",
          "type": "string",
          "enum": [
            "bar",
            "spinner"
          ],
          "default": "bar"
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [],
        "category": "display",
        "composes": [],
        "events": {},
        "examples": [
          {
            "description": "Two-column dashboard with quick actions (buttons) and system status (progress bars).",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"Grid\",\n    \"children\": [\n      \"c1\",\n      \"c2\"\n    ],\n    \"columns\": \"2\"\n  },\n  {\n    \"id\": \"c1\",\n    \"component\": \"Card\",\n    \"children\": [\n      \"c1h\",\n      \"c1s\"\n    ]\n  },\n  {\n    \"id\": \"c1h\",\n    \"component\": \"Header\",\n    \"children\": [\n      \"c1t\"\n    ]\n  },\n  {\n    \"id\": \"c1t\",\n    \"component\": \"Text\",\n    \"slot\": \"heading\",\n    \"textContent\": \"Quick Actions\",\n    \"variant\": \"section\"\n  },\n  {\n    \"id\": \"c1s\",\n    \"component\": \"Section\",\n    \"children\": [\n      \"c1col\"\n    ]\n  },\n  {\n    \"id\": \"c1col\",\n    \"component\": \"Column\",\n    \"children\": [\n      \"b1\",\n      \"b2\",\n      \"b3\"\n    ]\n  },\n  {\n    \"id\": \"b1\",\n    \"component\": \"Button\",\n    \"text\": \"New Project\",\n    \"variant\": \"solid\",\n    \"iconLeading\": \"plus\"\n  },\n  {\n    \"id\": \"b2\",\n    \"component\": \"Button\",\n    \"text\": \"Invite Member\",\n    \"variant\": \"outline\",\n    \"iconLeading\": \"users\"\n  },\n  {\n    \"id\": \"b3\",\n    \"component\": \"Button\",\n    \"text\": \"View Reports\",\n    \"variant\": \"ghost\",\n    \"iconLeading\": \"chart\"\n  },\n  {\n    \"id\": \"c2\",\n    \"component\": \"Card\",\n    \"children\": [\n      \"c2h\",\n      \"c2s\"\n    ]\n  },\n  {\n    \"id\": \"c2h\",\n    \"component\": \"Header\",\n    \"children\": [\n      \"c2t\"\n    ]\n  },\n  {\n    \"id\": \"c2t\",\n    \"component\": \"Text\",\n    \"slot\": \"heading\",\n    \"textContent\": \"System Status\",\n    \"variant\": \"section\"\n  },\n  {\n    \"id\": \"c2s\",\n    \"component\": \"Section\",\n    \"children\": [\n      \"c2col\"\n    ]\n  },\n  {\n    \"id\": \"c2col\",\n    \"component\": \"Column\",\n    \"children\": [\n      \"p1\",\n      \"p2\",\n      \"p3\"\n    ]\n  },\n  {\n    \"id\": \"p1\",\n    \"component\": \"Progress\",\n    \"value\": \"92\",\n    \"label\": \"CPU\"\n  },\n  {\n    \"id\": \"p2\",\n    \"component\": \"Progress\",\n    \"value\": \"67\",\n    \"label\": \"Memory\"\n  },\n  {\n    \"id\": \"p3\",\n    \"component\": \"Progress\",\n    \"value\": \"34\",\n    \"label\": \"Disk\"\n  }\n]",
            "name": "dashboard"
          },
          {
            "description": "User onboarding checklist with progress and checkbox items.",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"Card\",\n    \"children\": [\n      \"hdr\",\n      \"sec\"\n    ]\n  },\n  {\n    \"id\": \"hdr\",\n    \"component\": \"Header\",\n    \"children\": [\n      \"title\"\n    ]\n  },\n  {\n    \"id\": \"title\",\n    \"component\": \"Text\",\n    \"slot\": \"heading\",\n    \"textContent\": \"Getting Started\"\n  },\n  {\n    \"id\": \"sec\",\n    \"component\": \"Section\",\n    \"children\": [\n      \"col\"\n    ]\n  },\n  {\n    \"id\": \"col\",\n    \"component\": \"Column\",\n    \"children\": [\n      \"prog\",\n      \"c1\",\n      \"c2\",\n      \"c3\"\n    ],\n    \"gap\": \"3\"\n  },\n  {\n    \"id\": \"prog\",\n    \"component\": \"Progress\",\n    \"value\": 33,\n    \"max\": 100\n  },\n  {\n    \"id\": \"c1\",\n    \"component\": \"CheckBox\",\n    \"label\": \"Complete your profile\",\n    \"checked\": true\n  },\n  {\n    \"id\": \"c2\",\n    \"component\": \"CheckBox\",\n    \"label\": \"Invite team members\"\n  },\n  {\n    \"id\": \"c3\",\n    \"component\": \"CheckBox\",\n    \"label\": \"Create your first project\"\n  }\n]",
            "name": "onboarding-checklist"
          }
        ],
        "keywords": [
          "progress",
          "monitor",
          "monitoring",
          "health",
          "performance",
          "workflow",
          "stepper",
          "wizard",
          "multi-step",
          "timeline",
          "loading",
          "spinner",
          "percent",
          "gamification"
        ],
        "name": "UIProgress",
        "related": [
          "grid",
          "button",
          "check-box",
          "upload"
        ],
        "slots": {
          "fill": {
            "description": "Bar fill element inside track"
          },
          "track": {
            "description": "Bar track container"
          }
        },
        "states": [
          {
            "description": "Default, ready for interaction.",
            "name": "idle"
          }
        ],
        "status": "stable",
        "synonyms": {
          "gamification": [
            "leaderboard",
            "badge",
            "progress"
          ],
          "health": [
            "dashboard",
            "metric",
            "stat",
            "progress"
          ],
          "loading": [
            "loading",
            "skeleton",
            "progress",
            "bar"
          ],
          "monitor": [
            "dashboard",
            "metric",
            "stat",
            "chart",
            "progress"
          ],
          "monitoring": [
            "dashboard",
            "metric",
            "stat",
            "chart",
            "progress"
          ],
          "multi-step": [
            "wizard",
            "step",
            "progress"
          ],
          "percent": [
            "progress",
            "bar"
          ],
          "performance": [
            "dashboard",
            "metric",
            "chart",
            "stat",
            "progress"
          ],
          "progress": [
            "progress",
            "bar",
            "tracker",
            "loading"
          ],
          "spinner": [
            "loading",
            "skeleton",
            "progress"
          ],
          "stepper": [
            "wizard",
            "step",
            "progress",
            "tracker"
          ],
          "tags": [
            "LoadingIndicator"
          ],
          "timeline": [
            "social",
            "post",
            "activity",
            "team",
            "progress"
          ],
          "wizard": [
            "wizard",
            "step",
            "progress",
            "tracker",
            "onboarding"
          ],
          "workflow": [
            "kanban",
            "board",
            "project",
            "wizard",
            "progress",
            "step"
          ]
        },
        "tag": "progress-ui",
        "tokens": {},
        "traits": [],
        "version": 1
      }
    },
    "ProgressRow": {
      "title": "ProgressRow",
      "description": "Inline labeled progress row with label, progress bar, and meta text. Used for storage quotas, capacity breakdowns, usage indicators.",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "component": {
          "const": "ProgressRow"
        },
        "label": {
          "description": "Left-hand label text",
          "type": "string",
          "default": ""
        },
        "meta": {
          "description": "Right-hand meta text (e.g. '32 GB', '4.2k / 10k')",
          "type": "string",
          "default": ""
        },
        "value": {
          "description": "Progress value 0-100 (null = indeterminate; legacy -1 accepted for back-compat)",
          "type": "number",
          "default": null
        },
        "variant": {
          "description": "Color variant for the progress fill",
          "type": "string",
          "enum": [
            "default",
            "success",
            "warning",
            "danger"
          ],
          "default": "default"
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [],
        "category": "data",
        "composes": [
          "progress-ui"
        ],
        "events": {},
        "examples": [
          {
            "description": "Basic ProgressRow usage",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"Card\",\n    \"children\": [\n      \"sec\"\n    ]\n  },\n  {\n    \"id\": \"sec\",\n    \"component\": \"Section\",\n    \"children\": [\n      \"comp\"\n    ]\n  },\n  {\n    \"id\": \"comp\",\n    \"component\": \"ProgressRow\",\n    \"label\": \"Example ProgressRow\"\n  }\n]",
            "name": "basic-progress-row"
          }
        ],
        "keywords": [
          "progressrow",
          "progress-row",
          "progress",
          "row"
        ],
        "name": "UIProgressRow",
        "related": [
          "Progress",
          "StepProgress",
          "List"
        ],
        "slots": {
          "label": {
            "description": "Label region — control label."
          },
          "meta": {
            "description": "Child content region for the `meta` slot."
          }
        },
        "states": [
          {
            "description": "Default, ready for interaction.",
            "name": "idle"
          }
        ],
        "status": "stable",
        "synonyms": {
          "progress-row": [
            "task-row",
            "progress-line",
            "labeled-progress"
          ]
        },
        "tag": "progress-row-ui",
        "tokens": {},
        "traits": [],
        "version": 1
      }
    },
    "QRCode": {
      "title": "QRCode",
      "description": "Inline QR code generator — renders a scannable code as inline SVG.\nTwo modes:\n\n**A. Auto-encode (default).** Set `[value]` to a string (URL, plain\ntext, share link, 2FA secret). The component encodes the data with\nthe built-in zero-deps QR encoder (byte mode, ECC level configurable,\nversions 1–10 up to ~150 byte chars) and renders an SVG.\n\n**B. Bring-your-own matrix.** Set `[matrix]` to a JSON string of a\n2-D 0/1 array (`[[1,0,1,...],[...],...]`). The component renders the\nsupplied matrix directly without invoking its own encoder. Use this\nwhen you need versions 11–40, kanji/alphanumeric mode, or any\nencoder feature beyond the built-in. When both `[value]` and\n`[matrix]` are set, the matrix wins (BYO override).\n\nOutput is a single `<svg>` with `viewBox=\"0 0 N N\"`. Crisp-edges\nrendering preserves the scannable cell boundaries at any size.\nSizing is controlled by the `[size]` prop (host CSS-pixel dimension);\ninternal cell size is computed from `size / (matrix-size + 2 ·\nmargin)`. ARIA: `role=\"img\"` with `aria-label` (default \"QR code\"\nor the `[label]` prop).\n",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "background": {
          "description": "Background (light-cell) color. **Empty defaults to `#ffffff` —\nhardcoded white** alongside the black foreground, for guaranteed\nscanability. Override only when paired with an explicit\n[color] (the contrast pair must scan).\n",
          "type": "string",
          "default": ""
        },
        "color": {
          "description": "Foreground (dark-cell) color. Any CSS color string (hex, rgb,\ntoken reference). **Empty defaults to `#000000` — hardcoded black\nfor guaranteed scanability** (theme-aware `currentColor` would\nproduce light-on-dark in dark mode, which most phone scanners\nrefuse to decode). Override for branded QRs only when you've\nverified the chosen color/background pair scans on the target\ndevices.\n",
          "type": "string",
          "default": ""
        },
        "component": {
          "const": "QRCode"
        },
        "errorCorrection": {
          "description": "Error-correction level (auto-encode mode only). `L` (7% recovery),\n`M` (15%, default), `Q` (25%), `H` (30%). Higher levels recover\nfrom more damage at the cost of QR-version size growth.\n",
          "type": "string",
          "enum": [
            "L",
            "M",
            "Q",
            "H"
          ],
          "default": "M"
        },
        "label": {
          "description": "`aria-label` for the SVG. Defaults to \"QR code\". Customize for\nbetter AT context (e.g. \"Share link QR code\", \"2FA setup QR\").\n",
          "type": "string",
          "default": "QR code"
        },
        "margin": {
          "description": "Quiet zone in cells around the QR pattern. QR spec requires a\nminimum 4-cell margin for reliable scanning; smaller values may\nnot scan on some devices. Default `4`.\n",
          "type": "number",
          "default": 4
        },
        "matrix": {
          "description": "BYO precomputed bit matrix as JSON — a 2-D array of 0/1\n(`[[1,0,...],[0,1,...],...]`). When set, the built-in encoder is\nbypassed and this matrix renders directly. Useful for QR variants\nthe built-in doesn't support (versions 11–40, alphanumeric mode,\nkanji, etc.) — bring your own encoder, pass the matrix here.\n",
          "type": "string",
          "default": ""
        },
        "size": {
          "description": "Host display size in CSS pixels (width and height; the SVG is\nalways square). Default 200. Internal cell size is computed from\nthis divided by `matrix-size + 2·margin`.\n",
          "type": "number",
          "default": 200
        },
        "value": {
          "description": "The string to encode (URL / text / share link / 2FA seed). When\n[matrix] is also set, the matrix wins. Empty value + empty matrix\nrenders nothing.\n",
          "type": "string",
          "default": ""
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [
          {
            "fix": "Drop the ECC level (lower L gives more capacity for the same\nversion), OR shorten the URL (use a URL shortener), OR encode\nwith a BYO encoder library + pass the [matrix]:\n`<qr-code-ui matrix=\"[[1,0,1,...],...]\"></qr-code-ui>`\n",
            "why": "Built-in encoder covers versions 1–10. Data beyond v10 capacity\nthrows + renders empty + sets [data-error]. Console warns with\nthe byte length so consumers can diagnose.\n",
            "wrong": "<qr-code-ui value=\"https://very.long.url.that.exceeds.150.bytes.of.utf8.encoded.length...\"></qr-code-ui>\n"
          },
          {
            "fix": "<qr-code-ui value=\"...\" margin=\"4\"></qr-code-ui>\n",
            "why": "Zero margin breaks scanning. QR spec requires a 4-cell quiet\nzone for reliable detection.\n",
            "wrong": "<qr-code-ui value=\"...\" margin=\"0\"></qr-code-ui>\n"
          }
        ],
        "category": "display",
        "composes": [],
        "events": {},
        "examples": [
          {
            "description": "Plain URL encoding at default size + ECC-M.",
            "a2ui": "[\n  {\n    \"id\": \"q\",\n    \"component\": \"QRCode\",\n    \"value\": \"https://example.com\"\n  }\n]\n",
            "name": "default"
          },
          {
            "description": "Custom colors matching brand chrome.",
            "a2ui": "[\n  {\n    \"id\": \"q\",\n    \"component\": \"QRCode\",\n    \"value\": \"https://adia.health/share/abc123\",\n    \"size\": 280,\n    \"color\": \"#1e293b\",\n    \"background\": \"#ffffff\",\n    \"errorCorrection\": \"Q\"\n  }\n]\n",
            "name": "branded"
          },
          {
            "description": "BYO precomputed matrix from an external encoder.",
            "a2ui": "[\n  {\n    \"id\": \"q\",\n    \"component\": \"QRCode\",\n    \"matrix\": \"[[1,1,1,1,1,1,1,0,1,...]...]\",\n    \"size\": 200,\n    \"label\": \"Boarding pass QR\"\n  }\n]\n",
            "name": "byo-matrix"
          }
        ],
        "keywords": [
          "qr-code",
          "qr",
          "barcode",
          "scan",
          "share",
          "2fa",
          "share-link"
        ],
        "name": "UIQRCode",
        "related": [
          "link",
          "share"
        ],
        "slots": {},
        "states": [
          {
            "description": "Default — QR rendered (or empty if no value/matrix).",
            "name": "idle"
          },
          {
            "description": "Auto-encode failed (data too long for v1–10 at requested ECC). Renders an empty placeholder; logs a console warning. Switch to a BYO matrix from an external encoder, or downgrade the ECC level.",
            "attribute": "data-error",
            "name": "error"
          }
        ],
        "status": "stable",
        "synonyms": {
          "qr": [
            "qr-code",
            "barcode"
          ],
          "scan": [
            "qr-code",
            "barcode"
          ]
        },
        "tag": "qr-code-ui",
        "tokens": {
          "--qr-code-bg": {
            "description": "Background (light) color when [background] is empty.",
            "default": "transparent"
          },
          "--qr-code-fg": {
            "description": "Foreground (dark) color when [color] is empty.",
            "default": "currentColor"
          }
        },
        "traits": [],
        "version": 1
      }
    },
    "Radio": {
      "title": "Radio",
      "description": "Radio button with pure CSS dot. Groups by name attribute (one selected value per group); form-associated and emits standard change events. Use for single-select option groups in forms; for richer styling or button-style options use <segment-ui> inside <segmented-ui> instead.",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "required": {
          "description": "Marks the radio group as requiring a selection for form validation",
          "type": "boolean",
          "default": false
        },
        "checked": {
          "description": "Whether this radio option is currently selected",
          "type": "boolean",
          "default": false
        },
        "component": {
          "const": "Radio"
        },
        "disabled": {
          "description": "Disables interaction and dims the control",
          "type": "boolean",
          "default": false
        },
        "error": {
          "description": "Validation error message displayed by the parent form wrapper",
          "type": "string",
          "default": ""
        },
        "hint": {
          "description": "Helper text displayed below the label",
          "type": "string",
          "default": ""
        },
        "label": {
          "description": "Label text, rendered via CSS attr(label) on ::after",
          "type": "string",
          "default": ""
        },
        "name": {
          "description": "Form control name for form data submission",
          "type": "string",
          "default": ""
        },
        "readonly": {
          "description": "Prevents value changes while keeping the control focusable",
          "type": "boolean",
          "default": false
        },
        "value": {
          "description": "Form value submitted when checked (defaults to 'on' if empty)",
          "type": "string",
          "default": ""
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [
          {
            "description": "Wrapping a radio-ui in field-ui. The widget already self-labels.",
            "right": "<radio-ui label=\"Basic plan\" name=\"plan\" value=\"basic\"></radio-ui>\n",
            "rule": "Use [label] on radio-ui directly; do not wrap in field-ui.",
            "wrong": "<field-ui inline label=\"Basic plan\">\n  <radio-ui name=\"plan\" value=\"basic\"></radio-ui>\n</field-ui>\n"
          }
        ],
        "category": "input",
        "composes": [],
        "events": {
          "change": {
            "description": "Fired when this radio becomes selected (bubbles)"
          }
        },
        "examples": [
          {
            "description": "Card with radio group for plan selection: Basic, Pro, and Enterprise tiers.",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"Card\",\n    \"children\": [\n      \"hdr\",\n      \"sec\",\n      \"ftr\"\n    ]\n  },\n  {\n    \"id\": \"hdr\",\n    \"component\": \"Header\",\n    \"children\": [\n      \"title\",\n      \"desc\"\n    ]\n  },\n  {\n    \"id\": \"title\",\n    \"component\": \"Text\",\n    \"slot\": \"heading\",\n    \"textContent\": \"Choose a Plan\",\n    \"variant\": \"section\"\n  },\n  {\n    \"id\": \"desc\",\n    \"component\": \"Text\",\n    \"slot\": \"description\",\n    \"variant\": \"caption\",\n    \"textContent\": \"Select the plan that works best for you\"\n  },\n  {\n    \"id\": \"sec\",\n    \"component\": \"Section\",\n    \"children\": [\n      \"options\"\n    ]\n  },\n  {\n    \"id\": \"options\",\n    \"component\": \"Column\",\n    \"children\": [\n      \"basic\",\n      \"pro\",\n      \"enterprise\"\n    ],\n    \"gap\": \"3\"\n  },\n  {\n    \"id\": \"basic\",\n    \"component\": \"Radio\",\n    \"label\": \"Basic — $9/mo\",\n    \"value\": \"basic\",\n    \"name\": \"plan\"\n  },\n  {\n    \"id\": \"pro\",\n    \"component\": \"Radio\",\n    \"label\": \"Pro — $29/mo\",\n    \"value\": \"pro\",\n    \"name\": \"plan\"\n  },\n  {\n    \"id\": \"enterprise\",\n    \"component\": \"Radio\",\n    \"label\": \"Enterprise — $99/mo\",\n    \"value\": \"enterprise\",\n    \"name\": \"plan\"\n  },\n  {\n    \"id\": \"ftr\",\n    \"component\": \"Footer\",\n    \"children\": [\n      \"confirm-btn\"\n    ]\n  },\n  {\n    \"id\": \"confirm-btn\",\n    \"component\": \"Button\",\n    \"text\": \"Confirm Plan\",\n    \"variant\": \"primary\",\n    \"block\": true,\n    \"slot\": \"action\"\n  }\n]",
            "name": "radio-group"
          }
        ],
        "keywords": [
          "radio",
          "options",
          "select",
          "checkbox",
          "toggle",
          "switch",
          "survey",
          "questionnaire",
          "poll"
        ],
        "name": "UIRadio",
        "related": [
          "button"
        ],
        "slots": {
          "dot": {
            "description": "Radio dot indicator, sized via --dot-size"
          },
          "label": {
            "description": "Label text container, rendered via CSS attr(label) on ::after"
          }
        },
        "states": [
          {
            "description": "Default, ready for interaction.",
            "name": "idle"
          },
          {
            "description": "Non-interactive; dimmed.",
            "attribute": "disabled",
            "name": "disabled"
          },
          {
            "description": "Keyboard focus ring.",
            "name": "focused",
            "selector": ":focus-visible"
          }
        ],
        "status": "stable",
        "synonyms": {
          "checkbox": [
            "radio",
            "checklist",
            "form"
          ],
          "options": [
            "settings",
            "radio",
            "segmented",
            "accordion"
          ],
          "poll": [
            "form",
            "radio",
            "chart"
          ],
          "questionnaire": [
            "form",
            "create",
            "radio",
            "wizard"
          ],
          "select": [
            "radio",
            "segmented",
            "form"
          ],
          "survey": [
            "form",
            "create",
            "radio"
          ],
          "switch": [
            "segmented",
            "radio",
            "settings"
          ],
          "toggle": [
            "segmented",
            "radio",
            "settings"
          ]
        },
        "tag": "radio-ui",
        "tokens": {
          "--radio-checked-background": {
            "description": "Override checked state background"
          },
          "--radio-checked-border-color": {
            "description": "Override checked state border color"
          },
          "--radio-checked-foreground": {
            "description": "Override inner dot color when checked"
          },
          "--radio-disabled-opacity": {
            "description": "Override disabled state opacity"
          },
          "--radio-dot-background": {
            "description": "Override default dot background"
          },
          "--radio-dot-border-color": {
            "description": "Override default dot border color"
          },
          "--radio-dot-radius": {
            "description": "Override dot border radius"
          },
          "--radio-dot-size": {
            "description": "Override dot diameter (default: 64% of --a-content-height)"
          },
          "--radio-focus-color": {
            "description": "Override focus ring color"
          },
          "--radio-gap": {
            "description": "Override gap between dot and label"
          },
          "--radio-hint-color": {
            "description": "Override hint text color"
          },
          "--radio-hint-font-size": {
            "description": "Override hint font size"
          },
          "--radio-hover-border-color": {
            "description": "Override hover state border color"
          },
          "--radio-label-color": {
            "description": "Override label text color"
          },
          "--radio-label-font-family": {
            "description": "Override label font family"
          },
          "--radio-label-font-size": {
            "description": "Override label font size"
          },
          "--radio-label-line-height": {
            "description": "Override label line height"
          },
          "--radio-transition": {
            "description": "Override transition timing"
          }
        },
        "traits": [
          "focusable"
        ],
        "version": 1
      }
    },
    "Range": {
      "title": "Range",
      "description": "Draggable numeric field — horizontal drag on the value changes it. No track/thumb, the entire field is the scrubber. Form-associated.",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "required": {
          "description": "Required for validation",
          "type": "boolean",
          "default": false
        },
        "component": {
          "const": "Range"
        },
        "disabled": {
          "description": "Disables interaction",
          "type": "boolean",
          "default": false
        },
        "error": {
          "description": "Validation error",
          "type": "string",
          "default": ""
        },
        "label": {
          "description": "Left-aligned label text",
          "type": "string",
          "default": ""
        },
        "max": {
          "description": "Maximum value",
          "type": "number",
          "default": 100
        },
        "min": {
          "description": "Minimum value",
          "type": "number",
          "default": 0
        },
        "name": {
          "description": "Form field name",
          "type": "string",
          "default": ""
        },
        "step": {
          "description": "Step increment",
          "type": "number",
          "default": 1
        },
        "suffix": {
          "description": "Unit suffix after value (px, rem, %)",
          "type": "string",
          "default": ""
        },
        "value": {
          "description": "Current numeric value",
          "type": "number",
          "default": 0
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [],
        "category": "input",
        "composes": [],
        "events": {
          "change": {
            "description": "Fired on drag end or keyboard commit"
          },
          "input": {
            "description": "Fired on each value change during drag or keyboard"
          }
        },
        "examples": [
          {
            "description": "E-commerce price range filter with range slider, min/max number inputs, and apply button.",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"Card\",\n    \"children\": [\n      \"hdr\",\n      \"sec\"\n    ]\n  },\n  {\n    \"id\": \"hdr\",\n    \"component\": \"Header\",\n    \"children\": [\n      \"title\"\n    ]\n  },\n  {\n    \"id\": \"title\",\n    \"component\": \"Text\",\n    \"slot\": \"heading\",\n    \"textContent\": \"Price Range\",\n    \"variant\": \"section\"\n  },\n  {\n    \"id\": \"sec\",\n    \"component\": \"Section\",\n    \"children\": [\n      \"fields\"\n    ]\n  },\n  {\n    \"id\": \"fields\",\n    \"component\": \"Column\",\n    \"children\": [\n      \"range\",\n      \"inputs-row\",\n      \"apply-btn\"\n    ],\n    \"gap\": \"4\"\n  },\n  {\n    \"id\": \"range\",\n    \"component\": \"Range\",\n    \"min\": 0,\n    \"max\": 1000,\n    \"name\": \"priceRange\"\n  },\n  {\n    \"id\": \"inputs-row\",\n    \"component\": \"Row\",\n    \"children\": [\n      \"min-input\",\n      \"separator\",\n      \"max-input\"\n    ],\n    \"gap\": \"3\"\n  },\n  {\n    \"id\": \"min-input\",\n    \"component\": \"Input\",\n    \"label\": \"Min\",\n    \"type\": \"number\",\n    \"name\": \"minPrice\",\n    \"placeholder\": \"0\"\n  },\n  {\n    \"id\": \"separator\",\n    \"component\": \"Text\",\n    \"variant\": \"body\",\n    \"textContent\": \"to\"\n  },\n  {\n    \"id\": \"max-input\",\n    \"component\": \"Input\",\n    \"label\": \"Max\",\n    \"type\": \"number\",\n    \"name\": \"maxPrice\",\n    \"placeholder\": \"1000\"\n  },\n  {\n    \"id\": \"apply-btn\",\n    \"component\": \"Button\",\n    \"text\": \"Apply Filter\",\n    \"variant\": \"primary\"\n  }\n]",
            "name": "price-range-filter"
          }
        ],
        "keywords": [
          "range",
          "volume"
        ],
        "name": "UIRange",
        "related": [
          "input",
          "button"
        ],
        "slots": {},
        "states": [
          {
            "description": "Default, ready for interaction.",
            "name": "idle"
          },
          {
            "description": "Non-interactive; dimmed.",
            "attribute": "disabled",
            "name": "disabled"
          }
        ],
        "status": "stable",
        "synonyms": {
          "range": [
            "slider",
            "range"
          ],
          "volume": [
            "slider",
            "range",
            "music"
          ]
        },
        "tag": "range-ui",
        "tokens": {
          "--range-background": {
            "description": "Field background"
          },
          "--range-border-color": {
            "description": "Border color"
          },
          "--range-fill-background": {
            "description": "Fill bar background"
          },
          "--range-height": {
            "description": "Field height"
          },
          "--range-label-color": {
            "description": "Label text color"
          },
          "--range-radius": {
            "description": "Border radius"
          },
          "--range-value-color": {
            "description": "Value text color"
          }
        },
        "traits": [],
        "version": 1
      }
    },
    "Rating": {
      "title": "Rating",
      "description": "Pictorial discrete rating (stars by default) with optional half-step precision. Supports keyboard, mouse hover preview, and form participation.",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "allowHalf": {
          "description": "Enable 0.5-step precision on click/hover",
          "type": "boolean",
          "default": false
        },
        "component": {
          "const": "Rating"
        },
        "icon": {
          "description": "Phosphor icon name for each symbol (e.g. star, heart, thumbs-up)",
          "type": "string",
          "default": "star"
        },
        "max": {
          "description": "Number of rating symbols",
          "type": "number",
          "default": 5
        },
        "name": {
          "description": "Form participation — field name when submitted",
          "type": "string",
          "default": ""
        },
        "readonly": {
          "description": "Display-only — disables interaction but remains readable",
          "type": "boolean",
          "default": false
        },
        "size": {
          "description": "Symbol size",
          "type": "string",
          "enum": [
            "sm",
            "md",
            "lg"
          ],
          "default": "md"
        },
        "value": {
          "description": "Current rating value (0..max, supports 0.5 steps when allowHalf)",
          "type": "number",
          "default": 0
        },
        "variant": {
          "description": "Color variant — applied via `:scope[variant=...]` selectors in CSS, no JS reflection needed",
          "type": "string",
          "enum": [
            "",
            "accent",
            "warning"
          ],
          "default": ""
        }
      },
      "required": [
        "component",
        "value"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [],
        "category": "form",
        "composes": [],
        "events": {
          "[object Object]": {
            "description": "Fired on [object Object]."
          }
        },
        "examples": [],
        "keywords": [
          "rating",
          "stars",
          "review",
          "feedback",
          "score",
          "vote",
          "heart",
          "like"
        ],
        "name": "UIRating",
        "related": [
          "Field",
          "AgentFeedbackBar"
        ],
        "slots": {},
        "states": [
          {
            "description": "Default, ready for interaction.",
            "name": "idle"
          }
        ],
        "status": "stable",
        "synonyms": {
          "rating": [
            "rating",
            "star rating",
            "review score",
            "feedback rating"
          ]
        },
        "tag": "rating-ui",
        "tokens": {},
        "traits": [],
        "version": 1
      }
    },
    "RelativeTime": {
      "title": "RelativeTime",
      "description": "Display a timestamp as a human-readable relative time — \"3 hours ago\",\n\"in 2 days\", \"yesterday\". Wraps `Intl.RelativeTimeFormat` for i18n\n+ auto-updates on a configurable interval (default every 60 s) so\nrendered text stays current without re-mounting.\n\nSet `[datetime]` to an ISO 8601 timestamp; the element computes the\ndelta against `Date.now()` and renders the formatted string. Pair\nwith a `title` for full-precision-on-hover (the element sets one\nautomatically from a default locale-aware long format unless you\noverride).\n",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "component": {
          "const": "RelativeTime"
        },
        "datetime": {
          "description": "ISO 8601 timestamp (e.g. `2026-05-25T09:30:00Z`) or any string\nparseable by `Date`. Required for output — empty value renders\nnothing.\n",
          "type": "string",
          "default": ""
        },
        "locale": {
          "description": "BCP-47 locale tag for the formatter. Empty defaults to the document\nlocale (`<html lang>`) then to the browser default.\n",
          "type": "string",
          "default": ""
        },
        "numeric": {
          "description": "`Intl.RelativeTimeFormat` `numeric` option. `auto` lets the\nformatter substitute \"yesterday\" / \"tomorrow\" for ±1 day deltas;\n`always` keeps the numeric form (\"1 day ago\"). Defaults to `auto`.\n",
          "type": "string",
          "enum": [
            "auto",
            "always"
          ],
          "default": "auto"
        },
        "timeStyle": {
          "description": "`Intl.RelativeTimeFormat` `style` option. `long` = \"3 hours ago\",\n`short` = \"3 hr. ago\", `narrow` = \"3h ago\". Defaults to `long`.\n",
          "type": "string",
          "enum": [
            "long",
            "short",
            "narrow"
          ],
          "default": "long"
        },
        "updateInterval": {
          "description": "Auto-refresh interval in seconds. The component restarts a\n`setInterval` tick that re-reads `Date.now()` and re-renders the\nrelative string. Set to `0` to disable auto-update (static\nrender). Default `60` (one minute) is the natural cadence for\n\"minutes ago\" granularity.\n",
          "type": "number",
          "default": 60
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [],
        "category": "display",
        "composes": [],
        "events": {},
        "examples": [
          {
            "description": "A timestamp rendered as a long relative phrase, auto-updating every 60 s.",
            "a2ui": "[\n  {\n    \"id\": \"ts\",\n    \"component\": \"RelativeTime\",\n    \"datetime\": \"2026-05-25T09:00:00Z\"\n  }\n]\n",
            "name": "default"
          },
          {
            "description": "Tight UI affordances — narrow form for chat bubble timestamps.",
            "a2ui": "[\n  {\n    \"id\": \"ts\",\n    \"component\": \"RelativeTime\",\n    \"datetime\": \"2026-05-25T11:30:00Z\",\n    \"timeStyle\": \"narrow\"\n  }\n]\n",
            "name": "short-narrow"
          },
          {
            "description": "A historical timestamp that doesn't need to tick (commit log row).",
            "a2ui": "[\n  {\n    \"id\": \"ts\",\n    \"component\": \"RelativeTime\",\n    \"datetime\": \"2025-11-01T00:00:00Z\",\n    \"updateInterval\": 0\n  }\n]\n",
            "name": "static-historical"
          }
        ],
        "keywords": [
          "relative-time",
          "timeago",
          "time",
          "timestamp",
          "ago",
          "elapsed",
          "relative",
          "duration"
        ],
        "name": "UIRelativeTime",
        "related": [
          "text",
          "badge",
          "stat"
        ],
        "slots": {},
        "states": [
          {
            "description": "Default, displaying the formatted relative time.",
            "name": "idle"
          }
        ],
        "status": "stable",
        "synonyms": {
          "ago": [
            "relative-time",
            "timeago"
          ],
          "timestamp": [
            "relative-time",
            "time",
            "datetime"
          ]
        },
        "tag": "relative-time-ui",
        "tokens": {},
        "traits": [],
        "version": 1
      }
    },
    "RichText": {
      "title": "RichText",
      "description": "Markdown-to-HTML rendering primitive — converts the [markdown] prop\n(or fetched [src] content) into styled HTML using the canonical\nprose tokens. Used for rendering LLM responses inside chat surfaces,\narticle bodies, and documentation pages. Distinct from <code-ui>\n(syntax-highlighted code), <textarea-ui> (interactive editor), and\n<text-ui> (single-line typography). Not a Markdown editor — for\nediting use a CodeMirror-backed <code-ui language=\"markdown\"\neditable>.\n",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "component": {
          "const": "RichText"
        },
        "markdown": {
          "description": "Component property: markdown.",
          "type": "string",
          "default": ""
        },
        "src": {
          "description": "Source URL (image, iframe, etc.).",
          "type": "string",
          "default": ""
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [],
        "category": "forms",
        "composes": [],
        "events": {},
        "examples": [
          {
            "description": "Basic Richtext usage",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"Card\",\n    \"children\": [\n      \"sec\"\n    ]\n  },\n  {\n    \"id\": \"sec\",\n    \"component\": \"Section\",\n    \"children\": [\n      \"comp\"\n    ]\n  },\n  {\n    \"id\": \"comp\",\n    \"component\": \"Richtext\",\n    \"src\": \"/images/example.jpg\"\n  }\n]",
            "name": "basic-richtext"
          },
          {
            "description": "Inline markdown text rendered to styled HTML via the markdown attribute.",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"Richtext\",\n    \"markdown\": \"# Hello world\\n\\nWelcome to **AdiaUI**. This paragraph was parsed from markdown:\\n\\n- Lists\\n- Render\\n- Cleanly\\n\\n`inline code` and [links](https://example.com) work too.\"\n  }\n]",
            "name": "markdown"
          },
          {
            "description": "Fetch a remote markdown file via src and render it; useful for docs pages.",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"Richtext\",\n    \"src\": \"/README.md\"\n  }\n]",
            "name": "src"
          },
          {
            "description": "Richtext with fenced code blocks; whitespace preserved and monospace styling applied.",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"Richtext\",\n    \"markdown\": \"## Example\\n\\n```js\\nfunction greet(name) {\\n  return `Hello, ${name}!`;\\n}\\n```\\n\\nInline `code` also works.\"\n  }\n]",
            "name": "code-blocks"
          }
        ],
        "keywords": [
          "richtext"
        ],
        "name": "UIRichText",
        "related": [
          "Code",
          "Text",
          "Textarea"
        ],
        "slots": {
          "default": {
            "description": "Default slot — primary child content."
          }
        },
        "states": [
          {
            "description": "Default, ready for interaction.",
            "name": "idle"
          }
        ],
        "status": "stable",
        "synonyms": {
          "tags": [
            "markdown",
            "md-render",
            "rich-text"
          ]
        },
        "tag": "richtext-ui",
        "tokens": {},
        "traits": [],
        "version": 1
      }
    },
    "Row": {
      "title": "Row",
      "description": "Flex row layout primitive — horizontal stack of children with\n[gap] / [align] / [justify] / [grow] / [wrap]. The horizontal\ncounterpart to <col-ui>. Use <row-ui> for horizontal toolbars,\ninline-control clusters, button groups, table cells. For action\nclusters inside chrome containers (<header-ui> / <footer-ui>) use\nthe parent's [slot=\"action\"] convention instead — the chrome scope\nalready lays out actions correctly without wrapping in row-ui.\n",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "align": {
          "description": "Cross-axis alignment (start/center/end/stretch/baseline). Accepts `@bp` notation: align=\"start center@sm\".",
          "type": "string",
          "default": "center"
        },
        "component": {
          "const": "Row"
        },
        "draggable": {
          "description": "Enables drag handle + cursor:grab. Wires the draggable trait; dispatches drag-end.",
          "type": "boolean",
          "default": false
        },
        "gap": {
          "description": "Gap between children. Two grammars: a NAMED scale (xs/sm/md/lg/xl, parametric via --a-gap-k — 4/8/12/16/20px at k=1) and an integer space-rung (\"0\"…\"10\", \"12\", \"16\", literal). At k=1 they coincide: xs=1, sm=2, md=3, lg=4, xl=5. Accepts `@bp` notation: gap=\"2 4@md\".",
          "type": "string",
          "default": "md"
        },
        "grow": {
          "description": "Fills remaining space in a flex parent. CSS-only attribute via :scope[grow] in row.css.",
          "type": "boolean",
          "default": false
        },
        "justify": {
          "description": "Main-axis justify (start/center/end/between/space-between/space-around). Accepts `@bp` notation: justify=\"start between@md\".",
          "type": "string",
          "default": "start"
        },
        "wrap": {
          "description": "Enable flex-wrap unconditionally. For viewport-responsive wrapping use [wrap-at] instead.",
          "type": "boolean",
          "default": false
        },
        "wrapAt": {
          "description": "Enable flex-wrap from the named breakpoint upward (xs/sm/md/lg/xl). `wrap-at=\"sm\"` = no-wrap on xs, wrap from sm up. Complements the boolean [wrap] (always-wrap) without conflicting with it.",
          "type": "string",
          "default": ""
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [],
        "category": "layout",
        "composes": [],
        "events": {},
        "examples": [
          {
            "description": "Chat interface with message bubbles containing avatar and text pairs, plus an input footer.",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"Card\",\n    \"children\": [\n      \"hdr\",\n      \"sec\",\n      \"ftr\"\n    ]\n  },\n  {\n    \"id\": \"hdr\",\n    \"component\": \"Header\",\n    \"children\": [\n      \"title\"\n    ]\n  },\n  {\n    \"id\": \"title\",\n    \"component\": \"Text\",\n    \"slot\": \"heading\",\n    \"textContent\": \"Chat\"\n  },\n  {\n    \"id\": \"sec\",\n    \"component\": \"Section\",\n    \"children\": [\n      \"messages\"\n    ]\n  },\n  {\n    \"id\": \"messages\",\n    \"component\": \"Column\",\n    \"gap\": \"3\",\n    \"children\": [\n      \"msg1\",\n      \"msg2\",\n      \"msg3\",\n      \"msg4\"\n    ]\n  },\n  {\n    \"id\": \"msg1\",\n    \"component\": \"Row\",\n    \"gap\": \"2\",\n    \"children\": [\n      \"a1\",\n      \"t1\"\n    ]\n  },\n  {\n    \"id\": \"a1\",\n    \"component\": \"Avatar\",\n    \"name\": \"User\",\n    \"size\": \"sm\"\n  },\n  {\n    \"id\": \"t1\",\n    \"component\": \"Text\",\n    \"variant\": \"body\",\n    \"textContent\": \"Hello! Can you help me with something?\"\n  },\n  {\n    \"id\": \"msg2\",\n    \"component\": \"Row\",\n    \"gap\": \"2\",\n    \"children\": [\n      \"a2\",\n      \"t2\"\n    ]\n  },\n  {\n    \"id\": \"a2\",\n    \"component\": \"Avatar\",\n    \"name\": \"Assistant\",\n    \"size\": \"sm\"\n  },\n  {\n    \"id\": \"t2\",\n    \"component\": \"Text\",\n    \"variant\": \"body\",\n    \"textContent\": \"Of course! I'd be happy to help. What do you need?\"\n  },\n  {\n    \"id\": \"msg3\",\n    \"component\": \"Row\",\n    \"gap\": \"2\",\n    \"children\": [\n      \"a3\",\n      \"t3\"\n    ]\n  },\n  {\n    \"id\": \"a3\",\n    \"component\": \"Avatar\",\n    \"name\": \"User\",\n    \"size\": \"sm\"\n  },\n  {\n    \"id\": \"t3\",\n    \"component\": \"Text\",\n    \"variant\": \"body\",\n    \"textContent\": \"I need to build a dashboard layout.\"\n  },\n  {\n    \"id\": \"msg4\",\n    \"component\": \"Row\",\n    \"gap\": \"2\",\n    \"children\": [\n      \"a4\",\n      \"t4\"\n    ]\n  },\n  {\n    \"id\": \"a4\",\n    \"component\": \"Avatar\",\n    \"name\": \"Assistant\",\n    \"size\": \"sm\"\n  },\n  {\n    \"id\": \"t4\",\n    \"component\": \"Text\",\n    \"variant\": \"body\",\n    \"textContent\": \"Great choice! Let me suggest some patterns for that.\"\n  },\n  {\n    \"id\": \"ftr\",\n    \"component\": \"Footer\",\n    \"children\": [\n      \"input-row\"\n    ]\n  },\n  {\n    \"id\": \"input-row\",\n    \"component\": \"Row\",\n    \"gap\": \"2\",\n    \"children\": [\n      \"chat-input\",\n      \"send-btn\"\n    ]\n  },\n  {\n    \"id\": \"chat-input\",\n    \"component\": \"Input\",\n    \"placeholder\": \"Type a message...\"\n  },\n  {\n    \"id\": \"send-btn\",\n    \"component\": \"Button\",\n    \"text\": \"Send\",\n    \"icon\": \"send\",\n    \"variant\": \"primary\"\n  }\n]",
            "name": "chat-interface"
          },
          {
            "description": "Command palette card with search input and a list of command options.",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"Card\",\n    \"children\": [\n      \"hdr\",\n      \"sec\"\n    ]\n  },\n  {\n    \"id\": \"hdr\",\n    \"component\": \"Header\",\n    \"children\": [\n      \"search\"\n    ]\n  },\n  {\n    \"id\": \"search\",\n    \"component\": \"Input\",\n    \"placeholder\": \"Type a command or search...\",\n    \"icon\": \"search\"\n  },\n  {\n    \"id\": \"sec\",\n    \"component\": \"Section\",\n    \"children\": [\n      \"options\"\n    ]\n  },\n  {\n    \"id\": \"options\",\n    \"component\": \"Column\",\n    \"gap\": \"1\",\n    \"children\": [\n      \"opt1\",\n      \"opt2\",\n      \"opt3\",\n      \"opt4\",\n      \"opt5\"\n    ]\n  },\n  {\n    \"id\": \"opt1\",\n    \"component\": \"Row\",\n    \"gap\": \"2\",\n    \"children\": [\n      \"i1\",\n      \"l1\"\n    ]\n  },\n  {\n    \"id\": \"i1\",\n    \"component\": \"Icon\",\n    \"name\": \"file\"\n  },\n  {\n    \"id\": \"l1\",\n    \"component\": \"Text\",\n    \"textContent\": \"Open File\"\n  },\n  {\n    \"id\": \"opt2\",\n    \"component\": \"Row\",\n    \"gap\": \"2\",\n    \"children\": [\n      \"i2\",\n      \"l2\"\n    ]\n  },\n  {\n    \"id\": \"i2\",\n    \"component\": \"Icon\",\n    \"name\": \"gear\"\n  },\n  {\n    \"id\": \"l2\",\n    \"component\": \"Text\",\n    \"textContent\": \"Settings\"\n  },\n  {\n    \"id\": \"opt3\",\n    \"component\": \"Row\",\n    \"gap\": \"2\",\n    \"children\": [\n      \"i3\",\n      \"l3\"\n    ]\n  },\n  {\n    \"id\": \"i3\",\n    \"component\": \"Icon\",\n    \"name\": \"palette\"\n  },\n  {\n    \"id\": \"l3\",\n    \"component\": \"Text\",\n    \"textContent\": \"Change Theme\"\n  },\n  {\n    \"id\": \"opt4\",\n    \"component\": \"Row\",\n    \"gap\": \"2\",\n    \"children\": [\n      \"i4\",\n      \"l4\"\n    ]\n  },\n  {\n    \"id\": \"i4\",\n    \"component\": \"Icon\",\n    \"name\": \"users\"\n  },\n  {\n    \"id\": \"l4\",\n    \"component\": \"Text\",\n    \"textContent\": \"Manage Users\"\n  },\n  {\n    \"id\": \"opt5\",\n    \"component\": \"Row\",\n    \"gap\": \"2\",\n    \"children\": [\n      \"i5\",\n      \"l5\"\n    ]\n  },\n  {\n    \"id\": \"i5\",\n    \"component\": \"Icon\",\n    \"name\": \"sign-out\"\n  },\n  {\n    \"id\": \"l5\",\n    \"component\": \"Text\",\n    \"textContent\": \"Sign Out\"\n  }\n]",
            "name": "command-palette"
          }
        ],
        "keywords": [
          "row"
        ],
        "name": "UIRow",
        "related": [
          "avatar",
          "input",
          "button",
          "badge",
          "grid"
        ],
        "slots": {
          "default": {
            "description": "Default slot — primary child content."
          }
        },
        "states": [
          {
            "description": "Default, ready for interaction.",
            "name": "idle"
          }
        ],
        "status": "stable",
        "synonyms": {
          "row": [
            "hstack",
            "horizontal-stack",
            "hbox"
          ]
        },
        "tag": "row-ui",
        "tokens": {},
        "traits": [],
        "version": 1
      }
    },
    "Search": {
      "title": "Search",
      "description": "Search input with magnifying-glass icon, clear button, and debounced search event.",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "required": {
          "description": "Marks as required",
          "type": "boolean",
          "default": false
        },
        "component": {
          "const": "Search"
        },
        "debounce": {
          "description": "Debounce delay in ms before search event fires",
          "type": "number",
          "default": 300
        },
        "disabled": {
          "description": "Disables interaction",
          "type": "boolean",
          "default": false
        },
        "name": {
          "description": "Form field name",
          "type": "string",
          "default": ""
        },
        "placeholder": {
          "description": "Placeholder text",
          "type": "string",
          "default": "Search..."
        },
        "value": {
          "description": "Current search query",
          "type": "string",
          "default": ""
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [],
        "category": "input",
        "composes": [],
        "events": {
          "change": {
            "description": "Fired alongside `input` on every keystroke + on clear. Provides form-bearing-primitive event-shape parity (every UIFormElement emits `change` with `detail.value`).",
            "detail": {
              "value": {
                "description": "Current search-input value.",
                "type": "string"
              }
            }
          },
          "clear": {
            "description": "Fired when the clear button is clicked"
          },
          "input": {
            "description": "Fired on each input change during typing."
          },
          "search": {
            "description": "Debounced CustomEvent with detail.query containing the search string"
          }
        },
        "examples": [
          {
            "description": "Basic Search usage",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"Card\",\n    \"children\": [\n      \"sec\"\n    ]\n  },\n  {\n    \"id\": \"sec\",\n    \"component\": \"Section\",\n    \"children\": [\n      \"comp\"\n    ]\n  },\n  {\n    \"id\": \"comp\",\n    \"component\": \"Search\",\n    \"name\": \"search\",\n    \"placeholder\": \"Enter search...\",\n    \"value\": \"\"\n  }\n]",
            "name": "basic-search"
          }
        ],
        "keywords": [
          "search",
          "marketplace",
          "find",
          "lookup",
          "autocomplete",
          "typeahead",
          "spotlight",
          "omnibar",
          "combobox"
        ],
        "name": "UISearch",
        "related": [
          "Input",
          "Command",
          "Select"
        ],
        "slots": {},
        "states": [
          {
            "description": "Default, ready for interaction.",
            "name": "idle"
          },
          {
            "description": "Non-interactive; dimmed.",
            "attribute": "disabled",
            "name": "disabled"
          }
        ],
        "status": "stable",
        "synonyms": {
          "autocomplete": [
            "search",
            "command",
            "palette",
            "tag"
          ],
          "combobox": [
            "search",
            "command",
            "select"
          ],
          "find": [
            "search",
            "filter",
            "command"
          ],
          "lookup": [
            "search",
            "filter",
            "command"
          ],
          "marketplace": [
            "product",
            "pricing",
            "card",
            "image",
            "grid",
            "search",
            "filter"
          ],
          "omnibar": [
            "command",
            "palette",
            "search"
          ],
          "search": [
            "search",
            "filter",
            "command",
            "palette"
          ],
          "spotlight": [
            "command",
            "palette",
            "search"
          ],
          "typeahead": [
            "search",
            "command",
            "palette"
          ]
        },
        "tag": "search-ui",
        "tokens": {
          "--search-background": {
            "description": "Input background color"
          },
          "--search-border-color": {
            "description": "Input border color"
          },
          "--search-font-size": {
            "description": "Input font size"
          },
          "--search-foreground": {
            "description": "Input text color"
          },
          "--search-radius": {
            "description": "Input border radius"
          }
        },
        "traits": [],
        "version": 1
      }
    },
    "Section": {
      "title": "Section",
      "description": "Content section — styled by closest container parent (Card / Drawer / Modal / Page / AppShell). Groups related content between Header and Footer. `[scroll]` only kicks in inside Card / Drawer / Modal — Page and AppShell own their own scroll containers.",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "bleed": {
          "description": "Remove section padding so children can reach the card edges (used for full-bleed media).",
          "type": "boolean",
          "default": false
        },
        "component": {
          "const": "Section"
        },
        "scroll": {
          "description": "Enable overflow scrolling",
          "type": "boolean",
          "default": false
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [],
        "category": "container",
        "composes": [],
        "events": {},
        "examples": [
          {
            "description": "Chat interface with message bubbles containing avatar and text pairs, plus an input footer.",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"Card\",\n    \"children\": [\n      \"hdr\",\n      \"sec\",\n      \"ftr\"\n    ]\n  },\n  {\n    \"id\": \"hdr\",\n    \"component\": \"Header\",\n    \"children\": [\n      \"title\"\n    ]\n  },\n  {\n    \"id\": \"title\",\n    \"component\": \"Text\",\n    \"slot\": \"heading\",\n    \"textContent\": \"Chat\"\n  },\n  {\n    \"id\": \"sec\",\n    \"component\": \"Section\",\n    \"children\": [\n      \"messages\"\n    ]\n  },\n  {\n    \"id\": \"messages\",\n    \"component\": \"Column\",\n    \"gap\": \"3\",\n    \"children\": [\n      \"msg1\",\n      \"msg2\",\n      \"msg3\",\n      \"msg4\"\n    ]\n  },\n  {\n    \"id\": \"msg1\",\n    \"component\": \"Row\",\n    \"gap\": \"2\",\n    \"children\": [\n      \"a1\",\n      \"t1\"\n    ]\n  },\n  {\n    \"id\": \"a1\",\n    \"component\": \"Avatar\",\n    \"name\": \"User\",\n    \"size\": \"sm\"\n  },\n  {\n    \"id\": \"t1\",\n    \"component\": \"Text\",\n    \"variant\": \"body\",\n    \"textContent\": \"Hello! Can you help me with something?\"\n  },\n  {\n    \"id\": \"msg2\",\n    \"component\": \"Row\",\n    \"gap\": \"2\",\n    \"children\": [\n      \"a2\",\n      \"t2\"\n    ]\n  },\n  {\n    \"id\": \"a2\",\n    \"component\": \"Avatar\",\n    \"name\": \"Assistant\",\n    \"size\": \"sm\"\n  },\n  {\n    \"id\": \"t2\",\n    \"component\": \"Text\",\n    \"variant\": \"body\",\n    \"textContent\": \"Of course! I'd be happy to help. What do you need?\"\n  },\n  {\n    \"id\": \"msg3\",\n    \"component\": \"Row\",\n    \"gap\": \"2\",\n    \"children\": [\n      \"a3\",\n      \"t3\"\n    ]\n  },\n  {\n    \"id\": \"a3\",\n    \"component\": \"Avatar\",\n    \"name\": \"User\",\n    \"size\": \"sm\"\n  },\n  {\n    \"id\": \"t3\",\n    \"component\": \"Text\",\n    \"variant\": \"body\",\n    \"textContent\": \"I need to build a dashboard layout.\"\n  },\n  {\n    \"id\": \"msg4\",\n    \"component\": \"Row\",\n    \"gap\": \"2\",\n    \"children\": [\n      \"a4\",\n      \"t4\"\n    ]\n  },\n  {\n    \"id\": \"a4\",\n    \"component\": \"Avatar\",\n    \"name\": \"Assistant\",\n    \"size\": \"sm\"\n  },\n  {\n    \"id\": \"t4\",\n    \"component\": \"Text\",\n    \"variant\": \"body\",\n    \"textContent\": \"Great choice! Let me suggest some patterns for that.\"\n  },\n  {\n    \"id\": \"ftr\",\n    \"component\": \"Footer\",\n    \"children\": [\n      \"input-row\"\n    ]\n  },\n  {\n    \"id\": \"input-row\",\n    \"component\": \"Row\",\n    \"gap\": \"2\",\n    \"children\": [\n      \"chat-input\",\n      \"send-btn\"\n    ]\n  },\n  {\n    \"id\": \"chat-input\",\n    \"component\": \"Input\",\n    \"placeholder\": \"Type a message...\"\n  },\n  {\n    \"id\": \"send-btn\",\n    \"component\": \"Button\",\n    \"text\": \"Send\",\n    \"icon\": \"send\",\n    \"variant\": \"primary\"\n  }\n]",
            "name": "chat-interface"
          },
          {
            "description": "Command palette card with search input and a list of command options.",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"Card\",\n    \"children\": [\n      \"hdr\",\n      \"sec\"\n    ]\n  },\n  {\n    \"id\": \"hdr\",\n    \"component\": \"Header\",\n    \"children\": [\n      \"search\"\n    ]\n  },\n  {\n    \"id\": \"search\",\n    \"component\": \"Input\",\n    \"placeholder\": \"Type a command or search...\",\n    \"icon\": \"search\"\n  },\n  {\n    \"id\": \"sec\",\n    \"component\": \"Section\",\n    \"children\": [\n      \"options\"\n    ]\n  },\n  {\n    \"id\": \"options\",\n    \"component\": \"Column\",\n    \"gap\": \"1\",\n    \"children\": [\n      \"opt1\",\n      \"opt2\",\n      \"opt3\",\n      \"opt4\",\n      \"opt5\"\n    ]\n  },\n  {\n    \"id\": \"opt1\",\n    \"component\": \"Row\",\n    \"gap\": \"2\",\n    \"children\": [\n      \"i1\",\n      \"l1\"\n    ]\n  },\n  {\n    \"id\": \"i1\",\n    \"component\": \"Icon\",\n    \"name\": \"file\"\n  },\n  {\n    \"id\": \"l1\",\n    \"component\": \"Text\",\n    \"textContent\": \"Open File\"\n  },\n  {\n    \"id\": \"opt2\",\n    \"component\": \"Row\",\n    \"gap\": \"2\",\n    \"children\": [\n      \"i2\",\n      \"l2\"\n    ]\n  },\n  {\n    \"id\": \"i2\",\n    \"component\": \"Icon\",\n    \"name\": \"gear\"\n  },\n  {\n    \"id\": \"l2\",\n    \"component\": \"Text\",\n    \"textContent\": \"Settings\"\n  },\n  {\n    \"id\": \"opt3\",\n    \"component\": \"Row\",\n    \"gap\": \"2\",\n    \"children\": [\n      \"i3\",\n      \"l3\"\n    ]\n  },\n  {\n    \"id\": \"i3\",\n    \"component\": \"Icon\",\n    \"name\": \"palette\"\n  },\n  {\n    \"id\": \"l3\",\n    \"component\": \"Text\",\n    \"textContent\": \"Change Theme\"\n  },\n  {\n    \"id\": \"opt4\",\n    \"component\": \"Row\",\n    \"gap\": \"2\",\n    \"children\": [\n      \"i4\",\n      \"l4\"\n    ]\n  },\n  {\n    \"id\": \"i4\",\n    \"component\": \"Icon\",\n    \"name\": \"users\"\n  },\n  {\n    \"id\": \"l4\",\n    \"component\": \"Text\",\n    \"textContent\": \"Manage Users\"\n  },\n  {\n    \"id\": \"opt5\",\n    \"component\": \"Row\",\n    \"gap\": \"2\",\n    \"children\": [\n      \"i5\",\n      \"l5\"\n    ]\n  },\n  {\n    \"id\": \"i5\",\n    \"component\": \"Icon\",\n    \"name\": \"sign-out\"\n  },\n  {\n    \"id\": \"l5\",\n    \"component\": \"Text\",\n    \"textContent\": \"Sign Out\"\n  }\n]",
            "name": "command-palette"
          }
        ],
        "keywords": [
          "section"
        ],
        "name": "UISection",
        "related": [
          "avatar",
          "input",
          "button",
          "alert",
          "skeleton"
        ],
        "slots": {
          "default": {
            "description": "Default slot — primary child content."
          }
        },
        "states": [
          {
            "description": "Default, ready for interaction.",
            "name": "idle"
          }
        ],
        "status": "stable",
        "synonyms": {
          "section": [
            "section-region",
            "body-region",
            "content-section"
          ]
        },
        "tag": "section-ui",
        "tokens": {},
        "traits": [],
        "version": 1
      }
    },
    "Segment": {
      "title": "Segment",
      "description": "Individual segment child of <segmented-ui> — carries the [value],\n[text], optional [icon], and [selected] state for one option in\na horizontal segmented selector. Distinct from <tab-ui> (a view\nswitcher's child) and <option> (native option for <select-ui>).\nUse segment-ui only as a direct child of <segmented-ui>; never\nstandalone.\n",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "component": {
          "const": "Segment"
        },
        "disabled": {
          "description": "Disables this segment.",
          "type": "boolean",
          "default": false
        },
        "icon": {
          "description": "Phosphor icon name. Rendered as a leading <icon-ui> child stamped on render.",
          "type": "string",
          "default": ""
        },
        "selected": {
          "description": "Whether this segment is currently selected. Managed by the parent Segmented container; don't set multiple siblings selected.",
          "type": "boolean",
          "default": false
        },
        "text": {
          "description": "Display text. Rendered via CSS attr(text) on ::after pseudo-element.",
          "type": "string",
          "default": ""
        },
        "value": {
          "description": "Value emitted when this segment is selected.",
          "type": "string",
          "default": ""
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [],
        "category": "navigation",
        "composes": [
          "icon-ui"
        ],
        "events": {},
        "examples": [
          {
            "description": "Segmented control with 3 segment options for tab-like switching.",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"SegmentedControl\",\n    \"children\": [\n      \"s1\",\n      \"s2\",\n      \"s3\"\n    ]\n  },\n  {\n    \"id\": \"s1\",\n    \"component\": \"Segment\",\n    \"text\": \"Overview\",\n    \"active\": true\n  },\n  {\n    \"id\": \"s2\",\n    \"component\": \"Segment\",\n    \"text\": \"Features\"\n  },\n  {\n    \"id\": \"s3\",\n    \"component\": \"Segment\",\n    \"text\": \"Pricing\"\n  }\n]",
            "name": "segmented-control"
          },
          {
            "description": "Three segments inside a segmented control for view switching.",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"SegmentedControl\",\n    \"children\": [\n      \"s1\",\n      \"s2\",\n      \"s3\"\n    ]\n  },\n  {\n    \"id\": \"s1\",\n    \"component\": \"Segment\",\n    \"value\": \"overview\",\n    \"text\": \"Overview\"\n  },\n  {\n    \"id\": \"s2\",\n    \"component\": \"Segment\",\n    \"value\": \"features\",\n    \"text\": \"Features\"\n  },\n  {\n    \"id\": \"s3\",\n    \"component\": \"Segment\",\n    \"value\": \"pricing\",\n    \"text\": \"Pricing\"\n  }\n]",
            "name": "basic"
          },
          {
            "description": "Segmented control showing four time-range segments labeled via text attribute.",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"SegmentedControl\",\n    \"children\": [\n      \"s1\",\n      \"s2\",\n      \"s3\",\n      \"s4\"\n    ]\n  },\n  {\n    \"id\": \"s1\",\n    \"component\": \"Segment\",\n    \"value\": \"d\",\n    \"text\": \"Daily\"\n  },\n  {\n    \"id\": \"s2\",\n    \"component\": \"Segment\",\n    \"value\": \"w\",\n    \"text\": \"Weekly\"\n  },\n  {\n    \"id\": \"s3\",\n    \"component\": \"Segment\",\n    \"value\": \"m\",\n    \"text\": \"Monthly\"\n  },\n  {\n    \"id\": \"s4\",\n    \"component\": \"Segment\",\n    \"value\": \"y\",\n    \"text\": \"Yearly\"\n  }\n]",
            "name": "text"
          },
          {
            "description": "Segmented control with one disabled segment that cannot be selected.",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"SegmentedControl\",\n    \"children\": [\n      \"s1\",\n      \"s2\",\n      \"s3\"\n    ]\n  },\n  {\n    \"id\": \"s1\",\n    \"component\": \"Segment\",\n    \"value\": \"free\",\n    \"text\": \"Free\"\n  },\n  {\n    \"id\": \"s2\",\n    \"component\": \"Segment\",\n    \"value\": \"pro\",\n    \"text\": \"Pro\"\n  },\n  {\n    \"id\": \"s3\",\n    \"component\": \"Segment\",\n    \"value\": \"enterprise\",\n    \"text\": \"Enterprise\",\n    \"disabled\": true\n  }\n]",
            "name": "disabled"
          },
          {
            "description": "Segmented control with icon+text segments for view-mode toggles (list, grid, board).",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"SegmentedControl\",\n    \"children\": [\n      \"s1\",\n      \"s2\",\n      \"s3\"\n    ]\n  },\n  {\n    \"id\": \"s1\",\n    \"component\": \"Segment\",\n    \"value\": \"list\",\n    \"text\": \"List\",\n    \"icon\": \"list\"\n  },\n  {\n    \"id\": \"s2\",\n    \"component\": \"Segment\",\n    \"value\": \"grid\",\n    \"text\": \"Grid\",\n    \"icon\": \"squares-four\"\n  },\n  {\n    \"id\": \"s3\",\n    \"component\": \"Segment\",\n    \"value\": \"board\",\n    \"text\": \"Board\",\n    \"icon\": \"kanban\"\n  }\n]",
            "name": "icons"
          }
        ],
        "keywords": [
          "segment"
        ],
        "name": "UISegment",
        "related": [
          "segmented-control"
        ],
        "slots": {},
        "states": [
          {
            "description": "Default, ready for interaction.",
            "name": "idle"
          },
          {
            "description": "Non-interactive; dimmed.",
            "attribute": "disabled",
            "name": "disabled"
          }
        ],
        "status": "stable",
        "synonyms": {
          "segment": [
            "segment-button",
            "segmented-option",
            "option-button"
          ]
        },
        "tag": "segment-ui",
        "tokens": {},
        "traits": [],
        "version": 1
      }
    },
    "Segmented": {
      "title": "Segmented",
      "description": "Single-select toggle group with an animated sliding indicator. Children must be segment-ui elements.",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "component": {
          "const": "Segmented"
        },
        "value": {
          "description": "Value of the currently selected segment.",
          "type": "string",
          "default": ""
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [],
        "category": "navigation",
        "composes": [],
        "events": {
          "change": {
            "description": "Fired when the selected segment changes. detail contains { value }."
          }
        },
        "examples": [
          {
            "description": "Segmented control with three segment-ui children for view switching.",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"Card\",\n    \"children\": [\n      \"sec\"\n    ]\n  },\n  {\n    \"id\": \"sec\",\n    \"component\": \"Section\",\n    \"children\": [\n      \"comp\"\n    ]\n  },\n  {\n    \"id\": \"comp\",\n    \"component\": \"Segmented\",\n    \"value\": \"daily\",\n    \"children\": [\n      \"s1\",\n      \"s2\",\n      \"s3\"\n    ]\n  },\n  {\n    \"id\": \"s1\",\n    \"component\": \"Segment\",\n    \"value\": \"daily\",\n    \"text\": \"Daily\"\n  },\n  {\n    \"id\": \"s2\",\n    \"component\": \"Segment\",\n    \"value\": \"weekly\",\n    \"text\": \"Weekly\"\n  },\n  {\n    \"id\": \"s3\",\n    \"component\": \"Segment\",\n    \"value\": \"monthly\",\n    \"text\": \"Monthly\"\n  }\n]",
            "name": "basic-segmented"
          }
        ],
        "keywords": [
          "segmented",
          "options",
          "select",
          "toggle",
          "switch",
          "tab",
          "tabs",
          "button-group"
        ],
        "name": "UISegmented",
        "related": [
          "Segment",
          "ToggleGroup",
          "Tabs",
          "Radio"
        ],
        "slots": {
          "default": {
            "description": "Child segment-ui elements that form the toggle group. Children MUST be segment-ui — bare segment tags render text but are silently ignored for the sliding indicator and role/aria-checked state."
          },
          "indicator": {
            "description": "Auto-created sliding indicator element prepended on first render."
          }
        },
        "states": [
          {
            "description": "Default, ready for interaction.",
            "name": "idle"
          }
        ],
        "status": "stable",
        "synonyms": {
          "button-group": [
            "toolbar",
            "button",
            "segmented"
          ],
          "options": [
            "settings",
            "radio",
            "segmented",
            "accordion"
          ],
          "select": [
            "radio",
            "segmented",
            "form"
          ],
          "switch": [
            "segmented",
            "radio",
            "settings"
          ],
          "tab": [
            "tabs",
            "panel",
            "segmented"
          ],
          "tabs": [
            "tabs",
            "panel",
            "segmented"
          ],
          "tags": [
            "SegmentedControl",
            "Segmented"
          ],
          "toggle": [
            "segmented",
            "radio",
            "settings"
          ]
        },
        "tag": "segmented-ui",
        "tokens": {},
        "traits": [],
        "version": 1
      }
    },
    "Select": {
      "title": "Select",
      "description": "Single- and multi-select dropdown primitive — the canonical AdiaUI\nselect control. Form-bearing via UIFormElement: [name], [value],\n[required], [disabled], fires `change`. Options via native\n<option> / <optgroup> children, programmatic `.options` array, or\nJSON [data-options] (hydrated by <editor-shell>'s wireSelects).\nUse for single-select with > 4 options; for ≤ 4 options use\n<segmented-ui> or <radio-ui>. Multi-select via [multiple]: trigger\nrenders <tag-ui> chips per selection, popover shows checkbox-style\noption list, Backspace removes the last chip, [select-all] adds\nbulk controls, [max-chips] caps the visible chip count with a\n\"+N more\" pill. Form value stays a comma-separated string under\n[name] for native <form> compatibility (parse with .split(',')).\n",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "required": {
          "description": "Marks the field as required for form validation",
          "type": "boolean",
          "default": false
        },
        "avatar": {
          "description": "URL for leading avatar image (takes precedence over icon)",
          "type": "string",
          "default": ""
        },
        "clearable": {
          "description": "Multi-select only. Adds a clear-all `x` affordance to the trigger\nwhen at least one chip is present. Click empties value and fires\n`change`.\n",
          "type": "boolean",
          "default": false
        },
        "component": {
          "const": "Select"
        },
        "disabled": {
          "description": "Disables interaction and dims the control",
          "type": "boolean",
          "default": false
        },
        "divider": {
          "description": "Reserved attribute on a select option that renders as a visual divider instead of a selectable row.",
          "type": "boolean",
          "default": false
        },
        "error": {
          "description": "Validation error message",
          "type": "string",
          "default": ""
        },
        "free-text": {
          "description": "With searchable: commit the typed query on Enter when no option matches (unconstrained autocomplete)",
          "type": "boolean",
          "default": false
        },
        "hint": {
          "description": "§184 (v0.5.5, FEEDBACK-08 §7): small caption rendered beneath the select. Sets `aria-describedby` on the host so screen readers announce it as a description (distinct from `aria-label`, which comes from `label`). Does not conflict with the in-component `label`.",
          "type": "string",
          "default": ""
        },
        "icon": {
          "description": "Leading icon name rendered inside the trigger",
          "type": "string",
          "default": ""
        },
        "label": {
          "description": "Label text above the trigger",
          "type": "string",
          "default": ""
        },
        "max": {
          "description": "Multi-select only. Maximum allowed selections. Toggling past the\ncap is suppressed; the `invalid` event fires with reason=\"max\".\n`0` (default) = unlimited.\n",
          "type": "number",
          "default": 0
        },
        "max-chips": {
          "description": "Multi-select only. Caps the number of chips visible in the\ntrigger. When `value.length > max-chips`, the first N chips\nrender plus a \"+M more\" pill that opens the popover on click.\n`0` (default) = unlimited.\n",
          "type": "number",
          "default": 0
        },
        "maxlength": {
          "description": "Maximum character length for validation",
          "type": "number",
          "default": null
        },
        "min": {
          "description": "Multi-select only. Minimum required selections. Below this floor\nthe host's form validity goes invalid (valueMissing) and the\n`invalid` event fires.\n",
          "type": "number",
          "default": 0
        },
        "minlength": {
          "description": "Minimum character length for validation",
          "type": "number",
          "default": null
        },
        "multiple": {
          "description": "Enables multi-select. Trigger renders <tag-ui> chips per selection\n(not comma-separated text); popover renders checkbox-style option\nrows where clicks toggle without closing; Backspace from the\ntrigger removes the last chip. Form value remains comma-separated\nunder [name] for native <form> compatibility.\n",
          "type": "boolean",
          "default": false
        },
        "name": {
          "description": "Form control name for form data submission",
          "type": "string",
          "default": ""
        },
        "open": {
          "description": "Whether the listbox is open",
          "type": "boolean",
          "default": false
        },
        "options": {
          "description": "Option list. Array of {value, label, disabled?, icon?, avatar?} or grouped {label, options: [...]}. Alternative to declarative <option> / <optgroup> children. Per-option icon/avatar render in the list AND reflect in the trigger's selected state.",
          "$ref": "#/$defs/DynamicStringList"
        },
        "pattern": {
          "description": "Regex pattern for validation",
          "type": "string",
          "default": ""
        },
        "placeholder": {
          "description": "Placeholder when no option is selected",
          "type": "string",
          "default": "Select..."
        },
        "readonly": {
          "description": "Prevents selection changes while keeping the field focusable",
          "type": "boolean",
          "default": false
        },
        "searchable": {
          "description": "Enables a search/filter input inside the listbox",
          "type": "boolean",
          "default": false
        },
        "select-all": {
          "description": "Multi-select only. Renders a \"Select all\" / \"Clear\" control row\nabove the option list. Click selects every non-disabled option;\nwhen already all selected, click clears.\n",
          "type": "boolean",
          "default": false
        },
        "size": {
          "description": "Sizing scale via universal `[size]` attribute system (packages/web-components/styles/tokens.css). Matches Input's sizing tokens so a Select rendered alongside an Input feels coherent in a form row.",
          "type": "string",
          "enum": [
            "sm",
            "md",
            "lg"
          ],
          "default": "md"
        },
        "value": {
          "description": "Currently selected option value. With declarative <option> children, a child carrying the native `selected` attribute sets the initial value when this attribute is absent (native <select> parity).",
          "type": "string",
          "default": ""
        },
        "variant": {
          "description": "Visual variant — `default` chrome or `ghost` for inline.",
          "type": "string",
          "enum": [
            "default",
            "ghost"
          ],
          "default": "default"
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [],
        "category": "input",
        "composes": [
          "icon-ui",
          "tag-ui"
        ],
        "events": {
          "change": {
            "description": "Fired when selected value changes"
          },
          "invalid": {
            "description": "Multi-select only. Fired when a toggle is suppressed by [min] or\n[max] constraints. detail = { value, reason: 'min' | 'max' }.\n"
          }
        },
        "examples": [
          {
            "description": "Design system settings page with brand header, photo upload section, bleed/margin controls, and approval workflow.",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"Card\",\n    \"children\": [\n      \"hdr\",\n      \"photo-sec\",\n      \"settings-sec\",\n      \"ftr\"\n    ]\n  },\n  {\n    \"id\": \"hdr\",\n    \"component\": \"Header\",\n    \"children\": [\n      \"hdr-title\",\n      \"hdr-desc\"\n    ]\n  },\n  {\n    \"id\": \"hdr-title\",\n    \"component\": \"Text\",\n    \"slot\": \"heading\",\n    \"textContent\": \"Bleed Design Settings\",\n    \"variant\": \"section\"\n  },\n  {\n    \"id\": \"hdr-desc\",\n    \"component\": \"Text\",\n    \"slot\": \"description\",\n    \"textContent\": \"Configure bleed margins, upload artwork, and preview before approval.\",\n    \"variant\": \"body\"\n  },\n  {\n    \"id\": \"photo-sec\",\n    \"component\": \"Section\",\n    \"children\": [\n      \"photo-col\"\n    ]\n  },\n  {\n    \"id\": \"photo-col\",\n    \"component\": \"Column\",\n    \"children\": [\n      \"photo-label\",\n      \"photo-img\",\n      \"photo-btn\"\n    ],\n    \"gap\": \"3\"\n  },\n  {\n    \"id\": \"photo-label\",\n    \"component\": \"Text\",\n    \"textContent\": \"Artwork Upload\",\n    \"variant\": \"label\"\n  },\n  {\n    \"id\": \"photo-img\",\n    \"component\": \"Image\",\n    \"src\": \"https://picsum.photos/400/200\",\n    \"aspect\": \"2/1\"\n  },\n  {\n    \"id\": \"photo-btn\",\n    \"component\": \"Button\",\n    \"text\": \"Upload Photo\",\n    \"variant\": \"secondary\"\n  },\n  {\n    \"id\": \"settings-sec\",\n    \"component\": \"Section\",\n    \"children\": [\n      \"settings-col\"\n    ]\n  },\n  {\n    \"id\": \"settings-col\",\n    \"component\": \"Column\",\n    \"children\": [\n      \"bleed-mode\",\n      \"bleed-margin\",\n      \"bleed-unit\",\n      \"approved\"\n    ],\n    \"gap\": \"4\"\n  },\n  {\n    \"id\": \"bleed-mode\",\n    \"component\": \"Select\",\n    \"label\": \"Bleed Mode\",\n    \"name\": \"bleed-mode\",\n    \"placeholder\": \"Select mode...\"\n  },\n  {\n    \"id\": \"bleed-margin\",\n    \"component\": \"Input\",\n    \"label\": \"Bleed Margin\",\n    \"name\": \"bleed-margin\",\n    \"type\": \"number\",\n    \"placeholder\": \"e.g. 3\"\n  },\n  {\n    \"id\": \"bleed-unit\",\n    \"component\": \"Select\",\n    \"label\": \"Unit\",\n    \"name\": \"bleed-unit\",\n    \"placeholder\": \"mm\"\n  },\n  {\n    \"id\": \"approved\",\n    \"component\": \"CheckBox\",\n    \"label\": \"Approved for production\",\n    \"name\": \"approved\"\n  },\n  {\n    \"id\": \"ftr\",\n    \"component\": \"Footer\",\n    \"children\": [\n      \"preview-btn\",\n      \"apply-btn\"\n    ]\n  },\n  {\n    \"id\": \"preview-btn\",\n    \"component\": \"Button\",\n    \"text\": \"Preview\",\n    \"variant\": \"secondary\"\n  },\n  {\n    \"id\": \"apply-btn\",\n    \"component\": \"Button\",\n    \"text\": \"Apply\",\n    \"variant\": \"primary\"\n  }\n]",
            "name": "bleed-design-settings"
          },
          {
            "description": "Multi-select with chip trigger + checkbox option list (SPEC-040).",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"Card\",\n    \"children\": [\"sec\"]\n  },\n  {\n    \"id\": \"sec\",\n    \"component\": \"Section\",\n    \"children\": [\"col\"]\n  },\n  {\n    \"id\": \"col\",\n    \"component\": \"Column\",\n    \"children\": [\"tags\"],\n    \"gap\": \"3\"\n  },\n  {\n    \"id\": \"tags\",\n    \"component\": \"Select\",\n    \"multiple\": true,\n    \"selectAll\": true,\n    \"label\": \"Tags\",\n    \"name\": \"tags\",\n    \"placeholder\": \"Pick tags...\",\n    \"value\": \"urgent,backend\"\n  }\n]",
            "name": "multi-select-tags"
          },
          {
            "description": "Simple account creation form with text fields, select, and action buttons.",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"Card\",\n    \"children\": [\n      \"hdr\",\n      \"sec\",\n      \"ftr\"\n    ]\n  },\n  {\n    \"id\": \"hdr\",\n    \"component\": \"Header\",\n    \"children\": [\n      \"title\",\n      \"desc\"\n    ]\n  },\n  {\n    \"id\": \"title\",\n    \"component\": \"Text\",\n    \"slot\": \"heading\",\n    \"textContent\": \"Create Account\",\n    \"variant\": \"section\"\n  },\n  {\n    \"id\": \"desc\",\n    \"component\": \"Text\",\n    \"slot\": \"description\",\n    \"variant\": \"caption\",\n    \"textContent\": \"Fill in your details\"\n  },\n  {\n    \"id\": \"sec\",\n    \"component\": \"Section\",\n    \"children\": [\n      \"form\"\n    ]\n  },\n  {\n    \"id\": \"form\",\n    \"component\": \"Column\",\n    \"children\": [\n      \"name\",\n      \"email\",\n      \"role\"\n    ],\n    \"gap\": \"4\"\n  },\n  {\n    \"id\": \"name\",\n    \"component\": \"Input\",\n    \"label\": \"Full Name\",\n    \"placeholder\": \"Kim Granlund\",\n    \"name\": \"name\",\n    \"required\": true\n  },\n  {\n    \"id\": \"email\",\n    \"component\": \"Input\",\n    \"label\": \"Email\",\n    \"type\": \"email\",\n    \"placeholder\": \"kim@adia.health\",\n    \"name\": \"email\",\n    \"required\": true\n  },\n  {\n    \"id\": \"role\",\n    \"component\": \"Select\",\n    \"label\": \"Role\",\n    \"placeholder\": \"Choose role...\",\n    \"name\": \"role\"\n  },\n  {\n    \"id\": \"ftr\",\n    \"component\": \"Footer\",\n    \"children\": [\n      \"cancel\",\n      \"submit\"\n    ]\n  },\n  {\n    \"id\": \"cancel\",\n    \"component\": \"Button\",\n    \"text\": \"Cancel\",\n    \"variant\": \"ghost\"\n  },\n  {\n    \"id\": \"submit\",\n    \"component\": \"Button\",\n    \"text\": \"Create\",\n    \"variant\": \"primary\"\n  }\n]",
            "name": "create-form"
          }
        ],
        "keywords": [
          "select",
          "dropdown",
          "combobox",
          "autocomplete",
          "multi-select",
          "multiple",
          "chips",
          "tokens",
          "tags",
          "picker"
        ],
        "name": "UISelect",
        "related": [
          "image",
          "button",
          "input",
          "check-box",
          "upload"
        ],
        "slots": {
          "hint": {
            "description": "Override slot for hint markup richer than the plain [hint] attribute string (inline links, code spans). Renders beneath the trigger at body-subtle typography. Mutually exclusive with [hint]."
          },
          "label": {
            "description": "Label element above the trigger"
          },
          "listbox": {
            "description": "Popover container for options (role=listbox)"
          },
          "trigger": {
            "description": "Button that opens the listbox"
          }
        },
        "states": [
          {
            "description": "Default, ready for interaction.",
            "name": "idle"
          },
          {
            "description": "Non-interactive; dimmed.",
            "attribute": "disabled",
            "name": "disabled"
          }
        ],
        "status": "stable",
        "synonyms": {
          "autocomplete": [
            "combobox",
            "typeahead",
            "suggest",
            "free-text"
          ],
          "combobox": [
            "search",
            "command",
            "select",
            "autocomplete",
            "typeahead",
            "filter"
          ],
          "dropdown": [
            "popover",
            "menu",
            "select",
            "form"
          ],
          "multi-select": [
            "multiselect",
            "multi-pick",
            "chips",
            "tokens",
            "tags",
            "multiple"
          ],
          "multiple": [
            "multi-select",
            "multiselect",
            "chips",
            "select-many"
          ]
        },
        "tag": "select-ui",
        "tokens": {},
        "traits": [],
        "version": 1
      }
    },
    "SimpleContent": {
      "title": "SimpleContent",
      "description": "Module-tier article-body container. CSS-only — no JS, no state.\nSits inside <simple-shell> as the main content surface with\ntoken-correct vertical rhythm and prose-friendly max-width.\n\nCompanion to <simple-hero> (optional top strip) per ADR-0023\nbespoke shell-tier children.\n",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "component": {
          "const": "SimpleContent"
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [],
        "category": "shells",
        "composes": [],
        "events": {},
        "examples": [],
        "keywords": [
          "simple-content",
          "article",
          "body",
          "prose",
          "main-content",
          "landing-body",
          "marketing-body"
        ],
        "name": "SimpleContent",
        "related": [
          "SimpleShell",
          "SimpleHero"
        ],
        "slots": {
          "default": {
            "description": "Article body content — prose, code blocks, illustrations. Authors compose freely; <simple-content> provides only the container with sensible defaults (vertical rhythm, max-width, typography token application)."
          }
        },
        "states": [
          {
            "description": "Default, visible.",
            "name": "idle"
          }
        ],
        "status": "stable",
        "synonyms": {
          "simple-content": [
            "page-content",
            "article-body",
            "prose-container",
            "main-body"
          ]
        },
        "tag": "simple-content",
        "tokens": {},
        "traits": [],
        "version": 1
      }
    },
    "SimpleHero": {
      "title": "SimpleHero",
      "description": "Module-tier hero strip for the top of marketing / landing / error\npages. CSS-only — no JS, no state. Three named slots (heading, lede,\nactions) carry the canonical hero composition.\n\nSits inside <simple-shell> above <simple-content>. Companion to\n<simple-content> per ADR-0023 bespoke shell-tier children.\n",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "component": {
          "const": "SimpleHero"
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [],
        "category": "shells",
        "composes": [],
        "events": {},
        "examples": [],
        "keywords": [
          "simple-hero",
          "hero",
          "splash",
          "landing-hero",
          "marketing-hero",
          "intro",
          "page-title"
        ],
        "name": "SimpleHero",
        "related": [
          "SimpleShell",
          "SimpleContent"
        ],
        "slots": {
          "default": {
            "description": "Optional inline content if the named slots are insufficient."
          },
          "actions": {
            "description": "Action row (button-ui, link-ui) for primary CTAs."
          },
          "heading": {
            "description": "Large display heading (h1) — the page title."
          },
          "lede": {
            "description": "Lead paragraph below heading — short summary or CTA tagline."
          }
        },
        "states": [
          {
            "description": "Default, visible.",
            "name": "idle"
          }
        ],
        "status": "stable",
        "synonyms": {
          "simple-hero": [
            "page-hero",
            "splash-hero",
            "landing-hero",
            "intro-strip"
          ]
        },
        "tag": "simple-hero",
        "tokens": {},
        "traits": [],
        "version": 1
      }
    },
    "SimpleShell": {
      "title": "SimpleShell",
      "description": "Module-tier minimal shell for marketing / landing / error pages.\nBehavior-only orchestrator with two reflected attributes — [centered]\nfor vertical centering, [full-bleed] for dropping the max-width\nconstraint.\n\nThe 4th cluster in the bespoke shell family per ADR-0023, designed\ndeliberately small (1 host + 2 CSS-only children) to demonstrate\nthe pattern works without ceremony for thin clusters.\n\nUse cases: marketing splashes, error pages (404 / 500 / maintenance),\nthank-you pages, single-card flows (sign-in, password reset).\n",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "centered": {
          "description": "Reflected — vertically centers content in viewport.",
          "type": "boolean",
          "default": false
        },
        "component": {
          "const": "SimpleShell"
        },
        "full-bleed": {
          "description": "Reflected — drops the default max-width so content fills full viewport.",
          "type": "boolean",
          "default": false
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [],
        "category": "shells",
        "composes": [],
        "events": {},
        "examples": [],
        "keywords": [
          "simple-shell",
          "landing",
          "marketing",
          "error-page",
          "splash",
          "confirmation",
          "minimal-shell"
        ],
        "name": "SimpleShell",
        "related": [
          "SimpleHero",
          "SimpleContent",
          "AdminShell"
        ],
        "slots": {
          "default": {
            "description": "Bespoke children (<simple-hero>, <simple-content>) compose here. The author owns layout order."
          }
        },
        "states": [
          {
            "description": "Default layout — top-aligned, max-width container.",
            "name": "idle"
          },
          {
            "description": "When [centered] is set — vertically centers the content stack.",
            "name": "centered"
          },
          {
            "description": "When [full-bleed] is set — drops max-width so content fills the viewport.",
            "name": "full-bleed"
          }
        ],
        "status": "stable",
        "synonyms": {
          "simple-shell": [
            "marketing-shell",
            "landing-shell",
            "minimal-shell",
            "splash-shell",
            "error-shell"
          ]
        },
        "tag": "simple-shell",
        "tokens": {},
        "traits": [],
        "version": 1
      }
    },
    "Skeleton": {
      "title": "Skeleton",
      "description": "Placeholder shimmer for loading states. Purely presentational — animated pulse background with configurable shape via CSS sizing. Use as a structural placeholder while data loads; for zero-state messaging after loading completes use <empty-state-ui> instead.",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "component": {
          "const": "Skeleton"
        },
        "height": {
          "description": "Height of the placeholder.",
          "type": "string",
          "default": "1.2em"
        },
        "radius": {
          "description": "Border radius",
          "type": "string",
          "enum": [
            "none",
            "sm",
            "md",
            "lg",
            "full"
          ],
          "default": "sm"
        },
        "static": {
          "description": "When true, suppress the shimmer animation.",
          "type": "boolean",
          "default": false
        },
        "width": {
          "description": "Width of the placeholder.",
          "type": "string",
          "default": "100%"
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [],
        "category": "display",
        "composes": [],
        "events": {},
        "examples": [
          {
            "description": "Column of skeleton components mimicking a card layout for loading states.",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"Card\",\n    \"children\": [\n      \"hdr\",\n      \"sec\"\n    ]\n  },\n  {\n    \"id\": \"hdr\",\n    \"component\": \"Header\",\n    \"children\": [\n      \"sk-avatar\",\n      \"sk-title\"\n    ]\n  },\n  {\n    \"id\": \"sk-avatar\",\n    \"component\": \"Skeleton\",\n    \"slot\": \"icon\",\n    \"variant\": \"circle\",\n    \"width\": \"40px\",\n    \"height\": \"40px\"\n  },\n  {\n    \"id\": \"sk-title\",\n    \"component\": \"Skeleton\",\n    \"slot\": \"heading\",\n    \"variant\": \"text\",\n    \"width\": \"60%\"\n  },\n  {\n    \"id\": \"sec\",\n    \"component\": \"Section\",\n    \"children\": [\n      \"body\"\n    ]\n  },\n  {\n    \"id\": \"body\",\n    \"component\": \"Column\",\n    \"gap\": \"2\",\n    \"children\": [\n      \"sk1\",\n      \"sk2\",\n      \"sk3\",\n      \"sk4\"\n    ]\n  },\n  {\n    \"id\": \"sk1\",\n    \"component\": \"Skeleton\",\n    \"variant\": \"text\",\n    \"width\": \"100%\"\n  },\n  {\n    \"id\": \"sk2\",\n    \"component\": \"Skeleton\",\n    \"variant\": \"text\",\n    \"width\": \"90%\"\n  },\n  {\n    \"id\": \"sk3\",\n    \"component\": \"Skeleton\",\n    \"variant\": \"text\",\n    \"width\": \"95%\"\n  },\n  {\n    \"id\": \"sk4\",\n    \"component\": \"Skeleton\",\n    \"variant\": \"text\",\n    \"width\": \"70%\"\n  }\n]",
            "name": "loading-skeleton"
          }
        ],
        "keywords": [
          "skeleton",
          "loading",
          "spinner",
          "placeholder",
          "shimmer"
        ],
        "name": "UISkeleton",
        "related": [
          "EmptyState",
          "Card",
          "Table",
          "List"
        ],
        "slots": {},
        "states": [
          {
            "description": "Default, ready for interaction.",
            "name": "idle"
          }
        ],
        "status": "stable",
        "synonyms": {
          "loading": [
            "loading",
            "skeleton",
            "progress",
            "bar"
          ],
          "placeholder": [
            "loading",
            "skeleton",
            "empty"
          ],
          "shimmer": [
            "loading",
            "skeleton"
          ],
          "skeleton": [
            "loading",
            "skeleton"
          ],
          "spinner": [
            "loading",
            "skeleton",
            "progress"
          ]
        },
        "tag": "skeleton-ui",
        "tokens": {},
        "traits": [],
        "version": 1
      }
    },
    "SkipNav": {
      "title": "SkipNav",
      "description": "Accessibility utility — visually-hidden link that becomes visible on\nkeyboard focus, letting keyboard users skip past repetitive navigation\nto the main content. WCAG 2.1 Success Criterion 2.4.1 \"Bypass Blocks\".\n\nPlace as the FIRST focusable element on the page (typically inside\n`<body>` before any nav / shell chrome). Target an `id` on your main\ncontent region (commonly `#main` / `#main-content`).\n",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "component": {
          "const": "SkipNav"
        },
        "target": {
          "description": "CSS id (with leading `#`) of the main content region the link skips to.",
          "type": "string",
          "default": "#main"
        },
        "text": {
          "description": "Link label. Defaults to \"Skip to main content\"; localize per site.",
          "type": "string",
          "default": "Skip to main content"
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [
          {
            "fix": "<body><skip-nav-ui></skip-nav-ui><header>…nav…</header><main id=\"main\" tabindex=\"-1\">…</main></body>",
            "why": "The skip link comes AFTER the nav — keyboard users have already tabbed through everything you wanted them to skip.",
            "wrong": "<header>…nav…</header><skip-nav-ui></skip-nav-ui><main id=\"main\">…</main>"
          }
        ],
        "category": "utility",
        "composes": [],
        "events": {},
        "examples": [
          {
            "description": "Standard skip-nav at the top of the page.",
            "a2ui": "[\n  { \"id\": \"skip\", \"component\": \"SkipNav\", \"target\": \"#main\" }\n]\n",
            "name": "default"
          }
        ],
        "keywords": [
          "skip-nav",
          "skip-link",
          "bypass-blocks",
          "a11y",
          "accessibility",
          "keyboard-navigation"
        ],
        "name": "UISkipNav",
        "related": [
          "visually-hidden"
        ],
        "slots": {},
        "states": [
          {
            "description": "Default — link is visually hidden but focusable.",
            "name": "idle"
          },
          {
            "description": "Link is focused via keyboard and visible at the top of the viewport.",
            "attribute": ":focus-within",
            "name": "focused"
          }
        ],
        "status": "stable",
        "synonyms": {},
        "tag": "skip-nav-ui",
        "tokens": {
          "--skip-nav-bg": {
            "description": "Background of the visible (focused) skip link.",
            "default": "var(--a-accent-bg)"
          },
          "--skip-nav-fg": {
            "description": "Foreground of the visible (focused) skip link.",
            "default": "var(--a-accent-fg)"
          }
        },
        "traits": [],
        "version": 1
      }
    },
    "Slider": {
      "title": "Slider",
      "description": "Range slider with track, fill, and thumb. Supports label, suffix, and keyboard control. Form-associated.",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "required": {
          "description": "Required for validation",
          "type": "boolean",
          "default": false
        },
        "component": {
          "const": "Slider"
        },
        "disabled": {
          "description": "Disables interaction",
          "type": "boolean",
          "default": false
        },
        "dual": {
          "description": "Two-thumb range slider mode. When enabled, [lower-value] and\n[upper-value] are authoritative and [value] is ignored. The fill\nrenders between the two thumbs (not from left to thumb). Form-data\nunder [name] serializes as \"<lower>,<upper>\". Use for price filters,\ndate ranges, audio range gates, etc.",
          "type": "boolean",
          "default": false
        },
        "error": {
          "description": "Validation error",
          "type": "string",
          "default": ""
        },
        "hint": {
          "description": "§184 (v0.5.5, FEEDBACK-08 §7): small caption rendered beneath the slider track. Sets `aria-describedby` on the host so screen readers announce it as a description (distinct from `aria-label`, which comes from `label`). Does not conflict with the in-component `label`. Use for semantic clarifications a `<field-ui>` wrapper would be overkill for.",
          "type": "string",
          "default": ""
        },
        "label": {
          "description": "Label text above the slider",
          "type": "string",
          "default": ""
        },
        "lowerValue": {
          "description": "Lower thumb value (dual mode only; clamped to ≤ [upper-value]).",
          "type": "number",
          "default": 0
        },
        "max": {
          "description": "Maximum slider value",
          "type": "number",
          "default": 100
        },
        "min": {
          "description": "Minimum slider value",
          "type": "number",
          "default": 0
        },
        "name": {
          "description": "Form field name",
          "type": "string",
          "default": ""
        },
        "step": {
          "description": "Step increment between values",
          "type": "number",
          "default": 1
        },
        "suffix": {
          "description": "Value suffix text",
          "type": "string",
          "default": ""
        },
        "throttle": {
          "description": "§184 (v0.5.5, FEEDBACK-08 §4): when > 0, debounce the `input` event by this many milliseconds. Value updates + visual feedback remain immediate; only event dispatch accumulates. Pending input flushes BEFORE `change` so consumers always see input→…→input→change ordering. throttle=\"0\" (default) preserves the pre-§184 every-pointer-move-fires-input behavior. Common values: 50-100ms for palette regen / shader compile / large list reflow.",
          "type": "number",
          "default": 0
        },
        "upperValue": {
          "description": "Upper thumb value (dual mode only; clamped to ≥ [lower-value]).",
          "type": "number",
          "default": 100
        },
        "value": {
          "description": "Current slider value (single-thumb mode; ignored when [dual] is set)",
          "type": "number",
          "default": 50
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [],
        "category": "input",
        "composes": [],
        "events": {
          "change": {
            "description": "Fired when the value changes (on blur for inputs, on selection for pickers)."
          },
          "input": {
            "description": "Fired on each slider movement"
          }
        },
        "examples": [
          {
            "description": "Card with labeled slider components for adjusting values like volume, brightness, and contrast.",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"Card\",\n    \"children\": [\n      \"hdr\",\n      \"sec\"\n    ]\n  },\n  {\n    \"id\": \"hdr\",\n    \"component\": \"Header\",\n    \"children\": [\n      \"title\"\n    ]\n  },\n  {\n    \"id\": \"title\",\n    \"component\": \"Text\",\n    \"slot\": \"heading\",\n    \"textContent\": \"Audio & Display\",\n    \"variant\": \"section\"\n  },\n  {\n    \"id\": \"sec\",\n    \"component\": \"Section\",\n    \"children\": [\n      \"sliders\"\n    ]\n  },\n  {\n    \"id\": \"sliders\",\n    \"component\": \"Column\",\n    \"children\": [\n      \"volume\",\n      \"brightness\",\n      \"contrast\"\n    ],\n    \"gap\": \"6\"\n  },\n  {\n    \"id\": \"volume\",\n    \"component\": \"Slider\",\n    \"label\": \"Volume\",\n    \"min\": 0,\n    \"max\": 100,\n    \"value\": 75,\n    \"name\": \"volume\"\n  },\n  {\n    \"id\": \"brightness\",\n    \"component\": \"Slider\",\n    \"label\": \"Brightness\",\n    \"min\": 0,\n    \"max\": 100,\n    \"value\": 50,\n    \"name\": \"brightness\"\n  },\n  {\n    \"id\": \"contrast\",\n    \"component\": \"Slider\",\n    \"label\": \"Contrast\",\n    \"min\": 0,\n    \"max\": 100,\n    \"value\": 60,\n    \"name\": \"contrast\"\n  }\n]",
            "name": "slider-range"
          },
          {
            "description": "Card with color pickers, theme select, density slider, and preview area for theme customization.",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"Card\",\n    \"size\": \"lg\",\n    \"children\": [\n      \"hdr\",\n      \"sec\",\n      \"ftr\"\n    ]\n  },\n  {\n    \"id\": \"hdr\",\n    \"component\": \"Header\",\n    \"children\": [\n      \"title\",\n      \"desc\"\n    ]\n  },\n  {\n    \"id\": \"title\",\n    \"component\": \"Text\",\n    \"slot\": \"heading\",\n    \"textContent\": \"Theme Customizer\",\n    \"variant\": \"section\"\n  },\n  {\n    \"id\": \"desc\",\n    \"component\": \"Text\",\n    \"slot\": \"description\",\n    \"variant\": \"caption\",\n    \"textContent\": \"Personalize your interface appearance\"\n  },\n  {\n    \"id\": \"sec\",\n    \"component\": \"Section\",\n    \"children\": [\n      \"fields\"\n    ]\n  },\n  {\n    \"id\": \"fields\",\n    \"component\": \"Column\",\n    \"children\": [\n      \"colors-row\",\n      \"theme-select\",\n      \"density\",\n      \"preview-label\"\n    ],\n    \"gap\": \"4\"\n  },\n  {\n    \"id\": \"colors-row\",\n    \"component\": \"Row\",\n    \"children\": [\n      \"primary-color\",\n      \"accent-color\"\n    ],\n    \"gap\": \"3\"\n  },\n  {\n    \"id\": \"primary-color\",\n    \"component\": \"Input\",\n    \"label\": \"Primary Color\",\n    \"type\": \"color\",\n    \"name\": \"primaryColor\",\n    \"value\": \"#6366f1\"\n  },\n  {\n    \"id\": \"accent-color\",\n    \"component\": \"Input\",\n    \"label\": \"Accent Color\",\n    \"type\": \"color\",\n    \"name\": \"accentColor\",\n    \"value\": \"#f59e0b\"\n  },\n  {\n    \"id\": \"theme-select\",\n    \"component\": \"Select\",\n    \"label\": \"Theme\",\n    \"name\": \"theme\",\n    \"placeholder\": \"Select theme...\"\n  },\n  {\n    \"id\": \"density\",\n    \"component\": \"Slider\",\n    \"label\": \"Density\",\n    \"min\": 1,\n    \"max\": 5,\n    \"value\": 3,\n    \"name\": \"density\"\n  },\n  {\n    \"id\": \"preview-label\",\n    \"component\": \"Text\",\n    \"variant\": \"caption\",\n    \"textContent\": \"Preview will update in real time\"\n  },\n  {\n    \"id\": \"ftr\",\n    \"component\": \"Footer\",\n    \"children\": [\n      \"reset-btn\",\n      \"save-btn\"\n    ]\n  },\n  {\n    \"id\": \"reset-btn\",\n    \"component\": \"Button\",\n    \"text\": \"Reset to Default\",\n    \"variant\": \"ghost\"\n  },\n  {\n    \"id\": \"save-btn\",\n    \"component\": \"Button\",\n    \"text\": \"Save Theme\",\n    \"variant\": \"primary\"\n  }\n]",
            "name": "theme-customizer"
          }
        ],
        "keywords": [
          "slider",
          "range",
          "volume"
        ],
        "name": "UISlider",
        "related": [
          "input",
          "select",
          "button",
          "embed"
        ],
        "slots": {
          "header": {
            "description": "Wholesale override of the stamped label + value-readout header row. Use only when full custom-header markup is needed; otherwise prefer the granular `label` / `value` slots and the [label] attribute."
          },
          "hint": {
            "description": "Override slot for hint markup richer than the plain [hint] attribute string (inline links, code spans). Renders beneath the slider at body-subtle typography. Mutually exclusive with [hint]."
          },
          "label": {
            "description": "Label element above the slider"
          },
          "value": {
            "description": "Current value display"
          }
        },
        "states": [
          {
            "description": "Default, ready for interaction.",
            "name": "idle"
          },
          {
            "description": "Non-interactive; dimmed.",
            "attribute": "disabled",
            "name": "disabled"
          }
        ],
        "status": "stable",
        "synonyms": {
          "range": [
            "slider",
            "range"
          ],
          "volume": [
            "slider",
            "range",
            "music"
          ]
        },
        "tag": "slider-ui",
        "tokens": {
          "--slider-fill": {
            "description": "Filled portion / progress color (was mixed accent, now primary)"
          },
          "--slider-thumb-height": {
            "description": "Thumb pill height (track-height − 2× inset)"
          },
          "--slider-thumb-width": {
            "description": "Thumb pill width (2× thumb-height, driven by track-height)"
          },
          "--slider-track": {
            "description": "Unfilled track background color"
          },
          "--slider-track-height": {
            "description": "Full track height (scales via universal [size] attribute)"
          }
        },
        "traits": [],
        "version": 1
      }
    },
    "Spinner": {
      "title": "Spinner",
      "description": "Circular animated indicator for indeterminate loading. Renders a rotating arc, full ring, or three bouncing dots inside a sized box; the animation runs while the element is in the DOM and `[paused]` is unset. Fills the circular-spinner gap left by <skeleton-ui> (rectangular placeholder) and <progress-ui> (linear determinate bar) — use <spinner-ui> when the wait duration is unknown and the shape of the eventual content is irregular or the region is too small for a placeholder block.",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "component": {
          "const": "Spinner"
        },
        "label": {
          "description": "Accessible operation name surfaced via `aria-valuetext`. Override for context-specific labels (\"Saving\", \"Uploading\").",
          "type": "string",
          "default": "Loading"
        },
        "paused": {
          "description": "Pause the animation in-place. Useful for screenshot tests and explicit-control flows.",
          "type": "boolean",
          "default": false
        },
        "size": {
          "description": "Diameter — matches icon-ui's ladder (sm 14px, md 16px, lg 20px).",
          "type": "string",
          "enum": [
            "sm",
            "md",
            "lg"
          ],
          "default": "md"
        },
        "tone": {
          "description": "Color tone — `current` inherits parent text color (matches button label), `accent` uses brand accent, `subtle` is muted, `inverse` flips for on-accent surfaces.",
          "type": "string",
          "enum": [
            "current",
            "accent",
            "subtle",
            "inverse"
          ],
          "default": "current"
        },
        "variant": {
          "description": "Visual flavor — `arc` (rotating quarter-circle, the default glyph spinner), `ring` (full ring with one colored segment rotating around it), `dots` (three bouncing dots — animated in a left-to-right wave), `knight` (horizontal \"knight-rider\" bar — a sliding thumb that bounces back-and-forth across a track; widest variant, reads as a determinate-looking bar but is indeterminate by intent).",
          "type": "string",
          "enum": [
            "arc",
            "ring",
            "dots",
            "knight"
          ],
          "default": "arc"
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [
          {
            "fix": "{\"component\": \"Progress\", \"value\": 42, \"max\": 100}\n",
            "why": "Spinner is INDETERMINATE only. `value` and any quantitative\nprogress field belongs on Progress, not Spinner. Also \"Spin\" is\nnot a valid operation label.\n",
            "wrong": "{\"component\": \"Spinner\", \"label\": \"Spin\", \"value\": 0.42}\n"
          },
          {
            "fix": "{\"component\": \"Spinner\", \"size\": \"md\"}\n",
            "why": "Skeleton is a placeholder; rotation is not part of its contract.\nA rotating circle is a Spinner.\n",
            "wrong": "{\"component\": \"Skeleton\", \"variant\": \"circle\", \"animation\": \"rotate\"}\n"
          },
          {
            "fix": "{\"component\": \"Card\", \"children\": [\n  {\"component\": \"Spinner\", \"size\": \"lg\"}\n]}\n",
            "why": "Multiple sibling spinners in one region produce visual noise\nwithout extra information. Use one parent-level Spinner.\n",
            "wrong": "{\"component\": \"Card\", \"children\": [\n  {\"component\": \"Spinner\"},\n  {\"component\": \"Spinner\"},\n  {\"component\": \"Spinner\"}\n]}\n"
          }
        ],
        "category": "feedback",
        "composes": [],
        "events": {},
        "examples": [
          {
            "description": "Loading button — primary action with a saving spinner. The button is disabled while the operation is in progress; the spinner matches the button label color via tone=\"current\".",
            "a2ui": "[\n  {\n    \"id\": \"btn-save\",\n    \"component\": \"Button\",\n    \"text\": \"Saving\",\n    \"variant\": \"primary\",\n    \"disabled\": true,\n    \"children\": [\"sp-1\"]\n  },\n  {\n    \"id\": \"sp-1\",\n    \"component\": \"Spinner\",\n    \"size\": \"sm\",\n    \"tone\": \"current\",\n    \"label\": \"Saving\"\n  }\n]",
            "name": "button-saving"
          },
          {
            "description": "Standalone centered spinner inside a card while body content fetches.",
            "a2ui": "[\n  {\n    \"id\": \"card\",\n    \"component\": \"Card\",\n    \"children\": [\"row\"]\n  },\n  {\n    \"id\": \"row\",\n    \"component\": \"Row\",\n    \"justify\": \"center\",\n    \"align\": \"center\",\n    \"children\": [\"sp\"]\n  },\n  {\n    \"id\": \"sp\",\n    \"component\": \"Spinner\",\n    \"size\": \"lg\",\n    \"tone\": \"subtle\",\n    \"label\": \"Loading dashboard\"\n  }\n]",
            "name": "centered-card-loading"
          },
          {
            "description": "Three bouncing dots — good for chat / typing indicators.",
            "a2ui": "[\n  {\n    \"id\": \"sp\",\n    \"component\": \"Spinner\",\n    \"variant\": \"dots\",\n    \"tone\": \"subtle\",\n    \"label\": \"Assistant is typing\"\n  }\n]",
            "name": "typing-indicator"
          }
        ],
        "keywords": [
          "spinner",
          "loader",
          "loading",
          "indeterminate",
          "progress",
          "busy",
          "feedback",
          "circular"
        ],
        "name": "UISpinner",
        "related": [
          "Progress",
          "Skeleton",
          "Button",
          "EmptyState"
        ],
        "slots": {},
        "states": [
          {
            "description": "Default; animation active.",
            "name": "running"
          },
          {
            "description": "Animation frozen at the current frame.",
            "attribute": "paused",
            "name": "paused"
          },
          {
            "description": "Triggered by prefers-reduced-motion. Animation replaced with a static ellipsis. Detected via CSS, not JS.",
            "name": "reduced"
          }
        ],
        "status": "stable",
        "synonyms": {
          "busy": [
            "spinner",
            "loading"
          ],
          "indeterminate": [
            "spinner",
            "progress"
          ],
          "loader": [
            "spinner",
            "loading",
            "progress"
          ],
          "loading": [
            "spinner",
            "loading",
            "progress",
            "skeleton"
          ],
          "saving": [
            "spinner",
            "loading"
          ],
          "spinner": [
            "spinner",
            "loader",
            "progress"
          ],
          "uploading": [
            "spinner",
            "loading"
          ]
        },
        "tag": "spinner-ui",
        "tokens": {
          "--spinner-color": {
            "description": "Color of the active arc / ring / dots. Defaults to currentColor so a tone-driven cascade resolves naturally.",
            "default": "currentColor"
          },
          "--spinner-duration": {
            "description": "One full rotation duration.",
            "default": "var(--a-duration-slow)"
          },
          "--spinner-size": {
            "description": "Diameter of the spinner box.",
            "default": "1rem"
          },
          "--spinner-stroke": {
            "description": "Border thickness for the arc / ring variants.",
            "default": "2px"
          },
          "--spinner-track-opacity": {
            "description": "Opacity for the non-rotating ring track (variant=ring only).",
            "default": "0.25"
          }
        },
        "traits": [],
        "version": 1
      }
    },
    "Stack": {
      "title": "Stack",
      "description": "Grid-overlay layout primitive — children stack on TOP of each\nother in a single grid cell (z-axis layering). Distinct from\n<col-ui> (vertical) / <row-ui> (horizontal) / <grid-ui> (2D\ngrid with cells). Use stack-ui for badge overlays on avatars,\nabsolute-positioned UI on top of charts, loading spinners over\ncontent, or any case where children must occupy the same physical\nspace. [align] controls how children align within the shared\ncell.\n",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "align": {
          "description": "Alignment of the layered children within the shared cell (maps to grid place-items). `center` (default) plus eight directional keywords.",
          "type": "string",
          "enum": [
            "center",
            "top-left",
            "top",
            "top-right",
            "left",
            "right",
            "bottom-left",
            "bottom",
            "bottom-right"
          ],
          "default": "center"
        },
        "component": {
          "const": "Stack"
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [],
        "category": "layout",
        "composes": [],
        "events": {},
        "examples": [
          {
            "description": "Basic Stack usage",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"Stack\",\n    \"children\": [\n      \"child1\",\n      \"child2\"\n    ]\n  },\n  {\n    \"id\": \"child1\",\n    \"component\": \"Text\",\n    \"textContent\": \"First item\"\n  },\n  {\n    \"id\": \"child2\",\n    \"component\": \"Text\",\n    \"textContent\": \"Second item\"\n  }\n]",
            "name": "basic-stack"
          }
        ],
        "keywords": [
          "stack"
        ],
        "name": "UIStack",
        "related": [
          "Col",
          "Row",
          "Grid"
        ],
        "slots": {
          "default": {
            "description": "Default slot — primary child content."
          }
        },
        "states": [
          {
            "description": "Default, ready for interaction.",
            "name": "idle"
          }
        ],
        "status": "stable",
        "synonyms": {
          "stack": [
            "overlay-stack",
            "z-stack",
            "grid-overlay",
            "layer"
          ]
        },
        "tag": "stack-ui",
        "tokens": {},
        "traits": [],
        "version": 1
      }
    },
    "Stat": {
      "title": "Stat",
      "description": "Metric/KPI display — value + label + optional change indicator and trend icon. Renders as a stacked block with prominent value and small caption; supports positive/negative delta coloring. Use inside dashboard cards or summary headers; for inline percentages or progress use <progress-ui>.",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "bleed": {
          "description": "Horizontal-bleed KPI layout. With a `slot=\"chart\"` child, the value / label / change stack on the left while the chart fills the right column at full height and bleeds to the card's top / right / bottom edges (the horizontal counterpart to a chart in a card `<section bleed>`). No effect without a chart slot.",
          "type": "boolean",
          "default": false
        },
        "change": {
          "description": "Change indicator text (e.g. '+12%', '-3%')",
          "type": "string",
          "default": ""
        },
        "component": {
          "const": "Stat"
        },
        "icon": {
          "description": "Icon name displayed in the icon slot",
          "type": "string",
          "default": ""
        },
        "label": {
          "description": "Eyebrow label describing the metric",
          "type": "string",
          "default": ""
        },
        "loading": {
          "description": "Renders skeleton-ui shimmer placeholders in place of the value and change slots while data is fetching. Sets aria-busy=\"true\" on the host. Label and icon are preserved (they're static metadata, not fetched data). Toggle back to false when data arrives.",
          "type": "boolean",
          "default": false
        },
        "trend": {
          "description": "Trend direction or narrative subtitle. Canonical values color the change badge (up=success, down=danger, neutral/flat=muted); any other string renders as caption-style text under the primary value.",
          "type": "string",
          "default": ""
        },
        "value": {
          "description": "The primary metric value to display",
          "type": "string",
          "default": ""
        }
      },
      "required": [
        "component",
        "label",
        "value"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [],
        "category": "display",
        "composes": [
          "icon-ui",
          "skeleton-ui"
        ],
        "events": {},
        "examples": [
          {
            "description": "Basic Stat usage",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"Card\",\n    \"children\": [\n      \"sec\"\n    ]\n  },\n  {\n    \"id\": \"sec\",\n    \"component\": \"Section\",\n    \"children\": [\n      \"comp\"\n    ]\n  },\n  {\n    \"id\": \"comp\",\n    \"component\": \"Stat\",\n    \"label\": \"Example Stat\",\n    \"value\": \"\"\n  }\n]",
            "name": "basic-stat"
          }
        ],
        "keywords": [
          "stat",
          "stats",
          "statistics",
          "kpi",
          "numbers",
          "figures",
          "analytics",
          "reporting",
          "insights",
          "monitor",
          "monitoring",
          "health",
          "overview",
          "summary",
          "telemetry",
          "observability",
          "performance",
          "scoreboard"
        ],
        "name": "UIStat",
        "related": [
          "Card",
          "Badge",
          "Progress"
        ],
        "slots": {
          "change": {
            "description": "Child content region for the `change` slot."
          },
          "chart": {
            "description": "Inline sparkline / mini-chart slot. Typically a `<chart-ui slot=\"chart\" type=\"sparkline\">` positioned to the right of the value + change rows. The grid reflows to give the chart a sized right-column region; authors can use any chart type but sparklines / small bar variants read best."
          },
          "icon": {
            "description": "Icon region — single icon-ui child."
          },
          "label": {
            "description": "Label region — control label."
          },
          "value": {
            "description": "Child content region for the `value` slot."
          }
        },
        "states": [
          {
            "description": "Default, ready for interaction.",
            "name": "idle"
          }
        ],
        "status": "stable",
        "synonyms": {
          "analytics": [
            "chart",
            "dashboard",
            "metric",
            "stat",
            "leaderboard"
          ],
          "figures": [
            "stat",
            "metric",
            "chart"
          ],
          "health": [
            "dashboard",
            "metric",
            "stat",
            "progress"
          ],
          "insights": [
            "chart",
            "dashboard",
            "metric",
            "stat"
          ],
          "kpi": [
            "stat",
            "metric",
            "dashboard",
            "chart"
          ],
          "monitor": [
            "dashboard",
            "metric",
            "stat",
            "chart",
            "progress"
          ],
          "monitoring": [
            "dashboard",
            "metric",
            "stat",
            "chart",
            "progress"
          ],
          "numbers": [
            "stat",
            "metric"
          ],
          "observability": [
            "dashboard",
            "metric",
            "chart",
            "stat"
          ],
          "overview": [
            "dashboard",
            "metric",
            "stat",
            "card"
          ],
          "performance": [
            "dashboard",
            "metric",
            "chart",
            "stat",
            "progress"
          ],
          "reporting": [
            "chart",
            "dashboard",
            "metric",
            "stat",
            "table",
            "data"
          ],
          "scoreboard": [
            "leaderboard",
            "stat"
          ],
          "statistics": [
            "stat",
            "metric",
            "dashboard",
            "chart"
          ],
          "stats": [
            "stat",
            "metric",
            "dashboard",
            "chart"
          ],
          "summary": [
            "dashboard",
            "metric",
            "stat",
            "card"
          ],
          "telemetry": [
            "dashboard",
            "metric",
            "chart",
            "stat"
          ]
        },
        "tag": "stat-ui",
        "tokens": {
          "--stat-change-size": {
            "description": "Font size for the change badge"
          },
          "--stat-column-gap": {
            "description": "Horizontal gap between grid columns"
          },
          "--stat-down-fg": {
            "description": "Color for downward trend"
          },
          "--stat-icon-fg": {
            "description": "Color for the icon"
          },
          "--stat-label-fg": {
            "description": "Text color for the label"
          },
          "--stat-label-size": {
            "description": "Font size for the label"
          },
          "--stat-row-gap": {
            "description": "Vertical gap between grid rows"
          },
          "--stat-up-fg": {
            "description": "Color for upward trend"
          },
          "--stat-value-fg": {
            "description": "Text color for the primary value"
          },
          "--stat-value-size": {
            "description": "Font size for the primary value"
          },
          "--stat-value-weight": {
            "description": "Font weight for the primary value"
          }
        },
        "traits": [],
        "version": 1
      }
    },
    "Stepper": {
      "title": "Stepper",
      "description": "Wizard / process stepper — parent step index drives numbered children's complete/current/upcoming states automatically. Renders horizontally as a labeled step bar with connectors. Use for multi-step forms, onboarding, or pipelines; for read-only event history use <timeline-ui> instead.",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "component": {
          "const": "Stepper"
        },
        "orientation": {
          "description": "horizontal | vertical",
          "type": "string",
          "default": "horizontal"
        },
        "step": {
          "description": "Current step index (0-based).",
          "type": "number",
          "default": 0
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [],
        "category": "navigation",
        "composes": [
          "icon-ui"
        ],
        "events": {},
        "examples": [
          {
            "description": "Three-step wizard",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"Stepper\",\n    \"step\": 1,\n    \"children\": [\n      \"s1\",\n      \"s2\",\n      \"s3\"\n    ]\n  },\n  {\n    \"id\": \"s1\",\n    \"component\": \"StepperItem\",\n    \"text\": \"Account\"\n  },\n  {\n    \"id\": \"s2\",\n    \"component\": \"StepperItem\",\n    \"text\": \"Details\"\n  },\n  {\n    \"id\": \"s3\",\n    \"component\": \"StepperItem\",\n    \"text\": \"Review\"\n  }\n]",
            "name": "basic"
          }
        ],
        "keywords": [
          "stepper",
          "wizard",
          "steps",
          "process",
          "onboarding",
          "multi-step"
        ],
        "name": "UIStepper",
        "related": [
          "timeline-ui",
          "progress-ui"
        ],
        "slots": {
          "default": {
            "description": "Default slot — primary child content."
          }
        },
        "states": [
          {
            "description": "Default, ready for interaction.",
            "name": "idle"
          }
        ],
        "status": "stable",
        "synonyms": {
          "timeline-ui mode=steps": "stepper-ui"
        },
        "tag": "stepper-ui",
        "tokens": {},
        "traits": [],
        "version": 1
      }
    },
    "StepperItem": {
      "title": "StepperItem",
      "description": "Child of `<stepper-ui>`. One stage in a multi-step flow with status (idle | active | completed | error) + optional icon + description.",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "description": {
          "description": "Secondary description line under the label.",
          "type": "string",
          "default": ""
        },
        "component": {
          "const": "StepperItem"
        },
        "icon": {
          "description": "Optional leading Phosphor icon name; overrides the auto-stamped numeric badge.",
          "type": "string",
          "default": ""
        },
        "status": {
          "description": "Canonical stage-progress state. Mutually exclusive (prevents the\n`active && completed` footgun the prior multi-Boolean shape allowed).",
          "type": "string",
          "enum": [
            "idle",
            "active",
            "completed",
            "error"
          ],
          "default": "idle"
        },
        "text": {
          "description": "Stage label.",
          "type": "string",
          "default": ""
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [],
        "category": "navigation",
        "composes": [],
        "events": {},
        "examples": [],
        "keywords": [
          "stepper-item",
          "step",
          "wizard-step",
          "progress-step",
          "step-row"
        ],
        "name": "UIStepperItem",
        "related": [
          "Stepper",
          "Timeline",
          "StepProgress"
        ],
        "slots": {
          "description": {
            "description": "Custom description content; falls through to `[description]` prop if not slotted."
          },
          "icon": {
            "description": "Override the step-status glyph with a custom slotted element. By default the step renders a numeral / check / x indicator based on [status]; slot an `<icon-ui>` or image to customize."
          },
          "label": {
            "description": "Custom label content; falls through to `[text]` prop if not slotted."
          }
        },
        "states": [],
        "status": "stable",
        "synonyms": {
          "stepper-item": [
            "step",
            "wizard-step",
            "progress-step",
            "checkpoint"
          ]
        },
        "tag": "stepper-item-ui",
        "tokens": {},
        "traits": [],
        "version": 1
      }
    },
    "StepProgress": {
      "title": "StepProgress",
      "description": "Discrete-dash step-progress indicator. One <span> dash per step in\n[total]; the first [value] dashes are filled with --a-accent. Used\nin multi-step flows (registration, onboarding, wizards). Replaces\nthe bespoke `[data-onb-progress]` + `[data-reg-progress]` markup\nthat lived in onboarding.css + registration.css with a single\nprimitive.\n",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "caption": {
          "description": "Optional caption text rendered above the track (e.g. 'Step 3 of 10', 'Step 3 of 10 · Optional', 'All steps complete'). Hidden when empty.",
          "type": "string",
          "default": ""
        },
        "component": {
          "const": "StepProgress"
        },
        "total": {
          "description": "Total number of steps. The track renders this many dashes.",
          "type": "number",
          "default": 0
        },
        "value": {
          "description": "Number of steps completed (1-indexed). Clamped to [0, total].",
          "type": "number",
          "default": 0
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [],
        "category": "feedback",
        "composes": [],
        "events": {},
        "examples": [
          {
            "description": "3 of 10 steps complete with caption.",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"StepProgress\",\n    \"value\": 3,\n    \"total\": 10,\n    \"caption\": \"Step 3 of 10\"\n  }\n]",
            "name": "in-progress"
          },
          {
            "description": "All steps complete.",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"StepProgress\",\n    \"value\": 10,\n    \"total\": 10,\n    \"caption\": \"All steps complete\"\n  }\n]",
            "name": "complete"
          },
          {
            "description": "A 9-of-10 step that's optional.",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"StepProgress\",\n    \"value\": 9,\n    \"total\": 10,\n    \"caption\": \"Step 9 of 10 · Optional\"\n  }\n]",
            "name": "optional-step"
          }
        ],
        "keywords": [
          "progress",
          "step",
          "wizard",
          "onboarding",
          "registration",
          "multi-step",
          "indicator"
        ],
        "name": "UIStepProgress",
        "related": [
          "progress-ui",
          "stepper-ui"
        ],
        "slots": {
          "caption": {
            "description": "Optional override of the auto-minted caption (use for rich content like icon + text). When present, the [caption] attribute is ignored."
          },
          "track": {
            "description": "Optional override of the auto-minted track (rare — use only when the dash structure needs to differ)."
          }
        },
        "states": [
          {
            "description": "value=0; no dashes filled.",
            "name": "empty"
          },
          {
            "description": "0 < value < total; some dashes filled.",
            "name": "in-progress"
          },
          {
            "description": "value=total; all dashes filled.",
            "name": "complete"
          }
        ],
        "status": "stable",
        "synonyms": {
          "step": [
            "stage",
            "phase"
          ],
          "total": [
            "count",
            "length"
          ]
        },
        "tag": "step-progress-ui",
        "tokens": {},
        "traits": [],
        "version": 1
      }
    },
    "Stream": {
      "title": "Stream",
      "description": "Renders an AsyncIterable<string> as streaming text. Used for LLM output and real-time logs.",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "component": {
          "const": "Stream"
        },
        "hide-cursor": {
          "description": "When true, suppress the blinking cursor during active streaming",
          "type": "boolean",
          "default": false
        },
        "pace": {
          "description": "Milliseconds between character renders. 0 = real-time.",
          "type": "number",
          "default": 0
        },
        "streaming": {
          "description": "Read-only reflected state, true while stream is active",
          "type": "boolean",
          "default": false
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [],
        "category": "agent",
        "composes": [],
        "events": {
          "stream-end": {
            "description": "Fired when stream completes naturally"
          },
          "stream-error": {
            "description": "Fired on stream error, detail: { error }",
            "detail": {
              "error": {
                "description": "Error object or message.",
                "type": "object"
              }
            }
          },
          "stream-start": {
            "description": "Fired when streaming begins"
          }
        },
        "examples": [
          {
            "description": "AI streaming text response in a chat card.",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"Card\",\n    \"children\": [\n      \"sec\"\n    ]\n  },\n  {\n    \"id\": \"sec\",\n    \"component\": \"Section\",\n    \"children\": [\n      \"stream\"\n    ]\n  },\n  {\n    \"id\": \"stream\",\n    \"component\": \"Stream\",\n    \"children\": [\n      \"txt\"\n    ]\n  },\n  {\n    \"id\": \"txt\",\n    \"component\": \"Text\",\n    \"variant\": \"body\",\n    \"textContent\": \"Generating response...\"\n  }\n]",
            "name": "streaming-response"
          }
        ],
        "keywords": [
          "stream"
        ],
        "name": "UIStream",
        "related": [
          "ChatThreadUI",
          "Text",
          "Code"
        ],
        "slots": {
          "default": {
            "description": "Default slot — primary child content."
          }
        },
        "states": [
          {
            "description": "Default, ready for interaction.",
            "name": "idle"
          }
        ],
        "status": "stable",
        "synonyms": {
          "stream": [
            "streaming-text",
            "live-text",
            "incremental-text"
          ]
        },
        "tag": "stream-ui",
        "tokens": {
          "--stream-color": {
            "description": "Text color"
          },
          "--stream-cursor-color": {
            "description": "Blinking cursor color"
          },
          "--stream-font-family": {
            "description": "Font family"
          },
          "--stream-font-size": {
            "description": "Font size"
          },
          "--stream-line-height": {
            "description": "Line height"
          }
        },
        "traits": [],
        "version": 1
      }
    },
    "Swatch": {
      "title": "Swatch",
      "description": "Color/style swatch primitive — a small inline tile representing a single\nvisual sample. Renders as block, dot, square, line, or dashed depending on\nshape; pairs with an optional label slot or attribute. Composed by chart-\nlegend-ui's per-row swatch and consumed directly by the token-colors /\nspacing demo pages.\n",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "autoContrast": {
          "description": "When set, computes the swatch color's OKLab L and switches the label /\ndetail color between light + dark so it remains legible against the\ntile background. Active when `label-position=\"overlay\"` (where the\nlabel sits ON the tile). Uses a 1px canvas probe to handle any CSS\ncolor form (oklch / hex / hsl / named / var() references).\n",
          "type": "boolean",
          "default": false
        },
        "badge": {
          "description": "Optional marker(s) rendered in the upper-right of the tile. Single value\nOR comma/space-separated list of variants (v0.4.9+ multi-badge support).\nVariants: out-of-gamut (△), p3-only (✦), apca-pass (✓), apca-fail (✗).\nEach pip carries an aria-label so screen readers surface the semantic\n(\"Outside sRGB gamut\", \"Contrast passes APCA\", etc.). Unknown variants\nare silently dropped.\n",
          "type": "string",
          "default": ""
        },
        "color": {
          "description": "Swatch color. Accepts any CSS color value or var() reference. Sets the internal --swatch-color custom property; consumers can also set --swatch-color via inline style.",
          "type": "string",
          "default": ""
        },
        "component": {
          "const": "Swatch"
        },
        "copyable": {
          "description": "When set, renders an inline copy-to-clipboard button. Defaults to copying [color]; override via [copy-value].",
          "type": "boolean",
          "default": false
        },
        "copyValue": {
          "description": "Override what gets copied when [copyable] is set. Defaults to [color]. Not reflected (color strings are long; attr round-tripping reads poorly).",
          "type": "string",
          "default": ""
        },
        "detail": {
          "description": "Optional secondary line of text rendered below the label. Typically the raw token value (e.g. \"oklch(0.53 0.18 240)\") when the swatch represents a design-token step.",
          "type": "string",
          "default": ""
        },
        "label": {
          "description": "Optional label rendered next to (or below, for shape=\"block\") the swatch. Use the default slot for richer content.",
          "type": "string",
          "default": ""
        },
        "labelPosition": {
          "description": "§253 (v0.5.12, FB-23 §1). Position the label relative to the tile.\n`below` (default) stacks label under the tile (current shape=\"block\"\nlayout — `flex-direction: column`). `overlay` renders the label\nINSIDE the tile via absolute positioning; pair with `[auto-contrast]`\nto keep the label legible against the tile color (`data-on-light` /\n`data-on-dark` classes auto-stamped per OKLab-L probe). Only meaningful\nwhen `shape=\"block\"` (other shapes are too small for in-tile labels).\nUnblocks Tokens Studio's C1.3 dogfood migration (label-inside-the-tile\npattern; blocked 3 cycles on this design call).",
          "type": "string",
          "enum": [
            "below",
            "overlay"
          ],
          "default": "below"
        },
        "selectable": {
          "description": "When set, makes the swatch keyboard-focusable + clickable. Sets role=\"button\" + tabindex=\"0\". Dispatches a \"select\" event on activation (click / Enter / Space).",
          "type": "boolean",
          "default": false
        },
        "selected": {
          "description": "Reflected visual selected state. Pair with [selectable] to make the swatch behave like a radio-style picker. Sets aria-pressed.",
          "type": "boolean",
          "default": false
        },
        "shape": {
          "description": "Visual shape — block (filled tile), dot (small circle), square (small filled square), line (solid hairline), dashed (dashed hairline).",
          "type": "string",
          "enum": [
            "block",
            "dot",
            "square",
            "line",
            "dashed"
          ],
          "default": "square"
        },
        "size": {
          "description": "Size preset — sm / md / lg. Drives the swatch's intrinsic dimensions; lg is reserved for the token-scale demo (40 px tall).",
          "type": "string",
          "enum": [
            "sm",
            "md",
            "lg"
          ],
          "default": "md"
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [],
        "category": "display",
        "composes": [],
        "events": {
          "select": {
            "description": "Fired when a selectable swatch is activated (click / Enter / Space). detail carries the swatch's value, color, and label.",
            "detail": {
              "color": {
                "description": "The raw [color] attribute value.",
                "type": "string"
              },
              "label": {
                "description": "The [label] attribute value.",
                "type": "string"
              },
              "value": {
                "description": "The swatch's effective value — [color] when present, else [label].",
                "type": "string"
              }
            }
          }
        },
        "examples": [
          {
            "description": "A single dot swatch with text label, e.g. as a chart-legend row.",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"Swatch\",\n    \"shape\": \"dot\",\n    \"color\": \"var(--a-data-0)\",\n    \"label\": \"Revenue\"\n  }\n]",
            "name": "basic-swatch"
          },
          {
            "description": "Block swatch for a token-scale step.",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"Swatch\",\n    \"shape\": \"block\",\n    \"size\": \"lg\",\n    \"color\": \"var(--a-neutral-50)\",\n    \"label\": \"50\"\n  }\n]",
            "name": "token-block"
          }
        ],
        "keywords": [
          "swatch",
          "color",
          "chip",
          "sample",
          "palette",
          "legend",
          "step",
          "token"
        ],
        "name": "UISwatch",
        "related": [
          "chart-legend-ui",
          "tag-ui"
        ],
        "slots": {
          "default": {
            "description": "Optional rich label content. When present, replaces the [label]\nattribute's text. Consumer chrome positioned absolutely against the\nswatch tile should use `[slot=\"chrome\"]` instead — default-slot\nchildren are funneled into the label region.\n"
          },
          "chrome": {
            "description": "§-TBD (v0.5.13, FB-34 §1). Sibling-of-tile chrome — gamut badges,\noverride/tracked dots, custom indicators — that survives stamping as\na direct host sibling rather than being funneled into the label. Pair\nwith consumer-authored CSS `position: absolute` against the host\n(the host carries `position: relative` when `shape=\"block\"`, so\n`top/right/bottom/left` offsets anchor to the tile's geometry).\nCloses the C1.3 dogfood chrome-overlay composition gap.\n"
          }
        },
        "states": [
          {
            "description": "Default, ready for display.",
            "name": "idle"
          },
          {
            "description": "Reflected when the swatch is in the selected state (pair with [selectable]).",
            "attribute": "selected",
            "name": "selected"
          }
        ],
        "status": "stable",
        "synonyms": {
          "color-chip": [
            "swatch",
            "chip"
          ],
          "color-sample": [
            "swatch"
          ]
        },
        "tag": "swatch-ui",
        "tokens": {
          "--swatch-badge-fg": {
            "description": "Color of the badge symbol. Defaults to chrome-foreground; overridden per-badge variant."
          },
          "--swatch-color": {
            "description": "Resolved color of the swatch fill / line. Wins over the [color] attr if set inline."
          },
          "--swatch-detail-fg": {
            "description": "Color of the secondary detail line. Defaults to subtle-foreground."
          },
          "--swatch-select-ring": {
            "description": "Color of the focus + selected ring when [selectable] is set."
          }
        },
        "traits": [],
        "version": 1
      }
    },
    "Swiper": {
      "title": "Swiper",
      "description": "CSS-first carousel with scroll-snap. Supports autoplay, loop, and peek; JS-stamped pagination dots and paddles.",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "autoplay": {
          "description": "Enable auto-advance",
          "type": "boolean",
          "default": false
        },
        "chrome": {
          "description": "Pagination chrome layout. `default` (overlay paddles + centered dots below) or `toolbar` (header row with label + paddles, footer row with counter + dots).",
          "type": "string",
          "enum": [
            "default",
            "toolbar"
          ],
          "default": "default"
        },
        "component": {
          "const": "Swiper"
        },
        "counter": {
          "description": "When `chrome=\"toolbar\"`, show a \"current / total\" page counter in the footer (left).",
          "type": "boolean",
          "default": false
        },
        "gap": {
          "description": "Gap between slides (token: sm, md, lg)",
          "type": "string",
          "default": ""
        },
        "interval": {
          "description": "Autoplay interval in ms",
          "type": "number",
          "default": 5000
        },
        "label": {
          "description": "Title rendered in the toolbar header (left). Only used when `chrome=\"toolbar\"`.",
          "type": "string",
          "default": ""
        },
        "loop": {
          "description": "Infinite loop",
          "type": "boolean",
          "default": false
        },
        "noPauseOnHover": {
          "description": "Suppress the default pause-on-hover/focus behavior for autoplay.",
          "type": "boolean",
          "default": false
        },
        "peek": {
          "description": "Show peek of adjacent slides",
          "type": "boolean",
          "default": false
        },
        "slidesPerView": {
          "description": "Number of slides visible at once. Accepts \"1\", \"2\", \"3\", or \"auto\". Empty = CSS default (single slide).",
          "type": "string",
          "default": ""
        },
        "snap": {
          "description": "Scroll-snap alignment — start, center, end, or none.",
          "type": "string",
          "enum": [
            "start",
            "center",
            "end",
            "none"
          ],
          "default": "start"
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [],
        "category": "layout",
        "composes": [
          "button-ui"
        ],
        "events": {
          "autoplay-pause": {
            "description": "Fired on autoplay-pause.",
            "detail": {
              "reason": {
                "description": "Pause reason (\"hover\" or \"focus\").",
                "type": "string"
              }
            }
          },
          "autoplay-resume": {
            "description": "Fired on autoplay-resume."
          },
          "change": {
            "description": "Fired when the active slide changes. Detail: { index, slide }.",
            "detail": {
              "index": {
                "description": "New active slide index.",
                "type": "number"
              },
              "slide": {
                "description": "The active slide element.",
                "type": "object"
              }
            }
          }
        },
        "examples": [
          {
            "description": "Basic image carousel with 3 slides",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"Card\",\n    \"children\": [\n      \"hdr\",\n      \"sec\"\n    ]\n  },\n  {\n    \"id\": \"hdr\",\n    \"component\": \"Header\",\n    \"children\": [\n      \"title\"\n    ]\n  },\n  {\n    \"id\": \"title\",\n    \"component\": \"Text\",\n    \"slot\": \"heading\",\n    \"variant\": \"section\",\n    \"textContent\": \"Photo Gallery\"\n  },\n  {\n    \"id\": \"sec\",\n    \"component\": \"Section\",\n    \"children\": [\n      \"carousel\"\n    ]\n  },\n  {\n    \"id\": \"carousel\",\n    \"component\": \"Swiper\",\n    \"children\": [\n      \"s1\",\n      \"s2\",\n      \"s3\"\n    ],\n    \"gap\": \"md\"\n  },\n  {\n    \"id\": \"s1\",\n    \"component\": \"Image\",\n    \"src\": \"/images/photo-1.jpg\",\n    \"alt\": \"Mountain landscape\"\n  },\n  {\n    \"id\": \"s2\",\n    \"component\": \"Image\",\n    \"src\": \"/images/photo-2.jpg\",\n    \"alt\": \"Ocean sunset\"\n  },\n  {\n    \"id\": \"s3\",\n    \"component\": \"Image\",\n    \"src\": \"/images/photo-3.jpg\",\n    \"alt\": \"Forest trail\"\n  }\n]",
            "name": "image-carousel"
          },
          {
            "description": "Product cards in a peek carousel with autoplay",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"Swiper\",\n    \"children\": [\n      \"p1\",\n      \"p2\",\n      \"p3\"\n    ],\n    \"peek\": true,\n    \"slides-per-view\": \"3\",\n    \"gap\": \"md\",\n    \"autoplay\": true,\n    \"interval\": \"5000\"\n  },\n  {\n    \"id\": \"p1\",\n    \"component\": \"Card\",\n    \"children\": [\n      \"p1-sec\"\n    ]\n  },\n  {\n    \"id\": \"p1-sec\",\n    \"component\": \"Section\",\n    \"children\": [\n      \"p1-img\",\n      \"p1-name\",\n      \"p1-price\"\n    ]\n  },\n  {\n    \"id\": \"p1-img\",\n    \"component\": \"Image\",\n    \"src\": \"/images/product-1.jpg\",\n    \"alt\": \"Wireless headphones\"\n  },\n  {\n    \"id\": \"p1-name\",\n    \"component\": \"Text\",\n    \"variant\": \"label\",\n    \"textContent\": \"Wireless Headphones\"\n  },\n  {\n    \"id\": \"p1-price\",\n    \"component\": \"Text\",\n    \"variant\": \"metric\",\n    \"textContent\": \"$79.99\"\n  },\n  {\n    \"id\": \"p2\",\n    \"component\": \"Card\",\n    \"children\": [\n      \"p2-sec\"\n    ]\n  },\n  {\n    \"id\": \"p2-sec\",\n    \"component\": \"Section\",\n    \"children\": [\n      \"p2-img\",\n      \"p2-name\",\n      \"p2-price\"\n    ]\n  },\n  {\n    \"id\": \"p2-img\",\n    \"component\": \"Image\",\n    \"src\": \"/images/product-2.jpg\",\n    \"alt\": \"Smart watch\"\n  },\n  {\n    \"id\": \"p2-name\",\n    \"component\": \"Text\",\n    \"variant\": \"label\",\n    \"textContent\": \"Smart Watch\"\n  },\n  {\n    \"id\": \"p2-price\",\n    \"component\": \"Text\",\n    \"variant\": \"metric\",\n    \"textContent\": \"$199.99\"\n  },\n  {\n    \"id\": \"p3\",\n    \"component\": \"Card\",\n    \"children\": [\n      \"p3-sec\"\n    ]\n  },\n  {\n    \"id\": \"p3-sec\",\n    \"component\": \"Section\",\n    \"children\": [\n      \"p3-img\",\n      \"p3-name\",\n      \"p3-price\"\n    ]\n  },\n  {\n    \"id\": \"p3-img\",\n    \"component\": \"Image\",\n    \"src\": \"/images/product-3.jpg\",\n    \"alt\": \"Bluetooth speaker\"\n  },\n  {\n    \"id\": \"p3-name\",\n    \"component\": \"Text\",\n    \"variant\": \"label\",\n    \"textContent\": \"Bluetooth Speaker\"\n  },\n  {\n    \"id\": \"p3-price\",\n    \"component\": \"Text\",\n    \"variant\": \"metric\",\n    \"textContent\": \"$49.99\"\n  }\n]",
            "name": "product-showcase"
          }
        ],
        "keywords": [
          "carousel",
          "slider",
          "slideshow",
          "slides",
          "gallery",
          "banner",
          "swiper"
        ],
        "name": "UISwiper",
        "related": [
          "image-gallery",
          "hero-section",
          "product-card"
        ],
        "slots": {
          "default": {
            "description": "Default slot — primary child content."
          }
        },
        "states": [
          {
            "description": "Default, ready for interaction.",
            "name": "idle"
          }
        ],
        "status": "stable",
        "synonyms": {
          "carousel": [
            "swiper",
            "slide",
            "gallery",
            "banner"
          ],
          "slideshow": [
            "swiper",
            "carousel",
            "slide"
          ],
          "tags": [
            "Slideshow",
            "Carousel"
          ]
        },
        "tag": "swiper-ui",
        "tokens": {},
        "traits": [],
        "version": 1
      }
    },
    "Switch": {
      "title": "Switch",
      "description": "Toggle switch primitive — binary on/off control where the host IS\nthe control (per ADR-0025, no native <input type=\"checkbox\"> wrapped\nunderneath). Form-bearing via UIFormElement: [name], [value],\n[checked] (reflect), [required], [disabled]. Distinct from <check-ui>\n— use switch-ui for setting-style toggles (notifications on/off,\ndark mode, feature flags), check-ui for opt-in lists, terms\nacceptance, multi-select rows.\n",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "required": {
          "description": "Marks as required",
          "type": "boolean",
          "default": false
        },
        "checked": {
          "description": "Whether the toggle is on",
          "type": "boolean",
          "default": false
        },
        "component": {
          "const": "Switch"
        },
        "disabled": {
          "description": "Disables the toggle",
          "type": "boolean",
          "default": false
        },
        "hint": {
          "description": "Help text below the label",
          "type": "string",
          "default": ""
        },
        "label": {
          "description": "Label text beside the toggle",
          "type": "string",
          "default": ""
        },
        "name": {
          "description": "Form field name",
          "type": "string",
          "default": ""
        },
        "size": {
          "description": "Sizing scale (full tier — xs / sm / md / lg / xl).",
          "type": "string",
          "enum": [
            "xs",
            "sm",
            "md",
            "lg",
            "xl"
          ],
          "default": ""
        },
        "value": {
          "description": "Form value (submitted as 'on' when checked)",
          "type": "string",
          "default": ""
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [
          {
            "description": "Wrapping a switch-ui in field-ui. The widget already self-labels.",
            "right": "<switch-ui label=\"Email notifications\"></switch-ui>\n",
            "rule": "Use [label] on switch-ui directly; do not wrap in field-ui.",
            "wrong": "<field-ui inline label=\"Email notifications\">\n  <switch-ui></switch-ui>\n</field-ui>\n"
          }
        ],
        "category": "layout",
        "composes": [],
        "events": {
          "change": {
            "description": "Fired when checked state changes"
          }
        },
        "examples": [
          {
            "description": "Notification preferences card with toggle switches for different notification channels and types.",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"Card\",\n    \"children\": [\n      \"hdr\",\n      \"sec\"\n    ]\n  },\n  {\n    \"id\": \"hdr\",\n    \"component\": \"Header\",\n    \"children\": [\n      \"title\",\n      \"desc\"\n    ]\n  },\n  {\n    \"id\": \"title\",\n    \"component\": \"Text\",\n    \"slot\": \"heading\",\n    \"variant\": \"span\",\n    \"textContent\": \"Notification Preferences\"\n  },\n  {\n    \"id\": \"desc\",\n    \"component\": \"Text\",\n    \"slot\": \"description\",\n    \"textContent\": \"Choose how you want to be notified\"\n  },\n  {\n    \"id\": \"sec\",\n    \"component\": \"Section\",\n    \"children\": [\n      \"list\"\n    ]\n  },\n  {\n    \"id\": \"list\",\n    \"component\": \"Column\",\n    \"gap\": \"4\",\n    \"children\": [\n      \"r1\",\n      \"r2\",\n      \"r3\",\n      \"r4\",\n      \"r5\"\n    ]\n  },\n  {\n    \"id\": \"r1\",\n    \"component\": \"Row\",\n    \"gap\": \"3\",\n    \"align\": \"center\",\n    \"children\": [\n      \"info1\",\n      \"sw1\"\n    ]\n  },\n  {\n    \"id\": \"info1\",\n    \"component\": \"Column\",\n    \"gap\": \"0\",\n    \"grow\": true,\n    \"children\": [\n      \"label1\",\n      \"hint1\"\n    ]\n  },\n  {\n    \"id\": \"label1\",\n    \"component\": \"Text\",\n    \"weight\": \"semibold\",\n    \"textContent\": \"Email Notifications\"\n  },\n  {\n    \"id\": \"hint1\",\n    \"component\": \"Text\",\n    \"color\": \"muted\",\n    \"textContent\": \"Receive updates via email\"\n  },\n  {\n    \"id\": \"sw1\",\n    \"component\": \"Switch\",\n    \"checked\": true\n  },\n  {\n    \"id\": \"r2\",\n    \"component\": \"Row\",\n    \"gap\": \"3\",\n    \"align\": \"center\",\n    \"children\": [\n      \"info2\",\n      \"sw2\"\n    ]\n  },\n  {\n    \"id\": \"info2\",\n    \"component\": \"Column\",\n    \"gap\": \"0\",\n    \"grow\": true,\n    \"children\": [\n      \"label2\",\n      \"hint2\"\n    ]\n  },\n  {\n    \"id\": \"label2\",\n    \"component\": \"Text\",\n    \"weight\": \"semibold\",\n    \"textContent\": \"Push Notifications\"\n  },\n  {\n    \"id\": \"hint2\",\n    \"component\": \"Text\",\n    \"color\": \"muted\",\n    \"textContent\": \"Browser and mobile push alerts\"\n  },\n  {\n    \"id\": \"sw2\",\n    \"component\": \"Switch\",\n    \"checked\": true\n  },\n  {\n    \"id\": \"r3\",\n    \"component\": \"Row\",\n    \"gap\": \"3\",\n    \"align\": \"center\",\n    \"children\": [\n      \"info3\",\n      \"sw3\"\n    ]\n  },\n  {\n    \"id\": \"info3\",\n    \"component\": \"Column\",\n    \"gap\": \"0\",\n    \"grow\": true,\n    \"children\": [\n      \"label3\",\n      \"hint3\"\n    ]\n  },\n  {\n    \"id\": \"label3\",\n    \"component\": \"Text\",\n    \"weight\": \"semibold\",\n    \"textContent\": \"Marketing Emails\"\n  },\n  {\n    \"id\": \"hint3\",\n    \"component\": \"Text\",\n    \"color\": \"muted\",\n    \"textContent\": \"Product updates and announcements\"\n  },\n  {\n    \"id\": \"sw3\",\n    \"component\": \"Switch\"\n  },\n  {\n    \"id\": \"r4\",\n    \"component\": \"Row\",\n    \"gap\": \"3\",\n    \"align\": \"center\",\n    \"children\": [\n      \"info4\",\n      \"sw4\"\n    ]\n  },\n  {\n    \"id\": \"info4\",\n    \"component\": \"Column\",\n    \"gap\": \"0\",\n    \"grow\": true,\n    \"children\": [\n      \"label4\",\n      \"hint4\"\n    ]\n  },\n  {\n    \"id\": \"label4\",\n    \"component\": \"Text\",\n    \"weight\": \"semibold\",\n    \"textContent\": \"Security Alerts\"\n  },\n  {\n    \"id\": \"hint4\",\n    \"component\": \"Text\",\n    \"color\": \"muted\",\n    \"textContent\": \"Login attempts and password changes\"\n  },\n  {\n    \"id\": \"sw4\",\n    \"component\": \"Switch\",\n    \"checked\": true\n  },\n  {\n    \"id\": \"r5\",\n    \"component\": \"Row\",\n    \"gap\": \"3\",\n    \"align\": \"center\",\n    \"children\": [\n      \"info5\",\n      \"sw5\"\n    ]\n  },\n  {\n    \"id\": \"info5\",\n    \"component\": \"Column\",\n    \"gap\": \"0\",\n    \"grow\": true,\n    \"children\": [\n      \"label5\",\n      \"hint5\"\n    ]\n  },\n  {\n    \"id\": \"label5\",\n    \"component\": \"Text\",\n    \"weight\": \"semibold\",\n    \"textContent\": \"Weekly Digest\"\n  },\n  {\n    \"id\": \"hint5\",\n    \"component\": \"Text\",\n    \"color\": \"muted\",\n    \"textContent\": \"Summary of activity each week\"\n  },\n  {\n    \"id\": \"sw5\",\n    \"component\": \"Switch\"\n  }\n]",
            "name": "notification-preferences"
          }
        ],
        "keywords": [
          "switch"
        ],
        "name": "UISwitch",
        "related": [
          "Check",
          "Radio",
          "Field"
        ],
        "slots": {
          "hint": {
            "description": "Help text below the label"
          },
          "label": {
            "description": "Label text beside the toggle"
          },
          "thumb": {
            "description": "Sliding thumb indicator inside track"
          },
          "track": {
            "description": "Toggle track container (holds thumb)"
          }
        },
        "states": [
          {
            "description": "Default, ready for interaction.",
            "name": "idle"
          },
          {
            "description": "Non-interactive; dimmed.",
            "attribute": "disabled",
            "name": "disabled"
          }
        ],
        "status": "stable",
        "synonyms": {
          "tags": [
            "Toggle",
            "Switch"
          ]
        },
        "tag": "switch-ui",
        "tokens": {
          "--toggle-thumb-background": {
            "description": "Thumb color"
          },
          "--toggle-thumb-size": {
            "description": "Thumb diameter"
          },
          "--toggle-track-background": {
            "description": "Unchecked track color"
          },
          "--toggle-track-checked": {
            "description": "Checked track color"
          },
          "--toggle-track-height": {
            "description": "Track height"
          },
          "--toggle-track-width": {
            "description": "Track width"
          }
        },
        "traits": [],
        "version": 1
      }
    },
    "Tab": {
      "title": "Tab",
      "description": "Child of <tabs-ui>. One tab panel — the tab BUTTON is rendered by the parent from this child's text/icon. Wraps panel content as light DOM.",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "component": {
          "const": "Tab"
        },
        "disabled": {
          "description": "Whether the tab is selectable.",
          "type": "boolean",
          "default": false
        },
        "icon": {
          "description": "Optional leading icon name (Phosphor) for the tab button.",
          "type": "string"
        },
        "text": {
          "description": "Tab button label (rendered by parent <tabs-ui>).",
          "type": "string"
        },
        "value": {
          "description": "Stable id for the tab. Parent uses this to coordinate active state.",
          "type": "string"
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [],
        "category": "navigation",
        "composes": [],
        "events": {},
        "examples": [],
        "keywords": [
          "tab",
          "tab-panel",
          "view-switcher-child",
          "tabs-child"
        ],
        "name": "UITab",
        "related": [
          "Tabs",
          "Nav",
          "Segmented"
        ],
        "slots": {},
        "states": [],
        "status": "stable",
        "synonyms": {
          "tab": [
            "view-tab",
            "switcher-tab"
          ]
        },
        "tag": "tab-ui",
        "tokens": {},
        "traits": [],
        "version": 1
      }
    },
    "Table": {
      "title": "Table",
      "description": "Data table with sorting, selection, pagination, search, column resize, keyboard nav, cell types, and CSV export. CSS grid + ARIA grid roles.",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "columns": {
          "description": "Column definitions. Array of {key, label, type?, width?, minWidth?, maxWidth?, flex?, sortable?, resizable?, filterable?, pinned?, hidden?, wrap?, accessor?, format?, render?, sortFn?, filterType?, meta?}. Alternative to declarative <col-def> children.",
          "$ref": "#/$defs/DynamicStringList"
        },
        "component": {
          "const": "Table"
        },
        "data": {
          "description": "Row records. Array of plain objects keyed to columns[].key.",
          "$ref": "#/$defs/DynamicStringList"
        },
        "density": {
          "description": "Controls cell padding and row height. 'compact' for dense data, 'standard' for default spacing, 'comfortable' for spacious rows.",
          "type": "string",
          "enum": [
            "compact",
            "standard",
            "comfortable"
          ],
          "default": "standard"
        },
        "expandable": {
          "description": "Enable row expansion",
          "type": "boolean",
          "default": false
        },
        "loading": {
          "description": "Renders N ghost skeleton rows in place of the body data (count derived from `paginate` if set, else 5). Header + columns stay intact so the table layout is preserved while data fetches. Sets aria-busy=\"true\" on the host. Data updates are deferred until loading is set back to false.",
          "type": "boolean",
          "default": false
        },
        "paginate": {
          "description": "Rows per page. 0 = show all rows without pagination. When > 0, renders a pagination bar below the table.",
          "type": "number",
          "default": 0
        },
        "raw": {
          "description": "Visual-only passthrough — applies `<table-ui>`'s chrome reset (background / border / border-radius all transparent) AND short-circuits the data lifecycle entirely. The consumer owns the body shape: no header injection, no row reconciliation from `.data`, no empty-state / loading overlays, no aggregation or pagination footers. Use raw when embedding `<table-ui>` inside surfaces that supply their own chrome (e.g. `<card-ui><section bleed>`), or when wrapping a consumer-authored native `<table>` for design-token styling without the framework's data semantics. Pre-v0.6.33 (FB-53 §2) `raw` was visual-only and the data lifecycle still ran — wrapping a `.data`-unset native table produced a phantom \"No data\" overlay. v0.6.33+ matches the documented contract.",
          "type": "boolean",
          "default": false
        },
        "search": {
          "description": "Global search/filter string. Filters visible rows across all columns using case-insensitive substring matching. Resets to page 1 on change.",
          "type": "string",
          "default": ""
        },
        "selectable": {
          "description": "Show checkbox column for row selection. Select-all checkbox in header. Shift+click for range select.",
          "type": "boolean",
          "default": false
        },
        "sortable": {
          "description": "Enable click-to-sort on column headers. Supports multi-sort via Shift+click.",
          "type": "boolean",
          "default": false
        },
        "striped": {
          "description": "Alternate row background colors for visual scanning.",
          "type": "boolean",
          "default": false
        },
        "wrap": {
          "description": "Allow body-cell content to wrap onto multiple lines. Default is single-line with ellipsis truncation (matches the row convention shared by <select-ui> + <nav-item-ui>); long unbreakable strings clip gracefully rather than rewrapping the row. With [wrap], row height auto-grows to fit wrapped content. For surgical opt-in on a single column, set [data-wrap] on the cell / col-def instead.",
          "type": "boolean",
          "default": false
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [
          {
            "fix": "<table-ui paginate=\"25\"></table-ui>",
            "why": "[virtual] is not a recognized prop. The attribute is silently accepted (custom elements ignore unknown attributes) but has no effect — all rows are still rendered to the DOM. Common cross-framework instinct (AG Grid / TanStack / lit-virtualizer) that does not transfer to table-ui.",
            "wrong": "<table-ui virtual></table-ui>"
          }
        ],
        "category": "agent",
        "composes": [
          "check-ui",
          "icon-ui",
          "progress-ui",
          "pagination-ui",
          "skeleton-ui",
          "badge-ui"
        ],
        "events": {
          "cell-click": {
            "description": "Fired when a data cell is clicked. detail carries the cell location + value.",
            "detail": {
              "dataIndex": {
                "description": "Row index in the underlying data array.",
                "type": "number"
              },
              "key": {
                "description": "Column key.",
                "type": "string"
              },
              "row": {
                "description": "Row data object.",
                "type": "object"
              },
              "value": {
                "description": "Cell value (type depends on column)."
              }
            }
          },
          "filter-change": {
            "description": "Fired when an interactive filter row applies / clears. detail.filters is the current filter map.",
            "detail": {
              "filters": {
                "description": "Map of `{ [columnKey]: filterValue }` reflecting active filters.",
                "type": "object"
              }
            }
          },
          "page": {
            "description": "Fired when the user navigates to a different page.",
            "detail": {
              "page": {
                "description": "New active page index (1-based).",
                "type": "number"
              }
            }
          },
          "resize": {
            "description": "Fired when a column is resized via drag.",
            "detail": {
              "key": {
                "description": "Column key being resized.",
                "type": "string"
              },
              "width": {
                "description": "New column width in pixels.",
                "type": "number"
              }
            }
          },
          "row-click": {
            "description": "Fired once when any cell in a data row is clicked — the row-level companion to cell-click. Use it for master-detail / open-flyout wiring.",
            "detail": {
              "dataIndex": {
                "description": "Row index in the underlying data array.",
                "type": "number"
              },
              "row": {
                "description": "Row data object.",
                "type": "object"
              }
            }
          },
          "row-collapse": {
            "description": "Fired when an already-expanded row's caret is activated (collapses the row). Mirror of row-expand.",
            "detail": {
              "index": {
                "description": "Row index in the underlying data array.",
                "type": "number"
              },
              "row": {
                "description": "Row data object.",
                "type": "object"
              }
            }
          },
          "row-expand": {
            "description": "Fired when an expandable row's caret is activated. detail.index is the row position; detail.row is the row data.",
            "detail": {
              "index": {
                "description": "Row index in the underlying data array.",
                "type": "number"
              },
              "row": {
                "description": "Row data object.",
                "type": "object"
              }
            }
          },
          "select": {
            "description": "Fired when row selection changes. detail.selected is an array of row indices or IDs.",
            "detail": {
              "selected": {
                "description": "Array of selected row indices or IDs (driven by [select-mode]).",
                "type": "array"
              }
            }
          },
          "sort": {
            "description": "Fired when sort state changes via header click.",
            "detail": {
              "dir": {
                "description": "Sort direction — \"asc\" / \"desc\" / null (cleared). The detail field is `dir` (not `direction`).",
                "type": "string"
              },
              "key": {
                "description": "Column key being sorted — the detail field is `key` (not `column`).",
                "type": "string"
              },
              "sortState": {
                "description": "Full sort state array (multi-column support).",
                "type": "array"
              }
            }
          }
        },
        "examples": [
          {
            "description": "API key management table with actions and status badges.",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"Card\",\n    \"children\": [\n      \"hdr\",\n      \"sec\"\n    ]\n  },\n  {\n    \"id\": \"hdr\",\n    \"component\": \"Header\",\n    \"children\": [\n      \"title\",\n      \"add\"\n    ]\n  },\n  {\n    \"id\": \"title\",\n    \"component\": \"Text\",\n    \"slot\": \"heading\",\n    \"textContent\": \"API Keys\"\n  },\n  {\n    \"id\": \"add\",\n    \"component\": \"Button\",\n    \"slot\": \"action\",\n    \"text\": \"Create Key\",\n    \"variant\": \"primary\",\n    \"size\": \"sm\"\n  },\n  {\n    \"id\": \"sec\",\n    \"component\": \"Section\",\n    \"children\": [\n      \"tbl\"\n    ]\n  },\n  {\n    \"id\": \"tbl\",\n    \"component\": \"Table\",\n    \"sortable\": true,\n    \"columns\": [\n      {\n        \"key\": \"name\",\n        \"label\": \"Name\",\n        \"sortable\": true\n      },\n      {\n        \"key\": \"key\",\n        \"label\": \"Key\"\n      },\n      {\n        \"key\": \"created\",\n        \"label\": \"Created\",\n        \"sortable\": true\n      },\n      {\n        \"key\": \"lastUsed\",\n        \"label\": \"Last Used\",\n        \"sortable\": true\n      },\n      {\n        \"key\": \"status\",\n        \"label\": \"Status\",\n        \"component\": \"Badge\"\n      }\n    ],\n    \"rows\": [\n      {\n        \"name\": \"Production API\",\n        \"key\": \"sk-****-****-3a7f\",\n        \"created\": \"2025-01-15\",\n        \"lastUsed\": \"2025-04-16\",\n        \"status\": {\n          \"text\": \"Active\",\n          \"variant\": \"success\"\n        }\n      },\n      {\n        \"name\": \"Staging API\",\n        \"key\": \"sk-****-****-9b2e\",\n        \"created\": \"2025-03-01\",\n        \"lastUsed\": \"2025-04-10\",\n        \"status\": {\n          \"text\": \"Active\",\n          \"variant\": \"success\"\n        }\n      },\n      {\n        \"name\": \"Legacy Client\",\n        \"key\": \"sk-****-****-5d1c\",\n        \"created\": \"2024-06-20\",\n        \"lastUsed\": \"2024-12-01\",\n        \"status\": {\n          \"text\": \"Revoked\",\n          \"variant\": \"danger\"\n        }\n      }\n    ]\n  }\n]",
            "name": "api-key-table"
          },
          {
            "description": "Card with header containing title and search input, table component, and pagination footer.",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"Card\",\n    \"size\": \"lg\",\n    \"children\": [\n      \"hdr\",\n      \"sec\",\n      \"ftr\"\n    ]\n  },\n  {\n    \"id\": \"hdr\",\n    \"component\": \"Header\",\n    \"children\": [\n      \"title-row\"\n    ]\n  },\n  {\n    \"id\": \"title-row\",\n    \"component\": \"Row\",\n    \"children\": [\n      \"title\",\n      \"search\"\n    ],\n    \"gap\": \"4\"\n  },\n  {\n    \"id\": \"title\",\n    \"component\": \"Text\",\n    \"slot\": \"heading\",\n    \"textContent\": \"Data Table\",\n    \"variant\": \"section\"\n  },\n  {\n    \"id\": \"search\",\n    \"component\": \"Input\",\n    \"placeholder\": \"Search...\",\n    \"type\": \"search\",\n    \"name\": \"search\"\n  },\n  {\n    \"id\": \"sec\",\n    \"component\": \"Section\",\n    \"children\": [\n      \"tbl\"\n    ]\n  },\n  {\n    \"id\": \"tbl\",\n    \"component\": \"Table\",\n    \"sortable\": true\n  },\n  {\n    \"id\": \"ftr\",\n    \"component\": \"Footer\",\n    \"children\": [\n      \"pager\"\n    ]\n  },\n  {\n    \"id\": \"pager\",\n    \"component\": \"Pagination\",\n    \"totalPages\": 10,\n    \"currentPage\": 1\n  }\n]",
            "name": "data-table-view"
          }
        ],
        "keywords": [
          "table",
          "order",
          "invoice",
          "reporting",
          "spreadsheet",
          "grid",
          "listing",
          "records",
          "database",
          "csv",
          "excel",
          "rows",
          "columns",
          "datatable",
          "directory",
          "admin",
          "backoffice",
          "console",
          "crm",
          "paginate",
          "import",
          "export",
          "download",
          "billing",
          "api",
          "leaderboard",
          "ranking",
          "inventory",
          "stock",
          "warehouse",
          "supply",
          "log",
          "audit",
          "history",
          "file-manager",
          "files",
          "assets",
          "management",
          "manage"
        ],
        "name": "UITable",
        "related": [
          "button",
          "input",
          "pagination"
        ],
        "slots": {},
        "states": [
          {
            "description": "Default, ready for interaction.",
            "name": "idle"
          }
        ],
        "status": "stable",
        "synonyms": {
          "admin": [
            "dashboard",
            "table",
            "data",
            "sidebar",
            "nav",
            "settings"
          ],
          "api": [
            "api",
            "key",
            "table",
            "code"
          ],
          "assets": [
            "data",
            "table",
            "file",
            "image",
            "gallery"
          ],
          "audit": [
            "team",
            "activity",
            "table",
            "data"
          ],
          "backoffice": [
            "dashboard",
            "table",
            "data",
            "sidebar",
            "settings"
          ],
          "billing": [
            "pricing",
            "tier",
            "table"
          ],
          "columns": [
            "split",
            "grid",
            "table"
          ],
          "console": [
            "dashboard",
            "table",
            "data",
            "sidebar",
            "command"
          ],
          "crm": [
            "dashboard",
            "table",
            "data",
            "user",
            "profile",
            "chart"
          ],
          "csv": [
            "table",
            "data",
            "import"
          ],
          "database": [
            "table",
            "data",
            "import"
          ],
          "datatable": [
            "table",
            "data"
          ],
          "directory": [
            "team",
            "avatar",
            "group",
            "table",
            "data"
          ],
          "download": [
            "data",
            "table",
            "file"
          ],
          "excel": [
            "table",
            "data",
            "import"
          ],
          "export": [
            "data",
            "table",
            "download"
          ],
          "file-manager": [
            "data",
            "table",
            "file",
            "upload"
          ],
          "files": [
            "data",
            "table",
            "file",
            "upload"
          ],
          "grid": [
            "table",
            "data",
            "card",
            "image",
            "feature",
            "grid"
          ],
          "history": [
            "team",
            "activity",
            "table"
          ],
          "import": [
            "data",
            "import",
            "file",
            "upload",
            "table"
          ],
          "inventory": [
            "inventory",
            "table",
            "product",
            "data"
          ],
          "invoice": [
            "table",
            "data",
            "pricing"
          ],
          "leaderboard": [
            "leaderboard",
            "table",
            "rank"
          ],
          "listing": [
            "table",
            "data",
            "list"
          ],
          "log": [
            "team",
            "activity",
            "table",
            "data"
          ],
          "manage": [
            "project",
            "board",
            "kanban",
            "team",
            "dashboard",
            "settings",
            "table"
          ],
          "management": [
            "project",
            "board",
            "kanban",
            "team",
            "activity",
            "settings",
            "dashboard",
            "table"
          ],
          "order": [
            "table",
            "data",
            "inventory",
            "form"
          ],
          "paginate": [
            "pagination",
            "nav",
            "table"
          ],
          "ranking": [
            "leaderboard",
            "table"
          ],
          "records": [
            "table",
            "data"
          ],
          "reporting": [
            "chart",
            "dashboard",
            "metric",
            "stat",
            "table",
            "data"
          ],
          "rows": [
            "table",
            "data"
          ],
          "spreadsheet": [
            "table",
            "data"
          ],
          "stock": [
            "inventory",
            "table",
            "product"
          ],
          "supply": [
            "inventory",
            "table"
          ],
          "warehouse": [
            "inventory",
            "table"
          ]
        },
        "tag": "table-ui",
        "tokens": {
          "--table-accent": {
            "description": "Accent color for checkboxes and focus"
          },
          "--table-border-color": {
            "description": "Row/cell border color"
          },
          "--table-border-width": {
            "description": "Border width"
          },
          "--table-font-family": {
            "description": "Font family"
          },
          "--table-font-size": {
            "description": "Body font size"
          },
          "--table-foreground": {
            "description": "Body text color"
          },
          "--table-heading-background": {
            "description": "Header row background"
          },
          "--table-heading-color": {
            "description": "Header text color"
          },
          "--table-heading-size": {
            "description": "Header font size"
          },
          "--table-heading-weight": {
            "description": "Header font weight"
          },
          "--table-loading-overlay": {
            "description": "Loading overlay background"
          },
          "--table-padding-x": {
            "description": "Horizontal cell padding"
          },
          "--table-padding-y": {
            "description": "Vertical cell padding"
          },
          "--table-radius": {
            "description": "Border-radius for table container"
          },
          "--table-resize-handle-color": {
            "description": "Column resize drag handle color"
          },
          "--table-resize-handle-width": {
            "description": "Resize handle hit area width"
          },
          "--table-row-background": {
            "description": "Default row background"
          },
          "--table-row-background-hover": {
            "description": "Row hover background"
          },
          "--table-row-background-selected": {
            "description": "Selected row background"
          },
          "--table-row-background-striped": {
            "description": "Alternate row background"
          },
          "--table-search-highlight": {
            "description": "Search match highlight color"
          },
          "--table-sort-indicator-color": {
            "description": "Sort arrow color"
          },
          "--table-transition": {
            "description": "Transition timing"
          }
        },
        "traits": [],
        "version": 1
      }
    },
    "TableOfContents": {
      "title": "TableOfContents",
      "description": "Auto-generated in-page table of contents. Scans a target container\nfor headings (default `h2,h3`), ensures each has an `id` (slugifies\nthe text content if missing), and stamps a `<nav>` list of anchor\nlinks. An `IntersectionObserver` tracks the active heading and\napplies `[data-active]` to the matching link so consumers can style\nthe currently-visible section. Smooth-scroll on click is handled by\nthe global `scroll-behavior: smooth` set in resets.css.\n\nPair with a sticky container (`position: sticky; top: <offset>;`) in\nan aside / right rail for the classic docs-site outline pattern.\n",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "component": {
          "const": "TableOfContents"
        },
        "headings": {
          "description": "CSS selector listing the heading tags to include (e.g. `h2,h3`).\nThe selector is matched against the target container's\ndescendants. Default `h2,h3` produces the common two-level\noutline.\n",
          "type": "string",
          "default": "h2,h3"
        },
        "label": {
          "description": "`aria-label` for the nav. Defaults to `Table of contents`.\n",
          "type": "string",
          "default": "Table of contents"
        },
        "offset": {
          "description": "Top offset in pixels for active-state detection. The\nIntersectionObserver's `rootMargin` is set to\n`-<offset>px 0px -50% 0px` so the active item becomes the\nheading nearest the top of the viewport BELOW any sticky header\nchrome. Tune to match the height of your sticky topbar (default\n`80` is a reasonable docs-shell value).\n",
          "type": "number",
          "default": 80
        },
        "target": {
          "description": "CSS selector pointing to the container to scan. Empty (default)\nscans the toc-ui's parent element. Set to `#article` /\n`[data-toc-target]` / `main` for a specific scope.\n",
          "type": "string",
          "default": ""
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [
          {
            "fix": "<toc-ui target=\"#article\"></toc-ui>\n<article id=\"article\">\n  <h2>...</h2><h3>...</h3>\n</article>\n",
            "why": "toc-ui's default scans its PARENT for headings. If toc-ui is a\nsibling of the content (not inside it), the scan finds the\nheadings inside the toc-ui's parent which usually means the\nheadings + the toc itself — works only by coincidence. Set\n[target] explicitly for clarity.\n",
            "wrong": "<toc-ui></toc-ui>\n<h2>...</h2><h3>...</h3>\n"
          }
        ],
        "category": "navigation",
        "composes": [],
        "events": {
          "section-change": {
            "description": "Fired when the active heading changes (the user scrolls into a new section). Detail carries the new active id.",
            "detail": {
              "activeId": "string"
            }
          }
        },
        "examples": [
          {
            "description": "TOC scanning the parent container.",
            "a2ui": "[\n  {\n    \"id\": \"page\",\n    \"component\": \"Section\",\n    \"children\": [\"toc\", \"h1\", \"h2-1\", \"p-1\", \"h2-2\", \"p-2\"]\n  },\n  {\"id\": \"toc\",  \"component\": \"TableOfContents\"},\n  {\"id\": \"h1\",   \"component\": \"Text\", \"variant\": \"title\", \"textContent\": \"Article title\"},\n  {\"id\": \"h2-1\", \"component\": \"Text\", \"variant\": \"heading\", \"textContent\": \"Introduction\"},\n  {\"id\": \"p-1\",  \"component\": \"Text\", \"textContent\": \"...\"},\n  {\"id\": \"h2-2\", \"component\": \"Text\", \"variant\": \"heading\", \"textContent\": \"Conclusion\"},\n  {\"id\": \"p-2\",  \"component\": \"Text\", \"textContent\": \"...\"}\n]\n",
            "name": "default"
          },
          {
            "description": "TOC scanning a specific article container.",
            "a2ui": "[\n  {\n    \"id\": \"shell\",\n    \"component\": \"Row\",\n    \"children\": [\"toc\", \"article\"]\n  },\n  {\n    \"id\": \"toc\",\n    \"component\": \"TableOfContents\",\n    \"target\": \"#main-article\",\n    \"headings\": \"h2,h3,h4\"\n  },\n  {\n    \"id\": \"article\",\n    \"component\": \"Section\",\n    \"attrs\": { \"id\": \"main-article\" },\n    \"children\": []\n  }\n]\n",
            "name": "targeted"
          }
        ],
        "keywords": [
          "toc",
          "table-of-contents",
          "outline",
          "sub-nav",
          "page-nav",
          "in-page-nav",
          "heading-nav"
        ],
        "name": "UITableOfContents",
        "related": [
          "aside",
          "nav",
          "link",
          "text"
        ],
        "slots": {
          "default": {
            "description": "Stamped automatically — a `<nav>` containing a flat `<ul>` of `<a href=\"#id\">` links. Override by authoring your own content; auto-stamp is skipped when a `<nav>` is already present."
          }
        },
        "states": [
          {
            "description": "Default — no active section yet.",
            "name": "idle"
          },
          {
            "description": "A section is in view; the matching `<a>` carries `[data-active]`.",
            "attribute": "data-active",
            "name": "active"
          }
        ],
        "status": "stable",
        "synonyms": {
          "outline": [
            "toc",
            "table-of-contents"
          ],
          "toc": [
            "table-of-contents",
            "outline"
          ]
        },
        "tag": "toc-ui",
        "tokens": {
          "--toc-fg": {
            "description": "Default link color.",
            "default": "var(--a-fg-muted)"
          },
          "--toc-fg-active": {
            "description": "Active-link color.",
            "default": "var(--a-fg)"
          },
          "--toc-fg-hover": {
            "description": "Hover color.",
            "default": "var(--a-fg)"
          },
          "--toc-gap": {
            "description": "Vertical gap between links.",
            "default": "var(--a-space-1)"
          },
          "--toc-indent": {
            "description": "Per-depth-level indent.",
            "default": "var(--a-space-3)"
          },
          "--toc-padding-block": {
            "description": "Per-link block padding (top/bottom).",
            "default": "var(--a-space-1)"
          },
          "--toc-padding-inline": {
            "description": "Per-link inline padding.",
            "default": "var(--a-space-2)"
          },
          "--toc-rule-active": {
            "description": "Active-item indicator rule color (left border).",
            "default": "var(--a-accent-bg)"
          },
          "--toc-size": {
            "description": "Link font-size.",
            "default": "var(--a-ui-sm)"
          }
        },
        "traits": [],
        "version": 1
      }
    },
    "TableToolbar": {
      "title": "TableToolbar",
      "description": "Header / companion bar for a sibling table-ui. Renders title + count badge, filter / sort / columns popovers, and a search input — all wired to the target table via an [for] id-ref. Modeled on chart-legend-ui's [for] binding pattern. Drop next to (or above) any table-ui to add the standard data-grid toolbar without re-implementing search, filter, sort, or column visibility. Filter rows auto-pick a primitive per column: ≤ 50 distinct values → multi- select (searchable when ≥ 12 options), id-like keys → free-text contains. The column descriptor's `filter` field overrides the auto-detect: `'select'` forces multi-select even on high-cardinality columns; `'text'` forces a contains input even on small enums.",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "component": {
          "const": "TableToolbar"
        },
        "count": {
          "description": "Optional count badge value shown next to the title. When unset, falls back to the row count of the bound table.",
          "type": "string",
          "default": ""
        },
        "for": {
          "description": "id-ref of the table-ui to control. Falls back to the first sibling table-ui within the same parent when omitted.",
          "type": "string",
          "default": ""
        },
        "noColumns": {
          "description": "Hide the Columns visibility popover button. Columns control is shown by default; set to opt out.",
          "type": "boolean",
          "default": false
        },
        "noFilter": {
          "description": "Hide the Filter popover button. Filter is shown by default; set to opt out.",
          "type": "boolean",
          "default": false
        },
        "noSearch": {
          "description": "Hide the search input. Search is shown by default; set to opt out.",
          "type": "boolean",
          "default": false
        },
        "noSort": {
          "description": "Hide the Sort popover button. Sort is shown by default; set to opt out.",
          "type": "boolean",
          "default": false
        },
        "placeholder": {
          "description": "Placeholder text for the search input.",
          "type": "string",
          "default": "Search..."
        },
        "text": {
          "description": "Title text shown on the left.",
          "type": "string",
          "default": ""
        },
        "variant": {
          "description": "Toolbar visual variant. `default` renders bare on parent surface; `card` adds the same chrome as a card-ui header.",
          "type": "string",
          "enum": [
            "default",
            "card"
          ],
          "default": "default"
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [],
        "category": "agent",
        "composes": [
          "text-ui",
          "badge-ui",
          "search-ui",
          "button-ui",
          "field-ui",
          "select-ui",
          "input-ui",
          "menu-item-ui",
          "icon-ui",
          "check-ui"
        ],
        "events": {
          "columns-change": {
            "description": "Column visibility changed. Detail: { hiddenColumns }."
          },
          "filter-change": {
            "description": "Filter set changed. Detail: { filters }."
          },
          "search": {
            "description": "Debounced search query change. Detail: { value }."
          },
          "sort-change": {
            "description": "Sort state changed. Detail: { sortState }."
          }
        },
        "examples": [
          {
            "description": "Members table with filter/sort/columns/search wired to a sibling table-ui.",
            "a2ui": "[\n  {\"id\": \"root\", \"component\": \"Column\", \"gap\": \"3\", \"children\": [\"bar\", \"card\"]},\n  {\"id\": \"bar\", \"component\": \"TableToolbar\", \"for\": \"members\", \"text\": \"All Employees\", \"count\": \"32\"},\n  {\"id\": \"card\", \"component\": \"Card\", \"children\": [\"sec\"]},\n  {\"id\": \"sec\", \"component\": \"Section\", \"bleed\": true, \"children\": [\"tbl\"]},\n  {\"id\": \"tbl\", \"component\": \"Table\", \"id\": \"members\", \"sortable\": true, \"raw\": true}\n]",
            "name": "members-toolbar"
          }
        ],
        "keywords": [
          "table-toolbar",
          "data-grid",
          "data-grid-toolbar",
          "filter",
          "sort",
          "columns",
          "search",
          "directory",
          "admin",
          "backoffice",
          "listing",
          "records"
        ],
        "name": "UITableToolbar",
        "related": [
          "table",
          "search",
          "button",
          "badge",
          "popover"
        ],
        "slots": {
          "actions": {
            "description": "Trailing action area — primary buttons (e.g. \"New row\") rendered after the search input."
          }
        },
        "states": [
          {
            "description": "Default, ready for interaction.",
            "name": "idle"
          }
        ],
        "status": "stable",
        "synonyms": {
          "columns": [
            "table-toolbar",
            "table"
          ],
          "data-grid": [
            "table-toolbar",
            "table"
          ],
          "data-grid-toolbar": [
            "table-toolbar",
            "table"
          ],
          "filter": [
            "table-toolbar",
            "table"
          ],
          "sort": [
            "table-toolbar",
            "table"
          ]
        },
        "tag": "table-toolbar-ui",
        "tokens": {
          "--table-toolbar-bg": {
            "description": "Toolbar background (variant=card)"
          },
          "--table-toolbar-border": {
            "description": "Toolbar border color (variant=card)"
          },
          "--table-toolbar-gap": {
            "description": "Gap between toolbar clusters"
          },
          "--table-toolbar-px": {
            "description": "Horizontal padding"
          },
          "--table-toolbar-py": {
            "description": "Vertical padding"
          },
          "--table-toolbar-radius": {
            "description": "Toolbar corner radius (variant=card)"
          },
          "--table-toolbar-title-fg": {
            "description": "Title text color"
          },
          "--table-toolbar-title-size": {
            "description": "Title font size"
          },
          "--table-toolbar-title-weight": {
            "description": "Title font weight"
          }
        },
        "traits": [],
        "version": 1
      }
    },
    "Tabs": {
      "title": "Tabs",
      "description": "Tabbed panel switcher. Renders a button strip from child <tab-ui> elements and toggles their associated panel via the active attribute. Use for switching between equivalent peer views in one region; for navigation between routes use <nav-ui> instead.",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "component": {
          "const": "Tabs"
        },
        "orientation": {
          "description": "Tab strip orientation. Set to 'vertical' for vertical layout; empty/omitted for horizontal.",
          "type": "string",
          "default": ""
        },
        "value": {
          "description": "Value of the currently active tab. Set programmatically or auto-assigned to the first non-disabled tab on connect.",
          "type": "string",
          "default": ""
        },
        "variant": {
          "description": "Visual variant — `default` (underline strip) or `bordered`.",
          "type": "string",
          "enum": [
            "default",
            "bordered"
          ],
          "default": "default"
        }
      },
      "required": [
        "component",
        "value"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [],
        "category": "container",
        "composes": [
          "icon-ui"
        ],
        "events": {
          "change": {
            "description": "Fired when the value changes (on blur for inputs, on selection for pickers).",
            "detail": {
              "value": {
                "description": "New active tab value.",
                "type": "string"
              }
            }
          }
        },
        "examples": [
          {
            "description": "Tabs component with three tab panels, each containing descriptive content for different sections.",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"Card\",\n    \"children\": [\n      \"body\"\n    ]\n  },\n  {\n    \"id\": \"body\",\n    \"component\": \"Section\",\n    \"children\": [\n      \"tabs\"\n    ]\n  },\n  {\n    \"id\": \"tabs\",\n    \"component\": \"Tabs\",\n    \"attrs\": {\n      \"defaultValue\": \"overview\"\n    },\n    \"children\": [\n      \"tab-overview\",\n      \"tab-features\",\n      \"tab-specs\"\n    ]\n  },\n  {\n    \"id\": \"tab-overview\",\n    \"component\": \"Tab\",\n    \"attrs\": {\n      \"value\": \"overview\",\n      \"label\": \"Overview\"\n    },\n    \"children\": [\n      \"overview-content\"\n    ]\n  },\n  {\n    \"id\": \"overview-content\",\n    \"component\": \"Column\",\n    \"attrs\": {\n      \"gap\": \"sm\"\n    },\n    \"children\": [\n      \"overview-heading\",\n      \"overview-text\"\n    ]\n  },\n  {\n    \"id\": \"overview-heading\",\n    \"component\": \"Text\",\n    \"attrs\": {\n      \"variant\": \"heading\"\n    },\n    \"content\": \"Product Overview\"\n  },\n  {\n    \"id\": \"overview-text\",\n    \"component\": \"Text\",\n    \"attrs\": {\n      \"variant\": \"body\"\n    },\n    \"content\": \"Our platform provides a comprehensive suite of tools for building modern web applications. From design to deployment, everything you need is included.\"\n  },\n  {\n    \"id\": \"tab-features\",\n    \"component\": \"Tab\",\n    \"attrs\": {\n      \"value\": \"features\",\n      \"label\": \"Features\"\n    },\n    \"children\": [\n      \"features-content\"\n    ]\n  },\n  {\n    \"id\": \"features-content\",\n    \"component\": \"Column\",\n    \"attrs\": {\n      \"gap\": \"sm\"\n    },\n    \"children\": [\n      \"features-heading\",\n      \"features-text\"\n    ]\n  },\n  {\n    \"id\": \"features-heading\",\n    \"component\": \"Text\",\n    \"attrs\": {\n      \"variant\": \"heading\"\n    },\n    \"content\": \"Key Features\"\n  },\n  {\n    \"id\": \"features-text\",\n    \"component\": \"Text\",\n    \"attrs\": {\n      \"variant\": \"body\"\n    },\n    \"content\": \"Includes real-time collaboration, version control integration, automated testing, CI/CD pipelines, and a built-in component library with 50+ pre-built patterns.\"\n  },\n  {\n    \"id\": \"tab-specs\",\n    \"component\": \"Tab\",\n    \"attrs\": {\n      \"value\": \"specs\",\n      \"label\": \"Specifications\"\n    },\n    \"children\": [\n      \"specs-content\"\n    ]\n  },\n  {\n    \"id\": \"specs-content\",\n    \"component\": \"Column\",\n    \"attrs\": {\n      \"gap\": \"sm\"\n    },\n    \"children\": [\n      \"specs-heading\",\n      \"specs-text\"\n    ]\n  },\n  {\n    \"id\": \"specs-heading\",\n    \"component\": \"Text\",\n    \"attrs\": {\n      \"variant\": \"heading\"\n    },\n    \"content\": \"Technical Specs\"\n  },\n  {\n    \"id\": \"specs-text\",\n    \"component\": \"Text\",\n    \"attrs\": {\n      \"variant\": \"body\"\n    },\n    \"content\": \"Built on TypeScript with React 19 support. Bundle size under 15KB gzipped. Supports SSR, RSC, and edge runtime. Compatible with Node.js 18+ and all modern browsers.\"\n  }\n]",
            "name": "tabs-panels"
          }
        ],
        "keywords": [
          "tabs",
          "panel",
          "navigation",
          "layout",
          "tab"
        ],
        "name": "UITabs",
        "related": [
          "tab"
        ],
        "slots": {
          "default": {
            "description": "Child tab-ui elements that form the tab strip"
          },
          "indicator": {
            "description": "Auto-created sliding indicator element (line variant only)"
          }
        },
        "states": [
          {
            "description": "Default, ready for interaction.",
            "name": "idle"
          }
        ],
        "status": "stable",
        "synonyms": {
          "layout": [
            "split",
            "sidebar",
            "drawer",
            "tabs",
            "divider",
            "bleed"
          ],
          "navigation": [
            "nav",
            "sidebar",
            "breadcrumb",
            "tabs",
            "menu",
            "pagination"
          ],
          "panel": [
            "tabs",
            "drawer",
            "panel",
            "split"
          ],
          "tab": [
            "tabs",
            "panel",
            "segmented"
          ],
          "tabs": [
            "tabs",
            "panel",
            "segmented"
          ]
        },
        "tag": "tabs-ui",
        "tokens": {
          "--tabs-background": {
            "description": "Override tab strip background"
          },
          "--tabs-border-bottom": {
            "description": "Override bottom border (full shorthand)"
          },
          "--tabs-border-color": {
            "description": "Override bottom border color"
          },
          "--tabs-gap": {
            "description": "Override gap between tabs"
          },
          "--tabs-indicator-color": {
            "description": "Override sliding indicator color"
          },
          "--tabs-indicator-height": {
            "description": "Override sliding indicator thickness"
          },
          "--tabs-outer-radius": {
            "description": "Override outer container border radius"
          },
          "--tabs-padding": {
            "description": "Override inner tab padding (density-scaled)"
          },
          "--tabs-padding-outer": {
            "description": "Override outer container padding"
          },
          "--tabs-pill-background": {
            "description": "Override pill variant container background"
          },
          "--tabs-pill-border-bottom": {
            "description": "Override pill variant bottom border"
          },
          "--tabs-pill-border-color": {
            "description": "Override pill variant border color"
          },
          "--tabs-pill-gap": {
            "description": "Override pill variant tab gap"
          },
          "--tabs-pill-padding-outer": {
            "description": "Override pill variant outer padding"
          },
          "--tabs-pill-radius": {
            "description": "Override pill variant border radius"
          },
          "--tabs-radius": {
            "description": "Override base border radius"
          }
        },
        "traits": [],
        "version": 1
      }
    },
    "Tag": {
      "title": "Tag",
      "description": "Inline INTERACTIVE chip / pill with optional dismiss affordance.\nText rendered via CSS `attr(text)`. Use for filter chips\n(removable=true + `remove` event), autocomplete tokens, and\nuser-managed labels. Distinct from <badge-ui>, which is READ-ONLY\nand includes the [status] shorthand for Beta / New / Deprecated\nmarkers — badge-ui has no remove event. For navigation grouping\nuse <nav-group-ui>; for inline command actions use\n<action-list-ui>.\n",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "component": {
          "const": "Tag"
        },
        "disabled": {
          "description": "Disables interaction and dims the tag.",
          "type": "boolean",
          "default": false
        },
        "removable": {
          "description": "Shows a dismiss button that fires the remove event.",
          "type": "boolean",
          "default": false
        },
        "size": {
          "description": "Size preset controlling font-size and padding.",
          "type": "string",
          "enum": [
            "sm",
            "md"
          ],
          "default": "md"
        },
        "text": {
          "description": "Tag text content.",
          "type": "string",
          "default": ""
        },
        "textContent": {
          "description": "Tag label. Renderer routes this to the `text` attribute, rendered via CSS attr(text) on ::after.",
          "$ref": "#/$defs/DynamicString"
        },
        "tone": {
          "description": "Fill style — orthogonal to [variant]. Three values:\n  - `solid` (default for family variants) — saturated bg + on-strong\n    (near-white) text. The chip IS the state.\n  - `muted` — tinted bg with scheme-paired text. Matches <badge-ui>'s\n    default look. Use on metadata chips in dense lists where the\n    saturated default would compete for attention.\n  - `outline` — transparent bg + family-colored border + family-colored\n    text. The lightest visual weight; good in dense data tables or\n    faceted filter rows where multiple chips would otherwise compete.\nThe `default` variant (no family) stays quiet chrome regardless of\ntone unless `tone=\"solid\"` is set explicitly (high-contrast neutral\ninverse), or `tone=\"outline\"` (fg-muted text + subtle border).\n",
          "type": "string",
          "enum": [
            "solid",
            "muted",
            "outline"
          ],
          "default": "solid"
        },
        "variant": {
          "description": "Semantic variant — `default | info | success | warning | danger`.",
          "type": "string",
          "enum": [
            "default",
            "info",
            "success",
            "warning",
            "danger"
          ],
          "default": "default"
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [],
        "category": "display",
        "composes": [],
        "events": {
          "remove": {
            "description": "Fired when the dismiss button is activated.",
            "detail": {
              "text": {
                "description": "Tag text content.",
                "type": "string"
              },
              "value": {
                "description": "Tag value (same as text).",
                "type": "string"
              }
            }
          }
        },
        "examples": [
          {
            "description": "Basic Tag usage",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"Card\",\n    \"children\": [\n      \"sec\"\n    ]\n  },\n  {\n    \"id\": \"sec\",\n    \"component\": \"Section\",\n    \"children\": [\n      \"comp\"\n    ]\n  },\n  {\n    \"id\": \"comp\",\n    \"component\": \"Tag\",\n    \"text\": \"Example Tag\"\n  }\n]",
            "name": "basic-tag"
          }
        ],
        "keywords": [
          "tag",
          "autocomplete",
          "input",
          "badge",
          "chip",
          "label",
          "pill"
        ],
        "name": "UITag",
        "related": [
          "Badge",
          "NavGroup",
          "ActionList"
        ],
        "slots": {},
        "states": [
          {
            "description": "Default, ready for interaction.",
            "name": "idle"
          },
          {
            "description": "Non-interactive; dimmed.",
            "attribute": "disabled",
            "name": "disabled"
          }
        ],
        "status": "stable",
        "synonyms": {
          "autocomplete": [
            "search",
            "command",
            "palette",
            "tag"
          ],
          "badge": [
            "badge",
            "showcase",
            "tag",
            "label"
          ],
          "chip": [
            "badge",
            "tag",
            "input"
          ],
          "input": [
            "form",
            "create",
            "tag",
            "input"
          ],
          "label": [
            "badge",
            "tag",
            "divider",
            "label"
          ],
          "pill": [
            "badge",
            "tag"
          ],
          "tag": [
            "tag",
            "input",
            "badge"
          ]
        },
        "tag": "tag-ui",
        "tokens": {},
        "traits": [],
        "version": 1
      }
    },
    "TagsInput": {
      "title": "TagsInput",
      "description": "Free-form token input — type a value, press Enter (or the configured\ndelimiter) to commit it as a chip; Backspace from the empty inline\ninput removes the last chip. Distinct from <select-ui multiple>\n(SPEC-040), which is constrained to a fixed option list — tags-input\nis for OPEN sets (labels, email recipients, keyword inputs). Per\nADR-0025 the inline editor is a contenteditable surface (NO native\n`<input>` wrap). Form-bearing via UIFormElement + ElementInternals:\nthe form value is a JSON-serialized string array under `[name]`.\nEach rendered chip is a `<tag-ui removable>`; the `remove` event\ndelegates back to the host. Optional autocompletion: when\n`.suggestions` is non-empty, a popover renders below the field and\nthe host announces as a combobox per WAI-APG.\n",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "required": {
          "description": "Required for form validation. Empty array fails `:invalid`.",
          "type": "boolean",
          "default": false
        },
        "component": {
          "const": "TagsInput"
        },
        "delimiter": {
          "description": "Inline character that commits the typed value as a chip. The\nsentinel `enter` disables in-line commit — only the Enter key\n(or programmatic `addToken`) commits. Default is `,`.",
          "type": "string",
          "default": ","
        },
        "disabled": {
          "description": "Block all interaction; dim the field.",
          "type": "boolean",
          "default": false
        },
        "max": {
          "description": "Maximum number of tokens. `0` (default) means unlimited.",
          "type": "number",
          "default": 0
        },
        "maxLength": {
          "description": "Maximum per-token character count. `0` (default) means unlimited.",
          "type": "number",
          "default": 0
        },
        "min": {
          "description": "Minimum required tokens for form validity.",
          "type": "number",
          "default": 0
        },
        "minLength": {
          "description": "Minimum per-token character count after `transform` is applied.",
          "type": "number",
          "default": 1
        },
        "name": {
          "description": "Form field name. Serializes the token list as JSON under this key.",
          "type": "string",
          "default": ""
        },
        "pasteSplit": {
          "description": "Regex character-class fragment matched against pasted text to\nsplit it into multiple tokens. Default `,\\n` splits on commas\nand newlines. Use `\"\"` to disable paste-splitting entirely.",
          "type": "string",
          "default": ",\n"
        },
        "placeholder": {
          "description": "Placeholder text for the inline input when no chips are committed.",
          "type": "string",
          "default": "Add tag…"
        },
        "readonly": {
          "description": "Block edits; allow inspection (chips render without remove buttons).",
          "type": "boolean",
          "default": false
        },
        "size": {
          "description": "Sizing scale via universal `[size]` attribute system. Matches\nInput + Combobox sizing tokens so a TagsInput rendered alongside\neither feels coherent in a form row.",
          "type": "string",
          "enum": [
            "sm",
            "md",
            "lg"
          ],
          "default": "md"
        },
        "suggestions": {
          "description": "Optional autocomplete strings rendered in a popover below the\nfield. Suggestions are hints, not gates — the typed value still\nwins on commit. JS property only (array reflection skipped).",
          "$ref": "#/$defs/DynamicStringList"
        },
        "transform": {
          "description": "Normalize tokens on commit. `lowercase` lowercases, `trim` strips\nleading + trailing whitespace, `strip-spaces` removes all\nwhitespace, `\"\"` (default) preserves the typed value.",
          "type": "string",
          "enum": [
            "",
            "lowercase",
            "trim",
            "strip-spaces"
          ],
          "default": ""
        },
        "unique": {
          "description": "Reject duplicate tokens silently (no `invalid` event for accidental dups).",
          "type": "boolean",
          "default": true
        },
        "validateFn": {
          "description": "Per-token validator. Sync `(value, index) => boolean` rejects\nfalse synchronously; async `(value, index) => Promise<boolean>`\nflips the host into `[validating]` while pending. JS property\nonly — not serializable in A2UI JSON; wire post-mount.",
          "type": "object",
          "default": null
        },
        "value": {
          "description": "Current token list (string array). Setting `.value = ['a','b']`\nreplaces the rendered chips. Reflection skipped — array values\ndo not round-trip through attribute strings.",
          "$ref": "#/$defs/DynamicStringList"
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [
          {
            "fix": "{\"component\": \"Select\", \"multiple\": true, \"options\": [{\"id\": \"a\", \"label\": \"A\"}]}\n",
            "why": "TagsInput does NOT accept `options`. It is the OPEN-set primitive — any\ntyped string is valid. For closed option lists, use the multi-select\nprimitive with `multiple: true`.\n",
            "wrong": "{\"component\": \"TagsInput\", \"options\": [{\"id\": \"a\", \"label\": \"A\"}]}\n"
          },
          {
            "fix": "{\"component\": \"TagsInput\", \"value\": [\"bug\", \"high-priority\"]}\n",
            "why": "Comma-separated string is invalid for `value`. The contract requires\na string array.\n",
            "wrong": "{\"component\": \"TagsInput\", \"value\": \"bug,high-priority\"}\n"
          },
          {
            "fix": "{\"component\": \"TagsInput\", \"value\": [\"Tag 1\"]}\n",
            "why": "Chips are rendered automatically from `value`. Slotting Tag children\ndecouples the rendered DOM from the form value and breaks Backspace\nremoval + the `change` event payload.\n",
            "wrong": "{\"component\": \"TagsInput\", \"children\": [\n  {\"component\": \"Tag\", \"text\": \"Tag 1\"}\n]}\n"
          }
        ],
        "category": "input",
        "composes": [
          "tag-ui",
          "icon-ui"
        ],
        "events": {
          "change": {
            "description": "Fired after `value` changes (token added or removed).",
            "detail": {
              "added": {
                "description": "Tokens added by this change (`[]` when only removals occurred).",
                "type": "array"
              },
              "removed": {
                "description": "Tokens removed by this change (`[]` when only additions occurred).",
                "type": "array"
              },
              "value": {
                "description": "Current token list (string array).",
                "type": "array"
              }
            }
          },
          "commit": {
            "description": "Fired immediately before a token is committed. Call\n`event.preventDefault()` to reject the candidate token.",
            "detail": {
              "accepted": {
                "description": "True unless the consumer calls `preventDefault()`.",
                "type": "boolean"
              },
              "value": {
                "description": "Candidate token text (post-transform).",
                "type": "string"
              }
            }
          },
          "input": {
            "description": "Fired on each keystroke in the inline input (pre-commit).",
            "detail": {
              "query": {
                "description": "Current typed text in the inline input.",
                "type": "string"
              }
            }
          },
          "invalid": {
            "description": "Fired when a candidate token is rejected. Reasons cover all\nbuilt-in validators and the user-supplied `validateFn`.",
            "detail": {
              "reason": {
                "description": "One of `duplicate` / `too-short` / `too-long` / `validator` / `max`.",
                "type": "string"
              },
              "value": {
                "description": "Rejected token text.",
                "type": "string"
              }
            }
          }
        },
        "examples": [
          {
            "description": "Label input with lowercase normalization + max 10 tags + 2 pre-committed values.",
            "a2ui": "[\n  {\"id\": \"root\", \"component\": \"Card\", \"children\": [\"sec\"]},\n  {\"id\": \"sec\", \"component\": \"Section\", \"children\": [\"field\"]},\n  {\n    \"id\": \"field\",\n    \"component\": \"Field\",\n    \"label\": \"Labels\",\n    \"children\": [\"tags\"]\n  },\n  {\n    \"id\": \"tags\",\n    \"component\": \"TagsInput\",\n    \"name\": \"labels\",\n    \"placeholder\": \"Add a label, press Enter\",\n    \"transform\": \"lowercase\",\n    \"max\": 10,\n    \"value\": [\"bug\", \"high-priority\"]\n  }\n]",
            "name": "canonical-labels"
          },
          {
            "description": "Recipient picker with Enter-only commit (commas are legal in display names).",
            "a2ui": "[\n  {\n    \"id\": \"to\",\n    \"component\": \"TagsInput\",\n    \"name\": \"to\",\n    \"placeholder\": \"Email…\",\n    \"delimiter\": \"enter\",\n    \"transform\": \"trim\"\n  }\n]",
            "name": "email-recipients"
          }
        ],
        "keywords": [
          "tags-input",
          "tag-input",
          "token-input",
          "chips-input",
          "chip-input",
          "labels",
          "recipients",
          "keywords",
          "tags",
          "email-input",
          "multi-value-input"
        ],
        "name": "UITagsInput",
        "related": [
          "tag",
          "select",
          "combobox",
          "field",
          "input"
        ],
        "slots": {
          "chip": {
            "description": "Custom chip template — receives `{value, index}` per token.\nWhen absent, each token renders as a default\n`<tag-ui removable text=\"<value>\">`."
          }
        },
        "states": [
          {
            "description": "No tokens; no typed text.",
            "name": "idle"
          },
          {
            "description": "One or more tokens committed.",
            "attribute": "populated",
            "name": "populated"
          },
          {
            "description": "User is typing into the inline input.",
            "attribute": "editing",
            "name": "editing"
          },
          {
            "description": "Suggestion popover is open.",
            "attribute": "suggesting",
            "name": "suggesting"
          },
          {
            "description": "Async `validateFn` is in flight.",
            "attribute": "validating",
            "name": "validating"
          },
          {
            "description": "Non-interactive; dimmed.",
            "attribute": "disabled",
            "name": "disabled"
          },
          {
            "description": "Read-only; chips render without remove affordance.",
            "attribute": "readonly",
            "name": "readonly"
          }
        ],
        "status": "experimental",
        "synonyms": {
          "chips-input": [
            "tags-input",
            "chip-input",
            "token-input"
          ],
          "labels": [
            "tags",
            "tag-input",
            "labels-input"
          ],
          "recipients": [
            "email-input",
            "tags-input",
            "to-field"
          ],
          "tags-input": [
            "tag-input",
            "chip-input",
            "token-input",
            "tokenizer"
          ],
          "token-input": [
            "tags-input",
            "chip-input",
            "tokenizer"
          ]
        },
        "tag": "tags-input-ui",
        "tokens": {
          "--tags-input-bg": {
            "description": "Host background color."
          },
          "--tags-input-border": {
            "description": "Host border color (idle)."
          },
          "--tags-input-border-hover": {
            "description": "Host border color on hover."
          },
          "--tags-input-chip-bg-invalid": {
            "description": "Chip background color when a chip is marked invalid (validator rejection echo)."
          },
          "--tags-input-fg": {
            "description": "Host foreground (typed-text color)."
          },
          "--tags-input-focus-ring": {
            "description": "Focus-ring box-shadow when the host is focus-within."
          },
          "--tags-input-gap": {
            "description": "Gap between chips and the inline input."
          },
          "--tags-input-placeholder-fg": {
            "description": "Placeholder color for the empty inline input."
          },
          "--tags-input-px": {
            "description": "Horizontal padding inside the chip-cluster wrapper."
          },
          "--tags-input-py": {
            "description": "Vertical padding inside the chip-cluster wrapper."
          },
          "--tags-input-radius": {
            "description": "Host border radius."
          }
        },
        "traits": [],
        "version": 1
      }
    },
    "Text": {
      "title": "Text",
      "description": "Typography wrapper that applies role tokens. Supports truncation and line clamping.",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "color": {
          "description": "Override the variant's color token. Permissive: unknown values are no-ops (variant color wins). Added v0.6.18 (FB-10).",
          "type": "string",
          "enum": [
            "default",
            "subtle",
            "strong",
            "accent",
            "danger",
            "success",
            "warning"
          ],
          "default": ""
        },
        "component": {
          "const": "Text"
        },
        "lines": {
          "description": "Multi-line clamp count (0 = no clamp)",
          "type": "number",
          "default": 0
        },
        "size": {
          "description": "Override the variant's font-size on the body ladder (sm/md/lg → --a-body-sm/md/lg). Accepts `@bp` notation: size=\"sm md@lg\" = sm below lg, md from lg up. Added v0.6.18 (FB-10).",
          "type": "string",
          "enum": [
            "sm",
            "md",
            "lg"
          ],
          "default": ""
        },
        "strong": {
          "description": "When true, applies stronger emphasis (heavier weight + accent color). Styled via :scope[strong] in text.css. Use instead of variant=heading when you want a single emphasized word inline in body copy.",
          "type": "boolean",
          "default": false
        },
        "text-align": {
          "description": "Override text alignment. Note: text-ui defaults to display:inline, so this only takes effect when text-ui is block-like (wrapping or parent display:block/grid). Added v0.6.18 (FB-10).",
          "type": "string",
          "enum": [
            "start",
            "center",
            "end",
            "justify"
          ],
          "default": ""
        },
        "textContent": {
          "description": "Display text content. The main payload field for Text components extracted from HTML.",
          "$ref": "#/$defs/DynamicString"
        },
        "truncate": {
          "description": "Single-line truncation with ellipsis. Ignored when `lines` is set.",
          "type": "boolean",
          "default": false
        },
        "variant": {
          "description": "Typography variant — sets design-role tokens (size / weight /\ntracking / color / leading) per the L0 typography token family.\n**PRESENTATIONAL-ONLY (§247, FB-23 §2).** `<text-ui variant=\"heading\">`\ndoes NOT set `role=\"heading\"` + `aria-level` on the host. Document-\noutline assistive technology will treat the element as `role=\"generic\"`.\nFor semantic headings, wrap with native `<h1>`-`<h6>` OR add\n`role=\"heading\" aria-level=\"N\"` on the host directly. For visual-only\nlabels (eyebrows, kickers, captions, deck), the presentational default\nis correct. The §221k chooser guide in USAGE.md documents picker heuristics.",
          "type": "string",
          "enum": [
            "body",
            "heading",
            "title",
            "subsection",
            "display",
            "caption",
            "label",
            "kicker",
            "deck",
            "section",
            "metric",
            "code"
          ],
          "default": "body",
          "enum_descriptions": {
            "title": "Page title (visual rank H1). Largest under display. Use at the top of an authoritative page or dialog.",
            "body": "Default body copy. 14px / regular. Paragraphs, multi-line content, running prose.",
            "caption": "Annotation under a primary line — smaller + muted. Use for image captions, footnotes.",
            "code": "Inline monospace code reference. Use for inline code within prose.",
            "deck": "Sub-title under a `title`. One-line lead, slightly larger than body. Use for the lead sentence after a title.",
            "display": "Top-level hero / brand display. Tallest visual rank. Use for page-level hero one-liners.",
            "heading": "Major page heading (visual rank H2). 16-18px / bold. Use for major sub-section dividers.",
            "kicker": "Eyebrow text above a `title`. UPPERCASE + small + tracking. Use for content eyebrows (NOT form labels — use `label` for those).",
            "label": "Form-control label (above an `<input-ui>` / `<select-ui>` etc). UI-sized + medium-weight. Use for field labels bound to form controls.",
            "metric": "Numeric KPI / big-number stat. Bold + large. Use for dashboard metric numbers.",
            "section": "Inline form-group / navlist heading (visual rank H4). Small-cap. Use for form group labels, nav list headings.",
            "subsection": "Sub-landmark within a section (visual rank H3). 14px / semibold. Use for card titles within a section."
          }
        },
        "weight": {
          "description": "Override the variant's font-weight. Maps to --a-weight / --a-weight-medium / --a-weight-semibold / --a-weight-bold. Permissive: unknown values are no-ops (variant weight wins). Added v0.6.18 (FB-10).",
          "type": "string",
          "enum": [
            "regular",
            "medium",
            "semibold",
            "bold"
          ],
          "default": ""
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [],
        "category": "display",
        "composes": [],
        "events": {},
        "examples": [
          {
            "description": "Chat interface with message bubbles containing avatar and text pairs, plus an input footer.",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"Card\",\n    \"children\": [\n      \"hdr\",\n      \"sec\",\n      \"ftr\"\n    ]\n  },\n  {\n    \"id\": \"hdr\",\n    \"component\": \"Header\",\n    \"children\": [\n      \"title\"\n    ]\n  },\n  {\n    \"id\": \"title\",\n    \"component\": \"Text\",\n    \"slot\": \"heading\",\n    \"textContent\": \"Chat\"\n  },\n  {\n    \"id\": \"sec\",\n    \"component\": \"Section\",\n    \"children\": [\n      \"messages\"\n    ]\n  },\n  {\n    \"id\": \"messages\",\n    \"component\": \"Column\",\n    \"gap\": \"3\",\n    \"children\": [\n      \"msg1\",\n      \"msg2\",\n      \"msg3\",\n      \"msg4\"\n    ]\n  },\n  {\n    \"id\": \"msg1\",\n    \"component\": \"Row\",\n    \"gap\": \"2\",\n    \"children\": [\n      \"a1\",\n      \"t1\"\n    ]\n  },\n  {\n    \"id\": \"a1\",\n    \"component\": \"Avatar\",\n    \"name\": \"User\",\n    \"size\": \"sm\"\n  },\n  {\n    \"id\": \"t1\",\n    \"component\": \"Text\",\n    \"variant\": \"body\",\n    \"textContent\": \"Hello! Can you help me with something?\"\n  },\n  {\n    \"id\": \"msg2\",\n    \"component\": \"Row\",\n    \"gap\": \"2\",\n    \"children\": [\n      \"a2\",\n      \"t2\"\n    ]\n  },\n  {\n    \"id\": \"a2\",\n    \"component\": \"Avatar\",\n    \"name\": \"Assistant\",\n    \"size\": \"sm\"\n  },\n  {\n    \"id\": \"t2\",\n    \"component\": \"Text\",\n    \"variant\": \"body\",\n    \"textContent\": \"Of course! I'd be happy to help. What do you need?\"\n  },\n  {\n    \"id\": \"msg3\",\n    \"component\": \"Row\",\n    \"gap\": \"2\",\n    \"children\": [\n      \"a3\",\n      \"t3\"\n    ]\n  },\n  {\n    \"id\": \"a3\",\n    \"component\": \"Avatar\",\n    \"name\": \"User\",\n    \"size\": \"sm\"\n  },\n  {\n    \"id\": \"t3\",\n    \"component\": \"Text\",\n    \"variant\": \"body\",\n    \"textContent\": \"I need to build a dashboard layout.\"\n  },\n  {\n    \"id\": \"msg4\",\n    \"component\": \"Row\",\n    \"gap\": \"2\",\n    \"children\": [\n      \"a4\",\n      \"t4\"\n    ]\n  },\n  {\n    \"id\": \"a4\",\n    \"component\": \"Avatar\",\n    \"name\": \"Assistant\",\n    \"size\": \"sm\"\n  },\n  {\n    \"id\": \"t4\",\n    \"component\": \"Text\",\n    \"variant\": \"body\",\n    \"textContent\": \"Great choice! Let me suggest some patterns for that.\"\n  },\n  {\n    \"id\": \"ftr\",\n    \"component\": \"Footer\",\n    \"children\": [\n      \"input-row\"\n    ]\n  },\n  {\n    \"id\": \"input-row\",\n    \"component\": \"Row\",\n    \"gap\": \"2\",\n    \"children\": [\n      \"chat-input\",\n      \"send-btn\"\n    ]\n  },\n  {\n    \"id\": \"chat-input\",\n    \"component\": \"Input\",\n    \"placeholder\": \"Type a message...\"\n  },\n  {\n    \"id\": \"send-btn\",\n    \"component\": \"Button\",\n    \"text\": \"Send\",\n    \"icon\": \"send\",\n    \"variant\": \"primary\"\n  }\n]",
            "name": "chat-interface"
          },
          {
            "description": "Command palette card with search input and a list of command options.",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"Card\",\n    \"children\": [\n      \"hdr\",\n      \"sec\"\n    ]\n  },\n  {\n    \"id\": \"hdr\",\n    \"component\": \"Header\",\n    \"children\": [\n      \"search\"\n    ]\n  },\n  {\n    \"id\": \"search\",\n    \"component\": \"Input\",\n    \"placeholder\": \"Type a command or search...\",\n    \"icon\": \"search\"\n  },\n  {\n    \"id\": \"sec\",\n    \"component\": \"Section\",\n    \"children\": [\n      \"options\"\n    ]\n  },\n  {\n    \"id\": \"options\",\n    \"component\": \"Column\",\n    \"gap\": \"1\",\n    \"children\": [\n      \"opt1\",\n      \"opt2\",\n      \"opt3\",\n      \"opt4\",\n      \"opt5\"\n    ]\n  },\n  {\n    \"id\": \"opt1\",\n    \"component\": \"Row\",\n    \"gap\": \"2\",\n    \"children\": [\n      \"i1\",\n      \"l1\"\n    ]\n  },\n  {\n    \"id\": \"i1\",\n    \"component\": \"Icon\",\n    \"name\": \"file\"\n  },\n  {\n    \"id\": \"l1\",\n    \"component\": \"Text\",\n    \"textContent\": \"Open File\"\n  },\n  {\n    \"id\": \"opt2\",\n    \"component\": \"Row\",\n    \"gap\": \"2\",\n    \"children\": [\n      \"i2\",\n      \"l2\"\n    ]\n  },\n  {\n    \"id\": \"i2\",\n    \"component\": \"Icon\",\n    \"name\": \"gear\"\n  },\n  {\n    \"id\": \"l2\",\n    \"component\": \"Text\",\n    \"textContent\": \"Settings\"\n  },\n  {\n    \"id\": \"opt3\",\n    \"component\": \"Row\",\n    \"gap\": \"2\",\n    \"children\": [\n      \"i3\",\n      \"l3\"\n    ]\n  },\n  {\n    \"id\": \"i3\",\n    \"component\": \"Icon\",\n    \"name\": \"palette\"\n  },\n  {\n    \"id\": \"l3\",\n    \"component\": \"Text\",\n    \"textContent\": \"Change Theme\"\n  },\n  {\n    \"id\": \"opt4\",\n    \"component\": \"Row\",\n    \"gap\": \"2\",\n    \"children\": [\n      \"i4\",\n      \"l4\"\n    ]\n  },\n  {\n    \"id\": \"i4\",\n    \"component\": \"Icon\",\n    \"name\": \"users\"\n  },\n  {\n    \"id\": \"l4\",\n    \"component\": \"Text\",\n    \"textContent\": \"Manage Users\"\n  },\n  {\n    \"id\": \"opt5\",\n    \"component\": \"Row\",\n    \"gap\": \"2\",\n    \"children\": [\n      \"i5\",\n      \"l5\"\n    ]\n  },\n  {\n    \"id\": \"i5\",\n    \"component\": \"Icon\",\n    \"name\": \"sign-out\"\n  },\n  {\n    \"id\": \"l5\",\n    \"component\": \"Text\",\n    \"textContent\": \"Sign Out\"\n  }\n]",
            "name": "command-palette"
          }
        ],
        "keywords": [
          "text"
        ],
        "name": "UIText",
        "related": [
          "avatar",
          "input",
          "button",
          "empty-state",
          "alert"
        ],
        "slots": {},
        "states": [
          {
            "description": "Default, ready for interaction.",
            "name": "idle"
          }
        ],
        "status": "stable",
        "synonyms": {
          "text": [
            "typography",
            "prose",
            "label-text",
            "paragraph"
          ]
        },
        "tag": "text-ui",
        "tokens": {},
        "traits": [],
        "version": 1
      }
    },
    "Textarea": {
      "title": "Textarea",
      "description": "Multi-line text input primitive — the host IS the contenteditable\nsurface (per ADR-0025, no native <textarea> wrapped underneath).\nForm-bearing via UIFormElement: [name], [value], [required],\n[disabled], [readonly], fires `change` on blur and `input` per\nkeystroke. Enter (without Shift) dispatches a bubbling `submit`\nevent — Shift+Enter inserts a newline. This is unconditional;\nthere is no opt-in/opt-out attribute. For Enter-to-send composers\nuse <chat-input-ui> inside <chat-composer>. Wrap in <field-ui\nlabel=\"…\"> for the canonical labeled stack.\n",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "required": {
          "description": "Marks the field as required for form validation. Sets aria-required. Inherited from UIFormElement.",
          "type": "boolean",
          "default": false
        },
        "component": {
          "const": "Textarea"
        },
        "disabled": {
          "description": "Disables interaction, removes contenteditable, and dims the control. Inherited from UIFormElement.",
          "type": "boolean",
          "default": false
        },
        "error": {
          "description": "Validation error message. Set by constraint validation or manually via setInvalid(). Inherited from UIFormElement.",
          "type": "string",
          "default": ""
        },
        "hint": {
          "description": "Help text displayed below the textarea. Hidden when error is set.",
          "type": "string",
          "default": ""
        },
        "label": {
          "description": "Label text displayed above the textarea.",
          "type": "string",
          "default": ""
        },
        "name": {
          "description": "Form control name for form data submission. Inherited from UIFormElement.",
          "type": "string",
          "default": ""
        },
        "placeholder": {
          "description": "Placeholder text shown when textarea is empty.",
          "type": "string",
          "default": ""
        },
        "readonly": {
          "description": "Prevents editing while keeping the surface focusable. Sets contenteditable=false. Inherited from UIFormElement.",
          "type": "boolean",
          "default": false
        },
        "resize": {
          "description": "Resize behavior of the textarea.",
          "type": "string",
          "enum": [
            "vertical",
            "horizontal",
            "both",
            "none"
          ],
          "default": "vertical"
        },
        "rows": {
          "description": "Number of visible text rows (sets min-height).",
          "type": "number",
          "default": 3
        },
        "throttle": {
          "description": "§220 (v0.5.9, FEEDBACK-14 §3). Trailing-debounce on the `input`\nevent in milliseconds. When > 0, value mutates immediately + the UI\nstays responsive, but `input` dispatch is collapsed so only the\nfinal value in the throttle window emits. Useful for expensive\n`input`-driven computation (autosave preview, server-side\nautocomplete, large-doc reflow). `change` fires unthrottled on blur\n/ Enter; any pending `input` flushes before `change` so consumers\nsee input→input→…→input→change ordering. Default 0 preserves\nsynchronous emission.",
          "type": "number",
          "default": 0
        },
        "value": {
          "description": "Current textarea value, synced with the contenteditable text surface. Inherited from UIFormElement.",
          "type": "string",
          "default": ""
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [],
        "category": "layout",
        "composes": [],
        "events": {
          "change": {
            "description": "Fired when the textarea loses focus after a value change."
          },
          "input": {
            "description": "Fired on each keystroke as the value changes."
          }
        },
        "examples": [
          {
            "description": "Basic Textarea usage",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"Card\",\n    \"children\": [\n      \"sec\"\n    ]\n  },\n  {\n    \"id\": \"sec\",\n    \"component\": \"Section\",\n    \"children\": [\n      \"comp\"\n    ]\n  },\n  {\n    \"id\": \"comp\",\n    \"component\": \"Textarea\",\n    \"label\": \"Example Textarea\",\n    \"placeholder\": \"Enter textarea...\"\n  }\n]",
            "name": "basic-textarea"
          }
        ],
        "keywords": [
          "textarea"
        ],
        "name": "UITextarea",
        "related": [
          "Input",
          "Field",
          "ChatInput",
          "Code"
        ],
        "slots": {},
        "states": [
          {
            "description": "Default, ready for interaction.",
            "name": "idle"
          }
        ],
        "status": "stable",
        "synonyms": {
          "textarea": [
            "multiline-input",
            "text-area",
            "comment-input",
            "long-text-input"
          ]
        },
        "tag": "textarea-ui",
        "tokens": {},
        "traits": [],
        "version": 1
      }
    },
    "ThemePanel": {
      "title": "ThemePanel",
      "description": "Module-tier appearance-preferences control surface. Owns the three knobs\nof the AdiaUI theming contract: [theme=<slug>] named themes,\n--a-density / --a-radius-k parametric overrides, and color-scheme\nlight/dark switching, plus optional localStorage persistence behind a\nsmall attribute API.\n\nDrops into any consumer's <popover-ui slot=\"content\"> (the canonical\ncomposition) or directly into a sidebar section. Eight named themes\nship by default; section visibility flips on/off via boolean attributes\n([parametric], [presets], [scheme-toggle]).\n\nPromoted from the duplicated <div id=\"theme-panel\"> block in site/ and\nplaygrounds/admin-shell/ — see docs/specs/theme-panel-module.md.\n",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "active-density": {
          "description": "Reflected — mirrors the current --a-density value on the target\nelement. Stringified number.\n",
          "type": "string",
          "default": ""
        },
        "active-radius": {
          "description": "Reflected — mirrors the current --a-radius-k value on the target\nelement. Stringified number.\n",
          "type": "string",
          "default": ""
        },
        "active-register": {
          "description": "Reflected — the active typographic register on the target\n(verse | prose); empty for regular.\n",
          "type": "string",
          "default": ""
        },
        "active-scheme": {
          "description": "Reflected — the resolved color-scheme (auto collapsed to a\nconcrete value). Either \"light\" or \"dark\".\n",
          "type": "string",
          "default": ""
        },
        "active-theme": {
          "description": "Reflected — the currently selected theme slug. Empty string when\nunset (default theme). Read-only externally; use .apply({theme})\nto change.\n",
          "type": "string",
          "default": ""
        },
        "component": {
          "const": "ThemePanel"
        },
        "parametric": {
          "description": "Renders the density + radius slider block. Sliders bind to\n--a-density and --a-radius-k on the target element.\n",
          "type": "boolean",
          "default": false
        },
        "persist": {
          "description": "Persists selections to localStorage. Defaults to ephemeral so\nplaygrounds and embedded demos do not silently mutate a user's\ndocs-shell preferences.\n",
          "type": "boolean",
          "default": false
        },
        "presets": {
          "description": "Renders the compact / reset / spacious preset row. Each preset\napplies a (density, radius) pair; \"default\" also clears the\n[theme] attribute.\n",
          "type": "boolean",
          "default": false
        },
        "register": {
          "description": "Renders a \"Scale Context\" row (verse / regular / prose) — a\n<segmented-ui> that toggles the [verse] / [prose] typographic register\non the target element (regular clears both). Persisted like the other\nknobs when [persist] is set.\n",
          "type": "boolean",
          "default": false
        },
        "scheme": {
          "description": "Initial color-scheme. \"auto\" follows prefers-color-scheme via a\nmatchMedia listener; user clicks on the scheme toggle promote to\nan explicit light or dark choice.\n",
          "type": "string",
          "enum": [
            "light",
            "dark",
            "auto"
          ],
          "default": "auto"
        },
        "scheme-toggle": {
          "description": "Renders an integrated light/dark <segmented-ui> at the top of the\npanel. When absent, the panel omits scheme entirely — consumers\ncan still drive scheme via the .apply({scheme}) public method.\n",
          "type": "boolean",
          "default": false
        },
        "storage-prefix": {
          "description": "Namespace for localStorage keys when [persist] is set. Four keys\nare written: {prefix}theme, {prefix}scheme, {prefix}density,\n{prefix}radius.\n",
          "type": "string",
          "default": "adia-theme-"
        },
        "target": {
          "description": "CSS selector for the element that receives [theme] and\n--a-density / --a-radius-k writes. Defaults to :root (the\n<html> element). Scoped targets are useful for preview-pane\ndemos.\n",
          "type": "string",
          "default": ":root"
        },
        "themes": {
          "description": "Space-separated list of theme slugs to render as buttons. Author\nmay restrict ([themes=\"default ocean\"]) or extend. Tolerant —\nunknown slugs render a button; clicking applies [theme=slug]\nregardless of whether themes.css has a matching block.\n",
          "type": "string",
          "default": "default ocean forest sunset lavender rose slate midnight"
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [],
        "category": "layout",
        "composes": [
          "segmented-ui",
          "segment-ui",
          "text-ui",
          "button-ui",
          "divider-ui",
          "field-ui",
          "slider-ui"
        ],
        "events": {
          "theme-change": {
            "description": "Bubbles when any user-visible state changes (theme click, slider\ninput, preset click, scheme flip, reset). One event per change.\nNo event on auto-rehydrate-from-storage at boot.\n",
            "detail": {
              "theme": "string",
              "density": "number",
              "radius": "number",
              "scheme": "string",
              "source": "string"
            }
          }
        },
        "examples": [],
        "keywords": [
          "theme",
          "theme-panel",
          "palette",
          "density",
          "radius",
          "scheme",
          "dark-mode",
          "light-mode",
          "color-scheme",
          "preferences",
          "settings",
          "color",
          "appearance",
          "skin"
        ],
        "name": "ThemePanel",
        "related": [
          "Popover",
          "Button",
          "Slider",
          "Field",
          "Divider",
          "Text",
          "Segmented",
          "AdminShell"
        ],
        "slots": {},
        "states": [
          {
            "description": "Default — panel rendered, awaiting input.",
            "name": "idle"
          },
          {
            "description": "[persist] is set; selections write to localStorage under\n[storage-prefix].\n",
            "attribute": "persist",
            "name": "persisted"
          },
          {
            "description": "[scheme=\"auto\"] and no user override this session; a\nprefers-color-scheme listener reapplies on system flip.\n",
            "name": "scheme-auto"
          }
        ],
        "status": "stable",
        "synonyms": {
          "theme": [
            "palette",
            "skin",
            "appearance"
          ],
          "density": [
            "compactness",
            "spacing-scale"
          ],
          "radius": [
            "corner-roundness",
            "border-radius"
          ],
          "scheme": [
            "mode",
            "color-scheme",
            "dark-mode"
          ]
        },
        "tag": "theme-panel",
        "tokens": {},
        "traits": [],
        "version": 1
      }
    },
    "ThemeProvider": {
      "title": "ThemeProvider",
      "description": "Foundation-providing wrapper — adopts the AdiaUI foundation (design tokens +\nresets + page-frame + every primitive's CSS) into the document from anywhere\nin the DOM, so a surface renders fully-styled WITHOUT a hand-wired\n<link rel=\"stylesheet\"> in <head>. Layout-transparent (display: contents): the\nelement owns no box; children lay out as if it weren't there.\n\nMechanism: it imports the constructable-stylesheet twin of web-components.min.css\n(byte-identical to the CDN bundle, emitted from the same build buffer) and\nadopts it once into document.adoptedStyleSheets, deduped — adoption fires at\nmodule load, before paint. Coexists with the render-blocking <link> path; both\ndeliver the same bytes. Use a <link> (-> the CDN web-components.min.css) for\nmulti-page / top-level surfaces (cacheable across navigations, zero flash); use\n<theme-provider> for SPA roots, embedded apps, and dynamic mounts where you do\nnot control <head> (e.g. <embed-shell>, an A2UI surface, a micro-frontend).\n\nTheming: the base foundation is OS light/dark via light-dark() tokens. Two opt-in\nattributes adopt their layer on demand — theme=\"ocean|forest|slate|…\" applies a\nnamed preset (adopts the themes layer; matches the [theme] hook) and\nscale=\"verse|prose\" sets the compact / long-form typographic register (adopts the\nmatching register layer; maps onto the [verse]/[prose] attribute). Each layer is\nfetched only when its attribute is set, so a bare provider stays lean.\nOpt-in infra: NOT in the all-in-one @adia-ai/web-components barrel (it carries\nthe whole foundation); import @adia-ai/web-components/components/theme-provider\nexplicitly. Distinct from <frame-ui> (a layout skeleton, owns no CSS delivery)\nand the page shells (chrome over the same foundation).\n",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "theme": {
          "description": "Named theme preset for the wrapped subtree (default, ocean, forest, sunset, lavender, rose, slate, midnight). Adopts the themes layer on demand + matches the [theme=\"…\"] hook.",
          "type": "string",
          "default": ""
        },
        "component": {
          "const": "ThemeProvider"
        },
        "scale": {
          "description": "Typographic / density register for the subtree — \"verse\" (compact) or \"prose\" (long-form). Adopts the matching register layer on demand; maps onto the [verse]/[prose] attribute (additive).",
          "type": "string",
          "default": ""
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [],
        "category": "layout",
        "composes": [],
        "events": {},
        "examples": [
          {
            "description": "A client-mounted app root that self-provides the foundation (no head link).",
            "a2ui": "[\n  { \"id\": \"root\", \"component\": \"ThemeProvider\", \"children\": [\"panel\"] },\n  { \"id\": \"panel\", \"component\": \"Frame\", \"children\": [\"body\", \"actions\"] },\n  { \"id\": \"body\", \"component\": \"Section\", \"children\": [\"copy\"] },\n  { \"id\": \"copy\", \"component\": \"Text\", \"variant\": \"body\", \"textContent\": \"Fully styled — no <head> stylesheet link.\" },\n  { \"id\": \"actions\", \"component\": \"Footer\", \"children\": [\"go\"] },\n  { \"id\": \"go\", \"component\": \"Button\", \"text\": \"Continue\", \"variant\": \"primary\" }\n]",
            "name": "spa-root"
          }
        ],
        "keywords": [
          "style",
          "provider",
          "foundation",
          "tokens",
          "reset",
          "adopt",
          "stylesheet",
          "shell",
          "embed",
          "spa"
        ],
        "name": "UIThemeProvider",
        "related": [
          "Frame",
          "Card"
        ],
        "slots": {},
        "states": [
          {
            "description": "Default — foundation adopted into the document; children rendered.",
            "name": "idle"
          }
        ],
        "status": "experimental",
        "synonyms": {
          "foundation": [
            "foundation",
            "tokens",
            "styles"
          ],
          "provider": [
            "provider",
            "root",
            "host"
          ]
        },
        "tag": "theme-provider",
        "tokens": {},
        "traits": [],
        "version": 1
      }
    },
    "Timeline": {
      "title": "Timeline",
      "description": "Timeline and step wizard. Two modes: timeline (per-item state) and steps (parent-driven).",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "component": {
          "const": "Timeline"
        },
        "orientation": {
          "description": "Layout direction",
          "type": "string",
          "enum": [
            "vertical",
            "horizontal"
          ],
          "default": "vertical"
        },
        "size": {
          "description": "Rail size preset — use `sm` for agent-reasoning/pipeline views; `md` is the default.",
          "type": "string",
          "enum": [
            "sm",
            "md"
          ],
          "default": "md"
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [],
        "category": "display",
        "composes": [
          "icon-ui"
        ],
        "events": {
          "timeline-toggle": {
            "description": "Fired when a collapsible timeline item is expanded or collapsed. detail.expanded carries the new open state.",
            "detail": {
              "expanded": {
                "description": "New open state of the toggled item after the press.",
                "type": "boolean"
              }
            }
          }
        },
        "examples": [
          {
            "description": "Order tracking card with a timeline showing order status milestones from placed to delivered.",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"Card\",\n    \"children\": [\n      \"hdr\",\n      \"sec\"\n    ]\n  },\n  {\n    \"id\": \"hdr\",\n    \"component\": \"Header\",\n    \"children\": [\n      \"title\",\n      \"desc\"\n    ]\n  },\n  {\n    \"id\": \"title\",\n    \"component\": \"Text\",\n    \"slot\": \"heading\",\n    \"variant\": \"span\",\n    \"textContent\": \"Order #12345\"\n  },\n  {\n    \"id\": \"desc\",\n    \"component\": \"Text\",\n    \"slot\": \"description\",\n    \"textContent\": \"Estimated delivery: April 20, 2026\"\n  },\n  {\n    \"id\": \"sec\",\n    \"component\": \"Section\",\n    \"children\": [\n      \"col\"\n    ]\n  },\n  {\n    \"id\": \"col\",\n    \"component\": \"Column\",\n    \"gap\": \"4\",\n    \"children\": [\n      \"info\",\n      \"tl\"\n    ]\n  },\n  {\n    \"id\": \"info\",\n    \"component\": \"Row\",\n    \"gap\": \"4\",\n    \"children\": [\n      \"status\",\n      \"carrier\"\n    ]\n  },\n  {\n    \"id\": \"status\",\n    \"component\": \"Column\",\n    \"gap\": \"0\",\n    \"children\": [\n      \"sl\",\n      \"sv\"\n    ]\n  },\n  {\n    \"id\": \"sl\",\n    \"component\": \"Text\",\n    \"color\": \"muted\",\n    \"textContent\": \"Status\"\n  },\n  {\n    \"id\": \"sv\",\n    \"component\": \"Text\",\n    \"weight\": \"semibold\",\n    \"textContent\": \"In Transit\"\n  },\n  {\n    \"id\": \"carrier\",\n    \"component\": \"Column\",\n    \"gap\": \"0\",\n    \"children\": [\n      \"cl\",\n      \"cv\"\n    ]\n  },\n  {\n    \"id\": \"cl\",\n    \"component\": \"Text\",\n    \"color\": \"muted\",\n    \"textContent\": \"Carrier\"\n  },\n  {\n    \"id\": \"cv\",\n    \"component\": \"Text\",\n    \"weight\": \"semibold\",\n    \"textContent\": \"FedEx Express\"\n  },\n  {\n    \"id\": \"tl\",\n    \"component\": \"Timeline\",\n    \"children\": [\n      \"t1\",\n      \"t2\",\n      \"t3\",\n      \"t4\"\n    ]\n  },\n  {\n    \"id\": \"t1\",\n    \"component\": \"TimelineItem\",\n    \"text\": \"Order Placed\",\n    \"description\": \"April 15, 2026 at 2:30 PM\",\n    \"color\": \"success\"\n  },\n  {\n    \"id\": \"t2\",\n    \"component\": \"TimelineItem\",\n    \"text\": \"Processing\",\n    \"description\": \"April 16, 2026 at 9:00 AM\",\n    \"color\": \"success\"\n  },\n  {\n    \"id\": \"t3\",\n    \"component\": \"TimelineItem\",\n    \"text\": \"Shipped\",\n    \"description\": \"April 17, 2026 at 11:45 AM\",\n    \"color\": \"primary\"\n  },\n  {\n    \"id\": \"t4\",\n    \"component\": \"TimelineItem\",\n    \"text\": \"Delivered\",\n    \"description\": \"Expected April 20, 2026\",\n    \"color\": \"muted\"\n  }\n]",
            "name": "order-tracking"
          }
        ],
        "keywords": [
          "timeline"
        ],
        "name": "UITimeline",
        "related": [
          "timeline-item"
        ],
        "slots": {
          "default": {
            "description": "Accepts <timeline-item-ui> children."
          }
        },
        "states": [
          {
            "description": "Default, ready for interaction.",
            "name": "idle"
          }
        ],
        "status": "stable",
        "synonyms": {
          "timeline": [
            "activity-log",
            "event-log",
            "history",
            "audit-trail"
          ]
        },
        "tag": "timeline-ui",
        "tokens": {},
        "traits": [],
        "version": 1
      }
    },
    "TimelineItem": {
      "title": "TimelineItem",
      "description": "Child of <timeline-ui>. One step in a sequenced reasoning/process timeline. Used heavily by <agent-reasoning-ui> + <agent-trace-ui>.",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "description": {
          "description": "Subtitle below the label.",
          "type": "string"
        },
        "component": {
          "const": "TimelineItem"
        },
        "duration": {
          "description": "Elapsed time (e.g. \"1.2s\", \"340ms\").",
          "type": "string"
        },
        "icon": {
          "description": "Optional leading icon name (Phosphor).",
          "type": "string"
        },
        "spinner": {
          "description": "Show a spinner instead of the icon while status=pending.",
          "type": "boolean",
          "default": false
        },
        "status": {
          "description": "Lifecycle state (idle | pending | done | failed).",
          "type": "string",
          "default": "idle"
        },
        "text": {
          "description": "Primary step label.",
          "type": "string"
        },
        "time": {
          "description": "Absolute timestamp (HH:MM or ISO).",
          "type": "string"
        },
        "variant": {
          "description": "Visual variant (default | accent | success | warning | danger).",
          "type": "string",
          "default": "default"
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [],
        "category": "feedback",
        "composes": [],
        "events": {},
        "examples": [],
        "keywords": [
          "timeline-item",
          "timeline-row",
          "activity-entry",
          "event-entry",
          "history-row"
        ],
        "name": "UITimelineItem",
        "related": [
          "Timeline",
          "FeedItem",
          "Stepper"
        ],
        "slots": {
          "description": {
            "description": "Override slot for rich description markup (inline links, code spans, embedded badges). Renders beneath the primary text at body-subtle typography."
          },
          "icon": {
            "description": "Override the [icon] glyph with a custom slotted element. Use for branded icons, avatars, or non-Phosphor sources. Mutually exclusive with the [icon] attribute."
          }
        },
        "states": [],
        "status": "stable",
        "synonyms": {
          "timeline-item": [
            "timeline-row",
            "activity-row",
            "event-row",
            "history-entry"
          ]
        },
        "tag": "timeline-item-ui",
        "tokens": {},
        "traits": [],
        "version": 1
      }
    },
    "TimePicker": {
      "title": "TimePicker",
      "description": "Time-of-day picker with discrete segments (hour, minute, optional second, optional AM/PM). Each segment follows the WAI-ARIA Spinbutton pattern with Arrow-key increment/decrement, Page Up/Down for larger jumps, Home/End for segment min/max, and Tab to move between segments. Form-associated input emitting ISO 8601 time string (\"HH:mm\" or \"HH:mm:ss\") via change events. Per ADR-0025 no native form controls — segments are contenteditable spans inside a custom host. SPEC-043.",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "required": {
          "description": "Marks the field as required for form validation. Sets aria-required.",
          "type": "boolean",
          "default": false
        },
        "component": {
          "const": "TimePicker"
        },
        "disabled": {
          "description": "Disables interaction; dims the control",
          "type": "boolean",
          "default": false
        },
        "hourcycle": {
          "description": "Hour cycle. Empty (default) derives from the document locale — most\nen-* locales resolve to `h23`. `h12` forces a 12-hour cycle with an\nAM/PM (meridiem) segment; `h23` forces 24-hour cycle.\n",
          "type": "string",
          "enum": [
            "",
            "h12",
            "h23"
          ],
          "default": ""
        },
        "locale": {
          "description": "BCP-47 locale tag used to derive hour-cycle when `hour-cycle` is empty. Falls back to `<html lang>` then to browser default.",
          "type": "string",
          "default": ""
        },
        "max": {
          "description": "Latest selectable time as ISO 8601. Empty disables the constraint.",
          "type": "string",
          "default": ""
        },
        "min": {
          "description": "Earliest selectable time as ISO 8601. Empty disables the constraint.",
          "type": "string",
          "default": ""
        },
        "name": {
          "description": "Form field name for FormData submission",
          "type": "string",
          "default": ""
        },
        "placeholder": {
          "description": "Per-segment placeholder text shown when a segment is empty. Defaults to \"--\".",
          "type": "string",
          "default": "--"
        },
        "precision": {
          "description": "Whether the seconds segment is exposed. `minute` (default) hides seconds; `second` adds the seconds segment + separator.",
          "type": "string",
          "enum": [
            "minute",
            "second"
          ],
          "default": "minute"
        },
        "readonly": {
          "description": "Prevents editing while keeping the field focusable. Segments stay focusable for inspection.",
          "type": "boolean",
          "default": false
        },
        "step": {
          "description": "Per-Arrow-keypress increment in seconds. 60 = minute precision (default), 900 = 15-minute, 1 = second precision.",
          "type": "number",
          "default": 60
        },
        "value": {
          "description": "Current time value as ISO 8601 (\"HH:mm\" or \"HH:mm:ss\"). Empty when no value selected.",
          "type": "string",
          "default": ""
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [
          {
            "fix": "{\"component\": \"TimePicker\", \"value\": \"09:30\"}\n",
            "why": "Localized format is not a valid `value`. The contract requires ISO\n8601 time (`HH:mm` or `HH:mm:ss`, 24-hour). The display format is\nderived from `hourCycle` regardless of how the value is stored.\n",
            "wrong": "{\"component\": \"TimePicker\", \"value\": \"9:30 AM\"}\n"
          },
          {
            "fix": "{\"component\": \"DatetimePicker\", \"value\": \"2026-05-24T09:30\"}\n",
            "why": "Datetime string is invalid for TimePicker — the date portion is\nnot accepted. For datetime selection use the DatetimePicker\ncomponent.\n",
            "wrong": "{\"component\": \"TimePicker\", \"value\": \"2026-05-24T09:30\"}\n"
          },
          {
            "fix": "{\"component\": \"TimePicker\", \"name\": \"field-name\"}\n",
            "why": "Nesting a native time input violates ADR-0025 and bypasses\nElementInternals form participation.\n",
            "wrong": "{\"component\": \"TimePicker\", \"children\": [\n  {\"component\": \"Input\", \"type\": \"time\"}\n]}\n"
          }
        ],
        "category": "input",
        "composes": [],
        "events": {
          "change": {
            "description": "Fired when the value commits (segment edit completes via Arrow / Tab / blur).",
            "detail": {
              "segment": {
                "description": "Which segment commit fired the event (`hour` | `minute` | `second` | `meridiem`).",
                "type": "string"
              },
              "value": {
                "description": "Current value as ISO 8601 (\"HH:mm\" or \"HH:mm:ss\").",
                "type": "string"
              }
            }
          },
          "input": {
            "description": "Fired on intermediate segment edits before commit.",
            "detail": {
              "value": {
                "description": "In-flight value as ISO 8601.",
                "type": "string"
              }
            }
          },
          "invalid": {
            "description": "Fired when a constraint is violated (min/max range, parse error).",
            "detail": {
              "reason": {
                "description": "Why it failed (`min` | `max` | `parse`).",
                "type": "string",
                "enum": [
                  "min",
                  "max",
                  "parse"
                ]
              },
              "value": {
                "description": "Value that failed validation.",
                "type": "string"
              }
            }
          }
        },
        "examples": [
          {
            "description": "Time-of-day picker with 15-minute step and business-hours bounds.",
            "a2ui": "[\n  {\"id\": \"root\", \"component\": \"Field\", \"label\": \"Start time\",\n   \"children\": [\"t\"]},\n  {\"id\": \"t\", \"component\": \"TimePicker\",\n   \"name\": \"start-time\", \"value\": \"09:30\",\n   \"min\": \"08:00\", \"max\": \"18:00\", \"step\": 900}\n]\n",
            "name": "meeting-time-15min-step"
          },
          {
            "description": "Time picker with second precision for a log-cursor query.",
            "a2ui": "[\n  {\"id\": \"root\", \"component\": \"Field\", \"label\": \"Cursor\",\n   \"children\": [\"t\"]},\n  {\"id\": \"t\", \"component\": \"TimePicker\",\n   \"name\": \"cursor\", \"precision\": \"second\", \"step\": 1,\n   \"value\": \"14:30:45\"}\n]\n",
            "name": "log-cursor-second-precision"
          },
          {
            "description": "Forced 12-hour cycle with AM/PM segment for an alarm picker.",
            "a2ui": "[\n  {\"id\": \"root\", \"component\": \"Field\", \"label\": \"Alarm\",\n   \"children\": [\"t\"]},\n  {\"id\": \"t\", \"component\": \"TimePicker\",\n   \"name\": \"alarm\", \"hourCycle\": \"h12\", \"value\": \"07:00\"}\n]\n",
            "name": "alarm-12h-cycle"
          }
        ],
        "keywords": [
          "time",
          "timepicker",
          "time-picker",
          "clock",
          "hour",
          "minute",
          "spinbutton"
        ],
        "name": "UITimePicker",
        "related": [
          "CalendarPicker",
          "Field",
          "Input"
        ],
        "slots": {
          "prefix": {
            "description": "Leading content (e.g. an `<icon-ui name=\"clock\">`); sits before the hour segment."
          },
          "suffix": {
            "description": "Trailing content (e.g. a timezone label); sits after the last segment."
          }
        },
        "states": [
          {
            "description": "Default, ready for interaction.",
            "name": "idle"
          },
          {
            "description": "One segment is the focus target.",
            "attribute": "editing",
            "name": "editing"
          },
          {
            "description": "Non-interactive; dimmed.",
            "attribute": "disabled",
            "name": "disabled"
          },
          {
            "description": "Keyboard focus ring on the host.",
            "name": "focused",
            "selector": ":focus-within"
          }
        ],
        "status": "stable",
        "synonyms": {
          "tags": [
            "TimeInput",
            "TimePicker"
          ],
          "time": [
            "clock",
            "hour",
            "minute",
            "alarm"
          ]
        },
        "tag": "time-picker-ui",
        "tokens": {
          "--time-picker-bg": {
            "description": "Host background color."
          },
          "--time-picker-border": {
            "description": "Host border color."
          },
          "--time-picker-fg": {
            "description": "Host text color."
          },
          "--time-picker-fg-muted": {
            "description": "Muted text color (empty placeholder + separator)."
          },
          "--time-picker-px": {
            "description": "Host inline padding."
          },
          "--time-picker-py": {
            "description": "Host block padding."
          },
          "--time-picker-radius": {
            "description": "Host border radius."
          },
          "--time-picker-segment-bg-focus": {
            "description": "Focused segment background."
          },
          "--time-picker-segment-fg-focus": {
            "description": "Focused segment text color."
          },
          "--time-picker-separator-fg": {
            "description": "Separator (`:`) text color."
          }
        },
        "traits": [
          "focusable"
        ],
        "version": 1
      }
    },
    "Toast": {
      "title": "Toast",
      "description": "Transient global notification popup with auto-dismiss + animated\nenter/exit. Variants map to severity (info / success / warning /\ndanger). Distinct from <alert-ui> (inline persistent banner) and\n<empty-state-ui> (zero-data placeholder). Use toast-ui for\nshort-lived feedback after user actions (\"Saved\", \"Copied to\nclipboard\"); the toast positions itself relative to viewport\n[position] regardless of where in the DOM it's rendered.\n",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "component": {
          "const": "Toast"
        },
        "duration": {
          "description": "Auto-dismiss time in milliseconds. 0 disables auto-dismiss.",
          "type": "number",
          "default": 4000
        },
        "position": {
          "description": "Screen position",
          "type": "string",
          "enum": [
            "top-left",
            "top-center",
            "top-right",
            "bottom-left",
            "bottom-center",
            "bottom-right"
          ],
          "default": "bottom-right"
        },
        "text": {
          "description": "Toast message text",
          "type": "string",
          "default": ""
        },
        "variant": {
          "description": "Semantic variant — `default | info | success | warning | danger`. `primary` and `muted` are style hints; canonical \"neutral but interesting\" tone is `info`.",
          "type": "string",
          "enum": [
            "default",
            "info",
            "success",
            "warning",
            "danger",
            "primary",
            "muted",
            "neutral"
          ],
          "default": "info"
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [],
        "category": "container",
        "composes": [],
        "events": {},
        "examples": [
          {
            "description": "Column of three toast notification components showing success, warning, and error variants.",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"Column\",\n    \"gap\": \"2\",\n    \"children\": [\n      \"t1\",\n      \"t2\",\n      \"t3\"\n    ]\n  },\n  {\n    \"id\": \"t1\",\n    \"component\": \"Toast\",\n    \"variant\": \"success\",\n    \"title\": \"Saved successfully\",\n    \"description\": \"Your changes have been saved.\",\n    \"dismissible\": true\n  },\n  {\n    \"id\": \"t2\",\n    \"component\": \"Toast\",\n    \"variant\": \"warning\",\n    \"title\": \"Storage almost full\",\n    \"description\": \"You are using 90% of your available storage.\",\n    \"dismissible\": true\n  },\n  {\n    \"id\": \"t3\",\n    \"component\": \"Toast\",\n    \"variant\": \"error\",\n    \"title\": \"Upload failed\",\n    \"description\": \"The file could not be uploaded. Please try again.\",\n    \"dismissible\": true\n  }\n]",
            "name": "toast-notification"
          }
        ],
        "keywords": [
          "toast",
          "inbox",
          "message",
          "snackbar",
          "popup",
          "warning",
          "error",
          "success",
          "info",
          "notification",
          "remind",
          "alert"
        ],
        "name": "UIToast",
        "related": [
          "Feed",
          "Alert",
          "FeedItem"
        ],
        "slots": {},
        "states": [
          {
            "description": "Default, ready for interaction.",
            "name": "idle"
          }
        ],
        "status": "stable",
        "synonyms": {
          "alert": [
            "alert",
            "banner",
            "toast",
            "notification"
          ],
          "error": [
            "alert",
            "error",
            "toast",
            "empty"
          ],
          "inbox": [
            "notification",
            "alert",
            "toast",
            "message",
            "email",
            "mail",
            "folder"
          ],
          "info": [
            "alert",
            "toast",
            "notification",
            "tooltip"
          ],
          "message": [
            "chat",
            "notification",
            "toast",
            "alert"
          ],
          "notification": [
            "notification",
            "toast",
            "alert",
            "badge"
          ],
          "popup": [
            "toast",
            "notification",
            "alert",
            "popover",
            "drawer"
          ],
          "remind": [
            "notification",
            "toast",
            "calendar"
          ],
          "snackbar": [
            "toast",
            "notification",
            "alert"
          ],
          "success": [
            "alert",
            "toast",
            "notification"
          ],
          "warning": [
            "alert",
            "error",
            "toast"
          ]
        },
        "tag": "toast-ui",
        "tokens": {
          "--toast-background": {
            "description": "Override background color"
          },
          "--toast-border-color": {
            "description": "Override border color"
          },
          "--toast-foreground": {
            "description": "Override text color"
          }
        },
        "traits": [],
        "version": 1
      }
    },
    "ToggleGroup": {
      "title": "ToggleGroup",
      "description": "Multi-select button group (unlike <segmented-ui> which is single-select). Hosts <toggle-option-ui> children, each independently toggleable; emits change events with the active value set. Use for filter chips or feature flag clusters; for single-select option groups use <segmented-ui> instead.",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "component": {
          "const": "ToggleGroup"
        },
        "single": {
          "description": "When true, restrict to one active option (single-select).",
          "type": "boolean",
          "default": false
        },
        "value": {
          "description": "Comma-separated selected values",
          "type": "string",
          "default": ""
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [],
        "category": "navigation",
        "composes": [],
        "events": {
          "change": {
            "description": "Fired when selection changes. detail: { value }",
            "detail": {
              "value": {
                "description": "New toggle-group value.",
                "type": "string"
              }
            }
          }
        },
        "examples": [
          {
            "description": "Basic ToggleGroup usage",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"Card\",\n    \"children\": [\n      \"sec\"\n    ]\n  },\n  {\n    \"id\": \"sec\",\n    \"component\": \"Section\",\n    \"children\": [\n      \"comp\"\n    ]\n  },\n  {\n    \"id\": \"comp\",\n    \"component\": \"ToggleGroup\",\n    \"value\": \"\"\n  }\n]",
            "name": "basic-toggle-group"
          }
        ],
        "keywords": [
          "togglegroup",
          "toggle-group",
          "toggle",
          "group"
        ],
        "name": "UIToggleGroup",
        "related": [
          "ToggleOption",
          "Segmented",
          "Radio"
        ],
        "slots": {
          "default": {
            "description": "Default slot — primary child content."
          }
        },
        "states": [
          {
            "description": "Default, ready for interaction.",
            "name": "idle"
          }
        ],
        "status": "stable",
        "synonyms": {
          "toggle-group": [
            "segmented-control",
            "option-group",
            "toggle-set"
          ]
        },
        "tag": "toggle-group-ui",
        "tokens": {
          "--toggle-group-border": {
            "description": "Border color of the group container"
          },
          "--toggle-group-height": {
            "description": "Height of the group container"
          },
          "--toggle-group-radius": {
            "description": "Border radius of the group container"
          },
          "--toggle-option-bg-hover": {
            "description": "Background color on hover"
          },
          "--toggle-option-border": {
            "description": "Border color between adjacent options"
          },
          "--toggle-option-duration": {
            "description": "Transition duration"
          },
          "--toggle-option-easing": {
            "description": "Transition easing function"
          },
          "--toggle-option-fg": {
            "description": "Default text color"
          },
          "--toggle-option-fg-disabled": {
            "description": "Text color when disabled"
          },
          "--toggle-option-fg-hover": {
            "description": "Text color on hover"
          },
          "--toggle-option-focus-ring": {
            "description": "Focus ring box-shadow"
          },
          "--toggle-option-font-size": {
            "description": "Font size for option text and icons"
          },
          "--toggle-option-gap": {
            "description": "Gap between icon and text within an option"
          },
          "--toggle-option-height": {
            "description": "Min-height of each option"
          },
          "--toggle-option-px": {
            "description": "Horizontal padding of each option"
          },
          "--toggle-option-selected-bg": {
            "description": "Background color when selected"
          },
          "--toggle-option-selected-fg": {
            "description": "Text color when selected"
          }
        },
        "traits": [],
        "version": 1
      }
    },
    "ToggleOption": {
      "title": "ToggleOption",
      "description": "Child of `<toggle-group-ui>`. One toggleable option inside a single-select or multi-select group. Pressed state mirrors `value` against the parent's selection.",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "component": {
          "const": "ToggleOption"
        },
        "disabled": {
          "description": "Disabled state — blocks pointer + keyboard activation.",
          "type": "boolean",
          "default": false
        },
        "icon": {
          "description": "Optional Phosphor icon name; renders as a leading icon.",
          "type": "string",
          "default": ""
        },
        "text": {
          "description": "Visible label text.",
          "type": "string",
          "default": ""
        },
        "value": {
          "description": "Stable identifier matched against the parent group's `value`.",
          "type": "string",
          "default": ""
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [],
        "category": "forms",
        "composes": [],
        "events": {},
        "examples": [],
        "keywords": [
          "toggle-option",
          "toggle-segment",
          "option-toggle",
          "segmented-option"
        ],
        "name": "UIToggleOption",
        "related": [
          "ToggleGroup",
          "Segment",
          "Radio"
        ],
        "slots": {},
        "states": [],
        "status": "stable",
        "synonyms": {
          "toggle-option": [
            "toggle-segment",
            "option-button",
            "segmented-option"
          ]
        },
        "tag": "toggle-option-ui",
        "tokens": {},
        "traits": [],
        "version": 1
      }
    },
    "ToggleScheme": {
      "title": "ToggleScheme",
      "description": "Icon-button primitive that toggles `color-scheme` between light and dark on a target element (default `:root`). Encapsulates the prefers-color-scheme initial-resolution, the inline-style write to the target, optional localStorage persistence (sharing the `adia-theme-` namespace with <theme-panel>), and the moon/sun icon swap. Replaces the hand-wired `<button-ui id=\"theme-toggle\">` + `applyScheme()` pattern previously duplicated across apps/genui, apps/construct-canvas, playgrounds/chat.",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "activeScheme": {
          "description": "Resolved scheme (\"light\" | \"dark\"). Read-only; mutate via .setScheme() or .toggle().",
          "type": "string",
          "enum": [
            "",
            "light",
            "dark"
          ],
          "default": ""
        },
        "color": {
          "description": "Semantic intent forwarded to the internal <button-ui>.",
          "type": "string",
          "enum": [
            "",
            "default",
            "accent",
            "info",
            "success",
            "warning",
            "danger"
          ],
          "default": ""
        },
        "component": {
          "const": "ToggleScheme"
        },
        "disabled": {
          "description": "Disables the internal button.",
          "type": "boolean",
          "default": false
        },
        "iconDark": {
          "description": "Phosphor icon shown when active-scheme is \"dark\" (clicking switches to light).",
          "type": "string",
          "default": "moon"
        },
        "iconLight": {
          "description": "Phosphor icon shown when active-scheme is \"light\" (clicking switches to dark).",
          "type": "string",
          "default": "sun"
        },
        "labelDark": {
          "description": "aria-label / title applied to the internal button when active-scheme is \"dark\".",
          "type": "string",
          "default": "Switch to light mode"
        },
        "labelLight": {
          "description": "aria-label / title applied to the internal button when active-scheme is \"light\".",
          "type": "string",
          "default": "Switch to dark mode"
        },
        "persist": {
          "description": "Persist the user's choice to localStorage under `${storage-prefix}scheme`.",
          "type": "boolean",
          "default": false
        },
        "scheme": {
          "description": "Initial scheme — \"auto\" follows prefers-color-scheme; \"light\" / \"dark\" force.",
          "type": "string",
          "enum": [
            "auto",
            "light",
            "dark"
          ],
          "default": "auto"
        },
        "size": {
          "description": "Sizing scale forwarded to the internal <button-ui>.",
          "type": "string",
          "enum": [
            "xs",
            "sm",
            "md",
            "lg",
            "xl"
          ],
          "default": "md"
        },
        "storagePrefix": {
          "description": "LocalStorage key prefix; default matches <theme-panel> for cross-element interop.",
          "type": "string",
          "default": "adia-theme-"
        },
        "target": {
          "description": "CSS selector for the element receiving `color-scheme`. \":root\" → <html>.",
          "type": "string",
          "default": ":root"
        },
        "variant": {
          "description": "Visual style forwarded to the internal <button-ui>. Defaults to \"ghost\" (matches app practice).",
          "type": "string",
          "enum": [
            "default",
            "solid",
            "outline",
            "ghost",
            "primary",
            "secondary",
            "soft"
          ],
          "default": "ghost"
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [],
        "category": "control",
        "composes": [
          "button-ui"
        ],
        "events": {
          "scheme-change": {
            "description": "Fired when the active scheme changes. detail contains { scheme: \"light\" | \"dark\", source: \"press\" | \"media\" | \"programmatic\" }.",
            "detail": {
              "scheme": {
                "description": "Active color scheme (\"light\" or \"dark\").",
                "type": "string"
              },
              "source": {
                "description": "Change source — \"press\" / \"media\" / \"programmatic\".",
                "type": "string"
              }
            }
          }
        },
        "examples": [
          {
            "description": "Drop into a toolbar / app header as a single icon-button affordance.",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"ToggleScheme\",\n    \"persist\": true\n  }\n]",
            "name": "header-action"
          }
        ],
        "keywords": [
          "scheme",
          "color-scheme",
          "dark-mode",
          "light-mode",
          "theme",
          "toggle",
          "moon",
          "sun"
        ],
        "name": "UIToggleScheme",
        "related": [
          "Button",
          "Switch"
        ],
        "slots": {},
        "states": [
          {
            "description": "Default, ready for interaction.",
            "name": "idle"
          },
          {
            "description": "Active scheme is light.",
            "attribute": "active-scheme",
            "name": "light"
          },
          {
            "description": "Active scheme is dark.",
            "attribute": "active-scheme",
            "name": "dark"
          },
          {
            "description": "Non-interactive; the internal button is disabled.",
            "attribute": "disabled",
            "name": "disabled"
          }
        ],
        "status": "stable",
        "synonyms": {
          "dark-mode": [
            "toggle-scheme"
          ],
          "theme-toggle": [
            "toggle-scheme"
          ],
          "toggle": [
            "toggle-scheme",
            "switch"
          ]
        },
        "tag": "toggle-scheme-ui",
        "tokens": {
          "--toggle-scheme-icon-transition": {
            "description": "Duration + easing for icon-color transition when scheme flips."
          }
        },
        "traits": [],
        "version": 1
      }
    },
    "Toolbar": {
      "title": "Toolbar",
      "description": "Horizontal action bar with automatic overflow. Items that don't fit move to a spillover popover menu.",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "align": {
          "description": "Item alignment",
          "type": "string",
          "default": "start"
        },
        "bordered": {
          "description": "Adds a border around the toolbar for visual separation from surrounding content.",
          "type": "boolean",
          "default": false
        },
        "component": {
          "const": "Toolbar"
        },
        "gap": {
          "description": "Gap between items",
          "type": "string",
          "default": "sm"
        },
        "overflow": {
          "description": "Overflow behavior",
          "type": "string",
          "enum": [
            "menu",
            "none"
          ],
          "default": "menu"
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [],
        "category": "layout",
        "composes": [
          "button-ui"
        ],
        "events": {},
        "examples": [
          {
            "description": "Toolbar with grouped icon buttons for text formatting, alignment, and undo/redo actions separated by dividers.",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"Toolbar\",\n    \"attrs\": {\n      \"aria-label\": \"Text formatting\"\n    },\n    \"children\": [\n      \"format-group\",\n      \"div1\",\n      \"align-group\",\n      \"div2\",\n      \"history-group\"\n    ]\n  },\n  {\n    \"id\": \"format-group\",\n    \"component\": \"Row\",\n    \"attrs\": {\n      \"gap\": \"xs\"\n    },\n    \"children\": [\n      \"btn-bold\",\n      \"btn-italic\",\n      \"btn-underline\"\n    ]\n  },\n  {\n    \"id\": \"btn-bold\",\n    \"component\": \"Button\",\n    \"attrs\": {\n      \"variant\": \"ghost\",\n      \"icon\": \"bold\",\n      \"aria-label\": \"Bold\",\n      \"size\": \"sm\"\n    }\n  },\n  {\n    \"id\": \"btn-italic\",\n    \"component\": \"Button\",\n    \"attrs\": {\n      \"variant\": \"ghost\",\n      \"icon\": \"italic\",\n      \"aria-label\": \"Italic\",\n      \"size\": \"sm\"\n    }\n  },\n  {\n    \"id\": \"btn-underline\",\n    \"component\": \"Button\",\n    \"attrs\": {\n      \"variant\": \"ghost\",\n      \"icon\": \"underline\",\n      \"aria-label\": \"Underline\",\n      \"size\": \"sm\"\n    }\n  },\n  {\n    \"id\": \"div1\",\n    \"component\": \"Divider\",\n    \"attrs\": {\n      \"orientation\": \"vertical\"\n    }\n  },\n  {\n    \"id\": \"align-group\",\n    \"component\": \"Row\",\n    \"attrs\": {\n      \"gap\": \"xs\"\n    },\n    \"children\": [\n      \"btn-align-left\",\n      \"btn-align-center\",\n      \"btn-align-right\"\n    ]\n  },\n  {\n    \"id\": \"btn-align-left\",\n    \"component\": \"Button\",\n    \"attrs\": {\n      \"variant\": \"ghost\",\n      \"icon\": \"align-left\",\n      \"aria-label\": \"Align left\",\n      \"size\": \"sm\"\n    }\n  },\n  {\n    \"id\": \"btn-align-center\",\n    \"component\": \"Button\",\n    \"attrs\": {\n      \"variant\": \"ghost\",\n      \"icon\": \"align-center\",\n      \"aria-label\": \"Align center\",\n      \"size\": \"sm\"\n    }\n  },\n  {\n    \"id\": \"btn-align-right\",\n    \"component\": \"Button\",\n    \"attrs\": {\n      \"variant\": \"ghost\",\n      \"icon\": \"align-right\",\n      \"aria-label\": \"Align right\",\n      \"size\": \"sm\"\n    }\n  },\n  {\n    \"id\": \"div2\",\n    \"component\": \"Divider\",\n    \"attrs\": {\n      \"orientation\": \"vertical\"\n    }\n  },\n  {\n    \"id\": \"history-group\",\n    \"component\": \"Row\",\n    \"attrs\": {\n      \"gap\": \"xs\"\n    },\n    \"children\": [\n      \"btn-undo\",\n      \"btn-redo\"\n    ]\n  },\n  {\n    \"id\": \"btn-undo\",\n    \"component\": \"Button\",\n    \"attrs\": {\n      \"variant\": \"ghost\",\n      \"icon\": \"undo\",\n      \"aria-label\": \"Undo\",\n      \"size\": \"sm\"\n    }\n  },\n  {\n    \"id\": \"btn-redo\",\n    \"component\": \"Button\",\n    \"attrs\": {\n      \"variant\": \"ghost\",\n      \"icon\": \"redo\",\n      \"aria-label\": \"Redo\",\n      \"size\": \"sm\"\n    }\n  }\n]",
            "name": "toolbar-buttons"
          }
        ],
        "keywords": [
          "toolbar",
          "action-bar",
          "button-group",
          "buttons",
          "actions"
        ],
        "name": "UIToolbar",
        "related": [
          "button",
          "divider"
        ],
        "slots": {},
        "states": [
          {
            "description": "Default, ready for interaction.",
            "name": "idle"
          }
        ],
        "status": "stable",
        "synonyms": {
          "action-bar": [
            "toolbar",
            "button"
          ],
          "actions": [
            "toolbar",
            "button",
            "popover"
          ],
          "button-group": [
            "toolbar",
            "button",
            "segmented"
          ],
          "buttons": [
            "toolbar",
            "button",
            "tooltip"
          ],
          "toolbar": [
            "toolbar",
            "button"
          ]
        },
        "tag": "toolbar-ui",
        "tokens": {},
        "traits": [],
        "version": 1
      }
    },
    "ToolbarGroup": {
      "title": "ToolbarGroup",
      "description": "Visual cluster of related actions inside a `<toolbar-ui>`. Provides role=\"group\" for assistive-tech grouping; no own visual chrome beyond a margin-collapsing gap with sibling groups.",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "component": {
          "const": "ToolbarGroup"
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [],
        "category": "navigation",
        "composes": [],
        "events": {},
        "examples": [],
        "keywords": [
          "toolbar-group",
          "button-group",
          "action-cluster",
          "toolbar-cluster"
        ],
        "name": "UIToolbarGroup",
        "related": [
          "Toolbar",
          "Button",
          "Divider"
        ],
        "slots": {},
        "states": [],
        "status": "stable",
        "synonyms": {
          "toolbar-group": [
            "button-group",
            "action-cluster",
            "toolbar-section"
          ]
        },
        "tag": "toolbar-group-ui",
        "tokens": {},
        "traits": [],
        "version": 1
      }
    },
    "Tooltip": {
      "title": "Tooltip",
      "description": "Tooltip popup. Two modes — default `follows=\"trigger\"` shows on hover/focus anchored to wrapped children; `follows=\"pointer\"` subscribes to chart-hover events from [for] and renders a data-viz card that tracks the pointer.",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "component": {
          "const": "Tooltip"
        },
        "delay": {
          "description": "Delay in milliseconds before showing the tooltip on hover (trigger mode only).",
          "type": "number",
          "default": 400
        },
        "follows": {
          "description": "`trigger` (default) pins to wrapped children via hover/focus. `pointer` subscribes to chart-hover/chart-leave events from [for] and positions at the pointer coordinates — used by chart-ui / heatmap-ui.",
          "type": "string",
          "enum": [
            "trigger",
            "pointer"
          ],
          "default": "trigger"
        },
        "for": {
          "description": "id-ref of a chart-ui / heatmap-ui to follow. Required when follows=pointer. The target must dispatch `chart-hover` and `chart-leave` events.",
          "type": "string",
          "default": ""
        },
        "indicator": {
          "description": "Color swatch shown beside each value row in pointer mode. `none` omits the swatch. Swatch color reads `--tooltip-indicator-color` which the host injects per-row from `--color-{seriesKey}`.",
          "type": "string",
          "enum": [
            "none",
            "dot",
            "line",
            "dashed"
          ],
          "default": "none"
        },
        "placement": {
          "description": "Preferred position relative to the anchor element (trigger mode only).",
          "type": "string",
          "enum": [
            "top",
            "bottom",
            "left",
            "right",
            "top-start",
            "top-end",
            "bottom-start",
            "bottom-end"
          ],
          "default": "top"
        },
        "text": {
          "description": "Tooltip text content displayed in the overlay (trigger mode only).",
          "type": "string",
          "default": ""
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [],
        "category": "container",
        "composes": [],
        "events": {},
        "examples": [
          {
            "description": "Row of icon buttons each wrapped in a Tooltip to provide accessible hover labels.",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"Row\",\n    \"attrs\": {\n      \"gap\": \"sm\"\n    },\n    \"children\": [\n      \"tip-edit\",\n      \"tip-duplicate\",\n      \"tip-share\",\n      \"tip-delete\"\n    ]\n  },\n  {\n    \"id\": \"tip-edit\",\n    \"component\": \"Tooltip\",\n    \"attrs\": {\n      \"content\": \"Edit item\"\n    },\n    \"children\": [\n      \"btn-edit\"\n    ]\n  },\n  {\n    \"id\": \"btn-edit\",\n    \"component\": \"Button\",\n    \"attrs\": {\n      \"variant\": \"ghost\",\n      \"icon\": \"edit\",\n      \"aria-label\": \"Edit\",\n      \"size\": \"sm\"\n    }\n  },\n  {\n    \"id\": \"tip-duplicate\",\n    \"component\": \"Tooltip\",\n    \"attrs\": {\n      \"content\": \"Duplicate item\"\n    },\n    \"children\": [\n      \"btn-duplicate\"\n    ]\n  },\n  {\n    \"id\": \"btn-duplicate\",\n    \"component\": \"Button\",\n    \"attrs\": {\n      \"variant\": \"ghost\",\n      \"icon\": \"copy\",\n      \"aria-label\": \"Duplicate\",\n      \"size\": \"sm\"\n    }\n  },\n  {\n    \"id\": \"tip-share\",\n    \"component\": \"Tooltip\",\n    \"attrs\": {\n      \"content\": \"Share item\"\n    },\n    \"children\": [\n      \"btn-share\"\n    ]\n  },\n  {\n    \"id\": \"btn-share\",\n    \"component\": \"Button\",\n    \"attrs\": {\n      \"variant\": \"ghost\",\n      \"icon\": \"share\",\n      \"aria-label\": \"Share\",\n      \"size\": \"sm\"\n    }\n  },\n  {\n    \"id\": \"tip-delete\",\n    \"component\": \"Tooltip\",\n    \"attrs\": {\n      \"content\": \"Delete item\"\n    },\n    \"children\": [\n      \"btn-delete\"\n    ]\n  },\n  {\n    \"id\": \"btn-delete\",\n    \"component\": \"Button\",\n    \"attrs\": {\n      \"variant\": \"danger\",\n      \"icon\": \"trash\",\n      \"aria-label\": \"Delete\",\n      \"size\": \"sm\"\n    }\n  }\n]",
            "name": "tooltip-buttons"
          }
        ],
        "keywords": [
          "tooltip",
          "info",
          "tutorial",
          "walkthrough",
          "tour",
          "help",
          "buttons",
          "hint",
          "popover"
        ],
        "name": "UITooltip",
        "related": [
          "button"
        ],
        "slots": {},
        "states": [
          {
            "description": "Default, ready for interaction.",
            "name": "idle"
          }
        ],
        "status": "stable",
        "synonyms": {
          "buttons": [
            "toolbar",
            "button",
            "tooltip"
          ],
          "help": [
            "faq",
            "accordion",
            "tooltip"
          ],
          "hint": [
            "tooltip",
            "button",
            "popover"
          ],
          "info": [
            "alert",
            "toast",
            "notification",
            "tooltip"
          ],
          "popover": [
            "popover",
            "menu",
            "tooltip"
          ],
          "tooltip": [
            "tooltip",
            "button",
            "popover"
          ],
          "tour": [
            "onboarding",
            "checklist",
            "wizard",
            "tooltip"
          ],
          "tutorial": [
            "onboarding",
            "checklist",
            "wizard",
            "tooltip"
          ],
          "walkthrough": [
            "onboarding",
            "checklist",
            "wizard",
            "tooltip"
          ]
        },
        "tag": "tooltip-ui",
        "tokens": {},
        "traits": [],
        "version": 1
      }
    },
    "Tour": {
      "title": "Tour",
      "description": "Spotlight-driven product tour / guided walkthrough. Hosts a sequence\nof `<tour-step>` children, each targeting an element via CSS selector.\nWhen active, dims the page with a scrim, cuts a \"hole\" around the\ncurrent step's target, and renders a popover next to it with step\ncontent + Skip / Previous / Next navigation.\n\nUse for first-run onboarding tours, feature introductions after a\nrelease, and inline walkthroughs the user opts into (\"Take the tour\").\nDistinct from `<onboarding-checklist-ui>` (persistent todo-list of\nsetup steps the user works through at their own pace) and from\n`<tooltip-ui>` (single hover hint with no orchestration).\n\nArchitecture: tour-ui is a behavioral wrapper (`display: contents`)\nthat reads target / title / content from `<tour-step>` children. On\nstart, mounts a spotlight + popover surface into `document.body`\n(top-layer via Popover API). The spotlight is a transparent\nposition:fixed element with a huge box-shadow that produces the\ndimmed scrim outside its bounds (single-element backdrop, no clip-path\nor SVG mask needed). The popover is anchored to the target via the\nsame `core/anchor.js` pattern used by menu-ui / context-menu-ui /\npopover-ui.\n",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "active": {
          "description": "Whether the tour is currently running. Setting to `true` mounts\nthe spotlight + popover; setting to `false` tears down.\n",
          "type": "boolean",
          "default": false
        },
        "auto-start": {
          "description": "Start the tour automatically when the element connects. Useful for\nfirst-run flows gated by a storage flag on the consumer side.\n",
          "type": "boolean",
          "default": false
        },
        "component": {
          "const": "Tour"
        },
        "step": {
          "description": "Current step index (0-based). Setting this property advances the\ntour to that step (updating spotlight + popover position).\n",
          "type": "number",
          "default": 0
        },
        "storage-key": {
          "description": "Optional localStorage key. When set, the tour records its\ncompletion state (`\"done\"`) to that key on finish/skip — and\nrefuses to auto-start on subsequent loads if the key is \"done\".\nUseful for \"show this tour once per user\" flows.\n",
          "type": "string",
          "default": ""
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [
          {
            "fix": "<tour-ui><tour-step target=\"#dashboard\" title=\"Dashboard\">Tour the dashboard…</tour-step>…</tour-ui>",
            "why": "Bare divs have no target / title — tour-ui can't position the spotlight.",
            "wrong": "<tour-ui><div>step 1 content</div><div>step 2 content</div></tour-ui>"
          },
          {
            "fix": "<tour-step target=\"#dashboard\">",
            "why": "target is a CSS selector — bare \"dashboard\" matches a <dashboard> element, NOT an id; use the # prefix.",
            "wrong": "<tour-step target=\"dashboard\">"
          }
        ],
        "category": "feedback",
        "composes": [
          "button-ui",
          "tour-step-ui"
        ],
        "events": {
          "tour-finish": {
            "description": "Fired when the user completes the last step. detail = { totalSteps }. Bubbles."
          },
          "tour-skip": {
            "description": "Fired when the user skips the tour mid-way. detail = { step, totalSteps }. Bubbles."
          },
          "tour-start": {
            "description": "Fired when the tour starts (after spotlight + popover mount). detail = { step }. Bubbles."
          },
          "tour-step-change": {
            "description": "Fired when the active step changes. detail = { from, to, totalSteps }. Bubbles."
          }
        },
        "examples": [
          {
            "description": "A 3-step product tour anchored to selector-resolved elements.",
            "a2ui": "[\n  { \"id\": \"tour\", \"component\": \"Tour\", \"auto-start\": true, \"children\": [\"s1\", \"s2\", \"s3\"] },\n  { \"id\": \"s1\", \"component\": \"TourStep\", \"target\": \"#dashboard\", \"title\": \"Your dashboard\", \"textContent\": \"Here's where you'll see your latest activity.\" },\n  { \"id\": \"s2\", \"component\": \"TourStep\", \"target\": \"#filters\", \"title\": \"Filters\", \"textContent\": \"Narrow results by status, owner, or date.\" },\n  { \"id\": \"s3\", \"component\": \"TourStep\", \"target\": \"#export\", \"title\": \"Export\", \"textContent\": \"Download a CSV of the current view.\" }\n]\n",
            "name": "basic-tour"
          }
        ],
        "keywords": [
          "tour",
          "product-tour",
          "walkthrough",
          "guided-tour",
          "spotlight",
          "coachmark",
          "feature-introduction"
        ],
        "name": "UITour",
        "related": [
          "tooltip",
          "popover",
          "onboarding-checklist"
        ],
        "slots": {
          "default": {
            "description": "<tour-step> children — each declares target + title + body content."
          }
        },
        "states": [
          {
            "description": "Tour is dormant; no scrim / popover rendered.",
            "name": "idle"
          },
          {
            "description": "Tour is running; scrim dims the page, current target is spotlighted.",
            "name": "active"
          },
          {
            "description": "Last step reached (Done is shown instead of Next).",
            "name": "complete"
          }
        ],
        "status": "stable",
        "synonyms": {
          "spotlight": [
            "coachmark",
            "feature-highlight"
          ],
          "tour": [
            "product-tour",
            "guided-tour",
            "walkthrough",
            "feature-intro"
          ]
        },
        "tag": "tour-ui",
        "tokens": {
          "--tour-popover-bg": {
            "description": "Background of the step-content popover.",
            "default": "var(--a-bg-subtle)"
          },
          "--tour-popover-border": {
            "description": "Border color of the popover.",
            "default": "var(--a-border-subtle)"
          },
          "--tour-popover-max-width": {
            "description": "Maximum width of the popover.",
            "default": "22rem"
          },
          "--tour-popover-min-width": {
            "description": "Minimum width of the popover (so step text wraps reasonably).",
            "default": "18rem"
          },
          "--tour-popover-radius": {
            "description": "Border-radius of the popover.",
            "default": "var(--a-radius-lg)"
          },
          "--tour-popover-shadow": {
            "description": "Shadow of the popover.",
            "default": "var(--a-shadow-lg)"
          },
          "--tour-scrim": {
            "description": "Backdrop scrim color (everything outside the spotlight).",
            "default": "var(--a-scrim-dialog)"
          },
          "--tour-spotlight-padding": {
            "description": "Padding around the target bounding box (the spotlight's \"halo\").",
            "default": "var(--a-space-2)"
          },
          "--tour-spotlight-radius": {
            "description": "Border radius of the spotlight cutout.",
            "default": "var(--a-radius-md)"
          }
        },
        "traits": [],
        "version": 1
      }
    },
    "TourStep": {
      "title": "TourStep",
      "description": "Single step inside a `<tour-ui>` walkthrough. Declares a target\nelement (via CSS selector), a title, and body content. The host\n`<tour-ui>` reads these declaratively and renders them in the\npopover as the user advances through the tour.\n\n`<tour-step>` itself renders nothing — it's a data carrier (light\nDOM source of truth). The tour-ui orchestrator clones the body\ncontent into the spotlight popover when the step becomes active.\n",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "title": {
          "description": "Step heading rendered in the popover.",
          "type": "string",
          "default": ""
        },
        "component": {
          "const": "TourStep"
        },
        "placement": {
          "description": "Preferred popover placement relative to the target. Same vocabulary\nas `core/anchor.js` (`top`, `bottom`, `left`, `right`,\n`bottom-start`, `bottom-end`, etc.). Auto-flips on viewport overflow\nvia position-try-fallbacks.\n",
          "type": "string",
          "enum": [
            "top",
            "bottom",
            "left",
            "right",
            "top-start",
            "top-end",
            "bottom-start",
            "bottom-end",
            "left-start",
            "left-end",
            "right-start",
            "right-end"
          ],
          "default": "bottom"
        },
        "target": {
          "description": "CSS selector for the element to spotlight when this step is\nactive. Resolved via `document.querySelector(target)` at step\nactivation time. If the selector matches nothing, the spotlight\nfalls back to viewport-center and the popover anchors to the\npage (no halo cutout).\n",
          "type": "string",
          "default": ""
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [
          {
            "fix": "<tour-step target=\"#dashboard\">",
            "why": "target is a CSS selector — bare \"dashboard\" doesn't match.",
            "wrong": "<tour-step target=\"dashboard\">"
          }
        ],
        "category": "feedback",
        "composes": [],
        "events": {},
        "examples": [],
        "keywords": [
          "tour-step",
          "walkthrough-step",
          "guided-step"
        ],
        "name": "UITourStep",
        "related": [
          "tour"
        ],
        "slots": {
          "default": {
            "description": "Body content rendered inside the step popover (plain text or inline HTML)."
          }
        },
        "states": [],
        "status": "stable",
        "synonyms": {
          "step": [
            "tour-step",
            "walkthrough-step"
          ]
        },
        "tag": "tour-step-ui",
        "tokens": {},
        "traits": [],
        "version": 1
      }
    },
    "Tree": {
      "title": "Tree",
      "description": "Collapsible tree container with keyboard navigation (arrow keys, Enter/Space). Manages selection across nested tree-item-ns.",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "component": {
          "const": "Tree"
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [],
        "category": "data",
        "composes": [
          "icon-ui"
        ],
        "events": {
          "tree-select": {
            "description": "Fired when an item is selected. detail: { item, text, value, ctrlKey, metaKey, shiftKey }. Modifier flags mirror the originating MouseEvent / KeyboardEvent; all default false for programmatic select() calls.\n",
            "detail": {
              "ctrlKey": {
                "description": "Ctrl key held during activation (false for programmatic select()).",
                "type": "boolean"
              },
              "item": {
                "description": "Selected tree-item element.",
                "type": "object"
              },
              "metaKey": {
                "description": "Meta (Cmd) key held during activation (false for programmatic select()).",
                "type": "boolean"
              },
              "shiftKey": {
                "description": "Shift key held during activation (false for programmatic select()).",
                "type": "boolean"
              },
              "text": {
                "description": "Item text content.",
                "type": "string"
              },
              "value": {
                "description": "Item value attribute.",
                "type": "string"
              }
            }
          }
        },
        "examples": [
          {
            "description": "Basic Tree usage",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"Card\",\n    \"children\": [\n      \"sec\"\n    ]\n  },\n  {\n    \"id\": \"sec\",\n    \"component\": \"Section\",\n    \"children\": [\n      \"comp\"\n    ]\n  },\n  {\n    \"id\": \"comp\",\n    \"component\": \"Tree\"\n  }\n]",
            "name": "basic-tree"
          }
        ],
        "keywords": [
          "tree",
          "folder"
        ],
        "name": "UITree",
        "related": [
          "TreeItem",
          "Nav",
          "List",
          "Accordion"
        ],
        "slots": {
          "default": {
            "description": "Holds the tree's top-level `<tree-item-ui>` children."
          },
          "icon": {
            "description": "Override slot for the per-node icon glyph. Tree-item's `[icon]` attr stamps a default Phosphor icon; the slot lets consumers fill custom icons (folder open/closed, file-type glyphs, branded markers)."
          }
        },
        "states": [
          {
            "description": "Default, ready for interaction.",
            "name": "idle"
          }
        ],
        "status": "stable",
        "synonyms": {
          "folder": [
            "inbox",
            "email",
            "sidebar",
            "nav",
            "tree"
          ]
        },
        "tag": "tree-ui",
        "tokens": {
          "--tree-actions-gap": {
            "description": "Gap between action icons"
          },
          "--tree-badge-bg": {
            "description": "Background color for the trailing badge (§184)."
          },
          "--tree-badge-fg": {
            "description": "Foreground color for the trailing badge (§184)."
          },
          "--tree-badge-px": {
            "description": "Inline padding for the trailing badge (§184)."
          },
          "--tree-badge-radius": {
            "description": "Border radius for the trailing badge (§184)."
          },
          "--tree-badge-size": {
            "description": "Font size for the trailing badge (§184)."
          },
          "--tree-bg-hover": {
            "description": "Background color on hover"
          },
          "--tree-bg-selected": {
            "description": "Background color when selected"
          },
          "--tree-caret-size": {
            "description": "Size of the collapse caret icon"
          },
          "--tree-duration": {
            "description": "Transition duration"
          },
          "--tree-easing": {
            "description": "Transition easing function"
          },
          "--tree-fg": {
            "description": "Primary text color"
          },
          "--tree-fg-muted": {
            "description": "Muted text color (icons, carets)"
          },
          "--tree-focus-ring": {
            "description": "Focus ring box-shadow"
          },
          "--tree-font-size": {
            "description": "Font size for tree items"
          },
          "--tree-icon-size": {
            "description": "Size of the item icon"
          },
          "--tree-indent": {
            "description": "Indentation per nesting level"
          },
          "--tree-row-gap": {
            "description": "Gap between elements within a row"
          },
          "--tree-row-height": {
            "description": "Height of each tree item row"
          },
          "--tree-row-px": {
            "description": "Inline-end padding of each row"
          },
          "--tree-row-radius": {
            "description": "Border radius of each row"
          }
        },
        "traits": [],
        "version": 1
      }
    },
    "TreeItem": {
      "title": "TreeItem",
      "description": "Child of <tree-ui>. One tree row with optional icon + text + trailing badge, plus nested tree-item-ui children for the collapsible hierarchy. Use inside <tree-ui> only.",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "badge": {
          "description": "Optional trailing badge text (count, label, etc.). Renders muted + small + right-aligned alongside the row, mirroring the nav-item-ui badge API. When empty, the badge slot stays empty.\n\nAdded in §184 (v0.5.5, FEEDBACK-08 §1).",
          "type": "string"
        },
        "component": {
          "const": "TreeItem"
        },
        "icon": {
          "description": "Optional leading icon name (Phosphor).",
          "type": "string"
        },
        "open": {
          "description": "When true, the item's children render expanded. Single-instance state; the parent `<tree-ui>` toggles this on click + Enter/Space + ArrowRight/ArrowLeft per tree-view APG.",
          "type": "boolean"
        },
        "selected": {
          "description": "Reflects the currently-selected item. Exactly one tree-item is selected per `<tree-ui>` parent (managed by the parent).",
          "type": "boolean"
        },
        "text": {
          "description": "Primary text rendered in the row.",
          "type": "string"
        },
        "value": {
          "description": "Stable value emitted in `tree-select` event detail.",
          "type": "string"
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [],
        "category": "data",
        "composes": [],
        "events": {},
        "examples": [],
        "keywords": [
          "tree-item",
          "tree-row",
          "tree-node",
          "hierarchy-item"
        ],
        "name": "UITreeItem",
        "related": [
          "Tree",
          "List",
          "Nav",
          "Accordion"
        ],
        "slots": {
          "actions": {
            "description": "Per-row action buttons (rename / add / overflow menu), right-aligned and hover-revealed. A declarative `slot=\"actions\"` child is adopted into the auto-stamped row (FEEDBACK-89), so it sits inline in the row rather than wrapping below it."
          },
          "caret": {
            "description": "Override slot for the expand/collapse caret. Auto-stamped as `<icon-ui slot=\"caret\" name=\"caret-right\">` (rotates on `[open]`, hidden for leaf nodes). Supply your own `slot=\"caret\"` child to customize — adopt-or-stamp moves a declarative caret into the row."
          },
          "icon": {
            "description": "Override the leading [icon] glyph with a custom slotted element (custom icon-ui, folder open/closed glyph, file-type marker). Mutually exclusive with the [icon] attribute — slot child wins."
          }
        },
        "states": [],
        "status": "stable",
        "synonyms": {
          "tree-item": [
            "tree-node",
            "tree-row",
            "hierarchy-row"
          ]
        },
        "tag": "tree-item-ui",
        "tokens": {},
        "traits": [],
        "version": 1
      }
    },
    "Upload": {
      "title": "Upload",
      "description": "File upload with drag-and-drop. Uses showOpenFilePicker with input[type=file] fallback. Form-associated.",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "required": {
          "description": "Marks as required",
          "type": "boolean",
          "default": false
        },
        "accept": {
          "description": "Accepted file types (e.g. image/*,.pdf)",
          "type": "string",
          "default": ""
        },
        "component": {
          "const": "Upload"
        },
        "disabled": {
          "description": "Disables interaction",
          "type": "boolean",
          "default": false
        },
        "hint": {
          "description": "Help text below the dropzone",
          "type": "string",
          "default": ""
        },
        "label": {
          "description": "Label text above the dropzone",
          "type": "string",
          "default": ""
        },
        "multiple": {
          "description": "Allows selecting multiple files",
          "type": "boolean",
          "default": false
        },
        "name": {
          "description": "Form field name",
          "type": "string",
          "default": ""
        },
        "value": {
          "description": "Current value",
          "type": "string",
          "default": ""
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [],
        "category": "input",
        "composes": [],
        "events": {
          "change": {
            "description": "Fired when files are selected via click or drag-and-drop"
          }
        },
        "examples": [
          {
            "description": "Data import wizard with file upload, progress tracking, and action buttons.",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"Card\",\n    \"children\": [\n      \"hdr\",\n      \"sec\"\n    ]\n  },\n  {\n    \"id\": \"hdr\",\n    \"component\": \"Header\",\n    \"children\": [\n      \"title\"\n    ]\n  },\n  {\n    \"id\": \"title\",\n    \"component\": \"Text\",\n    \"slot\": \"heading\",\n    \"textContent\": \"Import Data\"\n  },\n  {\n    \"id\": \"sec\",\n    \"component\": \"Section\",\n    \"children\": [\n      \"col\"\n    ]\n  },\n  {\n    \"id\": \"col\",\n    \"component\": \"Column\",\n    \"children\": [\n      \"upload\",\n      \"prog\",\n      \"actions\"\n    ],\n    \"gap\": \"4\"\n  },\n  {\n    \"id\": \"upload\",\n    \"component\": \"Upload\",\n    \"accept\": \".csv,.xlsx\",\n    \"label\": \"Drop files here\"\n  },\n  {\n    \"id\": \"prog\",\n    \"component\": \"Progress\",\n    \"value\": 0,\n    \"max\": 100\n  },\n  {\n    \"id\": \"actions\",\n    \"component\": \"Row\",\n    \"children\": [\n      \"cancel\",\n      \"start\"\n    ],\n    \"gap\": \"2\"\n  },\n  {\n    \"id\": \"cancel\",\n    \"component\": \"Button\",\n    \"text\": \"Cancel\",\n    \"variant\": \"outline\"\n  },\n  {\n    \"id\": \"start\",\n    \"component\": \"Button\",\n    \"text\": \"Import\",\n    \"variant\": \"primary\"\n  }\n]",
            "name": "data-import"
          },
          {
            "description": "Card with upload component, file list area, and submit button.",
            "a2ui": "[\n  {\n    \"id\": \"root\",\n    \"component\": \"Card\",\n    \"children\": [\n      \"hdr\",\n      \"sec\",\n      \"ftr\"\n    ]\n  },\n  {\n    \"id\": \"hdr\",\n    \"component\": \"Header\",\n    \"children\": [\n      \"title\",\n      \"desc\"\n    ]\n  },\n  {\n    \"id\": \"title\",\n    \"component\": \"Text\",\n    \"slot\": \"heading\",\n    \"textContent\": \"Upload Files\",\n    \"variant\": \"section\"\n  },\n  {\n    \"id\": \"desc\",\n    \"component\": \"Text\",\n    \"slot\": \"description\",\n    \"variant\": \"caption\",\n    \"textContent\": \"Drag and drop or browse to upload\"\n  },\n  {\n    \"id\": \"sec\",\n    \"component\": \"Section\",\n    \"children\": [\n      \"content\"\n    ]\n  },\n  {\n    \"id\": \"content\",\n    \"component\": \"Column\",\n    \"children\": [\n      \"uploader\",\n      \"file-list\"\n    ],\n    \"gap\": \"4\"\n  },\n  {\n    \"id\": \"uploader\",\n    \"component\": \"Upload\",\n    \"accept\": \"*/*\",\n    \"multiple\": true\n  },\n  {\n    \"id\": \"file-list\",\n    \"component\": \"Column\",\n    \"children\": [\n      \"file-list-label\"\n    ],\n    \"gap\": \"2\"\n  },\n  {\n    \"id\": \"file-list-label\",\n    \"component\": \"Text\",\n    \"variant\": \"caption\",\n    \"textContent\": \"No files selected\"\n  },\n  {\n    \"id\": \"ftr\",\n    \"component\": \"Footer\",\n    \"children\": [\n      \"ftr-actions\"\n    ]\n  },\n  {\n    \"id\": \"ftr-actions\",\n    \"component\": \"Row\",\n    \"children\": [\n      \"cancel-btn\",\n      \"submit-btn\"\n    ]\n  },\n  {\n    \"id\": \"cancel-btn\",\n    \"component\": \"Button\",\n    \"text\": \"Cancel\",\n    \"variant\": \"ghost\"\n  },\n  {\n    \"id\": \"submit-btn\",\n    \"component\": \"Button\",\n    \"text\": \"Upload\",\n    \"variant\": \"primary\"\n  }\n]",
            "name": "file-upload-form"
          }
        ],
        "keywords": [
          "upload",
          "attach",
          "dropzone",
          "drag",
          "import",
          "transfer",
          "file-manager",
          "files"
        ],
        "name": "UIUpload",
        "related": [
          "progress",
          "button",
          "grid",
          "image",
          "input"
        ],
        "slots": {},
        "states": [
          {
            "description": "Default, ready for interaction.",
            "name": "idle"
          },
          {
            "description": "Non-interactive; dimmed.",
            "attribute": "disabled",
            "name": "disabled"
          }
        ],
        "status": "stable",
        "synonyms": {
          "attach": [
            "file",
            "upload",
            "image"
          ],
          "drag": [
            "file",
            "upload",
            "import",
            "kanban"
          ],
          "dropzone": [
            "file",
            "upload",
            "image",
            "import"
          ],
          "file-manager": [
            "data",
            "table",
            "file",
            "upload"
          ],
          "files": [
            "data",
            "table",
            "file",
            "upload"
          ],
          "import": [
            "data",
            "import",
            "file",
            "upload",
            "table"
          ],
          "transfer": [
            "data",
            "import",
            "upload"
          ],
          "upload": [
            "file",
            "upload",
            "image",
            "import",
            "data"
          ]
        },
        "tag": "upload-ui",
        "tokens": {},
        "traits": [],
        "version": 1
      }
    },
    "VisuallyHidden": {
      "title": "VisuallyHidden",
      "description": "Accessibility utility — content visible to screen readers but hidden\nvisually (the canonical \"sr-only\" pattern). Use for icon-only buttons,\ncontextual labels on duplicate controls, status announcements via\nlive regions, and any text the AT needs but sighted users don't.\n\nDistinct from `[hidden]` / `display:none` (hidden from EVERYONE\nincluding AT) and from `aria-label` (which replaces visible text but\ndoesn't add invisible text). When you need both visible and invisible\ntext on the same element, `<visually-hidden-ui>` is the wrapper for\nthe invisible part.\n",
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/CatalogComponentCommon"
        }
      ],
      "properties": {
        "component": {
          "const": "VisuallyHidden"
        }
      },
      "required": [
        "component"
      ],
      "unevaluatedProperties": false,
      "x-adiaui": {
        "anti_patterns": [
          {
            "fix": "<button-ui icon=\"trash\"><visually-hidden-ui>Delete</visually-hidden-ui></button-ui> OR set aria-label=\"Delete\" — but visually-hidden-ui scales to longer context (\"Delete row 42 in the orders table\") without overloading the label attribute.",
            "why": "Icon-only buttons with no accessible name are unreadable for screen-reader users.",
            "wrong": "<button-ui icon=\"trash\"></button-ui>"
          }
        ],
        "category": "utility",
        "composes": [],
        "events": {},
        "examples": [
          {
            "description": "Sr-only label for an icon-only button.",
            "a2ui": "[\n  { \"id\": \"btn\", \"component\": \"Button\", \"icon\": \"trash\", \"children\": [\"lbl\"] },\n  { \"id\": \"lbl\", \"component\": \"VisuallyHidden\", \"textContent\": \"Delete row\" }\n]\n",
            "name": "icon-button-label"
          }
        ],
        "keywords": [
          "visually-hidden",
          "sr-only",
          "screen-reader",
          "a11y",
          "accessibility"
        ],
        "name": "UIVisuallyHidden",
        "related": [
          "text"
        ],
        "slots": {
          "default": {
            "description": "The text or content to hide visually while keeping accessible."
          }
        },
        "states": [
          {
            "description": "Default — content is visually hidden but in the accessibility tree.",
            "name": "idle"
          }
        ],
        "status": "stable",
        "synonyms": {},
        "tag": "visually-hidden-ui",
        "tokens": {},
        "traits": [],
        "version": 1
      }
    }
  },
  "functions": {
    "required": {
      "description": "Returns true when `value` is non-empty (non-null string, number, boolean, or array). Used in `checks` to gate Button enablement and surface inline errors.",
      "type": "object",
      "properties": {
        "args": {
          "type": "object",
          "properties": {
            "value": {
              "$ref": "#/$defs/DynamicString"
            }
          },
          "required": [
            "value"
          ],
          "additionalProperties": false
        },
        "call": {
          "const": "required"
        },
        "returnType": {
          "const": "boolean"
        }
      },
      "required": [
        "call",
        "args"
      ],
      "unevaluatedProperties": false
    },
    "equals": {
      "description": "Returns true when `value` deep-equals `target`. Used for confirm-password checks (compare field to its sibling).",
      "type": "object",
      "properties": {
        "args": {
          "type": "object",
          "properties": {
            "target": {
              "$ref": "#/$defs/DynamicString"
            },
            "value": {
              "$ref": "#/$defs/DynamicString"
            }
          },
          "required": [
            "value",
            "target"
          ],
          "additionalProperties": false
        },
        "call": {
          "const": "equals"
        },
        "returnType": {
          "const": "boolean"
        }
      },
      "required": [
        "call",
        "args"
      ],
      "unevaluatedProperties": false
    },
    "formatCurrency": {
      "description": "Render a numeric amount as currency in the given ISO-4217 code.",
      "type": "object",
      "properties": {
        "args": {
          "type": "object",
          "properties": {
            "currency": {
              "description": "ISO-4217 code (USD, EUR, JPY, …).",
              "type": "string"
            },
            "locale": {
              "type": "string"
            },
            "value": {
              "$ref": "#/$defs/DynamicNumber"
            }
          },
          "required": [
            "value",
            "currency"
          ],
          "additionalProperties": false
        },
        "call": {
          "const": "formatCurrency"
        },
        "returnType": {
          "const": "string"
        }
      },
      "required": [
        "call",
        "args"
      ],
      "unevaluatedProperties": false
    },
    "formatDate": {
      "description": "Format a date (ISO string or epoch ms). `style` shortcuts: short/medium/long/full; or pass an explicit Intl options shape.",
      "type": "object",
      "properties": {
        "args": {
          "type": "object",
          "properties": {
            "locale": {
              "type": "string"
            },
            "style": {
              "enum": [
                "short",
                "medium",
                "long",
                "full",
                "relative"
              ]
            },
            "value": {
              "$ref": "#/$defs/DynamicString"
            }
          },
          "required": [
            "value"
          ],
          "additionalProperties": false
        },
        "call": {
          "const": "formatDate"
        },
        "returnType": {
          "const": "string"
        }
      },
      "required": [
        "call",
        "args"
      ],
      "unevaluatedProperties": false
    },
    "formatNumber": {
      "description": "Localize a number. `style` = decimal (default) | percent | unit. `unit` paired with style=unit. `maximumFractionDigits` + `minimumFractionDigits` control precision.",
      "type": "object",
      "properties": {
        "args": {
          "type": "object",
          "properties": {
            "locale": {
              "type": "string"
            },
            "maximumFractionDigits": {
              "type": "number"
            },
            "minimumFractionDigits": {
              "type": "number"
            },
            "style": {
              "enum": [
                "decimal",
                "percent",
                "unit"
              ],
              "default": "decimal"
            },
            "unit": {
              "type": "string"
            },
            "value": {
              "$ref": "#/$defs/DynamicNumber"
            }
          },
          "required": [
            "value"
          ],
          "additionalProperties": false
        },
        "call": {
          "const": "formatNumber"
        },
        "returnType": {
          "const": "string"
        }
      },
      "required": [
        "call",
        "args"
      ],
      "unevaluatedProperties": false
    },
    "formatString": {
      "description": "Template-interpolate a string using `${/abs/path}` for absolute JSON Pointers, `${rel/path}` for relative paths inside a template child scope, and `${fn(arg: value)}` for nested calls. The `${...}` grammar is ONLY legal inside this function's `value` arg; every other string property in A2UI is static or path-bound via DynamicString.",
      "type": "object",
      "properties": {
        "args": {
          "type": "object",
          "properties": {
            "value": {
              "description": "Template. Supports ${path}, ${fn(...)}, \\${ escapes.",
              "type": "string"
            }
          },
          "required": [
            "value"
          ],
          "additionalProperties": false
        },
        "call": {
          "const": "formatString"
        },
        "returnType": {
          "const": "string"
        }
      },
      "required": [
        "call",
        "args"
      ],
      "unevaluatedProperties": false
    },
    "isEmail": {
      "description": "Convenience check — returns true when `value` parses as a well-formed email address.",
      "type": "object",
      "properties": {
        "args": {
          "type": "object",
          "properties": {
            "value": {
              "$ref": "#/$defs/DynamicString"
            }
          },
          "required": [
            "value"
          ],
          "additionalProperties": false
        },
        "call": {
          "const": "isEmail"
        },
        "returnType": {
          "const": "boolean"
        }
      },
      "required": [
        "call",
        "args"
      ],
      "unevaluatedProperties": false
    },
    "matchesPattern": {
      "description": "Returns true when `value` matches the regex `pattern` (tested as ^(?:pattern)$ — anchored full match).",
      "type": "object",
      "properties": {
        "args": {
          "type": "object",
          "properties": {
            "pattern": {
              "type": "string"
            },
            "value": {
              "$ref": "#/$defs/DynamicString"
            }
          },
          "required": [
            "value",
            "pattern"
          ],
          "additionalProperties": false
        },
        "call": {
          "const": "matchesPattern"
        },
        "returnType": {
          "const": "boolean"
        }
      },
      "required": [
        "call",
        "args"
      ],
      "unevaluatedProperties": false
    },
    "maxLength": {
      "description": "Returns true when `value`'s length is at most `max`.",
      "type": "object",
      "properties": {
        "args": {
          "type": "object",
          "properties": {
            "max": {
              "$ref": "#/$defs/DynamicNumber"
            },
            "value": {
              "$ref": "#/$defs/DynamicString"
            }
          },
          "required": [
            "value",
            "max"
          ],
          "additionalProperties": false
        },
        "call": {
          "const": "maxLength"
        },
        "returnType": {
          "const": "boolean"
        }
      },
      "required": [
        "call",
        "args"
      ],
      "unevaluatedProperties": false
    },
    "minLength": {
      "description": "Returns true when `value`'s length is at least `min`. Strings count characters; arrays count entries.",
      "type": "object",
      "properties": {
        "args": {
          "type": "object",
          "properties": {
            "min": {
              "$ref": "#/$defs/DynamicNumber"
            },
            "value": {
              "$ref": "#/$defs/DynamicString"
            }
          },
          "required": [
            "value",
            "min"
          ],
          "additionalProperties": false
        },
        "call": {
          "const": "minLength"
        },
        "returnType": {
          "const": "boolean"
        }
      },
      "required": [
        "call",
        "args"
      ],
      "unevaluatedProperties": false
    },
    "not": {
      "description": "Logical negation — inverts a boolean result. Useful for composing custom checks.",
      "type": "object",
      "properties": {
        "args": {
          "type": "object",
          "properties": {
            "value": {
              "$ref": "#/$defs/DynamicBoolean"
            }
          },
          "required": [
            "value"
          ],
          "additionalProperties": false
        },
        "call": {
          "const": "not"
        },
        "returnType": {
          "const": "boolean"
        }
      },
      "required": [
        "call",
        "args"
      ],
      "unevaluatedProperties": false
    },
    "pluralize": {
      "description": "Pick a variant based on `count`. Supply `one` and `plural` (and optionally `zero` / `other`). The return is the chosen variant string.",
      "type": "object",
      "properties": {
        "args": {
          "type": "object",
          "properties": {
            "count": {
              "$ref": "#/$defs/DynamicNumber"
            },
            "one": {
              "type": "string"
            },
            "other": {
              "type": "string"
            },
            "plural": {
              "type": "string"
            },
            "zero": {
              "type": "string"
            }
          },
          "required": [
            "count",
            "plural"
          ],
          "additionalProperties": false
        },
        "call": {
          "const": "pluralize"
        },
        "returnType": {
          "const": "string"
        }
      },
      "required": [
        "call",
        "args"
      ],
      "unevaluatedProperties": false
    }
  },
  "theme": {
    "description": "Design-system tokens applied surface-wide. Minimal baseline; extend per catalog.",
    "type": "object",
    "properties": {
      "agentDisplayName": {
        "type": "string"
      },
      "colorScheme": {
        "enum": [
          "light",
          "dark",
          "auto"
        ]
      },
      "iconUrl": {
        "type": "string",
        "format": "uri"
      },
      "primaryColor": {
        "type": "string"
      }
    }
  },
  "$defs": {
    "AccessibilityAttributes": {
      "type": "object",
      "properties": {
        "description": {
          "description": "Additional instructions/context for assistive tech.",
          "$ref": "#/$defs/DynamicString"
        },
        "label": {
          "description": "Short label (1–3 words) used by assistive tech.",
          "$ref": "#/$defs/DynamicString"
        }
      },
      "additionalProperties": false
    },
    "Action": {
      "description": "An event handler binding. The `event` identifies which AdiaEvent to match; `handler` names a registered handler function; `config` supplies handler arguments.",
      "type": "object",
      "properties": {
        "config": {
          "description": "Handler-specific configuration (URL, path, payload, etc.).",
          "type": "object"
        },
        "event": {
          "$ref": "#/$defs/Event"
        },
        "handler": {
          "description": "Handler name registered in the wiring registry.",
          "type": "string"
        },
        "onError": {
          "type": "array",
          "items": {
            "$ref": "#/$defs/Action"
          }
        },
        "onSuccess": {
          "type": "array",
          "items": {
            "$ref": "#/$defs/Action"
          }
        }
      },
      "required": [
        "event",
        "handler"
      ],
      "additionalProperties": false
    },
    "CatalogComponentCommon": {
      "description": "Shared properties accepted by every AdiaUI catalog component. Split into three concerns: runtime hooks (visible, style, slot), universal child region (children), and global HTML attributes the renderer honors on every custom element (nomargin, truncate, grow, color, weight, size, align, justify, text). Per-component schemas can restrict these further via their own enum declarations; allOf composition means the stricter rule wins.",
      "type": "object",
      "properties": {
        "title": {
          "description": "Short heading/identifier. Used by EmptyState/Dialog/Modal etc. for heading slot shortcut.",
          "$ref": "#/$defs/DynamicString"
        },
        "align": {
          "description": "Alignment role. Values depend on container (flex cross-axis for row-ui/col-ui, text for typography).",
          "$ref": "#/$defs/DynamicString"
        },
        "ariaHidden": {
          "description": "Accessibility hidden state (maps to aria-hidden at runtime).",
          "$ref": "#/$defs/DynamicBoolean"
        },
        "ariaLabel": {
          "description": "Accessibility label (maps to aria-label at runtime).",
          "$ref": "#/$defs/DynamicString"
        },
        "children": {
          "description": "Ordered list of child component ids (or a template binding).",
          "$ref": "#/$defs/ChildList"
        },
        "color": {
          "description": "Foreground color role. Common values: text, text-strong, subtle, muted, accent, success, warning, danger, info.",
          "$ref": "#/$defs/DynamicString"
        },
        "grow": {
          "description": "flex: 1 — fills remaining space in a flex parent (row-ui/col-ui).",
          "$ref": "#/$defs/DynamicBoolean"
        },
        "hidden": {
          "description": "HTML [hidden] — element not displayed but remains in the DOM.",
          "$ref": "#/$defs/DynamicBoolean"
        },
        "icon": {
          "description": "Leading Phosphor icon name. Components that support leading icons render it; others ignore.",
          "$ref": "#/$defs/DynamicString"
        },
        "justify": {
          "description": "Main-axis justification for flex/grid containers.",
          "$ref": "#/$defs/DynamicString"
        },
        "label": {
          "description": "Accessible label or leading heading — aria-label or first-line text depending on component.",
          "$ref": "#/$defs/DynamicString"
        },
        "nomargin": {
          "description": "Remove default block margins (typography + prose elements).",
          "$ref": "#/$defs/DynamicBoolean"
        },
        "prose": {
          "description": "Content-optimized spacing/typography for long-form prose containers.",
          "$ref": "#/$defs/DynamicBoolean"
        },
        "size": {
          "description": "Sizing role. Common values: xs, sm, md, lg, xl. Per-component schemas may narrow.",
          "$ref": "#/$defs/DynamicString"
        },
        "slot": {
          "description": "Named slot to project into when child of a slotted container.",
          "type": "string"
        },
        "style": {
          "description": "Inline CSS string applied to the host element (use sparingly; prefer variants).",
          "type": "string"
        },
        "text": {
          "description": "Short text payload rendered via CSS attr(text) on ::after (Button, Badge, Tag, etc.).",
          "$ref": "#/$defs/DynamicString"
        },
        "textAlign": {
          "description": "Text alignment — start, center, end, justify.",
          "$ref": "#/$defs/DynamicString"
        },
        "truncate": {
          "description": "Single-line ellipsis when the container constrains width.",
          "$ref": "#/$defs/DynamicBoolean"
        },
        "visible": {
          "description": "When false, the component is not rendered.",
          "$ref": "#/$defs/DynamicBoolean"
        },
        "weight": {
          "description": "Font weight role. Common values: thin, light, normal, medium, semibold, bold.",
          "$ref": "#/$defs/DynamicString"
        }
      }
    },
    "Checkable": {
      "description": "Mixed into components that support validation checks (Input, TextArea, Button, etc.). Failed checks block dependent actions (e.g. a Button with unmet checks is auto-disabled).",
      "type": "object",
      "properties": {
        "checks": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "args": {
                "type": "object"
              },
              "call": {
                "type": "string"
              },
              "errorMessage": {
                "$ref": "#/$defs/DynamicString"
              }
            },
            "required": [
              "call"
            ],
            "additionalProperties": false
          }
        }
      }
    },
    "ChildList": {
      "oneOf": [
        {
          "description": "A static list of child component ids.",
          "type": "array",
          "items": {
            "$ref": "#/$defs/ComponentId"
          }
        },
        {
          "description": "A template-driven list: binds a data model list and stamps a component template per item.",
          "type": "object",
          "properties": {
            "componentId": {
              "$ref": "#/$defs/ComponentId"
            },
            "path": {
              "type": "string"
            }
          },
          "required": [
            "path",
            "componentId"
          ],
          "additionalProperties": false
        }
      ]
    },
    "ComponentCommon": {
      "type": "object",
      "properties": {
        "accessibility": {
          "$ref": "#/$defs/AccessibilityAttributes"
        },
        "id": {
          "$ref": "#/$defs/ComponentId"
        }
      },
      "required": [
        "id"
      ]
    },
    "ComponentId": {
      "description": "Reference to another component's id within the same surface. Validators follow this ref to verify the target exists.",
      "type": "string"
    },
    "DynamicBoolean": {
      "oneOf": [
        {
          "type": "boolean"
        },
        {
          "type": "object",
          "properties": {
            "path": {
              "type": "string"
            }
          },
          "required": [
            "path"
          ],
          "additionalProperties": false
        },
        {
          "$ref": "#/$defs/FunctionCall"
        }
      ]
    },
    "DynamicNumber": {
      "oneOf": [
        {
          "type": "number"
        },
        {
          "type": "object",
          "properties": {
            "path": {
              "type": "string"
            }
          },
          "required": [
            "path"
          ],
          "additionalProperties": false
        },
        {
          "$ref": "#/$defs/FunctionCall"
        }
      ]
    },
    "DynamicString": {
      "description": "A string that may be a literal, a path-bound reference, or the result of a FunctionCall.",
      "oneOf": [
        {
          "type": "string"
        },
        {
          "description": "Binds to a JSON Pointer in the surface's data model.",
          "type": "object",
          "properties": {
            "path": {
              "type": "string"
            }
          },
          "required": [
            "path"
          ],
          "additionalProperties": false
        },
        {
          "$ref": "#/$defs/FunctionCall"
        }
      ]
    },
    "DynamicStringList": {
      "oneOf": [
        {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        {
          "type": "object",
          "properties": {
            "path": {
              "type": "string"
            }
          },
          "required": [
            "path"
          ],
          "additionalProperties": false
        },
        {
          "$ref": "#/$defs/FunctionCall"
        }
      ]
    },
    "Event": {
      "description": "A typed event selector. Matches events fired by components (submit, input, click, mount, etc.) optionally scoped to a component id.",
      "type": "object",
      "properties": {
        "condition": {
          "description": "Guard — the action only fires when the condition holds.",
          "type": "object",
          "properties": {
            "equals": {},
            "exists": {
              "type": "boolean"
            },
            "notEquals": {},
            "path": {
              "type": "string"
            }
          }
        },
        "debounce": {
          "description": "Debounce window in ms.",
          "type": "number"
        },
        "event": {
          "description": "Event type name (e.g. 'submit', 'input', 'press').",
          "type": "string"
        },
        "target": {
          "description": "Optional — scopes the match to a specific component. Omit for surface-level events.",
          "$ref": "#/$defs/ComponentId"
        },
        "throttle": {
          "description": "Throttle window in ms.",
          "type": "number"
        }
      },
      "required": [
        "event"
      ],
      "additionalProperties": false
    },
    "FunctionCall": {
      "description": "A reference to a client-side function. No code crosses the wire — only names and typed arguments.",
      "type": "object",
      "properties": {
        "args": {
          "description": "Named arguments; shape validated by the function's own schema entry.",
          "type": "object"
        },
        "call": {
          "description": "Name of a function registered in the catalog's `functions` dictionary.",
          "type": "string"
        }
      },
      "required": [
        "call"
      ],
      "additionalProperties": false
    }
  }
}
