{
  "components": [
    {
      "name": "Button",
      "description": "Action trigger. With `href` renders an anchor with identical styling (D33); `disabled` then maps to `aria-disabled`.",
      "slots": [],
      "props": [
        {
          "name": "variant",
          "type": "\"accent\" | \"accent-subtle\" | \"neutral\" | \"neutral-subtle\" | \"ghost\" | \"danger\" | \"danger-subtle\" | \"outline\"",
          "required": false,
          "default": "neutral",
          "description": "Visual variant."
        },
        {
          "name": "size",
          "type": "24 | 32 | 40 | 48",
          "required": false,
          "default": 32,
          "description": "Height in px (24 | 32 | 40 | 48)."
        },
        {
          "name": "href",
          "type": "string",
          "required": false,
          "default": null,
          "description": "Render as an anchor with this href (D33). disabled → aria-disabled,\nno href attribute, pointer-events: none."
        },
        {
          "name": "target",
          "type": "string",
          "required": false,
          "default": null,
          "description": "Anchor target; only used with href."
        },
        {
          "name": "rel",
          "type": "string",
          "required": false,
          "default": null,
          "description": "Anchor rel; only used with href."
        },
        {
          "name": "ref",
          "type": "Ref<HTMLButtonElement | HTMLAnchorElement>",
          "required": false,
          "default": null,
          "description": "Forwarded ref to the underlying element."
        },
        {
          "name": "className",
          "type": "string",
          "required": false,
          "default": null,
          "description": "Additional CSS class name(s) merged onto the component's root element."
        }
      ]
    },
    {
      "name": "IconButton",
      "description": "Square icon-only button; same variant/size/href contract as Button. Give it an accessible name (`aria-label`).",
      "slots": [],
      "props": [
        {
          "name": "variant",
          "type": "\"accent\" | \"neutral\" | \"ghost\" | \"danger\"",
          "required": false,
          "default": "neutral",
          "description": "Visual variant."
        },
        {
          "name": "size",
          "type": "24 | 32 | 40 | 48",
          "required": false,
          "default": 32,
          "description": "Square size in px (24 | 32 | 40 | 48)."
        },
        {
          "name": "href",
          "type": "string",
          "required": false,
          "default": null,
          "description": "Render as an anchor with this href (D33). disabled → aria-disabled,\nno href attribute, pointer-events: none."
        },
        {
          "name": "target",
          "type": "string",
          "required": false,
          "default": null,
          "description": "Anchor target; only used with href."
        },
        {
          "name": "rel",
          "type": "string",
          "required": false,
          "default": null,
          "description": "Anchor rel; only used with href."
        },
        {
          "name": "ref",
          "type": "Ref<HTMLButtonElement | HTMLAnchorElement>",
          "required": false,
          "default": null,
          "description": "Forwarded ref to the underlying element."
        },
        {
          "name": "className",
          "type": "string",
          "required": false,
          "default": null,
          "description": "Additional CSS class name(s) merged onto the component's root element."
        }
      ]
    },
    {
      "name": "Card",
      "description": "Content container with an optional edge-to-edge media slot; `stacked` (media above body) or `featured` (media beside body) layout.",
      "slots": [],
      "props": [
        {
          "name": "variant",
          "type": "\"stacked\" | \"featured\"",
          "required": false,
          "default": "stacked",
          "description": "stacked = media above body; featured = media beside body (~1.6fr/1fr), stacks under md."
        },
        {
          "name": "media",
          "type": "ReactNode",
          "required": false,
          "default": null,
          "description": "Media slot rendered edge-to-edge (img, AspectRatio, …)."
        },
        {
          "name": "hoverLift",
          "type": "boolean",
          "required": false,
          "default": false,
          "description": "Lift on hover: translateY(-6px) over --psi-duration-350."
        },
        {
          "name": "ref",
          "type": "Ref<HTMLDivElement>",
          "required": false,
          "default": null,
          "description": "Forwarded ref to the root element."
        },
        {
          "name": "className",
          "type": "string",
          "required": false,
          "default": null,
          "description": "Additional CSS class name(s) merged onto the component's root element."
        }
      ]
    },
    {
      "name": "Panel",
      "description": "Elevated surface panel (D51): secondary background, faint hairline, radius-12 — the shared --psi-surface-* recipe Dialog's panel also binds. Not a Card: no media slot, no hover lift, opaque by design.",
      "slots": [
        {
          "name": "body",
          "accepts": {},
          "cardinality": "1..*",
          "order": 1
        }
      ],
      "props": [
        {
          "name": "padding",
          "type": "16 | 24",
          "required": false,
          "default": 24,
          "description": "Inner padding in px."
        },
        {
          "name": "ref",
          "type": "Ref<HTMLDivElement>",
          "required": false,
          "default": null,
          "description": "Forwarded ref to the root element."
        },
        {
          "name": "className",
          "type": "string",
          "required": false,
          "default": null,
          "description": "Additional CSS class name(s) merged onto the component's root element."
        }
      ]
    },
    {
      "name": "Input",
      "description": "Single-line text input with pixel-true heights (24–48) and an error state. Inside a Field, id/aria-describedby/aria-invalid/required are wired automatically (D49).",
      "slots": [],
      "props": [
        {
          "name": "size",
          "type": "24 | 32 | 40 | 48",
          "required": false,
          "default": 32,
          "description": "Height in px (24 | 32 | 40 | 48)."
        },
        {
          "name": "error",
          "type": "boolean",
          "required": false,
          "default": false,
          "description": "Show error styling. Inside a Field, the Field's error also lights this."
        },
        {
          "name": "ref",
          "type": "Ref<HTMLInputElement>",
          "required": false,
          "default": null,
          "description": "Forwarded ref to the underlying `<input>` element."
        },
        {
          "name": "placeholder",
          "type": "string",
          "required": false,
          "default": null,
          "description": "Native placeholder text shown while the field is empty (only on components whose host element supports it)."
        },
        {
          "name": "className",
          "type": "string",
          "required": false,
          "default": null,
          "description": "Additional CSS class name(s) merged onto the component's root element."
        }
      ]
    },
    {
      "name": "Select",
      "description": "Styled native `<select>` with pixel-true heights (24–48) and an error state. Inside a Field, id/aria-describedby/aria-invalid/required are wired automatically (D49).",
      "slots": [],
      "props": [
        {
          "name": "size",
          "type": "24 | 32 | 40 | 48",
          "required": false,
          "default": 32,
          "description": "Height in px (24 | 32 | 40 | 48). Replaces the native `size` attribute\n(which sets the visible option-row count on a listbox-style `<select>`)\nwith the design system's control height in pixels."
        },
        {
          "name": "error",
          "type": "boolean",
          "required": false,
          "default": false,
          "description": "Show error styling. Inside a Field, the Field's error also lights this."
        },
        {
          "name": "ref",
          "type": "Ref<HTMLSelectElement>",
          "required": false,
          "default": null,
          "description": "Forwarded ref to the underlying `<select>` element."
        },
        {
          "name": "className",
          "type": "string",
          "required": false,
          "default": null,
          "description": "Additional CSS class name(s) merged onto the component's root element."
        }
      ]
    },
    {
      "name": "Field",
      "description": "Labeled form-row wrapper: label above, control, one message line below — description normally, error when set (aria-live). Auto-wires id/aria-describedby/aria-invalid into Input and Select (D49).",
      "slots": [
        {
          "name": "label",
          "accepts": {},
          "cardinality": "0..1",
          "order": 1
        },
        {
          "name": "body",
          "accepts": {},
          "cardinality": "1..*",
          "order": 2
        },
        {
          "name": "description",
          "accepts": {},
          "cardinality": "0..1",
          "order": 3
        }
      ],
      "props": [
        {
          "name": "label",
          "type": "ReactNode",
          "required": false,
          "default": null,
          "description": "Label content; renders a <label> (or <legend> in group mode)."
        },
        {
          "name": "description",
          "type": "ReactNode",
          "required": false,
          "default": null,
          "description": "Helper line under the control; replaced by error when error is set."
        },
        {
          "name": "error",
          "type": "ReactNode",
          "required": false,
          "default": null,
          "description": "Error content; when truthy it replaces the description and switches the\nfield (and a wrapped Input/Select) into error state."
        },
        {
          "name": "required",
          "type": "boolean",
          "required": false,
          "default": false,
          "description": "Renders the required marker and flows `required` to the control."
        },
        {
          "name": "group",
          "type": "boolean",
          "required": false,
          "default": false,
          "description": "Group mode: fieldset/legend wrapping several self-labeled controls\n(Checkbox/Switch); the message describes the whole group."
        },
        {
          "name": "htmlFor",
          "type": "string",
          "required": false,
          "default": null,
          "description": "Override the generated control id (pair it with the same id on the control)."
        },
        {
          "name": "ref",
          "type": "Ref<HTMLDivElement | HTMLFieldSetElement>",
          "required": false,
          "default": null,
          "description": "Forwarded ref to the root element."
        },
        {
          "name": "className",
          "type": "string",
          "required": false,
          "default": null,
          "description": "Additional CSS class name(s) merged onto the component's root element."
        }
      ]
    },
    {
      "name": "Dialog",
      "description": "Modal dialog on the native <dialog> top layer: focus trap, aria-modal and focus restore come from the platform; title/footer slots, Esc/backdrop/ close-button dismissal via onClose(reason) (D50).",
      "slots": [
        {
          "name": "title",
          "accepts": {
            "contracts": [
              "inline-content"
            ]
          },
          "cardinality": "0..1",
          "order": 1
        },
        {
          "name": "body",
          "accepts": {},
          "cardinality": "0..*",
          "order": 2
        },
        {
          "name": "footer",
          "accepts": {
            "components": [
              "Button"
            ],
            "contracts": [
              "inline-content"
            ]
          },
          "cardinality": "0..*",
          "order": 3
        }
      ],
      "props": [
        {
          "name": "open",
          "type": "boolean",
          "required": true,
          "default": null,
          "description": "Controlled open state; syncs to showModal()/close()."
        },
        {
          "name": "onClose",
          "type": "(reason: \"esc\" | \"backdrop\" | \"close-button\") => void",
          "required": true,
          "default": null,
          "description": "Called on every dismissal attempt with its source; the consumer flips `open`."
        },
        {
          "name": "title",
          "type": "ReactNode",
          "required": false,
          "default": null,
          "description": "Heading; renders an <h2> wired to aria-labelledby. Without it, pass aria-label."
        },
        {
          "name": "footer",
          "type": "ReactNode",
          "required": false,
          "default": null,
          "description": "Action row (Buttons — one accent per group, danger for destructive)."
        },
        {
          "name": "width",
          "type": "400 | 560 | 720",
          "required": false,
          "default": 560,
          "description": "Panel width in px (400 | 560 | 720)."
        },
        {
          "name": "dismissible",
          "type": "boolean",
          "required": false,
          "default": true,
          "description": "false = no close button, Esc and backdrop swallowed — footer is the only exit."
        },
        {
          "name": "ref",
          "type": "Ref<HTMLDialogElement>",
          "required": false,
          "default": null,
          "description": "Forwarded ref to the underlying <dialog> element."
        },
        {
          "name": "className",
          "type": "string",
          "required": false,
          "default": null,
          "description": "Additional CSS class name(s) merged onto the component's root element."
        }
      ]
    },
    {
      "name": "Checkbox",
      "description": "Native checkbox with a built-in label; for independent binary choices.",
      "slots": [],
      "props": [
        {
          "name": "children",
          "type": "ReactNode",
          "required": false,
          "default": null,
          "description": "Label text."
        },
        {
          "name": "ref",
          "type": "Ref<HTMLInputElement>",
          "required": false,
          "default": null,
          "description": "Forwarded ref to the underlying `<input type=\"checkbox\">` element."
        },
        {
          "name": "className",
          "type": "string",
          "required": false,
          "default": null,
          "description": "Additional CSS class name(s) merged onto the component's root element."
        }
      ]
    },
    {
      "name": "Switch",
      "description": "On/off toggle (`role=\"switch\"`) with a built-in label; for settings that take effect immediately.",
      "slots": [],
      "props": [
        {
          "name": "children",
          "type": "ReactNode",
          "required": false,
          "default": null,
          "description": "Label text."
        },
        {
          "name": "ref",
          "type": "Ref<HTMLInputElement>",
          "required": false,
          "default": null,
          "description": "Forwarded ref to the underlying `<input type=\"checkbox\" role=\"switch\">` element."
        },
        {
          "name": "className",
          "type": "string",
          "required": false,
          "default": null,
          "description": "Additional CSS class name(s) merged onto the component's root element."
        }
      ]
    },
    {
      "name": "Tag",
      "description": "Compact label for status or category; semantic variants, optional subtle tint and dismiss button.",
      "slots": [],
      "props": [
        {
          "name": "variant",
          "type": "\"neutral\" | \"accent\" | \"success\" | \"warning\" | \"danger\"",
          "required": false,
          "default": "neutral",
          "description": "Semantic color variant."
        },
        {
          "name": "subtle",
          "type": "boolean",
          "required": false,
          "default": false,
          "description": "Use tinted background with semantic foreground."
        },
        {
          "name": "onDismiss",
          "type": "(() => void)",
          "required": false,
          "default": null,
          "description": "When provided, renders a dismiss button that calls this handler."
        },
        {
          "name": "ref",
          "type": "Ref<HTMLSpanElement>",
          "required": false,
          "default": null,
          "description": "Forwarded ref to the underlying `<span>` element."
        },
        {
          "name": "className",
          "type": "string",
          "required": false,
          "default": null,
          "description": "Additional CSS class name(s) merged onto the component's root element."
        }
      ]
    },
    {
      "name": "Toolbar",
      "description": "Horizontal grouping row for filter/search controls (D52). Wraps on overflow; zero JS. Deliberately NOT ARIA role=\"toolbar\" — that role contracts roving-tabindex arrow-key navigation, wrong for form controls. With aria-label it announces as role=\"group\".",
      "slots": [
        {
          "name": "body",
          "accepts": {},
          "cardinality": "0..*",
          "order": 1
        }
      ],
      "props": [
        {
          "name": "gap",
          "type": "8 | 12 | 16",
          "required": false,
          "default": 8,
          "description": "Gap between controls in px."
        },
        {
          "name": "ref",
          "type": "Ref<HTMLDivElement>",
          "required": false,
          "default": null,
          "description": "Forwarded ref to the root element."
        },
        {
          "name": "className",
          "type": "string",
          "required": false,
          "default": null,
          "description": "Additional CSS class name(s) merged onto the component's root element."
        }
      ]
    },
    {
      "name": "Tooltip",
      "description": "Short hover/focus hint attached to a single trigger element.",
      "slots": [],
      "props": [
        {
          "name": "content",
          "type": "ReactNode",
          "required": true,
          "default": null,
          "description": "Tooltip content."
        },
        {
          "name": "children",
          "type": "ReactElement<Record<string, unknown>, string | JSXElementConstructor<any>>",
          "required": true,
          "default": null,
          "description": "The trigger element (must accept ref, onMouseEnter/Leave, onFocus/Blur)."
        },
        {
          "name": "placement",
          "type": "\"top\" | \"bottom\" | \"left\" | \"right\"",
          "required": false,
          "default": "top",
          "description": "Preferred placement."
        }
      ]
    },
    {
      "name": "NavBar",
      "description": "Top navigation bar with brand, nav-link, and trailing-action slots.",
      "slots": [],
      "props": [
        {
          "name": "brand",
          "type": "ReactNode",
          "required": false,
          "default": null,
          "description": "Brand slot (wordmark / logo link), leading edge."
        },
        {
          "name": "actions",
          "type": "ReactNode",
          "required": false,
          "default": null,
          "description": "Trailing actions slot (theme switch, CTA)."
        },
        {
          "name": "children",
          "type": "ReactNode",
          "required": false,
          "default": null,
          "description": "Nav links."
        },
        {
          "name": "ref",
          "type": "Ref<HTMLElement>",
          "required": false,
          "default": null,
          "description": "Forwarded ref to the header element."
        },
        {
          "name": "className",
          "type": "string",
          "required": false,
          "default": null,
          "description": "Additional CSS class name(s) merged onto the component's root element."
        }
      ]
    },
    {
      "name": "AspectRatio",
      "description": "Fixed-aspect-ratio box that sizes its child media.",
      "slots": [],
      "props": [
        {
          "name": "ratio",
          "type": "number",
          "required": true,
          "default": null,
          "description": "Width/height ratio, e.g. 16/10 or 4/5."
        },
        {
          "name": "ref",
          "type": "Ref<HTMLDivElement>",
          "required": false,
          "default": null,
          "description": "Forwarded ref to the frame element."
        },
        {
          "name": "className",
          "type": "string",
          "required": false,
          "default": null,
          "description": "Additional CSS class name(s) merged onto the component's root element."
        }
      ]
    }
  ]
}
