@polderlabs/bizar 7.0.2 → 8.0.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 (490) hide show
  1. package/.claude/settings.local.json +8 -0
  2. package/bizar-dash/DESIGN.md +729 -969
  3. package/bizar-dash/GLYPH.md +418 -0
  4. package/bizar-dash/PLAN.md +1135 -0
  5. package/bizar-dash/dist/assets/ActivityFeed-BRBtQOHB.js +6 -0
  6. package/bizar-dash/dist/assets/ActivityFeed-BRBtQOHB.js.map +1 -0
  7. package/bizar-dash/dist/assets/ActivityView-CwqhxBfh.js +1 -0
  8. package/bizar-dash/dist/assets/ActivityView-CwqhxBfh.js.map +1 -0
  9. package/bizar-dash/dist/assets/AgentActivity-6MxU-a9F.js +1 -0
  10. package/bizar-dash/dist/assets/AgentActivity-6MxU-a9F.js.map +1 -0
  11. package/bizar-dash/dist/assets/AgentsView-BYrOFdwl.js +8 -0
  12. package/bizar-dash/dist/assets/AgentsView-BYrOFdwl.js.map +1 -0
  13. package/bizar-dash/dist/assets/Badge-Cd61wsBa.js +1 -0
  14. package/bizar-dash/dist/assets/Badge-Cd61wsBa.js.map +1 -0
  15. package/bizar-dash/dist/assets/Card-C_bvqXdQ.js +1 -0
  16. package/bizar-dash/dist/assets/Card-C_bvqXdQ.js.map +1 -0
  17. package/bizar-dash/dist/assets/EmptyState-BWQuKnk9.js +1 -0
  18. package/bizar-dash/dist/assets/EmptyState-BWQuKnk9.js.map +1 -0
  19. package/bizar-dash/dist/assets/GoalsView-Dok0yt9S.js +11 -0
  20. package/bizar-dash/dist/assets/GoalsView-Dok0yt9S.js.map +1 -0
  21. package/bizar-dash/dist/assets/Grid-C62gCPqt.js +1 -0
  22. package/bizar-dash/dist/assets/Grid-C62gCPqt.js.map +1 -0
  23. package/bizar-dash/dist/assets/KanbanCard-CtTKP6ZX.js +21 -0
  24. package/bizar-dash/dist/assets/KanbanCard-CtTKP6ZX.js.map +1 -0
  25. package/bizar-dash/dist/assets/LibrariesView-BcyBQXiY.js +67 -0
  26. package/bizar-dash/dist/assets/LibrariesView-BcyBQXiY.js.map +1 -0
  27. package/bizar-dash/dist/assets/MemoryView-49wR4u-y.js +13 -0
  28. package/bizar-dash/dist/assets/MemoryView-49wR4u-y.js.map +1 -0
  29. package/bizar-dash/dist/assets/OverviewView-BtQ_UWYj.js +1 -0
  30. package/bizar-dash/dist/assets/OverviewView-BtQ_UWYj.js.map +1 -0
  31. package/bizar-dash/dist/assets/ProgressBar-CpvDeq9F.js +1 -0
  32. package/bizar-dash/dist/assets/ProgressBar-CpvDeq9F.js.map +1 -0
  33. package/bizar-dash/dist/assets/SettingsRow-DmIe5OUu.js +30 -0
  34. package/bizar-dash/dist/assets/SettingsRow-DmIe5OUu.js.map +1 -0
  35. package/bizar-dash/dist/assets/SettingsView-D1KmGWbi.js +48 -0
  36. package/bizar-dash/dist/assets/SettingsView-D1KmGWbi.js.map +1 -0
  37. package/bizar-dash/dist/assets/StatTile-BkIP32gG.js +11 -0
  38. package/bizar-dash/dist/assets/StatTile-BkIP32gG.js.map +1 -0
  39. package/bizar-dash/dist/assets/TasksView-Cba3GJ42.js +1 -0
  40. package/bizar-dash/dist/assets/TasksView-Cba3GJ42.js.map +1 -0
  41. package/bizar-dash/dist/assets/ViewHeader-D6c2cw1b.js +6 -0
  42. package/bizar-dash/dist/assets/ViewHeader-D6c2cw1b.js.map +1 -0
  43. package/bizar-dash/dist/assets/brain-DeoXNDE2.js +6 -0
  44. package/bizar-dash/dist/assets/brain-DeoXNDE2.js.map +1 -0
  45. package/bizar-dash/dist/assets/calendar-DRlQkGJc.js +6 -0
  46. package/bizar-dash/dist/assets/calendar-DRlQkGJc.js.map +1 -0
  47. package/bizar-dash/dist/assets/circle-check-DmYQ3vGp.js +6 -0
  48. package/bizar-dash/dist/assets/circle-check-DmYQ3vGp.js.map +1 -0
  49. package/bizar-dash/dist/assets/cmdk-BwN8hcKQ.js +80 -0
  50. package/bizar-dash/dist/assets/cmdk-BwN8hcKQ.js.map +1 -0
  51. package/bizar-dash/dist/assets/dnd-kit-DR2Qzzxk.js +5 -0
  52. package/bizar-dash/dist/assets/dnd-kit-DR2Qzzxk.js.map +1 -0
  53. package/bizar-dash/dist/assets/git-merge-OoqBKQer.js +6 -0
  54. package/bizar-dash/dist/assets/git-merge-OoqBKQer.js.map +1 -0
  55. package/bizar-dash/dist/assets/git-pull-request-CXBQTR2f.js +6 -0
  56. package/bizar-dash/dist/assets/git-pull-request-CXBQTR2f.js.map +1 -0
  57. package/bizar-dash/dist/assets/main-COdgjqbZ.css +1 -0
  58. package/bizar-dash/dist/assets/main-Cw6gybzS.js +109 -0
  59. package/bizar-dash/dist/assets/main-Cw6gybzS.js.map +1 -0
  60. package/bizar-dash/dist/assets/message-square-DUTeIQAR.js +6 -0
  61. package/bizar-dash/dist/assets/message-square-DUTeIQAR.js.map +1 -0
  62. package/bizar-dash/dist/assets/minus-CrStJTZ7.js +6 -0
  63. package/bizar-dash/dist/assets/minus-CrStJTZ7.js.map +1 -0
  64. package/bizar-dash/dist/assets/wrench-BJ1WIC4u.js +6 -0
  65. package/bizar-dash/dist/assets/wrench-BJ1WIC4u.js.map +1 -0
  66. package/bizar-dash/dist/{mobile.html → v8.html} +6 -9
  67. package/bizar-dash/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +1 -0
  68. package/bizar-dash/src/server/server.mjs +1 -57
  69. package/bizar-dash/src/web/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +1 -0
  70. package/bizar-dash/src/web/v8/App.tsx +188 -0
  71. package/bizar-dash/src/web/v8/__tests__/App.test.tsx +102 -0
  72. package/bizar-dash/src/web/v8/__tests__/AppShell.test.tsx +79 -0
  73. package/bizar-dash/src/web/v8/__tests__/PageSkeleton.test.tsx +12 -0
  74. package/bizar-dash/src/web/v8/__tests__/SettingsView.test.tsx +84 -0
  75. package/bizar-dash/src/web/v8/__tests__/Sidebar.test.tsx +95 -0
  76. package/bizar-dash/src/web/v8/__tests__/activity.test.tsx +63 -0
  77. package/bizar-dash/src/web/v8/__tests__/agents.test.tsx +90 -0
  78. package/bizar-dash/src/web/v8/__tests__/controls.test.tsx +135 -0
  79. package/bizar-dash/src/web/v8/__tests__/cx.test.ts +25 -0
  80. package/bizar-dash/src/web/v8/__tests__/data.test.tsx +293 -0
  81. package/bizar-dash/src/web/v8/__tests__/feedback.test.tsx +213 -0
  82. package/bizar-dash/src/web/v8/__tests__/goals.test.tsx +105 -0
  83. package/bizar-dash/src/web/v8/__tests__/kanban.test.tsx +176 -0
  84. package/bizar-dash/src/web/v8/__tests__/libraries.test.tsx +70 -0
  85. package/bizar-dash/src/web/v8/__tests__/memory.test.tsx +60 -0
  86. package/bizar-dash/src/web/v8/__tests__/navigation.test.tsx +137 -0
  87. package/bizar-dash/src/web/v8/__tests__/settings.test.tsx +104 -0
  88. package/bizar-dash/src/web/v8/__tests__/theme.test.tsx +98 -0
  89. package/bizar-dash/src/web/v8/__tests__/views.test.tsx +112 -0
  90. package/bizar-dash/src/web/v8/main.tsx +28 -0
  91. package/bizar-dash/src/web/v8/shell/AppShell.tsx +90 -0
  92. package/bizar-dash/src/web/v8/shell/PageSkeleton.tsx +29 -0
  93. package/bizar-dash/src/web/v8/shell/Sidebar.tsx +361 -0
  94. package/bizar-dash/src/web/v8/shell/StatusBar.tsx +63 -0
  95. package/bizar-dash/src/web/v8/shell/Topbar.tsx +113 -0
  96. package/bizar-dash/src/web/v8/shell/index.ts +15 -0
  97. package/bizar-dash/src/web/v8/ui/activity/ActivityFeed.tsx +137 -0
  98. package/bizar-dash/src/web/v8/ui/agents/AgentActivity.tsx +101 -0
  99. package/bizar-dash/src/web/v8/ui/agents/AgentCard.tsx +158 -0
  100. package/bizar-dash/src/web/v8/ui/controls/Button.tsx +141 -0
  101. package/bizar-dash/src/web/v8/ui/controls/ButtonGroup.tsx +32 -0
  102. package/bizar-dash/src/web/v8/ui/controls/Checkbox.tsx +49 -0
  103. package/bizar-dash/src/web/v8/ui/controls/Field.tsx +78 -0
  104. package/bizar-dash/src/web/v8/ui/controls/Form.tsx +23 -0
  105. package/bizar-dash/src/web/v8/ui/controls/IconButton.tsx +112 -0
  106. package/bizar-dash/src/web/v8/ui/controls/Input.tsx +94 -0
  107. package/bizar-dash/src/web/v8/ui/controls/RadioGroup.tsx +74 -0
  108. package/bizar-dash/src/web/v8/ui/controls/Select.tsx +171 -0
  109. package/bizar-dash/src/web/v8/ui/controls/Slider.tsx +68 -0
  110. package/bizar-dash/src/web/v8/ui/controls/Switch.tsx +56 -0
  111. package/bizar-dash/src/web/v8/ui/controls/Textarea.tsx +64 -0
  112. package/bizar-dash/src/web/v8/ui/controls/Toggle.tsx +36 -0
  113. package/bizar-dash/src/web/v8/ui/controls/ToggleGroup.tsx +85 -0
  114. package/bizar-dash/src/web/v8/ui/data/Accordion.tsx +134 -0
  115. package/bizar-dash/src/web/v8/ui/data/Avatar.tsx +175 -0
  116. package/bizar-dash/src/web/v8/ui/data/Badge.tsx +93 -0
  117. package/bizar-dash/src/web/v8/ui/data/BarList.tsx +101 -0
  118. package/bizar-dash/src/web/v8/ui/data/Card.tsx +140 -0
  119. package/bizar-dash/src/web/v8/ui/data/Chip.tsx +96 -0
  120. package/bizar-dash/src/web/v8/ui/data/Kbd.tsx +42 -0
  121. package/bizar-dash/src/web/v8/ui/data/ProgressBar.tsx +93 -0
  122. package/bizar-dash/src/web/v8/ui/data/Sparkline.tsx +98 -0
  123. package/bizar-dash/src/web/v8/ui/data/StatTile.tsx +150 -0
  124. package/bizar-dash/src/web/v8/ui/data/Table.tsx +170 -0
  125. package/bizar-dash/src/web/v8/ui/data/Timeline.tsx +130 -0
  126. package/bizar-dash/src/web/v8/ui/data/ViewHeader.tsx +122 -0
  127. package/bizar-dash/src/web/v8/ui/feedback/Alert.tsx +95 -0
  128. package/bizar-dash/src/web/v8/ui/feedback/Banner.tsx +39 -0
  129. package/bizar-dash/src/web/v8/ui/feedback/ContextMenu.tsx +143 -0
  130. package/bizar-dash/src/web/v8/ui/feedback/Dialog.tsx +149 -0
  131. package/bizar-dash/src/web/v8/ui/feedback/Drawer.tsx +8 -0
  132. package/bizar-dash/src/web/v8/ui/feedback/DropdownMenu.tsx +231 -0
  133. package/bizar-dash/src/web/v8/ui/feedback/EmptyState.tsx +48 -0
  134. package/bizar-dash/src/web/v8/ui/feedback/Popover.tsx +56 -0
  135. package/bizar-dash/src/web/v8/ui/feedback/Sheet.tsx +103 -0
  136. package/bizar-dash/src/web/v8/ui/feedback/Skeleton.tsx +67 -0
  137. package/bizar-dash/src/web/v8/ui/feedback/Spinner.tsx +30 -0
  138. package/bizar-dash/src/web/v8/ui/feedback/Toast.tsx +66 -0
  139. package/bizar-dash/src/web/v8/ui/feedback/Tooltip.tsx +89 -0
  140. package/bizar-dash/src/web/v8/ui/goals/GoalCard.tsx +176 -0
  141. package/bizar-dash/src/web/v8/ui/goals/KeyResult.tsx +115 -0
  142. package/bizar-dash/src/web/v8/ui/index.ts +322 -0
  143. package/bizar-dash/src/web/v8/ui/kanban/KanbanBoard.tsx +80 -0
  144. package/bizar-dash/src/web/v8/ui/kanban/KanbanCard.tsx +247 -0
  145. package/bizar-dash/src/web/v8/ui/kanban/KanbanColumn.tsx +181 -0
  146. package/bizar-dash/src/web/v8/ui/kanban/KanbanContextMenu.tsx +122 -0
  147. package/bizar-dash/src/web/v8/ui/kanban/KanbanQuickAdd.tsx +141 -0
  148. package/bizar-dash/src/web/v8/ui/libraries/LibraryGrid.tsx +30 -0
  149. package/bizar-dash/src/web/v8/ui/libraries/LibraryItem.tsx +161 -0
  150. package/bizar-dash/src/web/v8/ui/memory/MemoryVault.tsx +144 -0
  151. package/bizar-dash/src/web/v8/ui/navigation/CommandPalette.tsx +224 -0
  152. package/bizar-dash/src/web/v8/ui/navigation/NavLink.tsx +81 -0
  153. package/bizar-dash/src/web/v8/ui/navigation/Pagination.tsx +164 -0
  154. package/bizar-dash/src/web/v8/ui/navigation/Tabs.tsx +128 -0
  155. package/bizar-dash/src/web/v8/ui/navigation/useCommandPaletteHotkey.test.ts +79 -0
  156. package/bizar-dash/src/web/v8/ui/primitives/Box.tsx +144 -0
  157. package/bizar-dash/src/web/v8/ui/primitives/Center.tsx +40 -0
  158. package/bizar-dash/src/web/v8/ui/primitives/Cluster.tsx +67 -0
  159. package/bizar-dash/src/web/v8/ui/primitives/Grid.tsx +104 -0
  160. package/bizar-dash/src/web/v8/ui/primitives/Inline.tsx +77 -0
  161. package/bizar-dash/src/web/v8/ui/primitives/Portal.tsx +33 -0
  162. package/bizar-dash/src/web/v8/ui/primitives/ScrollArea.tsx +62 -0
  163. package/bizar-dash/src/web/v8/ui/primitives/Separator.tsx +42 -0
  164. package/bizar-dash/src/web/v8/ui/primitives/Stack.tsx +73 -0
  165. package/bizar-dash/src/web/v8/ui/primitives/VisuallyHidden.tsx +49 -0
  166. package/bizar-dash/src/web/v8/ui/settings/SettingsNav.tsx +91 -0
  167. package/bizar-dash/src/web/v8/ui/settings/SettingsRow.tsx +88 -0
  168. package/bizar-dash/src/web/v8/ui/settings/SettingsSection.tsx +109 -0
  169. package/bizar-dash/src/web/v8/ui/styles/globals.css +220 -0
  170. package/bizar-dash/src/web/v8/ui/styles/reset.css +57 -0
  171. package/bizar-dash/src/web/v8/ui/styles/tokens.css +217 -0
  172. package/bizar-dash/src/web/v8/ui/theme/DensityProvider.test.tsx +74 -0
  173. package/bizar-dash/src/web/v8/ui/theme/DensityProvider.tsx +66 -0
  174. package/bizar-dash/src/web/v8/ui/theme/ThemeProvider.test.tsx +86 -0
  175. package/bizar-dash/src/web/v8/ui/theme/ThemeProvider.tsx +94 -0
  176. package/bizar-dash/src/web/v8/ui/theme/ThemeToggle.tsx +88 -0
  177. package/bizar-dash/src/web/v8/ui/theme/useDensity.ts +15 -0
  178. package/bizar-dash/src/web/v8/ui/theme/useTheme.ts +16 -0
  179. package/bizar-dash/src/web/v8/ui/utils/cx.ts +19 -0
  180. package/bizar-dash/src/web/v8/views/Activity/ActivityView.tsx +33 -0
  181. package/bizar-dash/src/web/v8/views/Agents/AgentsView.tsx +108 -0
  182. package/bizar-dash/src/web/v8/views/CommandPalette/AppCommandPalette.test.tsx +142 -0
  183. package/bizar-dash/src/web/v8/views/CommandPalette/AppCommandPalette.tsx +144 -0
  184. package/bizar-dash/src/web/v8/views/Goals/GoalsView.tsx +84 -0
  185. package/bizar-dash/src/web/v8/views/Libraries/LibrariesView.tsx +41 -0
  186. package/bizar-dash/src/web/v8/views/Memory/MemoryView.tsx +61 -0
  187. package/bizar-dash/src/web/v8/views/Overview/OverviewView.tsx +92 -0
  188. package/bizar-dash/src/web/v8/views/Router.tsx +96 -0
  189. package/bizar-dash/src/web/v8/views/Settings/SettingsView.tsx +305 -0
  190. package/bizar-dash/src/web/v8/views/Tasks/CommandPalettePlaceholder.tsx +106 -0
  191. package/bizar-dash/src/web/v8/views/Tasks/TasksKanbanPlaceholder.tsx +62 -0
  192. package/bizar-dash/src/web/v8/views/Tasks/TasksView.tsx +74 -0
  193. package/bizar-dash/src/web/v8/vite-env.d.ts +15 -0
  194. package/bizar-dash/src/web/{mobile.html → v8.html} +4 -7
  195. package/bizar-dash/tests/settings-layout.test.tsx +2 -2
  196. package/bizar-dash/tests/settings-nav.test.tsx +6 -6
  197. package/bizar-dash/tests/setup.ts +26 -0
  198. package/bizar-dash/vite.config.ts +26 -2
  199. package/bizar-dash/vitest.config.ts +5 -3
  200. package/cli/provision-claude.mjs +108 -5
  201. package/package.json +36 -3
  202. package/bizar-dash/dist/assets/EnvVarsSection-BfhAz3ax.js +0 -114
  203. package/bizar-dash/dist/assets/EnvVarsSection-BfhAz3ax.js.map +0 -1
  204. package/bizar-dash/dist/assets/MobileChat-DLWdv6tQ.js +0 -1
  205. package/bizar-dash/dist/assets/MobileChat-DLWdv6tQ.js.map +0 -1
  206. package/bizar-dash/dist/assets/MobileSettings-Bxv62uPY.js +0 -1
  207. package/bizar-dash/dist/assets/MobileSettings-Bxv62uPY.js.map +0 -1
  208. package/bizar-dash/dist/assets/Toast-ATSAmbdi.js +0 -26
  209. package/bizar-dash/dist/assets/Toast-ATSAmbdi.js.map +0 -1
  210. package/bizar-dash/dist/assets/__vite-browser-external-BIHI7g3E.js +0 -1
  211. package/bizar-dash/dist/assets/__vite-browser-external-BIHI7g3E.js.map +0 -1
  212. package/bizar-dash/dist/assets/main-306CZfn6.js +0 -430
  213. package/bizar-dash/dist/assets/main-306CZfn6.js.map +0 -1
  214. package/bizar-dash/dist/assets/main-G3bNDpY3.css +0 -1
  215. package/bizar-dash/dist/assets/mobile-C_naUN91.js +0 -1
  216. package/bizar-dash/dist/assets/mobile-C_naUN91.js.map +0 -1
  217. package/bizar-dash/dist/assets/mobile-layout-BWLtwtfQ.css +0 -1
  218. package/bizar-dash/dist/assets/mobile-layout-GZ3bE8L6.js +0 -211
  219. package/bizar-dash/dist/assets/mobile-layout-GZ3bE8L6.js.map +0 -1
  220. package/bizar-dash/dist/assets/useSlashCommands-BOwD7lNb.js +0 -65
  221. package/bizar-dash/dist/assets/useSlashCommands-BOwD7lNb.js.map +0 -1
  222. package/bizar-dash/dist/index.html +0 -43
  223. package/bizar-dash/src/web/App.tsx +0 -915
  224. package/bizar-dash/src/web/MobileApp.tsx +0 -414
  225. package/bizar-dash/src/web/components/ArtifactCreateDialog.tsx +0 -95
  226. package/bizar-dash/src/web/components/ArtifactListDialog.tsx +0 -55
  227. package/bizar-dash/src/web/components/ArtifactViewer.tsx +0 -144
  228. package/bizar-dash/src/web/components/AuditDialog.tsx +0 -79
  229. package/bizar-dash/src/web/components/AutosaveField.tsx +0 -50
  230. package/bizar-dash/src/web/components/BackupRestore.tsx +0 -330
  231. package/bizar-dash/src/web/components/BgStatusBadge.tsx +0 -32
  232. package/bizar-dash/src/web/components/Button.tsx +0 -56
  233. package/bizar-dash/src/web/components/CanvasContextMenu.tsx +0 -68
  234. package/bizar-dash/src/web/components/Card.tsx +0 -40
  235. package/bizar-dash/src/web/components/CollapsibleSection.tsx +0 -72
  236. package/bizar-dash/src/web/components/CommandDialog.tsx +0 -66
  237. package/bizar-dash/src/web/components/DoctorPanel.tsx +0 -160
  238. package/bizar-dash/src/web/components/EmptyState.tsx +0 -30
  239. package/bizar-dash/src/web/components/EnvVarManager.tsx +0 -430
  240. package/bizar-dash/src/web/components/EvalDiff.tsx +0 -157
  241. package/bizar-dash/src/web/components/EvalExportButton.tsx +0 -27
  242. package/bizar-dash/src/web/components/EvalRunCard.tsx +0 -78
  243. package/bizar-dash/src/web/components/FileBrowser.tsx +0 -633
  244. package/bizar-dash/src/web/components/HeadroomSettings.tsx +0 -418
  245. package/bizar-dash/src/web/components/HeadroomStatus.tsx +0 -158
  246. package/bizar-dash/src/web/components/HelpDialog.tsx +0 -55
  247. package/bizar-dash/src/web/components/InviteDialog.tsx +0 -205
  248. package/bizar-dash/src/web/components/KillConfirmDialog.tsx +0 -88
  249. package/bizar-dash/src/web/components/MobileBottomNav.tsx +0 -38
  250. package/bizar-dash/src/web/components/MobileDrawer.tsx +0 -68
  251. package/bizar-dash/src/web/components/MobileHeader.tsx +0 -50
  252. package/bizar-dash/src/web/components/MobileLayout.tsx +0 -63
  253. package/bizar-dash/src/web/components/Modal.tsx +0 -215
  254. package/bizar-dash/src/web/components/Notifications.tsx +0 -242
  255. package/bizar-dash/src/web/components/ScheduleTemplateCard.tsx +0 -72
  256. package/bizar-dash/src/web/components/ScreenshotCapture.tsx +0 -138
  257. package/bizar-dash/src/web/components/ScreenshotOCR.tsx +0 -42
  258. package/bizar-dash/src/web/components/SearchModal.tsx +0 -227
  259. package/bizar-dash/src/web/components/SettingsNav.tsx +0 -112
  260. package/bizar-dash/src/web/components/SettingsSearch.tsx +0 -328
  261. package/bizar-dash/src/web/components/Sidebar.tsx +0 -89
  262. package/bizar-dash/src/web/components/Spinner.tsx +0 -19
  263. package/bizar-dash/src/web/components/StatusBadge.tsx +0 -56
  264. package/bizar-dash/src/web/components/Tag.tsx +0 -41
  265. package/bizar-dash/src/web/components/TailscaleSettings.tsx +0 -161
  266. package/bizar-dash/src/web/components/TaskCard.tsx +0 -69
  267. package/bizar-dash/src/web/components/TaskCreateSheet.tsx +0 -76
  268. package/bizar-dash/src/web/components/Toast.tsx +0 -150
  269. package/bizar-dash/src/web/components/Toggle.tsx +0 -31
  270. package/bizar-dash/src/web/components/Topbar.tsx +0 -410
  271. package/bizar-dash/src/web/components/UsageChart.tsx +0 -250
  272. package/bizar-dash/src/web/components/UsageTable.tsx +0 -90
  273. package/bizar-dash/src/web/components/VirtualList.tsx +0 -53
  274. package/bizar-dash/src/web/components/VisualPlanDialog.tsx +0 -58
  275. package/bizar-dash/src/web/components/VoiceNotesPanel.tsx +0 -211
  276. package/bizar-dash/src/web/components/VoiceRecorder.tsx +0 -105
  277. package/bizar-dash/src/web/components/WorkspaceSelector.tsx +0 -158
  278. package/bizar-dash/src/web/components/agents/CommunicationLog.tsx +0 -126
  279. package/bizar-dash/src/web/components/agents/DependencyGraph.tsx +0 -163
  280. package/bizar-dash/src/web/components/agents/QualityGates.tsx +0 -123
  281. package/bizar-dash/src/web/components/agents/RealTimeEventLog.tsx +0 -127
  282. package/bizar-dash/src/web/components/agents/RoutingDecisions.test.tsx +0 -148
  283. package/bizar-dash/src/web/components/agents/RoutingDecisions.tsx +0 -160
  284. package/bizar-dash/src/web/components/background/AttachButton.tsx +0 -96
  285. package/bizar-dash/src/web/components/background/TmuxAttachCard.tsx +0 -122
  286. package/bizar-dash/src/web/components/chat/AgentChip.tsx +0 -68
  287. package/bizar-dash/src/web/components/chat/AgentNode.tsx +0 -127
  288. package/bizar-dash/src/web/components/chat/AgentTree.tsx +0 -80
  289. package/bizar-dash/src/web/components/chat/ChatBubble.tsx +0 -60
  290. package/bizar-dash/src/web/components/chat/ChatComposer.tsx +0 -72
  291. package/bizar-dash/src/web/components/chat/ChatInfoPanel.tsx +0 -370
  292. package/bizar-dash/src/web/components/chat/ChatRail.tsx +0 -387
  293. package/bizar-dash/src/web/components/chat/ChatThread.tsx +0 -127
  294. package/bizar-dash/src/web/components/chat/ChatTopBar.tsx +0 -50
  295. package/bizar-dash/src/web/components/chat/Composer.tsx +0 -166
  296. package/bizar-dash/src/web/components/chat/ConfirmModal.tsx +0 -54
  297. package/bizar-dash/src/web/components/chat/EmptyState.tsx +0 -21
  298. package/bizar-dash/src/web/components/chat/FirstRunGreeting.tsx +0 -18
  299. package/bizar-dash/src/web/components/chat/FloatingComposer.tsx +0 -38
  300. package/bizar-dash/src/web/components/chat/InfoPanel.tsx +0 -184
  301. package/bizar-dash/src/web/components/chat/JumpToLatest.tsx +0 -58
  302. package/bizar-dash/src/web/components/chat/LoadingSkeleton.tsx +0 -19
  303. package/bizar-dash/src/web/components/chat/MessageBlock.tsx +0 -260
  304. package/bizar-dash/src/web/components/chat/MessageBubble.tsx +0 -60
  305. package/bizar-dash/src/web/components/chat/SessionList.tsx +0 -163
  306. package/bizar-dash/src/web/components/chat/SessionRowMenu.tsx +0 -206
  307. package/bizar-dash/src/web/components/chat/StreamingIndicator.tsx +0 -37
  308. package/bizar-dash/src/web/components/chat/SuggestionCards.tsx +0 -55
  309. package/bizar-dash/src/web/components/chat/WelcomeScreen.tsx +0 -36
  310. package/bizar-dash/src/web/components/chat/_legacy.ts +0 -30
  311. package/bizar-dash/src/web/components/chat/index.ts +0 -31
  312. package/bizar-dash/src/web/components/chat/useAutoGrowTextarea.ts +0 -18
  313. package/bizar-dash/src/web/components/chat/useChat.ts +0 -1190
  314. package/bizar-dash/src/web/components/chat/useSlashCommands.ts +0 -47
  315. package/bizar-dash/src/web/components/goals/GoalInput.tsx +0 -86
  316. package/bizar-dash/src/web/components/goals/PlanVisualization.tsx +0 -111
  317. package/bizar-dash/src/web/components/tasks/BacklogPanel.css +0 -109
  318. package/bizar-dash/src/web/components/tasks/BacklogPanel.tsx +0 -209
  319. package/bizar-dash/src/web/hooks/useAutosave.ts +0 -107
  320. package/bizar-dash/src/web/hooks/useI18n.ts +0 -13
  321. package/bizar-dash/src/web/index.html +0 -37
  322. package/bizar-dash/src/web/lib/api.ts +0 -237
  323. package/bizar-dash/src/web/lib/goapPlanner.ts +0 -614
  324. package/bizar-dash/src/web/lib/i18n.ts +0 -25
  325. package/bizar-dash/src/web/lib/logger.ts +0 -30
  326. package/bizar-dash/src/web/lib/markdown.tsx +0 -59
  327. package/bizar-dash/src/web/lib/search.ts +0 -115
  328. package/bizar-dash/src/web/lib/types.ts +0 -894
  329. package/bizar-dash/src/web/lib/utils.ts +0 -114
  330. package/bizar-dash/src/web/lib/ws.ts +0 -177
  331. package/bizar-dash/src/web/locales/en.json +0 -52
  332. package/bizar-dash/src/web/main.tsx +0 -43
  333. package/bizar-dash/src/web/mobile/MobileApp.tsx +0 -309
  334. package/bizar-dash/src/web/mobile/MobileBottomNav.tsx +0 -38
  335. package/bizar-dash/src/web/mobile/MobileChat.tsx +0 -138
  336. package/bizar-dash/src/web/mobile/MobileDoctor.tsx +0 -80
  337. package/bizar-dash/src/web/mobile/MobileEval.tsx +0 -167
  338. package/bizar-dash/src/web/mobile/MobileMemory.tsx +0 -108
  339. package/bizar-dash/src/web/mobile/MobileOverview.tsx +0 -213
  340. package/bizar-dash/src/web/mobile/MobileSettings.tsx +0 -251
  341. package/bizar-dash/src/web/mobile/MobileTasks.tsx +0 -94
  342. package/bizar-dash/src/web/mobile/MobileTopbar.tsx +0 -115
  343. package/bizar-dash/src/web/mobile/components/MobileBottomSheet.tsx +0 -182
  344. package/bizar-dash/src/web/mobile/components/MobileListItem.tsx +0 -64
  345. package/bizar-dash/src/web/mobile/components/MobileModal.tsx +0 -123
  346. package/bizar-dash/src/web/mobile/views/MobileActivity.tsx +0 -273
  347. package/bizar-dash/src/web/mobile/views/MobileAgents.tsx +0 -374
  348. package/bizar-dash/src/web/mobile/views/MobileArtifactCanvas.tsx +0 -439
  349. package/bizar-dash/src/web/mobile/views/MobileArtifacts.tsx +0 -143
  350. package/bizar-dash/src/web/mobile/views/MobileChat.tsx +0 -257
  351. package/bizar-dash/src/web/mobile/views/MobileConfig.tsx +0 -175
  352. package/bizar-dash/src/web/mobile/views/MobileHistory.tsx +0 -191
  353. package/bizar-dash/src/web/mobile/views/MobileMods.tsx +0 -149
  354. package/bizar-dash/src/web/mobile/views/MobileMore.tsx +0 -121
  355. package/bizar-dash/src/web/mobile/views/MobileNotifications.tsx +0 -137
  356. package/bizar-dash/src/web/mobile/views/MobilePlans.tsx +0 -26
  357. package/bizar-dash/src/web/mobile/views/MobileSchedules.tsx +0 -685
  358. package/bizar-dash/src/web/mobile/views/MobileSearchModal.tsx +0 -172
  359. package/bizar-dash/src/web/mobile/views/MobileSettings.tsx +0 -363
  360. package/bizar-dash/src/web/mobile/views/MobileSkills.tsx +0 -153
  361. package/bizar-dash/src/web/mobile/views/MobileTasks.tsx +0 -564
  362. package/bizar-dash/src/web/mobile/views/QrCodePanel.tsx +0 -69
  363. package/bizar-dash/src/web/mobile.tsx +0 -14
  364. package/bizar-dash/src/web/styles/agents-redesign.css +0 -311
  365. package/bizar-dash/src/web/styles/chat.css +0 -1740
  366. package/bizar-dash/src/web/styles/glyphs.css +0 -960
  367. package/bizar-dash/src/web/styles/main.css +0 -10391
  368. package/bizar-dash/src/web/styles/memory.css +0 -1182
  369. package/bizar-dash/src/web/styles/minimax-usage.css +0 -842
  370. package/bizar-dash/src/web/styles/mobile-chat.css +0 -5
  371. package/bizar-dash/src/web/styles/mobile-layout.css +0 -233
  372. package/bizar-dash/src/web/styles/mobile.css +0 -2181
  373. package/bizar-dash/src/web/styles/settings.css +0 -795
  374. package/bizar-dash/src/web/styles/skills.css +0 -302
  375. package/bizar-dash/src/web/styles/tasks-redesign.css +0 -253
  376. package/bizar-dash/src/web/styles/tasks.css +0 -605
  377. package/bizar-dash/src/web/ui/controls/Button.tsx +0 -77
  378. package/bizar-dash/src/web/ui/controls/Checkbox.tsx +0 -95
  379. package/bizar-dash/src/web/ui/controls/IconButton.tsx +0 -66
  380. package/bizar-dash/src/web/ui/controls/Kbd.tsx +0 -24
  381. package/bizar-dash/src/web/ui/controls/NumberInput.tsx +0 -77
  382. package/bizar-dash/src/web/ui/controls/RadioGroup.tsx +0 -109
  383. package/bizar-dash/src/web/ui/controls/SearchInput.tsx +0 -91
  384. package/bizar-dash/src/web/ui/controls/Select.tsx +0 -92
  385. package/bizar-dash/src/web/ui/controls/Slider.tsx +0 -70
  386. package/bizar-dash/src/web/ui/controls/TextInput.tsx +0 -67
  387. package/bizar-dash/src/web/ui/controls/Textarea.tsx +0 -56
  388. package/bizar-dash/src/web/ui/controls/Toggle.tsx +0 -79
  389. package/bizar-dash/src/web/ui/controls/controls.css +0 -476
  390. package/bizar-dash/src/web/ui/controls/index.ts +0 -35
  391. package/bizar-dash/src/web/ui/data/BarChart.tsx +0 -60
  392. package/bizar-dash/src/web/ui/data/DataTable.tsx +0 -216
  393. package/bizar-dash/src/web/ui/data/EmptyState.tsx +0 -60
  394. package/bizar-dash/src/web/ui/data/ErrorState.tsx +0 -56
  395. package/bizar-dash/src/web/ui/data/KeyValueList.tsx +0 -106
  396. package/bizar-dash/src/web/ui/data/LoadingState.tsx +0 -65
  397. package/bizar-dash/src/web/ui/data/Sparkline.tsx +0 -87
  398. package/bizar-dash/src/web/ui/data/StatTile.tsx +0 -87
  399. package/bizar-dash/src/web/ui/data/data.css +0 -535
  400. package/bizar-dash/src/web/ui/data/index.ts +0 -31
  401. package/bizar-dash/src/web/ui/feedback/Badge.tsx +0 -49
  402. package/bizar-dash/src/web/ui/feedback/Dialog.tsx +0 -209
  403. package/bizar-dash/src/web/ui/feedback/ProgressBar.tsx +0 -69
  404. package/bizar-dash/src/web/ui/feedback/StatusDot.tsx +0 -50
  405. package/bizar-dash/src/web/ui/feedback/Toast.tsx +0 -200
  406. package/bizar-dash/src/web/ui/feedback/Tooltip.tsx +0 -126
  407. package/bizar-dash/src/web/ui/feedback/feedback.css +0 -314
  408. package/bizar-dash/src/web/ui/feedback/index.ts +0 -43
  409. package/bizar-dash/src/web/ui/index.ts +0 -56
  410. package/bizar-dash/src/web/ui/layout/AppShell.tsx +0 -51
  411. package/bizar-dash/src/web/ui/layout/Breadcrumbs.tsx +0 -97
  412. package/bizar-dash/src/web/ui/layout/Panel.tsx +0 -73
  413. package/bizar-dash/src/web/ui/layout/PanelHeader.tsx +0 -39
  414. package/bizar-dash/src/web/ui/layout/Sidebar.tsx +0 -131
  415. package/bizar-dash/src/web/ui/layout/Tabs.tsx +0 -133
  416. package/bizar-dash/src/web/ui/layout/Topbar.tsx +0 -42
  417. package/bizar-dash/src/web/ui/layout/ViewHeader.tsx +0 -48
  418. package/bizar-dash/src/web/ui/layout/index.ts +0 -34
  419. package/bizar-dash/src/web/ui/layout/layout.css +0 -464
  420. package/bizar-dash/src/web/ui/navigation/CommandPalette.tsx +0 -199
  421. package/bizar-dash/src/web/ui/navigation/NavGroup.tsx +0 -95
  422. package/bizar-dash/src/web/ui/navigation/NavLink.tsx +0 -93
  423. package/bizar-dash/src/web/ui/navigation/index.ts +0 -17
  424. package/bizar-dash/src/web/ui/navigation/navigation.css +0 -343
  425. package/bizar-dash/src/web/ui/primitives/Box.tsx +0 -91
  426. package/bizar-dash/src/web/ui/primitives/Grid.tsx +0 -49
  427. package/bizar-dash/src/web/ui/primitives/Inline.tsx +0 -55
  428. package/bizar-dash/src/web/ui/primitives/Separator.tsx +0 -46
  429. package/bizar-dash/src/web/ui/primitives/Stack.tsx +0 -54
  430. package/bizar-dash/src/web/ui/primitives/VisuallyHidden.tsx +0 -26
  431. package/bizar-dash/src/web/ui/primitives/index.ts +0 -23
  432. package/bizar-dash/src/web/ui/primitives/primitives.css +0 -183
  433. package/bizar-dash/src/web/ui/styles/globals.css +0 -86
  434. package/bizar-dash/src/web/ui/styles/reset.css +0 -125
  435. package/bizar-dash/src/web/ui/styles/tokens.css +0 -208
  436. package/bizar-dash/src/web/ui/theme/ThemeProvider.tsx +0 -142
  437. package/bizar-dash/src/web/ui/theme/tokens.ts +0 -131
  438. package/bizar-dash/src/web/ui/theme/useTheme.ts +0 -22
  439. package/bizar-dash/src/web/ui/utils/cx.ts +0 -42
  440. package/bizar-dash/src/web/views/Activity.tsx +0 -1221
  441. package/bizar-dash/src/web/views/Agents.tsx +0 -964
  442. package/bizar-dash/src/web/views/Artifacts.tsx +0 -1494
  443. package/bizar-dash/src/web/views/BackgroundAgents.tsx +0 -822
  444. package/bizar-dash/src/web/views/Chat.tsx +0 -532
  445. package/bizar-dash/src/web/views/Config.tsx +0 -3
  446. package/bizar-dash/src/web/views/Doctor.tsx +0 -317
  447. package/bizar-dash/src/web/views/Eval.tsx +0 -372
  448. package/bizar-dash/src/web/views/EvalReport.tsx +0 -353
  449. package/bizar-dash/src/web/views/GoalPlanner.tsx +0 -158
  450. package/bizar-dash/src/web/views/Harness.tsx +0 -306
  451. package/bizar-dash/src/web/views/History.tsx +0 -353
  452. package/bizar-dash/src/web/views/Memory.tsx +0 -161
  453. package/bizar-dash/src/web/views/MiniMaxUsage.tsx +0 -942
  454. package/bizar-dash/src/web/views/ModView.tsx +0 -207
  455. package/bizar-dash/src/web/views/Mods.tsx +0 -706
  456. package/bizar-dash/src/web/views/Overview.tsx +0 -1364
  457. package/bizar-dash/src/web/views/Providers.tsx +0 -302
  458. package/bizar-dash/src/web/views/Schedules.tsx +0 -902
  459. package/bizar-dash/src/web/views/Settings.tsx +0 -308
  460. package/bizar-dash/src/web/views/Skills.tsx +0 -383
  461. package/bizar-dash/src/web/views/SpawnAgentModal.tsx +0 -221
  462. package/bizar-dash/src/web/views/Tasks.tsx +0 -789
  463. package/bizar-dash/src/web/views/Workspace.tsx +0 -294
  464. package/bizar-dash/src/web/views/glyphs/GlyphRenderer.tsx +0 -844
  465. package/bizar-dash/src/web/views/glyphs/components.tsx +0 -1098
  466. package/bizar-dash/src/web/views/memory/ConfigPanel.tsx +0 -426
  467. package/bizar-dash/src/web/views/memory/FromScreenshotPanel.tsx +0 -23
  468. package/bizar-dash/src/web/views/memory/GitSyncPanel.tsx +0 -220
  469. package/bizar-dash/src/web/views/memory/LightragPanel.tsx +0 -310
  470. package/bizar-dash/src/web/views/memory/MemoryGraphLegend.tsx +0 -29
  471. package/bizar-dash/src/web/views/memory/MemoryGraphPanel.tsx +0 -192
  472. package/bizar-dash/src/web/views/memory/MemoryGraphView.tsx +0 -336
  473. package/bizar-dash/src/web/views/memory/MemoryOverview.tsx +0 -367
  474. package/bizar-dash/src/web/views/memory/MemoryStatusCard.tsx +0 -160
  475. package/bizar-dash/src/web/views/memory/ObsidianPanel.tsx +0 -650
  476. package/bizar-dash/src/web/views/memory/SemanticSearchPanel.tsx +0 -197
  477. package/bizar-dash/src/web/views/memory/VaultFromClipboardPanel.tsx +0 -101
  478. package/bizar-dash/src/web/views/settings/ActivitySection.tsx +0 -205
  479. package/bizar-dash/src/web/views/settings/AgentSection.tsx +0 -305
  480. package/bizar-dash/src/web/views/settings/AuthSection.tsx +0 -159
  481. package/bizar-dash/src/web/views/settings/EnvVarsSection.tsx +0 -15
  482. package/bizar-dash/src/web/views/settings/GeneralSection.tsx +0 -128
  483. package/bizar-dash/src/web/views/settings/HeadroomSection.tsx +0 -39
  484. package/bizar-dash/src/web/views/settings/MemorySection.tsx +0 -154
  485. package/bizar-dash/src/web/views/settings/NetworkSection.tsx +0 -87
  486. package/bizar-dash/src/web/views/settings/NotificationsSection.tsx +0 -34
  487. package/bizar-dash/src/web/views/settings/SystemLlmSection.tsx +0 -81
  488. package/bizar-dash/src/web/views/settings/ThemeSection.tsx +0 -168
  489. package/bizar-dash/src/web/views/settings/UpdatesSection.tsx +0 -256
  490. package/bizar-dash/src/web/views/settings/WorkspacesSection.tsx +0 -189
