@cat-factory/app 0.308.0 → 0.310.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 (265) hide show
  1. package/README.md +32 -2
  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 +8 -6
  6. package/app/components/auth/BackendMisconfiguredScreen.vue +4 -3
  7. package/app/components/auth/LoginScreen.vue +40 -26
  8. package/app/components/auth/ResetPasswordScreen.vue +9 -4
  9. package/app/components/auth/UserMenu.vue +5 -4
  10. package/app/components/binaryCandidates/BinaryCandidatesWindow.vue +48 -37
  11. package/app/components/binaryOutput/BinaryOutputReport.vue +10 -14
  12. package/app/components/binaryOutput/StoredAssetView.vue +13 -11
  13. package/app/components/board/AddTaskModal.vue +30 -27
  14. package/app/components/board/AgentFailureCard.vue +21 -18
  15. package/app/components/board/AgentFailureHistory.vue +18 -9
  16. package/app/components/board/CreateInitiativeModal.vue +7 -6
  17. package/app/components/board/FailureDetail.vue +22 -12
  18. package/app/components/board/FailureHistoryList.vue +5 -5
  19. package/app/components/board/RecurringPipelineModal.vue +12 -11
  20. package/app/components/board/ReviewFrictionDialog.vue +8 -6
  21. package/app/components/board/StepExecutionHistory.vue +8 -8
  22. package/app/components/board/nodes/AgentChip.vue +1 -1
  23. package/app/components/board/nodes/BlockNode.vue +25 -24
  24. package/app/components/board/nodes/DecisionBadge.vue +4 -3
  25. package/app/components/board/nodes/EpicNode.vue +4 -4
  26. package/app/components/board/nodes/FrameSwimlanes.vue +8 -10
  27. package/app/components/board/nodes/InitiativeCard.vue +4 -4
  28. package/app/components/board/nodes/LaneGroup.vue +3 -5
  29. package/app/components/board/nodes/TaskCard.vue +20 -15
  30. package/app/components/board/nodes/TaskLane.vue +3 -3
  31. package/app/components/board/nodes/TaskPipelineMini.vue +21 -18
  32. package/app/components/bootstrap/AdoptionReviewModal.vue +36 -26
  33. package/app/components/bootstrap/BootstrapModal.vue +14 -13
  34. package/app/components/bootstrap/BootstrapRunSteps.vue +1 -1
  35. package/app/components/brainstorm/BrainstormWindow.vue +13 -10
  36. package/app/components/bugFishing/BugFishingWindow.vue +81 -58
  37. package/app/components/clarity/ClarityReviewWindow.vue +13 -10
  38. package/app/components/common/AsyncViewError.vue +1 -1
  39. package/app/components/common/ClarificationItem.vue +6 -6
  40. package/app/components/common/CopyButton.vue +12 -11
  41. package/app/components/common/DescriptorFields.vue +1 -1
  42. package/app/components/common/EmptyState.vue +1 -1
  43. package/app/components/common/IconButton.vue +34 -9
  44. package/app/components/common/InterviewGateNotice.vue +4 -4
  45. package/app/components/common/MarkdownProse.vue +8 -2
  46. package/app/components/common/SectionLabel.vue +38 -0
  47. package/app/components/consensus/ConsensusSessionWindow.vue +10 -9
  48. package/app/components/context/ContextAttachmentFields.vue +32 -20
  49. package/app/components/docs/DocInterviewWindow.vue +10 -9
  50. package/app/components/documents/ContextDocumentPicker.vue +22 -21
  51. package/app/components/documents/DocumentImportModal.vue +7 -5
  52. package/app/components/documents/DocumentOriginLink.vue +12 -9
  53. package/app/components/documents/DocumentSourceConnectModal.vue +2 -2
  54. package/app/components/documents/DocumentSyncState.vue +4 -4
  55. package/app/components/documents/DocumentTemplatesModal.vue +5 -4
  56. package/app/components/documents/RepoContextDocPicker.vue +7 -9
  57. package/app/components/documents/StartFromDesignModal.vue +4 -4
  58. package/app/components/documents/TaskContextDocs.vue +1 -1
  59. package/app/components/environments/EnvSetupStepper.vue +3 -3
  60. package/app/components/environments/EnvironmentStatusPanel.vue +15 -13
  61. package/app/components/environments/steps/EnvPreflightStep.vue +8 -8
  62. package/app/components/environments/steps/EnvReviewStep.vue +23 -22
  63. package/app/components/environments/steps/EnvSaveStep.vue +5 -5
  64. package/app/components/focus/BlockFocusView.vue +11 -10
  65. package/app/components/followUp/FollowUpWindow.vue +18 -15
  66. package/app/components/forkDecision/ForkDecisionWindow.vue +85 -97
  67. package/app/components/foundational/FoundationalContractSummary.vue +2 -2
  68. package/app/components/foundational/FoundationalServiceCatalogList.vue +6 -5
  69. package/app/components/foundational/FoundationalServiceRegistry.vue +10 -9
  70. package/app/components/foundational/FoundationalServiceSources.vue +7 -6
  71. package/app/components/foundational/FoundationalSuppressions.vue +2 -2
  72. package/app/components/fragments/FragmentLibraryManager.vue +8 -7
  73. package/app/components/fragments/FragmentSelector.vue +22 -20
  74. package/app/components/gates/GateFailingCheckList.vue +7 -6
  75. package/app/components/gates/GateResultView.vue +55 -49
  76. package/app/components/github/AddServiceFromRepoModal.vue +16 -11
  77. package/app/components/github/BranchProtectionPreflight.vue +5 -5
  78. package/app/components/github/GitHubConnect.vue +5 -3
  79. package/app/components/github/GitHubOnboarding.vue +7 -2
  80. package/app/components/github/GitHubPanel.vue +23 -19
  81. package/app/components/github/RepoTreeBrowser.vue +16 -13
  82. package/app/components/humanTest/HumanTestWindow.vue +29 -24
  83. package/app/components/initiative/InitiativePlanNotice.vue +3 -3
  84. package/app/components/initiative/InitiativePlanReview.vue +46 -38
  85. package/app/components/initiative/InitiativePlanningWindow.vue +5 -5
  86. package/app/components/initiative/InitiativeTrackerWindow.vue +213 -165
  87. package/app/components/judge/JudgeResultView.vue +28 -27
  88. package/app/components/kaizen/KaizenPanel.vue +70 -56
  89. package/app/components/kaizen/KaizenStepStatus.vue +7 -6
  90. package/app/components/layout/AccountAuditLog.vue +1 -1
  91. package/app/components/layout/AccountDeploymentSettings.vue +10 -10
  92. package/app/components/layout/AccountFailureKindRules.vue +13 -13
  93. package/app/components/layout/AccountFoundationalSettings.vue +1 -1
  94. package/app/components/layout/AccountFragmentSettings.vue +1 -1
  95. package/app/components/layout/AccountModelPolicySettings.vue +7 -7
  96. package/app/components/layout/AccountPlatformAlertSettings.vue +8 -8
  97. package/app/components/layout/AccountRiskPolicySettings.vue +2 -2
  98. package/app/components/layout/AccountRunCredentialSettings.vue +3 -3
  99. package/app/components/layout/AccountSkillSettings.vue +1 -1
  100. package/app/components/layout/AccountTeamSettings.vue +13 -9
  101. package/app/components/layout/AiProvidersBanner.vue +1 -1
  102. package/app/components/layout/AppearanceSwitcher.vue +5 -4
  103. package/app/components/layout/BoardSwitcher.vue +13 -10
  104. package/app/components/layout/BoardToolbar.vue +10 -5
  105. package/app/components/layout/CommandBar.vue +8 -5
  106. package/app/components/layout/DefaultTestEnvBanner.vue +6 -5
  107. package/app/components/layout/IntegrationsHub.vue +12 -9
  108. package/app/components/layout/LanguageSwitcher.vue +5 -4
  109. package/app/components/layout/ModelProvidersHub.vue +10 -7
  110. package/app/components/layout/NotificationsInbox.vue +47 -36
  111. package/app/components/layout/PersonalSetupModal.vue +9 -6
  112. package/app/components/layout/RolePrompt.vue +5 -4
  113. package/app/components/layout/SideBar.vue +7 -8
  114. package/app/components/layout/SpendWarningBanner.vue +3 -3
  115. package/app/components/layout/TranslationWarningBanner.vue +5 -4
  116. package/app/components/layout/UiModeSwitcher.vue +15 -12
  117. package/app/components/layout/UiRoleSwitcher.vue +10 -8
  118. package/app/components/layout/WorkspaceMembersSettings.vue +2 -2
  119. package/app/components/media/ArtifactLightbox.vue +74 -44
  120. package/app/components/media/ImageCompare.vue +80 -85
  121. package/app/components/merge/MergeEffortChips.vue +4 -6
  122. package/app/components/notifications/NotificationSettingsPanel.vue +6 -5
  123. package/app/components/observability/OutcomeFilterChips.vue +6 -5
  124. package/app/components/observability/RunFailureSummary.vue +22 -23
  125. package/app/components/observability/StepMetricsBar.vue +9 -8
  126. package/app/components/observability/StepModelActivity.vue +8 -5
  127. package/app/components/observability/ToolCallList.vue +19 -20
  128. package/app/components/outcome/OutcomeSummaryWindow.vue +48 -46
  129. package/app/components/palettes/AgentPalette.vue +21 -15
  130. package/app/components/palettes/AgentTierSelect.vue +1 -1
  131. package/app/components/palettes/PipelinePurposeSelect.vue +1 -1
  132. package/app/components/panels/AgentStepDetail.vue +57 -49
  133. package/app/components/panels/AttemptEntryHeader.vue +2 -2
  134. package/app/components/panels/DecisionModal.vue +1 -1
  135. package/app/components/panels/GenericStructuredResultView.vue +6 -5
  136. package/app/components/panels/InspectorPanel.vue +15 -13
  137. package/app/components/panels/MergerResultView.vue +10 -9
  138. package/app/components/panels/ObservabilityPanel.vue +211 -186
  139. package/app/components/panels/OperatorDashboardPanel.vue +124 -115
  140. package/app/components/panels/ReportsPanel.vue +87 -83
  141. package/app/components/panels/ReportsSpendBreakdown.vue +2 -2
  142. package/app/components/panels/ResultWindowShell.vue +152 -137
  143. package/app/components/panels/RunDetailLoadState.vue +1 -1
  144. package/app/components/panels/StepContainerStatus.vue +17 -16
  145. package/app/components/panels/StepDelegatedStatus.vue +24 -21
  146. package/app/components/panels/StepEffortReport.vue +12 -17
  147. package/app/components/panels/StepFragmentAdherence.vue +9 -10
  148. package/app/components/panels/StepMetadataCard.vue +41 -43
  149. package/app/components/panels/StepReproductionReport.vue +18 -20
  150. package/app/components/panels/StepRestartControl.vue +3 -2
  151. package/app/components/panels/StepRunMeta.vue +27 -26
  152. package/app/components/panels/StepTestReport.vue +16 -15
  153. package/app/components/panels/StepToolServers.vue +7 -8
  154. package/app/components/panels/StepValidationReport.vue +5 -5
  155. package/app/components/panels/inspector/ContainerSummary.vue +4 -4
  156. package/app/components/panels/inspector/DocReferenceRepos.vue +5 -4
  157. package/app/components/panels/inspector/EnvProbeReport.vue +16 -13
  158. package/app/components/panels/inspector/EpicChildren.vue +12 -10
  159. package/app/components/panels/inspector/FrontendBindingsResolved.vue +5 -4
  160. package/app/components/panels/inspector/FrontendConfig.vue +29 -36
  161. package/app/components/panels/inspector/InitiativeInspector.vue +3 -3
  162. package/app/components/panels/inspector/InspectorSection.vue +25 -17
  163. package/app/components/panels/inspector/RecurringScheduleSettings.vue +9 -8
  164. package/app/components/panels/inspector/ServiceConnections.vue +5 -4
  165. package/app/components/panels/inspector/ServiceReleaseHealthConfig.vue +2 -2
  166. package/app/components/panels/inspector/ServiceSelfTests.vue +9 -13
  167. package/app/components/panels/inspector/ServiceTestConfig.vue +46 -49
  168. package/app/components/panels/inspector/ServiceTestSecrets.vue +3 -3
  169. package/app/components/panels/inspector/ServiceTestingContext.vue +2 -2
  170. package/app/components/panels/inspector/ServiceValidationConfig.vue +2 -2
  171. package/app/components/panels/inspector/TaskAgentConfig.vue +2 -2
  172. package/app/components/panels/inspector/TaskAprioriBranches.vue +6 -5
  173. package/app/components/panels/inspector/TaskDependencies.vue +1 -1
  174. package/app/components/panels/inspector/TaskEstimateBadge.vue +3 -7
  175. package/app/components/panels/inspector/TaskExecution.vue +18 -16
  176. package/app/components/panels/inspector/TaskRunSettings.vue +45 -44
  177. package/app/components/panels/inspector/TaskStructure.vue +5 -4
  178. package/app/components/pipeline/AgentPromptEditor.vue +15 -14
  179. package/app/components/pipeline/BinaryOutputStepPicker.vue +42 -52
  180. package/app/components/pipeline/EstimateThresholdFields.vue +14 -11
  181. package/app/components/pipeline/GateConfigFields.vue +19 -23
  182. package/app/components/pipeline/IterationCapPrompt.vue +1 -1
  183. package/app/components/pipeline/PipelineBuilder.vue +113 -99
  184. package/app/components/pipeline/PipelineHealthModal.vue +7 -7
  185. package/app/components/pipeline/PipelinePicker.vue +11 -9
  186. package/app/components/pipeline/PipelinePreview.vue +6 -7
  187. package/app/components/pipeline/PipelineProgress.vue +49 -45
  188. package/app/components/prReview/PrReviewWindow.vue +87 -65
  189. package/app/components/providers/AiPresetMismatchDialog.vue +4 -3
  190. package/app/components/providers/AiProviderOnboardingModal.vue +2 -2
  191. package/app/components/providers/ApiKeysSection.vue +11 -9
  192. package/app/components/providers/PersonalSubscriptionSection.vue +4 -3
  193. package/app/components/providers/VendorCredentialsModal.vue +5 -4
  194. package/app/components/provisioning/ProvisioningLogsDrawer.vue +10 -9
  195. package/app/components/ralph/RalphLoopResultView.vue +29 -29
  196. package/app/components/requirements/RequirementsReviewWindow.vue +22 -17
  197. package/app/components/riskPolicy/RiskPolicyPicker.vue +13 -11
  198. package/app/components/riskPolicy/RiskPolicyPreview.vue +16 -15
  199. package/app/components/sandbox/SandboxPanel.vue +93 -73
  200. package/app/components/settings/ApiTokensPanel.vue +1 -1
  201. package/app/components/settings/BudgetSettings.vue +18 -17
  202. package/app/components/settings/CapabilityCredentialsPanel.vue +5 -5
  203. package/app/components/settings/CloudflareHandlerSection.vue +44 -41
  204. package/app/components/settings/ComposeEnvironmentSetupSection.vue +14 -12
  205. package/app/components/settings/ConnectionTestVerdict.vue +1 -1
  206. package/app/components/settings/ConsensusGroupsSection.vue +58 -47
  207. package/app/components/settings/CustomManifestTypeEditor.vue +8 -7
  208. package/app/components/settings/DefaultProvisionTypeSection.vue +5 -5
  209. package/app/components/settings/InfraHandlersConfigurator.vue +26 -24
  210. package/app/components/settings/InfrastructureBackendPicker.vue +18 -18
  211. package/app/components/settings/IssueTrackerPanel.vue +30 -21
  212. package/app/components/settings/KubernetesEngineForm.vue +9 -8
  213. package/app/components/settings/KubernetesEnvironmentForm.vue +4 -3
  214. package/app/components/settings/LocalContainerPoolSettings.vue +2 -2
  215. package/app/components/settings/LocalModelEndpointsPanel.vue +13 -11
  216. package/app/components/settings/MergeClassRulesEditor.vue +6 -5
  217. package/app/components/settings/MergeRolePolicyEditor.vue +13 -12
  218. package/app/components/settings/ModelConfigurationPanel.vue +17 -19
  219. package/app/components/settings/ModelPresetHealthModal.vue +3 -3
  220. package/app/components/settings/ObservabilityConnectionPanel.vue +1 -1
  221. package/app/components/settings/OpenRouterCatalogPanel.vue +10 -8
  222. package/app/components/settings/PackageRegistriesPanel.vue +4 -4
  223. package/app/components/settings/ProviderConnectionTab.vue +5 -4
  224. package/app/components/settings/ProviderManifestEditor.vue +9 -8
  225. package/app/components/settings/ProviderPreferenceEditor.vue +13 -13
  226. package/app/components/settings/RiskPolicyCreateForm.vue +40 -26
  227. package/app/components/settings/RiskPolicyEditorRow.vue +21 -19
  228. package/app/components/settings/RiskPolicyHealthModal.vue +3 -3
  229. package/app/components/settings/RiskPolicyPanel.vue +11 -13
  230. package/app/components/settings/ServiceFragmentDefaultsPanel.vue +15 -12
  231. package/app/components/settings/SharedStacksPanel.vue +5 -5
  232. package/app/components/settings/TaskSourceCard.vue +2 -2
  233. package/app/components/settings/TaskTypeSuppressionsPanel.vue +4 -4
  234. package/app/components/settings/ToolServerChecklist.vue +22 -22
  235. package/app/components/settings/UsageSettings.vue +13 -13
  236. package/app/components/settings/UserSecretsSection.vue +4 -3
  237. package/app/components/settings/WorkspaceMetadataSettings.vue +6 -5
  238. package/app/components/settings/WorkspaceSettingsPanel.vue +72 -58
  239. package/app/components/skills/ReviewSkillQueue.vue +12 -10
  240. package/app/components/skills/SkillLibraryManager.vue +9 -8
  241. package/app/components/slack/SlackPanel.vue +17 -12
  242. package/app/components/spec/ServiceSpecWindow.vue +19 -19
  243. package/app/components/tasks/BugHuntModal.vue +1 -1
  244. package/app/components/tasks/ContextIssuePicker.vue +16 -15
  245. package/app/components/tasks/TaskContextIssues.vue +5 -4
  246. package/app/components/tasks/TaskImportModal.vue +3 -2
  247. package/app/components/tasks/TaskSourceConnectModal.vue +5 -5
  248. package/app/components/testing/TestReportWindow.vue +67 -60
  249. package/app/components/theme/ThemeImportModal.vue +2 -2
  250. package/app/components/tutorial/TutorialNudge.vue +3 -2
  251. package/app/components/tutorial/TutorialOverlay.vue +3 -2
  252. package/app/components/vcs/GitLabConnect.vue +1 -1
  253. package/app/components/visualConfirm/VisualConfirmationWindow.vue +79 -54
  254. package/app/utils/theme/builtins.ts +7 -1
  255. package/i18n/locales/de.json +7 -3
  256. package/i18n/locales/en.json +7 -3
  257. package/i18n/locales/es.json +7 -3
  258. package/i18n/locales/fr.json +7 -3
  259. package/i18n/locales/he.json +7 -3
  260. package/i18n/locales/it.json +7 -3
  261. package/i18n/locales/ja.json +7 -3
  262. package/i18n/locales/pl.json +7 -3
  263. package/i18n/locales/tr.json +7 -3
  264. package/i18n/locales/uk.json +7 -3
  265. package/package.json +1 -1
