@cat-factory/app 0.302.2 → 0.303.1

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 (328) hide show
  1. package/README.md +99 -14
  2. package/app/app.config.ts +19 -10
  3. package/app/assets/css/main.css +13 -13
  4. package/app/assets/css/prose.css +22 -22
  5. package/app/assets/css/tokens.css +298 -0
  6. package/app/components/assistant/AssistantModal.vue +22 -22
  7. package/app/components/auth/AuthGate.vue +1 -1
  8. package/app/components/auth/BackendMisconfiguredScreen.vue +10 -10
  9. package/app/components/auth/LoginScreen.vue +34 -36
  10. package/app/components/auth/ResetPasswordScreen.vue +12 -12
  11. package/app/components/auth/UserMenu.vue +4 -4
  12. package/app/components/binaryCandidates/BinaryCandidatesWindow.vue +27 -25
  13. package/app/components/binaryOutput/BinaryOutputReport.vue +15 -15
  14. package/app/components/binaryOutput/StoredAssetView.vue +5 -5
  15. package/app/components/board/AddTaskModal.vue +17 -20
  16. package/app/components/board/AgentFailureCard.vue +11 -11
  17. package/app/components/board/AgentFailureHistory.vue +2 -2
  18. package/app/components/board/BoardCanvas.vue +6 -5
  19. package/app/components/board/CreateInitiativeModal.vue +8 -10
  20. package/app/components/board/DependencyConnectOverlay.vue +1 -1
  21. package/app/components/board/FailureHistoryList.vue +7 -7
  22. package/app/components/board/RecurringPipelineModal.vue +17 -17
  23. package/app/components/board/ReviewFrictionDialog.vue +6 -6
  24. package/app/components/board/StepExecutionHistory.vue +13 -13
  25. package/app/components/board/TaskDependencyEdges.vue +8 -8
  26. package/app/components/board/nodes/AgentChip.vue +10 -10
  27. package/app/components/board/nodes/BlockNode.vue +29 -29
  28. package/app/components/board/nodes/DecisionBadge.vue +2 -2
  29. package/app/components/board/nodes/EpicNode.vue +14 -10
  30. package/app/components/board/nodes/FrameSwimlanes.vue +7 -9
  31. package/app/components/board/nodes/InitiativeCard.vue +8 -8
  32. package/app/components/board/nodes/LaneGroup.vue +1 -1
  33. package/app/components/board/nodes/LaneTask.vue +2 -2
  34. package/app/components/board/nodes/ResizeGrips.vue +4 -4
  35. package/app/components/board/nodes/TaskCard.vue +18 -18
  36. package/app/components/board/nodes/TaskLane.vue +5 -5
  37. package/app/components/board/nodes/TaskPipelineMini.vue +18 -18
  38. package/app/components/bootstrap/AdoptionReviewModal.vue +29 -26
  39. package/app/components/bootstrap/BootstrapModal.vue +21 -23
  40. package/app/components/bootstrap/BootstrapRunSteps.vue +1 -1
  41. package/app/components/brainstorm/BrainstormWindow.vue +30 -33
  42. package/app/components/bugFishing/BugFishingWindow.vue +49 -49
  43. package/app/components/clarity/ClarityReviewWindow.vue +30 -30
  44. package/app/components/common/AsyncViewError.vue +5 -5
  45. package/app/components/common/ClarificationItem.vue +8 -13
  46. package/app/components/common/ConfirmDialog.vue +4 -2
  47. package/app/components/common/DescriptorFields.vue +1 -1
  48. package/app/components/common/EmptyState.vue +3 -3
  49. package/app/components/common/InterviewGateNotice.vue +7 -7
  50. package/app/components/common/KeyboardShortcutsHelp.vue +1 -1
  51. package/app/components/common/MarkdownProse.vue +14 -13
  52. package/app/components/consensus/ConsensusSessionWindow.vue +26 -26
  53. package/app/components/context/ContextAttachmentFields.vue +17 -17
  54. package/app/components/docs/DocInterviewWindow.vue +14 -14
  55. package/app/components/documents/ContextDocumentPicker.vue +17 -17
  56. package/app/components/documents/DocumentImportModal.vue +7 -7
  57. package/app/components/documents/DocumentSourceConnectModal.vue +3 -3
  58. package/app/components/documents/DocumentSyncState.vue +5 -5
  59. package/app/components/documents/DocumentTemplatesModal.vue +15 -15
  60. package/app/components/documents/RepoContextDocPicker.vue +5 -5
  61. package/app/components/documents/SpawnPreviewModal.vue +12 -12
  62. package/app/components/documents/StartFromDesignModal.vue +11 -11
  63. package/app/components/documents/TaskContextDocs.vue +5 -5
  64. package/app/components/environments/EnvSetupStepper.vue +6 -6
  65. package/app/components/environments/EnvironmentStatusPanel.vue +17 -17
  66. package/app/components/environments/steps/EnvPickStep.vue +3 -3
  67. package/app/components/environments/steps/EnvPreflightStep.vue +9 -9
  68. package/app/components/environments/steps/EnvReviewStep.vue +25 -22
  69. package/app/components/environments/steps/EnvSaveStep.vue +7 -5
  70. package/app/components/environments/steps/JourneyStepNav.vue +1 -1
  71. package/app/components/focus/BlockFocusView.vue +17 -19
  72. package/app/components/followUp/FollowUpWindow.vue +23 -23
  73. package/app/components/forkDecision/ForkDecisionWindow.vue +37 -39
  74. package/app/components/foundational/FoundationalContractSummary.vue +7 -7
  75. package/app/components/foundational/FoundationalServiceCatalogList.vue +11 -11
  76. package/app/components/foundational/FoundationalServiceManager.vue +1 -1
  77. package/app/components/foundational/FoundationalServiceRegistry.vue +13 -13
  78. package/app/components/foundational/FoundationalServiceSources.vue +13 -13
  79. package/app/components/foundational/FoundationalSuppressions.vue +7 -7
  80. package/app/components/foundational/ServiceCatalogConnection.vue +10 -10
  81. package/app/components/fragments/FragmentLibraryManager.vue +41 -44
  82. package/app/components/fragments/FragmentSelector.vue +13 -13
  83. package/app/components/fragments/GitHubDocUrlImport.vue +1 -1
  84. package/app/components/gates/GateFailingCheckList.vue +5 -5
  85. package/app/components/gates/GateResultView.vue +50 -47
  86. package/app/components/github/AddServiceFromRepoModal.vue +14 -14
  87. package/app/components/github/BranchProtectionPreflight.vue +13 -13
  88. package/app/components/github/GitHubConnect.vue +7 -7
  89. package/app/components/github/GitHubOnboarding.vue +7 -7
  90. package/app/components/github/GitHubPanel.vue +37 -40
  91. package/app/components/github/RepoTreeBrowser.vue +18 -18
  92. package/app/components/humanTest/HumanTestWindow.vue +30 -33
  93. package/app/components/initiative/InitiativePlanNotice.vue +5 -5
  94. package/app/components/initiative/InitiativePlanReview.vue +27 -29
  95. package/app/components/initiative/InitiativePlanningWindow.vue +10 -10
  96. package/app/components/initiative/InitiativeTrackerWindow.vue +71 -65
  97. package/app/components/inputGate/InputGateNotice.vue +2 -4
  98. package/app/components/judge/JudgeResultView.vue +30 -32
  99. package/app/components/kaizen/KaizenPanel.vue +40 -36
  100. package/app/components/kaizen/KaizenStepStatus.vue +21 -21
  101. package/app/components/layout/AccountAuditLog.vue +10 -10
  102. package/app/components/layout/AccountDeploymentSettings.vue +20 -20
  103. package/app/components/layout/AccountFailureKindRules.vue +13 -13
  104. package/app/components/layout/AccountFoundationalSettings.vue +1 -1
  105. package/app/components/layout/AccountFragmentSettings.vue +1 -1
  106. package/app/components/layout/AccountModelPolicySettings.vue +9 -9
  107. package/app/components/layout/AccountPlatformAlertSettings.vue +11 -11
  108. package/app/components/layout/AccountRiskPolicySettings.vue +2 -2
  109. package/app/components/layout/AccountRunCredentialSettings.vue +5 -5
  110. package/app/components/layout/AccountSkillSettings.vue +1 -1
  111. package/app/components/layout/AccountTeamSettings.vue +23 -15
  112. package/app/components/layout/AiProvidersBanner.vue +11 -8
  113. package/app/components/layout/AppearanceSwitcher.vue +108 -0
  114. package/app/components/layout/BoardSwitcher.vue +8 -11
  115. package/app/components/layout/BoardToolbar.vue +3 -3
  116. package/app/components/layout/CommandBar.vue +7 -9
  117. package/app/components/layout/ConnectionStatusBanner.vue +2 -2
  118. package/app/components/layout/DefaultTestEnvBanner.vue +5 -5
  119. package/app/components/layout/GitHubPatBanner.vue +5 -5
  120. package/app/components/layout/GitHubPatPermissionsBanner.vue +16 -10
  121. package/app/components/layout/InfraSetupBanner.vue +6 -6
  122. package/app/components/layout/IntegrationsHub.vue +15 -15
  123. package/app/components/layout/LanguageSwitcher.vue +5 -5
  124. package/app/components/layout/ModelProvidersHub.vue +13 -16
  125. package/app/components/layout/NotificationsInbox.vue +10 -10
  126. package/app/components/layout/PersonalSetupModal.vue +8 -8
  127. package/app/components/layout/ProviderConfigBanner.vue +4 -4
  128. package/app/components/layout/RolePrompt.vue +7 -7
  129. package/app/components/layout/SideBar.vue +6 -4
  130. package/app/components/layout/SpendWarningBanner.vue +17 -14
  131. package/app/components/layout/TranslationWarningBanner.vue +4 -4
  132. package/app/components/layout/UiModeSwitcher.vue +13 -13
  133. package/app/components/layout/UiRoleSwitcher.vue +8 -8
  134. package/app/components/layout/WorkspaceMembersSettings.vue +15 -11
  135. package/app/components/media/ArtifactLightbox.vue +13 -13
  136. package/app/components/media/ImageCompare.vue +31 -24
  137. package/app/components/merge/MergeEffortChips.vue +2 -2
  138. package/app/components/notifications/NotificationSettingsPanel.vue +14 -12
  139. package/app/components/observability/OutcomeFilterChips.vue +6 -6
  140. package/app/components/observability/RunFailureSummary.vue +28 -25
  141. package/app/components/observability/StepMetricsBar.vue +26 -28
  142. package/app/components/observability/StepModelActivity.vue +2 -2
  143. package/app/components/observability/ToolCallList.vue +24 -24
  144. package/app/components/outcome/OutcomeSummaryWindow.vue +47 -47
  145. package/app/components/palettes/AgentPalette.vue +8 -8
  146. package/app/components/palettes/AgentTierSelect.vue +1 -1
  147. package/app/components/palettes/PipelinePurposeSelect.vue +1 -1
  148. package/app/components/panels/AgentStepDetail.vue +52 -51
  149. package/app/components/panels/AttemptEntryHeader.vue +4 -6
  150. package/app/components/panels/DecisionModal.vue +7 -7
  151. package/app/components/panels/GenericStructuredResultView.vue +7 -7
  152. package/app/components/panels/InspectorPanel.vue +17 -17
  153. package/app/components/panels/MergerResultView.vue +19 -19
  154. package/app/components/panels/ObservabilityPanel.vue +115 -123
  155. package/app/components/panels/OperatorDashboardPanel.vue +89 -97
  156. package/app/components/panels/ReportsPanel.vue +69 -66
  157. package/app/components/panels/ReportsSpendBreakdown.vue +9 -9
  158. package/app/components/panels/ResultWindowShell.vue +38 -38
  159. package/app/components/panels/RunDetailLoadState.vue +2 -2
  160. package/app/components/panels/StepContainerStatus.vue +9 -9
  161. package/app/components/panels/StepDelegatedStatus.logic.spec.ts +135 -0
  162. package/app/components/panels/StepDelegatedStatus.logic.ts +160 -0
  163. package/app/components/panels/StepDelegatedStatus.vue +181 -0
  164. package/app/components/panels/StepEffortReport.vue +16 -15
  165. package/app/components/panels/StepFragmentAdherence.vue +14 -10
  166. package/app/components/panels/StepMetadataCard.vue +74 -45
  167. package/app/components/panels/StepReproductionReport.vue +25 -21
  168. package/app/components/panels/StepRunMeta.vue +20 -20
  169. package/app/components/panels/StepTestReport.logic.spec.ts +8 -3
  170. package/app/components/panels/StepTestReport.logic.ts +4 -4
  171. package/app/components/panels/StepTestReport.vue +28 -28
  172. package/app/components/panels/StepToolServers.vue +14 -11
  173. package/app/components/panels/StepValidationReport.vue +7 -7
  174. package/app/components/panels/inspector/ContainerSummary.vue +9 -9
  175. package/app/components/panels/inspector/DocReferenceRepos.vue +3 -3
  176. package/app/components/panels/inspector/EnvProbeReport.vue +24 -27
  177. package/app/components/panels/inspector/EpicChildren.vue +8 -12
  178. package/app/components/panels/inspector/FrontendBindingsResolved.vue +11 -11
  179. package/app/components/panels/inspector/FrontendConfig.vue +37 -41
  180. package/app/components/panels/inspector/InitiativeInspector.vue +3 -3
  181. package/app/components/panels/inspector/InspectorSection.vue +6 -6
  182. package/app/components/panels/inspector/RecurringScheduleSettings.vue +16 -19
  183. package/app/components/panels/inspector/ServiceConnections.vue +2 -2
  184. package/app/components/panels/inspector/ServiceReleaseHealthConfig.vue +2 -2
  185. package/app/components/panels/inspector/ServiceSelfTests.vue +21 -17
  186. package/app/components/panels/inspector/ServiceTestConfig.vue +51 -59
  187. package/app/components/panels/inspector/ServiceTestSecrets.vue +5 -5
  188. package/app/components/panels/inspector/ServiceTestingContext.vue +3 -3
  189. package/app/components/panels/inspector/ServiceValidationConfig.vue +2 -2
  190. package/app/components/panels/inspector/TaskAgentConfig.vue +3 -3
  191. package/app/components/panels/inspector/TaskAprioriBranches.vue +8 -5
  192. package/app/components/panels/inspector/TaskDependencies.vue +1 -1
  193. package/app/components/panels/inspector/TaskEstimateBadge.vue +11 -11
  194. package/app/components/panels/inspector/TaskExecution.vue +17 -17
  195. package/app/components/panels/inspector/TaskReviewTarget.vue +2 -2
  196. package/app/components/panels/inspector/TaskRunSettings.vue +35 -37
  197. package/app/components/panels/inspector/TaskStructure.vue +3 -3
  198. package/app/components/pipeline/AgentKindIcon.vue +1 -1
  199. package/app/components/pipeline/AgentPromptEditor.vue +17 -17
  200. package/app/components/pipeline/BinaryOutputStepPicker.vue +42 -56
  201. package/app/components/pipeline/EstimateThresholdFields.vue +4 -4
  202. package/app/components/pipeline/GateConfigFields.vue +13 -10
  203. package/app/components/pipeline/IterationCapPrompt.vue +4 -2
  204. package/app/components/pipeline/PipelineBuilder.vue +47 -55
  205. package/app/components/pipeline/PipelineHealthModal.vue +27 -29
  206. package/app/components/pipeline/PipelinePicker.vue +10 -10
  207. package/app/components/pipeline/PipelinePreview.vue +10 -10
  208. package/app/components/pipeline/PipelineProgress.vue +64 -67
  209. package/app/components/prReview/PrReviewPhaseBadge.vue +7 -7
  210. package/app/components/prReview/PrReviewWindow.vue +75 -77
  211. package/app/components/providers/AiPresetMismatchDialog.vue +5 -5
  212. package/app/components/providers/AiProviderOnboardingModal.vue +9 -9
  213. package/app/components/providers/ApiKeysSection.vue +13 -13
  214. package/app/components/providers/PersonalCredentialModal.vue +2 -2
  215. package/app/components/providers/PersonalSubscriptionSection.vue +10 -10
  216. package/app/components/providers/SignInRequiredNotice.vue +1 -1
  217. package/app/components/providers/VendorCredentialsModal.vue +10 -10
  218. package/app/components/provisioning/ProvisioningLogsDrawer.vue +13 -13
  219. package/app/components/ralph/RalphLoopResultView.vue +28 -30
  220. package/app/components/recurring/RecurrenceEditor.vue +2 -2
  221. package/app/components/requirements/RequirementsReviewWindow.vue +51 -58
  222. package/app/components/riskPolicy/RiskPolicyPicker.vue +12 -15
  223. package/app/components/riskPolicy/RiskPolicyPreview.vue +14 -14
  224. package/app/components/sandbox/SandboxPanel.vue +58 -59
  225. package/app/components/settings/AccountSettingsPanel.vue +1 -1
  226. package/app/components/settings/ApiTokensPanel.vue +10 -10
  227. package/app/components/settings/BudgetSettings.vue +18 -22
  228. package/app/components/settings/CapabilityCredentialsPanel.vue +15 -15
  229. package/app/components/settings/CloudflareHandlerSection.vue +20 -20
  230. package/app/components/settings/ComposeEnvironmentSetupSection.vue +13 -13
  231. package/app/components/settings/ConnectionTestVerdict.vue +3 -3
  232. package/app/components/settings/ConnectionWarnings.vue +1 -1
  233. package/app/components/settings/ConsensusGroupsSection.vue +27 -35
  234. package/app/components/settings/CustomManifestTypeEditor.vue +10 -10
  235. package/app/components/settings/DefaultProvisionTypeSection.vue +6 -6
  236. package/app/components/settings/InfraHandlersConfigurator.vue +24 -22
  237. package/app/components/settings/InfrastructureBackendPicker.vue +6 -6
  238. package/app/components/settings/InfrastructureWindow.vue +5 -5
  239. package/app/components/settings/IssueTrackerPanel.vue +29 -23
  240. package/app/components/settings/KubernetesEngineForm.vue +11 -11
  241. package/app/components/settings/KubernetesEnvironmentForm.vue +4 -4
  242. package/app/components/settings/LocalContainerPoolSettings.vue +6 -11
  243. package/app/components/settings/LocalModelEndpointsPanel.vue +20 -18
  244. package/app/components/settings/McpAuthorizeScreen.vue +13 -15
  245. package/app/components/settings/McpOAuthCallbackScreen.vue +16 -10
  246. package/app/components/settings/MergeClassRulesEditor.vue +6 -9
  247. package/app/components/settings/MergeRolePolicyEditor.vue +16 -16
  248. package/app/components/settings/ModelConfigurationPanel.vue +23 -30
  249. package/app/components/settings/ModelPresetHealthModal.vue +15 -13
  250. package/app/components/settings/ObservabilityConnectionPanel.vue +4 -4
  251. package/app/components/settings/OpenRouterCatalogPanel.vue +26 -19
  252. package/app/components/settings/PackageRegistriesPanel.vue +8 -8
  253. package/app/components/settings/ProviderConnectionTab.vue +8 -11
  254. package/app/components/settings/ProviderManifestEditor.vue +9 -9
  255. package/app/components/settings/ProviderPreferenceEditor.vue +8 -8
  256. package/app/components/settings/RiskPolicyCreateForm.vue +10 -10
  257. package/app/components/settings/RiskPolicyEditorRow.vue +14 -14
  258. package/app/components/settings/RiskPolicyHealthModal.vue +15 -13
  259. package/app/components/settings/RiskPolicyInheritedRow.vue +1 -1
  260. package/app/components/settings/RiskPolicyPanel.vue +10 -15
  261. package/app/components/settings/ServiceFragmentDefaultsPanel.vue +7 -7
  262. package/app/components/settings/SharedStacksPanel.vue +9 -12
  263. package/app/components/settings/TaskSourceCard.vue +4 -4
  264. package/app/components/settings/TaskTypeSuppressionsPanel.vue +6 -6
  265. package/app/components/settings/ToolServerChecklist.vue +36 -29
  266. package/app/components/settings/UsageSettings.vue +15 -15
  267. package/app/components/settings/UserSecretsSection.vue +9 -12
  268. package/app/components/settings/WorkspaceMetadataSettings.vue +5 -5
  269. package/app/components/settings/WorkspaceSettingsPanel.vue +47 -47
  270. package/app/components/skills/ReviewSkillQueue.vue +10 -10
  271. package/app/components/skills/SkillLibraryManager.vue +23 -20
  272. package/app/components/slack/SlackPanel.vue +13 -17
  273. package/app/components/spec/ServiceSpecWindow.vue +45 -42
  274. package/app/components/tasks/BugHuntModal.vue +24 -27
  275. package/app/components/tasks/ContextIssuePicker.vue +11 -11
  276. package/app/components/tasks/TaskContextIssues.vue +3 -3
  277. package/app/components/tasks/TaskImportModal.vue +7 -7
  278. package/app/components/tasks/TaskSourceConnectModal.vue +10 -8
  279. package/app/components/testing/TestReportWindow.vue +99 -82
  280. package/app/components/theme/ThemeImportModal.vue +115 -0
  281. package/app/components/tutorial/TutorialCatalogue.vue +9 -9
  282. package/app/components/tutorial/TutorialNudge.vue +5 -5
  283. package/app/components/tutorial/TutorialOverlay.vue +12 -12
  284. package/app/components/tutorial/TutorialPrompt.vue +6 -9
  285. package/app/components/vcs/GitLabConnect.vue +4 -4
  286. package/app/components/vcs/VcsConnectSurfaces.vue +2 -2
  287. package/app/components/visualConfirm/VisualConfirmationWindow.vue +36 -36
  288. package/app/composables/api/client.ts +6 -1
  289. package/app/composables/usePipelineErrorToast.ts +17 -0
  290. package/app/modular/agent-kinds.ts +24 -0
  291. package/app/pages/index.vue +5 -5
  292. package/app/plugins/theme.client.ts +125 -0
  293. package/app/spa-loading-template.html +52 -14
  294. package/app/stores/agents.ts +1 -1
  295. package/app/stores/theme.spec.ts +56 -0
  296. package/app/stores/theme.ts +87 -0
  297. package/app/types/domain.ts +19 -0
  298. package/app/types/execution.ts +4 -0
  299. package/app/utils/agentOutput.ts +1 -1
  300. package/app/utils/binaryOutput.ts +6 -6
  301. package/app/utils/bootstrapSteps.ts +14 -14
  302. package/app/utils/catalog.ts +87 -83
  303. package/app/utils/colorTint.ts +10 -0
  304. package/app/utils/failureKinds.ts +1 -0
  305. package/app/utils/observability.ts +3 -3
  306. package/app/utils/pipelineRender.ts +13 -17
  307. package/app/utils/swimlanes.ts +4 -4
  308. package/app/utils/theme/bootPalette.spec.ts +54 -0
  309. package/app/utils/theme/bootPalette.ts +108 -0
  310. package/app/utils/theme/builtins.spec.ts +38 -0
  311. package/app/utils/theme/builtins.ts +55 -0
  312. package/app/utils/theme/css.ts +162 -0
  313. package/app/utils/theme/doc.ts +353 -0
  314. package/app/utils/theme/link.ts +93 -0
  315. package/app/utils/theme/presets.ts +509 -0
  316. package/app/utils/theme/theme.spec.ts +224 -0
  317. package/i18n/locales/de.json +61 -4
  318. package/i18n/locales/en.json +70 -4
  319. package/i18n/locales/es.json +61 -4
  320. package/i18n/locales/fr.json +61 -4
  321. package/i18n/locales/he.json +61 -4
  322. package/i18n/locales/it.json +61 -4
  323. package/i18n/locales/ja.json +61 -4
  324. package/i18n/locales/pl.json +61 -4
  325. package/i18n/locales/tr.json +61 -4
  326. package/i18n/locales/uk.json +61 -4
  327. package/nuxt.config.ts +37 -11
  328. package/package.json +10 -9
