@ashlr/hub 3.10.0 → 3.11.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 (534) hide show
  1. package/CHANGELOG.md +156 -0
  2. package/README.md +343 -82
  3. package/dist/authority-surface.json +109 -29
  4. package/dist/build-identity.json +2 -2
  5. package/dist/cli/cloud.d.ts +39 -0
  6. package/dist/cli/cloud.js +448 -0
  7. package/dist/cli/cloud.js.map +1 -0
  8. package/dist/cli/completions.js +4 -0
  9. package/dist/cli/completions.js.map +1 -1
  10. package/dist/cli/help.js +2 -0
  11. package/dist/cli/help.js.map +1 -1
  12. package/dist/cli/index.d.ts +1 -0
  13. package/dist/cli/index.js +10 -0
  14. package/dist/cli/index.js.map +1 -1
  15. package/dist/core/cloud/backlog.d.ts +17 -0
  16. package/dist/core/cloud/backlog.js +177 -0
  17. package/dist/core/cloud/backlog.js.map +1 -0
  18. package/dist/core/cloud/budget.d.ts +19 -0
  19. package/dist/core/cloud/budget.js +99 -0
  20. package/dist/core/cloud/budget.js.map +1 -0
  21. package/dist/core/cloud/checkout.d.ts +41 -0
  22. package/dist/core/cloud/checkout.js +168 -0
  23. package/dist/core/cloud/checkout.js.map +1 -0
  24. package/dist/core/cloud/cloud-api.d.ts +86 -0
  25. package/dist/core/cloud/cloud-api.js +599 -0
  26. package/dist/core/cloud/cloud-api.js.map +1 -0
  27. package/dist/core/cloud/delivery-contract.d.ts +25 -0
  28. package/dist/core/cloud/delivery-contract.js +138 -0
  29. package/dist/core/cloud/delivery-contract.js.map +1 -0
  30. package/dist/core/cloud/improvement-backlog.d.ts +11 -0
  31. package/dist/core/cloud/improvement-backlog.js +26 -0
  32. package/dist/core/cloud/improvement-backlog.js.map +1 -0
  33. package/dist/core/cloud/launcher.d.ts +68 -0
  34. package/dist/core/cloud/launcher.js +312 -0
  35. package/dist/core/cloud/launcher.js.map +1 -0
  36. package/dist/core/cloud/service.d.ts +51 -0
  37. package/dist/core/cloud/service.js +215 -0
  38. package/dist/core/cloud/service.js.map +1 -0
  39. package/dist/core/cloud/store.d.ts +41 -0
  40. package/dist/core/cloud/store.js +278 -0
  41. package/dist/core/cloud/store.js.map +1 -0
  42. package/dist/core/cloud/tracker.d.ts +30 -0
  43. package/dist/core/cloud/tracker.js +152 -0
  44. package/dist/core/cloud/tracker.js.map +1 -0
  45. package/dist/core/cloud/types.d.ts +233 -0
  46. package/dist/core/cloud/types.js +73 -0
  47. package/dist/core/cloud/types.js.map +1 -0
  48. package/dist/core/daemon/capacity-publisher.d.ts +19 -0
  49. package/dist/core/daemon/capacity-publisher.js +49 -2
  50. package/dist/core/daemon/capacity-publisher.js.map +1 -1
  51. package/dist/core/daemon/overnight-status.d.ts +13 -0
  52. package/dist/core/daemon/overnight-status.js +93 -8
  53. package/dist/core/daemon/overnight-status.js.map +1 -1
  54. package/dist/core/fleet/dispatch-router.js +26 -9
  55. package/dist/core/fleet/dispatch-router.js.map +1 -1
  56. package/dist/core/fleet/fleet-runtime-journal.js +12 -5
  57. package/dist/core/fleet/fleet-runtime-journal.js.map +1 -1
  58. package/dist/core/fleet/fleet-types.d.ts +13 -0
  59. package/dist/core/routing/budget-store.js +11 -5
  60. package/dist/core/routing/budget-store.js.map +1 -1
  61. package/dist/core/routing/capacity-history-api.d.ts +30 -0
  62. package/dist/core/routing/capacity-history-api.js +147 -0
  63. package/dist/core/routing/capacity-history-api.js.map +1 -0
  64. package/dist/core/routing/capacity-history-types.d.ts +63 -0
  65. package/dist/core/routing/capacity-history-types.js +18 -0
  66. package/dist/core/routing/capacity-history-types.js.map +1 -0
  67. package/dist/core/routing/capacity-history.d.ts +130 -0
  68. package/dist/core/routing/capacity-history.js +654 -0
  69. package/dist/core/routing/capacity-history.js.map +1 -0
  70. package/dist/core/routing/headroom.d.ts +5 -1
  71. package/dist/core/routing/headroom.js +82 -41
  72. package/dist/core/routing/headroom.js.map +1 -1
  73. package/dist/core/routing/router.d.ts +8 -1
  74. package/dist/core/routing/router.js +49 -16
  75. package/dist/core/routing/router.js.map +1 -1
  76. package/dist/core/routing/seat-reasons.d.ts +35 -0
  77. package/dist/core/routing/seat-reasons.js +48 -0
  78. package/dist/core/routing/seat-reasons.js.map +1 -0
  79. package/dist/core/routing/types.d.ts +37 -0
  80. package/dist/core/routing/types.js.map +1 -1
  81. package/dist/core/verse/activity-api.d.ts +3 -1
  82. package/dist/core/verse/activity-api.js +16 -1
  83. package/dist/core/verse/activity-api.js.map +1 -1
  84. package/dist/core/verse/activity.d.ts +7 -0
  85. package/dist/core/verse/activity.js +23 -0
  86. package/dist/core/verse/activity.js.map +1 -1
  87. package/dist/core/verse/fleet-history-types.d.ts +12 -4
  88. package/dist/core/verse/fleet-history-types.js +4 -2
  89. package/dist/core/verse/fleet-history-types.js.map +1 -1
  90. package/dist/core/verse/fleet-live-api.d.ts +14 -1
  91. package/dist/core/verse/fleet-live-api.js +31 -11
  92. package/dist/core/verse/fleet-live-api.js.map +1 -1
  93. package/dist/core/verse/preferences.d.ts +3 -1
  94. package/dist/core/verse/preferences.js +5 -2
  95. package/dist/core/verse/preferences.js.map +1 -1
  96. package/dist/core/verse/types.d.ts +5 -1
  97. package/dist/core/verse/types.js.map +1 -1
  98. package/dist/core/verse/verse-api.d.ts +1 -1
  99. package/dist/core/verse/verse-api.js +4 -1
  100. package/dist/core/verse/verse-api.js.map +1 -1
  101. package/dist/core/vision/leader-cloud.d.ts +63 -0
  102. package/dist/core/vision/leader-cloud.js +134 -0
  103. package/dist/core/vision/leader-cloud.js.map +1 -0
  104. package/dist/core/vision/leader.d.ts +6 -0
  105. package/dist/core/vision/leader.js +12 -1
  106. package/dist/core/vision/leader.js.map +1 -1
  107. package/dist/core/web/public/next/assets/{ActionMenu-DhbNne-M.js → ActionMenu-CQvNJvHY.js} +2 -2
  108. package/dist/core/web/public/next/assets/{ActionMenu-DhbNne-M.js.map → ActionMenu-CQvNJvHY.js.map} +1 -1
  109. package/dist/core/web/public/next/assets/Advanced-Bywv_iYR.css +1 -0
  110. package/dist/core/web/public/next/assets/Advanced-DEM93sKI.js +2 -0
  111. package/dist/core/web/public/next/assets/Advanced-DEM93sKI.js.map +1 -0
  112. package/dist/core/web/public/next/assets/{App-DyBg1v_q.js → App-CimXmK0L.js} +5 -5
  113. package/dist/core/web/public/next/assets/{App-DyBg1v_q.js.map → App-CimXmK0L.js.map} +1 -1
  114. package/dist/core/web/public/next/assets/AppsSection-D6U-dSj6.js +2 -0
  115. package/dist/core/web/public/next/assets/AppsSection-D6U-dSj6.js.map +1 -0
  116. package/dist/core/web/public/next/assets/AreaTrend-LD9lCPkT.js +2 -0
  117. package/dist/core/web/public/next/assets/AreaTrend-LD9lCPkT.js.map +1 -0
  118. package/dist/core/web/public/next/assets/AutonomySection-3V9pUyxm.js +2 -0
  119. package/dist/core/web/public/next/assets/{AutonomySection-CoMngwNB.js.map → AutonomySection-3V9pUyxm.js.map} +1 -1
  120. package/dist/core/web/public/next/assets/BranchBar-BZNQ50YE.css +1 -0
  121. package/dist/core/web/public/next/assets/BranchBar-U8UdpfEB.js +2 -0
  122. package/dist/core/web/public/next/assets/BranchBar-U8UdpfEB.js.map +1 -0
  123. package/dist/core/web/public/next/assets/BudgetControl-DOTlMSmW.js +2 -0
  124. package/dist/core/web/public/next/assets/BudgetControl-DOTlMSmW.js.map +1 -0
  125. package/dist/core/web/public/next/assets/BurnDown-x4PWH9JF.js +2 -0
  126. package/dist/core/web/public/next/assets/BurnDown-x4PWH9JF.js.map +1 -0
  127. package/dist/core/web/public/next/assets/{Button-0-nNbv1h.js → Button-DYv_KKxr.js} +2 -2
  128. package/dist/core/web/public/next/assets/{Button-0-nNbv1h.js.map → Button-DYv_KKxr.js.map} +1 -1
  129. package/dist/core/web/public/next/assets/CapacityStrip-C667yQe8.js +2 -0
  130. package/dist/core/web/public/next/assets/CapacityStrip-C667yQe8.js.map +1 -0
  131. package/dist/core/web/public/next/assets/CapacityStrip-Cc28CyWk.css +1 -0
  132. package/dist/core/web/public/next/assets/ChatSection-CCcIPpOq.js +3 -0
  133. package/dist/core/web/public/next/assets/{ChatSection-B9cdRKUh.js.map → ChatSection-CCcIPpOq.js.map} +1 -1
  134. package/dist/core/web/public/next/assets/CloudBudgetForm-DJeJvBEu.js +2 -0
  135. package/dist/core/web/public/next/assets/CloudBudgetForm-DJeJvBEu.js.map +1 -0
  136. package/dist/core/web/public/next/assets/{CommandPalette-GpeCSrPy.js → CommandPalette-FiD4N8XD.js} +2 -2
  137. package/dist/core/web/public/next/assets/{CommandPalette-GpeCSrPy.js.map → CommandPalette-FiD4N8XD.js.map} +1 -1
  138. package/dist/core/web/public/next/assets/CommandSection-DN8KwH-X.js +2 -0
  139. package/dist/core/web/public/next/assets/CommandSection-DN8KwH-X.js.map +1 -0
  140. package/dist/core/web/public/next/assets/Composer-ByzxOJK6.css +1 -0
  141. package/dist/core/web/public/next/assets/Composer.module-C8U73KdQ.js +2 -0
  142. package/dist/core/web/public/next/assets/{Composer.module-DJMdrqNt.js.map → Composer.module-C8U73KdQ.js.map} +1 -1
  143. package/dist/core/web/public/next/assets/DiffPane-BAvvbBsf.css +1 -0
  144. package/dist/core/web/public/next/assets/DiffPane-DLJ3gGGK.js +2 -0
  145. package/dist/core/web/public/next/assets/DiffPane-DLJ3gGGK.js.map +1 -0
  146. package/dist/core/web/public/next/assets/{DiffViewer-tOGWk0CA.js → DiffViewer-B7NWPjIO.js} +2 -2
  147. package/dist/core/web/public/next/assets/{DiffViewer-tOGWk0CA.js.map → DiffViewer-B7NWPjIO.js.map} +1 -1
  148. package/dist/core/web/public/next/assets/DockHost-B4RaYOET.css +1 -0
  149. package/dist/core/web/public/next/assets/DockHost-DvR-hPhZ.js +2 -0
  150. package/dist/core/web/public/next/assets/DockHost-DvR-hPhZ.js.map +1 -0
  151. package/dist/core/web/public/next/assets/{EmptyState-DdJ4CxtO.js → EmptyState-DhNgDDrF.js} +2 -2
  152. package/dist/core/web/public/next/assets/{EmptyState-DdJ4CxtO.js.map → EmptyState-DhNgDDrF.js.map} +1 -1
  153. package/dist/core/web/public/next/assets/{Epistemic-BLjM5y_y.js → Epistemic-uARPnx9x.js} +2 -2
  154. package/dist/core/web/public/next/assets/{Epistemic-BLjM5y_y.js.map → Epistemic-uARPnx9x.js.map} +1 -1
  155. package/dist/core/web/public/next/assets/FleetSection-CFiWeOEs.css +1 -0
  156. package/dist/core/web/public/next/assets/FleetSection-D_zRBCub.js +3 -0
  157. package/dist/core/web/public/next/assets/FleetSection-D_zRBCub.js.map +1 -0
  158. package/dist/core/web/public/next/assets/Funnel-CL8uHONq.js +2 -0
  159. package/dist/core/web/public/next/assets/Funnel-CL8uHONq.js.map +1 -0
  160. package/dist/core/web/public/next/assets/GearTray-C7k4l_BW.js +2 -0
  161. package/dist/core/web/public/next/assets/GearTray-C7k4l_BW.js.map +1 -0
  162. package/dist/core/web/public/next/assets/GrowthSection-DwdNSGj8.js +2 -0
  163. package/dist/core/web/public/next/assets/GrowthSection-DwdNSGj8.js.map +1 -0
  164. package/dist/core/web/public/next/assets/HandoffDialog-FPVOqOMN.js +2 -0
  165. package/dist/core/web/public/next/assets/HandoffDialog-FPVOqOMN.js.map +1 -0
  166. package/dist/core/web/public/next/assets/{Input-CTu0CycC.js → Input-B9-VLcHS.js} +2 -2
  167. package/dist/core/web/public/next/assets/{Input-CTu0CycC.js.map → Input-B9-VLcHS.js.map} +1 -1
  168. package/dist/core/web/public/next/assets/{LeaderCard-BuSDeATv.js → LeaderCard-4R0BhDzT.js} +2 -2
  169. package/dist/core/web/public/next/assets/{LeaderCard-BuSDeATv.js.map → LeaderCard-4R0BhDzT.js.map} +1 -1
  170. package/dist/core/web/public/next/assets/{MatrixHeatmap-9dKgJ_pT.css → MatrixHeatmap-Bmnvo1l1.css} +1 -1
  171. package/dist/core/web/public/next/assets/MatrixHeatmap-DiuushcS.js +2 -0
  172. package/dist/core/web/public/next/assets/MatrixHeatmap-DiuushcS.js.map +1 -0
  173. package/dist/core/web/public/next/assets/McpSection-CJ__OJKl.js +2 -0
  174. package/dist/core/web/public/next/assets/{McpSection-1UncWBpW.js.map → McpSection-CJ__OJKl.js.map} +1 -1
  175. package/dist/core/web/public/next/assets/MessageMarkdown-Cgh5f1-Q.css +1 -0
  176. package/dist/core/web/public/next/assets/MessageMarkdown-qWKyJvAQ.js +3 -0
  177. package/dist/core/web/public/next/assets/{MessageMarkdown-C4pl9LI5.js.map → MessageMarkdown-qWKyJvAQ.js.map} +1 -1
  178. package/dist/core/web/public/next/assets/{MessageMarkdownRenderer-CZsF77ZM.js → MessageMarkdownRenderer-x05TrsrW.js} +2 -2
  179. package/dist/core/web/public/next/assets/{MessageMarkdownRenderer-CZsF77ZM.js.map → MessageMarkdownRenderer-x05TrsrW.js.map} +1 -1
  180. package/dist/core/web/public/next/assets/{Meter-C18ciKz4.js → Meter-D-hncpkO.js} +2 -2
  181. package/dist/core/web/public/next/assets/{Meter-C18ciKz4.js.map → Meter-D-hncpkO.js.map} +1 -1
  182. package/dist/core/web/public/next/assets/MindSection-BjXHkQPS.js +2 -0
  183. package/dist/core/web/public/next/assets/MindSection-BjXHkQPS.js.map +1 -0
  184. package/dist/core/web/public/next/assets/MutationTokenDialog-SkRxqV_I.js +2 -0
  185. package/dist/core/web/public/next/assets/MutationTokenDialog-SkRxqV_I.js.map +1 -0
  186. package/dist/core/web/public/next/assets/NeedsYouDrawer-BpvidnM2.css +1 -0
  187. package/dist/core/web/public/next/assets/NeedsYouDrawer-rSd1ZHAR.js +2 -0
  188. package/dist/core/web/public/next/assets/NeedsYouDrawer-rSd1ZHAR.js.map +1 -0
  189. package/dist/core/web/public/next/assets/NeedsYouList-CG-nB1tr.js +2 -0
  190. package/dist/core/web/public/next/assets/NeedsYouList-CG-nB1tr.js.map +1 -0
  191. package/dist/core/web/public/next/assets/NeedsYouList-CruOt4JT.css +1 -0
  192. package/dist/core/web/public/next/assets/NewChatDialog-BeDQ1eW3.js +3 -0
  193. package/dist/core/web/public/next/assets/{NewChatDialog-B_BsS9pr.js.map → NewChatDialog-BeDQ1eW3.js.map} +1 -1
  194. package/dist/core/web/public/next/assets/OnboardingFlow-CkTZtt-m.js +2 -0
  195. package/dist/core/web/public/next/assets/{OnboardingFlow-CtCPpgoX.js.map → OnboardingFlow-CkTZtt-m.js.map} +1 -1
  196. package/dist/core/web/public/next/assets/PreviewPane-DoMsJSG3.css +1 -0
  197. package/dist/core/web/public/next/assets/PreviewPane-kzbbSK4u.js +2 -0
  198. package/dist/core/web/public/next/assets/PreviewPane-kzbbSK4u.js.map +1 -0
  199. package/dist/core/web/public/next/assets/RailStatus-D-t2gPae.js +2 -0
  200. package/dist/core/web/public/next/assets/RailStatus-D-t2gPae.js.map +1 -0
  201. package/dist/core/web/public/next/assets/{RefreshIndicator-CnhEovMZ.js → RefreshIndicator-BLnr9IOM.js} +2 -2
  202. package/dist/core/web/public/next/assets/{RefreshIndicator-CnhEovMZ.js.map → RefreshIndicator-BLnr9IOM.js.map} +1 -1
  203. package/dist/core/web/public/next/assets/{ResourcePoolConsoleApp-28gLwmwV.js → ResourcePoolConsoleApp-BeG0gBif.js} +4 -4
  204. package/dist/core/web/public/next/assets/{ResourcePoolConsoleApp-28gLwmwV.js.map → ResourcePoolConsoleApp-BeG0gBif.js.map} +1 -1
  205. package/dist/core/web/public/next/assets/ResourcesChrome-B3Z3O98t.css +1 -0
  206. package/dist/core/web/public/next/assets/ResourcesChrome-BzV6bkIa.js +3 -0
  207. package/dist/core/web/public/next/assets/ResourcesChrome-BzV6bkIa.js.map +1 -0
  208. package/dist/core/web/public/next/assets/ResourcesDrawer-CSKIO_wZ.css +1 -0
  209. package/dist/core/web/public/next/assets/ResourcesDrawer-o4ILHdep.js +2 -0
  210. package/dist/core/web/public/next/assets/ResourcesDrawer-o4ILHdep.js.map +1 -0
  211. package/dist/core/web/public/next/assets/{RouteErrorBoundary-AyUPCIb3.js → RouteErrorBoundary-C5SxA2Dg.js} +2 -2
  212. package/dist/core/web/public/next/assets/{RouteErrorBoundary-AyUPCIb3.js.map → RouteErrorBoundary-C5SxA2Dg.js.map} +1 -1
  213. package/dist/core/web/public/next/assets/RunInCloudAction-C3LBp7C4.js +2 -0
  214. package/dist/core/web/public/next/assets/RunInCloudAction-C3LBp7C4.js.map +1 -0
  215. package/dist/core/web/public/next/assets/SeatSelector-DpvvbjNm.js +3 -0
  216. package/dist/core/web/public/next/assets/{SeatSelector-DaUO-zoK.js.map → SeatSelector-DpvvbjNm.js.map} +1 -1
  217. package/dist/core/web/public/next/assets/{Segmented-B_8c_83S.js → Segmented-BL40udoO.js} +2 -2
  218. package/dist/core/web/public/next/assets/{Segmented-B_8c_83S.js.map → Segmented-BL40udoO.js.map} +1 -1
  219. package/dist/core/web/public/next/assets/{Select-Bl5g5Dt_.js → Select-FWLnAw_j.js} +2 -2
  220. package/dist/core/web/public/next/assets/{Select-Bl5g5Dt_.js.map → Select-FWLnAw_j.js.map} +1 -1
  221. package/dist/core/web/public/next/assets/{SessionInsightChip-w0I21q0c.js → SessionInsightChip-CWye87Ju.js} +2 -2
  222. package/dist/core/web/public/next/assets/{SessionInsightChip-w0I21q0c.js.map → SessionInsightChip-CWye87Ju.js.map} +1 -1
  223. package/dist/core/web/public/next/assets/SessionSearch-YvCHFUuN.js +2 -0
  224. package/dist/core/web/public/next/assets/{SessionSearch-B5aQ0BCM.js.map → SessionSearch-YvCHFUuN.js.map} +1 -1
  225. package/dist/core/web/public/next/assets/SettingsSection-Dr18upeE.js +2 -0
  226. package/dist/core/web/public/next/assets/SettingsSection-Dr18upeE.js.map +1 -0
  227. package/dist/core/web/public/next/assets/{Sheet-CVjk-cLI.js → Sheet-DZKcQXQg.js} +2 -2
  228. package/dist/core/web/public/next/assets/{Sheet-CVjk-cLI.js.map → Sheet-DZKcQXQg.js.map} +1 -1
  229. package/dist/core/web/public/next/assets/{ShortcutsOverlay-BiBjnBcc.js → ShortcutsOverlay-BpDimdPq.js} +2 -2
  230. package/dist/core/web/public/next/assets/{ShortcutsOverlay-BiBjnBcc.js.map → ShortcutsOverlay-BpDimdPq.js.map} +1 -1
  231. package/dist/core/web/public/next/assets/Sidebar-BRc1vGDF.css +1 -0
  232. package/dist/core/web/public/next/assets/Sidebar-BoBzBEFX.js +3 -0
  233. package/dist/core/web/public/next/assets/Sidebar-BoBzBEFX.js.map +1 -0
  234. package/dist/core/web/public/next/assets/{Slider-BS9MU5ZV.js → Slider-DUMo9HDD.js} +2 -2
  235. package/dist/core/web/public/next/assets/{Slider-BS9MU5ZV.js.map → Slider-DUMo9HDD.js.map} +1 -1
  236. package/dist/core/web/public/next/assets/{StatusBadge-DAf-ArKE.js → StatusBadge-BwnBNFQr.js} +2 -2
  237. package/dist/core/web/public/next/assets/{StatusBadge-DAf-ArKE.js.map → StatusBadge-BwnBNFQr.js.map} +1 -1
  238. package/dist/core/web/public/next/assets/StepBand-PDXMIlRk.js +2 -0
  239. package/dist/core/web/public/next/assets/StepBand-PDXMIlRk.js.map +1 -0
  240. package/dist/core/web/public/next/assets/{Surface-CiYOdNKQ.js → Surface-B3TZVoER.js} +2 -2
  241. package/dist/core/web/public/next/assets/{Surface-CiYOdNKQ.js.map → Surface-B3TZVoER.js.map} +1 -1
  242. package/dist/core/web/public/next/assets/Swimlane-DR4OgON_.js +2 -0
  243. package/dist/core/web/public/next/assets/Swimlane-DR4OgON_.js.map +1 -0
  244. package/dist/core/web/public/next/assets/{Switch-BzRXtNPt.js → Switch-CcR5Llk5.js} +2 -2
  245. package/dist/core/web/public/next/assets/{Switch-BzRXtNPt.js.map → Switch-CcR5Llk5.js.map} +1 -1
  246. package/dist/core/web/public/next/assets/{Tag-DEEbDz7T.js → Tag-_-K1h7Hk.js} +2 -2
  247. package/dist/core/web/public/next/assets/{Tag-DEEbDz7T.js.map → Tag-_-K1h7Hk.js.map} +1 -1
  248. package/dist/core/web/public/next/assets/TerminalPane-BwfMbnJz.css +1 -0
  249. package/dist/core/web/public/next/assets/TerminalPane-_1aH4ndN.js +7 -0
  250. package/dist/core/web/public/next/assets/TerminalPane-_1aH4ndN.js.map +1 -0
  251. package/dist/core/web/public/next/assets/UniverseConsoleApp-BUsq-inZ.js +2 -0
  252. package/dist/core/web/public/next/assets/{UniverseConsoleApp-DKqAf-eD.js.map → UniverseConsoleApp-BUsq-inZ.js.map} +1 -1
  253. package/dist/core/web/public/next/assets/{UniverseView-D6081LQL.js → UniverseView-Dogy_dsB.js} +2 -2
  254. package/dist/core/web/public/next/assets/{UniverseView-D6081LQL.js.map → UniverseView-Dogy_dsB.js.map} +1 -1
  255. package/dist/core/web/public/next/assets/UsageSection-DiX_dTyo.js +2 -0
  256. package/dist/core/web/public/next/assets/UsageSection-DiX_dTyo.js.map +1 -0
  257. package/dist/core/web/public/next/assets/UsageSection-DsB-Jqyl.css +1 -0
  258. package/dist/core/web/public/next/assets/VerseConsoleApp-Cxqr-3qc.css +1 -0
  259. package/dist/core/web/public/next/assets/VerseConsoleApp-WVeyJnW7.js +3 -0
  260. package/dist/core/web/public/next/assets/VerseConsoleApp-WVeyJnW7.js.map +1 -0
  261. package/dist/core/web/public/next/assets/Workspace-BYW9dm90.css +1 -0
  262. package/dist/core/web/public/next/assets/Workspace-BbxZHwQd.js +10 -0
  263. package/dist/core/web/public/next/assets/Workspace-BbxZHwQd.js.map +1 -0
  264. package/dist/core/web/public/next/assets/actions-Ddfg2iLl.css +1 -0
  265. package/dist/core/web/public/next/assets/actions-s2lfm_5k.js +2 -0
  266. package/dist/core/web/public/next/assets/actions-s2lfm_5k.js.map +1 -0
  267. package/dist/core/web/public/next/assets/apps-model-CDFvmsQV.js +2 -0
  268. package/dist/core/web/public/next/assets/apps-model-CDFvmsQV.js.map +1 -0
  269. package/dist/core/web/public/next/assets/{budget-queries-Dacv1VYP.js → budget-queries-wUshcovN.js} +2 -2
  270. package/dist/core/web/public/next/assets/{budget-queries-Dacv1VYP.js.map → budget-queries-wUshcovN.js.map} +1 -1
  271. package/dist/core/web/public/next/assets/calendar-day-BxBYHfX1.js +2 -0
  272. package/dist/core/web/public/next/assets/calendar-day-BxBYHfX1.js.map +1 -0
  273. package/dist/core/web/public/next/assets/capacity-strip-model-Bj_9ztzs.js +2 -0
  274. package/dist/core/web/public/next/assets/capacity-strip-model-Bj_9ztzs.js.map +1 -0
  275. package/dist/core/web/public/next/assets/charts-CMSgAUKn.js +2 -0
  276. package/dist/core/web/public/next/assets/charts-CMSgAUKn.js.map +1 -0
  277. package/dist/core/web/public/next/assets/cloud-C1KPNRHC.css +1 -0
  278. package/dist/core/web/public/next/assets/cloud-queries-CnV1yaNG.js +2 -0
  279. package/dist/core/web/public/next/assets/cloud-queries-CnV1yaNG.js.map +1 -0
  280. package/dist/core/web/public/next/assets/cloud.module-CiwatLj3.js +2 -0
  281. package/dist/core/web/public/next/assets/cloud.module-CiwatLj3.js.map +1 -0
  282. package/dist/core/web/public/next/assets/colors-BZ3a9wFf.js +2 -0
  283. package/dist/core/web/public/next/assets/colors-BZ3a9wFf.js.map +1 -0
  284. package/dist/core/web/public/next/assets/{command-bus-CpYuam1F.js → command-bus-DqimKCUY.js} +2 -2
  285. package/dist/core/web/public/next/assets/{command-bus-CpYuam1F.js.map → command-bus-DqimKCUY.js.map} +1 -1
  286. package/dist/core/web/public/next/assets/command-catalog-BdtDH93o.js +2 -0
  287. package/dist/core/web/public/next/assets/command-catalog-BdtDH93o.js.map +1 -0
  288. package/dist/core/web/public/next/assets/{composer-keys-CYz4U4Bg.js → composer-keys-DBRymxQn.js} +2 -2
  289. package/dist/core/web/public/next/assets/{composer-keys-CYz4U4Bg.js.map → composer-keys-DBRymxQn.js.map} +1 -1
  290. package/dist/core/web/public/next/assets/context-model-Dwd49-dp.js +2 -0
  291. package/dist/core/web/public/next/assets/context-model-Dwd49-dp.js.map +1 -0
  292. package/dist/core/web/public/next/assets/context-model-MT17V86_.js +2 -0
  293. package/dist/core/web/public/next/assets/context-model-MT17V86_.js.map +1 -0
  294. package/dist/core/web/public/next/assets/context-queries-xVKIeynP.js +2 -0
  295. package/dist/core/web/public/next/assets/context-queries-xVKIeynP.js.map +1 -0
  296. package/dist/core/web/public/next/assets/context.module-BijAfoJw.js +2 -0
  297. package/dist/core/web/public/next/assets/context.module-BijAfoJw.js.map +1 -0
  298. package/dist/core/web/public/next/assets/{control-queries-BGjarMm9.js → control-queries-DOZR-D8G.js} +2 -2
  299. package/dist/core/web/public/next/assets/{control-queries-BGjarMm9.js.map → control-queries-DOZR-D8G.js.map} +1 -1
  300. package/dist/core/web/public/next/assets/dark-since-DOMvtB_G.js +2 -0
  301. package/dist/core/web/public/next/assets/dark-since-DOMvtB_G.js.map +1 -0
  302. package/dist/core/web/public/next/assets/dock-icons-8EtARwUm.js +2 -0
  303. package/dist/core/web/public/next/assets/dock-icons-8EtARwUm.js.map +1 -0
  304. package/dist/core/web/public/next/assets/dock-panes-UKS-mXhr.js +2 -0
  305. package/dist/core/web/public/next/assets/{dock-panes-BNTLvX7G.js.map → dock-panes-UKS-mXhr.js.map} +1 -1
  306. package/dist/core/web/public/next/assets/{dock-store-_E5h6TEq.js → dock-store-BA1cHOYA.js} +2 -2
  307. package/dist/core/web/public/next/assets/{dock-store-_E5h6TEq.js.map → dock-store-BA1cHOYA.js.map} +1 -1
  308. package/dist/core/web/public/next/assets/fleet-model-CNe8Wh-s.js +2 -0
  309. package/dist/core/web/public/next/assets/fleet-model-CNe8Wh-s.js.map +1 -0
  310. package/dist/core/web/public/next/assets/fleet-queries-BSdRlUwJ.js +2 -0
  311. package/dist/core/web/public/next/assets/fleet-queries-BSdRlUwJ.js.map +1 -0
  312. package/dist/core/web/public/next/assets/format-B8DAVcn2.js +2 -0
  313. package/dist/core/web/public/next/assets/format-B8DAVcn2.js.map +1 -0
  314. package/dist/core/web/public/next/assets/format-DKrNjdwD.js +2 -0
  315. package/dist/core/web/public/next/assets/format-DKrNjdwD.js.map +1 -0
  316. package/dist/core/web/public/next/assets/{git-model-5v5xGobf.js → git-model-CivuBY_D.js} +2 -2
  317. package/dist/core/web/public/next/assets/{git-model-5v5xGobf.js.map → git-model-CivuBY_D.js.map} +1 -1
  318. package/dist/core/web/public/next/assets/global-Di2PUgj4.js +2 -0
  319. package/dist/core/web/public/next/assets/global-Di2PUgj4.js.map +1 -0
  320. package/dist/core/web/public/next/assets/{guarded-action-vOPc8v75.js → guarded-action-CvOHcqyH.js} +2 -2
  321. package/dist/core/web/public/next/assets/{guarded-action-vOPc8v75.js.map → guarded-action-CvOHcqyH.js.map} +1 -1
  322. package/dist/core/web/public/next/assets/{icons-DWb24OA6.js → icons-B_yuAgdN.js} +2 -2
  323. package/dist/core/web/public/next/assets/{icons-DWb24OA6.js.map → icons-B_yuAgdN.js.map} +1 -1
  324. package/dist/core/web/public/next/assets/{index-afDA8cwW.js → index-oAAq8XJa.js} +3 -3
  325. package/dist/core/web/public/next/assets/{index-afDA8cwW.js.map → index-oAAq8XJa.js.map} +1 -1
  326. package/dist/core/web/public/next/assets/live-model-DCw_IFRI.js +2 -0
  327. package/dist/core/web/public/next/assets/live-model-DCw_IFRI.js.map +1 -0
  328. package/dist/core/web/public/next/assets/local-model-DFyjKX0b.js +2 -0
  329. package/dist/core/web/public/next/assets/local-model-DFyjKX0b.js.map +1 -0
  330. package/dist/core/web/public/next/assets/mind-B9PzLcl0.css +1 -0
  331. package/dist/core/web/public/next/assets/mind.module-vnuJcwvD.js +2 -0
  332. package/dist/core/web/public/next/assets/mind.module-vnuJcwvD.js.map +1 -0
  333. package/dist/core/web/public/next/assets/mutations-Dpsql5t7.js +2 -0
  334. package/dist/core/web/public/next/assets/{mutations-C6E10SPX.js.map → mutations-Dpsql5t7.js.map} +1 -1
  335. package/dist/core/web/public/next/assets/{overnight-queries-CCGfiS-g.js → overnight-queries-X-44Gsw5.js} +2 -2
  336. package/dist/core/web/public/next/assets/{overnight-queries-CCGfiS-g.js.map → overnight-queries-X-44Gsw5.js.map} +1 -1
  337. package/dist/core/web/public/next/assets/pane-chrome-8JmEhHVD.css +1 -0
  338. package/dist/core/web/public/next/assets/pane-chrome.module-D7o-fVd0.js +2 -0
  339. package/dist/core/web/public/next/assets/pane-chrome.module-D7o-fVd0.js.map +1 -0
  340. package/dist/core/web/public/next/assets/primitives-BDIcUvob.js +1 -0
  341. package/dist/core/web/public/next/assets/{queries-BuYIEHst.js → queries-BA4rNGD-.js} +2 -2
  342. package/dist/core/web/public/next/assets/{queries-BuYIEHst.js.map → queries-BA4rNGD-.js.map} +1 -1
  343. package/dist/core/web/public/next/assets/{reasoning-pref-BVzGczV7.js → reasoning-pref-B9-DJUXP.js} +2 -2
  344. package/dist/core/web/public/next/assets/{reasoning-pref-BVzGczV7.js.map → reasoning-pref-B9-DJUXP.js.map} +1 -1
  345. package/dist/core/web/public/next/assets/seat-subscription-CH6fW4fJ.js +2 -0
  346. package/dist/core/web/public/next/assets/seat-subscription-CH6fW4fJ.js.map +1 -0
  347. package/dist/core/web/public/next/assets/{section-visibility-CSrsTcwK.js → section-visibility-qFqc_d4Z.js} +2 -2
  348. package/dist/core/web/public/next/assets/{section-visibility-CSrsTcwK.js.map → section-visibility-qFqc_d4Z.js.map} +1 -1
  349. package/dist/core/web/public/next/assets/{sidebar-model-C8fyqSQY.js → sidebar-model-M1GaQU5l.js} +2 -2
  350. package/dist/core/web/public/next/assets/{sidebar-model-C8fyqSQY.js.map → sidebar-model-M1GaQU5l.js.map} +1 -1
  351. package/dist/core/web/public/next/assets/slots-Ds9ZIqUL.js +3 -0
  352. package/dist/core/web/public/next/assets/{slots-W8gkmdfE.js.map → slots-Ds9ZIqUL.js.map} +1 -1
  353. package/dist/core/web/public/next/assets/surface-data-J52iIGMD.js +2 -0
  354. package/dist/core/web/public/next/assets/surface-data-J52iIGMD.js.map +1 -0
  355. package/dist/core/web/public/next/assets/surface-prefetch-CgZ-LEJK.js +2 -0
  356. package/dist/core/web/public/next/assets/surface-prefetch-CgZ-LEJK.js.map +1 -0
  357. package/dist/core/web/public/next/assets/tasks-model-ent8f0jZ.js +2 -0
  358. package/dist/core/web/public/next/assets/{tasks-model-CnYQzgxk.js.map → tasks-model-ent8f0jZ.js.map} +1 -1
  359. package/dist/core/web/public/next/assets/{terminal-icons-CxUYaWX9.js → terminal-icons-DJTK7QpR.js} +2 -2
  360. package/dist/core/web/public/next/assets/{terminal-icons-CxUYaWX9.js.map → terminal-icons-DJTK7QpR.js.map} +1 -1
  361. package/dist/core/web/public/next/assets/{tool-semantics-CTRuLF5j.js → tool-semantics-GX8ScuSH.js} +2 -2
  362. package/dist/core/web/public/next/assets/{tool-semantics-CTRuLF5j.js.map → tool-semantics-GX8ScuSH.js.map} +1 -1
  363. package/dist/core/web/public/next/assets/{turn-files-BvB5LLNw.js → turn-files-BPHQzYuH.js} +2 -2
  364. package/dist/core/web/public/next/assets/{turn-files-BvB5LLNw.js.map → turn-files-BPHQzYuH.js.map} +1 -1
  365. package/dist/core/web/public/next/assets/types-D5XOdyw8.js +2 -0
  366. package/dist/core/web/public/next/assets/types-D5XOdyw8.js.map +1 -0
  367. package/dist/core/web/public/next/assets/{usage-queries-CQOpeE1H.js → usage-queries-Bn8ccqyN.js} +2 -2
  368. package/dist/core/web/public/next/assets/{usage-queries-CQOpeE1H.js.map → usage-queries-Bn8ccqyN.js.map} +1 -1
  369. package/dist/core/web/public/next/assets/use-guarded-action-C2HlSzkz.js +2 -0
  370. package/dist/core/web/public/next/assets/use-guarded-action-C2HlSzkz.js.map +1 -0
  371. package/dist/core/web/public/next/assets/{use-ticker-hryPXnyp.js → use-ticker-BNc1H4ZC.js} +2 -2
  372. package/dist/core/web/public/next/assets/{use-ticker-hryPXnyp.js.map → use-ticker-BNc1H4ZC.js.map} +1 -1
  373. package/dist/core/web/public/next/assets/use-token-gate-B3IJL6bf.js +2 -0
  374. package/dist/core/web/public/next/assets/use-token-gate-B3IJL6bf.js.map +1 -0
  375. package/dist/core/web/public/next/assets/{useActivity-Cg_9-7nt.js → useActivity-Bk3XgXjL.js} +2 -2
  376. package/dist/core/web/public/next/assets/{useActivity-Cg_9-7nt.js.map → useActivity-Bk3XgXjL.js.map} +1 -1
  377. package/dist/core/web/public/next/assets/useChartWidth-BAtVgn2n.css +1 -0
  378. package/dist/core/web/public/next/assets/useChartWidth-lZ9PrQn0.js +2 -0
  379. package/dist/core/web/public/next/assets/useChartWidth-lZ9PrQn0.js.map +1 -0
  380. package/dist/core/web/public/next/assets/{useSeatsRefresh-4Ov9eT1F.js → useSeatsRefresh-CG4jczeL.js} +2 -2
  381. package/dist/core/web/public/next/assets/{useSeatsRefresh-4Ov9eT1F.js.map → useSeatsRefresh-CG4jczeL.js.map} +1 -1
  382. package/dist/core/web/public/next/assets/verse-model-D7NZQFAR.js +2 -0
  383. package/dist/core/web/public/next/assets/verse-model-D7NZQFAR.js.map +1 -0
  384. package/dist/core/web/public/next/assets/{verse-queries-BjQoOTwv.js → verse-queries-DvIJcn6Z.js} +2 -2
  385. package/dist/core/web/public/next/assets/{verse-queries-BjQoOTwv.js.map → verse-queries-DvIJcn6Z.js.map} +1 -1
  386. package/dist/core/web/public/next/assets/verse-store-DjBWj04q.js +3 -0
  387. package/dist/core/web/public/next/assets/verse-store-DjBWj04q.js.map +1 -0
  388. package/dist/core/web/public/next/assets/verse-ui-store-zafyzXKD.js +3 -0
  389. package/dist/core/web/public/next/assets/{verse-ui-store-KTTKfv-T.js.map → verse-ui-store-zafyzXKD.js.map} +1 -1
  390. package/dist/core/web/public/next/assets/{viewport-ZB86jdES.js → viewport-BEqGUoTA.js} +2 -2
  391. package/dist/core/web/public/next/assets/{viewport-ZB86jdES.js.map → viewport-BEqGUoTA.js.map} +1 -1
  392. package/dist/core/web/public/next/assets/warmup-BR6pxAKs.js +3 -0
  393. package/dist/core/web/public/next/assets/warmup-BR6pxAKs.js.map +1 -0
  394. package/dist/core/web/public/next/assets/{workspace-model-4hq_Mv3N.js → workspace-model-D_tWD5Wt.js} +2 -2
  395. package/dist/core/web/public/next/assets/{workspace-model-4hq_Mv3N.js.map → workspace-model-D_tWD5Wt.js.map} +1 -1
  396. package/dist/core/web/public/next/index.html +1 -1
  397. package/dist/release-dependency-inventory.json +1 -1
  398. package/package.json +1 -1
  399. package/dist/core/web/public/next/assets/Advanced-CHjxJt2z.css +0 -1
  400. package/dist/core/web/public/next/assets/Advanced-DM0DYibH.js +0 -2
  401. package/dist/core/web/public/next/assets/Advanced-DM0DYibH.js.map +0 -1
  402. package/dist/core/web/public/next/assets/AppsSection-CXxbfPJQ.js +0 -2
  403. package/dist/core/web/public/next/assets/AppsSection-CXxbfPJQ.js.map +0 -1
  404. package/dist/core/web/public/next/assets/AreaTrend-gUVXkfhf.js +0 -2
  405. package/dist/core/web/public/next/assets/AreaTrend-gUVXkfhf.js.map +0 -1
  406. package/dist/core/web/public/next/assets/AutonomySection-CoMngwNB.js +0 -2
  407. package/dist/core/web/public/next/assets/BranchBar-C-NovaXr.js +0 -2
  408. package/dist/core/web/public/next/assets/BranchBar-C-NovaXr.js.map +0 -1
  409. package/dist/core/web/public/next/assets/BranchBar-C9BpPVLr.css +0 -1
  410. package/dist/core/web/public/next/assets/BudgetControl-P5lMxHvQ.js +0 -2
  411. package/dist/core/web/public/next/assets/BudgetControl-P5lMxHvQ.js.map +0 -1
  412. package/dist/core/web/public/next/assets/BurnDown-4P1LDoCL.js +0 -2
  413. package/dist/core/web/public/next/assets/BurnDown-4P1LDoCL.js.map +0 -1
  414. package/dist/core/web/public/next/assets/CapacityStrip-D6Yyg4a1.js +0 -2
  415. package/dist/core/web/public/next/assets/CapacityStrip-D6Yyg4a1.js.map +0 -1
  416. package/dist/core/web/public/next/assets/CapacityStrip-wgFP9MUA.css +0 -1
  417. package/dist/core/web/public/next/assets/ChatSection-B9cdRKUh.js +0 -3
  418. package/dist/core/web/public/next/assets/CommandSection-BC0uXim_.js +0 -2
  419. package/dist/core/web/public/next/assets/CommandSection-BC0uXim_.js.map +0 -1
  420. package/dist/core/web/public/next/assets/Composer-CkcwbQhG.css +0 -1
  421. package/dist/core/web/public/next/assets/Composer.module-DJMdrqNt.js +0 -2
  422. package/dist/core/web/public/next/assets/DiffPane-5uLKa0au.js +0 -2
  423. package/dist/core/web/public/next/assets/DiffPane-5uLKa0au.js.map +0 -1
  424. package/dist/core/web/public/next/assets/DiffPane-Csboxnn0.css +0 -1
  425. package/dist/core/web/public/next/assets/DockHost-BGnTgdIb.css +0 -1
  426. package/dist/core/web/public/next/assets/DockHost-CBV_6Ehi.js +0 -2
  427. package/dist/core/web/public/next/assets/DockHost-CBV_6Ehi.js.map +0 -1
  428. package/dist/core/web/public/next/assets/FleetSection-DuJcQCGg.js +0 -3
  429. package/dist/core/web/public/next/assets/FleetSection-DuJcQCGg.js.map +0 -1
  430. package/dist/core/web/public/next/assets/FleetSection-w9AjqfTR.css +0 -1
  431. package/dist/core/web/public/next/assets/Funnel-qX3Hlbce.js +0 -2
  432. package/dist/core/web/public/next/assets/Funnel-qX3Hlbce.js.map +0 -1
  433. package/dist/core/web/public/next/assets/GearTray-kVGP1coG.js +0 -2
  434. package/dist/core/web/public/next/assets/GearTray-kVGP1coG.js.map +0 -1
  435. package/dist/core/web/public/next/assets/GrowthSection-CYxJ9MH5.js +0 -2
  436. package/dist/core/web/public/next/assets/GrowthSection-CYxJ9MH5.js.map +0 -1
  437. package/dist/core/web/public/next/assets/HandoffDialog-DHZo3Ev0.js +0 -2
  438. package/dist/core/web/public/next/assets/HandoffDialog-DHZo3Ev0.js.map +0 -1
  439. package/dist/core/web/public/next/assets/MatrixHeatmap-B_JWCjZx.js +0 -2
  440. package/dist/core/web/public/next/assets/MatrixHeatmap-B_JWCjZx.js.map +0 -1
  441. package/dist/core/web/public/next/assets/McpSection-1UncWBpW.js +0 -2
  442. package/dist/core/web/public/next/assets/MessageMarkdown-C4pl9LI5.js +0 -3
  443. package/dist/core/web/public/next/assets/MessageMarkdown-Czcl3L_Q.css +0 -1
  444. package/dist/core/web/public/next/assets/MindSection-C3fCw_fD.js +0 -2
  445. package/dist/core/web/public/next/assets/MindSection-C3fCw_fD.js.map +0 -1
  446. package/dist/core/web/public/next/assets/MutationTokenDialog-Dn0tzCrh.js +0 -2
  447. package/dist/core/web/public/next/assets/MutationTokenDialog-Dn0tzCrh.js.map +0 -1
  448. package/dist/core/web/public/next/assets/NeedsYouDrawer-CuNYJCJ0.js +0 -2
  449. package/dist/core/web/public/next/assets/NeedsYouDrawer-CuNYJCJ0.js.map +0 -1
  450. package/dist/core/web/public/next/assets/NeedsYouDrawer-SkhvvdLb.css +0 -1
  451. package/dist/core/web/public/next/assets/NewChatDialog-B_BsS9pr.js +0 -3
  452. package/dist/core/web/public/next/assets/OnboardingFlow-CtCPpgoX.js +0 -2
  453. package/dist/core/web/public/next/assets/PreviewPane-Cx6RRwzM.js +0 -2
  454. package/dist/core/web/public/next/assets/PreviewPane-Cx6RRwzM.js.map +0 -1
  455. package/dist/core/web/public/next/assets/PreviewPane-WQJFjSXe.css +0 -1
  456. package/dist/core/web/public/next/assets/RailStatus-BWs6xevj.js +0 -2
  457. package/dist/core/web/public/next/assets/RailStatus-BWs6xevj.js.map +0 -1
  458. package/dist/core/web/public/next/assets/SeatSelector-DaUO-zoK.js +0 -3
  459. package/dist/core/web/public/next/assets/SessionSearch-B5aQ0BCM.js +0 -2
  460. package/dist/core/web/public/next/assets/SettingsSection-CuESA30a.js +0 -2
  461. package/dist/core/web/public/next/assets/SettingsSection-CuESA30a.js.map +0 -1
  462. package/dist/core/web/public/next/assets/Sidebar-DfD8MNZt.css +0 -1
  463. package/dist/core/web/public/next/assets/Sidebar-q11dtYZf.js +0 -3
  464. package/dist/core/web/public/next/assets/Sidebar-q11dtYZf.js.map +0 -1
  465. package/dist/core/web/public/next/assets/StepBand-B1W7rU70.js +0 -2
  466. package/dist/core/web/public/next/assets/StepBand-B1W7rU70.js.map +0 -1
  467. package/dist/core/web/public/next/assets/Swimlane-BR40WVcj.js +0 -2
  468. package/dist/core/web/public/next/assets/Swimlane-BR40WVcj.js.map +0 -1
  469. package/dist/core/web/public/next/assets/TerminalPane-CPKUTD9K.js +0 -7
  470. package/dist/core/web/public/next/assets/TerminalPane-CPKUTD9K.js.map +0 -1
  471. package/dist/core/web/public/next/assets/TerminalPane-CmE2QL-Q.css +0 -1
  472. package/dist/core/web/public/next/assets/UniverseConsoleApp-DKqAf-eD.js +0 -2
  473. package/dist/core/web/public/next/assets/UsageSection-B6fR3cru.js +0 -2
  474. package/dist/core/web/public/next/assets/UsageSection-B6fR3cru.js.map +0 -1
  475. package/dist/core/web/public/next/assets/UsageSection-DwgNOYvi.css +0 -1
  476. package/dist/core/web/public/next/assets/VerseConsoleApp-C0V221WL.css +0 -1
  477. package/dist/core/web/public/next/assets/VerseConsoleApp-bjARLPwN.js +0 -3
  478. package/dist/core/web/public/next/assets/VerseConsoleApp-bjARLPwN.js.map +0 -1
  479. package/dist/core/web/public/next/assets/Workspace-DQXMVDf7.css +0 -1
  480. package/dist/core/web/public/next/assets/Workspace-DtJb5tiM.js +0 -10
  481. package/dist/core/web/public/next/assets/Workspace-DtJb5tiM.js.map +0 -1
  482. package/dist/core/web/public/next/assets/actions-Bszsdpms.js +0 -2
  483. package/dist/core/web/public/next/assets/actions-Bszsdpms.js.map +0 -1
  484. package/dist/core/web/public/next/assets/actions-Dug8YIf0.css +0 -1
  485. package/dist/core/web/public/next/assets/capacity-strip-model-BR539Ci8.js +0 -2
  486. package/dist/core/web/public/next/assets/capacity-strip-model-BR539Ci8.js.map +0 -1
  487. package/dist/core/web/public/next/assets/charts-D4NaLaXA.js +0 -2
  488. package/dist/core/web/public/next/assets/charts-D4NaLaXA.js.map +0 -1
  489. package/dist/core/web/public/next/assets/colors-B-vHsX1S.js +0 -2
  490. package/dist/core/web/public/next/assets/colors-B-vHsX1S.js.map +0 -1
  491. package/dist/core/web/public/next/assets/command-catalog-s3W6Z96D.js +0 -2
  492. package/dist/core/web/public/next/assets/command-catalog-s3W6Z96D.js.map +0 -1
  493. package/dist/core/web/public/next/assets/context-model-Bto3LZn2.js +0 -2
  494. package/dist/core/web/public/next/assets/context-model-Bto3LZn2.js.map +0 -1
  495. package/dist/core/web/public/next/assets/context-queries-DVdSLrYy.js +0 -2
  496. package/dist/core/web/public/next/assets/context-queries-DVdSLrYy.js.map +0 -1
  497. package/dist/core/web/public/next/assets/context.module-B_k02HNU.js +0 -2
  498. package/dist/core/web/public/next/assets/context.module-B_k02HNU.js.map +0 -1
  499. package/dist/core/web/public/next/assets/dock-icons-oG8d7mNZ.js +0 -2
  500. package/dist/core/web/public/next/assets/dock-icons-oG8d7mNZ.js.map +0 -1
  501. package/dist/core/web/public/next/assets/dock-panes-BNTLvX7G.js +0 -2
  502. package/dist/core/web/public/next/assets/fleet-model-ClBbQ0Uj.js +0 -2
  503. package/dist/core/web/public/next/assets/fleet-model-ClBbQ0Uj.js.map +0 -1
  504. package/dist/core/web/public/next/assets/format-BNYWGJat.js +0 -2
  505. package/dist/core/web/public/next/assets/format-BNYWGJat.js.map +0 -1
  506. package/dist/core/web/public/next/assets/global-DVgMguLr.js +0 -2
  507. package/dist/core/web/public/next/assets/global-DVgMguLr.js.map +0 -1
  508. package/dist/core/web/public/next/assets/live-model-Dm6ITHvX.js +0 -2
  509. package/dist/core/web/public/next/assets/live-model-Dm6ITHvX.js.map +0 -1
  510. package/dist/core/web/public/next/assets/mind-B-lYfSUJ.css +0 -1
  511. package/dist/core/web/public/next/assets/mind.module-BzhAlg3e.js +0 -2
  512. package/dist/core/web/public/next/assets/mind.module-BzhAlg3e.js.map +0 -1
  513. package/dist/core/web/public/next/assets/mutations-C6E10SPX.js +0 -2
  514. package/dist/core/web/public/next/assets/primitives-DQvYikjm.js +0 -1
  515. package/dist/core/web/public/next/assets/seat-subscription-CrWOV4Qc.js +0 -2
  516. package/dist/core/web/public/next/assets/seat-subscription-CrWOV4Qc.js.map +0 -1
  517. package/dist/core/web/public/next/assets/slots-W8gkmdfE.js +0 -3
  518. package/dist/core/web/public/next/assets/surface-data-ZtCegYMQ.js +0 -2
  519. package/dist/core/web/public/next/assets/surface-data-ZtCegYMQ.js.map +0 -1
  520. package/dist/core/web/public/next/assets/tasks-model-CnYQzgxk.js +0 -2
  521. package/dist/core/web/public/next/assets/types-Dypu22dp.js +0 -3
  522. package/dist/core/web/public/next/assets/types-Dypu22dp.js.map +0 -1
  523. package/dist/core/web/public/next/assets/use-guarded-action-CO_aAsed.js +0 -2
  524. package/dist/core/web/public/next/assets/use-guarded-action-CO_aAsed.js.map +0 -1
  525. package/dist/core/web/public/next/assets/use-token-gate-DYA2-ALC.js +0 -2
  526. package/dist/core/web/public/next/assets/use-token-gate-DYA2-ALC.js.map +0 -1
  527. package/dist/core/web/public/next/assets/useChartWidth-B8E5mJgM.css +0 -1
  528. package/dist/core/web/public/next/assets/useChartWidth-MEXvDxDL.js +0 -2
  529. package/dist/core/web/public/next/assets/useChartWidth-MEXvDxDL.js.map +0 -1
  530. package/dist/core/web/public/next/assets/verse-model-E98kXngO.js +0 -2
  531. package/dist/core/web/public/next/assets/verse-model-E98kXngO.js.map +0 -1
  532. package/dist/core/web/public/next/assets/verse-store-BgKx_YGs.js +0 -2
  533. package/dist/core/web/public/next/assets/verse-store-BgKx_YGs.js.map +0 -1
  534. package/dist/core/web/public/next/assets/verse-ui-store-KTTKfv-T.js +0 -3
