@durablex/react-ui 0.1.0-beta.3

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 (143) hide show
  1. package/LICENSE +202 -0
  2. package/NOTICE +5 -0
  3. package/dist/index.d.ts +1078 -0
  4. package/dist/index.js +6407 -0
  5. package/dist/index.js.map +1 -0
  6. package/package.json +86 -0
  7. package/src/components/AnimatedDurablexMark.tsx +35 -0
  8. package/src/components/AppStatusBadge.tsx +17 -0
  9. package/src/components/AppTag.tsx +17 -0
  10. package/src/components/AppsView.tsx +226 -0
  11. package/src/components/BulkReplayButton.tsx +52 -0
  12. package/src/components/CursorPager.tsx +50 -0
  13. package/src/components/DeliveriesSplit.tsx +187 -0
  14. package/src/components/DeliveryDetail.tsx +188 -0
  15. package/src/components/DurablexLogo.tsx +12 -0
  16. package/src/components/EndpointFormDialog.tsx +153 -0
  17. package/src/components/EndpointRow.tsx +172 -0
  18. package/src/components/EndpointsTab.tsx +83 -0
  19. package/src/components/EventsList.tsx +170 -0
  20. package/src/components/EventsView.tsx +24 -0
  21. package/src/components/Facts.tsx +14 -0
  22. package/src/components/FlowControlBadge.tsx +23 -0
  23. package/src/components/FlowControlSection.tsx +82 -0
  24. package/src/components/FlowSummary.tsx +47 -0
  25. package/src/components/FormField.tsx +10 -0
  26. package/src/components/GlyphBadge.tsx +41 -0
  27. package/src/components/JsonBlock.tsx +48 -0
  28. package/src/components/JsonEditor.tsx +91 -0
  29. package/src/components/LogList.tsx +45 -0
  30. package/src/components/Meta.tsx +31 -0
  31. package/src/components/OverviewView.tsx +39 -0
  32. package/src/components/PayloadTabs.tsx +70 -0
  33. package/src/components/ReceiverFormDialog.tsx +123 -0
  34. package/src/components/ReceiversTab.tsx +194 -0
  35. package/src/components/ReplayRunDialog.tsx +112 -0
  36. package/src/components/ResumeMark.tsx +38 -0
  37. package/src/components/RetryFromStepButton.tsx +44 -0
  38. package/src/components/RunCancelButton.tsx +23 -0
  39. package/src/components/RunControlHistory.tsx +71 -0
  40. package/src/components/RunInspector.test.tsx +78 -0
  41. package/src/components/RunInspector.tsx +297 -0
  42. package/src/components/RunInspectorActions.tsx +40 -0
  43. package/src/components/RunPauseButton.tsx +34 -0
  44. package/src/components/RunnerLiveBadge.tsx +11 -0
  45. package/src/components/RunsFilterBar.tsx +180 -0
  46. package/src/components/RunsTable.tsx +110 -0
  47. package/src/components/RunsTableHead.tsx +19 -0
  48. package/src/components/RunsTableLoader.tsx +10 -0
  49. package/src/components/RunsTablePlaceholder.tsx +19 -0
  50. package/src/components/RunsTableRow.tsx +103 -0
  51. package/src/components/RunsView.test.tsx +46 -0
  52. package/src/components/RunsView.tsx +243 -0
  53. package/src/components/ScheduledBadge.tsx +15 -0
  54. package/src/components/SecretReveal.tsx +45 -0
  55. package/src/components/SectionHeader.tsx +10 -0
  56. package/src/components/StatTileGrid.tsx +71 -0
  57. package/src/components/StatsTiles.tsx +66 -0
  58. package/src/components/StatusBadge.tsx +50 -0
  59. package/src/components/StepFlow.tsx +105 -0
  60. package/src/components/StepGlyph.tsx +25 -0
  61. package/src/components/StepInspector.tsx +44 -0
  62. package/src/components/StepRow.tsx +69 -0
  63. package/src/components/StepTabsView.tsx +51 -0
  64. package/src/components/StepTimeline.tsx +87 -0
  65. package/src/components/TableStatusRows.tsx +54 -0
  66. package/src/components/TriggerEventDialog.tsx +180 -0
  67. package/src/components/TriggerEventResult.tsx +61 -0
  68. package/src/components/WebhookBadges.tsx +69 -0
  69. package/src/components/WebhookStatusBadge.tsx +25 -0
  70. package/src/components/WebhooksView.tsx +69 -0
  71. package/src/components/WorkflowDetail.tsx +149 -0
  72. package/src/components/WorkflowRunAction.tsx +46 -0
  73. package/src/components/WorkflowRunDialog.tsx +187 -0
  74. package/src/components/WorkflowsView.tsx +168 -0
  75. package/src/components/charts/ChartCard.tsx +19 -0
  76. package/src/components/charts/RunCharts.tsx +31 -0
  77. package/src/components/charts/RunLatencyChart.tsx +71 -0
  78. package/src/components/charts/RunsOverTimeChart.tsx +60 -0
  79. package/src/components/filters/AppFilter.tsx +65 -0
  80. package/src/components/filters/FilterDropdown.tsx +33 -0
  81. package/src/components/filters/FilterDropdownButton.tsx +31 -0
  82. package/src/components/filters/FilterDropdownItem.tsx +37 -0
  83. package/src/components/filters/TimeRangeFilter.tsx +43 -0
  84. package/src/components/filters/TimeZoneFilter.tsx +40 -0
  85. package/src/components/filters/use-click-outside.ts +18 -0
  86. package/src/components/filters-pager.test.tsx +94 -0
  87. package/src/components/marks-geometry.ts +10 -0
  88. package/src/components/replay-dialog.test.tsx +18 -0
  89. package/src/components/run-components.test.tsx +126 -0
  90. package/src/components/run-controls.test.tsx +97 -0
  91. package/src/hooks/use-confirm-action.ts +19 -0
  92. package/src/hooks/use-copy.ts +22 -0
  93. package/src/hooks/use-keyset-pager.ts +34 -0
  94. package/src/hooks/use-mobile.ts +16 -0
  95. package/src/index.ts +165 -0
  96. package/src/lib/app-color.test.ts +32 -0
  97. package/src/lib/app-color.ts +8 -0
  98. package/src/lib/control-action.ts +36 -0
  99. package/src/lib/flow-control.ts +77 -0
  100. package/src/lib/format.test.ts +102 -0
  101. package/src/lib/format.ts +45 -0
  102. package/src/lib/json-highlight.test.ts +36 -0
  103. package/src/lib/json-highlight.ts +64 -0
  104. package/src/lib/run-filters.ts +8 -0
  105. package/src/lib/run-logs.test.ts +80 -0
  106. package/src/lib/run-logs.ts +34 -0
  107. package/src/lib/run-progress.test.ts +109 -0
  108. package/src/lib/run-progress.ts +44 -0
  109. package/src/lib/run-sort.test.ts +40 -0
  110. package/src/lib/run-sort.ts +19 -0
  111. package/src/lib/status-label.test.ts +35 -0
  112. package/src/lib/status-label.ts +13 -0
  113. package/src/lib/step-detail.test.ts +122 -0
  114. package/src/lib/step-detail.ts +35 -0
  115. package/src/lib/step-display.test.ts +19 -0
  116. package/src/lib/step-display.ts +13 -0
  117. package/src/lib/step-timeline.test.ts +89 -0
  118. package/src/lib/step-timeline.ts +50 -0
  119. package/src/lib/table.ts +2 -0
  120. package/src/lib/theme.ts +35 -0
  121. package/src/lib/time-range.ts +81 -0
  122. package/src/lib/utils.ts +6 -0
  123. package/src/lib/webhook-view.test.ts +176 -0
  124. package/src/lib/webhook-view.ts +113 -0
  125. package/src/lib/workflow-run.test.ts +55 -0
  126. package/src/lib/workflow-run.ts +45 -0
  127. package/src/shell/AppShell.tsx +34 -0
  128. package/src/shell/Sidebar.tsx +78 -0
  129. package/src/shell/Topbar.tsx +22 -0
  130. package/src/styles.css +2204 -0
  131. package/src/test-utils.tsx +130 -0
  132. package/src/ui/button.tsx +67 -0
  133. package/src/ui/chart.tsx +337 -0
  134. package/src/ui/dialog.tsx +145 -0
  135. package/src/ui/input.tsx +19 -0
  136. package/src/ui/resizable.tsx +40 -0
  137. package/src/ui/separator.tsx +28 -0
  138. package/src/ui/sheet.tsx +128 -0
  139. package/src/ui/sidebar.tsx +665 -0
  140. package/src/ui/skeleton.tsx +15 -0
  141. package/src/ui/sonner.tsx +35 -0
  142. package/src/ui/table.tsx +87 -0
  143. package/src/ui/tooltip.tsx +51 -0
