@loworbitstudio/visor 1.18.1 → 1.20.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -96,7 +96,7 @@
96
96
  {
97
97
  "path": "components/ui/text/text.module.css",
98
98
  "type": "registry:ui",
99
- "content": "/* Text base styles */\n.base {\n font-family: var(--font-body, ui-sans-serif, system-ui, sans-serif);\n margin: 0;\n}\n\n/* Sizes */\n.sizeXs {\n font-size: var(--font-size-xs, 0.75rem);\n}\n\n.sizeSm {\n font-size: var(--font-size-sm, 0.875rem);\n}\n\n.sizeMd {\n font-size: var(--font-size-base, 1rem);\n}\n\n.sizeLg {\n font-size: var(--font-size-lg, 1.125rem);\n}\n\n.sizeXl {\n font-size: var(--font-size-xl, 1.25rem);\n}\n\n/* Weights */\n.weightNormal {\n font-weight: var(--font-weight-normal, 400);\n}\n\n.weightMedium {\n font-weight: var(--font-weight-medium, 500);\n}\n\n.weightSemibold {\n font-weight: var(--font-weight-semibold, 600);\n}\n\n.weightBold {\n font-weight: var(--font-weight-bold, 700);\n}\n\n/* Colors */\n.colorPrimary {\n color: var(--text-primary, #111827);\n}\n\n.colorSecondary {\n color: var(--text-secondary, #6b7280);\n}\n\n.colorTertiary {\n color: var(--text-tertiary, #9ca3af);\n}\n\n.colorInherit {\n color: inherit;\n}\n\n/* Line height */\n.leadingTight {\n line-height: var(--line-height-tight, 1.25);\n}\n\n.leadingSnug {\n line-height: var(--line-height-snug, 1.375);\n}\n\n.leadingNormal {\n line-height: var(--line-height-normal, 1.5);\n}\n\n.leadingRelaxed {\n line-height: var(--line-height-relaxed, 1.625);\n}\n\n.leadingLoose {\n line-height: var(--line-height-loose, 2);\n}\n"
99
+ "content": "/* Text base styles */\n.base {\n font-family: var(--font-body, inherit);\n margin: 0;\n}\n\n/* Sizes */\n.sizeXs {\n font-size: var(--font-size-xs, 0.75rem);\n}\n\n.sizeSm {\n font-size: var(--font-size-sm, 0.875rem);\n}\n\n.sizeMd {\n font-size: var(--font-size-base, 1rem);\n}\n\n.sizeLg {\n font-size: var(--font-size-lg, 1.125rem);\n}\n\n.sizeXl {\n font-size: var(--font-size-xl, 1.25rem);\n}\n\n/* Weights */\n.weightNormal {\n font-weight: var(--font-weight-normal, 400);\n}\n\n.weightMedium {\n font-weight: var(--font-weight-medium, 500);\n}\n\n.weightSemibold {\n font-weight: var(--font-weight-semibold, 600);\n}\n\n.weightBold {\n font-weight: var(--font-weight-bold, 700);\n}\n\n/* Colors */\n.colorPrimary {\n color: var(--text-primary, #111827);\n}\n\n.colorSecondary {\n color: var(--text-secondary, #6b7280);\n}\n\n.colorTertiary {\n color: var(--text-tertiary, #9ca3af);\n}\n\n.colorInherit {\n color: inherit;\n}\n\n/* Line height */\n.leadingTight {\n line-height: var(--line-height-tight, 1.25);\n}\n\n.leadingSnug {\n line-height: var(--line-height-snug, 1.375);\n}\n\n.leadingNormal {\n line-height: var(--line-height-normal, 1.5);\n}\n\n.leadingRelaxed {\n line-height: var(--line-height-relaxed, 1.625);\n}\n\n.leadingLoose {\n line-height: var(--line-height-loose, 2);\n}\n"
100
100
  }
101
101
  ]
102
102
  },
@@ -141,12 +141,12 @@
141
141
  {
142
142
  "path": "components/ui/button/button.tsx",
143
143
  "type": "registry:ui",
144
- "content": "import * as React from \"react\"\nimport { Slot } from \"@radix-ui/react-slot\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\nimport { cn } from \"../../../lib/utils\"\nimport styles from \"./button.module.css\"\nimport {\n Tooltip,\n TooltipContent,\n TooltipTrigger,\n} from \"../tooltip/tooltip\"\n\nconst buttonVariants = cva(styles.base, {\n variants: {\n variant: {\n default: styles.variantDefault,\n secondary: styles.variantSecondary,\n outline: styles.variantOutline,\n ghost: styles.variantGhost,\n destructive: styles.variantDestructive,\n },\n size: {\n sm: styles.sizeSm,\n md: styles.sizeMd,\n lg: styles.sizeLg,\n },\n },\n defaultVariants: {\n variant: \"default\",\n size: \"md\",\n },\n})\n\nexport interface ButtonProps\n extends React.ButtonHTMLAttributes<HTMLButtonElement>,\n VariantProps<typeof buttonVariants> {\n asChild?: boolean\n /**\n * When true, the button renders in an inert gated state — visually dimmed,\n * cursor not-allowed, and click handlers suppressed. Uses `aria-disabled`\n * instead of the native `disabled` attribute so the button remains\n * keyboard-focusable (required for the tooltip to be accessible).\n *\n * Note: a `<TooltipProvider>` ancestor is required when `gatedReason` is set.\n */\n gated?: boolean\n /**\n * Explanation surfaced in an anchored tooltip when the button is gated.\n * Only rendered when `gated` is also true.\n * Example: \"You can't delete this — you're not an owner\"\n */\n gatedReason?: string\n}\n\nconst Button = React.forwardRef<HTMLButtonElement, ButtonProps>(\n ({ className, variant, size, asChild, gated, gatedReason, onClick, ...props }, ref) => {\n const Comp = asChild ? Slot : \"button\"\n\n const handleClick = React.useCallback(\n (e: React.MouseEvent<HTMLButtonElement>) => {\n if (gated) return\n onClick?.(e)\n },\n [gated, onClick]\n )\n\n const button = (\n <Comp\n className={cn(buttonVariants({ variant, size }), className)}\n ref={ref}\n aria-disabled={gated ? true : undefined}\n data-gated={gated ? \"true\" : undefined}\n data-gated-reason={gated && gatedReason ? gatedReason : undefined}\n onClick={handleClick}\n {...props}\n />\n )\n\n if (gated && gatedReason) {\n return (\n <Tooltip>\n <TooltipTrigger asChild>{button}</TooltipTrigger>\n <TooltipContent>{gatedReason}</TooltipContent>\n </Tooltip>\n )\n }\n\n return button\n }\n)\nButton.displayName = \"Button\"\n\nexport { Button, buttonVariants }\n"
144
+ "content": "import * as React from \"react\"\nimport { Slot } from \"@radix-ui/react-slot\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\nimport { cn } from \"../../../lib/utils\"\nimport styles from \"./button.module.css\"\nimport {\n Tooltip,\n TooltipContent,\n TooltipTrigger,\n} from \"../tooltip/tooltip\"\n\nconst buttonVariants = cva(styles.base, {\n variants: {\n variant: {\n default: styles.variantDefault,\n secondary: styles.variantSecondary,\n outline: styles.variantOutline,\n ghost: styles.variantGhost,\n destructive: styles.variantDestructive,\n },\n size: {\n sm: styles.sizeSm,\n md: styles.sizeMd,\n lg: styles.sizeLg,\n dlg: styles.sizeDlg,\n },\n },\n defaultVariants: {\n variant: \"default\",\n size: \"md\",\n },\n})\n\nexport interface ButtonProps\n extends React.ButtonHTMLAttributes<HTMLButtonElement>,\n VariantProps<typeof buttonVariants> {\n asChild?: boolean\n /**\n * When true, the button renders in an inert gated state — visually dimmed,\n * cursor not-allowed, and click handlers suppressed. Uses `aria-disabled`\n * instead of the native `disabled` attribute so the button remains\n * keyboard-focusable (required for the tooltip to be accessible).\n *\n * Note: a `<TooltipProvider>` ancestor is required when `gatedReason` is set.\n */\n gated?: boolean\n /**\n * Explanation surfaced in an anchored tooltip when the button is gated.\n * Only rendered when `gated` is also true.\n * Example: \"You can't delete this — you're not an owner\"\n */\n gatedReason?: string\n}\n\nconst Button = React.forwardRef<HTMLButtonElement, ButtonProps>(\n ({ className, variant, size, asChild, gated, gatedReason, onClick, ...props }, ref) => {\n const Comp = asChild ? Slot : \"button\"\n\n const handleClick = React.useCallback(\n (e: React.MouseEvent<HTMLButtonElement>) => {\n if (gated) return\n onClick?.(e)\n },\n [gated, onClick]\n )\n\n const button = (\n <Comp\n className={cn(buttonVariants({ variant, size }), className)}\n ref={ref}\n aria-disabled={gated ? true : undefined}\n data-gated={gated ? \"true\" : undefined}\n data-gated-reason={gated && gatedReason ? gatedReason : undefined}\n onClick={handleClick}\n {...props}\n />\n )\n\n if (gated && gatedReason) {\n return (\n <Tooltip>\n <TooltipTrigger asChild>{button}</TooltipTrigger>\n <TooltipContent>{gatedReason}</TooltipContent>\n </Tooltip>\n )\n }\n\n return button\n }\n)\nButton.displayName = \"Button\"\n\nexport { Button, buttonVariants }\n"
145
145
  },
146
146
  {
147
147
  "path": "components/ui/button/button.module.css",
148
148
  "type": "registry:ui",
149
- "content": "/* Button base styles */\n.base {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: var(--spacing-2, 0.5rem);\n white-space: nowrap;\n border-radius: var(--radius-md, 0.375rem);\n font-size: var(--font-size-sm, 0.875rem);\n font-weight: var(--font-weight-medium, 500);\n line-height: 1;\n cursor: pointer;\n border: 1px solid transparent;\n transition: background-color var(--motion-duration-150, 150ms) var(--motion-easing-default, ease-in-out), color var(--motion-duration-150, 150ms) var(--motion-easing-default, ease-in-out), border-color var(--motion-duration-150, 150ms) var(--motion-easing-default, ease-in-out), opacity var(--motion-duration-150, 150ms) var(--motion-easing-default, ease-in-out), transform var(--motion-duration-150, 150ms) var(--motion-easing-default, ease-in-out);\n text-decoration: none;\n outline: none;\n}\n\n.base:focus-visible {\n outline: var(--focus-ring-width, 2px) solid var(--border-focus, currentColor);\n outline-offset: var(--focus-ring-offset, 2px);\n}\n\n.base:active:not(:disabled) {\n transform: translateY(1px);\n transition: none;\n}\n\n.base:disabled {\n pointer-events: none;\n opacity: 0.5;\n}\n\n/* Variants */\n.variantDefault {\n background-color: var(--interactive-primary-bg, var(--primary, #111827));\n color: var(--interactive-primary-text, #f9fafb);\n}\n\n.variantSecondary {\n background-color: var(--interactive-secondary-bg, #f3f4f6);\n color: var(--interactive-secondary-text, #111827);\n}\n\n/* Editorial density: secondary on the card tier, ghost truly transparent.\n * Direct values — the editorial design language owns control surfaces, so the\n * theme's --interactive-secondary-bg / --interactive-ghost-bg are deliberately\n * bypassed (matches the blessed overlay, which out-cascaded the palette). */\n:global([data-density=\"editorial\"]) .variantSecondary {\n background-color: var(--surface-card, #ffffff);\n}\n\n:global([data-density=\"editorial\"]) .variantGhost {\n background-color: transparent;\n}\n\n.variantOutline {\n background-color: transparent;\n color: var(--text-primary, #111827);\n border-color: var(--border-strong, #e5e7eb);\n}\n\n.variantGhost {\n background-color: var(--interactive-ghost-bg, transparent);\n color: var(--text-primary, #111827);\n}\n\n.variantDestructive {\n background-color: var(--interactive-destructive-bg, #ef4444);\n color: var(--interactive-destructive-text, #fef2f2);\n}\n\n@media (hover: hover) {\n .variantDefault:hover {\n background-color: var(--interactive-primary-bg-hover, #1f2937);\n }\n\n .variantSecondary:hover {\n background-color: var(--interactive-secondary-bg-hover, #e5e7eb);\n }\n\n .variantOutline:hover {\n background-color: var(--surface-muted, #f3f4f6);\n }\n\n .variantGhost:hover {\n background-color: var(--interactive-ghost-bg-hover, var(--surface-muted, #f3f4f6));\n }\n\n .variantDestructive:hover {\n background-color: var(--interactive-destructive-bg-hover, #dc2626);\n }\n}\n\n/* Open / active state — ghost variant only. OPT-IN, strictly additive.\n A ghost Button reads as \"held\" while its popover/menu is open so the\n trigger no longer needs an inline style. Three opt-in triggers, all\n resolving to the same held look:\n - data-state=\"open\" — forwarded automatically by Radix when the\n Button is the trigger via <Trigger asChild> (Popover/DropdownMenu).\n - data-active=\"true\" — manual non-Radix triggers (mirrors the\n sidebar `data-active` convention).\n - .isActive — className opt-in (mirrors sidebar/section-nav).\n Default ghost rendering is untouched: none of these match unless a\n consumer explicitly sets them. Matches the prototype-overlay held look:\n background var(--surface-subtle), color var(--text-primary). */\n.variantGhost[data-state=\"open\"],\n.variantGhost[data-active=\"true\"],\n.variantGhost.isActive {\n background-color: var(--surface-subtle, var(--surface-muted, #f3f4f6));\n color: var(--text-primary, #111827);\n}\n\n/* Gated state — orthogonal to variant, works with all variants */\n.base[data-gated=\"true\"] {\n opacity: var(--opacity-40, 0.4);\n cursor: not-allowed;\n border-color: var(--border-default, #e5e7eb);\n}\n\n/* Editorial density: gated reads like plain disabled (the blessed admin\n builds render gated actions at the 0.5 disabled opacity). */\n:global([data-density=\"editorial\"]) .base[data-gated=\"true\"] {\n opacity: 0.5;\n}\n\n/* Suppress active transform when gated */\n.base[data-gated=\"true\"]:active {\n transform: none;\n transition: opacity var(--motion-duration-150, 150ms) var(--motion-easing-default, ease-in-out);\n}\n\n/* Sizes\n Default (no data-density attr) rendering is byte-identical to the prior\n canonical values. Under data-density=\"editorial\" (set on any ancestor,\n typically the app root), the editorial density axis re-drives specific\n metrics to the blessed admin values. */\n.sizeSm {\n height: 2rem;\n padding: 0 var(--spacing-3, 0.75rem);\n font-size: var(--font-size-xs, 0.75rem);\n}\n\n.sizeMd {\n height: 2.5rem;\n padding: 0 var(--spacing-4, 1rem);\n line-height: 1;\n}\n\n:global([data-density=\"editorial\"]) .sizeSm {\n font-size: 0.8125rem;\n}\n\n:global([data-density=\"editorial\"]) .sizeMd {\n height: 2.125rem;\n line-height: normal;\n}\n\n.sizeLg {\n height: 3rem;\n padding: 0 var(--spacing-6, 1.5rem);\n font-size: var(--font-size-base, 1rem);\n}\n\n/* VI-510: form controls do not inherit font-family from the page; opt back in (matches textarea). */\n.base {\n font-family: inherit;\n}\n"
149
+ "content": "/* Button base styles */\n.base {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: var(--spacing-2, 0.5rem);\n white-space: nowrap;\n border-radius: var(--radius-md, 0.375rem);\n font-size: var(--font-size-sm, 0.875rem);\n font-weight: var(--font-weight-medium, 500);\n line-height: 1;\n cursor: pointer;\n border: 1px solid transparent;\n transition: background-color var(--motion-duration-150, 150ms) var(--motion-easing-default, ease-in-out), color var(--motion-duration-150, 150ms) var(--motion-easing-default, ease-in-out), border-color var(--motion-duration-150, 150ms) var(--motion-easing-default, ease-in-out), opacity var(--motion-duration-150, 150ms) var(--motion-easing-default, ease-in-out), transform var(--motion-duration-150, 150ms) var(--motion-easing-default, ease-in-out);\n text-decoration: none;\n outline: none;\n}\n\n.base:focus-visible {\n outline: var(--focus-ring-width, 2px) solid var(--border-focus, currentColor);\n outline-offset: var(--focus-ring-offset, 2px);\n}\n\n.base:active:not(:disabled) {\n transform: translateY(1px);\n transition: none;\n}\n\n.base:disabled {\n pointer-events: none;\n opacity: 0.5;\n}\n\n/* Variants */\n.variantDefault {\n background-color: var(--interactive-primary-bg, var(--primary, #111827));\n color: var(--interactive-primary-text, #f9fafb);\n}\n\n.variantSecondary {\n background-color: var(--interactive-secondary-bg, #f3f4f6);\n color: var(--interactive-secondary-text, #111827);\n}\n\n/* Editorial density: secondary on the card tier, ghost truly transparent.\n * Direct values — the editorial design language owns control surfaces, so the\n * theme's --interactive-secondary-bg / --interactive-ghost-bg are deliberately\n * bypassed (matches the blessed overlay, which out-cascaded the palette). */\n:global([data-density=\"editorial\"]) .variantSecondary {\n background-color: var(--surface-card, #ffffff);\n}\n\n:global([data-density=\"editorial\"]) .variantGhost {\n background-color: transparent;\n}\n\n.variantOutline {\n background-color: transparent;\n color: var(--text-primary, #111827);\n border-color: var(--border-strong, #e5e7eb);\n}\n\n.variantGhost {\n background-color: var(--interactive-ghost-bg, transparent);\n color: var(--text-primary, #111827);\n}\n\n.variantDestructive {\n background-color: var(--interactive-destructive-bg, #ef4444);\n color: var(--interactive-destructive-text, #fef2f2);\n}\n\n@media (hover: hover) {\n .variantDefault:hover {\n background-color: var(--interactive-primary-bg-hover, #1f2937);\n }\n\n .variantSecondary:hover {\n background-color: var(--interactive-secondary-bg-hover, #e5e7eb);\n }\n\n .variantOutline:hover {\n background-color: var(--surface-muted, #f3f4f6);\n }\n\n .variantGhost:hover {\n background-color: var(--interactive-ghost-bg-hover, var(--surface-muted, #f3f4f6));\n }\n\n .variantDestructive:hover {\n background-color: var(--interactive-destructive-bg-hover, #dc2626);\n }\n}\n\n/* Open / active state — ghost variant only. OPT-IN, strictly additive.\n A ghost Button reads as \"held\" while its popover/menu is open so the\n trigger no longer needs an inline style. Three opt-in triggers, all\n resolving to the same held look:\n - data-state=\"open\" — forwarded automatically by Radix when the\n Button is the trigger via <Trigger asChild> (Popover/DropdownMenu).\n - data-active=\"true\" — manual non-Radix triggers (mirrors the\n sidebar `data-active` convention).\n - .isActive — className opt-in (mirrors sidebar/section-nav).\n Default ghost rendering is untouched: none of these match unless a\n consumer explicitly sets them. Matches the prototype-overlay held look:\n background var(--surface-subtle), color var(--text-primary). */\n.variantGhost[data-state=\"open\"],\n.variantGhost[data-active=\"true\"],\n.variantGhost.isActive {\n background-color: var(--surface-subtle, var(--surface-muted, #f3f4f6));\n color: var(--text-primary, #111827);\n}\n\n/* Gated state — orthogonal to variant, works with all variants */\n.base[data-gated=\"true\"] {\n opacity: var(--opacity-40, 0.4);\n cursor: not-allowed;\n border-color: var(--border-default, #e5e7eb);\n}\n\n/* Editorial density: gated reads like plain disabled (the blessed admin\n builds render gated actions at the 0.5 disabled opacity). */\n:global([data-density=\"editorial\"]) .base[data-gated=\"true\"] {\n opacity: 0.5;\n}\n\n/* Suppress active transform when gated */\n.base[data-gated=\"true\"]:active {\n transform: none;\n transition: opacity var(--motion-duration-150, 150ms) var(--motion-easing-default, ease-in-out);\n}\n\n/* Sizes\n Default (no data-density attr) rendering is byte-identical to the prior\n canonical values. Under data-density=\"editorial\" (set on any ancestor,\n typically the app root), the editorial density axis re-drives specific\n metrics to the blessed admin values. */\n.sizeSm {\n height: 2rem;\n padding: 0 var(--spacing-3, 0.75rem);\n font-size: var(--font-size-xs, 0.75rem);\n}\n\n.sizeMd {\n height: 2.5rem;\n padding: 0 var(--spacing-4, 1rem);\n line-height: 1;\n}\n\n:global([data-density=\"editorial\"]) .sizeSm {\n font-size: 0.8125rem;\n}\n\n:global([data-density=\"editorial\"]) .sizeMd {\n height: 2.125rem;\n line-height: normal;\n}\n\n.sizeLg {\n height: 3rem;\n padding: 0 var(--spacing-6, 1.5rem);\n font-size: var(--font-size-base, 1rem);\n}\n\n/* Dialog-footer button — dlg-btn (Animal dialog substrate, VI-620).\n Compact modal-action metrics measured from the AN prototype (11.5px / 600,\n ~7px 13px padding, 7px radius), normalized onto Visor tokens: font-size-2xs\n (11px), spacing-2/spacing-3 padding (8/12px), radius-lg (8px). Height is\n auto so the compact padding drives the box. Color faces reuse the existing\n variant axis — primary via variant=\"default\", ghost via variant=\"ghost\"\n (refined below to a hairline-outlined, secondary-ink face), danger via\n variant=\"destructive\" (refined below to a subtle-danger face). */\n.sizeDlg {\n height: auto;\n padding: var(--spacing-2, 0.5rem) var(--spacing-3, 0.75rem);\n font-size: var(--font-size-2xs, 0.6875rem);\n font-weight: var(--font-weight-semibold, 600);\n line-height: 1;\n border-radius: var(--radius-lg, 0.5rem);\n}\n\n/* dlg ghost — transparent well with a hairline outline + secondary ink\n (AN dlg-btn ghost face: transparent / --ink-60 / 1px --hair). Two-class\n specificity keeps this scoped to the dlg size only. */\n.sizeDlg.variantGhost {\n color: var(--text-secondary, #6b7280);\n border-color: var(--hairline, var(--border-default, #e5e7eb));\n}\n\n/* dlg danger — subtle-danger face (AN dlg-btn danger face: --red on a faint\n red fill), distinct from the solid `destructive` variant. */\n.sizeDlg.variantDestructive {\n background-color: var(--surface-error-subtle, color-mix(in srgb, var(--destructive, #ef4444) 8%, transparent));\n color: var(--text-error, var(--destructive, #b91c1c));\n}\n\n@media (hover: hover) {\n .sizeDlg.variantDestructive:hover {\n background-color: color-mix(in srgb, var(--destructive, #ef4444) 14%, transparent);\n }\n}\n"
150
150
  }
151
151
  ]
152
152
  },
@@ -172,7 +172,7 @@
172
172
  {
173
173
  "path": "components/ui/input/input.module.css",
174
174
  "type": "registry:ui",
175
- "content": "/* Input base styles */\n.base {\n width: 100%;\n min-width: 0;\n border: 1px solid var(--input-border, var(--border-default, #e5e7eb));\n /* --field-control-bg is the shared \"what surface does a form control sit on\"\n role. It defaults to var(--input-bg), so default inputs are unchanged. A\n form context (for example an in-dialog wrapper) can set --field-control-bg:\n var(--surface-subtle) to lift controls onto a different surface without a\n per-component prop. Under data-density=\"editorial\", the fallback chain\n defaults to var(--surface-card) while still honoring any scoped\n --field-control-bg override from a form context. */\n background-color: var(--field-control-bg, var(--input-bg, var(--surface-interactive-default, #f9fafb)));\n line-height: 1.5;\n color: var(--text-primary, #111827);\n transition: border-color var(--motion-duration-150, 150ms) var(--motion-easing-default, ease-in-out), box-shadow var(--motion-duration-150, 150ms) var(--motion-easing-default, ease-in-out);\n outline: none;\n}\n\n:global([data-density=\"editorial\"]) .base {\n background-color: var(--field-control-bg, var(--surface-card));\n}\n\n.base::placeholder {\n color: var(--input-placeholder-color, var(--text-secondary, #9ca3af));\n}\n\n@media (hover: hover) {\n .base:hover:not(:focus-visible):not(:disabled):not([aria-invalid=\"true\"]) {\n border-color: var(--border-strong, #d1d5db);\n }\n}\n\n.base:focus-visible {\n border-color: var(--border-focus, #111827);\n box-shadow: 0 0 0 var(--focus-ring-width, 2px) color-mix(in srgb, var(--border-focus, #111827) 15%, transparent);\n}\n\n.base:disabled {\n pointer-events: none;\n cursor: not-allowed;\n opacity: 0.5;\n}\n\n.base[aria-invalid=\"true\"] {\n border-color: transparent;\n background-color: var(--input-bg-invalid, var(--surface-error-subtle, color-mix(in srgb, var(--border-error, #ef4444) 6%, var(--field-control-bg, var(--input-bg, #f9fafb)))));\n box-shadow: inset 0 0 0 1.5px var(--border-error, #ef4444);\n}\n\n:global([data-density=\"editorial\"]) .base[aria-invalid=\"true\"] {\n background-color: var(--input-bg-invalid, var(--surface-error-subtle, color-mix(in srgb, var(--border-error, #ef4444) 6%, var(--field-control-bg, var(--surface-card)))));\n}\n\n.base[aria-invalid=\"true\"]:focus-visible {\n border-color: transparent;\n outline-offset: var(--focus-ring-offset, 2px);\n box-shadow: inset 0 0 0 1.5px var(--border-error, #ef4444),\n 0 0 0 var(--focus-ring-width, 2px) color-mix(in srgb, var(--border-error, #ef4444) 30%, transparent);\n}\n\n/* File input styles */\n.base[type=\"file\"] {\n font-size: var(--font-size-sm, 0.875rem);\n}\n\n/* Leading-icon wrapper\n *\n * When the consumer passes a leadingIcon node, Input wraps its <input> in a\n * <span> and positions the icon absolutely inside it. The <input> itself\n * picks up .hasLeadingIcon, which adds enough left padding to clear the\n * icon (sized in em so it scales with the field's font-size). */\n.leadingIconWrapper {\n position: relative;\n display: flex;\n align-items: center;\n width: 100%;\n min-width: 0;\n}\n\n.leadingIcon {\n position: absolute;\n left: var(--spacing-3, 0.75rem);\n top: 50%;\n transform: translateY(-50%);\n display: inline-flex;\n align-items: center;\n justify-content: center;\n color: var(--text-secondary, #9ca3af);\n pointer-events: none;\n font-size: 1.125em;\n line-height: 1;\n}\n\n/* Size variants\n *\n * Default rendering uses canonical values directly. Under data-density=\"editorial\"\n * (set on any ancestor), the editorial density axis bakes in the blessed admin\n * values — sm inputs at 33.5px height with --radius-md corners. Padding and the\n * md/lg sizes are not driven by the editorial treatment and remain canonical. */\n.sizeSm {\n height: 2.25rem;\n padding: var(--input-padding-sm, var(--spacing-1, 0.25rem) var(--spacing-3, 0.75rem));\n font-size: var(--font-size-sm, 0.875rem);\n border-radius: var(--radius-sm, 0.25rem);\n}\n\n:global([data-density=\"editorial\"]) .sizeSm {\n height: 33.5px;\n border-radius: var(--radius-md);\n}\n\n.sizeMd {\n height: var(--input-height-md, auto);\n padding: var(--input-padding-md, var(--spacing-3_5, 0.875rem) var(--spacing-4, 1rem));\n font-size: var(--font-size-sm, 0.875rem);\n border-radius: var(--input-radius-md, var(--radius-sm, 0.5rem));\n}\n\n.sizeLg {\n height: var(--input-height-lg, auto);\n padding: var(--input-padding-lg, var(--spacing-4_5, 1.125rem) var(--spacing-5, 1.25rem));\n font-size: var(--font-size-base, 1rem);\n border-radius: var(--input-radius-lg, var(--radius-sm, 0.5rem));\n}\n\n/* Leading-icon left-padding override.\n *\n * Declared AFTER the size variants so the padding-left value wins the\n * cascade against the shorthand `padding` each size sets. Double-class\n * selector bumps specificity above the size classes for good measure. */\n.sizeSm.hasLeadingIcon {\n padding-left: calc(var(--spacing-3, 0.75rem) * 2 + 1.125em);\n}\n\n.sizeMd.hasLeadingIcon {\n padding-left: calc(var(--spacing-4, 1rem) + var(--spacing-3, 0.75rem) + 1.125em);\n}\n\n.sizeLg.hasLeadingIcon {\n padding-left: calc(var(--spacing-5, 1.25rem) + var(--spacing-3, 0.75rem) + 1.125em);\n}\n\n/* VI-510: form controls do not inherit font-family from the page; opt back in (matches textarea). */\n.base {\n font-family: inherit;\n}\n"
175
+ "content": "/* Input base styles */\n.base {\n width: 100%;\n min-width: 0;\n border: 1px solid var(--input-border, var(--border-default, #e5e7eb));\n /* --field-control-bg is the shared \"what surface does a form control sit on\"\n role. It defaults to var(--input-bg), so default inputs are unchanged. A\n form context (for example an in-dialog wrapper) can set --field-control-bg:\n var(--surface-subtle) to lift controls onto a different surface without a\n per-component prop. Under data-density=\"editorial\", the fallback chain\n defaults to var(--surface-card) while still honoring any scoped\n --field-control-bg override from a form context. */\n background-color: var(--field-control-bg, var(--input-bg, var(--surface-interactive-default, #f9fafb)));\n line-height: 1.5;\n color: var(--text-primary, #111827);\n transition: border-color var(--motion-duration-150, 150ms) var(--motion-easing-default, ease-in-out), box-shadow var(--motion-duration-150, 150ms) var(--motion-easing-default, ease-in-out);\n outline: none;\n}\n\n:global([data-density=\"editorial\"]) .base {\n background-color: var(--field-control-bg, var(--surface-card));\n}\n\n.base::placeholder {\n color: var(--input-placeholder-color, var(--text-secondary, #9ca3af));\n}\n\n@media (hover: hover) {\n .base:hover:not(:focus-visible):not(:disabled):not([aria-invalid=\"true\"]) {\n border-color: var(--border-strong, #d1d5db);\n }\n}\n\n.base:focus-visible {\n border-color: var(--border-focus, #111827);\n box-shadow: 0 0 0 var(--focus-ring-width, 2px) color-mix(in srgb, var(--border-focus, #111827) 15%, transparent);\n}\n\n.base:disabled {\n pointer-events: none;\n cursor: not-allowed;\n opacity: 0.5;\n}\n\n.base[aria-invalid=\"true\"] {\n border-color: transparent;\n background-color: var(--input-bg-invalid, var(--surface-error-subtle, color-mix(in srgb, var(--border-error, #ef4444) 6%, var(--field-control-bg, var(--input-bg, #f9fafb)))));\n box-shadow: inset 0 0 0 1.5px var(--border-error, #ef4444);\n}\n\n:global([data-density=\"editorial\"]) .base[aria-invalid=\"true\"] {\n background-color: var(--input-bg-invalid, var(--surface-error-subtle, color-mix(in srgb, var(--border-error, #ef4444) 6%, var(--field-control-bg, var(--surface-card)))));\n}\n\n.base[aria-invalid=\"true\"]:focus-visible {\n border-color: transparent;\n outline-offset: var(--focus-ring-offset, 2px);\n box-shadow: inset 0 0 0 1.5px var(--border-error, #ef4444),\n 0 0 0 var(--focus-ring-width, 2px) color-mix(in srgb, var(--border-error, #ef4444) 30%, transparent);\n}\n\n/* File input styles */\n.base[type=\"file\"] {\n font-size: var(--font-size-sm, 0.875rem);\n}\n\n/* Leading-icon wrapper\n *\n * When the consumer passes a leadingIcon node, Input wraps its <input> in a\n * <span> and positions the icon absolutely inside it. The <input> itself\n * picks up .hasLeadingIcon, which adds enough left padding to clear the\n * icon (sized in em so it scales with the field's font-size). */\n.leadingIconWrapper {\n position: relative;\n display: flex;\n align-items: center;\n width: 100%;\n min-width: 0;\n}\n\n.leadingIcon {\n position: absolute;\n left: var(--spacing-3, 0.75rem);\n top: 50%;\n transform: translateY(-50%);\n display: inline-flex;\n align-items: center;\n justify-content: center;\n color: var(--text-secondary, #9ca3af);\n pointer-events: none;\n font-size: 1.125em;\n line-height: 1;\n}\n\n/* Size variants\n *\n * Default rendering uses canonical values directly. Under data-density=\"editorial\"\n * (set on any ancestor), the editorial density axis bakes in the blessed admin\n * values — sm inputs at 33.5px height with --radius-md corners. Padding and the\n * md/lg sizes are not driven by the editorial treatment and remain canonical. */\n.sizeSm {\n height: 2.25rem;\n padding: var(--input-padding-sm, var(--spacing-1, 0.25rem) var(--spacing-3, 0.75rem));\n font-size: var(--font-size-sm, 0.875rem);\n border-radius: var(--radius-sm, 0.25rem);\n}\n\n:global([data-density=\"editorial\"]) .sizeSm {\n height: 33.5px;\n border-radius: var(--radius-md);\n}\n\n.sizeMd {\n height: var(--input-height-md, auto);\n padding: var(--input-padding-md, var(--spacing-3_5, 0.875rem) var(--spacing-4, 1rem));\n font-size: var(--font-size-sm, 0.875rem);\n border-radius: var(--input-radius-md, var(--radius-sm, 0.5rem));\n}\n\n.sizeLg {\n height: var(--input-height-lg, auto);\n padding: var(--input-padding-lg, var(--spacing-4_5, 1.125rem) var(--spacing-5, 1.25rem));\n font-size: var(--font-size-base, 1rem);\n border-radius: var(--input-radius-lg, var(--radius-sm, 0.5rem));\n}\n\n/* Leading-icon left-padding override.\n *\n * Declared AFTER the size variants so the padding-left value wins the\n * cascade against the shorthand `padding` each size sets. Double-class\n * selector bumps specificity above the size classes for good measure. */\n.sizeSm.hasLeadingIcon {\n padding-left: calc(var(--spacing-3, 0.75rem) * 2 + 1.125em);\n}\n\n.sizeMd.hasLeadingIcon {\n padding-left: calc(var(--spacing-4, 1rem) + var(--spacing-3, 0.75rem) + 1.125em);\n}\n\n.sizeLg.hasLeadingIcon {\n padding-left: calc(var(--spacing-5, 1.25rem) + var(--spacing-3, 0.75rem) + 1.125em);\n}\n"
176
176
  }
177
177
  ]
178
178
  },
@@ -223,7 +223,7 @@
223
223
  {
224
224
  "path": "components/ui/textarea/textarea.module.css",
225
225
  "type": "registry:ui",
226
- "content": "/* Textarea base styles */\n.base {\n display: flex;\n width: 100%;\n resize: none;\n border: 1px solid var(--textarea-border, var(--border-default, #e5e7eb));\n background-color: var(--textarea-bg, var(--surface-interactive-default, #f9fafb));\n line-height: 1.5;\n color: var(--text-primary, #111827);\n transition: border-color var(--motion-duration-150, 150ms) var(--motion-easing-default, ease-in-out), box-shadow var(--motion-duration-150, 150ms) var(--motion-easing-default, ease-in-out);\n outline: none;\n font-family: inherit;\n}\n\n.base::placeholder {\n color: var(--text-secondary, #9ca3af);\n}\n\n@media (hover: hover) {\n .base:hover:not(:focus-visible):not(:disabled):not([aria-invalid=\"true\"]) {\n border-color: var(--border-strong, #d1d5db);\n }\n}\n\n.base:focus-visible {\n border-color: var(--border-focus, #111827);\n box-shadow: 0 0 0 var(--focus-ring-width, 2px) color-mix(in srgb, var(--border-focus, #111827) 15%, transparent);\n}\n\n.base:disabled {\n cursor: not-allowed;\n opacity: 0.5;\n}\n\n.base[aria-invalid=\"true\"] {\n border-color: var(--border-error, #ef4444);\n box-shadow: 0 0 0 var(--focus-ring-width, 2px) color-mix(in srgb, var(--border-error, #ef4444) 15%, transparent);\n}\n\n/* Size variants */\n.sizeSm {\n min-height: 4rem;\n padding: var(--spacing-3, 0.75rem);\n font-size: var(--font-size-sm, 0.875rem);\n border-radius: var(--radius-sm, 0.25rem);\n}\n\n.sizeMd {\n min-height: 6.25rem;\n padding: var(--spacing-3_5, 0.875rem) var(--spacing-4, 1rem);\n font-size: var(--font-size-sm, 0.875rem);\n border-radius: var(--radius-sm, 0.5rem);\n}\n\n.sizeLg {\n min-height: 8rem;\n padding: var(--spacing-4_5, 1.125rem) var(--spacing-5, 1.25rem);\n font-size: var(--font-size-base, 1rem);\n border-radius: var(--radius-sm, 0.5rem);\n}\n"
226
+ "content": "/* Textarea base styles */\n.base {\n display: flex;\n width: 100%;\n resize: none;\n border: 1px solid var(--textarea-border, var(--border-default, #e5e7eb));\n background-color: var(--textarea-bg, var(--surface-interactive-default, #f9fafb));\n line-height: 1.5;\n color: var(--text-primary, #111827);\n transition: border-color var(--motion-duration-150, 150ms) var(--motion-easing-default, ease-in-out), box-shadow var(--motion-duration-150, 150ms) var(--motion-easing-default, ease-in-out);\n outline: none;\n}\n\n.base::placeholder {\n color: var(--text-secondary, #9ca3af);\n}\n\n@media (hover: hover) {\n .base:hover:not(:focus-visible):not(:disabled):not([aria-invalid=\"true\"]) {\n border-color: var(--border-strong, #d1d5db);\n }\n}\n\n.base:focus-visible {\n border-color: var(--border-focus, #111827);\n box-shadow: 0 0 0 var(--focus-ring-width, 2px) color-mix(in srgb, var(--border-focus, #111827) 15%, transparent);\n}\n\n.base:disabled {\n cursor: not-allowed;\n opacity: 0.5;\n}\n\n.base[aria-invalid=\"true\"] {\n border-color: var(--border-error, #ef4444);\n box-shadow: 0 0 0 var(--focus-ring-width, 2px) color-mix(in srgb, var(--border-error, #ef4444) 15%, transparent);\n}\n\n/* Size variants */\n.sizeSm {\n min-height: 4rem;\n padding: var(--spacing-3, 0.75rem);\n font-size: var(--font-size-sm, 0.875rem);\n border-radius: var(--radius-sm, 0.25rem);\n}\n\n.sizeMd {\n min-height: 6.25rem;\n padding: var(--spacing-3_5, 0.875rem) var(--spacing-4, 1rem);\n font-size: var(--font-size-sm, 0.875rem);\n border-radius: var(--radius-sm, 0.5rem);\n}\n\n.sizeLg {\n min-height: 8rem;\n padding: var(--spacing-4_5, 1.125rem) var(--spacing-5, 1.25rem);\n font-size: var(--font-size-base, 1rem);\n border-radius: var(--radius-sm, 0.5rem);\n}\n"
227
227
  }
228
228
  ]
229
229
  },
@@ -275,7 +275,7 @@
275
275
  {
276
276
  "path": "components/ui/select/select.module.css",
277
277
  "type": "registry:ui",
278
- "content": "/* Select Trigger */\n.trigger {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: calc(var(--spacing-1, 0.25rem) * 1.5);\n width: fit-content;\n border-radius: var(--radius-md, 0.375rem);\n border: 1px solid var(--select-border, var(--border-default, #e5e7eb));\n background-color: var(--field-control-bg, var(--select-bg, var(--surface-interactive-default, #f9fafb)));\n padding: var(--spacing-2, 0.5rem) var(--spacing-3, 0.75rem);\n font-size: var(--font-size-sm, 0.875rem);\n /* Match Input's line-height so the trigger's height tracks the text field at\n the same size. Without this the trigger inherited line-height 2.0, rendering\n ~7px taller than a same-size Input. */\n line-height: 1.5;\n white-space: nowrap;\n color: var(--text-primary, #111827);\n transition: border-color var(--motion-duration-150, 150ms) var(--motion-easing-default, ease-in-out), box-shadow var(--motion-duration-150, 150ms) var(--motion-easing-default, ease-in-out);\n outline: none;\n cursor: pointer;\n}\n\n@media (hover: hover) {\n .trigger:hover:not(:focus-visible):not(:disabled):not([aria-invalid=\"true\"]) {\n border-color: var(--border-strong, #d1d5db);\n }\n}\n\n.trigger:focus-visible {\n border-color: var(--border-focus, #111827);\n box-shadow: 0 0 0 var(--focus-ring-width, 2px) color-mix(in srgb, var(--border-focus, #111827) 15%, transparent);\n}\n\n.trigger:disabled {\n cursor: not-allowed;\n opacity: 0.5;\n}\n\n.trigger[aria-invalid=\"true\"] {\n border-color: var(--border-error, #ef4444);\n box-shadow: 0 0 0 var(--focus-ring-width, 2px) color-mix(in srgb, var(--border-error, #ef4444) 15%, transparent);\n}\n\n.trigger[data-placeholder] {\n color: var(--text-secondary, #9ca3af);\n}\n\n/* Borderless trigger variant (opt-in via <SelectTrigger variant=\"borderless\">).\n *\n * Closed trigger has no 1px border and sits on --field-control-bg — the same\n * shared form-control surface role Input uses — so a borderless Select matches a\n * borderless Input inside an in-dialog form context that sets\n * --field-control-bg: var(--surface-subtle). Default Select is unchanged. The\n * border is kept transparent (rather than removed) so the trigger's box size\n * stays identical to the default trigger and the focus ring keeps its geometry.\n * Declared after the base .trigger so these overrides win the cascade. */\n.triggerBorderless {\n border-color: transparent;\n background-color: var(--field-control-bg, var(--select-bg, var(--surface-interactive-default, #f9fafb)));\n /* In-form borderless selects match the Input they sit beside: full width and\n the same md height/padding (the prototype paired select and input controls inside its field rows). */\n width: 100%;\n padding: var(--spacing-3_5, 0.875rem) var(--spacing-4, 1rem);\n}\n\n@media (hover: hover) {\n .triggerBorderless:hover:not(:focus-visible):not(:disabled):not([aria-invalid=\"true\"]) {\n border-color: transparent;\n }\n}\n\n.triggerBorderless:focus-visible {\n border-color: transparent;\n box-shadow: 0 0 0 var(--focus-ring-width, 2px) color-mix(in srgb, var(--border-focus, #111827) 15%, transparent);\n}\n\n:global([data-density=\"editorial\"]) .trigger {\n background-color: var(--field-control-bg, var(--surface-card));\n}\n\n:global([data-density=\"editorial\"]) .triggerBorderless {\n background-color: var(--field-control-bg, var(--surface-card));\n}\n\n.triggerSizeSm {\n height: 2.25rem;\n border-radius: var(--radius-sm, 0.25rem);\n}\n\n.triggerSizeMd {\n height: auto;\n padding: var(--spacing-3_5, 0.875rem) var(--spacing-4, 1rem);\n font-size: var(--font-size-sm, 0.875rem);\n border-radius: var(--radius-sm, 0.5rem);\n}\n\n.triggerSizeLg {\n height: auto;\n padding: var(--spacing-4_5, 1.125rem) var(--spacing-5, 1.25rem);\n font-size: var(--font-size-base, 1rem);\n border-radius: var(--radius-sm, 0.5rem);\n}\n\n.triggerIcon {\n pointer-events: none;\n width: 1rem;\n height: 1rem;\n flex-shrink: 0;\n color: var(--text-secondary, #9ca3af);\n}\n\n/* Select Content */\n.content {\n position: relative;\n z-index: 50;\n max-height: var(--radix-select-content-available-height, 300px);\n min-width: 9rem;\n overflow: hidden;\n border-radius: var(--radius-lg, 0.5rem);\n background-color: var(--field-menu-bg, var(--surface-popover, var(--surface-card, #ffffff)));\n color: var(--text-primary, #111827);\n box-shadow: var(--shadow-lg);\n}\n\n/* Select Viewport */\n.viewport {\n padding: var(--spacing-1, 0.25rem);\n}\n\n.viewportPopper {\n height: var(--radix-select-trigger-height);\n width: 100%;\n min-width: var(--radix-select-trigger-width);\n}\n\n/* Select Label */\n.label {\n padding: var(--spacing-2, 0.5rem) var(--spacing-3, 0.75rem);\n font-size: var(--font-size-xs, 0.75rem);\n color: var(--text-secondary, #9ca3af);\n}\n\n/* Select Item */\n.item {\n position: relative;\n display: flex;\n width: 100%;\n cursor: default;\n align-items: center;\n gap: calc(var(--spacing-2, 0.5rem) + var(--spacing-1, 0.25rem) / 2);\n border-radius: var(--radius-sm, 0.25rem);\n padding: var(--spacing-2, 0.5rem) var(--spacing-8, 2rem) var(--spacing-2, 0.5rem) var(--spacing-3, 0.75rem);\n font-size: var(--font-size-sm, 0.875rem);\n outline: none;\n user-select: none;\n}\n\n.item:focus,\n.item[data-highlighted] {\n background-color: var(--surface-interactive-hover, #f3f4f6);\n color: var(--text-primary, #111827);\n}\n\n.item[data-disabled] {\n pointer-events: none;\n opacity: 0.5;\n}\n\n.itemIndicatorWrapper {\n position: absolute;\n right: 0.5rem;\n display: flex;\n width: 1rem;\n height: 1rem;\n align-items: center;\n justify-content: center;\n}\n\n.itemIndicatorIcon {\n width: 0.875rem;\n height: 0.875rem;\n pointer-events: none;\n}\n\n/* Select Separator */\n.separator {\n pointer-events: none;\n margin: var(--spacing-1, 0.25rem) calc(-1 * var(--spacing-1, 0.25rem));\n height: 1px;\n background-color: var(--border-default, #e5e7eb);\n}\n\n/* Scroll Buttons */\n.scrollButton {\n display: flex;\n cursor: default;\n align-items: center;\n justify-content: center;\n padding: var(--spacing-1, 0.25rem);\n background-color: var(--field-menu-bg, var(--surface-popover, var(--surface-card, #ffffff)));\n}\n\n.scrollButtonIcon {\n width: 1rem;\n height: 1rem;\n}\n\n/* VI-510: form controls do not inherit font-family from the page; opt back in (matches textarea). */\n.trigger {\n font-family: inherit;\n}\n"
278
+ "content": "/* Select Trigger */\n.trigger {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: calc(var(--spacing-1, 0.25rem) * 1.5);\n width: fit-content;\n border-radius: var(--radius-md, 0.375rem);\n border: 1px solid var(--select-border, var(--border-default, #e5e7eb));\n background-color: var(--field-control-bg, var(--select-bg, var(--surface-interactive-default, #f9fafb)));\n padding: var(--spacing-2, 0.5rem) var(--spacing-3, 0.75rem);\n font-size: var(--font-size-sm, 0.875rem);\n /* Match Input's line-height so the trigger's height tracks the text field at\n the same size. Without this the trigger inherited line-height 2.0, rendering\n ~7px taller than a same-size Input. */\n line-height: 1.5;\n white-space: nowrap;\n color: var(--text-primary, #111827);\n transition: border-color var(--motion-duration-150, 150ms) var(--motion-easing-default, ease-in-out), box-shadow var(--motion-duration-150, 150ms) var(--motion-easing-default, ease-in-out);\n outline: none;\n cursor: pointer;\n}\n\n@media (hover: hover) {\n .trigger:hover:not(:focus-visible):not(:disabled):not([aria-invalid=\"true\"]) {\n border-color: var(--border-strong, #d1d5db);\n }\n}\n\n.trigger:focus-visible {\n border-color: var(--border-focus, #111827);\n box-shadow: 0 0 0 var(--focus-ring-width, 2px) color-mix(in srgb, var(--border-focus, #111827) 15%, transparent);\n}\n\n.trigger:disabled {\n cursor: not-allowed;\n opacity: 0.5;\n}\n\n.trigger[aria-invalid=\"true\"] {\n border-color: var(--border-error, #ef4444);\n box-shadow: 0 0 0 var(--focus-ring-width, 2px) color-mix(in srgb, var(--border-error, #ef4444) 15%, transparent);\n}\n\n.trigger[data-placeholder] {\n color: var(--text-secondary, #9ca3af);\n}\n\n/* Borderless trigger variant (opt-in via <SelectTrigger variant=\"borderless\">).\n *\n * Closed trigger has no 1px border and sits on --field-control-bg — the same\n * shared form-control surface role Input uses — so a borderless Select matches a\n * borderless Input inside an in-dialog form context that sets\n * --field-control-bg: var(--surface-subtle). Default Select is unchanged. The\n * border is kept transparent (rather than removed) so the trigger's box size\n * stays identical to the default trigger and the focus ring keeps its geometry.\n * Declared after the base .trigger so these overrides win the cascade. */\n.triggerBorderless {\n border-color: transparent;\n background-color: var(--field-control-bg, var(--select-bg, var(--surface-interactive-default, #f9fafb)));\n /* In-form borderless selects match the Input they sit beside: full width and\n the same md height/padding (the prototype paired select and input controls inside its field rows). */\n width: 100%;\n padding: var(--spacing-3_5, 0.875rem) var(--spacing-4, 1rem);\n}\n\n@media (hover: hover) {\n .triggerBorderless:hover:not(:focus-visible):not(:disabled):not([aria-invalid=\"true\"]) {\n border-color: transparent;\n }\n}\n\n.triggerBorderless:focus-visible {\n border-color: transparent;\n box-shadow: 0 0 0 var(--focus-ring-width, 2px) color-mix(in srgb, var(--border-focus, #111827) 15%, transparent);\n}\n\n:global([data-density=\"editorial\"]) .trigger {\n background-color: var(--field-control-bg, var(--surface-card));\n}\n\n:global([data-density=\"editorial\"]) .triggerBorderless {\n background-color: var(--field-control-bg, var(--surface-card));\n}\n\n.triggerSizeSm {\n height: 2.25rem;\n border-radius: var(--radius-sm, 0.25rem);\n}\n\n.triggerSizeMd {\n height: auto;\n padding: var(--spacing-3_5, 0.875rem) var(--spacing-4, 1rem);\n font-size: var(--font-size-sm, 0.875rem);\n border-radius: var(--radius-sm, 0.5rem);\n}\n\n.triggerSizeLg {\n height: auto;\n padding: var(--spacing-4_5, 1.125rem) var(--spacing-5, 1.25rem);\n font-size: var(--font-size-base, 1rem);\n border-radius: var(--radius-sm, 0.5rem);\n}\n\n.triggerIcon {\n pointer-events: none;\n width: 1rem;\n height: 1rem;\n flex-shrink: 0;\n color: var(--text-secondary, #9ca3af);\n}\n\n/* Select Content */\n.content {\n position: relative;\n z-index: 50;\n max-height: var(--radix-select-content-available-height, 300px);\n min-width: 9rem;\n overflow: hidden;\n border-radius: var(--radius-lg, 0.5rem);\n background-color: var(--field-menu-bg, var(--surface-popover, var(--surface-card, #ffffff)));\n color: var(--text-primary, #111827);\n box-shadow: var(--shadow-lg);\n}\n\n/* Select Viewport */\n.viewport {\n padding: var(--spacing-1, 0.25rem);\n}\n\n.viewportPopper {\n height: var(--radix-select-trigger-height);\n width: 100%;\n min-width: var(--radix-select-trigger-width);\n}\n\n/* Select Label */\n.label {\n padding: var(--spacing-2, 0.5rem) var(--spacing-3, 0.75rem);\n font-size: var(--font-size-xs, 0.75rem);\n color: var(--text-secondary, #9ca3af);\n}\n\n/* Select Item */\n.item {\n position: relative;\n display: flex;\n width: 100%;\n cursor: default;\n align-items: center;\n gap: calc(var(--spacing-2, 0.5rem) + var(--spacing-1, 0.25rem) / 2);\n border-radius: var(--radius-sm, 0.25rem);\n padding: var(--spacing-2, 0.5rem) var(--spacing-8, 2rem) var(--spacing-2, 0.5rem) var(--spacing-3, 0.75rem);\n font-size: var(--font-size-sm, 0.875rem);\n outline: none;\n user-select: none;\n}\n\n.item:focus,\n.item[data-highlighted] {\n background-color: var(--surface-interactive-hover, #f3f4f6);\n color: var(--text-primary, #111827);\n}\n\n.item[data-disabled] {\n pointer-events: none;\n opacity: 0.5;\n}\n\n.itemIndicatorWrapper {\n position: absolute;\n right: 0.5rem;\n display: flex;\n width: 1rem;\n height: 1rem;\n align-items: center;\n justify-content: center;\n}\n\n.itemIndicatorIcon {\n width: 0.875rem;\n height: 0.875rem;\n pointer-events: none;\n}\n\n/* Select Separator */\n.separator {\n pointer-events: none;\n margin: var(--spacing-1, 0.25rem) calc(-1 * var(--spacing-1, 0.25rem));\n height: 1px;\n background-color: var(--border-default, #e5e7eb);\n}\n\n/* Scroll Buttons */\n.scrollButton {\n display: flex;\n cursor: default;\n align-items: center;\n justify-content: center;\n padding: var(--spacing-1, 0.25rem);\n background-color: var(--field-menu-bg, var(--surface-popover, var(--surface-card, #ffffff)));\n}\n\n.scrollButtonIcon {\n width: 1rem;\n height: 1rem;\n}\n"
279
279
  }
280
280
  ]
281
281
  },
@@ -651,7 +651,7 @@
651
651
  {
652
652
  "path": "components/ui/challenge-card/challenge-card.module.css",
653
653
  "type": "registry:ui",
654
- "content": "/* ChallengeCard\n *\n * First-class adversarial challenge message — an AI pushes back on the user's\n * input and the HUMAN holds the gate. Distinct from Alert (passive notice):\n * ChallengeCard carries its own action semantics and gate affordance.\n *\n * Visual spec: docs/design/brand-workbench/elicit-core (the adversarial\n * challenge card section, around line 261-273)\n */\n\n/* Root card */\n.root {\n /* Component-scoped hooks — consumers can override any of these on the wrapper. */\n --challenge-card-action-primary-text: var(--color-warning-900, var(--text-warning, #78350f));\n\n width: 100%;\n border-radius: var(--radius-xl, 1rem);\n background-color: var(--surface-warning-subtle, #fffbeb);\n border: var(--stroke-width-thin, 1px) solid var(--border-warning, #d97706);\n overflow: hidden;\n}\n\n/* Header — flag icon + uppercase warning-colored title */\n.header {\n display: flex;\n align-items: center;\n gap: var(--spacing-2, 0.5rem);\n padding: var(--spacing-2-5, 0.625rem) var(--spacing-4, 1rem);\n font-size: 11.5px;\n font-weight: 800;\n letter-spacing: 0.05em;\n text-transform: uppercase;\n color: var(--text-warning, #b45309);\n}\n\n.headerIcon {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 14px;\n height: 14px;\n flex-shrink: 0;\n color: var(--text-warning, #b45309);\n}\n\n/* Body — prose */\n.body {\n padding: 0 var(--spacing-4, 1rem) var(--spacing-3, 0.75rem);\n font-size: 14.5px;\n line-height: 1.55;\n color: var(--text-primary, #111827);\n}\n\n/* Actions row */\n.actions {\n display: flex;\n align-items: center;\n gap: var(--spacing-2, 0.5rem);\n padding: 0 var(--spacing-4, 1rem) var(--spacing-3-5, 0.875rem);\n}\n\n/* Action button base */\n.action {\n height: 32px;\n padding: 0 var(--spacing-3-5, 0.875rem);\n border-radius: var(--radius-lg, 0.5rem);\n font-family: inherit;\n font-size: 12.5px;\n font-weight: 700;\n cursor: pointer;\n display: inline-flex;\n align-items: center;\n gap: var(--spacing-1-5, 0.375rem);\n transition:\n opacity var(--motion-duration-150, 150ms) var(--motion-easing-default, ease-in-out),\n box-shadow var(--motion-duration-150, 150ms) var(--motion-easing-default, ease-in-out);\n outline: none;\n}\n\n.action:focus-visible {\n outline: var(--focus-ring-width, 2px) solid var(--text-warning, #b45309);\n outline-offset: var(--focus-ring-offset, 2px);\n}\n\n.action:disabled {\n opacity: var(--opacity-40, 0.4);\n cursor: not-allowed;\n}\n\n/* Primary — filled warning-toned */\n.actionPrimary {\n background-color: var(--warning, #f59e0b);\n /* Warning amber is a light/warm amber — dark warm-900 text has the highest contrast */\n color: var(--challenge-card-action-primary-text);\n border: none;\n}\n\n.actionPrimary:hover:not(:disabled) {\n opacity: var(--opacity-80, 0.8);\n}\n\n/* Ghost — transparent with border */\n.actionGhost {\n background-color: transparent;\n color: var(--text-secondary, #6b7280);\n border: var(--stroke-width-thin, 1px) solid var(--border-default, #e5e7eb);\n}\n\n.actionGhost:hover:not(:disabled) {\n background-color: color-mix(in srgb, var(--surface-card, #ffffff) 80%, transparent);\n}\n\n/* Action icon */\n.actionIcon {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 13px;\n height: 13px;\n flex-shrink: 0;\n}\n\n/* Gate indicator — pushed right via margin-left: auto */\n.gate {\n margin-left: auto;\n font-size: 11px;\n color: var(--text-tertiary, #9ca3af);\n display: inline-flex;\n align-items: center;\n gap: var(--spacing-1, 0.25rem);\n white-space: nowrap;\n flex-shrink: 0;\n}\n\n.gateIcon {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 12px;\n height: 12px;\n flex-shrink: 0;\n}\n\n/* Respect reduced motion */\n@media (prefers-reduced-motion: reduce) {\n .action {\n transition: none;\n }\n}\n"
654
+ "content": "/* ChallengeCard\n *\n * First-class adversarial challenge message — an AI pushes back on the user's\n * input and the HUMAN holds the gate. Distinct from Alert (passive notice):\n * ChallengeCard carries its own action semantics and gate affordance.\n *\n * Visual spec: docs/design/brand-workbench/elicit-core (the adversarial\n * challenge card section, around line 261-273)\n */\n\n/* Root card */\n.root {\n /* Component-scoped hooks — consumers can override any of these on the wrapper. */\n --challenge-card-action-primary-text: var(--color-warning-900, var(--text-warning, #78350f));\n\n width: 100%;\n border-radius: var(--radius-xl, 1rem);\n background-color: var(--surface-warning-subtle, #fffbeb);\n border: var(--stroke-width-thin, 1px) solid var(--border-warning, #d97706);\n overflow: hidden;\n}\n\n/* Header — flag icon + uppercase warning-colored title */\n.header {\n display: flex;\n align-items: center;\n gap: var(--spacing-2, 0.5rem);\n padding: var(--spacing-2-5, 0.625rem) var(--spacing-4, 1rem);\n font-size: 11.5px;\n font-weight: 800;\n letter-spacing: 0.05em;\n text-transform: uppercase;\n color: var(--text-warning, #b45309);\n}\n\n.headerIcon {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 14px;\n height: 14px;\n flex-shrink: 0;\n color: var(--text-warning, #b45309);\n}\n\n/* Body — prose */\n.body {\n padding: 0 var(--spacing-4, 1rem) var(--spacing-3, 0.75rem);\n font-size: 14.5px;\n line-height: 1.55;\n color: var(--text-primary, #111827);\n}\n\n/* Actions row */\n.actions {\n display: flex;\n align-items: center;\n gap: var(--spacing-2, 0.5rem);\n padding: 0 var(--spacing-4, 1rem) var(--spacing-3-5, 0.875rem);\n}\n\n/* Action button base */\n.action {\n height: 32px;\n padding: 0 var(--spacing-3-5, 0.875rem);\n border-radius: var(--radius-lg, 0.5rem);\n font-size: 12.5px;\n font-weight: 700;\n cursor: pointer;\n display: inline-flex;\n align-items: center;\n gap: var(--spacing-1-5, 0.375rem);\n transition:\n opacity var(--motion-duration-150, 150ms) var(--motion-easing-default, ease-in-out),\n box-shadow var(--motion-duration-150, 150ms) var(--motion-easing-default, ease-in-out);\n outline: none;\n}\n\n.action:focus-visible {\n outline: var(--focus-ring-width, 2px) solid var(--text-warning, #b45309);\n outline-offset: var(--focus-ring-offset, 2px);\n}\n\n.action:disabled {\n opacity: var(--opacity-40, 0.4);\n cursor: not-allowed;\n}\n\n/* Primary — filled warning-toned */\n.actionPrimary {\n background-color: var(--warning, #f59e0b);\n /* Warning amber is a light/warm amber — dark warm-900 text has the highest contrast */\n color: var(--challenge-card-action-primary-text);\n border: none;\n}\n\n.actionPrimary:hover:not(:disabled) {\n opacity: var(--opacity-80, 0.8);\n}\n\n/* Ghost — transparent with border */\n.actionGhost {\n background-color: transparent;\n color: var(--text-secondary, #6b7280);\n border: var(--stroke-width-thin, 1px) solid var(--border-default, #e5e7eb);\n}\n\n.actionGhost:hover:not(:disabled) {\n background-color: color-mix(in srgb, var(--surface-card, #ffffff) 80%, transparent);\n}\n\n/* Action icon */\n.actionIcon {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 13px;\n height: 13px;\n flex-shrink: 0;\n}\n\n/* Gate indicator — pushed right via margin-left: auto */\n.gate {\n margin-left: auto;\n font-size: 11px;\n color: var(--text-tertiary, #9ca3af);\n display: inline-flex;\n align-items: center;\n gap: var(--spacing-1, 0.25rem);\n white-space: nowrap;\n flex-shrink: 0;\n}\n\n.gateIcon {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 12px;\n height: 12px;\n flex-shrink: 0;\n}\n\n/* Respect reduced motion */\n@media (prefers-reduced-motion: reduce) {\n .action {\n transition: none;\n }\n}\n"
655
655
  }
656
656
  ]
657
657
  },
@@ -677,7 +677,7 @@
677
677
  {
678
678
  "path": "components/ui/coherence-check/coherence-check.module.css",
679
679
  "type": "registry:ui",
680
- "content": "/* ─── CheckGroup ─────────────────────────────────────────────────────────── */\n\n.group {\n margin-bottom: var(--spacing-5, 1.25rem);\n}\n\n/* Uppercase group header */\n.groupHeading {\n margin: 0 0 var(--spacing-2, 0.5rem);\n padding: 0 calc(var(--spacing-1, 0.25rem) / 2);\n font-size: var(--font-size-xs, 0.75rem);\n font-weight: var(--font-weight-extrabold, 800);\n letter-spacing: 0.06em;\n text-transform: uppercase;\n color: var(--text-tertiary, #9ca3af);\n line-height: 1.4;\n}\n\n/* ─── CheckRow ───────────────────────────────────────────────────────────── */\n\n.row {\n display: flex;\n align-items: flex-start;\n gap: var(--spacing-3, 0.75rem);\n background: var(--surface-card, #ffffff);\n border: var(--stroke-width-thin, 1px) solid var(--hairline, #e5e7eb);\n border-radius: var(--radius-lg, 0.5rem);\n padding: var(--spacing-3, 0.75rem) var(--spacing-4, 1rem);\n margin-bottom: var(--spacing-2, 0.5rem);\n box-shadow: var(--shadow-sm);\n}\n\n/* Last row in a group has no bottom margin */\n.row:last-child {\n margin-bottom: 0;\n}\n\n/* ─── State icon circle ─────────────────────────────────────────────────── */\n\n.icon {\n flex: none;\n width: var(--spacing-6, 1.5rem);\n height: var(--spacing-6, 1.5rem);\n border-radius: var(--radius-full, 9999px);\n display: grid;\n place-items: center;\n margin-top: calc(var(--spacing-1, 0.25rem) / 4);\n color: var(--text-inverse, #ffffff);\n}\n\n.icon svg {\n width: var(--spacing-4, 1rem);\n height: var(--spacing-4, 1rem);\n}\n\n/* State — icon background tints */\n.statePass .icon {\n background: var(--success, #22c55e);\n}\n\n.stateWarn .icon {\n background: var(--warning, #f59e0b);\n}\n\n.stateFail .icon {\n background: var(--destructive, #ef4444);\n}\n\n/* ─── Body (title + description) ─────────────────────────────────────────── */\n\n.body {\n flex: 1;\n min-width: 0;\n}\n\n.rowTitle {\n display: block;\n font-size: var(--font-size-sm, 0.875rem);\n font-weight: var(--font-weight-bold, 700);\n color: var(--text-primary, #111827);\n line-height: 1.4;\n}\n\n.rowDescription {\n margin: calc(var(--spacing-1, 0.25rem) * 0.75) 0 0;\n font-size: var(--font-size-xs, 0.75rem);\n color: var(--text-secondary, #6b7280);\n line-height: 1.5;\n}\n\n/* Inline code token support within description */\n.rowDescription code {\n font-family: var(--font-mono, ui-monospace, monospace);\n font-size: var(--font-size-xs, 0.75rem);\n background: var(--surface-muted, #f3f4f6);\n padding: var(--stroke-width-thin, 1px) var(--spacing-1, 0.25rem);\n border-radius: var(--radius-sm, 0.125rem);\n}\n\n/* ─── Fix action button (ghost) ──────────────────────────────────────────── */\n\n.fixButton {\n flex: none;\n align-self: center;\n height: var(--spacing-8, 2rem);\n padding: 0 var(--spacing-3, 0.75rem);\n border-radius: var(--radius-md, 0.25rem);\n font-family: inherit;\n font-size: var(--font-size-xs, 0.75rem);\n font-weight: var(--font-weight-bold, 700);\n border: var(--stroke-width-thin, 1px) solid var(--border-default, #e5e7eb);\n background: transparent;\n color: var(--text-primary, #111827);\n cursor: pointer;\n transition:\n background-color var(--motion-duration-150, 150ms) var(--motion-easing-default, ease-in-out),\n border-color var(--motion-duration-150, 150ms) var(--motion-easing-default, ease-in-out),\n color var(--motion-duration-150, 150ms) var(--motion-easing-default, ease-in-out);\n white-space: nowrap;\n}\n\n.fixButton:hover {\n background: var(--surface-muted, #f3f4f6);\n border-color: var(--border-strong, #d1d5db);\n}\n\n.fixButton:focus-visible {\n outline: var(--focus-ring-width, 2px) solid var(--border-focus, currentColor);\n outline-offset: var(--focus-ring-offset, 2px);\n}\n"
680
+ "content": "/* ─── CheckGroup ─────────────────────────────────────────────────────────── */\n\n.group {\n margin-bottom: var(--spacing-5, 1.25rem);\n}\n\n/* Uppercase group header */\n.groupHeading {\n margin: 0 0 var(--spacing-2, 0.5rem);\n padding: 0 calc(var(--spacing-1, 0.25rem) / 2);\n font-size: var(--font-size-xs, 0.75rem);\n font-weight: var(--font-weight-extrabold, 800);\n letter-spacing: 0.06em;\n text-transform: uppercase;\n color: var(--text-tertiary, #9ca3af);\n line-height: 1.4;\n}\n\n/* ─── CheckRow ───────────────────────────────────────────────────────────── */\n\n.row {\n display: flex;\n align-items: flex-start;\n gap: var(--spacing-3, 0.75rem);\n background: var(--surface-card, #ffffff);\n border: var(--stroke-width-thin, 1px) solid var(--hairline, #e5e7eb);\n border-radius: var(--radius-lg, 0.5rem);\n padding: var(--spacing-3, 0.75rem) var(--spacing-4, 1rem);\n margin-bottom: var(--spacing-2, 0.5rem);\n box-shadow: var(--shadow-sm);\n}\n\n/* Last row in a group has no bottom margin */\n.row:last-child {\n margin-bottom: 0;\n}\n\n/* ─── State icon circle ─────────────────────────────────────────────────── */\n\n.icon {\n flex: none;\n width: var(--spacing-6, 1.5rem);\n height: var(--spacing-6, 1.5rem);\n border-radius: var(--radius-full, 9999px);\n display: grid;\n place-items: center;\n margin-top: calc(var(--spacing-1, 0.25rem) / 4);\n color: var(--text-inverse, #ffffff);\n}\n\n.icon svg {\n width: var(--spacing-4, 1rem);\n height: var(--spacing-4, 1rem);\n}\n\n/* State — icon background tints */\n.statePass .icon {\n background: var(--success, #22c55e);\n}\n\n.stateWarn .icon {\n background: var(--warning, #f59e0b);\n}\n\n.stateFail .icon {\n background: var(--destructive, #ef4444);\n}\n\n/* ─── Body (title + description) ─────────────────────────────────────────── */\n\n.body {\n flex: 1;\n min-width: 0;\n}\n\n.rowTitle {\n display: block;\n font-size: var(--font-size-sm, 0.875rem);\n font-weight: var(--font-weight-bold, 700);\n color: var(--text-primary, #111827);\n line-height: 1.4;\n}\n\n.rowDescription {\n margin: calc(var(--spacing-1, 0.25rem) * 0.75) 0 0;\n font-size: var(--font-size-xs, 0.75rem);\n color: var(--text-secondary, #6b7280);\n line-height: 1.5;\n}\n\n/* Inline code token support within description */\n.rowDescription code {\n font-family: var(--font-mono, ui-monospace, monospace);\n font-size: var(--font-size-xs, 0.75rem);\n background: var(--surface-muted, #f3f4f6);\n padding: var(--stroke-width-thin, 1px) var(--spacing-1, 0.25rem);\n border-radius: var(--radius-sm, 0.125rem);\n}\n\n/* ─── Fix action button (ghost) ──────────────────────────────────────────── */\n\n.fixButton {\n flex: none;\n align-self: center;\n height: var(--spacing-8, 2rem);\n padding: 0 var(--spacing-3, 0.75rem);\n border-radius: var(--radius-md, 0.25rem);\n font-size: var(--font-size-xs, 0.75rem);\n font-weight: var(--font-weight-bold, 700);\n border: var(--stroke-width-thin, 1px) solid var(--border-default, #e5e7eb);\n background: transparent;\n color: var(--text-primary, #111827);\n cursor: pointer;\n transition:\n background-color var(--motion-duration-150, 150ms) var(--motion-easing-default, ease-in-out),\n border-color var(--motion-duration-150, 150ms) var(--motion-easing-default, ease-in-out),\n color var(--motion-duration-150, 150ms) var(--motion-easing-default, ease-in-out);\n white-space: nowrap;\n}\n\n.fixButton:hover {\n background: var(--surface-muted, #f3f4f6);\n border-color: var(--border-strong, #d1d5db);\n}\n\n.fixButton:focus-visible {\n outline: var(--focus-ring-width, 2px) solid var(--border-focus, currentColor);\n outline-offset: var(--focus-ring-offset, 2px);\n}\n"
681
681
  }
682
682
  ]
683
683
  },
@@ -832,7 +832,7 @@
832
832
  {
833
833
  "path": "components/ui/tabs/tabs.module.css",
834
834
  "type": "registry:ui",
835
- "content": "/* Tabs root */\n.root {\n display: flex;\n flex-direction: column;\n gap: var(--spacing-2, 0.5rem);\n}\n\n/* Tabs list */\n.list {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n border-radius: var(--radius-full, 9999px);\n padding: calc(var(--spacing-1, 0.25rem) * 0.75);\n color: var(--text-secondary, #6b7280);\n height: 2.25rem;\n width: fit-content;\n}\n\n.listVariantDefault {\n background-color: var(--surface-muted, #f3f4f6);\n}\n\n.listVariantLine {\n position: relative;\n gap: var(--spacing-2, 0.5rem);\n background-color: transparent;\n border-radius: 0;\n border-bottom: 1px solid var(--hairline, var(--border-default, #e5e7eb));\n height: auto;\n padding-bottom: 0;\n width: 100%;\n justify-content: flex-start;\n}\n\n/* Line variant: content-width triggers with comfortable padding — the strip\n reads as an underlined rail, not a segmented control. */\n.listVariantLine .trigger {\n flex: 0 0 auto;\n padding: var(--spacing-2, 0.5rem) var(--spacing-3, 0.75rem);\n}\n\n/* Tabs trigger */\n.trigger {\n position: relative;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: calc(var(--spacing-1, 0.25rem) * 1.5);\n border-radius: var(--radius-md, 0.375rem);\n border: 1px solid transparent;\n padding: var(--spacing-1, 0.25rem) var(--spacing-2, 0.5rem);\n font-size: var(--font-size-sm, 0.875rem);\n font-weight: var(--font-weight-medium, 500);\n /* <button> doesn't inherit font-family — without this the trigger falls back\n to the UA default (Arial), not the theme font. */\n font-family: inherit;\n white-space: nowrap;\n color: var(--text-secondary, #6b7280);\n background: transparent;\n cursor: pointer;\n transition: color var(--motion-duration-150, 150ms) var(--motion-easing-default, ease-in-out), background-color var(--motion-duration-150, 150ms) var(--motion-easing-default, ease-in-out), border-color var(--motion-duration-150, 150ms) var(--motion-easing-default, ease-in-out), transform var(--motion-duration-150, 150ms) var(--motion-easing-default, ease-in-out);\n outline: none;\n flex: 1;\n height: calc(100% - 2px);\n}\n\n.trigger:active:not(:disabled) {\n transform: translateY(1px);\n transition: none;\n}\n\n@media (hover: hover) {\n .trigger:hover {\n color: var(--text-primary, #111827);\n }\n}\n\n.trigger:focus-visible {\n outline: var(--focus-ring-width, 2px) solid var(--border-focus, currentColor);\n outline-offset: var(--focus-ring-offset, 2px);\n}\n\n.trigger:disabled {\n pointer-events: none;\n opacity: 0.5;\n}\n\n.trigger[data-state=\"active\"] {\n background-color: var(--surface-page, #ffffff);\n color: var(--text-primary, #111827);\n box-shadow: var(--shadow-sm);\n}\n\n/* Trigger label — wraps children to allow count pill alongside */\n.label {\n flex: 1 1 auto;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n/* Count pill */\n.count {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n border-radius: var(--radius-full, 9999px);\n padding: 0 var(--spacing-2, 0.5rem);\n font-size: var(--font-size-xs, 0.75rem);\n font-weight: var(--font-weight-medium, 500);\n font-variant-numeric: tabular-nums;\n line-height: 1.5;\n vertical-align: baseline;\n}\n\n.countNeutral {\n background-color: var(--surface-muted, #f3f4f6);\n color: var(--text-secondary, #6b7280);\n}\n\n.countPrimary {\n background-color: var(--surface-accent-subtle, #eff6ff);\n color: var(--text-link, #2563eb);\n}\n\n/* Active-state re-tone: regardless of countTone, re-tone to primary on active */\n.trigger[data-state=\"active\"] .count {\n background-color: var(--surface-accent-subtle, #eff6ff);\n color: var(--text-link, #2563eb);\n}\n\n/* Tabs content */\n.content {\n flex: 1;\n font-size: var(--font-size-sm, 0.875rem);\n outline: none;\n}\n\n.content:focus-visible {\n outline: var(--focus-ring-width, 2px) solid var(--border-focus, currentColor);\n outline-offset: var(--focus-ring-offset, 2px);\n}\n\n/* Line variant: active trigger loses shadow/bg, just text color */\n.listVariantLine .trigger[data-state=\"active\"] {\n background-color: transparent;\n box-shadow: none;\n}\n\n/* Animated sliding indicator for line variant */\n.indicator {\n position: absolute;\n bottom: -1px;\n height: 2px;\n /* Default: text-primary */\n background-color: var(--text-primary, #111827);\n border-radius: var(--radius-full, 9999px);\n transition: left var(--motion-duration-normal, 200ms) var(--motion-easing-default, ease-in-out),\n width var(--motion-duration-normal, 200ms) var(--motion-easing-default, ease-in-out);\n}\n\n/* Density axis — editorial: brand primary underline for dark admin surfaces */\n:global([data-density=\"editorial\"]) .indicator {\n background-color: var(--primary);\n}\n"
835
+ "content": "/* Tabs root */\n.root {\n display: flex;\n flex-direction: column;\n gap: var(--spacing-2, 0.5rem);\n}\n\n/* Tabs list */\n.list {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n border-radius: var(--radius-full, 9999px);\n padding: calc(var(--spacing-1, 0.25rem) * 0.75);\n color: var(--text-secondary, #6b7280);\n height: 2.25rem;\n width: fit-content;\n}\n\n.listVariantDefault {\n background-color: var(--surface-muted, #f3f4f6);\n}\n\n.listVariantLine {\n position: relative;\n gap: var(--spacing-2, 0.5rem);\n background-color: transparent;\n border-radius: 0;\n border-bottom: 1px solid var(--hairline, var(--border-default, #e5e7eb));\n height: auto;\n padding-bottom: 0;\n width: 100%;\n justify-content: flex-start;\n}\n\n/* Line variant: content-width triggers with comfortable padding — the strip\n reads as an underlined rail, not a segmented control. */\n.listVariantLine .trigger {\n flex: 0 0 auto;\n padding: var(--spacing-2, 0.5rem) var(--spacing-3, 0.75rem);\n}\n\n/* Tabs trigger */\n.trigger {\n position: relative;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: calc(var(--spacing-1, 0.25rem) * 1.5);\n border-radius: var(--radius-md, 0.375rem);\n border: 1px solid transparent;\n padding: var(--spacing-1, 0.25rem) var(--spacing-2, 0.5rem);\n font-size: var(--font-size-sm, 0.875rem);\n font-weight: var(--font-weight-medium, 500);\n white-space: nowrap;\n color: var(--text-secondary, #6b7280);\n background: transparent;\n cursor: pointer;\n transition: color var(--motion-duration-150, 150ms) var(--motion-easing-default, ease-in-out), background-color var(--motion-duration-150, 150ms) var(--motion-easing-default, ease-in-out), border-color var(--motion-duration-150, 150ms) var(--motion-easing-default, ease-in-out), transform var(--motion-duration-150, 150ms) var(--motion-easing-default, ease-in-out);\n outline: none;\n flex: 1;\n height: calc(100% - 2px);\n}\n\n.trigger:active:not(:disabled) {\n transform: translateY(1px);\n transition: none;\n}\n\n@media (hover: hover) {\n .trigger:hover {\n color: var(--text-primary, #111827);\n }\n}\n\n.trigger:focus-visible {\n outline: var(--focus-ring-width, 2px) solid var(--border-focus, currentColor);\n outline-offset: var(--focus-ring-offset, 2px);\n}\n\n.trigger:disabled {\n pointer-events: none;\n opacity: 0.5;\n}\n\n.trigger[data-state=\"active\"] {\n background-color: var(--surface-page, #ffffff);\n color: var(--text-primary, #111827);\n box-shadow: var(--shadow-sm);\n}\n\n/* Trigger label — wraps children to allow count pill alongside */\n.label {\n flex: 1 1 auto;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n/* Count pill */\n.count {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n border-radius: var(--radius-full, 9999px);\n padding: 0 var(--spacing-2, 0.5rem);\n font-size: var(--font-size-xs, 0.75rem);\n font-weight: var(--font-weight-medium, 500);\n font-variant-numeric: tabular-nums;\n line-height: 1.5;\n vertical-align: baseline;\n}\n\n.countNeutral {\n background-color: var(--surface-muted, #f3f4f6);\n color: var(--text-secondary, #6b7280);\n}\n\n.countPrimary {\n background-color: var(--surface-accent-subtle, #eff6ff);\n color: var(--text-link, #2563eb);\n}\n\n/* Active-state re-tone: regardless of countTone, re-tone to primary on active */\n.trigger[data-state=\"active\"] .count {\n background-color: var(--surface-accent-subtle, #eff6ff);\n color: var(--text-link, #2563eb);\n}\n\n/* Tabs content */\n.content {\n flex: 1;\n font-size: var(--font-size-sm, 0.875rem);\n outline: none;\n}\n\n.content:focus-visible {\n outline: var(--focus-ring-width, 2px) solid var(--border-focus, currentColor);\n outline-offset: var(--focus-ring-offset, 2px);\n}\n\n/* Line variant: active trigger loses shadow/bg, just text color */\n.listVariantLine .trigger[data-state=\"active\"] {\n background-color: transparent;\n box-shadow: none;\n}\n\n/* Animated sliding indicator for line variant */\n.indicator {\n position: absolute;\n bottom: -1px;\n height: 2px;\n /* Default: text-primary */\n background-color: var(--text-primary, #111827);\n border-radius: var(--radius-full, 9999px);\n transition: left var(--motion-duration-normal, 200ms) var(--motion-easing-default, ease-in-out),\n width var(--motion-duration-normal, 200ms) var(--motion-easing-default, ease-in-out);\n}\n\n/* Density axis — editorial: brand primary underline for dark admin surfaces */\n:global([data-density=\"editorial\"]) .indicator {\n background-color: var(--primary);\n}\n"
836
836
  }
837
837
  ]
838
838
  },
@@ -1070,7 +1070,7 @@
1070
1070
  {
1071
1071
  "path": "components/ui/toast/toast.module.css",
1072
1072
  "type": "registry:ui",
1073
- "content": "/* Toaster container */\n.toaster {\n /* Container styling if needed */\n}\n\n/* Individual toast — :global() selectors nested under .toaster for CSS Modules purity.\n Sonner renders toasts as children of its container element. */\n.toaster :global([data-sonner-toast]) {\n font-family: var(--font-family-sans, system-ui, sans-serif);\n background-color: var(--surface-popover, var(--surface-card, #ffffff));\n color: var(--text-primary, #111827);\n border-radius: var(--radius-lg, 0.5rem);\n box-shadow: var(--shadow-lg);\n padding: var(--spacing-3, 0.75rem) var(--spacing-4, 1rem);\n gap: var(--spacing-2, 0.5rem);\n /* Override Sonner's default 400ms transitions with Visor motion tokens */\n transition:\n transform var(--motion-duration-normal, 200ms) var(--motion-easing-enter, ease-out),\n opacity var(--motion-duration-normal, 200ms) var(--motion-easing-enter, ease-out),\n height var(--motion-duration-normal, 200ms) !important;\n}\n\n/* Faster exit animation for dismissed toasts */\n.toaster :global([data-sonner-toast][data-removed=\"true\"]) {\n transition:\n transform var(--motion-duration-150, 150ms) var(--motion-easing-exit, ease-in),\n opacity var(--motion-duration-150, 150ms) var(--motion-easing-exit, ease-in) !important;\n}\n\n/* Toast title */\n.toaster :global([data-sonner-toast] [data-title]) {\n font-weight: var(--font-weight-semibold, 600);\n font-size: var(--font-size-sm, 0.875rem);\n color: var(--text-primary, #111827);\n}\n\n/* Toast description */\n.toaster :global([data-sonner-toast] [data-description]) {\n font-size: var(--font-size-sm, 0.875rem);\n color: var(--text-secondary, #6b7280);\n}\n\n/* Type-specific colors — subtle bg fill + left accent border */\n\n/* Success: Borealis-spec dark inverse surface (VI-589).\n Dark bg + light text signals a completed, affirmative action.\n Falls back to a high-contrast dark surface on themes that lack\n the --surface-inverse token (for example, custom minimal themes). */\n.toaster :global([data-sonner-toast][data-type=\"success\"]) {\n background-color: var(--surface-inverse, var(--text-primary, #111827));\n color: var(--text-inverse, #f9fafb);\n border-left: none;\n}\n\n/* Success title — use inverse text so it reads on the dark bg */\n.toaster :global([data-sonner-toast][data-type=\"success\"] [data-title]) {\n color: var(--text-inverse, #f9fafb);\n font-weight: var(--font-weight-semibold, 700);\n}\n\n/* Success description — slightly muted inverse text */\n.toaster :global([data-sonner-toast][data-type=\"success\"] [data-description]) {\n color: var(--text-inverse-secondary, #d1d5db);\n}\n\n/* Success action button — accent colour reads on dark surface */\n.toaster :global([data-sonner-toast][data-type=\"success\"] [data-button]) {\n background-color: var(--primary, #111827);\n color: var(--primary-text, #ffffff);\n border: var(--stroke-width-thin, 1px) solid color-mix(in srgb, var(--primary, #111827) 60%, transparent);\n}\n\n/* Success close button — muted inverse */\n.toaster :global([data-sonner-toast][data-type=\"success\"] [data-close-button]) {\n background-color: transparent;\n border-color: color-mix(in srgb, var(--text-inverse, #f9fafb) 20%, transparent);\n color: var(--text-inverse-secondary, #d1d5db);\n}\n\n.toaster :global([data-sonner-toast][data-type=\"error\"]) {\n background-color: var(--surface-error-subtle, #fef2f2);\n border-left: 3px solid var(--border-error, #ef4444);\n}\n\n.toaster :global([data-sonner-toast][data-type=\"warning\"]) {\n background-color: var(--surface-warning-subtle, #fffbeb);\n border-left: 3px solid var(--border-warning, #f59e0b);\n}\n\n.toaster :global([data-sonner-toast][data-type=\"info\"]) {\n background-color: var(--surface-info-subtle, #f0f9ff);\n border-left: 3px solid var(--border-info, #0ea5e9);\n}\n\n/* Action button */\n.toaster :global([data-sonner-toast] [data-button]) {\n background-color: var(--interactive-primary-bg, var(--primary, #111827));\n color: var(--interactive-primary-text, #ffffff);\n border-radius: var(--radius-md, 0.375rem);\n font-size: var(--font-size-xs, 0.75rem);\n font-weight: var(--font-weight-medium, 500);\n padding: var(--spacing-1, 0.25rem) var(--spacing-2, 0.5rem);\n}\n\n/* Cancel button */\n.toaster :global([data-sonner-toast] [data-cancel]) {\n background-color: transparent;\n color: var(--text-secondary, #6b7280);\n font-size: var(--font-size-xs, 0.75rem);\n}\n\n/* Close button */\n.toaster :global([data-sonner-toast] [data-close-button]) {\n background-color: var(--surface-card, #ffffff);\n border: 1px solid var(--border-default, #e5e7eb);\n color: var(--text-secondary, #6b7280);\n}\n\n/* Dark mode support — :where() keeps specificity low so type-specific selectors above win */\n:global(:where(.dark)) .toaster :global([data-sonner-toast]),\n:global(:where([data-theme=\"dark\"])) .toaster :global([data-sonner-toast]) {\n background-color: var(--surface-card, #1f2937);\n color: var(--text-primary, #f9fafb);\n}\n\n/* Class-based styles applied via Sonner's classNames option */\n.toast {\n /* Specificity boost layer — matches :global styles above */\n}\n\n.title {\n font-weight: var(--font-weight-semibold, 600);\n}\n\n.description {\n color: var(--text-secondary, #6b7280);\n}\n\n.actionButton {\n background-color: var(--interactive-primary-bg, var(--primary, #111827));\n color: var(--interactive-primary-text, #ffffff);\n border-radius: var(--radius-md, 0.375rem);\n font-size: var(--font-size-xs, 0.75rem);\n font-weight: var(--font-weight-medium, 500);\n padding: var(--spacing-1, 0.25rem) var(--spacing-2, 0.5rem);\n}\n\n.cancelButton {\n background-color: transparent;\n color: var(--text-secondary, #6b7280);\n font-size: var(--font-size-xs, 0.75rem);\n}\n\n.closeButton {\n background-color: var(--surface-card, #ffffff);\n border: 1px solid var(--border-default, #e5e7eb);\n color: var(--text-secondary, #6b7280);\n}\n"
1073
+ "content": "/* Toaster container */\n.toaster {\n /* Container styling if needed */\n}\n\n/* Individual toast — :global() selectors nested under .toaster for CSS Modules purity.\n Sonner renders toasts as children of its container element. */\n.toaster :global([data-sonner-toast]) {\n font-family: var(--font-family-sans, inherit);\n background-color: var(--surface-popover, var(--surface-card, #ffffff));\n color: var(--text-primary, #111827);\n border-radius: var(--radius-lg, 0.5rem);\n box-shadow: var(--shadow-lg);\n padding: var(--spacing-3, 0.75rem) var(--spacing-4, 1rem);\n gap: var(--spacing-2, 0.5rem);\n /* Override Sonner's default 400ms transitions with Visor motion tokens */\n transition:\n transform var(--motion-duration-normal, 200ms) var(--motion-easing-enter, ease-out),\n opacity var(--motion-duration-normal, 200ms) var(--motion-easing-enter, ease-out),\n height var(--motion-duration-normal, 200ms) !important;\n}\n\n/* Faster exit animation for dismissed toasts */\n.toaster :global([data-sonner-toast][data-removed=\"true\"]) {\n transition:\n transform var(--motion-duration-150, 150ms) var(--motion-easing-exit, ease-in),\n opacity var(--motion-duration-150, 150ms) var(--motion-easing-exit, ease-in) !important;\n}\n\n/* Toast title */\n.toaster :global([data-sonner-toast] [data-title]) {\n font-weight: var(--font-weight-semibold, 600);\n font-size: var(--font-size-sm, 0.875rem);\n color: var(--text-primary, #111827);\n}\n\n/* Toast description */\n.toaster :global([data-sonner-toast] [data-description]) {\n font-size: var(--font-size-sm, 0.875rem);\n color: var(--text-secondary, #6b7280);\n}\n\n/* Type-specific colors — subtle bg fill + left accent border */\n\n/* Success: Borealis-spec dark inverse surface (VI-589).\n Dark bg + light text signals a completed, affirmative action.\n Falls back to a high-contrast dark surface on themes that lack\n the --surface-inverse token (for example, custom minimal themes). */\n.toaster :global([data-sonner-toast][data-type=\"success\"]) {\n background-color: var(--surface-inverse, var(--text-primary, #111827));\n color: var(--text-inverse, #f9fafb);\n border-left: none;\n}\n\n/* Success title — use inverse text so it reads on the dark bg */\n.toaster :global([data-sonner-toast][data-type=\"success\"] [data-title]) {\n color: var(--text-inverse, #f9fafb);\n font-weight: var(--font-weight-semibold, 700);\n}\n\n/* Success description — slightly muted inverse text */\n.toaster :global([data-sonner-toast][data-type=\"success\"] [data-description]) {\n color: var(--text-inverse-secondary, #d1d5db);\n}\n\n/* Success action button — accent colour reads on dark surface */\n.toaster :global([data-sonner-toast][data-type=\"success\"] [data-button]) {\n background-color: var(--primary, #111827);\n color: var(--primary-text, #ffffff);\n border: var(--stroke-width-thin, 1px) solid color-mix(in srgb, var(--primary, #111827) 60%, transparent);\n}\n\n/* Success close button — muted inverse */\n.toaster :global([data-sonner-toast][data-type=\"success\"] [data-close-button]) {\n background-color: transparent;\n border-color: color-mix(in srgb, var(--text-inverse, #f9fafb) 20%, transparent);\n color: var(--text-inverse-secondary, #d1d5db);\n}\n\n.toaster :global([data-sonner-toast][data-type=\"error\"]) {\n background-color: var(--surface-error-subtle, #fef2f2);\n border-left: 3px solid var(--border-error, #ef4444);\n}\n\n.toaster :global([data-sonner-toast][data-type=\"warning\"]) {\n background-color: var(--surface-warning-subtle, #fffbeb);\n border-left: 3px solid var(--border-warning, #f59e0b);\n}\n\n.toaster :global([data-sonner-toast][data-type=\"info\"]) {\n background-color: var(--surface-info-subtle, #f0f9ff);\n border-left: 3px solid var(--border-info, #0ea5e9);\n}\n\n/* Action button */\n.toaster :global([data-sonner-toast] [data-button]) {\n background-color: var(--interactive-primary-bg, var(--primary, #111827));\n color: var(--interactive-primary-text, #ffffff);\n border-radius: var(--radius-md, 0.375rem);\n font-size: var(--font-size-xs, 0.75rem);\n font-weight: var(--font-weight-medium, 500);\n padding: var(--spacing-1, 0.25rem) var(--spacing-2, 0.5rem);\n}\n\n/* Cancel button */\n.toaster :global([data-sonner-toast] [data-cancel]) {\n background-color: transparent;\n color: var(--text-secondary, #6b7280);\n font-size: var(--font-size-xs, 0.75rem);\n}\n\n/* Close button */\n.toaster :global([data-sonner-toast] [data-close-button]) {\n background-color: var(--surface-card, #ffffff);\n border: 1px solid var(--border-default, #e5e7eb);\n color: var(--text-secondary, #6b7280);\n}\n\n/* Dark mode support — :where() keeps specificity low so type-specific selectors above win */\n:global(:where(.dark)) .toaster :global([data-sonner-toast]),\n:global(:where([data-theme=\"dark\"])) .toaster :global([data-sonner-toast]) {\n background-color: var(--surface-card, #1f2937);\n color: var(--text-primary, #f9fafb);\n}\n\n/* Class-based styles applied via Sonner's classNames option */\n.toast {\n /* Specificity boost layer — matches :global styles above */\n}\n\n.title {\n font-weight: var(--font-weight-semibold, 600);\n}\n\n.description {\n color: var(--text-secondary, #6b7280);\n}\n\n.actionButton {\n background-color: var(--interactive-primary-bg, var(--primary, #111827));\n color: var(--interactive-primary-text, #ffffff);\n border-radius: var(--radius-md, 0.375rem);\n font-size: var(--font-size-xs, 0.75rem);\n font-weight: var(--font-weight-medium, 500);\n padding: var(--spacing-1, 0.25rem) var(--spacing-2, 0.5rem);\n}\n\n.cancelButton {\n background-color: transparent;\n color: var(--text-secondary, #6b7280);\n font-size: var(--font-size-xs, 0.75rem);\n}\n\n.closeButton {\n background-color: var(--surface-card, #ffffff);\n border: 1px solid var(--border-default, #e5e7eb);\n color: var(--text-secondary, #6b7280);\n}\n"
1074
1074
  }
1075
1075
  ]
1076
1076
  },
@@ -1299,7 +1299,7 @@
1299
1299
  {
1300
1300
  "path": "components/ui/combobox/combobox.module.css",
1301
1301
  "type": "registry:ui",
1302
- "content": "/* Combobox root */\n.root {\n position: relative;\n display: inline-flex;\n flex-direction: column;\n width: fit-content;\n}\n\n/* Input wrapper */\n.inputWrapper {\n position: relative;\n display: flex;\n align-items: center;\n}\n\n/* Input */\n.input {\n width: 100%;\n height: 2.25rem;\n padding: var(--spacing-2, 0.5rem) calc(var(--spacing-8, 2rem) + var(--spacing-1, 0.25rem)) var(--spacing-2, 0.5rem) var(--spacing-3, 0.75rem);\n border-radius: var(--radius-md, 0.375rem);\n border: 1px solid var(--combobox-border, var(--border-default, #e5e7eb));\n background-color: var(--combobox-bg, var(--surface-interactive-default, #f9fafb));\n font-size: var(--font-size-sm, 0.875rem);\n color: var(--text-primary, #111827);\n transition: border-color var(--motion-duration-150, 150ms) var(--motion-easing-default, ease-in-out),\n box-shadow var(--motion-duration-150, 150ms) var(--motion-easing-default, ease-in-out);\n outline: none;\n}\n\n.input::placeholder {\n color: var(--text-secondary, #9ca3af);\n}\n\n@media (hover: hover) {\n .input:hover:not(:focus-visible):not(:disabled) {\n border-color: var(--border-strong, #d1d5db);\n }\n}\n\n.input:focus-visible {\n border-color: var(--border-focus, #111827);\n box-shadow: 0 0 0 var(--focus-ring-width, 2px) color-mix(in srgb, var(--border-focus, #111827) 15%, transparent);\n}\n\n.input:disabled {\n cursor: not-allowed;\n opacity: 0.5;\n}\n\n/* Caret icon */\n.icon {\n position: absolute;\n right: var(--spacing-3, 0.75rem);\n top: 50%;\n transform: translateY(-50%);\n width: 1rem;\n height: 1rem;\n pointer-events: none;\n color: var(--text-secondary, #9ca3af);\n transition: transform var(--motion-duration-150, 150ms) var(--motion-easing-default, ease-in-out);\n}\n\n.iconOpen {\n transform: translateY(-50%) rotate(180deg);\n}\n\n/* Content popover */\n.content {\n z-index: 50;\n min-width: var(--radix-popover-trigger-width, 12rem);\n max-height: 18rem;\n overflow: hidden auto;\n border-radius: var(--radius-lg, 0.5rem);\n background-color: var(--field-menu-bg, var(--surface-popover, var(--surface-card, #ffffff)));\n color: var(--text-primary, #111827);\n box-shadow: var(--shadow-lg);\n padding: var(--spacing-1, 0.25rem);\n}\n\n/* Listbox */\n.listbox {\n list-style: none;\n margin: 0;\n padding: 0;\n}\n\n/* Item */\n.item {\n position: relative;\n display: flex;\n align-items: center;\n gap: var(--spacing-2, 0.5rem);\n padding: var(--spacing-2, 0.5rem) var(--spacing-3, 0.75rem);\n border-radius: var(--radius-sm, 0.25rem);\n font-size: var(--font-size-sm, 0.875rem);\n cursor: default;\n outline: none;\n user-select: none;\n}\n\n.item:focus:not([data-disabled]) {\n background-color: var(--surface-interactive-hover, #f3f4f6);\n cursor: pointer;\n}\n\n@media (hover: hover) {\n .item:hover:not([data-disabled]) {\n background-color: var(--surface-interactive-hover, #f3f4f6);\n cursor: pointer;\n }\n}\n\n.item[data-disabled] {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n.item[data-selected] {\n background-color: var(--surface-interactive-hover, #f3f4f6);\n font-weight: var(--font-weight-medium, 500);\n}\n\n.itemCheck {\n display: inline-flex;\n width: 1rem;\n height: 1rem;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n}\n\n.itemCheckIcon {\n width: 0.875rem;\n height: 0.875rem;\n color: var(--interactive-primary-bg, var(--primary, #111827));\n}\n\n/* Empty */\n.empty {\n list-style: none;\n padding: var(--spacing-4, 1rem) var(--spacing-3, 0.75rem);\n text-align: center;\n font-size: var(--font-size-sm, 0.875rem);\n color: var(--text-secondary, #9ca3af);\n}\n\n/* Group */\n.group {\n list-style: none;\n}\n\n.group ul {\n list-style: none;\n margin: 0;\n padding: 0;\n}\n\n.groupHeading {\n padding: var(--spacing-1, 0.25rem) var(--spacing-3, 0.75rem) var(--spacing-1, 0.25rem);\n font-size: var(--font-size-xs, 0.75rem);\n font-weight: var(--font-weight-medium, 500);\n color: var(--text-secondary, #9ca3af);\n text-transform: uppercase;\n letter-spacing: 0.05em;\n}\n\n/* Separator */\n.separator {\n list-style: none;\n height: 1px;\n margin: var(--spacing-1, 0.25rem) calc(-1 * var(--spacing-1, 0.25rem));\n background-color: var(--border-default, #e5e7eb);\n}\n\n/* VI-510: form controls do not inherit font-family from the page; opt back in (matches textarea). */\n.root :is(input, button, textarea) {\n font-family: inherit;\n}\n"
1302
+ "content": "/* Combobox root */\n.root {\n position: relative;\n display: inline-flex;\n flex-direction: column;\n width: fit-content;\n}\n\n/* Input wrapper */\n.inputWrapper {\n position: relative;\n display: flex;\n align-items: center;\n}\n\n/* Input */\n.input {\n width: 100%;\n height: 2.25rem;\n padding: var(--spacing-2, 0.5rem) calc(var(--spacing-8, 2rem) + var(--spacing-1, 0.25rem)) var(--spacing-2, 0.5rem) var(--spacing-3, 0.75rem);\n border-radius: var(--radius-md, 0.375rem);\n border: 1px solid var(--combobox-border, var(--border-default, #e5e7eb));\n background-color: var(--combobox-bg, var(--surface-interactive-default, #f9fafb));\n font-size: var(--font-size-sm, 0.875rem);\n color: var(--text-primary, #111827);\n transition: border-color var(--motion-duration-150, 150ms) var(--motion-easing-default, ease-in-out),\n box-shadow var(--motion-duration-150, 150ms) var(--motion-easing-default, ease-in-out);\n outline: none;\n}\n\n.input::placeholder {\n color: var(--text-secondary, #9ca3af);\n}\n\n@media (hover: hover) {\n .input:hover:not(:focus-visible):not(:disabled) {\n border-color: var(--border-strong, #d1d5db);\n }\n}\n\n.input:focus-visible {\n border-color: var(--border-focus, #111827);\n box-shadow: 0 0 0 var(--focus-ring-width, 2px) color-mix(in srgb, var(--border-focus, #111827) 15%, transparent);\n}\n\n.input:disabled {\n cursor: not-allowed;\n opacity: 0.5;\n}\n\n/* Caret icon */\n.icon {\n position: absolute;\n right: var(--spacing-3, 0.75rem);\n top: 50%;\n transform: translateY(-50%);\n width: 1rem;\n height: 1rem;\n pointer-events: none;\n color: var(--text-secondary, #9ca3af);\n transition: transform var(--motion-duration-150, 150ms) var(--motion-easing-default, ease-in-out);\n}\n\n.iconOpen {\n transform: translateY(-50%) rotate(180deg);\n}\n\n/* Content popover */\n.content {\n z-index: 50;\n min-width: var(--radix-popover-trigger-width, 12rem);\n max-height: 18rem;\n overflow: hidden auto;\n border-radius: var(--radius-lg, 0.5rem);\n background-color: var(--field-menu-bg, var(--surface-popover, var(--surface-card, #ffffff)));\n color: var(--text-primary, #111827);\n box-shadow: var(--shadow-lg);\n padding: var(--spacing-1, 0.25rem);\n}\n\n/* Listbox */\n.listbox {\n list-style: none;\n margin: 0;\n padding: 0;\n}\n\n/* Item */\n.item {\n position: relative;\n display: flex;\n align-items: center;\n gap: var(--spacing-2, 0.5rem);\n padding: var(--spacing-2, 0.5rem) var(--spacing-3, 0.75rem);\n border-radius: var(--radius-sm, 0.25rem);\n font-size: var(--font-size-sm, 0.875rem);\n cursor: default;\n outline: none;\n user-select: none;\n}\n\n.item:focus:not([data-disabled]) {\n background-color: var(--surface-interactive-hover, #f3f4f6);\n cursor: pointer;\n}\n\n@media (hover: hover) {\n .item:hover:not([data-disabled]) {\n background-color: var(--surface-interactive-hover, #f3f4f6);\n cursor: pointer;\n }\n}\n\n.item[data-disabled] {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n.item[data-selected] {\n background-color: var(--surface-interactive-hover, #f3f4f6);\n font-weight: var(--font-weight-medium, 500);\n}\n\n.itemCheck {\n display: inline-flex;\n width: 1rem;\n height: 1rem;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n}\n\n.itemCheckIcon {\n width: 0.875rem;\n height: 0.875rem;\n color: var(--interactive-primary-bg, var(--primary, #111827));\n}\n\n/* Empty */\n.empty {\n list-style: none;\n padding: var(--spacing-4, 1rem) var(--spacing-3, 0.75rem);\n text-align: center;\n font-size: var(--font-size-sm, 0.875rem);\n color: var(--text-secondary, #9ca3af);\n}\n\n/* Group */\n.group {\n list-style: none;\n}\n\n.group ul {\n list-style: none;\n margin: 0;\n padding: 0;\n}\n\n.groupHeading {\n padding: var(--spacing-1, 0.25rem) var(--spacing-3, 0.75rem) var(--spacing-1, 0.25rem);\n font-size: var(--font-size-xs, 0.75rem);\n font-weight: var(--font-weight-medium, 500);\n color: var(--text-secondary, #9ca3af);\n text-transform: uppercase;\n letter-spacing: 0.05em;\n}\n\n/* Separator */\n.separator {\n list-style: none;\n height: 1px;\n margin: var(--spacing-1, 0.25rem) calc(-1 * var(--spacing-1, 0.25rem));\n background-color: var(--border-default, #e5e7eb);\n}\n"
1303
1303
  }
1304
1304
  ]
1305
1305
  },
@@ -1324,7 +1324,7 @@
1324
1324
  {
1325
1325
  "path": "components/ui/composer/composer.module.css",
1326
1326
  "type": "registry:ui",
1327
- "content": "/* Composer\n *\n * AI-chat composer — a rounded card container holding a multi-line\n * auto-growing text field and a tools row with icon buttons, an arbitrary\n * status-chip slot, and a circular primary send button.\n *\n * Visual source: docs/design/brand-workbench/elicit-core (cbox selector)\n *\n * All values flow through CSS custom properties. No hard-coded colors or\n * magic numbers — every value traces to a design token or is documented.\n */\n\n/* ─── Root container ────────────────────────────────────────────────────── */\n\n.root {\n background: var(--surface-card, #ffffff);\n border: var(--stroke-width-thin, 1px) solid var(--border-default, #e5e7eb);\n border-radius: var(--radius-2xl, 1.5rem); /* ~24px, matches cbox prototype */\n box-shadow: var(--shadow-md, 0 4px 6px -1px rgb(0 0 0 / 0.1));\n padding: var(--spacing-3, 0.75rem) var(--spacing-4, 1rem); /* prototype 14/16/11px, snapped to 4px grid */\n display: flex;\n flex-direction: column;\n gap: 0;\n}\n\n.root[data-disabled] {\n opacity: var(--opacity-50, 0.5);\n pointer-events: none;\n}\n\n/* ─── Field row ─────────────────────────────────────────────────────────── */\n\n.fieldWrap {\n position: relative;\n /* The textarea and replica share the same box; replica drives the height */\n}\n\n/* Shared typographic baseline for both field and replica */\n.field {\n font-family: inherit;\n font-size: var(--font-size-base, 1rem); /* ~15px in prototype */\n line-height: var(--line-height-normal, 1.5);\n color: var(--text-primary, #111827);\n background: transparent;\n border: none;\n outline: none;\n resize: none;\n padding: 0;\n margin: 0;\n width: 100%;\n display: block;\n min-height: 22px; /* prototype: min-height 22px */\n overflow: hidden;\n}\n\n/* Hidden replica — same metrics as textarea, invisible, used for auto-grow */\n.fieldReplica {\n position: absolute;\n top: 0;\n left: 0;\n pointer-events: none;\n visibility: hidden;\n white-space: pre-wrap;\n word-break: break-word;\n overflow: hidden;\n}\n\n/* Textarea itself */\n.field:not(.fieldReplica) {\n position: relative;\n color: var(--text-primary, #111827);\n caret-color: var(--primary, #111827);\n}\n\n.field:not(.fieldReplica)::placeholder {\n color: var(--text-tertiary, #6b7280);\n}\n\n.field:not(.fieldReplica):focus-visible {\n outline: var(--focus-ring-width, 2px) solid var(--primary, #111827);\n outline-offset: var(--focus-ring-offset, 2px);\n border-radius: var(--radius-sm, 0.25rem);\n}\n\n/* ─── Toolbar row ───────────────────────────────────────────────────────── */\n\n.toolbar {\n display: flex;\n align-items: center;\n gap: var(--spacing-2, 0.5rem); /* prototype: 7px ≈ spacing-2 */\n margin-top: var(--spacing-3, 0.75rem); /* prototype 11px, snapped to 4px grid */\n}\n\n/* ─── Tool button ───────────────────────────────────────────────────────── */\n\n.toolBtn {\n width: 32px;\n height: 32px;\n border-radius: var(--radius-full, 9999px);\n border: var(--stroke-width-thin, 1px) solid var(--border-default, #e5e7eb);\n background: transparent;\n display: grid;\n place-items: center;\n color: var(--text-secondary, #374151);\n flex: none;\n cursor: pointer;\n transition:\n background-color var(--motion-duration-150, 150ms) var(--motion-easing-default, ease-in-out),\n border-color var(--motion-duration-150, 150ms) var(--motion-easing-default, ease-in-out),\n color var(--motion-duration-150, 150ms) var(--motion-easing-default, ease-in-out);\n}\n\n.toolBtn:hover:not(:disabled) {\n background: var(--surface-hover, color-mix(in srgb, var(--border-default, #e5e7eb) 40%, transparent));\n border-color: var(--border-strong, #9ca3af);\n}\n\n.toolBtn:focus-visible {\n outline: var(--focus-ring-width, 2px) solid var(--primary, #111827);\n outline-offset: var(--focus-ring-offset, 2px);\n}\n\n.toolBtn:disabled {\n opacity: var(--opacity-40, 0.4);\n cursor: not-allowed;\n}\n\n/* Icon inside tool button — 16px per prototype */\n.toolBtn > svg,\n.toolBtn > * > svg {\n width: 16px;\n height: 16px;\n}\n\n/* ─── Spacer ────────────────────────────────────────────────────────────── */\n\n.spacer {\n flex: 1;\n}\n\n/* ─── Send button ───────────────────────────────────────────────────────── */\n\n.send {\n width: 34px;\n height: 34px;\n border-radius: var(--radius-full, 9999px);\n background: var(--primary, #111827);\n color: var(--primary-foreground, #ffffff);\n display: grid;\n place-items: center;\n box-shadow: var(--shadow-sm, 0 1px 2px 0 rgb(0 0 0 / 0.05));\n flex: none;\n border: none;\n cursor: pointer;\n transition:\n background-color var(--motion-duration-150, 150ms) var(--motion-easing-default, ease-in-out),\n opacity var(--motion-duration-150, 150ms) var(--motion-easing-default, ease-in-out),\n box-shadow var(--motion-duration-150, 150ms) var(--motion-easing-default, ease-in-out);\n}\n\n.send:hover:not(:disabled) {\n background: color-mix(in srgb, var(--primary, #111827) 88%, white);\n box-shadow: var(--shadow-md, 0 4px 6px -1px rgb(0 0 0 / 0.1));\n}\n\n.send:focus-visible {\n outline: var(--focus-ring-width, 2px) solid var(--primary, #111827);\n outline-offset: var(--focus-ring-offset, 2px);\n}\n\n.send:disabled {\n opacity: var(--opacity-40, 0.4);\n cursor: not-allowed;\n}\n\n/* Icon inside send button — 17px per prototype */\n.send > svg,\n.send > * > svg {\n width: 17px;\n height: 17px;\n}\n\n/* ─── Reduced motion ────────────────────────────────────────────────────── */\n\n@media (prefers-reduced-motion: reduce) {\n .toolBtn,\n .send {\n transition: none;\n }\n}\n"
1327
+ "content": "/* Composer\n *\n * AI-chat composer — a rounded card container holding a multi-line\n * auto-growing text field and a tools row with icon buttons, an arbitrary\n * status-chip slot, and a circular primary send button.\n *\n * Visual source: docs/design/brand-workbench/elicit-core (cbox selector)\n *\n * All values flow through CSS custom properties. No hard-coded colors or\n * magic numbers — every value traces to a design token or is documented.\n */\n\n/* ─── Root container ────────────────────────────────────────────────────── */\n\n.root {\n background: var(--surface-card, #ffffff);\n border: var(--stroke-width-thin, 1px) solid var(--border-default, #e5e7eb);\n border-radius: var(--radius-2xl, 1.5rem); /* ~24px, matches cbox prototype */\n box-shadow: var(--shadow-md, 0 4px 6px -1px rgb(0 0 0 / 0.1));\n padding: var(--spacing-3, 0.75rem) var(--spacing-4, 1rem); /* prototype 14/16/11px, snapped to 4px grid */\n display: flex;\n flex-direction: column;\n gap: 0;\n}\n\n.root[data-disabled] {\n opacity: var(--opacity-50, 0.5);\n pointer-events: none;\n}\n\n/* ─── Field row ─────────────────────────────────────────────────────────── */\n\n.fieldWrap {\n position: relative;\n /* The textarea and replica share the same box; replica drives the height */\n}\n\n/* Shared typographic baseline for both field and replica */\n.field {\n font-size: var(--font-size-base, 1rem); /* ~15px in prototype */\n line-height: var(--line-height-normal, 1.5);\n color: var(--text-primary, #111827);\n background: transparent;\n border: none;\n outline: none;\n resize: none;\n padding: 0;\n margin: 0;\n width: 100%;\n display: block;\n min-height: 22px; /* prototype: min-height 22px */\n overflow: hidden;\n}\n\n/* Hidden replica — same metrics as textarea, invisible, used for auto-grow */\n.fieldReplica {\n position: absolute;\n top: 0;\n left: 0;\n pointer-events: none;\n visibility: hidden;\n white-space: pre-wrap;\n word-break: break-word;\n overflow: hidden;\n}\n\n/* Textarea itself */\n.field:not(.fieldReplica) {\n position: relative;\n color: var(--text-primary, #111827);\n caret-color: var(--primary, #111827);\n}\n\n.field:not(.fieldReplica)::placeholder {\n color: var(--text-tertiary, #6b7280);\n}\n\n.field:not(.fieldReplica):focus-visible {\n outline: var(--focus-ring-width, 2px) solid var(--primary, #111827);\n outline-offset: var(--focus-ring-offset, 2px);\n border-radius: var(--radius-sm, 0.25rem);\n}\n\n/* ─── Toolbar row ───────────────────────────────────────────────────────── */\n\n.toolbar {\n display: flex;\n align-items: center;\n gap: var(--spacing-2, 0.5rem); /* prototype: 7px ≈ spacing-2 */\n margin-top: var(--spacing-3, 0.75rem); /* prototype 11px, snapped to 4px grid */\n}\n\n/* ─── Tool button ───────────────────────────────────────────────────────── */\n\n.toolBtn {\n width: 32px;\n height: 32px;\n border-radius: var(--radius-full, 9999px);\n border: var(--stroke-width-thin, 1px) solid var(--border-default, #e5e7eb);\n background: transparent;\n display: grid;\n place-items: center;\n color: var(--text-secondary, #374151);\n flex: none;\n cursor: pointer;\n transition:\n background-color var(--motion-duration-150, 150ms) var(--motion-easing-default, ease-in-out),\n border-color var(--motion-duration-150, 150ms) var(--motion-easing-default, ease-in-out),\n color var(--motion-duration-150, 150ms) var(--motion-easing-default, ease-in-out);\n}\n\n.toolBtn:hover:not(:disabled) {\n background: var(--surface-hover, color-mix(in srgb, var(--border-default, #e5e7eb) 40%, transparent));\n border-color: var(--border-strong, #9ca3af);\n}\n\n.toolBtn:focus-visible {\n outline: var(--focus-ring-width, 2px) solid var(--primary, #111827);\n outline-offset: var(--focus-ring-offset, 2px);\n}\n\n.toolBtn:disabled {\n opacity: var(--opacity-40, 0.4);\n cursor: not-allowed;\n}\n\n/* Icon inside tool button — 16px per prototype */\n.toolBtn > svg,\n.toolBtn > * > svg {\n width: 16px;\n height: 16px;\n}\n\n/* ─── Spacer ────────────────────────────────────────────────────────────── */\n\n.spacer {\n flex: 1;\n}\n\n/* ─── Send button ───────────────────────────────────────────────────────── */\n\n.send {\n width: 34px;\n height: 34px;\n border-radius: var(--radius-full, 9999px);\n background: var(--primary, #111827);\n color: var(--primary-foreground, #ffffff);\n display: grid;\n place-items: center;\n box-shadow: var(--shadow-sm, 0 1px 2px 0 rgb(0 0 0 / 0.05));\n flex: none;\n border: none;\n cursor: pointer;\n transition:\n background-color var(--motion-duration-150, 150ms) var(--motion-easing-default, ease-in-out),\n opacity var(--motion-duration-150, 150ms) var(--motion-easing-default, ease-in-out),\n box-shadow var(--motion-duration-150, 150ms) var(--motion-easing-default, ease-in-out);\n}\n\n.send:hover:not(:disabled) {\n background: color-mix(in srgb, var(--primary, #111827) 88%, white);\n box-shadow: var(--shadow-md, 0 4px 6px -1px rgb(0 0 0 / 0.1));\n}\n\n.send:focus-visible {\n outline: var(--focus-ring-width, 2px) solid var(--primary, #111827);\n outline-offset: var(--focus-ring-offset, 2px);\n}\n\n.send:disabled {\n opacity: var(--opacity-40, 0.4);\n cursor: not-allowed;\n}\n\n/* Icon inside send button — 17px per prototype */\n.send > svg,\n.send > * > svg {\n width: 17px;\n height: 17px;\n}\n\n/* ─── Reduced motion ────────────────────────────────────────────────────── */\n\n@media (prefers-reduced-motion: reduce) {\n .toolBtn,\n .send {\n transition: none;\n }\n}\n"
1328
1328
  }
1329
1329
  ]
1330
1330
  },
@@ -1800,7 +1800,7 @@
1800
1800
  {
1801
1801
  "path": "components/ui/search-input/search-input.module.css",
1802
1802
  "type": "registry:ui",
1803
- "content": "/* Search input wrapper\n *\n * The leading magnifier is provided by Input's leadingIcon prop; this\n * wrapper only exists to overlay the optional clear button on top of\n * the field when there's a value to clear. */\n.wrapper {\n position: relative;\n display: flex;\n align-items: center;\n width: 100%;\n}\n\n/* Reserve right padding on the input when the clear button is rendered\n * so the text doesn't slide under the button. */\n.inputWithClear {\n padding-right: var(--spacing-8, 2rem);\n}\n\n/* Hide browser-native search clear button — we ship our own */\n.wrapper input[type=\"search\"]::-webkit-search-cancel-button {\n display: none;\n}\n\n/* Clear button */\n.clearButton {\n position: absolute;\n right: var(--spacing-1, 0.25rem);\n display: flex;\n align-items: center;\n justify-content: center;\n width: 1.75rem;\n height: 1.75rem;\n padding: 0;\n border: none;\n border-radius: var(--radius-sm, 0.25rem);\n background: transparent;\n color: var(--text-secondary, #9ca3af);\n cursor: pointer;\n transition: color var(--motion-duration-150, 150ms) var(--motion-easing-default, ease-in-out);\n}\n\n@media (hover: hover) {\n .clearButton:hover {\n color: var(--text-primary, #111827);\n }\n}\n\n.clearButton:focus-visible {\n outline: var(--focus-ring-width, 2px) solid var(--border-focus, #111827);\n outline-offset: var(--focus-ring-offset, -2px);\n}\n\n.clearButton svg {\n width: 0.875rem;\n height: 0.875rem;\n}\n\n/* VI-510: form controls do not inherit font-family from the page; opt back in (matches textarea). */\n.wrapper :is(input, button, textarea) {\n font-family: inherit;\n}\n"
1803
+ "content": "/* Search input wrapper\n *\n * The leading magnifier is provided by Input's leadingIcon prop; this\n * wrapper only exists to overlay the optional clear button on top of\n * the field when there's a value to clear. */\n.wrapper {\n position: relative;\n display: flex;\n align-items: center;\n width: 100%;\n}\n\n/* Reserve right padding on the input when the clear button is rendered\n * so the text doesn't slide under the button. */\n.inputWithClear {\n padding-right: var(--spacing-8, 2rem);\n}\n\n/* Hide browser-native search clear button — we ship our own */\n.wrapper input[type=\"search\"]::-webkit-search-cancel-button {\n display: none;\n}\n\n/* Clear button */\n.clearButton {\n position: absolute;\n right: var(--spacing-1, 0.25rem);\n display: flex;\n align-items: center;\n justify-content: center;\n width: 1.75rem;\n height: 1.75rem;\n padding: 0;\n border: none;\n border-radius: var(--radius-sm, 0.25rem);\n background: transparent;\n color: var(--text-secondary, #9ca3af);\n cursor: pointer;\n transition: color var(--motion-duration-150, 150ms) var(--motion-easing-default, ease-in-out);\n}\n\n@media (hover: hover) {\n .clearButton:hover {\n color: var(--text-primary, #111827);\n }\n}\n\n.clearButton:focus-visible {\n outline: var(--focus-ring-width, 2px) solid var(--border-focus, #111827);\n outline-offset: var(--focus-ring-offset, -2px);\n}\n\n.clearButton svg {\n width: 0.875rem;\n height: 0.875rem;\n}\n"
1804
1804
  }
1805
1805
  ]
1806
1806
  },
@@ -1826,7 +1826,7 @@
1826
1826
  {
1827
1827
  "path": "components/ui/password-input/password-input.module.css",
1828
1828
  "type": "registry:ui",
1829
- "content": "/* Password input wrapper */\n.wrapper {\n width: 100%;\n}\n\n.inputWrapper {\n position: relative;\n display: flex;\n align-items: center;\n}\n\n/* Input override — pad right for toggle button */\n.input {\n padding-right: var(--spacing-10, 2.5rem);\n}\n\n/* Toggle visibility button */\n.toggleButton {\n position: absolute;\n right: var(--spacing-1, 0.25rem);\n display: flex;\n align-items: center;\n justify-content: center;\n width: 1.75rem;\n height: 1.75rem;\n padding: 0;\n border: none;\n border-radius: var(--radius-sm, 0.25rem);\n background: transparent;\n color: var(--text-secondary, #9ca3af);\n cursor: pointer;\n transition: color var(--motion-duration-150, 150ms) var(--motion-easing-default, ease-in-out);\n}\n\n@media (hover: hover) {\n .toggleButton:hover {\n color: var(--text-primary, #111827);\n }\n}\n\n.toggleButton:focus-visible {\n outline: var(--focus-ring-width, 2px) solid var(--border-focus, #111827);\n outline-offset: var(--focus-ring-offset, -2px);\n}\n\n.toggleButton svg {\n width: 1rem;\n height: 1rem;\n}\n\n/* Strength meter */\n.strengthMeter {\n display: flex;\n align-items: center;\n gap: var(--spacing-2, 0.5rem);\n margin-top: var(--spacing-1, 0.25rem);\n}\n\n.strengthTrack {\n display: flex;\n flex: 1;\n gap: var(--spacing-1, 0.25rem);\n}\n\n.strengthSegment {\n height: 0.25rem;\n flex: 1;\n border-radius: var(--radius-full, 9999px);\n background-color: var(--border-default, #e5e7eb);\n transition: background-color var(--motion-duration-150, 150ms) var(--motion-easing-default, ease-in-out);\n}\n\n.strengthWeak {\n background-color: var(--border-error, #ef4444);\n}\n\n.strengthFair {\n background-color: var(--surface-warning-default, #f59e0b);\n}\n\n.strengthGood {\n background-color: var(--surface-success-default, #10b981);\n}\n\n.strengthStrong {\n background-color: var(--surface-success-default, #10b981);\n}\n\n.strengthLabel {\n font-size: var(--font-size-xs, 0.75rem);\n color: var(--text-secondary, #9ca3af);\n min-width: 3rem;\n}\n\n/* VI-510: form controls do not inherit font-family from the page; opt back in (matches textarea). */\n.wrapper :is(input, button, textarea) {\n font-family: inherit;\n}\n"
1829
+ "content": "/* Password input wrapper */\n.wrapper {\n width: 100%;\n}\n\n.inputWrapper {\n position: relative;\n display: flex;\n align-items: center;\n}\n\n/* Input override — pad right for toggle button */\n.input {\n padding-right: var(--spacing-10, 2.5rem);\n}\n\n/* Toggle visibility button */\n.toggleButton {\n position: absolute;\n right: var(--spacing-1, 0.25rem);\n display: flex;\n align-items: center;\n justify-content: center;\n width: 1.75rem;\n height: 1.75rem;\n padding: 0;\n border: none;\n border-radius: var(--radius-sm, 0.25rem);\n background: transparent;\n color: var(--text-secondary, #9ca3af);\n cursor: pointer;\n transition: color var(--motion-duration-150, 150ms) var(--motion-easing-default, ease-in-out);\n}\n\n@media (hover: hover) {\n .toggleButton:hover {\n color: var(--text-primary, #111827);\n }\n}\n\n.toggleButton:focus-visible {\n outline: var(--focus-ring-width, 2px) solid var(--border-focus, #111827);\n outline-offset: var(--focus-ring-offset, -2px);\n}\n\n.toggleButton svg {\n width: 1rem;\n height: 1rem;\n}\n\n/* Strength meter */\n.strengthMeter {\n display: flex;\n align-items: center;\n gap: var(--spacing-2, 0.5rem);\n margin-top: var(--spacing-1, 0.25rem);\n}\n\n.strengthTrack {\n display: flex;\n flex: 1;\n gap: var(--spacing-1, 0.25rem);\n}\n\n.strengthSegment {\n height: 0.25rem;\n flex: 1;\n border-radius: var(--radius-full, 9999px);\n background-color: var(--border-default, #e5e7eb);\n transition: background-color var(--motion-duration-150, 150ms) var(--motion-easing-default, ease-in-out);\n}\n\n.strengthWeak {\n background-color: var(--border-error, #ef4444);\n}\n\n.strengthFair {\n background-color: var(--surface-warning-default, #f59e0b);\n}\n\n.strengthGood {\n background-color: var(--surface-success-default, #10b981);\n}\n\n.strengthStrong {\n background-color: var(--surface-success-default, #10b981);\n}\n\n.strengthLabel {\n font-size: var(--font-size-xs, 0.75rem);\n color: var(--text-secondary, #9ca3af);\n min-width: 3rem;\n}\n"
1830
1830
  }
1831
1831
  ]
1832
1832
  },
@@ -1923,7 +1923,7 @@
1923
1923
  {
1924
1924
  "path": "components/ui/number-input/number-input.module.css",
1925
1925
  "type": "registry:ui",
1926
- "content": "/* Number input wrapper */\n.wrapper {\n display: inline-flex;\n align-items: center;\n border: 1px solid var(--number-input-border, var(--border-default, #e5e7eb));\n border-radius: var(--radius-md, 0.375rem);\n background-color: var(--number-input-bg, var(--surface-interactive-default, #f9fafb));\n overflow: hidden;\n transition: border-color var(--motion-duration-150, 150ms) var(--motion-easing-default, ease-in-out),\n box-shadow var(--motion-duration-150, 150ms) var(--motion-easing-default, ease-in-out);\n}\n\n@media (hover: hover) {\n .button:hover {\n color: var(--text-primary, #111827);\n background-color: var(--surface-muted, #f3f4f6);\n }\n}\n\n.wrapper:focus-within {\n border-color: var(--border-focus, #111827);\n box-shadow: 0 0 0 var(--focus-ring-width, 2px) color-mix(in srgb, var(--border-focus, #111827) 15%, transparent);\n}\n\n.wrapperDisabled {\n opacity: 0.5;\n pointer-events: none;\n}\n\n/* Stepper buttons */\n.button {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 2.25rem;\n height: 2.25rem;\n padding: 0;\n border: none;\n background: transparent;\n color: var(--text-secondary, #9ca3af);\n cursor: pointer;\n flex-shrink: 0;\n transition: color var(--motion-duration-150, 150ms) var(--motion-easing-default, ease-in-out),\n background-color var(--motion-duration-150, 150ms) var(--motion-easing-default, ease-in-out);\n}\n\n.button:active {\n background-color: var(--surface-interactive-hover, #e5e7eb);\n transition: none;\n}\n\n.button:focus-visible {\n outline: var(--focus-ring-width, 2px) solid var(--border-focus, currentColor);\n outline-offset: var(--focus-ring-offset, -2px);\n}\n\n.button:disabled {\n cursor: not-allowed;\n opacity: 0.5;\n}\n\n.buttonIcon {\n width: 0.875rem;\n height: 0.875rem;\n}\n\n/* Input */\n.input {\n width: 4rem;\n height: 2.25rem;\n padding: 0;\n border: none;\n background: transparent;\n text-align: center;\n font-size: var(--font-size-sm, 0.875rem);\n color: var(--text-primary, #111827);\n outline: none;\n}\n\n.input::placeholder {\n color: var(--text-secondary, #9ca3af);\n}\n\n/* VI-510: form controls do not inherit font-family from the page; opt back in (matches textarea). */\n.wrapper :is(input, button, textarea) {\n font-family: inherit;\n}\n"
1926
+ "content": "/* Number input wrapper */\n.wrapper {\n display: inline-flex;\n align-items: center;\n border: 1px solid var(--number-input-border, var(--border-default, #e5e7eb));\n border-radius: var(--radius-md, 0.375rem);\n background-color: var(--number-input-bg, var(--surface-interactive-default, #f9fafb));\n overflow: hidden;\n transition: border-color var(--motion-duration-150, 150ms) var(--motion-easing-default, ease-in-out),\n box-shadow var(--motion-duration-150, 150ms) var(--motion-easing-default, ease-in-out);\n}\n\n@media (hover: hover) {\n .button:hover {\n color: var(--text-primary, #111827);\n background-color: var(--surface-muted, #f3f4f6);\n }\n}\n\n.wrapper:focus-within {\n border-color: var(--border-focus, #111827);\n box-shadow: 0 0 0 var(--focus-ring-width, 2px) color-mix(in srgb, var(--border-focus, #111827) 15%, transparent);\n}\n\n.wrapperDisabled {\n opacity: 0.5;\n pointer-events: none;\n}\n\n/* Stepper buttons */\n.button {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 2.25rem;\n height: 2.25rem;\n padding: 0;\n border: none;\n background: transparent;\n color: var(--text-secondary, #9ca3af);\n cursor: pointer;\n flex-shrink: 0;\n transition: color var(--motion-duration-150, 150ms) var(--motion-easing-default, ease-in-out),\n background-color var(--motion-duration-150, 150ms) var(--motion-easing-default, ease-in-out);\n}\n\n.button:active {\n background-color: var(--surface-interactive-hover, #e5e7eb);\n transition: none;\n}\n\n.button:focus-visible {\n outline: var(--focus-ring-width, 2px) solid var(--border-focus, currentColor);\n outline-offset: var(--focus-ring-offset, -2px);\n}\n\n.button:disabled {\n cursor: not-allowed;\n opacity: 0.5;\n}\n\n.buttonIcon {\n width: 0.875rem;\n height: 0.875rem;\n}\n\n/* Input */\n.input {\n width: 4rem;\n height: 2.25rem;\n padding: 0;\n border: none;\n background: transparent;\n text-align: center;\n font-size: var(--font-size-sm, 0.875rem);\n color: var(--text-primary, #111827);\n outline: none;\n}\n\n.input::placeholder {\n color: var(--text-secondary, #9ca3af);\n}\n"
1927
1927
  }
1928
1928
  ]
1929
1929
  },
@@ -1977,7 +1977,7 @@
1977
1977
  {
1978
1978
  "path": "components/ui/otp-input/otp-input.module.css",
1979
1979
  "type": "registry:ui",
1980
- "content": "/* OTP input wrapper */\n.wrapper {\n display: inline-flex;\n gap: var(--spacing-2, 0.5rem);\n}\n\n/* Individual digit cell */\n.cell {\n width: 2.5rem;\n height: 2.75rem;\n border: 1px solid var(--otp-border, var(--border-default, #e5e7eb));\n border-radius: var(--radius-md, 0.375rem);\n background-color: var(--otp-bg, var(--surface-interactive-default, #f9fafb));\n text-align: center;\n font-size: var(--font-size-lg, 1.125rem);\n font-weight: var(--font-weight-medium, 500);\n color: var(--text-primary, #111827);\n outline: none;\n transition: border-color var(--motion-duration-150, 150ms) var(--motion-easing-default, ease-in-out),\n box-shadow var(--motion-duration-150, 150ms) var(--motion-easing-default, ease-in-out);\n}\n\n.cell::placeholder {\n color: var(--text-secondary, #9ca3af);\n}\n\n@media (hover: hover) {\n .cell:hover:not(:focus-visible):not(:disabled) {\n border-color: var(--border-strong, #d1d5db);\n }\n}\n\n.cell:focus-visible {\n border-color: var(--border-focus, #111827);\n box-shadow: 0 0 0 var(--focus-ring-width, 2px) color-mix(in srgb, var(--border-focus, #111827) 15%, transparent);\n}\n\n.cell:disabled {\n pointer-events: none;\n cursor: not-allowed;\n opacity: 0.5;\n}\n\n.cellFilled {\n border-color: var(--border-focus, #111827);\n}\n\n/* VI-510: form controls do not inherit font-family from the page; opt back in (matches textarea). */\n.wrapper :is(input, button, textarea) {\n font-family: inherit;\n}\n"
1980
+ "content": "/* OTP input wrapper */\n.wrapper {\n display: inline-flex;\n gap: var(--spacing-2, 0.5rem);\n}\n\n/* Individual digit cell */\n.cell {\n width: 2.5rem;\n height: 2.75rem;\n border: 1px solid var(--otp-border, var(--border-default, #e5e7eb));\n border-radius: var(--radius-md, 0.375rem);\n background-color: var(--otp-bg, var(--surface-interactive-default, #f9fafb));\n text-align: center;\n font-size: var(--font-size-lg, 1.125rem);\n font-weight: var(--font-weight-medium, 500);\n color: var(--text-primary, #111827);\n outline: none;\n transition: border-color var(--motion-duration-150, 150ms) var(--motion-easing-default, ease-in-out),\n box-shadow var(--motion-duration-150, 150ms) var(--motion-easing-default, ease-in-out);\n}\n\n.cell::placeholder {\n color: var(--text-secondary, #9ca3af);\n}\n\n@media (hover: hover) {\n .cell:hover:not(:focus-visible):not(:disabled) {\n border-color: var(--border-strong, #d1d5db);\n }\n}\n\n.cell:focus-visible {\n border-color: var(--border-focus, #111827);\n box-shadow: 0 0 0 var(--focus-ring-width, 2px) color-mix(in srgb, var(--border-focus, #111827) 15%, transparent);\n}\n\n.cell:disabled {\n pointer-events: none;\n cursor: not-allowed;\n opacity: 0.5;\n}\n\n.cellFilled {\n border-color: var(--border-focus, #111827);\n}\n"
1981
1981
  }
1982
1982
  ]
1983
1983
  },
@@ -2002,7 +2002,7 @@
2002
2002
  {
2003
2003
  "path": "components/ui/tag-input/tag-input.module.css",
2004
2004
  "type": "registry:ui",
2005
- "content": "/* Tag input wrapper — styled like an Input */\n.wrapper {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--spacing-1, 0.25rem);\n min-height: 2.25rem;\n width: 100%;\n border-radius: var(--radius-md, 0.375rem);\n border: 1px solid var(--tag-input-border, var(--border-default, #e5e7eb));\n background-color: var(--tag-input-bg, var(--surface-interactive-default, #f9fafb));\n padding: var(--spacing-1, 0.25rem) var(--spacing-2, 0.5rem);\n cursor: text;\n transition: border-color var(--motion-duration-150, 150ms) var(--motion-easing-default, ease-in-out),\n box-shadow var(--motion-duration-150, 150ms) var(--motion-easing-default, ease-in-out);\n}\n\n@media (hover: hover) {\n .wrapper:hover:not(.wrapperFocused):not(.wrapperDisabled) {\n border-color: var(--border-strong, #d1d5db);\n }\n}\n\n.wrapperFocused {\n border-color: var(--border-focus, #111827);\n box-shadow: 0 0 0 var(--focus-ring-width, 2px) color-mix(in srgb, var(--border-focus, #111827) 15%, transparent);\n}\n\n.wrapperDisabled {\n pointer-events: none;\n cursor: not-allowed;\n opacity: 0.5;\n}\n\n/* Individual tag chip */\n.tag {\n display: inline-flex;\n align-items: center;\n gap: var(--spacing-1, 0.25rem);\n padding: calc(var(--spacing-1, 0.25rem) / 4) var(--spacing-2, 0.5rem);\n border-radius: var(--radius-full, 9999px);\n background-color: var(--surface-muted, #f3f4f6);\n border: 1px solid var(--border-default, #e5e7eb);\n font-size: var(--font-size-xs, 0.75rem);\n line-height: 1.5;\n color: var(--text-primary, #111827);\n}\n\n.tagLabel {\n white-space: nowrap;\n}\n\n.tagRemove {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 0.875rem;\n height: 0.875rem;\n padding: 0;\n border: none;\n background: transparent;\n color: var(--text-secondary, #9ca3af);\n cursor: pointer;\n border-radius: var(--radius-full, 9999px);\n transition: color var(--motion-duration-150, 150ms) var(--motion-easing-default, ease-in-out);\n}\n\n@media (hover: hover) {\n .tagRemove:hover {\n color: var(--text-primary, #111827);\n }\n}\n\n.tagRemove svg {\n width: 0.625rem;\n height: 0.625rem;\n}\n\n/* Inline text input */\n.input {\n flex: 1;\n min-width: 4rem;\n height: 1.5rem;\n padding: 0;\n border: none;\n background: transparent;\n font-size: var(--font-size-sm, 0.875rem);\n color: var(--text-primary, #111827);\n outline: none;\n}\n\n.input::placeholder {\n color: var(--text-secondary, #9ca3af);\n}\n\n/* VI-510: form controls do not inherit font-family from the page; opt back in (matches textarea). */\n.wrapper :is(input, button, textarea) {\n font-family: inherit;\n}\n"
2005
+ "content": "/* Tag input wrapper — styled like an Input */\n.wrapper {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--spacing-1, 0.25rem);\n min-height: 2.25rem;\n width: 100%;\n border-radius: var(--radius-md, 0.375rem);\n border: 1px solid var(--tag-input-border, var(--border-default, #e5e7eb));\n background-color: var(--tag-input-bg, var(--surface-interactive-default, #f9fafb));\n padding: var(--spacing-1, 0.25rem) var(--spacing-2, 0.5rem);\n cursor: text;\n transition: border-color var(--motion-duration-150, 150ms) var(--motion-easing-default, ease-in-out),\n box-shadow var(--motion-duration-150, 150ms) var(--motion-easing-default, ease-in-out);\n}\n\n@media (hover: hover) {\n .wrapper:hover:not(.wrapperFocused):not(.wrapperDisabled) {\n border-color: var(--border-strong, #d1d5db);\n }\n}\n\n.wrapperFocused {\n border-color: var(--border-focus, #111827);\n box-shadow: 0 0 0 var(--focus-ring-width, 2px) color-mix(in srgb, var(--border-focus, #111827) 15%, transparent);\n}\n\n.wrapperDisabled {\n pointer-events: none;\n cursor: not-allowed;\n opacity: 0.5;\n}\n\n/* Individual tag chip */\n.tag {\n display: inline-flex;\n align-items: center;\n gap: var(--spacing-1, 0.25rem);\n padding: calc(var(--spacing-1, 0.25rem) / 4) var(--spacing-2, 0.5rem);\n border-radius: var(--radius-full, 9999px);\n background-color: var(--surface-muted, #f3f4f6);\n border: 1px solid var(--border-default, #e5e7eb);\n font-size: var(--font-size-xs, 0.75rem);\n line-height: 1.5;\n color: var(--text-primary, #111827);\n}\n\n.tagLabel {\n white-space: nowrap;\n}\n\n.tagRemove {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 0.875rem;\n height: 0.875rem;\n padding: 0;\n border: none;\n background: transparent;\n color: var(--text-secondary, #9ca3af);\n cursor: pointer;\n border-radius: var(--radius-full, 9999px);\n transition: color var(--motion-duration-150, 150ms) var(--motion-easing-default, ease-in-out);\n}\n\n@media (hover: hover) {\n .tagRemove:hover {\n color: var(--text-primary, #111827);\n }\n}\n\n.tagRemove svg {\n width: 0.625rem;\n height: 0.625rem;\n}\n\n/* Inline text input */\n.input {\n flex: 1;\n min-width: 4rem;\n height: 1.5rem;\n padding: 0;\n border: none;\n background: transparent;\n font-size: var(--font-size-sm, 0.875rem);\n color: var(--text-primary, #111827);\n outline: none;\n}\n\n.input::placeholder {\n color: var(--text-secondary, #9ca3af);\n}\n"
2006
2006
  }
2007
2007
  ]
2008
2008
  },
@@ -2103,7 +2103,7 @@
2103
2103
  {
2104
2104
  "path": "components/ui/editable-block/editable-block.module.css",
2105
2105
  "type": "registry:ui",
2106
- "content": "/* EditableBlock\n *\n * Canvas brand block — a card tile with an uppercase label header (+ done\n * check), a value body, a hover-revealed edit icon, and an editing state\n * (focus ring, inline input + save button, AI action slot).\n *\n * Visual source: docs/design/brand-workbench/journey (HTML) L274-285\n * (prototype selectors: block, bk, bv, ed, editrow, aibtn)\n *\n * All values flow through CSS custom properties. No hard-coded colors or\n * magic numbers — every value traces to a design token or is documented.\n */\n\n/* ─── Root tile ─────────────────────────────────────────────────────────── */\n\n.root {\n background: var(--surface-card, #ffffff);\n border: var(--stroke-width-thin, 1px) solid var(--hairline, rgba(0,0,0,0.06));\n border-radius: var(--radius-lg, 0.75rem);\n padding: var(--spacing-3_5, 0.875rem); /* prototype: 14px */\n box-shadow: var(--shadow-sm, 0 1px 2px 0 rgb(0 0 0 / 0.05));\n min-height: 6rem; /* prototype: 96px */\n position: relative;\n cursor: pointer;\n display: flex;\n flex-direction: column;\n transition:\n border-color var(--motion-duration-150, 150ms) var(--motion-easing-default, ease-in-out),\n box-shadow var(--motion-duration-150, 150ms) var(--motion-easing-default, ease-in-out);\n}\n\n/* ─── State: default (hover) ────────────────────────────────────────────── */\n\n.stateDefault:hover {\n border-color: var(--border-default, #e5e7eb);\n}\n\n/* Reveal edit icon on hover — use CSS opacity so resting state is still\n in the DOM (avoids SSR/hydration race on mount). */\n.stateDefault:hover .editIcon {\n opacity: var(--opacity-80, 0.8);\n}\n\n/* ─── State: done ───────────────────────────────────────────────────────── */\n\n.stateDone:hover {\n border-color: var(--border-default, #e5e7eb);\n}\n\n.stateDone:hover .editIcon {\n opacity: var(--opacity-80, 0.8);\n}\n\n/* ─── State: editing ────────────────────────────────────────────────────── */\n\n.stateEditing {\n /* Focus-ring shadow — exception per token-rules Rule 2 (focus ring variant) */\n border-color: var(--primary, #111827);\n box-shadow: 0 0 0 var(--spacing-1, 0.25rem) var(--interactive-primary-soft, color-mix(in srgb, var(--interactive-primary-bg, #111827) 12%, transparent));\n cursor: default;\n}\n\n.stateEditing .label {\n color: var(--primary, #111827);\n}\n\n/* ─── Header row ────────────────────────────────────────────────────────── */\n\n.header {\n display: flex;\n align-items: center;\n gap: var(--spacing-1_5, 0.375rem); /* prototype: 7px ≈ 1.5 × 4px */\n margin-bottom: var(--spacing-2, 0.5rem); /* prototype: 8px */\n}\n\n/* ─── Label ─────────────────────────────────────────────────────────────── */\n\n.label {\n font-size: var(--font-size-2xs, 0.65625rem); /* prototype: 10.5px */\n font-weight: 800;\n letter-spacing: 0.07em;\n text-transform: uppercase;\n color: var(--text-tertiary, #6b7280);\n transition: color var(--motion-duration-150, 150ms) var(--motion-easing-default, ease-in-out);\n}\n\n/* ─── Done check icon ───────────────────────────────────────────────────── */\n\n.doneCheck {\n display: inline-flex;\n align-items: center;\n color: var(--success, #22c55e);\n}\n\n.doneCheck > svg {\n width: var(--spacing-3, 0.75rem); /* prototype: 12px */\n height: var(--spacing-3, 0.75rem);\n stroke-width: 3;\n}\n\n/* ─── Value body ────────────────────────────────────────────────────────── */\n\n.value {\n font-size: var(--font-size-sm, 0.84375rem); /* prototype: 13.5px ≈ sm */\n color: var(--text-primary, #111827);\n line-height: var(--line-height-snug, 1.45);\n flex: 1;\n}\n\n/* ─── Hover-revealed edit icon ──────────────────────────────────────────── */\n\n.editIcon {\n position: absolute;\n top: var(--spacing-2_5, 0.6875rem); /* prototype: 11px */\n right: var(--spacing-2_5, 0.6875rem);\n display: inline-flex;\n align-items: center;\n justify-content: center;\n color: var(--text-tertiary, #6b7280);\n /* Resting state opacity=0 via CSS (visible on hover via .stateDefault:hover rule).\n Must remain in DOM at rest for accessibility & SSR hydration safety. */\n opacity: 0;\n background: none;\n border: none;\n padding: 0;\n cursor: pointer;\n transition: opacity var(--motion-duration-150, 150ms) var(--motion-easing-default, ease-in-out);\n}\n\n.editIcon:focus-visible {\n opacity: var(--opacity-80, 0.8);\n outline: var(--focus-ring-width, 2px) solid var(--primary, #111827);\n outline-offset: var(--focus-ring-offset, 2px);\n border-radius: var(--radius-sm, 0.25rem);\n}\n\n.editIcon > svg {\n width: var(--spacing-3_5, 0.875rem); /* prototype: 14px */\n height: var(--spacing-3_5, 0.875rem);\n}\n\n/* ─── Edit row (input + save button) ────────────────────────────────────── */\n\n.editRow {\n display: flex;\n gap: var(--spacing-1_5, 0.375rem); /* prototype: 7px */\n margin-top: var(--spacing-2_5, 0.625rem); /* prototype: 10px */\n}\n\n/* Inline edit input */\n.editInput {\n flex: 1;\n height: var(--spacing-8, 2rem); /* prototype: 32px */\n border-radius: var(--radius-md, 0.5rem);\n background: var(--surface-subtle, #f9fafb);\n border: var(--stroke-width-thin, 1px) solid\n color-mix(in srgb, var(--primary, #111827) 30%, transparent);\n font-family: inherit;\n font-size: var(--font-size-sm, 0.84375rem); /* prototype: 13px */\n font-weight: 600;\n color: var(--text-primary, #111827);\n padding: 0 var(--spacing-2_5, 0.625rem); /* prototype: 0 10px */\n outline: none;\n}\n\n.editInput:focus-visible {\n outline: var(--focus-ring-width, 2px) solid var(--primary, #111827);\n outline-offset: var(--focus-ring-offset, 2px);\n}\n\n/* Save button (checkmark) */\n.saveButton {\n width: var(--spacing-8, 2rem); /* prototype: 32px */\n height: var(--spacing-8, 2rem);\n border-radius: var(--radius-md, 0.5rem);\n background: var(--primary, #111827);\n color: var(--primary-text, #ffffff);\n display: grid;\n place-items: center;\n flex: none;\n border: none;\n cursor: pointer;\n transition:\n background-color var(--motion-duration-150, 150ms) var(--motion-easing-default, ease-in-out),\n opacity var(--motion-duration-150, 150ms) var(--motion-easing-default, ease-in-out);\n}\n\n.saveButton:hover {\n background: color-mix(in srgb, var(--primary, #111827) 88%, white);\n}\n\n.saveButton:focus-visible {\n outline: var(--focus-ring-width, 2px) solid var(--primary, #111827);\n outline-offset: var(--focus-ring-offset, 2px);\n}\n\n.saveButton > svg {\n width: var(--spacing-3_5, 0.9375rem); /* prototype: 15px */\n height: var(--spacing-3_5, 0.9375rem);\n stroke-width: 2.4;\n}\n\n/* ─── AI action button ───────────────────────────────────────────────────── */\n\n.aiAction {\n display: inline-flex;\n align-items: center;\n gap: var(--spacing-1_5, 0.375rem); /* prototype: 6px */\n margin-top: var(--spacing-2, 0.5rem); /* prototype: 9px ≈ spacing-2 */\n font-family: inherit;\n font-size: var(--font-size-xs, 0.71875rem); /* prototype: 11.5px */\n font-weight: 700;\n color: var(--primary, #111827);\n background: none;\n border: none;\n cursor: pointer;\n padding: 0;\n transition: opacity var(--motion-duration-150, 150ms) var(--motion-easing-default, ease-in-out);\n}\n\n.aiAction:hover {\n opacity: var(--opacity-80, 0.8);\n}\n\n.aiAction:focus-visible {\n outline: var(--focus-ring-width, 2px) solid var(--primary, #111827);\n outline-offset: var(--focus-ring-offset, 2px);\n border-radius: var(--radius-sm, 0.25rem);\n}\n\n.aiAction > svg {\n width: var(--spacing-3, 0.8125rem); /* prototype: 13px */\n height: var(--spacing-3, 0.8125rem);\n}\n\n/* ─── Reduced motion ─────────────────────────────────────────────────────── */\n\n@media (prefers-reduced-motion: reduce) {\n .root,\n .label,\n .editIcon,\n .saveButton,\n .aiAction {\n transition: none;\n }\n}\n"
2106
+ "content": "/* EditableBlock\n *\n * Canvas brand block — a card tile with an uppercase label header (+ done\n * check), a value body, a hover-revealed edit icon, and an editing state\n * (focus ring, inline input + save button, AI action slot).\n *\n * Visual source: docs/design/brand-workbench/journey (HTML) L274-285\n * (prototype selectors: block, bk, bv, ed, editrow, aibtn)\n *\n * All values flow through CSS custom properties. No hard-coded colors or\n * magic numbers — every value traces to a design token or is documented.\n */\n\n/* ─── Root tile ─────────────────────────────────────────────────────────── */\n\n.root {\n background: var(--surface-card, #ffffff);\n border: var(--stroke-width-thin, 1px) solid var(--hairline, rgba(0,0,0,0.06));\n border-radius: var(--radius-lg, 0.75rem);\n padding: var(--spacing-3_5, 0.875rem); /* prototype: 14px */\n box-shadow: var(--shadow-sm, 0 1px 2px 0 rgb(0 0 0 / 0.05));\n min-height: 6rem; /* prototype: 96px */\n position: relative;\n cursor: pointer;\n display: flex;\n flex-direction: column;\n transition:\n border-color var(--motion-duration-150, 150ms) var(--motion-easing-default, ease-in-out),\n box-shadow var(--motion-duration-150, 150ms) var(--motion-easing-default, ease-in-out);\n}\n\n/* ─── State: default (hover) ────────────────────────────────────────────── */\n\n.stateDefault:hover {\n border-color: var(--border-default, #e5e7eb);\n}\n\n/* Reveal edit icon on hover — use CSS opacity so resting state is still\n in the DOM (avoids SSR/hydration race on mount). */\n.stateDefault:hover .editIcon {\n opacity: var(--opacity-80, 0.8);\n}\n\n/* ─── State: done ───────────────────────────────────────────────────────── */\n\n.stateDone:hover {\n border-color: var(--border-default, #e5e7eb);\n}\n\n.stateDone:hover .editIcon {\n opacity: var(--opacity-80, 0.8);\n}\n\n/* ─── State: editing ────────────────────────────────────────────────────── */\n\n.stateEditing {\n /* Focus-ring shadow — exception per token-rules Rule 2 (focus ring variant) */\n border-color: var(--primary, #111827);\n box-shadow: 0 0 0 var(--spacing-1, 0.25rem) var(--interactive-primary-soft, color-mix(in srgb, var(--interactive-primary-bg, #111827) 12%, transparent));\n cursor: default;\n}\n\n.stateEditing .label {\n color: var(--primary, #111827);\n}\n\n/* ─── Header row ────────────────────────────────────────────────────────── */\n\n.header {\n display: flex;\n align-items: center;\n gap: var(--spacing-1_5, 0.375rem); /* prototype: 7px ≈ 1.5 × 4px */\n margin-bottom: var(--spacing-2, 0.5rem); /* prototype: 8px */\n}\n\n/* ─── Label ─────────────────────────────────────────────────────────────── */\n\n.label {\n font-size: var(--font-size-2xs, 0.65625rem); /* prototype: 10.5px */\n font-weight: 800;\n letter-spacing: 0.07em;\n text-transform: uppercase;\n color: var(--text-tertiary, #6b7280);\n transition: color var(--motion-duration-150, 150ms) var(--motion-easing-default, ease-in-out);\n}\n\n/* ─── Done check icon ───────────────────────────────────────────────────── */\n\n.doneCheck {\n display: inline-flex;\n align-items: center;\n color: var(--success, #22c55e);\n}\n\n.doneCheck > svg {\n width: var(--spacing-3, 0.75rem); /* prototype: 12px */\n height: var(--spacing-3, 0.75rem);\n stroke-width: 3;\n}\n\n/* ─── Value body ────────────────────────────────────────────────────────── */\n\n.value {\n font-size: var(--font-size-sm, 0.84375rem); /* prototype: 13.5px ≈ sm */\n color: var(--text-primary, #111827);\n line-height: var(--line-height-snug, 1.45);\n flex: 1;\n}\n\n/* ─── Hover-revealed edit icon ──────────────────────────────────────────── */\n\n.editIcon {\n position: absolute;\n top: var(--spacing-2_5, 0.6875rem); /* prototype: 11px */\n right: var(--spacing-2_5, 0.6875rem);\n display: inline-flex;\n align-items: center;\n justify-content: center;\n color: var(--text-tertiary, #6b7280);\n /* Resting state opacity=0 via CSS (visible on hover via .stateDefault:hover rule).\n Must remain in DOM at rest for accessibility & SSR hydration safety. */\n opacity: 0;\n background: none;\n border: none;\n padding: 0;\n cursor: pointer;\n transition: opacity var(--motion-duration-150, 150ms) var(--motion-easing-default, ease-in-out);\n}\n\n.editIcon:focus-visible {\n opacity: var(--opacity-80, 0.8);\n outline: var(--focus-ring-width, 2px) solid var(--primary, #111827);\n outline-offset: var(--focus-ring-offset, 2px);\n border-radius: var(--radius-sm, 0.25rem);\n}\n\n.editIcon > svg {\n width: var(--spacing-3_5, 0.875rem); /* prototype: 14px */\n height: var(--spacing-3_5, 0.875rem);\n}\n\n/* ─── Edit row (input + save button) ────────────────────────────────────── */\n\n.editRow {\n display: flex;\n gap: var(--spacing-1_5, 0.375rem); /* prototype: 7px */\n margin-top: var(--spacing-2_5, 0.625rem); /* prototype: 10px */\n}\n\n/* Inline edit input */\n.editInput {\n flex: 1;\n height: var(--spacing-8, 2rem); /* prototype: 32px */\n border-radius: var(--radius-md, 0.5rem);\n background: var(--surface-subtle, #f9fafb);\n border: var(--stroke-width-thin, 1px) solid\n color-mix(in srgb, var(--primary, #111827) 30%, transparent);\n font-size: var(--font-size-sm, 0.84375rem); /* prototype: 13px */\n font-weight: 600;\n color: var(--text-primary, #111827);\n padding: 0 var(--spacing-2_5, 0.625rem); /* prototype: 0 10px */\n outline: none;\n}\n\n.editInput:focus-visible {\n outline: var(--focus-ring-width, 2px) solid var(--primary, #111827);\n outline-offset: var(--focus-ring-offset, 2px);\n}\n\n/* Save button (checkmark) */\n.saveButton {\n width: var(--spacing-8, 2rem); /* prototype: 32px */\n height: var(--spacing-8, 2rem);\n border-radius: var(--radius-md, 0.5rem);\n background: var(--primary, #111827);\n color: var(--primary-text, #ffffff);\n display: grid;\n place-items: center;\n flex: none;\n border: none;\n cursor: pointer;\n transition:\n background-color var(--motion-duration-150, 150ms) var(--motion-easing-default, ease-in-out),\n opacity var(--motion-duration-150, 150ms) var(--motion-easing-default, ease-in-out);\n}\n\n.saveButton:hover {\n background: color-mix(in srgb, var(--primary, #111827) 88%, white);\n}\n\n.saveButton:focus-visible {\n outline: var(--focus-ring-width, 2px) solid var(--primary, #111827);\n outline-offset: var(--focus-ring-offset, 2px);\n}\n\n.saveButton > svg {\n width: var(--spacing-3_5, 0.9375rem); /* prototype: 15px */\n height: var(--spacing-3_5, 0.9375rem);\n stroke-width: 2.4;\n}\n\n/* ─── AI action button ───────────────────────────────────────────────────── */\n\n.aiAction {\n display: inline-flex;\n align-items: center;\n gap: var(--spacing-1_5, 0.375rem); /* prototype: 6px */\n margin-top: var(--spacing-2, 0.5rem); /* prototype: 9px ≈ spacing-2 */\n font-size: var(--font-size-xs, 0.71875rem); /* prototype: 11.5px */\n font-weight: 700;\n color: var(--primary, #111827);\n background: none;\n border: none;\n cursor: pointer;\n padding: 0;\n transition: opacity var(--motion-duration-150, 150ms) var(--motion-easing-default, ease-in-out);\n}\n\n.aiAction:hover {\n opacity: var(--opacity-80, 0.8);\n}\n\n.aiAction:focus-visible {\n outline: var(--focus-ring-width, 2px) solid var(--primary, #111827);\n outline-offset: var(--focus-ring-offset, 2px);\n border-radius: var(--radius-sm, 0.25rem);\n}\n\n.aiAction > svg {\n width: var(--spacing-3, 0.8125rem); /* prototype: 13px */\n height: var(--spacing-3, 0.8125rem);\n}\n\n/* ─── Reduced motion ─────────────────────────────────────────────────────── */\n\n@media (prefers-reduced-motion: reduce) {\n .root,\n .label,\n .editIcon,\n .saveButton,\n .aiAction {\n transition: none;\n }\n}\n"
2107
2107
  }
2108
2108
  ]
2109
2109
  },
@@ -2506,7 +2506,7 @@
2506
2506
  {
2507
2507
  "path": "components/ui/confirm-dialog/confirm-dialog.module.css",
2508
2508
  "type": "registry:ui",
2509
- "content": "/* ConfirmDialog — destructive-action confirmation compound wrapping Dialog. */\n\n.root {\n width: 100%;\n min-width: 0;\n container-type: inline-size;\n container-name: confirm-dialog;\n}\n\n/* ── Canonical default treatment (iconTreatment unset) ─────────────────────\n * A tinted circular plate (~2.5rem, surface-*-subtle wash) stacked above the\n * title/description. This is the unchanged default rendering. */\n\n/* Header layout — plate stacked above title/description */\n.headerStack {\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n gap: var(--spacing-3, 0.75rem);\n}\n\n/* Tinted circular icon plate (~2.5rem) stacked above the dialog title */\n.iconPlate {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n width: var(--spacing-10, 2.5rem);\n height: var(--spacing-10, 2.5rem);\n border-radius: 9999px;\n}\n\n.iconPlate svg {\n width: var(--spacing-5, 1.25rem);\n height: var(--spacing-5, 1.25rem);\n}\n\n.plateInfo {\n background: var(--surface-info-subtle, #f0f9ff);\n color: var(--text-info, #0369a1);\n}\n\n.plateWarning {\n background: var(--surface-warning-subtle, #fffbeb);\n color: var(--text-warning, #b45309);\n}\n\n.plateDestructive {\n background: var(--surface-error-subtle, #fef2f2);\n color: var(--text-error, #b91c1c);\n}\n\n/* ── Blessed editorial treatments (iconTreatment=\"inline\" | \"plated\") ───────\n * Brought in from the blessed admin build's confirm-dialog. Opt-in via the\n * iconTreatment prop; the canonical default (above) is unchanged. */\n\n/* Title row with leading severity icon — blessed inline treatment. */\n.titleRow {\n display: flex;\n align-items: center;\n gap: var(--spacing-2, 0.5rem);\n}\n\n/* Plated layout — opt-in via iconTreatment=\"plated\". Stacks a tinted circular\n * icon container ABOVE the title (golden organization-management Feedback\n * screen). */\n.titleRowPlated {\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n gap: var(--spacing-3, 0.75rem);\n}\n\n/* Plated severity icon container — ~40px tinted circle. */\n.iconPlated {\n width: var(--confirm-dialog-plate-size, 40px);\n height: var(--confirm-dialog-plate-size, 40px);\n border-radius: var(--radius-full, 999px);\n display: grid;\n place-items: center;\n flex-shrink: 0;\n}\n\n.iconPlated svg {\n width: var(--confirm-dialog-plate-icon-size, 22px);\n height: var(--confirm-dialog-plate-icon-size, 22px);\n}\n\n/* Plated severity tints — bg uses a tinted wash of the severity token;\n * foreground uses the solid severity token. Matches prototype-overlay\n * the prototype's warning / destructive icon plates exactly. */\n.iconPlatedInfo {\n background: color-mix(in srgb, var(--accent, #0369a1) 18%, transparent);\n color: var(--accent, #0369a1);\n}\n\n.iconPlatedWarning {\n background: color-mix(in srgb, var(--warning, #b45309) 22%, transparent);\n color: var(--warning, #b45309);\n}\n\n.iconPlatedDanger {\n background: color-mix(in srgb, var(--destructive, #b91c1c) 18%, transparent);\n color: var(--destructive, #b91c1c);\n}\n\n/* Inline severity icon — sized via svg to respect Phosphor sizing contract.\n * Also serves as the legacy `.iconInfo/.iconWarning/.iconDanger` color hook for\n * theme overrides targeting the old class names. */\n.icon {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n line-height: 1;\n}\n\n.icon svg {\n width: var(--spacing-5, 1.25rem);\n height: var(--spacing-5, 1.25rem);\n}\n\n.iconInfo {\n color: var(--text-info, #0369a1);\n}\n\n.iconWarning {\n color: var(--text-warning, #b45309);\n}\n\n.iconDanger {\n color: var(--text-error, #b91c1c);\n}\n\n/* Body slot — description paragraph or richer children */\n.body {\n margin-top: var(--spacing-2, 0.5rem);\n font-size: var(--font-size-sm, 0.875rem);\n color: var(--text-secondary, #6b7280);\n line-height: var(--line-height-relaxed, 1.6);\n}\n\n.body > :first-child {\n margin-top: 0;\n}\n\n.body > :last-child {\n margin-bottom: 0;\n}\n\n/* Confirm-text gate — labeled text input between body and actions */\n.confirmGate {\n display: flex;\n flex-direction: column;\n gap: var(--spacing-1, 0.25rem);\n margin-top: var(--spacing-4, 1rem);\n}\n\n.confirmGateLabel {\n font-size: var(--font-size-sm, 0.875rem);\n color: var(--text-primary, #111827);\n font-weight: var(--font-weight-medium, 500);\n}\n\n.confirmGateInput {\n width: 100%;\n padding: var(--spacing-2, 0.5rem) var(--spacing-3, 0.75rem);\n border-radius: var(--radius-md, 0.5rem);\n border: 1px solid var(--border-default, #e5e7eb);\n background-color: var(--surface-page, #ffffff);\n color: var(--text-primary, #111827);\n font-size: var(--font-size-sm, 0.875rem);\n font-family: inherit;\n line-height: var(--line-height-normal, 1.5);\n transition: border-color var(--motion-duration-150, 150ms) var(--motion-easing-default, ease-in-out);\n}\n\n.confirmGateInput:focus-visible {\n outline: var(--focus-ring-width, 2px) solid var(--border-focus, currentColor);\n outline-offset: var(--focus-ring-offset, 2px);\n border-color: var(--border-focus, currentColor);\n}\n\n.confirmGateInput:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n}\n\n/* Action row — cancel + confirm, right-aligned on wide, stacked on narrow */\n.actions {\n display: flex;\n flex-direction: row;\n justify-content: flex-end;\n align-items: center;\n gap: var(--spacing-2, 0.5rem);\n margin-top: var(--spacing-6, 1.5rem);\n}\n\n.action {\n display: inline-flex;\n}\n\n/* Inline (non-portal) surface — opt-in via mode=\"inline\". Renders the dialog\n * content card in normal flow WITHOUT Radix DialogPortal/DialogOverlay/auto\n * X-close, so consumers can stack multiple dialogs inside one shared scrim.\n * Mirrors the dialog content card visuals (surface/radius/padding/shadow) but\n * uses static positioning instead of fixed centering.\n * Default: 32rem max-width, radius-lg, surface-card, spacing-6, shadow-xl.\n * Density axis: editorial uses 480px, radius-xl, surface-card, spacing-8, shadow-lg. */\n.inlineSurface {\n position: relative;\n width: 100%;\n max-width: 32rem;\n border-radius: var(--radius-lg, 0.5rem);\n background-color: var(--surface-card, var(--surface-page, #ffffff));\n padding: var(--spacing-6, 1.5rem);\n box-shadow: var(--shadow-xl);\n}\n\n/* Editorial density: the inline confirm card carries the editorial modal\n metrics (card surface, 480px, radius-xl, spacing-8, shadow-lg) — verified\n against the blessed user-states render. */\n:global([data-density=\"editorial\"]) .inlineSurface {\n background-color: var(--surface-card);\n max-width: 480px;\n border-radius: var(--radius-xl);\n padding: var(--spacing-8);\n box-shadow: var(--shadow-lg);\n}\n\n/* Inline header — replaces DialogHeader (which depends on the dialog stylesheet). */\n.inlineHeader {\n display: flex;\n flex-direction: column;\n gap: calc(var(--spacing-1, 0.25rem) * 1.5);\n margin-bottom: var(--spacing-4, 1rem);\n}\n\n/* Inline title — replaces Radix DialogTitle (no Dialog context in inline mode).\n * Default: font-size-lg / semibold. Density axis: editorial uses font-size-2xl / 700. */\n.inlineTitle {\n font-size: var(--font-size-lg, 1.125rem);\n font-weight: var(--font-weight-semibold, 600);\n color: var(--text-primary, #111827);\n margin: 0;\n}\n\n:global([data-density=\"editorial\"]) .inlineTitle {\n font-size: var(--font-size-2xl);\n font-weight: 700;\n}\n\n/* Inline description — replaces Radix DialogDescription.\n * Default: text-secondary. Density axis: editorial uses text-tertiary. */\n.inlineDescription {\n font-size: var(--font-size-sm, 0.875rem);\n color: var(--text-secondary, #6b7280);\n margin: 0;\n}\n\n:global([data-density=\"editorial\"]) .inlineDescription {\n color: var(--text-tertiary);\n}\n\n/* Container query: stack actions vertically on narrow dialog widths */\n@container confirm-dialog (max-width: 360px) {\n .actions {\n flex-direction: column-reverse;\n align-items: stretch;\n width: 100%;\n }\n\n .actions .action {\n width: 100%;\n }\n\n .actions .action > * {\n width: 100%;\n justify-content: center;\n }\n}\n"
2509
+ "content": "/* ConfirmDialog — destructive-action confirmation compound wrapping Dialog. */\n\n.root {\n width: 100%;\n min-width: 0;\n container-type: inline-size;\n container-name: confirm-dialog;\n}\n\n/* ── Canonical default treatment (iconTreatment unset) ─────────────────────\n * A tinted circular plate (~2.5rem, surface-*-subtle wash) stacked above the\n * title/description. This is the unchanged default rendering. */\n\n/* Header layout — plate stacked above title/description */\n.headerStack {\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n gap: var(--spacing-3, 0.75rem);\n}\n\n/* Tinted circular icon plate (~2.5rem) stacked above the dialog title */\n.iconPlate {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n width: var(--spacing-10, 2.5rem);\n height: var(--spacing-10, 2.5rem);\n border-radius: 9999px;\n}\n\n.iconPlate svg {\n width: var(--spacing-5, 1.25rem);\n height: var(--spacing-5, 1.25rem);\n}\n\n.plateInfo {\n background: var(--surface-info-subtle, #f0f9ff);\n color: var(--text-info, #0369a1);\n}\n\n.plateWarning {\n background: var(--surface-warning-subtle, #fffbeb);\n color: var(--text-warning, #b45309);\n}\n\n.plateDestructive {\n background: var(--surface-error-subtle, #fef2f2);\n color: var(--text-error, #b91c1c);\n}\n\n/* ── Blessed editorial treatments (iconTreatment=\"inline\" | \"plated\") ───────\n * Brought in from the blessed admin build's confirm-dialog. Opt-in via the\n * iconTreatment prop; the canonical default (above) is unchanged. */\n\n/* Title row with leading severity icon — blessed inline treatment. */\n.titleRow {\n display: flex;\n align-items: center;\n gap: var(--spacing-2, 0.5rem);\n}\n\n/* Plated layout — opt-in via iconTreatment=\"plated\". Stacks a tinted circular\n * icon container ABOVE the title (golden organization-management Feedback\n * screen). */\n.titleRowPlated {\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n gap: var(--spacing-3, 0.75rem);\n}\n\n/* Plated severity icon container — ~40px tinted circle. */\n.iconPlated {\n width: var(--confirm-dialog-plate-size, 40px);\n height: var(--confirm-dialog-plate-size, 40px);\n border-radius: var(--radius-full, 999px);\n display: grid;\n place-items: center;\n flex-shrink: 0;\n}\n\n.iconPlated svg {\n width: var(--confirm-dialog-plate-icon-size, 22px);\n height: var(--confirm-dialog-plate-icon-size, 22px);\n}\n\n/* Plated severity tints — bg uses a tinted wash of the severity token;\n * foreground uses the solid severity token. Matches prototype-overlay\n * the prototype's warning / destructive icon plates exactly. */\n.iconPlatedInfo {\n background: color-mix(in srgb, var(--accent, #0369a1) 18%, transparent);\n color: var(--accent, #0369a1);\n}\n\n.iconPlatedWarning {\n background: color-mix(in srgb, var(--warning, #b45309) 22%, transparent);\n color: var(--warning, #b45309);\n}\n\n.iconPlatedDanger {\n background: color-mix(in srgb, var(--destructive, #b91c1c) 18%, transparent);\n color: var(--destructive, #b91c1c);\n}\n\n/* Inline severity icon — sized via svg to respect Phosphor sizing contract.\n * Also serves as the legacy `.iconInfo/.iconWarning/.iconDanger` color hook for\n * theme overrides targeting the old class names. */\n.icon {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n line-height: 1;\n}\n\n.icon svg {\n width: var(--spacing-5, 1.25rem);\n height: var(--spacing-5, 1.25rem);\n}\n\n.iconInfo {\n color: var(--text-info, #0369a1);\n}\n\n.iconWarning {\n color: var(--text-warning, #b45309);\n}\n\n.iconDanger {\n color: var(--text-error, #b91c1c);\n}\n\n/* Body slot — description paragraph or richer children */\n.body {\n margin-top: var(--spacing-2, 0.5rem);\n font-size: var(--font-size-sm, 0.875rem);\n color: var(--text-secondary, #6b7280);\n line-height: var(--line-height-relaxed, 1.6);\n}\n\n.body > :first-child {\n margin-top: 0;\n}\n\n.body > :last-child {\n margin-bottom: 0;\n}\n\n/* Confirm-text gate — labeled text input between body and actions */\n.confirmGate {\n display: flex;\n flex-direction: column;\n gap: var(--spacing-1, 0.25rem);\n margin-top: var(--spacing-4, 1rem);\n}\n\n.confirmGateLabel {\n font-size: var(--font-size-sm, 0.875rem);\n color: var(--text-primary, #111827);\n font-weight: var(--font-weight-medium, 500);\n}\n\n.confirmGateInput {\n width: 100%;\n padding: var(--spacing-2, 0.5rem) var(--spacing-3, 0.75rem);\n border-radius: var(--radius-md, 0.5rem);\n border: 1px solid var(--border-default, #e5e7eb);\n background-color: var(--surface-page, #ffffff);\n color: var(--text-primary, #111827);\n font-size: var(--font-size-sm, 0.875rem);\n line-height: var(--line-height-normal, 1.5);\n transition: border-color var(--motion-duration-150, 150ms) var(--motion-easing-default, ease-in-out);\n}\n\n.confirmGateInput:focus-visible {\n outline: var(--focus-ring-width, 2px) solid var(--border-focus, currentColor);\n outline-offset: var(--focus-ring-offset, 2px);\n border-color: var(--border-focus, currentColor);\n}\n\n.confirmGateInput:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n}\n\n/* Action row — cancel + confirm, right-aligned on wide, stacked on narrow */\n.actions {\n display: flex;\n flex-direction: row;\n justify-content: flex-end;\n align-items: center;\n gap: var(--spacing-2, 0.5rem);\n margin-top: var(--spacing-6, 1.5rem);\n}\n\n.action {\n display: inline-flex;\n}\n\n/* Inline (non-portal) surface — opt-in via mode=\"inline\". Renders the dialog\n * content card in normal flow WITHOUT Radix DialogPortal/DialogOverlay/auto\n * X-close, so consumers can stack multiple dialogs inside one shared scrim.\n * Mirrors the dialog content card visuals (surface/radius/padding/shadow) but\n * uses static positioning instead of fixed centering.\n * Default: 32rem max-width, radius-lg, surface-card, spacing-6, shadow-xl.\n * Density axis: editorial uses 480px, radius-xl, surface-card, spacing-8, shadow-lg. */\n.inlineSurface {\n position: relative;\n width: 100%;\n max-width: 32rem;\n border-radius: var(--radius-lg, 0.5rem);\n background-color: var(--surface-card, var(--surface-page, #ffffff));\n padding: var(--spacing-6, 1.5rem);\n box-shadow: var(--shadow-xl);\n}\n\n/* Editorial density: the inline confirm card carries the editorial modal\n metrics (card surface, 480px, radius-xl, spacing-8, shadow-lg) — verified\n against the blessed user-states render. */\n:global([data-density=\"editorial\"]) .inlineSurface {\n background-color: var(--surface-card);\n max-width: 480px;\n border-radius: var(--radius-xl);\n padding: var(--spacing-8);\n box-shadow: var(--shadow-lg);\n}\n\n/* Inline header — replaces DialogHeader (which depends on the dialog stylesheet). */\n.inlineHeader {\n display: flex;\n flex-direction: column;\n gap: calc(var(--spacing-1, 0.25rem) * 1.5);\n margin-bottom: var(--spacing-4, 1rem);\n}\n\n/* Inline title — replaces Radix DialogTitle (no Dialog context in inline mode).\n * Default: font-size-lg / semibold. Density axis: editorial uses font-size-2xl / 700. */\n.inlineTitle {\n font-size: var(--font-size-lg, 1.125rem);\n font-weight: var(--font-weight-semibold, 600);\n color: var(--text-primary, #111827);\n margin: 0;\n}\n\n:global([data-density=\"editorial\"]) .inlineTitle {\n font-size: var(--font-size-2xl);\n font-weight: 700;\n}\n\n/* Inline description — replaces Radix DialogDescription.\n * Default: text-secondary. Density axis: editorial uses text-tertiary. */\n.inlineDescription {\n font-size: var(--font-size-sm, 0.875rem);\n color: var(--text-secondary, #6b7280);\n margin: 0;\n}\n\n:global([data-density=\"editorial\"]) .inlineDescription {\n color: var(--text-tertiary);\n}\n\n/* Container query: stack actions vertically on narrow dialog widths */\n@container confirm-dialog (max-width: 360px) {\n .actions {\n flex-direction: column-reverse;\n align-items: stretch;\n width: 100%;\n }\n\n .actions .action {\n width: 100%;\n }\n\n .actions .action > * {\n width: 100%;\n justify-content: center;\n }\n}\n"
2510
2510
  }
2511
2511
  ]
2512
2512
  },
@@ -2539,7 +2539,7 @@
2539
2539
  {
2540
2540
  "path": "components/ui/data-table/data-table.module.css",
2541
2541
  "type": "registry:ui",
2542
- "content": "/* DataTable root — inline-size container for responsive collapse */\n.root {\n display: flex;\n flex-direction: column;\n width: 100%;\n min-width: 0;\n gap: var(--spacing-3, 0.75rem);\n container-type: inline-size;\n container-name: data-table;\n color: var(--text-primary, #111827);\n}\n\n/* Density axis — vertical row padding step driven by `data-density` on the\n root (or any ancestor). The three tiers map the full density spectrum:\n compact (sub-content lists), default (backward-compatible baseline), and\n editorial (generous card-like rows; high-design admin patterns).\n\n Cells consume `--dt-row-py` via the `.root td` rule below. Horizontal cell\n padding stays at TableCell's `padding: var(--spacing-3)` shorthand cascade\n — we only override the top/bottom longhand properties here, so `default`\n density renders identically to pre-density-axis markup.\n\n Themes can override per-density values via their own selectors. Example:\n [data-theme=\"entr\"] [data-density=\"editorial\"] { --dt-row-py: var(--spacing-6); } */\n.root[data-density=\"compact\"] { --dt-row-py: var(--spacing-2, 0.5rem); }\n.root[data-density=\"default\"] { --dt-row-py: var(--spacing-3, 0.75rem); }\n.root[data-density=\"editorial\"] { --dt-row-py: var(--spacing-5, 1.25rem); }\n\n/* Editorial surface treatment — bakes the editorial-admin baseline values into\n the density axis. The var() reads keep --dt-* hooks working for per-theme\n overrides; the fallbacks resolve to the editorial values when no hook is set.\n Container goes flush (radius 0, no shadow); header and rows use card/page\n surface tiers instead of transparent. */\n.root[data-density=\"editorial\"] .stickyHeader,\n.root[data-density=\"editorial\"] [data-slot=\"table-container\"] {\n border-radius: var(--dt-container-radius, 0);\n box-shadow: var(--dt-container-shadow, none);\n}\n.root[data-density=\"editorial\"] [data-slot=\"table-head\"] {\n background-color: var(--dt-header-bg, var(--surface-card));\n}\n.root[data-density=\"editorial\"] [data-slot=\"table-cell\"] {\n background-color: var(--dt-row-bg, color-mix(in srgb, var(--surface-page) 75%, var(--surface-card) 25%));\n}\n\n/* Editorial column-header treatment — uppercase, 11px, tertiary color,\n tracked type (0.08em). Anchored on .root to avoid a bare attribute selector\n (Turbopack pure-selector rule). Overrides the TableHead default styles and\n the sort-button font-weight rule below. */\n.root[data-density=\"editorial\"] th {\n font-size: var(--dt-header-font-size, 11px);\n font-weight: var(--font-weight-medium, 500);\n color: var(--text-tertiary, #6b7280);\n letter-spacing: 0.08em;\n text-transform: uppercase;\n}\n\n/* Editorial density widens horizontal cell padding (spacing-5 / 20px) to match\n the editorial-admin baseline; vertical stays driven by --dt-row-py. The\n --dt-cell-px hook lets a theme tune it; default equals the editorial value. */\n.root[data-density=\"editorial\"] td,\n.root[data-density=\"editorial\"] th {\n padding-left: var(--dt-cell-px, var(--spacing-5, 1.25rem));\n padding-right: var(--dt-cell-px, var(--spacing-5, 1.25rem));\n}\n\n/* The sort button inherits font from its <th>, but explicitly overrides\n font-weight to semibold — reset to medium for the editorial treatment. */\n.root[data-density=\"editorial\"] .sortButton {\n font-weight: var(--font-weight-medium, 500);\n}\n\n.root td {\n padding-top: var(--dt-row-py, var(--spacing-3, 0.75rem));\n padding-bottom: var(--dt-row-py, var(--spacing-3, 0.75rem));\n}\n\n/* Sticky header wrapper — toggled when stickyHeader prop is true */\n.stickyHeader {\n position: sticky;\n top: 0;\n z-index: 1;\n background: var(--surface-card, #ffffff);\n}\n\n/* Sort-bar row — the thead <tr> that houses the column headers.\n `--data-table-sort-bar-radius` controls the top-corner radius of the first\n and last <th> cells. Defaults to the container's border-radius so the sort\n bar visually follows the table card's rounded top corners.\n\n Set `--data-table-sort-bar-radius: 0` on a parent scope for the\n borderless-admin pattern — straight corners without touching the container\n itself. */\n.sortBar th:first-child {\n border-top-left-radius: var(--data-table-sort-bar-radius, var(--radius-lg, 0.5rem));\n}\n\n.sortBar th:last-child {\n border-top-right-radius: var(--data-table-sort-bar-radius, var(--radius-lg, 0.5rem));\n}\n\n/* Editorial density: the flush admin shell has straight header corners — the\n sort-bar radius defaults to 0 (still overridable via the hook). */\n.root[data-density=\"editorial\"] .sortBar th:first-child {\n border-top-left-radius: var(--data-table-sort-bar-radius, 0);\n}\n\n.root[data-density=\"editorial\"] .sortBar th:last-child {\n border-top-right-radius: var(--data-table-sort-bar-radius, 0);\n}\n\n/* Sort button — renders inside the <th> */\n.sortButton {\n display: inline-flex;\n align-items: center;\n gap: var(--spacing-1, 0.25rem);\n padding: 0;\n margin: 0;\n background: transparent;\n border: 0;\n color: inherit;\n font: inherit;\n font-weight: var(--font-weight-semibold, 600);\n cursor: pointer;\n line-height: var(--line-height-tight, 1.25);\n border-radius: var(--radius-sm, 0.25rem);\n transition:\n color var(--motion-duration-fast, 150ms)\n var(--motion-easing-standard, ease),\n background-color var(--motion-duration-fast, 150ms)\n var(--motion-easing-standard, ease);\n}\n\n.sortButton:hover {\n color: var(--text-primary, #111827);\n}\n\n.sortButton:focus-visible {\n outline: var(--focus-ring-width, 2px) solid\n var(--focus-ring-color, #2563eb);\n outline-offset: var(--focus-ring-offset, 2px);\n}\n\n.sortLabel {\n display: inline-block;\n}\n\n.sortIcon {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: var(--spacing-4, 1rem);\n height: var(--spacing-4, 1rem);\n color: var(--text-tertiary, #6b7280);\n flex-shrink: 0;\n}\n\n.sortIcon svg {\n width: 100%;\n height: 100%;\n}\n\n/* Skeleton cell fills the cell width */\n.skeletonCell {\n width: 100%;\n height: var(--spacing-4, 1rem);\n}\n\n/* Empty-row cell centers the EmptyState slot */\n.emptyCell {\n padding: var(--spacing-6, 1.5rem) var(--spacing-4, 1rem);\n text-align: center;\n}\n\n/* Footer — info on the left, controls on the right */\n.footer {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--spacing-4, 1rem);\n padding: var(--spacing-2, 0.5rem) var(--spacing-1, 0.25rem);\n min-width: 0;\n flex-wrap: wrap;\n}\n\n.footerInfo {\n font-size: var(--font-size-sm, 0.875rem);\n color: var(--text-secondary, #6b7280);\n min-width: 0;\n}\n\n.footerControls {\n display: flex;\n align-items: center;\n gap: var(--spacing-4, 1rem);\n flex-wrap: wrap;\n}\n\n.pageSizeLabel {\n display: inline-flex;\n align-items: center;\n gap: var(--spacing-2, 0.5rem);\n font-size: var(--font-size-sm, 0.875rem);\n color: var(--text-secondary, #6b7280);\n}\n\n.pageSizeLabelText {\n white-space: nowrap;\n}\n\n/* Native <select> styled to match Visor input controls */\n.pageSizeSelect {\n appearance: none;\n -webkit-appearance: none;\n -moz-appearance: none;\n height: var(--spacing-8, 2rem);\n padding: 0 var(--spacing-6, 1.5rem) 0 var(--spacing-2, 0.5rem);\n border-radius: var(--radius-md, 0.375rem);\n border: 1px solid var(--border-default, #e5e7eb);\n background-color: var(--surface-card, #ffffff);\n background-image: linear-gradient(\n 45deg,\n transparent 50%,\n var(--text-tertiary, #6b7280) 50%\n ),\n linear-gradient(\n 135deg,\n var(--text-tertiary, #6b7280) 50%,\n transparent 50%\n );\n background-position:\n right var(--spacing-3, 0.75rem) center,\n right var(--spacing-2, 0.5rem) center;\n background-size:\n 5px 5px,\n 5px 5px;\n background-repeat: no-repeat;\n color: var(--text-primary, #111827);\n font-size: var(--font-size-sm, 0.875rem);\n line-height: var(--line-height-tight, 1.25);\n cursor: pointer;\n transition:\n border-color var(--motion-duration-fast, 150ms)\n var(--motion-easing-standard, ease),\n box-shadow var(--motion-duration-fast, 150ms)\n var(--motion-easing-standard, ease);\n}\n\n.pageSizeSelect:hover {\n border-color: var(--border-strong, #d1d5db);\n}\n\n.pageSizeSelect:focus-visible {\n outline: var(--focus-ring-width, 2px) solid\n var(--focus-ring-color, #2563eb);\n outline-offset: var(--focus-ring-offset, 2px);\n}\n\n.pageNav {\n display: inline-flex;\n align-items: center;\n gap: var(--spacing-2, 0.5rem);\n}\n\n.pageCounter {\n font-size: var(--font-size-sm, 0.875rem);\n color: var(--text-secondary, #6b7280);\n white-space: nowrap;\n}\n\n/* Data row — base layer for the per-row data-state / data-tone / data-clickable\n variants below. The selectors are scoped to `.dataRow` so the tone/selected\n tints never bleed onto group-head rows or skeleton/empty rows. */\n.dataRow {\n transition: background-color var(--motion-duration-fast, 150ms)\n var(--motion-easing-standard, ease);\n}\n\n/* Selected row — wires the latent `data-state=\"selected\"` attribute (already\n emitted by TanStack on selected rows) to a subtle accent fill. Fixes a\n latent bug where selection had no visual feedback. */\n.dataRow[data-state=\"selected\"] {\n background-color: var(\n --surface-selected,\n var(--surface-interactive-active, #e5e7eb)\n );\n}\n\n/* Per-row tone tints — semantic background hints for editorial status.\n Mirrors the tone token mapping used by StatusBadge / StatusDot so a\n row tinted \"live\" reads consistently with a \"live\" badge inline.\n `scheduled` and `draft` intentionally have no tint — they render on\n the default surface to keep visual signal focused on actionable rows. */\n.dataRow[data-tone=\"live\"],\n.dataRow[data-tone=\"sold\"] {\n background-color: var(--surface-success-subtle, #ecfdf5);\n}\n\n.dataRow[data-tone=\"warn\"] {\n background-color: var(--surface-warning-subtle, #fffbeb);\n}\n\n.dataRow[data-tone=\"danger\"] {\n background-color: var(--surface-error-subtle, #fef2f2);\n}\n\n.dataRow[data-tone=\"info\"] {\n background-color: var(--surface-info-subtle, #eff6ff);\n}\n\n/* Selected state should win over tone tint — selection is a stronger\n signal than editorial status. */\n.dataRow[data-state=\"selected\"][data-tone] {\n background-color: var(\n --surface-selected,\n var(--surface-interactive-active, #e5e7eb)\n );\n}\n\n/* Clickable rows — opt-in affordance when `onRowClick` is supplied. */\n.dataRow[data-clickable=\"true\"] {\n cursor: pointer;\n}\n\n.dataRow[data-clickable=\"true\"]:hover {\n background-color: var(--surface-interactive-default, #f3f4f6);\n}\n\n.dataRow[data-clickable=\"true\"]:focus-visible {\n outline: var(--focus-ring-width, 2px) solid\n var(--focus-ring-color, #2563eb);\n outline-offset: calc(var(--focus-ring-offset, 2px) * -1);\n}\n\n/* Group-head row — full-width separator inside the table body. The colSpan\n cell carries the visual; the inner span owns the sticky positioning so it\n pins to the top of the scroll container as data rows scroll beneath. */\n.groupRow {\n background-color: transparent;\n cursor: default;\n}\n\n.groupRow:hover {\n background-color: transparent;\n}\n\n.groupCell {\n padding: 0;\n}\n\n.groupLabel {\n display: flex;\n align-items: center;\n gap: var(--spacing-2, 0.5rem);\n height: 28px;\n padding: 0 var(--spacing-4, 1rem);\n background: var(--surface-subtle, #f3f4f6);\n font-size: var(--font-size-xs, 0.6875rem);\n font-weight: var(--font-weight-medium, 500);\n letter-spacing: 0.14em;\n text-transform: uppercase;\n color: var(--text-tertiary, #6b7280);\n position: sticky;\n top: 0;\n z-index: 1;\n}\n\n.groupCount {\n font-size: var(--font-size-xs, 0.6875rem);\n color: var(--text-quaternary, #9ca3af);\n font-variant-numeric: tabular-nums;\n letter-spacing: 0;\n}\n\n/* Narrow containers — stack footer sections */\n@container data-table (max-width: 560px) {\n .footer {\n flex-direction: column;\n align-items: stretch;\n }\n\n .footerControls {\n justify-content: space-between;\n }\n}\n"
2542
+ "content": "/* DataTable root — inline-size container for responsive collapse */\n.root {\n display: flex;\n flex-direction: column;\n width: 100%;\n min-width: 0;\n gap: var(--spacing-3, 0.75rem);\n container-type: inline-size;\n container-name: data-table;\n color: var(--text-primary, #111827);\n}\n\n/* Density axis — vertical row padding step driven by `data-density` on the\n root (or any ancestor). The three tiers map the full density spectrum:\n compact (sub-content lists), default (backward-compatible baseline), and\n editorial (generous card-like rows; high-design admin patterns).\n\n Cells consume `--dt-row-py` via the `.root td` rule below. Horizontal cell\n padding stays at TableCell's `padding: var(--spacing-3)` shorthand cascade\n — we only override the top/bottom longhand properties here, so `default`\n density renders identically to pre-density-axis markup.\n\n Themes can override per-density values via their own selectors. Example:\n [data-theme=\"entr\"] [data-density=\"editorial\"] { --dt-row-py: var(--spacing-6); } */\n.root[data-density=\"compact\"] { --dt-row-py: var(--spacing-2, 0.5rem); }\n.root[data-density=\"default\"] { --dt-row-py: var(--spacing-3, 0.75rem); }\n.root[data-density=\"editorial\"] { --dt-row-py: var(--spacing-5, 1.25rem); }\n\n/* Editorial surface treatment — bakes the editorial-admin baseline values into\n the density axis. The var() reads keep --dt-* hooks working for per-theme\n overrides; the fallbacks resolve to the editorial values when no hook is set.\n Container goes flush (radius 0, no shadow); header and rows use card/page\n surface tiers instead of transparent. */\n.root[data-density=\"editorial\"] .stickyHeader,\n.root[data-density=\"editorial\"] [data-slot=\"table-container\"] {\n border-radius: var(--dt-container-radius, 0);\n box-shadow: var(--dt-container-shadow, none);\n}\n.root[data-density=\"editorial\"] [data-slot=\"table-head\"] {\n background-color: var(--dt-header-bg, var(--surface-card));\n}\n.root[data-density=\"editorial\"] [data-slot=\"table-cell\"] {\n background-color: var(--dt-row-bg, color-mix(in srgb, var(--surface-page) 75%, var(--surface-card) 25%));\n}\n\n/* Editorial column-header treatment — uppercase, 11px, tertiary color,\n tracked type (0.08em). Anchored on .root to avoid a bare attribute selector\n (Turbopack pure-selector rule). Overrides the TableHead default styles and\n the sort-button font-weight rule below. */\n.root[data-density=\"editorial\"] th {\n font-size: var(--dt-header-font-size, 11px);\n font-weight: var(--font-weight-medium, 500);\n color: var(--text-tertiary, #6b7280);\n letter-spacing: 0.08em;\n text-transform: uppercase;\n}\n\n/* Editorial density widens horizontal cell padding (spacing-5 / 20px) to match\n the editorial-admin baseline; vertical stays driven by --dt-row-py. The\n --dt-cell-px hook lets a theme tune it; default equals the editorial value. */\n.root[data-density=\"editorial\"] td,\n.root[data-density=\"editorial\"] th {\n padding-left: var(--dt-cell-px, var(--spacing-5, 1.25rem));\n padding-right: var(--dt-cell-px, var(--spacing-5, 1.25rem));\n}\n\n/* The sort button inherits font from its <th>, but explicitly overrides\n font-weight to semibold — reset to medium for the editorial treatment. */\n.root[data-density=\"editorial\"] .sortButton {\n font-weight: var(--font-weight-medium, 500);\n}\n\n.root td {\n padding-top: var(--dt-row-py, var(--spacing-3, 0.75rem));\n padding-bottom: var(--dt-row-py, var(--spacing-3, 0.75rem));\n}\n\n/* Sticky header wrapper — toggled when stickyHeader prop is true */\n.stickyHeader {\n position: sticky;\n top: 0;\n z-index: 1;\n background: var(--surface-card, #ffffff);\n}\n\n/* Sort-bar row — the thead <tr> that houses the column headers.\n `--data-table-sort-bar-radius` controls the top-corner radius of the first\n and last <th> cells. Defaults to the container's border-radius so the sort\n bar visually follows the table card's rounded top corners.\n\n Set `--data-table-sort-bar-radius: 0` on a parent scope for the\n borderless-admin pattern — straight corners without touching the container\n itself. */\n.sortBar th:first-child {\n border-top-left-radius: var(--data-table-sort-bar-radius, var(--radius-lg, 0.5rem));\n}\n\n.sortBar th:last-child {\n border-top-right-radius: var(--data-table-sort-bar-radius, var(--radius-lg, 0.5rem));\n}\n\n/* Editorial density: the flush admin shell has straight header corners — the\n sort-bar radius defaults to 0 (still overridable via the hook). */\n.root[data-density=\"editorial\"] .sortBar th:first-child {\n border-top-left-radius: var(--data-table-sort-bar-radius, 0);\n}\n\n.root[data-density=\"editorial\"] .sortBar th:last-child {\n border-top-right-radius: var(--data-table-sort-bar-radius, 0);\n}\n\n/* Sort button — renders inside the <th> */\n.sortButton {\n display: inline-flex;\n align-items: center;\n gap: var(--spacing-1, 0.25rem);\n padding: 0;\n margin: 0;\n background: transparent;\n border: 0;\n color: inherit;\n font-weight: var(--font-weight-semibold, 600);\n cursor: pointer;\n line-height: var(--line-height-tight, 1.25);\n border-radius: var(--radius-sm, 0.25rem);\n transition:\n color var(--motion-duration-fast, 150ms)\n var(--motion-easing-standard, ease),\n background-color var(--motion-duration-fast, 150ms)\n var(--motion-easing-standard, ease);\n}\n\n.sortButton:hover {\n color: var(--text-primary, #111827);\n}\n\n.sortButton:focus-visible {\n outline: var(--focus-ring-width, 2px) solid\n var(--focus-ring-color, #2563eb);\n outline-offset: var(--focus-ring-offset, 2px);\n}\n\n.sortLabel {\n display: inline-block;\n}\n\n.sortIcon {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: var(--spacing-4, 1rem);\n height: var(--spacing-4, 1rem);\n color: var(--text-tertiary, #6b7280);\n flex-shrink: 0;\n}\n\n.sortIcon svg {\n width: 100%;\n height: 100%;\n}\n\n/* Skeleton cell fills the cell width */\n.skeletonCell {\n width: 100%;\n height: var(--spacing-4, 1rem);\n}\n\n/* Empty-row cell centers the EmptyState slot */\n.emptyCell {\n padding: var(--spacing-6, 1.5rem) var(--spacing-4, 1rem);\n text-align: center;\n}\n\n/* Footer — info on the left, controls on the right */\n.footer {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--spacing-4, 1rem);\n padding: var(--spacing-2, 0.5rem) var(--spacing-1, 0.25rem);\n min-width: 0;\n flex-wrap: wrap;\n}\n\n.footerInfo {\n font-size: var(--font-size-sm, 0.875rem);\n color: var(--text-secondary, #6b7280);\n min-width: 0;\n}\n\n.footerControls {\n display: flex;\n align-items: center;\n gap: var(--spacing-4, 1rem);\n flex-wrap: wrap;\n}\n\n.pageSizeLabel {\n display: inline-flex;\n align-items: center;\n gap: var(--spacing-2, 0.5rem);\n font-size: var(--font-size-sm, 0.875rem);\n color: var(--text-secondary, #6b7280);\n}\n\n.pageSizeLabelText {\n white-space: nowrap;\n}\n\n/* Native <select> styled to match Visor input controls */\n.pageSizeSelect {\n appearance: none;\n -webkit-appearance: none;\n -moz-appearance: none;\n height: var(--spacing-8, 2rem);\n padding: 0 var(--spacing-6, 1.5rem) 0 var(--spacing-2, 0.5rem);\n border-radius: var(--radius-md, 0.375rem);\n border: 1px solid var(--border-default, #e5e7eb);\n background-color: var(--surface-card, #ffffff);\n background-image: linear-gradient(\n 45deg,\n transparent 50%,\n var(--text-tertiary, #6b7280) 50%\n ),\n linear-gradient(\n 135deg,\n var(--text-tertiary, #6b7280) 50%,\n transparent 50%\n );\n background-position:\n right var(--spacing-3, 0.75rem) center,\n right var(--spacing-2, 0.5rem) center;\n background-size:\n 5px 5px,\n 5px 5px;\n background-repeat: no-repeat;\n color: var(--text-primary, #111827);\n font-size: var(--font-size-sm, 0.875rem);\n line-height: var(--line-height-tight, 1.25);\n cursor: pointer;\n transition:\n border-color var(--motion-duration-fast, 150ms)\n var(--motion-easing-standard, ease),\n box-shadow var(--motion-duration-fast, 150ms)\n var(--motion-easing-standard, ease);\n}\n\n.pageSizeSelect:hover {\n border-color: var(--border-strong, #d1d5db);\n}\n\n.pageSizeSelect:focus-visible {\n outline: var(--focus-ring-width, 2px) solid\n var(--focus-ring-color, #2563eb);\n outline-offset: var(--focus-ring-offset, 2px);\n}\n\n.pageNav {\n display: inline-flex;\n align-items: center;\n gap: var(--spacing-2, 0.5rem);\n}\n\n.pageCounter {\n font-size: var(--font-size-sm, 0.875rem);\n color: var(--text-secondary, #6b7280);\n white-space: nowrap;\n}\n\n/* Data row — base layer for the per-row data-state / data-tone / data-clickable\n variants below. The selectors are scoped to `.dataRow` so the tone/selected\n tints never bleed onto group-head rows or skeleton/empty rows. */\n.dataRow {\n transition: background-color var(--motion-duration-fast, 150ms)\n var(--motion-easing-standard, ease);\n}\n\n/* Selected row — wires the latent `data-state=\"selected\"` attribute (already\n emitted by TanStack on selected rows) to a subtle accent fill. Fixes a\n latent bug where selection had no visual feedback. */\n.dataRow[data-state=\"selected\"] {\n background-color: var(\n --surface-selected,\n var(--surface-interactive-active, #e5e7eb)\n );\n}\n\n/* Per-row tone tints — semantic background hints for editorial status.\n Mirrors the tone token mapping used by StatusBadge / StatusDot so a\n row tinted \"live\" reads consistently with a \"live\" badge inline.\n `scheduled` and `draft` intentionally have no tint — they render on\n the default surface to keep visual signal focused on actionable rows. */\n.dataRow[data-tone=\"live\"],\n.dataRow[data-tone=\"sold\"] {\n background-color: var(--surface-success-subtle, #ecfdf5);\n}\n\n.dataRow[data-tone=\"warn\"] {\n background-color: var(--surface-warning-subtle, #fffbeb);\n}\n\n.dataRow[data-tone=\"danger\"] {\n background-color: var(--surface-error-subtle, #fef2f2);\n}\n\n.dataRow[data-tone=\"info\"] {\n background-color: var(--surface-info-subtle, #eff6ff);\n}\n\n/* Selected state should win over tone tint — selection is a stronger\n signal than editorial status. */\n.dataRow[data-state=\"selected\"][data-tone] {\n background-color: var(\n --surface-selected,\n var(--surface-interactive-active, #e5e7eb)\n );\n}\n\n/* Clickable rows — opt-in affordance when `onRowClick` is supplied. */\n.dataRow[data-clickable=\"true\"] {\n cursor: pointer;\n}\n\n.dataRow[data-clickable=\"true\"]:hover {\n background-color: var(--surface-interactive-default, #f3f4f6);\n}\n\n.dataRow[data-clickable=\"true\"]:focus-visible {\n outline: var(--focus-ring-width, 2px) solid\n var(--focus-ring-color, #2563eb);\n outline-offset: calc(var(--focus-ring-offset, 2px) * -1);\n}\n\n/* Group-head row — full-width separator inside the table body. The colSpan\n cell carries the visual; the inner span owns the sticky positioning so it\n pins to the top of the scroll container as data rows scroll beneath. */\n.groupRow {\n background-color: transparent;\n cursor: default;\n}\n\n.groupRow:hover {\n background-color: transparent;\n}\n\n.groupCell {\n padding: 0;\n}\n\n.groupLabel {\n display: flex;\n align-items: center;\n gap: var(--spacing-2, 0.5rem);\n height: 28px;\n padding: 0 var(--spacing-4, 1rem);\n background: var(--surface-subtle, #f3f4f6);\n font-size: var(--font-size-xs, 0.6875rem);\n font-weight: var(--font-weight-medium, 500);\n letter-spacing: 0.14em;\n text-transform: uppercase;\n color: var(--text-tertiary, #6b7280);\n position: sticky;\n top: 0;\n z-index: 1;\n}\n\n.groupCount {\n font-size: var(--font-size-xs, 0.6875rem);\n color: var(--text-quaternary, #9ca3af);\n font-variant-numeric: tabular-nums;\n letter-spacing: 0;\n}\n\n/* Narrow containers — stack footer sections */\n@container data-table (max-width: 560px) {\n .footer {\n flex-direction: column;\n align-items: stretch;\n }\n\n .footerControls {\n justify-content: space-between;\n }\n}\n"
2543
2543
  }
2544
2544
  ]
2545
2545
  },
@@ -2816,7 +2816,7 @@
2816
2816
  {
2817
2817
  "path": "components/ui/doc-nav/doc-nav.module.css",
2818
2818
  "type": "registry:ui",
2819
- "content": "/* DocNav — manifest-driven, grouped/collapsible doc navigation.\n *\n * Renders peer, collapsible groups from a manifest slice: a pinned Shared set,\n * accordion product groups (one open at a time), and an Appendix bucket for\n * ad-hoc docs. The group row wraps (flex-wrap) and is NEVER an overflow-x\n * scroll strip — the run-off-the-edge defect this component exists to kill.\n *\n * Theme-agnostic: every value references a CSS custom property token.\n */\n\n/* Root — the wrapping row of peer groups. */\n.root {\n /* Accent-pop indirection (B2): the active pill / caret / hub / pinned frame\n * all route through this single token so a consumer (DocFrame) can retint the\n * whole nav in one place. Defaults to the theme's vivid `--accent` — not\n * `--primary`, which reads dull on muted-primary themes such as Strata. */\n --doc-nav-accent: var(--accent, #2563eb);\n /* Group cluster radius — a controlled, fixed radius the doc-nav owns, NOT the\n * theme `--radius-*` scale, which decorative themes inflate far past what a\n * dense nav cluster wants (for example Strata inflates `--radius-xl` to 32px).\n * The approved design pins ~12px per theme for exactly this reason; any single\n * theme radius token renders ~6px on some themes and ~32px on others.\n * Overridable by a consumer/theme via this variable. */\n --doc-nav-group-radius: 0.75rem;\n /* Resting pill fill — a recessed well, darker than the group's `--surface-card`\n * in BOTH modes. The surface ramp inverts light↔dark (page is darkest in dark\n * but lightest in light), so a single surface token can't stay \"below\" the card;\n * mixing the card toward neutral-950 darkens it directionally in either mode.\n * Overridable by a consumer/theme. */\n --doc-nav-pill-bg: color-mix(\n in srgb,\n var(--surface-card, #111827),\n var(--color-neutral-950, #030712) 20%\n );\n display: flex;\n flex-wrap: wrap;\n align-items: flex-start;\n gap: var(--spacing-2, 0.5rem);\n /* Deliberately no overflow-x: groups wrap down, never scroll sideways. */\n}\n\n/* Group — a bordered, surface-backed cluster: header + pill row. */\n.group {\n display: inline-flex;\n flex-direction: column;\n gap: var(--spacing-2, 0.5rem);\n padding: var(--spacing-2, 0.5rem);\n border: var(--stroke-width-thin, 1px) solid\n var(--hairline, var(--border-default, #e5e7eb));\n border-radius: var(--doc-nav-group-radius, var(--radius-md, 0.375rem));\n background: var(--surface-card, #ffffff);\n}\n\n/* Pinned — the Shared group stays open; a subtle frame keyed to the group hue.\n * Routed through overridable tokens (P5) so borderless themes (Animal / ENTR)\n * can null the frame — set `--doc-nav-pin-border: transparent` and\n * `--doc-nav-pin-bg: var(--surface-card)`. Default derives from the group's\n * shared hue, not `--primary` (which read as an unwanted border on those\n * borderless themes). */\n.groupPinned {\n border-color: var(\n --doc-nav-pin-border,\n color-mix(in srgb, var(--doc-nav-group-accent, var(--info, #0ea5e9)) 32%, transparent)\n );\n background: var(\n --doc-nav-pin-bg,\n color-mix(in srgb, var(--doc-nav-group-accent, var(--info, #0ea5e9)) 6%, var(--surface-card, #ffffff))\n );\n}\n\n/* Collapsed — a group reduces to a single pill-shaped chip. */\n.groupCollapsed {\n padding: 0;\n border-color: transparent;\n background: transparent;\n}\n\n/* Header — the group label row. As a chip when collapsed, plain when open. */\n.head {\n display: inline-flex;\n align-items: center;\n gap: var(--spacing-2, 0.5rem);\n padding: var(--spacing-1, 0.25rem) var(--spacing-2, 0.5rem);\n font-family: var(--font-mono, ui-monospace, \"SFMono-Regular\", Menlo, monospace);\n font-size: var(--font-size-2xs, 0.6875rem);\n font-weight: var(--font-weight-bold, 700);\n letter-spacing: 0.14em;\n text-transform: uppercase;\n /* Collapse the label's line box to the glyph height so the all-caps text\n * optically centers against the dot/caret (matching `.pill`). Without this the\n * caps ride high — the empty descender space pushes the line-box center below\n * the visual center of the caps. */\n line-height: 1;\n color: var(--text-secondary, #4b5563);\n}\n\n/* Button variant — collapsible group heads are clickable. */\n.headButton {\n cursor: pointer;\n border: 0;\n background: transparent;\n font-family: inherit;\n transition: color var(--motion-duration-fast, 150ms)\n var(--motion-easing-standard, ease);\n}\n\n.headButton:hover {\n color: var(--text-primary, #111827);\n}\n\n.headButton:focus-visible {\n outline: var(--focus-ring-width, 2px) solid\n var(--border-focus, currentColor);\n outline-offset: var(--focus-ring-offset, 2px);\n border-radius: var(--radius-sm, 0.25rem);\n}\n\n/* Collapsed group head — reads as a resting chip. */\n.groupCollapsed .head {\n border: var(--stroke-width-thin, 1px) solid\n var(--hairline, var(--border-default, #e5e7eb));\n border-radius: var(--radius-full, 9999px);\n /* A collapsed chip stands alone in the nav row, so it carries more vertical\n * padding than the tight open-group label (the design gives it ~7px 12px). */\n padding: var(--spacing-2, 0.5rem) var(--spacing-3, 0.75rem);\n /* The chip reads as the group's card surface (matching the design's chip-bg),\n * not a lighter subtle surface — `--surface-subtle` resolves as a mid-gray in\n * dark themes. */\n background: var(--surface-card, #111827);\n}\n\n/* Caret — accent-popped fill glyph (P6). */\n.caret {\n flex-shrink: 0;\n color: var(--doc-nav-accent, var(--accent, #2563eb));\n}\n\n/* Scope dot — a per-group grouping cue, color-coded with a soft glow (P1).\n * `color` carries the group hue so `currentColor` drives both the fill and the\n * glow; a consumer overrides the whole group via `--doc-nav-group-accent`.\n * Default (product groups) is the vivid accent; pinned/appendix retint below. */\n.scopeDot {\n width: var(--spacing-2, 0.5rem);\n height: var(--spacing-2, 0.5rem);\n flex-shrink: 0;\n border-radius: var(--radius-full, 9999px);\n color: var(--doc-nav-group-accent, var(--accent, #2563eb));\n background: currentColor;\n box-shadow: 0 0 var(--spacing-2, 0.5rem)\n color-mix(in srgb, currentColor 60%, transparent);\n}\n\n/* Shared (pinned) group reads in the info hue. */\n.groupPinned .scopeDot {\n color: var(--doc-nav-group-accent, var(--info, #0ea5e9));\n}\n\n/* Appendix reads muted and un-glowed — an ad-hoc bucket, not a product. */\n.group[data-role=\"appendix\"] .scopeDot {\n color: var(--doc-nav-group-accent, var(--text-tertiary, #9ca3af));\n box-shadow: none;\n}\n\n/* Group label text. */\n.groupLabel {\n min-width: 0;\n}\n\n/* Trailing count badge — a hairline mono pill on a collapsed group (N2). */\n.count {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n min-width: var(--spacing-4, 1rem);\n padding: 0 calc(var(--spacing-1, 0.25rem) * 1.5);\n border: var(--stroke-width-thin, 1px) solid\n var(--hairline, var(--border-default, #e5e7eb));\n border-radius: var(--radius-full, 9999px);\n font-family: var(--font-mono, ui-monospace, \"SFMono-Regular\", Menlo, monospace);\n /* ~9px — a quarter down from the xs step, matching the design's tiny badge. */\n font-size: calc(var(--font-size-xs, 0.75rem) * 0.75);\n font-variant-numeric: tabular-nums;\n color: var(--text-tertiary, #9ca3af);\n}\n\n/* Pill row — wraps within the group. */\n.pills {\n display: flex;\n flex-wrap: wrap;\n gap: var(--spacing-1, 0.25rem);\n}\n\n/* Pill — a single doc link. Mono · UPPERCASE · letter-spaced (B1). */\n.pill {\n display: inline-flex;\n align-items: center;\n gap: var(--spacing-2, 0.5rem);\n padding: calc(var(--spacing-1, 0.25rem) * 1.5) var(--spacing-3, 0.75rem);\n border: var(--stroke-width-thin, 1px) solid transparent;\n border-radius: var(--radius-full, 9999px);\n background: var(--doc-nav-pill-bg, var(--surface-card, #111827));\n font-family: var(--font-mono, ui-monospace, \"SFMono-Regular\", Menlo, monospace);\n font-size: var(--font-size-2xs, 0.6875rem);\n font-weight: var(--font-weight-medium, 500);\n letter-spacing: 0.05em;\n text-transform: uppercase;\n line-height: 1;\n white-space: nowrap;\n color: var(--text-secondary, #4b5563);\n text-decoration: none;\n cursor: pointer;\n transition: color var(--motion-duration-fast, 150ms)\n var(--motion-easing-standard, ease),\n border-color var(--motion-duration-fast, 150ms)\n var(--motion-easing-standard, ease),\n background-color var(--motion-duration-fast, 150ms)\n var(--motion-easing-standard, ease);\n}\n\n.pill:hover {\n color: var(--text-primary, #111827);\n border-color: var(--hairline, var(--border-default, #e5e7eb));\n}\n\n.pill:focus-visible {\n outline: var(--focus-ring-width, 2px) solid\n var(--border-focus, currentColor);\n outline-offset: var(--focus-ring-offset, 2px);\n}\n\n/* Shared-group pills carry the group's tint at rest (P4) — hover/active win. */\n.groupPinned .pill:not(.pillActive) {\n color: var(--doc-nav-group-accent, var(--info, #0ea5e9));\n}\n\n.groupPinned .pill:not(.pillActive):hover {\n color: var(--text-primary, #111827);\n}\n\n/* Active — the current doc, resolved from currentPath. Contrast-safe (VI-612):\n * the label is `--text-primary` (always legible), NOT raw `--doc-nav-accent`,\n * which is unreadable when a theme's accent is white/near-white (Blacklight, say)\n * on a light card. The active pill reads as active via a distinct opaque surface\n * plus an accent ring blended with a hairline so it never fully vanishes. */\n.pillActive {\n color: var(--text-primary, #111827);\n border-color: color-mix(\n in srgb,\n var(--doc-nav-accent, var(--accent, #2563eb)) 55%,\n var(--hairline, var(--border-default, #e5e7eb))\n );\n background: var(\n --surface-selected,\n color-mix(\n in srgb,\n var(--surface-card, #111827),\n var(--doc-nav-accent, var(--accent, #2563eb)) 14%\n )\n );\n}\n\n/* Hub — the group's overview entry gets a leading accent dot with a glow (N1).\n * `color` carries the accent so `currentColor` drives fill + glow together. */\n.pillHub::before {\n content: \"\";\n width: calc(var(--spacing-1, 0.25rem) * 1.25);\n height: calc(var(--spacing-1, 0.25rem) * 1.25);\n flex-shrink: 0;\n border-radius: var(--radius-full, 9999px);\n color: var(--doc-nav-accent, var(--accent, #2563eb));\n background: currentColor;\n box-shadow: 0 0 var(--spacing-2, 0.5rem)\n color-mix(in srgb, currentColor 60%, transparent);\n}\n\n/* Leading order number — mono, a step under the pill (B1). */\n.pillNum {\n font-family: var(--font-mono, ui-monospace, \"SFMono-Regular\", Menlo, monospace);\n font-size: calc(var(--font-size-xs, 0.75rem) * 0.8);\n font-variant-numeric: tabular-nums;\n color: var(--text-tertiary, #9ca3af);\n}\n\n.pillActive .pillNum {\n color: var(--doc-nav-accent, var(--accent, #2563eb));\n}\n\n/* Label text. */\n.pillLabel {\n min-width: 0;\n}\n\n/* External-link badge. */\n.pillExternal {\n flex-shrink: 0;\n color: var(--text-tertiary, #9ca3af);\n}\n\n/* Visually-hidden text for assistive technology. */\n.srOnly {\n position: absolute;\n width: var(--stroke-width-thin, 1px);\n height: var(--stroke-width-thin, 1px);\n padding: 0;\n margin: calc(-1 * var(--stroke-width-thin, 1px));\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n white-space: nowrap;\n border: 0;\n}\n"
2819
+ "content": "/* DocNav — manifest-driven, grouped/collapsible doc navigation.\n *\n * Renders peer, collapsible groups from a manifest slice: a pinned Shared set,\n * accordion product groups (one open at a time), and an Appendix bucket for\n * ad-hoc docs. The group row wraps (flex-wrap) and is NEVER an overflow-x\n * scroll strip — the run-off-the-edge defect this component exists to kill.\n *\n * Theme-agnostic: every value references a CSS custom property token.\n */\n\n/* Root — the wrapping row of peer groups. */\n.root {\n /* Accent-pop indirection (B2): the active pill / caret / hub / pinned frame\n * all route through this single token so a consumer (DocFrame) can retint the\n * whole nav in one place. Defaults to the theme's vivid `--accent` — not\n * `--primary`, which reads dull on muted-primary themes such as Strata. */\n --doc-nav-accent: var(--accent, #2563eb);\n /* Group cluster radius — a controlled, fixed radius the doc-nav owns, NOT the\n * theme `--radius-*` scale, which decorative themes inflate far past what a\n * dense nav cluster wants (for example Strata inflates `--radius-xl` to 32px).\n * The approved design pins ~12px per theme for exactly this reason; any single\n * theme radius token renders ~6px on some themes and ~32px on others.\n * Overridable by a consumer/theme via this variable. */\n --doc-nav-group-radius: 0.75rem;\n /* Resting pill fill — a recessed well, darker than the group's `--surface-card`\n * in BOTH modes. The surface ramp inverts light↔dark (page is darkest in dark\n * but lightest in light), so a single surface token can't stay \"below\" the card;\n * mixing the card toward neutral-950 darkens it directionally in either mode.\n * Overridable by a consumer/theme. */\n --doc-nav-pill-bg: color-mix(\n in srgb,\n var(--surface-card, #111827),\n var(--color-neutral-950, #030712) 20%\n );\n display: flex;\n flex-wrap: wrap;\n align-items: flex-start;\n gap: var(--spacing-2, 0.5rem);\n /* Deliberately no overflow-x: groups wrap down, never scroll sideways. */\n}\n\n/* Group — a bordered, surface-backed cluster: header + pill row. */\n.group {\n display: inline-flex;\n flex-direction: column;\n gap: var(--spacing-2, 0.5rem);\n padding: var(--spacing-2, 0.5rem);\n border: var(--stroke-width-thin, 1px) solid\n var(--hairline, var(--border-default, #e5e7eb));\n border-radius: var(--doc-nav-group-radius, var(--radius-md, 0.375rem));\n background: var(--surface-card, #ffffff);\n}\n\n/* Pinned — the Shared group stays open; a subtle frame keyed to the group hue.\n * Routed through overridable tokens (P5) so borderless themes (Animal / ENTR)\n * can null the frame — set `--doc-nav-pin-border: transparent` and\n * `--doc-nav-pin-bg: var(--surface-card)`. Default derives from the group's\n * shared hue, not `--primary` (which read as an unwanted border on those\n * borderless themes). */\n.groupPinned {\n border-color: var(\n --doc-nav-pin-border,\n color-mix(in srgb, var(--doc-nav-group-accent, var(--info, #0ea5e9)) 32%, transparent)\n );\n background: var(\n --doc-nav-pin-bg,\n color-mix(in srgb, var(--doc-nav-group-accent, var(--info, #0ea5e9)) 6%, var(--surface-card, #ffffff))\n );\n}\n\n/* Collapsed — a group reduces to a single pill-shaped chip. */\n.groupCollapsed {\n padding: 0;\n border-color: transparent;\n background: transparent;\n}\n\n/* Header — the group label row. As a chip when collapsed, plain when open. */\n.head {\n display: inline-flex;\n align-items: center;\n gap: var(--spacing-2, 0.5rem);\n padding: var(--spacing-1, 0.25rem) var(--spacing-2, 0.5rem);\n font-family: var(--font-mono, ui-monospace, \"SFMono-Regular\", Menlo, monospace);\n font-size: var(--font-size-2xs, 0.6875rem);\n font-weight: var(--font-weight-bold, 700);\n letter-spacing: 0.14em;\n text-transform: uppercase;\n /* Collapse the label's line box to the glyph height so the all-caps text\n * optically centers against the dot/caret (matching `.pill`). Without this the\n * caps ride high — the empty descender space pushes the line-box center below\n * the visual center of the caps. */\n line-height: 1;\n color: var(--text-secondary, #4b5563);\n}\n\n/* Button variant — collapsible group heads are clickable. */\n.headButton {\n cursor: pointer;\n border: 0;\n background: transparent;\n transition: color var(--motion-duration-fast, 150ms)\n var(--motion-easing-standard, ease);\n}\n\n.headButton:hover {\n color: var(--text-primary, #111827);\n}\n\n.headButton:focus-visible {\n outline: var(--focus-ring-width, 2px) solid\n var(--border-focus, currentColor);\n outline-offset: var(--focus-ring-offset, 2px);\n border-radius: var(--radius-sm, 0.25rem);\n}\n\n/* Collapsed group head — reads as a resting chip. */\n.groupCollapsed .head {\n border: var(--stroke-width-thin, 1px) solid\n var(--hairline, var(--border-default, #e5e7eb));\n border-radius: var(--radius-full, 9999px);\n /* A collapsed chip stands alone in the nav row, so it carries more vertical\n * padding than the tight open-group label (the design gives it ~7px 12px). */\n padding: var(--spacing-2, 0.5rem) var(--spacing-3, 0.75rem);\n /* The chip reads as the group's card surface (matching the design's chip-bg),\n * not a lighter subtle surface — `--surface-subtle` resolves as a mid-gray in\n * dark themes. */\n background: var(--surface-card, #111827);\n}\n\n/* Caret — accent-popped fill glyph (P6). */\n.caret {\n flex-shrink: 0;\n color: var(--doc-nav-accent, var(--accent, #2563eb));\n}\n\n/* Scope dot — a per-group grouping cue, color-coded with a soft glow (P1).\n * `color` carries the group hue so `currentColor` drives both the fill and the\n * glow; a consumer overrides the whole group via `--doc-nav-group-accent`.\n * Default (product groups) is the vivid accent; pinned/appendix retint below. */\n.scopeDot {\n width: var(--spacing-2, 0.5rem);\n height: var(--spacing-2, 0.5rem);\n flex-shrink: 0;\n border-radius: var(--radius-full, 9999px);\n color: var(--doc-nav-group-accent, var(--accent, #2563eb));\n background: currentColor;\n box-shadow: 0 0 var(--spacing-2, 0.5rem)\n color-mix(in srgb, currentColor 60%, transparent);\n}\n\n/* Shared (pinned) group reads in the info hue. */\n.groupPinned .scopeDot {\n color: var(--doc-nav-group-accent, var(--info, #0ea5e9));\n}\n\n/* Appendix reads muted and un-glowed — an ad-hoc bucket, not a product. */\n.group[data-role=\"appendix\"] .scopeDot {\n color: var(--doc-nav-group-accent, var(--text-tertiary, #9ca3af));\n box-shadow: none;\n}\n\n/* Group label text. */\n.groupLabel {\n min-width: 0;\n}\n\n/* Trailing count badge — a hairline mono pill on a collapsed group (N2). */\n.count {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n min-width: var(--spacing-4, 1rem);\n padding: 0 calc(var(--spacing-1, 0.25rem) * 1.5);\n border: var(--stroke-width-thin, 1px) solid\n var(--hairline, var(--border-default, #e5e7eb));\n border-radius: var(--radius-full, 9999px);\n font-family: var(--font-mono, ui-monospace, \"SFMono-Regular\", Menlo, monospace);\n /* ~9px — a quarter down from the xs step, matching the design's tiny badge. */\n font-size: calc(var(--font-size-xs, 0.75rem) * 0.75);\n font-variant-numeric: tabular-nums;\n color: var(--text-tertiary, #9ca3af);\n}\n\n/* Pill row — wraps within the group. */\n.pills {\n display: flex;\n flex-wrap: wrap;\n gap: var(--spacing-1, 0.25rem);\n}\n\n/* Pill — a single doc link. Mono · UPPERCASE · letter-spaced (B1). */\n.pill {\n display: inline-flex;\n align-items: center;\n gap: var(--spacing-2, 0.5rem);\n padding: calc(var(--spacing-1, 0.25rem) * 1.5) var(--spacing-3, 0.75rem);\n border: var(--stroke-width-thin, 1px) solid transparent;\n border-radius: var(--radius-full, 9999px);\n background: var(--doc-nav-pill-bg, var(--surface-card, #111827));\n font-family: var(--font-mono, ui-monospace, \"SFMono-Regular\", Menlo, monospace);\n font-size: var(--font-size-2xs, 0.6875rem);\n font-weight: var(--font-weight-medium, 500);\n letter-spacing: 0.05em;\n text-transform: uppercase;\n line-height: 1;\n white-space: nowrap;\n color: var(--text-secondary, #4b5563);\n text-decoration: none;\n cursor: pointer;\n transition: color var(--motion-duration-fast, 150ms)\n var(--motion-easing-standard, ease),\n border-color var(--motion-duration-fast, 150ms)\n var(--motion-easing-standard, ease),\n background-color var(--motion-duration-fast, 150ms)\n var(--motion-easing-standard, ease);\n}\n\n.pill:hover {\n color: var(--text-primary, #111827);\n border-color: var(--hairline, var(--border-default, #e5e7eb));\n}\n\n.pill:focus-visible {\n outline: var(--focus-ring-width, 2px) solid\n var(--border-focus, currentColor);\n outline-offset: var(--focus-ring-offset, 2px);\n}\n\n/* Shared-group pills carry the group's tint at rest (P4) — hover/active win. */\n.groupPinned .pill:not(.pillActive) {\n color: var(--doc-nav-group-accent, var(--info, #0ea5e9));\n}\n\n.groupPinned .pill:not(.pillActive):hover {\n color: var(--text-primary, #111827);\n}\n\n/* Active — the current doc, resolved from currentPath. Contrast-safe (VI-612):\n * the label is `--text-primary` (always legible), NOT raw `--doc-nav-accent`,\n * which is unreadable when a theme's accent is white/near-white (Blacklight, say)\n * on a light card. The active pill reads as active via a distinct opaque surface\n * plus an accent ring blended with a hairline so it never fully vanishes. */\n.pillActive {\n color: var(--text-primary, #111827);\n border-color: color-mix(\n in srgb,\n var(--doc-nav-accent, var(--accent, #2563eb)) 55%,\n var(--hairline, var(--border-default, #e5e7eb))\n );\n background: var(\n --surface-selected,\n color-mix(\n in srgb,\n var(--surface-card, #111827),\n var(--doc-nav-accent, var(--accent, #2563eb)) 14%\n )\n );\n}\n\n/* Hub — the group's overview entry gets a leading accent dot with a glow (N1).\n * `color` carries the accent so `currentColor` drives fill + glow together. */\n.pillHub::before {\n content: \"\";\n width: calc(var(--spacing-1, 0.25rem) * 1.25);\n height: calc(var(--spacing-1, 0.25rem) * 1.25);\n flex-shrink: 0;\n border-radius: var(--radius-full, 9999px);\n color: var(--doc-nav-accent, var(--accent, #2563eb));\n background: currentColor;\n box-shadow: 0 0 var(--spacing-2, 0.5rem)\n color-mix(in srgb, currentColor 60%, transparent);\n}\n\n/* Leading order number — mono, a step under the pill (B1). */\n.pillNum {\n font-family: var(--font-mono, ui-monospace, \"SFMono-Regular\", Menlo, monospace);\n font-size: calc(var(--font-size-xs, 0.75rem) * 0.8);\n font-variant-numeric: tabular-nums;\n color: var(--text-tertiary, #9ca3af);\n}\n\n.pillActive .pillNum {\n color: var(--doc-nav-accent, var(--accent, #2563eb));\n}\n\n/* Label text. */\n.pillLabel {\n min-width: 0;\n}\n\n/* External-link badge. */\n.pillExternal {\n flex-shrink: 0;\n color: var(--text-tertiary, #9ca3af);\n}\n\n/* Visually-hidden text for assistive technology. */\n.srOnly {\n position: absolute;\n width: var(--stroke-width-thin, 1px);\n height: var(--stroke-width-thin, 1px);\n padding: 0;\n margin: calc(-1 * var(--stroke-width-thin, 1px));\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n white-space: nowrap;\n border: 0;\n}\n"
2820
2820
  }
2821
2821
  ]
2822
2822
  },
@@ -2867,7 +2867,7 @@
2867
2867
  {
2868
2868
  "path": "components/ui/fidelity-mirror/fidelity-mirror.module.css",
2869
2869
  "type": "registry:ui",
2870
- "content": "/* FidelityMirror — the design-left / built-right comparison surface.\n *\n * Renders the pure DESIGN source (left) beside the BUILT render (right) in\n * recessed capture wells, with a verdict/diff indicator, numbered delta\n * callouts, a classed delta legend, and a drag-to-reveal overlay mode. Composes\n * inside DocFrame's content, and goes full-bleed on widescreen so each pane is\n * ~50vw (the compare is meant for fullscreen monitors).\n *\n * Theme-agnostic: every value references a Visor token. The card/cluster radius\n * and the recessed well fill are component-OWNED (fixed) tokens, NOT the theme\n * `--radius-*` scale or a bare `--surface-*` token — decorative themes inflate\n * `--radius-xl` to 32px and lift `--surface-subtle` ABOVE the card in dark mode,\n * which is precisely the drift this component exists to surface.\n */\n\n/* Root — the framed compare. */\n.root {\n /* Fixed cluster radius the component OWNS — NOT the theme `--radius-*` scale,\n * which decorative themes inflate far past what a dense compare cluster wants\n * (Space inflates `--radius-xl` to 32px). Overridable by a consumer/theme. */\n --fm-radius: 0.75rem;\n --fm-well-radius: 0.625rem;\n /* Widescreen gutter/padding — the outer left/right padding AND the center\n * gutter resolve to the SAME value, so each pane is ~50vw: (100vw - 3*pad)/2. */\n --fm-pad: clamp(1.25rem, 3.2vw, 3.5rem);\n /* Recessed well fill — darker than `--surface-card` in BOTH modes (the DocNav\n * pill-bg convention). The surface ramp inverts light<->dark, so a single\n * surface token can't stay \"below\" the card; mixing the card toward\n * neutral-950 darkens it directionally in either mode. Overridable. */\n --fm-well: color-mix(\n in srgb,\n var(--surface-card, #111827),\n var(--color-neutral-950, #030712) 22%\n );\n /* Source identity hues (kept across split + overlay): design = info, built =\n * accent. These carry SOURCE identity, not decoration — do not retint. */\n --fm-design-hue: var(--info, #0ea5e9);\n --fm-built-hue: var(--accent, #2563eb);\n\n display: flex;\n flex-direction: column;\n border: var(--stroke-width-thin, 1px) solid var(--hairline, #e5e7eb);\n border-radius: var(--fm-radius);\n background: var(--surface-card, #ffffff);\n box-shadow: var(--shadow-md);\n overflow: hidden;\n font-family: var(--font-sans, system-ui, sans-serif);\n}\n\n/* Widescreen full-bleed — escape DocFrame's centered column and span the\n * viewport. Header + legend align to the panes' outer edge via `--fm-pad`; the\n * panes grid uses `gap: var(--fm-pad)` so each column resolves to ~50vw. */\n.bleed {\n width: 100vw;\n margin-left: calc(50% - 50vw);\n border-radius: 0;\n border-inline: 0;\n}\n.bleed .bar {\n padding-inline: var(--fm-pad);\n}\n.bleed .panes {\n padding-inline: var(--fm-pad);\n gap: var(--fm-pad);\n}\n.bleed .legend {\n padding-inline: var(--fm-pad);\n}\n.bleed .overlay {\n padding-inline: var(--fm-pad);\n}\n\n/* ── Header bar ──────────────────────────────────────────────────────────── */\n.bar {\n display: flex;\n align-items: center;\n gap: var(--spacing-3, 0.75rem);\n flex-wrap: wrap;\n padding: var(--spacing-3, 0.75rem) var(--spacing-4, 1rem);\n border-bottom: var(--stroke-width-thin, 1px) solid var(--hairline, #e5e7eb);\n}\n.titleWrap {\n display: inline-flex;\n flex-direction: column;\n gap: calc(var(--spacing-1, 0.25rem) * 1.5);\n min-width: 0;\n}\n.title {\n font-family: var(--font-mono, ui-monospace, \"SFMono-Regular\", Menlo, monospace);\n font-size: var(--font-size-sm, 0.8125rem);\n font-weight: var(--font-weight-bold, 700);\n letter-spacing: 0.02em;\n line-height: 1;\n color: var(--text-primary, #111827);\n}\n.subtitle {\n font-family: var(--font-mono, ui-monospace, \"SFMono-Regular\", Menlo, monospace);\n font-size: var(--font-size-2xs, 0.6875rem);\n font-weight: var(--font-weight-medium, 500);\n letter-spacing: 0.12em;\n text-transform: uppercase;\n line-height: 1;\n color: var(--text-tertiary, #9ca3af);\n}\n\n/* Spacer — pushes the status + toggle to the right edge. */\n.spacer {\n flex: 1 1 auto;\n}\n\n/* Platform chip — mono caps pill, hairline, card bg. */\n.chip {\n display: inline-flex;\n align-items: center;\n gap: var(--spacing-2, 0.5rem);\n padding: calc(var(--spacing-1, 0.25rem) * 1.25) var(--spacing-3, 0.75rem);\n border: var(--stroke-width-thin, 1px) solid var(--hairline, #e5e7eb);\n border-radius: var(--radius-full, 9999px);\n background: var(--surface-card, #ffffff);\n font-family: var(--font-mono, ui-monospace, \"SFMono-Regular\", Menlo, monospace);\n font-size: var(--font-size-2xs, 0.6875rem);\n font-weight: var(--font-weight-medium, 500);\n letter-spacing: 0.06em;\n line-height: 1;\n text-transform: uppercase;\n white-space: nowrap;\n color: var(--text-secondary, #4b5563);\n}\n.chipDot {\n width: 0.375rem;\n height: 0.375rem;\n border-radius: var(--radius-full, 9999px);\n background: var(--success, #22c55e);\n box-shadow: 0 0 0.375rem color-mix(in srgb, var(--success, #22c55e) 70%, transparent);\n}\n.chipIcon {\n width: 0.75rem;\n height: 0.75rem;\n color: var(--text-tertiary, #9ca3af);\n}\n\n/* Status pill — the diff indicator, tinted by verdict. */\n.status {\n display: inline-flex;\n align-items: center;\n gap: var(--spacing-2, 0.5rem);\n padding: calc(var(--spacing-1, 0.25rem) * 1.25) var(--spacing-3, 0.75rem);\n border: var(--stroke-width-thin, 1px) solid transparent;\n border-radius: var(--radius-full, 9999px);\n font-family: var(--font-mono, ui-monospace, \"SFMono-Regular\", Menlo, monospace);\n font-size: var(--font-size-2xs, 0.6875rem);\n font-weight: var(--font-weight-bold, 700);\n letter-spacing: 0.08em;\n line-height: 1;\n text-transform: uppercase;\n white-space: nowrap;\n}\n.status[data-verdict=\"match\"] {\n color: var(--success, #22c55e);\n border-color: color-mix(in srgb, var(--success, #22c55e) 40%, transparent);\n background: color-mix(in srgb, var(--success, #22c55e) 12%, var(--surface-card, #ffffff));\n}\n.status[data-verdict=\"drift\"] {\n color: var(--warning, #f59e0b);\n border-color: color-mix(in srgb, var(--warning, #f59e0b) 42%, transparent);\n background: color-mix(in srgb, var(--warning, #f59e0b) 12%, var(--surface-card, #ffffff));\n}\n.status[data-verdict=\"fail\"] {\n color: var(--destructive, #ef4444);\n border-color: color-mix(in srgb, var(--destructive, #ef4444) 42%, transparent);\n background: color-mix(in srgb, var(--destructive, #ef4444) 12%, var(--surface-card, #ffffff));\n}\n.statusGlyph {\n width: 0.625rem;\n height: 0.625rem;\n border-radius: var(--radius-full, 9999px);\n background: currentColor;\n box-shadow: 0 0 0.4375rem currentColor;\n}\n.score {\n font-variant-numeric: tabular-nums;\n letter-spacing: 0.02em;\n opacity: var(--opacity-80, 0.85);\n}\n\n/* Segmented compare-mode toggle — split / overlay. */\n.seg {\n display: inline-flex;\n gap: calc(var(--spacing-1, 0.25rem) * 0.5);\n padding: calc(var(--spacing-1, 0.25rem) * 0.75);\n border: var(--stroke-width-thin, 1px) solid var(--hairline, #e5e7eb);\n border-radius: var(--radius-full, 9999px);\n background: var(--fm-well);\n}\n.segBtn {\n display: inline-flex;\n align-items: center;\n gap: var(--spacing-2, 0.5rem);\n padding: calc(var(--spacing-1, 0.25rem) * 1.25) calc(var(--spacing-1, 0.25rem) * 2.5);\n border: 0;\n border-radius: var(--radius-full, 9999px);\n background: transparent;\n font-family: var(--font-mono, ui-monospace, \"SFMono-Regular\", Menlo, monospace);\n font-size: var(--font-size-2xs, 0.6875rem);\n font-weight: var(--font-weight-medium, 500);\n letter-spacing: 0.06em;\n text-transform: uppercase;\n line-height: 1;\n color: var(--text-tertiary, #9ca3af);\n cursor: pointer;\n transition: color var(--motion-duration-fast, 150ms) var(--motion-easing-standard, ease),\n background-color var(--motion-duration-fast, 150ms) var(--motion-easing-standard, ease);\n}\n.segIcon {\n width: 0.8125rem;\n height: 0.8125rem;\n}\n.segBtn[aria-pressed=\"true\"] {\n color: var(--text-primary, #111827);\n background: var(--surface-card, #ffffff);\n box-shadow: var(--shadow-md);\n}\n.segBtn:focus-visible {\n outline: var(--focus-ring-width, 2px) solid var(--border-focus, currentColor);\n outline-offset: var(--focus-ring-offset, 2px);\n}\n\n/* ── Panes: side-by-side ─────────────────────────────────────────────────── */\n.panes {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: var(--spacing-4, 1rem);\n padding: var(--spacing-4, 1rem);\n align-items: start;\n}\n.pane {\n display: flex;\n flex-direction: column;\n gap: var(--spacing-2, 0.5rem);\n min-width: 0;\n}\n.paneLabel {\n display: inline-flex;\n align-items: center;\n gap: var(--spacing-2, 0.5rem);\n font-family: var(--font-mono, ui-monospace, \"SFMono-Regular\", Menlo, monospace);\n font-size: var(--font-size-2xs, 0.6875rem);\n font-weight: var(--font-weight-bold, 700);\n letter-spacing: 0.14em;\n text-transform: uppercase;\n line-height: 1;\n color: var(--text-secondary, #4b5563);\n}\n.scopeDot {\n width: 0.5rem;\n height: 0.5rem;\n flex-shrink: 0;\n border-radius: var(--radius-full, 9999px);\n background: currentColor;\n box-shadow: 0 0 0.5rem color-mix(in srgb, currentColor 60%, transparent);\n}\n.pane[data-side=\"design\"] .scopeDot {\n color: var(--fm-design-hue);\n}\n.pane[data-side=\"built\"] .scopeDot {\n color: var(--fm-built-hue);\n}\n.paneMeta {\n margin-left: auto;\n color: var(--text-tertiary, #9ca3af);\n letter-spacing: 0.1em;\n font-weight: var(--font-weight-medium, 500);\n}\n\n/* Capture well — the recessed frame that holds a captured surface. */\n.well {\n position: relative;\n border: var(--stroke-width-thin, 1px) solid var(--hairline, #e5e7eb);\n border-radius: var(--fm-well-radius);\n background: var(--fm-well);\n padding: var(--spacing-3, 0.75rem);\n overflow: hidden;\n}\n.pane[data-side=\"built\"] .well {\n box-shadow: inset 0 0 0 var(--stroke-width-thin, 1px)\n color-mix(in srgb, var(--fm-built-hue) 22%, transparent);\n}\n\n/* Captured media — an image or a live-route/external iframe fills the well. */\n.media {\n display: block;\n width: 100%;\n height: auto;\n border: 0;\n border-radius: calc(var(--fm-well-radius) - 0.25rem);\n}\n\n/* Device bezel — native / flutter screenshots read inside a subtle frame. */\n.bezel {\n width: 10.5rem;\n margin: 0 auto;\n border: 0.375rem solid color-mix(in srgb, var(--text-primary, #111827) 78%, transparent);\n border-radius: 1.625rem;\n overflow: hidden;\n background: var(--surface-page, #ffffff);\n box-shadow: var(--shadow-lg);\n}\n.bezel .media {\n border-radius: 0;\n}\n\n/* Delta callout marker — a numbered accent dot pinned over a drift location. */\n.delta {\n position: absolute;\n z-index: 3;\n display: grid;\n place-items: center;\n width: 1.25rem;\n height: 1.25rem;\n border-radius: var(--radius-full, 9999px);\n background: var(--warning, #f59e0b);\n color: var(--color-neutral-950, #030712);\n font-family: var(--font-mono, ui-monospace, \"SFMono-Regular\", Menlo, monospace);\n font-size: var(--font-size-2xs, 0.6875rem);\n font-weight: var(--font-weight-bold, 700);\n line-height: 1;\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--warning, #f59e0b) 30%, transparent),\n var(--shadow-md);\n}\n\n/* ── Overlay / slider mode ───────────────────────────────────────────────── */\n.overlay {\n position: relative;\n padding: var(--spacing-4, 1rem);\n}\n.overlayFrame {\n position: relative;\n border: var(--stroke-width-thin, 1px) solid var(--hairline, #e5e7eb);\n border-radius: var(--fm-well-radius);\n background: var(--fm-well);\n overflow: hidden;\n}\n.layer {\n padding: var(--spacing-3, 0.75rem);\n}\n/* Clear space below the corner ribbons so they never collide with content. */\n.overlayFrame .layer {\n padding-top: var(--spacing-10, 2.5rem);\n}\n.layerTop {\n position: absolute;\n inset: 0;\n /* Revealed portion driven by `--fm-split` (design shows on the left). */\n clip-path: inset(0 calc(100% - var(--fm-split, 55%)) 0 0);\n}\n.handle {\n position: absolute;\n top: 0;\n bottom: 0;\n left: var(--fm-split, 55%);\n width: 2px;\n background: var(--accent, #2563eb);\n box-shadow: 0 0 0.625rem color-mix(in srgb, var(--accent, #2563eb) 70%, transparent);\n z-index: 4;\n}\n.grip {\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n display: grid;\n place-items: center;\n width: 1.75rem;\n height: 1.75rem;\n border-radius: var(--radius-full, 9999px);\n background: var(--accent, #2563eb);\n color: var(--color-white, #ffffff);\n box-shadow: 0 0 0 4px color-mix(in srgb, var(--accent, #2563eb) 26%, transparent),\n var(--shadow-md);\n}\n.gripIcon {\n width: 0.9375rem;\n height: 0.9375rem;\n}\n.ribbon {\n position: absolute;\n z-index: 5;\n top: var(--spacing-3, 0.75rem);\n padding: var(--spacing-1, 0.25rem) var(--spacing-2, 0.5rem);\n border-radius: var(--radius-full, 9999px);\n font-family: var(--font-mono, ui-monospace, \"SFMono-Regular\", Menlo, monospace);\n font-size: calc(var(--font-size-2xs, 0.6875rem) * 0.9);\n font-weight: var(--font-weight-bold, 700);\n letter-spacing: 0.12em;\n text-transform: uppercase;\n line-height: 1;\n color: var(--color-white, #ffffff);\n}\n.ribbon[data-side=\"design\"] {\n left: var(--spacing-3, 0.75rem);\n background: color-mix(in srgb, var(--fm-design-hue) 85%, var(--color-neutral-950, #030712));\n}\n.ribbon[data-side=\"built\"] {\n right: var(--spacing-3, 0.75rem);\n background: color-mix(in srgb, var(--fm-built-hue) 85%, var(--color-neutral-950, #030712));\n}\n.range {\n width: 100%;\n margin-top: var(--spacing-3, 0.75rem);\n accent-color: var(--accent, #2563eb);\n cursor: ew-resize;\n}\n.range:focus-visible {\n outline: var(--focus-ring-width, 2px) solid var(--border-focus, currentColor);\n outline-offset: var(--focus-ring-offset, 2px);\n}\n\n/* ── Delta legend ────────────────────────────────────────────────────────── */\n.legend {\n display: flex;\n flex-direction: column;\n gap: var(--spacing-2, 0.5rem);\n padding: var(--spacing-3, 0.75rem) var(--spacing-4, 1rem);\n border-top: var(--stroke-width-thin, 1px) solid var(--hairline, #e5e7eb);\n}\n.legendHead {\n font-family: var(--font-mono, ui-monospace, \"SFMono-Regular\", Menlo, monospace);\n font-size: var(--font-size-2xs, 0.6875rem);\n font-weight: var(--font-weight-bold, 700);\n letter-spacing: 0.14em;\n text-transform: uppercase;\n color: var(--text-tertiary, #9ca3af);\n}\n.legendRow {\n display: flex;\n align-items: center;\n gap: var(--spacing-3, 0.75rem);\n}\n.legendNum {\n flex-shrink: 0;\n display: grid;\n place-items: center;\n width: 1.125rem;\n height: 1.125rem;\n border-radius: var(--radius-full, 9999px);\n background: var(--warning, #f59e0b);\n color: var(--color-neutral-950, #030712);\n font-family: var(--font-mono, ui-monospace, \"SFMono-Regular\", Menlo, monospace);\n font-size: calc(var(--font-size-2xs, 0.6875rem) * 0.9);\n font-weight: var(--font-weight-bold, 700);\n}\n.tag {\n flex-shrink: 0;\n padding: calc(var(--spacing-1, 0.25rem) * 0.75) var(--spacing-2, 0.5rem);\n border: var(--stroke-width-thin, 1px) solid var(--hairline, #e5e7eb);\n border-radius: var(--radius-sm, 0.25rem);\n background: var(--surface-subtle, #f3f4f6);\n font-family: var(--font-mono, ui-monospace, \"SFMono-Regular\", Menlo, monospace);\n font-size: calc(var(--font-size-2xs, 0.6875rem) * 0.9);\n font-weight: var(--font-weight-bold, 700);\n letter-spacing: 0.08em;\n text-transform: uppercase;\n color: var(--text-secondary, #4b5563);\n}\n.legendText {\n font-family: var(--font-mono, ui-monospace, \"SFMono-Regular\", Menlo, monospace);\n font-size: var(--font-size-sm, 0.8125rem);\n color: var(--text-secondary, #4b5563);\n}\n.legendText b {\n color: var(--text-primary, #111827);\n font-weight: var(--font-weight-bold, 700);\n}\n\n/* Visually-hidden text for assistive technology. */\n.srOnly {\n position: absolute;\n width: var(--stroke-width-thin, 1px);\n height: var(--stroke-width-thin, 1px);\n padding: 0;\n margin: calc(-1 * var(--stroke-width-thin, 1px));\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n white-space: nowrap;\n border: 0;\n}\n\n/* Responsive: panes stack under 768px (design over built) — NEVER a sideways\n * scroll strip (the defect the doc-set surfaces exist to kill). */\n@media (max-width: 767px) {\n .panes {\n grid-template-columns: 1fr;\n }\n .bar {\n gap: var(--spacing-2, 0.5rem);\n }\n}\n"
2870
+ "content": "/* FidelityMirror — the design-left / built-right comparison surface.\n *\n * Renders the pure DESIGN source (left) beside the BUILT render (right) in\n * recessed capture wells, with a verdict/diff indicator, numbered delta\n * callouts, a classed delta legend, and a drag-to-reveal overlay mode. Composes\n * inside DocFrame's content, and goes full-bleed on widescreen so each pane is\n * ~50vw (the compare is meant for fullscreen monitors).\n *\n * Theme-agnostic: every value references a Visor token. The card/cluster radius\n * and the recessed well fill are component-OWNED (fixed) tokens, NOT the theme\n * `--radius-*` scale or a bare `--surface-*` token — decorative themes inflate\n * `--radius-xl` to 32px and lift `--surface-subtle` ABOVE the card in dark mode,\n * which is precisely the drift this component exists to surface.\n */\n\n/* Root — the framed compare. */\n.root {\n /* Fixed cluster radius the component OWNS — NOT the theme `--radius-*` scale,\n * which decorative themes inflate far past what a dense compare cluster wants\n * (Space inflates `--radius-xl` to 32px). Overridable by a consumer/theme. */\n --fm-radius: 0.75rem;\n --fm-well-radius: 0.625rem;\n /* Widescreen gutter/padding — the outer left/right padding AND the center\n * gutter resolve to the SAME value, so each pane is ~50vw: (100vw - 3*pad)/2. */\n --fm-pad: clamp(1.25rem, 3.2vw, 3.5rem);\n /* Recessed well fill — darker than `--surface-card` in BOTH modes (the DocNav\n * pill-bg convention). The surface ramp inverts light<->dark, so a single\n * surface token can't stay \"below\" the card; mixing the card toward\n * neutral-950 darkens it directionally in either mode. Overridable. */\n --fm-well: color-mix(\n in srgb,\n var(--surface-card, #111827),\n var(--color-neutral-950, #030712) 22%\n );\n /* Source identity hues (kept across split + overlay): design = info, built =\n * accent. These carry SOURCE identity, not decoration — do not retint. */\n --fm-design-hue: var(--info, #0ea5e9);\n --fm-built-hue: var(--accent, #2563eb);\n\n display: flex;\n flex-direction: column;\n border: var(--stroke-width-thin, 1px) solid var(--hairline, #e5e7eb);\n border-radius: var(--fm-radius);\n background: var(--surface-card, #ffffff);\n box-shadow: var(--shadow-md);\n overflow: hidden;\n font-family: var(--font-sans, inherit);\n}\n\n/* Widescreen full-bleed — escape DocFrame's centered column and span the\n * viewport. Header + legend align to the panes' outer edge via `--fm-pad`; the\n * panes grid uses `gap: var(--fm-pad)` so each column resolves to ~50vw. */\n.bleed {\n width: 100vw;\n margin-left: calc(50% - 50vw);\n border-radius: 0;\n border-inline: 0;\n}\n.bleed .bar {\n padding-inline: var(--fm-pad);\n}\n.bleed .panes {\n padding-inline: var(--fm-pad);\n gap: var(--fm-pad);\n}\n.bleed .legend {\n padding-inline: var(--fm-pad);\n}\n.bleed .overlay {\n padding-inline: var(--fm-pad);\n}\n\n/* ── Header bar ──────────────────────────────────────────────────────────── */\n.bar {\n display: flex;\n align-items: center;\n gap: var(--spacing-3, 0.75rem);\n flex-wrap: wrap;\n padding: var(--spacing-3, 0.75rem) var(--spacing-4, 1rem);\n border-bottom: var(--stroke-width-thin, 1px) solid var(--hairline, #e5e7eb);\n}\n.titleWrap {\n display: inline-flex;\n flex-direction: column;\n gap: calc(var(--spacing-1, 0.25rem) * 1.5);\n min-width: 0;\n}\n.title {\n font-family: var(--font-mono, ui-monospace, \"SFMono-Regular\", Menlo, monospace);\n font-size: var(--font-size-sm, 0.8125rem);\n font-weight: var(--font-weight-bold, 700);\n letter-spacing: 0.02em;\n line-height: 1;\n color: var(--text-primary, #111827);\n}\n.subtitle {\n font-family: var(--font-mono, ui-monospace, \"SFMono-Regular\", Menlo, monospace);\n font-size: var(--font-size-2xs, 0.6875rem);\n font-weight: var(--font-weight-medium, 500);\n letter-spacing: 0.12em;\n text-transform: uppercase;\n line-height: 1;\n color: var(--text-tertiary, #9ca3af);\n}\n\n/* Spacer — pushes the status + toggle to the right edge. */\n.spacer {\n flex: 1 1 auto;\n}\n\n/* Platform chip — mono caps pill, hairline, card bg. */\n.chip {\n display: inline-flex;\n align-items: center;\n gap: var(--spacing-2, 0.5rem);\n padding: calc(var(--spacing-1, 0.25rem) * 1.25) var(--spacing-3, 0.75rem);\n border: var(--stroke-width-thin, 1px) solid var(--hairline, #e5e7eb);\n border-radius: var(--radius-full, 9999px);\n background: var(--surface-card, #ffffff);\n font-family: var(--font-mono, ui-monospace, \"SFMono-Regular\", Menlo, monospace);\n font-size: var(--font-size-2xs, 0.6875rem);\n font-weight: var(--font-weight-medium, 500);\n letter-spacing: 0.06em;\n line-height: 1;\n text-transform: uppercase;\n white-space: nowrap;\n color: var(--text-secondary, #4b5563);\n}\n.chipDot {\n width: 0.375rem;\n height: 0.375rem;\n border-radius: var(--radius-full, 9999px);\n background: var(--success, #22c55e);\n box-shadow: 0 0 0.375rem color-mix(in srgb, var(--success, #22c55e) 70%, transparent);\n}\n.chipIcon {\n width: 0.75rem;\n height: 0.75rem;\n color: var(--text-tertiary, #9ca3af);\n}\n\n/* Status pill — the diff indicator, tinted by verdict. */\n.status {\n display: inline-flex;\n align-items: center;\n gap: var(--spacing-2, 0.5rem);\n padding: calc(var(--spacing-1, 0.25rem) * 1.25) var(--spacing-3, 0.75rem);\n border: var(--stroke-width-thin, 1px) solid transparent;\n border-radius: var(--radius-full, 9999px);\n font-family: var(--font-mono, ui-monospace, \"SFMono-Regular\", Menlo, monospace);\n font-size: var(--font-size-2xs, 0.6875rem);\n font-weight: var(--font-weight-bold, 700);\n letter-spacing: 0.08em;\n line-height: 1;\n text-transform: uppercase;\n white-space: nowrap;\n}\n.status[data-verdict=\"match\"] {\n color: var(--success, #22c55e);\n border-color: color-mix(in srgb, var(--success, #22c55e) 40%, transparent);\n background: color-mix(in srgb, var(--success, #22c55e) 12%, var(--surface-card, #ffffff));\n}\n.status[data-verdict=\"drift\"] {\n color: var(--warning, #f59e0b);\n border-color: color-mix(in srgb, var(--warning, #f59e0b) 42%, transparent);\n background: color-mix(in srgb, var(--warning, #f59e0b) 12%, var(--surface-card, #ffffff));\n}\n.status[data-verdict=\"fail\"] {\n color: var(--destructive, #ef4444);\n border-color: color-mix(in srgb, var(--destructive, #ef4444) 42%, transparent);\n background: color-mix(in srgb, var(--destructive, #ef4444) 12%, var(--surface-card, #ffffff));\n}\n.statusGlyph {\n width: 0.625rem;\n height: 0.625rem;\n border-radius: var(--radius-full, 9999px);\n background: currentColor;\n box-shadow: 0 0 0.4375rem currentColor;\n}\n.score {\n font-variant-numeric: tabular-nums;\n letter-spacing: 0.02em;\n opacity: var(--opacity-80, 0.85);\n}\n\n/* Segmented compare-mode toggle — split / overlay. */\n.seg {\n display: inline-flex;\n gap: calc(var(--spacing-1, 0.25rem) * 0.5);\n padding: calc(var(--spacing-1, 0.25rem) * 0.75);\n border: var(--stroke-width-thin, 1px) solid var(--hairline, #e5e7eb);\n border-radius: var(--radius-full, 9999px);\n background: var(--fm-well);\n}\n.segBtn {\n display: inline-flex;\n align-items: center;\n gap: var(--spacing-2, 0.5rem);\n padding: calc(var(--spacing-1, 0.25rem) * 1.25) calc(var(--spacing-1, 0.25rem) * 2.5);\n border: 0;\n border-radius: var(--radius-full, 9999px);\n background: transparent;\n font-family: var(--font-mono, ui-monospace, \"SFMono-Regular\", Menlo, monospace);\n font-size: var(--font-size-2xs, 0.6875rem);\n font-weight: var(--font-weight-medium, 500);\n letter-spacing: 0.06em;\n text-transform: uppercase;\n line-height: 1;\n color: var(--text-tertiary, #9ca3af);\n cursor: pointer;\n transition: color var(--motion-duration-fast, 150ms) var(--motion-easing-standard, ease),\n background-color var(--motion-duration-fast, 150ms) var(--motion-easing-standard, ease);\n}\n.segIcon {\n width: 0.8125rem;\n height: 0.8125rem;\n}\n.segBtn[aria-pressed=\"true\"] {\n color: var(--text-primary, #111827);\n background: var(--surface-card, #ffffff);\n box-shadow: var(--shadow-md);\n}\n.segBtn:focus-visible {\n outline: var(--focus-ring-width, 2px) solid var(--border-focus, currentColor);\n outline-offset: var(--focus-ring-offset, 2px);\n}\n\n/* ── Panes: side-by-side ─────────────────────────────────────────────────── */\n.panes {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: var(--spacing-4, 1rem);\n padding: var(--spacing-4, 1rem);\n align-items: start;\n}\n.pane {\n display: flex;\n flex-direction: column;\n gap: var(--spacing-2, 0.5rem);\n min-width: 0;\n}\n.paneLabel {\n display: inline-flex;\n align-items: center;\n gap: var(--spacing-2, 0.5rem);\n font-family: var(--font-mono, ui-monospace, \"SFMono-Regular\", Menlo, monospace);\n font-size: var(--font-size-2xs, 0.6875rem);\n font-weight: var(--font-weight-bold, 700);\n letter-spacing: 0.14em;\n text-transform: uppercase;\n line-height: 1;\n color: var(--text-secondary, #4b5563);\n}\n.scopeDot {\n width: 0.5rem;\n height: 0.5rem;\n flex-shrink: 0;\n border-radius: var(--radius-full, 9999px);\n background: currentColor;\n box-shadow: 0 0 0.5rem color-mix(in srgb, currentColor 60%, transparent);\n}\n.pane[data-side=\"design\"] .scopeDot {\n color: var(--fm-design-hue);\n}\n.pane[data-side=\"built\"] .scopeDot {\n color: var(--fm-built-hue);\n}\n.paneMeta {\n margin-left: auto;\n color: var(--text-tertiary, #9ca3af);\n letter-spacing: 0.1em;\n font-weight: var(--font-weight-medium, 500);\n}\n\n/* Capture well — the recessed frame that holds a captured surface. */\n.well {\n position: relative;\n border: var(--stroke-width-thin, 1px) solid var(--hairline, #e5e7eb);\n border-radius: var(--fm-well-radius);\n background: var(--fm-well);\n padding: var(--spacing-3, 0.75rem);\n overflow: hidden;\n}\n.pane[data-side=\"built\"] .well {\n box-shadow: inset 0 0 0 var(--stroke-width-thin, 1px)\n color-mix(in srgb, var(--fm-built-hue) 22%, transparent);\n}\n\n/* Captured media — an image or a live-route/external iframe fills the well. */\n.media {\n display: block;\n width: 100%;\n height: auto;\n border: 0;\n border-radius: calc(var(--fm-well-radius) - 0.25rem);\n}\n\n/* Device bezel — native / flutter screenshots read inside a subtle frame. */\n.bezel {\n width: 10.5rem;\n margin: 0 auto;\n border: 0.375rem solid color-mix(in srgb, var(--text-primary, #111827) 78%, transparent);\n border-radius: 1.625rem;\n overflow: hidden;\n background: var(--surface-page, #ffffff);\n box-shadow: var(--shadow-lg);\n}\n.bezel .media {\n border-radius: 0;\n}\n\n/* Delta callout marker — a numbered accent dot pinned over a drift location. */\n.delta {\n position: absolute;\n z-index: 3;\n display: grid;\n place-items: center;\n width: 1.25rem;\n height: 1.25rem;\n border-radius: var(--radius-full, 9999px);\n background: var(--warning, #f59e0b);\n color: var(--color-neutral-950, #030712);\n font-family: var(--font-mono, ui-monospace, \"SFMono-Regular\", Menlo, monospace);\n font-size: var(--font-size-2xs, 0.6875rem);\n font-weight: var(--font-weight-bold, 700);\n line-height: 1;\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--warning, #f59e0b) 30%, transparent),\n var(--shadow-md);\n}\n\n/* ── Overlay / slider mode ───────────────────────────────────────────────── */\n.overlay {\n position: relative;\n padding: var(--spacing-4, 1rem);\n}\n.overlayFrame {\n position: relative;\n border: var(--stroke-width-thin, 1px) solid var(--hairline, #e5e7eb);\n border-radius: var(--fm-well-radius);\n background: var(--fm-well);\n overflow: hidden;\n}\n.layer {\n padding: var(--spacing-3, 0.75rem);\n}\n/* Clear space below the corner ribbons so they never collide with content. */\n.overlayFrame .layer {\n padding-top: var(--spacing-10, 2.5rem);\n}\n.layerTop {\n position: absolute;\n inset: 0;\n /* Revealed portion driven by `--fm-split` (design shows on the left). */\n clip-path: inset(0 calc(100% - var(--fm-split, 55%)) 0 0);\n}\n.handle {\n position: absolute;\n top: 0;\n bottom: 0;\n left: var(--fm-split, 55%);\n width: 2px;\n background: var(--accent, #2563eb);\n box-shadow: 0 0 0.625rem color-mix(in srgb, var(--accent, #2563eb) 70%, transparent);\n z-index: 4;\n}\n.grip {\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n display: grid;\n place-items: center;\n width: 1.75rem;\n height: 1.75rem;\n border-radius: var(--radius-full, 9999px);\n background: var(--accent, #2563eb);\n color: var(--color-white, #ffffff);\n box-shadow: 0 0 0 4px color-mix(in srgb, var(--accent, #2563eb) 26%, transparent),\n var(--shadow-md);\n}\n.gripIcon {\n width: 0.9375rem;\n height: 0.9375rem;\n}\n.ribbon {\n position: absolute;\n z-index: 5;\n top: var(--spacing-3, 0.75rem);\n padding: var(--spacing-1, 0.25rem) var(--spacing-2, 0.5rem);\n border-radius: var(--radius-full, 9999px);\n font-family: var(--font-mono, ui-monospace, \"SFMono-Regular\", Menlo, monospace);\n font-size: calc(var(--font-size-2xs, 0.6875rem) * 0.9);\n font-weight: var(--font-weight-bold, 700);\n letter-spacing: 0.12em;\n text-transform: uppercase;\n line-height: 1;\n color: var(--color-white, #ffffff);\n}\n.ribbon[data-side=\"design\"] {\n left: var(--spacing-3, 0.75rem);\n background: color-mix(in srgb, var(--fm-design-hue) 85%, var(--color-neutral-950, #030712));\n}\n.ribbon[data-side=\"built\"] {\n right: var(--spacing-3, 0.75rem);\n background: color-mix(in srgb, var(--fm-built-hue) 85%, var(--color-neutral-950, #030712));\n}\n.range {\n width: 100%;\n margin-top: var(--spacing-3, 0.75rem);\n accent-color: var(--accent, #2563eb);\n cursor: ew-resize;\n}\n.range:focus-visible {\n outline: var(--focus-ring-width, 2px) solid var(--border-focus, currentColor);\n outline-offset: var(--focus-ring-offset, 2px);\n}\n\n/* ── Delta legend ────────────────────────────────────────────────────────── */\n.legend {\n display: flex;\n flex-direction: column;\n gap: var(--spacing-2, 0.5rem);\n padding: var(--spacing-3, 0.75rem) var(--spacing-4, 1rem);\n border-top: var(--stroke-width-thin, 1px) solid var(--hairline, #e5e7eb);\n}\n.legendHead {\n font-family: var(--font-mono, ui-monospace, \"SFMono-Regular\", Menlo, monospace);\n font-size: var(--font-size-2xs, 0.6875rem);\n font-weight: var(--font-weight-bold, 700);\n letter-spacing: 0.14em;\n text-transform: uppercase;\n color: var(--text-tertiary, #9ca3af);\n}\n.legendRow {\n display: flex;\n align-items: center;\n gap: var(--spacing-3, 0.75rem);\n}\n.legendNum {\n flex-shrink: 0;\n display: grid;\n place-items: center;\n width: 1.125rem;\n height: 1.125rem;\n border-radius: var(--radius-full, 9999px);\n background: var(--warning, #f59e0b);\n color: var(--color-neutral-950, #030712);\n font-family: var(--font-mono, ui-monospace, \"SFMono-Regular\", Menlo, monospace);\n font-size: calc(var(--font-size-2xs, 0.6875rem) * 0.9);\n font-weight: var(--font-weight-bold, 700);\n}\n.tag {\n flex-shrink: 0;\n padding: calc(var(--spacing-1, 0.25rem) * 0.75) var(--spacing-2, 0.5rem);\n border: var(--stroke-width-thin, 1px) solid var(--hairline, #e5e7eb);\n border-radius: var(--radius-sm, 0.25rem);\n background: var(--surface-subtle, #f3f4f6);\n font-family: var(--font-mono, ui-monospace, \"SFMono-Regular\", Menlo, monospace);\n font-size: calc(var(--font-size-2xs, 0.6875rem) * 0.9);\n font-weight: var(--font-weight-bold, 700);\n letter-spacing: 0.08em;\n text-transform: uppercase;\n color: var(--text-secondary, #4b5563);\n}\n.legendText {\n font-family: var(--font-mono, ui-monospace, \"SFMono-Regular\", Menlo, monospace);\n font-size: var(--font-size-sm, 0.8125rem);\n color: var(--text-secondary, #4b5563);\n}\n.legendText b {\n color: var(--text-primary, #111827);\n font-weight: var(--font-weight-bold, 700);\n}\n\n/* Visually-hidden text for assistive technology. */\n.srOnly {\n position: absolute;\n width: var(--stroke-width-thin, 1px);\n height: var(--stroke-width-thin, 1px);\n padding: 0;\n margin: calc(-1 * var(--stroke-width-thin, 1px));\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n white-space: nowrap;\n border: 0;\n}\n\n/* Responsive: panes stack under 768px (design over built) — NEVER a sideways\n * scroll strip (the defect the doc-set surfaces exist to kill). */\n@media (max-width: 767px) {\n .panes {\n grid-template-columns: 1fr;\n }\n .bar {\n gap: var(--spacing-2, 0.5rem);\n }\n}\n"
2871
2871
  }
2872
2872
  ]
2873
2873
  },
@@ -3012,12 +3012,12 @@
3012
3012
  {
3013
3013
  "path": "components/ui/status-badge/status-badge.tsx",
3014
3014
  "type": "registry:ui",
3015
- "content": "import * as React from \"react\"\nimport { cn } from \"../../../lib/utils\"\nimport { Badge } from \"../badge/badge\"\nimport type { BadgeProps } from \"../badge/badge\"\nimport styles from \"./status-badge.module.css\"\n\nexport type StatusBadgeStatus =\n | \"healthy\"\n | \"degraded\"\n | \"down\"\n | \"failed\"\n | \"running\"\n | \"pending\"\n | \"queued\"\n | \"idle\"\n | \"complete\"\n | \"live\"\n | \"warn\"\n | \"scheduled\"\n | \"sold\"\n | \"draft\"\n | \"prospect\"\n | \"pitched\"\n | \"contracted\"\n | \"active\"\n | \"paused\"\n | \"completed\"\n | \"archived\"\n\nexport type StatusBadgeTone = \"subtle\" | \"filled\"\n\nexport interface StatusBadgeProps\n extends Omit<React.HTMLAttributes<HTMLSpanElement>, \"children\"> {\n /** Semantic admin status. Drives both color and default label. */\n status: StatusBadgeStatus\n /** Visible text. Defaults to the capitalized status key. */\n label?: React.ReactNode\n /** Which Badge variant family to use. Defaults to \"subtle\". */\n tone?: StatusBadgeTone\n /** Render the leading indicator dot. Defaults to true. */\n indicator?: boolean\n /** Animate the indicator dot with a soft pulse. Defaults to false. */\n pulse?: boolean\n}\n\n/**\n * Default human-readable labels for each status. Exported so consumers can\n * localize or override without reimplementing the map.\n */\nexport const statusBadgeLabels: Record<StatusBadgeStatus, string> = {\n healthy: \"Healthy\",\n degraded: \"Degraded\",\n down: \"Down\",\n failed: \"Failed\",\n running: \"Running\",\n pending: \"Pending\",\n queued: \"Queued\",\n idle: \"Idle\",\n complete: \"Complete\",\n live: \"Live\",\n warn: \"Warn\",\n scheduled: \"Scheduled\",\n sold: \"Sold\",\n draft: \"Draft\",\n prospect: \"Prospect\",\n pitched: \"Pitched\",\n contracted: \"Contracted\",\n active: \"Active\",\n paused: \"Paused\",\n completed: \"Completed\",\n archived: \"Archived\",\n}\n\ntype BadgeVariant = NonNullable<BadgeProps[\"variant\"]>\n\n/**\n * Color group keyed on the semantic status. Used to pick the indicator dot\n * class and the underlying Badge variant.\n */\ntype StatusColorGroup =\n | \"success\"\n | \"warning\"\n | \"destructive\"\n | \"info\"\n | \"neutral\"\n\nconst STATUS_COLOR_GROUP: Record<StatusBadgeStatus, StatusColorGroup> = {\n healthy: \"success\",\n complete: \"success\",\n degraded: \"warning\",\n pending: \"warning\",\n down: \"destructive\",\n failed: \"destructive\",\n running: \"info\",\n queued: \"neutral\",\n idle: \"neutral\",\n // Admin-ui event tones — map to existing semantic groups.\n // live: active/in-progress positive event → success accent\n // warn: needs attention but not failing → warning\n // scheduled: upcoming/committed, distinct from draft's muted grey → info\n // sold: positive completed outcome → success\n // draft: unpublished/muted → neutral\n live: \"success\",\n warn: \"warning\",\n scheduled: \"info\",\n sold: \"success\",\n draft: \"neutral\",\n // CRM / pipeline stages (VI-492) — bind to existing semantic groups.\n // No new tokens: stages that share a meaning share a color.\n // prospect: new informational lead → info\n // pitched: awaiting response, needs attention → warning\n // contracted / active / completed: positive, in-good-standing → success\n // paused: temporarily on hold, needs attention → warning\n // archived: closed/muted, grouped with draft → neutral\n prospect: \"info\",\n pitched: \"warning\",\n contracted: \"success\",\n active: \"success\",\n paused: \"warning\",\n completed: \"success\",\n archived: \"neutral\",\n}\n\nconst SUBTLE_VARIANT: Record<StatusColorGroup, BadgeVariant> = {\n success: \"success\",\n warning: \"warning\",\n destructive: \"destructive\",\n info: \"info\",\n neutral: \"neutral\",\n}\n\nconst FILLED_VARIANT: Record<StatusColorGroup, BadgeVariant> = {\n success: \"filled-success\",\n warning: \"filled-warning\",\n destructive: \"filled-destructive\",\n info: \"filled-info\",\n neutral: \"filled-neutral\",\n}\n\nconst INDICATOR_CLASS: Record<StatusColorGroup, string> = {\n success: styles.indicatorSuccess,\n warning: styles.indicatorWarning,\n destructive: styles.indicatorDestructive,\n info: styles.indicatorInfo,\n neutral: styles.indicatorNeutral,\n}\n\nconst StatusBadge = React.forwardRef<HTMLSpanElement, StatusBadgeProps>(\n (\n {\n className,\n status,\n label,\n tone = \"subtle\",\n indicator = true,\n pulse = false,\n ...props\n },\n ref\n ) => {\n const group = STATUS_COLOR_GROUP[status]\n const variant: BadgeVariant =\n tone === \"filled\" ? FILLED_VARIANT[group] : SUBTLE_VARIANT[group]\n const visibleLabel = label ?? statusBadgeLabels[status]\n\n return (\n <Badge\n ref={ref}\n variant={variant}\n data-slot=\"status-badge\"\n data-status={status}\n data-tone={tone}\n className={cn(className)}\n {...props}\n >\n {indicator ? (\n <span\n data-slot=\"status-badge-indicator\"\n aria-hidden=\"true\"\n className={cn(\n styles.indicator,\n INDICATOR_CLASS[group],\n pulse && styles.pulse\n )}\n />\n ) : null}\n <span className={styles.srOnly}>Status: </span>\n <span data-slot=\"status-badge-label\">{visibleLabel}</span>\n </Badge>\n )\n }\n)\nStatusBadge.displayName = \"StatusBadge\"\n\nexport { StatusBadge }\n"
3015
+ "content": "import * as React from \"react\"\nimport { cn } from \"../../../lib/utils\"\nimport { Badge } from \"../badge/badge\"\nimport type { BadgeProps } from \"../badge/badge\"\nimport styles from \"./status-badge.module.css\"\n\nexport type StatusBadgeStatus =\n | \"healthy\"\n | \"degraded\"\n | \"down\"\n | \"failed\"\n | \"running\"\n | \"pending\"\n | \"queued\"\n | \"idle\"\n | \"complete\"\n | \"live\"\n | \"warn\"\n | \"scheduled\"\n | \"sold\"\n | \"draft\"\n | \"prospect\"\n | \"pitched\"\n | \"contracted\"\n | \"active\"\n | \"paused\"\n | \"completed\"\n | \"archived\"\n\nexport type StatusBadgeTone = \"subtle\" | \"filled\"\n\nexport interface StatusBadgeProps\n extends Omit<React.HTMLAttributes<HTMLSpanElement>, \"children\"> {\n /** Semantic admin status. Drives both color and default label. */\n status: StatusBadgeStatus\n /** Visible text. Defaults to the capitalized status key. */\n label?: React.ReactNode\n /** Which Badge variant family to use. Defaults to \"subtle\". */\n tone?: StatusBadgeTone\n /** Render the leading indicator dot. Defaults to true. */\n indicator?: boolean\n /** Animate the indicator dot with a soft pulse. Defaults to false. */\n pulse?: boolean\n /**\n * Render the label in the monospace token face (`--font-mono`, 11px) — the\n * dot + mono-token treatment from the Animal dialog substrate (VI-620), for\n * ID / code / token-style status readouts. Defaults to false.\n */\n mono?: boolean\n}\n\n/**\n * Default human-readable labels for each status. Exported so consumers can\n * localize or override without reimplementing the map.\n */\nexport const statusBadgeLabels: Record<StatusBadgeStatus, string> = {\n healthy: \"Healthy\",\n degraded: \"Degraded\",\n down: \"Down\",\n failed: \"Failed\",\n running: \"Running\",\n pending: \"Pending\",\n queued: \"Queued\",\n idle: \"Idle\",\n complete: \"Complete\",\n live: \"Live\",\n warn: \"Warn\",\n scheduled: \"Scheduled\",\n sold: \"Sold\",\n draft: \"Draft\",\n prospect: \"Prospect\",\n pitched: \"Pitched\",\n contracted: \"Contracted\",\n active: \"Active\",\n paused: \"Paused\",\n completed: \"Completed\",\n archived: \"Archived\",\n}\n\ntype BadgeVariant = NonNullable<BadgeProps[\"variant\"]>\n\n/**\n * Color group keyed on the semantic status. Used to pick the indicator dot\n * class and the underlying Badge variant.\n */\ntype StatusColorGroup =\n | \"success\"\n | \"warning\"\n | \"destructive\"\n | \"info\"\n | \"neutral\"\n\nconst STATUS_COLOR_GROUP: Record<StatusBadgeStatus, StatusColorGroup> = {\n healthy: \"success\",\n complete: \"success\",\n degraded: \"warning\",\n pending: \"warning\",\n down: \"destructive\",\n failed: \"destructive\",\n running: \"info\",\n queued: \"neutral\",\n idle: \"neutral\",\n // Admin-ui event tones — map to existing semantic groups.\n // live: active/in-progress positive event → success accent\n // warn: needs attention but not failing → warning\n // scheduled: upcoming/committed, distinct from draft's muted grey → info\n // sold: positive completed outcome → success\n // draft: unpublished/muted → neutral\n live: \"success\",\n warn: \"warning\",\n scheduled: \"info\",\n sold: \"success\",\n draft: \"neutral\",\n // CRM / pipeline stages (VI-492) — bind to existing semantic groups.\n // No new tokens: stages that share a meaning share a color.\n // prospect: new informational lead → info\n // pitched: awaiting response, needs attention → warning\n // contracted / active / completed: positive, in-good-standing → success\n // paused: temporarily on hold, needs attention → warning\n // archived: closed/muted, grouped with draft → neutral\n prospect: \"info\",\n pitched: \"warning\",\n contracted: \"success\",\n active: \"success\",\n paused: \"warning\",\n completed: \"success\",\n archived: \"neutral\",\n}\n\nconst SUBTLE_VARIANT: Record<StatusColorGroup, BadgeVariant> = {\n success: \"success\",\n warning: \"warning\",\n destructive: \"destructive\",\n info: \"info\",\n neutral: \"neutral\",\n}\n\nconst FILLED_VARIANT: Record<StatusColorGroup, BadgeVariant> = {\n success: \"filled-success\",\n warning: \"filled-warning\",\n destructive: \"filled-destructive\",\n info: \"filled-info\",\n neutral: \"filled-neutral\",\n}\n\nconst INDICATOR_CLASS: Record<StatusColorGroup, string> = {\n success: styles.indicatorSuccess,\n warning: styles.indicatorWarning,\n destructive: styles.indicatorDestructive,\n info: styles.indicatorInfo,\n neutral: styles.indicatorNeutral,\n}\n\nconst StatusBadge = React.forwardRef<HTMLSpanElement, StatusBadgeProps>(\n (\n {\n className,\n status,\n label,\n tone = \"subtle\",\n indicator = true,\n pulse = false,\n mono = false,\n ...props\n },\n ref\n ) => {\n const group = STATUS_COLOR_GROUP[status]\n const variant: BadgeVariant =\n tone === \"filled\" ? FILLED_VARIANT[group] : SUBTLE_VARIANT[group]\n const visibleLabel = label ?? statusBadgeLabels[status]\n\n return (\n <Badge\n ref={ref}\n variant={variant}\n data-slot=\"status-badge\"\n data-status={status}\n data-tone={tone}\n className={cn(className)}\n {...props}\n >\n {indicator ? (\n <span\n data-slot=\"status-badge-indicator\"\n aria-hidden=\"true\"\n className={cn(\n styles.indicator,\n INDICATOR_CLASS[group],\n pulse && styles.pulse\n )}\n />\n ) : null}\n <span className={styles.srOnly}>Status: </span>\n <span\n data-slot=\"status-badge-label\"\n data-mono={mono ? \"true\" : undefined}\n className={cn(mono && styles.labelMono)}\n >\n {visibleLabel}\n </span>\n </Badge>\n )\n }\n)\nStatusBadge.displayName = \"StatusBadge\"\n\nexport { StatusBadge }\n"
3016
3016
  },
3017
3017
  {
3018
3018
  "path": "components/ui/status-badge/status-badge.module.css",
3019
3019
  "type": "registry:ui",
3020
- "content": "/*\n * StatusBadge — semantic wrapper over Badge.\n *\n * These styles only cover the additions on top of Badge: the leading\n * indicator dot, its per-status color, the optional pulse animation, and\n * the visually-hidden \"Status:\" prefix. All visual chrome (padding, radius,\n * typography, background) is inherited from Badge.\n */\n\n/* Indicator dot — filled circle, 0.5rem, colored per status */\n.indicator {\n display: inline-block;\n width: 0.5rem;\n height: 0.5rem;\n flex-shrink: 0;\n border-radius: var(--radius-full, 9999px);\n background-color: currentColor;\n}\n\n/* Per-color-group fills. Use brand surface default tokens so the dot\n * reads as a saturated status color independent of the Badge subtle bg. */\n.indicatorSuccess {\n background-color: var(--surface-success-default, transparent);\n}\n\n.indicatorWarning {\n background-color: var(--surface-warning-default, transparent);\n}\n\n.indicatorDestructive {\n background-color: var(--surface-error-default, transparent);\n}\n\n.indicatorInfo {\n background-color: var(--surface-info-default, transparent);\n}\n\n.indicatorNeutral {\n background-color: var(--text-tertiary, currentColor);\n}\n\n/* In filled tone, the dot sits on top of a saturated brand fill —\n * paint it with the same inverse token the Badge uses for its text\n * so it's visible in every theme. */\n[data-tone=\"filled\"] .indicatorSuccess,\n[data-tone=\"filled\"] .indicatorWarning,\n[data-tone=\"filled\"] .indicatorDestructive,\n[data-tone=\"filled\"] .indicatorInfo {\n background-color: var(--text-inverse, currentColor);\n}\n\n/* Neutral's filled fill (filled-neutral) is a fixed dark gray in both modes,\n * so its dot stays white rather than following --text-inverse (which flips\n * dark in dark mode). */\n[data-tone=\"filled\"] .indicatorNeutral {\n background-color: var(--color-white, #ffffff);\n}\n\n/* Pulse animation — soft opacity + scale.\n * Keyframes are defined locally to keep the component self-contained. */\n.pulse {\n /* Doubled 800ms token gives ~1.6s per cycle — slow enough to read as a\n * heartbeat without drawing focus away from content. */\n animation: status-badge-pulse\n calc(var(--motion-duration-800, 800ms) * 2)\n var(--motion-easing-standard, ease-in-out) infinite;\n transform-origin: center;\n will-change: opacity, transform;\n}\n\n@keyframes status-badge-pulse {\n 0%,\n 100% {\n opacity: 1;\n transform: scale(1);\n }\n 50% {\n opacity: 0.55;\n transform: scale(0.85);\n }\n}\n\n/* Respect reduced motion */\n@media (prefers-reduced-motion: reduce) {\n .pulse {\n animation: none;\n }\n}\n\n/* Visually hidden but announced to screen readers */\n.srOnly {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n white-space: nowrap;\n border: 0;\n}\n"
3020
+ "content": "/*\n * StatusBadge — semantic wrapper over Badge.\n *\n * These styles only cover the additions on top of Badge: the leading\n * indicator dot, its per-status color, the optional pulse animation, and\n * the visually-hidden \"Status:\" prefix. All visual chrome (padding, radius,\n * typography, background) is inherited from Badge.\n */\n\n/* Indicator dot — filled circle, 0.5rem, colored per status */\n.indicator {\n display: inline-block;\n width: 0.5rem;\n height: 0.5rem;\n flex-shrink: 0;\n border-radius: var(--radius-full, 9999px);\n background-color: currentColor;\n}\n\n/* Per-color-group fills. Use brand surface default tokens so the dot\n * reads as a saturated status color independent of the Badge subtle bg. */\n.indicatorSuccess {\n background-color: var(--surface-success-default, transparent);\n}\n\n.indicatorWarning {\n background-color: var(--surface-warning-default, transparent);\n}\n\n.indicatorDestructive {\n background-color: var(--surface-error-default, transparent);\n}\n\n.indicatorInfo {\n background-color: var(--surface-info-default, transparent);\n}\n\n.indicatorNeutral {\n background-color: var(--text-tertiary, currentColor);\n}\n\n/* In filled tone, the dot sits on top of a saturated brand fill —\n * paint it with the same inverse token the Badge uses for its text\n * so it's visible in every theme. */\n[data-tone=\"filled\"] .indicatorSuccess,\n[data-tone=\"filled\"] .indicatorWarning,\n[data-tone=\"filled\"] .indicatorDestructive,\n[data-tone=\"filled\"] .indicatorInfo {\n background-color: var(--text-inverse, currentColor);\n}\n\n/* Neutral's filled fill (filled-neutral) is a fixed dark gray in both modes,\n * so its dot stays white rather than following --text-inverse (which flips\n * dark in dark mode). */\n[data-tone=\"filled\"] .indicatorNeutral {\n background-color: var(--color-white, #ffffff);\n}\n\n/* Pulse animation — soft opacity + scale.\n * Keyframes are defined locally to keep the component self-contained. */\n.pulse {\n /* Doubled 800ms token gives ~1.6s per cycle — slow enough to read as a\n * heartbeat without drawing focus away from content. */\n animation: status-badge-pulse\n calc(var(--motion-duration-800, 800ms) * 2)\n var(--motion-easing-standard, ease-in-out) infinite;\n transform-origin: center;\n will-change: opacity, transform;\n}\n\n@keyframes status-badge-pulse {\n 0%,\n 100% {\n opacity: 1;\n transform: scale(1);\n }\n 50% {\n opacity: 0.55;\n transform: scale(0.85);\n }\n}\n\n/* Respect reduced motion */\n@media (prefers-reduced-motion: reduce) {\n .pulse {\n animation: none;\n }\n}\n\n/* Mono label variant (Animal dialog substrate, VI-620) — monospace token\n * label at the 11px chrome step, for ID / code / token-style status readouts.\n * Overrides only the label typography; dot, color, and chrome are unchanged. */\n.labelMono {\n font-family: var(--font-mono, \"SF Mono\", \"Fira Code\", \"Fira Mono\", monospace);\n font-size: var(--text-11, 0.6875rem);\n letter-spacing: 0.02em;\n}\n\n/* Visually hidden but announced to screen readers */\n.srOnly {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n white-space: nowrap;\n border: 0;\n}\n"
3021
3021
  }
3022
3022
  ]
3023
3023
  },
@@ -3086,7 +3086,7 @@
3086
3086
  {
3087
3087
  "path": "components/ui/theme-switcher/theme-switcher.module.css",
3088
3088
  "type": "registry:ui",
3089
- "content": ".root {\n position: fixed;\n bottom: var(--spacing-3, 0.75rem);\n right: var(--spacing-3, 0.75rem);\n z-index: 1000;\n\n display: inline-flex;\n align-items: center;\n gap: var(--spacing-2, 0.5rem);\n\n padding: var(--spacing-1, 0.25rem) var(--spacing-2, 0.5rem);\n border-radius: var(--radius-full, 9999px);\n background: var(--surface-popover, var(--surface-card, #111827));\n color: var(--text-secondary, #4b5563);\n backdrop-filter: blur(8px);\n -webkit-backdrop-filter: blur(8px);\n\n font-family: var(--font-body, system-ui, sans-serif);\n font-size: var(--font-size-xs, 0.75rem);\n letter-spacing: 0.04em;\n\n outline: var(--stroke-width-thin, 1px) solid color-mix(in srgb, var(--text-tertiary, #9ca3af) 30%, transparent);\n outline-offset: 0;\n box-shadow: var(--shadow-md, 0 4px 6px -1px rgba(0, 0, 0, 0.1));\n}\n\n.label {\n font-size: var(--font-size-xs, 0.75rem);\n text-transform: uppercase;\n letter-spacing: 0.12em;\n color: var(--text-tertiary, #9ca3af);\n font-weight: var(--font-weight-medium, 500);\n}\n\n.divider {\n display: inline-block;\n width: var(--stroke-width-thin, 1px);\n height: 14px;\n background: color-mix(in srgb, var(--text-tertiary, #9ca3af) 35%, transparent);\n}\n\n.segment {\n display: inline-flex;\n align-items: center;\n gap: calc(var(--spacing-1, 0.25rem) / 2);\n padding: calc(var(--spacing-1, 0.25rem) / 2);\n background: color-mix(in srgb, var(--text-tertiary, #9ca3af) 14%, transparent);\n border-radius: var(--radius-full, 9999px);\n}\n\n.option {\n appearance: none;\n background: transparent;\n border: 0;\n padding: calc(var(--spacing-1, 0.25rem) * 0.75) var(--spacing-2, 0.5rem);\n border-radius: var(--radius-full, 9999px);\n font-size: var(--font-size-xs, 0.75rem);\n font-weight: var(--font-weight-medium, 500);\n color: var(--text-secondary, #4b5563);\n cursor: pointer;\n letter-spacing: 0.02em;\n transition: background-color var(--motion-duration-100, 100ms) var(--motion-easing-default, ease-in-out),\n color var(--motion-duration-100, 100ms) var(--motion-easing-default, ease-in-out);\n}\n\n.option:hover {\n color: var(--text-primary, #111827);\n}\n\n.option[data-active=\"true\"] {\n background: var(--surface-card, #ffffff);\n color: var(--text-primary, #111827);\n box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--text-tertiary, #9ca3af) 25%, transparent);\n}\n\n.option:focus-visible {\n outline: var(--focus-ring-width, 2px) solid var(--border-focus, currentColor);\n outline-offset: var(--focus-ring-offset, 2px);\n}\n"
3089
+ "content": ".root {\n position: fixed;\n bottom: var(--spacing-3, 0.75rem);\n right: var(--spacing-3, 0.75rem);\n z-index: 1000;\n\n display: inline-flex;\n align-items: center;\n gap: var(--spacing-2, 0.5rem);\n\n padding: var(--spacing-1, 0.25rem) var(--spacing-2, 0.5rem);\n border-radius: var(--radius-full, 9999px);\n background: var(--surface-popover, var(--surface-card, #111827));\n color: var(--text-secondary, #4b5563);\n backdrop-filter: blur(8px);\n -webkit-backdrop-filter: blur(8px);\n\n font-family: var(--font-body, inherit);\n font-size: var(--font-size-xs, 0.75rem);\n letter-spacing: 0.04em;\n\n outline: var(--stroke-width-thin, 1px) solid color-mix(in srgb, var(--text-tertiary, #9ca3af) 30%, transparent);\n outline-offset: 0;\n box-shadow: var(--shadow-md, 0 4px 6px -1px rgba(0, 0, 0, 0.1));\n}\n\n.label {\n font-size: var(--font-size-xs, 0.75rem);\n text-transform: uppercase;\n letter-spacing: 0.12em;\n color: var(--text-tertiary, #9ca3af);\n font-weight: var(--font-weight-medium, 500);\n}\n\n.divider {\n display: inline-block;\n width: var(--stroke-width-thin, 1px);\n height: 14px;\n background: color-mix(in srgb, var(--text-tertiary, #9ca3af) 35%, transparent);\n}\n\n.segment {\n display: inline-flex;\n align-items: center;\n gap: calc(var(--spacing-1, 0.25rem) / 2);\n padding: calc(var(--spacing-1, 0.25rem) / 2);\n background: color-mix(in srgb, var(--text-tertiary, #9ca3af) 14%, transparent);\n border-radius: var(--radius-full, 9999px);\n}\n\n.option {\n appearance: none;\n background: transparent;\n border: 0;\n padding: calc(var(--spacing-1, 0.25rem) * 0.75) var(--spacing-2, 0.5rem);\n border-radius: var(--radius-full, 9999px);\n font-size: var(--font-size-xs, 0.75rem);\n font-weight: var(--font-weight-medium, 500);\n color: var(--text-secondary, #4b5563);\n cursor: pointer;\n letter-spacing: 0.02em;\n transition: background-color var(--motion-duration-100, 100ms) var(--motion-easing-default, ease-in-out),\n color var(--motion-duration-100, 100ms) var(--motion-easing-default, ease-in-out);\n}\n\n.option:hover {\n color: var(--text-primary, #111827);\n}\n\n.option[data-active=\"true\"] {\n background: var(--surface-card, #ffffff);\n color: var(--text-primary, #111827);\n box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--text-tertiary, #9ca3af) 25%, transparent);\n}\n\n.option:focus-visible {\n outline: var(--focus-ring-width, 2px) solid var(--border-focus, currentColor);\n outline-offset: var(--focus-ring-offset, 2px);\n}\n"
3090
3090
  }
3091
3091
  ]
3092
3092
  },
@@ -3231,7 +3231,7 @@
3231
3231
  {
3232
3232
  "path": "components/ui/color-picker/color-picker.module.css",
3233
3233
  "type": "registry:ui",
3234
- "content": "/* ColorPicker — theme-agnostic OKLCH picker.\n *\n * All surface, border, focus, shadow, and motion declarations use semantic\n * tokens via var() with Tailwind Gray fallbacks. Canvas pixels are computed\n * colors — outputs of the picker, not theme surfaces — so they reference no\n * tokens. The indicator dimensions (crosshair 12px, hue indicator 4px) are\n * documented as intentional pixel values for pointing precision per\n * the token-rules doc, rule 12.\n */\n\n/* ─── Root container ──────────────────────────────────────────────────── */\n\n.root {\n display: inline-block;\n}\n\n.root[data-mode=\"inline\"] {\n display: block;\n width: 100%;\n}\n\n/* ─── Trigger (popover mode) ──────────────────────────────────────────── */\n\n.trigger {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n padding: 0;\n background-color: transparent;\n border: var(--stroke-width-thin, 1px) solid var(--border-default, #e5e7eb);\n border-radius: var(--radius-sm, 0.5rem);\n cursor: pointer;\n transition: border-color var(--motion-duration-150, 150ms) var(--motion-easing-default, ease-in-out),\n box-shadow var(--motion-duration-150, 150ms) var(--motion-easing-default, ease-in-out);\n outline: none;\n overflow: hidden;\n}\n\n@media (hover: hover) {\n .trigger:hover:not(:focus-visible):not(:disabled) {\n border-color: var(--border-strong, #d1d5db);\n }\n}\n\n.trigger:focus-visible {\n border-color: var(--border-focus, #111827);\n box-shadow: 0 0 0 var(--focus-ring-width, 2px) color-mix(in srgb, var(--border-focus, #111827) 15%, transparent);\n}\n\n.trigger:disabled {\n cursor: not-allowed;\n opacity: var(--opacity-40, 0.4);\n}\n\n.triggerSm {\n width: 1.5rem;\n height: 1.5rem;\n}\n\n.triggerMd {\n width: 2rem;\n height: 2rem;\n}\n\n.triggerLg {\n width: 2.5rem;\n height: 2.5rem;\n}\n\n.triggerSwatch {\n display: block;\n width: 100%;\n height: 100%;\n}\n\n/* ─── Popover content ─────────────────────────────────────────────────── */\n\n.popoverContent {\n z-index: 50;\n min-width: 16rem;\n padding: var(--spacing-4, 1rem);\n background-color: var(--surface-popover, var(--surface-card, #ffffff));\n color: var(--text-primary, #111827);\n border: var(--stroke-width-thin, 1px) solid var(--border-default, #e5e7eb);\n border-radius: var(--radius-sm, 0.5rem);\n box-shadow: var(--shadow-md);\n}\n\n.popoverContent[data-state=\"open\"] {\n animation: contentShow var(--motion-duration-fast, 100ms) var(--motion-easing-enter, ease-out);\n}\n\n.popoverContent[data-state=\"closed\"] {\n animation: contentHide var(--motion-duration-fast, 100ms) var(--motion-easing-exit, ease-in);\n}\n\n@keyframes contentShow {\n from {\n opacity: 0;\n transform: scale(0.96);\n }\n to {\n opacity: 1;\n transform: scale(1);\n }\n}\n\n@keyframes contentHide {\n from {\n opacity: 1;\n transform: scale(1);\n }\n to {\n opacity: 0;\n transform: scale(0.96);\n }\n}\n\n/* ─── Picker surface (the actual picker UI) ───────────────────────────── */\n\n.picker {\n display: flex;\n flex-direction: column;\n gap: var(--spacing-3, 0.75rem);\n min-width: 16rem;\n}\n\n.picker[data-disabled] {\n opacity: var(--opacity-40, 0.4);\n pointer-events: none;\n}\n\n/* ─── 2D Lightness × Chroma plane ─────────────────────────────────────── */\n\n.planeWrapper {\n position: relative;\n width: 100%;\n aspect-ratio: 1.4;\n border-radius: var(--radius-sm, 0.25rem);\n overflow: hidden;\n cursor: crosshair;\n border: var(--stroke-width-thin, 1px) solid var(--border-default, #e5e7eb);\n outline: none;\n}\n\n.planeWrapper:focus-visible {\n border-color: var(--border-focus, #111827);\n box-shadow: 0 0 0 var(--focus-ring-width, 2px) color-mix(in srgb, var(--border-focus, #111827) 15%, transparent);\n}\n\n.planeCanvas {\n display: block;\n width: 100%;\n height: 100%;\n}\n\n.crosshair {\n /* Crosshair is a floating overlay on top of the computed-color canvas, not\n * a theme surface. The 12px diameter is an intentional pixel value chosen\n * for pointing precision (documented under token-rules rule 12). The white\n * stroke + dark micro-shadow give the indicator legibility against any\n * underlying canvas color regardless of theme — that's the whole point of\n * the marker. Themes can opt to override these via the color-picker tokens\n * declared in the planeWrapper rule above. */\n position: absolute;\n width: 12px;\n height: 12px;\n border: var(--stroke-width-medium, 2px) solid var(--color-picker-indicator, #ffffff);\n border-radius: 50%;\n box-shadow: var(\n --color-picker-indicator-shadow,\n 0 0 0 var(--stroke-width-thin, 1px) rgba(0, 0, 0, 0.3)\n ),\n inset 0 0 0 var(--stroke-width-thin, 1px) var(--color-picker-indicator-shadow-color, rgba(0, 0, 0, 0.3));\n pointer-events: none;\n transform: translate(-50%, -50%);\n transition: left var(--motion-duration-fast, 100ms) var(--motion-easing-default, ease-in-out),\n top var(--motion-duration-fast, 100ms) var(--motion-easing-default, ease-in-out);\n}\n\n@media (prefers-reduced-motion: reduce) {\n .crosshair {\n transition: none;\n }\n}\n\n/* ─── Hue slider ──────────────────────────────────────────────────────── */\n\n.hueWrapper {\n position: relative;\n width: 100%;\n height: var(--spacing-4, 1rem);\n border-radius: var(--radius-sm, 0.25rem);\n overflow: hidden;\n cursor: crosshair;\n border: var(--stroke-width-thin, 1px) solid var(--border-default, #e5e7eb);\n outline: none;\n}\n\n.hueWrapper:focus-visible {\n border-color: var(--border-focus, #111827);\n box-shadow: 0 0 0 var(--focus-ring-width, 2px) color-mix(in srgb, var(--border-focus, #111827) 15%, transparent);\n}\n\n.hueCanvas {\n display: block;\n width: 100%;\n height: 100%;\n}\n\n.hueIndicator {\n /* Hue indicator is a floating overlay on top of the computed-color hue\n * canvas, not a theme surface. The 4px width is an intentional pixel value\n * chosen for pointing precision (documented under token-rules rule 12).\n * The white stroke + dark micro-shadow give the indicator legibility\n * against any underlying hue regardless of theme. Themes can opt to\n * override via the color-picker tokens declared in the planeWrapper rule\n * above. */\n position: absolute;\n top: calc(-1 * var(--stroke-width-thin, 1px));\n bottom: calc(-1 * var(--stroke-width-thin, 1px));\n width: 4px;\n border: var(--stroke-width-medium, 2px) solid var(--color-picker-indicator, #ffffff);\n border-radius: 1px;\n box-shadow: var(\n --color-picker-indicator-shadow,\n 0 0 0 var(--stroke-width-thin, 1px) rgba(0, 0, 0, 0.3)\n );\n pointer-events: none;\n transform: translateX(-50%);\n transition: left var(--motion-duration-fast, 100ms) var(--motion-easing-default, ease-in-out);\n}\n\n@media (prefers-reduced-motion: reduce) {\n .hueIndicator {\n transition: none;\n }\n}\n\n/* ─── Readout (L / C / H) ─────────────────────────────────────────────── */\n\n.readout {\n display: flex;\n justify-content: space-between;\n font-size: var(--font-size-xs, 0.75rem);\n color: var(--text-tertiary, #9ca3af);\n font-variant-numeric: tabular-nums;\n}\n\n/* ─── Hex row (chip + input) ──────────────────────────────────────────── */\n\n.hexRow {\n display: flex;\n gap: var(--spacing-2, 0.5rem);\n align-items: center;\n}\n\n.hexChip {\n width: 2rem;\n height: 2rem;\n border: var(--stroke-width-thin, 1px) solid var(--border-default, #e5e7eb);\n border-radius: var(--radius-sm, 0.5rem);\n flex-shrink: 0;\n}\n\n.hexInput {\n flex: 1;\n min-width: 0;\n height: 2.25rem;\n padding: var(--spacing-1, 0.25rem) var(--spacing-3, 0.75rem);\n border: var(--stroke-width-thin, 1px) solid var(--border-default, #e5e7eb);\n border-radius: var(--radius-sm, 0.5rem);\n background-color: var(--surface-interactive-default, #f9fafb);\n color: var(--text-primary, #111827);\n font-family: ui-monospace, SFMono-Regular, Menlo, monospace;\n font-size: var(--font-size-sm, 0.875rem);\n font-variant-numeric: tabular-nums;\n outline: none;\n transition: border-color var(--motion-duration-150, 150ms) var(--motion-easing-default, ease-in-out),\n box-shadow var(--motion-duration-150, 150ms) var(--motion-easing-default, ease-in-out);\n}\n\n.hexInput:focus-visible {\n border-color: var(--border-focus, #111827);\n box-shadow: 0 0 0 var(--focus-ring-width, 2px) color-mix(in srgb, var(--border-focus, #111827) 15%, transparent);\n}\n\n.hexInput[aria-invalid=\"true\"] {\n border-color: var(--border-error, #ef4444);\n box-shadow: 0 0 0 var(--focus-ring-width, 2px) color-mix(in srgb, var(--border-error, #ef4444) 15%, transparent);\n}\n\n.hexInput:disabled {\n cursor: not-allowed;\n opacity: var(--opacity-40, 0.4);\n}\n\n/* ─── Preset chips ────────────────────────────────────────────────────── */\n\n.presets {\n display: flex;\n gap: var(--spacing-2, 0.5rem);\n flex-wrap: wrap;\n}\n\n.presetChip {\n width: 1.5rem;\n height: 1.5rem;\n padding: 0;\n border: var(--stroke-width-thin, 1px) solid var(--border-default, #e5e7eb);\n border-radius: var(--radius-sm, 0.25rem);\n cursor: pointer;\n outline: none;\n transition: border-color var(--motion-duration-150, 150ms) var(--motion-easing-default, ease-in-out),\n box-shadow var(--motion-duration-150, 150ms) var(--motion-easing-default, ease-in-out);\n}\n\n@media (hover: hover) {\n .presetChip:hover:not(:focus-visible):not(:disabled) {\n border-color: var(--border-strong, #d1d5db);\n }\n}\n\n.presetChip:focus-visible {\n border-color: var(--border-focus, #111827);\n box-shadow: 0 0 0 var(--focus-ring-width, 2px) color-mix(in srgb, var(--border-focus, #111827) 15%, transparent);\n}\n\n.presetChip:disabled {\n cursor: not-allowed;\n opacity: var(--opacity-40, 0.4);\n}\n"
3234
+ "content": "/* ColorPicker — theme-agnostic OKLCH picker.\n *\n * All surface, border, focus, shadow, and motion declarations use semantic\n * tokens via var() with Tailwind Gray fallbacks. Canvas pixels are computed\n * colors — outputs of the picker, not theme surfaces — so they reference no\n * tokens. The indicator dimensions (crosshair 12px, hue indicator 4px) are\n * documented as intentional pixel values for pointing precision per\n * the token-rules doc, rule 12.\n */\n\n/* ─── Root container ──────────────────────────────────────────────────── */\n\n.root {\n display: inline-block;\n}\n\n.root[data-mode=\"inline\"] {\n display: block;\n width: 100%;\n}\n\n/* ─── Trigger (popover mode) ──────────────────────────────────────────── */\n\n.trigger {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n padding: 0;\n background-color: transparent;\n border: var(--stroke-width-thin, 1px) solid var(--border-default, #e5e7eb);\n border-radius: var(--radius-sm, 0.5rem);\n cursor: pointer;\n transition: border-color var(--motion-duration-150, 150ms) var(--motion-easing-default, ease-in-out),\n box-shadow var(--motion-duration-150, 150ms) var(--motion-easing-default, ease-in-out);\n outline: none;\n overflow: hidden;\n}\n\n@media (hover: hover) {\n .trigger:hover:not(:focus-visible):not(:disabled) {\n border-color: var(--border-strong, #d1d5db);\n }\n}\n\n.trigger:focus-visible {\n border-color: var(--border-focus, #111827);\n box-shadow: 0 0 0 var(--focus-ring-width, 2px) color-mix(in srgb, var(--border-focus, #111827) 15%, transparent);\n}\n\n.trigger:disabled {\n cursor: not-allowed;\n opacity: var(--opacity-40, 0.4);\n}\n\n.triggerSm {\n width: 1.5rem;\n height: 1.5rem;\n}\n\n.triggerMd {\n width: 2rem;\n height: 2rem;\n}\n\n.triggerLg {\n width: 2.5rem;\n height: 2.5rem;\n}\n\n.triggerSwatch {\n display: block;\n width: 100%;\n height: 100%;\n}\n\n/* ─── Popover content ─────────────────────────────────────────────────── */\n\n.popoverContent {\n z-index: 50;\n min-width: 16rem;\n padding: var(--spacing-4, 1rem);\n background-color: var(--surface-popover, var(--surface-card, #ffffff));\n color: var(--text-primary, #111827);\n border: var(--stroke-width-thin, 1px) solid var(--border-default, #e5e7eb);\n border-radius: var(--radius-sm, 0.5rem);\n box-shadow: var(--shadow-md);\n}\n\n.popoverContent[data-state=\"open\"] {\n animation: contentShow var(--motion-duration-fast, 100ms) var(--motion-easing-enter, ease-out);\n}\n\n.popoverContent[data-state=\"closed\"] {\n animation: contentHide var(--motion-duration-fast, 100ms) var(--motion-easing-exit, ease-in);\n}\n\n@keyframes contentShow {\n from {\n opacity: 0;\n transform: scale(0.96);\n }\n to {\n opacity: 1;\n transform: scale(1);\n }\n}\n\n@keyframes contentHide {\n from {\n opacity: 1;\n transform: scale(1);\n }\n to {\n opacity: 0;\n transform: scale(0.96);\n }\n}\n\n/* ─── Picker surface (the actual picker UI) ───────────────────────────── */\n\n.picker {\n display: flex;\n flex-direction: column;\n gap: var(--spacing-3, 0.75rem);\n min-width: 16rem;\n}\n\n.picker[data-disabled] {\n opacity: var(--opacity-40, 0.4);\n pointer-events: none;\n}\n\n/* ─── 2D Lightness × Chroma plane ─────────────────────────────────────── */\n\n.planeWrapper {\n position: relative;\n width: 100%;\n aspect-ratio: 1.4;\n border-radius: var(--radius-sm, 0.25rem);\n overflow: hidden;\n cursor: crosshair;\n border: var(--stroke-width-thin, 1px) solid var(--border-default, #e5e7eb);\n outline: none;\n}\n\n.planeWrapper:focus-visible {\n border-color: var(--border-focus, #111827);\n box-shadow: 0 0 0 var(--focus-ring-width, 2px) color-mix(in srgb, var(--border-focus, #111827) 15%, transparent);\n}\n\n.planeCanvas {\n display: block;\n width: 100%;\n height: 100%;\n}\n\n.crosshair {\n /* Crosshair is a floating overlay on top of the computed-color canvas, not\n * a theme surface. The 12px diameter is an intentional pixel value chosen\n * for pointing precision (documented under token-rules rule 12). The white\n * stroke + dark micro-shadow give the indicator legibility against any\n * underlying canvas color regardless of theme — that's the whole point of\n * the marker. Themes can opt to override these via the color-picker tokens\n * declared in the planeWrapper rule above. */\n position: absolute;\n width: 12px;\n height: 12px;\n border: var(--stroke-width-medium, 2px) solid var(--color-picker-indicator, #ffffff);\n border-radius: 50%;\n box-shadow: var(\n --color-picker-indicator-shadow,\n 0 0 0 var(--stroke-width-thin, 1px) rgba(0, 0, 0, 0.3)\n ),\n inset 0 0 0 var(--stroke-width-thin, 1px) var(--color-picker-indicator-shadow-color, rgba(0, 0, 0, 0.3));\n pointer-events: none;\n transform: translate(-50%, -50%);\n transition: left var(--motion-duration-fast, 100ms) var(--motion-easing-default, ease-in-out),\n top var(--motion-duration-fast, 100ms) var(--motion-easing-default, ease-in-out);\n}\n\n@media (prefers-reduced-motion: reduce) {\n .crosshair {\n transition: none;\n }\n}\n\n/* ─── Hue slider ──────────────────────────────────────────────────────── */\n\n.hueWrapper {\n position: relative;\n width: 100%;\n height: var(--spacing-4, 1rem);\n border-radius: var(--radius-sm, 0.25rem);\n overflow: hidden;\n cursor: crosshair;\n border: var(--stroke-width-thin, 1px) solid var(--border-default, #e5e7eb);\n outline: none;\n}\n\n.hueWrapper:focus-visible {\n border-color: var(--border-focus, #111827);\n box-shadow: 0 0 0 var(--focus-ring-width, 2px) color-mix(in srgb, var(--border-focus, #111827) 15%, transparent);\n}\n\n.hueCanvas {\n display: block;\n width: 100%;\n height: 100%;\n}\n\n.hueIndicator {\n /* Hue indicator is a floating overlay on top of the computed-color hue\n * canvas, not a theme surface. The 4px width is an intentional pixel value\n * chosen for pointing precision (documented under token-rules rule 12).\n * The white stroke + dark micro-shadow give the indicator legibility\n * against any underlying hue regardless of theme. Themes can opt to\n * override via the color-picker tokens declared in the planeWrapper rule\n * above. */\n position: absolute;\n top: calc(-1 * var(--stroke-width-thin, 1px));\n bottom: calc(-1 * var(--stroke-width-thin, 1px));\n width: 4px;\n border: var(--stroke-width-medium, 2px) solid var(--color-picker-indicator, #ffffff);\n border-radius: 1px;\n box-shadow: var(\n --color-picker-indicator-shadow,\n 0 0 0 var(--stroke-width-thin, 1px) rgba(0, 0, 0, 0.3)\n );\n pointer-events: none;\n transform: translateX(-50%);\n transition: left var(--motion-duration-fast, 100ms) var(--motion-easing-default, ease-in-out);\n}\n\n@media (prefers-reduced-motion: reduce) {\n .hueIndicator {\n transition: none;\n }\n}\n\n/* ─── Readout (L / C / H) ─────────────────────────────────────────────── */\n\n.readout {\n display: flex;\n justify-content: space-between;\n font-size: var(--font-size-xs, 0.75rem);\n color: var(--text-tertiary, #9ca3af);\n font-variant-numeric: tabular-nums;\n}\n\n/* ─── Hex row (chip + input) ──────────────────────────────────────────── */\n\n.hexRow {\n display: flex;\n gap: var(--spacing-2, 0.5rem);\n align-items: center;\n}\n\n.hexChip {\n width: 2rem;\n height: 2rem;\n border: var(--stroke-width-thin, 1px) solid var(--border-default, #e5e7eb);\n border-radius: var(--radius-sm, 0.5rem);\n flex-shrink: 0;\n}\n\n.hexInput {\n flex: 1;\n min-width: 0;\n height: 2.25rem;\n padding: var(--spacing-1, 0.25rem) var(--spacing-3, 0.75rem);\n border: var(--stroke-width-thin, 1px) solid var(--border-default, #e5e7eb);\n border-radius: var(--radius-sm, 0.5rem);\n background-color: var(--surface-interactive-default, #f9fafb);\n color: var(--text-primary, #111827);\n font-family: var(--font-mono, ui-monospace, SFMono-Regular, Menlo, monospace);\n font-size: var(--font-size-sm, 0.875rem);\n font-variant-numeric: tabular-nums;\n outline: none;\n transition: border-color var(--motion-duration-150, 150ms) var(--motion-easing-default, ease-in-out),\n box-shadow var(--motion-duration-150, 150ms) var(--motion-easing-default, ease-in-out);\n}\n\n.hexInput:focus-visible {\n border-color: var(--border-focus, #111827);\n box-shadow: 0 0 0 var(--focus-ring-width, 2px) color-mix(in srgb, var(--border-focus, #111827) 15%, transparent);\n}\n\n.hexInput[aria-invalid=\"true\"] {\n border-color: var(--border-error, #ef4444);\n box-shadow: 0 0 0 var(--focus-ring-width, 2px) color-mix(in srgb, var(--border-error, #ef4444) 15%, transparent);\n}\n\n.hexInput:disabled {\n cursor: not-allowed;\n opacity: var(--opacity-40, 0.4);\n}\n\n/* ─── Preset chips ────────────────────────────────────────────────────── */\n\n.presets {\n display: flex;\n gap: var(--spacing-2, 0.5rem);\n flex-wrap: wrap;\n}\n\n.presetChip {\n width: 1.5rem;\n height: 1.5rem;\n padding: 0;\n border: var(--stroke-width-thin, 1px) solid var(--border-default, #e5e7eb);\n border-radius: var(--radius-sm, 0.25rem);\n cursor: pointer;\n outline: none;\n transition: border-color var(--motion-duration-150, 150ms) var(--motion-easing-default, ease-in-out),\n box-shadow var(--motion-duration-150, 150ms) var(--motion-easing-default, ease-in-out);\n}\n\n@media (hover: hover) {\n .presetChip:hover:not(:focus-visible):not(:disabled) {\n border-color: var(--border-strong, #d1d5db);\n }\n}\n\n.presetChip:focus-visible {\n border-color: var(--border-focus, #111827);\n box-shadow: 0 0 0 var(--focus-ring-width, 2px) color-mix(in srgb, var(--border-focus, #111827) 15%, transparent);\n}\n\n.presetChip:disabled {\n cursor: not-allowed;\n opacity: var(--opacity-40, 0.4);\n}\n"
3235
3235
  },
3236
3236
  {
3237
3237
  "path": "components/ui/color-picker/oklch.ts",
@@ -3260,7 +3260,7 @@
3260
3260
  {
3261
3261
  "path": "components/ui/structured-prompt/structured-prompt.module.css",
3262
3262
  "type": "registry:ui",
3263
- "content": "/* StructuredPrompt\n *\n * Inline \"mad-lib\" fill-in-the-blank card used in brand elicitation and\n * structured-prompt workflows. A card with an eyebrow header, flowing prose\n * at tall line-height, and inline slot chips (filled or empty) embedded in\n * the prose, plus a hint footer.\n */\n\n.root {\n width: 100%;\n border-radius: var(--radius-xl, 1rem);\n background: var(--surface-card, #ffffff);\n border: var(--stroke-width-thin, 1px) solid var(--border-default, #e5e7eb);\n box-shadow: var(--shadow-sm, 0 1px 2px 0 rgba(0, 0, 0, 0.05));\n overflow: hidden;\n}\n\n/* Header bar — small icon + uppercase eyebrow label, hairline bottom border */\n.header {\n display: flex;\n align-items: center;\n gap: var(--spacing-2, 0.5rem);\n padding: var(--spacing-2-5, 0.625rem) var(--spacing-3-5, 0.875rem);\n border-bottom: var(--stroke-width-thin, 1px) solid var(--hairline, #e5e7eb);\n /* 11.5px — no line-height token matches this tall-prose context; intentional */\n font-size: 11.5px;\n font-weight: 700;\n letter-spacing: 0.04em;\n text-transform: uppercase;\n color: var(--text-tertiary, #6b7280);\n}\n\n.headerIcon {\n display: inline-flex;\n align-items: center;\n /* Use accent color for the eyebrow icon, matching the design spec */\n color: var(--surface-accent-default, #3b82f6);\n flex-shrink: 0;\n /* 13px icon — sized to match the 11.5px label rhythm */\n font-size: 13px;\n line-height: 1;\n}\n\n.headerLabel {\n flex: 1;\n min-width: 0;\n}\n\n/* Body — prose container with tall line-height so inline chips breathe */\n.body {\n padding: var(--spacing-3-5, 0.875rem);\n /* 15px — closest to --font-size-base but intentionally smaller for prose density */\n font-size: 15px;\n /* 2.05 line-height — no token matches; intentional value from design spec (elicit-core HiFi prototype) */\n line-height: 2.05;\n color: var(--text-primary, #111827);\n}\n\n/* Slot chip — inline; rendered inside flowing prose text */\n.slot {\n display: inline-flex;\n align-items: center;\n /* min-height 30px — no spacing token; intentional to match chip rhythm */\n min-height: 30px;\n padding: var(--spacing-0-5, 0.125rem) var(--spacing-2-5, 0.625rem);\n margin: 0 var(--spacing-0-5, 0.125rem);\n border-radius: var(--radius-md, 0.5rem);\n border-width: var(--stroke-width-thin, 1px);\n border-style: solid;\n /* 14px — intentionally one step below body prose for visual hierarchy */\n font-size: 14px;\n cursor: default;\n vertical-align: middle;\n line-height: 1.4;\n /* Reset button defaults when rendered as <button> */\n font-family: inherit;\n text-decoration: none;\n -webkit-appearance: none;\n appearance: none;\n}\n\n/* Focus ring — only when rendered as <button> */\n.slot:focus-visible {\n outline: var(--focus-ring-width, 2px) solid var(--border-focus, #3b82f6);\n outline-offset: var(--focus-ring-offset, 2px);\n}\n\n/* Filled slot — accent-subtle bg + accent-default border + text-link color + 600 weight.\n * Uses the same token triplet as Chip's selected state so it adapts correctly in dark mode.\n */\n.slotFilled {\n background: var(--surface-accent-subtle, #eff6ff);\n border-color: var(--surface-accent-default, #3b82f6);\n color: var(--text-link, #2563eb);\n font-weight: var(--font-weight-semibold, 600);\n}\n\n/* Empty slot — dashed border, muted bg, italic, tertiary text */\n.slotEmpty {\n color: var(--text-tertiary, #6b7280);\n font-style: italic;\n font-weight: var(--font-weight-medium, 500);\n background: var(--surface-subtle, #f9fafb);\n border-style: dashed;\n border-color: var(--border-default, #e5e7eb);\n cursor: text;\n}\n\n/* Hint footer — small tertiary text below the body */\n.hint {\n padding: 0 var(--spacing-3-5, 0.875rem) var(--spacing-3, 0.75rem);\n /* 11.5px — matches header eyebrow size; intentional */\n font-size: 11.5px;\n color: var(--text-tertiary, #6b7280);\n}\n\n/* Respect reduced motion */\n@media (prefers-reduced-motion: reduce) {\n .slot {\n transition: none;\n }\n}\n"
3263
+ "content": "/* StructuredPrompt\n *\n * Inline \"mad-lib\" fill-in-the-blank card used in brand elicitation and\n * structured-prompt workflows. A card with an eyebrow header, flowing prose\n * at tall line-height, and inline slot chips (filled or empty) embedded in\n * the prose, plus a hint footer.\n */\n\n.root {\n width: 100%;\n border-radius: var(--radius-xl, 1rem);\n background: var(--surface-card, #ffffff);\n border: var(--stroke-width-thin, 1px) solid var(--border-default, #e5e7eb);\n box-shadow: var(--shadow-sm, 0 1px 2px 0 rgba(0, 0, 0, 0.05));\n overflow: hidden;\n}\n\n/* Header bar — small icon + uppercase eyebrow label, hairline bottom border */\n.header {\n display: flex;\n align-items: center;\n gap: var(--spacing-2, 0.5rem);\n padding: var(--spacing-2-5, 0.625rem) var(--spacing-3-5, 0.875rem);\n border-bottom: var(--stroke-width-thin, 1px) solid var(--hairline, #e5e7eb);\n /* 11.5px — no line-height token matches this tall-prose context; intentional */\n font-size: 11.5px;\n font-weight: 700;\n letter-spacing: 0.04em;\n text-transform: uppercase;\n color: var(--text-tertiary, #6b7280);\n}\n\n.headerIcon {\n display: inline-flex;\n align-items: center;\n /* Use accent color for the eyebrow icon, matching the design spec */\n color: var(--surface-accent-default, #3b82f6);\n flex-shrink: 0;\n /* 13px icon — sized to match the 11.5px label rhythm */\n font-size: 13px;\n line-height: 1;\n}\n\n.headerLabel {\n flex: 1;\n min-width: 0;\n}\n\n/* Body — prose container with tall line-height so inline chips breathe */\n.body {\n padding: var(--spacing-3-5, 0.875rem);\n /* 15px — closest to --font-size-base but intentionally smaller for prose density */\n font-size: 15px;\n /* 2.05 line-height — no token matches; intentional value from design spec (elicit-core HiFi prototype) */\n line-height: 2.05;\n color: var(--text-primary, #111827);\n}\n\n/* Slot chip — inline; rendered inside flowing prose text */\n.slot {\n display: inline-flex;\n align-items: center;\n /* min-height 30px — no spacing token; intentional to match chip rhythm */\n min-height: 30px;\n padding: var(--spacing-0-5, 0.125rem) var(--spacing-2-5, 0.625rem);\n margin: 0 var(--spacing-0-5, 0.125rem);\n border-radius: var(--radius-md, 0.5rem);\n border-width: var(--stroke-width-thin, 1px);\n border-style: solid;\n /* 14px — intentionally one step below body prose for visual hierarchy */\n font-size: 14px;\n cursor: default;\n vertical-align: middle;\n line-height: 1.4;\n text-decoration: none;\n -webkit-appearance: none;\n appearance: none;\n}\n\n/* Focus ring — only when rendered as <button> */\n.slot:focus-visible {\n outline: var(--focus-ring-width, 2px) solid var(--border-focus, #3b82f6);\n outline-offset: var(--focus-ring-offset, 2px);\n}\n\n/* Filled slot — accent-subtle bg + accent-default border + text-link color + 600 weight.\n * Uses the same token triplet as Chip's selected state so it adapts correctly in dark mode.\n */\n.slotFilled {\n background: var(--surface-accent-subtle, #eff6ff);\n border-color: var(--surface-accent-default, #3b82f6);\n color: var(--text-link, #2563eb);\n font-weight: var(--font-weight-semibold, 600);\n}\n\n/* Empty slot — dashed border, muted bg, italic, tertiary text */\n.slotEmpty {\n color: var(--text-tertiary, #6b7280);\n font-style: italic;\n font-weight: var(--font-weight-medium, 500);\n background: var(--surface-subtle, #f9fafb);\n border-style: dashed;\n border-color: var(--border-default, #e5e7eb);\n cursor: text;\n}\n\n/* Hint footer — small tertiary text below the body */\n.hint {\n padding: 0 var(--spacing-3-5, 0.875rem) var(--spacing-3, 0.75rem);\n /* 11.5px — matches header eyebrow size; intentional */\n font-size: 11.5px;\n color: var(--text-tertiary, #6b7280);\n}\n\n/* Respect reduced motion */\n@media (prefers-reduced-motion: reduce) {\n .slot {\n transition: none;\n }\n}\n"
3264
3264
  }
3265
3265
  ]
3266
3266
  },
@@ -4098,6 +4098,60 @@
4098
4098
  }
4099
4099
  ]
4100
4100
  },
4101
+ {
4102
+ "name": "dialog-form",
4103
+ "type": "registry:block",
4104
+ "description": "Compact admin modal shell (Animal dialog substrate) composing the Dialog atom into a backdrop + centered panel + header + footer. Titled header with a size axis (13px/16px), a body stack for DialogField blocks, and a right-aligned dlg-btn footer row. Token-driven — the theme swaps surface, hairline, radius, and title scale.",
4105
+ "category": "overlay",
4106
+ "dependencies": [
4107
+ "@radix-ui/react-dialog",
4108
+ "@phosphor-icons/react",
4109
+ "@loworbitstudio/visor-core"
4110
+ ],
4111
+ "registryDependencies": [
4112
+ "utils",
4113
+ "dialog",
4114
+ "button"
4115
+ ],
4116
+ "files": [
4117
+ {
4118
+ "path": "blocks/dialog-form/dialog-form.tsx",
4119
+ "type": "registry:block",
4120
+ "content": "\"use client\"\n\nimport * as React from \"react\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\nimport { cn } from \"../../lib/utils\"\nimport {\n Dialog,\n DialogTrigger,\n DialogClose,\n DialogContent,\n DialogTitle,\n DialogDescription,\n} from \"../../components/ui/dialog/dialog\"\nimport styles from \"./dialog-form.module.css\"\n\n/**\n * DialogForm — the Animal dialog substrate shell (VI-620).\n *\n * A mid-tier block that composes the `dialog` atom into the compact admin\n * modal shell the app's 10 hand-rolled modals converge onto: backdrop +\n * centered panel + header + footer. Everything is token-driven; the active\n * theme swaps the surface, hairline, radius, and title scale.\n *\n * The root pieces (open state, trigger, close) are re-exported straight from\n * the atom so a modal imports its whole substrate from one place.\n */\nconst DialogForm = Dialog\nconst DialogFormTrigger = DialogTrigger\nconst DialogFormClose = DialogClose\nconst DialogFormDescription = DialogDescription\n\n/* ─── Content — the compact panel ───────────────────────────────────── */\n\nexport type DialogFormContentProps = React.ComponentProps<typeof DialogContent>\n\nconst DialogFormContent = React.forwardRef<\n React.ComponentRef<typeof DialogContent>,\n DialogFormContentProps\n>(({ className, ...props }, ref) => (\n <DialogContent ref={ref} className={cn(styles.panel, className)} {...props} />\n))\nDialogFormContent.displayName = \"DialogFormContent\"\n\n/* ─── Header ─────────────────────────────────────────────────────────── */\n\nfunction DialogFormHeader({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"dialog-form-header\"\n className={cn(styles.header, className)}\n {...props}\n />\n )\n}\nDialogFormHeader.displayName = \"DialogFormHeader\"\n\n/* ─── Title (size axis: sm 13px default, md 16px) ────────────────────── */\n\nconst titleVariants = cva(styles.title, {\n variants: {\n size: {\n sm: styles.titleSm,\n md: styles.titleMd,\n },\n },\n defaultVariants: {\n size: \"sm\",\n },\n})\n\nexport interface DialogFormTitleProps\n extends React.ComponentProps<typeof DialogTitle>,\n VariantProps<typeof titleVariants> {}\n\nconst DialogFormTitle = React.forwardRef<\n React.ComponentRef<typeof DialogTitle>,\n DialogFormTitleProps\n>(({ className, size, ...props }, ref) => (\n <DialogTitle\n ref={ref}\n className={cn(titleVariants({ size }), className)}\n {...props}\n />\n))\nDialogFormTitle.displayName = \"DialogFormTitle\"\n\n/* ─── Body — vertical stack of DialogField blocks ────────────────────── */\n\nfunction DialogFormBody({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"dialog-form-body\"\n className={cn(styles.body, className)}\n {...props}\n />\n )\n}\nDialogFormBody.displayName = \"DialogFormBody\"\n\n/* ─── Footer — the right-aligned dlg-btn action row ──────────────────── */\n\nfunction DialogFormFooter({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"dialog-form-footer\"\n className={cn(styles.footer, className)}\n {...props}\n />\n )\n}\nDialogFormFooter.displayName = \"DialogFormFooter\"\n\nexport {\n DialogForm,\n DialogFormTrigger,\n DialogFormClose,\n DialogFormContent,\n DialogFormHeader,\n DialogFormTitle,\n DialogFormBody,\n DialogFormFooter,\n DialogFormDescription,\n titleVariants,\n}\n"
4121
+ },
4122
+ {
4123
+ "path": "blocks/dialog-form/dialog-form.module.css",
4124
+ "type": "registry:block",
4125
+ "content": "/* DialogForm block — Animal dialog substrate shell (VI-620).\n *\n * Restyles the `dialog` atom's DialogContent into the compact admin modal\n * panel, then adds the header / title / body / footer chrome the 10 hand-rolled\n * Animal modals converge onto. Every value traces to a Visor token so the\n * active theme (Animal, or any other) swaps the whole shell — no bespoke CSS.\n */\n\n/* Compact panel — overrides the atom's default 32rem / spacing-6 content. */\n.panel {\n max-width: 30rem;\n border-radius: var(--radius-xl, 0.75rem);\n padding: var(--spacing-5, 1.25rem);\n background: var(--surface-card, #ffffff);\n border: var(--stroke-width-thin, 1px) solid\n var(--hairline, var(--border-default, #e5e7eb));\n box-shadow: var(--shadow-lg);\n}\n\n/* Header — title + optional description, tight stack above the body. */\n.header {\n display: flex;\n flex-direction: column;\n gap: var(--spacing-1, 0.25rem);\n margin-bottom: var(--spacing-4, 1rem);\n}\n\n/* Title — dlg-title. Bold, primary ink. Size axis reconciles the two AN\n * sources: the 13.5px surface scale (default `sm`) and reuse.html's 15px\n * shared/confirm dialogs (`md`). Normalized onto the --text-N chrome scale. */\n.title {\n font-weight: var(--font-weight-bold, 700);\n color: var(--text-primary, #111827);\n margin: 0;\n line-height: 1.3;\n}\n\n.titleSm {\n font-size: var(--text-13, 0.8125rem);\n}\n\n.titleMd {\n font-size: var(--text-16, 1rem);\n}\n\n/* Body — vertical stack of DialogField blocks. */\n.body {\n display: flex;\n flex-direction: column;\n gap: var(--spacing-4, 1rem);\n}\n\n/* Footer — right-aligned dlg-btn action row. */\n.footer {\n display: flex;\n justify-content: flex-end;\n align-items: center;\n gap: var(--spacing-2, 0.5rem);\n margin-top: var(--spacing-5, 1.25rem);\n}\n"
4126
+ }
4127
+ ]
4128
+ },
4129
+ {
4130
+ "name": "dialog-field",
4131
+ "type": "registry:block",
4132
+ "description": "Compact dialog field (dlg-field, Animal dialog substrate): a flex-column field with a 5px label→control gap, an 11px/600 primary-ink label, and a recessed control well (surface deeper than the card in both modes + hairline border) hosting leading-icon and trailing control/caret slots. Composes the Label atom; token-driven.",
4133
+ "category": "form",
4134
+ "dependencies": [
4135
+ "@radix-ui/react-label",
4136
+ "@loworbitstudio/visor-core"
4137
+ ],
4138
+ "registryDependencies": [
4139
+ "utils",
4140
+ "label"
4141
+ ],
4142
+ "files": [
4143
+ {
4144
+ "path": "blocks/dialog-field/dialog-field.tsx",
4145
+ "type": "registry:block",
4146
+ "content": "\"use client\"\n\nimport * as React from \"react\"\nimport { cn } from \"../../lib/utils\"\nimport { Label } from \"../../components/ui/label/label\"\nimport styles from \"./dialog-field.module.css\"\n\n/**\n * DialogField — the Animal dialog substrate field block (dlg-field, VI-620).\n *\n * A flex-column field (label over control) with the compact dialog treatment:\n * 5px label→control gap, an 11px/600 primary-ink label, and the standard Visor\n * medium field (md size, themed form-control surface, borderless) that hosts a\n * leading icon slot, the control itself, and a trailing control/caret slot.\n * Composes the `label` atom for the label. Every value traces to a Visor token\n * so the active theme swaps the whole treatment.\n */\n\n/* ─── Field root — flex column, 5px gap ──────────────────────────────── */\n\nconst DialogField = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement>\n>(({ className, ...props }, ref) => (\n <div\n data-slot=\"dialog-field\"\n className={cn(styles.field, className)}\n ref={ref}\n {...props}\n />\n))\nDialogField.displayName = \"DialogField\"\n\n/* ─── Label — 11px / 600 / primary ink (dlg-label) ───────────────────── */\n\nexport type DialogFieldLabelProps = React.ComponentPropsWithoutRef<typeof Label>\n\nconst DialogFieldLabel = React.forwardRef<\n React.ElementRef<typeof Label>,\n DialogFieldLabelProps\n>(({ className, ...props }, ref) => (\n <Label\n data-slot=\"dialog-field-label\"\n className={cn(styles.label, className)}\n ref={ref}\n {...props}\n />\n))\nDialogFieldLabel.displayName = \"DialogFieldLabel\"\n\n/* ─── Control — the recessed well with icon + trailing slots ─────────── */\n\nexport interface DialogFieldControlProps\n extends React.HTMLAttributes<HTMLDivElement> {\n /** Leading icon rendered before the control (aria-hidden decoration). */\n icon?: React.ReactNode\n /** Trailing control / caret slot rendered after the control. */\n trailing?: React.ReactNode\n}\n\nconst DialogFieldControl = React.forwardRef<\n HTMLDivElement,\n DialogFieldControlProps\n>(({ className, icon, trailing, children, ...props }, ref) => (\n <div\n data-slot=\"dialog-field-control\"\n className={cn(styles.control, className)}\n ref={ref}\n {...props}\n >\n {icon ? (\n <span className={styles.icon} aria-hidden=\"true\">\n {icon}\n </span>\n ) : null}\n <span className={styles.controlInner}>{children}</span>\n {trailing ? <span className={styles.trailing}>{trailing}</span> : null}\n </div>\n))\nDialogFieldControl.displayName = \"DialogFieldControl\"\n\nexport { DialogField, DialogFieldLabel, DialogFieldControl }\n"
4147
+ },
4148
+ {
4149
+ "path": "blocks/dialog-field/dialog-field.module.css",
4150
+ "type": "registry:block",
4151
+ "content": "/* DialogField block — Animal dialog substrate field (dlg-field, VI-620).\n *\n * flex column, 5px gap · 11px/600 primary-ink label · the standard Visor medium\n * field (md size, themed form-control surface, borderless) hosting a leading\n * icon, the control, and a trailing control/caret. Every value traces to a Visor\n * token; the active theme swaps the whole treatment (no bespoke CSS).\n */\n\n/* Field — flex column. 5px label→control gap (dlg-field spec): the 4px grid\n * has no 5px step, so derive it from --spacing-1 (the same calc idiom the\n * field atom uses for its 6px icon gap). */\n.field {\n display: flex;\n flex-direction: column;\n gap: calc(var(--spacing-1, 0.25rem) + var(--spacing-1, 0.25rem) / 4);\n}\n\n/* Label — dlg-label: 11px / 600 / --ink (primary). */\n.label {\n font-size: var(--text-11, 0.6875rem);\n font-weight: var(--font-weight-semibold, 600);\n color: var(--text-primary, #111827);\n line-height: 1.4;\n}\n\n/* Control — the standard Visor medium field: md size (--input-padding-md) on the\n * shared form-control surface role (--field-control-bg), borderless. The surface\n * color is theme-driven — a dialog context may lift it with --field-control-bg\n * (the documented in-dialog hook on the input atom); we do not hand-roll it here.\n * Borderless per the dlg-field direction; focus shows a tokenized ring. */\n.control {\n display: flex;\n align-items: center;\n gap: var(--spacing-2, 0.5rem);\n padding: var(--input-padding-md, var(--spacing-3_5, 0.875rem) var(--spacing-4, 1rem));\n border-radius: var(--input-radius-md, var(--radius-sm, 0.5rem));\n /* Borderless field → the surface must contrast with the card on its own. A\n * fixed surface token (--surface-subtle) can't guarantee that: some themes\n * pin it almost on the card (e.g. space/light). Instead derive it from the\n * card mixed a few percent toward --text-primary — which is legible on the\n * card by definition, so the field reads as a subtle-but-visible step in\n * every theme and both modes. Overridable per theme via --field-control-bg. */\n background: var(\n --field-control-bg,\n color-mix(in srgb, var(--surface-card, #ffffff), var(--text-primary, #111827) 7%)\n );\n color: var(--text-primary, #111827);\n transition: box-shadow var(--motion-duration-150, 150ms)\n var(--motion-easing-default, ease-in-out);\n}\n\n.control:focus-within {\n box-shadow: 0 0 0 var(--focus-ring-width, 2px)\n color-mix(in srgb, var(--border-focus, var(--primary, #111827)) 15%, transparent);\n}\n\n/* Leading icon slot. */\n.icon {\n display: inline-flex;\n align-items: center;\n flex-shrink: 0;\n color: var(--text-tertiary, #9ca3af);\n}\n\n/* The control itself sits on the well surface — transparent, borderless, so a\n * plain <input>/<select>/<textarea> dropped in reads as part of the well. */\n.controlInner {\n flex: 1;\n min-width: 0;\n display: flex;\n}\n\n.controlInner :global(input),\n.controlInner :global(select),\n.controlInner :global(textarea) {\n flex: 1;\n min-width: 0;\n border: 0;\n padding: 0;\n background: transparent;\n outline: none;\n color: var(--text-primary, #111827);\n}\n\n/* Trailing control / caret slot. */\n.trailing {\n display: inline-flex;\n align-items: center;\n flex-shrink: 0;\n color: var(--text-tertiary, #9ca3af);\n}\n"
4152
+ }
4153
+ ]
4154
+ },
4101
4155
  {
4102
4156
  "name": "admin-tabbed-editor",
4103
4157
  "type": "registry:block",
@@ -4230,7 +4284,7 @@
4230
4284
  {
4231
4285
  "path": "blocks/month-calendar/month-calendar.module.css",
4232
4286
  "type": "registry:block",
4233
- "content": "/* Month Calendar\n * A theme-portable month event-grid (scheduler) block: a 6×7 day-cell grid\n * under a weekday header, with month navigation, a view-mode segmented control,\n * and per-cell event chips carrying a status dot and an optional series tint.\n *\n * Every color, size, spacing, stroke, radius, and motion value binds to a Visor\n * token so the block adopts the active theme without modification. Selectors are\n * anchored on a local class to satisfy the docs bundler's pure-selector rule.\n */\n\n.root {\n display: flex;\n flex-direction: column;\n background: var(--surface-card);\n border: var(--stroke-width-thin) solid var(--border-muted);\n border-radius: var(--radius-lg);\n overflow: hidden;\n color: var(--text-primary);\n}\n\n/* ── Header: month nav + view segmented control ── */\n.header {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n justify-content: space-between;\n gap: var(--spacing-3, 0.75rem);\n padding: var(--spacing-4, 1rem);\n}\n\n.nav {\n display: flex;\n align-items: center;\n gap: var(--spacing-2, 0.5rem);\n}\n\n.navButton {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n /* 32px — icon-button sizing; sizing tokens deferred (Rule 5 exception). */\n width: 2rem;\n height: 2rem;\n padding: 0;\n color: var(--text-secondary);\n background: transparent;\n border: var(--stroke-width-thin) solid transparent;\n border-radius: var(--radius-md);\n cursor: pointer;\n}\n\n.navButton:hover:not(:disabled) {\n background: var(--surface-interactive-hover);\n color: var(--text-primary);\n}\n\n.navButton:disabled {\n opacity: var(--opacity-40);\n cursor: default;\n}\n\n.navButton:focus-visible {\n outline: var(--focus-ring-width) solid var(--border-focus);\n outline-offset: var(--focus-ring-offset);\n}\n\n.monthLabel {\n margin: 0;\n min-width: 10ch;\n text-align: center;\n font-size: var(--font-size-lg, 1.125rem);\n font-weight: var(--font-weight-semibold, 600);\n color: var(--text-primary);\n}\n\n/* ── View-mode segmented control ── */\n.segmented {\n display: inline-flex;\n align-items: center;\n gap: var(--stroke-width-thin);\n padding: var(--spacing-1, 0.25rem);\n background: var(--surface-subtle);\n border: var(--stroke-width-thin) solid var(--border-muted);\n border-radius: var(--radius-md);\n}\n\n.segment {\n appearance: none;\n padding: var(--spacing-1, 0.25rem) var(--spacing-3, 0.75rem);\n font-size: var(--font-size-sm, 0.875rem);\n font-weight: var(--font-weight-medium, 500);\n color: var(--text-secondary);\n background: transparent;\n border: none;\n border-radius: var(--radius-sm);\n cursor: pointer;\n transition: color var(--motion-duration-fast, 100ms)\n var(--motion-easing-default, ease-in-out),\n background-color var(--motion-duration-fast, 100ms)\n var(--motion-easing-default, ease-in-out);\n}\n\n.segment:hover:not([data-active]) {\n color: var(--text-primary);\n}\n\n.segment[data-active] {\n color: var(--text-primary);\n background: var(--surface-card);\n box-shadow: var(--shadow-xs);\n}\n\n.segment:focus-visible {\n outline: var(--focus-ring-width) solid var(--border-focus);\n outline-offset: var(--focus-ring-offset);\n}\n\n/* ── Weekday header row ── */\n.weekdays {\n display: grid;\n grid-template-columns: repeat(7, minmax(0, 1fr));\n border-top: var(--stroke-width-thin) solid var(--border-muted);\n background: var(--surface-subtle);\n}\n\n.weekday {\n padding: var(--spacing-2, 0.5rem);\n text-align: center;\n font-size: var(--font-size-xs, 0.75rem);\n font-weight: var(--font-weight-medium, 500);\n letter-spacing: 0.04em;\n text-transform: uppercase;\n color: var(--text-tertiary);\n}\n\n/* ── 6×7 day grid ── */\n/* The hairline background shows through the 1px gaps to draw the grid lines. */\n.grid {\n display: grid;\n grid-template-columns: repeat(7, minmax(0, 1fr));\n grid-auto-rows: minmax(0, 1fr);\n gap: var(--stroke-width-thin);\n background: var(--border-muted);\n border-top: var(--stroke-width-thin) solid var(--border-muted);\n}\n\n.cell {\n display: flex;\n flex-direction: column;\n gap: var(--spacing-1, 0.25rem);\n /* 104px — day-cell min height; sizing tokens deferred (Rule 5 exception). */\n min-height: 6.5rem;\n padding: var(--spacing-1, 0.25rem);\n background: var(--surface-card);\n}\n\n.cell[data-outside] {\n background: var(--surface-subtle);\n}\n\n.cell[data-outside] .dayNumber {\n color: var(--text-disabled);\n}\n\n.cell[data-selected] {\n background: var(--interactive-primary-soft);\n}\n\n/* ── Day number head (button when the day is selectable) ── */\n.dayHead {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n align-self: flex-start;\n /* 24px — day-number badge sizing; sizing tokens deferred (Rule 5 exception). */\n min-width: 1.5rem;\n height: 1.5rem;\n padding: 0 var(--spacing-1, 0.25rem);\n font: inherit;\n color: inherit;\n background: transparent;\n border: none;\n border-radius: var(--radius-full);\n cursor: default;\n}\n\n.dayHead:is(button) {\n cursor: pointer;\n}\n\n.dayHead:is(button):hover {\n background: var(--surface-interactive-hover);\n}\n\n.dayHead:focus-visible {\n outline: var(--focus-ring-width) solid var(--border-focus);\n outline-offset: var(--focus-ring-offset);\n}\n\n.dayNumber {\n font-size: var(--font-size-sm, 0.875rem);\n font-weight: var(--font-weight-medium, 500);\n color: var(--text-secondary);\n font-variant-numeric: tabular-nums;\n}\n\n.cell[data-today] .dayHead {\n background: var(--interactive-primary-bg);\n}\n\n.cell[data-today] .dayNumber {\n color: var(--interactive-primary-text);\n font-weight: var(--font-weight-semibold, 600);\n}\n\n/* ── Event chips ── */\n.events {\n display: flex;\n flex-direction: column;\n gap: var(--spacing-1, 0.25rem);\n min-width: 0;\n}\n\n.chip {\n display: flex;\n align-items: center;\n gap: var(--spacing-1, 0.25rem);\n width: 100%;\n padding: var(--spacing-1, 0.25rem) var(--spacing-2, 0.5rem);\n font-size: var(--font-size-xs, 0.75rem);\n font-weight: var(--font-weight-medium, 500);\n text-align: start;\n color: var(--text-primary);\n background: var(--surface-subtle);\n border: none;\n border-radius: var(--radius-sm);\n cursor: default;\n}\n\n.chip:is(button) {\n cursor: pointer;\n}\n\n.chip:is(button):hover {\n background: var(--surface-interactive-hover);\n}\n\n.chip:focus-visible {\n outline: var(--focus-ring-width) solid var(--border-focus);\n outline-offset: var(--focus-ring-offset);\n}\n\n/* Series tint — background wash + leading accent bar keyed to the chart ramp. */\n.chip[data-series=\"1\"] {\n --mc-series: var(--chart-1);\n}\n.chip[data-series=\"2\"] {\n --mc-series: var(--chart-2);\n}\n.chip[data-series=\"3\"] {\n --mc-series: var(--chart-3);\n}\n.chip[data-series=\"4\"] {\n --mc-series: var(--chart-4);\n}\n.chip[data-series=\"5\"] {\n --mc-series: var(--chart-5);\n}\n\n.chip[data-series] {\n background: color-mix(in srgb, var(--mc-series) 16%, transparent);\n box-shadow: inset var(--stroke-width-medium) 0 0 0 var(--mc-series);\n}\n\n.chip[data-series]:is(button):hover {\n background: color-mix(in srgb, var(--mc-series) 28%, transparent);\n}\n\n.chipLabel {\n flex: 1;\n min-width: 0;\n overflow: hidden;\n white-space: nowrap;\n text-overflow: ellipsis;\n}\n\n/* ── Status dot ── */\n.dot {\n flex-shrink: 0;\n /* 8px dot — bound to the spacing scale. */\n width: var(--spacing-2, 0.5rem);\n height: var(--spacing-2, 0.5rem);\n border-radius: var(--radius-full);\n background: var(--text-tertiary);\n}\n\n.dot[data-status=\"success\"] {\n background: var(--surface-success-default);\n}\n.dot[data-status=\"warning\"] {\n background: var(--surface-warning-default);\n}\n.dot[data-status=\"danger\"] {\n background: var(--surface-error-default);\n}\n.dot[data-status=\"info\"] {\n background: var(--surface-info-default);\n}\n\n/* ── Overflow row ── */\n.overflow {\n padding: 0 var(--spacing-2, 0.5rem);\n font-size: var(--font-size-xs, 0.75rem);\n font-weight: var(--font-weight-medium, 500);\n color: var(--text-tertiary);\n}\n\n@media (prefers-reduced-motion: reduce) {\n .segment {\n transition: none;\n }\n}\n"
4287
+ "content": "/* Month Calendar\n * A theme-portable month event-grid (scheduler) block: a 6×7 day-cell grid\n * under a weekday header, with month navigation, a view-mode segmented control,\n * and per-cell event chips carrying a status dot and an optional series tint.\n *\n * Every color, size, spacing, stroke, radius, and motion value binds to a Visor\n * token so the block adopts the active theme without modification. Selectors are\n * anchored on a local class to satisfy the docs bundler's pure-selector rule.\n */\n\n.root {\n display: flex;\n flex-direction: column;\n background: var(--surface-card);\n border: var(--stroke-width-thin) solid var(--border-muted);\n border-radius: var(--radius-lg);\n overflow: hidden;\n color: var(--text-primary);\n}\n\n/* ── Header: month nav + view segmented control ── */\n.header {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n justify-content: space-between;\n gap: var(--spacing-3, 0.75rem);\n padding: var(--spacing-4, 1rem);\n}\n\n.nav {\n display: flex;\n align-items: center;\n gap: var(--spacing-2, 0.5rem);\n}\n\n.navButton {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n /* 32px — icon-button sizing; sizing tokens deferred (Rule 5 exception). */\n width: 2rem;\n height: 2rem;\n padding: 0;\n color: var(--text-secondary);\n background: transparent;\n border: var(--stroke-width-thin) solid transparent;\n border-radius: var(--radius-md);\n cursor: pointer;\n}\n\n.navButton:hover:not(:disabled) {\n background: var(--surface-interactive-hover);\n color: var(--text-primary);\n}\n\n.navButton:disabled {\n opacity: var(--opacity-40);\n cursor: default;\n}\n\n.navButton:focus-visible {\n outline: var(--focus-ring-width) solid var(--border-focus);\n outline-offset: var(--focus-ring-offset);\n}\n\n.monthLabel {\n margin: 0;\n min-width: 10ch;\n text-align: center;\n font-size: var(--font-size-lg, 1.125rem);\n font-weight: var(--font-weight-semibold, 600);\n color: var(--text-primary);\n}\n\n/* ── View-mode segmented control ── */\n.segmented {\n display: inline-flex;\n align-items: center;\n gap: var(--stroke-width-thin);\n padding: var(--spacing-1, 0.25rem);\n background: var(--surface-subtle);\n border: var(--stroke-width-thin) solid var(--border-muted);\n border-radius: var(--radius-md);\n}\n\n.segment {\n appearance: none;\n padding: var(--spacing-1, 0.25rem) var(--spacing-3, 0.75rem);\n font-size: var(--font-size-sm, 0.875rem);\n font-weight: var(--font-weight-medium, 500);\n color: var(--text-secondary);\n background: transparent;\n border: none;\n border-radius: var(--radius-sm);\n cursor: pointer;\n transition: color var(--motion-duration-fast, 100ms)\n var(--motion-easing-default, ease-in-out),\n background-color var(--motion-duration-fast, 100ms)\n var(--motion-easing-default, ease-in-out);\n}\n\n.segment:hover:not([data-active]) {\n color: var(--text-primary);\n}\n\n.segment[data-active] {\n color: var(--text-primary);\n background: var(--surface-card);\n box-shadow: var(--shadow-xs);\n}\n\n.segment:focus-visible {\n outline: var(--focus-ring-width) solid var(--border-focus);\n outline-offset: var(--focus-ring-offset);\n}\n\n/* ── Weekday header row ── */\n.weekdays {\n display: grid;\n grid-template-columns: repeat(7, minmax(0, 1fr));\n border-top: var(--stroke-width-thin) solid var(--border-muted);\n background: var(--surface-subtle);\n}\n\n.weekday {\n padding: var(--spacing-2, 0.5rem);\n text-align: center;\n font-size: var(--font-size-xs, 0.75rem);\n font-weight: var(--font-weight-medium, 500);\n letter-spacing: 0.04em;\n text-transform: uppercase;\n color: var(--text-tertiary);\n}\n\n/* ── 6×7 day grid ── */\n/* The hairline background shows through the 1px gaps to draw the grid lines. */\n.grid {\n display: grid;\n grid-template-columns: repeat(7, minmax(0, 1fr));\n grid-auto-rows: minmax(0, 1fr);\n gap: var(--stroke-width-thin);\n background: var(--border-muted);\n border-top: var(--stroke-width-thin) solid var(--border-muted);\n}\n\n.cell {\n display: flex;\n flex-direction: column;\n gap: var(--spacing-1, 0.25rem);\n /* 104px — day-cell min height; sizing tokens deferred (Rule 5 exception). */\n min-height: 6.5rem;\n padding: var(--spacing-1, 0.25rem);\n background: var(--surface-card);\n}\n\n.cell[data-outside] {\n background: var(--surface-subtle);\n}\n\n.cell[data-outside] .dayNumber {\n color: var(--text-disabled);\n}\n\n.cell[data-selected] {\n background: var(--interactive-primary-soft);\n}\n\n/* ── Day number head (button when the day is selectable) ── */\n.dayHead {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n align-self: flex-start;\n /* 24px — day-number badge sizing; sizing tokens deferred (Rule 5 exception). */\n min-width: 1.5rem;\n height: 1.5rem;\n padding: 0 var(--spacing-1, 0.25rem);\n color: inherit;\n background: transparent;\n border: none;\n border-radius: var(--radius-full);\n cursor: default;\n}\n\n.dayHead:is(button) {\n cursor: pointer;\n}\n\n.dayHead:is(button):hover {\n background: var(--surface-interactive-hover);\n}\n\n.dayHead:focus-visible {\n outline: var(--focus-ring-width) solid var(--border-focus);\n outline-offset: var(--focus-ring-offset);\n}\n\n.dayNumber {\n font-size: var(--font-size-sm, 0.875rem);\n font-weight: var(--font-weight-medium, 500);\n color: var(--text-secondary);\n font-variant-numeric: tabular-nums;\n}\n\n.cell[data-today] .dayHead {\n background: var(--interactive-primary-bg);\n}\n\n.cell[data-today] .dayNumber {\n color: var(--interactive-primary-text);\n font-weight: var(--font-weight-semibold, 600);\n}\n\n/* ── Event chips ── */\n.events {\n display: flex;\n flex-direction: column;\n gap: var(--spacing-1, 0.25rem);\n min-width: 0;\n}\n\n.chip {\n display: flex;\n align-items: center;\n gap: var(--spacing-1, 0.25rem);\n width: 100%;\n padding: var(--spacing-1, 0.25rem) var(--spacing-2, 0.5rem);\n font-size: var(--font-size-xs, 0.75rem);\n font-weight: var(--font-weight-medium, 500);\n text-align: start;\n color: var(--text-primary);\n background: var(--surface-subtle);\n border: none;\n border-radius: var(--radius-sm);\n cursor: default;\n}\n\n.chip:is(button) {\n cursor: pointer;\n}\n\n.chip:is(button):hover {\n background: var(--surface-interactive-hover);\n}\n\n.chip:focus-visible {\n outline: var(--focus-ring-width) solid var(--border-focus);\n outline-offset: var(--focus-ring-offset);\n}\n\n/* Series tint — background wash + leading accent bar keyed to the chart ramp. */\n.chip[data-series=\"1\"] {\n --mc-series: var(--chart-1);\n}\n.chip[data-series=\"2\"] {\n --mc-series: var(--chart-2);\n}\n.chip[data-series=\"3\"] {\n --mc-series: var(--chart-3);\n}\n.chip[data-series=\"4\"] {\n --mc-series: var(--chart-4);\n}\n.chip[data-series=\"5\"] {\n --mc-series: var(--chart-5);\n}\n\n.chip[data-series] {\n background: color-mix(in srgb, var(--mc-series) 16%, transparent);\n box-shadow: inset var(--stroke-width-medium) 0 0 0 var(--mc-series);\n}\n\n.chip[data-series]:is(button):hover {\n background: color-mix(in srgb, var(--mc-series) 28%, transparent);\n}\n\n.chipLabel {\n flex: 1;\n min-width: 0;\n overflow: hidden;\n white-space: nowrap;\n text-overflow: ellipsis;\n}\n\n/* ── Status dot ── */\n.dot {\n flex-shrink: 0;\n /* 8px dot — bound to the spacing scale. */\n width: var(--spacing-2, 0.5rem);\n height: var(--spacing-2, 0.5rem);\n border-radius: var(--radius-full);\n background: var(--text-tertiary);\n}\n\n.dot[data-status=\"success\"] {\n background: var(--surface-success-default);\n}\n.dot[data-status=\"warning\"] {\n background: var(--surface-warning-default);\n}\n.dot[data-status=\"danger\"] {\n background: var(--surface-error-default);\n}\n.dot[data-status=\"info\"] {\n background: var(--surface-info-default);\n}\n\n/* ── Overflow row ── */\n.overflow {\n padding: 0 var(--spacing-2, 0.5rem);\n font-size: var(--font-size-xs, 0.75rem);\n font-weight: var(--font-weight-medium, 500);\n color: var(--text-tertiary);\n}\n\n@media (prefers-reduced-motion: reduce) {\n .segment {\n transition: none;\n }\n}\n"
4234
4288
  }
4235
4289
  ]
4236
4290
  },
@@ -4257,7 +4311,7 @@
4257
4311
  {
4258
4312
  "path": "blocks/workspace-switcher/workspace-switcher.module.css",
4259
4313
  "type": "registry:block",
4260
- "content": "/* Trigger button */\n.trigger {\n display: flex;\n align-items: center;\n gap: var(--spacing-2, 0.5rem);\n width: 100%;\n padding: var(--spacing-2, 0.5rem) var(--spacing-3, 0.75rem);\n background: transparent;\n color: var(--text-primary, #111827);\n border: 1px solid transparent;\n border-radius: var(--radius-md, 0.375rem);\n font-family: inherit;\n font-size: var(--font-size-sm, 0.875rem);\n text-align: start;\n cursor: pointer;\n min-width: 0;\n transition:\n background-color var(--motion-duration-fast, 150ms)\n var(--motion-easing-standard, ease),\n border-color var(--motion-duration-fast, 150ms)\n var(--motion-easing-standard, ease);\n}\n\n.trigger:hover {\n background: var(--surface-interactive-hover, var(--surface-hover, #f3f4f6));\n}\n\n.trigger:focus-visible {\n outline: var(--focus-ring-width, 2px) solid\n var(--focus-ring-color, var(--primary, #3b82f6));\n outline-offset: var(--focus-ring-offset, 2px);\n}\n\n.trigger[data-state=\"open\"] {\n background: var(--surface-interactive-hover, var(--surface-hover, #f3f4f6));\n}\n\n.triggerCompact {\n width: auto;\n padding: var(--spacing-2, 0.5rem);\n}\n\n.triggerAvatar {\n flex-shrink: 0;\n}\n\n.triggerText {\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n flex: 1 1 auto;\n min-width: 0;\n line-height: 1.2;\n}\n\n.triggerName {\n font-weight: var(--font-weight-semibold, 600);\n font-size: var(--font-size-sm, 0.875rem);\n color: var(--text-primary, #111827);\n width: 100%;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.triggerPlan {\n font-weight: var(--font-weight-regular, 400);\n font-size: var(--font-size-xs, 0.75rem);\n color: var(--text-tertiary, var(--text-secondary, #6b7280));\n width: 100%;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n margin-top: var(--spacing-0-5, 0.125rem);\n}\n\n.triggerCaret {\n flex-shrink: 0;\n margin-inline-start: auto;\n color: var(--text-tertiary, var(--text-secondary, #6b7280));\n}\n\n.triggerCompact .triggerCaret {\n margin-inline-start: var(--spacing-1, 0.25rem);\n}\n\n/* Menu content */\n.content {\n min-width: 14rem;\n}\n\n/* Menu item layout (composes onto DropdownMenuItem default styles) */\n.item {\n gap: var(--spacing-2, 0.5rem);\n}\n\n.itemAvatar {\n flex-shrink: 0;\n}\n\n.itemText {\n display: flex;\n flex-direction: column;\n flex: 1 1 auto;\n min-width: 0;\n line-height: 1.2;\n}\n\n.itemName {\n font-weight: var(--font-weight-medium, 500);\n font-size: var(--font-size-sm, 0.875rem);\n color: var(--text-primary, #111827);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.itemPlan {\n font-weight: var(--font-weight-regular, 400);\n font-size: var(--font-size-xs, 0.75rem);\n color: var(--text-tertiary, var(--text-secondary, #6b7280));\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n margin-top: var(--spacing-0-5, 0.125rem);\n}\n\n.itemCheck {\n flex-shrink: 0;\n margin-inline-start: auto;\n color: var(--text-secondary, #6b7280);\n}\n\n.emptyItem {\n font-size: var(--font-size-sm, 0.875rem);\n color: var(--text-tertiary, var(--text-secondary, #6b7280));\n}\n"
4314
+ "content": "/* Trigger button */\n.trigger {\n display: flex;\n align-items: center;\n gap: var(--spacing-2, 0.5rem);\n width: 100%;\n padding: var(--spacing-2, 0.5rem) var(--spacing-3, 0.75rem);\n background: transparent;\n color: var(--text-primary, #111827);\n border: 1px solid transparent;\n border-radius: var(--radius-md, 0.375rem);\n font-size: var(--font-size-sm, 0.875rem);\n text-align: start;\n cursor: pointer;\n min-width: 0;\n transition:\n background-color var(--motion-duration-fast, 150ms)\n var(--motion-easing-standard, ease),\n border-color var(--motion-duration-fast, 150ms)\n var(--motion-easing-standard, ease);\n}\n\n.trigger:hover {\n background: var(--surface-interactive-hover, var(--surface-hover, #f3f4f6));\n}\n\n.trigger:focus-visible {\n outline: var(--focus-ring-width, 2px) solid\n var(--focus-ring-color, var(--primary, #3b82f6));\n outline-offset: var(--focus-ring-offset, 2px);\n}\n\n.trigger[data-state=\"open\"] {\n background: var(--surface-interactive-hover, var(--surface-hover, #f3f4f6));\n}\n\n.triggerCompact {\n width: auto;\n padding: var(--spacing-2, 0.5rem);\n}\n\n.triggerAvatar {\n flex-shrink: 0;\n}\n\n.triggerText {\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n flex: 1 1 auto;\n min-width: 0;\n line-height: 1.2;\n}\n\n.triggerName {\n font-weight: var(--font-weight-semibold, 600);\n font-size: var(--font-size-sm, 0.875rem);\n color: var(--text-primary, #111827);\n width: 100%;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.triggerPlan {\n font-weight: var(--font-weight-regular, 400);\n font-size: var(--font-size-xs, 0.75rem);\n color: var(--text-tertiary, var(--text-secondary, #6b7280));\n width: 100%;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n margin-top: var(--spacing-0-5, 0.125rem);\n}\n\n.triggerCaret {\n flex-shrink: 0;\n margin-inline-start: auto;\n color: var(--text-tertiary, var(--text-secondary, #6b7280));\n}\n\n.triggerCompact .triggerCaret {\n margin-inline-start: var(--spacing-1, 0.25rem);\n}\n\n/* Menu content */\n.content {\n min-width: 14rem;\n}\n\n/* Menu item layout (composes onto DropdownMenuItem default styles) */\n.item {\n gap: var(--spacing-2, 0.5rem);\n}\n\n.itemAvatar {\n flex-shrink: 0;\n}\n\n.itemText {\n display: flex;\n flex-direction: column;\n flex: 1 1 auto;\n min-width: 0;\n line-height: 1.2;\n}\n\n.itemName {\n font-weight: var(--font-weight-medium, 500);\n font-size: var(--font-size-sm, 0.875rem);\n color: var(--text-primary, #111827);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.itemPlan {\n font-weight: var(--font-weight-regular, 400);\n font-size: var(--font-size-xs, 0.75rem);\n color: var(--text-tertiary, var(--text-secondary, #6b7280));\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n margin-top: var(--spacing-0-5, 0.125rem);\n}\n\n.itemCheck {\n flex-shrink: 0;\n margin-inline-start: auto;\n color: var(--text-secondary, #6b7280);\n}\n\n.emptyItem {\n font-size: var(--font-size-sm, 0.875rem);\n color: var(--text-tertiary, var(--text-secondary, #6b7280));\n}\n"
4261
4315
  }
4262
4316
  ]
4263
4317
  },
@@ -4284,7 +4338,7 @@
4284
4338
  {
4285
4339
  "path": "blocks/profile-menu/profile-menu.module.css",
4286
4340
  "type": "registry:block",
4287
- "content": "/* Trigger button */\n.trigger {\n display: flex;\n align-items: center;\n gap: var(--spacing-3, 0.75rem);\n width: 100%;\n padding: var(--spacing-2, 0.5rem) var(--spacing-3, 0.75rem);\n background: transparent;\n color: var(--text-primary, #111827);\n border: 1px solid transparent;\n border-radius: var(--radius-md, 0.375rem);\n font-family: inherit;\n font-size: var(--font-size-sm, 0.875rem);\n text-align: start;\n cursor: pointer;\n min-width: 0;\n transition:\n background-color var(--motion-duration-fast, 150ms)\n var(--motion-easing-standard, ease),\n border-color var(--motion-duration-fast, 150ms)\n var(--motion-easing-standard, ease);\n}\n\n.trigger:hover {\n background: var(--surface-interactive-hover, var(--surface-hover, #f3f4f6));\n}\n\n.trigger:focus-visible {\n outline: var(--focus-ring-width, 2px) solid\n var(--focus-ring-color, var(--primary, #3b82f6));\n outline-offset: var(--focus-ring-offset, 2px);\n}\n\n.trigger[data-state=\"open\"] {\n background: var(--surface-interactive-hover, var(--surface-hover, #f3f4f6));\n}\n\n.triggerAvatarWrap {\n position: relative;\n flex-shrink: 0;\n display: inline-flex;\n}\n\n.triggerAvatar {\n flex-shrink: 0;\n}\n\n.statusDot {\n position: absolute;\n bottom: 0;\n right: 0;\n width: var(--spacing-2-5, 0.625rem);\n height: var(--spacing-2-5, 0.625rem);\n border-radius: 999px;\n border: var(--stroke-width-medium, 2px) solid\n var(--surface-card, #ffffff);\n background: var(--text-tertiary, #6b7280);\n}\n\n.statusDot[data-status=\"online\"] {\n background: var(--status-success, #10b981);\n}\n\n.statusDot[data-status=\"away\"] {\n background: var(--status-warning, #f59e0b);\n}\n\n.statusDot[data-status=\"busy\"] {\n background: var(--status-error, #ef4444);\n}\n\n.statusDot[data-status=\"offline\"] {\n background: var(--text-tertiary, #6b7280);\n}\n\n.triggerIdentity {\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n flex: 1 1 auto;\n min-width: 0;\n line-height: 1.2;\n}\n\n.triggerName {\n font-weight: var(--font-weight-semibold, 600);\n font-size: var(--font-size-sm, 0.875rem);\n color: var(--text-primary, #111827);\n width: 100%;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.triggerContext {\n display: inline-flex;\n align-items: center;\n gap: var(--spacing-1, 0.25rem);\n font-weight: var(--font-weight-regular, 400);\n font-size: var(--font-size-xs, 0.75rem);\n color: var(--text-tertiary, var(--text-secondary, #6b7280));\n width: 100%;\n min-width: 0;\n margin-top: var(--spacing-0-5, 0.125rem);\n}\n\n.triggerContextIcon {\n display: inline-flex;\n flex-shrink: 0;\n width: 0.875rem;\n height: 0.875rem;\n}\n\n.triggerContextLabel {\n min-width: 0;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.triggerCaret {\n flex-shrink: 0;\n margin-inline-start: auto;\n color: var(--text-tertiary, var(--text-secondary, #6b7280));\n}\n\n/* Menu content */\n.content {\n min-width: 14rem;\n}\n\n.menuHeader {\n display: flex;\n flex-direction: column;\n gap: var(--spacing-0-5, 0.125rem);\n padding: var(--spacing-2, 0.5rem) var(--spacing-3, 0.75rem);\n}\n\n.menuHeaderHint {\n font-size: var(--font-size-xs, 0.75rem);\n color: var(--text-tertiary, var(--text-secondary, #6b7280));\n}\n\n.menuHeaderEmail {\n font-size: var(--font-size-sm, 0.875rem);\n font-weight: var(--font-weight-medium, 500);\n color: var(--text-primary, #111827);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n/* Item rows */\n.item {\n gap: var(--spacing-2, 0.5rem);\n}\n\n.itemIcon {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 1rem;\n height: 1rem;\n flex-shrink: 0;\n color: var(--text-secondary, #6b7280);\n}\n\n.itemLabel {\n flex: 1 1 auto;\n min-width: 0;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.itemBadge {\n margin-inline-start: auto;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n min-width: 1.25rem;\n padding: 0 var(--spacing-1-5, 0.375rem);\n border-radius: 999px;\n background: var(--accent-subtle, color-mix(in srgb, var(--primary, #3b82f6) 18%, transparent));\n color: var(--primary, #3b82f6);\n font-size: var(--font-size-xs, 0.75rem);\n font-weight: var(--font-weight-semibold, 600);\n line-height: 1.4;\n}\n\n/* When both badge and shortcut are present, keep shortcut after badge. */\n.itemBadge + .itemShortcut {\n margin-inline-start: var(--spacing-2, 0.5rem);\n}\n\n.itemShortcut {\n /* DropdownMenuShortcut already aligns to the end via margin-left: auto.\n When a badge precedes it, we override margin-left above to keep spacing. */\n}\n"
4341
+ "content": "/* Trigger button */\n.trigger {\n display: flex;\n align-items: center;\n gap: var(--spacing-3, 0.75rem);\n width: 100%;\n padding: var(--spacing-2, 0.5rem) var(--spacing-3, 0.75rem);\n background: transparent;\n color: var(--text-primary, #111827);\n border: 1px solid transparent;\n border-radius: var(--radius-md, 0.375rem);\n font-size: var(--font-size-sm, 0.875rem);\n text-align: start;\n cursor: pointer;\n min-width: 0;\n transition:\n background-color var(--motion-duration-fast, 150ms)\n var(--motion-easing-standard, ease),\n border-color var(--motion-duration-fast, 150ms)\n var(--motion-easing-standard, ease);\n}\n\n.trigger:hover {\n background: var(--surface-interactive-hover, var(--surface-hover, #f3f4f6));\n}\n\n.trigger:focus-visible {\n outline: var(--focus-ring-width, 2px) solid\n var(--focus-ring-color, var(--primary, #3b82f6));\n outline-offset: var(--focus-ring-offset, 2px);\n}\n\n.trigger[data-state=\"open\"] {\n background: var(--surface-interactive-hover, var(--surface-hover, #f3f4f6));\n}\n\n.triggerAvatarWrap {\n position: relative;\n flex-shrink: 0;\n display: inline-flex;\n}\n\n.triggerAvatar {\n flex-shrink: 0;\n}\n\n.statusDot {\n position: absolute;\n bottom: 0;\n right: 0;\n width: var(--spacing-2-5, 0.625rem);\n height: var(--spacing-2-5, 0.625rem);\n border-radius: 999px;\n border: var(--stroke-width-medium, 2px) solid\n var(--surface-card, #ffffff);\n background: var(--text-tertiary, #6b7280);\n}\n\n.statusDot[data-status=\"online\"] {\n background: var(--status-success, #10b981);\n}\n\n.statusDot[data-status=\"away\"] {\n background: var(--status-warning, #f59e0b);\n}\n\n.statusDot[data-status=\"busy\"] {\n background: var(--status-error, #ef4444);\n}\n\n.statusDot[data-status=\"offline\"] {\n background: var(--text-tertiary, #6b7280);\n}\n\n.triggerIdentity {\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n flex: 1 1 auto;\n min-width: 0;\n line-height: 1.2;\n}\n\n.triggerName {\n font-weight: var(--font-weight-semibold, 600);\n font-size: var(--font-size-sm, 0.875rem);\n color: var(--text-primary, #111827);\n width: 100%;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.triggerContext {\n display: inline-flex;\n align-items: center;\n gap: var(--spacing-1, 0.25rem);\n font-weight: var(--font-weight-regular, 400);\n font-size: var(--font-size-xs, 0.75rem);\n color: var(--text-tertiary, var(--text-secondary, #6b7280));\n width: 100%;\n min-width: 0;\n margin-top: var(--spacing-0-5, 0.125rem);\n}\n\n.triggerContextIcon {\n display: inline-flex;\n flex-shrink: 0;\n width: 0.875rem;\n height: 0.875rem;\n}\n\n.triggerContextLabel {\n min-width: 0;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.triggerCaret {\n flex-shrink: 0;\n margin-inline-start: auto;\n color: var(--text-tertiary, var(--text-secondary, #6b7280));\n}\n\n/* Menu content */\n.content {\n min-width: 14rem;\n}\n\n.menuHeader {\n display: flex;\n flex-direction: column;\n gap: var(--spacing-0-5, 0.125rem);\n padding: var(--spacing-2, 0.5rem) var(--spacing-3, 0.75rem);\n}\n\n.menuHeaderHint {\n font-size: var(--font-size-xs, 0.75rem);\n color: var(--text-tertiary, var(--text-secondary, #6b7280));\n}\n\n.menuHeaderEmail {\n font-size: var(--font-size-sm, 0.875rem);\n font-weight: var(--font-weight-medium, 500);\n color: var(--text-primary, #111827);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n/* Item rows */\n.item {\n gap: var(--spacing-2, 0.5rem);\n}\n\n.itemIcon {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 1rem;\n height: 1rem;\n flex-shrink: 0;\n color: var(--text-secondary, #6b7280);\n}\n\n.itemLabel {\n flex: 1 1 auto;\n min-width: 0;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.itemBadge {\n margin-inline-start: auto;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n min-width: 1.25rem;\n padding: 0 var(--spacing-1-5, 0.375rem);\n border-radius: 999px;\n background: var(--accent-subtle, color-mix(in srgb, var(--primary, #3b82f6) 18%, transparent));\n color: var(--primary, #3b82f6);\n font-size: var(--font-size-xs, 0.75rem);\n font-weight: var(--font-weight-semibold, 600);\n line-height: 1.4;\n}\n\n/* When both badge and shortcut are present, keep shortcut after badge. */\n.itemBadge + .itemShortcut {\n margin-inline-start: var(--spacing-2, 0.5rem);\n}\n\n.itemShortcut {\n /* DropdownMenuShortcut already aligns to the end via margin-left: auto.\n When a badge precedes it, we override margin-left above to keep spacing. */\n}\n"
4288
4342
  }
4289
4343
  ]
4290
4344
  },
@@ -4810,7 +4864,7 @@
4810
4864
  {
4811
4865
  "path": "blocks/pricing-section/pricing-section.module.css",
4812
4866
  "type": "registry:block",
4813
- "content": ".root {\n width: 100%;\n padding: var(--spacing-16, 4rem) var(--spacing-6, 1.5rem);\n}\n\n.container {\n max-width: 72rem;\n margin: 0 auto;\n}\n\n.header {\n text-align: center;\n margin-bottom: var(--spacing-12, 3rem);\n}\n\n.headerDescription {\n margin-top: var(--spacing-4, 1rem);\n max-width: 36rem;\n margin-left: auto;\n margin-right: auto;\n}\n\n/* ── Grid ── */\n\n.grid {\n display: grid;\n gap: var(--spacing-6, 1.5rem);\n grid-template-columns: 1fr;\n align-items: start;\n}\n\n@media (min-width: 640px) {\n .grid {\n grid-template-columns: repeat(2, 1fr);\n }\n}\n\n@media (min-width: 1024px) {\n .grid {\n grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));\n }\n}\n\n/* ── Tier card ── */\n\n.tier {\n display: flex;\n flex-direction: column;\n height: 100%;\n transition:\n transform var(--motion-duration-normal, 200ms) cubic-bezier(0.4, 0, 0.2, 1),\n box-shadow var(--motion-duration-normal, 200ms) cubic-bezier(0.4, 0, 0.2, 1);\n}\n\n.tier:hover {\n transform: translateY(-4px);\n box-shadow:\n 0 0 0 1px color-mix(in srgb, var(--tier-color, var(--border-default, #e5e7eb)) 50%, transparent),\n 0 0 30px -10px color-mix(in srgb, var(--tier-color, var(--accent, #3b82f6)) 15%, transparent),\n 0 10px 30px -10px rgba(0, 0, 0, 0.15);\n}\n\n/* ── Highlighted tier ── */\n\n.tierHighlighted {\n box-shadow:\n 0 0 0 1px var(--tier-color, var(--accent, #3b82f6)),\n 0 0 0 4px color-mix(in srgb, var(--tier-color, var(--accent, #3b82f6)) 12%, transparent);\n background-color: color-mix(in srgb, var(--tier-color, var(--accent, #3b82f6)) 5%, var(--surface-card, #ffffff));\n position: relative;\n}\n\n.tierHighlighted:hover {\n box-shadow:\n 0 0 0 1px var(--tier-color, var(--accent, #3b82f6)),\n 0 0 0 4px color-mix(in srgb, var(--tier-color, var(--accent, #3b82f6)) 15%, transparent),\n 0 0 40px -10px color-mix(in srgb, var(--tier-color, var(--accent, #3b82f6)) 30%, transparent),\n 0 20px 40px -20px rgba(0, 0, 0, 0.25);\n transform: translateY(-6px);\n}\n\n/* ── Tier header ── */\n\n.tierHeader {\n display: flex;\n flex-direction: column;\n gap: var(--spacing-3, 0.75rem);\n}\n\n.tierBadge {\n align-self: flex-start;\n}\n\n.tierName {\n font-size: var(--font-size-sm, 0.875rem);\n font-weight: var(--font-weight-medium, 500);\n color: var(--tier-color, var(--text-tertiary, #9ca3af));\n text-transform: uppercase;\n letter-spacing: 0.05em;\n margin: 0;\n transition: color var(--motion-duration-fast, 100ms) cubic-bezier(0.4, 0, 0.2, 1);\n}\n\n/* ── Price ── */\n\n.priceRow {\n display: flex;\n align-items: baseline;\n gap: 0;\n}\n\n.price {\n font-size: var(--font-size-4xl, 2.25rem);\n font-family: var(--font-heading, var(--font-body, ui-sans-serif, system-ui, sans-serif));\n font-weight: var(--font-weight-medium, 500);\n color: var(--text-primary, #111827);\n line-height: 1;\n letter-spacing: -0.02em;\n}\n\n.period {\n font-size: var(--font-size-base, 1rem);\n color: var(--text-tertiary, #9ca3af);\n}\n\n.tierDescription {\n font-size: var(--font-size-sm, 0.875rem);\n font-style: italic;\n color: var(--text-tertiary, #9ca3af);\n margin: 0;\n}\n\n/* ── Feature list ── */\n\n.tierContent {\n flex: 1;\n}\n\n.featureList {\n list-style: none;\n padding: 0;\n margin: 0;\n display: flex;\n flex-direction: column;\n gap: var(--spacing-4, 1rem);\n}\n\n.featureItem {\n display: flex;\n align-items: flex-start;\n gap: var(--spacing-3, 0.75rem);\n font-size: var(--font-size-sm, 0.875rem);\n color: var(--text-secondary, #6b7280);\n}\n\n.featureIcon {\n color: var(--tier-color, var(--accent, #15803d));\n flex-shrink: 0;\n margin-top: 2px;\n}\n\n/* ── Footer ── */\n\n.tierFooter {\n margin-top: auto;\n padding-top: var(--spacing-8, 2rem);\n}\n\n.tierButton {\n width: 100%;\n}\n\n/* ── Reduced motion ── */\n\n@media (prefers-reduced-motion: reduce) {\n .tier,\n .tierName {\n transition: none;\n }\n\n .tier:hover,\n .tierHighlighted:hover {\n transform: none;\n }\n}\n"
4867
+ "content": ".root {\n width: 100%;\n padding: var(--spacing-16, 4rem) var(--spacing-6, 1.5rem);\n}\n\n.container {\n max-width: 72rem;\n margin: 0 auto;\n}\n\n.header {\n text-align: center;\n margin-bottom: var(--spacing-12, 3rem);\n}\n\n.headerDescription {\n margin-top: var(--spacing-4, 1rem);\n max-width: 36rem;\n margin-left: auto;\n margin-right: auto;\n}\n\n/* ── Grid ── */\n\n.grid {\n display: grid;\n gap: var(--spacing-6, 1.5rem);\n grid-template-columns: 1fr;\n align-items: start;\n}\n\n@media (min-width: 640px) {\n .grid {\n grid-template-columns: repeat(2, 1fr);\n }\n}\n\n@media (min-width: 1024px) {\n .grid {\n grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));\n }\n}\n\n/* ── Tier card ── */\n\n.tier {\n display: flex;\n flex-direction: column;\n height: 100%;\n transition:\n transform var(--motion-duration-normal, 200ms) cubic-bezier(0.4, 0, 0.2, 1),\n box-shadow var(--motion-duration-normal, 200ms) cubic-bezier(0.4, 0, 0.2, 1);\n}\n\n.tier:hover {\n transform: translateY(-4px);\n box-shadow:\n 0 0 0 1px color-mix(in srgb, var(--tier-color, var(--border-default, #e5e7eb)) 50%, transparent),\n 0 0 30px -10px color-mix(in srgb, var(--tier-color, var(--accent, #3b82f6)) 15%, transparent),\n 0 10px 30px -10px rgba(0, 0, 0, 0.15);\n}\n\n/* ── Highlighted tier ── */\n\n.tierHighlighted {\n box-shadow:\n 0 0 0 1px var(--tier-color, var(--accent, #3b82f6)),\n 0 0 0 4px color-mix(in srgb, var(--tier-color, var(--accent, #3b82f6)) 12%, transparent);\n background-color: color-mix(in srgb, var(--tier-color, var(--accent, #3b82f6)) 5%, var(--surface-card, #ffffff));\n position: relative;\n}\n\n.tierHighlighted:hover {\n box-shadow:\n 0 0 0 1px var(--tier-color, var(--accent, #3b82f6)),\n 0 0 0 4px color-mix(in srgb, var(--tier-color, var(--accent, #3b82f6)) 15%, transparent),\n 0 0 40px -10px color-mix(in srgb, var(--tier-color, var(--accent, #3b82f6)) 30%, transparent),\n 0 20px 40px -20px rgba(0, 0, 0, 0.25);\n transform: translateY(-6px);\n}\n\n/* ── Tier header ── */\n\n.tierHeader {\n display: flex;\n flex-direction: column;\n gap: var(--spacing-3, 0.75rem);\n}\n\n.tierBadge {\n align-self: flex-start;\n}\n\n.tierName {\n font-size: var(--font-size-sm, 0.875rem);\n font-weight: var(--font-weight-medium, 500);\n color: var(--tier-color, var(--text-tertiary, #9ca3af));\n text-transform: uppercase;\n letter-spacing: 0.05em;\n margin: 0;\n transition: color var(--motion-duration-fast, 100ms) cubic-bezier(0.4, 0, 0.2, 1);\n}\n\n/* ── Price ── */\n\n.priceRow {\n display: flex;\n align-items: baseline;\n gap: 0;\n}\n\n.price {\n font-size: var(--font-size-4xl, 2.25rem);\n font-family: var(--font-heading, var(--font-body, inherit));\n font-weight: var(--font-weight-medium, 500);\n color: var(--text-primary, #111827);\n line-height: 1;\n letter-spacing: -0.02em;\n}\n\n.period {\n font-size: var(--font-size-base, 1rem);\n color: var(--text-tertiary, #9ca3af);\n}\n\n.tierDescription {\n font-size: var(--font-size-sm, 0.875rem);\n font-style: italic;\n color: var(--text-tertiary, #9ca3af);\n margin: 0;\n}\n\n/* ── Feature list ── */\n\n.tierContent {\n flex: 1;\n}\n\n.featureList {\n list-style: none;\n padding: 0;\n margin: 0;\n display: flex;\n flex-direction: column;\n gap: var(--spacing-4, 1rem);\n}\n\n.featureItem {\n display: flex;\n align-items: flex-start;\n gap: var(--spacing-3, 0.75rem);\n font-size: var(--font-size-sm, 0.875rem);\n color: var(--text-secondary, #6b7280);\n}\n\n.featureIcon {\n color: var(--tier-color, var(--accent, #15803d));\n flex-shrink: 0;\n margin-top: 2px;\n}\n\n/* ── Footer ── */\n\n.tierFooter {\n margin-top: auto;\n padding-top: var(--spacing-8, 2rem);\n}\n\n.tierButton {\n width: 100%;\n}\n\n/* ── Reduced motion ── */\n\n@media (prefers-reduced-motion: reduce) {\n .tier,\n .tierName {\n transition: none;\n }\n\n .tier:hover,\n .tierHighlighted:hover {\n transform: none;\n }\n}\n"
4814
4868
  }
4815
4869
  ]
4816
4870
  },
@@ -4889,7 +4943,7 @@
4889
4943
  {
4890
4944
  "path": "blocks/prototype-review/prototype-review.module.css",
4891
4945
  "type": "registry:block",
4892
- "content": "/* ============================================================\n Prototype Review block\n Theme-agnostic. All colors come from Visor semantic tokens.\n The brand color is injected by the React block as\n --prototype-review-brand (per-instance override).\n ============================================================ */\n\n.root {\n display: flex;\n flex-direction: column;\n width: 100%;\n min-height: 100vh;\n background: var(--surface-page);\n color: var(--text-primary);\n font-family: var(\n --font-body,\n var(--font-family-body, ui-sans-serif, system-ui, sans-serif)\n );\n font-weight: 300;\n line-height: 1.5;\n -webkit-font-smoothing: antialiased;\n container-type: inline-size;\n}\n\n/* ─── Header ─────────────────────────────────────────────── */\n\n.chrome {\n position: sticky;\n top: 0;\n z-index: 100;\n background: var(--surface-card);\n border-bottom: var(--stroke-width-thin, 1px) solid var(--border-muted);\n}\n\n.chromeRow {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--spacing-6);\n padding: var(--spacing-3) var(--spacing-7);\n flex-wrap: wrap;\n}\n\n.brand {\n display: flex;\n align-items: center;\n gap: var(--spacing-3);\n min-width: 0;\n}\n\n.brandMark {\n width: 1.75rem;\n height: 1.75rem;\n background: var(--prototype-review-brand, var(--interactive-primary-bg));\n display: grid;\n place-items: center;\n color: var(--prototype-review-brand-on, var(--interactive-primary-text));\n font-family: var(\n --font-display,\n var(--font-family-display, var(--font-family-heading, inherit))\n );\n font-weight: 700;\n font-size: var(--font-size-xs);\n letter-spacing: -0.02em;\n}\n\n.brandText {\n display: flex;\n flex-direction: column;\n line-height: 1.15;\n}\n\n.brandName {\n font-family: var(\n --font-display,\n var(--font-family-display, var(--font-family-heading, inherit))\n );\n font-weight: 600;\n font-size: var(--font-size-sm);\n letter-spacing: 0.12em;\n text-transform: uppercase;\n}\n\n.brandSub {\n font-family: var(--font-mono, var(--font-family-mono, monospace));\n font-size: var(--font-size-xs);\n color: var(--text-tertiary);\n letter-spacing: 0.05em;\n}\n\n.chromeActions {\n display: flex;\n gap: var(--spacing-2);\n align-items: center;\n flex-wrap: wrap;\n}\n\n.pill {\n font-family: var(--font-mono, var(--font-family-mono, monospace));\n font-size: var(--font-size-xs);\n text-transform: uppercase;\n letter-spacing: 0.12em;\n padding: var(--spacing-1) var(--spacing-2);\n border: var(--stroke-width-thin, 1px) solid var(--border-default);\n color: var(--text-tertiary);\n border-radius: var(--radius-full, 9999px);\n}\n\n.pillBrand {\n background: var(--prototype-review-brand-soft, var(--surface-subtle));\n border-color: var(--prototype-review-brand, var(--border-default));\n color: var(--prototype-review-brand, var(--text-primary));\n}\n\n/* ─── Controls ───────────────────────────────────────────── */\n\n.controls {\n border-bottom: var(--stroke-width-thin, 1px) solid var(--border-muted);\n background: var(--surface-muted, var(--surface-subtle));\n}\n\n.controlsRow {\n display: grid;\n grid-template-columns: minmax(0, 1fr) auto auto;\n gap: var(--spacing-6);\n align-items: center;\n padding: var(--spacing-3) var(--spacing-7);\n}\n\n@container (max-width: 64rem) {\n .controlsRow {\n grid-template-columns: 1fr;\n }\n}\n\n.controlGroup {\n display: flex;\n align-items: center;\n gap: var(--spacing-4);\n flex-wrap: wrap;\n}\n\n.controlLabel {\n font-family: var(--font-mono, var(--font-family-mono, monospace));\n font-size: var(--font-size-xs);\n letter-spacing: 0.12em;\n text-transform: uppercase;\n color: var(--text-tertiary);\n}\n\n/* Tabs */\n\n.tabs {\n display: flex;\n gap: 0;\n flex-wrap: wrap;\n align-items: stretch;\n border: var(--stroke-width-thin, 1px) solid var(--border-default);\n background: var(--surface-page);\n width: fit-content;\n border-radius: var(--radius-full, 9999px);\n overflow: hidden;\n}\n\n.tab {\n background: transparent;\n border: none;\n color: var(--text-tertiary);\n font-family: var(--font-mono, var(--font-family-mono, monospace));\n font-size: var(--font-size-xs);\n letter-spacing: 0.08em;\n text-transform: uppercase;\n padding: var(--spacing-2) var(--spacing-4);\n cursor: pointer;\n transition:\n color var(--motion-duration-fast, 150ms)\n var(--motion-easing-standard, ease),\n background var(--motion-duration-fast, 150ms)\n var(--motion-easing-standard, ease);\n}\n\n.tab:hover {\n color: var(--text-primary);\n}\n\n.tab[aria-selected=\"true\"] {\n background: var(--prototype-review-brand, var(--interactive-primary-bg));\n color: var(--prototype-review-brand-on, var(--interactive-primary-text));\n}\n\n.tab:focus-visible {\n outline: var(--focus-ring-width, 2px) solid\n var(--focus-ring-color, var(--prototype-review-brand, var(--primary)));\n outline-offset: calc(var(--focus-ring-offset, 2px) * -1);\n}\n\n.tabId {\n font-family: var(\n --font-display,\n var(--font-family-display, var(--font-family-heading, inherit))\n );\n font-weight: 600;\n letter-spacing: 0.02em;\n text-transform: none;\n font-size: var(--font-size-sm);\n margin-right: var(--spacing-2);\n}\n\n/* Theme select */\n\n.themeGroup {\n display: flex;\n align-items: center;\n gap: var(--spacing-2);\n}\n\n.themeSelect {\n background: var(--surface-page);\n border: var(--stroke-width-thin, 1px) solid var(--border-default);\n color: var(--text-primary);\n font-family: var(--font-mono, var(--font-family-mono, monospace));\n font-size: var(--font-size-xs);\n padding: var(--spacing-2) var(--spacing-3);\n border-radius: var(--radius-full, 9999px);\n cursor: pointer;\n letter-spacing: 0.05em;\n text-transform: uppercase;\n}\n\n.themeSelect:focus-visible {\n outline: var(--focus-ring-width, 2px) solid\n var(--focus-ring-color, var(--prototype-review-brand, var(--primary)));\n outline-offset: var(--focus-ring-offset, 2px);\n}\n\n/* Mode + viewport toggle buttons */\n\n.modeGroup,\n.vpGroup {\n display: flex;\n align-items: center;\n gap: var(--spacing-2);\n}\n\n.toggleButtons {\n display: flex;\n border: var(--stroke-width-thin, 1px) solid var(--border-default);\n background: var(--surface-page);\n border-radius: var(--radius-full, 9999px);\n overflow: hidden;\n}\n\n.toggleButton {\n background: transparent;\n border: none;\n color: var(--text-tertiary);\n font-family: var(--font-mono, var(--font-family-mono, monospace));\n font-size: var(--font-size-xs);\n letter-spacing: 0.05em;\n padding: var(--spacing-2) var(--spacing-3);\n cursor: pointer;\n text-transform: uppercase;\n transition:\n color var(--motion-duration-fast, 150ms)\n var(--motion-easing-standard, ease),\n background var(--motion-duration-fast, 150ms)\n var(--motion-easing-standard, ease);\n}\n\n.toggleButton:hover {\n color: var(--text-primary);\n}\n\n.toggleButton[aria-pressed=\"true\"] {\n background: var(--prototype-review-brand, var(--interactive-primary-bg));\n color: var(--prototype-review-brand-on, var(--interactive-primary-text));\n}\n\n.toggleButton:focus-visible {\n outline: var(--focus-ring-width, 2px) solid\n var(--focus-ring-color, var(--prototype-review-brand, var(--primary)));\n outline-offset: calc(var(--focus-ring-offset, 2px) * -1);\n}\n\n/* Brand picker */\n\n.picker {\n display: flex;\n align-items: center;\n gap: var(--spacing-3);\n flex-wrap: wrap;\n}\n\n.swatches {\n display: flex;\n gap: var(--spacing-1);\n align-items: center;\n}\n\n.swatch {\n width: 1.375rem;\n height: 1.375rem;\n border-radius: var(--radius-full, 9999px);\n border: var(--stroke-width-medium, 2px) solid transparent;\n cursor: pointer;\n padding: 0;\n transition:\n transform var(--motion-duration-fast, 150ms)\n var(--motion-easing-standard, ease),\n border-color var(--motion-duration-fast, 150ms)\n var(--motion-easing-standard, ease);\n}\n\n.swatch:hover {\n transform: scale(1.12);\n}\n\n.swatch[data-active=\"true\"] {\n border-color: var(--text-primary);\n box-shadow: 0 0 0 var(--stroke-width-medium, 2px) var(--surface-page);\n}\n\n.swatch:focus-visible {\n outline: var(--focus-ring-width, 2px) solid\n var(--focus-ring-color, var(--prototype-review-brand, var(--primary)));\n outline-offset: var(--focus-ring-offset, 2px);\n}\n\n.hexInput {\n background: var(--surface-page);\n border: var(--stroke-width-thin, 1px) solid var(--border-default);\n color: var(--text-primary);\n font-family: var(--font-mono, var(--font-family-mono, monospace));\n font-size: var(--font-size-xs);\n padding: var(--spacing-1) var(--spacing-3);\n width: 8.5rem;\n letter-spacing: 0.05em;\n text-transform: uppercase;\n border-radius: var(--radius-full, 9999px);\n}\n\n.hexInput:focus {\n outline: none;\n border-color: var(--prototype-review-brand, var(--border-default));\n}\n\n.hexInput:focus-visible {\n outline: var(--focus-ring-width, 2px) solid\n var(--focus-ring-color, var(--prototype-review-brand, var(--primary)));\n outline-offset: var(--focus-ring-offset, 2px);\n}\n\n.resetButton {\n background: transparent;\n border: var(--stroke-width-thin, 1px) solid var(--border-default);\n color: var(--text-tertiary);\n font-family: var(--font-mono, var(--font-family-mono, monospace));\n font-size: var(--font-size-xs);\n letter-spacing: 0.1em;\n text-transform: uppercase;\n padding: var(--spacing-1) var(--spacing-3);\n border-radius: var(--radius-full, 9999px);\n cursor: pointer;\n transition:\n color var(--motion-duration-fast, 150ms)\n var(--motion-easing-standard, ease),\n border-color var(--motion-duration-fast, 150ms)\n var(--motion-easing-standard, ease);\n}\n\n.resetButton:hover {\n color: var(--prototype-review-brand, var(--text-primary));\n border-color: var(--prototype-review-brand, var(--border-strong));\n}\n\n.resetButton:focus-visible {\n outline: var(--focus-ring-width, 2px) solid\n var(--focus-ring-color, var(--prototype-review-brand, var(--primary)));\n outline-offset: var(--focus-ring-offset, 2px);\n}\n\n/* ─── Stage ──────────────────────────────────────────────── */\n\n.stage {\n padding: var(--spacing-7);\n max-width: 100%;\n}\n\n.stageMeta {\n display: flex;\n gap: var(--spacing-6);\n align-items: flex-start;\n justify-content: space-between;\n margin-bottom: var(--spacing-5);\n flex-wrap: wrap;\n}\n\n.stageTitleBlock {\n min-width: 0;\n max-width: 56rem;\n}\n\n.stageTitle {\n font-family: var(\n --font-display,\n var(--font-family-display, var(--font-family-heading, inherit))\n );\n font-weight: 500;\n font-size: var(--font-size-2xl);\n letter-spacing: -0.01em;\n line-height: 1.2;\n margin-bottom: var(--spacing-1);\n}\n\n.stageTitle em {\n font-style: normal;\n color: var(--prototype-review-brand, var(--primary));\n}\n\n.stageSummary {\n color: var(--text-secondary);\n font-size: var(--font-size-base);\n line-height: 1.6;\n}\n\n.stageTagRow {\n display: flex;\n gap: var(--spacing-2);\n flex-wrap: wrap;\n}\n\n/* Viewport grid */\n\n.viewportGrid {\n display: grid;\n gap: var(--spacing-6);\n grid-template-columns: 375px 768px 1280px;\n overflow-x: auto;\n padding-bottom: var(--spacing-4);\n}\n\n.viewportGridSolo {\n grid-template-columns: 1fr;\n}\n\n.vpFrame {\n background: var(--surface-card);\n border: var(--stroke-width-thin, 1px) solid var(--border-default);\n border-radius: var(--radius-lg);\n overflow: hidden;\n display: flex;\n flex-direction: column;\n min-width: 0;\n}\n\n.vpFrameHead {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: var(--spacing-2) var(--spacing-3);\n border-bottom: var(--stroke-width-thin, 1px) solid var(--border-muted);\n background: var(--surface-muted, var(--surface-subtle));\n}\n\n.vpFrameName {\n font-family: var(--font-mono, var(--font-family-mono, monospace));\n font-size: var(--font-size-xs);\n letter-spacing: 0.12em;\n text-transform: uppercase;\n color: var(--text-tertiary);\n}\n\n.vpFrameDims {\n font-family: var(--font-mono, var(--font-family-mono, monospace));\n font-size: var(--font-size-xs);\n color: var(--text-disabled, var(--text-tertiary));\n}\n\n.vpIframeWrap {\n background: var(--surface-page);\n}\n\n.vpIframe {\n width: 100%;\n border: none;\n display: block;\n background: var(--surface-page);\n}\n\n/* ─── Landing ────────────────────────────────────────────── */\n\n.landing {\n max-width: 64rem;\n margin: 0 auto;\n padding: var(--spacing-12, 3.5rem) var(--spacing-7);\n}\n\n.landingEyebrow {\n font-family: var(--font-mono, var(--font-family-mono, monospace));\n font-size: var(--font-size-sm);\n letter-spacing: 0.18em;\n text-transform: uppercase;\n color: var(--prototype-review-brand, var(--primary));\n margin-bottom: var(--spacing-4);\n}\n\n.landingTitle {\n font-family: var(\n --font-display,\n var(--font-family-display, var(--font-family-heading, inherit))\n );\n font-weight: 500;\n font-size: clamp(2rem, 4.5vw, 3.25rem);\n line-height: 1.05;\n letter-spacing: -0.02em;\n margin-bottom: var(--spacing-5);\n}\n\n.landingTitle em {\n font-style: normal;\n color: var(--prototype-review-brand, var(--primary));\n}\n\n.landingLede {\n font-size: var(--font-size-lg);\n color: var(--text-secondary);\n line-height: 1.65;\n margin-bottom: var(--spacing-10, 2.5rem);\n max-width: 48rem;\n}\n\n.landingLede code {\n font-family: var(--font-mono, var(--font-family-mono, monospace));\n color: var(--prototype-review-brand, var(--primary));\n font-size: 0.95em;\n}\n\n.protoGrid {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));\n gap: var(--spacing-5);\n margin-bottom: var(--spacing-12, 3rem);\n}\n\n.protoCard {\n background: var(--surface-card);\n border: var(--stroke-width-thin, 1px) solid var(--border-default);\n border-radius: var(--radius-lg);\n padding: var(--spacing-6);\n cursor: pointer;\n text-align: left;\n font-family: inherit;\n color: inherit;\n display: flex;\n flex-direction: column;\n gap: var(--spacing-3);\n transition:\n border-color var(--motion-duration-fast, 150ms)\n var(--motion-easing-standard, ease),\n background var(--motion-duration-fast, 150ms)\n var(--motion-easing-standard, ease);\n}\n\n.protoCard:hover {\n border-color: var(--prototype-review-brand, var(--border-strong));\n background: var(--surface-interactive-hover, var(--surface-subtle));\n}\n\n.protoCard:focus-visible {\n outline: var(--focus-ring-width, 2px) solid\n var(--focus-ring-color, var(--prototype-review-brand, var(--primary)));\n outline-offset: var(--focus-ring-offset, 2px);\n}\n\n.protoCardId {\n font-family: var(--font-mono, var(--font-family-mono, monospace));\n font-size: var(--font-size-xs);\n letter-spacing: 0.18em;\n text-transform: uppercase;\n color: var(--prototype-review-brand, var(--primary));\n}\n\n.protoCardTitle {\n font-family: var(\n --font-display,\n var(--font-family-display, var(--font-family-heading, inherit))\n );\n font-weight: 500;\n font-size: var(--font-size-xl, 1.25rem);\n letter-spacing: -0.01em;\n}\n\n.protoCardDesc {\n color: var(--text-secondary);\n font-size: var(--font-size-sm);\n line-height: 1.55;\n}\n\n.protoCardMeta {\n margin-top: auto;\n font-family: var(--font-mono, var(--font-family-mono, monospace));\n font-size: var(--font-size-xs);\n color: var(--text-tertiary);\n letter-spacing: 0.05em;\n text-transform: uppercase;\n}\n\n.ctxGrid {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr));\n gap: var(--spacing-5);\n margin-top: var(--spacing-10, 2.5rem);\n padding-top: var(--spacing-8);\n border-top: var(--stroke-width-thin, 1px) solid var(--border-muted);\n}\n\n.ctxCard h4 {\n font-family: var(--font-mono, var(--font-family-mono, monospace));\n font-size: var(--font-size-sm);\n text-transform: uppercase;\n letter-spacing: 0.12em;\n color: var(--prototype-review-brand, var(--primary));\n margin-bottom: var(--spacing-2);\n}\n\n.ctxCard p {\n color: var(--text-secondary);\n font-size: var(--font-size-sm);\n line-height: 1.6;\n}\n\n/* ─── Footer ─────────────────────────────────────────────── */\n\n.foot {\n border-top: var(--stroke-width-thin, 1px) solid var(--border-muted);\n padding: var(--spacing-6) var(--spacing-7);\n display: flex;\n justify-content: space-between;\n gap: var(--spacing-4);\n flex-wrap: wrap;\n font-family: var(--font-mono, var(--font-family-mono, monospace));\n font-size: var(--font-size-xs);\n color: var(--text-tertiary);\n letter-spacing: 0.06em;\n text-transform: uppercase;\n margin-top: auto;\n}\n"
4946
+ "content": "/* ============================================================\n Prototype Review block\n Theme-agnostic. All colors come from Visor semantic tokens.\n The brand color is injected by the React block as\n --prototype-review-brand (per-instance override).\n ============================================================ */\n\n.root {\n display: flex;\n flex-direction: column;\n width: 100%;\n min-height: 100vh;\n background: var(--surface-page);\n color: var(--text-primary);\n font-family: var(\n --font-body,\n var(--font-family-body, ui-sans-serif, system-ui, sans-serif)\n );\n font-weight: 300;\n line-height: 1.5;\n -webkit-font-smoothing: antialiased;\n container-type: inline-size;\n}\n\n/* ─── Header ─────────────────────────────────────────────── */\n\n.chrome {\n position: sticky;\n top: 0;\n z-index: 100;\n background: var(--surface-card);\n border-bottom: var(--stroke-width-thin, 1px) solid var(--border-muted);\n}\n\n.chromeRow {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--spacing-6);\n padding: var(--spacing-3) var(--spacing-7);\n flex-wrap: wrap;\n}\n\n.brand {\n display: flex;\n align-items: center;\n gap: var(--spacing-3);\n min-width: 0;\n}\n\n.brandMark {\n width: 1.75rem;\n height: 1.75rem;\n background: var(--prototype-review-brand, var(--interactive-primary-bg));\n display: grid;\n place-items: center;\n color: var(--prototype-review-brand-on, var(--interactive-primary-text));\n font-family: var(\n --font-display,\n var(--font-family-display, var(--font-family-heading, inherit))\n );\n font-weight: 700;\n font-size: var(--font-size-xs);\n letter-spacing: -0.02em;\n}\n\n.brandText {\n display: flex;\n flex-direction: column;\n line-height: 1.15;\n}\n\n.brandName {\n font-family: var(\n --font-display,\n var(--font-family-display, var(--font-family-heading, inherit))\n );\n font-weight: 600;\n font-size: var(--font-size-sm);\n letter-spacing: 0.12em;\n text-transform: uppercase;\n}\n\n.brandSub {\n font-family: var(--font-mono, var(--font-family-mono, monospace));\n font-size: var(--font-size-xs);\n color: var(--text-tertiary);\n letter-spacing: 0.05em;\n}\n\n.chromeActions {\n display: flex;\n gap: var(--spacing-2);\n align-items: center;\n flex-wrap: wrap;\n}\n\n.pill {\n font-family: var(--font-mono, var(--font-family-mono, monospace));\n font-size: var(--font-size-xs);\n text-transform: uppercase;\n letter-spacing: 0.12em;\n padding: var(--spacing-1) var(--spacing-2);\n border: var(--stroke-width-thin, 1px) solid var(--border-default);\n color: var(--text-tertiary);\n border-radius: var(--radius-full, 9999px);\n}\n\n.pillBrand {\n background: var(--prototype-review-brand-soft, var(--surface-subtle));\n border-color: var(--prototype-review-brand, var(--border-default));\n color: var(--prototype-review-brand, var(--text-primary));\n}\n\n/* ─── Controls ───────────────────────────────────────────── */\n\n.controls {\n border-bottom: var(--stroke-width-thin, 1px) solid var(--border-muted);\n background: var(--surface-muted, var(--surface-subtle));\n}\n\n.controlsRow {\n display: grid;\n grid-template-columns: minmax(0, 1fr) auto auto;\n gap: var(--spacing-6);\n align-items: center;\n padding: var(--spacing-3) var(--spacing-7);\n}\n\n@container (max-width: 64rem) {\n .controlsRow {\n grid-template-columns: 1fr;\n }\n}\n\n.controlGroup {\n display: flex;\n align-items: center;\n gap: var(--spacing-4);\n flex-wrap: wrap;\n}\n\n.controlLabel {\n font-family: var(--font-mono, var(--font-family-mono, monospace));\n font-size: var(--font-size-xs);\n letter-spacing: 0.12em;\n text-transform: uppercase;\n color: var(--text-tertiary);\n}\n\n/* Tabs */\n\n.tabs {\n display: flex;\n gap: 0;\n flex-wrap: wrap;\n align-items: stretch;\n border: var(--stroke-width-thin, 1px) solid var(--border-default);\n background: var(--surface-page);\n width: fit-content;\n border-radius: var(--radius-full, 9999px);\n overflow: hidden;\n}\n\n.tab {\n background: transparent;\n border: none;\n color: var(--text-tertiary);\n font-family: var(--font-mono, var(--font-family-mono, monospace));\n font-size: var(--font-size-xs);\n letter-spacing: 0.08em;\n text-transform: uppercase;\n padding: var(--spacing-2) var(--spacing-4);\n cursor: pointer;\n transition:\n color var(--motion-duration-fast, 150ms)\n var(--motion-easing-standard, ease),\n background var(--motion-duration-fast, 150ms)\n var(--motion-easing-standard, ease);\n}\n\n.tab:hover {\n color: var(--text-primary);\n}\n\n.tab[aria-selected=\"true\"] {\n background: var(--prototype-review-brand, var(--interactive-primary-bg));\n color: var(--prototype-review-brand-on, var(--interactive-primary-text));\n}\n\n.tab:focus-visible {\n outline: var(--focus-ring-width, 2px) solid\n var(--focus-ring-color, var(--prototype-review-brand, var(--primary)));\n outline-offset: calc(var(--focus-ring-offset, 2px) * -1);\n}\n\n.tabId {\n font-family: var(\n --font-display,\n var(--font-family-display, var(--font-family-heading, inherit))\n );\n font-weight: 600;\n letter-spacing: 0.02em;\n text-transform: none;\n font-size: var(--font-size-sm);\n margin-right: var(--spacing-2);\n}\n\n/* Theme select */\n\n.themeGroup {\n display: flex;\n align-items: center;\n gap: var(--spacing-2);\n}\n\n.themeSelect {\n background: var(--surface-page);\n border: var(--stroke-width-thin, 1px) solid var(--border-default);\n color: var(--text-primary);\n font-family: var(--font-mono, var(--font-family-mono, monospace));\n font-size: var(--font-size-xs);\n padding: var(--spacing-2) var(--spacing-3);\n border-radius: var(--radius-full, 9999px);\n cursor: pointer;\n letter-spacing: 0.05em;\n text-transform: uppercase;\n}\n\n.themeSelect:focus-visible {\n outline: var(--focus-ring-width, 2px) solid\n var(--focus-ring-color, var(--prototype-review-brand, var(--primary)));\n outline-offset: var(--focus-ring-offset, 2px);\n}\n\n/* Mode + viewport toggle buttons */\n\n.modeGroup,\n.vpGroup {\n display: flex;\n align-items: center;\n gap: var(--spacing-2);\n}\n\n.toggleButtons {\n display: flex;\n border: var(--stroke-width-thin, 1px) solid var(--border-default);\n background: var(--surface-page);\n border-radius: var(--radius-full, 9999px);\n overflow: hidden;\n}\n\n.toggleButton {\n background: transparent;\n border: none;\n color: var(--text-tertiary);\n font-family: var(--font-mono, var(--font-family-mono, monospace));\n font-size: var(--font-size-xs);\n letter-spacing: 0.05em;\n padding: var(--spacing-2) var(--spacing-3);\n cursor: pointer;\n text-transform: uppercase;\n transition:\n color var(--motion-duration-fast, 150ms)\n var(--motion-easing-standard, ease),\n background var(--motion-duration-fast, 150ms)\n var(--motion-easing-standard, ease);\n}\n\n.toggleButton:hover {\n color: var(--text-primary);\n}\n\n.toggleButton[aria-pressed=\"true\"] {\n background: var(--prototype-review-brand, var(--interactive-primary-bg));\n color: var(--prototype-review-brand-on, var(--interactive-primary-text));\n}\n\n.toggleButton:focus-visible {\n outline: var(--focus-ring-width, 2px) solid\n var(--focus-ring-color, var(--prototype-review-brand, var(--primary)));\n outline-offset: calc(var(--focus-ring-offset, 2px) * -1);\n}\n\n/* Brand picker */\n\n.picker {\n display: flex;\n align-items: center;\n gap: var(--spacing-3);\n flex-wrap: wrap;\n}\n\n.swatches {\n display: flex;\n gap: var(--spacing-1);\n align-items: center;\n}\n\n.swatch {\n width: 1.375rem;\n height: 1.375rem;\n border-radius: var(--radius-full, 9999px);\n border: var(--stroke-width-medium, 2px) solid transparent;\n cursor: pointer;\n padding: 0;\n transition:\n transform var(--motion-duration-fast, 150ms)\n var(--motion-easing-standard, ease),\n border-color var(--motion-duration-fast, 150ms)\n var(--motion-easing-standard, ease);\n}\n\n.swatch:hover {\n transform: scale(1.12);\n}\n\n.swatch[data-active=\"true\"] {\n border-color: var(--text-primary);\n box-shadow: 0 0 0 var(--stroke-width-medium, 2px) var(--surface-page);\n}\n\n.swatch:focus-visible {\n outline: var(--focus-ring-width, 2px) solid\n var(--focus-ring-color, var(--prototype-review-brand, var(--primary)));\n outline-offset: var(--focus-ring-offset, 2px);\n}\n\n.hexInput {\n background: var(--surface-page);\n border: var(--stroke-width-thin, 1px) solid var(--border-default);\n color: var(--text-primary);\n font-family: var(--font-mono, var(--font-family-mono, monospace));\n font-size: var(--font-size-xs);\n padding: var(--spacing-1) var(--spacing-3);\n width: 8.5rem;\n letter-spacing: 0.05em;\n text-transform: uppercase;\n border-radius: var(--radius-full, 9999px);\n}\n\n.hexInput:focus {\n outline: none;\n border-color: var(--prototype-review-brand, var(--border-default));\n}\n\n.hexInput:focus-visible {\n outline: var(--focus-ring-width, 2px) solid\n var(--focus-ring-color, var(--prototype-review-brand, var(--primary)));\n outline-offset: var(--focus-ring-offset, 2px);\n}\n\n.resetButton {\n background: transparent;\n border: var(--stroke-width-thin, 1px) solid var(--border-default);\n color: var(--text-tertiary);\n font-family: var(--font-mono, var(--font-family-mono, monospace));\n font-size: var(--font-size-xs);\n letter-spacing: 0.1em;\n text-transform: uppercase;\n padding: var(--spacing-1) var(--spacing-3);\n border-radius: var(--radius-full, 9999px);\n cursor: pointer;\n transition:\n color var(--motion-duration-fast, 150ms)\n var(--motion-easing-standard, ease),\n border-color var(--motion-duration-fast, 150ms)\n var(--motion-easing-standard, ease);\n}\n\n.resetButton:hover {\n color: var(--prototype-review-brand, var(--text-primary));\n border-color: var(--prototype-review-brand, var(--border-strong));\n}\n\n.resetButton:focus-visible {\n outline: var(--focus-ring-width, 2px) solid\n var(--focus-ring-color, var(--prototype-review-brand, var(--primary)));\n outline-offset: var(--focus-ring-offset, 2px);\n}\n\n/* ─── Stage ──────────────────────────────────────────────── */\n\n.stage {\n padding: var(--spacing-7);\n max-width: 100%;\n}\n\n.stageMeta {\n display: flex;\n gap: var(--spacing-6);\n align-items: flex-start;\n justify-content: space-between;\n margin-bottom: var(--spacing-5);\n flex-wrap: wrap;\n}\n\n.stageTitleBlock {\n min-width: 0;\n max-width: 56rem;\n}\n\n.stageTitle {\n font-family: var(\n --font-display,\n var(--font-family-display, var(--font-family-heading, inherit))\n );\n font-weight: 500;\n font-size: var(--font-size-2xl);\n letter-spacing: -0.01em;\n line-height: 1.2;\n margin-bottom: var(--spacing-1);\n}\n\n.stageTitle em {\n font-style: normal;\n color: var(--prototype-review-brand, var(--primary));\n}\n\n.stageSummary {\n color: var(--text-secondary);\n font-size: var(--font-size-base);\n line-height: 1.6;\n}\n\n.stageTagRow {\n display: flex;\n gap: var(--spacing-2);\n flex-wrap: wrap;\n}\n\n/* Viewport grid */\n\n.viewportGrid {\n display: grid;\n gap: var(--spacing-6);\n grid-template-columns: 375px 768px 1280px;\n overflow-x: auto;\n padding-bottom: var(--spacing-4);\n}\n\n.viewportGridSolo {\n grid-template-columns: 1fr;\n}\n\n.vpFrame {\n background: var(--surface-card);\n border: var(--stroke-width-thin, 1px) solid var(--border-default);\n border-radius: var(--radius-lg);\n overflow: hidden;\n display: flex;\n flex-direction: column;\n min-width: 0;\n}\n\n.vpFrameHead {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: var(--spacing-2) var(--spacing-3);\n border-bottom: var(--stroke-width-thin, 1px) solid var(--border-muted);\n background: var(--surface-muted, var(--surface-subtle));\n}\n\n.vpFrameName {\n font-family: var(--font-mono, var(--font-family-mono, monospace));\n font-size: var(--font-size-xs);\n letter-spacing: 0.12em;\n text-transform: uppercase;\n color: var(--text-tertiary);\n}\n\n.vpFrameDims {\n font-family: var(--font-mono, var(--font-family-mono, monospace));\n font-size: var(--font-size-xs);\n color: var(--text-disabled, var(--text-tertiary));\n}\n\n.vpIframeWrap {\n background: var(--surface-page);\n}\n\n.vpIframe {\n width: 100%;\n border: none;\n display: block;\n background: var(--surface-page);\n}\n\n/* ─── Landing ────────────────────────────────────────────── */\n\n.landing {\n max-width: 64rem;\n margin: 0 auto;\n padding: var(--spacing-12, 3.5rem) var(--spacing-7);\n}\n\n.landingEyebrow {\n font-family: var(--font-mono, var(--font-family-mono, monospace));\n font-size: var(--font-size-sm);\n letter-spacing: 0.18em;\n text-transform: uppercase;\n color: var(--prototype-review-brand, var(--primary));\n margin-bottom: var(--spacing-4);\n}\n\n.landingTitle {\n font-family: var(\n --font-display,\n var(--font-family-display, var(--font-family-heading, inherit))\n );\n font-weight: 500;\n font-size: clamp(2rem, 4.5vw, 3.25rem);\n line-height: 1.05;\n letter-spacing: -0.02em;\n margin-bottom: var(--spacing-5);\n}\n\n.landingTitle em {\n font-style: normal;\n color: var(--prototype-review-brand, var(--primary));\n}\n\n.landingLede {\n font-size: var(--font-size-lg);\n color: var(--text-secondary);\n line-height: 1.65;\n margin-bottom: var(--spacing-10, 2.5rem);\n max-width: 48rem;\n}\n\n.landingLede code {\n font-family: var(--font-mono, var(--font-family-mono, monospace));\n color: var(--prototype-review-brand, var(--primary));\n font-size: 0.95em;\n}\n\n.protoGrid {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));\n gap: var(--spacing-5);\n margin-bottom: var(--spacing-12, 3rem);\n}\n\n.protoCard {\n background: var(--surface-card);\n border: var(--stroke-width-thin, 1px) solid var(--border-default);\n border-radius: var(--radius-lg);\n padding: var(--spacing-6);\n cursor: pointer;\n text-align: left;\n color: inherit;\n display: flex;\n flex-direction: column;\n gap: var(--spacing-3);\n transition:\n border-color var(--motion-duration-fast, 150ms)\n var(--motion-easing-standard, ease),\n background var(--motion-duration-fast, 150ms)\n var(--motion-easing-standard, ease);\n}\n\n.protoCard:hover {\n border-color: var(--prototype-review-brand, var(--border-strong));\n background: var(--surface-interactive-hover, var(--surface-subtle));\n}\n\n.protoCard:focus-visible {\n outline: var(--focus-ring-width, 2px) solid\n var(--focus-ring-color, var(--prototype-review-brand, var(--primary)));\n outline-offset: var(--focus-ring-offset, 2px);\n}\n\n.protoCardId {\n font-family: var(--font-mono, var(--font-family-mono, monospace));\n font-size: var(--font-size-xs);\n letter-spacing: 0.18em;\n text-transform: uppercase;\n color: var(--prototype-review-brand, var(--primary));\n}\n\n.protoCardTitle {\n font-family: var(\n --font-display,\n var(--font-family-display, var(--font-family-heading, inherit))\n );\n font-weight: 500;\n font-size: var(--font-size-xl, 1.25rem);\n letter-spacing: -0.01em;\n}\n\n.protoCardDesc {\n color: var(--text-secondary);\n font-size: var(--font-size-sm);\n line-height: 1.55;\n}\n\n.protoCardMeta {\n margin-top: auto;\n font-family: var(--font-mono, var(--font-family-mono, monospace));\n font-size: var(--font-size-xs);\n color: var(--text-tertiary);\n letter-spacing: 0.05em;\n text-transform: uppercase;\n}\n\n.ctxGrid {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr));\n gap: var(--spacing-5);\n margin-top: var(--spacing-10, 2.5rem);\n padding-top: var(--spacing-8);\n border-top: var(--stroke-width-thin, 1px) solid var(--border-muted);\n}\n\n.ctxCard h4 {\n font-family: var(--font-mono, var(--font-family-mono, monospace));\n font-size: var(--font-size-sm);\n text-transform: uppercase;\n letter-spacing: 0.12em;\n color: var(--prototype-review-brand, var(--primary));\n margin-bottom: var(--spacing-2);\n}\n\n.ctxCard p {\n color: var(--text-secondary);\n font-size: var(--font-size-sm);\n line-height: 1.6;\n}\n\n/* ─── Footer ─────────────────────────────────────────────── */\n\n.foot {\n border-top: var(--stroke-width-thin, 1px) solid var(--border-muted);\n padding: var(--spacing-6) var(--spacing-7);\n display: flex;\n justify-content: space-between;\n gap: var(--spacing-4);\n flex-wrap: wrap;\n font-family: var(--font-mono, var(--font-family-mono, monospace));\n font-size: var(--font-size-xs);\n color: var(--text-tertiary);\n letter-spacing: 0.06em;\n text-transform: uppercase;\n margin-top: auto;\n}\n"
4893
4947
  }
4894
4948
  ]
4895
4949
  },