@ai-matrx/design-system 0.86.349 → 0.86.351

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.
Files changed (96) hide show
  1. package/CHANGELOG.md +22 -2
  2. package/dist/carousel.cjs.map +1 -1
  3. package/dist/carousel.js +5 -5
  4. package/dist/chunk-4WSXAP24.js +51 -0
  5. package/dist/chunk-4WSXAP24.js.map +1 -0
  6. package/dist/{chunk-XTP6HOB6.js → chunk-6XNYYROM.js} +1 -1
  7. package/dist/chunk-6XNYYROM.js.map +1 -0
  8. package/dist/{chunk-CEA6X445.js → chunk-CFUXEGW2.js} +2 -2
  9. package/dist/{chunk-54UK6P7E.js → chunk-FLWSEDUW.js} +3 -3
  10. package/dist/{chunk-BC7LMEOD.js → chunk-GJ6UGQ4X.js} +7 -3
  11. package/dist/chunk-GJ6UGQ4X.js.map +1 -0
  12. package/dist/{chunk-6CDAHINE.js → chunk-GMNROZQJ.js} +4 -4
  13. package/dist/{chunk-6CDAHINE.js.map → chunk-GMNROZQJ.js.map} +1 -1
  14. package/dist/{chunk-6QKT52FR.js → chunk-MTE6N7XU.js} +2 -2
  15. package/dist/{chunk-S6F34AX5.js → chunk-QA7EHFRX.js} +2 -2
  16. package/dist/{chunk-CJBSBKG5.js → chunk-SOCNWQMX.js} +2 -2
  17. package/dist/{chunk-GLLPO66A.js → chunk-U46XUQI7.js} +2 -2
  18. package/dist/{chunk-KYH42WEX.js → chunk-UGQRAQTE.js} +433 -344
  19. package/dist/chunk-UGQRAQTE.js.map +1 -0
  20. package/dist/{chunk-TWRC7NP4.js → chunk-WUD23YTG.js} +4 -4
  21. package/dist/{chunk-MIJMP4WI.js → chunk-YRF22M5S.js} +6 -1
  22. package/dist/{chunk-MIJMP4WI.js.map → chunk-YRF22M5S.js.map} +1 -1
  23. package/dist/clipboard-fallback-dialog.cjs.map +1 -1
  24. package/dist/clipboard-fallback-dialog.js +1 -1
  25. package/dist/controls.cjs +547 -458
  26. package/dist/controls.cjs.map +1 -1
  27. package/dist/controls.css +52 -18
  28. package/dist/controls.d.cts +51 -3
  29. package/dist/controls.d.ts +51 -3
  30. package/dist/controls.js +13 -5
  31. package/dist/data-table/data-row-inspector.cjs.map +1 -1
  32. package/dist/data-table/data-row-inspector.js +4 -4
  33. package/dist/data-table/data-row-window.cjs.map +1 -1
  34. package/dist/data-table/data-row-window.js +5 -5
  35. package/dist/data-table/index.cjs +53 -43
  36. package/dist/data-table/index.cjs.map +1 -1
  37. package/dist/data-table/index.js +52 -45
  38. package/dist/data-table/index.js.map +1 -1
  39. package/dist/data-table/pagination.cjs.map +1 -1
  40. package/dist/data-table/pagination.js +2 -2
  41. package/dist/data-table/spreadsheet.cjs +6 -2
  42. package/dist/data-table/spreadsheet.cjs.map +1 -1
  43. package/dist/data-table/spreadsheet.d.cts +4 -1
  44. package/dist/data-table/spreadsheet.d.ts +4 -1
  45. package/dist/data-table/spreadsheet.js +3 -1
  46. package/dist/data-table/uuid-cell.cjs.map +1 -1
  47. package/dist/data-table/uuid-cell.js +2 -2
  48. package/dist/desktop.cjs +158 -16
  49. package/dist/desktop.cjs.map +1 -1
  50. package/dist/desktop.css +46 -0
  51. package/dist/desktop.d.cts +6 -5
  52. package/dist/desktop.d.ts +6 -5
  53. package/dist/desktop.js +127 -17
  54. package/dist/desktop.js.map +1 -1
  55. package/dist/index.cjs +19 -9
  56. package/dist/index.cjs.map +1 -1
  57. package/dist/index.d.cts +10 -1
  58. package/dist/index.d.ts +10 -1
  59. package/dist/index.js +21 -14
  60. package/dist/index.js.map +1 -1
  61. package/dist/item.cjs.map +1 -1
  62. package/dist/item.js +2 -2
  63. package/dist/lite-table.cjs.map +1 -1
  64. package/dist/lite-table.js +1 -1
  65. package/dist/notice-stack.cjs +70 -0
  66. package/dist/notice-stack.cjs.map +1 -0
  67. package/dist/notice-stack.d.cts +60 -0
  68. package/dist/notice-stack.d.ts +60 -0
  69. package/dist/notice-stack.js +16 -0
  70. package/dist/notice-stack.js.map +1 -0
  71. package/dist/record-list.cjs.map +1 -1
  72. package/dist/record-list.js +2 -2
  73. package/dist/settings.cjs +2 -2
  74. package/dist/settings.cjs.map +1 -1
  75. package/dist/settings.js +3 -3
  76. package/dist/swipe-deck.cjs +95 -25
  77. package/dist/swipe-deck.cjs.map +1 -1
  78. package/dist/swipe-deck.css +14 -0
  79. package/dist/swipe-deck.d.cts +20 -0
  80. package/dist/swipe-deck.d.ts +20 -0
  81. package/dist/swipe-deck.js +87 -25
  82. package/dist/swipe-deck.js.map +1 -1
  83. package/dist/writing-field.cjs +2 -2
  84. package/dist/writing-field.cjs.map +1 -1
  85. package/dist/writing-field.js +2 -2
  86. package/package.json +12 -18
  87. package/dist/chunk-BC7LMEOD.js.map +0 -1
  88. package/dist/chunk-KYH42WEX.js.map +0 -1
  89. package/dist/chunk-XTP6HOB6.js.map +0 -1
  90. /package/dist/{chunk-CEA6X445.js.map → chunk-CFUXEGW2.js.map} +0 -0
  91. /package/dist/{chunk-54UK6P7E.js.map → chunk-FLWSEDUW.js.map} +0 -0
  92. /package/dist/{chunk-6QKT52FR.js.map → chunk-MTE6N7XU.js.map} +0 -0
  93. /package/dist/{chunk-S6F34AX5.js.map → chunk-QA7EHFRX.js.map} +0 -0
  94. /package/dist/{chunk-CJBSBKG5.js.map → chunk-SOCNWQMX.js.map} +0 -0
  95. /package/dist/{chunk-GLLPO66A.js.map → chunk-U46XUQI7.js.map} +0 -0
  96. /package/dist/{chunk-TWRC7NP4.js.map → chunk-WUD23YTG.js.map} +0 -0
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/writing-field/index.ts","../src/writing-field/pro-textarea.tsx","../src/cn.ts","../src/label.tsx","../src/dialog.tsx","../src/motion.ts","../src/close-slot.tsx","../src/icons.tsx","../src/portal-container.tsx","../src/look.tsx","../src/radix-dialog-modal-context.tsx","../src/use-is-mobile.ts","../src/layer-front.ts","../src/window-drag.ts","../src/drag-cursor.ts","../src/floating-layer.tsx","../src/title-tooltips.ts","../src/focus-return.ts","../src/popover.tsx","../src/solid-surface.ts","../src/tap-target/tap-target-button.tsx","../src/tooltip.tsx","../src/tap-target/tap-target-guard.ts","../src/layout-scale.ts","../src/tap-target/tap-surface.tsx","../src/tap-target/tap-features.tsx","../src/tap-shortcut.ts","../src/tap-target/link.ts","../src/tap-target/tap-buttons.tsx","../src/tap-target/tap-default-variant.tsx","../src/stand-in-notice.ts","../src/writing-field/control-fit.ts","../src/writing-field/control-placement.ts","../src/writing-field/add-ons.tsx","../src/controls/surfaces.tsx","../src/button.tsx","../src/alert-dialog.tsx","../src/controls/controls.tsx","../src/field-surface.ts","../src/textarea.tsx","../src/writing-field/voice-chrome.tsx","../src/writing-field/pro-input.tsx","../src/writing-field/reserved-padding.ts"],"sourcesContent":["\"use client\";\n\n/**\n * @ai-matrx/design-system/writing-field — THE writing field (one-ui-system rule 6): `ProTextarea`\n * and `ProInput`, plus the add-on ports a host registers once at its root\n * (`WritingFieldAddOnsProvider`). Moved from matrx-frontend `components/official/` (2026-10-22).\n *\n * The add-on props (`surfaceName`, `getApplicationScope`, `cleanupContextItems`, …) are typed by the\n * add-ons' owner through module augmentation, so this package never imports their types:\n *\n * declare module \"@ai-matrx/design-system/writing-field\" {\n * interface ProTextareaAddOnProps { surfaceName?: string; … }\n * }\n */\n\n/** Props a ProTextarea's add-ons read; the add-ons' owner augments this interface. */\n// eslint-disable-next-line @typescript-eslint/no-empty-object-type\nexport interface ProTextareaAddOnProps {}\n\n/** Props a ProInput's add-ons read; the add-ons' owner augments this interface. */\n// eslint-disable-next-line @typescript-eslint/no-empty-object-type\nexport interface ProInputAddOnProps {}\n\nexport {\n ProTextarea,\n StandInMenu,\n type DictationRefusalReason,\n type DictationStartResult,\n type ProTextareaElement,\n type ProTextareaProps,\n} from \"./pro-textarea\";\nexport { ProInput, type ProInputElement, type ProInputProps } from \"./pro-input\";\nexport {\n ADD_ON_PROP_NAMES,\n WritingFieldAddOnsProvider,\n announceMissingPort,\n splitAddOnProps,\n useWritingFieldAddOns,\n type WritingFieldAddOns,\n type WritingFieldApi,\n type WritingFieldContextMenuProps,\n type WritingFieldMenuProps,\n type WritingFieldMicButtonProps,\n type WritingFieldNotify,\n type WritingFieldTextStats,\n type WritingFieldVoice,\n type WritingFieldVoiceOptions,\n} from \"./add-ons\";\nexport { FieldMenuRow, VoiceProtectionDialog, micAriaLabel } from \"./voice-chrome\";\nexport * from \"./control-fit\";\nexport * from \"./control-placement\";\nexport * from \"./reserved-padding\";\nexport type * from \"./editor-slot\";\n","\"use client\";\n\n/**\n * ProTextarea — THE box a person writes words in (one-ui-system rule 6). Moved from\n * matrx-frontend `components/official/ProTextarea.tsx` (2026-10-22): the field core lives here; the\n * recorder, the \"…\" actions, the page's agents, the right-click menu, markdown formatting and text\n * stats arrive through the add-on ports (`./add-ons.tsx`), registered once at the host root.\n *\n * Built in: auto-grow (`autoGrow` + `minHeight`/`maxHeight`), floating label, `hero` appearance,\n * the reserved control row or the `inline` composer shape (`controls`), the ONE fitting rule\n * (`./control-fit.ts`: whatever does not fit beside the text folds into \"…\", never deleted), submit\n * (`onSubmit`, ⌘/Ctrl+Enter, `submitOnEnter`, the one composer rule from `@ai-matrx/kit/composer-keys`),\n * field navigation (`onEnterKey`), a `leading` slot, Expand (`expandable`), a hosted editor\n * (`editor`, `./editor-slot.ts`), the pre-hydration keep, and the dictation handle: the forwarded\n * node is a real `HTMLTextAreaElement` carrying `startDictation()` / `stopDictation()` /\n * `isDictating()` / `requestClose()` / `isTranscribing()`; a refusal always returns a named reason\n * with a sentence AND says it on screen (notify + `onTranscriptionError`).\n */\nimport * as React from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { composerKeyIntent, intentTakesTheKey } from \"@ai-matrx/kit/composer-keys\";\nimport { useMediaQuery } from \"@ai-matrx/kit/media-query\";\nimport { copyText } from \"@ai-matrx/kit/clipboard\";\nimport { cn } from \"../cn\";\nimport { Label } from \"../label\";\nimport { Dialog, DialogContent, DialogTitle } from \"../dialog\";\nimport { Popover, PopoverContent, PopoverTrigger } from \"../popover\";\nimport { TapTargetButtonSolid } from \"../tap-target/tap-target-button\";\nimport { MaximizeTapButton, MoreHorizontalTapButton } from \"../tap-target/tap-buttons\";\nimport { CopyIcon, Loader2Icon, Maximize2Icon, MicIcon, SendIcon, SlidersHorizontalIcon } from \"../icons\";\nimport { UNCONFIGURED } from \"../stand-in-notice\";\nimport { DENSE_SIZES, controlSizes, fitFieldControls } from \"./control-fit\";\nimport {\n INLINE_CONTROLS_MIN_HEIGHT_PX,\n TAP_HALF_GAP_PX,\n inlineControlsFieldPadding,\n proTextareaClusterPlacement,\n type ProTextareaControls,\n} from \"./control-placement\";\nimport type { ProTextareaEditorSlot } from \"./editor-slot\";\nimport {\n announceMissingPort,\n resolveHookPorts,\n splitAddOnProps,\n useWritingFieldAddOns,\n type WritingFieldApi,\n} from \"./add-ons\";\nimport { FieldMenuRow, FinalizingStrip, ListeningStrip, VoiceProtectionDialog, micAriaLabel } from \"./voice-chrome\";\nimport type { ProTextareaAddOnProps } from \"./index\";\nimport { Textarea } from \"../controls/controls\";\n\nconst FILL_HEIGHT_REGEX = /(?:^|\\s)(h-full|h-dvh|flex-1|grow|inset-0|min-h-0)(?:\\s|$)/;\n\n/** Detect when the caller wants the field to stretch to its container. */\nfunction wantsFillHeight(className?: string, wrapperClassName?: string): boolean {\n return FILL_HEIGHT_REGEX.test(className ?? \"\") || FILL_HEIGHT_REGEX.test(wrapperClassName ?? \"\");\n}\n\n/** Why `startDictation()` refused. Every value is a real, nameable condition. */\nexport type DictationRefusalReason =\n | \"voice-disabled\"\n | \"field-disabled\"\n | \"no-microphone\"\n | \"recorder-unavailable\"\n | \"finalizing\";\n\nexport type DictationStartResult =\n | { started: true }\n | { started: false; reason: DictationRefusalReason; message: string };\n\n/**\n * Real HTMLTextAreaElement with the expandos ProTextarea sets one commit after mount (always call\n * them with `?.()`). Expandos, not `useImperativeHandle`: hundreds of hosts forward this ref\n * expecting a genuine element (`focus()`, `select()`, `selectionStart`, form association).\n */\nexport interface ProTextareaElement extends HTMLTextAreaElement {\n requestClose?: () => void;\n isTranscribing?: () => boolean;\n startDictation?: () => Promise<DictationStartResult>;\n stopDictation?: () => void;\n isDictating?: () => boolean;\n}\n\nexport interface ProTextareaProps\n extends React.TextareaHTMLAttributes<HTMLTextAreaElement>,\n ProTextareaAddOnProps {\n onTranscriptionComplete?: (text: string) => void;\n onTranscriptionError?: (error: string) => void;\n /** If true, appends to existing text; if false, replaces. Default: true. */\n appendTranscript?: boolean;\n /** Voice input. ON by default; `false` when the host owns recording itself. */\n enableVoice?: boolean;\n autoGrow?: boolean;\n minHeight?: number;\n maxHeight?: number;\n wrapperClassName?: string;\n /** Called when it's safe to close/unmount (after confirm or once recording/transcription completes). */\n onRequestClose?: () => void;\n /** Warn before unmount during recording/transcription. Default: true. */\n protectTranscription?: boolean;\n /** Copy rows in \"…\". Default: true. */\n showCopyButton?: boolean;\n /** Text stats in \"…\" + the pinned stats bar. OFF by default. */\n enableTextStats?: boolean;\n /** Initial pinned stats bar display when text stats are enabled. Default: true. */\n defaultShowTextStatsBar?: boolean;\n onSubmit?: () => void;\n submitDisabled?: boolean;\n allowEmptySubmit?: boolean;\n isSubmitting?: boolean;\n /** Accessible/tooltip label for the submit button. Default: \"Send\". */\n submitLabel?: string;\n /** The submit button's VISIBLE word (\"Build agent\"): a labeled solid pill instead of the send glyph. */\n submitText?: string;\n submitIcon?: React.ReactNode;\n submitOnCmdEnter?: boolean;\n submitOnEnter?: boolean;\n /** Field-navigation mode: plain Enter calls this; Shift+Enter / ⌘+Enter insert a newline. */\n onEnterKey?: (e: React.KeyboardEvent<HTMLTextAreaElement>) => void;\n auxiliaryControlsTabIndex?: number;\n auxiliaryControlsLabel?: string;\n /** Dense-form label inside the border (use only on a `bg-card` surface). */\n floatingLabel?: string;\n /** Markdown chords + selection toolbar. Default: on for a long-form box. */\n markdownFormatting?: boolean;\n /** Draw the mic + \"…\" cluster inside this element; `\"none\"`: the host already carries them. */\n controlsHost?: HTMLElement | null | \"none\";\n /** Host a different editor in place of the <textarea> (`./editor-slot.ts`). */\n editor?: ProTextareaEditorSlot;\n /** Expand button (in the control row) that opens the same field large. Off by default. */\n expandable?: boolean;\n /** `\"row\"` (default): a reserved row under the text. `\"inline\"`: the chat-composer shape. */\n controls?: ProTextareaControls;\n /** `field` (default) or `hero` (a front door's one big composer). */\n appearance?: \"field\" | \"hero\";\n /** Content at the START of the reserved control row. */\n leading?: React.ReactNode;\n /** `all` (default): \"…\" carries the shared action registry. `none`: only the field's own controls. */\n menuActions?: \"all\" | \"none\";\n}\n\nexport const ProTextarea = React.forwardRef<HTMLTextAreaElement, ProTextareaProps>(\n (\n {\n className,\n wrapperClassName,\n onTranscriptionComplete,\n onTranscriptionError,\n appendTranscript = true,\n menuActions = \"all\",\n enableVoice = true,\n autoGrow = false,\n minHeight,\n maxHeight,\n value,\n onChange,\n onKeyDown,\n disabled,\n onRequestClose,\n protectTranscription = true,\n showCopyButton = true,\n enableTextStats = false,\n defaultShowTextStatsBar = true,\n onSubmit,\n submitDisabled,\n allowEmptySubmit = false,\n isSubmitting = false,\n submitLabel = \"Send\",\n submitText,\n submitIcon,\n submitOnCmdEnter,\n submitOnEnter = false,\n onEnterKey,\n auxiliaryControlsTabIndex,\n auxiliaryControlsLabel,\n floatingLabel,\n id: idProp,\n placeholder,\n style,\n editor,\n markdownFormatting,\n expandable = false,\n controls,\n controlsHost,\n appearance = \"field\",\n leading,\n ...rest\n },\n ref,\n ) => {\n const addOns = useWritingFieldAddOns();\n const ports = resolveHookPorts(addOns);\n const { dom: props, addOnProps } = splitAddOnProps(\n rest as Record<string, unknown>,\n addOns.propNames,\n ) as { dom: React.TextareaHTMLAttributes<HTMLTextAreaElement>; addOnProps: Record<string, unknown> };\n const notify = ports.notify;\n\n // A one-row box takes the inline controls on its own; an explicit `controls` still wins.\n const resolvedControls: ProTextareaControls =\n controls ?? (props.rows !== undefined && Number(props.rows) <= 1 ? \"inline\" : \"row\");\n const inlineControls = resolvedControls === \"inline\" && !editor;\n const [smallType, setSmallType] = React.useState(false);\n const denseInline = inlineControls && smallType;\n const inlineMinHeight = denseInline ? DENSE_SIZES.box + 2 * TAP_HALF_GAP_PX : INLINE_CONTROLS_MIN_HEIGHT_PX;\n const effectiveMinHeight = inlineControls ? Math.max(minHeight ?? 0, inlineMinHeight) : minHeight;\n // Both measured boxes are watched through CALLBACK refs: the field subtree can mount again (the\n // right-click wrapper wraps it once it loads).\n const clusterRef = React.useRef<HTMLDivElement | null>(null);\n const [clusterWidth, setClusterWidth] = React.useState(0);\n const clusterObserver = React.useRef<ResizeObserver | null>(null);\n // Stable, so React re-runs it only when the node changes (a new function each render re-measured in\n // every commit, which loops when the measured size moves with the field's own controls).\n const setClusterNode = React.useCallback((node: HTMLDivElement | null) => {\n if (clusterRef.current === node) return;\n clusterRef.current = node;\n clusterObserver.current?.disconnect();\n clusterObserver.current = null;\n if (!node || typeof ResizeObserver === \"undefined\") return;\n const measure = () => setClusterWidth(node.offsetWidth);\n measure();\n clusterObserver.current = new ResizeObserver(measure);\n clusterObserver.current.observe(node);\n }, []);\n const fieldBoxRef = React.useRef<HTMLDivElement | null>(null);\n const [fieldBoxWidth, setFieldBoxWidth] = React.useState(0);\n const fieldBoxObserver = React.useRef<ResizeObserver | null>(null);\n // Stable, so React re-runs it only when the node changes (a new function each render re-measured in\n // every commit, which loops when the measured size moves with the field's own controls).\n const setFieldBoxNode = React.useCallback((node: HTMLDivElement | null) => {\n if (fieldBoxRef.current === node) return;\n fieldBoxRef.current = node;\n fieldBoxObserver.current?.disconnect();\n fieldBoxObserver.current = null;\n if (!node || typeof ResizeObserver === \"undefined\") return;\n const measure = () => {\n setFieldBoxWidth(node.offsetWidth);\n const field = node.querySelector(\"textarea\");\n if (field) setSmallType(Number.parseFloat(getComputedStyle(field).fontSize) < 14);\n };\n measure();\n fieldBoxObserver.current = new ResizeObserver(measure);\n fieldBoxObserver.current.observe(node);\n }, []);\n React.useEffect(\n () => () => {\n clusterObserver.current?.disconnect();\n fieldBoxObserver.current?.disconnect();\n },\n [],\n );\n const coarsePointer = useMediaQuery(\"(pointer: coarse)\");\n const openAudioSettings = ports.useOpenAudioSettings();\n const generatedId = React.useId();\n const inputId = idProp ?? (floatingLabel ? generatedId : undefined);\n const [isFocused, setIsFocused] = React.useState(false);\n const [isHovered, setIsHovered] = React.useState(false);\n const [expandOpen, setExpandOpen] = React.useState(false);\n const [overflowing, setOverflowing] = React.useState(false);\n const [menuOpen, setMenuOpen] = React.useState(false);\n const [statsOpen, setStatsOpen] = React.useState(false);\n const [showTextStatsBar, setShowTextStatsBar] = React.useState(defaultShowTextStatsBar);\n // The element ref is ALWAYS our own, merged into the host's forwarded ref (a CALLBACK ref left\n // `.current` undefined and every internal feature returned silently — RC-B6).\n const internalRef = React.useRef<HTMLTextAreaElement | null>(null);\n const textareaRef = internalRef;\n const setTextareaRef = (node: HTMLTextAreaElement | null) => {\n internalRef.current = node;\n if (typeof ref === \"function\") ref(node);\n else if (ref) (ref as React.MutableRefObject<HTMLTextAreaElement | null>).current = node;\n };\n\n // Markdown formatting for a long-form box (the element mirrored into state once per mount).\n const formattingOn =\n markdownFormatting ??\n (!editor && !submitOnEnter && (props.rows === undefined || Number(props.rows) >= 2));\n const [formatElement, setFormatElement] = React.useState<HTMLTextAreaElement | null>(null);\n React.useLayoutEffect(() => {\n if (internalRef.current !== formatElement) setFormatElement(internalRef.current);\n });\n ports.useFormatting(formatElement, formattingOn, addOnProps);\n\n // Auto-grow: scrollHeight excludes the border; add it so the last line never hides.\n React.useEffect(() => {\n if (!autoGrow || !textareaRef.current) return;\n const textarea = textareaRef.current;\n textarea.style.height = \"auto\";\n let newHeight = textarea.scrollHeight + (textarea.offsetHeight - textarea.clientHeight);\n if (effectiveMinHeight) newHeight = Math.max(newHeight, effectiveMinHeight);\n if (maxHeight) newHeight = Math.min(newHeight, maxHeight);\n textarea.style.height = `${newHeight}px`;\n }, [value, autoGrow, effectiveMinHeight, maxHeight, clusterWidth]);\n\n /** Write through React's own change path; true when the field now holds `newValue`. */\n const pushToTextarea = React.useCallback(\n (newValue: string): boolean => {\n if (editor) return editor.handle.current?.write(newValue) ?? false;\n const el = textareaRef.current;\n if (!el) return false;\n const setter = Object.getOwnPropertyDescriptor(window.HTMLTextAreaElement.prototype, \"value\")?.set;\n if (!setter) return false;\n setter.call(el, newValue);\n el.dispatchEvent(new Event(\"input\", { bubbles: true }));\n return el.value === newValue;\n },\n [editor],\n );\n\n // THE PRE-HYDRATION KEEP: text typed into a server-rendered box before hydration is handed to\n // the host through its own onChange (lane P, 2026-10-07).\n const keepPreHydrationText = React.useEffectEvent(() => {\n const el = internalRef.current;\n if (editor || !el || !onChange) return;\n const typed = el.value;\n if (!typed || typed === String(value ?? \"\")) return;\n el.value = \"\";\n pushToTextarea(typed);\n });\n React.useLayoutEffect(() => {\n keepPreHydrationText();\n }, []);\n\n const getLiveText = React.useCallback(\n () =>\n editor\n ? (editor.handle.current?.getValue() ?? String(value ?? \"\"))\n : (textareaRef.current?.value ?? String(value ?? \"\")),\n [editor, value],\n );\n\n // Voice rides the host's ONE recorder through the voice port.\n const voice = ports.useVoice({\n enabled: enableVoice,\n instanceId: inputId,\n label: typeof floatingLabel === \"string\" ? floatingLabel : undefined,\n getValue: getLiveText,\n writeValue: pushToTextarea,\n appendTranscript,\n protect: protectTranscription,\n onRequestClose,\n onTranscriptionComplete,\n onTranscriptionError,\n });\n const { isRecording, isTranscribing } = voice;\n const isAudioAvailable = voice.microphone;\n\n const refuseDictation = React.useCallback(\n (reason: DictationRefusalReason, message: string): DictationStartResult => {\n notify.error(message);\n onTranscriptionError?.(message);\n return { started: false, reason, message };\n },\n [notify, onTranscriptionError],\n );\n\n /** The imperative half of the mic button: the same checks, then the same start. */\n const startDictation = React.useCallback(async (): Promise<DictationStartResult> => {\n if (!enableVoice)\n return refuseDictation(\"voice-disabled\", \"Voice input is turned off for this field, so it cannot start dictating.\");\n if (disabled) return refuseDictation(\"field-disabled\", \"This field is disabled, so it cannot start dictating.\");\n if (!isAudioAvailable)\n return refuseDictation(\"no-microphone\", \"No microphone is available in this browser, so dictation cannot start.\");\n if (!voice.available)\n return refuseDictation(\n \"recorder-unavailable\",\n \"Voice recording is unavailable on this screen, so dictation cannot start.\",\n );\n if (isTranscribing && !isRecording)\n return refuseDictation(\n \"finalizing\",\n \"The last recording is still being transcribed. Wait for it to finish, then start again.\",\n );\n await voice.startDictation();\n return { started: true };\n }, [enableVoice, disabled, isAudioAvailable, voice, isTranscribing, isRecording, refuseDictation]);\n\n React.useEffect(() => {\n const el = textareaRef.current as ProTextareaElement | null;\n if (!el) return;\n el.requestClose = voice.requestClose;\n el.isTranscribing = () => isTranscribing;\n el.startDictation = startDictation;\n el.stopDictation = voice.stopDictation;\n el.isDictating = () => isRecording;\n }, [voice.requestClose, isTranscribing, startDictation, voice.stopDictation, isRecording]);\n\n const valueAsString = String(value ?? \"\");\n const hasContent = valueAsString.trim().length > 0;\n const canSubmit = !!onSubmit && (hasContent || allowEmptySubmit) && !submitDisabled && !isSubmitting && !disabled;\n const cmdEnterEnabled = submitOnCmdEnter ?? !!onSubmit;\n const triggerSubmit = React.useCallback(() => {\n if (canSubmit && onSubmit) onSubmit();\n }, [canSubmit, onSubmit]);\n\n const insertNewlineAtCursor = React.useCallback(() => {\n const el = textareaRef.current;\n if (!el) return;\n const start = el.selectionStart ?? el.value.length;\n const end = el.selectionEnd ?? el.value.length;\n pushToTextarea(el.value.slice(0, start) + \"\\n\" + el.value.slice(end));\n const caret = start + 1;\n requestAnimationFrame(() => {\n const node = textareaRef.current;\n if (!node) return;\n node.selectionStart = caret;\n node.selectionEnd = caret;\n });\n }, [pushToTextarea]);\n\n const handleKeyDown = React.useCallback(\n (e: React.KeyboardEvent<HTMLTextAreaElement>) => {\n // Typing hides the hover controls until the mouse moves again (like the OS cursor).\n if (isHovered) setIsHovered(false);\n onKeyDown?.(e);\n if (e.defaultPrevented || e.key !== \"Enter\") return;\n const withCmd = e.metaKey || e.ctrlKey;\n if (onEnterKey) {\n if (e.shiftKey) return;\n e.preventDefault();\n if (withCmd) insertNewlineAtCursor();\n else onEnterKey(e);\n return;\n }\n if (!onSubmit) return;\n if (cmdEnterEnabled && withCmd) {\n e.preventDefault();\n triggerSubmit();\n return;\n }\n const intent = composerKeyIntent(\n {\n key: e.key,\n shiftKey: e.shiftKey,\n metaKey: e.metaKey,\n ctrlKey: e.ctrlKey,\n isComposing: e.nativeEvent.isComposing,\n },\n { submitOnEnter },\n );\n if (!intentTakesTheKey(intent)) return;\n e.preventDefault();\n triggerSubmit();\n },\n [isHovered, onKeyDown, onEnterKey, insertNewlineAtCursor, onSubmit, cmdEnterEnabled, submitOnEnter, triggerSubmit],\n );\n\n const fieldApi: WritingFieldApi = {\n kind: \"textarea\",\n text: valueAsString,\n getText: getLiveText,\n write: pushToTextarea,\n getSelection: () => {\n const handle = editor?.handle.current ?? null;\n if (handle) return handle.getSelection();\n const el = textareaRef.current;\n return { start: el?.selectionStart ?? 0, end: el?.selectionEnd ?? 0 };\n },\n getElement: () => textareaRef.current,\n addOnProps,\n showCopyButton,\n flashCopied: () => undefined,\n };\n\n const showControls =\n (appearance === \"hero\" ||\n (typeof HTMLElement !== \"undefined\" && controlsHost instanceof HTMLElement) ||\n isHovered ||\n isFocused ||\n isRecording ||\n isTranscribing) &&\n !disabled;\n const isVoiceDisabled = !isAudioAvailable || disabled || (isTranscribing && !isRecording);\n\n const addOnMenuItems = addOns.Menu\n ? (addOns.menuHasItems?.({ kind: \"textarea\", addOnProps, showCopyButton }) ?? true)\n : false;\n // The menu's OWN actions; \"…\" also shows to hold whatever did not fit.\n const showMenu = !disabled && menuActions !== \"none\" && (showCopyButton || addOnMenuItems);\n // THE ONE FITTING RULE (./control-fit.ts), shared with ProInput.\n const micOffered = enableVoice && isAudioAvailable;\n const fit = fitFieldControls({\n fieldWidth: fieldBoxWidth,\n sizes: controlSizes({ coarse: coarsePointer, dense: denseInline }),\n fixedPx: inlineControls ? 12 + 2 * TAP_HALF_GAP_PX : 8,\n minText: inlineControls ? undefined : 0,\n hasSubmit: !!onSubmit,\n menuHasOwnItems: showMenu,\n mic: micOffered,\n clear: false,\n expand: expandable && !editor && overflowing,\n });\n const voiceBusyNow = isRecording || isTranscribing;\n const micInline = micOffered && (fit.mic === \"inline\" || voiceBusyNow);\n const voiceInMenu = micOffered && !micInline;\n const expandInMenu = fit.folded.includes(\"expand\");\n const menuShown =\n !disabled && (showMenu || voiceInMenu || expandInMenu || (menuActions === \"none\" && enableVoice));\n const audioSettingsInMenu = menuShown && enableVoice;\n const hasCoarseControls = (enableVoice && isAudioAvailable && !disabled) || showMenu;\n const Stats = addOns.TextStats;\n const showTextStats = enableTextStats && showMenu && !!Stats;\n React.useEffect(() => {\n if (enableTextStats && !addOns.TextStats) announceMissingPort(\"TextStats\");\n }, [enableTextStats, addOns.TextStats]);\n const showPinnedTextStatsBar = showTextStats && showTextStatsBar;\n // An auto-growing box sizes itself to its text, so it never fills its host's height.\n const fillHeight = !autoGrow && wantsFillHeight(className, wrapperClassName);\n\n React.useEffect(() => {\n if (!expandable || editor) return;\n const el = internalRef.current;\n if (!el) return;\n const measure = () => setOverflowing(el.scrollHeight > el.clientHeight + 2);\n measure();\n const observer = new ResizeObserver(measure);\n observer.observe(el);\n return () => observer.disconnect();\n }, [expandable, editor, value]);\n\n const isInvalid = props[\"aria-invalid\"] === true || props[\"aria-invalid\"] === \"true\";\n const labelFloated = isFocused || valueAsString.length > 0;\n\n const hero = appearance === \"hero\";\n const fieldClassName = cn(\n hero\n ? \"flex w-full border border-border bg-card px-5 pt-4 pb-3 text-base leading-7 text-foreground placeholder:text-muted-foreground shadow-[0_1px_2px_rgb(0_0_0/0.05),0_12px_32px_-12px_rgb(0_0_0/0.22)] transition-[border-color,box-shadow] duration-200\"\n : \"flex w-full border border-border bg-card px-3 py-2 text-sm shadow-sm placeholder:text-muted-foreground\",\n showPinnedTextStatsBar\n ? hero\n ? \"rounded-2xl sm:rounded-b-none sm:border-b-0\"\n : \"rounded-md sm:rounded-b-none sm:border-b-0\"\n : hero\n ? \"rounded-2xl\"\n : \"rounded-md\",\n // THE FIELD FOCUS (Arman 2026-10-21): border takes the ring + the one halo token.\n \"focus-visible:outline-none focus-visible:border-primary focus-visible:ring-[3px] focus-visible:ring-primary/15\",\n \"disabled:cursor-not-allowed disabled:text-disabled-foreground\",\n fillHeight ? \"min-h-0 flex-1 resize-none overflow-y-auto\" : \"resize-y\",\n autoGrow && \"resize-none overflow-y-auto\",\n hero ? \"pr-5\" : \"pr-3\",\n className,\n // AFTER the caller's className: the reserved control row always wins (a floor, never a ceiling).\n !inlineControls &&\n !controlsHost &&\n (hasCoarseControls || onSubmit) &&\n (editor?.singleLine && !onSubmit\n ? \"pr-24 pointer-coarse:pr-32\"\n : hero\n ? \"pb-[max(3.5rem,var(--matrx-textarea-end,0px))]\"\n : \"pb-[max(2.75rem,var(--matrx-textarea-end,0px))]\"),\n );\n const reservesRow = !inlineControls && !controlsHost && (hasCoarseControls || !!onSubmit) && !editor?.singleLine;\n const fieldStyle: React.CSSProperties = {\n ...style,\n minHeight: effectiveMinHeight !== undefined ? `${effectiveMinHeight}px` : style?.minHeight,\n maxHeight: maxHeight !== undefined ? `${maxHeight}px` : style?.maxHeight,\n ...(inlineControls ? inlineControlsFieldPadding(clusterWidth, inlineMinHeight) : {}),\n };\n\n const closeMenu = () => setMenuOpen(false);\n const ownRows =\n expandInMenu || voiceInMenu || audioSettingsInMenu ? (\n <>\n {expandInMenu ? (\n <FieldMenuRow\n icon={<Maximize2Icon />}\n onClick={() => {\n closeMenu();\n setExpandOpen(true);\n }}\n >\n Expand\n </FieldMenuRow>\n ) : null}\n {voiceInMenu ? (\n <FieldMenuRow\n icon={<MicIcon />}\n disabled={isVoiceDisabled}\n onClick={() => {\n closeMenu();\n void voice.handleVoiceClick();\n }}\n >\n Voice input\n </FieldMenuRow>\n ) : null}\n {audioSettingsInMenu ? (\n <FieldMenuRow\n icon={<SlidersHorizontalIcon />}\n onClick={() => {\n closeMenu();\n openAudioSettings();\n }}\n >\n Audio settings\n </FieldMenuRow>\n ) : null}\n {showMenu ? <div className=\"my-1 h-px bg-border\" role=\"separator\" /> : null}\n </>\n ) : null;\n const trailingRows =\n showTextStats && Stats ? (\n <>\n <div className=\"my-1 h-px bg-border\" role=\"separator\" />\n <Stats.MenuItems\n showStatsBar={showTextStatsBar}\n onToggleStatsBar={() => setShowTextStatsBar((prev) => !prev)}\n onOpenStatsPanel={() => setStatsOpen(true)}\n />\n </>\n ) : null;\n const Menu = addOns.Menu;\n const menuBody =\n statsOpen && Stats ? (\n <div className=\"w-56\">\n <Stats.Panel text={valueAsString} onBack={() => setStatsOpen(false)} onClose={closeMenu} />\n </div>\n ) : Menu && menuActions !== \"none\" ? (\n <Menu field={fieldApi} ownRows={ownRows} trailingRows={trailingRows} close={closeMenu} />\n ) : (\n <StandInMenu field={fieldApi} ownRows={ownRows} trailingRows={trailingRows} close={closeMenu} registry={menuActions !== \"none\"} />\n );\n\n const cluster = (\n <div\n ref={setClusterNode}\n onMouseDown={(e) => e.preventDefault()}\n data-matrx-tap-dense={denseInline ? \"\" : undefined}\n className={\n controlsHost\n ? \"flex items-center\"\n : cn(\n \"absolute z-10 flex items-center\",\n hero && !inlineControls\n ? \"bottom-2 right-2\"\n : proTextareaClusterPlacement(!!onSubmit, inlineControls ? \"inline\" : \"row\").className,\n editor?.singleLine && \"top-1/2 bottom-auto -translate-y-1/2\",\n )\n }\n >\n {fit.expandInline ? (\n <MaximizeTapButton\n tabIndex={auxiliaryControlsTabIndex}\n variant=\"transparent\"\n ariaLabel={auxiliaryControlsLabel ? `Expand ${auxiliaryControlsLabel}` : \"Expand\"}\n tooltip=\"Expand\"\n onClick={() => setExpandOpen(true)}\n className=\"text-muted-foreground\"\n />\n ) : null}\n {/* A GLASS PLANE (tap-target placement rule 1): it rides over the field's own text. */}\n <div\n data-matrx-glass-plane\n className={cn(\n \"flex items-center transition-opacity duration-200 focus-within:opacity-100 focus-within:pointer-events-auto\",\n \"pointer-coarse:opacity-100 pointer-coarse:pointer-events-auto\",\n showControls || menuOpen ? \"opacity-100\" : \"opacity-0 pointer-events-none\",\n )}\n >\n {micInline && addOns.MicButton ? (\n <addOns.MicButton\n tabIndex={auxiliaryControlsTabIndex}\n onMicClick={() => void voice.handleVoiceClick()}\n dense={denseInline}\n disabled={isVoiceDisabled}\n isRecording={isRecording}\n isTranscribing={isTranscribing}\n audioLevel={voice.audioLevel}\n micAriaLabel={micAriaLabel(isRecording, auxiliaryControlsLabel)}\n />\n ) : null}\n {menuShown && (\n <Popover\n open={menuOpen}\n onOpenChange={(open) => {\n setMenuOpen(open);\n if (!open) setStatsOpen(false);\n }}\n >\n <PopoverTrigger asChild>\n <MoreHorizontalTapButton\n tabIndex={auxiliaryControlsTabIndex}\n variant=\"transparent\"\n ariaLabel={auxiliaryControlsLabel ? `More options for ${auxiliaryControlsLabel}` : \"More options\"}\n tooltip=\"More\"\n className=\"text-muted-foreground\"\n />\n </PopoverTrigger>\n <PopoverContent\n /* sizing: fixed — the add-on body sizes itself (list, stats, agent panels) */\n align=\"end\"\n side=\"bottom\"\n sideOffset={6}\n className=\"w-auto max-w-none p-0\"\n onOpenAutoFocus={(e) => e.preventDefault()}\n >\n {menuBody}\n </PopoverContent>\n </Popover>\n )}\n </div>\n {onSubmit && (\n <TapTargetButtonSolid\n onClick={triggerSubmit}\n disabled={!canSubmit}\n ariaLabel={submitLabel}\n tooltip={submitLabel}\n label={submitText}\n icon={\n isSubmitting ? (\n <Loader2Icon className=\"h-4 w-4 animate-spin\" />\n ) : (\n (submitIcon ?? <SendIcon className=\"h-4 w-4\" />)\n )\n }\n />\n )}\n </div>\n );\n\n const field = (\n <div\n ref={setFieldBoxNode}\n className={cn(\"relative group\", wrapperClassName)}\n data-writing-field-host={addOns.Menu && addOns.useVoice ? undefined : UNCONFIGURED}\n onMouseEnter={() => setIsHovered(true)}\n onMouseMove={() => {\n if (!isHovered) setIsHovered(true);\n }}\n onMouseLeave={() => setIsHovered(false)}\n >\n <div className={cn(\"flex min-h-0 min-w-0 w-full flex-col\", fillHeight ? \"h-full flex-1\" : \"flex-1\")}>\n <div className={cn(\"relative min-w-0 w-full\", fillHeight && \"flex min-h-0 flex-1 flex-col\")}>\n {editor ? (\n editor.render({\n id: inputId,\n className: fieldClassName,\n style: fieldStyle,\n placeholder: floatingLabel ? undefined : placeholder,\n disabled,\n onFocus: () => setIsFocused(true),\n onBlur: () => setIsFocused(false),\n onKeyDown: () => {\n if (isHovered) setIsHovered(false);\n },\n })\n ) : (\n <Textarea\n hero={hero}\n joinedBottom={showPinnedTextStatsBar}\n ref={setTextareaRef}\n id={inputId}\n placeholder={floatingLabel ? undefined : placeholder}\n className={cn(\"w-full\", fillHeight ? \"min-h-0 flex-1 resize-none overflow-y-auto\" : \"resize-y\", autoGrow && \"resize-none overflow-y-auto\", className)}\n reservedInlineEnd={inlineControls ? clusterWidth + 6 : 0}\n reservedBlockEnd={reservesRow ? hero ? 56 : 44 : 0}\n style={fieldStyle}\n value={value}\n onChange={onChange}\n onFocus={() => setIsFocused(true)}\n onBlur={() => setIsFocused(false)}\n onKeyDown={handleKeyDown}\n disabled={disabled}\n {...props}\n />\n )}\n\n {expandable && !editor ? (\n <Dialog open={expandOpen} onOpenChange={setExpandOpen}>\n <DialogContent className=\"flex max-h-[90dvh] w-[min(56rem,calc(100vw-2rem))] max-w-none flex-col gap-3 sm:max-w-none\">\n <DialogTitle className=\"truncate\">{auxiliaryControlsLabel ?? floatingLabel ?? \"Text\"}</DialogTitle>\n {/* The SAME field, large: one value, one onChange. */}\n <ProTextarea\n {...(addOnProps as ProTextareaAddOnProps)}\n value={value}\n onChange={onChange}\n placeholder={placeholder}\n disabled={disabled}\n wrapperClassName=\"h-[min(70dvh,40rem)]\"\n className=\"h-full text-sm\"\n autoFocus\n />\n </DialogContent>\n </Dialog>\n ) : null}\n\n {floatingLabel && inputId && (\n <Label\n htmlFor={inputId}\n className={cn(\n \"absolute left-3 px-1 pointer-events-none transition-all duration-200 ease-in-out z-10 bg-transparent\",\n labelFloated ? \"-top-2 text-xs\" : \"top-3 text-sm\",\n isInvalid ? \"text-destructive\" : isFocused ? \"text-primary\" : \"text-muted-foreground\",\n disabled && \"text-disabled-foreground\",\n )}\n >\n {floatingLabel}\n </Label>\n )}\n\n {leading && reservesRow ? (\n <div\n data-pro-textarea-leading=\"\"\n onMouseDown={(e) => e.preventDefault()}\n className={cn(\"absolute z-10 flex items-center gap-1\", hero ? \"bottom-2 left-3\" : \"bottom-1 left-1\")}\n >\n {leading}\n </div>\n ) : null}\n {controlsHost === \"none\" ? null : controlsHost ? createPortal(cluster, controlsHost) : cluster}\n\n {enableVoice && isRecording && (\n <ListeningStrip\n liveTranscript={voice.liveTranscript}\n className={\n inlineControls\n ? \"inset-x-0 bottom-full mb-1.5 border border-border bg-card shadow-sm\"\n : cn(\"left-2 bottom-2 bg-primary/10 dark:bg-primary/15\", onSubmit ? \"right-32\" : \"right-24\")\n }\n />\n )}\n {enableVoice && isTranscribing && !isRecording && (\n <FinalizingStrip className={inlineControls ? \"left-0 bottom-full mb-1.5\" : \"left-2 bottom-2\"} />\n )}\n </div>\n\n {voice.dialogs}\n <VoiceProtectionDialog voice={voice} />\n\n {/* Desktop-only: on a phone the counts row is clutter under every field. */}\n {showPinnedTextStatsBar && Stats ? (\n <div className=\"hidden sm:block\">\n <Stats.Bar text={valueAsString} />\n </div>\n ) : null}\n </div>\n </div>\n );\n\n const ContextMenu = addOns.ContextMenu;\n if (!ContextMenu) return field;\n return (\n <ContextMenu field={fieldApi} disabled={disabled}>\n {field}\n </ContextMenu>\n );\n },\n);\n\nProTextarea.displayName = \"ProTextarea\";\n\n/** \"…\" with no Menu port: the field's own rows plus a working Copy — announced as a stand-in. */\nexport function StandInMenu({\n field,\n ownRows,\n trailingRows,\n close,\n registry,\n}: {\n field: WritingFieldApi;\n ownRows: React.ReactNode;\n trailingRows: React.ReactNode;\n close: () => void;\n registry: boolean;\n}) {\n React.useEffect(() => {\n if (registry) announceMissingPort(\"Menu\");\n }, [registry]);\n return (\n <div className=\"flex w-48 flex-col p-1\" data-writing-field-host={registry ? UNCONFIGURED : undefined}>\n {ownRows}\n {registry && field.showCopyButton ? (\n <FieldMenuRow\n icon={<CopyIcon />}\n onClick={() => {\n const text = field.getText();\n close();\n if (text) void copyText(text).then((ok) => ok && field.flashCopied());\n }}\n >\n Copy\n </FieldMenuRow>\n ) : null}\n {trailingRows}\n </div>\n );\n}\n","import { clsx, type ClassValue } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\nexport function cn(...inputs: ClassValue[]): string {\n return twMerge(clsx(inputs));\n}\n","\"use client\";\n\nimport * as LabelPrimitive from \"@radix-ui/react-label\";\nimport * as React from \"react\";\n\nimport { cn } from \"./cn\";\n\nexport const Label = React.forwardRef<\n React.ComponentRef<typeof LabelPrimitive.Root>,\n React.ComponentPropsWithoutRef<typeof LabelPrimitive.Root>\n>(({ className, ...props }, ref) => (\n <LabelPrimitive.Root\n ref={ref}\n className={cn(\n \"text-sm font-medium leading-none text-foreground peer-disabled:cursor-not-allowed peer-disabled:opacity-70\",\n className,\n )}\n {...props}\n />\n));\nLabel.displayName = LabelPrimitive.Root.displayName;\n","\"use client\";\n\n/**\n * Dialog — the modal surface, carrying every ruling the host forks paid for.\n *\n * Four hosts shipped four dialogs. Three were the stock shadcn body: a\n * fixed-size centered card with `overflow: visible`. matrx-frontend's had been\n * hardened, incident by incident, and those hardenings are the reason this\n * component belongs in the package rather than being copied a fifth time:\n *\n * 1. THE ROOT RENDERS UNCONDITIONALLY — no hydration mount gate. The gate a\n * wrapper once carried (\"Radix ids differ between SSR and client\") was\n * false — Radix ids come from React's SSR-stable `useId` — and it deleted\n * the always-visible Trigger from SSR and the first client paint.\n *\n * 2. THE DIALOG IS CLAMPED TO THE VIEWPORT AND SCROLLS INSIDE ITSELF. Proven\n * live: an admin \"Create Category\" dialog rendered 851px tall in a 657px\n * viewport with `overflow-y: visible`, so its Create button sat below the\n * fold, unreachable. The only way out was a backdrop click — which\n * dismisses WITHOUT writing, and is indistinguishable from a silent save\n * failure. `max-h-[85dvh] overflow-y-auto` is the cap.\n *\n * 3. THE PRIMARY ACTION IS ALWAYS PRESSABLE — AND NEVER ON TOP OF THE BODY.\n * `DialogFooter` is sticky and bleeds to the card's edges using\n * `--dialog-pad`. Until 0.11.3 that bleed was a NEGATIVE BLOCK MARGIN,\n * which sticky clamps: the footer was dragged up over the row above it by\n * `--dialog-pad` minus the card gap. The card now RESERVES the footer's\n * block size instead (`.matrx-dialog-card` in `styles.css` hands its bottom\n * padding to the footer), so scrolled content never shows through beneath\n * the actions AND the footer never covers the row above it. Outside a\n * DialogContent both variables are unset, the padding falls back to `0px`,\n * and the footer is the plain row it always was.\n *\n * 4. ON MOBILE THE SAME DIALOG IS A BOTTOM SHEET — full width, bottom\n * anchored, height-capped, internally scrollable, safe-area padded. Opt out\n * with `mobileSheet={false}` only for the rare surface that must stay\n * centered (a tiny spinner). The sheet geometry is re-asserted AFTER the\n * caller's className so a desktop `max-w-2xl` cannot un-fullscreen it.\n *\n * 5. AN UNTITLED DIALOG IS STILL ACCESSIBLE. Radix warns (correctly) that\n * every dialog needs a title; rather than let hosts ship the warning, a\n * visually-hidden title is injected when the tree has none, and\n * `aria-describedby` is dropped when there is no description rather than\n * pointing at nothing.\n *\n * 6. ON DESKTOP A DIALOG IS A WINDOW, NOT A WALL (0.38.0, Arman 2026-09-23:\n * \"none of the built-in page ai integrations are accessible because the\n * page is totally blocked\"). Unless the caller passes `modal`, a desktop\n * dialog does not block the page: no overlay, the page, the Agents menu,\n * the assist dock and right-click AI stay usable beside it. It behaves like\n * a window: a click outside never closes it (`dismissOnOutsideClick` opts a\n * quick picker back in), Escape closes it only while focus is inside it\n * (Escape in the page belongs to the page), and its `DialogHeader` drags\n * it, clamped on screen, double-click to recenter. On a phone it stays the\n * blocking bottom sheet — nothing useful sits behind a sheet. Confirmations\n * are `AlertDialog`, a different component, and stay blocking. This is a\n * LIGHT window: the host's heavy window manager (tray, persistence) is a\n * separate system and must not be pulled into every dialog.\n *\n * SEAM INVERSIONS. The host original resolved its portal target through\n * app-shaped hooks (a popped-out window-panel body). Here that is the\n * package's `PortalContainerProvider` seam, with an explicit `container` prop\n * keeping top priority. And DialogContent PROVIDES that seam to its own\n * children, so a Popover or menu opened inside a dialog portals INTO the\n * dialog — staying inside the scroll shard, where its wheel events work.\n * `useDialogContainer` exposes the same element for host code that needs it.\n */\n\nimport * as DialogPrimitive from \"@radix-ui/react-dialog\";\nimport * as VisuallyHidden from \"@radix-ui/react-visually-hidden\";\nimport { treeContainsComponent } from \"@ai-matrx/kit/react-tree\";\nimport * as React from \"react\";\n\nimport { cn } from \"./cn\";\nimport {\n MOTION_BOTTOM_SHEET,\n MOTION_DIALOG,\n MOTION_OVERLAY,\n} from \"./motion\";\nimport { CloseRow, CloseSlotProvider, HeaderWithClose, useCloseSlot } from \"./close-slot\";\nimport { usePortalContainer, PortalContainerProvider } from \"./portal-container\";\nimport { useLook } from \"./look\";\nimport {\n RadixDialogModalProvider,\n useRadixDialogModal,\n} from \"./radix-dialog-modal-context\";\nimport { useIsMobile } from \"./use-is-mobile\";\nimport { announceLayerFront, LAYER_FRONT_EVENT, type LayerFrontDetail } from \"./layer-front\";\nimport { clampRectToViewport, readViewport, useDragMove } from \"./window-drag\";\nimport { keepFloatingLayersInside, useModalLayer } from \"./floating-layer\";\nimport { keepMovedFocus } from \"./focus-return\";\n\n/**\n * True when the dialog is a window because the caller said nothing about\n * modality (rule 6), false when the caller passed `modal={false}` itself.\n * The two sit on different layers: a default window sits WITH the other\n * layers it was opened from (z-10000 — a dialog opened from a menu, a popover\n * or a host window must never appear behind its opener), while an explicit\n * `modal={false}` keeps the older coexistence contract below the host's window\n * manager (z-900).\n */\nconst DialogWindowedByDefaultContext = React.createContext(false);\n\nconst Dialog = ({\n children,\n ...props\n}: React.ComponentPropsWithoutRef<typeof DialogPrimitive.Root>) => {\n const isMobile = useIsMobile();\n // THE LOOK (look.tsx): in a desktop scope every dialog is a macOS sheet, modal over a dimmed\n // window, whatever `modal` says (the desktop standard's Dialog).\n const desktopLook = useLook() === \"desktop\";\n // A window on desktop, a blocking sheet on a phone; `modal` forces either (rule 6).\n const modal = desktopLook || (props.modal ?? isMobile);\n return (\n <DialogWindowedByDefaultContext.Provider value={!desktopLook && props.modal === undefined}>\n <RadixDialogModalProvider modal={modal}>\n <DialogPrimitive.Root {...props} modal={modal}>\n {children}\n </DialogPrimitive.Root>\n </RadixDialogModalProvider>\n </DialogWindowedByDefaultContext.Provider>\n );\n};\nDialog.displayName = \"Dialog\";\n\nconst DialogTrigger = DialogPrimitive.Trigger;\nconst DialogClose = DialogPrimitive.Close;\n\n/**\n * Portal-seam-aware DialogPortal. An explicit `container` always wins; with\n * none, the injected `PortalContainerProvider` value decides; with neither,\n * Radix's `document.body`.\n */\nconst DialogPortal = ({\n container,\n ...props\n}: Omit<\n React.ComponentPropsWithoutRef<typeof DialogPrimitive.Portal>,\n \"container\"\n> & {\n /** `undefined` → use the injected container; `null` → force document.body. */\n container?: HTMLElement | null | undefined;\n}) => {\n const resolved = usePortalContainer(container);\n return <DialogPrimitive.Portal container={resolved ?? null} {...props} />;\n};\nDialogPortal.displayName = \"DialogPortal\";\n\n// Shared identity across independently bundled public entrypoints/loaders.\nconst CONTEXT_SLOT = Symbol.for(\"ai-matrx.design-system.dialog-container-context\");\nconst contextRegistry = globalThis as typeof globalThis & { [CONTEXT_SLOT]?: React.Context<HTMLElement | null> };\nconst DialogContainerContext = contextRegistry[CONTEXT_SLOT] ??= React.createContext<HTMLElement | null>(null);\n\n/** The DialogContent element, for host code that portals into the dialog. */\nexport const useDialogContainer = (): HTMLElement | null =>\n React.useContext(DialogContainerContext);\n\nconst DialogOverlay = React.forwardRef<\n React.ComponentRef<typeof DialogPrimitive.Overlay>,\n React.ComponentPropsWithoutRef<typeof DialogPrimitive.Overlay>\n>(({ className, ...props }, ref) => (\n <DialogPrimitive.Overlay\n ref={ref}\n data-slot=\"dialog-overlay\"\n className={cn(\n // Page context behind the modal stays readable; separation comes from a\n // light token scrim, not a blur.\n \"fixed inset-0 z-[10000] bg-[var(--matrx-overlay-scrim-soft)]\",\n MOTION_OVERLAY,\n className,\n )}\n {...props}\n />\n));\nDialogOverlay.displayName = DialogPrimitive.Overlay.displayName;\n\n/**\n * Unstyled, non-portalling Content for custom dialog layouts. Preserves Radix\n * focus/background behavior and derives `aria-modal` from the Root.\n */\nconst DialogContentPrimitive = React.forwardRef<\n React.ComponentRef<typeof DialogPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof DialogPrimitive.Content>\n>(({ onInteractOutside, onCloseAutoFocus, ...props }, ref) => {\n const isModal = useRadixDialogModal();\n // A blocking dialog registers, so floating layers opened from it (a host\n // window, a picker window) stack above its scrim (floating-layer.tsx).\n useModalLayer(isModal);\n return (\n <DialogPrimitive.Content\n {...props}\n ref={ref}\n aria-modal={isModal || undefined}\n onInteractOutside={keepFloatingLayersInside(onInteractOutside)}\n onCloseAutoFocus={keepMovedFocus(onCloseAutoFocus)}\n />\n );\n});\nDialogContentPrimitive.displayName = \"DialogContentPrimitive\";\n\nconst DIALOG_DESKTOP_CLASSES =\n \"matrx-dialog-card fixed inset-0 z-[10000] m-auto grid h-fit min-w-0 w-full max-w-lg gap-4 max-h-[85dvh] overflow-y-auto overscroll-contain [--dialog-pad:1.5rem] overflow-x-clip border bg-background p-6 shadow-lg [overflow-wrap:anywhere] [&>*]:min-w-0 [&>*]:max-w-full sm:rounded-lg\";\n\nconst DIALOG_MOBILE_SHEET_CLASSES =\n \"matrx-mobile-sheet matrx-dialog-card fixed inset-x-0 bottom-0 left-0 right-0 top-auto z-[10000] flex min-w-0 flex-col w-full max-w-full max-h-[90dvh] gap-4 [--dialog-pad:1rem] overflow-x-clip border-t bg-background p-4 pb-safe shadow-lg [overflow-wrap:anywhere] [&>*]:min-w-0 [&>*]:max-w-full rounded-t-2xl rounded-b-none overflow-y-auto overscroll-contain\";\n\n// Re-asserted LAST so sheet geometry always wins over a caller className.\nconst DIALOG_MOBILE_SHEET_OVERRIDE =\n \"inset-x-0 bottom-0 left-0 right-0 top-auto translate-none w-full max-w-full max-h-[90dvh] rounded-b-none rounded-t-2xl overflow-y-auto\";\n\n/** Drag props the windowed DialogContent hands its DialogHeader (rule 6). */\ntype DialogWindowHandle = {\n onPointerDown: (event: React.PointerEvent<HTMLElement>) => void;\n onDoubleClick: () => void;\n};\nconst DialogWindowHandleContext = React.createContext<DialogWindowHandle | null>(null);\n\n/** Pixels of a dragged window that must stay on screen. */\nconst WINDOW_KEEP_VISIBLE = 80;\n\nexport interface DialogContentProps\n extends React.ComponentPropsWithoutRef<typeof DialogPrimitive.Content> {\n /**\n * Windowed (non-blocking) dialogs never close from a click outside them —\n * the person is reaching for the page or an AI control beside the window.\n * Pass `true` for a quick picker that should close when the person clicks\n * away. Ignored on a blocking dialog, which keeps Radix's behavior.\n */\n dismissOnOutsideClick?: boolean;\n /** Render as a bottom sheet below the mobile breakpoint. Default `true`. */\n mobileSheet?: boolean;\n /** Render the built-in close control. Default `true`. */\n showCloseButton?: boolean;\n /** Explicit portal target; wins over the injected container. */\n container?: HTMLElement | null;\n /**\n * Package-owned open/close motion. Default `true`. Pass `false` for a\n * surface that must appear instantly. It is NOT the reduced-motion switch;\n * `styles.css` already honors `prefers-reduced-motion`.\n */\n animated?: boolean;\n /**\n * THE NAMED WIDTHS (0.68.22) — a dialog never pastes `max-w-[860px]`. Derived from the call\n * sites: `sm` 28rem (a confirm, a one-field ask), `md` 32rem (default), `lg` 42rem (a form with\n * two columns), `xl` 56rem (a detail or a table), `2xl` 72rem (a workspace in a dialog),\n * `full` the viewport less 1rem each side, `screen` the whole viewport (a record opened as a\n * page). On a phone the dialog is a bottom sheet at every size.\n */\n size?: DialogSize;\n /**\n * `default`: the card pads and gaps its children (24px). `none`: the content draws its own\n * frame edge to edge — a command palette, a picker with its own header row, a full-bleed grid.\n */\n padding?: \"default\" | \"none\";\n /**\n * `auto` (default): the card is as tall as its content, up to 85dvh. `tall`: the card holds\n * 85dvh whatever its content — a workspace whose body scrolls inside (a grid, a document).\n */\n height?: \"auto\" | \"tall\";\n}\n\nexport type DialogSize = \"sm\" | \"md\" | \"lg\" | \"xl\" | \"2xl\" | \"full\" | \"screen\";\n\n/**\n * Literal classes so a host's Tailwind scan of the package finds every one. Every width above\n * `md` keeps a 1rem gutter each side on a screen narrower than itself (the card is `w-full`\n * with `inset-0`, so an un-guttered `max-w-4xl` ran edge to edge at 800px). `screen` is the\n * whole viewport, square-cornered — a record opened \"as a page\".\n */\nexport const DIALOG_SIZE_CLASS: Record<DialogSize, string> = {\n sm: \"max-w-md\",\n md: \"max-w-lg\",\n lg: \"max-w-[min(42rem,calc(100vw-2rem))]\",\n xl: \"max-w-[min(56rem,calc(100vw-2rem))]\",\n \"2xl\": \"max-w-[min(72rem,calc(100vw-2rem))]\",\n full: \"max-w-[calc(100vw-2rem)]\",\n screen: \"max-w-none w-screen h-dvh max-h-none rounded-none sm:rounded-none\",\n};\n\nconst DialogContent = React.forwardRef<\n React.ComponentRef<typeof DialogPrimitive.Content>,\n DialogContentProps\n>(\n (\n {\n className,\n children,\n mobileSheet = true,\n animated = true,\n showCloseButton = true,\n container,\n dismissOnOutsideClick = false,\n size = \"md\",\n padding = \"default\",\n height = \"auto\",\n onInteractOutside,\n onEscapeKeyDown,\n onPointerDownCapture,\n onFocusCapture,\n style,\n ...props\n },\n ref,\n ) => {\n const isMobile = useIsMobile();\n const isModal = useRadixDialogModal();\n // Falls through to the injected container while `containerEl` is unset\n // (pre-mount) — the original's dialog > popout > body priority.\n const injectedContainer = usePortalContainer(container);\n // THE LOOK (look.tsx): inside a desktop scope the dialog is a macOS sheet — never a phone's\n // bottom sheet, no close (×), no web motion; look-desktop.css draws it from `data-desktop-sheet`.\n const desktopLook = useLook() === \"desktop\";\n const asSheet = mobileSheet && isMobile && !desktopLook;\n const windowed = !isModal && !asSheet;\n const windowedByDefault = React.useContext(DialogWindowedByDefaultContext);\n const [containerEl, setContainerEl] = React.useState<HTMLElement | null>(\n null,\n );\n\n // ── the front-most layer (layer-front.ts) ───────────────────────────────\n // A default window sits at z-10000 with the layers it was opened from; it\n // steps behind when another layer comes to the front after it (a host\n // window opened from the Agents menu) and returns when the person reaches\n // for it again. An explicit modal={false} keeps its fixed z-900 contract.\n const stacks = windowed && windowedByDefault;\n const [behind, setBehind] = React.useState(false);\n React.useEffect(() => {\n if (!stacks || !containerEl) return;\n const onFront = (event: Event) => {\n const element = (event as CustomEvent<LayerFrontDetail>).detail?.element ?? null;\n if (element && (element === containerEl || containerEl.contains(element))) return;\n setBehind(true);\n };\n document.addEventListener(LAYER_FRONT_EVENT, onFront);\n // Opening is coming to the front.\n announceLayerFront(containerEl);\n return () => document.removeEventListener(LAYER_FRONT_EVENT, onFront);\n }, [stacks, containerEl]);\n const bringToFront = () => {\n if (!stacks || !containerEl) return;\n setBehind(false);\n announceLayerFront(containerEl);\n };\n\n // ── rule 6: the windowed dialog drags by its header ──────────────────────\n // THE WINDOW DRAG (window-drag.ts): painted per frame, committed once on release,\n // the header kept on screen.\n const [offset, setOffset] = React.useState({ x: 0, y: 0 });\n const drag = useDragMove({\n element: containerEl,\n enabled: windowed,\n paint: \"offset\",\n offset,\n constrain: (next) => clampRectToViewport(next, readViewport(), { keepVisible: WINDOW_KEEP_VISIBLE }),\n onCommit: (_rect, commit) => setOffset(commit.offset),\n });\n const handle = React.useMemo<DialogWindowHandle | null>(\n () => (windowed ? { onPointerDown: drag.onPointerDown, onDoubleClick: () => setOffset({ x: 0, y: 0 }) } : null),\n [windowed, drag.onPointerDown],\n );\n\n const mergedRef = React.useCallback(\n (node: HTMLDivElement | null) => {\n setContainerEl(node);\n if (typeof ref === \"function\") ref(node);\n else if (ref)\n (ref as React.MutableRefObject<HTMLDivElement | null>).current = node;\n },\n [ref],\n );\n\n // The × sits in the header's row, or in a row of its own (close-slot.tsx).\n const closeSlot = useCloseSlot(showCloseButton && !desktopLook);\n\n const hasTitle =\n treeContainsComponent(children, DialogTitle) ||\n treeContainsComponent(children, DialogPrimitive.Title);\n const hasDescription =\n treeContainsComponent(children, DialogDescription) ||\n treeContainsComponent(children, DialogPrimitive.Description);\n\n return (\n <DialogPortal container={container}>\n {isModal ? <DialogOverlay /> : null}\n <DialogContentPrimitive\n ref={mergedRef}\n data-slot=\"dialog-content\"\n data-size={size}\n data-padding={padding === \"none\" ? \"none\" : undefined}\n data-height={height === \"tall\" ? \"tall\" : undefined}\n data-desktop-sheet={desktopLook ? \"\" : undefined}\n className={cn(\n asSheet ? DIALOG_MOBILE_SHEET_CLASSES : DIALOG_DESKTOP_CLASSES,\n !asSheet && DIALOG_SIZE_CLASS[size],\n padding === \"none\" && (asSheet ? \"gap-0 p-0 pb-safe [--dialog-pad:0px]\" : \"gap-0 p-0 [--dialog-pad:0px]\"),\n height === \"tall\" && (asSheet ? \"h-[90dvh]\" : \"h-[85dvh]\"),\n animated && !desktopLook && (asSheet ? MOTION_BOTTOM_SHEET : MOTION_DIALOG),\n className,\n asSheet && DIALOG_MOBILE_SHEET_OVERRIDE,\n // A non-modal dialog is the coexistence contract for content that\n // can sit beside a host's floating window manager (which starts at\n // z=1000); staying below that boundary makes a newly focused window\n // usable without coupling the two systems.\n !isModal && !windowedByDefault && \"z-[900]\",\n // Another layer came to the front after this window (layer-front.ts).\n stacks && behind && \"z-[999]\",\n // Without an overlay the card needs its own separation from the page.\n windowed && \"shadow-2xl ring-1 ring-border/60\",\n )}\n style={\n windowed && (offset.x !== 0 || offset.y !== 0)\n ? { ...style, translate: `${offset.x}px ${offset.y}px` }\n : style\n }\n onPointerDownCapture={(event) => {\n onPointerDownCapture?.(event);\n if (behind) bringToFront();\n }}\n onFocusCapture={(event) => {\n onFocusCapture?.(event);\n if (behind) bringToFront();\n }}\n onInteractOutside={(event) => {\n onInteractOutside?.(event);\n if (windowed && !dismissOnOutsideClick) event.preventDefault();\n }}\n onEscapeKeyDown={(event) => {\n onEscapeKeyDown?.(event);\n // Escape pressed in the page belongs to the page (a grid canceling\n // an edit), not to the window beside it.\n // The key's own target is where the person pressed it; focus is\n // the fallback when the event carries no element target.\n const pressedIn =\n event.target instanceof Node && event.target !== document.body\n ? event.target\n : document.activeElement;\n // Focus on <body> (or nowhere) belongs to nobody in the page: a button that disabled itself\n // while it worked (Share with User) drops focus there, and Escape must still close the window.\n const nowhere =\n !pressedIn || pressedIn === document.body || pressedIn === document.documentElement;\n if (windowed && containerEl && !nowhere && !containerEl.contains(pressedIn)) {\n event.preventDefault();\n }\n }}\n {...(hasDescription ? {} : { \"aria-describedby\": undefined })}\n {...props}\n >\n {hasTitle ? null : (\n <VisuallyHidden.Root>\n <DialogPrimitive.Title>Dialog</DialogPrimitive.Title>\n </VisuallyHidden.Root>\n )}\n {closeSlot.slot && !closeSlot.claimed ? <CloseRow /> : null}\n <CloseSlotProvider value={closeSlot.slot}>\n <DialogContainerContext.Provider value={containerEl}>\n <DialogWindowHandleContext.Provider value={handle}>\n <PortalContainerProvider\n container={containerEl ?? injectedContainer ?? null}\n >\n {children}\n </PortalContainerProvider>\n </DialogWindowHandleContext.Provider>\n </DialogContainerContext.Provider>\n </CloseSlotProvider>\n </DialogContentPrimitive>\n </DialogPortal>\n );\n },\n);\nDialogContent.displayName = DialogPrimitive.Content.displayName;\n\nconst DialogHeader = ({\n className,\n ...props\n}: React.HTMLAttributes<HTMLDivElement>) => {\n // In a windowed dialog the header is the drag handle (rule 6).\n const handle = React.useContext(DialogWindowHandleContext);\n return (\n <HeaderWithClose\n slotName=\"dialog-header\"\n baseClassName=\"flex flex-col space-y-1.5 text-center sm:text-left\"\n // DialogTitle's line is 18px (text-lg leading-none): (44 - 18) / 2 = 13, (32 - 18) / 2 = 7.\n closeOffsetClassName=\"-mt-3 lg:-mt-1.5\"\n {...(handle\n ? {\n ...handle,\n \"data-window-handle\": \"\",\n title: \"Drag to move · double-click to recenter\",\n }\n : {})}\n className={cn(handle && \"cursor-grab select-none active:cursor-grabbing\", className)}\n {...props}\n />\n );\n};\nDialogHeader.displayName = \"DialogHeader\";\n\nconst DialogFooter = ({\n className,\n ...props\n}: React.HTMLAttributes<HTMLDivElement>) => (\n <div\n data-slot=\"dialog-footer\"\n className={cn(\n // `gap-2` is the stacked (phone) gap — the buttons never touch; from sm up the\n // row keeps its `space-x-2`, so the gap resets to 0 there.\n \"flex flex-col-reverse gap-2 sm:flex-row sm:justify-end sm:gap-0 sm:space-x-2\",\n // Ruling 3/4 — sticky to the card edges so a scrolled body never shows\n // through under the actions, and safe-area padded on a phone.\n //\n // 🚨 THERE IS NO `mb-[…]` HERE, AND THERE MUST NEVER BE ONE AGAIN\n // (0.11.3, feedback bf8fb00b). The bleed over the card's bottom padding\n // used to be a NEGATIVE BLOCK MARGIN, which makes this box taller than\n // the grid area the card allocates it — and `position: sticky` CLAMPS a\n // box to its containing block, so the browser yanked the footer UP by\n // `--dialog-pad` against the card's `gap-4` and painted 8px of opaque\n // footer over the last line of the consequence, at every length. The\n // card now RESERVES this footer's block size instead (`matrx-dialog-card`\n // in styles.css hands over its `padding-bottom`), so the bleed costs no\n // margin at all. Guard: `sticky-footer-geometry.test.tsx`.\n //\n // These stay UTILITIES rather than a shipped rule so a caller's\n // `className` still wins through tailwind-merge — a shipped rule would\n // have to be unlayered to survive Tailwind preflight (§ THE PREFLIGHT\n // RULE in styles.css) and would then override every caller's padding.\n \"sticky bottom-0 z-10 bg-background pt-3\",\n \"mx-[calc(var(--dialog-pad,0px)*-1)] px-[var(--dialog-pad,0px)] pb-[var(--dialog-pad,0px)]\",\n className,\n )}\n {...props}\n />\n);\nDialogFooter.displayName = \"DialogFooter\";\n\nconst DialogTitle = React.forwardRef<\n React.ComponentRef<typeof DialogPrimitive.Title>,\n React.ComponentPropsWithoutRef<typeof DialogPrimitive.Title>\n>(({ className, ...props }, ref) => (\n <DialogPrimitive.Title\n ref={ref}\n data-slot=\"dialog-title\"\n className={cn(\"text-lg font-semibold leading-none tracking-tight\", className)}\n {...props}\n />\n));\nDialogTitle.displayName = DialogPrimitive.Title.displayName;\n\nconst DialogDescription = React.forwardRef<\n React.ComponentRef<typeof DialogPrimitive.Description>,\n React.ComponentPropsWithoutRef<typeof DialogPrimitive.Description>\n>(({ className, ...props }, ref) => (\n <DialogPrimitive.Description\n ref={ref}\n data-slot=\"dialog-description\"\n className={cn(\"text-sm text-muted-foreground\", className)}\n {...props}\n />\n));\nDialogDescription.displayName = DialogPrimitive.Description.displayName;\n\nexport {\n Dialog,\n DialogClose,\n DialogContent,\n DialogContentPrimitive,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogOverlay,\n DialogPortal,\n DialogTitle,\n DialogTrigger,\n};\n","/**\n * THE MOTION CONTRACT (0.10.0) — the class names every animated surface in\n * this package puts on the DOM, in ONE place.\n *\n * Why a module and not ten inline strings: the sweep that produced this file\n * found the same defect ten times over, and it was invisible each time\n * because each primitive spelled its animation out by hand. Ten hand-written\n * copies of `data-[state=open]:animate-in data-[state=closed]:animate-out\n * data-[state=closed]:fade-out-0 …` meant ten chances to reach for a utility\n * nothing in the package defines — which is exactly what happened. A single\n * exported constant per motion SHAPE means the next primitive cannot invent\n * an eleventh spelling, and `styles.test.ts` can prove every one of them\n * resolves to a rule in the shipped stylesheet.\n *\n * Every rule these name lives in `styles.css` under the package's own\n * keyframes. NONE of them is a Tailwind utility, and none requires a host\n * plugin — see that file's header for the measurement that made this\n * necessary.\n */\n\n/** Modal scrims: Dialog, AlertDialog, Sheet, CommandDialog. Fade only. */\nexport const MOTION_OVERLAY = \"matrx-motion-overlay\";\n\n/** The centered dialog card. Fades and scales; centering is not its business. */\nexport const MOTION_DIALOG = \"matrx-motion-dialog\";\n\n/**\n * THE CENTERING OF A CENTERED DIALOG CARD — package-owned, in the `translate`\n * property, and NEVER a Tailwind `translate-x-[-50%] translate-y-[-50%]` pair.\n *\n * Those utilities do not compile to the same thing in every host: Tailwind v3\n * writes them into `transform`, Tailwind v4 writes them into the independent\n * `translate` property, which COMPOSES with `transform` instead of being\n * replaced by it. 0.10.0's keyframes restated the centering inside `transform`,\n * which was harmless on v3 and doubled the centering on v4 — the card flew in\n * from off the top-left of the viewport for the animation's whole duration and\n * snapped into place at the end (fixed in 0.10.1).\n *\n * Owning it here means one spelling that reads the same on both, and it frees\n * `transform` so the keyframes carry ONLY the delta. Put this on every centered\n * surface UNCONDITIONALLY — it is geometry, so unlike {@link MOTION_DIALOG} it\n * must survive `animated={false}`. Its rule ships in `styles.css`.\n */\nexport const CENTERED_DIALOG = \"matrx-dialog-centered\";\n\n/**\n * The resting gap between a `popper`-positioned surface and its trigger, for\n * the primitives that want one (today: `Select`). Same law and same reason as\n * {@link CENTERED_DIALOG} — a position an animated surface holds AT REST is\n * the `translate` property's job, never a Tailwind translate utility, because\n * those land in `transform` on a v3 host and in `translate` on a v4 one while\n * the keyframes animate `transform` either way. Sizes from\n * `--matrx-popper-offset`; keys off Radix's `data-side`.\n */\nexport const POPPER_OFFSET = \"matrx-popper-offset\";\n\n/** The mobile Dialog / CommandDialog bottom sheet. Slides up and fades. */\nexport const MOTION_BOTTOM_SHEET = \"matrx-motion-bottom-sheet\";\n\n/**\n * Radix-popper surfaces: Popover, DropdownMenu, ContextMenu, HoverCard,\n * Select, Tooltip. Reads `--radix-popper-transform-origin` so the surface\n * grows out of its trigger, and `data-side` so it travels from it.\n */\nexport const MOTION_POPPER = \"matrx-motion-popper\";\n\n/** Edge sheets, one class per `sheetVariants` side. */\nexport const MOTION_SHEET = {\n top: \"matrx-motion-sheet-top\",\n bottom: \"matrx-motion-sheet-bottom\",\n left: \"matrx-motion-sheet-left\",\n right: \"matrx-motion-sheet-right\",\n center: \"matrx-motion-sheet-center\",\n} as const;\n\n/** Skeleton's breathing loop. */\nexport const MOTION_PULSE = \"matrx-pulse\";\n/** A waiting box's crossing band of light (Skeleton `motion=\"shimmer\"`). Reduced motion: a slow breathe, no travel. */\nexport const MOTION_SHIMMER = \"matrx-shimmer\";\n\n/** The spinner loop, for every inline busy indicator in the package. */\nexport const MOTION_SPIN = \"matrx-spin\";\n\n/**\n * FirstUseHint's beacon: a soft ring that pulses three times around the anchor, on\n * `box-shadow` only, so nothing moves. A still ring under reduced motion.\n */\nexport const MOTION_HINT_BEACON = \"matrx-motion-hint-beacon\";\n\n/**\n * Every motion class the package ships, for the guards. If a rule for one of\n * these is missing from `styles.css`, a component animates in no consumer and\n * says nothing about it — the C26 failure this list exists to make loud.\n */\nexport const ALL_MOTION_CLASSES = [\n MOTION_OVERLAY,\n MOTION_DIALOG,\n MOTION_BOTTOM_SHEET,\n MOTION_POPPER,\n ...Object.values(MOTION_SHEET),\n MOTION_PULSE,\n MOTION_SHIMMER,\n MOTION_SPIN,\n MOTION_HINT_BEACON,\n] as const;\n\n/**\n * The host-plugin utilities this package is forbidden to emit. They are\n * supplied by `tailwindcss-animate` / `tw-animate-css`, which is a HOST CSS\n * entry concern a package cannot declare a dependency on: three of the four\n * AI Matrx consumers never loaded it, so every surface wearing these appeared\n * with no animation and no error. `styles.test.ts` fails the build if one\n * comes back.\n */\nexport const FORBIDDEN_HOST_MOTION_UTILITIES = [\n \"animate-in\",\n \"animate-out\",\n \"fade-in\",\n \"fade-out\",\n \"zoom-in\",\n \"zoom-out\",\n \"slide-in-from\",\n \"slide-out-to\",\n \"animate-accordion\",\n \"animate-slide-down\",\n \"animate-slide-up\",\n \"animate-pulse\",\n \"animate-spin\",\n] as const;\n\n/**\n * THE PANEL MOTION as a Tailwind class string (moved from matrx-frontend\n * `lib/motion/panel-motion.ts`): every panel, sidebar, dock, drawer and sheet\n * slides its size/position on the host's `--matrx-motion-duration-panel` /\n * `--matrx-motion-ease-panel` (tokens.css ships the standard). Pair it with the\n * transition property you animate (`transition-transform`, …).\n */\nexport const PANEL_MOTION_CLASS =\n \"duration-(--matrx-motion-duration-panel) ease-(--matrx-motion-ease-panel) motion-reduce:transition-none\";\nexport const PANEL_MOTION_DURATION_VAR = \"var(--matrx-motion-duration-panel)\";\nexport const PANEL_MOTION_EASE_VAR = \"var(--matrx-motion-ease-panel)\";\n","\"use client\";\n\n/**\n * THE CLOSE CONTROL LIVES IN A ROW, NEVER IN A CORNER.\n *\n * The stock shadcn dialog pins its × with `absolute right-4 top-4`: a\n * coordinate guess about how tall the content's first row will be. Every\n * content whose first row is a different height got an × floating off its\n * row — the command palette's sat 12px below its 48px search row, on the\n * divider, with the query running underneath it (Arman, 2026-10-20: \"each\n * time they use this component, we end up with a very oddly placed x\").\n * Agents re-typed that snippet from memory faster than it could be fixed.\n *\n * So the × is a flex item of the row it belongs to, centered by layout:\n *\n * - `CommandInput` inside a `CommandDialog` draws it at the end of the\n * search row.\n * - `DialogHeader` / `SheetHeader` draw it at the end of the header row and\n * CLAIM it, so the content does not draw a second one; with two headers the\n * first one mounted draws it.\n * - Content with no visible header gets a close row of its own at the top,\n * in flow — it takes space, it never covers anything.\n *\n * Guard: `close-in-flow.test.tsx` — no `*.Close` in this package or its\n * consumers carries `absolute`/`fixed`, and each surface puts the × inside\n * its row.\n */\n\nimport * as DialogPrimitive from \"@radix-ui/react-dialog\";\nimport * as React from \"react\";\n\nimport { cn } from \"./cn\";\nimport { XIcon } from \"./icons\";\n\n/** 44px on touch, 32px from `lg`; a flex item, never positioned. */\nconst CLOSE_CONTROL_CLASSES =\n \"flex h-11 w-11 shrink-0 items-center justify-center rounded-sm text-muted-foreground ring-offset-background transition-colors hover:text-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none lg:h-8 lg:w-8\";\n\nexport function CloseControl({ className }: { className?: string }): React.ReactElement {\n return (\n <DialogPrimitive.Close data-slot=\"dialog-close\" aria-label=\"Close\" className={cn(CLOSE_CONTROL_CLASSES, className)}>\n <XIcon className=\"h-4 w-4\" aria-hidden=\"true\" />\n <span className=\"sr-only\">Close</span>\n </DialogPrimitive.Close>\n );\n}\n\ninterface CloseSlot {\n /** A row takes the × into itself; returns the release. The FIRST live claimant owns it. */\n claim(id: string): () => void;\n /** The id that draws the ×, or null while nobody claims it. */\n owner: string | null;\n}\n\n/** Dialog and Sheet: claimed by their header. */\nconst CloseSlotContext = React.createContext<CloseSlot | null>(null);\n/**\n * CommandDialog: claimed by its search row only. A separate context so a\n * CommandInput in a combobox (Popover > Command) opened INSIDE a Dialog never\n * takes the dialog's × — context crosses portals, and that × closes the dialog.\n */\nconst SearchRowCloseSlotContext = React.createContext<CloseSlot | null>(null);\n\n/**\n * For a content surface: returns the provider value and whether a row has\n * claimed the ×. Unclaimed (no header, or only an `sr-only`/`hidden` one) the\n * content draws `<CloseRow />` first, in flow. Claims land in a layout effect,\n * so the fallback never paints when a row takes it.\n */\nexport function useCloseSlot(enabled: boolean): { slot: CloseSlot | null; claimed: boolean } {\n const [claims, setClaims] = React.useState<string[]>([]);\n const owner = claims[0] ?? null;\n const claim = React.useCallback((id: string) => {\n setClaims((list) => [...list, id]);\n return () => setClaims((list) => list.filter((c) => c !== id));\n }, []);\n const slot = React.useMemo<CloseSlot | null>(() => (enabled ? { claim, owner } : null), [enabled, claim, owner]);\n return { slot, claimed: owner !== null };\n}\n\nexport const CloseSlotProvider = CloseSlotContext.Provider;\nexport const SearchRowCloseSlotProvider = SearchRowCloseSlotContext.Provider;\n\nfunction useClaim(context: React.Context<CloseSlot | null>, declined: boolean): boolean {\n const slot = React.useContext(context);\n const id = React.useId();\n const claim = slot?.claim;\n const wants = claim !== undefined && !declined;\n // Depends on the stable `claim`, never on `owner`, so a change of owner never re-claims.\n React.useLayoutEffect(() => (wants && claim ? claim(id) : undefined), [wants, claim, id]);\n return wants && slot?.owner === id;\n}\n\n/** For a header row: claims the Dialog/Sheet slot; true when this row draws the ×. */\nexport function useCloseSlotClaim(declined = false): boolean {\n return useClaim(CloseSlotContext, declined);\n}\n\n/** For CommandInput: claims only a CommandDialog's slot; true when this row draws the ×. */\nexport function useSearchRowCloseSlotClaim(): boolean {\n return useClaim(SearchRowCloseSlotContext, false);\n}\n\n/** The fallback: a row of its own at the top of the content. */\nexport function CloseRow({ className }: { className?: string }): React.ReactElement {\n return (\n <div data-slot=\"close-row\" className={cn(\"flex justify-end\", className)}>\n <CloseControl />\n </div>\n );\n}\n\n/** Classes that lay out a header's CHILDREN; they move to the header's body. */\nconst BODY_LAYOUT = /^!?(?:[a-z0-9]+:)*(?:flex|grid|flex-(?:row|col)(?:-reverse)?|grid-(?:cols|rows|flow)-\\S+|place-\\S+|items-\\S+|justify-\\S+|content-\\S+|gap(?:-[xy])?-\\S+|space-[xy]-\\S+|text-(?:left|center|right|start|end)|flex-wrap|flex-nowrap)$/;\n/**\n * Right padding a header carried to clear the old corner ×; with the × in the\n * row it would only push the × inward, so it is dropped.\n */\nconst OLD_CLOSE_RESERVE = /^pr-(?:8|9|10|11|12|14|16)$/;\n\nfunction splitHeaderClasses(className: string | undefined): { row: string; body: string } {\n const row: string[] = [];\n const body: string[] = [];\n for (const c of (className ?? \"\").split(/\\s+/)) {\n if (!c || OLD_CLOSE_RESERVE.test(c)) continue;\n (BODY_LAYOUT.test(c) ? body : row).push(c);\n }\n return { row: row.join(\" \"), body: body.join(\" \") };\n}\n\n/**\n * A header's element. With a close slot it is a row — the caller's children\n * in a body column, the × after them; the caller's padding, border and\n * background stay on the row, the caller's child layout (`flex-row`,\n * `space-y-*`, `text-left`…) moves to the body. Without one (no ×, or the\n * header is `sr-only`) it renders exactly as `baseClassName` + `className`.\n */\nexport function HeaderWithClose({\n slotName,\n baseClassName,\n closeOffsetClassName,\n className,\n children,\n ...props\n}: React.HTMLAttributes<HTMLDivElement> & {\n slotName: string;\n baseClassName: string;\n /** Pulls the × up so its center sits on the title's first line (the title's line height is the header's to know). */\n closeOffsetClassName: string;\n}): React.ReactElement {\n // A header nobody sees declines the ×; the content's own close row draws it.\n const owns = useCloseSlotClaim(/(?:^|\\s)(?:sr-only|hidden)(?:\\s|$)/.test(className ?? \"\"));\n if (!owns) {\n return (\n <div data-slot={slotName} className={cn(baseClassName, className)} {...props}>\n {children}\n </div>\n );\n }\n const { row, body } = splitHeaderClasses(className);\n // A header laid out as a row centers the × on that row; a stacked one, on the title's first line.\n const rowish = /(?:^|\\s)(?:[a-z0-9]+:)*flex-row(?:\\s|$)/.test(body);\n return (\n <div data-slot={slotName} data-has-close=\"\" className={cn(\"flex gap-2\", rowish ? \"items-center\" : \"items-start\", row)} {...props}>\n <div data-slot={`${slotName}-body`} className={cn(\"min-w-0 flex-1\", baseClassName, body)}>\n {children}\n </div>\n <CloseControl className={cn(\"-mr-2\", !rowish && closeOffsetClassName)} />\n </div>\n );\n}\n","/**\n * Internal inlined SVG icons (policy C19: no icon-library dependency, ever).\n *\n * Each icon is copied from the exact glyph the ported originals rendered:\n * lucide-react's Loader2 / ChevronLeft / ChevronRight / MoreHorizontal and\n * @radix-ui/react-icons' Cross2Icon. Same viewBoxes, same paths, same default\n * stroke geometry — a host swapping the import sees pixel-identical output.\n *\n * Not exported from the package entry; components consume them directly.\n */\n\nimport * as React from \"react\";\n\nexport type IconProps = React.SVGAttributes<SVGSVGElement>;\n\n/**\n * Every lucide glyph carries `lucide-<name>`, the class lucide-react itself renders: THE OPTICAL\n * GLYPH TRIM (tap-target.css) reads the glyph's real air from it, and a caller's own class follows it.\n */\nfunction lucideProps(name: string, { className, ...props }: IconProps): React.SVGAttributes<SVGSVGElement> {\n return {\n className: className ? `lucide-${name} ${className}` : `lucide-${name}`,\n xmlns: \"http://www.w3.org/2000/svg\",\n viewBox: \"0 0 24 24\",\n fill: \"none\",\n stroke: \"currentColor\",\n strokeWidth: 2,\n strokeLinecap: \"round\",\n strokeLinejoin: \"round\",\n \"aria-hidden\": true,\n ...props,\n };\n}\n\n/**\n * lucide `loader-2` — the spinner glyph. Callers add `matrx-spin`.\n * Never a resting icon: at rest this incomplete arc reads as a broken\n * half-circle. Refresh controls use arrows, then swap to this only while busy.\n */\nexport function Loader2Icon(props: IconProps) {\n return (\n <svg {...lucideProps(\"loader-circle\", props)}>\n <path d=\"M21 12a9 9 0 1 1-6.219-8.56\" />\n </svg>\n );\n}\n\n/** lucide `chevron-left`. */\nexport function ChevronLeftIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"chevron-left\", props)}>\n <path d=\"m15 18-6-6 6-6\" />\n </svg>\n );\n}\n\n/** lucide `chevron-right`. */\nexport function ChevronRightIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"chevron-right\", props)}>\n <path d=\"m9 18 6-6-6-6\" />\n </svg>\n );\n}\n\n/** lucide `chevron-down` — the disclosure's open glyph. */\nexport function ChevronDownIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"chevron-down\", props)}>\n <path d=\"m6 9 6 6 6-6\" />\n </svg>\n );\n}\n\n/** lucide `trash-2` (moved from @ai-matrx/agents). */\nexport function Trash2Icon(props: IconProps) {\n return (\n <svg {...lucideProps(\"trash-2\", props)}>\n <path d=\"M10 11v6\" />\n <path d=\"M14 11v6\" />\n <path d=\"M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6\" />\n <path d=\"M3 6h18\" />\n <path d=\"M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2\" />\n </svg>\n );\n}\n\n/** lucide `archive` — the archived-rows glyph (ArchivedDisclosure). */\nexport function ArchiveIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"archive\", props)}>\n <rect width=\"20\" height=\"5\" x=\"2\" y=\"3\" rx=\"1\" />\n <path d=\"M4 8v11a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8\" />\n <path d=\"M10 12h4\" />\n </svg>\n );\n}\n\n/** lucide `more-horizontal` — the kebab/ellipsis glyph. */\nexport function MoreHorizontalIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"ellipsis\", props)}>\n <circle cx=\"12\" cy=\"12\" r=\"1\" />\n <circle cx=\"19\" cy=\"12\" r=\"1\" />\n <circle cx=\"5\" cy=\"12\" r=\"1\" />\n </svg>\n );\n}\n\n/** lucide `check` — the selected-row tick (CreatablePicker). */\nexport function CheckIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"check\", props)}>\n <path d=\"M20 6 9 17l-5-5\" />\n </svg>\n );\n}\n\n/** lucide `chevrons-up-down` — the combobox trigger glyph. */\nexport function ChevronsUpDownIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"chevrons-up-down\", props)}>\n <path d=\"m7 15 5 5 5-5\" />\n <path d=\"m7 9 5-5 5 5\" />\n </svg>\n );\n}\n\n/** lucide `external-link` — the manage-in-new-tab glyph. */\nexport function ExternalLinkIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"external-link\", props)}>\n <path d=\"M15 3h6v6\" />\n <path d=\"M10 14 21 3\" />\n <path d=\"M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6\" />\n </svg>\n );\n}\n\n/** lucide `lock` — the platform-governed vocabulary glyph. */\nexport function LockIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"lock\", props)}>\n <rect width=\"18\" height=\"11\" x=\"3\" y=\"11\" rx=\"2\" ry=\"2\" />\n <path d=\"M7 11V7a5 5 0 0 1 10 0v4\" />\n </svg>\n );\n}\n\n/** lucide `pencil` — the edit glyph (the table card's Edit action). */\nexport function PencilIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"pencil\", props)}>\n <path d=\"M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z\" />\n <path d=\"m15 5 4 4\" />\n </svg>\n );\n}\n\n/** lucide `message-square` — a row's comments (records-ui SectionCard). */\nexport function MessageSquareIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"message-square\", props)}>\n <path d=\"M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z\" />\n </svg>\n );\n}\n\n/** lucide `sticky-note` — a row's usage note (records-ui SectionCard). */\nexport function StickyNoteIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"sticky-note\", props)}>\n <path d=\"M16 3H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V8Z\" />\n <path d=\"M15 3v4a2 2 0 0 0 2 2h4\" />\n </svg>\n );\n}\n\n/** lucide `minus` — the decrease glyph (NumberStepper). */\nexport function MinusIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"minus\", props)}>\n <path d=\"M5 12h14\" />\n </svg>\n );\n}\n\n/** lucide `plus` — the create/add glyph. */\nexport function PlusIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"plus\", props)}>\n <path d=\"M5 12h14\" />\n <path d=\"M12 5v14\" />\n </svg>\n );\n}\n\n/** lucide `search` — the magnifier (the `@ai-matrx/design-system/icons` section). */\nexport function SearchIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"search\", props)}>\n <circle cx=\"11\" cy=\"11\" r=\"8\" />\n <path d=\"m21 21-4.3-4.3\" />\n </svg>\n );\n}\n\n/** lucide `list-filter` — a table's filter button (Mail's and Finder's filter). */\nexport function ListFilterIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"list-filter\", props)}>\n <path d=\"M3 6h18\" />\n <path d=\"M7 12h10\" />\n <path d=\"M10 18h4\" />\n </svg>\n );\n}\n\n/** lucide `pin` — pinned state (the `@ai-matrx/design-system/icons` section). */\nexport function PinIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"pin\", props)}>\n <path d=\"M12 17v5\" />\n <path d=\"M9 10.76a2 2 0 0 1-1.11 1.79l-1.78.9A2 2 0 0 0 5 15.24V16a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1v-.76a2 2 0 0 0-1.11-1.79l-1.78-.9A2 2 0 0 1 15 10.76V7a1 1 0 0 1 1-1 2 2 0 0 0 0-4H8a2 2 0 0 0 0 4 1 1 0 0 1 1 1z\" />\n </svg>\n );\n}\n\n/** lucide `x` — the dialog close glyph (host dialog module used lucide X). */\nexport function XIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"x\", props)}>\n <path d=\"M18 6 6 18\" />\n <path d=\"m6 6 12 12\" />\n </svg>\n );\n}\n\n/**\n * @radix-ui/react-icons components default to width/height 15 — the bare\n * `<ChevronUpIcon />` renders in Select's scroll buttons rely on it.\n */\nfunction radixProps(props: IconProps): React.SVGAttributes<SVGSVGElement> {\n return {\n xmlns: \"http://www.w3.org/2000/svg\",\n viewBox: \"0 0 15 15\",\n width: 15,\n height: 15,\n fill: \"none\",\n \"aria-hidden\": true,\n ...props,\n };\n}\n\n/** @radix-ui/react-icons `MagnifyingGlassIcon` — the command search glyph. */\nexport function MagnifyingGlassIcon(props: IconProps) {\n return (\n <svg {...radixProps(props)}>\n <path\n d=\"M10 6.5C10 8.433 8.433 10 6.5 10C4.567 10 3 8.433 3 6.5C3 4.567 4.567 3 6.5 3C8.433 3 10 4.567 10 6.5ZM9.30884 10.0159C8.53901 10.6318 7.56251 11 6.5 11C4.01472 11 2 8.98528 2 6.5C2 4.01472 4.01472 2 6.5 2C8.98528 2 11 4.01472 11 6.5C11 7.56251 10.6318 8.53901 10.0159 9.30884L12.8536 12.1464C13.0488 12.3417 13.0488 12.6583 12.8536 12.8536C12.6583 13.0488 12.3417 13.0488 12.1464 12.8536L9.30884 10.0159Z\"\n fill=\"currentColor\"\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n />\n </svg>\n );\n}\n\n/** @radix-ui/react-icons `CheckIcon` — the select item indicator glyph. */\nexport function RadixCheckIcon(props: IconProps) {\n return (\n <svg {...radixProps(props)}>\n <path\n d=\"M11.4669 3.72684C11.7558 3.91574 11.8369 4.30308 11.648 4.59198L7.39799 11.092C7.29783 11.2452 7.13556 11.3467 6.95402 11.3699C6.77247 11.3931 6.58989 11.3355 6.45446 11.2124L3.70446 8.71241C3.44905 8.48022 3.43023 8.08494 3.66242 7.82953C3.89461 7.57412 4.28989 7.55529 4.5453 7.78749L6.75292 9.79441L10.6018 3.90792C10.7907 3.61902 11.178 3.53795 11.4669 3.72684Z\"\n fill=\"currentColor\"\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n />\n </svg>\n );\n}\n\n/**\n * @radix-ui/react-icons `DividerHorizontalIcon` — the INDETERMINATE checkbox\n * glyph. Radix renders the indicator for both `true` and `\"indeterminate\"`, so\n * a half-selected \"select all\" that shows a full check states something false;\n * the two states get different glyphs on purpose.\n */\nexport function DividerHorizontalIcon(props: IconProps) {\n return (\n <svg {...radixProps(props)}>\n <path\n d=\"M2 7.5C2 7.22386 2.22386 7 2.5 7H12.5C12.7761 7 13 7.22386 13 7.5C13 7.77614 12.7761 8 12.5 8H2.5C2.22386 8 2 7.77614 2 7.5Z\"\n fill=\"currentColor\"\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n />\n </svg>\n );\n}\n\n/** @radix-ui/react-icons `DotFilledIcon` — the menu radio-item indicator. */\nexport function DotFilledIcon(props: IconProps) {\n return (\n <svg {...radixProps(props)}>\n <path\n d=\"M9.875 7.5C9.875 8.81168 8.81168 9.875 7.5 9.875C6.18832 9.875 5.125 8.81168 5.125 7.5C5.125 6.18832 6.18832 5.125 7.5 5.125C8.81168 5.125 9.875 6.18832 9.875 7.5Z\"\n fill=\"currentColor\"\n />\n </svg>\n );\n}\n\n/** @radix-ui/react-icons `ChevronRightIcon` — the submenu-trigger glyph. */\nexport function RadixChevronRightIcon(props: IconProps) {\n return (\n <svg {...radixProps(props)}>\n <path\n d=\"M6.1584 3.13508C6.35985 2.94621 6.67627 2.95642 6.86514 3.15788L10.6151 7.15788C10.7954 7.3502 10.7954 7.64949 10.6151 7.84182L6.86514 11.8418C6.67627 12.0433 6.35985 12.0535 6.1584 11.8646C5.95694 11.6757 5.94673 11.3593 6.1356 11.1579L9.565 7.49985L6.1356 3.84182C5.94673 3.64036 5.95694 3.32394 6.1584 3.13508Z\"\n fill=\"currentColor\"\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n />\n </svg>\n );\n}\n\n/** @radix-ui/react-icons `ChevronDownIcon` — the select trigger/scroll glyph. */\nexport function RadixChevronDownIcon(props: IconProps) {\n return (\n <svg {...radixProps(props)}>\n <path\n d=\"M3.13523 6.15803C3.3241 5.95657 3.64052 5.94637 3.84197 6.13523L7.5 9.56464L11.158 6.13523C11.3595 5.94637 11.6759 5.95657 11.8648 6.15803C12.0536 6.35949 12.0434 6.67591 11.842 6.86477L7.84197 10.6148C7.64964 10.7951 7.35036 10.7951 7.15803 10.6148L3.15803 6.86477C2.95657 6.67591 2.94637 6.35949 3.13523 6.15803Z\"\n fill=\"currentColor\"\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n />\n </svg>\n );\n}\n\n/** @radix-ui/react-icons `ChevronUpIcon` — the select scroll-up glyph. */\nexport function RadixChevronUpIcon(props: IconProps) {\n return (\n <svg {...radixProps(props)}>\n <path\n d=\"M3.13523 8.84197C3.3241 9.04343 3.64052 9.05363 3.84197 8.86477L7.5 5.43536L11.158 8.86477C11.3595 9.05363 11.6759 9.04343 11.8648 8.84197C12.0536 8.64051 12.0434 8.32409 11.842 8.13523L7.84197 4.38523C7.64964 4.20492 7.35036 4.20492 7.15803 4.38523L3.15803 8.13523C2.95657 8.32409 2.94637 8.64051 3.13523 8.84197Z\"\n fill=\"currentColor\"\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n />\n </svg>\n );\n}\n\n/** @radix-ui/react-icons `Cross2Icon` — the dialog/sheet close glyph. */\nexport function Cross2Icon(props: IconProps) {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 15 15\"\n fill=\"none\"\n aria-hidden\n {...props}\n >\n <path\n d=\"M11.7816 4.03157C12.0062 3.80702 12.0062 3.44295 11.7816 3.2184C11.5571 2.99385 11.193 2.99385 10.9685 3.2184L7.50005 6.68682L4.03164 3.2184C3.80708 2.99385 3.44301 2.99385 3.21846 3.2184C2.99391 3.44295 2.99391 3.80702 3.21846 4.03157L6.68688 7.49999L3.21846 10.9684C2.99391 11.193 2.99391 11.557 3.21846 11.7816C3.44301 12.0061 3.80708 12.0061 4.03164 11.7816L7.50005 8.31316L10.9685 11.7816C11.193 12.0061 11.5571 12.0061 11.7816 11.7816C12.0062 11.557 12.0062 11.193 11.7816 10.9684L8.31322 7.49999L11.7816 4.03157Z\"\n fill=\"currentColor\"\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n />\n </svg>\n );\n}\n\n/**\n * @radix-ui/react-icons `DragHandleDots2Icon` — the grip on `ResizableHandle`.\n * Inlined per C19: this package depends on no icon library.\n */\nexport function DragHandleDots2Icon(props: IconProps) {\n return (\n <svg {...radixProps(props)}>\n <path\n d=\"M4.5 2.5C5.05228 2.5 5.5 2.05228 5.5 1.5C5.5 0.947715 5.05228 0.5 4.5 0.5C3.94772 0.5 3.5 0.947715 3.5 1.5C3.5 2.05228 3.94772 2.5 4.5 2.5ZM4.5 6.5C5.05228 6.5 5.5 6.05229 5.5 5.5C5.5 4.94771 5.05228 4.5 4.5 4.5C3.94772 4.5 3.5 4.94771 3.5 5.5C3.5 6.05229 3.94772 6.5 4.5 6.5ZM5.5 9.5C5.5 10.0523 5.05228 10.5 4.5 10.5C3.94772 10.5 3.5 10.0523 3.5 9.5C3.5 8.94771 3.94772 8.5 4.5 8.5C5.05228 8.5 5.5 8.94771 5.5 9.5ZM4.5 14.5C5.05228 14.5 5.5 14.0523 5.5 13.5C5.5 12.9477 5.05228 12.5 4.5 12.5C3.94772 12.5 3.5 12.9477 3.5 13.5C3.5 14.0523 3.94772 14.5 4.5 14.5ZM11.5 1.5C11.5 2.05228 11.0523 2.5 10.5 2.5C9.94771 2.5 9.5 2.05228 9.5 1.5C9.5 0.947715 9.94771 0.5 10.5 0.5C11.0523 0.5 11.5 0.947715 11.5 1.5ZM10.5 6.5C11.0523 6.5 11.5 6.05229 11.5 5.5C11.5 4.94771 11.0523 4.5 10.5 4.5C9.94771 4.5 9.5 4.94771 9.5 5.5C9.5 6.05229 9.94771 6.5 10.5 6.5ZM11.5 9.5C11.5 10.0523 11.0523 10.5 10.5 10.5C9.94771 10.5 9.5 10.0523 9.5 9.5C9.5 8.94771 9.94771 8.5 10.5 8.5C11.0523 8.5 11.5 8.94771 11.5 9.5ZM10.5 14.5C11.0523 14.5 11.5 14.0523 11.5 13.5C11.5 12.9477 11.0523 12.5 10.5 12.5C9.94771 12.5 9.5 12.9477 9.5 13.5C9.5 14.0523 9.94771 14.5 10.5 14.5Z\"\n fill=\"currentColor\"\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n />\n </svg>\n );\n}\n\n/** lucide `star` — the saved-organization badge (OrganizationPicker). */\nexport function StarIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"star\", props)}>\n <path d=\"M11.525 2.295a.53.53 0 0 1 .95 0l2.31 4.679a2.123 2.123 0 0 0 1.595 1.16l5.166.756a.53.53 0 0 1 .294.904l-3.736 3.638a2.123 2.123 0 0 0-.611 1.878l.882 5.14a.53.53 0 0 1-.771.56l-4.618-2.428a2.122 2.122 0 0 0-1.973 0L6.396 21.01a.53.53 0 0 1-.77-.56l.881-5.139a2.122 2.122 0 0 0-.611-1.879L2.16 9.795a.53.53 0 0 1 .294-.906l5.165-.755a2.122 2.122 0 0 0 1.597-1.16z\" />\n </svg>\n );\n}\n\n/** lucide `building-2` — the organization glyph (OrganizationPicker trigger). */\nexport function Building2Icon(props: IconProps) {\n return (\n <svg {...lucideProps(\"building-2\", props)}>\n <path d=\"M6 22V4a2 2 0 0 1 2-2h8a2 2 0 0 1 2 2v18Z\" />\n <path d=\"M6 12H4a2 2 0 0 0-2 2v6a2 2 0 0 0 2 2h2\" />\n <path d=\"M18 9h2a2 2 0 0 1 2 2v9a2 2 0 0 1-2 2h-2\" />\n <path d=\"M10 6h4\" />\n <path d=\"M10 10h4\" />\n <path d=\"M10 14h4\" />\n <path d=\"M10 18h4\" />\n </svg>\n );\n}\n\n/** lucide `panel-left` — the sidebar toggle glyph. */\nexport function PanelLeftIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"panel-left\", props)}>\n <rect width=\"18\" height=\"18\" x=\"3\" y=\"3\" rx=\"2\" />\n <path d=\"M9 3v18\" />\n </svg>\n );\n}\n\n/** lucide `ellipsis-vertical` — a panel's \"more\" menu. */\nexport function MoreVerticalIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"ellipsis-vertical\", props)}>\n <circle cx=\"12\" cy=\"12\" r=\"1\" />\n <circle cx=\"12\" cy=\"5\" r=\"1\" />\n <circle cx=\"12\" cy=\"19\" r=\"1\" />\n </svg>\n );\n}\n\n/** lucide `maximize-2` — expand a panel. */\nexport function Maximize2Icon(props: IconProps) {\n return (\n <svg {...lucideProps(\"maximize-2\", props)}>\n <path d=\"M15 3h6v6\" />\n <path d=\"m21 3-7 7\" />\n <path d=\"m3 21 7-7\" />\n <path d=\"M9 21H3v-6\" />\n </svg>\n );\n}\n\n/** lucide `minimize-2` — restore an expanded panel. */\nexport function Minimize2Icon(props: IconProps) {\n return (\n <svg {...lucideProps(\"minimize-2\", props)}>\n <path d=\"m14 10 7-7\" />\n <path d=\"M20 10h-6V4\" />\n <path d=\"m3 21 7-7\" />\n <path d=\"M4 14h6v6\" />\n </svg>\n );\n}\n\n/** lucide `arrow-left`. */\nexport function ArrowLeftIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"arrow-left\", props)}>\n <path d=\"m12 19-7-7 7-7\" />\n <path d=\"M19 12H5\" />\n </svg>\n );\n}\n\n/** lucide `arrow-right`. */\nexport function ArrowRightIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"arrow-right\", props)}>\n <path d=\"M5 12h14\" />\n <path d=\"m12 5 7 7-7 7\" />\n </svg>\n );\n}\n\n/** lucide `arrow-up` — the swipe deck's up edge. */\nexport function ArrowUpIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"arrow-up\", props)}>\n <path d=\"m5 12 7-7 7 7\" />\n <path d=\"M12 19V5\" />\n </svg>\n );\n}\n\n/** lucide `arrow-down` — the swipe deck's down edge. */\nexport function ArrowDownIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"arrow-down\", props)}>\n <path d=\"M12 5v14\" />\n <path d=\"m19 12-7 7-7-7\" />\n </svg>\n );\n}\n\n/** lucide `undo-2` — take back the last change. */\nexport function Undo2Icon(props: IconProps) {\n return (\n <svg {...lucideProps(\"undo-2\", props)}>\n <path d=\"M9 14 4 9l5-5\" />\n <path d=\"M4 9h10.5a5.5 5.5 0 0 1 5.5 5.5a5.5 5.5 0 0 1-5.5 5.5H11\" />\n </svg>\n );\n}\n\n/** lucide `eraser` — forget a marked part. */\nexport function EraserIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"eraser\", props)}>\n <path d=\"m7 21-4.3-4.3c-1-1-1-2.5 0-3.4l9.6-9.6c1-1 2.5-1 3.4 0l5.6 5.6c1 1 1 2.5 0 3.4L13 21\" />\n <path d=\"M22 21H7\" />\n <path d=\"m5 11 9 9\" />\n </svg>\n );\n}\n\n/** lucide `rotate-cw` — reload. */\nexport function RotateCwIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"rotate-cw\", props)}>\n <path d=\"M21 12a9 9 0 1 1-9-9c2.52 0 4.93 1 6.74 2.74L21 8\" />\n <path d=\"M21 3v5h-5\" />\n </svg>\n );\n}\n\n/** lucide `globe` — a web page with no favicon. */\nexport function GlobeIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"globe\", props)}>\n <circle cx=\"12\" cy=\"12\" r=\"10\" />\n <path d=\"M12 2a14.5 14.5 0 0 0 0 20 14.5 14.5 0 0 0 0-20\" />\n <path d=\"M2 12h20\" />\n </svg>\n );\n}\n\n/** lucide `calendar` — the date field's glyph. */\nexport function CalendarIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"calendar\", props)}>\n <path d=\"M8 2v4\" />\n <path d=\"M16 2v4\" />\n <rect width=\"18\" height=\"18\" x=\"3\" y=\"4\" rx=\"2\" />\n <path d=\"M3 10h18\" />\n </svg>\n );\n}\n\n/** lucide `clock` — the time field's glyph. */\nexport function ClockIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"clock\", props)}>\n <circle cx=\"12\" cy=\"12\" r=\"10\" />\n <polyline points=\"12 6 12 12 16 14\" />\n </svg>\n );\n}\n\n/** lucide `refresh-cw` — retry / reload. */\nexport function RefreshCwIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"refresh-cw\", props)}>\n <path d=\"M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8\" />\n <path d=\"M21 3v5h-5\" />\n <path d=\"M21 12a9 9 0 0 1-9 9 9.75 9.75 0 0 1-6.74-2.74L3 16\" />\n <path d=\"M8 16H3v5\" />\n </svg>\n );\n}\n\n/** lucide `triangle-alert` (alias `AlertTriangle`) — an error or warning. */\nexport function AlertTriangleIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"triangle-alert\", props)}>\n <path d=\"m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3\" />\n <path d=\"M12 9v4\" />\n <path d=\"M12 17h.01\" />\n </svg>\n );\n}\n\n/** lucide `circle-check` — a passing state. */\nexport function CircleCheckIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"circle-check\", props)}>\n <circle cx=\"12\" cy=\"12\" r=\"10\" />\n <path d=\"m16 9-5.5 5.5L8 12\" />\n </svg>\n );\n}\n\n/** lucide `circle-question-mark` (alias `CircleHelp`) — field help. */\nexport function CircleHelpIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"circle-question-mark\", props)}>\n <circle cx=\"12\" cy=\"12\" r=\"10\" />\n <path d=\"M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3\" />\n <path d=\"M12 17h.01\" />\n </svg>\n );\n}\n\n/** lucide `circle-x` — a failing state. */\nexport function CircleXIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"circle-x\", props)}>\n <circle cx=\"12\" cy=\"12\" r=\"10\" />\n <path d=\"m15 9-6 6\" />\n <path d=\"m9 9 6 6\" />\n </svg>\n );\n}\n\n/** lucide `info` — a row label's help glyph (controls `PropertyRow`). */\nexport function InfoIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"info\", props)}>\n <circle cx=\"12\" cy=\"12\" r=\"10\" />\n <path d=\"M12 16v-4\" />\n <path d=\"M12 8h.01\" />\n </svg>\n );\n}\n\n/** lucide `circle-dot` — the \"Get help from Matrx AI\" button glyph (controls `HelpIcon`). */\nexport function CircleDotIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"circle-dot\", props)}>\n <circle cx=\"12\" cy=\"12\" r=\"10\" />\n <circle cx=\"12\" cy=\"12\" r=\"1\" />\n </svg>\n );\n}\n\n/** lucide `copy` — the Peek's token chip (copy the exact token). */\nexport function CopyIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"copy\", props)}>\n <rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\" />\n <path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\" />\n </svg>\n );\n}\n\n/** lucide `upload` (moved from @ai-matrx/media). */\nexport function UploadIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"upload\", props)}>\n <path d=\"M12 3v12\" />\n <path d=\"m17 8-5-5-5 5\" />\n <path d=\"M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4\" />\n </svg>\n );\n}\n\n/** lucide `circle-alert` — an error or attention state. */\nexport function CircleAlertIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"circle-alert\", props)}>\n <circle cx=\"12\" cy=\"12\" r=\"10\" />\n <line x1=\"12\" x2=\"12\" y1=\"8\" y2=\"12\" />\n <line x1=\"12\" x2=\"12.01\" y1=\"16\" y2=\"16\" />\n </svg>\n );\n}\n\n/** lucide `panel-right` — a side pane toggle. */\nexport function PanelRightIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"panel-right\", props)}>\n <rect width=\"18\" height=\"18\" x=\"3\" y=\"3\" rx=\"2\" />\n <path d=\"M15 3v18\" />\n </svg>\n );\n}\n\n/** lucide `bell` — notifications. */\nexport function BellIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"bell\", props)}>\n <path d=\"M10.268 21a2 2 0 0 0 3.464 0\" />\n <path d=\"M3.262 15.326A1 1 0 0 0 4 17h16a1 1 0 0 0 .74-1.673C19.41 13.956 18 12.499 18 8A6 6 0 0 0 6 8c0 4.499-1.411 5.956-2.738 7.326\" />\n </svg>\n );\n}\n\n/** lucide `eye-off` — hidden. */\nexport function EyeOffIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"eye-off\", props)}>\n <path d=\"M10.733 5.076a10.744 10.744 0 0 1 11.205 6.575 1 1 0 0 1 0 .696 10.747 10.747 0 0 1-1.444 2.49\" />\n <path d=\"M14.084 14.158a3 3 0 0 1-4.242-4.242\" />\n <path d=\"M17.479 17.499a10.75 10.75 0 0 1-15.417-5.151 1 1 0 0 1 0-.696 10.75 10.75 0 0 1 4.446-5.143\" />\n <path d=\"m2 2 20 20\" />\n </svg>\n );\n}\n\n/** lucide `app-window` — open as a window. */\nexport function AppWindowIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"app-window\", props)}>\n <rect x=\"2\" y=\"4\" width=\"20\" height=\"16\" rx=\"2\" />\n <path d=\"M10 4v4\" />\n <path d=\"M2 8h20\" />\n <path d=\"M6 4v4\" />\n </svg>\n );\n}\n\n/** lucide `video` — a video call or clip. */\nexport function VideoIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"video\", props)}>\n <path d=\"m16 13 5.223 3.482a.5.5 0 0 0 .777-.416V7.87a.5.5 0 0 0-.752-.432L16 10.5\" />\n <rect x=\"2\" y=\"6\" width=\"14\" height=\"12\" rx=\"2\" />\n </svg>\n );\n}\n\n/** lucide `phone` — a voice call. */\nexport function PhoneIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"phone\", props)}>\n <path d=\"M13.832 16.568a1 1 0 0 0 1.213-.303l.355-.465A2 2 0 0 1 17 15h3a2 2 0 0 1 2 2v3a2 2 0 0 1-2 2A18 18 0 0 1 2 4a2 2 0 0 1 2-2h3a2 2 0 0 1 2 2v3a2 2 0 0 1-.8 1.6l-.468.351a1 1 0 0 0-.292 1.233 14 14 0 0 0 6.392 6.384\" />\n </svg>\n );\n}\n\n/** lucide `sparkles` — AI. */\nexport function SparklesIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"sparkles\", props)}>\n <path d=\"M11.017 2.814a1 1 0 0 1 1.966 0l1.051 5.558a2 2 0 0 0 1.594 1.594l5.558 1.051a1 1 0 0 1 0 1.966l-5.558 1.051a2 2 0 0 0-1.594 1.594l-1.051 5.558a1 1 0 0 1-1.966 0l-1.051-5.558a2 2 0 0 0-1.594-1.594l-5.558-1.051a1 1 0 0 1 0-1.966l5.558-1.051a2 2 0 0 0 1.594-1.594z\" />\n <path d=\"M20 2v4\" />\n <path d=\"M22 4h-4\" />\n <circle cx=\"4\" cy=\"20\" r=\"2\" />\n </svg>\n );\n}\n\n/** lucide `panels-top-left` — a layout. */\nexport function PanelsTopLeftIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"panels-top-left\", props)}>\n <rect width=\"18\" height=\"18\" x=\"3\" y=\"3\" rx=\"2\" />\n <path d=\"M3 9h18\" />\n <path d=\"M9 21V9\" />\n </svg>\n );\n}\n\n/** lucide `download`. */\nexport function DownloadIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"download\", props)}>\n <path d=\"M12 15V3\" />\n <path d=\"M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4\" />\n <path d=\"m7 10 5 5 5-5\" />\n </svg>\n );\n}\n\n/** lucide `settings`. */\nexport function SettingsIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"settings\", props)}>\n <path d=\"M9.671 4.136a2.34 2.34 0 0 1 4.659 0 2.34 2.34 0 0 0 3.319 1.915 2.34 2.34 0 0 1 2.33 4.033 2.34 2.34 0 0 0 0 3.831 2.34 2.34 0 0 1-2.33 4.033 2.34 2.34 0 0 0-3.319 1.915 2.34 2.34 0 0 1-4.659 0 2.34 2.34 0 0 0-3.32-1.915 2.34 2.34 0 0 1-2.33-4.033 2.34 2.34 0 0 0 0-3.831A2.34 2.34 0 0 1 6.35 6.051a2.34 2.34 0 0 0 3.319-1.915\" />\n <circle cx=\"12\" cy=\"12\" r=\"3\" />\n </svg>\n );\n}\n\n/** lucide `users`. */\nexport function UsersIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"users\", props)}>\n <path d=\"M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2\" />\n <path d=\"M16 3.128a4 4 0 0 1 0 7.744\" />\n <path d=\"M22 21v-2a4 4 0 0 0-3-3.87\" />\n <circle cx=\"9\" cy=\"7\" r=\"4\" />\n </svg>\n );\n}\n\n/** lucide `grip-vertical` — a drag handle. */\nexport function GripVerticalIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"grip-vertical\", props)}>\n <circle cx=\"9\" cy=\"12\" r=\"1\" />\n <circle cx=\"9\" cy=\"5\" r=\"1\" />\n <circle cx=\"9\" cy=\"19\" r=\"1\" />\n <circle cx=\"15\" cy=\"12\" r=\"1\" />\n <circle cx=\"15\" cy=\"5\" r=\"1\" />\n <circle cx=\"15\" cy=\"19\" r=\"1\" />\n </svg>\n );\n}\n\n/** lucide `history`. */\nexport function HistoryIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"history\", props)}>\n <path d=\"M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8\" />\n <path d=\"M3 3v5h5\" />\n <path d=\"M12 7v5l4 2\" />\n </svg>\n );\n}\n\n/** lucide `workflow`. */\nexport function WorkflowIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"workflow\", props)}>\n <rect width=\"8\" height=\"8\" x=\"3\" y=\"3\" rx=\"2\" />\n <path d=\"M7 11v4a2 2 0 0 0 2 2h4\" />\n <rect width=\"8\" height=\"8\" x=\"13\" y=\"13\" rx=\"2\" />\n </svg>\n );\n}\n\n// ---- Glyphs consolidated from the packages above the design system (one glyph home). ----\n\n/** lucide `activities` (moved from @ai-matrx/meet). */\nexport function ActivitiesIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"activities\", props)}>\n <path d=\"M8.3 10a.7.7 0 0 1-.626-1.079L11.4 3a.7.7 0 0 1 1.198-.043L16.3 8.9a.7.7 0 0 1-.572 1.1Z\" />\n <rect x=\"3\" y=\"14\" width=\"7\" height=\"7\" rx=\"1\" />\n <circle cx=\"17.5\" cy=\"17.5\" r=\"3.5\" />\n </svg>\n );\n}\n\n/** lucide `arrow-down-to-line` (moved from @ai-matrx/agents). */\nexport function ArrowDownToLineIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"arrow-down-to-line\", props)}>\n <path d=\"M12 17V3\" />\n <path d=\"m6 11 6 6 6-6\" />\n <path d=\"M19 21H5\" />\n </svg>\n );\n}\n\n/** lucide `arrow-left-right` (moved from @ai-matrx/diff). */\nexport function ArrowLeftRightIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"arrow-left-right\", props)}>\n <path d=\"M8 3 4 7l4 4\" />\n <path d=\"M4 7h16\" />\n <path d=\"m16 21 4-4-4-4\" />\n <path d=\"M20 17H4\" />\n </svg>\n );\n}\n\n/** lucide `arrow-left-to-line` (moved from @ai-matrx/summon). */\nexport function ArrowLeftToLineIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"arrow-left-to-line\", props)}>\n <path d=\"M3 19V5\" />\n <path d=\"m13 6-6 6 6 6\" />\n <path d=\"M7 12h14\" />\n </svg>\n );\n}\n\n/** lucide `atom` (moved from @ai-matrx/agents). */\nexport function AtomIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"atom\", props)}>\n <circle cx=\"12\" cy=\"12\" r=\"1\" />\n <path d=\"M20.2 20.2c2.04-2.03.02-7.36-4.5-11.9-4.54-4.52-9.87-6.54-11.9-4.5-2.04 2.03-.02 7.36 4.5 11.9 4.54 4.52 9.87 6.54 11.9 4.5Z\" />\n <path d=\"M15.7 15.7c4.52-4.54 6.54-9.87 4.5-11.9-2.03-2.04-7.36-.02-11.9 4.5-4.52 4.54-6.54 9.87-4.5 11.9 2.03 2.04 7.36.02 11.9-4.5Z\" />\n </svg>\n );\n}\n\n/** lucide `audio-lines` (moved from @ai-matrx/content-ir). */\nexport function AudioLinesIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"audio-lines\", props)}>\n <path d=\"M2 10v3\" />\n <path d=\"M6 6v11\" />\n <path d=\"M10 3v18\" />\n <path d=\"M14 8v7\" />\n <path d=\"M18 5v13\" />\n <path d=\"M22 10v3\" />\n </svg>\n );\n}\n\n/** lucide `boxes` (moved from @ai-matrx/associations). */\nexport function BoxesIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"boxes\", props)}>\n <path d=\"M2.97 12.92A2 2 0 0 0 2 14.63v3.24a2 2 0 0 0 .97 1.71l3 1.8a2 2 0 0 0 2.06 0L12 19v-5.5l-5-3-4.03 2.42Z\" />\n <path d=\"m7 16.5-4.74-2.85\" />\n <path d=\"m7 16.5 5-3\" />\n <path d=\"M7 16.5v5.17\" />\n <path d=\"M12 13.5V19l3.97 2.38a2 2 0 0 0 2.06 0l3-1.8a2 2 0 0 0 .97-1.71v-3.24a2 2 0 0 0-.97-1.71L17 10.5l-5 3Z\" />\n <path d=\"m17 16.5-5-3\" />\n <path d=\"m17 16.5 4.74-2.85\" />\n <path d=\"M17 16.5v5.17\" />\n <path d=\"M7.97 4.42A2 2 0 0 0 7 6.13v4.37l5 3 5-3V6.13a2 2 0 0 0-.97-1.71l-3-1.8a2 2 0 0 0-2.06 0l-3 1.8Z\" />\n <path d=\"M12 8 7.26 5.15\" />\n <path d=\"m12 8 4.74-2.85\" />\n <path d=\"M12 13.5V8\" />\n </svg>\n );\n}\n\n/** lucide `braces` (moved from @ai-matrx/media). */\nexport function BracesIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"braces\", props)}>\n <path d=\"M8 3H7a2 2 0 0 0-2 2v5a2 2 0 0 1-2 2 2 2 0 0 1 2 2v5c0 1.1.9 2 2 2h1\" />\n <path d=\"M16 21h1a2 2 0 0 0 2-2v-5c0-1.1.9-2 2-2a2 2 0 0 1-2-2V5a2 2 0 0 0-2-2h-1\" />\n </svg>\n );\n}\n\n/** lucide `breakout` (moved from @ai-matrx/meet). */\nexport function BreakoutIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"breakout\", props)}>\n <rect width=\"7\" height=\"18\" x=\"3\" y=\"3\" rx=\"1\" />\n <rect width=\"7\" height=\"7\" x=\"14\" y=\"3\" rx=\"1\" />\n <rect width=\"7\" height=\"7\" x=\"14\" y=\"14\" rx=\"1\" />\n </svg>\n );\n}\n\n/** lucide `camera` (moved from @ai-matrx/meet). */\nexport function CameraIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"camera\", props)}>\n <path d=\"m23 7-7 5 7 5V7Z\" />\n <rect x=\"1\" y=\"5\" width=\"15\" height=\"14\" rx=\"2\" />\n </svg>\n );\n}\n\n/** lucide `camera-off` (moved from @ai-matrx/meet). */\nexport function CameraOffIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"camera-off\", props)}>\n <path d=\"M2 2l20 20\" />\n <path d=\"M10.66 5H14a2 2 0 0 1 2 2v3.34l1 1L23 7v10\" />\n <path d=\"M16 16a2 2 0 0 1-2 2H3a2 2 0 0 1-2-2V7a2 2 0 0 1 2-2h2\" />\n </svg>\n );\n}\n\n/** lucide `captions` (moved from @ai-matrx/meet). */\nexport function CaptionsIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"captions\", props)}>\n <rect x=\"3\" y=\"5\" width=\"18\" height=\"14\" rx=\"2\" />\n <path d=\"M10 10.5a2 2 0 1 0 0 3M16 10.5a2 2 0 1 0 0 3\" />\n </svg>\n );\n}\n\n/** lucide `chat-bubble` (moved from @ai-matrx/coding-sessions). */\nexport function ChatBubbleIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"chat-bubble\", props)}>\n <path d=\"M20 12.5a7.5 7.5 0 0 1-10.9 6.7L4 20.5l1.3-4.6A7.5 7.5 0 1 1 20 12.5z\" />\n </svg>\n );\n}\n\n/** lucide `chat` (moved from @ai-matrx/meet). */\nexport function ChatIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"chat\", props)}>\n <path d=\"M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2Z\" />\n </svg>\n );\n}\n\n/** lucide `check-circle-2` (moved from @ai-matrx/media). */\nexport function CheckCircle2Icon(props: IconProps) {\n return (\n <svg {...lucideProps(\"check-circle-2\", props)}>\n <path d=\"M21.801 10A10 10 0 1 1 17 3.335\" />\n <path d=\"m9 11 3 3L22 4\" />\n </svg>\n );\n}\n\n/** lucide `chevron-up` (moved from @ai-matrx/meet). */\nexport function ChevronUpIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"chevron-up\", props)}>\n <path d=\"m6 15 6-6 6 6\" />\n </svg>\n );\n}\n\n/** lucide `chevrons-down-up` (moved from @ai-matrx/diff). */\nexport function ChevronsDownUpIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"chevrons-down-up\", props)}>\n <path d=\"m7 20 5-5 5 5\" />\n <path d=\"m7 4 5 5 5-5\" />\n </svg>\n );\n}\n\n/** lucide `clock-3` (moved from @ai-matrx/diff). */\nexport function Clock3Icon(props: IconProps) {\n return (\n <svg {...lucideProps(\"clock-3\", props)}>\n <circle cx=\"12\" cy=\"12\" r=\"10\" />\n <path d=\"M12 6v6h4\" />\n </svg>\n );\n}\n\n/** lucide `code-2` (moved from @ai-matrx/office). */\nexport function Code2Icon(props: IconProps) {\n return (\n <svg {...lucideProps(\"code-2\", props)}>\n <path d=\"m18 16 4-4-4-4\" />\n <path d=\"m6 8-4 4 4 4\" />\n <path d=\"m14.5 4-5 16\" />\n </svg>\n );\n}\n\n/** lucide `code` (moved from @ai-matrx/media). */\nexport function CodeIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"code\", props)}>\n <path d=\"m16 18 6-6-6-6\" />\n <path d=\"m8 6-6 6 6 6\" />\n </svg>\n );\n}\n\n/** lucide `columns-2` (moved from @ai-matrx/diff). */\nexport function Columns2Icon(props: IconProps) {\n return (\n <svg {...lucideProps(\"columns-2\", props)}>\n <rect width=\"18\" height=\"18\" x=\"3\" y=\"3\" rx=\"2\" />\n <path d=\"M12 3v18\" />\n </svg>\n );\n}\n\n/** lucide `corner-down-right` (moved from @ai-matrx/associations). */\nexport function CornerDownRightIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"corner-down-right\", props)}>\n <polyline points=\"15 10 20 15 15 20\" />\n <path d=\"M4 4v7a4 4 0 0 0 4 4h12\" />\n </svg>\n );\n}\n\n/** lucide `database` (moved from @ai-matrx/media). */\nexport function DatabaseIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"database\", props)}>\n <ellipse cx=\"12\" cy=\"5\" rx=\"9\" ry=\"3\" />\n <path d=\"M3 5V19A9 3 0 0 0 21 19V5\" />\n <path d=\"M3 12A9 3 0 0 0 21 12\" />\n </svg>\n );\n}\n\n/** lucide `dock` (moved from @ai-matrx/canvas). */\nexport function DockIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"dock\", props)}>\n <path d=\"M21 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h6\" />\n <path d=\"M21 3 12 12\" />\n <path d=\"M12 6v6h6\" />\n </svg>\n );\n}\n\n/** lucide `expand` (moved from @ai-matrx/detail). */\nexport function ExpandIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"expand\", props)}>\n <path d=\"m15 15 6 6\" />\n <path d=\"m15 9 6-6\" />\n <path d=\"M21 16v5h-5\" />\n <path d=\"M21 8V3h-5\" />\n <path d=\"M3 16v5h5\" />\n <path d=\"m3 21 6-6\" />\n <path d=\"M3 8V3h5\" />\n <path d=\"M9 9 3 3\" />\n </svg>\n );\n}\n\n/** lucide `eye` (moved from @ai-matrx/agents). */\nexport function EyeIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"eye\", props)}>\n <path d=\"M2.062 12.348a1 1 0 0 1 0-.696 10.75 10.75 0 0 1 19.876 0 1 1 0 0 1 0 .696 10.75 10.75 0 0 1-19.876 0\" />\n <circle cx=\"12\" cy=\"12\" r=\"3\" />\n </svg>\n );\n}\n\n/** lucide `file-archive` (moved from @ai-matrx/content-ir). */\nexport function FileArchiveIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"file-archive\", props)}>\n <path d=\"M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z\" />\n <path d=\"M14 2v5a1 1 0 0 0 1 1h5\" />\n <path d=\"M10 6h1\" />\n <path d=\"M10 10h1\" />\n <circle cx=\"10\" cy=\"16\" r=\"2\" />\n <path d=\"M10 2v12\" />\n </svg>\n );\n}\n\n/** lucide `file-audio` (moved from @ai-matrx/media). */\nexport function FileAudioIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"file-audio\", props)}>\n <path d=\"M4 6.835V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.706.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2h-.343\" />\n <path d=\"M14 2v5a1 1 0 0 0 1 1h5\" />\n <path d=\"M2 19a2 2 0 0 1 4 0v1a2 2 0 0 1-4 0v-4a6 6 0 0 1 12 0v4a2 2 0 0 1-4 0v-1a2 2 0 0 1 4 0\" />\n </svg>\n );\n}\n\n/** lucide `file-code` (moved from @ai-matrx/media). */\nexport function FileCodeIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"file-code\", props)}>\n <path d=\"M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z\" />\n <path d=\"M14 2v5a1 1 0 0 0 1 1h5\" />\n <path d=\"M10 12.5 8 15l2 2.5\" />\n <path d=\"m14 12.5 2 2.5-2 2.5\" />\n </svg>\n );\n}\n\n/** lucide `file-json` (moved from @ai-matrx/media). */\nexport function FileJsonIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"file-json\", props)}>\n <path d=\"M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z\" />\n <path d=\"M14 2v5a1 1 0 0 0 1 1h5\" />\n <path d=\"M10 12a1 1 0 0 0-1 1v1a1 1 0 0 1-1 1 1 1 0 0 1 1 1v1a1 1 0 0 0 1 1\" />\n <path d=\"M14 18a1 1 0 0 0 1-1v-1a1 1 0 0 1 1-1 1 1 0 0 1-1-1v-1a1 1 0 0 0-1-1\" />\n </svg>\n );\n}\n\n/** lucide `file` (moved from @ai-matrx/media). */\nexport function FilePageIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"file\", props)}>\n <path d=\"M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z\" />\n <path d=\"M14 2v5a1 1 0 0 0 1 1h5\" />\n </svg>\n );\n}\n\n/** lucide `file-plus` (moved from @ai-matrx/content-ir). */\nexport function FilePlusIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"file-plus\", props)}>\n <path d=\"M4 22h14a2 2 0 0 0 2-2V7l-5-5H6a2 2 0 0 0-2 2v4\" />\n <path d=\"M14 2v4a2 2 0 0 0 2 2h4\" />\n <path d=\"M3 15h6\" />\n <path d=\"M6 12v6\" />\n </svg>\n );\n}\n\n/** lucide `file-spreadsheet` (moved from @ai-matrx/media). */\nexport function FileSpreadsheetIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"file-spreadsheet\", props)}>\n <path d=\"M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z\" />\n <path d=\"M14 2v5a1 1 0 0 0 1 1h5\" />\n <path d=\"M8 13h2\" />\n <path d=\"M14 13h2\" />\n <path d=\"M8 17h2\" />\n <path d=\"M14 17h2\" />\n </svg>\n );\n}\n\n/** lucide `file-text` (moved from @ai-matrx/media). */\nexport function FileTextIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"file-text\", props)}>\n <path d=\"M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z\" />\n <path d=\"M14 2v5a1 1 0 0 0 1 1h5\" />\n <path d=\"M10 9H8\" />\n <path d=\"M16 13H8\" />\n <path d=\"M16 17H8\" />\n </svg>\n );\n}\n\n/** lucide `file-type` (moved from @ai-matrx/media). */\nexport function FileTypeIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"file-type\", props)}>\n <path d=\"M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z\" />\n <path d=\"M14 2v5a1 1 0 0 0 1 1h5\" />\n <path d=\"M11 18h2\" />\n <path d=\"M12 12v6\" />\n <path d=\"M9 13v-.5a.5.5 0 0 1 .5-.5h5a.5.5 0 0 1 .5.5v.5\" />\n </svg>\n );\n}\n\n/** lucide `file-video` (moved from @ai-matrx/media). */\nexport function FileVideoIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"file-video\", props)}>\n <path d=\"M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z\" />\n <path d=\"M14 2v5a1 1 0 0 0 1 1h5\" />\n <path d=\"M15.033 13.44a.647.647 0 0 1 0 1.12l-4.065 2.352a.645.645 0 0 1-.968-.56v-4.704a.645.645 0 0 1 .967-.56z\" />\n </svg>\n );\n}\n\n/** lucide `film` (moved from @ai-matrx/content-ir). */\nexport function FilmIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"film\", props)}>\n <rect width=\"18\" height=\"18\" x=\"3\" y=\"3\" rx=\"2\" />\n <path d=\"M7 3v18\" />\n <path d=\"M3 7.5h4\" />\n <path d=\"M3 12h18\" />\n <path d=\"M3 16.5h4\" />\n <path d=\"M17 3v18\" />\n <path d=\"M17 7.5h4\" />\n <path d=\"M17 16.5h4\" />\n </svg>\n );\n}\n\n/** lucide `flag` (moved from @ai-matrx/meet). */\nexport function FlagIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"flag\", props)}>\n <path d=\"M4 15s1-1 4-1 5 2 8 2 4-1 4-1V3s-1 1-4 1-5-2-8-2-4 1-4 1z\" />\n <line x1=\"4\" x2=\"4\" y1=\"22\" y2=\"15\" />\n </svg>\n );\n}\n\n/** lucide `flip-horizontal-2` (moved from @ai-matrx/capture). */\nexport function FlipHorizontal2Icon(props: IconProps) {\n return (\n <svg {...lucideProps(\"flip-horizontal-2\", props)}>\n <path d=\"m3 7 5 5-5 5V7\" />\n <path d=\"m21 7-5 5 5 5V7\" />\n <path d=\"M12 20v2\" />\n <path d=\"M12 14v2\" />\n <path d=\"M12 8v2\" />\n <path d=\"M12 2v2\" />\n </svg>\n );\n}\n\n/** lucide `fold-vertical` (moved from @ai-matrx/diff). */\nexport function FoldVerticalIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"fold-vertical\", props)}>\n <path d=\"M12 22v-6\" />\n <path d=\"M12 8V2\" />\n <path d=\"M4 12H2\" />\n <path d=\"M10 12H8\" />\n <path d=\"M16 12h-2\" />\n <path d=\"M22 12h-2\" />\n <path d=\"m15 19-3-3-3 3\" />\n <path d=\"m15 5-3 3-3-3\" />\n </svg>\n );\n}\n\n/** lucide `folder` (moved from @ai-matrx/media). */\nexport function FolderIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"folder\", props)}>\n <path d=\"M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z\" />\n </svg>\n );\n}\n\n/** lucide `folder-open` (moved from @ai-matrx/media). */\nexport function FolderOpenIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"folder-open\", props)}>\n <path d=\"m6 14 1.5-2.9A2 2 0 0 1 9.24 10H20a2 2 0 0 1 1.94 2.5l-1.54 6a2 2 0 0 1-1.95 1.5H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h3.9a2 2 0 0 1 1.69.9l.81 1.2a2 2 0 0 0 1.67.9H18a2 2 0 0 1 2 2v2\" />\n </svg>\n );\n}\n\n/** lucide `git-merge` (moved from @ai-matrx/diff). */\nexport function GitMergeIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"git-merge\", props)}>\n <circle cx=\"18\" cy=\"18\" r=\"3\" />\n <circle cx=\"6\" cy=\"6\" r=\"3\" />\n <path d=\"M6 21V9a9 9 0 0 0 9 9\" />\n </svg>\n );\n}\n\n/** lucide `graduation-cap` (moved from @ai-matrx/office). */\nexport function GraduationCapIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"graduation-cap\", props)}>\n <path d=\"M21.42 10.922a1 1 0 0 0-.019-1.838L12.83 5.18a2 2 0 0 0-1.66 0L2.6 9.08a1 1 0 0 0 0 1.832l8.57 3.908a2 2 0 0 0 1.66 0z\" />\n <path d=\"M22 10v6\" />\n <path d=\"M6 12.5V16a6 3 0 0 0 12 0v-3.5\" />\n </svg>\n );\n}\n\n/** lucide `grid-3x-3` (moved from @ai-matrx/capture). */\nexport function Grid3x3Icon(props: IconProps) {\n return (\n <svg {...lucideProps(\"grid-3x-3\", props)}>\n <rect width=\"18\" height=\"18\" x=\"3\" y=\"3\" rx=\"2\" />\n <path d=\"M3 9h18\" />\n <path d=\"M3 15h18\" />\n <path d=\"M9 3v18\" />\n <path d=\"M15 3v18\" />\n </svg>\n );\n}\n\n/** lucide `grip` (moved from @ai-matrx/capture). */\nexport function GripIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"grip\", props)}>\n <circle cx=\"12\" cy=\"5\" r=\"1\" />\n <circle cx=\"19\" cy=\"5\" r=\"1\" />\n <circle cx=\"5\" cy=\"5\" r=\"1\" />\n <circle cx=\"12\" cy=\"12\" r=\"1\" />\n <circle cx=\"19\" cy=\"12\" r=\"1\" />\n <circle cx=\"5\" cy=\"12\" r=\"1\" />\n <circle cx=\"12\" cy=\"19\" r=\"1\" />\n <circle cx=\"19\" cy=\"19\" r=\"1\" />\n <circle cx=\"5\" cy=\"19\" r=\"1\" />\n </svg>\n );\n}\n\n/** lucide `grip-resize` (moved from @ai-matrx/associations). */\nexport function GripResizeIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"grip-resize\", props)}>\n <path d=\"M21 15 15 21\" />\n <path d=\"M21 20 20 21\" />\n </svg>\n );\n}\n\n/** lucide `hammer` (moved from @ai-matrx/agents). */\nexport function HammerIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"hammer\", props)}>\n <path d=\"m15 12-8.5 8.5c-.83.83-2.17.83-3 0 0 0 0 0 0 0a2.12 2.12 0 0 1 0-3L12 9\" />\n <path d=\"M17.64 15 22 10.64\" />\n <path d=\"m20.91 11.7-1.25-1.25c-.6-.6-.93-1.4-.93-2.25v-.86L16.01 4.6a5.56 5.56 0 0 0-3.94-1.64H9l.92.82A6.18 6.18 0 0 1 12 8.4v1.56l2 2h2.47l2.26 1.91\" />\n </svg>\n );\n}\n\n/** lucide `hand` (moved from @ai-matrx/meet). */\nexport function HandIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"hand\", props)}>\n <path d=\"M18 11V6a2 2 0 0 0-4 0v5\" />\n <path d=\"M14 10V4a2 2 0 0 0-4 0v7\" />\n <path d=\"M10 10.5V6a2 2 0 0 0-4 0v8\" />\n <path d=\"M18 8a2 2 0 1 1 4 0v6a8 8 0 0 1-8 8h-2a8 8 0 0 1-8-8v-1a2 2 0 1 1 4 0\" />\n </svg>\n );\n}\n\n/** lucide `handoff` (moved from @ai-matrx/coding-sessions). */\nexport function HandoffIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"handoff\", props)}>\n <path d=\"M5 12h12M13 7l5 5-5 5\" />\n <path d=\"M5 5v14\" />\n </svg>\n );\n}\n\n/** lucide `hash` (moved from @ai-matrx/diff). */\nexport function HashIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"hash\", props)}>\n <path d=\"M4 9h16\" />\n <path d=\"M4 15h16\" />\n <path d=\"M10 3 8 21\" />\n <path d=\"M16 3l-2 18\" />\n </svg>\n );\n}\n\n/** lucide `highlighter` (moved from @ai-matrx/diff). */\nexport function HighlighterIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"highlighter\", props)}>\n <path d=\"m9 11-6 6v3h9l3-3\" />\n <path d=\"m22 12-4.6 4.6a2 2 0 0 1-2.8 0l-5.2-5.2a2 2 0 0 1 0-2.8L14 4\" />\n </svg>\n );\n}\n\n/** lucide `image` (moved from @ai-matrx/media). */\nexport function ImageIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"image\", props)}>\n <rect width=\"18\" height=\"18\" x=\"3\" y=\"3\" rx=\"2\" ry=\"2\" />\n <circle cx=\"9\" cy=\"9\" r=\"2\" />\n <path d=\"m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21\" />\n </svg>\n );\n}\n\n/** lucide `image-off` (moved from @ai-matrx/media). */\nexport function ImageOffIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"image-off\", props)}>\n <line x1=\"2\" x2=\"22\" y1=\"2\" y2=\"22\" />\n <path d=\"M10.41 10.41a2 2 0 1 1-2.83-2.83\" />\n <line x1=\"13.5\" x2=\"6\" y1=\"13.5\" y2=\"21\" />\n <line x1=\"18\" x2=\"21\" y1=\"12\" y2=\"15\" />\n <path d=\"M3.59 3.59A1.99 1.99 0 0 0 3 5v14a2 2 0 0 0 2 2h14c.55 0 1.052-.22 1.41-.59\" />\n <path d=\"M21 15V5a2 2 0 0 0-2-2H9\" />\n </svg>\n );\n}\n\n/** lucide `images` (moved from @ai-matrx/capture). */\nexport function ImagesIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"images\", props)}>\n <path d=\"m22 11-1.296-1.296a2.4 2.4 0 0 0-3.408 0L11 16\" />\n <path d=\"M4 8a2 2 0 0 0-2 2v10a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2\" />\n <circle cx=\"13\" cy=\"7\" r=\"1\" fill=\"currentColor\" />\n <rect x=\"8\" y=\"2\" width=\"14\" height=\"14\" rx=\"2\" />\n </svg>\n );\n}\n\n/** lucide `keyboard` (moved from @ai-matrx/meet). */\nexport function KeyboardIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"keyboard\", props)}>\n <path d=\"M10 8h.01M12 12h.01M14 8h.01M16 12h.01M18 8h.01M6 8h.01M7 16h10M8 12h.01\" />\n <rect width=\"20\" height=\"16\" x=\"2\" y=\"4\" rx=\"2\" />\n </svg>\n );\n}\n\n/** lucide `languages` (moved from @ai-matrx/agents). */\nexport function LanguagesIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"languages\", props)}>\n <path d=\"m5 8 6 6\" />\n <path d=\"m4 14 6-6 2-3\" />\n <path d=\"M2 5h12\" />\n <path d=\"M7 2h1\" />\n <path d=\"m22 22-5-10-5 10\" />\n <path d=\"M14 18h6\" />\n </svg>\n );\n}\n\n/** lucide `layers` (moved from @ai-matrx/agents). */\nexport function LayersIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"layers\", props)}>\n <path d=\"M12.83 2.18a2 2 0 0 0-1.66 0L2.6 6.08a1 1 0 0 0 0 1.83l8.58 3.91a2 2 0 0 0 1.66 0l8.58-3.9a1 1 0 0 0 0-1.83z\" />\n <path d=\"M2 12a1 1 0 0 0 .58.91l8.6 3.91a2 2 0 0 0 1.65 0l8.58-3.9A1 1 0 0 0 22 12\" />\n <path d=\"M2 17a1 1 0 0 0 .58.91l8.6 3.91a2 2 0 0 0 1.65 0l8.58-3.9A1 1 0 0 0 22 17\" />\n </svg>\n );\n}\n\n/** lucide `layout-grid` (moved from @ai-matrx/canvas). */\nexport function LayoutGridIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"layout-grid\", props)}>\n <rect width=\"7\" height=\"7\" x=\"3\" y=\"3\" rx=\"1\" />\n <rect width=\"7\" height=\"7\" x=\"14\" y=\"3\" rx=\"1\" />\n <rect width=\"7\" height=\"7\" x=\"14\" y=\"14\" rx=\"1\" />\n <rect width=\"7\" height=\"7\" x=\"3\" y=\"14\" rx=\"1\" />\n </svg>\n );\n}\n\n/** lucide `link-2` (moved from @ai-matrx/media). */\nexport function Link2Icon(props: IconProps) {\n return (\n <svg {...lucideProps(\"link-2\", props)}>\n <path d=\"M9 17H7A5 5 0 0 1 7 7h2\" />\n <path d=\"M15 7h2a5 5 0 1 1 0 10h-2\" />\n <line x1=\"8\" x2=\"16\" y1=\"12\" y2=\"12\" />\n </svg>\n );\n}\n\n/** lucide `list-checks` (moved from @ai-matrx/diff). */\nexport function ListChecksIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"list-checks\", props)}>\n <path d=\"m3 17 2 2 4-4\" />\n <path d=\"m3 7 2 2 4-4\" />\n <path d=\"M13 6h8\" />\n <path d=\"M13 12h8\" />\n <path d=\"M13 18h8\" />\n </svg>\n );\n}\n\n/** lucide `list` (moved from @ai-matrx/diff). */\nexport function ListIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"list\", props)}>\n <path d=\"M3 12h.01\" />\n <path d=\"M3 18h.01\" />\n <path d=\"M3 6h.01\" />\n <path d=\"M8 12h13\" />\n <path d=\"M8 18h13\" />\n <path d=\"M8 6h13\" />\n </svg>\n );\n}\n\n/** lucide `maximize` (moved from @ai-matrx/content-ir). */\nexport function MaximizeIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"maximize\", props)}>\n <polyline points=\"15 3 21 3 21 9\" />\n <polyline points=\"9 21 3 21 3 15\" />\n <line x1=\"21\" x2=\"14\" y1=\"3\" y2=\"10\" />\n <line x1=\"3\" x2=\"10\" y1=\"21\" y2=\"14\" />\n </svg>\n );\n}\n\n/** lucide `megaphone` (moved from @ai-matrx/office). */\nexport function MegaphoneIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"megaphone\", props)}>\n <path d=\"M11 6a13 13 0 0 0 8.4-2.8A1 1 0 0 1 21 4v12a1 1 0 0 1-1.6.8A13 13 0 0 0 11 14H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2z\" />\n <path d=\"M6 14a12 12 0 0 0 2.4 7.2 2 2 0 0 0 3.2-2.4A8 8 0 0 1 10 14\" />\n <path d=\"M8 6v8\" />\n </svg>\n );\n}\n\n/** lucide `message-square-warning` (moved from @ai-matrx/office). */\nexport function MessageSquareWarningIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"message-square-warning\", props)}>\n <path d=\"M22 17a2 2 0 0 1-2 2H6.828a2 2 0 0 0-1.414.586l-2.202 2.202A.71.71 0 0 1 2 21.286V5a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2z\" />\n <path d=\"M12 15h.01\" />\n <path d=\"M12 7v4\" />\n </svg>\n );\n}\n\n/** lucide `mic` (moved from @ai-matrx/meet). */\nexport function MicIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"mic\", props)}>\n <path d=\"M12 2a3 3 0 0 0-3 3v7a3 3 0 0 0 6 0V5a3 3 0 0 0-3-3Z\" />\n <path d=\"M19 10v2a7 7 0 0 1-14 0v-2\" />\n <path d=\"M12 19v3\" />\n </svg>\n );\n}\n\n/** lucide `mic-off` (moved from @ai-matrx/meet). */\nexport function MicOffIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"mic-off\", props)}>\n <path d=\"M2 2l20 20\" />\n <path d=\"M9 9v3a3 3 0 0 0 5.12 2.12\" />\n <path d=\"M15 9.34V5a3 3 0 0 0-5.94-.6\" />\n <path d=\"M19 10v2a7 7 0 0 1-.11 1.23M5 10v2a7 7 0 0 0 11 5.66\" />\n <path d=\"M12 19v3\" />\n </svg>\n );\n}\n\n/** lucide `monitor` (moved from @ai-matrx/coding-sessions). */\nexport function MonitorIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"monitor\", props)}>\n <rect x=\"3\" y=\"4.5\" width=\"18\" height=\"12\" rx=\"2\" />\n <path d=\"M8.5 20h7M12 16.5V20\" />\n </svg>\n );\n}\n\n/** lucide `moon` (moved from @ai-matrx/coding-sessions). */\nexport function MoonIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"moon\", props)}>\n <path d=\"M20 14.5A8 8 0 0 1 9.5 4a8 8 0 1 0 10.5 10.5z\" />\n </svg>\n );\n}\n\n/** lucide `music` (moved from @ai-matrx/media). */\nexport function MusicIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"music\", props)}>\n <path d=\"M9 18V5l12-2v13\" />\n <circle cx=\"6\" cy=\"18\" r=\"3\" />\n <circle cx=\"18\" cy=\"16\" r=\"3\" />\n </svg>\n );\n}\n\n/** lucide `notes` (moved from @ai-matrx/meet). */\nexport function NotesIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"notes\", props)}>\n <path d=\"M4 20l1-4L16.5 4.5a2.1 2.1 0 0 1 3 3L8 19l-4 1Z\" />\n <path d=\"M14 7l3 3\" />\n </svg>\n );\n}\n\n/** lucide `package-box` (moved from @ai-matrx/media). */\nexport function PackageBoxIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"package-box\", props)}>\n <path d=\"M11 21.73a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73z\" />\n <path d=\"M12 22V12\" />\n <polyline points=\"3.29 7 12 12 20.71 7\" />\n <path d=\"m7.5 4.27 9 5.15\" />\n </svg>\n );\n}\n\n/** lucide `page` (moved from @ai-matrx/canvas). */\nexport function PageIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"page\", props)}>\n <rect x=\"4\" y=\"4\" width=\"16\" height=\"16\" rx=\"2\" />\n <path d=\"M8 9h8\" />\n <path d=\"M8 13h8\" />\n <path d=\"M8 17h5\" />\n </svg>\n );\n}\n\n/** lucide `panel-left-close` (moved from @ai-matrx/summon). */\nexport function PanelLeftCloseIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"panel-left-close\", props)}>\n <rect width=\"18\" height=\"18\" x=\"3\" y=\"3\" rx=\"2\" />\n <path d=\"M9 3v18\" />\n <path d=\"m16 15-3-3 3-3\" />\n </svg>\n );\n}\n\n/** lucide `pause` (moved from @ai-matrx/media). */\nexport function PauseIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"pause\", props)}>\n <rect x=\"14\" y=\"3\" width=\"5\" height=\"18\" rx=\"1\" />\n <rect x=\"5\" y=\"3\" width=\"5\" height=\"18\" rx=\"1\" />\n </svg>\n );\n}\n\n/** lucide `pen-tool` (moved from @ai-matrx/media). */\nexport function PenToolIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"pen-tool\", props)}>\n <path d=\"M15.707 21.293a1 1 0 0 1-1.414 0l-1.586-1.586a1 1 0 0 1 0-1.414l5.586-5.586a1 1 0 0 1 1.414 0l1.586 1.586a1 1 0 0 1 0 1.414z\" />\n <path d=\"m18 13-1.375-6.874a1 1 0 0 0-.746-.776L3.235 2.028a1 1 0 0 0-1.207 1.207L5.35 15.879a1 1 0 0 0 .776.746L13 18\" />\n <path d=\"m2.3 2.3 7.286 7.286\" />\n <circle cx=\"11\" cy=\"11\" r=\"2\" />\n </svg>\n );\n}\n\n/** lucide `people` (moved from @ai-matrx/meet). */\nexport function PeopleIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"people\", props)}>\n <path d=\"M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2\" />\n <circle cx=\"9\" cy=\"7\" r=\"4\" />\n <path d=\"M22 21v-2a4 4 0 0 0-3-3.87M16 3.13a4 4 0 0 1 0 7.75\" />\n </svg>\n );\n}\n\n/** lucide `phone-off` (moved from @ai-matrx/meet). */\nexport function PhoneOffIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"phone-off\", props)}>\n <path d=\"M12 9c-1.6 0-3.15.25-4.6.72v3.1c0 .39-.23.74-.56.9-.98.49-1.87 1.12-2.66 1.85-.18.18-.43.28-.7.28-.28 0-.53-.11-.71-.29L.29 13.08a.99.99 0 0 1-.29-.7c0-.28.11-.53.29-.71C3.34 8.78 7.46 7 12 7s8.66 1.78 11.71 4.67c.18.18.29.43.29.71 0 .28-.11.53-.29.71l-2.48 2.48c-.18.18-.43.29-.71.29-.27 0-.52-.11-.7-.28a11.27 11.27 0 0 0-2.67-1.85.996.996 0 0 1-.56-.9v-3.1C15.15 9.25 13.6 9 12 9Z\" fill=\"currentColor\" stroke=\"none\" />\n </svg>\n );\n}\n\n/** lucide `play` (moved from @ai-matrx/media). */\nexport function PlayIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"play\", props)}>\n <path d=\"M5 5a2 2 0 0 1 3.008-1.728l11.997 6.998a2 2 0 0 1 .003 3.458l-12 7A2 2 0 0 1 5 19z\" />\n </svg>\n );\n}\n\n/** lucide `poll` (moved from @ai-matrx/meet). */\nexport function PollIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"poll\", props)}>\n <line x1=\"18\" x2=\"18\" y1=\"20\" y2=\"10\" />\n <line x1=\"12\" x2=\"12\" y1=\"20\" y2=\"4\" />\n <line x1=\"6\" x2=\"6\" y1=\"20\" y2=\"14\" />\n </svg>\n );\n}\n\n/** lucide `proportions` (moved from @ai-matrx/capture). */\nexport function ProportionsIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"proportions\", props)}>\n <rect width=\"20\" height=\"16\" x=\"2\" y=\"4\" rx=\"2\" />\n <path d=\"M12 9v11\" />\n <path d=\"M2 9h13a2 2 0 0 1 2 2v9\" />\n </svg>\n );\n}\n\n/** lucide `puzzle` (moved from @ai-matrx/office). */\nexport function PuzzleIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"puzzle\", props)}>\n <path d=\"M15.39 4.39a1 1 0 0 0 1.68-.474 2.5 2.5 0 1 1 3.014 3.015 1 1 0 0 0-.474 1.68l1.683 1.682a2.414 2.414 0 0 1 0 3.414L19.61 15.39a1 1 0 0 1-1.68-.474 2.5 2.5 0 1 0-3.014 3.015 1 1 0 0 1 .474 1.68l-1.683 1.682a2.414 2.414 0 0 1-3.414 0L8.61 19.61a1 1 0 0 0-1.68.474 2.5 2.5 0 1 1-3.014-3.015 1 1 0 0 0 .474-1.68l-1.683-1.682a2.414 2.414 0 0 1 0-3.414L4.39 8.61a1 1 0 0 1 1.68.474 2.5 2.5 0 1 0 3.014-3.015 1 1 0 0 1-.474-1.68l1.683-1.682a2.414 2.414 0 0 1 3.414 0z\" />\n </svg>\n );\n}\n\n/** lucide `question` (moved from @ai-matrx/meet). */\nexport function QuestionIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"question\", props)}>\n <path d=\"M7.9 20A9 9 0 1 0 4 16.1L2 22Z\" />\n <path d=\"M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3\" />\n <path d=\"M12 17h.01\" />\n </svg>\n );\n}\n\n/** lucide `record` (moved from @ai-matrx/meet). */\nexport function RecordIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"record\", props)}>\n <circle cx=\"12\" cy=\"12\" r=\"8\" fill=\"currentColor\" stroke=\"none\" />\n </svg>\n );\n}\n\n/** lucide `rectangle-vertical` (moved from @ai-matrx/summon). */\nexport function RectangleVerticalIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"rectangle-vertical\", props)}>\n <rect width=\"12\" height=\"20\" x=\"6\" y=\"2\" rx=\"2\" />\n </svg>\n );\n}\n\n/** lucide `restore` (moved from @ai-matrx/associations). */\nexport function RestoreIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"restore\", props)}>\n <path d=\"M4 14h6v6\" />\n <path d=\"M20 10h-6V4\" />\n <path d=\"M14 10l7-7\" />\n <path d=\"M3 21l7-7\" />\n </svg>\n );\n}\n\n/** lucide `rotate-ccw` (moved from @ai-matrx/capture). */\nexport function RotateCcwIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"rotate-ccw\", props)}>\n <path d=\"M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8\" />\n <path d=\"M3 3v5h5\" />\n </svg>\n );\n}\n\n/** lucide `rows-3` (moved from @ai-matrx/diff). */\nexport function Rows3Icon(props: IconProps) {\n return (\n <svg {...lucideProps(\"rows-3\", props)}>\n <rect width=\"18\" height=\"18\" x=\"3\" y=\"3\" rx=\"2\" />\n <path d=\"M21 9H3\" />\n <path d=\"M21 15H3\" />\n </svg>\n );\n}\n\n/** lucide `save` (moved from @ai-matrx/summon). */\nexport function SaveIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"save\", props)}>\n <path d=\"M15.2 3a2 2 0 0 1 1.4.6l3.8 3.8a2 2 0 0 1 .6 1.4V19a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2z\" />\n <path d=\"M17 21v-7a1 1 0 0 0-1-1H8a1 1 0 0 0-1 1v7\" />\n <path d=\"M7 3v4a1 1 0 0 0 1 1h7\" />\n </svg>\n );\n}\n\n/** lucide `scale` (moved from @ai-matrx/agents). */\nexport function ScaleIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"scale\", props)}>\n <path d=\"M12 3v18\" />\n <path d=\"m19 8 3 8a5 5 0 0 1-6 0zV7\" />\n <path d=\"M3 7h1a17 17 0 0 0 8-2 17 17 0 0 0 8 2h1\" />\n <path d=\"m5 8 3 8a5 5 0 0 1-6 0zV7\" />\n <path d=\"M7 21h10\" />\n </svg>\n );\n}\n\n/** lucide `screen-share` (moved from @ai-matrx/meet). */\nexport function ScreenShareIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"screen-share\", props)}>\n <rect x=\"2\" y=\"3\" width=\"20\" height=\"14\" rx=\"2\" />\n <path d=\"M8 21h8M12 17v4\" />\n <path d=\"M12 13V8m0 0-2.5 2.5M12 8l2.5 2.5\" />\n </svg>\n );\n}\n\n/** lucide `server` (moved from @ai-matrx/agents). */\nexport function ServerIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"server\", props)}>\n <rect width=\"20\" height=\"8\" x=\"2\" y=\"2\" rx=\"2\" ry=\"2\" />\n <rect width=\"20\" height=\"8\" x=\"2\" y=\"14\" rx=\"2\" ry=\"2\" />\n <line x1=\"6\" x2=\"6.01\" y1=\"6\" y2=\"6\" />\n <line x1=\"6\" x2=\"6.01\" y1=\"18\" y2=\"18\" />\n </svg>\n );\n}\n\n/** lucide `settings-2` (moved from @ai-matrx/media). */\nexport function Settings2Icon(props: IconProps) {\n return (\n <svg {...lucideProps(\"settings-2\", props)}>\n <path d=\"M20 7h-9\" />\n <path d=\"M14 17H5\" />\n <circle cx=\"17\" cy=\"17\" r=\"3\" />\n <circle cx=\"7\" cy=\"7\" r=\"3\" />\n </svg>\n );\n}\n\n/** lucide `share-2` (moved from @ai-matrx/media). */\nexport function Share2Icon(props: IconProps) {\n return (\n <svg {...lucideProps(\"share-2\", props)}>\n <circle cx=\"18\" cy=\"5\" r=\"3\" />\n <circle cx=\"6\" cy=\"12\" r=\"3\" />\n <circle cx=\"18\" cy=\"19\" r=\"3\" />\n <line x1=\"8.59\" x2=\"15.42\" y1=\"13.51\" y2=\"17.49\" />\n <line x1=\"15.41\" x2=\"8.59\" y1=\"6.51\" y2=\"10.49\" />\n </svg>\n );\n}\n\n/** lucide `shield-alert` (moved from @ai-matrx/detail). */\nexport function ShieldAlertIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"shield-alert\", props)}>\n <path d=\"M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z\" />\n <path d=\"M12 8v4\" />\n <path d=\"M12 16h.01\" />\n </svg>\n );\n}\n\n/** lucide `shield-check` (moved from @ai-matrx/detail). */\nexport function ShieldCheckIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"shield-check\", props)}>\n <path d=\"M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z\" />\n <path d=\"m9 12 2 2 4-4\" />\n </svg>\n );\n}\n\n/** lucide `badge-check` — the verified mark. */\nexport function BadgeCheckIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"badge-check\", props)}>\n <path d=\"M3.85 8.62a4 4 0 0 1 4.78-4.77 4 4 0 0 1 6.74 0 4 4 0 0 1 4.78 4.78 4 4 0 0 1 0 6.74 4 4 0 0 1-4.77 4.78 4 4 0 0 1-6.75 0 4 4 0 0 1-4.78-4.77 4 4 0 0 1 0-6.76Z\" />\n <path d=\"m9 12 2 2 4-4\" />\n </svg>\n );\n}\n\n/** lucide `shield` (moved from @ai-matrx/agents). */\nexport function ShieldIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"shield\", props)}>\n <path d=\"M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z\" />\n </svg>\n );\n}\n\n/** lucide `sidebar` (moved from @ai-matrx/coding-sessions). */\nexport function SidebarIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"sidebar\", props)}>\n <rect x=\"3.5\" y=\"4.5\" width=\"17\" height=\"15\" rx=\"2.5\" />\n <path d=\"M9.5 4.5v15\" />\n </svg>\n );\n}\n\n/** lucide `sliders-horizontal` (moved from @ai-matrx/agents). */\nexport function SlidersHorizontalIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"sliders-horizontal\", props)}>\n <path d=\"M10 5H3\" />\n <path d=\"M12 19H3\" />\n <path d=\"M14 3v4\" />\n <path d=\"M16 17v4\" />\n <path d=\"M21 12h-9\" />\n <path d=\"M21 19h-5\" />\n <path d=\"M21 5h-7\" />\n <path d=\"M8 10v4\" />\n <path d=\"M8 12H3\" />\n </svg>\n );\n}\n\n/** lucide `smile` (moved from @ai-matrx/meet). */\nexport function SmileIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"smile\", props)}>\n <circle cx=\"12\" cy=\"12\" r=\"10\" />\n <path d=\"M8 14s1.5 2 4 2 4-2 4-2\" />\n <line x1=\"9\" x2=\"9.01\" y1=\"9\" y2=\"9\" />\n <line x1=\"15\" x2=\"15.01\" y1=\"9\" y2=\"9\" />\n </svg>\n );\n}\n\n/** lucide `speaker` (moved from @ai-matrx/meet). */\nexport function SpeakerIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"speaker\", props)}>\n <path d=\"M11 5 6 9H2v6h4l5 4V5Z\" />\n <path d=\"M15.54 8.46a5 5 0 0 1 0 7.07\" />\n <path d=\"M19.07 4.93a10 10 0 0 1 0 14.14\" />\n </svg>\n );\n}\n\n/** lucide `split-down` (moved from @ai-matrx/canvas). */\nexport function SplitDownIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"split-down\", props)}>\n <rect width=\"18\" height=\"18\" x=\"3\" y=\"3\" rx=\"2\" />\n <path d=\"M3 12h18\" />\n </svg>\n );\n}\n\n/** lucide `spotlight` (moved from @ai-matrx/meet). */\nexport function SpotlightIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"spotlight\", props)}>\n <path d=\"M12 2 15 8.5 22 9.3 17 14 18.2 21 12 17.6 5.8 21 7 14 2 9.3 9 8.5Z\" />\n </svg>\n );\n}\n\n/** lucide `stop` (moved from @ai-matrx/coding-sessions). */\nexport function StopIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"stop\", props)}>\n <rect x=\"6\" y=\"6\" width=\"12\" height=\"12\" rx=\"2\" fill=\"currentColor\" stroke=\"none\" />\n </svg>\n );\n}\n\n/** lucide `subtitles` (moved from @ai-matrx/media). */\nexport function SubtitlesIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"subtitles\", props)}>\n <rect width=\"18\" height=\"14\" x=\"3\" y=\"5\" rx=\"2\" ry=\"2\" />\n <path d=\"M7 15h4M15 15h2M7 11h2M13 11h4\" />\n </svg>\n );\n}\n\n/** lucide `sun` (moved from @ai-matrx/coding-sessions). */\nexport function SunIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"sun\", props)}>\n <circle cx=\"12\" cy=\"12\" r=\"4\" />\n <path d=\"M12 2.5v2M12 19.5v2M4.2 4.2l1.4 1.4M18.4 18.4l1.4 1.4M2.5 12h2M19.5 12h2M4.2 19.8l1.4-1.4M18.4 5.6l1.4-1.4\" />\n </svg>\n );\n}\n\n/** lucide `sun-medium` (moved from @ai-matrx/capture). */\nexport function SunMediumIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"sun-medium\", props)}>\n <circle cx=\"12\" cy=\"12\" r=\"4\" />\n <path d=\"M12 3v1\" />\n <path d=\"M12 20v1\" />\n <path d=\"M3 12h1\" />\n <path d=\"M20 12h1\" />\n <path d=\"m18.364 5.636-.707.707\" />\n <path d=\"m6.343 17.657-.707.707\" />\n <path d=\"m5.636 5.636.707.707\" />\n <path d=\"m17.657 17.657.707.707\" />\n </svg>\n );\n}\n\n/** lucide `tag` (moved from @ai-matrx/associations). */\nexport function TagIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"tag\", props)}>\n <path d=\"M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z\" />\n <circle cx=\"7.5\" cy=\"7.5\" r=\".5\" fill=\"currentColor\" />\n </svg>\n );\n}\n\n/** lucide `timer` (moved from @ai-matrx/capture). */\nexport function TimerIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"timer\", props)}>\n <line x1=\"10\" x2=\"14\" y1=\"2\" y2=\"2\" />\n <line x1=\"12\" x2=\"15\" y1=\"14\" y2=\"11\" />\n <circle cx=\"12\" cy=\"14\" r=\"8\" />\n </svg>\n );\n}\n\n/** lucide `type` (moved from @ai-matrx/agents). */\nexport function TypeIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"type\", props)}>\n <path d=\"M12 4v16\" />\n <path d=\"M4 7V5a1 1 0 0 1 1-1h14a1 1 0 0 1 1 1v2\" />\n <path d=\"M9 20h6\" />\n </svg>\n );\n}\n\n/** lucide `unfold-vertical` (moved from @ai-matrx/diff). */\nexport function UnfoldVerticalIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"unfold-vertical\", props)}>\n <path d=\"M12 22v-6\" />\n <path d=\"M12 8V2\" />\n <path d=\"M4 12H2\" />\n <path d=\"M10 12H8\" />\n <path d=\"M16 12h-2\" />\n <path d=\"M22 12h-2\" />\n <path d=\"m15 19-3 3-3-3\" />\n <path d=\"m15 5-3-3-3 3\" />\n </svg>\n );\n}\n\n/** lucide `unlink` (moved from @ai-matrx/agents). */\nexport function UnlinkIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"unlink\", props)}>\n <path d=\"m18.84 12.25 1.72-1.71h-.02a5.004 5.004 0 0 0-.12-7.07 5.006 5.006 0 0 0-6.95 0l-1.72 1.71\" />\n <path d=\"m5.17 11.75-1.71 1.71a5.004 5.004 0 0 0 .12 7.07 5.006 5.006 0 0 0 6.95 0l1.71-1.71\" />\n <line x1=\"8\" x2=\"8\" y1=\"2\" y2=\"5\" />\n <line x1=\"2\" x2=\"5\" y1=\"8\" y2=\"8\" />\n <line x1=\"16\" x2=\"16\" y1=\"19\" y2=\"22\" />\n <line x1=\"19\" x2=\"22\" y1=\"16\" y2=\"16\" />\n </svg>\n );\n}\n\n/** lucide `upvote` (moved from @ai-matrx/meet). */\nexport function UpvoteIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"upvote\", props)}>\n <path d=\"M9 18v-6H5l7-7 7 7h-4v6H9z\" />\n </svg>\n );\n}\n\n/** lucide `variable` (moved from @ai-matrx/agents). */\nexport function VariableIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"variable\", props)}>\n <path d=\"M8 21s-4-3-4-9 4-9 4-9\" />\n <path d=\"M16 3s4 3 4 9-4 9-4 9\" />\n <line x1=\"15\" x2=\"9\" y1=\"9\" y2=\"15\" />\n <line x1=\"9\" x2=\"15\" y1=\"9\" y2=\"15\" />\n </svg>\n );\n}\n\n/** lucide `video-off` (moved from @ai-matrx/media). */\nexport function VideoOffIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"video-off\", props)}>\n <path d=\"M10.66 6H14a2 2 0 0 1 2 2v2.5l5.248-3.062A.5.5 0 0 1 22 7.87v8.196\" />\n <path d=\"M16 16a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h2\" />\n <path d=\"m2 2 20 20\" />\n </svg>\n );\n}\n\n/** lucide `volume-x` (moved from @ai-matrx/media). */\nexport function VolumeXIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"volume-x\", props)}>\n <path d=\"M11 4.702a.705.705 0 0 0-1.203-.498L6.413 7.587A1.4 1.4 0 0 1 5.416 8H3a1 1 0 0 0-1 1v6a1 1 0 0 0 1 1h2.416a1.4 1.4 0 0 1 .997.413l3.383 3.384A.705.705 0 0 0 11 19.298z\" />\n <line x1=\"22\" x2=\"16\" y1=\"9\" y2=\"15\" />\n <line x1=\"16\" x2=\"22\" y1=\"9\" y2=\"15\" />\n </svg>\n );\n}\n\n/** lucide `webhook` (moved from @ai-matrx/agents). */\nexport function WebhookIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"webhook\", props)}>\n <path d=\"M18 16.98h-5.99c-1.1 0-1.95.94-2.48 1.9A4 4 0 0 1 2 17c.01-.7.2-1.4.57-2\" />\n <path d=\"m6 17 3.13-5.78c.53-.97.1-2.18-.5-3.1a4 4 0 1 1 6.89-4.06\" />\n <path d=\"m12 6 3.13 5.73C15.66 12.7 16.9 13 18 13a4 4 0 0 1 0 8\" />\n </svg>\n );\n}\n\n/** lucide `whiteboard` (moved from @ai-matrx/meet). */\nexport function WhiteboardIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"whiteboard\", props)}>\n <path d=\"M2 3h20\" />\n <path d=\"M21 3v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V3\" />\n <path d=\"m7 21 5-5 5 5\" />\n </svg>\n );\n}\n\n/** lucide `wifi-low` (moved from @ai-matrx/meet). */\nexport function WifiLowIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"wifi-low\", props)}>\n <path d=\"M12 20h.01\" />\n <path d=\"M8.5 16.5a5 5 0 0 1 7 0\" />\n </svg>\n );\n}\n\n/** lucide `wrap-text` (moved from @ai-matrx/diff). */\nexport function WrapTextIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"wrap-text\", props)}>\n <path d=\"M3 6h18\" />\n <path d=\"M3 12h15a3 3 0 1 1 0 6h-4\" />\n <path d=\"m16 16-2 2 2 2\" />\n <path d=\"M3 18h7\" />\n </svg>\n );\n}\n\n/** lucide `wrench` (moved from @ai-matrx/agents). */\nexport function WrenchIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"wrench\", props)}>\n <path d=\"M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.106-3.105c.32-.322.863-.22.983.218a6 6 0 0 1-8.259 7.057l-7.91 7.91a1 1 0 0 1-2.999-3l7.91-7.91a6 6 0 0 1 7.057-8.259c.438.12.54.662.219.984z\" />\n </svg>\n );\n}\n\n/** lucide `youtube` (moved from @ai-matrx/agents). */\nexport function YoutubeIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"youtube\", props)}>\n <path d=\"M2.5 17a24.12 24.12 0 0 1 0-10 2 2 0 0 1 1.4-1.4 49.56 49.56 0 0 1 16.2 0A2 2 0 0 1 21.5 7a24.12 24.12 0 0 1 0 10 2 2 0 0 1-1.4 1.4 49.55 49.55 0 0 1-16.2 0A2 2 0 0 1 2.5 17\" />\n <path d=\"m10 15 5-3-5-3z\" />\n </svg>\n );\n}\n\n/** lucide `zap` (moved from @ai-matrx/capture). */\nexport function ZapIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"zap\", props)}>\n <path d=\"M4 14a1 1 0 0 1-.78-1.63l9.9-10.2a.5.5 0 0 1 .86.46l-1.92 6.02A1 1 0 0 0 13 10h7a1 1 0 0 1 .78 1.63l-9.9 10.2a.5.5 0 0 1-.86-.46l1.92-6.02A1 1 0 0 0 11 14z\" />\n </svg>\n );\n}\n\n/** lucide `zap-off` (moved from @ai-matrx/capture). */\nexport function ZapOffIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"zap-off\", props)}>\n <path d=\"M10.513 4.856 13.12 2.17a.5.5 0 0 1 .86.46l-1.377 4.317\" />\n <path d=\"M15.656 10H20a1 1 0 0 1 .78 1.63l-1.72 1.773\" />\n <path d=\"M16.273 16.273 10.88 21.83a.5.5 0 0 1-.86-.46l1.92-6.02A1 1 0 0 0 11 14H4a1 1 0 0 1-.78-1.63l4.507-4.643\" />\n <path d=\"m2 2 20 20\" />\n </svg>\n );\n}\n\n/** lucide `log-in` — the sign-in action of the auth gate. */\nexport function LogInIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"log-in\", props)}>\n <path d=\"M15 3h4a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2h-4\" />\n <polyline points=\"10 17 15 12 10 7\" />\n <line x1=\"15\" x2=\"3\" y1=\"12\" y2=\"12\" />\n </svg>\n );\n}\n\n/** lucide `gem` — the create-account action of the auth gate. */\nexport function GemIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"gem\", props)}>\n <path d=\"M6 3h12l4 6-10 13L2 9Z\" />\n <path d=\"M11 3 8 9l4 13 4-13-3-6\" />\n <path d=\"M2 9h20\" />\n </svg>\n );\n}\n\n/** lucide `key`. */\nexport function KeyIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"key\", props)}>\n <path d=\"m2 21 9.6-9.6\" />\n <path d=\"m7.5 15.5 2.3 2.3a1 1 0 0 1 0 1.4l-2.1 2.1a1 1 0 0 1-1.4 0L4 19\" />\n <circle cx=\"15.5\" cy=\"7.5\" r=\"5.5\" />\n </svg>\n );\n}\n\n/** lucide `credit-card`. */\nexport function CreditCardIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"credit-card\", props)}>\n <rect width=\"20\" height=\"14\" x=\"2\" y=\"5\" rx=\"2\" />\n <line x1=\"2\" x2=\"22\" y1=\"10\" y2=\"10\" />\n <path d=\"M6 14h2\" />\n </svg>\n );\n}\n\n/** lucide `user-round`. */\nexport function UserRoundIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"user-round\", props)}>\n <circle cx=\"12\" cy=\"8\" r=\"5\" />\n <path d=\"M20 21a8 8 0 0 0-16 0\" />\n </svg>\n );\n}\n\n/** lucide `user`. */\nexport function UserIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"user\", props)}>\n <path d=\"M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2\" />\n <circle cx=\"12\" cy=\"7\" r=\"4\" />\n </svg>\n );\n}\n\n/** lucide `terminal`. */\nexport function TerminalIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"terminal\", props)}>\n <path d=\"M12 19h8\" />\n <path d=\"m4 17 6-6-6-6\" />\n </svg>\n );\n}\n\n/** lucide `trash`. */\nexport function TrashIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"trash\", props)}>\n <path d=\"M10 11v6\" />\n <path d=\"M14 11v6\" />\n <path d=\"M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6\" />\n <path d=\"M3 6h18\" />\n <path d=\"M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2\" />\n </svg>\n );\n}\n\n/** lucide `building`. */\nexport function BuildingIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"building\", props)}>\n <path d=\"M12 10h.01\" />\n <path d=\"M12 14h.01\" />\n <path d=\"M12 6h.01\" />\n <path d=\"M16 10h.01\" />\n <path d=\"M16 14h.01\" />\n <path d=\"M16 6h.01\" />\n <path d=\"M8 10h.01\" />\n <path d=\"M8 14h.01\" />\n <path d=\"M8 6h.01\" />\n <path d=\"M9 22v-3a1 1 0 0 1 1-1h4a1 1 0 0 1 1 1v3\" />\n <rect x=\"4\" y=\"2\" width=\"16\" height=\"20\" rx=\"2\" />\n </svg>\n );\n}\n\n/** lucide `plug`. */\nexport function PlugIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"plug\", props)}>\n <path d=\"M12 22v-5\" />\n <path d=\"M15 8V2\" />\n <path d=\"M17 8a1 1 0 0 1 1 1v4a4 4 0 0 1-4 4h-4a4 4 0 0 1-4-4V9a1 1 0 0 1 1-1z\" />\n <path d=\"M9 8V2\" />\n </svg>\n );\n}\n\n/** lucide `share`. */\nexport function ShareIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"share\", props)}>\n <path d=\"M12 2v13\" />\n <path d=\"m16 6-4-4-4 4\" />\n <path d=\"M4 12v8a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-8\" />\n </svg>\n );\n}\n\n/** lucide `arrow-up-down`. */\nexport function ArrowUpDownIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"arrow-up-down\", props)}>\n <path d=\"m21 16-4 4-4-4\" />\n <path d=\"M17 20V4\" />\n <path d=\"m3 8 4-4 4 4\" />\n <path d=\"M7 4v16\" />\n </svg>\n );\n}\n\n/** lucide `move`. */\nexport function MoveIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"move\", props)}>\n <path d=\"M12 2v20\" />\n <path d=\"m15 19-3 3-3-3\" />\n <path d=\"m19 9 3 3-3 3\" />\n <path d=\"M2 12h20\" />\n <path d=\"m5 9-3 3 3 3\" />\n <path d=\"m9 5 3-3 3 3\" />\n </svg>\n );\n}\n\n/** lucide `qr-code`. */\nexport function QrCodeIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"qr-code\", props)}>\n <rect width=\"5\" height=\"5\" x=\"3\" y=\"3\" rx=\"1\" />\n <rect width=\"5\" height=\"5\" x=\"16\" y=\"3\" rx=\"1\" />\n <rect width=\"5\" height=\"5\" x=\"3\" y=\"16\" rx=\"1\" />\n <path d=\"M21 16h-3a2 2 0 0 0-2 2v3\" />\n <path d=\"M21 21v.01\" />\n <path d=\"M12 7v3a2 2 0 0 1-2 2H7\" />\n <path d=\"M3 12h.01\" />\n <path d=\"M12 3h.01\" />\n <path d=\"M12 16v.01\" />\n <path d=\"M16 12h1\" />\n <path d=\"M21 12v.01\" />\n <path d=\"M12 21v-1\" />\n </svg>\n );\n}\n\n/** lucide `power`. */\nexport function PowerIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"power\", props)}>\n <path d=\"M12 2v10\" />\n <path d=\"M18.4 6.6a9 9 0 1 1-12.77.04\" />\n </svg>\n );\n}\n\n/** lucide `sliders-vertical`. */\nexport function SlidersVerticalIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"sliders-vertical\", props)}>\n <path d=\"M10 8h4\" />\n <path d=\"M12 21v-9\" />\n <path d=\"M12 8V3\" />\n <path d=\"M17 16h4\" />\n <path d=\"M19 12V3\" />\n <path d=\"M19 21v-5\" />\n <path d=\"M3 14h4\" />\n <path d=\"M5 10V3\" />\n <path d=\"M5 21v-7\" />\n </svg>\n );\n}\n\n/** lucide `fingerprint-pattern`. */\nexport function FingerprintPatternIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"fingerprint-pattern\", props)}>\n <path d=\"M12 10a2 2 0 0 0-2 2c0 1.02-.1 2.51-.26 4\" />\n <path d=\"M14 13.12c0 2.38 0 6.38-1 8.88\" />\n <path d=\"M17.29 21.02c.12-.6.43-2.3.5-3.02\" />\n <path d=\"M2 12a10 10 0 0 1 18-6\" />\n <path d=\"M2 16h.01\" />\n <path d=\"M21.8 16c.2-2 .131-5.354 0-6\" />\n <path d=\"M5 19.5C5.5 18 6 15 6 12a6 6 0 0 1 .34-2\" />\n <path d=\"M8.65 22c.21-.66.45-1.32.57-2\" />\n <path d=\"M9 6.8a6 6 0 0 1 9 5.2v2\" />\n </svg>\n );\n}\n\n/** lucide `send`. */\nexport function SendIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"send\", props)}>\n <path d=\"M14.536 21.686a.5.5 0 0 0 .937-.024l6.5-19a.496.496 0 0 0-.635-.635l-19 6.5a.5.5 0 0 0-.024.937l7.93 3.18a2 2 0 0 1 1.112 1.11z\" />\n <path d=\"m21.854 2.147-10.94 10.939\" />\n </svg>\n );\n}\n\n/** lucide `paperclip`. */\nexport function PaperclipIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"paperclip\", props)}>\n <path d=\"m16 6-8.414 8.586a2 2 0 0 0 2.829 2.829l8.414-8.586a4 4 0 1 0-5.657-5.657l-8.379 8.551a6 6 0 1 0 8.485 8.485l8.379-8.551\" />\n </svg>\n );\n}\n\n/** lucide `check-check`. */\nexport function CheckCheckIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"check-check\", props)}>\n <path d=\"M18 6 7 17l-5-5\" />\n <path d=\"m22 10-7.5 7.5L13 16\" />\n </svg>\n );\n}\n\n/** lucide `reply`. */\nexport function ReplyIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"reply\", props)}>\n <path d=\"M20 18v-2a4 4 0 0 0-4-4H4\" />\n <path d=\"m9 17-5-5 5-5\" />\n </svg>\n );\n}\n\n/** lucide `link`. */\nexport function LinkIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"link\", props)}>\n <path d=\"M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71\" />\n <path d=\"M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71\" />\n </svg>\n );\n}\n\n/** lucide `bot`. */\nexport function BotIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"bot\", props)}>\n <path d=\"M12 8V4H8\" />\n <rect width=\"16\" height=\"12\" x=\"4\" y=\"8\" rx=\"2\" />\n <path d=\"M2 14h2\" />\n <path d=\"M20 14h2\" />\n <path d=\"M15 13v2\" />\n <path d=\"M9 13v2\" />\n </svg>\n );\n}\n\n/** lucide `bell-off`. */\nexport function BellOffIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"bell-off\", props)}>\n <path d=\"M10.268 21a2 2 0 0 0 3.464 0\" />\n <path d=\"M17 17H4a1 1 0 0 1-.74-1.673C4.59 13.956 6 12.499 6 8a6 6 0 0 1 .258-1.742\" />\n <path d=\"m2 2 20 20\" />\n <path d=\"M8.668 3.01A6 6 0 0 1 18 8c0 2.687.77 4.653 1.707 6.05\" />\n </svg>\n );\n}\n\n/** lucide `mail`. */\nexport function MailIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"mail\", props)}>\n <path d=\"m22 7-8.991 5.727a2 2 0 0 1-2.009 0L2 7\" />\n <rect x=\"2\" y=\"4\" width=\"20\" height=\"16\" rx=\"2\" />\n </svg>\n );\n}\n\n/** lucide `mail-open`. */\nexport function MailOpenIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"mail-open\", props)}>\n <path d=\"M21.2 8.4c.5.38.8.97.8 1.6v10a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V10a2 2 0 0 1 .8-1.6l8-6a2 2 0 0 1 2.4 0l8 6Z\" />\n <path d=\"m22 10-8.97 5.7a1.94 1.94 0 0 1-2.06 0L2 10\" />\n </svg>\n );\n}\n\n/** lucide `folder-input`. */\nexport function FolderInputIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"folder-input\", props)}>\n <path d=\"M2 9V5a2 2 0 0 1 2-2h3.9a2 2 0 0 1 1.69.9l.81 1.2a2 2 0 0 0 1.67.9H20a2 2 0 0 1 2 2v10a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2v-1\" />\n <path d=\"M2 13h10\" />\n <path d=\"m9 16 3-3-3-3\" />\n </svg>\n );\n}\n\n/** lucide `star-off`. */\nexport function StarOffIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"star-off\", props)}>\n <path d=\"m10.344 4.688 1.181-2.393a.53.53 0 0 1 .95 0l2.31 4.679a2.12 2.12 0 0 0 1.595 1.16l5.166.756a.53.53 0 0 1 .294.904l-3.237 3.152\" />\n <path d=\"m17.945 17.945.43 2.505a.53.53 0 0 1-.771.56l-4.618-2.428a2.12 2.12 0 0 0-1.973 0L6.396 21.01a.53.53 0 0 1-.77-.56l.881-5.139a2.12 2.12 0 0 0-.611-1.879L2.16 9.795a.53.53 0 0 1 .294-.906l5.165-.755a8 8 0 0 0 .4-.099\" />\n <path d=\"m2 2 20 20\" />\n </svg>\n );\n}\n\n/** lucide `columns-3`. */\nexport function Columns3Icon(props: IconProps) {\n return (\n <svg {...lucideProps(\"columns-3\", props)}>\n <rect width=\"18\" height=\"18\" x=\"3\" y=\"3\" rx=\"2\" />\n <path d=\"M9 3v18\" />\n <path d=\"M15 3v18\" />\n </svg>\n );\n}\n\n/** lucide `blocks`. */\nexport function BlocksIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"blocks\", props)}>\n <path d=\"M10 22V7a1 1 0 0 0-1-1H4a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-5a1 1 0 0 0-1-1H2\" />\n <rect x=\"14\" y=\"2\" width=\"8\" height=\"8\" rx=\"1\" />\n </svg>\n );\n}\n\n/** lucide `calendar-clock`. */\nexport function CalendarClockIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"calendar-clock\", props)}>\n <path d=\"M16 14v2.2l1.6 1\" />\n <path d=\"M16 2v3\" />\n <path d=\"M21 7.338V5a2 2 0 00-2-2H5a2 2 0 00-2 2v14a2 2 0 002 2h2.338\" />\n <path d=\"M3 9h5.859\" />\n <path d=\"M8 2v3\" />\n <circle cx=\"16\" cy=\"16\" r=\"6\" />\n </svg>\n );\n}\n\n/** lucide `door-open`. */\nexport function DoorOpenIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"door-open\", props)}>\n <path d=\"M10 21H2\" />\n <path d=\"M10 3H7a2 2 0 00-2 2v16\" />\n <path d=\"M14 12h.01\" />\n <path d=\"M19 21V5a2 2 0 00-1.675-1.974l-6.163-1.013A1 1 0 0010 3v18a1 1 0 001.124.992z\" />\n <path d=\"M22 21h-3\" />\n </svg>\n );\n}\n\n/** lucide `inbox`. */\nexport function InboxIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"inbox\", props)}>\n <polyline points=\"22 12 16 12 14 15 10 15 8 12 2 12\" />\n <path d=\"M5.45 5.11 2 12v6a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-6l-3.45-6.89A2 2 0 0 0 16.76 4H7.24a2 2 0 0 0-1.79 1.11z\" />\n </svg>\n );\n}\n\n/** lucide `layout-dashboard`. */\nexport function LayoutDashboardIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"layout-dashboard\", props)}>\n <rect width=\"7\" height=\"9\" x=\"3\" y=\"3\" rx=\"1\" />\n <rect width=\"7\" height=\"5\" x=\"14\" y=\"3\" rx=\"1\" />\n <rect width=\"7\" height=\"9\" x=\"14\" y=\"12\" rx=\"1\" />\n <rect width=\"7\" height=\"5\" x=\"3\" y=\"16\" rx=\"1\" />\n </svg>\n );\n}\n\n/** lucide `archive-restore`. */\nexport function ArchiveRestoreIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"archive-restore\", props)}>\n <rect width=\"20\" height=\"5\" x=\"2\" y=\"3\" rx=\"1\" />\n <path d=\"M4 8v11a2 2 0 0 0 2 2h2\" />\n <path d=\"M20 8v11a2 2 0 0 1-2 2h-2\" />\n <path d=\"m9 15 3-3 3 3\" />\n <path d=\"M12 12v9\" />\n </svg>\n );\n}\n\n/** lucide `split`. */\nexport function SplitIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"split\", props)}>\n <path d=\"M16 3h5v5\" />\n <path d=\"M8 3H3v5\" />\n <path d=\"M12 22v-8.3a4 4 0 0 0-1.172-2.872L3 3\" />\n <path d=\"m15 9 6-6\" />\n </svg>\n );\n}\n\n/** lucide `arrow-up-from-line`. */\nexport function ArrowUpFromLineIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"arrow-up-from-line\", props)}>\n <path d=\"m18 9-6-6-6 6\" />\n <path d=\"M12 3v14\" />\n <path d=\"M5 21h14\" />\n </svg>\n );\n}\n\n/** lucide `lock-open`. */\nexport function LockOpenIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"lock-open\", props)}>\n <rect width=\"18\" height=\"11\" x=\"3\" y=\"11\" rx=\"2\" ry=\"2\" />\n <path d=\"M7 11V7a5 5 0 0 1 9.9-1\" />\n </svg>\n );\n}\n\n/** lucide `printer`. */\nexport function PrinterIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"printer\", props)}>\n <path d=\"M6 18H4a2 2 0 0 1-2-2v-5a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2v5a2 2 0 0 1-2 2h-2\" />\n <path d=\"M6 9V3a1 1 0 0 1 1-1h10a1 1 0 0 1 1 1v6\" />\n <rect x=\"6\" y=\"14\" width=\"12\" height=\"8\" rx=\"1\" />\n </svg>\n );\n}\n\n/** lucide `rocket`. */\nexport function RocketIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"rocket\", props)}>\n <path d=\"M12 15v5s3.03-.55 4-2c1.08-1.62 0-5 0-5\" />\n <path d=\"M4.5 16.5c-1.5 1.26-2 5-2 5s3.74-.5 5-2c.71-.84.7-2.13-.09-2.91a2.18 2.18 0 0 0-2.91-.09\" />\n <path d=\"M9 12a22 22 0 0 1 2-3.95A12.88 12.88 0 0 1 22 2c0 2.72-.78 7.5-6 11a22.4 22.4 0 0 1-4 2z\" />\n <path d=\"M9 12H4s.55-3.03 2-4c1.62-1.08 5 .05 5 .05\" />\n </svg>\n );\n}\n\n/** lucide `message-circle`. */\nexport function MessageCircleIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"message-circle\", props)}>\n <path d=\"M2.992 16.342a2 2 0 0 1 .094 1.167l-1.065 3.29a1 1 0 0 0 1.236 1.168l3.413-.998a2 2 0 0 1 1.099.092 10 10 0 1 0-4.777-4.719\" />\n </svg>\n );\n}\n\n/** lucide `copy-plus`. */\nexport function CopyPlusIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"copy-plus\", props)}>\n <line x1=\"15\" x2=\"15\" y1=\"12\" y2=\"18\" />\n <line x1=\"12\" x2=\"18\" y1=\"15\" y2=\"15\" />\n <rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\" />\n <path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\" />\n </svg>\n );\n}\n\n/** lucide `map-pin`. */\nexport function MapPinIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"map-pin\", props)}>\n <path d=\"M20 10c0 4.993-5.539 10.193-7.399 11.799a1 1 0 0 1-1.202 0C9.539 20.193 4 14.993 4 10a8 8 0 0 1 16 0\" />\n <circle cx=\"12\" cy=\"10\" r=\"3\" />\n </svg>\n );\n}\n\n/** lucide `at-sign`. */\nexport function AtSignIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"at-sign\", props)}>\n <circle cx=\"12\" cy=\"12\" r=\"4\" />\n <path d=\"M16 8v5a3 3 0 0 0 6 0v-1a10 10 0 1 0-4 8\" />\n </svg>\n );\n}\n\n/** lucide `link-2-off`. */\nexport function Link2OffIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"link-2-off\", props)}>\n <path d=\"M9 17H7A5 5 0 0 1 7 7\" />\n <path d=\"M15 7h2a5 5 0 0 1 4 8\" />\n <line x1=\"8\" x2=\"12\" y1=\"12\" y2=\"12\" />\n <line x1=\"2\" x2=\"22\" y1=\"2\" y2=\"22\" />\n </svg>\n );\n}\n\n/** lucide `whole-word`. */\nexport function WholeWordIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"whole-word\", props)}>\n <circle cx=\"7\" cy=\"12\" r=\"3\" />\n <path d=\"M10 9v6\" />\n <circle cx=\"17\" cy=\"12\" r=\"3\" />\n <path d=\"M14 7v8\" />\n <path d=\"M22 17v1c0 .5-.5 1-1 1H3c-.5 0-1-.5-1-1v-1\" />\n </svg>\n );\n}\n\n/** lucide `lightbulb`. */\nexport function LightbulbIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"lightbulb\", props)}>\n <path d=\"M15 14c.2-1 .7-1.7 1.5-2.5 1-.9 1.5-2.2 1.5-3.5A6 6 0 0 0 6 8c0 1 .2 2.2 1.5 3.5.7.7 1.3 1.5 1.5 2.5\" />\n <path d=\"M9 18h6\" />\n <path d=\"M10 22h4\" />\n </svg>\n );\n}\n\n/** lucide `shield-off`. */\nexport function ShieldOffIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"shield-off\", props)}>\n <path d=\"m2 2 20 20\" />\n <path d=\"M5 5a1 1 0 0 0-1 1v7c0 5 3.5 7.5 7.67 8.94a1 1 0 0 0 .67.01c2.35-.82 4.48-1.97 5.9-3.71\" />\n <path d=\"M9.309 3.652A12.252 12.252 0 0 0 11.24 2.28a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1v7a9.784 9.784 0 0 1-.08 1.264\" />\n </svg>\n );\n}\n\n/** lucide `chevrons-left`. */\nexport function ChevronsLeftIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"chevrons-left\", props)}>\n <path d=\"m11 17-5-5 5-5\" />\n <path d=\"m18 17-5-5 5-5\" />\n </svg>\n );\n}\n\n/** lucide `chevrons-right`. */\nexport function ChevronsRightIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"chevrons-right\", props)}>\n <path d=\"m6 17 5-5-5-5\" />\n <path d=\"m13 17 5-5-5-5\" />\n </svg>\n );\n}\n\n/** lucide `users-round`. */\nexport function UsersRoundIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"users-round\", props)}>\n <path d=\"M18 21a8 8 0 0 0-16 0\" />\n <circle cx=\"10\" cy=\"8\" r=\"5\" />\n <path d=\"M22 20c0-3.37-2-6.5-4-8a5 5 0 0 0-.45-8.3\" />\n </svg>\n );\n}\n\n/** lucide `landmark`. */\nexport function LandmarkIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"landmark\", props)}>\n <path d=\"M10 18v-7\" />\n <path d=\"M11.119 2.205a2 2 0 0 1 1.762 0l7.84 3.846A.5.5 0 0 1 20.5 7h-17a.5.5 0 0 1-.22-.949z\" />\n <path d=\"M14 18v-7\" />\n <path d=\"M18 18v-7\" />\n <path d=\"M3 22h18\" />\n <path d=\"M6 18v-7\" />\n </svg>\n );\n}\n\n/** lucide `factory`. */\nexport function FactoryIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"factory\", props)}>\n <path d=\"M12 16h.01\" />\n <path d=\"M16 16h.01\" />\n <path d=\"M3 19a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V8.5a.5.5 0 0 0-.769-.422l-4.462 2.844A.5.5 0 0 1 15 10.5v-2a.5.5 0 0 0-.769-.422L9.77 10.922A.5.5 0 0 1 9 10.5V5a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2z\" />\n <path d=\"M8 16h.01\" />\n </svg>\n );\n}\n\n/** lucide `chevrons-down` — CollapsibleText's \"expand all\". */\nexport function ChevronsDownIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"chevrons-down\", props)}>\n <path d=\"m7 6 5 5 5-5\" />\n <path d=\"m7 13 5 5 5-5\" />\n </svg>\n );\n}\n\n/** lucide `chevrons-up` — CollapsibleText's \"collapse all\". */\nexport function ChevronsUpIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"chevrons-up\", props)}>\n <path d=\"m17 11-5-5-5 5\" />\n <path d=\"m17 18-5-5-5 5\" />\n </svg>\n );\n}\n\n/** lucide `arrow-up-right` — CitationChip's \"open source\". */\nexport function ArrowUpRightIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"arrow-up-right\", props)}>\n <path d=\"M7 7h10v10\" />\n <path d=\"M7 17 17 7\" />\n </svg>\n );\n}\n\n/** lucide `quote` — CitationChip's excerpt blockquote. */\nexport function QuoteIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"quote\", props)}>\n <path d=\"M16 3a2 2 0 0 0-2 2v6a2 2 0 0 0 2 2 1 1 0 0 1 1 1v1a2 2 0 0 1-2 2 1 1 0 0 0-1 1v2a1 1 0 0 0 1 1 6 6 0 0 0 6-6V5a2 2 0 0 0-2-2z\" />\n <path d=\"M5 3a2 2 0 0 0-2 2v6a2 2 0 0 0 2 2 1 1 0 0 1 1 1v1a2 2 0 0 1-2 2 1 1 0 0 0-1 1v2a1 1 0 0 0 1 1 6 6 0 0 0 6-6V5a2 2 0 0 0-2-2z\" />\n </svg>\n );\n}\n\n/** lucide `panel-top-open` — the floating dock's phone menu button (opens the list). */\nexport function PanelTopOpenIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"panel-top-open\", props)}>\n <rect width=\"18\" height=\"18\" x=\"3\" y=\"3\" rx=\"2\" />\n <path d=\"M3 9h18\" />\n <path d=\"m15 14-3 3-3-3\" />\n </svg>\n );\n}\n\n/** lucide `panel-top-close` — the floating dock's phone menu button (closes the list). */\nexport function PanelTopCloseIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"panel-top-close\", props)}>\n <rect width=\"18\" height=\"18\" x=\"3\" y=\"3\" rx=\"2\" />\n <path d=\"M3 9h18\" />\n <path d=\"m9 16 3-3 3 3\" />\n </svg>\n );\n}\n","\"use client\";\n\n/**\n * Injected portal-container seam.\n *\n * The matrx-frontend original resolved nested portal targets through\n * `useNestedPortalContainer` (explicit prop > dialog content > popout body >\n * document.body) — a host-shaped hook wired to that app's dialog and\n * window-panel systems. The package inverts the seam: hosts provide the\n * resolved container through `PortalContainerProvider`; an explicit\n * `container` prop on a component still wins, and with neither the portal\n * falls through to `document.body` (Radix default). Priority semantics are\n * unchanged from the original.\n */\n\nimport * as React from \"react\";\n\n// Shared identity across independently bundled public entrypoints/loaders.\nconst CONTEXT_SLOT = Symbol.for(\"ai-matrx.design-system.portal-container-context\");\nconst contextRegistry = globalThis as typeof globalThis & { [CONTEXT_SLOT]?: React.Context<HTMLElement | null | undefined> };\nconst PortalContainerContext = contextRegistry[CONTEXT_SLOT] ??= React.createContext<HTMLElement | null | undefined>(undefined);\n\nexport interface PortalContainerProviderProps {\n /** Where nested Radix portals (Popover, etc.) should mount. `null`/`undefined` → document.body. */\n container: HTMLElement | null | undefined;\n children: React.ReactNode;\n}\n\nexport function PortalContainerProvider({\n container,\n children,\n}: PortalContainerProviderProps) {\n return (\n <PortalContainerContext.Provider value={container ?? undefined}>\n {children}\n </PortalContainerContext.Provider>\n );\n}\n\n/**\n * Resolve a portal target: explicit prop (including an explicit `null`,\n * meaning \"the default body\") beats the injected container.\n */\nexport function usePortalContainer(\n explicit?: HTMLElement | null,\n): HTMLElement | undefined {\n const injected = React.useContext(PortalContainerContext);\n\n if (explicit !== undefined) {\n return explicit ?? undefined;\n }\n\n return injected ?? undefined;\n}\n","\"use client\";\n\n/**\n * THE LOOK — one implementation, the host's native skin.\n *\n * A shared workspace (the Vault, …) is written ONCE in the web vocabulary (`/controls`, the root\n * Dialog/menus, semantic Tailwind tokens). Inside Matrx Desktop it must look like a Mac app (the\n * desktop standard, `desktop/DESKTOP.md`). `LookScope look=\"desktop\"` is that switch:\n *\n * - it draws a `data-matrx-look=\"desktop\"` box; `look-desktop.css` (imported by styles.css, inert\n * without the attribute) puts the web tokens on AppKit's values, Tailwind's type scale on\n * Apple's text styles, the platform's system font, and the `/controls` on NSControl geometry;\n * - every portal-aware layer opened inside it (Dialog, Popover, menus, Select, Tooltip) mounts in a\n * layer that carries the same attribute, so a menu or sheet wears the look too;\n * - `useLook()` tells a component the look, so the root `DialogContent` becomes a macOS sheet.\n *\n * `look=\"web\"` (the default) renders its children only: the web output is byte-for-byte unchanged.\n * Never a second component tree, never per-call-site overrides.\n */\n\nimport * as React from \"react\";\nimport { PortalContainerProvider } from \"./portal-container\";\n\nexport type Look = \"web\" | \"desktop\";\n\n// Shared identity across independently bundled public entrypoints (as portal-container does).\nconst CONTEXT_SLOT = Symbol.for(\"ai-matrx.design-system.look-context\");\nconst registry = globalThis as typeof globalThis & { [CONTEXT_SLOT]?: React.Context<Look> };\nconst LookContext = (registry[CONTEXT_SLOT] ??= React.createContext<Look>(\"web\"));\n\n/** The look the nearest `LookScope` chose; `\"web\"` outside any scope. */\nexport function useLook(): Look {\n return React.useContext(LookContext);\n}\n\nexport const LOOK_ATTRIBUTE = \"data-matrx-look\";\n\nexport interface LookScopeProps extends React.HTMLAttributes<HTMLDivElement> {\n look: Look;\n children: React.ReactNode;\n}\n\n/** The layer every portal opened inside a desktop scope mounts in: a body child wearing the look. */\nfunction useLookLayer(look: Look): HTMLElement | null {\n const [layer, setLayer] = React.useState<HTMLElement | null>(null);\n React.useEffect(() => {\n if (look === \"web\" || typeof document === \"undefined\") return;\n const el = document.createElement(\"div\");\n el.setAttribute(LOOK_ATTRIBUTE, look);\n el.setAttribute(\"data-slot\", \"look-layer\");\n document.body.appendChild(el);\n setLayer(el);\n return () => {\n el.remove();\n setLayer(null);\n };\n }, [look]);\n return layer;\n}\n\nexport function LookScope({ look, children, ...div }: LookScopeProps) {\n const layer = useLookLayer(look);\n if (look === \"web\") return <LookContext.Provider value=\"web\">{children}</LookContext.Provider>;\n return (\n <LookContext.Provider value={look}>\n <div {...div} {...{ [LOOK_ATTRIBUTE]: look }}>\n <PortalContainerProvider container={layer}>{children}</PortalContainerProvider>\n </div>\n </LookContext.Provider>\n );\n}\n","\"use client\";\n\n/**\n * Ported verbatim from matrx-frontend `components/ui/radix-dialog-modal-context.tsx`.\n * Shared by the Sheet and BottomSheet families (and available to hosts that\n * compose their own Radix Dialog-derived wrappers around these primitives).\n */\n\nimport * as React from \"react\";\n\n// Shared identity across independently bundled public entrypoints/loaders.\nconst CONTEXT_SLOT = Symbol.for(\"ai-matrx.design-system.dialog-modal-context\");\nconst contextRegistry = globalThis as typeof globalThis & { [CONTEXT_SLOT]?: React.Context<boolean> };\nconst RadixDialogModalContext = contextRegistry[CONTEXT_SLOT] ??= React.createContext<boolean>(true);\n\nexport interface RadixDialogModalProviderProps {\n children: React.ReactNode;\n modal: boolean;\n}\n\n/**\n * Keeps our Radix-based content wrappers aligned with the owning Root's\n * modality so ARIA semantics cannot drift from focus/pointer behavior.\n */\nexport function RadixDialogModalProvider({\n children,\n modal,\n}: RadixDialogModalProviderProps) {\n return (\n <RadixDialogModalContext.Provider value={modal}>\n {children}\n </RadixDialogModalContext.Provider>\n );\n}\n\n/** Returns whether the nearest Radix Dialog-derived root is modal. */\nexport function useRadixDialogModal(): boolean {\n return React.useContext(RadixDialogModalContext);\n}\n","/**\n * useIsMobile — the ONE breakpoint hook the package's responsive primitives\n * read (CommandDialog and Dialog both auto-render as a bottom sheet below it).\n *\n * The body lives in `@ai-matrx/kit/media-query` (chat-package independence\n * P12, 2026-10-01): the app's `hooks/use-mobile` and this package each carried\n * their own copy, and two breakpoint hooks is exactly the duplication this\n * package exists to end. Kit's reads through `useSyncExternalStore` — `false`\n * on the server and during hydration, so the desktop geometry hydrates — and\n * never throws where `matchMedia` is absent.\n */\nexport { MOBILE_BREAKPOINT, useIsMobile } from \"@ai-matrx/kit/media-query\";\n","/**\n * THE FRONT-MOST LAYER — one signal every floating layer shares, so the layer\n * the person used last is the one on top.\n *\n * A windowed Dialog sits at z-10000 so it is never behind the menu, popover or\n * host window it was opened from (0.38.1). But a host window opened or focused\n * AFTER it — the window an agent run opens from the Agents menu while Table\n * settings is open — then sat underneath it, and its composer could not be\n * clicked or typed into (found live 2026-09-26, register ARE-010). Recency has\n * to decide, across both systems, without coupling them.\n *\n * So any layer that comes to the front announces it: `announceLayerFront(el)`\n * dispatches `matrx:layer-front` on `document`. A windowed Dialog announces\n * itself when it opens and when the person presses or focuses inside it; it\n * steps BEHIND (z-999, still above the page and below the host's window\n * manager at 1000+) whenever another layer announces, and comes back the\n * moment the person reaches for it. A host window manager announces its\n * window on open and on focus.\n */\n\nexport const LAYER_FRONT_EVENT = \"matrx:layer-front\";\n\nexport interface LayerFrontDetail {\n /** The element that came to the front. */\n element: Element | null;\n}\n\n/** Tell every other floating layer that `element` is now the one in front. */\nexport function announceLayerFront(element: Element | null): void {\n if (typeof document === \"undefined\") return;\n document.dispatchEvent(\n new CustomEvent<LayerFrontDetail>(LAYER_FRONT_EVENT, { detail: { element } }),\n );\n}\n","/**\n * THE WINDOW DRAG — the ONE pointer-drag / resize / viewport-clamp primitive\n * every floating surface uses: a windowed Dialog's header, a PeekWindow, the\n * desktop InspectorPanel, @ai-matrx/summon's WindowPanel, Dock and LiteWindow,\n * and @ai-matrx/associations' DefaultWindowShell. It lives at this layer\n * because every one of them sits on design-system; nothing below may fork it.\n *\n * Three layers, use the highest one that fits:\n *\n * 1. `useDragMove()` — the React hook. A pointer move PAINTS the element\n * inside one animation frame (CSS `translate`, plus `width`/`height` for a\n * resize) and the host's state is committed EXACTLY ONCE, on release.\n * Writing state per pointer event re-renders whatever streams inside the\n * window sixty times a second (paid for in Workflow Studio's floating chat\n * and chat's ChatPanel). It also carries THE CURSOR LAW (`holdDragCursor`\n * for the whole gesture), z-order (`announceLayerFront` on press), the\n * \"controls in the handle stay controls\" rule, and a cleanup that leaves\n * no listener, frame or cursor behind on unmount.\n * 2. `startPointerDrag()` — the gesture lifecycle alone (window listeners per\n * pointer id, threshold, cursor hold, frame-coalesced moves, trailing-click\n * swallow, cancel). For a host whose moves must reach a store live (summon's\n * WindowPanel: pop-out drag-out detection and window-manager geometry).\n * 3. Pure geometry — `resizeRect()` (8-edge resize with size limits) and\n * `clampRectToViewport()` (the header always stays reachable).\n */\n\nimport {\n useCallback,\n useEffect,\n useLayoutEffect,\n useRef,\n useState,\n type PointerEvent as ReactPointerEvent,\n} from \"react\";\n\nimport { type DragCursor, holdDragCursor } from \"./drag-cursor\";\nimport { announceLayerFront } from \"./layer-front\";\n\n// ── Geometry ─────────────────────────────────────────────────────────────────\n\n/** A window's box in px — viewport px unless the host measures in a container. */\nexport interface DragRect {\n x: number;\n y: number;\n width: number;\n height: number;\n}\n\nexport interface DragViewport {\n width: number;\n height: number;\n}\n\n/** The edge or corner a resize handle grabs. */\nexport type ResizeEdge = \"n\" | \"s\" | \"e\" | \"w\" | \"ne\" | \"nw\" | \"se\" | \"sw\";\n\n/** The cursor held on the document while each edge resizes (THE CURSOR LAW). */\nexport const RESIZE_EDGE_CURSOR: Record<ResizeEdge, DragCursor> = {\n e: \"ew-resize\",\n w: \"ew-resize\",\n n: \"ns-resize\",\n s: \"ns-resize\",\n se: \"nwse-resize\",\n nw: \"nwse-resize\",\n ne: \"nesw-resize\",\n sw: \"nesw-resize\",\n};\n\nexport interface SizeLimits {\n minWidth?: number;\n minHeight?: number;\n maxWidth?: number;\n maxHeight?: number;\n}\n\n/** Controls inside a drag handle that stay controls — a press there never starts a drag. */\nexport const DRAG_IGNORE_SELECTOR =\n \"button,a,input,select,textarea,[role='button'],[contenteditable='true'],[data-no-drag]\";\n\nconst bound = (value: number, min: number, max: number): number => Math.min(max, Math.max(min, value));\n\n/**\n * `origin` resized by a pointer that traveled (`dx`, `dy`) from the press on\n * `edge`. A west or north edge keeps the opposite edge still; sizes honor\n * `limits`.\n */\nexport function resizeRect(origin: DragRect, edge: ResizeEdge, dx: number, dy: number, limits: SizeLimits = {}): DragRect {\n const minWidth = limits.minWidth ?? 0;\n const minHeight = limits.minHeight ?? 0;\n const maxWidth = limits.maxWidth ?? Number.POSITIVE_INFINITY;\n const maxHeight = limits.maxHeight ?? Number.POSITIVE_INFINITY;\n const next = { ...origin };\n if (edge.includes(\"e\")) next.width = bound(origin.width + dx, minWidth, maxWidth);\n if (edge.includes(\"s\")) next.height = bound(origin.height + dy, minHeight, maxHeight);\n if (edge.includes(\"w\")) {\n next.width = bound(origin.width - dx, minWidth, maxWidth);\n next.x = origin.x + (origin.width - next.width);\n }\n if (edge.includes(\"n\")) {\n next.height = bound(origin.height - dy, minHeight, maxHeight);\n next.y = origin.y + (origin.height - next.height);\n }\n return next;\n}\n\nexport interface ViewportClamp {\n /** Smallest gap kept to the viewport edge. Default 0. */\n margin?: number;\n /**\n * Px of the window that must stay on screen horizontally and below the top\n * edge. Omit to keep the WHOLE window on screen. Either way the top edge (the\n * header) is never above `margin`, and a window larger than the room keeps\n * its top-left visible — an unreachable header is an unclosable window.\n */\n keepVisible?: number;\n /** Shrink the window to the room (never below these) before placing it. */\n fit?: { minWidth: number; minHeight: number };\n}\n\n/** `rect` kept reachable inside `viewport` (see `ViewportClamp`). */\nexport function clampRectToViewport(rect: DragRect, viewport: DragViewport, clamp: ViewportClamp = {}): DragRect {\n const margin = clamp.margin ?? 0;\n let { width, height } = rect;\n if (clamp.fit) {\n width = Math.min(width, Math.max(clamp.fit.minWidth, viewport.width - margin * 2));\n height = Math.min(height, Math.max(clamp.fit.minHeight, viewport.height - margin * 2));\n }\n const keep = clamp.keepVisible;\n const lowX = keep === undefined ? margin : margin + Math.min(keep, width) - width;\n const highX = keep === undefined ? viewport.width - width - margin : viewport.width - Math.min(keep, width) - margin;\n const highY = keep === undefined ? viewport.height - height - margin : viewport.height - Math.min(keep, height) - margin;\n return {\n width,\n height,\n x: Math.round(Math.max(lowX, Math.min(rect.x, highX))),\n y: Math.round(Math.max(margin, Math.min(rect.y, highY))),\n };\n}\n\n/** The browser viewport (a sane desktop size during SSR). */\nexport function readViewport(): DragViewport {\n return typeof window === \"undefined\" ? { width: 1280, height: 800 } : { width: window.innerWidth, height: window.innerHeight };\n}\n\n// ── The gesture ──────────────────────────────────────────────────────────────\n\nexport interface DragDelta {\n dx: number;\n dy: number;\n}\n\nexport interface PointerDragOptions {\n /** Px the pointer must travel before the press becomes a drag. Default 0 (a drag from the press). */\n threshold?: number;\n /** Cursor held on the document while dragging. Default `grabbing`; `null` holds none. */\n cursor?: DragCursor | null;\n /** Coalesce moves to one call per animation frame. Default true. */\n frame?: boolean;\n /** Swallow the click the browser fires after a real drag. Default: `threshold > 0`. */\n swallowClick?: boolean;\n /** The press became a drag (immediately when `threshold` is 0). */\n onStart?(): void;\n /** The pointer traveled `delta` from the press (only after `onStart`). */\n onMove(delta: DragDelta, event: PointerEvent): void;\n /** Released or canceled by the browser. `moved` is false for a press that never traveled. */\n onEnd?(delta: DragDelta, info: { moved: boolean; started: boolean; cancelled: boolean }): void;\n}\n\nexport interface PointerDragHandle {\n /** Abort silently (unmount, close): listeners, frame and cursor are released, `onEnd` is not called. */\n cancel(): void;\n}\n\ninterface PressPoint {\n clientX: number;\n clientY: number;\n pointerId: number;\n}\n\n/** Track one pointer from its press until release. See the module doc. */\nexport function startPointerDrag(press: PressPoint, options: PointerDragOptions): PointerDragHandle {\n const threshold = options.threshold ?? 0;\n const useFrame = options.frame !== false;\n const swallowClick = options.swallowClick ?? threshold > 0;\n let started = false;\n let moved = false;\n let releaseCursor: (() => void) | null = null;\n let frame: number | null = null;\n let pending: { delta: DragDelta; event: PointerEvent } | null = null;\n let last: DragDelta = { dx: 0, dy: 0 };\n let done = false;\n\n const start = () => {\n started = true;\n if (options.cursor !== null) releaseCursor = holdDragCursor(options.cursor ?? \"grabbing\");\n options.onStart?.();\n };\n const flush = () => {\n frame = null;\n if (!pending) return;\n const { delta, event } = pending;\n pending = null;\n options.onMove(delta, event);\n };\n const onMove = (event: PointerEvent) => {\n if (event.pointerId !== press.pointerId) return;\n const delta = { dx: event.clientX - press.clientX, dy: event.clientY - press.clientY };\n if (!started) {\n if (Math.abs(delta.dx) < threshold && Math.abs(delta.dy) < threshold) return;\n start();\n }\n if (delta.dx !== 0 || delta.dy !== 0) moved = true;\n last = delta;\n pending = { delta, event };\n if (!useFrame || typeof window.requestAnimationFrame !== \"function\") flush();\n else if (frame === null) frame = window.requestAnimationFrame(flush);\n };\n const teardown = () => {\n done = true;\n window.removeEventListener(\"pointermove\", onMove);\n window.removeEventListener(\"pointerup\", onUp);\n window.removeEventListener(\"pointercancel\", onUp);\n if (frame !== null) window.cancelAnimationFrame?.(frame);\n frame = null;\n releaseCursor?.();\n releaseCursor = null;\n };\n const onUp = (event: PointerEvent) => {\n if (event.pointerId !== press.pointerId || done) return;\n // The last position is painted before the gesture ends, never dropped with its frame.\n if (pending) flush();\n teardown();\n options.onEnd?.(last, { moved, started, cancelled: event.type === \"pointercancel\" });\n if (moved && swallowClick) {\n const swallow = (click: MouseEvent) => {\n click.stopPropagation();\n click.preventDefault();\n };\n window.addEventListener(\"click\", swallow, { capture: true, once: true });\n window.setTimeout(() => window.removeEventListener(\"click\", swallow, { capture: true }), 0);\n }\n };\n\n window.addEventListener(\"pointermove\", onMove);\n window.addEventListener(\"pointerup\", onUp);\n window.addEventListener(\"pointercancel\", onUp);\n if (threshold <= 0) start();\n return {\n cancel: () => {\n if (!done) teardown();\n },\n };\n}\n\n// ── The hook ─────────────────────────────────────────────────────────────────\n\n/** What a gesture is doing: moving the window, or resizing it from an edge. */\nexport type DragGesture = \"move\" | ResizeEdge;\n\nexport interface DragCommit {\n /** The window's box when pressed. */\n origin: DragRect;\n gesture: DragGesture;\n /** Pointer travel, after `constrain`: `rect.x - origin.x`, `rect.y - origin.y`. */\n delta: DragDelta;\n /** `paint: \"offset\"` only: the host's `offset` at the press plus `delta`. */\n offset: { x: number; y: number };\n}\n\nexport interface UseDragMoveOptions {\n /** The element that MOVES (the window frame). */\n element: HTMLElement | null;\n /** Default true. False: presses do nothing (a phone sheet, a maximized window). */\n enabled?: boolean;\n /** Px before a press becomes a drag. Default 0. A handle that is also a click target passes 4. */\n threshold?: number;\n /** Allow touch drags. Default true. */\n touch?: boolean;\n /** Controls inside a handle that never start a drag. Default `DRAG_IGNORE_SELECTOR`; `null` = none. */\n ignore?: string | null;\n /** Announce the element as the front-most layer on press (layer-front.ts). Default true. */\n announce?: boolean;\n /**\n * How a drag paints the element before the commit:\n * - `delta` (default): `translate` by the travel, cleared in the commit's own render\n * (the host positions with left/top/right/bottom and commits the new place);\n * - `offset`: the host renders `translate` from its own `offset` — the drag paints\n * `offset + travel` and leaves it for the host's commit to own.\n */\n paint?: \"delta\" | \"offset\";\n /** The host's committed translate (`paint: \"offset\"`). */\n offset?: { x: number; y: number };\n /** The window's box at the press. Default: the element's viewport rect. */\n getRect?: () => DragRect;\n /** Keep every painted box legal (e.g. `clampRectToViewport`). */\n constrain?: (next: DragRect, gesture: DragGesture, origin: DragRect) => DragRect;\n /** Resize size limits. */\n limits?: SizeLimits;\n /** Cursor held while moving. Default `grabbing` (resizes hold their edge's cursor). */\n cursor?: DragCursor;\n /** A press is starting a gesture (focus or raise the window here). */\n onPress?: (event: ReactPointerEvent<HTMLElement>, gesture: DragGesture) => void;\n /** Every painted frame — for observers that are NOT React state. */\n onFrame?: (rect: DragRect, gesture: DragGesture) => void;\n /** Once per gesture that moved, on release. Commit the host's state here. */\n onCommit: (rect: DragRect, commit: DragCommit) => void;\n}\n\nexport interface DragMoveApi {\n /** Spread onto the element you drag BY: `onPointerDown={drag.onPointerDown}`. */\n onPointerDown: (event: ReactPointerEvent<HTMLElement>) => void;\n /** `onPointerDown` for the handle that resizes from `edge`. */\n resizeHandle: (edge: ResizeEdge) => (event: ReactPointerEvent<HTMLElement>) => void;\n /** True from the moment a press becomes a drag until release. */\n dragging: boolean;\n /** Abandon a drag in flight (the window closed): nothing is committed, the cursor is released. */\n cancel: () => void;\n}\n\n/** Drag and resize a floating element without re-rendering it while the pointer moves. */\nexport function useDragMove(options: UseDragMoveOptions): DragMoveApi {\n const live = useRef(options);\n useLayoutEffect(() => {\n live.current = options;\n });\n const [dragging, setDragging] = useState(false);\n const gestureRef = useRef<PointerDragHandle | null>(null);\n /** The translate to put back once the commit has rendered (`paint: \"delta\"`). */\n const restoreRef = useRef<{ element: HTMLElement; translate: string } | null>(null);\n\n useLayoutEffect(() => {\n const restore = restoreRef.current;\n if (!restore) return;\n restoreRef.current = null;\n restore.element.style.translate = restore.translate;\n });\n\n useEffect(\n () => () => {\n gestureRef.current?.cancel();\n gestureRef.current = null;\n },\n [],\n );\n\n const begin = useCallback((event: ReactPointerEvent<HTMLElement>, gesture: DragGesture) => {\n const opts = live.current;\n const element = opts.element;\n if (opts.enabled === false || !element || event.button !== 0) return;\n if (opts.touch === false && event.pointerType === \"touch\") return;\n const target = event.target instanceof Element ? event.target : null;\n const ignore = opts.ignore === undefined ? DRAG_IGNORE_SELECTOR : opts.ignore;\n if (gesture === \"move\" && ignore && target) {\n const hit = target.closest(ignore);\n if (hit && hit !== event.currentTarget && event.currentTarget.contains(hit)) return;\n }\n // A press on bare chrome must not start a text selection; a press on a control keeps its default.\n if (gesture !== \"move\" || !target?.closest(\"button,a,input,select,textarea,label,[role=button]\")) event.preventDefault();\n if (gesture !== \"move\") event.stopPropagation();\n gestureRef.current?.cancel();\n opts.onPress?.(event, gesture);\n if (opts.announce !== false) announceLayerFront(element);\n\n const origin = opts.getRect?.() ?? (() => {\n const rect = element.getBoundingClientRect();\n return { x: rect.left, y: rect.top, width: rect.width, height: rect.height };\n })();\n const paintMode = opts.paint ?? \"delta\";\n const base = paintMode === \"offset\" ? (opts.offset ?? { x: 0, y: 0 }) : { x: 0, y: 0 };\n const baseTranslate = element.style.translate;\n let latest = origin;\n\n gestureRef.current = startPointerDrag(event, {\n threshold: opts.threshold ?? 0,\n cursor: gesture === \"move\" ? (opts.cursor ?? \"grabbing\") : RESIZE_EDGE_CURSOR[gesture],\n onStart: () => setDragging(true),\n onMove: ({ dx, dy }) => {\n const now = live.current;\n const raw =\n gesture === \"move\"\n ? { ...origin, x: origin.x + dx, y: origin.y + dy }\n : resizeRect(origin, gesture, dx, dy, now.limits);\n latest = now.constrain ? now.constrain(raw, gesture, origin) : raw;\n element.style.translate = `${base.x + latest.x - origin.x}px ${base.y + latest.y - origin.y}px`;\n if (gesture !== \"move\") {\n element.style.width = `${latest.width}px`;\n element.style.height = `${latest.height}px`;\n }\n now.onFrame?.(latest, gesture);\n },\n onEnd: (_delta, { moved, started }) => {\n gestureRef.current = null;\n if (started) setDragging(false);\n if (!moved) return;\n if (paintMode === \"delta\") restoreRef.current = { element, translate: baseTranslate };\n const delta = { dx: latest.x - origin.x, dy: latest.y - origin.y };\n live.current.onCommit(latest, {\n origin,\n gesture,\n delta,\n offset: { x: base.x + delta.dx, y: base.y + delta.dy },\n });\n },\n });\n }, []);\n\n const onPointerDown = useCallback((event: ReactPointerEvent<HTMLElement>) => begin(event, \"move\"), [begin]);\n const resizeHandle = useCallback(\n (edge: ResizeEdge) => (event: ReactPointerEvent<HTMLElement>) => begin(event, edge),\n [begin],\n );\n\n const cancel = useCallback(() => {\n if (!gestureRef.current) return;\n gestureRef.current.cancel();\n gestureRef.current = null;\n setDragging(false);\n }, []);\n\n return { onPointerDown, resizeHandle, dragging, cancel };\n}\n","/**\n * THE DRAG CURSOR HOLD — the ONE way a drag sets its cursor (THE CURSOR LAW,\n * common-docs/policies/cursor-law.md).\n *\n * A cursor set on the dragged element flickers: the pointer outruns the\n * element, crosses a button or a field, and the cursor changes under it. So a\n * drag holds its cursor on `<html data-dragging=\"…\">` for its whole duration,\n * and `styles.css` § THE CURSOR LAW pins that cursor on every element,\n * important, in the first layer (`matrx-tap-lock`), so nothing — not a\n * utility, not the tap lock's own `cursor: pointer !important` — can override\n * it mid-drag.\n *\n * const release = holdDragCursor(); // pointerdown\n * … // pointermove\n * release(); // pointerup / pointercancel\n *\n * Holds nest: the newest hold's cursor shows, and the attribute clears only\n * when every hold has released. A release is idempotent.\n *\n * Inside a dnd-kit `<DndContext>`, render `<DragCursorMonitor />` (from\n * `./drag-cursor-monitor`) instead of calling this by hand.\n */\n\nexport const DRAG_CURSORS = [\n \"grabbing\",\n \"move\",\n \"col-resize\",\n \"row-resize\",\n \"ew-resize\",\n \"ns-resize\",\n \"nwse-resize\",\n \"nesw-resize\",\n] as const;\n\nexport type DragCursor = (typeof DRAG_CURSORS)[number];\n\nconst holds: { id: number; cursor: DragCursor }[] = [];\nlet nextId = 0;\n\nfunction apply(): void {\n if (typeof document === \"undefined\") return;\n const root = document.documentElement;\n const top = holds[holds.length - 1];\n if (top) root.dataset.dragging = top.cursor;\n else delete root.dataset.dragging;\n}\n\n/** Hold `cursor` on the whole document until the returned release is called. */\nexport function holdDragCursor(cursor: DragCursor = \"grabbing\"): () => void {\n const id = nextId++;\n holds.push({ id, cursor });\n apply();\n let released = false;\n return () => {\n if (released) return;\n released = true;\n const index = holds.findIndex((hold) => hold.id === id);\n if (index >= 0) holds.splice(index, 1);\n apply();\n };\n}\n","\"use client\";\n\n/**\n * FLOATING LAYERS OPENED FROM INSIDE A MODAL — one contract, every surface.\n *\n * A blocking surface (a `modal` Dialog, AlertDialog, Sheet, Drawer,\n * BottomSheet, CommandDialog — and every Dialog on a phone) paints a scrim at\n * the modal tier, `MODAL_LAYER_Z`. Radix children of that surface (Popover,\n * Select, menus) are safe: they portal into it or after it at the same z, and\n * Radix counts a press inside them as inside. A floating layer that is NOT a\n * Radix child — a host window manager's window, the associations picker\n * window, anything `createPortal`ed to `<body>` at its own z — was not: it\n * painted UNDER the scrim (a window manager lives near z-1000), so the click\n * that picked an option landed on the scrim and closed the modal (Source\n * screen side sheet + association picker, 2026-09-26). Behind the scrim it\n * would also have lost focus to the modal's trap and had presses inside it\n * counted as outside-clicks.\n *\n * The contract, in three parts:\n *\n * 1. Every modal content registers while it is open (`useModalLayer`), and\n * treats a press or focus inside any `[data-matrx-floating-layer]` as\n * inside (`keepFloatingLayersInside`).\n * 2. A floating layer reads `useFloatingLayerZIndex(ownZ)`: while a modal is\n * open it is lifted to the modal tier. Equal z, so DOM order decides — a\n * layer opened AFTER the modal (portal appended later) paints above its\n * scrim; a window that was already open stays underneath, as it should.\n * While lifted, several floating layers order by when they opened, not by\n * their own manager's focus order; that returns when the modal closes.\n * 3. A floating layer's root is wrapped in `<FloatingLayer>`: it carries the\n * marker attribute, re-asserts `pointer-events: auto` (a modal sets `none`\n * on `<body>`), and mounts a non-trapping focus scope, which pauses the\n * modal's focus trap while the layer is open so its inputs take focus.\n *\n * 4. Popper content (a Popover, a combobox) a floating layer opens is portaled\n * to <body>; while a floating layer is open it counts as part of it, and\n * wheel/touchmove inside either stops at <body> so the modal's scroll lock\n * never cancels it.\n *\n * Guard: `floating-layer.test.tsx` — a window-manager-style layer opened from\n * each blocking surface must stack above the scrim, keep the modal open when\n * it or a popover it opened is pressed, scroll, keep focus in its own input,\n * and hand focus back to its opener when it closes.\n */\n\nimport { FocusScope } from \"@radix-ui/react-focus-scope\";\nimport { Slot } from \"@radix-ui/react-slot\";\nimport * as React from \"react\";\n\n/** The modal tier: every blocking scrim and its content sit here. */\nexport const MODAL_LAYER_Z = 10000;\n\n/** THE tooltip layer (defined beside the tooltips, `title-tooltips.ts`). */\nexport { TOOLTIP_LAYER_Z } from \"./title-tooltips\";\n\n/** Marker attribute on the root of a floating layer. */\nexport const FLOATING_LAYER_ATTR = \"data-matrx-floating-layer\";\n\n// ── the open-modal registry ─────────────────────────────────────────────────\n// Shared identity across independently bundled public entrypoints, like the\n// dialog contexts: two copies of this module must see one count.\ninterface ModalLayerRegistry {\n count: number;\n listeners: Set<() => void>;\n}\nconst REGISTRY_SLOT = Symbol.for(\"ai-matrx.design-system.modal-layer-registry\");\nconst registryHost = globalThis as typeof globalThis & {\n [REGISTRY_SLOT]?: ModalLayerRegistry;\n};\nconst registry: ModalLayerRegistry = (registryHost[REGISTRY_SLOT] ??= {\n count: 0,\n listeners: new Set(),\n});\n\nfunction emit(): void {\n for (const listener of registry.listeners) listener();\n}\n\n// A modal's scroll lock (react-remove-scroll) cancels wheel and touchmove on\n// `document` for anything outside the modal's own content — including a\n// floating layer opened from it, whose list then never scrolls. While a modal\n// is open, a scroll gesture inside a floating layer stops at <body>: React's\n// own portal listener on <body> still sees it (stopPropagation never stops\n// listeners on the same node), the lock on `document` never does.\nconst SCROLL_EVENTS = [\"wheel\", \"touchmove\"] as const;\nfunction stopAtBody(event: Event): void {\n if (isInsideFloatingLayer(event.target)) event.stopPropagation();\n}\nfunction setScrollPassthrough(on: boolean): void {\n if (typeof document === \"undefined\" || !document.body) return;\n for (const type of SCROLL_EVENTS) {\n if (on) document.body.addEventListener(type, stopAtBody, { passive: true });\n else document.body.removeEventListener(type, stopAtBody);\n }\n}\n\n/** Register one open modal layer; returns its release. */\nexport function registerModalLayer(): () => void {\n registry.count += 1;\n if (registry.count === 1) setScrollPassthrough(true);\n emit();\n let released = false;\n return () => {\n if (released) return;\n released = true;\n registry.count = Math.max(0, registry.count - 1);\n if (registry.count === 0) setScrollPassthrough(false);\n emit();\n };\n}\n\n/** True while at least one blocking surface is open. */\nexport function isModalLayerOpen(): boolean {\n return registry.count > 0;\n}\n\nfunction subscribe(listener: () => void): () => void {\n registry.listeners.add(listener);\n return () => registry.listeners.delete(listener);\n}\n\n/** Reactive `isModalLayerOpen()`. */\nexport function useModalLayerOpen(): boolean {\n return React.useSyncExternalStore(subscribe, isModalLayerOpen, () => false);\n}\n\n/**\n * Called by every modal content while it is mounted. `active` is false for a\n * content whose root is not modal (a windowed dialog, a `modal={false}` sheet).\n */\nexport function useModalLayer(active: boolean): void {\n React.useLayoutEffect(() => (active ? registerModalLayer() : undefined), [active]);\n}\n\n// ── the outside-click guard ─────────────────────────────────────────────────\n\nconst POPPER_WRAPPER = \"[data-radix-popper-content-wrapper]\";\n\n/**\n * True when `target` is inside a floating layer — or inside popper content (a\n * Popover, a combobox list) while a floating layer is open. Popper content a\n * window opens is portaled to <body>, outside the window's own element and\n * outside the modal's React tree; popper content the MODAL opens is portaled\n * into the modal and never reaches this check.\n */\nexport function isInsideFloatingLayer(target: EventTarget | null | undefined): boolean {\n if (!(target instanceof Element)) return false;\n if (target.closest(`[${FLOATING_LAYER_ATTR}]`)) return true;\n return (\n target.closest(POPPER_WRAPPER) !== null &&\n target.ownerDocument.querySelector(`[${FLOATING_LAYER_ATTR}]`) !== null\n );\n}\n\n/**\n * Wrap a Radix `onInteractOutside` so a press or focus inside a floating layer\n * never dismisses the modal. The caller's handler still runs first.\n */\nexport function keepFloatingLayersInside<\n E extends { target: EventTarget | null; preventDefault: () => void },\n>(handler?: (event: E) => void): (event: E) => void {\n return (event) => {\n handler?.(event);\n if (isInsideFloatingLayer(event.target)) event.preventDefault();\n };\n}\n\n// ── the floating layer's side ───────────────────────────────────────────────\n\n/** Pure form of `useFloatingLayerZIndex`, for callers outside React. */\nexport function floatingLayerZIndex(ownZ: number, modalOpen: boolean): number {\n return modalOpen ? Math.max(ownZ, MODAL_LAYER_Z) : ownZ;\n}\n\n/** The z-index a floating layer should paint at, given its own. */\nexport function useFloatingLayerZIndex(ownZ: number): number {\n return floatingLayerZIndex(ownZ, useModalLayerOpen());\n}\n\nconst preventAutoFocus = (event: Event) => event.preventDefault();\n\n/**\n * Wrap the root element of a floating layer (exactly one element child).\n * Marks it, keeps it pressable under a modal's `pointer-events: none` body,\n * and pauses the modal's focus trap while it is mounted. It never takes focus\n * on open. On close, if focus was lost with it while a modal is still open,\n * focus returns to the control that opened it — otherwise the next Tab would\n * land behind the modal.\n */\nexport const FloatingLayer = React.forwardRef<\n HTMLElement,\n { children: React.ReactElement }\n>(({ children }, ref) => {\n const [opener] = React.useState<Element | null>(() =>\n typeof document === \"undefined\" ? null : document.activeElement,\n );\n const returnFocus = (event: Event) => {\n event.preventDefault();\n const active = document.activeElement;\n const lost = !active || active === document.body || !active.isConnected;\n if (lost && isModalLayerOpen() && opener instanceof HTMLElement && opener.isConnected) {\n opener.focus({ preventScroll: true });\n }\n };\n return (\n <FocusScope\n asChild\n trapped={false}\n loop={false}\n onMountAutoFocus={preventAutoFocus}\n onUnmountAutoFocus={returnFocus}\n >\n <Slot\n ref={ref}\n {...{ [FLOATING_LAYER_ATTR]: \"\" }}\n style={{ pointerEvents: \"auto\" }}\n >\n {children}\n </Slot>\n </FocusScope>\n );\n});\nFloatingLayer.displayName = \"FloatingLayer\";\n\n// ── THE Escape stack ────────────────────────────────────────────────────────\n// One Escape owner for every floating window (summon's WindowPanel and\n// LiteWindow, the PeekWindow here): the TOPMOST open layer gets the key, and\n// only it — two windows never close on one press, and a window under another\n// never closes first. A layer joins on open (top), `raise()`s when it comes to\n// the front (a focused window), and leaves on close. Its handler decides\n// whether it closes (a menu or dialog it does not own may hold the key) and\n// calls `preventDefault()` when it does; a layer that declines still keeps the\n// key from the layers under it. One window listener, shared across bundled\n// copies of this module through a global slot (like the modal registry).\ninterface EscapeLayerEntry {\n readonly key: symbol;\n handle: (event: KeyboardEvent) => void;\n}\ninterface EscapeStack {\n layers: EscapeLayerEntry[];\n listening: boolean;\n}\nconst ESCAPE_SLOT = Symbol.for(\"ai-matrx.design-system.escape-stack\");\nconst escapeHost = globalThis as typeof globalThis & { [ESCAPE_SLOT]?: EscapeStack };\nconst escapeStack = (): EscapeStack => (escapeHost[ESCAPE_SLOT] ??= { layers: [], listening: false });\n\nfunction onEscapeKeydown(event: KeyboardEvent): void {\n if (event.key !== \"Escape\" || event.defaultPrevented) return;\n const { layers } = escapeStack();\n layers[layers.length - 1]?.handle(event);\n}\n\nexport interface EscapeLayerHandle {\n /** Move this layer to the top (it came to the front). */\n raise(): void;\n /** Leave the stack (closed). */\n release(): void;\n}\n\n/** Join the Escape stack at the top. The handler runs only while this layer is topmost. */\nexport function pushEscapeLayer(handle: (event: KeyboardEvent) => void): EscapeLayerHandle {\n const stack = escapeStack();\n if (!stack.listening && typeof window !== \"undefined\") {\n window.addEventListener(\"keydown\", onEscapeKeydown);\n stack.listening = true;\n }\n const entry: EscapeLayerEntry = { key: Symbol(\"escape-layer\"), handle };\n stack.layers.push(entry);\n const drop = () => {\n const at = stack.layers.indexOf(entry);\n if (at !== -1) stack.layers.splice(at, 1);\n };\n return {\n raise() {\n drop();\n stack.layers.push(entry);\n },\n release: drop,\n };\n}\n\n/** How many layers hold the Escape stack (tests and diagnostics). */\nexport function escapeLayerDepth(): number {\n return escapeStack().layers.length;\n}\n\n/**\n * Hold a place in the Escape stack while `active`. The latest `onEscape` runs\n * (never a stale closure). `raiseKey`: when it changes the layer moves to the\n * top (pass a window manager's z-index). Returns a stable `raise()` for a\n * layer that tracks \"front\" itself (a pointerdown on the window).\n */\nexport function useEscapeLayer(active: boolean, onEscape: (event: KeyboardEvent) => void, raiseKey?: unknown): () => void {\n const latest = React.useRef(onEscape);\n latest.current = onEscape;\n const handleRef = React.useRef<EscapeLayerHandle | null>(null);\n React.useEffect(() => {\n if (!active) return undefined;\n const handle = pushEscapeLayer((event) => latest.current(event));\n handleRef.current = handle;\n return () => {\n handle.release();\n handleRef.current = null;\n };\n }, [active]);\n const first = React.useRef(true);\n React.useEffect(() => {\n if (first.current) {\n first.current = false;\n return;\n }\n handleRef.current?.raise();\n }, [raiseKey]);\n return React.useCallback(() => handleRef.current?.raise(), []);\n}\n","/**\n * THE TITLE TAKEOVER — every native `title` attribute in the document shows\n * as THE fleet tooltip instead of the browser's.\n *\n * Why this exists. A `title=` is the one tooltip nobody has to import, so it\n * is what every hand-written control reaches for: ~50 of them on an ordinary\n * matrx-frontend page (2026-09-28), next to the Radix tooltips on the tap\n * buttons. The browser draws those as a slow, unstyled system box, and a page\n * that mixes the two reads as having \"lost all of its tooltips\" (Arman,\n * 2026-09-28). Asking every author — human or agent — to wrap every control in\n * `<Tooltip>` is a rule that is broken the day it is written. So the\n * `TooltipProvider` every host already mounts at its root installs this layer,\n * and a `title` is simply a tooltip from then on. Nothing to remember.\n *\n * How it works. On hover (mouse or pen) or keyboard focus (`:focus-visible`)\n * of an element that carries a `title`, the attribute is lifted onto\n * `data-matrx-title` for exactly as long as the pointer or focus stays — so\n * the browser has nothing to show — and one shared, script-placed element\n * wearing `.matrx-tooltip` shows the text instead. When the pointer or focus\n * leaves, the `title` is put back, so assistive technology and every\n * `[title]` selector read the element exactly as authored the rest of the\n * time. Touch never shows it (a `title` has no touch affordance either).\n *\n * What it does not draw: a tooltip that only repeats text already readable in\n * full inside the element (it still draws when that text is hidden or\n * truncated).\n *\n * What it leaves alone:\n * - an element that is already a Radix tooltip trigger\n * (`[data-matrx-tooltip-trigger]`, stamped by `TooltipTrigger`): its\n * `title` is still lifted — two tooltips on one control was the other\n * half of the mess — but only the Radix one shows;\n * - anything inside `[data-native-title]` (the explicit opt-out);\n * - SVG `<title>` children, which are elements, not attributes.\n *\n * Placement. `tooltipSide` (THE SMART SIDE, below): beside a control in a\n * vertical stack, else the host's side; flipped when there is no room,\n * clamped into the viewport. `data-title-side=\"right\" | \"left\" | \"bottom\" |\n * \"top\"` on the element or any ancestor states a preferred side — a vertical\n * rail sets `right` once on its container.\n *\n * Installed at most once per document, reference-counted across every\n * mounted provider, and removed when the last one unmounts.\n */\n\n/**\n * THE SMART SIDE (Arman, 2026-10-15: tooltips \"don't show up intelligently\"). A tooltip never\n * covers the control next to its own. Where the control's neighbours stand decides the side:\n * - an explicit side (a prop, or `data-title-side` on the control or an ancestor below <html>) wins;\n * - an icon-sized control in a vertical stack (an icon column, a tool palette) has its neighbours\n * above and below, so it opens beside the control: right, or left when the control is in the\n * window's right half (an inspector column). A wide row in a list keeps the host's side: its\n * tooltip is the row's own text in full, and beside it would sit over the page next to the list;\n * - anywhere else (a toolbar, a row of buttons, a lone control) it opens on the host's default\n * side (`data-title-side` on <html>: macOS desktop hosts say \"bottom\"; the web's is \"top\").\n * Either way it flips to the other side when there is no room, and stays inside the window.\n */\nexport function tooltipSide(el: Element | null, fallback?: Side): Side {\n if (!el) return fallback ?? \"top\";\n const doc = el.ownerDocument;\n const hinted = el.closest(\"[data-title-side]\");\n const hint = hinted?.getAttribute(\"data-title-side\");\n const isSide = (v: string | null | undefined): v is Side => v === \"top\" || v === \"bottom\" || v === \"left\" || v === \"right\";\n if (hinted && hinted !== doc.documentElement && isSide(hint)) return hint;\n const base: Side = fallback ?? (isSide(hint) ? hint : \"top\");\n const box = el.getBoundingClientRect();\n if (box.width <= ICON_CONTROL_MAX_PX && stackDirection(el) === \"vertical\") {\n const vw = doc.defaultView?.innerWidth ?? 0;\n return vw > 0 && box.left + box.width / 2 > vw / 2 ? \"left\" : \"right\";\n }\n return base;\n}\n\n/** The widest control that counts as an icon (a navigator item, a palette tool). */\nconst ICON_CONTROL_MAX_PX = 64;\n\n/** How the control's nearest group of siblings is laid out, from where they actually are on screen. */\nfunction stackDirection(el: Element): \"vertical\" | \"horizontal\" | null {\n let node: Element | null = el;\n for (let depth = 0; node && depth < 4; depth++, node = node.parentElement) {\n const parent: Element | null = node.parentElement;\n if (!parent) return null;\n const me = node.getBoundingClientRect();\n if (me.width === 0 && me.height === 0) return null;\n let vertical = 0;\n let horizontal = 0;\n for (const sib of Array.from(parent.children)) {\n if (sib === node) continue;\n const r = sib.getBoundingClientRect();\n if (r.width === 0 || r.height === 0) continue;\n const overlapX = Math.min(me.right, r.right) - Math.max(me.left, r.left);\n const overlapY = Math.min(me.bottom, r.bottom) - Math.max(me.top, r.top);\n if (overlapX > 0.5 * Math.min(me.width, r.width) && overlapY <= 0) vertical++;\n else if (overlapY > 0.5 * Math.min(me.height, r.height) && overlapX <= 0) horizontal++;\n }\n if (vertical > 0 && horizontal === 0) return \"vertical\";\n if (horizontal > 0) return \"horizontal\";\n }\n return null;\n}\n\nexport const TITLE_TOOLTIP_ATTR = \"data-matrx-title\";\nexport const TOOLTIP_TRIGGER_ATTR = \"data-matrx-tooltip-trigger\";\nexport const NATIVE_TITLE_OPT_OUT_ATTR = \"data-native-title\";\n\nexport type Side = \"top\" | \"bottom\" | \"left\" | \"right\";\n\nconst OPEN_DELAY_MS = 350;\n/** Moving from one titled control to the next inside this window is instant. */\nconst SKIP_DELAY_MS = 500;\n/**\n * THE HOVER BRIDGE. Leaving the control does not close the tooltip at once: the pointer has this\n * long to reach the tooltip itself (Arman, 2026-10-14: a tooltip must stay long enough to put the\n * mouse on it and copy its text). Entering the tooltip holds it open.\n */\n/**\n * THE TOOLTIP LAYER — above every other layer, always (Arman, 2026-10-14: a tooltip \"coming up\n * behind the content\"). Menus and popovers share the modal tier (equal z, DOM order decides), so a\n * tooltip on that tier lost to any menu opened after it. A tooltip is transient and never takes a\n * press, so nothing ever needs to sit above it.\n */\nexport const TOOLTIP_LAYER_Z = 2_147_483_000;\n\nexport const TOOLTIP_CLOSE_DELAY_MS = 300;\nconst GAP_PX = 6;\nconst EDGE_PX = 8;\n/** How far every tooltip stays from the window's edge (both implementations). */\nexport const TOOLTIP_EDGE_PX = EDGE_PX;\n/**\n * A tooltip is a short hint, never a paragraph (Apple HIG: a tooltip is a few words): text past\n * this budget is cut at a word boundary with an ellipsis. Long detail belongs in a sheet or a\n * Copy details action, not on hover.\n */\nexport const TOOLTIP_TEXT_BUDGET = 140;\n\nexport function clipTooltipText(text: string, budget: number = TOOLTIP_TEXT_BUDGET): string {\n const flat = text.replace(/\\s+/g, \" \").trim();\n if (flat.length <= budget) return flat;\n const cut = flat.slice(0, budget - 1);\n const space = cut.lastIndexOf(\" \");\n return `${(space > budget * 0.6 ? cut.slice(0, space) : cut).replace(/[\\s,.;:–—-]+$/, \"\")}…`;\n}\n\nconst SURFACE_CLASS =\n \"matrx-tooltip matrx-title-tooltip matrx-motion-popper max-w-xs select-text rounded-md border border-border bg-popover px-2.5 py-1 text-xs font-medium text-popover-foreground\";\n\ninterface Installation {\n count: number;\n uninstall: () => void;\n}\n\n/**\n * Keyed on the document itself through a registered symbol, never a module\n * WeakMap: tsup bundles this module into more than one entry (`index`,\n * `tap-target`), and two module copies each holding their own map would\n * install twice — two listeners, two surfaces.\n */\nconst INSTALLATION_KEY = Symbol.for(\"@ai-matrx/design-system/title-tooltips\");\ntype DocumentWithInstallation = Document & { [INSTALLATION_KEY]?: Installation };\nconst installations = {\n get: (doc: Document) => (doc as DocumentWithInstallation)[INSTALLATION_KEY],\n set: (doc: Document, value: Installation) => {\n (doc as DocumentWithInstallation)[INSTALLATION_KEY] = value;\n },\n delete: (doc: Document) => {\n delete (doc as DocumentWithInstallation)[INSTALLATION_KEY];\n },\n};\n\n/** Install the takeover on `doc`. Returns the release function. */\nexport function acquireTitleTooltips(doc: Document | undefined = typeof document === \"undefined\" ? undefined : document): () => void {\n if (!doc) return () => {};\n const existing = installations.get(doc);\n if (existing) {\n existing.count += 1;\n } else {\n installations.set(doc, { count: 1, uninstall: install(doc) });\n }\n let released = false;\n return () => {\n if (released) return;\n released = true;\n const current = installations.get(doc);\n if (!current) return;\n current.count -= 1;\n if (current.count <= 0) {\n current.uninstall();\n installations.delete(doc);\n }\n };\n}\n\nfunction install(doc: Document): () => void {\n const win = doc.defaultView;\n let active: HTMLElement | null = null;\n let surface: HTMLDivElement | null = null;\n let openTimer: ReturnType<typeof setTimeout> | undefined;\n let closeTimer: ReturnType<typeof setTimeout> | undefined;\n let lastClosedAt = 0;\n /** A press began on the tooltip (selecting its text): it must not close until release. */\n let holding = false;\n\n const HTMLElementCtor = win?.HTMLElement;\n\n const titledAncestor = (node: EventTarget | null): HTMLElement | null => {\n if (!HTMLElementCtor || !(node instanceof win!.Node)) return null;\n const start = node instanceof HTMLElementCtor ? node : (node as Node).parentElement;\n if (!start) return null;\n const el = start.closest<HTMLElement>(`[title], [${TITLE_TOOLTIP_ATTR}]`);\n if (!el || !(el instanceof HTMLElementCtor)) return null;\n if (el.closest(`[${NATIVE_TITLE_OPT_OUT_ATTR}]`)) return null;\n return el;\n };\n\n const textOf = (el: HTMLElement) => clipTooltipText(el.getAttribute(TITLE_TOOLTIP_ATTR) ?? el.getAttribute(\"title\") ?? \"\");\n\n const lift = (el: HTMLElement) => {\n const title = el.getAttribute(\"title\");\n if (title === null) return;\n el.setAttribute(TITLE_TOOLTIP_ATTR, title);\n el.removeAttribute(\"title\");\n };\n\n const restore = (el: HTMLElement) => {\n const held = el.getAttribute(TITLE_TOOLTIP_ATTR);\n if (held === null) return;\n // An author who changed or removed the title while it was lifted wins:\n // only put ours back when nothing re-set it in the meantime.\n if (!el.hasAttribute(\"title\")) el.setAttribute(\"title\", held);\n el.removeAttribute(TITLE_TOOLTIP_ATTR);\n };\n\n const ensureSurface = () => {\n if (surface && surface.isConnected) return surface;\n surface = doc.createElement(\"div\");\n surface.setAttribute(\"role\", \"tooltip\");\n surface.setAttribute(\"data-slot\", \"title-tooltip\");\n surface.className = SURFACE_CLASS;\n surface.style.position = \"fixed\";\n surface.style.zIndex = String(TOOLTIP_LAYER_Z);\n surface.style.visibility = \"hidden\";\n doc.body.appendChild(surface);\n return surface;\n };\n\n /**\n * THE PART OF `el` A PERSON CAN SEE: its box clipped by every ancestor that clips (scrolls or hides\n * overflow) and by the window. A truncated cell in a sideways-scrolling table is far wider than its\n * visible part; anchored to the whole box the tooltip landed at the window's edge (2026-10-14).\n */\n const visibleRect = (el: HTMLElement, vw: number, vh: number) => {\n const box = el.getBoundingClientRect();\n let left = box.left;\n let top = box.top;\n let right = box.right;\n let bottom = box.bottom;\n for (let node = el.parentElement; node && node !== doc.body && node !== doc.documentElement; node = node.parentElement) {\n const cs = win?.getComputedStyle(node);\n if (!cs) break;\n const clipsX = cs.overflowX !== \"visible\" || cs.overflow === \"hidden\";\n const clipsY = cs.overflowY !== \"visible\" || cs.overflow === \"hidden\";\n if (!clipsX && !clipsY) continue;\n const clip = node.getBoundingClientRect();\n if (clipsX) { left = Math.max(left, clip.left); right = Math.min(right, clip.right); }\n if (clipsY) { top = Math.max(top, clip.top); bottom = Math.min(bottom, clip.bottom); }\n }\n left = Math.max(left, 0);\n top = Math.max(top, 0);\n right = Math.min(right, vw || right);\n bottom = Math.min(bottom, vh || bottom);\n // Nothing of it is visible (scrolled away under the pointer is impossible, but a test DOM can say so): the box itself.\n if (right <= left || bottom <= top) return box;\n return { left, top, right, bottom, width: right - left, height: bottom - top };\n };\n\n const preferredSide = (el: HTMLElement): Side => tooltipSide(el);\n\n const place = (el: HTMLElement, node: HTMLDivElement) => {\n // The VISIBLE viewport, not the window: inside a clipped host (the kind\n // sandbox frame is window-wide but shown only at its column) the visual\n // viewport is what the reader sees, so a tooltip never lands past it.\n const vw = win?.visualViewport?.width ?? win?.innerWidth ?? 0;\n const vh = win?.visualViewport?.height ?? win?.innerHeight ?? 0;\n const anchor = visibleRect(el, vw, vh);\n const box = node.getBoundingClientRect();\n const fits: Record<Side, boolean> = {\n top: anchor.top - GAP_PX - box.height >= EDGE_PX,\n bottom: anchor.bottom + GAP_PX + box.height <= vh - EDGE_PX,\n left: anchor.left - GAP_PX - box.width >= EDGE_PX,\n right: anchor.right + GAP_PX + box.width <= vw - EDGE_PX,\n };\n const opposite: Record<Side, Side> = { top: \"bottom\", bottom: \"top\", left: \"right\", right: \"left\" };\n const wanted = preferredSide(el);\n const side: Side = fits[wanted] ? wanted : fits[opposite[wanted]] ? opposite[wanted] : wanted;\n\n let x: number;\n let y: number;\n if (side === \"top\" || side === \"bottom\") {\n x = anchor.left + anchor.width / 2 - box.width / 2;\n y = side === \"top\" ? anchor.top - GAP_PX - box.height : anchor.bottom + GAP_PX;\n } else {\n y = anchor.top + anchor.height / 2 - box.height / 2;\n x = side === \"left\" ? anchor.left - GAP_PX - box.width : anchor.right + GAP_PX;\n }\n x = Math.min(Math.max(x, EDGE_PX), Math.max(EDGE_PX, vw - EDGE_PX - box.width));\n y = Math.min(Math.max(y, EDGE_PX), Math.max(EDGE_PX, vh - EDGE_PX - box.height));\n // Placed with `left`/`top`, NEVER `transform`: the open animation\n // (`.matrx-motion-popper`) animates `transform`, and a running animation\n // overrides an inline transform — the chip sat at the page's top-left\n // corner for the whole animation, then jumped to its control (2026-10-08).\n node.style.left = `${Math.round(x)}px`;\n node.style.top = `${Math.round(y)}px`;\n node.setAttribute(\"data-side\", side);\n };\n\n const isShown = (node: HTMLElement, root: HTMLElement) => {\n const rect = node.getBoundingClientRect();\n if (rect.width <= 0 || rect.height <= 0) return false;\n for (let cur: HTMLElement | null = node; cur; cur = cur === root ? null : cur.parentElement) {\n const cs = win?.getComputedStyle(cur);\n if (!cs) return false;\n if (cs.display === \"none\" || cs.visibility === \"hidden\" || Number(cs.opacity) === 0) return false;\n }\n return true;\n };\n\n /**\n * A tooltip that repeats text the person can already read in full is noise\n * (an expanded sidebar row, a \"Save\" button titled \"Save\"). It still shows\n * when that text is hidden (a collapsed rail's label) or cut off\n * (truncated) — the two cases a title exists for.\n */\n const isClipped = (host: HTMLElement, root: HTMLElement) => {\n for (let node: HTMLElement | null = host; node; node = node.parentElement) {\n if (node.scrollWidth > node.clientWidth + 1 && node.clientWidth > 0) return true;\n if (node.scrollHeight > node.clientHeight + 1 && node.clientHeight > 0) return true;\n if (node === root) break;\n }\n return false;\n };\n\n const repeatsVisibleText = (el: HTMLElement, text: string) => {\n const norm = (t: string) => t.replace(/\\s+/g, \" \").trim().toLowerCase();\n const want = norm(text);\n if (!want || !win) return false;\n const walker = doc.createTreeWalker(el, win.NodeFilter.SHOW_TEXT);\n for (let node = walker.nextNode(); node; node = walker.nextNode()) {\n if (norm(node.textContent ?? \"\") !== want) continue;\n const host = node.parentElement;\n if (!host || !isShown(host, el)) continue;\n // Cut off is measured on the BOX that clips: an inline host (a span inside a truncating\n // cell) has no box width of its own, so every ancestor up to the titled element is asked.\n if (isClipped(host, el)) continue;\n return true;\n }\n return false;\n };\n\n const show = (el: HTMLElement, instant: boolean) => {\n if (active !== el) return;\n // A Radix tooltip trigger shows its own tooltip — never a second one.\n if (el.closest(`[${TOOLTIP_TRIGGER_ATTR}]`)) return;\n const text = textOf(el);\n if (!text || !el.isConnected) return;\n if (repeatsVisibleText(el, text)) return;\n const node = ensureSurface();\n node.textContent = text;\n node.style.visibility = \"hidden\";\n // Measure and place BEFORE the open state starts the animation: measured\n // mid-animation the box reads at its 0.95 entry scale and lands off-centre.\n node.removeAttribute(\"data-state\");\n // The surface is ONE shared fixed element that keeps the `left` of its last\n // placement. Measured there, a longer text wraps against the room that is\n // left of the OLD spot, reads one line too tall, and lands a line too high\n // once it moves (the sandbox tooltip spec caught a 16px extra gap). Rewind\n // to the origin so the box is measured at its natural, unwrapped size.\n node.style.left = \"0px\";\n node.style.top = \"0px\";\n place(el, node);\n node.setAttribute(\"data-state\", instant ? \"instant-open\" : \"delayed-open\");\n node.style.visibility = \"visible\";\n if (el.id) node.id = `${el.id}-title-tooltip`;\n };\n\n const hide = () => {\n if (openTimer !== undefined) clearTimeout(openTimer);\n openTimer = undefined;\n cancelClose();\n holding = false;\n if (surface && surface.style.visibility === \"visible\") lastClosedAt = Date.now();\n if (surface) {\n surface.style.visibility = \"hidden\";\n surface.removeAttribute(\"data-state\");\n }\n };\n\n const cancelClose = () => {\n if (closeTimer !== undefined) clearTimeout(closeTimer);\n closeTimer = undefined;\n };\n\n const inSurface = (node: EventTarget | null) =>\n !!surface && !!win && node instanceof win.Node && surface.contains(node);\n\n const hasSelectionInSurface = () => {\n const sel = win?.getSelection();\n return !!sel && !sel.isCollapsed && !!surface && !!sel.anchorNode && surface.contains(sel.anchorNode);\n };\n\n /** Close after the bridge delay unless the pointer reached the tooltip or text in it is selected. */\n const scheduleClose = () => {\n cancelClose();\n // Nothing is showing yet (the open delay has not run, or the text was not worth drawing): there is\n // nothing to bridge to, so leaving simply cancels.\n if (!surface || surface.style.visibility !== \"visible\") {\n deactivate();\n return;\n }\n closeTimer = setTimeout(() => {\n closeTimer = undefined;\n if (holding || hasSelectionInSurface()) return;\n deactivate();\n }, TOOLTIP_CLOSE_DELAY_MS);\n };\n\n const activate = (el: HTMLElement) => {\n cancelClose();\n if (active === el) return;\n deactivate();\n active = el;\n lift(el);\n const instant = Date.now() - lastClosedAt < SKIP_DELAY_MS;\n if (instant) show(el, true);\n else openTimer = setTimeout(() => show(el, false), OPEN_DELAY_MS);\n };\n\n const deactivate = () => {\n hide();\n if (active) restore(active);\n active = null;\n };\n\n // A touch has no hover: the tap that focuses a button must not open its tooltip, and a tooltip\n // that is open when a finger lands closes. The compat mouse events and the focus a tap leaves\n // behind used to pin \"Copy chart source\" over the chart title on a phone (review 5, G13).\n let lastTouchAt = Number.NEGATIVE_INFINITY;\n const TOUCH_FOCUS_WINDOW_MS = 1000;\n const onPointerOver = (e: PointerEvent) => {\n if (e.pointerType === \"touch\") {\n lastTouchAt = Date.now();\n if (active) deactivate();\n return;\n }\n if (inSurface(e.target)) {\n cancelClose();\n return;\n }\n if (holding || hasSelectionInSurface()) {\n // Text is being selected in the tooltip: another control passing under the pointer must not replace it.\n return;\n }\n const el = titledAncestor(e.target);\n if (el) activate(el);\n else if (active && closeTimer === undefined) scheduleClose();\n };\n\n const onPointerOut = (e: PointerEvent) => {\n if (!active) return;\n const next = e.relatedTarget;\n if (next instanceof win!.Node && (active.contains(next) || inSurface(next))) return;\n if (inSurface(e.target)) {\n if (holding) return;\n scheduleClose();\n return;\n }\n scheduleClose();\n };\n\n const onPointerDown = (e: PointerEvent) => {\n if (e.pointerType === \"touch\") lastTouchAt = Date.now();\n if (inSurface(e.target)) {\n // Selecting the tooltip's text: keep it open until the press ends.\n holding = true;\n cancelClose();\n return;\n }\n deactivate();\n };\n\n const onPointerUp = () => {\n if (!holding) return;\n holding = false;\n if (!hasSelectionInSurface()) scheduleClose();\n };\n\n const onFocusIn = (e: FocusEvent) => {\n if (Date.now() - lastTouchAt < TOUCH_FOCUS_WINDOW_MS) return;\n const el = titledAncestor(e.target);\n if (!el) return;\n let visible = true;\n try {\n visible = (e.target as Element).matches(\":focus-visible\");\n } catch {\n visible = true;\n }\n if (visible) activate(el);\n };\n\n const onFocusOut = (e: FocusEvent) => {\n if (!active) return;\n const next = e.relatedTarget;\n if (next instanceof win!.Node && active.contains(next)) return;\n deactivate();\n };\n\n const onDismiss = (e?: Event) => {\n if (e && inSurface(e.target)) return;\n deactivate();\n };\n const onKeyDown = (e: KeyboardEvent) => {\n if (e.key === \"Escape\") deactivate();\n };\n\n doc.addEventListener(\"pointerover\", onPointerOver, true);\n doc.addEventListener(\"pointerout\", onPointerOut, true);\n doc.addEventListener(\"focusin\", onFocusIn, true);\n doc.addEventListener(\"focusout\", onFocusOut, true);\n doc.addEventListener(\"pointerdown\", onPointerDown, true);\n doc.addEventListener(\"pointerup\", onPointerUp, true);\n doc.addEventListener(\"keydown\", onKeyDown, true);\n doc.addEventListener(\"scroll\", onDismiss, true);\n win?.addEventListener(\"blur\", onDismiss);\n\n return () => {\n deactivate();\n doc.removeEventListener(\"pointerover\", onPointerOver, true);\n doc.removeEventListener(\"pointerout\", onPointerOut, true);\n doc.removeEventListener(\"focusin\", onFocusIn, true);\n doc.removeEventListener(\"focusout\", onFocusOut, true);\n doc.removeEventListener(\"pointerdown\", onPointerDown, true);\n doc.removeEventListener(\"pointerup\", onPointerUp, true);\n doc.removeEventListener(\"keydown\", onKeyDown, true);\n doc.removeEventListener(\"scroll\", onDismiss, true);\n win?.removeEventListener(\"blur\", onDismiss);\n surface?.remove();\n surface = null;\n };\n}\n","/**\n * THE FOCUS-RETURN GUARD — a closing menu, popover, select or dialog never takes focus back from a\n * field the person has already moved into.\n *\n * Radix returns focus to the trigger when its content UNMOUNTS (FocusScope: a `setTimeout(0)` after the\n * exit animation, unconditionally). On a busy page that is hundreds of milliseconds after the person\n * picked an option — long enough for them to click the next field and start typing. The return then\n * lands mid-word: focus jumps to the trigger and every key after it is lost (\"https://drive…\" saved as\n * \"https:\", Applet social planner, 2026-10-08).\n *\n * `keepMovedFocus(handler)` composes a content's `onCloseAutoFocus`: when focus already sits on a live\n * element outside the closing content (not the page body), the return is canceled; otherwise Radix\n * returns focus to the trigger exactly as before (keyboard users closing with Escape keep their place).\n */\n/** True when focus has already moved to something the person chose, outside `container`. */\nexport function focusMovedElsewhere(container: EventTarget | null, doc: Document | undefined = typeof document === \"undefined\" ? undefined : document): boolean {\n if (!doc) return false;\n const active = doc.activeElement;\n if (!active || active === doc.body || active === doc.documentElement) return false;\n if (!active.isConnected) return false;\n if (container && typeof (container as Node).contains === \"function\" && (container as Node).contains(active)) return false;\n return true;\n}\n\n/** Compose a content's `onCloseAutoFocus` with THE FOCUS-RETURN GUARD (the caller's handler runs first). */\nexport function keepMovedFocus(handler?: (event: Event) => void): (event: Event) => void {\n return (event: Event) => {\n handler?.(event);\n if (event.defaultPrevented) return;\n const container = (event.currentTarget ?? event.target) as EventTarget | null;\n if (focusMovedElsewhere(container, (container as Node | null)?.ownerDocument ?? undefined)) event.preventDefault();\n };\n}\n","\"use client\";\n\n/**\n * Popover — ported verbatim from matrx-frontend `components/ui/popover.tsx`.\n *\n * Seam inversion: the host's `useNestedPortalContainer` (dialog/popout aware)\n * becomes the injected `PortalContainerProvider` seam (`portal-container.tsx`);\n * the explicit `container` prop keeps top priority, exactly as before.\n *\n * THE ROOT RENDERS UNCONDITIONALLY — no mount gate. This wrapper used to defer\n * rendering until after hydration (\"Radix generates dynamic aria-controls ids\n * that differ between SSR and client\"), and that justification was false:\n * Radix ids come from React's SSR-stable `useId` (verified against\n * @radix-ui/react-popover 1.1.17 / react-id 1.1.2). The gate was actively\n * harmful — the Trigger wraps ALWAYS-VISIBLE content, so `return null`\n * deleted it from SSR and the first client paint.\n */\n\nimport * as PopoverPrimitive from \"@radix-ui/react-popover\";\nimport * as React from \"react\";\n\nimport { cn } from \"./cn\";\nimport { MOTION_POPPER } from \"./motion\";\nimport { SOLID_SURFACE_CLASS, type PopoverSurface } from \"./solid-surface\";\nimport { usePortalContainer } from \"./portal-container\";\nimport { keepMovedFocus } from \"./focus-return\";\n\nexport const Popover = PopoverPrimitive.Root;\n\nexport const PopoverTrigger = PopoverPrimitive.Trigger;\n\nexport const PopoverAnchor = PopoverPrimitive.Anchor;\n\nexport interface PopoverContentProps\n extends React.ComponentPropsWithoutRef<typeof PopoverPrimitive.Content> {\n /** Explicit portal target; wins over the injected container. */\n container?: HTMLElement | null;\n /**\n * Package-owned open/close motion. Default `true`. Pass `false` for a\n * surface that must appear instantly — a picker re-anchoring while the user\n * types, a measurement pass. It is NOT the reduced-motion switch;\n * `styles.css` already honors `prefers-reduced-motion`.\n */\n animated?: boolean;\n /**\n * HOW WIDE THE POPOVER IS ALLOWED TO BE, and it is the SYSTEM that decides — never a\n * surface pasting its own `w-64` over the default (lane FIX-14, 2026-09-22).\n *\n * `\"fixed\"` (default) is the historical `w-72`: right for a menu of short, known\n * labels, where a ragged edge would look broken.\n *\n * `\"content\"` is for a popover whose whole job is to SHOW SOMETHING THE SYSTEM DID\n * NOT CHOOSE — a person's name, a record's title, a row the user is about to\n * create. The relation picker offered\n *\n * Create “Marisol Okonkwo — 418 Calle Pu\n *\n * inside a 16rem box, cut mid-word, on the one control that exists to show the name\n * being created. A fixed width cannot be right for content of unknown length, so\n * this one grows to its content between an honest floor and an honest ceiling:\n *\n * · at least the trigger's own width, and at least 20rem — the width Airtable's and\n * Notion's link-record pickers settle on, and wide enough that an ordinary\n * \"name — street, town\" fits on one line;\n * · at most 28rem, and never wider than the viewport less a 1rem gutter each side,\n * so it still fits a 375px phone with nothing running off the screen. The floor is\n * clamped by the same gutter, so on a very narrow screen the ceiling still wins.\n *\n * Beyond that ceiling the CONTENT truncates with an ellipsis and carries a `title`.\n * Growing, then ellipsis — never a mid-word cut.\n *\n * BOTH modes keep the phone gutter (2026-09-26): the box is never wider than the\n * viewport less 1rem each side, and Radix keeps it `collisionPadding` (16px) off every\n * screen edge. Measured at 375px before this: `w-72`/`w-80` callers landed flush on\n * the right edge (55→375) because collision padding was 0.\n */\n sizing?: \"fixed\" | \"content\";\n /**\n * The surface fill. `\"default\"` is the theme's popover surface (a host may render it\n * translucent / glass). `\"solid\"` is the OPAQUE surface — the popover token at full\n * alpha, no backdrop blur — for a menu that must read as paper over a cover image or a\n * busy page (a Notion-style ••• menu). Same option on `DropdownMenuContent`.\n */\n surface?: PopoverSurface;\n /**\n * A NAMED fixed width (0.68.22), for a `sizing=\"fixed\"` popover whose content needs more or\n * less room than the default `md` (18rem) — never a pasted `w-[260px]`. Every width keeps the\n * phone gutter (never wider than the viewport less 1rem each side). Derived from the call\n * sites: `xs` 12rem (a short menu), `sm` 15rem (a ••• menu), `md` 18rem (default),\n * `lg` 20rem (a small form), `xl` 26rem (a picker grid), `2xl` 34rem (a gallery).\n * Ignored when `sizing=\"content\"`.\n */\n width?: PopoverWidth;\n /**\n * The inner padding, named (0.68.22): `none` (the content draws its own — a command list, a\n * picker), `xs` 4px (a menu of rows), `sm` 8px, `md` 12px, `default` 16px.\n */\n padding?: PopoverPadding;\n}\n\nexport type PopoverWidth = \"xs\" | \"sm\" | \"md\" | \"lg\" | \"xl\" | \"2xl\";\nexport type PopoverPadding = \"none\" | \"xs\" | \"sm\" | \"md\" | \"default\";\n\n/** Literal class per width so a host's Tailwind scan of the package finds every one. */\nexport const POPOVER_WIDTH_CLASS: Record<PopoverWidth, string> = {\n xs: \"w-48\",\n sm: \"w-60\",\n md: \"w-72\",\n lg: \"w-80\",\n xl: \"w-[26rem]\",\n \"2xl\": \"w-[34rem]\",\n};\nexport const POPOVER_PADDING_CLASS: Record<PopoverPadding, string> = {\n none: \"p-0\",\n xs: \"p-1\",\n sm: \"p-2\",\n md: \"p-3\",\n default: \"p-4\",\n};\n\nexport const PopoverContent = React.forwardRef<\n React.ComponentRef<typeof PopoverPrimitive.Content>,\n PopoverContentProps\n>(\n (\n {\n className,\n align = \"center\",\n sideOffset = 4,\n container,\n animated = true,\n sizing = \"fixed\",\n surface = \"default\",\n width = \"md\",\n padding = \"default\",\n collisionPadding = 16,\n onCloseAutoFocus,\n ...props\n },\n ref,\n ) => {\n const portalContainer = usePortalContainer(container);\n return (\n <PopoverPrimitive.Portal container={portalContainer}>\n <PopoverPrimitive.Content\n ref={ref}\n align={align}\n sideOffset={sideOffset}\n collisionPadding={collisionPadding}\n data-surface={surface === \"solid\" ? \"solid\" : undefined}\n data-width={sizing === \"content\" ? undefined : width}\n data-padding={padding}\n className={cn(\n // Cap to the viewport space Radix measured and scroll — a popover taller\n // than the screen must never trap the user with unreachable content.\n // z must EQUAL the dialog layer (z-[10000]), never exceed it: with equal\n // z, DOM portal order decides, so a dialog opened FROM a popover stacks\n // above it, and a popover opened from a dialog still stacks above the\n // dialog. z-[10001] buried dialogs behind fullscreen popovers.\n \"z-[10000] max-h-[var(--radix-popover-content-available-height)] overflow-y-auto overscroll-contain rounded-md border bg-popover text-popover-foreground shadow-md outline-none\",\n POPOVER_PADDING_CLASS[padding],\n sizing === \"content\"\n ? \"w-auto min-w-[min(max(var(--radix-popover-trigger-width),20rem),calc(100vw-2rem))] max-w-[min(28rem,calc(100vw-2rem))]\"\n : cn(POPOVER_WIDTH_CLASS[width], \"max-w-[calc(100vw-2rem)]\"),\n surface === \"solid\" && SOLID_SURFACE_CLASS,\n animated && MOTION_POPPER,\n className,\n )}\n {...props}\n onCloseAutoFocus={keepMovedFocus(onCloseAutoFocus)}\n />\n </PopoverPrimitive.Portal>\n );\n },\n);\nPopoverContent.displayName = PopoverPrimitive.Content.displayName;\n","/**\n * The opaque surface option shared by every floating menu surface\n * (`PopoverContent`, `DropdownMenuContent`, `DropdownMenuSubContent`).\n * `data-surface=\"solid\"` is also styled in `styles.css`, so the fill holds even\n * where a host utility layer tints the default surface.\n */\nexport type PopoverSurface = \"default\" | \"solid\";\n\nexport const SOLID_SURFACE_CLASS =\n \"bg-[hsl(var(--popover)/1)] [backdrop-filter:none] [-webkit-backdrop-filter:none]\";\n","\"use client\";\n\nimport {\n cloneElement,\n forwardRef,\n isValidElement,\n useCallback,\n useRef,\n type ButtonHTMLAttributes,\n type ReactElement,\n type ReactNode,\n type Ref,\n} from \"react\";\n\nimport { Tooltip, TooltipContent, TooltipTrigger } from \"../tooltip\";\nimport { joinClassNames } from \"@ai-matrx/kit/dom\";\nimport { classNameMisuse, useTapGuardRef } from \"./tap-target-guard\";\nimport { useTapSurface } from \"./tap-surface\";\nimport {\n TAP_SOLID_TONE,\n TAP_TONE_CLASS,\n TapBadge,\n TapChevron,\n TapSpinner,\n formatTapShortcut,\n tooltipBody,\n useTapShortcut,\n type TapFeatureProps,\n type TapShortcut,\n type TapSolidTone,\n} from \"./tap-features\";\nimport {\n getTapTargetLinkComponent,\n type TapTargetLinkComponent,\n} from \"./link\";\n\nexport interface TapTargetButtonProps extends TapFeatureProps {\n icon?: React.ReactNode;\n children?: React.ReactNode;\n strokeWidth?: number | undefined;\n onClick?: (() => void) | undefined;\n className?: string | undefined;\n as?: \"button\" | \"label\" | undefined;\n htmlFor?: string | undefined;\n ariaLabel?: string | undefined;\n disabled?: boolean | undefined;\n /**\n * When set, the tap button renders as a link instead of a button.\n * - Internal hrefs (e.g. \"/tasks\") render via the injected link component\n * (`setTapTargetLinkComponent` / the `linkComponent` prop), falling back\n * to a plain `<a>` when none is registered.\n * - External hrefs (http://, https://, mailto:, tel:) render as `<a>`\n * with `target=\"_blank\"` and `rel=\"noopener noreferrer\"` by default.\n * - When combined with `disabled`, the trigger renders as a non-navigable\n * `<span aria-disabled=\"true\">` with the same visual styling.\n */\n href?: string | undefined;\n /** Override target. Works on both internal links and external anchors. */\n target?: \"_blank\" | \"_self\" | \"_parent\" | \"_top\" | undefined;\n /** Override rel. Works on both internal links and external anchors. */\n rel?: string | undefined;\n /** Forwarded to the injected link component. Pass `false` to disable prefetching. */\n prefetch?: boolean | null | undefined;\n /**\n * Per-instance link component for internal hrefs — overrides the\n * module-level `setTapTargetLinkComponent` registration.\n */\n linkComponent?: TapTargetLinkComponent | undefined;\n /**\n * Tooltip text. Defaults to `ariaLabel` when omitted.\n * EVERY tap button shows a tooltip (owner ruling 2026-10-01). `false` no\n * longer hides it: it renders the tooltip through `title` (the provider's\n * title takeover draws the same surface) — for a button nested inside\n * another `asChild` trigger, where the Tooltip wrapper cannot sit.\n */\n tooltip?: string | false | undefined;\n /** Tooltip placement. Defaults to \"top\". */\n tooltipSide?: \"top\" | \"right\" | \"bottom\" | \"left\" | undefined;\n /** Tooltip alignment along its side. Defaults to \"center\". */\n tooltipAlign?: \"start\" | \"center\" | \"end\" | undefined;\n /**\n * Visible caption rendered inline after the icon (`[icon Label]`).\n * Widens the pill automatically. Tooltip defaults to off when set — the\n * label is self-describing. Visible text becomes the accessible name.\n */\n label?: string | undefined;\n /**\n * Collapse an icon + caption pill to its icon-only 44px tap target below\n * the `sm` breakpoint. The caption and inline geometry return at `sm+`;\n * `ariaLabel` (falling back to `label`) remains the accessible name.\n */\n mobileIconOnly?: boolean | undefined;\n}\n\nexport interface TapTargetButtonSolidProps extends Omit<TapTargetButtonProps, \"tone\"> {\n /** The fill, from the system's list. Replaces bgColor / iconColor / hover / active. */\n tone?: TapSolidTone | undefined;\n bgColor?: string | undefined;\n iconColor?: string | undefined;\n hoverBgColor?: string | undefined;\n /**\n * Press-state background. Defaults to `group-active/tap:brightness-90` (the\n * BOX is what is pressed — its touch area included), which works on\n * any color. Override when using a custom `bgColor` that should darken to a\n * specific shade on press (e.g. `group-active/tap:bg-primary/60`).\n */\n activeBgColor?: string | undefined;\n}\n\n/** Native button attributes a tap button accepts — everything except `style`:\n * a tap button's geometry is the system's, never the caller's. */\nexport type TapTargetNativeProps = Omit<ButtonHTMLAttributes<HTMLButtonElement>, \"style\">;\n\nconst EXTERNAL_RE = /^(https?:|mailto:|tel:)/i;\n\n// Geometry + press feedback + tap hygiene are the SINGLE SOURCE OF TRUTH in\n// the shipped stylesheet (the `.matrx-tap-*` family in styles.css — import\n// \"@ai-matrx/tap-target/styles.css\" once at app root). This component only\n// picks the right class and layers each variant's decoration on top.\nconst TAP_OUTER_CLASS = \"matrx-tap-target group group/tap\";\nconst TAP_GROUP_OUTER_CLASS = \"matrx-tap-target matrx-tap-target-sm group group/tap\";\n\nfunction IconContent({\n icon,\n children,\n strokeWidth = 2,\n className,\n}: Pick<\n TapTargetButtonProps,\n \"icon\" | \"children\" | \"strokeWidth\" | \"className\"\n>) {\n if (icon) {\n if (isValidElement<{ className?: string }>(icon)) {\n return cloneElement(icon, {\n className: joinClassNames(className, icon.props.className),\n });\n }\n return <span className={className}>{icon}</span>;\n }\n return (\n <svg\n className={className}\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n strokeWidth={strokeWidth}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n {children}\n </svg>\n );\n}\n\ntype TapTargetSize = \"default\" | \"sm\";\n\nfunction resolveTapGeometry(\n label: string | undefined,\n size: TapTargetSize,\n mobileIconOnly: boolean,\n) {\n const inline = Boolean(label);\n if (size === \"sm\") {\n return {\n outerClassName:\n inline && mobileIconOnly\n ? \"matrx-tap-target matrx-tap-target-sm matrx-tap-target-mobile-icon-only-sm group group/tap\"\n : inline\n ? \"matrx-tap-target matrx-tap-target-sm matrx-tap-target-inline-sm group group/tap\"\n : TAP_GROUP_OUTER_CLASS,\n inlineModifier: mobileIconOnly\n ? \"matrx-tap-pill-mobile-icon-only-sm\"\n : \"matrx-tap-pill-inline-sm\",\n };\n }\n return {\n outerClassName:\n inline && mobileIconOnly\n ? `${TAP_OUTER_CLASS} matrx-tap-target-mobile-icon-only`\n : inline\n ? `${TAP_OUTER_CLASS} matrx-tap-target-inline`\n : TAP_OUTER_CLASS,\n inlineModifier: mobileIconOnly\n ? \"matrx-tap-pill-mobile-icon-only\"\n : \"matrx-tap-pill-inline\",\n };\n}\n\nfunction buildTapInner({\n label,\n pillClassName,\n iconClassName,\n labelClassName,\n inlineModifier,\n icon,\n children,\n strokeWidth = 2,\n loading,\n chevron,\n}: {\n label?: string | undefined;\n pillClassName: string;\n iconClassName: string;\n labelClassName?: string | undefined;\n inlineModifier: string;\n icon?: React.ReactNode;\n children?: React.ReactNode;\n strokeWidth?: number | undefined;\n loading?: boolean | undefined;\n chevron?: boolean | undefined;\n}) {\n const iconEl = loading ? (\n <TapSpinner className={iconClassName} />\n ) : (\n <IconContent\n icon={icon}\n strokeWidth={strokeWidth}\n className={iconClassName}\n >\n {children}\n </IconContent>\n );\n const pillClasses = label\n ? `${pillClassName} ${inlineModifier}`.trim()\n : pillClassName;\n\n if (!label) {\n return <div className={pillClasses}>{iconEl}</div>;\n }\n\n return (\n <div className={pillClasses}>\n {iconEl}\n <span className={labelClassName ?? \"matrx-tap-label\"}>{label}</span>\n {chevron ? <TapChevron /> : null}\n </div>\n );\n}\n\ninterface RenderTapTargetArgs extends Pick<\n TapTargetButtonProps,\n | \"icon\"\n | \"children\"\n | \"strokeWidth\"\n | \"label\"\n | \"mobileIconOnly\"\n | \"onClick\"\n | \"as\"\n | \"htmlFor\"\n | \"ariaLabel\"\n | \"disabled\"\n | \"href\"\n | \"target\"\n | \"rel\"\n | \"prefetch\"\n | \"linkComponent\"\n | \"tooltip\"\n | \"tooltipSide\"\n | \"tooltipAlign\"\n> {\n size?: TapTargetSize;\n /** The caller's raw `className` (the glyph color) — checked by the guard. */\n colorClassName?: string | undefined;\n pillClassName: string;\n iconClassName: string;\n labelClassName?: string | undefined;\n rest?: (TapTargetNativeProps & TapFeatureProps) | undefined;\n buttonRef?: Ref<HTMLButtonElement> | undefined;\n}\n\n// A hook (it carries the guard ref); every variant calls it exactly once.\nfunction useTapTarget({\n size = \"default\",\n colorClassName,\n pillClassName,\n iconClassName,\n labelClassName,\n icon,\n children,\n strokeWidth,\n label,\n mobileIconOnly = false,\n onClick,\n as,\n htmlFor,\n ariaLabel,\n disabled,\n href,\n target,\n rel,\n prefetch,\n linkComponent,\n tooltip,\n tooltipSide,\n tooltipAlign,\n rest,\n buttonRef,\n}: RenderTapTargetArgs): ReactElement {\n const {\n tone,\n badge,\n pressed,\n loading,\n disabledReason,\n shortcut,\n chevron,\n ...nativeRest\n } = rest ?? {};\n const isDisabled = Boolean(disabled || disabledReason);\n // FORCED TOOLTIPS: the text is the reason, an explicit tooltip, the\n // accessible name, or the label — and a button with none is a defect.\n const tipText =\n disabledReason || (typeof tooltip === \"string\" && tooltip ? tooltip : undefined) || ariaLabel || label;\n const titleMode = tooltip === false;\n const propViolation =\n (tipText ? null : \"every tap button needs a tooltip — pass ariaLabel\") ??\n classNameMisuse(colorClassName ?? nativeRest.className) ??\n ((nativeRest as { style?: unknown }).style ? \"style is not supported on a tap button\" : null);\n const guardRef = useTapGuardRef<HTMLElement>(\n buttonRef as Ref<HTMLElement> | undefined,\n propViolation,\n );\n const nodeRef = useRef<HTMLElement | null>(null);\n const triggerRef = useCallback(\n (node: HTMLElement | null) => {\n nodeRef.current = node;\n guardRef(node);\n },\n [guardRef],\n );\n const getNode = useCallback(() => nodeRef.current, []);\n useTapShortcut(shortcut, getNode, !isDisabled && !loading);\n\n // Tone (or a pressed toggle) owns the glyph and label color.\n const toneColor = tone ? TAP_TONE_CLASS[tone] : pressed && !colorClassName ? TAP_TONE_CLASS.primary : null;\n if (toneColor) {\n iconClassName = `matrx-tap-icon ${toneColor}`;\n labelClassName = `matrx-tap-label ${toneColor}`;\n }\n if (pressed) pillClassName = `${pillClassName} matrx-tap-pressed`;\n const { outerClassName, inlineModifier } = resolveTapGeometry(\n label,\n size,\n mobileIconOnly,\n );\n const responsiveLabelClassName = mobileIconOnly\n ? `${labelClassName ?? \"matrx-tap-label\"} matrx-tap-label-mobile-icon-only`\n : labelClassName;\n const inner = buildTapInner({\n label,\n pillClassName,\n iconClassName,\n labelClassName: responsiveLabelClassName,\n inlineModifier: label ? inlineModifier : \"\",\n icon,\n children,\n strokeWidth,\n loading,\n chevron,\n });\n const triggerAriaLabel =\n label && !mobileIconOnly ? undefined : (ariaLabel ?? label);\n const trigger = renderTrigger({\n href,\n target,\n rel,\n prefetch,\n linkComponent,\n as,\n htmlFor,\n onClick: loading ? undefined : onClick,\n ariaLabel: triggerAriaLabel,\n disabled: isDisabled,\n outerClassName,\n title: titleMode && tipText ? (shortcut ? `${tipText} (${formatTapShortcut(shortcut)})` : tipText) : undefined,\n children: (\n <>\n {inner}\n {badge !== undefined ? <TapBadge badge={badge} /> : null}\n </>\n ),\n rest: {\n ...nativeRest,\n ...(pressed !== undefined ? { \"aria-pressed\": pressed } : {}),\n ...(loading ? { \"aria-busy\": true } : {}),\n ...(shortcut ? { \"aria-keyshortcuts\": shortcut.replace(/mod/i, \"Meta\") } : {}),\n },\n triggerRef,\n });\n if (titleMode || !tipText) return trigger;\n return withTooltip(trigger, {\n tooltip: tipText,\n ariaLabel: tipText,\n disabled: isDisabled,\n tooltipSide,\n tooltipAlign,\n shortcut,\n });\n}\n\ninterface RenderTriggerArgs {\n href?: string | undefined;\n target?: \"_blank\" | \"_self\" | \"_parent\" | \"_top\" | undefined;\n rel?: string | undefined;\n prefetch?: boolean | null | undefined;\n linkComponent?: TapTargetLinkComponent | undefined;\n as?: \"button\" | \"label\" | undefined;\n htmlFor?: string | undefined;\n onClick?: (() => void) | undefined;\n ariaLabel?: string | undefined;\n disabled?: boolean | undefined;\n outerClassName: string;\n children: ReactNode;\n rest?: ButtonHTMLAttributes<HTMLButtonElement> | undefined;\n triggerRef: Ref<HTMLElement>;\n /** Tooltip text drawn through `title` (tooltip={false}: a nested trigger). */\n title?: string | undefined;\n}\n\n/**\n * Resolves the correct trigger element based on the props passed.\n *\n * - `href` + `disabled` → unclickable `<span aria-disabled>`\n * - `href` matching `http(s):|mailto:|tel:` → `<a target=\"_blank\" rel=\"noopener noreferrer\">`\n * - `href` (internal) → the injected link component (per-instance\n * `linkComponent` prop, else `setTapTargetLinkComponent` registration),\n * falling back to a plain `<a>` when none is registered\n * - `as=\"label\"` → `<label htmlFor=...>`\n * - default → `<button>`\n */\nfunction renderTrigger({\n href,\n target,\n rel,\n prefetch,\n linkComponent,\n as,\n htmlFor,\n onClick,\n ariaLabel,\n disabled,\n outerClassName,\n children,\n rest,\n triggerRef,\n title,\n}: RenderTriggerArgs): ReactElement {\n const { style: _style, ...restWithoutStyle } = rest ?? {};\n if (disabled && href) {\n return (\n <span\n ref={triggerRef}\n aria-disabled=\"true\"\n aria-label={ariaLabel}\n title={title}\n className={`${outerClassName} opacity-40`}\n >\n {children}\n </span>\n );\n }\n if (href) {\n const isExternal = EXTERNAL_RE.test(href);\n if (isExternal) {\n return (\n <a\n ref={triggerRef as Ref<HTMLAnchorElement>}\n href={href}\n target={target ?? \"_blank\"}\n rel={rel ?? \"noopener noreferrer\"}\n aria-label={ariaLabel}\n title={title}\n className={outerClassName}\n >\n {children}\n </a>\n );\n }\n const Link = linkComponent ?? getTapTargetLinkComponent();\n if (Link) {\n return (\n <Link\n ref={triggerRef as Ref<HTMLAnchorElement>}\n href={href}\n target={target}\n rel={rel}\n prefetch={prefetch}\n aria-label={ariaLabel}\n title={title}\n className={outerClassName}\n >\n {children}\n </Link>\n );\n }\n // No link component registered — plain <a>. `prefetch` is a router hint,\n // not a DOM attribute, so it is deliberately dropped here.\n return (\n <a\n ref={triggerRef as Ref<HTMLAnchorElement>}\n href={href}\n target={target}\n rel={rel}\n aria-label={ariaLabel}\n title={title}\n className={outerClassName}\n >\n {children}\n </a>\n );\n }\n if (as === \"label\") {\n return (\n <label\n ref={triggerRef as Ref<HTMLLabelElement>}\n htmlFor={htmlFor}\n aria-label={ariaLabel}\n title={title}\n className={outerClassName}\n >\n {children}\n </label>\n );\n }\n return (\n <button\n ref={triggerRef as Ref<HTMLButtonElement>}\n type=\"button\"\n onClick={onClick}\n aria-label={ariaLabel}\n title={title}\n disabled={disabled}\n {...restWithoutStyle}\n className={outerClassName}\n >\n {children}\n </button>\n );\n}\n\n/**\n * Wraps a trigger element in a Tooltip when a tooltip label is available.\n * Falls back to `ariaLabel` when `tooltip` is not explicitly set. If both\n * are absent (or `tooltip === false`), the trigger is returned unwrapped.\n */\nfunction withTooltip(\n trigger: ReactElement,\n {\n tooltip,\n ariaLabel,\n disabled,\n tooltipSide = \"top\",\n tooltipAlign = \"center\",\n shortcut,\n }: {\n tooltip?: string | false | undefined;\n ariaLabel?: string | undefined;\n disabled?: boolean | undefined;\n tooltipSide?: \"top\" | \"right\" | \"bottom\" | \"left\" | undefined;\n tooltipAlign?: \"start\" | \"center\" | \"end\" | undefined;\n shortcut?: TapShortcut | undefined;\n },\n): ReactElement {\n if (tooltip === false) return trigger;\n const label =\n typeof tooltip === \"string\" && tooltip.length > 0 ? tooltip : ariaLabel;\n if (!label) return trigger;\n return (\n <Tooltip>\n <TooltipTrigger asChild>\n {disabled ? (\n // Radix Tooltip triggers need a hoverable element; a disabled button\n // does not dispatch pointer events, so we wrap in a span for the\n // trigger target while keeping the disabled visual state.\n <span className=\"inline-flex\">{trigger}</span>\n ) : (\n trigger\n )}\n </TooltipTrigger>\n <TooltipContent side={tooltipSide} align={tooltipAlign}>\n {tooltipBody(label, shortcut)}\n </TooltipContent>\n </Tooltip>\n );\n}\n\n// To resize/retune every tap button, edit styles.css — not here.\n\nexport const TapTargetButton = forwardRef<\n HTMLButtonElement,\n TapTargetButtonProps & TapTargetNativeProps\n>(function TapTargetButton(\n {\n icon,\n children,\n strokeWidth = 2,\n onClick,\n className,\n as,\n htmlFor,\n ariaLabel,\n disabled,\n href,\n target,\n rel,\n prefetch,\n linkComponent,\n tooltip,\n tooltipSide,\n tooltipAlign,\n label,\n mobileIconOnly,\n ...rest\n },\n ref,\n) {\n const color = className ?? \"text-foreground\";\n return useTapTarget({\n colorClassName: className,\n icon,\n children,\n strokeWidth,\n onClick,\n as,\n htmlFor,\n ariaLabel,\n disabled,\n href,\n target,\n rel,\n prefetch,\n linkComponent,\n tooltip,\n tooltipSide,\n tooltipAlign,\n label,\n mobileIconOnly,\n pillClassName: \"matrx-tap-pill matrx-glass-thin-border\",\n iconClassName: `matrx-tap-icon ${color}`,\n rest,\n buttonRef: ref,\n });\n});\n\nexport const TapTargetButtonTransparent = forwardRef<\n HTMLButtonElement,\n TapTargetButtonProps & TapTargetNativeProps\n>(function TapTargetButtonTransparent(\n {\n icon,\n children,\n strokeWidth = 2,\n onClick,\n className,\n as,\n htmlFor,\n ariaLabel,\n disabled,\n href,\n target,\n rel,\n prefetch,\n linkComponent,\n tooltip,\n tooltipSide,\n tooltipAlign,\n label,\n mobileIconOnly,\n ...rest\n },\n ref,\n) {\n const color = className ?? \"text-foreground\";\n return useTapTarget({\n colorClassName: className,\n icon,\n children,\n strokeWidth,\n onClick,\n as,\n htmlFor,\n ariaLabel,\n disabled,\n href,\n target,\n rel,\n prefetch,\n linkComponent,\n tooltip,\n tooltipSide,\n tooltipAlign,\n label,\n mobileIconOnly,\n pillClassName:\n \"matrx-tap-pill group-hover/tap:bg-muted group-active/tap:bg-muted-foreground/15\",\n iconClassName: `matrx-tap-icon ${color}`,\n rest,\n buttonRef: ref,\n });\n});\n\n/** Outline pill — a plain 1px border, no fill, no blur, no shadow. Glass only\n * reads as glass over something you can see through; on an opaque card or\n * header use THIS. Same colors as the classic square \"+\": border-border,\n * muted glyph, primary border + foreground glyph on hover. */\nexport const TapTargetButtonOutline = forwardRef<\n HTMLButtonElement,\n TapTargetButtonProps & TapTargetNativeProps\n>(function TapTargetButtonOutline(\n {\n icon,\n children,\n strokeWidth = 2,\n onClick,\n className,\n as,\n htmlFor,\n ariaLabel,\n disabled,\n href,\n target,\n rel,\n prefetch,\n linkComponent,\n tooltip,\n tooltipSide,\n tooltipAlign,\n label,\n mobileIconOnly,\n ...rest\n },\n ref,\n) {\n const color =\n className ?? \"text-muted-foreground group-hover/tap:text-foreground\";\n return useTapTarget({\n colorClassName: className,\n icon,\n children,\n strokeWidth,\n onClick,\n as,\n htmlFor,\n ariaLabel,\n disabled,\n href,\n target,\n rel,\n prefetch,\n linkComponent,\n tooltip,\n tooltipSide,\n tooltipAlign,\n label,\n mobileIconOnly,\n pillClassName:\n \"matrx-tap-pill border border-border bg-transparent transition-colors group-hover/tap:border-primary/60 group-active/tap:bg-muted\",\n iconClassName: `matrx-tap-icon ${color}`,\n labelClassName: `matrx-tap-label ${color}`,\n rest,\n buttonRef: ref,\n });\n});\n\nexport const TapTargetButtonSolid = forwardRef<\n HTMLButtonElement,\n TapTargetButtonSolidProps & TapTargetNativeProps\n>(function TapTargetButtonSolid(\n {\n icon,\n children,\n strokeWidth = 2,\n onClick,\n as,\n htmlFor,\n ariaLabel,\n disabled,\n href,\n target,\n rel,\n prefetch,\n linkComponent,\n tone,\n bgColor,\n iconColor,\n hoverBgColor,\n activeBgColor,\n tooltip,\n tooltipSide,\n tooltipAlign,\n label,\n mobileIconOnly,\n ...rest\n },\n ref,\n) {\n return useTapTarget({\n icon,\n children,\n strokeWidth,\n onClick,\n as,\n htmlFor,\n ariaLabel,\n disabled,\n href,\n target,\n rel,\n prefetch,\n linkComponent,\n tooltip,\n tooltipSide,\n tooltipAlign,\n label,\n mobileIconOnly,\n ...solidClasses(tone, bgColor, iconColor, hoverBgColor, activeBgColor),\n rest,\n buttonRef: ref,\n });\n});\n\n// `tone` is the system's fill; the four color strings are the pre-tone API,\n// accepted only until their last callers move to `tone`. `matrx-tap-solid` marks the\n// filled pill so the stylesheet can give a DISABLED solid the system's disabled token\n// (muted fill + --disabled-foreground glyph) instead of a 40%-opacity ghost of its fill.\nfunction solidClasses(\n tone: TapSolidTone | undefined,\n bgColor: string | undefined,\n iconColor: string | undefined,\n hoverBgColor: string | undefined,\n activeBgColor: string | undefined,\n) {\n const legacy = !tone && (bgColor || iconColor || hoverBgColor || activeBgColor);\n if (!legacy) {\n const t = TAP_SOLID_TONE[tone ?? \"primary\"];\n return {\n pillClassName: `matrx-tap-pill matrx-tap-solid ${t.fill} ${t.glyph} group-active/tap:brightness-90`,\n iconClassName: `matrx-tap-icon ${t.glyph}`,\n labelClassName: `matrx-tap-label ${t.glyph}`,\n };\n }\n const glyph = iconColor ?? \"text-primary-foreground\";\n return {\n pillClassName: `matrx-tap-pill matrx-tap-solid ${bgColor ?? \"bg-primary\"} ${glyph} ${hoverBgColor ?? \"group-hover/tap:bg-primary/80\"} ${activeBgColor ?? \"group-active/tap:brightness-90\"}`,\n iconClassName: `matrx-tap-icon ${glyph}`,\n labelClassName: `matrx-tap-label ${glyph}`,\n };\n}\n\n/** Solid destructive pill — delete/remove actions. White-on-red like the\n * primary solid is white-on-blue. Use THIS, never hand-pass bg-destructive\n * with the default (dark) icon color. */\nexport const TapTargetButtonDestructive = forwardRef<\n HTMLButtonElement,\n TapTargetButtonSolidProps & TapTargetNativeProps\n>(function TapTargetButtonDestructive({ tone = \"destructive\", ...rest }, ref) {\n return <TapTargetButtonSolid ref={ref} tone={tone} {...rest} />;\n});\n\nexport const TapTargetButtonForGroup = forwardRef<\n HTMLButtonElement,\n TapTargetButtonProps & TapTargetNativeProps\n>(function TapTargetButtonForGroup(\n {\n icon,\n children,\n strokeWidth = 2,\n onClick,\n className,\n as,\n htmlFor,\n ariaLabel,\n disabled,\n href,\n target,\n rel,\n prefetch,\n linkComponent,\n tooltip,\n tooltipSide,\n tooltipAlign,\n label,\n mobileIconOnly,\n ...rest\n },\n ref,\n) {\n const color = className ?? \"text-foreground\";\n return useTapTarget({\n colorClassName: className,\n size: \"sm\",\n icon,\n children,\n strokeWidth,\n onClick,\n as,\n htmlFor,\n ariaLabel,\n disabled,\n href,\n target,\n rel,\n prefetch,\n linkComponent,\n tooltip,\n tooltipSide,\n tooltipAlign,\n label,\n mobileIconOnly,\n pillClassName: \"matrx-tap-pill matrx-tap-pill-sm matrx-glass-interactive\",\n iconClassName: `matrx-tap-icon ${color}`,\n labelClassName: `matrx-tap-label ${color}`,\n rest,\n buttonRef: ref,\n });\n});\n\nexport function TapTargetButtonGroup({\n children,\n className,\n surface: surfaceProp,\n}: {\n children: React.ReactNode;\n className?: string | undefined;\n /**\n * GLASS ONLY FLOATS (owner rule, 2026-10-02): glass belongs on a bar that\n * floats over scrolling content or a see-through plane. On a solid surface\n * (a page, a card, a toast, a table toolbar) use `\"solid\"`: a muted track,\n * no glass stroke, the same geometry.\n */\n surface?: \"glass\" | \"solid\" | undefined;\n}) {\n // Geometry (height, the half-gap outside the capsule, the capsule itself)\n // is `.matrx-tap-group*` in tap-target.css.\n const surface = useTapSurface(surfaceProp);\n return (\n <div\n className={className ? `matrx-tap-group ${className}` : \"matrx-tap-group\"}\n data-surface={surface}\n >\n <div\n className={\n surface === \"solid\"\n ? \"matrx-tap-group-capsule matrx-tap-group-capsule-solid\"\n : \"matrx-tap-group-capsule matrx-glass-thin-border\"\n }\n />\n <div className=\"matrx-tap-group-row\">{children}</div>\n </div>\n );\n}\n","\"use client\";\n\n/**\n * Tooltip — the ONE tooltip in the fleet.\n *\n * THE COLLAPSE (0.6.0). Two implementations existed: matrx-frontend's\n * `components/ui/tooltip.tsx` (182 import sites) and `@ai-matrx/tap-target`'s\n * `src/tooltip.tsx` — the latter an explicit inlined PORT of the former,\n * carrying a header that said so. tap-target shipped it only because its ~60\n * tap buttons need a tooltip and no shared package owned one; four repos then\n * adopted `TooltipProvider` from tap-target. That made tap-target — a\n * button-geometry package — the accidental owner of a design-system primitive,\n * with a second copy living in the biggest host.\n *\n * A tooltip is a design-system surface, so it lives here. tap-target now takes\n * `@ai-matrx/design-system` as an ordinary sibling dependency and imports this\n * file; its own copy is deleted, and its re-export removed. The DAG already\n * ordered design-system before tap-target, so no cycle is introduced.\n *\n * BEHAVIOR is matrx-frontend's, verbatim, including the ruling both copies\n * carried in prose:\n *\n * 1. THE ROOT RENDERS UNCONDITIONALLY — no hydration mount gate. The gate the\n * host wrapper once carried (\"Radix generates dynamic aria-controls ids that\n * differ between SSR and client\") was false: Radix ids come from React's\n * SSR-stable `useId`. It was actively harmful — a Trigger wraps\n * ALWAYS-VISIBLE content, so `return null` deleted that subtree from SSR and\n * the first client paint.\n *\n * 2. THE SURFACE IS TOKEN-DRIVEN, NOT BRANDED. Popover tokens, not\n * `bg-primary`: rich tooltip content using `text-muted-foreground` was\n * illegible on a brand-colored background in one theme or the other.\n * Since 2026-09-28 the `.matrx-tooltip` class re-scopes those tokens to a dark,\n * high-contrast chip in both themes (styles.css, THE TOOLTIP SURFACE): the\n * neutral white surface it wore before was indistinguishable from the\n * browser's own `title` box.\n *\n * 3. EVERY `title` IS THIS TOOLTIP. The provider installs the title takeover\n * (`title-tooltips.ts`), so a hand-written `title=` anywhere in the\n * document shows this surface, never the browser's.\n *\n * SEAM INVERSION. The host resolved nested portal targets through\n * `useNestedPortalContainer` (an app hook wired to its dialog + window-panel\n * systems); tap-target's port dropped that seam entirely and always portalled\n * to `document.body` — which is why a tooltip inside a popped-out panel landed\n * in the wrong window. Here it is the package's `PortalContainerProvider`\n * seam: an explicit `container` prop wins, then the injected container, then\n * `document.body`. Both prior behaviors are reachable; neither is forked.\n */\n\nimport * as TooltipPrimitive from \"@radix-ui/react-tooltip\";\nimport * as React from \"react\";\n\nimport { cn } from \"./cn\";\nimport { MOTION_POPPER } from \"./motion\";\nimport { usePortalContainer } from \"./portal-container\";\nimport { acquireTitleTooltips, clipTooltipText, tooltipSide, TOOLTIP_EDGE_PX, TOOLTIP_LAYER_Z, TOOLTIP_TRIGGER_ATTR, type Side } from \"./title-tooltips\";\n\nexport interface TooltipProviderProps\n extends React.ComponentProps<typeof TooltipPrimitive.Provider> {\n /**\n * THE TITLE TAKEOVER (2026-09-28) — while any provider is mounted, every native\n * `title` attribute in the document shows as this tooltip instead of the\n * browser's (see `title-tooltips.ts`). On by default, because a rule every\n * author must remember is a rule that is broken; pass `false` only for a\n * surface that must keep the browser's own box. One provider opting out does\n * not turn it off while another one is mounted.\n */\n titleTooltips?: boolean;\n}\n\n/**\n * Mount once near the app root. Every tooltip in the tree shares its\n * `delayDuration` / `skipDelayDuration` timing, and the root provider takes\n * over native `title` attributes (see `titleTooltips`). The fleet default keeps\n * tooltip content hoverable and selectable. A native mirrored Desktop shell may\n * explicitly opt in to `disableHoverableContent` so its overlay view yields the\n * pointer back to the host; ordinary application tooltips must leave it unset.\n */\nfunction TooltipProvider({ titleTooltips = true, disableHoverableContent = false, ...props }: TooltipProviderProps) {\n React.useEffect(() => {\n if (!titleTooltips) return;\n return acquireTitleTooltips();\n }, [titleTooltips]);\n return <TooltipPrimitive.Provider {...props} disableHoverableContent={disableHoverableContent} />;\n}\n\n/**\n * The tooltip root inherits its provider's hoverability policy: the ordinary\n * provider defaults to hoverable, selectable content (Arman, 2026-10-14), while\n * a native mirrored Desktop shell may opt in at its provider so the overlay view\n * yields pointer control to its host. An explicit root prop still wins.\n */\n/** The tooltip's trigger and whether it is open, so its content takes THE SMART SIDE\n * (title-tooltips.ts) from where the trigger stands at the moment it opens. */\ninterface TriggerState {\n ref: React.MutableRefObject<HTMLElement | null>;\n open: boolean;\n}\nconst TriggerContext = React.createContext<TriggerState | null>(null);\n\nconst Tooltip = ({ onOpenChange, ...props }: React.ComponentProps<typeof TooltipPrimitive.Root>) => {\n const ref = React.useRef<HTMLElement | null>(null);\n const [open, setOpen] = React.useState(Boolean(props.open ?? props.defaultOpen));\n const shown = props.open ?? open;\n const value = React.useMemo(() => ({ ref, open: shown }), [shown]);\n return (\n <TriggerContext.Provider value={value}>\n <TooltipPrimitive.Root\n {...props}\n onOpenChange={(next) => {\n setOpen(next);\n onOpenChange?.(next);\n }}\n />\n </TriggerContext.Provider>\n );\n};\nTooltip.displayName = \"Tooltip\";\n\n/**\n * Stamps `data-matrx-tooltip-trigger` so the title takeover never draws a\n * second tooltip over a control that already has this one — it still lifts a\n * `title` on the same control, so the browser's box never doubles it either.\n */\nconst TooltipTrigger = React.forwardRef<\n React.ComponentRef<typeof TooltipPrimitive.Trigger>,\n React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Trigger>\n>((props, ref) => {\n const trigger = React.useContext(TriggerContext);\n const setRef = React.useCallback(\n (node: HTMLButtonElement | null) => {\n if (trigger) trigger.ref.current = node;\n if (typeof ref === \"function\") ref(node);\n else if (ref) ref.current = node;\n },\n [trigger, ref],\n );\n return <TooltipPrimitive.Trigger ref={setRef} {...{ [TOOLTIP_TRIGGER_ATTR]: \"\" }} {...props} />;\n});\nTooltipTrigger.displayName = TooltipPrimitive.Trigger.displayName;\n\nexport interface TooltipContentProps\n extends React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Content> {\n /**\n * Explicit portal target; wins over the injected `PortalContainerProvider`\n * value. Pass `null` to force `document.body`.\n */\n container?: HTMLElement | null;\n /**\n * Package-owned open/close motion. Default `true`. Pass `false` for a\n * surface that must appear instantly. It is NOT the reduced-motion switch;\n * `styles.css` already honors `prefers-reduced-motion`.\n */\n animated?: boolean;\n /**\n * The side when the control is not in a vertical stack and no side is given (the host's default:\n * a macOS desktop host says \"bottom\"). Omit for the document's `data-title-side`, else \"top\".\n */\n fallbackSide?: Side;\n}\n\nconst TooltipContent = React.forwardRef<\n React.ComponentRef<typeof TooltipPrimitive.Content>,\n TooltipContentProps\n>(({ className, side, fallbackSide, sideOffset = 4, collisionPadding = TOOLTIP_EDGE_PX, container, animated = true, children, style, ...props }, ref) => {\n const resolved = usePortalContainer(container);\n const trigger = React.useContext(TriggerContext);\n // THE SMART SIDE: an explicit side wins; otherwise where the trigger's neighbours stand decides.\n const placed = side ?? (trigger?.open ? tooltipSide(trigger.ref.current, fallbackSide) : (fallbackSide ?? \"top\"));\n return (\n <TooltipPrimitive.Portal container={resolved ?? null}>\n <TooltipPrimitive.Content\n ref={ref}\n data-slot=\"tooltip-content\"\n side={placed}\n sideOffset={sideOffset}\n // Flip and stay inside the window: Radix flips to the opposite side when the preferred one\n // does not fit, and shifts along the edge; the padding keeps it off the window's border.\n avoidCollisions\n collisionPadding={collisionPadding}\n className={cn(\n \"matrx-tooltip max-w-xs select-text overflow-hidden whitespace-normal break-words rounded-md border border-border bg-popover px-2.5 py-1 text-xs font-medium text-popover-foreground\",\n animated && MOTION_POPPER,\n className,\n )}\n // THE tooltip layer: above every menu, popover and modal (Radix copies it onto its wrapper).\n style={{ zIndex: TOOLTIP_LAYER_Z, ...style }}\n {...props}\n >\n {typeof children === \"string\" ? clipTooltipText(children) : children}\n </TooltipPrimitive.Content>\n </TooltipPrimitive.Portal>\n );\n});\nTooltipContent.displayName = TooltipPrimitive.Content.displayName;\n\nexport { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger };\nexport { acquireTitleTooltips, clipTooltipText, NATIVE_TITLE_OPT_OUT_ATTR, TOOLTIP_TEXT_BUDGET } from \"./title-tooltips\";\n","\"use client\";\n\n// THE TAP-TARGET GUARD — development builds only.\n//\n// The lock layer in tap-target.css makes a tap button's own box, pill and\n// glyph impossible to resize from outside. What CSS cannot stop is a caller\n// bending the system AROUND the button: a parent that adds `gap` between two\n// tap buttons, a wrapper with margin or padding, a local override of a\n// `--matrx-tap-*` token, a utility class smuggled in through `className`.\n// After a tap button mounts, this guard measures it in the real layout and,\n// on any of those, marks it `data-matrx-tap-violation`: the stylesheet then\n// paints it as a giant red box carrying the reason, and the console names\n// the element.\n//\n// OFF until the host turns it on with `enableTapTargetGuard()` — from code the\n// HOST compiles, e.g. matrx-frontend's dev-only client boot. Never gate it on\n// `process.env.NODE_ENV` in here: this package's own build inlines that\n// expression, so a \"dev only\" check written here would run in production too\n// (see @ai-matrx/associations' context.tsx for the outage that taught this).\n\nimport { useCallback, useRef, type MutableRefObject, type Ref } from \"react\";\nimport { layoutScale } from \"../layout-scale\";\n\n// A `Symbol.for` slot on globalThis, like the link seam: the `.` and\n// `./buttons` bundles each inline this module, and one switch must reach both.\nconst GUARD_SLOT = Symbol.for(\"@ai-matrx/tap-target:guard\");\ntype GlobalWithGuard = typeof globalThis & { [GUARD_SLOT]?: boolean };\n\n/** Turn the development guard on (or off). Call once at client boot, only in\n * development builds of the host. */\nexport function enableTapTargetGuard(on = true): void {\n (globalThis as GlobalWithGuard)[GUARD_SLOT] = on;\n if (on) startPillInsetScan();\n}\n\nfunction guardOn(): boolean {\n return (globalThis as GlobalWithGuard)[GUARD_SLOT] === true;\n}\n\nconst TOKENS = [\n \"--matrx-tap-box\",\n \"--matrx-tap-gap\",\n \"--matrx-tap-pill-size\",\n \"--matrx-tap-pill-sm-size\",\n \"--matrx-tap-wide-size\",\n \"--matrx-tap-icon-size\",\n \"--matrx-tap-touch-min\",\n \"--matrx-tap-target-size\",\n] as const;\n\n/** The only scopes that may move tap tokens, and which ones — each owned by\n * this package's own CSS: the table density scales (tap-target.css) and\n * Alchemy's 18px trigger glyph (content-transfer.css). */\nconst SANCTIONED: ReadonlyArray<{ scope: string; tokens: ReadonlySet<string> }> = [\n {\n scope: \"[data-matrx-table][data-matrx-table-density]\",\n tokens: new Set([\n \"--matrx-tap-target-size\",\n \"--matrx-tap-pill-size\",\n \"--matrx-tap-wide-size\",\n \"--matrx-tap-pill-sm-size\",\n \"--matrx-tap-icon-size\",\n ]),\n },\n { scope: \"[data-alchemy-trigger]\", tokens: new Set([\"--matrx-tap-icon-size\"]) },\n // THE ONE CONTROL scope (controls.css): tap buttons beside the 28px controls\n // take the controls' height — a 28px pill in a 34px box, the same 6px apart.\n {\n scope: \"[data-matrx-controls]\",\n tokens: new Set([\n \"--matrx-tap-target-size\",\n \"--matrx-tap-pill-size\",\n \"--matrx-tap-wide-size\",\n \"--matrx-tap-pill-sm-size\",\n ]),\n },\n];\nconst TABLE_SCOPE = SANCTIONED[0]!.scope;\nconst CONTROL_SCOPE = SANCTIONED[2]!.scope;\nconst TAP_ITEM = \".matrx-tap-target, .matrx-tap-group\";\n\n/** `className` on a tap button is the GLYPH COLOR. Anything that sizes,\n * spaces, positions or fills is misuse. */\nconst NON_COLOR_CLASS =\n /^(?:[^\\s:]+:)*!?-?(?:\\[&|scale|translate|h|w|size|min-h|min-w|max-h|max-w|p|px|py|ps|pe|pt|pb|pl|pr|m|mx|my|ms|me|mt|mb|ml|mr|gap|space-x|space-y|bg|rounded|border|ring|shadow|absolute|relative|fixed|sticky|inset|top|left|right|bottom|flex|grid|block|inline|hidden|z|shrink|grow|basis|self|order)(?:-|$|\\[)/;\n\nexport function classNameMisuse(className: string | undefined): string | null {\n if (!guardOn() || !className) return null;\n const bad = className.split(/\\s+/).filter((t) => t && NON_COLOR_CLASS.test(t));\n return bad.length\n ? `className is the glyph color only — remove \"${bad.join(\" \")}\"`\n : null;\n}\n\n/**\n * The horizontal space a wrapper adds around what it holds. An `auto` margin (`ml-auto` pushing a\n * toolbar's actions to the end) only aligns — the browser resolves it to pixels in\n * `getComputedStyle`, so read the computed keyword from the typed OM and count it as zero.\n */\nexport function wrapperSpace(el: Element, view: Window): number {\n const pcs = view.getComputedStyle(el);\n const typed = (el as Element & { computedStyleMap?: () => { get(p: string): unknown } }).computedStyleMap?.();\n const margin = (prop: \"margin-left\" | \"margin-right\", resolved: string) =>\n typed && String(typed.get(prop)) === \"auto\" ? 0 : px(resolved);\n return margin(\"margin-left\", pcs.marginLeft) + margin(\"margin-right\", pcs.marginRight) + px(pcs.paddingLeft) + px(pcs.paddingRight);\n}\n\nfunction px(value: string): number {\n const n = Number.parseFloat(value);\n return Number.isFinite(n) ? n : 0;\n}\n\nfunction describe(el: Element): string {\n const cls = typeof el.className === \"string\" ? el.className.trim().split(/\\s+/).slice(0, 4).join(\".\") : \"\";\n return `<${el.tagName.toLowerCase()}${cls ? `.${cls}` : \"\"}>`;\n}\n\n/** Elements that ride along with a tap button without taking space from it\n * (a badge, a capsule, a tooltip portal anchor). */\nfunction isDecor(el: Element, view: Window): boolean {\n const cs = view.getComputedStyle(el);\n return cs.position === \"absolute\" || cs.position === \"fixed\" || cs.display === \"none\";\n}\n\nfunction tapCount(el: Element): number {\n return el.matches(TAP_ITEM) ? 1 : el.querySelectorAll(TAP_ITEM).length;\n}\n\n/** Visible text in `container` outside `tap` and outside decor (a badge's\n * count is decor) — a wrapper with its own words is a chip, not a wrapper. */\nfunction ownText(container: Element, tap: Element, view: Window): string {\n let out = \"\";\n const walk = (node: Node) => {\n if (node === tap) return;\n if (node.nodeType === 3) out += node.textContent ?? \"\";\n else if (node.nodeType === 1 && !isDecor(node as Element, view)) node.childNodes.forEach(walk);\n };\n container.childNodes.forEach(walk);\n return out.trim();\n}\n\n/** True when `child` is a tap button, or a plain wrapper whose only content\n * is ONE tap button (plus decor) — never a search box that happens to hold\n * a clear button, never a chip with words. */\nfunction isTapSlot(child: Element, view: Window): boolean {\n if (child.matches(TAP_ITEM)) return true;\n if (tapCount(child) !== 1) return false;\n const tap = child.querySelector(TAP_ITEM)!;\n const controls = Array.from(child.querySelectorAll(\"input, select, textarea, button, a, [role='button']\"));\n if (controls.some((c) => c !== tap && !tap.contains(c))) return false;\n return ownText(child, tap, view) === \"\";\n}\n\nlet probe: { key: string; target: number; pill: number; sm: number; smPill: number; wide: number; icon: number } | null = null;\n\n/** What the package's own CSS produces with no surrounding context — the\n * canon every mounted button is measured against. Re-measured whenever the\n * root tokens change (the lab page switches the gap). */\nfunction canon(doc: Document) {\n const view = doc.defaultView!;\n const root = view.getComputedStyle(doc.documentElement);\n const key = TOKENS.map((t) => root.getPropertyValue(t)).join(\"|\");\n if (probe?.key === key) return probe;\n const host = doc.createElement(\"div\");\n host.setAttribute(\"aria-hidden\", \"true\");\n host.style.cssText = \"position:absolute;visibility:hidden;pointer-events:none;left:-9999px;top:0\";\n host.innerHTML =\n '<button class=\"matrx-tap-target\"><div class=\"matrx-tap-pill\"><svg class=\"matrx-tap-icon\"></svg></div></button>' +\n '<button class=\"matrx-tap-target matrx-tap-target-sm\"><div class=\"matrx-tap-pill matrx-tap-pill-sm\"></div></button>' +\n '<button class=\"matrx-tap-target matrx-tap-target-inline\"><div class=\"matrx-tap-pill matrx-tap-pill-inline\"></div></button>';\n doc.body.appendChild(host);\n const [a, b, w] = Array.from(host.children) as HTMLElement[];\n probe = {\n key,\n target: a!.offsetHeight,\n pill: (a!.firstElementChild as HTMLElement).offsetHeight,\n icon: px(view.getComputedStyle(a!.querySelector(\"svg\")!).height),\n sm: b!.offsetHeight,\n smPill: (b!.firstElementChild as HTMLElement).offsetHeight,\n wide: (w!.firstElementChild as HTMLElement).offsetHeight,\n };\n host.remove();\n return probe;\n}\n\n/** Returns the first rule this mounted tap button breaks, or null. */\nexport function findTapViolation(el: HTMLElement): string | null {\n const doc = el.ownerDocument;\n const view = doc.defaultView;\n if (!view || !el.isConnected) return null;\n const cs = view.getComputedStyle(el);\n if (cs.display === \"none\") return null;\n\n // 1. Tokens are the package's alone. Only the table-density scope may move\n // the three it owns.\n const root = view.getComputedStyle(doc.documentElement);\n // Both scaled scopes size by their own tokens; the canon check below reads\n // the root canon, so it applies outside them only.\n const inTable = el.closest(TABLE_SCOPE) !== null || el.closest(CONTROL_SCOPE) !== null;\n const moved = new Set<string>();\n for (const token of TOKENS) {\n const mine = cs.getPropertyValue(token).trim();\n const base = root.getPropertyValue(token).trim();\n if (mine === base) continue;\n if (!SANCTIONED.some((s) => s.tokens.has(token) && el.closest(s.scope))) {\n return `${token} overridden to \"${mine}\" — tap geometry is not configurable`;\n }\n moved.add(token);\n }\n\n // 2. Measured geometry equals the canon (outside table density, which\n // sizes by its own tokens).\n const sm = el.classList.contains(\"matrx-tap-target-sm\");\n const inline = /matrx-tap-target-(?:inline|mobile-icon-only)/.test(el.className);\n const pill = el.querySelector<HTMLElement>(\":scope > .matrx-tap-pill\");\n const icon = pill?.querySelector(\".matrx-tap-icon\") ?? null;\n // A host touch floor (min-width / min-height) may enlarge a box; that is\n // the floor working, not a bend.\n const floored =\n px(cs.minHeight) >= el.offsetHeight - 0.5 || px(cs.minWidth) >= el.offsetWidth - 0.5;\n if (!inTable && pill && !floored) {\n const c = canon(doc);\n const box = sm ? c.sm : c.target;\n // A labeled pill is a WIDE shape (shorter than a round one); below the\n // `sm` breakpoint a mobile-icon-only pill is round again — either is canon.\n const pillSizes = sm ? [c.smPill] : inline ? [c.pill, c.wide] : [c.pill];\n if (Math.abs(el.offsetHeight - box) > 0.5) return `button is ${el.offsetHeight}px tall, canon is ${box}px`;\n if (!inline && Math.abs(el.offsetWidth - box) > 0.5) return `button is ${el.offsetWidth}px wide, canon is ${box}px`;\n if (!pillSizes.some((p) => Math.abs(pill.offsetHeight - p) <= 0.5)) {\n return `pill is ${pill.offsetHeight}px, canon is ${pillSizes.join(\" or \")}px`;\n }\n if (icon && !moved.has(\"--matrx-tap-icon-size\")) {\n const size = px(view.getComputedStyle(icon).height);\n if (Math.abs(size - c.icon) > 0.5) return `glyph is ${size}px, canon is ${c.icon}px`;\n }\n }\n\n // 3. Nothing adds space around it. Climb the wrappers that hold only this\n // button (plus decor such as a badge); none may carry inline margin or\n // padding. A tap button inside a group is represented by its group.\n let slot: Element = el;\n if (el.parentElement?.matches(\".matrx-tap-group-row, .matrx-tap-search-measure\")) {\n const group = el.closest(\".matrx-tap-group\");\n if (group && tapCount(el.parentElement) > 1) return null;\n slot = group ?? el;\n }\n for (let depth = 0; depth < 2; depth += 1) {\n const parent: HTMLElement | null = slot.parentElement;\n if (!parent || parent === doc.body) break;\n const others = Array.from(parent.children).filter((c) => c !== slot && !isDecor(c, view));\n if (others.length > 0) break; // `parent` is the row\n if (ownText(parent, slot, view) !== \"\") break; // a chip or a titled header\n const space = wrapperSpace(parent, view);\n if (space > 0.5) {\n return `${describe(parent)} adds ${space}px around a tap button — tap buttons space themselves`;\n }\n slot = parent;\n }\n\n // 4. The row adds no gap between tap buttons.\n const row = slot.parentElement;\n if (row) {\n const rcs = view.getComputedStyle(row);\n const flexOrGrid = /flex|grid/.test(rcs.display);\n const neighbours = Array.from(row.children).filter((c) => c !== slot && isTapSlot(c, view));\n if (flexOrGrid && neighbours.length > 0) {\n const horizontal = rcs.display.includes(\"grid\") || !rcs.flexDirection.startsWith(\"column\");\n const gap = px(horizontal ? rcs.columnGap : rcs.rowGap);\n if (gap > 0.5) {\n return `${describe(row)} adds a ${gap}px gap between tap buttons — remove it; tap buttons space themselves`;\n }\n }\n }\n return null;\n}\n\n/* ------------------------------------------------------------------ */\n/* PLACEMENT — the three rules a tap button's SURROUNDINGS must keep */\n/* (owner, 2026-10-02). Reported as a WARNING (a dashed outline and one */\n/* console error naming the fix), not the misuse box: they are about */\n/* the page around the button, and the whole app is being brought into */\n/* line with them. */\n/* 1. GLASS ONLY FLOATS — glass is see-through; it belongs on a bar */\n/* that floats over moving content (position fixed/sticky) or on a */\n/* plane marked `data-matrx-glass-plane`. On a page, card, toast or */\n/* table use `variant=\"transparent\"` / a solid group. */\n/* 2. ALL GLASS OR NONE — a glass item's row holds only glass items */\n/* (glass tap buttons, glass groups, or `data-matrx-glass` pieces). */\n/* 3. NEIGHBOURS KEEP THEIR HALF-GAP — a tap box carries 3px of unseen */\n/* space each side (box − pill = one gap, 6px). Anything beside it */\n/* adds its own 3px, so the visible distance is always one gap. */\n/* ------------------------------------------------------------------ */\n\nconst GLASS = \".matrx-glass-thin-border, .matrx-glass-interactive\";\n\nfunction isGlassItem(node: Element): boolean {\n if (node.hasAttribute(\"data-matrx-glass\")) return true;\n if (node.matches(\".matrx-tap-group\")) return node.querySelector(\":scope > .matrx-tap-group-capsule.matrx-glass-thin-border\") !== null;\n if (node.matches(\".matrx-tap-target\")) return node.querySelector(`:scope > .matrx-tap-pill:is(${GLASS})`) !== null;\n // A plain wrapper whose only content is ONE tap button (plus decor such as a\n // badge) is that button: a badge host around a glass button is glass.\n const view = node.ownerDocument.defaultView;\n if (view && isTapSlot(node, view)) return isGlassItem(node.querySelector(TAP_ITEM)!);\n return false;\n}\n\nconst SCROLLS = /^(auto|scroll|overlay)$/;\n\n/** True when `el` rides a bar over moving content: a fixed/sticky ancestor (or\n * a glass plane) reached BEFORE any scroll container. Inside a scroller the\n * button IS the moving content — an app root that is itself `position:\n * fixed` (the shell) must not make every page button \"float\". */\nfunction floats(el: Element, view: Window): boolean {\n for (let n: Element | null = el; n && n !== el.ownerDocument.body; n = n.parentElement) {\n if (n.hasAttribute(\"data-matrx-glass-plane\")) return true;\n const cs = view.getComputedStyle(n);\n if (cs.position === \"fixed\" || cs.position === \"sticky\") return true;\n if (n !== el && (SCROLLS.test(cs.overflowY) || SCROLLS.test(cs.overflowX))) return false;\n }\n return false;\n}\n\n/** True when the edge of `wrapper` that faces a neighbour (`side` is where the\n * wrapper sits relative to that neighbour) is itself a tap slot: that button\n * carries its own 3px half-gap, so the wrapper is spacing-correct however many\n * tap buttons it holds (the fading mic + More cluster beside Send). A wrapper\n * whose edge is text or a field is not — it still has to keep its distance. */\nfunction facesWithTapSlot(wrapper: Element, side: \"after\" | \"before\", view: Window): boolean {\n for (let node: Element | null = wrapper; node; ) {\n if (isTapSlot(node, view)) return true;\n const kids: Element[] = Array.from(node.children).filter((c) => !isDecor(c, view));\n node = (side === \"after\" ? kids[0] : kids[kids.length - 1]) ?? null;\n }\n return false;\n}\n\nfunction visible(el: Element, view: Window): boolean {\n if (el.getAttribute(\"aria-hidden\") === \"true\" || isDecor(el, view)) return false;\n const r = el.getBoundingClientRect();\n return r.width > 1 && r.height > 1;\n}\n\nconst INTERACTIVE = \"button, a[href], input, select, textarea, [role='button'], svg, img\";\n\n/** The box the eye sees on the side of `sib` that faces the tap button. An\n * unpainted layout wrapper (no fill, no border on that side, no words of its\n * own) is invisible, so the distance is judged at the first thing inside it —\n * the wrapper around ProTextarea's mic sits 3px from Expand while the mic\n * capsule, which keeps its own 3px margin, sits one gap away (2026-10-13). */\nfunction facingBox(sib: Element, side: \"after\" | \"before\", view: Window): Element {\n let node = sib;\n for (;;) {\n if (node.matches(INTERACTIVE)) return node;\n const cs = view.getComputedStyle(node);\n const fill = cs.backgroundColor;\n if ((fill && fill !== \"rgba(0, 0, 0, 0)\" && fill !== \"transparent\") || px(side === \"after\" ? cs.borderLeftWidth : cs.borderRightWidth) > 0) {\n return node;\n }\n if (Array.from(node.childNodes).some((c) => c.nodeType === 3 && c.textContent?.trim())) return node;\n const kids = Array.from(node.children).filter((c) => visible(c, view));\n const next = side === \"after\" ? kids[0] : kids[kids.length - 1];\n if (!next) return node;\n node = next;\n }\n}\n\n/** The first placement rule this tap button's surroundings break, or null. */\nexport function findTapPlacementWarning(el: HTMLElement): string | null {\n const doc = el.ownerDocument;\n const view = doc.defaultView;\n if (!view || !el.isConnected) return null;\n // A button inside a group is judged as its group.\n const slot: Element = el.closest(\".matrx-tap-group\") ?? el;\n const glass = isGlassItem(slot);\n\n if (glass && !floats(slot, view)) {\n return 'glass on a solid surface — glass only floats over moving content; use variant=\"transparent\" (or a solid group)';\n }\n\n const row = slot.parentElement;\n if (!row) return null;\n if (glass) {\n const mixed = Array.from(row.children).find((c) => c !== slot && visible(c, view) && !isGlassItem(c));\n if (mixed) return `glass beside non-glass ${describe(mixed)} — make the row all glass or none`;\n }\n\n const pill = (el.querySelector(\":scope > .matrx-tap-pill\") as HTMLElement | null) ?? (slot.querySelector(\".matrx-tap-group-capsule\") as HTMLElement | null);\n if (!pill) return null;\n const gap = px(view.getComputedStyle(el).getPropertyValue(\"--matrx-tap-gap\")) || 6;\n const p = pill.getBoundingClientRect();\n if (p.width === 0) return null;\n // Distances are judged in LAYOUT pixels: inside a zoomed (transformed) tile a screen distance\n // is the layout distance times the scale.\n const scale = layoutScale(pill);\n for (const [side, sib] of [[\"after\", slot.nextElementSibling], [\"before\", slot.previousElementSibling]] as const) {\n if (!sib || !visible(sib, view) || isTapSlot(sib, view) || isGlassItem(sib) || facesWithTapSlot(sib, side, view)) continue;\n if (Math.abs(sib.getBoundingClientRect().top + sib.getBoundingClientRect().height / 2 - (p.top + p.height / 2)) > p.height) continue; // not on this row\n const box = facingBox(sib, side, view);\n const r = box.getBoundingClientRect();\n const cs = view.getComputedStyle(box);\n const distance =\n (side === \"after\" ? r.left - p.right : p.left - r.right) / scale + (side === \"after\" ? px(cs.paddingLeft) : px(cs.paddingRight));\n if (distance < gap - 0.5) {\n return `${describe(sib)} sits ${Math.round(distance)}px from the pill — anything beside a tap button adds its own ${gap / 2}px (the box only carries ${gap / 2}px)`;\n }\n }\n return null;\n}\n\nconst reported = new Set<string>();\n\nfunction report(el: HTMLElement, reason: string) {\n el.setAttribute(\"data-matrx-tap-violation\", reason);\n const key = `${reason}@${el.getAttribute(\"aria-label\") ?? el.textContent ?? \"\"}`;\n if (reported.has(key)) return;\n reported.add(key);\n console.error(`[tap-target] ${reason}`, el);\n}\n\nconst mounted = new Set<HTMLElement>();\nlet resizeTimer: ReturnType<typeof setTimeout> | null = null;\nlet listening = false;\n\nfunction check(node: HTMLElement) {\n const reason = findTapViolation(node);\n if (reason) {\n report(node, reason);\n return;\n }\n node.removeAttribute(\"data-matrx-tap-violation\");\n const warning = findTapPlacementWarning(node);\n if (warning) {\n node.setAttribute(\"data-matrx-tap-warning\", warning);\n const key = `w:${warning}@${node.getAttribute(\"aria-label\") ?? \"\"}`;\n if (!reported.has(key)) {\n reported.add(key);\n console.error(`[tap-target] ${warning}`, node);\n }\n } else node.removeAttribute(\"data-matrx-tap-warning\");\n}\n\nfunction listenForResize(view: Window) {\n if (listening) return;\n listening = true;\n view.addEventListener(\"resize\", () => {\n if (resizeTimer) clearTimeout(resizeTimer);\n resizeTimer = setTimeout(() => mounted.forEach((n) => (n.isConnected ? check(n) : mounted.delete(n))), 200);\n });\n // A button is judged once, at mount — but its neighbours keep changing (a\n // loading placeholder becomes the real control). Re-judge a button when the\n // row it sits in gains or loses children, so a mark never outlives the\n // neighbour it named (2026-10-13: \"New run\" kept a red outline for a\n // skeleton that had already left the header).\n const Observer = (view as Window & { MutationObserver?: typeof MutationObserver }).MutationObserver;\n if (!Observer || !view.document.body) return;\n const changedRows = new Set<Node>();\n let rowTimer: ReturnType<typeof setTimeout> | null = null;\n new Observer((records) => {\n for (const r of records) changedRows.add(r.target);\n if (rowTimer) clearTimeout(rowTimer);\n rowTimer = setTimeout(() => {\n mounted.forEach((n) => {\n if (!n.isConnected) return void mounted.delete(n);\n const row = (n.closest(\".matrx-tap-group\") ?? n).parentElement;\n if (row && changedRows.has(row)) check(n);\n });\n changedRows.clear();\n }, 200);\n }).observe(view.document.body, { childList: true, subtree: true });\n}\n\nfunction assignRef<T>(ref: Ref<T> | undefined, value: T | null) {\n if (typeof ref === \"function\") ref(value);\n else if (ref) (ref as MutableRefObject<T | null>).current = value;\n}\n\n/**\n * The callback ref every tap trigger carries. In production it only forwards\n * the caller's ref; in development it also measures the trigger once it is in\n * the layout and paints a violation.\n */\nexport function useTapGuardRef<T extends HTMLElement>(\n forwarded: Ref<T> | undefined,\n propViolation: string | null,\n): (node: T | null) => void {\n const current = useRef<T | null>(null);\n return useCallback(\n (node: T | null) => {\n assignRef(forwarded, node);\n if (current.current && current.current !== node) mounted.delete(current.current);\n current.current = node;\n if (!guardOn() || !node) return;\n if (propViolation) {\n report(node, propViolation);\n return;\n }\n const view = node.ownerDocument.defaultView;\n if (!view) return;\n mounted.add(node);\n listenForResize(view);\n view.requestAnimationFrame(() => check(node));\n },\n [forwarded, propViolation],\n );\n}\n\n/* ------------------------------------------------------------------ */\n/* THE PILL-INSET GUARD (0.60.10). A pill is balanced when its INK sits */\n/* the same distance from both edges. On 2026-10-04 every icon+label */\n/* pill read off-centre (1.3–3.3px) because padding was shaved on the */\n/* glyph side by a guess at the glyph's air. The trim in tap-target.css */\n/* now removes each glyph's real air; this measures the result in the */\n/* real layout and marks any pill whose ink insets differ by more than */\n/* 2px — dashed red outline + one console error naming both numbers. */\n/* ------------------------------------------------------------------ */\n\nconst PILL_TOLERANCE_PX = 2;\nconst PILL_ITEMS = \"button, a[href], [role='button'], [role='tab'], [role='radio'], [role='menuitem']\";\nconst PILL_CANDIDATES = \"button, a[href], [role='button'], .rounded-full, .matrx-tap-pill-inline, .matrx-tap-pill-mobile-icon-only\";\n\n/** Horizontal ink extents inside `el`: glyph geometry for svgs, text runs for text. */\nfunction inkExtents(el: Element): { left: number; right: number } | null {\n const doc = el.ownerDocument;\n const view = doc.defaultView;\n if (!view) return null;\n let left = Infinity;\n let right = -Infinity;\n const walker = doc.createTreeWalker(el, 0x1 | 0x4 /* SHOW_ELEMENT | SHOW_TEXT */);\n let n: Node | null;\n while ((n = walker.nextNode())) {\n if (n.nodeType === 1) {\n const node = n as Element;\n const cs = view.getComputedStyle(node);\n if (cs.display === \"none\" || cs.visibility === \"hidden\" || cs.position === \"absolute\") continue;\n const tag = node.tagName.toLowerCase();\n if (tag === \"img\" || tag === \"picture\" || tag === \"video\" || tag === \"canvas\") {\n // A picture (a favicon, an avatar) is ink by its box — it draws its own pixels, and a logo\n // renders exactly as it is, never tinted to make a guard see it (2026-10-13: every\n // favicon-led link pill read \"29px left vs 10px right\" because the image was invisible here).\n const r = node.getBoundingClientRect();\n if (r.width > 0) {\n left = Math.min(left, r.left);\n right = Math.max(right, r.right);\n }\n continue;\n }\n if (tag !== \"svg\" && (node.getAttribute(\"role\") === \"status\" || node.getAttribute(\"role\") === \"progressbar\")) {\n // A busy spinner drawn with borders (its rings are absolute, so nothing below sees them)\n // is ink by its box: a pill whose icon turned into a spinner read \"44px left vs 20px right\".\n const r = node.getBoundingClientRect();\n if (r.width > 0) {\n left = Math.min(left, r.left);\n right = Math.max(right, r.right);\n }\n continue;\n }\n if (tag !== \"svg\") {\n // A painted chip inside the pill (a count badge) is ink by its box: its fill is what the eye sees.\n const paintedChip = (cs.backgroundColor !== \"rgba(0, 0, 0, 0)\" && cs.backgroundColor !== \"transparent\") || parseFloat(cs.borderLeftWidth) > 0;\n if (paintedChip) {\n const r = node.getBoundingClientRect();\n if (r.width > 0) {\n left = Math.min(left, r.left);\n right = Math.max(right, r.right);\n }\n }\n continue;\n }\n const svg = node as SVGGraphicsElement;\n if (typeof svg.getBBox !== \"function\" || typeof svg.getScreenCTM !== \"function\") continue;\n const bb = svg.getBBox();\n const ctm = svg.getScreenCTM();\n if (!ctm || bb.width === 0) continue;\n if (Math.abs(ctm.b) > 0.001 || Math.abs(ctm.c) > 0.001) {\n // A turning glyph (a busy spinner) has no fixed ink: judge it by its layout box, centered\n // where the rotation centers it — never by a mid-turn snapshot of its paths.\n const r = node.getBoundingClientRect();\n const half = (parseFloat(cs.width) || r.width) / 2;\n const mid = r.left + r.width / 2;\n left = Math.min(left, mid - half);\n right = Math.max(right, mid + half);\n continue;\n }\n const half = ((parseFloat(cs.strokeWidth) || 0) * Math.abs(ctm.a)) / 2;\n const x1 = ctm.a * bb.x + ctm.e;\n const x2 = ctm.a * (bb.x + bb.width) + ctm.e;\n left = Math.min(left, Math.min(x1, x2) - half);\n right = Math.max(right, Math.max(x1, x2) + half);\n } else if (n.nodeValue && n.nodeValue.trim()) {\n const parent = n.parentElement;\n if (!parent || parent.closest(\"svg\")) continue;\n const pcs = view.getComputedStyle(parent);\n if (pcs.visibility === \"hidden\" || pcs.position === \"absolute\") continue;\n const range = doc.createRange();\n range.selectNodeContents(n);\n // A truncated label (`truncate max-w-*`) draws only what its clipping box shows: its text\n // run keeps going past the ellipsis, so the run is clipped to every overflow-hiding box\n // between it and the pill (2026-10-18: a scope chip \"matrx-frontend (LCP test)\" read\n // \"9.0px left vs 5.7px right\" while its ellipsis sat exactly 9px from the edge).\n const clip = textClip(parent, el, view);\n for (const r of Array.from(range.getClientRects())) {\n if (r.width <= 0) continue;\n const rl = Math.max(r.left, clip.left);\n const rr = Math.min(r.right, clip.right);\n if (rr <= rl) continue;\n left = Math.min(left, rl);\n right = Math.max(right, rr);\n }\n }\n }\n return Number.isFinite(left) && Number.isFinite(right) ? { left, right } : null;\n}\n\n/** The horizontal window a text run can paint in: its overflow-clipping ancestors up to (excluding) `pill`. */\nfunction textClip(from: Element, pill: Element, view: Window): { left: number; right: number } {\n let left = -Infinity;\n let right = Infinity;\n for (let node: Element | null = from; node && node !== pill; node = node.parentElement) {\n const cs = view.getComputedStyle(node);\n // overflow-x, or the shorthand's first (x) value where a runtime does not expand it (jsdom)\n const clipsX = (cs.overflowX && cs.overflowX !== \"visible\") || (cs.overflow && !cs.overflow.startsWith(\"visible\"));\n if (clipsX) {\n const r = node.getBoundingClientRect();\n if (r.width > 0) {\n left = Math.max(left, r.left);\n right = Math.min(right, r.right);\n }\n }\n }\n return { left, right };\n}\n\nconst FIELDS = \"input, textarea, select, [contenteditable='true'], [role='textbox'], [role='searchbox'], [role='combobox']\";\n\n/**\n * Only a BUTTON can be a pill whose ink must balance: an interactive element,\n * or the painted pill inside one (a tap button's `.matrx-tap-pill-inline`).\n * A field — or a capsule that holds one, like a rounded search box — aligns its\n * text to an edge by design, and a non-interactive container (a status chip, a\n * wrapper painted `rounded-full`) is never a pill button (2026-10-09: the\n * messenger's search field and messaging's AI chips wore the red outline).\n */\nexport function isPillButton(el: Element): boolean {\n if (el.matches(FIELDS) || el.querySelector(FIELDS) !== null) return false;\n if (el.matches(PILL_ITEMS)) return true;\n if (el.parentElement?.closest(PILL_ITEMS)) return true;\n return el.querySelector(PILL_ITEMS) !== null;\n}\n\n/** Why this pill's ink is off-centre, or null. Only judges a pill — a capsule\n * (radius ≥ half its height) with its own fill or border, carrying ink. */\nexport function findPillInsetWarning(el: HTMLElement): string | null {\n const view = el.ownerDocument.defaultView;\n if (!view || !el.isConnected) return null;\n if (!isPillButton(el)) return null;\n const box = el.getBoundingClientRect();\n const scale = layoutScale(el);\n if (box.width / scale < 20 || box.height / scale < 16 || box.height / scale > 48) return null;\n const cs = view.getComputedStyle(el);\n if (parseFloat(cs.borderTopLeftRadius) < box.height / scale / 2 - 1) return null;\n const painted = cs.backgroundColor !== \"rgba(0, 0, 0, 0)\" && cs.backgroundColor !== \"transparent\";\n if (!painted && !(parseFloat(cs.borderLeftWidth) > 0)) return null;\n // A wide capsule (a stretched select or field) aligns content to an edge on purpose.\n if (box.width / scale > 320) return null;\n // Ink balance is a question only for CENTERED content. A select trigger (value left, chevron\n // right), a field, or a full-width action row that says justify-start aligns its content on\n // purpose — content alignment is placement, not an inset to balance.\n if (cs.display.includes(\"flex\") && ![\"center\", \"normal\"].includes(cs.justifyContent)) return null;\n if (el.matches(\"[data-matrx-control='select'], [data-matrx-control='field']\")) return null;\n // A switch, checkbox or slider carries STATE, not a label: its thumb sits at one end by design\n // (measured 2026-10-04: every connector switch read \"18px left vs 2px right\" in the chat composer).\n if (el.matches(\"[role='switch'], [role='checkbox'], [role='slider'], [role='radio']\")) return null;\n // A TRACK of several controls (a segmented nav, a tab strip) is a container, not a pill: its\n // items sit where the selection puts them, so the ink is lopsided by design — each item is\n // judged on its own (measured 2026-10-05: the shell route nav's icon track read 2px vs 12.5px\n // at 768 because the selected item's fill hugs one end and the last glyph carries its air).\n if (el.querySelectorAll(PILL_ITEMS).length > 1) return null;\n const ink = inkExtents(el);\n if (!ink) return null;\n const left = (ink.left - box.left) / scale;\n const right = (box.right - ink.right) / scale;\n if (left < 0 || right < 0) return null; // clipped / overflowing content: not this guard's question\n if (Math.abs(left - right) <= PILL_TOLERANCE_PX) return null;\n return `pill ink is off-centre: ${left.toFixed(1)}px left vs ${right.toFixed(1)}px right — pad both sides alike and let the glyph trim (tap-target.css, THE OPTICAL GLYPH TRIM) remove the glyph's air; never shave one side by hand`;\n}\n\nlet pillTimer: ReturnType<typeof setTimeout> | null = null;\nlet pillObserver: MutationObserver | null = null;\n\nfunction scanPills(doc: Document) {\n if (!guardOn()) return;\n for (const node of Array.from(doc.querySelectorAll<HTMLElement>(PILL_CANDIDATES))) {\n // A tap button's own pill is judged, not its invisible box.\n if (node.classList.contains(\"matrx-tap-target\")) continue;\n const warning = findPillInsetWarning(node);\n if (warning) {\n if (node.getAttribute(\"data-matrx-pill-inset-warning\") === warning) continue;\n node.setAttribute(\"data-matrx-pill-inset-warning\", warning);\n const key = `p:${warning}@${(node.textContent ?? \"\").trim().slice(0, 40)}`;\n if (!reported.has(key)) {\n reported.add(key);\n console.error(`[tap-target] ${warning}`, node);\n }\n } else if (node.hasAttribute(\"data-matrx-pill-inset-warning\")) {\n node.removeAttribute(\"data-matrx-pill-inset-warning\");\n }\n }\n}\n\nfunction startPillInsetScan() {\n if (pillObserver || typeof document === \"undefined\" || typeof MutationObserver === \"undefined\") return;\n const doc = document;\n const schedule = () => {\n if (pillTimer) clearTimeout(pillTimer);\n pillTimer = setTimeout(() => scanPills(doc), 600);\n };\n pillObserver = new MutationObserver((records) => {\n // Our own attribute writes must not re-trigger the scan.\n if (records.every((r) => r.type === \"attributes\" && r.attributeName === \"data-matrx-pill-inset-warning\")) return;\n schedule();\n });\n const begin = () => {\n pillObserver?.observe(doc.body, { childList: true, subtree: true, characterData: true, attributes: true, attributeFilter: [\"class\", \"style\", \"data-matrx-pill-inset-warning\"] });\n schedule();\n };\n if (doc.body) begin();\n else doc.addEventListener(\"DOMContentLoaded\", begin, { once: true });\n}\n","// THE LAYOUT SCALE (0.62.4). The dev guards (pill guard, tap-target guard) judge spacing, ink\n// balance and width in LAYOUT pixels — the numbers a stylesheet writes. `getBoundingClientRect`\n// returns SCREEN pixels, so inside a CSS-transformed (zoomed) container — every Board tile at\n// overview zoom — a correct 11px gap read 5.3px at 0.48 and warned falsely. The effective scale\n// is the ratio of an element's drawn width to its layout width (`offsetWidth`, which ignores\n// transforms), taken from the nearest ancestor-or-self that has a box. 1 when no engine reports\n// layout (jsdom) or the ratio is within 2% of 1, so a real violation at scale 1 reads unchanged.\n\nexport function layoutScale(el: Element | null): number {\n for (let n: Element | null = el; n; n = n.parentElement) {\n const w = (n as HTMLElement).offsetWidth;\n if (!w) continue;\n const drawn = n.getBoundingClientRect().width;\n if (!(drawn > 0)) continue;\n const s = drawn / w;\n if (!Number.isFinite(s) || s <= 0) return 1;\n return Math.abs(s - 1) < 0.02 ? 1 : s;\n }\n return 1;\n}\n","\"use client\";\n\nimport { createContext, useContext, type ReactNode } from \"react\";\n\n/** The surface a tap group sits on. \"glass\" floats over moving content; \"solid\" is a page, card,\n * toast or a header row that is itself a solid band. */\nexport type TapSurfaceKind = \"glass\" | \"solid\";\n\n// Shared through a Symbol.for slot on globalThis (like the default-variant context): the `.` and\n// `./buttons` dist bundles each inline this module, and a provider rendered by one must reach\n// buttons rendered by the other.\nconst SLOT = Symbol.for(\"@ai-matrx/tap-target:surface\");\ntype GlobalWithSlot = typeof globalThis & { [SLOT]?: ReturnType<typeof createContext<TapSurfaceKind>> };\nconst TapSurfaceContext = ((globalThis as GlobalWithSlot)[SLOT] ??= createContext<TapSurfaceKind>(\"glass\"));\n\n/**\n * GLASS ONLY FLOATS, declared once by the surface. A host whose header (or any region) is a solid\n * row wraps it in `<TapSurface surface=\"solid\">`; every `TapTargetButtonGroup` /\n * `TapTargetSearchGroup` inside then renders solid by itself — no per-page `surface=\"solid\"`.\n * A group's own `surface` prop still wins.\n */\nexport function TapSurface({ surface, children }: { surface: TapSurfaceKind; children: ReactNode }) {\n return <TapSurfaceContext.Provider value={surface}>{children}</TapSurfaceContext.Provider>;\n}\n\n/** The group's surface: its explicit prop, else the nearest `<TapSurface>`, else glass. */\nexport function useTapSurface(explicit: TapSurfaceKind | undefined): TapSurfaceKind {\n const inherited = useContext(TapSurfaceContext);\n return explicit ?? inherited;\n}\n","\"use client\";\n\n// THE BUILT-IN CAPABILITIES of every tap button — each one an enum or a flag,\n// never a class a caller writes. Rendering and geometry live in tap-target.css\n// (`.matrx-tap-badge`, `.matrx-tap-pressed`, `.matrx-tap-chevron`, …).\n\nimport { useEffect, type ReactNode } from \"react\";\n\nimport { MOTION_SPIN } from \"../motion\";\nimport { formatTapShortcut, parseShortcut, type TapShortcut } from \"../tap-shortcut\";\n\n/** Glyph color. Replaces the free-form `className`. */\nexport type TapTone = \"default\" | \"muted\" | \"primary\" | \"destructive\" | \"success\" | \"warning\" | \"info\";\n\n/** Fill of a solid button. Replaces `bgColor` / `iconColor` / hover / active. */\nexport type TapSolidTone = \"primary\" | \"destructive\" | \"success\" | \"warning\" | \"neutral\";\n\nexport const TAP_TONE_CLASS: Record<TapTone, string> = {\n default: \"text-foreground\",\n muted: \"text-muted-foreground group-hover/tap:text-foreground\",\n primary: \"text-primary-ink\",\n destructive: \"text-destructive-ink\",\n success: \"text-success-ink\",\n warning: \"text-warning-ink\",\n info: \"text-info-ink\",\n};\n\nexport const TAP_SOLID_TONE: Record<TapSolidTone, { fill: string; glyph: string }> = {\n primary: { fill: \"bg-primary group-hover/tap:bg-primary/85\", glyph: \"text-primary-foreground\" },\n destructive: { fill: \"bg-danger-fill group-hover/tap:bg-danger-fill/85\", glyph: \"text-danger-fill-foreground\" },\n success: { fill: \"bg-success-fill group-hover/tap:bg-success-fill/85\", glyph: \"text-success-fill-foreground\" },\n warning: { fill: \"bg-warning group-hover/tap:bg-warning/85\", glyph: \"text-warning-foreground\" },\n neutral: { fill: \"bg-foreground group-hover/tap:bg-foreground/85\", glyph: \"text-background\" },\n};\n\n/**\n * A keyboard shortcut: modifiers joined by \"+\", then one key —\n * \"mod+k\" (⌘ on Apple, Ctrl elsewhere), \"shift+mod+p\", \"alt+n\", \"/\", \"?\".\n */\nexport { formatTapShortcut, parseShortcut, type TapShortcut };\n\nexport interface TapFeatureProps {\n /** Glyph color, from the system's list. */\n tone?: TapTone | undefined;\n /** A count (99+ past 99) or a dot, drawn on the pill's corner by the system. */\n badge?: number | \"dot\" | undefined;\n /** A toggle that is on (sidebar open, filter on): tinted pill + aria-pressed. */\n pressed?: boolean | undefined;\n /** Work in flight: the glyph becomes a spinner and presses are ignored. */\n loading?: boolean | undefined;\n /** Why the button cannot be used — disables it and becomes its tooltip. */\n disabledReason?: string | undefined;\n /** Keyboard shortcut that presses the button; shown in its tooltip. */\n shortcut?: TapShortcut | undefined;\n /** A menu trigger: a small chevron after the label. */\n chevron?: boolean | undefined;\n}\n\nfunction isTyping(target: EventTarget | null): boolean {\n const el = target as HTMLElement | null;\n return !!el && (el.isContentEditable || /^(INPUT|TEXTAREA|SELECT)$/.test(el.tagName));\n}\n\nexport function matchesTapShortcut(e: KeyboardEvent, shortcut: TapShortcut): boolean {\n const p = parseShortcut(shortcut);\n if ((e.metaKey || e.ctrlKey) !== p.mod || e.altKey !== p.alt) return false;\n // \"?\" and other shifted symbols arrive with shiftKey set — only compare\n // shift for letters and named keys.\n if (/^[a-z0-9]$|^[a-z]{2,}$/.test(p.key) && e.shiftKey !== p.shift) return false;\n if (!p.mod && isTyping(e.target)) return false;\n return e.key.toLowerCase() === p.key;\n}\n\n/** Presses `node` when its shortcut is typed anywhere on the page. */\nexport function useTapShortcut(shortcut: TapShortcut | undefined, getNode: () => HTMLElement | null, enabled: boolean) {\n useEffect(() => {\n if (!shortcut || !enabled) return;\n const onKey = (e: KeyboardEvent) => {\n if (!matchesTapShortcut(e, shortcut)) return;\n const node = getNode();\n if (!node || !node.isConnected) return;\n e.preventDefault();\n node.click();\n };\n window.addEventListener(\"keydown\", onKey);\n return () => window.removeEventListener(\"keydown\", onKey);\n }, [shortcut, enabled, getNode]);\n}\n\nexport function TapBadge({ badge }: { badge: number | \"dot\" }) {\n if (badge === \"dot\") return <span aria-hidden=\"true\" className=\"matrx-tap-badge\" data-dot=\"\" />;\n if (badge <= 0) return null;\n return (\n <span aria-hidden=\"true\" className=\"matrx-tap-badge\">\n {badge > 99 ? \"99+\" : badge}\n </span>\n );\n}\n\nexport function TapSpinner({ className }: { className: string }) {\n return (\n <svg className={className} fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={2} aria-hidden=\"true\">\n <circle\n className={MOTION_SPIN}\n cx=\"12\"\n cy=\"12\"\n r=\"9\"\n strokeDasharray=\"28.27\"\n strokeDashoffset=\"9\"\n strokeLinecap=\"round\"\n style={{ transformOrigin: \"12px 12px\" }}\n />\n </svg>\n );\n}\n\nexport function TapChevron() {\n return (\n <svg\n className=\"matrx-tap-chevron\"\n aria-hidden=\"true\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n strokeWidth={2}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <path d=\"m6 9 6 6 6-6\" />\n </svg>\n );\n}\n\n/** Tooltip body: the label, then the shortcut as a key cap. */\nexport function tooltipBody(label: string, shortcut: TapShortcut | undefined): ReactNode {\n if (!shortcut) return label;\n return (\n <span className=\"matrx-tap-tooltip\">\n {label}\n <kbd className=\"matrx-tap-kbd\">{formatTapShortcut(shortcut)}</kbd>\n </span>\n );\n}\n","// src/tap-shortcut.ts — @ai-matrx/design-system/tap-shortcut\n//\n// THE ONE SHORTCUT FORMATTER, light (FB5, 2026-10-23). `formatTapShortcut` (\"mod+k\" → \"⌘K\" on Apple, \"Ctrl+K\"\n// elsewhere) is pure; it lived in tap-target's \"use client\" feature module, so a plain helper that only needed the\n// words (records-ui's table action list) had to import the whole tap-target entry and was itself stamped\n// \"use client\". This entry carries the parse and the words only — no React. `./tap-target` re-exports both.\n\n/** A keyboard shortcut, written \"mod+k\", \"shift+?\", \"alt+enter\". */\nexport type TapShortcut = string;\n\nexport interface ParsedShortcut {\n mod: boolean;\n shift: boolean;\n alt: boolean;\n key: string;\n}\n\nconst IS_APPLE =\n typeof navigator !== \"undefined\" && /Mac|iPhone|iPad|iPod/.test(navigator.platform || navigator.userAgent);\n\nexport function parseShortcut(shortcut: TapShortcut): ParsedShortcut {\n const parts = shortcut.toLowerCase().split(\"+\");\n const key = parts.pop() ?? \"\";\n return { mod: parts.includes(\"mod\"), shift: parts.includes(\"shift\"), alt: parts.includes(\"alt\"), key };\n}\n\n/** \"mod+k\" → \"⌘K\" on Apple, \"Ctrl+K\" elsewhere. */\nexport function formatTapShortcut(shortcut: TapShortcut): string {\n const p = parseShortcut(shortcut);\n const key = p.key.length === 1 ? p.key.toUpperCase() : p.key[0]!.toUpperCase() + p.key.slice(1);\n if (IS_APPLE) return `${p.alt ? \"⌥\" : \"\"}${p.shift ? \"⇧\" : \"\"}${p.mod ? \"⌘\" : \"\"}${key}`;\n return [p.mod && \"Ctrl\", p.alt && \"Alt\", p.shift && \"Shift\", key].filter(Boolean).join(\"+\");\n}\n","import type { ComponentType, ReactNode, Ref } from \"react\";\n\n/**\n * The injectable link seam — the package's replacement for the original\n * hard `next/link` import.\n *\n * Internal hrefs (anything NOT matching `http(s):`, `mailto:`, `tel:`) render\n * through the link component resolved here; external hrefs always render a\n * plain `<a target=\"_blank\" rel=\"noopener noreferrer\">`, exactly like the\n * original. When nothing is registered and no per-instance `linkComponent`\n * prop is given, internal hrefs fall back to a plain `<a>` (no prefetch, no\n * client-side routing — still a working link).\n */\nexport interface TapTargetLinkProps {\n href: string;\n target?: \"_blank\" | \"_self\" | \"_parent\" | \"_top\" | undefined;\n rel?: string | undefined;\n /** Router prefetch hint (next/link semantics). Plain `<a>` fallback ignores it. */\n prefetch?: boolean | null | undefined;\n \"aria-label\"?: string | undefined;\n /** Tooltip text drawn through `title` (the provider's title takeover). */\n title?: string | undefined;\n className?: string | undefined;\n children?: ReactNode;\n /** The trigger's ref (the development guard measures the rendered link).\n * next/link forwards it to its `<a>`. */\n ref?: Ref<HTMLAnchorElement> | undefined;\n}\n\nexport type TapTargetLinkComponent = ComponentType<TapTargetLinkProps>;\n\n/**\n * The registered component lives in a `Symbol.for` slot on `globalThis` — NOT\n * in module state — so it survives the module graph being instantiated more\n * than once: the `.` and `./buttons` dist bundles each inline the primitives\n * (tsup `splitting: false`), and a consumer may even mix `import` and\n * `require`. One registration must reach every copy.\n */\nconst LINK_SLOT = Symbol.for(\"@ai-matrx/tap-target:link-component\");\n\ntype GlobalWithLinkSlot = typeof globalThis & {\n [LINK_SLOT]?: TapTargetLinkComponent | null;\n};\n\n/**\n * Register the app's link component once at startup (e.g. `next/link`):\n *\n * ```tsx\n * import Link from \"next/link\";\n * import { setTapTargetLinkComponent } from \"@ai-matrx/tap-target\";\n * setTapTargetLinkComponent(Link);\n * ```\n *\n * Pass `null` to unregister (plain `<a>` fallback resumes).\n */\nexport function setTapTargetLinkComponent(\n component: TapTargetLinkComponent | null,\n): void {\n (globalThis as GlobalWithLinkSlot)[LINK_SLOT] = component;\n}\n\n/** The currently registered link component, or `null` when none is set. */\nexport function getTapTargetLinkComponent(): TapTargetLinkComponent | null {\n return (globalThis as GlobalWithLinkSlot)[LINK_SLOT] ?? null;\n}\n","\"use client\";\n\nimport { forwardRef, type Ref } from \"react\";\n// The spinner loop comes from `@ai-matrx/design-system`'s motion layer — the\n// package this one already depends on — NOT from core Tailwind's\n// `animate-spin` and NOT from a keyframe copied into this package's\n// stylesheet. See the note above `LoadingTapButton`.\nimport { MOTION_SPIN } from \"../motion\";\nimport {\n TapTargetButton,\n TapTargetButtonTransparent,\n TapTargetButtonOutline,\n TapTargetButtonSolid,\n TapTargetButtonForGroup,\n} from \"./tap-target-button\";\nimport type { TapTargetLinkComponent } from \"./link\";\nimport { useTapButtonVariant } from \"./tap-default-variant\";\nimport type { TapFeatureProps, TapSolidTone } from \"./tap-features\";\n\n// ---------------------------------------------------------------------------\n// Shared types\n// ---------------------------------------------------------------------------\n\ntype Variant = \"glass\" | \"transparent\" | \"outline\" | \"solid\" | \"group\";\n\nexport interface TapButtonProps extends TapFeatureProps {\n /** Forwarded to the underlying button (Radix `asChild`, focus chains, etc.). */\n ref?: Ref<HTMLButtonElement> | undefined;\n variant?: Variant | undefined;\n onClick?: (() => void) | undefined;\n as?: \"button\" | \"label\" | undefined;\n htmlFor?: string | undefined;\n ariaLabel?: string | undefined;\n disabled?: boolean | undefined;\n tabIndex?: number | undefined;\n className?: string | undefined;\n strokeWidth?: number | undefined;\n // Solid-variant color overrides — only used when variant=\"solid\"\n bgColor?: string | undefined;\n iconColor?: string | undefined;\n hoverBgColor?: string | undefined;\n activeBgColor?: string | undefined;\n // Link support — when set, the button renders as a link or <a>.\n // Internal hrefs use the injected link component (setTapTargetLinkComponent\n // or the `linkComponent` prop; plain <a> when none is registered); external\n // (http(s)://, mailto:, tel:) use <a> with target=\"_blank\" +\n // rel=\"noopener noreferrer\" by default. Pass an explicit `target` to\n // override (works for internal links too).\n href?: string | undefined;\n target?: \"_blank\" | \"_self\" | \"_parent\" | \"_top\" | undefined;\n rel?: string | undefined;\n prefetch?: boolean | null | undefined;\n /** Per-instance link component override for internal hrefs. */\n linkComponent?: TapTargetLinkComponent | undefined;\n // Tooltip support — defaults to `ariaLabel`. Pass `false` to opt out.\n tooltip?: string | false | undefined;\n tooltipSide?: \"top\" | \"right\" | \"bottom\" | \"left\" | undefined;\n tooltipAlign?: \"start\" | \"center\" | \"end\" | undefined;\n /** Inline caption after the icon — see TapTargetButton `label`. */\n label?: string | undefined;\n /** Passthrough from AITapButtonProps / MakerTapButton — stripped before DOM. */\n colored?: boolean | undefined;\n}\n\n// ---------------------------------------------------------------------------\n// Variant resolver — maps a variant string to the correct wrapper component.\n// Runs at build/server time so there's zero client cost.\n//\n// IMPORTANT: `Wrap` MUST forward refs. The pre-composed `*TapButton` functions\n// below are plain function components (in React 19 ref is a regular prop) and\n// spread `{...props}` to `Wrap` — that spread carries ref through. `Wrap`\n// extracts ref and passes it explicitly to the underlying `forwardRef`\n// primitive. Without this, every `*TapButton` placed inside a Radix\n// `*Trigger asChild` (DropdownMenu, Popover, Tooltip, etc.) silently loses\n// the ref — the popper can't anchor and Radix's injected event handlers /\n// `data-state` / `aria-*` get dropped. (Precedent: matrx-frontend\n// `features/files/FEATURE.md`, where this pattern was established.)\n// ---------------------------------------------------------------------------\n\nconst Wrap = forwardRef<\n HTMLButtonElement,\n TapButtonProps & { children: React.ReactNode }\n>(function Wrap(\n {\n variant: variantProp,\n children,\n bgColor,\n iconColor,\n hoverBgColor,\n activeBgColor,\n // AITapButtonProps passthrough — not a DOM attribute (see ai-tap-buttons Wrap)\n colored: _colored,\n ...props\n },\n ref,\n) {\n const variant = useTapButtonVariant(variantProp);\n switch (variant) {\n case \"transparent\":\n return (\n <TapTargetButtonTransparent ref={ref} {...props}>\n {children}\n </TapTargetButtonTransparent>\n );\n case \"outline\":\n return (\n <TapTargetButtonOutline ref={ref} {...props}>\n {children}\n </TapTargetButtonOutline>\n );\n case \"solid\": {\n // On a solid button `tone` is the FILL; a glyph-only tone (\"muted\",\n // \"default\", \"info\") has no fill meaning and falls back to primary.\n const { tone, ...solidProps } = props;\n const fill: TapSolidTone | undefined =\n tone === \"primary\" || tone === \"destructive\" || tone === \"success\" || tone === \"warning\" ? tone : undefined;\n return (\n <TapTargetButtonSolid\n ref={ref}\n tone={fill}\n bgColor={bgColor}\n iconColor={iconColor}\n hoverBgColor={hoverBgColor}\n activeBgColor={activeBgColor}\n {...solidProps}\n >\n {children}\n </TapTargetButtonSolid>\n );\n }\n case \"group\":\n return (\n <TapTargetButtonForGroup ref={ref} {...props}>\n {children}\n </TapTargetButtonForGroup>\n );\n default:\n return (\n <TapTargetButton ref={ref} {...props}>\n {children}\n </TapTargetButton>\n );\n }\n});\n\n// ---------------------------------------------------------------------------\n// Pre-composed buttons — one import, one tag, zero configuration needed.\n// Default variant is \"glass\". Override with variant=\"transparent\" etc.\n// All SVG paths match lucide-react v0.577.0 exactly.\n// ---------------------------------------------------------------------------\n\n// lucide: menu (hand-crafted HeroIcons path — no Lucide equivalent, kept as-is)\nexport function MenuTapButton(props: TapButtonProps) {\n return (\n <Wrap ariaLabel=\"Menu\" strokeWidth={1.75} {...props}>\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n d=\"M3.75 6.75h16.5M3.75 12h16.5m-16.5 5.25h16.5\"\n />\n </Wrap>\n );\n}\n\n// lucide: plus (hand-crafted — no drift, kept as-is)\nexport function PlusTapButton(props: TapButtonProps) {\n return (\n <Wrap ariaLabel=\"Add\" {...props}>\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n d=\"M12 4.5v15m7.5-7.5h-15\"\n />\n </Wrap>\n );\n}\n\n// lucide: search → circle cx=11 cy=11 r=8 + line to 21,21\nexport function SearchTapButton(props: TapButtonProps) {\n return (\n <Wrap ariaLabel=\"Search\" {...props}>\n <circle cx=\"11\" cy=\"11\" r=\"8\" />\n <path d=\"m21 21-4.34-4.34\" />\n </Wrap>\n );\n}\n\n// lucide: settings (hand-crafted — kept as-is, Lucide uses \"settings-2\" pattern)\nexport function SettingsTapButton(props: TapButtonProps) {\n return (\n <Wrap ariaLabel=\"Settings\" {...props}>\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n d=\"M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z\"\n />\n </Wrap>\n );\n}\n\n// lucide: maximize (hand-crafted corner-arrows — kept as-is)\nexport function MaximizeTapButton(props: TapButtonProps) {\n return (\n <Wrap ariaLabel=\"Fullscreen\" {...props}>\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n d=\"M3.75 3.75v4.5m0-4.5h4.5m-4.5 0L9 9M3.75 20.25v-4.5m0 4.5h4.5m-4.5 0L9 15M20.25 3.75h-4.5m4.5 0v4.5m0-4.5L15 9m5.25 11.25h-4.5m4.5 0v-4.5m0 4.5L15 15\"\n />\n </Wrap>\n );\n}\n\n// lucide: home v0.577.0 — used as the \"Hub\" (main/list) action\nexport function HomeTapButton(props: TapButtonProps) {\n return (\n <Wrap ariaLabel=\"Hub\" {...props}>\n <path d=\"M15 21v-8a1 1 0 0 0-1-1h-4a1 1 0 0 0-1 1v8\" />\n <path d=\"M3 10a2 2 0 0 1 .709-1.528l7-5.999a2 2 0 0 1 2.582 0l7 5.999A2 2 0 0 1 21 10v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z\" />\n </Wrap>\n );\n}\n\n// lucide: layout-grid v0.577.0\nexport function LayoutGridTapButton(props: TapButtonProps) {\n return (\n <Wrap ariaLabel=\"Card view\" {...props}>\n <rect width=\"7\" height=\"7\" x=\"3\" y=\"3\" rx=\"1\" />\n <rect width=\"7\" height=\"7\" x=\"14\" y=\"3\" rx=\"1\" />\n <rect width=\"7\" height=\"7\" x=\"14\" y=\"14\" rx=\"1\" />\n <rect width=\"7\" height=\"7\" x=\"3\" y=\"14\" rx=\"1\" />\n </Wrap>\n );\n}\n\n// lucide: list v0.577.0\nexport function ListTapButton(props: TapButtonProps) {\n return (\n <Wrap ariaLabel=\"Table view\" {...props}>\n <path d=\"M3 5h.01\" />\n <path d=\"M3 12h.01\" />\n <path d=\"M3 19h.01\" />\n <path d=\"M8 5h13\" />\n <path d=\"M8 12h13\" />\n <path d=\"M8 19h13\" />\n </Wrap>\n );\n}\n\n// lucide: arrow-down-up (hand-crafted — kept as-is)\nexport function ArrowDownUpTapButton(props: TapButtonProps) {\n return (\n <Wrap ariaLabel=\"Sort\" {...props}>\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n d=\"M3 4.5h14.25M3 9h9.75M3 13.5h5.25m5.25-.75L17.25 9m0 0L21 12.75M17.25 9v10.5\"\n />\n </Wrap>\n );\n}\n\n// lucide: bell v0.577.0\nexport function BellTapButton(props: TapButtonProps) {\n return (\n <Wrap ariaLabel=\"Notifications\" {...props}>\n <path d=\"M10.268 21a2 2 0 0 0 3.464 0\" />\n <path d=\"M3.262 15.326A1 1 0 0 0 4 17h16a1 1 0 0 0 .74-1.673C19.41 13.956 18 12.499 18 8A6 6 0 0 0 6 8c0 4.499-1.411 5.956-2.738 7.326\" />\n </Wrap>\n );\n}\n\n// lucide: bell-ring v0.577.0 — animated cousin of bell, used for \"has unread\"\nexport function BellRingTapButton(props: TapButtonProps) {\n return (\n <Wrap ariaLabel=\"Notifications\" {...props}>\n <path d=\"M10.268 21a2 2 0 0 0 3.464 0\" />\n <path d=\"M22 8c0-2.3-.8-4.3-2-6\" />\n <path d=\"M3.262 15.326A1 1 0 0 0 4 17h16a1 1 0 0 0 .74-1.673C19.41 13.956 18 12.499 18 8A6 6 0 0 0 6 8c0 4.499-1.411 5.956-2.738 7.326\" />\n <path d=\"M4 2C2.8 3.7 2 5.7 2 8\" />\n </Wrap>\n );\n}\n\n// lucide: zap v0.577.0 — lightning bolt, used as the Quick Actions trigger\nexport function ZapTapButton(props: TapButtonProps) {\n return (\n <Wrap ariaLabel=\"Quick actions\" {...props}>\n <path d=\"M4 14a1 1 0 0 1-.78-1.63l9.9-10.2a.5.5 0 0 1 .86.46l-1.92 6.02A1 1 0 0 0 13 10h7a1 1 0 0 1 .78 1.63l-9.9 10.2a.5.5 0 0 1-.86-.46l1.92-6.02A1 1 0 0 0 11 14z\" />\n </Wrap>\n );\n}\n\n// lucide: upload v0.577.0\nexport function UploadTapButton(props: TapButtonProps) {\n return (\n <Wrap ariaLabel=\"Upload\" {...props}>\n <path d=\"M12 3v12\" />\n <path d=\"m17 8-5-5-5 5\" />\n <path d=\"M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4\" />\n </Wrap>\n );\n}\n\n// lucide: download v0.577.0\nexport function DownloadTapButton(props: TapButtonProps) {\n return (\n <Wrap ariaLabel=\"Download\" {...props}>\n <path d=\"M12 15V3\" />\n <path d=\"M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4\" />\n <path d=\"m7 10 5 5 5-5\" />\n </Wrap>\n );\n}\n\n// lucide: share-2 v0.577.0\nexport function ShareTapButton(props: TapButtonProps) {\n return (\n <Wrap ariaLabel=\"Share\" {...props}>\n <circle cx=\"18\" cy=\"5\" r=\"3\" />\n <circle cx=\"6\" cy=\"12\" r=\"3\" />\n <circle cx=\"18\" cy=\"19\" r=\"3\" />\n <line x1=\"8.59\" x2=\"15.42\" y1=\"13.51\" y2=\"17.49\" />\n <line x1=\"15.41\" x2=\"8.59\" y1=\"6.51\" y2=\"10.49\" />\n </Wrap>\n );\n}\n\n// lucide: undo v0.577.0\nexport function UndoTapButton(props: TapButtonProps) {\n return (\n <Wrap ariaLabel=\"Undo\" {...props}>\n <path d=\"M3 7v6h6\" />\n <path d=\"M21 17a9 9 0 0 0-9-9 9 9 0 0 0-6 2.3L3 13\" />\n </Wrap>\n );\n}\n\n// lucide: redo v0.577.0\nexport function RedoTapButton(props: TapButtonProps) {\n return (\n <Wrap ariaLabel=\"Redo\" {...props}>\n <path d=\"M21 7v6h-6\" />\n <path d=\"M3 17a9 9 0 0 1 9-9 9 9 0 0 1 6 2.3l3 2.7\" />\n </Wrap>\n );\n}\n\n// lucide: copy v0.577.0\nexport function CopyTapButton(props: TapButtonProps) {\n return (\n <Wrap ariaLabel=\"Copy\" {...props}>\n <rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\" />\n <path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\" />\n </Wrap>\n );\n}\n\n// lucide: trash v0.577.0\nexport function TrashTapButton(props: TapButtonProps) {\n return (\n <Wrap ariaLabel=\"Delete\" {...props}>\n <path d=\"M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6\" />\n <path d=\"M3 6h18\" />\n <path d=\"M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2\" />\n </Wrap>\n );\n}\n\n// lucide: files v0.577.0\nexport function FilesTapButton(props: TapButtonProps) {\n return (\n <Wrap ariaLabel=\"Copy all\" {...props}>\n <path d=\"M20 7h-3a2 2 0 0 1-2-2V2\" />\n <path d=\"M9 18a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h7l4 4v10a2 2 0 0 1-2 2Z\" />\n <path d=\"M3 7.6v12.8A1.6 1.6 0 0 0 4.6 22h9.8\" />\n </Wrap>\n );\n}\n\n// lucide: chevron-left v0.577.0 — arms extended from 6 to 7 (45° kept) for a\n// slightly larger glyph that better fills the 32px inner pill.\nexport function ChevronLeftTapButton(props: TapButtonProps) {\n return (\n <Wrap ariaLabel=\"Back\" {...props}>\n <path d=\"m16 19-7-7 7-7\" />\n </Wrap>\n );\n}\n\n// lucide: chevron-right v0.577.0\nexport function ChevronRightTapButton(props: TapButtonProps) {\n return (\n <Wrap ariaLabel=\"Next\" {...props}>\n <path d=\"m9 18 6-6-6-6\" />\n </Wrap>\n );\n}\n\n// lucide: panel-left v0.577.0\nexport function PanelLeftTapButton(props: TapButtonProps) {\n return (\n <Wrap ariaLabel=\"Toggle sidebar\" {...props}>\n <rect width=\"18\" height=\"18\" x=\"3\" y=\"3\" rx=\"2\" />\n <path d=\"M9 3v18\" />\n </Wrap>\n );\n}\n\n// lucide: panel-right v0.577.0\nexport function PanelRightTapButton(props: TapButtonProps) {\n return (\n <Wrap ariaLabel=\"Toggle sidebar\" {...props}>\n <rect width=\"18\" height=\"18\" x=\"3\" y=\"3\" rx=\"2\" />\n <path d=\"M15 3v18\" />\n </Wrap>\n );\n}\n\n// lucide: square-pen v0.577.0\nexport function SquarePenTapButton(props: TapButtonProps) {\n return (\n <Wrap ariaLabel=\"New chat\" {...props}>\n <path d=\"M12 3H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7\" />\n <path d=\"M18.375 2.625a1 1 0 0 1 3 3l-9.013 9.014a2 2 0 0 1-.853.505l-2.873.84a.5.5 0 0 1-.62-.62l.84-2.873a2 2 0 0 1 .506-.852z\" />\n </Wrap>\n );\n}\n\n// lucide: x v0.577.0\nexport function XTapButton(props: TapButtonProps) {\n return (\n <Wrap ariaLabel=\"Close\" {...props}>\n <path d=\"M18 6 6 18\" />\n <path d=\"m6 6 12 12\" />\n </Wrap>\n );\n}\n\n// lucide: funnel v0.577.0 (filter is an alias for funnel in this version)\nexport function FilterTapButton(props: TapButtonProps) {\n return (\n <Wrap ariaLabel=\"Filter\" {...props}>\n <path d=\"M10 20a1 1 0 0 0 .553.895l2 1A1 1 0 0 0 14 21v-7a2 2 0 0 1 .517-1.341L21.74 4.67A1 1 0 0 0 21 3H3a1 1 0 0 0-.742 1.67l7.225 7.989A2 2 0 0 1 10 14z\" />\n </Wrap>\n );\n}\n\n// lucide: play v0.577.0\nexport function PlayTapButton(props: TapButtonProps) {\n return (\n <Wrap ariaLabel=\"Play\" {...props}>\n <path d=\"M5 5a2 2 0 0 1 3.008-1.728l11.997 6.998a2 2 0 0 1 .003 3.458l-12 7A2 2 0 0 1 5 19z\" />\n </Wrap>\n );\n}\n\n// lucide: pause v0.577.0 — two rects (redesigned from bar paths)\nexport function PauseTapButton(props: TapButtonProps) {\n return (\n <Wrap ariaLabel=\"Pause\" {...props}>\n <rect x=\"14\" y=\"3\" width=\"5\" height=\"18\" rx=\"1\" />\n <rect x=\"5\" y=\"3\" width=\"5\" height=\"18\" rx=\"1\" />\n </Wrap>\n );\n}\n\n// lucide: square v0.577.0 (stop uses filled square)\nexport function StopTapButton(props: TapButtonProps) {\n return (\n <Wrap ariaLabel=\"Stop\" {...props}>\n <rect width=\"18\" height=\"18\" x=\"3\" y=\"3\" rx=\"2\" />\n </Wrap>\n );\n}\n\n// lucide: volume-2 v0.577.0\nexport function Volume2TapButton(props: TapButtonProps) {\n return (\n <Wrap ariaLabel=\"Speaker\" {...props}>\n <path d=\"M11 4.702a.705.705 0 0 0-1.203-.498L6.413 7.587A1.4 1.4 0 0 1 5.416 8H3a1 1 0 0 0-1 1v6a1 1 0 0 0 1 1h2.416a1.4 1.4 0 0 1 .997.413l3.383 3.384A.705.705 0 0 0 11 19.298z\" />\n <path d=\"M16 9a5 5 0 0 1 0 6\" />\n <path d=\"M19.364 18.364a9 9 0 0 0 0-12.728\" />\n </Wrap>\n );\n}\n\n// lucide: arrow-up v0.577.0\nexport function ArrowUpTapButton(props: TapButtonProps) {\n return (\n <Wrap ariaLabel=\"Send\" {...props}>\n <path d=\"m5 12 7-7 7 7\" />\n <path d=\"M12 19V5\" />\n </Wrap>\n );\n}\n\n// lucide: mic v0.577.0\nexport function MicTapButton(props: TapButtonProps) {\n return (\n <Wrap ariaLabel=\"Start recording\" {...props}>\n <path d=\"M12 19v3\" />\n <path d=\"M19 10v2a7 7 0 0 1-14 0v-2\" />\n <rect x=\"9\" y=\"2\" width=\"6\" height=\"13\" rx=\"3\" />\n </Wrap>\n );\n}\n\n// lucide: mic-off v0.577.0\nexport function MicOffTapButton(props: TapButtonProps) {\n return (\n <Wrap ariaLabel=\"Stop recording\" {...props}>\n <path d=\"M12 19v3\" />\n <path d=\"M15 9.34V5a3 3 0 0 0-5.68-1.33\" />\n <path d=\"M16.95 16.95A7 7 0 0 1 5 12v-2\" />\n <path d=\"M18.89 13.23A7 7 0 0 0 19 12v-2\" />\n <path d=\"m2 2 20 20\" />\n <path d=\"M9 9v3a3 3 0 0 0 5.12 2.12\" />\n </Wrap>\n );\n}\n\n// lucide: triangle-alert v0.577.0\nexport function TriangleAlertTapButton(props: TapButtonProps) {\n return (\n <Wrap ariaLabel=\"Alert\" {...props}>\n <path d=\"m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3\" />\n <path d=\"M12 9v4\" />\n <path d=\"M12 17h.01\" />\n </Wrap>\n );\n}\n\n// lucide: shield-check (context set)\nexport function ShieldCheckTapButton(props: TapButtonProps) {\n return (\n <Wrap ariaLabel=\"Context set\" {...props}>\n <path d=\"M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z\" />\n <path d=\"m9 12 2 2 4-4\" />\n </Wrap>\n );\n}\n\n// lucide: shield-alert (context unset)\nexport function ShieldAlertTapButton(props: TapButtonProps) {\n return (\n <Wrap ariaLabel=\"No context\" {...props}>\n <path d=\"M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z\" />\n <path d=\"M12 8v4\" />\n <path d=\"M12 16h.01\" />\n </Wrap>\n );\n}\n\n// lucide: bug v0.577.0 (major update — full insect anatomy)\nexport function BugTapButton(props: TapButtonProps) {\n return (\n <Wrap ariaLabel=\"Debug\" {...props}>\n <path d=\"M12 20v-9\" />\n <path d=\"M14 7a4 4 0 0 1 4 4v3a6 6 0 0 1-12 0v-3a4 4 0 0 1 4-4z\" />\n <path d=\"M14.12 3.88 16 2\" />\n <path d=\"M21 21a4 4 0 0 0-3.81-4\" />\n <path d=\"M21 5a4 4 0 0 1-3.55 3.97\" />\n <path d=\"M22 13h-4\" />\n <path d=\"M3 21a4 4 0 0 1 3.81-4\" />\n <path d=\"M3 5a4 4 0 0 0 3.55 3.97\" />\n <path d=\"M6 13H2\" />\n <path d=\"m8 2 1.88 1.88\" />\n <path d=\"M9 7.13V6a3 3 0 1 1 6 0v1.13\" />\n </Wrap>\n );\n}\n\n// lucide: settings-2 v0.577.0 (gear + center circle — kept as-is, matches intent)\nexport function Settings2TapButton(props: TapButtonProps) {\n return (\n <Wrap ariaLabel=\"Settings\" {...props}>\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n d=\"M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z\"\n />\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n d=\"M15 12a3 3 0 11-6 0 3 3 0 016 0z\"\n />\n </Wrap>\n );\n}\n\n// lucide: save (hand-crafted floppy disk — no direct Lucide equivalent, kept as-is)\nexport function SaveTapButton(props: TapButtonProps) {\n return (\n <Wrap ariaLabel=\"Save\" {...props}>\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n d=\"M4.5 6a2 2 0 012-2h9.25L20.5 9v9a2 2 0 01-2 2h-12a2 2 0 01-2-2V6z\"\n />\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n d=\"M8.5 4v4.5a.5.5 0 00.5.5h6a.5.5 0 00.5-.5V4\"\n />\n <rect\n x=\"8\"\n y=\"14\"\n width=\"8\"\n height=\"5.5\"\n rx=\"0.5\"\n strokeLinejoin=\"round\"\n />\n </Wrap>\n );\n}\n\n// lucide: send v0.577.0 (paper-airplane redesign)\nexport function SendTapButton(props: TapButtonProps) {\n return (\n <Wrap ariaLabel=\"Send\" {...props}>\n <path d=\"M14.536 21.686a.5.5 0 0 0 .937-.024l6.5-19a.496.496 0 0 0-.635-.635l-19 6.5a.5.5 0 0 0-.024.937l7.93 3.18a2 2 0 0 1 1.112 1.11z\" />\n <path d=\"m21.854 2.147-10.94 10.939\" />\n </Wrap>\n );\n}\n\n// lucide: message-square v0.577.0\nexport function MessageTapButton(props: TapButtonProps) {\n return (\n <Wrap ariaLabel=\"Message\" {...props}>\n <path d=\"M22 17a2 2 0 0 1-2 2H6.828a2 2 0 0 0-1.414.586l-2.202 2.202A.71.71 0 0 1 2 21.286V5a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2z\" />\n </Wrap>\n );\n}\n\n// lucide: variable v0.577.0 (major update — uses line elements + bracket paths)\nexport function VariableTapButton(props: TapButtonProps) {\n return (\n <Wrap ariaLabel=\"Variable\" {...props}>\n <path d=\"M8 21s-4-3-4-9 4-9 4-9\" />\n <path d=\"M16 3s4 3 4 9-4 9-4 9\" />\n <line x1=\"15\" x2=\"9\" y1=\"9\" y2=\"15\" />\n <line x1=\"9\" x2=\"15\" y1=\"9\" y2=\"15\" />\n </Wrap>\n );\n}\n\n// lucide: wrench v0.577.0 (single clean path)\nexport function WrenchTapButton(props: TapButtonProps) {\n return (\n <Wrap ariaLabel=\"Tool\" {...props}>\n <path d=\"M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.106-3.105c.32-.322.863-.22.983.218a6 6 0 0 1-8.259 7.057l-7.91 7.91a1 1 0 0 1-2.999-3l7.91-7.91a6 6 0 0 1 7.057-8.259c.438.12.54.662.219.984z\" />\n </Wrap>\n );\n}\n\n// lucide: command v0.577.0 (single continuous path)\nexport function CommandTapButton(props: TapButtonProps) {\n return (\n <Wrap ariaLabel=\"Command\" {...props}>\n <path d=\"M15 6v12a3 3 0 1 0 3-3H6a3 3 0 1 0 3 3V6a3 3 0 1 0-3 3h12a3 3 0 1 0-3-3\" />\n </Wrap>\n );\n}\n\n// lucide: terminal v0.577.0 (two paths: chevron + underline)\nexport function TerminalTapButton(props: TapButtonProps) {\n return (\n <Wrap ariaLabel=\"Terminal\" {...props}>\n <path d=\"M12 19h8\" />\n <path d=\"m4 17 6-6-6-6\" />\n </Wrap>\n );\n}\n\n// lucide: test-tube v0.577.0 (3 clean paths)\nexport function TestTubeTapButton(props: TapButtonProps) {\n return (\n <Wrap ariaLabel=\"Test\" {...props}>\n <path d=\"M14.5 2v17.5c0 1.4-1.1 2.5-2.5 2.5c-1.4 0-2.5-1.1-2.5-2.5V2\" />\n <path d=\"M8.5 2h7\" />\n <path d=\"M14.5 16h-5\" />\n </Wrap>\n );\n}\n\n// lucide: rotate-ccw v0.577.0 (same shape as history minus the clock hand — used for Reset)\nexport function ResetTapButton(props: TapButtonProps) {\n return (\n <Wrap ariaLabel=\"Reset\" {...props}>\n <path d=\"M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8\" />\n <path d=\"M3 3v5h5\" />\n </Wrap>\n );\n}\n\n// lucide: eraser v0.577.0 (major update — proper eraser shape)\nexport function ClearTapButton(props: TapButtonProps) {\n return (\n <Wrap ariaLabel=\"Clear\" {...props}>\n <path d=\"M21 21H8a2 2 0 0 1-1.42-.587l-3.994-3.999a2 2 0 0 1 0-2.828l10-10a2 2 0 0 1 2.829 0l5.999 6a2 2 0 0 1 0 2.828L12.834 21\" />\n <path d=\"m5.082 11.09 8.828 8.828\" />\n </Wrap>\n );\n}\n\n// lucide: refresh-cw v1.22.0 (dual arrows — was a broken hand-crafted Heroicons-style path)\nexport function RetryTapButton(props: TapButtonProps) {\n return (\n <Wrap ariaLabel=\"Retry\" {...props}>\n <path d=\"M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8\" />\n <path d=\"M21 3v5h-5\" />\n <path d=\"M21 12a9 9 0 0 1-9 9 9.75 9.75 0 0 1-6.74-2.74L3 16\" />\n <path d=\"M8 16H3v5\" />\n </Wrap>\n );\n}\n\n/** Alias — same Lucide refresh-cw glyph as RetryTapButton. */\nexport function RefreshCwTapButton(props: TapButtonProps) {\n return <RetryTapButton ariaLabel=\"Refresh\" {...props} />;\n}\n\n// lucide: loading spinner (custom animated — no Lucide equivalent)\n//\n// 🚨 `matrx-spin`, NEVER `animate-spin` (census row 19i, closed here at 0.2.1).\n// `animate-spin` is a core Tailwind utility, so it happened to survive in all\n// four current consumers — but a package cannot ship a class it does not\n// define: the first host without Tailwind's core animate utilities gets a\n// spinner that does not spin, which is a load-bearing lie (it says the work\n// has stopped) with no error to find it by. `matrx-spin` is design-system\n// 0.10.0's own keyframe + rule, shipped in ITS `styles.css` and asserted\n// present in ITS packed tarball. This package IMPORTS that contract (the\n// exported `MOTION_SPIN` constant, and `styles.css` `@import`s the sheet) —\n// it does not copy the keyframe, which would be a twin of exactly the kind\n// this row exists to kill. Under `prefers-reduced-motion` the shared rule\n// SLOWS the loop instead of stopping it, because a stopped spinner removes\n// information rather than motion.\nexport function LoadingTapButton(props: TapButtonProps) {\n return (\n <Wrap ariaLabel=\"Loading\" {...props}>\n <circle\n className={MOTION_SPIN}\n cx=\"12\"\n cy=\"12\"\n r=\"9\"\n strokeDasharray=\"28.27\"\n strokeDashoffset=\"9\"\n strokeLinecap=\"round\"\n style={{ transformOrigin: \"12px 12px\" }}\n />\n </Wrap>\n );\n}\n\n// lucide: bot/robot (hand-crafted — kept as-is)\nexport function RobotTapButton(props: TapButtonProps) {\n return (\n <Wrap ariaLabel=\"AI Agent\" {...props}>\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n d=\"M9 3.75H6.912a2.25 2.25 0 00-2.15 1.588L2.35 13.177a2.25 2.25 0 00-.1.661V18a2.25 2.25 0 002.25 2.25h15A2.25 2.25 0 0021.75 18v-4.162c0-.224-.034-.447-.1-.661L19.24 5.338a2.25 2.25 0 00-2.15-1.588H15M2.25 13.5h3.86a2.25 2.25 0 012.012 1.244l.256.512a2.25 2.25 0 002.013 1.244h3.218a2.25 2.25 0 002.013-1.244l.256-.512a2.25 2.25 0 012.013-1.244h3.859M12 3v8.25m0 0-3-3m3 3 3-3\"\n />\n </Wrap>\n );\n}\n\n// lucide: webhook v0.577.0\nexport function WebhookTapButton(props: TapButtonProps) {\n return (\n <Wrap ariaLabel=\"Webhook\" {...props}>\n <path d=\"M18 16.98h-5.99c-1.1 0-1.95.94-2.48 1.9A4 4 0 0 1 2 17c.01-.7.2-1.4.57-2\" />\n <path d=\"m6 17 3.13-5.78c.53-.97.1-2.18-.5-3.1a4 4 0 1 1 6.89-4.06\" />\n <path d=\"m12 6 3.13 5.73C15.66 12.7 16.9 13 18 13a4 4 0 0 1 0 8\" />\n </Wrap>\n );\n}\n\n// lucide: eye v0.577.0\nexport function ViewTapButton(props: TapButtonProps) {\n return (\n <Wrap ariaLabel=\"View\" {...props}>\n <path d=\"M2.062 12.348a1 1 0 0 1 0-.696 10.75 10.75 0 0 1 19.876 0 1 1 0 0 1 0 .696 10.75 10.75 0 0 1-19.876 0\" />\n <circle cx=\"12\" cy=\"12\" r=\"3\" />\n </Wrap>\n );\n}\n\n// lucide: hammer v0.577.0\nexport function BuildTapButton(props: TapButtonProps) {\n return (\n <Wrap ariaLabel=\"Build\" {...props}>\n <path d=\"m15 12-9.373 9.373a1 1 0 0 1-3.001-3L12 9\" />\n <path d=\"m18 15 4-4\" />\n <path d=\"m21.5 11.5-1.914-1.914A2 2 0 0 1 19 8.172v-.344a2 2 0 0 0-.586-1.414l-1.657-1.657A6 6 0 0 0 12.516 3H9l1.243 1.243A6 6 0 0 1 12 8.485V10l2 2h1.172a2 2 0 0 1 1.414.586L18.5 14.5\" />\n </Wrap>\n );\n}\n\n// lucide: play v0.577.0 (alias for Run context)\nexport function RunTapButton(props: TapButtonProps) {\n return (\n <Wrap ariaLabel=\"Run\" {...props}>\n <path d=\"M5 5a2 2 0 0 1 3.008-1.728l11.997 6.998a2 2 0 0 1 .003 3.458l-12 7A2 2 0 0 1 5 19z\" />\n </Wrap>\n );\n}\n\n// lucide: history v0.577.0\nexport function HistoryTapButton(props: TapButtonProps) {\n return (\n <Wrap ariaLabel=\"History\" {...props}>\n <path d=\"M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8\" />\n <path d=\"M3 3v5h5\" />\n <path d=\"M12 7v5l4 2\" />\n </Wrap>\n );\n}\n\n// lucide: paperclip v0.577.0\nexport function PaperclipTapButton(props: TapButtonProps) {\n return (\n <Wrap ariaLabel=\"Attach file\" {...props}>\n <path d=\"m16 6-8.414 8.586a2 2 0 0 0 2.829 2.829l8.414-8.586a4 4 0 1 0-5.657-5.657l-8.379 8.551a6 6 0 1 0 8.485 8.485l8.379-8.551\" />\n </Wrap>\n );\n}\n\n// lucide: thumbs-up v0.577.0\nexport function ThumbsUpTapButton(props: TapButtonProps) {\n return (\n <Wrap ariaLabel=\"Like\" {...props}>\n <path d=\"M7 10v12\" />\n <path d=\"M15 5.88 14 10h5.83a2 2 0 0 1 1.92 2.56l-2.33 8A2 2 0 0 1 17.5 22H4a2 2 0 0 1-2-2v-8a2 2 0 0 1 2-2h2.76a2 2 0 0 0 1.79-1.11L12 2a3.13 3.13 0 0 1 3 3.88Z\" />\n </Wrap>\n );\n}\n\n// lucide: thumbs-down v0.577.0\nexport function ThumbsDownTapButton(props: TapButtonProps) {\n return (\n <Wrap ariaLabel=\"Dislike\" {...props}>\n <path d=\"M17 14V2\" />\n <path d=\"M9 18.12 10 14H4.17a2 2 0 0 1-1.92-2.56l2.33-8A2 2 0 0 1 6.5 2H20a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2h-2.76a2 2 0 0 0-1.79 1.11L12 22a3.13 3.13 0 0 1-3-3.88Z\" />\n </Wrap>\n );\n}\n\n// lucide: check v0.577.0\nexport function CheckTapButton(props: TapButtonProps) {\n return (\n <Wrap ariaLabel=\"Done\" {...props}>\n <path d=\"M20 6 9 17l-5-5\" />\n </Wrap>\n );\n}\n\n// lucide: pencil v0.577.0\nexport function PencilTapButton(props: TapButtonProps) {\n return (\n <Wrap ariaLabel=\"Edit\" {...props}>\n <path d=\"M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z\" />\n <path d=\"m15 5 4 4\" />\n </Wrap>\n );\n}\n\n// lucide: ellipsis (more-horizontal) v0.577.0\nexport function MoreHorizontalTapButton(props: TapButtonProps) {\n return (\n <Wrap ariaLabel=\"More options\" {...props}>\n <circle cx=\"12\" cy=\"12\" r=\"1\" />\n <circle cx=\"19\" cy=\"12\" r=\"1\" />\n <circle cx=\"5\" cy=\"12\" r=\"1\" />\n </Wrap>\n );\n}\n\n// lucide: check-square v0.577.0\nexport function CheckSquareTapButton(props: TapButtonProps) {\n return (\n <Wrap ariaLabel=\"Task\" {...props}>\n <path d=\"m9 11 3 3L22 4\" />\n <path d=\"M21 12v7a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11\" />\n </Wrap>\n );\n}\n\n// lucide: ghost v0.577.0\nexport function GhostTapButton(props: TapButtonProps) {\n return (\n <Wrap ariaLabel=\"Incognito chat\" {...props}>\n <path d=\"M9 10h.01\" />\n <path d=\"M15 10h.01\" />\n <path d=\"M12 2a8 8 0 0 0-8 8v12l3-3 2.5 2.5L12 19l2.5 2.5L17 19l3 3V10a8 8 0 0 0-8-8z\" />\n </Wrap>\n );\n}\n\n// lucide: link (chain link — used for \"attach to task\") v0.577.0\nexport function LinkTapButton(props: TapButtonProps) {\n return (\n <Wrap ariaLabel=\"Attach\" {...props}>\n <path d=\"M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71\" />\n <path d=\"M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71\" />\n </Wrap>\n );\n}\n\n// lucide: external-link v0.577.0\nexport function ExternalLinkTapButton(props: TapButtonProps) {\n return (\n <Wrap ariaLabel=\"Open source\" {...props}>\n <path d=\"M15 3h6v6\" />\n <path d=\"M10 14 21 3\" />\n <path d=\"M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6\" />\n </Wrap>\n );\n}\n\n// lucide: clipboard-list v0.577.0\nexport function ClipboardListTapButton(props: TapButtonProps) {\n return (\n <Wrap ariaLabel=\"Copy Pages\" {...props}>\n <rect width=\"8\" height=\"4\" x=\"8\" y=\"2\" rx=\"1\" ry=\"1\" />\n <path d=\"M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2\" />\n <path d=\"M12 11h4\" />\n <path d=\"M12 16h4\" />\n <path d=\"M8 11h.01\" />\n <path d=\"M8 16h.01\" />\n </Wrap>\n );\n}\n\n// lucide: party-popper v0.577.0\nexport function PartyPopperTapButton(props: TapButtonProps) {\n return (\n <Wrap ariaLabel=\"AI Clean\" {...props}>\n <path d=\"M5.8 11.3 2 22l10.7-3.79\" />\n <path d=\"M4 3h.01\" />\n <path d=\"M22 8h.01\" />\n <path d=\"M15 2h.01\" />\n <path d=\"M22 20h.01\" />\n <path d=\"m22 2-2.24.75a2.9 2.9 0 0 0-1.96 3.12c.1.86-.57 1.63-1.45 1.63h-.38c-.86 0-1.6.6-1.76 1.44L14 10\" />\n <path d=\"m22 13-.82-.33c-.86-.34-1.82.2-1.98 1.11c-.11.7-.72 1.22-1.43 1.22H17\" />\n <path d=\"m11 2 .33.82c.34.86-.2 1.82-1.11 1.98C9.52 4.9 9 5.52 9 6.23V7\" />\n <path d=\"M11 13c1.93 1.93 2.83 4.17 2 5-.83.83-3.07-.07-5-2-1.93-1.93-2.83-4.17-2-5 .83-.83 3.07.07 5 2Z\" />\n </Wrap>\n );\n}\n\n// lucide: layers v0.577.0 — \"this PDF everywhere\" surface switcher\nexport function LayersTapButton(props: TapButtonProps) {\n return (\n <Wrap ariaLabel=\"Open this PDF in another surface\" {...props}>\n <path d=\"M12.83 2.18a2 2 0 0 0-1.66 0L2.6 6.08a1 1 0 0 0 0 1.83l8.58 3.91a2 2 0 0 0 1.66 0l8.58-3.9a1 1 0 0 0 0-1.83z\" />\n <path d=\"M2 12a1 1 0 0 0 .58.91l8.6 3.91a2 2 0 0 0 1.65 0l8.58-3.9A1 1 0 0 0 22 12\" />\n <path d=\"M2 17a1 1 0 0 0 .58.91l8.6 3.91a2 2 0 0 0 1.65 0l8.58-3.9A1 1 0 0 0 22 17\" />\n </Wrap>\n );\n}\n","\"use client\";\n\nimport { createContext, useContext, type ReactNode } from \"react\";\n\nimport { useTapSurface } from \"./tap-surface\";\n\n// THE PLACEMENT DEFAULT — which variant a tap button takes when its caller\n// names none. Outside a provider that is \"glass\" (the floating-bar look). A\n// host region that holds tap buttons BESIDE text (a route header's back +\n// title cell) wraps itself in <TapDefaultVariant value=\"transparent\"> so every\n// button in it matches its neighbours (rule 2, \"all glass or none\") without\n// each call site repeating variant=\"transparent\". An explicit `variant` prop\n// always wins, so a bar whose pieces are ALL glass stays glass.\n//\n// The context object lives in a `Symbol.for` slot on globalThis, like the link\n// seam: the `.` and `./buttons` dist bundles each inline this module, and a\n// provider rendered by one must reach buttons rendered by the other.\n\nexport type TapDefaultVariantValue = \"glass\" | \"transparent\";\n\nconst SLOT = Symbol.for(\"@ai-matrx/tap-target:default-variant\");\ntype GlobalWithSlot = typeof globalThis & {\n [SLOT]?: ReturnType<typeof createContext<TapDefaultVariantValue>>;\n};\n\nfunction ctx() {\n const g = globalThis as GlobalWithSlot;\n return (g[SLOT] ??= createContext<TapDefaultVariantValue>(\"glass\"));\n}\n\n/** The variant tap buttons below take when they name none. */\nexport function useTapDefaultVariant(): TapDefaultVariantValue {\n return useContext(ctx());\n}\n\n/** Set the default variant for every tap button below that names none. */\nexport function TapDefaultVariant({ value, children }: { value: TapDefaultVariantValue; children: ReactNode }) {\n const Context = ctx();\n return <Context.Provider value={value}>{children}</Context.Provider>;\n}\n\n/**\n * The variant a lone tap button draws: its explicit `variant`, else a region's\n * <TapDefaultVariant>, else — on a <TapSurface surface=\"solid\"> — \"transparent\"\n * (glass only floats), else glass. An explicit variant always wins.\n */\nexport function useTapButtonVariant<V extends string>(explicit: V | undefined): V | TapDefaultVariantValue {\n const placed = useTapDefaultVariant();\n const surface = useTapSurface(undefined);\n if (explicit !== undefined) return explicit;\n if (placed !== \"glass\") return placed;\n return surface === \"solid\" ? \"transparent\" : \"glass\";\n}\n","/**\n * A STAND-IN ANNOUNCES ITSELF (law 4). Where a design-system component has a working default for a\n * part the host is meant to supply (the writing box, the sandbox panel, how a scope is drawn), the\n * default says so: ONE console notice per stand-in naming what to pass, and a `data-*=\"unconfigured\"`\n * attribute on what it draws. The pattern is records-ui's `data-entity-ref-host=\"unconfigured\"` and\n * settings' `data-settings-host=\"unconfigured\"`.\n */\nconst announced = new Set<string>();\n\n/** Warn once per `key`, in words naming the field the host should pass. */\nexport function announceStandIn(key: string, message: string): void {\n if (announced.has(key)) return;\n announced.add(key);\n console.warn(`[design-system] ${message}`);\n}\n\n/** Test seam: forget every notice that was printed. */\nexport function _resetStandInNotices(): void {\n announced.clear();\n}\n\n/** The value every stand-in's data attribute carries. */\nexport const UNCONFIGURED = \"unconfigured\" as const;\n","/**\n * THE ONE FITTING RULE for ProInput and ProTextarea's controls (2026-10-15).\n *\n * A writing field's controls never take the room the text needs, and a control\n * that does not fit is never deleted — it moves inside \"…\". Until this module\n * each field had its own step-down rule: ProInput dropped its mic AND its \"…\"\n * outright below ~220px when it also had Clear + Send (voice, copy, clean-up and\n * read-aloud became unreachable), and on a phone a 110px field kept two letters\n * of text beside Clear and Send.\n *\n * The rule:\n * - REQUIRED controls always show: Send (the field's action) and \"…\" whenever\n * it holds anything.\n * - OPTIONAL controls show in priority order while the text keeps its floor;\n * the rest go inside \"…\". Folding runs from the lowest priority up: Expand,\n * then Clear, then the mic.\n * - There is no device chevron (Arman, 2026-10-16): the microphone choice is\n * a right-click / press-and-hold on the mic, and an \"Audio settings\" row in\n * \"…\" whenever \"…\" shows — so it never takes room here.\n * - A live recording always keeps its stop button inline (the caller forces it).\n *\n * Widths are the real rendered footprints per pointer and density (measured\n * 2026-10-15 on a fine pointer and a 375px phone), so a phone folds earlier\n * instead of being crushed.\n */\n\nexport type FoldableControl = \"mic\" | \"clear\" | \"expand\";\n\n/** How the mic shows: inline, inside \"…\", or not offered. */\nexport type MicFit = \"inline\" | \"folded\" | \"none\";\n\nexport interface ControlSizes {\n /** One tap box (Send, \"…\", Clear, Expand). */\n box: number;\n /** The mic button, its own 3px margins included. */\n mic: number;\n}\n\n/** 38px tap box; the mic is a 28px button plus its 3px margins. */\nexport const FINE_SIZES: ControlSizes = { box: 38, mic: 34 };\n/** Touch: the tap box keeps 38px of layout (the 44px hit area is invisible); the mic pads out. */\nexport const COARSE_SIZES: ControlSizes = { box: 38, mic: 46 };\n/** The dense field scope (`data-matrx-tap-dense`): a 24px pill in a 28px box. */\nexport const DENSE_SIZES: ControlSizes = { box: 28, mic: 28 };\n\nexport function controlSizes(opts: { coarse: boolean; dense: boolean }): ControlSizes {\n if (opts.dense) return DENSE_SIZES;\n return opts.coarse ? COARSE_SIZES : FINE_SIZES;\n}\n\n/** Below this field height the controls take the dense 28px size. */\nexport const DENSE_FIELD_MAX_HEIGHT_PX = 34;\n\nexport function isDenseField(fieldHeight: number): boolean {\n return fieldHeight > 0 && fieldHeight < DENSE_FIELD_MAX_HEIGHT_PX;\n}\n\n/**\n * The text's floor: half the field, never more than 140px and never less than\n * 48px (about five characters).\n */\nexport function minTextPx(fieldWidth: number): number {\n return Math.max(48, Math.min(140, Math.round(fieldWidth * 0.5)));\n}\n\nexport interface FitRequest {\n /** The field's measured width; 0 = not measured yet (first paint, jsdom) → everything that may be inline is. */\n fieldWidth: number;\n sizes: ControlSizes;\n /** Space the field always spends outside the controls: its left padding, a start icon, the text gap. */\n fixedPx?: number | undefined;\n /** The text floor; defaults to `minTextPx(fieldWidth)`. A reserved control row passes 0. */\n minText?: number | undefined;\n hasSubmit: boolean;\n /** The \"…\" menu has items of its own (copy, clean-up, read-aloud, agents…). */\n menuHasOwnItems: boolean;\n /** The field offers voice input. */\n mic: boolean;\n /** Clear is offered right now (the field has text). */\n clear: boolean;\n /** Expand is offered right now (the text overflows the box). */\n expand: boolean;\n}\n\nexport interface FitResult {\n mic: MicFit;\n clearInline: boolean;\n expandInline: boolean;\n /** Controls that live inside \"…\" because they did not fit. */\n folded: FoldableControl[];\n /** \"…\" shows: it has its own items or holds a folded control. */\n showMenu: boolean;\n /** Width every inline control takes together, px. */\n inlineWidth: number;\n}\n\nexport function fitFieldControls(req: FitRequest): FitResult {\n const { sizes } = req;\n const folded: FoldableControl[] = [];\n let mic: MicFit = req.mic ? \"inline\" : \"none\";\n let clearInline = req.clear;\n let expandInline = req.expand;\n\n const menuWillShow = () => req.menuHasOwnItems || folded.length > 0;\n const width = () =>\n (req.hasSubmit ? sizes.box : 0) +\n (menuWillShow() ? sizes.box : 0) +\n (mic === \"inline\" ? sizes.mic : 0) +\n (clearInline ? sizes.box : 0) +\n (expandInline ? sizes.box : 0);\n\n if (req.fieldWidth > 0) {\n const floor = req.minText ?? minTextPx(req.fieldWidth);\n const room = req.fieldWidth - (req.fixedPx ?? 0) - floor;\n const steps: Array<() => void> = [\n () => {\n if (expandInline) {\n expandInline = false;\n folded.push(\"expand\");\n }\n },\n () => {\n if (clearInline) {\n clearInline = false;\n folded.push(\"clear\");\n }\n },\n () => {\n if (mic === \"inline\") {\n mic = \"folded\";\n folded.push(\"mic\");\n }\n },\n ];\n for (const step of steps) {\n if (width() <= room) break;\n step();\n }\n }\n\n return {\n mic,\n clearInline,\n expandInline,\n folded,\n showMenu: menuWillShow(),\n inlineWidth: width(),\n };\n}\n","/**\n * WHERE PROTEXTAREA'S MIC + \"…\" CLUSTER SITS, and the rule that it never covers\n * text (the ProTextarea twin of `proInputReservedPadding.ts`, page-pass 2026-09-27).\n *\n * A textarea's lines run the full width, so the cluster cannot take a right\n * gutter; it sits in a bottom ROW the field reserves (`pb-11`) on every\n * pointer. Mic, \"…\" and the submit button share ONE flex row inset 4px from\n * the corner, so they sit as adjacent tap boxes — no hand-typed offset between\n * them (a 48px offset beside a 38px box left a 10px hole, 2026-10-05).\n */\nexport type ClusterRow = \"top\" | \"bottom\";\n\nexport interface ClusterPlacement {\n row: ClusterRow;\n /** Distance from the right edge, px (clears the submit button when they share a row). */\n rightPx: number;\n /** The rows the field reserves, per pointer kind. */\n reserved: { fine: ClusterRow[]; coarse: ClusterRow[] };\n /** The submit button's row and width, when there is one. */\n submit: { row: ClusterRow; widthPx: number } | null;\n /** The classes the cluster container adds. */\n className: string;\n}\n\n/** The tap box (`--matrx-tap-box`, 38px since 2026-10-01). */\nexport const SUBMIT_BUTTON_WIDTH_PX = 38;\n\n/** Where the cluster sits: a reserved row under the text, or inline at the end of the last line. */\nexport type ProTextareaControls = \"row\" | \"inline\";\n\n/** The tap pill's half-gap (`--matrx-tap-gap` / 2): a container edge is a neighbour (tap-target rule 4). */\nexport const TAP_HALF_GAP_PX = 3;\n\n/** One tap row plus the half-gap above and below it: the shortest an inline-controls box may be. */\nexport const INLINE_CONTROLS_MIN_HEIGHT_PX = SUBMIT_BUTTON_WIDTH_PX + 2 * TAP_HALF_GAP_PX;\n\n/**\n * The inline-controls text padding: centered on one tap row vertically (whatever\n * the host's line height — `1lh`), and a right gutter the measured cluster\n * width plus the half-gap, so text never runs under a control.\n */\nexport function inlineControlsFieldPadding(\n clusterWidthPx: number,\n /** The one-line height: 44px, or 34px for a dense (small-type) box. */\n minHeightPx: number = INLINE_CONTROLS_MIN_HEIGHT_PX,\n): {\n paddingTop: string;\n paddingBottom: string;\n paddingRight: string;\n} {\n const block = `calc((${minHeightPx}px - 1lh) / 2 - 1px)`;\n return {\n paddingTop: block,\n paddingBottom: block,\n paddingRight: `${clusterWidthPx + 2 * TAP_HALF_GAP_PX}px`,\n };\n}\n\nexport function proTextareaClusterPlacement(\n hasSubmit: boolean,\n controls: ProTextareaControls = \"row\",\n): ClusterPlacement {\n if (controls === \"inline\") {\n // Inset by the half-gap: a 38px box in a 44px-min box is dead-centre on\n // one line, and stays on the last line as the text grows.\n return {\n row: \"bottom\",\n rightPx: hasSubmit ? SUBMIT_BUTTON_WIDTH_PX + TAP_HALF_GAP_PX : TAP_HALF_GAP_PX,\n reserved: { fine: [\"bottom\"], coarse: [\"bottom\"] },\n submit: hasSubmit ? { row: \"bottom\", widthPx: SUBMIT_BUTTON_WIDTH_PX } : null,\n className: \"bottom-[3px] right-[3px]\",\n };\n }\n // One flex row inset 4px from the bottom-right corner: the hover part, then\n // the submit button. They are adjacent tap boxes in the SAME row, so the\n // cluster sits exactly one submit box (plus the inset) from the edge.\n return {\n row: \"bottom\",\n rightPx: hasSubmit ? SUBMIT_BUTTON_WIDTH_PX + 4 : 4,\n reserved: { fine: [\"bottom\"], coarse: [\"bottom\"] },\n submit: hasSubmit ? { row: \"bottom\", widthPx: SUBMIT_BUTTON_WIDTH_PX } : null,\n className: \"bottom-1 right-1\",\n };\n}\n\n/** Every way a placement lets the cluster cover text or the submit button. `[]` = sound. */\nexport function clusterPlacementProblems(p: ClusterPlacement): string[] {\n const problems: string[] = [];\n if (!p.reserved.fine.includes(p.row)) {\n problems.push(`on a fine pointer the ${p.row} row is not reserved, so the cluster covers text on hover`);\n }\n if (!p.reserved.coarse.includes(p.row)) {\n problems.push(`on a touch screen the ${p.row} row is not reserved, so the cluster covers text`);\n }\n if (p.submit && p.submit.row === p.row && p.rightPx < p.submit.widthPx) {\n problems.push(\"the cluster overlaps the submit button\");\n }\n return problems;\n}\n\n// What fits beside the text — and what moves inside \"…\" — is decided by THE\n// ONE FITTING RULE shared with ProInput: `proFieldControlFit.ts`.\n","\"use client\";\n\n/**\n * THE WRITING FIELD'S ADD-ON PORTS. `ProTextarea` / `ProInput` (this subpath) own the box: the\n * textarea/input, auto-grow, the control row, submit and Enter rules, the dictation handle, the\n * close-protection dialog. Everything that needs a recorder, a server, an agent or a menu engine\n * reaches the field through these ports, registered ONCE at the host root:\n *\n * <WritingFieldAddOnsProvider addOns={matrxWritingFieldAddOns}>…</WritingFieldAddOnsProvider>\n *\n * so design-system (layer 2) never imports chat, agents, rich-content, context-menu or a recorder.\n * A port the host did not register falls back to a stand-in that ANNOUNCES itself (law 4): one\n * console notice naming the port, and `data-writing-field-host=\"unconfigured\"` on the field.\n *\n * Hook ports (`useVoice`, `useFormatting`, `useOpenAudioSettings`) are called on every render, so\n * the registered object must be module-constant: the provider keeps the FIRST object it receives\n * and announces a swap instead of breaking hook order.\n *\n * One context for every bundle copy of this module (tsup inlines it into each entry), keyed like\n * `writing-box.tsx`.\n */\nimport * as React from \"react\";\nimport { announceStandIn } from \"../stand-in-notice\";\n\n/** Options the field hands its voice port — the same contract the app's `useMicField` takes. */\nexport interface WritingFieldVoiceOptions {\n /** Voice is on for this field (`enableVoice`). When false the port must stay inert. */\n enabled: boolean;\n instanceId?: string | undefined;\n label?: string | undefined;\n getValue: () => string;\n /** Write the next value through the field's own change path. */\n writeValue: (next: string) => boolean | void;\n appendTranscript?: boolean | undefined;\n join?: ((base: string, text: string) => string) | undefined;\n protect?: boolean | undefined;\n onRequestClose?: (() => void) | undefined;\n onTranscriptionComplete?: ((text: string) => void) | undefined;\n onTranscriptionError?: ((error: string) => void) | undefined;\n}\n\n/** What a voice port returns: recorder state plus the controls the field draws. */\nexport interface WritingFieldVoice {\n /** The browser exposes a microphone (device enumeration works). */\n microphone: boolean;\n /** A recorder is mounted on this route. */\n available: boolean;\n isRecording: boolean;\n isTranscribing: boolean;\n audioLevel: number;\n liveTranscript: string;\n handleVoiceClick: () => void | Promise<void>;\n startDictation: () => Promise<void>;\n stopDictation: () => void;\n requestClose: () => void;\n showProtectionDialog: boolean;\n setShowProtectionDialog: (open: boolean) => void;\n confirmClose: () => void;\n cancelClose: () => void;\n /** The port's own dialogs (troubleshooting), drawn beside the field. */\n dialogs?: React.ReactNode | undefined;\n}\n\nexport interface WritingFieldMicButtonProps {\n onMicClick: () => void;\n disabled?: boolean | undefined;\n isRecording?: boolean | undefined;\n isTranscribing?: boolean | undefined;\n audioLevel?: number | undefined;\n micAriaLabel?: string | undefined;\n tabIndex?: number | undefined;\n dense?: boolean | undefined;\n}\n\n/** The field as an add-on sees it. */\nexport interface WritingFieldApi {\n kind: \"textarea\" | \"input\";\n /** The value the host last rendered. */\n text: string;\n /** The live text (the DOM or the hosted editor), falling back to `text`. */\n getText: () => string;\n /** Write through the field's own change path; true when the field now holds `next`. */\n write: (next: string) => boolean;\n getSelection: () => { start: number; end: number };\n getElement: () => HTMLTextAreaElement | HTMLInputElement | null;\n /** The add-on props the caller passed (surfaceName, getApplicationScope, cleanup…), untouched. */\n addOnProps: Readonly<Record<string, unknown>>;\n showCopyButton: boolean;\n /** Show the brief \"Copied\" check on the \"…\" trigger (ProInput). */\n flashCopied: () => void;\n}\n\nexport interface WritingFieldMenuProps {\n field: WritingFieldApi;\n /** The field's own rows (Expand, Voice input, Audio settings, Clear) — place them in the list view. */\n ownRows: React.ReactNode;\n /** Rows the field adds after the add-on's list (text stats). */\n trailingRows: React.ReactNode;\n close: () => void;\n}\n\nexport interface WritingFieldContextMenuProps {\n field: WritingFieldApi;\n disabled?: boolean | undefined;\n children: React.ReactNode;\n}\n\nexport interface WritingFieldTextStats {\n Bar: React.ComponentType<{ text: string }>;\n MenuItems: React.ComponentType<{\n showStatsBar: boolean;\n onToggleStatsBar: () => void;\n onOpenStatsPanel: () => void;\n }>;\n Panel: React.ComponentType<{ text: string; onBack?: () => void; onClose?: () => void }>;\n}\n\nexport interface WritingFieldNotify {\n error: (message: string, options?: { description?: string }) => void;\n info: (message: string) => void;\n success: (message: string) => void;\n}\n\nexport interface WritingFieldAddOns {\n useVoice?: ((options: WritingFieldVoiceOptions) => WritingFieldVoice) | undefined;\n MicButton?: React.ComponentType<WritingFieldMicButtonProps> | undefined;\n useOpenAudioSettings?: (() => () => void) | undefined;\n /** Markdown chords + selection toolbar on a long-form box. */\n useFormatting?:\n | ((\n element: HTMLTextAreaElement | null,\n on: boolean,\n addOnProps: Readonly<Record<string, unknown>>,\n ) => void)\n | undefined;\n /** The \"…\" body (actions, agents, read-aloud). */\n Menu?: React.ComponentType<WritingFieldMenuProps> | undefined;\n /** Whether `Menu` has rows of its own for this field (so \"…\" shows). */\n menuHasItems?: ((field: Pick<WritingFieldApi, \"kind\" | \"addOnProps\" | \"showCopyButton\">) => boolean) | undefined;\n /** The right-click floor around the field. */\n ContextMenu?: React.ComponentType<WritingFieldContextMenuProps> | undefined;\n TextStats?: WritingFieldTextStats | undefined;\n notify?: WritingFieldNotify | undefined;\n /** Extra prop names the add-ons read (kept off the DOM element). */\n propNames?: readonly string[] | undefined;\n}\n\n/** Add-on prop names the field never spreads onto the DOM (the Matrx add-ons' props). */\nexport const ADD_ON_PROP_NAMES: readonly string[] = [\n \"surfaceName\",\n \"getApplicationScope\",\n \"sourceFeature\",\n \"surfaceContextItems\",\n \"enableBoundAgents\",\n \"enableContextMenu\",\n \"enableCleanup\",\n \"cleanupAgentId\",\n \"cleanupContextItems\",\n \"enableHelpWithThis\",\n \"helpMandateKey\",\n \"helpContextItems\",\n \"enableCustomAgent\",\n \"customAgentMandateKey\",\n \"customAgentContextItems\",\n \"uploadImage\",\n];\n\n/** Split a field's rest props into DOM props and add-on props. */\nexport function splitAddOnProps<T extends Record<string, unknown>>(\n props: T,\n extra: readonly string[] = [],\n): { dom: T; addOnProps: Record<string, unknown> } {\n const dom: Record<string, unknown> = {};\n const addOnProps: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(props)) {\n if (ADD_ON_PROP_NAMES.includes(key) || extra.includes(key)) addOnProps[key] = value;\n else dom[key] = value;\n }\n return { dom: dom as T, addOnProps };\n}\n\nconst KEY = Symbol.for(\"@ai-matrx/design-system/writing-field-add-ons\");\ntype Registry = Record<symbol, React.Context<WritingFieldAddOns | null> | undefined>;\nconst registry = globalThis as unknown as Registry;\nconst AddOnsContext: React.Context<WritingFieldAddOns | null> =\n registry[KEY] ?? (registry[KEY] = React.createContext<WritingFieldAddOns | null>(null));\n\n/** Mount once at the host's app root. The first `addOns` object is kept for the provider's life. */\nexport function WritingFieldAddOnsProvider({\n addOns,\n children,\n}: {\n addOns: WritingFieldAddOns;\n children: React.ReactNode;\n}) {\n const first = React.useRef(addOns);\n if (first.current !== addOns) {\n announceStandIn(\n \"writing-field-add-ons-swap\",\n \"WritingFieldAddOnsProvider received a different addOns object; the first one is kept (hook ports must be module-constant).\",\n );\n }\n return <AddOnsContext.Provider value={first.current}>{children}</AddOnsContext.Provider>;\n}\n\nconst EMPTY: WritingFieldAddOns = {};\n\n/** The registered add-ons (or none). */\nexport function useWritingFieldAddOns(): WritingFieldAddOns {\n return React.useContext(AddOnsContext) ?? EMPTY;\n}\n\n/** Announce a missing port once, in words naming what to register. */\nexport function announceMissingPort(port: string): void {\n announceStandIn(\n `writing-field:${port}`,\n `A writing field drew without its \"${port}\" add-on: the host did not register it in <WritingFieldAddOnsProvider addOns={{ ${port} }}>.`,\n );\n}\n\nconst INERT = () => undefined;\n\n/** The voice stand-in: no recorder, every control inert, announced when a field asks for voice. */\nexport function useStandInVoice(options: WritingFieldVoiceOptions): WritingFieldVoice {\n React.useEffect(() => {\n if (options.enabled) announceMissingPort(\"useVoice\");\n }, [options.enabled]);\n return {\n microphone: false,\n available: false,\n isRecording: false,\n isTranscribing: false,\n audioLevel: 0,\n liveTranscript: \"\",\n handleVoiceClick: INERT,\n startDictation: async () => undefined,\n stopDictation: INERT,\n requestClose: () => options.onRequestClose?.(),\n showProtectionDialog: false,\n setShowProtectionDialog: INERT,\n confirmClose: () => options.onRequestClose?.(),\n cancelClose: INERT,\n };\n}\n\n/** Notices with no host toast go to the console, announced once. */\nexport const STAND_IN_NOTIFY: WritingFieldNotify = {\n error: (message) => {\n announceMissingPort(\"notify\");\n console.error(`[writing-field] ${message}`);\n },\n info: (message) => {\n announceMissingPort(\"notify\");\n console.info(`[writing-field] ${message}`);\n },\n success: (message) => {\n announceMissingPort(\"notify\");\n console.info(`[writing-field] ${message}`);\n },\n};\n\nfunction useNoFormatting(): void {}\nfunction useNoAudioSettings(): () => void {\n return () => announceMissingPort(\"useOpenAudioSettings\");\n}\n\n/** The add-ons with every missing hook port filled by its stand-in (stable for a stable registry). */\nexport function resolveHookPorts(addOns: WritingFieldAddOns) {\n return {\n useVoice: addOns.useVoice ?? useStandInVoice,\n useFormatting: addOns.useFormatting ?? useNoFormatting,\n useOpenAudioSettings: addOns.useOpenAudioSettings ?? useNoAudioSettings,\n notify: addOns.notify ?? STAND_IN_NOTIFY,\n };\n}\n","\"use client\";\n\n/**\n * The settled surfaces that hold the one control (owner, 2026-10-02/03):\n * one surface level, ~36px hairline rows, 8px radius; the empty state; the\n * region-shaped skeleton; the three delete tiers; the one-feature promo banner.\n * Skins are locked in `controls.css` like the controls themselves.\n */\n\nimport { Slot } from \"@radix-ui/react-slot\";\nimport * as React from \"react\";\n\nimport { swallowClick } from \"../button\";\nimport { cn } from \"../cn\";\nimport { ConfirmDialog } from \"../confirm-dialog\";\nimport { ChevronRightIcon, Trash2Icon } from \"../icons\";\nimport { Skeleton } from \"../skeleton\";\nimport { Button, ControlRow, type ChipTone, type GlyphTone } from \"./controls\";\n\n/* ------------------------------------------------------------------ */\n/* Row groups */\n/* ------------------------------------------------------------------ */\n\nexport interface RowGroupProps extends Omit<React.HTMLAttributes<HTMLElement>, \"title\"> {\n /** 11px uppercase heading above the group. */\n title?: React.ReactNode;\n /** The danger-zone skin (delete tier 3). */\n danger?: boolean;\n}\n\n/** A bordered group of hairline rows — the one surface for grouped content. */\nexport function RowGroup({ title, danger, className, children, ...props }: RowGroupProps) {\n return (\n <section\n data-matrx-row-group=\"\"\n data-danger={danger ? \"\" : undefined}\n className={cn(\"matrx-control-group\", className)}\n {...props}\n >\n {title ? <h2 className=\"matrx-control-group-title\">{title}</h2> : null}\n <div className=\"matrx-control-group-body\">{children}</div>\n </section>\n );\n}\n\nexport interface SettingRowProps {\n label: React.ReactNode;\n /** One 12px line under the label. */\n line?: React.ReactNode;\n /** Ties the label to the control it describes. */\n htmlFor?: string;\n /** The row's controls, right-aligned on one line. */\n children?: React.ReactNode;\n className?: string;\n}\n\n/** One ~36px row: 13px label, optional 12px line, controls on the right. */\nexport function SettingRow({ label, line, htmlFor, children, className }: SettingRowProps) {\n return (\n <div data-matrx-setting-row=\"\" className={cn(\"matrx-control-setting-row\", className)}>\n <div className=\"matrx-control-setting-text\">\n {htmlFor ? (\n <label htmlFor={htmlFor} className=\"matrx-control-setting-label\">\n {label}\n </label>\n ) : (\n <div className=\"matrx-control-setting-label\">{label}</div>\n )}\n {line ? <div className=\"matrx-control-setting-line\">{line}</div> : null}\n </div>\n {children ? (\n <ControlRow nowrap data-matrx-row-actions=\"\">\n {children}\n </ControlRow>\n ) : null}\n </div>\n );\n}\n\n/* ------------------------------------------------------------------ */\n/* Tile — the pressable row / tile (a choice, a destination) */\n/* ------------------------------------------------------------------ */\n\nexport type TileLayout = \"row\" | \"stack\" | \"adaptive\" | \"icon\";\n\nexport interface TileProps extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, \"title\"> {\n /** `row` (default): glyph, then a 13px title over a 12px line, start-aligned, full width — a\n * choice in a list, a quick action. `stack`: glyph on top, title and line under it — a grid\n * tile. `adaptive`: `stack` from the `sm` breakpoint (640px) up, a compact `row` below it — a\n * grid of option cards that becomes a list on a phone. `icon`: the launcher tile of an icon\n * grid (a \"Can make\" grid, a sidebar's pinned apps, a copy palette) — the glyph centered over\n * an 11px label centered under it, up to two lines, no frame, a pick is a soft tint, `end`\n * is a badge on the top corner, `line` is hidden. All are taller than a control: they carry\n * text, so they never take the 28px lock. */\n layout?: TileLayout;\n /** `outline` (default): the bordered card skin. `quiet`: no frame until hover — a row in a\n * menu-like list. */\n variant?: \"outline\" | \"quiet\";\n /** Leading 16px glyph (an avatar or image works too). */\n icon?: React.ReactNode;\n /** The 13px title. */\n title: React.ReactNode;\n /** The title wraps over several lines (up to 6) instead of one line with an ellipsis: a quiz\n * answer, a step, a sentence-long choice. Off by default — a short title is one line. */\n wrapTitle?: boolean;\n /** One 12px secondary line (clamped to two lines; one with `oneLine`). */\n line?: React.ReactNode;\n /** The `line` stays ONE line with an ellipsis, so every row of a master list keeps one height. */\n oneLine?: boolean;\n /** Trailing content in a row (a chevron, a count, a shortcut). */\n end?: React.ReactNode;\n /** A choice: `true` tints it and sets `aria-pressed`; `false` sets `aria-pressed=\"false\"`. A link tile (`asChild`) never sets `aria-pressed`: the caller sets `aria-current`. */\n selected?: boolean;\n /** How `selected` looks. `outline` (default): primary frame and tint. `fill`: a soft neutral fill,\n * no outline, ink unchanged — a sidebar's active row. `primary`: the solid primary fill with\n * every ink (title, line, glyph, end) on primary — the open item of a master list. */\n selectedStyle?: \"outline\" | \"fill\" | \"primary\";\n /** The hover / focus tooltip (the native `title` attribute: `title` is the visible label). */\n tooltip?: string;\n /** Nesting depth under a parent row: each level moves the row's start past one glyph and its\n * gap, so an icon-less child's title starts where its parent's title does. */\n level?: 1 | 2 | 3;\n /** Size to the content and never shrink or truncate the title — a code, a short value. */\n fit?: boolean;\n /** Keep room at the row's end for a control laid OVER it (a row's More button): `control`\n * reserves one control's width plus its gap, so the title never runs under it. */\n endInset?: \"control\";\n /** A dashed border: the \"add another\" tile (an empty slot to fill), never a choice. */\n dashed?: boolean;\n /** hoverStyle=\"fill\": the pointer's soft neutral fill (the desktop look's secondary fill) instead of the accent. */\n hoverStyle?: \"fill\";\n /** A destructive row (Remove, Delete): destructive title and glyph, destructive hover tint. */\n danger?: boolean;\n /**\n * A choice that is ALREADY USED elsewhere (an option already placed, a field already mapped): a\n * faint shade and quieter ink, still fully pressable — a hint for the eye, never a disabled state.\n */\n dimmed?: boolean;\n /** The glyph's own status ink when its color carries meaning (Button's `glyphTone`). */\n glyphTone?: GlyphTone;\n /** The inviting choice card for a front door: roomy padding, a 40px icon square, a 14px title. */\n hero?: boolean;\n /** Tint card, edge and icon square from one `ChipTone` (the `Chip` hue tokens). */\n tone?: ChipTone;\n /** A 28px navigation / filter row for sidebars and dense lists: `min-height` is the control size,\n * padding 4px 8px, gap 8px, 13px title. The `line` is HIDDEN when dense (one line, always).\n * `variant=\"quiet\"` + `dense` is a clean nav row: transparent until hover / selected. */\n dense?: boolean;\n /** Render the one child element (a link) with the tile's skin; its children are ignored —\n * the tile draws `icon`/`title`/`line`/`end`. */\n asChild?: boolean;\n}\n\n/**\n * THE pressable row / tile: two named layouts, two skins, no size. `className` places it\n * (width, grid cell); its height follows its text.\n */\nexport const Tile = React.forwardRef<HTMLButtonElement, TileProps>(\n (\n { layout = \"row\", variant = \"outline\", icon, title, wrapTitle, line, end, selected, selectedStyle, tooltip, level, fit, endInset, oneLine, dashed, hoverStyle, danger, dimmed, glyphTone, hero, tone, dense, asChild = false, className, children, onClick, type, ...props },\n ref,\n ) => {\n const Component = asChild ? Slot : \"button\";\n const ariaDisabled = props[\"aria-disabled\"];\n const inert = ariaDisabled === true || ariaDisabled === \"true\";\n const body = (\n <>\n {icon ? <span className=\"matrx-tile-icon\">{icon}</span> : null}\n <span className=\"matrx-tile-text\">\n <span className=\"matrx-tile-title\">{title}</span>\n {line ? <span className=\"matrx-tile-line\">{line}</span> : null}\n </span>\n {end ? <span className=\"matrx-tile-end\">{end}</span> : null}\n </>\n );\n return (\n <Component\n ref={ref}\n type={asChild ? undefined : (type ?? \"button\")}\n data-matrx-tile=\"\"\n data-layout={layout}\n data-variant={variant}\n data-selected={selected ? \"\" : undefined}\n data-selected-style={selected && (selectedStyle === \"fill\" || selectedStyle === \"primary\") ? selectedStyle : undefined}\n data-level={level}\n data-fit={fit ? \"\" : undefined}\n data-one-line={oneLine ? \"\" : undefined}\n data-end-inset={endInset}\n data-dashed={dashed ? \"\" : undefined}\n data-hover-style={hoverStyle}\n title={tooltip}\n data-danger={danger ? \"\" : undefined}\n data-dimmed={dimmed ? \"\" : undefined}\n data-wrap-title={wrapTitle ? \"\" : undefined}\n data-glyph-tone={glyphTone}\n data-hero={hero ? \"\" : undefined}\n data-dense={dense ? \"\" : undefined}\n data-tone={tone}\n aria-pressed={asChild || selected === undefined ? undefined : selected}\n className={cn(\"matrx-tile\", className)}\n {...props}\n onClick={inert ? swallowClick : onClick}\n >\n {asChild && React.isValidElement(children) ? (\n React.cloneElement(children as React.ReactElement<{ children?: React.ReactNode }>, undefined, body)\n ) : (\n body\n )}\n </Component>\n );\n },\n);\nTile.displayName = \"Tile\";\n\n/* ------------------------------------------------------------------ */\n/* Section disclosure header */\n/* ------------------------------------------------------------------ */\n\nexport type DisclosureHeaderVariant = \"row\" | \"label\";\n\nexport interface DisclosureHeaderProps extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, \"title\"> {\n /** Whether the section under the header is showing. Sets `aria-expanded`. */\n open: boolean;\n /** `row` (default): a 13px/500 title — a collapsible section, a group of results, a \"details\"\n * fold. `label`: the 11px uppercase muted label that heads a sidebar or menu group. */\n variant?: DisclosureHeaderVariant;\n /** Optional 16px glyph after the chevron (row variant). */\n icon?: React.ReactNode;\n /** Colors ONLY the icon: a status tone uses its `-ink` token, a hue its `--matrx-chip-<hue>-ink`.\n * A section that carries a color (violet Organization, amber Projects) keeps it here. */\n glyphTone?: GlyphTone | ChipTone;\n /** The section's name. */\n title: React.ReactNode;\n /** A short muted fact after the title: a count, a size, \"3 of 12\". Never a sentence. */\n meta?: React.ReactNode;\n /** Trailing content pinned to the end (a status glyph, a count badge). Non-interactive — a\n * control beside the header sits outside it, never inside the button. */\n end?: React.ReactNode;\n /** One 12px secondary line under the title (row variant) — what the section holds. */\n line?: React.ReactNode;\n /** Where the turning chevron sits. `start` (default) leads the row; `end` trails it, for a\n * sidebar section whose label keeps the column's left edge. */\n chevron?: \"start\" | \"end\";\n}\n\n/**\n * THE section-disclosure header: a chevron that turns, a title, an optional count and trailing\n * status — one full-width pressable row that opens and closes the section below it. Every\n * \"click the heading to fold\" row is this, never a raw button with a hand-drawn chevron.\n */\nexport const DisclosureHeader = React.forwardRef<HTMLButtonElement, DisclosureHeaderProps>(\n ({ open, variant = \"row\", icon, glyphTone, title, meta, end, line, chevron = \"start\", className, type, ...props }, ref) => (\n <button\n ref={ref}\n type={type ?? \"button\"}\n aria-expanded={open}\n data-matrx-disclosure=\"\"\n data-variant={variant}\n data-open={open ? \"\" : undefined}\n data-chevron={chevron}\n className={cn(\"matrx-disclosure\", className)}\n {...props}\n >\n {chevron === \"start\" ? (\n <span className=\"matrx-disclosure-chevron\" aria-hidden=\"true\">\n <ChevronRightIcon />\n </span>\n ) : null}\n {icon ? (\n <span className=\"matrx-disclosure-icon\" data-glyph-tone={glyphTone}>\n {icon}\n </span>\n ) : null}\n {line ? (\n <span className=\"matrx-disclosure-text\">\n <span className=\"matrx-disclosure-title\">{title}</span>\n <span className=\"matrx-disclosure-line\">{line}</span>\n </span>\n ) : (\n <span className=\"matrx-disclosure-title\">{title}</span>\n )}\n {meta === undefined || meta === null || meta === false ? null : (\n <span className=\"matrx-disclosure-meta\">{meta}</span>\n )}\n {end ? <span className=\"matrx-disclosure-end\">{end}</span> : null}\n {chevron === \"end\" ? (\n <span className=\"matrx-disclosure-chevron\" data-end=\"\" aria-hidden=\"true\">\n <ChevronRightIcon />\n </span>\n ) : null}\n </button>\n ),\n);\nDisclosureHeader.displayName = \"DisclosureHeader\";\n\n/* ------------------------------------------------------------------ */\n/* Empty state */\n/* ------------------------------------------------------------------ */\n\nexport interface EmptyStateProps {\n /** A 20px glyph inside the tinted disc. */\n icon: React.ReactNode;\n /** 13px title. */\n title: React.ReactNode;\n /** One 12px line. */\n line?: React.ReactNode;\n /** The one 28px action (a controls `Button`). */\n action?: React.ReactNode;\n className?: string;\n}\n\n/** Tinted icon disc + 13px title + one line + one 28px button. */\nexport function EmptyState({ icon, title, line, action, className }: EmptyStateProps) {\n return (\n <div data-matrx-empty-state=\"\" className={cn(\"matrx-control-empty\", className)}>\n <div className=\"matrx-control-empty-disc\" aria-hidden=\"true\">\n {icon}\n </div>\n <div>\n <div className=\"matrx-control-empty-title\">{title}</div>\n {line ? <div className=\"matrx-control-empty-line\">{line}</div> : null}\n </div>\n {action ? <ControlRow className=\"justify-center\">{action}</ControlRow> : null}\n </div>\n );\n}\n\n/* ------------------------------------------------------------------ */\n/* Region skeleton */\n/* ------------------------------------------------------------------ */\n\nexport interface RegionSkeletonProps {\n /** The region's shape: hairline rows, a form's label+field pairs, or cards. */\n shape?: \"rows\" | \"form\" | \"cards\";\n /** How many rows / fields / cards. */\n count?: number;\n /** Rows: a second (meta) line under each title. */\n twoLine?: boolean;\n className?: string;\n \"aria-label\"?: string;\n}\n\n/**\n * A skeleton shaped like the region it stands in for — never one block for a\n * page, never a spinner in the middle. A spinner belongs only inside a busy\n * control.\n */\nexport function RegionSkeleton({\n shape = \"rows\",\n count = shape === \"cards\" ? 3 : shape === \"form\" ? 4 : 8,\n twoLine = false,\n className,\n \"aria-label\": ariaLabel = \"Loading\",\n}: RegionSkeletonProps) {\n const items = Array.from({ length: count }, (_, i) => i);\n if (shape === \"form\") {\n return (\n <div aria-busy=\"true\" aria-label={ariaLabel} className={cn(\"flex flex-col gap-3\", className)}>\n {items.map((i) => (\n <div key={i} className=\"flex flex-col gap-1.5\">\n <Skeleton className=\"h-3 w-24\" />\n <Skeleton className=\"h-7 rounded-full\" />\n </div>\n ))}\n </div>\n );\n }\n if (shape === \"cards\") {\n return (\n <div aria-busy=\"true\" aria-label={ariaLabel} className={cn(\"grid gap-2 sm:grid-cols-3\", className)}>\n {items.map((i) => (\n <div key={i} className=\"flex items-center gap-3 rounded-lg border border-border p-3\">\n <Skeleton className=\"size-8 rounded-full\" />\n <div className=\"flex flex-1 flex-col gap-1.5\">\n <Skeleton className=\"h-3.5 w-2/3\" />\n <Skeleton className=\"h-2.5 w-1/2\" />\n </div>\n </div>\n ))}\n </div>\n );\n }\n return (\n <div aria-busy=\"true\" aria-label={ariaLabel} className={cn(\"divide-y divide-border\", className)}>\n {items.map((i) => (\n <div key={i} className=\"flex min-h-9 items-center gap-3 px-3 py-1.5\">\n <Skeleton className=\"size-4 rounded-full\" />\n <div className=\"flex min-w-0 flex-1 flex-col gap-1\">\n <Skeleton className=\"h-3.5\" style={{ width: `${30 + ((i * 17) % 35)}%` }} />\n {twoLine ? <Skeleton className=\"h-2.5 w-1/4\" /> : null}\n </div>\n <Skeleton className=\"hidden h-[1.125rem] w-16 rounded-md sm:block\" />\n <Skeleton className=\"size-5 rounded-full\" />\n </div>\n ))}\n </div>\n );\n}\n\n/* ------------------------------------------------------------------ */\n/* The three delete tiers */\n/* ------------------------------------------------------------------ */\n\nexport interface DeleteButtonProps\n extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, \"children\" | \"aria-label\"> {\n /** What it deletes, e.g. \"Delete reference\". */\n \"aria-label\": string;\n}\n\n/** Tier 1 — the quiet trash glyph: muted until hover, destructive on hover. */\nexport const DeleteButton = React.forwardRef<HTMLButtonElement, DeleteButtonProps>((props, ref) => (\n <Button ref={ref} variant=\"quiet\" icon={<Trash2Icon />} data-delete=\"\" title={props[\"aria-label\"]} {...props} />\n));\nDeleteButton.displayName = \"DeleteButton\";\n\nexport interface ConfirmDeleteProps {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n /** \"Delete this project?\" */\n title: React.ReactNode;\n /** REQUIRED: name the cost — what is lost, what goes with it. Never \"Are you sure?\". */\n cost: React.ReactNode;\n /** The confirm button names the act, e.g. \"Delete project\". */\n confirmLabel: string;\n onConfirm: () => void | Promise<void>;\n busy?: boolean;\n}\n\n/** Tier 2 — a confirm that names the cost. */\nexport function ConfirmDelete({ open, onOpenChange, title, cost, confirmLabel, onConfirm, busy }: ConfirmDeleteProps) {\n return (\n <ConfirmDialog\n open={open}\n onOpenChange={onOpenChange}\n title={title}\n description={cost}\n confirmLabel={confirmLabel}\n variant=\"destructive\"\n busy={busy}\n onConfirm={onConfirm}\n />\n );\n}\n\n/** Tier 3 — the danger zone: a red-ruled group of rows at the end of settings. */\nexport function DangerZone({\n title = \"Danger zone\",\n children,\n className,\n}: {\n title?: React.ReactNode;\n children: React.ReactNode;\n className?: string;\n}) {\n return (\n <RowGroup title={title} danger className={className}>\n {children}\n </RowGroup>\n );\n}\n\n/* ------------------------------------------------------------------ */\n/* Promo banner */\n/* ------------------------------------------------------------------ */\n\nexport type PromoTone = \"primary\" | \"success\" | \"warning\" | \"info\";\n\nexport interface PromoBannerProps {\n /** A 16px glyph inside the tinted disc. */\n icon: React.ReactNode;\n /** 11px label before the title, e.g. \"Next challenge\". Never a pill. */\n eyebrow?: React.ReactNode;\n /** One line, 13px. */\n title: React.ReactNode;\n /** One line, 12px, ≤60 characters. Omit rather than pad. */\n line?: React.ReactNode;\n /** Outline badges — the evidence behind the promo. */\n chips?: React.ReactNode;\n /** The one action: a controls `Button` (or a link wearing it). */\n action?: React.ReactNode;\n tone?: PromoTone;\n /**\n * Let the title wrap onto as many lines as it needs, for a sentence that must be read whole (a question with its\n * answer buttons beside it). Default false: one line, truncated.\n */\n wrap?: boolean;\n className?: string;\n /** Accessible name of the region. Defaults to \"Featured\". */\n \"aria-label\"?: string;\n}\n\n/**\n * A page-top variant that promotes ONE feature in one bordered row (~56px):\n * [disc] EYEBROW · Title / one line … [chips] [Action]. On a phone the chips\n * wrap under the text and the action stretches full width.\n */\nexport function PromoBanner({\n icon,\n eyebrow,\n title,\n line,\n chips,\n action,\n tone = \"primary\",\n wrap = false,\n className,\n \"aria-label\": ariaLabel,\n}: PromoBannerProps) {\n return (\n <section\n aria-label={ariaLabel ?? (typeof eyebrow === \"string\" ? eyebrow : \"Featured\")}\n data-matrx-promo=\"\"\n data-tone={tone}\n data-wrap={wrap ? \"\" : undefined}\n className={cn(\"matrx-control-promo\", className)}\n >\n <span className=\"matrx-control-promo-disc\" aria-hidden=\"true\">\n {icon}\n </span>\n <div className=\"matrx-control-promo-text\">\n <div className=\"matrx-control-promo-head\">\n {eyebrow ? <span className=\"matrx-control-promo-eyebrow\">{eyebrow}</span> : null}\n {eyebrow ? (\n <span className=\"matrx-control-promo-eyebrow\" aria-hidden=\"true\">\n ·\n </span>\n ) : null}\n <span className=\"matrx-control-promo-title\">{title}</span>\n </div>\n {line ? <div className=\"matrx-control-promo-line\">{line}</div> : null}\n </div>\n {chips ? <div className=\"matrx-control-promo-chips\">{chips}</div> : null}\n {action ? (\n <ControlRow nowrap className=\"matrx-control-promo-action\">\n {action}\n </ControlRow>\n ) : null}\n </section>\n );\n}\n","\"use client\";\n\nimport { Slot } from \"@radix-ui/react-slot\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\nimport * as React from \"react\";\n\nimport { cn } from \"./cn\";\n\nexport const buttonVariants = cva(\n \"matrx-glyph-trim inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all duration-200 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-0 disabled:opacity-50 active:scale-[0.98] [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0\",\n {\n variants: {\n variant: {\n default: \"bg-primary text-primary-foreground shadow-sm hover:bg-primary/90\",\n /**\n * An explicit spelling of `default`, identical by construction. It is\n * not decoration: matrx-frontend's `ButtonMine` fork carried it, ~17\n * call sites say `variant=\"primary\"`, and the alternative to keeping\n * the word was a host shim translating a prop — the massage C22 bans.\n */\n primary: \"bg-primary text-primary-foreground shadow-sm hover:bg-primary/90\",\n destructive:\n \"bg-danger-fill text-danger-fill-foreground shadow-sm hover:bg-danger-fill/90\",\n /** The affirmative twin of `destructive` — confirm, approve, publish. */\n success:\n \"bg-success-fill text-success-fill-foreground shadow-sm hover:bg-success-fill/90\",\n outline:\n \"border border-border bg-card shadow-sm hover:bg-accent hover:text-accent-foreground\",\n secondary:\n \"bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80\",\n ghost: \"hover:bg-accent hover:text-accent-foreground\",\n link: \"text-primary-ink underline-offset-4 hover:underline\",\n subtle:\n \"border border-transparent bg-muted/50 text-foreground hover:border-border hover:bg-muted\",\n },\n /**\n * ONE size scale, xs → 3xl, plus the two icon boxes. The top and bottom\n * of the scale came in from matrx-frontend's `ButtonMine` fork (2026-09-07):\n * a dense toolbar needs `xs`, and a marketing/hero call to action needs\n * `xl`+. A host that has to reach outside this scale forks the button,\n * which is exactly how `ButtonMine` was born.\n */\n size: {\n xs: \"h-6 rounded-md px-1 text-xs\",\n sm: \"h-8 rounded-md px-3 text-xs\",\n default: \"h-9 px-4 py-2\",\n /** An explicit spelling of `default` (the fork's middle rung). */\n md: \"h-9 px-4 py-2\",\n lg: \"h-10 rounded-md px-6\",\n xl: \"h-12 px-8 py-3 text-base\",\n \"2xl\": \"h-14 px-10 py-3 text-base\",\n \"3xl\": \"h-16 px-12 py-3 text-base\",\n icon: \"h-9 w-9\",\n \"icon-sm\": \"h-7 w-7\",\n /** A circular icon box — an avatar-shaped control, not a square one. */\n roundIcon: \"h-8 w-8 rounded-full p-0\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n size: \"default\",\n },\n },\n);\n\n/**\n * THE TOUCH FLOOR (2026-09-17).\n *\n * Every rung of the size scale below `xl` is shorter than the 44px platform\n * touch target: `xs` 24, `icon-sm` 28, `sm` 32, `roundIcon` 32, `default`/`md`\n * 36, `icon` 36, `lg` 40. Measured live at 390x844 on `/masterwork/<id>`, ALL\n * SEVEN design-system Buttons in the viewport were under the floor (four at\n * 32px, two at 28px).\n *\n * The floor is raised in CSS, under `@media (pointer: coarse)` ONLY, so DESKTOP\n * DENSITY IS UNTOUCHED — a narrow desktop window is not a finger, which is why\n * this rule deliberately does NOT carry the `(max-width: 1023px)` half that the\n * dialog-footer floor in `styles.css` uses.\n *\n * WHY EVERY SUB-44 RUNG AND NOT JUST `sm`: a floor applied to one rung inverts\n * the scale. Lift `sm` (32) alone and it renders TALLER on a phone than\n * `default` (36) and `lg` (40) — the scale would stop being a scale. A floor is\n * only coherent applied to everything beneath it.\n *\n * The mechanism is `min-height`/`min-width`, not an invisible 44px hit ring\n * over a 32px pill. A ring is the tap-target package's pattern and it is right\n * THERE (isolated glass buttons), but on a toolbar of adjacent `sm` buttons\n * separated by an 8px gap the rings overlap in the gap and one button silently\n * eats taps aimed at its neighbour — unacceptable where a neighbour is\n * destructive. `lib/entity-list`'s own phone contract (`h-11 min-w-11`) already\n * chose growth for the same reason; this is that choice made once, in the\n * primitive, instead of per surface.\n *\n * `min-width` is raised only on the SQUARE rungs (`icon`, `icon-sm`,\n * `roundIcon`) — a text button is already wider than 44px, and forcing a floor\n * on it would stretch short labels.\n *\n * Opt out on a control that is genuinely not a finger target with\n * `data-touch-exempt` (same escape hatch the footer floor honors), and say why\n * at the call site.\n */\nconst TOUCH_FLOOR_SIZES = new Set([\n \"xs\",\n \"sm\",\n \"default\",\n \"md\",\n \"lg\",\n \"icon\",\n \"icon-sm\",\n \"roundIcon\",\n]);\nconst SQUARE_SIZES = new Set([\"icon\", \"icon-sm\", \"roundIcon\"]);\n\nexport interface ButtonProps\n extends React.ButtonHTMLAttributes<HTMLButtonElement>,\n VariantProps<typeof buttonVariants> {\n asChild?: boolean;\n}\n\n/**\n * THE CURSOR LAW (common-docs/policies/cursor-law.md): a disabled control says\n * so with `not-allowed`, which the package's base layer sets on `:disabled`\n * and `[aria-disabled=\"true\"]`. `pointer-events: none` is never the mechanism\n * — it swallows the cursor. A native `<button disabled>` already fires no\n * click; the two shapes that WOULD fire one are handled here, once:\n * - `asChild` + `disabled` (a Link wearing button styles): marked\n * `aria-disabled`, taken out of the tab order, and its click is swallowed;\n * - `aria-disabled=\"true\"` on an enabled button: its click is swallowed.\n */\nexport function swallowClick(event: React.MouseEvent<HTMLButtonElement>): void {\n event.preventDefault();\n event.stopPropagation();\n}\n\nexport const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(\n ({ className, variant, size, asChild = false, onClick, ...props }, ref) => {\n const Component = asChild ? Slot : \"button\";\n const resolvedSize = size ?? \"default\";\n const disabledChild = asChild && Boolean(props.disabled);\n const ariaDisabled = props[\"aria-disabled\"];\n const inert =\n disabledChild || ariaDisabled === true || ariaDisabled === \"true\";\n return (\n <Component\n className={cn(buttonVariants({ variant, size, className }))}\n data-matrx-button=\"\"\n data-tap-floor={TOUCH_FLOOR_SIZES.has(resolvedSize) ? \"\" : undefined}\n data-tap-floor-square={\n SQUARE_SIZES.has(resolvedSize) ? \"\" : undefined\n }\n ref={ref}\n {...props}\n aria-disabled={disabledChild ? true : ariaDisabled}\n tabIndex={disabledChild ? -1 : props.tabIndex}\n onClick={inert ? swallowClick : onClick}\n />\n );\n },\n);\nButton.displayName = \"Button\";\n","\"use client\";\n\n/**\n * AlertDialog — the confirm/destroy surface (78 host import sites).\n *\n * Ported from matrx-frontend `components/ui/alert-dialog.tsx`, which was the\n * only variant in the fleet that had been hardened. Its rulings, kept verbatim:\n *\n * 1. THE ROOT RENDERS UNCONDITIONALLY — no hydration mount gate. The gate a\n * wrapper once carried (\"Radix ids differ between SSR and client\") was\n * false, and it deleted always-visible Triggers (delete buttons, mostly)\n * from SSR and the first client paint.\n *\n * 2. AN UNDESCRIBED ALERT DIALOG STILL DESCRIBES ITSELF. A confirm dialog with\n * no `AlertDialogDescription` gets a screen-reader-only one rather than a\n * console warning — the surface where a blind user is about to destroy\n * something is the wrong place to ship an accessibility gap.\n *\n * ADDED HERE, from the same doctrine `Dialog` already carries and this\n * component demonstrably needed:\n *\n * 3. IT IS CLAMPED TO THE VIEWPORT AND SCROLLS INSIDE ITSELF\n * (`max-h-[85dvh] overflow-y-auto`). The host copy was NOT — an alert\n * dialog whose body listed what is about to be deleted pushed Cancel and\n * Continue below the fold on a short viewport, and the only way out was a\n * backdrop click. On an ALERT dialog Radix does not dismiss on backdrop\n * click, so the surface was a genuine dead end. Recorded in CHANGELOG as a\n * real defect fixed in the port, not \"preserved\".\n *\n * 4. THE ACTIONS ARE 44px TALL ON COARSE POINTERS. `AlertDialogAction` and\n * `AlertDialogCancel` inherit the package Button's own target rules through\n * `buttonVariants`; the footer keeps them safe-area padded on mobile.\n *\n * 5. THE STICKY FOOTER NEVER PAINTS OVER THE BODY (0.11.3). Ruling 3's footer\n * bled over the card's bottom padding with a negative block margin, and\n * `position: sticky` clamps a box to its containing block — so the footer\n * was dragged UP by `--dialog-pad` against the card's `gap-4`, covering the\n * last 8px of the consequence copy at every length, unreachable because the\n * card did not scroll. The bleed is now the card's RESERVATION\n * (`.matrx-dialog-card` hands its bottom padding to the footer), which\n * sticky has nothing to clamp. See `sticky-footer-geometry.test.tsx`.\n *\n * SEAM INVERSION. The host resolved its portal target through\n * `usePopoutContainer` (its window-panel popout body); here that is the\n * package's `PortalContainerProvider`, with an explicit `container` prop still\n * winning.\n */\n\nimport * as AlertDialogPrimitive from \"@radix-ui/react-alert-dialog\";\nimport { treeContainsComponent } from \"@ai-matrx/kit/react-tree\";\nimport * as React from \"react\";\n\nimport { buttonVariants } from \"./button\";\nimport { cn } from \"./cn\";\nimport { useModalLayer } from \"./floating-layer\";\nimport { CENTERED_DIALOG, MOTION_DIALOG, MOTION_OVERLAY } from \"./motion\";\nimport { usePortalContainer } from \"./portal-container\";\nimport { keepMovedFocus } from \"./focus-return\";\n\nconst AlertDialog = AlertDialogPrimitive.Root;\n\nconst AlertDialogTrigger = AlertDialogPrimitive.Trigger;\n\n/**\n * Portal-seam-aware AlertDialogPortal. Explicit `container` wins; with none,\n * the injected container; with neither, Radix's `document.body`.\n */\nconst AlertDialogPortal = ({\n container,\n ...props\n}: Omit<\n React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Portal>,\n \"container\"\n> & {\n /** `undefined` → use the injected container; `null` → force document.body. */\n container?: HTMLElement | null | undefined;\n}) => {\n const resolved = usePortalContainer(container);\n return (\n <AlertDialogPrimitive.Portal container={resolved ?? null} {...props} />\n );\n};\nAlertDialogPortal.displayName = \"AlertDialogPortal\";\n\nconst AlertDialogOverlay = React.forwardRef<\n React.ComponentRef<typeof AlertDialogPrimitive.Overlay>,\n React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Overlay>\n>(({ className, ...props }, ref) => (\n <AlertDialogPrimitive.Overlay\n ref={ref}\n data-slot=\"alert-dialog-overlay\"\n className={cn(\n \"fixed inset-0 z-[10000] bg-[var(--matrx-overlay-scrim)]\",\n MOTION_OVERLAY,\n className,\n )}\n {...props}\n />\n));\nAlertDialogOverlay.displayName = AlertDialogPrimitive.Overlay.displayName;\n\n/**\n * Unstyled, non-portalling Content for custom layouts. AlertDialog is always\n * modal, so `aria-modal` is stated rather than derived.\n */\nconst AlertDialogContentPrimitive = React.forwardRef<\n React.ComponentRef<typeof AlertDialogPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Content>\n>(({ onCloseAutoFocus, ...props }, ref) => {\n // Always blocking: floating layers opened from it stack above its scrim.\n useModalLayer(true);\n return <AlertDialogPrimitive.Content {...props} ref={ref} aria-modal=\"true\" onCloseAutoFocus={keepMovedFocus(onCloseAutoFocus)} />;\n});\nAlertDialogContentPrimitive.displayName = \"AlertDialogContentPrimitive\";\n\nconst AlertDialogDescription = React.forwardRef<\n React.ComponentRef<typeof AlertDialogPrimitive.Description>,\n React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Description>\n>(({ className, ...props }, ref) => (\n <AlertDialogPrimitive.Description\n ref={ref}\n data-slot=\"alert-dialog-description\"\n className={cn(\"text-sm text-muted-foreground\", className)}\n {...props}\n />\n));\nAlertDialogDescription.displayName =\n AlertDialogPrimitive.Description.displayName;\n\nexport interface AlertDialogContentProps\n extends React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Content> {\n /** Explicit portal target; wins over the injected container. */\n container?: HTMLElement | null;\n /**\n * Package-owned open/close motion. Default `true`. Pass `false` for a\n * surface that must appear instantly. It is NOT the reduced-motion switch;\n * `styles.css` already honors `prefers-reduced-motion`.\n */\n animated?: boolean;\n}\n\nconst AlertDialogContent = React.forwardRef<\n React.ComponentRef<typeof AlertDialogPrimitive.Content>,\n AlertDialogContentProps\n>(({ className, children, container, animated = true, ...props }, ref) => {\n const hasDescription =\n treeContainsComponent(children, AlertDialogDescription) ||\n treeContainsComponent(children, AlertDialogPrimitive.Description);\n return (\n <AlertDialogPortal container={container}>\n <AlertDialogOverlay />\n <AlertDialogContentPrimitive\n ref={ref}\n data-slot=\"alert-dialog-content\"\n className={cn(\n `matrx-dialog-card fixed left-[50%] top-[50%] z-[10000] grid min-w-0 w-full max-w-lg ${CENTERED_DIALOG} gap-4 border bg-background p-6 shadow-lg`,\n // Ruling 3 — never taller than the viewport, always scrollable, and\n // the footer stays reachable via --dialog-pad like Dialog's.\n // Ruling 5 (0.11.3) — `matrx-dialog-card` hands the bottom padding to\n // a sticky footer when there is one, so the footer's box matches the\n // space the grid gave it and sticky never clamps it up over the\n // consequence copy.\n \"max-h-[85dvh] overflow-y-auto overscroll-contain [--dialog-pad:1.5rem] overflow-x-clip [overflow-wrap:anywhere] [&>*]:min-w-0 [&>*]:max-w-full\",\n \"sm:rounded-lg\",\n animated && MOTION_DIALOG,\n className,\n )}\n {...props}\n >\n {hasDescription ? null : (\n <AlertDialogPrimitive.Description className=\"sr-only\">\n Please confirm the action described in this dialog.\n </AlertDialogPrimitive.Description>\n )}\n {children}\n </AlertDialogContentPrimitive>\n </AlertDialogPortal>\n );\n});\nAlertDialogContent.displayName = AlertDialogPrimitive.Content.displayName;\n\nconst AlertDialogHeader = ({\n className,\n ...props\n}: React.HTMLAttributes<HTMLDivElement>) => (\n <div\n data-slot=\"alert-dialog-header\"\n className={cn(\"flex flex-col space-y-2 text-center sm:text-left\", className)}\n {...props}\n />\n);\nAlertDialogHeader.displayName = \"AlertDialogHeader\";\n\nconst AlertDialogFooter = ({\n className,\n ...props\n}: React.HTMLAttributes<HTMLDivElement>) => (\n <div\n data-slot=\"alert-dialog-footer\"\n className={cn(\n \"flex flex-col-reverse gap-2 sm:flex-row sm:justify-end sm:gap-0 sm:space-x-2\",\n // Ruling 3/4 — sticky to the card edges so a scrolled body never shows\n // through under the actions, and safe-area padded on a phone.\n //\n // 🚨 THERE IS NO `mb-[…]` HERE, AND THERE MUST NEVER BE ONE AGAIN\n // (0.11.3, feedback bf8fb00b). The bleed over the card's bottom padding\n // used to be a NEGATIVE BLOCK MARGIN, which makes this box taller than\n // the grid area the card allocates it — and `position: sticky` CLAMPS a\n // box to its containing block, so the browser yanked the footer UP by\n // `--dialog-pad` against the card's `gap-4` and painted 8px of opaque\n // footer over the last line of the consequence, at every length. The\n // card now RESERVES this footer's block size instead (`matrx-dialog-card`\n // in styles.css hands over its `padding-bottom`), so the bleed costs no\n // margin at all. Guard: `sticky-footer-geometry.test.tsx`.\n //\n // These stay UTILITIES rather than a shipped rule so a caller's\n // `className` still wins through tailwind-merge — a shipped rule would\n // have to be unlayered to survive Tailwind preflight (§ THE PREFLIGHT\n // RULE in styles.css) and would then override every caller's padding.\n \"sticky bottom-0 z-10 bg-background pt-3\",\n \"mx-[calc(var(--dialog-pad,0px)*-1)] px-[var(--dialog-pad,0px)] pb-[var(--dialog-pad,0px)]\",\n className,\n )}\n {...props}\n />\n);\nAlertDialogFooter.displayName = \"AlertDialogFooter\";\n\nconst AlertDialogTitle = React.forwardRef<\n React.ComponentRef<typeof AlertDialogPrimitive.Title>,\n React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Title>\n>(({ className, ...props }, ref) => (\n <AlertDialogPrimitive.Title\n ref={ref}\n data-slot=\"alert-dialog-title\"\n className={cn(\"text-lg font-semibold\", className)}\n {...props}\n />\n));\nAlertDialogTitle.displayName = AlertDialogPrimitive.Title.displayName;\n\nconst AlertDialogAction = React.forwardRef<\n React.ComponentRef<typeof AlertDialogPrimitive.Action>,\n React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Action>\n>(({ className, ...props }, ref) => (\n <AlertDialogPrimitive.Action\n ref={ref}\n data-slot=\"alert-dialog-action\"\n className={cn(buttonVariants(), className)}\n {...props}\n />\n));\nAlertDialogAction.displayName = AlertDialogPrimitive.Action.displayName;\n\nconst AlertDialogCancel = React.forwardRef<\n React.ComponentRef<typeof AlertDialogPrimitive.Cancel>,\n React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Cancel>\n>(({ className, ...props }, ref) => (\n <AlertDialogPrimitive.Cancel\n ref={ref}\n data-slot=\"alert-dialog-cancel\"\n className={cn(\n buttonVariants({ variant: \"outline\" }),\n \"mt-2 sm:mt-0\",\n className,\n )}\n {...props}\n />\n));\nAlertDialogCancel.displayName = AlertDialogPrimitive.Cancel.displayName;\n\nexport {\n AlertDialog,\n AlertDialogAction,\n AlertDialogCancel,\n AlertDialogContent,\n AlertDialogContentPrimitive,\n AlertDialogDescription,\n AlertDialogFooter,\n AlertDialogHeader,\n AlertDialogOverlay,\n AlertDialogPortal,\n AlertDialogTitle,\n AlertDialogTrigger,\n};\n","\"use client\";\n\n/**\n * THE ONE CONTROL — the settled control family (owner, 2026-10-02/03).\n *\n * Every control here is the same object: 28px visible height, capsule, 13px/500\n * label, 16px glyph inset 6px, text inset 10px, and HALF A GAP (3px) of its own\n * on each side so containers add no gap. There is NO size prop: agents get no\n * choice. Geometry and color live in `controls.css`, locked inside\n * `@layer matrx-tap-lock` (`!important` in the host's first layer), so a call\n * site's `className` can place a control (width, flex, grid, position) but can\n * never restyle it. The rare big control is a different component behind a\n * `// ui-exception:` comment, never a prop.\n *\n * Built on the package's own internals — Radix Slot / Switch / DropdownMenu, the\n * cursor law's `swallowClick`, `SelectChevron`, the package icons — so nothing\n * here is a second implementation of a behavior the package already owns.\n */\n\nimport * as SwitchPrimitives from \"@radix-ui/react-switch\";\nimport { Slot, Slottable } from \"@radix-ui/react-slot\";\nimport * as React from \"react\";\n\nimport { swallowClick } from \"../button\";\nimport { cn } from \"../cn\";\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuLabel,\n DropdownMenuRadioGroup,\n DropdownMenuRadioItem,\n DropdownMenuSeparator,\n DropdownMenuTrigger,\n} from \"../dropdown-menu\";\nimport { MagnifyingGlassIcon, PlusIcon } from \"../icons\";\nimport { SelectChevron } from \"../select\";\nimport { isIconOnly } from \"./icon-only\";\nimport { boxStyle, useAutoGrow, useMergedTextareaRef } from \"../textarea\";\n\n/* ------------------------------------------------------------------ */\n/* Layout: the row and the scope */\n/* ------------------------------------------------------------------ */\n\nexport interface ControlRowProps extends React.HTMLAttributes<HTMLDivElement> {\n /** Keep the controls on one line (a row's trailing actions). */\n nowrap?: boolean;\n}\n\n/** A row of controls. It adds no gap: each control carries its own half-gap. */\nexport const ControlRow = React.forwardRef<HTMLDivElement, ControlRowProps>(\n ({ className, nowrap, ...props }, ref) => (\n <div\n ref={ref}\n data-matrx-control-row=\"\"\n data-nowrap={nowrap ? \"\" : undefined}\n className={cn(\"matrx-control-row\", className)}\n {...props}\n />\n ),\n);\nControlRow.displayName = \"ControlRow\";\n\n/**\n * Until the tap tokens move to 28/34 app-wide (the rollout), a tap button\n * inside a ControlScope matches the controls beside it: a 28px pill in a 34px\n * box. Wrap a page (or a region) that mixes tap buttons and controls.\n */\nexport const ControlScope = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(\n (props, ref) => <div ref={ref} data-matrx-controls=\"\" {...props} />,\n);\nControlScope.displayName = \"ControlScope\";\n\n/**\n * THE CONTAINER a collapsing control measures (`Button collapse=\"container\"`).\n * A host declares it on the box whose WIDTH decides — a list pane, a panel,\n * never the viewport: beside a chat panel a 1024px screen holds a 540px list.\n * `className={CONTROLS_CONTAINER_CLASS}`, or add the name to the box's own\n * `container-name` when it already names a container (`list matrx-controls`).\n */\nexport const CONTROLS_CONTAINER_NAME = \"matrx-controls\";\nexport const CONTROLS_CONTAINER_CLASS = \"matrx-controls-container\";\n/** Below this container width a `collapse=\"container\"` button is its icon alone (48rem). */\nexport const CONTROLS_COLLAPSE_BELOW_REM = 48;\n\n/* ------------------------------------------------------------------ */\n/* Button */\n/* ------------------------------------------------------------------ */\n\n/**\n * Tone, never size. `success` is the solid confirm-a-good-outcome fill (approve,\n * publish, mark done); `link` is a text action at the control's height — no\n * fill, no border, primary ink, underline on hover (an inline \"View all\").\n */\nexport type ControlVariant = \"primary\" | \"quiet\" | \"outline\" | \"danger\" | \"success\" | \"link\";\n\n/**\n * THE NAMED CONTROL WIDTHS (0.68.22) — a button, field or select trigger that should not fill\n * its row takes one of these instead of a pasted `w-40`. Derived from the call sites:\n * `xs` 6rem (a unit, a short enum), `sm` 8rem, `md` 10rem (a date, a status), `lg` 14rem (a\n * name, an account), `xl` 20rem (a search, a URL). Never wider than its container.\n */\nexport type ControlWidth = \"xs\" | \"sm\" | \"md\" | \"lg\" | \"xl\";\n\ninterface ButtonBase extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, \"children\"> {\n /** Tone, never size. Default `outline`. */\n variant?: ControlVariant;\n /** A status tint from the role tokens (the Badge's), for a button that\n * reports a state — a drift door, an alert count. Default: none. */\n tone?: BadgeTone;\n /** Leading 16px glyph. */\n icon?: React.ReactNode;\n /** Trailing 16px glyph (a menu chevron, an external-link mark). */\n iconEnd?: React.ReactNode;\n /** Render the one child element (a link) with the button's skin. */\n asChild?: boolean;\n /**\n * `\"container\"`: below 48rem of the nearest `matrx-controls` container\n * (CONTROLS_CONTAINER_NAME) the button is its leading `icon` alone — a 28px\n * circle; the label stays its accessible name and its tooltip. Needs `icon`;\n * without one it never collapses. Outside such a container it never does.\n */\n collapse?: \"container\";\n /**\n * A TOGGLE (a choice in a set, a mode, a tab-like switch): `true` is on —\n * the accent fill and full ink; `false` is off — no fill, quiet ink. Sets\n * `aria-pressed`. Omit for an ordinary action.\n */\n pressed?: boolean;\n /**\n * A count or a dot on the button's top-right corner, for something waiting\n * behind it (items added, unread). A number draws the count (99+ above 99;\n * 0 draws nothing); `true` draws an 8px dot. On a button with a text label\n * the count sits in the row after the label instead (never over it). Name it in `aria-label` too —\n * the mark is decoration.\n */\n badge?: number | boolean;\n /**\n * The glyph's own status ink, for a glyph whose COLOR carries meaning (the\n * green check after a copy, an amber debug bug) while the button stays\n * quiet. Tints only the icon(s), never the fill. Default: none.\n */\n glyphTone?: GlyphTone;\n /**\n * A removing act (clear, remove, disconnect): muted until hover,\n * destructive on hover — the delete tier-1 skin on any glyph or label.\n * Quiet variant only.\n */\n removes?: boolean;\n /**\n * MIXED CONTENT (0.68.12): a short muted fact after the label — a count, a\n * size, a shortcut, a \"3 of 12\" — in the 12px secondary ink. The button\n * stays 28px; the fact is part of the button, never a second element styled\n * beside it. Never a sentence.\n */\n meta?: React.ReactNode;\n /** A named width instead of the label's own (see `ControlWidth`). */\n width?: ControlWidth;\n /**\n * THE INVITING-PAGE CALL TO ACTION (0.68.22): a 44px capsule with a 16px/600 label and a\n * 24px inset — the size a marketing hero, a module landing or a kit's front door asks for.\n * Inviting pages are never densified; functional pages never use it. A `primary` hero\n * carries a soft primary glow.\n */\n hero?: boolean;\n}\n/** The status inks a glyph may carry (the role tokens). */\nexport type GlyphTone = \"success\" | \"warning\" | \"destructive\" | \"info\" | \"primary\";\ninterface LabelledButton extends ButtonBase {\n children: React.ReactNode;\n}\ninterface IconOnlyButton extends ButtonBase {\n children?: undefined;\n /** An icon-only button must say what it does. */\n \"aria-label\": string;\n}\nexport type ButtonProps = LabelledButton | IconOnlyButton;\n\nfunction glyphSlot(icon: unknown, iconEnd: unknown, label: unknown): string | undefined {\n if (!label && (icon || iconEnd)) return \"only\";\n if (icon && iconEnd) return \"both\";\n if (icon) return \"start\";\n if (iconEnd) return \"end\";\n return undefined;\n}\n\n/**\n * THE button: primary / quiet / outline / danger / success / link, one 28px geometry; text,\n * icon + text, or icon-only (a 28px circle). `asChild` puts the skin on a link.\n */\nexport const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(\n ({ className, variant = \"outline\", tone, icon, iconEnd, asChild = false, collapse, pressed, badge, glyphTone, removes, meta, width, hero, children, onClick, type, ...props }, ref) => {\n const Component = asChild ? Slot : \"button\";\n const badgeText =\n typeof badge === \"number\" ? (badge > 0 ? (badge > 99 ? \"99+\" : String(badge)) : null) : badge ? \"\" : null;\n const ariaDisabled = props[\"aria-disabled\"];\n const disabledChild = asChild && Boolean(props.disabled);\n const inert = disabledChild || ariaDisabled === true || ariaDisabled === \"true\";\n // asChild: the child element carries the label, so the glyph slot reads\n // the child's own children.\n const label = asChild && React.isValidElement<{ children?: React.ReactNode }>(children)\n ? children.props.children\n : children;\n const collapses = collapse === \"container\" && Boolean(icon) && Boolean(label);\n return (\n <Component\n ref={ref}\n type={asChild ? undefined : (type ?? \"button\")}\n data-matrx-control=\"button\"\n data-variant={variant}\n data-tone={tone && tone !== \"neutral\" ? tone : undefined}\n data-glyph={glyphSlot(icon, iconEnd, label)}\n data-collapse={collapses ? \"container\" : undefined}\n data-pressed={pressed === undefined ? undefined : pressed ? \"true\" : \"false\"}\n aria-pressed={pressed}\n data-badge={badgeText === null ? undefined : badgeText === \"\" ? \"dot\" : \"count\"}\n // A labeled button carries its count IN the row after the label: the\n // corner count sat over the label's last letter (\"HR 28\" on /tasks).\n data-badge-place={badgeText && label ? \"inline\" : undefined}\n data-glyph-tone={glyphTone}\n data-delete={removes ? \"\" : undefined}\n data-width={width}\n data-hero={hero ? \"\" : undefined}\n className={cn(\"matrx-control matrx-control-button matrx-glyph-trim\", className)}\n // A collapsed button still says what it does on hover.\n title={collapses && typeof label === \"string\" && props.title === undefined ? label : undefined}\n {...props}\n aria-disabled={disabledChild ? true : ariaDisabled}\n tabIndex={disabledChild ? -1 : props.tabIndex}\n onClick={inert ? swallowClick : onClick}\n >\n {icon}\n <Slottable>\n {/* A text label NEVER spills past its button (owner, 2026-10-05: a\n long chat title ran under the mode switch beside it). It sits in\n its own box so a capped button ellipsizes instead of overflowing. */}\n {!asChild && (typeof children === \"string\" || typeof children === \"number\") ? (\n <span className=\"matrx-control-button-label\">{children}</span>\n ) : (\n children\n )}\n </Slottable>\n {meta === undefined || meta === null || meta === false ? null : (\n <span className=\"matrx-control-button-meta\">{meta}</span>\n )}\n {iconEnd}\n {badgeText === null ? null : (\n <span className=\"matrx-control-button-badge\" aria-hidden=\"true\">\n {badgeText}\n </span>\n )}\n </Component>\n );\n },\n);\nButton.displayName = \"Button\";\n\n/** A split button: two Buttons joined — the act, and its menu of variants. */\nexport const SplitButton = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(\n ({ className, ...props }, ref) => (\n <div ref={ref} role=\"group\" data-matrx-control=\"split\" className={cn(\"matrx-control-split\", className)} {...props} />\n ),\n);\nSplitButton.displayName = \"SplitButton\";\n\n/* ------------------------------------------------------------------ */\n/* Field (input capsule) and SearchField */\n/* ------------------------------------------------------------------ */\n\nexport interface FieldProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, \"size\"> {\n /** Leading 16px glyph. */\n icon?: React.ReactNode;\n /** Trailing content inside the capsule — a clear button, a unit. */\n end?: React.ReactNode;\n /** A named width instead of filling the row (see `ControlWidth`). */\n width?: ControlWidth;\n /**\n * THE INVITING-PAGE INPUT: a 56px capsule with an 18px value and a 24px inset — the big,\n * friendly field a welcome / onboarding front door asks for (pairs with Button `hero`).\n * Inviting pages only; functional pages never use it.\n */\n hero?: boolean;\n /**\n * THE LEADING SEARCH: a 48px filled capsule — no frame, the muted fill, a 16px value, a 20px\n * glyph — that turns the card color with a soft lift on focus. The one search a home page leads\n * with (a file home's search, as on Google Docs / Drive). One per page; never in a form or toolbar.\n */\n filled?: boolean;\n}\n\n/** The input capsule. `className`/`style` place the capsule (width, flex). */\nexport const Field = React.forwardRef<HTMLInputElement, FieldProps>(\n ({ className, style, icon, end, width, hero, filled, ...props }, ref) => (\n <label\n data-matrx-control=\"field\"\n data-glyph={icon ? \"start\" : undefined}\n data-width={width}\n data-hero={hero ? \"\" : undefined}\n data-filled={filled ? \"\" : undefined}\n className={cn(\"matrx-control matrx-control-field\", className)}\n style={style}\n >\n {icon}\n <input ref={ref} {...props} />\n {end}\n </label>\n ),\n);\nField.displayName = \"Field\";\n\n/** The search capsule: a Field with the magnifier, `type=\"search\"`. */\nexport const SearchField = React.forwardRef<HTMLInputElement, Omit<FieldProps, \"icon\">>(\n ({ placeholder = \"Search\", ...props }, ref) => (\n <Field\n ref={ref}\n type=\"search\"\n icon={<MagnifyingGlassIcon aria-hidden=\"true\" />}\n placeholder={placeholder}\n aria-label={props[\"aria-label\"] ?? placeholder}\n {...props}\n />\n ),\n);\nSearchField.displayName = \"SearchField\";\n\n/* ------------------------------------------------------------------ */\n/* Select — a capsule trigger over a radio menu */\n/* ------------------------------------------------------------------ */\n\nexport interface SelectOption<T extends string = string> {\n value: T;\n label: string;\n /** 11px trailing text in the menu (a count, a shortcut). */\n meta?: string;\n /** Muted text right after the label, menu and trigger alike: what tells two same-named options apart (a short id, an owner). */\n hint?: string;\n /** A section heading: the menu shows it (foreground weight) above the first option of each consecutive run. */\n group?: string;\n /** Shown but not choosable (an unavailable tool, a sentinel the URL set). */\n disabled?: boolean;\n}\n\nexport interface SelectProps<T extends string = string> {\n value: T;\n options: readonly SelectOption<T>[];\n onValueChange: (value: T) => void;\n \"aria-label\": string;\n /** Leading 16px glyph on the trigger. */\n icon?: React.ReactNode;\n align?: \"start\" | \"end\";\n disabled?: boolean;\n /**\n * `field` (default): the capsule a form row uses. `inline`: the value as text with a small chevron,\n * no capsule — for a choice that sits inside a dense row or a toolbar sentence (\"Full ⌄\"), where a\n * row of capsules reads as clutter (Arman, 2026-10-14).\n */\n variant?: \"field\" | \"inline\";\n /**\n * A search row at the top of the menu once there are at least this many options (a long list of\n * organizations). It matches label, hint and group. Omitted: never.\n */\n searchAt?: number;\n /** Placement only (width, flex). */\n className?: string;\n style?: React.CSSProperties;\n}\n\nexport function Select<T extends string = string>({\n value,\n options,\n onValueChange,\n icon,\n align = \"start\",\n disabled,\n className,\n style,\n \"aria-label\": ariaLabel,\n variant = \"field\",\n searchAt,\n}: SelectProps<T>) {\n const current = options.find((o) => o.value === value);\n const [query, setQuery] = React.useState(\"\");\n const searchable = searchAt !== undefined && options.length >= searchAt;\n const q = searchable ? query.trim().toLowerCase() : \"\";\n const shown = q ? options.filter((o) => [o.label, o.hint, o.group].some((t) => t?.toLowerCase().includes(q))) : options;\n return (\n <DropdownMenu onOpenChange={(open) => !open && setQuery(\"\")}>\n <DropdownMenuTrigger asChild disabled={disabled}>\n <button\n type=\"button\"\n data-matrx-control=\"select\"\n data-variant={variant === \"inline\" ? \"inline\" : undefined}\n data-glyph={icon ? \"start\" : undefined}\n className={cn(\"matrx-control matrx-control-select\", className)}\n style={style}\n aria-label={ariaLabel}\n >\n <span className=\"matrx-control-select-value\">\n {icon}\n <span>{current?.label ?? value}</span>\n {current?.hint ? <span className=\"text-muted-foreground\" data-select-hint=\"\">{current.hint}</span> : null}\n </span>\n <SelectChevron />\n </button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align={align} className=\"max-h-80 w-max min-w-[max(10rem,var(--radix-dropdown-menu-trigger-width))] max-w-[min(24rem,var(--radix-dropdown-menu-content-available-width))] overflow-y-auto\">\n {searchable ? (\n <div className=\"sticky top-0 z-10 bg-popover p-1\" data-select-search=\"\">\n <SearchField\n className=\"w-full\"\n value={query}\n autoFocus\n aria-label={`Search ${ariaLabel}`}\n onChange={(e) => setQuery(e.target.value)}\n // The menu's type-ahead never takes the letters; arrows and Escape still drive the menu.\n onKeyDown={(e) => {\n if (e.key !== \"ArrowDown\" && e.key !== \"ArrowUp\" && e.key !== \"Escape\" && e.key !== \"Tab\") e.stopPropagation();\n }}\n />\n </div>\n ) : null}\n {searchable && shown.length === 0 ? <div className=\"px-2 py-1.5 text-[0.8125rem] text-muted-foreground\" role=\"status\">No match</div> : null}\n <DropdownMenuRadioGroup value={value} onValueChange={(v) => onValueChange(v as T)}>\n {shown.map((o, i) => (\n <React.Fragment key={o.value}>\n {o.group && o.group !== shown[i - 1]?.group ? (\n <>\n {i > 0 ? <DropdownMenuSeparator /> : null}\n <DropdownMenuLabel>{o.group}</DropdownMenuLabel>\n </>\n ) : null}\n <DropdownMenuRadioItem value={o.value} disabled={o.disabled === true} className=\"text-[0.8125rem]\">\n {/* The label truncates; the hint never does (it is what tells two same-named options apart). */}\n <span className=\"flex min-w-0 flex-1 items-baseline\">\n <span className=\"min-w-0 truncate\">{o.label}</span>\n {o.hint ? <span className=\"ml-1.5 shrink-0 text-muted-foreground\" data-select-hint=\"\">{o.hint}</span> : null}\n </span>\n {o.meta ? <span className=\"ml-3 text-[0.6875rem] text-muted-foreground\">{o.meta}</span> : null}\n </DropdownMenuRadioItem>\n </React.Fragment>\n ))}\n </DropdownMenuRadioGroup>\n </DropdownMenuContent>\n </DropdownMenu>\n );\n}\n\n/* ------------------------------------------------------------------ */\n/* SegmentedControl and Tabs */\n/* ------------------------------------------------------------------ */\n\nexport interface SegmentOption<T extends string = string> {\n value: T;\n label: React.ReactNode;\n /** An 11px count after the label. */\n count?: number | null;\n ariaLabel?: string;\n /** Hover text (an icon-only segment's name). */\n title?: string;\n disabled?: boolean;\n}\n\nexport interface SegmentedControlProps<T extends string = string> {\n /** The selected segment; `null` = none is selected (an optional choice). */\n value: T | null;\n onValueChange: (value: T) => void;\n data: readonly SegmentOption<T>[];\n \"aria-label\": string;\n /** The segments share the row's whole width equally (a full-width choice: levels, modes). */\n fill?: boolean;\n /** Placement only. */\n className?: string;\n style?: React.CSSProperties;\n}\n\nfunction SegmentItems<T extends string>({\n data,\n value,\n onValueChange,\n role,\n}: {\n data: readonly SegmentOption<T>[];\n value: T | null;\n onValueChange: (value: T) => void;\n role: \"tab\" | undefined;\n}) {\n return (\n <>\n {data.map((o) => {\n const on = o.value === value;\n return (\n <button\n key={o.value}\n type=\"button\"\n role={role}\n aria-selected={role ? on : undefined}\n aria-pressed={role ? undefined : on}\n aria-label={o.ariaLabel}\n title={o.title}\n disabled={o.disabled}\n data-state={on ? \"on\" : \"off\"}\n data-icon-only={o.count == null && isIconOnly(o.label) ? \"\" : undefined}\n className=\"matrx-control-segment\"\n onClick={() => onValueChange(o.value)}\n >\n {o.label}\n {o.count != null ? <span className=\"matrx-control-count\">{o.count}</span> : null}\n </button>\n );\n })}\n </>\n );\n}\n\n/** The capsule toggle group: a muted track, the selected thumb inset 2px. */\nexport function SegmentedControl<T extends string = string>({\n value,\n onValueChange,\n data,\n fill,\n className,\n style,\n \"aria-label\": ariaLabel,\n}: SegmentedControlProps<T>) {\n return (\n <div\n role=\"group\"\n aria-label={ariaLabel}\n data-matrx-control=\"segmented\"\n data-fill={fill ? \"\" : undefined}\n className={cn(\"matrx-control matrx-control-segmented\", className)}\n style={style}\n >\n <SegmentItems data={data} value={value} onValueChange={onValueChange} role={undefined} />\n </div>\n );\n}\n\nexport interface TabsProps<T extends string = string> extends SegmentedControlProps<T> {\n /** `underline` for page sections (default); `capsule` for filters. */\n variant?: \"underline\" | \"capsule\";\n /** Underline tabs draw their own hairline (default). Pass `false` when the row the tabs\n * sit in already draws it — the selected underline then lands on that row's rule. */\n rule?: boolean;\n /** Underline tabs inside a framed panel (a card, a bordered box): the labels start at the\n * panel's 12px content inset while the hairline still runs edge to edge. Page-level tabs\n * stay flush with the page gutter (default). Arman, 2026-10-21. */\n inset?: boolean;\n}\n\n/** Tabs: underline for page sections, capsule for filters. */\nexport function Tabs<T extends string = string>({\n variant = \"underline\",\n rule = true,\n inset = false,\n value,\n onValueChange,\n data,\n className,\n style,\n \"aria-label\": ariaLabel,\n}: TabsProps<T>) {\n if (variant === \"capsule\") {\n return (\n <div\n role=\"tablist\"\n aria-label={ariaLabel}\n data-matrx-control=\"tabs\"\n className={cn(\"matrx-control matrx-control-segmented\", className)}\n style={style}\n >\n <SegmentItems data={data} value={value} onValueChange={onValueChange} role=\"tab\" />\n </div>\n );\n }\n return (\n <div\n role=\"tablist\"\n aria-label={ariaLabel}\n data-matrx-control=\"tabs\"\n data-rule={rule ? undefined : \"none\"}\n data-inset={inset ? \"\" : undefined}\n className={cn(\"matrx-control-tabs\", className)}\n style={style}\n >\n {data.map((o) => (\n <button\n key={o.value}\n type=\"button\"\n role=\"tab\"\n aria-selected={o.value === value}\n aria-label={o.ariaLabel}\n disabled={o.disabled}\n className=\"matrx-control-tab\"\n onClick={() => onValueChange(o.value)}\n >\n {o.label}\n {o.count != null ? <span className=\"matrx-control-count\">{o.count}</span> : null}\n </button>\n ))}\n </div>\n );\n}\n\n/* ------------------------------------------------------------------ */\n/* Badge */\n/* ------------------------------------------------------------------ */\n\nexport type BadgeTone = \"neutral\" | \"primary\" | \"success\" | \"warning\" | \"destructive\" | \"info\";\n\nexport interface BadgeProps extends React.HTMLAttributes<HTMLSpanElement> {\n /** A status tint from the role tokens. Default `neutral` (plain outline). */\n tone?: BadgeTone;\n /** A 12px glyph before the label, 4px gap, in the badge's own tone color. */\n icon?: React.ReactNode;\n}\n\n/** Outline, 18px, 11px text, clamped to one line (≤20rem) — never a sentence. */\nexport function Badge({ tone = \"neutral\", icon, className, children, ...props }: BadgeProps) {\n return (\n <span\n data-matrx-control=\"badge\"\n data-tone={tone}\n className={cn(\"matrx-control-badge\", className)}\n title={typeof children === \"string\" ? children : undefined}\n {...props}\n >\n {icon ? (\n <span className=\"matrx-control-badge-icon\" aria-hidden=\"true\">\n {icon}\n </span>\n ) : null}\n <span>{children}</span>\n </span>\n );\n}\n\n/* ------------------------------------------------------------------ */\n/* Chip and ChipSet */\n/* ------------------------------------------------------------------ */\n\n/**\n * The status tones (the Badge's) plus a FIXED set of categorical hues, each a\n * token pair in `controls.css` (`--matrx-chip-<hue>`, stepped for dark). A\n * feature maps its kinds onto these through ONE table of its own\n * (`kind → ChipTone`) — never a class string.\n */\nexport type ChipHue =\n | \"sky\"\n | \"blue\"\n | \"indigo\"\n | \"violet\"\n | \"fuchsia\"\n | \"rose\"\n | \"orange\"\n | \"amber\"\n | \"lime\"\n | \"emerald\"\n | \"teal\"\n | \"cyan\"\n | \"slate\";\nexport type ChipTone = BadgeTone | ChipHue;\n\n/** Every tone a chip accepts, in a fixed order (tests, pickers, demos). */\nexport const CHIP_TONES: readonly ChipTone[] = [\n \"neutral\",\n \"primary\",\n \"success\",\n \"warning\",\n \"destructive\",\n \"info\",\n \"sky\",\n \"blue\",\n \"indigo\",\n \"violet\",\n \"fuchsia\",\n \"rose\",\n \"orange\",\n \"amber\",\n \"lime\",\n \"emerald\",\n \"teal\",\n \"cyan\",\n \"slate\",\n] as const;\n\nexport interface ChipProps extends Omit<React.HTMLAttributes<HTMLSpanElement>, \"children\"> {\n /** The one line of text. Truncates; the full text is the tooltip. */\n label: string;\n /** `item` (default): an existing thing, tinted. `add`: a suggestion to make\n * one — dashed, quiet, with the package's own leading `+`. */\n variant?: \"item\" | \"add\";\n /** A named tone, never a class. Default `neutral`. Ignored by `add`. */\n tone?: ChipTone;\n /** Leading glyph (drawn 14px, optically trimmed). */\n icon?: React.ReactNode;\n /** Put the chip's skin on the one child element (a link or a button); the\n * child carries no children of its own — the chip draws glyph + label. */\n asChild?: boolean;\n /**\n * A FILTER chip (a toggle in a set of choices): `true` is on — tinted in its\n * `tone` (default `primary`); `false` is off — untinted outline, quiet ink.\n * Sets `aria-pressed`. Use with `asChild` on a `<button>`. Omit for a tag.\n */\n pressed?: boolean;\n children?: React.ReactElement;\n}\n\n/**\n * THE chip: a tag that names a thing (a format, a kind, a status, a source).\n * ONE 24px height, one 6px radius, one 12px/500 label, 14px glyph, matched\n * insets, single line with an ellipsis and a tooltip, and the controls' 3px\n * half-gap of its own so a `ChipSet` adds none. Geometry and tint are locked\n * in `controls.css`; a call site may place it, never restyle it.\n */\nexport const Chip = React.forwardRef<HTMLSpanElement, ChipProps>(\n ({ label, variant = \"item\", tone, icon, asChild = false, pressed, children, className, title, ...props }, ref) => {\n const Component = asChild ? Slot : \"span\";\n const glyph = variant === \"add\" ? <PlusIcon className=\"lucide lucide-plus\" /> : icon;\n const toggle = pressed !== undefined && variant === \"item\";\n const resolvedTone = tone ?? (toggle ? \"primary\" : \"neutral\");\n return (\n <Component\n ref={ref}\n data-matrx-control=\"chip\"\n data-variant={variant}\n data-tone={variant === \"add\" ? undefined : resolvedTone}\n data-pressed={toggle ? String(pressed) : undefined}\n aria-pressed={toggle ? pressed : undefined}\n data-glyph={glyph ? (variant === \"add\" && icon ? \"both\" : \"start\") : undefined}\n className={cn(\"matrx-control-chip matrx-glyph-trim\", className)}\n title={title ?? label}\n {...props}\n >\n {glyph}\n {variant === \"add\" ? icon : null}\n {asChild ? <Slottable>{children}</Slottable> : null}\n <span className=\"matrx-control-chip-label\">{label}</span>\n </Component>\n );\n },\n);\nChip.displayName = \"Chip\";\n\nexport interface ChipSetProps extends React.HTMLAttributes<HTMLDivElement> {\n /**\n * `flow` (default): chips sit at their own width and wrap.\n * `grid`: every chip is the same width (auto-filled columns of at least\n * 7.5rem), labels truncate — for a SET of siblings (a kit's formats).\n */\n layout?: \"flow\" | \"grid\";\n}\n\n/** A set of chips: same height, one baseline, the chips space themselves. */\nexport const ChipSet = React.forwardRef<HTMLDivElement, ChipSetProps>(\n ({ layout = \"flow\", className, ...props }, ref) => (\n <div\n ref={ref}\n data-matrx-control=\"chip-set\"\n data-layout={layout}\n className={cn(\"matrx-control-chip-set\", className)}\n {...props}\n />\n ),\n);\nChipSet.displayName = \"ChipSet\";\n\n/* ------------------------------------------------------------------ */\n/* Switch and Textarea */\n/* ------------------------------------------------------------------ */\n\nexport type SwitchProps = Omit<React.ComponentPropsWithoutRef<typeof SwitchPrimitives.Root>, \"children\">;\n\n/** A 20px track in the 28px control box, so it lines up with every control. */\nexport const Switch = React.forwardRef<React.ComponentRef<typeof SwitchPrimitives.Root>, SwitchProps>(\n ({ className, ...props }, ref) => (\n <SwitchPrimitives.Root\n ref={ref}\n data-matrx-control=\"switch\"\n className={cn(\"matrx-control matrx-control-switch\", className)}\n {...props}\n >\n <span className=\"matrx-control-switch-track\">\n <SwitchPrimitives.Thumb className=\"matrx-control-switch-thumb\" />\n </span>\n </SwitchPrimitives.Root>\n ),\n);\nSwitch.displayName = \"Switch\";\n\nexport interface TextareaProps extends React.TextareaHTMLAttributes<HTMLTextAreaElement> {\n /** The roomy writing surface used by inviting prompt boxes. */\n hero?: boolean;\n /** Join a pinned status row below this field from the small breakpoint upward. */\n joinedBottom?: boolean;\n /** `field` (default): the field skin. `bare`: the surrounding surface draws the frame (a\n * composer) — no border, no fill, no inset, no focus ring of its own. */\n variant?: \"field\" | \"bare\";\n /** Monospace text — code, JSON, keys. */\n mono?: boolean;\n /** Grow with the content (stopping at `maxHeight`, then scroll). */\n autoGrow?: boolean;\n /** Minimum height in px (a writing area that must start tall). `rows` also sizes it. */\n minHeight?: number;\n /** Maximum height in px; past it the field scrolls. */\n maxHeight?: number;\n /** Space occupied by an overlaid control cluster, so editable text stays clear of it. */\n reservedInlineEnd?: number;\n /** Space occupied by an overlaid row of controls at the bottom of the writing area. */\n reservedBlockEnd?: number;\n}\n\n/**\n * The field skin, multi-line (8px radius — a capsule cannot hold paragraphs). Height is the\n * textarea's own business — `rows`, `minHeight`/`maxHeight`, `autoGrow`, `resize` — never a class.\n */\nexport const Textarea = React.forwardRef<HTMLTextAreaElement, TextareaProps>(\n ({ className, style, variant = \"field\", mono, hero, joinedBottom, autoGrow, minHeight, maxHeight, reservedInlineEnd, reservedBlockEnd, ...props }, forwarded) => {\n const { ref, callback } = useMergedTextareaRef(forwarded);\n useAutoGrow(ref, props.value, autoGrow, minHeight, maxHeight);\n return (\n <textarea\n ref={callback}\n data-matrx-control=\"textarea\"\n data-variant={variant === \"bare\" ? \"bare\" : undefined}\n data-mono={mono ? \"\" : undefined}\n data-hero={hero ? \"\" : undefined}\n data-joined-bottom={joinedBottom ? \"\" : undefined}\n className={cn(\"matrx-control-textarea\", className)}\n style={{ ...boxStyle(minHeight, maxHeight), ...style,\n ...(reservedInlineEnd === undefined ? {} : { \"--matrx-textarea-reserved-inline-end\": `${Math.max(0, reservedInlineEnd)}px` }),\n ...(reservedBlockEnd === undefined ? {} : { \"--matrx-textarea-reserved-block-end\": `${Math.max(0, reservedBlockEnd)}px` }),\n } as React.CSSProperties}\n {...props}\n />\n );\n },\n);\nTextarea.displayName = \"Textarea\";\n","/**\n * THE ONE FIELD SURFACE (page-pass shared fix, 2026-09-27).\n *\n * Every control a person types into or picks from — Input, BasicInput,\n * Textarea, the Select trigger, and the host's ProInput / ProTextarea — sits on\n * this fill and this border. They used to disagree: Input and the elevated\n * Textarea filled with `bg-background` (the gray page color in light mode),\n * BasicInput and the control Textarea were `bg-transparent` (gray on a gray\n * page), while the Select trigger filled with `bg-card` (white). On one form\n * the text fields therefore looked disabled beside white Selects\n * (/hr/settings/employer, the message-template editor) — a screen that lies\n * about what it will let you do.\n *\n * The surface is the Select's: the card fill and the regular border. A caller\n * that genuinely wants no fill (an inline cell editor) still passes\n * `bg-transparent`, which wins through `cn`.\n */\nexport const FIELD_SURFACE_CLASS = \"border border-border bg-card\";\n","\"use client\";\n\n/**\n * Textarea — the multi-line twin of the Input family, same three shapes:\n * `Textarea` (elevated), `BasicTextarea` (plain control), and\n * `TextareaWithPrefix`.\n *\n * WHAT THE FORKS PROVED. Three hosts shipped a bare `<textarea>` with a\n * min-height and nothing else; matrx-frontend shipped auto-grow, min/max\n * height clamping, and a stretch-detection pass. That last one is the reason\n * this file is worth having: a `<textarea>` is a REPLACED element, so\n * `className=\"h-full\"` on it does nothing useful unless its parent is also\n * told to stretch — which is why every host that wanted a filling textarea\n * ended up wrapping it by hand at the call site, differently each time.\n * `getStretchClasses` reads the caller's own fill intent out of the className\n * and builds the wrapper for them.\n *\n * COLOR IS TOKENS (C26). The ported original pinned its body text to literal\n * black/white, its placeholder and focus ring to raw palette steps, and its\n * dark elevation to a custom property no host defined — so that shadow\n * computed to nothing. All four now resolve from the semantic vocabulary.\n *\n * AND `shadow-textarea` NOW EXISTS. The original's resting elevation class was\n * `shadow-textarea`, and NO host defined `--shadow-textarea` or generated that\n * utility — 125 call sites asked for an elevation they never got. The package\n * ships the token (defaulting to the Input family's `--shadow-input`, which is\n * plainly what the twin class meant) and the rule, so the class finally does\n * what it says. A host that wants the flat look sets `--shadow-textarea: none`.\n *\n * The clipboard/motion variants matrx-frontend layers on top (CopyTextarea,\n * FancyTextarea) stay host-owned under the C8 split-out law: they drag in\n * `motion/react`, and plain-textarea consumers must not pay for it.\n */\n\nimport * as React from \"react\";\n\nimport { cn } from \"./cn\";\nimport { FIELD_SURFACE_CLASS } from \"./field-surface\";\n\nexport interface TextareaProps\n extends React.TextareaHTMLAttributes<HTMLTextAreaElement> {\n /** Grow to fit content as the user types (and stop growing at `maxHeight`). */\n autoGrow?: boolean;\n /** Minimum height in px. */\n minHeight?: number;\n /** Maximum height in px; past it the field scrolls instead of growing. */\n maxHeight?: number;\n /** Classes for the wrapper this component adds when one is needed. */\n wrapperClassName?: string;\n}\n\nconst FILL_HEIGHT_REGEX = /(?:^|\\s)(h-full|h-dvh|flex-1|grow)(?:\\s|$)/;\nconst FILL_WIDTH_REGEX = /(?:^|\\s)(w-full|w-screen)(?:\\s|$)/;\n\n/**\n * A `<textarea>` cannot fill a box on its own — the box has to be told too.\n * Read the caller's fill intent out of its own className and mirror it onto\n * the wrapper, so `className=\"h-full\"` means what the caller thought it meant.\n */\nfunction getStretchClasses(className?: string): string | undefined {\n if (!className) return undefined;\n const fills: string[] = [];\n if (FILL_HEIGHT_REGEX.test(className)) fills.push(\"h-full min-h-0\");\n if (FILL_WIDTH_REGEX.test(className)) fills.push(\"w-full\");\n return fills.length ? fills.join(\" \") : undefined;\n}\n\nconst TEXTAREA_ELEVATED_CLASS =\n `flex h-auto w-full rounded-md ${FIELD_SURFACE_CLASS} px-3 py-2 text-sm text-foreground shadow-textarea transition duration-400 placeholder:text-muted-foreground focus-visible:outline-none focus-visible:border-primary focus-visible:ring-[3px] focus-visible:ring-primary/15 disabled:cursor-not-allowed disabled:opacity-50`;\n\nconst TEXTAREA_CONTROL_CLASS =\n `flex w-full rounded-md ${FIELD_SURFACE_CLASS} px-3 py-2 text-sm text-foreground shadow-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:border-primary focus-visible:ring-[3px] focus-visible:ring-primary/15 disabled:cursor-not-allowed disabled:opacity-50`;\n\nexport function useAutoGrow(\n ref: React.RefObject<HTMLTextAreaElement | null>,\n value: React.TextareaHTMLAttributes<HTMLTextAreaElement>[\"value\"],\n autoGrow = false,\n minHeight?: number,\n maxHeight?: number,\n): void {\n React.useEffect(() => {\n if (!autoGrow || !ref.current) return;\n\n const textarea = ref.current;\n textarea.style.height = \"auto\";\n\n let newHeight = textarea.scrollHeight;\n if (minHeight) newHeight = Math.max(newHeight, minHeight);\n\n if (maxHeight && newHeight >= maxHeight) {\n textarea.style.height = `${maxHeight}px`;\n textarea.style.overflowY = \"auto\";\n } else {\n textarea.style.height = `${newHeight}px`;\n textarea.style.overflowY = \"hidden\";\n }\n }, [value, autoGrow, minHeight, maxHeight, ref]);\n}\n\n/** Merge a forwarded ref with the internal one auto-grow needs to measure. */\nexport function useMergedTextareaRef(\n forwarded: React.ForwardedRef<HTMLTextAreaElement>,\n): {\n ref: React.RefObject<HTMLTextAreaElement | null>;\n callback: (node: HTMLTextAreaElement | null) => void;\n} {\n const internal = React.useRef<HTMLTextAreaElement | null>(null);\n const callback = React.useCallback(\n (node: HTMLTextAreaElement | null) => {\n internal.current = node;\n if (typeof forwarded === \"function\") forwarded(node);\n else if (forwarded) forwarded.current = node;\n },\n [forwarded],\n );\n return { ref: internal, callback };\n}\n\nexport function boxStyle(\n minHeight?: number,\n maxHeight?: number,\n): React.CSSProperties | undefined {\n if (minHeight === undefined && maxHeight === undefined) return undefined;\n return {\n minHeight: minHeight ? `${minHeight}px` : undefined,\n maxHeight: maxHeight ? `${maxHeight}px` : undefined,\n };\n}\n\n/** The elevated textarea — the Input family's `Input`, in multi-line form. */\nconst Textarea = React.forwardRef<HTMLTextAreaElement, TextareaProps>(\n (\n { className, autoGrow, minHeight, maxHeight, wrapperClassName, ...props },\n forwarded,\n ) => {\n const { ref, callback } = useMergedTextareaRef(forwarded);\n const stretchClasses = getStretchClasses(className);\n const needsWrapper = Boolean(wrapperClassName || stretchClasses);\n\n useAutoGrow(ref, props.value, autoGrow, minHeight, maxHeight);\n\n const textarea = (\n <textarea\n ref={callback}\n data-slot=\"textarea\"\n className={cn(\n TEXTAREA_ELEVATED_CLASS,\n autoGrow && \"resize-none\",\n stretchClasses,\n className,\n )}\n style={boxStyle(minHeight, maxHeight)}\n {...props}\n />\n );\n\n if (!needsWrapper) return textarea;\n\n return <div className={cn(stretchClasses, wrapperClassName)}>{textarea}</div>;\n },\n);\nTextarea.displayName = \"Textarea\";\n\n/**\n * The plain control — a bordered, transparent field with a 60px floor. This is\n * what matrx-extend, aidream/apps/dashboard and workflow-studio each called\n * `Textarea`; the floor is theirs and it is the sensible default (a one-line\n * box for multi-line content invites a scrollbar on the first Enter).\n */\nconst BasicTextarea = React.forwardRef<HTMLTextAreaElement, TextareaProps>(\n ({ className, autoGrow, minHeight, maxHeight, ...props }, forwarded) => {\n const { ref, callback } = useMergedTextareaRef(forwarded);\n\n useAutoGrow(ref, props.value, autoGrow, minHeight, maxHeight);\n\n return (\n <textarea\n ref={callback}\n data-slot=\"textarea\"\n className={cn(\n TEXTAREA_CONTROL_CLASS,\n \"h-auto min-h-[60px]\",\n autoGrow && \"resize-none\",\n className,\n )}\n style={boxStyle(minHeight, maxHeight)}\n {...props}\n />\n );\n },\n);\nBasicTextarea.displayName = \"BasicTextarea\";\n\nexport interface TextareaWithPrefixProps extends Omit<TextareaProps, \"prefix\"> {\n /** Leading adornment, absolutely placed at the field's top-left. */\n prefix?: React.ReactNode;\n}\n\nconst TextareaWithPrefix = React.forwardRef<\n HTMLTextAreaElement,\n TextareaWithPrefixProps\n>(\n (\n {\n prefix,\n className,\n wrapperClassName,\n autoGrow,\n minHeight,\n maxHeight,\n ...props\n },\n forwarded,\n ) => {\n const { ref, callback } = useMergedTextareaRef(forwarded);\n\n useAutoGrow(ref, props.value, autoGrow, minHeight, maxHeight);\n\n return (\n <div\n className={cn(\"relative\", getStretchClasses(className), wrapperClassName)}\n >\n {prefix ? (\n <div className=\"pointer-events-none absolute left-3 top-3 z-10 text-muted-foreground\">\n {prefix}\n </div>\n ) : null}\n <textarea\n ref={callback}\n data-slot=\"textarea\"\n className={cn(\n TEXTAREA_CONTROL_CLASS,\n \"resize-y\",\n prefix && \"pl-10\",\n autoGrow && \"resize-none\",\n className,\n )}\n style={boxStyle(minHeight, maxHeight)}\n {...props}\n />\n </div>\n );\n },\n);\nTextareaWithPrefix.displayName = \"TextareaWithPrefix\";\n\nexport { BasicTextarea, Textarea, TextareaWithPrefix };\n","\"use client\";\n\n/**\n * The field-owned voice chrome every writing field shares: the live \"Listening…\" strip, the\n * \"Finalizing…\" strip and the close-protection dialog. The recorder itself is the host's\n * (`useVoice` port); these only draw its state.\n */\nimport * as React from \"react\";\nimport { cn } from \"../cn\";\nimport { Tile } from \"../controls/surfaces\";\nimport { CheckIcon, Loader2Icon } from \"../icons\";\nimport {\n AlertDialog,\n AlertDialogAction,\n AlertDialogCancel,\n AlertDialogContent,\n AlertDialogDescription,\n AlertDialogFooter,\n AlertDialogHeader,\n AlertDialogTitle,\n} from \"../alert-dialog\";\nimport type { WritingFieldVoice } from \"./add-ons\";\n\nexport function ListeningStrip({ liveTranscript, className }: { liveTranscript: string; className?: string }) {\n return (\n <div className={cn(\"absolute flex items-center gap-1.5 px-2 py-1 rounded-md\", className)}>\n <span aria-hidden className=\"w-2 h-2 bg-primary rounded-full flex-shrink-0 animate-pulse\" />\n <span className=\"type-secondary text-primary font-medium truncate\">\n {liveTranscript ? liveTranscript.slice(-60) : \"Listening...\"}\n </span>\n </div>\n );\n}\n\nexport function FinalizingStrip({ className }: { className?: string }) {\n return (\n <div\n className={cn(\n \"absolute flex items-center gap-1.5 px-2 py-1 rounded-md bg-blue-100 dark:bg-blue-900/30\",\n className,\n )}\n >\n <Loader2Icon className=\"w-3 h-3 animate-spin text-blue-600 dark:text-blue-400\" />\n <span className=\"type-secondary text-blue-600 dark:text-blue-400 font-medium\">Finalizing...</span>\n </div>\n );\n}\n\n/** Warns before a field closes while a recording or transcription is in flight. */\nexport function VoiceProtectionDialog({ voice }: { voice: WritingFieldVoice }) {\n const { isRecording, isTranscribing } = voice;\n const busy = isRecording || isTranscribing;\n return (\n <AlertDialog open={voice.showProtectionDialog} onOpenChange={voice.setShowProtectionDialog}>\n <AlertDialogContent>\n <AlertDialogHeader>\n <div className=\"flex items-center gap-3 mb-2\">\n {busy ? (\n <>\n <Loader2Icon className=\"h-5 w-5 animate-spin text-blue-500\" />\n <AlertDialogTitle>\n {isRecording ? \"Recording in Progress\" : \"Transcription in Progress\"}\n </AlertDialogTitle>\n </>\n ) : (\n <>\n <CheckIcon className=\"h-5 w-5 text-green-500\" />\n <AlertDialogTitle>Voice Input Complete</AlertDialogTitle>\n </>\n )}\n </div>\n <AlertDialogDescription>\n {isRecording\n ? \"Your voice is currently being recorded. If you close now, the recording will be stopped and lost.\"\n : isTranscribing\n ? \"Your voice recording is currently being transcribed. If you close now, the transcription will be lost.\"\n : \"Your voice input has been processed successfully! You can now safely close this panel.\"}\n </AlertDialogDescription>\n </AlertDialogHeader>\n <AlertDialogFooter>\n {busy ? (\n <>\n <AlertDialogCancel onClick={voice.cancelClose}>Cancel & Wait</AlertDialogCancel>\n <AlertDialogAction\n onClick={voice.confirmClose}\n className=\"bg-destructive text-destructive-foreground hover:bg-destructive/90\"\n >\n {isRecording ? \"Stop Recording\" : \"End Transcription\"}\n </AlertDialogAction>\n </>\n ) : (\n <AlertDialogAction onClick={voice.confirmClose}>Close</AlertDialogAction>\n )}\n </AlertDialogFooter>\n </AlertDialogContent>\n </AlertDialog>\n );\n}\n\n/** A menu row in the field's own part of \"…\" (Expand, Voice input, Audio settings, Clear). */\nexport function FieldMenuRow({\n icon,\n children,\n onClick,\n disabled,\n}: {\n icon: React.ReactNode;\n children: React.ReactNode;\n onClick: () => void;\n disabled?: boolean;\n}) {\n return (\n <Tile\n type=\"button\"\n disabled={disabled}\n onClick={onClick}\n variant=\"quiet\"\n className=\"w-full\"\n icon={icon}\n title={children}\n />\n );\n}\n\n/** The mic button a host without a voice port would get — never drawn: no port, no microphone. */\nexport function micAriaLabel(isRecording: boolean, label?: string): string {\n if (isRecording) return label ? `Stop recording for ${label}` : \"Stop recording\";\n return label ? `Start voice input for ${label}` : \"Start voice input\";\n}\n","\"use client\";\n\n/**\n * ProInput — THE one-line box a person writes words in (titles, names, short replies). Moved from\n * matrx-frontend `components/official/ProInput.tsx` (2026-10-22); its recorder, read-aloud, Copy\n * and Clean up arrive through the add-on ports (`./add-ons.tsx`).\n *\n * Built in: submit (`onSubmit`, ⌘/Ctrl+Enter, `submitOnEnter`), field navigation (`onEnterKey`),\n * Clear (`clearable` + `onClear`), `startIcon`, the iOS zoom guard (value text 16px), floating\n * label, the ONE fitting rule (`./control-fit.ts`), and the measured right padding that keeps the\n * hover cluster off the text (`./reserved-padding.ts`; a narrow field reveals it on focus).\n */\nimport * as React from \"react\";\nimport { useMediaQuery } from \"@ai-matrx/kit/media-query\";\nimport { cn } from \"../cn\";\nimport { Label } from \"../label\";\nimport { Field } from \"../controls/controls\";\nimport { Popover, PopoverContent, PopoverTrigger } from \"../popover\";\nimport {\n CheckTapButton,\n LoadingTapButton,\n MoreHorizontalTapButton,\n SendTapButton,\n XTapButton,\n} from \"../tap-target/tap-buttons\";\nimport { MicIcon, SlidersHorizontalIcon, XIcon } from \"../icons\";\nimport { UNCONFIGURED } from \"../stand-in-notice\";\nimport { PRO_INPUT_TEXT_GAP_PX, hoverRevealsCluster, reservedRightPaddingPx } from \"./reserved-padding\";\nimport { controlSizes, fitFieldControls, isDenseField } from \"./control-fit\";\nimport { resolveHookPorts, splitAddOnProps, useWritingFieldAddOns, type WritingFieldApi } from \"./add-ons\";\nimport { FieldMenuRow, FinalizingStrip, VoiceProtectionDialog, micAriaLabel } from \"./voice-chrome\";\nimport { StandInMenu } from \"./pro-textarea\";\nimport type { ProInputAddOnProps } from \"./index\";\n\n/** Real HTMLInputElement with optional expando methods set by ProInput. */\nexport interface ProInputElement extends HTMLInputElement {\n requestClose?: () => void;\n isTranscribing?: () => boolean;\n}\n\nexport interface ProInputProps extends React.InputHTMLAttributes<HTMLInputElement>, ProInputAddOnProps {\n onTranscriptionComplete?: (text: string) => void;\n onTranscriptionError?: (error: string) => void;\n /** If true, appends to existing text; if false, replaces. Default: true. */\n appendTranscript?: boolean;\n wrapperClassName?: string;\n onRequestClose?: () => void;\n /** Warn before unmount during recording/transcription. Default: true. */\n protectTranscription?: boolean;\n /** Show the Copy action inside the \"…\" menu. Default: true. */\n showCopyButton?: boolean;\n /** Voice input. Default true; false for search bars and filters. */\n enableVoice?: boolean;\n onSubmit?: () => void;\n submitDisabled?: boolean;\n isSubmitting?: boolean;\n /** Accessible/tooltip label for the submit button. Default: \"Send\". */\n submitLabel?: string;\n submitOnCmdEnter?: boolean;\n submitOnEnter?: boolean;\n /** Field-navigation mode: plain Enter calls this instead of submitting. */\n onEnterKey?: (e: React.KeyboardEvent<HTMLInputElement>) => void;\n auxiliaryControlsTabIndex?: number;\n auxiliaryControlsLabel?: string;\n /** Optional leading icon/node — auto-applies left padding. */\n startIcon?: React.ReactNode;\n /** Shows a clear (×) control while the field has content. */\n clearable?: boolean;\n /** Called when the clear control is pressed. Defaults to clearing via `onChange`. */\n onClear?: () => void;\n /** Dense-form label inside the border (use only on a `bg-card` surface). */\n floatingLabel?: string;\n}\n\nconst joinWithSpace = (base: string, text: string) => `${base}${base.endsWith(\" \") ? \"\" : \" \"}${text}`;\n\nexport const ProInput = React.forwardRef<HTMLInputElement, ProInputProps>(\n (\n {\n className,\n wrapperClassName,\n onTranscriptionComplete,\n onTranscriptionError,\n appendTranscript = true,\n value,\n onChange,\n onKeyDown,\n disabled,\n onRequestClose,\n protectTranscription = true,\n showCopyButton = true,\n enableVoice = true,\n onSubmit,\n submitDisabled,\n isSubmitting = false,\n submitLabel = \"Send\",\n submitOnCmdEnter,\n submitOnEnter = false,\n onEnterKey,\n auxiliaryControlsTabIndex,\n auxiliaryControlsLabel,\n startIcon,\n clearable = false,\n onClear,\n floatingLabel,\n id: idProp,\n placeholder,\n type = \"text\",\n ...rest\n },\n ref,\n ) => {\n const addOns = useWritingFieldAddOns();\n const ports = resolveHookPorts(addOns);\n const { dom: props, addOnProps } = splitAddOnProps(rest as Record<string, unknown>, addOns.propNames) as {\n dom: React.InputHTMLAttributes<HTMLInputElement>;\n addOnProps: Record<string, unknown>;\n };\n const generatedId = React.useId();\n // Field owns its geometry; the legacy native size attribute must not become a skin.\n const { size: _nativeSize, width: nativeWidth, style: nativeStyle, ...fieldProps } = props;\n const inputId = idProp ?? (floatingLabel ? generatedId : undefined);\n const [hasCopied, setHasCopied] = React.useState(false);\n const [menuOpen, setMenuOpen] = React.useState(false);\n const [isFocused, setIsFocused] = React.useState(false);\n const [isHovered, setIsHovered] = React.useState(false);\n const internalRef = React.useRef<HTMLInputElement | null>(null);\n const clusterRef = React.useRef<HTMLDivElement | null>(null);\n const auxRef = React.useRef<HTMLDivElement>(null);\n const [clusterWidths, setClusterWidths] = React.useState({ cluster: 0, aux: 0 });\n const [inputWidth, setInputWidth] = React.useState(0);\n const [inputHeight, setInputHeight] = React.useState(0);\n const coarsePointer = useMediaQuery(\"(pointer: coarse)\");\n const clusterObserver = React.useRef<ResizeObserver | null>(null);\n // Stable, so React re-runs it only when the node changes (a new function each render re-measured in\n // every commit, which loops when the measured size moves with the field's own controls).\n const setClusterNode = React.useCallback((cluster: HTMLDivElement | null) => {\n if (clusterRef.current === cluster) return;\n clusterRef.current = cluster;\n clusterObserver.current?.disconnect();\n clusterObserver.current = null;\n if (!cluster || typeof ResizeObserver === \"undefined\") return;\n const measure = () => {\n const next = {\n cluster: cluster.getBoundingClientRect().width,\n aux: auxRef.current?.getBoundingClientRect().width ?? 0,\n };\n setClusterWidths((prev) => (prev.cluster === next.cluster && prev.aux === next.aux ? prev : next));\n };\n measure();\n clusterObserver.current = new ResizeObserver(measure);\n clusterObserver.current.observe(cluster);\n if (auxRef.current) clusterObserver.current.observe(auxRef.current);\n }, []);\n const inputRef = internalRef;\n const inputObserver = React.useRef<ResizeObserver | null>(null);\n // A merged CALLBACK ref: the host gets the element AND the field still measures that element.\n // Stable, so React re-runs it only when the node changes (a new function each render re-measured in\n // every commit, which loops when the measured size moves with the field's own controls).\n const setInputRef = React.useCallback((node: HTMLInputElement | null) => {\n if (internalRef.current !== node) {\n inputObserver.current?.disconnect();\n inputObserver.current = null;\n if (node && typeof ResizeObserver !== \"undefined\") {\n const measure = () => {\n const rect = node.getBoundingClientRect();\n setInputWidth(rect.width);\n setInputHeight(rect.height);\n };\n measure();\n inputObserver.current = new ResizeObserver(measure);\n inputObserver.current.observe(node);\n }\n }\n internalRef.current = node;\n if (typeof ref === \"function\") ref(node);\n else if (ref) (ref as React.MutableRefObject<HTMLInputElement | null>).current = node;\n }, [ref]);\n // THE PRE-HYDRATION KEEP (see ProTextarea).\n const keepPreHydrationText = React.useEffectEvent(() => {\n const el = inputRef.current;\n if (!el || !onChange) return;\n const typed = el.value;\n if (!typed || typed === String(value ?? \"\")) return;\n el.value = \"\";\n Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype, \"value\")?.set?.call(el, typed);\n el.dispatchEvent(new Event(\"input\", { bubbles: true }));\n });\n React.useLayoutEffect(() => {\n keepPreHydrationText();\n }, []);\n React.useEffect(\n () => () => {\n clusterObserver.current?.disconnect();\n inputObserver.current?.disconnect();\n },\n [],\n );\n const openAudioSettings = ports.useOpenAudioSettings();\n\n const pushToInput = React.useCallback((newValue: string): boolean => {\n const el = inputRef.current;\n if (!el) return false;\n const setter = Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype, \"value\")?.set;\n if (!setter) return false;\n setter.call(el, newValue);\n el.dispatchEvent(new Event(\"input\", { bubbles: true }));\n return el.value === newValue;\n }, []);\n\n const getLiveText = React.useCallback(() => inputRef.current?.value ?? String(value ?? \"\"), [value]);\n const voice = ports.useVoice({\n enabled: enableVoice,\n instanceId: inputId,\n getValue: getLiveText,\n writeValue: pushToInput,\n appendTranscript,\n join: joinWithSpace,\n protect: protectTranscription,\n onRequestClose,\n onTranscriptionComplete,\n onTranscriptionError,\n });\n const { isRecording, isTranscribing } = voice;\n const isAudioAvailable = voice.microphone;\n\n React.useEffect(() => {\n const el = inputRef.current as ProInputElement | null;\n if (!el) return;\n el.requestClose = voice.requestClose;\n el.isTranscribing = () => isTranscribing;\n }, [voice.requestClose, isTranscribing]);\n\n const flashCopied = React.useCallback(() => {\n setHasCopied(true);\n setTimeout(() => setHasCopied(false), 450);\n }, []);\n\n const handleClear = React.useCallback(() => {\n if (onClear) {\n onClear();\n return;\n }\n pushToInput(\"\");\n onChange?.({ target: { value: \"\" } } as React.ChangeEvent<HTMLInputElement>);\n }, [onClear, pushToInput, onChange]);\n\n const valueAsString = String(value ?? \"\");\n const hasContent = valueAsString.trim().length > 0;\n const canSubmit = !!onSubmit && hasContent && !submitDisabled && !isSubmitting && !disabled;\n const cmdEnterEnabled = submitOnCmdEnter ?? !!onSubmit;\n const triggerSubmit = React.useCallback(() => {\n if (canSubmit && onSubmit) onSubmit();\n }, [canSubmit, onSubmit]);\n\n const handleKeyDown = React.useCallback(\n (e: React.KeyboardEvent<HTMLInputElement>) => {\n if (isHovered) setIsHovered(false);\n onKeyDown?.(e);\n if (e.defaultPrevented || e.key !== \"Enter\") return;\n const withCmd = e.metaKey || e.ctrlKey;\n if (onEnterKey) {\n if (e.shiftKey || withCmd) return;\n e.preventDefault();\n onEnterKey(e);\n return;\n }\n if (!onSubmit) return;\n if (cmdEnterEnabled && withCmd) {\n e.preventDefault();\n triggerSubmit();\n return;\n }\n if (submitOnEnter && !e.shiftKey && !withCmd) {\n e.preventDefault();\n triggerSubmit();\n }\n },\n [isHovered, onKeyDown, onEnterKey, onSubmit, cmdEnterEnabled, submitOnEnter, triggerSubmit],\n );\n\n const fieldApi: WritingFieldApi = {\n kind: \"input\",\n text: valueAsString,\n getText: getLiveText,\n write: pushToInput,\n getSelection: () => ({\n start: inputRef.current?.selectionStart ?? 0,\n end: inputRef.current?.selectionEnd ?? 0,\n }),\n getElement: () => inputRef.current,\n addOnProps: { ...addOnProps, type },\n showCopyButton,\n flashCopied,\n };\n\n const pointerReveals = hoverRevealsCluster(inputWidth) ? isHovered : isFocused;\n const showHoverControls = (pointerReveals || isRecording || isTranscribing) && !disabled;\n const isVoiceDisabled = !isAudioAvailable || disabled || (isTranscribing && !isRecording);\n const showMic = enableVoice && isAudioAvailable;\n const showClear = clearable && hasContent;\n const addOnMenuItems = addOns.Menu\n ? (addOns.menuHasItems?.({ kind: \"input\", addOnProps: fieldApi.addOnProps, showCopyButton }) ?? true)\n : false;\n const denseField = isDenseField(inputHeight);\n const fit = fitFieldControls({\n fieldWidth: inputWidth,\n sizes: controlSizes({ coarse: coarsePointer, dense: denseField }),\n fixedPx: (startIcon ? 36 : 12) + PRO_INPUT_TEXT_GAP_PX,\n hasSubmit: !!onSubmit,\n menuHasOwnItems: !disabled && (showCopyButton || addOnMenuItems || hasContent),\n mic: showMic,\n clear: showClear,\n expand: false,\n });\n const voiceBusy = isRecording || isTranscribing;\n const showMicInline = showMic && (fit.mic === \"inline\" || voiceBusy);\n const voiceInMenu = showMic && !showMicInline;\n const clearInline = showClear && fit.clearInline;\n const clearInMenu = showClear && !fit.clearInline;\n const showMenu = !disabled && (showCopyButton || addOnMenuItems || voiceInMenu || clearInMenu || hasContent);\n const audioSettingsInMenu = showMenu && enableVoice;\n const auxVisible = (showHoverControls || menuOpen) && (showMicInline || showMenu);\n const measuredRightPadding = reservedRightPaddingPx({\n clusterWidth: clusterWidths.cluster,\n auxWidth: clusterWidths.aux,\n auxVisible,\n });\n const isInvalid = props[\"aria-invalid\"] === true || props[\"aria-invalid\"] === \"true\";\n const labelFloated = isFocused || valueAsString.length > 0;\n const showVoiceStatus = isRecording || (isTranscribing && !isRecording);\n const closeMenu = () => setMenuOpen(false);\n\n const ownRows = (\n <>\n {clearInMenu ? (\n <FieldMenuRow\n icon={<XIcon />}\n onClick={() => {\n closeMenu();\n handleClear();\n }}\n >\n Clear\n </FieldMenuRow>\n ) : null}\n {voiceInMenu ? (\n <FieldMenuRow\n icon={<MicIcon />}\n disabled={isVoiceDisabled}\n onClick={() => {\n closeMenu();\n void voice.handleVoiceClick();\n }}\n >\n Voice input\n </FieldMenuRow>\n ) : null}\n {audioSettingsInMenu ? (\n <FieldMenuRow\n icon={<SlidersHorizontalIcon />}\n onClick={() => {\n closeMenu();\n openAudioSettings();\n }}\n >\n Audio settings\n </FieldMenuRow>\n ) : null}\n {clearInMenu || voiceInMenu || audioSettingsInMenu ? (\n <div className=\"my-1 h-px bg-border\" role=\"separator\" />\n ) : null}\n </>\n );\n const Menu = addOns.Menu;\n\n return (\n <div\n className={cn(\"relative group\", wrapperClassName)}\n data-writing-field-host={addOns.Menu && addOns.useVoice ? undefined : UNCONFIGURED}\n onMouseEnter={() => setIsHovered(true)}\n onMouseMove={() => {\n if (!isHovered) setIsHovered(true);\n }}\n onMouseLeave={() => setIsHovered(false)}\n >\n <Field\n ref={setInputRef}\n id={inputId}\n type={type}\n placeholder={floatingLabel ? undefined : placeholder}\n className={cn(\"w-full\", className)}\n style={{ ...(nativeWidth === undefined ? {} : { width: nativeWidth }), ...nativeStyle }}\n icon={startIcon}\n end={<span aria-hidden=\"true\" style={{ width: measuredRightPadding === null ? `calc(${Number(!!onSubmit) + Number(clearInline)} * (var(--matrx-tap-pill-size) + var(--matrx-tap-gap)))` : Math.max(0, measuredRightPadding - 12), flexShrink: 0 }} />}\n value={value}\n onChange={onChange}\n onFocus={() => setIsFocused(true)}\n onBlur={() => setIsFocused(false)}\n onKeyDown={handleKeyDown}\n disabled={disabled}\n {...fieldProps}\n />\n {floatingLabel && inputId && (\n <Label\n htmlFor={inputId}\n className={cn(\n \"absolute left-3 px-1 pointer-events-none transition-all duration-200 ease-in-out z-10 bg-card\",\n labelFloated ? \"-top-2 text-xs\" : \"top-2 text-sm\",\n isInvalid ? \"text-destructive\" : isFocused ? \"text-primary\" : \"text-muted-foreground\",\n disabled && \"text-disabled-foreground\",\n )}\n >\n {floatingLabel}\n </Label>\n )}\n {/* A GLASS PLANE (tap-target placement rule 1); a press here never takes focus from the field. */}\n <div\n ref={setClusterNode}\n onMouseDown={(e) => e.preventDefault()}\n data-matrx-glass-plane\n data-matrx-tap-dense={denseField ? \"\" : undefined}\n className=\"absolute right-0 top-1/2 -translate-y-1/2 flex items-center z-10\"\n >\n <div\n ref={auxRef}\n className={cn(\n \"flex items-center transition-opacity duration-200\",\n showHoverControls || menuOpen ? \"opacity-100\" : \"opacity-0 pointer-events-none\",\n )}\n >\n {showMicInline && addOns.MicButton ? (\n <addOns.MicButton\n dense={denseField}\n tabIndex={auxiliaryControlsTabIndex}\n onMicClick={() => void voice.handleVoiceClick()}\n disabled={isVoiceDisabled}\n isRecording={isRecording}\n isTranscribing={isTranscribing}\n audioLevel={voice.audioLevel}\n micAriaLabel={micAriaLabel(isRecording, auxiliaryControlsLabel)}\n />\n ) : null}\n {showMenu && (\n <Popover open={menuOpen} onOpenChange={setMenuOpen}>\n <PopoverTrigger asChild>\n {hasCopied ? (\n <CheckTapButton\n tabIndex={auxiliaryControlsTabIndex}\n variant=\"transparent\"\n ariaLabel={auxiliaryControlsLabel ? `Copied ${auxiliaryControlsLabel}` : \"Copied\"}\n tooltip=\"Copied\"\n className=\"text-green-500\"\n />\n ) : (\n <MoreHorizontalTapButton\n tabIndex={auxiliaryControlsTabIndex}\n variant=\"transparent\"\n ariaLabel={auxiliaryControlsLabel ? `More options for ${auxiliaryControlsLabel}` : \"More options\"}\n tooltip=\"More\"\n className=\"text-muted-foreground\"\n />\n )}\n </PopoverTrigger>\n <PopoverContent\n /* sizing: fixed — the add-on body sizes itself (short list vs. cleanup panel) */\n align=\"end\"\n side=\"bottom\"\n sideOffset={6}\n className=\"w-auto max-w-none p-0\"\n onOpenAutoFocus={(e) => e.preventDefault()}\n >\n {Menu ? (\n <Menu field={fieldApi} ownRows={ownRows} trailingRows={null} close={closeMenu} />\n ) : (\n <StandInMenu field={fieldApi} ownRows={ownRows} trailingRows={null} close={closeMenu} registry />\n )}\n </PopoverContent>\n </Popover>\n )}\n </div>\n {clearInline && (\n <XTapButton\n variant=\"transparent\"\n onClick={handleClear}\n ariaLabel=\"Clear\"\n tooltip=\"Clear\"\n className=\"text-muted-foreground\"\n />\n )}\n {onSubmit &&\n (isSubmitting ? (\n <LoadingTapButton variant=\"transparent\" ariaLabel={submitLabel} tooltip={submitLabel} className=\"text-primary\" />\n ) : (\n <SendTapButton\n variant=\"transparent\"\n onClick={triggerSubmit}\n disabled={!canSubmit}\n ariaLabel={submitLabel}\n tooltip={submitLabel}\n className={canSubmit ? \"text-primary\" : \"text-muted-foreground\"}\n />\n ))}\n </div>\n {showVoiceStatus && (\n <div className=\"absolute left-0 top-full mt-1 flex items-center gap-1.5 px-2 py-1 rounded-md max-w-full\">\n {isRecording ? (\n <div className=\"relative flex items-center gap-1.5 px-2 py-1 bg-primary/10 dark:bg-primary/15 rounded-md max-w-full\">\n <span aria-hidden className=\"w-2 h-2 bg-primary rounded-full flex-shrink-0 animate-pulse\" />\n <span className=\"type-secondary text-primary font-medium truncate\">\n {voice.liveTranscript ? voice.liveTranscript.slice(-60) : \"Listening...\"}\n </span>\n </div>\n ) : (\n <FinalizingStrip className=\"relative\" />\n )}\n </div>\n )}\n {voice.dialogs}\n <VoiceProtectionDialog voice={voice} />\n </div>\n );\n },\n);\n\nProInput.displayName = \"ProInput\";\n","/**\n * THE TOOLBAR NEVER COVERS TEXT (page-pass 2026-09-27, /chat/message-templates/<id> at 375px).\n *\n * ProInput's mic + \"…\" cluster fades in over the right end of the field. On a\n * phone a tap counts as a hover and stays one, so the cluster sat on top of the\n * text being typed and clipped it. The fix is to reserve exactly the width the\n * visible right-hand controls take — measured, never guessed — as the input's\n * right padding:\n *\n * - the whole cluster while the mic / \"…\" part is showing;\n * - only the always-visible part (clear, submit) while it is faded out — the\n * faded part still takes layout width, so it is subtracted, not ignored.\n *\n * `null` means \"nothing measured yet\" (first paint, jsdom): the caller keeps its\n * class-based fallback padding.\n */\nexport const PRO_INPUT_TEXT_GAP_PX = 4;\nexport const PRO_INPUT_MIN_RIGHT_PADDING_PX = 12;\n\nexport function reservedRightPaddingPx({\n clusterWidth,\n auxWidth,\n auxVisible,\n}: {\n clusterWidth: number;\n auxWidth: number;\n auxVisible: boolean;\n}): number | null {\n if (!(clusterWidth > 0)) return null;\n const visible = auxVisible\n ? clusterWidth\n : Math.max(0, clusterWidth - Math.max(0, auxWidth));\n if (visible <= 0) return PRO_INPUT_MIN_RIGHT_PADDING_PX;\n return Math.max(\n PRO_INPUT_MIN_RIGHT_PADDING_PX,\n Math.ceil(visible) + PRO_INPUT_TEXT_GAP_PX,\n );\n}\n\n/**\n * A NARROW FIELD NEVER LETS A HOVER STEAL ITS CLICK.\n *\n * The mic + \"…\" cluster fades in on pointer hover over the right end of the\n * field. In a field only a couple of hundred px wide (a board tile's task-add\n * row, a sidebar) the cluster and its reserved padding leave a sliver of text,\n * and a press aimed at the middle of the field lands ON the mic: no focus, no\n * typing. Below this width the cluster appears on FOCUS instead of hover, so\n * the first press always focuses the field.\n */\nexport const PRO_INPUT_NARROW_FIELD_PX = 260;\n\nexport function hoverRevealsCluster(inputWidth: number): boolean {\n return !(inputWidth > 0 && inputWidth < PRO_INPUT_NARROW_FIELD_PX);\n}\n\n// What fits beside the text — and what moves inside \"…\" — is decided by THE\n// ONE FITTING RULE shared with ProTextarea: `proFieldControlFit.ts`.\n"],"mappings":"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","names":["React","import_media_query","DialogPrimitive","React","React","import_jsx_runtime","import_jsx_runtime","React","import_jsx_runtime","React","import_jsx_runtime","CONTEXT_SLOT","React","import_jsx_runtime","CONTEXT_SLOT","contextRegistry","swallowClick","React","import_jsx_runtime","registry","import_jsx_runtime","CONTEXT_SLOT","contextRegistry","React","import_jsx_runtime","import_react","React","import_jsx_runtime","import_react","import_react","import_jsx_runtime","import_react","import_jsx_runtime","import_jsx_runtime","tooltipSide","TapTargetButton","TapTargetButtonTransparent","TapTargetButtonOutline","TapTargetButtonSolid","TapTargetButtonDestructive","TapTargetButtonForGroup","import_react","import_react","import_jsx_runtime","SLOT","import_jsx_runtime","Wrap","React","import_jsx_runtime","registry","import_react_slot","React","import_react_slot","React","import_jsx_runtime","import_react_tree","React","import_jsx_runtime","import_react_slot","React","React","import_jsx_runtime","import_jsx_runtime","Button","Textarea","import_jsx_runtime","Button","import_jsx_runtime","import_jsx_runtime","FILL_HEIGHT_REGEX","field","Textarea","registry","React","import_media_query","visible","import_jsx_runtime"]}
1
+ {"version":3,"sources":["../src/writing-field/index.ts","../src/writing-field/pro-textarea.tsx","../src/cn.ts","../src/label.tsx","../src/dialog.tsx","../src/motion.ts","../src/close-slot.tsx","../src/icons.tsx","../src/portal-container.tsx","../src/look.tsx","../src/radix-dialog-modal-context.tsx","../src/use-is-mobile.ts","../src/layer-front.ts","../src/window-drag.ts","../src/drag-cursor.ts","../src/floating-layer.tsx","../src/title-tooltips.ts","../src/focus-return.ts","../src/popover.tsx","../src/solid-surface.ts","../src/tap-target/tap-target-button.tsx","../src/tooltip.tsx","../src/tap-target/tap-target-guard.ts","../src/layout-scale.ts","../src/tap-target/tap-surface.tsx","../src/tap-target/tap-features.tsx","../src/tap-shortcut.ts","../src/tap-target/link.ts","../src/tap-target/tap-buttons.tsx","../src/tap-target/tap-default-variant.tsx","../src/stand-in-notice.ts","../src/writing-field/control-fit.ts","../src/writing-field/control-placement.ts","../src/writing-field/add-ons.tsx","../src/controls/surfaces.tsx","../src/button.tsx","../src/alert-dialog.tsx","../src/controls/controls.tsx","../src/field-surface.ts","../src/textarea.tsx","../src/writing-field/voice-chrome.tsx","../src/writing-field/pro-input.tsx","../src/writing-field/reserved-padding.ts"],"sourcesContent":["\"use client\";\n\n/**\n * @ai-matrx/design-system/writing-field — THE writing field (one-ui-system rule 6): `ProTextarea`\n * and `ProInput`, plus the add-on ports a host registers once at its root\n * (`WritingFieldAddOnsProvider`). Moved from matrx-frontend `components/official/` (2026-10-22).\n *\n * The add-on props (`surfaceName`, `getApplicationScope`, `cleanupContextItems`, …) are typed by the\n * add-ons' owner through module augmentation, so this package never imports their types:\n *\n * declare module \"@ai-matrx/design-system/writing-field\" {\n * interface ProTextareaAddOnProps { surfaceName?: string; … }\n * }\n */\n\n/** Props a ProTextarea's add-ons read; the add-ons' owner augments this interface. */\n// eslint-disable-next-line @typescript-eslint/no-empty-object-type\nexport interface ProTextareaAddOnProps {}\n\n/** Props a ProInput's add-ons read; the add-ons' owner augments this interface. */\n// eslint-disable-next-line @typescript-eslint/no-empty-object-type\nexport interface ProInputAddOnProps {}\n\nexport {\n ProTextarea,\n StandInMenu,\n type DictationRefusalReason,\n type DictationStartResult,\n type ProTextareaElement,\n type ProTextareaProps,\n} from \"./pro-textarea\";\nexport { ProInput, type ProInputElement, type ProInputProps } from \"./pro-input\";\nexport {\n ADD_ON_PROP_NAMES,\n WritingFieldAddOnsProvider,\n announceMissingPort,\n splitAddOnProps,\n useWritingFieldAddOns,\n type WritingFieldAddOns,\n type WritingFieldApi,\n type WritingFieldContextMenuProps,\n type WritingFieldMenuProps,\n type WritingFieldMicButtonProps,\n type WritingFieldNotify,\n type WritingFieldTextStats,\n type WritingFieldVoice,\n type WritingFieldVoiceOptions,\n} from \"./add-ons\";\nexport { FieldMenuRow, VoiceProtectionDialog, micAriaLabel } from \"./voice-chrome\";\nexport * from \"./control-fit\";\nexport * from \"./control-placement\";\nexport * from \"./reserved-padding\";\nexport type * from \"./editor-slot\";\n","\"use client\";\n\n/**\n * ProTextarea — THE box a person writes words in (one-ui-system rule 6). Moved from\n * matrx-frontend `components/official/ProTextarea.tsx` (2026-10-22): the field core lives here; the\n * recorder, the \"…\" actions, the page's agents, the right-click menu, markdown formatting and text\n * stats arrive through the add-on ports (`./add-ons.tsx`), registered once at the host root.\n *\n * Built in: auto-grow (`autoGrow` + `minHeight`/`maxHeight`), floating label, `hero` appearance,\n * the reserved control row or the `inline` composer shape (`controls`), the ONE fitting rule\n * (`./control-fit.ts`: whatever does not fit beside the text folds into \"…\", never deleted), submit\n * (`onSubmit`, ⌘/Ctrl+Enter, `submitOnEnter`, the one composer rule from `@ai-matrx/kit/composer-keys`),\n * field navigation (`onEnterKey`), a `leading` slot, Expand (`expandable`), a hosted editor\n * (`editor`, `./editor-slot.ts`), the pre-hydration keep, and the dictation handle: the forwarded\n * node is a real `HTMLTextAreaElement` carrying `startDictation()` / `stopDictation()` /\n * `isDictating()` / `requestClose()` / `isTranscribing()`; a refusal always returns a named reason\n * with a sentence AND says it on screen (notify + `onTranscriptionError`).\n */\nimport * as React from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { composerKeyIntent, intentTakesTheKey } from \"@ai-matrx/kit/composer-keys\";\nimport { useMediaQuery } from \"@ai-matrx/kit/media-query\";\nimport { copyText } from \"@ai-matrx/kit/clipboard\";\nimport { cn } from \"../cn\";\nimport { Label } from \"../label\";\nimport { Dialog, DialogContent, DialogTitle } from \"../dialog\";\nimport { Popover, PopoverContent, PopoverTrigger } from \"../popover\";\nimport { TapTargetButtonSolid } from \"../tap-target/tap-target-button\";\nimport { MaximizeTapButton, MoreHorizontalTapButton } from \"../tap-target/tap-buttons\";\nimport { CopyIcon, Loader2Icon, Maximize2Icon, MicIcon, SendIcon, SlidersHorizontalIcon } from \"../icons\";\nimport { UNCONFIGURED } from \"../stand-in-notice\";\nimport { DENSE_SIZES, controlSizes, fitFieldControls } from \"./control-fit\";\nimport {\n INLINE_CONTROLS_MIN_HEIGHT_PX,\n TAP_HALF_GAP_PX,\n inlineControlsFieldPadding,\n proTextareaClusterPlacement,\n type ProTextareaControls,\n} from \"./control-placement\";\nimport type { ProTextareaEditorSlot } from \"./editor-slot\";\nimport {\n announceMissingPort,\n resolveHookPorts,\n splitAddOnProps,\n useWritingFieldAddOns,\n type WritingFieldApi,\n} from \"./add-ons\";\nimport { FieldMenuRow, FinalizingStrip, ListeningStrip, VoiceProtectionDialog, micAriaLabel } from \"./voice-chrome\";\nimport type { ProTextareaAddOnProps } from \"./index\";\nimport { Textarea } from \"../controls/controls\";\n\nconst FILL_HEIGHT_REGEX = /(?:^|\\s)(h-full|h-dvh|flex-1|grow|inset-0|min-h-0)(?:\\s|$)/;\n\n/** Detect when the caller wants the field to stretch to its container. */\nfunction wantsFillHeight(className?: string, wrapperClassName?: string): boolean {\n return FILL_HEIGHT_REGEX.test(className ?? \"\") || FILL_HEIGHT_REGEX.test(wrapperClassName ?? \"\");\n}\n\n/** Why `startDictation()` refused. Every value is a real, nameable condition. */\nexport type DictationRefusalReason =\n | \"voice-disabled\"\n | \"field-disabled\"\n | \"no-microphone\"\n | \"recorder-unavailable\"\n | \"finalizing\";\n\nexport type DictationStartResult =\n | { started: true }\n | { started: false; reason: DictationRefusalReason; message: string };\n\n/**\n * Real HTMLTextAreaElement with the expandos ProTextarea sets one commit after mount (always call\n * them with `?.()`). Expandos, not `useImperativeHandle`: hundreds of hosts forward this ref\n * expecting a genuine element (`focus()`, `select()`, `selectionStart`, form association).\n */\nexport interface ProTextareaElement extends HTMLTextAreaElement {\n requestClose?: () => void;\n isTranscribing?: () => boolean;\n startDictation?: () => Promise<DictationStartResult>;\n stopDictation?: () => void;\n isDictating?: () => boolean;\n}\n\nexport interface ProTextareaProps\n extends React.TextareaHTMLAttributes<HTMLTextAreaElement>,\n ProTextareaAddOnProps {\n onTranscriptionComplete?: (text: string) => void;\n onTranscriptionError?: (error: string) => void;\n /** If true, appends to existing text; if false, replaces. Default: true. */\n appendTranscript?: boolean;\n /** Voice input. ON by default; `false` when the host owns recording itself. */\n enableVoice?: boolean;\n autoGrow?: boolean;\n minHeight?: number;\n maxHeight?: number;\n wrapperClassName?: string;\n /** Called when it's safe to close/unmount (after confirm or once recording/transcription completes). */\n onRequestClose?: () => void;\n /** Warn before unmount during recording/transcription. Default: true. */\n protectTranscription?: boolean;\n /** Copy rows in \"…\". Default: true. */\n showCopyButton?: boolean;\n /** Text stats in \"…\" + the pinned stats bar. OFF by default. */\n enableTextStats?: boolean;\n /** Initial pinned stats bar display when text stats are enabled. Default: true. */\n defaultShowTextStatsBar?: boolean;\n onSubmit?: () => void;\n submitDisabled?: boolean;\n allowEmptySubmit?: boolean;\n isSubmitting?: boolean;\n /** Accessible/tooltip label for the submit button. Default: \"Send\". */\n submitLabel?: string;\n /** The submit button's VISIBLE word (\"Build agent\"): a labeled solid pill instead of the send glyph. */\n submitText?: string;\n submitIcon?: React.ReactNode;\n submitOnCmdEnter?: boolean;\n submitOnEnter?: boolean;\n /** Field-navigation mode: plain Enter calls this; Shift+Enter / ⌘+Enter insert a newline. */\n onEnterKey?: (e: React.KeyboardEvent<HTMLTextAreaElement>) => void;\n auxiliaryControlsTabIndex?: number;\n auxiliaryControlsLabel?: string;\n /** Dense-form label inside the border (use only on a `bg-card` surface). */\n floatingLabel?: string;\n /** Markdown chords + selection toolbar. Default: on for a long-form box. */\n markdownFormatting?: boolean;\n /** Draw the mic + \"…\" cluster inside this element; `\"none\"`: the host already carries them. */\n controlsHost?: HTMLElement | null | \"none\";\n /** Host a different editor in place of the <textarea> (`./editor-slot.ts`). */\n editor?: ProTextareaEditorSlot;\n /** Expand button (in the control row) that opens the same field large. Off by default. */\n expandable?: boolean;\n /** `\"row\"` (default): a reserved row under the text. `\"inline\"`: the chat-composer shape. */\n controls?: ProTextareaControls;\n /** `field` (default) or `hero` (a front door's one big composer). */\n appearance?: \"field\" | \"hero\";\n /** Content at the START of the reserved control row. */\n leading?: React.ReactNode;\n /** `all` (default): \"…\" carries the shared action registry. `none`: only the field's own controls. */\n menuActions?: \"all\" | \"none\";\n}\n\nexport const ProTextarea = React.forwardRef<HTMLTextAreaElement, ProTextareaProps>(\n (\n {\n className,\n wrapperClassName,\n onTranscriptionComplete,\n onTranscriptionError,\n appendTranscript = true,\n menuActions = \"all\",\n enableVoice = true,\n autoGrow = false,\n minHeight,\n maxHeight,\n value,\n onChange,\n onKeyDown,\n disabled,\n onRequestClose,\n protectTranscription = true,\n showCopyButton = true,\n enableTextStats = false,\n defaultShowTextStatsBar = true,\n onSubmit,\n submitDisabled,\n allowEmptySubmit = false,\n isSubmitting = false,\n submitLabel = \"Send\",\n submitText,\n submitIcon,\n submitOnCmdEnter,\n submitOnEnter = false,\n onEnterKey,\n auxiliaryControlsTabIndex,\n auxiliaryControlsLabel,\n floatingLabel,\n id: idProp,\n placeholder,\n style,\n editor,\n markdownFormatting,\n expandable = false,\n controls,\n controlsHost,\n appearance = \"field\",\n leading,\n ...rest\n },\n ref,\n ) => {\n const addOns = useWritingFieldAddOns();\n const ports = resolveHookPorts(addOns);\n const { dom: props, addOnProps } = splitAddOnProps(\n rest as Record<string, unknown>,\n addOns.propNames,\n ) as { dom: React.TextareaHTMLAttributes<HTMLTextAreaElement>; addOnProps: Record<string, unknown> };\n const notify = ports.notify;\n\n // A one-row box takes the inline controls on its own; an explicit `controls` still wins.\n const resolvedControls: ProTextareaControls =\n controls ?? (props.rows !== undefined && Number(props.rows) <= 1 ? \"inline\" : \"row\");\n const inlineControls = resolvedControls === \"inline\" && !editor;\n const [smallType, setSmallType] = React.useState(false);\n const denseInline = inlineControls && smallType;\n const inlineMinHeight = denseInline ? DENSE_SIZES.box + 2 * TAP_HALF_GAP_PX : INLINE_CONTROLS_MIN_HEIGHT_PX;\n const effectiveMinHeight = inlineControls ? Math.max(minHeight ?? 0, inlineMinHeight) : minHeight;\n // Both measured boxes are watched through CALLBACK refs: the field subtree can mount again (the\n // right-click wrapper wraps it once it loads).\n const clusterRef = React.useRef<HTMLDivElement | null>(null);\n const [clusterWidth, setClusterWidth] = React.useState(0);\n const clusterObserver = React.useRef<ResizeObserver | null>(null);\n // Stable, so React re-runs it only when the node changes (a new function each render re-measured in\n // every commit, which loops when the measured size moves with the field's own controls).\n const setClusterNode = React.useCallback((node: HTMLDivElement | null) => {\n if (clusterRef.current === node) return;\n clusterRef.current = node;\n clusterObserver.current?.disconnect();\n clusterObserver.current = null;\n if (!node || typeof ResizeObserver === \"undefined\") return;\n const measure = () => setClusterWidth(node.offsetWidth);\n measure();\n clusterObserver.current = new ResizeObserver(measure);\n clusterObserver.current.observe(node);\n }, []);\n const fieldBoxRef = React.useRef<HTMLDivElement | null>(null);\n const [fieldBoxWidth, setFieldBoxWidth] = React.useState(0);\n const fieldBoxObserver = React.useRef<ResizeObserver | null>(null);\n // Stable, so React re-runs it only when the node changes (a new function each render re-measured in\n // every commit, which loops when the measured size moves with the field's own controls).\n const setFieldBoxNode = React.useCallback((node: HTMLDivElement | null) => {\n if (fieldBoxRef.current === node) return;\n fieldBoxRef.current = node;\n fieldBoxObserver.current?.disconnect();\n fieldBoxObserver.current = null;\n if (!node || typeof ResizeObserver === \"undefined\") return;\n const measure = () => {\n setFieldBoxWidth(node.offsetWidth);\n const field = node.querySelector(\"textarea\");\n if (field) setSmallType(Number.parseFloat(getComputedStyle(field).fontSize) < 14);\n };\n measure();\n fieldBoxObserver.current = new ResizeObserver(measure);\n fieldBoxObserver.current.observe(node);\n }, []);\n React.useEffect(\n () => () => {\n clusterObserver.current?.disconnect();\n fieldBoxObserver.current?.disconnect();\n },\n [],\n );\n const coarsePointer = useMediaQuery(\"(pointer: coarse)\");\n const openAudioSettings = ports.useOpenAudioSettings();\n const generatedId = React.useId();\n const inputId = idProp ?? (floatingLabel ? generatedId : undefined);\n const [isFocused, setIsFocused] = React.useState(false);\n const [isHovered, setIsHovered] = React.useState(false);\n const [expandOpen, setExpandOpen] = React.useState(false);\n const [overflowing, setOverflowing] = React.useState(false);\n const [menuOpen, setMenuOpen] = React.useState(false);\n const [statsOpen, setStatsOpen] = React.useState(false);\n const [showTextStatsBar, setShowTextStatsBar] = React.useState(defaultShowTextStatsBar);\n // The element ref is ALWAYS our own, merged into the host's forwarded ref (a CALLBACK ref left\n // `.current` undefined and every internal feature returned silently — RC-B6).\n const internalRef = React.useRef<HTMLTextAreaElement | null>(null);\n const textareaRef = internalRef;\n const setTextareaRef = (node: HTMLTextAreaElement | null) => {\n internalRef.current = node;\n if (typeof ref === \"function\") ref(node);\n else if (ref) (ref as React.MutableRefObject<HTMLTextAreaElement | null>).current = node;\n };\n\n // Markdown formatting for a long-form box (the element mirrored into state once per mount).\n const formattingOn =\n markdownFormatting ??\n (!editor && !submitOnEnter && (props.rows === undefined || Number(props.rows) >= 2));\n const [formatElement, setFormatElement] = React.useState<HTMLTextAreaElement | null>(null);\n React.useLayoutEffect(() => {\n if (internalRef.current !== formatElement) setFormatElement(internalRef.current);\n });\n ports.useFormatting(formatElement, formattingOn, addOnProps);\n\n // Auto-grow: scrollHeight excludes the border; add it so the last line never hides.\n React.useEffect(() => {\n if (!autoGrow || !textareaRef.current) return;\n const textarea = textareaRef.current;\n textarea.style.height = \"auto\";\n let newHeight = textarea.scrollHeight + (textarea.offsetHeight - textarea.clientHeight);\n if (effectiveMinHeight) newHeight = Math.max(newHeight, effectiveMinHeight);\n if (maxHeight) newHeight = Math.min(newHeight, maxHeight);\n textarea.style.height = `${newHeight}px`;\n }, [value, autoGrow, effectiveMinHeight, maxHeight, clusterWidth]);\n\n /** Write through React's own change path; true when the field now holds `newValue`. */\n const pushToTextarea = React.useCallback(\n (newValue: string): boolean => {\n if (editor) return editor.handle.current?.write(newValue) ?? false;\n const el = textareaRef.current;\n if (!el) return false;\n const setter = Object.getOwnPropertyDescriptor(window.HTMLTextAreaElement.prototype, \"value\")?.set;\n if (!setter) return false;\n setter.call(el, newValue);\n el.dispatchEvent(new Event(\"input\", { bubbles: true }));\n return el.value === newValue;\n },\n [editor],\n );\n\n // THE PRE-HYDRATION KEEP: text typed into a server-rendered box before hydration is handed to\n // the host through its own onChange (lane P, 2026-10-07).\n const keepPreHydrationText = React.useEffectEvent(() => {\n const el = internalRef.current;\n if (editor || !el || !onChange) return;\n const typed = el.value;\n if (!typed || typed === String(value ?? \"\")) return;\n el.value = \"\";\n pushToTextarea(typed);\n });\n React.useLayoutEffect(() => {\n keepPreHydrationText();\n }, []);\n\n const getLiveText = React.useCallback(\n () =>\n editor\n ? (editor.handle.current?.getValue() ?? String(value ?? \"\"))\n : (textareaRef.current?.value ?? String(value ?? \"\")),\n [editor, value],\n );\n\n // Voice rides the host's ONE recorder through the voice port.\n const voice = ports.useVoice({\n enabled: enableVoice,\n instanceId: inputId,\n label: typeof floatingLabel === \"string\" ? floatingLabel : undefined,\n getValue: getLiveText,\n writeValue: pushToTextarea,\n appendTranscript,\n protect: protectTranscription,\n onRequestClose,\n onTranscriptionComplete,\n onTranscriptionError,\n });\n const { isRecording, isTranscribing } = voice;\n const isAudioAvailable = voice.microphone;\n\n const refuseDictation = React.useCallback(\n (reason: DictationRefusalReason, message: string): DictationStartResult => {\n notify.error(message);\n onTranscriptionError?.(message);\n return { started: false, reason, message };\n },\n [notify, onTranscriptionError],\n );\n\n /** The imperative half of the mic button: the same checks, then the same start. */\n const startDictation = React.useCallback(async (): Promise<DictationStartResult> => {\n if (!enableVoice)\n return refuseDictation(\"voice-disabled\", \"Voice input is turned off for this field, so it cannot start dictating.\");\n if (disabled) return refuseDictation(\"field-disabled\", \"This field is disabled, so it cannot start dictating.\");\n if (!isAudioAvailable)\n return refuseDictation(\"no-microphone\", \"No microphone is available in this browser, so dictation cannot start.\");\n if (!voice.available)\n return refuseDictation(\n \"recorder-unavailable\",\n \"Voice recording is unavailable on this screen, so dictation cannot start.\",\n );\n if (isTranscribing && !isRecording)\n return refuseDictation(\n \"finalizing\",\n \"The last recording is still being transcribed. Wait for it to finish, then start again.\",\n );\n await voice.startDictation();\n return { started: true };\n }, [enableVoice, disabled, isAudioAvailable, voice, isTranscribing, isRecording, refuseDictation]);\n\n React.useEffect(() => {\n const el = textareaRef.current as ProTextareaElement | null;\n if (!el) return;\n el.requestClose = voice.requestClose;\n el.isTranscribing = () => isTranscribing;\n el.startDictation = startDictation;\n el.stopDictation = voice.stopDictation;\n el.isDictating = () => isRecording;\n }, [voice.requestClose, isTranscribing, startDictation, voice.stopDictation, isRecording]);\n\n const valueAsString = String(value ?? \"\");\n const hasContent = valueAsString.trim().length > 0;\n const canSubmit = !!onSubmit && (hasContent || allowEmptySubmit) && !submitDisabled && !isSubmitting && !disabled;\n const cmdEnterEnabled = submitOnCmdEnter ?? !!onSubmit;\n const triggerSubmit = React.useCallback(() => {\n if (canSubmit && onSubmit) onSubmit();\n }, [canSubmit, onSubmit]);\n\n const insertNewlineAtCursor = React.useCallback(() => {\n const el = textareaRef.current;\n if (!el) return;\n const start = el.selectionStart ?? el.value.length;\n const end = el.selectionEnd ?? el.value.length;\n pushToTextarea(el.value.slice(0, start) + \"\\n\" + el.value.slice(end));\n const caret = start + 1;\n requestAnimationFrame(() => {\n const node = textareaRef.current;\n if (!node) return;\n node.selectionStart = caret;\n node.selectionEnd = caret;\n });\n }, [pushToTextarea]);\n\n const handleKeyDown = React.useCallback(\n (e: React.KeyboardEvent<HTMLTextAreaElement>) => {\n // Typing hides the hover controls until the mouse moves again (like the OS cursor).\n if (isHovered) setIsHovered(false);\n onKeyDown?.(e);\n if (e.defaultPrevented || e.key !== \"Enter\") return;\n const withCmd = e.metaKey || e.ctrlKey;\n if (onEnterKey) {\n if (e.shiftKey) return;\n e.preventDefault();\n if (withCmd) insertNewlineAtCursor();\n else onEnterKey(e);\n return;\n }\n if (!onSubmit) return;\n if (cmdEnterEnabled && withCmd) {\n e.preventDefault();\n triggerSubmit();\n return;\n }\n const intent = composerKeyIntent(\n {\n key: e.key,\n shiftKey: e.shiftKey,\n metaKey: e.metaKey,\n ctrlKey: e.ctrlKey,\n isComposing: e.nativeEvent.isComposing,\n },\n { submitOnEnter },\n );\n if (!intentTakesTheKey(intent)) return;\n e.preventDefault();\n triggerSubmit();\n },\n [isHovered, onKeyDown, onEnterKey, insertNewlineAtCursor, onSubmit, cmdEnterEnabled, submitOnEnter, triggerSubmit],\n );\n\n const fieldApi: WritingFieldApi = {\n kind: \"textarea\",\n text: valueAsString,\n getText: getLiveText,\n write: pushToTextarea,\n getSelection: () => {\n const handle = editor?.handle.current ?? null;\n if (handle) return handle.getSelection();\n const el = textareaRef.current;\n return { start: el?.selectionStart ?? 0, end: el?.selectionEnd ?? 0 };\n },\n getElement: () => textareaRef.current,\n addOnProps,\n showCopyButton,\n flashCopied: () => undefined,\n };\n\n const showControls =\n (appearance === \"hero\" ||\n (typeof HTMLElement !== \"undefined\" && controlsHost instanceof HTMLElement) ||\n isHovered ||\n isFocused ||\n isRecording ||\n isTranscribing) &&\n !disabled;\n const isVoiceDisabled = !isAudioAvailable || disabled || (isTranscribing && !isRecording);\n\n const addOnMenuItems = addOns.Menu\n ? (addOns.menuHasItems?.({ kind: \"textarea\", addOnProps, showCopyButton }) ?? true)\n : false;\n // The menu's OWN actions; \"…\" also shows to hold whatever did not fit.\n const showMenu = !disabled && menuActions !== \"none\" && (showCopyButton || addOnMenuItems);\n // THE ONE FITTING RULE (./control-fit.ts), shared with ProInput.\n const micOffered = enableVoice && isAudioAvailable;\n const fit = fitFieldControls({\n fieldWidth: fieldBoxWidth,\n sizes: controlSizes({ coarse: coarsePointer, dense: denseInline }),\n fixedPx: inlineControls ? 12 + 2 * TAP_HALF_GAP_PX : 8,\n minText: inlineControls ? undefined : 0,\n hasSubmit: !!onSubmit,\n menuHasOwnItems: showMenu,\n mic: micOffered,\n clear: false,\n expand: expandable && !editor && overflowing,\n });\n const voiceBusyNow = isRecording || isTranscribing;\n const micInline = micOffered && (fit.mic === \"inline\" || voiceBusyNow);\n const voiceInMenu = micOffered && !micInline;\n const expandInMenu = fit.folded.includes(\"expand\");\n const menuShown =\n !disabled && (showMenu || voiceInMenu || expandInMenu || (menuActions === \"none\" && enableVoice));\n const audioSettingsInMenu = menuShown && enableVoice;\n const hasCoarseControls = (enableVoice && isAudioAvailable && !disabled) || showMenu;\n const Stats = addOns.TextStats;\n const showTextStats = enableTextStats && showMenu && !!Stats;\n React.useEffect(() => {\n if (enableTextStats && !addOns.TextStats) announceMissingPort(\"TextStats\");\n }, [enableTextStats, addOns.TextStats]);\n const showPinnedTextStatsBar = showTextStats && showTextStatsBar;\n // An auto-growing box sizes itself to its text, so it never fills its host's height.\n const fillHeight = !autoGrow && wantsFillHeight(className, wrapperClassName);\n\n React.useEffect(() => {\n if (!expandable || editor) return;\n const el = internalRef.current;\n if (!el) return;\n const measure = () => setOverflowing(el.scrollHeight > el.clientHeight + 2);\n measure();\n const observer = new ResizeObserver(measure);\n observer.observe(el);\n return () => observer.disconnect();\n }, [expandable, editor, value]);\n\n const isInvalid = props[\"aria-invalid\"] === true || props[\"aria-invalid\"] === \"true\";\n const labelFloated = isFocused || valueAsString.length > 0;\n\n const hero = appearance === \"hero\";\n const fieldClassName = cn(\n hero\n ? \"flex w-full border border-border bg-card px-5 pt-4 pb-3 text-base leading-7 text-foreground placeholder:text-muted-foreground shadow-[0_1px_2px_rgb(0_0_0/0.05),0_12px_32px_-12px_rgb(0_0_0/0.22)] transition-[border-color,box-shadow] duration-200\"\n : \"flex w-full border border-border bg-card px-3 py-2 text-sm shadow-sm placeholder:text-muted-foreground\",\n showPinnedTextStatsBar\n ? hero\n ? \"rounded-2xl sm:rounded-b-none sm:border-b-0\"\n : \"rounded-md sm:rounded-b-none sm:border-b-0\"\n : hero\n ? \"rounded-2xl\"\n : \"rounded-md\",\n // THE FIELD FOCUS (Arman 2026-10-21): border takes the ring + the one halo token.\n \"focus-visible:outline-none focus-visible:border-primary focus-visible:ring-[3px] focus-visible:ring-primary/15\",\n \"disabled:cursor-not-allowed disabled:text-disabled-foreground\",\n fillHeight ? \"min-h-0 flex-1 resize-none overflow-y-auto\" : \"resize-y\",\n autoGrow && \"resize-none overflow-y-auto\",\n hero ? \"pr-5\" : \"pr-3\",\n className,\n // AFTER the caller's className: the reserved control row always wins (a floor, never a ceiling).\n !inlineControls &&\n !controlsHost &&\n (hasCoarseControls || onSubmit) &&\n (editor?.singleLine && !onSubmit\n ? \"pr-24 pointer-coarse:pr-32\"\n : hero\n ? \"pb-[max(3.5rem,var(--matrx-textarea-end,0px))]\"\n : \"pb-[max(2.75rem,var(--matrx-textarea-end,0px))]\"),\n );\n const reservesRow = !inlineControls && !controlsHost && (hasCoarseControls || !!onSubmit) && !editor?.singleLine;\n const fieldStyle: React.CSSProperties = {\n ...style,\n minHeight: effectiveMinHeight !== undefined ? `${effectiveMinHeight}px` : style?.minHeight,\n maxHeight: maxHeight !== undefined ? `${maxHeight}px` : style?.maxHeight,\n ...(inlineControls ? inlineControlsFieldPadding(clusterWidth, inlineMinHeight) : {}),\n };\n\n const closeMenu = () => setMenuOpen(false);\n const ownRows =\n expandInMenu || voiceInMenu || audioSettingsInMenu ? (\n <>\n {expandInMenu ? (\n <FieldMenuRow\n icon={<Maximize2Icon />}\n onClick={() => {\n closeMenu();\n setExpandOpen(true);\n }}\n >\n Expand\n </FieldMenuRow>\n ) : null}\n {voiceInMenu ? (\n <FieldMenuRow\n icon={<MicIcon />}\n disabled={isVoiceDisabled}\n onClick={() => {\n closeMenu();\n void voice.handleVoiceClick();\n }}\n >\n Voice input\n </FieldMenuRow>\n ) : null}\n {audioSettingsInMenu ? (\n <FieldMenuRow\n icon={<SlidersHorizontalIcon />}\n onClick={() => {\n closeMenu();\n openAudioSettings();\n }}\n >\n Audio settings\n </FieldMenuRow>\n ) : null}\n {showMenu ? <div className=\"my-1 h-px bg-border\" role=\"separator\" /> : null}\n </>\n ) : null;\n const trailingRows =\n showTextStats && Stats ? (\n <>\n <div className=\"my-1 h-px bg-border\" role=\"separator\" />\n <Stats.MenuItems\n showStatsBar={showTextStatsBar}\n onToggleStatsBar={() => setShowTextStatsBar((prev) => !prev)}\n onOpenStatsPanel={() => setStatsOpen(true)}\n />\n </>\n ) : null;\n const Menu = addOns.Menu;\n const menuBody =\n statsOpen && Stats ? (\n <div className=\"w-56\">\n <Stats.Panel text={valueAsString} onBack={() => setStatsOpen(false)} onClose={closeMenu} />\n </div>\n ) : Menu && menuActions !== \"none\" ? (\n <Menu field={fieldApi} ownRows={ownRows} trailingRows={trailingRows} close={closeMenu} />\n ) : (\n <StandInMenu field={fieldApi} ownRows={ownRows} trailingRows={trailingRows} close={closeMenu} registry={menuActions !== \"none\"} />\n );\n\n const cluster = (\n <div\n ref={setClusterNode}\n onMouseDown={(e) => e.preventDefault()}\n data-matrx-tap-dense={denseInline ? \"\" : undefined}\n className={\n controlsHost\n ? \"flex items-center\"\n : cn(\n \"absolute z-10 flex items-center\",\n hero && !inlineControls\n ? \"bottom-2 right-2\"\n : proTextareaClusterPlacement(!!onSubmit, inlineControls ? \"inline\" : \"row\").className,\n editor?.singleLine && \"top-1/2 bottom-auto -translate-y-1/2\",\n )\n }\n >\n {fit.expandInline ? (\n <MaximizeTapButton\n tabIndex={auxiliaryControlsTabIndex}\n variant=\"transparent\"\n ariaLabel={auxiliaryControlsLabel ? `Expand ${auxiliaryControlsLabel}` : \"Expand\"}\n tooltip=\"Expand\"\n onClick={() => setExpandOpen(true)}\n className=\"text-muted-foreground\"\n />\n ) : null}\n {/* A GLASS PLANE (tap-target placement rule 1): it rides over the field's own text. */}\n <div\n data-matrx-glass-plane\n className={cn(\n \"flex items-center transition-opacity duration-200 focus-within:opacity-100 focus-within:pointer-events-auto\",\n \"pointer-coarse:opacity-100 pointer-coarse:pointer-events-auto\",\n showControls || menuOpen ? \"opacity-100\" : \"opacity-0 pointer-events-none\",\n )}\n >\n {micInline && addOns.MicButton ? (\n <addOns.MicButton\n tabIndex={auxiliaryControlsTabIndex}\n onMicClick={() => void voice.handleVoiceClick()}\n dense={denseInline}\n disabled={isVoiceDisabled}\n isRecording={isRecording}\n isTranscribing={isTranscribing}\n audioLevel={voice.audioLevel}\n micAriaLabel={micAriaLabel(isRecording, auxiliaryControlsLabel)}\n />\n ) : null}\n {menuShown && (\n <Popover\n open={menuOpen}\n onOpenChange={(open) => {\n setMenuOpen(open);\n if (!open) setStatsOpen(false);\n }}\n >\n <PopoverTrigger asChild>\n <MoreHorizontalTapButton\n tabIndex={auxiliaryControlsTabIndex}\n variant=\"transparent\"\n ariaLabel={auxiliaryControlsLabel ? `More options for ${auxiliaryControlsLabel}` : \"More options\"}\n tooltip=\"More\"\n className=\"text-muted-foreground\"\n />\n </PopoverTrigger>\n <PopoverContent\n /* sizing: fixed — the add-on body sizes itself (list, stats, agent panels) */\n align=\"end\"\n side=\"bottom\"\n sideOffset={6}\n className=\"w-auto max-w-none p-0\"\n onOpenAutoFocus={(e) => e.preventDefault()}\n >\n {menuBody}\n </PopoverContent>\n </Popover>\n )}\n </div>\n {onSubmit && (\n <TapTargetButtonSolid\n onClick={triggerSubmit}\n disabled={!canSubmit}\n ariaLabel={submitLabel}\n tooltip={submitLabel}\n label={submitText}\n icon={\n isSubmitting ? (\n <Loader2Icon className=\"h-4 w-4 animate-spin\" />\n ) : (\n (submitIcon ?? <SendIcon className=\"h-4 w-4\" />)\n )\n }\n />\n )}\n </div>\n );\n\n const field = (\n <div\n ref={setFieldBoxNode}\n className={cn(\"relative group\", wrapperClassName)}\n data-writing-field-host={addOns.Menu && addOns.useVoice ? undefined : UNCONFIGURED}\n onMouseEnter={() => setIsHovered(true)}\n onMouseMove={() => {\n if (!isHovered) setIsHovered(true);\n }}\n onMouseLeave={() => setIsHovered(false)}\n >\n <div className={cn(\"flex min-h-0 min-w-0 w-full flex-col\", fillHeight ? \"h-full flex-1\" : \"flex-1\")}>\n <div className={cn(\"relative min-w-0 w-full\", fillHeight && \"flex min-h-0 flex-1 flex-col\")}>\n {editor ? (\n editor.render({\n id: inputId,\n className: fieldClassName,\n style: fieldStyle,\n placeholder: floatingLabel ? undefined : placeholder,\n disabled,\n onFocus: () => setIsFocused(true),\n onBlur: () => setIsFocused(false),\n onKeyDown: () => {\n if (isHovered) setIsHovered(false);\n },\n })\n ) : (\n <Textarea\n hero={hero}\n joinedBottom={showPinnedTextStatsBar}\n ref={setTextareaRef}\n id={inputId}\n placeholder={floatingLabel ? undefined : placeholder}\n className={cn(\"w-full\", fillHeight ? \"min-h-0 flex-1 resize-none overflow-y-auto\" : \"resize-y\", autoGrow && \"resize-none overflow-y-auto\", className)}\n reservedInlineEnd={inlineControls ? clusterWidth + 6 : 0}\n reservedBlockEnd={reservesRow ? hero ? 56 : 44 : 0}\n style={fieldStyle}\n value={value}\n onChange={onChange}\n onFocus={() => setIsFocused(true)}\n onBlur={() => setIsFocused(false)}\n onKeyDown={handleKeyDown}\n disabled={disabled}\n {...props}\n />\n )}\n\n {expandable && !editor ? (\n <Dialog open={expandOpen} onOpenChange={setExpandOpen}>\n <DialogContent className=\"flex max-h-[90dvh] w-[min(56rem,calc(100vw-2rem))] max-w-none flex-col gap-3 sm:max-w-none\">\n <DialogTitle className=\"truncate\">{auxiliaryControlsLabel ?? floatingLabel ?? \"Text\"}</DialogTitle>\n {/* The SAME field, large: one value, one onChange. */}\n <ProTextarea\n {...(addOnProps as ProTextareaAddOnProps)}\n value={value}\n onChange={onChange}\n placeholder={placeholder}\n disabled={disabled}\n wrapperClassName=\"h-[min(70dvh,40rem)]\"\n className=\"h-full text-sm\"\n autoFocus\n />\n </DialogContent>\n </Dialog>\n ) : null}\n\n {floatingLabel && inputId && (\n <Label\n htmlFor={inputId}\n className={cn(\n \"absolute left-3 px-1 pointer-events-none transition-all duration-200 ease-in-out z-10 bg-transparent\",\n labelFloated ? \"-top-2 text-xs\" : \"top-3 text-sm\",\n isInvalid ? \"text-destructive\" : isFocused ? \"text-primary\" : \"text-muted-foreground\",\n disabled && \"text-disabled-foreground\",\n )}\n >\n {floatingLabel}\n </Label>\n )}\n\n {leading && reservesRow ? (\n <div\n data-pro-textarea-leading=\"\"\n onMouseDown={(e) => e.preventDefault()}\n className={cn(\"absolute z-10 flex items-center gap-1\", hero ? \"bottom-2 left-3\" : \"bottom-1 left-1\")}\n >\n {leading}\n </div>\n ) : null}\n {controlsHost === \"none\" ? null : controlsHost ? createPortal(cluster, controlsHost) : cluster}\n\n {enableVoice && isRecording && (\n <ListeningStrip\n liveTranscript={voice.liveTranscript}\n className={\n inlineControls\n ? \"inset-x-0 bottom-full mb-1.5 border border-border bg-card shadow-sm\"\n : cn(\"left-2 bottom-2 bg-primary/10 dark:bg-primary/15\", onSubmit ? \"right-32\" : \"right-24\")\n }\n />\n )}\n {enableVoice && isTranscribing && !isRecording && (\n <FinalizingStrip className={inlineControls ? \"left-0 bottom-full mb-1.5\" : \"left-2 bottom-2\"} />\n )}\n </div>\n\n {voice.dialogs}\n <VoiceProtectionDialog voice={voice} />\n\n {/* Desktop-only: on a phone the counts row is clutter under every field. */}\n {showPinnedTextStatsBar && Stats ? (\n <div className=\"hidden sm:block\">\n <Stats.Bar text={valueAsString} />\n </div>\n ) : null}\n </div>\n </div>\n );\n\n const ContextMenu = addOns.ContextMenu;\n if (!ContextMenu) return field;\n return (\n <ContextMenu field={fieldApi} disabled={disabled}>\n {field}\n </ContextMenu>\n );\n },\n);\n\nProTextarea.displayName = \"ProTextarea\";\n\n/** \"…\" with no Menu port: the field's own rows plus a working Copy — announced as a stand-in. */\nexport function StandInMenu({\n field,\n ownRows,\n trailingRows,\n close,\n registry,\n}: {\n field: WritingFieldApi;\n ownRows: React.ReactNode;\n trailingRows: React.ReactNode;\n close: () => void;\n registry: boolean;\n}) {\n React.useEffect(() => {\n if (registry) announceMissingPort(\"Menu\");\n }, [registry]);\n return (\n <div className=\"flex w-48 flex-col p-1\" data-writing-field-host={registry ? UNCONFIGURED : undefined}>\n {ownRows}\n {registry && field.showCopyButton ? (\n <FieldMenuRow\n icon={<CopyIcon />}\n onClick={() => {\n const text = field.getText();\n close();\n if (text) void copyText(text).then((ok) => ok && field.flashCopied());\n }}\n >\n Copy\n </FieldMenuRow>\n ) : null}\n {trailingRows}\n </div>\n );\n}\n","import { clsx, type ClassValue } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\nexport function cn(...inputs: ClassValue[]): string {\n return twMerge(clsx(inputs));\n}\n","\"use client\";\n\nimport * as LabelPrimitive from \"@radix-ui/react-label\";\nimport * as React from \"react\";\n\nimport { cn } from \"./cn\";\n\nexport const Label = React.forwardRef<\n React.ComponentRef<typeof LabelPrimitive.Root>,\n React.ComponentPropsWithoutRef<typeof LabelPrimitive.Root>\n>(({ className, ...props }, ref) => (\n <LabelPrimitive.Root\n ref={ref}\n className={cn(\n \"text-sm font-medium leading-none text-foreground peer-disabled:cursor-not-allowed peer-disabled:opacity-70\",\n className,\n )}\n {...props}\n />\n));\nLabel.displayName = LabelPrimitive.Root.displayName;\n","\"use client\";\n\n/**\n * Dialog — the modal surface, carrying every ruling the host forks paid for.\n *\n * Four hosts shipped four dialogs. Three were the stock shadcn body: a\n * fixed-size centered card with `overflow: visible`. matrx-frontend's had been\n * hardened, incident by incident, and those hardenings are the reason this\n * component belongs in the package rather than being copied a fifth time:\n *\n * 1. THE ROOT RENDERS UNCONDITIONALLY — no hydration mount gate. The gate a\n * wrapper once carried (\"Radix ids differ between SSR and client\") was\n * false — Radix ids come from React's SSR-stable `useId` — and it deleted\n * the always-visible Trigger from SSR and the first client paint.\n *\n * 2. THE DIALOG IS CLAMPED TO THE VIEWPORT AND SCROLLS INSIDE ITSELF. Proven\n * live: an admin \"Create Category\" dialog rendered 851px tall in a 657px\n * viewport with `overflow-y: visible`, so its Create button sat below the\n * fold, unreachable. The only way out was a backdrop click — which\n * dismisses WITHOUT writing, and is indistinguishable from a silent save\n * failure. `max-h-[85dvh] overflow-y-auto` is the cap.\n *\n * 3. THE PRIMARY ACTION IS ALWAYS PRESSABLE — AND NEVER ON TOP OF THE BODY.\n * `DialogFooter` is sticky and bleeds to the card's edges using\n * `--dialog-pad`. Until 0.11.3 that bleed was a NEGATIVE BLOCK MARGIN,\n * which sticky clamps: the footer was dragged up over the row above it by\n * `--dialog-pad` minus the card gap. The card now RESERVES the footer's\n * block size instead (`.matrx-dialog-card` in `styles.css` hands its bottom\n * padding to the footer), so scrolled content never shows through beneath\n * the actions AND the footer never covers the row above it. Outside a\n * DialogContent both variables are unset, the padding falls back to `0px`,\n * and the footer is the plain row it always was.\n *\n * 4. ON MOBILE THE SAME DIALOG IS A BOTTOM SHEET — full width, bottom\n * anchored, height-capped, internally scrollable, safe-area padded. Opt out\n * with `mobileSheet={false}` only for the rare surface that must stay\n * centered (a tiny spinner). The sheet geometry is re-asserted AFTER the\n * caller's className so a desktop `max-w-2xl` cannot un-fullscreen it.\n *\n * 5. AN UNTITLED DIALOG IS STILL ACCESSIBLE. Radix warns (correctly) that\n * every dialog needs a title; rather than let hosts ship the warning, a\n * visually-hidden title is injected when the tree has none, and\n * `aria-describedby` is dropped when there is no description rather than\n * pointing at nothing.\n *\n * 6. ON DESKTOP A DIALOG IS A WINDOW, NOT A WALL (0.38.0, Arman 2026-09-23:\n * \"none of the built-in page ai integrations are accessible because the\n * page is totally blocked\"). Unless the caller passes `modal`, a desktop\n * dialog does not block the page: no overlay, the page, the Agents menu,\n * the assist dock and right-click AI stay usable beside it. It behaves like\n * a window: a click outside never closes it (`dismissOnOutsideClick` opts a\n * quick picker back in), Escape closes it only while focus is inside it\n * (Escape in the page belongs to the page), and its `DialogHeader` drags\n * it, clamped on screen, double-click to recenter. On a phone it stays the\n * blocking bottom sheet — nothing useful sits behind a sheet. Confirmations\n * are `AlertDialog`, a different component, and stay blocking. This is a\n * LIGHT window: the host's heavy window manager (tray, persistence) is a\n * separate system and must not be pulled into every dialog.\n *\n * SEAM INVERSIONS. The host original resolved its portal target through\n * app-shaped hooks (a popped-out window-panel body). Here that is the\n * package's `PortalContainerProvider` seam, with an explicit `container` prop\n * keeping top priority. And DialogContent PROVIDES that seam to its own\n * children, so a Popover or menu opened inside a dialog portals INTO the\n * dialog — staying inside the scroll shard, where its wheel events work.\n * `useDialogContainer` exposes the same element for host code that needs it.\n */\n\nimport * as DialogPrimitive from \"@radix-ui/react-dialog\";\nimport * as VisuallyHidden from \"@radix-ui/react-visually-hidden\";\nimport { treeContainsComponent } from \"@ai-matrx/kit/react-tree\";\nimport * as React from \"react\";\n\nimport { cn } from \"./cn\";\nimport {\n MOTION_BOTTOM_SHEET,\n MOTION_DIALOG,\n MOTION_OVERLAY,\n} from \"./motion\";\nimport { CloseRow, CloseSlotProvider, HeaderWithClose, useCloseSlot } from \"./close-slot\";\nimport { usePortalContainer, PortalContainerProvider } from \"./portal-container\";\nimport { useLook } from \"./look\";\nimport {\n RadixDialogModalProvider,\n useRadixDialogModal,\n} from \"./radix-dialog-modal-context\";\nimport { useIsMobile } from \"./use-is-mobile\";\nimport { announceLayerFront, LAYER_FRONT_EVENT, type LayerFrontDetail } from \"./layer-front\";\nimport { clampRectToViewport, readViewport, useDragMove } from \"./window-drag\";\nimport { keepFloatingLayersInside, useModalLayer } from \"./floating-layer\";\nimport { keepMovedFocus } from \"./focus-return\";\n\n/**\n * True when the dialog is a window because the caller said nothing about\n * modality (rule 6), false when the caller passed `modal={false}` itself.\n * The two sit on different layers: a default window sits WITH the other\n * layers it was opened from (z-10000 — a dialog opened from a menu, a popover\n * or a host window must never appear behind its opener), while an explicit\n * `modal={false}` keeps the older coexistence contract below the host's window\n * manager (z-900).\n */\nconst DialogWindowedByDefaultContext = React.createContext(false);\n\nconst Dialog = ({\n children,\n ...props\n}: React.ComponentPropsWithoutRef<typeof DialogPrimitive.Root>) => {\n const isMobile = useIsMobile();\n // THE LOOK (look.tsx): in a desktop scope every dialog is a macOS sheet, modal over a dimmed\n // window, whatever `modal` says (the desktop standard's Dialog).\n const desktopLook = useLook() === \"desktop\";\n // A window on desktop, a blocking sheet on a phone; `modal` forces either (rule 6).\n const modal = desktopLook || (props.modal ?? isMobile);\n return (\n <DialogWindowedByDefaultContext.Provider value={!desktopLook && props.modal === undefined}>\n <RadixDialogModalProvider modal={modal}>\n <DialogPrimitive.Root {...props} modal={modal}>\n {children}\n </DialogPrimitive.Root>\n </RadixDialogModalProvider>\n </DialogWindowedByDefaultContext.Provider>\n );\n};\nDialog.displayName = \"Dialog\";\n\nconst DialogTrigger = DialogPrimitive.Trigger;\nconst DialogClose = DialogPrimitive.Close;\n\n/**\n * Portal-seam-aware DialogPortal. An explicit `container` always wins; with\n * none, the injected `PortalContainerProvider` value decides; with neither,\n * Radix's `document.body`.\n */\nconst DialogPortal = ({\n container,\n ...props\n}: Omit<\n React.ComponentPropsWithoutRef<typeof DialogPrimitive.Portal>,\n \"container\"\n> & {\n /** `undefined` → use the injected container; `null` → force document.body. */\n container?: HTMLElement | null | undefined;\n}) => {\n const resolved = usePortalContainer(container);\n return <DialogPrimitive.Portal container={resolved ?? null} {...props} />;\n};\nDialogPortal.displayName = \"DialogPortal\";\n\n// Shared identity across independently bundled public entrypoints/loaders.\nconst CONTEXT_SLOT = Symbol.for(\"ai-matrx.design-system.dialog-container-context\");\nconst contextRegistry = globalThis as typeof globalThis & { [CONTEXT_SLOT]?: React.Context<HTMLElement | null> };\nconst DialogContainerContext = contextRegistry[CONTEXT_SLOT] ??= React.createContext<HTMLElement | null>(null);\n\n/** The DialogContent element, for host code that portals into the dialog. */\nexport const useDialogContainer = (): HTMLElement | null =>\n React.useContext(DialogContainerContext);\n\nconst DialogOverlay = React.forwardRef<\n React.ComponentRef<typeof DialogPrimitive.Overlay>,\n React.ComponentPropsWithoutRef<typeof DialogPrimitive.Overlay>\n>(({ className, ...props }, ref) => (\n <DialogPrimitive.Overlay\n ref={ref}\n data-slot=\"dialog-overlay\"\n className={cn(\n // Page context behind the modal stays readable; separation comes from a\n // light token scrim, not a blur.\n \"fixed inset-0 z-[10000] bg-[var(--matrx-overlay-scrim-soft)]\",\n MOTION_OVERLAY,\n className,\n )}\n {...props}\n />\n));\nDialogOverlay.displayName = DialogPrimitive.Overlay.displayName;\n\n/**\n * Unstyled, non-portalling Content for custom dialog layouts. Preserves Radix\n * focus/background behavior and derives `aria-modal` from the Root.\n */\nconst DialogContentPrimitive = React.forwardRef<\n React.ComponentRef<typeof DialogPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof DialogPrimitive.Content>\n>(({ onInteractOutside, onCloseAutoFocus, ...props }, ref) => {\n const isModal = useRadixDialogModal();\n // A blocking dialog registers, so floating layers opened from it (a host\n // window, a picker window) stack above its scrim (floating-layer.tsx).\n useModalLayer(isModal);\n return (\n <DialogPrimitive.Content\n {...props}\n ref={ref}\n aria-modal={isModal || undefined}\n onInteractOutside={keepFloatingLayersInside(onInteractOutside)}\n onCloseAutoFocus={keepMovedFocus(onCloseAutoFocus)}\n />\n );\n});\nDialogContentPrimitive.displayName = \"DialogContentPrimitive\";\n\nconst DIALOG_DESKTOP_CLASSES =\n \"matrx-dialog-card fixed inset-0 z-[10000] m-auto grid h-fit min-w-0 w-full max-w-lg gap-4 max-h-[85dvh] overflow-y-auto overscroll-contain [--dialog-pad:1.5rem] overflow-x-clip border bg-background p-6 shadow-lg [overflow-wrap:anywhere] [&>*]:min-w-0 [&>*]:max-w-full sm:rounded-lg\";\n\nconst DIALOG_MOBILE_SHEET_CLASSES =\n \"matrx-mobile-sheet matrx-dialog-card fixed inset-x-0 bottom-0 left-0 right-0 top-auto z-[10000] flex min-w-0 flex-col w-full max-w-full max-h-[90dvh] gap-4 [--dialog-pad:1rem] overflow-x-clip border-t bg-background p-4 pb-safe shadow-lg [overflow-wrap:anywhere] [&>*]:min-w-0 [&>*]:max-w-full rounded-t-2xl rounded-b-none overflow-y-auto overscroll-contain\";\n\n// Re-asserted LAST so sheet geometry always wins over a caller className.\nconst DIALOG_MOBILE_SHEET_OVERRIDE =\n \"inset-x-0 bottom-0 left-0 right-0 top-auto translate-none w-full max-w-full max-h-[90dvh] rounded-b-none rounded-t-2xl overflow-y-auto\";\n\n/** Drag props the windowed DialogContent hands its DialogHeader (rule 6). */\ntype DialogWindowHandle = {\n onPointerDown: (event: React.PointerEvent<HTMLElement>) => void;\n onDoubleClick: () => void;\n};\nconst DialogWindowHandleContext = React.createContext<DialogWindowHandle | null>(null);\n\n/** Pixels of a dragged window that must stay on screen. */\nconst WINDOW_KEEP_VISIBLE = 80;\n\nexport interface DialogContentProps\n extends React.ComponentPropsWithoutRef<typeof DialogPrimitive.Content> {\n /**\n * Windowed (non-blocking) dialogs never close from a click outside them —\n * the person is reaching for the page or an AI control beside the window.\n * Pass `true` for a quick picker that should close when the person clicks\n * away. Ignored on a blocking dialog, which keeps Radix's behavior.\n */\n dismissOnOutsideClick?: boolean;\n /** Render as a bottom sheet below the mobile breakpoint. Default `true`. */\n mobileSheet?: boolean;\n /** Render the built-in close control. Default `true`. */\n showCloseButton?: boolean;\n /** Explicit portal target; wins over the injected container. */\n container?: HTMLElement | null;\n /**\n * Package-owned open/close motion. Default `true`. Pass `false` for a\n * surface that must appear instantly. It is NOT the reduced-motion switch;\n * `styles.css` already honors `prefers-reduced-motion`.\n */\n animated?: boolean;\n /**\n * THE NAMED WIDTHS (0.68.22) — a dialog never pastes `max-w-[860px]`. Derived from the call\n * sites: `sm` 28rem (a confirm, a one-field ask), `md` 32rem (default), `lg` 42rem (a form with\n * two columns), `xl` 56rem (a detail or a table), `2xl` 72rem (a workspace in a dialog),\n * `full` the viewport less 1rem each side, `screen` the whole viewport (a record opened as a\n * page). On a phone the dialog is a bottom sheet at every size.\n */\n size?: DialogSize;\n /**\n * `default`: the card pads and gaps its children (24px). `none`: the content draws its own\n * frame edge to edge — a command palette, a picker with its own header row, a full-bleed grid.\n */\n padding?: \"default\" | \"none\";\n /**\n * `auto` (default): the card is as tall as its content, up to 85dvh. `tall`: the card holds\n * 85dvh whatever its content — a workspace whose body scrolls inside (a grid, a document).\n */\n height?: \"auto\" | \"tall\";\n}\n\nexport type DialogSize = \"sm\" | \"md\" | \"lg\" | \"xl\" | \"2xl\" | \"full\" | \"screen\";\n\n/**\n * Literal classes so a host's Tailwind scan of the package finds every one. Every width above\n * `md` keeps a 1rem gutter each side on a screen narrower than itself (the card is `w-full`\n * with `inset-0`, so an un-guttered `max-w-4xl` ran edge to edge at 800px). `screen` is the\n * whole viewport, square-cornered — a record opened \"as a page\".\n */\nexport const DIALOG_SIZE_CLASS: Record<DialogSize, string> = {\n sm: \"max-w-md\",\n md: \"max-w-lg\",\n lg: \"max-w-[min(42rem,calc(100vw-2rem))]\",\n xl: \"max-w-[min(56rem,calc(100vw-2rem))]\",\n \"2xl\": \"max-w-[min(72rem,calc(100vw-2rem))]\",\n full: \"max-w-[calc(100vw-2rem)]\",\n screen: \"max-w-none w-screen h-dvh max-h-none rounded-none sm:rounded-none\",\n};\n\nconst DialogContent = React.forwardRef<\n React.ComponentRef<typeof DialogPrimitive.Content>,\n DialogContentProps\n>(\n (\n {\n className,\n children,\n mobileSheet = true,\n animated = true,\n showCloseButton = true,\n container,\n dismissOnOutsideClick = false,\n size = \"md\",\n padding = \"default\",\n height = \"auto\",\n onInteractOutside,\n onEscapeKeyDown,\n onPointerDownCapture,\n onFocusCapture,\n style,\n ...props\n },\n ref,\n ) => {\n const isMobile = useIsMobile();\n const isModal = useRadixDialogModal();\n // Falls through to the injected container while `containerEl` is unset\n // (pre-mount) — the original's dialog > popout > body priority.\n const injectedContainer = usePortalContainer(container);\n // THE LOOK (look.tsx): inside a desktop scope the dialog is a macOS sheet — never a phone's\n // bottom sheet, no close (×), no web motion; look-desktop.css draws it from `data-desktop-sheet`.\n const desktopLook = useLook() === \"desktop\";\n const asSheet = mobileSheet && isMobile && !desktopLook;\n const windowed = !isModal && !asSheet;\n const windowedByDefault = React.useContext(DialogWindowedByDefaultContext);\n const [containerEl, setContainerEl] = React.useState<HTMLElement | null>(\n null,\n );\n\n // ── the front-most layer (layer-front.ts) ───────────────────────────────\n // A default window sits at z-10000 with the layers it was opened from; it\n // steps behind when another layer comes to the front after it (a host\n // window opened from the Agents menu) and returns when the person reaches\n // for it again. An explicit modal={false} keeps its fixed z-900 contract.\n const stacks = windowed && windowedByDefault;\n const [behind, setBehind] = React.useState(false);\n React.useEffect(() => {\n if (!stacks || !containerEl) return;\n const onFront = (event: Event) => {\n const element = (event as CustomEvent<LayerFrontDetail>).detail?.element ?? null;\n if (element && (element === containerEl || containerEl.contains(element))) return;\n setBehind(true);\n };\n document.addEventListener(LAYER_FRONT_EVENT, onFront);\n // Opening is coming to the front.\n announceLayerFront(containerEl);\n return () => document.removeEventListener(LAYER_FRONT_EVENT, onFront);\n }, [stacks, containerEl]);\n const bringToFront = () => {\n if (!stacks || !containerEl) return;\n setBehind(false);\n announceLayerFront(containerEl);\n };\n\n // ── rule 6: the windowed dialog drags by its header ──────────────────────\n // THE WINDOW DRAG (window-drag.ts): painted per frame, committed once on release,\n // the header kept on screen.\n const [offset, setOffset] = React.useState({ x: 0, y: 0 });\n const drag = useDragMove({\n element: containerEl,\n enabled: windowed,\n paint: \"offset\",\n offset,\n constrain: (next) => clampRectToViewport(next, readViewport(), { keepVisible: WINDOW_KEEP_VISIBLE }),\n onCommit: (_rect, commit) => setOffset(commit.offset),\n });\n const handle = React.useMemo<DialogWindowHandle | null>(\n () => (windowed ? { onPointerDown: drag.onPointerDown, onDoubleClick: () => setOffset({ x: 0, y: 0 }) } : null),\n [windowed, drag.onPointerDown],\n );\n\n const mergedRef = React.useCallback(\n (node: HTMLDivElement | null) => {\n setContainerEl(node);\n if (typeof ref === \"function\") ref(node);\n else if (ref)\n (ref as React.MutableRefObject<HTMLDivElement | null>).current = node;\n },\n [ref],\n );\n\n // The × sits in the header's row, or in a row of its own (close-slot.tsx).\n const closeSlot = useCloseSlot(showCloseButton && !desktopLook);\n\n const hasTitle =\n treeContainsComponent(children, DialogTitle) ||\n treeContainsComponent(children, DialogPrimitive.Title);\n const hasDescription =\n treeContainsComponent(children, DialogDescription) ||\n treeContainsComponent(children, DialogPrimitive.Description);\n\n return (\n <DialogPortal container={container}>\n {isModal ? <DialogOverlay /> : null}\n <DialogContentPrimitive\n ref={mergedRef}\n data-slot=\"dialog-content\"\n data-size={size}\n data-padding={padding === \"none\" ? \"none\" : undefined}\n data-height={height === \"tall\" ? \"tall\" : undefined}\n data-desktop-sheet={desktopLook ? \"\" : undefined}\n className={cn(\n asSheet ? DIALOG_MOBILE_SHEET_CLASSES : DIALOG_DESKTOP_CLASSES,\n !asSheet && DIALOG_SIZE_CLASS[size],\n padding === \"none\" && (asSheet ? \"gap-0 p-0 pb-safe [--dialog-pad:0px]\" : \"gap-0 p-0 [--dialog-pad:0px]\"),\n height === \"tall\" && (asSheet ? \"h-[90dvh]\" : \"h-[85dvh]\"),\n animated && !desktopLook && (asSheet ? MOTION_BOTTOM_SHEET : MOTION_DIALOG),\n className,\n asSheet && DIALOG_MOBILE_SHEET_OVERRIDE,\n // A non-modal dialog is the coexistence contract for content that\n // can sit beside a host's floating window manager (which starts at\n // z=1000); staying below that boundary makes a newly focused window\n // usable without coupling the two systems.\n !isModal && !windowedByDefault && \"z-[900]\",\n // Another layer came to the front after this window (layer-front.ts).\n stacks && behind && \"z-[999]\",\n // Without an overlay the card needs its own separation from the page.\n windowed && \"shadow-2xl ring-1 ring-border/60\",\n )}\n style={\n windowed && (offset.x !== 0 || offset.y !== 0)\n ? { ...style, translate: `${offset.x}px ${offset.y}px` }\n : style\n }\n onPointerDownCapture={(event) => {\n onPointerDownCapture?.(event);\n if (behind) bringToFront();\n }}\n onFocusCapture={(event) => {\n onFocusCapture?.(event);\n if (behind) bringToFront();\n }}\n onInteractOutside={(event) => {\n onInteractOutside?.(event);\n if (windowed && !dismissOnOutsideClick) event.preventDefault();\n }}\n onEscapeKeyDown={(event) => {\n onEscapeKeyDown?.(event);\n // Escape pressed in the page belongs to the page (a grid canceling\n // an edit), not to the window beside it.\n // The key's own target is where the person pressed it; focus is\n // the fallback when the event carries no element target.\n const pressedIn =\n event.target instanceof Node && event.target !== document.body\n ? event.target\n : document.activeElement;\n // Focus on <body> (or nowhere) belongs to nobody in the page: a button that disabled itself\n // while it worked (Share with User) drops focus there, and Escape must still close the window.\n const nowhere =\n !pressedIn || pressedIn === document.body || pressedIn === document.documentElement;\n if (windowed && containerEl && !nowhere && !containerEl.contains(pressedIn)) {\n event.preventDefault();\n }\n }}\n {...(hasDescription ? {} : { \"aria-describedby\": undefined })}\n {...props}\n >\n {hasTitle ? null : (\n <VisuallyHidden.Root>\n <DialogPrimitive.Title>Dialog</DialogPrimitive.Title>\n </VisuallyHidden.Root>\n )}\n {closeSlot.slot && !closeSlot.claimed ? <CloseRow /> : null}\n <CloseSlotProvider value={closeSlot.slot}>\n <DialogContainerContext.Provider value={containerEl}>\n <DialogWindowHandleContext.Provider value={handle}>\n <PortalContainerProvider\n container={containerEl ?? injectedContainer ?? null}\n >\n {children}\n </PortalContainerProvider>\n </DialogWindowHandleContext.Provider>\n </DialogContainerContext.Provider>\n </CloseSlotProvider>\n </DialogContentPrimitive>\n </DialogPortal>\n );\n },\n);\nDialogContent.displayName = DialogPrimitive.Content.displayName;\n\nconst DialogHeader = ({\n className,\n ...props\n}: React.HTMLAttributes<HTMLDivElement>) => {\n // In a windowed dialog the header is the drag handle (rule 6).\n const handle = React.useContext(DialogWindowHandleContext);\n return (\n <HeaderWithClose\n slotName=\"dialog-header\"\n baseClassName=\"flex flex-col space-y-1.5 text-center sm:text-left\"\n // DialogTitle's line is 18px (text-lg leading-none): (44 - 18) / 2 = 13, (32 - 18) / 2 = 7.\n closeOffsetClassName=\"-mt-3 lg:-mt-1.5\"\n {...(handle\n ? {\n ...handle,\n \"data-window-handle\": \"\",\n title: \"Drag to move · double-click to recenter\",\n }\n : {})}\n className={cn(handle && \"cursor-grab select-none active:cursor-grabbing\", className)}\n {...props}\n />\n );\n};\nDialogHeader.displayName = \"DialogHeader\";\n\nconst DialogFooter = ({\n className,\n ...props\n}: React.HTMLAttributes<HTMLDivElement>) => (\n <div\n data-slot=\"dialog-footer\"\n className={cn(\n // `gap-2` is the stacked (phone) gap — the buttons never touch; from sm up the\n // row keeps its `space-x-2`, so the gap resets to 0 there.\n \"flex flex-col-reverse gap-2 sm:flex-row sm:justify-end sm:gap-0 sm:space-x-2\",\n // Ruling 3/4 — sticky to the card edges so a scrolled body never shows\n // through under the actions, and safe-area padded on a phone.\n //\n // 🚨 THERE IS NO `mb-[…]` HERE, AND THERE MUST NEVER BE ONE AGAIN\n // (0.11.3, feedback bf8fb00b). The bleed over the card's bottom padding\n // used to be a NEGATIVE BLOCK MARGIN, which makes this box taller than\n // the grid area the card allocates it — and `position: sticky` CLAMPS a\n // box to its containing block, so the browser yanked the footer UP by\n // `--dialog-pad` against the card's `gap-4` and painted 8px of opaque\n // footer over the last line of the consequence, at every length. The\n // card now RESERVES this footer's block size instead (`matrx-dialog-card`\n // in styles.css hands over its `padding-bottom`), so the bleed costs no\n // margin at all. Guard: `sticky-footer-geometry.test.tsx`.\n //\n // These stay UTILITIES rather than a shipped rule so a caller's\n // `className` still wins through tailwind-merge — a shipped rule would\n // have to be unlayered to survive Tailwind preflight (§ THE PREFLIGHT\n // RULE in styles.css) and would then override every caller's padding.\n \"sticky bottom-0 z-10 bg-background pt-3\",\n \"mx-[calc(var(--dialog-pad,0px)*-1)] px-[var(--dialog-pad,0px)] pb-[var(--dialog-pad,0px)]\",\n className,\n )}\n {...props}\n />\n);\nDialogFooter.displayName = \"DialogFooter\";\n\nconst DialogTitle = React.forwardRef<\n React.ComponentRef<typeof DialogPrimitive.Title>,\n React.ComponentPropsWithoutRef<typeof DialogPrimitive.Title>\n>(({ className, ...props }, ref) => (\n <DialogPrimitive.Title\n ref={ref}\n data-slot=\"dialog-title\"\n className={cn(\"text-lg font-semibold leading-none tracking-tight\", className)}\n {...props}\n />\n));\nDialogTitle.displayName = DialogPrimitive.Title.displayName;\n\nconst DialogDescription = React.forwardRef<\n React.ComponentRef<typeof DialogPrimitive.Description>,\n React.ComponentPropsWithoutRef<typeof DialogPrimitive.Description>\n>(({ className, ...props }, ref) => (\n <DialogPrimitive.Description\n ref={ref}\n data-slot=\"dialog-description\"\n className={cn(\"text-sm text-muted-foreground\", className)}\n {...props}\n />\n));\nDialogDescription.displayName = DialogPrimitive.Description.displayName;\n\nexport {\n Dialog,\n DialogClose,\n DialogContent,\n DialogContentPrimitive,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogOverlay,\n DialogPortal,\n DialogTitle,\n DialogTrigger,\n};\n","/**\n * THE MOTION CONTRACT (0.10.0) — the class names every animated surface in\n * this package puts on the DOM, in ONE place.\n *\n * Why a module and not ten inline strings: the sweep that produced this file\n * found the same defect ten times over, and it was invisible each time\n * because each primitive spelled its animation out by hand. Ten hand-written\n * copies of `data-[state=open]:animate-in data-[state=closed]:animate-out\n * data-[state=closed]:fade-out-0 …` meant ten chances to reach for a utility\n * nothing in the package defines — which is exactly what happened. A single\n * exported constant per motion SHAPE means the next primitive cannot invent\n * an eleventh spelling, and `styles.test.ts` can prove every one of them\n * resolves to a rule in the shipped stylesheet.\n *\n * Every rule these name lives in `styles.css` under the package's own\n * keyframes. NONE of them is a Tailwind utility, and none requires a host\n * plugin — see that file's header for the measurement that made this\n * necessary.\n */\n\n/** Modal scrims: Dialog, AlertDialog, Sheet, CommandDialog. Fade only. */\nexport const MOTION_OVERLAY = \"matrx-motion-overlay\";\n\n/** The centered dialog card. Fades and scales; centering is not its business. */\nexport const MOTION_DIALOG = \"matrx-motion-dialog\";\n\n/**\n * THE CENTERING OF A CENTERED DIALOG CARD — package-owned, in the `translate`\n * property, and NEVER a Tailwind `translate-x-[-50%] translate-y-[-50%]` pair.\n *\n * Those utilities do not compile to the same thing in every host: Tailwind v3\n * writes them into `transform`, Tailwind v4 writes them into the independent\n * `translate` property, which COMPOSES with `transform` instead of being\n * replaced by it. 0.10.0's keyframes restated the centering inside `transform`,\n * which was harmless on v3 and doubled the centering on v4 — the card flew in\n * from off the top-left of the viewport for the animation's whole duration and\n * snapped into place at the end (fixed in 0.10.1).\n *\n * Owning it here means one spelling that reads the same on both, and it frees\n * `transform` so the keyframes carry ONLY the delta. Put this on every centered\n * surface UNCONDITIONALLY — it is geometry, so unlike {@link MOTION_DIALOG} it\n * must survive `animated={false}`. Its rule ships in `styles.css`.\n */\nexport const CENTERED_DIALOG = \"matrx-dialog-centered\";\n\n/**\n * The resting gap between a `popper`-positioned surface and its trigger, for\n * the primitives that want one (today: `Select`). Same law and same reason as\n * {@link CENTERED_DIALOG} — a position an animated surface holds AT REST is\n * the `translate` property's job, never a Tailwind translate utility, because\n * those land in `transform` on a v3 host and in `translate` on a v4 one while\n * the keyframes animate `transform` either way. Sizes from\n * `--matrx-popper-offset`; keys off Radix's `data-side`.\n */\nexport const POPPER_OFFSET = \"matrx-popper-offset\";\n\n/** The mobile Dialog / CommandDialog bottom sheet. Slides up and fades. */\nexport const MOTION_BOTTOM_SHEET = \"matrx-motion-bottom-sheet\";\n\n/**\n * Radix-popper surfaces: Popover, DropdownMenu, ContextMenu, HoverCard,\n * Select, Tooltip. Reads `--radix-popper-transform-origin` so the surface\n * grows out of its trigger, and `data-side` so it travels from it.\n */\nexport const MOTION_POPPER = \"matrx-motion-popper\";\n\n/** Edge sheets, one class per `sheetVariants` side. */\nexport const MOTION_SHEET = {\n top: \"matrx-motion-sheet-top\",\n bottom: \"matrx-motion-sheet-bottom\",\n left: \"matrx-motion-sheet-left\",\n right: \"matrx-motion-sheet-right\",\n center: \"matrx-motion-sheet-center\",\n} as const;\n\n/** Skeleton's breathing loop. */\nexport const MOTION_PULSE = \"matrx-pulse\";\n/** A waiting box's crossing band of light (Skeleton `motion=\"shimmer\"`). Reduced motion: a slow breathe, no travel. */\nexport const MOTION_SHIMMER = \"matrx-shimmer\";\n\n/** The spinner loop, for every inline busy indicator in the package. */\nexport const MOTION_SPIN = \"matrx-spin\";\n\n/**\n * FirstUseHint's beacon: a soft ring that pulses three times around the anchor, on\n * `box-shadow` only, so nothing moves. A still ring under reduced motion.\n */\nexport const MOTION_HINT_BEACON = \"matrx-motion-hint-beacon\";\n\n/**\n * Every motion class the package ships, for the guards. If a rule for one of\n * these is missing from `styles.css`, a component animates in no consumer and\n * says nothing about it — the C26 failure this list exists to make loud.\n */\nexport const ALL_MOTION_CLASSES = [\n MOTION_OVERLAY,\n MOTION_DIALOG,\n MOTION_BOTTOM_SHEET,\n MOTION_POPPER,\n ...Object.values(MOTION_SHEET),\n MOTION_PULSE,\n MOTION_SHIMMER,\n MOTION_SPIN,\n MOTION_HINT_BEACON,\n] as const;\n\n/**\n * The host-plugin utilities this package is forbidden to emit. They are\n * supplied by `tailwindcss-animate` / `tw-animate-css`, which is a HOST CSS\n * entry concern a package cannot declare a dependency on: three of the four\n * AI Matrx consumers never loaded it, so every surface wearing these appeared\n * with no animation and no error. `styles.test.ts` fails the build if one\n * comes back.\n */\nexport const FORBIDDEN_HOST_MOTION_UTILITIES = [\n \"animate-in\",\n \"animate-out\",\n \"fade-in\",\n \"fade-out\",\n \"zoom-in\",\n \"zoom-out\",\n \"slide-in-from\",\n \"slide-out-to\",\n \"animate-accordion\",\n \"animate-slide-down\",\n \"animate-slide-up\",\n \"animate-pulse\",\n \"animate-spin\",\n] as const;\n\n/**\n * THE PANEL MOTION as a Tailwind class string (moved from matrx-frontend\n * `lib/motion/panel-motion.ts`): every panel, sidebar, dock, drawer and sheet\n * slides its size/position on the host's `--matrx-motion-duration-panel` /\n * `--matrx-motion-ease-panel` (tokens.css ships the standard). Pair it with the\n * transition property you animate (`transition-transform`, …).\n */\nexport const PANEL_MOTION_CLASS =\n \"duration-(--matrx-motion-duration-panel) ease-(--matrx-motion-ease-panel) motion-reduce:transition-none\";\nexport const PANEL_MOTION_DURATION_VAR = \"var(--matrx-motion-duration-panel)\";\nexport const PANEL_MOTION_EASE_VAR = \"var(--matrx-motion-ease-panel)\";\n","\"use client\";\n\n/**\n * THE CLOSE CONTROL LIVES IN A ROW, NEVER IN A CORNER.\n *\n * The stock shadcn dialog pins its × with `absolute right-4 top-4`: a\n * coordinate guess about how tall the content's first row will be. Every\n * content whose first row is a different height got an × floating off its\n * row — the command palette's sat 12px below its 48px search row, on the\n * divider, with the query running underneath it (Arman, 2026-10-20: \"each\n * time they use this component, we end up with a very oddly placed x\").\n * Agents re-typed that snippet from memory faster than it could be fixed.\n *\n * So the × is a flex item of the row it belongs to, centered by layout:\n *\n * - `CommandInput` inside a `CommandDialog` draws it at the end of the\n * search row.\n * - `DialogHeader` / `SheetHeader` draw it at the end of the header row and\n * CLAIM it, so the content does not draw a second one; with two headers the\n * first one mounted draws it.\n * - Content with no visible header gets a close row of its own at the top,\n * in flow — it takes space, it never covers anything.\n *\n * Guard: `close-in-flow.test.tsx` — no `*.Close` in this package or its\n * consumers carries `absolute`/`fixed`, and each surface puts the × inside\n * its row.\n */\n\nimport * as DialogPrimitive from \"@radix-ui/react-dialog\";\nimport * as React from \"react\";\n\nimport { cn } from \"./cn\";\nimport { XIcon } from \"./icons\";\n\n/** 44px on touch, 32px from `lg`; a flex item, never positioned. */\nconst CLOSE_CONTROL_CLASSES =\n \"flex h-11 w-11 shrink-0 items-center justify-center rounded-sm text-muted-foreground ring-offset-background transition-colors hover:text-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none lg:h-8 lg:w-8\";\n\nexport function CloseControl({ className }: { className?: string }): React.ReactElement {\n return (\n <DialogPrimitive.Close data-slot=\"dialog-close\" aria-label=\"Close\" className={cn(CLOSE_CONTROL_CLASSES, className)}>\n <XIcon className=\"h-4 w-4\" aria-hidden=\"true\" />\n <span className=\"sr-only\">Close</span>\n </DialogPrimitive.Close>\n );\n}\n\ninterface CloseSlot {\n /** A row takes the × into itself; returns the release. The FIRST live claimant owns it. */\n claim(id: string): () => void;\n /** The id that draws the ×, or null while nobody claims it. */\n owner: string | null;\n}\n\n/** Dialog and Sheet: claimed by their header. */\nconst CloseSlotContext = React.createContext<CloseSlot | null>(null);\n/**\n * CommandDialog: claimed by its search row only. A separate context so a\n * CommandInput in a combobox (Popover > Command) opened INSIDE a Dialog never\n * takes the dialog's × — context crosses portals, and that × closes the dialog.\n */\nconst SearchRowCloseSlotContext = React.createContext<CloseSlot | null>(null);\n\n/**\n * For a content surface: returns the provider value and whether a row has\n * claimed the ×. Unclaimed (no header, or only an `sr-only`/`hidden` one) the\n * content draws `<CloseRow />` first, in flow. Claims land in a layout effect,\n * so the fallback never paints when a row takes it.\n */\nexport function useCloseSlot(enabled: boolean): { slot: CloseSlot | null; claimed: boolean } {\n const [claims, setClaims] = React.useState<string[]>([]);\n const owner = claims[0] ?? null;\n const claim = React.useCallback((id: string) => {\n setClaims((list) => [...list, id]);\n return () => setClaims((list) => list.filter((c) => c !== id));\n }, []);\n const slot = React.useMemo<CloseSlot | null>(() => (enabled ? { claim, owner } : null), [enabled, claim, owner]);\n return { slot, claimed: owner !== null };\n}\n\nexport const CloseSlotProvider = CloseSlotContext.Provider;\nexport const SearchRowCloseSlotProvider = SearchRowCloseSlotContext.Provider;\n\nfunction useClaim(context: React.Context<CloseSlot | null>, declined: boolean): boolean {\n const slot = React.useContext(context);\n const id = React.useId();\n const claim = slot?.claim;\n const wants = claim !== undefined && !declined;\n // Depends on the stable `claim`, never on `owner`, so a change of owner never re-claims.\n React.useLayoutEffect(() => (wants && claim ? claim(id) : undefined), [wants, claim, id]);\n return wants && slot?.owner === id;\n}\n\n/** For a header row: claims the Dialog/Sheet slot; true when this row draws the ×. */\nexport function useCloseSlotClaim(declined = false): boolean {\n return useClaim(CloseSlotContext, declined);\n}\n\n/** For CommandInput: claims only a CommandDialog's slot; true when this row draws the ×. */\nexport function useSearchRowCloseSlotClaim(): boolean {\n return useClaim(SearchRowCloseSlotContext, false);\n}\n\n/** The fallback: a row of its own at the top of the content. */\nexport function CloseRow({ className }: { className?: string }): React.ReactElement {\n return (\n <div data-slot=\"close-row\" className={cn(\"flex justify-end\", className)}>\n <CloseControl />\n </div>\n );\n}\n\n/** Classes that lay out a header's CHILDREN; they move to the header's body. */\nconst BODY_LAYOUT = /^!?(?:[a-z0-9]+:)*(?:flex|grid|flex-(?:row|col)(?:-reverse)?|grid-(?:cols|rows|flow)-\\S+|place-\\S+|items-\\S+|justify-\\S+|content-\\S+|gap(?:-[xy])?-\\S+|space-[xy]-\\S+|text-(?:left|center|right|start|end)|flex-wrap|flex-nowrap)$/;\n/**\n * Right padding a header carried to clear the old corner ×; with the × in the\n * row it would only push the × inward, so it is dropped.\n */\nconst OLD_CLOSE_RESERVE = /^pr-(?:8|9|10|11|12|14|16)$/;\n\nfunction splitHeaderClasses(className: string | undefined): { row: string; body: string } {\n const row: string[] = [];\n const body: string[] = [];\n for (const c of (className ?? \"\").split(/\\s+/)) {\n if (!c || OLD_CLOSE_RESERVE.test(c)) continue;\n (BODY_LAYOUT.test(c) ? body : row).push(c);\n }\n return { row: row.join(\" \"), body: body.join(\" \") };\n}\n\n/**\n * A header's element. With a close slot it is a row — the caller's children\n * in a body column, the × after them; the caller's padding, border and\n * background stay on the row, the caller's child layout (`flex-row`,\n * `space-y-*`, `text-left`…) moves to the body. Without one (no ×, or the\n * header is `sr-only`) it renders exactly as `baseClassName` + `className`.\n */\nexport function HeaderWithClose({\n slotName,\n baseClassName,\n closeOffsetClassName,\n className,\n children,\n ...props\n}: React.HTMLAttributes<HTMLDivElement> & {\n slotName: string;\n baseClassName: string;\n /** Pulls the × up so its center sits on the title's first line (the title's line height is the header's to know). */\n closeOffsetClassName: string;\n}): React.ReactElement {\n // A header nobody sees declines the ×; the content's own close row draws it.\n const owns = useCloseSlotClaim(/(?:^|\\s)(?:sr-only|hidden)(?:\\s|$)/.test(className ?? \"\"));\n if (!owns) {\n return (\n <div data-slot={slotName} className={cn(baseClassName, className)} {...props}>\n {children}\n </div>\n );\n }\n const { row, body } = splitHeaderClasses(className);\n // A header laid out as a row centers the × on that row; a stacked one, on the title's first line.\n const rowish = /(?:^|\\s)(?:[a-z0-9]+:)*flex-row(?:\\s|$)/.test(body);\n return (\n <div data-slot={slotName} data-has-close=\"\" className={cn(\"flex gap-2\", rowish ? \"items-center\" : \"items-start\", row)} {...props}>\n <div data-slot={`${slotName}-body`} className={cn(\"min-w-0 flex-1\", baseClassName, body)}>\n {children}\n </div>\n <CloseControl className={cn(\"-mr-2\", !rowish && closeOffsetClassName)} />\n </div>\n );\n}\n","/**\n * Internal inlined SVG icons (policy C19: no icon-library dependency, ever).\n *\n * Each icon is copied from the exact glyph the ported originals rendered:\n * lucide-react's Loader2 / ChevronLeft / ChevronRight / MoreHorizontal and\n * @radix-ui/react-icons' Cross2Icon. Same viewBoxes, same paths, same default\n * stroke geometry — a host swapping the import sees pixel-identical output.\n *\n * Not exported from the package entry; components consume them directly.\n */\n\nimport * as React from \"react\";\n\nexport type IconProps = React.SVGAttributes<SVGSVGElement>;\n\n/**\n * Every lucide glyph carries `lucide-<name>`, the class lucide-react itself renders: THE OPTICAL\n * GLYPH TRIM (tap-target.css) reads the glyph's real air from it, and a caller's own class follows it.\n */\nfunction lucideProps(name: string, { className, ...props }: IconProps): React.SVGAttributes<SVGSVGElement> {\n return {\n className: className ? `lucide-${name} ${className}` : `lucide-${name}`,\n xmlns: \"http://www.w3.org/2000/svg\",\n viewBox: \"0 0 24 24\",\n fill: \"none\",\n stroke: \"currentColor\",\n strokeWidth: 2,\n strokeLinecap: \"round\",\n strokeLinejoin: \"round\",\n \"aria-hidden\": true,\n ...props,\n };\n}\n\n/**\n * lucide `loader-2` — the spinner glyph. Callers add `matrx-spin`.\n * Never a resting icon: at rest this incomplete arc reads as a broken\n * half-circle. Refresh controls use arrows, then swap to this only while busy.\n */\nexport function Loader2Icon(props: IconProps) {\n return (\n <svg {...lucideProps(\"loader-circle\", props)}>\n <path d=\"M21 12a9 9 0 1 1-6.219-8.56\" />\n </svg>\n );\n}\n\n/** lucide `chevron-left`. */\nexport function ChevronLeftIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"chevron-left\", props)}>\n <path d=\"m15 18-6-6 6-6\" />\n </svg>\n );\n}\n\n/** lucide `chevron-right`. */\nexport function ChevronRightIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"chevron-right\", props)}>\n <path d=\"m9 18 6-6-6-6\" />\n </svg>\n );\n}\n\n/** lucide `chevron-down` — the disclosure's open glyph. */\nexport function ChevronDownIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"chevron-down\", props)}>\n <path d=\"m6 9 6 6 6-6\" />\n </svg>\n );\n}\n\n/** lucide `trash-2` (moved from @ai-matrx/agents). */\nexport function Trash2Icon(props: IconProps) {\n return (\n <svg {...lucideProps(\"trash-2\", props)}>\n <path d=\"M10 11v6\" />\n <path d=\"M14 11v6\" />\n <path d=\"M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6\" />\n <path d=\"M3 6h18\" />\n <path d=\"M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2\" />\n </svg>\n );\n}\n\n/** lucide `archive` — the archived-rows glyph (ArchivedDisclosure). */\nexport function ArchiveIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"archive\", props)}>\n <rect width=\"20\" height=\"5\" x=\"2\" y=\"3\" rx=\"1\" />\n <path d=\"M4 8v11a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8\" />\n <path d=\"M10 12h4\" />\n </svg>\n );\n}\n\n/** lucide `more-horizontal` — the kebab/ellipsis glyph. */\nexport function MoreHorizontalIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"ellipsis\", props)}>\n <circle cx=\"12\" cy=\"12\" r=\"1\" />\n <circle cx=\"19\" cy=\"12\" r=\"1\" />\n <circle cx=\"5\" cy=\"12\" r=\"1\" />\n </svg>\n );\n}\n\n/** lucide `check` — the selected-row tick (CreatablePicker). */\nexport function CheckIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"check\", props)}>\n <path d=\"M20 6 9 17l-5-5\" />\n </svg>\n );\n}\n\n/** lucide `chevrons-up-down` — the combobox trigger glyph. */\nexport function ChevronsUpDownIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"chevrons-up-down\", props)}>\n <path d=\"m7 15 5 5 5-5\" />\n <path d=\"m7 9 5-5 5 5\" />\n </svg>\n );\n}\n\n/** lucide `external-link` — the manage-in-new-tab glyph. */\nexport function ExternalLinkIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"external-link\", props)}>\n <path d=\"M15 3h6v6\" />\n <path d=\"M10 14 21 3\" />\n <path d=\"M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6\" />\n </svg>\n );\n}\n\n/** lucide `lock` — the platform-governed vocabulary glyph. */\nexport function LockIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"lock\", props)}>\n <rect width=\"18\" height=\"11\" x=\"3\" y=\"11\" rx=\"2\" ry=\"2\" />\n <path d=\"M7 11V7a5 5 0 0 1 10 0v4\" />\n </svg>\n );\n}\n\n/** lucide `pencil` — the edit glyph (the table card's Edit action). */\nexport function PencilIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"pencil\", props)}>\n <path d=\"M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z\" />\n <path d=\"m15 5 4 4\" />\n </svg>\n );\n}\n\n/** lucide `message-square` — a row's comments (records-ui SectionCard). */\nexport function MessageSquareIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"message-square\", props)}>\n <path d=\"M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z\" />\n </svg>\n );\n}\n\n/** lucide `sticky-note` — a row's usage note (records-ui SectionCard). */\nexport function StickyNoteIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"sticky-note\", props)}>\n <path d=\"M16 3H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V8Z\" />\n <path d=\"M15 3v4a2 2 0 0 0 2 2h4\" />\n </svg>\n );\n}\n\n/** lucide `minus` — the decrease glyph (NumberStepper). */\nexport function MinusIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"minus\", props)}>\n <path d=\"M5 12h14\" />\n </svg>\n );\n}\n\n/** lucide `plus` — the create/add glyph. */\nexport function PlusIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"plus\", props)}>\n <path d=\"M5 12h14\" />\n <path d=\"M12 5v14\" />\n </svg>\n );\n}\n\n/** lucide `search` — the magnifier (the `@ai-matrx/design-system/icons` section). */\nexport function SearchIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"search\", props)}>\n <circle cx=\"11\" cy=\"11\" r=\"8\" />\n <path d=\"m21 21-4.3-4.3\" />\n </svg>\n );\n}\n\n/** lucide `list-filter` — a table's filter button (Mail's and Finder's filter). */\nexport function ListFilterIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"list-filter\", props)}>\n <path d=\"M3 6h18\" />\n <path d=\"M7 12h10\" />\n <path d=\"M10 18h4\" />\n </svg>\n );\n}\n\n/** lucide `pin` — pinned state (the `@ai-matrx/design-system/icons` section). */\nexport function PinIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"pin\", props)}>\n <path d=\"M12 17v5\" />\n <path d=\"M9 10.76a2 2 0 0 1-1.11 1.79l-1.78.9A2 2 0 0 0 5 15.24V16a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1v-.76a2 2 0 0 0-1.11-1.79l-1.78-.9A2 2 0 0 1 15 10.76V7a1 1 0 0 1 1-1 2 2 0 0 0 0-4H8a2 2 0 0 0 0 4 1 1 0 0 1 1 1z\" />\n </svg>\n );\n}\n\n/** lucide `x` — the dialog close glyph (host dialog module used lucide X). */\nexport function XIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"x\", props)}>\n <path d=\"M18 6 6 18\" />\n <path d=\"m6 6 12 12\" />\n </svg>\n );\n}\n\n/**\n * @radix-ui/react-icons components default to width/height 15 — the bare\n * `<ChevronUpIcon />` renders in Select's scroll buttons rely on it.\n */\nfunction radixProps(props: IconProps): React.SVGAttributes<SVGSVGElement> {\n return {\n xmlns: \"http://www.w3.org/2000/svg\",\n viewBox: \"0 0 15 15\",\n width: 15,\n height: 15,\n fill: \"none\",\n \"aria-hidden\": true,\n ...props,\n };\n}\n\n/** @radix-ui/react-icons `MagnifyingGlassIcon` — the command search glyph. */\nexport function MagnifyingGlassIcon(props: IconProps) {\n return (\n <svg {...radixProps(props)}>\n <path\n d=\"M10 6.5C10 8.433 8.433 10 6.5 10C4.567 10 3 8.433 3 6.5C3 4.567 4.567 3 6.5 3C8.433 3 10 4.567 10 6.5ZM9.30884 10.0159C8.53901 10.6318 7.56251 11 6.5 11C4.01472 11 2 8.98528 2 6.5C2 4.01472 4.01472 2 6.5 2C8.98528 2 11 4.01472 11 6.5C11 7.56251 10.6318 8.53901 10.0159 9.30884L12.8536 12.1464C13.0488 12.3417 13.0488 12.6583 12.8536 12.8536C12.6583 13.0488 12.3417 13.0488 12.1464 12.8536L9.30884 10.0159Z\"\n fill=\"currentColor\"\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n />\n </svg>\n );\n}\n\n/** @radix-ui/react-icons `CheckIcon` — the select item indicator glyph. */\nexport function RadixCheckIcon(props: IconProps) {\n return (\n <svg {...radixProps(props)}>\n <path\n d=\"M11.4669 3.72684C11.7558 3.91574 11.8369 4.30308 11.648 4.59198L7.39799 11.092C7.29783 11.2452 7.13556 11.3467 6.95402 11.3699C6.77247 11.3931 6.58989 11.3355 6.45446 11.2124L3.70446 8.71241C3.44905 8.48022 3.43023 8.08494 3.66242 7.82953C3.89461 7.57412 4.28989 7.55529 4.5453 7.78749L6.75292 9.79441L10.6018 3.90792C10.7907 3.61902 11.178 3.53795 11.4669 3.72684Z\"\n fill=\"currentColor\"\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n />\n </svg>\n );\n}\n\n/**\n * @radix-ui/react-icons `DividerHorizontalIcon` — the INDETERMINATE checkbox\n * glyph. Radix renders the indicator for both `true` and `\"indeterminate\"`, so\n * a half-selected \"select all\" that shows a full check states something false;\n * the two states get different glyphs on purpose.\n */\nexport function DividerHorizontalIcon(props: IconProps) {\n return (\n <svg {...radixProps(props)}>\n <path\n d=\"M2 7.5C2 7.22386 2.22386 7 2.5 7H12.5C12.7761 7 13 7.22386 13 7.5C13 7.77614 12.7761 8 12.5 8H2.5C2.22386 8 2 7.77614 2 7.5Z\"\n fill=\"currentColor\"\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n />\n </svg>\n );\n}\n\n/** @radix-ui/react-icons `DotFilledIcon` — the menu radio-item indicator. */\nexport function DotFilledIcon(props: IconProps) {\n return (\n <svg {...radixProps(props)}>\n <path\n d=\"M9.875 7.5C9.875 8.81168 8.81168 9.875 7.5 9.875C6.18832 9.875 5.125 8.81168 5.125 7.5C5.125 6.18832 6.18832 5.125 7.5 5.125C8.81168 5.125 9.875 6.18832 9.875 7.5Z\"\n fill=\"currentColor\"\n />\n </svg>\n );\n}\n\n/** @radix-ui/react-icons `ChevronRightIcon` — the submenu-trigger glyph. */\nexport function RadixChevronRightIcon(props: IconProps) {\n return (\n <svg {...radixProps(props)}>\n <path\n d=\"M6.1584 3.13508C6.35985 2.94621 6.67627 2.95642 6.86514 3.15788L10.6151 7.15788C10.7954 7.3502 10.7954 7.64949 10.6151 7.84182L6.86514 11.8418C6.67627 12.0433 6.35985 12.0535 6.1584 11.8646C5.95694 11.6757 5.94673 11.3593 6.1356 11.1579L9.565 7.49985L6.1356 3.84182C5.94673 3.64036 5.95694 3.32394 6.1584 3.13508Z\"\n fill=\"currentColor\"\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n />\n </svg>\n );\n}\n\n/** @radix-ui/react-icons `ChevronDownIcon` — the select trigger/scroll glyph. */\nexport function RadixChevronDownIcon(props: IconProps) {\n return (\n <svg {...radixProps(props)}>\n <path\n d=\"M3.13523 6.15803C3.3241 5.95657 3.64052 5.94637 3.84197 6.13523L7.5 9.56464L11.158 6.13523C11.3595 5.94637 11.6759 5.95657 11.8648 6.15803C12.0536 6.35949 12.0434 6.67591 11.842 6.86477L7.84197 10.6148C7.64964 10.7951 7.35036 10.7951 7.15803 10.6148L3.15803 6.86477C2.95657 6.67591 2.94637 6.35949 3.13523 6.15803Z\"\n fill=\"currentColor\"\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n />\n </svg>\n );\n}\n\n/** @radix-ui/react-icons `ChevronUpIcon` — the select scroll-up glyph. */\nexport function RadixChevronUpIcon(props: IconProps) {\n return (\n <svg {...radixProps(props)}>\n <path\n d=\"M3.13523 8.84197C3.3241 9.04343 3.64052 9.05363 3.84197 8.86477L7.5 5.43536L11.158 8.86477C11.3595 9.05363 11.6759 9.04343 11.8648 8.84197C12.0536 8.64051 12.0434 8.32409 11.842 8.13523L7.84197 4.38523C7.64964 4.20492 7.35036 4.20492 7.15803 4.38523L3.15803 8.13523C2.95657 8.32409 2.94637 8.64051 3.13523 8.84197Z\"\n fill=\"currentColor\"\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n />\n </svg>\n );\n}\n\n/** @radix-ui/react-icons `Cross2Icon` — the dialog/sheet close glyph. */\nexport function Cross2Icon(props: IconProps) {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 15 15\"\n fill=\"none\"\n aria-hidden\n {...props}\n >\n <path\n d=\"M11.7816 4.03157C12.0062 3.80702 12.0062 3.44295 11.7816 3.2184C11.5571 2.99385 11.193 2.99385 10.9685 3.2184L7.50005 6.68682L4.03164 3.2184C3.80708 2.99385 3.44301 2.99385 3.21846 3.2184C2.99391 3.44295 2.99391 3.80702 3.21846 4.03157L6.68688 7.49999L3.21846 10.9684C2.99391 11.193 2.99391 11.557 3.21846 11.7816C3.44301 12.0061 3.80708 12.0061 4.03164 11.7816L7.50005 8.31316L10.9685 11.7816C11.193 12.0061 11.5571 12.0061 11.7816 11.7816C12.0062 11.557 12.0062 11.193 11.7816 10.9684L8.31322 7.49999L11.7816 4.03157Z\"\n fill=\"currentColor\"\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n />\n </svg>\n );\n}\n\n/**\n * @radix-ui/react-icons `DragHandleDots2Icon` — the grip on `ResizableHandle`.\n * Inlined per C19: this package depends on no icon library.\n */\nexport function DragHandleDots2Icon(props: IconProps) {\n return (\n <svg {...radixProps(props)}>\n <path\n d=\"M4.5 2.5C5.05228 2.5 5.5 2.05228 5.5 1.5C5.5 0.947715 5.05228 0.5 4.5 0.5C3.94772 0.5 3.5 0.947715 3.5 1.5C3.5 2.05228 3.94772 2.5 4.5 2.5ZM4.5 6.5C5.05228 6.5 5.5 6.05229 5.5 5.5C5.5 4.94771 5.05228 4.5 4.5 4.5C3.94772 4.5 3.5 4.94771 3.5 5.5C3.5 6.05229 3.94772 6.5 4.5 6.5ZM5.5 9.5C5.5 10.0523 5.05228 10.5 4.5 10.5C3.94772 10.5 3.5 10.0523 3.5 9.5C3.5 8.94771 3.94772 8.5 4.5 8.5C5.05228 8.5 5.5 8.94771 5.5 9.5ZM4.5 14.5C5.05228 14.5 5.5 14.0523 5.5 13.5C5.5 12.9477 5.05228 12.5 4.5 12.5C3.94772 12.5 3.5 12.9477 3.5 13.5C3.5 14.0523 3.94772 14.5 4.5 14.5ZM11.5 1.5C11.5 2.05228 11.0523 2.5 10.5 2.5C9.94771 2.5 9.5 2.05228 9.5 1.5C9.5 0.947715 9.94771 0.5 10.5 0.5C11.0523 0.5 11.5 0.947715 11.5 1.5ZM10.5 6.5C11.0523 6.5 11.5 6.05229 11.5 5.5C11.5 4.94771 11.0523 4.5 10.5 4.5C9.94771 4.5 9.5 4.94771 9.5 5.5C9.5 6.05229 9.94771 6.5 10.5 6.5ZM11.5 9.5C11.5 10.0523 11.0523 10.5 10.5 10.5C9.94771 10.5 9.5 10.0523 9.5 9.5C9.5 8.94771 9.94771 8.5 10.5 8.5C11.0523 8.5 11.5 8.94771 11.5 9.5ZM10.5 14.5C11.0523 14.5 11.5 14.0523 11.5 13.5C11.5 12.9477 11.0523 12.5 10.5 12.5C9.94771 12.5 9.5 12.9477 9.5 13.5C9.5 14.0523 9.94771 14.5 10.5 14.5Z\"\n fill=\"currentColor\"\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n />\n </svg>\n );\n}\n\n/** lucide `star` — the saved-organization badge (OrganizationPicker). */\nexport function StarIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"star\", props)}>\n <path d=\"M11.525 2.295a.53.53 0 0 1 .95 0l2.31 4.679a2.123 2.123 0 0 0 1.595 1.16l5.166.756a.53.53 0 0 1 .294.904l-3.736 3.638a2.123 2.123 0 0 0-.611 1.878l.882 5.14a.53.53 0 0 1-.771.56l-4.618-2.428a2.122 2.122 0 0 0-1.973 0L6.396 21.01a.53.53 0 0 1-.77-.56l.881-5.139a2.122 2.122 0 0 0-.611-1.879L2.16 9.795a.53.53 0 0 1 .294-.906l5.165-.755a2.122 2.122 0 0 0 1.597-1.16z\" />\n </svg>\n );\n}\n\n/** lucide `building-2` — the organization glyph (OrganizationPicker trigger). */\nexport function Building2Icon(props: IconProps) {\n return (\n <svg {...lucideProps(\"building-2\", props)}>\n <path d=\"M6 22V4a2 2 0 0 1 2-2h8a2 2 0 0 1 2 2v18Z\" />\n <path d=\"M6 12H4a2 2 0 0 0-2 2v6a2 2 0 0 0 2 2h2\" />\n <path d=\"M18 9h2a2 2 0 0 1 2 2v9a2 2 0 0 1-2 2h-2\" />\n <path d=\"M10 6h4\" />\n <path d=\"M10 10h4\" />\n <path d=\"M10 14h4\" />\n <path d=\"M10 18h4\" />\n </svg>\n );\n}\n\n/** lucide `panel-left` — the sidebar toggle glyph. */\nexport function PanelLeftIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"panel-left\", props)}>\n <rect width=\"18\" height=\"18\" x=\"3\" y=\"3\" rx=\"2\" />\n <path d=\"M9 3v18\" />\n </svg>\n );\n}\n\n/** lucide `ellipsis-vertical` — a panel's \"more\" menu. */\nexport function MoreVerticalIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"ellipsis-vertical\", props)}>\n <circle cx=\"12\" cy=\"12\" r=\"1\" />\n <circle cx=\"12\" cy=\"5\" r=\"1\" />\n <circle cx=\"12\" cy=\"19\" r=\"1\" />\n </svg>\n );\n}\n\n/** lucide `maximize-2` — expand a panel. */\nexport function Maximize2Icon(props: IconProps) {\n return (\n <svg {...lucideProps(\"maximize-2\", props)}>\n <path d=\"M15 3h6v6\" />\n <path d=\"m21 3-7 7\" />\n <path d=\"m3 21 7-7\" />\n <path d=\"M9 21H3v-6\" />\n </svg>\n );\n}\n\n/** lucide `minimize-2` — restore an expanded panel. */\nexport function Minimize2Icon(props: IconProps) {\n return (\n <svg {...lucideProps(\"minimize-2\", props)}>\n <path d=\"m14 10 7-7\" />\n <path d=\"M20 10h-6V4\" />\n <path d=\"m3 21 7-7\" />\n <path d=\"M4 14h6v6\" />\n </svg>\n );\n}\n\n/** lucide `arrow-left`. */\nexport function ArrowLeftIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"arrow-left\", props)}>\n <path d=\"m12 19-7-7 7-7\" />\n <path d=\"M19 12H5\" />\n </svg>\n );\n}\n\n/** lucide `arrow-right`. */\nexport function ArrowRightIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"arrow-right\", props)}>\n <path d=\"M5 12h14\" />\n <path d=\"m12 5 7 7-7 7\" />\n </svg>\n );\n}\n\n/** lucide `arrow-up` — the swipe deck's up edge. */\nexport function ArrowUpIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"arrow-up\", props)}>\n <path d=\"m5 12 7-7 7 7\" />\n <path d=\"M12 19V5\" />\n </svg>\n );\n}\n\n/** lucide `arrow-down` — the swipe deck's down edge. */\nexport function ArrowDownIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"arrow-down\", props)}>\n <path d=\"M12 5v14\" />\n <path d=\"m19 12-7 7-7-7\" />\n </svg>\n );\n}\n\n/** lucide `undo-2` — take back the last change. */\nexport function Undo2Icon(props: IconProps) {\n return (\n <svg {...lucideProps(\"undo-2\", props)}>\n <path d=\"M9 14 4 9l5-5\" />\n <path d=\"M4 9h10.5a5.5 5.5 0 0 1 5.5 5.5a5.5 5.5 0 0 1-5.5 5.5H11\" />\n </svg>\n );\n}\n\n/** lucide `eraser` — forget a marked part. */\nexport function EraserIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"eraser\", props)}>\n <path d=\"m7 21-4.3-4.3c-1-1-1-2.5 0-3.4l9.6-9.6c1-1 2.5-1 3.4 0l5.6 5.6c1 1 1 2.5 0 3.4L13 21\" />\n <path d=\"M22 21H7\" />\n <path d=\"m5 11 9 9\" />\n </svg>\n );\n}\n\n/** lucide `rotate-cw` — reload. */\nexport function RotateCwIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"rotate-cw\", props)}>\n <path d=\"M21 12a9 9 0 1 1-9-9c2.52 0 4.93 1 6.74 2.74L21 8\" />\n <path d=\"M21 3v5h-5\" />\n </svg>\n );\n}\n\n/** lucide `globe` — a web page with no favicon. */\nexport function GlobeIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"globe\", props)}>\n <circle cx=\"12\" cy=\"12\" r=\"10\" />\n <path d=\"M12 2a14.5 14.5 0 0 0 0 20 14.5 14.5 0 0 0 0-20\" />\n <path d=\"M2 12h20\" />\n </svg>\n );\n}\n\n/** lucide `calendar` — the date field's glyph. */\nexport function CalendarIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"calendar\", props)}>\n <path d=\"M8 2v4\" />\n <path d=\"M16 2v4\" />\n <rect width=\"18\" height=\"18\" x=\"3\" y=\"4\" rx=\"2\" />\n <path d=\"M3 10h18\" />\n </svg>\n );\n}\n\n/** lucide `clock` — the time field's glyph. */\nexport function ClockIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"clock\", props)}>\n <circle cx=\"12\" cy=\"12\" r=\"10\" />\n <polyline points=\"12 6 12 12 16 14\" />\n </svg>\n );\n}\n\n/** lucide `refresh-cw` — retry / reload. */\nexport function RefreshCwIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"refresh-cw\", props)}>\n <path d=\"M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8\" />\n <path d=\"M21 3v5h-5\" />\n <path d=\"M21 12a9 9 0 0 1-9 9 9.75 9.75 0 0 1-6.74-2.74L3 16\" />\n <path d=\"M8 16H3v5\" />\n </svg>\n );\n}\n\n/** lucide `triangle-alert` (alias `AlertTriangle`) — an error or warning. */\nexport function AlertTriangleIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"triangle-alert\", props)}>\n <path d=\"m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3\" />\n <path d=\"M12 9v4\" />\n <path d=\"M12 17h.01\" />\n </svg>\n );\n}\n\n/** lucide `circle-check` — a passing state. */\nexport function CircleCheckIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"circle-check\", props)}>\n <circle cx=\"12\" cy=\"12\" r=\"10\" />\n <path d=\"m16 9-5.5 5.5L8 12\" />\n </svg>\n );\n}\n\n/** lucide `circle-question-mark` (alias `CircleHelp`) — field help. */\nexport function CircleHelpIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"circle-question-mark\", props)}>\n <circle cx=\"12\" cy=\"12\" r=\"10\" />\n <path d=\"M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3\" />\n <path d=\"M12 17h.01\" />\n </svg>\n );\n}\n\n/** lucide `circle-x` — a failing state. */\nexport function CircleXIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"circle-x\", props)}>\n <circle cx=\"12\" cy=\"12\" r=\"10\" />\n <path d=\"m15 9-6 6\" />\n <path d=\"m9 9 6 6\" />\n </svg>\n );\n}\n\n/** lucide `info` — a row label's help glyph (controls `PropertyRow`). */\nexport function InfoIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"info\", props)}>\n <circle cx=\"12\" cy=\"12\" r=\"10\" />\n <path d=\"M12 16v-4\" />\n <path d=\"M12 8h.01\" />\n </svg>\n );\n}\n\n/** lucide `circle-dot` — the \"Get help from Matrx AI\" button glyph (controls `HelpIcon`). */\nexport function CircleDotIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"circle-dot\", props)}>\n <circle cx=\"12\" cy=\"12\" r=\"10\" />\n <circle cx=\"12\" cy=\"12\" r=\"1\" />\n </svg>\n );\n}\n\n/** lucide `copy` — the Peek's token chip (copy the exact token). */\nexport function CopyIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"copy\", props)}>\n <rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\" />\n <path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\" />\n </svg>\n );\n}\n\n/** lucide `upload` (moved from @ai-matrx/media). */\nexport function UploadIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"upload\", props)}>\n <path d=\"M12 3v12\" />\n <path d=\"m17 8-5-5-5 5\" />\n <path d=\"M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4\" />\n </svg>\n );\n}\n\n/** lucide `circle-alert` — an error or attention state. */\nexport function CircleAlertIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"circle-alert\", props)}>\n <circle cx=\"12\" cy=\"12\" r=\"10\" />\n <line x1=\"12\" x2=\"12\" y1=\"8\" y2=\"12\" />\n <line x1=\"12\" x2=\"12.01\" y1=\"16\" y2=\"16\" />\n </svg>\n );\n}\n\n/** lucide `panel-right` — a side pane toggle. */\nexport function PanelRightIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"panel-right\", props)}>\n <rect width=\"18\" height=\"18\" x=\"3\" y=\"3\" rx=\"2\" />\n <path d=\"M15 3v18\" />\n </svg>\n );\n}\n\n/** lucide `bell` — notifications. */\nexport function BellIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"bell\", props)}>\n <path d=\"M10.268 21a2 2 0 0 0 3.464 0\" />\n <path d=\"M3.262 15.326A1 1 0 0 0 4 17h16a1 1 0 0 0 .74-1.673C19.41 13.956 18 12.499 18 8A6 6 0 0 0 6 8c0 4.499-1.411 5.956-2.738 7.326\" />\n </svg>\n );\n}\n\n/** lucide `eye-off` — hidden. */\nexport function EyeOffIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"eye-off\", props)}>\n <path d=\"M10.733 5.076a10.744 10.744 0 0 1 11.205 6.575 1 1 0 0 1 0 .696 10.747 10.747 0 0 1-1.444 2.49\" />\n <path d=\"M14.084 14.158a3 3 0 0 1-4.242-4.242\" />\n <path d=\"M17.479 17.499a10.75 10.75 0 0 1-15.417-5.151 1 1 0 0 1 0-.696 10.75 10.75 0 0 1 4.446-5.143\" />\n <path d=\"m2 2 20 20\" />\n </svg>\n );\n}\n\n/** lucide `app-window` — open as a window. */\nexport function AppWindowIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"app-window\", props)}>\n <rect x=\"2\" y=\"4\" width=\"20\" height=\"16\" rx=\"2\" />\n <path d=\"M10 4v4\" />\n <path d=\"M2 8h20\" />\n <path d=\"M6 4v4\" />\n </svg>\n );\n}\n\n/** lucide `video` — a video call or clip. */\nexport function VideoIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"video\", props)}>\n <path d=\"m16 13 5.223 3.482a.5.5 0 0 0 .777-.416V7.87a.5.5 0 0 0-.752-.432L16 10.5\" />\n <rect x=\"2\" y=\"6\" width=\"14\" height=\"12\" rx=\"2\" />\n </svg>\n );\n}\n\n/** lucide `phone` — a voice call. */\nexport function PhoneIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"phone\", props)}>\n <path d=\"M13.832 16.568a1 1 0 0 0 1.213-.303l.355-.465A2 2 0 0 1 17 15h3a2 2 0 0 1 2 2v3a2 2 0 0 1-2 2A18 18 0 0 1 2 4a2 2 0 0 1 2-2h3a2 2 0 0 1 2 2v3a2 2 0 0 1-.8 1.6l-.468.351a1 1 0 0 0-.292 1.233 14 14 0 0 0 6.392 6.384\" />\n </svg>\n );\n}\n\n/** lucide `sparkles` — AI. */\nexport function SparklesIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"sparkles\", props)}>\n <path d=\"M11.017 2.814a1 1 0 0 1 1.966 0l1.051 5.558a2 2 0 0 0 1.594 1.594l5.558 1.051a1 1 0 0 1 0 1.966l-5.558 1.051a2 2 0 0 0-1.594 1.594l-1.051 5.558a1 1 0 0 1-1.966 0l-1.051-5.558a2 2 0 0 0-1.594-1.594l-5.558-1.051a1 1 0 0 1 0-1.966l5.558-1.051a2 2 0 0 0 1.594-1.594z\" />\n <path d=\"M20 2v4\" />\n <path d=\"M22 4h-4\" />\n <circle cx=\"4\" cy=\"20\" r=\"2\" />\n </svg>\n );\n}\n\n/** lucide `panels-top-left` — a layout. */\nexport function PanelsTopLeftIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"panels-top-left\", props)}>\n <rect width=\"18\" height=\"18\" x=\"3\" y=\"3\" rx=\"2\" />\n <path d=\"M3 9h18\" />\n <path d=\"M9 21V9\" />\n </svg>\n );\n}\n\n/** lucide `download`. */\nexport function DownloadIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"download\", props)}>\n <path d=\"M12 15V3\" />\n <path d=\"M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4\" />\n <path d=\"m7 10 5 5 5-5\" />\n </svg>\n );\n}\n\n/** lucide `settings`. */\nexport function SettingsIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"settings\", props)}>\n <path d=\"M9.671 4.136a2.34 2.34 0 0 1 4.659 0 2.34 2.34 0 0 0 3.319 1.915 2.34 2.34 0 0 1 2.33 4.033 2.34 2.34 0 0 0 0 3.831 2.34 2.34 0 0 1-2.33 4.033 2.34 2.34 0 0 0-3.319 1.915 2.34 2.34 0 0 1-4.659 0 2.34 2.34 0 0 0-3.32-1.915 2.34 2.34 0 0 1-2.33-4.033 2.34 2.34 0 0 0 0-3.831A2.34 2.34 0 0 1 6.35 6.051a2.34 2.34 0 0 0 3.319-1.915\" />\n <circle cx=\"12\" cy=\"12\" r=\"3\" />\n </svg>\n );\n}\n\n/** lucide `users`. */\nexport function UsersIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"users\", props)}>\n <path d=\"M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2\" />\n <path d=\"M16 3.128a4 4 0 0 1 0 7.744\" />\n <path d=\"M22 21v-2a4 4 0 0 0-3-3.87\" />\n <circle cx=\"9\" cy=\"7\" r=\"4\" />\n </svg>\n );\n}\n\n/** lucide `grip-vertical` — a drag handle. */\nexport function GripVerticalIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"grip-vertical\", props)}>\n <circle cx=\"9\" cy=\"12\" r=\"1\" />\n <circle cx=\"9\" cy=\"5\" r=\"1\" />\n <circle cx=\"9\" cy=\"19\" r=\"1\" />\n <circle cx=\"15\" cy=\"12\" r=\"1\" />\n <circle cx=\"15\" cy=\"5\" r=\"1\" />\n <circle cx=\"15\" cy=\"19\" r=\"1\" />\n </svg>\n );\n}\n\n/** lucide `history`. */\nexport function HistoryIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"history\", props)}>\n <path d=\"M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8\" />\n <path d=\"M3 3v5h5\" />\n <path d=\"M12 7v5l4 2\" />\n </svg>\n );\n}\n\n/** lucide `workflow`. */\nexport function WorkflowIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"workflow\", props)}>\n <rect width=\"8\" height=\"8\" x=\"3\" y=\"3\" rx=\"2\" />\n <path d=\"M7 11v4a2 2 0 0 0 2 2h4\" />\n <rect width=\"8\" height=\"8\" x=\"13\" y=\"13\" rx=\"2\" />\n </svg>\n );\n}\n\n// ---- Glyphs consolidated from the packages above the design system (one glyph home). ----\n\n/** lucide `activities` (moved from @ai-matrx/meet). */\nexport function ActivitiesIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"activities\", props)}>\n <path d=\"M8.3 10a.7.7 0 0 1-.626-1.079L11.4 3a.7.7 0 0 1 1.198-.043L16.3 8.9a.7.7 0 0 1-.572 1.1Z\" />\n <rect x=\"3\" y=\"14\" width=\"7\" height=\"7\" rx=\"1\" />\n <circle cx=\"17.5\" cy=\"17.5\" r=\"3.5\" />\n </svg>\n );\n}\n\n/** lucide `arrow-down-to-line` (moved from @ai-matrx/agents). */\nexport function ArrowDownToLineIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"arrow-down-to-line\", props)}>\n <path d=\"M12 17V3\" />\n <path d=\"m6 11 6 6 6-6\" />\n <path d=\"M19 21H5\" />\n </svg>\n );\n}\n\n/** lucide `arrow-left-right` (moved from @ai-matrx/diff). */\nexport function ArrowLeftRightIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"arrow-left-right\", props)}>\n <path d=\"M8 3 4 7l4 4\" />\n <path d=\"M4 7h16\" />\n <path d=\"m16 21 4-4-4-4\" />\n <path d=\"M20 17H4\" />\n </svg>\n );\n}\n\n/** lucide `arrow-left-to-line` (moved from @ai-matrx/summon). */\nexport function ArrowLeftToLineIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"arrow-left-to-line\", props)}>\n <path d=\"M3 19V5\" />\n <path d=\"m13 6-6 6 6 6\" />\n <path d=\"M7 12h14\" />\n </svg>\n );\n}\n\n/** lucide `atom` (moved from @ai-matrx/agents). */\nexport function AtomIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"atom\", props)}>\n <circle cx=\"12\" cy=\"12\" r=\"1\" />\n <path d=\"M20.2 20.2c2.04-2.03.02-7.36-4.5-11.9-4.54-4.52-9.87-6.54-11.9-4.5-2.04 2.03-.02 7.36 4.5 11.9 4.54 4.52 9.87 6.54 11.9 4.5Z\" />\n <path d=\"M15.7 15.7c4.52-4.54 6.54-9.87 4.5-11.9-2.03-2.04-7.36-.02-11.9 4.5-4.52 4.54-6.54 9.87-4.5 11.9 2.03 2.04 7.36.02 11.9-4.5Z\" />\n </svg>\n );\n}\n\n/** lucide `audio-lines` (moved from @ai-matrx/content-ir). */\nexport function AudioLinesIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"audio-lines\", props)}>\n <path d=\"M2 10v3\" />\n <path d=\"M6 6v11\" />\n <path d=\"M10 3v18\" />\n <path d=\"M14 8v7\" />\n <path d=\"M18 5v13\" />\n <path d=\"M22 10v3\" />\n </svg>\n );\n}\n\n/** lucide `boxes` (moved from @ai-matrx/associations). */\nexport function BoxesIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"boxes\", props)}>\n <path d=\"M2.97 12.92A2 2 0 0 0 2 14.63v3.24a2 2 0 0 0 .97 1.71l3 1.8a2 2 0 0 0 2.06 0L12 19v-5.5l-5-3-4.03 2.42Z\" />\n <path d=\"m7 16.5-4.74-2.85\" />\n <path d=\"m7 16.5 5-3\" />\n <path d=\"M7 16.5v5.17\" />\n <path d=\"M12 13.5V19l3.97 2.38a2 2 0 0 0 2.06 0l3-1.8a2 2 0 0 0 .97-1.71v-3.24a2 2 0 0 0-.97-1.71L17 10.5l-5 3Z\" />\n <path d=\"m17 16.5-5-3\" />\n <path d=\"m17 16.5 4.74-2.85\" />\n <path d=\"M17 16.5v5.17\" />\n <path d=\"M7.97 4.42A2 2 0 0 0 7 6.13v4.37l5 3 5-3V6.13a2 2 0 0 0-.97-1.71l-3-1.8a2 2 0 0 0-2.06 0l-3 1.8Z\" />\n <path d=\"M12 8 7.26 5.15\" />\n <path d=\"m12 8 4.74-2.85\" />\n <path d=\"M12 13.5V8\" />\n </svg>\n );\n}\n\n/** lucide `braces` (moved from @ai-matrx/media). */\nexport function BracesIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"braces\", props)}>\n <path d=\"M8 3H7a2 2 0 0 0-2 2v5a2 2 0 0 1-2 2 2 2 0 0 1 2 2v5c0 1.1.9 2 2 2h1\" />\n <path d=\"M16 21h1a2 2 0 0 0 2-2v-5c0-1.1.9-2 2-2a2 2 0 0 1-2-2V5a2 2 0 0 0-2-2h-1\" />\n </svg>\n );\n}\n\n/** lucide `breakout` (moved from @ai-matrx/meet). */\nexport function BreakoutIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"breakout\", props)}>\n <rect width=\"7\" height=\"18\" x=\"3\" y=\"3\" rx=\"1\" />\n <rect width=\"7\" height=\"7\" x=\"14\" y=\"3\" rx=\"1\" />\n <rect width=\"7\" height=\"7\" x=\"14\" y=\"14\" rx=\"1\" />\n </svg>\n );\n}\n\n/** lucide `camera` (moved from @ai-matrx/meet). */\nexport function CameraIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"camera\", props)}>\n <path d=\"m23 7-7 5 7 5V7Z\" />\n <rect x=\"1\" y=\"5\" width=\"15\" height=\"14\" rx=\"2\" />\n </svg>\n );\n}\n\n/** lucide `camera-off` (moved from @ai-matrx/meet). */\nexport function CameraOffIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"camera-off\", props)}>\n <path d=\"M2 2l20 20\" />\n <path d=\"M10.66 5H14a2 2 0 0 1 2 2v3.34l1 1L23 7v10\" />\n <path d=\"M16 16a2 2 0 0 1-2 2H3a2 2 0 0 1-2-2V7a2 2 0 0 1 2-2h2\" />\n </svg>\n );\n}\n\n/** lucide `captions` (moved from @ai-matrx/meet). */\nexport function CaptionsIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"captions\", props)}>\n <rect x=\"3\" y=\"5\" width=\"18\" height=\"14\" rx=\"2\" />\n <path d=\"M10 10.5a2 2 0 1 0 0 3M16 10.5a2 2 0 1 0 0 3\" />\n </svg>\n );\n}\n\n/** lucide `chat-bubble` (moved from @ai-matrx/coding-sessions). */\nexport function ChatBubbleIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"chat-bubble\", props)}>\n <path d=\"M20 12.5a7.5 7.5 0 0 1-10.9 6.7L4 20.5l1.3-4.6A7.5 7.5 0 1 1 20 12.5z\" />\n </svg>\n );\n}\n\n/** lucide `chat` (moved from @ai-matrx/meet). */\nexport function ChatIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"chat\", props)}>\n <path d=\"M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2Z\" />\n </svg>\n );\n}\n\n/** lucide `check-circle-2` (moved from @ai-matrx/media). */\nexport function CheckCircle2Icon(props: IconProps) {\n return (\n <svg {...lucideProps(\"check-circle-2\", props)}>\n <path d=\"M21.801 10A10 10 0 1 1 17 3.335\" />\n <path d=\"m9 11 3 3L22 4\" />\n </svg>\n );\n}\n\n/** lucide `chevron-up` (moved from @ai-matrx/meet). */\nexport function ChevronUpIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"chevron-up\", props)}>\n <path d=\"m6 15 6-6 6 6\" />\n </svg>\n );\n}\n\n/** lucide `chevrons-down-up` (moved from @ai-matrx/diff). */\nexport function ChevronsDownUpIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"chevrons-down-up\", props)}>\n <path d=\"m7 20 5-5 5 5\" />\n <path d=\"m7 4 5 5 5-5\" />\n </svg>\n );\n}\n\n/** lucide `clock-3` (moved from @ai-matrx/diff). */\nexport function Clock3Icon(props: IconProps) {\n return (\n <svg {...lucideProps(\"clock-3\", props)}>\n <circle cx=\"12\" cy=\"12\" r=\"10\" />\n <path d=\"M12 6v6h4\" />\n </svg>\n );\n}\n\n/** lucide `code-2` (moved from @ai-matrx/office). */\nexport function Code2Icon(props: IconProps) {\n return (\n <svg {...lucideProps(\"code-2\", props)}>\n <path d=\"m18 16 4-4-4-4\" />\n <path d=\"m6 8-4 4 4 4\" />\n <path d=\"m14.5 4-5 16\" />\n </svg>\n );\n}\n\n/** lucide `code` (moved from @ai-matrx/media). */\nexport function CodeIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"code\", props)}>\n <path d=\"m16 18 6-6-6-6\" />\n <path d=\"m8 6-6 6 6 6\" />\n </svg>\n );\n}\n\n/** lucide `columns-2` (moved from @ai-matrx/diff). */\nexport function Columns2Icon(props: IconProps) {\n return (\n <svg {...lucideProps(\"columns-2\", props)}>\n <rect width=\"18\" height=\"18\" x=\"3\" y=\"3\" rx=\"2\" />\n <path d=\"M12 3v18\" />\n </svg>\n );\n}\n\n/** lucide `corner-down-right` (moved from @ai-matrx/associations). */\nexport function CornerDownRightIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"corner-down-right\", props)}>\n <polyline points=\"15 10 20 15 15 20\" />\n <path d=\"M4 4v7a4 4 0 0 0 4 4h12\" />\n </svg>\n );\n}\n\n/** lucide `database` (moved from @ai-matrx/media). */\nexport function DatabaseIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"database\", props)}>\n <ellipse cx=\"12\" cy=\"5\" rx=\"9\" ry=\"3\" />\n <path d=\"M3 5V19A9 3 0 0 0 21 19V5\" />\n <path d=\"M3 12A9 3 0 0 0 21 12\" />\n </svg>\n );\n}\n\n/** lucide `dock` (moved from @ai-matrx/canvas). */\nexport function DockIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"dock\", props)}>\n <path d=\"M21 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h6\" />\n <path d=\"M21 3 12 12\" />\n <path d=\"M12 6v6h6\" />\n </svg>\n );\n}\n\n/** lucide `expand` (moved from @ai-matrx/detail). */\nexport function ExpandIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"expand\", props)}>\n <path d=\"m15 15 6 6\" />\n <path d=\"m15 9 6-6\" />\n <path d=\"M21 16v5h-5\" />\n <path d=\"M21 8V3h-5\" />\n <path d=\"M3 16v5h5\" />\n <path d=\"m3 21 6-6\" />\n <path d=\"M3 8V3h5\" />\n <path d=\"M9 9 3 3\" />\n </svg>\n );\n}\n\n/** lucide `eye` (moved from @ai-matrx/agents). */\nexport function EyeIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"eye\", props)}>\n <path d=\"M2.062 12.348a1 1 0 0 1 0-.696 10.75 10.75 0 0 1 19.876 0 1 1 0 0 1 0 .696 10.75 10.75 0 0 1-19.876 0\" />\n <circle cx=\"12\" cy=\"12\" r=\"3\" />\n </svg>\n );\n}\n\n/** lucide `file-archive` (moved from @ai-matrx/content-ir). */\nexport function FileArchiveIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"file-archive\", props)}>\n <path d=\"M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z\" />\n <path d=\"M14 2v5a1 1 0 0 0 1 1h5\" />\n <path d=\"M10 6h1\" />\n <path d=\"M10 10h1\" />\n <circle cx=\"10\" cy=\"16\" r=\"2\" />\n <path d=\"M10 2v12\" />\n </svg>\n );\n}\n\n/** lucide `file-audio` (moved from @ai-matrx/media). */\nexport function FileAudioIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"file-audio\", props)}>\n <path d=\"M4 6.835V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.706.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2h-.343\" />\n <path d=\"M14 2v5a1 1 0 0 0 1 1h5\" />\n <path d=\"M2 19a2 2 0 0 1 4 0v1a2 2 0 0 1-4 0v-4a6 6 0 0 1 12 0v4a2 2 0 0 1-4 0v-1a2 2 0 0 1 4 0\" />\n </svg>\n );\n}\n\n/** lucide `file-code` (moved from @ai-matrx/media). */\nexport function FileCodeIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"file-code\", props)}>\n <path d=\"M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z\" />\n <path d=\"M14 2v5a1 1 0 0 0 1 1h5\" />\n <path d=\"M10 12.5 8 15l2 2.5\" />\n <path d=\"m14 12.5 2 2.5-2 2.5\" />\n </svg>\n );\n}\n\n/** lucide `file-json` (moved from @ai-matrx/media). */\nexport function FileJsonIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"file-json\", props)}>\n <path d=\"M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z\" />\n <path d=\"M14 2v5a1 1 0 0 0 1 1h5\" />\n <path d=\"M10 12a1 1 0 0 0-1 1v1a1 1 0 0 1-1 1 1 1 0 0 1 1 1v1a1 1 0 0 0 1 1\" />\n <path d=\"M14 18a1 1 0 0 0 1-1v-1a1 1 0 0 1 1-1 1 1 0 0 1-1-1v-1a1 1 0 0 0-1-1\" />\n </svg>\n );\n}\n\n/** lucide `file` (moved from @ai-matrx/media). */\nexport function FilePageIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"file\", props)}>\n <path d=\"M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z\" />\n <path d=\"M14 2v5a1 1 0 0 0 1 1h5\" />\n </svg>\n );\n}\n\n/** lucide `file-plus` (moved from @ai-matrx/content-ir). */\nexport function FilePlusIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"file-plus\", props)}>\n <path d=\"M4 22h14a2 2 0 0 0 2-2V7l-5-5H6a2 2 0 0 0-2 2v4\" />\n <path d=\"M14 2v4a2 2 0 0 0 2 2h4\" />\n <path d=\"M3 15h6\" />\n <path d=\"M6 12v6\" />\n </svg>\n );\n}\n\n/** lucide `file-spreadsheet` (moved from @ai-matrx/media). */\nexport function FileSpreadsheetIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"file-spreadsheet\", props)}>\n <path d=\"M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z\" />\n <path d=\"M14 2v5a1 1 0 0 0 1 1h5\" />\n <path d=\"M8 13h2\" />\n <path d=\"M14 13h2\" />\n <path d=\"M8 17h2\" />\n <path d=\"M14 17h2\" />\n </svg>\n );\n}\n\n/** lucide `file-text` (moved from @ai-matrx/media). */\nexport function FileTextIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"file-text\", props)}>\n <path d=\"M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z\" />\n <path d=\"M14 2v5a1 1 0 0 0 1 1h5\" />\n <path d=\"M10 9H8\" />\n <path d=\"M16 13H8\" />\n <path d=\"M16 17H8\" />\n </svg>\n );\n}\n\n/** lucide `file-type` (moved from @ai-matrx/media). */\nexport function FileTypeIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"file-type\", props)}>\n <path d=\"M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z\" />\n <path d=\"M14 2v5a1 1 0 0 0 1 1h5\" />\n <path d=\"M11 18h2\" />\n <path d=\"M12 12v6\" />\n <path d=\"M9 13v-.5a.5.5 0 0 1 .5-.5h5a.5.5 0 0 1 .5.5v.5\" />\n </svg>\n );\n}\n\n/** lucide `file-video` (moved from @ai-matrx/media). */\nexport function FileVideoIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"file-video\", props)}>\n <path d=\"M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z\" />\n <path d=\"M14 2v5a1 1 0 0 0 1 1h5\" />\n <path d=\"M15.033 13.44a.647.647 0 0 1 0 1.12l-4.065 2.352a.645.645 0 0 1-.968-.56v-4.704a.645.645 0 0 1 .967-.56z\" />\n </svg>\n );\n}\n\n/** lucide `film` (moved from @ai-matrx/content-ir). */\nexport function FilmIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"film\", props)}>\n <rect width=\"18\" height=\"18\" x=\"3\" y=\"3\" rx=\"2\" />\n <path d=\"M7 3v18\" />\n <path d=\"M3 7.5h4\" />\n <path d=\"M3 12h18\" />\n <path d=\"M3 16.5h4\" />\n <path d=\"M17 3v18\" />\n <path d=\"M17 7.5h4\" />\n <path d=\"M17 16.5h4\" />\n </svg>\n );\n}\n\n/** lucide `flag` (moved from @ai-matrx/meet). */\nexport function FlagIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"flag\", props)}>\n <path d=\"M4 15s1-1 4-1 5 2 8 2 4-1 4-1V3s-1 1-4 1-5-2-8-2-4 1-4 1z\" />\n <line x1=\"4\" x2=\"4\" y1=\"22\" y2=\"15\" />\n </svg>\n );\n}\n\n/** lucide `flip-horizontal-2` (moved from @ai-matrx/capture). */\nexport function FlipHorizontal2Icon(props: IconProps) {\n return (\n <svg {...lucideProps(\"flip-horizontal-2\", props)}>\n <path d=\"m3 7 5 5-5 5V7\" />\n <path d=\"m21 7-5 5 5 5V7\" />\n <path d=\"M12 20v2\" />\n <path d=\"M12 14v2\" />\n <path d=\"M12 8v2\" />\n <path d=\"M12 2v2\" />\n </svg>\n );\n}\n\n/** lucide `fold-vertical` (moved from @ai-matrx/diff). */\nexport function FoldVerticalIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"fold-vertical\", props)}>\n <path d=\"M12 22v-6\" />\n <path d=\"M12 8V2\" />\n <path d=\"M4 12H2\" />\n <path d=\"M10 12H8\" />\n <path d=\"M16 12h-2\" />\n <path d=\"M22 12h-2\" />\n <path d=\"m15 19-3-3-3 3\" />\n <path d=\"m15 5-3 3-3-3\" />\n </svg>\n );\n}\n\n/** lucide `folder` (moved from @ai-matrx/media). */\nexport function FolderIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"folder\", props)}>\n <path d=\"M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z\" />\n </svg>\n );\n}\n\n/** lucide `folder-open` (moved from @ai-matrx/media). */\nexport function FolderOpenIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"folder-open\", props)}>\n <path d=\"m6 14 1.5-2.9A2 2 0 0 1 9.24 10H20a2 2 0 0 1 1.94 2.5l-1.54 6a2 2 0 0 1-1.95 1.5H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h3.9a2 2 0 0 1 1.69.9l.81 1.2a2 2 0 0 0 1.67.9H18a2 2 0 0 1 2 2v2\" />\n </svg>\n );\n}\n\n/** lucide `git-merge` (moved from @ai-matrx/diff). */\nexport function GitMergeIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"git-merge\", props)}>\n <circle cx=\"18\" cy=\"18\" r=\"3\" />\n <circle cx=\"6\" cy=\"6\" r=\"3\" />\n <path d=\"M6 21V9a9 9 0 0 0 9 9\" />\n </svg>\n );\n}\n\n/** lucide `graduation-cap` (moved from @ai-matrx/office). */\nexport function GraduationCapIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"graduation-cap\", props)}>\n <path d=\"M21.42 10.922a1 1 0 0 0-.019-1.838L12.83 5.18a2 2 0 0 0-1.66 0L2.6 9.08a1 1 0 0 0 0 1.832l8.57 3.908a2 2 0 0 0 1.66 0z\" />\n <path d=\"M22 10v6\" />\n <path d=\"M6 12.5V16a6 3 0 0 0 12 0v-3.5\" />\n </svg>\n );\n}\n\n/** lucide `grid-3x-3` (moved from @ai-matrx/capture). */\nexport function Grid3x3Icon(props: IconProps) {\n return (\n <svg {...lucideProps(\"grid-3x-3\", props)}>\n <rect width=\"18\" height=\"18\" x=\"3\" y=\"3\" rx=\"2\" />\n <path d=\"M3 9h18\" />\n <path d=\"M3 15h18\" />\n <path d=\"M9 3v18\" />\n <path d=\"M15 3v18\" />\n </svg>\n );\n}\n\n/** lucide `grip` (moved from @ai-matrx/capture). */\nexport function GripIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"grip\", props)}>\n <circle cx=\"12\" cy=\"5\" r=\"1\" />\n <circle cx=\"19\" cy=\"5\" r=\"1\" />\n <circle cx=\"5\" cy=\"5\" r=\"1\" />\n <circle cx=\"12\" cy=\"12\" r=\"1\" />\n <circle cx=\"19\" cy=\"12\" r=\"1\" />\n <circle cx=\"5\" cy=\"12\" r=\"1\" />\n <circle cx=\"12\" cy=\"19\" r=\"1\" />\n <circle cx=\"19\" cy=\"19\" r=\"1\" />\n <circle cx=\"5\" cy=\"19\" r=\"1\" />\n </svg>\n );\n}\n\n/** lucide `grip-resize` (moved from @ai-matrx/associations). */\nexport function GripResizeIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"grip-resize\", props)}>\n <path d=\"M21 15 15 21\" />\n <path d=\"M21 20 20 21\" />\n </svg>\n );\n}\n\n/** lucide `hammer` (moved from @ai-matrx/agents). */\nexport function HammerIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"hammer\", props)}>\n <path d=\"m15 12-8.5 8.5c-.83.83-2.17.83-3 0 0 0 0 0 0 0a2.12 2.12 0 0 1 0-3L12 9\" />\n <path d=\"M17.64 15 22 10.64\" />\n <path d=\"m20.91 11.7-1.25-1.25c-.6-.6-.93-1.4-.93-2.25v-.86L16.01 4.6a5.56 5.56 0 0 0-3.94-1.64H9l.92.82A6.18 6.18 0 0 1 12 8.4v1.56l2 2h2.47l2.26 1.91\" />\n </svg>\n );\n}\n\n/** lucide `hand` (moved from @ai-matrx/meet). */\nexport function HandIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"hand\", props)}>\n <path d=\"M18 11V6a2 2 0 0 0-4 0v5\" />\n <path d=\"M14 10V4a2 2 0 0 0-4 0v7\" />\n <path d=\"M10 10.5V6a2 2 0 0 0-4 0v8\" />\n <path d=\"M18 8a2 2 0 1 1 4 0v6a8 8 0 0 1-8 8h-2a8 8 0 0 1-8-8v-1a2 2 0 1 1 4 0\" />\n </svg>\n );\n}\n\n/** lucide `handoff` (moved from @ai-matrx/coding-sessions). */\nexport function HandoffIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"handoff\", props)}>\n <path d=\"M5 12h12M13 7l5 5-5 5\" />\n <path d=\"M5 5v14\" />\n </svg>\n );\n}\n\n/** lucide `hash` (moved from @ai-matrx/diff). */\nexport function HashIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"hash\", props)}>\n <path d=\"M4 9h16\" />\n <path d=\"M4 15h16\" />\n <path d=\"M10 3 8 21\" />\n <path d=\"M16 3l-2 18\" />\n </svg>\n );\n}\n\n/** lucide `highlighter` (moved from @ai-matrx/diff). */\nexport function HighlighterIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"highlighter\", props)}>\n <path d=\"m9 11-6 6v3h9l3-3\" />\n <path d=\"m22 12-4.6 4.6a2 2 0 0 1-2.8 0l-5.2-5.2a2 2 0 0 1 0-2.8L14 4\" />\n </svg>\n );\n}\n\n/** lucide `image` (moved from @ai-matrx/media). */\nexport function ImageIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"image\", props)}>\n <rect width=\"18\" height=\"18\" x=\"3\" y=\"3\" rx=\"2\" ry=\"2\" />\n <circle cx=\"9\" cy=\"9\" r=\"2\" />\n <path d=\"m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21\" />\n </svg>\n );\n}\n\n/** lucide `image-off` (moved from @ai-matrx/media). */\nexport function ImageOffIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"image-off\", props)}>\n <line x1=\"2\" x2=\"22\" y1=\"2\" y2=\"22\" />\n <path d=\"M10.41 10.41a2 2 0 1 1-2.83-2.83\" />\n <line x1=\"13.5\" x2=\"6\" y1=\"13.5\" y2=\"21\" />\n <line x1=\"18\" x2=\"21\" y1=\"12\" y2=\"15\" />\n <path d=\"M3.59 3.59A1.99 1.99 0 0 0 3 5v14a2 2 0 0 0 2 2h14c.55 0 1.052-.22 1.41-.59\" />\n <path d=\"M21 15V5a2 2 0 0 0-2-2H9\" />\n </svg>\n );\n}\n\n/** lucide `images` (moved from @ai-matrx/capture). */\nexport function ImagesIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"images\", props)}>\n <path d=\"m22 11-1.296-1.296a2.4 2.4 0 0 0-3.408 0L11 16\" />\n <path d=\"M4 8a2 2 0 0 0-2 2v10a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2\" />\n <circle cx=\"13\" cy=\"7\" r=\"1\" fill=\"currentColor\" />\n <rect x=\"8\" y=\"2\" width=\"14\" height=\"14\" rx=\"2\" />\n </svg>\n );\n}\n\n/** lucide `keyboard` (moved from @ai-matrx/meet). */\nexport function KeyboardIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"keyboard\", props)}>\n <path d=\"M10 8h.01M12 12h.01M14 8h.01M16 12h.01M18 8h.01M6 8h.01M7 16h10M8 12h.01\" />\n <rect width=\"20\" height=\"16\" x=\"2\" y=\"4\" rx=\"2\" />\n </svg>\n );\n}\n\n/** lucide `languages` (moved from @ai-matrx/agents). */\nexport function LanguagesIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"languages\", props)}>\n <path d=\"m5 8 6 6\" />\n <path d=\"m4 14 6-6 2-3\" />\n <path d=\"M2 5h12\" />\n <path d=\"M7 2h1\" />\n <path d=\"m22 22-5-10-5 10\" />\n <path d=\"M14 18h6\" />\n </svg>\n );\n}\n\n/** lucide `layers` (moved from @ai-matrx/agents). */\nexport function LayersIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"layers\", props)}>\n <path d=\"M12.83 2.18a2 2 0 0 0-1.66 0L2.6 6.08a1 1 0 0 0 0 1.83l8.58 3.91a2 2 0 0 0 1.66 0l8.58-3.9a1 1 0 0 0 0-1.83z\" />\n <path d=\"M2 12a1 1 0 0 0 .58.91l8.6 3.91a2 2 0 0 0 1.65 0l8.58-3.9A1 1 0 0 0 22 12\" />\n <path d=\"M2 17a1 1 0 0 0 .58.91l8.6 3.91a2 2 0 0 0 1.65 0l8.58-3.9A1 1 0 0 0 22 17\" />\n </svg>\n );\n}\n\n/** lucide `layout-grid` (moved from @ai-matrx/canvas). */\nexport function LayoutGridIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"layout-grid\", props)}>\n <rect width=\"7\" height=\"7\" x=\"3\" y=\"3\" rx=\"1\" />\n <rect width=\"7\" height=\"7\" x=\"14\" y=\"3\" rx=\"1\" />\n <rect width=\"7\" height=\"7\" x=\"14\" y=\"14\" rx=\"1\" />\n <rect width=\"7\" height=\"7\" x=\"3\" y=\"14\" rx=\"1\" />\n </svg>\n );\n}\n\n/** lucide `link-2` (moved from @ai-matrx/media). */\nexport function Link2Icon(props: IconProps) {\n return (\n <svg {...lucideProps(\"link-2\", props)}>\n <path d=\"M9 17H7A5 5 0 0 1 7 7h2\" />\n <path d=\"M15 7h2a5 5 0 1 1 0 10h-2\" />\n <line x1=\"8\" x2=\"16\" y1=\"12\" y2=\"12\" />\n </svg>\n );\n}\n\n/** lucide `list-checks` (moved from @ai-matrx/diff). */\nexport function ListChecksIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"list-checks\", props)}>\n <path d=\"m3 17 2 2 4-4\" />\n <path d=\"m3 7 2 2 4-4\" />\n <path d=\"M13 6h8\" />\n <path d=\"M13 12h8\" />\n <path d=\"M13 18h8\" />\n </svg>\n );\n}\n\n/** lucide `list` (moved from @ai-matrx/diff). */\nexport function ListIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"list\", props)}>\n <path d=\"M3 12h.01\" />\n <path d=\"M3 18h.01\" />\n <path d=\"M3 6h.01\" />\n <path d=\"M8 12h13\" />\n <path d=\"M8 18h13\" />\n <path d=\"M8 6h13\" />\n </svg>\n );\n}\n\n/** lucide `maximize` (moved from @ai-matrx/content-ir). */\nexport function MaximizeIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"maximize\", props)}>\n <polyline points=\"15 3 21 3 21 9\" />\n <polyline points=\"9 21 3 21 3 15\" />\n <line x1=\"21\" x2=\"14\" y1=\"3\" y2=\"10\" />\n <line x1=\"3\" x2=\"10\" y1=\"21\" y2=\"14\" />\n </svg>\n );\n}\n\n/** lucide `megaphone` (moved from @ai-matrx/office). */\nexport function MegaphoneIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"megaphone\", props)}>\n <path d=\"M11 6a13 13 0 0 0 8.4-2.8A1 1 0 0 1 21 4v12a1 1 0 0 1-1.6.8A13 13 0 0 0 11 14H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2z\" />\n <path d=\"M6 14a12 12 0 0 0 2.4 7.2 2 2 0 0 0 3.2-2.4A8 8 0 0 1 10 14\" />\n <path d=\"M8 6v8\" />\n </svg>\n );\n}\n\n/** lucide `message-square-warning` (moved from @ai-matrx/office). */\nexport function MessageSquareWarningIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"message-square-warning\", props)}>\n <path d=\"M22 17a2 2 0 0 1-2 2H6.828a2 2 0 0 0-1.414.586l-2.202 2.202A.71.71 0 0 1 2 21.286V5a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2z\" />\n <path d=\"M12 15h.01\" />\n <path d=\"M12 7v4\" />\n </svg>\n );\n}\n\n/** lucide `mic` (moved from @ai-matrx/meet). */\nexport function MicIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"mic\", props)}>\n <path d=\"M12 2a3 3 0 0 0-3 3v7a3 3 0 0 0 6 0V5a3 3 0 0 0-3-3Z\" />\n <path d=\"M19 10v2a7 7 0 0 1-14 0v-2\" />\n <path d=\"M12 19v3\" />\n </svg>\n );\n}\n\n/** lucide `mic-off` (moved from @ai-matrx/meet). */\nexport function MicOffIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"mic-off\", props)}>\n <path d=\"M2 2l20 20\" />\n <path d=\"M9 9v3a3 3 0 0 0 5.12 2.12\" />\n <path d=\"M15 9.34V5a3 3 0 0 0-5.94-.6\" />\n <path d=\"M19 10v2a7 7 0 0 1-.11 1.23M5 10v2a7 7 0 0 0 11 5.66\" />\n <path d=\"M12 19v3\" />\n </svg>\n );\n}\n\n/** lucide `monitor` (moved from @ai-matrx/coding-sessions). */\nexport function MonitorIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"monitor\", props)}>\n <rect x=\"3\" y=\"4.5\" width=\"18\" height=\"12\" rx=\"2\" />\n <path d=\"M8.5 20h7M12 16.5V20\" />\n </svg>\n );\n}\n\n/** lucide `moon` (moved from @ai-matrx/coding-sessions). */\nexport function MoonIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"moon\", props)}>\n <path d=\"M20 14.5A8 8 0 0 1 9.5 4a8 8 0 1 0 10.5 10.5z\" />\n </svg>\n );\n}\n\n/** lucide `music` (moved from @ai-matrx/media). */\nexport function MusicIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"music\", props)}>\n <path d=\"M9 18V5l12-2v13\" />\n <circle cx=\"6\" cy=\"18\" r=\"3\" />\n <circle cx=\"18\" cy=\"16\" r=\"3\" />\n </svg>\n );\n}\n\n/** lucide `notes` (moved from @ai-matrx/meet). */\nexport function NotesIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"notes\", props)}>\n <path d=\"M4 20l1-4L16.5 4.5a2.1 2.1 0 0 1 3 3L8 19l-4 1Z\" />\n <path d=\"M14 7l3 3\" />\n </svg>\n );\n}\n\n/** lucide `package-box` (moved from @ai-matrx/media). */\nexport function PackageBoxIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"package-box\", props)}>\n <path d=\"M11 21.73a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73z\" />\n <path d=\"M12 22V12\" />\n <polyline points=\"3.29 7 12 12 20.71 7\" />\n <path d=\"m7.5 4.27 9 5.15\" />\n </svg>\n );\n}\n\n/** lucide `page` (moved from @ai-matrx/canvas). */\nexport function PageIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"page\", props)}>\n <rect x=\"4\" y=\"4\" width=\"16\" height=\"16\" rx=\"2\" />\n <path d=\"M8 9h8\" />\n <path d=\"M8 13h8\" />\n <path d=\"M8 17h5\" />\n </svg>\n );\n}\n\n/** lucide `panel-left-close` (moved from @ai-matrx/summon). */\nexport function PanelLeftCloseIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"panel-left-close\", props)}>\n <rect width=\"18\" height=\"18\" x=\"3\" y=\"3\" rx=\"2\" />\n <path d=\"M9 3v18\" />\n <path d=\"m16 15-3-3 3-3\" />\n </svg>\n );\n}\n\n/** lucide `pause` (moved from @ai-matrx/media). */\nexport function PauseIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"pause\", props)}>\n <rect x=\"14\" y=\"3\" width=\"5\" height=\"18\" rx=\"1\" />\n <rect x=\"5\" y=\"3\" width=\"5\" height=\"18\" rx=\"1\" />\n </svg>\n );\n}\n\n/** lucide `pen-tool` (moved from @ai-matrx/media). */\nexport function PenToolIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"pen-tool\", props)}>\n <path d=\"M15.707 21.293a1 1 0 0 1-1.414 0l-1.586-1.586a1 1 0 0 1 0-1.414l5.586-5.586a1 1 0 0 1 1.414 0l1.586 1.586a1 1 0 0 1 0 1.414z\" />\n <path d=\"m18 13-1.375-6.874a1 1 0 0 0-.746-.776L3.235 2.028a1 1 0 0 0-1.207 1.207L5.35 15.879a1 1 0 0 0 .776.746L13 18\" />\n <path d=\"m2.3 2.3 7.286 7.286\" />\n <circle cx=\"11\" cy=\"11\" r=\"2\" />\n </svg>\n );\n}\n\n/** lucide `people` (moved from @ai-matrx/meet). */\nexport function PeopleIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"people\", props)}>\n <path d=\"M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2\" />\n <circle cx=\"9\" cy=\"7\" r=\"4\" />\n <path d=\"M22 21v-2a4 4 0 0 0-3-3.87M16 3.13a4 4 0 0 1 0 7.75\" />\n </svg>\n );\n}\n\n/** lucide `phone-off` (moved from @ai-matrx/meet). */\nexport function PhoneOffIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"phone-off\", props)}>\n <path d=\"M12 9c-1.6 0-3.15.25-4.6.72v3.1c0 .39-.23.74-.56.9-.98.49-1.87 1.12-2.66 1.85-.18.18-.43.28-.7.28-.28 0-.53-.11-.71-.29L.29 13.08a.99.99 0 0 1-.29-.7c0-.28.11-.53.29-.71C3.34 8.78 7.46 7 12 7s8.66 1.78 11.71 4.67c.18.18.29.43.29.71 0 .28-.11.53-.29.71l-2.48 2.48c-.18.18-.43.29-.71.29-.27 0-.52-.11-.7-.28a11.27 11.27 0 0 0-2.67-1.85.996.996 0 0 1-.56-.9v-3.1C15.15 9.25 13.6 9 12 9Z\" fill=\"currentColor\" stroke=\"none\" />\n </svg>\n );\n}\n\n/** lucide `play` (moved from @ai-matrx/media). */\nexport function PlayIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"play\", props)}>\n <path d=\"M5 5a2 2 0 0 1 3.008-1.728l11.997 6.998a2 2 0 0 1 .003 3.458l-12 7A2 2 0 0 1 5 19z\" />\n </svg>\n );\n}\n\n/** lucide `poll` (moved from @ai-matrx/meet). */\nexport function PollIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"poll\", props)}>\n <line x1=\"18\" x2=\"18\" y1=\"20\" y2=\"10\" />\n <line x1=\"12\" x2=\"12\" y1=\"20\" y2=\"4\" />\n <line x1=\"6\" x2=\"6\" y1=\"20\" y2=\"14\" />\n </svg>\n );\n}\n\n/** lucide `proportions` (moved from @ai-matrx/capture). */\nexport function ProportionsIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"proportions\", props)}>\n <rect width=\"20\" height=\"16\" x=\"2\" y=\"4\" rx=\"2\" />\n <path d=\"M12 9v11\" />\n <path d=\"M2 9h13a2 2 0 0 1 2 2v9\" />\n </svg>\n );\n}\n\n/** lucide `puzzle` (moved from @ai-matrx/office). */\nexport function PuzzleIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"puzzle\", props)}>\n <path d=\"M15.39 4.39a1 1 0 0 0 1.68-.474 2.5 2.5 0 1 1 3.014 3.015 1 1 0 0 0-.474 1.68l1.683 1.682a2.414 2.414 0 0 1 0 3.414L19.61 15.39a1 1 0 0 1-1.68-.474 2.5 2.5 0 1 0-3.014 3.015 1 1 0 0 1 .474 1.68l-1.683 1.682a2.414 2.414 0 0 1-3.414 0L8.61 19.61a1 1 0 0 0-1.68.474 2.5 2.5 0 1 1-3.014-3.015 1 1 0 0 0 .474-1.68l-1.683-1.682a2.414 2.414 0 0 1 0-3.414L4.39 8.61a1 1 0 0 1 1.68.474 2.5 2.5 0 1 0 3.014-3.015 1 1 0 0 1-.474-1.68l1.683-1.682a2.414 2.414 0 0 1 3.414 0z\" />\n </svg>\n );\n}\n\n/** lucide `question` (moved from @ai-matrx/meet). */\nexport function QuestionIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"question\", props)}>\n <path d=\"M7.9 20A9 9 0 1 0 4 16.1L2 22Z\" />\n <path d=\"M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3\" />\n <path d=\"M12 17h.01\" />\n </svg>\n );\n}\n\n/** lucide `record` (moved from @ai-matrx/meet). */\nexport function RecordIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"record\", props)}>\n <circle cx=\"12\" cy=\"12\" r=\"8\" fill=\"currentColor\" stroke=\"none\" />\n </svg>\n );\n}\n\n/** lucide `rectangle-vertical` (moved from @ai-matrx/summon). */\nexport function RectangleVerticalIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"rectangle-vertical\", props)}>\n <rect width=\"12\" height=\"20\" x=\"6\" y=\"2\" rx=\"2\" />\n </svg>\n );\n}\n\n/** lucide `restore` (moved from @ai-matrx/associations). */\nexport function RestoreIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"restore\", props)}>\n <path d=\"M4 14h6v6\" />\n <path d=\"M20 10h-6V4\" />\n <path d=\"M14 10l7-7\" />\n <path d=\"M3 21l7-7\" />\n </svg>\n );\n}\n\n/** lucide `rotate-ccw` (moved from @ai-matrx/capture). */\nexport function RotateCcwIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"rotate-ccw\", props)}>\n <path d=\"M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8\" />\n <path d=\"M3 3v5h5\" />\n </svg>\n );\n}\n\n/** lucide `rows-3` (moved from @ai-matrx/diff). */\nexport function Rows3Icon(props: IconProps) {\n return (\n <svg {...lucideProps(\"rows-3\", props)}>\n <rect width=\"18\" height=\"18\" x=\"3\" y=\"3\" rx=\"2\" />\n <path d=\"M21 9H3\" />\n <path d=\"M21 15H3\" />\n </svg>\n );\n}\n\n/** lucide `save` (moved from @ai-matrx/summon). */\nexport function SaveIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"save\", props)}>\n <path d=\"M15.2 3a2 2 0 0 1 1.4.6l3.8 3.8a2 2 0 0 1 .6 1.4V19a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2z\" />\n <path d=\"M17 21v-7a1 1 0 0 0-1-1H8a1 1 0 0 0-1 1v7\" />\n <path d=\"M7 3v4a1 1 0 0 0 1 1h7\" />\n </svg>\n );\n}\n\n/** lucide `scale` (moved from @ai-matrx/agents). */\nexport function ScaleIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"scale\", props)}>\n <path d=\"M12 3v18\" />\n <path d=\"m19 8 3 8a5 5 0 0 1-6 0zV7\" />\n <path d=\"M3 7h1a17 17 0 0 0 8-2 17 17 0 0 0 8 2h1\" />\n <path d=\"m5 8 3 8a5 5 0 0 1-6 0zV7\" />\n <path d=\"M7 21h10\" />\n </svg>\n );\n}\n\n/** lucide `screen-share` (moved from @ai-matrx/meet). */\nexport function ScreenShareIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"screen-share\", props)}>\n <rect x=\"2\" y=\"3\" width=\"20\" height=\"14\" rx=\"2\" />\n <path d=\"M8 21h8M12 17v4\" />\n <path d=\"M12 13V8m0 0-2.5 2.5M12 8l2.5 2.5\" />\n </svg>\n );\n}\n\n/** lucide `server` (moved from @ai-matrx/agents). */\nexport function ServerIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"server\", props)}>\n <rect width=\"20\" height=\"8\" x=\"2\" y=\"2\" rx=\"2\" ry=\"2\" />\n <rect width=\"20\" height=\"8\" x=\"2\" y=\"14\" rx=\"2\" ry=\"2\" />\n <line x1=\"6\" x2=\"6.01\" y1=\"6\" y2=\"6\" />\n <line x1=\"6\" x2=\"6.01\" y1=\"18\" y2=\"18\" />\n </svg>\n );\n}\n\n/** lucide `settings-2` (moved from @ai-matrx/media). */\nexport function Settings2Icon(props: IconProps) {\n return (\n <svg {...lucideProps(\"settings-2\", props)}>\n <path d=\"M20 7h-9\" />\n <path d=\"M14 17H5\" />\n <circle cx=\"17\" cy=\"17\" r=\"3\" />\n <circle cx=\"7\" cy=\"7\" r=\"3\" />\n </svg>\n );\n}\n\n/** lucide `share-2` (moved from @ai-matrx/media). */\nexport function Share2Icon(props: IconProps) {\n return (\n <svg {...lucideProps(\"share-2\", props)}>\n <circle cx=\"18\" cy=\"5\" r=\"3\" />\n <circle cx=\"6\" cy=\"12\" r=\"3\" />\n <circle cx=\"18\" cy=\"19\" r=\"3\" />\n <line x1=\"8.59\" x2=\"15.42\" y1=\"13.51\" y2=\"17.49\" />\n <line x1=\"15.41\" x2=\"8.59\" y1=\"6.51\" y2=\"10.49\" />\n </svg>\n );\n}\n\n/** lucide `shield-alert` (moved from @ai-matrx/detail). */\nexport function ShieldAlertIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"shield-alert\", props)}>\n <path d=\"M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z\" />\n <path d=\"M12 8v4\" />\n <path d=\"M12 16h.01\" />\n </svg>\n );\n}\n\n/** lucide `shield-check` (moved from @ai-matrx/detail). */\nexport function ShieldCheckIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"shield-check\", props)}>\n <path d=\"M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z\" />\n <path d=\"m9 12 2 2 4-4\" />\n </svg>\n );\n}\n\n/** lucide `badge-check` — the verified mark. */\nexport function BadgeCheckIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"badge-check\", props)}>\n <path d=\"M3.85 8.62a4 4 0 0 1 4.78-4.77 4 4 0 0 1 6.74 0 4 4 0 0 1 4.78 4.78 4 4 0 0 1 0 6.74 4 4 0 0 1-4.77 4.78 4 4 0 0 1-6.75 0 4 4 0 0 1-4.78-4.77 4 4 0 0 1 0-6.76Z\" />\n <path d=\"m9 12 2 2 4-4\" />\n </svg>\n );\n}\n\n/** lucide `shield` (moved from @ai-matrx/agents). */\nexport function ShieldIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"shield\", props)}>\n <path d=\"M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z\" />\n </svg>\n );\n}\n\n/** lucide `sidebar` (moved from @ai-matrx/coding-sessions). */\nexport function SidebarIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"sidebar\", props)}>\n <rect x=\"3.5\" y=\"4.5\" width=\"17\" height=\"15\" rx=\"2.5\" />\n <path d=\"M9.5 4.5v15\" />\n </svg>\n );\n}\n\n/** lucide `sliders-horizontal` (moved from @ai-matrx/agents). */\nexport function SlidersHorizontalIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"sliders-horizontal\", props)}>\n <path d=\"M10 5H3\" />\n <path d=\"M12 19H3\" />\n <path d=\"M14 3v4\" />\n <path d=\"M16 17v4\" />\n <path d=\"M21 12h-9\" />\n <path d=\"M21 19h-5\" />\n <path d=\"M21 5h-7\" />\n <path d=\"M8 10v4\" />\n <path d=\"M8 12H3\" />\n </svg>\n );\n}\n\n/** lucide `smile` (moved from @ai-matrx/meet). */\nexport function SmileIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"smile\", props)}>\n <circle cx=\"12\" cy=\"12\" r=\"10\" />\n <path d=\"M8 14s1.5 2 4 2 4-2 4-2\" />\n <line x1=\"9\" x2=\"9.01\" y1=\"9\" y2=\"9\" />\n <line x1=\"15\" x2=\"15.01\" y1=\"9\" y2=\"9\" />\n </svg>\n );\n}\n\n/** lucide `speaker` (moved from @ai-matrx/meet). */\nexport function SpeakerIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"speaker\", props)}>\n <path d=\"M11 5 6 9H2v6h4l5 4V5Z\" />\n <path d=\"M15.54 8.46a5 5 0 0 1 0 7.07\" />\n <path d=\"M19.07 4.93a10 10 0 0 1 0 14.14\" />\n </svg>\n );\n}\n\n/** lucide `split-down` (moved from @ai-matrx/canvas). */\nexport function SplitDownIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"split-down\", props)}>\n <rect width=\"18\" height=\"18\" x=\"3\" y=\"3\" rx=\"2\" />\n <path d=\"M3 12h18\" />\n </svg>\n );\n}\n\n/** lucide `spotlight` (moved from @ai-matrx/meet). */\nexport function SpotlightIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"spotlight\", props)}>\n <path d=\"M12 2 15 8.5 22 9.3 17 14 18.2 21 12 17.6 5.8 21 7 14 2 9.3 9 8.5Z\" />\n </svg>\n );\n}\n\n/** lucide `stop` (moved from @ai-matrx/coding-sessions). */\nexport function StopIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"stop\", props)}>\n <rect x=\"6\" y=\"6\" width=\"12\" height=\"12\" rx=\"2\" fill=\"currentColor\" stroke=\"none\" />\n </svg>\n );\n}\n\n/** lucide `subtitles` (moved from @ai-matrx/media). */\nexport function SubtitlesIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"subtitles\", props)}>\n <rect width=\"18\" height=\"14\" x=\"3\" y=\"5\" rx=\"2\" ry=\"2\" />\n <path d=\"M7 15h4M15 15h2M7 11h2M13 11h4\" />\n </svg>\n );\n}\n\n/** lucide `sun` (moved from @ai-matrx/coding-sessions). */\nexport function SunIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"sun\", props)}>\n <circle cx=\"12\" cy=\"12\" r=\"4\" />\n <path d=\"M12 2.5v2M12 19.5v2M4.2 4.2l1.4 1.4M18.4 18.4l1.4 1.4M2.5 12h2M19.5 12h2M4.2 19.8l1.4-1.4M18.4 5.6l1.4-1.4\" />\n </svg>\n );\n}\n\n/** lucide `sun-medium` (moved from @ai-matrx/capture). */\nexport function SunMediumIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"sun-medium\", props)}>\n <circle cx=\"12\" cy=\"12\" r=\"4\" />\n <path d=\"M12 3v1\" />\n <path d=\"M12 20v1\" />\n <path d=\"M3 12h1\" />\n <path d=\"M20 12h1\" />\n <path d=\"m18.364 5.636-.707.707\" />\n <path d=\"m6.343 17.657-.707.707\" />\n <path d=\"m5.636 5.636.707.707\" />\n <path d=\"m17.657 17.657.707.707\" />\n </svg>\n );\n}\n\n/** lucide `tag` (moved from @ai-matrx/associations). */\nexport function TagIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"tag\", props)}>\n <path d=\"M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z\" />\n <circle cx=\"7.5\" cy=\"7.5\" r=\".5\" fill=\"currentColor\" />\n </svg>\n );\n}\n\n/** lucide `timer` (moved from @ai-matrx/capture). */\nexport function TimerIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"timer\", props)}>\n <line x1=\"10\" x2=\"14\" y1=\"2\" y2=\"2\" />\n <line x1=\"12\" x2=\"15\" y1=\"14\" y2=\"11\" />\n <circle cx=\"12\" cy=\"14\" r=\"8\" />\n </svg>\n );\n}\n\n/** lucide `type` (moved from @ai-matrx/agents). */\nexport function TypeIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"type\", props)}>\n <path d=\"M12 4v16\" />\n <path d=\"M4 7V5a1 1 0 0 1 1-1h14a1 1 0 0 1 1 1v2\" />\n <path d=\"M9 20h6\" />\n </svg>\n );\n}\n\n/** lucide `unfold-vertical` (moved from @ai-matrx/diff). */\nexport function UnfoldVerticalIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"unfold-vertical\", props)}>\n <path d=\"M12 22v-6\" />\n <path d=\"M12 8V2\" />\n <path d=\"M4 12H2\" />\n <path d=\"M10 12H8\" />\n <path d=\"M16 12h-2\" />\n <path d=\"M22 12h-2\" />\n <path d=\"m15 19-3 3-3-3\" />\n <path d=\"m15 5-3-3-3 3\" />\n </svg>\n );\n}\n\n/** lucide `unlink` (moved from @ai-matrx/agents). */\nexport function UnlinkIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"unlink\", props)}>\n <path d=\"m18.84 12.25 1.72-1.71h-.02a5.004 5.004 0 0 0-.12-7.07 5.006 5.006 0 0 0-6.95 0l-1.72 1.71\" />\n <path d=\"m5.17 11.75-1.71 1.71a5.004 5.004 0 0 0 .12 7.07 5.006 5.006 0 0 0 6.95 0l1.71-1.71\" />\n <line x1=\"8\" x2=\"8\" y1=\"2\" y2=\"5\" />\n <line x1=\"2\" x2=\"5\" y1=\"8\" y2=\"8\" />\n <line x1=\"16\" x2=\"16\" y1=\"19\" y2=\"22\" />\n <line x1=\"19\" x2=\"22\" y1=\"16\" y2=\"16\" />\n </svg>\n );\n}\n\n/** lucide `upvote` (moved from @ai-matrx/meet). */\nexport function UpvoteIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"upvote\", props)}>\n <path d=\"M9 18v-6H5l7-7 7 7h-4v6H9z\" />\n </svg>\n );\n}\n\n/** lucide `variable` (moved from @ai-matrx/agents). */\nexport function VariableIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"variable\", props)}>\n <path d=\"M8 21s-4-3-4-9 4-9 4-9\" />\n <path d=\"M16 3s4 3 4 9-4 9-4 9\" />\n <line x1=\"15\" x2=\"9\" y1=\"9\" y2=\"15\" />\n <line x1=\"9\" x2=\"15\" y1=\"9\" y2=\"15\" />\n </svg>\n );\n}\n\n/** lucide `video-off` (moved from @ai-matrx/media). */\nexport function VideoOffIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"video-off\", props)}>\n <path d=\"M10.66 6H14a2 2 0 0 1 2 2v2.5l5.248-3.062A.5.5 0 0 1 22 7.87v8.196\" />\n <path d=\"M16 16a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h2\" />\n <path d=\"m2 2 20 20\" />\n </svg>\n );\n}\n\n/** lucide `volume-x` (moved from @ai-matrx/media). */\nexport function VolumeXIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"volume-x\", props)}>\n <path d=\"M11 4.702a.705.705 0 0 0-1.203-.498L6.413 7.587A1.4 1.4 0 0 1 5.416 8H3a1 1 0 0 0-1 1v6a1 1 0 0 0 1 1h2.416a1.4 1.4 0 0 1 .997.413l3.383 3.384A.705.705 0 0 0 11 19.298z\" />\n <line x1=\"22\" x2=\"16\" y1=\"9\" y2=\"15\" />\n <line x1=\"16\" x2=\"22\" y1=\"9\" y2=\"15\" />\n </svg>\n );\n}\n\n/** lucide `webhook` (moved from @ai-matrx/agents). */\nexport function WebhookIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"webhook\", props)}>\n <path d=\"M18 16.98h-5.99c-1.1 0-1.95.94-2.48 1.9A4 4 0 0 1 2 17c.01-.7.2-1.4.57-2\" />\n <path d=\"m6 17 3.13-5.78c.53-.97.1-2.18-.5-3.1a4 4 0 1 1 6.89-4.06\" />\n <path d=\"m12 6 3.13 5.73C15.66 12.7 16.9 13 18 13a4 4 0 0 1 0 8\" />\n </svg>\n );\n}\n\n/** lucide `whiteboard` (moved from @ai-matrx/meet). */\nexport function WhiteboardIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"whiteboard\", props)}>\n <path d=\"M2 3h20\" />\n <path d=\"M21 3v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V3\" />\n <path d=\"m7 21 5-5 5 5\" />\n </svg>\n );\n}\n\n/** lucide `wifi-low` (moved from @ai-matrx/meet). */\nexport function WifiLowIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"wifi-low\", props)}>\n <path d=\"M12 20h.01\" />\n <path d=\"M8.5 16.5a5 5 0 0 1 7 0\" />\n </svg>\n );\n}\n\n/** lucide `wrap-text` (moved from @ai-matrx/diff). */\nexport function WrapTextIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"wrap-text\", props)}>\n <path d=\"M3 6h18\" />\n <path d=\"M3 12h15a3 3 0 1 1 0 6h-4\" />\n <path d=\"m16 16-2 2 2 2\" />\n <path d=\"M3 18h7\" />\n </svg>\n );\n}\n\n/** lucide `wrench` (moved from @ai-matrx/agents). */\nexport function WrenchIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"wrench\", props)}>\n <path d=\"M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.106-3.105c.32-.322.863-.22.983.218a6 6 0 0 1-8.259 7.057l-7.91 7.91a1 1 0 0 1-2.999-3l7.91-7.91a6 6 0 0 1 7.057-8.259c.438.12.54.662.219.984z\" />\n </svg>\n );\n}\n\n/** lucide `youtube` (moved from @ai-matrx/agents). */\nexport function YoutubeIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"youtube\", props)}>\n <path d=\"M2.5 17a24.12 24.12 0 0 1 0-10 2 2 0 0 1 1.4-1.4 49.56 49.56 0 0 1 16.2 0A2 2 0 0 1 21.5 7a24.12 24.12 0 0 1 0 10 2 2 0 0 1-1.4 1.4 49.55 49.55 0 0 1-16.2 0A2 2 0 0 1 2.5 17\" />\n <path d=\"m10 15 5-3-5-3z\" />\n </svg>\n );\n}\n\n/** lucide `zap` (moved from @ai-matrx/capture). */\nexport function ZapIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"zap\", props)}>\n <path d=\"M4 14a1 1 0 0 1-.78-1.63l9.9-10.2a.5.5 0 0 1 .86.46l-1.92 6.02A1 1 0 0 0 13 10h7a1 1 0 0 1 .78 1.63l-9.9 10.2a.5.5 0 0 1-.86-.46l1.92-6.02A1 1 0 0 0 11 14z\" />\n </svg>\n );\n}\n\n/** lucide `zap-off` (moved from @ai-matrx/capture). */\nexport function ZapOffIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"zap-off\", props)}>\n <path d=\"M10.513 4.856 13.12 2.17a.5.5 0 0 1 .86.46l-1.377 4.317\" />\n <path d=\"M15.656 10H20a1 1 0 0 1 .78 1.63l-1.72 1.773\" />\n <path d=\"M16.273 16.273 10.88 21.83a.5.5 0 0 1-.86-.46l1.92-6.02A1 1 0 0 0 11 14H4a1 1 0 0 1-.78-1.63l4.507-4.643\" />\n <path d=\"m2 2 20 20\" />\n </svg>\n );\n}\n\n/** lucide `log-in` — the sign-in action of the auth gate. */\nexport function LogInIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"log-in\", props)}>\n <path d=\"M15 3h4a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2h-4\" />\n <polyline points=\"10 17 15 12 10 7\" />\n <line x1=\"15\" x2=\"3\" y1=\"12\" y2=\"12\" />\n </svg>\n );\n}\n\n/** lucide `gem` — the create-account action of the auth gate. */\nexport function GemIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"gem\", props)}>\n <path d=\"M6 3h12l4 6-10 13L2 9Z\" />\n <path d=\"M11 3 8 9l4 13 4-13-3-6\" />\n <path d=\"M2 9h20\" />\n </svg>\n );\n}\n\n/** lucide `key`. */\nexport function KeyIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"key\", props)}>\n <path d=\"m2 21 9.6-9.6\" />\n <path d=\"m7.5 15.5 2.3 2.3a1 1 0 0 1 0 1.4l-2.1 2.1a1 1 0 0 1-1.4 0L4 19\" />\n <circle cx=\"15.5\" cy=\"7.5\" r=\"5.5\" />\n </svg>\n );\n}\n\n/** lucide `credit-card`. */\nexport function CreditCardIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"credit-card\", props)}>\n <rect width=\"20\" height=\"14\" x=\"2\" y=\"5\" rx=\"2\" />\n <line x1=\"2\" x2=\"22\" y1=\"10\" y2=\"10\" />\n <path d=\"M6 14h2\" />\n </svg>\n );\n}\n\n/** lucide `user-round`. */\nexport function UserRoundIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"user-round\", props)}>\n <circle cx=\"12\" cy=\"8\" r=\"5\" />\n <path d=\"M20 21a8 8 0 0 0-16 0\" />\n </svg>\n );\n}\n\n/** lucide `user`. */\nexport function UserIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"user\", props)}>\n <path d=\"M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2\" />\n <circle cx=\"12\" cy=\"7\" r=\"4\" />\n </svg>\n );\n}\n\n/** lucide `terminal`. */\nexport function TerminalIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"terminal\", props)}>\n <path d=\"M12 19h8\" />\n <path d=\"m4 17 6-6-6-6\" />\n </svg>\n );\n}\n\n/** lucide `trash`. */\nexport function TrashIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"trash\", props)}>\n <path d=\"M10 11v6\" />\n <path d=\"M14 11v6\" />\n <path d=\"M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6\" />\n <path d=\"M3 6h18\" />\n <path d=\"M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2\" />\n </svg>\n );\n}\n\n/** lucide `building`. */\nexport function BuildingIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"building\", props)}>\n <path d=\"M12 10h.01\" />\n <path d=\"M12 14h.01\" />\n <path d=\"M12 6h.01\" />\n <path d=\"M16 10h.01\" />\n <path d=\"M16 14h.01\" />\n <path d=\"M16 6h.01\" />\n <path d=\"M8 10h.01\" />\n <path d=\"M8 14h.01\" />\n <path d=\"M8 6h.01\" />\n <path d=\"M9 22v-3a1 1 0 0 1 1-1h4a1 1 0 0 1 1 1v3\" />\n <rect x=\"4\" y=\"2\" width=\"16\" height=\"20\" rx=\"2\" />\n </svg>\n );\n}\n\n/** lucide `plug`. */\nexport function PlugIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"plug\", props)}>\n <path d=\"M12 22v-5\" />\n <path d=\"M15 8V2\" />\n <path d=\"M17 8a1 1 0 0 1 1 1v4a4 4 0 0 1-4 4h-4a4 4 0 0 1-4-4V9a1 1 0 0 1 1-1z\" />\n <path d=\"M9 8V2\" />\n </svg>\n );\n}\n\n/** lucide `share`. */\nexport function ShareIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"share\", props)}>\n <path d=\"M12 2v13\" />\n <path d=\"m16 6-4-4-4 4\" />\n <path d=\"M4 12v8a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-8\" />\n </svg>\n );\n}\n\n/** lucide `arrow-up-down`. */\nexport function ArrowUpDownIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"arrow-up-down\", props)}>\n <path d=\"m21 16-4 4-4-4\" />\n <path d=\"M17 20V4\" />\n <path d=\"m3 8 4-4 4 4\" />\n <path d=\"M7 4v16\" />\n </svg>\n );\n}\n\n/** lucide `move`. */\nexport function MoveIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"move\", props)}>\n <path d=\"M12 2v20\" />\n <path d=\"m15 19-3 3-3-3\" />\n <path d=\"m19 9 3 3-3 3\" />\n <path d=\"M2 12h20\" />\n <path d=\"m5 9-3 3 3 3\" />\n <path d=\"m9 5 3-3 3 3\" />\n </svg>\n );\n}\n\n/** lucide `qr-code`. */\nexport function QrCodeIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"qr-code\", props)}>\n <rect width=\"5\" height=\"5\" x=\"3\" y=\"3\" rx=\"1\" />\n <rect width=\"5\" height=\"5\" x=\"16\" y=\"3\" rx=\"1\" />\n <rect width=\"5\" height=\"5\" x=\"3\" y=\"16\" rx=\"1\" />\n <path d=\"M21 16h-3a2 2 0 0 0-2 2v3\" />\n <path d=\"M21 21v.01\" />\n <path d=\"M12 7v3a2 2 0 0 1-2 2H7\" />\n <path d=\"M3 12h.01\" />\n <path d=\"M12 3h.01\" />\n <path d=\"M12 16v.01\" />\n <path d=\"M16 12h1\" />\n <path d=\"M21 12v.01\" />\n <path d=\"M12 21v-1\" />\n </svg>\n );\n}\n\n/** lucide `power`. */\nexport function PowerIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"power\", props)}>\n <path d=\"M12 2v10\" />\n <path d=\"M18.4 6.6a9 9 0 1 1-12.77.04\" />\n </svg>\n );\n}\n\n/** lucide `sliders-vertical`. */\nexport function SlidersVerticalIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"sliders-vertical\", props)}>\n <path d=\"M10 8h4\" />\n <path d=\"M12 21v-9\" />\n <path d=\"M12 8V3\" />\n <path d=\"M17 16h4\" />\n <path d=\"M19 12V3\" />\n <path d=\"M19 21v-5\" />\n <path d=\"M3 14h4\" />\n <path d=\"M5 10V3\" />\n <path d=\"M5 21v-7\" />\n </svg>\n );\n}\n\n/** lucide `fingerprint-pattern`. */\nexport function FingerprintPatternIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"fingerprint-pattern\", props)}>\n <path d=\"M12 10a2 2 0 0 0-2 2c0 1.02-.1 2.51-.26 4\" />\n <path d=\"M14 13.12c0 2.38 0 6.38-1 8.88\" />\n <path d=\"M17.29 21.02c.12-.6.43-2.3.5-3.02\" />\n <path d=\"M2 12a10 10 0 0 1 18-6\" />\n <path d=\"M2 16h.01\" />\n <path d=\"M21.8 16c.2-2 .131-5.354 0-6\" />\n <path d=\"M5 19.5C5.5 18 6 15 6 12a6 6 0 0 1 .34-2\" />\n <path d=\"M8.65 22c.21-.66.45-1.32.57-2\" />\n <path d=\"M9 6.8a6 6 0 0 1 9 5.2v2\" />\n </svg>\n );\n}\n\n/** lucide `send`. */\nexport function SendIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"send\", props)}>\n <path d=\"M14.536 21.686a.5.5 0 0 0 .937-.024l6.5-19a.496.496 0 0 0-.635-.635l-19 6.5a.5.5 0 0 0-.024.937l7.93 3.18a2 2 0 0 1 1.112 1.11z\" />\n <path d=\"m21.854 2.147-10.94 10.939\" />\n </svg>\n );\n}\n\n/** lucide `paperclip`. */\nexport function PaperclipIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"paperclip\", props)}>\n <path d=\"m16 6-8.414 8.586a2 2 0 0 0 2.829 2.829l8.414-8.586a4 4 0 1 0-5.657-5.657l-8.379 8.551a6 6 0 1 0 8.485 8.485l8.379-8.551\" />\n </svg>\n );\n}\n\n/** lucide `check-check`. */\nexport function CheckCheckIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"check-check\", props)}>\n <path d=\"M18 6 7 17l-5-5\" />\n <path d=\"m22 10-7.5 7.5L13 16\" />\n </svg>\n );\n}\n\n/** lucide `reply`. */\nexport function ReplyIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"reply\", props)}>\n <path d=\"M20 18v-2a4 4 0 0 0-4-4H4\" />\n <path d=\"m9 17-5-5 5-5\" />\n </svg>\n );\n}\n\n/** lucide `link`. */\nexport function LinkIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"link\", props)}>\n <path d=\"M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71\" />\n <path d=\"M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71\" />\n </svg>\n );\n}\n\n/** lucide `bot`. */\nexport function BotIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"bot\", props)}>\n <path d=\"M12 8V4H8\" />\n <rect width=\"16\" height=\"12\" x=\"4\" y=\"8\" rx=\"2\" />\n <path d=\"M2 14h2\" />\n <path d=\"M20 14h2\" />\n <path d=\"M15 13v2\" />\n <path d=\"M9 13v2\" />\n </svg>\n );\n}\n\n/** lucide `bell-off`. */\nexport function BellOffIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"bell-off\", props)}>\n <path d=\"M10.268 21a2 2 0 0 0 3.464 0\" />\n <path d=\"M17 17H4a1 1 0 0 1-.74-1.673C4.59 13.956 6 12.499 6 8a6 6 0 0 1 .258-1.742\" />\n <path d=\"m2 2 20 20\" />\n <path d=\"M8.668 3.01A6 6 0 0 1 18 8c0 2.687.77 4.653 1.707 6.05\" />\n </svg>\n );\n}\n\n/** lucide `mail`. */\nexport function MailIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"mail\", props)}>\n <path d=\"m22 7-8.991 5.727a2 2 0 0 1-2.009 0L2 7\" />\n <rect x=\"2\" y=\"4\" width=\"20\" height=\"16\" rx=\"2\" />\n </svg>\n );\n}\n\n/** lucide `mail-open`. */\nexport function MailOpenIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"mail-open\", props)}>\n <path d=\"M21.2 8.4c.5.38.8.97.8 1.6v10a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V10a2 2 0 0 1 .8-1.6l8-6a2 2 0 0 1 2.4 0l8 6Z\" />\n <path d=\"m22 10-8.97 5.7a1.94 1.94 0 0 1-2.06 0L2 10\" />\n </svg>\n );\n}\n\n/** lucide `folder-input`. */\nexport function FolderInputIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"folder-input\", props)}>\n <path d=\"M2 9V5a2 2 0 0 1 2-2h3.9a2 2 0 0 1 1.69.9l.81 1.2a2 2 0 0 0 1.67.9H20a2 2 0 0 1 2 2v10a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2v-1\" />\n <path d=\"M2 13h10\" />\n <path d=\"m9 16 3-3-3-3\" />\n </svg>\n );\n}\n\n/** lucide `star-off`. */\nexport function StarOffIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"star-off\", props)}>\n <path d=\"m10.344 4.688 1.181-2.393a.53.53 0 0 1 .95 0l2.31 4.679a2.12 2.12 0 0 0 1.595 1.16l5.166.756a.53.53 0 0 1 .294.904l-3.237 3.152\" />\n <path d=\"m17.945 17.945.43 2.505a.53.53 0 0 1-.771.56l-4.618-2.428a2.12 2.12 0 0 0-1.973 0L6.396 21.01a.53.53 0 0 1-.77-.56l.881-5.139a2.12 2.12 0 0 0-.611-1.879L2.16 9.795a.53.53 0 0 1 .294-.906l5.165-.755a8 8 0 0 0 .4-.099\" />\n <path d=\"m2 2 20 20\" />\n </svg>\n );\n}\n\n/** lucide `columns-3`. */\nexport function Columns3Icon(props: IconProps) {\n return (\n <svg {...lucideProps(\"columns-3\", props)}>\n <rect width=\"18\" height=\"18\" x=\"3\" y=\"3\" rx=\"2\" />\n <path d=\"M9 3v18\" />\n <path d=\"M15 3v18\" />\n </svg>\n );\n}\n\n/** lucide `blocks`. */\nexport function BlocksIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"blocks\", props)}>\n <path d=\"M10 22V7a1 1 0 0 0-1-1H4a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-5a1 1 0 0 0-1-1H2\" />\n <rect x=\"14\" y=\"2\" width=\"8\" height=\"8\" rx=\"1\" />\n </svg>\n );\n}\n\n/** lucide `calendar-clock`. */\nexport function CalendarClockIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"calendar-clock\", props)}>\n <path d=\"M16 14v2.2l1.6 1\" />\n <path d=\"M16 2v3\" />\n <path d=\"M21 7.338V5a2 2 0 00-2-2H5a2 2 0 00-2 2v14a2 2 0 002 2h2.338\" />\n <path d=\"M3 9h5.859\" />\n <path d=\"M8 2v3\" />\n <circle cx=\"16\" cy=\"16\" r=\"6\" />\n </svg>\n );\n}\n\n/** lucide `door-open`. */\nexport function DoorOpenIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"door-open\", props)}>\n <path d=\"M10 21H2\" />\n <path d=\"M10 3H7a2 2 0 00-2 2v16\" />\n <path d=\"M14 12h.01\" />\n <path d=\"M19 21V5a2 2 0 00-1.675-1.974l-6.163-1.013A1 1 0 0010 3v18a1 1 0 001.124.992z\" />\n <path d=\"M22 21h-3\" />\n </svg>\n );\n}\n\n/** lucide `inbox`. */\nexport function InboxIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"inbox\", props)}>\n <polyline points=\"22 12 16 12 14 15 10 15 8 12 2 12\" />\n <path d=\"M5.45 5.11 2 12v6a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-6l-3.45-6.89A2 2 0 0 0 16.76 4H7.24a2 2 0 0 0-1.79 1.11z\" />\n </svg>\n );\n}\n\n/** lucide `layout-dashboard`. */\nexport function LayoutDashboardIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"layout-dashboard\", props)}>\n <rect width=\"7\" height=\"9\" x=\"3\" y=\"3\" rx=\"1\" />\n <rect width=\"7\" height=\"5\" x=\"14\" y=\"3\" rx=\"1\" />\n <rect width=\"7\" height=\"9\" x=\"14\" y=\"12\" rx=\"1\" />\n <rect width=\"7\" height=\"5\" x=\"3\" y=\"16\" rx=\"1\" />\n </svg>\n );\n}\n\n/** lucide `archive-restore`. */\nexport function ArchiveRestoreIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"archive-restore\", props)}>\n <rect width=\"20\" height=\"5\" x=\"2\" y=\"3\" rx=\"1\" />\n <path d=\"M4 8v11a2 2 0 0 0 2 2h2\" />\n <path d=\"M20 8v11a2 2 0 0 1-2 2h-2\" />\n <path d=\"m9 15 3-3 3 3\" />\n <path d=\"M12 12v9\" />\n </svg>\n );\n}\n\n/** lucide `split`. */\nexport function SplitIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"split\", props)}>\n <path d=\"M16 3h5v5\" />\n <path d=\"M8 3H3v5\" />\n <path d=\"M12 22v-8.3a4 4 0 0 0-1.172-2.872L3 3\" />\n <path d=\"m15 9 6-6\" />\n </svg>\n );\n}\n\n/** lucide `arrow-up-from-line`. */\nexport function ArrowUpFromLineIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"arrow-up-from-line\", props)}>\n <path d=\"m18 9-6-6-6 6\" />\n <path d=\"M12 3v14\" />\n <path d=\"M5 21h14\" />\n </svg>\n );\n}\n\n/** lucide `lock-open`. */\nexport function LockOpenIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"lock-open\", props)}>\n <rect width=\"18\" height=\"11\" x=\"3\" y=\"11\" rx=\"2\" ry=\"2\" />\n <path d=\"M7 11V7a5 5 0 0 1 9.9-1\" />\n </svg>\n );\n}\n\n/** lucide `printer`. */\nexport function PrinterIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"printer\", props)}>\n <path d=\"M6 18H4a2 2 0 0 1-2-2v-5a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2v5a2 2 0 0 1-2 2h-2\" />\n <path d=\"M6 9V3a1 1 0 0 1 1-1h10a1 1 0 0 1 1 1v6\" />\n <rect x=\"6\" y=\"14\" width=\"12\" height=\"8\" rx=\"1\" />\n </svg>\n );\n}\n\n/** lucide `rocket`. */\nexport function RocketIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"rocket\", props)}>\n <path d=\"M12 15v5s3.03-.55 4-2c1.08-1.62 0-5 0-5\" />\n <path d=\"M4.5 16.5c-1.5 1.26-2 5-2 5s3.74-.5 5-2c.71-.84.7-2.13-.09-2.91a2.18 2.18 0 0 0-2.91-.09\" />\n <path d=\"M9 12a22 22 0 0 1 2-3.95A12.88 12.88 0 0 1 22 2c0 2.72-.78 7.5-6 11a22.4 22.4 0 0 1-4 2z\" />\n <path d=\"M9 12H4s.55-3.03 2-4c1.62-1.08 5 .05 5 .05\" />\n </svg>\n );\n}\n\n/** lucide `message-circle`. */\nexport function MessageCircleIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"message-circle\", props)}>\n <path d=\"M2.992 16.342a2 2 0 0 1 .094 1.167l-1.065 3.29a1 1 0 0 0 1.236 1.168l3.413-.998a2 2 0 0 1 1.099.092 10 10 0 1 0-4.777-4.719\" />\n </svg>\n );\n}\n\n/** lucide `copy-plus`. */\nexport function CopyPlusIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"copy-plus\", props)}>\n <line x1=\"15\" x2=\"15\" y1=\"12\" y2=\"18\" />\n <line x1=\"12\" x2=\"18\" y1=\"15\" y2=\"15\" />\n <rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\" />\n <path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\" />\n </svg>\n );\n}\n\n/** lucide `map-pin`. */\nexport function MapPinIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"map-pin\", props)}>\n <path d=\"M20 10c0 4.993-5.539 10.193-7.399 11.799a1 1 0 0 1-1.202 0C9.539 20.193 4 14.993 4 10a8 8 0 0 1 16 0\" />\n <circle cx=\"12\" cy=\"10\" r=\"3\" />\n </svg>\n );\n}\n\n/** lucide `at-sign`. */\nexport function AtSignIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"at-sign\", props)}>\n <circle cx=\"12\" cy=\"12\" r=\"4\" />\n <path d=\"M16 8v5a3 3 0 0 0 6 0v-1a10 10 0 1 0-4 8\" />\n </svg>\n );\n}\n\n/** lucide `link-2-off`. */\nexport function Link2OffIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"link-2-off\", props)}>\n <path d=\"M9 17H7A5 5 0 0 1 7 7\" />\n <path d=\"M15 7h2a5 5 0 0 1 4 8\" />\n <line x1=\"8\" x2=\"12\" y1=\"12\" y2=\"12\" />\n <line x1=\"2\" x2=\"22\" y1=\"2\" y2=\"22\" />\n </svg>\n );\n}\n\n/** lucide `whole-word`. */\nexport function WholeWordIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"whole-word\", props)}>\n <circle cx=\"7\" cy=\"12\" r=\"3\" />\n <path d=\"M10 9v6\" />\n <circle cx=\"17\" cy=\"12\" r=\"3\" />\n <path d=\"M14 7v8\" />\n <path d=\"M22 17v1c0 .5-.5 1-1 1H3c-.5 0-1-.5-1-1v-1\" />\n </svg>\n );\n}\n\n/** lucide `lightbulb`. */\nexport function LightbulbIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"lightbulb\", props)}>\n <path d=\"M15 14c.2-1 .7-1.7 1.5-2.5 1-.9 1.5-2.2 1.5-3.5A6 6 0 0 0 6 8c0 1 .2 2.2 1.5 3.5.7.7 1.3 1.5 1.5 2.5\" />\n <path d=\"M9 18h6\" />\n <path d=\"M10 22h4\" />\n </svg>\n );\n}\n\n/** lucide `shield-off`. */\nexport function ShieldOffIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"shield-off\", props)}>\n <path d=\"m2 2 20 20\" />\n <path d=\"M5 5a1 1 0 0 0-1 1v7c0 5 3.5 7.5 7.67 8.94a1 1 0 0 0 .67.01c2.35-.82 4.48-1.97 5.9-3.71\" />\n <path d=\"M9.309 3.652A12.252 12.252 0 0 0 11.24 2.28a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1v7a9.784 9.784 0 0 1-.08 1.264\" />\n </svg>\n );\n}\n\n/** lucide `chevrons-left`. */\nexport function ChevronsLeftIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"chevrons-left\", props)}>\n <path d=\"m11 17-5-5 5-5\" />\n <path d=\"m18 17-5-5 5-5\" />\n </svg>\n );\n}\n\n/** lucide `chevrons-right`. */\nexport function ChevronsRightIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"chevrons-right\", props)}>\n <path d=\"m6 17 5-5-5-5\" />\n <path d=\"m13 17 5-5-5-5\" />\n </svg>\n );\n}\n\n/** lucide `users-round`. */\nexport function UsersRoundIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"users-round\", props)}>\n <path d=\"M18 21a8 8 0 0 0-16 0\" />\n <circle cx=\"10\" cy=\"8\" r=\"5\" />\n <path d=\"M22 20c0-3.37-2-6.5-4-8a5 5 0 0 0-.45-8.3\" />\n </svg>\n );\n}\n\n/** lucide `landmark`. */\nexport function LandmarkIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"landmark\", props)}>\n <path d=\"M10 18v-7\" />\n <path d=\"M11.119 2.205a2 2 0 0 1 1.762 0l7.84 3.846A.5.5 0 0 1 20.5 7h-17a.5.5 0 0 1-.22-.949z\" />\n <path d=\"M14 18v-7\" />\n <path d=\"M18 18v-7\" />\n <path d=\"M3 22h18\" />\n <path d=\"M6 18v-7\" />\n </svg>\n );\n}\n\n/** lucide `factory`. */\nexport function FactoryIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"factory\", props)}>\n <path d=\"M12 16h.01\" />\n <path d=\"M16 16h.01\" />\n <path d=\"M3 19a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V8.5a.5.5 0 0 0-.769-.422l-4.462 2.844A.5.5 0 0 1 15 10.5v-2a.5.5 0 0 0-.769-.422L9.77 10.922A.5.5 0 0 1 9 10.5V5a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2z\" />\n <path d=\"M8 16h.01\" />\n </svg>\n );\n}\n\n/** lucide `chevrons-down` — CollapsibleText's \"expand all\". */\nexport function ChevronsDownIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"chevrons-down\", props)}>\n <path d=\"m7 6 5 5 5-5\" />\n <path d=\"m7 13 5 5 5-5\" />\n </svg>\n );\n}\n\n/** lucide `chevrons-up` — CollapsibleText's \"collapse all\". */\nexport function ChevronsUpIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"chevrons-up\", props)}>\n <path d=\"m17 11-5-5-5 5\" />\n <path d=\"m17 18-5-5-5 5\" />\n </svg>\n );\n}\n\n/** lucide `arrow-up-right` — CitationChip's \"open source\". */\nexport function ArrowUpRightIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"arrow-up-right\", props)}>\n <path d=\"M7 7h10v10\" />\n <path d=\"M7 17 17 7\" />\n </svg>\n );\n}\n\n/** lucide `quote` — CitationChip's excerpt blockquote. */\nexport function QuoteIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"quote\", props)}>\n <path d=\"M16 3a2 2 0 0 0-2 2v6a2 2 0 0 0 2 2 1 1 0 0 1 1 1v1a2 2 0 0 1-2 2 1 1 0 0 0-1 1v2a1 1 0 0 0 1 1 6 6 0 0 0 6-6V5a2 2 0 0 0-2-2z\" />\n <path d=\"M5 3a2 2 0 0 0-2 2v6a2 2 0 0 0 2 2 1 1 0 0 1 1 1v1a2 2 0 0 1-2 2 1 1 0 0 0-1 1v2a1 1 0 0 0 1 1 6 6 0 0 0 6-6V5a2 2 0 0 0-2-2z\" />\n </svg>\n );\n}\n\n/** lucide `panel-top-open` — the floating dock's phone menu button (opens the list). */\nexport function PanelTopOpenIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"panel-top-open\", props)}>\n <rect width=\"18\" height=\"18\" x=\"3\" y=\"3\" rx=\"2\" />\n <path d=\"M3 9h18\" />\n <path d=\"m15 14-3 3-3-3\" />\n </svg>\n );\n}\n\n/** lucide `panel-top-close` — the floating dock's phone menu button (closes the list). */\nexport function PanelTopCloseIcon(props: IconProps) {\n return (\n <svg {...lucideProps(\"panel-top-close\", props)}>\n <rect width=\"18\" height=\"18\" x=\"3\" y=\"3\" rx=\"2\" />\n <path d=\"M3 9h18\" />\n <path d=\"m9 16 3-3 3 3\" />\n </svg>\n );\n}\n","\"use client\";\n\n/**\n * Injected portal-container seam.\n *\n * The matrx-frontend original resolved nested portal targets through\n * `useNestedPortalContainer` (explicit prop > dialog content > popout body >\n * document.body) — a host-shaped hook wired to that app's dialog and\n * window-panel systems. The package inverts the seam: hosts provide the\n * resolved container through `PortalContainerProvider`; an explicit\n * `container` prop on a component still wins, and with neither the portal\n * falls through to `document.body` (Radix default). Priority semantics are\n * unchanged from the original.\n */\n\nimport * as React from \"react\";\n\n// Shared identity across independently bundled public entrypoints/loaders.\nconst CONTEXT_SLOT = Symbol.for(\"ai-matrx.design-system.portal-container-context\");\nconst contextRegistry = globalThis as typeof globalThis & { [CONTEXT_SLOT]?: React.Context<HTMLElement | null | undefined> };\nconst PortalContainerContext = contextRegistry[CONTEXT_SLOT] ??= React.createContext<HTMLElement | null | undefined>(undefined);\n\nexport interface PortalContainerProviderProps {\n /** Where nested Radix portals (Popover, etc.) should mount. `null`/`undefined` → document.body. */\n container: HTMLElement | null | undefined;\n children: React.ReactNode;\n}\n\nexport function PortalContainerProvider({\n container,\n children,\n}: PortalContainerProviderProps) {\n return (\n <PortalContainerContext.Provider value={container ?? undefined}>\n {children}\n </PortalContainerContext.Provider>\n );\n}\n\n/**\n * Resolve a portal target: explicit prop (including an explicit `null`,\n * meaning \"the default body\") beats the injected container.\n */\nexport function usePortalContainer(\n explicit?: HTMLElement | null,\n): HTMLElement | undefined {\n const injected = React.useContext(PortalContainerContext);\n\n if (explicit !== undefined) {\n return explicit ?? undefined;\n }\n\n return injected ?? undefined;\n}\n","\"use client\";\n\n/**\n * THE LOOK — one implementation, the host's native skin.\n *\n * A shared workspace (the Vault, …) is written ONCE in the web vocabulary (`/controls`, the root\n * Dialog/menus, semantic Tailwind tokens). Inside Matrx Desktop it must look like a Mac app (the\n * desktop standard, `desktop/DESKTOP.md`). `LookScope look=\"desktop\"` is that switch:\n *\n * - it draws a `data-matrx-look=\"desktop\"` box; `look-desktop.css` (imported by styles.css, inert\n * without the attribute) puts the web tokens on AppKit's values, Tailwind's type scale on\n * Apple's text styles, the platform's system font, and the `/controls` on NSControl geometry;\n * - every portal-aware layer opened inside it (Dialog, Popover, menus, Select, Tooltip) mounts in a\n * layer that carries the same attribute, so a menu or sheet wears the look too;\n * - `useLook()` tells a component the look, so the root `DialogContent` becomes a macOS sheet.\n *\n * `look=\"web\"` (the default) renders its children only: the web output is byte-for-byte unchanged.\n * Never a second component tree, never per-call-site overrides.\n */\n\nimport * as React from \"react\";\nimport { PortalContainerProvider } from \"./portal-container\";\n\nexport type Look = \"web\" | \"desktop\";\n\n// Shared identity across independently bundled public entrypoints (as portal-container does).\nconst CONTEXT_SLOT = Symbol.for(\"ai-matrx.design-system.look-context\");\nconst registry = globalThis as typeof globalThis & { [CONTEXT_SLOT]?: React.Context<Look> };\nconst LookContext = (registry[CONTEXT_SLOT] ??= React.createContext<Look>(\"web\"));\n\n/** The look the nearest `LookScope` chose; `\"web\"` outside any scope. */\nexport function useLook(): Look {\n return React.useContext(LookContext);\n}\n\nexport const LOOK_ATTRIBUTE = \"data-matrx-look\";\n\nexport interface LookScopeProps extends React.HTMLAttributes<HTMLDivElement> {\n look: Look;\n children: React.ReactNode;\n}\n\n/** The layer every portal opened inside a desktop scope mounts in: a body child wearing the look. */\nfunction useLookLayer(look: Look): HTMLElement | null {\n const [layer, setLayer] = React.useState<HTMLElement | null>(null);\n React.useEffect(() => {\n if (look === \"web\" || typeof document === \"undefined\") return;\n const el = document.createElement(\"div\");\n el.setAttribute(LOOK_ATTRIBUTE, look);\n el.setAttribute(\"data-slot\", \"look-layer\");\n document.body.appendChild(el);\n setLayer(el);\n return () => {\n el.remove();\n setLayer(null);\n };\n }, [look]);\n return layer;\n}\n\nexport function LookScope({ look, children, ...div }: LookScopeProps) {\n const layer = useLookLayer(look);\n if (look === \"web\") return <LookContext.Provider value=\"web\">{children}</LookContext.Provider>;\n return (\n <LookContext.Provider value={look}>\n <div {...div} {...{ [LOOK_ATTRIBUTE]: look }}>\n <PortalContainerProvider container={layer}>{children}</PortalContainerProvider>\n </div>\n </LookContext.Provider>\n );\n}\n","\"use client\";\n\n/**\n * Ported verbatim from matrx-frontend `components/ui/radix-dialog-modal-context.tsx`.\n * Shared by the Sheet and BottomSheet families (and available to hosts that\n * compose their own Radix Dialog-derived wrappers around these primitives).\n */\n\nimport * as React from \"react\";\n\n// Shared identity across independently bundled public entrypoints/loaders.\nconst CONTEXT_SLOT = Symbol.for(\"ai-matrx.design-system.dialog-modal-context\");\nconst contextRegistry = globalThis as typeof globalThis & { [CONTEXT_SLOT]?: React.Context<boolean> };\nconst RadixDialogModalContext = contextRegistry[CONTEXT_SLOT] ??= React.createContext<boolean>(true);\n\nexport interface RadixDialogModalProviderProps {\n children: React.ReactNode;\n modal: boolean;\n}\n\n/**\n * Keeps our Radix-based content wrappers aligned with the owning Root's\n * modality so ARIA semantics cannot drift from focus/pointer behavior.\n */\nexport function RadixDialogModalProvider({\n children,\n modal,\n}: RadixDialogModalProviderProps) {\n return (\n <RadixDialogModalContext.Provider value={modal}>\n {children}\n </RadixDialogModalContext.Provider>\n );\n}\n\n/** Returns whether the nearest Radix Dialog-derived root is modal. */\nexport function useRadixDialogModal(): boolean {\n return React.useContext(RadixDialogModalContext);\n}\n","/**\n * useIsMobile — the ONE breakpoint hook the package's responsive primitives\n * read (CommandDialog and Dialog both auto-render as a bottom sheet below it).\n *\n * The body lives in `@ai-matrx/kit/media-query` (chat-package independence\n * P12, 2026-10-01): the app's `hooks/use-mobile` and this package each carried\n * their own copy, and two breakpoint hooks is exactly the duplication this\n * package exists to end. Kit's reads through `useSyncExternalStore` — `false`\n * on the server and during hydration, so the desktop geometry hydrates — and\n * never throws where `matchMedia` is absent.\n */\nexport { MOBILE_BREAKPOINT, useIsMobile } from \"@ai-matrx/kit/media-query\";\n","/**\n * THE FRONT-MOST LAYER — one signal every floating layer shares, so the layer\n * the person used last is the one on top.\n *\n * A windowed Dialog sits at z-10000 so it is never behind the menu, popover or\n * host window it was opened from (0.38.1). But a host window opened or focused\n * AFTER it — the window an agent run opens from the Agents menu while Table\n * settings is open — then sat underneath it, and its composer could not be\n * clicked or typed into (found live 2026-09-26, register ARE-010). Recency has\n * to decide, across both systems, without coupling them.\n *\n * So any layer that comes to the front announces it: `announceLayerFront(el)`\n * dispatches `matrx:layer-front` on `document`. A windowed Dialog announces\n * itself when it opens and when the person presses or focuses inside it; it\n * steps BEHIND (z-999, still above the page and below the host's window\n * manager at 1000+) whenever another layer announces, and comes back the\n * moment the person reaches for it. A host window manager announces its\n * window on open and on focus.\n */\n\nexport const LAYER_FRONT_EVENT = \"matrx:layer-front\";\n\nexport interface LayerFrontDetail {\n /** The element that came to the front. */\n element: Element | null;\n}\n\n/** Tell every other floating layer that `element` is now the one in front. */\nexport function announceLayerFront(element: Element | null): void {\n if (typeof document === \"undefined\") return;\n document.dispatchEvent(\n new CustomEvent<LayerFrontDetail>(LAYER_FRONT_EVENT, { detail: { element } }),\n );\n}\n","/**\n * THE WINDOW DRAG — the ONE pointer-drag / resize / viewport-clamp primitive\n * every floating surface uses: a windowed Dialog's header, a PeekWindow, the\n * desktop InspectorPanel, @ai-matrx/summon's WindowPanel, Dock and LiteWindow,\n * and @ai-matrx/associations' DefaultWindowShell. It lives at this layer\n * because every one of them sits on design-system; nothing below may fork it.\n *\n * Three layers, use the highest one that fits:\n *\n * 1. `useDragMove()` — the React hook. A pointer move PAINTS the element\n * inside one animation frame (CSS `translate`, plus `width`/`height` for a\n * resize) and the host's state is committed EXACTLY ONCE, on release.\n * Writing state per pointer event re-renders whatever streams inside the\n * window sixty times a second (paid for in Workflow Studio's floating chat\n * and chat's ChatPanel). It also carries THE CURSOR LAW (`holdDragCursor`\n * for the whole gesture), z-order (`announceLayerFront` on press), the\n * \"controls in the handle stay controls\" rule, and a cleanup that leaves\n * no listener, frame or cursor behind on unmount.\n * 2. `startPointerDrag()` — the gesture lifecycle alone (window listeners per\n * pointer id, threshold, cursor hold, frame-coalesced moves, trailing-click\n * swallow, cancel). For a host whose moves must reach a store live (summon's\n * WindowPanel: pop-out drag-out detection and window-manager geometry).\n * 3. Pure geometry — `resizeRect()` (8-edge resize with size limits) and\n * `clampRectToViewport()` (the header always stays reachable).\n */\n\nimport {\n useCallback,\n useEffect,\n useLayoutEffect,\n useRef,\n useState,\n type PointerEvent as ReactPointerEvent,\n} from \"react\";\n\nimport { type DragCursor, holdDragCursor } from \"./drag-cursor\";\nimport { announceLayerFront } from \"./layer-front\";\n\n// ── Geometry ─────────────────────────────────────────────────────────────────\n\n/** A window's box in px — viewport px unless the host measures in a container. */\nexport interface DragRect {\n x: number;\n y: number;\n width: number;\n height: number;\n}\n\nexport interface DragViewport {\n width: number;\n height: number;\n}\n\n/** The edge or corner a resize handle grabs. */\nexport type ResizeEdge = \"n\" | \"s\" | \"e\" | \"w\" | \"ne\" | \"nw\" | \"se\" | \"sw\";\n\n/** The cursor held on the document while each edge resizes (THE CURSOR LAW). */\nexport const RESIZE_EDGE_CURSOR: Record<ResizeEdge, DragCursor> = {\n e: \"ew-resize\",\n w: \"ew-resize\",\n n: \"ns-resize\",\n s: \"ns-resize\",\n se: \"nwse-resize\",\n nw: \"nwse-resize\",\n ne: \"nesw-resize\",\n sw: \"nesw-resize\",\n};\n\nexport interface SizeLimits {\n minWidth?: number;\n minHeight?: number;\n maxWidth?: number;\n maxHeight?: number;\n}\n\n/** Controls inside a drag handle that stay controls — a press there never starts a drag. */\nexport const DRAG_IGNORE_SELECTOR =\n \"button,a,input,select,textarea,[role='button'],[contenteditable='true'],[data-no-drag]\";\n\nconst bound = (value: number, min: number, max: number): number => Math.min(max, Math.max(min, value));\n\n/**\n * `origin` resized by a pointer that traveled (`dx`, `dy`) from the press on\n * `edge`. A west or north edge keeps the opposite edge still; sizes honor\n * `limits`.\n */\nexport function resizeRect(origin: DragRect, edge: ResizeEdge, dx: number, dy: number, limits: SizeLimits = {}): DragRect {\n const minWidth = limits.minWidth ?? 0;\n const minHeight = limits.minHeight ?? 0;\n const maxWidth = limits.maxWidth ?? Number.POSITIVE_INFINITY;\n const maxHeight = limits.maxHeight ?? Number.POSITIVE_INFINITY;\n const next = { ...origin };\n if (edge.includes(\"e\")) next.width = bound(origin.width + dx, minWidth, maxWidth);\n if (edge.includes(\"s\")) next.height = bound(origin.height + dy, minHeight, maxHeight);\n if (edge.includes(\"w\")) {\n next.width = bound(origin.width - dx, minWidth, maxWidth);\n next.x = origin.x + (origin.width - next.width);\n }\n if (edge.includes(\"n\")) {\n next.height = bound(origin.height - dy, minHeight, maxHeight);\n next.y = origin.y + (origin.height - next.height);\n }\n return next;\n}\n\nexport interface ViewportClamp {\n /** Smallest gap kept to the viewport edge. Default 0. */\n margin?: number;\n /**\n * Px of the window that must stay on screen horizontally and below the top\n * edge. Omit to keep the WHOLE window on screen. Either way the top edge (the\n * header) is never above `margin`, and a window larger than the room keeps\n * its top-left visible — an unreachable header is an unclosable window.\n */\n keepVisible?: number;\n /** Shrink the window to the room (never below these) before placing it. */\n fit?: { minWidth: number; minHeight: number };\n}\n\n/** `rect` kept reachable inside `viewport` (see `ViewportClamp`). */\nexport function clampRectToViewport(rect: DragRect, viewport: DragViewport, clamp: ViewportClamp = {}): DragRect {\n const margin = clamp.margin ?? 0;\n let { width, height } = rect;\n if (clamp.fit) {\n width = Math.min(width, Math.max(clamp.fit.minWidth, viewport.width - margin * 2));\n height = Math.min(height, Math.max(clamp.fit.minHeight, viewport.height - margin * 2));\n }\n const keep = clamp.keepVisible;\n const lowX = keep === undefined ? margin : margin + Math.min(keep, width) - width;\n const highX = keep === undefined ? viewport.width - width - margin : viewport.width - Math.min(keep, width) - margin;\n const highY = keep === undefined ? viewport.height - height - margin : viewport.height - Math.min(keep, height) - margin;\n return {\n width,\n height,\n x: Math.round(Math.max(lowX, Math.min(rect.x, highX))),\n y: Math.round(Math.max(margin, Math.min(rect.y, highY))),\n };\n}\n\n/** The browser viewport (a sane desktop size during SSR). */\nexport function readViewport(): DragViewport {\n return typeof window === \"undefined\" ? { width: 1280, height: 800 } : { width: window.innerWidth, height: window.innerHeight };\n}\n\n// ── The gesture ──────────────────────────────────────────────────────────────\n\nexport interface DragDelta {\n dx: number;\n dy: number;\n}\n\nexport interface PointerDragOptions {\n /** Px the pointer must travel before the press becomes a drag. Default 0 (a drag from the press). */\n threshold?: number;\n /** Cursor held on the document while dragging. Default `grabbing`; `null` holds none. */\n cursor?: DragCursor | null;\n /** Coalesce moves to one call per animation frame. Default true. */\n frame?: boolean;\n /** Swallow the click the browser fires after a real drag. Default: `threshold > 0`. */\n swallowClick?: boolean;\n /** The press became a drag (immediately when `threshold` is 0). */\n onStart?(): void;\n /** The pointer traveled `delta` from the press (only after `onStart`). */\n onMove(delta: DragDelta, event: PointerEvent): void;\n /** Released or canceled by the browser. `moved` is false for a press that never traveled. */\n onEnd?(delta: DragDelta, info: { moved: boolean; started: boolean; cancelled: boolean }): void;\n}\n\nexport interface PointerDragHandle {\n /** Abort silently (unmount, close): listeners, frame and cursor are released, `onEnd` is not called. */\n cancel(): void;\n}\n\ninterface PressPoint {\n clientX: number;\n clientY: number;\n pointerId: number;\n}\n\n/** Track one pointer from its press until release. See the module doc. */\nexport function startPointerDrag(press: PressPoint, options: PointerDragOptions): PointerDragHandle {\n const threshold = options.threshold ?? 0;\n const useFrame = options.frame !== false;\n const swallowClick = options.swallowClick ?? threshold > 0;\n let started = false;\n let moved = false;\n let releaseCursor: (() => void) | null = null;\n let frame: number | null = null;\n let pending: { delta: DragDelta; event: PointerEvent } | null = null;\n let last: DragDelta = { dx: 0, dy: 0 };\n let done = false;\n\n const start = () => {\n started = true;\n if (options.cursor !== null) releaseCursor = holdDragCursor(options.cursor ?? \"grabbing\");\n options.onStart?.();\n };\n const flush = () => {\n frame = null;\n if (!pending) return;\n const { delta, event } = pending;\n pending = null;\n options.onMove(delta, event);\n };\n const onMove = (event: PointerEvent) => {\n if (event.pointerId !== press.pointerId) return;\n const delta = { dx: event.clientX - press.clientX, dy: event.clientY - press.clientY };\n if (!started) {\n if (Math.abs(delta.dx) < threshold && Math.abs(delta.dy) < threshold) return;\n start();\n }\n if (delta.dx !== 0 || delta.dy !== 0) moved = true;\n last = delta;\n pending = { delta, event };\n if (!useFrame || typeof window.requestAnimationFrame !== \"function\") flush();\n else if (frame === null) frame = window.requestAnimationFrame(flush);\n };\n const teardown = () => {\n done = true;\n window.removeEventListener(\"pointermove\", onMove);\n window.removeEventListener(\"pointerup\", onUp);\n window.removeEventListener(\"pointercancel\", onUp);\n if (frame !== null) window.cancelAnimationFrame?.(frame);\n frame = null;\n releaseCursor?.();\n releaseCursor = null;\n };\n const onUp = (event: PointerEvent) => {\n if (event.pointerId !== press.pointerId || done) return;\n // The last position is painted before the gesture ends, never dropped with its frame.\n if (pending) flush();\n teardown();\n options.onEnd?.(last, { moved, started, cancelled: event.type === \"pointercancel\" });\n if (moved && swallowClick) {\n const swallow = (click: MouseEvent) => {\n click.stopPropagation();\n click.preventDefault();\n };\n window.addEventListener(\"click\", swallow, { capture: true, once: true });\n window.setTimeout(() => window.removeEventListener(\"click\", swallow, { capture: true }), 0);\n }\n };\n\n window.addEventListener(\"pointermove\", onMove);\n window.addEventListener(\"pointerup\", onUp);\n window.addEventListener(\"pointercancel\", onUp);\n if (threshold <= 0) start();\n return {\n cancel: () => {\n if (!done) teardown();\n },\n };\n}\n\n// ── The hook ─────────────────────────────────────────────────────────────────\n\n/** What a gesture is doing: moving the window, or resizing it from an edge. */\nexport type DragGesture = \"move\" | ResizeEdge;\n\nexport interface DragCommit {\n /** The window's box when pressed. */\n origin: DragRect;\n gesture: DragGesture;\n /** Pointer travel, after `constrain`: `rect.x - origin.x`, `rect.y - origin.y`. */\n delta: DragDelta;\n /** `paint: \"offset\"` only: the host's `offset` at the press plus `delta`. */\n offset: { x: number; y: number };\n}\n\nexport interface UseDragMoveOptions {\n /** The element that MOVES (the window frame). */\n element: HTMLElement | null;\n /** Default true. False: presses do nothing (a phone sheet, a maximized window). */\n enabled?: boolean;\n /** Px before a press becomes a drag. Default 0. A handle that is also a click target passes 4. */\n threshold?: number;\n /** Allow touch drags. Default true. */\n touch?: boolean;\n /** Controls inside a handle that never start a drag. Default `DRAG_IGNORE_SELECTOR`; `null` = none. */\n ignore?: string | null;\n /** Announce the element as the front-most layer on press (layer-front.ts). Default true. */\n announce?: boolean;\n /**\n * How a drag paints the element before the commit:\n * - `delta` (default): `translate` by the travel, cleared in the commit's own render\n * (the host positions with left/top/right/bottom and commits the new place);\n * - `offset`: the host renders `translate` from its own `offset` — the drag paints\n * `offset + travel` and leaves it for the host's commit to own.\n */\n paint?: \"delta\" | \"offset\";\n /** The host's committed translate (`paint: \"offset\"`). */\n offset?: { x: number; y: number };\n /** The window's box at the press. Default: the element's viewport rect. */\n getRect?: () => DragRect;\n /** Keep every painted box legal (e.g. `clampRectToViewport`). */\n constrain?: (next: DragRect, gesture: DragGesture, origin: DragRect) => DragRect;\n /** Resize size limits. */\n limits?: SizeLimits;\n /** Cursor held while moving. Default `grabbing` (resizes hold their edge's cursor). */\n cursor?: DragCursor;\n /** A press is starting a gesture (focus or raise the window here). */\n onPress?: (event: ReactPointerEvent<HTMLElement>, gesture: DragGesture) => void;\n /** Every painted frame — for observers that are NOT React state. */\n onFrame?: (rect: DragRect, gesture: DragGesture) => void;\n /** Once per gesture that moved, on release. Commit the host's state here. */\n onCommit: (rect: DragRect, commit: DragCommit) => void;\n}\n\nexport interface DragMoveApi {\n /** Spread onto the element you drag BY: `onPointerDown={drag.onPointerDown}`. */\n onPointerDown: (event: ReactPointerEvent<HTMLElement>) => void;\n /** `onPointerDown` for the handle that resizes from `edge`. */\n resizeHandle: (edge: ResizeEdge) => (event: ReactPointerEvent<HTMLElement>) => void;\n /** True from the moment a press becomes a drag until release. */\n dragging: boolean;\n /** Abandon a drag in flight (the window closed): nothing is committed, the cursor is released. */\n cancel: () => void;\n}\n\n/** Drag and resize a floating element without re-rendering it while the pointer moves. */\nexport function useDragMove(options: UseDragMoveOptions): DragMoveApi {\n const live = useRef(options);\n useLayoutEffect(() => {\n live.current = options;\n });\n const [dragging, setDragging] = useState(false);\n const gestureRef = useRef<PointerDragHandle | null>(null);\n /** The translate to put back once the commit has rendered (`paint: \"delta\"`). */\n const restoreRef = useRef<{ element: HTMLElement; translate: string } | null>(null);\n\n useLayoutEffect(() => {\n const restore = restoreRef.current;\n if (!restore) return;\n restoreRef.current = null;\n restore.element.style.translate = restore.translate;\n });\n\n useEffect(\n () => () => {\n gestureRef.current?.cancel();\n gestureRef.current = null;\n },\n [],\n );\n\n const begin = useCallback((event: ReactPointerEvent<HTMLElement>, gesture: DragGesture) => {\n const opts = live.current;\n const element = opts.element;\n if (opts.enabled === false || !element || event.button !== 0) return;\n if (opts.touch === false && event.pointerType === \"touch\") return;\n const target = event.target instanceof Element ? event.target : null;\n const ignore = opts.ignore === undefined ? DRAG_IGNORE_SELECTOR : opts.ignore;\n if (gesture === \"move\" && ignore && target) {\n const hit = target.closest(ignore);\n if (hit && hit !== event.currentTarget && event.currentTarget.contains(hit)) return;\n }\n // A press on bare chrome must not start a text selection; a press on a control keeps its default.\n if (gesture !== \"move\" || !target?.closest(\"button,a,input,select,textarea,label,[role=button]\")) event.preventDefault();\n if (gesture !== \"move\") event.stopPropagation();\n gestureRef.current?.cancel();\n opts.onPress?.(event, gesture);\n if (opts.announce !== false) announceLayerFront(element);\n\n const origin = opts.getRect?.() ?? (() => {\n const rect = element.getBoundingClientRect();\n return { x: rect.left, y: rect.top, width: rect.width, height: rect.height };\n })();\n const paintMode = opts.paint ?? \"delta\";\n const base = paintMode === \"offset\" ? (opts.offset ?? { x: 0, y: 0 }) : { x: 0, y: 0 };\n const baseTranslate = element.style.translate;\n let latest = origin;\n\n gestureRef.current = startPointerDrag(event, {\n threshold: opts.threshold ?? 0,\n cursor: gesture === \"move\" ? (opts.cursor ?? \"grabbing\") : RESIZE_EDGE_CURSOR[gesture],\n onStart: () => setDragging(true),\n onMove: ({ dx, dy }) => {\n const now = live.current;\n const raw =\n gesture === \"move\"\n ? { ...origin, x: origin.x + dx, y: origin.y + dy }\n : resizeRect(origin, gesture, dx, dy, now.limits);\n latest = now.constrain ? now.constrain(raw, gesture, origin) : raw;\n element.style.translate = `${base.x + latest.x - origin.x}px ${base.y + latest.y - origin.y}px`;\n if (gesture !== \"move\") {\n element.style.width = `${latest.width}px`;\n element.style.height = `${latest.height}px`;\n }\n now.onFrame?.(latest, gesture);\n },\n onEnd: (_delta, { moved, started }) => {\n gestureRef.current = null;\n if (started) setDragging(false);\n if (!moved) return;\n if (paintMode === \"delta\") restoreRef.current = { element, translate: baseTranslate };\n const delta = { dx: latest.x - origin.x, dy: latest.y - origin.y };\n live.current.onCommit(latest, {\n origin,\n gesture,\n delta,\n offset: { x: base.x + delta.dx, y: base.y + delta.dy },\n });\n },\n });\n }, []);\n\n const onPointerDown = useCallback((event: ReactPointerEvent<HTMLElement>) => begin(event, \"move\"), [begin]);\n const resizeHandle = useCallback(\n (edge: ResizeEdge) => (event: ReactPointerEvent<HTMLElement>) => begin(event, edge),\n [begin],\n );\n\n const cancel = useCallback(() => {\n if (!gestureRef.current) return;\n gestureRef.current.cancel();\n gestureRef.current = null;\n setDragging(false);\n }, []);\n\n return { onPointerDown, resizeHandle, dragging, cancel };\n}\n","/**\n * THE DRAG CURSOR HOLD — the ONE way a drag sets its cursor (THE CURSOR LAW,\n * common-docs/policies/cursor-law.md).\n *\n * A cursor set on the dragged element flickers: the pointer outruns the\n * element, crosses a button or a field, and the cursor changes under it. So a\n * drag holds its cursor on `<html data-dragging=\"…\">` for its whole duration,\n * and `styles.css` § THE CURSOR LAW pins that cursor on every element,\n * important, in the first layer (`matrx-tap-lock`), so nothing — not a\n * utility, not the tap lock's own `cursor: pointer !important` — can override\n * it mid-drag.\n *\n * const release = holdDragCursor(); // pointerdown\n * … // pointermove\n * release(); // pointerup / pointercancel\n *\n * Holds nest: the newest hold's cursor shows, and the attribute clears only\n * when every hold has released. A release is idempotent.\n *\n * Inside a dnd-kit `<DndContext>`, render `<DragCursorMonitor />` (from\n * `./drag-cursor-monitor`) instead of calling this by hand.\n */\n\nexport const DRAG_CURSORS = [\n \"grabbing\",\n \"move\",\n \"col-resize\",\n \"row-resize\",\n \"ew-resize\",\n \"ns-resize\",\n \"nwse-resize\",\n \"nesw-resize\",\n] as const;\n\nexport type DragCursor = (typeof DRAG_CURSORS)[number];\n\nconst holds: { id: number; cursor: DragCursor }[] = [];\nlet nextId = 0;\n\nfunction apply(): void {\n if (typeof document === \"undefined\") return;\n const root = document.documentElement;\n const top = holds[holds.length - 1];\n if (top) root.dataset.dragging = top.cursor;\n else delete root.dataset.dragging;\n}\n\n/** Hold `cursor` on the whole document until the returned release is called. */\nexport function holdDragCursor(cursor: DragCursor = \"grabbing\"): () => void {\n const id = nextId++;\n holds.push({ id, cursor });\n apply();\n let released = false;\n return () => {\n if (released) return;\n released = true;\n const index = holds.findIndex((hold) => hold.id === id);\n if (index >= 0) holds.splice(index, 1);\n apply();\n };\n}\n","\"use client\";\n\n/**\n * FLOATING LAYERS OPENED FROM INSIDE A MODAL — one contract, every surface.\n *\n * A blocking surface (a `modal` Dialog, AlertDialog, Sheet, Drawer,\n * BottomSheet, CommandDialog — and every Dialog on a phone) paints a scrim at\n * the modal tier, `MODAL_LAYER_Z`. Radix children of that surface (Popover,\n * Select, menus) are safe: they portal into it or after it at the same z, and\n * Radix counts a press inside them as inside. A floating layer that is NOT a\n * Radix child — a host window manager's window, the associations picker\n * window, anything `createPortal`ed to `<body>` at its own z — was not: it\n * painted UNDER the scrim (a window manager lives near z-1000), so the click\n * that picked an option landed on the scrim and closed the modal (Source\n * screen side sheet + association picker, 2026-09-26). Behind the scrim it\n * would also have lost focus to the modal's trap and had presses inside it\n * counted as outside-clicks.\n *\n * The contract, in three parts:\n *\n * 1. Every modal content registers while it is open (`useModalLayer`), and\n * treats a press or focus inside any `[data-matrx-floating-layer]` as\n * inside (`keepFloatingLayersInside`).\n * 2. A floating layer reads `useFloatingLayerZIndex(ownZ)`: while a modal is\n * open it is lifted to the modal tier. Equal z, so DOM order decides — a\n * layer opened AFTER the modal (portal appended later) paints above its\n * scrim; a window that was already open stays underneath, as it should.\n * While lifted, several floating layers order by when they opened, not by\n * their own manager's focus order; that returns when the modal closes.\n * 3. A floating layer's root is wrapped in `<FloatingLayer>`: it carries the\n * marker attribute, re-asserts `pointer-events: auto` (a modal sets `none`\n * on `<body>`), and mounts a non-trapping focus scope, which pauses the\n * modal's focus trap while the layer is open so its inputs take focus.\n *\n * 4. Popper content (a Popover, a combobox) a floating layer opens is portaled\n * to <body>; while a floating layer is open it counts as part of it, and\n * wheel/touchmove inside either stops at <body> so the modal's scroll lock\n * never cancels it.\n *\n * Guard: `floating-layer.test.tsx` — a window-manager-style layer opened from\n * each blocking surface must stack above the scrim, keep the modal open when\n * it or a popover it opened is pressed, scroll, keep focus in its own input,\n * and hand focus back to its opener when it closes.\n */\n\nimport { FocusScope } from \"@radix-ui/react-focus-scope\";\nimport { Slot } from \"@radix-ui/react-slot\";\nimport * as React from \"react\";\n\n/** The modal tier: every blocking scrim and its content sit here. */\nexport const MODAL_LAYER_Z = 10000;\n\n/** THE tooltip layer (defined beside the tooltips, `title-tooltips.ts`). */\nexport { TOOLTIP_LAYER_Z } from \"./title-tooltips\";\n\n/** Marker attribute on the root of a floating layer. */\nexport const FLOATING_LAYER_ATTR = \"data-matrx-floating-layer\";\n\n// ── the open-modal registry ─────────────────────────────────────────────────\n// Shared identity across independently bundled public entrypoints, like the\n// dialog contexts: two copies of this module must see one count.\ninterface ModalLayerRegistry {\n count: number;\n listeners: Set<() => void>;\n}\nconst REGISTRY_SLOT = Symbol.for(\"ai-matrx.design-system.modal-layer-registry\");\nconst registryHost = globalThis as typeof globalThis & {\n [REGISTRY_SLOT]?: ModalLayerRegistry;\n};\nconst registry: ModalLayerRegistry = (registryHost[REGISTRY_SLOT] ??= {\n count: 0,\n listeners: new Set(),\n});\n\nfunction emit(): void {\n for (const listener of registry.listeners) listener();\n}\n\n// A modal's scroll lock (react-remove-scroll) cancels wheel and touchmove on\n// `document` for anything outside the modal's own content — including a\n// floating layer opened from it, whose list then never scrolls. While a modal\n// is open, a scroll gesture inside a floating layer stops at <body>: React's\n// own portal listener on <body> still sees it (stopPropagation never stops\n// listeners on the same node), the lock on `document` never does.\nconst SCROLL_EVENTS = [\"wheel\", \"touchmove\"] as const;\nfunction stopAtBody(event: Event): void {\n if (isInsideFloatingLayer(event.target)) event.stopPropagation();\n}\nfunction setScrollPassthrough(on: boolean): void {\n if (typeof document === \"undefined\" || !document.body) return;\n for (const type of SCROLL_EVENTS) {\n if (on) document.body.addEventListener(type, stopAtBody, { passive: true });\n else document.body.removeEventListener(type, stopAtBody);\n }\n}\n\n/** Register one open modal layer; returns its release. */\nexport function registerModalLayer(): () => void {\n registry.count += 1;\n if (registry.count === 1) setScrollPassthrough(true);\n emit();\n let released = false;\n return () => {\n if (released) return;\n released = true;\n registry.count = Math.max(0, registry.count - 1);\n if (registry.count === 0) setScrollPassthrough(false);\n emit();\n };\n}\n\n/** True while at least one blocking surface is open. */\nexport function isModalLayerOpen(): boolean {\n return registry.count > 0;\n}\n\nfunction subscribe(listener: () => void): () => void {\n registry.listeners.add(listener);\n return () => registry.listeners.delete(listener);\n}\n\n/** Reactive `isModalLayerOpen()`. */\nexport function useModalLayerOpen(): boolean {\n return React.useSyncExternalStore(subscribe, isModalLayerOpen, () => false);\n}\n\n/**\n * Called by every modal content while it is mounted. `active` is false for a\n * content whose root is not modal (a windowed dialog, a `modal={false}` sheet).\n */\nexport function useModalLayer(active: boolean): void {\n React.useLayoutEffect(() => (active ? registerModalLayer() : undefined), [active]);\n}\n\n// ── the outside-click guard ─────────────────────────────────────────────────\n\nconst POPPER_WRAPPER = \"[data-radix-popper-content-wrapper]\";\n\n/**\n * True when `target` is inside a floating layer — or inside popper content (a\n * Popover, a combobox list) while a floating layer is open. Popper content a\n * window opens is portaled to <body>, outside the window's own element and\n * outside the modal's React tree; popper content the MODAL opens is portaled\n * into the modal and never reaches this check.\n */\nexport function isInsideFloatingLayer(target: EventTarget | null | undefined): boolean {\n if (!(target instanceof Element)) return false;\n if (target.closest(`[${FLOATING_LAYER_ATTR}]`)) return true;\n return (\n target.closest(POPPER_WRAPPER) !== null &&\n target.ownerDocument.querySelector(`[${FLOATING_LAYER_ATTR}]`) !== null\n );\n}\n\n/**\n * Wrap a Radix `onInteractOutside` so a press or focus inside a floating layer\n * never dismisses the modal. The caller's handler still runs first.\n */\nexport function keepFloatingLayersInside<\n E extends { target: EventTarget | null; preventDefault: () => void },\n>(handler?: (event: E) => void): (event: E) => void {\n return (event) => {\n handler?.(event);\n if (isInsideFloatingLayer(event.target)) event.preventDefault();\n };\n}\n\n// ── the floating layer's side ───────────────────────────────────────────────\n\n/** Pure form of `useFloatingLayerZIndex`, for callers outside React. */\nexport function floatingLayerZIndex(ownZ: number, modalOpen: boolean): number {\n return modalOpen ? Math.max(ownZ, MODAL_LAYER_Z) : ownZ;\n}\n\n/** The z-index a floating layer should paint at, given its own. */\nexport function useFloatingLayerZIndex(ownZ: number): number {\n return floatingLayerZIndex(ownZ, useModalLayerOpen());\n}\n\nconst preventAutoFocus = (event: Event) => event.preventDefault();\n\n/**\n * Wrap the root element of a floating layer (exactly one element child).\n * Marks it, keeps it pressable under a modal's `pointer-events: none` body,\n * and pauses the modal's focus trap while it is mounted. It never takes focus\n * on open. On close, if focus was lost with it while a modal is still open,\n * focus returns to the control that opened it — otherwise the next Tab would\n * land behind the modal.\n */\nexport const FloatingLayer = React.forwardRef<\n HTMLElement,\n { children: React.ReactElement }\n>(({ children }, ref) => {\n const [opener] = React.useState<Element | null>(() =>\n typeof document === \"undefined\" ? null : document.activeElement,\n );\n const returnFocus = (event: Event) => {\n event.preventDefault();\n const active = document.activeElement;\n const lost = !active || active === document.body || !active.isConnected;\n if (lost && isModalLayerOpen() && opener instanceof HTMLElement && opener.isConnected) {\n opener.focus({ preventScroll: true });\n }\n };\n return (\n <FocusScope\n asChild\n trapped={false}\n loop={false}\n onMountAutoFocus={preventAutoFocus}\n onUnmountAutoFocus={returnFocus}\n >\n <Slot\n ref={ref}\n {...{ [FLOATING_LAYER_ATTR]: \"\" }}\n style={{ pointerEvents: \"auto\" }}\n >\n {children}\n </Slot>\n </FocusScope>\n );\n});\nFloatingLayer.displayName = \"FloatingLayer\";\n\n// ── THE Escape stack ────────────────────────────────────────────────────────\n// One Escape owner for every floating window (summon's WindowPanel and\n// LiteWindow, the PeekWindow here): the TOPMOST open layer gets the key, and\n// only it — two windows never close on one press, and a window under another\n// never closes first. A layer joins on open (top), `raise()`s when it comes to\n// the front (a focused window), and leaves on close. Its handler decides\n// whether it closes (a menu or dialog it does not own may hold the key) and\n// calls `preventDefault()` when it does; a layer that declines still keeps the\n// key from the layers under it. One window listener, shared across bundled\n// copies of this module through a global slot (like the modal registry).\ninterface EscapeLayerEntry {\n readonly key: symbol;\n handle: (event: KeyboardEvent) => void;\n}\ninterface EscapeStack {\n layers: EscapeLayerEntry[];\n listening: boolean;\n}\nconst ESCAPE_SLOT = Symbol.for(\"ai-matrx.design-system.escape-stack\");\nconst escapeHost = globalThis as typeof globalThis & { [ESCAPE_SLOT]?: EscapeStack };\nconst escapeStack = (): EscapeStack => (escapeHost[ESCAPE_SLOT] ??= { layers: [], listening: false });\n\nfunction onEscapeKeydown(event: KeyboardEvent): void {\n if (event.key !== \"Escape\" || event.defaultPrevented) return;\n const { layers } = escapeStack();\n layers[layers.length - 1]?.handle(event);\n}\n\nexport interface EscapeLayerHandle {\n /** Move this layer to the top (it came to the front). */\n raise(): void;\n /** Leave the stack (closed). */\n release(): void;\n}\n\n/** Join the Escape stack at the top. The handler runs only while this layer is topmost. */\nexport function pushEscapeLayer(handle: (event: KeyboardEvent) => void): EscapeLayerHandle {\n const stack = escapeStack();\n if (!stack.listening && typeof window !== \"undefined\") {\n window.addEventListener(\"keydown\", onEscapeKeydown);\n stack.listening = true;\n }\n const entry: EscapeLayerEntry = { key: Symbol(\"escape-layer\"), handle };\n stack.layers.push(entry);\n const drop = () => {\n const at = stack.layers.indexOf(entry);\n if (at !== -1) stack.layers.splice(at, 1);\n };\n return {\n raise() {\n drop();\n stack.layers.push(entry);\n },\n release: drop,\n };\n}\n\n/** How many layers hold the Escape stack (tests and diagnostics). */\nexport function escapeLayerDepth(): number {\n return escapeStack().layers.length;\n}\n\n/**\n * Hold a place in the Escape stack while `active`. The latest `onEscape` runs\n * (never a stale closure). `raiseKey`: when it changes the layer moves to the\n * top (pass a window manager's z-index). Returns a stable `raise()` for a\n * layer that tracks \"front\" itself (a pointerdown on the window).\n */\nexport function useEscapeLayer(active: boolean, onEscape: (event: KeyboardEvent) => void, raiseKey?: unknown): () => void {\n const latest = React.useRef(onEscape);\n latest.current = onEscape;\n const handleRef = React.useRef<EscapeLayerHandle | null>(null);\n React.useEffect(() => {\n if (!active) return undefined;\n const handle = pushEscapeLayer((event) => latest.current(event));\n handleRef.current = handle;\n return () => {\n handle.release();\n handleRef.current = null;\n };\n }, [active]);\n const first = React.useRef(true);\n React.useEffect(() => {\n if (first.current) {\n first.current = false;\n return;\n }\n handleRef.current?.raise();\n }, [raiseKey]);\n return React.useCallback(() => handleRef.current?.raise(), []);\n}\n","/**\n * THE TITLE TAKEOVER — every native `title` attribute in the document shows\n * as THE fleet tooltip instead of the browser's.\n *\n * Why this exists. A `title=` is the one tooltip nobody has to import, so it\n * is what every hand-written control reaches for: ~50 of them on an ordinary\n * matrx-frontend page (2026-09-28), next to the Radix tooltips on the tap\n * buttons. The browser draws those as a slow, unstyled system box, and a page\n * that mixes the two reads as having \"lost all of its tooltips\" (Arman,\n * 2026-09-28). Asking every author — human or agent — to wrap every control in\n * `<Tooltip>` is a rule that is broken the day it is written. So the\n * `TooltipProvider` every host already mounts at its root installs this layer,\n * and a `title` is simply a tooltip from then on. Nothing to remember.\n *\n * How it works. On hover (mouse or pen) or keyboard focus (`:focus-visible`)\n * of an element that carries a `title`, the attribute is lifted onto\n * `data-matrx-title` for exactly as long as the pointer or focus stays — so\n * the browser has nothing to show — and one shared, script-placed element\n * wearing `.matrx-tooltip` shows the text instead. When the pointer or focus\n * leaves, the `title` is put back, so assistive technology and every\n * `[title]` selector read the element exactly as authored the rest of the\n * time. Touch never shows it (a `title` has no touch affordance either).\n *\n * What it does not draw: a tooltip that only repeats text already readable in\n * full inside the element (it still draws when that text is hidden or\n * truncated).\n *\n * What it leaves alone:\n * - an element that is already a Radix tooltip trigger\n * (`[data-matrx-tooltip-trigger]`, stamped by `TooltipTrigger`): its\n * `title` is still lifted — two tooltips on one control was the other\n * half of the mess — but only the Radix one shows;\n * - anything inside `[data-native-title]` (the explicit opt-out);\n * - SVG `<title>` children, which are elements, not attributes.\n *\n * Placement. `tooltipSide` (THE SMART SIDE, below): beside a control in a\n * vertical stack, else the host's side; flipped when there is no room,\n * clamped into the viewport. `data-title-side=\"right\" | \"left\" | \"bottom\" |\n * \"top\"` on the element or any ancestor states a preferred side — a vertical\n * rail sets `right` once on its container.\n *\n * Installed at most once per document, reference-counted across every\n * mounted provider, and removed when the last one unmounts.\n */\n\n/**\n * THE SMART SIDE (Arman, 2026-10-15: tooltips \"don't show up intelligently\"). A tooltip never\n * covers the control next to its own. Where the control's neighbours stand decides the side:\n * - an explicit side (a prop, or `data-title-side` on the control or an ancestor below <html>) wins;\n * - an icon-sized control in a vertical stack (an icon column, a tool palette) has its neighbours\n * above and below, so it opens beside the control: right, or left when the control is in the\n * window's right half (an inspector column). A wide row in a list keeps the host's side: its\n * tooltip is the row's own text in full, and beside it would sit over the page next to the list;\n * - anywhere else (a toolbar, a row of buttons, a lone control) it opens on the host's default\n * side (`data-title-side` on <html>: macOS desktop hosts say \"bottom\"; the web's is \"top\").\n * Either way it flips to the other side when there is no room, and stays inside the window.\n */\nexport function tooltipSide(el: Element | null, fallback?: Side): Side {\n if (!el) return fallback ?? \"top\";\n const doc = el.ownerDocument;\n const hinted = el.closest(\"[data-title-side]\");\n const hint = hinted?.getAttribute(\"data-title-side\");\n const isSide = (v: string | null | undefined): v is Side => v === \"top\" || v === \"bottom\" || v === \"left\" || v === \"right\";\n if (hinted && hinted !== doc.documentElement && isSide(hint)) return hint;\n const base: Side = fallback ?? (isSide(hint) ? hint : \"top\");\n const box = el.getBoundingClientRect();\n if (box.width <= ICON_CONTROL_MAX_PX && stackDirection(el) === \"vertical\") {\n const vw = doc.defaultView?.innerWidth ?? 0;\n return vw > 0 && box.left + box.width / 2 > vw / 2 ? \"left\" : \"right\";\n }\n return base;\n}\n\n/** The widest control that counts as an icon (a navigator item, a palette tool). */\nconst ICON_CONTROL_MAX_PX = 64;\n\n/** How the control's nearest group of siblings is laid out, from where they actually are on screen. */\nfunction stackDirection(el: Element): \"vertical\" | \"horizontal\" | null {\n let node: Element | null = el;\n for (let depth = 0; node && depth < 4; depth++, node = node.parentElement) {\n const parent: Element | null = node.parentElement;\n if (!parent) return null;\n const me = node.getBoundingClientRect();\n if (me.width === 0 && me.height === 0) return null;\n let vertical = 0;\n let horizontal = 0;\n for (const sib of Array.from(parent.children)) {\n if (sib === node) continue;\n const r = sib.getBoundingClientRect();\n if (r.width === 0 || r.height === 0) continue;\n const overlapX = Math.min(me.right, r.right) - Math.max(me.left, r.left);\n const overlapY = Math.min(me.bottom, r.bottom) - Math.max(me.top, r.top);\n if (overlapX > 0.5 * Math.min(me.width, r.width) && overlapY <= 0) vertical++;\n else if (overlapY > 0.5 * Math.min(me.height, r.height) && overlapX <= 0) horizontal++;\n }\n if (vertical > 0 && horizontal === 0) return \"vertical\";\n if (horizontal > 0) return \"horizontal\";\n }\n return null;\n}\n\nexport const TITLE_TOOLTIP_ATTR = \"data-matrx-title\";\nexport const TOOLTIP_TRIGGER_ATTR = \"data-matrx-tooltip-trigger\";\nexport const NATIVE_TITLE_OPT_OUT_ATTR = \"data-native-title\";\n\nexport type Side = \"top\" | \"bottom\" | \"left\" | \"right\";\n\nconst OPEN_DELAY_MS = 350;\n/** Moving from one titled control to the next inside this window is instant. */\nconst SKIP_DELAY_MS = 500;\n/**\n * THE HOVER BRIDGE. Leaving the control does not close the tooltip at once: the pointer has this\n * long to reach the tooltip itself (Arman, 2026-10-14: a tooltip must stay long enough to put the\n * mouse on it and copy its text). Entering the tooltip holds it open.\n */\n/**\n * THE TOOLTIP LAYER — above every other layer, always (Arman, 2026-10-14: a tooltip \"coming up\n * behind the content\"). Menus and popovers share the modal tier (equal z, DOM order decides), so a\n * tooltip on that tier lost to any menu opened after it. A tooltip is transient and never takes a\n * press, so nothing ever needs to sit above it.\n */\nexport const TOOLTIP_LAYER_Z = 2_147_483_000;\n\nexport const TOOLTIP_CLOSE_DELAY_MS = 300;\nconst GAP_PX = 6;\nconst EDGE_PX = 8;\n/** How far every tooltip stays from the window's edge (both implementations). */\nexport const TOOLTIP_EDGE_PX = EDGE_PX;\n/**\n * A tooltip is a short hint, never a paragraph (Apple HIG: a tooltip is a few words): text past\n * this budget is cut at a word boundary with an ellipsis. Long detail belongs in a sheet or a\n * Copy details action, not on hover.\n */\nexport const TOOLTIP_TEXT_BUDGET = 140;\n\nexport function clipTooltipText(text: string, budget: number = TOOLTIP_TEXT_BUDGET): string {\n const flat = text.replace(/\\s+/g, \" \").trim();\n if (flat.length <= budget) return flat;\n const cut = flat.slice(0, budget - 1);\n const space = cut.lastIndexOf(\" \");\n return `${(space > budget * 0.6 ? cut.slice(0, space) : cut).replace(/[\\s,.;:–—-]+$/, \"\")}…`;\n}\n\nconst SURFACE_CLASS =\n \"matrx-tooltip matrx-title-tooltip matrx-motion-popper max-w-xs select-text rounded-md border border-border bg-popover px-2.5 py-1 text-xs font-medium text-popover-foreground\";\n\ninterface Installation {\n count: number;\n uninstall: () => void;\n}\n\n/**\n * Keyed on the document itself through a registered symbol, never a module\n * WeakMap: tsup bundles this module into more than one entry (`index`,\n * `tap-target`), and two module copies each holding their own map would\n * install twice — two listeners, two surfaces.\n */\nconst INSTALLATION_KEY = Symbol.for(\"@ai-matrx/design-system/title-tooltips\");\ntype DocumentWithInstallation = Document & { [INSTALLATION_KEY]?: Installation };\nconst installations = {\n get: (doc: Document) => (doc as DocumentWithInstallation)[INSTALLATION_KEY],\n set: (doc: Document, value: Installation) => {\n (doc as DocumentWithInstallation)[INSTALLATION_KEY] = value;\n },\n delete: (doc: Document) => {\n delete (doc as DocumentWithInstallation)[INSTALLATION_KEY];\n },\n};\n\n/** Install the takeover on `doc`. Returns the release function. */\nexport function acquireTitleTooltips(doc: Document | undefined = typeof document === \"undefined\" ? undefined : document): () => void {\n if (!doc) return () => {};\n const existing = installations.get(doc);\n if (existing) {\n existing.count += 1;\n } else {\n installations.set(doc, { count: 1, uninstall: install(doc) });\n }\n let released = false;\n return () => {\n if (released) return;\n released = true;\n const current = installations.get(doc);\n if (!current) return;\n current.count -= 1;\n if (current.count <= 0) {\n current.uninstall();\n installations.delete(doc);\n }\n };\n}\n\nfunction install(doc: Document): () => void {\n const win = doc.defaultView;\n let active: HTMLElement | null = null;\n let surface: HTMLDivElement | null = null;\n let openTimer: ReturnType<typeof setTimeout> | undefined;\n let closeTimer: ReturnType<typeof setTimeout> | undefined;\n let lastClosedAt = 0;\n /** A press began on the tooltip (selecting its text): it must not close until release. */\n let holding = false;\n\n const HTMLElementCtor = win?.HTMLElement;\n\n const titledAncestor = (node: EventTarget | null): HTMLElement | null => {\n if (!HTMLElementCtor || !(node instanceof win!.Node)) return null;\n const start = node instanceof HTMLElementCtor ? node : (node as Node).parentElement;\n if (!start) return null;\n const el = start.closest<HTMLElement>(`[title], [${TITLE_TOOLTIP_ATTR}]`);\n if (!el || !(el instanceof HTMLElementCtor)) return null;\n if (el.closest(`[${NATIVE_TITLE_OPT_OUT_ATTR}]`)) return null;\n return el;\n };\n\n const textOf = (el: HTMLElement) => clipTooltipText(el.getAttribute(TITLE_TOOLTIP_ATTR) ?? el.getAttribute(\"title\") ?? \"\");\n\n const lift = (el: HTMLElement) => {\n const title = el.getAttribute(\"title\");\n if (title === null) return;\n el.setAttribute(TITLE_TOOLTIP_ATTR, title);\n el.removeAttribute(\"title\");\n };\n\n const restore = (el: HTMLElement) => {\n const held = el.getAttribute(TITLE_TOOLTIP_ATTR);\n if (held === null) return;\n // An author who changed or removed the title while it was lifted wins:\n // only put ours back when nothing re-set it in the meantime.\n if (!el.hasAttribute(\"title\")) el.setAttribute(\"title\", held);\n el.removeAttribute(TITLE_TOOLTIP_ATTR);\n };\n\n const ensureSurface = () => {\n if (surface && surface.isConnected) return surface;\n surface = doc.createElement(\"div\");\n surface.setAttribute(\"role\", \"tooltip\");\n surface.setAttribute(\"data-slot\", \"title-tooltip\");\n surface.className = SURFACE_CLASS;\n surface.style.position = \"fixed\";\n surface.style.zIndex = String(TOOLTIP_LAYER_Z);\n surface.style.visibility = \"hidden\";\n doc.body.appendChild(surface);\n return surface;\n };\n\n /**\n * THE PART OF `el` A PERSON CAN SEE: its box clipped by every ancestor that clips (scrolls or hides\n * overflow) and by the window. A truncated cell in a sideways-scrolling table is far wider than its\n * visible part; anchored to the whole box the tooltip landed at the window's edge (2026-10-14).\n */\n const visibleRect = (el: HTMLElement, vw: number, vh: number) => {\n const box = el.getBoundingClientRect();\n let left = box.left;\n let top = box.top;\n let right = box.right;\n let bottom = box.bottom;\n for (let node = el.parentElement; node && node !== doc.body && node !== doc.documentElement; node = node.parentElement) {\n const cs = win?.getComputedStyle(node);\n if (!cs) break;\n const clipsX = cs.overflowX !== \"visible\" || cs.overflow === \"hidden\";\n const clipsY = cs.overflowY !== \"visible\" || cs.overflow === \"hidden\";\n if (!clipsX && !clipsY) continue;\n const clip = node.getBoundingClientRect();\n if (clipsX) { left = Math.max(left, clip.left); right = Math.min(right, clip.right); }\n if (clipsY) { top = Math.max(top, clip.top); bottom = Math.min(bottom, clip.bottom); }\n }\n left = Math.max(left, 0);\n top = Math.max(top, 0);\n right = Math.min(right, vw || right);\n bottom = Math.min(bottom, vh || bottom);\n // Nothing of it is visible (scrolled away under the pointer is impossible, but a test DOM can say so): the box itself.\n if (right <= left || bottom <= top) return box;\n return { left, top, right, bottom, width: right - left, height: bottom - top };\n };\n\n const preferredSide = (el: HTMLElement): Side => tooltipSide(el);\n\n const place = (el: HTMLElement, node: HTMLDivElement) => {\n // The VISIBLE viewport, not the window: inside a clipped host (the kind\n // sandbox frame is window-wide but shown only at its column) the visual\n // viewport is what the reader sees, so a tooltip never lands past it.\n const vw = win?.visualViewport?.width ?? win?.innerWidth ?? 0;\n const vh = win?.visualViewport?.height ?? win?.innerHeight ?? 0;\n const anchor = visibleRect(el, vw, vh);\n const box = node.getBoundingClientRect();\n const fits: Record<Side, boolean> = {\n top: anchor.top - GAP_PX - box.height >= EDGE_PX,\n bottom: anchor.bottom + GAP_PX + box.height <= vh - EDGE_PX,\n left: anchor.left - GAP_PX - box.width >= EDGE_PX,\n right: anchor.right + GAP_PX + box.width <= vw - EDGE_PX,\n };\n const opposite: Record<Side, Side> = { top: \"bottom\", bottom: \"top\", left: \"right\", right: \"left\" };\n const wanted = preferredSide(el);\n const side: Side = fits[wanted] ? wanted : fits[opposite[wanted]] ? opposite[wanted] : wanted;\n\n let x: number;\n let y: number;\n if (side === \"top\" || side === \"bottom\") {\n x = anchor.left + anchor.width / 2 - box.width / 2;\n y = side === \"top\" ? anchor.top - GAP_PX - box.height : anchor.bottom + GAP_PX;\n } else {\n y = anchor.top + anchor.height / 2 - box.height / 2;\n x = side === \"left\" ? anchor.left - GAP_PX - box.width : anchor.right + GAP_PX;\n }\n x = Math.min(Math.max(x, EDGE_PX), Math.max(EDGE_PX, vw - EDGE_PX - box.width));\n y = Math.min(Math.max(y, EDGE_PX), Math.max(EDGE_PX, vh - EDGE_PX - box.height));\n // Placed with `left`/`top`, NEVER `transform`: the open animation\n // (`.matrx-motion-popper`) animates `transform`, and a running animation\n // overrides an inline transform — the chip sat at the page's top-left\n // corner for the whole animation, then jumped to its control (2026-10-08).\n node.style.left = `${Math.round(x)}px`;\n node.style.top = `${Math.round(y)}px`;\n node.setAttribute(\"data-side\", side);\n };\n\n const isShown = (node: HTMLElement, root: HTMLElement) => {\n const rect = node.getBoundingClientRect();\n if (rect.width <= 0 || rect.height <= 0) return false;\n for (let cur: HTMLElement | null = node; cur; cur = cur === root ? null : cur.parentElement) {\n const cs = win?.getComputedStyle(cur);\n if (!cs) return false;\n if (cs.display === \"none\" || cs.visibility === \"hidden\" || Number(cs.opacity) === 0) return false;\n }\n return true;\n };\n\n /**\n * A tooltip that repeats text the person can already read in full is noise\n * (an expanded sidebar row, a \"Save\" button titled \"Save\"). It still shows\n * when that text is hidden (a collapsed rail's label) or cut off\n * (truncated) — the two cases a title exists for.\n */\n const isClipped = (host: HTMLElement, root: HTMLElement) => {\n for (let node: HTMLElement | null = host; node; node = node.parentElement) {\n if (node.scrollWidth > node.clientWidth + 1 && node.clientWidth > 0) return true;\n if (node.scrollHeight > node.clientHeight + 1 && node.clientHeight > 0) return true;\n if (node === root) break;\n }\n return false;\n };\n\n const repeatsVisibleText = (el: HTMLElement, text: string) => {\n const norm = (t: string) => t.replace(/\\s+/g, \" \").trim().toLowerCase();\n const want = norm(text);\n if (!want || !win) return false;\n const walker = doc.createTreeWalker(el, win.NodeFilter.SHOW_TEXT);\n for (let node = walker.nextNode(); node; node = walker.nextNode()) {\n if (norm(node.textContent ?? \"\") !== want) continue;\n const host = node.parentElement;\n if (!host || !isShown(host, el)) continue;\n // Cut off is measured on the BOX that clips: an inline host (a span inside a truncating\n // cell) has no box width of its own, so every ancestor up to the titled element is asked.\n if (isClipped(host, el)) continue;\n return true;\n }\n return false;\n };\n\n const show = (el: HTMLElement, instant: boolean) => {\n if (active !== el) return;\n // A Radix tooltip trigger shows its own tooltip — never a second one.\n if (el.closest(`[${TOOLTIP_TRIGGER_ATTR}]`)) return;\n const text = textOf(el);\n if (!text || !el.isConnected) return;\n if (repeatsVisibleText(el, text)) return;\n const node = ensureSurface();\n node.textContent = text;\n node.style.visibility = \"hidden\";\n // Measure and place BEFORE the open state starts the animation: measured\n // mid-animation the box reads at its 0.95 entry scale and lands off-centre.\n node.removeAttribute(\"data-state\");\n // The surface is ONE shared fixed element that keeps the `left` of its last\n // placement. Measured there, a longer text wraps against the room that is\n // left of the OLD spot, reads one line too tall, and lands a line too high\n // once it moves (the sandbox tooltip spec caught a 16px extra gap). Rewind\n // to the origin so the box is measured at its natural, unwrapped size.\n node.style.left = \"0px\";\n node.style.top = \"0px\";\n place(el, node);\n node.setAttribute(\"data-state\", instant ? \"instant-open\" : \"delayed-open\");\n node.style.visibility = \"visible\";\n if (el.id) node.id = `${el.id}-title-tooltip`;\n };\n\n const hide = () => {\n if (openTimer !== undefined) clearTimeout(openTimer);\n openTimer = undefined;\n cancelClose();\n holding = false;\n if (surface && surface.style.visibility === \"visible\") lastClosedAt = Date.now();\n if (surface) {\n surface.style.visibility = \"hidden\";\n surface.removeAttribute(\"data-state\");\n }\n };\n\n const cancelClose = () => {\n if (closeTimer !== undefined) clearTimeout(closeTimer);\n closeTimer = undefined;\n };\n\n const inSurface = (node: EventTarget | null) =>\n !!surface && !!win && node instanceof win.Node && surface.contains(node);\n\n const hasSelectionInSurface = () => {\n const sel = win?.getSelection();\n return !!sel && !sel.isCollapsed && !!surface && !!sel.anchorNode && surface.contains(sel.anchorNode);\n };\n\n /** Close after the bridge delay unless the pointer reached the tooltip or text in it is selected. */\n const scheduleClose = () => {\n cancelClose();\n // Nothing is showing yet (the open delay has not run, or the text was not worth drawing): there is\n // nothing to bridge to, so leaving simply cancels.\n if (!surface || surface.style.visibility !== \"visible\") {\n deactivate();\n return;\n }\n closeTimer = setTimeout(() => {\n closeTimer = undefined;\n if (holding || hasSelectionInSurface()) return;\n deactivate();\n }, TOOLTIP_CLOSE_DELAY_MS);\n };\n\n const activate = (el: HTMLElement) => {\n cancelClose();\n if (active === el) return;\n deactivate();\n active = el;\n lift(el);\n const instant = Date.now() - lastClosedAt < SKIP_DELAY_MS;\n if (instant) show(el, true);\n else openTimer = setTimeout(() => show(el, false), OPEN_DELAY_MS);\n };\n\n const deactivate = () => {\n hide();\n if (active) restore(active);\n active = null;\n };\n\n // A touch has no hover: the tap that focuses a button must not open its tooltip, and a tooltip\n // that is open when a finger lands closes. The compat mouse events and the focus a tap leaves\n // behind used to pin \"Copy chart source\" over the chart title on a phone (review 5, G13).\n let lastTouchAt = Number.NEGATIVE_INFINITY;\n const TOUCH_FOCUS_WINDOW_MS = 1000;\n const onPointerOver = (e: PointerEvent) => {\n if (e.pointerType === \"touch\") {\n lastTouchAt = Date.now();\n if (active) deactivate();\n return;\n }\n if (inSurface(e.target)) {\n cancelClose();\n return;\n }\n if (holding || hasSelectionInSurface()) {\n // Text is being selected in the tooltip: another control passing under the pointer must not replace it.\n return;\n }\n const el = titledAncestor(e.target);\n if (el) activate(el);\n else if (active && closeTimer === undefined) scheduleClose();\n };\n\n const onPointerOut = (e: PointerEvent) => {\n if (!active) return;\n const next = e.relatedTarget;\n if (next instanceof win!.Node && (active.contains(next) || inSurface(next))) return;\n if (inSurface(e.target)) {\n if (holding) return;\n scheduleClose();\n return;\n }\n scheduleClose();\n };\n\n const onPointerDown = (e: PointerEvent) => {\n if (e.pointerType === \"touch\") lastTouchAt = Date.now();\n if (inSurface(e.target)) {\n // Selecting the tooltip's text: keep it open until the press ends.\n holding = true;\n cancelClose();\n return;\n }\n deactivate();\n };\n\n const onPointerUp = () => {\n if (!holding) return;\n holding = false;\n if (!hasSelectionInSurface()) scheduleClose();\n };\n\n const onFocusIn = (e: FocusEvent) => {\n if (Date.now() - lastTouchAt < TOUCH_FOCUS_WINDOW_MS) return;\n const el = titledAncestor(e.target);\n if (!el) return;\n let visible = true;\n try {\n visible = (e.target as Element).matches(\":focus-visible\");\n } catch {\n visible = true;\n }\n if (visible) activate(el);\n };\n\n const onFocusOut = (e: FocusEvent) => {\n if (!active) return;\n const next = e.relatedTarget;\n if (next instanceof win!.Node && active.contains(next)) return;\n deactivate();\n };\n\n const onDismiss = (e?: Event) => {\n if (e && inSurface(e.target)) return;\n deactivate();\n };\n const onKeyDown = (e: KeyboardEvent) => {\n if (e.key === \"Escape\") deactivate();\n };\n\n doc.addEventListener(\"pointerover\", onPointerOver, true);\n doc.addEventListener(\"pointerout\", onPointerOut, true);\n doc.addEventListener(\"focusin\", onFocusIn, true);\n doc.addEventListener(\"focusout\", onFocusOut, true);\n doc.addEventListener(\"pointerdown\", onPointerDown, true);\n doc.addEventListener(\"pointerup\", onPointerUp, true);\n doc.addEventListener(\"keydown\", onKeyDown, true);\n doc.addEventListener(\"scroll\", onDismiss, true);\n win?.addEventListener(\"blur\", onDismiss);\n\n return () => {\n deactivate();\n doc.removeEventListener(\"pointerover\", onPointerOver, true);\n doc.removeEventListener(\"pointerout\", onPointerOut, true);\n doc.removeEventListener(\"focusin\", onFocusIn, true);\n doc.removeEventListener(\"focusout\", onFocusOut, true);\n doc.removeEventListener(\"pointerdown\", onPointerDown, true);\n doc.removeEventListener(\"pointerup\", onPointerUp, true);\n doc.removeEventListener(\"keydown\", onKeyDown, true);\n doc.removeEventListener(\"scroll\", onDismiss, true);\n win?.removeEventListener(\"blur\", onDismiss);\n surface?.remove();\n surface = null;\n };\n}\n","/**\n * THE FOCUS-RETURN GUARD — a closing menu, popover, select or dialog never takes focus back from a\n * field the person has already moved into.\n *\n * Radix returns focus to the trigger when its content UNMOUNTS (FocusScope: a `setTimeout(0)` after the\n * exit animation, unconditionally). On a busy page that is hundreds of milliseconds after the person\n * picked an option — long enough for them to click the next field and start typing. The return then\n * lands mid-word: focus jumps to the trigger and every key after it is lost (\"https://drive…\" saved as\n * \"https:\", Applet social planner, 2026-10-08).\n *\n * `keepMovedFocus(handler)` composes a content's `onCloseAutoFocus`: when focus already sits on a live\n * element outside the closing content (not the page body), the return is canceled; otherwise Radix\n * returns focus to the trigger exactly as before (keyboard users closing with Escape keep their place).\n */\n/** True when focus has already moved to something the person chose, outside `container`. */\nexport function focusMovedElsewhere(container: EventTarget | null, doc: Document | undefined = typeof document === \"undefined\" ? undefined : document): boolean {\n if (!doc) return false;\n const active = doc.activeElement;\n if (!active || active === doc.body || active === doc.documentElement) return false;\n if (!active.isConnected) return false;\n if (container && typeof (container as Node).contains === \"function\" && (container as Node).contains(active)) return false;\n return true;\n}\n\n/** Compose a content's `onCloseAutoFocus` with THE FOCUS-RETURN GUARD (the caller's handler runs first). */\nexport function keepMovedFocus(handler?: (event: Event) => void): (event: Event) => void {\n return (event: Event) => {\n handler?.(event);\n if (event.defaultPrevented) return;\n const container = (event.currentTarget ?? event.target) as EventTarget | null;\n if (focusMovedElsewhere(container, (container as Node | null)?.ownerDocument ?? undefined)) event.preventDefault();\n };\n}\n","\"use client\";\n\n/**\n * Popover — ported verbatim from matrx-frontend `components/ui/popover.tsx`.\n *\n * Seam inversion: the host's `useNestedPortalContainer` (dialog/popout aware)\n * becomes the injected `PortalContainerProvider` seam (`portal-container.tsx`);\n * the explicit `container` prop keeps top priority, exactly as before.\n *\n * THE ROOT RENDERS UNCONDITIONALLY — no mount gate. This wrapper used to defer\n * rendering until after hydration (\"Radix generates dynamic aria-controls ids\n * that differ between SSR and client\"), and that justification was false:\n * Radix ids come from React's SSR-stable `useId` (verified against\n * @radix-ui/react-popover 1.1.17 / react-id 1.1.2). The gate was actively\n * harmful — the Trigger wraps ALWAYS-VISIBLE content, so `return null`\n * deleted it from SSR and the first client paint.\n */\n\nimport * as PopoverPrimitive from \"@radix-ui/react-popover\";\nimport * as React from \"react\";\n\nimport { cn } from \"./cn\";\nimport { MOTION_POPPER } from \"./motion\";\nimport { SOLID_SURFACE_CLASS, type PopoverSurface } from \"./solid-surface\";\nimport { usePortalContainer } from \"./portal-container\";\nimport { keepMovedFocus } from \"./focus-return\";\n\nexport const Popover = PopoverPrimitive.Root;\n\nexport const PopoverTrigger = PopoverPrimitive.Trigger;\n\nexport const PopoverAnchor = PopoverPrimitive.Anchor;\n\nexport interface PopoverContentProps\n extends React.ComponentPropsWithoutRef<typeof PopoverPrimitive.Content> {\n /** Explicit portal target; wins over the injected container. */\n container?: HTMLElement | null;\n /**\n * Package-owned open/close motion. Default `true`. Pass `false` for a\n * surface that must appear instantly — a picker re-anchoring while the user\n * types, a measurement pass. It is NOT the reduced-motion switch;\n * `styles.css` already honors `prefers-reduced-motion`.\n */\n animated?: boolean;\n /**\n * HOW WIDE THE POPOVER IS ALLOWED TO BE, and it is the SYSTEM that decides — never a\n * surface pasting its own `w-64` over the default (lane FIX-14, 2026-09-22).\n *\n * `\"fixed\"` (default) is the historical `w-72`: right for a menu of short, known\n * labels, where a ragged edge would look broken.\n *\n * `\"content\"` is for a popover whose whole job is to SHOW SOMETHING THE SYSTEM DID\n * NOT CHOOSE — a person's name, a record's title, a row the user is about to\n * create. The relation picker offered\n *\n * Create “Marisol Okonkwo — 418 Calle Pu\n *\n * inside a 16rem box, cut mid-word, on the one control that exists to show the name\n * being created. A fixed width cannot be right for content of unknown length, so\n * this one grows to its content between an honest floor and an honest ceiling:\n *\n * · at least the trigger's own width, and at least 20rem — the width Airtable's and\n * Notion's link-record pickers settle on, and wide enough that an ordinary\n * \"name — street, town\" fits on one line;\n * · at most 28rem, and never wider than the viewport less a 1rem gutter each side,\n * so it still fits a 375px phone with nothing running off the screen. The floor is\n * clamped by the same gutter, so on a very narrow screen the ceiling still wins.\n *\n * Beyond that ceiling the CONTENT truncates with an ellipsis and carries a `title`.\n * Growing, then ellipsis — never a mid-word cut.\n *\n * BOTH modes keep the phone gutter (2026-09-26): the box is never wider than the\n * viewport less 1rem each side, and Radix keeps it `collisionPadding` (16px) off every\n * screen edge. Measured at 375px before this: `w-72`/`w-80` callers landed flush on\n * the right edge (55→375) because collision padding was 0.\n */\n sizing?: \"fixed\" | \"content\";\n /**\n * The surface fill. `\"default\"` is the theme's popover surface (a host may render it\n * translucent / glass). `\"solid\"` is the OPAQUE surface — the popover token at full\n * alpha, no backdrop blur — for a menu that must read as paper over a cover image or a\n * busy page (a Notion-style ••• menu). Same option on `DropdownMenuContent`.\n */\n surface?: PopoverSurface;\n /**\n * A NAMED fixed width (0.68.22), for a `sizing=\"fixed\"` popover whose content needs more or\n * less room than the default `md` (18rem) — never a pasted `w-[260px]`. Every width keeps the\n * phone gutter (never wider than the viewport less 1rem each side). Derived from the call\n * sites: `xs` 12rem (a short menu), `sm` 15rem (a ••• menu), `md` 18rem (default),\n * `lg` 20rem (a small form), `xl` 26rem (a picker grid), `2xl` 34rem (a gallery).\n * Ignored when `sizing=\"content\"`.\n */\n width?: PopoverWidth;\n /**\n * The inner padding, named (0.68.22): `none` (the content draws its own — a command list, a\n * picker), `xs` 4px (a menu of rows), `sm` 8px, `md` 12px, `default` 16px.\n */\n padding?: PopoverPadding;\n}\n\nexport type PopoverWidth = \"xs\" | \"sm\" | \"md\" | \"lg\" | \"xl\" | \"2xl\";\nexport type PopoverPadding = \"none\" | \"xs\" | \"sm\" | \"md\" | \"default\";\n\n/** Literal class per width so a host's Tailwind scan of the package finds every one. */\nexport const POPOVER_WIDTH_CLASS: Record<PopoverWidth, string> = {\n xs: \"w-48\",\n sm: \"w-60\",\n md: \"w-72\",\n lg: \"w-80\",\n xl: \"w-[26rem]\",\n \"2xl\": \"w-[34rem]\",\n};\nexport const POPOVER_PADDING_CLASS: Record<PopoverPadding, string> = {\n none: \"p-0\",\n xs: \"p-1\",\n sm: \"p-2\",\n md: \"p-3\",\n default: \"p-4\",\n};\n\nexport const PopoverContent = React.forwardRef<\n React.ComponentRef<typeof PopoverPrimitive.Content>,\n PopoverContentProps\n>(\n (\n {\n className,\n align = \"center\",\n sideOffset = 4,\n container,\n animated = true,\n sizing = \"fixed\",\n surface = \"default\",\n width = \"md\",\n padding = \"default\",\n collisionPadding = 16,\n onCloseAutoFocus,\n ...props\n },\n ref,\n ) => {\n const portalContainer = usePortalContainer(container);\n return (\n <PopoverPrimitive.Portal container={portalContainer}>\n <PopoverPrimitive.Content\n ref={ref}\n align={align}\n sideOffset={sideOffset}\n collisionPadding={collisionPadding}\n data-surface={surface === \"solid\" ? \"solid\" : undefined}\n data-width={sizing === \"content\" ? undefined : width}\n data-padding={padding}\n className={cn(\n // Cap to the viewport space Radix measured and scroll — a popover taller\n // than the screen must never trap the user with unreachable content.\n // z must EQUAL the dialog layer (z-[10000]), never exceed it: with equal\n // z, DOM portal order decides, so a dialog opened FROM a popover stacks\n // above it, and a popover opened from a dialog still stacks above the\n // dialog. z-[10001] buried dialogs behind fullscreen popovers.\n \"z-[10000] max-h-[var(--radix-popover-content-available-height)] overflow-y-auto overscroll-contain rounded-md border bg-popover text-popover-foreground shadow-md outline-none\",\n POPOVER_PADDING_CLASS[padding],\n sizing === \"content\"\n ? \"w-auto min-w-[min(max(var(--radix-popover-trigger-width),20rem),calc(100vw-2rem))] max-w-[min(28rem,calc(100vw-2rem))]\"\n : cn(POPOVER_WIDTH_CLASS[width], \"max-w-[calc(100vw-2rem)]\"),\n surface === \"solid\" && SOLID_SURFACE_CLASS,\n animated && MOTION_POPPER,\n className,\n )}\n {...props}\n onCloseAutoFocus={keepMovedFocus(onCloseAutoFocus)}\n />\n </PopoverPrimitive.Portal>\n );\n },\n);\nPopoverContent.displayName = PopoverPrimitive.Content.displayName;\n","/**\n * The opaque surface option shared by every floating menu surface\n * (`PopoverContent`, `DropdownMenuContent`, `DropdownMenuSubContent`).\n * `data-surface=\"solid\"` is also styled in `styles.css`, so the fill holds even\n * where a host utility layer tints the default surface.\n */\nexport type PopoverSurface = \"default\" | \"solid\";\n\nexport const SOLID_SURFACE_CLASS =\n \"bg-[hsl(var(--popover)/1)] [backdrop-filter:none] [-webkit-backdrop-filter:none]\";\n","\"use client\";\n\nimport {\n cloneElement,\n forwardRef,\n isValidElement,\n useCallback,\n useRef,\n type ButtonHTMLAttributes,\n type ReactElement,\n type ReactNode,\n type Ref,\n} from \"react\";\n\nimport { Tooltip, TooltipContent, TooltipTrigger } from \"../tooltip\";\nimport { joinClassNames } from \"@ai-matrx/kit/dom\";\nimport { classNameMisuse, useTapGuardRef } from \"./tap-target-guard\";\nimport { useTapSurface } from \"./tap-surface\";\nimport {\n TAP_SOLID_TONE,\n TAP_TONE_CLASS,\n TapBadge,\n TapChevron,\n TapSpinner,\n formatTapShortcut,\n tooltipBody,\n useTapShortcut,\n type TapFeatureProps,\n type TapShortcut,\n type TapSolidTone,\n} from \"./tap-features\";\nimport {\n getTapTargetLinkComponent,\n type TapTargetLinkComponent,\n} from \"./link\";\n\nexport interface TapTargetButtonProps extends TapFeatureProps {\n icon?: React.ReactNode;\n children?: React.ReactNode;\n strokeWidth?: number | undefined;\n onClick?: (() => void) | undefined;\n className?: string | undefined;\n as?: \"button\" | \"label\" | undefined;\n htmlFor?: string | undefined;\n ariaLabel?: string | undefined;\n disabled?: boolean | undefined;\n /**\n * When set, the tap button renders as a link instead of a button.\n * - Internal hrefs (e.g. \"/tasks\") render via the injected link component\n * (`setTapTargetLinkComponent` / the `linkComponent` prop), falling back\n * to a plain `<a>` when none is registered.\n * - External hrefs (http://, https://, mailto:, tel:) render as `<a>`\n * with `target=\"_blank\"` and `rel=\"noopener noreferrer\"` by default.\n * - When combined with `disabled`, the trigger renders as a non-navigable\n * `<span aria-disabled=\"true\">` with the same visual styling.\n */\n href?: string | undefined;\n /** Override target. Works on both internal links and external anchors. */\n target?: \"_blank\" | \"_self\" | \"_parent\" | \"_top\" | undefined;\n /** Override rel. Works on both internal links and external anchors. */\n rel?: string | undefined;\n /** Forwarded to the injected link component. Pass `false` to disable prefetching. */\n prefetch?: boolean | null | undefined;\n /**\n * Per-instance link component for internal hrefs — overrides the\n * module-level `setTapTargetLinkComponent` registration.\n */\n linkComponent?: TapTargetLinkComponent | undefined;\n /**\n * Tooltip text. Defaults to `ariaLabel` when omitted.\n * EVERY tap button shows a tooltip (owner ruling 2026-10-01). `false` no\n * longer hides it: it renders the tooltip through `title` (the provider's\n * title takeover draws the same surface) — for a button nested inside\n * another `asChild` trigger, where the Tooltip wrapper cannot sit.\n */\n tooltip?: string | false | undefined;\n /** Tooltip placement. Defaults to \"top\". */\n tooltipSide?: \"top\" | \"right\" | \"bottom\" | \"left\" | undefined;\n /** Tooltip alignment along its side. Defaults to \"center\". */\n tooltipAlign?: \"start\" | \"center\" | \"end\" | undefined;\n /**\n * Visible caption rendered inline after the icon (`[icon Label]`).\n * Widens the pill automatically. Tooltip defaults to off when set — the\n * label is self-describing. Visible text becomes the accessible name.\n */\n label?: string | undefined;\n /**\n * Collapse an icon + caption pill to its icon-only 44px tap target below\n * the `sm` breakpoint. The caption and inline geometry return at `sm+`;\n * `ariaLabel` (falling back to `label`) remains the accessible name.\n */\n mobileIconOnly?: boolean | undefined;\n}\n\nexport interface TapTargetButtonSolidProps extends Omit<TapTargetButtonProps, \"tone\"> {\n /** The fill, from the system's list. Replaces bgColor / iconColor / hover / active. */\n tone?: TapSolidTone | undefined;\n bgColor?: string | undefined;\n iconColor?: string | undefined;\n hoverBgColor?: string | undefined;\n /**\n * Press-state background. Defaults to `group-active/tap:brightness-90` (the\n * BOX is what is pressed — its touch area included), which works on\n * any color. Override when using a custom `bgColor` that should darken to a\n * specific shade on press (e.g. `group-active/tap:bg-primary/60`).\n */\n activeBgColor?: string | undefined;\n}\n\n/** Native button attributes a tap button accepts — everything except `style`:\n * a tap button's geometry is the system's, never the caller's. */\nexport type TapTargetNativeProps = Omit<ButtonHTMLAttributes<HTMLButtonElement>, \"style\">;\n\nconst EXTERNAL_RE = /^(https?:|mailto:|tel:)/i;\n\n// Geometry + press feedback + tap hygiene are the SINGLE SOURCE OF TRUTH in\n// the shipped stylesheet (the `.matrx-tap-*` family in styles.css — import\n// \"@ai-matrx/tap-target/styles.css\" once at app root). This component only\n// picks the right class and layers each variant's decoration on top.\nconst TAP_OUTER_CLASS = \"matrx-tap-target group group/tap\";\nconst TAP_GROUP_OUTER_CLASS = \"matrx-tap-target matrx-tap-target-sm group group/tap\";\n\nfunction IconContent({\n icon,\n children,\n strokeWidth = 2,\n className,\n}: Pick<\n TapTargetButtonProps,\n \"icon\" | \"children\" | \"strokeWidth\" | \"className\"\n>) {\n if (icon) {\n if (isValidElement<{ className?: string }>(icon)) {\n return cloneElement(icon, {\n className: joinClassNames(className, icon.props.className),\n });\n }\n return <span className={className}>{icon}</span>;\n }\n return (\n <svg\n className={className}\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n strokeWidth={strokeWidth}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n {children}\n </svg>\n );\n}\n\ntype TapTargetSize = \"default\" | \"sm\";\n\nfunction resolveTapGeometry(\n label: string | undefined,\n size: TapTargetSize,\n mobileIconOnly: boolean,\n) {\n const inline = Boolean(label);\n if (size === \"sm\") {\n return {\n outerClassName:\n inline && mobileIconOnly\n ? \"matrx-tap-target matrx-tap-target-sm matrx-tap-target-mobile-icon-only-sm group group/tap\"\n : inline\n ? \"matrx-tap-target matrx-tap-target-sm matrx-tap-target-inline-sm group group/tap\"\n : TAP_GROUP_OUTER_CLASS,\n inlineModifier: mobileIconOnly\n ? \"matrx-tap-pill-mobile-icon-only-sm\"\n : \"matrx-tap-pill-inline-sm\",\n };\n }\n return {\n outerClassName:\n inline && mobileIconOnly\n ? `${TAP_OUTER_CLASS} matrx-tap-target-mobile-icon-only`\n : inline\n ? `${TAP_OUTER_CLASS} matrx-tap-target-inline`\n : TAP_OUTER_CLASS,\n inlineModifier: mobileIconOnly\n ? \"matrx-tap-pill-mobile-icon-only\"\n : \"matrx-tap-pill-inline\",\n };\n}\n\nfunction buildTapInner({\n label,\n pillClassName,\n iconClassName,\n labelClassName,\n inlineModifier,\n icon,\n children,\n strokeWidth = 2,\n loading,\n chevron,\n}: {\n label?: string | undefined;\n pillClassName: string;\n iconClassName: string;\n labelClassName?: string | undefined;\n inlineModifier: string;\n icon?: React.ReactNode;\n children?: React.ReactNode;\n strokeWidth?: number | undefined;\n loading?: boolean | undefined;\n chevron?: boolean | undefined;\n}) {\n const iconEl = loading ? (\n <TapSpinner className={iconClassName} />\n ) : (\n <IconContent\n icon={icon}\n strokeWidth={strokeWidth}\n className={iconClassName}\n >\n {children}\n </IconContent>\n );\n const pillClasses = label\n ? `${pillClassName} ${inlineModifier}`.trim()\n : pillClassName;\n\n if (!label) {\n return <div className={pillClasses}>{iconEl}</div>;\n }\n\n return (\n <div className={pillClasses}>\n {iconEl}\n <span className={labelClassName ?? \"matrx-tap-label\"}>{label}</span>\n {chevron ? <TapChevron /> : null}\n </div>\n );\n}\n\ninterface RenderTapTargetArgs extends Pick<\n TapTargetButtonProps,\n | \"icon\"\n | \"children\"\n | \"strokeWidth\"\n | \"label\"\n | \"mobileIconOnly\"\n | \"onClick\"\n | \"as\"\n | \"htmlFor\"\n | \"ariaLabel\"\n | \"disabled\"\n | \"href\"\n | \"target\"\n | \"rel\"\n | \"prefetch\"\n | \"linkComponent\"\n | \"tooltip\"\n | \"tooltipSide\"\n | \"tooltipAlign\"\n> {\n size?: TapTargetSize;\n /** The caller's raw `className` (the glyph color) — checked by the guard. */\n colorClassName?: string | undefined;\n pillClassName: string;\n iconClassName: string;\n labelClassName?: string | undefined;\n rest?: (TapTargetNativeProps & TapFeatureProps) | undefined;\n buttonRef?: Ref<HTMLButtonElement> | undefined;\n}\n\n// A hook (it carries the guard ref); every variant calls it exactly once.\nfunction useTapTarget({\n size = \"default\",\n colorClassName,\n pillClassName,\n iconClassName,\n labelClassName,\n icon,\n children,\n strokeWidth,\n label,\n mobileIconOnly = false,\n onClick,\n as,\n htmlFor,\n ariaLabel,\n disabled,\n href,\n target,\n rel,\n prefetch,\n linkComponent,\n tooltip,\n tooltipSide,\n tooltipAlign,\n rest,\n buttonRef,\n}: RenderTapTargetArgs): ReactElement {\n const {\n tone,\n badge,\n pressed,\n loading,\n disabledReason,\n shortcut,\n chevron,\n ...nativeRest\n } = rest ?? {};\n const isDisabled = Boolean(disabled || disabledReason);\n // FORCED TOOLTIPS: the text is the reason, an explicit tooltip, the\n // accessible name, or the label — and a button with none is a defect.\n const tipText =\n disabledReason || (typeof tooltip === \"string\" && tooltip ? tooltip : undefined) || ariaLabel || label;\n const titleMode = tooltip === false;\n const propViolation =\n (tipText ? null : \"every tap button needs a tooltip — pass ariaLabel\") ??\n classNameMisuse(colorClassName ?? nativeRest.className) ??\n ((nativeRest as { style?: unknown }).style ? \"style is not supported on a tap button\" : null);\n const guardRef = useTapGuardRef<HTMLElement>(\n buttonRef as Ref<HTMLElement> | undefined,\n propViolation,\n );\n const nodeRef = useRef<HTMLElement | null>(null);\n const triggerRef = useCallback(\n (node: HTMLElement | null) => {\n nodeRef.current = node;\n guardRef(node);\n },\n [guardRef],\n );\n const getNode = useCallback(() => nodeRef.current, []);\n useTapShortcut(shortcut, getNode, !isDisabled && !loading);\n\n // Tone (or a pressed toggle) owns the glyph and label color.\n const toneColor = tone ? TAP_TONE_CLASS[tone] : pressed && !colorClassName ? TAP_TONE_CLASS.primary : null;\n if (toneColor) {\n iconClassName = `matrx-tap-icon ${toneColor}`;\n labelClassName = `matrx-tap-label ${toneColor}`;\n }\n if (pressed) pillClassName = `${pillClassName} matrx-tap-pressed`;\n const { outerClassName, inlineModifier } = resolveTapGeometry(\n label,\n size,\n mobileIconOnly,\n );\n const responsiveLabelClassName = mobileIconOnly\n ? `${labelClassName ?? \"matrx-tap-label\"} matrx-tap-label-mobile-icon-only`\n : labelClassName;\n const inner = buildTapInner({\n label,\n pillClassName,\n iconClassName,\n labelClassName: responsiveLabelClassName,\n inlineModifier: label ? inlineModifier : \"\",\n icon,\n children,\n strokeWidth,\n loading,\n chevron,\n });\n const triggerAriaLabel =\n label && !mobileIconOnly ? undefined : (ariaLabel ?? label);\n const trigger = renderTrigger({\n href,\n target,\n rel,\n prefetch,\n linkComponent,\n as,\n htmlFor,\n onClick: loading ? undefined : onClick,\n ariaLabel: triggerAriaLabel,\n disabled: isDisabled,\n outerClassName,\n title: titleMode && tipText ? (shortcut ? `${tipText} (${formatTapShortcut(shortcut)})` : tipText) : undefined,\n children: (\n <>\n {inner}\n {badge !== undefined ? <TapBadge badge={badge} /> : null}\n </>\n ),\n rest: {\n ...nativeRest,\n ...(pressed !== undefined ? { \"aria-pressed\": pressed } : {}),\n ...(loading ? { \"aria-busy\": true } : {}),\n ...(shortcut ? { \"aria-keyshortcuts\": shortcut.replace(/mod/i, \"Meta\") } : {}),\n },\n triggerRef,\n });\n if (titleMode || !tipText) return trigger;\n return withTooltip(trigger, {\n tooltip: tipText,\n ariaLabel: tipText,\n disabled: isDisabled,\n tooltipSide,\n tooltipAlign,\n shortcut,\n });\n}\n\ninterface RenderTriggerArgs {\n href?: string | undefined;\n target?: \"_blank\" | \"_self\" | \"_parent\" | \"_top\" | undefined;\n rel?: string | undefined;\n prefetch?: boolean | null | undefined;\n linkComponent?: TapTargetLinkComponent | undefined;\n as?: \"button\" | \"label\" | undefined;\n htmlFor?: string | undefined;\n onClick?: (() => void) | undefined;\n ariaLabel?: string | undefined;\n disabled?: boolean | undefined;\n outerClassName: string;\n children: ReactNode;\n rest?: ButtonHTMLAttributes<HTMLButtonElement> | undefined;\n triggerRef: Ref<HTMLElement>;\n /** Tooltip text drawn through `title` (tooltip={false}: a nested trigger). */\n title?: string | undefined;\n}\n\n/**\n * Resolves the correct trigger element based on the props passed.\n *\n * - `href` + `disabled` → unclickable `<span aria-disabled>`\n * - `href` matching `http(s):|mailto:|tel:` → `<a target=\"_blank\" rel=\"noopener noreferrer\">`\n * - `href` (internal) → the injected link component (per-instance\n * `linkComponent` prop, else `setTapTargetLinkComponent` registration),\n * falling back to a plain `<a>` when none is registered\n * - `as=\"label\"` → `<label htmlFor=...>`\n * - default → `<button>`\n */\nfunction renderTrigger({\n href,\n target,\n rel,\n prefetch,\n linkComponent,\n as,\n htmlFor,\n onClick,\n ariaLabel,\n disabled,\n outerClassName,\n children,\n rest,\n triggerRef,\n title,\n}: RenderTriggerArgs): ReactElement {\n const { style: _style, ...restWithoutStyle } = rest ?? {};\n if (disabled && href) {\n return (\n <span\n ref={triggerRef}\n aria-disabled=\"true\"\n aria-label={ariaLabel}\n title={title}\n className={`${outerClassName} opacity-40`}\n >\n {children}\n </span>\n );\n }\n if (href) {\n const isExternal = EXTERNAL_RE.test(href);\n if (isExternal) {\n return (\n <a\n ref={triggerRef as Ref<HTMLAnchorElement>}\n href={href}\n target={target ?? \"_blank\"}\n rel={rel ?? \"noopener noreferrer\"}\n aria-label={ariaLabel}\n title={title}\n className={outerClassName}\n >\n {children}\n </a>\n );\n }\n const Link = linkComponent ?? getTapTargetLinkComponent();\n if (Link) {\n return (\n <Link\n ref={triggerRef as Ref<HTMLAnchorElement>}\n href={href}\n target={target}\n rel={rel}\n prefetch={prefetch}\n aria-label={ariaLabel}\n title={title}\n className={outerClassName}\n >\n {children}\n </Link>\n );\n }\n // No link component registered — plain <a>. `prefetch` is a router hint,\n // not a DOM attribute, so it is deliberately dropped here.\n return (\n <a\n ref={triggerRef as Ref<HTMLAnchorElement>}\n href={href}\n target={target}\n rel={rel}\n aria-label={ariaLabel}\n title={title}\n className={outerClassName}\n >\n {children}\n </a>\n );\n }\n if (as === \"label\") {\n return (\n <label\n ref={triggerRef as Ref<HTMLLabelElement>}\n htmlFor={htmlFor}\n aria-label={ariaLabel}\n title={title}\n className={outerClassName}\n >\n {children}\n </label>\n );\n }\n return (\n <button\n ref={triggerRef as Ref<HTMLButtonElement>}\n type=\"button\"\n onClick={onClick}\n aria-label={ariaLabel}\n title={title}\n disabled={disabled}\n {...restWithoutStyle}\n className={outerClassName}\n >\n {children}\n </button>\n );\n}\n\n/**\n * Wraps a trigger element in a Tooltip when a tooltip label is available.\n * Falls back to `ariaLabel` when `tooltip` is not explicitly set. If both\n * are absent (or `tooltip === false`), the trigger is returned unwrapped.\n */\nfunction withTooltip(\n trigger: ReactElement,\n {\n tooltip,\n ariaLabel,\n disabled,\n tooltipSide = \"top\",\n tooltipAlign = \"center\",\n shortcut,\n }: {\n tooltip?: string | false | undefined;\n ariaLabel?: string | undefined;\n disabled?: boolean | undefined;\n tooltipSide?: \"top\" | \"right\" | \"bottom\" | \"left\" | undefined;\n tooltipAlign?: \"start\" | \"center\" | \"end\" | undefined;\n shortcut?: TapShortcut | undefined;\n },\n): ReactElement {\n if (tooltip === false) return trigger;\n const label =\n typeof tooltip === \"string\" && tooltip.length > 0 ? tooltip : ariaLabel;\n if (!label) return trigger;\n return (\n <Tooltip>\n <TooltipTrigger asChild>\n {disabled ? (\n // Radix Tooltip triggers need a hoverable element; a disabled button\n // does not dispatch pointer events, so we wrap in a span for the\n // trigger target while keeping the disabled visual state.\n <span className=\"inline-flex\">{trigger}</span>\n ) : (\n trigger\n )}\n </TooltipTrigger>\n <TooltipContent side={tooltipSide} align={tooltipAlign}>\n {tooltipBody(label, shortcut)}\n </TooltipContent>\n </Tooltip>\n );\n}\n\n// To resize/retune every tap button, edit styles.css — not here.\n\nexport const TapTargetButton = forwardRef<\n HTMLButtonElement,\n TapTargetButtonProps & TapTargetNativeProps\n>(function TapTargetButton(\n {\n icon,\n children,\n strokeWidth = 2,\n onClick,\n className,\n as,\n htmlFor,\n ariaLabel,\n disabled,\n href,\n target,\n rel,\n prefetch,\n linkComponent,\n tooltip,\n tooltipSide,\n tooltipAlign,\n label,\n mobileIconOnly,\n ...rest\n },\n ref,\n) {\n const color = className ?? \"text-foreground\";\n return useTapTarget({\n colorClassName: className,\n icon,\n children,\n strokeWidth,\n onClick,\n as,\n htmlFor,\n ariaLabel,\n disabled,\n href,\n target,\n rel,\n prefetch,\n linkComponent,\n tooltip,\n tooltipSide,\n tooltipAlign,\n label,\n mobileIconOnly,\n pillClassName: \"matrx-tap-pill matrx-glass-thin-border\",\n iconClassName: `matrx-tap-icon ${color}`,\n rest,\n buttonRef: ref,\n });\n});\n\nexport const TapTargetButtonTransparent = forwardRef<\n HTMLButtonElement,\n TapTargetButtonProps & TapTargetNativeProps\n>(function TapTargetButtonTransparent(\n {\n icon,\n children,\n strokeWidth = 2,\n onClick,\n className,\n as,\n htmlFor,\n ariaLabel,\n disabled,\n href,\n target,\n rel,\n prefetch,\n linkComponent,\n tooltip,\n tooltipSide,\n tooltipAlign,\n label,\n mobileIconOnly,\n ...rest\n },\n ref,\n) {\n const color = className ?? \"text-foreground\";\n return useTapTarget({\n colorClassName: className,\n icon,\n children,\n strokeWidth,\n onClick,\n as,\n htmlFor,\n ariaLabel,\n disabled,\n href,\n target,\n rel,\n prefetch,\n linkComponent,\n tooltip,\n tooltipSide,\n tooltipAlign,\n label,\n mobileIconOnly,\n pillClassName:\n \"matrx-tap-pill group-hover/tap:bg-muted group-active/tap:bg-muted-foreground/15\",\n iconClassName: `matrx-tap-icon ${color}`,\n rest,\n buttonRef: ref,\n });\n});\n\n/** Outline pill — a plain 1px border, no fill, no blur, no shadow. Glass only\n * reads as glass over something you can see through; on an opaque card or\n * header use THIS. Same colors as the classic square \"+\": border-border,\n * muted glyph, primary border + foreground glyph on hover. */\nexport const TapTargetButtonOutline = forwardRef<\n HTMLButtonElement,\n TapTargetButtonProps & TapTargetNativeProps\n>(function TapTargetButtonOutline(\n {\n icon,\n children,\n strokeWidth = 2,\n onClick,\n className,\n as,\n htmlFor,\n ariaLabel,\n disabled,\n href,\n target,\n rel,\n prefetch,\n linkComponent,\n tooltip,\n tooltipSide,\n tooltipAlign,\n label,\n mobileIconOnly,\n ...rest\n },\n ref,\n) {\n const color =\n className ?? \"text-muted-foreground group-hover/tap:text-foreground\";\n return useTapTarget({\n colorClassName: className,\n icon,\n children,\n strokeWidth,\n onClick,\n as,\n htmlFor,\n ariaLabel,\n disabled,\n href,\n target,\n rel,\n prefetch,\n linkComponent,\n tooltip,\n tooltipSide,\n tooltipAlign,\n label,\n mobileIconOnly,\n pillClassName:\n \"matrx-tap-pill border border-border bg-transparent transition-colors group-hover/tap:border-primary/60 group-active/tap:bg-muted\",\n iconClassName: `matrx-tap-icon ${color}`,\n labelClassName: `matrx-tap-label ${color}`,\n rest,\n buttonRef: ref,\n });\n});\n\nexport const TapTargetButtonSolid = forwardRef<\n HTMLButtonElement,\n TapTargetButtonSolidProps & TapTargetNativeProps\n>(function TapTargetButtonSolid(\n {\n icon,\n children,\n strokeWidth = 2,\n onClick,\n as,\n htmlFor,\n ariaLabel,\n disabled,\n href,\n target,\n rel,\n prefetch,\n linkComponent,\n tone,\n bgColor,\n iconColor,\n hoverBgColor,\n activeBgColor,\n tooltip,\n tooltipSide,\n tooltipAlign,\n label,\n mobileIconOnly,\n ...rest\n },\n ref,\n) {\n return useTapTarget({\n icon,\n children,\n strokeWidth,\n onClick,\n as,\n htmlFor,\n ariaLabel,\n disabled,\n href,\n target,\n rel,\n prefetch,\n linkComponent,\n tooltip,\n tooltipSide,\n tooltipAlign,\n label,\n mobileIconOnly,\n ...solidClasses(tone, bgColor, iconColor, hoverBgColor, activeBgColor),\n rest,\n buttonRef: ref,\n });\n});\n\n// `tone` is the system's fill; the four color strings are the pre-tone API,\n// accepted only until their last callers move to `tone`. `matrx-tap-solid` marks the\n// filled pill so the stylesheet can give a DISABLED solid the system's disabled token\n// (muted fill + --disabled-foreground glyph) instead of a 40%-opacity ghost of its fill.\nfunction solidClasses(\n tone: TapSolidTone | undefined,\n bgColor: string | undefined,\n iconColor: string | undefined,\n hoverBgColor: string | undefined,\n activeBgColor: string | undefined,\n) {\n const legacy = !tone && (bgColor || iconColor || hoverBgColor || activeBgColor);\n if (!legacy) {\n const t = TAP_SOLID_TONE[tone ?? \"primary\"];\n return {\n pillClassName: `matrx-tap-pill matrx-tap-solid ${t.fill} ${t.glyph} group-active/tap:brightness-90`,\n iconClassName: `matrx-tap-icon ${t.glyph}`,\n labelClassName: `matrx-tap-label ${t.glyph}`,\n };\n }\n const glyph = iconColor ?? \"text-primary-foreground\";\n return {\n pillClassName: `matrx-tap-pill matrx-tap-solid ${bgColor ?? \"bg-primary\"} ${glyph} ${hoverBgColor ?? \"group-hover/tap:bg-primary/80\"} ${activeBgColor ?? \"group-active/tap:brightness-90\"}`,\n iconClassName: `matrx-tap-icon ${glyph}`,\n labelClassName: `matrx-tap-label ${glyph}`,\n };\n}\n\n/** Solid destructive pill — delete/remove actions. White-on-red like the\n * primary solid is white-on-blue. Use THIS, never hand-pass bg-destructive\n * with the default (dark) icon color. */\nexport const TapTargetButtonDestructive = forwardRef<\n HTMLButtonElement,\n TapTargetButtonSolidProps & TapTargetNativeProps\n>(function TapTargetButtonDestructive({ tone = \"destructive\", ...rest }, ref) {\n return <TapTargetButtonSolid ref={ref} tone={tone} {...rest} />;\n});\n\nexport const TapTargetButtonForGroup = forwardRef<\n HTMLButtonElement,\n TapTargetButtonProps & TapTargetNativeProps\n>(function TapTargetButtonForGroup(\n {\n icon,\n children,\n strokeWidth = 2,\n onClick,\n className,\n as,\n htmlFor,\n ariaLabel,\n disabled,\n href,\n target,\n rel,\n prefetch,\n linkComponent,\n tooltip,\n tooltipSide,\n tooltipAlign,\n label,\n mobileIconOnly,\n ...rest\n },\n ref,\n) {\n const color = className ?? \"text-foreground\";\n return useTapTarget({\n colorClassName: className,\n size: \"sm\",\n icon,\n children,\n strokeWidth,\n onClick,\n as,\n htmlFor,\n ariaLabel,\n disabled,\n href,\n target,\n rel,\n prefetch,\n linkComponent,\n tooltip,\n tooltipSide,\n tooltipAlign,\n label,\n mobileIconOnly,\n pillClassName: \"matrx-tap-pill matrx-tap-pill-sm matrx-glass-interactive\",\n iconClassName: `matrx-tap-icon ${color}`,\n labelClassName: `matrx-tap-label ${color}`,\n rest,\n buttonRef: ref,\n });\n});\n\nexport function TapTargetButtonGroup({\n children,\n className,\n surface: surfaceProp,\n}: {\n children: React.ReactNode;\n className?: string | undefined;\n /**\n * GLASS ONLY FLOATS (owner rule, 2026-10-02): glass belongs on a bar that\n * floats over scrolling content or a see-through plane. On a solid surface\n * (a page, a card, a toast, a table toolbar) use `\"solid\"`: a muted track,\n * no glass stroke, the same geometry.\n */\n surface?: \"glass\" | \"solid\" | undefined;\n}) {\n // Geometry (height, the half-gap outside the capsule, the capsule itself)\n // is `.matrx-tap-group*` in tap-target.css.\n const surface = useTapSurface(surfaceProp);\n return (\n <div\n className={className ? `matrx-tap-group ${className}` : \"matrx-tap-group\"}\n data-surface={surface}\n >\n <div\n className={\n surface === \"solid\"\n ? \"matrx-tap-group-capsule matrx-tap-group-capsule-solid\"\n : \"matrx-tap-group-capsule matrx-glass-thin-border\"\n }\n />\n <div className=\"matrx-tap-group-row\">{children}</div>\n </div>\n );\n}\n","\"use client\";\n\n/**\n * Tooltip — the ONE tooltip in the fleet.\n *\n * THE COLLAPSE (0.6.0). Two implementations existed: matrx-frontend's\n * `components/ui/tooltip.tsx` (182 import sites) and `@ai-matrx/tap-target`'s\n * `src/tooltip.tsx` — the latter an explicit inlined PORT of the former,\n * carrying a header that said so. tap-target shipped it only because its ~60\n * tap buttons need a tooltip and no shared package owned one; four repos then\n * adopted `TooltipProvider` from tap-target. That made tap-target — a\n * button-geometry package — the accidental owner of a design-system primitive,\n * with a second copy living in the biggest host.\n *\n * A tooltip is a design-system surface, so it lives here. tap-target now takes\n * `@ai-matrx/design-system` as an ordinary sibling dependency and imports this\n * file; its own copy is deleted, and its re-export removed. The DAG already\n * ordered design-system before tap-target, so no cycle is introduced.\n *\n * BEHAVIOR is matrx-frontend's, verbatim, including the ruling both copies\n * carried in prose:\n *\n * 1. THE ROOT RENDERS UNCONDITIONALLY — no hydration mount gate. The gate the\n * host wrapper once carried (\"Radix generates dynamic aria-controls ids that\n * differ between SSR and client\") was false: Radix ids come from React's\n * SSR-stable `useId`. It was actively harmful — a Trigger wraps\n * ALWAYS-VISIBLE content, so `return null` deleted that subtree from SSR and\n * the first client paint.\n *\n * 2. THE SURFACE IS TOKEN-DRIVEN, NOT BRANDED. Popover tokens, not\n * `bg-primary`: rich tooltip content using `text-muted-foreground` was\n * illegible on a brand-colored background in one theme or the other.\n * Since 2026-09-28 the `.matrx-tooltip` class re-scopes those tokens to a dark,\n * high-contrast chip in both themes (styles.css, THE TOOLTIP SURFACE): the\n * neutral white surface it wore before was indistinguishable from the\n * browser's own `title` box.\n *\n * 3. EVERY `title` IS THIS TOOLTIP. The provider installs the title takeover\n * (`title-tooltips.ts`), so a hand-written `title=` anywhere in the\n * document shows this surface, never the browser's.\n *\n * SEAM INVERSION. The host resolved nested portal targets through\n * `useNestedPortalContainer` (an app hook wired to its dialog + window-panel\n * systems); tap-target's port dropped that seam entirely and always portalled\n * to `document.body` — which is why a tooltip inside a popped-out panel landed\n * in the wrong window. Here it is the package's `PortalContainerProvider`\n * seam: an explicit `container` prop wins, then the injected container, then\n * `document.body`. Both prior behaviors are reachable; neither is forked.\n */\n\nimport * as TooltipPrimitive from \"@radix-ui/react-tooltip\";\nimport * as React from \"react\";\n\nimport { cn } from \"./cn\";\nimport { MOTION_POPPER } from \"./motion\";\nimport { usePortalContainer } from \"./portal-container\";\nimport { acquireTitleTooltips, clipTooltipText, tooltipSide, TOOLTIP_EDGE_PX, TOOLTIP_LAYER_Z, TOOLTIP_TRIGGER_ATTR, type Side } from \"./title-tooltips\";\n\nexport interface TooltipProviderProps\n extends React.ComponentProps<typeof TooltipPrimitive.Provider> {\n /**\n * THE TITLE TAKEOVER (2026-09-28) — while any provider is mounted, every native\n * `title` attribute in the document shows as this tooltip instead of the\n * browser's (see `title-tooltips.ts`). On by default, because a rule every\n * author must remember is a rule that is broken; pass `false` only for a\n * surface that must keep the browser's own box. One provider opting out does\n * not turn it off while another one is mounted.\n */\n titleTooltips?: boolean;\n}\n\n/**\n * Mount once near the app root. Every tooltip in the tree shares its\n * `delayDuration` / `skipDelayDuration` timing, and the root provider takes\n * over native `title` attributes (see `titleTooltips`). The fleet default keeps\n * tooltip content hoverable and selectable. A native mirrored Desktop shell may\n * explicitly opt in to `disableHoverableContent` so its overlay view yields the\n * pointer back to the host; ordinary application tooltips must leave it unset.\n */\nfunction TooltipProvider({ titleTooltips = true, disableHoverableContent = false, ...props }: TooltipProviderProps) {\n React.useEffect(() => {\n if (!titleTooltips) return;\n return acquireTitleTooltips();\n }, [titleTooltips]);\n return <TooltipPrimitive.Provider {...props} disableHoverableContent={disableHoverableContent} />;\n}\n\n/**\n * The tooltip root inherits its provider's hoverability policy: the ordinary\n * provider defaults to hoverable, selectable content (Arman, 2026-10-14), while\n * a native mirrored Desktop shell may opt in at its provider so the overlay view\n * yields pointer control to its host. An explicit root prop still wins.\n */\n/** The tooltip's trigger and whether it is open, so its content takes THE SMART SIDE\n * (title-tooltips.ts) from where the trigger stands at the moment it opens. */\ninterface TriggerState {\n ref: React.MutableRefObject<HTMLElement | null>;\n open: boolean;\n}\nconst TriggerContext = React.createContext<TriggerState | null>(null);\n\nconst Tooltip = ({ onOpenChange, ...props }: React.ComponentProps<typeof TooltipPrimitive.Root>) => {\n const ref = React.useRef<HTMLElement | null>(null);\n const [open, setOpen] = React.useState(Boolean(props.open ?? props.defaultOpen));\n const shown = props.open ?? open;\n const value = React.useMemo(() => ({ ref, open: shown }), [shown]);\n return (\n <TriggerContext.Provider value={value}>\n <TooltipPrimitive.Root\n {...props}\n onOpenChange={(next) => {\n setOpen(next);\n onOpenChange?.(next);\n }}\n />\n </TriggerContext.Provider>\n );\n};\nTooltip.displayName = \"Tooltip\";\n\n/**\n * Stamps `data-matrx-tooltip-trigger` so the title takeover never draws a\n * second tooltip over a control that already has this one — it still lifts a\n * `title` on the same control, so the browser's box never doubles it either.\n */\nconst TooltipTrigger = React.forwardRef<\n React.ComponentRef<typeof TooltipPrimitive.Trigger>,\n React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Trigger>\n>((props, ref) => {\n const trigger = React.useContext(TriggerContext);\n const setRef = React.useCallback(\n (node: HTMLButtonElement | null) => {\n if (trigger) trigger.ref.current = node;\n if (typeof ref === \"function\") ref(node);\n else if (ref) ref.current = node;\n },\n [trigger, ref],\n );\n return <TooltipPrimitive.Trigger ref={setRef} {...{ [TOOLTIP_TRIGGER_ATTR]: \"\" }} {...props} />;\n});\nTooltipTrigger.displayName = TooltipPrimitive.Trigger.displayName;\n\nexport interface TooltipContentProps\n extends React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Content> {\n /**\n * Explicit portal target; wins over the injected `PortalContainerProvider`\n * value. Pass `null` to force `document.body`.\n */\n container?: HTMLElement | null;\n /**\n * Package-owned open/close motion. Default `true`. Pass `false` for a\n * surface that must appear instantly. It is NOT the reduced-motion switch;\n * `styles.css` already honors `prefers-reduced-motion`.\n */\n animated?: boolean;\n /**\n * The side when the control is not in a vertical stack and no side is given (the host's default:\n * a macOS desktop host says \"bottom\"). Omit for the document's `data-title-side`, else \"top\".\n */\n fallbackSide?: Side;\n}\n\nconst TooltipContent = React.forwardRef<\n React.ComponentRef<typeof TooltipPrimitive.Content>,\n TooltipContentProps\n>(({ className, side, fallbackSide, sideOffset = 4, collisionPadding = TOOLTIP_EDGE_PX, container, animated = true, children, style, ...props }, ref) => {\n const resolved = usePortalContainer(container);\n const trigger = React.useContext(TriggerContext);\n // THE SMART SIDE: an explicit side wins; otherwise where the trigger's neighbours stand decides.\n const placed = side ?? (trigger?.open ? tooltipSide(trigger.ref.current, fallbackSide) : (fallbackSide ?? \"top\"));\n return (\n <TooltipPrimitive.Portal container={resolved ?? null}>\n <TooltipPrimitive.Content\n ref={ref}\n data-slot=\"tooltip-content\"\n side={placed}\n sideOffset={sideOffset}\n // Flip and stay inside the window: Radix flips to the opposite side when the preferred one\n // does not fit, and shifts along the edge; the padding keeps it off the window's border.\n avoidCollisions\n collisionPadding={collisionPadding}\n className={cn(\n \"matrx-tooltip max-w-xs select-text overflow-hidden whitespace-normal break-words rounded-md border border-border bg-popover px-2.5 py-1 text-xs font-medium text-popover-foreground\",\n animated && MOTION_POPPER,\n className,\n )}\n // THE tooltip layer: above every menu, popover and modal (Radix copies it onto its wrapper).\n style={{ zIndex: TOOLTIP_LAYER_Z, ...style }}\n {...props}\n >\n {typeof children === \"string\" ? clipTooltipText(children) : children}\n </TooltipPrimitive.Content>\n </TooltipPrimitive.Portal>\n );\n});\nTooltipContent.displayName = TooltipPrimitive.Content.displayName;\n\nexport { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger };\nexport { acquireTitleTooltips, clipTooltipText, NATIVE_TITLE_OPT_OUT_ATTR, TOOLTIP_TEXT_BUDGET } from \"./title-tooltips\";\n","\"use client\";\n\n// THE TAP-TARGET GUARD — development builds only.\n//\n// The lock layer in tap-target.css makes a tap button's own box, pill and\n// glyph impossible to resize from outside. What CSS cannot stop is a caller\n// bending the system AROUND the button: a parent that adds `gap` between two\n// tap buttons, a wrapper with margin or padding, a local override of a\n// `--matrx-tap-*` token, a utility class smuggled in through `className`.\n// After a tap button mounts, this guard measures it in the real layout and,\n// on any of those, marks it `data-matrx-tap-violation`: the stylesheet then\n// paints it as a giant red box carrying the reason, and the console names\n// the element.\n//\n// OFF until the host turns it on with `enableTapTargetGuard()` — from code the\n// HOST compiles, e.g. matrx-frontend's dev-only client boot. Never gate it on\n// `process.env.NODE_ENV` in here: this package's own build inlines that\n// expression, so a \"dev only\" check written here would run in production too\n// (see @ai-matrx/associations' context.tsx for the outage that taught this).\n\nimport { useCallback, useRef, type MutableRefObject, type Ref } from \"react\";\nimport { layoutScale } from \"../layout-scale\";\n\n// A `Symbol.for` slot on globalThis, like the link seam: the `.` and\n// `./buttons` bundles each inline this module, and one switch must reach both.\nconst GUARD_SLOT = Symbol.for(\"@ai-matrx/tap-target:guard\");\ntype GlobalWithGuard = typeof globalThis & { [GUARD_SLOT]?: boolean };\n\n/** Turn the development guard on (or off). Call once at client boot, only in\n * development builds of the host. */\nexport function enableTapTargetGuard(on = true): void {\n (globalThis as GlobalWithGuard)[GUARD_SLOT] = on;\n if (on) startPillInsetScan();\n}\n\nfunction guardOn(): boolean {\n return (globalThis as GlobalWithGuard)[GUARD_SLOT] === true;\n}\n\nconst TOKENS = [\n \"--matrx-tap-box\",\n \"--matrx-tap-gap\",\n \"--matrx-tap-pill-size\",\n \"--matrx-tap-pill-sm-size\",\n \"--matrx-tap-wide-size\",\n \"--matrx-tap-icon-size\",\n \"--matrx-tap-touch-min\",\n \"--matrx-tap-target-size\",\n] as const;\n\n/** The only scopes that may move tap tokens, and which ones — each owned by\n * this package's own CSS: the table density scales (tap-target.css) and\n * Alchemy's 18px trigger glyph (content-transfer.css). */\nconst SANCTIONED: ReadonlyArray<{ scope: string; tokens: ReadonlySet<string> }> = [\n {\n scope: \"[data-matrx-table][data-matrx-table-density]\",\n tokens: new Set([\n \"--matrx-tap-target-size\",\n \"--matrx-tap-pill-size\",\n \"--matrx-tap-wide-size\",\n \"--matrx-tap-pill-sm-size\",\n \"--matrx-tap-icon-size\",\n ]),\n },\n { scope: \"[data-alchemy-trigger]\", tokens: new Set([\"--matrx-tap-icon-size\"]) },\n // THE ONE CONTROL scope (controls.css): tap buttons beside the 28px controls\n // take the controls' height — a 28px pill in a 34px box, the same 6px apart.\n {\n scope: \"[data-matrx-controls]\",\n tokens: new Set([\n \"--matrx-tap-target-size\",\n \"--matrx-tap-pill-size\",\n \"--matrx-tap-wide-size\",\n \"--matrx-tap-pill-sm-size\",\n ]),\n },\n];\nconst TABLE_SCOPE = SANCTIONED[0]!.scope;\nconst CONTROL_SCOPE = SANCTIONED[2]!.scope;\nconst TAP_ITEM = \".matrx-tap-target, .matrx-tap-group\";\n\n/** `className` on a tap button is the GLYPH COLOR. Anything that sizes,\n * spaces, positions or fills is misuse. */\nconst NON_COLOR_CLASS =\n /^(?:[^\\s:]+:)*!?-?(?:\\[&|scale|translate|h|w|size|min-h|min-w|max-h|max-w|p|px|py|ps|pe|pt|pb|pl|pr|m|mx|my|ms|me|mt|mb|ml|mr|gap|space-x|space-y|bg|rounded|border|ring|shadow|absolute|relative|fixed|sticky|inset|top|left|right|bottom|flex|grid|block|inline|hidden|z|shrink|grow|basis|self|order)(?:-|$|\\[)/;\n\nexport function classNameMisuse(className: string | undefined): string | null {\n if (!guardOn() || !className) return null;\n const bad = className.split(/\\s+/).filter((t) => t && NON_COLOR_CLASS.test(t));\n return bad.length\n ? `className is the glyph color only — remove \"${bad.join(\" \")}\"`\n : null;\n}\n\n/**\n * The horizontal space a wrapper adds around what it holds. An `auto` margin (`ml-auto` pushing a\n * toolbar's actions to the end) only aligns — the browser resolves it to pixels in\n * `getComputedStyle`, so read the computed keyword from the typed OM and count it as zero.\n */\nexport function wrapperSpace(el: Element, view: Window): number {\n const pcs = view.getComputedStyle(el);\n const typed = (el as Element & { computedStyleMap?: () => { get(p: string): unknown } }).computedStyleMap?.();\n const margin = (prop: \"margin-left\" | \"margin-right\", resolved: string) =>\n typed && String(typed.get(prop)) === \"auto\" ? 0 : px(resolved);\n return margin(\"margin-left\", pcs.marginLeft) + margin(\"margin-right\", pcs.marginRight) + px(pcs.paddingLeft) + px(pcs.paddingRight);\n}\n\nfunction px(value: string): number {\n const n = Number.parseFloat(value);\n return Number.isFinite(n) ? n : 0;\n}\n\nfunction describe(el: Element): string {\n const cls = typeof el.className === \"string\" ? el.className.trim().split(/\\s+/).slice(0, 4).join(\".\") : \"\";\n return `<${el.tagName.toLowerCase()}${cls ? `.${cls}` : \"\"}>`;\n}\n\n/** Elements that ride along with a tap button without taking space from it\n * (a badge, a capsule, a tooltip portal anchor). */\nfunction isDecor(el: Element, view: Window): boolean {\n const cs = view.getComputedStyle(el);\n return cs.position === \"absolute\" || cs.position === \"fixed\" || cs.display === \"none\";\n}\n\nfunction tapCount(el: Element): number {\n return el.matches(TAP_ITEM) ? 1 : el.querySelectorAll(TAP_ITEM).length;\n}\n\n/** Visible text in `container` outside `tap` and outside decor (a badge's\n * count is decor) — a wrapper with its own words is a chip, not a wrapper. */\nfunction ownText(container: Element, tap: Element, view: Window): string {\n let out = \"\";\n const walk = (node: Node) => {\n if (node === tap) return;\n if (node.nodeType === 3) out += node.textContent ?? \"\";\n else if (node.nodeType === 1 && !isDecor(node as Element, view)) node.childNodes.forEach(walk);\n };\n container.childNodes.forEach(walk);\n return out.trim();\n}\n\n/** True when `child` is a tap button, or a plain wrapper whose only content\n * is ONE tap button (plus decor) — never a search box that happens to hold\n * a clear button, never a chip with words. */\nfunction isTapSlot(child: Element, view: Window): boolean {\n if (child.matches(TAP_ITEM)) return true;\n if (tapCount(child) !== 1) return false;\n const tap = child.querySelector(TAP_ITEM)!;\n const controls = Array.from(child.querySelectorAll(\"input, select, textarea, button, a, [role='button']\"));\n if (controls.some((c) => c !== tap && !tap.contains(c))) return false;\n return ownText(child, tap, view) === \"\";\n}\n\nlet probe: { key: string; target: number; pill: number; sm: number; smPill: number; wide: number; icon: number } | null = null;\n\n/** What the package's own CSS produces with no surrounding context — the\n * canon every mounted button is measured against. Re-measured whenever the\n * root tokens change (the lab page switches the gap). */\nfunction canon(doc: Document) {\n const view = doc.defaultView!;\n const root = view.getComputedStyle(doc.documentElement);\n const key = TOKENS.map((t) => root.getPropertyValue(t)).join(\"|\");\n if (probe?.key === key) return probe;\n const host = doc.createElement(\"div\");\n host.setAttribute(\"aria-hidden\", \"true\");\n host.style.cssText = \"position:absolute;visibility:hidden;pointer-events:none;left:-9999px;top:0\";\n host.innerHTML =\n '<button class=\"matrx-tap-target\"><div class=\"matrx-tap-pill\"><svg class=\"matrx-tap-icon\"></svg></div></button>' +\n '<button class=\"matrx-tap-target matrx-tap-target-sm\"><div class=\"matrx-tap-pill matrx-tap-pill-sm\"></div></button>' +\n '<button class=\"matrx-tap-target matrx-tap-target-inline\"><div class=\"matrx-tap-pill matrx-tap-pill-inline\"></div></button>';\n doc.body.appendChild(host);\n const [a, b, w] = Array.from(host.children) as HTMLElement[];\n probe = {\n key,\n target: a!.offsetHeight,\n pill: (a!.firstElementChild as HTMLElement).offsetHeight,\n icon: px(view.getComputedStyle(a!.querySelector(\"svg\")!).height),\n sm: b!.offsetHeight,\n smPill: (b!.firstElementChild as HTMLElement).offsetHeight,\n wide: (w!.firstElementChild as HTMLElement).offsetHeight,\n };\n host.remove();\n return probe;\n}\n\n/** Returns the first rule this mounted tap button breaks, or null. */\nexport function findTapViolation(el: HTMLElement): string | null {\n const doc = el.ownerDocument;\n const view = doc.defaultView;\n if (!view || !el.isConnected) return null;\n const cs = view.getComputedStyle(el);\n if (cs.display === \"none\") return null;\n\n // 1. Tokens are the package's alone. Only the table-density scope may move\n // the three it owns.\n const root = view.getComputedStyle(doc.documentElement);\n // Both scaled scopes size by their own tokens; the canon check below reads\n // the root canon, so it applies outside them only.\n const inTable = el.closest(TABLE_SCOPE) !== null || el.closest(CONTROL_SCOPE) !== null;\n const moved = new Set<string>();\n for (const token of TOKENS) {\n const mine = cs.getPropertyValue(token).trim();\n const base = root.getPropertyValue(token).trim();\n if (mine === base) continue;\n if (!SANCTIONED.some((s) => s.tokens.has(token) && el.closest(s.scope))) {\n return `${token} overridden to \"${mine}\" — tap geometry is not configurable`;\n }\n moved.add(token);\n }\n\n // 2. Measured geometry equals the canon (outside table density, which\n // sizes by its own tokens).\n const sm = el.classList.contains(\"matrx-tap-target-sm\");\n const inline = /matrx-tap-target-(?:inline|mobile-icon-only)/.test(el.className);\n const pill = el.querySelector<HTMLElement>(\":scope > .matrx-tap-pill\");\n const icon = pill?.querySelector(\".matrx-tap-icon\") ?? null;\n // A host touch floor (min-width / min-height) may enlarge a box; that is\n // the floor working, not a bend.\n const floored =\n px(cs.minHeight) >= el.offsetHeight - 0.5 || px(cs.minWidth) >= el.offsetWidth - 0.5;\n if (!inTable && pill && !floored) {\n const c = canon(doc);\n const box = sm ? c.sm : c.target;\n // A labeled pill is a WIDE shape (shorter than a round one); below the\n // `sm` breakpoint a mobile-icon-only pill is round again — either is canon.\n const pillSizes = sm ? [c.smPill] : inline ? [c.pill, c.wide] : [c.pill];\n if (Math.abs(el.offsetHeight - box) > 0.5) return `button is ${el.offsetHeight}px tall, canon is ${box}px`;\n if (!inline && Math.abs(el.offsetWidth - box) > 0.5) return `button is ${el.offsetWidth}px wide, canon is ${box}px`;\n if (!pillSizes.some((p) => Math.abs(pill.offsetHeight - p) <= 0.5)) {\n return `pill is ${pill.offsetHeight}px, canon is ${pillSizes.join(\" or \")}px`;\n }\n if (icon && !moved.has(\"--matrx-tap-icon-size\")) {\n const size = px(view.getComputedStyle(icon).height);\n if (Math.abs(size - c.icon) > 0.5) return `glyph is ${size}px, canon is ${c.icon}px`;\n }\n }\n\n // 3. Nothing adds space around it. Climb the wrappers that hold only this\n // button (plus decor such as a badge); none may carry inline margin or\n // padding. A tap button inside a group is represented by its group.\n let slot: Element = el;\n if (el.parentElement?.matches(\".matrx-tap-group-row, .matrx-tap-search-measure\")) {\n const group = el.closest(\".matrx-tap-group\");\n if (group && tapCount(el.parentElement) > 1) return null;\n slot = group ?? el;\n }\n for (let depth = 0; depth < 2; depth += 1) {\n const parent: HTMLElement | null = slot.parentElement;\n if (!parent || parent === doc.body) break;\n const others = Array.from(parent.children).filter((c) => c !== slot && !isDecor(c, view));\n if (others.length > 0) break; // `parent` is the row\n if (ownText(parent, slot, view) !== \"\") break; // a chip or a titled header\n const space = wrapperSpace(parent, view);\n if (space > 0.5) {\n return `${describe(parent)} adds ${space}px around a tap button — tap buttons space themselves`;\n }\n slot = parent;\n }\n\n // 4. The row adds no gap between tap buttons.\n const row = slot.parentElement;\n if (row) {\n const rcs = view.getComputedStyle(row);\n const flexOrGrid = /flex|grid/.test(rcs.display);\n const neighbours = Array.from(row.children).filter((c) => c !== slot && isTapSlot(c, view));\n if (flexOrGrid && neighbours.length > 0) {\n const horizontal = rcs.display.includes(\"grid\") || !rcs.flexDirection.startsWith(\"column\");\n const gap = px(horizontal ? rcs.columnGap : rcs.rowGap);\n if (gap > 0.5) {\n return `${describe(row)} adds a ${gap}px gap between tap buttons — remove it; tap buttons space themselves`;\n }\n }\n }\n return null;\n}\n\n/* ------------------------------------------------------------------ */\n/* PLACEMENT — the three rules a tap button's SURROUNDINGS must keep */\n/* (owner, 2026-10-02). Reported as a WARNING (a dashed outline and one */\n/* console error naming the fix), not the misuse box: they are about */\n/* the page around the button, and the whole app is being brought into */\n/* line with them. */\n/* 1. GLASS ONLY FLOATS — glass is see-through; it belongs on a bar */\n/* that floats over moving content (position fixed/sticky) or on a */\n/* plane marked `data-matrx-glass-plane`. On a page, card, toast or */\n/* table use `variant=\"transparent\"` / a solid group. */\n/* 2. ALL GLASS OR NONE — a glass item's row holds only glass items */\n/* (glass tap buttons, glass groups, or `data-matrx-glass` pieces). */\n/* 3. NEIGHBOURS KEEP THEIR HALF-GAP — a tap box carries 3px of unseen */\n/* space each side (box − pill = one gap, 6px). Anything beside it */\n/* adds its own 3px, so the visible distance is always one gap. */\n/* ------------------------------------------------------------------ */\n\nconst GLASS = \".matrx-glass-thin-border, .matrx-glass-interactive\";\n\nfunction isGlassItem(node: Element): boolean {\n if (node.hasAttribute(\"data-matrx-glass\")) return true;\n if (node.matches(\".matrx-tap-group\")) return node.querySelector(\":scope > .matrx-tap-group-capsule.matrx-glass-thin-border\") !== null;\n if (node.matches(\".matrx-tap-target\")) return node.querySelector(`:scope > .matrx-tap-pill:is(${GLASS})`) !== null;\n // A plain wrapper whose only content is ONE tap button (plus decor such as a\n // badge) is that button: a badge host around a glass button is glass.\n const view = node.ownerDocument.defaultView;\n if (view && isTapSlot(node, view)) return isGlassItem(node.querySelector(TAP_ITEM)!);\n return false;\n}\n\nconst SCROLLS = /^(auto|scroll|overlay)$/;\n\n/** True when `el` rides a bar over moving content: a fixed/sticky ancestor (or\n * a glass plane) reached BEFORE any scroll container. Inside a scroller the\n * button IS the moving content — an app root that is itself `position:\n * fixed` (the shell) must not make every page button \"float\". */\nfunction floats(el: Element, view: Window): boolean {\n for (let n: Element | null = el; n && n !== el.ownerDocument.body; n = n.parentElement) {\n if (n.hasAttribute(\"data-matrx-glass-plane\")) return true;\n const cs = view.getComputedStyle(n);\n if (cs.position === \"fixed\" || cs.position === \"sticky\") return true;\n if (n !== el && (SCROLLS.test(cs.overflowY) || SCROLLS.test(cs.overflowX))) return false;\n }\n return false;\n}\n\n/** True when the edge of `wrapper` that faces a neighbour (`side` is where the\n * wrapper sits relative to that neighbour) is itself a tap slot: that button\n * carries its own 3px half-gap, so the wrapper is spacing-correct however many\n * tap buttons it holds (the fading mic + More cluster beside Send). A wrapper\n * whose edge is text or a field is not — it still has to keep its distance. */\nfunction facesWithTapSlot(wrapper: Element, side: \"after\" | \"before\", view: Window): boolean {\n for (let node: Element | null = wrapper; node; ) {\n if (isTapSlot(node, view)) return true;\n const kids: Element[] = Array.from(node.children).filter((c) => !isDecor(c, view));\n node = (side === \"after\" ? kids[0] : kids[kids.length - 1]) ?? null;\n }\n return false;\n}\n\nfunction visible(el: Element, view: Window): boolean {\n if (el.getAttribute(\"aria-hidden\") === \"true\" || isDecor(el, view)) return false;\n const r = el.getBoundingClientRect();\n return r.width > 1 && r.height > 1;\n}\n\nconst INTERACTIVE = \"button, a[href], input, select, textarea, [role='button'], svg, img\";\n\n/** The box the eye sees on the side of `sib` that faces the tap button. An\n * unpainted layout wrapper (no fill, no border on that side, no words of its\n * own) is invisible, so the distance is judged at the first thing inside it —\n * the wrapper around ProTextarea's mic sits 3px from Expand while the mic\n * capsule, which keeps its own 3px margin, sits one gap away (2026-10-13). */\nfunction facingBox(sib: Element, side: \"after\" | \"before\", view: Window): Element {\n let node = sib;\n for (;;) {\n if (node.matches(INTERACTIVE)) return node;\n const cs = view.getComputedStyle(node);\n const fill = cs.backgroundColor;\n if ((fill && fill !== \"rgba(0, 0, 0, 0)\" && fill !== \"transparent\") || px(side === \"after\" ? cs.borderLeftWidth : cs.borderRightWidth) > 0) {\n return node;\n }\n if (Array.from(node.childNodes).some((c) => c.nodeType === 3 && c.textContent?.trim())) return node;\n const kids = Array.from(node.children).filter((c) => visible(c, view));\n const next = side === \"after\" ? kids[0] : kids[kids.length - 1];\n if (!next) return node;\n node = next;\n }\n}\n\n/** The first placement rule this tap button's surroundings break, or null. */\nexport function findTapPlacementWarning(el: HTMLElement): string | null {\n const doc = el.ownerDocument;\n const view = doc.defaultView;\n if (!view || !el.isConnected) return null;\n // A button inside a group is judged as its group.\n const slot: Element = el.closest(\".matrx-tap-group\") ?? el;\n const glass = isGlassItem(slot);\n\n if (glass && !floats(slot, view)) {\n return 'glass on a solid surface — glass only floats over moving content; use variant=\"transparent\" (or a solid group)';\n }\n\n const row = slot.parentElement;\n if (!row) return null;\n if (glass) {\n const mixed = Array.from(row.children).find((c) => c !== slot && visible(c, view) && !isGlassItem(c));\n if (mixed) return `glass beside non-glass ${describe(mixed)} — make the row all glass or none`;\n }\n\n const pill = (el.querySelector(\":scope > .matrx-tap-pill\") as HTMLElement | null) ?? (slot.querySelector(\".matrx-tap-group-capsule\") as HTMLElement | null);\n if (!pill) return null;\n const gap = px(view.getComputedStyle(el).getPropertyValue(\"--matrx-tap-gap\")) || 6;\n const p = pill.getBoundingClientRect();\n if (p.width === 0) return null;\n // Distances are judged in LAYOUT pixels: inside a zoomed (transformed) tile a screen distance\n // is the layout distance times the scale.\n const scale = layoutScale(pill);\n for (const [side, sib] of [[\"after\", slot.nextElementSibling], [\"before\", slot.previousElementSibling]] as const) {\n if (!sib || !visible(sib, view) || isTapSlot(sib, view) || isGlassItem(sib) || facesWithTapSlot(sib, side, view)) continue;\n if (Math.abs(sib.getBoundingClientRect().top + sib.getBoundingClientRect().height / 2 - (p.top + p.height / 2)) > p.height) continue; // not on this row\n const box = facingBox(sib, side, view);\n const r = box.getBoundingClientRect();\n const cs = view.getComputedStyle(box);\n const distance =\n (side === \"after\" ? r.left - p.right : p.left - r.right) / scale + (side === \"after\" ? px(cs.paddingLeft) : px(cs.paddingRight));\n if (distance < gap - 0.5) {\n return `${describe(sib)} sits ${Math.round(distance)}px from the pill — anything beside a tap button adds its own ${gap / 2}px (the box only carries ${gap / 2}px)`;\n }\n }\n return null;\n}\n\nconst reported = new Set<string>();\n\nfunction report(el: HTMLElement, reason: string) {\n el.setAttribute(\"data-matrx-tap-violation\", reason);\n const key = `${reason}@${el.getAttribute(\"aria-label\") ?? el.textContent ?? \"\"}`;\n if (reported.has(key)) return;\n reported.add(key);\n console.error(`[tap-target] ${reason}`, el);\n}\n\nconst mounted = new Set<HTMLElement>();\nlet resizeTimer: ReturnType<typeof setTimeout> | null = null;\nlet listening = false;\n\nfunction check(node: HTMLElement) {\n const reason = findTapViolation(node);\n if (reason) {\n report(node, reason);\n return;\n }\n node.removeAttribute(\"data-matrx-tap-violation\");\n const warning = findTapPlacementWarning(node);\n if (warning) {\n node.setAttribute(\"data-matrx-tap-warning\", warning);\n const key = `w:${warning}@${node.getAttribute(\"aria-label\") ?? \"\"}`;\n if (!reported.has(key)) {\n reported.add(key);\n console.error(`[tap-target] ${warning}`, node);\n }\n } else node.removeAttribute(\"data-matrx-tap-warning\");\n}\n\nfunction listenForResize(view: Window) {\n if (listening) return;\n listening = true;\n view.addEventListener(\"resize\", () => {\n if (resizeTimer) clearTimeout(resizeTimer);\n resizeTimer = setTimeout(() => mounted.forEach((n) => (n.isConnected ? check(n) : mounted.delete(n))), 200);\n });\n // A button is judged once, at mount — but its neighbours keep changing (a\n // loading placeholder becomes the real control). Re-judge a button when the\n // row it sits in gains or loses children, so a mark never outlives the\n // neighbour it named (2026-10-13: \"New run\" kept a red outline for a\n // skeleton that had already left the header).\n const Observer = (view as Window & { MutationObserver?: typeof MutationObserver }).MutationObserver;\n if (!Observer || !view.document.body) return;\n const changedRows = new Set<Node>();\n let rowTimer: ReturnType<typeof setTimeout> | null = null;\n new Observer((records) => {\n for (const r of records) changedRows.add(r.target);\n if (rowTimer) clearTimeout(rowTimer);\n rowTimer = setTimeout(() => {\n mounted.forEach((n) => {\n if (!n.isConnected) return void mounted.delete(n);\n const row = (n.closest(\".matrx-tap-group\") ?? n).parentElement;\n if (row && changedRows.has(row)) check(n);\n });\n changedRows.clear();\n }, 200);\n }).observe(view.document.body, { childList: true, subtree: true });\n}\n\nfunction assignRef<T>(ref: Ref<T> | undefined, value: T | null) {\n if (typeof ref === \"function\") ref(value);\n else if (ref) (ref as MutableRefObject<T | null>).current = value;\n}\n\n/**\n * The callback ref every tap trigger carries. In production it only forwards\n * the caller's ref; in development it also measures the trigger once it is in\n * the layout and paints a violation.\n */\nexport function useTapGuardRef<T extends HTMLElement>(\n forwarded: Ref<T> | undefined,\n propViolation: string | null,\n): (node: T | null) => void {\n const current = useRef<T | null>(null);\n return useCallback(\n (node: T | null) => {\n assignRef(forwarded, node);\n if (current.current && current.current !== node) mounted.delete(current.current);\n current.current = node;\n if (!guardOn() || !node) return;\n if (propViolation) {\n report(node, propViolation);\n return;\n }\n const view = node.ownerDocument.defaultView;\n if (!view) return;\n mounted.add(node);\n listenForResize(view);\n view.requestAnimationFrame(() => check(node));\n },\n [forwarded, propViolation],\n );\n}\n\n/* ------------------------------------------------------------------ */\n/* THE PILL-INSET GUARD (0.60.10). A pill is balanced when its INK sits */\n/* the same distance from both edges. On 2026-10-04 every icon+label */\n/* pill read off-centre (1.3–3.3px) because padding was shaved on the */\n/* glyph side by a guess at the glyph's air. The trim in tap-target.css */\n/* now removes each glyph's real air; this measures the result in the */\n/* real layout and marks any pill whose ink insets differ by more than */\n/* 2px — dashed red outline + one console error naming both numbers. */\n/* ------------------------------------------------------------------ */\n\nconst PILL_TOLERANCE_PX = 2;\nconst PILL_ITEMS = \"button, a[href], [role='button'], [role='tab'], [role='radio'], [role='menuitem']\";\nconst PILL_CANDIDATES = \"button, a[href], [role='button'], .rounded-full, .matrx-tap-pill-inline, .matrx-tap-pill-mobile-icon-only\";\n\n/** Horizontal ink extents inside `el`: glyph geometry for svgs, text runs for text. */\nfunction inkExtents(el: Element): { left: number; right: number } | null {\n const doc = el.ownerDocument;\n const view = doc.defaultView;\n if (!view) return null;\n let left = Infinity;\n let right = -Infinity;\n const walker = doc.createTreeWalker(el, 0x1 | 0x4 /* SHOW_ELEMENT | SHOW_TEXT */);\n let n: Node | null;\n while ((n = walker.nextNode())) {\n if (n.nodeType === 1) {\n const node = n as Element;\n const cs = view.getComputedStyle(node);\n if (cs.display === \"none\" || cs.visibility === \"hidden\" || cs.position === \"absolute\") continue;\n const tag = node.tagName.toLowerCase();\n if (tag === \"img\" || tag === \"picture\" || tag === \"video\" || tag === \"canvas\") {\n // A picture (a favicon, an avatar) is ink by its box — it draws its own pixels, and a logo\n // renders exactly as it is, never tinted to make a guard see it (2026-10-13: every\n // favicon-led link pill read \"29px left vs 10px right\" because the image was invisible here).\n const r = node.getBoundingClientRect();\n if (r.width > 0) {\n left = Math.min(left, r.left);\n right = Math.max(right, r.right);\n }\n continue;\n }\n if (tag !== \"svg\" && (node.getAttribute(\"role\") === \"status\" || node.getAttribute(\"role\") === \"progressbar\")) {\n // A busy spinner drawn with borders (its rings are absolute, so nothing below sees them)\n // is ink by its box: a pill whose icon turned into a spinner read \"44px left vs 20px right\".\n const r = node.getBoundingClientRect();\n if (r.width > 0) {\n left = Math.min(left, r.left);\n right = Math.max(right, r.right);\n }\n continue;\n }\n if (tag !== \"svg\") {\n // A painted chip inside the pill (a count badge) is ink by its box: its fill is what the eye sees.\n const paintedChip = (cs.backgroundColor !== \"rgba(0, 0, 0, 0)\" && cs.backgroundColor !== \"transparent\") || parseFloat(cs.borderLeftWidth) > 0;\n if (paintedChip) {\n const r = node.getBoundingClientRect();\n if (r.width > 0) {\n left = Math.min(left, r.left);\n right = Math.max(right, r.right);\n }\n }\n continue;\n }\n const svg = node as SVGGraphicsElement;\n if (typeof svg.getBBox !== \"function\" || typeof svg.getScreenCTM !== \"function\") continue;\n const bb = svg.getBBox();\n const ctm = svg.getScreenCTM();\n if (!ctm || bb.width === 0) continue;\n if (Math.abs(ctm.b) > 0.001 || Math.abs(ctm.c) > 0.001) {\n // A turning glyph (a busy spinner) has no fixed ink: judge it by its layout box, centered\n // where the rotation centers it — never by a mid-turn snapshot of its paths.\n const r = node.getBoundingClientRect();\n const half = (parseFloat(cs.width) || r.width) / 2;\n const mid = r.left + r.width / 2;\n left = Math.min(left, mid - half);\n right = Math.max(right, mid + half);\n continue;\n }\n const half = ((parseFloat(cs.strokeWidth) || 0) * Math.abs(ctm.a)) / 2;\n const x1 = ctm.a * bb.x + ctm.e;\n const x2 = ctm.a * (bb.x + bb.width) + ctm.e;\n left = Math.min(left, Math.min(x1, x2) - half);\n right = Math.max(right, Math.max(x1, x2) + half);\n } else if (n.nodeValue && n.nodeValue.trim()) {\n const parent = n.parentElement;\n if (!parent || parent.closest(\"svg\")) continue;\n const pcs = view.getComputedStyle(parent);\n if (pcs.visibility === \"hidden\" || pcs.position === \"absolute\") continue;\n const range = doc.createRange();\n range.selectNodeContents(n);\n // A truncated label (`truncate max-w-*`) draws only what its clipping box shows: its text\n // run keeps going past the ellipsis, so the run is clipped to every overflow-hiding box\n // between it and the pill (2026-10-18: a scope chip \"matrx-frontend (LCP test)\" read\n // \"9.0px left vs 5.7px right\" while its ellipsis sat exactly 9px from the edge).\n const clip = textClip(parent, el, view);\n for (const r of Array.from(range.getClientRects())) {\n if (r.width <= 0) continue;\n const rl = Math.max(r.left, clip.left);\n const rr = Math.min(r.right, clip.right);\n if (rr <= rl) continue;\n left = Math.min(left, rl);\n right = Math.max(right, rr);\n }\n }\n }\n return Number.isFinite(left) && Number.isFinite(right) ? { left, right } : null;\n}\n\n/** The horizontal window a text run can paint in: its overflow-clipping ancestors up to (excluding) `pill`. */\nfunction textClip(from: Element, pill: Element, view: Window): { left: number; right: number } {\n let left = -Infinity;\n let right = Infinity;\n for (let node: Element | null = from; node && node !== pill; node = node.parentElement) {\n const cs = view.getComputedStyle(node);\n // overflow-x, or the shorthand's first (x) value where a runtime does not expand it (jsdom)\n const clipsX = (cs.overflowX && cs.overflowX !== \"visible\") || (cs.overflow && !cs.overflow.startsWith(\"visible\"));\n if (clipsX) {\n const r = node.getBoundingClientRect();\n if (r.width > 0) {\n left = Math.max(left, r.left);\n right = Math.min(right, r.right);\n }\n }\n }\n return { left, right };\n}\n\nconst FIELDS = \"input, textarea, select, [contenteditable='true'], [role='textbox'], [role='searchbox'], [role='combobox']\";\n\n/**\n * Only a BUTTON can be a pill whose ink must balance: an interactive element,\n * or the painted pill inside one (a tap button's `.matrx-tap-pill-inline`).\n * A field — or a capsule that holds one, like a rounded search box — aligns its\n * text to an edge by design, and a non-interactive container (a status chip, a\n * wrapper painted `rounded-full`) is never a pill button (2026-10-09: the\n * messenger's search field and messaging's AI chips wore the red outline).\n */\nexport function isPillButton(el: Element): boolean {\n if (el.matches(FIELDS) || el.querySelector(FIELDS) !== null) return false;\n if (el.matches(PILL_ITEMS)) return true;\n if (el.parentElement?.closest(PILL_ITEMS)) return true;\n return el.querySelector(PILL_ITEMS) !== null;\n}\n\n/** Why this pill's ink is off-centre, or null. Only judges a pill — a capsule\n * (radius ≥ half its height) with its own fill or border, carrying ink. */\nexport function findPillInsetWarning(el: HTMLElement): string | null {\n const view = el.ownerDocument.defaultView;\n if (!view || !el.isConnected) return null;\n if (!isPillButton(el)) return null;\n const box = el.getBoundingClientRect();\n const scale = layoutScale(el);\n if (box.width / scale < 20 || box.height / scale < 16 || box.height / scale > 48) return null;\n const cs = view.getComputedStyle(el);\n if (parseFloat(cs.borderTopLeftRadius) < box.height / scale / 2 - 1) return null;\n const painted = cs.backgroundColor !== \"rgba(0, 0, 0, 0)\" && cs.backgroundColor !== \"transparent\";\n if (!painted && !(parseFloat(cs.borderLeftWidth) > 0)) return null;\n // A wide capsule (a stretched select or field) aligns content to an edge on purpose.\n if (box.width / scale > 320) return null;\n // Ink balance is a question only for CENTERED content. A select trigger (value left, chevron\n // right), a field, or a full-width action row that says justify-start aligns its content on\n // purpose — content alignment is placement, not an inset to balance.\n if (cs.display.includes(\"flex\") && ![\"center\", \"normal\"].includes(cs.justifyContent)) return null;\n if (el.matches(\"[data-matrx-control='select'], [data-matrx-control='field']\")) return null;\n // A switch, checkbox or slider carries STATE, not a label: its thumb sits at one end by design\n // (measured 2026-10-04: every connector switch read \"18px left vs 2px right\" in the chat composer).\n if (el.matches(\"[role='switch'], [role='checkbox'], [role='slider'], [role='radio']\")) return null;\n // A TRACK of several controls (a segmented nav, a tab strip) is a container, not a pill: its\n // items sit where the selection puts them, so the ink is lopsided by design — each item is\n // judged on its own (measured 2026-10-05: the shell route nav's icon track read 2px vs 12.5px\n // at 768 because the selected item's fill hugs one end and the last glyph carries its air).\n if (el.querySelectorAll(PILL_ITEMS).length > 1) return null;\n const ink = inkExtents(el);\n if (!ink) return null;\n const left = (ink.left - box.left) / scale;\n const right = (box.right - ink.right) / scale;\n if (left < 0 || right < 0) return null; // clipped / overflowing content: not this guard's question\n if (Math.abs(left - right) <= PILL_TOLERANCE_PX) return null;\n return `pill ink is off-centre: ${left.toFixed(1)}px left vs ${right.toFixed(1)}px right — pad both sides alike and let the glyph trim (tap-target.css, THE OPTICAL GLYPH TRIM) remove the glyph's air; never shave one side by hand`;\n}\n\nlet pillTimer: ReturnType<typeof setTimeout> | null = null;\nlet pillObserver: MutationObserver | null = null;\n\nfunction scanPills(doc: Document) {\n if (!guardOn()) return;\n for (const node of Array.from(doc.querySelectorAll<HTMLElement>(PILL_CANDIDATES))) {\n // A tap button's own pill is judged, not its invisible box.\n if (node.classList.contains(\"matrx-tap-target\")) continue;\n const warning = findPillInsetWarning(node);\n if (warning) {\n if (node.getAttribute(\"data-matrx-pill-inset-warning\") === warning) continue;\n node.setAttribute(\"data-matrx-pill-inset-warning\", warning);\n const key = `p:${warning}@${(node.textContent ?? \"\").trim().slice(0, 40)}`;\n if (!reported.has(key)) {\n reported.add(key);\n console.error(`[tap-target] ${warning}`, node);\n }\n } else if (node.hasAttribute(\"data-matrx-pill-inset-warning\")) {\n node.removeAttribute(\"data-matrx-pill-inset-warning\");\n }\n }\n}\n\nfunction startPillInsetScan() {\n if (pillObserver || typeof document === \"undefined\" || typeof MutationObserver === \"undefined\") return;\n const doc = document;\n const schedule = () => {\n if (pillTimer) clearTimeout(pillTimer);\n pillTimer = setTimeout(() => scanPills(doc), 600);\n };\n pillObserver = new MutationObserver((records) => {\n // Our own attribute writes must not re-trigger the scan.\n if (records.every((r) => r.type === \"attributes\" && r.attributeName === \"data-matrx-pill-inset-warning\")) return;\n schedule();\n });\n const begin = () => {\n pillObserver?.observe(doc.body, { childList: true, subtree: true, characterData: true, attributes: true, attributeFilter: [\"class\", \"style\", \"data-matrx-pill-inset-warning\"] });\n schedule();\n };\n if (doc.body) begin();\n else doc.addEventListener(\"DOMContentLoaded\", begin, { once: true });\n}\n","// THE LAYOUT SCALE (0.62.4). The dev guards (pill guard, tap-target guard) judge spacing, ink\n// balance and width in LAYOUT pixels — the numbers a stylesheet writes. `getBoundingClientRect`\n// returns SCREEN pixels, so inside a CSS-transformed (zoomed) container — every Board tile at\n// overview zoom — a correct 11px gap read 5.3px at 0.48 and warned falsely. The effective scale\n// is the ratio of an element's drawn width to its layout width (`offsetWidth`, which ignores\n// transforms), taken from the nearest ancestor-or-self that has a box. 1 when no engine reports\n// layout (jsdom) or the ratio is within 2% of 1, so a real violation at scale 1 reads unchanged.\n\nexport function layoutScale(el: Element | null): number {\n for (let n: Element | null = el; n; n = n.parentElement) {\n const w = (n as HTMLElement).offsetWidth;\n if (!w) continue;\n const drawn = n.getBoundingClientRect().width;\n if (!(drawn > 0)) continue;\n const s = drawn / w;\n if (!Number.isFinite(s) || s <= 0) return 1;\n return Math.abs(s - 1) < 0.02 ? 1 : s;\n }\n return 1;\n}\n","\"use client\";\n\nimport { createContext, useContext, type ReactNode } from \"react\";\n\n/** The surface a tap group sits on. \"glass\" floats over moving content; \"solid\" is a page, card,\n * toast or a header row that is itself a solid band. */\nexport type TapSurfaceKind = \"glass\" | \"solid\";\n\n// Shared through a Symbol.for slot on globalThis (like the default-variant context): the `.` and\n// `./buttons` dist bundles each inline this module, and a provider rendered by one must reach\n// buttons rendered by the other.\nconst SLOT = Symbol.for(\"@ai-matrx/tap-target:surface\");\ntype GlobalWithSlot = typeof globalThis & { [SLOT]?: ReturnType<typeof createContext<TapSurfaceKind>> };\nconst TapSurfaceContext = ((globalThis as GlobalWithSlot)[SLOT] ??= createContext<TapSurfaceKind>(\"glass\"));\n\n/**\n * GLASS ONLY FLOATS, declared once by the surface. A host whose header (or any region) is a solid\n * row wraps it in `<TapSurface surface=\"solid\">`; every `TapTargetButtonGroup` /\n * `TapTargetSearchGroup` inside then renders solid by itself — no per-page `surface=\"solid\"`.\n * A group's own `surface` prop still wins.\n */\nexport function TapSurface({ surface, children }: { surface: TapSurfaceKind; children: ReactNode }) {\n return <TapSurfaceContext.Provider value={surface}>{children}</TapSurfaceContext.Provider>;\n}\n\n/** The group's surface: its explicit prop, else the nearest `<TapSurface>`, else glass. */\nexport function useTapSurface(explicit: TapSurfaceKind | undefined): TapSurfaceKind {\n const inherited = useContext(TapSurfaceContext);\n return explicit ?? inherited;\n}\n","\"use client\";\n\n// THE BUILT-IN CAPABILITIES of every tap button — each one an enum or a flag,\n// never a class a caller writes. Rendering and geometry live in tap-target.css\n// (`.matrx-tap-badge`, `.matrx-tap-pressed`, `.matrx-tap-chevron`, …).\n\nimport { useEffect, type ReactNode } from \"react\";\n\nimport { MOTION_SPIN } from \"../motion\";\nimport { formatTapShortcut, parseShortcut, type TapShortcut } from \"../tap-shortcut\";\n\n/** Glyph color. Replaces the free-form `className`. */\nexport type TapTone = \"default\" | \"muted\" | \"primary\" | \"destructive\" | \"success\" | \"warning\" | \"info\";\n\n/** Fill of a solid button. Replaces `bgColor` / `iconColor` / hover / active. */\nexport type TapSolidTone = \"primary\" | \"destructive\" | \"success\" | \"warning\" | \"neutral\";\n\nexport const TAP_TONE_CLASS: Record<TapTone, string> = {\n default: \"text-foreground\",\n muted: \"text-muted-foreground group-hover/tap:text-foreground\",\n primary: \"text-primary-ink\",\n destructive: \"text-destructive-ink\",\n success: \"text-success-ink\",\n warning: \"text-warning-ink\",\n info: \"text-info-ink\",\n};\n\nexport const TAP_SOLID_TONE: Record<TapSolidTone, { fill: string; glyph: string }> = {\n primary: { fill: \"bg-primary group-hover/tap:bg-primary/85\", glyph: \"text-primary-foreground\" },\n destructive: { fill: \"bg-danger-fill group-hover/tap:bg-danger-fill/85\", glyph: \"text-danger-fill-foreground\" },\n success: { fill: \"bg-success-fill group-hover/tap:bg-success-fill/85\", glyph: \"text-success-fill-foreground\" },\n warning: { fill: \"bg-warning group-hover/tap:bg-warning/85\", glyph: \"text-warning-foreground\" },\n neutral: { fill: \"bg-foreground group-hover/tap:bg-foreground/85\", glyph: \"text-background\" },\n};\n\n/**\n * A keyboard shortcut: modifiers joined by \"+\", then one key —\n * \"mod+k\" (⌘ on Apple, Ctrl elsewhere), \"shift+mod+p\", \"alt+n\", \"/\", \"?\".\n */\nexport { formatTapShortcut, parseShortcut, type TapShortcut };\n\nexport interface TapFeatureProps {\n /** Glyph color, from the system's list. */\n tone?: TapTone | undefined;\n /** A count (99+ past 99) or a dot, drawn on the pill's corner by the system. */\n badge?: number | \"dot\" | undefined;\n /** A toggle that is on (sidebar open, filter on): tinted pill + aria-pressed. */\n pressed?: boolean | undefined;\n /** Work in flight: the glyph becomes a spinner and presses are ignored. */\n loading?: boolean | undefined;\n /** Why the button cannot be used — disables it and becomes its tooltip. */\n disabledReason?: string | undefined;\n /** Keyboard shortcut that presses the button; shown in its tooltip. */\n shortcut?: TapShortcut | undefined;\n /** A menu trigger: a small chevron after the label. */\n chevron?: boolean | undefined;\n}\n\nfunction isTyping(target: EventTarget | null): boolean {\n const el = target as HTMLElement | null;\n return !!el && (el.isContentEditable || /^(INPUT|TEXTAREA|SELECT)$/.test(el.tagName));\n}\n\nexport function matchesTapShortcut(e: KeyboardEvent, shortcut: TapShortcut): boolean {\n const p = parseShortcut(shortcut);\n if ((e.metaKey || e.ctrlKey) !== p.mod || e.altKey !== p.alt) return false;\n // \"?\" and other shifted symbols arrive with shiftKey set — only compare\n // shift for letters and named keys.\n if (/^[a-z0-9]$|^[a-z]{2,}$/.test(p.key) && e.shiftKey !== p.shift) return false;\n if (!p.mod && isTyping(e.target)) return false;\n return e.key.toLowerCase() === p.key;\n}\n\n/** Presses `node` when its shortcut is typed anywhere on the page. */\nexport function useTapShortcut(shortcut: TapShortcut | undefined, getNode: () => HTMLElement | null, enabled: boolean) {\n useEffect(() => {\n if (!shortcut || !enabled) return;\n const onKey = (e: KeyboardEvent) => {\n if (!matchesTapShortcut(e, shortcut)) return;\n const node = getNode();\n if (!node || !node.isConnected) return;\n e.preventDefault();\n node.click();\n };\n window.addEventListener(\"keydown\", onKey);\n return () => window.removeEventListener(\"keydown\", onKey);\n }, [shortcut, enabled, getNode]);\n}\n\nexport function TapBadge({ badge }: { badge: number | \"dot\" }) {\n if (badge === \"dot\") return <span aria-hidden=\"true\" className=\"matrx-tap-badge\" data-dot=\"\" />;\n if (badge <= 0) return null;\n return (\n <span aria-hidden=\"true\" className=\"matrx-tap-badge\">\n {badge > 99 ? \"99+\" : badge}\n </span>\n );\n}\n\nexport function TapSpinner({ className }: { className: string }) {\n return (\n <svg className={className} fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={2} aria-hidden=\"true\">\n <circle\n className={MOTION_SPIN}\n cx=\"12\"\n cy=\"12\"\n r=\"9\"\n strokeDasharray=\"28.27\"\n strokeDashoffset=\"9\"\n strokeLinecap=\"round\"\n style={{ transformOrigin: \"12px 12px\" }}\n />\n </svg>\n );\n}\n\nexport function TapChevron() {\n return (\n <svg\n className=\"matrx-tap-chevron\"\n aria-hidden=\"true\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n strokeWidth={2}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <path d=\"m6 9 6 6 6-6\" />\n </svg>\n );\n}\n\n/** Tooltip body: the label, then the shortcut as a key cap. */\nexport function tooltipBody(label: string, shortcut: TapShortcut | undefined): ReactNode {\n if (!shortcut) return label;\n return (\n <span className=\"matrx-tap-tooltip\">\n {label}\n <kbd className=\"matrx-tap-kbd\">{formatTapShortcut(shortcut)}</kbd>\n </span>\n );\n}\n","// src/tap-shortcut.ts — @ai-matrx/design-system/tap-shortcut\n//\n// THE ONE SHORTCUT FORMATTER, light (FB5, 2026-10-23). `formatTapShortcut` (\"mod+k\" → \"⌘K\" on Apple, \"Ctrl+K\"\n// elsewhere) is pure; it lived in tap-target's \"use client\" feature module, so a plain helper that only needed the\n// words (records-ui's table action list) had to import the whole tap-target entry and was itself stamped\n// \"use client\". This entry carries the parse and the words only — no React. `./tap-target` re-exports both.\n\n/** A keyboard shortcut, written \"mod+k\", \"shift+?\", \"alt+enter\". */\nexport type TapShortcut = string;\n\nexport interface ParsedShortcut {\n mod: boolean;\n shift: boolean;\n alt: boolean;\n key: string;\n}\n\nconst IS_APPLE =\n typeof navigator !== \"undefined\" && /Mac|iPhone|iPad|iPod/.test(navigator.platform || navigator.userAgent);\n\nexport function parseShortcut(shortcut: TapShortcut): ParsedShortcut {\n const parts = shortcut.toLowerCase().split(\"+\");\n const key = parts.pop() ?? \"\";\n return { mod: parts.includes(\"mod\"), shift: parts.includes(\"shift\"), alt: parts.includes(\"alt\"), key };\n}\n\n/** \"mod+k\" → \"⌘K\" on Apple, \"Ctrl+K\" elsewhere. */\nexport function formatTapShortcut(shortcut: TapShortcut): string {\n const p = parseShortcut(shortcut);\n const key = p.key.length === 1 ? p.key.toUpperCase() : p.key[0]!.toUpperCase() + p.key.slice(1);\n if (IS_APPLE) return `${p.alt ? \"⌥\" : \"\"}${p.shift ? \"⇧\" : \"\"}${p.mod ? \"⌘\" : \"\"}${key}`;\n return [p.mod && \"Ctrl\", p.alt && \"Alt\", p.shift && \"Shift\", key].filter(Boolean).join(\"+\");\n}\n","import type { ComponentType, ReactNode, Ref } from \"react\";\n\n/**\n * The injectable link seam — the package's replacement for the original\n * hard `next/link` import.\n *\n * Internal hrefs (anything NOT matching `http(s):`, `mailto:`, `tel:`) render\n * through the link component resolved here; external hrefs always render a\n * plain `<a target=\"_blank\" rel=\"noopener noreferrer\">`, exactly like the\n * original. When nothing is registered and no per-instance `linkComponent`\n * prop is given, internal hrefs fall back to a plain `<a>` (no prefetch, no\n * client-side routing — still a working link).\n */\nexport interface TapTargetLinkProps {\n href: string;\n target?: \"_blank\" | \"_self\" | \"_parent\" | \"_top\" | undefined;\n rel?: string | undefined;\n /** Router prefetch hint (next/link semantics). Plain `<a>` fallback ignores it. */\n prefetch?: boolean | null | undefined;\n \"aria-label\"?: string | undefined;\n /** Tooltip text drawn through `title` (the provider's title takeover). */\n title?: string | undefined;\n className?: string | undefined;\n children?: ReactNode;\n /** The trigger's ref (the development guard measures the rendered link).\n * next/link forwards it to its `<a>`. */\n ref?: Ref<HTMLAnchorElement> | undefined;\n}\n\nexport type TapTargetLinkComponent = ComponentType<TapTargetLinkProps>;\n\n/**\n * The registered component lives in a `Symbol.for` slot on `globalThis` — NOT\n * in module state — so it survives the module graph being instantiated more\n * than once: the `.` and `./buttons` dist bundles each inline the primitives\n * (tsup `splitting: false`), and a consumer may even mix `import` and\n * `require`. One registration must reach every copy.\n */\nconst LINK_SLOT = Symbol.for(\"@ai-matrx/tap-target:link-component\");\n\ntype GlobalWithLinkSlot = typeof globalThis & {\n [LINK_SLOT]?: TapTargetLinkComponent | null;\n};\n\n/**\n * Register the app's link component once at startup (e.g. `next/link`):\n *\n * ```tsx\n * import Link from \"next/link\";\n * import { setTapTargetLinkComponent } from \"@ai-matrx/tap-target\";\n * setTapTargetLinkComponent(Link);\n * ```\n *\n * Pass `null` to unregister (plain `<a>` fallback resumes).\n */\nexport function setTapTargetLinkComponent(\n component: TapTargetLinkComponent | null,\n): void {\n (globalThis as GlobalWithLinkSlot)[LINK_SLOT] = component;\n}\n\n/** The currently registered link component, or `null` when none is set. */\nexport function getTapTargetLinkComponent(): TapTargetLinkComponent | null {\n return (globalThis as GlobalWithLinkSlot)[LINK_SLOT] ?? null;\n}\n","\"use client\";\n\nimport { forwardRef, type Ref } from \"react\";\n// The spinner loop comes from `@ai-matrx/design-system`'s motion layer — the\n// package this one already depends on — NOT from core Tailwind's\n// `animate-spin` and NOT from a keyframe copied into this package's\n// stylesheet. See the note above `LoadingTapButton`.\nimport { MOTION_SPIN } from \"../motion\";\nimport {\n TapTargetButton,\n TapTargetButtonTransparent,\n TapTargetButtonOutline,\n TapTargetButtonSolid,\n TapTargetButtonForGroup,\n} from \"./tap-target-button\";\nimport type { TapTargetLinkComponent } from \"./link\";\nimport { useTapButtonVariant } from \"./tap-default-variant\";\nimport type { TapFeatureProps, TapSolidTone } from \"./tap-features\";\n\n// ---------------------------------------------------------------------------\n// Shared types\n// ---------------------------------------------------------------------------\n\ntype Variant = \"glass\" | \"transparent\" | \"outline\" | \"solid\" | \"group\";\n\nexport interface TapButtonProps extends TapFeatureProps {\n /** Forwarded to the underlying button (Radix `asChild`, focus chains, etc.). */\n ref?: Ref<HTMLButtonElement> | undefined;\n variant?: Variant | undefined;\n onClick?: (() => void) | undefined;\n as?: \"button\" | \"label\" | undefined;\n htmlFor?: string | undefined;\n ariaLabel?: string | undefined;\n disabled?: boolean | undefined;\n tabIndex?: number | undefined;\n className?: string | undefined;\n strokeWidth?: number | undefined;\n // Solid-variant color overrides — only used when variant=\"solid\"\n bgColor?: string | undefined;\n iconColor?: string | undefined;\n hoverBgColor?: string | undefined;\n activeBgColor?: string | undefined;\n // Link support — when set, the button renders as a link or <a>.\n // Internal hrefs use the injected link component (setTapTargetLinkComponent\n // or the `linkComponent` prop; plain <a> when none is registered); external\n // (http(s)://, mailto:, tel:) use <a> with target=\"_blank\" +\n // rel=\"noopener noreferrer\" by default. Pass an explicit `target` to\n // override (works for internal links too).\n href?: string | undefined;\n target?: \"_blank\" | \"_self\" | \"_parent\" | \"_top\" | undefined;\n rel?: string | undefined;\n prefetch?: boolean | null | undefined;\n /** Per-instance link component override for internal hrefs. */\n linkComponent?: TapTargetLinkComponent | undefined;\n // Tooltip support — defaults to `ariaLabel`. Pass `false` to opt out.\n tooltip?: string | false | undefined;\n tooltipSide?: \"top\" | \"right\" | \"bottom\" | \"left\" | undefined;\n tooltipAlign?: \"start\" | \"center\" | \"end\" | undefined;\n /** Inline caption after the icon — see TapTargetButton `label`. */\n label?: string | undefined;\n /** Passthrough from AITapButtonProps / MakerTapButton — stripped before DOM. */\n colored?: boolean | undefined;\n}\n\n// ---------------------------------------------------------------------------\n// Variant resolver — maps a variant string to the correct wrapper component.\n// Runs at build/server time so there's zero client cost.\n//\n// IMPORTANT: `Wrap` MUST forward refs. The pre-composed `*TapButton` functions\n// below are plain function components (in React 19 ref is a regular prop) and\n// spread `{...props}` to `Wrap` — that spread carries ref through. `Wrap`\n// extracts ref and passes it explicitly to the underlying `forwardRef`\n// primitive. Without this, every `*TapButton` placed inside a Radix\n// `*Trigger asChild` (DropdownMenu, Popover, Tooltip, etc.) silently loses\n// the ref — the popper can't anchor and Radix's injected event handlers /\n// `data-state` / `aria-*` get dropped. (Precedent: matrx-frontend\n// `features/files/FEATURE.md`, where this pattern was established.)\n// ---------------------------------------------------------------------------\n\nconst Wrap = forwardRef<\n HTMLButtonElement,\n TapButtonProps & { children: React.ReactNode }\n>(function Wrap(\n {\n variant: variantProp,\n children,\n bgColor,\n iconColor,\n hoverBgColor,\n activeBgColor,\n // AITapButtonProps passthrough — not a DOM attribute (see ai-tap-buttons Wrap)\n colored: _colored,\n ...props\n },\n ref,\n) {\n const variant = useTapButtonVariant(variantProp);\n switch (variant) {\n case \"transparent\":\n return (\n <TapTargetButtonTransparent ref={ref} {...props}>\n {children}\n </TapTargetButtonTransparent>\n );\n case \"outline\":\n return (\n <TapTargetButtonOutline ref={ref} {...props}>\n {children}\n </TapTargetButtonOutline>\n );\n case \"solid\": {\n // On a solid button `tone` is the FILL; a glyph-only tone (\"muted\",\n // \"default\", \"info\") has no fill meaning and falls back to primary.\n const { tone, ...solidProps } = props;\n const fill: TapSolidTone | undefined =\n tone === \"primary\" || tone === \"destructive\" || tone === \"success\" || tone === \"warning\" ? tone : undefined;\n return (\n <TapTargetButtonSolid\n ref={ref}\n tone={fill}\n bgColor={bgColor}\n iconColor={iconColor}\n hoverBgColor={hoverBgColor}\n activeBgColor={activeBgColor}\n {...solidProps}\n >\n {children}\n </TapTargetButtonSolid>\n );\n }\n case \"group\":\n return (\n <TapTargetButtonForGroup ref={ref} {...props}>\n {children}\n </TapTargetButtonForGroup>\n );\n default:\n return (\n <TapTargetButton ref={ref} {...props}>\n {children}\n </TapTargetButton>\n );\n }\n});\n\n// ---------------------------------------------------------------------------\n// Pre-composed buttons — one import, one tag, zero configuration needed.\n// Default variant is \"glass\". Override with variant=\"transparent\" etc.\n// All SVG paths match lucide-react v0.577.0 exactly.\n// ---------------------------------------------------------------------------\n\n// lucide: menu (hand-crafted HeroIcons path — no Lucide equivalent, kept as-is)\nexport function MenuTapButton(props: TapButtonProps) {\n return (\n <Wrap ariaLabel=\"Menu\" strokeWidth={1.75} {...props}>\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n d=\"M3.75 6.75h16.5M3.75 12h16.5m-16.5 5.25h16.5\"\n />\n </Wrap>\n );\n}\n\n// lucide: plus (hand-crafted — no drift, kept as-is)\nexport function PlusTapButton(props: TapButtonProps) {\n return (\n <Wrap ariaLabel=\"Add\" {...props}>\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n d=\"M12 4.5v15m7.5-7.5h-15\"\n />\n </Wrap>\n );\n}\n\n// lucide: search → circle cx=11 cy=11 r=8 + line to 21,21\nexport function SearchTapButton(props: TapButtonProps) {\n return (\n <Wrap ariaLabel=\"Search\" {...props}>\n <circle cx=\"11\" cy=\"11\" r=\"8\" />\n <path d=\"m21 21-4.34-4.34\" />\n </Wrap>\n );\n}\n\n// lucide: settings (hand-crafted — kept as-is, Lucide uses \"settings-2\" pattern)\nexport function SettingsTapButton(props: TapButtonProps) {\n return (\n <Wrap ariaLabel=\"Settings\" {...props}>\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n d=\"M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z\"\n />\n </Wrap>\n );\n}\n\n// lucide: maximize (hand-crafted corner-arrows — kept as-is)\nexport function MaximizeTapButton(props: TapButtonProps) {\n return (\n <Wrap ariaLabel=\"Fullscreen\" {...props}>\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n d=\"M3.75 3.75v4.5m0-4.5h4.5m-4.5 0L9 9M3.75 20.25v-4.5m0 4.5h4.5m-4.5 0L9 15M20.25 3.75h-4.5m4.5 0v4.5m0-4.5L15 9m5.25 11.25h-4.5m4.5 0v-4.5m0 4.5L15 15\"\n />\n </Wrap>\n );\n}\n\n// lucide: home v0.577.0 — used as the \"Hub\" (main/list) action\nexport function HomeTapButton(props: TapButtonProps) {\n return (\n <Wrap ariaLabel=\"Hub\" {...props}>\n <path d=\"M15 21v-8a1 1 0 0 0-1-1h-4a1 1 0 0 0-1 1v8\" />\n <path d=\"M3 10a2 2 0 0 1 .709-1.528l7-5.999a2 2 0 0 1 2.582 0l7 5.999A2 2 0 0 1 21 10v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z\" />\n </Wrap>\n );\n}\n\n// lucide: layout-grid v0.577.0\nexport function LayoutGridTapButton(props: TapButtonProps) {\n return (\n <Wrap ariaLabel=\"Card view\" {...props}>\n <rect width=\"7\" height=\"7\" x=\"3\" y=\"3\" rx=\"1\" />\n <rect width=\"7\" height=\"7\" x=\"14\" y=\"3\" rx=\"1\" />\n <rect width=\"7\" height=\"7\" x=\"14\" y=\"14\" rx=\"1\" />\n <rect width=\"7\" height=\"7\" x=\"3\" y=\"14\" rx=\"1\" />\n </Wrap>\n );\n}\n\n// lucide: list v0.577.0\nexport function ListTapButton(props: TapButtonProps) {\n return (\n <Wrap ariaLabel=\"Table view\" {...props}>\n <path d=\"M3 5h.01\" />\n <path d=\"M3 12h.01\" />\n <path d=\"M3 19h.01\" />\n <path d=\"M8 5h13\" />\n <path d=\"M8 12h13\" />\n <path d=\"M8 19h13\" />\n </Wrap>\n );\n}\n\n// lucide: arrow-down-up (hand-crafted — kept as-is)\nexport function ArrowDownUpTapButton(props: TapButtonProps) {\n return (\n <Wrap ariaLabel=\"Sort\" {...props}>\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n d=\"M3 4.5h14.25M3 9h9.75M3 13.5h5.25m5.25-.75L17.25 9m0 0L21 12.75M17.25 9v10.5\"\n />\n </Wrap>\n );\n}\n\n// lucide: bell v0.577.0\nexport function BellTapButton(props: TapButtonProps) {\n return (\n <Wrap ariaLabel=\"Notifications\" {...props}>\n <path d=\"M10.268 21a2 2 0 0 0 3.464 0\" />\n <path d=\"M3.262 15.326A1 1 0 0 0 4 17h16a1 1 0 0 0 .74-1.673C19.41 13.956 18 12.499 18 8A6 6 0 0 0 6 8c0 4.499-1.411 5.956-2.738 7.326\" />\n </Wrap>\n );\n}\n\n// lucide: bell-ring v0.577.0 — animated cousin of bell, used for \"has unread\"\nexport function BellRingTapButton(props: TapButtonProps) {\n return (\n <Wrap ariaLabel=\"Notifications\" {...props}>\n <path d=\"M10.268 21a2 2 0 0 0 3.464 0\" />\n <path d=\"M22 8c0-2.3-.8-4.3-2-6\" />\n <path d=\"M3.262 15.326A1 1 0 0 0 4 17h16a1 1 0 0 0 .74-1.673C19.41 13.956 18 12.499 18 8A6 6 0 0 0 6 8c0 4.499-1.411 5.956-2.738 7.326\" />\n <path d=\"M4 2C2.8 3.7 2 5.7 2 8\" />\n </Wrap>\n );\n}\n\n// lucide: zap v0.577.0 — lightning bolt, used as the Quick Actions trigger\nexport function ZapTapButton(props: TapButtonProps) {\n return (\n <Wrap ariaLabel=\"Quick actions\" {...props}>\n <path d=\"M4 14a1 1 0 0 1-.78-1.63l9.9-10.2a.5.5 0 0 1 .86.46l-1.92 6.02A1 1 0 0 0 13 10h7a1 1 0 0 1 .78 1.63l-9.9 10.2a.5.5 0 0 1-.86-.46l1.92-6.02A1 1 0 0 0 11 14z\" />\n </Wrap>\n );\n}\n\n// lucide: upload v0.577.0\nexport function UploadTapButton(props: TapButtonProps) {\n return (\n <Wrap ariaLabel=\"Upload\" {...props}>\n <path d=\"M12 3v12\" />\n <path d=\"m17 8-5-5-5 5\" />\n <path d=\"M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4\" />\n </Wrap>\n );\n}\n\n// lucide: download v0.577.0\nexport function DownloadTapButton(props: TapButtonProps) {\n return (\n <Wrap ariaLabel=\"Download\" {...props}>\n <path d=\"M12 15V3\" />\n <path d=\"M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4\" />\n <path d=\"m7 10 5 5 5-5\" />\n </Wrap>\n );\n}\n\n// lucide: share-2 v0.577.0\nexport function ShareTapButton(props: TapButtonProps) {\n return (\n <Wrap ariaLabel=\"Share\" {...props}>\n <circle cx=\"18\" cy=\"5\" r=\"3\" />\n <circle cx=\"6\" cy=\"12\" r=\"3\" />\n <circle cx=\"18\" cy=\"19\" r=\"3\" />\n <line x1=\"8.59\" x2=\"15.42\" y1=\"13.51\" y2=\"17.49\" />\n <line x1=\"15.41\" x2=\"8.59\" y1=\"6.51\" y2=\"10.49\" />\n </Wrap>\n );\n}\n\n// lucide: undo v0.577.0\nexport function UndoTapButton(props: TapButtonProps) {\n return (\n <Wrap ariaLabel=\"Undo\" {...props}>\n <path d=\"M3 7v6h6\" />\n <path d=\"M21 17a9 9 0 0 0-9-9 9 9 0 0 0-6 2.3L3 13\" />\n </Wrap>\n );\n}\n\n// lucide: redo v0.577.0\nexport function RedoTapButton(props: TapButtonProps) {\n return (\n <Wrap ariaLabel=\"Redo\" {...props}>\n <path d=\"M21 7v6h-6\" />\n <path d=\"M3 17a9 9 0 0 1 9-9 9 9 0 0 1 6 2.3l3 2.7\" />\n </Wrap>\n );\n}\n\n// lucide: copy v0.577.0\nexport function CopyTapButton(props: TapButtonProps) {\n return (\n <Wrap ariaLabel=\"Copy\" {...props}>\n <rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\" />\n <path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\" />\n </Wrap>\n );\n}\n\n// lucide: trash v0.577.0\nexport function TrashTapButton(props: TapButtonProps) {\n return (\n <Wrap ariaLabel=\"Delete\" {...props}>\n <path d=\"M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6\" />\n <path d=\"M3 6h18\" />\n <path d=\"M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2\" />\n </Wrap>\n );\n}\n\n// lucide: files v0.577.0\nexport function FilesTapButton(props: TapButtonProps) {\n return (\n <Wrap ariaLabel=\"Copy all\" {...props}>\n <path d=\"M20 7h-3a2 2 0 0 1-2-2V2\" />\n <path d=\"M9 18a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h7l4 4v10a2 2 0 0 1-2 2Z\" />\n <path d=\"M3 7.6v12.8A1.6 1.6 0 0 0 4.6 22h9.8\" />\n </Wrap>\n );\n}\n\n// lucide: chevron-left v0.577.0 — arms extended from 6 to 7 (45° kept) for a\n// slightly larger glyph that better fills the 32px inner pill.\nexport function ChevronLeftTapButton(props: TapButtonProps) {\n return (\n <Wrap ariaLabel=\"Back\" {...props}>\n <path d=\"m16 19-7-7 7-7\" />\n </Wrap>\n );\n}\n\n// lucide: chevron-right v0.577.0\nexport function ChevronRightTapButton(props: TapButtonProps) {\n return (\n <Wrap ariaLabel=\"Next\" {...props}>\n <path d=\"m9 18 6-6-6-6\" />\n </Wrap>\n );\n}\n\n// lucide: panel-left v0.577.0\nexport function PanelLeftTapButton(props: TapButtonProps) {\n return (\n <Wrap ariaLabel=\"Toggle sidebar\" {...props}>\n <rect width=\"18\" height=\"18\" x=\"3\" y=\"3\" rx=\"2\" />\n <path d=\"M9 3v18\" />\n </Wrap>\n );\n}\n\n// lucide: panel-right v0.577.0\nexport function PanelRightTapButton(props: TapButtonProps) {\n return (\n <Wrap ariaLabel=\"Toggle sidebar\" {...props}>\n <rect width=\"18\" height=\"18\" x=\"3\" y=\"3\" rx=\"2\" />\n <path d=\"M15 3v18\" />\n </Wrap>\n );\n}\n\n// lucide: square-pen v0.577.0\nexport function SquarePenTapButton(props: TapButtonProps) {\n return (\n <Wrap ariaLabel=\"New chat\" {...props}>\n <path d=\"M12 3H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7\" />\n <path d=\"M18.375 2.625a1 1 0 0 1 3 3l-9.013 9.014a2 2 0 0 1-.853.505l-2.873.84a.5.5 0 0 1-.62-.62l.84-2.873a2 2 0 0 1 .506-.852z\" />\n </Wrap>\n );\n}\n\n// lucide: x v0.577.0\nexport function XTapButton(props: TapButtonProps) {\n return (\n <Wrap ariaLabel=\"Close\" {...props}>\n <path d=\"M18 6 6 18\" />\n <path d=\"m6 6 12 12\" />\n </Wrap>\n );\n}\n\n// lucide: funnel v0.577.0 (filter is an alias for funnel in this version)\nexport function FilterTapButton(props: TapButtonProps) {\n return (\n <Wrap ariaLabel=\"Filter\" {...props}>\n <path d=\"M10 20a1 1 0 0 0 .553.895l2 1A1 1 0 0 0 14 21v-7a2 2 0 0 1 .517-1.341L21.74 4.67A1 1 0 0 0 21 3H3a1 1 0 0 0-.742 1.67l7.225 7.989A2 2 0 0 1 10 14z\" />\n </Wrap>\n );\n}\n\n// lucide: play v0.577.0\nexport function PlayTapButton(props: TapButtonProps) {\n return (\n <Wrap ariaLabel=\"Play\" {...props}>\n <path d=\"M5 5a2 2 0 0 1 3.008-1.728l11.997 6.998a2 2 0 0 1 .003 3.458l-12 7A2 2 0 0 1 5 19z\" />\n </Wrap>\n );\n}\n\n// lucide: pause v0.577.0 — two rects (redesigned from bar paths)\nexport function PauseTapButton(props: TapButtonProps) {\n return (\n <Wrap ariaLabel=\"Pause\" {...props}>\n <rect x=\"14\" y=\"3\" width=\"5\" height=\"18\" rx=\"1\" />\n <rect x=\"5\" y=\"3\" width=\"5\" height=\"18\" rx=\"1\" />\n </Wrap>\n );\n}\n\n// lucide: square v0.577.0 (stop uses filled square)\nexport function StopTapButton(props: TapButtonProps) {\n return (\n <Wrap ariaLabel=\"Stop\" {...props}>\n <rect width=\"18\" height=\"18\" x=\"3\" y=\"3\" rx=\"2\" />\n </Wrap>\n );\n}\n\n// lucide: volume-2 v0.577.0\nexport function Volume2TapButton(props: TapButtonProps) {\n return (\n <Wrap ariaLabel=\"Speaker\" {...props}>\n <path d=\"M11 4.702a.705.705 0 0 0-1.203-.498L6.413 7.587A1.4 1.4 0 0 1 5.416 8H3a1 1 0 0 0-1 1v6a1 1 0 0 0 1 1h2.416a1.4 1.4 0 0 1 .997.413l3.383 3.384A.705.705 0 0 0 11 19.298z\" />\n <path d=\"M16 9a5 5 0 0 1 0 6\" />\n <path d=\"M19.364 18.364a9 9 0 0 0 0-12.728\" />\n </Wrap>\n );\n}\n\n// lucide: arrow-up v0.577.0\nexport function ArrowUpTapButton(props: TapButtonProps) {\n return (\n <Wrap ariaLabel=\"Send\" {...props}>\n <path d=\"m5 12 7-7 7 7\" />\n <path d=\"M12 19V5\" />\n </Wrap>\n );\n}\n\n// lucide: mic v0.577.0\nexport function MicTapButton(props: TapButtonProps) {\n return (\n <Wrap ariaLabel=\"Start recording\" {...props}>\n <path d=\"M12 19v3\" />\n <path d=\"M19 10v2a7 7 0 0 1-14 0v-2\" />\n <rect x=\"9\" y=\"2\" width=\"6\" height=\"13\" rx=\"3\" />\n </Wrap>\n );\n}\n\n// lucide: mic-off v0.577.0\nexport function MicOffTapButton(props: TapButtonProps) {\n return (\n <Wrap ariaLabel=\"Stop recording\" {...props}>\n <path d=\"M12 19v3\" />\n <path d=\"M15 9.34V5a3 3 0 0 0-5.68-1.33\" />\n <path d=\"M16.95 16.95A7 7 0 0 1 5 12v-2\" />\n <path d=\"M18.89 13.23A7 7 0 0 0 19 12v-2\" />\n <path d=\"m2 2 20 20\" />\n <path d=\"M9 9v3a3 3 0 0 0 5.12 2.12\" />\n </Wrap>\n );\n}\n\n// lucide: triangle-alert v0.577.0\nexport function TriangleAlertTapButton(props: TapButtonProps) {\n return (\n <Wrap ariaLabel=\"Alert\" {...props}>\n <path d=\"m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3\" />\n <path d=\"M12 9v4\" />\n <path d=\"M12 17h.01\" />\n </Wrap>\n );\n}\n\n// lucide: shield-check (context set)\nexport function ShieldCheckTapButton(props: TapButtonProps) {\n return (\n <Wrap ariaLabel=\"Context set\" {...props}>\n <path d=\"M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z\" />\n <path d=\"m9 12 2 2 4-4\" />\n </Wrap>\n );\n}\n\n// lucide: shield-alert (context unset)\nexport function ShieldAlertTapButton(props: TapButtonProps) {\n return (\n <Wrap ariaLabel=\"No context\" {...props}>\n <path d=\"M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z\" />\n <path d=\"M12 8v4\" />\n <path d=\"M12 16h.01\" />\n </Wrap>\n );\n}\n\n// lucide: bug v0.577.0 (major update — full insect anatomy)\nexport function BugTapButton(props: TapButtonProps) {\n return (\n <Wrap ariaLabel=\"Debug\" {...props}>\n <path d=\"M12 20v-9\" />\n <path d=\"M14 7a4 4 0 0 1 4 4v3a6 6 0 0 1-12 0v-3a4 4 0 0 1 4-4z\" />\n <path d=\"M14.12 3.88 16 2\" />\n <path d=\"M21 21a4 4 0 0 0-3.81-4\" />\n <path d=\"M21 5a4 4 0 0 1-3.55 3.97\" />\n <path d=\"M22 13h-4\" />\n <path d=\"M3 21a4 4 0 0 1 3.81-4\" />\n <path d=\"M3 5a4 4 0 0 0 3.55 3.97\" />\n <path d=\"M6 13H2\" />\n <path d=\"m8 2 1.88 1.88\" />\n <path d=\"M9 7.13V6a3 3 0 1 1 6 0v1.13\" />\n </Wrap>\n );\n}\n\n// lucide: settings-2 v0.577.0 (gear + center circle — kept as-is, matches intent)\nexport function Settings2TapButton(props: TapButtonProps) {\n return (\n <Wrap ariaLabel=\"Settings\" {...props}>\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n d=\"M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z\"\n />\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n d=\"M15 12a3 3 0 11-6 0 3 3 0 016 0z\"\n />\n </Wrap>\n );\n}\n\n// lucide: save (hand-crafted floppy disk — no direct Lucide equivalent, kept as-is)\nexport function SaveTapButton(props: TapButtonProps) {\n return (\n <Wrap ariaLabel=\"Save\" {...props}>\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n d=\"M4.5 6a2 2 0 012-2h9.25L20.5 9v9a2 2 0 01-2 2h-12a2 2 0 01-2-2V6z\"\n />\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n d=\"M8.5 4v4.5a.5.5 0 00.5.5h6a.5.5 0 00.5-.5V4\"\n />\n <rect\n x=\"8\"\n y=\"14\"\n width=\"8\"\n height=\"5.5\"\n rx=\"0.5\"\n strokeLinejoin=\"round\"\n />\n </Wrap>\n );\n}\n\n// lucide: send v0.577.0 (paper-airplane redesign)\nexport function SendTapButton(props: TapButtonProps) {\n return (\n <Wrap ariaLabel=\"Send\" {...props}>\n <path d=\"M14.536 21.686a.5.5 0 0 0 .937-.024l6.5-19a.496.496 0 0 0-.635-.635l-19 6.5a.5.5 0 0 0-.024.937l7.93 3.18a2 2 0 0 1 1.112 1.11z\" />\n <path d=\"m21.854 2.147-10.94 10.939\" />\n </Wrap>\n );\n}\n\n// lucide: message-square v0.577.0\nexport function MessageTapButton(props: TapButtonProps) {\n return (\n <Wrap ariaLabel=\"Message\" {...props}>\n <path d=\"M22 17a2 2 0 0 1-2 2H6.828a2 2 0 0 0-1.414.586l-2.202 2.202A.71.71 0 0 1 2 21.286V5a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2z\" />\n </Wrap>\n );\n}\n\n// lucide: variable v0.577.0 (major update — uses line elements + bracket paths)\nexport function VariableTapButton(props: TapButtonProps) {\n return (\n <Wrap ariaLabel=\"Variable\" {...props}>\n <path d=\"M8 21s-4-3-4-9 4-9 4-9\" />\n <path d=\"M16 3s4 3 4 9-4 9-4 9\" />\n <line x1=\"15\" x2=\"9\" y1=\"9\" y2=\"15\" />\n <line x1=\"9\" x2=\"15\" y1=\"9\" y2=\"15\" />\n </Wrap>\n );\n}\n\n// lucide: wrench v0.577.0 (single clean path)\nexport function WrenchTapButton(props: TapButtonProps) {\n return (\n <Wrap ariaLabel=\"Tool\" {...props}>\n <path d=\"M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.106-3.105c.32-.322.863-.22.983.218a6 6 0 0 1-8.259 7.057l-7.91 7.91a1 1 0 0 1-2.999-3l7.91-7.91a6 6 0 0 1 7.057-8.259c.438.12.54.662.219.984z\" />\n </Wrap>\n );\n}\n\n// lucide: command v0.577.0 (single continuous path)\nexport function CommandTapButton(props: TapButtonProps) {\n return (\n <Wrap ariaLabel=\"Command\" {...props}>\n <path d=\"M15 6v12a3 3 0 1 0 3-3H6a3 3 0 1 0 3 3V6a3 3 0 1 0-3 3h12a3 3 0 1 0-3-3\" />\n </Wrap>\n );\n}\n\n// lucide: terminal v0.577.0 (two paths: chevron + underline)\nexport function TerminalTapButton(props: TapButtonProps) {\n return (\n <Wrap ariaLabel=\"Terminal\" {...props}>\n <path d=\"M12 19h8\" />\n <path d=\"m4 17 6-6-6-6\" />\n </Wrap>\n );\n}\n\n// lucide: test-tube v0.577.0 (3 clean paths)\nexport function TestTubeTapButton(props: TapButtonProps) {\n return (\n <Wrap ariaLabel=\"Test\" {...props}>\n <path d=\"M14.5 2v17.5c0 1.4-1.1 2.5-2.5 2.5c-1.4 0-2.5-1.1-2.5-2.5V2\" />\n <path d=\"M8.5 2h7\" />\n <path d=\"M14.5 16h-5\" />\n </Wrap>\n );\n}\n\n// lucide: rotate-ccw v0.577.0 (same shape as history minus the clock hand — used for Reset)\nexport function ResetTapButton(props: TapButtonProps) {\n return (\n <Wrap ariaLabel=\"Reset\" {...props}>\n <path d=\"M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8\" />\n <path d=\"M3 3v5h5\" />\n </Wrap>\n );\n}\n\n// lucide: eraser v0.577.0 (major update — proper eraser shape)\nexport function ClearTapButton(props: TapButtonProps) {\n return (\n <Wrap ariaLabel=\"Clear\" {...props}>\n <path d=\"M21 21H8a2 2 0 0 1-1.42-.587l-3.994-3.999a2 2 0 0 1 0-2.828l10-10a2 2 0 0 1 2.829 0l5.999 6a2 2 0 0 1 0 2.828L12.834 21\" />\n <path d=\"m5.082 11.09 8.828 8.828\" />\n </Wrap>\n );\n}\n\n// lucide: refresh-cw v1.22.0 (dual arrows — was a broken hand-crafted Heroicons-style path)\nexport function RetryTapButton(props: TapButtonProps) {\n return (\n <Wrap ariaLabel=\"Retry\" {...props}>\n <path d=\"M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8\" />\n <path d=\"M21 3v5h-5\" />\n <path d=\"M21 12a9 9 0 0 1-9 9 9.75 9.75 0 0 1-6.74-2.74L3 16\" />\n <path d=\"M8 16H3v5\" />\n </Wrap>\n );\n}\n\n/** Alias — same Lucide refresh-cw glyph as RetryTapButton. */\nexport function RefreshCwTapButton(props: TapButtonProps) {\n return <RetryTapButton ariaLabel=\"Refresh\" {...props} />;\n}\n\n// lucide: loading spinner (custom animated — no Lucide equivalent)\n//\n// 🚨 `matrx-spin`, NEVER `animate-spin` (census row 19i, closed here at 0.2.1).\n// `animate-spin` is a core Tailwind utility, so it happened to survive in all\n// four current consumers — but a package cannot ship a class it does not\n// define: the first host without Tailwind's core animate utilities gets a\n// spinner that does not spin, which is a load-bearing lie (it says the work\n// has stopped) with no error to find it by. `matrx-spin` is design-system\n// 0.10.0's own keyframe + rule, shipped in ITS `styles.css` and asserted\n// present in ITS packed tarball. This package IMPORTS that contract (the\n// exported `MOTION_SPIN` constant, and `styles.css` `@import`s the sheet) —\n// it does not copy the keyframe, which would be a twin of exactly the kind\n// this row exists to kill. Under `prefers-reduced-motion` the shared rule\n// SLOWS the loop instead of stopping it, because a stopped spinner removes\n// information rather than motion.\nexport function LoadingTapButton(props: TapButtonProps) {\n return (\n <Wrap ariaLabel=\"Loading\" {...props}>\n <circle\n className={MOTION_SPIN}\n cx=\"12\"\n cy=\"12\"\n r=\"9\"\n strokeDasharray=\"28.27\"\n strokeDashoffset=\"9\"\n strokeLinecap=\"round\"\n style={{ transformOrigin: \"12px 12px\" }}\n />\n </Wrap>\n );\n}\n\n// lucide: bot/robot (hand-crafted — kept as-is)\nexport function RobotTapButton(props: TapButtonProps) {\n return (\n <Wrap ariaLabel=\"AI Agent\" {...props}>\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n d=\"M9 3.75H6.912a2.25 2.25 0 00-2.15 1.588L2.35 13.177a2.25 2.25 0 00-.1.661V18a2.25 2.25 0 002.25 2.25h15A2.25 2.25 0 0021.75 18v-4.162c0-.224-.034-.447-.1-.661L19.24 5.338a2.25 2.25 0 00-2.15-1.588H15M2.25 13.5h3.86a2.25 2.25 0 012.012 1.244l.256.512a2.25 2.25 0 002.013 1.244h3.218a2.25 2.25 0 002.013-1.244l.256-.512a2.25 2.25 0 012.013-1.244h3.859M12 3v8.25m0 0-3-3m3 3 3-3\"\n />\n </Wrap>\n );\n}\n\n// lucide: webhook v0.577.0\nexport function WebhookTapButton(props: TapButtonProps) {\n return (\n <Wrap ariaLabel=\"Webhook\" {...props}>\n <path d=\"M18 16.98h-5.99c-1.1 0-1.95.94-2.48 1.9A4 4 0 0 1 2 17c.01-.7.2-1.4.57-2\" />\n <path d=\"m6 17 3.13-5.78c.53-.97.1-2.18-.5-3.1a4 4 0 1 1 6.89-4.06\" />\n <path d=\"m12 6 3.13 5.73C15.66 12.7 16.9 13 18 13a4 4 0 0 1 0 8\" />\n </Wrap>\n );\n}\n\n// lucide: eye v0.577.0\nexport function ViewTapButton(props: TapButtonProps) {\n return (\n <Wrap ariaLabel=\"View\" {...props}>\n <path d=\"M2.062 12.348a1 1 0 0 1 0-.696 10.75 10.75 0 0 1 19.876 0 1 1 0 0 1 0 .696 10.75 10.75 0 0 1-19.876 0\" />\n <circle cx=\"12\" cy=\"12\" r=\"3\" />\n </Wrap>\n );\n}\n\n// lucide: hammer v0.577.0\nexport function BuildTapButton(props: TapButtonProps) {\n return (\n <Wrap ariaLabel=\"Build\" {...props}>\n <path d=\"m15 12-9.373 9.373a1 1 0 0 1-3.001-3L12 9\" />\n <path d=\"m18 15 4-4\" />\n <path d=\"m21.5 11.5-1.914-1.914A2 2 0 0 1 19 8.172v-.344a2 2 0 0 0-.586-1.414l-1.657-1.657A6 6 0 0 0 12.516 3H9l1.243 1.243A6 6 0 0 1 12 8.485V10l2 2h1.172a2 2 0 0 1 1.414.586L18.5 14.5\" />\n </Wrap>\n );\n}\n\n// lucide: play v0.577.0 (alias for Run context)\nexport function RunTapButton(props: TapButtonProps) {\n return (\n <Wrap ariaLabel=\"Run\" {...props}>\n <path d=\"M5 5a2 2 0 0 1 3.008-1.728l11.997 6.998a2 2 0 0 1 .003 3.458l-12 7A2 2 0 0 1 5 19z\" />\n </Wrap>\n );\n}\n\n// lucide: history v0.577.0\nexport function HistoryTapButton(props: TapButtonProps) {\n return (\n <Wrap ariaLabel=\"History\" {...props}>\n <path d=\"M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8\" />\n <path d=\"M3 3v5h5\" />\n <path d=\"M12 7v5l4 2\" />\n </Wrap>\n );\n}\n\n// lucide: paperclip v0.577.0\nexport function PaperclipTapButton(props: TapButtonProps) {\n return (\n <Wrap ariaLabel=\"Attach file\" {...props}>\n <path d=\"m16 6-8.414 8.586a2 2 0 0 0 2.829 2.829l8.414-8.586a4 4 0 1 0-5.657-5.657l-8.379 8.551a6 6 0 1 0 8.485 8.485l8.379-8.551\" />\n </Wrap>\n );\n}\n\n// lucide: thumbs-up v0.577.0\nexport function ThumbsUpTapButton(props: TapButtonProps) {\n return (\n <Wrap ariaLabel=\"Like\" {...props}>\n <path d=\"M7 10v12\" />\n <path d=\"M15 5.88 14 10h5.83a2 2 0 0 1 1.92 2.56l-2.33 8A2 2 0 0 1 17.5 22H4a2 2 0 0 1-2-2v-8a2 2 0 0 1 2-2h2.76a2 2 0 0 0 1.79-1.11L12 2a3.13 3.13 0 0 1 3 3.88Z\" />\n </Wrap>\n );\n}\n\n// lucide: thumbs-down v0.577.0\nexport function ThumbsDownTapButton(props: TapButtonProps) {\n return (\n <Wrap ariaLabel=\"Dislike\" {...props}>\n <path d=\"M17 14V2\" />\n <path d=\"M9 18.12 10 14H4.17a2 2 0 0 1-1.92-2.56l2.33-8A2 2 0 0 1 6.5 2H20a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2h-2.76a2 2 0 0 0-1.79 1.11L12 22a3.13 3.13 0 0 1-3-3.88Z\" />\n </Wrap>\n );\n}\n\n// lucide: check v0.577.0\nexport function CheckTapButton(props: TapButtonProps) {\n return (\n <Wrap ariaLabel=\"Done\" {...props}>\n <path d=\"M20 6 9 17l-5-5\" />\n </Wrap>\n );\n}\n\n// lucide: pencil v0.577.0\nexport function PencilTapButton(props: TapButtonProps) {\n return (\n <Wrap ariaLabel=\"Edit\" {...props}>\n <path d=\"M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z\" />\n <path d=\"m15 5 4 4\" />\n </Wrap>\n );\n}\n\n// lucide: ellipsis (more-horizontal) v0.577.0\nexport function MoreHorizontalTapButton(props: TapButtonProps) {\n return (\n <Wrap ariaLabel=\"More options\" {...props}>\n <circle cx=\"12\" cy=\"12\" r=\"1\" />\n <circle cx=\"19\" cy=\"12\" r=\"1\" />\n <circle cx=\"5\" cy=\"12\" r=\"1\" />\n </Wrap>\n );\n}\n\n// lucide: check-square v0.577.0\nexport function CheckSquareTapButton(props: TapButtonProps) {\n return (\n <Wrap ariaLabel=\"Task\" {...props}>\n <path d=\"m9 11 3 3L22 4\" />\n <path d=\"M21 12v7a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11\" />\n </Wrap>\n );\n}\n\n// lucide: ghost v0.577.0\nexport function GhostTapButton(props: TapButtonProps) {\n return (\n <Wrap ariaLabel=\"Incognito chat\" {...props}>\n <path d=\"M9 10h.01\" />\n <path d=\"M15 10h.01\" />\n <path d=\"M12 2a8 8 0 0 0-8 8v12l3-3 2.5 2.5L12 19l2.5 2.5L17 19l3 3V10a8 8 0 0 0-8-8z\" />\n </Wrap>\n );\n}\n\n// lucide: link (chain link — used for \"attach to task\") v0.577.0\nexport function LinkTapButton(props: TapButtonProps) {\n return (\n <Wrap ariaLabel=\"Attach\" {...props}>\n <path d=\"M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71\" />\n <path d=\"M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71\" />\n </Wrap>\n );\n}\n\n// lucide: external-link v0.577.0\nexport function ExternalLinkTapButton(props: TapButtonProps) {\n return (\n <Wrap ariaLabel=\"Open source\" {...props}>\n <path d=\"M15 3h6v6\" />\n <path d=\"M10 14 21 3\" />\n <path d=\"M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6\" />\n </Wrap>\n );\n}\n\n// lucide: clipboard-list v0.577.0\nexport function ClipboardListTapButton(props: TapButtonProps) {\n return (\n <Wrap ariaLabel=\"Copy Pages\" {...props}>\n <rect width=\"8\" height=\"4\" x=\"8\" y=\"2\" rx=\"1\" ry=\"1\" />\n <path d=\"M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2\" />\n <path d=\"M12 11h4\" />\n <path d=\"M12 16h4\" />\n <path d=\"M8 11h.01\" />\n <path d=\"M8 16h.01\" />\n </Wrap>\n );\n}\n\n// lucide: party-popper v0.577.0\nexport function PartyPopperTapButton(props: TapButtonProps) {\n return (\n <Wrap ariaLabel=\"AI Clean\" {...props}>\n <path d=\"M5.8 11.3 2 22l10.7-3.79\" />\n <path d=\"M4 3h.01\" />\n <path d=\"M22 8h.01\" />\n <path d=\"M15 2h.01\" />\n <path d=\"M22 20h.01\" />\n <path d=\"m22 2-2.24.75a2.9 2.9 0 0 0-1.96 3.12c.1.86-.57 1.63-1.45 1.63h-.38c-.86 0-1.6.6-1.76 1.44L14 10\" />\n <path d=\"m22 13-.82-.33c-.86-.34-1.82.2-1.98 1.11c-.11.7-.72 1.22-1.43 1.22H17\" />\n <path d=\"m11 2 .33.82c.34.86-.2 1.82-1.11 1.98C9.52 4.9 9 5.52 9 6.23V7\" />\n <path d=\"M11 13c1.93 1.93 2.83 4.17 2 5-.83.83-3.07-.07-5-2-1.93-1.93-2.83-4.17-2-5 .83-.83 3.07.07 5 2Z\" />\n </Wrap>\n );\n}\n\n// lucide: layers v0.577.0 — \"this PDF everywhere\" surface switcher\nexport function LayersTapButton(props: TapButtonProps) {\n return (\n <Wrap ariaLabel=\"Open this PDF in another surface\" {...props}>\n <path d=\"M12.83 2.18a2 2 0 0 0-1.66 0L2.6 6.08a1 1 0 0 0 0 1.83l8.58 3.91a2 2 0 0 0 1.66 0l8.58-3.9a1 1 0 0 0 0-1.83z\" />\n <path d=\"M2 12a1 1 0 0 0 .58.91l8.6 3.91a2 2 0 0 0 1.65 0l8.58-3.9A1 1 0 0 0 22 12\" />\n <path d=\"M2 17a1 1 0 0 0 .58.91l8.6 3.91a2 2 0 0 0 1.65 0l8.58-3.9A1 1 0 0 0 22 17\" />\n </Wrap>\n );\n}\n","\"use client\";\n\nimport { createContext, useContext, type ReactNode } from \"react\";\n\nimport { useTapSurface } from \"./tap-surface\";\n\n// THE PLACEMENT DEFAULT — which variant a tap button takes when its caller\n// names none. Outside a provider that is \"glass\" (the floating-bar look). A\n// host region that holds tap buttons BESIDE text (a route header's back +\n// title cell) wraps itself in <TapDefaultVariant value=\"transparent\"> so every\n// button in it matches its neighbours (rule 2, \"all glass or none\") without\n// each call site repeating variant=\"transparent\". An explicit `variant` prop\n// always wins, so a bar whose pieces are ALL glass stays glass.\n//\n// The context object lives in a `Symbol.for` slot on globalThis, like the link\n// seam: the `.` and `./buttons` dist bundles each inline this module, and a\n// provider rendered by one must reach buttons rendered by the other.\n\nexport type TapDefaultVariantValue = \"glass\" | \"transparent\";\n\nconst SLOT = Symbol.for(\"@ai-matrx/tap-target:default-variant\");\ntype GlobalWithSlot = typeof globalThis & {\n [SLOT]?: ReturnType<typeof createContext<TapDefaultVariantValue>>;\n};\n\nfunction ctx() {\n const g = globalThis as GlobalWithSlot;\n return (g[SLOT] ??= createContext<TapDefaultVariantValue>(\"glass\"));\n}\n\n/** The variant tap buttons below take when they name none. */\nexport function useTapDefaultVariant(): TapDefaultVariantValue {\n return useContext(ctx());\n}\n\n/** Set the default variant for every tap button below that names none. */\nexport function TapDefaultVariant({ value, children }: { value: TapDefaultVariantValue; children: ReactNode }) {\n const Context = ctx();\n return <Context.Provider value={value}>{children}</Context.Provider>;\n}\n\n/**\n * The variant a lone tap button draws: its explicit `variant`, else a region's\n * <TapDefaultVariant>, else — on a <TapSurface surface=\"solid\"> — \"transparent\"\n * (glass only floats), else glass. An explicit variant always wins.\n */\nexport function useTapButtonVariant<V extends string>(explicit: V | undefined): V | TapDefaultVariantValue {\n const placed = useTapDefaultVariant();\n const surface = useTapSurface(undefined);\n if (explicit !== undefined) return explicit;\n if (placed !== \"glass\") return placed;\n return surface === \"solid\" ? \"transparent\" : \"glass\";\n}\n","/**\n * A STAND-IN ANNOUNCES ITSELF (law 4). Where a design-system component has a working default for a\n * part the host is meant to supply (the writing box, the sandbox panel, how a scope is drawn), the\n * default says so: ONE console notice per stand-in naming what to pass, and a `data-*=\"unconfigured\"`\n * attribute on what it draws. The pattern is records-ui's `data-entity-ref-host=\"unconfigured\"` and\n * settings' `data-settings-host=\"unconfigured\"`.\n */\nconst announced = new Set<string>();\n\n/** Warn once per `key`, in words naming the field the host should pass. */\nexport function announceStandIn(key: string, message: string): void {\n if (announced.has(key)) return;\n announced.add(key);\n console.warn(`[design-system] ${message}`);\n}\n\n/** Test seam: forget every notice that was printed. */\nexport function _resetStandInNotices(): void {\n announced.clear();\n}\n\n/** The value every stand-in's data attribute carries. */\nexport const UNCONFIGURED = \"unconfigured\" as const;\n","/**\n * THE ONE FITTING RULE for ProInput and ProTextarea's controls (2026-10-15).\n *\n * A writing field's controls never take the room the text needs, and a control\n * that does not fit is never deleted — it moves inside \"…\". Until this module\n * each field had its own step-down rule: ProInput dropped its mic AND its \"…\"\n * outright below ~220px when it also had Clear + Send (voice, copy, clean-up and\n * read-aloud became unreachable), and on a phone a 110px field kept two letters\n * of text beside Clear and Send.\n *\n * The rule:\n * - REQUIRED controls always show: Send (the field's action) and \"…\" whenever\n * it holds anything.\n * - OPTIONAL controls show in priority order while the text keeps its floor;\n * the rest go inside \"…\". Folding runs from the lowest priority up: Expand,\n * then Clear, then the mic.\n * - There is no device chevron (Arman, 2026-10-16): the microphone choice is\n * a right-click / press-and-hold on the mic, and an \"Audio settings\" row in\n * \"…\" whenever \"…\" shows — so it never takes room here.\n * - A live recording always keeps its stop button inline (the caller forces it).\n *\n * Widths are the real rendered footprints per pointer and density (measured\n * 2026-10-15 on a fine pointer and a 375px phone), so a phone folds earlier\n * instead of being crushed.\n */\n\nexport type FoldableControl = \"mic\" | \"clear\" | \"expand\";\n\n/** How the mic shows: inline, inside \"…\", or not offered. */\nexport type MicFit = \"inline\" | \"folded\" | \"none\";\n\nexport interface ControlSizes {\n /** One tap box (Send, \"…\", Clear, Expand). */\n box: number;\n /** The mic button, its own 3px margins included. */\n mic: number;\n}\n\n/** 38px tap box; the mic is a 28px button plus its 3px margins. */\nexport const FINE_SIZES: ControlSizes = { box: 38, mic: 34 };\n/** Touch: the tap box keeps 38px of layout (the 44px hit area is invisible); the mic pads out. */\nexport const COARSE_SIZES: ControlSizes = { box: 38, mic: 46 };\n/** The dense field scope (`data-matrx-tap-dense`): a 24px pill in a 28px box. */\nexport const DENSE_SIZES: ControlSizes = { box: 28, mic: 28 };\n\nexport function controlSizes(opts: { coarse: boolean; dense: boolean }): ControlSizes {\n if (opts.dense) return DENSE_SIZES;\n return opts.coarse ? COARSE_SIZES : FINE_SIZES;\n}\n\n/** Below this field height the controls take the dense 28px size. */\nexport const DENSE_FIELD_MAX_HEIGHT_PX = 34;\n\nexport function isDenseField(fieldHeight: number): boolean {\n return fieldHeight > 0 && fieldHeight < DENSE_FIELD_MAX_HEIGHT_PX;\n}\n\n/**\n * The text's floor: half the field, never more than 140px and never less than\n * 48px (about five characters).\n */\nexport function minTextPx(fieldWidth: number): number {\n return Math.max(48, Math.min(140, Math.round(fieldWidth * 0.5)));\n}\n\nexport interface FitRequest {\n /** The field's measured width; 0 = not measured yet (first paint, jsdom) → everything that may be inline is. */\n fieldWidth: number;\n sizes: ControlSizes;\n /** Space the field always spends outside the controls: its left padding, a start icon, the text gap. */\n fixedPx?: number | undefined;\n /** The text floor; defaults to `minTextPx(fieldWidth)`. A reserved control row passes 0. */\n minText?: number | undefined;\n hasSubmit: boolean;\n /** The \"…\" menu has items of its own (copy, clean-up, read-aloud, agents…). */\n menuHasOwnItems: boolean;\n /** The field offers voice input. */\n mic: boolean;\n /** Clear is offered right now (the field has text). */\n clear: boolean;\n /** Expand is offered right now (the text overflows the box). */\n expand: boolean;\n}\n\nexport interface FitResult {\n mic: MicFit;\n clearInline: boolean;\n expandInline: boolean;\n /** Controls that live inside \"…\" because they did not fit. */\n folded: FoldableControl[];\n /** \"…\" shows: it has its own items or holds a folded control. */\n showMenu: boolean;\n /** Width every inline control takes together, px. */\n inlineWidth: number;\n}\n\nexport function fitFieldControls(req: FitRequest): FitResult {\n const { sizes } = req;\n const folded: FoldableControl[] = [];\n let mic: MicFit = req.mic ? \"inline\" : \"none\";\n let clearInline = req.clear;\n let expandInline = req.expand;\n\n const menuWillShow = () => req.menuHasOwnItems || folded.length > 0;\n const width = () =>\n (req.hasSubmit ? sizes.box : 0) +\n (menuWillShow() ? sizes.box : 0) +\n (mic === \"inline\" ? sizes.mic : 0) +\n (clearInline ? sizes.box : 0) +\n (expandInline ? sizes.box : 0);\n\n if (req.fieldWidth > 0) {\n const floor = req.minText ?? minTextPx(req.fieldWidth);\n const room = req.fieldWidth - (req.fixedPx ?? 0) - floor;\n const steps: Array<() => void> = [\n () => {\n if (expandInline) {\n expandInline = false;\n folded.push(\"expand\");\n }\n },\n () => {\n if (clearInline) {\n clearInline = false;\n folded.push(\"clear\");\n }\n },\n () => {\n if (mic === \"inline\") {\n mic = \"folded\";\n folded.push(\"mic\");\n }\n },\n ];\n for (const step of steps) {\n if (width() <= room) break;\n step();\n }\n }\n\n return {\n mic,\n clearInline,\n expandInline,\n folded,\n showMenu: menuWillShow(),\n inlineWidth: width(),\n };\n}\n","/**\n * WHERE PROTEXTAREA'S MIC + \"…\" CLUSTER SITS, and the rule that it never covers\n * text (the ProTextarea twin of `proInputReservedPadding.ts`, page-pass 2026-09-27).\n *\n * A textarea's lines run the full width, so the cluster cannot take a right\n * gutter; it sits in a bottom ROW the field reserves (`pb-11`) on every\n * pointer. Mic, \"…\" and the submit button share ONE flex row inset 4px from\n * the corner, so they sit as adjacent tap boxes — no hand-typed offset between\n * them (a 48px offset beside a 38px box left a 10px hole, 2026-10-05).\n */\nexport type ClusterRow = \"top\" | \"bottom\";\n\nexport interface ClusterPlacement {\n row: ClusterRow;\n /** Distance from the right edge, px (clears the submit button when they share a row). */\n rightPx: number;\n /** The rows the field reserves, per pointer kind. */\n reserved: { fine: ClusterRow[]; coarse: ClusterRow[] };\n /** The submit button's row and width, when there is one. */\n submit: { row: ClusterRow; widthPx: number } | null;\n /** The classes the cluster container adds. */\n className: string;\n}\n\n/** The tap box (`--matrx-tap-box`, 38px since 2026-10-01). */\nexport const SUBMIT_BUTTON_WIDTH_PX = 38;\n\n/** Where the cluster sits: a reserved row under the text, or inline at the end of the last line. */\nexport type ProTextareaControls = \"row\" | \"inline\";\n\n/** The tap pill's half-gap (`--matrx-tap-gap` / 2): a container edge is a neighbour (tap-target rule 4). */\nexport const TAP_HALF_GAP_PX = 3;\n\n/** One tap row plus the half-gap above and below it: the shortest an inline-controls box may be. */\nexport const INLINE_CONTROLS_MIN_HEIGHT_PX = SUBMIT_BUTTON_WIDTH_PX + 2 * TAP_HALF_GAP_PX;\n\n/**\n * The inline-controls text padding: centered on one tap row vertically (whatever\n * the host's line height — `1lh`), and a right gutter the measured cluster\n * width plus the half-gap, so text never runs under a control.\n */\nexport function inlineControlsFieldPadding(\n clusterWidthPx: number,\n /** The one-line height: 44px, or 34px for a dense (small-type) box. */\n minHeightPx: number = INLINE_CONTROLS_MIN_HEIGHT_PX,\n): {\n paddingTop: string;\n paddingBottom: string;\n paddingRight: string;\n} {\n const block = `calc((${minHeightPx}px - 1lh) / 2 - 1px)`;\n return {\n paddingTop: block,\n paddingBottom: block,\n paddingRight: `${clusterWidthPx + 2 * TAP_HALF_GAP_PX}px`,\n };\n}\n\nexport function proTextareaClusterPlacement(\n hasSubmit: boolean,\n controls: ProTextareaControls = \"row\",\n): ClusterPlacement {\n if (controls === \"inline\") {\n // Inset by the half-gap: a 38px box in a 44px-min box is dead-centre on\n // one line, and stays on the last line as the text grows.\n return {\n row: \"bottom\",\n rightPx: hasSubmit ? SUBMIT_BUTTON_WIDTH_PX + TAP_HALF_GAP_PX : TAP_HALF_GAP_PX,\n reserved: { fine: [\"bottom\"], coarse: [\"bottom\"] },\n submit: hasSubmit ? { row: \"bottom\", widthPx: SUBMIT_BUTTON_WIDTH_PX } : null,\n className: \"bottom-[3px] right-[3px]\",\n };\n }\n // One flex row inset 4px from the bottom-right corner: the hover part, then\n // the submit button. They are adjacent tap boxes in the SAME row, so the\n // cluster sits exactly one submit box (plus the inset) from the edge.\n return {\n row: \"bottom\",\n rightPx: hasSubmit ? SUBMIT_BUTTON_WIDTH_PX + 4 : 4,\n reserved: { fine: [\"bottom\"], coarse: [\"bottom\"] },\n submit: hasSubmit ? { row: \"bottom\", widthPx: SUBMIT_BUTTON_WIDTH_PX } : null,\n className: \"bottom-1 right-1\",\n };\n}\n\n/** Every way a placement lets the cluster cover text or the submit button. `[]` = sound. */\nexport function clusterPlacementProblems(p: ClusterPlacement): string[] {\n const problems: string[] = [];\n if (!p.reserved.fine.includes(p.row)) {\n problems.push(`on a fine pointer the ${p.row} row is not reserved, so the cluster covers text on hover`);\n }\n if (!p.reserved.coarse.includes(p.row)) {\n problems.push(`on a touch screen the ${p.row} row is not reserved, so the cluster covers text`);\n }\n if (p.submit && p.submit.row === p.row && p.rightPx < p.submit.widthPx) {\n problems.push(\"the cluster overlaps the submit button\");\n }\n return problems;\n}\n\n// What fits beside the text — and what moves inside \"…\" — is decided by THE\n// ONE FITTING RULE shared with ProInput: `proFieldControlFit.ts`.\n","\"use client\";\n\n/**\n * THE WRITING FIELD'S ADD-ON PORTS. `ProTextarea` / `ProInput` (this subpath) own the box: the\n * textarea/input, auto-grow, the control row, submit and Enter rules, the dictation handle, the\n * close-protection dialog. Everything that needs a recorder, a server, an agent or a menu engine\n * reaches the field through these ports, registered ONCE at the host root:\n *\n * <WritingFieldAddOnsProvider addOns={matrxWritingFieldAddOns}>…</WritingFieldAddOnsProvider>\n *\n * so design-system (layer 2) never imports chat, agents, rich-content, context-menu or a recorder.\n * A port the host did not register falls back to a stand-in that ANNOUNCES itself (law 4): one\n * console notice naming the port, and `data-writing-field-host=\"unconfigured\"` on the field.\n *\n * Hook ports (`useVoice`, `useFormatting`, `useOpenAudioSettings`) are called on every render, so\n * the registered object must be module-constant: the provider keeps the FIRST object it receives\n * and announces a swap instead of breaking hook order.\n *\n * One context for every bundle copy of this module (tsup inlines it into each entry), keyed like\n * `writing-box.tsx`.\n */\nimport * as React from \"react\";\nimport { announceStandIn } from \"../stand-in-notice\";\n\n/** Options the field hands its voice port — the same contract the app's `useMicField` takes. */\nexport interface WritingFieldVoiceOptions {\n /** Voice is on for this field (`enableVoice`). When false the port must stay inert. */\n enabled: boolean;\n instanceId?: string | undefined;\n label?: string | undefined;\n getValue: () => string;\n /** Write the next value through the field's own change path. */\n writeValue: (next: string) => boolean | void;\n appendTranscript?: boolean | undefined;\n join?: ((base: string, text: string) => string) | undefined;\n protect?: boolean | undefined;\n onRequestClose?: (() => void) | undefined;\n onTranscriptionComplete?: ((text: string) => void) | undefined;\n onTranscriptionError?: ((error: string) => void) | undefined;\n}\n\n/** What a voice port returns: recorder state plus the controls the field draws. */\nexport interface WritingFieldVoice {\n /** The browser exposes a microphone (device enumeration works). */\n microphone: boolean;\n /** A recorder is mounted on this route. */\n available: boolean;\n isRecording: boolean;\n isTranscribing: boolean;\n audioLevel: number;\n liveTranscript: string;\n handleVoiceClick: () => void | Promise<void>;\n startDictation: () => Promise<void>;\n stopDictation: () => void;\n requestClose: () => void;\n showProtectionDialog: boolean;\n setShowProtectionDialog: (open: boolean) => void;\n confirmClose: () => void;\n cancelClose: () => void;\n /** The port's own dialogs (troubleshooting), drawn beside the field. */\n dialogs?: React.ReactNode | undefined;\n}\n\nexport interface WritingFieldMicButtonProps {\n onMicClick: () => void;\n disabled?: boolean | undefined;\n isRecording?: boolean | undefined;\n isTranscribing?: boolean | undefined;\n audioLevel?: number | undefined;\n micAriaLabel?: string | undefined;\n tabIndex?: number | undefined;\n dense?: boolean | undefined;\n}\n\n/** The field as an add-on sees it. */\nexport interface WritingFieldApi {\n kind: \"textarea\" | \"input\";\n /** The value the host last rendered. */\n text: string;\n /** The live text (the DOM or the hosted editor), falling back to `text`. */\n getText: () => string;\n /** Write through the field's own change path; true when the field now holds `next`. */\n write: (next: string) => boolean;\n getSelection: () => { start: number; end: number };\n getElement: () => HTMLTextAreaElement | HTMLInputElement | null;\n /** The add-on props the caller passed (surfaceName, getApplicationScope, cleanup…), untouched. */\n addOnProps: Readonly<Record<string, unknown>>;\n showCopyButton: boolean;\n /** Show the brief \"Copied\" check on the \"…\" trigger (ProInput). */\n flashCopied: () => void;\n}\n\nexport interface WritingFieldMenuProps {\n field: WritingFieldApi;\n /** The field's own rows (Expand, Voice input, Audio settings, Clear) — place them in the list view. */\n ownRows: React.ReactNode;\n /** Rows the field adds after the add-on's list (text stats). */\n trailingRows: React.ReactNode;\n close: () => void;\n}\n\nexport interface WritingFieldContextMenuProps {\n field: WritingFieldApi;\n disabled?: boolean | undefined;\n children: React.ReactNode;\n}\n\nexport interface WritingFieldTextStats {\n Bar: React.ComponentType<{ text: string }>;\n MenuItems: React.ComponentType<{\n showStatsBar: boolean;\n onToggleStatsBar: () => void;\n onOpenStatsPanel: () => void;\n }>;\n Panel: React.ComponentType<{ text: string; onBack?: () => void; onClose?: () => void }>;\n}\n\nexport interface WritingFieldNotify {\n error: (message: string, options?: { description?: string }) => void;\n info: (message: string) => void;\n success: (message: string) => void;\n}\n\nexport interface WritingFieldAddOns {\n useVoice?: ((options: WritingFieldVoiceOptions) => WritingFieldVoice) | undefined;\n MicButton?: React.ComponentType<WritingFieldMicButtonProps> | undefined;\n useOpenAudioSettings?: (() => () => void) | undefined;\n /** Markdown chords + selection toolbar on a long-form box. */\n useFormatting?:\n | ((\n element: HTMLTextAreaElement | null,\n on: boolean,\n addOnProps: Readonly<Record<string, unknown>>,\n ) => void)\n | undefined;\n /** The \"…\" body (actions, agents, read-aloud). */\n Menu?: React.ComponentType<WritingFieldMenuProps> | undefined;\n /** Whether `Menu` has rows of its own for this field (so \"…\" shows). */\n menuHasItems?: ((field: Pick<WritingFieldApi, \"kind\" | \"addOnProps\" | \"showCopyButton\">) => boolean) | undefined;\n /** The right-click floor around the field. */\n ContextMenu?: React.ComponentType<WritingFieldContextMenuProps> | undefined;\n TextStats?: WritingFieldTextStats | undefined;\n notify?: WritingFieldNotify | undefined;\n /** Extra prop names the add-ons read (kept off the DOM element). */\n propNames?: readonly string[] | undefined;\n}\n\n/** Add-on prop names the field never spreads onto the DOM (the Matrx add-ons' props). */\nexport const ADD_ON_PROP_NAMES: readonly string[] = [\n \"surfaceName\",\n \"getApplicationScope\",\n \"sourceFeature\",\n \"surfaceContextItems\",\n \"enableBoundAgents\",\n \"enableContextMenu\",\n \"enableCleanup\",\n \"cleanupAgentId\",\n \"cleanupContextItems\",\n \"enableHelpWithThis\",\n \"helpMandateKey\",\n \"helpContextItems\",\n \"enableCustomAgent\",\n \"customAgentMandateKey\",\n \"customAgentContextItems\",\n \"uploadImage\",\n];\n\n/** Split a field's rest props into DOM props and add-on props. */\nexport function splitAddOnProps<T extends Record<string, unknown>>(\n props: T,\n extra: readonly string[] = [],\n): { dom: T; addOnProps: Record<string, unknown> } {\n const dom: Record<string, unknown> = {};\n const addOnProps: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(props)) {\n if (ADD_ON_PROP_NAMES.includes(key) || extra.includes(key)) addOnProps[key] = value;\n else dom[key] = value;\n }\n return { dom: dom as T, addOnProps };\n}\n\nconst KEY = Symbol.for(\"@ai-matrx/design-system/writing-field-add-ons\");\ntype Registry = Record<symbol, React.Context<WritingFieldAddOns | null> | undefined>;\nconst registry = globalThis as unknown as Registry;\nconst AddOnsContext: React.Context<WritingFieldAddOns | null> =\n registry[KEY] ?? (registry[KEY] = React.createContext<WritingFieldAddOns | null>(null));\n\n/** Mount once at the host's app root. The first `addOns` object is kept for the provider's life. */\nexport function WritingFieldAddOnsProvider({\n addOns,\n children,\n}: {\n addOns: WritingFieldAddOns;\n children: React.ReactNode;\n}) {\n const first = React.useRef(addOns);\n if (first.current !== addOns) {\n announceStandIn(\n \"writing-field-add-ons-swap\",\n \"WritingFieldAddOnsProvider received a different addOns object; the first one is kept (hook ports must be module-constant).\",\n );\n }\n return <AddOnsContext.Provider value={first.current}>{children}</AddOnsContext.Provider>;\n}\n\nconst EMPTY: WritingFieldAddOns = {};\n\n/** The registered add-ons (or none). */\nexport function useWritingFieldAddOns(): WritingFieldAddOns {\n return React.useContext(AddOnsContext) ?? EMPTY;\n}\n\n/** Announce a missing port once, in words naming what to register. */\nexport function announceMissingPort(port: string): void {\n announceStandIn(\n `writing-field:${port}`,\n `A writing field drew without its \"${port}\" add-on: the host did not register it in <WritingFieldAddOnsProvider addOns={{ ${port} }}>.`,\n );\n}\n\nconst INERT = () => undefined;\n\n/** The voice stand-in: no recorder, every control inert, announced when a field asks for voice. */\nexport function useStandInVoice(options: WritingFieldVoiceOptions): WritingFieldVoice {\n React.useEffect(() => {\n if (options.enabled) announceMissingPort(\"useVoice\");\n }, [options.enabled]);\n return {\n microphone: false,\n available: false,\n isRecording: false,\n isTranscribing: false,\n audioLevel: 0,\n liveTranscript: \"\",\n handleVoiceClick: INERT,\n startDictation: async () => undefined,\n stopDictation: INERT,\n requestClose: () => options.onRequestClose?.(),\n showProtectionDialog: false,\n setShowProtectionDialog: INERT,\n confirmClose: () => options.onRequestClose?.(),\n cancelClose: INERT,\n };\n}\n\n/** Notices with no host toast go to the console, announced once. */\nexport const STAND_IN_NOTIFY: WritingFieldNotify = {\n error: (message) => {\n announceMissingPort(\"notify\");\n console.error(`[writing-field] ${message}`);\n },\n info: (message) => {\n announceMissingPort(\"notify\");\n console.info(`[writing-field] ${message}`);\n },\n success: (message) => {\n announceMissingPort(\"notify\");\n console.info(`[writing-field] ${message}`);\n },\n};\n\nfunction useNoFormatting(): void {}\nfunction useNoAudioSettings(): () => void {\n return () => announceMissingPort(\"useOpenAudioSettings\");\n}\n\n/** The add-ons with every missing hook port filled by its stand-in (stable for a stable registry). */\nexport function resolveHookPorts(addOns: WritingFieldAddOns) {\n return {\n useVoice: addOns.useVoice ?? useStandInVoice,\n useFormatting: addOns.useFormatting ?? useNoFormatting,\n useOpenAudioSettings: addOns.useOpenAudioSettings ?? useNoAudioSettings,\n notify: addOns.notify ?? STAND_IN_NOTIFY,\n };\n}\n","\"use client\";\n\n/**\n * The settled surfaces that hold the one control (owner, 2026-10-02/03):\n * one surface level, ~36px hairline rows, 8px radius; the empty state; the\n * region-shaped skeleton; the three delete tiers; the one-feature promo banner.\n * Skins are locked in `controls.css` like the controls themselves.\n */\n\nimport { Slot } from \"@radix-ui/react-slot\";\nimport * as React from \"react\";\n\nimport { swallowClick } from \"../button\";\nimport { cn } from \"../cn\";\nimport { ConfirmDialog } from \"../confirm-dialog\";\nimport { ChevronRightIcon, Trash2Icon } from \"../icons\";\nimport { Skeleton } from \"../skeleton\";\nimport { Button, ControlRow, type ChipTone, type GlyphTone } from \"./controls\";\n\n/* ------------------------------------------------------------------ */\n/* Row groups */\n/* ------------------------------------------------------------------ */\n\nexport interface RowGroupProps extends Omit<React.HTMLAttributes<HTMLElement>, \"title\"> {\n /** 11px uppercase heading above the group. */\n title?: React.ReactNode;\n /** The danger-zone skin (delete tier 3). */\n danger?: boolean;\n}\n\n/** A bordered group of hairline rows — the one surface for grouped content. */\nexport function RowGroup({ title, danger, className, children, ...props }: RowGroupProps) {\n return (\n <section\n data-matrx-row-group=\"\"\n data-danger={danger ? \"\" : undefined}\n className={cn(\"matrx-control-group\", className)}\n {...props}\n >\n {title ? <h2 className=\"matrx-control-group-title\">{title}</h2> : null}\n <div className=\"matrx-control-group-body\">{children}</div>\n </section>\n );\n}\n\nexport interface SettingRowProps {\n label: React.ReactNode;\n /** One 12px line under the label. */\n line?: React.ReactNode;\n /** Ties the label to the control it describes. */\n htmlFor?: string;\n /** The row's controls, right-aligned on one line. */\n children?: React.ReactNode;\n className?: string;\n}\n\n/** One ~36px row: 13px label, optional 12px line, controls on the right. */\nexport function SettingRow({ label, line, htmlFor, children, className }: SettingRowProps) {\n return (\n <div data-matrx-setting-row=\"\" className={cn(\"matrx-control-setting-row\", className)}>\n <div className=\"matrx-control-setting-text\">\n {htmlFor ? (\n <label htmlFor={htmlFor} className=\"matrx-control-setting-label\">\n {label}\n </label>\n ) : (\n <div className=\"matrx-control-setting-label\">{label}</div>\n )}\n {line ? <div className=\"matrx-control-setting-line\">{line}</div> : null}\n </div>\n {children ? (\n <ControlRow nowrap data-matrx-row-actions=\"\">\n {children}\n </ControlRow>\n ) : null}\n </div>\n );\n}\n\n/* ------------------------------------------------------------------ */\n/* Tile — the pressable row / tile (a choice, a destination) */\n/* ------------------------------------------------------------------ */\n\nexport type TileLayout = \"row\" | \"stack\" | \"adaptive\" | \"icon\";\n\nexport interface TileProps extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, \"title\"> {\n /** `row` (default): glyph, then a 13px title over a 12px line, start-aligned, full width — a\n * choice in a list, a quick action. `stack`: glyph on top, title and line under it — a grid\n * tile. `adaptive`: `stack` from the `sm` breakpoint (640px) up, a compact `row` below it — a\n * grid of option cards that becomes a list on a phone. `icon`: the launcher tile of an icon\n * grid (a \"Can make\" grid, a sidebar's pinned apps, a copy palette) — the glyph centered over\n * an 11px label centered under it, up to two lines, no frame, a pick is a soft tint, `end`\n * is a badge on the top corner, `line` is hidden. All are taller than a control: they carry\n * text, so they never take the 28px lock. */\n layout?: TileLayout;\n /** `outline` (default): the bordered card skin. `quiet`: no frame until hover — a row in a\n * menu-like list. */\n variant?: \"outline\" | \"quiet\";\n /** Leading 16px glyph (an avatar or image works too). */\n icon?: React.ReactNode;\n /** The 13px title. */\n title: React.ReactNode;\n /** The title wraps over several lines (up to 6) instead of one line with an ellipsis: a quiz\n * answer, a step, a sentence-long choice. Off by default — a short title is one line. */\n wrapTitle?: boolean;\n /** One 12px secondary line (clamped to two lines; one with `oneLine`). */\n line?: React.ReactNode;\n /** The `line` stays ONE line with an ellipsis, so every row of a master list keeps one height. */\n oneLine?: boolean;\n /** Trailing content in a row (a chevron, a count, a shortcut). */\n end?: React.ReactNode;\n /** A choice: `true` tints it and sets `aria-pressed`; `false` sets `aria-pressed=\"false\"`. A link tile (`asChild`) never sets `aria-pressed`: the caller sets `aria-current`. */\n selected?: boolean;\n /** How `selected` looks. `outline` (default): primary frame and tint. `fill`: a soft neutral fill,\n * no outline, ink unchanged — a sidebar's active row. `primary`: the solid primary fill with\n * every ink (title, line, glyph, end) on primary — the open item of a master list. */\n selectedStyle?: \"outline\" | \"fill\" | \"primary\";\n /** The hover / focus tooltip (the native `title` attribute: `title` is the visible label). */\n tooltip?: string;\n /** Nesting depth under a parent row: each level moves the row's start past one glyph and its\n * gap, so an icon-less child's title starts where its parent's title does. */\n level?: 1 | 2 | 3;\n /** Size to the content and never shrink or truncate the title — a code, a short value. */\n fit?: boolean;\n /** Keep room at the row's end for a control laid OVER it (a row's More button): `control`\n * reserves one control's width plus its gap, so the title never runs under it. */\n endInset?: \"control\";\n /** A dashed border: the \"add another\" tile (an empty slot to fill), never a choice. */\n dashed?: boolean;\n /** hoverStyle=\"fill\": the pointer's soft neutral fill (the desktop look's secondary fill) instead of the accent. */\n hoverStyle?: \"fill\";\n /** A destructive row (Remove, Delete): destructive title and glyph, destructive hover tint. */\n danger?: boolean;\n /**\n * A choice that is ALREADY USED elsewhere (an option already placed, a field already mapped): a\n * faint shade and quieter ink, still fully pressable — a hint for the eye, never a disabled state.\n */\n dimmed?: boolean;\n /** The glyph's own status ink when its color carries meaning (Button's `glyphTone`). */\n glyphTone?: GlyphTone;\n /** The inviting choice card for a front door: roomy padding, a 40px icon square, a 14px title. */\n hero?: boolean;\n /** Tint card, edge and icon square from one `ChipTone` (the `Chip` hue tokens). */\n tone?: ChipTone;\n /** Tint ONLY the icon, as a 28px colored square, on a neutral card: a grid of actions where each\n * job keeps its own hue (quick actions) without every card turning into a colored card. */\n iconTone?: ChipTone;\n /** A 28px navigation / filter row for sidebars and dense lists: `min-height` is the control size,\n * padding 4px 8px, gap 8px, 13px title. The `line` is HIDDEN when dense (one line, always).\n * `variant=\"quiet\"` + `dense` is a clean nav row: transparent until hover / selected. */\n dense?: boolean;\n /** Render the one child element (a link) with the tile's skin; its children are ignored —\n * the tile draws `icon`/`title`/`line`/`end`. */\n asChild?: boolean;\n}\n\n/**\n * THE pressable row / tile: two named layouts, two skins, no size. `className` places it\n * (width, grid cell); its height follows its text.\n */\nexport const Tile = React.forwardRef<HTMLButtonElement, TileProps>(\n (\n { layout = \"row\", variant = \"outline\", icon, title, wrapTitle, line, end, selected, selectedStyle, tooltip, level, fit, endInset, oneLine, dashed, hoverStyle, danger, dimmed, glyphTone, hero, tone, iconTone, dense, asChild = false, className, children, onClick, type, ...props },\n ref,\n ) => {\n const Component = asChild ? Slot : \"button\";\n const ariaDisabled = props[\"aria-disabled\"];\n const inert = ariaDisabled === true || ariaDisabled === \"true\";\n const body = (\n <>\n {icon ? (\n <span className=\"matrx-tile-icon\" data-tone={iconTone && iconTone !== \"neutral\" ? iconTone : undefined}>\n {icon}\n </span>\n ) : null}\n <span className=\"matrx-tile-text\">\n <span className=\"matrx-tile-title\">{title}</span>\n {line ? <span className=\"matrx-tile-line\">{line}</span> : null}\n </span>\n {end ? <span className=\"matrx-tile-end\">{end}</span> : null}\n </>\n );\n return (\n <Component\n ref={ref}\n type={asChild ? undefined : (type ?? \"button\")}\n data-matrx-tile=\"\"\n data-layout={layout}\n data-variant={variant}\n data-selected={selected ? \"\" : undefined}\n data-selected-style={selected && (selectedStyle === \"fill\" || selectedStyle === \"primary\") ? selectedStyle : undefined}\n data-level={level}\n data-fit={fit ? \"\" : undefined}\n data-one-line={oneLine ? \"\" : undefined}\n data-end-inset={endInset}\n data-dashed={dashed ? \"\" : undefined}\n data-hover-style={hoverStyle}\n title={tooltip}\n data-danger={danger ? \"\" : undefined}\n data-dimmed={dimmed ? \"\" : undefined}\n data-wrap-title={wrapTitle ? \"\" : undefined}\n data-glyph-tone={glyphTone}\n data-hero={hero ? \"\" : undefined}\n data-dense={dense ? \"\" : undefined}\n data-tone={tone}\n aria-pressed={asChild || selected === undefined ? undefined : selected}\n className={cn(\"matrx-tile\", className)}\n {...props}\n onClick={inert ? swallowClick : onClick}\n >\n {asChild && React.isValidElement(children) ? (\n React.cloneElement(children as React.ReactElement<{ children?: React.ReactNode }>, undefined, body)\n ) : (\n body\n )}\n </Component>\n );\n },\n);\nTile.displayName = \"Tile\";\n\n/* ------------------------------------------------------------------ */\n/* Section disclosure header */\n/* ------------------------------------------------------------------ */\n\nexport type DisclosureHeaderVariant = \"row\" | \"label\";\n\nexport interface DisclosureHeaderProps extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, \"title\"> {\n /** Whether the section under the header is showing. Sets `aria-expanded`. */\n open: boolean;\n /** `row` (default): a 13px/500 title — a collapsible section, a group of results, a \"details\"\n * fold. `label`: the 11px uppercase muted label that heads a sidebar or menu group. */\n variant?: DisclosureHeaderVariant;\n /** Optional 16px glyph after the chevron (row variant). */\n icon?: React.ReactNode;\n /** Colors ONLY the icon: a status tone uses its `-ink` token, a hue its `--matrx-chip-<hue>-ink`.\n * A section that carries a color (violet Organization, amber Projects) keeps it here. */\n glyphTone?: GlyphTone | ChipTone;\n /** The section's name. */\n title: React.ReactNode;\n /** A short muted fact after the title: a count, a size, \"3 of 12\". Never a sentence. */\n meta?: React.ReactNode;\n /** Trailing content pinned to the end (a status glyph, a count badge). Non-interactive — a\n * control beside the header sits outside it, never inside the button. */\n end?: React.ReactNode;\n /** One 12px secondary line under the title (row variant) — what the section holds. */\n line?: React.ReactNode;\n /** Where the turning chevron sits. `start` (default) leads the row; `end` trails it, for a\n * sidebar section whose label keeps the column's left edge. */\n chevron?: \"start\" | \"end\";\n}\n\n/**\n * THE section-disclosure header: a chevron that turns, a title, an optional count and trailing\n * status — one full-width pressable row that opens and closes the section below it. Every\n * \"click the heading to fold\" row is this, never a raw button with a hand-drawn chevron.\n */\nexport const DisclosureHeader = React.forwardRef<HTMLButtonElement, DisclosureHeaderProps>(\n ({ open, variant = \"row\", icon, glyphTone, title, meta, end, line, chevron = \"start\", className, type, ...props }, ref) => (\n <button\n ref={ref}\n type={type ?? \"button\"}\n aria-expanded={open}\n data-matrx-disclosure=\"\"\n data-variant={variant}\n data-open={open ? \"\" : undefined}\n data-chevron={chevron}\n className={cn(\"matrx-disclosure\", className)}\n {...props}\n >\n {chevron === \"start\" ? (\n <span className=\"matrx-disclosure-chevron\" aria-hidden=\"true\">\n <ChevronRightIcon />\n </span>\n ) : null}\n {icon ? (\n <span className=\"matrx-disclosure-icon\" data-glyph-tone={glyphTone}>\n {icon}\n </span>\n ) : null}\n {line ? (\n <span className=\"matrx-disclosure-text\">\n <span className=\"matrx-disclosure-title\">{title}</span>\n <span className=\"matrx-disclosure-line\">{line}</span>\n </span>\n ) : (\n <span className=\"matrx-disclosure-title\">{title}</span>\n )}\n {meta === undefined || meta === null || meta === false ? null : (\n <span className=\"matrx-disclosure-meta\">{meta}</span>\n )}\n {end ? <span className=\"matrx-disclosure-end\">{end}</span> : null}\n {chevron === \"end\" ? (\n <span className=\"matrx-disclosure-chevron\" data-end=\"\" aria-hidden=\"true\">\n <ChevronRightIcon />\n </span>\n ) : null}\n </button>\n ),\n);\nDisclosureHeader.displayName = \"DisclosureHeader\";\n\n/* ------------------------------------------------------------------ */\n/* Empty state */\n/* ------------------------------------------------------------------ */\n\nexport interface EmptyStateProps {\n /** A 20px glyph inside the tinted disc. */\n icon: React.ReactNode;\n /** 13px title. */\n title: React.ReactNode;\n /** One 12px line. */\n line?: React.ReactNode;\n /** The one 28px action (a controls `Button`). */\n action?: React.ReactNode;\n className?: string;\n}\n\n/** Tinted icon disc + 13px title + one line + one 28px button. */\nexport function EmptyState({ icon, title, line, action, className }: EmptyStateProps) {\n return (\n <div data-matrx-empty-state=\"\" className={cn(\"matrx-control-empty\", className)}>\n <div className=\"matrx-control-empty-disc\" aria-hidden=\"true\">\n {icon}\n </div>\n <div>\n <div className=\"matrx-control-empty-title\">{title}</div>\n {line ? <div className=\"matrx-control-empty-line\">{line}</div> : null}\n </div>\n {action ? <ControlRow className=\"justify-center\">{action}</ControlRow> : null}\n </div>\n );\n}\n\n/* ------------------------------------------------------------------ */\n/* Region skeleton */\n/* ------------------------------------------------------------------ */\n\nexport interface RegionSkeletonProps {\n /** The region's shape: hairline rows, a form's label+field pairs, or cards. */\n shape?: \"rows\" | \"form\" | \"cards\";\n /** How many rows / fields / cards. */\n count?: number;\n /** Rows: a second (meta) line under each title. */\n twoLine?: boolean;\n className?: string;\n \"aria-label\"?: string;\n}\n\n/**\n * A skeleton shaped like the region it stands in for — never one block for a\n * page, never a spinner in the middle. A spinner belongs only inside a busy\n * control.\n */\nexport function RegionSkeleton({\n shape = \"rows\",\n count = shape === \"cards\" ? 3 : shape === \"form\" ? 4 : 8,\n twoLine = false,\n className,\n \"aria-label\": ariaLabel = \"Loading\",\n}: RegionSkeletonProps) {\n const items = Array.from({ length: count }, (_, i) => i);\n if (shape === \"form\") {\n return (\n <div aria-busy=\"true\" aria-label={ariaLabel} className={cn(\"flex flex-col gap-3\", className)}>\n {items.map((i) => (\n <div key={i} className=\"flex flex-col gap-1.5\">\n <Skeleton className=\"h-3 w-24\" />\n <Skeleton className=\"h-7 rounded-full\" />\n </div>\n ))}\n </div>\n );\n }\n if (shape === \"cards\") {\n return (\n <div aria-busy=\"true\" aria-label={ariaLabel} className={cn(\"grid gap-2 sm:grid-cols-3\", className)}>\n {items.map((i) => (\n <div key={i} className=\"flex items-center gap-3 rounded-lg border border-border p-3\">\n <Skeleton className=\"size-8 rounded-full\" />\n <div className=\"flex flex-1 flex-col gap-1.5\">\n <Skeleton className=\"h-3.5 w-2/3\" />\n <Skeleton className=\"h-2.5 w-1/2\" />\n </div>\n </div>\n ))}\n </div>\n );\n }\n return (\n <div aria-busy=\"true\" aria-label={ariaLabel} className={cn(\"divide-y divide-border\", className)}>\n {items.map((i) => (\n <div key={i} className=\"flex min-h-9 items-center gap-3 px-3 py-1.5\">\n <Skeleton className=\"size-4 rounded-full\" />\n <div className=\"flex min-w-0 flex-1 flex-col gap-1\">\n <Skeleton className=\"h-3.5\" style={{ width: `${30 + ((i * 17) % 35)}%` }} />\n {twoLine ? <Skeleton className=\"h-2.5 w-1/4\" /> : null}\n </div>\n <Skeleton className=\"hidden h-[1.125rem] w-16 rounded-md sm:block\" />\n <Skeleton className=\"size-5 rounded-full\" />\n </div>\n ))}\n </div>\n );\n}\n\n/* ------------------------------------------------------------------ */\n/* The three delete tiers */\n/* ------------------------------------------------------------------ */\n\nexport interface DeleteButtonProps\n extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, \"children\" | \"aria-label\"> {\n /** What it deletes, e.g. \"Delete reference\". */\n \"aria-label\": string;\n}\n\n/** Tier 1 — the quiet trash glyph: muted until hover, destructive on hover. */\nexport const DeleteButton = React.forwardRef<HTMLButtonElement, DeleteButtonProps>((props, ref) => (\n <Button ref={ref} variant=\"quiet\" icon={<Trash2Icon />} data-delete=\"\" title={props[\"aria-label\"]} {...props} />\n));\nDeleteButton.displayName = \"DeleteButton\";\n\nexport interface ConfirmDeleteProps {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n /** \"Delete this project?\" */\n title: React.ReactNode;\n /** REQUIRED: name the cost — what is lost, what goes with it. Never \"Are you sure?\". */\n cost: React.ReactNode;\n /** The confirm button names the act, e.g. \"Delete project\". */\n confirmLabel: string;\n onConfirm: () => void | Promise<void>;\n busy?: boolean;\n}\n\n/** Tier 2 — a confirm that names the cost. */\nexport function ConfirmDelete({ open, onOpenChange, title, cost, confirmLabel, onConfirm, busy }: ConfirmDeleteProps) {\n return (\n <ConfirmDialog\n open={open}\n onOpenChange={onOpenChange}\n title={title}\n description={cost}\n confirmLabel={confirmLabel}\n variant=\"destructive\"\n busy={busy}\n onConfirm={onConfirm}\n />\n );\n}\n\n/** Tier 3 — the danger zone: a red-ruled group of rows at the end of settings. */\nexport function DangerZone({\n title = \"Danger zone\",\n children,\n className,\n}: {\n title?: React.ReactNode;\n children: React.ReactNode;\n className?: string;\n}) {\n return (\n <RowGroup title={title} danger className={className}>\n {children}\n </RowGroup>\n );\n}\n\n/* ------------------------------------------------------------------ */\n/* Promo banner */\n/* ------------------------------------------------------------------ */\n\nexport type PromoTone = \"primary\" | \"success\" | \"warning\" | \"info\";\n\nexport interface PromoBannerProps {\n /** A 16px glyph inside the tinted disc. */\n icon: React.ReactNode;\n /** 11px label before the title, e.g. \"Next challenge\". Never a pill. */\n eyebrow?: React.ReactNode;\n /** One line, 13px. */\n title: React.ReactNode;\n /** One line, 12px, ≤60 characters. Omit rather than pad. */\n line?: React.ReactNode;\n /** Outline badges — the evidence behind the promo. */\n chips?: React.ReactNode;\n /** The one action: a controls `Button` (or a link wearing it). */\n action?: React.ReactNode;\n tone?: PromoTone;\n /**\n * Let the title wrap onto as many lines as it needs, for a sentence that must be read whole (a question with its\n * answer buttons beside it). Default false: one line, truncated.\n */\n wrap?: boolean;\n className?: string;\n /** Accessible name of the region. Defaults to \"Featured\". */\n \"aria-label\"?: string;\n}\n\n/**\n * A page-top variant that promotes ONE feature in one bordered row (~56px):\n * [disc] EYEBROW · Title / one line … [chips] [Action]. On a phone the chips\n * wrap under the text and the action stretches full width.\n */\nexport function PromoBanner({\n icon,\n eyebrow,\n title,\n line,\n chips,\n action,\n tone = \"primary\",\n wrap = false,\n className,\n \"aria-label\": ariaLabel,\n}: PromoBannerProps) {\n return (\n <section\n aria-label={ariaLabel ?? (typeof eyebrow === \"string\" ? eyebrow : \"Featured\")}\n data-matrx-promo=\"\"\n data-tone={tone}\n data-wrap={wrap ? \"\" : undefined}\n className={cn(\"matrx-control-promo\", className)}\n >\n <span className=\"matrx-control-promo-disc\" aria-hidden=\"true\">\n {icon}\n </span>\n <div className=\"matrx-control-promo-text\">\n <div className=\"matrx-control-promo-head\">\n {eyebrow ? <span className=\"matrx-control-promo-eyebrow\">{eyebrow}</span> : null}\n {eyebrow ? (\n <span className=\"matrx-control-promo-eyebrow\" aria-hidden=\"true\">\n ·\n </span>\n ) : null}\n <span className=\"matrx-control-promo-title\">{title}</span>\n </div>\n {line ? <div className=\"matrx-control-promo-line\">{line}</div> : null}\n </div>\n {chips ? <div className=\"matrx-control-promo-chips\">{chips}</div> : null}\n {action ? (\n <ControlRow nowrap className=\"matrx-control-promo-action\">\n {action}\n </ControlRow>\n ) : null}\n </section>\n );\n}\n","\"use client\";\n\nimport { Slot } from \"@radix-ui/react-slot\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\nimport * as React from \"react\";\n\nimport { cn } from \"./cn\";\n\nexport const buttonVariants = cva(\n \"matrx-glyph-trim inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all duration-200 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-0 disabled:opacity-50 active:scale-[0.98] [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0\",\n {\n variants: {\n variant: {\n default: \"bg-primary text-primary-foreground shadow-sm hover:bg-primary/90\",\n /**\n * An explicit spelling of `default`, identical by construction. It is\n * not decoration: matrx-frontend's `ButtonMine` fork carried it, ~17\n * call sites say `variant=\"primary\"`, and the alternative to keeping\n * the word was a host shim translating a prop — the massage C22 bans.\n */\n primary: \"bg-primary text-primary-foreground shadow-sm hover:bg-primary/90\",\n destructive:\n \"bg-danger-fill text-danger-fill-foreground shadow-sm hover:bg-danger-fill/90\",\n /** The affirmative twin of `destructive` — confirm, approve, publish. */\n success:\n \"bg-success-fill text-success-fill-foreground shadow-sm hover:bg-success-fill/90\",\n outline:\n \"border border-border bg-card shadow-sm hover:bg-accent hover:text-accent-foreground\",\n secondary:\n \"bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80\",\n ghost: \"hover:bg-accent hover:text-accent-foreground\",\n link: \"text-primary-ink underline-offset-4 hover:underline\",\n subtle:\n \"border border-transparent bg-muted/50 text-foreground hover:border-border hover:bg-muted\",\n },\n /**\n * ONE size scale, xs → 3xl, plus the two icon boxes. The top and bottom\n * of the scale came in from matrx-frontend's `ButtonMine` fork (2026-09-07):\n * a dense toolbar needs `xs`, and a marketing/hero call to action needs\n * `xl`+. A host that has to reach outside this scale forks the button,\n * which is exactly how `ButtonMine` was born.\n */\n size: {\n xs: \"h-6 rounded-md px-1 text-xs\",\n sm: \"h-8 rounded-md px-3 text-xs\",\n default: \"h-9 px-4 py-2\",\n /** An explicit spelling of `default` (the fork's middle rung). */\n md: \"h-9 px-4 py-2\",\n lg: \"h-10 rounded-md px-6\",\n xl: \"h-12 px-8 py-3 text-base\",\n \"2xl\": \"h-14 px-10 py-3 text-base\",\n \"3xl\": \"h-16 px-12 py-3 text-base\",\n icon: \"h-9 w-9\",\n \"icon-sm\": \"h-7 w-7\",\n /** A circular icon box — an avatar-shaped control, not a square one. */\n roundIcon: \"h-8 w-8 rounded-full p-0\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n size: \"default\",\n },\n },\n);\n\n/**\n * THE TOUCH FLOOR (2026-09-17).\n *\n * Every rung of the size scale below `xl` is shorter than the 44px platform\n * touch target: `xs` 24, `icon-sm` 28, `sm` 32, `roundIcon` 32, `default`/`md`\n * 36, `icon` 36, `lg` 40. Measured live at 390x844 on `/masterwork/<id>`, ALL\n * SEVEN design-system Buttons in the viewport were under the floor (four at\n * 32px, two at 28px).\n *\n * The floor is raised in CSS, under `@media (pointer: coarse)` ONLY, so DESKTOP\n * DENSITY IS UNTOUCHED — a narrow desktop window is not a finger, which is why\n * this rule deliberately does NOT carry the `(max-width: 1023px)` half that the\n * dialog-footer floor in `styles.css` uses.\n *\n * WHY EVERY SUB-44 RUNG AND NOT JUST `sm`: a floor applied to one rung inverts\n * the scale. Lift `sm` (32) alone and it renders TALLER on a phone than\n * `default` (36) and `lg` (40) — the scale would stop being a scale. A floor is\n * only coherent applied to everything beneath it.\n *\n * The mechanism is `min-height`/`min-width`, not an invisible 44px hit ring\n * over a 32px pill. A ring is the tap-target package's pattern and it is right\n * THERE (isolated glass buttons), but on a toolbar of adjacent `sm` buttons\n * separated by an 8px gap the rings overlap in the gap and one button silently\n * eats taps aimed at its neighbour — unacceptable where a neighbour is\n * destructive. `lib/entity-list`'s own phone contract (`h-11 min-w-11`) already\n * chose growth for the same reason; this is that choice made once, in the\n * primitive, instead of per surface.\n *\n * `min-width` is raised only on the SQUARE rungs (`icon`, `icon-sm`,\n * `roundIcon`) — a text button is already wider than 44px, and forcing a floor\n * on it would stretch short labels.\n *\n * Opt out on a control that is genuinely not a finger target with\n * `data-touch-exempt` (same escape hatch the footer floor honors), and say why\n * at the call site.\n */\nconst TOUCH_FLOOR_SIZES = new Set([\n \"xs\",\n \"sm\",\n \"default\",\n \"md\",\n \"lg\",\n \"icon\",\n \"icon-sm\",\n \"roundIcon\",\n]);\nconst SQUARE_SIZES = new Set([\"icon\", \"icon-sm\", \"roundIcon\"]);\n\nexport interface ButtonProps\n extends React.ButtonHTMLAttributes<HTMLButtonElement>,\n VariantProps<typeof buttonVariants> {\n asChild?: boolean;\n}\n\n/**\n * THE CURSOR LAW (common-docs/policies/cursor-law.md): a disabled control says\n * so with `not-allowed`, which the package's base layer sets on `:disabled`\n * and `[aria-disabled=\"true\"]`. `pointer-events: none` is never the mechanism\n * — it swallows the cursor. A native `<button disabled>` already fires no\n * click; the two shapes that WOULD fire one are handled here, once:\n * - `asChild` + `disabled` (a Link wearing button styles): marked\n * `aria-disabled`, taken out of the tab order, and its click is swallowed;\n * - `aria-disabled=\"true\"` on an enabled button: its click is swallowed.\n */\nexport function swallowClick(event: React.MouseEvent<HTMLButtonElement>): void {\n event.preventDefault();\n event.stopPropagation();\n}\n\nexport const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(\n ({ className, variant, size, asChild = false, onClick, ...props }, ref) => {\n const Component = asChild ? Slot : \"button\";\n const resolvedSize = size ?? \"default\";\n const disabledChild = asChild && Boolean(props.disabled);\n const ariaDisabled = props[\"aria-disabled\"];\n const inert =\n disabledChild || ariaDisabled === true || ariaDisabled === \"true\";\n return (\n <Component\n className={cn(buttonVariants({ variant, size, className }))}\n data-matrx-button=\"\"\n data-tap-floor={TOUCH_FLOOR_SIZES.has(resolvedSize) ? \"\" : undefined}\n data-tap-floor-square={\n SQUARE_SIZES.has(resolvedSize) ? \"\" : undefined\n }\n ref={ref}\n {...props}\n aria-disabled={disabledChild ? true : ariaDisabled}\n tabIndex={disabledChild ? -1 : props.tabIndex}\n onClick={inert ? swallowClick : onClick}\n />\n );\n },\n);\nButton.displayName = \"Button\";\n","\"use client\";\n\n/**\n * AlertDialog — the confirm/destroy surface (78 host import sites).\n *\n * Ported from matrx-frontend `components/ui/alert-dialog.tsx`, which was the\n * only variant in the fleet that had been hardened. Its rulings, kept verbatim:\n *\n * 1. THE ROOT RENDERS UNCONDITIONALLY — no hydration mount gate. The gate a\n * wrapper once carried (\"Radix ids differ between SSR and client\") was\n * false, and it deleted always-visible Triggers (delete buttons, mostly)\n * from SSR and the first client paint.\n *\n * 2. AN UNDESCRIBED ALERT DIALOG STILL DESCRIBES ITSELF. A confirm dialog with\n * no `AlertDialogDescription` gets a screen-reader-only one rather than a\n * console warning — the surface where a blind user is about to destroy\n * something is the wrong place to ship an accessibility gap.\n *\n * ADDED HERE, from the same doctrine `Dialog` already carries and this\n * component demonstrably needed:\n *\n * 3. IT IS CLAMPED TO THE VIEWPORT AND SCROLLS INSIDE ITSELF\n * (`max-h-[85dvh] overflow-y-auto`). The host copy was NOT — an alert\n * dialog whose body listed what is about to be deleted pushed Cancel and\n * Continue below the fold on a short viewport, and the only way out was a\n * backdrop click. On an ALERT dialog Radix does not dismiss on backdrop\n * click, so the surface was a genuine dead end. Recorded in CHANGELOG as a\n * real defect fixed in the port, not \"preserved\".\n *\n * 4. THE ACTIONS ARE 44px TALL ON COARSE POINTERS. `AlertDialogAction` and\n * `AlertDialogCancel` inherit the package Button's own target rules through\n * `buttonVariants`; the footer keeps them safe-area padded on mobile.\n *\n * 5. THE STICKY FOOTER NEVER PAINTS OVER THE BODY (0.11.3). Ruling 3's footer\n * bled over the card's bottom padding with a negative block margin, and\n * `position: sticky` clamps a box to its containing block — so the footer\n * was dragged UP by `--dialog-pad` against the card's `gap-4`, covering the\n * last 8px of the consequence copy at every length, unreachable because the\n * card did not scroll. The bleed is now the card's RESERVATION\n * (`.matrx-dialog-card` hands its bottom padding to the footer), which\n * sticky has nothing to clamp. See `sticky-footer-geometry.test.tsx`.\n *\n * SEAM INVERSION. The host resolved its portal target through\n * `usePopoutContainer` (its window-panel popout body); here that is the\n * package's `PortalContainerProvider`, with an explicit `container` prop still\n * winning.\n */\n\nimport * as AlertDialogPrimitive from \"@radix-ui/react-alert-dialog\";\nimport { treeContainsComponent } from \"@ai-matrx/kit/react-tree\";\nimport * as React from \"react\";\n\nimport { buttonVariants } from \"./button\";\nimport { cn } from \"./cn\";\nimport { useModalLayer } from \"./floating-layer\";\nimport { CENTERED_DIALOG, MOTION_DIALOG, MOTION_OVERLAY } from \"./motion\";\nimport { usePortalContainer } from \"./portal-container\";\nimport { keepMovedFocus } from \"./focus-return\";\n\nconst AlertDialog = AlertDialogPrimitive.Root;\n\nconst AlertDialogTrigger = AlertDialogPrimitive.Trigger;\n\n/**\n * Portal-seam-aware AlertDialogPortal. Explicit `container` wins; with none,\n * the injected container; with neither, Radix's `document.body`.\n */\nconst AlertDialogPortal = ({\n container,\n ...props\n}: Omit<\n React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Portal>,\n \"container\"\n> & {\n /** `undefined` → use the injected container; `null` → force document.body. */\n container?: HTMLElement | null | undefined;\n}) => {\n const resolved = usePortalContainer(container);\n return (\n <AlertDialogPrimitive.Portal container={resolved ?? null} {...props} />\n );\n};\nAlertDialogPortal.displayName = \"AlertDialogPortal\";\n\nconst AlertDialogOverlay = React.forwardRef<\n React.ComponentRef<typeof AlertDialogPrimitive.Overlay>,\n React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Overlay>\n>(({ className, ...props }, ref) => (\n <AlertDialogPrimitive.Overlay\n ref={ref}\n data-slot=\"alert-dialog-overlay\"\n className={cn(\n \"fixed inset-0 z-[10000] bg-[var(--matrx-overlay-scrim)]\",\n MOTION_OVERLAY,\n className,\n )}\n {...props}\n />\n));\nAlertDialogOverlay.displayName = AlertDialogPrimitive.Overlay.displayName;\n\n/**\n * Unstyled, non-portalling Content for custom layouts. AlertDialog is always\n * modal, so `aria-modal` is stated rather than derived.\n */\nconst AlertDialogContentPrimitive = React.forwardRef<\n React.ComponentRef<typeof AlertDialogPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Content>\n>(({ onCloseAutoFocus, ...props }, ref) => {\n // Always blocking: floating layers opened from it stack above its scrim.\n useModalLayer(true);\n return <AlertDialogPrimitive.Content {...props} ref={ref} aria-modal=\"true\" onCloseAutoFocus={keepMovedFocus(onCloseAutoFocus)} />;\n});\nAlertDialogContentPrimitive.displayName = \"AlertDialogContentPrimitive\";\n\nconst AlertDialogDescription = React.forwardRef<\n React.ComponentRef<typeof AlertDialogPrimitive.Description>,\n React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Description>\n>(({ className, ...props }, ref) => (\n <AlertDialogPrimitive.Description\n ref={ref}\n data-slot=\"alert-dialog-description\"\n className={cn(\"text-sm text-muted-foreground\", className)}\n {...props}\n />\n));\nAlertDialogDescription.displayName =\n AlertDialogPrimitive.Description.displayName;\n\nexport interface AlertDialogContentProps\n extends React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Content> {\n /** Explicit portal target; wins over the injected container. */\n container?: HTMLElement | null;\n /**\n * Package-owned open/close motion. Default `true`. Pass `false` for a\n * surface that must appear instantly. It is NOT the reduced-motion switch;\n * `styles.css` already honors `prefers-reduced-motion`.\n */\n animated?: boolean;\n}\n\nconst AlertDialogContent = React.forwardRef<\n React.ComponentRef<typeof AlertDialogPrimitive.Content>,\n AlertDialogContentProps\n>(({ className, children, container, animated = true, ...props }, ref) => {\n const hasDescription =\n treeContainsComponent(children, AlertDialogDescription) ||\n treeContainsComponent(children, AlertDialogPrimitive.Description);\n return (\n <AlertDialogPortal container={container}>\n <AlertDialogOverlay />\n <AlertDialogContentPrimitive\n ref={ref}\n data-slot=\"alert-dialog-content\"\n className={cn(\n `matrx-dialog-card fixed left-[50%] top-[50%] z-[10000] grid min-w-0 w-full max-w-lg ${CENTERED_DIALOG} gap-4 border bg-background p-6 shadow-lg`,\n // Ruling 3 — never taller than the viewport, always scrollable, and\n // the footer stays reachable via --dialog-pad like Dialog's.\n // Ruling 5 (0.11.3) — `matrx-dialog-card` hands the bottom padding to\n // a sticky footer when there is one, so the footer's box matches the\n // space the grid gave it and sticky never clamps it up over the\n // consequence copy.\n \"max-h-[85dvh] overflow-y-auto overscroll-contain [--dialog-pad:1.5rem] overflow-x-clip [overflow-wrap:anywhere] [&>*]:min-w-0 [&>*]:max-w-full\",\n \"sm:rounded-lg\",\n animated && MOTION_DIALOG,\n className,\n )}\n {...props}\n >\n {hasDescription ? null : (\n <AlertDialogPrimitive.Description className=\"sr-only\">\n Please confirm the action described in this dialog.\n </AlertDialogPrimitive.Description>\n )}\n {children}\n </AlertDialogContentPrimitive>\n </AlertDialogPortal>\n );\n});\nAlertDialogContent.displayName = AlertDialogPrimitive.Content.displayName;\n\nconst AlertDialogHeader = ({\n className,\n ...props\n}: React.HTMLAttributes<HTMLDivElement>) => (\n <div\n data-slot=\"alert-dialog-header\"\n className={cn(\"flex flex-col space-y-2 text-center sm:text-left\", className)}\n {...props}\n />\n);\nAlertDialogHeader.displayName = \"AlertDialogHeader\";\n\nconst AlertDialogFooter = ({\n className,\n ...props\n}: React.HTMLAttributes<HTMLDivElement>) => (\n <div\n data-slot=\"alert-dialog-footer\"\n className={cn(\n \"flex flex-col-reverse gap-2 sm:flex-row sm:justify-end sm:gap-0 sm:space-x-2\",\n // Ruling 3/4 — sticky to the card edges so a scrolled body never shows\n // through under the actions, and safe-area padded on a phone.\n //\n // 🚨 THERE IS NO `mb-[…]` HERE, AND THERE MUST NEVER BE ONE AGAIN\n // (0.11.3, feedback bf8fb00b). The bleed over the card's bottom padding\n // used to be a NEGATIVE BLOCK MARGIN, which makes this box taller than\n // the grid area the card allocates it — and `position: sticky` CLAMPS a\n // box to its containing block, so the browser yanked the footer UP by\n // `--dialog-pad` against the card's `gap-4` and painted 8px of opaque\n // footer over the last line of the consequence, at every length. The\n // card now RESERVES this footer's block size instead (`matrx-dialog-card`\n // in styles.css hands over its `padding-bottom`), so the bleed costs no\n // margin at all. Guard: `sticky-footer-geometry.test.tsx`.\n //\n // These stay UTILITIES rather than a shipped rule so a caller's\n // `className` still wins through tailwind-merge — a shipped rule would\n // have to be unlayered to survive Tailwind preflight (§ THE PREFLIGHT\n // RULE in styles.css) and would then override every caller's padding.\n \"sticky bottom-0 z-10 bg-background pt-3\",\n \"mx-[calc(var(--dialog-pad,0px)*-1)] px-[var(--dialog-pad,0px)] pb-[var(--dialog-pad,0px)]\",\n className,\n )}\n {...props}\n />\n);\nAlertDialogFooter.displayName = \"AlertDialogFooter\";\n\nconst AlertDialogTitle = React.forwardRef<\n React.ComponentRef<typeof AlertDialogPrimitive.Title>,\n React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Title>\n>(({ className, ...props }, ref) => (\n <AlertDialogPrimitive.Title\n ref={ref}\n data-slot=\"alert-dialog-title\"\n className={cn(\"text-lg font-semibold\", className)}\n {...props}\n />\n));\nAlertDialogTitle.displayName = AlertDialogPrimitive.Title.displayName;\n\nconst AlertDialogAction = React.forwardRef<\n React.ComponentRef<typeof AlertDialogPrimitive.Action>,\n React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Action>\n>(({ className, ...props }, ref) => (\n <AlertDialogPrimitive.Action\n ref={ref}\n data-slot=\"alert-dialog-action\"\n className={cn(buttonVariants(), className)}\n {...props}\n />\n));\nAlertDialogAction.displayName = AlertDialogPrimitive.Action.displayName;\n\nconst AlertDialogCancel = React.forwardRef<\n React.ComponentRef<typeof AlertDialogPrimitive.Cancel>,\n React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Cancel>\n>(({ className, ...props }, ref) => (\n <AlertDialogPrimitive.Cancel\n ref={ref}\n data-slot=\"alert-dialog-cancel\"\n className={cn(\n buttonVariants({ variant: \"outline\" }),\n \"mt-2 sm:mt-0\",\n className,\n )}\n {...props}\n />\n));\nAlertDialogCancel.displayName = AlertDialogPrimitive.Cancel.displayName;\n\nexport {\n AlertDialog,\n AlertDialogAction,\n AlertDialogCancel,\n AlertDialogContent,\n AlertDialogContentPrimitive,\n AlertDialogDescription,\n AlertDialogFooter,\n AlertDialogHeader,\n AlertDialogOverlay,\n AlertDialogPortal,\n AlertDialogTitle,\n AlertDialogTrigger,\n};\n","\"use client\";\n\n/**\n * THE ONE CONTROL — the settled control family (owner, 2026-10-02/03).\n *\n * Every control here is the same object: 28px visible height, capsule, 13px/500\n * label, 16px glyph inset 6px, text inset 10px, and HALF A GAP (3px) of its own\n * on each side so containers add no gap. There is NO size prop: agents get no\n * choice. Geometry and color live in `controls.css`, locked inside\n * `@layer matrx-tap-lock` (`!important` in the host's first layer), so a call\n * site's `className` can place a control (width, flex, grid, position) but can\n * never restyle it. The rare big control is a different component behind a\n * `// ui-exception:` comment, never a prop.\n *\n * Built on the package's own internals — Radix Slot / Switch / DropdownMenu, the\n * cursor law's `swallowClick`, `SelectChevron`, the package icons — so nothing\n * here is a second implementation of a behavior the package already owns.\n */\n\nimport * as SwitchPrimitives from \"@radix-ui/react-switch\";\nimport { Slot, Slottable } from \"@radix-ui/react-slot\";\nimport * as React from \"react\";\n\nimport { swallowClick } from \"../button\";\nimport { cn } from \"../cn\";\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuLabel,\n DropdownMenuRadioGroup,\n DropdownMenuRadioItem,\n DropdownMenuSeparator,\n DropdownMenuTrigger,\n} from \"../dropdown-menu\";\nimport { MagnifyingGlassIcon, PlusIcon } from \"../icons\";\nimport { SelectChevron } from \"../select\";\nimport { isIconOnly } from \"./icon-only\";\nimport { boxStyle, useAutoGrow, useMergedTextareaRef } from \"../textarea\";\n\n/* ------------------------------------------------------------------ */\n/* Layout: the row and the scope */\n/* ------------------------------------------------------------------ */\n\nexport interface ControlRowProps extends React.HTMLAttributes<HTMLDivElement> {\n /** Keep the controls on one line (a row's trailing actions). */\n nowrap?: boolean;\n}\n\n/** A row of controls. It adds no gap: each control carries its own half-gap. */\nexport const ControlRow = React.forwardRef<HTMLDivElement, ControlRowProps>(\n ({ className, nowrap, ...props }, ref) => (\n <div\n ref={ref}\n data-matrx-control-row=\"\"\n data-nowrap={nowrap ? \"\" : undefined}\n className={cn(\"matrx-control-row\", className)}\n {...props}\n />\n ),\n);\nControlRow.displayName = \"ControlRow\";\n\n/**\n * Until the tap tokens move to 28/34 app-wide (the rollout), a tap button\n * inside a ControlScope matches the controls beside it: a 28px pill in a 34px\n * box. Wrap a page (or a region) that mixes tap buttons and controls.\n */\nexport const ControlScope = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(\n (props, ref) => <div ref={ref} data-matrx-controls=\"\" {...props} />,\n);\nControlScope.displayName = \"ControlScope\";\n\n/**\n * THE CONTAINER a collapsing control measures (`Button collapse=\"container\"`).\n * A host declares it on the box whose WIDTH decides — a list pane, a panel,\n * never the viewport: beside a chat panel a 1024px screen holds a 540px list.\n * `className={CONTROLS_CONTAINER_CLASS}`, or add the name to the box's own\n * `container-name` when it already names a container (`list matrx-controls`).\n */\nexport const CONTROLS_CONTAINER_NAME = \"matrx-controls\";\nexport const CONTROLS_CONTAINER_CLASS = \"matrx-controls-container\";\n/** Below this container width a `collapse=\"container\"` button is its icon alone (48rem). */\nexport const CONTROLS_COLLAPSE_BELOW_REM = 48;\n\n/* ------------------------------------------------------------------ */\n/* Button */\n/* ------------------------------------------------------------------ */\n\n/**\n * Tone, never size. `success` is the solid confirm-a-good-outcome fill (approve,\n * publish, mark done); `link` is a text action at the control's height — no\n * fill, no border, primary ink, underline on hover (an inline \"View all\").\n */\nexport type ControlVariant = \"primary\" | \"quiet\" | \"outline\" | \"danger\" | \"success\" | \"link\" | \"meta\";\n\n/**\n * THE NAMED CONTROL WIDTHS (0.68.22) — a button, field or select trigger that should not fill\n * its row takes one of these instead of a pasted `w-40`. Derived from the call sites:\n * `xs` 6rem (a unit, a short enum), `sm` 8rem, `md` 10rem (a date, a status), `lg` 14rem (a\n * name, an account), `xl` 20rem (a search, a URL). Never wider than its container.\n */\nexport type ControlWidth = \"xs\" | \"sm\" | \"md\" | \"lg\" | \"xl\";\n\ninterface ButtonBase extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, \"children\"> {\n /** Tone, never size. Default `outline`. */\n variant?: ControlVariant;\n /** A status tint from the role tokens (the Badge's), for a button that\n * reports a state — a drift door, an alert count. Default: none. */\n tone?: BadgeTone;\n /** Leading 16px glyph. */\n icon?: React.ReactNode;\n /** Trailing 16px glyph (a menu chevron, an external-link mark). */\n iconEnd?: React.ReactNode;\n /** Render the one child element (a link) with the button's skin. */\n asChild?: boolean;\n /**\n * `\"container\"`: below 48rem of the nearest `matrx-controls` container\n * (CONTROLS_CONTAINER_NAME) the button is its leading `icon` alone — a 28px\n * circle; the label stays its accessible name and its tooltip. Needs `icon`;\n * without one it never collapses. Outside such a container it never does.\n */\n collapse?: \"container\";\n /**\n * A TOGGLE (a choice in a set, a mode, a tab-like switch): `true` is on —\n * the accent fill and full ink; `false` is off — no fill, quiet ink. Sets\n * `aria-pressed`. Omit for an ordinary action.\n */\n pressed?: boolean;\n /**\n * A count or a dot on the button's top-right corner, for something waiting\n * behind it (items added, unread). A number draws the count (99+ above 99;\n * 0 draws nothing); `true` draws an 8px dot. On a button with a text label\n * the count sits in the row after the label instead (never over it). Name it in `aria-label` too —\n * the mark is decoration.\n */\n badge?: number | boolean;\n /**\n * The glyph's own status ink, for a glyph whose COLOR carries meaning (the\n * green check after a copy, an amber debug bug) while the button stays\n * quiet. Tints only the icon(s), never the fill. Default: none.\n */\n glyphTone?: GlyphTone;\n /**\n * A removing act (clear, remove, disconnect): muted until hover,\n * destructive on hover — the delete tier-1 skin on any glyph or label.\n * Quiet variant only.\n */\n removes?: boolean;\n /**\n * MIXED CONTENT (0.68.12): a short muted fact after the label — a count, a\n * size, a shortcut, a \"3 of 12\" — in the 12px secondary ink. The button\n * stays 28px; the fact is part of the button, never a second element styled\n * beside it. Never a sentence.\n */\n meta?: React.ReactNode;\n /** A named width instead of the label's own (see `ControlWidth`). */\n width?: ControlWidth;\n /**\n * THE INVITING-PAGE CALL TO ACTION (0.68.22): a 44px capsule with a 16px/600 label and a\n * 24px inset — the size a marketing hero, a module landing or a kit's front door asks for.\n * Inviting pages are never densified; functional pages never use it. A `primary` hero\n * carries a soft primary glow.\n */\n hero?: boolean;\n}\n/** The status inks a glyph may carry (the role tokens). */\nexport type GlyphTone = \"success\" | \"warning\" | \"destructive\" | \"info\" | \"primary\";\ninterface LabelledButton extends ButtonBase {\n children: React.ReactNode;\n}\ninterface IconOnlyButton extends ButtonBase {\n children?: undefined;\n /** An icon-only button must say what it does. */\n \"aria-label\": string;\n}\nexport type ButtonProps = LabelledButton | IconOnlyButton;\n\nfunction glyphSlot(icon: unknown, iconEnd: unknown, label: unknown): string | undefined {\n if (!label && (icon || iconEnd)) return \"only\";\n if (icon && iconEnd) return \"both\";\n if (icon) return \"start\";\n if (iconEnd) return \"end\";\n return undefined;\n}\n\n/**\n * THE button: primary / quiet / outline / danger / success / link, one 28px geometry; text,\n * icon + text, or icon-only (a 28px circle). `asChild` puts the skin on a link.\n */\nexport const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(\n ({ className, variant = \"outline\", tone, icon, iconEnd, asChild = false, collapse, pressed, badge, glyphTone, removes, meta, width, hero, children, onClick, type, ...props }, ref) => {\n const Component = asChild ? Slot : \"button\";\n const badgeText =\n typeof badge === \"number\" ? (badge > 0 ? (badge > 99 ? \"99+\" : String(badge)) : null) : badge ? \"\" : null;\n const ariaDisabled = props[\"aria-disabled\"];\n const disabledChild = asChild && Boolean(props.disabled);\n const inert = disabledChild || ariaDisabled === true || ariaDisabled === \"true\";\n // asChild: the child element carries the label, so the glyph slot reads\n // the child's own children.\n const label = asChild && React.isValidElement<{ children?: React.ReactNode }>(children)\n ? children.props.children\n : children;\n const collapses = collapse === \"container\" && Boolean(icon) && Boolean(label);\n return (\n <Component\n ref={ref}\n type={asChild ? undefined : (type ?? \"button\")}\n data-matrx-control=\"button\"\n data-variant={variant}\n data-tone={tone && tone !== \"neutral\" ? tone : undefined}\n data-glyph={glyphSlot(icon, iconEnd, label)}\n data-collapse={collapses ? \"container\" : undefined}\n data-pressed={pressed === undefined ? undefined : pressed ? \"true\" : \"false\"}\n aria-pressed={pressed}\n data-badge={badgeText === null ? undefined : badgeText === \"\" ? \"dot\" : \"count\"}\n // A labeled button carries its count IN the row after the label: the\n // corner count sat over the label's last letter (\"HR 28\" on /tasks).\n data-badge-place={badgeText && label ? \"inline\" : undefined}\n data-glyph-tone={glyphTone}\n data-delete={removes ? \"\" : undefined}\n data-width={width}\n data-hero={hero ? \"\" : undefined}\n className={cn(\"matrx-control matrx-control-button matrx-glyph-trim\", className)}\n // A collapsed button still says what it does on hover.\n title={collapses && typeof label === \"string\" && props.title === undefined ? label : undefined}\n {...props}\n aria-disabled={disabledChild ? true : ariaDisabled}\n tabIndex={disabledChild ? -1 : props.tabIndex}\n onClick={inert ? swallowClick : onClick}\n >\n {icon}\n <Slottable>\n {/* A text label NEVER spills past its button (owner, 2026-10-05: a\n long chat title ran under the mode switch beside it). It sits in\n its own box so a capped button ellipsizes instead of overflowing. */}\n {!asChild && (typeof children === \"string\" || typeof children === \"number\") ? (\n <span className=\"matrx-control-button-label\">{children}</span>\n ) : (\n children\n )}\n </Slottable>\n {meta === undefined || meta === null || meta === false ? null : (\n <span className=\"matrx-control-button-meta\">{meta}</span>\n )}\n {iconEnd}\n {badgeText === null ? null : (\n <span className=\"matrx-control-button-badge\" aria-hidden=\"true\">\n {badgeText}\n </span>\n )}\n </Component>\n );\n },\n);\nButton.displayName = \"Button\";\n\n/** A split button: two Buttons joined — the act, and its menu of variants. */\nexport const SplitButton = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(\n ({ className, ...props }, ref) => (\n <div ref={ref} role=\"group\" data-matrx-control=\"split\" className={cn(\"matrx-control-split\", className)} {...props} />\n ),\n);\nSplitButton.displayName = \"SplitButton\";\n\n/* ------------------------------------------------------------------ */\n/* Field (input capsule) and SearchField */\n/* ------------------------------------------------------------------ */\n\nexport interface FieldProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, \"size\"> {\n /** Leading 16px glyph. */\n icon?: React.ReactNode;\n /** Trailing content inside the capsule — a clear button, a unit. */\n end?: React.ReactNode;\n /** A named width instead of filling the row (see `ControlWidth`). */\n width?: ControlWidth;\n /**\n * THE INVITING-PAGE INPUT: a 56px capsule with an 18px value and a 24px inset — the big,\n * friendly field a welcome / onboarding front door asks for (pairs with Button `hero`).\n * Inviting pages only; functional pages never use it.\n */\n hero?: boolean;\n /**\n * THE LEADING SEARCH: a 48px filled capsule — no frame, the muted fill, a 16px value, a 20px\n * glyph — that turns the card color with a soft lift on focus. The one search a home page leads\n * with (a file home's search, as on Google Docs / Drive). One per page; never in a form or toolbar.\n */\n filled?: boolean;\n}\n\n/** The input capsule. `className`/`style` place the capsule (width, flex). */\nexport const Field = React.forwardRef<HTMLInputElement, FieldProps>(\n ({ className, style, icon, end, width, hero, filled, ...props }, ref) => (\n <label\n data-matrx-control=\"field\"\n data-glyph={icon ? \"start\" : undefined}\n data-width={width}\n data-hero={hero ? \"\" : undefined}\n data-filled={filled ? \"\" : undefined}\n className={cn(\"matrx-control matrx-control-field\", className)}\n style={style}\n >\n {icon}\n <input ref={ref} {...props} />\n {end}\n </label>\n ),\n);\nField.displayName = \"Field\";\n\n/** The search capsule: a Field with the magnifier, `type=\"search\"`. */\nexport const SearchField = React.forwardRef<HTMLInputElement, Omit<FieldProps, \"icon\">>(\n ({ placeholder = \"Search\", ...props }, ref) => (\n <Field\n ref={ref}\n type=\"search\"\n icon={<MagnifyingGlassIcon aria-hidden=\"true\" />}\n placeholder={placeholder}\n aria-label={props[\"aria-label\"] ?? placeholder}\n {...props}\n />\n ),\n);\nSearchField.displayName = \"SearchField\";\n\n/* ------------------------------------------------------------------ */\n/* Select — a capsule trigger over a radio menu */\n/* ------------------------------------------------------------------ */\n\nexport interface SelectOption<T extends string = string> {\n value: T;\n label: string;\n /** 11px trailing text in the menu (a count, a shortcut). */\n meta?: string;\n /** Muted text right after the label, menu and trigger alike: what tells two same-named options apart (a short id, an owner). */\n hint?: string;\n /** A section heading: the menu shows it (foreground weight) above the first option of each consecutive run. */\n group?: string;\n /** Shown but not choosable (an unavailable tool, a sentinel the URL set). */\n disabled?: boolean;\n}\n\nexport interface SelectProps<T extends string = string> {\n value: T;\n options: readonly SelectOption<T>[];\n onValueChange: (value: T) => void;\n \"aria-label\": string;\n /** Leading 16px glyph on the trigger. */\n icon?: React.ReactNode;\n align?: \"start\" | \"end\";\n disabled?: boolean;\n /**\n * `field` (default): the capsule a form row uses. `inline`: the value as text with a small chevron,\n * no capsule — for a choice that sits inside a dense row or a toolbar sentence (\"Full ⌄\"), where a\n * row of capsules reads as clutter (Arman, 2026-10-14).\n */\n variant?: \"field\" | \"inline\";\n /**\n * A search row at the top of the menu once there are at least this many options (a long list of\n * organizations). It matches label, hint and group. Omitted: never.\n */\n searchAt?: number;\n /** Placement only (width, flex). */\n className?: string;\n style?: React.CSSProperties;\n}\n\nexport function Select<T extends string = string>({\n value,\n options,\n onValueChange,\n icon,\n align = \"start\",\n disabled,\n className,\n style,\n \"aria-label\": ariaLabel,\n variant = \"field\",\n searchAt,\n}: SelectProps<T>) {\n const current = options.find((o) => o.value === value);\n const [query, setQuery] = React.useState(\"\");\n const searchable = searchAt !== undefined && options.length >= searchAt;\n const q = searchable ? query.trim().toLowerCase() : \"\";\n const shown = q ? options.filter((o) => [o.label, o.hint, o.group].some((t) => t?.toLowerCase().includes(q))) : options;\n return (\n <DropdownMenu onOpenChange={(open) => !open && setQuery(\"\")}>\n <DropdownMenuTrigger asChild disabled={disabled}>\n <button\n type=\"button\"\n data-matrx-control=\"select\"\n data-variant={variant === \"inline\" ? \"inline\" : undefined}\n data-glyph={icon ? \"start\" : undefined}\n className={cn(\"matrx-control matrx-control-select\", className)}\n style={style}\n aria-label={ariaLabel}\n >\n <span className=\"matrx-control-select-value\">\n {icon}\n <span>{current?.label ?? value}</span>\n {current?.hint ? <span className=\"text-muted-foreground\" data-select-hint=\"\">{current.hint}</span> : null}\n </span>\n <SelectChevron />\n </button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align={align} className=\"max-h-80 w-max min-w-[max(10rem,var(--radix-dropdown-menu-trigger-width))] max-w-[min(24rem,var(--radix-dropdown-menu-content-available-width))] overflow-y-auto\">\n {searchable ? (\n <div className=\"sticky top-0 z-10 bg-popover p-1\" data-select-search=\"\">\n <SearchField\n className=\"w-full\"\n value={query}\n autoFocus\n aria-label={`Search ${ariaLabel}`}\n onChange={(e) => setQuery(e.target.value)}\n // The menu's type-ahead never takes the letters; arrows and Escape still drive the menu.\n onKeyDown={(e) => {\n if (e.key !== \"ArrowDown\" && e.key !== \"ArrowUp\" && e.key !== \"Escape\" && e.key !== \"Tab\") e.stopPropagation();\n }}\n />\n </div>\n ) : null}\n {searchable && shown.length === 0 ? <div className=\"px-2 py-1.5 text-[0.8125rem] text-muted-foreground\" role=\"status\">No match</div> : null}\n <DropdownMenuRadioGroup value={value} onValueChange={(v) => onValueChange(v as T)}>\n {shown.map((o, i) => (\n <React.Fragment key={o.value}>\n {o.group && o.group !== shown[i - 1]?.group ? (\n <>\n {i > 0 ? <DropdownMenuSeparator /> : null}\n <DropdownMenuLabel>{o.group}</DropdownMenuLabel>\n </>\n ) : null}\n <DropdownMenuRadioItem value={o.value} disabled={o.disabled === true} className=\"text-[0.8125rem]\">\n {/* The label truncates; the hint never does (it is what tells two same-named options apart). */}\n <span className=\"flex min-w-0 flex-1 items-baseline\">\n <span className=\"min-w-0 truncate\">{o.label}</span>\n {o.hint ? <span className=\"ml-1.5 shrink-0 text-muted-foreground\" data-select-hint=\"\">{o.hint}</span> : null}\n </span>\n {o.meta ? <span className=\"ml-3 text-[0.6875rem] text-muted-foreground\">{o.meta}</span> : null}\n </DropdownMenuRadioItem>\n </React.Fragment>\n ))}\n </DropdownMenuRadioGroup>\n </DropdownMenuContent>\n </DropdownMenu>\n );\n}\n\n/* ------------------------------------------------------------------ */\n/* SegmentedControl and Tabs */\n/* ------------------------------------------------------------------ */\n\nexport interface SegmentOption<T extends string = string> {\n value: T;\n label: React.ReactNode;\n /** An 11px count after the label. */\n count?: number | null;\n ariaLabel?: string;\n /** Hover text (an icon-only segment's name). */\n title?: string;\n disabled?: boolean;\n}\n\nexport interface SegmentedControlProps<T extends string = string> {\n /** The selected segment; `null` = none is selected (an optional choice). */\n value: T | null;\n onValueChange: (value: T) => void;\n data: readonly SegmentOption<T>[];\n \"aria-label\": string;\n /** The segments share the row's whole width equally (a full-width choice: levels, modes). */\n fill?: boolean;\n /** Placement only. */\n className?: string;\n style?: React.CSSProperties;\n}\n\nfunction SegmentItems<T extends string>({\n data,\n value,\n onValueChange,\n role,\n}: {\n data: readonly SegmentOption<T>[];\n value: T | null;\n onValueChange: (value: T) => void;\n role: \"tab\" | undefined;\n}) {\n return (\n <>\n {data.map((o) => {\n const on = o.value === value;\n return (\n <button\n key={o.value}\n type=\"button\"\n role={role}\n aria-selected={role ? on : undefined}\n aria-pressed={role ? undefined : on}\n aria-label={o.ariaLabel}\n title={o.title}\n disabled={o.disabled}\n data-state={on ? \"on\" : \"off\"}\n data-icon-only={o.count == null && isIconOnly(o.label) ? \"\" : undefined}\n className=\"matrx-control-segment\"\n onClick={() => onValueChange(o.value)}\n >\n {o.label}\n {o.count != null ? <span className=\"matrx-control-count\">{o.count}</span> : null}\n </button>\n );\n })}\n </>\n );\n}\n\n/** The capsule toggle group: a muted track, the selected thumb inset 2px. */\nexport function SegmentedControl<T extends string = string>({\n value,\n onValueChange,\n data,\n fill,\n className,\n style,\n \"aria-label\": ariaLabel,\n}: SegmentedControlProps<T>) {\n return (\n <div\n role=\"group\"\n aria-label={ariaLabel}\n data-matrx-control=\"segmented\"\n data-fill={fill ? \"\" : undefined}\n className={cn(\"matrx-control matrx-control-segmented\", className)}\n style={style}\n >\n <SegmentItems data={data} value={value} onValueChange={onValueChange} role={undefined} />\n </div>\n );\n}\n\nexport interface TabsProps<T extends string = string> extends SegmentedControlProps<T> {\n /** `underline` for page sections (default); `capsule` for filters. */\n variant?: \"underline\" | \"capsule\";\n /** Underline tabs draw their own hairline (default). Pass `false` when the row the tabs\n * sit in already draws it — the selected underline then lands on that row's rule. */\n rule?: boolean;\n /** Underline tabs inside a framed panel (a card, a bordered box): the labels start at the\n * panel's 12px content inset while the hairline still runs edge to edge. Page-level tabs\n * stay flush with the page gutter (default). Arman, 2026-10-21. */\n inset?: boolean;\n}\n\n/** Tabs: underline for page sections, capsule for filters. */\nexport function Tabs<T extends string = string>({\n variant = \"underline\",\n rule = true,\n inset = false,\n value,\n onValueChange,\n data,\n className,\n style,\n \"aria-label\": ariaLabel,\n}: TabsProps<T>) {\n if (variant === \"capsule\") {\n return (\n <div\n role=\"tablist\"\n aria-label={ariaLabel}\n data-matrx-control=\"tabs\"\n className={cn(\"matrx-control matrx-control-segmented\", className)}\n style={style}\n >\n <SegmentItems data={data} value={value} onValueChange={onValueChange} role=\"tab\" />\n </div>\n );\n }\n return (\n <div\n role=\"tablist\"\n aria-label={ariaLabel}\n data-matrx-control=\"tabs\"\n data-rule={rule ? undefined : \"none\"}\n data-inset={inset ? \"\" : undefined}\n className={cn(\"matrx-control-tabs\", className)}\n style={style}\n >\n {data.map((o) => (\n <button\n key={o.value}\n type=\"button\"\n role=\"tab\"\n aria-selected={o.value === value}\n aria-label={o.ariaLabel}\n disabled={o.disabled}\n className=\"matrx-control-tab\"\n onClick={() => onValueChange(o.value)}\n >\n {o.label}\n {o.count != null ? <span className=\"matrx-control-count\">{o.count}</span> : null}\n </button>\n ))}\n </div>\n );\n}\n\n/* ------------------------------------------------------------------ */\n/* Badge */\n/* ------------------------------------------------------------------ */\n\nexport type BadgeTone = \"neutral\" | \"primary\" | \"success\" | \"warning\" | \"destructive\" | \"info\";\n\nexport interface BadgeProps extends React.HTMLAttributes<HTMLSpanElement> {\n /** A status tint from the role tokens. Default `neutral` (plain outline). */\n tone?: BadgeTone;\n /** A 12px glyph before the label, 4px gap, in the badge's own tone color. */\n icon?: React.ReactNode;\n}\n\n/** Outline, 18px, 11px text, clamped to one line (≤20rem) — never a sentence. */\nexport function Badge({ tone = \"neutral\", icon, className, children, ...props }: BadgeProps) {\n return (\n <span\n data-matrx-control=\"badge\"\n data-tone={tone}\n className={cn(\"matrx-control-badge\", className)}\n title={typeof children === \"string\" ? children : undefined}\n {...props}\n >\n {icon ? (\n <span className=\"matrx-control-badge-icon\" aria-hidden=\"true\">\n {icon}\n </span>\n ) : null}\n <span>{children}</span>\n </span>\n );\n}\n\n/* ------------------------------------------------------------------ */\n/* Chip and ChipSet */\n/* ------------------------------------------------------------------ */\n\n/**\n * The status tones (the Badge's) plus a FIXED set of categorical hues, each a\n * token pair in `controls.css` (`--matrx-chip-<hue>`, stepped for dark). A\n * feature maps its kinds onto these through ONE table of its own\n * (`kind → ChipTone`) — never a class string.\n */\nexport type ChipHue =\n | \"sky\"\n | \"blue\"\n | \"indigo\"\n | \"violet\"\n | \"fuchsia\"\n | \"rose\"\n | \"orange\"\n | \"amber\"\n | \"lime\"\n | \"emerald\"\n | \"teal\"\n | \"cyan\"\n | \"slate\";\nexport type ChipTone = BadgeTone | ChipHue;\n\n/** Every tone a chip accepts, in a fixed order (tests, pickers, demos). */\nexport const CHIP_TONES: readonly ChipTone[] = [\n \"neutral\",\n \"primary\",\n \"success\",\n \"warning\",\n \"destructive\",\n \"info\",\n \"sky\",\n \"blue\",\n \"indigo\",\n \"violet\",\n \"fuchsia\",\n \"rose\",\n \"orange\",\n \"amber\",\n \"lime\",\n \"emerald\",\n \"teal\",\n \"cyan\",\n \"slate\",\n] as const;\n\nexport interface ChipProps extends Omit<React.HTMLAttributes<HTMLSpanElement>, \"children\"> {\n /** The one line of text. Truncates; the full text is the tooltip. */\n label: string;\n /** `item` (default): an existing thing, tinted. `add`: a suggestion to make\n * one — dashed, quiet, with the package's own leading `+`. */\n variant?: \"item\" | \"add\";\n /** A named tone, never a class. Default `neutral`. Ignored by `add`. */\n tone?: ChipTone;\n /** Leading glyph (drawn 14px, optically trimmed). */\n icon?: React.ReactNode;\n /** Put the chip's skin on the one child element (a link or a button); the\n * child carries no children of its own — the chip draws glyph + label. */\n asChild?: boolean;\n /**\n * A FILTER chip (a toggle in a set of choices): `true` is on — tinted in its\n * `tone` (default `primary`); `false` is off — untinted outline, quiet ink.\n * Sets `aria-pressed`. Use with `asChild` on a `<button>`. Omit for a tag.\n */\n pressed?: boolean;\n children?: React.ReactElement;\n}\n\n/**\n * THE chip: a tag that names a thing (a format, a kind, a status, a source).\n * ONE 24px height, one 6px radius, one 12px/500 label, 14px glyph, matched\n * insets, single line with an ellipsis and a tooltip, and the controls' 3px\n * half-gap of its own so a `ChipSet` adds none. Geometry and tint are locked\n * in `controls.css`; a call site may place it, never restyle it.\n */\nexport const Chip = React.forwardRef<HTMLSpanElement, ChipProps>(\n ({ label, variant = \"item\", tone, icon, asChild = false, pressed, children, className, title, ...props }, ref) => {\n const Component = asChild ? Slot : \"span\";\n const glyph = variant === \"add\" ? <PlusIcon className=\"lucide lucide-plus\" /> : icon;\n const toggle = pressed !== undefined && variant === \"item\";\n const resolvedTone = tone ?? (toggle ? \"primary\" : \"neutral\");\n return (\n <Component\n ref={ref}\n data-matrx-control=\"chip\"\n data-variant={variant}\n data-tone={variant === \"add\" ? undefined : resolvedTone}\n data-pressed={toggle ? String(pressed) : undefined}\n aria-pressed={toggle ? pressed : undefined}\n data-glyph={glyph ? (variant === \"add\" && icon ? \"both\" : \"start\") : undefined}\n className={cn(\"matrx-control-chip matrx-glyph-trim\", className)}\n title={title ?? label}\n {...props}\n >\n {glyph}\n {variant === \"add\" ? icon : null}\n {asChild ? <Slottable>{children}</Slottable> : null}\n <span className=\"matrx-control-chip-label\">{label}</span>\n </Component>\n );\n },\n);\nChip.displayName = \"Chip\";\n\nexport interface ChipSetProps extends React.HTMLAttributes<HTMLDivElement> {\n /**\n * `flow` (default): chips sit at their own width and wrap.\n * `grid`: every chip is the same width (auto-filled columns of at least\n * 7.5rem), labels truncate — for a SET of siblings (a kit's formats).\n */\n layout?: \"flow\" | \"grid\";\n}\n\n/** A set of chips: same height, one baseline, the chips space themselves. */\nexport const ChipSet = React.forwardRef<HTMLDivElement, ChipSetProps>(\n ({ layout = \"flow\", className, ...props }, ref) => (\n <div\n ref={ref}\n data-matrx-control=\"chip-set\"\n data-layout={layout}\n className={cn(\"matrx-control-chip-set\", className)}\n {...props}\n />\n ),\n);\nChipSet.displayName = \"ChipSet\";\n\n/* ------------------------------------------------------------------ */\n/* Switch and Textarea */\n/* ------------------------------------------------------------------ */\n\nexport type SwitchProps = Omit<React.ComponentPropsWithoutRef<typeof SwitchPrimitives.Root>, \"children\">;\n\n/** A 20px track in the 28px control box, so it lines up with every control. */\nexport const Switch = React.forwardRef<React.ComponentRef<typeof SwitchPrimitives.Root>, SwitchProps>(\n ({ className, ...props }, ref) => (\n <SwitchPrimitives.Root\n ref={ref}\n data-matrx-control=\"switch\"\n className={cn(\"matrx-control matrx-control-switch\", className)}\n {...props}\n >\n <span className=\"matrx-control-switch-track\">\n <SwitchPrimitives.Thumb className=\"matrx-control-switch-thumb\" />\n </span>\n </SwitchPrimitives.Root>\n ),\n);\nSwitch.displayName = \"Switch\";\n\nexport interface TextareaProps extends React.TextareaHTMLAttributes<HTMLTextAreaElement> {\n /** The roomy writing surface used by inviting prompt boxes. */\n hero?: boolean;\n /** Join a pinned status row below this field from the small breakpoint upward. */\n joinedBottom?: boolean;\n /** `field` (default): the field skin. `bare`: the surrounding surface draws the frame (a\n * composer) — no border, no fill, no inset, no focus ring of its own. */\n variant?: \"field\" | \"bare\";\n /** Monospace text — code, JSON, keys. */\n mono?: boolean;\n /** Grow with the content (stopping at `maxHeight`, then scroll). */\n autoGrow?: boolean;\n /** Minimum height in px (a writing area that must start tall). `rows` also sizes it. */\n minHeight?: number;\n /** Maximum height in px; past it the field scrolls. */\n maxHeight?: number;\n /** Space occupied by an overlaid control cluster, so editable text stays clear of it. */\n reservedInlineEnd?: number;\n /** Space occupied by an overlaid row of controls at the bottom of the writing area. */\n reservedBlockEnd?: number;\n}\n\n/**\n * The field skin, multi-line (8px radius — a capsule cannot hold paragraphs). Height is the\n * textarea's own business — `rows`, `minHeight`/`maxHeight`, `autoGrow`, `resize` — never a class.\n */\nexport const Textarea = React.forwardRef<HTMLTextAreaElement, TextareaProps>(\n ({ className, style, variant = \"field\", mono, hero, joinedBottom, autoGrow, minHeight, maxHeight, reservedInlineEnd, reservedBlockEnd, ...props }, forwarded) => {\n const { ref, callback } = useMergedTextareaRef(forwarded);\n useAutoGrow(ref, props.value, autoGrow, minHeight, maxHeight);\n return (\n <textarea\n ref={callback}\n data-matrx-control=\"textarea\"\n data-variant={variant === \"bare\" ? \"bare\" : undefined}\n data-mono={mono ? \"\" : undefined}\n data-hero={hero ? \"\" : undefined}\n data-joined-bottom={joinedBottom ? \"\" : undefined}\n className={cn(\"matrx-control-textarea\", className)}\n style={{ ...boxStyle(minHeight, maxHeight), ...style,\n ...(reservedInlineEnd === undefined ? {} : { \"--matrx-textarea-reserved-inline-end\": `${Math.max(0, reservedInlineEnd)}px` }),\n ...(reservedBlockEnd === undefined ? {} : { \"--matrx-textarea-reserved-block-end\": `${Math.max(0, reservedBlockEnd)}px` }),\n } as React.CSSProperties}\n {...props}\n />\n );\n },\n);\nTextarea.displayName = \"Textarea\";\n","/**\n * THE ONE FIELD SURFACE (page-pass shared fix, 2026-09-27).\n *\n * Every control a person types into or picks from — Input, BasicInput,\n * Textarea, the Select trigger, and the host's ProInput / ProTextarea — sits on\n * this fill and this border. They used to disagree: Input and the elevated\n * Textarea filled with `bg-background` (the gray page color in light mode),\n * BasicInput and the control Textarea were `bg-transparent` (gray on a gray\n * page), while the Select trigger filled with `bg-card` (white). On one form\n * the text fields therefore looked disabled beside white Selects\n * (/hr/settings/employer, the message-template editor) — a screen that lies\n * about what it will let you do.\n *\n * The surface is the Select's: the card fill and the regular border. A caller\n * that genuinely wants no fill (an inline cell editor) still passes\n * `bg-transparent`, which wins through `cn`.\n */\nexport const FIELD_SURFACE_CLASS = \"border border-border bg-card\";\n","\"use client\";\n\n/**\n * Textarea — the multi-line twin of the Input family, same three shapes:\n * `Textarea` (elevated), `BasicTextarea` (plain control), and\n * `TextareaWithPrefix`.\n *\n * WHAT THE FORKS PROVED. Three hosts shipped a bare `<textarea>` with a\n * min-height and nothing else; matrx-frontend shipped auto-grow, min/max\n * height clamping, and a stretch-detection pass. That last one is the reason\n * this file is worth having: a `<textarea>` is a REPLACED element, so\n * `className=\"h-full\"` on it does nothing useful unless its parent is also\n * told to stretch — which is why every host that wanted a filling textarea\n * ended up wrapping it by hand at the call site, differently each time.\n * `getStretchClasses` reads the caller's own fill intent out of the className\n * and builds the wrapper for them.\n *\n * COLOR IS TOKENS (C26). The ported original pinned its body text to literal\n * black/white, its placeholder and focus ring to raw palette steps, and its\n * dark elevation to a custom property no host defined — so that shadow\n * computed to nothing. All four now resolve from the semantic vocabulary.\n *\n * AND `shadow-textarea` NOW EXISTS. The original's resting elevation class was\n * `shadow-textarea`, and NO host defined `--shadow-textarea` or generated that\n * utility — 125 call sites asked for an elevation they never got. The package\n * ships the token (defaulting to the Input family's `--shadow-input`, which is\n * plainly what the twin class meant) and the rule, so the class finally does\n * what it says. A host that wants the flat look sets `--shadow-textarea: none`.\n *\n * The clipboard/motion variants matrx-frontend layers on top (CopyTextarea,\n * FancyTextarea) stay host-owned under the C8 split-out law: they drag in\n * `motion/react`, and plain-textarea consumers must not pay for it.\n */\n\nimport * as React from \"react\";\n\nimport { cn } from \"./cn\";\nimport { FIELD_SURFACE_CLASS } from \"./field-surface\";\n\nexport interface TextareaProps\n extends React.TextareaHTMLAttributes<HTMLTextAreaElement> {\n /** Grow to fit content as the user types (and stop growing at `maxHeight`). */\n autoGrow?: boolean;\n /** Minimum height in px. */\n minHeight?: number;\n /** Maximum height in px; past it the field scrolls instead of growing. */\n maxHeight?: number;\n /** Classes for the wrapper this component adds when one is needed. */\n wrapperClassName?: string;\n}\n\nconst FILL_HEIGHT_REGEX = /(?:^|\\s)(h-full|h-dvh|flex-1|grow)(?:\\s|$)/;\nconst FILL_WIDTH_REGEX = /(?:^|\\s)(w-full|w-screen)(?:\\s|$)/;\n\n/**\n * A `<textarea>` cannot fill a box on its own — the box has to be told too.\n * Read the caller's fill intent out of its own className and mirror it onto\n * the wrapper, so `className=\"h-full\"` means what the caller thought it meant.\n */\nfunction getStretchClasses(className?: string): string | undefined {\n if (!className) return undefined;\n const fills: string[] = [];\n if (FILL_HEIGHT_REGEX.test(className)) fills.push(\"h-full min-h-0\");\n if (FILL_WIDTH_REGEX.test(className)) fills.push(\"w-full\");\n return fills.length ? fills.join(\" \") : undefined;\n}\n\nconst TEXTAREA_ELEVATED_CLASS =\n `flex h-auto w-full rounded-md ${FIELD_SURFACE_CLASS} px-3 py-2 text-sm text-foreground shadow-textarea transition duration-400 placeholder:text-muted-foreground focus-visible:outline-none focus-visible:border-primary focus-visible:ring-[3px] focus-visible:ring-primary/15 disabled:cursor-not-allowed disabled:opacity-50`;\n\nconst TEXTAREA_CONTROL_CLASS =\n `flex w-full rounded-md ${FIELD_SURFACE_CLASS} px-3 py-2 text-sm text-foreground shadow-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:border-primary focus-visible:ring-[3px] focus-visible:ring-primary/15 disabled:cursor-not-allowed disabled:opacity-50`;\n\nexport function useAutoGrow(\n ref: React.RefObject<HTMLTextAreaElement | null>,\n value: React.TextareaHTMLAttributes<HTMLTextAreaElement>[\"value\"],\n autoGrow = false,\n minHeight?: number,\n maxHeight?: number,\n): void {\n React.useEffect(() => {\n if (!autoGrow || !ref.current) return;\n\n const textarea = ref.current;\n textarea.style.height = \"auto\";\n\n let newHeight = textarea.scrollHeight;\n if (minHeight) newHeight = Math.max(newHeight, minHeight);\n\n if (maxHeight && newHeight >= maxHeight) {\n textarea.style.height = `${maxHeight}px`;\n textarea.style.overflowY = \"auto\";\n } else {\n textarea.style.height = `${newHeight}px`;\n textarea.style.overflowY = \"hidden\";\n }\n }, [value, autoGrow, minHeight, maxHeight, ref]);\n}\n\n/** Merge a forwarded ref with the internal one auto-grow needs to measure. */\nexport function useMergedTextareaRef(\n forwarded: React.ForwardedRef<HTMLTextAreaElement>,\n): {\n ref: React.RefObject<HTMLTextAreaElement | null>;\n callback: (node: HTMLTextAreaElement | null) => void;\n} {\n const internal = React.useRef<HTMLTextAreaElement | null>(null);\n const callback = React.useCallback(\n (node: HTMLTextAreaElement | null) => {\n internal.current = node;\n if (typeof forwarded === \"function\") forwarded(node);\n else if (forwarded) forwarded.current = node;\n },\n [forwarded],\n );\n return { ref: internal, callback };\n}\n\nexport function boxStyle(\n minHeight?: number,\n maxHeight?: number,\n): React.CSSProperties | undefined {\n if (minHeight === undefined && maxHeight === undefined) return undefined;\n return {\n minHeight: minHeight ? `${minHeight}px` : undefined,\n maxHeight: maxHeight ? `${maxHeight}px` : undefined,\n };\n}\n\n/** The elevated textarea — the Input family's `Input`, in multi-line form. */\nconst Textarea = React.forwardRef<HTMLTextAreaElement, TextareaProps>(\n (\n { className, autoGrow, minHeight, maxHeight, wrapperClassName, ...props },\n forwarded,\n ) => {\n const { ref, callback } = useMergedTextareaRef(forwarded);\n const stretchClasses = getStretchClasses(className);\n const needsWrapper = Boolean(wrapperClassName || stretchClasses);\n\n useAutoGrow(ref, props.value, autoGrow, minHeight, maxHeight);\n\n const textarea = (\n <textarea\n ref={callback}\n data-slot=\"textarea\"\n className={cn(\n TEXTAREA_ELEVATED_CLASS,\n autoGrow && \"resize-none\",\n stretchClasses,\n className,\n )}\n style={boxStyle(minHeight, maxHeight)}\n {...props}\n />\n );\n\n if (!needsWrapper) return textarea;\n\n return <div className={cn(stretchClasses, wrapperClassName)}>{textarea}</div>;\n },\n);\nTextarea.displayName = \"Textarea\";\n\n/**\n * The plain control — a bordered, transparent field with a 60px floor. This is\n * what matrx-extend, aidream/apps/dashboard and workflow-studio each called\n * `Textarea`; the floor is theirs and it is the sensible default (a one-line\n * box for multi-line content invites a scrollbar on the first Enter).\n */\nconst BasicTextarea = React.forwardRef<HTMLTextAreaElement, TextareaProps>(\n ({ className, autoGrow, minHeight, maxHeight, ...props }, forwarded) => {\n const { ref, callback } = useMergedTextareaRef(forwarded);\n\n useAutoGrow(ref, props.value, autoGrow, minHeight, maxHeight);\n\n return (\n <textarea\n ref={callback}\n data-slot=\"textarea\"\n className={cn(\n TEXTAREA_CONTROL_CLASS,\n \"h-auto min-h-[60px]\",\n autoGrow && \"resize-none\",\n className,\n )}\n style={boxStyle(minHeight, maxHeight)}\n {...props}\n />\n );\n },\n);\nBasicTextarea.displayName = \"BasicTextarea\";\n\nexport interface TextareaWithPrefixProps extends Omit<TextareaProps, \"prefix\"> {\n /** Leading adornment, absolutely placed at the field's top-left. */\n prefix?: React.ReactNode;\n}\n\nconst TextareaWithPrefix = React.forwardRef<\n HTMLTextAreaElement,\n TextareaWithPrefixProps\n>(\n (\n {\n prefix,\n className,\n wrapperClassName,\n autoGrow,\n minHeight,\n maxHeight,\n ...props\n },\n forwarded,\n ) => {\n const { ref, callback } = useMergedTextareaRef(forwarded);\n\n useAutoGrow(ref, props.value, autoGrow, minHeight, maxHeight);\n\n return (\n <div\n className={cn(\"relative\", getStretchClasses(className), wrapperClassName)}\n >\n {prefix ? (\n <div className=\"pointer-events-none absolute left-3 top-3 z-10 text-muted-foreground\">\n {prefix}\n </div>\n ) : null}\n <textarea\n ref={callback}\n data-slot=\"textarea\"\n className={cn(\n TEXTAREA_CONTROL_CLASS,\n \"resize-y\",\n prefix && \"pl-10\",\n autoGrow && \"resize-none\",\n className,\n )}\n style={boxStyle(minHeight, maxHeight)}\n {...props}\n />\n </div>\n );\n },\n);\nTextareaWithPrefix.displayName = \"TextareaWithPrefix\";\n\nexport { BasicTextarea, Textarea, TextareaWithPrefix };\n","\"use client\";\n\n/**\n * The field-owned voice chrome every writing field shares: the live \"Listening…\" strip, the\n * \"Finalizing…\" strip and the close-protection dialog. The recorder itself is the host's\n * (`useVoice` port); these only draw its state.\n */\nimport * as React from \"react\";\nimport { cn } from \"../cn\";\nimport { Tile } from \"../controls/surfaces\";\nimport { CheckIcon, Loader2Icon } from \"../icons\";\nimport {\n AlertDialog,\n AlertDialogAction,\n AlertDialogCancel,\n AlertDialogContent,\n AlertDialogDescription,\n AlertDialogFooter,\n AlertDialogHeader,\n AlertDialogTitle,\n} from \"../alert-dialog\";\nimport type { WritingFieldVoice } from \"./add-ons\";\n\nexport function ListeningStrip({ liveTranscript, className }: { liveTranscript: string; className?: string }) {\n return (\n <div className={cn(\"absolute flex items-center gap-1.5 px-2 py-1 rounded-md\", className)}>\n <span aria-hidden className=\"w-2 h-2 bg-primary rounded-full flex-shrink-0 animate-pulse\" />\n <span className=\"type-secondary text-primary font-medium truncate\">\n {liveTranscript ? liveTranscript.slice(-60) : \"Listening...\"}\n </span>\n </div>\n );\n}\n\nexport function FinalizingStrip({ className }: { className?: string }) {\n return (\n <div\n className={cn(\n \"absolute flex items-center gap-1.5 px-2 py-1 rounded-md bg-blue-100 dark:bg-blue-900/30\",\n className,\n )}\n >\n <Loader2Icon className=\"w-3 h-3 animate-spin text-blue-600 dark:text-blue-400\" />\n <span className=\"type-secondary text-blue-600 dark:text-blue-400 font-medium\">Finalizing...</span>\n </div>\n );\n}\n\n/** Warns before a field closes while a recording or transcription is in flight. */\nexport function VoiceProtectionDialog({ voice }: { voice: WritingFieldVoice }) {\n const { isRecording, isTranscribing } = voice;\n const busy = isRecording || isTranscribing;\n return (\n <AlertDialog open={voice.showProtectionDialog} onOpenChange={voice.setShowProtectionDialog}>\n <AlertDialogContent>\n <AlertDialogHeader>\n <div className=\"flex items-center gap-3 mb-2\">\n {busy ? (\n <>\n <Loader2Icon className=\"h-5 w-5 animate-spin text-blue-500\" />\n <AlertDialogTitle>\n {isRecording ? \"Recording in Progress\" : \"Transcription in Progress\"}\n </AlertDialogTitle>\n </>\n ) : (\n <>\n <CheckIcon className=\"h-5 w-5 text-green-500\" />\n <AlertDialogTitle>Voice Input Complete</AlertDialogTitle>\n </>\n )}\n </div>\n <AlertDialogDescription>\n {isRecording\n ? \"Your voice is currently being recorded. If you close now, the recording will be stopped and lost.\"\n : isTranscribing\n ? \"Your voice recording is currently being transcribed. If you close now, the transcription will be lost.\"\n : \"Your voice input has been processed successfully! You can now safely close this panel.\"}\n </AlertDialogDescription>\n </AlertDialogHeader>\n <AlertDialogFooter>\n {busy ? (\n <>\n <AlertDialogCancel onClick={voice.cancelClose}>Cancel & Wait</AlertDialogCancel>\n <AlertDialogAction\n onClick={voice.confirmClose}\n className=\"bg-destructive text-destructive-foreground hover:bg-destructive/90\"\n >\n {isRecording ? \"Stop Recording\" : \"End Transcription\"}\n </AlertDialogAction>\n </>\n ) : (\n <AlertDialogAction onClick={voice.confirmClose}>Close</AlertDialogAction>\n )}\n </AlertDialogFooter>\n </AlertDialogContent>\n </AlertDialog>\n );\n}\n\n/** A menu row in the field's own part of \"…\" (Expand, Voice input, Audio settings, Clear). */\nexport function FieldMenuRow({\n icon,\n children,\n onClick,\n disabled,\n}: {\n icon: React.ReactNode;\n children: React.ReactNode;\n onClick: () => void;\n disabled?: boolean;\n}) {\n return (\n <Tile\n type=\"button\"\n disabled={disabled}\n onClick={onClick}\n variant=\"quiet\"\n className=\"w-full\"\n icon={icon}\n title={children}\n />\n );\n}\n\n/** The mic button a host without a voice port would get — never drawn: no port, no microphone. */\nexport function micAriaLabel(isRecording: boolean, label?: string): string {\n if (isRecording) return label ? `Stop recording for ${label}` : \"Stop recording\";\n return label ? `Start voice input for ${label}` : \"Start voice input\";\n}\n","\"use client\";\n\n/**\n * ProInput — THE one-line box a person writes words in (titles, names, short replies). Moved from\n * matrx-frontend `components/official/ProInput.tsx` (2026-10-22); its recorder, read-aloud, Copy\n * and Clean up arrive through the add-on ports (`./add-ons.tsx`).\n *\n * Built in: submit (`onSubmit`, ⌘/Ctrl+Enter, `submitOnEnter`), field navigation (`onEnterKey`),\n * Clear (`clearable` + `onClear`), `startIcon`, the iOS zoom guard (value text 16px), floating\n * label, the ONE fitting rule (`./control-fit.ts`), and the measured right padding that keeps the\n * hover cluster off the text (`./reserved-padding.ts`; a narrow field reveals it on focus).\n */\nimport * as React from \"react\";\nimport { useMediaQuery } from \"@ai-matrx/kit/media-query\";\nimport { cn } from \"../cn\";\nimport { Label } from \"../label\";\nimport { Field } from \"../controls/controls\";\nimport { Popover, PopoverContent, PopoverTrigger } from \"../popover\";\nimport {\n CheckTapButton,\n LoadingTapButton,\n MoreHorizontalTapButton,\n SendTapButton,\n XTapButton,\n} from \"../tap-target/tap-buttons\";\nimport { MicIcon, SlidersHorizontalIcon, XIcon } from \"../icons\";\nimport { UNCONFIGURED } from \"../stand-in-notice\";\nimport { PRO_INPUT_TEXT_GAP_PX, hoverRevealsCluster, reservedRightPaddingPx } from \"./reserved-padding\";\nimport { controlSizes, fitFieldControls, isDenseField } from \"./control-fit\";\nimport { resolveHookPorts, splitAddOnProps, useWritingFieldAddOns, type WritingFieldApi } from \"./add-ons\";\nimport { FieldMenuRow, FinalizingStrip, VoiceProtectionDialog, micAriaLabel } from \"./voice-chrome\";\nimport { StandInMenu } from \"./pro-textarea\";\nimport type { ProInputAddOnProps } from \"./index\";\n\n/** Real HTMLInputElement with optional expando methods set by ProInput. */\nexport interface ProInputElement extends HTMLInputElement {\n requestClose?: () => void;\n isTranscribing?: () => boolean;\n}\n\nexport interface ProInputProps extends React.InputHTMLAttributes<HTMLInputElement>, ProInputAddOnProps {\n onTranscriptionComplete?: (text: string) => void;\n onTranscriptionError?: (error: string) => void;\n /** If true, appends to existing text; if false, replaces. Default: true. */\n appendTranscript?: boolean;\n wrapperClassName?: string;\n onRequestClose?: () => void;\n /** Warn before unmount during recording/transcription. Default: true. */\n protectTranscription?: boolean;\n /** Show the Copy action inside the \"…\" menu. Default: true. */\n showCopyButton?: boolean;\n /** Voice input. Default true; false for search bars and filters. */\n enableVoice?: boolean;\n onSubmit?: () => void;\n submitDisabled?: boolean;\n isSubmitting?: boolean;\n /** Accessible/tooltip label for the submit button. Default: \"Send\". */\n submitLabel?: string;\n submitOnCmdEnter?: boolean;\n submitOnEnter?: boolean;\n /** Field-navigation mode: plain Enter calls this instead of submitting. */\n onEnterKey?: (e: React.KeyboardEvent<HTMLInputElement>) => void;\n auxiliaryControlsTabIndex?: number;\n auxiliaryControlsLabel?: string;\n /** Optional leading icon/node — auto-applies left padding. */\n startIcon?: React.ReactNode;\n /** Shows a clear (×) control while the field has content. */\n clearable?: boolean;\n /** Called when the clear control is pressed. Defaults to clearing via `onChange`. */\n onClear?: () => void;\n /** Dense-form label inside the border (use only on a `bg-card` surface). */\n floatingLabel?: string;\n}\n\nconst joinWithSpace = (base: string, text: string) => `${base}${base.endsWith(\" \") ? \"\" : \" \"}${text}`;\n\nexport const ProInput = React.forwardRef<HTMLInputElement, ProInputProps>(\n (\n {\n className,\n wrapperClassName,\n onTranscriptionComplete,\n onTranscriptionError,\n appendTranscript = true,\n value,\n onChange,\n onKeyDown,\n disabled,\n onRequestClose,\n protectTranscription = true,\n showCopyButton = true,\n enableVoice = true,\n onSubmit,\n submitDisabled,\n isSubmitting = false,\n submitLabel = \"Send\",\n submitOnCmdEnter,\n submitOnEnter = false,\n onEnterKey,\n auxiliaryControlsTabIndex,\n auxiliaryControlsLabel,\n startIcon,\n clearable = false,\n onClear,\n floatingLabel,\n id: idProp,\n placeholder,\n type = \"text\",\n ...rest\n },\n ref,\n ) => {\n const addOns = useWritingFieldAddOns();\n const ports = resolveHookPorts(addOns);\n const { dom: props, addOnProps } = splitAddOnProps(rest as Record<string, unknown>, addOns.propNames) as {\n dom: React.InputHTMLAttributes<HTMLInputElement>;\n addOnProps: Record<string, unknown>;\n };\n const generatedId = React.useId();\n // Field owns its geometry; the legacy native size attribute must not become a skin.\n const { size: _nativeSize, width: nativeWidth, style: nativeStyle, ...fieldProps } = props;\n const inputId = idProp ?? (floatingLabel ? generatedId : undefined);\n const [hasCopied, setHasCopied] = React.useState(false);\n const [menuOpen, setMenuOpen] = React.useState(false);\n const [isFocused, setIsFocused] = React.useState(false);\n const [isHovered, setIsHovered] = React.useState(false);\n const internalRef = React.useRef<HTMLInputElement | null>(null);\n const clusterRef = React.useRef<HTMLDivElement | null>(null);\n const auxRef = React.useRef<HTMLDivElement>(null);\n const [clusterWidths, setClusterWidths] = React.useState({ cluster: 0, aux: 0 });\n const [inputWidth, setInputWidth] = React.useState(0);\n const [inputHeight, setInputHeight] = React.useState(0);\n const coarsePointer = useMediaQuery(\"(pointer: coarse)\");\n const clusterObserver = React.useRef<ResizeObserver | null>(null);\n // Stable, so React re-runs it only when the node changes (a new function each render re-measured in\n // every commit, which loops when the measured size moves with the field's own controls).\n const setClusterNode = React.useCallback((cluster: HTMLDivElement | null) => {\n if (clusterRef.current === cluster) return;\n clusterRef.current = cluster;\n clusterObserver.current?.disconnect();\n clusterObserver.current = null;\n if (!cluster || typeof ResizeObserver === \"undefined\") return;\n const measure = () => {\n const next = {\n cluster: cluster.getBoundingClientRect().width,\n aux: auxRef.current?.getBoundingClientRect().width ?? 0,\n };\n setClusterWidths((prev) => (prev.cluster === next.cluster && prev.aux === next.aux ? prev : next));\n };\n measure();\n clusterObserver.current = new ResizeObserver(measure);\n clusterObserver.current.observe(cluster);\n if (auxRef.current) clusterObserver.current.observe(auxRef.current);\n }, []);\n const inputRef = internalRef;\n const inputObserver = React.useRef<ResizeObserver | null>(null);\n // A merged CALLBACK ref: the host gets the element AND the field still measures that element.\n // Stable, so React re-runs it only when the node changes (a new function each render re-measured in\n // every commit, which loops when the measured size moves with the field's own controls).\n const setInputRef = React.useCallback((node: HTMLInputElement | null) => {\n if (internalRef.current !== node) {\n inputObserver.current?.disconnect();\n inputObserver.current = null;\n if (node && typeof ResizeObserver !== \"undefined\") {\n const measure = () => {\n const rect = node.getBoundingClientRect();\n setInputWidth(rect.width);\n setInputHeight(rect.height);\n };\n measure();\n inputObserver.current = new ResizeObserver(measure);\n inputObserver.current.observe(node);\n }\n }\n internalRef.current = node;\n if (typeof ref === \"function\") ref(node);\n else if (ref) (ref as React.MutableRefObject<HTMLInputElement | null>).current = node;\n }, [ref]);\n // THE PRE-HYDRATION KEEP (see ProTextarea).\n const keepPreHydrationText = React.useEffectEvent(() => {\n const el = inputRef.current;\n if (!el || !onChange) return;\n const typed = el.value;\n if (!typed || typed === String(value ?? \"\")) return;\n el.value = \"\";\n Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype, \"value\")?.set?.call(el, typed);\n el.dispatchEvent(new Event(\"input\", { bubbles: true }));\n });\n React.useLayoutEffect(() => {\n keepPreHydrationText();\n }, []);\n React.useEffect(\n () => () => {\n clusterObserver.current?.disconnect();\n inputObserver.current?.disconnect();\n },\n [],\n );\n const openAudioSettings = ports.useOpenAudioSettings();\n\n const pushToInput = React.useCallback((newValue: string): boolean => {\n const el = inputRef.current;\n if (!el) return false;\n const setter = Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype, \"value\")?.set;\n if (!setter) return false;\n setter.call(el, newValue);\n el.dispatchEvent(new Event(\"input\", { bubbles: true }));\n return el.value === newValue;\n }, []);\n\n const getLiveText = React.useCallback(() => inputRef.current?.value ?? String(value ?? \"\"), [value]);\n const voice = ports.useVoice({\n enabled: enableVoice,\n instanceId: inputId,\n getValue: getLiveText,\n writeValue: pushToInput,\n appendTranscript,\n join: joinWithSpace,\n protect: protectTranscription,\n onRequestClose,\n onTranscriptionComplete,\n onTranscriptionError,\n });\n const { isRecording, isTranscribing } = voice;\n const isAudioAvailable = voice.microphone;\n\n React.useEffect(() => {\n const el = inputRef.current as ProInputElement | null;\n if (!el) return;\n el.requestClose = voice.requestClose;\n el.isTranscribing = () => isTranscribing;\n }, [voice.requestClose, isTranscribing]);\n\n const flashCopied = React.useCallback(() => {\n setHasCopied(true);\n setTimeout(() => setHasCopied(false), 450);\n }, []);\n\n const handleClear = React.useCallback(() => {\n if (onClear) {\n onClear();\n return;\n }\n pushToInput(\"\");\n onChange?.({ target: { value: \"\" } } as React.ChangeEvent<HTMLInputElement>);\n }, [onClear, pushToInput, onChange]);\n\n const valueAsString = String(value ?? \"\");\n const hasContent = valueAsString.trim().length > 0;\n const canSubmit = !!onSubmit && hasContent && !submitDisabled && !isSubmitting && !disabled;\n const cmdEnterEnabled = submitOnCmdEnter ?? !!onSubmit;\n const triggerSubmit = React.useCallback(() => {\n if (canSubmit && onSubmit) onSubmit();\n }, [canSubmit, onSubmit]);\n\n const handleKeyDown = React.useCallback(\n (e: React.KeyboardEvent<HTMLInputElement>) => {\n if (isHovered) setIsHovered(false);\n onKeyDown?.(e);\n if (e.defaultPrevented || e.key !== \"Enter\") return;\n const withCmd = e.metaKey || e.ctrlKey;\n if (onEnterKey) {\n if (e.shiftKey || withCmd) return;\n e.preventDefault();\n onEnterKey(e);\n return;\n }\n if (!onSubmit) return;\n if (cmdEnterEnabled && withCmd) {\n e.preventDefault();\n triggerSubmit();\n return;\n }\n if (submitOnEnter && !e.shiftKey && !withCmd) {\n e.preventDefault();\n triggerSubmit();\n }\n },\n [isHovered, onKeyDown, onEnterKey, onSubmit, cmdEnterEnabled, submitOnEnter, triggerSubmit],\n );\n\n const fieldApi: WritingFieldApi = {\n kind: \"input\",\n text: valueAsString,\n getText: getLiveText,\n write: pushToInput,\n getSelection: () => ({\n start: inputRef.current?.selectionStart ?? 0,\n end: inputRef.current?.selectionEnd ?? 0,\n }),\n getElement: () => inputRef.current,\n addOnProps: { ...addOnProps, type },\n showCopyButton,\n flashCopied,\n };\n\n const pointerReveals = hoverRevealsCluster(inputWidth) ? isHovered : isFocused;\n const showHoverControls = (pointerReveals || isRecording || isTranscribing) && !disabled;\n const isVoiceDisabled = !isAudioAvailable || disabled || (isTranscribing && !isRecording);\n const showMic = enableVoice && isAudioAvailable;\n const showClear = clearable && hasContent;\n const addOnMenuItems = addOns.Menu\n ? (addOns.menuHasItems?.({ kind: \"input\", addOnProps: fieldApi.addOnProps, showCopyButton }) ?? true)\n : false;\n const denseField = isDenseField(inputHeight);\n const fit = fitFieldControls({\n fieldWidth: inputWidth,\n sizes: controlSizes({ coarse: coarsePointer, dense: denseField }),\n fixedPx: (startIcon ? 36 : 12) + PRO_INPUT_TEXT_GAP_PX,\n hasSubmit: !!onSubmit,\n menuHasOwnItems: !disabled && (showCopyButton || addOnMenuItems || hasContent),\n mic: showMic,\n clear: showClear,\n expand: false,\n });\n const voiceBusy = isRecording || isTranscribing;\n const showMicInline = showMic && (fit.mic === \"inline\" || voiceBusy);\n const voiceInMenu = showMic && !showMicInline;\n const clearInline = showClear && fit.clearInline;\n const clearInMenu = showClear && !fit.clearInline;\n const showMenu = !disabled && (showCopyButton || addOnMenuItems || voiceInMenu || clearInMenu || hasContent);\n const audioSettingsInMenu = showMenu && enableVoice;\n const auxVisible = (showHoverControls || menuOpen) && (showMicInline || showMenu);\n const measuredRightPadding = reservedRightPaddingPx({\n clusterWidth: clusterWidths.cluster,\n auxWidth: clusterWidths.aux,\n auxVisible,\n });\n const isInvalid = props[\"aria-invalid\"] === true || props[\"aria-invalid\"] === \"true\";\n const labelFloated = isFocused || valueAsString.length > 0;\n const showVoiceStatus = isRecording || (isTranscribing && !isRecording);\n const closeMenu = () => setMenuOpen(false);\n\n const ownRows = (\n <>\n {clearInMenu ? (\n <FieldMenuRow\n icon={<XIcon />}\n onClick={() => {\n closeMenu();\n handleClear();\n }}\n >\n Clear\n </FieldMenuRow>\n ) : null}\n {voiceInMenu ? (\n <FieldMenuRow\n icon={<MicIcon />}\n disabled={isVoiceDisabled}\n onClick={() => {\n closeMenu();\n void voice.handleVoiceClick();\n }}\n >\n Voice input\n </FieldMenuRow>\n ) : null}\n {audioSettingsInMenu ? (\n <FieldMenuRow\n icon={<SlidersHorizontalIcon />}\n onClick={() => {\n closeMenu();\n openAudioSettings();\n }}\n >\n Audio settings\n </FieldMenuRow>\n ) : null}\n {clearInMenu || voiceInMenu || audioSettingsInMenu ? (\n <div className=\"my-1 h-px bg-border\" role=\"separator\" />\n ) : null}\n </>\n );\n const Menu = addOns.Menu;\n\n return (\n <div\n className={cn(\"relative group\", wrapperClassName)}\n data-writing-field-host={addOns.Menu && addOns.useVoice ? undefined : UNCONFIGURED}\n onMouseEnter={() => setIsHovered(true)}\n onMouseMove={() => {\n if (!isHovered) setIsHovered(true);\n }}\n onMouseLeave={() => setIsHovered(false)}\n >\n <Field\n ref={setInputRef}\n id={inputId}\n type={type}\n placeholder={floatingLabel ? undefined : placeholder}\n className={cn(\"w-full\", className)}\n style={{ ...(nativeWidth === undefined ? {} : { width: nativeWidth }), ...nativeStyle }}\n icon={startIcon}\n end={<span aria-hidden=\"true\" style={{ width: measuredRightPadding === null ? `calc(${Number(!!onSubmit) + Number(clearInline)} * (var(--matrx-tap-pill-size) + var(--matrx-tap-gap)))` : Math.max(0, measuredRightPadding - 12), flexShrink: 0 }} />}\n value={value}\n onChange={onChange}\n onFocus={() => setIsFocused(true)}\n onBlur={() => setIsFocused(false)}\n onKeyDown={handleKeyDown}\n disabled={disabled}\n {...fieldProps}\n />\n {floatingLabel && inputId && (\n <Label\n htmlFor={inputId}\n className={cn(\n \"absolute left-3 px-1 pointer-events-none transition-all duration-200 ease-in-out z-10 bg-card\",\n labelFloated ? \"-top-2 text-xs\" : \"top-2 text-sm\",\n isInvalid ? \"text-destructive\" : isFocused ? \"text-primary\" : \"text-muted-foreground\",\n disabled && \"text-disabled-foreground\",\n )}\n >\n {floatingLabel}\n </Label>\n )}\n {/* A GLASS PLANE (tap-target placement rule 1); a press here never takes focus from the field. */}\n <div\n ref={setClusterNode}\n onMouseDown={(e) => e.preventDefault()}\n data-matrx-glass-plane\n data-matrx-tap-dense={denseField ? \"\" : undefined}\n className=\"absolute right-0 top-1/2 -translate-y-1/2 flex items-center z-10\"\n >\n <div\n ref={auxRef}\n className={cn(\n \"flex items-center transition-opacity duration-200\",\n showHoverControls || menuOpen ? \"opacity-100\" : \"opacity-0 pointer-events-none\",\n )}\n >\n {showMicInline && addOns.MicButton ? (\n <addOns.MicButton\n dense={denseField}\n tabIndex={auxiliaryControlsTabIndex}\n onMicClick={() => void voice.handleVoiceClick()}\n disabled={isVoiceDisabled}\n isRecording={isRecording}\n isTranscribing={isTranscribing}\n audioLevel={voice.audioLevel}\n micAriaLabel={micAriaLabel(isRecording, auxiliaryControlsLabel)}\n />\n ) : null}\n {showMenu && (\n <Popover open={menuOpen} onOpenChange={setMenuOpen}>\n <PopoverTrigger asChild>\n {hasCopied ? (\n <CheckTapButton\n tabIndex={auxiliaryControlsTabIndex}\n variant=\"transparent\"\n ariaLabel={auxiliaryControlsLabel ? `Copied ${auxiliaryControlsLabel}` : \"Copied\"}\n tooltip=\"Copied\"\n className=\"text-green-500\"\n />\n ) : (\n <MoreHorizontalTapButton\n tabIndex={auxiliaryControlsTabIndex}\n variant=\"transparent\"\n ariaLabel={auxiliaryControlsLabel ? `More options for ${auxiliaryControlsLabel}` : \"More options\"}\n tooltip=\"More\"\n className=\"text-muted-foreground\"\n />\n )}\n </PopoverTrigger>\n <PopoverContent\n /* sizing: fixed — the add-on body sizes itself (short list vs. cleanup panel) */\n align=\"end\"\n side=\"bottom\"\n sideOffset={6}\n className=\"w-auto max-w-none p-0\"\n onOpenAutoFocus={(e) => e.preventDefault()}\n >\n {Menu ? (\n <Menu field={fieldApi} ownRows={ownRows} trailingRows={null} close={closeMenu} />\n ) : (\n <StandInMenu field={fieldApi} ownRows={ownRows} trailingRows={null} close={closeMenu} registry />\n )}\n </PopoverContent>\n </Popover>\n )}\n </div>\n {clearInline && (\n <XTapButton\n variant=\"transparent\"\n onClick={handleClear}\n ariaLabel=\"Clear\"\n tooltip=\"Clear\"\n className=\"text-muted-foreground\"\n />\n )}\n {onSubmit &&\n (isSubmitting ? (\n <LoadingTapButton variant=\"transparent\" ariaLabel={submitLabel} tooltip={submitLabel} className=\"text-primary\" />\n ) : (\n <SendTapButton\n variant=\"transparent\"\n onClick={triggerSubmit}\n disabled={!canSubmit}\n ariaLabel={submitLabel}\n tooltip={submitLabel}\n className={canSubmit ? \"text-primary\" : \"text-muted-foreground\"}\n />\n ))}\n </div>\n {showVoiceStatus && (\n <div className=\"absolute left-0 top-full mt-1 flex items-center gap-1.5 px-2 py-1 rounded-md max-w-full\">\n {isRecording ? (\n <div className=\"relative flex items-center gap-1.5 px-2 py-1 bg-primary/10 dark:bg-primary/15 rounded-md max-w-full\">\n <span aria-hidden className=\"w-2 h-2 bg-primary rounded-full flex-shrink-0 animate-pulse\" />\n <span className=\"type-secondary text-primary font-medium truncate\">\n {voice.liveTranscript ? voice.liveTranscript.slice(-60) : \"Listening...\"}\n </span>\n </div>\n ) : (\n <FinalizingStrip className=\"relative\" />\n )}\n </div>\n )}\n {voice.dialogs}\n <VoiceProtectionDialog voice={voice} />\n </div>\n );\n },\n);\n\nProInput.displayName = \"ProInput\";\n","/**\n * THE TOOLBAR NEVER COVERS TEXT (page-pass 2026-09-27, /chat/message-templates/<id> at 375px).\n *\n * ProInput's mic + \"…\" cluster fades in over the right end of the field. On a\n * phone a tap counts as a hover and stays one, so the cluster sat on top of the\n * text being typed and clipped it. The fix is to reserve exactly the width the\n * visible right-hand controls take — measured, never guessed — as the input's\n * right padding:\n *\n * - the whole cluster while the mic / \"…\" part is showing;\n * - only the always-visible part (clear, submit) while it is faded out — the\n * faded part still takes layout width, so it is subtracted, not ignored.\n *\n * `null` means \"nothing measured yet\" (first paint, jsdom): the caller keeps its\n * class-based fallback padding.\n */\nexport const PRO_INPUT_TEXT_GAP_PX = 4;\nexport const PRO_INPUT_MIN_RIGHT_PADDING_PX = 12;\n\nexport function reservedRightPaddingPx({\n clusterWidth,\n auxWidth,\n auxVisible,\n}: {\n clusterWidth: number;\n auxWidth: number;\n auxVisible: boolean;\n}): number | null {\n if (!(clusterWidth > 0)) return null;\n const visible = auxVisible\n ? clusterWidth\n : Math.max(0, clusterWidth - Math.max(0, auxWidth));\n if (visible <= 0) return PRO_INPUT_MIN_RIGHT_PADDING_PX;\n return Math.max(\n PRO_INPUT_MIN_RIGHT_PADDING_PX,\n Math.ceil(visible) + PRO_INPUT_TEXT_GAP_PX,\n );\n}\n\n/**\n * A NARROW FIELD NEVER LETS A HOVER STEAL ITS CLICK.\n *\n * The mic + \"…\" cluster fades in on pointer hover over the right end of the\n * field. In a field only a couple of hundred px wide (a board tile's task-add\n * row, a sidebar) the cluster and its reserved padding leave a sliver of text,\n * and a press aimed at the middle of the field lands ON the mic: no focus, no\n * typing. Below this width the cluster appears on FOCUS instead of hover, so\n * the first press always focuses the field.\n */\nexport const PRO_INPUT_NARROW_FIELD_PX = 260;\n\nexport function hoverRevealsCluster(inputWidth: number): boolean {\n return !(inputWidth > 0 && inputWidth < PRO_INPUT_NARROW_FIELD_PX);\n}\n\n// What fits beside the text — and what moves inside \"…\" — is decided by THE\n// ONE FITTING RULE shared with ProTextarea: `proFieldControlFit.ts`.\n"],"mappings":"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","names":["React","import_media_query","DialogPrimitive","React","React","import_jsx_runtime","import_jsx_runtime","React","import_jsx_runtime","React","import_jsx_runtime","CONTEXT_SLOT","React","import_jsx_runtime","CONTEXT_SLOT","contextRegistry","swallowClick","React","import_jsx_runtime","registry","import_jsx_runtime","CONTEXT_SLOT","contextRegistry","React","import_jsx_runtime","import_react","React","import_jsx_runtime","import_react","import_react","import_jsx_runtime","import_react","import_jsx_runtime","import_jsx_runtime","tooltipSide","TapTargetButton","TapTargetButtonTransparent","TapTargetButtonOutline","TapTargetButtonSolid","TapTargetButtonDestructive","TapTargetButtonForGroup","import_react","import_react","import_jsx_runtime","SLOT","import_jsx_runtime","Wrap","React","import_jsx_runtime","registry","import_react_slot","React","import_react_slot","React","import_jsx_runtime","import_react_tree","React","import_jsx_runtime","import_react_slot","React","React","import_jsx_runtime","import_jsx_runtime","Button","Textarea","import_jsx_runtime","Button","import_jsx_runtime","import_jsx_runtime","FILL_HEIGHT_REGEX","field","Textarea","registry","React","import_media_query","visible","import_jsx_runtime"]}