package/README.md CHANGED
@@ -15,6 +15,7 @@ The SPA source lives under `app/` (the Nuxt srcDir).
15
15
  - [What it is](#what-it-is)
16
16
  - [Tech stack](#tech-stack)
17
17
  - [Layout](#layout)
18
+ - [Nuxt UI: agent tooling and overrides](#nuxt-ui-agent-tooling-and-where-the-spa-overrides-the-skill)
18
19
  - [Task swimlanes](#task-swimlanes)
19
20
  - [Roles (engineer / product manager / designer)](#roles-engineer--product-manager--designer)
20
21
  - [Interface modes (basic / advanced)](#interface-modes-basic--advanced)
@@ -41,7 +42,8 @@ over the WebSocket. How that sync works is written up in
41
42
 
42
43
  ## Tech stack
43
44
 
44
- - **Nuxt 4 / Vue 3** SPA: single route (`pages/index.vue`).
45
+ - **Nuxt 4 / Vue 3** SPA: the board is `pages/index.vue`, beside three standalone routes
46
+ (`mcp-authorize.vue`, `mcp-oauth-callback.vue`, `reset-password.vue`).
45
47
  - **Pinia** (+ `pinia-plugin-persistedstate`): feature stores.
46
48
  - **Vue Flow** (`core`, `background`, `controls`, `node-resizer`): the canvas.
47
49
  - **Nuxt UI** + Tailwind: components and styling.
@@ -50,15 +52,15 @@ over the WebSocket. How that sync works is written up in
50
52
 
51
53
  ## Layout
52
54
 
53
- | Path | Contents |
54
- | ----------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
55
- | `app.vue` | Root; wraps the page in `AuthGate`. |
56
- | `pages/index.vue` | The only route: mounts the sidebar, canvas, toolbar, inspector, focus view, and all modals. |
57
- | `components/` | UI grouped by area (see [Key UI surfaces](#key-ui-surfaces)). |
58
- | `composables/` | `useApi` (typed client), `useWorkspaceStream` (WebSocket sync), `useBlockDrag`, `useBlockQueries`, `useBoardFlow`, `useSemanticZoom`, `useDepLabels`. |
59
- | `stores/` | Pinia stores, one per feature domain. |
60
- | `types/` | TypeScript domain unions (`domain.ts`) and wire types mirroring the contracts. |
61
- | `utils/` | Small pure helpers. |
55
+ | Path | Contents |
56
+ | -------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
57
+ | `app.vue` | Root; wraps the page in `AuthGate`. |
58
+ | `pages/` | The board (`index.vue`: sidebar, canvas, toolbar, inspector, focus view, all modals), plus the standalone `mcp-authorize`, `mcp-oauth-callback` and `reset-password` routes. |
59
+ | `components/` | UI grouped by area (see [Key UI surfaces](#key-ui-surfaces)). |
60
+ | `composables/` | `useApi` (typed client), `useWorkspaceStream` (WebSocket sync), `useBlockDrag`, `useBlockQueries`, `useBoardFlow`, `useSemanticZoom`, `useDepLabels`. |
61
+ | `stores/` | Pinia stores, one per feature domain. |
62
+ | `types/` | TypeScript domain unions (`domain.ts`) and wire types mirroring the contracts. |
63
+ | `utils/` | Small pure helpers. |
62
64
 
63
65
  ### The board's top overlay region has ONE owner
64
66
 
@@ -288,6 +290,80 @@ it has nothing to do at mount, and running it there would announce a close that
288
290
 
289
291
  A status → chip map feeding a `<UBadge :color="…">` types its values as `BadgeColor` (`utils/badge.ts`), which is derived from `UBadge`'s own prop type rather than restated as a literal union. Typed `string`, the binding does not compile and the reflex is `as any` at each call site: seven of them had accumulated. That cast also accepts a colour Nuxt UI does not define, which renders as an unstyled badge with nothing failing.
290
292
 
293
+ ### Colour through theme tokens, never a fixed palette shade
294
+
295
+ Every colour in the SPA is a token that follows the THEME and the colour MODE. Three kinds exist:
296
+
297
+ - **Nuxt UI role tokens** for greys (`bg-default`, `bg-elevated`, `bg-accented`, `text-default`, `text-toned`, `text-muted`, `text-dimmed`, `text-highlighted`, `border-default`, `border-muted`) and the **bare aliases** for an accent at Nuxt UI's own shade (`text-primary`, `bg-warning/10`, `ring-error/25`).
298
+ - **The app's mirrored numbered tokens** (`app/assets/css/tokens.css`) for a STATUS surface painted in a specific ramp shade: `bg-app-950` / `text-app-100` / `text-app-600` / `bg-app-500` / `ring-app-400` for the five grey shades with no role token, `bg-app-canvas` for the board canvas (the one surface below the page background; in light the page surface `app-950` sits at neutral-100 rather than the mirror's 50 and the canvas at 200, so the ~350 translucent `bg-default/NN` panels keep an edge), and `text-app-warning-300` / `bg-app-error-950/40` / `border-app-success-800` for the five status ramps (`secondary`, `success`, `info`, `warning`, `error`). Each token's dark value is the exact ramp shade and its light value is the MIRRORED shade (`50↔950`, `100↔900`, `200↔800`, `300↔700`, `400↔600`, `500` its own midpoint), so a `300` text on a `950/40` fill reads on both surfaces from one class list. Every value is a reference into the `--ui-color-<alias>-<n>` ramps, so a theme that remaps `warning` recolours every warning surface. `primary` has NO numbered token: brand accents use the bare alias, which is what the editor's primary slider and `blackAsPrimary` address.
299
+ - **Category hues** (`text-app-hue-pink`, `var(--app-hue-teal)` in an inline style) for an IDENTITY colour: an agent kind, a task type, a pipeline step kind (`utils/catalog.ts`). One token per Tailwind hue, `400` in dark and `600` in light (Nuxt UI's own alias convention), referencing Tailwind's ramps because a category is not a status. A STATUS (task status, step state, test verdict, finding severity) is not a category and takes the alias directly (`var(--ui-warning)`, `var(--ui-success)`, `var(--ui-text-muted)` for planned / done / skipped), so the halo, the badge and the dot recolour together. A translucent tile behind a category glyph goes through `tint()` (`utils/colorTint.ts`), which also accepts the hex a deployment-registered kind may send. A theme recolours a hue through its `tokens` block.
300
+ - **Never** a raw Tailwind hue (`bg-slate-900`, `text-amber-300`, `text-pink-300`) nor a fixed numbered alias (`text-primary-400`, `bg-warning-950/40`): the first is welded to one palette and one mode, the second follows the palette but not the mode. `scripts/check-frontend-palette.mjs` (CI) bans both. `red` and `rose` both mean `error`.
301
+ - **Never** a fixed `white` / `black` utility (`bg-white`, `text-black`, `border-white/5`, `bg-white/[0.02]`): invisible or wrong in light mode. Use `border-inverted` (a selection ring), `border-default` / `bg-muted` (faint chrome) or `text-inverted` (text over a filled surface). A line that genuinely needs a fixed value says why with a `fixed-colour-ok:` comment, on that line or the one above it.
302
+
303
+ ### Themes and colour mode
304
+
305
+ A **theme** is a Nuxt UI theme editor document (https://ui.nuxt.com/theme): the sparse `ThemeDoc` the editor edits and shares as a `?doc=` link, decoded by `utils/theme/link.ts` and typed in `utils/theme/doc.ts` (a port of the editor engine's tables). The app speaks THAT format rather than one of its own, so a theme built in the editor imports as-is and a built-in theme is a document a user could have exported. `utils/theme/builtins.ts` ships `Cat Factory` (the default; its `colors` MUST equal `app.config.ts`'s `ui.colors`, which paints the first frame) and the editor's own `Mono` preset, referenced from the preset table rather than copied. The `theme` store persists the pick and the user's imported documents in this browser; `plugins/theme.client.ts` applies the active document at runtime: aliases onto `appConfig.ui.colors` (Nuxt UI's own colours plugin re-emits the ramps), default variants and component overrides onto `appConfig.ui.<component>` merged INTO the layer's own overrides, and tokens / radius / fonts onto one `<style id="app-theme">` whose selectors anchor on the `data-theme` attribute on `<html>` (`utils/theme/css.ts`, which is also the write boundary for untrusted values). The faces the built-in themes name (Geist, Geist Mono) are self-hosted through `@nuxt/fonts` (`fonts.families` in `nuxt.config.ts`, pinned by `builtins.spec.ts`); a font an IMPORTED theme names is applied as a family name only, so it renders when the device or the deployment provides it. A editor link whose document equals one of the editor's presets collapses to `{ preset: 'mono' }`; `utils/theme/presets.ts` is a copy of the editor's preset table so such a link rebuilds (a decode table, not menu entries).
306
+
307
+ **Colour mode** (system / light / dark) is `@nuxtjs/color-mode`'s, registered by Nuxt UI, with its own persistence; `nuxt.config.ts` follows the system preference and falls back to dark. `AppearanceSwitcher` at the sidebar bottom is the one control for both axes. The pre-JS loading shell (`spa-loading-template.html`) cannot resolve a token (no stylesheet is loaded yet), so the plugin caches the computed colours of the four tokens the shell paints with, per colour mode, in `localStorage` (`utils/theme/bootPalette.ts`), and a two-line inline script in the shell applies the entry for the mode the `<head>` colour-mode script has already put on `<html>`. The hardcoded defaults are the default theme's, used only until a theme has been seen in that mode.
308
+
309
+ ## Nuxt UI: agent tooling and where the SPA overrides the skill
310
+
311
+ The SPA runs on Nuxt UI 4. Two first-party sources carry the rules this repo does not restate:
312
+
313
+ - **The vendored [`nuxt-ui` skill](https://github.com/kibertoad/cat-factory/tree/main/.claude/skills/nuxt-ui)** teaches WHEN to reach for which
314
+ component (Modal vs Slideover vs Drawer, Tabs vs NavigationMenu, Toast vs Alert) and HOW to build
315
+ well (the variant-weight table, one solid primary per view, semantic utility roles). It is
316
+ vendored under `.claude/skills/nuxt-ui/`, beside the project's own skills, so the rules version
317
+ with the code and every contributor on Claude Code reads the same text. This is the Claude Code
318
+ surface: `.claude/skills/` auto-loads for a local Claude Code session, and the repo `.mcp.json` is
319
+ offered once for approval on the first session in the repo (re-offered when the file changes); a
320
+ decline is remembered, and `claude mcp reset-project-choices` un-sticks it. Another tool that reads
321
+ `AGENTS.md` (Codex, for one) gets the pointers below but not an auto-loaded skill or an auto-wired
322
+ server. Making the platform's OWN coder agents (Claude Code, Codex, Pi in
323
+ the runner image) apply the skill is a separate, backend change: they stage skills and tool
324
+ servers per run through the agent-capabilities system (ADR 0024 /
325
+ [`custom-agents.md`](https://github.com/kibertoad/cat-factory/blob/main/backend/docs/custom-agents.md)), not from these repo files. The `@nuxt/ui` npm
326
+ package does not ship the skill, so it cannot move with `pnpm update`: it is vendored from the
327
+ `v4` branch of `nuxt/ui` (which tracks the 4.x line) and pinned by convention to the Nuxt UI
328
+ major in [`package.json`](./package.json) (`@nuxt/ui@^4.11`). Refresh it by re-vendoring
329
+ `skills/nuxt-ui/` from that branch (or `npx skills add nuxt/ui`) when the major moves. The
330
+ vendored files are kept byte-for-byte as upstream: `.oxfmtrc.json` exempts them from the
331
+ formatter and `scripts/check-doc-links.mjs` skips them, so a refresh stays a clean diff even when
332
+ upstream ships a link this repo's own doc rules would reject.
333
+ - **The [`nuxt-ui` MCP server](https://github.com/kibertoad/cat-factory/blob/main/.mcp.json)** (`https://ui.nuxt.com/mcp`, declared repo-level)
334
+ answers WHAT a component accepts: props, slots, events, theme files and examples per component.
335
+ The skill defers to it for every API question.
336
+
337
+ The SPA's own rules win where they and the skill disagree. Each entry below links the rule it
338
+ protects, so the two never contradict silently:
339
+
340
+ - **Visible copy is an i18n key, never a literal string.** The skill's examples hard-code labels and
341
+ placeholders (`label="Email"`, `placeholder="you@example.com"`); here every user-facing string
342
+ goes through `@nuxtjs/i18n` and lands in the catalog. [Rule](#internationalization-i18n-authoring).
343
+ - **Schema validation goes through valibot, never zod.** The skill's `forms.md` recipe opens with
344
+ `import * as z from 'zod'` and validates through `z.object({...})`; this package depends on
345
+ `valibot` (and `@toad-contracts/valibot`) and has no `zod`, so a `zod` import fails typecheck and
346
+ "fixing" it pulls in a dependency the repo deliberately lacks (which then has to clear the 24h
347
+ `minimumReleaseAge` gate). Validate with valibot, mirroring the wire contracts
348
+ ([`@cat-factory/contracts`](https://github.com/kibertoad/cat-factory/tree/main/backend/packages/contracts)).
349
+ - **A backend-declared form renders through `DescriptorFields.vue`, not a hand-built `UForm`.** The
350
+ skill teaches the hand-rolled `UForm` + `UFormField` shape for every form; when the backend
351
+ declares the fields and the SPA only collects them, that shape is forbidden here.
352
+ [Rule](#a-backend-declared-form-renders-through-descriptorfieldsvue).
353
+ - **Failure toasts go through the funnel, not a bare `toast.add`.** The skill uses `useToast()`
354
+ freely; here a failed backend call is reported with `usePipelineErrorToast().present(error, key)`.
355
+ [Rule](#every-failure-toast-goes-through-one-funnel).
356
+ - **Icon-only buttons carry an accessible name.** Use `common/IconButton.vue`
357
+ ([source](./app/components/common/IconButton.vue)), which applies `label` as both `title` and
358
+ `aria-label`, rather than a bare `<UButton icon>`.
359
+ - **Colour goes through theme tokens, never a fixed palette shade.** The skill bans raw Tailwind
360
+ hues; this repo also bans fixed numbered aliases, enforced by
361
+ [`scripts/check-frontend-palette.mjs`](https://github.com/kibertoad/cat-factory/blob/main/scripts/check-frontend-palette.mjs).
362
+ [Rule](#colour-through-theme-tokens-never-a-fixed-palette-shade).
363
+ - **Confirmation dialogs use the shared `useConfirm`.** The skill shows `useOverlay()` per call
364
+ site; here callers `await useConfirm().confirm({...})`
365
+ ([source](./app/composables/useConfirm.ts)) against one app-mounted `<ConfirmDialog />`.
366
+
291
367
  ## Task swimlanes
292
368
 
293
369
  A service frame lays its tasks out in **status lanes**, not at coordinates. Three lanes a reader
@@ -1341,12 +1417,21 @@ wrong place is invisible until a user cannot find it:
1341
1417
 
1342
1418
  ## Develop & test
1343
1419
 
1420
+ This package has no `dev` or `lint` script of its own: it is a layer, consumed through `extends`,
1421
+ and linting is whole-tree from the repo root (CLAUDE.md). The `AGENTS.md` verify checklist carries
1422
+ the same list, plus the install-free frontend guards.
1423
+
1344
1424
  ```bash
1425
+ # From the repo root:
1345
1426
  pnpm install
1346
- pnpm dev # Nuxt dev server (expects the Worker running; set NUXT_PUBLIC_API_BASE)
1347
- pnpm test # vitest
1348
- pnpm typecheck # nuxt typecheck
1349
- pnpm lint # oxlint + oxfmt --check
1427
+ pnpm dev:frontend # Nuxt dev server via deploy/frontend; set NUXT_PUBLIC_API_BASE to a running Worker
1428
+ pnpm exec turbo run typecheck --filter=@cat-factory/app # typecheck goes through Turbo
1429
+ pnpm lint # oxlint + oxfmt over the whole tree
1430
+
1431
+ # From frontend/app:
1432
+ pnpm exec vitest run <file> # run the spec your change touched
1433
+ pnpm i18n:check # catalog is well-formed
1434
+ pnpm i18n:parity # locales are in parity
1350
1435
  ```
1351
1436
 
1352
1437
  > Building/deploying the static site is covered in the deployment docs: see the
package/app/app.config.ts CHANGED
@@ -1,25 +1,34 @@
1
1
  export default defineAppConfig({
2
2
  ui: {
3
+ // The default theme's alias map. It MUST equal `CAT_FACTORY_THEME.doc.colors`
4
+ // (`utils/theme/builtins.ts`): this is what the first paint renders from, before the theme
5
+ // plugin applies the active document over it (`theme.builtins.spec.ts` pins the equality).
3
6
  colors: {
4
7
  primary: 'indigo',
8
+ secondary: 'violet',
9
+ success: 'emerald',
10
+ info: 'sky',
11
+ warning: 'amber',
12
+ error: 'rose',
5
13
  neutral: 'slate',
6
14
  },
7
- // Give every overlay the same layered dark palette the agent-run-details
8
- // reader uses: a deep slate-950 surface so the slate-900 panels/cards inside
9
- // pop, with slate-800 chrome. Applies to all UModal/USlideover instances so
10
- // overlays stay consistent without per-instance `:ui` overrides.
15
+ // Give every overlay the same layered surface the agent-run-details reader uses: the deep
16
+ // `app-950` surface (below `bg-default`) so the `bg-default` panels/cards inside pop, with
17
+ // `border-default` chrome. All tokens are theme role tokens (`app-950` is the hand-defined
18
+ // flipping token for the deep shade), so overlays track dark/light. Applies to all
19
+ // UModal/USlideover instances so they stay consistent without per-instance `:ui` overrides.
11
20
  modal: {
12
21
  slots: {
13
- content: 'bg-slate-950 ring-slate-800 divide-slate-800',
14
- header: 'border-b border-slate-800',
15
- title: 'text-white',
22
+ content: 'bg-app-950 ring-default divide-default',
23
+ header: 'border-b border-default',
24
+ title: 'text-highlighted',
16
25
  },
17
26
  },
18
27
  slideover: {
19
28
  slots: {
20
- content: 'bg-slate-950 ring-slate-800 divide-slate-800',
21
- header: 'border-b border-slate-800',
22
- title: 'text-white',
29
+ content: 'bg-app-950 ring-default divide-default',
30
+ header: 'border-b border-default',
31
+ title: 'text-highlighted',
23
32
  },
24
33
  },
25
34
  // The toaster's scroll region is the ONE `[data-slot='viewport']` the app's own
@@ -3,6 +3,9 @@
3
3
  /* The shared rendered-markdown reader presentation (see prose.css). */
4
4
  @import './prose.css';
5
5
 
6
+ /* The app's own mode-adaptive colour tokens (`app-*`), layered on Nuxt UI's. */
7
+ @import './tokens.css';
8
+
6
9
  /* The two toaster rules below are scoped by the `app-toaster` marker class that
7
10
  * `app.config.ts` puts on the toaster's viewport slot, NOT by `[data-slot='viewport']`.
8
11
  * That attribute is Nuxt UI's name for the scroll region of ELEVEN components
@@ -53,10 +56,6 @@
53
56
 
54
57
  /* ---- Agent Architecture Board: shared visual language ---------------------- */
55
58
 
56
- :root {
57
- --board-bg: #0b1020;
58
- }
59
-
60
59
  html,
61
60
  body,
62
61
  #__nuxt {
@@ -68,9 +67,9 @@ body {
68
67
  overflow: hidden;
69
68
  }
70
69
 
71
- /* Vue Flow surface tuned to a dark "design board" look */
70
+ /* The Vue Flow surface is the board canvas: one step below the page background in both modes. */
72
71
  .vue-flow__background {
73
- background-color: var(--board-bg);
72
+ background-color: var(--app-bg-canvas);
74
73
  }
75
74
 
76
75
  /* Touch: let the pane own one-finger pan + pinch-zoom rather than the browser
@@ -83,14 +82,15 @@ body {
83
82
  touch-action: none;
84
83
  }
85
84
 
86
- /* Status-pulse used by blocked / decision-needed blocks */
85
+ /* Status-pulse used by blocked / decision-needed blocks: the warning alias, so a theme that
86
+ * recolours `warning` recolours the halo. `color-mix` is how a custom property gets an alpha. */
87
87
  @keyframes board-pulse {
88
88
  0%,
89
89
  100% {
90
- box-shadow: 0 0 0 0 rgba(245, 158, 11, 0.55);
90
+ box-shadow: 0 0 0 0 color-mix(in srgb, var(--ui-warning) 55%, transparent);
91
91
  }
92
92
  50% {
93
- box-shadow: 0 0 0 10px rgba(245, 158, 11, 0);
93
+ box-shadow: 0 0 0 10px transparent;
94
94
  }
95
95
  }
96
96
 
@@ -98,14 +98,14 @@ body {
98
98
  animation: board-pulse 1.4s ease-in-out infinite;
99
99
  }
100
100
 
101
- /* Green pulse used when a block reaches the "PR ready" state */
101
+ /* Success pulse used when a block reaches the "PR ready" state */
102
102
  @keyframes board-pulse-green {
103
103
  0%,
104
104
  100% {
105
- box-shadow: 0 0 0 0 rgba(34, 197, 94, 0.6);
105
+ box-shadow: 0 0 0 0 color-mix(in srgb, var(--ui-success) 60%, transparent);
106
106
  }
107
107
  50% {
108
- box-shadow: 0 0 0 12px rgba(34, 197, 94, 0);
108
+ box-shadow: 0 0 0 12px transparent;
109
109
  }
110
110
  }
111
111
 
@@ -121,7 +121,7 @@ body {
121
121
 
122
122
  /* A selected edge: highlight it so the user knows what Delete/Backspace removes */
123
123
  .vue-flow__edge.selected .vue-flow__edge-path {
124
- stroke: #f43f5e !important;
124
+ stroke: var(--ui-error) !important;
125
125
  stroke-width: 2.5 !important;
126
126
  }
127
127
 
@@ -21,8 +21,8 @@
21
21
  transition: background 0.12s ease;
22
22
  }
23
23
  .reader-prose.review-mode [data-src-start]:hover {
24
- background: rgb(99 102 241 / 0.08);
25
- box-shadow: inset 2px 0 0 rgb(99 102 241 / 0.5);
24
+ background: color-mix(in srgb, var(--ui-primary) 8%, transparent);
25
+ box-shadow: inset 2px 0 0 color-mix(in srgb, var(--ui-primary) 50%, transparent);
26
26
  }
27
27
  .reader-prose.review-mode [data-src-start]::before {
28
28
  content: '+';
@@ -35,23 +35,23 @@
35
35
  align-items: center;
36
36
  justify-content: center;
37
37
  border-radius: 0.25rem;
38
- background: rgb(99 102 241);
39
- color: white;
38
+ background: var(--ui-primary);
39
+ color: var(--ui-text-inverted);
40
40
  font-size: 0.8rem;
41
41
  line-height: 1;
42
42
  }
43
43
  .reader-prose.review-mode [data-src-start]:hover::before {
44
44
  display: flex;
45
45
  }
46
- /* Persistent markers: amber for a block that already has a comment, indigo for
47
- the block whose composer is currently open. */
46
+ /* Persistent markers: the warning alias for a block that already has a comment, the primary
47
+ alias for the block whose composer is currently open. */
48
48
  .reader-prose .cf-commented {
49
- background: rgb(234 179 8 / 0.1);
50
- box-shadow: inset 2px 0 0 rgb(234 179 8 / 0.6);
49
+ background: color-mix(in srgb, var(--ui-warning) 10%, transparent);
50
+ box-shadow: inset 2px 0 0 color-mix(in srgb, var(--ui-warning) 60%, transparent);
51
51
  }
52
52
  .reader-prose .cf-selected {
53
- background: rgb(99 102 241 / 0.12);
54
- box-shadow: inset 2px 0 0 rgb(99 102 241 / 0.8);
53
+ background: color-mix(in srgb, var(--ui-primary) 12%, transparent);
54
+ box-shadow: inset 2px 0 0 color-mix(in srgb, var(--ui-primary) 80%, transparent);
55
55
  }
56
56
 
57
57
  /* Styling for the markdown HTML injected via v-html (out of scoped reach without
@@ -75,36 +75,36 @@
75
75
  }
76
76
  .reader-prose strong {
77
77
  font-weight: 600;
78
- color: rgb(226 232 240);
78
+ color: var(--ui-text-highlighted);
79
79
  }
80
80
  .reader-prose em {
81
81
  font-style: italic;
82
82
  }
83
83
  .reader-prose code {
84
84
  border-radius: 0.25rem;
85
- background: rgb(30 41 59 / 0.8);
85
+ background: var(--ui-bg-elevated);
86
86
  padding: 0.1rem 0.3rem;
87
- font-family: ui-monospace, monospace;
87
+ font-family: var(--font-mono);
88
88
  font-size: 0.85em;
89
- color: rgb(199 210 254);
89
+ color: var(--ui-primary);
90
90
  }
91
91
  .reader-prose pre {
92
92
  margin: 0.6rem 0;
93
93
  overflow: auto;
94
94
  border-radius: 0.5rem;
95
- background: rgb(2 6 23 / 0.6);
95
+ background: var(--app-bg-canvas);
96
96
  padding: 0.75rem 0.9rem;
97
97
  }
98
98
  .reader-prose pre code {
99
99
  background: transparent;
100
100
  padding: 0;
101
- color: rgb(203 213 225);
101
+ color: var(--ui-text-toned);
102
102
  }
103
103
  .reader-prose blockquote {
104
104
  margin: 0.6rem 0;
105
- border-left: 3px solid rgb(99 102 241 / 0.5);
105
+ border-left: 3px solid color-mix(in srgb, var(--ui-primary) 50%, transparent);
106
106
  padding-left: 0.75rem;
107
- color: rgb(148 163 184);
107
+ color: var(--ui-text-muted);
108
108
  }
109
109
  .reader-prose table {
110
110
  margin: 0.6rem 0;
@@ -113,17 +113,17 @@
113
113
  }
114
114
  .reader-prose th,
115
115
  .reader-prose td {
116
- border: 1px solid rgb(51 65 85);
116
+ border: 1px solid var(--ui-border-muted);
117
117
  padding: 0.3rem 0.6rem;
118
118
  }
119
119
  .reader-prose th {
120
- background: rgb(30 41 59 / 0.6);
120
+ background: var(--ui-bg-elevated);
121
121
  font-weight: 600;
122
122
  }
123
123
  .reader-prose hr {
124
124
  margin: 1rem 0;
125
125
  border: none;
126
- border-top: 1px solid rgb(51 65 85);
126
+ border-top: 1px solid var(--ui-border-muted);
127
127
  }
128
128
  .reader-prose h1,
129
129
  .reader-prose h2,
@@ -131,5 +131,5 @@
131
131
  .reader-prose h4 {
132
132
  margin: 0.6rem 0 0.3rem;
133
133
  font-weight: 600;
134
- color: rgb(226 232 240);
134
+ color: var(--ui-text-highlighted);
135
135
  }