@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
@@ -22,6 +22,7 @@
22
22
  // self-assessment (see the footer block below), so a window never renders it itself.
23
23
  import { computed, ref, watch } from 'vue'
24
24
  import { useModalBehavior } from '@modular-vue/core'
25
+ import IconButton from '~/components/common/IconButton.vue'
25
26
  import StepRestartControl from '~/components/panels/StepRestartControl.vue'
26
27
  import RunDetailLoadState from '~/components/panels/RunDetailLoadState.vue'
27
28
  import StepEffortReport from '~/components/panels/StepEffortReport.vue'
@@ -39,6 +40,7 @@ import {
39
40
  RESULT_WINDOW_WIDTH_CLASS,
40
41
  type ResultWindowWidth,
41
42
  } from '~/components/panels/ResultWindowShell.logic'
43
+ import SectionLabel from '~/components/common/SectionLabel.vue'
42
44
 
43
45
  /** A pipeline step reference — passed by step-result windows to surface the shared
44
46
  * "restart from here" control. `StepRestartControl` self-hides for an off-path open
@@ -68,8 +70,8 @@ const props = withDefaults(
68
70
  * worse, not better.
69
71
  *
70
72
  * The obligation that comes with it: CONTINUOUS PROSE inside a `full` window carries its
71
- * own reading measure (`PROSE_MEASURE_CLASS`, the step reader's own, over the same 13px
72
- * `.reader-prose`), or the width lands as 200-character lines.
73
+ * own reading measure (`PROSE_MEASURE_CLASS`, the step reader's own, over the same
74
+ * `text-sm` `.reader-prose`), or the width lands as 200-character lines.
73
75
  *
74
76
  * The unit that obligation attaches to is the PARAGRAPH, not the section — which is the
75
77
  * distinction to get right, because "a findings list reads better at the full span" is
@@ -289,7 +291,7 @@ const panelClass = computed(() => [
289
291
  </span>
290
292
  <div class="min-w-0 flex-1">
291
293
  <h2 class="truncate text-sm font-semibold text-app-100">{{ title }}</h2>
292
- <p v-if="subtitle" class="truncate text-[11px] text-muted">{{ subtitle }}</p>
294
+ <p v-if="subtitle" class="truncate text-2xs text-muted">{{ subtitle }}</p>
293
295
  </div>
294
296
  <!-- Window-specific header content (status badges, counts). -->
295
297
  <slot name="header-extras" />
@@ -299,14 +301,15 @@ const panelClass = computed(() => [
299
301
  :step-index="stepRef.stepIndex"
300
302
  @restarted="requestClose"
301
303
  />
302
- <button
303
- class="rounded-md p-1.5 text-muted hover:bg-elevated hover:text-default"
304
+ <IconButton
305
+ icon="i-lucide-x"
306
+ color="neutral"
307
+ variant="ghost"
308
+ size="sm"
304
309
  data-testid="result-window-close"
305
- :aria-label="t('common.close')"
310
+ :label="t('common.close')"
306
311
  @click="requestClose"
307
- >
308
- <UIcon name="i-lucide-x" class="h-4 w-4" />
309
- </button>
312
+ />
310
313
  </header>
311
314
  <!-- Whether the whole-run fetch behind this window's prose has landed. -->
312
315
  <RunDetailLoadState :instance-id="activeInstanceId" />
@@ -321,34 +324,37 @@ const panelClass = computed(() => [
321
324
  class="shrink-0 border-t border-default bg-default/60"
322
325
  data-testid="result-window-effort"
323
326
  >
324
- <button
325
- type="button"
326
- class="flex w-full items-center gap-2 px-5 py-2 text-start hover:bg-elevated/40"
327
- :aria-expanded="effortOpen"
328
- data-testid="result-window-effort-toggle"
329
- @click="effortOpen = !effortOpen"
330
- >
331
- <UIcon name="i-lucide-gauge" class="h-3.5 w-3.5 shrink-0 text-muted" />
332
- <span class="text-[11px] font-semibold uppercase tracking-wide text-muted">
333
- {{ t('panels.stepDetail.effort.heading') }}
334
- </span>
335
- <span
336
- class="shrink-0 rounded px-1.5 py-0.5 text-[11px] font-medium tabular-nums"
337
- :class="chipClass"
327
+ <UCollapsible v-model:open="effortOpen">
328
+ <UButton
329
+ color="neutral"
330
+ variant="ghost"
331
+ class="flex w-full items-center gap-2 px-5 py-2 text-start hover:bg-elevated/40"
332
+ data-testid="result-window-effort-toggle"
338
333
  >
339
- {{ t('panels.stepDetail.effort.outOfTen', { value: effortReport.difficulty }) }}
340
- </span>
341
- <span v-if="hint" class="min-w-0 flex-1 truncate text-[12px] text-muted">
342
- {{ hint }}
343
- </span>
344
- <UIcon
345
- :name="effortOpen ? 'i-lucide-chevron-down' : 'i-lucide-chevron-up'"
346
- class="ms-auto h-3.5 w-3.5 shrink-0 text-dimmed"
347
- />
348
- </button>
349
- <div v-if="effortOpen" class="max-h-56 overflow-y-auto px-5 pb-3">
350
- <StepEffortReport :report="effortReport" variant="flat" />
351
- </div>
334
+ <UIcon name="i-lucide-gauge" class="h-3.5 w-3.5 shrink-0 text-muted" />
335
+ <SectionLabel as="span">
336
+ {{ t('panels.stepDetail.effort.heading') }}
337
+ </SectionLabel>
338
+ <span
339
+ class="shrink-0 rounded-sm px-1.5 py-0.5 text-2xs font-medium tabular-nums"
340
+ :class="chipClass"
341
+ >
342
+ {{ t('panels.stepDetail.effort.outOfTen', { value: effortReport.difficulty }) }}
343
+ </span>
344
+ <span v-if="hint" class="min-w-0 flex-1 truncate text-xs text-muted">
345
+ {{ hint }}
346
+ </span>
347
+ <UIcon
348
+ :name="effortOpen ? 'i-lucide-chevron-down' : 'i-lucide-chevron-up'"
349
+ class="ms-auto h-3.5 w-3.5 shrink-0 text-dimmed"
350
+ />
351
+ </UButton>
352
+ <template #content>
353
+ <div class="max-h-56 overflow-y-auto px-5 pb-3">
354
+ <StepEffortReport :report="effortReport" variant="flat" />
355
+ </div>
356
+ </template>
357
+ </UCollapsible>
352
358
  </section>
353
359
 
354
360
  <!-- Shared trailing section: the pre-PR validation report (the service's check commands
@@ -359,51 +365,54 @@ const panelClass = computed(() => [
359
365
  class="shrink-0 border-t border-default bg-default/60"
360
366
  data-testid="result-window-validation"
361
367
  >
362
- <button
363
- type="button"
364
- class="flex w-full items-center gap-2 px-5 py-2 text-start hover:bg-elevated/40"
365
- :aria-expanded="validationOpen"
366
- data-testid="result-window-validation-toggle"
367
- @click="validationOpen = !validationOpen"
368
- >
369
- <UIcon
370
- :name="validationReport.passed ? 'i-lucide-shield-check' : 'i-lucide-shield-alert'"
371
- class="h-3.5 w-3.5 shrink-0"
372
- :class="validationReport.passed ? 'text-app-success-400' : 'text-app-error-400'"
373
- />
374
- <span class="text-[11px] font-semibold uppercase tracking-wide text-muted">
375
- {{ t('panels.stepDetail.validation.heading') }}
376
- </span>
377
- <span
378
- class="shrink-0 rounded px-1.5 py-0.5 text-[11px] font-medium tabular-nums"
379
- :class="
380
- validationReport.passed
381
- ? 'bg-app-success-500/15 text-app-success-300'
382
- : 'bg-app-error-500/15 text-app-error-300'
383
- "
368
+ <UCollapsible v-model:open="validationOpen">
369
+ <UButton
370
+ color="neutral"
371
+ variant="ghost"
372
+ class="flex w-full items-center gap-2 px-5 py-2 text-start hover:bg-elevated/40"
373
+ data-testid="result-window-validation-toggle"
384
374
  >
385
- {{
386
- validationReport.passed
387
- ? t('panels.stepDetail.validation.passed')
388
- : t('panels.stepDetail.validation.failed')
389
- }}
390
- </span>
391
- <span class="min-w-0 flex-1 truncate text-[12px] text-muted">
392
- {{
393
- t('panels.stepDetail.validation.attempts', {
394
- attempts: validationReport.attempts,
395
- maxAttempts: validationReport.maxAttempts,
396
- })
397
- }}
398
- </span>
399
- <UIcon
400
- :name="validationOpen ? 'i-lucide-chevron-down' : 'i-lucide-chevron-up'"
401
- class="ms-auto h-3.5 w-3.5 shrink-0 text-dimmed"
402
- />
403
- </button>
404
- <div v-if="validationOpen" class="max-h-72 overflow-y-auto px-5 pb-3">
405
- <StepValidationReport :report="validationReport" />
406
- </div>
375
+ <UIcon
376
+ :name="validationReport.passed ? 'i-lucide-shield-check' : 'i-lucide-shield-alert'"
377
+ class="h-3.5 w-3.5 shrink-0"
378
+ :class="validationReport.passed ? 'text-app-success-400' : 'text-app-error-400'"
379
+ />
380
+ <SectionLabel as="span">
381
+ {{ t('panels.stepDetail.validation.heading') }}
382
+ </SectionLabel>
383
+ <span
384
+ class="shrink-0 rounded-sm px-1.5 py-0.5 text-2xs font-medium tabular-nums"
385
+ :class="
386
+ validationReport.passed
387
+ ? 'bg-app-success-500/15 text-app-success-300'
388
+ : 'bg-app-error-500/15 text-app-error-300'
389
+ "
390
+ >
391
+ {{
392
+ validationReport.passed
393
+ ? t('panels.stepDetail.validation.passed')
394
+ : t('panels.stepDetail.validation.failed')
395
+ }}
396
+ </span>
397
+ <span class="min-w-0 flex-1 truncate text-xs text-muted">
398
+ {{
399
+ t('panels.stepDetail.validation.attempts', {
400
+ attempts: validationReport.attempts,
401
+ maxAttempts: validationReport.maxAttempts,
402
+ })
403
+ }}
404
+ </span>
405
+ <UIcon
406
+ :name="validationOpen ? 'i-lucide-chevron-down' : 'i-lucide-chevron-up'"
407
+ class="ms-auto h-3.5 w-3.5 shrink-0 text-dimmed"
408
+ />
409
+ </UButton>
410
+ <template #content>
411
+ <div class="max-h-72 overflow-y-auto px-5 pb-3">
412
+ <StepValidationReport :report="validationReport" />
413
+ </div>
414
+ </template>
415
+ </UCollapsible>
407
416
  </section>
408
417
 
409
418
  <!-- Shared trailing section: the bugfix reproduction proof (the declared check run against
@@ -415,42 +424,45 @@ const panelClass = computed(() => [
415
424
  class="shrink-0 border-t border-default bg-default/60"
416
425
  data-testid="result-window-reproduction"
417
426
  >
418
- <button
419
- type="button"
420
- class="flex w-full items-center gap-2 px-5 py-2 text-start hover:bg-elevated/40"
421
- :aria-expanded="reproductionOpen"
422
- data-testid="result-window-reproduction-toggle"
423
- @click="reproductionOpen = !reproductionOpen"
424
- >
425
- <UIcon
426
- :name="reproductionKeys!.icon"
427
- class="h-3.5 w-3.5 shrink-0"
428
- :class="reproductionKeys!.proven ? 'text-app-success-400' : 'text-app-warning-400'"
429
- />
430
- <span class="text-[11px] font-semibold uppercase tracking-wide text-muted">
431
- {{ t('panels.stepDetail.reproduction.heading') }}
432
- </span>
433
- <span
434
- class="shrink-0 rounded px-1.5 py-0.5 text-[11px] font-medium"
435
- :class="
436
- reproductionKeys!.proven
437
- ? 'bg-app-success-500/15 text-app-success-300'
438
- : 'bg-app-warning-500/15 text-app-warning-300'
439
- "
427
+ <UCollapsible v-model:open="reproductionOpen">
428
+ <UButton
429
+ color="neutral"
430
+ variant="ghost"
431
+ class="flex w-full items-center gap-2 px-5 py-2 text-start hover:bg-elevated/40"
432
+ data-testid="result-window-reproduction-toggle"
440
433
  >
441
- {{ t(reproductionKeys!.chip) }}
442
- </span>
443
- <span class="min-w-0 flex-1 truncate text-[12px] text-muted">
444
- {{ t(reproductionKeys!.verdict) }}
445
- </span>
446
- <UIcon
447
- :name="reproductionOpen ? 'i-lucide-chevron-down' : 'i-lucide-chevron-up'"
448
- class="ms-auto h-3.5 w-3.5 shrink-0 text-dimmed"
449
- />
450
- </button>
451
- <div v-if="reproductionOpen" class="max-h-72 overflow-y-auto px-5 pb-3">
452
- <StepReproductionReport :report="reproductionReport" />
453
- </div>
434
+ <UIcon
435
+ :name="reproductionKeys!.icon"
436
+ class="h-3.5 w-3.5 shrink-0"
437
+ :class="reproductionKeys!.proven ? 'text-app-success-400' : 'text-app-warning-400'"
438
+ />
439
+ <SectionLabel as="span">
440
+ {{ t('panels.stepDetail.reproduction.heading') }}
441
+ </SectionLabel>
442
+ <span
443
+ class="shrink-0 rounded-sm px-1.5 py-0.5 text-2xs font-medium"
444
+ :class="
445
+ reproductionKeys!.proven
446
+ ? 'bg-app-success-500/15 text-app-success-300'
447
+ : 'bg-app-warning-500/15 text-app-warning-300'
448
+ "
449
+ >
450
+ {{ t(reproductionKeys!.chip) }}
451
+ </span>
452
+ <span class="min-w-0 flex-1 truncate text-xs text-muted">
453
+ {{ t(reproductionKeys!.verdict) }}
454
+ </span>
455
+ <UIcon
456
+ :name="reproductionOpen ? 'i-lucide-chevron-down' : 'i-lucide-chevron-up'"
457
+ class="ms-auto h-3.5 w-3.5 shrink-0 text-dimmed"
458
+ />
459
+ </UButton>
460
+ <template #content>
461
+ <div class="max-h-72 overflow-y-auto px-5 pb-3">
462
+ <StepReproductionReport :report="reproductionReport" />
463
+ </div>
464
+ </template>
465
+ </UCollapsible>
454
466
  </section>
455
467
 
456
468
  <!-- Shared trailing section: what this step's agent declared it stored through a
@@ -463,28 +475,31 @@ const panelClass = computed(() => [
463
475
  class="shrink-0 border-t border-default bg-default/60"
464
476
  data-testid="result-window-binary-outputs"
465
477
  >
466
- <button
467
- type="button"
468
- class="flex w-full items-center gap-2 px-5 py-2 text-start hover:bg-elevated/40"
469
- :aria-expanded="binaryOutputsOpen"
470
- data-testid="result-window-binary-outputs-toggle"
471
- @click="binaryOutputsOpen = !binaryOutputsOpen"
472
- >
473
- <UIcon name="i-lucide-image" class="h-3.5 w-3.5 shrink-0 text-muted" />
474
- <span class="text-[11px] font-semibold uppercase tracking-wide text-muted">
475
- {{ t('binaryOutput.heading') }}
476
- </span>
477
- <span class="min-w-0 flex-1 truncate text-[12px] text-muted">
478
- {{ binaryOutputSummary }}
479
- </span>
480
- <UIcon
481
- :name="binaryOutputsOpen ? 'i-lucide-chevron-down' : 'i-lucide-chevron-up'"
482
- class="ms-auto h-3.5 w-3.5 shrink-0 text-dimmed"
483
- />
484
- </button>
485
- <div v-if="binaryOutputsOpen && activeStep" class="max-h-72 overflow-y-auto px-5 pb-3">
486
- <BinaryOutputReport :step="activeStep" />
487
- </div>
478
+ <UCollapsible v-model:open="binaryOutputsOpen">
479
+ <UButton
480
+ color="neutral"
481
+ variant="ghost"
482
+ class="flex w-full items-center gap-2 px-5 py-2 text-start hover:bg-elevated/40"
483
+ data-testid="result-window-binary-outputs-toggle"
484
+ >
485
+ <UIcon name="i-lucide-image" class="h-3.5 w-3.5 shrink-0 text-muted" />
486
+ <SectionLabel as="span">
487
+ {{ t('binaryOutput.heading') }}
488
+ </SectionLabel>
489
+ <span class="min-w-0 flex-1 truncate text-xs text-muted">
490
+ {{ binaryOutputSummary }}
491
+ </span>
492
+ <UIcon
493
+ :name="binaryOutputsOpen ? 'i-lucide-chevron-down' : 'i-lucide-chevron-up'"
494
+ class="ms-auto h-3.5 w-3.5 shrink-0 text-dimmed"
495
+ />
496
+ </UButton>
497
+ <template #content>
498
+ <div v-if="activeStep" class="max-h-72 overflow-y-auto px-5 pb-3">
499
+ <BinaryOutputReport :step="activeStep" />
500
+ </div>
501
+ </template>
502
+ </UCollapsible>
488
503
  </section>
489
504
  </div>
490
505
  </div>
@@ -25,7 +25,7 @@ const error = computed(() => execution.fullError(props.instanceId))
25
25
  <template>
26
26
  <div
27
27
  v-if="loading || error"
28
- class="flex items-center gap-2 border-b border-default px-4 py-2 text-[11px]"
28
+ class="flex items-center gap-2 border-b border-default px-4 py-2 text-2xs"
29
29
  :class="error ? 'text-app-error-300' : 'text-muted'"
30
30
  data-testid="run-detail-load-state"
31
31
  >
@@ -2,6 +2,8 @@
2
2
  import { computed } from 'vue'
3
3
  import type { PipelineStep, RunContainerStatus } from '~/types/execution'
4
4
  import { containerPhaseLabel } from '~/utils/pipelineRender'
5
+ import SectionLabel from '~/components/common/SectionLabel.vue'
6
+ import IconButton from '~/components/common/IconButton.vue'
5
7
 
6
8
  // The per-run container lifecycle for a container-backed step: its status (spinning up /
7
9
  // running / errored / reclaimed), the live phase (preparing the checkout vs the agent
@@ -94,7 +96,7 @@ const { copy: copyText } = useCopyToClipboard()
94
96
  live phase (preparing the checkout vs the agent making calls), and the
95
97
  container's id + reachable URL once up. -->
96
98
  <div
97
- class="rounded-lg border px-3 py-2 text-[12px]"
99
+ class="rounded-lg border px-3 py-2 text-xs"
98
100
  :class="CONTAINER_STATUS_META[containerStatus].cls"
99
101
  >
100
102
  <div class="flex items-center gap-2">
@@ -111,45 +113,44 @@ const { copy: copyText } = useCopyToClipboard()
111
113
  </div>
112
114
  <dl v-if="step.container?.id || step.container?.url" class="mt-2 space-y-1">
113
115
  <div v-if="step.container?.id" class="flex items-center gap-2">
114
- <dt class="shrink-0 text-[11px] uppercase tracking-wide text-dimmed">
116
+ <SectionLabel as="dt" class="shrink-0">
115
117
  {{ t('panels.stepMeta.container.id') }}
116
- </dt>
117
- <dd class="truncate font-mono text-[11px] text-toned" :title="step.container.id">
118
+ </SectionLabel>
119
+ <dd class="truncate font-mono text-2xs text-toned" :title="step.container.id">
118
120
  {{ step.container.id }}
119
121
  </dd>
120
- <UButton
122
+ <IconButton
121
123
  icon="i-lucide-copy"
122
124
  color="neutral"
123
125
  variant="ghost"
124
126
  size="xs"
125
127
  class="ms-auto shrink-0"
126
- :title="t('panels.stepMeta.container.copyId')"
127
- :aria-label="t('panels.stepMeta.container.copyId')"
128
+ :label="t('panels.stepMeta.container.copyId')"
128
129
  @click="copyText(step.container.id)"
129
130
  />
130
131
  </div>
131
132
  <div v-if="step.container?.url" class="flex items-center gap-2">
132
- <dt class="shrink-0 text-[11px] uppercase tracking-wide text-dimmed">
133
+ <SectionLabel as="dt" class="shrink-0">
133
134
  {{ t('panels.stepMeta.container.url') }}
134
- </dt>
135
- <dd class="truncate font-mono text-[11px] text-toned">
136
- <a
137
- :href="step.container.url"
135
+ </SectionLabel>
136
+ <dd class="truncate font-mono text-2xs text-toned">
137
+ <ULink
138
+ raw
139
+ :to="step.container.url"
138
140
  target="_blank"
139
141
  rel="noopener noreferrer"
140
142
  class="hover:underline"
141
143
  >
142
144
  {{ step.container.url }}
143
- </a>
145
+ </ULink>
144
146
  </dd>
145
- <UButton
147
+ <IconButton
146
148
  icon="i-lucide-copy"
147
149
  color="neutral"
148
150
  variant="ghost"
149
151
  size="xs"
150
152
  class="ms-auto shrink-0"
151
- :title="t('panels.stepMeta.container.copyUrl')"
152
- :aria-label="t('panels.stepMeta.container.copyUrl')"
153
+ :label="t('panels.stepMeta.container.copyUrl')"
153
154
  @click="copyText(step.container.url)"
154
155
  />
155
156
  </div>
@@ -6,6 +6,8 @@ import {
6
6
  externalRunHref,
7
7
  } from './StepDelegatedStatus.logic'
8
8
  import type { PipelineStep } from '~/types/execution'
9
+ import SectionLabel from '~/components/common/SectionLabel.vue'
10
+ import IconButton from '~/components/common/IconButton.vue'
9
11
 
10
12
  // The EXTERNAL work a delegated step dispatched: which registered executor is running it, what it
11
13
  // is doing, and the link to that system's own logs, which is the affordance everything else here
@@ -77,7 +79,7 @@ const { copy: copyText } = useCopyToClipboard()
77
79
  <!-- Single conditional root so a passed-through `class` (e.g. layout margin) applies cleanly.
78
80
  Renders nothing for a step that dispatched nowhere external. -->
79
81
  <div v-if="record" data-testid="step-delegated-status">
80
- <div class="rounded-lg border px-3 py-2 text-[12px]" :class="statusView.meta.cls">
82
+ <div class="rounded-lg border px-3 py-2 text-xs" :class="statusView.meta.cls">
81
83
  <div class="flex items-center gap-2">
82
84
  <UIcon
83
85
  :name="statusView.meta.icon"
@@ -98,32 +100,32 @@ const { copy: copyText } = useCopyToClipboard()
98
100
  <!-- The PRIMARY affordance: the executor's own logs. It is the only place the detail of
99
101
  what happened exists, which is why a failed delegated step without it is a dead end. -->
100
102
  <div v-if="record.url" class="mt-2 flex items-center gap-2">
101
- <dt class="shrink-0 text-[11px] uppercase tracking-wide text-dimmed">
103
+ <SectionLabel as="dt" class="shrink-0">
102
104
  {{ t('panels.stepMeta.delegated.run') }}
103
- </dt>
105
+ </SectionLabel>
104
106
  <!-- Linked only when the executor's URL is `http(s)`. Anything else is shown as the text
105
107
  it is: refusing to follow it is right, and hiding it would report a run that named
106
108
  no link at all. -->
107
- <dd class="truncate font-mono text-[11px] text-toned">
108
- <a
109
+ <dd class="truncate font-mono text-2xs text-toned">
110
+ <ULink
111
+ raw
109
112
  v-if="runHref"
110
- :href="runHref"
113
+ :to="runHref"
111
114
  target="_blank"
112
115
  rel="noopener noreferrer"
113
116
  class="hover:underline"
114
117
  >
115
118
  {{ record.url }}
116
- </a>
119
+ </ULink>
117
120
  <span v-else>{{ record.url }}</span>
118
121
  </dd>
119
- <UButton
122
+ <IconButton
120
123
  icon="i-lucide-copy"
121
124
  color="neutral"
122
125
  variant="ghost"
123
126
  size="xs"
124
127
  class="ms-auto shrink-0"
125
- :title="t('panels.stepMeta.delegated.copyUrl')"
126
- :aria-label="t('panels.stepMeta.delegated.copyUrl')"
128
+ :label="t('panels.stepMeta.delegated.copyUrl')"
127
129
  @click="copyText(record.url)"
128
130
  />
129
131
  </div>
@@ -132,48 +134,49 @@ const { copy: copyText } = useCopyToClipboard()
132
134
  request. Rendered here because the platform holds nothing else about that run's
133
135
  product. -->
134
136
  <div v-if="landedBranch" class="mt-2 flex items-center gap-2">
135
- <dt class="shrink-0 text-[11px] uppercase tracking-wide text-dimmed">
137
+ <SectionLabel as="dt" class="shrink-0">
136
138
  {{ t('panels.stepMeta.delegated.branch') }}
137
- </dt>
138
- <dd class="truncate font-mono text-[11px] text-toned">{{ landedBranch }}</dd>
139
+ </SectionLabel>
140
+ <dd class="truncate font-mono text-2xs text-toned">{{ landedBranch }}</dd>
139
141
  </div>
140
142
 
141
143
  <!-- What the platform could not do, stated rather than left to read as a clean outcome:
142
144
  a cancelled run whose executor declares no cancel is still going. -->
143
- <p v-if="record.note" class="mt-2 text-[11px] text-toned">{{ record.note }}</p>
145
+ <p v-if="record.note" class="mt-2 text-2xs text-toned">{{ record.note }}</p>
144
146
  </div>
145
147
 
146
148
  <!-- "Absent" and "zero" must never render the same. Without this line a delegated step shows
147
149
  no tokens beside a container step that shows some, and the only available reading is that
148
150
  it was free. -->
149
- <p v-if="usageUnreported" class="mt-2 text-[11px] text-dimmed">
151
+ <p v-if="usageUnreported" class="mt-2 text-2xs text-dimmed">
150
152
  {{ t('panels.stepMeta.delegated.usageNotReported', { executor: executorName }) }}
151
153
  </p>
152
154
 
153
155
  <!-- Earlier attempts. Kept across a re-run on purpose: the previous run's logs are the
154
156
  evidence for why this step is being run again, and the platform holds nothing else. -->
155
157
  <div v-if="priorAttempts.length" class="mt-3">
156
- <div class="text-[11px] uppercase tracking-wide text-dimmed">
158
+ <SectionLabel>
157
159
  {{ t('panels.stepMeta.delegated.earlierAttempts') }}
158
- </div>
160
+ </SectionLabel>
159
161
  <ul class="mt-1 space-y-1">
160
162
  <li
161
163
  v-for="(attempt, index) in priorAttempts"
162
164
  :key="`${attempt.startedAt}-${index}`"
163
- class="flex items-center gap-2 text-[11px] text-muted"
165
+ class="flex items-center gap-2 text-2xs text-muted"
164
166
  >
165
167
  <span class="truncate">{{
166
168
  attempt.outcome || t('panels.stepMeta.delegated.noOutcome')
167
169
  }}</span>
168
- <a
170
+ <ULink
171
+ raw
169
172
  v-if="externalRunHref(attempt.url)"
170
- :href="externalRunHref(attempt.url)!"
173
+ :to="externalRunHref(attempt.url)!"
171
174
  target="_blank"
172
175
  rel="noopener noreferrer"
173
176
  class="ms-auto shrink-0 font-mono hover:underline"
174
177
  >
175
178
  {{ t('panels.stepMeta.delegated.openRun') }}
176
- </a>
179
+ </ULink>
177
180
  </li>
178
181
  </ul>
179
182
  </div>
@@ -10,6 +10,7 @@
10
10
  // second one plus a nested border would just be chrome inside chrome.
11
11
  import type { AgentEffortReport } from '~/types/execution'
12
12
  import { effortBand } from '~/utils/effort'
13
+ import SectionLabel from '~/components/common/SectionLabel.vue'
13
14
 
14
15
  const props = withDefaults(
15
16
  defineProps<{ report: AgentEffortReport; variant?: 'card' | 'flat' }>(),
@@ -37,16 +38,13 @@ const difficultyClass = computed(() => BAR_CLASS[effortBand(props.report.difficu
37
38
  variant === 'card' ? 'scroll-mt-4 rounded-xl border border-default bg-default/50 p-4' : ''
38
39
  "
39
40
  >
40
- <div
41
- v-if="variant === 'card'"
42
- class="mb-2 flex items-center gap-1.5 text-[11px] font-semibold uppercase tracking-wide text-muted"
43
- >
41
+ <SectionLabel v-if="variant === 'card'" class="mb-2 flex items-center gap-1.5">
44
42
  <UIcon name="i-lucide-gauge" class="h-3.5 w-3.5" />
45
43
  <span>{{ t('panels.stepDetail.effort.heading') }}</span>
46
- </div>
44
+ </SectionLabel>
47
45
 
48
46
  <div class="flex items-center gap-2">
49
- <span class="text-[12px] text-toned" :title="t('panels.stepDetail.effort.difficultyHint')">
47
+ <span class="text-xs text-toned" :title="t('panels.stepDetail.effort.difficultyHint')">
50
48
  {{ t('panels.stepDetail.effort.difficulty') }}
51
49
  </span>
52
50
  <div class="h-1.5 flex-1 overflow-hidden rounded-full bg-accented/60">
@@ -58,38 +56,35 @@ const difficultyClass = computed(() => BAR_CLASS[effortBand(props.report.difficu
58
56
  </div>
59
57
  <span
60
58
  data-testid="step-effort-difficulty"
61
- class="text-[12px] font-medium text-default"
59
+ class="text-xs font-medium text-default"
62
60
  :title="t('panels.stepDetail.effort.difficultyHint')"
63
61
  >
64
62
  {{ t('panels.stepDetail.effort.outOfTen', { value: report.difficulty }) }}
65
63
  </span>
66
64
  </div>
67
65
 
68
- <p
69
- v-if="report.summary"
70
- class="mt-2 whitespace-pre-wrap text-[13px] leading-relaxed text-toned"
71
- >
66
+ <p v-if="report.summary" class="mt-2 whitespace-pre-wrap text-sm leading-relaxed text-toned">
72
67
  {{ report.summary }}
73
68
  </p>
74
69
 
75
70
  <div v-if="report.reducedEffectiveness" class="mt-3">
76
- <p class="text-[11px] font-semibold uppercase tracking-wide text-dimmed">
71
+ <SectionLabel as="p">
77
72
  {{ t('panels.stepDetail.effort.reduced') }}
78
- </p>
79
- <p class="mt-0.5 whitespace-pre-wrap text-[12px] text-toned">
73
+ </SectionLabel>
74
+ <p class="mt-0.5 whitespace-pre-wrap text-xs text-toned">
80
75
  {{ report.reducedEffectiveness }}
81
76
  </p>
82
77
  </div>
83
78
 
84
79
  <div v-if="report.obstacles?.length" class="mt-3">
85
- <p class="text-[11px] font-semibold uppercase tracking-wide text-dimmed">
80
+ <SectionLabel as="p">
86
81
  {{ t('panels.stepDetail.effort.obstacles') }}
87
- </p>
82
+ </SectionLabel>
88
83
  <ul class="mt-0.5 space-y-1">
89
84
  <li
90
85
  v-for="(obstacle, i) in report.obstacles"
91
86
  :key="i"
92
- class="flex items-start gap-1.5 text-[12px] text-toned"
87
+ class="flex items-start gap-1.5 text-xs text-toned"
93
88
  >
94
89
  <UIcon
95
90
  name="i-lucide-alert-triangle"