@cat-factory/app 0.302.2 → 0.303.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (328) hide show
  1. package/README.md +16 -0
  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 +23 -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 +9 -8
@@ -261,13 +261,13 @@ const hasOverrides = computed(
261
261
  <section
262
262
  v-if="store.available !== false"
263
263
  data-testid="account-platform-alerts"
264
- class="space-y-3 border-t border-slate-800 pt-6"
264
+ class="space-y-3 border-t border-default pt-6"
265
265
  >
266
266
  <div>
267
- <h4 class="text-sm font-semibold text-slate-200">
267
+ <h4 class="text-sm font-semibold text-default">
268
268
  {{ t('settings.platformAlerts.title') }}
269
269
  </h4>
270
- <p class="text-[11px] text-slate-400">{{ t('settings.platformAlerts.description') }}</p>
270
+ <p class="text-[11px] text-muted">{{ t('settings.platformAlerts.description') }}</p>
271
271
  </div>
272
272
 
273
273
  <!--
@@ -282,11 +282,11 @@ const hasOverrides = computed(
282
282
  :label="t('settings.platformAlerts.muteLabel')"
283
283
  data-testid="platform-alerts-mute"
284
284
  />
285
- <p class="ps-6 text-[11px] text-slate-400">{{ t('settings.platformAlerts.muteHint') }}</p>
285
+ <p class="ps-6 text-[11px] text-muted">{{ t('settings.platformAlerts.muteHint') }}</p>
286
286
  </div>
287
287
 
288
288
  <div class="space-y-1">
289
- <label class="text-[11px] font-medium text-slate-300">
289
+ <label class="text-[11px] font-medium text-toned">
290
290
  {{ t('settings.platformAlerts.windowLabel') }}
291
291
  </label>
292
292
  <div class="grid grid-cols-1 gap-2 sm:grid-cols-2">
@@ -298,17 +298,17 @@ const hasOverrides = computed(
298
298
  data-testid="platform-alerts-window"
299
299
  />
300
300
  </div>
301
- <p class="text-[11px] text-slate-400">{{ t('settings.platformAlerts.windowHint') }}</p>
301
+ <p class="text-[11px] text-muted">{{ t('settings.platformAlerts.windowHint') }}</p>
302
302
  </div>
303
303
 
304
304
  <div class="space-y-2">
305
- <label class="text-[11px] font-medium text-slate-300">
305
+ <label class="text-[11px] font-medium text-toned">
306
306
  {{ t('settings.platformAlerts.thresholdsLabel') }}
307
307
  </label>
308
- <p class="text-[11px] text-slate-400">{{ t('settings.platformAlerts.inheritHint') }}</p>
308
+ <p class="text-[11px] text-muted">{{ t('settings.platformAlerts.inheritHint') }}</p>
309
309
  <div class="grid grid-cols-1 gap-3 sm:grid-cols-2">
310
310
  <div v-for="th in THRESHOLDS" :key="th.field" class="space-y-1">
311
- <label class="block text-[11px] text-slate-300" :for="`platform-alert-${th.field}`">
311
+ <label class="block text-[11px] text-toned" :for="`platform-alert-${th.field}`">
312
312
  {{ thresholdLabels[th.field] }}
313
313
  </label>
314
314
  <UInput
@@ -320,7 +320,7 @@ const hasOverrides = computed(
320
320
  :placeholder="t('settings.platformAlerts.inheritPlaceholder')"
321
321
  :data-testid="`platform-alert-${th.field}`"
322
322
  />
323
- <p class="text-[11px] leading-snug text-slate-500">{{ thresholdHints[th.field] }}</p>
323
+ <p class="text-[11px] leading-snug text-dimmed">{{ thresholdHints[th.field] }}</p>
324
324
  </div>
325
325
  </div>
326
326
  </div>
@@ -334,7 +334,7 @@ const hasOverrides = computed(
334
334
  -->
335
335
  <p
336
336
  v-if="!loaded"
337
- class="rounded-lg border border-amber-800/60 bg-amber-950/30 px-3 py-2 text-xs text-amber-200"
337
+ class="rounded-lg border border-app-warning-800/60 bg-app-warning-950/30 px-3 py-2 text-xs text-app-warning-200"
338
338
  data-testid="account-platform-alerts-unloaded"
339
339
  >
340
340
  {{ t('settings.platformAlerts.notLoaded') }}
@@ -99,9 +99,9 @@ async function create(input: CreateRiskPolicyInput) {
99
99
 
100
100
  <template>
101
101
  <div class="space-y-4 text-sm" data-testid="account-risk-policy-panel">
102
- <p class="text-[11px] text-slate-400">{{ t('layout.accountRiskPolicies.intro') }}</p>
102
+ <p class="text-[11px] text-muted">{{ t('layout.accountRiskPolicies.intro') }}</p>
103
103
 
104
- <p v-if="!store.loading && policies.length === 0" class="text-[11px] text-slate-500">
104
+ <p v-if="!store.loading && policies.length === 0" class="text-[11px] text-dimmed">
105
105
  {{ t('layout.accountRiskPolicies.empty') }}
106
106
  </p>
107
107
 
@@ -59,22 +59,22 @@ async function save() {
59
59
 
60
60
  <template>
61
61
  <div v-if="store.available !== false" class="space-y-2" data-testid="account-run-credential">
62
- <h3 class="text-sm font-semibold text-slate-200">
62
+ <h3 class="text-sm font-semibold text-default">
63
63
  {{ t('settings.runCredentialPolicy.heading') }}
64
64
  </h3>
65
- <p class="text-[11px] text-slate-400">{{ t('settings.runCredentialPolicy.body') }}</p>
65
+ <p class="text-[11px] text-muted">{{ t('settings.runCredentialPolicy.body') }}</p>
66
66
 
67
67
  <label class="flex items-center gap-2">
68
68
  <USwitch v-model="forbid" size="sm" data-testid="account-forbid-initiator-pat" />
69
- <span class="text-sm text-slate-200">{{ t('settings.runCredentialPolicy.toggle') }}</span>
69
+ <span class="text-sm text-default">{{ t('settings.runCredentialPolicy.toggle') }}</span>
70
70
  </label>
71
71
 
72
72
  <!-- What the choice actually costs, stated at the point of choosing rather than discovered
73
73
  later: attribution is a real feature, and turning this on is what trades it away. -->
74
- <p v-if="forbid" class="text-[11px] text-amber-300">
74
+ <p v-if="forbid" class="text-[11px] text-app-warning-300">
75
75
  {{ t('settings.runCredentialPolicy.onHint') }}
76
76
  </p>
77
- <p v-else class="text-[11px] text-slate-500">
77
+ <p v-else class="text-[11px] text-dimmed">
78
78
  {{ t('settings.runCredentialPolicy.offHint') }}
79
79
  </p>
80
80
 
@@ -12,7 +12,7 @@ const { t } = useI18n()
12
12
  <template>
13
13
  <div class="space-y-6 text-sm">
14
14
  <section>
15
- <p class="mb-3 text-[11px] text-slate-400">
15
+ <p class="mb-3 text-[11px] text-muted">
16
16
  {{ t('layout.accountSkills.intro') }}
17
17
  </p>
18
18
  <SkillLibraryManager :account-id="props.accountId" />
@@ -200,9 +200,11 @@ async function disconnectEmail() {
200
200
  <template>
201
201
  <div class="space-y-6 text-sm">
202
202
  <!-- personal-account CTA: members/roles/invitations need an organization -->
203
- <section v-if="!isOrg" class="rounded-md border border-slate-800 bg-slate-800/40 p-4">
204
- <h3 class="mb-1 font-semibold text-white">{{ t('layout.accountTeam.org.ctaTitle') }}</h3>
205
- <p class="mb-3 text-slate-400">
203
+ <section v-if="!isOrg" class="rounded-md border border-default bg-elevated/40 p-4">
204
+ <h3 class="mb-1 font-semibold text-highlighted">
205
+ {{ t('layout.accountTeam.org.ctaTitle') }}
206
+ </h3>
207
+ <p class="mb-3 text-muted">
206
208
  {{ t('layout.accountTeam.org.ctaBody') }}
207
209
  </p>
208
210
  <form class="flex gap-2" @submit.prevent="createOrganization">
@@ -219,12 +221,14 @@ async function disconnectEmail() {
219
221
 
220
222
  <!-- members -->
221
223
  <section v-if="isOrg">
222
- <h3 class="mb-2 font-semibold text-white">{{ t('layout.accountTeam.members.title') }}</h3>
224
+ <h3 class="mb-2 font-semibold text-highlighted">
225
+ {{ t('layout.accountTeam.members.title') }}
226
+ </h3>
223
227
  <ul class="space-y-1">
224
228
  <li
225
229
  v-for="m in accounts.members"
226
230
  :key="m.userId"
227
- class="flex items-center justify-between rounded-md bg-slate-800/40 px-2 py-1"
231
+ class="flex items-center justify-between rounded-md bg-elevated/40 px-2 py-1"
228
232
  >
229
233
  <span class="truncate">{{ m.name || m.email || m.userId }}</span>
230
234
  <USelect
@@ -236,7 +240,7 @@ async function disconnectEmail() {
236
240
  class="w-44"
237
241
  @update:model-value="(r: AccountRole[]) => updateMemberRoles(m.userId, r)"
238
242
  />
239
- <span v-else class="text-xs uppercase tracking-wide text-slate-400">
243
+ <span v-else class="text-xs uppercase tracking-wide text-muted">
240
244
  {{ m.roles.join(', ') }}
241
245
  </span>
242
246
  <!-- Offboarding: end every session this member holds, leaving their membership and
@@ -254,7 +258,7 @@ async function disconnectEmail() {
254
258
  @click="revokeSessions(m.userId, m.name || m.email || m.userId)"
255
259
  />
256
260
  </li>
257
- <li v-if="accounts.members.length === 0" class="text-slate-500">
261
+ <li v-if="accounts.members.length === 0" class="text-dimmed">
258
262
  {{ t('layout.accountTeam.members.empty') }}
259
263
  </li>
260
264
  </ul>
@@ -262,7 +266,9 @@ async function disconnectEmail() {
262
266
 
263
267
  <!-- invitations -->
264
268
  <section v-if="isOrg">
265
- <h3 class="mb-2 font-semibold text-white">{{ t('layout.accountTeam.invite.title') }}</h3>
269
+ <h3 class="mb-2 font-semibold text-highlighted">
270
+ {{ t('layout.accountTeam.invite.title') }}
271
+ </h3>
266
272
  <form class="flex gap-2" @submit.prevent="sendInvite">
267
273
  <UInput
268
274
  v-model="inviteEmail"
@@ -280,11 +286,11 @@ async function disconnectEmail() {
280
286
  <li
281
287
  v-for="inv in accounts.invitations"
282
288
  :key="inv.id"
283
- class="flex items-center justify-between rounded-md bg-slate-800/40 px-2 py-1"
289
+ class="flex items-center justify-between rounded-md bg-elevated/40 px-2 py-1"
284
290
  >
285
291
  <span class="truncate">{{ inv.email }}</span>
286
292
  <span class="flex items-center gap-2 text-xs">
287
- <span class="uppercase tracking-wide text-slate-400">
293
+ <span class="uppercase tracking-wide text-muted">
288
294
  {{ invitationStatusLabel(inv.status) }}
289
295
  </span>
290
296
  <UButton
@@ -303,14 +309,14 @@ async function disconnectEmail() {
303
309
 
304
310
  <!-- email sender -->
305
311
  <section>
306
- <h3 class="mb-2 font-semibold text-white">{{ t('layout.accountTeam.email.title') }}</h3>
307
- <p v-if="!accounts.emailConfigured" class="text-slate-500">
312
+ <h3 class="mb-2 font-semibold text-highlighted">{{ t('layout.accountTeam.email.title') }}</h3>
313
+ <p v-if="!accounts.emailConfigured" class="text-dimmed">
308
314
  {{ t('layout.accountTeam.email.notEnabled') }}
309
315
  </p>
310
316
  <template v-else>
311
317
  <div
312
318
  v-if="accounts.emailConnection"
313
- class="flex items-center justify-between rounded-md bg-slate-800/40 px-2 py-1.5"
319
+ class="flex items-center justify-between rounded-md bg-elevated/40 px-2 py-1.5"
314
320
  >
315
321
  <i18n-t keypath="layout.accountTeam.email.connectedAs" tag="span" scope="global">
316
322
  <template #provider>
@@ -344,9 +350,11 @@ async function disconnectEmail() {
344
350
 
345
351
  <!-- account-wide provider API keys (admin-only): direct vendors + proxy gateways -->
346
352
  <section v-if="isAdmin" class="space-y-6">
347
- <h3 class="mb-2 font-semibold text-white">{{ t('layout.accountTeam.apiKeys.title') }}</h3>
353
+ <h3 class="mb-2 font-semibold text-highlighted">
354
+ {{ t('layout.accountTeam.apiKeys.title') }}
355
+ </h3>
348
356
  <ProvidersApiKeysSection :account-id="accountId" category="direct" />
349
- <div class="border-t border-slate-800 pt-6">
357
+ <div class="border-t border-default pt-6">
350
358
  <ProvidersApiKeysSection :account-id="accountId" category="proxy" />
351
359
  </div>
352
360
  </section>
@@ -24,14 +24,14 @@ const show = computed(() => showSetup.value || showPreset.value)
24
24
  <!-- (1) No usable AI source -->
25
25
  <div
26
26
  v-if="showSetup"
27
- class="w-full max-w-3xl rounded-2xl border-2 border-amber-500/70 bg-amber-950/95 p-5 shadow-2xl backdrop-blur"
27
+ class="w-full max-w-3xl rounded-2xl border-2 border-app-warning-500/70 bg-app-warning-950/95 p-5 shadow-2xl backdrop-blur"
28
28
  role="alert"
29
29
  >
30
30
  <div class="flex items-start gap-4">
31
- <UIcon name="i-lucide-cpu" class="mt-0.5 h-9 w-9 shrink-0 text-amber-400" />
31
+ <UIcon name="i-lucide-cpu" class="mt-0.5 h-9 w-9 shrink-0 text-app-warning-400" />
32
32
  <div class="min-w-0 flex-1">
33
33
  <div class="flex items-start justify-between gap-3">
34
- <h2 class="text-lg font-semibold text-amber-100">
34
+ <h2 class="text-lg font-semibold text-app-warning-100">
35
35
  {{ t('layout.aiProvidersBanner.setup.title') }}
36
36
  </h2>
37
37
  <UButton
@@ -43,7 +43,7 @@ const show = computed(() => showSetup.value || showPreset.value)
43
43
  @click="ui.dismissAiSetup()"
44
44
  />
45
45
  </div>
46
- <p class="mt-1 text-sm text-amber-200/90">
46
+ <p class="mt-1 text-sm text-app-warning-200/90">
47
47
  {{ t('layout.aiProvidersBanner.setup.body') }}
48
48
  </p>
49
49
  <div class="mt-4">
@@ -63,14 +63,17 @@ const show = computed(() => showSetup.value || showPreset.value)
63
63
  <!-- (2) Default preset references unavailable models -->
64
64
  <div
65
65
  v-else
66
- class="w-full max-w-3xl rounded-2xl border border-amber-500/50 bg-amber-950/90 p-4 shadow-xl backdrop-blur"
66
+ class="w-full max-w-3xl rounded-2xl border border-app-warning-500/50 bg-app-warning-950/90 p-4 shadow-xl backdrop-blur"
67
67
  role="alert"
68
68
  >
69
69
  <div class="flex items-start gap-3">
70
- <UIcon name="i-lucide-triangle-alert" class="mt-0.5 h-7 w-7 shrink-0 text-amber-400" />
70
+ <UIcon
71
+ name="i-lucide-triangle-alert"
72
+ class="mt-0.5 h-7 w-7 shrink-0 text-app-warning-400"
73
+ />
71
74
  <div class="min-w-0 flex-1">
72
75
  <div class="flex items-start justify-between gap-3">
73
- <h2 class="text-sm font-semibold text-amber-100">
76
+ <h2 class="text-sm font-semibold text-app-warning-100">
74
77
  {{ t('layout.aiProvidersBanner.preset.title') }}
75
78
  </h2>
76
79
  <UButton
@@ -82,7 +85,7 @@ const show = computed(() => showSetup.value || showPreset.value)
82
85
  @click="ui.dismissAiPresetMismatch()"
83
86
  />
84
87
  </div>
85
- <p class="mt-1 text-[13px] text-amber-200/90">
88
+ <p class="mt-1 text-[13px] text-app-warning-200/90">
86
89
  {{ t('layout.aiProvidersBanner.preset.body') }}
87
90
  </p>
88
91
  <div class="mt-3">
@@ -0,0 +1,108 @@
1
+ <script setup lang="ts">
2
+ import type { DropdownMenuItem } from '@nuxt/ui'
3
+ import { computed, ref } from 'vue'
4
+ import ThemeImportModal from '~/components/theme/ThemeImportModal.vue'
5
+ import { useThemeStore } from '~/stores/theme'
6
+
7
+ // Appearance picker, shown at the sidebar bottom beside the language switcher: colour MODE
8
+ // (system / light / dark) and THEME (the built-ins plus anything the user imported from the Nuxt
9
+ // UI theme editor) in one dropdown, because they are two halves of one question ("what does the
10
+ // app look like") and each on its own would cost a footer row for a control used once.
11
+ //
12
+ // Mode is `@nuxtjs/color-mode`'s preference (its own persisted storage); theme is the theme store.
13
+ // Neither is a deployment setting or an RBAC matter, so the row shows for every tier and role.
14
+ //
15
+ // `collapsed` renders the icon-only rail variant; the dropdown itself is unchanged.
16
+ withDefaults(defineProps<{ collapsed?: boolean }>(), { collapsed: false })
17
+
18
+ const { t } = useI18n()
19
+ const colorMode = useColorMode()
20
+ const theme = useThemeStore()
21
+ const importOpen = ref(false)
22
+
23
+ type ModePreference = 'system' | 'light' | 'dark'
24
+ const MODES: readonly ModePreference[] = ['system', 'light', 'dark']
25
+ // Static literal keys, one per mode, so the typed-message-keys check sees them.
26
+ const MODE_LABELS: Record<ModePreference, string> = {
27
+ system: 'appearance.mode.system',
28
+ light: 'appearance.mode.light',
29
+ dark: 'appearance.mode.dark',
30
+ }
31
+ const MODE_ICONS: Record<ModePreference, string> = {
32
+ system: 'i-lucide-monitor',
33
+ light: 'i-lucide-sun',
34
+ dark: 'i-lucide-moon',
35
+ }
36
+
37
+ function isMode(value: string): value is ModePreference {
38
+ return (MODES as readonly string[]).includes(value)
39
+ }
40
+ const preference = computed<ModePreference>(() =>
41
+ isMode(colorMode.preference) ? colorMode.preference : 'system',
42
+ )
43
+
44
+ const summary = computed(() => `${theme.active.name} · ${t(MODE_LABELS[preference.value])}`)
45
+
46
+ const items = computed<DropdownMenuItem[][]>(() => [
47
+ MODES.map((mode) => ({
48
+ label: t(MODE_LABELS[mode]),
49
+ icon: MODE_ICONS[mode],
50
+ type: 'checkbox' as const,
51
+ checked: preference.value === mode,
52
+ onSelect: () => {
53
+ colorMode.preference = mode
54
+ },
55
+ })),
56
+ [
57
+ { label: t('appearance.theme.section'), type: 'label' as const },
58
+ ...theme.themes.map((candidate) => ({
59
+ label: candidate.name,
60
+ type: 'checkbox' as const,
61
+ checked: theme.current === candidate.id,
62
+ onSelect: () => theme.select(candidate.id),
63
+ })),
64
+ ],
65
+ [
66
+ {
67
+ label: t('appearance.theme.import'),
68
+ icon: 'i-lucide-palette',
69
+ onSelect: () => {
70
+ importOpen.value = true
71
+ },
72
+ },
73
+ ...(theme.isCustom
74
+ ? [
75
+ {
76
+ label: t('appearance.theme.remove'),
77
+ icon: 'i-lucide-trash-2',
78
+ color: 'error' as const,
79
+ onSelect: () => theme.removeCustom(theme.current),
80
+ },
81
+ ]
82
+ : []),
83
+ ],
84
+ ])
85
+ </script>
86
+
87
+ <template>
88
+ <UDropdownMenu :items="items" :content="{ side: 'top', align: 'start' }">
89
+ <button
90
+ type="button"
91
+ data-testid="appearance-switcher"
92
+ :aria-label="t('appearance.switcher')"
93
+ :title="collapsed ? `${t('appearance.switcher')}: ${summary}` : undefined"
94
+ class="flex w-full items-center gap-2 rounded-lg border border-default bg-default/60 p-2 text-start transition hover:bg-elevated/60"
95
+ :class="collapsed ? 'justify-center' : ''"
96
+ >
97
+ <UIcon :name="MODE_ICONS[preference]" class="h-4 w-4 shrink-0 text-muted" />
98
+ <div v-if="!collapsed" class="min-w-0 flex-1">
99
+ <div class="truncate text-[10px] uppercase tracking-wide text-dimmed">
100
+ {{ t('appearance.switcher') }}
101
+ </div>
102
+ <div class="truncate text-xs font-medium text-highlighted">{{ summary }}</div>
103
+ </div>
104
+ <UIcon v-if="!collapsed" name="i-lucide-chevron-up" class="h-4 w-4 shrink-0 text-dimmed" />
105
+ </button>
106
+ </UDropdownMenu>
107
+ <ThemeImportModal v-model:open="importOpen" />
108
+ </template>
@@ -258,20 +258,17 @@ async function submitPrompt() {
258
258
  >
259
259
  <button
260
260
  type="button"
261
- class="flex w-full items-center gap-2 rounded-md px-1.5 py-1 text-start transition hover:bg-slate-800/60"
261
+ class="flex w-full items-center gap-2 rounded-md px-1.5 py-1 text-start transition hover:bg-elevated/60"
262
262
  :disabled="busy"
263
263
  >
264
264
  <UIcon
265
265
  :name="accounts.activeAccount?.type === 'org' ? 'i-lucide-users' : 'i-lucide-user'"
266
- class="h-3.5 w-3.5 shrink-0 text-slate-400"
266
+ class="h-3.5 w-3.5 shrink-0 text-muted"
267
267
  />
268
- <span class="truncate text-[11px] font-medium uppercase tracking-wide text-slate-400">
268
+ <span class="truncate text-[11px] font-medium uppercase tracking-wide text-muted">
269
269
  {{ accounts.activeAccount?.name ?? t('layout.boardSwitcher.accountFallback') }}
270
270
  </span>
271
- <UIcon
272
- name="i-lucide-chevrons-up-down"
273
- class="ms-auto h-3.5 w-3.5 shrink-0 text-slate-600"
274
- />
271
+ <UIcon name="i-lucide-chevrons-up-down" class="ms-auto h-3.5 w-3.5 shrink-0 text-app-600" />
275
272
  </button>
276
273
  </UDropdownMenu>
277
274
 
@@ -284,20 +281,20 @@ async function submitPrompt() {
284
281
  ? (workspace.activeWorkspace?.name ?? t('layout.boardSwitcher.boardFallback'))
285
282
  : undefined
286
283
  "
287
- class="flex w-full items-center gap-2 rounded-lg border border-slate-800 bg-slate-900/60 px-2.5 py-1.5 text-start transition hover:bg-slate-800/60"
284
+ class="flex w-full items-center gap-2 rounded-lg border border-default bg-default/60 px-2.5 py-1.5 text-start transition hover:bg-elevated/60"
288
285
  :class="collapsed ? 'justify-center' : ''"
289
286
  :disabled="busy"
290
287
  data-testid="board-switcher"
291
288
  :data-board-id="workspace.workspaceId ?? ''"
292
289
  >
293
- <UIcon name="i-lucide-layout-dashboard" class="h-4 w-4 shrink-0 text-indigo-400" />
294
- <span v-if="!collapsed" class="truncate text-sm font-medium text-white">
290
+ <UIcon name="i-lucide-layout-dashboard" class="h-4 w-4 shrink-0 text-primary" />
291
+ <span v-if="!collapsed" class="truncate text-sm font-medium text-highlighted">
295
292
  {{ workspace.activeWorkspace?.name ?? t('layout.boardSwitcher.boardFallback') }}
296
293
  </span>
297
294
  <UIcon
298
295
  v-if="!collapsed"
299
296
  name="i-lucide-chevron-down"
300
- class="ms-auto h-4 w-4 shrink-0 text-slate-500"
297
+ class="ms-auto h-4 w-4 shrink-0 text-dimmed"
301
298
  />
302
299
  </button>
303
300
  </UDropdownMenu>
@@ -132,7 +132,7 @@ const decisionItems = computed(() =>
132
132
  the board's top overlay region; this renders only the pill and re-enables pointer events
133
133
  on it. Self-anchoring here is what let a banner cover the toolbar outright. -->
134
134
  <div
135
- class="pointer-events-auto flex max-w-full items-center gap-1 overflow-x-auto rounded-full border border-slate-700 bg-slate-900/90 px-2 py-1.5 shadow-xl backdrop-blur"
135
+ class="pointer-events-auto flex max-w-full items-center gap-1 overflow-x-auto rounded-full border border-muted bg-default/90 px-2 py-1.5 shadow-xl backdrop-blur"
136
136
  >
137
137
  <!-- zoom controls -->
138
138
  <IconButton
@@ -153,14 +153,14 @@ const decisionItems = computed(() =>
153
153
  drops on narrow viewports) so the zoom level is never a mystery. -->
154
154
  <button
155
155
  type="button"
156
- class="w-16 rounded text-center text-xs tabular-nums text-slate-300 hover:bg-slate-800 focus-visible:ring-2 focus-visible:ring-slate-400/60 sm:w-20"
156
+ class="w-16 rounded text-center text-xs tabular-nums text-toned hover:bg-elevated focus-visible:ring-2 focus-visible:ring-app-400/60 sm:w-20"
157
157
  :title="t('board.toolbar.resetZoom')"
158
158
  :aria-label="t('board.toolbar.resetZoom')"
159
159
  data-testid="board-zoom-reset"
160
160
  @click="resetZoom()"
161
161
  >
162
162
  {{ zoomPct }}%
163
- <span class="hidden text-[9px] uppercase tracking-wide text-slate-500 sm:block">{{
163
+ <span class="hidden text-[9px] uppercase tracking-wide text-dimmed sm:block">{{
164
164
  lodLabel
165
165
  }}</span>
166
166
  </button>
@@ -256,8 +256,8 @@ function indexOf(cmd: Command) {
256
256
  <UModal v-model:open="open" :ui="{ content: 'max-w-xl' }">
257
257
  <template #content>
258
258
  <div class="flex flex-col" data-testid="command-bar" @keydown="onKeydown">
259
- <div class="flex items-center gap-2 border-b border-slate-800 px-3">
260
- <UIcon name="i-lucide-search" class="h-4 w-4 shrink-0 text-slate-500" />
259
+ <div class="flex items-center gap-2 border-b border-default px-3">
260
+ <UIcon name="i-lucide-search" class="h-4 w-4 shrink-0 text-dimmed" />
261
261
  <UInput
262
262
  ref="inputRef"
263
263
  v-model="query"
@@ -271,14 +271,12 @@ function indexOf(cmd: Command) {
271
271
  </div>
272
272
 
273
273
  <div class="max-h-80 overflow-y-auto p-1.5">
274
- <p v-if="filtered.length === 0" class="px-3 py-6 text-center text-sm text-slate-500">
274
+ <p v-if="filtered.length === 0" class="px-3 py-6 text-center text-sm text-dimmed">
275
275
  {{ t('layout.commandBar.noMatches') }}
276
276
  </p>
277
277
 
278
278
  <div v-for="group in groups" :key="group.name" class="mb-1">
279
- <p
280
- class="px-2 pb-1 pt-2 text-[11px] font-semibold uppercase tracking-wide text-slate-500"
281
- >
279
+ <p class="px-2 pb-1 pt-2 text-[11px] font-semibold uppercase tracking-wide text-dimmed">
282
280
  {{ group.name }}
283
281
  </p>
284
282
  <button
@@ -289,13 +287,13 @@ function indexOf(cmd: Command) {
289
287
  class="flex w-full items-center gap-2.5 rounded-md px-2 py-1.5 text-start text-sm transition"
290
288
  :class="
291
289
  indexOf(cmd) === activeIndex
292
- ? 'bg-slate-800 text-slate-100'
293
- : 'text-slate-300 hover:bg-slate-800/60'
290
+ ? 'bg-elevated text-app-100'
291
+ : 'text-toned hover:bg-elevated/60'
294
292
  "
295
293
  @mousemove="activeIndex = indexOf(cmd)"
296
294
  @click="run(cmd)"
297
295
  >
298
- <UIcon :name="cmd.icon" class="h-4 w-4 shrink-0 text-slate-400" />
296
+ <UIcon :name="cmd.icon" class="h-4 w-4 shrink-0 text-muted" />
299
297
  <span class="truncate">{{ cmd.label }}</span>
300
298
  </button>
301
299
  </div>
@@ -65,7 +65,7 @@ onBeforeUnmount(clearTimer)
65
65
  <div v-if="reconnecting || offline" class="pointer-events-none flex w-full justify-center">
66
66
  <div
67
67
  v-if="reconnecting"
68
- class="pointer-events-auto flex items-center gap-2 rounded-full border border-amber-500/60 bg-amber-950/90 px-3 py-1.5 text-xs text-amber-100 shadow-lg backdrop-blur"
68
+ class="pointer-events-auto flex items-center gap-2 rounded-full border border-app-warning-500/60 bg-app-warning-950/90 px-3 py-1.5 text-xs text-app-warning-100 shadow-lg backdrop-blur"
69
69
  role="status"
70
70
  aria-live="polite"
71
71
  data-testid="stream-reconnecting"
@@ -75,7 +75,7 @@ onBeforeUnmount(clearTimer)
75
75
  </div>
76
76
  <div
77
77
  v-else
78
- class="pointer-events-auto flex items-center gap-2 rounded-full border border-rose-500/60 bg-rose-950/90 px-3 py-1.5 text-xs text-rose-100 shadow-lg backdrop-blur"
78
+ class="pointer-events-auto flex items-center gap-2 rounded-full border border-app-error-500/60 bg-app-error-950/90 px-3 py-1.5 text-xs text-app-error-100 shadow-lg backdrop-blur"
79
79
  role="status"
80
80
  aria-live="polite"
81
81
  data-testid="stream-offline"
@@ -52,16 +52,16 @@ function openConfig(event: MouseEvent) {
52
52
  <Transition name="fade">
53
53
  <div
54
54
  v-if="show"
55
- class="pointer-events-auto w-full max-w-3xl rounded-2xl border border-sky-500/50 bg-sky-950/90 p-4 shadow-xl backdrop-blur"
55
+ class="pointer-events-auto w-full max-w-3xl rounded-2xl border border-app-info-500/50 bg-app-info-950/90 p-4 shadow-xl backdrop-blur"
56
56
  role="status"
57
57
  aria-live="polite"
58
58
  data-testid="default-test-env-banner"
59
59
  >
60
60
  <div class="flex items-start gap-3">
61
- <UIcon name="i-lucide-flask-conical" class="mt-0.5 h-7 w-7 shrink-0 text-sky-400" />
61
+ <UIcon name="i-lucide-flask-conical" class="mt-0.5 h-7 w-7 shrink-0 text-app-info-400" />
62
62
  <div class="min-w-0 flex-1">
63
63
  <div class="flex items-start justify-between gap-3">
64
- <h2 class="text-sm font-semibold text-sky-100">
64
+ <h2 class="text-sm font-semibold text-app-info-100">
65
65
  {{ t('layout.defaultTestEnvBanner.title') }}
66
66
  </h2>
67
67
  <UButton
@@ -74,7 +74,7 @@ function openConfig(event: MouseEvent) {
74
74
  @click="ui.dismissDefaultProvision()"
75
75
  />
76
76
  </div>
77
- <p class="mt-1 text-[13px] text-sky-200/90">
77
+ <p class="mt-1 text-[13px] text-app-info-200/90">
78
78
  {{ t('layout.defaultTestEnvBanner.body') }}
79
79
  </p>
80
80
  <div class="mt-3 flex flex-wrap items-center gap-x-3 gap-y-2">
@@ -92,7 +92,7 @@ function openConfig(event: MouseEvent) {
92
92
  <!-- The URL itself, shown so it can be read and copied, not just clicked. -->
93
93
  <a
94
94
  :href="configUrl"
95
- class="min-w-0 truncate font-mono text-[11px] text-sky-300/80 underline decoration-dotted underline-offset-2 hover:text-sky-200"
95
+ class="min-w-0 truncate font-mono text-[11px] text-app-info-300/80 underline decoration-dotted underline-offset-2 hover:text-app-info-200"
96
96
  data-testid="default-test-env-url"
97
97
  @click="openConfig"
98
98
  >
@@ -20,14 +20,14 @@ const show = computed(() => !!setupUrl.value && !dismissed.value)
20
20
  re-enables pointer events on it. -->
21
21
  <div v-if="show" class="pointer-events-auto w-full max-w-3xl">
22
22
  <div
23
- class="w-full max-w-3xl rounded-2xl border-2 border-amber-500/70 bg-amber-950/95 p-5 shadow-2xl backdrop-blur"
23
+ class="w-full max-w-3xl rounded-2xl border-2 border-app-warning-500/70 bg-app-warning-950/95 p-5 shadow-2xl backdrop-blur"
24
24
  role="alert"
25
25
  >
26
26
  <div class="flex items-start gap-4">
27
- <UIcon name="i-lucide-key-round" class="mt-0.5 h-9 w-9 shrink-0 text-amber-400" />
27
+ <UIcon name="i-lucide-key-round" class="mt-0.5 h-9 w-9 shrink-0 text-app-warning-400" />
28
28
  <div class="min-w-0 flex-1">
29
29
  <div class="flex items-start justify-between gap-3">
30
- <h2 class="text-lg font-semibold text-amber-100">
30
+ <h2 class="text-lg font-semibold text-app-warning-100">
31
31
  {{ t('layout.githubPatBanner.title') }}
32
32
  </h2>
33
33
  <UButton
@@ -43,7 +43,7 @@ const show = computed(() => !!setupUrl.value && !dismissed.value)
43
43
  "
44
44
  />
45
45
  </div>
46
- <p class="mt-1 text-sm text-amber-200/90">
46
+ <p class="mt-1 text-sm text-app-warning-200/90">
47
47
  {{ t('layout.githubPatBanner.body') }}
48
48
  </p>
49
49
 
@@ -59,7 +59,7 @@ const show = computed(() => !!setupUrl.value && !dismissed.value)
59
59
  >
60
60
  {{ t('layout.githubPatBanner.createToken') }}
61
61
  </UButton>
62
- <p class="mt-2 text-xs text-amber-300/70">
62
+ <p class="mt-2 text-xs text-app-warning-300/70">
63
63
  <i18n-t keypath="layout.githubPatBanner.thenSet" tag="span" scope="global">
64
64
  <template #envVar>
65
65
  <code class="font-mono">GITHUB_PAT</code>