@cat-factory/app 0.307.1 → 0.309.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 (255) hide show
  1. package/README.md +21 -0
  2. package/app/assets/css/main.css +22 -0
  3. package/app/assets/css/prose.css +4 -4
  4. package/app/assets/css/type.css +24 -0
  5. package/app/components/assistant/AssistantModal.vue +3 -2
  6. package/app/components/auth/UserMenu.vue +1 -1
  7. package/app/components/binaryCandidates/BinaryCandidatesWindow.vue +15 -15
  8. package/app/components/binaryOutput/BinaryOutputReport.vue +10 -14
  9. package/app/components/binaryOutput/StoredAssetView.vue +5 -5
  10. package/app/components/board/AddTaskModal.vue +16 -14
  11. package/app/components/board/AgentFailureCard.vue +9 -9
  12. package/app/components/board/AgentFailureHistory.vue +1 -1
  13. package/app/components/board/CreateInitiativeModal.vue +2 -2
  14. package/app/components/board/FailureDetail.vue +1 -1
  15. package/app/components/board/FailureHistoryList.vue +5 -5
  16. package/app/components/board/RecurringPipelineModal.vue +12 -11
  17. package/app/components/board/ReviewFrictionDialog.vue +4 -3
  18. package/app/components/board/StepExecutionHistory.vue +8 -8
  19. package/app/components/board/nodes/AgentChip.vue +1 -1
  20. package/app/components/board/nodes/BlockNode.vue +8 -9
  21. package/app/components/board/nodes/EpicNode.vue +4 -4
  22. package/app/components/board/nodes/FrameSwimlanes.vue +4 -7
  23. package/app/components/board/nodes/InitiativeCard.vue +4 -4
  24. package/app/components/board/nodes/LaneGroup.vue +3 -5
  25. package/app/components/board/nodes/TaskCard.vue +8 -8
  26. package/app/components/board/nodes/TaskLane.vue +3 -3
  27. package/app/components/board/nodes/TaskPipelineMini.vue +13 -12
  28. package/app/components/bootstrap/AdoptionReviewModal.vue +7 -6
  29. package/app/components/bootstrap/BootstrapModal.vue +11 -10
  30. package/app/components/bootstrap/BootstrapRunSteps.vue +1 -1
  31. package/app/components/brainstorm/BrainstormWindow.vue +8 -7
  32. package/app/components/bugFishing/BugFishingWindow.vue +37 -36
  33. package/app/components/clarity/ClarityReviewWindow.vue +8 -7
  34. package/app/components/common/AsyncViewError.vue +1 -1
  35. package/app/components/common/ClarificationItem.vue +6 -6
  36. package/app/components/common/DescriptorFields.vue +1 -1
  37. package/app/components/common/EmptyState.vue +1 -1
  38. package/app/components/common/InterviewGateNotice.vue +4 -4
  39. package/app/components/common/MarkdownProse.vue +8 -2
  40. package/app/components/common/SectionLabel.vue +38 -0
  41. package/app/components/consensus/ConsensusSessionWindow.vue +10 -9
  42. package/app/components/context/ContextAttachmentFields.vue +9 -8
  43. package/app/components/docs/DocInterviewWindow.vue +10 -9
  44. package/app/components/documents/ContextDocumentPicker.vue +10 -12
  45. package/app/components/documents/DocumentImportModal.vue +3 -2
  46. package/app/components/documents/DocumentSourceConnectModal.vue +2 -2
  47. package/app/components/documents/DocumentSyncState.vue +1 -1
  48. package/app/components/documents/DocumentTemplatesModal.vue +5 -4
  49. package/app/components/documents/RepoContextDocPicker.vue +3 -6
  50. package/app/components/documents/StartFromDesignModal.vue +4 -4
  51. package/app/components/documents/TaskContextDocs.vue +1 -1
  52. package/app/components/environments/EnvSetupStepper.vue +3 -3
  53. package/app/components/environments/EnvironmentStatusPanel.vue +11 -10
  54. package/app/components/environments/steps/EnvPreflightStep.vue +8 -8
  55. package/app/components/environments/steps/EnvReviewStep.vue +23 -22
  56. package/app/components/environments/steps/EnvSaveStep.vue +5 -5
  57. package/app/components/focus/BlockFocusView.vue +11 -10
  58. package/app/components/followUp/FollowUpWindow.vue +10 -10
  59. package/app/components/forkDecision/ForkDecisionWindow.vue +23 -26
  60. package/app/components/foundational/FoundationalContractSummary.vue +2 -2
  61. package/app/components/foundational/FoundationalServiceCatalogList.vue +3 -3
  62. package/app/components/foundational/FoundationalServiceRegistry.vue +3 -3
  63. package/app/components/foundational/FoundationalSuppressions.vue +2 -2
  64. package/app/components/fragments/FragmentLibraryManager.vue +3 -3
  65. package/app/components/fragments/FragmentSelector.vue +10 -11
  66. package/app/components/gates/GateFailingCheckList.vue +3 -3
  67. package/app/components/gates/GateResultView.vue +39 -38
  68. package/app/components/github/AddServiceFromRepoModal.vue +5 -4
  69. package/app/components/github/BranchProtectionPreflight.vue +5 -5
  70. package/app/components/github/GitHubConnect.vue +5 -3
  71. package/app/components/github/GitHubPanel.vue +14 -13
  72. package/app/components/github/RepoTreeBrowser.vue +1 -1
  73. package/app/components/humanTest/HumanTestWindow.vue +18 -17
  74. package/app/components/initiative/InitiativePlanNotice.vue +3 -3
  75. package/app/components/initiative/InitiativePlanReview.vue +19 -21
  76. package/app/components/initiative/InitiativePlanningWindow.vue +5 -5
  77. package/app/components/initiative/InitiativeTrackerWindow.vue +54 -53
  78. package/app/components/judge/JudgeResultView.vue +24 -25
  79. package/app/components/kaizen/KaizenPanel.vue +4 -4
  80. package/app/components/kaizen/KaizenStepStatus.vue +7 -6
  81. package/app/components/layout/AccountAuditLog.vue +1 -1
  82. package/app/components/layout/AccountDeploymentSettings.vue +10 -10
  83. package/app/components/layout/AccountFailureKindRules.vue +13 -13
  84. package/app/components/layout/AccountFoundationalSettings.vue +1 -1
  85. package/app/components/layout/AccountFragmentSettings.vue +1 -1
  86. package/app/components/layout/AccountModelPolicySettings.vue +7 -7
  87. package/app/components/layout/AccountPlatformAlertSettings.vue +8 -8
  88. package/app/components/layout/AccountRiskPolicySettings.vue +2 -2
  89. package/app/components/layout/AccountRunCredentialSettings.vue +3 -3
  90. package/app/components/layout/AccountSkillSettings.vue +1 -1
  91. package/app/components/layout/AccountTeamSettings.vue +4 -0
  92. package/app/components/layout/AiProvidersBanner.vue +1 -1
  93. package/app/components/layout/AppearanceSwitcher.vue +1 -1
  94. package/app/components/layout/BoardSwitcher.vue +3 -2
  95. package/app/components/layout/BoardToolbar.vue +6 -2
  96. package/app/components/layout/CommandBar.vue +4 -2
  97. package/app/components/layout/DefaultTestEnvBanner.vue +2 -2
  98. package/app/components/layout/IntegrationsHub.vue +4 -3
  99. package/app/components/layout/LanguageSwitcher.vue +1 -1
  100. package/app/components/layout/ModelProvidersHub.vue +6 -4
  101. package/app/components/layout/NotificationsInbox.vue +8 -7
  102. package/app/components/layout/PersonalSetupModal.vue +5 -3
  103. package/app/components/layout/RolePrompt.vue +1 -1
  104. package/app/components/layout/SideBar.vue +3 -5
  105. package/app/components/layout/SpendWarningBanner.vue +3 -3
  106. package/app/components/layout/TranslationWarningBanner.vue +1 -1
  107. package/app/components/layout/UiModeSwitcher.vue +7 -6
  108. package/app/components/layout/UiRoleSwitcher.vue +2 -2
  109. package/app/components/media/ArtifactLightbox.vue +6 -6
  110. package/app/components/media/ImageCompare.vue +16 -16
  111. package/app/components/merge/MergeEffortChips.vue +4 -6
  112. package/app/components/notifications/NotificationSettingsPanel.vue +6 -5
  113. package/app/components/observability/OutcomeFilterChips.vue +1 -1
  114. package/app/components/observability/RunFailureSummary.vue +14 -17
  115. package/app/components/observability/StepMetricsBar.vue +9 -8
  116. package/app/components/observability/StepModelActivity.vue +4 -3
  117. package/app/components/observability/ToolCallList.vue +15 -18
  118. package/app/components/outcome/OutcomeSummaryWindow.vue +43 -42
  119. package/app/components/palettes/AgentPalette.vue +7 -5
  120. package/app/components/palettes/AgentTierSelect.vue +1 -1
  121. package/app/components/palettes/PipelinePurposeSelect.vue +2 -1
  122. package/app/components/panels/AgentStepDetail.vue +27 -30
  123. package/app/components/panels/AttemptEntryHeader.vue +2 -2
  124. package/app/components/panels/DecisionModal.vue +1 -1
  125. package/app/components/panels/GenericStructuredResultView.vue +6 -5
  126. package/app/components/panels/InspectorPanel.vue +15 -13
  127. package/app/components/panels/MergerResultView.vue +10 -9
  128. package/app/components/panels/ObservabilityPanel.vue +66 -76
  129. package/app/components/panels/OperatorDashboardPanel.vue +27 -26
  130. package/app/components/panels/ReportsPanel.vue +26 -25
  131. package/app/components/panels/ReportsSpendBreakdown.vue +2 -2
  132. package/app/components/panels/ResultWindowShell.vue +19 -18
  133. package/app/components/panels/RunDetailLoadState.vue +1 -1
  134. package/app/components/panels/StepContainerStatus.vue +8 -7
  135. package/app/components/panels/StepDelegatedStatus.vue +13 -12
  136. package/app/components/panels/StepEffortReport.vue +12 -17
  137. package/app/components/panels/StepFragmentAdherence.vue +9 -10
  138. package/app/components/panels/StepMetadataCard.vue +41 -43
  139. package/app/components/panels/StepReproductionReport.vue +18 -20
  140. package/app/components/panels/StepRunMeta.vue +27 -26
  141. package/app/components/panels/StepTestReport.vue +16 -15
  142. package/app/components/panels/StepToolServers.vue +7 -8
  143. package/app/components/panels/StepValidationReport.vue +5 -5
  144. package/app/components/panels/inspector/ContainerSummary.vue +4 -4
  145. package/app/components/panels/inspector/DocReferenceRepos.vue +5 -4
  146. package/app/components/panels/inspector/EnvProbeReport.vue +16 -13
  147. package/app/components/panels/inspector/EpicChildren.vue +8 -7
  148. package/app/components/panels/inspector/FrontendBindingsResolved.vue +5 -4
  149. package/app/components/panels/inspector/FrontendConfig.vue +26 -34
  150. package/app/components/panels/inspector/InitiativeInspector.vue +3 -3
  151. package/app/components/panels/inspector/InspectorSection.vue +7 -4
  152. package/app/components/panels/inspector/RecurringScheduleSettings.vue +9 -8
  153. package/app/components/panels/inspector/ServiceConnections.vue +2 -2
  154. package/app/components/panels/inspector/ServiceReleaseHealthConfig.vue +2 -2
  155. package/app/components/panels/inspector/ServiceSelfTests.vue +9 -13
  156. package/app/components/panels/inspector/ServiceTestConfig.vue +41 -45
  157. package/app/components/panels/inspector/ServiceTestSecrets.vue +3 -3
  158. package/app/components/panels/inspector/ServiceTestingContext.vue +2 -2
  159. package/app/components/panels/inspector/ServiceValidationConfig.vue +2 -2
  160. package/app/components/panels/inspector/TaskAgentConfig.vue +2 -2
  161. package/app/components/panels/inspector/TaskAprioriBranches.vue +6 -5
  162. package/app/components/panels/inspector/TaskDependencies.vue +1 -1
  163. package/app/components/panels/inspector/TaskEstimateBadge.vue +3 -7
  164. package/app/components/panels/inspector/TaskExecution.vue +13 -12
  165. package/app/components/panels/inspector/TaskRunSettings.vue +35 -38
  166. package/app/components/panels/inspector/TaskStructure.vue +5 -4
  167. package/app/components/pipeline/AgentPromptEditor.vue +15 -14
  168. package/app/components/pipeline/BinaryOutputStepPicker.vue +42 -52
  169. package/app/components/pipeline/EstimateThresholdFields.vue +2 -2
  170. package/app/components/pipeline/GateConfigFields.vue +6 -6
  171. package/app/components/pipeline/IterationCapPrompt.vue +1 -1
  172. package/app/components/pipeline/PipelineBuilder.vue +28 -27
  173. package/app/components/pipeline/PipelineHealthModal.vue +7 -7
  174. package/app/components/pipeline/PipelinePicker.vue +3 -3
  175. package/app/components/pipeline/PipelinePreview.vue +6 -7
  176. package/app/components/pipeline/PipelineProgress.vue +23 -24
  177. package/app/components/prReview/PrReviewWindow.vue +42 -41
  178. package/app/components/providers/AiPresetMismatchDialog.vue +4 -3
  179. package/app/components/providers/AiProviderOnboardingModal.vue +2 -2
  180. package/app/components/providers/ApiKeysSection.vue +7 -6
  181. package/app/components/providers/PersonalSubscriptionSection.vue +4 -3
  182. package/app/components/providers/VendorCredentialsModal.vue +5 -4
  183. package/app/components/provisioning/ProvisioningLogsDrawer.vue +10 -9
  184. package/app/components/ralph/RalphLoopResultView.vue +25 -26
  185. package/app/components/requirements/RequirementsReviewWindow.vue +13 -12
  186. package/app/components/riskPolicy/RiskPolicyPicker.vue +5 -5
  187. package/app/components/riskPolicy/RiskPolicyPreview.vue +16 -15
  188. package/app/components/sandbox/SandboxPanel.vue +21 -20
  189. package/app/components/settings/ApiTokensPanel.vue +1 -1
  190. package/app/components/settings/BudgetSettings.vue +18 -17
  191. package/app/components/settings/CapabilityCredentialsPanel.vue +5 -5
  192. package/app/components/settings/CloudflareHandlerSection.vue +16 -16
  193. package/app/components/settings/ComposeEnvironmentSetupSection.vue +14 -12
  194. package/app/components/settings/ConnectionTestVerdict.vue +1 -1
  195. package/app/components/settings/ConsensusGroupsSection.vue +21 -20
  196. package/app/components/settings/CustomManifestTypeEditor.vue +8 -7
  197. package/app/components/settings/DefaultProvisionTypeSection.vue +5 -5
  198. package/app/components/settings/InfraHandlersConfigurator.vue +14 -15
  199. package/app/components/settings/InfrastructureBackendPicker.vue +2 -2
  200. package/app/components/settings/IssueTrackerPanel.vue +9 -15
  201. package/app/components/settings/KubernetesEngineForm.vue +9 -8
  202. package/app/components/settings/KubernetesEnvironmentForm.vue +4 -3
  203. package/app/components/settings/LocalContainerPoolSettings.vue +2 -2
  204. package/app/components/settings/LocalModelEndpointsPanel.vue +10 -9
  205. package/app/components/settings/MergeClassRulesEditor.vue +6 -5
  206. package/app/components/settings/MergeRolePolicyEditor.vue +13 -12
  207. package/app/components/settings/ModelConfigurationPanel.vue +8 -11
  208. package/app/components/settings/ModelPresetHealthModal.vue +3 -3
  209. package/app/components/settings/ObservabilityConnectionPanel.vue +1 -1
  210. package/app/components/settings/OpenRouterCatalogPanel.vue +6 -5
  211. package/app/components/settings/PackageRegistriesPanel.vue +4 -4
  212. package/app/components/settings/ProviderConnectionTab.vue +5 -4
  213. package/app/components/settings/ProviderManifestEditor.vue +9 -8
  214. package/app/components/settings/ProviderPreferenceEditor.vue +8 -7
  215. package/app/components/settings/RiskPolicyCreateForm.vue +40 -26
  216. package/app/components/settings/RiskPolicyEditorRow.vue +18 -17
  217. package/app/components/settings/RiskPolicyHealthModal.vue +3 -3
  218. package/app/components/settings/RiskPolicyPanel.vue +11 -13
  219. package/app/components/settings/ServiceFragmentDefaultsPanel.vue +5 -4
  220. package/app/components/settings/SharedStacksPanel.vue +5 -5
  221. package/app/components/settings/TaskSourceCard.vue +2 -2
  222. package/app/components/settings/TaskTypeSuppressionsPanel.vue +4 -4
  223. package/app/components/settings/ToolServerChecklist.vue +22 -22
  224. package/app/components/settings/UsageSettings.vue +13 -13
  225. package/app/components/settings/UserSecretsSection.vue +4 -3
  226. package/app/components/settings/WorkspaceMetadataSettings.vue +6 -5
  227. package/app/components/settings/WorkspaceSettingsPanel.vue +72 -58
  228. package/app/components/skills/ReviewSkillQueue.vue +8 -7
  229. package/app/components/skills/SkillLibraryManager.vue +2 -2
  230. package/app/components/slack/SlackPanel.vue +8 -7
  231. package/app/components/spec/ServiceSpecWindow.vue +15 -16
  232. package/app/components/tasks/BugHuntModal.vue +1 -1
  233. package/app/components/tasks/ContextIssuePicker.vue +4 -6
  234. package/app/components/tasks/TaskContextIssues.vue +1 -1
  235. package/app/components/tasks/TaskImportModal.vue +3 -2
  236. package/app/components/tasks/TaskSourceConnectModal.vue +5 -5
  237. package/app/components/testing/TestReportWindow.vue +54 -53
  238. package/app/components/tutorial/TutorialNudge.vue +3 -2
  239. package/app/components/tutorial/TutorialOverlay.vue +3 -2
  240. package/app/components/vcs/GitLabConnect.vue +1 -1
  241. package/app/components/visualConfirm/VisualConfirmationWindow.vue +23 -25
  242. package/app/composables/usePipelineErrorToast.ts +2 -0
  243. package/app/utils/catalog.ts +8 -0
  244. package/app/utils/theme/builtins.ts +7 -1
  245. package/i18n/locales/de.json +6 -3
  246. package/i18n/locales/en.json +6 -3
  247. package/i18n/locales/es.json +6 -3
  248. package/i18n/locales/fr.json +6 -3
  249. package/i18n/locales/he.json +6 -3
  250. package/i18n/locales/it.json +6 -3
  251. package/i18n/locales/ja.json +6 -3
  252. package/i18n/locales/pl.json +6 -3
  253. package/i18n/locales/tr.json +6 -3
  254. package/i18n/locales/uk.json +6 -3
  255. package/package.json +2 -2
