@zendir/ui 0.2.20 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (260) hide show
  1. package/CHANGELOG.md +192 -1
  2. package/README.md +70 -28
  3. package/dist/index.d.ts +1 -1
  4. package/dist/index.js +57 -41
  5. package/dist/index.js.map +1 -1
  6. package/dist/react/3d/CesiumCaptureSource.d.ts +119 -0
  7. package/dist/react/3d/CesiumCaptureSource.js +307 -0
  8. package/dist/react/3d/CesiumCaptureSource.js.map +1 -0
  9. package/dist/react/3d/ZenSpace3D.js +1253 -0
  10. package/dist/react/3d/ZenSpace3D.js.map +1 -0
  11. package/dist/react/3d/ZenSpace3DCesium.js +579 -0
  12. package/dist/react/3d/ZenSpace3DCesium.js.map +1 -0
  13. package/dist/react/3d/ZenSpace3DTypes.d.ts +28 -1
  14. package/dist/react/3d/ZenSpace3DUtils.d.ts +17 -173
  15. package/dist/react/3d/ZenSpace3DUtils.js +28 -0
  16. package/dist/react/3d/ZenSpace3DUtils.js.map +1 -0
  17. package/dist/react/3d/capturePngAnalysis.d.ts +16 -0
  18. package/dist/react/3d/index.d.ts +10 -12
  19. package/dist/react/3d/threeLoader.js +18 -0
  20. package/dist/react/3d/threeLoader.js.map +1 -0
  21. package/dist/react/astro/MonitoringIcon.js +1 -1
  22. package/dist/react/astro/MonitoringIcon.js.map +1 -1
  23. package/dist/react/astro/SimulationControls.js +2 -2
  24. package/dist/react/astro/SimulationControls.js.map +1 -1
  25. package/dist/react/astro/UnifiedTimeline.js +4 -4
  26. package/dist/react/astro/UnifiedTimeline.js.map +1 -1
  27. package/dist/react/charts/GroundTrackMap.d.ts +2 -15
  28. package/dist/react/charts/GroundTrackMap.js +1 -1
  29. package/dist/react/charts/GroundTrackMap.js.map +1 -1
  30. package/dist/react/charts/unified/AstroChart.js +34 -13
  31. package/dist/react/charts/unified/AstroChart.js.map +1 -1
  32. package/dist/react/chatgpt/AppCard.d.ts +0 -4
  33. package/dist/react/chatgpt/index.d.ts +0 -19
  34. package/dist/react/context/SpatialSelectionContext.d.ts +40 -0
  35. package/dist/react/context/SpatialSelectionContext.js +10 -0
  36. package/dist/react/context/SpatialSelectionContext.js.map +1 -0
  37. package/dist/react/context/index.d.ts +2 -0
  38. package/dist/react/core/{DataTable.d.ts → data/DataTable.d.ts} +1 -1
  39. package/dist/react/core/{DataTable.js → data/DataTable.js} +4 -4
  40. package/dist/react/core/data/DataTable.js.map +1 -0
  41. package/dist/react/core/{DataValue.d.ts → data/DataValue.d.ts} +2 -2
  42. package/dist/react/core/{DataValue.js → data/DataValue.js} +2 -2
  43. package/dist/react/core/data/DataValue.js.map +1 -0
  44. package/dist/react/core/{propertyConfig.d.ts → data/propertyConfig.d.ts} +2 -2
  45. package/dist/react/core/data/propertyConfig.js.map +1 -0
  46. package/dist/react/core/{AstroIcon.js → display/AstroIcon.js} +1 -1
  47. package/dist/react/core/display/AstroIcon.js.map +1 -0
  48. package/dist/react/core/{Badge.d.ts → display/Badge.d.ts} +1 -1
  49. package/dist/react/core/{Badge.js → display/Badge.js} +2 -2
  50. package/dist/react/core/display/Badge.js.map +1 -0
  51. package/dist/react/core/{CardHeader.d.ts → display/CardHeader.d.ts} +1 -1
  52. package/dist/react/core/{CardHeader.js → display/CardHeader.js} +2 -2
  53. package/dist/react/core/display/CardHeader.js.map +1 -0
  54. package/dist/react/core/{Container.d.ts → display/Container.d.ts} +1 -1
  55. package/dist/react/core/{Container.js → display/Container.js} +3 -3
  56. package/dist/react/core/display/Container.js.map +1 -0
  57. package/dist/react/core/{CopyButton.js → display/CopyButton.js} +1 -1
  58. package/dist/react/core/display/CopyButton.js.map +1 -0
  59. package/dist/react/core/{GlassCard.d.ts → display/GlassCard.d.ts} +1 -1
  60. package/dist/react/core/{GlassCard.js → display/GlassCard.js} +2 -2
  61. package/dist/react/core/display/GlassCard.js.map +1 -0
  62. package/dist/react/core/{HeaderIconWithStatus.d.ts → display/HeaderIconWithStatus.d.ts} +1 -1
  63. package/dist/react/core/{HeaderIconWithStatus.js → display/HeaderIconWithStatus.js} +1 -1
  64. package/dist/react/core/display/HeaderIconWithStatus.js.map +1 -0
  65. package/dist/react/core/{Icon.d.ts → display/Icon.d.ts} +1 -1
  66. package/dist/react/core/{Icon.js → display/Icon.js} +1 -1
  67. package/dist/react/core/display/Icon.js.map +1 -0
  68. package/dist/react/core/{Typography.d.ts → display/Typography.d.ts} +13 -4
  69. package/dist/react/core/{Typography.js → display/Typography.js} +1 -1
  70. package/dist/react/core/display/Typography.js.map +1 -0
  71. package/dist/react/core/{ConfirmDialog.js → feedback/ConfirmDialog.js} +1 -1
  72. package/dist/react/core/feedback/ConfirmDialog.js.map +1 -0
  73. package/dist/react/core/{Dialog.js → feedback/Dialog.js} +2 -2
  74. package/dist/react/core/feedback/Dialog.js.map +1 -0
  75. package/dist/react/core/{Toast.js → feedback/Toast.js} +3 -3
  76. package/dist/react/core/feedback/Toast.js.map +1 -0
  77. package/dist/react/core/index.d.ts +85 -83
  78. package/dist/react/core/{Button.js → inputs/Button.js} +2 -2
  79. package/dist/react/core/inputs/Button.js.map +1 -0
  80. package/dist/react/core/{Checkbox.js → inputs/Checkbox.js} +2 -2
  81. package/dist/react/core/inputs/Checkbox.js.map +1 -0
  82. package/dist/react/core/{Input.d.ts → inputs/Input.d.ts} +1 -1
  83. package/dist/react/core/{Input.js → inputs/Input.js} +3 -3
  84. package/dist/react/core/inputs/Input.js.map +1 -0
  85. package/dist/react/core/{LimitsBar.js → inputs/LimitsBar.js} +1 -1
  86. package/dist/react/core/inputs/LimitsBar.js.map +1 -0
  87. package/dist/react/core/{NumberInput.d.ts → inputs/NumberInput.d.ts} +2 -2
  88. package/dist/react/core/{NumberInput.js → inputs/NumberInput.js} +3 -3
  89. package/dist/react/core/inputs/NumberInput.js.map +1 -0
  90. package/dist/react/core/{PinInput.js → inputs/PinInput.js} +2 -2
  91. package/dist/react/core/inputs/PinInput.js.map +1 -0
  92. package/dist/react/core/{Select.js → inputs/Select.js} +3 -3
  93. package/dist/react/core/inputs/Select.js.map +1 -0
  94. package/dist/react/core/{Toggle.js → inputs/Toggle.js} +2 -2
  95. package/dist/react/core/inputs/Toggle.js.map +1 -0
  96. package/dist/react/core/{AppBar.d.ts → navigation/AppBar.d.ts} +1 -1
  97. package/dist/react/core/{AppBar.js → navigation/AppBar.js} +7 -7
  98. package/dist/react/core/navigation/AppBar.js.map +1 -0
  99. package/dist/react/core/{Pagination.js → navigation/Pagination.js} +2 -2
  100. package/dist/react/core/navigation/Pagination.js.map +1 -0
  101. package/dist/react/core/{SideNav.d.ts → navigation/SideNav.d.ts} +1 -1
  102. package/dist/react/core/{SideNav.js → navigation/SideNav.js} +8 -9
  103. package/dist/react/core/navigation/SideNav.js.map +1 -0
  104. package/dist/react/core/{Tabs.js → navigation/Tabs.js} +2 -2
  105. package/dist/react/core/navigation/Tabs.js.map +1 -0
  106. package/dist/react/core/{Popover.js → overlays/Popover.js} +1 -1
  107. package/dist/react/core/overlays/Popover.js.map +1 -0
  108. package/dist/react/core/{SidePanel.js → overlays/SidePanel.js} +7 -7
  109. package/dist/react/core/overlays/SidePanel.js.map +1 -0
  110. package/dist/react/core/{Tooltip.js → overlays/Tooltip.js} +2 -2
  111. package/dist/react/core/overlays/Tooltip.js.map +1 -0
  112. package/dist/react/core/{ActivityPlanner.js → widgets/ActivityPlanner.js} +1 -1
  113. package/dist/react/core/widgets/ActivityPlanner.js.map +1 -0
  114. package/dist/react/core/widgets/Capture.d.ts +140 -0
  115. package/dist/react/core/widgets/Capture.js +804 -0
  116. package/dist/react/core/widgets/Capture.js.map +1 -0
  117. package/dist/react/core/{ChatPanel.d.ts → widgets/ChatPanel.d.ts} +1 -1
  118. package/dist/react/core/{ChatPanel.js → widgets/ChatPanel.js} +5 -4
  119. package/dist/react/core/widgets/ChatPanel.js.map +1 -0
  120. package/dist/react/core/{ColorPickerPanel.d.ts → widgets/ColorPickerPanel.d.ts} +1 -1
  121. package/dist/react/core/{ColorPickerPanel.js → widgets/ColorPickerPanel.js} +3 -3
  122. package/dist/react/core/widgets/ColorPickerPanel.js.map +1 -0
  123. package/dist/react/core/{CommandBuilder.js → widgets/CommandBuilder.js} +1 -1
  124. package/dist/react/core/widgets/CommandBuilder.js.map +1 -0
  125. package/dist/react/core/{ConnectionForm.d.ts → widgets/ConnectionForm.d.ts} +1 -1
  126. package/dist/react/core/{ConnectionForm.js → widgets/ConnectionForm.js} +2 -2
  127. package/dist/react/core/widgets/ConnectionForm.js.map +1 -0
  128. package/dist/react/core/{FileExplorer.js → widgets/FileExplorer.js} +2 -2
  129. package/dist/react/core/widgets/FileExplorer.js.map +1 -0
  130. package/dist/react/core/{HexViewer.js → widgets/HexViewer.js} +1 -1
  131. package/dist/react/core/widgets/HexViewer.js.map +1 -0
  132. package/dist/react/core/{ImageGallery.d.ts → widgets/ImageGallery.d.ts} +1 -1
  133. package/dist/react/core/{ImageGallery.js → widgets/ImageGallery.js} +3 -3
  134. package/dist/react/core/widgets/ImageGallery.js.map +1 -0
  135. package/dist/react/core/{LogViewer.d.ts → widgets/LogViewer.d.ts} +13 -3
  136. package/dist/react/core/{LogViewer.js → widgets/LogViewer.js} +28 -8
  137. package/dist/react/core/widgets/LogViewer.js.map +1 -0
  138. package/dist/react/core/{MessageStream.d.ts → widgets/MessageStream.d.ts} +2 -2
  139. package/dist/react/core/{MessageStream.js → widgets/MessageStream.js} +4 -4
  140. package/dist/react/core/widgets/MessageStream.js.map +1 -0
  141. package/dist/react/core/{MissionCalendar.js → widgets/MissionCalendar.js} +2 -2
  142. package/dist/react/core/widgets/MissionCalendar.js.map +1 -0
  143. package/dist/react/core/{PacketViewer.js → widgets/PacketViewer.js} +1 -1
  144. package/dist/react/core/widgets/PacketViewer.js.map +1 -0
  145. package/dist/react/core/widgets/capture-placeholder.png.js +5 -0
  146. package/dist/react/core/widgets/capture-placeholder.png.js.map +1 -0
  147. package/dist/react/hooks/index.d.ts +9 -11
  148. package/dist/react/hooks/useAccessWindows.d.ts +15 -19
  149. package/dist/react/hooks/useGroundTrackHistory.d.ts +34 -0
  150. package/dist/react/hooks/useSimulationScene.d.ts +141 -0
  151. package/dist/react/hooks/useSimulationScene.js +401 -0
  152. package/dist/react/hooks/useSimulationScene.js.map +1 -0
  153. package/dist/react/hooks/useZendirSession.d.ts +44 -69
  154. package/dist/react/index.d.ts +10 -5
  155. package/dist/react/panels/LayerControlPanel.d.ts +54 -0
  156. package/dist/react/panels/LayerControlPanel.js +184 -0
  157. package/dist/react/panels/LayerControlPanel.js.map +1 -0
  158. package/dist/react/panels/ObjectInventoryPanel.d.ts +57 -0
  159. package/dist/react/panels/ObjectInventoryPanel.js +261 -0
  160. package/dist/react/panels/ObjectInventoryPanel.js.map +1 -0
  161. package/dist/react/panels/index.d.ts +15 -0
  162. package/dist/react/theme/ThemeProvider.d.ts +2 -0
  163. package/dist/react/theme/ThemeProvider.js +50 -72
  164. package/dist/react/theme/ThemeProvider.js.map +1 -1
  165. package/dist/react/types.d.ts +32 -3
  166. package/dist/react/types.js.map +1 -1
  167. package/dist/react.js +57 -41
  168. package/dist/react.js.map +1 -1
  169. package/dist/shaders/atmosphere.frag.js +5 -0
  170. package/dist/shaders/atmosphere.frag.js.map +1 -0
  171. package/dist/shaders/atmosphere.vert.js +5 -0
  172. package/dist/shaders/atmosphere.vert.js.map +1 -0
  173. package/dist/shaders/stars.frag.js +5 -0
  174. package/dist/shaders/stars.frag.js.map +1 -0
  175. package/dist/shaders/stars.vert.js +5 -0
  176. package/dist/shaders/stars.vert.js.map +1 -0
  177. package/dist/style.css +6 -4
  178. package/dist/tokens/css-vars.d.ts +91 -0
  179. package/dist/tokens/css-vars.js +228 -0
  180. package/dist/tokens/css-vars.js.map +1 -0
  181. package/dist/tokens/index.d.ts +71 -18
  182. package/dist/tokens/index.js +206 -97
  183. package/dist/tokens/index.js.map +1 -1
  184. package/dist/tokens/tokens.css +50 -50
  185. package/package.json +27 -22
  186. package/sdk-stub.js +10 -5
  187. package/dist/react/3d/EarthViewer.d.ts +0 -46
  188. package/dist/react/3d/SolarSystemViewer.d.ts +0 -43
  189. package/dist/react/chatgpt/ChatGPTCard.d.ts +0 -6
  190. package/dist/react/core/ActivityPlanner.js.map +0 -1
  191. package/dist/react/core/AppBar.js.map +0 -1
  192. package/dist/react/core/AstroIcon.js.map +0 -1
  193. package/dist/react/core/Badge.js.map +0 -1
  194. package/dist/react/core/Button.js.map +0 -1
  195. package/dist/react/core/CardHeader.js.map +0 -1
  196. package/dist/react/core/ChatPanel.js.map +0 -1
  197. package/dist/react/core/Checkbox.js.map +0 -1
  198. package/dist/react/core/ColorPickerPanel.js.map +0 -1
  199. package/dist/react/core/CommandBuilder.js.map +0 -1
  200. package/dist/react/core/ConfirmDialog.js.map +0 -1
  201. package/dist/react/core/ConnectionForm.js.map +0 -1
  202. package/dist/react/core/Container.js.map +0 -1
  203. package/dist/react/core/CopyButton.js.map +0 -1
  204. package/dist/react/core/DataTable.js.map +0 -1
  205. package/dist/react/core/DataValue.js.map +0 -1
  206. package/dist/react/core/Dialog.js.map +0 -1
  207. package/dist/react/core/FileExplorer.js.map +0 -1
  208. package/dist/react/core/GlassCard.js.map +0 -1
  209. package/dist/react/core/HeaderIconWithStatus.js.map +0 -1
  210. package/dist/react/core/HexViewer.js.map +0 -1
  211. package/dist/react/core/Icon.js.map +0 -1
  212. package/dist/react/core/ImageGallery.js.map +0 -1
  213. package/dist/react/core/Input.js.map +0 -1
  214. package/dist/react/core/LimitsBar.js.map +0 -1
  215. package/dist/react/core/LogViewer.js.map +0 -1
  216. package/dist/react/core/MessageStream.js.map +0 -1
  217. package/dist/react/core/MissionCalendar.js.map +0 -1
  218. package/dist/react/core/NumberInput.js.map +0 -1
  219. package/dist/react/core/PacketViewer.js.map +0 -1
  220. package/dist/react/core/Pagination.js.map +0 -1
  221. package/dist/react/core/PinInput.js.map +0 -1
  222. package/dist/react/core/Popover.js.map +0 -1
  223. package/dist/react/core/Select.js.map +0 -1
  224. package/dist/react/core/SideNav.js.map +0 -1
  225. package/dist/react/core/SidePanel.js.map +0 -1
  226. package/dist/react/core/Tabs.js.map +0 -1
  227. package/dist/react/core/Toast.js.map +0 -1
  228. package/dist/react/core/Toggle.js.map +0 -1
  229. package/dist/react/core/Tooltip.js.map +0 -1
  230. package/dist/react/core/Typography.js.map +0 -1
  231. package/dist/react/core/propertyConfig.js.map +0 -1
  232. package/dist/react/hooks/useSimulationTime.d.ts +0 -61
  233. package/dist/react/hooks/useSpacecraftPosition.d.ts +0 -50
  234. package/dist/react/hooks/useTelemetry.d.ts +0 -55
  235. package/dist/types.d.ts +0 -1
  236. package/dist/types.js +0 -2
  237. package/dist/types.js.map +0 -1
  238. /package/dist/react/core/{propertyConfig.js → data/propertyConfig.js} +0 -0
  239. /package/dist/react/core/{AstroIcon.d.ts → display/AstroIcon.d.ts} +0 -0
  240. /package/dist/react/core/{CopyButton.d.ts → display/CopyButton.d.ts} +0 -0
  241. /package/dist/react/core/{ConfirmDialog.d.ts → feedback/ConfirmDialog.d.ts} +0 -0
  242. /package/dist/react/core/{Dialog.d.ts → feedback/Dialog.d.ts} +0 -0
  243. /package/dist/react/core/{Toast.d.ts → feedback/Toast.d.ts} +0 -0
  244. /package/dist/react/core/{Button.d.ts → inputs/Button.d.ts} +0 -0
  245. /package/dist/react/core/{Checkbox.d.ts → inputs/Checkbox.d.ts} +0 -0
  246. /package/dist/react/core/{LimitsBar.d.ts → inputs/LimitsBar.d.ts} +0 -0
  247. /package/dist/react/core/{PinInput.d.ts → inputs/PinInput.d.ts} +0 -0
  248. /package/dist/react/core/{Select.d.ts → inputs/Select.d.ts} +0 -0
  249. /package/dist/react/core/{Toggle.d.ts → inputs/Toggle.d.ts} +0 -0
  250. /package/dist/react/core/{Pagination.d.ts → navigation/Pagination.d.ts} +0 -0
  251. /package/dist/react/core/{Tabs.d.ts → navigation/Tabs.d.ts} +0 -0
  252. /package/dist/react/core/{Popover.d.ts → overlays/Popover.d.ts} +0 -0
  253. /package/dist/react/core/{SidePanel.d.ts → overlays/SidePanel.d.ts} +0 -0
  254. /package/dist/react/core/{Tooltip.d.ts → overlays/Tooltip.d.ts} +0 -0
  255. /package/dist/react/core/{ActivityPlanner.d.ts → widgets/ActivityPlanner.d.ts} +0 -0
  256. /package/dist/react/core/{CommandBuilder.d.ts → widgets/CommandBuilder.d.ts} +0 -0
  257. /package/dist/react/core/{FileExplorer.d.ts → widgets/FileExplorer.d.ts} +0 -0
  258. /package/dist/react/core/{HexViewer.d.ts → widgets/HexViewer.d.ts} +0 -0
  259. /package/dist/react/core/{MissionCalendar.d.ts → widgets/MissionCalendar.d.ts} +0 -0
  260. /package/dist/react/core/{PacketViewer.d.ts → widgets/PacketViewer.d.ts} +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Capture.js","sources":["../../../../src/react/core/widgets/Capture.tsx"],"sourcesContent":["/**\n * @zendir/ui - Capture Component\n * \n * Transport-agnostic image capture server component. Generates a unique server\n * ID, accepts capture requests imperatively, and returns image bytes. The host\n * app (e.g. space-range-operator) handles all MQTT/transport wiring and uses\n * the server ID to construct topic paths externally.\n * \n * Features:\n * - Unique server ID with copy-to-clipboard\n * - Pause/resume capture processing\n * - Collapsible gallery of captured images\n * - Connection status display\n * - forwardRef with imperative CaptureHandle\n * \n * @example\n * ```tsx\n * const captureRef = useRef<CaptureHandle>(null);\n * \n * <Capture\n * ref={captureRef}\n * connected={isConnected}\n * onReady={(serverId) => {\n * mqttClient.subscribe('Zendir/SpaceImage/Request');\n * }}\n * onCapture={(req) => console.log('Captured', req.req_id)}\n * />\n * \n * // When a request arrives from external transport:\n * // Request: { req_id, args: { game_id, team_id, ...captureArgs } }\n * const imageBytes = await captureRef.current.capture(request);\n * // Publish response to: Zendir/SpaceImage/{game_id}/{team_id}/Response/{req_id}\n * ```\n */\n\nimport React, { memo, useState, useCallback, useRef, useEffect, useImperativeHandle, forwardRef } from 'react';\nimport { useTheme } from '../../theme';\nimport { useCopyToClipboard } from '../display/CopyButton';\nimport placeholderImageUrl from './capture-placeholder.png';\n\n// ─── Types ────────────────────────────────────────────────────────────────────\n\n/** Camera capture arguments */\nexport interface CaptureArgs {\n monochromatic: boolean;\n resolution: number;\n coc: number;\n pixel_pitch: number;\n focusing_distance: number;\n aperture: number;\n focal_length: number;\n fov: number;\n sample: boolean;\n position: [number, number, number];\n rotation: [number, number, number];\n /**\n * Output image format. Defaults to 'png' when omitted.\n * - 'png' → lossless, larger file (good for scientific/archival use)\n * - 'jpeg' → lossy, smaller file (~3-5× smaller than PNG at q=0.92)\n */\n format?: 'png' | 'jpeg';\n /**\n * JPEG quality factor (0–1). Only used when format='jpeg'. Default: 0.92.\n * Ignored for PNG (which is always lossless).\n */\n jpeg_quality?: number;\n}\n\n/** Incoming capture request */\nexport interface CaptureRequest {\n type: 'capture';\n req_id: number;\n args: CaptureArgs;\n}\n\n/** Imperative handle exposed via ref */\nexport interface CaptureHandle {\n /** Process a capture request, returns image bytes */\n capture: (request: CaptureRequest) => Promise<Uint8Array>;\n /** The server's unique ID */\n serverId: string;\n}\n\n/** Captured image entry stored for gallery display */\nexport interface CapturedImage {\n reqId: number;\n dataUrl: string;\n timestamp: number;\n /** Raw image byte count */\n bytes: number;\n /** The CaptureArgs used for this capture (camera settings, position, etc.) */\n args?: CaptureArgs;\n}\n\nexport interface CaptureProps {\n /** Whether host transport is connected (drives status indicator) */\n connected?: boolean;\n /**\n * Image source for capture responses. Three tiers:\n * 1. `Uint8Array` -- static bytes returned for every request\n * 2. `(args) => Promise<Uint8Array>` -- async renderer (e.g. CesiumCaptureSource)\n * 3. `undefined` (default) -- auto-detects CesiumJS; falls back to placeholder image\n */\n imageSource?: Uint8Array | ((args: CaptureArgs) => Promise<Uint8Array>);\n /**\n * Pre-load the CesiumJS renderer on mount instead of waiting for the first\n * capture request. Only applies when `imageSource` is not provided (auto-detect mode).\n * @default true\n */\n preload?: boolean;\n /**\n * Explicit server ID. When provided the component uses this value instead\n * of generating a new UUID. Useful for persisting across reloads via localStorage.\n */\n serverId?: string;\n /** Fired after each capture is processed */\n onCapture?: (request: CaptureRequest) => void;\n /** Called once on mount with the server ID */\n onReady?: (serverId: string) => void;\n /**\n * Start with the image gallery expanded. When true, the component renders\n * in a flex-column layout designed to fill its container height.\n * @default false\n */\n defaultGalleryExpanded?: boolean;\n /** Custom style */\n style?: React.CSSProperties;\n}\n\n// ─── Placeholder Image ───────────────────────────────────────────────────────\n\n/**\n * Generates a visible 256x256 fallback PNG via canvas when the bundled\n * astronaut image cannot be fetched (Storybook asset path, SSR, etc.).\n * Shows a branded \"ZENDIR\" placeholder so thumbnails are never invisible.\n */\nasync function generateCanvasFallback(): Promise<Uint8Array> {\n try {\n const size = 256;\n const canvas = document.createElement('canvas');\n canvas.width = size;\n canvas.height = size;\n const ctx = canvas.getContext('2d')!;\n\n // Dark space-themed gradient background\n const bg = ctx.createRadialGradient(size / 2, size / 2, 20, size / 2, size / 2, size);\n bg.addColorStop(0, '#1e2a4a');\n bg.addColorStop(1, '#0a0e1a');\n ctx.fillStyle = bg;\n ctx.fillRect(0, 0, size, size);\n\n // Subtle star field\n ctx.fillStyle = 'rgba(255, 255, 255, 0.5)';\n for (let i = 0; i < 40; i++) {\n const sx = (((i * 97) + 31) % size);\n const sy = (((i * 61) + 17) % size);\n const sr = ((i % 3) + 1) * 0.6;\n ctx.beginPath();\n ctx.arc(sx, sy, sr, 0, Math.PI * 2);\n ctx.fill();\n }\n\n // Crosshair / reticle\n ctx.strokeStyle = 'rgba(74, 143, 255, 0.35)';\n ctx.lineWidth = 1;\n ctx.beginPath();\n ctx.moveTo(size / 2, 40);\n ctx.lineTo(size / 2, size - 40);\n ctx.moveTo(40, size / 2);\n ctx.lineTo(size - 40, size / 2);\n ctx.stroke();\n ctx.beginPath();\n ctx.arc(size / 2, size / 2, 50, 0, Math.PI * 2);\n ctx.stroke();\n\n // \"ZENDIR\" label\n ctx.fillStyle = '#4a8fff';\n ctx.font = 'bold 28px monospace';\n ctx.textAlign = 'center';\n ctx.textBaseline = 'middle';\n ctx.fillText('ZENDIR', size / 2, size / 2 - 16);\n\n // \"PLACEHOLDER\" subtitle\n ctx.fillStyle = 'rgba(255, 255, 255, 0.4)';\n ctx.font = '13px monospace';\n ctx.fillText('PLACEHOLDER', size / 2, size / 2 + 14);\n\n // Res badge at bottom\n ctx.fillStyle = 'rgba(255, 255, 255, 0.25)';\n ctx.font = '10px monospace';\n ctx.fillText(`${size}x${size}`, size / 2, size - 20);\n\n const blob = await new Promise<Blob>((resolve) =>\n canvas.toBlob((b) => resolve(b!), 'image/png'),\n );\n return new Uint8Array(await blob.arrayBuffer());\n } catch {\n // Absolute last resort: 1x1 opaque dark-blue PNG (never transparent/black)\n return new Uint8Array([\n 0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A,\n 0x00, 0x00, 0x00, 0x0D, 0x49, 0x48, 0x44, 0x52,\n 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,\n 0x08, 0x02, 0x00, 0x00, 0x00, 0x90, 0x77, 0x53,\n 0xDE, 0x00, 0x00, 0x00, 0x0C, 0x49, 0x44, 0x41,\n 0x54, 0x78, 0x9C, 0x62, 0x68, 0x60, 0x60, 0x00,\n 0x00, 0x00, 0x04, 0x00, 0x01, 0x27, 0x34, 0x27,\n 0x0A, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4E,\n 0x44, 0xAE, 0x42, 0x60, 0x82,\n ]);\n }\n}\n\n/** Cached placeholder image bytes (lazy-loaded from bundled asset) */\nlet placeholderCache: Uint8Array | null = null;\n\n/**\n * Loads the bundled placeholder image (astronaut). Falls back to a\n * canvas-generated branded placeholder if the fetch fails (e.g. SSR,\n * Storybook asset paths, missing file).\n */\nasync function loadPlaceholderImage(): Promise<Uint8Array> {\n if (placeholderCache) return placeholderCache;\n try {\n const response = await fetch(placeholderImageUrl);\n if (!response.ok) throw new Error(`HTTP ${response.status}`);\n const buf = await response.arrayBuffer();\n if (buf.byteLength < 100) throw new Error('Suspiciously small image');\n placeholderCache = new Uint8Array(buf);\n } catch {\n placeholderCache = await generateCanvasFallback();\n }\n return placeholderCache;\n}\n\n/**\n * Bundled astronaut placeholder PNG (or 1x1 fallback). Exported for\n * `CesiumCaptureSource` when globe capture fails (e.g. missing Cesium assets, WebGL).\n */\nexport async function loadCapturePlaceholderImage(): Promise<Uint8Array> {\n return loadPlaceholderImage();\n}\n\n// ─── Hook ─────────────────────────────────────────────────────────────────────\n\nexport interface UseCaptureOptions {\n /** Image to return: static bytes or async function receiving capture args */\n imageSource?: Uint8Array | ((args: CaptureArgs) => Promise<Uint8Array>);\n /**\n * Pre-load the CesiumJS renderer on mount (only when imageSource is undefined).\n * Set to false for lazy init on first capture request.\n * @default true\n */\n preload?: boolean;\n /**\n * Explicit server ID. When provided the hook uses this value instead of\n * generating a new `crypto.randomUUID()`. Useful for persisting the ID\n * across page reloads (e.g. from localStorage).\n */\n serverId?: string;\n}\n\nexport interface UseCaptureResult {\n /** Stable unique server ID */\n serverId: string;\n /** Process a capture request, returns image bytes (empty if paused) */\n capture: (request: CaptureRequest) => Promise<Uint8Array>;\n /** Whether capture processing is paused */\n paused: boolean;\n /** Toggle pause state */\n setPaused: (paused: boolean) => void;\n /** Number of successfully processed requests */\n requestCount: number;\n /** Most recent request */\n lastRequest: CaptureRequest | null;\n /** Gallery of captured images (newest first) */\n capturedImages: CapturedImage[];\n}\n\n/**\n * Hook for capture server logic. Generates a stable UUID, manages\n * pause state, and processes capture requests into image bytes.\n * \n * @example\n * ```tsx\n * const { serverId, capture, paused, setPaused } = useCapture();\n * // call capture(request) when external message arrives\n * ```\n */\nexport function useCapture(options?: UseCaptureOptions): UseCaptureResult {\n const serverIdRef = useRef(options?.serverId || crypto.randomUUID());\n const [paused, setPaused] = useState(false);\n const [requestCount, setRequestCount] = useState(0);\n const [lastRequest, setLastRequest] = useState<CaptureRequest | null>(null);\n const [capturedImages, setCapturedImages] = useState<CapturedImage[]>([]);\n\n const imageSourceRef = useRef(options?.imageSource);\n imageSourceRef.current = options?.imageSource;\n\n const pausedRef = useRef(paused);\n pausedRef.current = paused;\n\n // Cache generated images by req_id to avoid regenerating the same capture\n const imageCacheRef = useRef<Map<number, Uint8Array>>(new Map());\n\n // Auto-detect CesiumJS when no imageSource is provided.\n // Lazily creates a hidden Cesium.Viewer on first use (or on mount if preload=true).\n const cesiumSourceRef = useRef<{ capture: (args: CaptureArgs) => Promise<Uint8Array>; destroy: () => void } | null>(null);\n const cesiumFailedRef = useRef(false);\n const cesiumLoadingRef = useRef<Promise<void> | null>(null);\n\n const initCesium = useCallback(async () => {\n if (cesiumSourceRef.current || cesiumFailedRef.current) return;\n try {\n const { createCesiumCaptureSource } = await import('../../3d/CesiumCaptureSource');\n cesiumSourceRef.current = await createCesiumCaptureSource();\n } catch {\n cesiumFailedRef.current = true;\n }\n }, []);\n\n // Pre-load Cesium on mount when preload is enabled and no explicit imageSource\n const preload = options?.preload !== false;\n useEffect(() => {\n if (imageSourceRef.current || !preload) return;\n cesiumLoadingRef.current = initCesium();\n }, [preload, initCesium]);\n\n // Cleanup Cesium viewer on unmount\n useEffect(() => {\n return () => {\n cesiumSourceRef.current?.destroy();\n cesiumSourceRef.current = null;\n };\n }, []);\n\n const capture = useCallback(async (request: CaptureRequest): Promise<Uint8Array> => {\n if (pausedRef.current) return new Uint8Array(0);\n\n if (!request || request.type !== 'capture' || typeof request.req_id !== 'number') {\n return new Uint8Array(0);\n }\n\n // Return cached image if this req_id was already processed\n const cached = imageCacheRef.current.get(request.req_id);\n if (cached) return cached;\n\n let bytes: Uint8Array;\n const src = imageSourceRef.current;\n\n if (src instanceof Uint8Array) {\n bytes = src;\n } else if (typeof src === 'function') {\n bytes = await src(request.args);\n } else {\n // Auto-detect: try CesiumJS, fall back to placeholder\n if (!cesiumSourceRef.current && !cesiumFailedRef.current) {\n if (cesiumLoadingRef.current) {\n await cesiumLoadingRef.current;\n } else {\n await initCesium();\n }\n }\n if (cesiumSourceRef.current) {\n bytes = await cesiumSourceRef.current.capture(request.args);\n } else {\n bytes = await loadPlaceholderImage();\n }\n }\n\n // Cache the result by req_id\n imageCacheRef.current.set(request.req_id, bytes);\n\n setRequestCount(c => c + 1);\n setLastRequest(request);\n\n const mimeType = request.args.format === 'jpeg' ? 'image/jpeg' : 'image/png';\n const blob = new Blob([bytes as unknown as BlobPart], { type: mimeType });\n const dataUrl = URL.createObjectURL(blob);\n setCapturedImages(prev => [\n { reqId: request.req_id, dataUrl, timestamp: Date.now(), bytes: bytes.length, args: request.args },\n ...prev,\n ]);\n\n return bytes;\n }, []);\n\n return {\n serverId: serverIdRef.current,\n capture,\n paused,\n setPaused,\n requestCount,\n lastRequest,\n capturedImages,\n };\n}\n\n// ─── Inline SVG Icons ─────────────────────────────────────────────────────────\n\nconst PauseIcon = ({ size = 14 }: { size?: number }) => (\n <svg width={size} height={size} viewBox=\"0 0 24 24\" fill=\"currentColor\">\n <rect x=\"6\" y=\"4\" width=\"4\" height=\"16\" rx=\"1\" />\n <rect x=\"14\" y=\"4\" width=\"4\" height=\"16\" rx=\"1\" />\n </svg>\n);\n\nconst PlayIcon = ({ size = 14 }: { size?: number }) => (\n <svg width={size} height={size} viewBox=\"0 0 24 24\" fill=\"currentColor\">\n <polygon points=\"6,4 20,12 6,20\" />\n </svg>\n);\n\nconst ChevronIcon = ({ size = 14, expanded }: { size?: number; expanded: boolean }) => (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n style={{\n transition: 'transform 0.2s ease',\n transform: expanded ? 'rotate(90deg)' : 'rotate(0deg)',\n }}\n >\n <polyline points=\"9 18 15 12 9 6\" />\n </svg>\n);\n\nconst CopyIcon = ({ size = 14 }: { size?: number }) => (\n <svg width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <rect x=\"9\" y=\"9\" width=\"13\" height=\"13\" rx=\"2\" ry=\"2\" />\n <path d=\"M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1\" />\n </svg>\n);\n\nconst CheckIcon = ({ size = 14, color }: { size?: number; color: string }) => (\n <svg width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke={color} strokeWidth=\"2.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <polyline points=\"20 6 9 17 4 12\" />\n </svg>\n);\n\n// ─── Component ────────────────────────────────────────────────────────────────\n\n/**\n * Capture server UI component. Displays server status, pause/resume control,\n * copy-ID button, and a collapsible gallery of captured images.\n * \n * Access `capture()` and `serverId` imperatively via the forwarded ref.\n */\nexport const Capture = memo(forwardRef<CaptureHandle, CaptureProps>(function Capture(\n {\n connected = false,\n imageSource,\n preload,\n serverId: serverIdProp,\n onCapture,\n onReady,\n defaultGalleryExpanded = false,\n style,\n },\n ref,\n) {\n const { tokens } = useTheme();\n const {\n serverId,\n capture,\n paused,\n setPaused,\n requestCount,\n capturedImages,\n } = useCapture({ imageSource, preload, serverId: serverIdProp });\n const { copy, copied } = useCopyToClipboard();\n const [galleryExpanded, setGalleryExpanded] = useState(defaultGalleryExpanded);\n const [hoveredBtn, setHoveredBtn] = useState<string | null>(null);\n const readyFiredRef = useRef(false);\n\n useEffect(() => {\n if (onReady && !readyFiredRef.current) {\n readyFiredRef.current = true;\n onReady(serverId);\n }\n }, [onReady, serverId]);\n\n const wrappedCapture = useCallback(async (request: CaptureRequest) => {\n const bytes = await capture(request);\n if (bytes.length > 0) {\n onCapture?.(request);\n }\n return bytes;\n }, [capture, onCapture]);\n\n useImperativeHandle(ref, () => ({\n capture: wrappedCapture,\n serverId,\n }), [wrappedCapture, serverId]);\n\n const statusColor = connected\n ? tokens.colors.status.normal\n : tokens.colors.status.off;\n const statusLabel = connected ? 'Connected' : 'Disconnected';\n\n const btnBase: React.CSSProperties = {\n display: 'inline-flex',\n alignItems: 'center',\n justifyContent: 'center',\n gap: '6px',\n height: 32,\n padding: '0 12px',\n fontSize: tokens.typography.fontSize.sm,\n fontWeight: 500,\n fontFamily: tokens.typography.fontFamily.primary,\n color: tokens.colors.text.secondary,\n backgroundColor: 'transparent',\n border: `1px solid ${tokens.colors.border.muted}`,\n borderRadius: tokens.borderRadius.md,\n cursor: 'pointer',\n transition: tokens.animation.fast,\n outline: 'none',\n whiteSpace: 'nowrap',\n };\n\n return (\n <div\n style={{\n display: 'flex',\n flexDirection: 'column',\n borderRadius: tokens.borderRadius.lg,\n border: `1px solid ${tokens.colors.border.default}`,\n backgroundColor: tokens.colors.background.surface,\n overflow: 'hidden',\n /* When gallery is expanded, allow container to stretch to fill parent */\n ...(galleryExpanded ? { flex: 1, minHeight: 0 } : {}),\n ...style,\n }}\n >\n {/* Top bar: pause/resume | status | copy ID */}\n <div\n style={{\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n padding: '8px 12px',\n gap: '12px',\n minHeight: 48,\n flexShrink: 0,\n }}\n >\n {/* Left: Pause/Resume */}\n <button\n type=\"button\"\n onClick={() => setPaused(!paused)}\n onMouseEnter={() => setHoveredBtn('pause')}\n onMouseLeave={() => setHoveredBtn(null)}\n aria-label={paused ? 'Resume capture server' : 'Pause capture server'}\n style={{\n ...btnBase,\n color: paused ? tokens.colors.status.caution : tokens.colors.text.secondary,\n borderColor: paused\n ? `${tokens.colors.status.caution}40`\n : tokens.colors.border.muted,\n backgroundColor: hoveredBtn === 'pause'\n ? `${tokens.colors.accent.primary}12`\n : 'transparent',\n }}\n >\n {paused ? <PlayIcon /> : <PauseIcon />}\n <span>{paused ? 'Resume' : 'Pause'}</span>\n </button>\n\n {/* Center: Status + request count */}\n <div\n style={{\n display: 'flex',\n alignItems: 'center',\n gap: '8px',\n fontSize: tokens.typography.fontSize.sm,\n color: tokens.colors.text.secondary,\n }}\n >\n <span\n style={{\n width: 8,\n height: 8,\n borderRadius: '50%',\n backgroundColor: statusColor,\n flexShrink: 0,\n }}\n />\n <span>{statusLabel}</span>\n {requestCount > 0 && (\n <span\n style={{\n fontSize: tokens.typography.fontSize.xs,\n color: tokens.colors.text.tertiary,\n fontFamily: tokens.typography.fontFamily.mono,\n }}\n >\n ({requestCount})\n </span>\n )}\n </div>\n\n {/* Right: Copy ID */}\n <button\n type=\"button\"\n onClick={() => copy(serverId)}\n onMouseEnter={() => setHoveredBtn('copy')}\n onMouseLeave={() => setHoveredBtn(null)}\n title={copied ? 'Copied!' : `Copy Server ID: ${serverId}`}\n aria-label={copied ? 'Server ID copied' : 'Copy server ID'}\n style={{\n ...btnBase,\n color: copied\n ? tokens.colors.status.normal\n : tokens.colors.text.secondary,\n borderColor: copied\n ? `${tokens.colors.status.normal}40`\n : tokens.colors.border.muted,\n backgroundColor: hoveredBtn === 'copy'\n ? `${tokens.colors.accent.primary}12`\n : 'transparent',\n }}\n >\n {copied\n ? <CheckIcon color={tokens.colors.status.normal} />\n : <CopyIcon />}\n <span\n style={{\n fontFamily: tokens.typography.fontFamily.mono,\n fontSize: tokens.typography.fontSize.xs,\n }}\n >\n {copied ? 'Copied!' : serverId.slice(0, 8)}\n </span>\n </button>\n </div>\n\n {/* Captured Images gallery (respects defaultGalleryExpanded prop) */}\n <CaptureGallery\n images={capturedImages}\n expanded={galleryExpanded}\n onToggle={() => setGalleryExpanded(!galleryExpanded)}\n tokens={tokens}\n serverId={serverId}\n />\n </div>\n );\n}));\n\n// ─── Gallery Sub-Components ───────────────────────────────────────────────────\n\n/** Format byte count for display */\nfunction fmtBytes(b: number): string {\n if (b > 1048576) return `${(b / 1048576).toFixed(1)} MB`;\n if (b > 1024) return `${(b / 1024).toFixed(1)} KB`;\n return `${b} B`;\n}\n\n/** Download a single captured image with the correct file extension */\nfunction downloadCapturedImage(img: CapturedImage, serverId: string): void {\n const ext = img.args?.format === 'jpeg' ? 'jpg' : 'png';\n const a = document.createElement('a');\n a.href = img.dataUrl;\n a.download = `capture_${serverId}_${img.reqId}.${ext}`;\n a.click();\n}\n\n/** Download all captured images sequentially */\nasync function downloadAllImages(images: CapturedImage[], serverId: string): Promise<void> {\n for (const img of images) {\n downloadCapturedImage(img, serverId);\n await new Promise<void>(r => setTimeout(r, 200));\n }\n}\n\n/** Download icon (inline SVG) */\nconst DownloadIcon = ({ size = 12 }: { size?: number }) => (\n <svg width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <path d=\"M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4\" />\n <polyline points=\"7 10 12 15 17 10\" />\n <line x1=\"12\" y1=\"15\" x2=\"12\" y2=\"3\" />\n </svg>\n);\n\n/** Close icon (inline SVG) */\nconst CloseIcon = ({ size = 12 }: { size?: number }) => (\n <svg width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2.5\" strokeLinecap=\"round\">\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\" />\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\" />\n </svg>\n);\n\n/** Metadata key-value row */\nfunction MetaRow({ label, value, tokens, mono }: { label: string; value: string; tokens: any; mono?: boolean }) {\n return (\n <div style={{\n display: 'flex', justifyContent: 'space-between', alignItems: 'center',\n padding: '2px 0', fontSize: tokens.typography.fontSize.xs,\n }}>\n <span style={{ color: tokens.colors.text.tertiary }}>{label}</span>\n <span style={{\n color: tokens.colors.text.primary,\n fontFamily: mono ? tokens.typography.fontFamily.mono : 'inherit',\n fontSize: mono ? '0.68rem' : tokens.typography.fontSize.xs,\n }}>{value}</span>\n </div>\n );\n}\n\n/** Metadata group heading */\nfunction MetaGroup({ label, tokens, children }: { label: string; tokens: any; children: React.ReactNode }) {\n return (\n <div style={{ marginTop: 6 }}>\n <div style={{\n fontSize: '0.6rem', fontWeight: 600, color: tokens.colors.text.tertiary,\n textTransform: 'uppercase' as const, letterSpacing: '0.06em',\n padding: '4px 0 2px', borderTop: `1px solid ${tokens.colors.border.muted}`,\n }}>{label}</div>\n {children}\n </div>\n );\n}\n\n/**\n * Image detail panel showing preview, metadata, camera settings, and position.\n * Displayed inline when a gallery thumbnail is clicked.\n */\nfunction CaptureImageDetail({ img, tokens, serverId, onClose }: {\n img: CapturedImage; tokens: any; serverId: string; onClose: () => void;\n}) {\n const a = img.args;\n const time = new Date(img.timestamp).toLocaleString('en-US', {\n hour12: false, year: 'numeric', month: 'short', day: 'numeric',\n hour: '2-digit', minute: '2-digit', second: '2-digit',\n });\n\n return (\n <div style={{\n backgroundColor: tokens.colors.background.elevated,\n display: 'flex',\n gap: '8px',\n padding: '8px',\n minHeight: 0,\n }}>\n {/* Left: Image preview + actions */}\n <div style={{\n flex: '1 1 50%', display: 'flex', flexDirection: 'column' as const, gap: '6px',\n minWidth: 0,\n }}>\n <img\n src={img.dataUrl}\n alt={`capture_${serverId}_${img.reqId}`}\n style={{\n width: '100%', borderRadius: tokens.borderRadius.sm,\n border: `1px solid ${tokens.colors.border.muted}`,\n objectFit: 'contain' as const,\n }}\n />\n <div style={{ display: 'flex', gap: '4px' }}>\n <button\n type=\"button\"\n onClick={() => downloadCapturedImage(img, serverId)}\n style={{\n flex: 1, display: 'flex', alignItems: 'center', justifyContent: 'center', gap: '4px',\n padding: '5px 0', borderRadius: tokens.borderRadius.sm,\n fontSize: tokens.typography.fontSize.xs, fontWeight: 500,\n fontFamily: tokens.typography.fontFamily.mono,\n color: tokens.colors.accent.primary,\n backgroundColor: `${tokens.colors.accent.primary}12`,\n border: `1px solid ${tokens.colors.accent.primary}30`,\n cursor: 'pointer',\n }}\n >\n <DownloadIcon /> Download PNG\n </button>\n <button\n type=\"button\"\n onClick={onClose}\n style={{\n padding: '5px 8px', borderRadius: tokens.borderRadius.sm,\n fontSize: tokens.typography.fontSize.xs,\n color: tokens.colors.text.tertiary,\n backgroundColor: 'transparent',\n border: `1px solid ${tokens.colors.border.muted}`,\n cursor: 'pointer',\n }}\n >\n <CloseIcon />\n </button>\n </div>\n </div>\n\n {/* Right: Metadata */}\n <div style={{\n flex: '1 1 50%', overflowY: 'auto' as const, minWidth: 0,\n }}>\n <MetaGroup label=\"File Info\" tokens={tokens}>\n <MetaRow label=\"Filename\" value={`capture_${serverId}_${img.reqId}.${img.args?.format === 'jpeg' ? 'jpg' : 'png'}`} tokens={tokens} mono />\n <MetaRow label=\"Req ID\" value={`#${img.reqId}`} tokens={tokens} mono />\n <MetaRow label=\"Size\" value={fmtBytes(img.bytes)} tokens={tokens} />\n <MetaRow label=\"Format\" value={img.args?.format === 'jpeg' ? `JPEG (q=${Math.round((img.args.jpeg_quality ?? 0.92) * 100)}%)` : 'PNG'} tokens={tokens} />\n <MetaRow label=\"Captured\" value={time} tokens={tokens} />\n </MetaGroup>\n\n {/* Camera settings (only if args are available) */}\n {a && (\n <>\n <MetaGroup label=\"Camera\" tokens={tokens}>\n <MetaRow label=\"Resolution\" value={`${a.resolution}px`} tokens={tokens} />\n <MetaRow label=\"FOV\" value={`${a.fov}°`} tokens={tokens} />\n <MetaRow label=\"Focal Length\" value={`${a.focal_length}mm`} tokens={tokens} />\n <MetaRow label=\"Aperture\" value={`f/${a.aperture}`} tokens={tokens} />\n <MetaRow label=\"CoC\" value={`${a.coc}mm`} tokens={tokens} />\n <MetaRow label=\"Pixel Pitch\" value={`${a.pixel_pitch}mm`} tokens={tokens} />\n <MetaRow label=\"Focus Dist\" value={`${a.focusing_distance}m`} tokens={tokens} />\n <MetaRow label=\"Monochrome\" value={a.monochromatic ? 'Yes' : 'No'} tokens={tokens} />\n <MetaRow label=\"Sample\" value={a.sample ? 'Yes (½ res)' : 'No'} tokens={tokens} />\n </MetaGroup>\n\n <MetaGroup label=\"Position & Orientation\" tokens={tokens}>\n <MetaRow label=\"X\" value={`${a.position[0].toFixed(2)} km`} tokens={tokens} mono />\n <MetaRow label=\"Y\" value={`${a.position[1].toFixed(2)} km`} tokens={tokens} mono />\n <MetaRow label=\"Z\" value={`${a.position[2].toFixed(2)} km`} tokens={tokens} mono />\n <MetaRow label=\"Heading\" value={`${a.rotation[0].toFixed(1)}°`} tokens={tokens} mono />\n <MetaRow label=\"Pitch\" value={`${a.rotation[1].toFixed(1)}°`} tokens={tokens} mono />\n <MetaRow label=\"Roll\" value={`${a.rotation[2].toFixed(1)}°`} tokens={tokens} mono />\n </MetaGroup>\n </>\n )}\n </div>\n </div>\n );\n}\n\n/**\n * Collapsible image gallery with thumbnails, detail panel, download per-image, and download-all.\n * Part of the Capture component's built-in UI.\n */\nfunction CaptureGallery({ images, expanded, onToggle, tokens, serverId }: {\n images: CapturedImage[]; expanded: boolean; onToggle: () => void; tokens: any; serverId: string;\n}) {\n const [selectedIdx, setSelectedIdx] = useState<number | null>(null);\n const selectedImg = selectedIdx !== null ? images[selectedIdx] : null;\n\n return (\n <div style={{\n borderTop: `1px solid ${tokens.colors.border.muted}`,\n /* Fill remaining space when expanded */\n ...(expanded ? { flex: 1, display: 'flex', flexDirection: 'column' as const, minHeight: 0, overflow: 'hidden' } : {}),\n }}>\n {/* Header row: toggle + count + download-all */}\n <div style={{\n display: 'flex', alignItems: 'center', gap: '4px', flexShrink: 0,\n }}>\n <button\n type=\"button\"\n onClick={onToggle}\n aria-expanded={expanded}\n aria-label={`Captured images, ${images.length} total`}\n style={{\n flex: 1, display: 'flex', alignItems: 'center', gap: '8px',\n padding: '8px 12px',\n fontSize: tokens.typography.fontSize.sm,\n fontWeight: 500,\n fontFamily: tokens.typography.fontFamily.primary,\n color: tokens.colors.text.secondary,\n backgroundColor: 'transparent',\n border: 'none',\n cursor: 'pointer',\n outline: 'none',\n textAlign: 'left' as const,\n }}\n >\n <ChevronIcon expanded={expanded} />\n <span>Captured Images</span>\n {images.length > 0 && (\n <span style={{\n fontSize: tokens.typography.fontSize.xs,\n color: tokens.colors.text.tertiary,\n fontFamily: tokens.typography.fontFamily.mono,\n }}>\n ({images.length})\n </span>\n )}\n </button>\n\n {/* Download All button (visible when expanded and has images) */}\n {expanded && images.length > 0 && (\n <button\n type=\"button\"\n onClick={() => downloadAllImages(images, serverId)}\n title={`Download all ${images.length} images`}\n style={{\n display: 'flex', alignItems: 'center', gap: '4px',\n padding: '4px 8px', marginRight: 8,\n fontSize: '0.62rem', fontWeight: 500,\n fontFamily: tokens.typography.fontFamily.mono,\n color: tokens.colors.text.tertiary,\n backgroundColor: 'transparent',\n border: `1px solid ${tokens.colors.border.muted}`,\n borderRadius: tokens.borderRadius.sm,\n cursor: 'pointer',\n whiteSpace: 'nowrap' as const,\n }}\n >\n <DownloadIcon size={10} /> All\n </button>\n )}\n </div>\n\n {expanded && (\n <div style={{\n flex: 1, minHeight: 0, display: 'flex',\n overflow: 'hidden',\n }}>\n {images.length === 0 ? (\n <div style={{\n fontSize: tokens.typography.fontSize.sm,\n color: tokens.colors.text.tertiary,\n padding: '12px',\n textAlign: 'center' as const,\n width: '100%',\n }}>\n No images captured yet\n </div>\n ) : (\n <>\n {/* Left: scrollable thumbnail grid\n - Detail panel open (200px strip): 2 columns fixed\n - Full width: 4 columns on desktop, collapses via auto-fill on narrow viewports */}\n <div style={{\n width: selectedImg ? 200 : '100%',\n flexShrink: 0,\n overflowY: 'auto' as const,\n padding: '6px',\n borderRight: selectedImg ? `1px solid ${tokens.colors.border.muted}` : 'none',\n display: 'grid',\n gridTemplateColumns: selectedImg\n ? 'repeat(2, 1fr)'\n : 'repeat(auto-fill, minmax(min(120px, 100%), 1fr))',\n gridAutoRows: 'min-content',\n gap: '4px',\n alignContent: 'start' as const,\n }}>\n {images.map((img, idx) => {\n const isSelected = selectedIdx === idx;\n return (\n <div\n key={`${img.reqId}-${img.timestamp}`}\n onClick={() => setSelectedIdx(isSelected ? null : idx)}\n style={{\n position: 'relative' as const,\n aspectRatio: '1',\n borderRadius: tokens.borderRadius.sm,\n overflow: 'hidden',\n border: `2px solid ${isSelected ? tokens.colors.accent.primary : tokens.colors.border.muted}`,\n backgroundColor: tokens.colors.background.elevated,\n cursor: 'pointer',\n transition: 'border-color 0.15s',\n }}\n >\n <img\n src={img.dataUrl}\n alt={`capture_${serverId}_${img.reqId}`}\n style={{ width: '100%', height: '100%', objectFit: 'cover' as const, display: 'block' }}\n />\n {/* Bottom label: #reqId + size */}\n <div style={{\n position: 'absolute' as const,\n bottom: 0, left: 0, right: 0,\n display: 'flex', justifyContent: 'space-between',\n padding: '2px 4px',\n fontSize: '9px',\n fontFamily: tokens.typography.fontFamily.mono,\n color: '#fff',\n backgroundColor: 'rgba(0, 0, 0, 0.65)',\n }}>\n <span>#{img.reqId}</span>\n <span>{fmtBytes(img.bytes)}</span>\n </div>\n </div>\n );\n })}\n </div>\n\n {/* Right: detail panel for selected image */}\n {selectedImg && (\n <div style={{ flex: 1, minWidth: 0, overflowY: 'auto' as const }}>\n <CaptureImageDetail\n img={selectedImg}\n tokens={tokens}\n serverId={serverId}\n onClose={() => setSelectedIdx(null)}\n />\n </div>\n )}\n </>\n )}\n </div>\n )}\n </div>\n );\n}\n\nexport default Capture;\n"],"names":["Capture"],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  import { default as React } from 'react';
