@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
@@ -102,15 +102,15 @@ const fineGrainedPermissions = GITHUB_PAT_FINE_GRAINED_PERMISSIONS.join(', ')
102
102
  <Transition name="fade">
103
103
  <div v-if="show" class="pointer-events-auto w-full max-w-3xl">
104
104
  <div
105
- class="w-full max-w-3xl rounded-2xl border-2 border-red-500/70 bg-red-950/95 p-5 shadow-2xl backdrop-blur"
105
+ class="w-full max-w-3xl rounded-2xl border-2 border-app-error-500/70 bg-app-error-950/95 p-5 shadow-2xl backdrop-blur"
106
106
  role="alert"
107
107
  data-testid="github-pat-permissions-banner"
108
108
  >
109
109
  <div class="flex items-start gap-4">
110
- <UIcon name="i-lucide-shield-alert" class="mt-0.5 h-9 w-9 shrink-0 text-red-400" />
110
+ <UIcon name="i-lucide-shield-alert" class="mt-0.5 h-9 w-9 shrink-0 text-app-error-400" />
111
111
  <div class="min-w-0 flex-1">
112
112
  <div class="flex items-start justify-between gap-3">
113
- <h2 class="text-lg font-semibold text-red-100">
113
+ <h2 class="text-lg font-semibold text-app-error-100">
114
114
  {{
115
115
  claim === 'rejected'
116
116
  ? t('layout.githubPatPermissionsBanner.rejectedTitle')
@@ -131,7 +131,7 @@ const fineGrainedPermissions = GITHUB_PAT_FINE_GRAINED_PERMISSIONS.join(', ')
131
131
  />
132
132
  </div>
133
133
 
134
- <p class="mt-1 text-sm text-red-200/90">
134
+ <p class="mt-1 text-sm text-app-error-200/90">
135
135
  {{
136
136
  claim === 'rejected'
137
137
  ? t('layout.githubPatPermissionsBanner.rejectedBody')
@@ -141,11 +141,11 @@ const fineGrainedPermissions = GITHUB_PAT_FINE_GRAINED_PERMISSIONS.join(', ')
141
141
 
142
142
  <!-- The established gaps, named one by one. A bare "permissions are missing" leaves
143
143
  the reader to guess which box to tick on a form with dozens. -->
144
- <p v-if="missing.length" class="mt-3 text-sm text-red-100">
144
+ <p v-if="missing.length" class="mt-3 text-sm text-app-error-100">
145
145
  <span class="font-medium">{{ t('layout.githubPatPermissionsBanner.missing') }}</span>
146
146
  {{ missing.map(capabilityLabel).join(', ') }}
147
147
  </p>
148
- <p v-if="advisory.length" class="mt-1 text-xs text-red-200/80">
148
+ <p v-if="advisory.length" class="mt-1 text-xs text-app-error-200/80">
149
149
  {{
150
150
  t('layout.githubPatPermissionsBanner.alsoMissing', {
151
151
  capabilities: advisory.map(capabilityLabel).join(', '),
@@ -155,7 +155,10 @@ const fineGrainedPermissions = GITHUB_PAT_FINE_GRAINED_PERMISSIONS.join(', ')
155
155
 
156
156
  <!-- For a fine-grained token, WHICH repositories it was not granted is the whole
157
157
  remedy: the permission list is right and the repository selection is not. -->
158
- <p v-if="report && report.deniedRepos.length" class="mt-1 text-xs text-red-200/80">
158
+ <p
159
+ v-if="report && report.deniedRepos.length"
160
+ class="mt-1 text-xs text-app-error-200/80"
161
+ >
159
162
  {{
160
163
  t('layout.githubPatPermissionsBanner.deniedRepos', {
161
164
  repos: report.deniedRepos.join(', '),
@@ -163,7 +166,7 @@ const fineGrainedPermissions = GITHUB_PAT_FINE_GRAINED_PERMISSIONS.join(', ')
163
166
  }}
164
167
  </p>
165
168
 
166
- <p class="mt-2 text-xs text-red-200/80">{{ t(sourceKey) }}</p>
169
+ <p class="mt-2 text-xs text-app-error-200/80">{{ t(sourceKey) }}</p>
167
170
 
168
171
  <div class="mt-4">
169
172
  <UButton
@@ -185,7 +188,7 @@ const fineGrainedPermissions = GITHUB_PAT_FINE_GRAINED_PERMISSIONS.join(', ')
185
188
  no prefill at all, so its permissions are spelled out. Saying so is the point:
186
189
  a link that silently arrived with nothing selected reads as "already done for
187
190
  you", which is how the missing permission got there in the first place. -->
188
- <p class="mt-2 text-xs text-red-300/70">
191
+ <p class="mt-2 text-xs text-app-error-300/70">
189
192
  {{
190
193
  kind === 'fine_grained'
191
194
  ? t('layout.githubPatPermissionsBanner.fineGrainedHint', {
@@ -196,7 +199,10 @@ const fineGrainedPermissions = GITHUB_PAT_FINE_GRAINED_PERMISSIONS.join(', ')
196
199
  </p>
197
200
  <!-- A fine-grained verdict is a SAMPLE of the linked repositories. Declaring the
198
201
  remainder keeps a clean-looking list from reading as a guarantee. -->
199
- <p v-if="report && report.unprobedRepoCount > 0" class="mt-1 text-xs text-red-300/60">
202
+ <p
203
+ v-if="report && report.unprobedRepoCount > 0"
204
+ class="mt-1 text-xs text-app-error-300/60"
205
+ >
200
206
  {{
201
207
  t('layout.githubPatPermissionsBanner.sampled', {
202
208
  checked: report.probedRepos.length,
@@ -208,8 +208,8 @@ function dismissMenu(card: AreaCard): DropdownMenuItem[][] {
208
208
  class="pointer-events-auto w-full max-w-3xl rounded-2xl border-2 p-5 shadow-2xl backdrop-blur"
209
209
  :class="
210
210
  card.kind === 'outage'
211
- ? 'border-red-500/70 bg-red-950/95'
212
- : 'border-amber-500/70 bg-amber-950/95'
211
+ ? 'border-app-error-500/70 bg-app-error-950/95'
212
+ : 'border-app-warning-500/70 bg-app-warning-950/95'
213
213
  "
214
214
  :data-testid="`infra-setup-banner-${card.area}`"
215
215
  :data-infra-status="card.kind === 'outage' ? 'unreachable' : 'not_defined'"
@@ -218,13 +218,13 @@ function dismissMenu(card: AreaCard): DropdownMenuItem[][] {
218
218
  <UIcon
219
219
  :name="card.kind === 'outage' ? 'i-lucide-plug-zap' : AREA_META[card.area].icon"
220
220
  class="mt-0.5 h-9 w-9 shrink-0"
221
- :class="card.kind === 'outage' ? 'text-red-400' : 'text-amber-400'"
221
+ :class="card.kind === 'outage' ? 'text-app-error-400' : 'text-app-warning-400'"
222
222
  />
223
223
  <div class="min-w-0 flex-1">
224
224
  <div class="flex items-start justify-between gap-3">
225
225
  <h2
226
226
  class="text-lg font-semibold"
227
- :class="card.kind === 'outage' ? 'text-red-100' : 'text-amber-100'"
227
+ :class="card.kind === 'outage' ? 'text-app-error-100' : 'text-app-warning-100'"
228
228
  >
229
229
  {{ t(titleKey(card)) }}
230
230
  </h2>
@@ -241,7 +241,7 @@ function dismissMenu(card: AreaCard): DropdownMenuItem[][] {
241
241
  </div>
242
242
  <p
243
243
  class="mt-1 text-sm"
244
- :class="card.kind === 'outage' ? 'text-red-200/90' : 'text-amber-200/90'"
244
+ :class="card.kind === 'outage' ? 'text-app-error-200/90' : 'text-app-warning-200/90'"
245
245
  >
246
246
  {{
247
247
  card.kind === 'outage'
@@ -256,7 +256,7 @@ function dismissMenu(card: AreaCard): DropdownMenuItem[][] {
256
256
  never the only thing that explains the card. -->
257
257
  <p
258
258
  v-if="card.detail"
259
- class="mt-2 truncate font-mono text-xs text-red-300/80"
259
+ class="mt-2 truncate font-mono text-xs text-app-error-300/80"
260
260
  :title="card.detail"
261
261
  :data-testid="`infra-setup-detail-${card.area}`"
262
262
  >
@@ -377,7 +377,7 @@ const filteredGroups = computed<IntegrationGroup[]>(() => {
377
377
  <!-- Named for the same reason `model-providers-hub` is: the tutorial tour that explains
378
378
  what a connection adds to a run points at this list. -->
379
379
  <div class="space-y-5" data-testid="integrations-hub">
380
- <p class="text-xs text-slate-400">
380
+ <p class="text-xs text-muted">
381
381
  {{ t('layout.integrationsHub.intro') }}
382
382
  </p>
383
383
 
@@ -385,13 +385,13 @@ const filteredGroups = computed<IntegrationGroup[]>(() => {
385
385
  run isn't blocked on hunting for them. Hidden once anything is connected. -->
386
386
  <div
387
387
  v-if="!anyConnected && recommendedActions.length"
388
- class="rounded-lg border border-primary-500/40 bg-primary-500/10 p-3"
388
+ class="rounded-lg border border-primary/40 bg-primary/10 p-3"
389
389
  >
390
- <div class="mb-2 flex items-center gap-2 text-sm font-medium text-primary-200">
390
+ <div class="mb-2 flex items-center gap-2 text-sm font-medium text-primary">
391
391
  <UIcon name="i-lucide-rocket" class="h-4 w-4 shrink-0" />
392
392
  <span>{{ t('layout.integrationsHub.getStarted.title') }}</span>
393
393
  </div>
394
- <p class="mb-3 text-xs text-slate-300">
394
+ <p class="mb-3 text-xs text-toned">
395
395
  {{ t('layout.integrationsHub.getStarted.body') }}
396
396
  </p>
397
397
  <div class="flex flex-wrap gap-2">
@@ -417,12 +417,12 @@ const filteredGroups = computed<IntegrationGroup[]>(() => {
417
417
  class="w-full"
418
418
  />
419
419
 
420
- <p v-if="!filteredGroups.length" class="px-1 py-6 text-center text-sm text-slate-500">
420
+ <p v-if="!filteredGroups.length" class="px-1 py-6 text-center text-sm text-dimmed">
421
421
  {{ t('layout.integrationsHub.noMatches', { query }) }}
422
422
  </p>
423
423
 
424
424
  <section v-for="group in filteredGroups" :key="group.title">
425
- <h3 class="mb-2 px-1 text-[11px] font-semibold uppercase tracking-wide text-slate-400">
425
+ <h3 class="mb-2 px-1 text-[11px] font-semibold uppercase tracking-wide text-muted">
426
426
  {{ group.title }}
427
427
  </h3>
428
428
  <div class="space-y-1.5">
@@ -430,20 +430,20 @@ const filteredGroups = computed<IntegrationGroup[]>(() => {
430
430
  v-for="item in group.items"
431
431
  :key="item.key"
432
432
  type="button"
433
- class="flex w-full items-center gap-3 rounded-lg border border-slate-800 bg-slate-900/50 px-3 py-2.5 text-start transition hover:border-slate-700 hover:bg-slate-900"
433
+ class="flex w-full items-center gap-3 rounded-lg border border-default bg-default/50 px-3 py-2.5 text-start transition hover:border-muted hover:bg-default"
434
434
  @click="item.onClick()"
435
435
  >
436
- <UIcon :name="item.icon" class="h-5 w-5 shrink-0 text-slate-300" />
436
+ <UIcon :name="item.icon" class="h-5 w-5 shrink-0 text-toned" />
437
437
  <div class="min-w-0 flex-1">
438
438
  <div class="flex items-center gap-2">
439
- <span class="truncate text-sm font-medium text-slate-100">{{ item.label }}</span>
439
+ <span class="truncate text-sm font-medium text-app-100">{{ item.label }}</span>
440
440
  <UBadge v-if="item.connected" color="success" variant="subtle" size="sm">
441
441
  {{ item.status || t('layout.integrationsHub.status.connected') }}
442
442
  </UBadge>
443
443
  <UBadge v-else-if="item.attention" color="warning" variant="subtle" size="sm">
444
444
  {{ item.attentionLabel || t('layout.integrationsHub.status.needsAttention') }}
445
445
  </UBadge>
446
- <span v-else class="text-[11px] text-slate-500">{{
446
+ <span v-else class="text-[11px] text-dimmed">{{
447
447
  t('layout.integrationsHub.status.notConnected')
448
448
  }}</span>
449
449
  <UBadge
@@ -455,11 +455,11 @@ const filteredGroups = computed<IntegrationGroup[]>(() => {
455
455
  {{ t('layout.integrationsHub.status.recommended') }}
456
456
  </UBadge>
457
457
  </div>
458
- <p class="truncate text-xs text-slate-400">{{ item.description }}</p>
458
+ <p class="truncate text-xs text-muted">{{ item.description }}</p>
459
459
  </div>
460
460
  <UIcon
461
461
  name="i-lucide-chevron-right"
462
- class="h-4 w-4 shrink-0 text-slate-500 rtl:-scale-x-100"
462
+ class="h-4 w-4 shrink-0 text-dimmed rtl:-scale-x-100"
463
463
  />
464
464
  </button>
465
465
  </div>
@@ -468,17 +468,17 @@ const filteredGroups = computed<IntegrationGroup[]>(() => {
468
468
  <button
469
469
  v-if="group.footerLink"
470
470
  type="button"
471
- class="mt-1.5 flex w-full items-center gap-2 rounded-md px-3 py-1.5 text-start text-xs text-slate-400 transition hover:bg-slate-900/60 hover:text-slate-200"
471
+ class="mt-1.5 flex w-full items-center gap-2 rounded-md px-3 py-1.5 text-start text-xs text-muted transition hover:bg-default/60 hover:text-default"
472
472
  @click="group.footerLink.onClick()"
473
473
  >
474
474
  <UIcon :name="group.footerLink.icon" class="h-3.5 w-3.5 shrink-0" />
475
475
  <span class="flex-1 truncate">{{ group.footerLink.label }}</span>
476
- <span v-if="group.footerLink.status" class="shrink-0 text-slate-500">{{
476
+ <span v-if="group.footerLink.status" class="shrink-0 text-dimmed">{{
477
477
  group.footerLink.status
478
478
  }}</span>
479
479
  <UIcon
480
480
  name="i-lucide-chevron-right"
481
- class="h-3.5 w-3.5 shrink-0 text-slate-600 rtl:-scale-x-100"
481
+ class="h-3.5 w-3.5 shrink-0 text-app-600 rtl:-scale-x-100"
482
482
  />
483
483
  </button>
484
484
  </section>
@@ -45,17 +45,17 @@ const items = computed<DropdownMenuItem[][]>(() => [
45
45
  data-testid="language-switcher"
46
46
  :aria-label="t('language.switcher')"
47
47
  :title="collapsed ? `${t('language.switcher')}: ${current}` : undefined"
48
- class="flex w-full items-center gap-2 rounded-lg border border-slate-800 bg-slate-900/60 p-2 text-start transition hover:bg-slate-800/60"
48
+ 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"
49
49
  :class="collapsed ? 'justify-center' : ''"
50
50
  >
51
- <UIcon name="i-lucide-languages" class="h-4 w-4 shrink-0 text-slate-400" />
51
+ <UIcon name="i-lucide-languages" class="h-4 w-4 shrink-0 text-muted" />
52
52
  <div v-if="!collapsed" class="min-w-0 flex-1">
53
- <div class="truncate text-[10px] uppercase tracking-wide text-slate-500">
53
+ <div class="truncate text-[10px] uppercase tracking-wide text-dimmed">
54
54
  {{ t('language.switcher') }}
55
55
  </div>
56
- <div class="truncate text-xs font-medium text-white">{{ current }}</div>
56
+ <div class="truncate text-xs font-medium text-highlighted">{{ current }}</div>
57
57
  </div>
58
- <UIcon v-if="!collapsed" name="i-lucide-chevron-up" class="h-4 w-4 shrink-0 text-slate-500" />
58
+ <UIcon v-if="!collapsed" name="i-lucide-chevron-up" class="h-4 w-4 shrink-0 text-dimmed" />
59
59
  </button>
60
60
  </UDropdownMenu>
61
61
  </template>
@@ -171,21 +171,18 @@ const filteredGroups = computed<ProviderGroup[]>(() => {
171
171
  >
172
172
  <template #body>
173
173
  <div class="space-y-5" data-testid="model-providers-hub">
174
- <p class="text-xs text-slate-400">
174
+ <p class="text-xs text-muted">
175
175
  {{ t('layout.modelProvidersHub.intro') }}
176
176
  </p>
177
177
 
178
178
  <!-- Nothing connected at all is a hard stop, not a nudge: no provider means no agent
179
179
  step can run. Say so plainly rather than showing an empty list of options. -->
180
- <div
181
- v-if="!anyConnected"
182
- class="rounded-lg border border-primary-500/40 bg-primary-500/10 p-3"
183
- >
184
- <div class="mb-1.5 flex items-center gap-2 text-sm font-medium text-primary-200">
180
+ <div v-if="!anyConnected" class="rounded-lg border border-primary/40 bg-primary/10 p-3">
181
+ <div class="mb-1.5 flex items-center gap-2 text-sm font-medium text-primary">
185
182
  <UIcon name="i-lucide-rocket" class="h-4 w-4 shrink-0" />
186
183
  <span>{{ t('layout.modelProvidersHub.getStarted.title') }}</span>
187
184
  </div>
188
- <p class="text-xs text-slate-300">
185
+ <p class="text-xs text-toned">
189
186
  {{ t('layout.modelProvidersHub.getStarted.body') }}
190
187
  </p>
191
188
  </div>
@@ -198,12 +195,12 @@ const filteredGroups = computed<ProviderGroup[]>(() => {
198
195
  class="w-full"
199
196
  />
200
197
 
201
- <p v-if="!filteredGroups.length" class="px-1 py-6 text-center text-sm text-slate-500">
198
+ <p v-if="!filteredGroups.length" class="px-1 py-6 text-center text-sm text-dimmed">
202
199
  {{ t('layout.modelProvidersHub.noMatches', { query }) }}
203
200
  </p>
204
201
 
205
202
  <section v-for="group in filteredGroups" :key="group.title">
206
- <h3 class="mb-2 px-1 text-[11px] font-semibold uppercase tracking-wide text-slate-400">
203
+ <h3 class="mb-2 px-1 text-[11px] font-semibold uppercase tracking-wide text-muted">
207
204
  {{ group.title }}
208
205
  </h3>
209
206
  <div class="space-y-1.5">
@@ -211,18 +208,18 @@ const filteredGroups = computed<ProviderGroup[]>(() => {
211
208
  v-for="item in group.items"
212
209
  :key="item.key"
213
210
  type="button"
214
- class="flex w-full items-center gap-3 rounded-lg border border-slate-800 bg-slate-900/50 px-3 py-2.5 text-start transition hover:border-slate-700 hover:bg-slate-900"
211
+ class="flex w-full items-center gap-3 rounded-lg border border-default bg-default/50 px-3 py-2.5 text-start transition hover:border-muted hover:bg-default"
215
212
  :data-testid="`model-provider-${item.key}`"
216
213
  @click="item.onClick()"
217
214
  >
218
- <UIcon :name="item.icon" class="h-5 w-5 shrink-0 text-slate-300" />
215
+ <UIcon :name="item.icon" class="h-5 w-5 shrink-0 text-toned" />
219
216
  <div class="min-w-0 flex-1">
220
217
  <div class="flex items-center gap-2">
221
- <span class="truncate text-sm font-medium text-slate-100">{{ item.label }}</span>
218
+ <span class="truncate text-sm font-medium text-app-100">{{ item.label }}</span>
222
219
  <UBadge v-if="item.connected" color="success" variant="subtle" size="sm">
223
220
  {{ item.status || t('layout.modelProvidersHub.status.connected') }}
224
221
  </UBadge>
225
- <span v-else class="text-[11px] text-slate-500">{{
222
+ <span v-else class="text-[11px] text-dimmed">{{
226
223
  t('layout.modelProvidersHub.status.notConnected')
227
224
  }}</span>
228
225
  <UBadge
@@ -234,15 +231,15 @@ const filteredGroups = computed<ProviderGroup[]>(() => {
234
231
  {{ t('layout.modelProvidersHub.status.recommended') }}
235
232
  </UBadge>
236
233
  </div>
237
- <p class="truncate text-xs text-slate-400">{{ item.description }}</p>
234
+ <p class="truncate text-xs text-muted">{{ item.description }}</p>
238
235
  </div>
239
236
  <UIcon
240
237
  name="i-lucide-chevron-right"
241
- class="h-4 w-4 shrink-0 text-slate-500 rtl:-scale-x-100"
238
+ class="h-4 w-4 shrink-0 text-dimmed rtl:-scale-x-100"
242
239
  />
243
240
  </button>
244
241
  </div>
245
- <p v-if="group.note" class="mt-1.5 px-1 text-[11px] text-slate-500">{{ group.note }}</p>
242
+ <p v-if="group.note" class="mt-1.5 px-1 text-[11px] text-dimmed">{{ group.note }}</p>
246
243
  </section>
247
244
  </div>
248
245
  </template>
@@ -406,7 +406,7 @@ function revealDecision(n: Notification) {
406
406
 
407
407
  <template #content>
408
408
  <div class="max-h-[28rem] w-[min(24rem,92vw)] overflow-y-auto p-2">
409
- <div class="px-2 py-1 text-[11px] font-semibold uppercase tracking-wide text-slate-400">
409
+ <div class="px-2 py-1 text-[11px] font-semibold uppercase tracking-wide text-muted">
410
410
  {{ t('layout.notifications.heading') }}
411
411
  </div>
412
412
  <div
@@ -417,8 +417,8 @@ function revealDecision(n: Notification) {
417
417
  class="rounded-lg border p-2.5 mt-1.5"
418
418
  :class="
419
419
  isUrgent(n)
420
- ? 'border-error-500/60 bg-error-500/10'
421
- : 'border-slate-700/60 bg-slate-800/40'
420
+ ? 'border-app-error-500/60 bg-app-error-500/10'
421
+ : 'border-muted/60 bg-elevated/40'
422
422
  "
423
423
  >
424
424
  <div class="flex items-start gap-2">
@@ -429,7 +429,7 @@ function revealDecision(n: Notification) {
429
429
  <div class="min-w-0 flex-1">
430
430
  <div class="flex items-center gap-1.5">
431
431
  <button
432
- class="block min-w-0 flex-1 truncate text-start text-sm font-medium text-slate-200 hover:underline"
432
+ class="block min-w-0 flex-1 truncate text-start text-sm font-medium text-default hover:underline"
433
433
  :title="n.title"
434
434
  @click="reveal(n)"
435
435
  >
@@ -437,18 +437,18 @@ function revealDecision(n: Notification) {
437
437
  </button>
438
438
  <span
439
439
  v-if="isUrgent(n)"
440
- class="shrink-0 rounded bg-error-500/20 px-1.5 py-0.5 text-[10px] font-semibold uppercase tracking-wide text-error-400"
440
+ class="shrink-0 rounded bg-app-error-500/20 px-1.5 py-0.5 text-[10px] font-semibold uppercase tracking-wide text-app-error-400"
441
441
  >
442
442
  {{ t('layout.notifications.overdue') }}
443
443
  </span>
444
444
  </div>
445
- <p class="mt-0.5 text-[11px] leading-snug text-slate-400">{{ n.body }}</p>
445
+ <p class="mt-0.5 text-[11px] leading-snug text-muted">{{ n.body }}</p>
446
446
  <a
447
447
  v-if="n.payload?.prUrl"
448
448
  :href="n.payload.prUrl"
449
449
  target="_blank"
450
450
  rel="noopener"
451
- class="mt-1 inline-flex items-center gap-1 text-[11px] text-sky-400 hover:underline"
451
+ class="mt-1 inline-flex items-center gap-1 text-[11px] text-app-info-400 hover:underline"
452
452
  >
453
453
  <UIcon name="i-lucide-external-link" class="h-3 w-3" />
454
454
  {{ t('layout.notifications.openPr') }}
@@ -470,8 +470,8 @@ function revealDecision(n: Notification) {
470
470
  class="flex items-center gap-1 text-start text-[11px]"
471
471
  :class="
472
472
  canOpenFailingRun(run)
473
- ? 'text-sky-400 hover:underline'
474
- : 'cursor-default text-slate-500'
473
+ ? 'text-app-info-400 hover:underline'
474
+ : 'cursor-default text-dimmed'
475
475
  "
476
476
  :title="
477
477
  canOpenFailingRun(run) ? undefined : t('layout.notifications.failingRunGone')
@@ -486,7 +486,7 @@ function revealDecision(n: Notification) {
486
486
  })
487
487
  }}</span>
488
488
  </component>
489
- <span v-if="failingRunsOmitted(n) > 0" class="text-[11px] text-slate-500">
489
+ <span v-if="failingRunsOmitted(n) > 0" class="text-[11px] text-dimmed">
490
490
  {{ t('layout.notifications.failingRunsMore', { count: failingRunsOmitted(n) }) }}
491
491
  </span>
492
492
  </div>
@@ -112,12 +112,12 @@ const groups = computed<PersonalGroup[]>(() => {
112
112
  >
113
113
  <template #body>
114
114
  <div class="space-y-5">
115
- <p class="text-xs text-slate-400">
115
+ <p class="text-xs text-muted">
116
116
  {{ t('layout.personalSetup.intro') }}
117
117
  </p>
118
118
 
119
119
  <section v-for="group in groups" :key="group.title">
120
- <h3 class="mb-2 px-1 text-[11px] font-semibold uppercase tracking-wide text-slate-400">
120
+ <h3 class="mb-2 px-1 text-[11px] font-semibold uppercase tracking-wide text-muted">
121
121
  {{ group.title }}
122
122
  </h3>
123
123
  <div class="space-y-1.5">
@@ -125,25 +125,25 @@ const groups = computed<PersonalGroup[]>(() => {
125
125
  v-for="item in group.items"
126
126
  :key="item.key"
127
127
  type="button"
128
- class="flex w-full items-center gap-3 rounded-lg border border-slate-800 bg-slate-900/50 px-3 py-2.5 text-start transition hover:border-slate-700 hover:bg-slate-900"
128
+ class="flex w-full items-center gap-3 rounded-lg border border-default bg-default/50 px-3 py-2.5 text-start transition hover:border-muted hover:bg-default"
129
129
  @click="item.onClick()"
130
130
  >
131
- <UIcon :name="item.icon" class="h-5 w-5 shrink-0 text-slate-300" />
131
+ <UIcon :name="item.icon" class="h-5 w-5 shrink-0 text-toned" />
132
132
  <div class="min-w-0 flex-1">
133
133
  <div class="flex items-center gap-2">
134
- <span class="truncate text-sm font-medium text-slate-100">{{ item.label }}</span>
134
+ <span class="truncate text-sm font-medium text-app-100">{{ item.label }}</span>
135
135
  <UBadge v-if="item.connected" color="success" variant="subtle" size="sm">
136
136
  {{ item.status || t('layout.personalSetup.connected') }}
137
137
  </UBadge>
138
- <span v-else class="text-[11px] text-slate-500">
138
+ <span v-else class="text-[11px] text-dimmed">
139
139
  {{ t('layout.personalSetup.notConnected') }}
140
140
  </span>
141
141
  </div>
142
- <p class="truncate text-xs text-slate-400">{{ item.description }}</p>
142
+ <p class="truncate text-xs text-muted">{{ item.description }}</p>
143
143
  </div>
144
144
  <UIcon
145
145
  name="i-lucide-chevron-right"
146
- class="h-4 w-4 shrink-0 text-slate-500 rtl:-scale-x-100"
146
+ class="h-4 w-4 shrink-0 text-dimmed rtl:-scale-x-100"
147
147
  />
148
148
  </button>
149
149
  </div>
@@ -42,14 +42,14 @@ const show = computed(() => pending.value.length > 0 && !dismissed.value)
42
42
  renders only its card and re-enables pointer events on it. -->
43
43
  <div v-if="show" class="pointer-events-auto w-full max-w-3xl">
44
44
  <div
45
- class="w-full max-w-3xl rounded-2xl border-2 border-amber-500/70 bg-amber-950/95 p-5 shadow-2xl backdrop-blur"
45
+ 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"
46
46
  role="alert"
47
47
  >
48
48
  <div class="flex items-start gap-4">
49
- <UIcon name="i-lucide-plug" class="mt-0.5 h-9 w-9 shrink-0 text-amber-400" />
49
+ <UIcon name="i-lucide-plug" class="mt-0.5 h-9 w-9 shrink-0 text-app-warning-400" />
50
50
  <div class="min-w-0 flex-1">
51
51
  <div class="flex items-start justify-between gap-3">
52
- <h2 class="text-lg font-semibold text-amber-100">
52
+ <h2 class="text-lg font-semibold text-app-warning-100">
53
53
  {{
54
54
  pending.length > 1
55
55
  ? t('layout.providerConfigBanner.titleMany')
@@ -69,7 +69,7 @@ const show = computed(() => pending.value.length > 0 && !dismissed.value)
69
69
  "
70
70
  />
71
71
  </div>
72
- <p class="mt-1 text-sm text-amber-200/90">
72
+ <p class="mt-1 text-sm text-app-warning-200/90">
73
73
  {{ t('layout.providerConfigBanner.body') }}
74
74
  </p>
75
75
  <div class="mt-4 flex flex-wrap gap-2">
@@ -29,7 +29,7 @@ function pick(role: UiRole) {
29
29
  <UModal v-model:open="open" :title="t('uiRole.prompt.title')" :ui="{ content: 'max-w-lg' }">
30
30
  <template #body>
31
31
  <div class="space-y-4" data-testid="role-prompt">
32
- <p class="text-sm text-slate-300">{{ t('uiRole.prompt.intro') }}</p>
32
+ <p class="text-sm text-toned">{{ t('uiRole.prompt.intro') }}</p>
33
33
  <div class="space-y-2">
34
34
  <button
35
35
  v-for="role in UI_ROLES"
@@ -40,23 +40,23 @@ function pick(role: UiRole) {
40
40
  class="flex w-full items-center gap-3 rounded-lg border p-3 text-start transition"
41
41
  :class="
42
42
  role === uiRole.role && uiRole.chosen
43
- ? 'border-indigo-500/60 bg-indigo-500/10'
44
- : 'border-slate-800 bg-slate-900/60 hover:border-slate-600 hover:bg-slate-800/60'
43
+ ? 'border-primary/60 bg-primary/10'
44
+ : 'border-default bg-default/60 hover:border-app-600 hover:bg-elevated/60'
45
45
  "
46
46
  @click="pick(role)"
47
47
  >
48
- <UIcon :name="ROLE_PRESENTATION[role].icon" class="h-5 w-5 shrink-0 text-primary-400" />
48
+ <UIcon :name="ROLE_PRESENTATION[role].icon" class="h-5 w-5 shrink-0 text-primary" />
49
49
  <div class="min-w-0 flex-1">
50
- <div class="text-sm font-medium text-slate-100">
50
+ <div class="text-sm font-medium text-app-100">
51
51
  {{ t(ROLE_PRESENTATION[role].labelKey) }}
52
52
  </div>
53
- <p class="text-xs text-slate-400">{{ t(ROLE_PRESENTATION[role].hintKey) }}</p>
53
+ <p class="text-xs text-muted">{{ t(ROLE_PRESENTATION[role].hintKey) }}</p>
54
54
  </div>
55
55
  </button>
56
56
  </div>
57
57
  <!-- The choice is not a commitment, and saying so is what makes the narrowed role
58
58
  pickable: it is one dropdown at the top of the sidebar to leave again. -->
59
- <p class="text-[11px] leading-snug text-slate-500">{{ t('uiRole.prompt.change') }}</p>
59
+ <p class="text-[11px] leading-snug text-dimmed">{{ t('uiRole.prompt.change') }}</p>
60
60
  </div>
61
61
  </template>
62
62
  <template #footer>
@@ -13,6 +13,7 @@
13
13
  // independently from the role / tier switchers at the top and the rail toggle.
14
14
  import { useEventListener, useScrollLock } from '@vueuse/core'
15
15
  import BoardSwitcher from '~/components/layout/BoardSwitcher.vue'
16
+ import AppearanceSwitcher from '~/components/layout/AppearanceSwitcher.vue'
16
17
  import LanguageSwitcher from '~/components/layout/LanguageSwitcher.vue'
17
18
  import UiModeSwitcher from '~/components/layout/UiModeSwitcher.vue'
18
19
  import UiRoleSwitcher from '~/components/layout/UiRoleSwitcher.vue'
@@ -154,7 +155,7 @@ watch(
154
155
  >
155
156
  <div
156
157
  v-if="ui.mobileNavOpen"
157
- class="fixed inset-0 z-30 bg-slate-950/60 backdrop-blur-sm lg:hidden"
158
+ class="fixed inset-0 z-30 bg-app-950/60 backdrop-blur-sm lg:hidden"
158
159
  data-testid="sidebar-backdrop"
159
160
  role="button"
160
161
  tabindex="-1"
@@ -171,7 +172,7 @@ watch(
171
172
  :aria-modal="drawerOpen ? 'true' : undefined"
172
173
  :aria-label="isCompact ? t('nav.menu') : undefined"
173
174
  :inert="isCompact && !ui.mobileNavOpen"
174
- class="fixed inset-y-0 start-0 z-40 flex h-full w-64 shrink-0 flex-col gap-4 overflow-y-auto border-e border-slate-800 bg-slate-900/95 px-3 pt-3 pb-[calc(0.75rem+env(safe-area-inset-bottom))] backdrop-blur transition-transform duration-200 focus:outline-none lg:static lg:z-auto lg:translate-x-0 lg:bg-slate-900/80"
175
+ class="fixed inset-y-0 start-0 z-40 flex h-full w-64 shrink-0 flex-col gap-4 overflow-y-auto border-e border-default bg-default/95 px-3 pt-3 pb-[calc(0.75rem+env(safe-area-inset-bottom))] backdrop-blur transition-transform duration-200 focus:outline-none lg:static lg:z-auto lg:translate-x-0 lg:bg-default/80"
175
176
  :class="[
176
177
  ui.mobileNavOpen
177
178
  ? 'translate-x-0'
@@ -226,7 +227,7 @@ watch(
226
227
  and reach every action below. -->
227
228
  <button
228
229
  type="button"
229
- class="flex items-center gap-2 rounded-lg border border-slate-700 bg-slate-800/60 py-2 text-start text-sm text-slate-400 transition hover:border-slate-500 hover:bg-slate-800"
230
+ class="flex items-center gap-2 rounded-lg border border-muted bg-elevated/60 py-2 text-start text-sm text-muted transition hover:border-app-500 hover:bg-elevated"
230
231
  :class="railed ? 'justify-center px-0' : 'px-2.5'"
231
232
  :aria-label="t('nav.commandBar')"
232
233
  :title="railed ? t('nav.commandBar') : undefined"
@@ -249,7 +250,7 @@ watch(
249
250
  <section>
250
251
  <h2
251
252
  v-if="!railed"
252
- class="mb-2 px-1 text-[11px] font-semibold uppercase tracking-wide text-slate-400"
253
+ class="mb-2 px-1 text-[11px] font-semibold uppercase tracking-wide text-muted"
253
254
  >
254
255
  {{ t(section.labelKey) }}
255
256
  </h2>
@@ -278,6 +279,7 @@ watch(
278
279
  </div>
279
280
 
280
281
  <div class="mt-auto space-y-2">
282
+ <AppearanceSwitcher :collapsed="railed" />
281
283
  <LanguageSwitcher :collapsed="railed" />
282
284
  <UserMenu :collapsed="railed" />
283
285
  </div>