@@ -12,6 +12,7 @@ import CopyButton from '~/components/common/CopyButton.vue'
12
12
  import MarkdownProse from '~/components/common/MarkdownProse.vue'
13
13
  import ResultWindowShell from '~/components/panels/ResultWindowShell.vue'
14
14
  import { agentKindMeta } from '~/utils/catalog'
15
+ import SectionLabel from '~/components/common/SectionLabel.vue'
15
16
 
16
17
  const { t, n } = useI18n()
17
18
 
@@ -165,12 +166,12 @@ function topScore(c: ConsensusContribution): { label: string; value: number } |
165
166
  <!-- synthesized result -->
166
167
  <section v-if="session.synthesis" class="mb-6">
167
168
  <div class="mb-2 flex items-center gap-2">
168
- <h3 class="text-xs font-semibold uppercase tracking-wide text-muted">
169
+ <SectionLabel as="h3">
169
170
  {{ t('consensus.synthesizedResult') }}
170
- </h3>
171
+ </SectionLabel>
171
172
  <span
172
173
  v-if="session.confidence != null"
173
- class="rounded bg-app-success-500/15 px-1.5 py-0.5 text-xs text-app-success-300"
174
+ class="rounded-sm bg-app-success-500/15 px-1.5 py-0.5 text-xs text-app-success-300"
174
175
  >{{ t('consensus.confidence', { pct: pct(session.confidence) }) }}</span