2
- import { StatusLevel } from '../utils';
2
+ import { StatusLevel } from '../../utils';
3
3
 
4
4
  /** Status alert block — renders as a colored banner with icon shape */
5
5
  export interface ChatBlockAlert {
@@ -1,7 +1,7 @@
1
1
  import { jsxs, jsx } from "react/jsx-runtime";
2
2
  import React, { memo, useState, useRef, useEffect, useCallback } from "react";
3
- import { safeAccentText } from "../utils/index.js";
4
- import { useTheme } from "../theme/ThemeProvider.js";
3
+ import { safeAccentText } from "../../utils/index.js";
4
+ import { useTheme } from "../../theme/ThemeProvider.js";
5
5
  function parseYamlLite(text) {
6
6
  const lines = [];
7
7
  for (const raw of text.split("\n")) {
@@ -1107,9 +1107,10 @@ const ChatPanel = memo(function ChatPanel2({
1107
1107
  color: tokens.colors.text.primary,
1108
1108
  backgroundColor: tokens.colors.background.base,
1109
1109
  outline: "none",
1110
- transition: tokens.animation.fast,
1110
+ transition: "border-color 150ms, background-color 150ms",
1111
1111
  maxHeight: 120,
1112
- lineHeight: 1.5
1112
+ lineHeight: 1.5,
1113
+ overflowY: "auto"
1113
1114
  }
1114
1115
  }
1115
1116
  ),
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ChatPanel.js","sources":["../../../../src/react/core/widgets/ChatPanel.tsx"],"sourcesContent":["/**\n * @zendir/ui - ChatPanel Component\n * \n * Status-aware chat interface for operator dashboards with AI/command assistance.\n * Supports structured message blocks (alerts, telemetry, status cards, data tables)\n * alongside plain text, markdown, and code.\n * \n * Astro UX Compliance:\n * - 6-level status system with dual-coded shapes (color + shape)\n * - Glass-morphism for message bubbles\n * - Monospace for code/command content\n * - Focus management and keyboard shortcuts\n * \n * AI Integration:\n * - Messages can include structured `blocks` that the AI emits\n * - Four integration strategies: Tool/Function Calling, YAML, JSON, and MCP\n * - Tool/Function calling schemas for OpenAI, Anthropic, Gemini, and MCP servers\n * - `parseChatResponse()` — universal parser for JSON, YAML, and plain text\n * - `parseMcpToolResult()` — bridge MCP tool results to ChatPanel blocks\n * - `CHAT_RESPONSE_TOOL_SCHEMA` — drop-in function schema for LLM API calls\n * - `CHAT_RESPONSE_MCP_TOOL` — MCP server tool definition for structured responses\n * - `CHAT_RESPONSE_YAML_PROMPT` — system prompt snippet for YAML mode\n * \n * @example\n * ```tsx\n * <ChatPanel\n * messages={messages}\n * onSend={(text) => handleSend(text)}\n * loading={isStreaming}\n * placeholder=\"Ask about telemetry...\"\n * title=\"AI Assistant\"\n * />\n * ```\n */\n\nimport React, { memo, useState, useCallback, useEffect, useRef } from 'react';\nimport { useTheme } from '../../theme';\nimport { safeAccentText } from '../../utils';\nimport type { StatusLevel } from '../../utils';\n\n// ─── Types ───────────────────────────────────────────────────────────────────\n\n/** Status alert block — renders as a colored banner with icon shape */\nexport interface ChatBlockAlert {\n type: 'alert';\n status: StatusLevel;\n title: string;\n detail?: string;\n}\n\n/** Telemetry readout block — key/value pairs with optional status per row */\nexport interface ChatBlockTelemetry {\n type: 'telemetry';\n title?: string;\n items: Array<{\n label: string;\n value: string | number;\n unit?: string;\n status?: StatusLevel;\n }>;\n}\n\n/** Progress block — inline progress bar */\nexport interface ChatBlockProgress {\n type: 'progress';\n label: string;\n value: number;\n max?: number;\n status?: StatusLevel;\n}\n\n/** Data table block */\nexport interface ChatBlockTable {\n type: 'table';\n title?: string;\n columns: string[];\n rows: (string | number)[][];\n}\n\n/** Action buttons block */\nexport interface ChatBlockActions {\n type: 'actions';\n buttons: Array<{ label: string; variant?: 'primary' | 'secondary' | 'critical'; onClick: () => void }>;\n}\n\n/** Choice/option selector — AI presents options, user picks one (or multiple) */\nexport interface ChatBlockChoice {\n type: 'choice';\n /** Unique ID for this choice block (used in onBlockEvent callback) */\n id: string;\n title?: string;\n /** Allow multiple selections */\n multiple?: boolean;\n options: Array<{\n id: string;\n label: string;\n description?: string;\n status?: StatusLevel;\n disabled?: boolean;\n }>;\n /** Pre-selected option IDs */\n selected?: string[];\n /** Has the user already submitted their choice? */\n submitted?: boolean;\n}\n\n/** Confirmation gate — requires explicit operator acknowledgment before proceeding */\nexport interface ChatBlockConfirm {\n type: 'confirm';\n /** Unique ID for this confirm block (used in onBlockEvent callback) */\n id: string;\n status?: StatusLevel;\n title: string;\n detail?: string;\n confirmLabel?: string;\n cancelLabel?: string;\n /** Has the operator already responded? */\n resolved?: 'confirmed' | 'cancelled';\n}\n\n/** Command block — displays a command with copy-to-clipboard and optional execute */\nexport interface ChatBlockCommand {\n type: 'command';\n /** Unique ID for this command block (used in onBlockEvent callback) */\n id?: string;\n language?: string;\n command: string;\n label?: string;\n /** Show an execute button (fires onBlockEvent with action:'execute') */\n executable?: boolean;\n}\n\n/** Key-value metadata block — compact pairs for context/metadata */\nexport interface ChatBlockKV {\n type: 'kv';\n title?: string;\n pairs: Array<{ key: string; value: string | number; mono?: boolean }>;\n}\n\nexport type ChatBlock =\n | ChatBlockAlert\n | ChatBlockTelemetry\n | ChatBlockProgress\n | ChatBlockTable\n | ChatBlockActions\n | ChatBlockChoice\n | ChatBlockConfirm\n | ChatBlockCommand\n | ChatBlockKV;\n\n/** Event emitted by interactive blocks (choice, confirm, command) */\nexport interface ChatBlockEvent {\n /** The block ID */\n blockId: string;\n /** The message ID containing this block */\n messageId: string;\n /** Action type */\n action: 'select' | 'confirm' | 'cancel' | 'execute' | 'copy';\n /** Payload (selected option IDs for choice, command string for execute/copy) */\n value?: string | string[];\n}\n\nexport interface ChatMessage {\n /** Unique message ID */\n id: string;\n /** Message content (supports markdown-like formatting) */\n content: string;\n /** Sender role */\n role: 'user' | 'assistant' | 'system';\n /** Timestamp (ms) */\n timestamp?: number;\n /** Message delivery status */\n status?: 'sending' | 'sent' | 'error';\n /** Astro UX severity — colors the message accent (system messages default to this) */\n severity?: StatusLevel;\n /** Structured blocks rendered below the text content */\n blocks?: ChatBlock[];\n /** Legacy: action buttons (prefer blocks with type:'actions') */\n actions?: Array<{ label: string; onClick: () => void }>;\n}\n\nexport interface ChatPanelProps {\n /** Array of messages */\n messages: ChatMessage[];\n /** Send handler */\n onSend: (text: string) => void;\n /** Is assistant currently generating */\n loading?: boolean;\n /** Input placeholder */\n placeholder?: string;\n /** Panel title */\n title?: string;\n /** Subtitle (e.g. model name) */\n subtitle?: string;\n /** Disable input */\n disabled?: boolean;\n /** Show timestamps */\n showTimestamps?: boolean;\n /** Height of the panel (default: 100%) */\n height?: string | number;\n /** Clear handler (shows clear button when provided) */\n onClear?: () => void;\n /** Handler for interactive block events (choice selection, confirm/cancel, command execute) */\n onBlockEvent?: (event: ChatBlockEvent) => void;\n /** Custom style */\n style?: React.CSSProperties;\n}\n\n// ─── Response format & parser ────────────────────────────────────────────────\n\n/**\n * Supported response formats from the AI backend.\n * - 'json': Standard JSON (default). Most compatible.\n * - 'yaml': YAML compact format. ~30-40% fewer tokens than JSON for identical data.\n * - 'auto': Auto-detect (tries JSON first, then YAML, then plain text).\n */\nexport type ChatResponseFormat = 'json' | 'yaml' | 'auto';\n\n/** Shape of a parsed AI response (content + optional blocks + severity). */\nexport interface ChatResponsePayload {\n content: string;\n severity?: StatusLevel;\n blocks?: ChatBlock[];\n}\n\n/** Options for creating a customised response parser. */\nexport interface ChatResponseParserOptions {\n /**\n * Custom YAML parser function. Receives raw YAML text, returns a parsed object.\n * If not provided, uses the built-in lightweight parser.\n *\n * For production, plug in `js-yaml` or `yaml`:\n * ```ts\n * import yaml from 'js-yaml';\n * const parse = createChatResponseParser({ yamlParser: (s) => yaml.load(s) });\n * ```\n */\n yamlParser?: (text: string) => unknown;\n /** Default format when not specified per-call. Defaults to `'auto'`. */\n defaultFormat?: ChatResponseFormat;\n /** Custom message ID generator. Defaults to `crypto.randomUUID()`. */\n idGenerator?: () => string;\n}\n\n// ─── Built-in YAML parser (recursive descent) ───────────────────────────────\n\n/**\n * Lightweight recursive-descent YAML parser for AI response structures.\n *\n * Handles: mappings, sequences, nested structures, scalars (string, number,\n * boolean, null), quoted strings, inline JSON arrays/objects, comments.\n *\n * Does NOT handle: multi-line strings, anchors/aliases, tags, flow collections\n * across lines, merge keys, or other advanced YAML features.\n *\n * For production with complex YAML, plug in `js-yaml` or `yaml` via\n * `createChatResponseParser({ yamlParser })`.\n */\nfunction parseYamlLite(text: string): unknown {\n type Line = { indent: number; text: string };\n const lines: Line[] = [];\n for (const raw of text.split('\\n')) {\n const content = raw.trimEnd();\n if (content.trim() === '' || content.trim().startsWith('#')) continue;\n lines.push({ indent: content.search(/\\S/), text: content.trim() });\n }\n\n let pos = 0;\n const peek = (): Line | null => (pos < lines.length ? lines[pos] : null);\n const advance = (): Line => lines[pos++];\n\n function scalar(s: string): unknown {\n const v = s.trim();\n if (v === '' || v === 'null' || v === '~') return null;\n if (v === 'true') return true;\n if (v === 'false') return false;\n if (/^-?\\d+(\\.\\d+)?([eE][+-]?\\d+)?$/.test(v)) return Number(v);\n if ((v.startsWith('\"') && v.endsWith('\"')) || (v.startsWith(\"'\") && v.endsWith(\"'\")))\n return v.slice(1, -1);\n if ((v.startsWith('[') && v.endsWith(']')) || (v.startsWith('{') && v.endsWith('}'))) {\n try { return JSON.parse(v); } catch { /* fall through */ }\n }\n return v;\n }\n\n function parseValue(minIndent: number): unknown {\n const line = peek();\n if (!line || line.indent < minIndent) return undefined;\n const actualIndent = line.indent;\n if (line.text.startsWith('- ')) return parseSequence(actualIndent);\n return parseMapping(actualIndent);\n }\n\n function parseSequence(level: number): unknown[] {\n const arr: unknown[] = [];\n while (peek() && peek()!.indent === level && peek()!.text.startsWith('- ')) {\n const line = advance();\n const after = line.text.slice(2).trim();\n\n if (!after) {\n // Bare `- ` → nested value on next lines\n const val = parseValue(level + 1);\n arr.push(val ?? null);\n continue;\n }\n\n const colonIdx = after.indexOf(':');\n if (colonIdx > 0 && !/^['\"]/.test(after)) {\n // Inline mapping start: `- key: value`\n const obj: Record<string, unknown> = {};\n const k = after.slice(0, colonIdx).trim();\n const v = after.slice(colonIdx + 1).trim();\n obj[k] = v ? scalar(v) : (parseValue(level + 3) ?? null);\n\n // Read sibling keys at `level + 2` (aligned with content after `- `)\n const siblingIndent = level + 2;\n while (peek() && peek()!.indent >= siblingIndent) {\n if (peek()!.indent === siblingIndent && !peek()!.text.startsWith('- ')) {\n const next = advance();\n const ci = next.text.indexOf(':');\n if (ci > 0) {\n const nk = next.text.slice(0, ci).trim();\n const nv = next.text.slice(ci + 1).trim();\n obj[nk] = nv ? scalar(nv) : (parseValue(siblingIndent + 1) ?? null);\n }\n } else if (peek()!.indent > siblingIndent) {\n // Deeper content should have been consumed by parseValue above;\n // if not, skip it to avoid infinite loops\n advance();\n } else {\n break;\n }\n }\n arr.push(obj);\n } else {\n // Simple scalar: `- value`\n arr.push(scalar(after));\n }\n }\n return arr;\n }\n\n function parseMapping(level: number): Record<string, unknown> {\n const obj: Record<string, unknown> = {};\n while (peek() && peek()!.indent === level && !peek()!.text.startsWith('- ')) {\n const line = advance();\n const colonIdx = line.text.indexOf(':');\n if (colonIdx <= 0) continue;\n const k = line.text.slice(0, colonIdx).trim();\n const v = line.text.slice(colonIdx + 1).trim();\n obj[k] = v ? scalar(v) : (parseValue(level + 1) ?? null);\n }\n return obj;\n }\n\n try {\n return parseValue(0) ?? {};\n } catch {\n return {};\n }\n}\n\n// ─── Sanitize parsed blocks ─────────────────────────────────────────────────\n\n/** Ensure parsed blocks have the correct array shapes so renderers never crash. */\nfunction sanitizeBlocks(blocks: unknown): ChatBlock[] | undefined {\n if (!Array.isArray(blocks)) return undefined;\n return blocks\n .filter((b): b is Record<string, unknown> => b != null && typeof b === 'object' && typeof (b as Record<string, unknown>).type === 'string')\n .map((b) => {\n const block = { ...b } as Record<string, unknown>;\n // Ensure required arrays exist for each block type\n switch (block.type) {\n case 'telemetry':\n if (!Array.isArray(block.items)) block.items = [];\n break;\n case 'table':\n if (!Array.isArray(block.columns)) block.columns = [];\n if (!Array.isArray(block.rows)) block.rows = [];\n break;\n case 'actions':\n if (!Array.isArray(block.buttons)) block.buttons = [];\n break;\n case 'choice':\n if (!Array.isArray(block.options)) block.options = [];\n if (typeof block.id !== 'string') block.id = `choice-${Date.now()}`;\n break;\n case 'confirm':\n if (typeof block.id !== 'string') block.id = `confirm-${Date.now()}`;\n if (typeof block.title !== 'string') block.title = '';\n break;\n case 'command':\n if (typeof block.command !== 'string') block.command = '';\n break;\n case 'kv':\n if (!Array.isArray(block.pairs)) block.pairs = [];\n break;\n case 'alert':\n if (typeof block.title !== 'string') block.title = '';\n if (typeof block.status !== 'string') block.status = 'normal';\n break;\n case 'progress':\n if (typeof block.label !== 'string') block.label = '';\n if (typeof block.value !== 'number') block.value = 0;\n break;\n }\n return block as unknown as ChatBlock;\n });\n}\n\n// ─── Generate message ID ────────────────────────────────────────────────────\n\nfunction generateId(custom?: () => string): string {\n if (custom) return custom();\n if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') return crypto.randomUUID();\n return `msg-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;\n}\n\n// ─── Core parse logic ───────────────────────────────────────────────────────\n\nfunction parseRaw(\n raw: string,\n format: ChatResponseFormat,\n yamlParser?: (text: string) => unknown,\n): ChatResponsePayload | null {\n const tryJSON = (s: string): ChatResponsePayload | null => {\n try {\n const parsed = JSON.parse(s);\n if (parsed && typeof parsed === 'object' && typeof parsed.content === 'string') return parsed;\n return null;\n } catch { return null; }\n };\n\n const tryYAML = (s: string): ChatResponsePayload | null => {\n try {\n const parser = yamlParser ?? parseYamlLite;\n const parsed = parser(s);\n if (parsed && typeof parsed === 'object' && typeof (parsed as Record<string, unknown>).content === 'string')\n return parsed as unknown as ChatResponsePayload;\n return null;\n } catch { return null; }\n };\n\n if (format === 'json') return tryJSON(raw);\n if (format === 'yaml') return tryYAML(raw);\n // auto: try JSON first, then YAML\n return tryJSON(raw) ?? tryYAML(raw);\n}\n\n/**\n * Parse an AI response string into a `ChatMessage`.\n *\n * Supports three strategies (controlled by `format`):\n * - **json**: Parse as JSON. Falls back to plain text on failure.\n * - **yaml**: Parse as YAML (built-in lightweight parser). ~30-40% fewer tokens.\n * - **auto** (default): Try JSON → YAML → plain text.\n *\n * All parsed blocks are sanitized to ensure required arrays exist, preventing\n * runtime crashes from malformed AI output.\n *\n * ## Why YAML?\n * For the same structured response, YAML uses ~30-40% fewer tokens:\n * ```\n * JSON (~180 tokens): {\"content\":\"Battery low.\",\"blocks\":[{\"type\":\"alert\",...}]}\n * YAML (~120 tokens): content: Battery low.\\nblocks:\\n - type: alert\\n ...\n * ```\n *\n * ## Tool/Function Calling (recommended for production)\n * Pass `CHAT_RESPONSE_TOOL_SCHEMA` in your API call. The model is constrained\n * at the decoding level — zero prompt tokens for the schema.\n *\n * ## Custom YAML parser\n * Use `createChatResponseParser({ yamlParser })` to plug in `js-yaml` or `yaml`.\n *\n * @example\n * ```ts\n * const msg = parseChatResponse(aiOutput); // auto-detect\n * const msg = parseChatResponse(aiOutput, 'yaml'); // force YAML\n * const msg = parseChatResponse(toolCallArgs, 'json'); // from function call\n * ```\n */\nexport function parseChatResponse(\n raw: string,\n format: ChatResponseFormat = 'auto',\n options?: ChatResponseParserOptions,\n): ChatMessage {\n const id = generateId(options?.idGenerator);\n const base: Pick<ChatMessage, 'id' | 'role' | 'timestamp'> = {\n id, role: 'assistant', timestamp: Date.now(),\n };\n\n const payload = parseRaw(raw, format, options?.yamlParser);\n if (payload) {\n return {\n ...base,\n content: payload.content ?? '',\n severity: payload.severity as StatusLevel | undefined,\n blocks: sanitizeBlocks(payload.blocks),\n };\n }\n return { ...base, content: raw };\n}\n\n/**\n * Create a pre-configured response parser.\n *\n * Use this to set global defaults (format, YAML parser, ID generator) so you\n * don't have to pass options on every call.\n *\n * @example\n * ```ts\n * import yaml from 'js-yaml';\n * import { createChatResponseParser } from '@zendir/ui';\n *\n * // Create once at app init\n * export const parseAI = createChatResponseParser({\n * yamlParser: (s) => yaml.load(s),\n * defaultFormat: 'yaml',\n * });\n *\n * // Use everywhere\n * const msg = parseAI(aiOutput);\n * ```\n */\nexport function createChatResponseParser(options: ChatResponseParserOptions = {}) {\n return (raw: string, format?: ChatResponseFormat): ChatMessage => {\n return parseChatResponse(raw, format ?? options.defaultFormat ?? 'auto', options);\n };\n}\n\n// ─── MCP (Model Context Protocol) Integration ───────────────────────────────\n\n/**\n * Lightweight types for MCP tool results.\n * These mirror the MCP specification without requiring the full SDK as a dependency.\n * @see https://modelcontextprotocol.io/specification/2025-11-25\n */\n\n/** A single content block in an MCP tool result. */\nexport interface McpToolContent {\n type: 'text' | 'image' | 'resource';\n text?: string;\n data?: string;\n mimeType?: string;\n resource?: { uri: string; text?: string; mimeType?: string };\n}\n\n/** MCP tool call result (matches `CallToolResult` from the spec). */\nexport interface McpToolResult {\n content: McpToolContent[];\n isError?: boolean;\n _meta?: Record<string, unknown>;\n}\n\n/**\n * Convert an MCP tool call result into a `ChatMessage` with structured blocks.\n *\n * Handles three patterns automatically:\n * 1. **Structured JSON/YAML** — Tool returns text matching `ChatResponsePayload` → parsed into typed blocks\n * 2. **Plain text** — Rendered as a simple assistant message with tool metadata\n * 3. **Error** — Rendered as a critical alert block\n *\n * This bridges the MCP protocol with ChatPanel's block rendering system, so any\n * MCP server tool can produce rich operator UIs without custom rendering code.\n *\n * @example\n * ```ts\n * import { parseMcpToolResult } from '@zendir/ui/react';\n *\n * // With use-mcp hook\n * const { callTool } = useMcp({ url: 'https://ops-server.example.com/mcp' });\n * const result = await callTool('get_satellite_health', { id: 'SAT-001' });\n * const msg = parseMcpToolResult('get_satellite_health', result);\n * setMessages(prev => [...prev, msg]);\n *\n * // With @modelcontextprotocol/sdk\n * const result = await mcpClient.callTool({ name: 'get_satellite_health', arguments: { id: 'SAT-001' } });\n * const msg = parseMcpToolResult('get_satellite_health', result);\n * ```\n */\nexport function parseMcpToolResult(\n toolName: string,\n result: McpToolResult,\n options?: { idGenerator?: () => string },\n): ChatMessage {\n const id = generateId(options?.idGenerator);\n const timestamp = Date.now();\n\n // Handle MCP errors\n if (result.isError) {\n const errorText = result.content\n ?.filter(c => c.type === 'text')\n .map(c => c.text)\n .join('\\n') || `Tool \"${toolName}\" failed`;\n return {\n id, role: 'assistant', timestamp,\n severity: 'critical' as StatusLevel,\n content: errorText,\n blocks: [{ type: 'alert' as const, status: 'critical' as StatusLevel, title: `MCP Tool Error: ${toolName}`, detail: errorText }],\n };\n }\n\n // Extract text content from MCP result\n const textParts = result.content?.filter(c => c.type === 'text').map(c => c.text ?? '') ?? [];\n const rawText = textParts.join('\\n');\n\n // Try parsing as structured ChatResponsePayload (JSON → YAML → plain)\n if (rawText.trim()) {\n const payload = parseRaw(rawText, 'auto');\n if (payload && payload.content) {\n return {\n id, role: 'assistant', timestamp,\n content: payload.content,\n severity: payload.severity as StatusLevel | undefined,\n blocks: sanitizeBlocks(payload.blocks),\n };\n }\n }\n\n // Plain text fallback with tool context\n return {\n id, role: 'assistant', timestamp,\n content: rawText || `Tool \\`${toolName}\\` completed successfully.`,\n blocks: [{\n type: 'kv' as const,\n title: 'MCP Tool Call',\n pairs: [\n { key: 'Tool', value: toolName, mono: true },\n ...(result._meta ? [{ key: 'Meta', value: JSON.stringify(result._meta), mono: true }] : []),\n ],\n }],\n };\n}\n\n/**\n * MCP server tool definition for the `respond_to_operator` tool.\n *\n * Register this on your MCP server to enable structured ChatPanel responses.\n * The schema is identical to `CHAT_RESPONSE_TOOL_SCHEMA` but formatted for the\n * MCP `server.tool()` registration API.\n *\n * Compatible with: `@modelcontextprotocol/sdk`, any MCP server implementation.\n *\n * @example\n * ```ts\n * import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\n * import { CHAT_RESPONSE_MCP_TOOL } from '@zendir/ui';\n *\n * const server = new McpServer({ name: 'ops-assistant', version: '1.0.0' });\n *\n * server.tool(\n * CHAT_RESPONSE_MCP_TOOL.name,\n * CHAT_RESPONSE_MCP_TOOL.description,\n * CHAT_RESPONSE_MCP_TOOL.inputSchema,\n * async ({ content, severity, blocks }) => ({\n * content: [{ type: 'text', text: JSON.stringify({ content, severity, blocks }) }],\n * })\n * );\n * ```\n */\nexport const CHAT_RESPONSE_MCP_TOOL = {\n name: 'respond_to_operator',\n description:\n 'Respond to the spacecraft operator with text content and optional structured UI blocks (alerts, telemetry, progress, tables, choices, confirmations, commands, key-value metadata). Use the Astro UX 6-level status system: normal, standby, caution, serious, critical, off.',\n inputSchema: {\n type: 'object' as const,\n required: ['content'],\n properties: {\n content: { type: 'string', description: 'Plain-text or markdown response shown to the operator.' },\n severity: { type: 'string', enum: ['normal', 'standby', 'caution', 'serious', 'critical', 'off'] },\n blocks: {\n type: 'array',\n description: 'Structured UI blocks rendered below the text content.',\n items: {\n type: 'object',\n required: ['type'],\n properties: {\n type: { type: 'string', enum: ['alert', 'telemetry', 'progress', 'table', 'choice', 'confirm', 'command', 'kv'] },\n status: { type: 'string', enum: ['normal', 'standby', 'caution', 'serious', 'critical', 'off'] },\n title: { type: 'string' },\n detail: { type: 'string' },\n label: { type: 'string' },\n value: { type: 'number' },\n id: { type: 'string' },\n command: { type: 'string' },\n executable: { type: 'boolean' },\n items: { type: 'array', items: { type: 'object', properties: { label: { type: 'string' }, value: {}, unit: { type: 'string' }, status: { type: 'string' } } } },\n columns: { type: 'array', items: { type: 'string' } },\n rows: { type: 'array', items: { type: 'array' } },\n options: { type: 'array', items: { type: 'object', properties: { id: { type: 'string' }, label: { type: 'string' }, description: { type: 'string' }, status: { type: 'string' } } } },\n pairs: { type: 'array', items: { type: 'object', properties: { key: { type: 'string' }, value: {}, mono: { type: 'boolean' } } } },\n },\n },\n },\n },\n },\n} as const;\n\n// ─── Tool / Function calling schema ─────────────────────────────────────────\n\n/**\n * OpenAI-compatible function/tool schema for structured chat responses.\n *\n * Pass this as a tool definition in your API call. The model is constrained\n * to emit valid JSON matching this schema — no prompt engineering required.\n *\n * Works with: OpenAI (Structured Outputs / function calling), Anthropic (Tool Use),\n * Google Gemini (Function Calling), Mistral, Cohere, and any OpenAI-compatible API.\n *\n * @example\n * ```ts\n * // OpenAI\n * tools: [{ type: 'function', function: CHAT_RESPONSE_TOOL_SCHEMA }]\n *\n * // Anthropic\n * tools: [{ name: CHAT_RESPONSE_TOOL_SCHEMA.name,\n * description: CHAT_RESPONSE_TOOL_SCHEMA.description,\n * input_schema: CHAT_RESPONSE_TOOL_SCHEMA.parameters }]\n *\n * // Google Gemini\n * tools: [{ functionDeclarations: [CHAT_RESPONSE_TOOL_SCHEMA] }]\n * ```\n */\nexport const CHAT_RESPONSE_TOOL_SCHEMA = {\n name: 'respond_to_operator',\n description:\n 'Respond to the spacecraft operator with text content and optional structured UI blocks (alerts, telemetry, progress, tables, choices, confirmations, commands, key-value metadata). Use the Astro UX 6-level status system: normal, standby, caution, serious, critical, off.',\n parameters: {\n type: 'object' as const,\n required: ['content'],\n properties: {\n content: {\n type: 'string',\n description: 'Plain-text or markdown response shown to the operator.',\n },\n severity: {\n type: 'string',\n enum: ['normal', 'standby', 'caution', 'serious', 'critical', 'off'],\n description: 'Overall message severity. Drives the accent color and icon.',\n },\n blocks: {\n type: 'array',\n description: 'Structured UI blocks rendered below the text content.',\n items: {\n type: 'object',\n required: ['type'],\n properties: {\n type: {\n type: 'string',\n enum: ['alert', 'telemetry', 'progress', 'table', 'choice', 'confirm', 'command', 'kv'],\n },\n status: { type: 'string', enum: ['normal', 'standby', 'caution', 'serious', 'critical', 'off'] },\n title: { type: 'string' },\n detail: { type: 'string' },\n items: {\n type: 'array',\n items: {\n type: 'object',\n properties: {\n label: { type: 'string' },\n value: {},\n unit: { type: 'string' },\n status: { type: 'string', enum: ['normal', 'standby', 'caution', 'serious', 'critical', 'off'] },\n },\n },\n },\n label: { type: 'string' },\n value: { type: 'number' },\n max: { type: 'number' },\n columns: { type: 'array', items: { type: 'string' } },\n rows: { type: 'array', items: { type: 'array' } },\n id: { type: 'string' },\n multiple: { type: 'boolean' },\n options: {\n type: 'array',\n items: {\n type: 'object',\n properties: {\n id: { type: 'string' },\n label: { type: 'string' },\n description: { type: 'string' },\n status: { type: 'string', enum: ['normal', 'standby', 'caution', 'serious', 'critical', 'off'] },\n disabled: { type: 'boolean' },\n },\n },\n },\n confirmLabel: { type: 'string' },\n cancelLabel: { type: 'string' },\n language: { type: 'string' },\n command: { type: 'string' },\n executable: { type: 'boolean' },\n pairs: {\n type: 'array',\n items: {\n type: 'object',\n properties: {\n key: { type: 'string' },\n value: {},\n mono: { type: 'boolean' },\n },\n },\n },\n },\n },\n },\n },\n },\n} as const;\n\n/**\n * JSON system prompt snippet — instructs the LLM to respond with JSON.\n * Include in your system prompt for the simplest integration path.\n */\nexport const CHAT_RESPONSE_JSON_PROMPT = `When reporting telemetry, status, or alerts, respond with a JSON object:\n\n{\n \"content\": \"Plain text explanation (supports **markdown**).\",\n \"severity\": \"normal\" | \"standby\" | \"caution\" | \"serious\" | \"critical\" | \"off\",\n \"blocks\": [\n { \"type\": \"alert\", \"status\": \"caution\", \"title\": \"Alert Title\", \"detail\": \"Description\" },\n { \"type\": \"telemetry\", \"title\": \"Subsystem\", \"items\": [{ \"label\": \"Temp\", \"value\": 72, \"unit\": \"°C\", \"status\": \"normal\" }] },\n { \"type\": \"progress\", \"label\": \"Operation\", \"value\": 75, \"max\": 100, \"status\": \"normal\" },\n { \"type\": \"table\", \"title\": \"Data\", \"columns\": [\"Col1\", \"Col2\"], \"rows\": [[\"val1\", \"val2\"]] },\n { \"type\": \"choice\", \"id\": \"unique-id\", \"title\": \"Pick one\", \"options\": [{ \"id\": \"opt1\", \"label\": \"Option 1\" }] },\n { \"type\": \"confirm\", \"id\": \"unique-id\", \"status\": \"caution\", \"title\": \"Confirm action\" },\n { \"type\": \"command\", \"id\": \"cmd-id\", \"command\": \"CMD SAT-001 EXECUTE\", \"executable\": true },\n { \"type\": \"kv\", \"title\": \"Context\", \"pairs\": [{ \"key\": \"Spacecraft\", \"value\": \"SAT-001\" }] }\n ]\n}\n\nStatus levels (Astro UX): normal (nominal), standby (idle), caution (approaching limit), serious (at limit), critical (exceeding limit), off (no data).\nAlways include \"content\". Only include \"blocks\" when structured data helps the operator.` as const;\n\n/**\n * YAML system prompt snippet — instructs the LLM to respond in compact YAML\n * instead of JSON. ~30-40% fewer output tokens for the same data.\n */\nexport const CHAT_RESPONSE_YAML_PROMPT = `Respond in YAML format (not JSON). Use this structure:\n\ncontent: Your plain-text or markdown response here.\nseverity: normal\nblocks:\n - type: alert\n status: caution\n title: Alert Title\n detail: Optional detail\n - type: telemetry\n title: Subsystem\n items:\n - label: Parameter\n value: 42.5\n unit: \"°C\"\n status: normal\n - type: progress\n label: Operation\n value: 75\n max: 100\n status: normal\n - type: choice\n id: unique-id\n title: Pick one\n options:\n - id: opt1\n label: Option 1\n status: normal\n - type: command\n id: cmd-id\n language: CCSDS-TC\n command: CMD SAT-001 EXECUTE\n executable: true\n - type: kv\n title: Context\n pairs:\n - key: Spacecraft\n value: SAT-001\n\nStatus levels (Astro UX): normal, standby, caution, serious, critical, off.\nAlways include \"content\". Only include \"blocks\" when structured data helps the operator.` as const;\n\n/**\n * Astro UX status rules snippet — append to any system prompt (JSON or YAML).\n * Gives the LLM concrete thresholds for assigning status levels.\n */\nexport const CHAT_STATUS_RULES_PROMPT = `Assign status levels using these thresholds:\n- Battery: normal >50%, standby 30-50%, caution 20-30%, serious 10-20%, critical <10%\n- Temperature: normal <70°C, caution 70-80°C, serious 80-85°C, critical >85°C\n- Signal: normal >-80 dBm, caution -80 to -90, serious -90 to -95, critical <-95 dBm\n- Memory/Storage: normal <70%, caution 70-85%, serious 85-95%, critical >95%\n\nGeneral rules:\n- \"normal\" → Operating within nominal parameters\n- \"standby\" → Idle, waiting, or scheduled\n- \"caution\" → Approaching a limit\n- \"serious\" → At or exceeding a soft limit\n- \"critical\" → Exceeding hard limit, loss of signal, or failure\n- \"off\" → Powered down, no data` as const;\n\n// ─── Status shape helper ─────────────────────────────────────────────────────\n\nfunction StatusShape({ status, size = 10, color }: { status: StatusLevel; size?: number; color: string }) {\n const glow = `${color}50`;\n switch (status) {\n case 'caution':\n return <svg viewBox=\"0 0 12 12\" width={size} height={size} style={{ filter: `drop-shadow(0 0 3px ${glow})` }}><rect x=\"1\" y=\"1\" width=\"10\" height=\"10\" fill={color} /></svg>;\n case 'serious':\n return <svg viewBox=\"0 0 12 12\" width={size} height={size} style={{ filter: `drop-shadow(0 0 3px ${glow})` }}><polygon points=\"6,1 11,6 6,11 1,6\" fill={color} /></svg>;\n case 'critical':\n return <svg viewBox=\"0 0 12 12\" width={size} height={size} style={{ filter: `drop-shadow(0 0 3px ${glow})` }}><polygon points=\"6,11 1,2 11,2\" fill={color} /></svg>;\n case 'standby':\n return <svg viewBox=\"0 0 12 12\" width={size} height={size} style={{ filter: `drop-shadow(0 0 3px ${glow})` }}><circle cx=\"6\" cy=\"6\" r=\"3.5\" fill=\"none\" stroke={color} strokeWidth=\"2\" /></svg>;\n case 'off':\n return <svg viewBox=\"0 0 12 12\" width={size} height={size} style={{ filter: `drop-shadow(0 0 3px ${glow})` }}><circle cx=\"6\" cy=\"6\" r=\"3\" fill={color} /></svg>;\n default:\n return <svg viewBox=\"0 0 12 12\" width={size} height={size} style={{ filter: `drop-shadow(0 0 3px ${glow})` }}><circle cx=\"6\" cy=\"6\" r=\"5\" fill={color} /></svg>;\n }\n}\n\n// ─── Block renderers ─────────────────────────────────────────────────────────\n\nfunction AlertBlock({ block }: { block: ChatBlockAlert }) {\n const { tokens } = useTheme();\n const color = tokens.colors.status[block.status];\n return (\n <div style={{\n display: 'flex', alignItems: 'flex-start', gap: 10,\n padding: '10px 14px',\n backgroundColor: `${color}12`,\n border: `1px solid ${color}30`,\n borderLeft: `3px solid ${color}`,\n borderRadius: tokens.borderRadius.md,\n marginTop: 8,\n }}>\n <div style={{ marginTop: 2, flexShrink: 0 }}>\n <StatusShape status={block.status} size={12} color={color} />\n </div>\n <div style={{ flex: 1, minWidth: 0 }}>\n <div style={{ fontSize: tokens.typography.fontSize.sm, fontWeight: 600, color: tokens.colors.text.primary }}>\n {block.title}\n </div>\n {block.detail && (\n <div style={{ fontSize: tokens.typography.fontSize.xs, color: tokens.colors.text.secondary, marginTop: 2, lineHeight: 1.5 }}>\n {block.detail}\n </div>\n )}\n </div>\n </div>\n );\n}\n\nfunction TelemetryBlock({ block }: { block: ChatBlockTelemetry }) {\n const { tokens } = useTheme();\n return (\n <div style={{\n marginTop: 8,\n border: `1px solid ${tokens.colors.border.muted}`,\n borderRadius: tokens.borderRadius.md,\n overflow: 'hidden',\n }}>\n {block.title && (\n <div style={{\n padding: '6px 12px',\n fontSize: tokens.typography.fontSize.xxs,\n fontWeight: 600,\n color: tokens.colors.text.secondary,\n textTransform: 'uppercase',\n letterSpacing: '0.05em',\n backgroundColor: `${tokens.colors.background.elevated}80`,\n borderBottom: `1px solid ${tokens.colors.border.muted}`,\n }}>\n {block.title}\n </div>\n )}\n <div style={{ padding: '8px 12px', display: 'flex', flexDirection: 'column', gap: 6 }}>\n {(block.items ?? []).map((item, i) => {\n const itemColor = item.status ? tokens.colors.status[item.status] : tokens.colors.text.secondary;\n return (\n <div key={i} style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 8, fontSize: tokens.typography.fontSize.sm }}>\n <span style={{ display: 'flex', alignItems: 'center', gap: 6, color: tokens.colors.text.secondary }}>\n {item.status && <StatusShape status={item.status} size={8} color={tokens.colors.status[item.status]} />}\n {item.label}\n </span>\n <span style={{\n fontFamily: tokens.typography.fontFamily.mono,\n fontVariantNumeric: 'tabular-nums',\n color: itemColor,\n fontWeight: 500,\n }}>\n {item.value}{item.unit ? ` ${item.unit}` : ''}\n </span>\n </div>\n );\n })}\n </div>\n </div>\n );\n}\n\nfunction ProgressBlock({ block }: { block: ChatBlockProgress }) {\n const { tokens } = useTheme();\n const max = block.max ?? 100;\n const pct = Math.min(100, Math.max(0, (block.value / max) * 100));\n const effectiveStatus: StatusLevel = block.status ?? (\n pct >= 75 ? 'normal' : pct >= 50 ? 'standby' : pct >= 25 ? 'caution' : pct > 0 ? 'serious' : 'off'\n );\n const color = tokens.colors.status[effectiveStatus];\n return (\n <div style={{ marginTop: 8 }}>\n <div style={{ display: 'flex', justifyContent: 'space-between', marginBottom: 4, fontSize: tokens.typography.fontSize.xs, color: tokens.colors.text.secondary }}>\n <span style={{ display: 'flex', alignItems: 'center', gap: 6 }}>\n <StatusShape status={effectiveStatus} size={8} color={color} />\n {block.label}\n </span>\n <span style={{ fontFamily: tokens.typography.fontFamily.mono, color: tokens.colors.text.primary }}>{pct.toFixed(0)}%</span>\n </div>\n <div style={{ height: 6, backgroundColor: tokens.colors.border.muted, borderRadius: 3, overflow: 'hidden' }}>\n <div style={{ height: '100%', width: `${pct}%`, backgroundColor: color, borderRadius: 3, transition: 'width 300ms', boxShadow: `0 0 6px ${color}40` }} />\n </div>\n </div>\n );\n}\n\nfunction TableBlock({ block }: { block: ChatBlockTable }) {\n const { tokens } = useTheme();\n return (\n <div style={{ marginTop: 8, border: `1px solid ${tokens.colors.border.muted}`, borderRadius: tokens.borderRadius.md, overflow: 'hidden' }}>\n {block.title && (\n <div style={{\n padding: '6px 12px',\n fontSize: tokens.typography.fontSize.xxs,\n fontWeight: 600,\n color: tokens.colors.text.secondary,\n textTransform: 'uppercase',\n letterSpacing: '0.05em',\n backgroundColor: `${tokens.colors.background.elevated}80`,\n borderBottom: `1px solid ${tokens.colors.border.muted}`,\n }}>\n {block.title}\n </div>\n )}\n <div style={{ overflowX: 'auto' }}>\n <table style={{ width: '100%', borderCollapse: 'collapse', fontSize: tokens.typography.fontSize.xs }}>\n <thead>\n <tr>\n {(block.columns ?? []).map((col, i) => (\n <th key={i} style={{\n padding: '6px 12px', textAlign: 'left', fontWeight: 600,\n color: tokens.colors.text.secondary,\n borderBottom: `1px solid ${tokens.colors.border.muted}`,\n whiteSpace: 'nowrap',\n }}>\n {col}\n </th>\n ))}\n </tr>\n </thead>\n <tbody>\n {(block.rows ?? []).map((row, ri) => (\n <tr key={ri}>\n {(row ?? []).map((cell, ci) => (\n <td key={ci} style={{\n padding: '5px 12px',\n color: tokens.colors.text.primary,\n fontFamily: typeof cell === 'number' ? tokens.typography.fontFamily.mono : undefined,\n fontVariantNumeric: typeof cell === 'number' ? 'tabular-nums' : undefined,\n borderBottom: ri < (block.rows ?? []).length - 1 ? `1px solid ${tokens.colors.border.muted}30` : 'none',\n whiteSpace: 'nowrap',\n }}>\n {cell}\n </td>\n ))}\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n </div>\n );\n}\n\nfunction ActionsBlock({ block }: { block: ChatBlockActions }) {\n const { tokens } = useTheme();\n return (\n <div style={{ display: 'flex', gap: 8, marginTop: 8, flexWrap: 'wrap' }}>\n {(block.buttons ?? []).map((btn, i) => {\n const isCritical = btn.variant === 'critical';\n const isPrimary = btn.variant === 'primary' || (!btn.variant && i === 0);\n const baseColor = isCritical ? tokens.colors.status.critical : tokens.colors.accent.primary;\n const textColor = isCritical ? tokens.colors.status.critical : safeAccentText(tokens.colors.accent.primary);\n return (\n <button key={i} onClick={btn.onClick} style={{\n fontSize: tokens.typography.fontSize.xxs, padding: '4px 14px',\n borderRadius: tokens.borderRadius.sm,\n border: `1px solid ${baseColor}${isPrimary ? '' : '40'}`,\n backgroundColor: isPrimary ? `${baseColor}20` : 'transparent',\n color: textColor, cursor: 'pointer',\n fontFamily: tokens.typography.fontFamily.primary,\n fontWeight: 500, transition: 'all 150ms',\n }}>\n {btn.label}\n </button>\n );\n })}\n </div>\n );\n}\n\nfunction ChoiceBlock({ block, messageId, onEvent }: { block: ChatBlockChoice; messageId: string; onEvent?: (e: ChatBlockEvent) => void }) {\n const { tokens } = useTheme();\n const [localSelected, setLocalSelected] = useState<Set<string>>(new Set(block.selected ?? []));\n const isSubmitted = block.submitted;\n\n const toggle = (optId: string) => {\n if (isSubmitted) return;\n setLocalSelected(prev => {\n const next = new Set(prev);\n if (block.multiple) {\n next.has(optId) ? next.delete(optId) : next.add(optId);\n } else {\n next.clear();\n next.add(optId);\n }\n return next;\n });\n };\n\n const submit = () => {\n if (localSelected.size === 0 || isSubmitted) return;\n onEvent?.({ blockId: block.id, messageId, action: 'select', value: Array.from(localSelected) });\n };\n\n return (\n <div style={{ marginTop: 8 }}>\n {block.title && (\n <div style={{ fontSize: tokens.typography.fontSize.xs, fontWeight: 600, color: tokens.colors.text.secondary, marginBottom: 6 }}>\n {block.title}{block.multiple ? ' (select multiple)' : ''}\n </div>\n )}\n <div style={{ display: 'flex', flexDirection: 'column', gap: 4 }}>\n {(block.options ?? []).map(opt => {\n const isSelected = localSelected.has(opt.id);\n const optColor = opt.status ? tokens.colors.status[opt.status] : tokens.colors.accent.primary;\n const isDisabled = opt.disabled || isSubmitted;\n return (\n <button key={opt.id} type=\"button\" onClick={() => toggle(opt.id)} disabled={isDisabled} style={{\n display: 'flex', alignItems: 'center', gap: 10, padding: '8px 12px',\n borderRadius: tokens.borderRadius.md, cursor: isDisabled ? 'default' : 'pointer',\n border: `1px solid ${isSelected ? optColor : tokens.colors.border.muted}`,\n backgroundColor: isSelected ? `${optColor}15` : 'transparent',\n transition: 'all 150ms', textAlign: 'left',\n fontFamily: tokens.typography.fontFamily.primary,\n opacity: isDisabled && !isSelected ? 0.5 : 1,\n }}>\n {/* Radio / checkbox indicator */}\n <div style={{\n width: 16, height: 16, flexShrink: 0,\n borderRadius: block.multiple ? 3 : '50%',\n border: `2px solid ${isSelected ? optColor : tokens.colors.border.muted}`,\n backgroundColor: isSelected ? optColor : 'transparent',\n display: 'flex', alignItems: 'center', justifyContent: 'center',\n transition: 'all 150ms',\n }}>\n {isSelected && (\n <svg viewBox=\"0 0 12 12\" width={10} height={10} fill=\"none\" stroke={tokens.colors.text.inverse} strokeWidth={2}>\n <polyline points=\"2,6 5,9 10,3\" />\n </svg>\n )}\n </div>\n <div style={{ flex: 1, minWidth: 0 }}>\n <div style={{ display: 'flex', alignItems: 'center', gap: 6 }}>\n {opt.status && <StatusShape status={opt.status} size={8} color={tokens.colors.status[opt.status]} />}\n <span style={{ fontSize: tokens.typography.fontSize.sm, color: tokens.colors.text.primary, fontWeight: 500 }}>{opt.label}</span>\n </div>\n {opt.description && (\n <div style={{ fontSize: tokens.typography.fontSize.xs, color: tokens.colors.text.tertiary, marginTop: 1 }}>{opt.description}</div>\n )}\n </div>\n </button>\n );\n })}\n </div>\n {!isSubmitted && onEvent && (\n <button type=\"button\" onClick={submit} disabled={localSelected.size === 0} style={{\n marginTop: 8, padding: '5px 18px', fontSize: tokens.typography.fontSize.xs,\n fontWeight: 600, borderRadius: tokens.borderRadius.sm,\n border: `1px solid ${tokens.colors.accent.primary}`,\n backgroundColor: localSelected.size > 0 ? `${tokens.colors.accent.primary}20` : 'transparent',\n color: localSelected.size > 0 ? safeAccentText(tokens.colors.accent.primary) : tokens.colors.text.tertiary,\n cursor: localSelected.size > 0 ? 'pointer' : 'not-allowed',\n fontFamily: tokens.typography.fontFamily.primary, transition: 'all 150ms',\n }}>\n Confirm Selection\n </button>\n )}\n {isSubmitted && (\n <div style={{ marginTop: 6, fontSize: tokens.typography.fontSize.xs, color: tokens.colors.text.tertiary, fontStyle: 'italic' }}>\n Selection submitted\n </div>\n )}\n </div>\n );\n}\n\nfunction ConfirmBlock({ block, messageId, onEvent }: { block: ChatBlockConfirm; messageId: string; onEvent?: (e: ChatBlockEvent) => void }) {\n const { tokens } = useTheme();\n const status = block.status ?? 'caution';\n const color = tokens.colors.status[status];\n const resolved = block.resolved;\n\n return (\n <div style={{\n marginTop: 8, padding: '12px 14px',\n backgroundColor: `${color}10`,\n border: `1px solid ${color}30`,\n borderLeft: `3px solid ${color}`,\n borderRadius: tokens.borderRadius.md,\n }}>\n <div style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 4 }}>\n <StatusShape status={status} size={12} color={color} />\n <span style={{ fontSize: tokens.typography.fontSize.sm, fontWeight: 600, color: tokens.colors.text.primary }}>{block.title}</span>\n </div>\n {block.detail && (\n <div style={{ fontSize: tokens.typography.fontSize.xs, color: tokens.colors.text.secondary, marginBottom: 8, lineHeight: 1.5 }}>{block.detail}</div>\n )}\n {!resolved && onEvent ? (\n <div style={{ display: 'flex', gap: 8 }}>\n <button type=\"button\" onClick={() => onEvent({ blockId: block.id, messageId, action: 'confirm' })} style={{\n padding: '5px 16px', fontSize: tokens.typography.fontSize.xs, fontWeight: 600,\n borderRadius: tokens.borderRadius.sm, cursor: 'pointer',\n border: `1px solid ${color}`, backgroundColor: `${color}20`, color,\n fontFamily: tokens.typography.fontFamily.primary, transition: 'all 150ms',\n }}>\n {block.confirmLabel ?? 'Confirm'}\n </button>\n <button type=\"button\" onClick={() => onEvent({ blockId: block.id, messageId, action: 'cancel' })} style={{\n padding: '5px 16px', fontSize: tokens.typography.fontSize.xs, fontWeight: 500,\n borderRadius: tokens.borderRadius.sm, cursor: 'pointer',\n border: `1px solid ${tokens.colors.border.muted}`, backgroundColor: 'transparent',\n color: tokens.colors.text.secondary,\n fontFamily: tokens.typography.fontFamily.primary, transition: 'all 150ms',\n }}>\n {block.cancelLabel ?? 'Cancel'}\n </button>\n </div>\n ) : resolved ? (\n <div style={{\n fontSize: tokens.typography.fontSize.xs, fontWeight: 500,\n color: resolved === 'confirmed' ? tokens.colors.status.normal : tokens.colors.text.tertiary,\n fontStyle: 'italic',\n }}>\n {resolved === 'confirmed' ? '✓ Confirmed' : '✗ Cancelled'}\n </div>\n ) : null}\n </div>\n );\n}\n\nfunction CommandBlock({ block, messageId, onEvent }: { block: ChatBlockCommand; messageId: string; onEvent?: (e: ChatBlockEvent) => void }) {\n const { tokens } = useTheme();\n const [copied, setCopied] = useState(false);\n\n const handleCopy = () => {\n navigator.clipboard?.writeText(block.command).then(() => {\n setCopied(true);\n setTimeout(() => setCopied(false), 2000);\n });\n if (block.id) onEvent?.({ blockId: block.id, messageId, action: 'copy', value: block.command });\n };\n\n const handleExecute = () => {\n if (block.id) onEvent?.({ blockId: block.id, messageId, action: 'execute', value: block.command });\n };\n\n return (\n <div style={{ marginTop: 8, borderRadius: tokens.borderRadius.md, overflow: 'hidden', border: `1px solid ${tokens.colors.border.muted}` }}>\n {block.label && (\n <div style={{\n padding: '5px 12px', fontSize: tokens.typography.fontSize.xxs, fontWeight: 600,\n color: tokens.colors.text.tertiary, textTransform: 'uppercase', letterSpacing: '0.05em',\n backgroundColor: `${tokens.colors.background.elevated}80`,\n borderBottom: `1px solid ${tokens.colors.border.muted}`,\n display: 'flex', alignItems: 'center', justifyContent: 'space-between',\n }}>\n <span>{block.label}{block.language ? ` · ${block.language}` : ''}</span>\n </div>\n )}\n <div style={{ position: 'relative' }}>\n <pre style={{\n margin: 0, padding: '10px 12px', paddingRight: 80,\n fontSize: tokens.typography.fontSize.xs, fontFamily: tokens.typography.fontFamily.mono,\n backgroundColor: `${tokens.colors.background.base}80`, color: tokens.colors.text.primary,\n overflowX: 'auto', lineHeight: 1.5,\n }}>\n {block.command}\n </pre>\n <div style={{ position: 'absolute', top: 6, right: 8, display: 'flex', gap: 4 }}>\n <button type=\"button\" onClick={handleCopy} style={{\n padding: '2px 8px', fontSize: tokens.typography.fontSize.micro, borderRadius: tokens.borderRadius.sm,\n border: `1px solid ${tokens.colors.border.muted}`, backgroundColor: tokens.colors.background.elevated,\n color: copied ? tokens.colors.status.normal : tokens.colors.text.tertiary,\n cursor: 'pointer', fontFamily: tokens.typography.fontFamily.primary, fontWeight: 500,\n }}>\n {copied ? '✓ Copied' : 'Copy'}\n </button>\n {block.executable && onEvent && block.id && (\n <button type=\"button\" onClick={handleExecute} style={{\n padding: '2px 8px', fontSize: tokens.typography.fontSize.micro, borderRadius: tokens.borderRadius.sm,\n border: `1px solid ${tokens.colors.accent.primary}60`,\n backgroundColor: `${tokens.colors.accent.primary}15`,\n color: safeAccentText(tokens.colors.accent.primary),\n cursor: 'pointer', fontFamily: tokens.typography.fontFamily.primary, fontWeight: 600,\n }}>\n Run\n </button>\n )}\n </div>\n </div>\n </div>\n );\n}\n\nfunction KVBlock({ block }: { block: ChatBlockKV }) {\n const { tokens } = useTheme();\n return (\n <div style={{\n marginTop: 8, padding: '8px 12px',\n backgroundColor: `${tokens.colors.background.elevated}40`,\n borderRadius: tokens.borderRadius.md,\n border: `1px solid ${tokens.colors.border.muted}`,\n }}>\n {block.title && (\n <div style={{\n fontSize: tokens.typography.fontSize.xxs, fontWeight: 600, color: tokens.colors.text.tertiary,\n textTransform: 'uppercase', letterSpacing: '0.05em', marginBottom: 6,\n }}>\n {block.title}\n </div>\n )}\n <div style={{ display: 'grid', gridTemplateColumns: 'auto 1fr', gap: '3px 16px', fontSize: tokens.typography.fontSize.xs }}>\n {(block.pairs ?? []).map((p, i) => (\n <React.Fragment key={i}>\n <span style={{ color: tokens.colors.text.tertiary, whiteSpace: 'nowrap' }}>{p.key}</span>\n <span style={{\n color: tokens.colors.text.primary,\n fontFamily: p.mono ? tokens.typography.fontFamily.mono : undefined,\n fontVariantNumeric: p.mono ? 'tabular-nums' : undefined,\n }}>\n {p.value}\n </span>\n </React.Fragment>\n ))}\n </div>\n </div>\n );\n}\n\nfunction renderBlock(block: ChatBlock, index: number, messageId: string, onEvent?: (e: ChatBlockEvent) => void) {\n switch (block.type) {\n case 'alert': return <AlertBlock key={index} block={block} />;\n case 'telemetry': return <TelemetryBlock key={index} block={block} />;\n case 'progress': return <ProgressBlock key={index} block={block} />;\n case 'table': return <TableBlock key={index} block={block} />;\n case 'actions': return <ActionsBlock key={index} block={block} />;\n case 'choice': return <ChoiceBlock key={index} block={block} messageId={messageId} onEvent={onEvent} />;\n case 'confirm': return <ConfirmBlock key={index} block={block} messageId={messageId} onEvent={onEvent} />;\n case 'command': return <CommandBlock key={index} block={block} messageId={messageId} onEvent={onEvent} />;\n case 'kv': return <KVBlock key={index} block={block} />;\n default: return null;\n }\n}\n\n// ─── Main component ──────────────────────────────────────────────────────────\n\nexport const ChatPanel = memo(function ChatPanel({\n messages = [],\n onSend,\n loading = false,\n placeholder = 'Type a message...',\n title,\n subtitle,\n disabled = false,\n showTimestamps = true,\n height = '100%',\n onClear,\n onBlockEvent,\n style,\n}: ChatPanelProps): React.ReactElement {\n const { tokens } = useTheme();\n const [input, setInput] = useState('');\n const messagesEndRef = useRef<HTMLDivElement>(null);\n const inputRef = useRef<HTMLTextAreaElement>(null);\n \n useEffect(() => {\n messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' });\n }, [messages, loading]);\n \n const handleSend = useCallback(() => {\n const text = input.trim();\n if (!text || disabled) return;\n onSend(text);\n setInput('');\n if (inputRef.current) inputRef.current.style.height = 'auto';\n }, [input, onSend, disabled]);\n \n const handleKeyDown = useCallback((e: React.KeyboardEvent) => {\n if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault(); handleSend(); }\n }, [handleSend]);\n \n const handleInput = useCallback((e: React.ChangeEvent<HTMLTextAreaElement>) => {\n setInput(e.target.value);\n const el = e.target;\n el.style.height = 'auto';\n el.style.height = `${Math.min(el.scrollHeight, 120)}px`;\n }, []);\n \n const formatTime = (ts?: number) => {\n if (!ts) return '';\n return new Date(ts).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });\n };\n \n // Markdown-ish rendering: **bold**, `code`, ```code blocks```, - lists\n const renderContent = (text: string) => {\n const parts: React.ReactNode[] = [];\n const lines = text.split('\\n');\n let inCode = false;\n let codeBlock: string[] = [];\n \n lines.forEach((line, i) => {\n if (line.startsWith('```')) {\n if (inCode) {\n parts.push(\n <pre key={`code-${i}`} style={{\n backgroundColor: `${tokens.colors.background.base}80`,\n padding: `${tokens.spacing.xs} ${tokens.spacing.sm}`,\n borderRadius: tokens.borderRadius.sm,\n fontSize: tokens.typography.fontSize.xs,\n fontFamily: tokens.typography.fontFamily.mono,\n overflowX: 'auto',\n margin: `${tokens.spacing.xs} 0`,\n border: `1px solid ${tokens.colors.border.muted}`,\n }}>\n {codeBlock.join('\\n')}\n </pre>\n );\n codeBlock = [];\n inCode = false;\n } else {\n inCode = true;\n }\n return;\n }\n if (inCode) { codeBlock.push(line); return; }\n \n let processed: React.ReactNode = line;\n if (line.includes('**')) {\n const segments = line.split(/\\*\\*(.*?)\\*\\*/g);\n processed = segments.map((seg, j) => j % 2 === 1 ? <strong key={j}>{seg}</strong> : seg);\n }\n if (typeof processed === 'string' && processed.includes('`')) {\n const segments = processed.split(/`(.*?)`/g);\n processed = segments.map((seg, j) =>\n j % 2 === 1\n ? <code key={j} style={{\n backgroundColor: `${tokens.colors.background.base}80`, padding: '1px 4px',\n borderRadius: '3px', fontSize: '0.9em', fontFamily: tokens.typography.fontFamily.mono,\n }}>{seg}</code>\n : seg\n );\n }\n parts.push(<React.Fragment key={`line-${i}`}>{processed}{i < lines.length - 1 && <br />}</React.Fragment>);\n });\n return parts;\n };\n \n const TypingDots = () => (\n <div style={{ display: 'flex', alignItems: 'center', gap: '4px', padding: tokens.spacing.xs }}>\n {[0, 1, 2].map(i => (\n <div key={i} style={{\n width: 6, height: 6, borderRadius: '50%',\n backgroundColor: tokens.colors.accent.primary, opacity: 0.6,\n animation: `zendir-typing 1.2s ease-in-out ${i * 0.2}s infinite`,\n }} />\n ))}\n <style>{`@keyframes zendir-typing { 0%,60%,100%{opacity:.3;transform:translateY(0)} 30%{opacity:1;transform:translateY(-3px)} }`}</style>\n </div>\n );\n \n return (\n <div style={{\n display: 'flex', flexDirection: 'column',\n height: typeof height === 'number' ? `${height}px` : height,\n fontFamily: tokens.typography.fontFamily.primary,\n backgroundColor: tokens.colors.background.base,\n borderRadius: tokens.borderRadius.lg,\n border: `1px solid ${tokens.colors.border.muted}`,\n overflow: 'hidden', ...style,\n }}>\n {/* Header */}\n {(title || onClear) && (\n <div style={{\n display: 'flex', alignItems: 'center', justifyContent: 'space-between',\n padding: `${tokens.spacing.sm} ${tokens.spacing.md}`,\n borderBottom: `1px solid ${tokens.colors.border.muted}`,\n backgroundColor: tokens.colors.background.surface,\n }}>\n <div>\n {title && <div style={{ fontSize: tokens.typography.fontSize.sm, fontWeight: 600, color: tokens.colors.text.primary }}>{title}</div>}\n {subtitle && <div style={{ fontSize: tokens.typography.fontSize.xxs, color: tokens.colors.text.tertiary }}>{subtitle}</div>}\n </div>\n {onClear && messages.length > 0 && (\n <button onClick={onClear} style={{\n fontSize: tokens.typography.fontSize.xxs, color: tokens.colors.text.tertiary,\n backgroundColor: 'transparent', border: 'none', cursor: 'pointer',\n padding: '4px 8px', borderRadius: tokens.borderRadius.sm, fontFamily: tokens.typography.fontFamily.primary,\n }}>Clear</button>\n )}\n </div>\n )}\n \n {/* Messages — aria-live so screen readers announce new messages */}\n <div\n role=\"log\"\n aria-live=\"polite\"\n aria-label=\"Chat messages\"\n style={{\n flex: 1, overflow: 'auto', padding: tokens.spacing.md,\n display: 'flex', flexDirection: 'column', gap: tokens.spacing.sm,\n }}\n >\n {messages.length === 0 && (\n <div style={{\n display: 'flex', alignItems: 'center', justifyContent: 'center',\n flex: 1, color: tokens.colors.text.tertiary, fontSize: tokens.typography.fontSize.sm,\n }}>No messages yet</div>\n )}\n \n {messages.map(msg => {\n const isUser = msg.role === 'user';\n const isSystem = msg.role === 'system';\n const severity = msg.severity;\n const severityColor = severity ? tokens.colors.status[severity] : undefined;\n \n // System message accent: uses severity if set, otherwise default caution tint\n const systemBg = severityColor ? `${severityColor}12` : `${tokens.colors.status.caution}10`;\n const systemBorder = severityColor ? `${severityColor}30` : `${tokens.colors.status.caution}20`;\n const systemAccent = severityColor || undefined;\n \n return (\n <div key={msg.id} style={{\n display: 'flex', flexDirection: 'column',\n alignItems: isUser ? 'flex-end' : 'flex-start',\n maxWidth: isSystem ? '100%' : '85%',\n alignSelf: isUser ? 'flex-end' : 'flex-start',\n }}>\n <div style={{\n padding: `${tokens.spacing.sm} ${tokens.spacing.md}`,\n borderRadius: tokens.borderRadius.md,\n backgroundColor: isUser\n ? `${tokens.colors.accent.primary}20`\n : isSystem ? systemBg : tokens.colors.background.surface,\n border: `1px solid ${isUser\n ? `${tokens.colors.accent.primary}30`\n : isSystem ? systemBorder : tokens.colors.border.muted}`,\n borderLeft: isSystem && systemAccent ? `3px solid ${systemAccent}` : undefined,\n fontSize: tokens.typography.fontSize.sm,\n color: tokens.colors.text.primary,\n lineHeight: 1.6,\n width: isSystem ? '100%' : 'auto',\n opacity: msg.status === 'sending' ? 0.7 : 1,\n }}>\n {/* Severity indicator for system messages */}\n {isSystem && severity && (\n <div style={{ display: 'flex', alignItems: 'center', gap: 6, marginBottom: 4 }}>\n <StatusShape status={severity} size={10} color={severityColor!} />\n <span style={{\n fontSize: tokens.typography.fontSize.xxs, fontWeight: 600,\n color: severityColor, textTransform: 'uppercase', letterSpacing: '0.04em',\n }}>\n {severity}\n </span>\n </div>\n )}\n \n {renderContent(msg.content)}\n \n {/* Structured blocks */}\n {Array.isArray(msg.blocks) && msg.blocks.map((block, i) => block ? renderBlock(block, i, msg.id, onBlockEvent) : null)}\n \n {/* Legacy action buttons */}\n {msg.actions && msg.actions.length > 0 && (\n <div style={{\n display: 'flex', gap: tokens.spacing.xs, marginTop: tokens.spacing.xs,\n paddingTop: tokens.spacing.xs, borderTop: `1px solid ${tokens.colors.border.muted}`,\n }}>\n {msg.actions.map((action, i) => (\n <button key={i} onClick={action.onClick} style={{\n fontSize: tokens.typography.fontSize.xxs, padding: '2px 10px',\n borderRadius: tokens.borderRadius.sm,\n border: `1px solid ${tokens.colors.accent.primary}40`,\n backgroundColor: `${tokens.colors.accent.primary}10`,\n color: safeAccentText(tokens.colors.accent.primary), cursor: 'pointer',\n fontFamily: tokens.typography.fontFamily.primary,\n }}>{action.label}</button>\n ))}\n </div>\n )}\n </div>\n \n {showTimestamps && msg.timestamp && (\n <div style={{\n fontSize: tokens.typography.fontSize.micro, color: tokens.colors.text.tertiary,\n marginTop: '2px', paddingLeft: tokens.spacing.xs, paddingRight: tokens.spacing.xs,\n display: 'flex', alignItems: 'center', gap: '4px',\n }}>\n {formatTime(msg.timestamp)}\n {msg.status === 'error' && <span style={{ color: tokens.colors.status.critical }}>• Failed</span>}\n </div>\n )}\n </div>\n );\n })}\n \n {loading && (\n <div style={{\n alignSelf: 'flex-start',\n padding: `${tokens.spacing.xs} ${tokens.spacing.md}`,\n borderRadius: tokens.borderRadius.md,\n backgroundColor: tokens.colors.background.surface,\n border: `1px solid ${tokens.colors.border.muted}`,\n }}>\n <TypingDots />\n </div>\n )}\n <div ref={messagesEndRef} />\n </div>\n \n {/* Input */}\n <div style={{\n display: 'flex', alignItems: 'flex-end', gap: tokens.spacing.sm,\n padding: tokens.spacing.md,\n borderTop: `1px solid ${tokens.colors.border.muted}`,\n backgroundColor: tokens.colors.background.surface,\n }}>\n <textarea\n ref={inputRef} value={input} onChange={handleInput} onKeyDown={handleKeyDown}\n placeholder={placeholder} disabled={disabled} aria-label=\"Message input\" rows={1}\n style={{\n flex: 1, resize: 'none',\n border: `1px solid ${tokens.colors.border.muted}`,\n borderRadius: tokens.borderRadius.md,\n padding: `${tokens.spacing.sm} ${tokens.spacing.md}`,\n fontSize: tokens.typography.fontSize.sm,\n fontFamily: tokens.typography.fontFamily.primary,\n color: tokens.colors.text.primary,\n backgroundColor: tokens.colors.background.base,\n outline: 'none', transition: 'border-color 150ms, background-color 150ms',\n maxHeight: 120, lineHeight: 1.5,\n overflowY: 'auto',\n }}\n />\n <button onClick={handleSend} disabled={disabled || !input.trim()} aria-label=\"Send message\" style={{\n display: 'flex', alignItems: 'center', justifyContent: 'center',\n width: 44, height: 44, borderRadius: tokens.borderRadius.md, border: 'none',\n backgroundColor: input.trim() ? tokens.colors.accent.primary : `${tokens.colors.accent.primary}20`,\n color: input.trim() ? tokens.colors.text.inverse : tokens.colors.text.tertiary,\n cursor: input.trim() && !disabled ? 'pointer' : 'not-allowed',\n transition: tokens.animation.fast, flexShrink: 0,\n }}>\n <svg width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"currentColor\"><path d=\"M2.01 21L23 12 2.01 3 2 10l15 2-15 2z\" /></svg>\n </button>\n </div>\n </div>\n );\n});\n\nexport default ChatPanel;\n"],"names":["ChatPanel"],"mappings":";;;;AAkQA,SAAS,cAAc,MAAuB;AAE5C,QAAM,QAAgB,CAAA;AACtB,aAAW,OAAO,KAAK,MAAM,IAAI,GAAG;AAClC,UAAM,UAAU,IAAI,QAAA;AACpB,QAAI,QAAQ,WAAW,MAAM,QAAQ,KAAA,EAAO,WAAW,GAAG,EAAG;AAC7D,UAAM,KAAK,EAAE,QAAQ,QAAQ,OAAO,IAAI,GAAG,MAAM,QAAQ,KAAA,EAAK,CAAG;AAAA,EACnE;AAEA,MAAI,MAAM;AACV,QAAM,OAAO,MAAoB,MAAM,MAAM,SAAS,MAAM,GAAG,IAAI;AACnE,QAAM,UAAU,MAAY,MAAM,KAAK;AAEvC,WAAS,OAAO,GAAoB;AAClC,UAAM,IAAI,EAAE,KAAA;AACZ,QAAI,MAAM,MAAM,MAAM,UAAU,MAAM,IAAK,QAAO;AAClD,QAAI,MAAM,OAAQ,QAAO;AACzB,QAAI,MAAM,QAAS,QAAO;AAC1B,QAAI,iCAAiC,KAAK,CAAC,EAAG,QAAO,OAAO,CAAC;AAC7D,QAAK,EAAE,WAAW,GAAG,KAAK,EAAE,SAAS,GAAG,KAAO,EAAE,WAAW,GAAG,KAAK,EAAE,SAAS,GAAG;AAChF,aAAO,EAAE,MAAM,GAAG,EAAE;AACtB,QAAK,EAAE,WAAW,GAAG,KAAK,EAAE,SAAS,GAAG,KAAO,EAAE,WAAW,GAAG,KAAK,EAAE,SAAS,GAAG,GAAI;AACpF,UAAI;AAAE,eAAO,KAAK,MAAM,CAAC;AAAA,MAAG,QAAQ;AAAA,MAAqB;AAAA,IAC3D;AACA,WAAO;AAAA,EACT;AAEA,WAAS,WAAW,WAA4B;AAC9C,UAAM,OAAO,KAAA;AACb,QAAI,CAAC,QAAQ,KAAK,SAAS,UAAW,QAAO;AAC7C,UAAM,eAAe,KAAK;AAC1B,QAAI,KAAK,KAAK,WAAW,IAAI,EAAG,QAAO,cAAc,YAAY;AACjE,WAAO,aAAa,YAAY;AAAA,EAClC;AAEA,WAAS,cAAc,OAA0B;AAC/C,UAAM,MAAiB,CAAA;AACvB,WAAO,KAAA,KAAU,KAAA,EAAQ,WAAW,SAAS,KAAA,EAAQ,KAAK,WAAW,IAAI,GAAG;AAC1E,YAAM,OAAO,QAAA;AACb,YAAM,QAAQ,KAAK,KAAK,MAAM,CAAC,EAAE,KAAA;AAEjC,UAAI,CAAC,OAAO;AAEV,cAAM,MAAM,WAAW,QAAQ,CAAC;AAChC,YAAI,KAAK,OAAO,IAAI;AACpB;AAAA,MACF;AAEA,YAAM,WAAW,MAAM,QAAQ,GAAG;AAClC,UAAI,WAAW,KAAK,CAAC,QAAQ,KAAK,KAAK,GAAG;AAExC,cAAM,MAA+B,CAAA;AACrC,cAAM,IAAI,MAAM,MAAM,GAAG,QAAQ,EAAE,KAAA;AACnC,cAAM,IAAI,MAAM,MAAM,WAAW,CAAC,EAAE,KAAA;AACpC,YAAI,CAAC,IAAI,IAAI,OAAO,CAAC,IAAK,WAAW,QAAQ,CAAC,KAAK;AAGnD,cAAM,gBAAgB,QAAQ;AAC9B,eAAO,KAAA,KAAU,OAAQ,UAAU,eAAe;AAChD,cAAI,KAAA,EAAQ,WAAW,iBAAiB,CAAC,OAAQ,KAAK,WAAW,IAAI,GAAG;AACtE,kBAAM,OAAO,QAAA;AACb,kBAAM,KAAK,KAAK,KAAK,QAAQ,GAAG;AAChC,gBAAI,KAAK,GAAG;AACV,oBAAM,KAAK,KAAK,KAAK,MAAM,GAAG,EAAE,EAAE,KAAA;AAClC,oBAAM,KAAK,KAAK,KAAK,MAAM,KAAK,CAAC,EAAE,KAAA;AACnC,kBAAI,EAAE,IAAI,KAAK,OAAO,EAAE,IAAK,WAAW,gBAAgB,CAAC,KAAK;AAAA,YAChE;AAAA,UACF,WAAW,OAAQ,SAAS,eAAe;AAGzC,oBAAA;AAAA,UACF,OAAO;AACL;AAAA,UACF;AAAA,QACF;AACA,YAAI,KAAK,GAAG;AAAA,MACd,OAAO;AAEL,YAAI,KAAK,OAAO,KAAK,CAAC;AAAA,MACxB;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAEA,WAAS,aAAa,OAAwC;AAC5D,UAAM,MAA+B,CAAA;AACrC,WAAO,KAAA,KAAU,KAAA,EAAQ,WAAW,SAAS,CAAC,OAAQ,KAAK,WAAW,IAAI,GAAG;AAC3E,YAAM,OAAO,QAAA;AACb,YAAM,WAAW,KAAK,KAAK,QAAQ,GAAG;AACtC,UAAI,YAAY,EAAG;AACnB,YAAM,IAAI,KAAK,KAAK,MAAM,GAAG,QAAQ,EAAE,KAAA;AACvC,YAAM,IAAI,KAAK,KAAK,MAAM,WAAW,CAAC,EAAE,KAAA;AACxC,UAAI,CAAC,IAAI,IAAI,OAAO,CAAC,IAAK,WAAW,QAAQ,CAAC,KAAK;AAAA,IACrD;AACA,WAAO;AAAA,EACT;AAEA,MAAI;AACF,WAAO,WAAW,CAAC,KAAK,CAAA;AAAA,EAC1B,QAAQ;AACN,WAAO,CAAA;AAAA,EACT;AACF;AAKA,SAAS,eAAe,QAA0C;AAChE,MAAI,CAAC,MAAM,QAAQ,MAAM,EAAG,QAAO;AACnC,SAAO,OACJ,OAAO,CAAC,MAAoC,KAAK,QAAQ,OAAO,MAAM,YAAY,OAAQ,EAA8B,SAAS,QAAQ,EACzI,IAAI,CAAC,MAAM;AACV,UAAM,QAAQ,EAAE,GAAG,EAAA;AAEnB,YAAQ,MAAM,MAAA;AAAA,MACZ,KAAK;AACH,YAAI,CAAC,MAAM,QAAQ,MAAM,KAAK,EAAG,OAAM,QAAQ,CAAA;AAC/C;AAAA,MACF,KAAK;AACH,YAAI,CAAC,MAAM,QAAQ,MAAM,OAAO,EAAG,OAAM,UAAU,CAAA;AACnD,YAAI,CAAC,MAAM,QAAQ,MAAM,IAAI,EAAG,OAAM,OAAO,CAAA;AAC7C;AAAA,MACF,KAAK;AACH,YAAI,CAAC,MAAM,QAAQ,MAAM,OAAO,EAAG,OAAM,UAAU,CAAA;AACnD;AAAA,MACF,KAAK;AACH,YAAI,CAAC,MAAM,QAAQ,MAAM,OAAO,EAAG,OAAM,UAAU,CAAA;AACnD,YAAI,OAAO,MAAM,OAAO,gBAAgB,KAAK,UAAU,KAAK,IAAA,CAAK;AACjE;AAAA,MACF,KAAK;AACH,YAAI,OAAO,MAAM,OAAO,gBAAgB,KAAK,WAAW,KAAK,IAAA,CAAK;AAClE,YAAI,OAAO,MAAM,UAAU,gBAAgB,QAAQ;AACnD;AAAA,MACF,KAAK;AACH,YAAI,OAAO,MAAM,YAAY,gBAAgB,UAAU;AACvD;AAAA,MACF,KAAK;AACH,YAAI,CAAC,MAAM,QAAQ,MAAM,KAAK,EAAG,OAAM,QAAQ,CAAA;AAC/C;AAAA,MACF,KAAK;AACH,YAAI,OAAO,MAAM,UAAU,gBAAgB,QAAQ;AACnD,YAAI,OAAO,MAAM,WAAW,gBAAgB,SAAS;AACrD;AAAA,MACF,KAAK;AACH,YAAI,OAAO,MAAM,UAAU,gBAAgB,QAAQ;AACnD,YAAI,OAAO,MAAM,UAAU,gBAAgB,QAAQ;AACnD;AAAA,IAAA;AAEJ,WAAO;AAAA,EACT,CAAC;AACL;AAIA,SAAS,WAAW,QAA+B;AACjD,MAAI,eAAe,OAAA;AACnB,MAAI,OAAO,WAAW,eAAe,OAAO,OAAO,eAAe,WAAY,QAAO,OAAO,WAAA;AAC5F,SAAO,OAAO,KAAK,IAAA,CAAK,IAAI,KAAK,OAAA,EAAS,SAAS,EAAE,EAAE,MAAM,GAAG,CAAC,CAAC;AACpE;AAIA,SAAS,SACP,KACA,QACA,YAC4B;AAC5B,QAAM,UAAU,CAAC,MAA0C;AACzD,QAAI;AACF,YAAM,SAAS,KAAK,MAAM,CAAC;AAC3B,UAAI,UAAU,OAAO,WAAW,YAAY,OAAO,OAAO,YAAY,SAAU,QAAO;AACvF,aAAO;AAAA,IACT,QAAQ;AAAE,aAAO;AAAA,IAAM;AAAA,EACzB;AAEA,QAAM,UAAU,CAAC,MAA0C;AACzD,QAAI;AACF,YAAM,SAAS,cAAc;AAC7B,YAAM,SAAS,OAAO,CAAC;AACvB,UAAI,UAAU,OAAO,WAAW,YAAY,OAAQ,OAAmC,YAAY;AACjG,eAAO;AACT,aAAO;AAAA,IACT,QAAQ;AAAE,aAAO;AAAA,IAAM;AAAA,EACzB;AAEA,MAAI,WAAW,OAAQ,QAAO,QAAQ,GAAG;AACzC,MAAI,WAAW,OAAQ,QAAO,QAAQ,GAAG;AAEzC,SAAO,QAAQ,GAAG,KAAK,QAAQ,GAAG;AACpC;AAkCO,SAAS,kBACd,KACA,SAA6B,QAC7B,SACa;AACb,QAAM,KAAK,WAAW,mCAAS,WAAW;AAC1C,QAAM,OAAuD;AAAA,IAC3D;AAAA,IAAI,MAAM;AAAA,IAAa,WAAW,KAAK,IAAA;AAAA,EAAI;AAG7C,QAAM,UAAU,SAAS,KAAK,QAAQ,mCAAS,UAAU;AACzD,MAAI,SAAS;AACX,WAAO;AAAA,MACL,GAAG;AAAA,MACH,SAAS,QAAQ,WAAW;AAAA,MAC5B,UAAU,QAAQ;AAAA,MAClB,QAAQ,eAAe,QAAQ,MAAM;AAAA,IAAA;AAAA,EAEzC;AACA,SAAO,EAAE,GAAG,MAAM,SAAS,IAAA;AAC7B;AAuBO,SAAS,yBAAyB,UAAqC,IAAI;AAChF,SAAO,CAAC,KAAa,WAA6C;AAChE,WAAO,kBAAkB,KAAK,UAAU,QAAQ,iBAAiB,QAAQ,OAAO;AAAA,EAClF;AACF;AAoDO,SAAS,mBACd,UACA,QACA,SACa;;AACb,QAAM,KAAK,WAAW,mCAAS,WAAW;AAC1C,QAAM,YAAY,KAAK,IAAA;AAGvB,MAAI,OAAO,SAAS;AAClB,UAAM,cAAY,YAAO,YAAP,mBACd,OAAO,CAAA,MAAK,EAAE,SAAS,QACxB,IAAI,CAAA,MAAK,EAAE,MACX,KAAK,UAAS,SAAS,QAAQ;AAClC,WAAO;AAAA,MACL;AAAA,MAAI,MAAM;AAAA,MAAa;AAAA,MACvB,UAAU;AAAA,MACV,SAAS;AAAA,MACT,QAAQ,CAAC,EAAE,MAAM,SAAkB,QAAQ,YAA2B,OAAO,mBAAmB,QAAQ,IAAI,QAAQ,WAAW;AAAA,IAAA;AAAA,EAEnI;AAGA,QAAM,cAAY,YAAO,YAAP,mBAAgB,OAAO,OAAK,EAAE,SAAS,QAAQ,IAAI,CAAA,MAAK,EAAE,QAAQ,QAAO,CAAA;AAC3F,QAAM,UAAU,UAAU,KAAK,IAAI;AAGnC,MAAI,QAAQ,QAAQ;AAClB,UAAM,UAAU,SAAS,SAAS,MAAM;AACxC,QAAI,WAAW,QAAQ,SAAS;AAC9B,aAAO;AAAA,QACL;AAAA,QAAI,MAAM;AAAA,QAAa;AAAA,QACvB,SAAS,QAAQ;AAAA,QACjB,UAAU,QAAQ;AAAA,QAClB,QAAQ,eAAe,QAAQ,MAAM;AAAA,MAAA;AAAA,IAEzC;AAAA,EACF;AAGA,SAAO;AAAA,IACL;AAAA,IAAI,MAAM;AAAA,IAAa;AAAA,IACvB,SAAS,WAAW,UAAU,QAAQ;AAAA,IACtC,QAAQ,CAAC;AAAA,MACP,MAAM;AAAA,MACN,OAAO;AAAA,MACP,OAAO;AAAA,QACL,EAAE,KAAK,QAAQ,OAAO,UAAU,MAAM,KAAA;AAAA,QACtC,GAAI,OAAO,QAAQ,CAAC,EAAE,KAAK,QAAQ,OAAO,KAAK,UAAU,OAAO,KAAK,GAAG,MAAM,KAAA,CAAM,IAAI,CAAA;AAAA,MAAC;AAAA,IAC3F,CACD;AAAA,EAAA;AAEL;AA4BO,MAAM,yBAAyB;AAAA,EACpC,MAAM;AAAA,EACN,aACE;AAAA,EACF,aAAa;AAAA,IACX,MAAM;AAAA,IACN,UAAU,CAAC,SAAS;AAAA,IACpB,YAAY;AAAA,MACV,SAAS,EAAE,MAAM,UAAU,aAAa,yDAAA;AAAA,MACxC,UAAU,EAAE,MAAM,UAAU,MAAM,CAAC,UAAU,WAAW,WAAW,WAAW,YAAY,KAAK,EAAA;AAAA,MAC/F,QAAQ;AAAA,QACN,MAAM;AAAA,QACN,aAAa;AAAA,QACb,OAAO;AAAA,UACL,MAAM;AAAA,UACN,UAAU,CAAC,MAAM;AAAA,UACjB,YAAY;AAAA,YACV,MAAM,EAAE,MAAM,UAAU,MAAM,CAAC,SAAS,aAAa,YAAY,SAAS,UAAU,WAAW,WAAW,IAAI,EAAA;AAAA,YAC9G,QAAQ,EAAE,MAAM,UAAU,MAAM,CAAC,UAAU,WAAW,WAAW,WAAW,YAAY,KAAK,EAAA;AAAA,YAC7F,OAAO,EAAE,MAAM,SAAA;AAAA,YACf,QAAQ,EAAE,MAAM,SAAA;AAAA,YAChB,OAAO,EAAE,MAAM,SAAA;AAAA,YACf,OAAO,EAAE,MAAM,SAAA;AAAA,YACf,IAAI,EAAE,MAAM,SAAA;AAAA,YACZ,SAAS,EAAE,MAAM,SAAA;AAAA,YACjB,YAAY,EAAE,MAAM,UAAA;AAAA,YACpB,OAAO,EAAE,MAAM,SAAS,OAAO,EAAE,MAAM,UAAU,YAAY,EAAE,OAAO,EAAE,MAAM,YAAY,OAAO,CAAA,GAAI,MAAM,EAAE,MAAM,YAAY,QAAQ,EAAE,MAAM,SAAA,EAAS,IAAI;AAAA,YAC5J,SAAS,EAAE,MAAM,SAAS,OAAO,EAAE,MAAM,WAAS;AAAA,YAClD,MAAM,EAAE,MAAM,SAAS,OAAO,EAAE,MAAM,UAAQ;AAAA,YAC9C,SAAS,EAAE,MAAM,SAAS,OAAO,EAAE,MAAM,UAAU,YAAY,EAAE,IAAI,EAAE,MAAM,SAAA,GAAY,OAAO,EAAE,MAAM,YAAY,aAAa,EAAE,MAAM,SAAA,GAAY,QAAQ,EAAE,MAAM,SAAA,EAAS,IAAI;AAAA,YAClL,OAAO,EAAE,MAAM,SAAS,OAAO,EAAE,MAAM,UAAU,YAAY,EAAE,KAAK,EAAE,MAAM,SAAA,GAAY,OAAO,CAAA,GAAI,MAAM,EAAE,MAAM,UAAA,IAAY,EAAE;AAAA,UAAE;AAAA,QACnI;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEJ;AA2BO,MAAM,4BAA4B;AAAA,EACvC,MAAM;AAAA,EACN,aACE;AAAA,EACF,YAAY;AAAA,IACV,MAAM;AAAA,IACN,UAAU,CAAC,SAAS;AAAA,IACpB,YAAY;AAAA,MACV,SAAS;AAAA,QACP,MAAM;AAAA,QACN,aAAa;AAAA,MAAA;AAAA,MAEf,UAAU;AAAA,QACR,MAAM;AAAA,QACN,MAAM,CAAC,UAAU,WAAW,WAAW,WAAW,YAAY,KAAK;AAAA,QACnE,aAAa;AAAA,MAAA;AAAA,MAEf,QAAQ;AAAA,QACN,MAAM;AAAA,QACN,aAAa;AAAA,QACb,OAAO;AAAA,UACL,MAAM;AAAA,UACN,UAAU,CAAC,MAAM;AAAA,UACjB,YAAY;AAAA,YACV,MAAM;AAAA,cACJ,MAAM;AAAA,cACN,MAAM,CAAC,SAAS,aAAa,YAAY,SAAS,UAAU,WAAW,WAAW,IAAI;AAAA,YAAA;AAAA,YAExF,QAAQ,EAAE,MAAM,UAAU,MAAM,CAAC,UAAU,WAAW,WAAW,WAAW,YAAY,KAAK,EAAA;AAAA,YAC7F,OAAO,EAAE,MAAM,SAAA;AAAA,YACf,QAAQ,EAAE,MAAM,SAAA;AAAA,YAChB,OAAO;AAAA,cACL,MAAM;AAAA,cACN,OAAO;AAAA,gBACL,MAAM;AAAA,gBACN,YAAY;AAAA,kBACV,OAAO,EAAE,MAAM,SAAA;AAAA,kBACf,OAAO,CAAA;AAAA,kBACP,MAAM,EAAE,MAAM,SAAA;AAAA,kBACd,QAAQ,EAAE,MAAM,UAAU,MAAM,CAAC,UAAU,WAAW,WAAW,WAAW,YAAY,KAAK,EAAA;AAAA,gBAAE;AAAA,cACjG;AAAA,YACF;AAAA,YAEF,OAAO,EAAE,MAAM,SAAA;AAAA,YACf,OAAO,EAAE,MAAM,SAAA;AAAA,YACf,KAAK,EAAE,MAAM,SAAA;AAAA,YACb,SAAS,EAAE,MAAM,SAAS,OAAO,EAAE,MAAM,WAAS;AAAA,YAClD,MAAM,EAAE,MAAM,SAAS,OAAO,EAAE,MAAM,UAAQ;AAAA,YAC9C,IAAI,EAAE,MAAM,SAAA;AAAA,YACZ,UAAU,EAAE,MAAM,UAAA;AAAA,YAClB,SAAS;AAAA,cACP,MAAM;AAAA,cACN,OAAO;AAAA,gBACL,MAAM;AAAA,gBACN,YAAY;AAAA,kBACV,IAAI,EAAE,MAAM,SAAA;AAAA,kBACZ,OAAO,EAAE,MAAM,SAAA;AAAA,kBACf,aAAa,EAAE,MAAM,SAAA;AAAA,kBACrB,QAAQ,EAAE,MAAM,UAAU,MAAM,CAAC,UAAU,WAAW,WAAW,WAAW,YAAY,KAAK,EAAA;AAAA,kBAC7F,UAAU,EAAE,MAAM,UAAA;AAAA,gBAAU;AAAA,cAC9B;AAAA,YACF;AAAA,YAEF,cAAc,EAAE,MAAM,SAAA;AAAA,YACtB,aAAa,EAAE,MAAM,SAAA;AAAA,YACrB,UAAU,EAAE,MAAM,SAAA;AAAA,YAClB,SAAS,EAAE,MAAM,SAAA;AAAA,YACjB,YAAY,EAAE,MAAM,UAAA;AAAA,YACpB,OAAO;AAAA,cACL,MAAM;AAAA,cACN,OAAO;AAAA,gBACL,MAAM;AAAA,gBACN,YAAY;AAAA,kBACV,KAAK,EAAE,MAAM,SAAA;AAAA,kBACb,OAAO,CAAA;AAAA,kBACP,MAAM,EAAE,MAAM,UAAA;AAAA,gBAAU;AAAA,cAC1B;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEJ;AAMO,MAAM,4BAA4B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAwBlC,MAAM,4BAA4B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA8ClC,MAAM,2BAA2B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAgBxC,SAAS,YAAY,EAAE,QAAQ,OAAO,IAAI,SAAgE;AACxG,QAAM,OAAO,GAAG,KAAK;AACrB,UAAQ,QAAA;AAAA,IACN,KAAK;AACH,aAAO,oBAAC,OAAA,EAAI,SAAQ,aAAY,OAAO,MAAM,QAAQ,MAAM,OAAO,EAAE,QAAQ,uBAAuB,IAAI,IAAA,GAAO,UAAA,oBAAC,QAAA,EAAK,GAAE,KAAI,GAAE,KAAI,OAAM,MAAK,QAAO,MAAK,MAAM,MAAA,CAAO,GAAE;AAAA,IACxK,KAAK;AACH,aAAO,oBAAC,SAAI,SAAQ,aAAY,OAAO,MAAM,QAAQ,MAAM,OAAO,EAAE,QAAQ,uBAAuB,IAAI,OAAO,UAAA,oBAAC,aAAQ,QAAO,qBAAoB,MAAM,MAAA,CAAO,EAAA,CAAE;AAAA,IACnK,KAAK;AACH,aAAO,oBAAC,SAAI,SAAQ,aAAY,OAAO,MAAM,QAAQ,MAAM,OAAO,EAAE,QAAQ,uBAAuB,IAAI,OAAO,UAAA,oBAAC,aAAQ,QAAO,iBAAgB,MAAM,MAAA,CAAO,EAAA,CAAE;AAAA,IAC/J,KAAK;AACH,aAAO,oBAAC,OAAA,EAAI,SAAQ,aAAY,OAAO,MAAM,QAAQ,MAAM,OAAO,EAAE,QAAQ,uBAAuB,IAAI,IAAA,GAAO,UAAA,oBAAC,UAAA,EAAO,IAAG,KAAI,IAAG,KAAI,GAAE,OAAM,MAAK,QAAO,QAAQ,OAAO,aAAY,KAAI,GAAE;AAAA,IAC3L,KAAK;AACH,aAAO,oBAAC,OAAA,EAAI,SAAQ,aAAY,OAAO,MAAM,QAAQ,MAAM,OAAO,EAAE,QAAQ,uBAAuB,IAAI,IAAA,GAAO,UAAA,oBAAC,UAAA,EAAO,IAAG,KAAI,IAAG,KAAI,GAAE,KAAI,MAAM,MAAA,CAAO,EAAA,CAAE;AAAA,IAC3J;AACE,aAAO,oBAAC,OAAA,EAAI,SAAQ,aAAY,OAAO,MAAM,QAAQ,MAAM,OAAO,EAAE,QAAQ,uBAAuB,IAAI,IAAA,GAAO,UAAA,oBAAC,UAAA,EAAO,IAAG,KAAI,IAAG,KAAI,GAAE,KAAI,MAAM,MAAA,CAAO,EAAA,CAAE;AAAA,EAAA;AAE/J;AAIA,SAAS,WAAW,EAAE,SAAoC;AACxD,QAAM,EAAE,OAAA,IAAW,SAAA;AACnB,QAAM,QAAQ,OAAO,OAAO,OAAO,MAAM,MAAM;AAC/C,SACE,qBAAC,SAAI,OAAO;AAAA,IACV,SAAS;AAAA,IAAQ,YAAY;AAAA,IAAc,KAAK;AAAA,IAChD,SAAS;AAAA,IACT,iBAAiB,GAAG,KAAK;AAAA,IACzB,QAAQ,aAAa,KAAK;AAAA,IAC1B,YAAY,aAAa,KAAK;AAAA,IAC9B,cAAc,OAAO,aAAa;AAAA,IAClC,WAAW;AAAA,EAAA,GAEX,UAAA;AAAA,IAAA,oBAAC,SAAI,OAAO,EAAE,WAAW,GAAG,YAAY,EAAA,GACtC,UAAA,oBAAC,aAAA,EAAY,QAAQ,MAAM,QAAQ,MAAM,IAAI,OAAc,GAC7D;AAAA,IACA,qBAAC,SAAI,OAAO,EAAE,MAAM,GAAG,UAAU,KAC/B,UAAA;AAAA,MAAA,oBAAC,SAAI,OAAO,EAAE,UAAU,OAAO,WAAW,SAAS,IAAI,YAAY,KAAK,OAAO,OAAO,OAAO,KAAK,QAAA,GAC/F,gBAAM,OACT;AAAA,MACC,MAAM,UACL,oBAAC,OAAA,EAAI,OAAO,EAAE,UAAU,OAAO,WAAW,SAAS,IAAI,OAAO,OAAO,OAAO,KAAK,WAAW,WAAW,GAAG,YAAY,IAAA,GACnH,UAAA,MAAM,OAAA,CACT;AAAA,IAAA,EAAA,CAEJ;AAAA,EAAA,GACF;AAEJ;AAEA,SAAS,eAAe,EAAE,SAAwC;AAChE,QAAM,EAAE,OAAA,IAAW,SAAA;AACnB,SACE,qBAAC,SAAI,OAAO;AAAA,IACV,WAAW;AAAA,IACX,QAAQ,aAAa,OAAO,OAAO,OAAO,KAAK;AAAA,IAC/C,cAAc,OAAO,aAAa;AAAA,IAClC,UAAU;AAAA,EAAA,GAET,UAAA;AAAA,IAAA,MAAM,SACL,oBAAC,OAAA,EAAI,OAAO;AAAA,MACV,SAAS;AAAA,MACT,UAAU,OAAO,WAAW,SAAS;AAAA,MACrC,YAAY;AAAA,MACZ,OAAO,OAAO,OAAO,KAAK;AAAA,MAC1B,eAAe;AAAA,MACf,eAAe;AAAA,MACf,iBAAiB,GAAG,OAAO,OAAO,WAAW,QAAQ;AAAA,MACrD,cAAc,aAAa,OAAO,OAAO,OAAO,KAAK;AAAA,IAAA,GAEpD,gBAAM,OACT;AAAA,IAEF,oBAAC,SAAI,OAAO,EAAE,SAAS,YAAY,SAAS,QAAQ,eAAe,UAAU,KAAK,EAAA,GAC9E,iBAAM,SAAS,CAAA,GAAI,IAAI,CAAC,MAAM,MAAM;AACpC,YAAM,YAAY,KAAK,SAAS,OAAO,OAAO,OAAO,KAAK,MAAM,IAAI,OAAO,OAAO,KAAK;AACvF,kCACG,OAAA,EAAY,OAAO,EAAE,SAAS,QAAQ,YAAY,UAAU,gBAAgB,iBAAiB,KAAK,GAAG,UAAU,OAAO,WAAW,SAAS,MACzI,UAAA;AAAA,QAAA,qBAAC,QAAA,EAAK,OAAO,EAAE,SAAS,QAAQ,YAAY,UAAU,KAAK,GAAG,OAAO,OAAO,OAAO,KAAK,aACrF,UAAA;AAAA,UAAA,KAAK,UAAU,oBAAC,aAAA,EAAY,QAAQ,KAAK,QAAQ,MAAM,GAAG,OAAO,OAAO,OAAO,OAAO,KAAK,MAAM,GAAG;AAAA,UACpG,KAAK;AAAA,QAAA,GACR;AAAA,QACA,qBAAC,UAAK,OAAO;AAAA,UACX,YAAY,OAAO,WAAW,WAAW;AAAA,UACzC,oBAAoB;AAAA,UACpB,OAAO;AAAA,UACP,YAAY;AAAA,QAAA,GAEX,UAAA;AAAA,UAAA,KAAK;AAAA,UAAO,KAAK,OAAO,IAAI,KAAK,IAAI,KAAK;AAAA,QAAA,EAAA,CAC7C;AAAA,MAAA,EAAA,GAZQ,CAaV;AAAA,IAEJ,CAAC,EAAA,CACH;AAAA,EAAA,GACF;AAEJ;AAEA,SAAS,cAAc,EAAE,SAAuC;AAC9D,QAAM,EAAE,OAAA,IAAW,SAAA;AACnB,QAAM,MAAM,MAAM,OAAO;AACzB,QAAM,MAAM,KAAK,IAAI,KAAK,KAAK,IAAI,GAAI,MAAM,QAAQ,MAAO,GAAG,CAAC;AAChE,QAAM,kBAA+B,MAAM,WACzC,OAAO,KAAK,WAAW,OAAO,KAAK,YAAY,OAAO,KAAK,YAAY,MAAM,IAAI,YAAY;AAE/F,QAAM,QAAQ,OAAO,OAAO,OAAO,eAAe;AAClD,8BACG,OAAA,EAAI,OAAO,EAAE,WAAW,KACvB,UAAA;AAAA,IAAA,qBAAC,SAAI,OAAO,EAAE,SAAS,QAAQ,gBAAgB,iBAAiB,cAAc,GAAG,UAAU,OAAO,WAAW,SAAS,IAAI,OAAO,OAAO,OAAO,KAAK,aAClJ,UAAA;AAAA,MAAA,qBAAC,QAAA,EAAK,OAAO,EAAE,SAAS,QAAQ,YAAY,UAAU,KAAK,EAAA,GACzD,UAAA;AAAA,QAAA,oBAAC,aAAA,EAAY,QAAQ,iBAAiB,MAAM,GAAG,OAAc;AAAA,QAC5D,MAAM;AAAA,MAAA,GACT;AAAA,MACA,qBAAC,QAAA,EAAK,OAAO,EAAE,YAAY,OAAO,WAAW,WAAW,MAAM,OAAO,OAAO,OAAO,KAAK,WAAY,UAAA;AAAA,QAAA,IAAI,QAAQ,CAAC;AAAA,QAAE;AAAA,MAAA,EAAA,CAAC;AAAA,IAAA,GACtH;AAAA,wBACC,OAAA,EAAI,OAAO,EAAE,QAAQ,GAAG,iBAAiB,OAAO,OAAO,OAAO,OAAO,cAAc,GAAG,UAAU,SAAA,GAC/F,UAAA,oBAAC,OAAA,EAAI,OAAO,EAAE,QAAQ,QAAQ,OAAO,GAAG,GAAG,KAAK,iBAAiB,OAAO,cAAc,GAAG,YAAY,eAAe,WAAW,WAAW,KAAK,KAAA,GAAQ,EAAA,CACzJ;AAAA,EAAA,GACF;AAEJ;AAEA,SAAS,WAAW,EAAE,SAAoC;AACxD,QAAM,EAAE,OAAA,IAAW,SAAA;AACnB,8BACG,OAAA,EAAI,OAAO,EAAE,WAAW,GAAG,QAAQ,aAAa,OAAO,OAAO,OAAO,KAAK,IAAI,cAAc,OAAO,aAAa,IAAI,UAAU,YAC5H,UAAA;AAAA,IAAA,MAAM,SACL,oBAAC,OAAA,EAAI,OAAO;AAAA,MACV,SAAS;AAAA,MACT,UAAU,OAAO,WAAW,SAAS;AAAA,MACrC,YAAY;AAAA,MACZ,OAAO,OAAO,OAAO,KAAK;AAAA,MAC1B,eAAe;AAAA,MACf,eAAe;AAAA,MACf,iBAAiB,GAAG,OAAO,OAAO,WAAW,QAAQ;AAAA,MACrD,cAAc,aAAa,OAAO,OAAO,OAAO,KAAK;AAAA,IAAA,GAEpD,gBAAM,OACT;AAAA,IAEF,oBAAC,SAAI,OAAO,EAAE,WAAW,OAAA,GACvB,+BAAC,SAAA,EAAM,OAAO,EAAE,OAAO,QAAQ,gBAAgB,YAAY,UAAU,OAAO,WAAW,SAAS,MAC9F,UAAA;AAAA,MAAA,oBAAC,SAAA,EACC,UAAA,oBAAC,MAAA,EACG,WAAA,MAAM,WAAW,CAAA,GAAI,IAAI,CAAC,KAAK,MAC/B,oBAAC,QAAW,OAAO;AAAA,QACjB,SAAS;AAAA,QAAY,WAAW;AAAA,QAAQ,YAAY;AAAA,QACpD,OAAO,OAAO,OAAO,KAAK;AAAA,QAC1B,cAAc,aAAa,OAAO,OAAO,OAAO,KAAK;AAAA,QACrD,YAAY;AAAA,MAAA,GAEX,UAAA,IAAA,GANM,CAOT,CACD,GACH,EAAA,CACF;AAAA,MACA,oBAAC,WACG,WAAA,MAAM,QAAQ,CAAA,GAAI,IAAI,CAAC,KAAK,2BAC3B,MAAA,EACG,WAAA,OAAO,CAAA,GAAI,IAAI,CAAC,MAAM,OACtB,oBAAC,MAAA,EAAY,OAAO;AAAA,QAClB,SAAS;AAAA,QACT,OAAO,OAAO,OAAO,KAAK;AAAA,QAC1B,YAAY,OAAO,SAAS,WAAW,OAAO,WAAW,WAAW,OAAO;AAAA,QAC3E,oBAAoB,OAAO,SAAS,WAAW,iBAAiB;AAAA,QAChE,cAAc,MAAM,MAAM,QAAQ,CAAA,GAAI,SAAS,IAAI,aAAa,OAAO,OAAO,OAAO,KAAK,OAAO;AAAA,QACjG,YAAY;AAAA,MAAA,GAEX,UAAA,QARM,EAST,CACD,EAAA,GAZM,EAaT,CACD,EAAA,CACH;AAAA,IAAA,EAAA,CACF,EAAA,CACF;AAAA,EAAA,GACF;AAEJ;AAEA,SAAS,aAAa,EAAE,SAAsC;AAC5D,QAAM,EAAE,OAAA,IAAW,SAAA;AACnB,SACE,oBAAC,SAAI,OAAO,EAAE,SAAS,QAAQ,KAAK,GAAG,WAAW,GAAG,UAAU,OAAA,GAC3D,iBAAM,WAAW,CAAA,GAAI,IAAI,CAAC,KAAK,MAAM;AACrC,UAAM,aAAa,IAAI,YAAY;AACnC,UAAM,YAAY,IAAI,YAAY,aAAc,CAAC,IAAI,WAAW,MAAM;AACtE,UAAM,YAAY,aAAa,OAAO,OAAO,OAAO,WAAW,OAAO,OAAO,OAAO;AACpF,UAAM,YAAY,aAAa,OAAO,OAAO,OAAO,WAAW,eAAe,OAAO,OAAO,OAAO,OAAO;AAC1G,WACE,oBAAC,UAAA,EAAe,SAAS,IAAI,SAAS,OAAO;AAAA,MAC3C,UAAU,OAAO,WAAW,SAAS;AAAA,MAAK,SAAS;AAAA,MACnD,cAAc,OAAO,aAAa;AAAA,MAClC,QAAQ,aAAa,SAAS,GAAG,YAAY,KAAK,IAAI;AAAA,MACtD,iBAAiB,YAAY,GAAG,SAAS,OAAO;AAAA,MAChD,OAAO;AAAA,MAAW,QAAQ;AAAA,MAC1B,YAAY,OAAO,WAAW,WAAW;AAAA,MACzC,YAAY;AAAA,MAAK,YAAY;AAAA,IAAA,GAE5B,UAAA,IAAI,MAAA,GATM,CAUb;AAAA,EAEJ,CAAC,EAAA,CACH;AAEJ;AAEA,SAAS,YAAY,EAAE,OAAO,WAAW,WAAiG;AACxI,QAAM,EAAE,OAAA,IAAW,SAAA;AACnB,QAAM,CAAC,eAAe,gBAAgB,IAAI,SAAsB,IAAI,IAAI,MAAM,YAAY,CAAA,CAAE,CAAC;AAC7F,QAAM,cAAc,MAAM;AAE1B,QAAM,SAAS,CAAC,UAAkB;AAChC,QAAI,YAAa;AACjB,qBAAiB,CAAA,SAAQ;AACvB,YAAM,OAAO,IAAI,IAAI,IAAI;AACzB,UAAI,MAAM,UAAU;AAClB,aAAK,IAAI,KAAK,IAAI,KAAK,OAAO,KAAK,IAAI,KAAK,IAAI,KAAK;AAAA,MACvD,OAAO;AACL,aAAK,MAAA;AACL,aAAK,IAAI,KAAK;AAAA,MAChB;AACA,aAAO;AAAA,IACT,CAAC;AAAA,EACH;AAEA,QAAM,SAAS,MAAM;AACnB,QAAI,cAAc,SAAS,KAAK,YAAa;AAC7C,uCAAU,EAAE,SAAS,MAAM,IAAI,WAAW,QAAQ,UAAU,OAAO,MAAM,KAAK,aAAa,EAAA;AAAA,EAC7F;AAEA,8BACG,OAAA,EAAI,OAAO,EAAE,WAAW,KACtB,UAAA;AAAA,IAAA,MAAM,SACL,qBAAC,OAAA,EAAI,OAAO,EAAE,UAAU,OAAO,WAAW,SAAS,IAAI,YAAY,KAAK,OAAO,OAAO,OAAO,KAAK,WAAW,cAAc,KACxH,UAAA;AAAA,MAAA,MAAM;AAAA,MAAO,MAAM,WAAW,uBAAuB;AAAA,IAAA,GACxD;AAAA,wBAED,OAAA,EAAI,OAAO,EAAE,SAAS,QAAQ,eAAe,UAAU,KAAK,EAAA,GACzD,WAAA,MAAM,WAAW,IAAI,IAAI,CAAA,QAAO;AAChC,YAAM,aAAa,cAAc,IAAI,IAAI,EAAE;AAC3C,YAAM,WAAW,IAAI,SAAS,OAAO,OAAO,OAAO,IAAI,MAAM,IAAI,OAAO,OAAO,OAAO;AACtF,YAAM,aAAa,IAAI,YAAY;AACnC,aACE,qBAAC,UAAA,EAAoB,MAAK,UAAS,SAAS,MAAM,OAAO,IAAI,EAAE,GAAG,UAAU,YAAY,OAAO;AAAA,QAC7F,SAAS;AAAA,QAAQ,YAAY;AAAA,QAAU,KAAK;AAAA,QAAI,SAAS;AAAA,QACzD,cAAc,OAAO,aAAa;AAAA,QAAI,QAAQ,aAAa,YAAY;AAAA,QACvE,QAAQ,aAAa,aAAa,WAAW,OAAO,OAAO,OAAO,KAAK;AAAA,QACvE,iBAAiB,aAAa,GAAG,QAAQ,OAAO;AAAA,QAChD,YAAY;AAAA,QAAa,WAAW;AAAA,QACpC,YAAY,OAAO,WAAW,WAAW;AAAA,QACzC,SAAS,cAAc,CAAC,aAAa,MAAM;AAAA,MAAA,GAG3C,UAAA;AAAA,QAAA,oBAAC,SAAI,OAAO;AAAA,UACV,OAAO;AAAA,UAAI,QAAQ;AAAA,UAAI,YAAY;AAAA,UACnC,cAAc,MAAM,WAAW,IAAI;AAAA,UACnC,QAAQ,aAAa,aAAa,WAAW,OAAO,OAAO,OAAO,KAAK;AAAA,UACvE,iBAAiB,aAAa,WAAW;AAAA,UACzC,SAAS;AAAA,UAAQ,YAAY;AAAA,UAAU,gBAAgB;AAAA,UACvD,YAAY;AAAA,QAAA,GAEX,UAAA,cACC,oBAAC,OAAA,EAAI,SAAQ,aAAY,OAAO,IAAI,QAAQ,IAAI,MAAK,QAAO,QAAQ,OAAO,OAAO,KAAK,SAAS,aAAa,GAC3G,8BAAC,YAAA,EAAS,QAAO,eAAA,CAAe,EAAA,CAClC,EAAA,CAEJ;AAAA,QACA,qBAAC,SAAI,OAAO,EAAE,MAAM,GAAG,UAAU,KAC/B,UAAA;AAAA,UAAA,qBAAC,OAAA,EAAI,OAAO,EAAE,SAAS,QAAQ,YAAY,UAAU,KAAK,EAAA,GACvD,UAAA;AAAA,YAAA,IAAI,UAAU,oBAAC,aAAA,EAAY,QAAQ,IAAI,QAAQ,MAAM,GAAG,OAAO,OAAO,OAAO,OAAO,IAAI,MAAM,GAAG;AAAA,gCACjG,QAAA,EAAK,OAAO,EAAE,UAAU,OAAO,WAAW,SAAS,IAAI,OAAO,OAAO,OAAO,KAAK,SAAS,YAAY,OAAQ,cAAI,MAAA,CAAM;AAAA,UAAA,GAC3H;AAAA,UACC,IAAI,eACH,oBAAC,OAAA,EAAI,OAAO,EAAE,UAAU,OAAO,WAAW,SAAS,IAAI,OAAO,OAAO,OAAO,KAAK,UAAU,WAAW,KAAM,cAAI,YAAA,CAAY;AAAA,QAAA,EAAA,CAEhI;AAAA,MAAA,EAAA,GAhCW,IAAI,EAiCjB;AAAA,IAEJ,CAAC,EAAA,CACH;AAAA,IACC,CAAC,eAAe,WACf,oBAAC,UAAA,EAAO,MAAK,UAAS,SAAS,QAAQ,UAAU,cAAc,SAAS,GAAG,OAAO;AAAA,MAChF,WAAW;AAAA,MAAG,SAAS;AAAA,MAAY,UAAU,OAAO,WAAW,SAAS;AAAA,MACxE,YAAY;AAAA,MAAK,cAAc,OAAO,aAAa;AAAA,MACnD,QAAQ,aAAa,OAAO,OAAO,OAAO,OAAO;AAAA,MACjD,iBAAiB,cAAc,OAAO,IAAI,GAAG,OAAO,OAAO,OAAO,OAAO,OAAO;AAAA,MAChF,OAAO,cAAc,OAAO,IAAI,eAAe,OAAO,OAAO,OAAO,OAAO,IAAI,OAAO,OAAO,KAAK;AAAA,MAClG,QAAQ,cAAc,OAAO,IAAI,YAAY;AAAA,MAC7C,YAAY,OAAO,WAAW,WAAW;AAAA,MAAS,YAAY;AAAA,IAAA,GAC7D,UAAA,qBAEH;AAAA,IAED,mCACE,OAAA,EAAI,OAAO,EAAE,WAAW,GAAG,UAAU,OAAO,WAAW,SAAS,IAAI,OAAO,OAAO,OAAO,KAAK,UAAU,WAAW,SAAA,GAAY,UAAA,sBAAA,CAEhI;AAAA,EAAA,GAEJ;AAEJ;AAEA,SAAS,aAAa,EAAE,OAAO,WAAW,WAAkG;AAC1I,QAAM,EAAE,OAAA,IAAW,SAAA;AACnB,QAAM,SAAS,MAAM,UAAU;AAC/B,QAAM,QAAQ,OAAO,OAAO,OAAO,MAAM;AACzC,QAAM,WAAW,MAAM;AAEvB,SACE,qBAAC,SAAI,OAAO;AAAA,IACV,WAAW;AAAA,IAAG,SAAS;AAAA,IACvB,iBAAiB,GAAG,KAAK;AAAA,IACzB,QAAQ,aAAa,KAAK;AAAA,IAC1B,YAAY,aAAa,KAAK;AAAA,IAC9B,cAAc,OAAO,aAAa;AAAA,EAAA,GAElC,UAAA;AAAA,IAAA,qBAAC,OAAA,EAAI,OAAO,EAAE,SAAS,QAAQ,YAAY,UAAU,KAAK,GAAG,cAAc,EAAA,GACzE,UAAA;AAAA,MAAA,oBAAC,aAAA,EAAY,QAAgB,MAAM,IAAI,OAAc;AAAA,0BACpD,QAAA,EAAK,OAAO,EAAE,UAAU,OAAO,WAAW,SAAS,IAAI,YAAY,KAAK,OAAO,OAAO,OAAO,KAAK,WAAY,gBAAM,MAAA,CAAM;AAAA,IAAA,GAC7H;AAAA,IACC,MAAM,UACL,oBAAC,OAAA,EAAI,OAAO,EAAE,UAAU,OAAO,WAAW,SAAS,IAAI,OAAO,OAAO,OAAO,KAAK,WAAW,cAAc,GAAG,YAAY,OAAQ,UAAA,MAAM,OAAA,CAAO;AAAA,IAE/I,CAAC,YAAY,UACZ,qBAAC,OAAA,EAAI,OAAO,EAAE,SAAS,QAAQ,KAAK,EAAA,GAClC,UAAA;AAAA,MAAA,oBAAC,UAAA,EAAO,MAAK,UAAS,SAAS,MAAM,QAAQ,EAAE,SAAS,MAAM,IAAI,WAAW,QAAQ,UAAA,CAAW,GAAG,OAAO;AAAA,QACxG,SAAS;AAAA,QAAY,UAAU,OAAO,WAAW,SAAS;AAAA,QAAI,YAAY;AAAA,QAC1E,cAAc,OAAO,aAAa;AAAA,QAAI,QAAQ;AAAA,QAC9C,QAAQ,aAAa,KAAK;AAAA,QAAI,iBAAiB,GAAG,KAAK;AAAA,QAAM;AAAA,QAC7D,YAAY,OAAO,WAAW,WAAW;AAAA,QAAS,YAAY;AAAA,MAAA,GAE7D,UAAA,MAAM,gBAAgB,UAAA,CACzB;AAAA,0BACC,UAAA,EAAO,MAAK,UAAS,SAAS,MAAM,QAAQ,EAAE,SAAS,MAAM,IAAI,WAAW,QAAQ,SAAA,CAAU,GAAG,OAAO;AAAA,QACvG,SAAS;AAAA,QAAY,UAAU,OAAO,WAAW,SAAS;AAAA,QAAI,YAAY;AAAA,QAC1E,cAAc,OAAO,aAAa;AAAA,QAAI,QAAQ;AAAA,QAC9C,QAAQ,aAAa,OAAO,OAAO,OAAO,KAAK;AAAA,QAAI,iBAAiB;AAAA,QACpE,OAAO,OAAO,OAAO,KAAK;AAAA,QAC1B,YAAY,OAAO,WAAW,WAAW;AAAA,QAAS,YAAY;AAAA,MAAA,GAE7D,UAAA,MAAM,eAAe,SAAA,CACxB;AAAA,IAAA,EAAA,CACF,IACE,WACF,oBAAC,OAAA,EAAI,OAAO;AAAA,MACV,UAAU,OAAO,WAAW,SAAS;AAAA,MAAI,YAAY;AAAA,MACrD,OAAO,aAAa,cAAc,OAAO,OAAO,OAAO,SAAS,OAAO,OAAO,KAAK;AAAA,MACnF,WAAW;AAAA,IAAA,GAEV,UAAA,aAAa,cAAc,gBAAgB,eAC9C,IACE;AAAA,EAAA,GACN;AAEJ;AAEA,SAAS,aAAa,EAAE,OAAO,WAAW,WAAkG;AAC1I,QAAM,EAAE,OAAA,IAAW,SAAA;AACnB,QAAM,CAAC,QAAQ,SAAS,IAAI,SAAS,KAAK;AAE1C,QAAM,aAAa,MAAM;;AACvB,oBAAU,cAAV,mBAAqB,UAAU,MAAM,SAAS,KAAK,MAAM;AACvD,gBAAU,IAAI;AACd,iBAAW,MAAM,UAAU,KAAK,GAAG,GAAI;AAAA,IACzC;AACA,QAAI,MAAM,GAAI,oCAAU,EAAE,SAAS,MAAM,IAAI,WAAW,QAAQ,QAAQ,OAAO,MAAM;EACvF;AAEA,QAAM,gBAAgB,MAAM;AAC1B,QAAI,MAAM,GAAI,oCAAU,EAAE,SAAS,MAAM,IAAI,WAAW,QAAQ,WAAW,OAAO,MAAM;EAC1F;AAEA,8BACG,OAAA,EAAI,OAAO,EAAE,WAAW,GAAG,cAAc,OAAO,aAAa,IAAI,UAAU,UAAU,QAAQ,aAAa,OAAO,OAAO,OAAO,KAAK,MAClI,UAAA;AAAA,IAAA,MAAM,SACL,oBAAC,OAAA,EAAI,OAAO;AAAA,MACV,SAAS;AAAA,MAAY,UAAU,OAAO,WAAW,SAAS;AAAA,MAAK,YAAY;AAAA,MAC3E,OAAO,OAAO,OAAO,KAAK;AAAA,MAAU,eAAe;AAAA,MAAa,eAAe;AAAA,MAC/E,iBAAiB,GAAG,OAAO,OAAO,WAAW,QAAQ;AAAA,MACrD,cAAc,aAAa,OAAO,OAAO,OAAO,KAAK;AAAA,MACrD,SAAS;AAAA,MAAQ,YAAY;AAAA,MAAU,gBAAgB;AAAA,IAAA,GAEvD,+BAAC,QAAA,EAAM,UAAA;AAAA,MAAA,MAAM;AAAA,MAAO,MAAM,WAAW,MAAM,MAAM,QAAQ,KAAK;AAAA,IAAA,EAAA,CAAG,EAAA,CACnE;AAAA,yBAED,OAAA,EAAI,OAAO,EAAE,UAAU,cACtB,UAAA;AAAA,MAAA,oBAAC,SAAI,OAAO;AAAA,QACV,QAAQ;AAAA,QAAG,SAAS;AAAA,QAAa,cAAc;AAAA,QAC/C,UAAU,OAAO,WAAW,SAAS;AAAA,QAAI,YAAY,OAAO,WAAW,WAAW;AAAA,QAClF,iBAAiB,GAAG,OAAO,OAAO,WAAW,IAAI;AAAA,QAAM,OAAO,OAAO,OAAO,KAAK;AAAA,QACjF,WAAW;AAAA,QAAQ,YAAY;AAAA,MAAA,GAE9B,gBAAM,SACT;AAAA,MACA,qBAAC,OAAA,EAAI,OAAO,EAAE,UAAU,YAAY,KAAK,GAAG,OAAO,GAAG,SAAS,QAAQ,KAAK,KAC1E,UAAA;AAAA,QAAA,oBAAC,UAAA,EAAO,MAAK,UAAS,SAAS,YAAY,OAAO;AAAA,UAChD,SAAS;AAAA,UAAW,UAAU,OAAO,WAAW,SAAS;AAAA,UAAO,cAAc,OAAO,aAAa;AAAA,UAClG,QAAQ,aAAa,OAAO,OAAO,OAAO,KAAK;AAAA,UAAI,iBAAiB,OAAO,OAAO,WAAW;AAAA,UAC7F,OAAO,SAAS,OAAO,OAAO,OAAO,SAAS,OAAO,OAAO,KAAK;AAAA,UACjE,QAAQ;AAAA,UAAW,YAAY,OAAO,WAAW,WAAW;AAAA,UAAS,YAAY;AAAA,QAAA,GAEhF,UAAA,SAAS,aAAa,OAAA,CACzB;AAAA,QACC,MAAM,cAAc,WAAW,MAAM,MACpC,oBAAC,UAAA,EAAO,MAAK,UAAS,SAAS,eAAe,OAAO;AAAA,UACnD,SAAS;AAAA,UAAW,UAAU,OAAO,WAAW,SAAS;AAAA,UAAO,cAAc,OAAO,aAAa;AAAA,UAClG,QAAQ,aAAa,OAAO,OAAO,OAAO,OAAO;AAAA,UACjD,iBAAiB,GAAG,OAAO,OAAO,OAAO,OAAO;AAAA,UAChD,OAAO,eAAe,OAAO,OAAO,OAAO,OAAO;AAAA,UAClD,QAAQ;AAAA,UAAW,YAAY,OAAO,WAAW,WAAW;AAAA,UAAS,YAAY;AAAA,QAAA,GAChF,UAAA,MAAA,CAEH;AAAA,MAAA,EAAA,CAEJ;AAAA,IAAA,EAAA,CACF;AAAA,EAAA,GACF;AAEJ;AAEA,SAAS,QAAQ,EAAE,SAAiC;AAClD,QAAM,EAAE,OAAA,IAAW,SAAA;AACnB,SACE,qBAAC,SAAI,OAAO;AAAA,IACV,WAAW;AAAA,IAAG,SAAS;AAAA,IACvB,iBAAiB,GAAG,OAAO,OAAO,WAAW,QAAQ;AAAA,IACrD,cAAc,OAAO,aAAa;AAAA,IAClC,QAAQ,aAAa,OAAO,OAAO,OAAO,KAAK;AAAA,EAAA,GAE9C,UAAA;AAAA,IAAA,MAAM,SACL,oBAAC,OAAA,EAAI,OAAO;AAAA,MACV,UAAU,OAAO,WAAW,SAAS;AAAA,MAAK,YAAY;AAAA,MAAK,OAAO,OAAO,OAAO,KAAK;AAAA,MACrF,eAAe;AAAA,MAAa,eAAe;AAAA,MAAU,cAAc;AAAA,IAAA,GAElE,gBAAM,OACT;AAAA,IAEF,oBAAC,OAAA,EAAI,OAAO,EAAE,SAAS,QAAQ,qBAAqB,YAAY,KAAK,YAAY,UAAU,OAAO,WAAW,SAAS,GAAA,GAClH,WAAA,MAAM,SAAS,CAAA,GAAI,IAAI,CAAC,GAAG,MAC3B,qBAAC,MAAM,UAAN,EACC,UAAA;AAAA,MAAA,oBAAC,QAAA,EAAK,OAAO,EAAE,OAAO,OAAO,OAAO,KAAK,UAAU,YAAY,SAAA,GAAa,UAAA,EAAE,KAAI;AAAA,MAClF,oBAAC,UAAK,OAAO;AAAA,QACX,OAAO,OAAO,OAAO,KAAK;AAAA,QAC1B,YAAY,EAAE,OAAO,OAAO,WAAW,WAAW,OAAO;AAAA,QACzD,oBAAoB,EAAE,OAAO,iBAAiB;AAAA,MAAA,GAE7C,YAAE,MAAA,CACL;AAAA,IAAA,EAAA,GARmB,CASrB,CACD,EAAA,CACH;AAAA,EAAA,GACF;AAEJ;AAEA,SAAS,YAAY,OAAkB,OAAe,WAAmB,SAAuC;AAC9G,UAAQ,MAAM,MAAA;AAAA,IACZ,KAAK;AAAS,aAAO,oBAAC,YAAA,EAAuB,MAAA,GAAP,KAAqB;AAAA,IAC3D,KAAK;AAAa,aAAO,oBAAC,gBAAA,EAA2B,MAAA,GAAP,KAAqB;AAAA,IACnE,KAAK;AAAY,aAAO,oBAAC,eAAA,EAA0B,MAAA,GAAP,KAAqB;AAAA,IACjE,KAAK;AAAS,aAAO,oBAAC,YAAA,EAAuB,MAAA,GAAP,KAAqB;AAAA,IAC3D,KAAK;AAAW,aAAO,oBAAC,cAAA,EAAyB,MAAA,GAAP,KAAqB;AAAA,IAC/D,KAAK;AAAU,aAAO,oBAAC,aAAA,EAAwB,OAAc,WAAsB,WAA3C,KAA6D;AAAA,IACrG,KAAK;AAAW,aAAO,oBAAC,cAAA,EAAyB,OAAc,WAAsB,WAA3C,KAA6D;AAAA,IACvG,KAAK;AAAW,aAAO,oBAAC,cAAA,EAAyB,OAAc,WAAsB,WAA3C,KAA6D;AAAA,IACvG,KAAK;AAAM,aAAO,oBAAC,SAAA,EAAoB,MAAA,GAAP,KAAqB;AAAA,IACrD;AAAS,aAAO;AAAA,EAAA;AAEpB;AAIO,MAAM,YAAY,KAAK,SAASA,WAAU;AAAA,EAC/C,WAAW,CAAA;AAAA,EACX;AAAA,EACA,UAAU;AAAA,EACV,cAAc;AAAA,EACd;AAAA,EACA;AAAA,EACA,WAAW;AAAA,EACX,iBAAiB;AAAA,EACjB,SAAS;AAAA,EACT;AAAA,EACA;AAAA,EACA;AACF,GAAuC;AACrC,QAAM,EAAE,OAAA,IAAW,SAAA;AACnB,QAAM,CAAC,OAAO,QAAQ,IAAI,SAAS,EAAE;AACrC,QAAM,iBAAiB,OAAuB,IAAI;AAClD,QAAM,WAAW,OAA4B,IAAI;AAEjD,YAAU,MAAM;;AACd,yBAAe,YAAf,mBAAwB,eAAe,EAAE,UAAU;EACrD,GAAG,CAAC,UAAU,OAAO,CAAC;AAEtB,QAAM,aAAa,YAAY,MAAM;AACnC,UAAM,OAAO,MAAM,KAAA;AACnB,QAAI,CAAC,QAAQ,SAAU;AACvB,WAAO,IAAI;AACX,aAAS,EAAE;AACX,QAAI,SAAS,QAAS,UAAS,QAAQ,MAAM,SAAS;AAAA,EACxD,GAAG,CAAC,OAAO,QAAQ,QAAQ,CAAC;AAE5B,QAAM,gBAAgB,YAAY,CAAC,MAA2B;AAC5D,QAAI,EAAE,QAAQ,WAAW,CAAC,EAAE,UAAU;AAAE,QAAE,eAAA;AAAkB,iBAAA;AAAA,IAAc;AAAA,EAC5E,GAAG,CAAC,UAAU,CAAC;AAEf,QAAM,cAAc,YAAY,CAAC,MAA8C;AAC7E,aAAS,EAAE,OAAO,KAAK;AACvB,UAAM,KAAK,EAAE;AACb,OAAG,MAAM,SAAS;AAClB,OAAG,MAAM,SAAS,GAAG,KAAK,IAAI,GAAG,cAAc,GAAG,CAAC;AAAA,EACrD,GAAG,CAAA,CAAE;AAEL,QAAM,aAAa,CAAC,OAAgB;AAClC,QAAI,CAAC,GAAI,QAAO;AAChB,WAAO,IAAI,KAAK,EAAE,EAAE,mBAAmB,CAAA,GAAI,EAAE,MAAM,WAAW,QAAQ,WAAW;AAAA,EACnF;AAGA,QAAM,gBAAgB,CAAC,SAAiB;AACtC,UAAM,QAA2B,CAAA;AACjC,UAAM,QAAQ,KAAK,MAAM,IAAI;AAC7B,QAAI,SAAS;AACb,QAAI,YAAsB,CAAA;AAE1B,UAAM,QAAQ,CAAC,MAAM,MAAM;AACzB,UAAI,KAAK,WAAW,KAAK,GAAG;AAC1B,YAAI,QAAQ;AACV,gBAAM;AAAA,YACJ,oBAAC,SAAsB,OAAO;AAAA,cAC5B,iBAAiB,GAAG,OAAO,OAAO,WAAW,IAAI;AAAA,cACjD,SAAS,GAAG,OAAO,QAAQ,EAAE,IAAI,OAAO,QAAQ,EAAE;AAAA,cAClD,cAAc,OAAO,aAAa;AAAA,cAClC,UAAU,OAAO,WAAW,SAAS;AAAA,cACrC,YAAY,OAAO,WAAW,WAAW;AAAA,cACzC,WAAW;AAAA,cACX,QAAQ,GAAG,OAAO,QAAQ,EAAE;AAAA,cAC5B,QAAQ,aAAa,OAAO,OAAO,OAAO,KAAK;AAAA,YAAA,GAE9C,UAAA,UAAU,KAAK,IAAI,EAAA,GAVZ,QAAQ,CAAC,EAWnB;AAAA,UAAA;AAEF,sBAAY,CAAA;AACZ,mBAAS;AAAA,QACX,OAAO;AACL,mBAAS;AAAA,QACX;AACA;AAAA,MACF;AACA,UAAI,QAAQ;AAAE,kBAAU,KAAK,IAAI;AAAG;AAAA,MAAQ;AAE5C,UAAI,YAA6B;AACjC,UAAI,KAAK,SAAS,IAAI,GAAG;AACvB,cAAM,WAAW,KAAK,MAAM,gBAAgB;AAC5C,oBAAY,SAAS,IAAI,CAAC,KAAK,MAAM,IAAI,MAAM,IAAI,oBAAC,UAAA,EAAgB,UAAA,IAAA,GAAJ,CAAQ,IAAY,GAAG;AAAA,MACzF;AACA,UAAI,OAAO,cAAc,YAAY,UAAU,SAAS,GAAG,GAAG;AAC5D,cAAM,WAAW,UAAU,MAAM,UAAU;AAC3C,oBAAY,SAAS;AAAA,UAAI,CAAC,KAAK,MAC7B,IAAI,MAAM,IACN,oBAAC,UAAa,OAAO;AAAA,YACnB,iBAAiB,GAAG,OAAO,OAAO,WAAW,IAAI;AAAA,YAAM,SAAS;AAAA,YAChE,cAAc;AAAA,YAAO,UAAU;AAAA,YAAS,YAAY,OAAO,WAAW,WAAW;AAAA,UAAA,GAC/E,UAAA,OAHO,CAGH,IACR;AAAA,QAAA;AAAA,MAER;AACA,YAAM,KAAK,qBAAC,MAAM,UAAN,EAAkC,UAAA;AAAA,QAAA;AAAA,QAAW,IAAI,MAAM,SAAS,yBAAM,MAAA,CAAA,CAAG;AAAA,MAAA,EAAA,GAArD,QAAQ,CAAC,EAA+C,CAAiB;AAAA,IAC3G,CAAC;AACD,WAAO;AAAA,EACT;AAEA,QAAM,aAAa,MACjB,qBAAC,OAAA,EAAI,OAAO,EAAE,SAAS,QAAQ,YAAY,UAAU,KAAK,OAAO,SAAS,OAAO,QAAQ,MACtF,UAAA;AAAA,IAAA,CAAC,GAAG,GAAG,CAAC,EAAE,IAAI,CAAA,MACb,oBAAC,SAAY,OAAO;AAAA,MAClB,OAAO;AAAA,MAAG,QAAQ;AAAA,MAAG,cAAc;AAAA,MACnC,iBAAiB,OAAO,OAAO,OAAO;AAAA,MAAS,SAAS;AAAA,MACxD,WAAW,kCAAkC,IAAI,GAAG;AAAA,IAAA,EACtD,GAJU,CAIP,CACJ;AAAA,IACD,oBAAC,WAAO,UAAA,yHAAA,CAAyH;AAAA,EAAA,GACnI;AAGF,SACE,qBAAC,SAAI,OAAO;AAAA,IACV,SAAS;AAAA,IAAQ,eAAe;AAAA,IAChC,QAAQ,OAAO,WAAW,WAAW,GAAG,MAAM,OAAO;AAAA,IACrD,YAAY,OAAO,WAAW,WAAW;AAAA,IACzC,iBAAiB,OAAO,OAAO,WAAW;AAAA,IAC1C,cAAc,OAAO,aAAa;AAAA,IAClC,QAAQ,aAAa,OAAO,OAAO,OAAO,KAAK;AAAA,IAC/C,UAAU;AAAA,IAAU,GAAG;AAAA,EAAA,GAGrB,UAAA;AAAA,KAAA,SAAS,YACT,qBAAC,OAAA,EAAI,OAAO;AAAA,MACV,SAAS;AAAA,MAAQ,YAAY;AAAA,MAAU,gBAAgB;AAAA,MACvD,SAAS,GAAG,OAAO,QAAQ,EAAE,IAAI,OAAO,QAAQ,EAAE;AAAA,MAClD,cAAc,aAAa,OAAO,OAAO,OAAO,KAAK;AAAA,MACrD,iBAAiB,OAAO,OAAO,WAAW;AAAA,IAAA,GAE1C,UAAA;AAAA,MAAA,qBAAC,OAAA,EACE,UAAA;AAAA,QAAA,6BAAU,OAAA,EAAI,OAAO,EAAE,UAAU,OAAO,WAAW,SAAS,IAAI,YAAY,KAAK,OAAO,OAAO,OAAO,KAAK,QAAA,GAAY,UAAA,OAAM;AAAA,QAC7H,YAAY,oBAAC,OAAA,EAAI,OAAO,EAAE,UAAU,OAAO,WAAW,SAAS,KAAK,OAAO,OAAO,OAAO,KAAK,SAAA,GAAa,UAAA,SAAA,CAAS;AAAA,MAAA,GACvH;AAAA,MACC,WAAW,SAAS,SAAS,yBAC3B,UAAA,EAAO,SAAS,SAAS,OAAO;AAAA,QAC/B,UAAU,OAAO,WAAW,SAAS;AAAA,QAAK,OAAO,OAAO,OAAO,KAAK;AAAA,QACpE,iBAAiB;AAAA,QAAe,QAAQ;AAAA,QAAQ,QAAQ;AAAA,QACxD,SAAS;AAAA,QAAW,cAAc,OAAO,aAAa;AAAA,QAAI,YAAY,OAAO,WAAW,WAAW;AAAA,MAAA,GAClG,UAAA,QAAA,CAAK;AAAA,IAAA,GAEZ;AAAA,IAIF;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,MAAK;AAAA,QACL,aAAU;AAAA,QACV,cAAW;AAAA,QACX,OAAO;AAAA,UACL,MAAM;AAAA,UAAG,UAAU;AAAA,UAAQ,SAAS,OAAO,QAAQ;AAAA,UACnD,SAAS;AAAA,UAAQ,eAAe;AAAA,UAAU,KAAK,OAAO,QAAQ;AAAA,QAAA;AAAA,QAG/D,UAAA;AAAA,UAAA,SAAS,WAAW,KACnB,oBAAC,OAAA,EAAI,OAAO;AAAA,YACV,SAAS;AAAA,YAAQ,YAAY;AAAA,YAAU,gBAAgB;AAAA,YACvD,MAAM;AAAA,YAAG,OAAO,OAAO,OAAO,KAAK;AAAA,YAAU,UAAU,OAAO,WAAW,SAAS;AAAA,UAAA,GACjF,UAAA,mBAAe;AAAA,UAGnB,SAAS,IAAI,CAAA,QAAO;AACnB,kBAAM,SAAS,IAAI,SAAS;AAC5B,kBAAM,WAAW,IAAI,SAAS;AAC9B,kBAAM,WAAW,IAAI;AACrB,kBAAM,gBAAgB,WAAW,OAAO,OAAO,OAAO,QAAQ,IAAI;AAGlE,kBAAM,WAAW,gBAAgB,GAAG,aAAa,OAAO,GAAG,OAAO,OAAO,OAAO,OAAO;AACvF,kBAAM,eAAe,gBAAgB,GAAG,aAAa,OAAO,GAAG,OAAO,OAAO,OAAO,OAAO;AAC3F,kBAAM,eAAe,iBAAiB;AAEtC,mBACE,qBAAC,SAAiB,OAAO;AAAA,cACvB,SAAS;AAAA,cAAQ,eAAe;AAAA,cAChC,YAAY,SAAS,aAAa;AAAA,cAClC,UAAU,WAAW,SAAS;AAAA,cAC9B,WAAW,SAAS,aAAa;AAAA,YAAA,GAEjC,UAAA;AAAA,cAAA,qBAAC,SAAI,OAAO;AAAA,gBACV,SAAS,GAAG,OAAO,QAAQ,EAAE,IAAI,OAAO,QAAQ,EAAE;AAAA,gBAClD,cAAc,OAAO,aAAa;AAAA,gBAClC,iBAAiB,SACb,GAAG,OAAO,OAAO,OAAO,OAAO,OAC/B,WAAW,WAAW,OAAO,OAAO,WAAW;AAAA,gBACnD,QAAQ,aAAa,SACjB,GAAG,OAAO,OAAO,OAAO,OAAO,OAC/B,WAAW,eAAe,OAAO,OAAO,OAAO,KAAK;AAAA,gBACxD,YAAY,YAAY,eAAe,aAAa,YAAY,KAAK;AAAA,gBACrE,UAAU,OAAO,WAAW,SAAS;AAAA,gBACrC,OAAO,OAAO,OAAO,KAAK;AAAA,gBAC1B,YAAY;AAAA,gBACZ,OAAO,WAAW,SAAS;AAAA,gBAC3B,SAAS,IAAI,WAAW,YAAY,MAAM;AAAA,cAAA,GAGzC,UAAA;AAAA,gBAAA,YAAY,YACX,qBAAC,OAAA,EAAI,OAAO,EAAE,SAAS,QAAQ,YAAY,UAAU,KAAK,GAAG,cAAc,KACzE,UAAA;AAAA,kBAAA,oBAAC,eAAY,QAAQ,UAAU,MAAM,IAAI,OAAO,eAAgB;AAAA,kBAChE,oBAAC,UAAK,OAAO;AAAA,oBACX,UAAU,OAAO,WAAW,SAAS;AAAA,oBAAK,YAAY;AAAA,oBACtD,OAAO;AAAA,oBAAe,eAAe;AAAA,oBAAa,eAAe;AAAA,kBAAA,GAEhE,UAAA,SAAA,CACH;AAAA,gBAAA,GACF;AAAA,gBAGD,cAAc,IAAI,OAAO;AAAA,gBAGzB,MAAM,QAAQ,IAAI,MAAM,KAAK,IAAI,OAAO,IAAI,CAAC,OAAO,MAAM,QAAQ,YAAY,OAAO,GAAG,IAAI,IAAI,YAAY,IAAI,IAAI;AAAA,gBAGpH,IAAI,WAAW,IAAI,QAAQ,SAAS,KACnC,oBAAC,SAAI,OAAO;AAAA,kBACV,SAAS;AAAA,kBAAQ,KAAK,OAAO,QAAQ;AAAA,kBAAI,WAAW,OAAO,QAAQ;AAAA,kBACnE,YAAY,OAAO,QAAQ;AAAA,kBAAI,WAAW,aAAa,OAAO,OAAO,OAAO,KAAK;AAAA,gBAAA,GAEhF,UAAA,IAAI,QAAQ,IAAI,CAAC,QAAQ,MACxB,oBAAC,UAAA,EAAe,SAAS,OAAO,SAAS,OAAO;AAAA,kBAC9C,UAAU,OAAO,WAAW,SAAS;AAAA,kBAAK,SAAS;AAAA,kBACnD,cAAc,OAAO,aAAa;AAAA,kBAClC,QAAQ,aAAa,OAAO,OAAO,OAAO,OAAO;AAAA,kBACjD,iBAAiB,GAAG,OAAO,OAAO,OAAO,OAAO;AAAA,kBAChD,OAAO,eAAe,OAAO,OAAO,OAAO,OAAO;AAAA,kBAAG,QAAQ;AAAA,kBAC7D,YAAY,OAAO,WAAW,WAAW;AAAA,gBAAA,GACvC,UAAA,OAAO,MAAA,GAPE,CAOI,CAClB,EAAA,CACH;AAAA,cAAA,GAEJ;AAAA,cAEC,kBAAkB,IAAI,aACrB,qBAAC,SAAI,OAAO;AAAA,gBACV,UAAU,OAAO,WAAW,SAAS;AAAA,gBAAO,OAAO,OAAO,OAAO,KAAK;AAAA,gBACtE,WAAW;AAAA,gBAAO,aAAa,OAAO,QAAQ;AAAA,gBAAI,cAAc,OAAO,QAAQ;AAAA,gBAC/E,SAAS;AAAA,gBAAQ,YAAY;AAAA,gBAAU,KAAK;AAAA,cAAA,GAE3C,UAAA;AAAA,gBAAA,WAAW,IAAI,SAAS;AAAA,gBACxB,IAAI,WAAW,WAAW,oBAAC,QAAA,EAAK,OAAO,EAAE,OAAO,OAAO,OAAO,OAAO,SAAA,GAAY,UAAA,WAAA,CAAQ;AAAA,cAAA,EAAA,CAC5F;AAAA,YAAA,EAAA,GApEM,IAAI,EAsEd;AAAA,UAEJ,CAAC;AAAA,UAEA,WACC,oBAAC,OAAA,EAAI,OAAO;AAAA,YACV,WAAW;AAAA,YACX,SAAS,GAAG,OAAO,QAAQ,EAAE,IAAI,OAAO,QAAQ,EAAE;AAAA,YAClD,cAAc,OAAO,aAAa;AAAA,YAClC,iBAAiB,OAAO,OAAO,WAAW;AAAA,YAC1C,QAAQ,aAAa,OAAO,OAAO,OAAO,KAAK;AAAA,UAAA,GAE/C,UAAA,oBAAC,YAAA,CAAA,CAAW,EAAA,CACd;AAAA,UAEF,oBAAC,OAAA,EAAI,KAAK,eAAA,CAAgB;AAAA,QAAA;AAAA,MAAA;AAAA,IAAA;AAAA,IAI5B,qBAAC,SAAI,OAAO;AAAA,MACV,SAAS;AAAA,MAAQ,YAAY;AAAA,MAAY,KAAK,OAAO,QAAQ;AAAA,MAC7D,SAAS,OAAO,QAAQ;AAAA,MACxB,WAAW,aAAa,OAAO,OAAO,OAAO,KAAK;AAAA,MAClD,iBAAiB,OAAO,OAAO,WAAW;AAAA,IAAA,GAE1C,UAAA;AAAA,MAAA;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,KAAK;AAAA,UAAU,OAAO;AAAA,UAAO,UAAU;AAAA,UAAa,WAAW;AAAA,UAC/D;AAAA,UAA0B;AAAA,UAAoB,cAAW;AAAA,UAAgB,MAAM;AAAA,UAC/E,OAAO;AAAA,YACL,MAAM;AAAA,YAAG,QAAQ;AAAA,YACjB,QAAQ,aAAa,OAAO,OAAO,OAAO,KAAK;AAAA,YAC/C,cAAc,OAAO,aAAa;AAAA,YAClC,SAAS,GAAG,OAAO,QAAQ,EAAE,IAAI,OAAO,QAAQ,EAAE;AAAA,YAClD,UAAU,OAAO,WAAW,SAAS;AAAA,YACrC,YAAY,OAAO,WAAW,WAAW;AAAA,YACzC,OAAO,OAAO,OAAO,KAAK;AAAA,YAC1B,iBAAiB,OAAO,OAAO,WAAW;AAAA,YAC1C,SAAS;AAAA,YAAQ,YAAY;AAAA,YAC7B,WAAW;AAAA,YAAK,YAAY;AAAA,YAC5B,WAAW;AAAA,UAAA;AAAA,QACb;AAAA,MAAA;AAAA,MAEF,oBAAC,UAAA,EAAO,SAAS,YAAY,UAAU,YAAY,CAAC,MAAM,KAAA,GAAQ,cAAW,gBAAe,OAAO;AAAA,QACjG,SAAS;AAAA,QAAQ,YAAY;AAAA,QAAU,gBAAgB;AAAA,QACvD,OAAO;AAAA,QAAI,QAAQ;AAAA,QAAI,cAAc,OAAO,aAAa;AAAA,QAAI,QAAQ;AAAA,QACrE,iBAAiB,MAAM,KAAA,IAAS,OAAO,OAAO,OAAO,UAAU,GAAG,OAAO,OAAO,OAAO,OAAO;AAAA,QAC9F,OAAO,MAAM,KAAA,IAAS,OAAO,OAAO,KAAK,UAAU,OAAO,OAAO,KAAK;AAAA,QACtE,QAAQ,MAAM,KAAA,KAAU,CAAC,WAAW,YAAY;AAAA,QAChD,YAAY,OAAO,UAAU;AAAA,QAAM,YAAY;AAAA,MAAA,GAE/C,UAAA,oBAAC,OAAA,EAAI,OAAM,MAAK,QAAO,MAAK,SAAQ,aAAY,MAAK,gBAAe,UAAA,oBAAC,QAAA,EAAK,GAAE,yCAAwC,GAAE,EAAA,CACxH;AAAA,IAAA,EAAA,CACF;AAAA,EAAA,GACF;AAEJ,CAAC;"}
@@ -1,5 +1,5 @@
1
1
  import { default as React } from 'react';
2
- import { ColorTarget } from '../context/DisplaySettingsContext';
2
+ import { ColorTarget } from '../../context/DisplaySettingsContext';
3
3
 
4
4
  export interface ColorPickerPanelProps {
5
5
  /** Current accent color */
@@ -1,8 +1,8 @@
1
1
  import { jsxs, jsx } from "react/jsx-runtime";
2
2
  import { memo, useState, useRef, useEffect } from "react";
3
- import { PRESET_COLORS } from "../context/DisplaySettingsContext.js";
4
- import { AstroIcon } from "./AstroIcon.js";
5
- import { useTheme } from "../theme/ThemeProvider.js";
3
+ import { PRESET_COLORS } from "../../context/DisplaySettingsContext.js";
4
+ import { AstroIcon } from "../display/AstroIcon.js";
5
+ import { useTheme } from "../../theme/ThemeProvider.js";
6
6
  const COLOR_SWATCHES = Object.entries(PRESET_COLORS).map(([key, color]) => ({
7
7
  key,
8
8
  color,
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ColorPickerPanel.js","sources":["../../../../src/react/core/widgets/ColorPickerPanel.tsx"],"sourcesContent":["/**\n * @zendir/ui - ColorPickerPanel Component\n * \n * Compact color picker with preset colors and target selector.\n * Used in AppBar for selecting accent and glass tint colors.\n * \n * Features:\n * - Preset color swatches grid\n * - Target toggle: Both | Accent Only | Glass Only\n * - Popover design with smooth animations\n * - Keyboard accessible\n * \n * @example\n * ```tsx\n * <ColorPickerPanel\n * accentColor=\"#8b5cf6\"\n * glassTint=\"#8b5cf6\"\n * colorTarget=\"both\"\n * onAccentChange={setAccentColor}\n * onGlassTintChange={setGlassTint}\n * onTargetChange={setColorTarget}\n * />\n * ```\n */\n\nimport React, { memo, useState, useRef, useEffect } from 'react';\nimport { useTheme } from '../../theme';\nimport { PRESET_COLORS, type ColorTarget } from '../../context/DisplaySettingsContext';\nimport { AstroIcon } from '../display/AstroIcon';\n\n// =============================================================================\n// Types\n// =============================================================================\n\nexport interface ColorPickerPanelProps {\n /** Current accent color */\n accentColor: string;\n \n /** Current glass tint color */\n glassTint: string;\n \n /** Which color to affect: both, accent, or glass */\n colorTarget: ColorTarget;\n \n /** Callback when accent color changes */\n onAccentChange: (color: string) => void;\n \n /** Callback when glass tint changes */\n onGlassTintChange: (color: string) => void;\n \n /** Callback when target changes */\n onTargetChange: (target: ColorTarget) => void;\n \n /** Callback when any color is selected (respects target) */\n onColorSelect?: (color: string) => void;\n \n /** Compact mode - show only trigger button */\n compact?: boolean;\n \n /** Custom className */\n className?: string;\n}\n\n// =============================================================================\n// Color Swatches\n// =============================================================================\n\nconst COLOR_SWATCHES = Object.entries(PRESET_COLORS).map(([key, color]) => ({\n key,\n color,\n label: key.charAt(0).toUpperCase() + key.slice(1),\n}));\n\n// =============================================================================\n// Target Toggle Component\n// =============================================================================\n\ninterface TargetToggleProps {\n value: ColorTarget;\n onChange: (target: ColorTarget) => void;\n tokens: any;\n}\n\nconst TargetToggle = memo(function TargetToggle({ value, onChange, tokens }: TargetToggleProps) {\n const targets: { key: ColorTarget; label: string }[] = [\n { key: 'both', label: 'Both' },\n { key: 'accent', label: 'Accent' },\n { key: 'glass', label: 'Glass' },\n ];\n \n return (\n <div style={{\n display: 'flex',\n gap: 2,\n padding: 2,\n backgroundColor: 'rgba(255,255,255,0.05)',\n borderRadius: tokens.borderRadius.sm,\n }}>\n {targets.map(({ key, label }) => (\n <button\n key={key}\n onClick={() => onChange(key)}\n style={{\n flex: 1,\n padding: '4px 8px',\n border: 'none',\n borderRadius: tokens.borderRadius.sm - 2,\n backgroundColor: value === key ? 'rgba(255,255,255,0.15)' : 'transparent',\n color: value === key ? tokens.colors.text.primary : tokens.colors.text.tertiary,\n fontSize: '0.625rem', // 10px in rem\n fontWeight: value === key ? 600 : 400,\n cursor: 'pointer',\n transition: 'all 0.15s ease',\n }}\n >\n {label}\n </button>\n ))}\n </div>\n );\n});\n\n// =============================================================================\n// Color Grid Component\n// =============================================================================\n\ninterface ColorGridProps {\n selectedColor: string;\n onSelect: (color: string) => void;\n tokens: any;\n}\n\nconst ColorGrid = memo(function ColorGrid({ selectedColor, onSelect, tokens: _tokens }: ColorGridProps) {\n return (\n <div style={{\n display: 'grid',\n gridTemplateColumns: 'repeat(6, 1fr)',\n gap: 4,\n }}>\n {COLOR_SWATCHES.map(({ key, color, label }) => {\n const isSelected = selectedColor.toLowerCase() === color.toLowerCase();\n \n return (\n <button\n key={key}\n onClick={() => onSelect(color)}\n aria-label={`Select ${label}`}\n title={label}\n style={{\n width: 24,\n height: 24,\n padding: 0,\n border: isSelected ? '2px solid white' : '1px solid rgba(255,255,255,0.2)',\n borderRadius: 4,\n backgroundColor: color,\n cursor: 'pointer',\n transition: 'all 0.15s ease',\n transform: isSelected ? 'scale(1.1)' : 'scale(1)',\n boxShadow: isSelected ? `0 0 8px ${color}80` : 'none',\n }}\n onMouseEnter={(e) => {\n if (!isSelected) {\n e.currentTarget.style.transform = 'scale(1.15)';\n e.currentTarget.style.borderColor = 'rgba(255,255,255,0.5)';\n }\n }}\n onMouseLeave={(e) => {\n e.currentTarget.style.transform = isSelected ? 'scale(1.1)' : 'scale(1)';\n e.currentTarget.style.borderColor = isSelected ? 'white' : 'rgba(255,255,255,0.2)';\n }}\n />\n );\n })}\n </div>\n );\n});\n\n// =============================================================================\n// ColorPickerPanel Component\n// =============================================================================\n\nexport const ColorPickerPanel = memo(function ColorPickerPanel({\n accentColor,\n glassTint,\n colorTarget,\n onAccentChange,\n onGlassTintChange,\n onTargetChange,\n onColorSelect,\n compact = true,\n className = '',\n}: ColorPickerPanelProps): React.ReactElement {\n const { tokens, theme } = useTheme();\n const [isOpen, setIsOpen] = useState(false);\n const panelRef = useRef<HTMLDivElement>(null);\n const triggerRef = useRef<HTMLButtonElement>(null);\n \n const isTransparentTheme = theme === 'transparent' || theme === 'transparent-bold' || theme === 'transparent-minimal';\n \n // Current display color based on target\n const displayColor = colorTarget === 'glass' ? glassTint : accentColor;\n \n // Handle color selection\n const handleColorSelect = (color: string) => {\n if (onColorSelect) {\n onColorSelect(color);\n } else {\n switch (colorTarget) {\n case 'accent':\n onAccentChange(color);\n break;\n case 'glass':\n onGlassTintChange(color);\n break;\n case 'both':\n default:\n onAccentChange(color);\n onGlassTintChange(color);\n break;\n }\n }\n };\n \n // Close panel when clicking outside\n useEffect(() => {\n const handleClickOutside = (event: MouseEvent) => {\n if (\n panelRef.current &&\n !panelRef.current.contains(event.target as Node) &&\n triggerRef.current &&\n !triggerRef.current.contains(event.target as Node)\n ) {\n setIsOpen(false);\n }\n };\n \n if (isOpen) {\n document.addEventListener('mousedown', handleClickOutside);\n return () => document.removeEventListener('mousedown', handleClickOutside);\n }\n }, [isOpen]);\n \n // Close on escape key\n useEffect(() => {\n const handleEscape = (event: KeyboardEvent) => {\n if (event.key === 'Escape') {\n setIsOpen(false);\n triggerRef.current?.focus();\n }\n };\n \n if (isOpen) {\n document.addEventListener('keydown', handleEscape);\n return () => document.removeEventListener('keydown', handleEscape);\n }\n }, [isOpen]);\n \n if (compact) {\n return (\n <div style={{ position: 'relative' }} className={className}>\n {/* Trigger Button */}\n <button\n ref={triggerRef}\n onClick={() => setIsOpen(!isOpen)}\n aria-label=\"Open color picker\"\n aria-expanded={isOpen}\n style={{\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n width: 36,\n height: 36,\n padding: 0,\n border: '2px solid rgba(255,255,255,0.3)',\n borderRadius: tokens.borderRadius.md,\n backgroundColor: displayColor,\n cursor: 'pointer',\n transition: 'all 0.15s ease',\n boxShadow: isOpen ? `0 0 12px ${displayColor}60` : 'none',\n }}\n onMouseEnter={(e) => {\n e.currentTarget.style.borderColor = 'rgba(255,255,255,0.5)';\n e.currentTarget.style.transform = 'scale(1.05)';\n }}\n onMouseLeave={(e) => {\n e.currentTarget.style.borderColor = 'rgba(255,255,255,0.3)';\n e.currentTarget.style.transform = 'scale(1)';\n }}\n >\n <AstroIcon name=\"palette\" size={16} color=\"white\" />\n </button>\n \n {/* Popover Panel */}\n {isOpen && (\n <div\n ref={panelRef}\n style={{\n position: 'absolute',\n top: '100%',\n right: 0,\n marginTop: 8,\n padding: 12,\n backgroundColor: tokens.colors.background.elevated,\n border: `1px solid ${tokens.colors.border.default}`,\n borderRadius: tokens.borderRadius.lg,\n boxShadow: tokens.shadows.lg,\n zIndex: 1000,\n minWidth: 180,\n }}\n >\n {/* Target Toggle - only show for transparent themes */}\n {isTransparentTheme && (\n <div style={{ marginBottom: 12 }}>\n <div style={{\n fontSize: '0.625rem', // 10px in rem\n fontWeight: 500,\n color: tokens.colors.text.tertiary,\n marginBottom: 6,\n textTransform: 'uppercase',\n letterSpacing: '0.05em',\n }}>\n Apply to\n </div>\n <TargetToggle\n value={colorTarget}\n onChange={onTargetChange}\n tokens={tokens}\n />\n </div>\n )}\n \n {/* Color Grid */}\n <div>\n <div style={{\n fontSize: '0.625rem', // 10px in rem\n fontWeight: 500,\n color: tokens.colors.text.tertiary,\n marginBottom: 6,\n textTransform: 'uppercase',\n letterSpacing: '0.05em',\n }}>\n {colorTarget === 'glass' ? 'Glass Tint' : colorTarget === 'accent' ? 'Accent Color' : 'Color'}\n </div>\n <ColorGrid\n selectedColor={displayColor}\n onSelect={handleColorSelect}\n tokens={tokens}\n />\n </div>\n \n {/* Current Colors Display */}\n {isTransparentTheme && colorTarget === 'both' && accentColor !== glassTint && (\n <div style={{\n marginTop: 12,\n paddingTop: 12,\n borderTop: `1px solid ${tokens.colors.border.muted}`,\n display: 'flex',\n gap: 8,\n fontSize: '0.625rem', // 10px in rem\n color: tokens.colors.text.tertiary,\n }}>\n <div style={{ display: 'flex', alignItems: 'center', gap: 4 }}>\n <span style={{\n width: 12,\n height: 12,\n borderRadius: 2,\n backgroundColor: accentColor,\n border: '1px solid rgba(255,255,255,0.2)',\n }} />\n Accent\n </div>\n <div style={{ display: 'flex', alignItems: 'center', gap: 4 }}>\n <span style={{\n width: 12,\n height: 12,\n borderRadius: 2,\n backgroundColor: glassTint,\n border: '1px solid rgba(255,255,255,0.2)',\n }} />\n Glass\n </div>\n </div>\n )}\n </div>\n )}\n </div>\n );\n }\n \n // Expanded/inline mode\n return (\n <div className={className} style={{ display: 'flex', flexDirection: 'column', gap: 12 }}>\n {isTransparentTheme && (\n <TargetToggle\n value={colorTarget}\n onChange={onTargetChange}\n tokens={tokens}\n />\n )}\n <ColorGrid\n selectedColor={displayColor}\n onSelect={handleColorSelect}\n tokens={tokens}\n />\n </div>\n );\n});\n\nexport default ColorPickerPanel;\n"],"names":["TargetToggle","ColorGrid","ColorPickerPanel"],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  import { jsxs, jsx } from "react/jsx-runtime";
2
2
  import { memo, useState, useCallback, useMemo } from "react";
3
- import { useTheme } from "../theme/ThemeProvider.js";
3
+ import { useTheme } from "../../theme/ThemeProvider.js";
4
4
  const CommandBuilder = memo(function CommandBuilder2({
5
5
  target,
6
6
  command,