package/src/styles.css ADDED
@@ -0,0 +1,2204 @@
1
+ @theme inline {
2
+ --font-heading: var(--font-sans);
3
+ --font-sans: 'Geist Variable', sans-serif;
4
+ --font-mono: 'JetBrains Mono Variable', ui-monospace, 'SF Mono', Menlo, monospace;
5
+ --color-sidebar-ring: var(--sidebar-ring);
6
+ --color-sidebar-border: var(--sidebar-border);
7
+ --color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
8
+ --color-sidebar-accent: var(--sidebar-accent);
9
+ --color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
10
+ --color-sidebar-primary: var(--sidebar-primary);
11
+ --color-sidebar-foreground: var(--sidebar-foreground);
12
+ --color-sidebar: var(--sidebar);
13
+ --color-chart-5: var(--chart-5);
14
+ --color-chart-4: var(--chart-4);
15
+ --color-chart-3: var(--chart-3);
16
+ --color-chart-2: var(--chart-2);
17
+ --color-chart-1: var(--chart-1);
18
+ --color-ring: var(--ring);
19
+ --color-input: var(--input);
20
+ --color-border: var(--border);
21
+ --color-destructive: var(--destructive);
22
+ --color-destructive-foreground: var(--destructive-foreground);
23
+ --color-accent-foreground: var(--accent-foreground);
24
+ --color-accent: var(--accent);
25
+ --color-muted-foreground: var(--muted-foreground);
26
+ --color-muted: var(--muted);
27
+ --color-secondary-foreground: var(--secondary-foreground);
28
+ --color-secondary: var(--secondary);
29
+ --color-primary-foreground: var(--primary-foreground);
30
+ --color-primary: var(--primary);
31
+ --color-popover-foreground: var(--popover-foreground);
32
+ --color-popover: var(--popover);
33
+ --color-card-foreground: var(--card-foreground);
34
+ --color-card: var(--card);
35
+ --color-foreground: var(--foreground);
36
+ --color-background: var(--background);
37
+ --radius-sm: calc(var(--radius) * 0.6);
38
+ --radius-md: calc(var(--radius) * 0.8);
39
+ --radius-lg: var(--radius);
40
+ --radius-xl: calc(var(--radius) * 1.4);
41
+ --radius-2xl: calc(var(--radius) * 1.8);
42
+ --radius-3xl: calc(var(--radius) * 2.2);
43
+ --radius-4xl: calc(var(--radius) * 2.6);
44
+ }
45
+
46
+ @theme {
47
+ --spacing: 0.2rem;
48
+ --shadow-2xs: 0 0 #0000;
49
+ --shadow-xs: 0 0 #0000;
50
+ --shadow-sm: 0 0 #0000;
51
+ --shadow-md: 0 0 #0000;
52
+ --shadow-lg: 0 0 #0000;
53
+ --shadow-xl: 0 0 #0000;
54
+ --shadow-2xl: 0 0 #0000;
55
+ }
56
+
57
+ :root {
58
+ --radius: 0rem;
59
+ --background: oklch(0.985 0.001 250);
60
+ --foreground: oklch(0.205 0.005 260);
61
+ --card: oklch(1 0 0);
62
+ --card-foreground: oklch(0.205 0.005 260);
63
+ --popover: oklch(1 0 0);
64
+ --popover-foreground: oklch(0.205 0.005 260);
65
+ --primary: oklch(0.52 0.2 277);
66
+ --primary-foreground: oklch(0.985 0.005 277);
67
+ --secondary: oklch(0.962 0.002 260);
68
+ --secondary-foreground: oklch(0.255 0.005 260);
69
+ --muted: oklch(0.967 0.002 260);
70
+ --muted-foreground: oklch(0.52 0.007 260);
71
+ --accent: oklch(0.958 0.003 260);
72
+ --accent-foreground: oklch(0.255 0.005 260);
73
+ --destructive: oklch(0.553 0.21 26);
74
+ --destructive-foreground: oklch(0.985 0.004 26);
75
+ --border: oklch(0.917 0.003 260);
76
+ --input: oklch(0.917 0.003 260);
77
+ --ring: oklch(0.52 0.2 277);
78
+ --chart-1: oklch(0.52 0.2 277);
79
+ --chart-2: oklch(0.64 0.12 195);
80
+ --chart-3: oklch(0.61 0.145 145);
81
+ --chart-4: oklch(0.705 0.13 75);
82
+ --chart-5: oklch(0.59 0.17 15);
83
+ --sidebar: oklch(0.974 0.002 260);
84
+ --sidebar-foreground: oklch(0.3 0.005 260);
85
+ --sidebar-primary: oklch(0.52 0.2 277);
86
+ --sidebar-primary-foreground: oklch(0.985 0.002 260);
87
+ --sidebar-accent: oklch(0.94 0.003 260);
88
+ --sidebar-accent-foreground: oklch(0.205 0.005 260);
89
+ --sidebar-border: oklch(0.917 0.003 260);
90
+ --sidebar-ring: oklch(0.52 0.2 277);
91
+ --dx-fault: oklch(0.553 0.21 26);
92
+
93
+ /* run/step status palette (bg + fg). "waiting" mirrors "running". */
94
+ --st-queued-bg: oklch(0.95 0.009 260);
95
+ --st-queued-fg: oklch(0.47 0.018 260);
96
+ --st-running-bg: oklch(0.94 0.043 245);
97
+ --st-running-fg: oklch(0.5 0.155 252);
98
+ --st-waiting-bg: oklch(0.94 0.043 245);
99
+ --st-waiting-fg: oklch(0.5 0.155 252);
100
+ --st-succeeded-bg: oklch(0.945 0.048 158);
101
+ --st-succeeded-fg: oklch(0.48 0.125 159);
102
+ --st-failed-bg: oklch(0.952 0.033 26);
103
+ --st-failed-fg: oklch(0.53 0.205 27);
104
+ --st-cancelled-bg: oklch(0.952 0.003 260);
105
+ --st-cancelled-fg: oklch(0.54 0.009 260);
106
+ --st-skipped-bg: oklch(0.964 0.0025 260);
107
+ --st-skipped-fg: oklch(0.6 0.007 260);
108
+ --st-paused-bg: oklch(0.952 0.044 85);
109
+ --st-paused-fg: oklch(0.52 0.12 75);
110
+ --st-scheduled-bg: oklch(0.95 0.032 292);
111
+ --st-scheduled-fg: oklch(0.52 0.16 292);
112
+ }
113
+
114
+ .dark {
115
+ --background: oklch(0.165 0.004 255);
116
+ --foreground: oklch(0.962 0.003 255);
117
+ --card: oklch(0.196 0.005 255);
118
+ --card-foreground: oklch(0.962 0.003 255);
119
+ --popover: oklch(0.196 0.005 255);
120
+ --popover-foreground: oklch(0.962 0.003 255);
121
+ --primary: oklch(0.66 0.17 277);
122
+ --primary-foreground: oklch(0.18 0.03 277);
123
+ --secondary: oklch(0.25 0.006 255);
124
+ --secondary-foreground: oklch(0.962 0.003 255);
125
+ --muted: oklch(0.235 0.006 255);
126
+ --muted-foreground: oklch(0.68 0.009 255);
127
+ --accent: oklch(0.258 0.007 255);
128
+ --accent-foreground: oklch(0.962 0.003 255);
129
+ --destructive: oklch(0.62 0.19 26);
130
+ --destructive-foreground: oklch(0.985 0.004 26);
131
+ --border: oklch(0.275 0.007 255);
132
+ --input: oklch(0.3 0.008 255);
133
+ --ring: oklch(0.66 0.17 277);
134
+ --chart-1: oklch(0.66 0.17 277);
135
+ --chart-2: oklch(0.7 0.12 195);
136
+ --chart-3: oklch(0.68 0.145 145);
137
+ --chart-4: oklch(0.76 0.13 75);
138
+ --chart-5: oklch(0.66 0.17 15);
139
+ --sidebar: oklch(0.185 0.005 255);
140
+ --sidebar-foreground: oklch(0.78 0.007 255);
141
+ --sidebar-primary: oklch(0.66 0.17 277);
142
+ --sidebar-primary-foreground: oklch(0.985 0.002 255);
143
+ --sidebar-accent: oklch(0.248 0.007 255);
144
+ --sidebar-accent-foreground: oklch(0.962 0.003 255);
145
+ --sidebar-border: oklch(0.258 0.007 255);
146
+ --sidebar-ring: oklch(0.66 0.17 277);
147
+ --dx-fault: oklch(0.7 0.175 27);
148
+
149
+ --st-queued-bg: oklch(0.272 0.018 255);
150
+ --st-queued-fg: oklch(0.76 0.042 255);
151
+ --st-running-bg: oklch(0.285 0.056 250);
152
+ --st-running-fg: oklch(0.8 0.128 245);
153
+ --st-waiting-bg: oklch(0.285 0.056 250);
154
+ --st-waiting-fg: oklch(0.8 0.128 245);
155
+ --st-succeeded-bg: oklch(0.28 0.056 159);
156
+ --st-succeeded-fg: oklch(0.81 0.14 160);
157
+ --st-failed-bg: oklch(0.29 0.072 26);
158
+ --st-failed-fg: oklch(0.79 0.155 28);
159
+ --st-cancelled-bg: oklch(0.262 0.005 255);
160
+ --st-cancelled-fg: oklch(0.66 0.01 255);
161
+ --st-skipped-bg: oklch(0.232 0.005 255);
162
+ --st-skipped-fg: oklch(0.58 0.008 255);
163
+ --st-paused-bg: oklch(0.29 0.05 85);
164
+ --st-paused-fg: oklch(0.8 0.12 85);
165
+ --st-scheduled-bg: oklch(0.285 0.05 292);
166
+ --st-scheduled-fg: oklch(0.8 0.13 292);
167
+ }
168
+
169
+ @layer base {
170
+ * {
171
+ @apply border-border outline-ring/50;
172
+ }
173
+ body {
174
+ @apply bg-background text-foreground;
175
+ }
176
+ html {
177
+ @apply font-sans;
178
+ }
179
+ /* Tailwind v4 Preflight drops the default pointer cursor on buttons; restore it. */
180
+ button:not(:disabled),
181
+ [role="button"]:not(:disabled) {
182
+ cursor: pointer;
183
+ }
184
+ }
185
+
186
+ /* Pin the shell to the viewport so scrolling stays inside the sidebar, run list,
187
+ and detail sheet, never the whole page. (!important beats SidebarProvider's
188
+ inline --sidebar-width.) */
189
+ [data-slot="sidebar-wrapper"] {
190
+ --sidebar-width: 12rem !important;
191
+ height: 100svh;
192
+ overflow: hidden;
193
+ }
194
+
195
+ /* sharp everywhere: un-layered so it wins over Tailwind's rounded-* utility layer */
196
+ *,
197
+ ::before,
198
+ ::after {
199
+ border-radius: 0;
200
+ }
201
+
202
+ /* slim resize divider: drop the grab knob and the handle's own line so the only
203
+ divider is the detail panel's hairline left border; the handle stays an
204
+ invisible drag strip. */
205
+ [data-slot="resizable-handle"] {
206
+ background-color: transparent;
207
+ }
208
+ [data-slot="resizable-handle"] > div {
209
+ display: none;
210
+ }
211
+
212
+ /* brand mark: loops a crash -> resume cycle (the Resume-D telling its own story) */
213
+ .dx-mark .dx-bars,
214
+ .dx-mark .dx-fault,
215
+ .dx-mark .dx-resume {
216
+ transform-box: fill-box;
217
+ transform-origin: center;
218
+ }
219
+ .dx-mark .dx-resume {
220
+ transform-origin: 13px 12px;
221
+ }
222
+ .dx-mark .dx-fault {
223
+ opacity: 0;
224
+ }
225
+ .dx-mark .dx-bars {
226
+ animation: dx-bars-glitch 4s linear infinite;
227
+ }
228
+ .dx-mark .dx-fault {
229
+ animation: dx-fault-flash 4s linear infinite;
230
+ }
231
+ .dx-mark .dx-resume {
232
+ animation: dx-resume-cycle 4s linear infinite;
233
+ }
234
+ @keyframes dx-bars-glitch {
235
+ 0%, 54% { transform: translateX(0); }
236
+ 56% { transform: translateX(0.7px); }
237
+ 58% { transform: translateX(-0.5px); }
238
+ 60% { transform: translateX(0.3px); }
239
+ 62%, 100% { transform: translateX(0); }
240
+ }
241
+ @keyframes dx-fault-flash {
242
+ 0%, 54% { opacity: 0; transform: translateX(0); }
243
+ 56% { opacity: 0.92; transform: translateX(0.9px); }
244
+ 59% { opacity: 0.5; transform: translateX(-0.6px); }
245
+ 62%, 100% { opacity: 0; }
246
+ }
247
+ @keyframes dx-resume-cycle {
248
+ 0%, 40% { opacity: 1; transform: scaleX(1); }
249
+ 44% { opacity: 1; transform: scaleX(1.04); }
250
+ 48%, 62% { opacity: 0; transform: scaleX(0.55) translateX(-1px); }
251
+ 70% { opacity: 1; transform: scaleX(0.55); }
252
+ 82% { transform: scaleX(1.05); }
253
+ 88%, 100% { opacity: 1; transform: scaleX(1); }
254
+ }
255
+ @media (prefers-reduced-motion: reduce) {
256
+ .dx-mark .dx-bars,
257
+ .dx-mark .dx-fault,
258
+ .dx-mark .dx-resume {
259
+ animation: none;
260
+ }
261
+ .dx-mark .dx-fault {
262
+ opacity: 0;
263
+ }
264
+ .dx-mark .dx-resume {
265
+ opacity: 1;
266
+ }
267
+ }
268
+
269
+ /* in-app resume mark: status heartbeat (run) + crash->resume loader (load).
270
+ Smaller/faster than the brand logo; tinted per status via --dxm-accent. */
271
+ .dxmark {
272
+ display: inline-grid;
273
+ place-items: center;
274
+ line-height: 0;
275
+ flex-shrink: 0;
276
+ }
277
+ .dxmark svg {
278
+ display: block;
279
+ }
280
+ .dxmark .dxm-fault {
281
+ opacity: 0;
282
+ }
283
+ .dxm-run .dxm-tri {
284
+ transform-box: fill-box;
285
+ transform-origin: center;
286
+ animation: dxmPulse 1.5s ease-in-out infinite;
287
+ }
288
+ @keyframes dxmPulse {
289
+ 0%, 100% { opacity: 0.5; transform: scale(0.84); }
290
+ 50% { opacity: 1; transform: scale(1); }
291
+ }
292
+ .dxm-load .dxm-bars {
293
+ transform-box: fill-box;
294
+ transform-origin: center;
295
+ animation: dxmLoadBars 1.3s linear infinite;
296
+ }
297
+ .dxm-load .dxm-fault {
298
+ transform-box: fill-box;
299
+ transform-origin: center;
300
+ animation: dxmLoadFault 1.3s linear infinite;
301
+ }
302
+ .dxm-load .dxm-tri {
303
+ transform-box: fill-box;
304
+ transform-origin: 13px 12px;
305
+ animation: dxmLoadTri 1.3s linear infinite;
306
+ }
307
+ @keyframes dxmLoadBars {
308
+ 0%, 52% { transform: translateX(0); }
309
+ 58% { transform: translateX(0.8px); }
310
+ 63% { transform: translateX(-0.5px); }
311
+ 68%, 100% { transform: translateX(0); }
312
+ }
313
+ @keyframes dxmLoadFault {
314
+ 0%, 52% { opacity: 0; }
315
+ 58% { opacity: 0.92; }
316
+ 65% { opacity: 0; }
317
+ 100% { opacity: 0; }
318
+ }
319
+ @keyframes dxmLoadTri {
320
+ 0%, 40% { opacity: 1; transform: scaleX(1); }
321
+ 48%, 60% { opacity: 0; transform: scaleX(0.5) translateX(-1px); }
322
+ 70% { opacity: 1; transform: scaleX(0.5); }
323
+ 84%, 100% { opacity: 1; transform: scaleX(1); }
324
+ }
325
+ @media (prefers-reduced-motion: reduce) {
326
+ .dxmark .dxm-bars,
327
+ .dxmark .dxm-tri,
328
+ .dxmark .dxm-fault {
329
+ animation: none !important;
330
+ }
331
+ .dxmark .dxm-fault {
332
+ opacity: 0;
333
+ }
334
+ }
335
+
336
+ /* status badge: tint the live mark to the running/waiting status colour
337
+ (running and waiting share the same --st token values) */
338
+ .badge-mark {
339
+ color: var(--st-running-fg);
340
+ --dxm-accent: var(--st-running-fg);
341
+ }
342
+
343
+ /* stat tiles: the Active tile's live mark carries the running colour */
344
+ .stat-mark {
345
+ color: var(--st-running-fg);
346
+ --dxm-accent: var(--st-running-fg);
347
+ }
348
+
349
+ /* ── Runs filter bar (search field + time/status/app/run-type dropdowns) ─── */
350
+ .focusable:focus-visible {
351
+ outline: 2px solid var(--ring);
352
+ outline-offset: -1px;
353
+ position: relative;
354
+ z-index: 2;
355
+ }
356
+ .filterbar {
357
+ display: flex;
358
+ align-items: center;
359
+ gap: 6px;
360
+ flex-wrap: wrap;
361
+ padding: 7px 12px;
362
+ border-bottom: 1px solid var(--border);
363
+ flex-shrink: 0;
364
+ }
365
+ .fb-spacer {
366
+ flex: 1;
367
+ }
368
+ .fb-meta {
369
+ font-size: 11.5px;
370
+ color: var(--muted-foreground);
371
+ font-family: var(--font-mono);
372
+ white-space: nowrap;
373
+ }
374
+ .fb-btn {
375
+ height: 26px;
376
+ padding: 0 8px;
377
+ border: 1px solid var(--input);
378
+ background: var(--card);
379
+ color: var(--foreground);
380
+ font-size: 12px;
381
+ cursor: pointer;
382
+ white-space: nowrap;
383
+ display: inline-flex;
384
+ align-items: center;
385
+ gap: 6px;
386
+ }
387
+ .fb-btn:hover {
388
+ background: var(--accent);
389
+ }
390
+ .fb-btn svg {
391
+ width: 13px;
392
+ height: 13px;
393
+ opacity: 0.75;
394
+ }
395
+ .fb-search-field {
396
+ display: flex;
397
+ align-items: center;
398
+ gap: 7px;
399
+ height: 26px;
400
+ padding: 0 9px;
401
+ border: 1px solid var(--input);
402
+ background: var(--card);
403
+ width: 212px;
404
+ flex: 0 0 auto;
405
+ }
406
+ .fb-search-field svg {
407
+ width: 13px;
408
+ height: 13px;
409
+ flex-shrink: 0;
410
+ color: var(--muted-foreground);
411
+ }
412
+ .fb-search-field input {
413
+ border: 0;
414
+ background: transparent;
415
+ outline: none;
416
+ color: var(--foreground);
417
+ font: inherit;
418
+ font-size: 12.5px;
419
+ width: 100%;
420
+ }
421
+ .fb-search-field input::placeholder {
422
+ color: var(--muted-foreground);
423
+ }
424
+ .fb-search-field .x {
425
+ cursor: pointer;
426
+ opacity: 0.6;
427
+ display: inline-grid;
428
+ place-items: center;
429
+ }
430
+ .fb-search-field .x:hover {
431
+ opacity: 1;
432
+ }
433
+ .fb-search-field:focus-within {
434
+ border-color: var(--ring);
435
+ }
436
+ .dd {
437
+ position: relative;
438
+ display: inline-flex;
439
+ }
440
+ .dd-btn {
441
+ height: 26px;
442
+ padding: 0 7px 0 9px;
443
+ border: 1px solid var(--input);
444
+ background: var(--card);
445
+ color: var(--foreground);
446
+ font-size: 12px;
447
+ cursor: pointer;
448
+ white-space: nowrap;
449
+ display: inline-flex;
450
+ align-items: center;
451
+ gap: 7px;
452
+ }
453
+ .dd-btn:hover {
454
+ background: var(--accent);
455
+ }
456
+ .dd-btn[data-open='1'] {
457
+ border-color: var(--ring);
458
+ background: var(--accent);
459
+ }
460
+ .dd-btn .dd-key {
461
+ color: var(--muted-foreground);
462
+ }
463
+ .dd-btn .dd-val {
464
+ font-weight: 500;
465
+ }
466
+ .dd-btn .dd-val .vdot {
467
+ display: inline-block;
468
+ width: 6px;
469
+ height: 6px;
470
+ border-radius: 50%;
471
+ margin-right: 6px;
472
+ vertical-align: middle;
473
+ }
474
+ .dd-btn .dd-chev {
475
+ width: 12px;
476
+ height: 12px;
477
+ opacity: 0.6;
478
+ margin-left: 1px;
479
+ }
480
+ .dd-menu {
481
+ position: absolute;
482
+ top: calc(100% + 3px);
483
+ left: 0;
484
+ z-index: 40;
485
+ min-width: 184px;
486
+ max-height: 320px;
487
+ overflow: auto;
488
+ background: var(--popover);
489
+ color: var(--popover-foreground);
490
+ border: 1px solid var(--border);
491
+ }
492
+ .dd-menu.right {
493
+ left: auto;
494
+ right: 0;
495
+ }
496
+ .dd-search {
497
+ padding: 7px;
498
+ border-bottom: 1px solid var(--border);
499
+ }
500
+ .dd-search input {
501
+ width: 100%;
502
+ height: 28px;
503
+ border: 1px solid var(--input);
504
+ background: var(--card);
505
+ color: var(--foreground);
506
+ font: inherit;
507
+ font-size: 12px;
508
+ padding: 0 8px;
509
+ outline: none;
510
+ }
511
+ .dd-search input:focus {
512
+ border-color: var(--ring);
513
+ }
514
+ .dd-item {
515
+ display: flex;
516
+ align-items: center;
517
+ gap: 8px;
518
+ width: 100%;
519
+ padding: 7px 10px;
520
+ border: 0;
521
+ background: transparent;
522
+ cursor: pointer;
523
+ color: var(--popover-foreground);
524
+ font: inherit;
525
+ font-size: 12.5px;
526
+ text-align: left;
527
+ }
528
+ .dd-item:hover {
529
+ background: var(--accent);
530
+ }
531
+ .dd-item .dd-dot {
532
+ width: 7px;
533
+ height: 7px;
534
+ border-radius: 50%;
535
+ flex-shrink: 0;
536
+ }
537
+ .dd-item .dd-lbl {
538
+ flex: 1;
539
+ }
540
+ .dd-item .dd-rt {
541
+ font-family: var(--font-mono);
542
+ font-size: 11px;
543
+ color: var(--muted-foreground);
544
+ }
545
+ .dd-item .dd-check {
546
+ width: 13px;
547
+ height: 13px;
548
+ color: var(--primary);
549
+ flex-shrink: 0;
550
+ }
551
+ .dd-item[data-on='1'] {
552
+ font-weight: 500;
553
+ }
554
+ .dd-sep {
555
+ height: 1px;
556
+ background: var(--border);
557
+ margin: 0;
558
+ }
559
+ /* ── Stat tiles ────────────────────────────────────────────────────────── */
560
+ .stats {
561
+ display: grid;
562
+ grid-template-columns: repeat(4, 1fr);
563
+ border-bottom: 1px solid var(--border);
564
+ flex-shrink: 0;
565
+ }
566
+ .stat {
567
+ padding: 9px 13px 10px;
568
+ border-right: 1px solid var(--border);
569
+ display: flex;
570
+ flex-direction: column;
571
+ gap: 4px;
572
+ background: var(--card);
573
+ }
574
+ .stat:last-child {
575
+ border-right: 0;
576
+ }
577
+ .stat-btn {
578
+ font: inherit;
579
+ text-align: left;
580
+ width: 100%;
581
+ border-top: 0;
582
+ border-bottom: 0;
583
+ border-left: 0;
584
+ cursor: pointer;
585
+ transition: background 0.1s;
586
+ }
587
+ .stat-btn:hover {
588
+ background: var(--muted);
589
+ }
590
+ .stat-btn[data-active='1'] {
591
+ background: var(--muted);
592
+ }
593
+ .stat-top {
594
+ display: flex;
595
+ align-items: center;
596
+ gap: 7px;
597
+ }
598
+ .stat-dot {
599
+ width: 7px;
600
+ height: 7px;
601
+ flex-shrink: 0;
602
+ }
603
+ .stat-label {
604
+ font-size: 11px;
605
+ font-weight: 500;
606
+ letter-spacing: 0.01em;
607
+ color: var(--muted-foreground);
608
+ }
609
+ .stat-val {
610
+ font-family: var(--font-mono);
611
+ font-size: 23px;
612
+ font-weight: 600;
613
+ font-variant-numeric: tabular-nums;
614
+ letter-spacing: -0.02em;
615
+ line-height: 1;
616
+ color: var(--foreground);
617
+ }
618
+ .stat-sub {
619
+ font-size: 11px;
620
+ color: var(--muted-foreground);
621
+ font-family: var(--font-mono);
622
+ font-variant-numeric: tabular-nums;
623
+ }
624
+ .stat-sub .up {
625
+ color: var(--st-succeeded-fg);
626
+ }
627
+ .stat-sub .down {
628
+ color: var(--st-failed-fg);
629
+ }
630
+
631
+ /* ── Runs table ────────────────────────────────────────────────────────── */
632
+ .tablewrap {
633
+ flex: 1;
634
+ min-height: 0;
635
+ overflow: auto;
636
+ }
637
+ table.runs {
638
+ width: 100%;
639
+ border-collapse: collapse;
640
+ font-size: 12.5px;
641
+ }
642
+ table.runs thead th {
643
+ position: sticky;
644
+ top: 0;
645
+ z-index: 1;
646
+ background: var(--muted);
647
+ color: var(--muted-foreground);
648
+ font-weight: 500;
649
+ font-size: 11px;
650
+ letter-spacing: 0.02em;
651
+ text-align: left;
652
+ padding: 5px 11px;
653
+ white-space: nowrap;
654
+ border-bottom: 1px solid var(--border);
655
+ user-select: none;
656
+ }
657
+ table.runs thead th.sortable {
658
+ cursor: pointer;
659
+ }
660
+ table.runs thead th.sortable:hover {
661
+ color: var(--foreground);
662
+ }
663
+ table.runs thead th .arrow {
664
+ color: var(--primary);
665
+ margin-left: 3px;
666
+ }
667
+ table.runs thead th.num,
668
+ table.runs td.num {
669
+ text-align: right;
670
+ }
671
+ table.runs tbody td {
672
+ padding: 0 11px;
673
+ height: 27px;
674
+ border-bottom: 1px solid var(--border);
675
+ white-space: nowrap;
676
+ vertical-align: middle;
677
+ }
678
+ table.runs tbody tr {
679
+ cursor: pointer;
680
+ }
681
+ table.runs tbody tr:hover td {
682
+ background: var(--accent);
683
+ }
684
+ table.runs tbody tr[data-selected='1'] td {
685
+ background: color-mix(in oklch, var(--primary) 13%, var(--card));
686
+ }
687
+ table.runs tbody tr[data-selected='1'] td:first-child {
688
+ box-shadow: inset 2px 0 0 var(--primary);
689
+ }
690
+ table.runs td.row-actions {
691
+ width: 1%;
692
+ text-align: right;
693
+ padding-right: 8px;
694
+ }
695
+ .row-action {
696
+ display: inline-flex;
697
+ align-items: center;
698
+ gap: 4px;
699
+ padding: 2px 7px;
700
+ font-size: 11px;
701
+ color: var(--muted-foreground);
702
+ border: 1px solid transparent;
703
+ background: transparent;
704
+ cursor: pointer;
705
+ opacity: 0;
706
+ }
707
+ table.runs tbody tr:hover .row-action,
708
+ table.runs tbody tr:focus-within .row-action {
709
+ opacity: 1;
710
+ }
711
+ .row-action:hover {
712
+ color: var(--foreground);
713
+ border-color: var(--border);
714
+ background: var(--card);
715
+ }
716
+ .wf-cell {
717
+ display: flex;
718
+ align-items: center;
719
+ gap: 9px;
720
+ }
721
+ .wf-name {
722
+ font-weight: 500;
723
+ color: var(--foreground);
724
+ }
725
+ .cell-mut {
726
+ color: var(--muted-foreground);
727
+ }
728
+ .step-cell {
729
+ display: flex;
730
+ align-items: center;
731
+ gap: 7px;
732
+ color: var(--muted-foreground);
733
+ }
734
+ .step-cell .ix {
735
+ font-family: var(--font-mono);
736
+ font-size: 11px;
737
+ color: var(--muted-foreground);
738
+ }
739
+ .run-err {
740
+ color: var(--st-failed-fg);
741
+ font-size: 11.5px;
742
+ max-width: 320px;
743
+ overflow: hidden;
744
+ text-overflow: ellipsis;
745
+ white-space: nowrap;
746
+ }
747
+ .dur,
748
+ .ts {
749
+ font-family: var(--font-mono);
750
+ font-variant-numeric: tabular-nums;
751
+ font-size: 12px;
752
+ }
753
+
754
+ /* runs table branded loader */
755
+ .runloader {
756
+ min-height: 320px;
757
+ display: flex;
758
+ flex-direction: column;
759
+ align-items: center;
760
+ justify-content: center;
761
+ gap: 14px;
762
+ padding: 60px 0;
763
+ }
764
+ .loadmark {
765
+ color: var(--foreground);
766
+ --dxm-accent: var(--primary);
767
+ }
768
+ .runloader-cap {
769
+ font-family: var(--font-mono);
770
+ font-size: 11.5px;
771
+ letter-spacing: 0.02em;
772
+ color: var(--muted-foreground);
773
+ }
774
+
775
+ /* runs table empty / error placeholder */
776
+ .placeholder {
777
+ display: grid;
778
+ place-items: center;
779
+ padding: 40px;
780
+ }
781
+ .ph-inner {
782
+ text-align: center;
783
+ max-width: 280px;
784
+ color: var(--muted-foreground);
785
+ }
786
+ .ph-inner .ico {
787
+ width: 30px;
788
+ height: 30px;
789
+ margin: 0 auto 12px;
790
+ color: var(--muted-foreground);
791
+ opacity: 0.7;
792
+ }
793
+ .ph-inner h3 {
794
+ font-size: 13px;
795
+ font-weight: 600;
796
+ color: var(--foreground);
797
+ margin: 0 0 5px;
798
+ }
799
+ .ph-inner p {
800
+ font-size: 12px;
801
+ margin: 0;
802
+ line-height: 1.5;
803
+ }
804
+
805
+ /* ── Pagination ────────────────────────────────────────────────────────── */
806
+ .pager {
807
+ display: flex;
808
+ align-items: center;
809
+ gap: 10px;
810
+ padding: 7px 12px;
811
+ border-top: 1px solid var(--border);
812
+ flex-shrink: 0;
813
+ background: var(--background);
814
+ }
815
+ .pager-range {
816
+ font-family: var(--font-mono);
817
+ font-size: 11.5px;
818
+ color: var(--foreground);
819
+ font-variant-numeric: tabular-nums;
820
+ }
821
+ .pager-range .pg-mut {
822
+ color: var(--muted-foreground);
823
+ }
824
+ .pager-nav {
825
+ display: flex;
826
+ align-items: center;
827
+ gap: 2px;
828
+ }
829
+ .pg-btn {
830
+ min-width: 25px;
831
+ height: 25px;
832
+ padding: 0 6px;
833
+ border: 1px solid transparent;
834
+ background: transparent;
835
+ color: var(--foreground);
836
+ font: inherit;
837
+ font-size: 12px;
838
+ font-variant-numeric: tabular-nums;
839
+ cursor: pointer;
840
+ display: inline-grid;
841
+ place-items: center;
842
+ }
843
+ .pg-btn:hover:not(:disabled) {
844
+ background: var(--accent);
845
+ }
846
+ .pg-btn[data-on='1'] {
847
+ background: var(--accent);
848
+ border-color: var(--border);
849
+ font-weight: 600;
850
+ }
851
+ .pg-btn:disabled {
852
+ opacity: 0.35;
853
+ cursor: default;
854
+ }
855
+ .pg-btn svg {
856
+ width: 13px;
857
+ height: 13px;
858
+ }
859
+ .pg-ellipsis {
860
+ color: var(--muted-foreground);
861
+ padding: 0 3px;
862
+ font-size: 12px;
863
+ }
864
+
865
+ /* ── Run detail panel ──────────────────────────────────────────────────── */
866
+ .tnum {
867
+ font-variant-numeric: tabular-nums;
868
+ }
869
+ .btn {
870
+ height: 28px;
871
+ padding: 0 11px;
872
+ border: 1px solid var(--input);
873
+ background: var(--card);
874
+ color: var(--foreground);
875
+ font-size: 12.5px;
876
+ font-weight: 500;
877
+ cursor: pointer;
878
+ white-space: nowrap;
879
+ display: inline-flex;
880
+ align-items: center;
881
+ gap: 6px;
882
+ }
883
+ .btn:hover {
884
+ background: var(--accent);
885
+ }
886
+ .btn:disabled {
887
+ opacity: 0.5;
888
+ cursor: not-allowed;
889
+ }
890
+ .btn svg {
891
+ width: 14px;
892
+ height: 14px;
893
+ }
894
+ .iconbtn {
895
+ width: 28px;
896
+ height: 28px;
897
+ border: 1px solid var(--input);
898
+ background: var(--card);
899
+ color: var(--muted-foreground);
900
+ display: grid;
901
+ place-items: center;
902
+ cursor: pointer;
903
+ flex-shrink: 0;
904
+ }
905
+ .iconbtn:hover {
906
+ background: var(--accent);
907
+ color: var(--accent-foreground);
908
+ }
909
+ .iconbtn svg {
910
+ width: 15px;
911
+ height: 15px;
912
+ }
913
+
914
+ .run-panel {
915
+ height: 100%;
916
+ min-height: 0;
917
+ overflow: hidden;
918
+ background: var(--card);
919
+ border-left: 1px solid var(--border);
920
+ display: flex;
921
+ flex-direction: column;
922
+ }
923
+ .panel-head {
924
+ border-bottom: 1px solid var(--border);
925
+ padding: 7px 12px 8px;
926
+ flex-shrink: 0;
927
+ }
928
+ .panel-head .ph-top {
929
+ display: flex;
930
+ align-items: center;
931
+ gap: 9px;
932
+ }
933
+ .panel-head h2 {
934
+ font-size: 14px;
935
+ font-weight: 600;
936
+ margin: 0;
937
+ letter-spacing: -0.01em;
938
+ display: flex;
939
+ align-items: center;
940
+ gap: 8px;
941
+ min-width: 0;
942
+ flex: 1 1 auto;
943
+ }
944
+ .panel-head h2 .h2-name {
945
+ overflow: hidden;
946
+ text-overflow: ellipsis;
947
+ }
948
+ .panel-head .ph-actions {
949
+ margin-left: auto;
950
+ display: flex;
951
+ gap: 6px;
952
+ }
953
+ .ph-status {
954
+ margin-top: 9px;
955
+ display: flex;
956
+ align-items: center;
957
+ gap: 9px;
958
+ min-width: 0;
959
+ }
960
+ .ph-status .runid {
961
+ font-family: var(--font-mono);
962
+ font-size: 11.5px;
963
+ color: var(--muted-foreground);
964
+ display: flex;
965
+ align-items: center;
966
+ gap: 7px;
967
+ min-width: 0;
968
+ }
969
+ .ph-status .runid .runid-text {
970
+ overflow: hidden;
971
+ text-overflow: ellipsis;
972
+ white-space: nowrap;
973
+ }
974
+ .ph-status .runid .copy {
975
+ cursor: pointer;
976
+ opacity: 0.7;
977
+ display: inline-grid;
978
+ place-items: center;
979
+ flex-shrink: 0;
980
+ }
981
+ .ph-status .runid .copy:hover {
982
+ opacity: 1;
983
+ color: var(--foreground);
984
+ }
985
+ .panel-body {
986
+ overflow: auto;
987
+ flex: 1;
988
+ min-height: 0;
989
+ }
990
+
991
+ .metagrid {
992
+ display: grid;
993
+ grid-template-columns: 1fr 1fr;
994
+ border-bottom: 1px solid var(--border);
995
+ }
996
+ .meta {
997
+ padding: 3px 11px 4px;
998
+ border-bottom: 1px solid var(--border);
999
+ border-right: 1px solid var(--border);
1000
+ display: flex;
1001
+ flex-direction: column;
1002
+ gap: 1px;
1003
+ min-width: 0;
1004
+ }
1005
+ .metagrid .meta:nth-child(2n) {
1006
+ border-right: 0;
1007
+ }
1008
+ .metagrid .meta:nth-last-child(-n + 2) {
1009
+ border-bottom: 0;
1010
+ }
1011
+ .meta-k {
1012
+ font-size: 10.5px;
1013
+ color: var(--muted-foreground);
1014
+ letter-spacing: 0.02em;
1015
+ }
1016
+ .meta-v {
1017
+ font-family: var(--font-mono);
1018
+ font-size: 12px;
1019
+ color: var(--foreground);
1020
+ font-variant-numeric: tabular-nums;
1021
+ overflow: hidden;
1022
+ text-overflow: ellipsis;
1023
+ white-space: nowrap;
1024
+ }
1025
+ .meta-v.err {
1026
+ color: var(--st-failed-fg);
1027
+ }
1028
+
1029
+ .flowctl {
1030
+ border-bottom: 1px solid var(--border);
1031
+ }
1032
+ .fc-rows {
1033
+ display: flex;
1034
+ flex-direction: column;
1035
+ }
1036
+ .fc-row {
1037
+ display: flex;
1038
+ align-items: baseline;
1039
+ gap: 8px;
1040
+ padding: 4px 11px 5px;
1041
+ border-bottom: 1px solid var(--border);
1042
+ font-size: 12px;
1043
+ }
1044
+ .fc-row:last-child {
1045
+ border-bottom: 0;
1046
+ }
1047
+ .fc-label {
1048
+ flex: 0 0 92px;
1049
+ color: var(--muted-foreground);
1050
+ font-size: 10.5px;
1051
+ letter-spacing: 0.02em;
1052
+ }
1053
+ .fc-value {
1054
+ font-family: var(--font-mono);
1055
+ color: var(--foreground);
1056
+ font-variant-numeric: tabular-nums;
1057
+ }
1058
+ .fc-key {
1059
+ font-family: var(--font-mono);
1060
+ font-size: 11px;
1061
+ color: var(--muted-foreground);
1062
+ }
1063
+ .fc-live {
1064
+ margin-left: auto;
1065
+ font-family: var(--font-mono);
1066
+ font-size: 11px;
1067
+ color: var(--st-running-fg);
1068
+ font-variant-numeric: tabular-nums;
1069
+ white-space: nowrap;
1070
+ }
1071
+ .flowsum {
1072
+ border-top: 1px solid var(--border);
1073
+ }
1074
+
1075
+ .section {
1076
+ border-bottom: 1px solid var(--border);
1077
+ }
1078
+ .io-tabs {
1079
+ display: flex;
1080
+ gap: 0;
1081
+ border-bottom: 1px solid var(--border);
1082
+ padding: 0 13px;
1083
+ }
1084
+ .io-tab {
1085
+ display: inline-flex;
1086
+ align-items: center;
1087
+ gap: 5px;
1088
+ font-size: 11px;
1089
+ padding: 6px 0;
1090
+ margin-right: 16px;
1091
+ cursor: pointer;
1092
+ color: var(--muted-foreground);
1093
+ background: transparent;
1094
+ border: 0;
1095
+ border-bottom: 1.5px solid transparent;
1096
+ margin-bottom: -1px;
1097
+ }
1098
+ .io-tab[data-on='1'] {
1099
+ color: var(--foreground);
1100
+ border-bottom-color: var(--primary);
1101
+ font-weight: 500;
1102
+ }
1103
+ .io-tab[data-kind='error'] {
1104
+ color: var(--st-failed-fg);
1105
+ }
1106
+ .io-tab[data-kind='error'][data-on='1'] {
1107
+ border-bottom-color: var(--destructive);
1108
+ }
1109
+ .io-null {
1110
+ margin-left: 5px;
1111
+ opacity: 0.6;
1112
+ font-family: var(--font-mono);
1113
+ font-size: 10px;
1114
+ }
1115
+ .jsonwrap {
1116
+ background: color-mix(in oklch, var(--foreground) 5%, var(--card));
1117
+ position: relative;
1118
+ }
1119
+ .json {
1120
+ margin: 0;
1121
+ padding: 12px 14px 13px;
1122
+ font-family: var(--font-mono);
1123
+ font-size: 11.5px;
1124
+ line-height: 1.7;
1125
+ color: var(--foreground);
1126
+ overflow-x: auto;
1127
+ white-space: pre;
1128
+ font-variant-numeric: tabular-nums;
1129
+ tab-size: 2;
1130
+ }
1131
+ .json .nul {
1132
+ color: var(--muted-foreground);
1133
+ font-style: italic;
1134
+ }
1135
+
1136
+ /* steps section header + list/flow toggle */
1137
+ .steps-head {
1138
+ display: flex;
1139
+ align-items: center;
1140
+ gap: 8px;
1141
+ padding: 6px 13px;
1142
+ border-bottom: 1px solid var(--border);
1143
+ position: sticky;
1144
+ top: 0;
1145
+ background: var(--card);
1146
+ z-index: 1;
1147
+ }
1148
+ .steps-head .sec-title {
1149
+ font-size: 11px;
1150
+ font-weight: 600;
1151
+ text-transform: uppercase;
1152
+ letter-spacing: 0.06em;
1153
+ color: var(--muted-foreground);
1154
+ }
1155
+ .steps-prog {
1156
+ font-family: var(--font-mono);
1157
+ font-size: 11px;
1158
+ font-weight: 500;
1159
+ color: var(--foreground);
1160
+ font-variant-numeric: tabular-nums;
1161
+ border: 1px solid var(--border);
1162
+ padding: 0 6px;
1163
+ line-height: 17px;
1164
+ }
1165
+ .steps-prog .sp-sep {
1166
+ color: var(--muted-foreground);
1167
+ margin: 0 1px;
1168
+ }
1169
+ .steps-seg {
1170
+ margin-left: auto;
1171
+ display: flex;
1172
+ border: 1px solid var(--border);
1173
+ }
1174
+ .seg-btn {
1175
+ display: inline-flex;
1176
+ align-items: center;
1177
+ gap: 4px;
1178
+ font: inherit;
1179
+ font-size: 11px;
1180
+ font-weight: 500;
1181
+ line-height: 1;
1182
+ padding: 4px 9px;
1183
+ cursor: pointer;
1184
+ background: var(--card);
1185
+ color: var(--muted-foreground);
1186
+ border: 0;
1187
+ border-right: 1px solid var(--border);
1188
+ }
1189
+ .seg-btn:last-child {
1190
+ border-right: 0;
1191
+ }
1192
+ .seg-btn:hover {
1193
+ color: var(--foreground);
1194
+ }
1195
+ .seg-btn[aria-selected='true'] {
1196
+ background: var(--accent);
1197
+ color: var(--foreground);
1198
+ }
1199
+ .seg-ico {
1200
+ width: 12px;
1201
+ height: 12px;
1202
+ }
1203
+ .steplist {
1204
+ padding: 0;
1205
+ }
1206
+ .steps-empty,
1207
+ .steps-loading {
1208
+ display: flex;
1209
+ align-items: center;
1210
+ justify-content: center;
1211
+ padding: 16px;
1212
+ color: var(--muted-foreground);
1213
+ font-size: 12px;
1214
+ }
1215
+
1216
+ /* per-step status palette (shared by list rows + flow nodes) */
1217
+ .step[data-status='succeeded'],
1218
+ .flow-node[data-status='succeeded'] {
1219
+ --step-c: var(--st-succeeded-fg);
1220
+ --step-bg: var(--st-succeeded-bg);
1221
+ }
1222
+ .step[data-status='failed'],
1223
+ .flow-node[data-status='failed'] {
1224
+ --step-c: var(--st-failed-fg);
1225
+ --step-bg: var(--st-failed-bg);
1226
+ }
1227
+ .step[data-status='running'],
1228
+ .flow-node[data-status='running'] {
1229
+ --step-c: var(--st-running-fg);
1230
+ --step-bg: var(--st-running-bg);
1231
+ }
1232
+ .step[data-status='waiting'],
1233
+ .flow-node[data-status='waiting'] {
1234
+ --step-c: var(--st-waiting-fg);
1235
+ --step-bg: var(--st-waiting-bg);
1236
+ }
1237
+ .step[data-status='queued'],
1238
+ .flow-node[data-status='queued'] {
1239
+ --step-c: var(--st-queued-fg);
1240
+ --step-bg: var(--st-queued-bg);
1241
+ }
1242
+ .step[data-status='cancelled'],
1243
+ .flow-node[data-status='cancelled'] {
1244
+ --step-c: var(--st-cancelled-fg);
1245
+ --step-bg: var(--st-cancelled-bg);
1246
+ }
1247
+ .step[data-status='skipped'],
1248
+ .flow-node[data-status='skipped'] {
1249
+ --step-c: var(--st-skipped-fg);
1250
+ --step-bg: var(--st-skipped-bg);
1251
+ }
1252
+ .step[data-status='paused'],
1253
+ .flow-node[data-status='paused'] {
1254
+ --step-c: var(--st-paused-fg);
1255
+ --step-bg: var(--st-paused-bg);
1256
+ }
1257
+
1258
+ .step {
1259
+ position: relative;
1260
+ border-bottom: 1px solid color-mix(in oklch, var(--foreground) 11%, var(--card));
1261
+ }
1262
+ .step:last-child {
1263
+ border-bottom: 0;
1264
+ }
1265
+ .step::before {
1266
+ content: '';
1267
+ position: absolute;
1268
+ left: 0;
1269
+ top: 0;
1270
+ bottom: 0;
1271
+ width: 2px;
1272
+ background: var(--step-c);
1273
+ opacity: 0.4;
1274
+ transition:
1275
+ opacity 0.12s,
1276
+ width 0.12s;
1277
+ }
1278
+ .step[data-status='skipped']::before,
1279
+ .step[data-status='queued']::before {
1280
+ opacity: 0.22;
1281
+ }
1282
+ .step.open::before,
1283
+ .step[data-status='failed']::before {
1284
+ opacity: 1;
1285
+ }
1286
+ .step.open::before {
1287
+ width: 3px;
1288
+ left: 0;
1289
+ }
1290
+ .step-row {
1291
+ display: flex;
1292
+ align-items: center;
1293
+ gap: 10px;
1294
+ padding: 5px 13px;
1295
+ cursor: pointer;
1296
+ width: 100%;
1297
+ background: transparent;
1298
+ border: 0;
1299
+ color: var(--foreground);
1300
+ text-align: left;
1301
+ }
1302
+ .step-row.static {
1303
+ cursor: default;
1304
+ }
1305
+ .step-row:not(.static):hover {
1306
+ background: var(--accent);
1307
+ }
1308
+ .step-node {
1309
+ width: 19px;
1310
+ height: 19px;
1311
+ flex-shrink: 0;
1312
+ display: grid;
1313
+ place-items: center;
1314
+ background: var(--step-bg);
1315
+ color: var(--step-c);
1316
+ border: 1px solid color-mix(in oklch, var(--step-c) 28%, transparent);
1317
+ }
1318
+ .step[data-status='skipped'] .step-node {
1319
+ border-style: dashed;
1320
+ }
1321
+ .step-gly {
1322
+ width: 12px;
1323
+ height: 12px;
1324
+ }
1325
+ .step-ix {
1326
+ font-family: var(--font-mono);
1327
+ font-size: 10.5px;
1328
+ color: var(--muted-foreground);
1329
+ width: 13px;
1330
+ flex-shrink: 0;
1331
+ text-align: right;
1332
+ font-variant-numeric: tabular-nums;
1333
+ opacity: 0.8;
1334
+ }
1335
+ .step-name {
1336
+ font-size: 12.5px;
1337
+ font-weight: 500;
1338
+ overflow: hidden;
1339
+ text-overflow: ellipsis;
1340
+ white-space: nowrap;
1341
+ min-width: 0;
1342
+ flex: 1 1 auto;
1343
+ }
1344
+ .step.open .step-name {
1345
+ font-weight: 600;
1346
+ }
1347
+ .step[data-status='skipped'] .step-name,
1348
+ .step[data-status='queued'] .step-name {
1349
+ color: var(--muted-foreground);
1350
+ }
1351
+ .step[data-current='1']:not(.open) .step-row {
1352
+ background: color-mix(in oklch, var(--step-bg) 38%, transparent);
1353
+ }
1354
+ .step-meta {
1355
+ margin-left: auto;
1356
+ display: flex;
1357
+ align-items: center;
1358
+ gap: 10px;
1359
+ flex-shrink: 0;
1360
+ }
1361
+ .step-status {
1362
+ font-size: 11px;
1363
+ font-weight: 500;
1364
+ color: var(--step-c);
1365
+ }
1366
+ .step-att {
1367
+ font-family: var(--font-mono);
1368
+ font-size: 10px;
1369
+ color: var(--muted-foreground);
1370
+ border: 1px solid var(--border);
1371
+ padding: 0 4px;
1372
+ line-height: 15px;
1373
+ }
1374
+ .step-dur {
1375
+ font-family: var(--font-mono);
1376
+ font-size: 11px;
1377
+ color: var(--muted-foreground);
1378
+ font-variant-numeric: tabular-nums;
1379
+ min-width: 44px;
1380
+ text-align: right;
1381
+ }
1382
+ .step-chev {
1383
+ width: 12px;
1384
+ height: 12px;
1385
+ color: var(--muted-foreground);
1386
+ transition: transform 0.14s;
1387
+ }
1388
+ .step.open .step-chev {
1389
+ transform: rotate(90deg);
1390
+ color: var(--foreground);
1391
+ }
1392
+ .step-chev-sp {
1393
+ width: 12px;
1394
+ flex-shrink: 0;
1395
+ }
1396
+ .step.open {
1397
+ background: color-mix(in oklch, var(--step-bg) 24%, var(--card));
1398
+ }
1399
+ .step.open .step-row:hover {
1400
+ background: transparent;
1401
+ }
1402
+ .step-body {
1403
+ border-top: 1px solid color-mix(in oklch, var(--step-c) 22%, var(--border));
1404
+ background: var(--card);
1405
+ }
1406
+ .step-actions {
1407
+ display: flex;
1408
+ justify-content: flex-end;
1409
+ padding: 8px 13px;
1410
+ }
1411
+ .step-tabs {
1412
+ display: flex;
1413
+ align-items: center;
1414
+ gap: 0;
1415
+ padding: 0 13px;
1416
+ border-bottom: 1px solid var(--border);
1417
+ background: var(--muted);
1418
+ }
1419
+ .step-tab {
1420
+ display: inline-flex;
1421
+ align-items: center;
1422
+ gap: 5px;
1423
+ font-size: 11px;
1424
+ font-weight: 500;
1425
+ padding: 6px 0;
1426
+ margin-right: 16px;
1427
+ cursor: pointer;
1428
+ color: var(--muted-foreground);
1429
+ background: transparent;
1430
+ border: 0;
1431
+ border-bottom: 1.5px solid transparent;
1432
+ margin-bottom: -1px;
1433
+ }
1434
+ .step-tab:hover {
1435
+ color: var(--foreground);
1436
+ }
1437
+ .step-tab[aria-selected='true'] {
1438
+ color: var(--foreground);
1439
+ border-bottom-color: var(--primary);
1440
+ }
1441
+ .step-tab[data-kind='error'] {
1442
+ color: var(--st-failed-fg);
1443
+ }
1444
+ .step-tab[data-kind='error'][aria-selected='true'] {
1445
+ border-bottom-color: var(--destructive);
1446
+ }
1447
+ .step-tab-ico {
1448
+ width: 12px;
1449
+ height: 12px;
1450
+ }
1451
+ .errbox {
1452
+ margin: 0;
1453
+ padding: 11px 14px 12px;
1454
+ border-left: 2px solid var(--destructive);
1455
+ background: color-mix(in oklch, var(--destructive) 6%, var(--card));
1456
+ color: color-mix(in oklch, var(--st-failed-fg) 88%, var(--foreground));
1457
+ font-family: var(--font-mono);
1458
+ font-size: 11.5px;
1459
+ line-height: 1.7;
1460
+ white-space: pre-wrap;
1461
+ tab-size: 2;
1462
+ }
1463
+
1464
+ /* ── Step flow view (vertical node graph) ──────────────────────────────── */
1465
+ .stepflow {
1466
+ display: flex;
1467
+ flex-direction: column;
1468
+ }
1469
+ .flow-canvas {
1470
+ padding: 10px 12px 14px;
1471
+ display: flex;
1472
+ flex-direction: column;
1473
+ align-items: center;
1474
+ background-color: var(--muted);
1475
+ background-image: radial-gradient(
1476
+ color-mix(in oklch, var(--foreground) 11%, transparent) 1px,
1477
+ transparent 1px
1478
+ );
1479
+ background-size: 13px 13px;
1480
+ border-bottom: 1px solid var(--border);
1481
+ }
1482
+ .flow-trigger {
1483
+ display: flex;
1484
+ align-items: center;
1485
+ gap: 6px;
1486
+ font-size: 9.5px;
1487
+ text-transform: uppercase;
1488
+ letter-spacing: 0.05em;
1489
+ color: var(--muted-foreground);
1490
+ font-weight: 600;
1491
+ background: var(--card);
1492
+ border: 1px dashed var(--border);
1493
+ padding: 3px 9px;
1494
+ width: 100%;
1495
+ max-width: 280px;
1496
+ }
1497
+ .flow-trigger-dot {
1498
+ width: 6px;
1499
+ height: 6px;
1500
+ border-radius: 50%;
1501
+ background: var(--muted-foreground);
1502
+ flex-shrink: 0;
1503
+ }
1504
+ .flow-trigger-wf {
1505
+ margin-left: auto;
1506
+ text-transform: none;
1507
+ letter-spacing: 0;
1508
+ font-family: var(--font-mono);
1509
+ font-size: 10px;
1510
+ font-weight: 400;
1511
+ color: var(--foreground);
1512
+ max-width: 130px;
1513
+ overflow: hidden;
1514
+ text-overflow: ellipsis;
1515
+ white-space: nowrap;
1516
+ }
1517
+ .flow-edge {
1518
+ display: flex;
1519
+ flex-direction: column;
1520
+ align-items: center;
1521
+ height: 13px;
1522
+ --edge-c: var(--muted-foreground);
1523
+ }
1524
+ .flow-edge[data-status='succeeded'] {
1525
+ --edge-c: var(--st-succeeded-fg);
1526
+ }
1527
+ .flow-edge[data-status='failed'] {
1528
+ --edge-c: var(--st-failed-fg);
1529
+ }
1530
+ .flow-edge[data-status='cancelled'] {
1531
+ --edge-c: var(--st-cancelled-fg);
1532
+ }
1533
+ .flow-edge[data-status='trigger'] {
1534
+ --edge-c: color-mix(in oklch, var(--foreground) 40%, transparent);
1535
+ }
1536
+ .flow-edge[data-status='skipped'],
1537
+ .flow-edge[data-status='queued'],
1538
+ .flow-edge[data-status='waiting'],
1539
+ .flow-edge[data-status='running'] {
1540
+ --edge-c: color-mix(in oklch, var(--foreground) 26%, transparent);
1541
+ }
1542
+ .fe-line {
1543
+ flex: 1;
1544
+ width: 1px;
1545
+ background: var(--edge-c);
1546
+ }
1547
+ .flow-edge[data-status='skipped'] .fe-line,
1548
+ .flow-edge[data-status='queued'] .fe-line {
1549
+ width: 0;
1550
+ border-left: 1px dashed var(--edge-c);
1551
+ }
1552
+ .fe-arrow {
1553
+ width: 10px;
1554
+ height: 10px;
1555
+ color: var(--edge-c);
1556
+ transform: rotate(90deg);
1557
+ margin-top: -3px;
1558
+ }
1559
+ .flow-node {
1560
+ position: relative;
1561
+ width: 100%;
1562
+ max-width: 280px;
1563
+ text-align: left;
1564
+ cursor: pointer;
1565
+ background: var(--card);
1566
+ border: 1px solid var(--border);
1567
+ padding: 4px 9px 4px 11px;
1568
+ display: flex;
1569
+ align-items: center;
1570
+ gap: 7px;
1571
+ color: var(--foreground);
1572
+ font: inherit;
1573
+ }
1574
+ .flow-node:hover {
1575
+ border-color: color-mix(in oklch, var(--step-c) 55%, var(--border));
1576
+ }
1577
+ .flow-node.sel {
1578
+ border-color: var(--step-c);
1579
+ background: color-mix(in oklch, var(--step-bg) 26%, var(--card));
1580
+ }
1581
+ .fn-rail {
1582
+ position: absolute;
1583
+ left: 0;
1584
+ top: 0;
1585
+ bottom: 0;
1586
+ width: 2px;
1587
+ background: var(--step-c);
1588
+ opacity: 0.45;
1589
+ }
1590
+ .flow-node[data-status='failed'] .fn-rail,
1591
+ .flow-node.sel .fn-rail {
1592
+ opacity: 1;
1593
+ }
1594
+ .flow-node[data-status='skipped'] .fn-rail,
1595
+ .flow-node[data-status='queued'] .fn-rail {
1596
+ opacity: 0.25;
1597
+ }
1598
+ .flow-node.sel .fn-rail {
1599
+ width: 3px;
1600
+ }
1601
+ .fn-node {
1602
+ width: 15px;
1603
+ height: 15px;
1604
+ flex-shrink: 0;
1605
+ display: grid;
1606
+ place-items: center;
1607
+ background: var(--step-bg);
1608
+ color: var(--step-c);
1609
+ border: 1px solid color-mix(in oklch, var(--step-c) 28%, transparent);
1610
+ }
1611
+ .flow-node[data-status='skipped'] .fn-node {
1612
+ border-style: dashed;
1613
+ }
1614
+ .fn-gly {
1615
+ width: 9px;
1616
+ height: 9px;
1617
+ }
1618
+ .fn-name {
1619
+ font-weight: 500;
1620
+ font-size: 11.5px;
1621
+ overflow: hidden;
1622
+ text-overflow: ellipsis;
1623
+ white-space: nowrap;
1624
+ flex: 1 1 auto;
1625
+ min-width: 0;
1626
+ }
1627
+ .flow-node.sel .fn-name {
1628
+ font-weight: 600;
1629
+ }
1630
+ .flow-node[data-status='skipped'] .fn-name,
1631
+ .flow-node[data-status='queued'] .fn-name {
1632
+ color: var(--muted-foreground);
1633
+ }
1634
+ .fn-att {
1635
+ font-family: var(--font-mono);
1636
+ font-size: 9px;
1637
+ color: var(--muted-foreground);
1638
+ border: 1px solid var(--border);
1639
+ padding: 0 3px;
1640
+ line-height: 13px;
1641
+ flex-shrink: 0;
1642
+ }
1643
+ .fn-status {
1644
+ font-size: 10px;
1645
+ font-weight: 500;
1646
+ color: var(--step-c);
1647
+ white-space: nowrap;
1648
+ flex-shrink: 0;
1649
+ }
1650
+ .fn-dur {
1651
+ font-family: var(--font-mono);
1652
+ font-size: 10px;
1653
+ color: var(--muted-foreground);
1654
+ font-variant-numeric: tabular-nums;
1655
+ flex-shrink: 0;
1656
+ }
1657
+ .fn-errflag {
1658
+ width: 12px;
1659
+ height: 12px;
1660
+ color: var(--st-failed-fg);
1661
+ flex-shrink: 0;
1662
+ }
1663
+ .flow-inspect {
1664
+ background: var(--card);
1665
+ }
1666
+ .fi-head {
1667
+ display: flex;
1668
+ align-items: center;
1669
+ gap: 8px;
1670
+ padding: 8px 13px;
1671
+ border-bottom: 1px solid var(--border);
1672
+ }
1673
+ .fi-dot {
1674
+ width: 8px;
1675
+ height: 8px;
1676
+ border-radius: 50%;
1677
+ flex-shrink: 0;
1678
+ background: var(--muted-foreground);
1679
+ }
1680
+ .fi-dot[data-status='succeeded'] {
1681
+ background: var(--st-succeeded-fg);
1682
+ }
1683
+ .fi-dot[data-status='failed'] {
1684
+ background: var(--st-failed-fg);
1685
+ }
1686
+ .fi-dot[data-status='running'] {
1687
+ background: var(--st-running-fg);
1688
+ }
1689
+ .fi-dot[data-status='waiting'] {
1690
+ background: var(--st-waiting-fg);
1691
+ }
1692
+ .fi-dot[data-status='cancelled'] {
1693
+ background: var(--st-cancelled-fg);
1694
+ }
1695
+ .fi-dot[data-status='paused'] {
1696
+ background: var(--st-paused-fg);
1697
+ }
1698
+ .fi-name {
1699
+ font-weight: 600;
1700
+ font-size: 12.5px;
1701
+ }
1702
+ .fi-meta {
1703
+ margin-left: auto;
1704
+ font-family: var(--font-mono);
1705
+ font-size: 10.5px;
1706
+ color: var(--muted-foreground);
1707
+ font-variant-numeric: tabular-nums;
1708
+ }
1709
+ .fi-retry {
1710
+ flex-shrink: 0;
1711
+ height: 24px;
1712
+ padding: 0 8px;
1713
+ font-size: 11px;
1714
+ gap: 4px;
1715
+ }
1716
+ .fi-retry svg {
1717
+ width: 12px;
1718
+ height: 12px;
1719
+ }
1720
+ .fi-empty {
1721
+ padding: 14px 13px;
1722
+ font-size: 11.5px;
1723
+ color: var(--muted-foreground);
1724
+ }
1725
+
1726
+ /* ── Step timeline (Gantt) view ────────────────────────────────────────── */
1727
+ .steptl {
1728
+ display: flex;
1729
+ flex-direction: column;
1730
+ --tl-label-w: 132px;
1731
+ --tl-dur-w: 56px;
1732
+ --tl-gap: 10px;
1733
+ }
1734
+ .tl-canvas {
1735
+ padding: 9px 12px 12px;
1736
+ border-bottom: 1px solid var(--border);
1737
+ }
1738
+ .tl-axis {
1739
+ display: grid;
1740
+ grid-template-columns: var(--tl-label-w) 1fr var(--tl-dur-w);
1741
+ gap: var(--tl-gap);
1742
+ padding-bottom: 5px;
1743
+ }
1744
+ .tl-axis-scale {
1745
+ grid-column: 2;
1746
+ display: flex;
1747
+ justify-content: space-between;
1748
+ font-family: var(--font-mono);
1749
+ font-size: 9.5px;
1750
+ color: var(--muted-foreground);
1751
+ }
1752
+ .tl-row {
1753
+ display: grid;
1754
+ grid-template-columns: var(--tl-label-w) 1fr var(--tl-dur-w);
1755
+ gap: var(--tl-gap);
1756
+ align-items: center;
1757
+ width: 100%;
1758
+ padding: 5px 0;
1759
+ background: none;
1760
+ border: 0;
1761
+ border-bottom: 1px solid var(--border);
1762
+ text-align: left;
1763
+ cursor: pointer;
1764
+ }
1765
+ .tl-row:last-child {
1766
+ border-bottom: 0;
1767
+ }
1768
+ .tl-row:hover {
1769
+ background: var(--muted);
1770
+ }
1771
+ .tl-row.sel {
1772
+ background: var(--accent);
1773
+ }
1774
+ .tl-label {
1775
+ font-family: var(--font-mono);
1776
+ font-size: 11px;
1777
+ color: var(--foreground);
1778
+ overflow: hidden;
1779
+ text-overflow: ellipsis;
1780
+ white-space: nowrap;
1781
+ }
1782
+ .tl-track {
1783
+ position: relative;
1784
+ height: 16px;
1785
+ overflow: hidden;
1786
+ background-color: color-mix(in oklch, var(--foreground) 5%, transparent);
1787
+ /* Quarter gridlines, so durations read against the axis ticks across all rows. */
1788
+ background-image: repeating-linear-gradient(
1789
+ to right,
1790
+ color-mix(in oklch, var(--foreground) 11%, transparent) 0 1px,
1791
+ transparent 1px 25%
1792
+ );
1793
+ }
1794
+ .tl-bar {
1795
+ position: absolute;
1796
+ top: 3px;
1797
+ height: 10px;
1798
+ min-width: 2px;
1799
+ border-radius: 2px;
1800
+ background: var(--muted-foreground);
1801
+ }
1802
+ .tl-bar[data-status='succeeded'] {
1803
+ background: var(--st-succeeded-fg);
1804
+ }
1805
+ .tl-bar[data-status='failed'] {
1806
+ background: var(--st-failed-fg);
1807
+ }
1808
+ .tl-bar[data-status='running'] {
1809
+ background: var(--st-running-fg);
1810
+ }
1811
+ .tl-bar[data-status='cancelled'] {
1812
+ background: var(--st-cancelled-fg);
1813
+ }
1814
+ .tl-bar[data-status='skipped'] {
1815
+ background: var(--st-skipped-fg);
1816
+ }
1817
+ .tl-bar[data-status='paused'] {
1818
+ background: var(--st-paused-fg);
1819
+ }
1820
+ /* A waiting step (sleep / waitForEvent) is time spent parked, not working - render
1821
+ it hatched so it reads as a gap-with-duration rather than active execution. */
1822
+ .tl-bar[data-status='waiting'] {
1823
+ background: repeating-linear-gradient(
1824
+ 45deg,
1825
+ var(--st-running-fg),
1826
+ var(--st-running-fg) 3px,
1827
+ transparent 3px,
1828
+ transparent 6px
1829
+ );
1830
+ }
1831
+ .tl-skip {
1832
+ font-size: 10px;
1833
+ color: var(--muted-foreground);
1834
+ padding-left: 4px;
1835
+ }
1836
+ .tl-dur {
1837
+ font-size: 10.5px;
1838
+ color: var(--muted-foreground);
1839
+ text-align: right;
1840
+ }
1841
+
1842
+ /* ── Content views (apps / workflows) ──────────────────────────────────── */
1843
+ .content {
1844
+ flex: 1;
1845
+ min-width: 0;
1846
+ min-height: 0;
1847
+ overflow: auto;
1848
+ display: flex;
1849
+ flex-direction: column;
1850
+ }
1851
+ .tbar {
1852
+ display: flex;
1853
+ align-items: center;
1854
+ gap: 7px;
1855
+ padding: 6px 13px;
1856
+ border-bottom: 1px solid var(--border);
1857
+ flex-shrink: 0;
1858
+ }
1859
+ .tbar-spacer {
1860
+ flex: 1;
1861
+ }
1862
+ .tbar .meta {
1863
+ font-size: 11.5px;
1864
+ color: var(--muted-foreground);
1865
+ font-family: var(--font-mono);
1866
+ white-space: nowrap;
1867
+ }
1868
+ .chip {
1869
+ height: 25px;
1870
+ padding: 0 9px;
1871
+ border: 1px solid var(--input);
1872
+ background: var(--card);
1873
+ color: var(--muted-foreground);
1874
+ font-size: 12px;
1875
+ cursor: pointer;
1876
+ display: inline-flex;
1877
+ align-items: center;
1878
+ gap: 6px;
1879
+ white-space: nowrap;
1880
+ }
1881
+ .chip:hover {
1882
+ background: var(--accent);
1883
+ color: var(--accent-foreground);
1884
+ }
1885
+ .chip[data-on='1'] {
1886
+ background: var(--accent);
1887
+ color: var(--foreground);
1888
+ border-color: var(--border);
1889
+ }
1890
+ .chip svg {
1891
+ width: 12px;
1892
+ height: 12px;
1893
+ opacity: 0.7;
1894
+ }
1895
+
1896
+ /* loading / empty / error row inside table.runs */
1897
+ .table-status td {
1898
+ height: auto;
1899
+ padding: 18px 11px;
1900
+ text-align: center;
1901
+ color: var(--muted-foreground);
1902
+ font-size: 12px;
1903
+ }
1904
+ .table-status:hover td {
1905
+ background: transparent;
1906
+ }
1907
+
1908
+ /* ── Apps table ────────────────────────────────────────────────────────── */
1909
+ .apps-table tbody td {
1910
+ height: 38px;
1911
+ }
1912
+ .app-row[aria-expanded='true'] td {
1913
+ background: var(--accent);
1914
+ }
1915
+ .app-cell {
1916
+ display: flex;
1917
+ align-items: center;
1918
+ gap: 10px;
1919
+ }
1920
+ .app-cell .app-chev {
1921
+ width: 12px;
1922
+ height: 12px;
1923
+ color: var(--muted-foreground);
1924
+ transition: transform 0.12s;
1925
+ flex-shrink: 0;
1926
+ }
1927
+ .app-row[aria-expanded='true'] .app-chev {
1928
+ transform: rotate(90deg);
1929
+ color: var(--foreground);
1930
+ }
1931
+ .app-cell .sq {
1932
+ width: 13px;
1933
+ height: 13px;
1934
+ flex-shrink: 0;
1935
+ border: 1px solid color-mix(in oklch, var(--foreground) 18%, transparent);
1936
+ }
1937
+ .app-id {
1938
+ display: flex;
1939
+ flex-direction: column;
1940
+ gap: 1px;
1941
+ min-width: 0;
1942
+ }
1943
+ .app-id .nm {
1944
+ font-weight: 500;
1945
+ color: var(--foreground);
1946
+ line-height: 1.25;
1947
+ }
1948
+ .app-detailrow {
1949
+ cursor: default;
1950
+ }
1951
+ .app-detailrow td {
1952
+ padding: 0 !important;
1953
+ height: auto !important;
1954
+ background: var(--muted);
1955
+ }
1956
+ .app-detailrow:hover td {
1957
+ background: var(--muted);
1958
+ }
1959
+ .app-detail-list {
1960
+ padding: 13px 16px 15px;
1961
+ border-bottom: 1px solid var(--border);
1962
+ }
1963
+ .app-sub {
1964
+ font-size: 10.5px;
1965
+ text-transform: uppercase;
1966
+ letter-spacing: 0.06em;
1967
+ color: var(--muted-foreground);
1968
+ margin-bottom: 8px;
1969
+ font-weight: 600;
1970
+ }
1971
+ .app-wf {
1972
+ display: flex;
1973
+ align-items: center;
1974
+ gap: 10px;
1975
+ padding: 6px 0;
1976
+ border-bottom: 1px solid var(--border);
1977
+ }
1978
+ .app-wf:last-child {
1979
+ border-bottom: 0;
1980
+ }
1981
+ .app-wf-name {
1982
+ font-size: 12px;
1983
+ color: var(--foreground);
1984
+ flex: 1;
1985
+ font-weight: 500;
1986
+ }
1987
+ .runner-row-end {
1988
+ display: flex;
1989
+ align-items: center;
1990
+ gap: 8px;
1991
+ }
1992
+ .runner-block {
1993
+ border-bottom: 1px solid var(--border);
1994
+ }
1995
+ .runner-block:last-child {
1996
+ border-bottom: 0;
1997
+ }
1998
+ .runner-block .app-wf {
1999
+ border-bottom: 0;
2000
+ }
2001
+ .runner-meta {
2002
+ border: 1px solid var(--border);
2003
+ margin: 0 0 8px;
2004
+ }
2005
+
2006
+ /* ── Webhooks: sub-nav, split deliveries, detail, endpoints, receivers ─────── */
2007
+ .wh-root { display: flex; flex-direction: column; flex: 1; min-height: 0; }
2008
+ .wh-body { display: flex; flex: 1; min-height: 0; }
2009
+
2010
+ .wh-subnav {
2011
+ display: flex; align-items: stretch; gap: 4px;
2012
+ padding: 0 13px; border-bottom: 1px solid var(--border);
2013
+ flex-shrink: 0; background: var(--card);
2014
+ }
2015
+ .wh-tab {
2016
+ display: inline-flex; align-items: center; gap: 7px;
2017
+ padding: 9px 4px 8px; margin-right: 14px;
2018
+ background: transparent; border: 0; cursor: pointer;
2019
+ color: var(--muted-foreground); font-size: 13px; font-weight: 500;
2020
+ border-bottom: 2px solid transparent; margin-bottom: -1px;
2021
+ }
2022
+ .wh-tab:hover { color: var(--foreground); }
2023
+ .wh-tab[aria-selected="true"] { color: var(--foreground); border-bottom-color: var(--primary); }
2024
+ .wh-tab-ico { width: 15px; height: 15px; }
2025
+ .wh-tab[aria-selected="true"] .wh-tab-ico { color: var(--primary); }
2026
+ .wh-count {
2027
+ font-family: var(--font-mono); font-size: 10.5px; line-height: 1;
2028
+ padding: 2px 5px; border: 1px solid var(--border); color: var(--muted-foreground);
2029
+ background: var(--muted);
2030
+ }
2031
+ .wh-tab[aria-selected="true"] .wh-count { color: var(--foreground); border-color: color-mix(in oklch, var(--primary) 40%, var(--border)); }
2032
+
2033
+ .bdot { width: 6px; height: 6px; flex-shrink: 0; border-radius: 50%; background: currentColor; }
2034
+ .sq { display: inline-block; }
2035
+
2036
+ /* http code pill */
2037
+ .wh-code {
2038
+ font-family: var(--font-mono); font-size: 11.5px; font-weight: 600;
2039
+ padding: 1px 6px; display: inline-block; letter-spacing: 0.01em;
2040
+ }
2041
+ .wh-code.ok { background: var(--st-succeeded-bg); color: var(--st-succeeded-fg); }
2042
+ .wh-code.warn { background: var(--st-waiting-bg); color: var(--st-waiting-fg); }
2043
+ .wh-code.err { background: var(--st-failed-bg); color: var(--st-failed-fg); }
2044
+ .wh-code.none { color: var(--muted-foreground); background: transparent; padding-left: 0; }
2045
+
2046
+ /* event chips */
2047
+ .wh-evchips { display: flex; align-items: center; gap: 5px; min-width: 0; }
2048
+ .wh-evchips.wrap { flex-wrap: wrap; margin-top: 9px; }
2049
+ .wh-evchip {
2050
+ font-family: var(--font-mono); font-size: 11px; color: var(--foreground);
2051
+ padding: 2px 7px; border: 1px solid var(--border); background: var(--muted);
2052
+ white-space: nowrap;
2053
+ }
2054
+ .wh-evmore { font-size: 11px; color: var(--muted-foreground); font-family: var(--font-mono); }
2055
+
2056
+ /* secret / verification */
2057
+ .wh-secret { display: inline-flex; align-items: center; gap: 8px; }
2058
+ .wh-mask {
2059
+ font-family: var(--font-sans); font-size: 9.5px; text-transform: uppercase; letter-spacing: 0.05em;
2060
+ color: var(--muted-foreground); border: 1px solid var(--border); padding: 1px 4px;
2061
+ }
2062
+ .wh-verify { display: inline-flex; align-items: center; gap: 5px; font-size: 11.5px; font-weight: 500; }
2063
+ .wh-verify svg { width: 13px; height: 13px; }
2064
+ .wh-verify.ok { color: var(--st-succeeded-fg); }
2065
+ .wh-verify.off { color: var(--st-waiting-fg); }
2066
+
2067
+ /* attempt timeline */
2068
+ .wh-attempts { padding: 3px 13px 5px; }
2069
+ .wh-attempt { display: flex; gap: 10px; padding: 5px 0; position: relative; }
2070
+ .wh-attempt:not(:last-child)::before {
2071
+ content: ""; position: absolute; left: 9px; top: 22px; bottom: -1px;
2072
+ width: 1.5px; background: var(--border);
2073
+ }
2074
+ .wh-att-node {
2075
+ width: 19px; height: 19px; flex-shrink: 0; display: grid; place-items: center;
2076
+ border: 1.5px solid var(--border); background: var(--card); color: var(--muted-foreground);
2077
+ z-index: 1; margin-top: 1px;
2078
+ }
2079
+ .wh-att-gly { width: 11px; height: 11px; }
2080
+ .wh-attempt[data-status="succeeded"] .wh-att-node { border-color: var(--st-succeeded-fg); color: var(--st-succeeded-fg); }
2081
+ .wh-attempt[data-status="failed"] .wh-att-node { border-color: var(--st-failed-fg); color: var(--st-failed-fg); }
2082
+ .wh-attempt[data-status="retrying"] .wh-att-node { border-color: var(--st-running-fg); color: var(--st-running-fg); }
2083
+ .wh-att-main { min-width: 0; flex: 1; }
2084
+ .wh-att-top { display: flex; align-items: center; gap: 8px; }
2085
+ .wh-att-n { font-size: 11.5px; font-weight: 600; color: var(--foreground); }
2086
+ .wh-att-at { margin-left: auto; font-family: var(--font-mono); font-size: 11px; color: var(--muted-foreground); }
2087
+ .wh-att-note { font-family: var(--font-mono); font-size: 11px; color: var(--muted-foreground); margin-top: 1px; }
2088
+
2089
+ /* response snippet block */
2090
+ .wh-resp { padding: 12px 13px 14px; }
2091
+ .wh-resp-line { display: flex; align-items: center; gap: 9px; margin-bottom: 12px; }
2092
+ .wh-resp-text { font-size: 12.5px; font-weight: 600; color: var(--foreground); }
2093
+ .wh-resp-dur { margin-left: auto; font-family: var(--font-mono); font-size: 11.5px; color: var(--muted-foreground); }
2094
+ .wh-resp-sub {
2095
+ font-size: 10.5px; text-transform: uppercase; letter-spacing: 0.06em; font-weight: 600;
2096
+ color: var(--muted-foreground); margin: 0 0 7px;
2097
+ }
2098
+ .wh-resp-body {
2099
+ margin: 0; padding: 10px 12px; background: var(--muted); border: 1px solid var(--border);
2100
+ font-family: var(--font-mono); font-size: 11.5px; color: var(--foreground);
2101
+ white-space: pre-wrap; word-break: break-word; line-height: 1.5;
2102
+ }
2103
+ .wh-foot-actions {
2104
+ display: flex; flex-wrap: wrap; gap: 7px; padding: 14px 13px 18px;
2105
+ border-top: 1px solid var(--border);
2106
+ }
2107
+
2108
+ /* endpoint target link */
2109
+ .wh-target {
2110
+ display: inline-flex; align-items: center; gap: 6px; margin-top: 9px;
2111
+ font-family: var(--font-mono); font-size: 11.5px; color: var(--primary); text-decoration: none;
2112
+ overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 100%;
2113
+ background: none; border: 0; padding: 0; cursor: pointer;
2114
+ }
2115
+ .wh-target svg { width: 12px; height: 12px; flex-shrink: 0; }
2116
+ .wh-target:hover { text-decoration: underline; }
2117
+ .wh-metagrid { grid-template-columns: repeat(3, 1fr); }
2118
+
2119
+ /* endpoint/receiver expanded detail */
2120
+ .wh-od {
2121
+ display: grid; grid-template-columns: 1.15fr 1fr; gap: 26px;
2122
+ padding: 15px 17px 17px; border-bottom: 1px solid var(--border);
2123
+ }
2124
+ .wh-od-main { min-width: 0; display: flex; flex-direction: column; gap: 17px; }
2125
+ .wh-od-sec { min-width: 0; }
2126
+ .wh-od-side { min-width: 0; display: flex; flex-direction: column; }
2127
+ .wh-od-h {
2128
+ font-size: 10.5px; text-transform: uppercase; letter-spacing: 0.06em; font-weight: 600;
2129
+ color: var(--muted-foreground); margin: 0 0 9px; padding-bottom: 6px;
2130
+ border-bottom: 1px solid var(--border);
2131
+ }
2132
+ .wh-od .app-actions { margin-top: 0; }
2133
+ .wh-reclist { border: 1px solid var(--border); max-height: 216px; overflow: auto; }
2134
+ .wh-rec {
2135
+ display: flex; align-items: center; gap: 10px; min-width: 0;
2136
+ padding: 6px 11px; border-bottom: 1px solid var(--border);
2137
+ }
2138
+ .wh-rec:last-child { border-bottom: 0; }
2139
+ .wh-rec-ev {
2140
+ flex: 1; min-width: 0; font-family: var(--font-mono); font-size: 11.5px; color: var(--foreground);
2141
+ overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
2142
+ }
2143
+ .wh-rec-meta { display: flex; align-items: center; gap: 8px; flex-shrink: 0; }
2144
+ .wh-rec-at { font-family: var(--font-mono); font-size: 10.5px; color: var(--muted-foreground); width: 56px; text-align: right; }
2145
+ .wh-rec-empty {
2146
+ border: 1px solid var(--border); padding: 14px 11px; font-size: 12px; color: var(--muted-foreground);
2147
+ }
2148
+
2149
+ /* Stripe-style split deliveries (two-column master-detail) */
2150
+ .whs { display: flex; flex: 1; min-height: 0; }
2151
+ .whs-list {
2152
+ width: 384px; flex-shrink: 0; display: flex; flex-direction: column; min-height: 0;
2153
+ border-right: 1px solid var(--border); background: var(--card);
2154
+ }
2155
+ .whs-toolbar {
2156
+ padding: 9px 11px 10px; border-bottom: 1px solid var(--border);
2157
+ display: flex; flex-direction: column; gap: 8px; flex-shrink: 0;
2158
+ }
2159
+ .whs-search2 { width: 100%; }
2160
+ .whs-chips { display: flex; flex-wrap: wrap; gap: 4px; }
2161
+ .whs-count {
2162
+ font-family: var(--font-mono); font-size: 10.5px; color: var(--muted-foreground); padding-top: 1px;
2163
+ }
2164
+ .whs-scroll { overflow: auto; flex: 1; min-height: 0; }
2165
+ .whs-item {
2166
+ display: flex; width: 100%; text-align: left; background: transparent;
2167
+ border: 0; border-bottom: 1px solid var(--border); padding: 0; cursor: pointer; position: relative;
2168
+ }
2169
+ .whs-item:hover { background: var(--accent); }
2170
+ .whs-item[data-selected="1"] { background: color-mix(in oklch, var(--primary) 12%, var(--card)); }
2171
+ .whs-accent { width: 2px; flex-shrink: 0; background: transparent; }
2172
+ .whs-item[data-selected="1"] .whs-accent { background: var(--primary); }
2173
+ .whs-item-main { flex: 1; min-width: 0; padding: 6px 12px 7px; display: flex; flex-direction: column; gap: 3px; }
2174
+ .whs-item-top { display: flex; align-items: center; gap: 8px; }
2175
+ .whs-ev {
2176
+ font-family: var(--font-mono); font-size: 12.5px; font-weight: 500; color: var(--foreground);
2177
+ overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
2178
+ }
2179
+ .whs-time { margin-left: auto; font-family: var(--font-mono); font-size: 10.5px; color: var(--muted-foreground); flex-shrink: 0; }
2180
+ .whs-item-bot { display: flex; align-items: center; gap: 7px; min-width: 0; }
2181
+ .whs-ep {
2182
+ display: inline-flex; align-items: center; gap: 6px; flex: 1; min-width: 0;
2183
+ font-size: 11px; color: var(--muted-foreground); overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
2184
+ }
2185
+ .whs-ep .sq { width: 7px; height: 7px; flex-shrink: 0; }
2186
+ .whs-att-tag {
2187
+ font-family: var(--font-mono); font-size: 10.5px; flex-shrink: 0;
2188
+ color: var(--muted-foreground); display: inline-flex; align-items: center; gap: 3px;
2189
+ }
2190
+ .whs-att-tag.warn { color: var(--st-waiting-fg); }
2191
+ .whs-att-tag.err { color: var(--st-failed-fg); }
2192
+ .whs-att-tag svg { width: 11px; height: 11px; }
2193
+ .whs-empty {
2194
+ display: flex; flex-direction: column; align-items: center; gap: 9px;
2195
+ padding: 40px 16px; text-align: center; color: var(--muted-foreground); font-size: 12px;
2196
+ }
2197
+ .whs-empty .ico { width: 24px; height: 24px; opacity: 0.6; }
2198
+ .whs-detail { flex: 1; min-width: 0; display: flex; min-height: 0; }
2199
+ .whs-detail .panel, .whs-detail .wh-panel, .whs-detail .run-panel { width: auto; flex: 1; min-width: 0; animation: none; }
2200
+
2201
+ .panel-empty {
2202
+ flex: 1; display: grid; place-items: center; padding: 32px 20px; text-align: center;
2203
+ color: var(--muted-foreground); font-size: 12px;
2204
+ }