175
176
  >
176
177
  <CopyButton :text="session.synthesis" class="ms-auto -my-1" />
@@ -193,9 +194,9 @@ function topScore(c: ConsensusContribution): { label: string; value: number } |
193
194
 
194
195
  <!-- participants -->
195
196
  <section class="mb-6">
196
- <h3 class="mb-2 text-xs font-semibold uppercase tracking-wide text-muted">
197
+ <SectionLabel as="h3" class="mb-2">
197
198
  {{ t('consensus.panel') }}
198
- </h3>
199
+ </SectionLabel>
199
200
  <div class="flex flex-wrap gap-2">
200
201
  <div
201
202
  v-for="(p, i) in session.participants"
@@ -215,10 +216,10 @@ function topScore(c: ConsensusContribution): { label: string; value: number } |
215
216
 
216
217
  <!-- rounds -->
217
218
  <section v-for="round in session.rounds" :key="round.index" class="mb-5">
218
- <h3 class="mb-2 text-xs font-semibold uppercase tracking-wide text-muted">
219
+ <SectionLabel as="h3" class="mb-2">
219
220
  {{ t('consensus.round.heading', { n: round.index + 1 }) }} ·
220
221
  {{ roundLabel(round.kind) }}
221
- </h3>
222
+ </SectionLabel>
222
223
  <div class="space-y-3">
