@ashlr/hub 3.13.0 → 3.14.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 (625) hide show
  1. package/CHANGELOG.md +74 -0
  2. package/dist/authority-surface.json +204 -124
  3. package/dist/build-identity.json +2 -2
  4. package/dist/cli/authority.js +112 -18
  5. package/dist/cli/authority.js.map +1 -1
  6. package/dist/cli/comms.d.ts +33 -19
  7. package/dist/cli/comms.js +128 -151
  8. package/dist/cli/comms.js.map +1 -1
  9. package/dist/cli/completions.js +1 -1
  10. package/dist/cli/completions.js.map +1 -1
  11. package/dist/cli/daemon.js +29 -0
  12. package/dist/cli/daemon.js.map +1 -1
  13. package/dist/cli/director.d.ts +8 -12
  14. package/dist/cli/director.js +17 -52
  15. package/dist/cli/director.js.map +1 -1
  16. package/dist/cli/fleet.js +4 -1
  17. package/dist/cli/fleet.js.map +1 -1
  18. package/dist/cli/help.js +1 -0
  19. package/dist/cli/help.js.map +1 -1
  20. package/dist/cli/leader.d.ts +27 -3
  21. package/dist/cli/leader.js +253 -4
  22. package/dist/cli/leader.js.map +1 -1
  23. package/dist/core/authority/server-enforcement.d.ts +110 -0
  24. package/dist/core/authority/server-enforcement.js +260 -0
  25. package/dist/core/authority/server-enforcement.js.map +1 -0
  26. package/dist/core/authority/standing-grant.d.ts +24 -4
  27. package/dist/core/authority/standing-grant.js +19 -3
  28. package/dist/core/authority/standing-grant.js.map +1 -1
  29. package/dist/core/cloud/timeline.js +13 -7
  30. package/dist/core/cloud/timeline.js.map +1 -1
  31. package/dist/core/comms/change-digest.d.ts +130 -0
  32. package/dist/core/comms/change-digest.js +451 -0
  33. package/dist/core/comms/change-digest.js.map +1 -0
  34. package/dist/core/comms/director-prompt.d.ts +4 -5
  35. package/dist/core/comms/director-prompt.js +4 -71
  36. package/dist/core/comms/director-prompt.js.map +1 -1
  37. package/dist/core/comms/director.d.ts +24 -61
  38. package/dist/core/comms/director.js +29 -382
  39. package/dist/core/comms/director.js.map +1 -1
  40. package/dist/core/comms/dispatch.d.ts +37 -12
  41. package/dist/core/comms/dispatch.js +244 -177
  42. package/dist/core/comms/dispatch.js.map +1 -1
  43. package/dist/core/comms/elon-dialogue.d.ts +23 -15
  44. package/dist/core/comms/elon-dialogue.js +36 -307
  45. package/dist/core/comms/elon-dialogue.js.map +1 -1
  46. package/dist/core/comms/fleet-pulse.js +4 -7
  47. package/dist/core/comms/fleet-pulse.js.map +1 -1
  48. package/dist/core/comms/handlers.d.ts +10 -6
  49. package/dist/core/comms/handlers.js +14 -48
  50. package/dist/core/comms/handlers.js.map +1 -1
  51. package/dist/core/comms/migrations.d.ts +47 -0
  52. package/dist/core/comms/migrations.js +125 -0
  53. package/dist/core/comms/migrations.js.map +1 -0
  54. package/dist/core/comms/requests.d.ts +32 -5
  55. package/dist/core/comms/requests.js +101 -5
  56. package/dist/core/comms/requests.js.map +1 -1
  57. package/dist/core/comms/telegram-channel.d.ts +104 -0
  58. package/dist/core/comms/telegram-channel.js +622 -0
  59. package/dist/core/comms/telegram-channel.js.map +1 -0
  60. package/dist/core/comms/telegram-thread-map.d.ts +56 -0
  61. package/dist/core/comms/telegram-thread-map.js +144 -0
  62. package/dist/core/comms/telegram-thread-map.js.map +1 -0
  63. package/dist/core/daemon/capacity-publisher.d.ts +8 -1
  64. package/dist/core/daemon/capacity-publisher.js +40 -2
  65. package/dist/core/daemon/capacity-publisher.js.map +1 -1
  66. package/dist/core/daemon/loop.js +18 -4
  67. package/dist/core/daemon/loop.js.map +1 -1
  68. package/dist/core/daemon/tick-deadline.d.ts +44 -0
  69. package/dist/core/daemon/tick-deadline.js +83 -0
  70. package/dist/core/daemon/tick-deadline.js.map +1 -0
  71. package/dist/core/daemon/tick-hooks.d.ts +7 -0
  72. package/dist/core/daemon/tick-hooks.js.map +1 -1
  73. package/dist/core/daemon/tick-progress.d.ts +39 -0
  74. package/dist/core/daemon/tick-progress.js +194 -0
  75. package/dist/core/daemon/tick-progress.js.map +1 -0
  76. package/dist/core/dashboard.js +3 -1
  77. package/dist/core/dashboard.js.map +1 -1
  78. package/dist/core/fleet/fleet-merge-state.d.ts +6 -0
  79. package/dist/core/fleet/fleet-merge-state.js.map +1 -1
  80. package/dist/core/fleet/host-merge.d.ts +9 -0
  81. package/dist/core/fleet/host-merge.js +13 -2
  82. package/dist/core/fleet/host-merge.js.map +1 -1
  83. package/dist/core/fleet/merge-gates.d.ts +13 -0
  84. package/dist/core/fleet/merge-gates.js +14 -0
  85. package/dist/core/fleet/merge-gates.js.map +1 -1
  86. package/dist/core/fleet/mirrors.d.ts +162 -6
  87. package/dist/core/fleet/mirrors.js +1051 -49
  88. package/dist/core/fleet/mirrors.js.map +1 -1
  89. package/dist/core/fleet/standing-merge-pass.d.ts +8 -0
  90. package/dist/core/fleet/standing-merge-pass.js +72 -1
  91. package/dist/core/fleet/standing-merge-pass.js.map +1 -1
  92. package/dist/core/fleet/status.d.ts +17 -0
  93. package/dist/core/fleet/status.js +22 -0
  94. package/dist/core/fleet/status.js.map +1 -1
  95. package/dist/core/fleet/tick-hooks-live.d.ts +1 -1
  96. package/dist/core/fleet/tick-hooks-live.js +13 -3
  97. package/dist/core/fleet/tick-hooks-live.js.map +1 -1
  98. package/dist/core/git.d.ts +17 -0
  99. package/dist/core/git.js +124 -25
  100. package/dist/core/git.js.map +1 -1
  101. package/dist/core/goals/open-goals.d.ts +47 -0
  102. package/dist/core/goals/open-goals.js +33 -0
  103. package/dist/core/goals/open-goals.js.map +1 -0
  104. package/dist/core/inbox/merge.d.ts +5 -0
  105. package/dist/core/inbox/merge.js +58 -2
  106. package/dist/core/inbox/merge.js.map +1 -1
  107. package/dist/core/integrations/locus.d.ts +28 -0
  108. package/dist/core/integrations/locus.js +155 -30
  109. package/dist/core/integrations/locus.js.map +1 -1
  110. package/dist/core/integrations/telegram-format.d.ts +40 -0
  111. package/dist/core/integrations/telegram-format.js +123 -0
  112. package/dist/core/integrations/telegram-format.js.map +1 -0
  113. package/dist/core/integrations/telegram.d.ts +60 -4
  114. package/dist/core/integrations/telegram.js +161 -28
  115. package/dist/core/integrations/telegram.js.map +1 -1
  116. package/dist/core/mcp-registry.d.ts +12 -0
  117. package/dist/core/mcp-registry.js +70 -0
  118. package/dist/core/mcp-registry.js.map +1 -1
  119. package/dist/core/observability/rollup.d.ts +12 -10
  120. package/dist/core/observability/rollup.js +44 -17
  121. package/dist/core/observability/rollup.js.map +1 -1
  122. package/dist/core/resources/connection-monitor.d.ts +9 -0
  123. package/dist/core/resources/connection-monitor.js +19 -9
  124. package/dist/core/resources/connection-monitor.js.map +1 -1
  125. package/dist/core/resources/quota-refresh-lease.d.ts +17 -0
  126. package/dist/core/resources/quota-refresh-lease.js +34 -1
  127. package/dist/core/resources/quota-refresh-lease.js.map +1 -1
  128. package/dist/core/routing/budget-api.d.ts +7 -1
  129. package/dist/core/routing/budget-api.js +56 -2
  130. package/dist/core/routing/budget-api.js.map +1 -1
  131. package/dist/core/routing/readiness-types.d.ts +82 -0
  132. package/dist/core/routing/readiness-types.js +23 -0
  133. package/dist/core/routing/readiness-types.js.map +1 -0
  134. package/dist/core/routing/readiness.d.ts +103 -0
  135. package/dist/core/routing/readiness.js +480 -0
  136. package/dist/core/routing/readiness.js.map +1 -0
  137. package/dist/core/sandbox/confine.js +22 -1
  138. package/dist/core/sandbox/confine.js.map +1 -1
  139. package/dist/core/sandbox/policy.d.ts +23 -0
  140. package/dist/core/sandbox/policy.js +100 -0
  141. package/dist/core/sandbox/policy.js.map +1 -1
  142. package/dist/core/types.d.ts +13 -0
  143. package/dist/core/types.js.map +1 -1
  144. package/dist/core/universe/builtins/preparation/manifest.json +1 -1
  145. package/dist/core/universe/builtins/preparation/preparation-bridge.mjs +1204 -939
  146. package/dist/core/universe/builtins/preparation/preparation-verification-fixtures.mjs +1319 -1054
  147. package/dist/core/usage/frontier-usage.d.ts +20 -2
  148. package/dist/core/usage/frontier-usage.js +75 -17
  149. package/dist/core/usage/frontier-usage.js.map +1 -1
  150. package/dist/core/verse/accounts.d.ts +45 -0
  151. package/dist/core/verse/accounts.js +246 -17
  152. package/dist/core/verse/accounts.js.map +1 -1
  153. package/dist/core/verse/apps-api.js +23 -11
  154. package/dist/core/verse/apps-api.js.map +1 -1
  155. package/dist/core/verse/apps.d.ts +11 -9
  156. package/dist/core/verse/apps.js +2 -2
  157. package/dist/core/verse/apps.js.map +1 -1
  158. package/dist/core/verse/authority-api.d.ts +8 -2
  159. package/dist/core/verse/authority-api.js +40 -5
  160. package/dist/core/verse/authority-api.js.map +1 -1
  161. package/dist/core/verse/autonomy-ladder.d.ts +172 -0
  162. package/dist/core/verse/autonomy-ladder.js +251 -0
  163. package/dist/core/verse/autonomy-ladder.js.map +1 -0
  164. package/dist/core/verse/context-fit.js +7 -5
  165. package/dist/core/verse/context-fit.js.map +1 -1
  166. package/dist/core/verse/control-api.d.ts +23 -1
  167. package/dist/core/verse/control-api.js +117 -10
  168. package/dist/core/verse/control-api.js.map +1 -1
  169. package/dist/core/verse/fleet-live-api.js +13 -5
  170. package/dist/core/verse/fleet-live-api.js.map +1 -1
  171. package/dist/core/verse/folder-io.d.ts +50 -0
  172. package/dist/core/verse/folder-io.js +142 -0
  173. package/dist/core/verse/folder-io.js.map +1 -0
  174. package/dist/core/verse/git-api.js +5 -4
  175. package/dist/core/verse/git-api.js.map +1 -1
  176. package/dist/core/verse/git-ops.d.ts +10 -1
  177. package/dist/core/verse/git-ops.js +18 -2
  178. package/dist/core/verse/git-ops.js.map +1 -1
  179. package/dist/core/verse/github-api.d.ts +1 -1
  180. package/dist/core/verse/github-api.js +5 -4
  181. package/dist/core/verse/github-api.js.map +1 -1
  182. package/dist/core/verse/github-repo.js +118 -14
  183. package/dist/core/verse/github-repo.js.map +1 -1
  184. package/dist/core/verse/leader-api.d.ts +5 -4
  185. package/dist/core/verse/leader-api.js +237 -10
  186. package/dist/core/verse/leader-api.js.map +1 -1
  187. package/dist/core/verse/local-models.d.ts +10 -0
  188. package/dist/core/verse/local-models.js +10 -1
  189. package/dist/core/verse/local-models.js.map +1 -1
  190. package/dist/core/verse/login-path.d.ts +73 -0
  191. package/dist/core/verse/login-path.js +123 -14
  192. package/dist/core/verse/login-path.js.map +1 -1
  193. package/dist/core/verse/mcp-control-api.js +4 -4
  194. package/dist/core/verse/mcp-control-api.js.map +1 -1
  195. package/dist/core/verse/mcp-scope.d.ts +22 -0
  196. package/dist/core/verse/mcp-scope.js +41 -1
  197. package/dist/core/verse/mcp-scope.js.map +1 -1
  198. package/dist/core/verse/mcp-seat-view.d.ts +10 -0
  199. package/dist/core/verse/mcp-seat-view.js +30 -4
  200. package/dist/core/verse/mcp-seat-view.js.map +1 -1
  201. package/dist/core/verse/overnight-api.js +20 -2
  202. package/dist/core/verse/overnight-api.js.map +1 -1
  203. package/dist/core/verse/path-guard.d.ts +24 -0
  204. package/dist/core/verse/path-guard.js +91 -22
  205. package/dist/core/verse/path-guard.js.map +1 -1
  206. package/dist/core/verse/preview-api.js +22 -0
  207. package/dist/core/verse/preview-api.js.map +1 -1
  208. package/dist/core/verse/projects.d.ts +21 -0
  209. package/dist/core/verse/projects.js +82 -0
  210. package/dist/core/verse/projects.js.map +1 -1
  211. package/dist/core/verse/session-controls-api.js +5 -3
  212. package/dist/core/verse/session-controls-api.js.map +1 -1
  213. package/dist/core/verse/session-handoff.d.ts +26 -0
  214. package/dist/core/verse/session-handoff.js +90 -12
  215. package/dist/core/verse/session-handoff.js.map +1 -1
  216. package/dist/core/verse/terminal-api.js +7 -4
  217. package/dist/core/verse/terminal-api.js.map +1 -1
  218. package/dist/core/verse/terminal.js +9 -5
  219. package/dist/core/verse/terminal.js.map +1 -1
  220. package/dist/core/verse/verse-api.js +81 -27
  221. package/dist/core/verse/verse-api.js.map +1 -1
  222. package/dist/core/verse/workspaces.d.ts +51 -0
  223. package/dist/core/verse/workspaces.js +177 -47
  224. package/dist/core/verse/workspaces.js.map +1 -1
  225. package/dist/core/vision/leader-apply.d.ts +40 -0
  226. package/dist/core/vision/leader-apply.js +101 -30
  227. package/dist/core/vision/leader-apply.js.map +1 -1
  228. package/dist/core/vision/leader-cadence.d.ts +114 -0
  229. package/dist/core/vision/leader-cadence.js +127 -0
  230. package/dist/core/vision/leader-cadence.js.map +1 -0
  231. package/dist/core/vision/leader-goal-evidence.d.ts +25 -0
  232. package/dist/core/vision/leader-goal-evidence.js +36 -0
  233. package/dist/core/vision/leader-goal-evidence.js.map +1 -0
  234. package/dist/core/vision/leader-health.d.ts +53 -0
  235. package/dist/core/vision/leader-health.js +92 -0
  236. package/dist/core/vision/leader-health.js.map +1 -0
  237. package/dist/core/vision/leader-operator.d.ts +176 -0
  238. package/dist/core/vision/leader-operator.js +355 -0
  239. package/dist/core/vision/leader-operator.js.map +1 -0
  240. package/dist/core/vision/leader-run-chain.d.ts +41 -0
  241. package/dist/core/vision/leader-run-chain.js +54 -0
  242. package/dist/core/vision/leader-run-chain.js.map +1 -0
  243. package/dist/core/vision/leader-seat-plan.d.ts +68 -0
  244. package/dist/core/vision/leader-seat-plan.js +93 -0
  245. package/dist/core/vision/leader-seat-plan.js.map +1 -0
  246. package/dist/core/vision/leader-seat.d.ts +71 -5
  247. package/dist/core/vision/leader-seat.js +235 -33
  248. package/dist/core/vision/leader-seat.js.map +1 -1
  249. package/dist/core/vision/leader-thread-types.d.ts +104 -0
  250. package/dist/core/vision/leader-thread-types.js +9 -0
  251. package/dist/core/vision/leader-thread-types.js.map +1 -0
  252. package/dist/core/vision/leader-thread.d.ts +138 -0
  253. package/dist/core/vision/leader-thread.js +926 -0
  254. package/dist/core/vision/leader-thread.js.map +1 -0
  255. package/dist/core/vision/leader-types.d.ts +75 -1
  256. package/dist/core/vision/leader.d.ts +88 -18
  257. package/dist/core/vision/leader.js +269 -69
  258. package/dist/core/vision/leader.js.map +1 -1
  259. package/dist/core/web/public/next/assets/{ActionMenu-Dwjk6rUQ.js → ActionMenu-CIiX2X8w.js} +2 -2
  260. package/dist/core/web/public/next/assets/{ActionMenu-Dwjk6rUQ.js.map → ActionMenu-CIiX2X8w.js.map} +1 -1
  261. package/dist/core/web/public/next/assets/Advanced-DHsysoIL.js +2 -0
  262. package/dist/core/web/public/next/assets/{Advanced-cVYTAsfB.js.map → Advanced-DHsysoIL.js.map} +1 -1
  263. package/dist/core/web/public/next/assets/{App-IsaWDsdF.js → App-CMeAocmW.js} +5 -5
  264. package/dist/core/web/public/next/assets/{App-IsaWDsdF.js.map → App-CMeAocmW.js.map} +1 -1
  265. package/dist/core/web/public/next/assets/AppsSection-DISYnMnc.js +2 -0
  266. package/dist/core/web/public/next/assets/{AppsSection-DDqeSrty.js.map → AppsSection-DISYnMnc.js.map} +1 -1
  267. package/dist/core/web/public/next/assets/AreaTrend-DK2Y2TbZ.js +2 -0
  268. package/dist/core/web/public/next/assets/AreaTrend-DK2Y2TbZ.js.map +1 -0
  269. package/dist/core/web/public/next/assets/{AutonomyOffState-CpFYS3tQ.js → AutonomyOffState-CEPSZToP.js} +3 -3
  270. package/dist/core/web/public/next/assets/{AutonomyOffState-CpFYS3tQ.js.map → AutonomyOffState-CEPSZToP.js.map} +1 -1
  271. package/dist/core/web/public/next/assets/AutonomySection-DWc3ciAD.js +2 -0
  272. package/dist/core/web/public/next/assets/{AutonomySection-Dwn8UtOy.js.map → AutonomySection-DWc3ciAD.js.map} +1 -1
  273. package/dist/core/web/public/next/assets/AutonomyStatus-CYaHjJ9U.js +2 -0
  274. package/dist/core/web/public/next/assets/AutonomyStatus-CYaHjJ9U.js.map +1 -0
  275. package/dist/core/web/public/next/assets/{BranchBar-ISZ7xUCj.js → BranchBar-BxhdiIpx.js} +2 -2
  276. package/dist/core/web/public/next/assets/{BranchBar-ISZ7xUCj.js.map → BranchBar-BxhdiIpx.js.map} +1 -1
  277. package/dist/core/web/public/next/assets/{BudgetControl-BARVp-En.js → BudgetControl-C-0KhjRS.js} +2 -2
  278. package/dist/core/web/public/next/assets/{BudgetControl-BARVp-En.js.map → BudgetControl-C-0KhjRS.js.map} +1 -1
  279. package/dist/core/web/public/next/assets/{Button-DtE0rlWD.js → Button-D90dzI_o.js} +2 -2
  280. package/dist/core/web/public/next/assets/{Button-DtE0rlWD.js.map → Button-D90dzI_o.js.map} +1 -1
  281. package/dist/core/web/public/next/assets/{CapacityStrip-DKbKA_Aa.js → CapacityStrip-qKDBC65C.js} +2 -2
  282. package/dist/core/web/public/next/assets/{CapacityStrip-DKbKA_Aa.js.map → CapacityStrip-qKDBC65C.js.map} +1 -1
  283. package/dist/core/web/public/next/assets/ChartFrame-DY-GVUb3.js +2 -0
  284. package/dist/core/web/public/next/assets/ChartFrame-DY-GVUb3.js.map +1 -0
  285. package/dist/core/web/public/next/assets/ChartFrame-DyjmyV8N.css +1 -0
  286. package/dist/core/web/public/next/assets/ChatSection-DlT4QU6a.js +3 -0
  287. package/dist/core/web/public/next/assets/{ChatSection-C9myY4ei.js.map → ChatSection-DlT4QU6a.js.map} +1 -1
  288. package/dist/core/web/public/next/assets/{CloudBudgetForm-CvjK4Oh6.js → CloudBudgetForm-BrNun_Yu.js} +2 -2
  289. package/dist/core/web/public/next/assets/{CloudBudgetForm-CvjK4Oh6.js.map → CloudBudgetForm-BrNun_Yu.js.map} +1 -1
  290. package/dist/core/web/public/next/assets/CommandPalette-C5lDDKN0.js +2 -0
  291. package/dist/core/web/public/next/assets/CommandPalette-C5lDDKN0.js.map +1 -0
  292. package/dist/core/web/public/next/assets/CommandSection-B0xuU-yZ.css +1 -0
  293. package/dist/core/web/public/next/assets/CommandSection-DXFvPgKp.js +3 -0
  294. package/dist/core/web/public/next/assets/CommandSection-DXFvPgKp.js.map +1 -0
  295. package/dist/core/web/public/next/assets/{ConfirmDialog-CLUhzaBj.js → ConfirmDialog-BR4nZQ2D.js} +2 -2
  296. package/dist/core/web/public/next/assets/{ConfirmDialog-CLUhzaBj.js.map → ConfirmDialog-BR4nZQ2D.js.map} +1 -1
  297. package/dist/core/web/public/next/assets/{DeleteChatDialog-C_eDhV8b.js → DeleteChatDialog-BCfP12GH.js} +2 -2
  298. package/dist/core/web/public/next/assets/{DeleteChatDialog-C_eDhV8b.js.map → DeleteChatDialog-BCfP12GH.js.map} +1 -1
  299. package/dist/core/web/public/next/assets/{Dialog-BRd_B9OE.js → Dialog-D3msQlCj.js} +2 -2
  300. package/dist/core/web/public/next/assets/{Dialog-BRd_B9OE.js.map → Dialog-D3msQlCj.js.map} +1 -1
  301. package/dist/core/web/public/next/assets/{DiffPane-Cpr9soB2.js → DiffPane-Ix6hvXlY.js} +2 -2
  302. package/dist/core/web/public/next/assets/{DiffPane-Cpr9soB2.js.map → DiffPane-Ix6hvXlY.js.map} +1 -1
  303. package/dist/core/web/public/next/assets/{DiffViewer-CNwd0W3Q.js → DiffViewer-C4WKsCIe.js} +2 -2
  304. package/dist/core/web/public/next/assets/{DiffViewer-CNwd0W3Q.js.map → DiffViewer-C4WKsCIe.js.map} +1 -1
  305. package/dist/core/web/public/next/assets/DockHost-aWP7liri.js +2 -0
  306. package/dist/core/web/public/next/assets/{DockHost-BcEq2qaS.js.map → DockHost-aWP7liri.js.map} +1 -1
  307. package/dist/core/web/public/next/assets/{EmptyState-DsN1H6MC.js → EmptyState-D2IRy3Cg.js} +2 -2
  308. package/dist/core/web/public/next/assets/{EmptyState-DsN1H6MC.js.map → EmptyState-D2IRy3Cg.js.map} +1 -1
  309. package/dist/core/web/public/next/assets/{Epistemic-fycQTBRO.js → Epistemic-DMr18muX.js} +2 -2
  310. package/dist/core/web/public/next/assets/{Epistemic-fycQTBRO.js.map → Epistemic-DMr18muX.js.map} +1 -1
  311. package/dist/core/web/public/next/assets/{EvidenceTimeline-sCCAdnBK.js → EvidenceTimeline-DXmmz6Fi.js} +2 -2
  312. package/dist/core/web/public/next/assets/{EvidenceTimeline-sCCAdnBK.js.map → EvidenceTimeline-DXmmz6Fi.js.map} +1 -1
  313. package/dist/core/web/public/next/assets/FleetSection-BfplcwFU.js +3 -0
  314. package/dist/core/web/public/next/assets/FleetSection-BfplcwFU.js.map +1 -0
  315. package/dist/core/web/public/next/assets/Funnel-Dh2yVHws.js +2 -0
  316. package/dist/core/web/public/next/assets/Funnel-Dh2yVHws.js.map +1 -0
  317. package/dist/core/web/public/next/assets/{GearTray-CpDt0xwj.js → GearTray-Dt-ee32-.js} +2 -2
  318. package/dist/core/web/public/next/assets/{GearTray-CpDt0xwj.js.map → GearTray-Dt-ee32-.js.map} +1 -1
  319. package/dist/core/web/public/next/assets/GrowthSection-P9EUfGeA.js +2 -0
  320. package/dist/core/web/public/next/assets/{GrowthSection-BvZezOsX.js.map → GrowthSection-P9EUfGeA.js.map} +1 -1
  321. package/dist/core/web/public/next/assets/{HandoffDialog-B1G6gQyk.js → HandoffDialog-CLJQLe7M.js} +2 -2
  322. package/dist/core/web/public/next/assets/{HandoffDialog-B1G6gQyk.js.map → HandoffDialog-CLJQLe7M.js.map} +1 -1
  323. package/dist/core/web/public/next/assets/{Input-CI0yBHmn.js → Input-D_KRJA9V.js} +2 -2
  324. package/dist/core/web/public/next/assets/{Input-CI0yBHmn.js.map → Input-D_KRJA9V.js.map} +1 -1
  325. package/dist/core/web/public/next/assets/LeaderCard-D-7DlJuR.js +2 -0
  326. package/dist/core/web/public/next/assets/LeaderCard-D-7DlJuR.js.map +1 -0
  327. package/dist/core/web/public/next/assets/LeaderCard-DNsbLwY3.css +1 -0
  328. package/dist/core/web/public/next/assets/LeaderConversation-DGZjWI-E.js +2 -0
  329. package/dist/core/web/public/next/assets/LeaderConversation-DGZjWI-E.js.map +1 -0
  330. package/dist/core/web/public/next/assets/LeaderConversation-DPHUTq6W.css +1 -0
  331. package/dist/core/web/public/next/assets/MatrixHeatmap-C7BCG2d7.js +2 -0
  332. package/dist/core/web/public/next/assets/MatrixHeatmap-C7BCG2d7.js.map +1 -0
  333. package/dist/core/web/public/next/assets/McpSection-DGbRcyv8.js +2 -0
  334. package/dist/core/web/public/next/assets/{McpSection-nuXer4K-.js.map → McpSection-DGbRcyv8.js.map} +1 -1
  335. package/dist/core/web/public/next/assets/{MessageMarkdown-BCe4TsXk.js → MessageMarkdown-DFvk06qG.js} +3 -3
  336. package/dist/core/web/public/next/assets/{MessageMarkdown-BCe4TsXk.js.map → MessageMarkdown-DFvk06qG.js.map} +1 -1
  337. package/dist/core/web/public/next/assets/{MessageMarkdownRenderer-DL3LU5kL.js → MessageMarkdownRenderer-BAv4oEUf.js} +2 -2
  338. package/dist/core/web/public/next/assets/{MessageMarkdownRenderer-DL3LU5kL.js.map → MessageMarkdownRenderer-BAv4oEUf.js.map} +1 -1
  339. package/dist/core/web/public/next/assets/{Meter-b69LM0mU.js → Meter-CMj-VafN.js} +2 -2
  340. package/dist/core/web/public/next/assets/{Meter-b69LM0mU.js.map → Meter-CMj-VafN.js.map} +1 -1
  341. package/dist/core/web/public/next/assets/MindSection-C6kLPIjt.js +3 -0
  342. package/dist/core/web/public/next/assets/MindSection-C6kLPIjt.js.map +1 -0
  343. package/dist/core/web/public/next/assets/{MutationTokenDialog-Bm34BNVV.js → MutationTokenDialog-DbnO8aYi.js} +2 -2
  344. package/dist/core/web/public/next/assets/{MutationTokenDialog-Bm34BNVV.js.map → MutationTokenDialog-DbnO8aYi.js.map} +1 -1
  345. package/dist/core/web/public/next/assets/NeedsYouDrawer-crsiX-Nc.js +3 -0
  346. package/dist/core/web/public/next/assets/NeedsYouDrawer-crsiX-Nc.js.map +1 -0
  347. package/dist/core/web/public/next/assets/{NeedsYouList-D5Kk549g.js → NeedsYouList-CCsijdWt.js} +2 -2
  348. package/dist/core/web/public/next/assets/{NeedsYouList-D5Kk549g.js.map → NeedsYouList-CCsijdWt.js.map} +1 -1
  349. package/dist/core/web/public/next/assets/NewChatDialog-BlCHtOIr.js +3 -0
  350. package/dist/core/web/public/next/assets/{NewChatDialog-BqFTWgHU.js.map → NewChatDialog-BlCHtOIr.js.map} +1 -1
  351. package/dist/core/web/public/next/assets/{OnboardingFlow-DcDsguAM.js → OnboardingFlow-Cy9BA9eR.js} +3 -3
  352. package/dist/core/web/public/next/assets/{OnboardingFlow-DcDsguAM.js.map → OnboardingFlow-Cy9BA9eR.js.map} +1 -1
  353. package/dist/core/web/public/next/assets/OnboardingGate-BXpNFoLt.js +3 -0
  354. package/dist/core/web/public/next/assets/{OnboardingGate-BZafM1Vf.js.map → OnboardingGate-BXpNFoLt.js.map} +1 -1
  355. package/dist/core/web/public/next/assets/PreviewPane-COid5A0f.js +2 -0
  356. package/dist/core/web/public/next/assets/{PreviewPane-zT3gK9TD.js.map → PreviewPane-COid5A0f.js.map} +1 -1
  357. package/dist/core/web/public/next/assets/{ProviderLogo-AwHn2sKm.js → ProviderLogo-Cq-CYIwT.js} +2 -2
  358. package/dist/core/web/public/next/assets/{ProviderLogo-AwHn2sKm.js.map → ProviderLogo-Cq-CYIwT.js.map} +1 -1
  359. package/dist/core/web/public/next/assets/{RailStatus-xHrovWvI.js → RailStatus-Co5UB6We.js} +2 -2
  360. package/dist/core/web/public/next/assets/{RailStatus-xHrovWvI.js.map → RailStatus-Co5UB6We.js.map} +1 -1
  361. package/dist/core/web/public/next/assets/{RefreshIndicator-SEFZlMB2.js → RefreshIndicator-DO9ibnSq.js} +2 -2
  362. package/dist/core/web/public/next/assets/{RefreshIndicator-SEFZlMB2.js.map → RefreshIndicator-DO9ibnSq.js.map} +1 -1
  363. package/dist/core/web/public/next/assets/ResourcePoolConsoleApp-Dr2WRgkq.js +7 -0
  364. package/dist/core/web/public/next/assets/{ResourcePoolConsoleApp-CAxPQ4sZ.js.map → ResourcePoolConsoleApp-Dr2WRgkq.js.map} +1 -1
  365. package/dist/core/web/public/next/assets/ResourcesChrome-CwMnbqI1.js +3 -0
  366. package/dist/core/web/public/next/assets/ResourcesChrome-CwMnbqI1.js.map +1 -0
  367. package/dist/core/web/public/next/assets/ResourcesDrawer-B_Xp_JNc.js +2 -0
  368. package/dist/core/web/public/next/assets/ResourcesDrawer-B_Xp_JNc.js.map +1 -0
  369. package/dist/core/web/public/next/assets/ResourcesDrawer-DrGoO8KG.css +1 -0
  370. package/dist/core/web/public/next/assets/{RouteErrorBoundary-C8WGiixc.js → RouteErrorBoundary-SkNhhUbt.js} +2 -2
  371. package/dist/core/web/public/next/assets/{RouteErrorBoundary-C8WGiixc.js.map → RouteErrorBoundary-SkNhhUbt.js.map} +1 -1
  372. package/dist/core/web/public/next/assets/{RunInCloudAction-1-IPLYhf.js → RunInCloudAction-BXPlZwJQ.js} +2 -2
  373. package/dist/core/web/public/next/assets/{RunInCloudAction-1-IPLYhf.js.map → RunInCloudAction-BXPlZwJQ.js.map} +1 -1
  374. package/dist/core/web/public/next/assets/{SeatSelector-DpwNiX8F.js → SeatSelector-J5R3zDkB.js} +3 -3
  375. package/dist/core/web/public/next/assets/{SeatSelector-DpwNiX8F.js.map → SeatSelector-J5R3zDkB.js.map} +1 -1
  376. package/dist/core/web/public/next/assets/{Segmented-Wt1ATod9.js → Segmented-CGh_-tBb.js} +2 -2
  377. package/dist/core/web/public/next/assets/{Segmented-Wt1ATod9.js.map → Segmented-CGh_-tBb.js.map} +1 -1
  378. package/dist/core/web/public/next/assets/{Select-By-V9lMc.js → Select-CWnmUzs3.js} +2 -2
  379. package/dist/core/web/public/next/assets/{Select-By-V9lMc.js.map → Select-CWnmUzs3.js.map} +1 -1
  380. package/dist/core/web/public/next/assets/{SessionGate-WROS02tK.js → SessionGate-sp4KsnUo.js} +2 -2
  381. package/dist/core/web/public/next/assets/{SessionGate-WROS02tK.js.map → SessionGate-sp4KsnUo.js.map} +1 -1
  382. package/dist/core/web/public/next/assets/{SessionInsightChip-DNUcruwp.js → SessionInsightChip-DLFAzdbi.js} +2 -2
  383. package/dist/core/web/public/next/assets/{SessionInsightChip-DNUcruwp.js.map → SessionInsightChip-DLFAzdbi.js.map} +1 -1
  384. package/dist/core/web/public/next/assets/{SessionSearch-UHtt7a8f.js → SessionSearch-DbFjwR1h.js} +2 -2
  385. package/dist/core/web/public/next/assets/{SessionSearch-UHtt7a8f.js.map → SessionSearch-DbFjwR1h.js.map} +1 -1
  386. package/dist/core/web/public/next/assets/{SettingsSection-Bf74l0Gj.js → SettingsSection-Ch23msJ5.js} +2 -2
  387. package/dist/core/web/public/next/assets/SettingsSection-Ch23msJ5.js.map +1 -0
  388. package/dist/core/web/public/next/assets/{SetupChecklist-CzpEcfOl.js → SetupChecklist-Bd76MBAR.js} +2 -2
  389. package/dist/core/web/public/next/assets/{SetupChecklist-CzpEcfOl.js.map → SetupChecklist-Bd76MBAR.js.map} +1 -1
  390. package/dist/core/web/public/next/assets/ShadowDecisions-C5RAY91f.js +3 -0
  391. package/dist/core/web/public/next/assets/ShadowDecisions-C5RAY91f.js.map +1 -0
  392. package/dist/core/web/public/next/assets/{Sheet-HkBOBMTT.js → Sheet-BZ2AG4Eo.js} +2 -2
  393. package/dist/core/web/public/next/assets/{Sheet-HkBOBMTT.js.map → Sheet-BZ2AG4Eo.js.map} +1 -1
  394. package/dist/core/web/public/next/assets/{ShortcutsOverlay-DiigiT8H.js → ShortcutsOverlay-C8n8y3zf.js} +2 -2
  395. package/dist/core/web/public/next/assets/{ShortcutsOverlay-DiigiT8H.js.map → ShortcutsOverlay-C8n8y3zf.js.map} +1 -1
  396. package/dist/core/web/public/next/assets/Sidebar-DN--cPYN.js +3 -0
  397. package/dist/core/web/public/next/assets/{Sidebar-C9YtBYVZ.js.map → Sidebar-DN--cPYN.js.map} +1 -1
  398. package/dist/core/web/public/next/assets/{Slider-DaEDws-b.js → Slider-KVoJLDD6.js} +2 -2
  399. package/dist/core/web/public/next/assets/{Slider-DaEDws-b.js.map → Slider-KVoJLDD6.js.map} +1 -1
  400. package/dist/core/web/public/next/assets/StatTile-C4KgjltA.js +2 -0
  401. package/dist/core/web/public/next/assets/StatTile-C4KgjltA.js.map +1 -0
  402. package/dist/core/web/public/next/assets/StatTile-CNCqDoPO.css +1 -0
  403. package/dist/core/web/public/next/assets/{StatusBadge-CXG3iNL4.js → StatusBadge-CXsYqmdU.js} +2 -2
  404. package/dist/core/web/public/next/assets/{StatusBadge-CXG3iNL4.js.map → StatusBadge-CXsYqmdU.js.map} +1 -1
  405. package/dist/core/web/public/next/assets/StepBand-BMtVOFpK.js +2 -0
  406. package/dist/core/web/public/next/assets/StepBand-BMtVOFpK.js.map +1 -0
  407. package/dist/core/web/public/next/assets/{Surface-5bNA08tK.js → Surface-BfDmQcKe.js} +2 -2
  408. package/dist/core/web/public/next/assets/{Surface-5bNA08tK.js.map → Surface-BfDmQcKe.js.map} +1 -1
  409. package/dist/core/web/public/next/assets/Swimlane-B9Exxekk.js +2 -0
  410. package/dist/core/web/public/next/assets/Swimlane-B9Exxekk.js.map +1 -0
  411. package/dist/core/web/public/next/assets/Swimlane-Bf4Rjoy9.css +1 -0
  412. package/dist/core/web/public/next/assets/{Switch-BmCzfFnu.js → Switch-9NtO_6Lj.js} +2 -2
  413. package/dist/core/web/public/next/assets/{Switch-BmCzfFnu.js.map → Switch-9NtO_6Lj.js.map} +1 -1
  414. package/dist/core/web/public/next/assets/{Tag-WSUIaMVy.js → Tag-DscCRFcN.js} +2 -2
  415. package/dist/core/web/public/next/assets/{Tag-WSUIaMVy.js.map → Tag-DscCRFcN.js.map} +1 -1
  416. package/dist/core/web/public/next/assets/{TerminalPane-BVFgYX6K.js → TerminalPane-B668-DJW.js} +5 -5
  417. package/dist/core/web/public/next/assets/{TerminalPane-BVFgYX6K.js.map → TerminalPane-B668-DJW.js.map} +1 -1
  418. package/dist/core/web/public/next/assets/UniverseConsoleApp-BUV_brY7.js +2 -0
  419. package/dist/core/web/public/next/assets/{UniverseConsoleApp-BpphLqoz.js.map → UniverseConsoleApp-BUV_brY7.js.map} +1 -1
  420. package/dist/core/web/public/next/assets/{UniverseView-DbpbSMwO.js → UniverseView-DG70zH0W.js} +4 -4
  421. package/dist/core/web/public/next/assets/{UniverseView-DbpbSMwO.js.map → UniverseView-DG70zH0W.js.map} +1 -1
  422. package/dist/core/web/public/next/assets/UsageSection-DY7uOTm1.js +3 -0
  423. package/dist/core/web/public/next/assets/UsageSection-DY7uOTm1.js.map +1 -0
  424. package/dist/core/web/public/next/assets/VerseConsoleApp-CWU6R3By.js +3 -0
  425. package/dist/core/web/public/next/assets/VerseConsoleApp-CWU6R3By.js.map +1 -0
  426. package/dist/core/web/public/next/assets/Workspace-D1nP9BhD.js +10 -0
  427. package/dist/core/web/public/next/assets/{Workspace-RXy0pqp6.js.map → Workspace-D1nP9BhD.js.map} +1 -1
  428. package/dist/core/web/public/next/assets/actions-CY-PjpGc.js +2 -0
  429. package/dist/core/web/public/next/assets/{actions-BZTidCXZ.js.map → actions-CY-PjpGc.js.map} +1 -1
  430. package/dist/core/web/public/next/assets/actions-DkWhhWIg.css +1 -0
  431. package/dist/core/web/public/next/assets/{apps-model-CHO133qt.js → apps-model-Du02KhAf.js} +2 -2
  432. package/dist/core/web/public/next/assets/{apps-model-CHO133qt.js.map → apps-model-Du02KhAf.js.map} +1 -1
  433. package/dist/core/web/public/next/assets/{authority-model-8NeAEwAF.js → authority-model-79SeuKlJ.js} +2 -2
  434. package/dist/core/web/public/next/assets/{authority-model-8NeAEwAF.js.map → authority-model-79SeuKlJ.js.map} +1 -1
  435. package/dist/core/web/public/next/assets/autonomy-ladder-BGWmZzP7.css +1 -0
  436. package/dist/core/web/public/next/assets/autonomy-ladder.module-ArDv4bkr.js +2 -0
  437. package/dist/core/web/public/next/assets/autonomy-ladder.module-ArDv4bkr.js.map +1 -0
  438. package/dist/core/web/public/next/assets/budget-queries-D8QV5XtH.js +2 -0
  439. package/dist/core/web/public/next/assets/{budget-queries-DFF-3ICg.js.map → budget-queries-D8QV5XtH.js.map} +1 -1
  440. package/dist/core/web/public/next/assets/{capacity-strip-model-5ViUgUlP.js → capacity-strip-model-BwZ1ZbkU.js} +2 -2
  441. package/dist/core/web/public/next/assets/{capacity-strip-model-5ViUgUlP.js.map → capacity-strip-model-BwZ1ZbkU.js.map} +1 -1
  442. package/dist/core/web/public/next/assets/charts-BZ50mZD_.js +2 -0
  443. package/dist/core/web/public/next/assets/charts-BZ50mZD_.js.map +1 -0
  444. package/dist/core/web/public/next/assets/charts-ClCB18la.css +1 -0
  445. package/dist/core/web/public/next/assets/{cloud-model-CfRydq8N.js → cloud-model-BDivRMqv.js} +2 -2
  446. package/dist/core/web/public/next/assets/{cloud-model-CfRydq8N.js.map → cloud-model-BDivRMqv.js.map} +1 -1
  447. package/dist/core/web/public/next/assets/{cloud-queries-DmptbjS8.js → cloud-queries-BPQQ5_pJ.js} +2 -2
  448. package/dist/core/web/public/next/assets/{cloud-queries-DmptbjS8.js.map → cloud-queries-BPQQ5_pJ.js.map} +1 -1
  449. package/dist/core/web/public/next/assets/{colors-BZ3a9wFf.js → colors-DvK0wMHH.js} +2 -2
  450. package/dist/core/web/public/next/assets/{colors-BZ3a9wFf.js.map → colors-DvK0wMHH.js.map} +1 -1
  451. package/dist/core/web/public/next/assets/{command-catalog-ffCAijVY.js → command-catalog-BIntSa9l.js} +2 -2
  452. package/dist/core/web/public/next/assets/command-catalog-BIntSa9l.js.map +1 -0
  453. package/dist/core/web/public/next/assets/{context-model-CDeyP0cA.js → context-model-Br8t9jgG.js} +2 -2
  454. package/dist/core/web/public/next/assets/{context-model-CDeyP0cA.js.map → context-model-Br8t9jgG.js.map} +1 -1
  455. package/dist/core/web/public/next/assets/{context-model-Bb15chFt.js → context-model-CokrgEUq.js} +3 -3
  456. package/dist/core/web/public/next/assets/{context-model-Bb15chFt.js.map → context-model-CokrgEUq.js.map} +1 -1
  457. package/dist/core/web/public/next/assets/context-queries-eL3caKVG.js +2 -0
  458. package/dist/core/web/public/next/assets/{context-queries-_9bFWb9v.js.map → context-queries-eL3caKVG.js.map} +1 -1
  459. package/dist/core/web/public/next/assets/{control-queries-CXtmZZH6.js → control-queries-B9K-wmcB.js} +2 -2
  460. package/dist/core/web/public/next/assets/{control-queries-CXtmZZH6.js.map → control-queries-B9K-wmcB.js.map} +1 -1
  461. package/dist/core/web/public/next/assets/{copy-setup-BIp0iaiZ.js → copy-setup-XMgCC5f8.js} +2 -2
  462. package/dist/core/web/public/next/assets/{copy-setup-BIp0iaiZ.js.map → copy-setup-XMgCC5f8.js.map} +1 -1
  463. package/dist/core/web/public/next/assets/{dock-icons-Cc43W7r4.js → dock-icons-BJ6ZqB2t.js} +2 -2
  464. package/dist/core/web/public/next/assets/{dock-icons-Cc43W7r4.js.map → dock-icons-BJ6ZqB2t.js.map} +1 -1
  465. package/dist/core/web/public/next/assets/{fleet-model-DOK8ZtEt.js → fleet-model-BvDR3gjp.js} +2 -2
  466. package/dist/core/web/public/next/assets/{fleet-model-DOK8ZtEt.js.map → fleet-model-BvDR3gjp.js.map} +1 -1
  467. package/dist/core/web/public/next/assets/{fleet-queries-BeEAqD6y.js → fleet-queries-W2UFVMZJ.js} +2 -2
  468. package/dist/core/web/public/next/assets/{fleet-queries-BeEAqD6y.js.map → fleet-queries-W2UFVMZJ.js.map} +1 -1
  469. package/dist/core/web/public/next/assets/{focus-trap-ChZ5EFfM.js → focus-trap-CtI1SlMX.js} +2 -2
  470. package/dist/core/web/public/next/assets/{focus-trap-ChZ5EFfM.js.map → focus-trap-CtI1SlMX.js.map} +1 -1
  471. package/dist/core/web/public/next/assets/{format-BmH2yWL6.js → format-CH4g_sl1.js} +2 -2
  472. package/dist/core/web/public/next/assets/{format-BmH2yWL6.js.map → format-CH4g_sl1.js.map} +1 -1
  473. package/dist/core/web/public/next/assets/{format-DKrNjdwD.js → format-D7nBg2bn.js} +2 -2
  474. package/dist/core/web/public/next/assets/{format-DKrNjdwD.js.map → format-D7nBg2bn.js.map} +1 -1
  475. package/dist/core/web/public/next/assets/{git-model-BFwAVbxF.js → git-model-Dnkd1TnK.js} +2 -2
  476. package/dist/core/web/public/next/assets/{git-model-BFwAVbxF.js.map → git-model-Dnkd1TnK.js.map} +1 -1
  477. package/dist/core/web/public/next/assets/global-CMNW_dqn.js +2 -0
  478. package/dist/core/web/public/next/assets/{global-y_exIyAP.js.map → global-CMNW_dqn.js.map} +1 -1
  479. package/dist/core/web/public/next/assets/guarded-runners-YeAc9wLQ.js +2 -0
  480. package/dist/core/web/public/next/assets/{guarded-runners-Cd4POBtI.js.map → guarded-runners-YeAc9wLQ.js.map} +1 -1
  481. package/dist/core/web/public/next/assets/{icons-CygCEFWs.js → icons-D1sYbCTQ.js} +2 -2
  482. package/dist/core/web/public/next/assets/{icons-CygCEFWs.js.map → icons-D1sYbCTQ.js.map} +1 -1
  483. package/dist/core/web/public/next/assets/{index-CyK31YRm.js → index-DZ-UQ7v8.js} +3 -3
  484. package/dist/core/web/public/next/assets/{index-CyK31YRm.js.map → index-DZ-UQ7v8.js.map} +1 -1
  485. package/dist/core/web/public/next/assets/leader-focus-BjeJv7CW.js +2 -0
  486. package/dist/core/web/public/next/assets/leader-focus-BjeJv7CW.js.map +1 -0
  487. package/dist/core/web/public/next/assets/leader-thread-types-CDb-VPPO.js +2 -0
  488. package/dist/core/web/public/next/assets/leader-thread-types-CDb-VPPO.js.map +1 -0
  489. package/dist/core/web/public/next/assets/{live-model-D7hilYFk.js → live-model-D_32RAOR.js} +2 -2
  490. package/dist/core/web/public/next/assets/{live-model-D7hilYFk.js.map → live-model-D_32RAOR.js.map} +1 -1
  491. package/dist/core/web/public/next/assets/{mind.module-B15k0Y9q.js → mind.module-7hA92hRg.js} +2 -2
  492. package/dist/core/web/public/next/assets/{mind.module-B15k0Y9q.js.map → mind.module-7hA92hRg.js.map} +1 -1
  493. package/dist/core/web/public/next/assets/mutations-DQPbFdRJ.js +2 -0
  494. package/dist/core/web/public/next/assets/{mutations-CWlxEMEm.js.map → mutations-DQPbFdRJ.js.map} +1 -1
  495. package/dist/core/web/public/next/assets/{nav-mimleI0R.js → nav-0dOYe2rJ.js} +2 -2
  496. package/dist/core/web/public/next/assets/{nav-mimleI0R.js.map → nav-0dOYe2rJ.js.map} +1 -1
  497. package/dist/core/web/public/next/assets/{overnight-queries-DJ4mZKSj.js → overnight-queries-C4wOnFtE.js} +2 -2
  498. package/dist/core/web/public/next/assets/{overnight-queries-DJ4mZKSj.js.map → overnight-queries-C4wOnFtE.js.map} +1 -1
  499. package/dist/core/web/public/next/assets/primitives-2A5Eq8FQ.js +1 -0
  500. package/dist/core/web/public/next/assets/{queries-Bw1McHTj.js → queries-BTXWdZzU.js} +2 -2
  501. package/dist/core/web/public/next/assets/{queries-Bw1McHTj.js.map → queries-BTXWdZzU.js.map} +1 -1
  502. package/dist/core/web/public/next/assets/{reasoning-pref-KkhI_5-j.js → reasoning-pref-Ca6lN6x_.js} +2 -2
  503. package/dist/core/web/public/next/assets/{reasoning-pref-KkhI_5-j.js.map → reasoning-pref-Ca6lN6x_.js.map} +1 -1
  504. package/dist/core/web/public/next/assets/{reveal-anchor-CCCx_kfT.js → reveal-anchor-DfNLgK_I.js} +2 -2
  505. package/dist/core/web/public/next/assets/{reveal-anchor-CCCx_kfT.js.map → reveal-anchor-DfNLgK_I.js.map} +1 -1
  506. package/dist/core/web/public/next/assets/seat-subscription-C5uPHBsN.js +2 -0
  507. package/dist/core/web/public/next/assets/{seat-subscription-BhUUz7VL.js.map → seat-subscription-C5uPHBsN.js.map} +1 -1
  508. package/dist/core/web/public/next/assets/{sidebar-model-Dcd437cf.js → sidebar-model-CLCdqwkR.js} +2 -2
  509. package/dist/core/web/public/next/assets/{sidebar-model-Dcd437cf.js.map → sidebar-model-CLCdqwkR.js.map} +1 -1
  510. package/dist/core/web/public/next/assets/{slots-BL_J5mmV.js → slots-C-qBeu-8.js} +3 -3
  511. package/dist/core/web/public/next/assets/{slots-BL_J5mmV.js.map → slots-C-qBeu-8.js.map} +1 -1
  512. package/dist/core/web/public/next/assets/{surface-data-C3UAQ4QX.js → surface-data-Dj71tdD-.js} +2 -2
  513. package/dist/core/web/public/next/assets/{surface-data-C3UAQ4QX.js.map → surface-data-Dj71tdD-.js.map} +1 -1
  514. package/dist/core/web/public/next/assets/surface-prefetch-B0WdJOJG.js +2 -0
  515. package/dist/core/web/public/next/assets/surface-prefetch-B0WdJOJG.js.map +1 -0
  516. package/dist/core/web/public/next/assets/{tasks-model-CzHvclVm.js → tasks-model-O8yR5YXp.js} +2 -2
  517. package/dist/core/web/public/next/assets/{tasks-model-CzHvclVm.js.map → tasks-model-O8yR5YXp.js.map} +1 -1
  518. package/dist/core/web/public/next/assets/{terminal-icons-BwgQTQP0.js → terminal-icons-CoRZq9iO.js} +2 -2
  519. package/dist/core/web/public/next/assets/{terminal-icons-BwgQTQP0.js.map → terminal-icons-CoRZq9iO.js.map} +1 -1
  520. package/dist/core/web/public/next/assets/thread-data-DQB_g66d.js +2 -0
  521. package/dist/core/web/public/next/assets/thread-data-DQB_g66d.js.map +1 -0
  522. package/dist/core/web/public/next/assets/{usage-queries-pXxvy54x.js → usage-queries-AdjEyEtn.js} +2 -2
  523. package/dist/core/web/public/next/assets/{usage-queries-pXxvy54x.js.map → usage-queries-AdjEyEtn.js.map} +1 -1
  524. package/dist/core/web/public/next/assets/{use-guarded-action-EgVWjM5c.js → use-guarded-action-CuuMHeDX.js} +2 -2
  525. package/dist/core/web/public/next/assets/{use-guarded-action-EgVWjM5c.js.map → use-guarded-action-CuuMHeDX.js.map} +1 -1
  526. package/dist/core/web/public/next/assets/{use-ticker-BoqFxRFG.js → use-ticker-BBcp02SZ.js} +2 -2
  527. package/dist/core/web/public/next/assets/{use-ticker-BoqFxRFG.js.map → use-ticker-BBcp02SZ.js.map} +1 -1
  528. package/dist/core/web/public/next/assets/{use-token-gate-DSNIIpI6.js → use-token-gate-CbXVYQYI.js} +2 -2
  529. package/dist/core/web/public/next/assets/{use-token-gate-DSNIIpI6.js.map → use-token-gate-CbXVYQYI.js.map} +1 -1
  530. package/dist/core/web/public/next/assets/{useOnboarding-Bk0VnkxQ.js → useOnboarding-C_Fpe_sH.js} +2 -2
  531. package/dist/core/web/public/next/assets/{useOnboarding-Bk0VnkxQ.js.map → useOnboarding-C_Fpe_sH.js.map} +1 -1
  532. package/dist/core/web/public/next/assets/{useSeatsRefresh-q7Id9RcW.js → useSeatsRefresh-Co1CnxLc.js} +2 -2
  533. package/dist/core/web/public/next/assets/{useSeatsRefresh-q7Id9RcW.js.map → useSeatsRefresh-Co1CnxLc.js.map} +1 -1
  534. package/dist/core/web/public/next/assets/{useVerseTranscript-CqH51rt9.js → useVerseTranscript-DgbigUlV.js} +2 -2
  535. package/dist/core/web/public/next/assets/{useVerseTranscript-CqH51rt9.js.map → useVerseTranscript-DgbigUlV.js.map} +1 -1
  536. package/dist/core/web/public/next/assets/{verse-icons-DsG1dOQx.js → verse-icons-S56hIiXS.js} +2 -2
  537. package/dist/core/web/public/next/assets/{verse-icons-DsG1dOQx.js.map → verse-icons-S56hIiXS.js.map} +1 -1
  538. package/dist/core/web/public/next/assets/verse-model-DAVevkNe.js +2 -0
  539. package/dist/core/web/public/next/assets/{verse-model-JTuvRBVK.js.map → verse-model-DAVevkNe.js.map} +1 -1
  540. package/dist/core/web/public/next/assets/{warmup-Bv1RumVq.js → warmup-B_RAtNZ_.js} +3 -3
  541. package/dist/core/web/public/next/assets/{warmup-Bv1RumVq.js.map → warmup-B_RAtNZ_.js.map} +1 -1
  542. package/dist/core/web/public/next/assets/{why-seat-model-Cau8qG6O.js → why-seat-model-M_r0wX3b.js} +2 -2
  543. package/dist/core/web/public/next/assets/{why-seat-model-Cau8qG6O.js.map → why-seat-model-M_r0wX3b.js.map} +1 -1
  544. package/dist/core/web/public/next/assets/{workspace-model-D-SLfads.js → workspace-model-dji5-Al3.js} +2 -2
  545. package/dist/core/web/public/next/assets/{workspace-model-D-SLfads.js.map → workspace-model-dji5-Al3.js.map} +1 -1
  546. package/dist/core/web/public/next/index.html +1 -1
  547. package/dist/core/web/read-projection-worker.js +2 -1
  548. package/dist/core/web/read-projection-worker.js.map +1 -1
  549. package/dist/core/web/read-projections.d.ts +3 -0
  550. package/dist/core/web/read-projections.js +2 -2
  551. package/dist/core/web/read-projections.js.map +1 -1
  552. package/dist/core/web/visibility.js +3 -4
  553. package/dist/core/web/visibility.js.map +1 -1
  554. package/dist/release-dependency-inventory.json +1 -1
  555. package/package.json +3 -2
  556. package/dist/core/web/public/next/assets/Advanced-cVYTAsfB.js +0 -2
  557. package/dist/core/web/public/next/assets/AppsSection-DDqeSrty.js +0 -2
  558. package/dist/core/web/public/next/assets/AreaTrend-C32rUaxm.js +0 -2
  559. package/dist/core/web/public/next/assets/AreaTrend-C32rUaxm.js.map +0 -1
  560. package/dist/core/web/public/next/assets/AutonomySection-Dwn8UtOy.js +0 -2
  561. package/dist/core/web/public/next/assets/ChartFrame-BVuBe6RP.css +0 -1
  562. package/dist/core/web/public/next/assets/ChartFrame-DK_BDXCt.js +0 -2
  563. package/dist/core/web/public/next/assets/ChartFrame-DK_BDXCt.js.map +0 -1
  564. package/dist/core/web/public/next/assets/ChatSection-C9myY4ei.js +0 -3
  565. package/dist/core/web/public/next/assets/CommandPalette-DzPsth0u.js +0 -2
  566. package/dist/core/web/public/next/assets/CommandPalette-DzPsth0u.js.map +0 -1
  567. package/dist/core/web/public/next/assets/CommandSection-Brp73iox.js +0 -3
  568. package/dist/core/web/public/next/assets/CommandSection-Brp73iox.js.map +0 -1
  569. package/dist/core/web/public/next/assets/CommandSection-CvAVd1w4.css +0 -1
  570. package/dist/core/web/public/next/assets/DockHost-BcEq2qaS.js +0 -2
  571. package/dist/core/web/public/next/assets/FleetSection-BG8iGraG.js +0 -3
  572. package/dist/core/web/public/next/assets/FleetSection-BG8iGraG.js.map +0 -1
  573. package/dist/core/web/public/next/assets/Funnel-B88_wpA4.js +0 -2
  574. package/dist/core/web/public/next/assets/Funnel-B88_wpA4.js.map +0 -1
  575. package/dist/core/web/public/next/assets/GrowthSection-BvZezOsX.js +0 -2
  576. package/dist/core/web/public/next/assets/LeaderCard-BxxiEg4e.js +0 -2
  577. package/dist/core/web/public/next/assets/LeaderCard-BxxiEg4e.js.map +0 -1
  578. package/dist/core/web/public/next/assets/MatrixHeatmap-iPFEU2Tv.js +0 -2
  579. package/dist/core/web/public/next/assets/MatrixHeatmap-iPFEU2Tv.js.map +0 -1
  580. package/dist/core/web/public/next/assets/McpSection-nuXer4K-.js +0 -2
  581. package/dist/core/web/public/next/assets/MindSection-Dc5v5rH3.js +0 -2
  582. package/dist/core/web/public/next/assets/MindSection-Dc5v5rH3.js.map +0 -1
  583. package/dist/core/web/public/next/assets/NeedsYouDrawer-N1cWJjpz.js +0 -3
  584. package/dist/core/web/public/next/assets/NeedsYouDrawer-N1cWJjpz.js.map +0 -1
  585. package/dist/core/web/public/next/assets/NewChatDialog-BqFTWgHU.js +0 -3
  586. package/dist/core/web/public/next/assets/OnboardingGate-BZafM1Vf.js +0 -3
  587. package/dist/core/web/public/next/assets/PreviewPane-zT3gK9TD.js +0 -2
  588. package/dist/core/web/public/next/assets/ResourcePoolConsoleApp-CAxPQ4sZ.js +0 -7
  589. package/dist/core/web/public/next/assets/ResourcesChrome-BnhnEdJe.js +0 -3
  590. package/dist/core/web/public/next/assets/ResourcesChrome-BnhnEdJe.js.map +0 -1
  591. package/dist/core/web/public/next/assets/ResourcesDrawer-BAFGodny.js +0 -2
  592. package/dist/core/web/public/next/assets/ResourcesDrawer-BAFGodny.js.map +0 -1
  593. package/dist/core/web/public/next/assets/ResourcesDrawer-BCFJ2Uq8.css +0 -1
  594. package/dist/core/web/public/next/assets/SettingsSection-Bf74l0Gj.js.map +0 -1
  595. package/dist/core/web/public/next/assets/Sidebar-C9YtBYVZ.js +0 -3
  596. package/dist/core/web/public/next/assets/StatTile-BuLMsJMx.css +0 -1
  597. package/dist/core/web/public/next/assets/StatTile-CTX41O6y.js +0 -2
  598. package/dist/core/web/public/next/assets/StatTile-CTX41O6y.js.map +0 -1
  599. package/dist/core/web/public/next/assets/StepBand-jJTqYIdX.js +0 -2
  600. package/dist/core/web/public/next/assets/StepBand-jJTqYIdX.js.map +0 -1
  601. package/dist/core/web/public/next/assets/Swimlane-LrslsGxw.js +0 -2
  602. package/dist/core/web/public/next/assets/Swimlane-LrslsGxw.js.map +0 -1
  603. package/dist/core/web/public/next/assets/Swimlane-o6_Zsrnr.css +0 -1
  604. package/dist/core/web/public/next/assets/UniverseConsoleApp-BpphLqoz.js +0 -2
  605. package/dist/core/web/public/next/assets/UsageSection-CUlaKtws.js +0 -3
  606. package/dist/core/web/public/next/assets/UsageSection-CUlaKtws.js.map +0 -1
  607. package/dist/core/web/public/next/assets/VerseConsoleApp-DXDv1aOi.js +0 -3
  608. package/dist/core/web/public/next/assets/VerseConsoleApp-DXDv1aOi.js.map +0 -1
  609. package/dist/core/web/public/next/assets/Workspace-RXy0pqp6.js +0 -10
  610. package/dist/core/web/public/next/assets/actions-BZTidCXZ.js +0 -2
  611. package/dist/core/web/public/next/assets/actions-BmIf9avl.css +0 -1
  612. package/dist/core/web/public/next/assets/budget-queries-DFF-3ICg.js +0 -2
  613. package/dist/core/web/public/next/assets/charts-CzxWrZn7.js +0 -2
  614. package/dist/core/web/public/next/assets/charts-CzxWrZn7.js.map +0 -1
  615. package/dist/core/web/public/next/assets/charts-DhKTrQLw.css +0 -1
  616. package/dist/core/web/public/next/assets/command-catalog-ffCAijVY.js.map +0 -1
  617. package/dist/core/web/public/next/assets/context-queries-_9bFWb9v.js +0 -2
  618. package/dist/core/web/public/next/assets/global-y_exIyAP.js +0 -2
  619. package/dist/core/web/public/next/assets/guarded-runners-Cd4POBtI.js +0 -2
  620. package/dist/core/web/public/next/assets/mutations-CWlxEMEm.js +0 -2
  621. package/dist/core/web/public/next/assets/primitives-DMijqcu0.js +0 -1
  622. package/dist/core/web/public/next/assets/seat-subscription-BhUUz7VL.js +0 -2
  623. package/dist/core/web/public/next/assets/surface-prefetch-BXKjPsV5.js +0 -2
  624. package/dist/core/web/public/next/assets/surface-prefetch-BXKjPsV5.js.map +0 -1
  625. package/dist/core/web/public/next/assets/verse-model-JTuvRBVK.js +0 -2
