@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
@@ -11,10 +11,10 @@ const props = defineProps<{
11
11
  const archetype = computed(() => agentKindMeta(props.step.agentKind))
12
12
 
13
13
  const stateRing: Record<AgentState, string> = {
14
- pending: 'ring-slate-600/60 opacity-60',
15
- working: 'ring-indigo-400',
16
- waiting_decision: 'ring-amber-400 board-pulse',
17
- done: 'ring-emerald-400',
14
+ pending: 'ring-app-600/60 opacity-60',
15
+ working: 'ring-primary',
16
+ waiting_decision: 'ring-app-warning-400 board-pulse',
17
+ done: 'ring-app-success-400',
18
18
  }
19
19
 
20
20
  const stateIcon: Record<AgentState, string | null> = {
@@ -32,27 +32,27 @@ const dim = computed(() => (props.size === 'sm' ? 'h-7 w-7' : 'h-9 w-9'))
32
32
  <div
33
33
  class="relative flex items-center justify-center rounded-full ring-2 transition"
34
34
  :class="[dim, stateRing[step.state], active ? 'scale-110' : '']"
35
- :style="{ backgroundColor: archetype.color + '22' }"
35
+ :style="{ backgroundColor: tint(archetype.color) }"
36
36
  >
37
37
  <UIcon :name="archetype.icon" class="text-base" :style="{ color: archetype.color }" />
38
38
  <span
39
39
  v-if="step.state === 'working'"
40
- class="absolute -bottom-1 -end-1 rounded-full bg-slate-900 p-0.5"
40
+ class="absolute -bottom-1 -end-1 rounded-full bg-default p-0.5"
41
41
  >
42
- <UIcon :name="stateIcon.working!" class="h-3 w-3 animate-spin text-indigo-300" />
42
+ <UIcon :name="stateIcon.working!" class="h-3 w-3 animate-spin text-primary" />
43
43
  </span>
44
44
  <span
45
45
  v-else-if="stateIcon[step.state]"
46
- class="absolute -bottom-1 -end-1 rounded-full bg-slate-900 p-0.5"
46
+ class="absolute -bottom-1 -end-1 rounded-full bg-default p-0.5"
47
47
  >
48
48
  <UIcon
49
49
  :name="stateIcon[step.state]!"
50
50
  class="h-3 w-3"
51
- :class="step.state === 'done' ? 'text-emerald-300' : 'text-amber-300'"
51
+ :class="step.state === 'done' ? 'text-app-success-300' : 'text-app-warning-300'"
52
52
  />
53
53
  </span>
54
54
  </div>
55
- <span v-if="size !== 'sm'" class="text-[10px] leading-none text-slate-300">
55
+ <span v-if="size !== 'sm'" class="text-[10px] leading-none text-toned">
56
56
  {{ archetype.label }}
57
57
  </span>
58
58
  </div>
@@ -238,21 +238,21 @@ const ITEM_ICON: Record<string, string> = {
238
238
  shows only the internal id + a "Permission denied" placeholder (never the repo). -->
239
239
  <div
240
240
  v-if="block?.accessDenied"
241
- class="w-56 overflow-hidden rounded-xl border border-slate-700 bg-slate-900/90 shadow-xl backdrop-blur"
241
+ class="w-56 overflow-hidden rounded-xl border border-muted bg-default/90 shadow-xl backdrop-blur"
242
242
  :data-block-id="block.id"
243
243
  data-testid="frame-access-denied"
244
244
  >
245
- <div class="flex items-center gap-2 border-b border-slate-800 px-3 py-2">
246
- <span class="i-lucide-lock h-4 w-4 shrink-0 text-slate-400" />
247
- <span class="truncate text-sm font-semibold text-slate-200">{{
245
+ <div class="flex items-center gap-2 border-b border-default px-3 py-2">
246
+ <span class="i-lucide-lock h-4 w-4 shrink-0 text-muted" />
247
+ <span class="truncate text-sm font-semibold text-default">{{
248
248
  t('board.frame.accessDenied.title')
249
249
  }}</span>
250
250
  </div>
251
251
  <div class="px-3 py-3">
252
- <p class="text-[11px] leading-snug text-slate-400">
252
+ <p class="text-[11px] leading-snug text-muted">
253
253
  {{ t('board.frame.accessDenied.hint') }}
254
254
  </p>
255
- <code class="mt-2 block truncate font-mono text-[11px] text-slate-500">{{ block.id }}</code>
255
+ <code class="mt-2 block truncate font-mono text-[11px] text-dimmed">{{ block.id }}</code>
256
256
  </div>
257
257
  </div>
258
258
 
@@ -291,23 +291,23 @@ const ITEM_ICON: Record<string, string> = {
291
291
  and a collapsed summary) went with the header's collapse control, since between them they
292
292
  held the only render of the "Shared" badge, which now lives in the header below. -->
293
293
  <div
294
- class="relative overflow-visible rounded-2xl border bg-slate-900/95 shadow-2xl backdrop-blur"
295
- :class="[selected ? 'border-white' : 'border-slate-700', pulseClass]"
294
+ class="relative overflow-visible rounded-2xl border bg-default/95 shadow-2xl backdrop-blur"
295
+ :class="[selected ? 'border-inverted' : 'border-muted', pulseClass]"
296
296
  >
297
297
  <div class="h-1.5 w-full rounded-t-2xl" :style="{ backgroundColor: accent }" />
298
298
  <!-- bootstrap-in-progress banner -->
299
299
  <div
300
300
  v-if="bootstrapping"
301
- class="border-b border-amber-900/50 bg-amber-950/30 px-4 py-2"
301
+ class="border-b border-app-warning-900/50 bg-app-warning-950/30 px-4 py-2"
302
302
  data-testid="bootstrap-progress"
303
303
  >
304
304
  <div class="flex items-center gap-1.5 text-xs">
305
305
  <UIcon
306
306
  name="i-lucide-loader-circle"
307
- class="h-4 w-4 shrink-0 animate-spin text-amber-400"
307
+ class="h-4 w-4 shrink-0 animate-spin text-app-warning-400"
308
308
  />
309
- <span class="text-amber-300">{{ t('board.frame.bootstrappingRepository') }}</span>
310
- <span v-if="bootstrapSubtasks" class="ms-auto text-amber-200/80">
309
+ <span class="text-app-warning-300">{{ t('board.frame.bootstrappingRepository') }}</span>
310
+ <span v-if="bootstrapSubtasks" class="ms-auto text-app-warning-200/80">
311
311
  {{
312
312
  t('board.frame.bootstrapStepsCount', {
313
313
  completed: bootstrapSubtasks.completed,
@@ -316,9 +316,9 @@ const ITEM_ICON: Record<string, string> = {
316
316
  }}
317
317
  </span>
318
318
  </div>
319
- <div class="mt-1.5 h-1 w-full overflow-hidden rounded bg-amber-900/40">
319
+ <div class="mt-1.5 h-1 w-full overflow-hidden rounded bg-app-warning-900/40">
320
320
  <div
321
- class="h-full rounded bg-amber-400 transition-all"
321
+ class="h-full rounded bg-app-warning-400 transition-all"
322
322
  :style="{ width: bootstrapPct + '%' }"
323
323
  />
324
324
  </div>
@@ -330,18 +330,18 @@ const ITEM_ICON: Record<string, string> = {
330
330
  class="flex items-start gap-1.5 text-[11px]"
331
331
  :class="
332
332
  item.status === 'completed'
333
- ? 'text-amber-200/60 line-through'
333
+ ? 'text-app-warning-200/60 line-through'
334
334
  : item.status === 'in_progress'
335
- ? 'text-amber-100'
336
- : 'text-amber-200/80'
335
+ ? 'text-app-warning-100'
336
+ : 'text-app-warning-200/80'
337
337
  "
338
338
  >
339
339
  <UIcon
340
340
  :name="ITEM_ICON[item.status]"
341
341
  class="mt-px h-3 w-3 shrink-0"
342
342
  :class="[
343
- item.status === 'in_progress' ? 'animate-spin text-amber-400' : '',
344
- item.status === 'completed' ? 'text-emerald-400' : 'text-amber-400/70',
343
+ item.status === 'in_progress' ? 'animate-spin text-app-warning-400' : '',
344
+ item.status === 'completed' ? 'text-app-success-400' : 'text-app-warning-400/70',
345
345
  ]"
346
346
  />
347
347
  <span>{{ item.label }}</span>
@@ -368,11 +368,11 @@ const ITEM_ICON: Record<string, string> = {
368
368
  <!-- parked on a human adoption review: the run is waiting on the viewer, not working -->
369
369
  <div
370
370
  v-else-if="awaitingReview"
371
- class="m-3 space-y-2 rounded-md border border-amber-500/40 bg-amber-500/5 p-3"
371
+ class="m-3 space-y-2 rounded-md border border-app-warning-500/40 bg-app-warning-500/5 p-3"
372
372
  >
373
373
  <div class="flex items-start gap-2">
374
- <UIcon name="i-lucide-user-check" class="mt-0.5 h-4 w-4 shrink-0 text-amber-400" />
375
- <p class="text-xs text-amber-200/90">{{ t('bootstrap.adoption.cardPrompt') }}</p>
374
+ <UIcon name="i-lucide-user-check" class="mt-0.5 h-4 w-4 shrink-0 text-app-warning-400" />
375
+ <p class="text-xs text-app-warning-200/90">{{ t('bootstrap.adoption.cardPrompt') }}</p>
376
376
  </div>
377
377
  <BootstrapRunSteps :run-id="awaitingReview.id" />
378
378
  <div class="flex justify-end">
@@ -404,7 +404,7 @@ const ITEM_ICON: Record<string, string> = {
404
404
  <div class="flex items-center gap-2">
405
405
  <div
406
406
  class="flex h-8 w-8 items-center justify-center rounded-lg"
407
- :style="{ backgroundColor: typeMeta!.accent + '22' }"
407
+ :style="{ backgroundColor: tint(typeMeta!.accent) }"
408
408
  >
409
409
  <UIcon
410
410
  :name="typeMeta!.icon"
@@ -414,7 +414,7 @@ const ITEM_ICON: Record<string, string> = {
414
414
  </div>
415
415
  <div>
416
416
  <div class="flex items-center gap-1.5">
417
- <span class="text-sm font-semibold text-white">{{ block.title }}</span>
417
+ <span class="text-sm font-semibold text-highlighted">{{ block.title }}</span>
418
418
  <!-- Mounted on more than one board in the org. On the title row rather than in
419
419
  the action strip, because it qualifies the service's NAME: the work lands in
420
420
  a repo another board also drives. -->
@@ -430,7 +430,7 @@ const ITEM_ICON: Record<string, string> = {
430
430
  {{ t('board.frame.shared') }}
431
431
  </UBadge>
432
432
  </div>
433
- <div class="text-[11px] text-slate-400">{{ typeMeta!.label }}</div>
433
+ <div class="text-[11px] text-muted">{{ typeMeta!.label }}</div>
434
434
  </div>
435
435
  </div>
436
436
  <div class="flex items-center gap-1">
@@ -530,13 +530,13 @@ const ITEM_ICON: Record<string, string> = {
530
530
  stays is what the canvas can't show at a glance. -->
531
531
  <div
532
532
  v-if="modules.length || prTasks"
533
- class="flex items-center gap-2 text-[10px] uppercase tracking-wide text-slate-500"
533
+ class="flex items-center gap-2 text-[10px] uppercase tracking-wide text-dimmed"
534
534
  >
535
535
  <span v-if="modules.length">{{
536
536
  t('board.frame.moduleCount', { count: modules.length }, modules.length)
537
537
  }}</span>
538
538
  <span v-if="modules.length && prTasks" aria-hidden="true">·</span>
539
- <span v-if="prTasks" class="text-emerald-400">{{
539
+ <span v-if="prTasks" class="text-app-success-400">{{
540
540
  t('board.frame.prReadyCount', { count: prTasks })
541
541
  }}</span>
542
542
  </div>
@@ -549,7 +549,7 @@ const ITEM_ICON: Record<string, string> = {
549
549
  through to nothing; each lane body carries the same zone for drops inside it. -->
550
550
  <div
551
551
  :data-drop-zone="block.id"
552
- class="nodrag relative rounded-xl bg-slate-950/40 p-2"
552
+ class="nodrag relative rounded-xl bg-app-950/40 p-2"
553
553
  :style="{ width: canvas.w + 'px', minHeight: canvas.h + 'px' }"
554
554
  >
555
555
  <!-- Initiatives sit in a wrapping band above the lanes: they are containers of work,
@@ -564,7 +564,7 @@ const ITEM_ICON: Record<string, string> = {
564
564
  v-if="!hasTasks && access.canWriteBoard.value"
565
565
  type="button"
566
566
  data-testid="frame-add-task-empty"
567
- class="absolute inset-4 flex items-center justify-center gap-1 rounded-lg border border-dashed border-slate-700 text-[11px] text-slate-500 hover:border-slate-500 hover:text-slate-300"
567
+ class="absolute inset-4 flex items-center justify-center gap-1 rounded-lg border border-dashed border-muted text-[11px] text-dimmed hover:border-app-500 hover:text-toned"
568
568
  @click.stop="addTask"
569
569
  >
570
570
  <UIcon name="i-lucide-plus" class="h-3.5 w-3.5" /> {{ t('board.frame.addFirstTask') }}
@@ -18,12 +18,12 @@ const displayLabel = computed(() => props.label ?? t('board.decisionBadge.decisi
18
18
  <template>
19
19
  <button
20
20
  type="button"
21
- class="board-pulse flex items-center gap-1 rounded-full bg-amber-500 px-2 py-0.5 text-xs font-semibold text-amber-950 shadow-lg transition hover:bg-amber-400"
21
+ class="board-pulse flex items-center gap-1 rounded-full bg-app-warning-500 px-2 py-0.5 text-xs font-semibold text-app-warning-50 dark:text-app-warning-950 shadow-lg transition hover:bg-app-warning-400"
22
22
  @click.stop="$emit('open')"
23
23
  >
24
24
  <UIcon :name="icon" class="h-3.5 w-3.5" />
25
25
  <span v-if="!compact">{{ displayLabel }}</span>
26
- <span v-if="count && count > 1" class="rounded-full bg-amber-950/30 px-1">
26
+ <span v-if="count && count > 1" class="rounded-full bg-app-warning-950/30 px-1">
27
27
  {{ count }}
28
28
  </span>
29
29
  </button>
@@ -26,30 +26,34 @@ const selected = computed(() => ui.selectedBlockId === props.id)
26
26
  <div
27
27
  v-if="block"
28
28
  :data-block-id="block.id"
29
- class="w-56 cursor-pointer rounded-lg border bg-slate-900/90 px-3 py-2 shadow-lg backdrop-blur transition-colors"
30
- :class="selected ? 'border-violet-400 ring-1 ring-violet-400/50' : 'border-violet-500/40'"
29
+ class="w-56 cursor-pointer rounded-lg border bg-default/90 px-3 py-2 shadow-lg backdrop-blur transition-colors"
30
+ :class="
31
+ selected
32
+ ? 'border-app-secondary-400 ring-1 ring-app-secondary-400/50'
33
+ : 'border-app-secondary-500/40'
34
+ "
31
35
  @click="ui.select(block.id)"
32
36
  >
33
37
  <div class="flex items-center gap-1.5">
34
- <UIcon name="i-lucide-layers" class="h-3.5 w-3.5 shrink-0 text-violet-400" />
35
- <span class="text-[10px] font-semibold uppercase tracking-wide text-violet-300">{{
38
+ <UIcon name="i-lucide-layers" class="h-3.5 w-3.5 shrink-0 text-app-secondary-400" />
39
+ <span class="text-[10px] font-semibold uppercase tracking-wide text-app-secondary-300">{{
36
40
  t('board.epic.label')
37
41
  }}</span>
38
- <span class="ms-auto text-[10px] text-slate-400">{{ done }}/{{ total }}</span>
42
+ <span class="ms-auto text-[10px] text-muted">{{ done }}/{{ total }}</span>
39
43
  </div>
40
- <div class="mt-1 truncate text-sm font-medium text-slate-100" :title="block.title">
44
+ <div class="mt-1 truncate text-sm font-medium text-app-100" :title="block.title">
41
45
  {{ block.title }}
42
46
  </div>
43
- <div class="mt-1.5 h-1 w-full overflow-hidden rounded-full bg-slate-700/60">
47
+ <div class="mt-1.5 h-1 w-full overflow-hidden rounded-full bg-accented/60">
44
48
  <div
45
- class="h-full rounded-full bg-violet-500"
49
+ class="h-full rounded-full bg-app-secondary-500"
46
50
  :style="{ width: total ? `${Math.round((done / total) * 100)}%` : '0%' }"
47
51
  />
48
52
  </div>
49
- <div v-if="active" class="mt-1 text-[10px] text-slate-400">
53
+ <div v-if="active" class="mt-1 text-[10px] text-muted">
50
54
  {{ t('board.epic.activeCount', { count: active }) }}
51
55
  </div>
52
- <div v-else-if="total === 0" class="mt-1 text-[10px] text-slate-500">
56
+ <div v-else-if="total === 0" class="mt-1 text-[10px] text-dimmed">
53
57
  {{ t('board.epic.noTasksYet') }}
54
58
  </div>
55
59
  </div>
@@ -66,39 +66,37 @@ const withheldNote = computed(() => {
66
66
  <!-- The Done strip. Rendered only once the service HAS finished something: an empty archive
67
67
  is the one lane whose emptiness says nothing a reader needs (a new service has merged
68
68
  nothing, which its three live lanes already show). -->
69
- <div v-if="doneLane && doneLane.total > 0" class="rounded-lg bg-slate-900/40">
69
+ <div v-if="doneLane && doneLane.total > 0" class="rounded-lg bg-default/40">
70
70
  <button
71
71
  type="button"
72
- class="nodrag flex w-full items-center gap-1.5 rounded-lg px-2 py-1.5 text-left hover:bg-slate-800/40"
72
+ class="nodrag flex w-full items-center gap-1.5 rounded-lg px-2 py-1.5 text-left hover:bg-elevated/40"
73
73
  data-testid="done-lane-toggle"
74
74
  :aria-expanded="!laneView.doneLaneCollapsed"
75
75
  @click.stop="laneView.toggleDoneLane()"
76
76
  >
77
77
  <UIcon
78
78
  :name="laneView.doneLaneCollapsed ? 'i-lucide-chevron-right' : 'i-lucide-chevron-down'"
79
- class="h-3.5 w-3.5 shrink-0 text-slate-500"
79
+ class="h-3.5 w-3.5 shrink-0 text-dimmed"
80
80
  />
81
81
  <UIcon
82
82
  :name="LANE_META.done.icon"
83
83
  class="h-3.5 w-3.5 shrink-0"
84
84
  :style="{ color: LANE_META.done.color }"
85
85
  />
86
- <span class="text-[11px] font-semibold text-slate-200">{{
87
- t(LANE_META.done.labelKey)
88
- }}</span>
86
+ <span class="text-[11px] font-semibold text-default">{{ t(LANE_META.done.labelKey) }}</span>
89
87
  <!-- The TOTAL, not what the caps admitted: "this service has finished 312 tasks" is the
90
88
  fact the lane carries, and counting only the visible cards would understate it by
91
89
  two orders of magnitude. -->
92
90
  <span
93
91
  class="shrink-0 rounded px-1 text-[10px] font-semibold tabular-nums"
94
92
  :style="{
95
- backgroundColor: LANE_META.done.color + '22',
93
+ backgroundColor: tint(LANE_META.done.color),
96
94
  color: LANE_META.done.color,
97
95
  }"
98
96
  data-testid="lane-count-done"
99
97
  >{{ doneLane.total }}</span
100
98
  >
101
- <span v-if="withheldNote" class="ms-auto truncate text-[10px] text-slate-500">{{
99
+ <span v-if="withheldNote" class="ms-auto truncate text-[10px] text-dimmed">{{
102
100
  withheldNote
103
101
  }}</span>
104
102
  </button>
@@ -120,7 +118,7 @@ const withheldNote = computed(() => {
120
118
  has nothing in it rather than looking broken. -->
121
119
  <p
122
120
  v-if="doneSelection.shown.length === 0"
123
- class="px-1 text-[10px] leading-snug text-slate-600"
121
+ class="px-1 text-[10px] leading-snug text-app-600"
124
122
  >
125
123
  {{ t('board.lanes.done.allWithheld') }}
126
124
  </p>
@@ -66,33 +66,33 @@ function select() {
66
66
  <div
67
67
  data-testid="initiative-card"
68
68
  :data-status="status"
69
- class="cursor-pointer rounded-lg border border-indigo-800/60 bg-indigo-950/40 p-3 transition hover:border-indigo-600"
69
+ class="cursor-pointer rounded-lg border border-primary/60 bg-primary/10 p-3 transition hover:border-primary"
70
70
  :class="[
71
- selected ? 'ring-2 ring-indigo-400/60' : '',
71
+ selected ? 'ring-2 ring-primary/60' : '',
72
72
  awaitingAnswers || attention ? 'board-pulse' : '',
73
73
  ]"
74
74
  @click.stop="select"
75
75
  >
76
76
  <div class="flex items-start justify-between gap-2">
77
77
  <div class="flex items-center gap-2">
78
- <UIcon name="i-lucide-milestone" class="h-4 w-4 shrink-0 text-indigo-400" />
79
- <div class="text-xs font-semibold text-white">{{ block.title }}</div>
78
+ <UIcon name="i-lucide-milestone" class="h-4 w-4 shrink-0 text-primary" />
79
+ <div class="text-xs font-semibold text-highlighted">{{ block.title }}</div>
80
80
  </div>
81
81
  <UBadge :color="INITIATIVE_STATUS_CHIPS[status]" variant="subtle" size="sm">
82
82
  {{ statusLabel }}
83
83
  </UBadge>
84
84
  </div>
85
- <div class="mt-1 text-[10px] uppercase tracking-wide text-indigo-300/70">
85
+ <div class="mt-1 text-[10px] uppercase tracking-wide text-primary/70">
86
86
  {{ t('initiative.card.kind') }}
87
87
  </div>
88
88
  <div v-if="progress" class="mt-2 space-y-1">
89
- <div class="h-1.5 overflow-hidden rounded bg-slate-800">
89
+ <div class="h-1.5 overflow-hidden rounded bg-elevated">
90
90
  <div
91
- class="h-full rounded bg-indigo-400"
91
+ class="h-full rounded bg-primary"
92
92
  :style="{ width: `${Math.round((progress.settled / progress.total) * 100)}%` }"
93
93
  />
94
94
  </div>
95
- <div class="text-[10px] text-slate-400">
95
+ <div class="text-[10px] text-muted">
96
96
  {{ t('initiative.card.progress', { done: progress.settled, total: progress.total }) }}
97
97
  </div>
98
98
  </div>
@@ -75,7 +75,7 @@ const icon = computed(() => {
75
75
  saying "all of them" would be a row of chrome carrying no information. -->
76
76
  <div
77
77
  v-if="groupKey !== 'none'"
78
- class="flex items-center gap-1 px-0.5 text-[10px] uppercase tracking-wide text-slate-500"
78
+ class="flex items-center gap-1 px-0.5 text-[10px] uppercase tracking-wide text-dimmed"
79
79
  >
80
80
  <UIcon v-if="icon" :name="icon" class="h-3 w-3 shrink-0" />
81
81
  <span class="truncate" :title="label">{{ label }}</span>
@@ -52,13 +52,13 @@ function onHandle(e: PointerEvent) {
52
52
  for read-only viewers, for whom the drag is a no-op anyway (see useBlockDrag). -->
53
53
  <div
54
54
  v-if="access.canWriteBoard.value"
55
- class="nodrag nopan flex cursor-grab touch-none items-center justify-center rounded-t-lg border border-b-0 border-slate-700 bg-slate-800/80 py-px active:cursor-grabbing pointer-coarse:py-2"
55
+ class="nodrag nopan flex cursor-grab touch-none items-center justify-center rounded-t-lg border border-b-0 border-muted bg-elevated/80 py-px active:cursor-grabbing pointer-coarse:py-2"
56
56
  :title="t('board.frame.dragTask')"
57
57
  @pointerdown="onHandle"
58
58
  >
59
59
  <UIcon
60
60
  name="i-lucide-grip-horizontal"
61
- class="h-3 w-3 text-slate-500 pointer-coarse:h-5 pointer-coarse:w-5"
61
+ class="h-3 w-3 text-dimmed pointer-coarse:h-5 pointer-coarse:w-5"
62
62
  />
63
63
  </div>
64
64
  <TaskCard :task-id="taskId" :class="access.canWriteBoard.value ? '!rounded-t-none' : ''" />
@@ -90,11 +90,11 @@ const GRIPS: Record<ResizeEdge, GripStyle> = {
90
90
  // A bar is filled, an L-shaped corner mark is drawn in border colour — so the lit/idle classes
91
91
  // differ per shape as well as per tone.
92
92
  const TONES = {
93
- frame: { barLit: 'bg-sky-400', markLit: 'border-sky-400', markIdle: 'border-slate-500' },
93
+ frame: { barLit: 'bg-app-info-400', markLit: 'border-app-info-400', markIdle: 'border-app-500' },
94
94
  module: {
95
- barLit: 'bg-violet-300',
96
- markLit: 'border-violet-300',
97
- markIdle: 'border-violet-400/60',
95
+ barLit: 'bg-app-secondary-300',
96
+ markLit: 'border-app-secondary-300',
97
+ markIdle: 'border-app-secondary-400/60',
98
98
  },
99
99
  } as const
100
100
 
@@ -311,9 +311,9 @@ function selectTask() {
311
311
  :data-status="task.status"
312
312
  :data-task-type="task.taskType"
313
313
  data-testid="task-card"
314
- class="nodrag w-full cursor-pointer rounded-lg border bg-slate-950/70 p-2 text-start transition"
314
+ class="nodrag w-full cursor-pointer rounded-lg border bg-app-950/70 p-2 text-start transition"
315
315
  :class="[
316
- selected ? 'border-white' : 'border-slate-700 hover:border-slate-500',
316
+ selected ? 'border-inverted' : 'border-muted hover:border-app-500',
317
317
  task.status === 'pr_ready' ? 'board-pulse-green' : attention ? 'board-pulse' : '',
318
318
  ]"
319
319
  @click.stop="selectTask"
@@ -328,7 +328,7 @@ function selectTask() {
328
328
  <span
329
329
  v-if="typeBadge"
330
330
  class="inline-flex h-3.5 w-3.5 shrink-0 items-center justify-center rounded"
331
- :style="{ color: typeBadge.color, backgroundColor: `${typeBadge.color}22` }"
331
+ :style="{ color: typeBadge.color, backgroundColor: tint(typeBadge.color) }"
332
332
  :title="typeBadge.label"
333
333
  :data-task-type-badge="task.taskType"
334
334
  data-testid="task-type-badge"
@@ -338,7 +338,7 @@ function selectTask() {
338
338
  <UIcon
339
339
  v-if="schedule"
340
340
  name="i-lucide-repeat"
341
- class="h-3 w-3 shrink-0 text-indigo-400"
341
+ class="h-3 w-3 shrink-0 text-primary"
342
342
  :title="
343
343
  schedule.enabled
344
344
  ? t('board.task.recurringPipeline')
@@ -349,12 +349,12 @@ function selectTask() {
349
349
  class="ms-auto truncate text-[9px] uppercase tracking-wide"
350
350
  :class="
351
351
  runFailed
352
- ? 'text-rose-400'
352
+ ? 'text-app-error-400'
353
353
  : reviewStage
354
- ? 'text-indigo-300'
354
+ ? 'text-primary'
355
355
  : attention
356
- ? 'text-amber-400'
357
- : 'text-slate-500'
356
+ ? 'text-app-warning-400'
357
+ : 'text-dimmed'
358
358
  "
359
359
  >
360
360
  {{ statusText }}
@@ -362,7 +362,7 @@ function selectTask() {
362
362
  <!-- drag-to-connect handle: drag onto another task to make it depend on this one -->
363
363
  <button
364
364
  type="button"
365
- class="nodrag shrink-0 cursor-crosshair touch-none rounded-full p-0.5 text-slate-500 hover:bg-slate-800 hover:text-amber-400 pointer-coarse:p-2.5"
365
+ class="nodrag shrink-0 cursor-crosshair touch-none rounded-full p-0.5 text-dimmed hover:bg-elevated hover:text-app-warning-400 pointer-coarse:p-2.5"
366
366
  :title="t('board.task.dragToConnect')"
367
367
  @pointerdown.stop="startConnect(task.id, $event)"
368
368
  @click.stop
@@ -379,7 +379,7 @@ function selectTask() {
379
379
  title is the one always-rendered part of the body that no control can occupy. -->
380
380
  <div
381
381
  data-testid="task-title"
382
- class="mt-1 line-clamp-2 break-words text-[11px] font-semibold leading-snug text-slate-100"
382
+ class="mt-1 line-clamp-2 break-words text-[11px] font-semibold leading-snug text-app-100"
383
383
  :title="task.title"
384
384
  >
385
385
  {{ task.title }}
@@ -410,13 +410,13 @@ function selectTask() {
410
410
  <UIcon
411
411
  :name="runnable ? 'i-lucide-link' : 'i-lucide-lock'"
412
412
  class="h-3 w-3"
413
- :class="runnable ? 'text-slate-500' : 'text-amber-400'"
413
+ :class="runnable ? 'text-dimmed' : 'text-app-warning-400'"
414
414
  />
415
415
  <span
416
416
  v-for="d in deps"
417
417
  :key="d.id"
418
- class="inline-flex items-center gap-0.5 rounded bg-slate-800/80 px-1 py-0.5 text-[9px]"
419
- :class="d.status === 'done' ? 'text-slate-400' : 'text-amber-300'"
418
+ class="inline-flex items-center gap-0.5 rounded bg-elevated/80 px-1 py-0.5 text-[9px]"
419
+ :class="d.status === 'done' ? 'text-muted' : 'text-app-warning-300'"
420
420
  :title="depLabel(d)"
421
421
  >
422
422
  <UIcon
@@ -431,7 +431,7 @@ function selectTask() {
431
431
  <div class="nodrag mt-2 flex flex-wrap items-center gap-1">
432
432
  <!-- a reviewer gate folding/re-reviewing in the background: a working indicator,
433
433
  NOT a gate — the human is back on the board and summoned only if input is needed -->
434
- <span v-if="reviewStage" class="inline-flex items-center gap-1 text-[9px] text-indigo-300">
434
+ <span v-if="reviewStage" class="inline-flex items-center gap-1 text-[9px] text-primary">
435
435
  <UIcon name="i-lucide-loader-circle" class="h-3 w-3 animate-spin" />
436
436
  {{ reviewStageLabel }}
437
437
  </span>
@@ -481,7 +481,7 @@ function selectTask() {
481
481
  </UButton>
482
482
  <span
483
483
  v-if="runnable && defaultPipeline"
484
- class="inline-flex items-center gap-0.5 text-[9px] text-slate-500"
484
+ class="inline-flex items-center gap-0.5 text-[9px] text-dimmed"
485
485
  >
486
486
  <UIcon name="i-lucide-workflow" class="h-2.5 w-2.5" />{{ defaultPipeline.name }}
487
487
  </span>
@@ -539,7 +539,7 @@ function selectTask() {
539
539
  <!-- A merged task is the one people come back to READ, so its result stays openable
540
540
  rather than collapsing to a tick the moment it lands. -->
541
541
  <template v-else-if="task.status === 'done'">
542
- <span class="inline-flex items-center gap-1 text-[9px] text-emerald-400">
542
+ <span class="inline-flex items-center gap-1 text-[9px] text-app-success-400">
543
543
  <UIcon name="i-lucide-check-check" class="h-3 w-3" /> {{ t('board.task.implemented') }}
544
544
  </span>
545
545
  <UButton
@@ -562,10 +562,10 @@ function selectTask() {
562
562
  cost a row of card height each and add nothing. -->
563
563
  <div
564
564
  v-if="showModuleChip"
565
- class="mt-2 flex flex-wrap items-center gap-1 border-t border-slate-800 pt-2"
565
+ class="mt-2 flex flex-wrap items-center gap-1 border-t border-default pt-2"
566
566
  >
567
567
  <span
568
- class="inline-flex items-center gap-1 rounded bg-violet-500/15 px-1.5 py-0.5 text-[9px] text-violet-200"
568
+ class="inline-flex items-center gap-1 rounded bg-app-secondary-500/15 px-1.5 py-0.5 text-[9px] text-app-secondary-200"
569
569
  :title="t('board.task.module', { name: task.moduleName })"
570
570
  >
571
571
  <UIcon :name="MODULE_META.icon" class="h-3 w-3" :style="{ color: MODULE_META.color }" />
@@ -36,20 +36,20 @@ const isEmpty = computed(() => props.rendered.groups.every((g) => g.entries.leng
36
36
 
37
37
  <template>
38
38
  <div
39
- class="flex min-w-0 flex-col rounded-lg bg-slate-900/40"
39
+ class="flex min-w-0 flex-col rounded-lg bg-default/40"
40
40
  :style="{ width: LANE_GEOMETRY.laneWidth + 'px' }"
41
41
  :data-lane="rendered.lane"
42
42
  >
43
43
  <!-- Lane header -->
44
44
  <div
45
45
  class="flex items-center gap-1.5 rounded-t-lg border-b px-2 py-1.5"
46
- :style="{ borderColor: meta.color + '33' }"
46
+ :style="{ borderColor: tint(meta.color, 20) }"
47
47
  >
48
48
  <UIcon :name="meta.icon" class="h-3.5 w-3.5 shrink-0" :style="{ color: meta.color }" />
49
- <span class="truncate text-[11px] font-semibold text-slate-200">{{ t(meta.labelKey) }}</span>
49
+ <span class="truncate text-[11px] font-semibold text-default">{{ t(meta.labelKey) }}</span>
50
50
  <span
51
51
  class="ms-auto shrink-0 rounded px-1 text-[10px] font-semibold tabular-nums"
52
- :style="{ backgroundColor: meta.color + '22', color: meta.color }"
52
+ :style="{ backgroundColor: tint(meta.color), color: meta.color }"
53
53
  :data-testid="`lane-count-${rendered.lane}`"
54
54
  >{{ rendered.total }}</span
55
55
  >
@@ -65,7 +65,7 @@ const isEmpty = computed(() => props.rendered.groups.every((g) => g.entries.leng
65
65
  <!-- An empty lane SAYS it is empty. Left blank, "nothing needs you" and "the lane failed
66
66
  to render" look identical, and the first is worth stating: it is the answer a reader
67
67
  scanning the needs-you column is hoping for. -->
68
- <p v-if="isEmpty" class="px-1 pt-2 text-[10px] leading-snug text-slate-600">
68
+ <p v-if="isEmpty" class="px-1 pt-2 text-[10px] leading-snug text-app-600">
69
69
  {{ t(meta.emptyKey) }}
70
70
  </p>
71
71
  <LaneGroup