@@ -1 +1 @@
1
- {"version":3,"file":"OnboardingFlow-CtCPpgoX.js","names":[],"sources":["../../../../../../src/web-ui/routes/verse/onboarding/onboarding-model.ts","../../../../../../src/web-ui/routes/verse/onboarding/onboarding.module.css","../../../../../../src/web-ui/routes/verse/onboarding/OnboardingFlow.tsx"],"sourcesContent":["/**\n * routes/verse/onboarding/onboarding-model.ts — the first-run tour's facts,\n * derived from the same reads the Usage section uses, with the same honesty\n * rules (docs/VERSE-TELEMETRY-V2.md).\n *\n * Pure: no React, no I/O. Everything the tour asserts about the machine is\n * computed here so it can be tested without a DOM, and so the one rule that\n * matters is enforced in one place:\n *\n * AN ABSENT READ IS \"UNKNOWN\", NEVER \"FINE\" AND NEVER \"BROKEN\".\n *\n * A first-run screen is exactly where a confident lie does the most damage —\n * it is the operator's first and only calibration of how much this app's\n * claims can be trusted. So a route that 404s, a payload that does not\n * narrow, and a probe that could not reach a runtime each produce their own\n * sentence, and none of them produces a green check.\n *\n * The tour NEVER renders a command it invented: the seats step shows only\n * A2's own fix argv (through C6's capacity rows).\n */\nimport type { LocalModelsSnapshot } from '../usage/usage-contract.js';\n\n// ---------------------------------------------------------------------------\n// Steps\n// ---------------------------------------------------------------------------\n\nexport type OnboardingStepId = 'welcome' | 'accounts' | 'local' | 'stops' | 'finish';\n\nexport interface OnboardingStepMeta {\n id: OnboardingStepId;\n /** Shown as the card's heading. */\n title: string;\n /** One line under the heading. */\n subtitle: string;\n}\n\nexport const ONBOARDING_STEPS: readonly OnboardingStepMeta[] = [\n {\n id: 'welcome',\n title: 'Welcome to Verse',\n subtitle: 'Five sections, one rail. Two minutes and you will know what each one does.',\n },\n {\n id: 'accounts',\n title: 'Your seats',\n subtitle: 'Which provider accounts this machine can actually dispatch to right now.',\n },\n {\n id: 'local',\n title: 'Local runtime',\n subtitle: 'Whether there is a model on this machine, and what that changes.',\n },\n {\n id: 'stops',\n title: 'Three ways to stop',\n subtitle: 'They do not have the same blast radius. This is the one screen that says so.',\n },\n {\n id: 'finish',\n title: 'Make it yours',\n subtitle: 'Theme, accent, density and font live in Settings. Then start a chat.',\n },\n];\n\nexport function clampStep(step: number): number {\n if (!Number.isFinite(step)) return 0;\n return Math.min(ONBOARDING_STEPS.length - 1, Math.max(0, Math.trunc(step)));\n}\n\n// ---------------------------------------------------------------------------\n// Tone\n// ---------------------------------------------------------------------------\n\n/**\n * Step 2 (seats) is C6's shared LiveCapacityStrip since 3.10 — the tour no\n * longer narrows the accounts route itself, so the seats can never read\n * differently here than in Apps & Accounts. The tone below serves the local\n * runtime and the stops.\n */\nexport type FindingTone = 'ok' | 'attention' | 'unknown';\n\n// ---------------------------------------------------------------------------\n// Local runtime\n// ---------------------------------------------------------------------------\n\nexport interface LocalFinding {\n tone: FindingTone;\n state: string;\n summary: string;\n /** What having (or not having) a local runtime means for the operator. */\n meaning: string;\n /** Present only when there is something to do about it. */\n fix: string | null;\n modelCount: number;\n toolCapableCount: number;\n /** True when this reading was retained from an earlier probe. */\n stale: boolean;\n}\n\nexport interface LocalInput {\n snapshot: LocalModelsSnapshot | null;\n loading: boolean;\n unavailableReason: string | null;\n}\n\nconst LOCAL_MEANING_AVAILABLE =\n 'Local seats cost nothing and consume no provider quota, so the autonomous loop can keep working after a cloud window is used up.';\nconst LOCAL_MEANING_ABSENT =\n 'Without one, every turn and every autonomous tick spends a provider account, and a used-up window stops the work.';\n\nexport function buildLocalFinding(input: LocalInput): LocalFinding {\n if (input.loading) {\n return {\n tone: 'unknown',\n state: 'checking',\n summary: 'Probing the local runtimes on this machine…',\n meaning: LOCAL_MEANING_AVAILABLE,\n fix: null,\n modelCount: 0,\n toolCapableCount: 0,\n stale: false,\n };\n }\n\n if (!input.snapshot) {\n return {\n tone: 'unknown',\n state: 'not reported',\n summary: 'This server does not report local runtimes, so Verse cannot say whether one is available here.',\n meaning: LOCAL_MEANING_ABSENT,\n fix: input.unavailableReason,\n modelCount: 0,\n toolCapableCount: 0,\n stale: false,\n };\n }\n\n const models = input.snapshot.models;\n const toolCapable = models.filter((m) => m.supportsTools === true).length;\n const stale = input.snapshot.runtimes.some((r) => r.stale);\n\n if (!input.snapshot.reachable) {\n return {\n tone: 'attention',\n state: 'unreachable',\n // \"Not reachable\" and \"not installed\" are different facts and the probe\n // cannot tell them apart — so this does not claim either one.\n summary:\n 'No local runtime answered. Verse cannot tell whether one is not running or not installed — the probe only knows it got no answer.',\n meaning: LOCAL_MEANING_ABSENT,\n fix: 'Start Ollama (or LM Studio) and press Refresh in Usage. If neither is installed, everything still works — it all runs on the cloud seats.',\n modelCount: 0,\n toolCapableCount: 0,\n stale,\n };\n }\n\n if (models.length === 0) {\n return {\n tone: 'attention',\n state: 'no models',\n summary: 'A local runtime answered, but it has no models installed.',\n meaning: LOCAL_MEANING_ABSENT,\n fix: 'Pull a model into the runtime, then press Refresh in Usage.',\n modelCount: 0,\n toolCapableCount: 0,\n stale,\n };\n }\n\n return {\n tone: 'ok',\n state: stale ? 'available (retained reading)' : 'available',\n summary:\n `${models.length} local ${models.length === 1 ? 'model' : 'models'} available` +\n (toolCapable > 0 ? `, ${toolCapable} of them tool-capable.` : ', none of them tool-capable.') +\n (stale ? ' This is a retained reading, not a fresh probe.' : ''),\n meaning: toolCapable > 0\n ? LOCAL_MEANING_AVAILABLE\n : `${LOCAL_MEANING_AVAILABLE} A model that cannot call tools can answer, but cannot run an agentic turn.`,\n fix: null,\n modelCount: models.length,\n toolCapableCount: toolCapable,\n stale,\n };\n}\n\n// ---------------------------------------------------------------------------\n// The three stops\n// ---------------------------------------------------------------------------\n\nexport interface StopControl {\n name: string;\n /** What it halts. */\n scope: string;\n /** What it does NOT halt — the half people get wrong. */\n limit: string;\n reversible: string;\n tone: FindingTone;\n}\n\n/**\n * Verbatim against docs/VERSE-CONTRACT-V2.md's two footguns and the V2.1\n * amendment. The kill switch is never called a pause, and \"Stop loop\" is\n * stated as engaging the same global sentinel as the emergency control,\n * because it does (`stopDaemon()` is `setKill(true)`).\n */\nexport const STOP_CONTROLS: readonly StopControl[] = [\n {\n name: 'Pause',\n scope: 'Halts autonomous dispatch only. A running loop parks instead of exiting.',\n limit: 'Your own chats and the agent’s write tools keep working.',\n reversible: 'Reversible in one click, with no restart and no confirmation.',\n tone: 'ok',\n },\n {\n name: 'Stop loop',\n scope: 'Stops the daemon — and engages the GLOBAL kill switch while doing it.',\n limit: 'That means it also refuses the agent’s own write tools, exactly like the emergency control.',\n reversible: 'Reversible, but confirm-guarded. For an ordinary halt, use Pause.',\n tone: 'attention',\n },\n {\n name: 'Emergency stop',\n scope: 'Engages the global kill switch (~/.ashlr/KILL) directly.',\n limit: 'Every mutating path refuses: the loop, dispatch, and the agent’s own write tools.',\n reversible: 'Reversible, confirm-guarded, and deliberately separated from the other two.',\n tone: 'attention',\n },\n];\n","/* First-run tour — a docked card, not a dialog. No backdrop: the app behind\n it stays visible and clickable, which is the whole design constraint.\n Hairlines and one elevation (DESIGN-V2 §1/§2); the only colour is the\n status tone on a glyph, never on body text. */\n\n/* Docked bottom-LEFT of the content area, not bottom-right of the viewport.\n The composer is centred on --measure-read inside the workspace and its\n control row — seat pill, mic, Send/Stop — sits at the bottom of that column,\n right-aligned. A 420px card pinned to the viewport's bottom-right lands on\n top of exactly those controls at ordinary window widths, which breaks this\n file's own rule 1: everything behind the card stays clickable. Clearing the\n rail and hugging the left edge keeps it out of the composer's way in both\n the wide and the 900px layouts. */\n.card {\n position: fixed;\n z-index: var(--z-dialog);\n left: calc(var(--rail-width) + var(--space-5));\n right: auto;\n bottom: calc(var(--space-5) + env(safe-area-inset-bottom, 0px));\n width: min(420px, calc(100vw - var(--rail-width) - var(--space-5) * 2));\n max-height: min(640px, calc(100vh - var(--space-8)));\n display: flex;\n flex-direction: column;\n overflow: hidden;\n background: var(--bg-surface-raised);\n border: 1px solid var(--border-default);\n border-radius: var(--radius-lg);\n box-shadow: var(--shadow-dialog);\n}\n\n/* One declaration, correct in all four motion states. `--duration-base`\n already collapses to 1ms under BOTH triggers the app honours — the OS\n preference (unless Settings asked for full motion) and Settings' own\n `data-motion=\"reduce\"` — so a bare `prefers-reduced-motion` media query was\n wrong in two of them: it ignored an operator who chose Reduce in Settings,\n and it removed the animation from one who chose Full against an OS reduce\n preference. This is a one-shot animation, so unlike the persistent\n `.dictationPulse`/`.caret` cases it needs no by-name rules. */\n.card {\n animation: onboarding-in var(--duration-base) var(--ease-decelerate);\n}\n\n@keyframes onboarding-in {\n from {\n opacity: 0;\n transform: translateY(4px);\n }\n to {\n opacity: 1;\n transform: none;\n }\n}\n\n/* ------------------------------------------------------------------ head */\n\n.head {\n display: flex;\n align-items: flex-start;\n gap: var(--space-2);\n padding: var(--space-4) var(--space-4) var(--space-3);\n border-bottom: 1px solid var(--border-subtle);\n}\n\n.headText {\n flex: 1;\n min-width: 0;\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n.eyebrow {\n font-family: var(--font-display);\n font-size: var(--text-2xs-size);\n letter-spacing: var(--tracking-label);\n text-transform: uppercase;\n color: var(--text-tertiary);\n}\n\n.title {\n font-family: var(--font-display);\n font-size: var(--text-md-size);\n font-weight: var(--font-weight-semibold);\n letter-spacing: var(--tracking-display);\n color: var(--text-primary);\n}\n\n.subtitle {\n font-size: var(--text-xs-size);\n line-height: var(--text-xs-line-relaxed);\n color: var(--text-secondary);\n}\n\n/* ------------------------------------------------------------------ body */\n\n.body {\n flex: 1;\n min-height: 0;\n overflow-y: auto;\n padding: var(--space-4);\n display: flex;\n flex-direction: column;\n gap: var(--space-3);\n align-items: flex-start;\n}\n\n.lead {\n font-size: var(--text-sm-size);\n line-height: var(--text-sm-line-relaxed);\n color: var(--text-primary);\n}\n\n.aside,\n.caveat {\n font-size: var(--text-xs-size);\n line-height: var(--text-xs-line-relaxed);\n color: var(--text-tertiary);\n}\n\n.caveat {\n border-left: 2px solid var(--border-strong);\n padding-left: var(--space-3);\n}\n\n.kbd {\n font-family: var(--font-mono);\n font-size: var(--text-2xs-size);\n padding: 1px 5px;\n border: 1px solid var(--border-default);\n border-radius: var(--radius-xs);\n background: var(--bg-surface);\n color: var(--text-secondary);\n white-space: nowrap;\n}\n\n/* --------------------------------------------------------- rail overview */\n\n.sections,\n.findings {\n list-style: none;\n margin: 0;\n padding: 0;\n width: 100%;\n display: flex;\n flex-direction: column;\n}\n\n.sectionRow {\n display: flex;\n align-items: flex-start;\n gap: var(--space-3);\n padding: var(--space-2) 0;\n border-top: 1px solid var(--border-subtle);\n}\n\n.sectionRow:first-child {\n border-top: none;\n}\n\n.sectionIcon,\n.localIcon {\n flex: none;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n /* Derived from the density scale rather than a literal, so compact density\n actually reaches it (design/control-density.test.ts). */\n width: var(--control-h-xs);\n height: var(--control-h-xs);\n color: var(--text-tertiary);\n}\n\n.sectionText {\n display: flex;\n flex-direction: column;\n gap: 2px;\n min-width: 0;\n}\n\n.sectionName {\n font-family: var(--font-display);\n font-size: var(--text-xs-size);\n font-weight: var(--font-weight-semibold);\n color: var(--text-primary);\n display: inline-flex;\n align-items: center;\n gap: var(--space-2);\n}\n\n.sectionBlurb {\n font-size: var(--text-xs-size);\n line-height: var(--text-xs-line-relaxed);\n color: var(--text-secondary);\n}\n\n/* ----------------------------------------------------------- findings */\n\n.finding {\n display: flex;\n flex-direction: column;\n gap: var(--space-1);\n padding: var(--space-3) 0;\n border-top: 1px solid var(--border-subtle);\n}\n\n.finding:first-child {\n border-top: none;\n}\n\n.findingHead {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--space-2);\n flex-wrap: wrap;\n}\n\n.stopName {\n font-family: var(--font-display);\n font-size: var(--text-sm-size);\n font-weight: var(--font-weight-semibold);\n color: var(--text-primary);\n}\n\n.findingDetail {\n font-size: var(--text-xs-size);\n line-height: var(--text-xs-line-relaxed);\n color: var(--text-secondary);\n}\n\n.findingNote {\n font-size: var(--text-xs-size);\n line-height: var(--text-xs-line-relaxed);\n color: var(--text-tertiary);\n}\n\n.findingFix {\n display: flex;\n align-items: baseline;\n gap: var(--space-2);\n flex-wrap: wrap;\n margin-top: 2px;\n}\n\n.fixLabel {\n font-family: var(--font-display);\n font-size: var(--text-2xs-size);\n letter-spacing: var(--tracking-label);\n text-transform: uppercase;\n color: var(--text-tertiary);\n flex: none;\n}\n\n.fixText {\n font-size: var(--text-xs-size);\n line-height: var(--text-xs-line-relaxed);\n color: var(--text-secondary);\n}\n\n.code {\n font-family: var(--font-mono);\n /* A command an operator is meant to READ and retype, not a micro-label:\n tokens.css reserves --text-2xs for uppercase labels and keyboard hints\n and sets the body floor at 12px. */\n font-size: var(--text-xs-size);\n padding: 2px 6px;\n border: 1px solid var(--border-subtle);\n border-radius: var(--radius-xs);\n background: var(--bg-code, var(--bg-surface));\n color: var(--text-primary);\n overflow-wrap: anywhere;\n}\n\n/* --------------------------------------------------------------- tone */\n\n.tone {\n display: inline-flex;\n align-items: center;\n gap: 5px;\n flex: none;\n}\n\n.toneLabel {\n font-family: var(--font-display);\n font-size: var(--text-2xs-size);\n letter-spacing: var(--tracking-label);\n text-transform: uppercase;\n color: var(--text-secondary);\n}\n\n.tone[data-tone='ok'] {\n color: var(--status-success-fg, var(--text-secondary));\n}\n\n.tone[data-tone='attention'] {\n color: var(--status-warning-fg, var(--text-secondary));\n}\n\n.tone[data-tone='unknown'] {\n color: var(--text-tertiary);\n}\n\n/* ------------------------------------------------------------------ foot */\n\n.foot {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--space-3);\n padding: var(--space-3) var(--space-4);\n border-top: 1px solid var(--border-subtle);\n background: var(--bg-surface);\n}\n\n.pips {\n list-style: none;\n margin: 0;\n padding: 0;\n display: flex;\n gap: 5px;\n}\n\n.pip {\n width: 14px;\n height: 2px;\n border-radius: 1px;\n background: var(--border-default);\n}\n\n.pip[data-state='current'] {\n background: var(--accent-500);\n}\n\n.pip[data-state='done'] {\n background: var(--border-strong);\n}\n\n.actions {\n display: flex;\n align-items: center;\n gap: var(--space-2);\n}\n\n/* Narrow layouts keep the SAME left anchor and the same cap. Stretching the\n card to `right: var(--space-3)` put it back over the composer's right end —\n which is exactly where Send and Stop sit — so the wide layout's fix stopped\n holding at the width where the window is tightest and the overlap matters\n most. Only the gutter tightens; the card still ends well left of Send. */\n@media (max-width: 900px) {\n .card {\n left: calc(var(--rail-width) + var(--space-3));\n right: auto;\n width: min(420px, calc(100vw - var(--rail-width) - var(--space-3) * 2));\n }\n}\n","/**\n * routes/verse/onboarding/OnboardingFlow.tsx — the first-run tour.\n *\n * A first-time operator opens Verse to five unlabelled rail icons and no\n * guidance. This is five short steps that answer the questions that actually\n * block someone on day one: which of my accounts can this thing use, is\n * there anything local, what do the three stop buttons really do, where do I\n * change how it looks, and how do I start.\n *\n * THREE RULES IT IS BUILT AROUND:\n *\n * 1. It never blocks the app. This is NOT a modal — no backdrop, no focus\n * trap, no `aria-modal`. It is a docked card over the section area; every\n * rail button, shortcut and section behind it stays clickable while it is\n * open. Escape closes it, so does Skip, so does the close button, and any\n * of those three silences it for good.\n *\n * 2. It never asserts more than it read. Step 2 is C6's shared capacity\n * strip (no reading is \"no reading\", never zero); step 3 reads the same\n * local-models route Usage reads, through the same narrower — an\n * unanswered probe is \"no answer\", never a green check (logic in\n * ./onboarding-model.ts, tested without a DOM).\n *\n * 3. It costs no extra requests on the common path. Each data step mounts\n * its own query only when the operator reaches it, and those queries are\n * the Usage section's own cache entries — so a first-run user who walks\n * the tour and then opens Usage finds both reads already in cache and\n * within the freshness window (data/hooks.ts DEFAULT_QUERY_FRESH_MS).\n */\nimport { useCallback, useEffect, useMemo, useRef, type ReactNode } from 'react';\nimport { Button } from '../../../components/primitives/index.js';\nimport {\n IconAlert,\n IconCheckCircle,\n IconChat,\n IconCpu,\n IconInfo,\n IconSliders,\n IconX,\n} from '../../../components/primitives/icons.js';\nimport { useQuery } from '../../../data/hooks.js';\nimport { SECTION_ICON } from '../verse-icons.js';\nimport { RAIL_SECTIONS, requestVerseCommand, setVerseSection } from '../verse-ui-store.js';\nimport { LiveCapacityStrip } from '../usage/CapacityStrip.js';\nimport { verseLocalModelsQuery } from '../usage/usage-queries.js';\nimport { projectLocalModels } from '../usage/usage-contract.js';\nimport {\n ONBOARDING_STEPS,\n STOP_CONTROLS,\n buildLocalFinding,\n clampStep,\n type FindingTone,\n} from './onboarding-model.js';\nimport {\n completeOnboarding,\n dismissOnboarding,\n setOnboardingStep,\n} from './onboarding-store.js';\nimport { useOnboarding } from './useOnboarding.js';\nimport styles from './onboarding.module.css';\n\n/**\n * Tone is paired with a glyph everywhere it appears, never carried by colour\n * alone (DESIGN-V2 §6).\n */\nfunction ToneMark({ tone, label }: { tone: FindingTone; label: string }) {\n const Glyph = tone === 'ok' ? IconCheckCircle : tone === 'attention' ? IconAlert : IconInfo;\n return (\n <span className={styles.tone} data-tone={tone}>\n <Glyph size={13} aria-hidden=\"true\" focusable=\"false\" />\n <span className={styles.toneLabel}>{label}</span>\n </span>\n );\n}\n\nfunction StepBody({ children }: { children: ReactNode }) {\n return <div className={styles.body}>{children}</div>;\n}\n\n// ---------------------------------------------------------------------------\n// Step 1 — what the rail is\n// ---------------------------------------------------------------------------\n\nfunction WelcomeStep() {\n return (\n <StepBody>\n <p className={styles.lead}>\n Verse is the desktop surface over this machine’s agentic fleet. Everything it shows comes from one local\n server — no session, token or artifact leaves this machine.\n </p>\n {/*\n The five rail surfaces, in ⌘1–⌘5 order, with the same one-line blurbs\n the palette uses (VERSE_SECTIONS) — one description per surface, not\n a second copy that drifts. Settings, Apps and Usage live in the gear.\n */}\n <ul className={styles.sections}>\n {RAIL_SECTIONS.map((entry, index) => {\n const Icon = SECTION_ICON[entry.id];\n return (\n <li key={entry.id} className={styles.sectionRow}>\n <span className={styles.sectionIcon} aria-hidden=\"true\">\n <Icon />\n </span>\n <span className={styles.sectionText}>\n <span className={styles.sectionName}>\n {entry.label} <kbd className={styles.kbd}>⌘{index + 1}</kbd>\n </span>\n <span className={styles.sectionBlurb}>{entry.blurb}</span>\n </span>\n </li>\n );\n })}\n </ul>\n <p className={styles.sectionBlurb}>\n <kbd className={styles.kbd}>⌘K</kbd> runs anything by name · <kbd className={styles.kbd}>⌘J</kbd> is everything\n waiting on you · Settings, Apps &amp; Accounts and Usage are under the gear.\n </p>\n </StepBody>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Step 2 — seats\n// ---------------------------------------------------------------------------\n\n/**\n * Step 2 mounts C6's shared LiveCapacityStrip — the SAME projection Apps &\n * Accounts, Usage, the new-chat dialog and the rail's capacity ring read — so\n * the tour can never describe a seat differently from the rest of the app\n * (3.9 had its own accounts narrower here, which drifted from Usage). A seat\n * that is signed out or out of usage shows the exact command that fixes it,\n * straight from A2's health report; nothing is run from the tour.\n */\nfunction AccountsStep() {\n return (\n <StepBody>\n <LiveCapacityStrip\n density=\"compact\"\n headline\n local=\"collapse\"\n // The step's own heading (\"Your seats\") names the strip: a second,\n // hidden heading with the same words is noise to a screen reader.\n labelledBy=\"verse-onboarding-title\"\n emptyText=\"No seats reported yet. Connect an account in Apps & Accounts, or start Ollama for local models.\"\n renderActions={(row) =>\n row.connection?.fixCommand ? (\n <p className={styles.findingFix}>\n <span className={styles.fixLabel}>Fix</span>\n <code className={styles.code}>{row.connection.fixCommand.join(' ')}</code>\n </p>\n ) : null\n }\n />\n <p className={styles.aside}>\n Every window, reset and reserve lives in Apps &amp; Accounts, under the gear.\n </p>\n </StepBody>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Step 3 — local runtime\n// ---------------------------------------------------------------------------\n\nfunction LocalStep() {\n const read = useQuery(verseLocalModelsQuery);\n const finding = useMemo(\n () =>\n buildLocalFinding({\n snapshot: read.data?.available ? projectLocalModels(read.data.raw) : null,\n loading: read.data === undefined && read.status !== 'error',\n unavailableReason: read.data?.reason ?? read.error?.message ?? null,\n }),\n [read.data, read.status, read.error],\n );\n\n return (\n <StepBody>\n <div className={styles.findingHead}>\n <span className={styles.localIcon} aria-hidden=\"true\">\n <IconCpu size={15} />\n </span>\n <ToneMark tone={finding.tone} label={finding.state} />\n </div>\n <p className={styles.lead}>{finding.summary}</p>\n <p className={styles.findingDetail}>{finding.meaning}</p>\n {finding.fix ? (\n <p className={styles.findingFix}>\n <span className={styles.fixLabel}>Fix</span>\n <span className={styles.fixText}>{finding.fix}</span>\n </p>\n ) : null}\n </StepBody>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Step 4 — the three stops\n// ---------------------------------------------------------------------------\n\nfunction StopsStep() {\n return (\n <StepBody>\n <p className={styles.lead}>\n Fleet <kbd className={styles.kbd}>⌘2</kbd> has three stop controls. They are not interchangeable, and the\n difference is the most important thing on this screen.\n </p>\n <ul className={styles.findings}>\n {STOP_CONTROLS.map((control) => (\n <li key={control.name} className={styles.finding}>\n <div className={styles.findingHead}>\n <span className={styles.stopName}>{control.name}</span>\n <ToneMark tone={control.tone} label={control.tone === 'ok' ? 'narrow' : 'global'} />\n </div>\n <p className={styles.findingDetail}>{control.scope}</p>\n <p className={styles.findingDetail}>{control.limit}</p>\n <p className={styles.findingNote}>{control.reversible}</p>\n </li>\n ))}\n </ul>\n </StepBody>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Step 5 — appearance, then go\n// ---------------------------------------------------------------------------\n\nfunction FinishStep() {\n return (\n <StepBody>\n <p className={styles.lead}>\n Settings <kbd className={styles.kbd}>⌘,</kbd> carries theme, accent hue, density, display font, corner radius\n and reduced motion. Every change applies as you make it — there is no save button.\n </p>\n <Button\n variant=\"subtle\"\n icon={<IconSliders size={14} />}\n onClick={() => setVerseSection('settings')}\n >\n Open Settings\n </Button>\n <p className={styles.aside}>\n You can replay this tour any time from Settings → Onboarding.\n </p>\n </StepBody>\n );\n}\n\nconst STEP_COMPONENTS = [WelcomeStep, AccountsStep, LocalStep, StopsStep, FinishStep] as const;\n\n// ---------------------------------------------------------------------------\n// The card\n// ---------------------------------------------------------------------------\n\nexport function OnboardingFlow() {\n const { open, step } = useOnboarding();\n const index = clampStep(step);\n const meta = ONBOARDING_STEPS[index]!;\n const Step = STEP_COMPONENTS[index]!;\n const last = index === ONBOARDING_STEPS.length - 1;\n\n const close = useCallback(() => dismissOnboarding(), []);\n const cardRef = useRef<HTMLElement>(null);\n\n // Escape dismisses the tour — but ONLY when the focus is inside the card.\n //\n // This card is deliberately not a modal (rule 1 above): the operator works\n // behind it, and every Escape they press for something else — closing the\n // command palette, backing out of a seat menu, stopping dictation — used to\n // land here too and permanently dismiss the tour, writing `dismissedAt` with\n // no confirmation and no undo short of Settings → Replay. It also swallowed\n // the default Escape behaviour of whatever they were actually trying to\n // close. Scoped to the card, both problems go away and the shortcut still\n // works where the operator would expect it to.\n useEffect(() => {\n if (!open) return undefined;\n function onKey(event: globalThis.KeyboardEvent) {\n if (event.key !== 'Escape') return;\n const card = cardRef.current;\n if (!card || !(event.target instanceof Node) || !card.contains(event.target)) return;\n event.preventDefault();\n dismissOnboarding();\n }\n document.addEventListener('keydown', onKey);\n return () => document.removeEventListener('keydown', onKey);\n }, [open]);\n\n if (!open) return null;\n\n return (\n <aside ref={cardRef} className={styles.card} aria-labelledby=\"verse-onboarding-title\" role=\"region\">\n <header className={styles.head}>\n <div className={styles.headText}>\n <p className={styles.eyebrow}>\n Getting started · {index + 1} of {ONBOARDING_STEPS.length}\n </p>\n <h2 id=\"verse-onboarding-title\" className={styles.title}>\n {meta.title}\n </h2>\n <p className={styles.subtitle}>{meta.subtitle}</p>\n </div>\n <Button\n iconOnly\n variant=\"ghost\"\n size=\"sm\"\n aria-label=\"Close getting started\"\n icon={<IconX size={14} />}\n onClick={close}\n />\n </header>\n\n <Step />\n\n <footer className={styles.foot}>\n <ol className={styles.pips} aria-hidden=\"true\">\n {ONBOARDING_STEPS.map((s, i) => (\n <li key={s.id} className={styles.pip} data-state={i === index ? 'current' : i < index ? 'done' : 'todo'} />\n ))}\n </ol>\n <div className={styles.actions}>\n <Button variant=\"ghost\" size=\"sm\" onClick={close}>\n Skip setup\n </Button>\n {index > 0 ? (\n <Button variant=\"subtle\" size=\"sm\" onClick={() => setOnboardingStep(index - 1)}>\n Back\n </Button>\n ) : null}\n {last ? (\n <Button\n variant=\"primary\"\n size=\"sm\"\n icon={<IconChat size={14} />}\n onClick={() => {\n completeOnboarding();\n // Switches to Chat and raises the one-shot ⌘N command the\n // chat section consumes by nonce (verse-ui-store.ts).\n requestVerseCommand('new-chat');\n }}\n >\n Start a first chat\n </Button>\n ) : (\n <Button variant=\"primary\" size=\"sm\" onClick={() => setOnboardingStep(index + 1)}>\n Next\n </Button>\n )}\n </div>\n </footer>\n </aside>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"OnboardingFlow-CkTZtt-m.js","names":[],"sources":["../../../../../../src/web-ui/routes/verse/onboarding/onboarding-model.ts","../../../../../../src/web-ui/routes/verse/onboarding/onboarding.module.css","../../../../../../src/web-ui/routes/verse/onboarding/OnboardingFlow.tsx"],"sourcesContent":["/**\n * routes/verse/onboarding/onboarding-model.ts — the first-run tour's facts,\n * derived from the same reads the Usage section uses, with the same honesty\n * rules (docs/VERSE-TELEMETRY-V2.md).\n *\n * Pure: no React, no I/O. Everything the tour asserts about the machine is\n * computed here so it can be tested without a DOM, and so the one rule that\n * matters is enforced in one place:\n *\n * AN ABSENT READ IS \"UNKNOWN\", NEVER \"FINE\" AND NEVER \"BROKEN\".\n *\n * A first-run screen is exactly where a confident lie does the most damage —\n * it is the operator's first and only calibration of how much this app's\n * claims can be trusted. So a route that 404s, a payload that does not\n * narrow, and a probe that could not reach a runtime each produce their own\n * sentence, and none of them produces a green check.\n *\n * The tour NEVER renders a command it invented: the seats step shows only\n * A2's own fix argv (through C6's capacity rows).\n */\nimport type { LocalModelsSnapshot } from '../usage/usage-contract.js';\n\n// ---------------------------------------------------------------------------\n// Steps\n// ---------------------------------------------------------------------------\n\nexport type OnboardingStepId = 'welcome' | 'accounts' | 'local' | 'stops' | 'finish';\n\nexport interface OnboardingStepMeta {\n id: OnboardingStepId;\n /** Shown as the card's heading. */\n title: string;\n /** One line under the heading. */\n subtitle: string;\n}\n\nexport const ONBOARDING_STEPS: readonly OnboardingStepMeta[] = [\n {\n id: 'welcome',\n title: 'Welcome to Verse',\n subtitle: 'Five sections, one rail. Two minutes and you will know what each one does.',\n },\n {\n id: 'accounts',\n title: 'Your seats',\n subtitle: 'Which provider accounts this machine can actually dispatch to right now.',\n },\n {\n id: 'local',\n title: 'Local runtime',\n subtitle: 'Whether there is a model on this machine, and what that changes.',\n },\n {\n id: 'stops',\n title: 'Three ways to stop',\n subtitle: 'They do not have the same blast radius. This is the one screen that says so.',\n },\n {\n id: 'finish',\n title: 'Make it yours',\n subtitle: 'Theme, accent, density and font live in Settings. Then start a chat.',\n },\n];\n\nexport function clampStep(step: number): number {\n if (!Number.isFinite(step)) return 0;\n return Math.min(ONBOARDING_STEPS.length - 1, Math.max(0, Math.trunc(step)));\n}\n\n// ---------------------------------------------------------------------------\n// Tone\n// ---------------------------------------------------------------------------\n\n/**\n * Step 2 (seats) is C6's shared LiveCapacityStrip since 3.10 — the tour no\n * longer narrows the accounts route itself, so the seats can never read\n * differently here than in Apps & Accounts. The tone below serves the local\n * runtime and the stops.\n */\nexport type FindingTone = 'ok' | 'attention' | 'unknown';\n\n// ---------------------------------------------------------------------------\n// Local runtime\n// ---------------------------------------------------------------------------\n\nexport interface LocalFinding {\n tone: FindingTone;\n state: string;\n summary: string;\n /** What having (or not having) a local runtime means for the operator. */\n meaning: string;\n /** Present only when there is something to do about it. */\n fix: string | null;\n modelCount: number;\n toolCapableCount: number;\n /** True when this reading was retained from an earlier probe. */\n stale: boolean;\n}\n\nexport interface LocalInput {\n snapshot: LocalModelsSnapshot | null;\n loading: boolean;\n unavailableReason: string | null;\n}\n\nconst LOCAL_MEANING_AVAILABLE =\n 'Local seats cost nothing and consume no provider quota, so the autonomous loop can keep working after a cloud window is used up.';\nconst LOCAL_MEANING_ABSENT =\n 'Without one, every turn and every autonomous tick spends a provider account, and a used-up window stops the work.';\n\nexport function buildLocalFinding(input: LocalInput): LocalFinding {\n if (input.loading) {\n return {\n tone: 'unknown',\n state: 'checking',\n summary: 'Probing the local runtimes on this machine…',\n meaning: LOCAL_MEANING_AVAILABLE,\n fix: null,\n modelCount: 0,\n toolCapableCount: 0,\n stale: false,\n };\n }\n\n if (!input.snapshot) {\n return {\n tone: 'unknown',\n state: 'not reported',\n summary: 'This server does not report local runtimes, so Verse cannot say whether one is available here.',\n meaning: LOCAL_MEANING_ABSENT,\n fix: input.unavailableReason,\n modelCount: 0,\n toolCapableCount: 0,\n stale: false,\n };\n }\n\n const models = input.snapshot.models;\n const toolCapable = models.filter((m) => m.supportsTools === true).length;\n const stale = input.snapshot.runtimes.some((r) => r.stale);\n\n if (!input.snapshot.reachable) {\n return {\n tone: 'attention',\n state: 'unreachable',\n // \"Not reachable\" and \"not installed\" are different facts and the probe\n // cannot tell them apart — so this does not claim either one.\n summary:\n 'No local runtime answered. Verse cannot tell whether one is not running or not installed — the probe only knows it got no answer.',\n meaning: LOCAL_MEANING_ABSENT,\n fix: 'Start Ollama (or LM Studio) and press Refresh in Usage. If neither is installed, everything still works — it all runs on the cloud seats.',\n modelCount: 0,\n toolCapableCount: 0,\n stale,\n };\n }\n\n if (models.length === 0) {\n return {\n tone: 'attention',\n state: 'no models',\n summary: 'A local runtime answered, but it has no models installed.',\n meaning: LOCAL_MEANING_ABSENT,\n fix: 'Pull a model into the runtime, then press Refresh in Usage.',\n modelCount: 0,\n toolCapableCount: 0,\n stale,\n };\n }\n\n return {\n tone: 'ok',\n state: stale ? 'available (retained reading)' : 'available',\n summary:\n `${models.length} local ${models.length === 1 ? 'model' : 'models'} available` +\n (toolCapable > 0 ? `, ${toolCapable} of them tool-capable.` : ', none of them tool-capable.') +\n (stale ? ' This is a retained reading, not a fresh probe.' : ''),\n meaning: toolCapable > 0\n ? LOCAL_MEANING_AVAILABLE\n : `${LOCAL_MEANING_AVAILABLE} A model that cannot call tools can answer, but cannot run an agentic turn.`,\n fix: null,\n modelCount: models.length,\n toolCapableCount: toolCapable,\n stale,\n };\n}\n\n// ---------------------------------------------------------------------------\n// The three stops\n// ---------------------------------------------------------------------------\n\nexport interface StopControl {\n name: string;\n /** What it halts. */\n scope: string;\n /** What it does NOT halt — the half people get wrong. */\n limit: string;\n reversible: string;\n tone: FindingTone;\n}\n\n/**\n * Verbatim against docs/VERSE-CONTRACT-V2.md's two footguns and the V2.1\n * amendment. The kill switch is never called a pause, and \"Stop loop\" is\n * stated as engaging the same global sentinel as the emergency control,\n * because it does (`stopDaemon()` is `setKill(true)`).\n */\nexport const STOP_CONTROLS: readonly StopControl[] = [\n {\n name: 'Pause',\n scope: 'Halts autonomous dispatch only. A running loop parks instead of exiting.',\n limit: 'Your own chats and the agent’s write tools keep working.',\n reversible: 'Reversible in one click, with no restart and no confirmation.',\n tone: 'ok',\n },\n {\n name: 'Stop loop',\n scope: 'Stops the daemon — and engages the GLOBAL kill switch while doing it.',\n limit: 'That means it also refuses the agent’s own write tools, exactly like the emergency control.',\n reversible: 'Reversible, but confirm-guarded. For an ordinary halt, use Pause.',\n tone: 'attention',\n },\n {\n name: 'Emergency stop',\n scope: 'Engages the global kill switch (~/.ashlr/KILL) directly.',\n limit: 'Every mutating path refuses: the loop, dispatch, and the agent’s own write tools.',\n reversible: 'Reversible, confirm-guarded, and deliberately separated from the other two.',\n tone: 'attention',\n },\n];\n","/* First-run tour — a docked card, not a dialog. No backdrop: the app behind\n it stays visible and clickable, which is the whole design constraint.\n Hairlines and one elevation (DESIGN-V2 §1/§2); the only colour is the\n status tone on a glyph, never on body text. */\n\n/* Docked bottom-LEFT of the content area, not bottom-right of the viewport.\n The composer is centred on --measure-read inside the workspace and its\n control row — seat pill, mic, Send/Stop — sits at the bottom of that column,\n right-aligned. A 420px card pinned to the viewport's bottom-right lands on\n top of exactly those controls at ordinary window widths, which breaks this\n file's own rule 1: everything behind the card stays clickable. Clearing the\n rail and hugging the left edge keeps it out of the composer's way in both\n the wide and the 900px layouts. */\n.card {\n position: fixed;\n z-index: var(--z-dialog);\n left: calc(var(--rail-width) + var(--space-5));\n right: auto;\n bottom: calc(var(--space-5) + env(safe-area-inset-bottom, 0px));\n width: min(420px, calc(100vw - var(--rail-width) - var(--space-5) * 2));\n max-height: min(640px, calc(100vh - var(--space-8)));\n display: flex;\n flex-direction: column;\n overflow: hidden;\n background: var(--bg-surface-raised);\n border: 1px solid var(--border-default);\n border-radius: var(--radius-lg);\n box-shadow: var(--shadow-dialog);\n}\n\n/* One declaration, correct in all four motion states. `--duration-base`\n already collapses to 1ms under BOTH triggers the app honours — the OS\n preference (unless Settings asked for full motion) and Settings' own\n `data-motion=\"reduce\"` — so a bare `prefers-reduced-motion` media query was\n wrong in two of them: it ignored an operator who chose Reduce in Settings,\n and it removed the animation from one who chose Full against an OS reduce\n preference. This is a one-shot animation, so unlike the persistent\n `.dictationPulse`/`.caret` cases it needs no by-name rules. */\n.card {\n animation: onboarding-in var(--duration-base) var(--ease-decelerate);\n}\n\n@keyframes onboarding-in {\n from {\n opacity: 0;\n transform: translateY(4px);\n }\n to {\n opacity: 1;\n transform: none;\n }\n}\n\n/* ------------------------------------------------------------------ head */\n\n.head {\n display: flex;\n align-items: flex-start;\n gap: var(--space-2);\n padding: var(--space-4) var(--space-4) var(--space-3);\n border-bottom: 1px solid var(--border-subtle);\n}\n\n.headText {\n flex: 1;\n min-width: 0;\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n.eyebrow {\n font-family: var(--font-display);\n font-size: var(--text-2xs-size);\n letter-spacing: var(--tracking-label);\n text-transform: uppercase;\n color: var(--text-tertiary);\n}\n\n.title {\n font-family: var(--font-display);\n font-size: var(--text-md-size);\n font-weight: var(--font-weight-semibold);\n letter-spacing: var(--tracking-display);\n color: var(--text-primary);\n}\n\n.subtitle {\n font-size: var(--text-xs-size);\n line-height: var(--text-xs-line-relaxed);\n color: var(--text-secondary);\n}\n\n/* ------------------------------------------------------------------ body */\n\n.body {\n flex: 1;\n min-height: 0;\n overflow-y: auto;\n padding: var(--space-4);\n display: flex;\n flex-direction: column;\n gap: var(--space-3);\n align-items: flex-start;\n}\n\n.lead {\n font-size: var(--text-sm-size);\n line-height: var(--text-sm-line-relaxed);\n color: var(--text-primary);\n}\n\n.aside,\n.caveat {\n font-size: var(--text-xs-size);\n line-height: var(--text-xs-line-relaxed);\n color: var(--text-tertiary);\n}\n\n.caveat {\n border-left: 2px solid var(--border-strong);\n padding-left: var(--space-3);\n}\n\n.kbd {\n font-family: var(--font-mono);\n font-size: var(--text-2xs-size);\n padding: 1px 5px;\n border: 1px solid var(--border-default);\n border-radius: var(--radius-xs);\n background: var(--bg-surface);\n color: var(--text-secondary);\n white-space: nowrap;\n}\n\n/* --------------------------------------------------------- rail overview */\n\n.sections,\n.findings {\n list-style: none;\n margin: 0;\n padding: 0;\n width: 100%;\n display: flex;\n flex-direction: column;\n}\n\n.sectionRow {\n display: flex;\n align-items: flex-start;\n gap: var(--space-3);\n padding: var(--space-2) 0;\n border-top: 1px solid var(--border-subtle);\n}\n\n.sectionRow:first-child {\n border-top: none;\n}\n\n.sectionIcon,\n.localIcon {\n flex: none;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n /* Derived from the density scale rather than a literal, so compact density\n actually reaches it (design/control-density.test.ts). */\n width: var(--control-h-xs);\n height: var(--control-h-xs);\n color: var(--text-tertiary);\n}\n\n.sectionText {\n display: flex;\n flex-direction: column;\n gap: 2px;\n min-width: 0;\n}\n\n.sectionName {\n font-family: var(--font-display);\n font-size: var(--text-xs-size);\n font-weight: var(--font-weight-semibold);\n color: var(--text-primary);\n display: inline-flex;\n align-items: center;\n gap: var(--space-2);\n}\n\n.sectionBlurb {\n font-size: var(--text-xs-size);\n line-height: var(--text-xs-line-relaxed);\n color: var(--text-secondary);\n}\n\n/* ----------------------------------------------------------- findings */\n\n.finding {\n display: flex;\n flex-direction: column;\n gap: var(--space-1);\n padding: var(--space-3) 0;\n border-top: 1px solid var(--border-subtle);\n}\n\n.finding:first-child {\n border-top: none;\n}\n\n.findingHead {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--space-2);\n flex-wrap: wrap;\n}\n\n.stopName {\n font-family: var(--font-display);\n font-size: var(--text-sm-size);\n font-weight: var(--font-weight-semibold);\n color: var(--text-primary);\n}\n\n.findingDetail {\n font-size: var(--text-xs-size);\n line-height: var(--text-xs-line-relaxed);\n color: var(--text-secondary);\n}\n\n.findingNote {\n font-size: var(--text-xs-size);\n line-height: var(--text-xs-line-relaxed);\n color: var(--text-tertiary);\n}\n\n.findingFix {\n display: flex;\n align-items: baseline;\n gap: var(--space-2);\n flex-wrap: wrap;\n margin-top: 2px;\n}\n\n.fixLabel {\n font-family: var(--font-display);\n font-size: var(--text-2xs-size);\n letter-spacing: var(--tracking-label);\n text-transform: uppercase;\n color: var(--text-tertiary);\n flex: none;\n}\n\n.fixText {\n font-size: var(--text-xs-size);\n line-height: var(--text-xs-line-relaxed);\n color: var(--text-secondary);\n}\n\n.code {\n font-family: var(--font-mono);\n /* A command an operator is meant to READ and retype, not a micro-label:\n tokens.css reserves --text-2xs for uppercase labels and keyboard hints\n and sets the body floor at 12px. */\n font-size: var(--text-xs-size);\n padding: 2px 6px;\n border: 1px solid var(--border-subtle);\n border-radius: var(--radius-xs);\n background: var(--bg-code, var(--bg-surface));\n color: var(--text-primary);\n overflow-wrap: anywhere;\n}\n\n/* --------------------------------------------------------------- tone */\n\n.tone {\n display: inline-flex;\n align-items: center;\n gap: 5px;\n flex: none;\n}\n\n.toneLabel {\n font-family: var(--font-display);\n font-size: var(--text-2xs-size);\n letter-spacing: var(--tracking-label);\n text-transform: uppercase;\n color: var(--text-secondary);\n}\n\n.tone[data-tone='ok'] {\n color: var(--status-success-fg, var(--text-secondary));\n}\n\n.tone[data-tone='attention'] {\n color: var(--status-warning-fg, var(--text-secondary));\n}\n\n.tone[data-tone='unknown'] {\n color: var(--text-tertiary);\n}\n\n/* ------------------------------------------------------------------ foot */\n\n.foot {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--space-3);\n padding: var(--space-3) var(--space-4);\n border-top: 1px solid var(--border-subtle);\n background: var(--bg-surface);\n}\n\n.pips {\n list-style: none;\n margin: 0;\n padding: 0;\n display: flex;\n gap: 5px;\n}\n\n.pip {\n width: 14px;\n height: 2px;\n border-radius: 1px;\n background: var(--border-default);\n}\n\n.pip[data-state='current'] {\n background: var(--accent-500);\n}\n\n.pip[data-state='done'] {\n background: var(--border-strong);\n}\n\n.actions {\n display: flex;\n align-items: center;\n gap: var(--space-2);\n}\n\n/* Narrow layouts keep the SAME left anchor and the same cap. Stretching the\n card to `right: var(--space-3)` put it back over the composer's right end —\n which is exactly where Send and Stop sit — so the wide layout's fix stopped\n holding at the width where the window is tightest and the overlap matters\n most. Only the gutter tightens; the card still ends well left of Send. */\n@media (max-width: 900px) {\n .card {\n left: calc(var(--rail-width) + var(--space-3));\n right: auto;\n width: min(420px, calc(100vw - var(--rail-width) - var(--space-3) * 2));\n }\n}\n","/**\n * routes/verse/onboarding/OnboardingFlow.tsx — the first-run tour.\n *\n * A first-time operator opens Verse to five unlabelled rail icons and no\n * guidance. This is five short steps that answer the questions that actually\n * block someone on day one: which of my accounts can this thing use, is\n * there anything local, what do the three stop buttons really do, where do I\n * change how it looks, and how do I start.\n *\n * THREE RULES IT IS BUILT AROUND:\n *\n * 1. It never blocks the app. This is NOT a modal — no backdrop, no focus\n * trap, no `aria-modal`. It is a docked card over the section area; every\n * rail button, shortcut and section behind it stays clickable while it is\n * open. Escape closes it, so does Skip, so does the close button, and any\n * of those three silences it for good.\n *\n * 2. It never asserts more than it read. Step 2 is C6's shared capacity\n * strip (no reading is \"no reading\", never zero); step 3 reads the same\n * local-models route Usage reads, through the same narrower — an\n * unanswered probe is \"no answer\", never a green check (logic in\n * ./onboarding-model.ts, tested without a DOM).\n *\n * 3. It costs no extra requests on the common path. Each data step mounts\n * its own query only when the operator reaches it, and those queries are\n * the Usage section's own cache entries — so a first-run user who walks\n * the tour and then opens Usage finds both reads already in cache and\n * within the freshness window (data/hooks.ts DEFAULT_QUERY_FRESH_MS).\n */\nimport { useCallback, useEffect, useMemo, useRef, type ReactNode } from 'react';\nimport { Button } from '../../../components/primitives/index.js';\nimport {\n IconAlert,\n IconCheckCircle,\n IconChat,\n IconCpu,\n IconInfo,\n IconSliders,\n IconX,\n} from '../../../components/primitives/icons.js';\nimport { useQuery } from '../../../data/hooks.js';\nimport { SECTION_ICON } from '../verse-icons.js';\nimport { RAIL_SECTIONS, requestVerseCommand, setVerseSection } from '../verse-ui-store.js';\nimport { LiveCapacityStrip } from '../usage/CapacityStrip.js';\nimport { tidyProse } from '../autonomy/format.js';\nimport { verseLocalModelsQuery } from '../usage/usage-queries.js';\nimport { projectLocalModels } from '../usage/usage-contract.js';\nimport {\n ONBOARDING_STEPS,\n STOP_CONTROLS,\n buildLocalFinding,\n clampStep,\n type FindingTone,\n} from './onboarding-model.js';\nimport {\n completeOnboarding,\n dismissOnboarding,\n setOnboardingStep,\n} from './onboarding-store.js';\nimport { useOnboarding } from './useOnboarding.js';\nimport styles from './onboarding.module.css';\n\n/**\n * Tone is paired with a glyph everywhere it appears, never carried by colour\n * alone (DESIGN-V2 §6).\n */\nfunction ToneMark({ tone, label }: { tone: FindingTone; label: string }) {\n const Glyph = tone === 'ok' ? IconCheckCircle : tone === 'attention' ? IconAlert : IconInfo;\n return (\n <span className={styles.tone} data-tone={tone}>\n <Glyph size={13} aria-hidden=\"true\" focusable=\"false\" />\n <span className={styles.toneLabel}>{label}</span>\n </span>\n );\n}\n\nfunction StepBody({ children }: { children: ReactNode }) {\n return <div className={styles.body}>{children}</div>;\n}\n\n// ---------------------------------------------------------------------------\n// Step 1 — what the rail is\n// ---------------------------------------------------------------------------\n\nfunction WelcomeStep() {\n return (\n <StepBody>\n <p className={styles.lead}>\n Verse is the desktop surface over this machine’s agentic fleet. Everything it shows comes from one local\n server — no session, token or artifact leaves this machine.\n </p>\n {/*\n The five rail surfaces, in ⌘1–⌘5 order, with the same one-line blurbs\n the palette uses (VERSE_SECTIONS) — one description per surface, not\n a second copy that drifts. Settings, Apps and Usage live in the gear.\n */}\n <ul className={styles.sections}>\n {RAIL_SECTIONS.map((entry, index) => {\n const Icon = SECTION_ICON[entry.id];\n return (\n <li key={entry.id} className={styles.sectionRow}>\n <span className={styles.sectionIcon} aria-hidden=\"true\">\n <Icon />\n </span>\n <span className={styles.sectionText}>\n <span className={styles.sectionName}>\n {entry.label} <kbd className={styles.kbd}>⌘{index + 1}</kbd>\n </span>\n <span className={styles.sectionBlurb}>{entry.blurb}</span>\n </span>\n </li>\n );\n })}\n </ul>\n <p className={styles.sectionBlurb}>\n <kbd className={styles.kbd}>⌘K</kbd> runs anything by name · <kbd className={styles.kbd}>⌘J</kbd> is everything\n waiting on you · Settings, Apps &amp; Accounts and Usage are under the gear.\n </p>\n </StepBody>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Step 2 — seats\n// ---------------------------------------------------------------------------\n\n/**\n * Step 2 mounts C6's shared LiveCapacityStrip — the SAME projection Apps &\n * Accounts, Usage, the new-chat dialog and the rail's capacity ring read — so\n * the tour can never describe a seat differently from the rest of the app\n * (3.9 had its own accounts narrower here, which drifted from Usage). A seat\n * that is signed out or out of usage shows the exact command that fixes it,\n * straight from A2's health report; nothing is run from the tour.\n */\nfunction AccountsStep() {\n return (\n <StepBody>\n <LiveCapacityStrip\n density=\"compact\"\n headline\n local=\"collapse\"\n // The step's own heading (\"Your seats\") names the strip: a second,\n // hidden heading with the same words is noise to a screen reader.\n labelledBy=\"verse-onboarding-title\"\n emptyText=\"No seats reported yet. Connect an account in Apps & Accounts, or start Ollama for local models.\"\n renderActions={(row) =>\n row.connection?.fixCommand ? (\n <p className={styles.findingFix}>\n <span className={styles.fixLabel}>Fix</span>\n <code className={styles.code}>{row.connection.fixCommand.join(' ')}</code>\n </p>\n ) : null\n }\n />\n <p className={styles.aside}>\n Every window, reset and reserve lives in Apps &amp; Accounts, under the gear.\n </p>\n </StepBody>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Step 3 — local runtime\n// ---------------------------------------------------------------------------\n\nfunction LocalStep() {\n const read = useQuery(verseLocalModelsQuery);\n const finding = useMemo(() => {\n // The server's sentence, with any ISO instant in it read as local time.\n const reason = read.data?.reason ?? read.error?.message ?? null;\n return buildLocalFinding({\n snapshot: read.data?.available ? projectLocalModels(read.data.raw) : null,\n loading: read.data === undefined && read.status !== 'error',\n unavailableReason: reason === null ? null : tidyProse(reason),\n });\n }, [read.data, read.status, read.error]);\n\n return (\n <StepBody>\n <div className={styles.findingHead}>\n <span className={styles.localIcon} aria-hidden=\"true\">\n <IconCpu size={15} />\n </span>\n <ToneMark tone={finding.tone} label={finding.state} />\n </div>\n <p className={styles.lead}>{finding.summary}</p>\n <p className={styles.findingDetail}>{finding.meaning}</p>\n {finding.fix ? (\n <p className={styles.findingFix}>\n <span className={styles.fixLabel}>Fix</span>\n <span className={styles.fixText}>{finding.fix}</span>\n </p>\n ) : null}\n </StepBody>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Step 4 — the three stops\n// ---------------------------------------------------------------------------\n\nfunction StopsStep() {\n return (\n <StepBody>\n <p className={styles.lead}>\n Fleet <kbd className={styles.kbd}>⌘2</kbd> has three stop controls. They are not interchangeable, and the\n difference is the most important thing on this screen.\n </p>\n <ul className={styles.findings}>\n {STOP_CONTROLS.map((control) => (\n <li key={control.name} className={styles.finding}>\n <div className={styles.findingHead}>\n <span className={styles.stopName}>{control.name}</span>\n <ToneMark tone={control.tone} label={control.tone === 'ok' ? 'narrow' : 'global'} />\n </div>\n <p className={styles.findingDetail}>{control.scope}</p>\n <p className={styles.findingDetail}>{control.limit}</p>\n <p className={styles.findingNote}>{control.reversible}</p>\n </li>\n ))}\n </ul>\n </StepBody>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Step 5 — appearance, then go\n// ---------------------------------------------------------------------------\n\nfunction FinishStep() {\n return (\n <StepBody>\n <p className={styles.lead}>\n Settings <kbd className={styles.kbd}>⌘,</kbd> carries theme, accent hue, density, display font, corner radius\n and reduced motion. Every change applies as you make it — there is no save button.\n </p>\n <Button\n variant=\"subtle\"\n icon={<IconSliders size={14} />}\n onClick={() => setVerseSection('settings')}\n >\n Open Settings\n </Button>\n <p className={styles.aside}>\n You can replay this tour any time from Settings → Onboarding.\n </p>\n </StepBody>\n );\n}\n\nconst STEP_COMPONENTS = [WelcomeStep, AccountsStep, LocalStep, StopsStep, FinishStep] as const;\n\n// ---------------------------------------------------------------------------\n// The card\n// ---------------------------------------------------------------------------\n\nexport function OnboardingFlow() {\n const { open, step } = useOnboarding();\n const index = clampStep(step);\n const meta = ONBOARDING_STEPS[index]!;\n const Step = STEP_COMPONENTS[index]!;\n const last = index === ONBOARDING_STEPS.length - 1;\n\n const close = useCallback(() => dismissOnboarding(), []);\n const cardRef = useRef<HTMLElement>(null);\n\n // Escape dismisses the tour — but ONLY when the focus is inside the card.\n //\n // This card is deliberately not a modal (rule 1 above): the operator works\n // behind it, and every Escape they press for something else — closing the\n // command palette, backing out of a seat menu, stopping dictation — used to\n // land here too and permanently dismiss the tour, writing `dismissedAt` with\n // no confirmation and no undo short of Settings → Replay. It also swallowed\n // the default Escape behaviour of whatever they were actually trying to\n // close. Scoped to the card, both problems go away and the shortcut still\n // works where the operator would expect it to.\n useEffect(() => {\n if (!open) return undefined;\n function onKey(event: globalThis.KeyboardEvent) {\n if (event.key !== 'Escape') return;\n const card = cardRef.current;\n if (!card || !(event.target instanceof Node) || !card.contains(event.target)) return;\n event.preventDefault();\n dismissOnboarding();\n }\n document.addEventListener('keydown', onKey);\n return () => document.removeEventListener('keydown', onKey);\n }, [open]);\n\n if (!open) return null;\n\n return (\n <aside ref={cardRef} className={styles.card} aria-labelledby=\"verse-onboarding-title\" role=\"region\">\n <header className={styles.head}>\n <div className={styles.headText}>\n <p className={styles.eyebrow}>\n Getting started · {index + 1} of {ONBOARDING_STEPS.length}\n </p>\n <h2 id=\"verse-onboarding-title\" className={styles.title}>\n {meta.title}\n </h2>\n <p className={styles.subtitle}>{meta.subtitle}</p>\n </div>\n <Button\n iconOnly\n variant=\"ghost\"\n size=\"sm\"\n aria-label=\"Close getting started\"\n title=\"Close getting started\"\n icon={<IconX size={14} />}\n onClick={close}\n />\n </header>\n\n <Step />\n\n <footer className={styles.foot}>\n <ol className={styles.pips} aria-hidden=\"true\">\n {ONBOARDING_STEPS.map((s, i) => (\n <li key={s.id} className={styles.pip} data-state={i === index ? 'current' : i < index ? 'done' : 'todo'} />\n ))}\n </ol>\n <div className={styles.actions}>\n <Button variant=\"ghost\" size=\"sm\" onClick={close}>\n Skip setup\n </Button>\n {index > 0 ? (\n <Button variant=\"subtle\" size=\"sm\" onClick={() => setOnboardingStep(index - 1)}>\n Back\n </Button>\n ) : null}\n {last ? (\n <Button\n variant=\"primary\"\n size=\"sm\"\n icon={<IconChat size={14} />}\n onClick={() => {\n completeOnboarding();\n // Switches to Chat and raises the one-shot ⌘N command the\n // chat section consumes by nonce (verse-ui-store.ts).\n requestVerseCommand('new-chat');\n }}\n >\n Start a first chat\n </Button>\n ) : (\n <Button variant=\"primary\" size=\"sm\" onClick={() => setOnboardingStep(index + 1)}>\n Next\n </Button>\n )}\n </div>\n </footer>\n </aside>\n );\n}\n"],"mappings":"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"}
@@ -0,0 +1 @@
1
+ ._pane_k6hui_8{background:var(--bg-canvas);height:100%;min-height:0;color:var(--text-primary);flex-direction:column;display:flex}._strip_k6hui_19{min-height:var(--control-h-sm);border-bottom:1px solid var(--border-subtle);background:var(--bg-surface);flex:none;align-items:stretch;display:flex}._tabs_k6hui_28{scrollbar-width:none;align-items:stretch;min-width:0;display:flex;overflow-x:auto}._tabs_k6hui_28::-webkit-scrollbar{display:none}._tab_k6hui_28{border-right:1px solid var(--border-subtle);max-width:220px;color:var(--text-secondary);flex:none;align-items:center;display:flex;position:relative}._tab_k6hui_28[data-selected]{color:var(--text-primary);background:var(--bg-canvas)}._tab_k6hui_28[data-selected]:after{content:"";background:var(--accent-500);height:2px;position:absolute;bottom:-1px;left:0;right:0}._tabButton_k6hui_60{align-items:center;gap:var(--space-2);min-width:0;height:100%;padding:0 var(--space-1) 0 var(--space-3);color:inherit;font-family:var(--font-ui);font-size:var(--text-xs-size);line-height:var(--text-xs-line);cursor:pointer;background:0 0;border:0;display:inline-flex}._tabButton_k6hui_60>svg{color:var(--text-tertiary);flex:none}._tabButton_k6hui_60:hover{color:var(--text-primary)}._tabButton_k6hui_60:focus-visible,._tabClose_k6hui_78:focus-visible,._noticeClose_k6hui_79:focus-visible,._external_k6hui_80:focus-visible{box-shadow:var(--shadow-focus-ring);outline:none}._tabTitle_k6hui_85{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}._tabClose_k6hui_78{width:calc(var(--control-h-xs) - var(--space-1));height:calc(var(--control-h-xs) - var(--space-1));margin-right:var(--space-1);border-radius:var(--radius-xs);color:var(--text-tertiary);cursor:pointer;opacity:0;transition:opacity var(--duration-fast) var(--ease-standard);background:0 0;border:0;flex:none;justify-content:center;align-items:center;display:inline-flex}._tab_k6hui_28:hover ._tabClose_k6hui_78,._tab_k6hui_28[data-selected] ._tabClose_k6hui_78,._tabClose_k6hui_78:focus-visible{opacity:1}._tabClose_k6hui_78:hover{background:var(--bg-hover);color:var(--text-primary)}@media (hover:none){._tabClose_k6hui_78{opacity:1}}._newTab_k6hui_118{margin:0 var(--space-1);align-self:center}._pane_k6hui_8 ._toolbar_k6hui_126{padding-left:var(--space-2)}._nav_k6hui_128{flex:none;align-items:center;display:flex}._addressForm_k6hui_134{flex:auto;min-width:0;display:flex}._address_k6hui_134{width:100%;min-width:0;height:var(--control-h-sm);padding:0 var(--space-3);border:1px solid var(--border-default);border-radius:var(--radius-full);background:var(--bg-input);color:var(--text-primary);font-family:var(--font-mono);font-size:var(--text-xs-size);line-height:var(--text-xs-line)}._address_k6hui_134::placeholder{color:var(--text-tertiary)}._address_k6hui_134:focus{border-color:var(--border-focus);box-shadow:var(--shadow-focus-ring);outline:none}._address_k6hui_134[readonly]{color:var(--text-secondary)}._external_k6hui_80{width:var(--density-row-sm);height:var(--density-row-sm);border-radius:var(--radius-sm);color:var(--text-secondary);flex:none;justify-content:center;align-items:center;display:inline-flex}._external_k6hui_80:hover{background:var(--bg-hover);color:var(--text-primary)}._external_k6hui_80[data-placeholder]{visibility:hidden}._addressNote_k6hui_177,._notice_k6hui_79,._waiting_k6hui_179{align-items:center;gap:var(--space-2);padding:var(--space-2) var(--space-3);border-bottom:1px solid var(--border-subtle);font-size:var(--text-sm-size);line-height:var(--text-sm-line);flex:none;display:flex}._addressNote_k6hui_177{background:var(--status-info-bg);color:var(--status-info-fg)}._notice_k6hui_79{background:var(--status-danger-bg);color:var(--status-danger-fg)}._waiting_k6hui_179{background:var(--status-running-bg);color:var(--status-running-fg)}._addressNote_k6hui_177>span,._notice_k6hui_79>span{flex:1;min-width:0}._addressNote_k6hui_177 a{color:inherit;font-weight:var(--font-weight-semibold)}._addressNote_k6hui_177 code,._waiting_k6hui_179 code{font-family:var(--font-mono);font-size:var(--text-xs-size)}._waitingText_k6hui_201{font-variant-numeric:tabular-nums;flex:1;min-width:0}._pulse_k6hui_208{border-radius:var(--radius-full);background:var(--status-running-solid);width:8px;height:8px;animation:_pulse_k6hui_208 var(--duration-pulse) ease-in-out infinite;flex:none}@keyframes _pulse_k6hui_208{0%,to{opacity:1}50%{opacity:.35}}._noticeClose_k6hui_79{padding:var(--space-1);border-radius:var(--radius-xs);color:inherit;cursor:pointer;background:0 0;border:0;flex:none;display:inline-flex}._body_k6hui_234{flex-direction:column;flex:auto;min-height:0;display:flex;position:relative;overflow:auto}._loading_k6hui_243{gap:var(--space-2);padding:var(--card-pad);flex-direction:column;display:flex}._stage_k6hui_250{flex-direction:column;flex:auto;align-items:stretch;min-height:0;display:flex}._stage_k6hui_250[data-device=phone]{padding:var(--space-3) 0;align-items:center}._frame_k6hui_262{background:var(--bg-surface);border:0;flex:auto;width:100%;min-height:0}._stage_k6hui_250[data-device=phone] ._frame_k6hui_262{border:1px solid var(--border-default);border-radius:var(--radius-lg);width:375px;max-width:100%;box-shadow:var(--shadow-md);flex:auto}._frameHint_k6hui_278{padding:var(--space-1) var(--space-3);border-top:1px solid var(--border-subtle);background:var(--bg-surface);font-size:var(--text-2xs-size);line-height:var(--text-2xs-line);color:var(--text-tertiary);flex:none;margin:0}._stage_k6hui_250[data-device=phone] ._frameHint_k6hui_278{margin-top:var(--space-3);align-self:stretch}._frameHint_k6hui_278 a{color:var(--text-link)}._imageStage_k6hui_291{min-height:0;padding:var(--card-pad);background:repeating-conic-gradient(var(--bg-hover) 0 25%, transparent 0 50%) 0 0 / 16px 16px, var(--bg-surface);flex:auto;justify-content:center;align-items:center;display:flex}._image_k6hui_291{object-fit:contain;max-width:100%;max-height:100%}._markdown_k6hui_308{padding:var(--card-pad) var(--space-6);max-width:var(--measure-read);background:var(--bg-canvas)}._launcher_k6hui_316{padding-bottom:var(--space-6);flex-direction:column;display:flex}._section_k6hui_322{padding:var(--space-4) var(--card-pad) 0}._section_k6hui_322+._section_k6hui_322{margin-top:var(--space-4);border-top:1px solid var(--border-subtle)}._sectionTitle_k6hui_328{margin:0 0 var(--space-2);font-family:var(--font-display);font-size:var(--text-2xs-size);line-height:var(--text-2xs-line);font-weight:var(--font-weight-semibold);letter-spacing:var(--tracking-label);text-transform:uppercase;color:var(--text-tertiary)}._muted_k6hui_339{font-size:var(--text-sm-size);line-height:var(--text-sm-line);color:var(--text-tertiary);margin:0}._muted_k6hui_339 code{font-family:var(--font-mono);font-size:var(--text-xs-size)}._rows_k6hui_347{flex-direction:column;margin:0;padding:0;list-style:none;display:flex}._row_k6hui_347{align-items:center;gap:var(--space-3);min-height:var(--density-row);padding:var(--space-2) 0;display:flex}._row_k6hui_347+._row_k6hui_347{border-top:1px solid var(--border-subtle)}._dot_k6hui_364{border:1.5px solid var(--text-tertiary);border-radius:var(--radius-full);flex:none;width:8px;height:8px}._dot_k6hui_364[data-running]{border-color:var(--status-success-solid);background:var(--status-success-solid)}._fileIcon_k6hui_376{color:var(--text-tertiary);flex:none}._rowMain_k6hui_378{flex-direction:column;flex:auto;min-width:0;display:flex}._rowTitle_k6hui_385{text-overflow:ellipsis;white-space:nowrap;font-family:var(--font-mono);font-size:var(--text-sm-size);line-height:var(--text-sm-line);color:var(--text-primary);overflow:hidden}._rowMeta_k6hui_395{text-overflow:ellipsis;white-space:nowrap;font-size:var(--text-xs-size);line-height:var(--text-xs-line);color:var(--text-tertiary);overflow:hidden}._rowCommand_k6hui_405{text-overflow:ellipsis;white-space:nowrap;font-family:var(--font-mono);font-size:var(--text-xs-size);line-height:var(--text-xs-line);color:var(--text-secondary);overflow:hidden}._pane_k6hui_8[data-compact] ._toolbar_k6hui_126{flex-wrap:wrap}._pane_k6hui_8[data-compact] ._addressForm_k6hui_134{flex-basis:100%;order:3}._pane_k6hui_8[data-compact] ._section_k6hui_322{padding-left:var(--space-3);padding-right:var(--space-3)}._pane_k6hui_8[data-compact] ._markdown_k6hui_308{padding:var(--space-3)}._pane_k6hui_8[data-compact] ._tab_k6hui_28{max-width:150px}@media (prefers-reduced-motion:reduce){._pulse_k6hui_208{animation:none}._tabClose_k6hui_78{transition:none}}
@@ -0,0 +1,2 @@
1
+ import{a as e,n as t,s as n}from"./index-oAAq8XJa.js";import{M as r,O as i,a,l as o,s}from"./global-Di2PUgj4.js";import{d as c,f as l,y as u}from"./workbench-types-DzN-5trg.js";import{n as ee}from"./viewport-BEqGUoTA.js";import{i as te,r as ne}from"./section-visibility-qFqc_d4Z.js";import{T as d,l as re,v as ie}from"./icons-B_yuAgdN.js";import{t as f}from"./MessageMarkdown-qWKyJvAQ.js";import{t as ae}from"./Segmented-BL40udoO.js";import{n as p,t as m}from"./Button-DYv_KKxr.js";import{t as h}from"./EmptyState-DhNgDDrF.js";import{a as oe,c as se,d as ce,i as le,l as ue,n as de,o as fe,s as g,t as pe}from"./terminal-icons-DJTK7QpR.js";import{t as me}from"./pane-chrome.module-D7o-fVd0.js";var _=n(e(),1),v=`/api/verse/preview/ticket`;function y(e){return new URLSearchParams(e).toString()}var b={targets:(e,t)=>o(`${l}?${y({sessionId:e})}`,t),ticket:(e,t)=>o(`${v}?${y({sessionId:e,path:t})}`),text:async(e,t)=>{let n=`${c}?${y({sessionId:e,path:t})}`,a=await fetch(n,{credentials:`same-origin`,headers:{"x-ashlr-read-client":i()}});if(a.status===401)throw r(),new s(`Read session expired.`,401,n);if(!a.ok)throw new s(`GET ${n} failed (HTTP ${a.status}).`,a.status,n);return a.text()}};function x(e){return e.port||(e.protocol===`https:`?`443`:`80`)}function S(e,t){let n=e.trim();if(n.length===0||n.length>2048||/\s/.test(n))return{kind:`invalid`};let r=n;if(/^:?\d{2,5}$/.test(n))r=`http://localhost:${n.replace(`:`,``)}/`;else if(/^(?:localhost|127\.0\.0\.1)(?::\d{1,5})?(?:[/?#].*)?$/i.test(n))r=`http://${n}`;else if(!/^[a-z][a-z0-9+.-]*:/i.test(n)){if(!/^[\w-]+(?:\.[\w-]+)+(?::\d{1,5})?(?:[/?#].*)?$/.test(n))return{kind:`invalid`};r=`https://${n}`}let i;try{i=new URL(r)}catch{return{kind:`invalid`}}if(i.protocol!==`http:`&&i.protocol!==`https:`)return{kind:`invalid`};if(u(i.href)){let e=null;try{e=new URL(t)}catch{e=null}return e&&(e.hostname===`localhost`||e.hostname===`127.0.0.1`)&&x(e)===x(i)?{kind:`self`,url:i.href}:{kind:`loopback`,url:i.href}}return i.username||i.password?{kind:`invalid`}:{kind:`external`,url:i.href}}function C(e){try{let t=new URL(e),n=t.pathname===`/`?``:t.pathname;return`${t.host}${n}${t.search}`}catch{return e}}function w(e){return!Number.isFinite(e)||e<0?`—`:e<1024?`${e} B`:e<1048576?`${(e/1024).toFixed(+(e<10240))} KB`:`${(e/1048576).toFixed(1)} MB`}var T={pane:`_pane_k6hui_8`,strip:`_strip_k6hui_19`,tabs:`_tabs_k6hui_28`,tab:`_tab_k6hui_28`,tabButton:`_tabButton_k6hui_60`,tabClose:`_tabClose_k6hui_78`,noticeClose:`_noticeClose_k6hui_79`,external:`_external_k6hui_80`,tabTitle:`_tabTitle_k6hui_85`,newTab:`_newTab_k6hui_118`,toolbar:`_toolbar_k6hui_126`,nav:`_nav_k6hui_128`,addressForm:`_addressForm_k6hui_134`,address:`_address_k6hui_134`,addressNote:`_addressNote_k6hui_177`,notice:`_notice_k6hui_79`,waiting:`_waiting_k6hui_179`,waitingText:`_waitingText_k6hui_201`,pulse:`_pulse_k6hui_208`,body:`_body_k6hui_234`,loading:`_loading_k6hui_243`,stage:`_stage_k6hui_250`,frame:`_frame_k6hui_262`,frameHint:`_frameHint_k6hui_278`,imageStage:`_imageStage_k6hui_291`,image:`_image_k6hui_291`,markdown:`_markdown_k6hui_308`,launcher:`_launcher_k6hui_316`,section:`_section_k6hui_322`,sectionTitle:`_sectionTitle_k6hui_328`,muted:`_muted_k6hui_339`,rows:`_rows_k6hui_347`,row:`_row_k6hui_347`,dot:`_dot_k6hui_364`,fileIcon:`_fileIcon_k6hui_376`,rowMain:`_rowMain_k6hui_378`,rowTitle:`_rowTitle_k6hui_385`,rowMeta:`_rowMeta_k6hui_395`,rowCommand:`_rowCommand_k6hui_405`},E=t(),he={api:b,origin:()=>window.location.origin,now:()=>Date.now()},ge=12e4,_e=2e3,ve=5e3,D=`ashlr.verse.preview.v1:`,O={"launch-json":`launch.json`,"package-json":`package.json`,listening:`running`},ye={html:`HTML`,md:`Markdown`,svg:`SVG`,image:`Image`,pdf:`PDF`},k=0,A=0,j=()=>`p${++A}`;function M(){k=0,A=0}function N(e){let t=e.toLowerCase().slice(e.lastIndexOf(`.`));return t===`.html`||t===`.htm`?`html`:t===`.md`||t===`.markdown`?`md`:t===`.svg`?`svg`:t===`.pdf`?`pdf`:[`.png`,`.jpg`,`.jpeg`,`.gif`,`.webp`,`.avif`,`.bmp`,`.ico`].includes(t)?`image`:null}function P(e){return e.slice(e.lastIndexOf(`/`)+1)||e}function F(e){return e.kind===`launcher`?`New tab`:e.kind===`url`?C(e.history[e.index]??``):P(e.path)}function be(e){return e?.kind===`url`?e.history[e.index]??null:null}function xe(e,t){try{let n=localStorage.getItem(`${D}${e}`);if(!n)return null;let r=JSON.parse(n),i=[],a=null;return Array.isArray(r.tabs)&&r.tabs.slice(0,12).forEach((e,n)=>{if(!e||typeof e!=`object`)return;let o=e,s=j();if(o.url&&typeof o.url==`string`&&S(o.url,t).kind===`loopback`)i.push({id:s,kind:`url`,history:[o.url],index:0,reloadKey:0});else if(typeof o.path==`string`){let e=N(o.path);if(e)i.push({id:s,kind:`artifact`,path:o.path,artifactKind:e,reloadKey:0});else return}else return;r.active===n&&(a=s)}),{tabs:i,activeId:a??i.at(-1)?.id??null,device:r.device===`phone`?`phone`:`desktop`}}catch{return null}}function Se(e,t,n,r){try{let i=t.filter(e=>e.kind!==`launcher`);localStorage.setItem(`${D}${e}`,JSON.stringify({tabs:i.map(e=>e.kind===`url`?{url:e.history[e.index]}:e.kind===`artifact`?{path:e.path}:{}),active:i.findIndex(e=>e.id===n),device:r}))}catch{}}function I({sessionId:e,roots:t,request:n,onOpenTerminal:r,visible:i,deps:a}){let o=(0,_.useMemo)(()=>({...he,...a}),[a]),c=te(),l=i&&c,u=ee().compact,[f]=(0,_.useState)(()=>xe(e,o.origin())),[h,g]=(0,_.useState)(()=>f?.tabs??[]),[v,y]=(0,_.useState)(()=>f?.activeId??null),[b,x]=(0,_.useState)(()=>f?.device??`desktop`),[w,ge]=(0,_.useState)(e),[D,O]=(0,_.useState)(null),[ye,A]=(0,_.useState)(null),[M,P]=(0,_.useState)(``),[I,L]=(0,_.useState)(null),[R,z]=(0,_.useState)(null),[Ee,B]=(0,_.useState)(null),[V,H]=(0,_.useState)(()=>new Map),[De,Oe]=(0,_.useState)(()=>o.now()),U=(0,_.useRef)(!0),W=(0,_.useRef)(new Map),ke=(0,_.useRef)(null);if(w!==e){let t=xe(e,o.origin());ge(e),g(t?.tabs??[]),y(t?.activeId??null),O(null),z(null),B(null)}let G=h.find(e=>e.id===v)??null,K=be(G),q=!G||G.kind===`launcher`;(0,_.useEffect)(()=>(U.current=!0,()=>{U.current=!1}),[]),(0,_.useEffect)(()=>{w===e&&Se(e,h,v,b)},[w,e,h,v,b]),(0,_.useEffect)(()=>{P(G?.kind===`url`?G.history[G.index]??``:G?.kind===`artifact`?G.path:``),L(null)},[G]);let J=(0,_.useCallback)(async()=>{try{let t=await o.api.targets(e);return U.current?(O(t),A(null),t):null}catch(e){return U.current&&A(e instanceof s&&e.detail?e.detail:`Dev servers and files could not be listed.`),null}},[o.api,e]),Ae=(0,_.useRef)(null);(0,_.useEffect)(()=>{l&&Ae.current!==e&&(Ae.current=e,J())},[l,e,J]),ne(()=>{J()},R?_e:ve,{enabled:i&&(R!==null||q)});let Y=(0,_.useCallback)((e,t={})=>{B(null);let n=h.find(e=>e.id===v);if(!t.newTab&&n?.kind===`launcher`){g(h.map(t=>t.id===n.id?{id:t.id,kind:`url`,history:[e],index:0,reloadKey:0}:t));return}let r=h.find(t=>t.kind===`url`&&t.history[t.index]===e);if(r&&!t.newTab){y(r.id);return}let i=j();g([...h,{id:i,kind:`url`,history:[e],index:0,reloadKey:0}]),y(i)},[h,v]),je=(0,_.useCallback)(e=>{if(!G||G.kind!==`url`){Y(e);return}g(t=>t.map(t=>{if(t.id!==G.id||t.kind!==`url`)return t;let n=[...t.history.slice(0,t.index+1),e].slice(-50);return{...t,history:n,index:n.length-1}}))},[G,Y]),X=(0,_.useCallback)((e,t)=>{B(null);let n=h.find(t=>t.kind===`artifact`&&t.path===e);if(n){y(n.id);return}let r=h.find(e=>e.id===v);if(r?.kind===`launcher`){g(h.map(n=>n.id===r.id?{id:n.id,kind:`artifact`,path:e,artifactKind:t,reloadKey:0}:n));return}let i=j();g([...h,{id:i,kind:`artifact`,path:e,artifactKind:t,reloadKey:0}]),y(i)},[h,v]),Me=()=>{let e=h.find(e=>e.kind===`launcher`);if(e)y(e.id);else{let e=j();g(t=>[...t,{id:e,kind:`launcher`}]),y(e)}J()},Ne=e=>{let t=h.findIndex(t=>t.id===e.id),n=h.filter(t=>t.id!==e.id);g(n),H(t=>{let n=new Map(t);for(let r of t.keys())r.startsWith(`${e.id}:`)&&n.delete(r);return n}),v===e.id&&y((n[t]??n[t-1]??null)?.id??null)},Pe=(e,t)=>{let n=-1;if(e.key===`ArrowRight`?n=(t+1)%h.length:e.key===`ArrowLeft`?n=(t-1+h.length)%h.length:e.key===`Home`?n=0:e.key===`End`&&(n=h.length-1),n<0)return;e.preventDefault();let r=h[n];y(r.id),W.current.get(r.id)?.focus()},Fe=(0,_.useCallback)(e=>{B(null),r({root:e.root,devServerId:e.id}),z({server:e,since:o.now()})},[o,r]),Z=(0,_.useCallback)(e=>{e.running?Y(e.url):Fe(e)},[Y,Fe]);(0,_.useEffect)(()=>{if(R&&D){if(D.devServers.find(e=>e.running&&(e.id===R.server.id||e.port===R.server.port))){z(null),Y(R.server.url);return}o.now()-R.since>12e4&&(z(null),B(`Nothing answered on port ${R.server.port} within 2 minutes. Check the terminal for errors.`))}},[D,R,Y,o,De]),(0,_.useEffect)(()=>{if(!R)return;let e=setInterval(()=>Oe(o.now()),1e3);return()=>clearInterval(e)},[R,o]);let Q=(0,_.useCallback)(async e=>{if(e.url){let t=S(e.url,o.origin());t.kind===`loopback`?Y(t.url):L(t);return}if(e.artifactPath){let t=D?.artifacts.find(t=>t.path===e.artifactPath)?.kind??N(e.artifactPath);t?X(e.artifactPath,t):B(`That file cannot be previewed.`);return}if(e.devServerId){let t=(await J()??D)?.devServers.find(t=>t.id===e.devServerId);t?Z(t):B(`That dev server is no longer listed for this chat.`)}},[o,X,Z,Y,J,D]);(0,_.useEffect)(()=>{!n||n.nonce<=k||(k=n.nonce,Q(n))},[n,Q]);let $=G?.kind===`artifact`?`${G.id}:${G.reloadKey}`:null;(0,_.useEffect)(()=>{if(!l||!G||G.kind!==`artifact`||!$||V.has($))return;let t=G,n=$;H(e=>new Map(e).set(n,{status:`loading`})),(t.artifactKind===`md`?o.api.text(e,t.path).then(e=>({status:`text`,text:e})):o.api.ticket(e,t.path).then(e=>({status:`frame`,src:e.url}))).then(e=>{U.current&&H(t=>new Map(t).set(n,e))},e=>{let t=e instanceof s&&e.status===404?`This file is no longer in the chat's folder.`:e instanceof s&&e.status===413?`This file is larger than 5 MB, too large to preview.`:`This file could not be loaded.`;U.current&&H(e=>new Map(e).set(n,{status:`error`,message:t}))})},[l,G,$,V,o.api,e]);let Ie=e=>{G&&G.kind===`url`&&g(t=>t.map(t=>t.id===G.id&&t.kind===`url`?{...t,index:Math.min(t.history.length-1,Math.max(0,t.index+e))}:t))},Le=()=>{if(G){if(G.kind===`launcher`){J();return}g(e=>e.map(e=>e.id===G.id&&e.kind!==`launcher`?{...e,reloadKey:e.reloadKey+1}:e))}},Re=e=>{e.preventDefault();let t=S(M,o.origin());if(t.kind===`loopback`){L(null),G?.kind===`url`?je(t.url):Y(t.url);return}L(t)},ze=e=>{e.key===`Escape`&&(e.preventDefault(),P(K??(G?.kind===`artifact`?G.path:``)),L(null),e.currentTarget.blur())},Be=G?.kind===`url`&&G.index>0,Ve=G?.kind===`url`&&G.index<G.history.length-1;return(0,E.jsxs)(`div`,{className:T.pane,"data-compact":u||void 0,children:[(0,E.jsxs)(`div`,{className:T.strip,children:[(0,E.jsx)(`div`,{className:T.tabs,role:`tablist`,"aria-label":`Previews`,children:h.map((e,t)=>{let n=e.id===v,r=F(e);return(0,E.jsxs)(`div`,{className:T.tab,"data-selected":n||void 0,role:`presentation`,children:[(0,E.jsxs)(`button`,{ref:t=>{t?W.current.set(e.id,t):W.current.delete(e.id)},type:`button`,role:`tab`,id:`preview-tab-${e.id}`,"aria-selected":n,"aria-controls":`preview-panel`,tabIndex:n?0:-1,className:T.tabButton,title:e.kind===`url`?e.history[e.index]:e.kind===`artifact`?e.path:`Choose what to preview`,onClick:()=>y(e.id),onKeyDown:e=>Pe(e,t),children:[e.kind===`artifact`?(0,E.jsx)(oe,{size:12}):e.kind===`url`?(0,E.jsx)(ce,{size:12}):(0,E.jsx)(se,{size:12}),(0,E.jsx)(`span`,{className:T.tabTitle,children:r})]}),(0,E.jsx)(`button`,{type:`button`,className:T.tabClose,"aria-label":`Close preview ${r}`,title:`Close`,onClick:()=>Ne(e),children:(0,E.jsx)(d,{size:12})})]},e.id)})}),(0,E.jsx)(p,{variant:`ghost`,size:`sm`,icon:(0,E.jsx)(ie,{}),"aria-label":`New preview tab`,title:`New preview tab`,className:T.newTab,onClick:Me})]}),(0,E.jsxs)(`div`,{className:`${me.header} ${T.toolbar}`,children:[(0,E.jsxs)(`div`,{className:T.nav,children:[(0,E.jsx)(p,{variant:`ghost`,size:`sm`,icon:(0,E.jsx)(pe,{}),"aria-label":`Back`,title:`Back`,disabled:!Be,onClick:()=>Ie(-1)}),(0,E.jsx)(p,{variant:`ghost`,size:`sm`,icon:(0,E.jsx)(de,{}),"aria-label":`Forward`,title:`Forward`,disabled:!Ve,onClick:()=>Ie(1)}),(0,E.jsx)(p,{variant:`ghost`,size:`sm`,icon:(0,E.jsx)(ue,{}),"aria-label":q?`Refresh the list`:`Reload`,title:q?`Refresh the list`:`Reload`,disabled:!G&&q&&D===null,onClick:Le})]}),(0,E.jsx)(`form`,{className:T.addressForm,onSubmit:Re,role:`search`,"aria-label":`Preview address`,children:(0,E.jsx)(`input`,{ref:ke,className:T.address,value:M,onChange:e=>P(e.target.value),onKeyDown:ze,onFocus:e=>e.currentTarget.select(),placeholder:`localhost:5173`,"aria-label":`Address`,spellCheck:!1,autoCapitalize:`off`,autoCorrect:`off`,inputMode:`url`,readOnly:G?.kind===`artifact`})}),(0,E.jsxs)(`div`,{className:me.actions,children:[u?null:(0,E.jsx)(ae,{"aria-label":`Frame width`,size:`sm`,value:b,onChange:x,options:[{value:`desktop`,label:(0,E.jsx)(le,{size:14}),ariaLabel:`Desktop width`},{value:`phone`,label:(0,E.jsx)(fe,{size:14}),ariaLabel:`375 px width`}]}),K?(0,E.jsx)(`a`,{className:T.external,href:K,target:`_blank`,rel:`noopener noreferrer`,"aria-label":`Open in browser`,title:`Open in browser`,children:(0,E.jsx)(re,{})}):(0,E.jsx)(`span`,{className:T.external,"data-placeholder":`true`,"aria-hidden":`true`})]})]}),I?(0,E.jsx)(Ce,{note:I,onDismiss:()=>L(null)}):null,R?(0,E.jsxs)(`div`,{className:T.waiting,role:`status`,children:[(0,E.jsx)(`span`,{className:T.pulse,"aria-hidden":`true`}),(0,E.jsxs)(`span`,{className:T.waitingText,children:[`Starting `,(0,E.jsx)(`code`,{children:R.server.command??R.server.label}),` — waiting for `,C(R.server.url),` · `,Math.max(0,Math.round((De-R.since)/1e3)),`s`]}),(0,E.jsx)(m,{size:`sm`,variant:`ghost`,onClick:()=>z(null),children:`Stop waiting`})]}):null,Ee?(0,E.jsxs)(`div`,{className:T.notice,role:`alert`,children:[(0,E.jsx)(`span`,{children:Ee}),(0,E.jsx)(`button`,{type:`button`,className:T.noticeClose,"aria-label":`Dismiss`,title:`Dismiss`,onClick:()=>B(null),children:(0,E.jsx)(d,{size:12})})]}):null,(0,E.jsx)(`div`,{className:T.body,id:`preview-panel`,role:`tabpanel`,"aria-labelledby":G?`preview-tab-${G.id}`:void 0,children:q?(0,E.jsx)(Te,{targets:D,error:ye,roots:t,onOpenServer:Z,onOpenArtifact:e=>X(e.path,e.kind),onRetry:()=>void J(),onOpenTerminal:()=>r(t[0]?{root:t[0]}:{}),waitingId:R?.server.id??null}):G?.kind===`url`?(0,E.jsxs)(`div`,{className:T.stage,"data-device":b,children:[(0,E.jsx)(`iframe`,{className:T.frame,src:G.history[G.index],title:`Preview of ${F(G)}`,sandbox:`allow-scripts allow-same-origin allow-forms allow-popups allow-modals allow-downloads`,referrerPolicy:`no-referrer`},`${G.id}:${G.index}:${G.reloadKey}`),(0,E.jsxs)(`p`,{className:T.frameHint,children:[`Blank page? Some servers refuse to be framed.`,` `,(0,E.jsx)(`a`,{href:G.history[G.index],target:`_blank`,rel:`noopener noreferrer`,children:`Open in browser ↗`})]})]}):G?.kind===`artifact`?(0,E.jsx)(we,{tab:G,content:$?V.get($)??{status:`loading`}:{status:`loading`},device:b,onRetry:Le}):null})]})}function Ce({note:e,onDismiss:t}){return(0,E.jsxs)(`div`,{className:T.addressNote,role:`status`,children:[e.kind===`external`?(0,E.jsxs)(`span`,{children:[`Only local dev servers open here.`,` `,(0,E.jsx)(`a`,{href:e.url,target:`_blank`,rel:`noopener noreferrer`,children:`Open in browser ↗`})]}):e.kind===`self`?(0,E.jsx)(`span`,{children:`That address is Verse itself.`}):(0,E.jsxs)(`span`,{children:[`Enter a local address, like `,(0,E.jsx)(`code`,{children:`localhost:5173`}),`.`]}),(0,E.jsx)(`button`,{type:`button`,className:T.noticeClose,"aria-label":`Dismiss`,title:`Dismiss`,onClick:t,children:(0,E.jsx)(d,{size:12})})]})}function we({tab:e,content:t,device:n,onRetry:r}){return t.status===`loading`?(0,E.jsxs)(`div`,{className:T.loading,"aria-busy":`true`,children:[(0,E.jsx)(a,{width:`50%`}),(0,E.jsx)(a,{width:`80%`})]}):t.status===`error`?(0,E.jsx)(h,{compact:!0,tone:`error`,title:`Preview unavailable`,body:t.message,action:(0,E.jsx)(m,{size:`sm`,variant:`subtle`,onClick:r,children:`Try again`})}):t.status===`text`?(0,E.jsx)(`article`,{className:T.markdown,"aria-label":e.path,children:(0,E.jsx)(f,{text:t.text})}):e.artifactKind===`image`?(0,E.jsx)(`div`,{className:T.imageStage,children:(0,E.jsx)(`img`,{className:T.image,src:t.src,alt:P(e.path)})}):(0,E.jsx)(`div`,{className:T.stage,"data-device":e.artifactKind===`pdf`?`desktop`:n,children:(0,E.jsx)(`iframe`,{className:T.frame,src:t.src,title:`Preview of ${e.path}`,...e.artifactKind===`pdf`?{}:{sandbox:`allow-scripts`},referrerPolicy:`no-referrer`},t.src)})}function Te({targets:e,error:t,roots:n,onOpenServer:r,onOpenArtifact:i,onRetry:o,onOpenTerminal:s,waitingId:c}){if(!e)return t?(0,E.jsx)(h,{compact:!0,tone:`error`,title:`Could not list what to preview`,body:t,action:(0,E.jsx)(m,{size:`sm`,variant:`subtle`,onClick:o,children:`Try again`})}):(0,E.jsxs)(`div`,{className:T.loading,"aria-busy":`true`,children:[(0,E.jsx)(a,{width:`35%`}),(0,E.jsx)(a,{width:`70%`}),(0,E.jsx)(a,{width:`60%`})]});let l=n.length>1;return e.devServers.length===0&&e.artifacts.length===0?(0,E.jsx)(h,{compact:!0,icon:(0,E.jsx)(se,{size:20}),title:`Nothing to preview yet`,body:`Start a dev server in the terminal, or ask for an HTML report. Local servers and the files this chat writes show up here.`,action:(0,E.jsx)(m,{size:`sm`,variant:`subtle`,onClick:s,children:`Open a terminal`})}):(0,E.jsxs)(`div`,{className:T.launcher,children:[(0,E.jsxs)(`section`,{className:T.section,"aria-labelledby":`preview-servers-title`,children:[(0,E.jsx)(`h3`,{className:T.sectionTitle,id:`preview-servers-title`,children:`Dev servers`}),e.devServers.length===0?(0,E.jsxs)(`p`,{className:T.muted,children:[`No dev server found in this chat's folders. Add one to `,(0,E.jsx)(`code`,{children:`.claude/launch.json`}),`, or start it in the terminal.`]}):(0,E.jsx)(`ul`,{className:T.rows,children:e.devServers.map(e=>(0,E.jsxs)(`li`,{className:T.row,children:[(0,E.jsx)(`span`,{className:T.dot,"data-running":e.running||void 0,"aria-hidden":`true`}),(0,E.jsxs)(`span`,{className:T.rowMain,children:[(0,E.jsx)(`span`,{className:T.rowTitle,title:e.label,children:e.label}),(0,E.jsxs)(`span`,{className:T.rowMeta,title:`${C(e.url)} · ${e.running?`running`:`stopped`} · ${O[e.source]}${l?` · ${e.root}`:``}`,children:[C(e.url),` · `,e.running?`running`:`stopped`,` · `,O[e.source],l?` · ${P(e.root)}`:``]}),!e.running&&e.command&&e.command!==e.label?(0,E.jsx)(`code`,{className:T.rowCommand,title:e.command,children:e.command}):null]}),e.running?(0,E.jsx)(m,{size:`sm`,variant:`subtle`,onClick:()=>r(e),"aria-label":`Open ${e.label}`,children:`Open`}):(0,E.jsx)(m,{size:`sm`,variant:`subtle`,icon:(0,E.jsx)(g,{size:12}),busy:c===e.id,onClick:()=>r(e),"aria-label":`Start ${e.label}`,title:`Runs ${e.command??e.label} in a terminal tab`,children:`Start`})]},e.id))})]}),(0,E.jsxs)(`section`,{className:T.section,"aria-labelledby":`preview-files-title`,children:[(0,E.jsx)(`h3`,{className:T.sectionTitle,id:`preview-files-title`,children:`This chat's files`}),e.artifacts.length===0?(0,E.jsx)(`p`,{className:T.muted,children:`Ask the chat for a report or a page: HTML, Markdown, SVG, images and PDFs it writes appear here.`}):(0,E.jsx)(`ul`,{className:T.rows,children:e.artifacts.map(e=>{let t=e.bytes>5242880;return(0,E.jsxs)(`li`,{className:T.row,children:[(0,E.jsx)(oe,{size:14,className:T.fileIcon}),(0,E.jsxs)(`span`,{className:T.rowMain,children:[(0,E.jsx)(`span`,{className:T.rowTitle,title:e.path,children:e.path}),(0,E.jsxs)(`span`,{className:T.rowMeta,children:[ye[e.kind],` · `,w(e.bytes)]})]}),(0,E.jsx)(m,{size:`sm`,variant:`subtle`,disabled:t,title:t?`Larger than 5 MB`:void 0,onClick:()=>i(e),"aria-label":`Open ${e.path}`,children:`Open`})]},e.path)})})]})]})}export{ge as PREVIEW_START_TIMEOUT_MS,I as PreviewPane,M as resetPreviewPaneForTest};
2
+ //# sourceMappingURL=PreviewPane-kzbbSK4u.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PreviewPane-kzbbSK4u.js","names":[],"sources":["../../../../../../src/web-ui/routes/verse/dock/preview/preview-client.ts","../../../../../../src/web-ui/routes/verse/dock/preview/PreviewPane.module.css","../../../../../../src/web-ui/routes/verse/dock/preview/PreviewPane.tsx"],"sourcesContent":["/**\n * dock/preview/preview-client.ts — the Preview pane's reads (unit C4) and the\n * address-bar rule.\n *\n * Every call is a header-authenticated GET. An artifact shown in an <iframe>\n * or <img> goes through a short-lived FRAME TICKET (preview.ts \"WHY\n * TICKETS\"): the element's own request cannot carry the read-client header.\n */\nimport type { VersePreviewArtifactKind, VersePreviewTargetsResponse } from '../../../../data/api-types.js';\nimport { getReadClientProof, reportSessionExpired } from '../../../../data/auth-store.js';\nimport { ApiError, apiGet } from '../../../../data/client.js';\nimport {\n VERSE_PREVIEW_RAW_PATH,\n VERSE_PREVIEW_TARGETS_PATH,\n isLoopbackPreviewUrl,\n} from '../../../../../core/verse/workbench-types.js';\n\nexport const VERSE_PREVIEW_TICKET_PATH = '/api/verse/preview/ticket';\n\nexport interface PreviewTicket {\n url: string;\n expiresAt: string;\n kind: VersePreviewArtifactKind;\n}\n\nexport interface PreviewApi {\n targets(sessionId: string, signal?: AbortSignal): Promise<VersePreviewTargetsResponse>;\n ticket(sessionId: string, path: string): Promise<PreviewTicket>;\n /** A markdown artifact's text (rendered by the pane, sanitised). */\n text(sessionId: string, path: string): Promise<string>;\n}\n\nfunction query(params: Record<string, string>): string {\n return new URLSearchParams(params).toString();\n}\n\nexport const previewApi: PreviewApi = {\n targets: (sessionId, signal) => apiGet<VersePreviewTargetsResponse>(`${VERSE_PREVIEW_TARGETS_PATH}?${query({ sessionId })}`, signal),\n ticket: (sessionId, path) => apiGet<PreviewTicket>(`${VERSE_PREVIEW_TICKET_PATH}?${query({ sessionId, path })}`),\n text: async (sessionId, path) => {\n const url = `${VERSE_PREVIEW_RAW_PATH}?${query({ sessionId, path })}`;\n const res = await fetch(url, { credentials: 'same-origin', headers: { 'x-ashlr-read-client': getReadClientProof() } });\n if (res.status === 401) {\n reportSessionExpired();\n throw new ApiError('Read session expired.', 401, url);\n }\n if (!res.ok) throw new ApiError(`GET ${url} failed (HTTP ${res.status}).`, res.status, url);\n return res.text();\n },\n};\n\n// ---------------------------------------------------------------------------\n// The address bar\n// ---------------------------------------------------------------------------\n\nexport type PreviewAddress =\n | { kind: 'loopback'; url: string }\n /** Not loopback http: offered as \"Open in browser ↗\", never framed. */\n | { kind: 'external'; url: string }\n /** Verse's own server: it refuses to be framed, and framing it would only confuse. */\n | { kind: 'self'; url: string }\n | { kind: 'invalid' };\n\nfunction portOf(url: URL): string {\n return url.port || (url.protocol === 'https:' ? '443' : '80');\n}\n\n/**\n * What the operator typed → where it goes. Shorthands: `5173` and `:5173`\n * are localhost ports; `localhost:3000/x` gets `http://`. A bare domain is an\n * EXTERNAL https page. Anything that is not http(s) (javascript:, file:,\n * data:) is invalid. `verseOrigin` is `window.location.origin`.\n */\nexport function parsePreviewAddress(input: string, verseOrigin: string): PreviewAddress {\n const raw = input.trim();\n if (raw.length === 0 || raw.length > 2048 || /\\s/.test(raw)) return { kind: 'invalid' };\n let candidate = raw;\n if (/^:?\\d{2,5}$/.test(raw)) candidate = `http://localhost:${raw.replace(':', '')}/`;\n else if (/^(?:localhost|127\\.0\\.0\\.1)(?::\\d{1,5})?(?:[/?#].*)?$/i.test(raw)) candidate = `http://${raw}`;\n else if (!/^[a-z][a-z0-9+.-]*:/i.test(raw)) {\n if (!/^[\\w-]+(?:\\.[\\w-]+)+(?::\\d{1,5})?(?:[/?#].*)?$/.test(raw)) return { kind: 'invalid' };\n candidate = `https://${raw}`;\n }\n let url: URL;\n try {\n url = new URL(candidate);\n } catch {\n return { kind: 'invalid' };\n }\n if (url.protocol !== 'http:' && url.protocol !== 'https:') return { kind: 'invalid' };\n if (isLoopbackPreviewUrl(url.href)) {\n let verse: URL | null = null;\n try { verse = new URL(verseOrigin); } catch { verse = null; }\n const loopbackVerse = verse && (verse.hostname === 'localhost' || verse.hostname === '127.0.0.1');\n if (loopbackVerse && portOf(verse!) === portOf(url)) return { kind: 'self', url: url.href };\n return { kind: 'loopback', url: url.href };\n }\n if (url.username || url.password) return { kind: 'invalid' };\n return { kind: 'external', url: url.href };\n}\n\n/** \"localhost:5173/admin\" — the tab and history label for a loopback URL. */\nexport function shortUrl(href: string): string {\n try {\n const url = new URL(href);\n const path = url.pathname === '/' ? '' : url.pathname;\n return `${url.host}${path}${url.search}`;\n } catch {\n return href;\n }\n}\n\nexport function formatBytes(bytes: number): string {\n if (!Number.isFinite(bytes) || bytes < 0) return '—';\n if (bytes < 1024) return `${bytes} B`;\n if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(bytes < 10 * 1024 ? 1 : 0)} KB`;\n return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;\n}\n","/*\n * dock/preview/PreviewPane.module.css — the Preview pane (unit C4).\n * Tokens only (design/style-scan-310: no raw hex, no px font sizes). The\n * chrome (tab strip, toolbar) matches the Terminal pane so the two read as\n * one dock when split.\n */\n\n.pane {\n display: flex;\n flex-direction: column;\n height: 100%;\n min-height: 0;\n background: var(--bg-canvas);\n color: var(--text-primary);\n}\n\n/* ---- tab strip ------------------------------------------------------------ */\n\n.strip {\n display: flex;\n align-items: stretch;\n flex: none;\n min-height: var(--control-h-sm);\n border-bottom: 1px solid var(--border-subtle);\n background: var(--bg-surface);\n}\n\n.tabs {\n display: flex;\n align-items: stretch;\n min-width: 0;\n overflow-x: auto;\n scrollbar-width: none;\n}\n.tabs::-webkit-scrollbar { display: none; }\n\n.tab {\n position: relative;\n display: flex;\n align-items: center;\n flex: none;\n max-width: 220px;\n border-right: 1px solid var(--border-subtle);\n color: var(--text-secondary);\n}\n.tab[data-selected] {\n color: var(--text-primary);\n background: var(--bg-canvas);\n}\n.tab[data-selected]::after {\n content: '';\n position: absolute;\n left: 0;\n right: 0;\n bottom: -1px;\n height: 2px;\n background: var(--accent-500);\n}\n\n.tabButton {\n display: inline-flex;\n align-items: center;\n gap: var(--space-2);\n min-width: 0;\n height: 100%;\n padding: 0 var(--space-1) 0 var(--space-3);\n border: 0;\n background: transparent;\n color: inherit;\n font-family: var(--font-ui);\n font-size: var(--text-xs-size);\n line-height: var(--text-xs-line);\n cursor: pointer;\n}\n.tabButton > svg { flex: none; color: var(--text-tertiary); }\n.tabButton:hover { color: var(--text-primary); }\n.tabButton:focus-visible,\n.tabClose:focus-visible,\n.noticeClose:focus-visible,\n.external:focus-visible {\n outline: none;\n box-shadow: var(--shadow-focus-ring);\n}\n\n.tabTitle {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.tabClose {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n flex: none;\n /* One step under the xs control: 20px comfortable, 16px compact. A literal\n 20px stayed comfortable when Density went compact and outgrew the\n shrunken tab row (control-density.test.ts, DESIGN-V2 §2). */\n width: calc(var(--control-h-xs) - var(--space-1));\n height: calc(var(--control-h-xs) - var(--space-1));\n margin-right: var(--space-1);\n border: 0;\n border-radius: var(--radius-xs);\n background: transparent;\n color: var(--text-tertiary);\n cursor: pointer;\n opacity: 0;\n transition: opacity var(--duration-fast) var(--ease-standard);\n}\n.tab:hover .tabClose,\n.tab[data-selected] .tabClose,\n.tabClose:focus-visible { opacity: 1; }\n.tabClose:hover { background: var(--bg-hover); color: var(--text-primary); }\n@media (hover: none) {\n .tabClose { opacity: 1; }\n}\n\n.newTab { align-self: center; margin: 0 var(--space-1); }\n\n/* ---- toolbar -------------------------------------------------------------- */\n\n/* Height, padding, border and surface come from ../pane-chrome.module.css\n (the row every dock pane shares); the toolbar only lays out its parts. */\n/* Starts with icon buttons, so a smaller inset than a text title (and scoped\n under .pane so it outranks the shared padding regardless of CSS order). */\n.pane .toolbar { padding-left: var(--space-2); }\n\n.nav {\n display: flex;\n align-items: center;\n flex: none;\n}\n\n.addressForm {\n display: flex;\n flex: 1 1 auto;\n min-width: 0;\n}\n\n.address {\n width: 100%;\n min-width: 0;\n height: var(--control-h-sm);\n padding: 0 var(--space-3);\n border: 1px solid var(--border-default);\n border-radius: var(--radius-full);\n background: var(--bg-input);\n color: var(--text-primary);\n font-family: var(--font-mono);\n font-size: var(--text-xs-size);\n line-height: var(--text-xs-line);\n}\n.address::placeholder { color: var(--text-tertiary); }\n.address:focus {\n outline: none;\n border-color: var(--border-focus);\n box-shadow: var(--shadow-focus-ring);\n}\n.address[readonly] { color: var(--text-secondary); }\n\n.external {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n flex: none;\n width: var(--density-row-sm);\n height: var(--density-row-sm);\n border-radius: var(--radius-sm);\n color: var(--text-secondary);\n}\n.external:hover { background: var(--bg-hover); color: var(--text-primary); }\n/* No page to open elsewhere: the slot keeps its width, so the address bar does not jump. */\n.external[data-placeholder] { visibility: hidden; }\n\n/* ---- notices -------------------------------------------------------------- */\n\n.addressNote,\n.notice,\n.waiting {\n display: flex;\n align-items: center;\n gap: var(--space-2);\n flex: none;\n padding: var(--space-2) var(--space-3);\n border-bottom: 1px solid var(--border-subtle);\n font-size: var(--text-sm-size);\n line-height: var(--text-sm-line);\n}\n.addressNote { background: var(--status-info-bg); color: var(--status-info-fg); }\n.notice { background: var(--status-danger-bg); color: var(--status-danger-fg); }\n.waiting { background: var(--status-running-bg); color: var(--status-running-fg); }\n.addressNote > span,\n.notice > span { flex: 1; min-width: 0; }\n.addressNote a { color: inherit; font-weight: var(--font-weight-semibold); }\n.addressNote code,\n.waiting code {\n font-family: var(--font-mono);\n font-size: var(--text-xs-size);\n}\n\n.waitingText {\n flex: 1;\n min-width: 0;\n font-variant-numeric: tabular-nums;\n}\n\n/* The 1.6 s running pulse (DESIGN §13.5); stops under reduced motion. */\n.pulse {\n flex: none;\n width: 8px;\n height: 8px;\n border-radius: var(--radius-full);\n background: var(--status-running-solid);\n animation: pulse var(--duration-pulse) ease-in-out infinite;\n}\n@keyframes pulse {\n 0%, 100% { opacity: 1; }\n 50% { opacity: 0.35; }\n}\n\n.noticeClose {\n display: inline-flex;\n flex: none;\n padding: var(--space-1);\n border: 0;\n border-radius: var(--radius-xs);\n background: transparent;\n color: inherit;\n cursor: pointer;\n}\n\n/* ---- body ----------------------------------------------------------------- */\n\n.body {\n position: relative;\n display: flex;\n flex-direction: column;\n flex: 1 1 auto;\n min-height: 0;\n overflow: auto;\n}\n\n.loading {\n display: flex;\n flex-direction: column;\n gap: var(--space-2);\n padding: var(--card-pad);\n}\n\n.stage {\n display: flex;\n flex-direction: column;\n align-items: stretch;\n flex: 1 1 auto;\n min-height: 0;\n}\n.stage[data-device='phone'] {\n align-items: center;\n padding: var(--space-3) 0;\n}\n\n.frame {\n flex: 1 1 auto;\n width: 100%;\n min-height: 0;\n border: 0;\n background: var(--bg-surface);\n}\n.stage[data-device='phone'] .frame {\n flex: 1 1 auto;\n width: 375px;\n max-width: 100%;\n border: 1px solid var(--border-default);\n border-radius: var(--radius-lg);\n box-shadow: var(--shadow-md);\n}\n\n.frameHint {\n flex: none;\n margin: 0;\n padding: var(--space-1) var(--space-3);\n border-top: 1px solid var(--border-subtle);\n background: var(--bg-surface);\n font-size: var(--text-2xs-size);\n line-height: var(--text-2xs-line);\n color: var(--text-tertiary);\n}\n.stage[data-device='phone'] .frameHint { align-self: stretch; margin-top: var(--space-3); }\n.frameHint a { color: var(--text-link); }\n\n.imageStage {\n display: flex;\n align-items: center;\n justify-content: center;\n flex: 1 1 auto;\n min-height: 0;\n padding: var(--card-pad);\n background:\n repeating-conic-gradient(var(--bg-hover) 0 25%, transparent 0 50%) 0 0 / 16px 16px,\n var(--bg-surface);\n}\n.image {\n max-width: 100%;\n max-height: 100%;\n object-fit: contain;\n}\n\n.markdown {\n padding: var(--card-pad) var(--space-6);\n max-width: var(--measure-read);\n background: var(--bg-canvas);\n}\n\n/* ---- launcher ------------------------------------------------------------- */\n\n.launcher {\n display: flex;\n flex-direction: column;\n padding-bottom: var(--space-6);\n}\n\n.section { padding: var(--space-4) var(--card-pad) 0; }\n.section + .section {\n margin-top: var(--space-4);\n border-top: 1px solid var(--border-subtle);\n}\n\n.sectionTitle {\n margin: 0 0 var(--space-2);\n font-family: var(--font-display);\n font-size: var(--text-2xs-size);\n line-height: var(--text-2xs-line);\n font-weight: var(--font-weight-semibold);\n letter-spacing: var(--tracking-label);\n text-transform: uppercase;\n color: var(--text-tertiary);\n}\n\n.muted {\n margin: 0;\n font-size: var(--text-sm-size);\n line-height: var(--text-sm-line);\n color: var(--text-tertiary);\n}\n.muted code { font-family: var(--font-mono); font-size: var(--text-xs-size); }\n\n.rows {\n display: flex;\n flex-direction: column;\n margin: 0;\n padding: 0;\n list-style: none;\n}\n\n.row {\n display: flex;\n align-items: center;\n gap: var(--space-3);\n min-height: var(--density-row);\n padding: var(--space-2) 0;\n}\n.row + .row { border-top: 1px solid var(--border-subtle); }\n\n.dot {\n flex: none;\n width: 8px;\n height: 8px;\n border: 1.5px solid var(--text-tertiary);\n border-radius: var(--radius-full);\n}\n.dot[data-running] {\n border-color: var(--status-success-solid);\n background: var(--status-success-solid);\n}\n\n.fileIcon { flex: none; color: var(--text-tertiary); }\n\n.rowMain {\n display: flex;\n flex-direction: column;\n flex: 1 1 auto;\n min-width: 0;\n}\n\n.rowTitle {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n font-family: var(--font-mono);\n font-size: var(--text-sm-size);\n line-height: var(--text-sm-line);\n color: var(--text-primary);\n}\n\n.rowMeta {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n font-size: var(--text-xs-size);\n line-height: var(--text-xs-line);\n color: var(--text-tertiary);\n}\n\n/* What Start will type (a launch.json row's label is only its name). */\n.rowCommand {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n font-family: var(--font-mono);\n font-size: var(--text-xs-size);\n line-height: var(--text-xs-line);\n color: var(--text-secondary);\n}\n\n/* ---- compact (375) -------------------------------------------------------- */\n\n.pane[data-compact] .toolbar { flex-wrap: wrap; }\n.pane[data-compact] .addressForm { order: 3; flex-basis: 100%; }\n.pane[data-compact] .section { padding-left: var(--space-3); padding-right: var(--space-3); }\n.pane[data-compact] .markdown { padding: var(--space-3); }\n.pane[data-compact] .tab { max-width: 150px; }\n\n@media (prefers-reduced-motion: reduce) {\n .pulse { animation: none; }\n .tabClose { transition: none; }\n}\n","/**\n * dock/preview/PreviewPane.tsx — the chat dock's Preview (unit C4; SPEC-310C\n * §3). Rendered by C2's Dock through C0's `preview-pane` slot.\n *\n * WHAT IT SHOWS, in tabs:\n * - a LOOPBACK dev server (http://localhost / 127.0.0.1 only) in an iframe,\n * with back / forward / reload, an address bar, and a Desktop / 375 frame;\n * anything else typed in the bar is offered as \"Open in browser ↗\";\n * - a file this chat WROTE — HTML, SVG, image, PDF through a short-lived\n * frame ticket and a CSP sandbox (an opaque origin: its own script runs,\n * Verse's cookies and API stay out of reach); Markdown rendered here,\n * sanitised, like a chat message.\n * An empty pane (or the + tab) is the launcher: the dev servers found in the\n * chat's folders — launch.json, package.json scripts, and anything already\n * listening inside them — and the chat's files. Start runs the server in a\n * TERMINAL tab (through the dock, never directly), then waits for its port\n * and opens it.\n *\n * WHAT THE FRAMES MAY DO. A dev server is a different origin (another port),\n * so `allow-same-origin` gives it ITS origin, never Verse's; the sandbox\n * still withholds top navigation, so a page can never navigate Verse away.\n * Verse's own address is refused outright. Back/forward walk the addresses\n * opened HERE: a cross-origin frame's own history is not readable.\n */\nimport { useCallback, useEffect, useMemo, useRef, useState, type FormEvent, type KeyboardEvent as ReactKeyboardEvent } from 'react';\nimport type { VersePreviewArtifact, VersePreviewArtifactKind, VersePreviewDevServer, VersePreviewTargetsResponse } from '../../../../data/api-types.js';\nimport { ApiError } from '../../../../data/client.js';\nimport { Button, IconButton } from '../../../../components/primitives/Button.js';\nimport { EmptyState } from '../../../../components/primitives/EmptyState.js';\nimport { Segmented } from '../../../../components/primitives/Segmented.js';\nimport { SkeletonLine } from '../../../../components/primitives/Skeleton.js';\nimport { IconExternalLink, IconPlus, IconX } from '../../../../components/primitives/icons.js';\nimport { MessageMarkdown } from '../../MessageMarkdown.js';\nimport { usePollWhileVisible, useSectionVisible } from '../../shell/section-visibility.js';\nimport type { PreviewOpenRequest, PreviewPaneProps } from '../../shell/slots.js';\nimport { useViewport } from '../../shell/viewport.js';\nimport {\n ArrowLeftGlyph,\n ArrowRightGlyph,\n DesktopGlyph,\n FileGlyph,\n PhoneGlyph,\n PlayGlyph,\n PreviewGlyph,\n ReloadGlyph,\n ServerGlyph,\n} from '../terminal/terminal-icons.js';\nimport { formatBytes, parsePreviewAddress, previewApi, shortUrl, type PreviewAddress, type PreviewApi } from './preview-client.js';\nimport chrome from '../pane-chrome.module.css';\nimport styles from './PreviewPane.module.css';\n\n// ---------------------------------------------------------------------------\n// Model\n// ---------------------------------------------------------------------------\n\nexport type PreviewTab =\n | { id: string; kind: 'launcher' }\n | { id: string; kind: 'url'; history: string[]; index: number; reloadKey: number }\n | { id: string; kind: 'artifact'; path: string; artifactKind: VersePreviewArtifactKind; reloadKey: number };\n\ntype Device = 'desktop' | 'phone';\n\ninterface Waiting {\n server: VersePreviewDevServer;\n since: number;\n}\n\ntype ArtifactContent =\n | { status: 'loading' }\n | { status: 'frame'; src: string }\n | { status: 'text'; text: string }\n | { status: 'error'; message: string };\n\nexport interface PreviewPaneDeps {\n api: PreviewApi;\n /** `window.location.origin`: Verse's own address, which is never framed. */\n origin: () => string;\n now: () => number;\n}\n\nconst DEFAULT_DEPS: PreviewPaneDeps = {\n api: previewApi,\n origin: () => window.location.origin,\n now: () => Date.now(),\n};\n\n/** How long Start waits for the server's port before saying so. */\nexport const PREVIEW_START_TIMEOUT_MS = 120_000;\nconst WAIT_POLL_MS = 2_000;\nconst LAUNCHER_POLL_MS = 5_000;\nconst STORAGE_PREFIX = 'ashlr.verse.preview.v1:';\nconst SOURCE_LABEL: Readonly<Record<VersePreviewDevServer['source'], string>> = {\n 'launch-json': 'launch.json',\n 'package-json': 'package.json',\n listening: 'running',\n};\nconst KIND_LABEL: Readonly<Record<VersePreviewArtifactKind, string>> = {\n html: 'HTML',\n md: 'Markdown',\n svg: 'SVG',\n image: 'Image',\n pdf: 'PDF',\n};\n\nlet lastHandledNonce = 0;\nlet idCounter = 0;\nconst nextId = (): string => `p${++idCounter}`;\n\n/** Test hygiene. */\nexport function resetPreviewPaneForTest(): void {\n lastHandledNonce = 0;\n idCounter = 0;\n}\n\nfunction kindFromPath(path: string): VersePreviewArtifactKind | null {\n const ext = path.toLowerCase().slice(path.lastIndexOf('.'));\n if (ext === '.html' || ext === '.htm') return 'html';\n if (ext === '.md' || ext === '.markdown') return 'md';\n if (ext === '.svg') return 'svg';\n if (ext === '.pdf') return 'pdf';\n if (['.png', '.jpg', '.jpeg', '.gif', '.webp', '.avif', '.bmp', '.ico'].includes(ext)) return 'image';\n return null;\n}\n\nfunction baseName(path: string): string {\n return path.slice(path.lastIndexOf('/') + 1) || path;\n}\n\nfunction tabLabel(tab: PreviewTab): string {\n if (tab.kind === 'launcher') return 'New tab';\n if (tab.kind === 'url') return shortUrl(tab.history[tab.index] ?? '');\n return baseName(tab.path);\n}\n\nfunction currentUrl(tab: PreviewTab | null): string | null {\n return tab?.kind === 'url' ? tab.history[tab.index] ?? null : null;\n}\n\n/** Tabs worth restoring after a reload (per viewer, per chat; never shared). */\nfunction loadTabs(sessionId: string, origin: string): { tabs: PreviewTab[]; activeId: string | null; device: Device } | null {\n try {\n const raw = localStorage.getItem(`${STORAGE_PREFIX}${sessionId}`);\n if (!raw) return null;\n const parsed = JSON.parse(raw) as { tabs?: unknown; active?: unknown; device?: unknown };\n const tabs: PreviewTab[] = [];\n let activeId: string | null = null;\n if (Array.isArray(parsed.tabs)) {\n parsed.tabs.slice(0, 12).forEach((t: unknown, i: number) => {\n if (!t || typeof t !== 'object') return;\n const rec = t as Record<string, unknown>;\n const id = nextId();\n if (rec['url'] && typeof rec['url'] === 'string' && parsePreviewAddress(rec['url'], origin).kind === 'loopback') {\n tabs.push({ id, kind: 'url', history: [rec['url']], index: 0, reloadKey: 0 });\n } else if (typeof rec['path'] === 'string') {\n const kind = kindFromPath(rec['path']);\n if (kind) tabs.push({ id, kind: 'artifact', path: rec['path'], artifactKind: kind, reloadKey: 0 });\n else return;\n } else {\n return;\n }\n if (parsed.active === i) activeId = id;\n });\n }\n return { tabs, activeId: activeId ?? tabs.at(-1)?.id ?? null, device: parsed.device === 'phone' ? 'phone' : 'desktop' };\n } catch {\n return null;\n }\n}\n\nfunction saveTabs(sessionId: string, tabs: readonly PreviewTab[], activeId: string | null, device: Device): void {\n try {\n const kept = tabs.filter((t) => t.kind !== 'launcher');\n localStorage.setItem(`${STORAGE_PREFIX}${sessionId}`, JSON.stringify({\n tabs: kept.map((t) => (t.kind === 'url' ? { url: t.history[t.index] } : t.kind === 'artifact' ? { path: t.path } : {})),\n active: kept.findIndex((t) => t.id === activeId),\n device,\n }));\n } catch {\n /* storage unavailable: tabs last for this page only */\n }\n}\n\n// ---------------------------------------------------------------------------\n// Component\n// ---------------------------------------------------------------------------\n\nexport function PreviewPane({ sessionId, roots, request, onOpenTerminal, visible, deps: depsOverride }: PreviewPaneProps & { deps?: Partial<PreviewPaneDeps> }) {\n const deps = useMemo<PreviewPaneDeps>(() => ({ ...DEFAULT_DEPS, ...depsOverride }), [depsOverride]);\n const sectionVisible = useSectionVisible();\n const shown = visible && sectionVisible;\n const compact = useViewport().compact;\n\n const [restored] = useState(() => loadTabs(sessionId, deps.origin()));\n const [tabs, setTabs] = useState<PreviewTab[]>(() => restored?.tabs ?? []);\n const [activeId, setActiveId] = useState<string | null>(() => restored?.activeId ?? null);\n const [device, setDevice] = useState<Device>(() => restored?.device ?? 'desktop');\n // The dock keeps this pane mounted across chats: another chat brings ITS\n // tabs. Reset during render (not in an effect) so the save below never\n // writes one chat's tabs under another chat's key.\n const [owner, setOwner] = useState(sessionId);\n const [targets, setTargets] = useState<VersePreviewTargetsResponse | null>(null);\n const [targetsError, setTargetsError] = useState<string | null>(null);\n const [address, setAddress] = useState('');\n const [addressNote, setAddressNote] = useState<PreviewAddress | null>(null);\n const [waiting, setWaiting] = useState<Waiting | null>(null);\n const [notice, setNotice] = useState<string | null>(null);\n const [content, setContent] = useState<ReadonlyMap<string, ArtifactContent>>(() => new Map());\n const [clock, setClock] = useState(() => deps.now());\n const mounted = useRef(true);\n const tabRefs = useRef(new Map<string, HTMLButtonElement>());\n const addressRef = useRef<HTMLInputElement>(null);\n\n if (owner !== sessionId) {\n const next = loadTabs(sessionId, deps.origin());\n setOwner(sessionId);\n setTabs(next?.tabs ?? []);\n setActiveId(next?.activeId ?? null);\n setTargets(null);\n setWaiting(null);\n setNotice(null);\n }\n\n const active = tabs.find((t) => t.id === activeId) ?? null;\n const url = currentUrl(active);\n const showLauncher = !active || active.kind === 'launcher';\n\n useEffect(() => {\n mounted.current = true;\n return () => { mounted.current = false; };\n }, []);\n\n useEffect(() => {\n if (owner === sessionId) saveTabs(sessionId, tabs, activeId, device);\n }, [owner, sessionId, tabs, activeId, device]);\n\n // The address bar mirrors the tab shown.\n useEffect(() => {\n setAddress(active?.kind === 'url' ? (active.history[active.index] ?? '') : active?.kind === 'artifact' ? active.path : '');\n setAddressNote(null);\n }, [active]);\n\n // -------------------------------------------------------------------------\n // Targets\n // -------------------------------------------------------------------------\n\n const refreshTargets = useCallback(async (): Promise<VersePreviewTargetsResponse | null> => {\n try {\n const next = await deps.api.targets(sessionId);\n if (!mounted.current) return null;\n setTargets(next);\n setTargetsError(null);\n return next;\n } catch (err) {\n if (mounted.current) setTargetsError(err instanceof ApiError && err.detail ? err.detail : 'Dev servers and files could not be listed.');\n return null;\n }\n }, [deps.api, sessionId]);\n\n const fetchedFor = useRef<string | null>(null);\n useEffect(() => {\n if (!shown || fetchedFor.current === sessionId) return;\n fetchedFor.current = sessionId;\n void refreshTargets();\n }, [shown, sessionId, refreshTargets]);\n\n usePollWhileVisible(() => { void refreshTargets(); }, waiting ? WAIT_POLL_MS : LAUNCHER_POLL_MS, {\n enabled: visible && (waiting !== null || showLauncher),\n });\n\n // -------------------------------------------------------------------------\n // Tabs\n // -------------------------------------------------------------------------\n\n const openUrl = useCallback((href: string, opts: { newTab?: boolean } = {}) => {\n setNotice(null);\n const current = tabs.find((t) => t.id === activeId);\n // Reuse the launcher tab the operator is looking at; otherwise focus an\n // existing tab on that address, or open a new one.\n if (!opts.newTab && current?.kind === 'launcher') {\n setTabs(tabs.map((t) => (t.id === current.id ? { id: t.id, kind: 'url', history: [href], index: 0, reloadKey: 0 } : t)));\n return;\n }\n const existing = tabs.find((t) => t.kind === 'url' && t.history[t.index] === href);\n if (existing && !opts.newTab) {\n setActiveId(existing.id);\n return;\n }\n const id = nextId();\n setTabs([...tabs, { id, kind: 'url', history: [href], index: 0, reloadKey: 0 }]);\n setActiveId(id);\n }, [tabs, activeId]);\n\n const navigateActive = useCallback((href: string) => {\n if (!active || active.kind !== 'url') {\n openUrl(href);\n return;\n }\n setTabs((prev) => prev.map((t) => {\n if (t.id !== active.id || t.kind !== 'url') return t;\n const history = [...t.history.slice(0, t.index + 1), href].slice(-50);\n return { ...t, history, index: history.length - 1 };\n }));\n }, [active, openUrl]);\n\n const openArtifact = useCallback((path: string, kind: VersePreviewArtifactKind) => {\n setNotice(null);\n const existing = tabs.find((t) => t.kind === 'artifact' && t.path === path);\n if (existing) {\n setActiveId(existing.id);\n return;\n }\n const current = tabs.find((t) => t.id === activeId);\n if (current?.kind === 'launcher') {\n setTabs(tabs.map((t) => (t.id === current.id ? { id: t.id, kind: 'artifact', path, artifactKind: kind, reloadKey: 0 } : t)));\n return;\n }\n const id = nextId();\n setTabs([...tabs, { id, kind: 'artifact', path, artifactKind: kind, reloadKey: 0 }]);\n setActiveId(id);\n }, [tabs, activeId]);\n\n const newLauncherTab = () => {\n const existing = tabs.find((t) => t.kind === 'launcher');\n if (existing) {\n setActiveId(existing.id);\n } else {\n const id = nextId();\n setTabs((prev) => [...prev, { id, kind: 'launcher' }]);\n setActiveId(id);\n }\n void refreshTargets();\n };\n\n const closeTab = (tab: PreviewTab) => {\n const index = tabs.findIndex((t) => t.id === tab.id);\n const rest = tabs.filter((t) => t.id !== tab.id);\n setTabs(rest);\n setContent((prev) => { const next = new Map(prev); for (const key of prev.keys()) if (key.startsWith(`${tab.id}:`)) next.delete(key); return next; });\n if (activeId === tab.id) setActiveId((rest[index] ?? rest[index - 1] ?? null)?.id ?? null);\n };\n\n const onTabKeyDown = (event: ReactKeyboardEvent<HTMLButtonElement>, index: number) => {\n let next = -1;\n if (event.key === 'ArrowRight') next = (index + 1) % tabs.length;\n else if (event.key === 'ArrowLeft') next = (index - 1 + tabs.length) % tabs.length;\n else if (event.key === 'Home') next = 0;\n else if (event.key === 'End') next = tabs.length - 1;\n if (next < 0) return;\n event.preventDefault();\n const tab = tabs[next]!;\n setActiveId(tab.id);\n tabRefs.current.get(tab.id)?.focus();\n };\n\n // -------------------------------------------------------------------------\n // Dev servers: open, start, wait\n // -------------------------------------------------------------------------\n\n const startServer = useCallback((server: VersePreviewDevServer) => {\n setNotice(null);\n onOpenTerminal({ root: server.root, devServerId: server.id });\n setWaiting({ server, since: deps.now() });\n }, [deps, onOpenTerminal]);\n\n const openServer = useCallback((server: VersePreviewDevServer) => {\n if (server.running) openUrl(server.url);\n else startServer(server);\n }, [openUrl, startServer]);\n\n // Waiting for a started server: open it the moment its port answers.\n useEffect(() => {\n if (!waiting || !targets) return;\n const up = targets.devServers.find((s) => s.running && (s.id === waiting.server.id || s.port === waiting.server.port));\n if (up) {\n setWaiting(null);\n openUrl(waiting.server.url);\n return;\n }\n if (deps.now() - waiting.since > PREVIEW_START_TIMEOUT_MS) {\n setWaiting(null);\n setNotice(`Nothing answered on port ${waiting.server.port} within 2 minutes. Check the terminal for errors.`);\n }\n // `clock` ticks every second while waiting, so the timeout is noticed\n // even when a poll brings nothing new.\n }, [targets, waiting, openUrl, deps, clock]);\n\n // The elapsed-time label while waiting (display only; the poll is separate).\n useEffect(() => {\n if (!waiting) return;\n const id = setInterval(() => setClock(deps.now()), 1_000);\n return () => clearInterval(id);\n }, [waiting, deps]);\n\n // -------------------------------------------------------------------------\n // Requests from the dock\n // -------------------------------------------------------------------------\n\n const handleRequest = useCallback(async (req: PreviewOpenRequest) => {\n if (req.url) {\n const parsed = parsePreviewAddress(req.url, deps.origin());\n if (parsed.kind === 'loopback') openUrl(parsed.url);\n else setAddressNote(parsed);\n return;\n }\n if (req.artifactPath) {\n const listed = targets?.artifacts.find((a) => a.path === req.artifactPath);\n const kind = listed?.kind ?? kindFromPath(req.artifactPath);\n if (kind) openArtifact(req.artifactPath, kind);\n else setNotice('That file cannot be previewed.');\n return;\n }\n if (req.devServerId) {\n const list = (await refreshTargets()) ?? targets;\n const server = list?.devServers.find((s) => s.id === req.devServerId);\n if (server) openServer(server);\n else setNotice('That dev server is no longer listed for this chat.');\n }\n }, [deps, openArtifact, openServer, openUrl, refreshTargets, targets]);\n\n useEffect(() => {\n if (!request || request.nonce <= lastHandledNonce) return;\n lastHandledNonce = request.nonce;\n void handleRequest(request);\n }, [request, handleRequest]);\n\n // -------------------------------------------------------------------------\n // Artifact content (visible tab only)\n // -------------------------------------------------------------------------\n\n const contentKey = active?.kind === 'artifact' ? `${active.id}:${active.reloadKey}` : null;\n useEffect(() => {\n if (!shown || !active || active.kind !== 'artifact' || !contentKey || content.has(contentKey)) return;\n const tab = active;\n const key = contentKey;\n setContent((prev) => new Map(prev).set(key, { status: 'loading' }));\n const load = tab.artifactKind === 'md'\n ? deps.api.text(sessionId, tab.path).then((text): ArtifactContent => ({ status: 'text', text }))\n : deps.api.ticket(sessionId, tab.path).then((ticket): ArtifactContent => ({ status: 'frame', src: ticket.url }));\n load.then(\n (value) => { if (mounted.current) setContent((prev) => new Map(prev).set(key, value)); },\n (err: unknown) => {\n const message = err instanceof ApiError && err.status === 404\n ? 'This file is no longer in the chat\\'s folder.'\n : err instanceof ApiError && err.status === 413\n ? 'This file is larger than 5 MB, too large to preview.'\n : 'This file could not be loaded.';\n if (mounted.current) setContent((prev) => new Map(prev).set(key, { status: 'error', message }));\n },\n );\n }, [shown, active, contentKey, content, deps.api, sessionId]);\n\n // -------------------------------------------------------------------------\n // Toolbar\n // -------------------------------------------------------------------------\n\n const go = (delta: -1 | 1) => {\n if (!active || active.kind !== 'url') return;\n setTabs((prev) => prev.map((t) => (t.id === active.id && t.kind === 'url'\n ? { ...t, index: Math.min(t.history.length - 1, Math.max(0, t.index + delta)) }\n : t)));\n };\n\n const reload = () => {\n if (!active) return;\n if (active.kind === 'launcher') {\n void refreshTargets();\n return;\n }\n setTabs((prev) => prev.map((t) => (t.id === active.id && t.kind !== 'launcher' ? { ...t, reloadKey: t.reloadKey + 1 } : t)));\n };\n\n const submitAddress = (event: FormEvent) => {\n event.preventDefault();\n const parsed = parsePreviewAddress(address, deps.origin());\n if (parsed.kind === 'loopback') {\n setAddressNote(null);\n if (active?.kind === 'url') navigateActive(parsed.url);\n else openUrl(parsed.url);\n return;\n }\n setAddressNote(parsed);\n };\n\n const onAddressKeyDown = (event: ReactKeyboardEvent<HTMLInputElement>) => {\n if (event.key !== 'Escape') return;\n event.preventDefault();\n setAddress(url ?? (active?.kind === 'artifact' ? active.path : ''));\n setAddressNote(null);\n event.currentTarget.blur();\n };\n\n const canBack = active?.kind === 'url' && active.index > 0;\n const canForward = active?.kind === 'url' && active.index < active.history.length - 1;\n\n // -------------------------------------------------------------------------\n // Render\n // -------------------------------------------------------------------------\n\n return (\n <div className={styles.pane} data-compact={compact || undefined}>\n <div className={styles.strip}>\n <div className={styles.tabs} role=\"tablist\" aria-label=\"Previews\">\n {tabs.map((tab, index) => {\n const selected = tab.id === activeId;\n const label = tabLabel(tab);\n return (\n <div key={tab.id} className={styles.tab} data-selected={selected || undefined} role=\"presentation\">\n <button\n ref={(node) => { if (node) tabRefs.current.set(tab.id, node); else tabRefs.current.delete(tab.id); }}\n type=\"button\"\n role=\"tab\"\n id={`preview-tab-${tab.id}`}\n aria-selected={selected}\n aria-controls=\"preview-panel\"\n tabIndex={selected ? 0 : -1}\n className={styles.tabButton}\n title={tab.kind === 'url' ? tab.history[tab.index] : tab.kind === 'artifact' ? tab.path : 'Choose what to preview'}\n onClick={() => setActiveId(tab.id)}\n onKeyDown={(event) => onTabKeyDown(event, index)}\n >\n {tab.kind === 'artifact' ? <FileGlyph size={12} /> : tab.kind === 'url' ? <ServerGlyph size={12} /> : <PreviewGlyph size={12} />}\n <span className={styles.tabTitle}>{label}</span>\n </button>\n <button type=\"button\" className={styles.tabClose} aria-label={`Close preview ${label}`} title=\"Close\"\n onClick={() => closeTab(tab)}>\n <IconX size={12} />\n </button>\n </div>\n );\n })}\n </div>\n <IconButton variant=\"ghost\" size=\"sm\" icon={<IconPlus />} aria-label=\"New preview tab\" title=\"New preview tab\"\n className={styles.newTab} onClick={newLauncherTab} />\n </div>\n\n <div className={`${chrome.header} ${styles.toolbar}`}>\n <div className={styles.nav}>\n <IconButton variant=\"ghost\" size=\"sm\" icon={<ArrowLeftGlyph />} aria-label=\"Back\" title=\"Back\" disabled={!canBack} onClick={() => go(-1)} />\n <IconButton variant=\"ghost\" size=\"sm\" icon={<ArrowRightGlyph />} aria-label=\"Forward\" title=\"Forward\" disabled={!canForward} onClick={() => go(1)} />\n <IconButton variant=\"ghost\" size=\"sm\" icon={<ReloadGlyph />} aria-label={showLauncher ? 'Refresh the list' : 'Reload'}\n title={showLauncher ? 'Refresh the list' : 'Reload'}\n disabled={!active && showLauncher && targets === null} onClick={reload} />\n </div>\n <form className={styles.addressForm} onSubmit={submitAddress} role=\"search\" aria-label=\"Preview address\">\n <input\n ref={addressRef}\n className={styles.address}\n value={address}\n onChange={(event) => setAddress(event.target.value)}\n onKeyDown={onAddressKeyDown}\n onFocus={(event) => event.currentTarget.select()}\n placeholder=\"localhost:5173\"\n aria-label=\"Address\"\n spellCheck={false}\n autoCapitalize=\"off\"\n autoCorrect=\"off\"\n inputMode=\"url\"\n readOnly={active?.kind === 'artifact'}\n />\n </form>\n <div className={chrome.actions}>\n {!compact ? (\n <Segmented<Device>\n aria-label=\"Frame width\"\n size=\"sm\"\n value={device}\n onChange={setDevice}\n options={[\n { value: 'desktop', label: <DesktopGlyph size={14} />, ariaLabel: 'Desktop width' },\n { value: 'phone', label: <PhoneGlyph size={14} />, ariaLabel: '375 px width' },\n ]}\n />\n ) : null}\n {url ? (\n <a className={styles.external} href={url} target=\"_blank\" rel=\"noopener noreferrer\" aria-label=\"Open in browser\" title=\"Open in browser\">\n <IconExternalLink />\n </a>\n ) : (\n // Holds the link's place so the address bar keeps its width when a\n // page opens or closes (no link to offer for a file or the launcher).\n <span className={styles.external} data-placeholder=\"true\" aria-hidden=\"true\" />\n )}\n </div>\n </div>\n\n {addressNote ? <AddressNote note={addressNote} onDismiss={() => setAddressNote(null)} /> : null}\n\n {waiting ? (\n <div className={styles.waiting} role=\"status\">\n <span className={styles.pulse} aria-hidden=\"true\" />\n <span className={styles.waitingText}>\n Starting <code>{waiting.server.command ?? waiting.server.label}</code> — waiting for {shortUrl(waiting.server.url)}\n {' · '}\n {Math.max(0, Math.round((clock - waiting.since) / 1000))}s\n </span>\n <Button size=\"sm\" variant=\"ghost\" onClick={() => setWaiting(null)}>Stop waiting</Button>\n </div>\n ) : null}\n\n {notice ? (\n <div className={styles.notice} role=\"alert\">\n <span>{notice}</span>\n <button type=\"button\" className={styles.noticeClose} aria-label=\"Dismiss\" title=\"Dismiss\" onClick={() => setNotice(null)}><IconX size={12} /></button>\n </div>\n ) : null}\n\n <div className={styles.body} id=\"preview-panel\" role=\"tabpanel\" aria-labelledby={active ? `preview-tab-${active.id}` : undefined}>\n {showLauncher ? (\n <Launcher\n targets={targets}\n error={targetsError}\n roots={roots}\n onOpenServer={openServer}\n onOpenArtifact={(a) => openArtifact(a.path, a.kind)}\n onRetry={() => void refreshTargets()}\n onOpenTerminal={() => onOpenTerminal(roots[0] ? { root: roots[0] } : {})}\n waitingId={waiting?.server.id ?? null}\n />\n ) : active?.kind === 'url' ? (\n <div className={styles.stage} data-device={device}>\n <iframe\n key={`${active.id}:${active.index}:${active.reloadKey}`}\n className={styles.frame}\n src={active.history[active.index]}\n title={`Preview of ${tabLabel(active)}`}\n // A dev server is another origin: allow-same-origin is ITS origin.\n // No allow-top-navigation: it can never navigate Verse away.\n sandbox=\"allow-scripts allow-same-origin allow-forms allow-popups allow-modals allow-downloads\"\n referrerPolicy=\"no-referrer\"\n />\n <p className={styles.frameHint}>\n Blank page? Some servers refuse to be framed.{' '}\n <a href={active.history[active.index]} target=\"_blank\" rel=\"noopener noreferrer\">Open in browser ↗</a>\n </p>\n </div>\n ) : active?.kind === 'artifact' ? (\n <ArtifactView tab={active} content={contentKey ? content.get(contentKey) ?? { status: 'loading' } : { status: 'loading' }} device={device}\n onRetry={reload} />\n ) : null}\n </div>\n </div>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Pieces\n// ---------------------------------------------------------------------------\n\nfunction AddressNote({ note, onDismiss }: { note: PreviewAddress; onDismiss: () => void }) {\n return (\n <div className={styles.addressNote} role=\"status\">\n {note.kind === 'external' ? (\n <span>\n Only local dev servers open here.{' '}\n <a href={note.url} target=\"_blank\" rel=\"noopener noreferrer\">Open in browser ↗</a>\n </span>\n ) : note.kind === 'self' ? (\n <span>That address is Verse itself.</span>\n ) : (\n <span>Enter a local address, like <code>localhost:5173</code>.</span>\n )}\n <button type=\"button\" className={styles.noticeClose} aria-label=\"Dismiss\" title=\"Dismiss\" onClick={onDismiss}><IconX size={12} /></button>\n </div>\n );\n}\n\nfunction ArtifactView({ tab, content, device, onRetry }: { tab: Extract<PreviewTab, { kind: 'artifact' }>; content: ArtifactContent; device: Device; onRetry: () => void }) {\n if (content.status === 'loading') {\n return <div className={styles.loading} aria-busy=\"true\"><SkeletonLine width=\"50%\" /><SkeletonLine width=\"80%\" /></div>;\n }\n if (content.status === 'error') {\n return <EmptyState compact tone=\"error\" title=\"Preview unavailable\" body={content.message}\n action={<Button size=\"sm\" variant=\"subtle\" onClick={onRetry}>Try again</Button>} />;\n }\n if (content.status === 'text') {\n return (\n <article className={styles.markdown} aria-label={tab.path}>\n <MessageMarkdown text={content.text} />\n </article>\n );\n }\n if (tab.artifactKind === 'image') {\n return (\n <div className={styles.imageStage}>\n <img className={styles.image} src={content.src} alt={baseName(tab.path)} />\n </div>\n );\n }\n return (\n <div className={styles.stage} data-device={tab.artifactKind === 'pdf' ? 'desktop' : device}>\n <iframe\n key={content.src}\n className={styles.frame}\n src={content.src}\n title={`Preview of ${tab.path}`}\n // HTML and SVG run in a sandbox with NO same-origin (the server's CSP\n // says the same): their own script works, Verse stays out of reach.\n // PDF viewers refuse to run sandboxed (see preview.ts PDF_CSP).\n {...(tab.artifactKind === 'pdf' ? {} : { sandbox: 'allow-scripts' })}\n referrerPolicy=\"no-referrer\"\n />\n </div>\n );\n}\n\nfunction Launcher({ targets, error, roots, onOpenServer, onOpenArtifact, onRetry, onOpenTerminal, waitingId }: {\n targets: VersePreviewTargetsResponse | null;\n error: string | null;\n roots: readonly string[];\n onOpenServer: (server: VersePreviewDevServer) => void;\n onOpenArtifact: (artifact: VersePreviewArtifact) => void;\n onRetry: () => void;\n /** Opens a terminal (below this pane) in the chat's first folder, to start a server by hand. */\n onOpenTerminal: () => void;\n waitingId: string | null;\n}) {\n if (!targets) {\n if (error) {\n return <EmptyState compact tone=\"error\" title=\"Could not list what to preview\" body={error}\n action={<Button size=\"sm\" variant=\"subtle\" onClick={onRetry}>Try again</Button>} />;\n }\n return <div className={styles.loading} aria-busy=\"true\"><SkeletonLine width=\"35%\" /><SkeletonLine width=\"70%\" /><SkeletonLine width=\"60%\" /></div>;\n }\n const multiRoot = roots.length > 1;\n if (targets.devServers.length === 0 && targets.artifacts.length === 0) {\n return (\n <EmptyState\n compact\n icon={<PreviewGlyph size={20} />}\n title=\"Nothing to preview yet\"\n body=\"Start a dev server in the terminal, or ask for an HTML report. Local servers and the files this chat writes show up here.\"\n action={<Button size=\"sm\" variant=\"subtle\" onClick={onOpenTerminal}>Open a terminal</Button>}\n />\n );\n }\n return (\n <div className={styles.launcher}>\n <section className={styles.section} aria-labelledby=\"preview-servers-title\">\n <h3 className={styles.sectionTitle} id=\"preview-servers-title\">Dev servers</h3>\n {targets.devServers.length === 0 ? (\n <p className={styles.muted}>No dev server found in this chat's folders. Add one to <code>.claude/launch.json</code>, or start it in the terminal.</p>\n ) : (\n <ul className={styles.rows}>\n {targets.devServers.map((server) => (\n <li key={server.id} className={styles.row}>\n <span className={styles.dot} data-running={server.running || undefined} aria-hidden=\"true\" />\n <span className={styles.rowMain}>\n <span className={styles.rowTitle} title={server.label}>{server.label}</span>\n <span className={styles.rowMeta}\n title={`${shortUrl(server.url)} · ${server.running ? 'running' : 'stopped'} · ${SOURCE_LABEL[server.source]}${multiRoot ? ` · ${server.root}` : ''}`}>\n {shortUrl(server.url)} · {server.running ? 'running' : 'stopped'} · {SOURCE_LABEL[server.source]}\n {multiRoot ? ` · ${baseName(server.root)}` : ''}\n </span>\n {/* What Start will type, before the click — a launch.json row's\n label is only its name. Skipped when the label already is it. */}\n {!server.running && server.command && server.command !== server.label ? (\n <code className={styles.rowCommand} title={server.command}>{server.command}</code>\n ) : null}\n </span>\n {server.running ? (\n <Button size=\"sm\" variant=\"subtle\" onClick={() => onOpenServer(server)} aria-label={`Open ${server.label}`}>Open</Button>\n ) : (\n <Button size=\"sm\" variant=\"subtle\" icon={<PlayGlyph size={12} />} busy={waitingId === server.id}\n onClick={() => onOpenServer(server)} aria-label={`Start ${server.label}`}\n title={`Runs ${server.command ?? server.label} in a terminal tab`}>\n Start\n </Button>\n )}\n </li>\n ))}\n </ul>\n )}\n </section>\n <section className={styles.section} aria-labelledby=\"preview-files-title\">\n <h3 className={styles.sectionTitle} id=\"preview-files-title\">This chat's files</h3>\n {targets.artifacts.length === 0 ? (\n <p className={styles.muted}>Ask the chat for a report or a page: HTML, Markdown, SVG, images and PDFs it writes appear here.</p>\n ) : (\n <ul className={styles.rows}>\n {targets.artifacts.map((artifact) => {\n const tooBig = artifact.bytes > 5 * 1024 * 1024;\n return (\n <li key={artifact.path} className={styles.row}>\n <FileGlyph size={14} className={styles.fileIcon} />\n <span className={styles.rowMain}>\n <span className={styles.rowTitle} title={artifact.path}>{artifact.path}</span>\n <span className={styles.rowMeta}>{KIND_LABEL[artifact.kind]} · {formatBytes(artifact.bytes)}</span>\n </span>\n <Button size=\"sm\" variant=\"subtle\" disabled={tooBig} title={tooBig ? 'Larger than 5 MB' : undefined}\n onClick={() => onOpenArtifact(artifact)} aria-label={`Open ${artifact.path}`}>\n Open\n </Button>\n </li>\n );\n })}\n </ul>\n )}\n </section>\n </div>\n );\n}\n"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import{a as e,n as t,s as n}from"./index-oAAq8XJa.js";import{t as r}from"./VerseConsoleApp-WVeyJnW7.js";import{i}from"./CapacityStrip-C667yQe8.js";import{c as a,n as o}from"./capacity-strip-model-Bj_9ztzs.js";var s=n(e(),1),c={count:`_count_16gc0_5`,dot:`_dot_16gc0_26`,pulse:`_pulse_16gc0_27`,autonomy:`_autonomy_16gc0_41`,ring:`_ring_16gc0_57`,ringTrack:`_ringTrack_16gc0_58`,ringFill:`_ringFill_16gc0_59`},l=t();function u(e){return e.stopped?`danger`:e.paused?`warning`:e.mode===`autonomous`?`success`:e.mode===`propose`?`info`:`neutral`}function d(e,t){if(!t)return null;switch(e){case`command`:{let e=t.counts.needsYou;return e>0?{kind:`count`,count:e,spoken:`, ${e} need${e===1?`s`:``} you`,tone:`warning`}:null}case`chat`:{let e=t.counts.running;if(e>0)return{kind:`pulse`,spoken:`, ${e} running`,tone:`running`};let n=t.counts.unread;return n>0?{kind:`dot`,spoken:`, ${n} unread`,tone:`info`}:null}case`fleet`:return t.autonomy?{kind:`autonomy`,spoken:`, ${t.autonomy.label}`,autonomy:t.autonomy,tone:u(t.autonomy)}:null;case`mind`:return t.mind?.unseen?{kind:`dot`,spoken:`, new memo`,tone:`info`}:null;default:return null}}function f({badge:e}){if(e.kind===`count`){let t=e.count??0;return(0,l.jsx)(`span`,{className:c.count,"data-tone":e.tone,"aria-hidden":`true`,"data-badge":`count`,children:t>99?`99+`:t})}if(e.kind===`autonomy`&&e.autonomy){let t=e.autonomy,n=t.stopped?`stopped`:t.paused?`paused`:t.mode;return(0,l.jsx)(`span`,{className:c.autonomy,"data-shape":n,"data-tone":e.tone,"aria-hidden":`true`,"data-badge":`autonomy`})}return(0,l.jsx)(`span`,{className:e.kind===`pulse`?c.pulse:c.dot,"data-tone":e.tone,"aria-hidden":`true`,"data-badge":e.kind})}function p(e){return e>=90?`critical`:e>=70?`tight`:`ok`}function m(e){if(!e)return null;let t=e.windows.find(e=>e.binding)??null,n=t?.limitReached===!0,r=e.cls===`blocked`||n?100:t?.usedPercent??null;return r===null?null:{seatId:e.seatId,label:e.label,windowLabel:t?.label??null,usedPercent:Math.max(0,Math.min(100,r)),limitReached:n,resetText:t?.resetText??null,word:e.word}}function h(e){let t=e.resetText?` · ${e.resetText}`:``;return e.limitReached?`${e.label}: ${e.windowLabel??`window`} limit reached${t}`:e.windowLabel===null?`${e.label}: ${e.word}`:`${e.label}: ${e.windowLabel} ${r(e.usedPercent)} used${t}`}function g(){let e=i({withBudget:!1});return(0,s.useMemo)(()=>m(a(o(e.seats,{health:e.health,local:`hide`}))),[e.seats,e.health])}var _=7,v=2*Math.PI*_;function y({badge:e}){let t=Math.max(0,Math.min(100,e.usedPercent)),n=p(t);return(0,l.jsxs)(`svg`,{className:c.ring,"data-tone":n,viewBox:`0 0 18 18`,width:18,height:18,"aria-hidden":`true`,focusable:`false`,children:[(0,l.jsx)(`circle`,{className:c.ringTrack,cx:`9`,cy:`9`,r:_}),(0,l.jsx)(`circle`,{className:c.ringFill,cx:`9`,cy:`9`,r:_,strokeDasharray:`${t/100*v} ${v}`,transform:`rotate(-90 9 9)`})]})}export{y as CapacityRing,f as RailBadgeMark,u as autonomyTone,p as capacityTone,h as describeRailCapacity,d as railBadgeFor,m as railCapacityFromRow,g as useRailCapacity};
2
+ //# sourceMappingURL=RailStatus-D-t2gPae.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RailStatus-D-t2gPae.js","names":[],"sources":["../../../../../../src/web-ui/routes/verse/shell/RailStatus.module.css","../../../../../../src/web-ui/routes/verse/shell/RailStatus.tsx"],"sourcesContent":["/* Rail badges: pinned to the icon's own 16px box (RailIcon), so they read the\n same in the 56px and the labelled rail. Shape carries meaning; colour\n confirms it. */\n\n.count {\n position: absolute;\n top: -6px;\n right: -9px;\n min-width: 16px;\n height: 16px;\n padding: 0 4px;\n border-radius: var(--radius-full);\n /* The status pair, not solid + ink: the bg/fg tokens are the ones tuned\n for text contrast in BOTH themes (the solid flips nothing). */\n background: var(--status-warning-bg);\n box-shadow: 0 0 0 2px var(--bg-canvas), inset 0 0 0 1px var(--status-warning-solid);\n color: var(--status-warning-fg);\n font-family: var(--font-ui);\n font-size: var(--text-2xs-size);\n font-weight: var(--font-weight-semibold);\n line-height: 16px;\n text-align: center;\n font-variant-numeric: tabular-nums;\n}\n\n.dot,\n.pulse {\n position: absolute;\n top: -3px;\n right: -3px;\n width: 7px;\n height: 7px;\n border-radius: var(--radius-full);\n box-shadow: 0 0 0 2px var(--bg-canvas);\n background: var(--status-info-solid);\n}\n.pulse { background: var(--status-running-solid); animation: pulse var(--duration-pulse) ease-in-out infinite; }\n\n/* Autonomy: off = hollow ring, propose = half, autonomous = full,\n paused = a bar, stopped = a square. */\n.autonomy {\n position: absolute;\n top: -3px;\n right: -4px;\n width: 8px;\n height: 8px;\n border-radius: var(--radius-full);\n box-shadow: 0 0 0 2px var(--bg-canvas);\n border: 1.5px solid var(--text-tertiary);\n background: transparent;\n}\n.autonomy[data-shape='propose'] { border-color: var(--status-info-solid); background: linear-gradient(90deg, var(--status-info-solid) 50%, transparent 50%); }\n.autonomy[data-shape='autonomous'] { border-color: var(--status-success-solid); background: var(--status-success-solid); }\n.autonomy[data-shape='paused'] { border-radius: 1px; border: 0; width: 8px; height: 3px; top: 0; background: var(--status-warning-solid); }\n.autonomy[data-shape='stopped'] { border-radius: 1px; border-color: var(--status-danger-solid); background: var(--status-danger-solid); }\n\n.ring { display: block; }\n.ringTrack { fill: none; stroke: var(--meter-track); stroke-width: 2.5; }\n.ringFill { fill: none; stroke: var(--data-seq-5); stroke-width: 2.5; stroke-linecap: round; }\n.ring[data-tone='tight'] .ringFill { stroke: var(--status-warning-solid); }\n.ring[data-tone='critical'] .ringFill { stroke: var(--status-danger-solid); }\n\n@keyframes pulse {\n 0%, 100% { opacity: 1; }\n 50% { opacity: 0.55; }\n}\n\n@media (prefers-reduced-motion: reduce) {\n :root:not([data-motion='full']) .pulse { animation: none; }\n}\n:root[data-motion='reduce'] .pulse { animation: none; }\n","/**\n * routes/verse/shell/RailStatus.tsx — what the rail says without being\n * opened (unit C1; SPEC-310C §1 \"Rail badges\"):\n *\n * Command the Needs-you count\n * Chat a pulsing amber dot while chats run (the count rides the\n * accessible name); a quiet dot for unread replies\n * Fleet the autonomy state (off / propose / autonomous, paused, stopped)\n * Mind a dot when there is a memo the operator has not opened\n * foot a capacity ring for the scarcest seat — C6's `scarcestSeat`\n * over the shared capacity rows, so the ring and Apps & Accounts\n * can never describe the same seat two ways\n *\n * Every badge is a SHAPE plus words in the accessible name — never colour\n * alone — and an unknown state draws nothing at all: no dot is \"we do not\n * know\", never \"zero\" (the activity route may not be in this build yet).\n */\nimport { useMemo } from 'react';\nimport type {\n VerseActivityResponse,\n VerseAutonomyBadge,\n VerseCapacityBadge,\n} from '../../../../core/verse/workbench-types.js';\nimport { buildCapacityRows, scarcestSeat, type CapacityRow } from '../usage/capacity-strip-model.js';\nimport { useCapacityData } from '../usage/CapacityStrip.js';\nimport type { VerseSectionId } from '../verse-ui-store.js';\nimport styles from './RailStatus.module.css';\nimport { usedPercentText } from '../percent-text.js';\n\nexport interface RailBadge {\n /** Appended to the rail button's accessible name (\", 3 need you\"). */\n spoken: string;\n kind: 'count' | 'pulse' | 'dot' | 'autonomy';\n /** The visible count, for `count`. */\n count?: number;\n tone?: 'running' | 'info' | 'warning' | 'danger' | 'success' | 'neutral';\n autonomy?: VerseAutonomyBadge;\n}\n\nexport function autonomyTone(badge: VerseAutonomyBadge): NonNullable<RailBadge['tone']> {\n if (badge.stopped) return 'danger';\n if (badge.paused) return 'warning';\n if (badge.mode === 'autonomous') return 'success';\n if (badge.mode === 'propose') return 'info';\n return 'neutral';\n}\n\n/** The badge a rail item shows, or null (nothing to say, or not known). */\nexport function railBadgeFor(section: VerseSectionId, data: VerseActivityResponse | null): RailBadge | null {\n if (!data) return null;\n switch (section) {\n case 'command': {\n const n = data.counts.needsYou;\n return n > 0 ? { kind: 'count', count: n, spoken: `, ${n} need${n === 1 ? 's' : ''} you`, tone: 'warning' } : null;\n }\n case 'chat': {\n const running = data.counts.running;\n if (running > 0) return { kind: 'pulse', spoken: `, ${running} running`, tone: 'running' };\n const unread = data.counts.unread;\n return unread > 0 ? { kind: 'dot', spoken: `, ${unread} unread`, tone: 'info' } : null;\n }\n case 'fleet':\n return data.autonomy ? { kind: 'autonomy', spoken: `, ${data.autonomy.label}`, autonomy: data.autonomy, tone: autonomyTone(data.autonomy) } : null;\n case 'mind':\n return data.mind?.unseen ? { kind: 'dot', spoken: ', new memo', tone: 'info' } : null;\n default:\n return null;\n }\n}\n\nexport function RailBadgeMark({ badge }: { badge: RailBadge }) {\n if (badge.kind === 'count') {\n const n = badge.count ?? 0;\n return (\n <span className={styles.count} data-tone={badge.tone} aria-hidden=\"true\" data-badge=\"count\">\n {n > 99 ? '99+' : n}\n </span>\n );\n }\n if (badge.kind === 'autonomy' && badge.autonomy) {\n const a = badge.autonomy;\n const shape = a.stopped ? 'stopped' : a.paused ? 'paused' : a.mode;\n return <span className={styles.autonomy} data-shape={shape} data-tone={badge.tone} aria-hidden=\"true\" data-badge=\"autonomy\" />;\n }\n return <span className={badge.kind === 'pulse' ? styles.pulse : styles.dot} data-tone={badge.tone} aria-hidden=\"true\" data-badge={badge.kind} />;\n}\n\n// ---------------------------------------------------------------------------\n// Capacity ring\n// ---------------------------------------------------------------------------\n\nexport function capacityTone(usedPercent: number): 'ok' | 'tight' | 'critical' {\n if (usedPercent >= 90) return 'critical';\n if (usedPercent >= 70) return 'tight';\n return 'ok';\n}\n\n/**\n * What the rail foot shows for the scarcest seat: one CapacityRow (C6's\n * projection) reduced to a ring and a sentence. Built ONLY from a row that\n * `scarcestSeat` chose, so there is always a measured binding window or a\n * blocked seat behind it — never an invented percent.\n */\nexport interface RailCapacity {\n seatId: string;\n label: string;\n /** \"5-hour window\", \"weekly fable window\"; null when the seat is blocked with no window read. */\n windowLabel: string | null;\n /** 0–100 for the ring. A reached limit or a blocked seat fills it. */\n usedPercent: number;\n limitReached: boolean;\n /** Provider prose or a formatted instant; null when neither. */\n resetText: string | null;\n /** \"blocked\", \"tight\", … — C6's word for the class. */\n word: string;\n}\n\nexport function railCapacityFromRow(row: CapacityRow | null): RailCapacity | null {\n if (!row) return null;\n const binding = row.windows.find((w) => w.binding) ?? null;\n const limitReached = binding?.limitReached === true;\n // Blocked (signed out, out of usage) reads as a full ring whatever the last\n // window said: the engine will refuse a turn on it.\n const used = row.cls === 'blocked' || limitReached ? 100 : binding?.usedPercent ?? null;\n if (used === null) return null;\n return {\n seatId: row.seatId,\n label: row.label,\n windowLabel: binding?.label ?? null,\n usedPercent: Math.max(0, Math.min(100, used)),\n limitReached,\n resetText: binding?.resetText ?? null,\n word: row.word,\n };\n}\n\n/** \"Claude Max: weekly fable window 92% used · resets Sep 25\" — the tooltip and the accessible name. */\nexport function describeRailCapacity(c: RailCapacity): string {\n const reset = c.resetText ? ` · ${c.resetText}` : '';\n if (c.limitReached) return `${c.label}: ${c.windowLabel ?? 'window'} limit reached${reset}`;\n if (c.windowLabel === null) return `${c.label}: ${c.word}`;\n return `${c.label}: ${c.windowLabel} ${usedPercentText(c.usedPercent)} used${reset}`;\n}\n\n/**\n * The rail's scarcest seat, live. Reads the app-wide seat + health caches the\n * capacity strip uses (mounting it costs no extra request when Apps or Usage\n * is also mounted). Budget is NOT read: the reserve does not change which\n * seat is closest to running out, and the rail is on screen on every surface,\n * so it should not keep the 60 s budget poll alive by itself. Local seats are\n * left out — they have no quota to run out of.\n */\nexport function useRailCapacity(): RailCapacity | null {\n const data = useCapacityData({ withBudget: false });\n return useMemo(\n () => railCapacityFromRow(scarcestSeat(buildCapacityRows(data.seats, { health: data.health, local: 'hide' }))),\n [data.seats, data.health],\n );\n}\n\nconst R = 7;\nconst C = 2 * Math.PI * R;\n\nexport function CapacityRing({ badge }: { badge: Pick<VerseCapacityBadge, 'usedPercent'> }) {\n const used = Math.max(0, Math.min(100, badge.usedPercent));\n const tone = capacityTone(used);\n return (\n <svg className={styles.ring} data-tone={tone} viewBox=\"0 0 18 18\" width={18} height={18} aria-hidden=\"true\" focusable=\"false\">\n <circle className={styles.ringTrack} cx=\"9\" cy=\"9\" r={R} />\n <circle\n className={styles.ringFill}\n cx=\"9\"\n cy=\"9\"\n r={R}\n strokeDasharray={`${(used / 100) * C} ${C}`}\n transform=\"rotate(-90 9 9)\"\n />\n </svg>\n );\n}\n"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- import{n as e}from"./index-afDA8cwW.js";var t={root:`_root_1lgxn_1`,spinner:`_spinner_1lgxn_9`,spin:`_spin_1lgxn_9`},n=e();function r({label:e=`Refreshing`}){return(0,n.jsxs)(`span`,{className:t.root,role:`status`,"aria-live":`polite`,children:[(0,n.jsx)(`span`,{className:t.spinner,"aria-hidden":`true`}),(0,n.jsx)(`span`,{className:`visually-hidden`,children:e})]})}export{r as t};
2
- //# sourceMappingURL=RefreshIndicator-CnhEovMZ.js.map
1
+ import{n as e}from"./index-oAAq8XJa.js";var t={root:`_root_1lgxn_1`,spinner:`_spinner_1lgxn_9`,spin:`_spin_1lgxn_9`},n=e();function r({label:e=`Refreshing`}){return(0,n.jsxs)(`span`,{className:t.root,role:`status`,"aria-live":`polite`,children:[(0,n.jsx)(`span`,{className:t.spinner,"aria-hidden":`true`}),(0,n.jsx)(`span`,{className:`visually-hidden`,children:e})]})}export{r as t};
2
+ //# sourceMappingURL=RefreshIndicator-BLnr9IOM.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"RefreshIndicator-CnhEovMZ.js","names":[],"sources":["../../../../../../src/web-ui/components/primitives/RefreshIndicator.module.css","../../../../../../src/web-ui/components/primitives/RefreshIndicator.tsx"],"sourcesContent":[".root {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 14px;\n height: 14px;\n}\n\n.spinner {\n width: 12px;\n height: 12px;\n border-radius: var(--radius-full);\n border: 2px solid var(--border-strong);\n border-top-color: var(--accent-500);\n animation: spin 0.7s linear infinite;\n}\n\n@keyframes spin {\n to {\n transform: rotate(360deg);\n }\n}\n\n@media (prefers-reduced-motion: reduce) {\n :root:not([data-motion=\"full\"]) .spinner {\n animation: none;\n border-top-color: var(--border-strong);\n }\n}\n\n:root[data-motion=\"reduce\"] .spinner {\n animation: none;\n border-top-color: var(--border-strong);\n}\n","/**\n * components/primitives/RefreshIndicator.tsx — the \"stale data, quietly\n * refreshing\" signal (foundation brief item 4: never blank the screen on\n * refresh). Pair with a QueryEntry's `status`:\n *\n * loading -> render a Skeleton instead of the view\n * refreshing -> render the view with data, plus <RefreshIndicator />\n * success -> render the view with data, no indicator\n * error -> render the view's error state\n */\nimport styles from './RefreshIndicator.module.css';\n\nexport function RefreshIndicator({ label = 'Refreshing' }: { label?: string }) {\n return (\n <span className={styles.root} role=\"status\" aria-live=\"polite\">\n <span className={styles.spinner} aria-hidden=\"true\" />\n <span className=\"visually-hidden\">{label}</span>\n </span>\n );\n}\n"],"mappings":"2HCYA,SAAgB,EAAiB,CAAE,QAAQ,cAAoC,CAC7E,OACE,EAAA,EAAA,KAAA,CAAC,OAAD,CAAM,UAAW,EAAO,KAAM,KAAK,SAAS,YAAU,SAAtD,SAAA,EACE,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,UAAW,EAAO,QAAS,cAAY,MAAQ,CAAA,GACrD,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,UAAU,kBAAmB,SAAA,CAAY,CAAA,CAC3C,GAEV"}
1
+ {"version":3,"file":"RefreshIndicator-BLnr9IOM.js","names":[],"sources":["../../../../../../src/web-ui/components/primitives/RefreshIndicator.module.css","../../../../../../src/web-ui/components/primitives/RefreshIndicator.tsx"],"sourcesContent":[".root {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 14px;\n height: 14px;\n}\n\n.spinner {\n width: 12px;\n height: 12px;\n border-radius: var(--radius-full);\n border: 2px solid var(--border-strong);\n border-top-color: var(--accent-500);\n animation: spin 0.7s linear infinite;\n}\n\n@keyframes spin {\n to {\n transform: rotate(360deg);\n }\n}\n\n@media (prefers-reduced-motion: reduce) {\n :root:not([data-motion=\"full\"]) .spinner {\n animation: none;\n border-top-color: var(--border-strong);\n }\n}\n\n:root[data-motion=\"reduce\"] .spinner {\n animation: none;\n border-top-color: var(--border-strong);\n}\n","/**\n * components/primitives/RefreshIndicator.tsx — the \"stale data, quietly\n * refreshing\" signal (foundation brief item 4: never blank the screen on\n * refresh). Pair with a QueryEntry's `status`:\n *\n * loading -> render a Skeleton instead of the view\n * refreshing -> render the view with data, plus <RefreshIndicator />\n * success -> render the view with data, no indicator\n * error -> render the view's error state\n */\nimport styles from './RefreshIndicator.module.css';\n\nexport function RefreshIndicator({ label = 'Refreshing' }: { label?: string }) {\n return (\n <span className={styles.root} role=\"status\" aria-live=\"polite\">\n <span className={styles.spinner} aria-hidden=\"true\" />\n <span className=\"visually-hidden\">{label}</span>\n </span>\n );\n}\n"],"mappings":"2HCYA,SAAgB,EAAiB,CAAE,QAAQ,cAAoC,CAC7E,OACE,EAAA,EAAA,KAAA,CAAC,OAAD,CAAM,UAAW,EAAO,KAAM,KAAK,SAAS,YAAU,SAAtD,SAAA,EACE,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,UAAW,EAAO,QAAS,cAAY,MAAQ,CAAA,GACrD,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,UAAU,kBAAmB,SAAA,CAAY,CAAA,CAC3C,GAEV"}