@@ -1 +1 @@
1
- {"version":3,"file":"BudgetControl-BARVp-En.js","names":[],"sources":["../../../../../../src/web-ui/routes/verse/budget/BudgetControl.module.css","../../../../../../src/web-ui/routes/verse/budget/BudgetControl.tsx"],"sourcesContent":["/* Budget panel. Hairlines and whitespace, no nested boxes (DESIGN-V2 §6).\n Every state is a WORD first; colour reinforces it. Status tokens are\n defined for both themes in tokens.css, so nothing here needs a dark rule. */\n\n.panel {\n display: flex;\n flex-direction: column;\n gap: var(--space-4);\n min-width: 0;\n color: var(--text-primary);\n font-family: var(--font-ui);\n}\n\n.header {\n display: flex;\n flex-wrap: wrap;\n align-items: baseline;\n gap: var(--space-2) var(--space-3);\n}\n.title {\n margin: 0;\n font-family: var(--font-display);\n font-size: var(--text-lg-size);\n font-weight: var(--font-weight-semibold);\n}\n.summary {\n margin: 0;\n flex: 1 1 16rem;\n font-size: var(--text-sm-size);\n color: var(--text-secondary);\n}\n.age {\n font-size: var(--text-2xs-size);\n color: var(--text-tertiary);\n font-variant-numeric: tabular-nums;\n}\n\n.mode {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--space-2) var(--space-3);\n}\n.modeText {\n margin: 0;\n flex: 1 1 14rem;\n font-size: var(--text-sm-size);\n color: var(--text-secondary);\n}\n\n.preview {\n margin: 0;\n display: flex;\n flex-wrap: wrap;\n align-items: baseline;\n gap: var(--space-1) var(--space-2);\n padding: var(--space-2) 0;\n border-top: 1px solid var(--border-subtle);\n border-bottom: 1px solid var(--border-subtle);\n font-size: var(--text-sm-size);\n}\n.previewLead { color: var(--text-secondary); }\n.previewWhy {\n flex-basis: 100%;\n font-size: var(--text-xs-size);\n color: var(--text-tertiary);\n}\n\n.error {\n margin: 0;\n font-size: var(--text-sm-size);\n color: var(--status-danger-fg);\n}\n.loading,\n.empty {\n margin: 0;\n font-size: var(--text-sm-size);\n color: var(--text-secondary);\n}\n\n.seats {\n list-style: none;\n margin: 0;\n padding: 0;\n display: flex;\n flex-direction: column;\n}\n.seat {\n display: flex;\n flex-direction: column;\n gap: var(--space-2);\n padding: var(--space-3) 0;\n border-bottom: 1px solid var(--border-subtle);\n min-width: 0;\n}\n.seat[aria-busy='true'] { opacity: 0.7; }\n\n.seatHead {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--space-2);\n min-width: 0;\n}\n.marker {\n width: 3px;\n height: 16px;\n border-radius: 2px;\n flex: none;\n}\n.seatName {\n font-weight: var(--font-weight-medium);\n font-size: var(--text-base-size);\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.status {\n font-family: var(--font-display);\n font-size: var(--text-2xs-size);\n font-weight: var(--font-weight-medium);\n letter-spacing: var(--tracking-label, 0.06em);\n text-transform: uppercase;\n color: var(--status-unknown-fg);\n}\n.status[data-status='eligible'] { color: var(--status-success-fg); }\n.status[data-status='held'] { color: var(--status-warning-fg); }\n.status[data-status='off'] { color: var(--status-neutral-fg); }\n.status[data-status='unknown'] { color: var(--status-unknown-fg); }\n.free {\n font-size: var(--text-2xs-size);\n color: var(--text-tertiary);\n}\n.toggle { margin-left: auto; }\n\n.bars {\n display: flex;\n flex-direction: column;\n gap: var(--space-1);\n}\n.bar {\n display: grid;\n grid-template-columns: 6.5rem minmax(0, 1fr) auto;\n align-items: center;\n gap: var(--space-2);\n font-size: var(--text-xs-size);\n}\n.barLabel {\n display: inline-flex;\n align-items: baseline;\n gap: var(--space-1);\n color: var(--text-secondary);\n white-space: nowrap;\n}\n.bar[data-binding] .barLabel { color: var(--text-primary); }\n.bindingMark {\n font-size: var(--text-2xs-size);\n color: var(--text-tertiary);\n}\n.barValue {\n font-variant-numeric: tabular-nums;\n color: var(--text-secondary);\n white-space: nowrap;\n}\n.unknown {\n font-style: italic;\n color: var(--status-unknown-fg);\n}\n\n/* The track: used (solid) · autonomy room (tint) · kept for you (hatched). */\n.track {\n position: relative;\n height: 8px;\n border-radius: var(--radius-full);\n background: var(--meter-track);\n overflow: hidden;\n}\n.used,\n.room,\n.reserveBand {\n position: absolute;\n top: 0;\n bottom: 0;\n}\n.used {\n left: 0;\n /* Quantity, not interaction: the fixed azure ramp, never the operator-chosen accent (DESIGN §13.2). */\n background: var(--data-seq-5);\n border-radius: var(--radius-full) 0 0 var(--radius-full);\n}\n.used[data-over] { background: var(--status-warning-solid); }\n.room {\n background: color-mix(in srgb, var(--data-seq-5) 28%, transparent);\n}\n.reserveBand {\n background: repeating-linear-gradient(\n 135deg,\n color-mix(in srgb, var(--text-tertiary) 30%, transparent) 0 3px,\n transparent 3px 6px\n );\n}\n.ceiling {\n position: absolute;\n top: -2px;\n bottom: -2px;\n width: 2px;\n margin-left: -1px;\n background: var(--text-primary);\n}\n.trackUnknown {\n height: 8px;\n border-radius: var(--radius-full);\n border: 1px dashed var(--border-strong);\n background: transparent;\n}\n\n.controls {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(12rem, 1fr));\n gap: var(--space-2) var(--space-4);\n}\n\n.freeLine,\n.why {\n margin: 0;\n font-size: var(--text-xs-size);\n color: var(--text-secondary);\n}\n.more {\n font-size: var(--text-xs-size);\n color: var(--text-tertiary);\n}\n.more summary { cursor: pointer; }\n.more ul {\n margin: var(--space-1) 0 0;\n padding-left: var(--space-4);\n}\n\n.footnote {\n margin: 0;\n font-size: var(--text-2xs-size);\n color: var(--text-tertiary);\n}\n\n@media (max-width: 480px) {\n .bar {\n grid-template-columns: minmax(0, 1fr) auto;\n }\n .bar .track,\n .bar .trackUnknown {\n grid-column: 1 / -1;\n grid-row: 2;\n }\n .toggle { margin-left: 0; }\n}\n","/**\n * routes/verse/budget/BudgetControl.tsx — budget modes, per-seat reserves and\n * live headroom, in one panel.\n *\n * ┌ Budget ─────────────────────────── 3 of 7 seats can take autonomous work\n * │ [ Reserve | Balanced | All-in ] Autonomy stops at each seat's reserve…\n * │ Next medium task → Grok · why\n * │ ● Claude Code Eligible Autonomy [on]\n * │ Weekly ███████▒▒▒▒▒▒▒▒░░░░░░░░░ 20% used · stops at 60%\n * │ 5-hour ███▒▒▒▒▒▒▒▒▒▒▒▒░░░░░░░░░ 15% used · stops at 70%\n * │ Kept for you ──●──── 40% 5-hour ceiling ─────●── 70%\n * │ 40% of the weekly window is left for autonomy (40% kept for you).\n *\n * Each bar reads left to right: what is USED (solid), what autonomy may\n * still use (tinted), and the band KEPT FOR MASON (hatched) past the ceiling\n * tick. An unread window is a dashed track and the words \"no reading\" —\n * never an empty bar (which would claim headroom) or a full one.\n *\n * `BudgetControlView` is pure (props in, callbacks out) and is what the tests\n * render; `BudgetControl` wires it to the API, the mutation-token gate and a\n * 60 s refresh while the document is visible.\n *\n * Mount point: a Track B surface (Command home / Autonomy) owns placement —\n * this file only exports the panel.\n */\nimport { useCallback, useEffect, useId, useRef, useState } from 'react';\nimport type { BudgetView } from '../../../../core/routing/policy.js';\nimport type { BudgetMode, SeatDecision } from '../../../../core/routing/types.js';\nimport { MutationTokenDialog } from '../../../components/auth/MutationTokenDialog.js';\nimport { Segmented } from '../../../components/primitives/Segmented.js';\nimport { Slider } from '../../../components/primitives/Slider.js';\nimport { Switch } from '../../../components/primitives/Switch.js';\nimport { EngineMarker } from '../../../components/primitives/Tag.js';\nimport { readFailureReason } from '../../../data/client.js';\nimport { useQuery, useRefetch } from '../../../data/hooks.js';\nimport { describeContextError, useTokenGate } from '../context/use-token-gate.js';\nimport { percentText, tidyProse } from '../autonomy/format.js';\nimport { readBudgetRows } from '../usage/capacity-strip-model.js';\nimport {\n BUDGET_MODE_OPTIONS,\n budgetSummary,\n clampPercent,\n modeAboveCeiling,\n readingAge,\n STATUS_WORDS,\n type BudgetBar,\n type BudgetSeatRow,\n} from './budget-model.js';\nimport { budgetPreviewQuery, budgetQuery, updateBudget, type BudgetSeatPatchWire } from './budget-queries.js';\nimport styles from './BudgetControl.module.css';\n\n/** Headroom moves with the collector (30 s cycle); a minute is plenty for a settings panel. */\nexport const BUDGET_POLL_MS = 60_000;\n/** Slider changes are committed this long after the last movement. */\nexport const BUDGET_COMMIT_DELAY_MS = 450;\n\n// ---------------------------------------------------------------------------\n// Headroom bar\n// ---------------------------------------------------------------------------\n\nfunction HeadroomBar({ bar }: { bar: BudgetBar }) {\n const used = bar.usedPercent;\n const ceiling = clampPercent(bar.ceilingPercent);\n if (used === null) {\n return (\n <div className={styles.bar} data-binding={bar.binding || undefined}>\n <span className={styles.barLabel}>{bar.label}</span>\n <div className={styles.trackUnknown} role=\"img\" aria-label={bar.description} />\n <span className={`${styles.barValue} ${styles.unknown}`}>no reading</span>\n </div>\n );\n }\n const usedPct = clampPercent(used);\n const over = usedPct >= ceiling;\n return (\n <div className={styles.bar} data-binding={bar.binding || undefined}>\n <span className={styles.barLabel}>\n {bar.label}\n {bar.binding ? <span className={styles.bindingMark} title=\"This window limits autonomy right now\">binding</span> : null}\n </span>\n <div className={styles.track} role=\"img\" aria-label={bar.description}>\n {ceiling < 100 ? (\n <div className={styles.reserveBand} style={{ left: `${ceiling}%`, width: `${100 - ceiling}%` }} />\n ) : null}\n {!over ? (\n <div className={styles.room} style={{ left: `${usedPct}%`, width: `${ceiling - usedPct}%` }} />\n ) : null}\n <div className={styles.used} data-over={over || undefined} style={{ width: `${usedPct}%` }} />\n {ceiling < 100 ? <div className={styles.ceiling} style={{ left: `${ceiling}%` }} /> : null}\n </div>\n <span className={styles.barValue}>\n {/* Words by the one percent rule; the bar geometry stays numeric. */}\n {percentText(used)} used{ceiling < 100 ? ` · stops at ${ceiling}%` : ''}\n </span>\n </div>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Draft slider — commits after the hand leaves it\n// ---------------------------------------------------------------------------\n\nfunction useCommittedDraft(serverValue: number, commit: (value: number) => void): [number, (v: number) => void] {\n const [draft, setDraft] = useState(serverValue);\n const dirty = useRef(false);\n const timer = useRef<ReturnType<typeof setTimeout> | null>(null);\n const commitRef = useRef(commit);\n commitRef.current = commit;\n\n // A new server value wins unless the operator is mid-drag.\n useEffect(() => {\n if (!dirty.current) setDraft(serverValue);\n }, [serverValue]);\n\n useEffect(() => () => {\n if (timer.current) clearTimeout(timer.current);\n }, []);\n\n const change = useCallback((value: number) => {\n setDraft(value);\n dirty.current = true;\n if (timer.current) clearTimeout(timer.current);\n timer.current = setTimeout(() => {\n dirty.current = false;\n timer.current = null;\n commitRef.current(value);\n }, BUDGET_COMMIT_DELAY_MS);\n }, []);\n\n return [draft, change];\n}\n\n// ---------------------------------------------------------------------------\n// One seat\n// ---------------------------------------------------------------------------\n\ninterface SeatRowProps {\n row: BudgetSeatRow;\n saving: boolean;\n readOnly: boolean;\n onSeat: (seatId: string, patch: BudgetSeatPatchWire) => void;\n}\n\nfunction SeatRow({ row, saving, readOnly, onSeat }: SeatRowProps) {\n const headingId = useId();\n const reserveServer = row.policy.reservePercent;\n const sessionServer = row.policy.maxSessionWindowPercent ?? 100;\n const [reserve, setReserve] = useCommittedDraft(reserveServer, (v) => {\n if (v !== reserveServer) onSeat(row.seatId, { reservePercent: v });\n });\n const [session, setSession] = useCommittedDraft(sessionServer, (v) => {\n if (v !== sessionServer) onSeat(row.seatId, { maxSessionWindowPercent: v >= 100 ? null : v });\n });\n const disabled = readOnly || saving;\n\n return (\n <li className={styles.seat} aria-labelledby={headingId} data-status={row.status} aria-busy={saving || undefined}>\n <div className={styles.seatHead}>\n <EngineMarker engine={row.engine} className={styles.marker} />\n {/* The name may truncate in a narrow sheet; the full name rides in the tooltip. */}\n <span id={headingId} className={styles.seatName} title={row.label}>{row.label}</span>\n <span className={styles.status} data-status={row.status}>{STATUS_WORDS[row.status]}</span>\n {row.free ? <span className={styles.free}>free</span> : null}\n <Switch\n className={styles.toggle}\n checked={row.policy.enabled}\n disabled={disabled}\n aria-label={`Autonomy on ${row.label}`}\n label=\"Autonomy\"\n onChange={(next) => onSeat(row.seatId, { enabled: next })}\n />\n </div>\n\n {row.bars.length > 0 ? (\n <div className={styles.bars}>\n {row.bars.map((bar) => <HeadroomBar key={bar.kind} bar={bar} />)}\n </div>\n ) : row.free ? (\n <p className={styles.freeLine}>No usage window — local models cost nothing and are never held back for you.</p>\n ) : null}\n\n {!row.free && row.policy.enabled ? (\n <div className={styles.controls}>\n <Slider\n label=\"Kept for you\"\n min={0}\n max={100}\n step={5}\n value={reserve}\n disabled={disabled}\n valueLabel={`${reserve}%`}\n valueText={`${reserve} percent of the ${row.engine === 'grok' ? 'billing period' : 'weekly window'} kept for you`}\n onChange={(e) => setReserve(clampPercent(Number(e.currentTarget.value)))}\n />\n {row.hasSessionCeiling ? (\n <Slider\n label=\"5-hour ceiling\"\n min={10}\n max={100}\n step={5}\n value={session}\n disabled={disabled}\n valueLabel={session >= 100 ? 'none' : `${session}%`}\n valueText={session >= 100 ? 'no 5-hour ceiling' : `autonomy stops at ${session} percent of the 5-hour window`}\n onChange={(e) => setSession(clampPercent(Number(e.currentTarget.value), 10, 100))}\n />\n ) : null}\n </div>\n ) : null}\n\n <p className={styles.why}>{row.why}</p>\n {row.more.length > 0 ? (\n <details className={styles.more}>\n <summary>{row.more.length === 1 ? '1 more note' : `${row.more.length} more notes`}</summary>\n <ul>\n {row.more.map((reason) => <li key={reason}>{reason}</li>)}\n </ul>\n </details>\n ) : null}\n </li>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Pure view\n// ---------------------------------------------------------------------------\n\nexport interface BudgetControlViewProps {\n view: BudgetView;\n preview: SeatDecision | null;\n nowMs: number;\n /** `'mode'` or a seat id while its change is in flight. */\n pending: string | null;\n error: string | null;\n /**\n * Why the last READ failed while an older answer is still on screen (the\n * server's own sentence, e.g. \"Seat capacity could not be read.\"). Without\n * it the panel kept showing the old bars as if they were current.\n */\n readError?: string | null;\n readOnly?: boolean;\n /**\n * The standing grant's ceiling (`spend.maxMode`). Modes above it are shown\n * DISABLED with the reason — never hidden — because autonomy could not\n * spend them anyway. Moving toward Reserve is always allowed. Null/absent\n * = no grant ceiling applies (every mode selectable).\n */\n maxMode?: BudgetMode | null;\n onMode: (mode: BudgetMode) => void;\n onSeat: (seatId: string, patch: BudgetSeatPatchWire) => void;\n}\n\nexport function BudgetControlView({ view, preview, nowMs, pending, error, readError = null, readOnly = false, maxMode = null, onMode, onSeat }: BudgetControlViewProps) {\n const titleId = useId();\n // The wire view is read defensively (the capacity strip's own guard): this\n // panel is opened from Apps, the composer's seat chip and the autonomy bar,\n // and a budget answer of `{}` or a garbled seat entry used to throw inside\n // buildBudgetRows and take the whole sheet down. A seat whose policy is\n // malformed is dropped, not shown as \"off\" — see readBudgetRows.\n const rows = [...readBudgetRows(view).values()];\n const summary = budgetSummary(rows);\n const knownMode = BUDGET_MODE_OPTIONS.find((o) => o.value === view.mode) ?? null;\n const mode = knownMode ?? BUDGET_MODE_OPTIONS[1]!;\n const maxAgeMs = typeof view.readingMaxAgeMs === 'number' && Number.isFinite(view.readingMaxAgeMs) ? view.readingMaxAgeMs : null;\n const ceilingLabel = maxMode ? BUDGET_MODE_OPTIONS.find((o) => o.value === maxMode)?.label ?? maxMode : null;\n const aboveNow = modeAboveCeiling(view.mode, maxMode);\n const chosen = preview?.seatId ? rows.find((r) => r.seatId === preview.seatId) : null;\n\n return (\n <section className={styles.panel} aria-labelledby={titleId}>\n <header className={styles.header}>\n <h2 id={titleId} className={styles.title}>Budget</h2>\n <p className={styles.summary}>{summary.sentence}</p>\n <span className={styles.age}>\n {Number.isFinite(Date.parse(view.sampledAt)) ? `Readings ${readingAge(view.sampledAt, nowMs)}` : 'Reading time not reported'}\n </span>\n </header>\n\n <div className={styles.mode}>\n <Segmented\n aria-label=\"Budget mode\"\n options={BUDGET_MODE_OPTIONS.map((o) => ({\n value: o.value,\n label: o.label,\n ...(modeAboveCeiling(o.value, maxMode) ? { ariaLabel: `${o.label} — above your grant` } : {}),\n disabled: readOnly || pending !== null || modeAboveCeiling(o.value, maxMode),\n }))}\n value={view.mode}\n onChange={(next) => { if (next !== view.mode && !modeAboveCeiling(next, maxMode)) onMode(next); }}\n />\n {/* No option is pressed when the server named no mode we know —\n showing Balanced there would claim a setting nobody read. */}\n <p className={styles.modeText}>{knownMode ? mode.description : 'The server did not say which mode is on.'}</p>\n {ceilingLabel ? (\n <p className={styles.modeText} data-ceiling=\"\">\n {aboveNow\n ? `Your grant allows up to ${ceilingLabel}, so autonomy spends as ${ceilingLabel} until this moves down.`\n : `Your grant allows up to ${ceilingLabel}; modes above it are off. Re-approve the grant to raise it.`}\n </p>\n ) : null}\n </div>\n\n {preview ? (\n <p className={styles.preview} aria-live=\"polite\">\n <span className={styles.previewLead}>Next medium task →</span>{' '}\n <strong>{chosen?.label ?? (preview.seatId ?? 'nowhere right now')}</strong>\n <span className={styles.previewWhy}>{/* A `{}` preview (an older server) has no why: say nothing rather than crash. */}\n {typeof preview.why === 'string' ? tidyProse(preview.why, nowMs) : null}</span>\n </p>\n ) : null}\n\n {error ? <p className={styles.error} role=\"alert\">{error}</p> : null}\n {readError ? <p className={styles.error} role=\"status\" data-read-error=\"\">{readError}</p> : null}\n\n {rows.length === 0 ? (\n <p className={styles.empty}>No seats yet — connect an account or start Ollama, and they appear here.</p>\n ) : (\n <ul className={styles.seats}>\n {rows.map((row) => (\n <SeatRow key={row.seatId} row={row} saving={pending === row.seatId || pending === 'mode'} readOnly={readOnly} onSeat={onSeat} />\n ))}\n </ul>\n )}\n\n <p className={styles.footnote}>\n Reserves limit autonomy only; your chats can always use a seat. A seat with no reading, or one{' '}\n {maxAgeMs !== null ? `older than ${Math.round(maxAgeMs / 60_000)} minutes` : 'whose reading is stale'}, is held back.\n </p>\n </section>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Connected panel\n// ---------------------------------------------------------------------------\n\nexport function BudgetControl({ maxMode = null }: { maxMode?: BudgetMode | null } = {}) {\n const budget = useQuery(budgetQuery, { freshMs: 0 });\n const preview = useQuery(budgetPreviewQuery, { freshMs: 0 });\n const refetchBudget = useRefetch(budgetQuery);\n const refetchPreview = useRefetch(budgetPreviewQuery);\n const gate = useTokenGate();\n const [latest, setLatest] = useState<BudgetView | null>(null);\n const [pending, setPending] = useState<string | null>(null);\n const [error, setError] = useState<string | null>(null);\n const [nowMs, setNowMs] = useState(() => Date.now());\n\n // Poll while visible; read immediately on return (useSeatsRefresh's pattern).\n useEffect(() => {\n const tick = (): void => {\n if (typeof document !== 'undefined' && document.visibilityState === 'hidden') return;\n refetchBudget();\n refetchPreview();\n setNowMs(Date.now());\n };\n const timer = window.setInterval(tick, BUDGET_POLL_MS);\n document.addEventListener('visibilitychange', tick);\n return () => {\n window.clearInterval(timer);\n document.removeEventListener('visibilitychange', tick);\n };\n }, [refetchBudget, refetchPreview]);\n\n // The POST response is newer than the cached read until the refetch lands.\n // A cached read with no parseable sampledAt cannot be shown to be newer, so\n // the POST's answer wins (NaN comparisons are always false).\n const cached = budget.data;\n const view = latest && (!cached || !(Date.parse(latest.sampledAt) < Date.parse(cached.sampledAt))) ? latest : cached;\n\n const apply = useCallback(async (key: string, reason: string, update: Parameters<typeof updateBudget>[0]) => {\n setPending(key);\n setError(null);\n try {\n const next = await gate.run(reason, () => updateBudget(update));\n if (next) setLatest(next);\n } catch (err) {\n setError(describeContextError(err));\n } finally {\n setPending(null);\n setNowMs(Date.now());\n }\n }, [gate]);\n\n // The server's reason (budget-api.ts answers `{ code, error }` for a read it\n // could not make), never the bare \"GET … failed (HTTP 503)\" wrapper.\n const budgetFailure = budget.status === 'error' ? readFailureReason(budget.error) : null;\n const previewFailure = preview.status === 'error' ? readFailureReason(preview.error) : null;\n\n if (!view) {\n return (\n <section className={styles.panel} aria-label=\"Budget\">\n {budgetFailure ? (\n <p className={styles.error} role=\"alert\">Budget unavailable. {budgetFailure}</p>\n ) : (\n <p className={styles.loading}>Reading seat usage…</p>\n )}\n </section>\n );\n }\n\n return (\n <>\n <BudgetControlView\n view={view}\n preview={preview.data ?? null}\n nowMs={nowMs}\n pending={pending}\n error={error}\n readError={budgetFailure\n ? `Showing the last readings. ${budgetFailure}`\n : previewFailure ? `Next-task preview unavailable. ${previewFailure}` : null}\n maxMode={maxMode}\n onMode={(mode) => void apply('mode', `Switch the budget to ${mode}`, { mode })}\n onSeat={(seatId, patch) => void apply(seatId, `Change the budget for ${seatId}`, { seatId, policy: patch })}\n />\n <MutationTokenDialog open={gate.dialog.open} reason={gate.dialog.reason} tokenLabel=\"Mutation token\"\n tokenHelp=\"the mutation token ashlr verse printed\" onClose={gate.dialog.onClose} onUnlocked={gate.dialog.onUnlocked} />\n </>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"BudgetControl-C-0KhjRS.js","names":[],"sources":["../../../../../../src/web-ui/routes/verse/budget/BudgetControl.module.css","../../../../../../src/web-ui/routes/verse/budget/BudgetControl.tsx"],"sourcesContent":["/* Budget panel. Hairlines and whitespace, no nested boxes (DESIGN-V2 §6).\n Every state is a WORD first; colour reinforces it. Status tokens are\n defined for both themes in tokens.css, so nothing here needs a dark rule. */\n\n.panel {\n display: flex;\n flex-direction: column;\n gap: var(--space-4);\n min-width: 0;\n color: var(--text-primary);\n font-family: var(--font-ui);\n}\n\n.header {\n display: flex;\n flex-wrap: wrap;\n align-items: baseline;\n gap: var(--space-2) var(--space-3);\n}\n.title {\n margin: 0;\n font-family: var(--font-display);\n font-size: var(--text-lg-size);\n font-weight: var(--font-weight-semibold);\n}\n.summary {\n margin: 0;\n flex: 1 1 16rem;\n font-size: var(--text-sm-size);\n color: var(--text-secondary);\n}\n.age {\n font-size: var(--text-2xs-size);\n color: var(--text-tertiary);\n font-variant-numeric: tabular-nums;\n}\n\n.mode {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--space-2) var(--space-3);\n}\n.modeText {\n margin: 0;\n flex: 1 1 14rem;\n font-size: var(--text-sm-size);\n color: var(--text-secondary);\n}\n\n.preview {\n margin: 0;\n display: flex;\n flex-wrap: wrap;\n align-items: baseline;\n gap: var(--space-1) var(--space-2);\n padding: var(--space-2) 0;\n border-top: 1px solid var(--border-subtle);\n border-bottom: 1px solid var(--border-subtle);\n font-size: var(--text-sm-size);\n}\n.previewLead { color: var(--text-secondary); }\n.previewWhy {\n flex-basis: 100%;\n font-size: var(--text-xs-size);\n color: var(--text-tertiary);\n}\n\n.error {\n margin: 0;\n font-size: var(--text-sm-size);\n color: var(--status-danger-fg);\n}\n.loading,\n.empty {\n margin: 0;\n font-size: var(--text-sm-size);\n color: var(--text-secondary);\n}\n\n.seats {\n list-style: none;\n margin: 0;\n padding: 0;\n display: flex;\n flex-direction: column;\n}\n.seat {\n display: flex;\n flex-direction: column;\n gap: var(--space-2);\n padding: var(--space-3) 0;\n border-bottom: 1px solid var(--border-subtle);\n min-width: 0;\n}\n.seat[aria-busy='true'] { opacity: 0.7; }\n\n.seatHead {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--space-2);\n min-width: 0;\n}\n.marker {\n width: 3px;\n height: 16px;\n border-radius: 2px;\n flex: none;\n}\n.seatName {\n font-weight: var(--font-weight-medium);\n font-size: var(--text-base-size);\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.status {\n font-family: var(--font-display);\n font-size: var(--text-2xs-size);\n font-weight: var(--font-weight-medium);\n letter-spacing: var(--tracking-label, 0.06em);\n text-transform: uppercase;\n color: var(--status-unknown-fg);\n}\n.status[data-status='eligible'] { color: var(--status-success-fg); }\n.status[data-status='held'] { color: var(--status-warning-fg); }\n.status[data-status='off'] { color: var(--status-neutral-fg); }\n.status[data-status='unknown'] { color: var(--status-unknown-fg); }\n.free {\n font-size: var(--text-2xs-size);\n color: var(--text-tertiary);\n}\n.toggle { margin-left: auto; }\n\n.bars {\n display: flex;\n flex-direction: column;\n gap: var(--space-1);\n}\n.bar {\n display: grid;\n grid-template-columns: 6.5rem minmax(0, 1fr) auto;\n align-items: center;\n gap: var(--space-2);\n font-size: var(--text-xs-size);\n}\n.barLabel {\n display: inline-flex;\n align-items: baseline;\n gap: var(--space-1);\n color: var(--text-secondary);\n white-space: nowrap;\n}\n.bar[data-binding] .barLabel { color: var(--text-primary); }\n.bindingMark {\n font-size: var(--text-2xs-size);\n color: var(--text-tertiary);\n}\n.barValue {\n font-variant-numeric: tabular-nums;\n color: var(--text-secondary);\n white-space: nowrap;\n}\n.unknown {\n font-style: italic;\n color: var(--status-unknown-fg);\n}\n\n/* The track: used (solid) · autonomy room (tint) · kept for you (hatched). */\n.track {\n position: relative;\n height: 8px;\n border-radius: var(--radius-full);\n background: var(--meter-track);\n overflow: hidden;\n}\n.used,\n.room,\n.reserveBand {\n position: absolute;\n top: 0;\n bottom: 0;\n}\n.used {\n left: 0;\n /* Quantity, not interaction: the fixed azure ramp, never the operator-chosen accent (DESIGN §13.2). */\n background: var(--data-seq-5);\n border-radius: var(--radius-full) 0 0 var(--radius-full);\n}\n.used[data-over] { background: var(--status-warning-solid); }\n.room {\n background: color-mix(in srgb, var(--data-seq-5) 28%, transparent);\n}\n.reserveBand {\n background: repeating-linear-gradient(\n 135deg,\n color-mix(in srgb, var(--text-tertiary) 30%, transparent) 0 3px,\n transparent 3px 6px\n );\n}\n.ceiling {\n position: absolute;\n top: -2px;\n bottom: -2px;\n width: 2px;\n margin-left: -1px;\n background: var(--text-primary);\n}\n.trackUnknown {\n height: 8px;\n border-radius: var(--radius-full);\n border: 1px dashed var(--border-strong);\n background: transparent;\n}\n\n.controls {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(12rem, 1fr));\n gap: var(--space-2) var(--space-4);\n}\n\n.freeLine,\n.why {\n margin: 0;\n font-size: var(--text-xs-size);\n color: var(--text-secondary);\n}\n.more {\n font-size: var(--text-xs-size);\n color: var(--text-tertiary);\n}\n.more summary { cursor: pointer; }\n.more ul {\n margin: var(--space-1) 0 0;\n padding-left: var(--space-4);\n}\n\n.footnote {\n margin: 0;\n font-size: var(--text-2xs-size);\n color: var(--text-tertiary);\n}\n\n@media (max-width: 480px) {\n .bar {\n grid-template-columns: minmax(0, 1fr) auto;\n }\n .bar .track,\n .bar .trackUnknown {\n grid-column: 1 / -1;\n grid-row: 2;\n }\n .toggle { margin-left: 0; }\n}\n","/**\n * routes/verse/budget/BudgetControl.tsx — budget modes, per-seat reserves and\n * live headroom, in one panel.\n *\n * ┌ Budget ─────────────────────────── 3 of 7 seats can take autonomous work\n * │ [ Reserve | Balanced | All-in ] Autonomy stops at each seat's reserve…\n * │ Next medium task → Grok · why\n * │ ● Claude Code Eligible Autonomy [on]\n * │ Weekly ███████▒▒▒▒▒▒▒▒░░░░░░░░░ 20% used · stops at 60%\n * │ 5-hour ███▒▒▒▒▒▒▒▒▒▒▒▒░░░░░░░░░ 15% used · stops at 70%\n * │ Kept for you ──●──── 40% 5-hour ceiling ─────●── 70%\n * │ 40% of the weekly window is left for autonomy (40% kept for you).\n *\n * Each bar reads left to right: what is USED (solid), what autonomy may\n * still use (tinted), and the band KEPT FOR MASON (hatched) past the ceiling\n * tick. An unread window is a dashed track and the words \"no reading\" —\n * never an empty bar (which would claim headroom) or a full one.\n *\n * `BudgetControlView` is pure (props in, callbacks out) and is what the tests\n * render; `BudgetControl` wires it to the API, the mutation-token gate and a\n * 60 s refresh while the document is visible.\n *\n * Mount point: a Track B surface (Command home / Autonomy) owns placement —\n * this file only exports the panel.\n */\nimport { useCallback, useEffect, useId, useRef, useState } from 'react';\nimport type { BudgetView } from '../../../../core/routing/policy.js';\nimport type { BudgetMode, SeatDecision } from '../../../../core/routing/types.js';\nimport { MutationTokenDialog } from '../../../components/auth/MutationTokenDialog.js';\nimport { Segmented } from '../../../components/primitives/Segmented.js';\nimport { Slider } from '../../../components/primitives/Slider.js';\nimport { Switch } from '../../../components/primitives/Switch.js';\nimport { EngineMarker } from '../../../components/primitives/Tag.js';\nimport { readFailureReason } from '../../../data/client.js';\nimport { useQuery, useRefetch } from '../../../data/hooks.js';\nimport { describeContextError, useTokenGate } from '../context/use-token-gate.js';\nimport { percentText, tidyProse } from '../autonomy/format.js';\nimport { readBudgetRows } from '../usage/capacity-strip-model.js';\nimport {\n BUDGET_MODE_OPTIONS,\n budgetSummary,\n clampPercent,\n modeAboveCeiling,\n readingAge,\n STATUS_WORDS,\n type BudgetBar,\n type BudgetSeatRow,\n} from './budget-model.js';\nimport { budgetPreviewQuery, budgetQuery, updateBudget, type BudgetSeatPatchWire } from './budget-queries.js';\nimport styles from './BudgetControl.module.css';\n\n/** Headroom moves with the collector (30 s cycle); a minute is plenty for a settings panel. */\nexport const BUDGET_POLL_MS = 60_000;\n/** Slider changes are committed this long after the last movement. */\nexport const BUDGET_COMMIT_DELAY_MS = 450;\n\n// ---------------------------------------------------------------------------\n// Headroom bar\n// ---------------------------------------------------------------------------\n\nfunction HeadroomBar({ bar }: { bar: BudgetBar }) {\n const used = bar.usedPercent;\n const ceiling = clampPercent(bar.ceilingPercent);\n if (used === null) {\n return (\n <div className={styles.bar} data-binding={bar.binding || undefined}>\n <span className={styles.barLabel}>{bar.label}</span>\n <div className={styles.trackUnknown} role=\"img\" aria-label={bar.description} />\n <span className={`${styles.barValue} ${styles.unknown}`}>no reading</span>\n </div>\n );\n }\n const usedPct = clampPercent(used);\n const over = usedPct >= ceiling;\n return (\n <div className={styles.bar} data-binding={bar.binding || undefined}>\n <span className={styles.barLabel}>\n {bar.label}\n {bar.binding ? <span className={styles.bindingMark} title=\"This window limits autonomy right now\">binding</span> : null}\n </span>\n <div className={styles.track} role=\"img\" aria-label={bar.description}>\n {ceiling < 100 ? (\n <div className={styles.reserveBand} style={{ left: `${ceiling}%`, width: `${100 - ceiling}%` }} />\n ) : null}\n {!over ? (\n <div className={styles.room} style={{ left: `${usedPct}%`, width: `${ceiling - usedPct}%` }} />\n ) : null}\n <div className={styles.used} data-over={over || undefined} style={{ width: `${usedPct}%` }} />\n {ceiling < 100 ? <div className={styles.ceiling} style={{ left: `${ceiling}%` }} /> : null}\n </div>\n <span className={styles.barValue}>\n {/* Words by the one percent rule; the bar geometry stays numeric. */}\n {percentText(used)} used{ceiling < 100 ? ` · stops at ${ceiling}%` : ''}\n </span>\n </div>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Draft slider — commits after the hand leaves it\n// ---------------------------------------------------------------------------\n\nfunction useCommittedDraft(serverValue: number, commit: (value: number) => void): [number, (v: number) => void] {\n const [draft, setDraft] = useState(serverValue);\n const dirty = useRef(false);\n const timer = useRef<ReturnType<typeof setTimeout> | null>(null);\n const commitRef = useRef(commit);\n commitRef.current = commit;\n\n // A new server value wins unless the operator is mid-drag.\n useEffect(() => {\n if (!dirty.current) setDraft(serverValue);\n }, [serverValue]);\n\n useEffect(() => () => {\n if (timer.current) clearTimeout(timer.current);\n }, []);\n\n const change = useCallback((value: number) => {\n setDraft(value);\n dirty.current = true;\n if (timer.current) clearTimeout(timer.current);\n timer.current = setTimeout(() => {\n dirty.current = false;\n timer.current = null;\n commitRef.current(value);\n }, BUDGET_COMMIT_DELAY_MS);\n }, []);\n\n return [draft, change];\n}\n\n// ---------------------------------------------------------------------------\n// One seat\n// ---------------------------------------------------------------------------\n\ninterface SeatRowProps {\n row: BudgetSeatRow;\n saving: boolean;\n readOnly: boolean;\n onSeat: (seatId: string, patch: BudgetSeatPatchWire) => void;\n}\n\nfunction SeatRow({ row, saving, readOnly, onSeat }: SeatRowProps) {\n const headingId = useId();\n const reserveServer = row.policy.reservePercent;\n const sessionServer = row.policy.maxSessionWindowPercent ?? 100;\n const [reserve, setReserve] = useCommittedDraft(reserveServer, (v) => {\n if (v !== reserveServer) onSeat(row.seatId, { reservePercent: v });\n });\n const [session, setSession] = useCommittedDraft(sessionServer, (v) => {\n if (v !== sessionServer) onSeat(row.seatId, { maxSessionWindowPercent: v >= 100 ? null : v });\n });\n const disabled = readOnly || saving;\n\n return (\n <li className={styles.seat} aria-labelledby={headingId} data-status={row.status} aria-busy={saving || undefined}>\n <div className={styles.seatHead}>\n <EngineMarker engine={row.engine} className={styles.marker} />\n {/* The name may truncate in a narrow sheet; the full name rides in the tooltip. */}\n <span id={headingId} className={styles.seatName} title={row.label}>{row.label}</span>\n <span className={styles.status} data-status={row.status}>{STATUS_WORDS[row.status]}</span>\n {row.free ? <span className={styles.free}>free</span> : null}\n <Switch\n className={styles.toggle}\n checked={row.policy.enabled}\n disabled={disabled}\n aria-label={`Autonomy on ${row.label}`}\n label=\"Autonomy\"\n onChange={(next) => onSeat(row.seatId, { enabled: next })}\n />\n </div>\n\n {row.bars.length > 0 ? (\n <div className={styles.bars}>\n {row.bars.map((bar) => <HeadroomBar key={bar.kind} bar={bar} />)}\n </div>\n ) : row.free ? (\n <p className={styles.freeLine}>No usage window — local models cost nothing and are never held back for you.</p>\n ) : null}\n\n {!row.free && row.policy.enabled ? (\n <div className={styles.controls}>\n <Slider\n label=\"Kept for you\"\n min={0}\n max={100}\n step={5}\n value={reserve}\n disabled={disabled}\n valueLabel={`${reserve}%`}\n valueText={`${reserve} percent of the ${row.engine === 'grok' ? 'billing period' : 'weekly window'} kept for you`}\n onChange={(e) => setReserve(clampPercent(Number(e.currentTarget.value)))}\n />\n {row.hasSessionCeiling ? (\n <Slider\n label=\"5-hour ceiling\"\n min={10}\n max={100}\n step={5}\n value={session}\n disabled={disabled}\n valueLabel={session >= 100 ? 'none' : `${session}%`}\n valueText={session >= 100 ? 'no 5-hour ceiling' : `autonomy stops at ${session} percent of the 5-hour window`}\n onChange={(e) => setSession(clampPercent(Number(e.currentTarget.value), 10, 100))}\n />\n ) : null}\n </div>\n ) : null}\n\n <p className={styles.why}>{row.why}</p>\n {row.more.length > 0 ? (\n <details className={styles.more}>\n <summary>{row.more.length === 1 ? '1 more note' : `${row.more.length} more notes`}</summary>\n <ul>\n {row.more.map((reason) => <li key={reason}>{reason}</li>)}\n </ul>\n </details>\n ) : null}\n </li>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Pure view\n// ---------------------------------------------------------------------------\n\nexport interface BudgetControlViewProps {\n view: BudgetView;\n preview: SeatDecision | null;\n nowMs: number;\n /** `'mode'` or a seat id while its change is in flight. */\n pending: string | null;\n error: string | null;\n /**\n * Why the last READ failed while an older answer is still on screen (the\n * server's own sentence, e.g. \"Seat capacity could not be read.\"). Without\n * it the panel kept showing the old bars as if they were current.\n */\n readError?: string | null;\n readOnly?: boolean;\n /**\n * The standing grant's ceiling (`spend.maxMode`). Modes above it are shown\n * DISABLED with the reason — never hidden — because autonomy could not\n * spend them anyway. Moving toward Reserve is always allowed. Null/absent\n * = no grant ceiling applies (every mode selectable).\n */\n maxMode?: BudgetMode | null;\n onMode: (mode: BudgetMode) => void;\n onSeat: (seatId: string, patch: BudgetSeatPatchWire) => void;\n}\n\nexport function BudgetControlView({ view, preview, nowMs, pending, error, readError = null, readOnly = false, maxMode = null, onMode, onSeat }: BudgetControlViewProps) {\n const titleId = useId();\n // The wire view is read defensively (the capacity strip's own guard): this\n // panel is opened from Apps, the composer's seat chip and the autonomy bar,\n // and a budget answer of `{}` or a garbled seat entry used to throw inside\n // buildBudgetRows and take the whole sheet down. A seat whose policy is\n // malformed is dropped, not shown as \"off\" — see readBudgetRows.\n const rows = [...readBudgetRows(view).values()];\n const summary = budgetSummary(rows);\n const knownMode = BUDGET_MODE_OPTIONS.find((o) => o.value === view.mode) ?? null;\n const mode = knownMode ?? BUDGET_MODE_OPTIONS[1]!;\n const maxAgeMs = typeof view.readingMaxAgeMs === 'number' && Number.isFinite(view.readingMaxAgeMs) ? view.readingMaxAgeMs : null;\n const ceilingLabel = maxMode ? BUDGET_MODE_OPTIONS.find((o) => o.value === maxMode)?.label ?? maxMode : null;\n const aboveNow = modeAboveCeiling(view.mode, maxMode);\n const chosen = preview?.seatId ? rows.find((r) => r.seatId === preview.seatId) : null;\n\n return (\n <section className={styles.panel} aria-labelledby={titleId}>\n <header className={styles.header}>\n <h2 id={titleId} className={styles.title}>Budget</h2>\n <p className={styles.summary}>{summary.sentence}</p>\n <span className={styles.age}>\n {Number.isFinite(Date.parse(view.sampledAt)) ? `Readings ${readingAge(view.sampledAt, nowMs)}` : 'Reading time not reported'}\n </span>\n </header>\n\n <div className={styles.mode}>\n <Segmented\n aria-label=\"Budget mode\"\n options={BUDGET_MODE_OPTIONS.map((o) => ({\n value: o.value,\n label: o.label,\n ...(modeAboveCeiling(o.value, maxMode) ? { ariaLabel: `${o.label} — above your grant` } : {}),\n disabled: readOnly || pending !== null || modeAboveCeiling(o.value, maxMode),\n }))}\n value={view.mode}\n onChange={(next) => { if (next !== view.mode && !modeAboveCeiling(next, maxMode)) onMode(next); }}\n />\n {/* No option is pressed when the server named no mode we know —\n showing Balanced there would claim a setting nobody read. */}\n <p className={styles.modeText}>{knownMode ? mode.description : 'The server did not say which mode is on.'}</p>\n {ceilingLabel ? (\n <p className={styles.modeText} data-ceiling=\"\">\n {aboveNow\n ? `Your grant allows up to ${ceilingLabel}, so autonomy spends as ${ceilingLabel} until this moves down.`\n : `Your grant allows up to ${ceilingLabel}; modes above it are off. Re-approve the grant to raise it.`}\n </p>\n ) : null}\n </div>\n\n {preview ? (\n <p className={styles.preview} aria-live=\"polite\">\n <span className={styles.previewLead}>Next medium task →</span>{' '}\n <strong>{chosen?.label ?? (preview.seatId ?? 'nowhere right now')}</strong>\n <span className={styles.previewWhy}>{/* A `{}` preview (an older server) has no why: say nothing rather than crash. */}\n {typeof preview.why === 'string' ? tidyProse(preview.why, nowMs) : null}</span>\n </p>\n ) : null}\n\n {error ? <p className={styles.error} role=\"alert\">{error}</p> : null}\n {readError ? <p className={styles.error} role=\"status\" data-read-error=\"\">{readError}</p> : null}\n\n {rows.length === 0 ? (\n <p className={styles.empty}>No seats yet — connect an account or start Ollama, and they appear here.</p>\n ) : (\n <ul className={styles.seats}>\n {rows.map((row) => (\n <SeatRow key={row.seatId} row={row} saving={pending === row.seatId || pending === 'mode'} readOnly={readOnly} onSeat={onSeat} />\n ))}\n </ul>\n )}\n\n <p className={styles.footnote}>\n Reserves limit autonomy only; your chats can always use a seat. A seat with no reading, or one{' '}\n {maxAgeMs !== null ? `older than ${Math.round(maxAgeMs / 60_000)} minutes` : 'whose reading is stale'}, is held back.\n </p>\n </section>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Connected panel\n// ---------------------------------------------------------------------------\n\nexport function BudgetControl({ maxMode = null }: { maxMode?: BudgetMode | null } = {}) {\n const budget = useQuery(budgetQuery, { freshMs: 0 });\n const preview = useQuery(budgetPreviewQuery, { freshMs: 0 });\n const refetchBudget = useRefetch(budgetQuery);\n const refetchPreview = useRefetch(budgetPreviewQuery);\n const gate = useTokenGate();\n const [latest, setLatest] = useState<BudgetView | null>(null);\n const [pending, setPending] = useState<string | null>(null);\n const [error, setError] = useState<string | null>(null);\n const [nowMs, setNowMs] = useState(() => Date.now());\n\n // Poll while visible; read immediately on return (useSeatsRefresh's pattern).\n useEffect(() => {\n const tick = (): void => {\n if (typeof document !== 'undefined' && document.visibilityState === 'hidden') return;\n refetchBudget();\n refetchPreview();\n setNowMs(Date.now());\n };\n const timer = window.setInterval(tick, BUDGET_POLL_MS);\n document.addEventListener('visibilitychange', tick);\n return () => {\n window.clearInterval(timer);\n document.removeEventListener('visibilitychange', tick);\n };\n }, [refetchBudget, refetchPreview]);\n\n // The POST response is newer than the cached read until the refetch lands.\n // A cached read with no parseable sampledAt cannot be shown to be newer, so\n // the POST's answer wins (NaN comparisons are always false).\n const cached = budget.data;\n const view = latest && (!cached || !(Date.parse(latest.sampledAt) < Date.parse(cached.sampledAt))) ? latest : cached;\n\n const apply = useCallback(async (key: string, reason: string, update: Parameters<typeof updateBudget>[0]) => {\n setPending(key);\n setError(null);\n try {\n const next = await gate.run(reason, () => updateBudget(update));\n if (next) setLatest(next);\n } catch (err) {\n setError(describeContextError(err));\n } finally {\n setPending(null);\n setNowMs(Date.now());\n }\n }, [gate]);\n\n // The server's reason (budget-api.ts answers `{ code, error }` for a read it\n // could not make), never the bare \"GET … failed (HTTP 503)\" wrapper.\n const budgetFailure = budget.status === 'error' ? readFailureReason(budget.error) : null;\n const previewFailure = preview.status === 'error' ? readFailureReason(preview.error) : null;\n\n if (!view) {\n return (\n <section className={styles.panel} aria-label=\"Budget\">\n {budgetFailure ? (\n <p className={styles.error} role=\"alert\">Budget unavailable. {budgetFailure}</p>\n ) : (\n <p className={styles.loading}>Reading seat usage…</p>\n )}\n </section>\n );\n }\n\n return (\n <>\n <BudgetControlView\n view={view}\n preview={preview.data ?? null}\n nowMs={nowMs}\n pending={pending}\n error={error}\n readError={budgetFailure\n ? `Showing the last readings. ${budgetFailure}`\n : previewFailure ? `Next-task preview unavailable. ${previewFailure}` : null}\n maxMode={maxMode}\n onMode={(mode) => void apply('mode', `Switch the budget to ${mode}`, { mode })}\n onSeat={(seatId, patch) => void apply(seatId, `Change the budget for ${seatId}`, { seatId, policy: patch })}\n />\n <MutationTokenDialog open={gate.dialog.open} reason={gate.dialog.reason} tokenLabel=\"Mutation token\"\n tokenHelp=\"the mutation token ashlr verse printed\" onClose={gate.dialog.onClose} onUnlocked={gate.dialog.onUnlocked} />\n </>\n );\n}\n"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- import{n as e}from"./index-CyK31YRm.js";var t={button:`_button_12qr7_1`,glyph:`_glyph_12qr7_30`,sm:`_sm_12qr7_37`,block:`_block_12qr7_43`,iconOnly:`_iconOnly_12qr7_48`,ghost:`_ghost_12qr7_60`,subtle:`_subtle_12qr7_71`,primary:`_primary_12qr7_84`,danger:`_danger_12qr7_99`},n=e();function r({variant:e=`subtle`,size:r=`md`,icon:i,trailingIcon:a,block:o=!1,busy:s=!1,iconOnly:c=!1,className:l,children:u,disabled:d,type:f=`button`,...p}){let m=[t.button,t[e],t[r],c?t.iconOnly:``,o?t.block:``,l??``].filter(Boolean).join(` `);return(0,n.jsxs)(`button`,{type:f,className:m,disabled:d||s,"aria-busy":s||void 0,...p,children:[i?(0,n.jsx)(`span`,{className:t.glyph,children:i}):null,c?null:u,a?(0,n.jsx)(`span`,{className:t.glyph,children:a}):null]})}function i({icon:e,...t}){return(0,n.jsx)(r,{...t,iconOnly:!0,icon:e})}export{i as n,r as t};
2
- //# sourceMappingURL=Button-DtE0rlWD.js.map
1
+ import{n as e}from"./index-DZ-UQ7v8.js";var t={button:`_button_12qr7_1`,glyph:`_glyph_12qr7_30`,sm:`_sm_12qr7_37`,block:`_block_12qr7_43`,iconOnly:`_iconOnly_12qr7_48`,ghost:`_ghost_12qr7_60`,subtle:`_subtle_12qr7_71`,primary:`_primary_12qr7_84`,danger:`_danger_12qr7_99`},n=e();function r({variant:e=`subtle`,size:r=`md`,icon:i,trailingIcon:a,block:o=!1,busy:s=!1,iconOnly:c=!1,className:l,children:u,disabled:d,type:f=`button`,...p}){let m=[t.button,t[e],t[r],c?t.iconOnly:``,o?t.block:``,l??``].filter(Boolean).join(` `);return(0,n.jsxs)(`button`,{type:f,className:m,disabled:d||s,"aria-busy":s||void 0,...p,children:[i?(0,n.jsx)(`span`,{className:t.glyph,children:i}):null,c?null:u,a?(0,n.jsx)(`span`,{className:t.glyph,children:a}):null]})}function i({icon:e,...t}){return(0,n.jsx)(r,{...t,iconOnly:!0,icon:e})}export{i as n,r as t};
2
+ //# sourceMappingURL=Button-D90dzI_o.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Button-DtE0rlWD.js","names":[],"sources":["../../../../../../src/web-ui/components/primitives/Button.module.css","../../../../../../src/web-ui/components/primitives/Button.tsx"],"sourcesContent":[".button {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: var(--space-2);\n height: var(--density-row);\n padding: 0 var(--density-pad);\n border: 1px solid transparent;\n border-radius: var(--radius-sm);\n background: transparent;\n color: var(--text-primary);\n font-family: var(--font-ui);\n font-size: var(--text-sm-size);\n line-height: 1;\n font-weight: var(--font-weight-medium);\n white-space: nowrap;\n cursor: pointer;\n transition:\n background-color var(--duration-fast) var(--ease-standard),\n border-color var(--duration-fast) var(--ease-standard),\n color var(--duration-fast) var(--ease-standard),\n opacity var(--duration-fast) var(--ease-standard);\n}\n\n.button:disabled {\n cursor: not-allowed;\n opacity: 0.55;\n}\n\n.glyph {\n display: inline-flex;\n flex: none;\n align-items: center;\n justify-content: center;\n}\n\n.sm {\n height: var(--density-row-sm);\n padding: 0 var(--space-2);\n font-size: var(--text-xs-size);\n}\n\n.block {\n width: 100%;\n}\n\n/* Square: width tracks the same density token as the height. */\n.iconOnly {\n width: var(--density-row);\n padding: 0;\n}\n\n.sm.iconOnly {\n width: var(--density-row-sm);\n}\n\n/* --------------------------------------------------------------------------\n * Variants\n * ------------------------------------------------------------------------ */\n.ghost {\n color: var(--text-secondary);\n}\n.ghost:hover:not(:disabled) {\n background: var(--bg-hover);\n color: var(--text-primary);\n}\n.ghost:active:not(:disabled) {\n background: var(--bg-active);\n}\n\n.subtle {\n border-color: var(--border-default);\n background: var(--bg-surface);\n color: var(--text-primary);\n}\n.subtle:hover:not(:disabled) {\n background: var(--bg-hover);\n border-color: var(--border-strong);\n}\n.subtle:active:not(:disabled) {\n background: var(--bg-active);\n}\n\n.primary {\n background: var(--accent-600);\n border-color: var(--accent-600);\n color: var(--text-on-accent);\n}\n.primary:hover:not(:disabled) {\n background: var(--accent-700);\n border-color: var(--accent-700);\n}\n.primary:active:not(:disabled) {\n background: var(--accent-700);\n}\n\n/* Destructive: outlined, never filled — a red block reads as an error state,\n and the design language reserves fills for the one primary action. */\n.danger {\n border-color: var(--border-default);\n color: var(--status-danger-fg);\n}\n.danger:hover:not(:disabled) {\n background: var(--status-danger-bg);\n border-color: var(--status-danger-solid);\n}\n.danger:active:not(:disabled) {\n background: var(--status-danger-bg);\n}\n\n/* Pressed/selected state for toggle buttons built on this primitive. */\n.button[aria-pressed='true'],\n.button[aria-expanded='true'] {\n background: var(--bg-selected);\n color: var(--text-primary);\n}\n","/**\n * components/primitives/Button.tsx — every clickable action in the console.\n *\n * Four variants, and they are a hierarchy, not a palette (design doc §1):\n * ghost — the default in dense chrome. No border, no fill. Header strips\n * contain only these.\n * subtle — hairline border, no fill. The ordinary form button.\n * primary — the ONE accent-filled action on a surface. If a screen has two,\n * one of them is wrong.\n * danger — destructive. Outlined, never filled, and always paired with a\n * confirm step at the call site (approve/emergency-stop/delete).\n *\n * Heights come from the density tokens, never from a literal px, so compact\n * mode moves every control together.\n *\n * Icon-only buttons are a TYPE-LEVEL contract: `iconOnly` requires\n * `aria-label`, because an icon with no text has no accessible name and the\n * operator's screen reader would announce \"button\". Use <IconButton> for the\n * common case.\n */\nimport type { ButtonHTMLAttributes, ReactNode, Ref } from 'react';\nimport styles from './Button.module.css';\n\nexport type ButtonVariant = 'ghost' | 'subtle' | 'primary' | 'danger';\nexport type ButtonSize = 'sm' | 'md';\n\ninterface ButtonBase extends Omit<ButtonHTMLAttributes<HTMLButtonElement>, 'className'> {\n variant?: ButtonVariant;\n size?: ButtonSize;\n /** Leading glyph (16px icon from ./icons.tsx). */\n icon?: ReactNode;\n /** Trailing glyph — chevrons, external-link marks. */\n trailingIcon?: ReactNode;\n /** Stretch to the container's width (forms, sheets). */\n block?: boolean;\n /** In-flight: disables the control and announces aria-busy. */\n busy?: boolean;\n /** Escape hatch for layout-only classes from a parent module. */\n className?: string;\n /** React 19 takes `ref` as an ordinary prop — no forwardRef wrapper needed. */\n ref?: Ref<HTMLButtonElement>;\n children?: ReactNode;\n}\n\nexport type ButtonProps = ButtonBase &\n (\n | {\n /** Square control with no visible label — an accessible name is mandatory. */\n iconOnly: true;\n 'aria-label': string;\n children?: never;\n }\n | { iconOnly?: false }\n );\n\nexport function Button({\n variant = 'subtle',\n size = 'md',\n icon,\n trailingIcon,\n block = false,\n busy = false,\n iconOnly = false,\n className,\n children,\n disabled,\n type = 'button',\n ...rest\n}: ButtonProps) {\n const classes = [\n styles.button,\n styles[variant],\n styles[size],\n iconOnly ? styles.iconOnly : '',\n block ? styles.block : '',\n className ?? '',\n ]\n .filter(Boolean)\n .join(' ');\n\n return (\n <button\n type={type}\n className={classes}\n disabled={disabled || busy}\n aria-busy={busy || undefined}\n {...rest}\n >\n {icon ? <span className={styles.glyph}>{icon}</span> : null}\n {iconOnly ? null : children}\n {trailingIcon ? <span className={styles.glyph}>{trailingIcon}</span> : null}\n </button>\n );\n}\n\nexport interface IconButtonProps extends Omit<ButtonBase, 'icon' | 'children' | 'trailingIcon'> {\n icon: ReactNode;\n /** Mandatory: the icon is the whole control. */\n 'aria-label': string;\n}\n\n/** Square, label-less button. Same variants and sizing as <Button>. */\nexport function IconButton({ icon, ...rest }: IconButtonProps) {\n return <Button {...rest} iconOnly icon={icon} />;\n}\n"],"mappings":"uRCuDA,SAAgB,EAAO,CACrB,UAAU,SACV,OAAO,KACP,OACA,eACA,QAAQ,GACR,OAAO,GACP,WAAW,GACX,YACA,WACA,WACA,OAAO,SACP,GAAG,GACW,CACd,IAAM,EAAU,CACd,EAAO,OACP,EAAO,GACP,EAAO,GACP,EAAW,EAAO,SAAW,GAC7B,EAAQ,EAAO,MAAQ,GACvB,GAAa,EACf,CAAC,CACE,OAAO,OAAO,CAAC,CACf,KAAK,GAAG,EAEX,OACE,EAAA,EAAA,KAAA,CAAC,SAAD,CACQ,OACN,UAAW,EACX,SAAU,GAAY,EACtB,YAAW,GAAQ,IAAA,GACnB,GAAI,EALN,SAAA,CAOG,GAAO,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,UAAW,EAAO,MAAQ,SAAA,CAAW,CAAA,EAAI,KACtD,EAAW,KAAO,EAClB,GAAe,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,UAAW,EAAO,MAAQ,SAAA,CAAmB,CAAA,EAAI,IACjE,GAEZ,CASA,SAAgB,EAAW,CAAE,OAAM,GAAG,GAAyB,CAC7D,OAAO,EAAA,EAAA,IAAA,CAAC,EAAD,CAAQ,GAAI,EAAM,SAAA,GAAe,MAAO,CAAA,CACjD"}
1
+ {"version":3,"file":"Button-D90dzI_o.js","names":[],"sources":["../../../../../../src/web-ui/components/primitives/Button.module.css","../../../../../../src/web-ui/components/primitives/Button.tsx"],"sourcesContent":[".button {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: var(--space-2);\n height: var(--density-row);\n padding: 0 var(--density-pad);\n border: 1px solid transparent;\n border-radius: var(--radius-sm);\n background: transparent;\n color: var(--text-primary);\n font-family: var(--font-ui);\n font-size: var(--text-sm-size);\n line-height: 1;\n font-weight: var(--font-weight-medium);\n white-space: nowrap;\n cursor: pointer;\n transition:\n background-color var(--duration-fast) var(--ease-standard),\n border-color var(--duration-fast) var(--ease-standard),\n color var(--duration-fast) var(--ease-standard),\n opacity var(--duration-fast) var(--ease-standard);\n}\n\n.button:disabled {\n cursor: not-allowed;\n opacity: 0.55;\n}\n\n.glyph {\n display: inline-flex;\n flex: none;\n align-items: center;\n justify-content: center;\n}\n\n.sm {\n height: var(--density-row-sm);\n padding: 0 var(--space-2);\n font-size: var(--text-xs-size);\n}\n\n.block {\n width: 100%;\n}\n\n/* Square: width tracks the same density token as the height. */\n.iconOnly {\n width: var(--density-row);\n padding: 0;\n}\n\n.sm.iconOnly {\n width: var(--density-row-sm);\n}\n\n/* --------------------------------------------------------------------------\n * Variants\n * ------------------------------------------------------------------------ */\n.ghost {\n color: var(--text-secondary);\n}\n.ghost:hover:not(:disabled) {\n background: var(--bg-hover);\n color: var(--text-primary);\n}\n.ghost:active:not(:disabled) {\n background: var(--bg-active);\n}\n\n.subtle {\n border-color: var(--border-default);\n background: var(--bg-surface);\n color: var(--text-primary);\n}\n.subtle:hover:not(:disabled) {\n background: var(--bg-hover);\n border-color: var(--border-strong);\n}\n.subtle:active:not(:disabled) {\n background: var(--bg-active);\n}\n\n.primary {\n background: var(--accent-600);\n border-color: var(--accent-600);\n color: var(--text-on-accent);\n}\n.primary:hover:not(:disabled) {\n background: var(--accent-700);\n border-color: var(--accent-700);\n}\n.primary:active:not(:disabled) {\n background: var(--accent-700);\n}\n\n/* Destructive: outlined, never filled — a red block reads as an error state,\n and the design language reserves fills for the one primary action. */\n.danger {\n border-color: var(--border-default);\n color: var(--status-danger-fg);\n}\n.danger:hover:not(:disabled) {\n background: var(--status-danger-bg);\n border-color: var(--status-danger-solid);\n}\n.danger:active:not(:disabled) {\n background: var(--status-danger-bg);\n}\n\n/* Pressed/selected state for toggle buttons built on this primitive. */\n.button[aria-pressed='true'],\n.button[aria-expanded='true'] {\n background: var(--bg-selected);\n color: var(--text-primary);\n}\n","/**\n * components/primitives/Button.tsx — every clickable action in the console.\n *\n * Four variants, and they are a hierarchy, not a palette (design doc §1):\n * ghost — the default in dense chrome. No border, no fill. Header strips\n * contain only these.\n * subtle — hairline border, no fill. The ordinary form button.\n * primary — the ONE accent-filled action on a surface. If a screen has two,\n * one of them is wrong.\n * danger — destructive. Outlined, never filled, and always paired with a\n * confirm step at the call site (approve/emergency-stop/delete).\n *\n * Heights come from the density tokens, never from a literal px, so compact\n * mode moves every control together.\n *\n * Icon-only buttons are a TYPE-LEVEL contract: `iconOnly` requires\n * `aria-label`, because an icon with no text has no accessible name and the\n * operator's screen reader would announce \"button\". Use <IconButton> for the\n * common case.\n */\nimport type { ButtonHTMLAttributes, ReactNode, Ref } from 'react';\nimport styles from './Button.module.css';\n\nexport type ButtonVariant = 'ghost' | 'subtle' | 'primary' | 'danger';\nexport type ButtonSize = 'sm' | 'md';\n\ninterface ButtonBase extends Omit<ButtonHTMLAttributes<HTMLButtonElement>, 'className'> {\n variant?: ButtonVariant;\n size?: ButtonSize;\n /** Leading glyph (16px icon from ./icons.tsx). */\n icon?: ReactNode;\n /** Trailing glyph — chevrons, external-link marks. */\n trailingIcon?: ReactNode;\n /** Stretch to the container's width (forms, sheets). */\n block?: boolean;\n /** In-flight: disables the control and announces aria-busy. */\n busy?: boolean;\n /** Escape hatch for layout-only classes from a parent module. */\n className?: string;\n /** React 19 takes `ref` as an ordinary prop — no forwardRef wrapper needed. */\n ref?: Ref<HTMLButtonElement>;\n children?: ReactNode;\n}\n\nexport type ButtonProps = ButtonBase &\n (\n | {\n /** Square control with no visible label — an accessible name is mandatory. */\n iconOnly: true;\n 'aria-label': string;\n children?: never;\n }\n | { iconOnly?: false }\n );\n\nexport function Button({\n variant = 'subtle',\n size = 'md',\n icon,\n trailingIcon,\n block = false,\n busy = false,\n iconOnly = false,\n className,\n children,\n disabled,\n type = 'button',\n ...rest\n}: ButtonProps) {\n const classes = [\n styles.button,\n styles[variant],\n styles[size],\n iconOnly ? styles.iconOnly : '',\n block ? styles.block : '',\n className ?? '',\n ]\n .filter(Boolean)\n .join(' ');\n\n return (\n <button\n type={type}\n className={classes}\n disabled={disabled || busy}\n aria-busy={busy || undefined}\n {...rest}\n >\n {icon ? <span className={styles.glyph}>{icon}</span> : null}\n {iconOnly ? null : children}\n {trailingIcon ? <span className={styles.glyph}>{trailingIcon}</span> : null}\n </button>\n );\n}\n\nexport interface IconButtonProps extends Omit<ButtonBase, 'icon' | 'children' | 'trailingIcon'> {\n icon: ReactNode;\n /** Mandatory: the icon is the whole control. */\n 'aria-label': string;\n}\n\n/** Square, label-less button. Same variants and sizing as <Button>. */\nexport function IconButton({ icon, ...rest }: IconButtonProps) {\n return <Button {...rest} iconOnly icon={icon} />;\n}\n"],"mappings":"uRCuDA,SAAgB,EAAO,CACrB,UAAU,SACV,OAAO,KACP,OACA,eACA,QAAQ,GACR,OAAO,GACP,WAAW,GACX,YACA,WACA,WACA,OAAO,SACP,GAAG,GACW,CACd,IAAM,EAAU,CACd,EAAO,OACP,EAAO,GACP,EAAO,GACP,EAAW,EAAO,SAAW,GAC7B,EAAQ,EAAO,MAAQ,GACvB,GAAa,EACf,CAAC,CACE,OAAO,OAAO,CAAC,CACf,KAAK,GAAG,EAEX,OACE,EAAA,EAAA,KAAA,CAAC,SAAD,CACQ,OACN,UAAW,EACX,SAAU,GAAY,EACtB,YAAW,GAAQ,IAAA,GACnB,GAAI,EALN,SAAA,CAOG,GAAO,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,UAAW,EAAO,MAAQ,SAAA,CAAW,CAAA,EAAI,KACtD,EAAW,KAAO,EAClB,GAAe,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,UAAW,EAAO,MAAQ,SAAA,CAAmB,CAAA,EAAI,IACjE,GAEZ,CASA,SAAgB,EAAW,CAAE,OAAM,GAAG,GAAyB,CAC7D,OAAO,EAAA,EAAA,IAAA,CAAC,EAAD,CAAQ,GAAI,EAAM,SAAA,GAAe,MAAO,CAAA,CACjD"}
@@ -1,2 +1,2 @@
1
- import{a as e,c as t,n}from"./index-CyK31YRm.js";import{h as r,m as i}from"./global-y_exIyAP.js";import{t as a}from"./ProviderLogo-AwHn2sKm.js";import{L as o,R as s,S as c}from"./VerseConsoleApp-DXDv1aOi.js";import{_ as l}from"./format-BmH2yWL6.js";import{r as u}from"./Tag-WSUIaMVy.js";import{n as d}from"./budget-queries-DFF-3ICg.js";import{a as f,l as p,n as m,o as h,r as g,t as _}from"./capacity-strip-model-5ViUgUlP.js";import{n as v,t as y}from"./useSeatsRefresh-q7Id9RcW.js";var b=t(e(),1),x={section:`_section_1vcn6_8`,scroll:`_scroll_1vcn6_16`,page:`_page_1vcn6_34`,header:`_header_1vcn6_43`,headerText:`_headerText_1vcn6_50`,title:`_title_1vcn6_56`,lede:`_lede_1vcn6_65`,headerMeta:`_headerMeta_1vcn6_71`,banner:`_banner_1vcn6_80`,accountsNote:`_accountsNote_1vcn6_96`,group:`_group_1vcn6_108`,groupHead:`_groupHead_1vcn6_114`,groupTitle:`_groupTitle_1vcn6_121`,caveat:`_caveat_1vcn6_138`,inlineCode:`_inlineCode_1vcn6_145`,card:`_card_1vcn6_154`,rows:`_rows_1vcn6_162`,row:`_row_1vcn6_162`,rowMain:`_rowMain_1vcn6_180`,rowHead:`_rowHead_1vcn6_187`,rowName:`_rowName_1vcn6_194`,rowVersion:`_rowVersion_1vcn6_200`,rowDesc:`_rowDesc_1vcn6_205`,rowDetail:`_rowDetail_1vcn6_206`,rowAside:`_rowAside_1vcn6_217`,health:`_health_1vcn6_228`,healthDot:`_healthDot_1vcn6_237`,loadingLine:`_loadingLine_1vcn6_263`,tile:`_tile_1vcn6_273`,pillWrap:`_pillWrap_1vcn6_314`,pill:`_pill_1vcn6_314`,pillText:`_pillText_1vcn6_348`,pillIcon:`_pillIcon_1vcn6_356`,visuallyHidden:`_visuallyHidden_1vcn6_367`,split:`_split_1vcn6_381`,disabledNote:`_disabledNote_1vcn6_394`,dialogBody:`_dialogBody_1vcn6_404`,commandBlock:`_commandBlock_1vcn6_415`,commandLabel:`_commandLabel_1vcn6_420`,dialogActions:`_dialogActions_1vcn6_428`,fieldset:`_fieldset_1vcn6_435`,legend:`_legend_1vcn6_443`,radio:`_radio_1vcn6_450`,error:`_error_1vcn6_460`,textarea:`_textarea_1vcn6_466`,fieldLabel:`_fieldLabel_1vcn6_483`,hint:`_hint_1vcn6_491`,warnings:`_warnings_1vcn6_495`,servers:`_servers_1vcn6_505`,reasonCode:`_reasonCode_1vcn6_511`,scopeLine:`_scopeLine_1vcn6_517`},S=n();function C({monogram:e,engine:t,size:n=`md`}){let r=t===null?void 0:{"--tile-hue":u(t)};return(0,S.jsx)(`span`,{className:x.tile,"data-size":n,"data-engine":t??void 0,style:r,"aria-hidden":`true`,children:t===null?e.slice(0,2):(0,S.jsx)(a,{engine:t,size:n===`sm`?14:18})})}var w={strip:`_strip_o9cqi_7`,visuallyHidden:`_visuallyHidden_o9cqi_15`,headline:`_headline_o9cqi_27`,empty:`_empty_o9cqi_35`,rows:`_rows_o9cqi_42`,row:`_row_o9cqi_42`,main:`_main_o9cqi_67`,head:`_head_o9cqi_27`,nameWrap:`_nameWrap_o9cqi_82`,nameButton:`_nameButton_o9cqi_83`,name:`_name_o9cqi_82`,plan:`_plan_o9cqi_121`,word:`_word_o9cqi_131`,dot:`_dot_o9cqi_140`,status:`_status_o9cqi_163`,statusLabel:`_statusLabel_o9cqi_176`,statusDetail:`_statusDetail_o9cqi_195`,stamp:`_stamp_o9cqi_199`,usableAgain:`_usableAgain_o9cqi_206`,summary:`_summary_o9cqi_211`,meta:`_meta_o9cqi_212`,autonomy:`_autonomy_o9cqi_222`,bars:`_bars_o9cqi_232`,bar:`_bar_o9cqi_232`,barLabel:`_barLabel_o9cqi_251`,track:`_track_o9cqi_262`,trackUnknown:`_trackUnknown_o9cqi_270`,used:`_used_o9cqi_276`,reserve:`_reserve_o9cqi_287`,ceiling:`_ceiling_o9cqi_297`,value:`_value_o9cqi_306`,reset:`_reset_o9cqi_319`,actions:`_actions_o9cqi_326`},T=90,E=3e4;function D(e){return Math.max(0,Math.min(100,Math.round(e)))}function O({row:e,w:t,reservePercent:n,compact:r}){let i=p(e,t,t.binding?n:null),a=t.binding&&n!==null&&n>0?100-D(n):null,o,s;if(t.limitReached)o=(0,S.jsx)(`span`,{className:w.track,role:`img`,"aria-label":i,children:(0,S.jsx)(`span`,{className:w.used,"data-level":`limit`,style:{width:`100%`}})}),s=(0,S.jsx)(`span`,{className:w.value,"data-level":`limit`,children:`limit reached`});else if(t.usedPercent===null)o=(0,S.jsx)(`span`,{className:w.trackUnknown,role:`img`,"aria-label":i}),s=(0,S.jsx)(`span`,{className:w.value,"data-level":`unknown`,children:`no reading`});else{let e=D(t.usedPercent),n=e>=T?`tight`:`ok`;o=(0,S.jsxs)(`span`,{className:w.track,role:`img`,"aria-label":i,children:[a===null?null:(0,S.jsx)(`span`,{className:w.reserve,style:{left:`${a}%`,width:`${100-a}%`}}),(0,S.jsx)(`span`,{className:w.used,"data-level":n,style:{width:`${e}%`}}),a===null?null:(0,S.jsx)(`span`,{className:w.ceiling,style:{left:`${a}%`}})]}),s=(0,S.jsx)(`span`,{className:w.value,"data-level":n,children:l(t.usedPercent)})}return(0,S.jsxs)(`div`,{className:w.bar,"data-binding":t.binding||void 0,"data-compact":r||void 0,children:[(0,S.jsx)(`span`,{className:w.barLabel,title:t.label,children:t.label.replace(/ window$/,``)}),o,s,!r&&t.resetText!==null?(0,S.jsx)(`span`,{className:w.reset,title:t.resetText,children:t.resetText}):null]})}function k({row:e,onSelect:t,selected:n}){let r=(0,S.jsxs)(S.Fragment,{children:[(0,S.jsx)(`span`,{className:w.name,children:e.label}),e.plan===null?null:(0,S.jsx)(`span`,{className:w.plan,children:e.plan})]});return t?(0,S.jsx)(`button`,{type:`button`,className:w.nameButton,"aria-pressed":n,onClick:()=>t(e.seatId),children:r}):(0,S.jsx)(`span`,{className:w.nameWrap,children:r})}function A({status:e}){return(0,S.jsxs)(`span`,{className:w.status,"data-tone":e.tone,"data-status":e.kind,children:[(0,S.jsx)(`span`,{className:w.dot,"aria-hidden":`true`}),(0,S.jsx)(`span`,{className:w.statusLabel,children:e.label}),e.detail===null?null:(0,S.jsx)(`span`,{className:w.statusDetail,children:`· ${e.detail}`})]})}function j({status:e}){return e.usableAgain===null&&e.checked===null?null:(0,S.jsxs)(`p`,{className:w.stamp,children:[e.usableAgain===null?null:(0,S.jsx)(`span`,{className:w.usableAgain,children:e.usableAgain}),e.usableAgain!==null&&e.checked!==null?` · `:null,e.checked===null?null:(0,S.jsx)(`span`,{title:e.checkedTitle??void 0,children:e.checked})]})}function M({row:e,compact:t,renderActions:n,onSelectSeat:r,selected:i,status:a}){let o=f(e.cls),s=e.windows.find(e=>e.binding)??null,c=t?s?[s]:[]:e.windows,l=n?n(e):null,u=e.reserve;return(0,S.jsxs)(`li`,{className:w.row,"data-capacity":e.cls,"data-compact":t||void 0,"data-status":a?.kind,children:[(0,S.jsx)(C,{monogram:e.monogram,engine:e.engine,size:`sm`}),(0,S.jsxs)(`div`,{className:w.main,children:[(0,S.jsxs)(`div`,{className:w.head,children:[(0,S.jsx)(k,{row:e,onSelect:r,selected:i}),a===null?(0,S.jsxs)(`span`,{className:w.word,"data-tone":o,children:[(0,S.jsx)(`span`,{className:w.dot,"aria-hidden":`true`}),e.word]}):(0,S.jsx)(A,{status:a}),e.connection!==null&&e.connection.connection!==`connected`&&e.connection.connection!==`unknown`&&!(a?.coversConnection??!1)&&a?.kind!==`signed-out`?(0,S.jsxs)(`span`,{className:w.word,"data-tone":e.connection.tone,children:[(0,S.jsx)(`span`,{className:w.dot,"aria-hidden":`true`}),e.connection.word]}):null]}),!t||c.length===0?(0,S.jsx)(`p`,{className:w.summary,children:e.summary}):null,a!==null&&!t?(0,S.jsx)(j,{status:a}):null,c.length>0?(0,S.jsx)(`div`,{className:w.bars,children:c.map(n=>(0,S.jsx)(O,{row:e,w:n,reservePercent:u?.percent??null,compact:t},n.id))}):null,!t&&(u!==null||e.credits!==null)?(0,S.jsxs)(`p`,{className:w.meta,children:[u===null?null:(0,S.jsxs)(`span`,{title:u.why,children:[u.label,u.autonomy===`off`?null:(0,S.jsxs)(S.Fragment,{children:[` · Autonomy: `,(0,S.jsx)(`span`,{className:w.autonomy,"data-status":u.autonomy,children:u.autonomyWord})]})]}),u!==null&&e.credits!==null?` · `:null,e.credits===null?null:(0,S.jsx)(`span`,{children:e.credits})]}):null]}),l?(0,S.jsx)(`div`,{className:w.actions,children:l}):null]})}function N({seats:e,health:t,budget:n,local:r,seatIds:i,density:a=`full`,headline:s,title:c=`Seat capacity`,labelledBy:l,renderActions:u,onSelectSeat:d,selectedSeatId:f=null,emptyText:p=`No seats yet. Connect an account or start Ollama.`,accounts:v}){let y=(0,b.useId)(),[x,C]=(0,b.useState)(()=>Date.now());o(()=>C(Date.now()),E,{enabled:v!==void 0&&v.now===void 0});let T=v?.now??x,D=v?.healthRead??!1,O=v!==void 0,k=O?T:void 0,A=(0,b.useMemo)(()=>m(e,{health:t??null,budget:n??null,...r?{local:r}:{},...i?{seatIds:i}:{},...k===void 0?{}:{now:k}}),[e,t,n,r,i,k]),j=(0,b.useMemo)(()=>O?h(A,{healthRead:D,now:T}):A,[A,O,D,T]),N=a===`compact`,P=s??!N;return(0,S.jsxs)(l?`div`:`section`,{className:w.strip,"aria-labelledby":l?void 0:y,"data-density":a,children:[l?null:(0,S.jsx)(`h3`,{id:y,className:w.visuallyHidden,children:c}),P&&j.length>0?(0,S.jsx)(`p`,{className:w.headline,children:g(j)}):null,j.length===0?(0,S.jsx)(`p`,{className:w.empty,children:p}):(0,S.jsx)(`ul`,{className:w.rows,"aria-label":l?void 0:c,"aria-labelledby":l,children:j.map(e=>(0,S.jsx)(M,{row:e,compact:N,renderActions:u,onSelectSeat:d,selected:f===e.seatId,status:v?_(e,{healthRead:D,now:T,checking:v.checkingSeatId===e.seatId}):null},e.seatId))})]})}var P=6e4;function F(e={}){let t=s(),n=e.withBudget??!0,a=e.withHealth??!0,l=i(c);y(t);let u=v(t&&a),f=i(d),p=r(d);o(p,P,{enabled:n});let m=l.data;return{seats:m?.seats??[],health:a?u.data?.seats??null:null,budget:n?f.data??null:null,loading:m===void 0&&(l.status===`loading`||l.status===`idle`)}}function I({seats:e,...t}){let n=F();return e===void 0&&n.loading?(0,S.jsx)(`p`,{className:w.empty,"aria-busy":`true`,children:`Reading seats…`}):(0,S.jsx)(N,{...t,seats:e??n.seats,health:n.health,budget:n.budget})}export{C as a,F as i,N as n,x as o,I as r,E as t};
2
- //# sourceMappingURL=CapacityStrip-DKbKA_Aa.js.map
1
+ import{a as e,c as t,n}from"./index-DZ-UQ7v8.js";import{g as r,h as i}from"./global-CMNW_dqn.js";import{t as a}from"./ProviderLogo-Cq-CYIwT.js";import{L as o,R as s,S as c}from"./VerseConsoleApp-CWU6R3By.js";import{_ as l}from"./format-CH4g_sl1.js";import{r as u}from"./Tag-DscCRFcN.js";import{n as d}from"./budget-queries-D8QV5XtH.js";import{a as f,l as p,n as m,o as h,r as g,t as _}from"./capacity-strip-model-BwZ1ZbkU.js";import{n as v,t as y}from"./useSeatsRefresh-Co1CnxLc.js";var b=t(e(),1),x={section:`_section_1vcn6_8`,scroll:`_scroll_1vcn6_16`,page:`_page_1vcn6_34`,header:`_header_1vcn6_43`,headerText:`_headerText_1vcn6_50`,title:`_title_1vcn6_56`,lede:`_lede_1vcn6_65`,headerMeta:`_headerMeta_1vcn6_71`,banner:`_banner_1vcn6_80`,accountsNote:`_accountsNote_1vcn6_96`,group:`_group_1vcn6_108`,groupHead:`_groupHead_1vcn6_114`,groupTitle:`_groupTitle_1vcn6_121`,caveat:`_caveat_1vcn6_138`,inlineCode:`_inlineCode_1vcn6_145`,card:`_card_1vcn6_154`,rows:`_rows_1vcn6_162`,row:`_row_1vcn6_162`,rowMain:`_rowMain_1vcn6_180`,rowHead:`_rowHead_1vcn6_187`,rowName:`_rowName_1vcn6_194`,rowVersion:`_rowVersion_1vcn6_200`,rowDesc:`_rowDesc_1vcn6_205`,rowDetail:`_rowDetail_1vcn6_206`,rowAside:`_rowAside_1vcn6_217`,health:`_health_1vcn6_228`,healthDot:`_healthDot_1vcn6_237`,loadingLine:`_loadingLine_1vcn6_263`,tile:`_tile_1vcn6_273`,pillWrap:`_pillWrap_1vcn6_314`,pill:`_pill_1vcn6_314`,pillText:`_pillText_1vcn6_348`,pillIcon:`_pillIcon_1vcn6_356`,visuallyHidden:`_visuallyHidden_1vcn6_367`,split:`_split_1vcn6_381`,disabledNote:`_disabledNote_1vcn6_394`,dialogBody:`_dialogBody_1vcn6_404`,commandBlock:`_commandBlock_1vcn6_415`,commandLabel:`_commandLabel_1vcn6_420`,dialogActions:`_dialogActions_1vcn6_428`,fieldset:`_fieldset_1vcn6_435`,legend:`_legend_1vcn6_443`,radio:`_radio_1vcn6_450`,error:`_error_1vcn6_460`,textarea:`_textarea_1vcn6_466`,fieldLabel:`_fieldLabel_1vcn6_483`,hint:`_hint_1vcn6_491`,warnings:`_warnings_1vcn6_495`,servers:`_servers_1vcn6_505`,reasonCode:`_reasonCode_1vcn6_511`,scopeLine:`_scopeLine_1vcn6_517`},S=n();function C({monogram:e,engine:t,size:n=`md`}){let r=t===null?void 0:{"--tile-hue":u(t)};return(0,S.jsx)(`span`,{className:x.tile,"data-size":n,"data-engine":t??void 0,style:r,"aria-hidden":`true`,children:t===null?e.slice(0,2):(0,S.jsx)(a,{engine:t,size:n===`sm`?14:18})})}var w={strip:`_strip_o9cqi_7`,visuallyHidden:`_visuallyHidden_o9cqi_15`,headline:`_headline_o9cqi_27`,empty:`_empty_o9cqi_35`,rows:`_rows_o9cqi_42`,row:`_row_o9cqi_42`,main:`_main_o9cqi_67`,head:`_head_o9cqi_27`,nameWrap:`_nameWrap_o9cqi_82`,nameButton:`_nameButton_o9cqi_83`,name:`_name_o9cqi_82`,plan:`_plan_o9cqi_121`,word:`_word_o9cqi_131`,dot:`_dot_o9cqi_140`,status:`_status_o9cqi_163`,statusLabel:`_statusLabel_o9cqi_176`,statusDetail:`_statusDetail_o9cqi_195`,stamp:`_stamp_o9cqi_199`,usableAgain:`_usableAgain_o9cqi_206`,summary:`_summary_o9cqi_211`,meta:`_meta_o9cqi_212`,autonomy:`_autonomy_o9cqi_222`,bars:`_bars_o9cqi_232`,bar:`_bar_o9cqi_232`,barLabel:`_barLabel_o9cqi_251`,track:`_track_o9cqi_262`,trackUnknown:`_trackUnknown_o9cqi_270`,used:`_used_o9cqi_276`,reserve:`_reserve_o9cqi_287`,ceiling:`_ceiling_o9cqi_297`,value:`_value_o9cqi_306`,reset:`_reset_o9cqi_319`,actions:`_actions_o9cqi_326`},T=90,E=3e4;function D(e){return Math.max(0,Math.min(100,Math.round(e)))}function O({row:e,w:t,reservePercent:n,compact:r}){let i=p(e,t,t.binding?n:null),a=t.binding&&n!==null&&n>0?100-D(n):null,o,s;if(t.limitReached)o=(0,S.jsx)(`span`,{className:w.track,role:`img`,"aria-label":i,children:(0,S.jsx)(`span`,{className:w.used,"data-level":`limit`,style:{width:`100%`}})}),s=(0,S.jsx)(`span`,{className:w.value,"data-level":`limit`,children:`limit reached`});else if(t.usedPercent===null)o=(0,S.jsx)(`span`,{className:w.trackUnknown,role:`img`,"aria-label":i}),s=(0,S.jsx)(`span`,{className:w.value,"data-level":`unknown`,children:`no reading`});else{let e=D(t.usedPercent),n=e>=T?`tight`:`ok`;o=(0,S.jsxs)(`span`,{className:w.track,role:`img`,"aria-label":i,children:[a===null?null:(0,S.jsx)(`span`,{className:w.reserve,style:{left:`${a}%`,width:`${100-a}%`}}),(0,S.jsx)(`span`,{className:w.used,"data-level":n,style:{width:`${e}%`}}),a===null?null:(0,S.jsx)(`span`,{className:w.ceiling,style:{left:`${a}%`}})]}),s=(0,S.jsx)(`span`,{className:w.value,"data-level":n,children:l(t.usedPercent)})}return(0,S.jsxs)(`div`,{className:w.bar,"data-binding":t.binding||void 0,"data-compact":r||void 0,children:[(0,S.jsx)(`span`,{className:w.barLabel,title:t.label,children:t.label.replace(/ window$/,``)}),o,s,!r&&t.resetText!==null?(0,S.jsx)(`span`,{className:w.reset,title:t.resetText,children:t.resetText}):null]})}function k({row:e,onSelect:t,selected:n}){let r=(0,S.jsxs)(S.Fragment,{children:[(0,S.jsx)(`span`,{className:w.name,children:e.label}),e.plan===null?null:(0,S.jsx)(`span`,{className:w.plan,children:e.plan})]});return t?(0,S.jsx)(`button`,{type:`button`,className:w.nameButton,"aria-pressed":n,onClick:()=>t(e.seatId),children:r}):(0,S.jsx)(`span`,{className:w.nameWrap,children:r})}function A({status:e}){return(0,S.jsxs)(`span`,{className:w.status,"data-tone":e.tone,"data-status":e.kind,children:[(0,S.jsx)(`span`,{className:w.dot,"aria-hidden":`true`}),(0,S.jsx)(`span`,{className:w.statusLabel,children:e.label}),e.detail===null?null:(0,S.jsx)(`span`,{className:w.statusDetail,children:`· ${e.detail}`})]})}function j({status:e}){return e.usableAgain===null&&e.checked===null?null:(0,S.jsxs)(`p`,{className:w.stamp,children:[e.usableAgain===null?null:(0,S.jsx)(`span`,{className:w.usableAgain,children:e.usableAgain}),e.usableAgain!==null&&e.checked!==null?` · `:null,e.checked===null?null:(0,S.jsx)(`span`,{title:e.checkedTitle??void 0,children:e.checked})]})}function M({row:e,compact:t,renderActions:n,onSelectSeat:r,selected:i,status:a}){let o=f(e.cls),s=e.windows.find(e=>e.binding)??null,c=t?s?[s]:[]:e.windows,l=n?n(e):null,u=e.reserve;return(0,S.jsxs)(`li`,{className:w.row,"data-capacity":e.cls,"data-compact":t||void 0,"data-status":a?.kind,children:[(0,S.jsx)(C,{monogram:e.monogram,engine:e.engine,size:`sm`}),(0,S.jsxs)(`div`,{className:w.main,children:[(0,S.jsxs)(`div`,{className:w.head,children:[(0,S.jsx)(k,{row:e,onSelect:r,selected:i}),a===null?(0,S.jsxs)(`span`,{className:w.word,"data-tone":o,children:[(0,S.jsx)(`span`,{className:w.dot,"aria-hidden":`true`}),e.word]}):(0,S.jsx)(A,{status:a}),e.connection!==null&&e.connection.connection!==`connected`&&e.connection.connection!==`unknown`&&!(a?.coversConnection??!1)&&a?.kind!==`signed-out`?(0,S.jsxs)(`span`,{className:w.word,"data-tone":e.connection.tone,children:[(0,S.jsx)(`span`,{className:w.dot,"aria-hidden":`true`}),e.connection.word]}):null]}),!t||c.length===0?(0,S.jsx)(`p`,{className:w.summary,children:e.summary}):null,a!==null&&!t?(0,S.jsx)(j,{status:a}):null,c.length>0?(0,S.jsx)(`div`,{className:w.bars,children:c.map(n=>(0,S.jsx)(O,{row:e,w:n,reservePercent:u?.percent??null,compact:t},n.id))}):null,!t&&(u!==null||e.credits!==null)?(0,S.jsxs)(`p`,{className:w.meta,children:[u===null?null:(0,S.jsxs)(`span`,{title:u.why,children:[u.label,u.autonomy===`off`?null:(0,S.jsxs)(S.Fragment,{children:[` · Autonomy: `,(0,S.jsx)(`span`,{className:w.autonomy,"data-status":u.autonomy,children:u.autonomyWord})]})]}),u!==null&&e.credits!==null?` · `:null,e.credits===null?null:(0,S.jsx)(`span`,{children:e.credits})]}):null]}),l?(0,S.jsx)(`div`,{className:w.actions,children:l}):null]})}function N({seats:e,health:t,budget:n,local:r,seatIds:i,density:a=`full`,headline:s,title:c=`Seat capacity`,labelledBy:l,renderActions:u,onSelectSeat:d,selectedSeatId:f=null,emptyText:p=`No seats yet. Connect an account or start Ollama.`,accounts:v}){let y=(0,b.useId)(),[x,C]=(0,b.useState)(()=>Date.now());o(()=>C(Date.now()),E,{enabled:v!==void 0&&v.now===void 0});let T=v?.now??x,D=v?.healthRead??!1,O=v!==void 0,k=O?T:void 0,A=(0,b.useMemo)(()=>m(e,{health:t??null,budget:n??null,...r?{local:r}:{},...i?{seatIds:i}:{},...k===void 0?{}:{now:k}}),[e,t,n,r,i,k]),j=(0,b.useMemo)(()=>O?h(A,{healthRead:D,now:T}):A,[A,O,D,T]),N=a===`compact`,P=s??!N;return(0,S.jsxs)(l?`div`:`section`,{className:w.strip,"aria-labelledby":l?void 0:y,"data-density":a,children:[l?null:(0,S.jsx)(`h3`,{id:y,className:w.visuallyHidden,children:c}),P&&j.length>0?(0,S.jsx)(`p`,{className:w.headline,children:g(j)}):null,j.length===0?(0,S.jsx)(`p`,{className:w.empty,children:p}):(0,S.jsx)(`ul`,{className:w.rows,"aria-label":l?void 0:c,"aria-labelledby":l,children:j.map(e=>(0,S.jsx)(M,{row:e,compact:N,renderActions:u,onSelectSeat:d,selected:f===e.seatId,status:v?_(e,{healthRead:D,now:T,checking:v.checkingSeatId===e.seatId}):null},e.seatId))})]})}var P=6e4;function F(e={}){let t=s(),n=e.withBudget??!0,a=e.withHealth??!0,l=i(c);y(t);let u=v(t&&a),f=i(d),p=r(d);o(p,P,{enabled:n});let m=l.data;return{seats:m?.seats??[],health:a?u.data?.seats??null:null,budget:n?f.data??null:null,loading:m===void 0&&(l.status===`loading`||l.status===`idle`)}}function I({seats:e,...t}){let n=F();return e===void 0&&n.loading?(0,S.jsx)(`p`,{className:w.empty,"aria-busy":`true`,children:`Reading seats…`}):(0,S.jsx)(N,{...t,seats:e??n.seats,health:n.health,budget:n.budget})}export{C as a,F as i,N as n,x as o,I as r,E as t};
2
+ //# sourceMappingURL=CapacityStrip-qKDBC65C.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"CapacityStrip-DKbKA_Aa.js","names":[],"sources":["../../../../../../src/web-ui/routes/verse/apps/Apps.module.css","../../../../../../src/web-ui/routes/verse/apps/MonogramTile.tsx","../../../../../../src/web-ui/routes/verse/usage/CapacityStrip.module.css","../../../../../../src/web-ui/routes/verse/usage/CapacityStrip.tsx"],"sourcesContent":["/*\n * Apps & Accounts (SPEC-310C §4) — grouped rows in the Ollama style, max\n * 880px. Tokens only (DESIGN.md §13; style-scan-310 enforces it): no raw\n * colour, no px font size. The row adapts to its container: at the compact\n * width (480, viewport.ts) the right-hand pill wraps under the description.\n */\n\n.section {\n display: flex;\n flex-direction: column;\n min-height: 0;\n height: 100%;\n background: var(--bg-canvas);\n}\n\n.scroll {\n flex: 1;\n min-height: 0;\n overflow-y: auto;\n padding: var(--space-6) var(--space-4) var(--space-12);\n /* Desktop shell (desktop/README.md \"Desktop shell contract\"): this page has\n no 48px strip, so its title sits inside the OS title-bar band. Once the\n window is narrow enough that the 880px column stops centring (minWidth\n is 900), the column's left edge lands at rail + 16px — under the macOS\n traffic lights, which cover the top-left 92px of the WINDOW. Owe the same\n overlap every header strip owes (inset − rail, 36px on a 56px rail);\n the vars are absent in a browser and the expanded rail sits under the\n lights itself, so both floor to --space-4 and nothing moves there. The\n whole column shifts, not just the header, so the title stays aligned\n with the rows under it. */\n padding-left: max(var(--space-4), calc(var(--app-traffic-light-inset, 0px) - var(--rail-width, 56px)));\n}\n\n.page {\n container-type: inline-size;\n max-width: 880px;\n margin: 0 auto;\n display: flex;\n flex-direction: column;\n gap: var(--space-8);\n}\n\n.header {\n display: flex;\n flex-wrap: wrap;\n align-items: flex-end;\n justify-content: space-between;\n gap: var(--space-3) var(--space-4);\n}\n.headerText {\n display: flex;\n flex-direction: column;\n gap: var(--space-1);\n min-width: 0;\n}\n.title {\n margin: 0;\n font-family: var(--font-display);\n font-size: var(--text-xl-size);\n line-height: var(--text-xl-line);\n letter-spacing: var(--tracking-display);\n font-weight: var(--font-weight-semibold);\n color: var(--text-primary);\n}\n.lede {\n margin: 0;\n font-size: var(--text-sm-size);\n line-height: var(--text-sm-line);\n color: var(--text-secondary);\n}\n.headerMeta {\n display: flex;\n align-items: center;\n gap: var(--space-2);\n font-size: var(--text-xs-size);\n line-height: var(--text-xs-line);\n color: var(--text-tertiary);\n}\n\n.banner {\n margin: 0;\n padding: var(--space-3) var(--space-4);\n border: 1px solid var(--border-subtle);\n border-radius: var(--radius-md);\n background: var(--bg-surface);\n font-size: var(--text-sm-size);\n line-height: var(--text-sm-line);\n color: var(--text-secondary);\n}\n.banner[data-tone='danger'] {\n border-color: color-mix(in srgb, var(--status-danger-solid) 40%, var(--border-subtle));\n color: var(--status-danger-fg);\n}\n\n/* The Accounts group's own \"Checked … again\" line, under the strip. */\n.accountsNote {\n margin: 0;\n font-size: var(--text-xs-size);\n line-height: var(--text-xs-line);\n color: var(--text-secondary);\n}\n.accountsNote[data-tone='danger'] {\n color: var(--status-danger-fg);\n}\n\n/* ── Groups ─────────────────────────────────────────────────────────── */\n\n.group {\n display: flex;\n flex-direction: column;\n gap: var(--space-2);\n scroll-margin-top: var(--space-6);\n}\n.groupHead {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--space-3);\n min-height: var(--control-h-sm);\n}\n.groupTitle {\n margin: 0;\n font-family: var(--font-display);\n font-size: var(--text-2xs-size);\n line-height: var(--text-2xs-line);\n text-transform: uppercase;\n letter-spacing: var(--tracking-label);\n font-weight: var(--font-weight-semibold);\n color: var(--text-tertiary);\n}\n.groupTitle:focus {\n outline: none;\n}\n.groupTitle:focus-visible {\n box-shadow: var(--shadow-focus-ring);\n border-radius: var(--radius-xs);\n}\n.caveat {\n margin: 0;\n font-size: var(--text-xs-size);\n line-height: var(--text-xs-line-relaxed);\n color: var(--text-secondary);\n}\n.caveat code,\n.inlineCode {\n font-family: var(--font-mono);\n font-size: var(--text-xs-size);\n background: var(--bg-code);\n padding: 0 var(--space-1);\n border-radius: var(--radius-xs);\n overflow-wrap: anywhere;\n}\n\n.card {\n border: 1px solid var(--border-subtle);\n border-radius: var(--radius-lg);\n background: var(--bg-surface);\n padding: 0 var(--card-pad);\n box-shadow: inset 0 1px 0 var(--hairline-lift);\n}\n\n.rows {\n list-style: none;\n margin: 0;\n padding: 0;\n}\n\n.row {\n display: grid;\n grid-template-columns: auto minmax(0, 1fr) auto;\n align-items: start;\n gap: var(--space-3);\n padding: var(--space-3) 0;\n border-top: 1px solid var(--border-subtle);\n}\n.row:first-child {\n border-top: 0;\n}\n\n.rowMain {\n display: flex;\n flex-direction: column;\n gap: var(--space-1);\n min-width: 0;\n padding-top: var(--space-1);\n}\n.rowHead {\n display: flex;\n flex-wrap: wrap;\n align-items: baseline;\n gap: var(--space-1) var(--space-3);\n min-width: 0;\n}\n.rowName {\n font-size: var(--text-sm-size);\n line-height: var(--text-sm-line);\n font-weight: var(--font-weight-semibold);\n color: var(--text-primary);\n}\n.rowVersion {\n font-family: var(--font-mono);\n font-size: var(--text-xs-size);\n color: var(--text-tertiary);\n}\n.rowDesc,\n.rowDetail {\n margin: 0;\n font-size: var(--text-xs-size);\n line-height: var(--text-xs-line-relaxed);\n color: var(--text-secondary);\n overflow-wrap: anywhere;\n}\n.rowDetail {\n color: var(--text-tertiary);\n}\n\n.rowAside {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n justify-content: flex-end;\n gap: var(--space-2);\n padding-top: var(--space-1);\n max-width: 26rem;\n}\n\n/* A health state is a WORD; the dot reinforces it (DESIGN §13.2). */\n.health {\n display: inline-flex;\n align-items: center;\n gap: var(--space-1);\n font-size: var(--text-xs-size);\n line-height: var(--text-xs-line);\n color: var(--text-secondary);\n white-space: nowrap;\n}\n.healthDot {\n width: 7px;\n height: 7px;\n border-radius: var(--radius-full);\n background: var(--status-neutral-solid);\n flex: none;\n}\n.health[data-tone='success'] .healthDot { background: var(--status-success-solid); }\n.health[data-tone='warning'] { color: var(--status-warning-fg); }\n.health[data-tone='warning'] .healthDot { background: var(--status-warning-solid); }\n.health[data-tone='danger'] { color: var(--status-danger-fg); }\n.health[data-tone='danger'] .healthDot { background: var(--status-danger-solid); }\n.health[data-tone='off'] { color: var(--text-tertiary); }\n.health[data-tone='off'] .healthDot {\n background: transparent;\n border: 1px solid var(--border-strong);\n}\n.health[data-tone='neutral'] {\n font-style: italic;\n color: var(--status-unknown-fg);\n}\n.health[data-tone='neutral'] .healthDot {\n background: transparent;\n border: 1px dashed var(--status-unknown-solid);\n}\n\n.loadingLine {\n margin: 0;\n padding: var(--space-3) 0;\n font-size: var(--text-sm-size);\n line-height: var(--text-sm-line);\n color: var(--text-secondary);\n}\n\n/* ── Monogram tile (32px rows, 24px capacity rows) ───────────────────── */\n\n.tile {\n --tile-hue: var(--text-tertiary);\n display: inline-flex;\n align-items: center;\n justify-content: center;\n flex: none;\n width: 32px;\n height: 32px;\n border-radius: var(--radius-md);\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 background: var(--bg-surface-raised);\n border: 1px solid var(--border-subtle);\n position: relative;\n overflow: hidden;\n}\n.tile[data-engine] {\n background: color-mix(in srgb, var(--tile-hue) 12%, var(--bg-surface));\n border-color: color-mix(in srgb, var(--tile-hue) 28%, var(--border-subtle));\n}\n/* The 2px identity tick. */\n.tile[data-engine]::before {\n content: '';\n position: absolute;\n left: 0;\n top: 0;\n bottom: 0;\n width: 2px;\n background: var(--tile-hue);\n}\n.tile[data-size='sm'] {\n width: 24px;\n height: 24px;\n border-radius: var(--radius-sm);\n font-size: var(--text-xs-size);\n}\n\n/* ── Copy pill ───────────────────────────────────────────────────────── */\n\n.pillWrap {\n display: inline-flex;\n min-width: 0;\n max-width: 100%;\n}\n/*\n * A long command WRAPS rather than ellipsizing: the operator reads what they\n * are about to paste, and a command cut mid-word (\"node ~/.ashlr/nat…\") is\n * exactly the part they need. One line keeps the pill shape (the radius is\n * half the control height); two lines become a soft capsule.\n */\n.pill {\n display: inline-flex;\n align-items: center;\n gap: var(--space-2);\n min-width: 0;\n max-width: 100%;\n min-height: var(--control-h-sm);\n padding: 2px var(--space-2) 2px var(--space-3);\n border: 1px solid var(--border-subtle);\n border-radius: calc(var(--control-h-sm) / 2);\n text-align: left;\n background: var(--bg-code);\n color: var(--text-primary);\n cursor: pointer;\n transition: border-color var(--duration-fast) var(--ease-standard);\n}\n.pill:hover {\n border-color: var(--border-strong);\n}\n.pill:focus-visible {\n outline: none;\n box-shadow: var(--shadow-focus-ring);\n}\n.pillText {\n font-family: var(--font-mono);\n font-size: var(--text-xs-size);\n line-height: var(--text-xs-line);\n white-space: normal;\n overflow-wrap: anywhere;\n min-width: 0;\n}\n.pillIcon {\n display: inline-flex;\n color: var(--text-tertiary);\n}\n.pill[data-state='copied'] .pillIcon {\n color: var(--status-success-fg);\n}\n.pill[data-state='failed'] {\n border-color: var(--status-danger-solid);\n}\n\n.visuallyHidden {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n clip: rect(0 0 0 0);\n white-space: nowrap;\n border: 0;\n}\n\n/* ── Launch split button ─────────────────────────────────────────────── */\n\n.split {\n display: inline-flex;\n align-items: stretch;\n}\n.split > :first-child {\n border-top-right-radius: 0;\n border-bottom-right-radius: 0;\n}\n.split > :last-child {\n border-top-left-radius: 0;\n border-bottom-left-radius: 0;\n margin-left: -1px;\n}\n.disabledNote {\n font-size: var(--text-xs-size);\n line-height: var(--text-xs-line);\n color: var(--text-tertiary);\n max-width: 18rem;\n text-align: right;\n}\n\n/* ── Dialog bodies ───────────────────────────────────────────────────── */\n\n.dialogBody {\n display: flex;\n flex-direction: column;\n gap: var(--space-3);\n font-size: var(--text-sm-size);\n line-height: var(--text-sm-line);\n color: var(--text-secondary);\n}\n.dialogBody p {\n margin: 0;\n}\n.commandBlock {\n display: flex;\n flex-direction: column;\n gap: var(--space-1);\n}\n.commandLabel {\n font-family: var(--font-display);\n font-size: var(--text-2xs-size);\n line-height: var(--text-2xs-line);\n text-transform: uppercase;\n letter-spacing: var(--tracking-label);\n color: var(--text-tertiary);\n}\n.dialogActions {\n display: flex;\n flex-wrap: wrap;\n justify-content: flex-end;\n gap: var(--space-2);\n margin-top: var(--space-2);\n}\n.fieldset {\n border: 0;\n margin: 0;\n padding: 0;\n display: flex;\n flex-direction: column;\n gap: var(--space-2);\n}\n.legend {\n padding: 0;\n margin-bottom: var(--space-1);\n font-size: var(--text-xs-size);\n font-weight: var(--font-weight-semibold);\n color: var(--text-primary);\n}\n.radio {\n display: flex;\n align-items: center;\n gap: var(--space-2);\n font-size: var(--text-sm-size);\n color: var(--text-primary);\n}\n.radio input {\n accent-color: var(--accent-500);\n}\n.error {\n margin: 0;\n font-size: var(--text-xs-size);\n line-height: var(--text-xs-line-relaxed);\n color: var(--status-danger-fg);\n}\n.textarea {\n width: 100%;\n min-height: 5rem;\n resize: vertical;\n padding: var(--space-2);\n border: 1px solid var(--border-default);\n border-radius: var(--radius-sm);\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-relaxed);\n}\n.textarea:focus-visible {\n outline: none;\n box-shadow: var(--shadow-focus-ring);\n}\n.fieldLabel {\n display: flex;\n flex-direction: column;\n gap: var(--space-1);\n font-size: var(--text-xs-size);\n font-weight: var(--font-weight-medium);\n color: var(--text-primary);\n}\n.hint {\n font-weight: var(--font-weight-regular);\n color: var(--text-tertiary);\n}\n.warnings {\n margin: 0;\n padding-left: var(--space-4);\n font-size: var(--text-xs-size);\n line-height: var(--text-xs-line-relaxed);\n color: var(--status-warning-fg);\n}\n\n/* ── MCP ─────────────────────────────────────────────────────────────── */\n\n.servers {\n display: flex;\n flex-direction: column;\n gap: var(--space-2);\n margin-top: var(--space-2);\n}\n.reasonCode {\n font-family: var(--font-mono);\n font-size: var(--text-2xs-size);\n color: var(--text-tertiary);\n}\n\n.scopeLine {\n margin: 0;\n padding: 0 0 var(--space-3);\n font-size: var(--text-xs-size);\n line-height: var(--text-xs-line-relaxed);\n color: var(--text-tertiary);\n}\n\n/* ── Compact container (a 375 window, or a narrow pane) ──────────────── */\n@container (max-width: 480px) {\n .row {\n grid-template-columns: auto minmax(0, 1fr);\n }\n .rowAside {\n grid-column: 2;\n justify-content: flex-start;\n max-width: none;\n }\n .disabledNote {\n text-align: left;\n }\n}\n\n@media (prefers-reduced-motion: reduce) {\n .pill {\n transition: none;\n }\n}\n","/**\n * routes/verse/apps/MonogramTile.tsx — the square tile every seat and app row\n * leads with. 3.11.1: engine-backed tiles show the provider's own mark\n * (Anthropic Claude, OpenAI, xAI Grok, Ollama — ProviderLogo) so an account is\n * recognisable at a glance; the mark only identifies the provider, the row's\n * text still names the account. Neutral tiles (Aider, Goose, …) keep their\n * letters.\n *\n * Engine-backed tiles take a 12% tint of the engine hue; marks draw in ink\n * (currentColor, Claude in its brand colour) so contrast never depends on the\n * hue. Decorative: the row's name carries the meaning.\n */\nimport type { CSSProperties } from 'react';\nimport type { VerseEngine } from '../../../data/api-types.js';\nimport { engineColor } from '../../../components/primitives/Tag.js';\nimport { ProviderLogo } from '../../../components/primitives/ProviderLogo.js';\nimport styles from './Apps.module.css';\n\nexport function MonogramTile({\n monogram,\n engine,\n size = 'md',\n}: {\n monogram: string;\n engine: VerseEngine | null;\n /** md = 32px (Apps rows), sm = 24px (capacity rows). */\n size?: 'sm' | 'md';\n}) {\n const style = engine === null ? undefined : ({ '--tile-hue': engineColor(engine) } as CSSProperties);\n return (\n <span\n className={styles.tile}\n data-size={size}\n data-engine={engine ?? undefined}\n style={style}\n aria-hidden=\"true\"\n >\n {engine === null ? monogram.slice(0, 2) : <ProviderLogo engine={engine} size={size === 'sm' ? 14 : 18} />}\n </span>\n );\n}\n","/*\n * The shared capacity strip. Tokens only (DESIGN.md §13): no raw colour, no\n * px font size. It adapts to ITS container, not the window — the same strip\n * sits in an 880px Apps column and a 300px Resources panel — so the narrow\n * layout is a container query at the compact breakpoint (480, viewport.ts).\n */\n.strip {\n container-type: inline-size;\n display: flex;\n flex-direction: column;\n gap: var(--space-3);\n min-width: 0;\n}\n\n.visuallyHidden {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n clip: rect(0 0 0 0);\n white-space: nowrap;\n border: 0;\n}\n\n.headline {\n margin: 0;\n font-size: var(--text-sm-size);\n line-height: var(--text-sm-line);\n font-weight: var(--font-weight-medium);\n color: var(--text-primary);\n}\n\n.empty {\n margin: 0;\n font-size: var(--text-sm-size);\n line-height: var(--text-sm-line);\n color: var(--text-secondary);\n}\n\n.rows {\n list-style: none;\n margin: 0;\n padding: 0;\n display: flex;\n flex-direction: column;\n}\n\n.row {\n display: grid;\n grid-template-columns: auto minmax(0, 1fr) auto;\n align-items: start;\n gap: var(--space-3);\n padding: var(--space-3) 0;\n border-top: 1px solid var(--border-subtle);\n}\n.row:first-child {\n border-top: 0;\n}\n.row[data-compact] {\n padding: var(--space-2) 0;\n gap: var(--space-2);\n align-items: center;\n}\n\n.main {\n display: flex;\n flex-direction: column;\n gap: var(--space-1);\n min-width: 0;\n}\n\n.head {\n display: flex;\n flex-wrap: wrap;\n align-items: baseline;\n gap: var(--space-1) var(--space-3);\n min-width: 0;\n}\n\n.nameWrap,\n.nameButton {\n display: inline-flex;\n align-items: baseline;\n gap: var(--space-2);\n min-width: 0;\n}\n.nameButton {\n padding: 0;\n border: 0;\n background: none;\n font: inherit;\n color: inherit;\n cursor: pointer;\n border-radius: var(--radius-xs);\n}\n.nameButton:hover .name {\n text-decoration: underline;\n text-underline-offset: 2px;\n}\n.nameButton:focus-visible {\n outline: none;\n box-shadow: var(--shadow-focus-ring);\n}\n.nameButton[aria-pressed='true'] .name {\n color: var(--text-link);\n}\n\n/* The seat name is often a control (Usage's toggle): it wraps, never cut mid-word. */\n.name {\n font-size: var(--text-sm-size);\n line-height: var(--text-sm-line);\n font-weight: var(--font-weight-semibold);\n color: var(--text-primary);\n min-width: 0;\n overflow-wrap: anywhere;\n text-align: left;\n}\n\n.plan {\n font-size: var(--text-2xs-size);\n line-height: var(--text-2xs-line);\n text-transform: uppercase;\n letter-spacing: var(--tracking-label);\n font-family: var(--font-display);\n color: var(--text-tertiary);\n}\n\n/* A state is a WORD; the dot only reinforces it. */\n.word {\n display: inline-flex;\n align-items: center;\n gap: var(--space-1);\n font-size: var(--text-xs-size);\n line-height: var(--text-xs-line);\n color: var(--text-secondary);\n white-space: nowrap;\n}\n.dot {\n width: 7px;\n height: 7px;\n border-radius: var(--radius-full);\n background: var(--status-neutral-solid);\n flex: none;\n}\n.word[data-tone='success'] .dot { background: var(--status-success-solid); }\n.word[data-tone='warning'] { color: var(--status-warning-fg); }\n.word[data-tone='warning'] .dot { background: var(--status-warning-solid); }\n.word[data-tone='danger'] { color: var(--status-danger-fg); }\n.word[data-tone='danger'] .dot { background: var(--status-danger-solid); }\n.word[data-tone='neutral'] { font-style: italic; }\n.word[data-tone='neutral'] .dot {\n background: transparent;\n border: 1px solid var(--status-unknown-solid);\n}\n\n/*\n * Accounts mode: the row's status reads as a short sentence — a label in the\n * tone's colour, then the detail in secondary text. The detail may wrap (a\n * provider's reset prose can be long); the label never truncates.\n */\n.status {\n display: inline-flex;\n align-items: baseline;\n flex-wrap: wrap;\n gap: 0 var(--space-1);\n min-width: 0;\n font-size: var(--text-xs-size);\n line-height: var(--text-xs-line);\n color: var(--text-secondary);\n}\n.status .dot {\n align-self: center;\n}\n.statusLabel {\n font-weight: var(--font-weight-medium);\n color: var(--text-primary);\n white-space: nowrap;\n}\n.status[data-tone='success'] .dot { background: var(--status-success-solid); }\n.status[data-tone='success'] .statusLabel { color: var(--status-success-fg); }\n.status[data-tone='warning'] .dot { background: var(--status-warning-solid); }\n.status[data-tone='warning'] .statusLabel { color: var(--status-warning-fg); }\n.status[data-tone='danger'] .dot { background: var(--status-danger-solid); }\n.status[data-tone='danger'] .statusLabel { color: var(--status-danger-fg); }\n.status[data-tone='neutral'] .dot {\n background: transparent;\n border: 1px solid var(--status-unknown-solid);\n}\n.status[data-tone='neutral'] .statusLabel {\n color: var(--text-secondary);\n font-style: italic;\n}\n.statusDetail {\n overflow-wrap: anywhere;\n}\n\n.stamp {\n margin: 0;\n font-size: var(--text-xs-size);\n line-height: var(--text-xs-line);\n color: var(--text-tertiary);\n font-variant-numeric: tabular-nums;\n}\n.usableAgain {\n color: var(--text-secondary);\n font-weight: var(--font-weight-medium);\n}\n\n.summary,\n.meta {\n margin: 0;\n font-size: var(--text-xs-size);\n line-height: var(--text-xs-line-relaxed);\n color: var(--text-secondary);\n overflow-wrap: anywhere;\n}\n.meta {\n color: var(--text-tertiary);\n}\n.autonomy {\n color: var(--text-secondary);\n font-weight: var(--font-weight-medium);\n}\n.autonomy[data-status='eligible'] { color: var(--status-success-fg); }\n.autonomy[data-status='unknown'] {\n font-style: italic;\n color: var(--status-unknown-fg);\n}\n\n.bars {\n display: flex;\n flex-direction: column;\n gap: var(--space-1);\n margin-top: var(--space-1);\n}\n\n.bar {\n display: grid;\n grid-template-columns: minmax(4.5rem, 7.5rem) minmax(5rem, 1fr) minmax(2.75rem, auto) minmax(0, 12rem);\n align-items: center;\n gap: var(--space-2);\n font-size: var(--text-xs-size);\n line-height: var(--text-xs-line);\n}\n.bar[data-compact] {\n grid-template-columns: minmax(3.5rem, 5.5rem) minmax(3rem, 1fr) auto;\n}\n\n.barLabel {\n color: var(--text-tertiary);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n.bar[data-binding] .barLabel {\n color: var(--text-secondary);\n}\n\n/* used (solid) · room (track) · kept for you (hatched, past the tick). */\n.track {\n position: relative;\n display: block;\n height: 6px;\n border-radius: var(--radius-full);\n background: var(--meter-track);\n overflow: hidden;\n}\n.trackUnknown {\n display: block;\n height: 6px;\n border-radius: var(--radius-full);\n border: 1px dashed var(--border-strong);\n}\n.used {\n position: absolute;\n left: 0;\n top: 0;\n bottom: 0;\n border-radius: var(--radius-full);\n background: var(--data-seq-5);\n transition: width var(--duration-base) var(--ease-standard);\n}\n.used[data-level='tight'] { background: var(--status-warning-solid); }\n.used[data-level='limit'] { background: var(--status-danger-solid); }\n.reserve {\n position: absolute;\n top: 0;\n bottom: 0;\n background: repeating-linear-gradient(\n 135deg,\n color-mix(in srgb, var(--text-tertiary) 34%, transparent) 0 2px,\n transparent 2px 5px\n );\n}\n.ceiling {\n position: absolute;\n top: 0;\n bottom: 0;\n width: 2px;\n margin-left: -1px;\n background: var(--text-secondary);\n}\n\n.value {\n font-variant-numeric: tabular-nums;\n color: var(--text-primary);\n white-space: nowrap;\n text-align: right;\n}\n.value[data-level='tight'] { color: var(--status-warning-fg); }\n.value[data-level='limit'] { color: var(--status-danger-fg); }\n.value[data-level='unknown'] {\n font-style: italic;\n color: var(--status-unknown-fg);\n}\n\n.reset {\n color: var(--text-tertiary);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.actions {\n display: flex;\n flex-wrap: wrap;\n justify-content: flex-end;\n gap: var(--space-1);\n}\n\n/* Narrow container (a side panel, or a 375 window): actions and resets wrap. */\n@container (max-width: 480px) {\n .row {\n grid-template-columns: auto minmax(0, 1fr);\n }\n .actions {\n grid-column: 2;\n justify-content: flex-start;\n }\n .bar {\n grid-template-columns: minmax(0, 1fr) auto;\n row-gap: var(--space-1);\n }\n .bar .track,\n .bar .trackUnknown {\n grid-column: 1 / -1;\n grid-row: 2;\n }\n .reset {\n grid-column: 1 / -1;\n grid-row: 3;\n white-space: normal;\n }\n .bar[data-compact] {\n grid-template-columns: minmax(3rem, auto) minmax(3rem, 1fr) auto;\n }\n .bar[data-compact] .track,\n .bar[data-compact] .trackUnknown {\n grid-column: auto;\n grid-row: auto;\n }\n}\n\n@media (prefers-reduced-motion: reduce) {\n .used {\n transition: none;\n }\n}\n","/**\n * routes/verse/usage/CapacityStrip.tsx — THE capacity view (SPEC-310C §4:\n * \"Resources, NewChatDialog and onboarding drop their own capacity views and\n * import usage/CapacityStrip instead\"). Apps & Accounts and Usage render it\n * too, so every surface answers \"how much of each seat is left\" the same way.\n *\n * [C] Claude Max · max ● connected [actions]\n * usable · 62% of 5-hour window used\n * 5-hour window ▇▇▇▇▇▇▇░░░░│▨▨▨ 62% resets 7pm\n * weekly window ▇▇▇░░░░░░░░│▨▨▨ 40% resets Thu\n * Reserved for you 40% · Autonomy: Eligible\n *\n * Each bar reads left to right: used (solid), what autonomy may still use\n * (track), and the band KEPT FOR YOU (hatched) past a tick at 100 − reserve —\n * so \"Reserved for you 40%\" is something you can see, not just read. The\n * reserve applies to the binding window; the other windows carry no tick.\n *\n * Honesty (docs/VERSE-TELEMETRY-V2.md), enforced by the model and kept here:\n * - no reading → a dashed track and the words \"no reading\", never a 0% bar;\n * - a flagged limit → \"limit reached\", never \"100%\";\n * - reset prose is printed verbatim, never turned into a countdown;\n * - every state is a WORD first; colour only reinforces it.\n *\n * Three entry points:\n * <CapacityStrip seats health? budget? …/> pure: props in, markup out;\n * <LiveCapacityStrip …/> reads the shared caches itself\n * (bootstrap seats, /health,\n * /budget) — drop-in for C1/C2;\n * useCapacityRows() the rows, for a custom layout\n * (the rail ring, the seat chip).\n */\nimport { useId, useMemo, useState, type CSSProperties, type ReactNode } from 'react';\nimport type { BudgetView } from '../../../../core/routing/policy.js';\nimport type { SeatHealthReport } from '../../../../core/verse/health-types.js';\nimport type { VerseBootstrap, VerseSeat } from '../../../data/api-types.js';\nimport { useQuery, useRefetch } from '../../../data/hooks.js';\nimport { MonogramTile } from '../apps/MonogramTile.js';\nimport { budgetQuery } from '../budget/budget-queries.js';\nimport { useSeatHealth } from '../health/useSeatHealth.js';\nimport { usePollWhileVisible, useSectionVisible } from '../shell/section-visibility.js';\nimport { useSeatsRefresh } from '../useSeatsRefresh.js';\nimport { verseBootstrapQuery } from '../verse-queries.js';\nimport {\n accountStatus,\n buildCapacityRows,\n capacityHeadline,\n capacityTone,\n orderAccountRows,\n percentText,\n windowSentence,\n type AccountStatus,\n type CapacityInputs,\n type CapacityRow,\n type CapacityWindowRow,\n} from './capacity-strip-model.js';\nimport styles from './CapacityStrip.module.css';\n\n/** Above this share of a window the bar turns amber (the word \"tight\" rides with it). */\nconst TIGHT_AT = 90;\n\n/** How often an accounts strip re-reads the clock (\"usable again in 7h\", \"checked 2m ago\"). */\nexport const ACCOUNT_CLOCK_MS = 30_000;\n\n/**\n * Apps & Accounts mode: every row leads with a sentence-case status\n * (\"Connected · usable now\", \"Spent · resets Fri 11:46 PM\", \"Signed out ·\n * reconnect to use it\", \"Checking…\"), says when it was last checked and — for\n * a spent seat — when it is usable again, and usable rows come first.\n */\nexport interface CapacityAccountsMode {\n /** False until the health sweep has answered once. */\n healthRead: boolean;\n /** The seat whose check is running now (its row reads \"Checking…\"). */\n checkingSeatId?: string | null;\n /** Injected clock for tests; otherwise the strip ticks every ACCOUNT_CLOCK_MS while visible. */\n now?: number;\n}\n\nexport interface CapacityStripProps {\n seats: readonly VerseSeat[];\n health?: readonly SeatHealthReport[] | null;\n budget?: BudgetView | null;\n local?: CapacityInputs['local'];\n seatIds?: readonly string[];\n /** full: every window with resets and the reserve; compact: one line per seat (pickers, side panels). */\n density?: 'full' | 'compact';\n /** Show the one-sentence summary above the rows. Default true for full, false for compact. */\n headline?: boolean;\n /** Heading for assistive tech (visually hidden). */\n title?: string;\n /**\n * The id of a heading that already names this strip (Apps' \"Accounts\"\n * group). The strip then labels itself by it instead of adding a second,\n * hidden heading — two regions with one name is noise to a screen reader.\n */\n labelledBy?: string;\n /** Per-seat trailing controls (Apps passes Reconnect / Fix / Edit budget). */\n renderActions?: (row: CapacityRow) => ReactNode;\n /** Makes each seat name a toggle (Usage opens the account's detail). */\n onSelectSeat?: (seatId: string) => void;\n selectedSeatId?: string | null;\n /** Shown instead of rows when the roster is empty. */\n emptyText?: string;\n /** Apps & Accounts: a status per row, when it was checked, usable rows first. */\n accounts?: CapacityAccountsMode;\n}\n\nfunction pct(n: number): number {\n return Math.max(0, Math.min(100, Math.round(n)));\n}\n\nfunction WindowBar({\n row,\n w,\n reservePercent,\n compact,\n}: {\n row: CapacityRow;\n w: CapacityWindowRow;\n reservePercent: number | null;\n compact: boolean;\n}) {\n const sentence = windowSentence(row, w, w.binding ? reservePercent : null);\n const ceiling = w.binding && reservePercent !== null && reservePercent > 0 ? 100 - pct(reservePercent) : null;\n let track: ReactNode;\n let value: ReactNode;\n if (w.limitReached) {\n track = (\n <span className={styles.track} role=\"img\" aria-label={sentence}>\n <span className={styles.used} data-level=\"limit\" style={{ width: '100%' }} />\n </span>\n );\n value = <span className={styles.value} data-level=\"limit\">limit reached</span>;\n } else if (w.usedPercent === null) {\n // Absence drawn as absence. Never a 0% bar.\n track = <span className={styles.trackUnknown} role=\"img\" aria-label={sentence} />;\n value = <span className={styles.value} data-level=\"unknown\">no reading</span>;\n } else {\n const used = pct(w.usedPercent);\n const level = used >= TIGHT_AT ? 'tight' : 'ok';\n track = (\n <span className={styles.track} role=\"img\" aria-label={sentence}>\n {ceiling !== null ? (\n <span className={styles.reserve} style={{ left: `${ceiling}%`, width: `${100 - ceiling}%` } as CSSProperties} />\n ) : null}\n <span className={styles.used} data-level={level} style={{ width: `${used}%` }} />\n {ceiling !== null ? <span className={styles.ceiling} style={{ left: `${ceiling}%` }} /> : null}\n </span>\n );\n value = <span className={styles.value} data-level={level}>{percentText(w.usedPercent)}</span>;\n }\n return (\n <div className={styles.bar} data-binding={w.binding || undefined} data-compact={compact || undefined}>\n <span className={styles.barLabel} title={w.label}>{w.label.replace(/ window$/, '')}</span>\n {track}\n {value}\n {!compact && w.resetText !== null ? <span className={styles.reset} title={w.resetText}>{w.resetText}</span> : null}\n </div>\n );\n}\n\nfunction SeatName({ row, onSelect, selected }: { row: CapacityRow; onSelect: ((id: string) => void) | undefined; selected: boolean }) {\n const text = (\n <>\n <span className={styles.name}>{row.label}</span>\n {row.plan !== null ? <span className={styles.plan}>{row.plan}</span> : null}\n </>\n );\n // A control only when there is something for it to open.\n if (!onSelect) return <span className={styles.nameWrap}>{text}</span>;\n return (\n <button type=\"button\" className={styles.nameButton} aria-pressed={selected} onClick={() => onSelect(row.seatId)}>\n {text}\n </button>\n );\n}\n\nfunction StatusLine({ status }: { status: AccountStatus }) {\n return (\n <span className={styles.status} data-tone={status.tone} data-status={status.kind}>\n <span className={styles.dot} aria-hidden=\"true\" />\n <span className={styles.statusLabel}>{status.label}</span>\n {status.detail !== null ? <span className={styles.statusDetail}>{`· ${status.detail}`}</span> : null}\n </span>\n );\n}\n\n/** \"usable again in 7h 12m · checked 2m ago\" — the row's clock facts, when it has any. */\nfunction StampLine({ status }: { status: AccountStatus }) {\n if (status.usableAgain === null && status.checked === null) return null;\n return (\n <p className={styles.stamp}>\n {status.usableAgain !== null ? <span className={styles.usableAgain}>{status.usableAgain}</span> : null}\n {status.usableAgain !== null && status.checked !== null ? ' · ' : null}\n {status.checked !== null ? <span title={status.checkedTitle ?? undefined}>{status.checked}</span> : null}\n </p>\n );\n}\n\nfunction CapacityRowView({\n row,\n compact,\n renderActions,\n onSelectSeat,\n selected,\n status,\n}: {\n row: CapacityRow;\n compact: boolean;\n renderActions: CapacityStripProps['renderActions'];\n onSelectSeat: CapacityStripProps['onSelectSeat'];\n selected: boolean;\n status: AccountStatus | null;\n}) {\n const tone = capacityTone(row.cls);\n const binding = row.windows.find((w) => w.binding) ?? null;\n const windows = compact ? (binding ? [binding] : []) : row.windows;\n const actions = renderActions ? renderActions(row) : null;\n const reserve = row.reserve;\n return (\n <li className={styles.row} data-capacity={row.cls} data-compact={compact || undefined} data-status={status?.kind}>\n <MonogramTile monogram={row.monogram} engine={row.engine} size=\"sm\" />\n <div className={styles.main}>\n <div className={styles.head}>\n <SeatName row={row} onSelect={onSelectSeat} selected={selected} />\n {status !== null ? (\n <StatusLine status={status} />\n ) : (\n <span className={styles.word} data-tone={tone}>\n <span className={styles.dot} aria-hidden=\"true\" />\n {row.word}\n </span>\n )}\n {row.connection !== null && row.connection.connection !== 'connected' && row.connection.connection !== 'unknown'\n && !(status?.coversConnection ?? false) && !(status?.kind === 'signed-out') ? (\n <span className={styles.word} data-tone={row.connection.tone}>\n <span className={styles.dot} aria-hidden=\"true\" />\n {row.connection.word}\n </span>\n ) : null}\n </div>\n {!compact || windows.length === 0 ? <p className={styles.summary}>{row.summary}</p> : null}\n {status !== null && !compact ? <StampLine status={status} /> : null}\n {windows.length > 0 ? (\n <div className={styles.bars}>\n {windows.map((w) => (\n <WindowBar key={w.id} row={row} w={w} reservePercent={reserve?.percent ?? null} compact={compact} />\n ))}\n </div>\n ) : null}\n {!compact && (reserve !== null || row.credits !== null) ? (\n <p className={styles.meta}>\n {reserve !== null ? (\n <span title={reserve.why}>\n {reserve.label}\n {/* \"Autonomy off — all yours\" already says it; no second \"Off\". */}\n {reserve.autonomy === 'off' ? null : (\n <> · Autonomy: <span className={styles.autonomy} data-status={reserve.autonomy}>{reserve.autonomyWord}</span></>\n )}\n </span>\n ) : null}\n {reserve !== null && row.credits !== null ? ' · ' : null}\n {row.credits !== null ? <span>{row.credits}</span> : null}\n </p>\n ) : null}\n </div>\n {actions ? <div className={styles.actions}>{actions}</div> : null}\n </li>\n );\n}\n\nexport function CapacityStrip({\n seats,\n health,\n budget,\n local,\n seatIds,\n density = 'full',\n headline,\n title = 'Seat capacity',\n labelledBy,\n renderActions,\n onSelectSeat,\n selectedSeatId = null,\n emptyText = 'No seats yet. Connect an account or start Ollama.',\n accounts,\n}: CapacityStripProps) {\n const headingId = useId();\n const [tick, setTick] = useState(() => Date.now());\n usePollWhileVisible(() => setTick(Date.now()), ACCOUNT_CLOCK_MS, { enabled: accounts !== undefined && accounts.now === undefined });\n const now = accounts?.now ?? tick;\n const healthRead = accounts?.healthRead ?? false;\n const accountsMode = accounts !== undefined;\n // Accounts mode words every window reset and reason against the SAME clock\n // as its status line (\"Spent · resets Sat 11:46 PM\"), so the two never\n // disagree about which day \"today\" is.\n const rowsNow = accountsMode ? now : undefined;\n const built = useMemo(\n () => buildCapacityRows(seats, {\n health: health ?? null,\n budget: budget ?? null,\n ...(local ? { local } : {}),\n ...(seatIds ? { seatIds } : {}),\n ...(rowsNow !== undefined ? { now: rowsNow } : {}),\n }),\n [seats, health, budget, local, seatIds, rowsNow],\n );\n const rows = useMemo(\n () => (accountsMode ? orderAccountRows(built, { healthRead, now }) : built),\n [built, accountsMode, healthRead, now],\n );\n const compact = density === 'compact';\n const showHeadline = headline ?? !compact;\n // Named by the caller's heading: a plain block inside the caller's region,\n // not a second region with the same name.\n const Wrapper = labelledBy ? 'div' : 'section';\n return (\n <Wrapper className={styles.strip} aria-labelledby={labelledBy ? undefined : headingId} data-density={density}>\n {labelledBy ? null : <h3 id={headingId} className={styles.visuallyHidden}>{title}</h3>}\n {showHeadline && rows.length > 0 ? <p className={styles.headline}>{capacityHeadline(rows)}</p> : null}\n {rows.length === 0 ? (\n <p className={styles.empty}>{emptyText}</p>\n ) : (\n <ul className={styles.rows} aria-label={labelledBy ? undefined : title} aria-labelledby={labelledBy}>\n {rows.map((row) => (\n <CapacityRowView\n key={row.seatId}\n row={row}\n compact={compact}\n renderActions={renderActions}\n onSelectSeat={onSelectSeat}\n selected={selectedSeatId === row.seatId}\n status={accounts\n ? accountStatus(row, { healthRead, now, checking: accounts.checkingSeatId === row.seatId })\n : null}\n />\n ))}\n </ul>\n )}\n </Wrapper>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Live data\n// ---------------------------------------------------------------------------\n\n/** Budget moves with the collector (30 s); a minute is plenty for a strip. */\nexport const CAPACITY_BUDGET_POLL_MS = 60_000;\n\nexport interface CapacityData {\n seats: readonly VerseSeat[];\n health: readonly SeatHealthReport[] | null;\n budget: BudgetView | null;\n /** True until the seat roster has been read once. */\n loading: boolean;\n}\n\n/**\n * The three shared reads behind the strip, kept live while the surface is on\n * screen: seats (the /seats poll merged into bootstrap), A2's health (30 s)\n * and A9's budget (60 s). Each is the app-wide cache entry — mounting this\n * twice costs no extra request.\n */\nexport function useCapacityData(opts: { withBudget?: boolean; withHealth?: boolean } = {}): CapacityData {\n const visible = useSectionVisible();\n const withBudget = opts.withBudget ?? true;\n const withHealth = opts.withHealth ?? true;\n const bootstrap = useQuery(verseBootstrapQuery);\n useSeatsRefresh(visible);\n const health = useSeatHealth(visible && withHealth);\n const budget = useQuery(budgetQuery);\n const refetchBudget = useRefetch(budgetQuery);\n usePollWhileVisible(refetchBudget, CAPACITY_BUDGET_POLL_MS, { enabled: withBudget });\n const data = bootstrap.data as VerseBootstrap | undefined;\n return {\n seats: data?.seats ?? [],\n health: withHealth ? (health.data?.seats ?? null) : null,\n budget: withBudget ? (budget.data ?? null) : null,\n loading: data === undefined && (bootstrap.status === 'loading' || bootstrap.status === 'idle'),\n };\n}\n\n/** The rows for a custom layout (the rail's capacity ring, the composer's seat chip). */\nexport function useCapacityRows(inputs: Omit<CapacityInputs, 'health' | 'budget'> = {}): CapacityRow[] {\n const data = useCapacityData();\n return useMemo(\n () => buildCapacityRows(data.seats, { health: data.health, budget: data.budget, ...inputs }),\n // eslint-disable-next-line react-hooks/exhaustive-deps -- inputs is a small literal; its fields are the identity.\n [data.seats, data.health, data.budget, inputs.local, inputs.seatIds],\n );\n}\n\nexport interface LiveCapacityStripProps extends Omit<CapacityStripProps, 'seats' | 'health' | 'budget'> {\n /**\n * The roster, when the caller already holds it (the new-chat dialog, whose\n * seat list IS this roster and whose pre-fill works from its own props).\n * The strip then adds only health and budget, and never shows \"Reading\n * seats…\" over a roster that is already on screen.\n */\n seats?: readonly VerseSeat[];\n}\n\n/** Drop-in strip that reads its own data — what NewChatDialog and onboarding mount. */\nexport function LiveCapacityStrip({ seats: given, ...props }: LiveCapacityStripProps) {\n const data = useCapacityData();\n if (given === undefined && data.loading) {\n return <p className={styles.empty} aria-busy=\"true\">Reading seats…</p>;\n }\n return <CapacityStrip {...props} seats={given ?? data.seats} health={data.health} budget={data.budget} />;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"CapacityStrip-qKDBC65C.js","names":[],"sources":["../../../../../../src/web-ui/routes/verse/apps/Apps.module.css","../../../../../../src/web-ui/routes/verse/apps/MonogramTile.tsx","../../../../../../src/web-ui/routes/verse/usage/CapacityStrip.module.css","../../../../../../src/web-ui/routes/verse/usage/CapacityStrip.tsx"],"sourcesContent":["/*\n * Apps & Accounts (SPEC-310C §4) — grouped rows in the Ollama style, max\n * 880px. Tokens only (DESIGN.md §13; style-scan-310 enforces it): no raw\n * colour, no px font size. The row adapts to its container: at the compact\n * width (480, viewport.ts) the right-hand pill wraps under the description.\n */\n\n.section {\n display: flex;\n flex-direction: column;\n min-height: 0;\n height: 100%;\n background: var(--bg-canvas);\n}\n\n.scroll {\n flex: 1;\n min-height: 0;\n overflow-y: auto;\n padding: var(--space-6) var(--space-4) var(--space-12);\n /* Desktop shell (desktop/README.md \"Desktop shell contract\"): this page has\n no 48px strip, so its title sits inside the OS title-bar band. Once the\n window is narrow enough that the 880px column stops centring (minWidth\n is 900), the column's left edge lands at rail + 16px — under the macOS\n traffic lights, which cover the top-left 92px of the WINDOW. Owe the same\n overlap every header strip owes (inset − rail, 36px on a 56px rail);\n the vars are absent in a browser and the expanded rail sits under the\n lights itself, so both floor to --space-4 and nothing moves there. The\n whole column shifts, not just the header, so the title stays aligned\n with the rows under it. */\n padding-left: max(var(--space-4), calc(var(--app-traffic-light-inset, 0px) - var(--rail-width, 56px)));\n}\n\n.page {\n container-type: inline-size;\n max-width: 880px;\n margin: 0 auto;\n display: flex;\n flex-direction: column;\n gap: var(--space-8);\n}\n\n.header {\n display: flex;\n flex-wrap: wrap;\n align-items: flex-end;\n justify-content: space-between;\n gap: var(--space-3) var(--space-4);\n}\n.headerText {\n display: flex;\n flex-direction: column;\n gap: var(--space-1);\n min-width: 0;\n}\n.title {\n margin: 0;\n font-family: var(--font-display);\n font-size: var(--text-xl-size);\n line-height: var(--text-xl-line);\n letter-spacing: var(--tracking-display);\n font-weight: var(--font-weight-semibold);\n color: var(--text-primary);\n}\n.lede {\n margin: 0;\n font-size: var(--text-sm-size);\n line-height: var(--text-sm-line);\n color: var(--text-secondary);\n}\n.headerMeta {\n display: flex;\n align-items: center;\n gap: var(--space-2);\n font-size: var(--text-xs-size);\n line-height: var(--text-xs-line);\n color: var(--text-tertiary);\n}\n\n.banner {\n margin: 0;\n padding: var(--space-3) var(--space-4);\n border: 1px solid var(--border-subtle);\n border-radius: var(--radius-md);\n background: var(--bg-surface);\n font-size: var(--text-sm-size);\n line-height: var(--text-sm-line);\n color: var(--text-secondary);\n}\n.banner[data-tone='danger'] {\n border-color: color-mix(in srgb, var(--status-danger-solid) 40%, var(--border-subtle));\n color: var(--status-danger-fg);\n}\n\n/* The Accounts group's own \"Checked … again\" line, under the strip. */\n.accountsNote {\n margin: 0;\n font-size: var(--text-xs-size);\n line-height: var(--text-xs-line);\n color: var(--text-secondary);\n}\n.accountsNote[data-tone='danger'] {\n color: var(--status-danger-fg);\n}\n\n/* ── Groups ─────────────────────────────────────────────────────────── */\n\n.group {\n display: flex;\n flex-direction: column;\n gap: var(--space-2);\n scroll-margin-top: var(--space-6);\n}\n.groupHead {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--space-3);\n min-height: var(--control-h-sm);\n}\n.groupTitle {\n margin: 0;\n font-family: var(--font-display);\n font-size: var(--text-2xs-size);\n line-height: var(--text-2xs-line);\n text-transform: uppercase;\n letter-spacing: var(--tracking-label);\n font-weight: var(--font-weight-semibold);\n color: var(--text-tertiary);\n}\n.groupTitle:focus {\n outline: none;\n}\n.groupTitle:focus-visible {\n box-shadow: var(--shadow-focus-ring);\n border-radius: var(--radius-xs);\n}\n.caveat {\n margin: 0;\n font-size: var(--text-xs-size);\n line-height: var(--text-xs-line-relaxed);\n color: var(--text-secondary);\n}\n.caveat code,\n.inlineCode {\n font-family: var(--font-mono);\n font-size: var(--text-xs-size);\n background: var(--bg-code);\n padding: 0 var(--space-1);\n border-radius: var(--radius-xs);\n overflow-wrap: anywhere;\n}\n\n.card {\n border: 1px solid var(--border-subtle);\n border-radius: var(--radius-lg);\n background: var(--bg-surface);\n padding: 0 var(--card-pad);\n box-shadow: inset 0 1px 0 var(--hairline-lift);\n}\n\n.rows {\n list-style: none;\n margin: 0;\n padding: 0;\n}\n\n.row {\n display: grid;\n grid-template-columns: auto minmax(0, 1fr) auto;\n align-items: start;\n gap: var(--space-3);\n padding: var(--space-3) 0;\n border-top: 1px solid var(--border-subtle);\n}\n.row:first-child {\n border-top: 0;\n}\n\n.rowMain {\n display: flex;\n flex-direction: column;\n gap: var(--space-1);\n min-width: 0;\n padding-top: var(--space-1);\n}\n.rowHead {\n display: flex;\n flex-wrap: wrap;\n align-items: baseline;\n gap: var(--space-1) var(--space-3);\n min-width: 0;\n}\n.rowName {\n font-size: var(--text-sm-size);\n line-height: var(--text-sm-line);\n font-weight: var(--font-weight-semibold);\n color: var(--text-primary);\n}\n.rowVersion {\n font-family: var(--font-mono);\n font-size: var(--text-xs-size);\n color: var(--text-tertiary);\n}\n.rowDesc,\n.rowDetail {\n margin: 0;\n font-size: var(--text-xs-size);\n line-height: var(--text-xs-line-relaxed);\n color: var(--text-secondary);\n overflow-wrap: anywhere;\n}\n.rowDetail {\n color: var(--text-tertiary);\n}\n\n.rowAside {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n justify-content: flex-end;\n gap: var(--space-2);\n padding-top: var(--space-1);\n max-width: 26rem;\n}\n\n/* A health state is a WORD; the dot reinforces it (DESIGN §13.2). */\n.health {\n display: inline-flex;\n align-items: center;\n gap: var(--space-1);\n font-size: var(--text-xs-size);\n line-height: var(--text-xs-line);\n color: var(--text-secondary);\n white-space: nowrap;\n}\n.healthDot {\n width: 7px;\n height: 7px;\n border-radius: var(--radius-full);\n background: var(--status-neutral-solid);\n flex: none;\n}\n.health[data-tone='success'] .healthDot { background: var(--status-success-solid); }\n.health[data-tone='warning'] { color: var(--status-warning-fg); }\n.health[data-tone='warning'] .healthDot { background: var(--status-warning-solid); }\n.health[data-tone='danger'] { color: var(--status-danger-fg); }\n.health[data-tone='danger'] .healthDot { background: var(--status-danger-solid); }\n.health[data-tone='off'] { color: var(--text-tertiary); }\n.health[data-tone='off'] .healthDot {\n background: transparent;\n border: 1px solid var(--border-strong);\n}\n.health[data-tone='neutral'] {\n font-style: italic;\n color: var(--status-unknown-fg);\n}\n.health[data-tone='neutral'] .healthDot {\n background: transparent;\n border: 1px dashed var(--status-unknown-solid);\n}\n\n.loadingLine {\n margin: 0;\n padding: var(--space-3) 0;\n font-size: var(--text-sm-size);\n line-height: var(--text-sm-line);\n color: var(--text-secondary);\n}\n\n/* ── Monogram tile (32px rows, 24px capacity rows) ───────────────────── */\n\n.tile {\n --tile-hue: var(--text-tertiary);\n display: inline-flex;\n align-items: center;\n justify-content: center;\n flex: none;\n width: 32px;\n height: 32px;\n border-radius: var(--radius-md);\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 background: var(--bg-surface-raised);\n border: 1px solid var(--border-subtle);\n position: relative;\n overflow: hidden;\n}\n.tile[data-engine] {\n background: color-mix(in srgb, var(--tile-hue) 12%, var(--bg-surface));\n border-color: color-mix(in srgb, var(--tile-hue) 28%, var(--border-subtle));\n}\n/* The 2px identity tick. */\n.tile[data-engine]::before {\n content: '';\n position: absolute;\n left: 0;\n top: 0;\n bottom: 0;\n width: 2px;\n background: var(--tile-hue);\n}\n.tile[data-size='sm'] {\n width: 24px;\n height: 24px;\n border-radius: var(--radius-sm);\n font-size: var(--text-xs-size);\n}\n\n/* ── Copy pill ───────────────────────────────────────────────────────── */\n\n.pillWrap {\n display: inline-flex;\n min-width: 0;\n max-width: 100%;\n}\n/*\n * A long command WRAPS rather than ellipsizing: the operator reads what they\n * are about to paste, and a command cut mid-word (\"node ~/.ashlr/nat…\") is\n * exactly the part they need. One line keeps the pill shape (the radius is\n * half the control height); two lines become a soft capsule.\n */\n.pill {\n display: inline-flex;\n align-items: center;\n gap: var(--space-2);\n min-width: 0;\n max-width: 100%;\n min-height: var(--control-h-sm);\n padding: 2px var(--space-2) 2px var(--space-3);\n border: 1px solid var(--border-subtle);\n border-radius: calc(var(--control-h-sm) / 2);\n text-align: left;\n background: var(--bg-code);\n color: var(--text-primary);\n cursor: pointer;\n transition: border-color var(--duration-fast) var(--ease-standard);\n}\n.pill:hover {\n border-color: var(--border-strong);\n}\n.pill:focus-visible {\n outline: none;\n box-shadow: var(--shadow-focus-ring);\n}\n.pillText {\n font-family: var(--font-mono);\n font-size: var(--text-xs-size);\n line-height: var(--text-xs-line);\n white-space: normal;\n overflow-wrap: anywhere;\n min-width: 0;\n}\n.pillIcon {\n display: inline-flex;\n color: var(--text-tertiary);\n}\n.pill[data-state='copied'] .pillIcon {\n color: var(--status-success-fg);\n}\n.pill[data-state='failed'] {\n border-color: var(--status-danger-solid);\n}\n\n.visuallyHidden {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n clip: rect(0 0 0 0);\n white-space: nowrap;\n border: 0;\n}\n\n/* ── Launch split button ─────────────────────────────────────────────── */\n\n.split {\n display: inline-flex;\n align-items: stretch;\n}\n.split > :first-child {\n border-top-right-radius: 0;\n border-bottom-right-radius: 0;\n}\n.split > :last-child {\n border-top-left-radius: 0;\n border-bottom-left-radius: 0;\n margin-left: -1px;\n}\n.disabledNote {\n font-size: var(--text-xs-size);\n line-height: var(--text-xs-line);\n color: var(--text-tertiary);\n max-width: 18rem;\n text-align: right;\n}\n\n/* ── Dialog bodies ───────────────────────────────────────────────────── */\n\n.dialogBody {\n display: flex;\n flex-direction: column;\n gap: var(--space-3);\n font-size: var(--text-sm-size);\n line-height: var(--text-sm-line);\n color: var(--text-secondary);\n}\n.dialogBody p {\n margin: 0;\n}\n.commandBlock {\n display: flex;\n flex-direction: column;\n gap: var(--space-1);\n}\n.commandLabel {\n font-family: var(--font-display);\n font-size: var(--text-2xs-size);\n line-height: var(--text-2xs-line);\n text-transform: uppercase;\n letter-spacing: var(--tracking-label);\n color: var(--text-tertiary);\n}\n.dialogActions {\n display: flex;\n flex-wrap: wrap;\n justify-content: flex-end;\n gap: var(--space-2);\n margin-top: var(--space-2);\n}\n.fieldset {\n border: 0;\n margin: 0;\n padding: 0;\n display: flex;\n flex-direction: column;\n gap: var(--space-2);\n}\n.legend {\n padding: 0;\n margin-bottom: var(--space-1);\n font-size: var(--text-xs-size);\n font-weight: var(--font-weight-semibold);\n color: var(--text-primary);\n}\n.radio {\n display: flex;\n align-items: center;\n gap: var(--space-2);\n font-size: var(--text-sm-size);\n color: var(--text-primary);\n}\n.radio input {\n accent-color: var(--accent-500);\n}\n.error {\n margin: 0;\n font-size: var(--text-xs-size);\n line-height: var(--text-xs-line-relaxed);\n color: var(--status-danger-fg);\n}\n.textarea {\n width: 100%;\n min-height: 5rem;\n resize: vertical;\n padding: var(--space-2);\n border: 1px solid var(--border-default);\n border-radius: var(--radius-sm);\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-relaxed);\n}\n.textarea:focus-visible {\n outline: none;\n box-shadow: var(--shadow-focus-ring);\n}\n.fieldLabel {\n display: flex;\n flex-direction: column;\n gap: var(--space-1);\n font-size: var(--text-xs-size);\n font-weight: var(--font-weight-medium);\n color: var(--text-primary);\n}\n.hint {\n font-weight: var(--font-weight-regular);\n color: var(--text-tertiary);\n}\n.warnings {\n margin: 0;\n padding-left: var(--space-4);\n font-size: var(--text-xs-size);\n line-height: var(--text-xs-line-relaxed);\n color: var(--status-warning-fg);\n}\n\n/* ── MCP ─────────────────────────────────────────────────────────────── */\n\n.servers {\n display: flex;\n flex-direction: column;\n gap: var(--space-2);\n margin-top: var(--space-2);\n}\n.reasonCode {\n font-family: var(--font-mono);\n font-size: var(--text-2xs-size);\n color: var(--text-tertiary);\n}\n\n.scopeLine {\n margin: 0;\n padding: 0 0 var(--space-3);\n font-size: var(--text-xs-size);\n line-height: var(--text-xs-line-relaxed);\n color: var(--text-tertiary);\n}\n\n/* ── Compact container (a 375 window, or a narrow pane) ──────────────── */\n@container (max-width: 480px) {\n .row {\n grid-template-columns: auto minmax(0, 1fr);\n }\n .rowAside {\n grid-column: 2;\n justify-content: flex-start;\n max-width: none;\n }\n .disabledNote {\n text-align: left;\n }\n}\n\n@media (prefers-reduced-motion: reduce) {\n .pill {\n transition: none;\n }\n}\n","/**\n * routes/verse/apps/MonogramTile.tsx — the square tile every seat and app row\n * leads with. 3.11.1: engine-backed tiles show the provider's own mark\n * (Anthropic Claude, OpenAI, xAI Grok, Ollama — ProviderLogo) so an account is\n * recognisable at a glance; the mark only identifies the provider, the row's\n * text still names the account. Neutral tiles (Aider, Goose, …) keep their\n * letters.\n *\n * Engine-backed tiles take a 12% tint of the engine hue; marks draw in ink\n * (currentColor, Claude in its brand colour) so contrast never depends on the\n * hue. Decorative: the row's name carries the meaning.\n */\nimport type { CSSProperties } from 'react';\nimport type { VerseEngine } from '../../../data/api-types.js';\nimport { engineColor } from '../../../components/primitives/Tag.js';\nimport { ProviderLogo } from '../../../components/primitives/ProviderLogo.js';\nimport styles from './Apps.module.css';\n\nexport function MonogramTile({\n monogram,\n engine,\n size = 'md',\n}: {\n monogram: string;\n engine: VerseEngine | null;\n /** md = 32px (Apps rows), sm = 24px (capacity rows). */\n size?: 'sm' | 'md';\n}) {\n const style = engine === null ? undefined : ({ '--tile-hue': engineColor(engine) } as CSSProperties);\n return (\n <span\n className={styles.tile}\n data-size={size}\n data-engine={engine ?? undefined}\n style={style}\n aria-hidden=\"true\"\n >\n {engine === null ? monogram.slice(0, 2) : <ProviderLogo engine={engine} size={size === 'sm' ? 14 : 18} />}\n </span>\n );\n}\n","/*\n * The shared capacity strip. Tokens only (DESIGN.md §13): no raw colour, no\n * px font size. It adapts to ITS container, not the window — the same strip\n * sits in an 880px Apps column and a 300px Resources panel — so the narrow\n * layout is a container query at the compact breakpoint (480, viewport.ts).\n */\n.strip {\n container-type: inline-size;\n display: flex;\n flex-direction: column;\n gap: var(--space-3);\n min-width: 0;\n}\n\n.visuallyHidden {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n clip: rect(0 0 0 0);\n white-space: nowrap;\n border: 0;\n}\n\n.headline {\n margin: 0;\n font-size: var(--text-sm-size);\n line-height: var(--text-sm-line);\n font-weight: var(--font-weight-medium);\n color: var(--text-primary);\n}\n\n.empty {\n margin: 0;\n font-size: var(--text-sm-size);\n line-height: var(--text-sm-line);\n color: var(--text-secondary);\n}\n\n.rows {\n list-style: none;\n margin: 0;\n padding: 0;\n display: flex;\n flex-direction: column;\n}\n\n.row {\n display: grid;\n grid-template-columns: auto minmax(0, 1fr) auto;\n align-items: start;\n gap: var(--space-3);\n padding: var(--space-3) 0;\n border-top: 1px solid var(--border-subtle);\n}\n.row:first-child {\n border-top: 0;\n}\n.row[data-compact] {\n padding: var(--space-2) 0;\n gap: var(--space-2);\n align-items: center;\n}\n\n.main {\n display: flex;\n flex-direction: column;\n gap: var(--space-1);\n min-width: 0;\n}\n\n.head {\n display: flex;\n flex-wrap: wrap;\n align-items: baseline;\n gap: var(--space-1) var(--space-3);\n min-width: 0;\n}\n\n.nameWrap,\n.nameButton {\n display: inline-flex;\n align-items: baseline;\n gap: var(--space-2);\n min-width: 0;\n}\n.nameButton {\n padding: 0;\n border: 0;\n background: none;\n font: inherit;\n color: inherit;\n cursor: pointer;\n border-radius: var(--radius-xs);\n}\n.nameButton:hover .name {\n text-decoration: underline;\n text-underline-offset: 2px;\n}\n.nameButton:focus-visible {\n outline: none;\n box-shadow: var(--shadow-focus-ring);\n}\n.nameButton[aria-pressed='true'] .name {\n color: var(--text-link);\n}\n\n/* The seat name is often a control (Usage's toggle): it wraps, never cut mid-word. */\n.name {\n font-size: var(--text-sm-size);\n line-height: var(--text-sm-line);\n font-weight: var(--font-weight-semibold);\n color: var(--text-primary);\n min-width: 0;\n overflow-wrap: anywhere;\n text-align: left;\n}\n\n.plan {\n font-size: var(--text-2xs-size);\n line-height: var(--text-2xs-line);\n text-transform: uppercase;\n letter-spacing: var(--tracking-label);\n font-family: var(--font-display);\n color: var(--text-tertiary);\n}\n\n/* A state is a WORD; the dot only reinforces it. */\n.word {\n display: inline-flex;\n align-items: center;\n gap: var(--space-1);\n font-size: var(--text-xs-size);\n line-height: var(--text-xs-line);\n color: var(--text-secondary);\n white-space: nowrap;\n}\n.dot {\n width: 7px;\n height: 7px;\n border-radius: var(--radius-full);\n background: var(--status-neutral-solid);\n flex: none;\n}\n.word[data-tone='success'] .dot { background: var(--status-success-solid); }\n.word[data-tone='warning'] { color: var(--status-warning-fg); }\n.word[data-tone='warning'] .dot { background: var(--status-warning-solid); }\n.word[data-tone='danger'] { color: var(--status-danger-fg); }\n.word[data-tone='danger'] .dot { background: var(--status-danger-solid); }\n.word[data-tone='neutral'] { font-style: italic; }\n.word[data-tone='neutral'] .dot {\n background: transparent;\n border: 1px solid var(--status-unknown-solid);\n}\n\n/*\n * Accounts mode: the row's status reads as a short sentence — a label in the\n * tone's colour, then the detail in secondary text. The detail may wrap (a\n * provider's reset prose can be long); the label never truncates.\n */\n.status {\n display: inline-flex;\n align-items: baseline;\n flex-wrap: wrap;\n gap: 0 var(--space-1);\n min-width: 0;\n font-size: var(--text-xs-size);\n line-height: var(--text-xs-line);\n color: var(--text-secondary);\n}\n.status .dot {\n align-self: center;\n}\n.statusLabel {\n font-weight: var(--font-weight-medium);\n color: var(--text-primary);\n white-space: nowrap;\n}\n.status[data-tone='success'] .dot { background: var(--status-success-solid); }\n.status[data-tone='success'] .statusLabel { color: var(--status-success-fg); }\n.status[data-tone='warning'] .dot { background: var(--status-warning-solid); }\n.status[data-tone='warning'] .statusLabel { color: var(--status-warning-fg); }\n.status[data-tone='danger'] .dot { background: var(--status-danger-solid); }\n.status[data-tone='danger'] .statusLabel { color: var(--status-danger-fg); }\n.status[data-tone='neutral'] .dot {\n background: transparent;\n border: 1px solid var(--status-unknown-solid);\n}\n.status[data-tone='neutral'] .statusLabel {\n color: var(--text-secondary);\n font-style: italic;\n}\n.statusDetail {\n overflow-wrap: anywhere;\n}\n\n.stamp {\n margin: 0;\n font-size: var(--text-xs-size);\n line-height: var(--text-xs-line);\n color: var(--text-tertiary);\n font-variant-numeric: tabular-nums;\n}\n.usableAgain {\n color: var(--text-secondary);\n font-weight: var(--font-weight-medium);\n}\n\n.summary,\n.meta {\n margin: 0;\n font-size: var(--text-xs-size);\n line-height: var(--text-xs-line-relaxed);\n color: var(--text-secondary);\n overflow-wrap: anywhere;\n}\n.meta {\n color: var(--text-tertiary);\n}\n.autonomy {\n color: var(--text-secondary);\n font-weight: var(--font-weight-medium);\n}\n.autonomy[data-status='eligible'] { color: var(--status-success-fg); }\n.autonomy[data-status='unknown'] {\n font-style: italic;\n color: var(--status-unknown-fg);\n}\n\n.bars {\n display: flex;\n flex-direction: column;\n gap: var(--space-1);\n margin-top: var(--space-1);\n}\n\n.bar {\n display: grid;\n grid-template-columns: minmax(4.5rem, 7.5rem) minmax(5rem, 1fr) minmax(2.75rem, auto) minmax(0, 12rem);\n align-items: center;\n gap: var(--space-2);\n font-size: var(--text-xs-size);\n line-height: var(--text-xs-line);\n}\n.bar[data-compact] {\n grid-template-columns: minmax(3.5rem, 5.5rem) minmax(3rem, 1fr) auto;\n}\n\n.barLabel {\n color: var(--text-tertiary);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n.bar[data-binding] .barLabel {\n color: var(--text-secondary);\n}\n\n/* used (solid) · room (track) · kept for you (hatched, past the tick). */\n.track {\n position: relative;\n display: block;\n height: 6px;\n border-radius: var(--radius-full);\n background: var(--meter-track);\n overflow: hidden;\n}\n.trackUnknown {\n display: block;\n height: 6px;\n border-radius: var(--radius-full);\n border: 1px dashed var(--border-strong);\n}\n.used {\n position: absolute;\n left: 0;\n top: 0;\n bottom: 0;\n border-radius: var(--radius-full);\n background: var(--data-seq-5);\n transition: width var(--duration-base) var(--ease-standard);\n}\n.used[data-level='tight'] { background: var(--status-warning-solid); }\n.used[data-level='limit'] { background: var(--status-danger-solid); }\n.reserve {\n position: absolute;\n top: 0;\n bottom: 0;\n background: repeating-linear-gradient(\n 135deg,\n color-mix(in srgb, var(--text-tertiary) 34%, transparent) 0 2px,\n transparent 2px 5px\n );\n}\n.ceiling {\n position: absolute;\n top: 0;\n bottom: 0;\n width: 2px;\n margin-left: -1px;\n background: var(--text-secondary);\n}\n\n.value {\n font-variant-numeric: tabular-nums;\n color: var(--text-primary);\n white-space: nowrap;\n text-align: right;\n}\n.value[data-level='tight'] { color: var(--status-warning-fg); }\n.value[data-level='limit'] { color: var(--status-danger-fg); }\n.value[data-level='unknown'] {\n font-style: italic;\n color: var(--status-unknown-fg);\n}\n\n.reset {\n color: var(--text-tertiary);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.actions {\n display: flex;\n flex-wrap: wrap;\n justify-content: flex-end;\n gap: var(--space-1);\n}\n\n/* Narrow container (a side panel, or a 375 window): actions and resets wrap. */\n@container (max-width: 480px) {\n .row {\n grid-template-columns: auto minmax(0, 1fr);\n }\n .actions {\n grid-column: 2;\n justify-content: flex-start;\n }\n .bar {\n grid-template-columns: minmax(0, 1fr) auto;\n row-gap: var(--space-1);\n }\n .bar .track,\n .bar .trackUnknown {\n grid-column: 1 / -1;\n grid-row: 2;\n }\n .reset {\n grid-column: 1 / -1;\n grid-row: 3;\n white-space: normal;\n }\n .bar[data-compact] {\n grid-template-columns: minmax(3rem, auto) minmax(3rem, 1fr) auto;\n }\n .bar[data-compact] .track,\n .bar[data-compact] .trackUnknown {\n grid-column: auto;\n grid-row: auto;\n }\n}\n\n@media (prefers-reduced-motion: reduce) {\n .used {\n transition: none;\n }\n}\n","/**\n * routes/verse/usage/CapacityStrip.tsx — THE capacity view (SPEC-310C §4:\n * \"Resources, NewChatDialog and onboarding drop their own capacity views and\n * import usage/CapacityStrip instead\"). Apps & Accounts and Usage render it\n * too, so every surface answers \"how much of each seat is left\" the same way.\n *\n * [C] Claude Max · max ● connected [actions]\n * usable · 62% of 5-hour window used\n * 5-hour window ▇▇▇▇▇▇▇░░░░│▨▨▨ 62% resets 7pm\n * weekly window ▇▇▇░░░░░░░░│▨▨▨ 40% resets Thu\n * Reserved for you 40% · Autonomy: Eligible\n *\n * Each bar reads left to right: used (solid), what autonomy may still use\n * (track), and the band KEPT FOR YOU (hatched) past a tick at 100 − reserve —\n * so \"Reserved for you 40%\" is something you can see, not just read. The\n * reserve applies to the binding window; the other windows carry no tick.\n *\n * Honesty (docs/VERSE-TELEMETRY-V2.md), enforced by the model and kept here:\n * - no reading → a dashed track and the words \"no reading\", never a 0% bar;\n * - a flagged limit → \"limit reached\", never \"100%\";\n * - reset prose is printed verbatim, never turned into a countdown;\n * - every state is a WORD first; colour only reinforces it.\n *\n * Three entry points:\n * <CapacityStrip seats health? budget? …/> pure: props in, markup out;\n * <LiveCapacityStrip …/> reads the shared caches itself\n * (bootstrap seats, /health,\n * /budget) — drop-in for C1/C2;\n * useCapacityRows() the rows, for a custom layout\n * (the rail ring, the seat chip).\n */\nimport { useId, useMemo, useState, type CSSProperties, type ReactNode } from 'react';\nimport type { BudgetView } from '../../../../core/routing/policy.js';\nimport type { SeatHealthReport } from '../../../../core/verse/health-types.js';\nimport type { VerseBootstrap, VerseSeat } from '../../../data/api-types.js';\nimport { useQuery, useRefetch } from '../../../data/hooks.js';\nimport { MonogramTile } from '../apps/MonogramTile.js';\nimport { budgetQuery } from '../budget/budget-queries.js';\nimport { useSeatHealth } from '../health/useSeatHealth.js';\nimport { usePollWhileVisible, useSectionVisible } from '../shell/section-visibility.js';\nimport { useSeatsRefresh } from '../useSeatsRefresh.js';\nimport { verseBootstrapQuery } from '../verse-queries.js';\nimport {\n accountStatus,\n buildCapacityRows,\n capacityHeadline,\n capacityTone,\n orderAccountRows,\n percentText,\n windowSentence,\n type AccountStatus,\n type CapacityInputs,\n type CapacityRow,\n type CapacityWindowRow,\n} from './capacity-strip-model.js';\nimport styles from './CapacityStrip.module.css';\n\n/** Above this share of a window the bar turns amber (the word \"tight\" rides with it). */\nconst TIGHT_AT = 90;\n\n/** How often an accounts strip re-reads the clock (\"usable again in 7h\", \"checked 2m ago\"). */\nexport const ACCOUNT_CLOCK_MS = 30_000;\n\n/**\n * Apps & Accounts mode: every row leads with a sentence-case status\n * (\"Connected · usable now\", \"Spent · resets Fri 11:46 PM\", \"Signed out ·\n * reconnect to use it\", \"Checking…\"), says when it was last checked and — for\n * a spent seat — when it is usable again, and usable rows come first.\n */\nexport interface CapacityAccountsMode {\n /** False until the health sweep has answered once. */\n healthRead: boolean;\n /** The seat whose check is running now (its row reads \"Checking…\"). */\n checkingSeatId?: string | null;\n /** Injected clock for tests; otherwise the strip ticks every ACCOUNT_CLOCK_MS while visible. */\n now?: number;\n}\n\nexport interface CapacityStripProps {\n seats: readonly VerseSeat[];\n health?: readonly SeatHealthReport[] | null;\n budget?: BudgetView | null;\n local?: CapacityInputs['local'];\n seatIds?: readonly string[];\n /** full: every window with resets and the reserve; compact: one line per seat (pickers, side panels). */\n density?: 'full' | 'compact';\n /** Show the one-sentence summary above the rows. Default true for full, false for compact. */\n headline?: boolean;\n /** Heading for assistive tech (visually hidden). */\n title?: string;\n /**\n * The id of a heading that already names this strip (Apps' \"Accounts\"\n * group). The strip then labels itself by it instead of adding a second,\n * hidden heading — two regions with one name is noise to a screen reader.\n */\n labelledBy?: string;\n /** Per-seat trailing controls (Apps passes Reconnect / Fix / Edit budget). */\n renderActions?: (row: CapacityRow) => ReactNode;\n /** Makes each seat name a toggle (Usage opens the account's detail). */\n onSelectSeat?: (seatId: string) => void;\n selectedSeatId?: string | null;\n /** Shown instead of rows when the roster is empty. */\n emptyText?: string;\n /** Apps & Accounts: a status per row, when it was checked, usable rows first. */\n accounts?: CapacityAccountsMode;\n}\n\nfunction pct(n: number): number {\n return Math.max(0, Math.min(100, Math.round(n)));\n}\n\nfunction WindowBar({\n row,\n w,\n reservePercent,\n compact,\n}: {\n row: CapacityRow;\n w: CapacityWindowRow;\n reservePercent: number | null;\n compact: boolean;\n}) {\n const sentence = windowSentence(row, w, w.binding ? reservePercent : null);\n const ceiling = w.binding && reservePercent !== null && reservePercent > 0 ? 100 - pct(reservePercent) : null;\n let track: ReactNode;\n let value: ReactNode;\n if (w.limitReached) {\n track = (\n <span className={styles.track} role=\"img\" aria-label={sentence}>\n <span className={styles.used} data-level=\"limit\" style={{ width: '100%' }} />\n </span>\n );\n value = <span className={styles.value} data-level=\"limit\">limit reached</span>;\n } else if (w.usedPercent === null) {\n // Absence drawn as absence. Never a 0% bar.\n track = <span className={styles.trackUnknown} role=\"img\" aria-label={sentence} />;\n value = <span className={styles.value} data-level=\"unknown\">no reading</span>;\n } else {\n const used = pct(w.usedPercent);\n const level = used >= TIGHT_AT ? 'tight' : 'ok';\n track = (\n <span className={styles.track} role=\"img\" aria-label={sentence}>\n {ceiling !== null ? (\n <span className={styles.reserve} style={{ left: `${ceiling}%`, width: `${100 - ceiling}%` } as CSSProperties} />\n ) : null}\n <span className={styles.used} data-level={level} style={{ width: `${used}%` }} />\n {ceiling !== null ? <span className={styles.ceiling} style={{ left: `${ceiling}%` }} /> : null}\n </span>\n );\n value = <span className={styles.value} data-level={level}>{percentText(w.usedPercent)}</span>;\n }\n return (\n <div className={styles.bar} data-binding={w.binding || undefined} data-compact={compact || undefined}>\n <span className={styles.barLabel} title={w.label}>{w.label.replace(/ window$/, '')}</span>\n {track}\n {value}\n {!compact && w.resetText !== null ? <span className={styles.reset} title={w.resetText}>{w.resetText}</span> : null}\n </div>\n );\n}\n\nfunction SeatName({ row, onSelect, selected }: { row: CapacityRow; onSelect: ((id: string) => void) | undefined; selected: boolean }) {\n const text = (\n <>\n <span className={styles.name}>{row.label}</span>\n {row.plan !== null ? <span className={styles.plan}>{row.plan}</span> : null}\n </>\n );\n // A control only when there is something for it to open.\n if (!onSelect) return <span className={styles.nameWrap}>{text}</span>;\n return (\n <button type=\"button\" className={styles.nameButton} aria-pressed={selected} onClick={() => onSelect(row.seatId)}>\n {text}\n </button>\n );\n}\n\nfunction StatusLine({ status }: { status: AccountStatus }) {\n return (\n <span className={styles.status} data-tone={status.tone} data-status={status.kind}>\n <span className={styles.dot} aria-hidden=\"true\" />\n <span className={styles.statusLabel}>{status.label}</span>\n {status.detail !== null ? <span className={styles.statusDetail}>{`· ${status.detail}`}</span> : null}\n </span>\n );\n}\n\n/** \"usable again in 7h 12m · checked 2m ago\" — the row's clock facts, when it has any. */\nfunction StampLine({ status }: { status: AccountStatus }) {\n if (status.usableAgain === null && status.checked === null) return null;\n return (\n <p className={styles.stamp}>\n {status.usableAgain !== null ? <span className={styles.usableAgain}>{status.usableAgain}</span> : null}\n {status.usableAgain !== null && status.checked !== null ? ' · ' : null}\n {status.checked !== null ? <span title={status.checkedTitle ?? undefined}>{status.checked}</span> : null}\n </p>\n );\n}\n\nfunction CapacityRowView({\n row,\n compact,\n renderActions,\n onSelectSeat,\n selected,\n status,\n}: {\n row: CapacityRow;\n compact: boolean;\n renderActions: CapacityStripProps['renderActions'];\n onSelectSeat: CapacityStripProps['onSelectSeat'];\n selected: boolean;\n status: AccountStatus | null;\n}) {\n const tone = capacityTone(row.cls);\n const binding = row.windows.find((w) => w.binding) ?? null;\n const windows = compact ? (binding ? [binding] : []) : row.windows;\n const actions = renderActions ? renderActions(row) : null;\n const reserve = row.reserve;\n return (\n <li className={styles.row} data-capacity={row.cls} data-compact={compact || undefined} data-status={status?.kind}>\n <MonogramTile monogram={row.monogram} engine={row.engine} size=\"sm\" />\n <div className={styles.main}>\n <div className={styles.head}>\n <SeatName row={row} onSelect={onSelectSeat} selected={selected} />\n {status !== null ? (\n <StatusLine status={status} />\n ) : (\n <span className={styles.word} data-tone={tone}>\n <span className={styles.dot} aria-hidden=\"true\" />\n {row.word}\n </span>\n )}\n {row.connection !== null && row.connection.connection !== 'connected' && row.connection.connection !== 'unknown'\n && !(status?.coversConnection ?? false) && !(status?.kind === 'signed-out') ? (\n <span className={styles.word} data-tone={row.connection.tone}>\n <span className={styles.dot} aria-hidden=\"true\" />\n {row.connection.word}\n </span>\n ) : null}\n </div>\n {!compact || windows.length === 0 ? <p className={styles.summary}>{row.summary}</p> : null}\n {status !== null && !compact ? <StampLine status={status} /> : null}\n {windows.length > 0 ? (\n <div className={styles.bars}>\n {windows.map((w) => (\n <WindowBar key={w.id} row={row} w={w} reservePercent={reserve?.percent ?? null} compact={compact} />\n ))}\n </div>\n ) : null}\n {!compact && (reserve !== null || row.credits !== null) ? (\n <p className={styles.meta}>\n {reserve !== null ? (\n <span title={reserve.why}>\n {reserve.label}\n {/* \"Autonomy off — all yours\" already says it; no second \"Off\". */}\n {reserve.autonomy === 'off' ? null : (\n <> · Autonomy: <span className={styles.autonomy} data-status={reserve.autonomy}>{reserve.autonomyWord}</span></>\n )}\n </span>\n ) : null}\n {reserve !== null && row.credits !== null ? ' · ' : null}\n {row.credits !== null ? <span>{row.credits}</span> : null}\n </p>\n ) : null}\n </div>\n {actions ? <div className={styles.actions}>{actions}</div> : null}\n </li>\n );\n}\n\nexport function CapacityStrip({\n seats,\n health,\n budget,\n local,\n seatIds,\n density = 'full',\n headline,\n title = 'Seat capacity',\n labelledBy,\n renderActions,\n onSelectSeat,\n selectedSeatId = null,\n emptyText = 'No seats yet. Connect an account or start Ollama.',\n accounts,\n}: CapacityStripProps) {\n const headingId = useId();\n const [tick, setTick] = useState(() => Date.now());\n usePollWhileVisible(() => setTick(Date.now()), ACCOUNT_CLOCK_MS, { enabled: accounts !== undefined && accounts.now === undefined });\n const now = accounts?.now ?? tick;\n const healthRead = accounts?.healthRead ?? false;\n const accountsMode = accounts !== undefined;\n // Accounts mode words every window reset and reason against the SAME clock\n // as its status line (\"Spent · resets Sat 11:46 PM\"), so the two never\n // disagree about which day \"today\" is.\n const rowsNow = accountsMode ? now : undefined;\n const built = useMemo(\n () => buildCapacityRows(seats, {\n health: health ?? null,\n budget: budget ?? null,\n ...(local ? { local } : {}),\n ...(seatIds ? { seatIds } : {}),\n ...(rowsNow !== undefined ? { now: rowsNow } : {}),\n }),\n [seats, health, budget, local, seatIds, rowsNow],\n );\n const rows = useMemo(\n () => (accountsMode ? orderAccountRows(built, { healthRead, now }) : built),\n [built, accountsMode, healthRead, now],\n );\n const compact = density === 'compact';\n const showHeadline = headline ?? !compact;\n // Named by the caller's heading: a plain block inside the caller's region,\n // not a second region with the same name.\n const Wrapper = labelledBy ? 'div' : 'section';\n return (\n <Wrapper className={styles.strip} aria-labelledby={labelledBy ? undefined : headingId} data-density={density}>\n {labelledBy ? null : <h3 id={headingId} className={styles.visuallyHidden}>{title}</h3>}\n {showHeadline && rows.length > 0 ? <p className={styles.headline}>{capacityHeadline(rows)}</p> : null}\n {rows.length === 0 ? (\n <p className={styles.empty}>{emptyText}</p>\n ) : (\n <ul className={styles.rows} aria-label={labelledBy ? undefined : title} aria-labelledby={labelledBy}>\n {rows.map((row) => (\n <CapacityRowView\n key={row.seatId}\n row={row}\n compact={compact}\n renderActions={renderActions}\n onSelectSeat={onSelectSeat}\n selected={selectedSeatId === row.seatId}\n status={accounts\n ? accountStatus(row, { healthRead, now, checking: accounts.checkingSeatId === row.seatId })\n : null}\n />\n ))}\n </ul>\n )}\n </Wrapper>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Live data\n// ---------------------------------------------------------------------------\n\n/** Budget moves with the collector (30 s); a minute is plenty for a strip. */\nexport const CAPACITY_BUDGET_POLL_MS = 60_000;\n\nexport interface CapacityData {\n seats: readonly VerseSeat[];\n health: readonly SeatHealthReport[] | null;\n budget: BudgetView | null;\n /** True until the seat roster has been read once. */\n loading: boolean;\n}\n\n/**\n * The three shared reads behind the strip, kept live while the surface is on\n * screen: seats (the /seats poll merged into bootstrap), A2's health (30 s)\n * and A9's budget (60 s). Each is the app-wide cache entry — mounting this\n * twice costs no extra request.\n */\nexport function useCapacityData(opts: { withBudget?: boolean; withHealth?: boolean } = {}): CapacityData {\n const visible = useSectionVisible();\n const withBudget = opts.withBudget ?? true;\n const withHealth = opts.withHealth ?? true;\n const bootstrap = useQuery(verseBootstrapQuery);\n useSeatsRefresh(visible);\n const health = useSeatHealth(visible && withHealth);\n const budget = useQuery(budgetQuery);\n const refetchBudget = useRefetch(budgetQuery);\n usePollWhileVisible(refetchBudget, CAPACITY_BUDGET_POLL_MS, { enabled: withBudget });\n const data = bootstrap.data as VerseBootstrap | undefined;\n return {\n seats: data?.seats ?? [],\n health: withHealth ? (health.data?.seats ?? null) : null,\n budget: withBudget ? (budget.data ?? null) : null,\n loading: data === undefined && (bootstrap.status === 'loading' || bootstrap.status === 'idle'),\n };\n}\n\n/** The rows for a custom layout (the rail's capacity ring, the composer's seat chip). */\nexport function useCapacityRows(inputs: Omit<CapacityInputs, 'health' | 'budget'> = {}): CapacityRow[] {\n const data = useCapacityData();\n return useMemo(\n () => buildCapacityRows(data.seats, { health: data.health, budget: data.budget, ...inputs }),\n // eslint-disable-next-line react-hooks/exhaustive-deps -- inputs is a small literal; its fields are the identity.\n [data.seats, data.health, data.budget, inputs.local, inputs.seatIds],\n );\n}\n\nexport interface LiveCapacityStripProps extends Omit<CapacityStripProps, 'seats' | 'health' | 'budget'> {\n /**\n * The roster, when the caller already holds it (the new-chat dialog, whose\n * seat list IS this roster and whose pre-fill works from its own props).\n * The strip then adds only health and budget, and never shows \"Reading\n * seats…\" over a roster that is already on screen.\n */\n seats?: readonly VerseSeat[];\n}\n\n/** Drop-in strip that reads its own data — what NewChatDialog and onboarding mount. */\nexport function LiveCapacityStrip({ seats: given, ...props }: LiveCapacityStripProps) {\n const data = useCapacityData();\n if (given === undefined && data.loading) {\n return <p className={styles.empty} aria-busy=\"true\">Reading seats…</p>;\n }\n return <CapacityStrip {...props} seats={given ?? data.seats} health={data.health} budget={data.budget} />;\n}\n"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import{a as e,c as t,n}from"./index-DZ-UQ7v8.js";import{d as r,f as i}from"./colors-DvK0wMHH.js";import{t as a}from"./ProviderLogo-Cq-CYIwT.js";import{n as o,o as s,s as c,u as l}from"./format-D7nBg2bn.js";var u=t(e(),1),d=n(),f={plotWrap:`_plotWrap_sf833_3`,svg:`_svg_sf833_9`,grid:`_grid_sf833_18`,axis:`_axis_sf833_24`,tick:`_tick_sf833_30`,label:`_label_sf833_37`,labelStrong:`_labelStrong_sf833_43`,line:`_line_sf833_50`,wash:`_wash_sf833_57`,reference:`_reference_sf833_62`,projection:`_projection_sf833_69`,marker:`_marker_sf833_76`,crosshair:`_crosshair_sf833_81`,area:`_area_sf833_89`,hoverBand:`_hoverBand_sf833_94`,reserveBand:`_reserveBand_sf833_102`,now:`_now_sf833_108`,endDot:`_endDot_sf833_117`,hit:`_hit_sf833_122`,focusable:`_focusable_sf833_136`,track:`_track_sf833_146`,trackEmpty:`_trackEmpty_sf833_160`,noData:`_noData_sf833_164`,tooltip:`_tooltip_sf833_171`,"chart-tooltip-in":`_chart-tooltip-in_sf833_1`,tooltipRight:`_tooltipRight_sf833_193`,tooltipLeft:`_tooltipLeft_sf833_197`,tooltipTitle:`_tooltipTitle_sf833_210`,tooltipRow:`_tooltipRow_sf833_216`,tooltipLabel:`_tooltipLabel_sf833_223`,tooltipTotal:`_tooltipTotal_sf833_228`,tooltipKey:`_tooltipKey_sf833_239`,tooltipKeyLine:`_tooltipKeyLine_sf833_247`,tooltipValue:`_tooltipValue_sf833_254`,tooltipMuted:`_tooltipMuted_sf833_261`,legend:`_legend_sf833_266`,legendItem:`_legendItem_sf833_277`,swatch:`_swatch_sf833_283`,swatchLine:`_swatchLine_sf833_290`,swatchEmpty:`_swatchEmpty_sf833_296`,note:`_note_sf833_304`,srOnly:`_srOnly_sf833_310`,draw:`_draw_sf833_334`,"chart-draw":`_chart-draw_sf833_1`,fadeIn:`_fadeIn_sf833_339`,"chart-fade":`_chart-fade_sf833_1`,rise:`_rise_sf833_345`,"chart-rise":`_chart-rise_sf833_1`,grow:`_grow_sf833_353`,"chart-grow":`_chart-grow_sf833_1`,skeleton:`_skeleton_sf833_405`,"chart-skeleton-pulse":`_chart-skeleton-pulse_sf833_1`,skeletonMark:`_skeletonMark_sf833_428`,skeletonTrack:`_skeletonTrack_sf833_432`,skeletonGrid:`_skeletonGrid_sf833_436`,monogram:`_monogram_sf833_454`,unknownMark:`_unknownMark_sf833_464`,swatchHatch:`_swatchHatch_sf833_470`,halo:`_halo_sf833_481`};function p({items:e,min:t=2}){return e.length<t?null:(0,d.jsx)(`ul`,{className:f.legend,children:e.map(e=>(0,d.jsxs)(`li`,{className:f.legendItem,children:[(0,d.jsx)(`span`,{"aria-hidden":`true`,className:e.kind===`line`?f.swatchLine:e.kind===`empty`?f.swatchEmpty:e.kind===`hatch`?f.swatchHatch:f.swatch,style:e.kind===`empty`||e.kind===`hatch`?void 0:{background:e.color}}),e.label]},e.label))})}function m({left:e,top:t,title:n,rows:r,side:i}){let a=i===`right`?`${f.tooltip} ${f.tooltipRight}`:i===`left`?`${f.tooltip} ${f.tooltipLeft}`:f.tooltip;return(0,d.jsxs)(`div`,{className:a,style:{left:e,top:t},role:`presentation`,"data-chart-tooltip":i??`above`,children:[(0,d.jsx)(`div`,{className:f.tooltipTitle,children:n}),r.map(e=>(0,d.jsxs)(`div`,{className:e.total?`${f.tooltipRow} ${f.tooltipTotal}`:f.tooltipRow,children:[e.color?(0,d.jsx)(`span`,{className:e.kind===`line`?f.tooltipKeyLine:f.tooltipKey,style:{background:e.color},"aria-hidden":`true`}):null,(0,d.jsx)(`span`,{className:f.tooltipLabel,children:e.label}),e.value===null?(0,d.jsx)(`span`,{className:`${f.tooltipValue} ${f.tooltipMuted}`,children:`no data`}):(0,d.jsx)(`span`,{className:f.tooltipValue,children:e.value})]},e.key))]})}var h=172,g=12;function _(e,t,n=h){if(e+g+n<=t)return`right`;if(e-g-n>=0)return`left`}function v(e,t,n=70){return Math.min(Math.max(e,Math.min(n,t/2)),Math.max(t-n,t/2))}function y({id:e}){let{size:t,angle:n,strokeWidth:i,stroke:a}=r;return(0,d.jsx)(`pattern`,{id:e,width:t,height:t,patternUnits:`userSpaceOnUse`,patternTransform:`rotate(${n})`,children:(0,d.jsx)(`line`,{x1:0,y1:0,x2:0,y2:t,stroke:a,strokeWidth:i})})}function ee({engine:e,x:t,y:n,height:r}){return(0,d.jsxs)(`g`,{"data-engine":e,"aria-hidden":`true`,children:[(0,d.jsx)(`rect`,{x:t,y:n,width:2,height:r,rx:1,fill:i(e)}),(0,d.jsx)(a,{engine:e,x:t+5,y:n+r/2-6,size:12,className:f.monogram})]})}function te(){return(0,d.jsxs)(`svg`,{width:16,height:16,viewBox:`0 0 16 16`,"aria-hidden":`true`,focusable:`false`,children:[(0,d.jsx)(`circle`,{cx:3.5,cy:8,r:1.4,fill:`currentColor`}),(0,d.jsx)(`circle`,{cx:8,cy:8,r:1.4,fill:`currentColor`}),(0,d.jsx)(`circle`,{cx:12.5,cy:8,r:1.4,fill:`currentColor`})]})}function b({id:e,color:t,top:n,bottom:r,from:i=.22}){return(0,d.jsxs)(`linearGradient`,{id:e,gradientUnits:`userSpaceOnUse`,x1:0,x2:0,y1:n,y2:r,"data-area-gradient":``,children:[(0,d.jsx)(`stop`,{offset:`0%`,style:{stopColor:t,stopOpacity:i}}),(0,d.jsx)(`stop`,{offset:`65%`,style:{stopColor:t,stopOpacity:i*.3}}),(0,d.jsx)(`stop`,{offset:`100%`,style:{stopColor:t,stopOpacity:0}})]})}var x=[.42,.58,.35,.7,.52,.8,.46,.64,.55,.74,.5,.62],S=[.55,.6,.48,.52,.4,.46,.36,.42,.3,.34,.28],C=600;function ne(e,t){let n=C,r=[.25,.5,.75].map(e=>(0,d.jsx)(`line`,{className:f.skeletonGrid,x1:0,x2:n,y1:t*e,y2:t*e},`g${e}`));switch(e){case`bars`:{let e=n/x.length;return(0,d.jsxs)(d.Fragment,{children:[r,x.map((n,r)=>(0,d.jsx)(`rect`,{className:f.skeletonMark,x:r*e+e*.25,width:e*.5,y:t-t*n*.9,height:t*n*.9,rx:3},r))]})}case`lanes`:{let e=Math.max(2,Math.min(6,Math.floor(t/32))),n=t/e;return Array.from({length:e},(e,t)=>(0,d.jsxs)(`g`,{children:[(0,d.jsx)(`rect`,{className:f.skeletonMark,x:0,y:t*n+n*.3,width:90,height:n*.4,rx:3}),(0,d.jsx)(`rect`,{className:f.skeletonMark,x:130+t*97%180,y:t*n+n*.25,width:120+t*53%200,height:n*.5,rx:3})]},t))}case`funnel`:{let e=t/5;return Array.from({length:5},(t,n)=>(0,d.jsxs)(`g`,{children:[(0,d.jsx)(`rect`,{className:f.skeletonTrack,x:140,y:n*e+e*.2,width:360,height:e*.6,rx:4}),(0,d.jsx)(`rect`,{className:f.skeletonMark,x:140,y:n*e+e*.2,width:360*(1-n*.18),height:e*.6,rx:4})]},n))}case`heat`:{let e=n/20,r=t/7;return Array.from({length:140},(t,n)=>(0,d.jsx)(`rect`,{className:n*7%5==0?f.skeletonMark:f.skeletonTrack,x:n%20*e+1.5,y:Math.floor(n/20)*r+1.5,width:27,height:r-3,rx:2},n))}case`gauge`:return(0,d.jsx)(`circle`,{className:f.skeletonMark,cx:n/2,cy:t/2,r:t/2});default:{let e=n/(S.length-1),i=S.map((n,r)=>`${r===0?`M`:`L`}${r*e},${t*n}`).join(` `);return(0,d.jsxs)(d.Fragment,{children:[r,(0,d.jsx)(`path`,{className:f.skeletonMark,d:`${i} L${n},${t} L0,${t} Z`})]})}}}function w({shape:e=`line`,height:t=200}){let n=Math.max(48,t);return(0,d.jsx)(`svg`,{className:f.skeleton,"data-chart-skeleton":e,width:`100%`,height:n,viewBox:`0 0 ${C} ${n}`,preserveAspectRatio:e===`gauge`?`xMidYMid meet`:`none`,"aria-hidden":`true`,focusable:`false`,children:ne(e,n)})}function T(e,t,n=4,r={}){if(!Number.isFinite(e)||!Number.isFinite(t))return[0];if(t<e&&([e,t]=[t,e]),t===e){if(t===0)return[0,1];let i=Math.abs(t)*.5;return T(Math.min(0,e-i),t+i,n,r)}let i=(t-e)/Math.max(1,n),a=10**Math.floor(Math.log10(i)),o=i/a,s=(o<=1?1:o<=2?2:o<=2.5?a>=10?2.5:2:o<=5?5:10)*a;r.integer&&s<1&&(s=1),r.minStep!==void 0&&Number.isFinite(r.minStep)&&s<r.minStep&&(s=r.minStep);let c=Math.floor(e/s)*s,l=Math.ceil(t/s)*s,u=Math.round((l-c)/s),d=Math.max(0,-Math.floor(Math.log10(s))+1),f=[];for(let e=0;e<=u;e++)f.push(Number((c+e*s).toFixed(d))||0);return f}function re(e){return e.every(e=>Number.isInteger(e))}function E(e,t){return new Set(t).size===t.length&&e.every((e,n)=>{if(e===0)return!0;let r=/\d[\d,]*(?:\.\d+)?/.exec(t[n]??``);if(!r)return!0;let i=Number(r[0].replace(/,/g,``));if(!Number.isFinite(i)||i===0)return!1;let a=i/Math.abs(e),o=10**Math.round(Math.log10(a));return Math.abs(a/o-1)<1e-6})}function D(e,t,n={}){let r=Math.max(1,n.count??4),i=n.integer===!0,a=n.format,o=(n,r,i)=>{let o=T(e,t,n,{integer:r,minStep:i}),c=o.length>1?o[1]-o[0]:1;if(a)return{ticks:o,labels:o.map(e=>a(e)),step:c};let u=l(o,c);return{ticks:o,labels:o.map(e=>s(e,c,u)),step:c}},c=o(r,i);if(!n.format||E(c.ticks,c.labels)||!Number.isFinite(e)||!Number.isFinite(t)||!(c.step>0))return c;let u=(e,t)=>{for(let n=r;n>=1;n--){let r=o(n,e,t);if(E(r.ticks,r.labels))return r}return null},d=u(i);if(d)return d;let f=Math.max(Math.abs(e),Math.abs(t),1);for(let e=Math.floor(Math.log10(c.step))+1;10**e<=f*10;e++){let t=u(i,Number((10**e).toPrecision(1)));if(t)return t}return u(!0)??c}function O(e){let t=t=>{let n=e(t).trim();if(!n.endsWith(`%`))return null;let r=Number(n.slice(0,-1).replace(/[,\s+]/g,``));return Number.isFinite(r)?r:null};return t(50)===50?100:t(.5)===50?1:null}function k(e){return Number.isFinite(e)&&e>=9466848e5}function A(e){return e.some(k)}function ie(e){return A(e)?k:Number.isFinite}var ae=6e5;function oe(e,t,n,r=`center`){if(t<e&&([e,t]=[t,e]),t-e>=n)return[e,t];if(r===`end`)return[t-n,t];let i=(e+t)/2;return[i-n/2,i+n/2]}var j=12*.6;function M(e){return Number.isFinite(e)&&e>0?e:1}function se(e=1){return j*M(e)}function ce(e,t=j){return e.length*t}var le=7;function ue(e,t,n,r=1){let i=M(r),a=Math.max(0,...e.map(e=>e.length));return Math.min(n*i,Math.max(t,a*le*i+10))}function de(e,t,n){let r=n.gap??8,i=e.map((e,t)=>({s:e,i:t})).sort((e,t)=>t.s.priority-e.s.priority||e.i-t.i),a=[];for(let{s:e,i:o}of i){let i=e.variants[Math.min(t,e.variants.length-1)]??``;if(!i)continue;let s=ce(i,n.charPx);if(s>n.max-n.min)continue;let c=e.anchor===`start`?e.x:e.anchor===`end`?e.x-s:e.x-s/2,l=e.x,u=e.anchor;c<n.min?(c=n.min,l=n.min,u=`start`):c+s>n.max&&(c=n.max-s,l=n.max,u=`end`);let d=c+s;a.some(e=>e.text===i||c<e.right+r&&e.left<d+r)||a.push({left:c,right:d,text:i,i:o,label:{key:e.key,text:i,x:l,anchor:u}})}return a.sort((e,t)=>e.i-t.i).map(e=>e.label)}function fe(e,t){if(e.length===0)return[];let n=Math.max(1,...e.map(e=>e.variants.length)),r=new Set(e.filter(e=>e.required!==!1).map(e=>e.key)),i=[],a=-1;for(let o=0;o<n;o++){let n=de(e,o,t),s=n.filter(e=>r.has(e.key)).length;if(s>a&&(i=n,a=s),a===r.size)break}return i}function pe(e,t,n,r){if(e.length===0)return new Map;if((e.length-1)*t>r-n+1e-9)return null;let i=e.map((e,t)=>({...e,i:t})).sort((e,t)=>e.y-t.y||e.i-t.i),a=e=>{let i=e.reduce((e,t)=>e+t.y,0)/e.length,a=(e.length-1)*t;return{members:e,top:P(i-a/2,n,r-a)}},o=i.map(e=>a([e]));for(let e=!0;e;){e=!1;for(let n=0;n+1<o.length;n++){let r=o[n],i=o[n+1];if(r.top+r.members.length*t>i.top+1e-9){o=[...o.slice(0,n),a([...r.members,...i.members]),...o.slice(n+2)],e=!0;break}}}let s=new Map;for(let e of o)e.members.forEach((n,r)=>s.set(n.key,e.top+r*t));return s}function me(e,t,n,r){let i=t-e;return i===0?()=>(n+r)/2:t=>n+(t-e)/i*(r-n)}function N(e,t){if(e<=0)return[];if(t<=1)return[e-1];if(e<=t)return Array.from({length:e},(e,t)=>t);let n=Math.ceil((e-1)/(t-1)),r=[];for(let t=e-1;t>=0;t-=n)r.push(t);return r.reverse()}function P(e,t,n){return Math.min(n,Math.max(t,e))}function F(e){let t=[],n=[];for(let r of e){if(r.y===null||!Number.isFinite(r.y)){n.length&&t.push(n),n=[];continue}n.push({x:r.x,y:r.y})}return n.length&&t.push(n),t}function I(e){return e.map((e,t)=>`${t===0?`M`:`L`}${L(e.x)},${L(e.y)}`).join(` `)}function L(e){return Math.round(e*10)/10}function R(e){return Math.floor(e)+.5}function z(e){return e<0?-1:1}function he(e,t,n){let r=t.x-e.x,i=n.x-t.x;if(r===0||i===0)return 0;let a=(t.y-e.y)/r,o=(n.y-t.y)/i,s=(a*i+o*r)/(r+i);return(z(a)+z(o))*Math.min(Math.abs(a),Math.abs(o),.5*Math.abs(s))||0}function B(e,t,n){let r=t.x-e.x;return r?(3*(t.y-e.y)/r-n)/2:n}function V(e){let t=e.length;if(t<2)return[];if(t===2){let[t,n]=[e[0],e[1]];return[{from:t,c1:{x:t.x+(n.x-t.x)/3,y:t.y+(n.y-t.y)/3},c2:{x:n.x-(n.x-t.x)/3,y:n.y-(n.y-t.y)/3},to:n}]}let n=Array(t).fill(0);for(let r=1;r<t-1;r++)n[r]=he(e[r-1],e[r],e[r+1]);n[0]=B(e[0],e[1],n[1]),n[t-1]=B(e[t-1],e[t-2],n[t-2]);let r=[];for(let i=0;i<t-1;i++){let t=e[i],a=e[i+1],o=(a.x-t.x)/3;r.push({from:t,c1:{x:t.x+o,y:t.y+o*n[i]},c2:{x:a.x-o,y:a.y-o*n[i+1]},to:a})}return r}function H(e){return`${L(e.x)},${L(e.y)}`}function U(e){return e.length===0?``:`M${H(e[0])}`+V(e).map(e=>` C${H(e.c1)} ${H(e.c2)} ${H(e.to)}`).join(``)}function ge(e,t){if(e.length===0)return``;let n=V(t).reverse(),r=n.length?`L${H(n[0].to)}`+n.map(e=>` C${H(e.c2)} ${H(e.c1)} ${H(e.from)}`).join(``):t.length?`L${H(t[0])}`:``;return`${U(e)} ${r} Z`}function _e(e){let t=0,n=!1,r=0,i=[];return e.forEach((e,a)=>{if(e===null||!Number.isFinite(e)){n=!0;return}r++;let o=Math.max(0,e);o>0&&i.push({index:a,value:o,y0:t,y1:t+o}),t+=o}),{segments:i,total:t,incomplete:n,unknown:r===0&&e.length>0}}function ve(e,t,n,r,i=4){if(r<=0||n<=0)return``;let a=Math.max(0,Math.min(i,n/2,r));return[`M${L(e)},${L(t+r)}`,`L${L(e)},${L(t+a)}`,`Q${L(e)},${L(t)} ${L(e+a)},${L(t)}`,`L${L(e+n-a)},${L(t)}`,`Q${L(e+n)},${L(t)} ${L(e+n)},${L(t+a)}`,`L${L(e+n)},${L(t+r)}`,`Z`].join(` `)}function ye(e,t,n,r,i=4){if(r<=0||n<=0)return``;let a=Math.max(0,Math.min(i,r/2,n));return[`M${L(e)},${L(t)}`,`L${L(e+n-a)},${L(t)}`,`Q${L(e+n)},${L(t)} ${L(e+n)},${L(t+a)}`,`L${L(e+n)},${L(t+r-a)}`,`Q${L(e+n)},${L(t+r)} ${L(e+n-a)},${L(t+r)}`,`L${L(e)},${L(t+r)}`,`Z`].join(` `)}function be(e){let t=e[0]??null;return e.map((n,r)=>{let i=r>0?e[r-1]??null:null;return{value:n,ofFirst:n!==null&&t!==null&&t>0?n/t:null,ofPrevious:r>0&&n!==null&&i!==null&&i>0?n/i:null}})}var xe=[`Jan`,`Feb`,`Mar`,`Apr`,`May`,`Jun`,`Jul`,`Aug`,`Sep`,`Oct`,`Nov`,`Dec`];function Se(e){if(!/^\d{4}-\d{2}-\d{2}$/.test(e))return null;let t=Date.parse(`${e}T00:00:00Z`);return Number.isFinite(t)&&new Date(t).toISOString().slice(0,10)===e?t:null}function Ce(e,t=1){let n=new Map,r=1/0,i=-1/0;for(let t of e){let e=Se(t.day);e===null||e<9466848e5||(n.set(t.day,t.value),r=Math.min(r,e),i=Math.max(i,e))}if(!Number.isFinite(r))return{cells:[],weeks:0,months:[]};let a=864e5,o=(new Date(r).getUTCDay()-t+7)%7,s=r-o*a,c=(new Date(i).getUTCDay()-t+7)%7,l=i+(6-c)*a,u=[],d=[],f=-1;for(let e=s,t=0;e<=l;e+=a,t++){let a=new Date(e).toISOString().slice(0,10),o=Math.floor(t/7),s=t%7,c=e<r||e>i;u.push({day:a,value:c?null:n.has(a)?n.get(a):null,week:o,weekday:s,outside:c});let l=new Date(e).getUTCMonth();!c&&l!==f&&(d.push({week:o,label:xe[l]}),f=l)}return{cells:u,weeks:Math.floor((l-s)/a/7)+1,months:d}}function we(e,t,n=4){return e===null||!Number.isFinite(e)?null:e<=0||t<=0?0:P(Math.ceil(e/t*n),1,n)}function Te(e,t,n={}){let r=t!==null&&Number.isFinite(t)?t:null,i=e.filter(e=>e.remaining!==null&&Number.isFinite(e.remaining)&&Number.isFinite(e.t)).sort((e,t)=>e.t-t.t),a=i.length?i[i.length-1]:null,o=i.slice(-(n.window??6));if(!a||o.length<2)return{slopePerMs:null,exhaustAt:null,reserveAt:null,remainingAtReset:null,from:a};let s=o.length,c=o.reduce((e,t)=>e+t.t,0)/s,l=o.reduce((e,t)=>e+t.remaining,0)/s,u=0,d=0;for(let e of o)u+=(e.t-c)*(e.remaining-l),d+=(e.t-c)**2;let f=d===0?0:u/d,p=e=>{if(a.remaining<=e)return a.t;if(f>=0||r===null)return null;let t=a.t+(e-a.remaining)/f;return t<=r?t:null},m=n.reserve??null;return{slopePerMs:f,exhaustAt:p(0),reserveAt:m===null?null:p(m),remainingAtReset:r===null?null:Math.max(0,a.remaining+f*Math.max(0,r-a.t)),from:a}}function W(e,t,n,r){return{x:e+n*Math.cos(r),y:t-n*Math.sin(r)}}function Ee(e,t,n,r,i){let a=P(r,0,1),o=P(i,0,1);if(o<=a)return``;let s=W(e,t,n,Math.PI*(1-a)),c=W(e,t,n,Math.PI*(1-o));return`M${L(s.x)},${L(s.y)} A${n},${n} 0 0 1 ${L(c.x)},${L(c.y)}`}function De(e,t,n){return e===null||!Number.isFinite(e)?`unknown`:e>=n?`danger`:e>=t?`warn`:`ok`}function Oe(){if(typeof document<`u`){let e=document.documentElement.getAttribute(`data-motion`);if(e===`reduce`)return!0;if(e===`full`)return!1}if(typeof window>`u`||typeof window.matchMedia!=`function`)return!1;try{return window.matchMedia(`(prefers-reduced-motion: reduce)`).matches}catch{return!1}}function ke(){let[e]=(0,u.useState)(()=>Oe()?`static`:`enter`);return e}function Ae(e,t,n=640){let[r,i]=(0,u.useState)(null),[a,o]=(0,u.useState)(null);return(0,u.useLayoutEffect)(()=>{e.current!==a&&o(e.current)}),(0,u.useLayoutEffect)(()=>{if(t!==void 0)return;let e=a;if(!e)return;let n=()=>{let t=Math.floor(e.getBoundingClientRect().width);t>0&&i(e=>e===t?e:t)};if(n(),typeof ResizeObserver>`u`)return;let r=0,o=new ResizeObserver(()=>{cancelAnimationFrame(r),r=requestAnimationFrame(n)});return o.observe(e),()=>{cancelAnimationFrame(r),o.disconnect()}},[a,t]),Math.max(280,t??r??n)}function G(e=typeof document>`u`?null:document.documentElement){return!e||typeof getComputedStyle!=`function`?1:M(Number.parseFloat(getComputedStyle(e).getPropertyValue(`--ui-text-scale`)))}var K=new Set,q=null,J=null;function Y(){let e=G();if(e!==q){q=e;for(let e of K)e()}}function je(){q=G();let e=document.documentElement,t=typeof MutationObserver>`u`?null:new MutationObserver(Y);t?.observe(e,{attributes:!0,attributeFilter:[`data-ui-scale`,`style`]});let n=typeof requestAnimationFrame==`function`,r=0,i=()=>{if(!n)return Y();cancelAnimationFrame(r),r=requestAnimationFrame(Y)};return window.addEventListener(`resize`,i),()=>{t?.disconnect(),n&&cancelAnimationFrame(r),window.removeEventListener(`resize`,i)}}function Me(e){return K.add(e),K.size===1&&typeof document<`u`&&(J=je()),()=>{K.delete(e),!(K.size>0)&&(J?.(),J=null,q=null)}}function Ne(){return q??G()}function X(){return(0,u.useSyncExternalStore)(Me,Ne,()=>1)}var Z={table:`_table_x2yvy_1`,numeric:`_numeric_x2yvy_22`,empty:`_empty_x2yvy_27`};function Pe({caption:e,columns:t,rows:n,rowKey:r,emptyMessage:i=`No rows.`}){return(0,d.jsxs)(`table`,{className:Z.table,children:[(0,d.jsx)(`caption`,{className:`visually-hidden`,children:e}),(0,d.jsx)(`thead`,{children:(0,d.jsx)(`tr`,{children:t.map(e=>(0,d.jsx)(`th`,{scope:`col`,className:e.numeric?Z.numeric:void 0,children:e.label},e.key))})}),(0,d.jsxs)(`tbody`,{children:[n.length===0?(0,d.jsx)(`tr`,{children:(0,d.jsx)(`td`,{colSpan:Math.max(1,t.length),className:Z.empty,children:i})}):null,n.map((e,n)=>(0,d.jsx)(`tr`,{children:t.map(t=>(0,d.jsx)(`td`,{className:t.numeric?Z.numeric:void 0,children:t.render(e)},t.key))},r(e,n)))]})]})}var Q={frame:`_frame_4uyc2_1`,header:`_header_4uyc2_11`,actions:`_actions_4uyc2_23`,menuWrap:`_menuWrap_4uyc2_31`,more:`_more_4uyc2_37`,menu:`_menu_4uyc2_31`,menuItem:`_menuItem_4uyc2_78`,check:`_check_4uyc2_100`,hint:`_hint_4uyc2_105`,heading:`_heading_4uyc2_17`,title:`_title_4uyc2_123`,description:`_description_4uyc2_129`,plot:`_plot_4uyc2_134`,table:`_table_4uyc2_140`,caveat:`_caveat_4uyc2_145`,state:`_state_4uyc2_155`,loading:`_loading_4uyc2_164`,dark:`_dark_4uyc2_170`,darkTitle:`_darkTitle_4uyc2_177`,darkBody:`_darkBody_4uyc2_183`,unknown:`_unknown_4uyc2_189`};function Fe(e){if(/^\d{4}-\d{2}-\d{2}$/.test(e))return o(e);let t=Date.parse(e);return Number.isFinite(t)?c(t):o(e.slice(0,10))}function Ie({status:e,skeleton:t,skeletonHeight:n}){switch(e.kind){case`loading`:return(0,d.jsxs)(`div`,{className:Q.loading,role:`status`,"aria-busy":`true`,children:[(0,d.jsx)(w,{shape:t,height:n}),(0,d.jsx)(`span`,{className:`visually-hidden`,children:`Loading…`})]});case`empty`:return(0,d.jsx)(`p`,{className:Q.state,children:e.message??`Nothing happened in this window.`});case`dark`:return(0,d.jsxs)(`div`,{className:`${Q.state} ${Q.dark}`,children:[(0,d.jsxs)(`p`,{className:Q.darkTitle,children:[e.subject??`Fleet`,` dark since `,Fe(e.since)]}),(0,d.jsx)(`p`,{className:Q.darkBody,children:e.detail??`No runs or proposals have been recorded since then.`})]});case`unknown`:return(0,d.jsxs)(`p`,{className:`${Q.state} ${Q.unknown}`,role:`note`,children:[`Unknown — `,e.reason??`the data source could not be read.`,` Nothing is shown rather than a guess.`]})}}function Le(e){if(!(e instanceof HTMLElement))return!1;let t=e.tagName;return t===`INPUT`||t===`TEXTAREA`||t===`SELECT`||e.isContentEditable}var $=[{view:`chart`,label:`Show as chart`,hint:null},{view:`table`,label:`Show as table`,hint:`T`}];function Re({title:e,view:t,onPick:n}){let[r,i]=(0,u.useState)(!1),[a,o]=(0,u.useState)(0),s=(0,u.useRef)(null),c=(0,u.useRef)(null),l=(0,u.useId)(),f=(0,u.useCallback)(e=>{i(!1),e&&s.current?.focus()},[]);(0,u.useEffect)(()=>{if(!r)return;let e=e=>{let t=e.target;t&&(c.current?.contains(t)||s.current?.contains(t))||i(!1)};return document.addEventListener(`pointerdown`,e),()=>document.removeEventListener(`pointerdown`,e)},[r]),(0,u.useEffect)(()=>{r&&c.current?.querySelectorAll(`[role="menuitemradio"]`)[a]?.focus()},[r,a]);function p(e){o(e),i(!0)}function m(e){(e.key===`ArrowDown`||e.key===`ArrowUp`)&&(e.preventDefault(),p(e.key===`ArrowUp`?$.length-1:0))}function h(e){e.key===`ArrowDown`?(e.preventDefault(),o(e=>(e+1)%$.length)):e.key===`ArrowUp`?(e.preventDefault(),o(e=>(e-1+$.length)%$.length)):e.key===`Home`?(e.preventDefault(),o(0)):e.key===`End`?(e.preventDefault(),o($.length-1)):e.key===`Escape`?(e.preventDefault(),e.stopPropagation(),f(!0)):e.key===`Tab`&&f(!1)}return(0,d.jsxs)(`span`,{className:Q.menuWrap,children:[(0,d.jsx)(`button`,{ref:s,type:`button`,className:Q.more,"aria-label":`${e}: view options`,"aria-haspopup":`menu`,"aria-expanded":r,"aria-controls":r?l:void 0,title:`View options (T toggles the table)`,onClick:()=>r?f(!1):p(Math.max(0,$.findIndex(e=>e.view===t))),onKeyDown:m,children:(0,d.jsx)(te,{})}),r?(0,d.jsx)(`div`,{ref:c,id:l,role:`menu`,"aria-label":`${e} view`,className:Q.menu,onKeyDown:h,children:$.map((e,r)=>(0,d.jsxs)(`button`,{type:`button`,role:`menuitemradio`,"aria-checked":t===e.view,tabIndex:r===a?0:-1,className:Q.menuItem,onClick:()=>{n(e.view),f(!0)},children:[(0,d.jsx)(`span`,{className:Q.check,"aria-hidden":`true`,children:t===e.view?`✓`:``}),(0,d.jsx)(`span`,{children:e.label}),e.hint?(0,d.jsx)(`kbd`,{className:Q.hint,children:e.hint}):null]},e.view))}):null]})}function ze({title:e,description:t,caveat:n,status:r={kind:`ready`},defaultView:i=`chart`,hideToggle:a=!1,actions:o,children:s,table:c,footer:l,skeleton:f,skeletonHeight:p}){let[m,h]=(0,u.useState)(i),g=(0,u.useId)(),_=r.kind===`ready`,v=_&&!a;function y(e){v&&!e.defaultPrevented&&(e.metaKey||e.ctrlKey||e.altKey||e.shiftKey||e.key.toLowerCase()!==`t`||Le(e.target)||(e.preventDefault(),h(e=>e===`chart`?`table`:`chart`)))}return(0,d.jsxs)(`figure`,{className:Q.frame,"aria-labelledby":g,"data-chart-card":``,"data-view":m,onKeyDown:y,children:[(0,d.jsxs)(`figcaption`,{className:Q.header,children:[(0,d.jsxs)(`span`,{className:Q.heading,children:[(0,d.jsx)(`span`,{id:g,className:Q.title,children:e}),t?(0,d.jsx)(`span`,{className:Q.description,children:t}):null]}),o||v?(0,d.jsxs)(`span`,{className:Q.actions,children:[o,v?(0,d.jsx)(Re,{title:e,view:m,onPick:h}):null]}):null]}),n?(0,d.jsx)(`p`,{className:Q.caveat,role:`note`,children:n}):null,_?m===`table`?(0,d.jsx)(`div`,{className:Q.table,children:c}):(0,d.jsxs)(d.Fragment,{children:[(0,d.jsx)(`div`,{className:Q.plot,children:s}),l]}):(0,d.jsx)(Ie,{status:r,skeleton:f,skeletonHeight:p})]})}export{U as A,ee as B,T as C,ye as D,Te as E,ie as F,v as H,b as I,p as L,_e as M,N,ve as O,ue as P,w as R,me as S,W as T,_ as U,y as V,f as W,k as _,ke as a,fe as b,D as c,pe as d,oe as f,we as g,De as h,Ae as i,F as j,ge as k,Ce as l,Ee as m,Pe as n,ae as o,be as p,X as r,re as s,ze as t,R as u,A as v,O as w,I as x,se as y,m as z};
2
+ //# sourceMappingURL=ChartFrame-DY-GVUb3.js.map