223
224
  <div
224
225
  v-for="c in round.contributions"
@@ -232,7 +233,7 @@ function topScore(c: ConsensusContribution): { label: string; value: number } |
232
233
  <span class="text-xs text-dimmed">{{ roleFor(c.participantId) }}</span>
233
234
  <span
234
235
  v-if="topScore(c)"
235
- class="ms-auto rounded bg-elevated px-1.5 py-0.5 text-xs text-toned"
236
+ class="ms-auto rounded-sm bg-elevated px-1.5 py-0.5 text-xs text-toned"
236
237
  >{{
237
238
  t('consensus.topScore', {
238
239
  label: topScore(c)!.label,
@@ -247,7 +248,7 @@ function topScore(c: ConsensusContribution): { label: string; value: number } |
247
248
  <span
248
249
  v-for="s in c.scores"
249
250
  :key="s.dimension"
250
- class="rounded bg-elevated/80 px-1.5 py-0.5 text-xs text-muted"
251
+ class="rounded-sm bg-elevated/80 px-1.5 py-0.5 text-xs text-muted"
251
252
  >{{ s.dimension }}: {{ pct(s.value) }}</span
252
253
  >
253
254
  </div>
@@ -21,6 +21,7 @@ import { claimCandidates, firstLinkCandidate } from '~/components/context/pasted
21
21
  import { connectableSources } from '~/utils/sourcePicker'
22
22
  import ContextDocumentPicker from '~/components/documents/ContextDocumentPicker.vue'
23
23
  import ContextIssuePicker from '~/components/tasks/ContextIssuePicker.vue'
24
+ import SectionLabel from '~/components/common/SectionLabel.vue'
24
25
 
25
26
  const props = defineProps<{
26
27
  /** The staged attachments; the host owns the array and commits it after creating the block. */
@@ -188,9 +189,9 @@ function removePending(item: PendingContext) {
188
189
  <!-- Context documents (ungated; Attach disabled until a source is connected). -->
189
190
  <div class="space-y-2">
190
191
  <div class="flex items-center justify-between">
191
- <span class="text-[11px] font-semibold uppercase tracking-wide text-muted">
192
+ <SectionLabel as="span">
192
193
  {{ t('contextAttachments.documents') }}
193
- </span>
194
+ </SectionLabel>
194
195
  <UButton
195
196
  v-if="docsConnected"
196
197
  color="neutral"
@@ -298,14 +299,14 @@ function removePending(item: PendingContext) {
298
299
  </div>
299
300
  <p
300
301
  v-if="item.unreadable"
301
- class="px-2 pb-1.5 text-[11px] text-app-warning-400"
302
+ class="px-2 pb-1.5 text-2xs text-app-warning-400"
302
303
  data-testid="context-item-unreadable"
303
304
  >
304
305
  {{ t('contextAttachments.unreadable', { error: item.unreadable }) }}
305
306
  </p>
306
307
  </div>
307
308
  </div>
308
- <p v-else class="text-[11px] text-dimmed">
309
+ <p v-else class="text-2xs text-dimmed">
309
310
  {{ docsHint }}
310
311
  </p>
311
312
  </div>
@@ -313,9 +314,9 @@ function removePending(item: PendingContext) {
313
314
  <!-- Context issues (ungated; Attach disabled until a tracker is connected). -->
314
315
  <div class="space-y-2">
315
316
  <div class="flex items-center justify-between">
316
- <span class="text-[11px] font-semibold uppercase tracking-wide text-muted">
317
+ <SectionLabel as="span">
317
318
  {{ t('contextAttachments.issues') }}
318
- </span>
319
+ </SectionLabel>
319
320
  <UButton
320
321
  v-if="issuesConnected"
321
322
  color="neutral"
@@ -409,14 +410,14 @@ function removePending(item: PendingContext) {
409
410
  again on submit, and a failure now blocks the create. -->
410
411
  <p
411
412
  v-if="item.unreadable"
412
- class="px-2 pb-1.5 text-[11px] text-app-warning-400"
413
+ class="px-2 pb-1.5 text-2xs text-app-warning-400"
413
414
  data-testid="context-item-unreadable"
414
415
  >
415
416
  {{ t('contextAttachments.unreadable', { error: item.unreadable }) }}
416
417
  </p>
417
418
  </div>
418
419
  </div>
419
- <p v-else class="text-[11px] text-dimmed">
420
+ <p v-else class="text-2xs text-dimmed">
420
421
  {{ issuesHint }}
421
422
  </p>
422
423
  </div>
@@ -24,6 +24,7 @@ import {
24
24
  interviewGatePhase,
25
25
  interviewStepReached,
26
26
  } from '~/utils/interviewGate'
27
+ import SectionLabel from '~/components/common/SectionLabel.vue'
27
28
 
28
29
  const board = useBoardStore()
29
30
  const docInterview = useDocInterviewStore()
@@ -131,7 +132,7 @@ const onProceed = () =>
131
132
  </div>
132
133
 
133
134
  <template v-else>
134
- <p class="mb-4 text-[13px] leading-relaxed text-toned">
135
+ <p class="mb-4 text-sm leading-relaxed text-toned">
135
136
  {{ t('docInterview.intro') }}
136
137
  </p>
137
138
 
@@ -171,20 +172,20 @@ const onProceed = () =>
171
172
  class="rounded-lg border border-default bg-app-950/40 p-4"
172
173
  data-testid="doc-interview-converged"
173
174
  >
174
- <p class="mb-2 text-[11px] font-medium uppercase tracking-wide text-dimmed">
175
+ <SectionLabel as="p" class="mb-2">
175
176
  {{ t('docInterview.brief') }}
176
- </p>
177
+ </SectionLabel>
177
178
  <pre
178
179
  v-if="session.brief"
179
- class="whitespace-pre-wrap break-words text-[13px] leading-relaxed text-toned"
180
+ class="whitespace-pre-wrap break-words text-sm leading-relaxed text-toned"
180
181
  >{{ session.brief }}</pre>
181
- <p v-else class="text-[13px] text-muted">{{ t('docInterview.converged') }}</p>
182
+ <p v-else class="text-sm text-muted">{{ t('docInterview.converged') }}</p>
182
183
  </div>
183
184
 
184
185
  <!-- No pending questions but not yet converged -->
185
186
  <div
186
187
  v-else-if="questions.length === 0"
187
- class="rounded-lg border border-default bg-app-950/40 p-4 text-center text-[13px] text-muted"
188
+ class="rounded-lg border border-default bg-app-950/40 p-4 text-center text-sm text-muted"
188
189
  >
189
190
  {{ t('docInterview.converged') }}
190
191
  </div>
@@ -197,7 +198,7 @@ const onProceed = () =>
197
198
  class="rounded-lg border border-default bg-app-950/40 p-3"
198
199
  data-testid="doc-interview-question"
199
200
  >
200
- <p class="mb-2 text-[13px] font-medium text-default">{{ q.question }}</p>
201
+ <p class="mb-2 text-sm font-medium text-default">{{ q.question }}</p>
201
202
  <UTextarea
202
203
  v-model="drafts[q.key]"
203
204
  :rows="2"
@@ -212,7 +213,7 @@ const onProceed = () =>
212
213
  for an answer to go. Saying so beats taking text the flush could only drop. -->
213
214
  <p
214
215
  v-if="!addressable(q)"
215
- class="mt-1 text-[11px] text-app-warning-300"
216
+ class="mt-1 text-2xs text-app-warning-300"
216
217
  data-testid="doc-interview-unanswerable"
217
218
  >
218
219
  {{ t('docInterview.unanswerable') }}
@@ -228,7 +229,7 @@ const onProceed = () =>
228
229
  v-if="session && phase === 'awaiting' && questions.length > 0"
229
230
  class="flex items-center justify-between gap-3 border-t border-default px-5 py-3"
230
231
  >
231
- <p class="text-[11px] text-dimmed">
232
+ <p class="text-2xs text-dimmed">
232
233
  <span
233
234
  v-if="unanswered > 0"
234
235
  class="text-app-warning-400/90"
@@ -49,6 +49,7 @@ import {
49
49
  reconcileSource,
50
50
  sourceMenuItems,
51
51
  } from '~/utils/sourcePicker'
52
+ import SectionLabel from '~/components/common/SectionLabel.vue'
52
53
 
53
54
  // Repo-backed document sources pick a FILE out of a repository (repo search → file
54
55
  // search / tree browse) instead of the generic free-text catalogue search. Today only
@@ -420,12 +421,9 @@ onMounted(() => {
420
421
  here (each opens the connect modal over the caller's form). Rendered as plain text when
421
422
  there is nothing to decide, which for a member is the usual case. -->
422
423
  <div class="flex items-center gap-1.5">
423
- <span
424
- :id="sourceLabelId"
425
- class="shrink-0 text-[11px] font-semibold uppercase tracking-wide text-dimmed"
426
- >
424
+ <SectionLabel as="span" :id="sourceLabelId" class="shrink-0">
427
425
  {{ t('documents.picker.sourceLabel') }}
428
- </span>
426
+ </SectionLabel>
429
427
  <UDropdownMenu
430
428
  v-if="sourcePickable"
431
429
  :items="sourceMenu"
@@ -490,7 +488,7 @@ onMounted(() => {
490
488
  @keydown.enter="refRow && pickRef(refRow)"
491
489
  />
492
490
 
493
- <p v-if="searchError" class="px-1 text-[11px] text-app-warning-400">
491
+ <p v-if="searchError" class="px-1 text-2xs text-app-warning-400">
494
492
  {{ t('documents.picker.searchFailed', { error: searchError }) }}
495
493
  </p>
496
494
 
@@ -498,14 +496,14 @@ onMounted(() => {
498
496
  the user can still edit, rather than as a toast after the task is created. -->
499
497
  <p
500
498
  v-if="refState.status === 'checking'"
501
- class="px-1 text-[11px] text-dimmed"
499
+ class="px-1 text-2xs text-dimmed"
502
500
  data-testid="doc-ref-checking"
503
501
  >
504
502
  {{ t('documents.picker.refChecking') }}
505
503
  </p>
506
504
  <div
507
505
  v-else-if="refRejection"
508
- class="flex flex-wrap items-center gap-x-2 gap-y-1 px-1 text-[11px] text-app-warning-400"
506
+ class="flex flex-wrap items-center gap-x-2 gap-y-1 px-1 text-2xs text-app-warning-400"
509
507
  data-testid="doc-ref-rejected"
510
508
  >
511
509
  <span>{{ refRejection }}</span>
@@ -523,7 +521,7 @@ onMounted(() => {
523
521
  </div>
524
522
  <p
525
523
  v-else-if="refState.status === 'unchecked'"
526
- class="px-1 text-[11px] text-app-warning-400"
524
+ class="px-1 text-2xs text-app-warning-400"
527
525
  data-testid="doc-ref-unchecked"
528
526
  >
529
527
  {{ t('documents.picker.refCheckFailed', { error: refState.message }) }}
@@ -532,7 +530,7 @@ onMounted(() => {
532
530
  at all reads as a picker that dropped it. -->
533
531
  <p
534
532
  v-else-if="refAlreadyAttached"
535
- class="px-1 text-[11px] text-dimmed"
533
+ class="px-1 text-2xs text-dimmed"
536
534
  data-testid="doc-ref-already-attached"
537
535
  >
538
536
  {{ t('documents.picker.refAlreadyAttached') }}
@@ -585,7 +583,7 @@ onMounted(() => {
585
583
  </template>
586
584
  </i18n-t>
587
585
  </span>
588
- <span v-if="refRow.trimmed" class="block truncate text-[11px] text-dimmed">
586
+ <span v-if="refRow.trimmed" class="block truncate text-2xs text-dimmed">
589
587
  {{ t('documents.picker.refTrimmed') }}
590
588
  </span>
591
589
  <!-- A WIDENED reference, which the trim note above must never be left to imply: the
@@ -593,7 +591,7 @@ onMounted(() => {
593
591
  around it. Amber and separate, because it is a loss rather than tidying. -->
594
592
  <span
595
593
  v-if="refRow.droppedScope"
596
- class="block text-[11px] text-app-warning-400"
594
+ class="block text-2xs text-app-warning-400"
597
595
  data-testid="doc-ref-widened"
598
596
  >
599
597
  {{ t('documents.picker.refWidened', { scope: refRow.droppedScope }) }}
@@ -2,6 +2,7 @@
2
2
  import type { DocumentSourceKind } from '~/types/domain'
3
3
  import DocumentSyncState from '~/components/documents/DocumentSyncState.vue'
4
4
  import IntegrationBackTitle from '~/components/layout/IntegrationBackTitle.vue'
5
+ import SectionLabel from '~/components/common/SectionLabel.vue'
5
6
 
6
7
  // Import pages from a connected document source and pick one to expand into
7
8
  // board structure. A source selector lets the user choose which connected source
@@ -125,9 +126,9 @@ function preview(externalId: string) {
125
126
  </div>
126
127
 
127
128
  <div v-if="sourceDocs.length" class="space-y-2">
128
- <h3 class="text-[11px] font-semibold uppercase tracking-wide text-muted">
129
+ <SectionLabel as="h3">
129
130
  {{ t('documents.import.importedHeading') }}
130
- </h3>
131
+ </SectionLabel>
131
132
  <div
132
133
  v-for="doc in sourceDocs"
133
134
  :key="`${doc.source}:${doc.externalId}`"
@@ -132,10 +132,10 @@ async function disconnect() {
132
132
  >
133
133
  {{ t('documents.connect.oauth.action', { source: descriptor.label }) }}
134
134
  </UButton>
135
- <p class="text-[11px] text-dimmed">
135
+ <p class="text-2xs text-dimmed">
136
136
  {{ t('documents.connect.oauth.scopes', { scopes: oauth.scopes.join(', ') }) }}
137
137
  </p>
138
- <p class="text-[11px] text-dimmed">{{ t('documents.connect.oauth.fallback') }}</p>
138
+ <p class="text-2xs text-dimmed">{{ t('documents.connect.oauth.fallback') }}</p>
139
139
  </div>
140
140
 
141
141
  <div class="space-y-3">
@@ -165,7 +165,7 @@ async function refresh() {
165
165
  </script>
166
166
 
167
167
  <template>
168
- <div class="flex items-center gap-1.5 text-[11px] text-dimmed">
168
+ <div class="flex items-center gap-1.5 text-2xs text-dimmed">
169
169
  <span class="truncate">
170
170
  {{ t('documents.freshness.updated', { when: d(new Date(props.doc.syncedAt), 'long') }) }}
171
171
  </span>
@@ -3,6 +3,7 @@ import { DOC_KINDS } from '~/types/domain'
3
3
  import type { DocKind, DocumentLinkRole, SourceDocument } from '~/types/domain'
4
4
  import DocumentOriginLink from '~/components/documents/DocumentOriginLink.vue'
5
5
  import IntegrationBackTitle from '~/components/layout/IntegrationBackTitle.vue'
6
+ import SectionLabel from '~/components/common/SectionLabel.vue'
6
7
 
7
8
  // Manage the workspace's per-DocKind TEMPLATE (singular) + EXEMPLAR (multi) document links (WS1).
8
9
  // A kind can be pointed at one of the workspace's already-imported documents so its parsed
@@ -132,9 +133,9 @@ async function unlink(doc: SourceDocument) {
132
133
 
133
134
  <!-- Template (singular per kind) ------------------------------------ -->
134
135
  <section class="rounded-lg border border-default bg-default/50 p-3">
135
- <h3 class="text-[11px] font-semibold uppercase tracking-wide text-muted">
136
+ <SectionLabel as="h3">
136
137
  {{ t('documents.templates.templateHeading') }}
137
- </h3>
138
+ </SectionLabel>
138
139
  <p class="mt-0.5 text-xs text-dimmed">
139
140
  {{ t('documents.templates.templateHint', { kind }) }}
140
141
  </p>
@@ -167,9 +168,9 @@ async function unlink(doc: SourceDocument) {
167
168
 
168
169
  <!-- Exemplars (multi per kind) -------------------------------------- -->
169
170
  <section class="rounded-lg border border-default bg-default/50 p-3">
170
- <h3 class="text-[11px] font-semibold uppercase tracking-wide text-muted">
171
+ <SectionLabel as="h3">
171
172
  {{ t('documents.templates.exemplarsHeading') }}
172
- </h3>
173
+ </SectionLabel>
173
174
  <p class="mt-0.5 text-xs text-dimmed">
174
175
  {{ t('documents.templates.exemplarsHint') }}
175
176
  </p>
@@ -238,7 +238,7 @@ onMounted(() => {
238
238
  class="w-full"
239
239
  :placeholder="t('documents.repoPicker.searchFilesPlaceholder')"
240
240
  />
241
- <p v-if="filesError" class="px-1 text-[11px] text-app-warning-400">
241
+ <p v-if="filesError" class="px-1 text-2xs text-app-warning-400">
242
242
  {{ t('documents.repoPicker.filesFailed', { error: filesError }) }}
243
243
  </p>
244
244
  <div class="max-h-56 space-y-0.5 overflow-y-auto">
@@ -252,7 +252,7 @@ onMounted(() => {
252
252
  <UIcon :name="icon" class="h-3.5 w-3.5 shrink-0 text-primary" />
253
253
  <span class="truncate">{{ f.path }}</span>
254
254
  </button>
255
- <p v-if="fileMatchesTruncated" class="px-2 py-1 text-[11px] text-dimmed">
255
+ <p v-if="fileMatchesTruncated" class="px-2 py-1 text-2xs text-dimmed">
256
256
  {{ t('documents.repoPicker.moreFiles', { count: FILE_RESULTS_CAP }) }}
257
257
  </p>
258
258
  <EmptyState
@@ -261,10 +261,7 @@ onMounted(() => {
261
261
  icon="i-lucide-file-search"
262
262
  :title="t('documents.repoPicker.noFileMatches')"
263
263
  />
264
- <p
265
- v-else-if="!loadingFiles && !fileQuery.trim()"
266
- class="px-2 py-1 text-[11px] text-dimmed"
267
- >
264
+ <p v-else-if="!loadingFiles && !fileQuery.trim()" class="px-2 py-1 text-2xs text-dimmed">
268
265
  {{ t('documents.repoPicker.searchFilesHint') }}
269
266
  </p>
270
267
  </div>
@@ -191,18 +191,18 @@ function stage() {
191
191
  <UIcon name="i-lucide-frame" class="h-4 w-4 text-primary" />
192
192
  <span class="truncate">{{ row.label }}</span>
193
193
  </div>
194
- <p v-if="row.trimmed" class="text-[11px] text-muted">
194
+ <p v-if="row.trimmed" class="text-2xs text-muted">
195
195
  {{ t('documents.startFromDesign.trimmed') }}
196
196
  </p>
197
197
  <!-- Its own line, in amber: a trim resolves the same page, a drop widens ONE frame to
198
198
  the whole design file, and the second is what a designer needs to see. -->
199
- <p v-if="row.droppedScope" class="text-[11px] text-app-warning-300">
199
+ <p v-if="row.droppedScope" class="text-2xs text-app-warning-300">
200
200
  {{ t('documents.startFromDesign.widened', { scope: row.droppedScope }) }}
201
201
  </p>
202
- <p v-if="row.unchecked && target" class="text-[11px] text-muted">
202
+ <p v-if="row.unchecked && target" class="text-2xs text-muted">
203
203
  {{ t('documents.startFromDesign.unchecked') }}
204
204
  </p>
205
- <p v-else-if="row.unchecked" class="text-[11px] text-app-warning-300">
205
+ <p v-else-if="row.unchecked" class="text-2xs text-app-warning-300">
206
206
  {{ t('documents.startFromDesign.uncheckedAmbiguous') }}
207
207
  </p>
208
208
  </div>
@@ -165,7 +165,7 @@ async function attach(item: PendingContext) {
165
165
  <DocumentSyncState :doc="doc" class="mt-1" />
166
166
  </div>
167
167
  </div>
168
- <p v-else class="text-[11px] text-dimmed">
168
+ <p v-else class="text-2xs text-dimmed">
169
169
  {{ emptyHint }}
170
170
  </p>
171
171
  </InspectorSection>
@@ -37,10 +37,10 @@ function stepLabel(key: string | undefined): string {
37
37
 
38
38
  <template>
39
39
  <div class="space-y-2" data-testid="env-setup-stepper">
40
- <p v-if="total" class="text-[11px] font-medium text-muted" data-testid="env-setup-progress">
40
+ <p v-if="total" class="text-2xs font-medium text-muted" data-testid="env-setup-progress">
41
41
  {{ t('environmentWizard.progress', { index: index + 1, total }) }}
42
42
  </p>
43
- <ol class="flex items-center gap-2 text-[11px]">
43
+ <ol class="flex items-center gap-2 text-2xs">
44
44
  <li
45
45
  v-for="(step, i) in steps"
46
46
  :key="step.entry"
@@ -48,7 +48,7 @@ function stepLabel(key: string | undefined): string {
48
48
  :data-testid="`env-setup-crumb-${step.entry}`"
49
49
  >
50
50
  <span
51
- class="flex h-5 w-5 items-center justify-center rounded-full text-[10px] font-semibold"
51
+ class="flex h-5 w-5 items-center justify-center rounded-full text-3xs font-semibold"
52
52
  :class="{
53
53
  'bg-primary text-inverted': i === index,
54
54
  'bg-app-success-600/70 text-highlighted': i < index,
@@ -9,6 +9,7 @@ import {
9
9
  readStatusNote,
10
10
  showsProviderFailure,
11
11
  } from '~/components/environments/EnvironmentStatusPanel.logic'
12
+ import SectionLabel from '~/components/common/SectionLabel.vue'
12
13
 
13
14
  const props = defineProps<{
14
15
  environment: RunEnvironment | null
@@ -106,11 +107,11 @@ const envInTransition = computed(
106
107
 
107
108
  <template>
108
109
  <section class="rounded-lg border border-default bg-default/60 p-3">
109
- <h3 class="mb-2 text-[11px] font-semibold uppercase tracking-wide text-dimmed">
110
+ <SectionLabel as="h3" class="mb-2">
110
111
  {{ t('environments.title') }}
111
- </h3>
112
+ </SectionLabel>
112
113
  <div v-if="environment" class="space-y-2">
113
- <div class="flex items-center gap-2 text-[13px]">
114
+ <div class="flex items-center gap-2 text-sm">
114
115
  <UIcon
115
116
  :name="ENV_STATUS_META[environment.status].icon"
116
117
  class="h-3.5 w-3.5"
@@ -128,22 +129,22 @@ const envInTransition = computed(
128
129
  :href="environment.url"
129
130
  target="_blank"
130
131
  rel="noopener"
131
- class="inline-flex items-center gap-1.5 break-all text-[13px] text-app-info-300 hover:underline"
132
+ class="inline-flex items-center gap-1.5 break-all text-sm text-app-info-300 hover:underline"
132
133
  >
133
134
  <UIcon name="i-lucide-external-link" class="h-3.5 w-3.5 shrink-0" />
134
135
  {{ environment.url }}
135
136
  </a>
136
- <p v-if="environment.expiresAt" class="text-[11px] text-dimmed">
137
+ <p v-if="environment.expiresAt" class="text-2xs text-dimmed">
137
138
  {{ t('environments.expires', { date: d(new Date(environment.expiresAt), 'long') }) }}
138
139
  </p>
139
140
  <!-- The resolved provision type + engine recorded at provision time, so a run states
140
141
  exactly what was provisioned and how (the what/where ÷ how split). -->
141
142
  <dl v-if="provisionTypeLabel || engineLabel" class="flex flex-wrap gap-x-4 gap-y-0.5">
142
- <div v-if="provisionTypeLabel" class="flex items-center gap-1 text-[11px]">
143
+ <div v-if="provisionTypeLabel" class="flex items-center gap-1 text-2xs">
143
144
  <dt class="text-dimmed">{{ t('environments.provisionTypeLabel') }}</dt>
144
145
  <dd class="text-toned">{{ provisionTypeLabel }}</dd>
145
146
  </div>
146
- <div v-if="engineLabel" class="flex items-center gap-1 text-[11px]">
147
+ <div v-if="engineLabel" class="flex items-center gap-1 text-2xs">
147
148
  <dt class="text-dimmed">{{ t('environments.engineLabel') }}</dt>
148
149
  <dd class="text-toned">{{ engineLabel }}</dd>
149
150
  </div>
@@ -151,7 +152,7 @@ const envInTransition = computed(
151
152
  <!-- The verbatim provider error when the environment failed/expired. -->
152
153
  <pre
153
154
  v-if="failureShown"
154
- class="mt-1 max-h-32 overflow-auto whitespace-pre-wrap rounded border border-app-error-900/60 bg-app-error-950/40 p-1.5 text-[11px] text-app-error-200/90"
155
+ class="mt-1 max-h-32 overflow-auto whitespace-pre-wrap rounded-sm border border-app-error-900/60 bg-app-error-950/40 p-1.5 text-2xs text-app-error-200/90"
155
156
  >{{ environment.lastError }}</pre>
156
157
  <!-- What the provider says it is still waiting on. Muted rather than alarming: an
157
158
  environment mid-rollout is healthy, and styling this like the error above would report
@@ -159,12 +160,12 @@ const envInTransition = computed(
159
160
  prose. -->
160
161
  <p
161
162
  v-if="statusNote"
162
- class="mt-1 max-h-32 overflow-auto whitespace-pre-wrap break-words text-[11px] text-muted"
163
+ class="mt-1 max-h-32 overflow-auto whitespace-pre-wrap break-words text-2xs text-muted"
163
164
  >
164
165
  {{ t('environments.statusNote', { note: statusNote }) }}
165
166
  </p>
166
167
  </div>
167
- <p v-else class="text-[12px] text-dimmed">
168
+ <p v-else class="text-xs text-dimmed">
168
169
  {{ degradedReason ?? t('environments.empty') }}
169
170
  </p>
170
171
  </section>
@@ -51,21 +51,21 @@ const PREFLIGHT_COLOR: Record<'pass' | 'warn' | 'fail', 'success' | 'warning' |
51
51
 
52
52
  <p
53
53
  v-if="!store.recipe.prerequisites?.length"
54
- class="text-[12px] text-dimmed"
54
+ class="text-xs text-dimmed"
55
55
  data-testid="env-setup-preflight-none"
56
56
  >
57
57
  {{ t('environmentWizard.preflight.none') }}
58
58
  </p>
59
59
  <p
60
60
  v-else-if="preflightsUnavailable"
61
- class="text-[12px] text-app-warning-300/80"
61
+ class="text-xs text-app-warning-300/80"
62
62
  data-testid="env-setup-preflight-unavailable"
63
63
  >
64
64
  {{ t('environmentWizard.preflight.unavailable') }}
65
65
  </p>
66
66
  <p
67
67
  v-if="store.preflightError"
68
- class="text-[12px] text-app-error-300/80"
68
+ class="text-xs text-app-error-300/80"
69
69
  data-testid="env-setup-preflight-error"
70
70
  >
71
71
  {{ store.preflightError }}
@@ -79,21 +79,21 @@ const PREFLIGHT_COLOR: Record<'pass' | 'warn' | 'fail', 'success' | 'warning' |
79
79
  <li
80
80
  v-for="r in store.preflightResults"
81
81
  :key="r.title"
82
- class="rounded border border-default bg-default/40 p-2"
82
+ class="rounded-sm border border-default bg-default/40 p-2"
83
83
  >
84
84
  <div class="flex items-center gap-2">
85
85
  <UBadge :color="PREFLIGHT_COLOR[r.status]" variant="subtle" size="sm">
86
86
  {{ r.status }}
87
87
  </UBadge>
88
- <span class="text-[12px] text-default">{{ r.title }}</span>
89
- <span v-if="!r.required" class="ms-auto text-[10px] text-dimmed">
88
+ <span class="text-xs text-default">{{ r.title }}</span>
89
+ <span v-if="!r.required" class="ms-auto text-3xs text-dimmed">
90
90
  {{ t('environmentWizard.preflight.optional') }}
91
91
  </span>
92
92
  </div>
93
- <p v-if="r.detail" class="mt-1 text-[11px] text-muted">{{ r.detail }}</p>
93
+ <p v-if="r.detail" class="mt-1 text-2xs text-muted">{{ r.detail }}</p>
94
94
  <pre
95
95
  v-if="r.status !== 'pass' && r.remediation"
96
- class="mt-1 max-h-40 overflow-auto whitespace-pre-wrap rounded border border-app-warning-900/40 bg-app-warning-950/20 p-1.5 text-[11px] text-app-warning-200/90"
96
+ class="mt-1 max-h-40 overflow-auto whitespace-pre-wrap rounded-sm border border-app-warning-900/40 bg-app-warning-950/20 p-1.5 text-2xs text-app-warning-200/90"
97
97
  >{{ r.remediation }}</pre>
98
98
  </li>
99
99
  </ul>