executable-stories-react 0.9.0 → 0.10.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.
package/dist/ssr.cjs CHANGED
@@ -42,63 +42,6 @@ var import_react2 = require("react");
42
42
  var import_react = require("react");
43
43
  var ReportContext = (0, import_react.createContext)(null);
44
44
 
45
- // src/context/ReportRoot.tsx
46
- var import_jsx_runtime = require("react/jsx-runtime");
47
- var EMPTY_CUSTOM = {};
48
- var EMPTY_RENDERERS = {};
49
- function ReportRoot({
50
- report,
51
- customRenderers,
52
- renderers,
53
- children
54
- }) {
55
- const value = (0, import_react2.useMemo)(
56
- () => ({
57
- report,
58
- customRenderers: customRenderers ?? EMPTY_CUSTOM,
59
- renderers: renderers ?? EMPTY_RENDERERS
60
- }),
61
- [report, customRenderers, renderers]
62
- );
63
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ReportContext.Provider, { value, children });
64
- }
65
-
66
- // src/hooks/useReport.ts
67
- var import_react3 = require("react");
68
- function useReport() {
69
- const ctx = (0, import_react3.useContext)(ReportContext);
70
- if (!ctx) {
71
- throw new Error(
72
- "useReport must be used inside <ReportRoot> or <Report>. Wrap your tree with one of those."
73
- );
74
- }
75
- return ctx.report;
76
- }
77
-
78
- // ../executable-stories-core/dist/utils/duration.js
79
- function formatDuration(ms) {
80
- if (ms < 1e3) {
81
- return `${Math.round(ms)} ms`;
82
- }
83
- if (ms < 6e4) {
84
- return `${(ms / 1e3).toFixed(2)} s`;
85
- }
86
- const minutes = Math.floor(ms / 6e4);
87
- const seconds = Math.floor(ms % 6e4 / 1e3);
88
- if (minutes < 60) {
89
- return seconds > 0 ? `${minutes}m ${seconds}s` : `${minutes}m`;
90
- }
91
- const hours = Math.floor(minutes / 60);
92
- const remainingMinutes = minutes % 60;
93
- return `${hours}h ${remainingMinutes}m`;
94
- }
95
-
96
- // src/components/doc/DocNote.tsx
97
- var import_jsx_runtime2 = require("react/jsx-runtime");
98
- function DocNote({ entry }) {
99
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "my-2 text-sm text-muted-foreground", children: entry.text });
100
- }
101
-
102
45
  // src/components/ui/badge.tsx
103
46
  var React = require("react");
104
47
  var import_class_variance_authority = require("class-variance-authority");
@@ -157,14 +100,249 @@ function Badge({
157
100
  });
158
101
  }
159
102
 
160
- // src/components/doc/DocTag.tsx
103
+ // src/components/doc/NarrativeBlocks.tsx
104
+ var import_jsx_runtime = require("react/jsx-runtime");
105
+ var FILE_TREE_TYPE = "file-tree";
106
+ var DATA_MODEL_TYPE = "data-model";
107
+ function isChangeKind(value) {
108
+ return value === "added" || value === "modified" || value === "removed" || value === "renamed";
109
+ }
110
+ function isRecord(value) {
111
+ return typeof value === "object" && value !== null && !Array.isArray(value);
112
+ }
113
+ function str(value) {
114
+ return typeof value === "string" && value !== "" ? value : void 0;
115
+ }
116
+ function AuthoredMarker({ authored }) {
117
+ if (authored !== "agent") return null;
118
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Badge, { variant: "outline", className: "border-border text-[10px] text-muted-foreground", children: "AI-authored, not verified by a run" });
119
+ }
120
+ function BlockFrame({
121
+ title,
122
+ authored,
123
+ children
124
+ }) {
125
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("figure", { className: "my-3", children: [
126
+ title || authored === "agent" ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("figcaption", { className: "mb-1.5 flex flex-wrap items-center gap-2", children: [
127
+ title ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "text-xs font-medium text-muted-foreground", children: title }) : null,
128
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AuthoredMarker, { authored })
129
+ ] }) : null,
130
+ children
131
+ ] });
132
+ }
133
+ function ChangeBadge({ change }) {
134
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Badge, { variant: "tag", className: "text-[10px]", children: change });
135
+ }
136
+ function parseFileTree(data) {
137
+ if (!isRecord(data) || !Array.isArray(data.files)) return void 0;
138
+ const files = [];
139
+ for (const raw of data.files) {
140
+ if (typeof raw === "string") {
141
+ if (raw) files.push({ path: raw });
142
+ continue;
143
+ }
144
+ if (!isRecord(raw)) continue;
145
+ const path = str(raw.path);
146
+ if (!path) continue;
147
+ files.push({
148
+ path,
149
+ change: isChangeKind(raw.change) ? raw.change : void 0,
150
+ note: str(raw.note)
151
+ });
152
+ }
153
+ if (files.length === 0) return void 0;
154
+ return { title: str(data.title), authored: str(data.authored), files };
155
+ }
156
+ function buildTree(files) {
157
+ const root = { name: "", children: /* @__PURE__ */ new Map() };
158
+ for (const file of files) {
159
+ const segments = file.path.split("/").filter(Boolean);
160
+ let node = root;
161
+ segments.forEach((segment, index) => {
162
+ let child = node.children.get(segment);
163
+ if (!child) {
164
+ child = { name: segment, children: /* @__PURE__ */ new Map() };
165
+ node.children.set(segment, child);
166
+ }
167
+ if (index === segments.length - 1) child.file = file;
168
+ node = child;
169
+ });
170
+ }
171
+ return root;
172
+ }
173
+ function sortedChildren(node) {
174
+ return [...node.children.values()].sort((a, b) => {
175
+ const aDir = a.children.size > 0;
176
+ const bDir = b.children.size > 0;
177
+ if (aDir !== bDir) return aDir ? -1 : 1;
178
+ return a.name.localeCompare(b.name);
179
+ });
180
+ }
181
+ function TreeBranch({ node, depth }) {
182
+ const children = sortedChildren(node);
183
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("ul", { className: cn("space-y-0.5", depth > 0 && "ml-3 border-l border-border/60 pl-3"), children: children.map((child) => {
184
+ const isDir = child.children.size > 0;
185
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("li", { children: [
186
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex flex-wrap items-baseline gap-2", children: [
187
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
188
+ "span",
189
+ {
190
+ className: cn(
191
+ "font-mono text-xs",
192
+ isDir ? "text-muted-foreground" : "text-foreground"
193
+ ),
194
+ children: isDir ? `${child.name}/` : child.name
195
+ }
196
+ ),
197
+ child.file?.change ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ChangeBadge, { change: child.file.change }) : null,
198
+ child.file?.note ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "text-xs text-muted-foreground", children: child.file.note }) : null
199
+ ] }),
200
+ isDir ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TreeBranch, { node: child, depth: depth + 1 }) : null
201
+ ] }, child.name);
202
+ }) });
203
+ }
204
+ function FileTreeBlock({ entry }) {
205
+ const data = parseFileTree(entry.data);
206
+ if (!data) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(UnreadableBlock, { entry });
207
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(BlockFrame, { title: data.title ?? "Files changed", authored: data.authored, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { tabIndex: 0, className: "overflow-x-auto rounded-md border border-border bg-card p-3", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TreeBranch, { node: buildTree(data.files), depth: 0 }) }) });
208
+ }
209
+ function parseDataModel(data) {
210
+ if (!isRecord(data) || !Array.isArray(data.fields)) return void 0;
211
+ const fields = [];
212
+ for (const raw of data.fields) {
213
+ if (!isRecord(raw)) continue;
214
+ const name = str(raw.name);
215
+ if (!name) continue;
216
+ fields.push({
217
+ name,
218
+ type: str(raw.type),
219
+ note: str(raw.note),
220
+ change: isChangeKind(raw.change) ? raw.change : void 0
221
+ });
222
+ }
223
+ if (fields.length === 0) return void 0;
224
+ return {
225
+ title: str(data.title),
226
+ authored: str(data.authored),
227
+ name: str(data.name),
228
+ fields
229
+ };
230
+ }
231
+ function DataModelBlock({ entry }) {
232
+ const data = parseDataModel(entry.data);
233
+ if (!data) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(UnreadableBlock, { entry });
234
+ const hasNotes = data.fields.some((f) => f.note);
235
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(BlockFrame, { title: data.title ?? data.name ?? "Data model", authored: data.authored, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { tabIndex: 0, className: "overflow-x-auto rounded-md border border-border", children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("table", { className: "w-full border-collapse text-sm", children: [
236
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("tr", { className: "bg-muted/50", children: [
237
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", { scope: "col", className: "border-b border-border px-3 py-2 text-left font-semibold", children: "Field" }),
238
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", { scope: "col", className: "border-b border-border px-3 py-2 text-left font-semibold", children: "Type" }),
239
+ hasNotes ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", { scope: "col", className: "border-b border-border px-3 py-2 text-left font-semibold", children: "Note" }) : null
240
+ ] }) }),
241
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("tbody", { children: data.fields.map((field) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("tr", { children: [
242
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", { className: "border-b border-border px-3 py-2", children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "flex flex-wrap items-center gap-2", children: [
243
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "font-mono text-xs text-foreground", children: field.name }),
244
+ field.change ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ChangeBadge, { change: field.change }) : null
245
+ ] }) }),
246
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", { className: "border-b border-border px-3 py-2 font-mono text-xs text-muted-foreground", children: field.type ?? "" }),
247
+ hasNotes ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", { className: "border-b border-border px-3 py-2 text-foreground", children: field.note ?? "" }) : null
248
+ ] }, field.name)) })
249
+ ] }) }) });
250
+ }
251
+ function UnreadableBlock({ entry }) {
252
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "my-2", "data-type": entry.type, children: [
253
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { className: "mb-1 text-xs font-medium text-muted-foreground", children: [
254
+ entry.type,
255
+ " (unrecognised shape)"
256
+ ] }),
257
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
258
+ "pre",
259
+ {
260
+ tabIndex: 0,
261
+ className: "overflow-x-auto rounded-md bg-muted p-3 font-mono text-xs text-foreground",
262
+ children: safeStringify(entry.data)
263
+ }
264
+ )
265
+ ] });
266
+ }
267
+ function safeStringify(value) {
268
+ try {
269
+ return JSON.stringify(value, null, 2);
270
+ } catch {
271
+ return String(value);
272
+ }
273
+ }
274
+ var narrativeBlockRenderers = {
275
+ [FILE_TREE_TYPE]: (entry) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(FileTreeBlock, { entry }),
276
+ [DATA_MODEL_TYPE]: (entry) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DataModelBlock, { entry })
277
+ };
278
+
279
+ // src/context/ReportRoot.tsx
280
+ var import_jsx_runtime2 = require("react/jsx-runtime");
281
+ var EMPTY_RENDERERS = {};
282
+ function ReportRoot({
283
+ report,
284
+ customRenderers,
285
+ renderers,
286
+ children
287
+ }) {
288
+ const value = (0, import_react2.useMemo)(
289
+ () => ({
290
+ report,
291
+ // Narrative blocks render everywhere the report does (static SSR, the
292
+ // island, Astro) without every host wiring them up. A host renderer for
293
+ // the same type still wins.
294
+ customRenderers: { ...narrativeBlockRenderers, ...customRenderers },
295
+ renderers: renderers ?? EMPTY_RENDERERS
296
+ }),
297
+ [report, customRenderers, renderers]
298
+ );
299
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(ReportContext.Provider, { value, children });
300
+ }
301
+
302
+ // src/hooks/useReport.ts
303
+ var import_react3 = require("react");
304
+ function useReport() {
305
+ const ctx = (0, import_react3.useContext)(ReportContext);
306
+ if (!ctx) {
307
+ throw new Error(
308
+ "useReport must be used inside <ReportRoot> or <Report>. Wrap your tree with one of those."
309
+ );
310
+ }
311
+ return ctx.report;
312
+ }
313
+
314
+ // ../executable-stories-core/dist/utils/duration.js
315
+ function formatDuration(ms) {
316
+ if (ms < 1e3) {
317
+ return `${Math.round(ms)} ms`;
318
+ }
319
+ if (ms < 6e4) {
320
+ return `${(ms / 1e3).toFixed(2)} s`;
321
+ }
322
+ const minutes = Math.floor(ms / 6e4);
323
+ const seconds = Math.floor(ms % 6e4 / 1e3);
324
+ if (minutes < 60) {
325
+ return seconds > 0 ? `${minutes}m ${seconds}s` : `${minutes}m`;
326
+ }
327
+ const hours = Math.floor(minutes / 60);
328
+ const remainingMinutes = minutes % 60;
329
+ return `${hours}h ${remainingMinutes}m`;
330
+ }
331
+
332
+ // src/components/doc/DocNote.tsx
161
333
  var import_jsx_runtime3 = require("react/jsx-runtime");