@@ -0,0 +1,38 @@
1
+ <script setup lang="ts">
2
+ // The one section "eyebrow": the small uppercase label that titles a group inside a panel, a
3
+ // result window, an inspector section or a dropdown (issue #2248).
4
+ //
5
+ // The recipe:
6
+ //
7
+ // text-2xs font-semibold uppercase tracking-wide text-muted
8
+ //
9
+ // Those five are the whole component and are NOT overridable. A caller that wants a different
10
+ // size or colour wants a different thing, not a variant of this one.
11
+ //
12
+ // The colour is `text-muted`, not `text-dimmed`, for contrast: at this size `text-dimmed` is 2.63:1
13
+ // on a light surface, under WCAG AA's 4.5:1 and under the 3:1 large-text floor. `text-muted` is
14
+ // 4.76:1. Do not "correct" it to the fainter token.
15
+ //
16
+ // A label that merely SHARES the uppercase styling is not this component: a pill or chip carrying
17
+ // a fill and a radius, an accent-coloured label signalling state or category, or a metadata row
18
+ // (`board/nodes/BlockNode.vue`'s composition line) that states counts rather than titling the
19
+ // block after it. Nor is a caption INSIDE a control: a switcher trigger's "Language" line above its
20
+ // value, a slider's end labels. A caption names part of the control and titles nothing after it.
21
+ // Those keep their own classes on a named step.
22
+ //
23
+ // What a caller DOES control:
24
+ // - `as`, the element. The default `div` suits a label that titles a region without being a
25
+ // document heading; pass `h3` / `h4` when the section is a real heading, `label` with an `:id`
26
+ // when it names a field. A collapsing section is a `UButton` around `as="span"`: the button
27
+ // owns the focus ring and the disabled state, which a raw `as="button"` would not have.
28
+ // - Layout, through the ordinary `class` attribute (`mb-2`, `px-2 pt-2`), which Vue merges onto
29
+ // the root. Spacing is the caller's business because it belongs to the surrounding block.
30
+ // - Every other attribute and listener, which fall through to the root element.
31
+ withDefaults(defineProps<{ as?: string }>(), { as: 'div' })
32
+ </script>
33
+
34
+ <template>
35
+ <component :is="as" class="text-2xs font-semibold uppercase tracking-wide text-muted">
36
+ <slot />
37
+ </component>
38
+ </template>
@@ -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,8 @@ 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'
25
+ import IconButton from '~/components/common/IconButton.vue'
24
26
 