@@ -1,62 +1,56 @@
1
- # DESIGN.md — Bizar Dashboard
2
-
3
- > The BizarHarness dashboard. Norse-pantheon operator surface, dark-mode
4
- > first, dense by intent. **v7.0** adds the comprehensive view index,
5
- > per-view data shapes, and the patterns needed for the eight secondary
6
- > tabs (Overview, Agents, Active, Skills, Memory, Mods, Schedules,
7
- > Settings) that v6 didn't fully document.
8
-
9
- ## 0 · How to use this file
10
-
11
- This document is the **single source of truth** for visual decisions in
12
- the dashboard. Every component, every color, every animation should be
13
- derivable from the tokens and rules below. If a future change isn't
14
- covered here, **add it to this file first**, then implement it.
15
-
16
- **Token binding.** Components consume CSS variables (`--bg`,
17
- `--text-strong`, `--accent`) defined in `:root` of `styles/main.css`.
18
- Do not hardcode hex outside `:root`. Derive tints with
19
- `color-mix(in oklch, var(--accent) 12%, transparent)` rather than
20
- inventing new tokens.
21
-
22
- **Themes.** The dashboard ships two themes — **dark** (default) and
23
- **light** (`[data-theme="light"]`). Both share the same token names;
24
- only the values change. Every component must read correctly in both
25
- themes without per-component overrides. Tokens are written in
26
- **OKLch** because the lightness/chroma/hue model flips cleanly across
27
- themes without the dark-mode channel separation that hex/rgb needs.
28
-
29
- **Visual contract for new screens.** A new view must:
30
- 1. Sit on one of three layouts (topbar / sidebar / both).
31
- 2. Use tokens from §3-§8 only.
32
- 3. Document its data shape in §15.
33
- 4. Have a P0 entry in the checklist (§14) and pass it.
1
+ # DESIGN.md — Bizar Dashboard v8 (Dashboard Rewrite)
2
+
3
+ > **Scope.** This document replaces the v7.0.0 design system (F-040)
4
+ > and the in-progress mobile pass (F-041) in their entirety. The old
5
+ > dashboard, its `src/web/ui/` primitives, its Norse-pantheon dark
6
+ > aesthetic, its views, and its previous `DESIGN.md` are all **deleted**
7
+ > under the rewrite. v8 ships a new file tree, a new component
8
+ > library, a new theme, a new layout, and a new feature scope.
9
+ >
10
+ > **Read order.** If you only read three sections, read
11
+ > [§1 Principles](#1--principles), [§3 Tokens](#3--design-tokens), and
12
+ > [§7 Layout](#7--layout). Everything else is the supporting cast.
13
+
14
+ ---
15
+
16
+ ## Table of contents
17
+
18
+ 1. [Principles](#1--principles)
19
+ 2. [Brand & voice](#2--brand--voice)
20
+ 3. [Design tokens](#3--design-tokens)
21
+ 4. [Typography](#4--typography)
22
+ 5. [Spacing & layout](#5--spacing--layout)
23
+ 6. [Motion & elevation](#6--motion--elevation)
24
+ 7. [Layout](#7--layout)
25
+ 8. [Component library](#8--component-library)
26
+ 9. [Interaction patterns](#9--interaction-patterns)
27
+ 10. [Settings model](#10--settings-model)
28
+ 11. [Accessibility](#11--accessibility)
29
+ 12. [Banned tropes](#12--banned-tropes)
30
+ 13. [Visual contract for new screens](#13--visual-contract-for-new-screens)
31
+ 14. [Pre-merge checklist](#14--pre-merge-checklist)
34
32
 
35
33
  ---
36
34
 
37
35
  ## 1 · Principles
38
36
 
39
- These five rules govern every visual decision. When in doubt, follow
40
- them in order; if two conflict, the higher rule wins.
41
-
42
- 1. **Operator-quality, not consumer-quality.** Surfaces are dense,
43
- numeric, monospace-friendly. Information per square inch matters
44
- more than breathing room. Whitespace is spent on legibility, not
45
- decoration.
46
- 2. **One accent, used with intent.** The accent earns its place by
47
- signaling primary action, active state, or data emphasis. No AI
48
- gradients. No purple washes behind text. No purple stripes on
49
- container edges.
37
+ Five rules govern every visual decision. When in doubt, follow them
38
+ in order; if two conflict, the higher rule wins.
39
+
40
+ 1. **Data first, chrome last.** Every pixel earns its place by
41
+ carrying information. Whitespace is spent on legibility, not
42
+ decoration. Density targets a desktop operator running two
43
+ external monitors — never a marketing screenshot.
44
+ 2. **One accent, used with intent.** The accent is the green primary
45
+ token (`--accent`). It signals primary action, active state,
46
+ live data, and selection nothing else. There is exactly one
47
+ accent across the entire product.
50
48
  3. **State is signal, not decoration.** Active, streaming, awaiting,
51
- error, success — every state must be distinguishable at a glance
52
- without reading copy. Use weight, glow, motion, and color but
53
- **never vertical accent edges on containers**.
54
- 4. **Type does hierarchy.** `Inter` carries the body, `JetBrains Mono`
55
- carries the metadata. Tabular numerics on every number. Display
56
- sizes scale with container, not viewport. Long copy wraps pretty.
57
- 5. **Layout over chrome.** The sidebar is rail-thin. The topbar is one
58
- row. The chat thread is the product. Chrome that doesn't pay rent
59
- gets removed.
49
+ error, success, offline — every state must be distinguishable at a glance without reading copy. Weight, fill, motion, and shape are the four channels. **Never gradients.** Never `border-left` accent stripes on containers.
50
+ 4. **Type does hierarchy.** A single sans family for UI, a single mono family for data. Size and weight carry the hierarchy; color is secondary. Tabular figures on every number.
51
+ 5. **Native over invented.** The browser already has menus, focus rings, scrollbars, and shortcuts. We add right-click context menus, command palettes, and keyboard shortcuts that wrap the platform — we never replace it.
52
+
53
+ **Anti-target.** v7's Norse-pantheon, dark-by-default, accent-stripe look is rejected. v8 is light-by-default, dark-mode peer, single accent (green), gradient-free, dense by intent.
60
54
 
61
55
  ---
62
56
 
@@ -64,1089 +58,855 @@ them in order; if two conflict, the higher rule wins.
64
58
 
65
59
  | | |
66
60
  |--|--|
67
- | **Wordmark** | Bizar · runic `ᛒ` glyph in `var(--accent)` |
68
- | **Version pill** | mono text on a `var(--accent)` `oklch(0.55 0.22 25)` gradient |
69
- | **Voice** | Direct, technical, never marketing. "404 not found" not "Oops! Something went wrong." Numbers with units. |
70
- | **Tab labels** | Single noun (`Chat`, `Agents`, `Tasks`). No icons-in-paragraphs. |
71
- | **Status copy** | "Streaming" not "Loading…". "Awaiting your reply" not "Ready". "13 of 47" not "Lots". |
72
-
73
- **Banned tropes** (audited before each PR):
74
-
75
- - Aggressive purple gradient backgrounds behind text or as page chrome.
76
- - Vertical accent stripes on containers (`box-shadow: inset 2px 0 0 …`,
77
- `border-left: 3px solid …`). State-encoded or not. Active state uses
78
- background, weight, glow, or motion — **never a left-edge bar**.
79
- - Generic emoji icons in feature lists (✨ 🚀 🎯 ❓). Use Lucide.
80
- - Inter as a display face for hero/section titles (Inter is body;
81
- display uses larger sizes of the same family but tighter tracking).
82
- - Filler copy: "Feature One", "Lorem ipsum", invented metrics.
61
+ | **Wordmark** | `Bizar` set in `Inter` SemiBold, 16px, `var(--fg)` |
62
+ | **Product glyph** | A minimal `ᛒ` (runic Berkanan) in `var(--accent)` for logo and favicon |
63
+ | **Voice** | Direct, technical, never marketing. Numbers with units. Inline code for IDs. |
64
+ | **Tab labels** | Single noun (`Tasks`, `Goals`, `Agents`). No emoji decorations. |
65
+ | **Status copy** | "Streaming" not "Loading…". "13 of 47" not "Lots". "Awaiting reply" not "Ready". |
66
+ | **Errors** | One sentence: what happened + one action the user can take. No "Oops!". |
83
67
 
84
68
  ---
85
69
 
86
- ## 3 · Color tokens
70
+ ## 3 · Design tokens
87
71
 
88
- All values written in OKLch where possible. Hex kept only for legacy
89
- or external-tool interop.
72
+ All values live in `:root` (light) and `.dark` (dark) in `bizar-dash/src/web/ui/styles/tokens.css`. Components consume the CSS custom properties only never raw color values. New tokens get added to this section **before** any component uses them.
90
73
 
91
- ### 3.1 Surface scale (dark, default)
74
+ The user-supplied shadcn preset theme is the source of truth for color tokens. Every other token (spacing, radius, motion, typography) is layered on top.
92
75
 
93
- ```
94
- --bg oklch(15% 0.012 260) #0b0e14 page canvas
95
- --bg-elev oklch(18% 0.012 260) #12161f cards, topbar, sidebars
96
- --bg-elev-2 oklch(22% 0.014 260) #1a1f2b nested surfaces
97
- --bg-elev-3 oklch(27% 0.016 260) #232a39 hover / pressed surfaces
98
- --border oklch(27% 0.016 260) #232a39 hairlines
99
- --border-strong oklch(33% 0.018 260) #2d3648 focus rings, dividers
100
- ```
101
-
102
- `--bg-1` and `--bg-2` from v6.x are deprecated; use `--bg-elev` and
103
- `--bg-elev-2` instead. (The chat composer backdrop uses
104
- `color-mix(in oklch, var(--bg-elev), black 12%)` for that nested feel.)
76
+ ### 3.1 Surface scale
77
+
78
+ | Token | Light (oklch) | Dark (oklch) | Use |
79
+ |--|--|--|--|
80
+ | `--bg` | `oklch(1 0 0)` | `oklch(0.141 0.005 285.823)` | Page canvas |
81
+ | `--surface-1` | `oklch(1 0 0)` | `oklch(0.21 0.006 285.885)` | Cards, topbar, sidebar, dialogs |
82
+ | `--surface-2` | `oklch(0.967 0.001 286.375)` | `oklch(0.274 0.006 286.033)` | Nested surfaces, table rows, hover bg |
83
+ | `--surface-3` | `oklch(0.92 0.004 286.32)` | `oklch(0.37 0.013 285.805)` | Pressed, selected, drag-over |
84
+ | `--surface-popover` | `oklch(1 0 0)` | `oklch(0.21 0.006 285.885)` | Popovers, context menus, command palette |
105
85
 
106
- ### 3.2 Surface scale (light)
107
-
108
- ```
109
- --bg oklch(98% 0.004 240) #f7f8fa
110
- --bg-elev oklch(100% 0 0) #ffffff
111
- --bg-elev-2 oklch(96% 0.006 240) #f0f3f8
112
- --bg-elev-3 oklch(92% 0.008 240) #e6ebf2
113
- --border oklch(90% 0.008 240) #e2e8f0
114
- --border-strong oklch(82% 0.012 240) #cbd5e1
115
- ```
116
86
 
117
- ### 3.3 Text scale
118
-
119
- | Token | Dark (OKLch) | Light (hex) | Use |
120
- |---|---|---|---|
121
- | `--text-strong` | `oklch(96% 0.005 240)` | `#0f172a` | Headings, primary content |
122
- | `--text` | `oklch(82% 0.010 245)` | `#1f2937` | Body |
123
- | `--text-dim` | `oklch(72% 0.012 245)` | `#475569` | Captions, metadata |
124
- | `--text-on-accent` | `oklch(100% 0 0)` | `#ffffff` | Text over accent fills |
125
-
126
- ### 3.4 Brand accent
127
-
128
- | Token | Dark | Light | Use |
129
- |---|---|---|---|
130
- | `--accent` | `oklch(0.62 0.18 273)` | `oklch(0.55 0.20 273)` | Primary action, active state, focus |
131
- | `--accent-2` | `oklch(0.72 0.16 273)` | `oklch(0.48 0.20 273)` | Hover state on accent |
132
- | `--accent-3` | `oklch(0.82 0.10 273)` | `oklch(0.40 0.18 273)` | Subdued accent text |
133
- | `--accent-bg` | `color-mix(in oklch, var(--accent) 12%, transparent)` | same, 8% | Tinted panel backgrounds |
134
- | `--accent-border` | `color-mix(in oklch, var(--accent) 40%, transparent)` | same, 30% | Tinted borders |
135
- | `--accent-glow` | `color-mix(in oklch, var(--accent) 18%, transparent)` | same | Focus glow shadow |
136
- | `--accent-soft` | `color-mix(in oklch, var(--accent) 8%, transparent)` | same, 6% | Hover wash on neutral surface |
137
-
138
- **Accent budget.** Two uses per region, max. Default allocation:
139
- 1. Active nav item background OR primary CTA fill.
140
- 2. Active state badge OR streaming pill.
141
-
142
- ### 3.5 Status colors (OKLch in both themes)
143
-
144
- | Token | Dark | Light | Use |
145
- |---|---|---|---|
146
- | `--success` | `oklch(0.72 0.16 145)` | `oklch(0.50 0.15 145)` | Streaming OK, task done, connected |
147
- | `--warning` | `oklch(0.78 0.14 70)` | `oklch(0.55 0.15 70)` | Stuck agent, retry, cost spike |
148
- | `--error` | `oklch(0.66 0.20 25)` | `oklch(0.52 0.20 25)` | Failed, deleted, auth error |
149
- | `--info` | `oklch(0.72 0.13 235)` | `oklch(0.50 0.15 235)` | Neutral informational |
150
- | `--success-soft` | `color-mix(in oklch, var(--success) 15%, transparent)` | same, 12% | Status pill bg |
151
- | `--error-soft` | `color-mix(in oklch, var(--error) 12%, transparent)` | same, 10% | Error region bg |
152
- | `--warning-soft` | `color-mix(in oklch, var(--warning) 15%, transparent)` | same, 10% | Warning region bg |
153
-
154
- ### 3.6 Derived tokens (chat overhaul, v3.21 — preserved)
87
+ ### 3.2 Foreground scale
155
88
 
156
- ```
157
- --gradient-hello linear 90deg, var(--accent-3) → var(--accent)
158
- --gradient-name linear 90deg, var(--accent) oklch(0.55 0.22 25)
159
- ```
89
+ | Token | Light | Dark | Use |
90
+ |--|--|--|--|
91
+ | `--fg` | `oklch(0.141 0.005 285.823)` | `oklch(0.985 0 0)` | Primary text |
92
+ | `--fg-muted` | `oklch(0.552 0.016 285.938)` | `oklch(0.705 0.015 286.067)` | Secondary text, captions, helper |
93
+ | `--fg-subtle` | `oklch(0.705 0.015 286.067)` | `oklch(0.552 0.016 285.938)` | Tertiary, placeholder, disabled |
94
+ | `--fg-on-accent` | `oklch(0.982 0.018 155.826)` | `oklch(0.982 0.018 155.826)` | Text on `--accent` backgrounds |
95
+ | `--fg-link` | `var(--accent)` | `var(--accent)` | Inline links, breadcrumbs |
160
96
 
161
- Both gradients are reserved for the **chat greeting** (`hello, name`)
162
- and **brand mark** (`ᛒ Bizar`) — never used elsewhere.
97
+ ### 3.3 Accent (the only color that gets to be loud)
163
98
 
164
- ### 3.7 Syntax highlight (json tree in JSON viewer)
99
+ | Token | Light | Dark | Use |
100
+ |--|--|--|--|
101
+ | `--accent` | `oklch(0.527 0.154 150.069)` | `oklch(0.448 0.119 151.328)` | Primary buttons, active state, focus ring tint, live indicator |
102
+ | `--accent-hover` | `oklch(0.477 0.154 150.069)` | `oklch(0.398 0.119 151.328)` | Hover on `--accent` |
103
+ | `--accent-soft` | `color-mix(in oklch, var(--accent) 12%, transparent)` | same | Selected row tint, badge bg |
104
+ | `--accent-ring` | `color-mix(in oklch, var(--accent) 35%, transparent)` | same | Focus ring |
165
105
 
166
- ```
167
- --syntax-key oklch(0.78 0.13 235)
168
- --syntax-string oklch(0.84 0.10 235)
169
- --syntax-number oklch(0.78 0.16 60)
170
- --syntax-boolean oklch(0.68 0.20 25)
171
- --syntax-null oklch(0.68 0.20 25)
172
- ```
106
+ ### 3.4 Semantic colors
173
107
 
174
- ### 3.8 Anti-pattern reference colors
108
+ | Token | Light | Dark | Use |
109
+ |--|--|--|--|
110
+ | `--success` | `oklch(0.527 0.154 150.069)` | `oklch(0.723 0.219 149.579)` | Passed, succeeded, completed |
111
+ | `--warning` | `oklch(0.7 0.15 75)` | `oklch(0.75 0.15 75)` | Awaiting, paused, queued |
112
+ | `--danger` | `oklch(0.577 0.245 27.325)` | `oklch(0.704 0.191 22.216)` | Failed, error, destructive |
113
+ | `--info` | `oklch(0.6 0.13 240)` | `oklch(0.7 0.13 240)` | Informational, neutral highlight |
175
114
 
176
- | Token | Value | When to use |
177
- |---|---|---|
178
- | ~~`--left-stripe`~~ | *banned* | Never. See §1.3. |
179
- | ~~purple page wash~~ | *banned* | Body backgrounds must be `--bg` or `--bg-elev`. |
180
- | ~~`#fff` raw~~ | `--text-strong` | Pure white is jarring on dark; use `--text-strong`. |
115
+ ### 3.5 Borders & inputs
181
116
 
182
- ---
117
+ | Token | Light | Dark | Use |
118
+ |--|--|--|--|
119
+ | `--border` | `oklch(0.92 0.004 286.32)` | `oklch(1 0 0 / 10%)` | Default 1px border |
120
+ | `--border-strong` | `oklch(0.85 0.005 286)` | `oklch(1 0 0 / 18%)` | Hover, dividers |
121
+ | `--input-bg` | `oklch(0.967 0.001 286.375)` | `oklch(0.274 0.006 286.033)` | Form control fill |
122
+ | `--focus-ring` | `oklch(0.705 0.015 286.067)` | `oklch(0.552 0.016 285.938)` | Outer focus ring |
183
123
 
184
- ## 4 · Typography
124
+ ### 3.6 Charts (categorical, sequential, status)
185
125
 
186
- ### 4.1 Font stacks
126
+ | Token | Value | Use |
127
+ |--|--|--|
128
+ | `--chart-1` | `oklch(0.871 0.006 286.286)` | First series, neutral |
129
+ | `--chart-2` | `oklch(0.552 0.016 285.938)` | Second series |
130
+ | `--chart-3` | `oklch(0.442 0.017 285.786)` | Third series |
131
+ | `--chart-4` | `oklch(0.37 0.013 285.805)` | Fourth series |
132
+ | `--chart-5` | `oklch(0.274 0.006 286.033)` | Fifth series |
133
+ | `--chart-accent` | `var(--accent)` | Highlighted series |
187
134
 
188
- ```
189
- --font-sans:
190
- 'Inter var', 'Inter', system-ui, -apple-system, 'Segoe UI',
191
- Roboto, 'Helvetica Neue', sans-serif
135
+ Chart colors intentionally **do not match `--accent`** — they form a neutral grayscale ramp so that the green primary is reserved for interactive state. When a chart needs to highlight a single series (e.g. "errors over time"), it switches to `--danger` or `--success`, not `--accent`.
192
136
 
193
- --font-mono:
194
- 'JetBrains Mono', 'Fira Code', 'SF Mono', 'Cascadia Code',
195
- Consolas, monospace
196
- ```
137
+ ### 3.7 Sidebar
197
138
 
198
- Inter variable enables `cv02`, `cv03`, `cv04`, `cv11` stylistic sets
199
- for more legible numbers, parentheses, and `@` symbol.
139
+ | Token | Light | Dark | Use |
140
+ |--|--|--|--|
141
+ | `--sidebar-bg` | `oklch(0.985 0 0)` | `oklch(0.21 0.006 285.885)` | Sidebar canvas |
142
+ | `--sidebar-fg` | `oklch(0.141 0.005 285.823)` | `oklch(0.985 0 0)` | Sidebar text |
143
+ | `--sidebar-accent` | `oklch(0.627 0.194 149.214)` | `oklch(0.723 0.219 149.579)` | Active nav item, primary sidebar button |
144
+ | `--sidebar-accent-fg` | `oklch(0.982 0.018 155.826)` | `oklch(0.982 0.018 155.826)` | Text on sidebar accent |
145
+ | `--sidebar-hover` | `oklch(0.967 0.001 286.375)` | `oklch(0.274 0.006 286.033)` | Nav hover bg |
146
+ | `--sidebar-border` | `oklch(0.92 0.004 286.32)` | `oklch(1 0 0 / 10%)` | Sidebar right border |
200
147
 
201
- ### 4.2 Scale
148
+ ### 3.8 Geometry
202
149
 
203
- | Token | px | Use |
204
- |---|---|---|
205
- | `--fs-display` | 28 | Section title in chrome bars |
206
- | `--fs-h3` | 16 | Card title |
207
- | `--fs-body` | 14 | Default body (small for density) |
208
- | `--fs-meta` | 12 | Captions, timestamps |
209
- | `--fs-micro` | 11 | Numeric eyebrows, badges |
150
+ | Token | Value | Use |
151
+ |--|--|--|
152
+ | `--radius` | `0.625rem` (10px) | Buttons, inputs, cards, popovers |
153
+ | `--radius-sm` | `0.375rem` (6px) | Chips, badges, small buttons |
154
+ | `--radius-lg` | `0.875rem` (14px) | Dialogs, sheets, large cards |
155
+ | `--radius-pill` | `9999px` | Avatars, pills, toggle switches |
210
156
 
211
- Tabular numerics (`font-variant-numeric: tabular-nums`) on every cell
212
- that contains numbers: token counters, costs, latencies, timestamps,
213
- session ids.
157
+ ### 3.9 Elevation
214
158
 
215
- ### 4.3 Weight scale
159
+ | Token | Value | Use |
160
+ |--|--|--|
161
+ | `--shadow-1` | `0 1px 2px oklch(0 0 0 / 0.04)` | Resting cards |
162
+ | `--shadow-2` | `0 4px 12px oklch(0 0 0 / 0.08)` | Hover cards, popovers |
163
+ | `--shadow-3` | `0 12px 32px oklch(0 0 0 / 0.12)` | Drag overlay, dialogs |
164
+ | `--shadow-4` | `0 24px 64px oklch(0 0 0 / 0.16)` | Sheets, command palette |
216
165
 
217
- | Weight | Use |
218
- |---|---|
219
- | 400 | Body, captions |
220
- | 500 | Tab labels, button text |
221
- | 600 | Card titles, section heads, active nav |
222
- | 700 | Reserved for hero metrics only |
166
+ Dark mode multiplies each shadow by `1.25` because shadows are weaker on dark surfaces.
223
167
 
224
- ### 4.4 Heading rhythm
168
+ ### 3.10 Motion
225
169
 
226
- - h1: never used in dashboard chrome. Display goes to `--fs-display` with
227
- letter-spacing `-0.02em`.
228
- - h2 / h3: card-level. `--fs-h3` (16px) weight 600.
229
- - Avoid long display copy inside cards; let the body carry meaning.
170
+ | Token | Value | Use |
171
+ |--|--|--|
172
+ | `--motion-instant` | `50ms` | Hover color shift, focus ring |
173
+ | `--motion-fast` | `120ms` | Small UI: button press, chip toggle |
174
+ | `--motion-base` | `200ms` | Default: popovers, menus, sidebar collapse |
175
+ | `--motion-slow` | `320ms` | Page transitions, drag overlays |
176
+ | `--ease-out` | `cubic-bezier(0.16, 1, 0.3, 1)` | 90% of motion — feels like Linear |
177
+ | `--ease-in-out` | `cubic-bezier(0.65, 0, 0.35, 1)` | Sidebar collapse, sheet slide |
178
+ | `--ease-spring` | `cubic-bezier(0.34, 1.56, 0.64, 1)` | Success micro-bounces |
179
+
180
+ `prefers-reduced-motion: reduce` zeroes every `--motion-*` token.
230
181
 
231
182
  ---
232
183
 
233
- ## 5 · Spacing
184
+ ## 4 · Typography
234
185
 
235
- 8-point grid, with semantic aliases introduced in v4.6.0:
186
+ Two families, six sizes, five weights. That is the whole type system.
236
187
 
237
- ```
238
- --space-1 4px --spacing-xs icon-to-text, micro gap
239
- --space-2 8px --spacing-sm between rows in a stack
240
- --space-3 12px --spacing-md default card padding
241
- --space-4 16px --spacing-lg section padding
242
- --space-6 24px --spacing-xl page-level padding
243
- --space-8 32px topbar vertical padding
244
- --space-10 40px
245
- --space-12 48px panel header padding
246
- --space-16 64px rare, full-page sections
247
- --space-20 80px
248
- --space-24 96px hero only
249
- ```
188
+ ### 4.1 Families
250
189
 
251
- **Card padding.** Default is `--space-3` (12px) — the dashboard is dense.
252
- Use `--space-4` (16px) only on kanban cards and chat info panels.
190
+ | Token | Family | Use |
191
+ |--|--|--|
192
+ | `--font-sans` | `Inter Variable`, system-ui fallback | UI, body, headings |
193
+ | `--font-mono` | `JetBrains Mono Variable`, `ui-monospace` fallback | IDs, paths, code, numerics |
194
+ | `--font-display` | `Inter Variable` (tight tracking) | Hero text, empty states |
253
195
 
254
- ---
196
+ ### 4.2 Sizes (modular scale 1.125)
255
197
 
256
- ## 6 · Radius
198
+ | Token | Size / line-height | Use |
199
+ |--|--|--|
200
+ | `--text-xs` | `0.75rem / 1rem` (12/16) | Captions, helper, table footnotes |
201
+ | `--text-sm` | `0.8125rem / 1.125rem` (13/18) | Default body, table cells |
202
+ | `--text-base` | `0.875rem / 1.25rem` (14/20) | Default body on wide screens |
203
+ | `--text-md` | `1rem / 1.5rem` (16/24) | Card titles, section headers |
204
+ | `--text-lg` | `1.125rem / 1.625rem` (18/26) | Page titles |
205
+ | `--text-xl` | `1.375rem / 1.75rem` (22/28) | Hero, empty-state title |
257
206
 
258
- ```
259
- --radius-sm 6px inputs, small buttons, badges
260
- --radius 8px buttons, tabs, default cards
261
- --radius-md 10px chat message bubbles
262
- --radius-lg 14px modals, kanban cards, topbar dropdowns
263
- --radius-xl 16px dialog, command palette
264
- --radius-pill 999px status pills, tag chips
265
- ```
266
-
267
- ---
207
+ ### 4.3 Weights
268
208
 
269
- ## 7 · Elevation
209
+ | Token | Value | Use |
210
+ |--|--|--|
211
+ | `--weight-regular` | `400` | Body |
212
+ | `--weight-medium` | `500` | Nav labels, button text |
213
+ | `--weight-semibold` | `600` | Card titles, table headers |
214
+ | `--weight-bold` | `700` | Page titles only |
270
215
 
271
- ```
272
- --shadow-1 0 1px 2px rgba(0,0,0,0.45) hairlines on cards
273
- --shadow-2 0 4px 12px rgba(0,0,0,0.45) dropdowns, popovers
274
- --shadow-3 0 12px 32px rgba(0,0,0,0.45) modals
275
- --shadow-glow 0 0 0 1px accent-border + glow focused/active surfaces
276
- ```
216
+ ### 4.4 Numerics
277
217
 
278
- Shadows are dark-tinted (not blurred gray) to read on the dark canvas.
279
- Avoid shadows on hairline borders; the border already separates.
218
+ All numeric cells use `font-variant-numeric: tabular-nums` so columns of figures align. The `mono` family is reserved for IDs, paths, and raw code; numerics stay in `sans` unless they are an ID.
280
219
 
281
- ---
220
+ ### 4.5 Long content
282
221
 
283
- ## 8 · Motion
222
+ Body copy uses `text-wrap: pretty`; headings use `text-wrap: balance`. Code blocks, table cells, and IDs use `text-wrap: nowrap` with `overflow: hidden; text-overflow: ellipsis` and a tooltip on hover.
284
223
 
285
- ```
286
- --motion-fast 120ms
287
- --motion-base 200ms
288
- --motion-slow 320ms
289
- --ease cubic-bezier(0.4, 0, 0.2, 1)
290
- --motion-ease cubic-bezier(0.2, 0, 0, 1) sharp, intentional
291
- ```
224
+ ---
292
225
 
293
- **Streaming indicator.** Three dots in `--accent`, staggered opacity
294
- animation, `--motion-slow` per dot. Never use a spinner on a streaming
295
- chat — the user knows it's typing.
226
+ ## 5 · Spacing & layout
296
227
 
297
- **Pulsing badges** (Cline runtime, WebSocket connecting). Use `--ease`,
298
- `--motion-slow`, infinite, alternate. Never use on content inside the
299
- chat thread; only on system-state chrome.
228
+ ### 5.1 Spacing scale (4px base)
300
229
 
301
- **No animations on data.** Token counts, cost numbers, task counts
302
- update in place. The number just changes — no flicker, no count-up.
230
+ | Token | px | Use |
231
+ |--|--|--|
232
+ | `--space-0` | `0` | Reset |
233
+ | `--space-1` | `4px` | Tight stack, chip padding-y |
234
+ | `--space-2` | `8px` | Inline gap, button padding-y |
235
+ | `--space-3` | `12px` | Default inline gap, control padding |
236
+ | `--space-4` | `16px` | Card padding, stack gap, control padding-x |
237
+ | `--space-5` | `20px` | Section padding |
238
+ | `--space-6` | `24px` | Page section gap |
239
+ | `--space-8` | `32px` | Page padding |
240
+ | `--space-10` | `40px` | Hero vertical rhythm |
241
+ | `--space-12` | `48px` | Page-level separators |
242
+ | `--space-16` | `64px` | Empty-state padding |
243
+
244
+ ### 5.2 Layout grid
245
+
246
+ - Desktop default: **12-column, 16px gutter, max 1440px content.**
247
+ - Sidebar: **260px expanded, 60px collapsed**, `--motion-base` ease.
248
+ - Topbar: **56px tall**, single row.
249
+ - Right detail drawer: **360px** when open, slides over content on <1280px, pushes content on ≥1280px.
250
+
251
+ ### 5.3 Density
252
+
253
+ Two density modes, user-toggleable per workspace:
254
+
255
+ | Mode | Row height | Padding-y | Use |
256
+ |--|--|--|--|
257
+ | **Compact** (default) | `32px` | `4px` | Power-user, screen-fillers |
258
+ | **Comfortable** | `40px` | `8px` | Touch, lower-resolution |
259
+
260
+ Density is a single CSS class on `<html>`: `data-density="compact"` or `"comfortable"`. Every list, table, and tree honors it. Card padding does not change with density.
261
+
262
+ ### 5.4 Z-index scale
263
+
264
+ | Layer | Value | Use |
265
+ |--|--|--|
266
+ | `--z-base` | `0` | Content |
267
+ | `--z-sticky` | `10` | Table headers, sticky filters |
268
+ | `--z-dropdown` | `1000` | Dropdowns, autocomplete |
269
+ | `--z-sticky-nav` | `1100` | Topbar, sidebar |
270
+ | `--z-overlay` | `1300` | Modal backdrop |
271
+ | `--z-modal` | `1400` | Dialogs, sheets |
272
+ | `--z-popover` | `1500` | Context menus, command palette |
273
+ | `--z-toast` | `1600` | Toasts, notifications |
274
+ | `--z-tooltip` | `1700` | Tooltips |
275
+
276
+ No z-index above `1700`. If you need it, you have mis-designed.
303
277
 
304
278
  ---
305
279
 
306
- ## 9 · Components catalog
280
+ ## 6 · Motion & elevation
307
281
 
308
- The dashboard ships ~60 components. Every new component must slot into
309
- one of these categories.
282
+ ### 6.1 Default transitions
310
283
 
311
- ### 9.1 Chrome
284
+ | Element | Property | Duration | Easing |
285
+ |--|--|--|--|
286
+ | Button bg | `background-color` | `--motion-instant` | `--ease-out` |
287
+ | Button press | `transform` | `--motion-fast` | `--ease-out` |
288
+ | Card hover | `box-shadow, transform` | `--motion-base` | `--ease-out` |
289
+ | Popover open | `opacity, transform` | `--motion-base` | `--ease-out` |
290
+ | Sidebar collapse | `width` | `--motion-base` | `--ease-in-out` |
291
+ | Page transition | `opacity` | `--motion-slow` | `--ease-out` |
292
+ | Drag overlay enter | `opacity, transform` | `--motion-fast` | `--ease-spring` |
293
+ | Toast | `transform` | `--motion-base` | `--ease-spring` |
312
294
 
313
- #### Topbar
314
- ```
315
- ┌─────────────────────────────────────────────────────────────────────────┐
316
- │ ᛒ Bizar v6.0.0 │ project ▾ │ ⌘K Search... │ • Cline·active • ws·live │ ← 1 row, ~52px tall
317
- │ [Overview][Chat][Agents][Glyphs][Tasks][Activity][Active][Skills]... ← 2nd row, tabs (topbar layout only)
318
- └─────────────────────────────────────────────────────────────────────────┘
319
- ```
295
+ ### 6.2 Micro-interactions
320
296
 
321
- - Brand block: runic `ᛒ` (24px, `--accent`) + "Bizar" wordmark +
322
- version pill. Pill uses `--gradient-name` and
323
- `text-shadow: 0 1px 0 rgba(0,0,0,0.2)` so it reads on light too.
324
- - Project selector: pill button with `Folder` icon + project name +
325
- chevron. Dropdown is `--bg-elev-2` with 8px radius, items 32px tall.
326
- - Search trigger: pill button with kbd hint `⌘K`, `--border` outline.
327
- - WebSocket status: dot (8px) + label. Dot color encodes state:
328
- green=live, yellow=connecting, red=closed, gray=disabled.
297
+ - **Live indicator:** green dot, 1.6s pulse animation (`opacity` 1→0.4→1, `--motion-slow`). Respects `prefers-reduced-motion`.
298
+ - **Streaming text:** no special animation. Cursor blinks at end of last token, 1s cadence.
299
+ - **Drag:** cursor changes to `grabbing` on `mousedown`. Drag overlay uses `--shadow-3` and `transform: rotate(1.5deg) scale(1.02)` for a "lifted" feel.
300
+ - **Save:** inline checkmark flash, `--motion-fast`, `--ease-spring`. No modal.
301
+ - **Error:** subtle 2px left border inside the input + focus ring tint `--danger`. No shake animation.
329
302
 
330
- #### Sidebar (sidebar / both layout)
331
- ```
332
- ┌──────┐
333
- │ ⌂ │ ← icon-only buttons, 56px wide × 44px tall
334
- │ 💬 │
335
- │ 🤖 │
336
- │ ✦ │ ← ~17 tabs in scrollable column
337
- │ ... │
338
- │ ⚙ │ ← Settings pinned to bottom
339
- └──────┘
340
- ```
303
+ ### 6.3 Reduced motion
341
304
 
342
- - Width: 56px collapsed.
343
- - Active state: `--accent-bg` background + `--accent` icon color +
344
- bold weight on the (hidden) label. **No left edge stripe.**
345
- - Mod tabs (post v3.20.3) sit below a hairline divider labelled "Mods".
346
- - Settings mode (v4.9.0) replaces tab list with the full SettingsNav.
305
+ When `prefers-reduced-motion: reduce`:
306
+ - All `--motion-*` tokens set to `0ms`.
307
+ - Drag overlay: no rotation/scale, only opacity.
308
+ - Page transitions: instant.
309
+ - Live indicator: static dot, no pulse.
347
310
 
348
- ### 9.2 Buttons
311
+ ---
349
312
 
350
- ```
351
- .btn-sm 24px tall, 8px 12px padding, 12px text
352
- .btn 32px tall, default, 13px text
353
- .btn-lg 40px tall, primary CTAs only
354
-
355
- Variants
356
- .btn-primary accent fill, white text, accent border
357
- .btn-secondary transparent, --border, --text
358
- .btn-ghost transparent, no border, hover → --fg
359
- .btn-danger transparent, --error text on hover
360
- .btn-icon square, icon-only, 32×32
361
- ```
313
+ ## 7 · Layout
362
314
 
363
- Disabled = 50% opacity, `cursor: not-allowed`, no hover. **Never** show
364
- a disabled button with a spinner inside it — show the spinner *instead*
365
- of the button or use a loading state on the button itself.
315
+ ### 7.1 App shell
366
316
 
367
- ### 9.3 Inputs
317
+ The app shell is a fixed two-column layout: a sticky topbar on top, a sidebar on the left, and the main content area (SidebarInset) on the right. An optional status bar lives at the bottom on desktop and is hidden by default; it surfaces when there is an active alert.
368
318
 
369
319
  ```
370
- .input 32px tall, --bg-elev, --border, focus = --accent border + glow
371
- .textarea auto, min 96px tall, resizes vertically
372
- .input-mono same as .input, font-family: --font-mono (used for hex/path fields)
320
+ ┌─────────────────────────────────────────────────────────────────────┐
321
+ │ TOPBAR 56px workspace · breadcrumb · status · search · user │
322
+ ├──────────┬──────────────────────────────────────────────────────────┤
323
+ │ │ │
324
+ │ SIDEBAR │ SIDEBAR INSET │
325
+ │ 260px │ max 1440px, centered │
326
+ │ │ │
327
+ │ nav │ page content │
328
+ │ groups │ │
329
+ │ │ │
330
+ ├──────────┴──────────────────────────────────────────────────────────┤
331
+ │ STATUS BAR 28px (optional) online · tokens · latency · build │
332
+ └─────────────────────────────────────────────────────────────────────┘
373
333
  ```
374
334
 
375
- Search trigger in the topbar is a `.input` styled as a pill with a kbd
376
- hint inside it on the right.
335
+ ### 7.2 Topbar
377
336
 
378
- ### 9.4 Status pills & badges
337
+ | Slot | Width | Contents |
338
+ |--|--|--|
339
+ | Left | 320px | Bizar logo · workspace switcher · project picker |
340
+ | Center | flex | breadcrumb (route) + inline search (Cmd+K opens palette; inline search is for quick find) |
341
+ | Right | auto | Status pills (agents online · tokens · queue) · notifications bell · theme toggle · user menu |
379
342
 
380
- ```
381
- .pill 999px radius, --accent-bg bg, --accent text, 11px mono uppercase
382
- .pill-success --success-soft bg, --success text
383
- .pill-warning --warning-soft bg, --warning text
384
- .pill-error --error-soft bg, --error text
385
- .pill-info --info bg (muted), --info text
386
-
387
- .badge square corner, --bg-elev-2 bg, --text text, 11px mono, 14px square
388
- .dot 8px circle, color encodes state
389
- ```
343
+ The topbar is sticky (`--z-sticky-nav`). It is **not** a tab bar — tabs live inside views when needed.
390
344
 
391
- Pills = uppercased categorical labels (`STREAMING`, `MOD`, `BETA`).
392
- Badges = numeric counts (unread messages, queued tasks).
345
+ ### 7.3 Sidebar
393
346
 
394
- ### 9.5 Cards
395
-
396
- ```
397
- .card --bg-elev, --border, --radius-lg (14px), --space-3 padding
398
- .card-elev-2 --bg-elev-2 (nested surfaces)
399
- .card-flat no background, no border
400
- .card-rule top border in --text-strong, used in log-style lists
401
- ```
347
+ | Slot | Contents |
348
+ |--|--|
349
+ | Header | Workspace switcher (240px), collapse toggle (right edge) |
350
+ | Section: **Workspace** | Overview, Tasks, Goals |
351
+ | Section: **Operations** | Agents, Activity, Memory |
352
+ | Section: **Libraries** | Skills, MCP servers, Hooks |
353
+ | Section: **System** | Settings |
354
+ | Footer | Status indicator (online/offline), build SHA, version |
402
355
 
403
- Kanban card: 16px padding, 14px radius, `box-shadow: --shadow-1` only
404
- on drag.
405
-
406
- ### 9.6 Modal & dialog
407
-
408
- - Backdrop: `--overlay-bg` (60% black).
409
- - Surface: `--bg-elev-2`, `--radius-xl`, `--shadow-3`.
410
- - Title: `--fs-h3` weight 600, `--space-3` from top.
411
- - Footer: `--border` top hairline, right-aligned actions.
412
-
413
- Command palette (v3.1.0+): 520px wide, centered, 16px padding, kbd row
414
- in footer showing shortcuts.
415
-
416
- ### 9.7 Toast
417
-
418
- - Bottom-right, stacks upward, 4 visible max.
419
- - Width 360px, `--bg-elev-2`, `--radius-md`, `--shadow-2`.
420
- - Color-coded left edge of *icon*, not the toast background.
421
- - Lifetimes: `info` 2.5s, `success` 3s, `warning` 5s, `error` 8s.
422
-
423
- ### 9.8 Tabs (topbar variant)
356
+ Each section has an 11px uppercase label in `--fg-subtle` with `letter-spacing: 0.04em`. Items are 32px tall, single line, with a 16x16 Lucide icon, label, and an optional count badge (right-aligned, `--fg-muted`). The active item uses `--sidebar-accent` background with `--sidebar-accent-fg` text and a 2px left-edge bar in `--sidebar-accent` (a single permitted use of an edge bar — it is the *only* navigation primitive allowed to use one).
424
357
 
425
- - 36px tall, `--fs-meta` text, `--font-mono`.
426
- - Active: `--text-strong` + 2px `--accent` underline (positioned at
427
- bottom of the tab, full-width).
428
- - Hover: `--text-strong` (no underline).
429
- - Settings tab: shows a small `Settings2` icon next to its label when
430
- settings mode is active.
358
+ ### 7.4 Content area
431
359
 
432
- ### 9.9 Sidebar tabs (sidebar / both layout)
433
-
434
- - 56px wide column, 44px tall.
435
- - Icon 18px, label hidden (tooltip via `title`).
436
- - Active: `--accent-bg` background, `--accent` icon, 600 weight label.
437
- - Inactive: `--text-dim` icon.
360
+ The `SidebarInset` is a 1440px-max container with `--space-8` horizontal padding and `--space-6` top padding (topbar adds the rest). Pages render their own header (ViewHeader primitive see §8.4) and then their content.
438
361
 
439
- ### 9.10 Chat
362
+ ### 7.5 Optional right detail drawer
440
363
 
441
- #### Rail (`<aside class="chat-rail">`)
442
- - Width 280px. Sections grouped by recency: Today, Yesterday, This
443
- week, Earlier.
444
- - Each row: state indicator (8px dot, color per state) + title + time
445
- + unread badge + 3-dot menu.
446
- - Active session background: `--accent-bg` with no left stripe.
447
- - Sub-agent tree: collapsible, indented 12px, smaller text, hairline
448
- connector.
449
-
450
- #### Thread (`<section class="chat-thread-section">`)
451
- - Center column, fills remaining width.
452
- - Thread head: title + source badge (`cline` / `bizar chat`) + subtitle
453
- with state (idle / Replying / Your turn).
454
- - Messages: alternating bubbles. User right-aligned, `--bg-elev-2`
455
- bubble. Assistant left-aligned, no bubble (transparent).
456
- - Streaming indicator: three pulsing dots in `--accent`, animated.
457
- - Jump-to-latest pill (when scrolled up): floating, bottom-right of
458
- thread, `--bg-elev-2` + `--shadow-2`.
364
+ The kanban and agents views can open a right-side **DetailDrawer** (360px). It slides in from the right with `--motion-base` and pushes content (≥1280px) or overlays it (<1280px). It contains:
365
+ - Read view: title, metadata, body, activity, comments
366
+ - Edit view: same + editable fields inline
459
367
 
460
- #### Composer
461
- - Pill-shaped input, `--bg-elev` outer, `--bg-elev-2` inner field.
462
- - Attachments: chip row above input.
463
- - Slash command suggestions: popover above, mono, `--font-mono`.
464
- - Agent + model selectors: pill chips on left, opens dropdown on
465
- click.
368
+ ### 7.6 Routes
466
369
 
467
- #### Info panel (`<aside class="chat-info">`)
468
- - Width 320px, sections (Session, Agent, Model, Tokens, Cost,
469
- Attached agents, MCPs, Slash commands, Actions).
470
- - Token usage: numeric + horizontal progress bar (`--bg-elev-2` track,
471
- `--accent` fill, 4px tall).
472
- - Cost: numeric + "approx · live from MiniMax" caption when not
473
- measured.
370
+ | Path | Page | Default view |
371
+ |--|--|--|
372
+ | `/` | Overview | Dashboard summary |
373
+ | `/tasks` | Tasks | Kanban (the main focus) |
374
+ | `/tasks/list` | Tasks | List view |
375
+ | `/tasks/calendar` | Tasks | Calendar view |
376
+ | `/goals` | Goals | Active goals |
377
+ | `/goals/:id` | Goal detail | Single goal |
378
+ | `/agents` | Agents | Roster |
379
+ | `/agents/:id` | Agent detail | Single agent |
380
+ | `/activity` | Activity | Event log |
381
+ | `/memory` | Memory | Vault browser |
382
+ | `/libraries/skills` | Skills | Library |
383
+ | `/libraries/mcps` | MCP servers | Library |
384
+ | `/libraries/hooks` | Hooks | Library |
385
+ | `/settings/*` | Settings | Hierarchical |
474
386
 
475
- ### 9.11 Tables
387
+ The nav stays at **6 top-level items** (Workspace, Operations, Libraries, System — the rest are sub-routes of the existing items). The user explicitly said "I do not want too many tabs", so we surface items as nav groups with secondary tabs inside the page.
476
388
 
477
- - Hairline borders (`--border`), no row striping.
478
- - Header row: `--text-dim`, `--font-mono`, 12px, uppercase, 0.04em
479
- letter-spacing.
480
- - Body row: 14px, `--text`, 12px 14px padding.
481
- - Numerics: `--font-mono`, `tabular-nums`, right-aligned.
482
- - Hover: `--bg-elev-2` wash — not a colored row.
389
+ ### 7.7 Empty states
483
390
 
484
- ### 9.12 Kanban (Tasks)
391
+ Every collection view has an `EmptyState` (see §8.5) with:
392
+ - A 24px Lucide icon in `--fg-subtle`
393
+ - A one-line title in `--text-md` `--weight-medium`
394
+ - A one-sentence body in `--fg-muted`
395
+ - One primary CTA button (`--accent`)
396
+ - Optional secondary text link
485
397
 
486
- 5-column board: Backlog Todo In progress Review → Done.
398
+ No illustrations, no emoji, no "celebrate your first task" copy.
487
399
 
488
- - Column header: 12px mono uppercase, count badge, scrollable column
489
- body.
490
- - Card: 14px radius, 16px padding, kanban-card-shadow only on drag.
491
- - Team badge (v6.0.0): pill with sparkle icon, attached to cards
492
- tagged `team:*`.
493
- - Drag: 1px `--accent-border` outline, `--shadow-3`.
400
+ ---
494
401
 
495
- ### 9.13 Status indicators (session, agent, runtime)
402
+ ## 8 · Component library
403
+
404
+ The library lives at `bizar-dash/src/web/ui/`. Every component is named with PascalCase, lives in its own file, exports a named function, and has a colocated `.test.tsx` file. No default exports.
405
+
406
+ ### 8.1 `ui/primitives/` — no business logic
407
+
408
+ - **Box** — `div` with tokens (bg, fg, padding, radius)
409
+ - **Stack** — vertical flex with `--space-N` gap
410
+ - **Inline** — horizontal flex with `--space-N` gap
411
+ - **Cluster** — wraps inline elements that pack
412
+ - **Grid** — CSS grid wrapper with col/row gap
413
+ - **Center** — centers content (empty states)
414
+ - **Separator** — 1px horizontal/vertical rule
415
+ - **ScrollArea** — themed scroll wrapper, hides scrollbars unless scrolling
416
+ - **Resizable** — wraps `react-resizable-panels`
417
+ - **VisuallyHidden** — `sr-only` helper
418
+ - **Portal** — Radix Portal wrapper
419
+
420
+ ### 8.2 `ui/controls/` — form & input
421
+
422
+ - **Button** (variants: `primary | secondary | ghost | outline | danger | link`, sizes: `xs | sm | md | lg | icon`)
423
+ - **ButtonGroup** — stacked buttons with shared borders
424
+ - **IconButton** — square, icon-only, requires `aria-label`
425
+ - **Input** — single-line text, optional left/right slots
426
+ - **Textarea** — multi-line, autoresize
427
+ - **InputOTP** — segmented code input
428
+ - **Select** — Radix Select wrapper (single)
429
+ - **MultiSelect** — Radix Popover + command list (multi)
430
+ - **Combobox** — Radix Popover + list + input (async-capable)
431
+ - **Checkbox** — Radix Checkbox
432
+ - **RadioGroup** — Radix RadioGroup
433
+ - **Switch** — Radix Switch
434
+ - **Toggle** — single toggle button
435
+ - **ToggleGroup** — Radix ToggleGroup
436
+ - **Slider** — Radix Slider
437
+ - **DatePicker** — single date
438
+ - **DateRangePicker** — two dates
439
+ - **TimePicker** — single time
440
+ - **ColorPicker** — popover with swatches + input
441
+ - **Field** — label + control + error + helper wrapper
442
+ - **Form** — React Hook Form + Zod integration
443
+
444
+ ### 8.3 `ui/feedback/` — feedback & status
445
+
446
+ - **Alert** — inline banner, variants `info | success | warning | danger`
447
+ - **Toast** — Sonner wrapper, top-right, auto-dismiss 5s
448
+ - **Dialog** — Radix Dialog (modal)
449
+ - **AlertDialog** — destructive confirm
450
+ - **Sheet** — Radix Dialog with side prop (right/left/top/bottom)
451
+ - **Drawer** — bottom-sheet variant for mobile
452
+ - **Popover** — Radix Popover
453
+ - **HoverCard** — Radix HoverCard (preview on hover)
454
+ - **Tooltip** — Radix Tooltip, 4-side aware
455
+ - **Progress** — linear bar
456
+ - **ProgressCircle** — circular determinate/indeterminate
457
+ - **Spinner** — single-element rotating arc
458
+ - **Skeleton** — shimmering placeholder
459
+ - **EmptyState** — see §7.7
460
+ - **ErrorBoundary** — React error boundary
461
+ - **Banner** — full-width inline banner
462
+
463
+ ### 8.4 `ui/data/` — data display
464
+
465
+ - **Card** — generic container with optional header/footer slots
466
+ - **StatTile** — single metric, optional delta indicator
467
+ - **StatGrid** — N-up grid of StatTiles
468
+ - **Table** — semantic `<table>` (low-level)
469
+ - **DataTable** — TanStack Table wrapper (sort, filter, paginate, select, resize, virtualize)
470
+ - **Badge** — small label, variants `default | accent | success | warning | danger | neutral`
471
+ - **Chip** — removable tag with avatar/icon
472
+ - **Avatar** — image or initials, with optional status dot
473
+ - **AvatarStack** — overlapping avatars
474
+ - **Timeline** — vertical event list with timestamps
475
+ - **Accordion** — Radix Accordion
476
+ - **Collapsible** — single show/hide
477
+ - **Chart** — Recharts wrapper (LineChart, BarChart, AreaChart, PieChart) bound to chart tokens
478
+ - **Sparkline** — inline mini-chart
479
+ - **MetricRing** — circular progress with label
480
+ - **BarList** — horizontal ranked list (used in activity feeds)
481
+ - **TreeView** — Radix Accordion-based tree
482
+ - **VirtualList** — TanStack Virtual wrapper
483
+ - **Kbd** — keyboard key cap
484
+ - **CountBadge** — numeric pill, optional max cap (e.g. "99+")
485
+ - **ViewHeader** — page title + description + actions slot (used at top of every page)
486
+
487
+ ### 8.5 `ui/navigation/` — navigation
488
+
489
+ - **Sidebar** (root + provider) — wraps `nav`, handles collapse
490
+ - **SidebarProvider** — context, persisted collapsed state
491
+ - **SidebarInset** — content slot inside SidebarProvider
492
+ - **SidebarSection** — labeled section
493
+ - **SidebarItem** — single nav row
494
+ - **SidebarGroup** — collapsible group
495
+ - **Topbar** — top bar slot composition
496
+ - **Breadcrumb** — list of links
497
+ - **NavLink** — Radix-styled anchor with active state
498
+ - **Tabs** — Radix Tabs wrapper
499
+ - **TabBar** — styled tab strip
500
+ - **TabPanel** — content slot
501
+ - **Menu** — Radix DropdownMenu with shortcut display
502
+ - **ContextMenu** — Radix ContextMenu (right-click trigger)
503
+ - **DropdownMenu** — Radix DropdownMenu
504
+ - **Menubar** — Radix Menubar
505
+ - **Pagination** — page + per-page controls
506
+ - **Stepper** — multi-step progress
507
+ - **CommandPalette** — Cmd+K overlay (see §9.4)
508
+ - **CommandBar** — inline command (Ctrl+K for filter focus)
509
+ - **NavSection** — labeled section for sidebar
510
+ - **NavItem** — sidebar row primitive
511
+ - **NavGroup** — collapsible section in sidebar
512
+ - **ViewTabs** — tab strip below ViewHeader
513
+
514
+ ### 8.6 `ui/kanban/` — the main feature
515
+
516
+ This directory is the largest and most important. The kanban is the centerpiece of the dashboard.
517
+
518
+ - **KanbanBoard** — root container, owns DnD context
519
+ - **KanbanColumn** — column with header (title, count, actions), droppable body, add-task footer
520
+ - **KanbanCard** — task card, draggable, with all metadata visible
521
+ - **KanbanCardCompact** — minimal card for high-density mode
522
+ - **KanbanCardExpanded** — preview-on-hover or detail-drawer card
523
+ - **KanbanDetail** — right-side drawer content
524
+ - **KanbanFilters** — filter bar (assignee, label, priority, due, search)
525
+ - **KanbanGroupBy** — group-by selector (status / assignee / label / priority / due / project)
526
+ - **KanbanSort** — sort selector
527
+ - **KanbanDensity** — compact/comfortable toggle
528
+ - **KanbanEmptyState** — column empty state
529
+ - **KanbanKeyboardShortcuts** — helper component showing available shortcuts
530
+ - **KanbanQuickAdd** — inline add input at top of each column
531
+ - **KanbanContextMenu** — right-click menu (see §9.2)
532
+ - **KanbanDragOverlay** — drag preview
533
+
534
+ ### 8.7 `ui/popups/` — right-click & custom popups
535
+
536
+ All popups are Radix-based or custom portals. **Browser default context menus are suppressed on all interactive surfaces** (`oncontextmenu` returns `false`); right-click opens our `ContextMenu`.
537
+
538
+ - **ContextMenu** — Radix ContextMenu (right-click + Shift+F10)
539
+ - **ActionMenu** — vertical list of actions with icons + shortcuts
540
+ - **SubActionMenu** — nested action menu (Radix Sub)
541
+ - **QuickAction** — single-action right-click shortcut
542
+ - **CommandBar** — Cmd+K overlay
543
+ - **DetailDrawer** — right-side drawer with read/edit toggle
544
+ - **ConfirmDialog** — destructive confirmation
545
+ - **InfoPopover** — hover/click popover with rich content
546
+
547
+ ### 8.8 `ui/theme/` — theming
548
+
549
+ - **ThemeProvider** — light/dark/system, persists to `localStorage`
550
+ - **useTheme** — hook returning `{ theme, setTheme, resolvedTheme }`
551
+ - **ThemeToggle** — dropdown trigger
552
+ - **DensityProvider** — compact/comfortable
553
+ - **useDensity** — hook
554
+
555
+ ### 8.9 `ui/utils/`
556
+
557
+ - **cx** — `clsx` + `tailwind-merge` wrapper
558
+ - **formatNumber**, **formatPercent**, **formatBytes**, **formatDuration**, **formatRelativeTime** — display formatters
559
+ - **useHotkeys** — global hotkey registry (see §9.3)
560
+ - **useFocusTrap** — focus trap for popovers
561
+ - **useMediaQuery** — responsive hook
562
+ - **useReducedMotion** — accessibility hook
563
+ - **useDebouncedValue** — search input debounce
564
+ - **useLocalStorage** — typed localStorage hook
565
+
566
+ ### 8.10 `ui/hooks/` — cross-cutting hooks
567
+
568
+ - **useWebSocket** — typed WS subscriber
569
+ - **useAgents** — agent roster query
570
+ - **useTasks** — task query/mutation
571
+ - **useGoals** — goal query/mutation
572
+ - **useShortcuts** — keyboard shortcut dispatcher
573
+ - **useContextMenu** — opens Radix ContextMenu at cursor
574
+ - **useDragAndDrop** — dnd-kit wrapper
496
575
 
497
- | State | Dot | Background | Animation |
498
- |---|---|---|---|
499
- | idle | `--text-dim` | none | none |
500
- | streaming | `--success` | `--success-soft` 4px wash on icon | pulsing glow |
501
- | awaiting | `--warning` | none | none |
502
- | error | `--error` | `--error-soft` ring | shake once on entry |
503
- | connecting | `--text-dim` | none | opacity 0.4↔1, slow |
576
+ ---
504
577
 
505
- ### 9.14 Glyph artifact cards
506
-
507
- - Square 1:1, `--bg-elev`, 1px `--accent-border` on hover.
508
- - Title in `--fs-h3`, 11px mono caption.
509
- - Send / Copy / Edit icon row in footer.
510
-
511
- ### 9.15 Notifications bell
578
+ ## 9 · Interaction patterns
512
579
 
513
- - 16px bell icon, dot for unread count.
514
- - Panel: 360px wide, scrolls, items 64px tall, hairline separators.
580
+ ### 9.1 The five inviolable rules
515
581
 
516
- ### 9.16 Search modal
517
-
518
- - 600px wide, 80vh max height.
519
- - Input at top (large), results list below.
520
- - Each result: icon + title + path (mono, dim) + kbd hint.
521
- - Arrow keys to navigate, Enter to open.
522
-
523
- ### 9.17 Sparkline & metric charts
524
-
525
- - Inline SVG, 32px tall, `--accent` stroke 1.5px, gradient fill (8% → 0%).
526
- - Right-aligned delta: `--success` for "up is good", `--error` for "up is bad".
527
- - Numeric body always tabular-nums.
528
-
529
- ### 9.18 Workflow DAG visualizer (v6.0.0)
530
-
531
- Used in Tasks card detail and Eval reports.
532
- - Nodes: rounded rectangles (8px radius), `--bg-elev-2` background, hairline border.
533
- - Node states: idle / running / done / failed / skipped — colored border + center dot.
534
- - Edges: 1.5px lines in `--text-dim`, animated dashed line on the "currently running" edge.
535
- - Vertical timeline: time on the left axis in mono.
536
-
537
- ### 9.19 Approval queue (v6.0.0)
538
-
539
- Used in Plans & Memory tabs.
540
- - Each row: 56px tall, agent avatar + plan title + target file (mono) + Approve / Steer / Reject buttons.
541
- - Hairline separators; rejected plans get a thin `--error-soft` wash on hover-to-undo.
542
- - Bulk action toolbar floats above the queue when ≥1 selected.
543
-
544
- ### 9.20 Cost / token chart card (v6.0.0)
545
-
546
- Used in Usage (MiniMax) and Overview.
547
- - Card: title + period selector (24h / 7d / 30d) + big numeric + sparkline + breakdown bars.
548
- - Breakdown bars: horizontal stacked bar by model, `--accent` for primary, `--text-dim` for others.
549
- - Always tabular-nums. Always right-aligned.
550
-
551
- ### 9.21 BG agent live panel (v6.0.0)
582
+ 1. **Right-click is sacred.** Every interactive surface has a `ContextMenu`. No element falls back to the browser default.
583
+ 2. **Keyboard parity.** Every action has a shortcut. Every menu item shows the shortcut right-aligned in `Kbd` style.
584
+ 3. **Cmd+K is everything.** Cmd+K opens the command palette, which contains every page, every action, every setting, every shortcut reference.
585
+ 4. **Optimistic by default.** Mutations apply instantly; rollback on error with a toast. No spinners on the user's own actions.
586
+ 5. **Real-time by default.** Live data refreshes via WS without user action; the green pulse indicator shows the connection is live.
552
587
 
553
- Used in Active tab.
554
- - Row: 56px tall, agent avatar + name + status pill + elapsed (mono, 1s tick) + action buttons (pause / steer / stop).
555
- - Status pill variants: `running` (success pulse) / `paused` (warning) / `stuck` (warning static + Retry) / `done` (text-dim).
556
- - Collapsed by default, expands to show streaming output and tool calls.
588
+ ### 9.2 Right-click context menus
557
589
 
558
- ---
590
+ Right-click menus replace browser defaults everywhere except in `<input>`, `<textarea>`, and `[contenteditable]`. The trigger is `onContextMenu` on the element, opening a Radix `ContextMenu`.
559
591
 
560
- ## 10 · Patterns
592
+ ```tsx
593
+ <KanbanCard onContextMenu={(e) => {
594
+ e.preventDefault();
595
+ openContextMenu(task.id, e);
596
+ }}>
597
+ ...
598
+ </KanbanCard>
599
+ ```
561
600
 
562
- ### 10.1 Layout shells
601
+ Every context menu follows this structure:
563
602
 
564
- Three layouts selectable in Settings → UI → Layout:
603
+ ```
604
+ ┌─────────────────────────────────────┐
605
+ │ Open in drawer ⌘↵ │
606
+ │ Edit E │
607
+ │ Duplicate ⇧D │
608
+ │ Copy link ⌥L │
609
+ │ ──────────────────────────────── │
610
+ │ Assign to agent ▸ │
611
+ │ Move to column ▸ │
612
+ │ Set priority ▸ │
613
+ │ ──────────────────────────────── │
614
+ │ Archive ⌘⇧A │
615
+ │ Delete (danger) ⌫ │
616
+ └─────────────────────────────────────┘
617
+ ```
565
618
 
566
- | Layout | Topbar tabs | Sidebar nav | Main grid |
567
- |---|---|---|---|
568
- | `topbar` | visible | hidden | topbar + view |
569
- | `sidebar` | collapsed (no tabs row) | visible | sidebar + view |
570
- | `both` | collapsed | visible | sidebar + view + small topbar |
619
+ The keyboard equivalent is **Shift+F10** when the element has focus. We render the same menu for both triggers.
571
620
 
572
- Default is `sidebar` (v6.0.0). Switching layouts preserves the active
573
- tab.
621
+ ### 9.3 Keyboard shortcuts
574
622
 
575
- ### 10.2 3-column chat
623
+ Every shortcut is registered in `ui/utils/shortcuts.ts` and bound through `useHotkeys`. Shortcuts are scoped:
576
624
 
577
- ```
578
- ┌────────┬──────────────────────────────┬─────────┐
579
- │ Rail │ Thread │ Info │
580
- 280px │ flex │ 320px │
581
- │ │ │ │
582
- │ │ [composer always at bottom] │ │
583
- └────────┴──────────────────────────────┴─────────┘
584
- ```
625
+ | Scope | Modifiers | Examples |
626
+ |--|--|--|
627
+ | **Global** | `Cmd`/`Ctrl` | `Cmd+K` palette, `Cmd+B` sidebar, `Cmd+/` shortcuts |
628
+ | **Tasks view** | none (when focused) | `C` new, `E` edit, `/` search, `1-9` jump column |
629
+ | **Anywhere** | `Cmd` | `Cmd+S` save (if open editor), `Cmd+,` settings |
585
630
 
586
- - All three columns scroll independently.
587
- - Composer sticks to bottom of thread column (`position: sticky`,
588
- `bottom: 0`, `--bg-elev` backdrop).
589
- - Info panel collapses below 1100px (becomes a sheet above 768px).
631
+ Shortcuts ignore typing when an `<input>` or `<textarea>` has focus unless the modifier is `Cmd`/`Ctrl`. The Command Palette shows all available shortcuts and is searchable.
590
632
 
591
- ### 10.3 Streaming thread
633
+ ### 9.4 Command Palette (Cmd+K)
592
634
 
593
- When a session is in `streaming` state:
635
+ Built on `cmdk` (the same library Linear uses). Triggers:
594
636
 
595
- - Source badge in thread head pulses `--success` glow.
596
- - Subtitle reads "Replying · odin · open-design".
597
- - Footer of thread shows three pulsing dots in `--accent`.
598
- - Composer is disabled (`pointer-events: none` on the textarea, send
599
- button replaced with a small stop icon).
637
+ | Command | Description |
638
+ |--|--|
639
+ | `Cmd+K` (Mac) / `Ctrl+K` (Win/Linux) | Open |
640
+ | `Esc` | Close |
641
+ | `↑↓` | Navigate |
642
+ | `↵` | Execute |
643
+ | `Tab` | Switch scope (Actions / Pages / Settings) |
600
644
 
601
- ### 10.4 Active tab navigation
645
+ Three scopes (tabs):
646
+ 1. **Actions** — quick mutations on the current selection. If nothing is selected, falls back to general actions.
647
+ 2. **Navigate** — every page, with breadcrumbs.
648
+ 3. **Settings** — every settings key, jump to its setting page.
602
649
 
603
- - Active tab has accent underline (topbar) or accent background
604
- (sidebar).
605
- - Keyboard: `1`–`9` for first 9 tabs, `0` for Overview (v3.2.0).
606
- - Browser back/forward navigates tab history.
650
+ The palette has a fuzzy-search input at the top, a list of matches, and a footer showing the current scope + scope-switch hint.
607
651
 
608
- ### 10.5 Status of background agents
652
+ ### 9.5 Optimistic mutations
609
653
 
610
- `Active` tab shows live background agents. Each row:
654
+ Every mutation goes through `useMutation` from TanStack Query:
611
655
 
612
- ```
613
- [●] odin odin@open-design · streaming 4m12s [pause][steer][stop]
656
+ ```ts
657
+ const updateTask = useMutation({
658
+ mutationFn: api.tasks.update,
659
+ onMutate: (newTask) => {
660
+ queryClient.setQueryData(['tasks'], applyUpdate(old, newTask));
661
+ return { previous: old };
662
+ },
663
+ onError: (_err, _vars, ctx) => {
664
+ queryClient.setQueryData(['tasks'], ctx?.previous);
665
+ toast.error('Could not save — reverted');
666
+ },
667
+ onSettled: () => queryClient.invalidateQueries(['tasks']),
668
+ });
614
669
  ```
615
670
 
616
- - Dot color = agent state.
617
- - Time elapsed updates every second (`--motion-fast`).
618
- - Action buttons are `.btn-sm .btn-ghost`.
619
- - Stuck agents (>5 min no progress) get a yellow dot + a `Retry`
620
- button.
671
+ The UI updates instantly; the toast confirms or reverts. No spinners on user-initiated mutations.
621
672
 
622
- ### 10.6 Memory sources
673
+ ### 9.6 Real-time updates
623
674
 
624
- 4 sources, each with its own glyph + accent-tinted background:
675
+ The dashboard maintains a single WebSocket connection (`/ws/dashboard`) that streams:
625
676
 
626
- | Source | Glyph | Accent |
627
- |---|---|---|
628
- | project notes | `Brain` | `--accent` |
629
- | skills | `Sparkles` | `--accent-2` |
630
- | tasks | `CheckSquare` | `--success` |
631
- | activity log | `Activity` | `--info` |
677
+ - `tasks:change` task created/updated/deleted
678
+ - `agents:change` — agent registered/deregistered
679
+ - `goals:change` goal progress tick
680
+ - `activity:event` new event in activity log
681
+ - `routing:decision` new routing decision
682
+ - `cost:tick` cost reservation update
683
+ - `system:status` — health, version, build
632
684
 
633
- A unified search bar queries all 4 in parallel; results are grouped by
634
- source with the matching glyph on the left of each row.
685
+ All hooks consume these via `useWebSocket` + React Query cache invalidation. The connection state shows in the topbar's status pill (green pulse = connected, amber = reconnecting, red = offline).
635
686
 
636
- ### 10.7 Cline runtime badge (v6.0.0)
687
+ ### 9.7 Hover & focus
637
688
 
638
- ```
639
- ┌──────────────────────────┐
640
- │ ● Cline · active │ ← pulse when state=active
641
- └──────────────────────────┘
642
- ```
689
+ - Hover previews use `HoverCard` with a 400ms delay, 200ms close.
690
+ - Focus rings: `--focus-ring` 2px outline + 2px offset, always visible on keyboard focus, never on mouse click.
691
+ - Tooltip: 4-side aware, 200ms delay, `--motion-base` ease.
643
692
 
644
- 8px dot, label in mono. Lives in topbar-right. `active` = pulsing
645
- green. `idle` = static dim. `unavailable` = static red. `unknown` =
646
- static gray.
693
+ ### 9.8 Empty states
647
694
 
648
- ### 10.8 Doctor / Harness status pills
695
+ (See §7.7.) Every collection has a deliberate empty state with one CTA. We never say "Nothing to see here." We always say what to do next.
649
696
 
650
- Subsystem status: 4 pill states, 5-dim progress bars.
697
+ ---
651
698
 
652
- ```
653
- [●] Cline runtime active ▰▰▰▰▰▱▱▱▱ 5/8
654
- [●] Task scheduler active ▰▰▰▰▰▰▱▱▱ 6/8
655
- [●] Memory store degraded ▰▰▰▱▱▱▱▱▱ 3/8
656
- [●] WebSocket active ▰▰▰▰▰▰▰▰▱ 7/8
657
- ```
699
+ ## 10 · Settings model
658
700
 
659
- Pills are pill-success / pill-warning / pill-error as appropriate.
660
- Progress bars: `--bg-elev-2` track, `--accent` fill. **No colored
661
- track backgrounds** — color stays on the fill, not on the rail.
701
+ Settings is hierarchical, scoped, and always findable. The full settings surface lives at `/settings/*` with a sidebar in the page itself (not the global sidebar).
662
702
 
663
- ### 10.9 Overview dashboard layout (v6.0.0)
703
+ ### 10.1 Section structure
664
704
 
665
705
  ```
666
- ┌────────────────────────────────────────────────────────────────┐
667
- │ HEADER: ⌂ Bizar project▾ ⌘K Search • ws·live • cline │
668
- ├────────────────────────────────────────────────────────────────┤
669
- │ HERO ROW (4 cards): │
670
- │ ┌────────────┐ ┌────────────┐ ┌────────────┐ ┌────────────┐
671
- │ │ tokens/hr │ latency │ error rate │ │ cost/hr │ │
672
- │ │ 1.42M │ 842ms │ 0.21% │ │ $1.84 │ │
673
- │ │ +12% ▲ │ −18ms ▼ │ │ +0.04 ▲ │ │ −8% ▼ │ │
674
- │ └────────────┘ └────────────┘ └────────────┘ └────────────┘ │
675
- ├────────────────────────────────────────────────────────────────┤
676
- │ TWO-COL: │
677
- │ ┌──────────────────────┐ ┌──────────────────────────────┐
678
- │ │ Live activity feed │ Active agents (3 running) │ │
679
- │ │ (timestamped rows) │ │ (status rows w/ pause) │ │
680
- │ │ │ │ │ │
681
- │ │ │ Memory health │ │
682
- │ │ │ (4 sources at a glance) │ │
683
- │ └──────────────────────┘ └──────────────────────────────┘ │
684
- ├────────────────────────────────────────────────────────────────┤
685
- │ GRAPH ROW: │
686
- │ ┌──────────────────────────────────────────────────────────┐ │
687
- │ │ Token spend · last 24h (large sparkline + breakdown) │ │
688
- │ └──────────────────────────────────────────────────────────┘ │
689
- └────────────────────────────────────────────────────────────────┘
706
+ /settings
707
+ ├── /general Workspace name, logo, default project
708
+ ├── /appearance Theme, density, accent color (future)
709
+ ├── /agents Default agent roster, max concurrency
710
+ ├── /goals Goal cadence, review interval
711
+ ├── /tasks Default workflow, custom statuses, kanban config
712
+ ├── /skills Skill library, default skill, auto-suggest
713
+ ├── /mcps MCP servers, auth, per-tool permissions
714
+ ├── /hooks Hook config (Pre/Post/UserPrompt)
715
+ ├── /routing Model tiers, cost ceiling, fallback
716
+ ├── /memory Vault location, retention, distillation
717
+ ├── /notifications Per-event toggles, channels
718
+ ├── /security Webhook secrets, HMAC keys, PII mode
719
+ ├── /integrations GitHub, Slack, webhooks
720
+ ├── /billing Cost gate, room budget, alerts
721
+ ├── /team Members, roles (future)
722
+ └── /advanced Debug, traces, export/import, reset
690
723
  ```
691
724
 
692
- ### 10.10 Cost dashboard layout (Usage tab)
693
-
694
- ```
695
- ┌────────────────────────────────────────────────────────────────┐
696
- │ HEADER Usage · 24h ▾ $1.84/hr −8% ▲ │
697
- ├────────────────────────────────────────────────────────────────┤
698
- │ STAT CARDS (4): │
699
- │ [spent 24h] [cost/hr] [tokens/hr] [alerts] │
700
- ├──────────────────────────────┬─────────────────────────────────┤
701
- │ TOKEN SPEND CHART │ MODEL BREAKDOWN │
702
- │ (stacked area, last 24h) │ (horizontal bars per model) │
703
- │ │ │
704
- ├──────────────────────────────┼─────────────────────────────────┤
705
- │ RECENT ALARMS │ BUDGET STATUS │
706
- │ (timeline of cost spikes) │ (4 budgets, percent gauges) │
707
- └──────────────────────────────┴─────────────────────────────────┘
708
- ```
725
+ ### 10.2 Settings page pattern
709
726
 
710
- ### 10.11 Active BG agents layout
727
+ Every settings page follows the same skeleton:
711
728
 
712
729
  ```
713
- ┌────────────────────────────────────────────────────────────────┐
714
- HEADER Active · 3 running 1 paused 1 stuck
730
+ ┌─ ViewHeader ────────────────────────────────────────────────────┐
731
+ Settings · Agents [ Save changes ]
732
+ │ Default roster and concurrency for new sessions. │
715
733
  ├────────────────────────────────────────────────────────────────┤
716
- ROW (collapsible, default collapsed):
717
- odin streaming 4m12s [pause][steer][stop][expand]
718
- expanded: streaming output + tool call list ─
719
-
720
- thor paused 8m03s [resume][steer][stop]
721
- mimir stuck 5m21s [retry][steer][stop]
722
- tyr done 2m41s [restart][remove]
734
+ ┌─ FieldGroup ──────────────────────────────────────────────┐
735
+ │ Default roster size [ 8 ] — help text
736
+ │ Max concurrent agents [ 16 ] — help text │
737
+ Agent types [ multi-select ] — help text │ │
738
+ │ Auto-spawn on session [ toggle ON ] — help text
739
+ └──────────────────────────────────────────────────────────┘
740
+ ┌─ FieldGroup ──────────────────────────────────────────────┐
741
+ │ │ Restart agents on config change [ toggle OFF ] │ │
742
+ │ └──────────────────────────────────────────────────────────┘ │
723
743
  └────────────────────────────────────────────────────────────────┘
724
744
  ```
725
745
 
726
- ### 10.12 Settings mode (v4.9.0)
746
+ A field group is a `Card` containing one or more `Field` rows. Each field has a label, control, and helper text (one short sentence). Fields auto-save on blur with an inline checkmark; an explicit "Save changes" button is reserved for grouped forms.
727
747
 
728
- When the user enters the Settings tab, the sidebar replaces its
729
- tab list with the full SettingsNav (16 sections). The active section
730
- lights up in the sidebar and the main panel scrolls to it.
748
+ ### 10.3 Settings discovery
731
749
 
732
- ```
733
- ┌──────┬───────────────────────────────────────────────┐
734
- ⌂ │ Theme │
735
- │ 💬 │ ────── │
736
- │ 🤖 │ Accent color [color picker] │
737
- │ ... │ Font family [Inter ▾] │
738
- │ ⚙ → │ Compact mode [▢] │
739
- │ │ │
740
- │ ▼ │ Layout │
741
- │ Theme│ ────── │
742
- │ Layo │ UI layout (•) sidebar ( ) topnav ( ) both│
743
- │ Net │ Show header [✓] │
744
- │ Auth │ │
745
- │ ... │ │
746
- └──────┴───────────────────────────────────────────────┘
747
- ```
750
+ - Every setting is reachable via Cmd+K (palette).
751
+ - Every setting is reachable via `/settings` breadcrumb.
752
+ - The settings sidebar is **the only** place that lives in the page (not the global sidebar) so it has room to breathe.
748
753
 
749
754
  ---
750
755
 
751
- ## 11 · Iconography
756
+ ## 11 · Accessibility
752
757
 
753
- Lucide React. 1.6 stroke width. Two sizes:
758
+ WCAG 2.2 AA is the floor. We aim higher where it does not cost.
754
759
 
755
- | Size | Use |
756
- |---|---|
757
- | 11px | Inline-with-text icons (chat thread head, info panel headers) |
758
- | 12px | Button icons, badge icons |
759
- | 14px | Topbar & sidebar nav icons |
760
- | 16px | Card-level icons |
761
- | 18px | Sidebar collapsed icons (intentional bump for visibility) |
762
- | 20px | Hero / empty-state |
760
+ ### 11.1 Color & contrast
763
761
 
764
- The runic `ᛒ` (berkanan) is the brand glyph not a Lucide icon. Always
765
- rendered in `var(--accent)` at 24px in the topbar brand block, 14px in
766
- the collapsed sidebar footer.
762
+ - All text/background pairs meet **AA 4.5:1** (body) and **AA 3:1** (large text, icons).
763
+ - Charts use shape + color (never color alone).
764
+ - Status indicators always have a shape or label in addition to color (green dot + "live"; red dot + "errored").
767
765
 
768
- ---
766
+ ### 11.2 Keyboard
769
767
 
770
- ## 12 · Accessibility
768
+ - Every interactive element is reachable via Tab.
769
+ - Focus order is visual order.
770
+ - Focus ring is always visible on keyboard focus.
771
+ - Modals trap focus; popovers return focus on close.
772
+ - Drag-and-drop has a keyboard alternative (`Space` to pick up, arrows to move, `Enter` to drop, `Esc` to cancel).
771
773
 
772
- - **WCAG 2.2 AA** contrast on all body text vs its surface.
773
- - `:focus-visible` ring: 2px `--accent` outline, 2px offset, 4px
774
- radius.
775
- - Keyboard navigation: tab order follows visual order. Modals trap
776
- focus. Esc closes. `Cmd/Ctrl+K` opens search.
777
- - Skip-to-main link (v4.8.0): visually hidden until focused, then pops
778
- in at top-left.
779
- - `aria-current="true"` on active nav, active session.
780
- - `aria-live="polite"` on the chat log region.
781
- - `aria-selected` on tabs.
782
- - Color is never the sole signal — always pair with text or icon.
774
+ ### 11.3 Screen readers
783
775
 
784
- ---
785
-
786
- ## 13 · Responsive
776
+ - Every icon-only button has `aria-label`.
777
+ - Every form control has a `<label>` (visible or sr-only).
778
+ - Live regions (`aria-live="polite"`) for activity updates and toasts.
779
+ - Tables use `<th scope="col">`; data tables announce sort state.
787
780
 
788
- Three breakpoints (in addition to mobile which has a dedicated shell
789
- `MobileApp.tsx`):
781
+ ### 11.4 Motion
790
782
 
791
- | Breakpoint | Behavior |
792
- |---|---|
793
- | 1440px | 3-column chat, sidebar + topbar visible |
794
- | 1100–1439 | 3-column chat, sidebar collapses to icons, info panel optional |
795
- | 768–1099 | Topbar-only layout, info panel becomes sheet |
796
- | < 768 | Mobile shell takes over (separate code path) |
783
+ - `prefers-reduced-motion` zeroes motion tokens (§6.3).
784
+ - Auto-playing animations have a pause control.
785
+ - Drag/drop has a non-motion alternative.
797
786
 
798
- The desktop dashboard never tries to reflow to mobile — `MobileApp.tsx`
799
- is its own tree with its own components.
800
-
801
- ---
787
+ ### 11.5 Touch & pointer
802
788
 
803
- ## 14 · Anti-patterns (audited before each PR)
804
-
805
- These break the design system. Any of these in a PR gets a review
806
- blocker.
807
-
808
- - ❌ **Left color stripes on containers.** `box-shadow: inset 2px 0 0`,
809
- `border-left: 3px solid`, or any vertical accent edge. Use background,
810
- weight, glow, or motion instead.
811
- - ❌ **Purple gradient backgrounds behind text or as page chrome.**
812
- Gradients are reserved for the greeting/brand mark only.
813
- - ❌ **Generic emoji as feature icons** in cards, lists, or empty
814
- states. Use Lucide or `ᛒ`.
815
- - ❌ **Spinners on disabled buttons.** Use a button-loading state or
816
- replace the button with the spinner.
817
- - ❌ **Inter as display face at >32px.** Inter is body. If you need a
818
- display face, propose it in a PR and add the stack to `--font-display`.
819
- - ❌ **Filler copy**: "Feature One", "Lorem ipsum", invented metrics.
820
- - ❌ **Raw hex outside `:root`.** All colors must reference a token.
821
- - ❌ **Row striping in tables.** Use hover wash only.
822
- - ❌ **Shadowed hairlines.** Borders OR shadows, not both.
823
- - ❌ **Status conveyed by color alone.** Always pair with text/icon.
824
- - ❌ **Decimal alignment broken.** Numerics in tables must use
825
- `tabular-nums` or be right-aligned.
826
- - ❌ **Horizontal scroll on viewport ≥ 1100px.** If your component
827
- breaks the layout, fix the component.
789
+ - Minimum target size: **44x44px** for touch (mobile/tablet), **24x24px** for desktop.
790
+ - Right-click has a long-press alternative on touch (650ms hold).
791
+ - Hover-only patterns have a focus equivalent.
828
792
 
829
793
  ---
830
794
 
831
- ## 15 · View index & data shapes
832
-
833
- Every view declares the data it consumes. Mock data lives in
834
- `canvas.html` for visual development; the live API endpoint that
835
- backs each view is documented in `docs/api.md`.
836
-
837
- ### 15.1 Overview
838
-
839
- **Layout:** §10.9. **Endpoint:** `GET /snapshot.overview`.
840
-
841
- ```ts
842
- interface OverviewData {
843
- // Live activity (last 50 items, newest first)
844
- recentActivity: ActivityItem[];
845
-
846
- // Hero metrics
847
- metrics: {
848
- tokensPerHour: number;
849
- avgLatencyMs: number;
850
- errorRate: number; // 0..1
851
- costPerHour: number; // USD
852
- activeBgAgents: number;
853
- activeSessions: number;
854
- };
855
-
856
- // Active agents (subset of BackgroundAgents)
857
- activeAgents: BgInstance[];
858
-
859
- // Memory health (4 sources)
860
- memoryHealth: {
861
- source: 'lightrag' | 'obsidian' | 'gitsync' | 'semantic';
862
- state: 'ok' | 'degraded' | 'down';
863
- lastSync: string;
864
- }[];
865
-
866
- // Token spend chart (last 24h, hourly buckets)
867
- tokenSpend: { hour: string; tokens: number; cost: number }[];
868
- }
869
- ```
870
-
871
- ### 15.2 Chat
872
-
873
- **Layout:** §10.2. **Endpoints:** `GET /snapshot.sessions` (list),
874
- `GET /api/cline-sessions` (cline), `POST /api/chat` (send),
875
- `WS /ws` (stream).
876
-
877
- ```ts
878
- interface ChatSession {
879
- id: string;
880
- title: string;
881
- mtime: number;
882
- state: 'idle' | 'streaming' | 'awaiting';
883
- source: 'bizar' | 'cline';
884
- agent: string;
885
- unread?: number;
886
- pinned?: boolean;
887
- tree?: { root: AgentTreeNode }; // orchestrator sub-agents
888
- }
889
-
890
- interface ChatMessage {
891
- id: number;
892
- role: 'user' | 'assistant' | 'tool';
893
- author: string;
894
- ts: string; // HH:MM
895
- text: ReactNode;
896
- toolCalls?: ToolCall[];
897
- pinned?: boolean;
898
- }
899
- ```
900
-
901
- ### 15.3 Agents
902
-
903
- **Layout:** Roster grid (3-col on ≥1440px, 2-col on ≥1024px, 1-col
904
- below). **Endpoint:** `GET /snapshot.agents`.
905
-
906
- ```ts
907
- interface Agent {
908
- name: string; // 'odin', 'thor', 'mimir', ...
909
- model: string; // 'anthropic/claude-sonnet-4-6'
910
- mode: string; // 'plan-then-forseti'
911
- status: 'idle' | 'busy' | 'stuck' | 'down';
912
- lastSeen: number;
913
- tasksCompleted: number;
914
- avgLatencyMs: number;
915
- }
916
- ```
917
-
918
- Each card: avatar (first 2 letters), name (mono), model (dim mono),
919
- status pill, last seen time, 3 mini stats.
920
-
921
- ### 15.4 Glyphs (Artifacts)
922
-
923
- **Layout:** Masonry grid of square cards. **Endpoint:**
924
- `GET /snapshot.artifacts`.
925
-
926
- ```ts
927
- interface Artifact {
928
- id: string;
929
- title: string;
930
- kind: 'glyph' | 'note' | 'doc';
931
- createdAt: number;
932
- thumbnail?: string; // data URL or absent
933
- size: number; // bytes
934
- }
935
- ```
936
-
937
- ### 15.5 Tasks
938
-
939
- **Layout:** 5-column kanban (§9.12). **Endpoint:** `GET /snapshot.tasks`.
940
-
941
- ```ts
942
- interface Task {
943
- id: string; // 'T-120'
944
- title: string;
945
- col: 'backlog' | 'todo' | 'in_progress' | 'review' | 'done';
946
- priority: 'high' | 'mid' | 'low';
947
- tags: string[];
948
- team?: boolean; // v6 team badge
949
- by: string; // agent name
950
- when: string; // 'now', '3h', '1d'
951
- }
952
- ```
795
+ ## 12 · Banned tropes
953
796
 
954
- ### 15.6 Activity
797
+ Audited before every PR via `scripts/check-design-tropes.sh`.
955
798
 
956
- **Layout:** Timeline (§9.7). **Endpoint:** `WS /api/activity/stream`.
799
+ - **No gradients.** Anywhere. As backgrounds, as fills, as borders, as button hovers. The accent color is solid. Charts use solid fills. Period.
800
+ - **No vertical accent stripes on containers.** Active state uses background tint + weight + motion. The single permitted edge bar is the 2px active-item bar inside `SidebarItem` (§7.3).
801
+ - **No purple, blue, or rainbow washes.** The accent is green. Charts are grayscale. Status colors are semantic.
802
+ - **No emoji in UI copy.** Use Lucide icons.
803
+ - **No "Lorem ipsum".** Every placeholder is realistic.
804
+ - **No "Feature One / Feature Two".** Labels are real.
805
+ - **No "Loading…" spinners as primary state.** Use skeleton or streaming copy ("Fetching agents…").
806
+ - **No default browser context menus** on any interactive surface.
807
+ - **No modal-on-modal stacking.** A modal cannot open another modal without an explicit close.
808
+ - **No tooltips on disabled buttons.** Tooltip on hover only when the action is enabled; if disabled, helper text appears inline.
809
+ - **No invented metrics.** Real numbers or "—" placeholder.
810
+ - **No glass / blur / noise effects.** Surfaces are solid fills.
811
+ - **No animated icons** except the live indicator pulse.
957
812
 
958
- ```ts
959
- interface ActivityItem {
960
- kind: 'agent' | 'task' | 'error' | 'info';
961
- ts: string; // HH:MM
962
- text: ReactNode; // allows inline mono spans
963
- target?: string; // optional file/task id
964
- }
965
- ```
966
-
967
- ### 15.7 Active (Background agents)
968
-
969
- **Layout:** §10.11. **Endpoints:** `GET /background`, `WS bg:*`.
970
-
971
- ```ts
972
- interface BgInstance {
973
- instanceId: string;
974
- agent: string;
975
- prompt: string;
976
- status: 'pending' | 'running' | 'paused' | 'done' | 'failed';
977
- startedAt: number;
978
- elapsedMs: number;
979
- toolCalls: BgToolCall[];
980
- output: string; // last 32k chars
981
- stuck?: boolean; // server-flagged
982
- }
983
- ```
984
-
985
- ### 15.8 Skills
986
-
987
- **Layout:** Card grid (3-col), each card collapsible. **Endpoint:**
988
- `GET /skills` (planned).
989
-
990
- ```ts
991
- interface Skill {
992
- id: string; // 'design-taste-frontend'
993
- name: string;
994
- description: string;
995
- enabled: boolean;
996
- triggers: string[];
997
- updatedAt: number;
998
- }
999
- ```
1000
-
1001
- ### 15.9 Memory
1002
-
1003
- **Layout:** 3-column (source rail · main panel · detail). **Endpoint:**
1004
- `GET /memory/overview`, `GET /memory/{source}`, `POST /memory/search`.
1005
-
1006
- ```ts
1007
- interface MemoryOverview {
1008
- sources: {
1009
- id: 'lightrag' | 'obsidian' | 'gitsync' | 'semantic';
1010
- state: 'ok' | 'degraded' | 'down';
1011
- noteCount: number;
1012
- lastSync: number;
1013
- }[];
1014
- recent: MemoryNote[];
1015
- }
1016
-
1017
- interface MemoryNote {
1018
- id: string;
1019
- source: MemoryOverview['sources'][number]['id'];
1020
- title: string;
1021
- preview: string;
1022
- tags: string[];
1023
- updatedAt: number;
1024
- }
1025
- ```
1026
-
1027
- ### 15.10 Mods
813
+ ---
1028
814
 
1029
- **Layout:** List of installed mods with enable/disable, install new
1030
- from URL. **Endpoint:** `GET /mods`, `POST /mods/install`.
815
+ ## 13 · Visual contract for new screens
816
+
817
+ A new screen must:
818
+
819
+ 1. Pick one of the seven layouts from §7 (default: topbar + sidebar).
820
+ 2. Use tokens from §3 only — never raw colors.
821
+ 3. Use type from §4 only — never custom families.
822
+ 4. Use motion from §6 only — never bespoke easings.
823
+ 5. Use icons from `lucide-react` — never emoji or custom SVGs (unless domain-specific, in which case it goes in `ui/icons/`).
824
+ 6. Use components from `ui/` only — never rebuild primitives.
825
+ 7. Honor density mode (§5.3).
826
+ 8. Honor `prefers-reduced-motion`.
827
+ 9. Honor `prefers-color-scheme` via the theme system.
828
+ 10. Have right-click context menus on every interactive element.
829
+ 11. Have keyboard shortcuts for every action.
830
+ 12. Have an empty state, a loading state, and an error state.
831
+ 13. Have at least one place where the green accent earns its keep.
832
+ 14. Document its data shape in `bizar-dash/src/web/views/<name>/README.md`.
833
+ 15. Have a colocated `.test.tsx` file with the AAA pattern.
1031
834
 
1032
- ```ts
1033
- interface Mod {
1034
- id: string;
1035
- name: string;
1036
- version: string;
1037
- enabled: boolean;
1038
- hasViews: boolean;
1039
- installPath: string;
1040
- updatedAt: number;
1041
- }
1042
- ```
835
+ ---
1043
836
 
1044
- ### 15.11 Schedules
837
+ ## 14 · Pre-merge checklist
1045
838
 
1046
- **Layout:** Card list with cron expression, last run, next run,
1047
- toggle. **Endpoint:** `GET /schedules`.
839
+ Run before opening a PR that touches UI:
1048
840
 
1049
- ```ts
1050
- interface Schedule {
1051
- id: string;
1052
- name: string;
1053
- cron: string; // '0 */6 * * *'
1054
- prompt: string;
1055
- agent: string;
1056
- enabled: boolean;
1057
- lastRun: number | null;
1058
- lastResult: 'ok' | 'fail' | null;
1059
- nextRun: number;
1060
- }
841
+ ```sh
842
+ pnpm check:design-tropes # grep for banned patterns (§12)
843
+ pnpm check:a11y # axe-core on every new page
844
+ pnpm check:visual # screenshot diff at 1440/1100/768/390
845
+ pnpm test -- ui # component tests
846
+ pnpm e2e # full app boots, no console errors
847
+ pnpm check:keyboard # manual keyboard-only walkthrough (CI recorded)
1061
848
  ```
1062
849
 
1063
- ### 15.12 Usage (MiniMax)
850
+ All five must pass. The visual diff must not regress at any of the four widths. The keyboard walkthrough must reach every interactive element via Tab only.
1064
851
 
1065
- **Layout:** §10.10. **Endpoint:** `GET /api/usage?range=24h|7d|30d`.
1066
-
1067
- ```ts
1068
- interface UsageData {
1069
- range: '24h' | '7d' | '30d';
1070
- totalCost: number;
1071
- totalTokens: number;
1072
- costPerHour: number;
1073
- byModel: { model: string; tokens: number; cost: number }[];
1074
- byHour: { hour: string; tokens: number; cost: number }[];
1075
- alerts: { ts: number; severity: 'warn' | 'error'; text: string }[];
1076
- budgets: { id: string; label: string; cap: number; spent: number }[];
1077
- }
1078
- ```
852
+ ---
1079
853
 
1080
- ### 15.13 Eval
854
+ ## Appendix A · shadcn preset `b7kBsBkh7b`
1081
855
 
1082
- **Layout:** Run list (top) + last run detail (bottom). **Endpoint:**
1083
- `GET /eval/runs`, `GET /eval/runs/:id`.
856
+ The dashboard is initialized with:
1084
857
 
1085
- ```ts
1086
- interface EvalRun {
1087
- id: string;
1088
- startedAt: number;
1089
- finishedAt: number | null;
1090
- passed: number;
1091
- total: number;
1092
- cases: { name: string; pass: boolean; latencyMs: number }[];
1093
- }
858
+ ```sh
859
+ pnpm dlx shadcn@latest init --preset b7kBsBkh7b
1094
860
  ```
1095
861
 
1096
- ### 15.14 Doctor
862
+ Per the [shadcn CLI v4 changelog](https://ui.shadcn.com/docs/changelog/2026-03-cli-v4), presets are opaque codes resolved by the CLI. The `b7kBsBkh7b` preset ships:
1097
863
 
1098
- **Layout:** Hero score + 8 subsystem cards (§9.18). **Endpoint:**
1099
- `GET /doctor`.
864
+ - Pre-configured `components.json` (style: `new-york`, base color: `neutral`, CSS variables: `yes`, icon library: `lucide`).
865
+ - Pre-tuned `tailwind.config.ts` with the OKLch color ramp.
866
+ - Pre-installed primitives matching the foundation in §3.
1100
867
 
1101
- ```ts
1102
- interface DoctorData {
1103
- checkedAt: number;
1104
- overall: number; // 0..8
1105
- subsystems: {
1106
- name: string;
1107
- state: 'ok' | 'degraded' | 'warning' | 'error';
1108
- score: number;
1109
- total: number;
1110
- note: string;
1111
- }[];
1112
- }
1113
- ```
868
+ If the preset resolves to a different package set than expected, the plan still holds: §3 is the contract, the preset is the bootstrap. Any preset mismatch is resolved by overriding `components.json` and running `pnpm dlx shadcn@latest add <component>` for each missing primitive in §8.
1114
869
 
1115
- ### 15.15 Harness
870
+ The provided OKLch theme in the user's brief maps directly to §3 — every token in `:root` (light) and `.dark` is taken verbatim from the brief, then extended with the geometry, motion, and z-index tokens that the preset does not cover.
1116
871
 
1117
- **Layout:** Audit rules list + 6/6 pass badge. **Endpoint:**
1118
- `GET /harness/audit`.
872
+ ---
1119
873
 
1120
- ```ts
1121
- interface HarnessAudit {
1122
- version: string;
1123
- rules: { rule: string; pass: boolean; detail: string }[];
1124
- }
874
+ ## Appendix B · File map
875
+
876
+ ```
877
+ bizar-dash/src/web/
878
+ ├── App.tsx
879
+ ├── main.tsx
880
+ ├── ui/
881
+ │ ├── index.ts # barrel export
882
+ │ ├── primitives/
883
+ │ ├── controls/
884
+ │ ├── feedback/
885
+ │ ├── data/
886
+ │ ├── navigation/
887
+ │ ├── kanban/
888
+ │ ├── popups/
889
+ │ ├── theme/
890
+ │ ├── hooks/
891
+ │ ├── utils/
892
+ │ └── styles/
893
+ │ ├── reset.css
894
+ │ ├── tokens.css # the entire §3, generated from JSON
895
+ │ └── globals.css
896
+ ├── views/
897
+ │ ├── Overview/
898
+ │ ├── Tasks/
899
+ │ ├── Goals/
900
+ │ ├── Agents/
901
+ │ ├── Activity/
902
+ │ ├── Memory/
903
+ │ ├── Libraries/
904
+ │ └── Settings/
905
+ ├── icons/ # domain-specific Lucide extensions
906
+ ├── routes.tsx # TanStack Router route tree
907
+ └── server/ # existing REST API (unchanged)
1125
908
  ```
1126
909
 
1127
- ### 15.16 Settings
1128
-
1129
- **Layout:** §10.12. **Endpoint:** `GET /settings`, `POST /settings`.
1130
-
1131
- 16 sections: theme, updates, layout, general, env-vars, network,
1132
- notifications, auth, agents, dashboard, background, system-llm,
1133
- headroom, activity-log, workspaces, about. Each section is its own
1134
- component in `src/web/views/settings/`.
1135
-
1136
910
  ---
1137
911
 
1138
- ## 16 · Versioning
1139
-
1140
- - v7.0 — this document. Adds view index, data shapes, 5 new component
1141
- patterns (DAG, approvals, cost chart, BG panel, workflow). Token
1142
- system migrated to OKLch + color-mix.
1143
- - v6.0.0 — Cline runtime badge, Harness tab, Tasks kanban team badge,
1144
- brand version pill, Mods-only navigation.
1145
- - v5.x — Eval framework, Doctor page.
1146
- - v4.x — Settings mode, char-counter, semi-collapsed topbar, slash
1147
- commands.
1148
- - v3.x — Mods system, chat overhaul (3-column, rail, info panel),
1149
- semantic spacing aliases, command palette.
1150
- - v2.x — Light theme, kanban board, hooks refactor.
1151
-
1152
- Future changes update this file first, then ship.
912
+ **End of DESIGN.md — v8.0.0**