@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
@@ -182,7 +182,7 @@ function kindLabel(item: RequirementItem): string {
182
182
  <ResultWindowShell
183
183
  :open="open"
184
184
  icon="i-lucide-scroll-text"
185
- icon-class="bg-indigo-500/15 text-indigo-300"
185
+ icon-class="bg-primary/15 text-primary"
186
186
  :title="t('spec.title')"
187
187
  :subtitle="block ? spec?.service || block.title : undefined"
188
188
  variant="centered"
@@ -191,7 +191,7 @@ function kindLabel(item: RequirementItem): string {
191
191
  >
192
192
  <!-- view toggle: Gherkin only when the spec (and its feature files) are on main -->
193
193
  <template v-if="present" #header-extras>
194
- <div class="flex items-center rounded-lg border border-slate-700 p-0.5">
194
+ <div class="flex items-center rounded-lg border border-muted p-0.5">
195
195
  <UButton
196
196
  :color="mode === 'structured' ? 'primary' : 'neutral'"
197
197
  :variant="mode === 'structured' ? 'soft' : 'ghost'"
@@ -226,7 +226,7 @@ function kindLabel(item: RequirementItem): string {
226
226
  <!-- loading -->
227
227
  <div
228
228
  v-if="loading && !view"
229
- class="flex flex-1 items-center justify-center gap-2 text-sm text-slate-400"
229
+ class="flex flex-1 items-center justify-center gap-2 text-sm text-muted"
230
230
  >
231
231
  <UIcon name="i-lucide-loader-circle" class="h-4 w-4 animate-spin" />
232
232
  {{ t('spec.loading') }}
@@ -235,9 +235,9 @@ function kindLabel(item: RequirementItem): string {
235
235
  <!-- error -->
236
236
  <div
237
237
  v-else-if="errored"
238
- class="flex flex-1 flex-col items-center justify-center gap-3 p-8 text-center text-sm text-slate-400"
238
+ class="flex flex-1 flex-col items-center justify-center gap-3 p-8 text-center text-sm text-muted"
239
239
  >
240
- <UIcon name="i-lucide-triangle-alert" class="h-6 w-6 text-amber-400" />
240
+ <UIcon name="i-lucide-triangle-alert" class="h-6 w-6 text-app-warning-400" />
241
241
  {{ t('spec.error') }}
242
242
  <UButton
243
243
  icon="i-lucide-rotate-cw"
@@ -256,10 +256,10 @@ function kindLabel(item: RequirementItem): string {
256
256
  v-else-if="!present"
257
257
  class="flex flex-1 flex-col items-center justify-center gap-3 p-8 text-center"
258
258
  >
259
- <UIcon name="i-lucide-scroll-text" class="h-8 w-8 text-slate-600" />
259
+ <UIcon name="i-lucide-scroll-text" class="h-8 w-8 text-app-600" />
260
260
  <div>
261
- <p class="text-sm font-medium text-slate-300">{{ t('spec.empty.title') }}</p>
262
- <p class="mx-auto mt-1 max-w-md text-xs text-slate-500">
261
+ <p class="text-sm font-medium text-toned">{{ t('spec.empty.title') }}</p>
262
+ <p class="mx-auto mt-1 max-w-md text-xs text-dimmed">
263
263
  {{ t('spec.empty.description') }}
264
264
  </p>
265
265
  </div>
@@ -268,7 +268,7 @@ function kindLabel(item: RequirementItem): string {
268
268
  <!-- spec body: navigable tree + detail -->
269
269
  <div v-else class="flex min-h-0 flex-1">
270
270
  <!-- nav: modules → feature groups -->
271
- <nav class="w-64 shrink-0 overflow-y-auto border-e border-slate-800 px-3 py-4">
271
+ <nav class="w-64 shrink-0 overflow-y-auto border-e border-default px-3 py-4">
272
272
  <UButton
273
273
  block
274
274
  class="mb-2 justify-start"
@@ -285,7 +285,7 @@ function kindLabel(item: RequirementItem): string {
285
285
  {{ t('spec.overview') }}
286
286
  </UButton>
287
287
  <div v-for="(mod, mi) in modules" :key="mi" class="mb-3">
288
- <div class="px-2 pb-1 text-[11px] font-semibold uppercase tracking-wide text-slate-500">
288
+ <div class="px-2 pb-1 text-[11px] font-semibold uppercase tracking-wide text-dimmed">
289
289
  {{ mod.name }}
290
290
  </div>
291
291
  <ul class="space-y-0.5">
@@ -295,18 +295,18 @@ function kindLabel(item: RequirementItem): string {
295
295
  class="flex w-full items-center justify-between gap-2 rounded-md px-2 py-1.5 text-start text-[13px] transition"
296
296
  :class="
297
297
  selected?.m === mi && selected?.g === gi
298
- ? 'bg-indigo-500/15 text-indigo-200'
299
- : 'text-slate-300 hover:bg-slate-800'
298
+ ? 'bg-primary/15 text-primary'
299
+ : 'text-toned hover:bg-elevated'
300
300
  "
301
301
  @click="selectGroup(mi, gi)"
302
302
  >
303
303
  <span class="truncate">{{ group.name }}</span>
304
- <span class="shrink-0 text-[10px] text-slate-500">{{ reqCount(group) }}</span>
304
+ <span class="shrink-0 text-[10px] text-dimmed">{{ reqCount(group) }}</span>
305
305
  </button>
306
306
  </li>
307
307
  <li
308
308
  v-if="(mod.groups?.length ?? 0) === 0"
309
- class="px-2 py-1 text-[11px] italic text-slate-600"
309
+ class="px-2 py-1 text-[11px] italic text-app-600"
310
310
  >
311
311
  {{ t('spec.noFeatureGroups') }}
312
312
  </li>
@@ -318,14 +318,14 @@ function kindLabel(item: RequirementItem): string {
318
318
  <div class="min-w-0 flex-1 overflow-y-auto px-6 py-5">
319
319
  <!-- service overview -->
320
320
  <template v-if="selected === null">
321
- <h2 class="text-lg font-semibold text-white">{{ spec?.service }}</h2>
321
+ <h2 class="text-lg font-semibold text-highlighted">{{ spec?.service }}</h2>
322
322
  <!-- The service's own prose, so it takes the reading measure the shell's `full` width
323
323
  obliges (see the `width` prop). The requirement rows and Gherkin blocks below keep
324
324
  the full span — they are structure, not paragraphs. -->
325
- <p v-if="spec?.summary" class="mt-2 max-w-3xl whitespace-pre-line text-sm text-slate-300">
325
+ <p v-if="spec?.summary" class="mt-2 max-w-3xl whitespace-pre-line text-sm text-toned">
326
326
  {{ spec.summary }}
327
327
  </p>
328
- <p v-else class="mt-2 text-sm text-slate-500">{{ t('spec.noSummary') }}</p>
328
+ <p v-else class="mt-2 text-sm text-dimmed">{{ t('spec.noSummary') }}</p>
329
329
  <!-- implementation-state rollup: how much of the written-down behaviour is observed
330
330
  to hold, rather than merely agreed -->
331
331
  <div
@@ -339,9 +339,9 @@ function kindLabel(item: RequirementItem): string {
339
339
  <UBadge color="neutral" variant="subtle" size="sm">
340
340
  {{ t('spec.state.aspirationalCount', { count: specStates.aspirational }) }}
341
341
  </UBadge>
342
- <span class="text-slate-500">{{ t('spec.state.rollupHint') }}</span>
342
+ <span class="text-dimmed">{{ t('spec.state.rollupHint') }}</span>
343
343
  </div>
344
- <p class="mt-4 text-xs text-slate-500">
344
+ <p class="mt-4 text-xs text-dimmed">
345
345
  {{
346
346
  hasGherkin
347
347
  ? t('spec.moduleHintGherkin', { count: modules.length }, modules.length)
@@ -352,11 +352,11 @@ function kindLabel(item: RequirementItem): string {
352
352
 
353
353
  <!-- selected feature group -->
354
354
  <template v-else-if="selectedGroup">
355
- <div class="mb-1 text-[11px] uppercase tracking-wide text-slate-500">
355
+ <div class="mb-1 text-[11px] uppercase tracking-wide text-dimmed">
356
356
  {{ selectedModule?.name }}
357
357
  </div>
358
- <h2 class="text-lg font-semibold text-white">{{ selectedGroup.name }}</h2>
359
- <p v-if="selectedGroup.summary" class="mt-1 max-w-3xl text-sm text-slate-400">
358
+ <h2 class="text-lg font-semibold text-highlighted">{{ selectedGroup.name }}</h2>
359
+ <p v-if="selectedGroup.summary" class="mt-1 max-w-3xl text-sm text-muted">
360
360
  {{ selectedGroup.summary }}
361
361
  </p>
362
362
 
@@ -364,11 +364,11 @@ function kindLabel(item: RequirementItem): string {
364
364
  <template v-if="mode === 'gherkin'">
365
365
  <pre
366
366
  v-if="selectedFeature"
367
- class="mt-4 overflow-x-auto rounded-lg border border-slate-800 bg-slate-950/60 p-4 text-[12.5px] leading-relaxed text-slate-200"
367
+ class="mt-4 overflow-x-auto rounded-lg border border-default bg-app-950/60 p-4 text-[12.5px] leading-relaxed text-default"
368
368
  ><code>{{ selectedFeature.content }}</code></pre>
369
369
  <div
370
370
  v-else
371
- class="mt-4 rounded-lg border border-dashed border-slate-700 p-6 text-center text-sm text-slate-500"
371
+ class="mt-4 rounded-lg border border-dashed border-muted p-6 text-center text-sm text-dimmed"
372
372
  >
373
373
  {{ t('spec.noGherkinForGroup') }}
374
374
  </div>
@@ -376,7 +376,7 @@ function kindLabel(item: RequirementItem): string {
376
376
 
377
377
  <!-- STRUCTURED view: requirements + acceptance + domain rules -->
378
378
  <template v-else>
379
- <div v-if="reqCount(selectedGroup) === 0" class="mt-4 text-sm text-slate-500">
379
+ <div v-if="reqCount(selectedGroup) === 0" class="mt-4 text-sm text-dimmed">
380
380
  {{ t('spec.noRequirements') }}
381
381
  </div>
382
382
  <!-- per-group implementation-state rollup + the filter over the two halves -->
@@ -385,8 +385,11 @@ function kindLabel(item: RequirementItem): string {
385
385
  class="mt-4 flex flex-wrap items-center justify-between gap-2"
386
386
  data-testid="spec-state-filter"
387
387
  >
388
- <div class="flex items-center gap-1.5 text-[11px] text-slate-500">
389
- <UIcon :name="STATE_META.established.icon" class="h-3.5 w-3.5 text-emerald-400" />
388
+ <div class="flex items-center gap-1.5 text-[11px] text-dimmed">
389
+ <UIcon
390
+ :name="STATE_META.established.icon"
391
+ class="h-3.5 w-3.5 text-app-success-400"
392
+ />
390
393
  {{
391
394
  t('spec.state.groupRollup', {
392
395
  established: groupStates.established,
@@ -394,7 +397,7 @@ function kindLabel(item: RequirementItem): string {
394
397
  })
395
398
  }}
396
399
  </div>
397
- <div class="flex items-center rounded-lg border border-slate-700 p-0.5">
400
+ <div class="flex items-center rounded-lg border border-muted p-0.5">
398
401
  <UButton
399
402
  v-for="option in STATE_FILTERS"
400
403
  :key="option.value"
@@ -418,7 +421,7 @@ function kindLabel(item: RequirementItem): string {
418
421
  back here rather than making them find the toggle again. -->
419
422
  <div
420
423
  v-if="reqCount(selectedGroup) > 0 && visibleRequirements.length === 0"
421
- class="mt-4 flex flex-wrap items-center gap-2 text-sm text-slate-500"
424
+ class="mt-4 flex flex-wrap items-center gap-2 text-sm text-dimmed"
422
425
  data-testid="spec-state-filter-empty"
423
426
  >
424
427
  {{ t('spec.state.noneMatchFilter') }}
@@ -441,10 +444,10 @@ function kindLabel(item: RequirementItem): string {
441
444
  <li
442
445
  v-for="req in visibleRequirements"
443
446
  :key="req.id"
444
- class="rounded-lg border border-slate-800 bg-slate-900/60 p-4"
447
+ class="rounded-lg border border-default bg-default/60 p-4"
445
448
  >
446
449
  <div class="flex items-start justify-between gap-3">
447
- <h3 class="text-sm font-semibold text-slate-100">{{ req.title }}</h3>
450
+ <h3 class="text-sm font-semibold text-app-100">{{ req.title }}</h3>
448
451
  <div class="flex shrink-0 items-center gap-1.5">
449
452
  <!-- implementation state: agreed vs observed to hold. The distinction the
450
453
  build prompt and the tester act on, so a reader must see it too. -->
@@ -463,7 +466,7 @@ function kindLabel(item: RequirementItem): string {
463
466
  <UBadge color="neutral" variant="subtle" size="sm">{{ kindLabel(req) }}</UBadge>
464
467
  </div>
465
468
  </div>
466
- <p class="mt-1.5 whitespace-pre-line text-[13px] leading-relaxed text-slate-300">
469
+ <p class="mt-1.5 whitespace-pre-line text-[13px] leading-relaxed text-toned">
467
470
  {{ req.statement }}
468
471
  </p>
469
472
  <!-- acceptance criteria (Given/When/Then) -->
@@ -471,22 +474,22 @@ function kindLabel(item: RequirementItem): string {
471
474
  <div
472
475
  v-for="ac in req.acceptance ?? []"
473
476
  :key="ac.id"
474
- class="rounded-md border border-slate-800 bg-slate-950/50 px-3 py-2 text-[12.5px] leading-relaxed"
477
+ class="rounded-md border border-default bg-app-950/50 px-3 py-2 text-[12.5px] leading-relaxed"
475
478
  >
476
- <p class="text-slate-300">
477
- <span class="font-semibold text-emerald-400">{{
479
+ <p class="text-toned">
480
+ <span class="font-semibold text-app-success-400">{{
478
481
  t('spec.acceptance.given')
479
482
  }}</span>
480
483
  {{ ac.given }}
481
484
  </p>
482
- <p class="text-slate-300">
483
- <span class="font-semibold text-sky-400">{{
485
+ <p class="text-toned">
486
+ <span class="font-semibold text-app-info-400">{{
484
487
  t('spec.acceptance.when')
485
488
  }}</span>
486
489
  {{ ac.when }}
487
490
  </p>
488
- <p class="text-slate-300">
489
- <span class="font-semibold text-violet-400">{{
491
+ <p class="text-toned">
492
+ <span class="font-semibold text-app-secondary-400">{{
490
493
  t('spec.acceptance.then')
491
494
  }}</span>
492
495
  {{ ac.outcome }}
@@ -499,7 +502,7 @@ function kindLabel(item: RequirementItem): string {
499
502
  <!-- domain rules / invariants scoped to this group -->
500
503
  <div v-if="(selectedGroup.rules?.length ?? 0) > 0" class="mt-6">
501
504
  <div
502
- class="mb-2 flex items-center gap-1.5 text-[11px] font-semibold uppercase tracking-wide text-slate-400"
505
+ class="mb-2 flex items-center gap-1.5 text-[11px] font-semibold uppercase tracking-wide text-muted"
503
506
  >
504
507
  <UIcon name="i-lucide-shield-check" class="h-3.5 w-3.5" />
505
508
  {{ t('spec.domainRules') }}
@@ -508,10 +511,10 @@ function kindLabel(item: RequirementItem): string {
508
511
  <li
509
512
  v-for="rule in selectedGroup.rules ?? []"
510
513
  :key="rule.id"
511
- class="rounded-md border border-slate-800 bg-slate-900/60 px-3 py-2 text-[13px] text-slate-300"
514
+ class="rounded-md border border-default bg-default/60 px-3 py-2 text-[13px] text-toned"
512
515
  >
513
516
  {{ rule.rule }}
514
- <span v-if="rule.rationale" class="text-slate-500">{{
517
+ <span v-if="rule.rationale" class="text-dimmed">{{
515
518
  t('spec.ruleRationale', { rationale: rule.rationale })
516
519
  }}</span>
517
520
  </li>
@@ -339,8 +339,8 @@ const STATUS_KEYS: Record<BugHuntAnalysisStatus, string> = {
339
339
  <template #body>
340
340
  <!-- No tracker offered (none connected/installed, or all disabled). -->
341
341
  <div v-if="!tasks.anyOffered" class="space-y-3 text-center">
342
- <UIcon name="i-lucide-plug" class="mx-auto h-8 w-8 text-slate-500" />
343
- <p class="text-sm text-slate-400">{{ t('bugHunt.connectFirst') }}</p>
342
+ <UIcon name="i-lucide-plug" class="mx-auto h-8 w-8 text-dimmed" />
343
+ <p class="text-sm text-muted">{{ t('bugHunt.connectFirst') }}</p>
344
344
  <div class="flex flex-wrap justify-center gap-2">
345
345
  <UButton
346
346
  v-for="choice in addableSources"
@@ -356,12 +356,12 @@ const STATUS_KEYS: Record<BugHuntAnalysisStatus, string> = {
356
356
  </div>
357
357
 
358
358
  <!-- No service frame yet → nowhere for an adopted bug to land. -->
359
- <p v-else-if="!containerItems.length" class="text-center text-xs text-slate-500">
359
+ <p v-else-if="!containerItems.length" class="text-center text-xs text-dimmed">
360
360
  {{ t('bugHunt.needFrameFirst') }}
361
361
  </p>
362
362
 
363
363
  <div v-else class="space-y-4">
364
- <p class="text-xs text-slate-400">{{ t('bugHunt.intro') }}</p>
364
+ <p class="text-xs text-muted">{{ t('bugHunt.intro') }}</p>
365
365
 
366
366
  <div class="grid gap-3 sm:grid-cols-2">
367
367
  <UFormField :label="t('bugHunt.tracker')">
@@ -386,7 +386,7 @@ const STATUS_KEYS: Record<BugHuntAnalysisStatus, string> = {
386
386
  <span class="truncate">{{ descriptor?.label ?? t('bugHunt.pickTracker') }}</span>
387
387
  </UButton>
388
388
  </UDropdownMenu>
389
- <p v-else class="flex items-center gap-1.5 py-1 text-sm text-slate-300">
389
+ <p v-else class="flex items-center gap-1.5 py-1 text-sm text-toned">
390
390
  <UIcon v-if="descriptor?.icon" :name="descriptor.icon" class="h-4 w-4 shrink-0" />
391
391
  <span class="truncate">{{ descriptor?.label ?? t('bugHunt.pickTracker') }}</span>
392
392
  </p>
@@ -397,10 +397,7 @@ const STATUS_KEYS: Record<BugHuntAnalysisStatus, string> = {
397
397
  STATED rather than asked: the repository the service below is linked to. No
398
398
  control at all, because every value one could offer here is either that repo
399
399
  (nothing to choose) or another one this board holds no service for. -->
400
- <p
401
- v-if="boardFromService"
402
- class="flex items-center gap-1.5 py-1 text-sm text-slate-300"
403
- >
400
+ <p v-if="boardFromService" class="flex items-center gap-1.5 py-1 text-sm text-toned">
404
401
  <UIcon name="i-lucide-folder-git-2" class="h-4 w-4 shrink-0" />
405
402
  <span class="truncate">{{ scopedRepo ?? t('bugHunt.boardFromService') }}</span>
406
403
  </p>
@@ -422,12 +419,12 @@ const STATUS_KEYS: Record<BugHuntAnalysisStatus, string> = {
422
419
  />
423
420
  <!-- The service holds no repository, so there are no issues to read. Said here
424
421
  rather than in a toast: it invalidates the scope named right above it. -->
425
- <p v-if="huntNeedsRepo" class="mt-1 text-xs text-amber-400">
422
+ <p v-if="huntNeedsRepo" class="mt-1 text-xs text-app-warning-400">
426
423
  {{ t('bugHunt.boardNeedsRepo') }}
427
424
  </p>
428
425
  <!-- A board read that failed for a fixable reason (unreachable site, expired
429
426
  token): named, so the user isn't left with an empty picker and no cause. -->
430
- <p v-else-if="boardsFailure" class="mt-1 text-xs text-amber-400">
427
+ <p v-else-if="boardsFailure" class="mt-1 text-xs text-app-warning-400">
431
428
  {{ t('bugHunt.boardsFailed', { reason: boardsFailure }) }}
432
429
  </p>
433
430
  </UFormField>
@@ -440,7 +437,7 @@ const STATUS_KEYS: Record<BugHuntAnalysisStatus, string> = {
440
437
  <!-- Not a disabled input: this tracker's provider never sends the predicate, so a box
441
438
  still holding a value would read as a filter that is on. What it CAN narrow by is
442
439
  named instead, since the alternative is a hunt over every open issue. -->
443
- <p v-else class="text-xs text-amber-400">
440
+ <p v-else class="text-xs text-app-warning-400">
444
441
  {{ t('bugHunt.issueTypeUnsupported', { tracker: descriptor?.label ?? '' }) }}
445
442
  </p>
446
443
  </UFormField>
@@ -458,15 +455,15 @@ const STATUS_KEYS: Record<BugHuntAnalysisStatus, string> = {
458
455
  <!-- Two blocks rather than one with a computed `keypath`: the i18n extractor reads a
459
456
  bound keypath as the key itself, so a dynamic one is a key missing from every
460
457
  locale. Every other `<i18n-t>` in the SPA names its key statically for that reason. -->
461
- <p v-if="containerStated" class="text-xs text-slate-400">
458
+ <p v-if="containerStated" class="text-xs text-muted">
462
459
  <i18n-t v-if="boardFromService" keypath="bugHunt.huntingIn" tag="span" scope="global">
463
460
  <template #container>
464
- <span class="font-medium text-slate-200">{{ pinnedContainer!.title }}</span>
461
+ <span class="font-medium text-default">{{ pinnedContainer!.title }}</span>
465
462
  </template>
466
463
  </i18n-t>
467
464
  <i18n-t v-else keypath="bugHunt.adoptingInto" tag="span" scope="global">
468
465
  <template #container>
469
- <span class="font-medium text-slate-200">{{ pinnedContainer!.title }}</span>
466
+ <span class="font-medium text-default">{{ pinnedContainer!.title }}</span>
470
467
  </template>
471
468
  </i18n-t>
472
469
  </p>
@@ -490,33 +487,33 @@ const STATUS_KEYS: Record<BugHuntAnalysisStatus, string> = {
490
487
  >
491
488
  {{ t('bugHunt.run') }}
492
489
  </UButton>
493
- <span v-if="hunt.hunting" class="text-xs text-slate-400">
490
+ <span v-if="hunt.hunting" class="text-xs text-muted">
494
491
  {{ t('bugHunt.running') }}
495
492
  </span>
496
493
  </div>
497
494
 
498
495
  <!-- Results -->
499
- <div v-if="hunt.hasResult" class="space-y-3 border-t border-slate-800 pt-3">
500
- <p class="text-xs text-slate-400">
496
+ <div v-if="hunt.hasResult" class="space-y-3 border-t border-default pt-3">
497
+ <p class="text-xs text-muted">
501
498
  <!-- The board the scan actually ran against, named because on a repo-backed tracker
502
499
  the platform resolved it: the person reading the shortlist should not have to
503
500
  infer which repository it came out of. -->
504
- <span class="text-slate-500">
501
+ <span class="text-dimmed">
505
502
  {{ t('bugHunt.scannedBoard', { board: hunt.result!.board }) }}
506
503
  </span>
507
504
  {{ t(STATUS_KEYS[hunt.result!.analysisStatus]) }}
508
- <span v-if="hunt.result!.model" class="text-slate-500">
505
+ <span v-if="hunt.result!.model" class="text-dimmed">
509
506
  {{ t('bugHunt.viaModel', { model: hunt.result!.model }) }}
510
507
  </span>
511
508
  </p>
512
- <p v-if="hunt.result!.truncated" class="text-xs text-amber-400">
509
+ <p v-if="hunt.result!.truncated" class="text-xs text-app-warning-400">
513
510
  {{ t('bugHunt.truncated', { count: hunt.result!.scanned }) }}
514
511
  </p>
515
512
 
516
513
  <div
517
514
  v-for="candidate in hunt.candidates"
518
515
  :key="candidate.externalId"
519
- class="space-y-2 rounded-md border border-slate-800 p-3"
516
+ class="space-y-2 rounded-md border border-default p-3"
520
517
  >
521
518
  <div class="flex items-start justify-between gap-3">
522
519
  <div class="min-w-0 space-y-1">
@@ -535,12 +532,12 @@ const STATUS_KEYS: Record<BugHuntAnalysisStatus, string> = {
535
532
  :to="candidate.url"
536
533
  target="_blank"
537
534
  rel="noopener noreferrer"
538
- class="truncate text-sm font-medium text-slate-100"
535
+ class="truncate text-sm font-medium text-app-100"
539
536
  >
540
537
  {{ candidate.externalId }}: {{ candidate.title }}
541
538
  </ULink>
542
539
  </div>
543
- <p v-if="candidate.analysis" class="text-xs text-slate-400">
540
+ <p v-if="candidate.analysis" class="text-xs text-muted">
544
541
  {{
545
542
  t('bugHunt.ratings', {
546
543
  impact: candidate.analysis.impact,
@@ -549,10 +546,10 @@ const STATUS_KEYS: Record<BugHuntAnalysisStatus, string> = {
549
546
  })
550
547
  }}
551
548
  </p>
552
- <p v-if="candidate.analysis?.rationale" class="text-xs text-slate-300">
549
+ <p v-if="candidate.analysis?.rationale" class="text-xs text-toned">
553
550
  {{ candidate.analysis.rationale }}
554
551
  </p>
555
- <div class="flex flex-wrap items-center gap-2 text-[11px] text-slate-500">
552
+ <div class="flex flex-wrap items-center gap-2 text-[11px] text-dimmed">
556
553
  <span v-if="candidate.priority">{{ candidate.priority }}</span>
557
554
  <span v-for="label in candidate.labels" :key="label">{{ label }}</span>
558
555
  <span v-if="createdAtDate(candidate.createdAt)">
@@ -582,7 +579,7 @@ const STATUS_KEYS: Record<BugHuntAnalysisStatus, string> = {
582
579
  </div>
583
580
  </div>
584
581
 
585
- <p v-if="!hunt.candidates.length" class="text-center text-xs text-slate-500">
582
+ <p v-if="!hunt.candidates.length" class="text-center text-xs text-dimmed">
586
583
  {{ t('bugHunt.noCandidates') }}
587
584
  </p>
588
585
  </div>
@@ -284,7 +284,7 @@ onMounted(() => {
284
284
  </script>
285
285
 
286
286
  <template>
287
- <div class="space-y-2 rounded-lg border border-slate-800 bg-slate-900/40 p-2">
287
+ <div class="space-y-2 rounded-lg border border-default bg-default/40 p-2">
288
288
  <!-- Which tracker is being searched, always visible, plus the trackers the user could add from
289
289
  here (each opens the connect modal over the caller's form). With a single entry there is
290
290
  nothing to decide, so the tracker is named as plain text: a chevron opening a one-item menu
@@ -293,7 +293,7 @@ onMounted(() => {
293
293
  <div class="flex items-center gap-1.5">
294
294
  <span
295
295
  :id="sourceLabelId"
296
- class="shrink-0 text-[11px] font-semibold uppercase tracking-wide text-slate-500"
296
+ class="shrink-0 text-[11px] font-semibold uppercase tracking-wide text-dimmed"
297
297
  >
298
298
  {{ t('tasks.picker.sourceLabel') }}
299
299
  </span>
@@ -315,7 +315,7 @@ onMounted(() => {
315
315
  <span class="truncate">{{ descriptor?.label ?? t('tasks.picker.noSource') }}</span>
316
316
  </UButton>
317
317
  </UDropdownMenu>
318
- <span v-else class="flex min-w-0 items-center gap-1 text-xs text-slate-300">
318
+ <span v-else class="flex min-w-0 items-center gap-1 text-xs text-toned">
319
319
  <UIcon :name="icon" class="h-3.5 w-3.5 shrink-0" />
320
320
  <span class="truncate">{{ descriptor?.label ?? t('tasks.picker.noSource') }}</span>
321
321
  </span>
@@ -335,7 +335,7 @@ onMounted(() => {
335
335
  @keydown.enter="refRow && pickRef(refRow)"
336
336
  />
337
337
 
338
- <p v-if="searchError" class="px-1 text-[11px] text-amber-400">
338
+ <p v-if="searchError" class="px-1 text-[11px] text-app-warning-400">
339
339
  {{ searchError }}
340
340
  </p>
341
341
 
@@ -345,10 +345,10 @@ onMounted(() => {
345
345
  v-for="row in importedRows"
346
346
  :key="`imp:${row.externalId}`"
347
347
  type="button"
348
- class="flex w-full items-center gap-1.5 rounded-md px-2 py-1.5 text-start text-xs text-slate-300 hover:bg-slate-800/70"
348
+ class="flex w-full items-center gap-1.5 rounded-md px-2 py-1.5 text-start text-xs text-toned hover:bg-elevated/70"
349
349
  @click="pickImported(row)"
350
350
  >
351
- <UIcon :name="icon" class="h-3.5 w-3.5 shrink-0 text-indigo-400" />
351
+ <UIcon :name="icon" class="h-3.5 w-3.5 shrink-0 text-primary" />
352
352
  <span class="truncate">{{ row.externalId }} · {{ row.title }}</span>
353
353
  <UBadge color="neutral" variant="soft" size="xs" class="ms-auto shrink-0">{{
354
354
  t('tasks.picker.imported')
@@ -360,10 +360,10 @@ onMounted(() => {
360
360
  v-for="r in searchRows"
361
361
  :key="`hit:${r.externalId}`"
362
362
  type="button"
363
- class="flex w-full items-center gap-1.5 rounded-md px-2 py-1.5 text-start text-xs text-slate-300 hover:bg-slate-800/70"
363
+ class="flex w-full items-center gap-1.5 rounded-md px-2 py-1.5 text-start text-xs text-toned hover:bg-elevated/70"
364
364
  @click="pickSearch(r)"
365
365
  >
366
- <UIcon :name="icon" class="h-3.5 w-3.5 shrink-0 text-slate-400" />
366
+ <UIcon :name="icon" class="h-3.5 w-3.5 shrink-0 text-muted" />
367
367
  <span class="truncate">{{ r.externalId }} · {{ r.title }}</span>
368
368
  <UBadge v-if="r.status" color="neutral" variant="soft" size="xs" class="ms-auto shrink-0">
369
369
  {{ r.status }}
@@ -374,14 +374,14 @@ onMounted(() => {
374
374
  <button
375
375
  v-if="refRow"
376
376
  type="button"
377
- class="flex w-full items-center gap-1.5 rounded-md px-2 py-1.5 text-start text-xs text-slate-300 hover:bg-slate-800/70"
377
+ class="flex w-full items-center gap-1.5 rounded-md px-2 py-1.5 text-start text-xs text-toned hover:bg-elevated/70"
378
378
  @click="pickRef(refRow)"
379
379
  >
380
- <UIcon name="i-lucide-link" class="h-3.5 w-3.5 shrink-0 text-slate-400" />
380
+ <UIcon name="i-lucide-link" class="h-3.5 w-3.5 shrink-0 text-muted" />
381
381
  <span class="truncate">
382
382
  <i18n-t keypath="tasks.picker.attachByReference" tag="span" scope="global">
383
383
  <template #ref>
384
- <span class="text-slate-200">{{ refRow }}</span>
384
+ <span class="text-default">{{ refRow }}</span>
385
385
  </template>
386
386
  </i18n-t>
387
387
  </span>
@@ -138,11 +138,11 @@ async function attach(item: PendingContext) {
138
138
  :href="issue.url"
139
139
  target="_blank"
140
140
  rel="noopener"
141
- class="flex items-center gap-1.5 rounded-md border border-slate-800 bg-slate-900/60 px-2 py-1.5 text-xs text-slate-300 hover:bg-slate-800/60"
141
+ class="flex items-center gap-1.5 rounded-md border border-default bg-default/60 px-2 py-1.5 text-xs text-toned hover:bg-elevated/60"
142
142
  >
143
143
  <UIcon
144
144
  :name="tasks.descriptorFor(issue.source)?.icon ?? 'i-lucide-square-check'"
145
- class="h-3.5 w-3.5 shrink-0 text-indigo-400"
145
+ class="h-3.5 w-3.5 shrink-0 text-primary"
146
146
  />
147
147
  <span class="truncate">{{ issue.externalId }} · {{ issue.title }}</span>
148
148
  <UBadge color="neutral" variant="soft" size="xs" class="ms-auto shrink-0">
@@ -150,7 +150,7 @@ async function attach(item: PendingContext) {
150
150
  </UBadge>
151
151
  </a>
152
152
  </div>
153
- <p v-else class="text-[11px] text-slate-500">
153
+ <p v-else class="text-[11px] text-dimmed">
154
154
  {{ emptyHint }}
155
155
  </p>
156
156
  </InspectorSection>
@@ -126,8 +126,8 @@ async function doSpawnEpic() {
126
126
  <template #body>
127
127
  <!-- Empty state: no source offered (none connected/installed, or all disabled) -->
128
128
  <div v-if="!tasks.anyOffered" class="space-y-3 text-center">
129
- <UIcon name="i-lucide-plug" class="mx-auto h-8 w-8 text-slate-500" />
130
- <p class="text-sm text-slate-400">{{ t('tasks.import.connectFirst') }}</p>
129
+ <UIcon name="i-lucide-plug" class="mx-auto h-8 w-8 text-dimmed" />
130
+ <p class="text-sm text-muted">{{ t('tasks.import.connectFirst') }}</p>
131
131
  <div class="flex justify-center gap-2">
132
132
  <UButton
133
133
  v-for="choice in addableSources"
@@ -143,7 +143,7 @@ async function doSpawnEpic() {
143
143
  </div>
144
144
 
145
145
  <!-- No service frame yet → nowhere to create a task. -->
146
- <p v-else-if="!containerItems.length" class="text-center text-xs text-slate-500">
146
+ <p v-else-if="!containerItems.length" class="text-center text-xs text-dimmed">
147
147
  {{ t('tasks.import.needFrameFirst') }}
148
148
  </p>
149
149
 
@@ -152,10 +152,10 @@ async function doSpawnEpic() {
152
152
  <!-- Where the new task lands. Stated when there is one legal target (opened from a service
153
153
  frame that has no modules); otherwise a real choice, scoped to that frame when the
154
154
  modal was opened from one. -->
155
- <p v-if="containerStated" class="text-xs text-slate-400">
155
+ <p v-if="containerStated" class="text-xs text-muted">
156
156
  <i18n-t keypath="tasks.import.creatingIn" tag="span" scope="global">
157
157
  <template #container>
158
- <span class="font-medium text-slate-200">{{ pinnedContainer!.title }}</span>
158
+ <span class="font-medium text-default">{{ pinnedContainer!.title }}</span>
159
159
  </template>
160
160
  </i18n-t>
161
161
  </p>
@@ -182,8 +182,8 @@ async function doSpawnEpic() {
182
182
  </UFormField>
183
183
 
184
184
  <!-- Secondary: spawn a parent/epic issue as a whole linked task group. -->
185
- <div class="space-y-2 border-t border-slate-800 pt-3">
186
- <span class="text-[11px] font-semibold uppercase tracking-wide text-slate-400">
185
+ <div class="space-y-2 border-t border-default pt-3">
186
+ <span class="text-[11px] font-semibold uppercase tracking-wide text-muted">
187
187
  {{ t('tasks.import.asEpic') }}
188
188
  </span>
189
189
  <div class="flex items-end gap-2">
@@ -122,16 +122,16 @@ async function toggleEnabled(enabled: boolean) {
122
122
  </template>
123
123
  <template #body>
124
124
  <div v-if="descriptor" class="space-y-4">
125
- <p class="text-sm text-slate-400">
125
+ <p class="text-sm text-muted">
126
126
  {{ t('tasks.connect.intro', { label: descriptor.label }) }}
127
127
  </p>
128
128
 
129
129
  <!-- Credentialless source (GitHub Issues): no form, just the on/off toggle. -->
130
130
  <template v-if="credentialless">
131
- <p class="text-[11px] text-slate-500">
131
+ <p class="text-[11px] text-dimmed">
132
132
  {{ t('tasks.connect.credentialless') }}
133
133
  </p>
134
- <p v-if="!available" class="text-[11px] text-amber-400">
134
+ <p v-if="!available" class="text-[11px] text-app-warning-400">
135
135
  {{ t('tasks.connect.installAppHint', { label: descriptor.label }) }}
136
136
  </p>
137
137
  </template>
@@ -149,7 +149,7 @@ async function toggleEnabled(enabled: boolean) {
149
149
  >
150
150
  {{ t('tasks.connect.oauthButton', { label: descriptor.label }) }}
151
151
  </UButton>
152
- <p class="text-center text-[11px] text-slate-500">
152
+ <p class="text-center text-[11px] text-dimmed">
153
153
  {{ t('tasks.connect.oauthOr') }}
154
154
  </p>
155
155
  </template>
@@ -167,7 +167,7 @@ async function toggleEnabled(enabled: boolean) {
167
167
  />
168
168
  </UFormField>
169
169
  </div>
170
- <p v-else class="text-[11px] text-slate-500">
170
+ <p v-else class="text-[11px] text-dimmed">
171
171
  {{
172
172
  connection?.label
173
173
  ? t('tasks.connect.connectedTo', { label: connection.label })
@@ -178,11 +178,13 @@ async function toggleEnabled(enabled: boolean) {
178
178
  <!-- The per-workspace on/off toggle, available once the source is usable. -->
179
179
  <div
180
180
  v-if="available"
181
- class="flex items-center justify-between gap-2 rounded-md border border-slate-800 px-3 py-2"
181
+ class="flex items-center justify-between gap-2 rounded-md border border-default px-3 py-2"
182
182
  >
183
183
  <div class="text-sm">
184
- <div class="font-medium text-slate-200">{{ t('tasks.connect.offerToWorkspace') }}</div>
185
- <div class="text-[11px] text-slate-500">
184
+ <div class="font-medium text-default">
185
+ {{ t('tasks.connect.offerToWorkspace') }}
186
+ </div>
187
+ <div class="text-[11px] text-dimmed">
186
188
  {{ t('tasks.connect.offerHint', { label: descriptor.label }) }}
187
189
  </div>
188
190
  </div>