25
27
  const props = defineProps<{
26
28
  /** The staged attachments; the host owns the array and commits it after creating the block. */
@@ -188,9 +190,9 @@ function removePending(item: PendingContext) {
188
190
  <!-- Context documents (ungated; Attach disabled until a source is connected). -->
189
191
  <div class="space-y-2">
190
192
  <div class="flex items-center justify-between">
191
- <span class="text-[11px] font-semibold uppercase tracking-wide text-muted">
193
+ <SectionLabel as="span">
192
194
  {{ t('contextAttachments.documents') }}
193
- </span>
195
+ </SectionLabel>
194
196
  <UButton
195
197
  v-if="docsConnected"
196
198
  color="neutral"
@@ -288,24 +290,29 @@ function removePending(item: PendingContext) {
288
290
  >
289
291
  {{ t('contextAttachments.importsOnAdd') }}
290
292
  </UBadge>
291
- <button
292
- type="button"
293
- class="ms-auto shrink-0 text-muted hover:text-default"
293
+ <IconButton
294
+ color="neutral"
295
+ variant="ghost"
296
+ icon="i-lucide-x"
297
+ class="ms-auto shrink-0"
298
+ :label="t('contextAttachments.removePending', { name: item.title })"
299
+ :ui="{
300
+ base: 'p-0 text-muted hover:bg-transparent hover:text-default',
301
+ leadingIcon: 'h-3.5 w-3.5',
302
+ }"
294
303
  @click="removePending(item)"
295
- >
296
- <UIcon name="i-lucide-x" class="h-3.5 w-3.5" />
297
- </button>
304
+ />
298
305
  </div>
299
306
  <p
300
307
  v-if="item.unreadable"
301
- class="px-2 pb-1.5 text-[11px] text-app-warning-400"
308
+ class="px-2 pb-1.5 text-2xs text-app-warning-400"
302
309
  data-testid="context-item-unreadable"
303
310
  >
304
311
  {{ t('contextAttachments.unreadable', { error: item.unreadable }) }}
305
312
  </p>
306
313
  </div>
307
314
  </div>
308
- <p v-else class="text-[11px] text-dimmed">
315
+ <p v-else class="text-2xs text-dimmed">
309
316
  {{ docsHint }}
310
317
  </p>
311
318
  </div>
@@ -313,9 +320,9 @@ function removePending(item: PendingContext) {
313
320
  <!-- Context issues (ungated; Attach disabled until a tracker is connected). -->
314
321
  <div class="space-y-2">
315
322
  <div class="flex items-center justify-between">
316
- <span class="text-[11px] font-semibold uppercase tracking-wide text-muted">
323
+ <SectionLabel as="span">
317
324
  {{ t('contextAttachments.issues') }}
318
- </span>
325
+ </SectionLabel>
319
326
  <UButton
320
327
  v-if="issuesConnected"
321
328
  color="neutral"
@@ -396,27 +403,32 @@ function removePending(item: PendingContext) {
396
403
  >
397
404
  {{ t('contextAttachments.importsOnAdd') }}
398
405
  </UBadge>
399
- <button
400
- type="button"
401
- class="ms-auto shrink-0 text-muted hover:text-default"
406
+ <IconButton
407
+ color="neutral"
408
+ variant="ghost"
409
+ icon="i-lucide-x"
410
+ class="ms-auto shrink-0"
411
+ :label="t('contextAttachments.removePending', { name: item.title })"
412
+ :ui="{
413
+ base: 'p-0 text-muted hover:bg-transparent hover:text-default',
414
+ leadingIcon: 'h-3.5 w-3.5',
415
+ }"
402
416
  @click="removePending(item)"
403
- >
404
- <UIcon name="i-lucide-x" class="h-3.5 w-3.5" />
405
- </button>
417
+ />
406
418
  </div>
407
419
  <!-- An issue reference gets no pre-flight of its own (there is no `parseRef` to ask a
408
420
  tracker), so this line IS its warning: the fetch is attempted when the form opens and
409
421
  again on submit, and a failure now blocks the create. -->
410
422
  <p
411
423
  v-if="item.unreadable"
412
- class="px-2 pb-1.5 text-[11px] text-app-warning-400"
424
+ class="px-2 pb-1.5 text-2xs text-app-warning-400"
413
425
  data-testid="context-item-unreadable"
414
426
  >
415
427
  {{ t('contextAttachments.unreadable', { error: item.unreadable }) }}
416
428
  </p>
417
429
  </div>
418
430
  </div>
419
- <p v-else class="text-[11px] text-dimmed">
431
+ <p v-else class="text-2xs text-dimmed">
420
432
  {{ issuesHint }}
421
433
  </p>
422
434
  </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') }}
@@ -540,10 +538,11 @@ onMounted(() => {
540
538
 
541
539
  <div class="max-h-56 space-y-0.5 overflow-y-auto">
542
540
  <!-- Already-imported documents (linked directly, no re-fetch). -->
543
- <button
541
+ <UButton
542
+ color="neutral"
543
+ variant="ghost"
544
544
  v-for="d in importedRows"
545
545
  :key="`imp:${d.externalId}`"
546
- type="button"
547
546
  class="flex w-full items-center gap-1.5 rounded-md px-2 py-1.5 text-start text-xs text-toned hover:bg-elevated/70"
548
547
  @click="pickImported(d.externalId, d.title, d.excerpt)"
549
548
  >
@@ -552,26 +551,28 @@ onMounted(() => {
552
551
  <UBadge color="neutral" variant="soft" size="xs" class="ms-auto shrink-0">{{
553
552
  t('documents.picker.importedBadge')
554
553
  }}</UBadge>
555
- </button>
554
+ </UButton>
556
555
 
557
556
  <!-- Source search hits (imported on add). -->
558
- <button
557
+ <UButton
558
+ color="neutral"
559
+ variant="ghost"
559
560
  v-for="r in searchRows"
560
561
  :key="`hit:${r.externalId}`"
561
- type="button"
562
562
  class="flex w-full items-center gap-1.5 rounded-md px-2 py-1.5 text-start text-xs text-toned hover:bg-elevated/70"
563
563
  @click="pickSearch(r)"
564
564
  >
565
565
  <UIcon :name="icon" class="h-3.5 w-3.5 shrink-0 text-muted" />
566
566
  <span class="truncate">{{ r.title }}</span>
567
- </button>
567
+ </UButton>
568
568
 
569
569
  <!-- Explicit URL/ID reference, RESOLVED: the row shows the canonical form the source
570
570
  settled on, so a share link's title segment and tracking params are visibly gone
571
571
  before the attachment is staged. -->
572
- <button
572
+ <UButton
573
+ color="neutral"
574
+ variant="ghost"
573
575
  v-if="refRow"
574
- type="button"
575
576
  class="flex w-full items-start gap-1.5 rounded-md px-2 py-1.5 text-start text-xs text-toned hover:bg-elevated/70"
576
577
  data-testid="doc-ref-attach"
577
578
  @click="pickRef(refRow)"
@@ -585,7 +586,7 @@ onMounted(() => {
585
586
  </template>
586
587
  </i18n-t>
587
588
  </span>
588
- <span v-if="refRow.trimmed" class="block truncate text-[11px] text-dimmed">
589
+ <span v-if="refRow.trimmed" class="block truncate text-2xs text-dimmed">
589
590
  {{ t('documents.picker.refTrimmed') }}
590
591
  </span>
591
592
  <!-- A WIDENED reference, which the trim note above must never be left to imply: the
@@ -593,7 +594,7 @@ onMounted(() => {
593
594
  around it. Amber and separate, because it is a loss rather than tidying. -->
594
595
  <span
595
596
  v-if="refRow.droppedScope"
596
- class="block text-[11px] text-app-warning-400"
597
+ class="block text-2xs text-app-warning-400"
597
598
  data-testid="doc-ref-widened"
598
599
  >
599
600
  {{ t('documents.picker.refWidened', { scope: refRow.droppedScope }) }}
@@ -608,7 +609,7 @@ onMounted(() => {
608
609
  >
609
610
  {{ t('documents.picker.importedBadge') }}
610
611
  </UBadge>
611
- </button>
612
+ </UButton>
612
613
 
613
614
  <EmptyState
614
615
  v-if="empty"
@@ -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}`"
@@ -135,14 +136,15 @@ function preview(externalId: string) {
135
136
  >
136
137
  <div class="flex items-start justify-between gap-2">
137
138
  <div class="min-w-0">
138
- <a
139
- :href="doc.url"
139
+ <ULink
140
+ raw
141
+ :to="doc.url"
140
142
  target="_blank"
141
143
  rel="noopener"
142
144
  class="truncate text-sm font-medium text-highlighted hover:underline"
143
145
  >
144
146
  {{ doc.title }}
145
- </a>
147
+ </ULink>
146
148
  <p class="mt-0.5 line-clamp-2 text-xs text-dimmed">{{ doc.excerpt }}</p>
147
149
  <DocumentSyncState :doc="doc" class="mt-1" />
148
150
  </div>
@@ -16,15 +16,18 @@ const { t } = useI18n()
16
16
  </script>
17
17
 
18
18
  <template>
19
- <component
20
- :is="props.url ? 'a' : 'span'"
21
- :class="props.url ? props.hoverClass : undefined"
22
- v-bind="
23
- props.url
24
- ? { href: props.url, title: props.url, target: '_blank', rel: 'noopener' }
25
- : { title: t('documents.taskDocs.uploadedHint') }
26
- "
19
+ <ULink
20
+ v-if="props.url"
21
+ raw
22
+ :to="props.url"
23
+ target="_blank"
24
+ rel="noopener"
25
+ :title="props.url"
26
+ :class="props.hoverClass"
27
27
  >
28
28
  <slot />
29
- </component>
29
+ </ULink>
30
+ <span v-else :title="t('documents.taskDocs.uploadedHint')">
31
+ <slot />
32
+ </span>
30
33
  </template>
@@ -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">
@@ -1,5 +1,6 @@
1
1
  <script setup lang="ts">
2
2
  import { isConnectableSource } from '@cat-factory/contracts'
3
+ import IconButton from '~/components/common/IconButton.vue'
3
4
  import type { SourceDocument } from '~/types/domain'
4
5
  import {
5
6
  CHANGE_KEYS,
@@ -165,7 +166,7 @@ async function refresh() {
165
166
  </script>
166
167
 
167
168
  <template>
168
- <div class="flex items-center gap-1.5 text-[11px] text-dimmed">
169
+ <div class="flex items-center gap-1.5 text-2xs text-dimmed">
169
170
  <span class="truncate">
170
171
  {{ t('documents.freshness.updated', { when: d(new Date(props.doc.syncedAt), 'long') }) }}
171
172
  </span>
@@ -182,15 +183,14 @@ async function refresh() {
182
183
  <UIcon name="i-lucide-image-off" class="h-3 w-3 shrink-0" />
183
184
  <span class="truncate">{{ renders }}</span>
184
185
  </span>
185
- <UButton
186
+ <IconButton
186
187
  v-if="askable"
187
188
  color="neutral"
188
189
  variant="ghost"
189
190
  size="xs"
190
191
  icon="i-lucide-refresh-cw"
191
192
  :loading="busy"
192
- :aria-label="t('documents.freshness.refresh')"
193
- :title="t('documents.freshness.refresh')"
193
+ :label="t('documents.freshness.refresh')"
194
194
  class="ml-auto shrink-0"
195
195
  @click="refresh"
196
196
  />
@@ -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,21 +238,22 @@ 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">
245
- <button
245
+ <UButton
246
+ color="neutral"
247
+ variant="ghost"
246
248
  v-for="f in fileMatches"
247
249
  :key="f.path"
248
- type="button"
249
250
  class="flex w-full items-center gap-1.5 rounded-md px-2 py-1.5 text-start text-xs text-toned hover:bg-elevated/70"
250
251
  @click="pickFile(f.path)"
251
252
  >
252
253
  <UIcon :name="icon" class="h-3.5 w-3.5 shrink-0 text-primary" />
253
254
  <span class="truncate">{{ f.path }}</span>
254
- </button>
255
- <p v-if="fileMatchesTruncated" class="px-2 py-1 text-[11px] text-dimmed">
255
+ </UButton>
256
+ <p v-if="fileMatchesTruncated" class="px-2 py-1 text-2xs text-dimmed">
256
257
  {{ t('documents.repoPicker.moreFiles', { count: FILE_RESULTS_CAP }) }}
257
258
  </p>
258
259
  <EmptyState
@@ -261,10 +262,7 @@ onMounted(() => {
261
262
  icon="i-lucide-file-search"
262
263
  :title="t('documents.repoPicker.noFileMatches')"
263
264
  />
264
- <p
265
- v-else-if="!loadingFiles && !fileQuery.trim()"
266
- class="px-2 py-1 text-[11px] text-dimmed"
267
- >
265
+ <p v-else-if="!loadingFiles && !fileQuery.trim()" class="px-2 py-1 text-2xs text-dimmed">
268
266
  {{ t('documents.repoPicker.searchFilesHint') }}
269
267
  </p>
270
268
  </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>