334
+ function DocNote({ entry }) {
335
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: "my-2 text-sm text-muted-foreground", children: entry.text });
336
+ }
337
+
338
+ // src/components/doc/DocTag.tsx
339
+ var import_jsx_runtime4 = require("react/jsx-runtime");
162
340
  function DocTag({ entry }) {
163
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("ul", { className: "my-2 flex flex-wrap gap-1.5", "aria-label": "Tags", children: entry.names.map((n) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Badge, { variant: "tag", children: n }) }, n)) });
341
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("ul", { className: "my-2 flex flex-wrap gap-1.5", "aria-label": "Tags", children: entry.names.map((n) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Badge, { variant: "tag", children: n }) }, n)) });
164
342
  }
165
343
 
166
344
  // src/components/doc/DocKv.tsx
167
- var import_jsx_runtime4 = require("react/jsx-runtime");
345
+ var import_jsx_runtime5 = require("react/jsx-runtime");
168
346
  function formatValue(value) {
169
347
  if (value === null) return "null";
170
348
  if (typeof value === "string") return value;
@@ -176,19 +354,19 @@ function formatValue(value) {
176
354
  }
177
355
  }
178
356
  function DocKv({ entry }) {
179
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("dl", { className: "my-2 flex flex-wrap items-baseline gap-x-2 text-sm", children: [
180
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("dt", { className: "font-semibold text-muted-foreground", children: entry.label }),
181
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("dd", { className: "font-mono text-foreground", children: formatValue(entry.value) })
357
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("dl", { className: "my-2 flex flex-wrap items-baseline gap-x-2 text-sm", children: [
358
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("dt", { className: "font-semibold text-muted-foreground", children: entry.label }),
359
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("dd", { className: "font-mono text-foreground", children: formatValue(entry.value) })
182
360
  ] });
183
361
  }
184
362
 
185
363
  // src/hooks/useRenderers.ts
186
364
  var import_react4 = require("react");
187
- var EMPTY_CUSTOM2 = {};
365
+ var EMPTY_CUSTOM = {};
188
366
  var EMPTY_RENDERERS2 = {};
189
367
  function useCustomRenderers() {
190
368
  const ctx = (0, import_react4.useContext)(ReportContext);
191
- return ctx?.customRenderers ?? EMPTY_CUSTOM2;
369
+ return ctx?.customRenderers ?? EMPTY_CUSTOM;
192
370
  }
193
371
  function useBuiltinRenderers() {
194
372
  const ctx = (0, import_react4.useContext)(ReportContext);
@@ -196,37 +374,37 @@ function useBuiltinRenderers() {
196
374
  }
197
375
 
198
376
  // src/components/doc/DocCode.tsx
199
- var import_jsx_runtime5 = require("react/jsx-runtime");
377
+ var import_jsx_runtime6 = require("react/jsx-runtime");
200
378
  function CodeFigure({ label, children }) {
201
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("figure", { className: "my-3", children: [
202
- label ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("figcaption", { className: "mb-1.5 text-xs font-medium text-muted-foreground", children: label }) : null,
203
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("pre", { tabIndex: 0, className: "overflow-x-auto rounded-md bg-muted p-3", children })
379
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("figure", { className: "my-3", children: [
380
+ label ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("figcaption", { className: "mb-1.5 text-xs font-medium text-muted-foreground", children: label }) : null,
381
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("pre", { tabIndex: 0, className: "overflow-x-auto rounded-md bg-muted p-3", children })
204
382
  ] });
205
383
  }
206
384
  function DocCode({ entry }) {
207
385
  const renderers = useBuiltinRenderers();
208
386
  if (renderers.code) {
209
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_jsx_runtime5.Fragment, { children: renderers.code(entry) });
387
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_jsx_runtime6.Fragment, { children: renderers.code(entry) });
210
388
  }
211
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(CodeFigure, { label: entry.label, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("code", { className: cn("font-mono text-xs", entry.lang && `language-${entry.lang}`), children: entry.content }) });
389
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(CodeFigure, { label: entry.label, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("code", { className: cn("font-mono text-xs", entry.lang && `language-${entry.lang}`), children: entry.content }) });
212
390
  }
213
391
 
214
392
  // src/components/doc/DocTable.tsx
215
- var import_jsx_runtime6 = require("react/jsx-runtime");
393
+ var import_jsx_runtime7 = require("react/jsx-runtime");
216
394
  function DocTable({ entry }) {
217
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("figure", { className: "my-3", children: [
218
- entry.label ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("figcaption", { className: "mb-1.5 text-xs font-medium text-muted-foreground", children: entry.label }) : null,
219
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { tabIndex: 0, className: "overflow-x-auto rounded-md border border-border", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("table", { className: "w-full border-collapse text-sm", children: [
220
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("tr", { className: "bg-muted/50", children: entry.columns.map((c) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("th", { scope: "col", className: "border-b border-border px-3 py-2 text-left font-semibold", children: c }, c)) }) }),
221
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("tbody", { children: entry.rows.map((row, i) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("tr", { children: row.map((cell, j) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("td", { className: "border-b border-border px-3 py-2 text-foreground", children: cell }, j)) }, i)) })
395
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("figure", { className: "my-3", children: [
396
+ entry.label ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("figcaption", { className: "mb-1.5 text-xs font-medium text-muted-foreground", children: entry.label }) : null,
397
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { tabIndex: 0, className: "overflow-x-auto rounded-md border border-border", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("table", { className: "w-full border-collapse text-sm", children: [
398
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("tr", { className: "bg-muted/50", children: entry.columns.map((c) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("th", { scope: "col", className: "border-b border-border px-3 py-2 text-left font-semibold", children: c }, c)) }) }),
399
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("tbody", { children: entry.rows.map((row, i) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("tr", { children: row.map((cell, j) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("td", { className: "border-b border-border px-3 py-2 text-foreground", children: cell }, j)) }, i)) })
222
400
  ] }) })
223
401
  ] });
224
402
  }
225
403
 
226
404
  // src/components/doc/DocLink.tsx
227
- var import_jsx_runtime7 = require("react/jsx-runtime");
405
+ var import_jsx_runtime8 = require("react/jsx-runtime");
228
406
  function DocLink({ entry }) {
229
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
407
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
230
408
  "a",
231
409
  {
232
410
  className: "text-sm font-medium text-primary underline underline-offset-2 hover:no-underline",
@@ -260,7 +438,7 @@ function isLocalFsPath(value) {
260
438
  }
261
439
 
262
440
  // src/components/doc/DocSection.tsx
263
- var import_jsx_runtime8 = require("react/jsx-runtime");
441
+ var import_jsx_runtime9 = require("react/jsx-runtime");
264
442
  function neutralizeUrl(value) {
265
443
  return safeUrl(value) ?? "#";
266
444
  }
@@ -271,12 +449,12 @@ function safeMarkdownHtml(markdown) {
271
449
  function DocSection({ entry }) {
272
450
  const renderers = useBuiltinRenderers();
273
451
  if (renderers.section) {
274
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_jsx_runtime8.Fragment, { children: renderers.section(entry) });
452
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_jsx_runtime9.Fragment, { children: renderers.section(entry) });
275
453
  }
276
454
  const html = safeMarkdownHtml(entry.markdown);
277
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("section", { className: "my-3 text-sm", "aria-label": entry.title, children: [
278
- entry.title ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("h4", { className: "mb-1 font-semibold text-foreground", children: entry.title }) : null,
279
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
455
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("section", { className: "my-3 text-sm", "aria-label": entry.title, children: [
456
+ entry.title ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("h4", { className: "mb-1 font-semibold text-foreground", children: entry.title }) : null,
457
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
280
458
  "div",
281
459
  {
282
460
  className: "es-doc-prose prose prose-sm max-w-none",
@@ -287,11 +465,11 @@ function DocSection({ entry }) {
287
465
  }
288
466
 
289
467
  // src/components/doc/DocMermaid.tsx
290
- var import_jsx_runtime9 = require("react/jsx-runtime");
468
+ var import_jsx_runtime10 = require("react/jsx-runtime");
291
469
  function MermaidSource({ entry, ref }) {
292
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("figure", { ref, className: "my-3", "aria-label": entry.title ?? "Diagram", children: [
293
- entry.title ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("figcaption", { className: "mb-1.5 text-xs font-medium text-muted-foreground", children: entry.title }) : null,
294
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
470
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("figure", { ref, className: "my-3", "aria-label": entry.title ?? "Diagram", children: [
471
+ entry.title ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("figcaption", { className: "mb-1.5 text-xs font-medium text-muted-foreground", children: entry.title }) : null,
472
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
295
473
  "pre",
296
474
  {
297
475
  "data-mermaid": true,
@@ -305,24 +483,24 @@ function MermaidSource({ entry, ref }) {
305
483
  function DocMermaid({ entry }) {
306
484
  const renderers = useBuiltinRenderers();
307
485
  if (renderers.mermaid) {
308
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_jsx_runtime9.Fragment, { children: renderers.mermaid(entry) });
486
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_jsx_runtime10.Fragment, { children: renderers.mermaid(entry) });
309
487
  }
310
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(MermaidSource, { entry });
488
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(MermaidSource, { entry });
311
489
  }
312
490
 
313
491
  // src/components/doc/DocScreenshot.tsx
314
- var import_jsx_runtime10 = require("react/jsx-runtime");
492
+ var import_jsx_runtime11 = require("react/jsx-runtime");
315
493
  function DocScreenshot({ entry }) {
316
494
  const src = isLocalFsPath(entry.path) ? void 0 : safeImageUrl(entry.path);
317
495
  if (!src) {
318
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("figure", { className: "my-3 rounded-md border border-dashed border-border p-3 text-sm text-muted-foreground", children: [
319
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "font-medium", children: "Screenshot unavailable" }),
320
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "mt-1 break-all font-mono text-xs", children: entry.path }),
321
- entry.alt ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("figcaption", { className: "mt-1.5 text-xs", children: entry.alt }) : null
496
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("figure", { className: "my-3 rounded-md border border-dashed border-border p-3 text-sm text-muted-foreground", children: [
497
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "font-medium", children: "Screenshot unavailable" }),
498
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "mt-1 break-all font-mono text-xs", children: entry.path }),
499
+ entry.alt ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("figcaption", { className: "mt-1.5 text-xs", children: entry.alt }) : null
322
500
  ] });
323
501
  }
324
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("figure", { className: "my-3", children: [
325
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
502
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("figure", { className: "my-3", children: [
503
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
326
504
  "img",
327
505
  {
328
506
  src,
@@ -331,24 +509,24 @@ function DocScreenshot({ entry }) {
331
509
  className: "max-w-full rounded-md border border-border"
332
510
  }
333
511
  ),
334
- entry.alt ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("figcaption", { className: "mt-1.5 text-xs text-muted-foreground", children: entry.alt }) : null
512
+ entry.alt ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("figcaption", { className: "mt-1.5 text-xs text-muted-foreground", children: entry.alt }) : null
335
513
  ] });
336
514
  }
337
515
 
338
516
  // src/components/doc/DocVideo.tsx
339
- var import_jsx_runtime11 = require("react/jsx-runtime");
517
+ var import_jsx_runtime12 = require("react/jsx-runtime");
340
518
  function DocVideo({ entry }) {
341
519
  if (isLocalFsPath(entry.path)) {
342
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("figure", { className: "my-3 rounded-md border border-dashed border-border p-3 text-sm text-muted-foreground", children: [
343
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "font-medium", children: "Video unavailable" }),
344
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "mt-1 break-all font-mono text-xs", children: entry.path }),
345
- entry.caption ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("figcaption", { className: "mt-1.5 text-xs", children: entry.caption }) : null
520
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("figure", { className: "my-3 rounded-md border border-dashed border-border p-3 text-sm text-muted-foreground", children: [
521
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "font-medium", children: "Video unavailable" }),
522
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "mt-1 break-all font-mono text-xs", children: entry.path }),
523
+ entry.caption ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("figcaption", { className: "mt-1.5 text-xs", children: entry.caption }) : null
346
524
  ] });
347
525
  }
348
526
  const src = safeUrl(entry.path);
349
527
  const poster = safeUrl(entry.poster);
350
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("figure", { className: "my-3", children: [
351
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
528
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("figure", { className: "my-3", children: [
529
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
352
530
  "video",
353
531
  {
354
532
  controls: true,
@@ -358,21 +536,21 @@ function DocVideo({ entry }) {
358
536
  className: "max-w-full rounded-md border border-border"
359
537
  }
360
538
  ),
361
- entry.caption ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("figcaption", { className: "mt-1 text-xs text-muted-foreground", children: entry.caption }) : null
539
+ entry.caption ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("figcaption", { className: "mt-1 text-xs text-muted-foreground", children: entry.caption }) : null
362
540
  ] });
363
541
  }
364
542
 
365
543
  // src/components/doc/DocHtml.tsx
366
- var import_jsx_runtime12 = require("react/jsx-runtime");
544
+ var import_jsx_runtime13 = require("react/jsx-runtime");
367
545
  function DocHtml({ entry }) {
368
546
  const height = typeof entry.height === "number" ? `${entry.height}px` : entry.height ?? "400px";
369
547
  const title = entry.title ?? "Embedded HTML";
370
548
  const safeHref = safeUrl(entry.url ?? entry.path);
371
549
  const frameProps = entry.content !== void 0 ? { srcDoc: entry.content } : { src: safeHref ?? "" };
372
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("figure", { className: "my-3 overflow-hidden rounded-md border border-border", children: [
373
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("figcaption", { className: "flex items-center justify-between border-b border-border bg-muted/40 px-3 py-1.5 text-xs font-medium text-muted-foreground", children: [
374
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { children: entry.title ?? "HTML" }),
375
- safeHref ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
550
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("figure", { className: "my-3 overflow-hidden rounded-md border border-border", children: [
551
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("figcaption", { className: "flex items-center justify-between border-b border-border bg-muted/40 px-3 py-1.5 text-xs font-medium text-muted-foreground", children: [
552
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { children: entry.title ?? "HTML" }),
553
+ safeHref ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
376
554
  "a",
377
555
  {
378
556
  href: safeHref,
@@ -385,7 +563,7 @@ function DocHtml({ entry }) {
385
563
  }
386
564
  ) : null
387
565
  ] }),
388
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
566
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
389
567
  "iframe",
390
568
  {
391
569
  ...frameProps,
@@ -400,7 +578,7 @@ function DocHtml({ entry }) {
400
578
  }
401
579
 
402
580
  // src/components/doc/DocState.tsx
403
- var import_jsx_runtime13 = require("react/jsx-runtime");
581
+ var import_jsx_runtime14 = require("react/jsx-runtime");
404
582
  function DocState({ entry }) {
405
583
  let json;
406
584
  try {
@@ -408,23 +586,23 @@ function DocState({ entry }) {
408
586
  } catch {
409
587
  json = String(entry.value);
410
588
  }
411
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(CodeFigure, { label: entry.label ?? "State", children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("code", { className: "font-mono text-xs language-json", children: json }) });
589
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(CodeFigure, { label: entry.label ?? "State", children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("code", { className: "font-mono text-xs language-json", children: json }) });
412
590
  }
413
591
 
414
592
  // src/components/doc/DocCustom.tsx
415
- var import_jsx_runtime14 = require("react/jsx-runtime");
593
+ var import_jsx_runtime15 = require("react/jsx-runtime");
416
594
  function DocCustom({ entry }) {
417
595
  const renderers = useCustomRenderers();
418
596
  const renderer = renderers[entry.type];
419
597
  if (renderer) {
420
- return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_jsx_runtime14.Fragment, { children: renderer(entry) });
598
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_jsx_runtime15.Fragment, { children: renderer(entry) });
421
599
  }
422
- return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "my-2", "data-type": entry.type, children: [
423
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("p", { className: "mb-1 text-xs font-medium text-muted-foreground", children: entry.type }),
424
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("pre", { tabIndex: 0, className: "overflow-x-auto rounded-md bg-muted p-3 font-mono text-xs text-foreground", children: safeStringify(entry.data) })
600
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "my-2", "data-type": entry.type, children: [
601
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("p", { className: "mb-1 text-xs font-medium text-muted-foreground", children: entry.type }),
602
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("pre", { tabIndex: 0, className: "overflow-x-auto rounded-md bg-muted p-3 font-mono text-xs text-foreground", children: safeStringify2(entry.data) })
425
603
  ] });
426
604
  }
427
- function safeStringify(value) {
605
+ function safeStringify2(value) {
428
606
  try {
429
607
  return JSON.stringify(value, null, 2);
430
608
  } catch {
@@ -433,47 +611,47 @@ function safeStringify(value) {
433
611
  }
434
612
 
435
613
  // src/components/doc/DocEntry.tsx
436
- var import_jsx_runtime15 = require("react/jsx-runtime");
614
+ var import_jsx_runtime16 = require("react/jsx-runtime");
437
615
  function DocEntry({ entry }) {
438
616
  switch (entry.kind) {
439
617
  case "note":
440
- return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(DocNote, { entry });
618
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(DocNote, { entry });
441
619
  case "tag":
442
- return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(DocTag, { entry });
620
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(DocTag, { entry });
443
621
  case "kv":
444
- return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(DocKv, { entry });
622
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(DocKv, { entry });
445
623
  case "code":
446
- return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(DocCode, { entry });
624
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(DocCode, { entry });
447
625
  case "table":
448
- return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(DocTable, { entry });
626
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(DocTable, { entry });
449
627
  case "link":
450
- return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(DocLink, { entry });
628
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(DocLink, { entry });
451
629
  case "section":
452
- return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(DocSection, { entry });
630
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(DocSection, { entry });
453
631
  case "mermaid":
454
- return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(DocMermaid, { entry });
632
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(DocMermaid, { entry });
455
633
  case "screenshot":
456
- return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(DocScreenshot, { entry });
634
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(DocScreenshot, { entry });
457
635
  case "video":
458
- return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(DocVideo, { entry });
636
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(DocVideo, { entry });
459
637
  case "html":
460
- return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(DocHtml, { entry });
638
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(DocHtml, { entry });
461
639
  case "state":
462
- return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(DocState, { entry });
640
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(DocState, { entry });
463
641
  case "custom":
464
- return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(DocCustom, { entry });
642
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(DocCustom, { entry });
465
643
  }
466
644
  }
467
645
 
468
646
  // src/components/ReportDocEntries.tsx
469
- var import_jsx_runtime16 = require("react/jsx-runtime");
647
+ var import_jsx_runtime17 = require("react/jsx-runtime");
470
648
  function ReportDocEntries({ entries }) {
471
649
  if (entries.length === 0) return null;
472
- return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_jsx_runtime16.Fragment, { children: entries.map((entry, i) => /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(DocEntry, { entry }, i)) });
650
+ return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_jsx_runtime17.Fragment, { children: entries.map((entry, i) => /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(DocEntry, { entry }, i)) });
473
651
  }
474
652
 
475
653
  // src/lib/step-params.tsx
476
- var import_jsx_runtime17 = require("react/jsx-runtime");
654
+ var import_jsx_runtime18 = require("react/jsx-runtime");
477
655
  var STEP_PARAM_PATTERN = /"[^"]*"|(?<![\w.-])\d+(?:\.\d+)?(?![\w.-])/g;
478
656
  function highlightStepParams(text) {
479
657
  const matches = Array.from(text.matchAll(STEP_PARAM_PATTERN));
@@ -485,7 +663,7 @@ function highlightStepParams(text) {
485
663
  const end = start + match[0].length;
486
664
  if (start > lastIndex) nodes.push(text.slice(lastIndex, start));
487
665
  nodes.push(
488
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "font-medium text-step-param italic", children: match[0] }, i)
666
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "font-medium text-step-param italic", children: match[0] }, i)
489
667
  );
490
668
  lastIndex = end;
491
669
  });
@@ -494,7 +672,7 @@ function highlightStepParams(text) {
494
672
  }
495
673
 
496
674
  // src/components/ReportSteps.tsx
497
- var import_jsx_runtime18 = require("react/jsx-runtime");
675
+ var import_jsx_runtime19 = require("react/jsx-runtime");
498
676
  var STEP_GLYPH = {
499
677
  passed: "\u2713",
500
678
  failed: "\u2717",
@@ -509,21 +687,21 @@ var STEP_GLYPH_COLOR = {
509
687
  };
510
688
  function ReportSteps({ scenario }) {
511
689
  if (scenario.steps.length === 0) return null;
512
- return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("ol", { "data-slot": "steps", className: "flex flex-col", children: scenario.steps.map((step) => /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(ReportStepItem, { step }, step.id)) });
690
+ return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("ol", { "data-slot": "steps", className: "flex flex-col", children: scenario.steps.map((step) => /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(ReportStepItem, { step }, step.id)) });
513
691
  }
514
692
  function ReportStepItem({ step }) {
515
693
  const kw = step.keyword.toLowerCase();
516
694
  const continuation = kw === "and" || kw === "but";
517
- return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
695
+ return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(
518
696
  "li",
519
697
  {
520
698
  id: step.id,
521
699
  "data-status": step.status,
522
700
  className: cn("py-1.5 text-[0.8125rem] leading-normal", continuation && "pl-5"),
523
701
  children: [
524
- /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "flex items-baseline gap-2", children: [
525
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { "aria-hidden": true, className: cn("w-4 shrink-0 text-center text-xs", STEP_GLYPH_COLOR[step.status]), children: STEP_GLYPH[step.status] ?? "\u25CB" }),
526
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
702
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "flex items-baseline gap-2", children: [
703
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { "aria-hidden": true, className: cn("w-4 shrink-0 text-center text-xs", STEP_GLYPH_COLOR[step.status]), children: STEP_GLYPH[step.status] ?? "\u25CB" }),
704
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
527
705
  "span",
528
706
  {
529
707
  className: cn(
@@ -533,10 +711,10 @@ function ReportStepItem({ step }) {
533
711
  children: step.keyword
534
712
  }
535
713
  ),
536
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "flex-1 text-foreground", children: highlightStepParams(step.text) }),
537
- step.durationMs > 0 ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "shrink-0 whitespace-nowrap font-mono text-[0.6875rem] text-muted-foreground", children: formatDuration(step.durationMs) }) : null
714
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "flex-1 text-foreground", children: highlightStepParams(step.text) }),
715
+ step.durationMs > 0 ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "shrink-0 whitespace-nowrap font-mono text-[0.6875rem] text-muted-foreground", children: formatDuration(step.durationMs) }) : null
538
716
  ] }),
539
- step.errorMessage ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
717
+ step.errorMessage ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
540
718
  "pre",
541
719
  {
542
720
  role: "alert",
@@ -544,7 +722,7 @@ function ReportStepItem({ step }) {
544
722
  children: step.errorMessage
545
723
  }
546
724
  ) : null,
547
- step.docEntries.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { "data-es-docs": true, className: "mt-2 ml-6", children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(ReportDocEntries, { entries: step.docEntries }) }) : null
725
+ step.docEntries.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { "data-es-docs": true, className: "mt-2 ml-6", children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(ReportDocEntries, { entries: step.docEntries }) }) : null
548
726
  ]
549
727
  }
550
728
  );
@@ -669,7 +847,7 @@ function extractStoryboardFrames(scenario) {
669
847
  }
670
848
 
671
849
  // src/components/ReportStoryboard.tsx
672
- var import_jsx_runtime19 = require("react/jsx-runtime");
850
+ var import_jsx_runtime20 = require("react/jsx-runtime");
673
851
  var FRAME_GLYPH = {
674
852
  passed: "\u2713",
675
853
  failed: "\u2717",
@@ -685,32 +863,32 @@ var FRAME_GLYPH_COLOR = {
685
863
  function ReportStoryboard({ scenario }) {
686
864
  const frames = extractStoryboardFrames(scenario);
687
865
  if (frames.length < 2) return null;
688
- return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("section", { "data-slot": "storyboard", "aria-label": "Storyboard", className: "mb-3", children: [
689
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("h4", { className: "mb-1.5 text-xs font-semibold tracking-wide text-muted-foreground uppercase", children: "Storyboard" }),
690
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("ol", { className: "flex items-start gap-3 overflow-x-auto pb-2", children: frames.map((frame) => /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(StoryboardFrameItem, { frame }, frame.stepId)) })
866
+ return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("section", { "data-slot": "storyboard", "aria-label": "Storyboard", className: "mb-3", children: [
867
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("h4", { className: "mb-1.5 text-xs font-semibold tracking-wide text-muted-foreground uppercase", children: "Storyboard" }),
868
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("ol", { className: "flex items-start gap-3 overflow-x-auto pb-2", children: frames.map((frame) => /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(StoryboardFrameItem, { frame }, frame.stepId)) })
691
869
  ] });
692
870
  }
693
871
  function StoryboardFrameItem({ frame }) {
694
872
  const label = `${frame.keyword} ${frame.text}`;
695
873
  const hasStates = frame.states.length > 0;
696
- const caption = /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("p", { className: "mt-1 flex items-baseline gap-1.5 text-[0.6875rem] leading-snug", children: [
697
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { "aria-hidden": true, className: cn("shrink-0", FRAME_GLYPH_COLOR[frame.status]), children: FRAME_GLYPH[frame.status] ?? "\u25CB" }),
698
- /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("span", { className: "min-w-0", children: [
699
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "font-mono font-semibold text-keyword", children: frame.keyword }),
874
+ const caption = /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("p", { className: "mt-1 flex items-baseline gap-1.5 text-[0.6875rem] leading-snug", children: [
875
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { "aria-hidden": true, className: cn("shrink-0", FRAME_GLYPH_COLOR[frame.status]), children: FRAME_GLYPH[frame.status] ?? "\u25CB" }),
876
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("span", { className: "min-w-0", children: [
877
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { className: "font-mono font-semibold text-keyword", children: frame.keyword }),
700
878
  " ",
701
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "text-muted-foreground", children: frame.screenshot?.alt ?? frame.text })
879
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { className: "text-muted-foreground", children: frame.screenshot?.alt ?? frame.text })
702
880
  ] })
703
881
  ] });
704
882
  return (
705
883
  // State cards need room for diff rows; screenshot-only frames keep the
706
884
  // original narrow film-cell width (and DOM) unchanged.
707
- /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("li", { className: cn("shrink-0", hasStates ? "w-64" : "w-40"), children: [
708
- frame.screenshot ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(FrameScreenshot, { frame, label }) : null,
709
- hasStates ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { className: cn("flex flex-col gap-1.5", frame.screenshot && "mt-1.5"), children: frame.states.map((card, i) => /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(StateCardView, { card }, card.label ?? i)) }) : null,
885
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("li", { className: cn("shrink-0", hasStates ? "w-64" : "w-40"), children: [
886
+ frame.screenshot ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(FrameScreenshot, { frame, label }) : null,
887
+ hasStates ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { className: cn("flex flex-col gap-1.5", frame.screenshot && "mt-1.5"), children: frame.states.map((card, i) => /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(StateCardView, { card }, card.label ?? i)) }) : null,
710
888
  frame.screenshot ? caption : (
711
889
  // No screenshot means no image anchor, so the caption carries the
712
890
  // jump-to-step link instead.
713
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("a", { href: `#${frame.stepId}`, "aria-label": `Jump to step: ${label}`, className: "block hover:underline", children: caption })
891
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("a", { href: `#${frame.stepId}`, "aria-label": `Jump to step: ${label}`, className: "block hover:underline", children: caption })
714
892
  )
715
893
  ] })
716
894
  );
@@ -718,13 +896,13 @@ function StoryboardFrameItem({ frame }) {
718
896
  function FrameScreenshot({ frame, label }) {
719
897
  const path = frame.screenshot?.path ?? "";
720
898
  const src = isLocalFsPath(path) ? void 0 : safeImageUrl(path);
721
- return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
899
+ return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
722
900
  "a",
723
901
  {
724
902
  href: `#${frame.stepId}`,
725
903
  "aria-label": `Jump to step: ${label}`,
726
904
  className: "block overflow-hidden rounded-md border border-border transition-colors hover:border-ring",
727
- children: src ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
905
+ children: src ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
728
906
  "img",
729
907
  {
730
908
  src,
@@ -732,7 +910,7 @@ function FrameScreenshot({ frame, label }) {
732
910
  loading: "lazy",
733
911
  className: "h-24 w-full bg-muted object-cover object-top"
734
912
  }
735
- ) : /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "flex h-24 w-full items-center justify-center border-b border-dashed border-border bg-muted px-2 text-center text-[0.6875rem] text-muted-foreground", children: "Screenshot unavailable" })
913
+ ) : /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { className: "flex h-24 w-full items-center justify-center border-b border-dashed border-border bg-muted px-2 text-center text-[0.6875rem] text-muted-foreground", children: "Screenshot unavailable" })
736
914
  }
737
915
  );
738
916
  }
@@ -751,12 +929,12 @@ function prettyJson(value) {
751
929
  function StateCardView({ card }) {
752
930
  const json = prettyJson(card.value);
753
931
  const firstCapture = card.changes === void 0;
754
- return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { "data-slot": "state-card", className: "rounded-md border border-border bg-card p-2", children: [
755
- /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("p", { className: "flex flex-wrap items-baseline gap-1.5", children: [
756
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "inline-flex rounded-full border border-border px-1.5 font-mono text-[0.625rem] font-medium text-muted-foreground", children: card.label ?? "State" }),
757
- firstCapture ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "text-[0.625rem] text-muted-foreground italic", children: "first capture" }) : null
932
+ return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { "data-slot": "state-card", className: "rounded-md border border-border bg-card p-2", children: [
933
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("p", { className: "flex flex-wrap items-baseline gap-1.5", children: [
934
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { className: "inline-flex rounded-full border border-border px-1.5 font-mono text-[0.625rem] font-medium text-muted-foreground", children: card.label ?? "State" }),
935
+ firstCapture ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { className: "text-[0.625rem] text-muted-foreground italic", children: "first capture" }) : null
758
936
  ] }),
759
- !firstCapture && (card.changes && card.changes.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("ul", { className: "mt-1.5 flex flex-col gap-0.5", children: card.changes.map((change, i) => /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
937
+ !firstCapture && (card.changes && card.changes.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("ul", { className: "mt-1.5 flex flex-col gap-0.5", children: card.changes.map((change, i) => /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
760
938
  "li",
761
939
  {
762
940
  className: cn(
@@ -766,15 +944,15 @@ function StateCardView({ card }) {
766
944
  children: summarizeStateChanges([change])[0]
767
945
  },
768
946
  i
769
- )) }) : /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("p", { className: "mt-1.5 text-[0.625rem] text-muted-foreground", children: "No changes" })),
770
- /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(
947
+ )) }) : /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("p", { className: "mt-1.5 text-[0.625rem] text-muted-foreground", children: "No changes" })),
948
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
771
949
  "details",
772
950
  {
773
951
  open: firstCapture && json.length <= 240,
774
952
  className: cn(firstCapture ? "mt-1.5" : "mt-1"),
775
953
  children: [
776
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("summary", { className: "cursor-pointer text-[0.625rem] text-muted-foreground hover:text-foreground", children: "Snapshot" }),
777
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("pre", { tabIndex: 0, className: "mt-1 max-h-48 overflow-auto rounded-sm bg-muted p-1.5 font-mono text-[0.625rem] leading-snug", children: json })
954
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("summary", { className: "cursor-pointer text-[0.625rem] text-muted-foreground hover:text-foreground", children: "Snapshot" }),
955
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("pre", { tabIndex: 0, className: "mt-1 max-h-48 overflow-auto rounded-sm bg-muted p-1.5 font-mono text-[0.625rem] leading-snug", children: json })
778
956
  ]
779
957
  }
780
958
  )
@@ -782,17 +960,17 @@ function StateCardView({ card }) {
782
960
  }
783
961
 
784
962
  // src/components/ReportAttachments.tsx
785
- var import_jsx_runtime20 = require("react/jsx-runtime");
963
+ var import_jsx_runtime21 = require("react/jsx-runtime");
786
964
  function ReportAttachments({ attachments }) {
787
965
  if (attachments.length === 0) return null;
788
966
  return (
789
967
  // role="group" (not a labelled <section>) so multiple scenarios' attachment
790
968
  // blocks don't create duplicate "Attachments" region landmarks.
791
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { role: "group", "aria-label": "Attachments", className: "mt-3 flex flex-col gap-2", children: attachments.map((att, i) => {
969
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { role: "group", "aria-label": "Attachments", className: "mt-3 flex flex-col gap-2", children: attachments.map((att, i) => {
792
970
  const dataUri = att.contentEncoding === "BASE64" ? `data:${att.mediaType};base64,${att.body}` : `data:${att.mediaType},${encodeURIComponent(att.body)}`;
793
971
  const isImage = att.mediaType.startsWith("image/");
794
- return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("figure", { className: "m-0", children: isImage ? /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(import_jsx_runtime20.Fragment, { children: [
795
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
972
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("figure", { className: "m-0", children: isImage ? /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_jsx_runtime21.Fragment, { children: [
973
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
796
974
  "img",
797
975
  {
798
976
  src: dataUri,
@@ -801,8 +979,8 @@ function ReportAttachments({ attachments }) {
801
979
  className: "max-w-full rounded-md border border-border"
802
980
  }
803
981
  ),
804
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("figcaption", { className: "mt-1 text-xs text-muted-foreground", children: att.name })
805
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
982
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("figcaption", { className: "mt-1 text-xs text-muted-foreground", children: att.name })
983
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
806
984
  "a",
807
985
  {
808
986
  href: dataUri,
@@ -811,7 +989,7 @@ function ReportAttachments({ attachments }) {
811
989
  children: [
812
990
  att.name,
813
991
  " ",
814
- /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("span", { className: "text-muted-foreground", children: [
992
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("span", { className: "text-muted-foreground", children: [
815
993
  "(",
816
994
  att.mediaType,
817
995
  ")"
@@ -899,7 +1077,7 @@ function traceWindow(rows) {
899
1077
  }
900
1078
 
901
1079
  // src/components/ReportTrace.tsx
902
- var import_jsx_runtime21 = require("react/jsx-runtime");
1080
+ var import_jsx_runtime22 = require("react/jsx-runtime");
903
1081
  var BAR_COLOR = {
904
1082
  ok: "bg-pass",
905
1083
  error: "bg-fail",
@@ -910,8 +1088,8 @@ function ReportTrace({ spans }) {
910
1088
  const rows = toTraceRows(spans);
911
1089
  if (rows.length === 0) return null;
912
1090
  const { minStartMs, totalMs } = traceWindow(rows);
913
- return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("details", { className: "mt-3 rounded-md border border-border bg-muted/30", children: [
914
- /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("summary", { className: "cursor-pointer px-3 py-2 text-xs font-medium text-muted-foreground", children: [
1091
+ return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("details", { className: "mt-3 rounded-md border border-border bg-muted/30", children: [
1092
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("summary", { className: "cursor-pointer px-3 py-2 text-xs font-medium text-muted-foreground", children: [
915
1093
  "Trace (",
916
1094
  rows.length,
917
1095
  " span",
@@ -920,11 +1098,11 @@ function ReportTrace({ spans }) {
920
1098
  formatDuration(totalMs),
921
1099
  ")"
922
1100
  ] }),
923
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("ul", { className: "flex flex-col gap-0.5 px-3 pb-3 font-mono text-[0.6875rem]", children: rows.map((row, i) => {
1101
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("ul", { className: "flex flex-col gap-0.5 px-3 pb-3 font-mono text-[0.6875rem]", children: rows.map((row, i) => {
924
1102
  const leftPct = (row.startTimeMs - minStartMs) / totalMs * 100;
925
1103
  const widthPct = Math.max(row.durationMs / totalMs * 100, 0.5);
926
- return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("li", { className: "flex items-center gap-2", children: [
927
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
1104
+ return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("li", { className: "flex items-center gap-2", children: [
1105
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
928
1106
  "span",
929
1107
  {
930
1108
  className: "min-w-0 flex-1 truncate text-foreground",
@@ -933,14 +1111,14 @@ function ReportTrace({ spans }) {
933
1111
  children: row.name
934
1112
  }
935
1113
  ),
936
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "relative h-3 w-1/2 shrink-0 overflow-hidden rounded-sm bg-border/40", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
1114
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "relative h-3 w-1/2 shrink-0 overflow-hidden rounded-sm bg-border/40", children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
937
1115
  "span",
938
1116
  {
939
1117
  className: cn("absolute top-0 h-full rounded-sm", BAR_COLOR[row.status]),
940
1118
  style: { left: `${leftPct}%`, width: `${widthPct}%` }
941
1119
  }
942
1120
  ) }),
943
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "w-16 shrink-0 text-right text-muted-foreground", children: formatDuration(row.durationMs) })
1121
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "w-16 shrink-0 text-right text-muted-foreground", children: formatDuration(row.durationMs) })
944
1122
  ] }, `${row.spanId}-${i}`);
945
1123
  }) })
946
1124
  ] });
@@ -991,7 +1169,7 @@ function flakinessOf(entries) {
991
1169
  }
992
1170
 
993
1171
  // src/components/ScenarioRunHistory.tsx
994
- var import_jsx_runtime22 = require("react/jsx-runtime");
1172
+ var import_jsx_runtime23 = require("react/jsx-runtime");
995
1173
  var MAX_DOTS = 10;
996
1174
  var DOT_COLOR = {
997
1175
  passed: "bg-pass",
@@ -1011,16 +1189,16 @@ function ScenarioRunHistory({ scenarioId }) {
1011
1189
  const recent = entries.slice(-MAX_DOTS);
1012
1190
  const flaky = flakinessOf(recent) === "flaky";
1013
1191
  const summary = flaky ? `${describeRunHistory(recent)} \xB7 Flaky` : describeRunHistory(recent);
1014
- return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(import_jsx_runtime22.Fragment, { children: [
1015
- flaky ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(Badge, { variant: "pending", "aria-label": "Flaky: status flips between recent runs", title: summary, children: "Flaky" }) : null,
1016
- /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
1192
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(import_jsx_runtime23.Fragment, { children: [
1193
+ flaky ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(Badge, { variant: "pending", "aria-label": "Flaky: status flips between recent runs", title: summary, children: "Flaky" }) : null,
1194
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
1017
1195
  "span",
1018
1196
  {
1019
1197
  role: "img",
1020
1198
  "aria-label": `Run history: ${summary}`,
1021
1199
  title: summary,
1022
1200
  className: "flex shrink-0 items-center gap-[3px]",
1023
- children: recent.map((e, i) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
1201
+ children: recent.map((e, i) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
1024
1202
  "span",
1025
1203
  {
1026
1204
  "aria-hidden": true,
@@ -1059,9 +1237,9 @@ function useScenarioActions() {
1059
1237
 
1060
1238
  // src/components/ui/card.tsx
1061
1239
  var React2 = require("react");
1062
- var import_jsx_runtime23 = require("react/jsx-runtime");
1240
+ var import_jsx_runtime24 = require("react/jsx-runtime");
1063
1241
  function Card({ className, ...props }) {
1064
- return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
1242
+ return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
1065
1243
  "div",
1066
1244
  {
1067
1245
  "data-slot": "card",
@@ -1074,7 +1252,7 @@ function Card({ className, ...props }) {
1074
1252
  );
1075
1253
  }
1076
1254
  function CardHeader({ className, ...props }) {
1077
- return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
1255
+ return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
1078
1256
  "div",
1079
1257
  {
1080
1258
  "data-slot": "card-header",
@@ -1087,7 +1265,7 @@ function CardHeader({ className, ...props }) {
1087
1265
  );
1088
1266
  }
1089
1267
  function CardContent({ className, ...props }) {
1090
- return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
1268
+ return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
1091
1269
  "div",
1092
1270
  {
1093
1271
  "data-slot": "card-content",
@@ -1101,13 +1279,13 @@ function CardContent({ className, ...props }) {
1101
1279
  var React3 = require("react");
1102
1280
  var import_menu = require("@base-ui/react/menu");
1103
1281
  var import_lucide_react = require("lucide-react");
1104
- var import_jsx_runtime24 = require("react/jsx-runtime");
1282
+ var import_jsx_runtime25 = require("react/jsx-runtime");
1105
1283
  var itemClasses = "relative flex cursor-pointer items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 data-[highlighted]:bg-accent data-[highlighted]:text-accent-foreground [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 [&_svg:not([class*='text-'])]:text-muted-foreground";
1106
1284
  function DropdownMenu(props) {
1107
- return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_menu.Menu.Root, { "data-slot": "dropdown-menu", ...props });
1285
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_menu.Menu.Root, { "data-slot": "dropdown-menu", ...props });
1108
1286
  }
1109
1287
  function DropdownMenuTrigger(props) {
1110
- return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_menu.Menu.Trigger, { "data-slot": "dropdown-menu-trigger", ...props });
1288
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_menu.Menu.Trigger, { "data-slot": "dropdown-menu-trigger", ...props });
1111
1289
  }
1112
1290
  function DropdownMenuContent({
1113
1291
  className,
@@ -1115,14 +1293,14 @@ function DropdownMenuContent({
1115
1293
  sideOffset = 4,
1116
1294
  ...props
1117
1295
  }) {
1118
- return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_menu.Menu.Portal, { children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
1296
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_menu.Menu.Portal, { children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
1119
1297
  import_menu.Menu.Positioner,
1120
1298
  {
1121
1299
  "data-slot": "dropdown-menu-positioner",
1122
1300
  className: "z-50",
1123
1301
  align,
1124
1302
  sideOffset,
1125
- children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
1303
+ children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
1126
1304
  import_menu.Menu.Popup,
1127
1305
  {
1128
1306
  "data-slot": "dropdown-menu-content",
@@ -1140,7 +1318,7 @@ function DropdownMenuItem({
1140
1318
  className,
1141
1319
  ...props
1142
1320
  }) {
1143
- return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
1321
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
1144
1322
  import_menu.Menu.Item,
1145
1323
  {
1146
1324
  "data-slot": "dropdown-menu-item",
@@ -1152,7 +1330,7 @@ function DropdownMenuItem({
1152
1330
 
1153
1331
  // src/components/ReportScenario.tsx
1154
1332
  var import_lucide_react2 = require("lucide-react");
1155
- var import_jsx_runtime25 = require("react/jsx-runtime");
1333
+ var import_jsx_runtime26 = require("react/jsx-runtime");
1156
1334
  var STATUS_META = {
1157
1335
  passed: { label: "Passed", glyph: "\u2713", glyphColor: "text-pass", badgeVariant: "passed", showPill: false },
1158
1336
  failed: { label: "Failed", glyph: "\u2717", glyphColor: "text-fail", badgeVariant: "failed", showPill: true },
@@ -1168,7 +1346,7 @@ function ReportScenario({ scenario, hideTitle = false }) {
1168
1346
  const collapsible = collapse !== null && !hideTitle;
1169
1347
  const collapsed = collapsible ? collapse.isCollapsed(scenario.id) : false;
1170
1348
  const actions = useScenarioActions();
1171
- return /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
1349
+ return /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(
1172
1350
  Card,
1173
1351
  {
1174
1352
  id: scenario.id,
@@ -1176,10 +1354,10 @@ function ReportScenario({ scenario, hideTitle = false }) {
1176
1354
  ...hideTitle ? { "aria-label": `${scenario.title}, ${label}` } : { "aria-labelledby": titleId },
1177
1355
  className: "gap-0 py-0",
1178
1356
  children: [
1179
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(CardHeader, { className: "px-4 py-3", children: [
1180
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: cn("flex items-start gap-4", hideTitle ? "justify-end" : "justify-between"), children: [
1181
- hideTitle ? null : /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("h3", { id: titleId, className: "flex items-center gap-2 text-sm font-medium text-foreground", children: [
1182
- collapsible ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
1357
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(CardHeader, { className: "px-4 py-3", children: [
1358
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: cn("flex items-start gap-4", hideTitle ? "justify-end" : "justify-between"), children: [
1359
+ hideTitle ? null : /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("h3", { id: titleId, className: "flex items-center gap-2 text-sm font-medium text-foreground", children: [
1360
+ collapsible ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
1183
1361
  "button",
1184
1362
  {
1185
1363
  type: "button",
@@ -1188,49 +1366,49 @@ function ReportScenario({ scenario, hideTitle = false }) {
1188
1366
  "aria-controls": bodyId,
1189
1367
  "aria-label": `Toggle ${scenario.title}`,
1190
1368
  className: "shrink-0 cursor-pointer text-muted-foreground hover:text-foreground",
1191
- children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { "aria-hidden": true, className: cn("inline-block text-xs transition-transform", !collapsed && "rotate-90"), children: "\u25B8" })
1369
+ children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { "aria-hidden": true, className: cn("inline-block text-xs transition-transform", !collapsed && "rotate-90"), children: "\u25B8" })
1192
1370
  }
1193
1371
  ) : null,
1194
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { "aria-hidden": true, className: cn("text-sm leading-none", meta.glyphColor), children: meta.glyph }),
1195
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { children: scenario.title })
1372
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { "aria-hidden": true, className: cn("text-sm leading-none", meta.glyphColor), children: meta.glyph }),
1373
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { children: scenario.title })
1196
1374
  ] }),
1197
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex shrink-0 items-center gap-2", children: [
1198
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ScenarioRunHistory, { scenarioId: scenario.id }),
1199
- scenario.durationMs > 0 ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { className: "whitespace-nowrap font-mono text-[0.6875rem] text-muted-foreground", children: formatDuration(scenario.durationMs) }) : null,
1200
- meta.showPill ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(Badge, { variant: meta.badgeVariant, "aria-label": `Status: ${label}`, children: label }) : /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { className: "sr-only", children: `Status: ${label}` }),
1201
- actions ? /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(DropdownMenu, { children: [
1202
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
1375
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "flex shrink-0 items-center gap-2", children: [
1376
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(ScenarioRunHistory, { scenarioId: scenario.id }),
1377
+ scenario.durationMs > 0 ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "whitespace-nowrap font-mono text-[0.6875rem] text-muted-foreground", children: formatDuration(scenario.durationMs) }) : null,
1378
+ meta.showPill ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(Badge, { variant: meta.badgeVariant, "aria-label": `Status: ${label}`, children: label }) : /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "sr-only", children: `Status: ${label}` }),
1379
+ actions ? /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(DropdownMenu, { children: [
1380
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
1203
1381
  DropdownMenuTrigger,
1204
1382
  {
1205
1383
  "aria-label": `Actions for ${scenario.title}`,
1206
1384
  className: "cursor-pointer rounded p-1 text-muted-foreground hover:bg-muted hover:text-foreground [&_svg]:size-4",
1207
- children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_lucide_react2.MoreHorizontalIcon, { "aria-hidden": true })
1385
+ children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_lucide_react2.MoreHorizontalIcon, { "aria-hidden": true })
1208
1386
  }
1209
1387
  ),
1210
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(DropdownMenuContent, { align: "end", children: [
1211
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(DropdownMenuItem, { onClick: () => actions.copyLink(scenario), children: [
1212
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_lucide_react2.LinkIcon, {}),
1388
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(DropdownMenuContent, { align: "end", children: [
1389
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(DropdownMenuItem, { onClick: () => actions.copyLink(scenario), children: [
1390
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_lucide_react2.LinkIcon, {}),
1213
1391
  " Copy link"
1214
1392
  ] }),
1215
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(DropdownMenuItem, { onClick: () => actions.copyMarkdown(scenario), children: [
1216
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_lucide_react2.FileTextIcon, {}),
1393
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(DropdownMenuItem, { onClick: () => actions.copyMarkdown(scenario), children: [
1394
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_lucide_react2.FileTextIcon, {}),
1217
1395
  " Copy as Markdown"
1218
1396
  ] }),
1219
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(DropdownMenuItem, { onClick: () => actions.copyPrompt(scenario), children: [
1220
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_lucide_react2.SparklesIcon, {}),
1397
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(DropdownMenuItem, { onClick: () => actions.copyPrompt(scenario), children: [
1398
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_lucide_react2.SparklesIcon, {}),
1221
1399
  " Explain with AI"
1222
1400
  ] })
1223
1401
  ] })
1224
1402
  ] }) : null
1225
1403
  ] })
1226
1404
  ] }),
1227
- scenario.tags.length > 0 || (scenario.tickets?.length ?? 0) > 0 ? /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("ul", { "aria-label": "Tags and tickets", className: "flex flex-wrap gap-1.5", children: [
1228
- scenario.tags.map((t) => /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(Badge, { variant: "tag", children: t }) }, `tag-${t}`)),
1229
- (scenario.tickets ?? []).map((ticket) => /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("li", { children: ticket.url ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("a", { href: ticket.url, target: "_blank", rel: "noreferrer noopener", children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(Badge, { variant: "outline", children: ticket.id }) }) : /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(Badge, { variant: "outline", children: ticket.id }) }, `ticket-${ticket.id}`))
1405
+ scenario.tags.length > 0 || (scenario.tickets?.length ?? 0) > 0 ? /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("ul", { "aria-label": "Tags and tickets", className: "flex flex-wrap gap-1.5", children: [
1406
+ scenario.tags.map((t) => /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(Badge, { variant: "tag", children: t }) }, `tag-${t}`)),
1407
+ (scenario.tickets ?? []).map((ticket) => /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("li", { children: ticket.url ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("a", { href: ticket.url, target: "_blank", rel: "noreferrer noopener", children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(Badge, { variant: "outline", children: ticket.id }) }) : /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(Badge, { variant: "outline", children: ticket.id }) }, `ticket-${ticket.id}`))
1230
1408
  ] }) : null
1231
1409
  ] }),
1232
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(CardContent, { id: bodyId, hidden: collapsed, className: "px-4 pt-0 pb-4", children: [
1233
- scenario.errorMessage ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
1410
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(CardContent, { id: bodyId, hidden: collapsed, className: "px-4 pt-0 pb-4", children: [
1411
+ scenario.errorMessage ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
1234
1412
  "pre",
1235
1413
  {
1236
1414
  role: "alert",
@@ -1238,11 +1416,11 @@ function ReportScenario({ scenario, hideTitle = false }) {
1238
1416
  children: scenario.errorMessage
1239
1417
  }
1240
1418
  ) : null,
1241
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ReportStoryboard, { scenario }),
1242
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ReportSteps, { scenario }),
1243
- scenario.docEntries.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { "data-es-docs": true, className: "mt-3", children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ReportDocEntries, { entries: scenario.docEntries }) }) : null,
1244
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ReportAttachments, { attachments: scenario.attachments }),
1245
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ReportTrace, { spans: scenario.otelSpans })
1419
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(ReportStoryboard, { scenario }),
1420
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(ReportSteps, { scenario }),
1421
+ scenario.docEntries.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { "data-es-docs": true, className: "mt-3", children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(ReportDocEntries, { entries: scenario.docEntries }) }) : null,
1422
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(ReportAttachments, { attachments: scenario.attachments }),
1423
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(ReportTrace, { spans: scenario.otelSpans })
1246
1424
  ] })
1247
1425
  ]
1248
1426
  }
@@ -1250,13 +1428,13 @@ function ReportScenario({ scenario, hideTitle = false }) {
1250
1428
  }
1251
1429
 
1252
1430
  // src/components/ReportScenarioList.tsx
1253
- var import_jsx_runtime26 = require("react/jsx-runtime");
1431
+ var import_jsx_runtime27 = require("react/jsx-runtime");
1254
1432
  function ReportScenarioList({ feature }) {
1255
- return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_jsx_runtime26.Fragment, { children: feature.scenarios.map((scenario) => /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(ReportScenario, { scenario }, scenario.id)) });
1433
+ return /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_jsx_runtime27.Fragment, { children: feature.scenarios.map((scenario) => /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(ReportScenario, { scenario }, scenario.id)) });
1256
1434
  }
1257
1435
 
1258
1436
  // src/components/ReportFeature.tsx
1259
- var import_jsx_runtime27 = require("react/jsx-runtime");
1437
+ var import_jsx_runtime28 = require("react/jsx-runtime");
1260
1438
  function ReportFeature({ feature }) {
1261
1439
  const titleId = `${feature.id}-title`;
1262
1440
  const bodyId = `${feature.id}-body`;
@@ -1267,7 +1445,7 @@ function ReportFeature({ feature }) {
1267
1445
  return (
1268
1446
  // Suite = a section heading + a divider, NOT another bordered card. Drops a
1269
1447
  // layer of nesting so the scenario cards below read as the primary unit.
1270
- /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(
1448
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(
1271
1449
  "section",
1272
1450
  {
1273
1451
  id: feature.id,
@@ -1275,9 +1453,9 @@ function ReportFeature({ feature }) {
1275
1453
  "aria-labelledby": titleId,
1276
1454
  className: "flex flex-col gap-3",
1277
1455
  children: [
1278
- /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "flex items-end justify-between gap-4 border-b border-border pb-2", children: [
1279
- /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "min-w-0", children: [
1280
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("h2", { id: titleId, className: "text-base font-semibold tracking-tight text-foreground", children: collapse ? /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(
1456
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: "flex items-end justify-between gap-4 border-b border-border pb-2", children: [
1457
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: "min-w-0", children: [
1458
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("h2", { id: titleId, className: "text-base font-semibold tracking-tight text-foreground", children: collapse ? /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(
1281
1459
  "button",
1282
1460
  {
1283
1461
  type: "button",
@@ -1286,31 +1464,31 @@ function ReportFeature({ feature }) {
1286
1464
  "aria-controls": bodyId,
1287
1465
  className: "flex w-full cursor-pointer items-center gap-2 text-left hover:text-foreground/80",
1288
1466
  children: [
1289
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { "aria-hidden": true, className: cn("shrink-0 text-xs text-muted-foreground transition-transform", !collapsed && "rotate-90"), children: "\u25B8" }),
1290
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { className: "truncate", children: feature.title })
1467
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("span", { "aria-hidden": true, className: cn("shrink-0 text-xs text-muted-foreground transition-transform", !collapsed && "rotate-90"), children: "\u25B8" }),
1468
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("span", { className: "truncate", children: feature.title })
1291
1469
  ]
1292
1470
  }
1293
1471
  ) : feature.title }),
1294
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("p", { className: cn("mt-0.5 truncate font-mono text-xs text-muted-foreground", collapse && "pl-5"), children: feature.sourceFile })
1472
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("p", { className: cn("mt-0.5 truncate font-mono text-xs text-muted-foreground", collapse && "pl-5"), children: feature.sourceFile })
1295
1473
  ] }),
1296
- /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(
1474
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(
1297
1475
  "p",
1298
1476
  {
1299
1477
  className: "flex shrink-0 items-center gap-1.5 text-xs text-muted-foreground",
1300
1478
  "aria-label": `${s.passed} passed, ${s.failed} failed, ${skipped} skipped`,
1301
1479
  children: [
1302
- /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("span", { children: [
1480
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("span", { children: [
1303
1481
  s.passed,
1304
1482
  " passed"
1305
1483
  ] }),
1306
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { "aria-hidden": true, children: "\xB7" }),
1307
- /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("span", { className: cn(s.failed > 0 && "font-medium text-fail"), children: [
1484
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("span", { "aria-hidden": true, children: "\xB7" }),
1485
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("span", { className: cn(s.failed > 0 && "font-medium text-fail"), children: [
1308
1486
  s.failed,
1309
1487
  " failed"
1310
1488
  ] }),
1311
- skipped > 0 ? /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(import_jsx_runtime27.Fragment, { children: [
1312
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { "aria-hidden": true, children: "\xB7" }),
1313
- /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("span", { children: [
1489
+ skipped > 0 ? /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(import_jsx_runtime28.Fragment, { children: [
1490
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("span", { "aria-hidden": true, children: "\xB7" }),
1491
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("span", { children: [
1314
1492
  skipped,
1315
1493
  " skipped"
1316
1494
  ] })
@@ -1319,7 +1497,7 @@ function ReportFeature({ feature }) {
1319
1497
  }
1320
1498
  )
1321
1499
  ] }),
1322
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { id: bodyId, hidden: collapsed, className: "flex flex-col gap-3", children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(ReportScenarioList, { feature }) })
1500
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("div", { id: bodyId, hidden: collapsed, className: "flex flex-col gap-3", children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(ReportScenarioList, { feature }) })
1323
1501
  ]
1324
1502
  }
1325
1503
  )
@@ -1327,17 +1505,17 @@ function ReportFeature({ feature }) {
1327
1505
  }
1328
1506
 
1329
1507
  // src/components/ReportFeatureList.tsx
1330
- var import_jsx_runtime28 = require("react/jsx-runtime");
1508
+ var import_jsx_runtime29 = require("react/jsx-runtime");
1331
1509
  function ReportFeatureList() {
1332
1510
  const report = useReport();
1333
- return /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("div", { className: "flex flex-col gap-8", children: report.features.map((feature) => /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(ReportFeature, { feature }, feature.id)) });
1511
+ return /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("div", { className: "flex flex-col gap-8", children: report.features.map((feature) => /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(ReportFeature, { feature }, feature.id)) });
1334
1512
  }
1335
1513
 
1336
1514
  // src/components/ui/empty.tsx
1337
1515
  var import_class_variance_authority2 = require("class-variance-authority");
1338
- var import_jsx_runtime29 = require("react/jsx-runtime");
1516
+ var import_jsx_runtime30 = require("react/jsx-runtime");
1339
1517
  function Empty({ className, ...props }) {
1340
- return /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
1518
+ return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
1341
1519
  "div",
1342
1520
  {
1343
1521
  "data-slot": "empty",
@@ -1350,7 +1528,7 @@ function Empty({ className, ...props }) {
1350
1528
  );
1351
1529
  }
1352
1530
  function EmptyHeader({ className, ...props }) {
1353
- return /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
1531
+ return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
1354
1532
  "div",
1355
1533
  {
1356
1534
  "data-slot": "empty-header",
@@ -1377,7 +1555,7 @@ var emptyMediaVariants = (0, import_class_variance_authority2.cva)(
1377
1555
  }
1378
1556
  );
1379
1557
  function EmptyTitle({ className, ...props }) {
1380
- return /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
1558
+ return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
1381
1559
  "div",
1382
1560
  {
1383
1561
  "data-slot": "empty-title",
@@ -1388,16 +1566,16 @@ function EmptyTitle({ className, ...props }) {
1388
1566
  }
1389
1567
 
1390
1568
  // src/components/ReportEmpty.tsx
1391
- var import_jsx_runtime30 = require("react/jsx-runtime");
1569
+ var import_jsx_runtime31 = require("react/jsx-runtime");
1392
1570
  function ReportEmpty({ message }) {
1393
- return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(Empty, { "aria-live": "polite", className: "border", children: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(EmptyHeader, { children: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(EmptyTitle, { children: message ?? "No scenarios in this report." }) }) });
1571
+ return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(Empty, { "aria-live": "polite", className: "border", children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(EmptyHeader, { children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(EmptyTitle, { children: message ?? "No scenarios in this report." }) }) });
1394
1572
  }
1395
1573
 
1396
1574
  // src/components/ReportSummary.tsx
1397
- var import_jsx_runtime31 = require("react/jsx-runtime");
1575
+ var import_jsx_runtime32 = require("react/jsx-runtime");
1398
1576
  function ReportSummary({ className }) {
1399
1577
  const report = useReport();
1400
- return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
1578
+ return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
1401
1579
  ReportSummaryView,
1402
1580
  {
1403
1581
  summary: report.summary,
@@ -1423,7 +1601,7 @@ function ReportSummaryView({ summary, className, ariaLabel }) {
1423
1601
  if (summary.pending > 0) {
1424
1602
  cards.push({ status: "pending", label: "Pending", value: summary.pending });
1425
1603
  }
1426
- return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
1604
+ return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
1427
1605
  "dl",
1428
1606
  {
1429
1607
  className: cn(
@@ -1436,17 +1614,17 @@ function ReportSummaryView({ summary, className, ariaLabel }) {
1436
1614
  "aria-label": ariaLabel,
1437
1615
  children: cards.map((c) => {
1438
1616
  const tone = TONE[c.status];
1439
- return /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(
1617
+ return /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(
1440
1618
  "div",
1441
1619
  {
1442
1620
  "data-status": c.status,
1443
1621
  className: "rounded-lg border bg-card px-4 py-3",
1444
1622
  children: [
1445
- /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("dt", { className: "flex items-center gap-1.5 font-mono text-[11px] font-medium uppercase tracking-wider text-muted-foreground", children: [
1446
- /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("span", { className: cn("size-1.5 shrink-0 rounded-full", tone.dot), "aria-hidden": "true" }),
1623
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("dt", { className: "flex items-center gap-1.5 font-mono text-[11px] font-medium uppercase tracking-wider text-muted-foreground", children: [
1624
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { className: cn("size-1.5 shrink-0 rounded-full", tone.dot), "aria-hidden": "true" }),
1447
1625
  c.label
1448
1626
  ] }),
1449
- /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("dd", { className: cn("mt-2 text-3xl font-semibold leading-none tracking-tight tabular-nums", tone.num), children: c.value })
1627
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("dd", { className: cn("mt-2 text-3xl font-semibold leading-none tracking-tight tabular-nums", tone.num), children: c.value })
1450
1628
  ]
1451
1629
  },
1452
1630
  c.status
@@ -1487,7 +1665,7 @@ function prUrl(ci) {
1487
1665
  }
1488
1666
 
1489
1667
  // src/components/ReportMeta.tsx
1490
- var import_jsx_runtime32 = require("react/jsx-runtime");
1668
+ var import_jsx_runtime33 = require("react/jsx-runtime");
1491
1669
  function ReportMeta() {
1492
1670
  const report = useReport();
1493
1671
  const items = [];
@@ -1510,13 +1688,13 @@ function ReportMeta() {
1510
1688
  const short = sha.slice(0, 8);
1511
1689
  items.push({
1512
1690
  label: "Commit",
1513
- value: url ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("a", { href: url, target: "_blank", rel: "noreferrer noopener", className: linkClass, children: short }) : short
1691
+ value: url ? /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("a", { href: url, target: "_blank", rel: "noreferrer noopener", className: linkClass, children: short }) : short
1514
1692
  });
1515
1693
  }
1516
1694
  if (report.ci) {
1517
1695
  items.push({
1518
1696
  label: "CI",
1519
- value: report.ci.url ? /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("a", { href: report.ci.url, target: "_blank", rel: "noreferrer noopener", className: linkClass, children: [
1697
+ value: report.ci.url ? /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("a", { href: report.ci.url, target: "_blank", rel: "noreferrer noopener", className: linkClass, children: [
1520
1698
  ciDisplayName(report.ci.name),
1521
1699
  report.ci.buildNumber ? ` #${report.ci.buildNumber}` : ""
1522
1700
  ] }) : `${ciDisplayName(report.ci.name)}${report.ci.buildNumber ? ` #${report.ci.buildNumber}` : ""}`
@@ -1527,7 +1705,7 @@ function ReportMeta() {
1527
1705
  const label = `#${report.ci.prNumber}`;
1528
1706
  items.push({
1529
1707
  label: "PR",
1530
- value: url ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("a", { href: url, target: "_blank", rel: "noreferrer noopener", className: linkClass, children: label }) : label
1708
+ value: url ? /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("a", { href: url, target: "_blank", rel: "noreferrer noopener", className: linkClass, children: label }) : label
1531
1709
  });
1532
1710
  }
1533
1711
  if (items.length === 0) return null;
@@ -1535,48 +1713,48 @@ function ReportMeta() {
1535
1713
  // Run metadata is useful but secondary to "what failed" — tuck it into a
1536
1714
  // collapsed disclosure so it doesn't push the result down. Native <details>
1537
1715
  // so it works with no JS (the SSR/no-hydration report still toggles).
1538
- /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("details", { "data-es-meta-card": true, className: "es-run-details group rounded-lg border border-border bg-card text-xs", children: [
1539
- /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("summary", { className: "flex cursor-pointer list-none select-none items-center gap-1.5 px-4 py-2 font-medium text-muted-foreground [&::-webkit-details-marker]:hidden", children: [
1540
- /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { "aria-hidden": true, className: "text-xs transition-transform group-open:rotate-90", children: "\u25B8" }),
1716
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("details", { "data-es-meta-card": true, className: "es-run-details group rounded-lg border border-border bg-card text-xs", children: [
1717
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("summary", { className: "flex cursor-pointer list-none select-none items-center gap-1.5 px-4 py-2 font-medium text-muted-foreground [&::-webkit-details-marker]:hidden", children: [
1718
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("span", { "aria-hidden": true, className: "text-xs transition-transform group-open:rotate-90", children: "\u25B8" }),
1541
1719
  "Run details"
1542
1720
  ] }),
1543
- /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("dl", { className: "flex flex-wrap gap-x-5 gap-y-2 border-t border-border px-4 py-3 text-muted-foreground", "aria-label": "Run metadata", children: items.map((item) => /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { className: "flex items-baseline gap-1.5", children: [
1544
- /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("dt", { className: "font-medium", children: item.label }),
1545
- /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("dd", { className: "font-mono text-foreground", children: item.value })
1721
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("dl", { className: "flex flex-wrap gap-x-5 gap-y-2 border-t border-border px-4 py-3 text-muted-foreground", "aria-label": "Run metadata", children: items.map((item) => /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("div", { className: "flex items-baseline gap-1.5", children: [
1722
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("dt", { className: "font-medium", children: item.label }),
1723
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("dd", { className: "font-mono text-foreground", children: item.value })
1546
1724
  ] }, item.label)) })
1547
1725
  ] })
1548
1726
  );
1549
1727
  }
1550
1728
 
1551
1729
  // src/components/ReportSchemaError.tsx
1552
- var import_jsx_runtime33 = require("react/jsx-runtime");
1730
+ var import_jsx_runtime34 = require("react/jsx-runtime");
1553
1731
  function ReportSchemaError({ error }) {
1554
- return /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("section", { className: "es-schema-error", role: "alert", "aria-live": "assertive", children: [
1555
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("p", { children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("strong", { children: "Report could not be displayed." }) }),
1556
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("p", { children: error.message }),
1557
- error.code === "SCHEMA_VERSION_MISMATCH" ? /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("p", { children: [
1732
+ return /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("section", { className: "es-schema-error", role: "alert", "aria-live": "assertive", children: [
1733
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("p", { children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("strong", { children: "Report could not be displayed." }) }),
1734
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("p", { children: error.message }),
1735
+ error.code === "SCHEMA_VERSION_MISMATCH" ? /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("p", { children: [
1558
1736
  "The report bundle is newer than this version of ",
1559
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("code", { children: "executable-stories-react" }),
1737
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("code", { children: "executable-stories-react" }),
1560
1738
  ". Upgrade the package, or regenerate the report with an older formatters CLI."
1561
1739
  ] }) : null,
1562
- error.issues && error.issues.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("details", { children: [
1563
- /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("summary", { children: [
1740
+ error.issues && error.issues.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("details", { children: [
1741
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("summary", { children: [
1564
1742
  error.issues.length,
1565
1743
  " validation issue",
1566
1744
  error.issues.length === 1 ? "" : "s"
1567
1745
  ] }),
1568
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("pre", { children: error.issues.slice(0, 20).map((i) => `${i.path}: ${i.message}`).join("\n") })
1746
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("pre", { children: error.issues.slice(0, 20).map((i) => `${i.path}: ${i.message}`).join("\n") })
1569
1747
  ] }) : null
1570
1748
  ] });
1571
1749
  }
1572
1750
 
1573
1751
  // src/components/ReportShell.tsx
1574
- var import_jsx_runtime34 = require("react/jsx-runtime");
1752
+ var import_jsx_runtime35 = require("react/jsx-runtime");
1575
1753
  function ReportTitleBlock({ title }) {
1576
- return /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(import_jsx_runtime34.Fragment, { children: [
1577
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("h1", { children: title ?? "Story Report" }),
1578
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(ReportSummary, {}),
1579
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(ReportMeta, {})
1754
+ return /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)(import_jsx_runtime35.Fragment, { children: [
1755
+ /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("h1", { children: title ?? "Story Report" }),
1756
+ /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(ReportSummary, {}),
1757
+ /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(ReportMeta, {})
1580
1758
  ] });
1581
1759
  }
1582
1760
  function ReportErrorShell({
@@ -1585,22 +1763,22 @@ function ReportErrorShell({
1585
1763
  title,
1586
1764
  dataTheme
1587
1765
  }) {
1588
- return /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("main", { className: cn("es-report", className), "aria-label": title ?? "Test report", "data-theme": dataTheme, children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(ReportSchemaError, { error }) });
1766
+ return /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("main", { className: cn("es-report", className), "aria-label": title ?? "Test report", "data-theme": dataTheme, children: /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(ReportSchemaError, { error }) });
1589
1767
  }
1590
1768
 
1591
1769
  // src/components/Report.tsx
1592
- var import_jsx_runtime35 = require("react/jsx-runtime");
1770
+ var import_jsx_runtime36 = require("react/jsx-runtime");
1593
1771
  function Report(props) {
1594
1772
  const { report, customRenderers, renderers, className, title, dataTheme } = props;
1595
1773
  const result = unwrapReport(report);
1596
1774
  if (!result.ok) {
1597
- return /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(ReportErrorShell, { error: result.error, className, title, dataTheme });
1775
+ return /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(ReportErrorShell, { error: result.error, className, title, dataTheme });
1598
1776
  }
1599
1777
  const data = result.data;
1600
1778
  const hasContent = data.features.length > 0;
1601
- return /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(ReportRoot, { report: data, customRenderers, renderers, children: /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("main", { className: cn("es-report", className), "aria-label": title ?? "Test report", "data-theme": dataTheme, children: [
1602
- /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("header", { className: "es-report-header", children: /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(ReportTitleBlock, { title }) }),
1603
- hasContent ? /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(ReportFeatureList, {}) : /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(ReportEmpty, {})
1779
+ return /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(ReportRoot, { report: data, customRenderers, renderers, children: /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("main", { className: cn("es-report", className), "aria-label": title ?? "Test report", "data-theme": dataTheme, children: [
1780
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("header", { className: "es-report-header", children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(ReportTitleBlock, { title }) }),
1781
+ hasContent ? /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(ReportFeatureList, {}) : /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(ReportEmpty, {})
1604
1782
  ] }) });
1605
1783
  }
1606
1784