executable-stories-react 0.7.0 → 0.8.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.
@@ -383,17 +383,29 @@ function DocHtml({ entry }) {
383
383
  ] });
384
384
  }
385
385
 
386
+ // src/components/doc/DocState.tsx
387
+ import { jsx as jsx13 } from "react/jsx-runtime";
388
+ function DocState({ entry }) {
389
+ let json;
390
+ try {
391
+ json = JSON.stringify(entry.value, null, 2) ?? String(entry.value);
392
+ } catch {
393
+ json = String(entry.value);
394
+ }
395
+ return /* @__PURE__ */ jsx13(CodeFigure, { label: entry.label ?? "State", children: /* @__PURE__ */ jsx13("code", { className: "font-mono text-xs language-json", children: json }) });
396
+ }
397
+
386
398
  // src/components/doc/DocCustom.tsx
387
- import { Fragment as Fragment4, jsx as jsx13, jsxs as jsxs9 } from "react/jsx-runtime";
399
+ import { Fragment as Fragment4, jsx as jsx14, jsxs as jsxs9 } from "react/jsx-runtime";
388
400
  function DocCustom({ entry }) {
389
401
  const renderers = useCustomRenderers();
390
402
  const renderer = renderers[entry.type];
391
403
  if (renderer) {
392
- return /* @__PURE__ */ jsx13(Fragment4, { children: renderer(entry) });
404
+ return /* @__PURE__ */ jsx14(Fragment4, { children: renderer(entry) });
393
405
  }
394
406
  return /* @__PURE__ */ jsxs9("div", { className: "my-2", "data-type": entry.type, children: [
395
- /* @__PURE__ */ jsx13("p", { className: "mb-1 text-xs font-medium text-muted-foreground", children: entry.type }),
396
- /* @__PURE__ */ jsx13("pre", { tabIndex: 0, className: "overflow-x-auto rounded-md bg-muted p-3 font-mono text-xs text-foreground", children: safeStringify(entry.data) })
407
+ /* @__PURE__ */ jsx14("p", { className: "mb-1 text-xs font-medium text-muted-foreground", children: entry.type }),
408
+ /* @__PURE__ */ jsx14("pre", { tabIndex: 0, className: "overflow-x-auto rounded-md bg-muted p-3 font-mono text-xs text-foreground", children: safeStringify(entry.data) })
397
409
  ] });
398
410
  }
399
411
  function safeStringify(value) {
@@ -405,45 +417,47 @@ function safeStringify(value) {
405
417
  }
406
418
 
407
419
  // src/components/doc/DocEntry.tsx
408
- import { jsx as jsx14 } from "react/jsx-runtime";
420
+ import { jsx as jsx15 } from "react/jsx-runtime";
409
421
  function DocEntry({ entry }) {
410
422
  switch (entry.kind) {
411
423
  case "note":
412
- return /* @__PURE__ */ jsx14(DocNote, { entry });
424
+ return /* @__PURE__ */ jsx15(DocNote, { entry });
413
425
  case "tag":
414
- return /* @__PURE__ */ jsx14(DocTag, { entry });
426
+ return /* @__PURE__ */ jsx15(DocTag, { entry });
415
427
  case "kv":
416
- return /* @__PURE__ */ jsx14(DocKv, { entry });
428
+ return /* @__PURE__ */ jsx15(DocKv, { entry });
417
429
  case "code":
418
- return /* @__PURE__ */ jsx14(DocCode, { entry });
430
+ return /* @__PURE__ */ jsx15(DocCode, { entry });
419
431
  case "table":
420
- return /* @__PURE__ */ jsx14(DocTable, { entry });
432
+ return /* @__PURE__ */ jsx15(DocTable, { entry });
421
433
  case "link":
422
- return /* @__PURE__ */ jsx14(DocLink, { entry });
434
+ return /* @__PURE__ */ jsx15(DocLink, { entry });
423
435
  case "section":
424
- return /* @__PURE__ */ jsx14(DocSection, { entry });
436
+ return /* @__PURE__ */ jsx15(DocSection, { entry });
425
437
  case "mermaid":
426
- return /* @__PURE__ */ jsx14(DocMermaid, { entry });
438
+ return /* @__PURE__ */ jsx15(DocMermaid, { entry });
427
439
  case "screenshot":
428
- return /* @__PURE__ */ jsx14(DocScreenshot, { entry });
440
+ return /* @__PURE__ */ jsx15(DocScreenshot, { entry });
429
441
  case "video":
430
- return /* @__PURE__ */ jsx14(DocVideo, { entry });
442
+ return /* @__PURE__ */ jsx15(DocVideo, { entry });
431
443
  case "html":
432
- return /* @__PURE__ */ jsx14(DocHtml, { entry });
444
+ return /* @__PURE__ */ jsx15(DocHtml, { entry });
445
+ case "state":
446
+ return /* @__PURE__ */ jsx15(DocState, { entry });
433
447
  case "custom":
434
- return /* @__PURE__ */ jsx14(DocCustom, { entry });
448
+ return /* @__PURE__ */ jsx15(DocCustom, { entry });
435
449
  }
436
450
  }
437
451
 
438
452
  // src/components/ReportDocEntries.tsx
439
- import { Fragment as Fragment5, jsx as jsx15 } from "react/jsx-runtime";
453
+ import { Fragment as Fragment5, jsx as jsx16 } from "react/jsx-runtime";
440
454
  function ReportDocEntries({ entries }) {
441
455
  if (entries.length === 0) return null;
442
- return /* @__PURE__ */ jsx15(Fragment5, { children: entries.map((entry, i) => /* @__PURE__ */ jsx15(DocEntry, { entry }, i)) });
456
+ return /* @__PURE__ */ jsx16(Fragment5, { children: entries.map((entry, i) => /* @__PURE__ */ jsx16(DocEntry, { entry }, i)) });
443
457
  }
444
458
 
445
459
  // src/lib/step-params.tsx
446
- import { jsx as jsx16 } from "react/jsx-runtime";
460
+ import { jsx as jsx17 } from "react/jsx-runtime";
447
461
  var STEP_PARAM_PATTERN = /"[^"]*"|(?<![\w.-])\d+(?:\.\d+)?(?![\w.-])/g;
448
462
  function highlightStepParams(text) {
449
463
  const matches = Array.from(text.matchAll(STEP_PARAM_PATTERN));
@@ -455,7 +469,7 @@ function highlightStepParams(text) {
455
469
  const end = start + match[0].length;
456
470
  if (start > lastIndex) nodes.push(text.slice(lastIndex, start));
457
471
  nodes.push(
458
- /* @__PURE__ */ jsx16("span", { className: "font-medium text-step-param italic", children: match[0] }, i)
472
+ /* @__PURE__ */ jsx17("span", { className: "font-medium text-step-param italic", children: match[0] }, i)
459
473
  );
460
474
  lastIndex = end;
461
475
  });
@@ -464,7 +478,7 @@ function highlightStepParams(text) {
464
478
  }
465
479
 
466
480
  // src/components/ReportSteps.tsx
467
- import { jsx as jsx17, jsxs as jsxs10 } from "react/jsx-runtime";
481
+ import { jsx as jsx18, jsxs as jsxs10 } from "react/jsx-runtime";
468
482
  var STEP_GLYPH = {
469
483
  passed: "\u2713",
470
484
  failed: "\u2717",
@@ -479,7 +493,7 @@ var STEP_GLYPH_COLOR = {
479
493
  };
480
494
  function ReportSteps({ scenario }) {
481
495
  if (scenario.steps.length === 0) return null;
482
- return /* @__PURE__ */ jsx17("ol", { "data-slot": "steps", className: "flex flex-col", children: scenario.steps.map((step) => /* @__PURE__ */ jsx17(ReportStepItem, { step }, step.id)) });
496
+ return /* @__PURE__ */ jsx18("ol", { "data-slot": "steps", className: "flex flex-col", children: scenario.steps.map((step) => /* @__PURE__ */ jsx18(ReportStepItem, { step }, step.id)) });
483
497
  }
484
498
  function ReportStepItem({ step }) {
485
499
  const kw = step.keyword.toLowerCase();
@@ -492,8 +506,8 @@ function ReportStepItem({ step }) {
492
506
  className: cn("py-1.5 text-[0.8125rem] leading-normal", continuation && "pl-5"),
493
507
  children: [
494
508
  /* @__PURE__ */ jsxs10("div", { className: "flex items-baseline gap-2", children: [
495
- /* @__PURE__ */ jsx17("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" }),
496
- /* @__PURE__ */ jsx17(
509
+ /* @__PURE__ */ jsx18("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" }),
510
+ /* @__PURE__ */ jsx18(
497
511
  "span",
498
512
  {
499
513
  className: cn(
@@ -503,10 +517,10 @@ function ReportStepItem({ step }) {
503
517
  children: step.keyword
504
518
  }
505
519
  ),
506
- /* @__PURE__ */ jsx17("span", { className: "flex-1 text-foreground", children: highlightStepParams(step.text) }),
507
- step.durationMs > 0 ? /* @__PURE__ */ jsx17("span", { className: "shrink-0 whitespace-nowrap font-mono text-[0.6875rem] text-muted-foreground", children: formatDuration(step.durationMs) }) : null
520
+ /* @__PURE__ */ jsx18("span", { className: "flex-1 text-foreground", children: highlightStepParams(step.text) }),
521
+ step.durationMs > 0 ? /* @__PURE__ */ jsx18("span", { className: "shrink-0 whitespace-nowrap font-mono text-[0.6875rem] text-muted-foreground", children: formatDuration(step.durationMs) }) : null
508
522
  ] }),
509
- step.errorMessage ? /* @__PURE__ */ jsx17(
523
+ step.errorMessage ? /* @__PURE__ */ jsx18(
510
524
  "pre",
511
525
  {
512
526
  role: "alert",
@@ -514,12 +528,72 @@ function ReportStepItem({ step }) {
514
528
  children: step.errorMessage
515
529
  }
516
530
  ) : null,
517
- step.docEntries.length > 0 ? /* @__PURE__ */ jsx17("div", { "data-es-docs": true, className: "mt-2 ml-6", children: /* @__PURE__ */ jsx17(ReportDocEntries, { entries: step.docEntries }) }) : null
531
+ step.docEntries.length > 0 ? /* @__PURE__ */ jsx18("div", { "data-es-docs": true, className: "mt-2 ml-6", children: /* @__PURE__ */ jsx18(ReportDocEntries, { entries: step.docEntries }) }) : null
518
532
  ]
519
533
  }
520
534
  );
521
535
  }
522
536
 
537
+ // ../executable-stories-core/dist/state-diff.js
538
+ var isPlainObject = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
539
+ function deepEqual(a, b) {
540
+ if (Object.is(a, b)) return true;
541
+ if (Array.isArray(a) && Array.isArray(b)) {
542
+ return a.length === b.length && a.every((v, i) => deepEqual(v, b[i]));
543
+ }
544
+ if (isPlainObject(a) && isPlainObject(b)) {
545
+ const ak = Object.keys(a);
546
+ const bk = Object.keys(b);
547
+ return ak.length === bk.length && ak.every((k) => k in b && deepEqual(a[k], b[k]));
548
+ }
549
+ return false;
550
+ }
551
+ var joinKey = (path, key) => path === "" ? key : `${path}.${key}`;
552
+ function walk(path, before, after, out) {
553
+ if (Object.is(before, after)) return;
554
+ if (Array.isArray(before) && Array.isArray(after)) {
555
+ const shared = Math.min(before.length, after.length);
556
+ for (let i = 0; i < shared; i++) walk(`${path}[${i}]`, before[i], after[i], out);
557
+ for (let i = shared; i < after.length; i++) out.push({ path: `${path}[${i}]`, kind: "added", after: after[i] });
558
+ for (let i = shared; i < before.length; i++) out.push({ path: `${path}[${i}]`, kind: "removed", before: before[i] });
559
+ return;
560
+ }
561
+ if (isPlainObject(before) && isPlainObject(after)) {
562
+ for (const key of Object.keys(after)) {
563
+ const p = joinKey(path, key);
564
+ if (key in before) walk(p, before[key], after[key], out);
565
+ else out.push({ path: p, kind: "added", after: after[key] });
566
+ }
567
+ for (const key of Object.keys(before)) {
568
+ if (!(key in after)) out.push({ path: joinKey(path, key), kind: "removed", before: before[key] });
569
+ }
570
+ return;
571
+ }
572
+ if (!deepEqual(before, after)) out.push({ path, kind: "changed", before, after });
573
+ }
574
+ function diffStateValues(before, after) {
575
+ const out = [];
576
+ walk("", before, after, out);
577
+ return out;
578
+ }
579
+ function formatStateValue(value, maxLen = 60) {
580
+ const s = value === void 0 ? "undefined" : JSON.stringify(value);
581
+ return s.length > maxLen ? `${s.slice(0, maxLen - 1)}\u2026` : s;
582
+ }
583
+ function summarizeStateChanges(changes) {
584
+ return changes.map((c) => {
585
+ const at = c.path === "" ? "(root)" : c.path;
586
+ switch (c.kind) {
587
+ case "added":
588
+ return `+ ${at}: ${formatStateValue(c.after)}`;
589
+ case "removed":
590
+ return `\u2212 ${at}`;
591
+ case "changed":
592
+ return `${at}: ${formatStateValue(c.before)} \u2192 ${formatStateValue(c.after)}`;
593
+ }
594
+ });
595
+ }
596
+
523
597
  // ../executable-stories-core/dist/storyboard.js
524
598
  function findScreenshot(entries) {
525
599
  for (const entry of entries) {
@@ -531,26 +605,55 @@ function findScreenshot(entries) {
531
605
  }
532
606
  return void 0;
533
607
  }
608
+ function findStates(entries, out = []) {
609
+ for (const entry of entries) {
610
+ if (entry.kind === "state") out.push(entry);
611
+ if (entry.children) findStates(entry.children, out);
612
+ }
613
+ return out;
614
+ }
615
+ var laneOf = (label) => label ?? "";
534
616
  function extractStoryboardFrames(scenario) {
535
617
  const frames = [];
618
+ const laneOrder = [];
619
+ const previous = /* @__PURE__ */ new Map();
536
620
  for (const step of scenario.steps) {
537
621
  const shot = findScreenshot(step.docEntries);
538
- if (!shot) continue;
622
+ const stateDocs = findStates(step.docEntries);
623
+ if (!shot && stateDocs.length === 0) continue;
624
+ const byLane = /* @__PURE__ */ new Map();
625
+ for (const doc of stateDocs) {
626
+ const lane = laneOf(doc.label);
627
+ if (!byLane.has(lane) && !laneOrder.includes(lane)) laneOrder.push(lane);
628
+ byLane.set(lane, doc);
629
+ }
630
+ const states = [];
631
+ for (const lane of laneOrder) {
632
+ const doc = byLane.get(lane);
633
+ if (!doc) continue;
634
+ const card = {
635
+ ...doc.label !== void 0 && { label: doc.label },
636
+ value: doc.value
637
+ };
638
+ if (previous.has(lane)) card.changes = diffStateValues(previous.get(lane), doc.value);
639
+ previous.set(lane, doc.value);
640
+ states.push(card);
641
+ }
539
642
  frames.push({
540
643
  stepId: step.id,
541
644
  stepIndex: step.index,
542
645
  keyword: step.keyword,
543
646
  text: step.text,
544
647
  status: step.status,
545
- path: shot.path,
546
- ...shot.alt !== void 0 && { alt: shot.alt }
648
+ ...shot && { screenshot: { path: shot.path, ...shot.alt !== void 0 && { alt: shot.alt } } },
649
+ states
547
650
  });
548
651
  }
549
652
  return frames;
550
653
  }
551
654
 
552
655
  // src/components/ReportStoryboard.tsx
553
- import { jsx as jsx18, jsxs as jsxs11 } from "react/jsx-runtime";
656
+ import { jsx as jsx19, jsxs as jsxs11 } from "react/jsx-runtime";
554
657
  var FRAME_GLYPH = {
555
658
  passed: "\u2713",
556
659
  failed: "\u2717",
@@ -567,54 +670,113 @@ function ReportStoryboard({ scenario }) {
567
670
  const frames = extractStoryboardFrames(scenario);
568
671
  if (frames.length < 2) return null;
569
672
  return /* @__PURE__ */ jsxs11("section", { "data-slot": "storyboard", "aria-label": "Storyboard", className: "mb-3", children: [
570
- /* @__PURE__ */ jsx18("h4", { className: "mb-1.5 text-xs font-semibold tracking-wide text-muted-foreground uppercase", children: "Storyboard" }),
571
- /* @__PURE__ */ jsx18("ol", { className: "flex gap-3 overflow-x-auto pb-2", children: frames.map((frame) => /* @__PURE__ */ jsx18(StoryboardFrameItem, { frame }, frame.stepId)) })
673
+ /* @__PURE__ */ jsx19("h4", { className: "mb-1.5 text-xs font-semibold tracking-wide text-muted-foreground uppercase", children: "Storyboard" }),
674
+ /* @__PURE__ */ jsx19("ol", { className: "flex items-start gap-3 overflow-x-auto pb-2", children: frames.map((frame) => /* @__PURE__ */ jsx19(StoryboardFrameItem, { frame }, frame.stepId)) })
572
675
  ] });
573
676
  }
574
677
  function StoryboardFrameItem({ frame }) {
575
- const src = isLocalFsPath(frame.path) ? void 0 : safeImageUrl(frame.path);
576
678
  const label = `${frame.keyword} ${frame.text}`;
577
- return /* @__PURE__ */ jsxs11("li", { className: "w-40 shrink-0", children: [
578
- /* @__PURE__ */ jsx18(
579
- "a",
679
+ const hasStates = frame.states.length > 0;
680
+ const caption = /* @__PURE__ */ jsxs11("p", { className: "mt-1 flex items-baseline gap-1.5 text-[0.6875rem] leading-snug", children: [
681
+ /* @__PURE__ */ jsx19("span", { "aria-hidden": true, className: cn("shrink-0", FRAME_GLYPH_COLOR[frame.status]), children: FRAME_GLYPH[frame.status] ?? "\u25CB" }),
682
+ /* @__PURE__ */ jsxs11("span", { className: "min-w-0", children: [
683
+ /* @__PURE__ */ jsx19("span", { className: "font-mono font-semibold text-keyword", children: frame.keyword }),
684
+ " ",
685
+ /* @__PURE__ */ jsx19("span", { className: "text-muted-foreground", children: frame.screenshot?.alt ?? frame.text })
686
+ ] })
687
+ ] });
688
+ return (
689
+ // State cards need room for diff rows; screenshot-only frames keep the
690
+ // original narrow film-cell width (and DOM) unchanged.
691
+ /* @__PURE__ */ jsxs11("li", { className: cn("shrink-0", hasStates ? "w-64" : "w-40"), children: [
692
+ frame.screenshot ? /* @__PURE__ */ jsx19(FrameScreenshot, { frame, label }) : null,
693
+ hasStates ? /* @__PURE__ */ jsx19("div", { className: cn("flex flex-col gap-1.5", frame.screenshot && "mt-1.5"), children: frame.states.map((card, i) => /* @__PURE__ */ jsx19(StateCardView, { card }, card.label ?? i)) }) : null,
694
+ frame.screenshot ? caption : (
695
+ // No screenshot means no image anchor, so the caption carries the
696
+ // jump-to-step link instead.
697
+ /* @__PURE__ */ jsx19("a", { href: `#${frame.stepId}`, "aria-label": `Jump to step: ${label}`, className: "block hover:underline", children: caption })
698
+ )
699
+ ] })
700
+ );
701
+ }
702
+ function FrameScreenshot({ frame, label }) {
703
+ const path = frame.screenshot?.path ?? "";
704
+ const src = isLocalFsPath(path) ? void 0 : safeImageUrl(path);
705
+ return /* @__PURE__ */ jsx19(
706
+ "a",
707
+ {
708
+ href: `#${frame.stepId}`,
709
+ "aria-label": `Jump to step: ${label}`,
710
+ className: "block overflow-hidden rounded-md border border-border transition-colors hover:border-ring",
711
+ children: src ? /* @__PURE__ */ jsx19(
712
+ "img",
713
+ {
714
+ src,
715
+ alt: frame.screenshot?.alt ?? label,
716
+ loading: "lazy",
717
+ className: "h-24 w-full bg-muted object-cover object-top"
718
+ }
719
+ ) : /* @__PURE__ */ jsx19("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" })
720
+ }
721
+ );
722
+ }
723
+ var CHANGE_TONE = {
724
+ added: "bg-pass-bg text-pass",
725
+ removed: "bg-fail-bg text-fail",
726
+ changed: "bg-skip-bg text-skip"
727
+ };
728
+ function prettyJson(value) {
729
+ try {
730
+ return JSON.stringify(value, null, 2) ?? String(value);
731
+ } catch {
732
+ return String(value);
733
+ }
734
+ }
735
+ function StateCardView({ card }) {
736
+ const json = prettyJson(card.value);
737
+ const firstCapture = card.changes === void 0;
738
+ return /* @__PURE__ */ jsxs11("div", { "data-slot": "state-card", className: "rounded-md border border-border bg-card p-2", children: [
739
+ /* @__PURE__ */ jsxs11("p", { className: "flex flex-wrap items-baseline gap-1.5", children: [
740
+ /* @__PURE__ */ jsx19("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" }),
741
+ firstCapture ? /* @__PURE__ */ jsx19("span", { className: "text-[0.625rem] text-muted-foreground italic", children: "first capture" }) : null
742
+ ] }),
743
+ !firstCapture && (card.changes && card.changes.length > 0 ? /* @__PURE__ */ jsx19("ul", { className: "mt-1.5 flex flex-col gap-0.5", children: card.changes.map((change, i) => /* @__PURE__ */ jsx19(
744
+ "li",
580
745
  {
581
- href: `#${frame.stepId}`,
582
- "aria-label": `Jump to step: ${label}`,
583
- className: "block overflow-hidden rounded-md border border-border transition-colors hover:border-ring",
584
- children: src ? /* @__PURE__ */ jsx18(
585
- "img",
586
- {
587
- src,
588
- alt: frame.alt ?? label,
589
- loading: "lazy",
590
- className: "h-24 w-full bg-muted object-cover object-top"
591
- }
592
- ) : /* @__PURE__ */ jsx18("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" })
746
+ className: cn(
747
+ "rounded-sm px-1.5 py-0.5 font-mono text-[0.625rem] leading-snug break-all",
748
+ CHANGE_TONE[change.kind]
749
+ ),
750
+ children: summarizeStateChanges([change])[0]
751
+ },
752
+ i
753
+ )) }) : /* @__PURE__ */ jsx19("p", { className: "mt-1.5 text-[0.625rem] text-muted-foreground", children: "No changes" })),
754
+ /* @__PURE__ */ jsxs11(
755
+ "details",
756
+ {
757
+ open: firstCapture && json.length <= 240,
758
+ className: cn(firstCapture ? "mt-1.5" : "mt-1"),
759
+ children: [
760
+ /* @__PURE__ */ jsx19("summary", { className: "cursor-pointer text-[0.625rem] text-muted-foreground hover:text-foreground", children: "Snapshot" }),
761
+ /* @__PURE__ */ jsx19("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 })
762
+ ]
593
763
  }
594
- ),
595
- /* @__PURE__ */ jsxs11("p", { className: "mt-1 flex items-baseline gap-1.5 text-[0.6875rem] leading-snug", children: [
596
- /* @__PURE__ */ jsx18("span", { "aria-hidden": true, className: cn("shrink-0", FRAME_GLYPH_COLOR[frame.status]), children: FRAME_GLYPH[frame.status] ?? "\u25CB" }),
597
- /* @__PURE__ */ jsxs11("span", { className: "min-w-0", children: [
598
- /* @__PURE__ */ jsx18("span", { className: "font-mono font-semibold text-keyword", children: frame.keyword }),
599
- " ",
600
- /* @__PURE__ */ jsx18("span", { className: "text-muted-foreground", children: frame.alt ?? frame.text })
601
- ] })
602
- ] })
764
+ )
603
765
  ] });
604
766
  }
605
767
 
606
768
  // src/components/ReportAttachments.tsx
607
- import { Fragment as Fragment6, jsx as jsx19, jsxs as jsxs12 } from "react/jsx-runtime";
769
+ import { Fragment as Fragment6, jsx as jsx20, jsxs as jsxs12 } from "react/jsx-runtime";
608
770
  function ReportAttachments({ attachments }) {
609
771
  if (attachments.length === 0) return null;
610
772
  return (
611
773
  // role="group" (not a labelled <section>) so multiple scenarios' attachment
612
774
  // blocks don't create duplicate "Attachments" region landmarks.
613
- /* @__PURE__ */ jsx19("div", { role: "group", "aria-label": "Attachments", className: "mt-3 flex flex-col gap-2", children: attachments.map((att, i) => {
775
+ /* @__PURE__ */ jsx20("div", { role: "group", "aria-label": "Attachments", className: "mt-3 flex flex-col gap-2", children: attachments.map((att, i) => {
614
776
  const dataUri = att.contentEncoding === "BASE64" ? `data:${att.mediaType};base64,${att.body}` : `data:${att.mediaType},${encodeURIComponent(att.body)}`;
615
777
  const isImage = att.mediaType.startsWith("image/");
616
- return /* @__PURE__ */ jsx19("figure", { className: "m-0", children: isImage ? /* @__PURE__ */ jsxs12(Fragment6, { children: [
617
- /* @__PURE__ */ jsx19(
778
+ return /* @__PURE__ */ jsx20("figure", { className: "m-0", children: isImage ? /* @__PURE__ */ jsxs12(Fragment6, { children: [
779
+ /* @__PURE__ */ jsx20(
618
780
  "img",
619
781
  {
620
782
  src: dataUri,
@@ -623,7 +785,7 @@ function ReportAttachments({ attachments }) {
623
785
  className: "max-w-full rounded-md border border-border"
624
786
  }
625
787
  ),
626
- /* @__PURE__ */ jsx19("figcaption", { className: "mt-1 text-xs text-muted-foreground", children: att.name })
788
+ /* @__PURE__ */ jsx20("figcaption", { className: "mt-1 text-xs text-muted-foreground", children: att.name })
627
789
  ] }) : /* @__PURE__ */ jsxs12(
628
790
  "a",
629
791
  {
@@ -697,15 +859,15 @@ function toTraceRows(spans) {
697
859
  roots.sort((a, b) => a.span.startTimeMs - b.span.startTimeMs);
698
860
  const rows = [];
699
861
  const seen = /* @__PURE__ */ new Set();
700
- const walk = (node, depth) => {
862
+ const walk2 = (node, depth) => {
701
863
  if (seen.has(node.span.spanId)) return;
702
864
  seen.add(node.span.spanId);
703
865
  rows.push({ ...node.span, depth });
704
- for (const child of node.children) walk(child, depth + 1);
866
+ for (const child of node.children) walk2(child, depth + 1);
705
867
  };
706
- for (const root of roots) walk(root, 0);
868
+ for (const root of roots) walk2(root, 0);
707
869
  for (const node of byId.values()) {
708
- if (!seen.has(node.span.spanId)) walk(node, 0);
870
+ if (!seen.has(node.span.spanId)) walk2(node, 0);
709
871
  }
710
872
  return rows;
711
873
  }
@@ -721,7 +883,7 @@ function traceWindow(rows) {
721
883
  }
722
884
 
723
885
  // src/components/ReportTrace.tsx
724
- import { jsx as jsx20, jsxs as jsxs13 } from "react/jsx-runtime";
886
+ import { jsx as jsx21, jsxs as jsxs13 } from "react/jsx-runtime";
725
887
  var BAR_COLOR = {
726
888
  ok: "bg-pass",
727
889
  error: "bg-fail",
@@ -742,11 +904,11 @@ function ReportTrace({ spans }) {
742
904
  formatDuration(totalMs),
743
905
  ")"
744
906
  ] }),
745
- /* @__PURE__ */ jsx20("ul", { className: "flex flex-col gap-0.5 px-3 pb-3 font-mono text-[0.6875rem]", children: rows.map((row, i) => {
907
+ /* @__PURE__ */ jsx21("ul", { className: "flex flex-col gap-0.5 px-3 pb-3 font-mono text-[0.6875rem]", children: rows.map((row, i) => {
746
908
  const leftPct = (row.startTimeMs - minStartMs) / totalMs * 100;
747
909
  const widthPct = Math.max(row.durationMs / totalMs * 100, 0.5);
748
910
  return /* @__PURE__ */ jsxs13("li", { className: "flex items-center gap-2", children: [
749
- /* @__PURE__ */ jsx20(
911
+ /* @__PURE__ */ jsx21(
750
912
  "span",
751
913
  {
752
914
  className: "min-w-0 flex-1 truncate text-foreground",
@@ -755,14 +917,14 @@ function ReportTrace({ spans }) {
755
917
  children: row.name
756
918
  }
757
919
  ),
758
- /* @__PURE__ */ jsx20("span", { className: "relative h-3 w-1/2 shrink-0 overflow-hidden rounded-sm bg-border/40", children: /* @__PURE__ */ jsx20(
920
+ /* @__PURE__ */ jsx21("span", { className: "relative h-3 w-1/2 shrink-0 overflow-hidden rounded-sm bg-border/40", children: /* @__PURE__ */ jsx21(
759
921
  "span",
760
922
  {
761
923
  className: cn("absolute top-0 h-full rounded-sm", BAR_COLOR[row.status]),
762
924
  style: { left: `${leftPct}%`, width: `${widthPct}%` }
763
925
  }
764
926
  ) }),
765
- /* @__PURE__ */ jsx20("span", { className: "w-16 shrink-0 text-right text-muted-foreground", children: formatDuration(row.durationMs) })
927
+ /* @__PURE__ */ jsx21("span", { className: "w-16 shrink-0 text-right text-muted-foreground", children: formatDuration(row.durationMs) })
766
928
  ] }, `${row.spanId}-${i}`);
767
929
  }) })
768
930
  ] });
@@ -831,7 +993,7 @@ function diffSinceLastRun(history2, scenarios) {
831
993
  }
832
994
 
833
995
  // src/components/ScenarioRunHistory.tsx
834
- import { Fragment as Fragment7, jsx as jsx21, jsxs as jsxs14 } from "react/jsx-runtime";
996
+ import { Fragment as Fragment7, jsx as jsx22, jsxs as jsxs14 } from "react/jsx-runtime";
835
997
  var MAX_DOTS = 10;
836
998
  var DOT_COLOR = {
837
999
  passed: "bg-pass",
@@ -852,15 +1014,15 @@ function ScenarioRunHistory({ scenarioId }) {
852
1014
  const flaky = flakinessOf(recent) === "flaky";
853
1015
  const summary = flaky ? `${describeRunHistory(recent)} \xB7 Flaky` : describeRunHistory(recent);
854
1016
  return /* @__PURE__ */ jsxs14(Fragment7, { children: [
855
- flaky ? /* @__PURE__ */ jsx21(Badge, { variant: "pending", "aria-label": "Flaky: status flips between recent runs", title: summary, children: "Flaky" }) : null,
856
- /* @__PURE__ */ jsx21(
1017
+ flaky ? /* @__PURE__ */ jsx22(Badge, { variant: "pending", "aria-label": "Flaky: status flips between recent runs", title: summary, children: "Flaky" }) : null,
1018
+ /* @__PURE__ */ jsx22(
857
1019
  "span",
858
1020
  {
859
1021
  role: "img",
860
1022
  "aria-label": `Run history: ${summary}`,
861
1023
  title: summary,
862
1024
  className: "flex shrink-0 items-center gap-[3px]",
863
- children: recent.map((e, i) => /* @__PURE__ */ jsx21(
1025
+ children: recent.map((e, i) => /* @__PURE__ */ jsx22(
864
1026
  "span",
865
1027
  {
866
1028
  "aria-hidden": true,
@@ -951,7 +1113,7 @@ function stringify(value) {
951
1113
  return String(value);
952
1114
  }
953
1115
  }
954
- function docEntryToMarkdown(entry) {
1116
+ function docEntryToMarkdown(entry, stateLanes) {
955
1117
  const lines = [];
956
1118
  switch (entry.kind) {
957
1119
  case "note":
@@ -1003,13 +1165,24 @@ function docEntryToMarkdown(entry) {
1003
1165
  case "custom":
1004
1166
  lines.push(`**${entry.type}**`, "", "```json", stringify(entry.data), "```");
1005
1167
  break;
1168
+ case "state": {
1169
+ const lane = entry.label ?? "";
1170
+ lines.push(`**${entry.label ?? "State"}**`);
1171
+ if (stateLanes?.has(lane)) {
1172
+ const summary = summarizeStateChanges(diffStateValues(stateLanes.get(lane), entry.value));
1173
+ if (summary.length > 0) lines.push("", ...summary.map((l) => `- ${l}`));
1174
+ }
1175
+ stateLanes?.set(lane, entry.value);
1176
+ lines.push("", "<details>", "<summary>snapshot</summary>", "", "```json", stringify(entry.value ?? null), "```", "", "</details>");
1177
+ break;
1178
+ }
1006
1179
  }
1007
1180
  for (const child of entry.children ?? []) {
1008
- lines.push("", ...docEntryToMarkdown(child));
1181
+ lines.push("", ...docEntryToMarkdown(child, stateLanes));
1009
1182
  }
1010
1183
  return lines;
1011
1184
  }
1012
- function stepLines(step, ordinal, full) {
1185
+ function stepLines(step, ordinal, full, stateLanes) {
1013
1186
  const status = step.status === "passed" ? "" : ` \u2014 **${step.status}**`;
1014
1187
  const lines = [`${ordinal}. **${step.keyword}** ${step.text}${status}`];
1015
1188
  if (!full) return lines;
@@ -1017,7 +1190,7 @@ function stepLines(step, ordinal, full) {
1017
1190
  lines.push(...step.errorMessage.split("\n").map((l) => ` > ${l}`));
1018
1191
  }
1019
1192
  for (const entry of step.docEntries) {
1020
- lines.push("", ...docEntryToMarkdown(entry).map((l) => l === "" ? l : ` ${l}`));
1193
+ lines.push("", ...docEntryToMarkdown(entry, stateLanes).map((l) => l === "" ? l : ` ${l}`));
1021
1194
  }
1022
1195
  return lines;
1023
1196
  }
@@ -1026,9 +1199,10 @@ function scenarioToMarkdown(scenario, options = {}) {
1026
1199
  const full = variant === "full";
1027
1200
  const lines = full ? [`# ${scenario.title}`, ""] : [`## ${scenario.title} _(${scenario.status})_`, ""];
1028
1201
  if (full && meta.length > 0) lines.push(...meta);
1202
+ const stateLanes = /* @__PURE__ */ new Map();
1029
1203
  if (scenario.steps.length > 0) {
1030
1204
  if (full) lines.push("", "## Steps", "");
1031
- scenario.steps.forEach((step, i) => lines.push(...stepLines(step, i + 1, full)));
1205
+ scenario.steps.forEach((step, i) => lines.push(...stepLines(step, i + 1, full, stateLanes)));
1032
1206
  }
1033
1207
  if (scenario.errorMessage) {
1034
1208
  if (full) lines.push("", "## Failure", "");
@@ -1037,7 +1211,7 @@ function scenarioToMarkdown(scenario, options = {}) {
1037
1211
  }
1038
1212
  if (full && scenario.docEntries.length > 0) {
1039
1213
  lines.push("", "## Docs", "");
1040
- for (const entry of scenario.docEntries) lines.push(...docEntryToMarkdown(entry), "");
1214
+ for (const entry of scenario.docEntries) lines.push(...docEntryToMarkdown(entry, stateLanes), "");
1041
1215
  }
1042
1216
  return lines.join("\n").replaceAll(/\n{3,}/g, "\n\n").trimEnd() + (full ? "\n" : "");
1043
1217
  }
@@ -1077,9 +1251,9 @@ function scenarioPermalink(scenario) {
1077
1251
 
1078
1252
  // src/components/ui/card.tsx
1079
1253
  import "react";
1080
- import { jsx as jsx22 } from "react/jsx-runtime";
1254
+ import { jsx as jsx23 } from "react/jsx-runtime";
1081
1255
  function Card({ className, ...props }) {
1082
- return /* @__PURE__ */ jsx22(
1256
+ return /* @__PURE__ */ jsx23(
1083
1257
  "div",
1084
1258
  {
1085
1259
  "data-slot": "card",
@@ -1092,7 +1266,7 @@ function Card({ className, ...props }) {
1092
1266
  );
1093
1267
  }
1094
1268
  function CardHeader({ className, ...props }) {
1095
- return /* @__PURE__ */ jsx22(
1269
+ return /* @__PURE__ */ jsx23(
1096
1270
  "div",
1097
1271
  {
1098
1272
  "data-slot": "card-header",
@@ -1105,7 +1279,7 @@ function CardHeader({ className, ...props }) {
1105
1279
  );
1106
1280
  }
1107
1281
  function CardContent({ className, ...props }) {
1108
- return /* @__PURE__ */ jsx22(
1282
+ return /* @__PURE__ */ jsx23(
1109
1283
  "div",
1110
1284
  {
1111
1285
  "data-slot": "card-content",
@@ -1119,13 +1293,13 @@ function CardContent({ className, ...props }) {
1119
1293
  import "react";
1120
1294
  import { Menu as MenuPrimitive } from "@base-ui/react/menu";
1121
1295
  import { CheckIcon } from "lucide-react";
1122
- import { jsx as jsx23, jsxs as jsxs15 } from "react/jsx-runtime";
1296
+ import { jsx as jsx24, jsxs as jsxs15 } from "react/jsx-runtime";
1123
1297
  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";
1124
1298
  function DropdownMenu(props) {
1125
- return /* @__PURE__ */ jsx23(MenuPrimitive.Root, { "data-slot": "dropdown-menu", ...props });
1299
+ return /* @__PURE__ */ jsx24(MenuPrimitive.Root, { "data-slot": "dropdown-menu", ...props });
1126
1300
  }
1127
1301
  function DropdownMenuTrigger(props) {
1128
- return /* @__PURE__ */ jsx23(MenuPrimitive.Trigger, { "data-slot": "dropdown-menu-trigger", ...props });
1302
+ return /* @__PURE__ */ jsx24(MenuPrimitive.Trigger, { "data-slot": "dropdown-menu-trigger", ...props });
1129
1303
  }
1130
1304
  function DropdownMenuContent({
1131
1305
  className,
@@ -1133,14 +1307,14 @@ function DropdownMenuContent({
1133
1307
  sideOffset = 4,
1134
1308
  ...props
1135
1309
  }) {
1136
- return /* @__PURE__ */ jsx23(MenuPrimitive.Portal, { children: /* @__PURE__ */ jsx23(
1310
+ return /* @__PURE__ */ jsx24(MenuPrimitive.Portal, { children: /* @__PURE__ */ jsx24(
1137
1311
  MenuPrimitive.Positioner,
1138
1312
  {
1139
1313
  "data-slot": "dropdown-menu-positioner",
1140
1314
  className: "z-50",
1141
1315
  align,
1142
1316
  sideOffset,
1143
- children: /* @__PURE__ */ jsx23(
1317
+ children: /* @__PURE__ */ jsx24(
1144
1318
  MenuPrimitive.Popup,
1145
1319
  {
1146
1320
  "data-slot": "dropdown-menu-content",
@@ -1158,7 +1332,7 @@ function DropdownMenuItem({
1158
1332
  className,
1159
1333
  ...props
1160
1334
  }) {
1161
- return /* @__PURE__ */ jsx23(
1335
+ return /* @__PURE__ */ jsx24(
1162
1336
  MenuPrimitive.Item,
1163
1337
  {
1164
1338
  "data-slot": "dropdown-menu-item",
@@ -1170,7 +1344,7 @@ function DropdownMenuItem({
1170
1344
 
1171
1345
  // src/components/ReportScenario.tsx
1172
1346
  import { LinkIcon, FileTextIcon, SparklesIcon, MoreHorizontalIcon } from "lucide-react";
1173
- import { jsx as jsx24, jsxs as jsxs16 } from "react/jsx-runtime";
1347
+ import { jsx as jsx25, jsxs as jsxs16 } from "react/jsx-runtime";
1174
1348
  var STATUS_META = {
1175
1349
  passed: { label: "Passed", glyph: "\u2713", glyphColor: "text-pass", badgeVariant: "passed", showPill: false },
1176
1350
  failed: { label: "Failed", glyph: "\u2717", glyphColor: "text-fail", badgeVariant: "failed", showPill: true },
@@ -1197,7 +1371,7 @@ function ReportScenario({ scenario, hideTitle = false }) {
1197
1371
  /* @__PURE__ */ jsxs16(CardHeader, { className: "px-4 py-3", children: [
1198
1372
  /* @__PURE__ */ jsxs16("div", { className: cn("flex items-start gap-4", hideTitle ? "justify-end" : "justify-between"), children: [
1199
1373
  hideTitle ? null : /* @__PURE__ */ jsxs16("h3", { id: titleId, className: "flex items-center gap-2 text-sm font-medium text-foreground", children: [
1200
- collapsible ? /* @__PURE__ */ jsx24(
1374
+ collapsible ? /* @__PURE__ */ jsx25(
1201
1375
  "button",
1202
1376
  {
1203
1377
  type: "button",
@@ -1206,36 +1380,36 @@ function ReportScenario({ scenario, hideTitle = false }) {
1206
1380
  "aria-controls": bodyId,
1207
1381
  "aria-label": `Toggle ${scenario.title}`,
1208
1382
  className: "shrink-0 cursor-pointer text-muted-foreground hover:text-foreground",
1209
- children: /* @__PURE__ */ jsx24("span", { "aria-hidden": true, className: cn("inline-block text-xs transition-transform", !collapsed && "rotate-90"), children: "\u25B8" })
1383
+ children: /* @__PURE__ */ jsx25("span", { "aria-hidden": true, className: cn("inline-block text-xs transition-transform", !collapsed && "rotate-90"), children: "\u25B8" })
1210
1384
  }
1211
1385
  ) : null,
1212
- /* @__PURE__ */ jsx24("span", { "aria-hidden": true, className: cn("text-sm leading-none", meta.glyphColor), children: meta.glyph }),
1213
- /* @__PURE__ */ jsx24("span", { children: scenario.title })
1386
+ /* @__PURE__ */ jsx25("span", { "aria-hidden": true, className: cn("text-sm leading-none", meta.glyphColor), children: meta.glyph }),
1387
+ /* @__PURE__ */ jsx25("span", { children: scenario.title })
1214
1388
  ] }),
1215
1389
  /* @__PURE__ */ jsxs16("div", { className: "flex shrink-0 items-center gap-2", children: [
1216
- /* @__PURE__ */ jsx24(ScenarioRunHistory, { scenarioId: scenario.id }),
1217
- scenario.durationMs > 0 ? /* @__PURE__ */ jsx24("span", { className: "whitespace-nowrap font-mono text-[0.6875rem] text-muted-foreground", children: formatDuration(scenario.durationMs) }) : null,
1218
- meta.showPill ? /* @__PURE__ */ jsx24(Badge, { variant: meta.badgeVariant, "aria-label": `Status: ${label}`, children: label }) : /* @__PURE__ */ jsx24("span", { className: "sr-only", children: `Status: ${label}` }),
1390
+ /* @__PURE__ */ jsx25(ScenarioRunHistory, { scenarioId: scenario.id }),
1391
+ scenario.durationMs > 0 ? /* @__PURE__ */ jsx25("span", { className: "whitespace-nowrap font-mono text-[0.6875rem] text-muted-foreground", children: formatDuration(scenario.durationMs) }) : null,
1392
+ meta.showPill ? /* @__PURE__ */ jsx25(Badge, { variant: meta.badgeVariant, "aria-label": `Status: ${label}`, children: label }) : /* @__PURE__ */ jsx25("span", { className: "sr-only", children: `Status: ${label}` }),
1219
1393
  actions ? /* @__PURE__ */ jsxs16(DropdownMenu, { children: [
1220
- /* @__PURE__ */ jsx24(
1394
+ /* @__PURE__ */ jsx25(
1221
1395
  DropdownMenuTrigger,
1222
1396
  {
1223
1397
  "aria-label": `Actions for ${scenario.title}`,
1224
1398
  className: "cursor-pointer rounded p-1 text-muted-foreground hover:bg-muted hover:text-foreground [&_svg]:size-4",
1225
- children: /* @__PURE__ */ jsx24(MoreHorizontalIcon, { "aria-hidden": true })
1399
+ children: /* @__PURE__ */ jsx25(MoreHorizontalIcon, { "aria-hidden": true })
1226
1400
  }
1227
1401
  ),
1228
1402
  /* @__PURE__ */ jsxs16(DropdownMenuContent, { align: "end", children: [
1229
1403
  /* @__PURE__ */ jsxs16(DropdownMenuItem, { onClick: () => actions.copyLink(scenario), children: [
1230
- /* @__PURE__ */ jsx24(LinkIcon, {}),
1404
+ /* @__PURE__ */ jsx25(LinkIcon, {}),
1231
1405
  " Copy link"
1232
1406
  ] }),
1233
1407
  /* @__PURE__ */ jsxs16(DropdownMenuItem, { onClick: () => actions.copyMarkdown(scenario), children: [
1234
- /* @__PURE__ */ jsx24(FileTextIcon, {}),
1408
+ /* @__PURE__ */ jsx25(FileTextIcon, {}),
1235
1409
  " Copy as Markdown"
1236
1410
  ] }),
1237
1411
  /* @__PURE__ */ jsxs16(DropdownMenuItem, { onClick: () => actions.copyPrompt(scenario), children: [
1238
- /* @__PURE__ */ jsx24(SparklesIcon, {}),
1412
+ /* @__PURE__ */ jsx25(SparklesIcon, {}),
1239
1413
  " Explain with AI"
1240
1414
  ] })
1241
1415
  ] })
@@ -1243,12 +1417,12 @@ function ReportScenario({ scenario, hideTitle = false }) {
1243
1417
  ] })
1244
1418
  ] }),
1245
1419
  scenario.tags.length > 0 || (scenario.tickets?.length ?? 0) > 0 ? /* @__PURE__ */ jsxs16("ul", { "aria-label": "Tags and tickets", className: "flex flex-wrap gap-1.5", children: [
1246
- scenario.tags.map((t) => /* @__PURE__ */ jsx24("li", { children: /* @__PURE__ */ jsx24(Badge, { variant: "tag", children: t }) }, `tag-${t}`)),
1247
- (scenario.tickets ?? []).map((ticket) => /* @__PURE__ */ jsx24("li", { children: ticket.url ? /* @__PURE__ */ jsx24("a", { href: ticket.url, target: "_blank", rel: "noreferrer noopener", children: /* @__PURE__ */ jsx24(Badge, { variant: "outline", children: ticket.id }) }) : /* @__PURE__ */ jsx24(Badge, { variant: "outline", children: ticket.id }) }, `ticket-${ticket.id}`))
1420
+ scenario.tags.map((t) => /* @__PURE__ */ jsx25("li", { children: /* @__PURE__ */ jsx25(Badge, { variant: "tag", children: t }) }, `tag-${t}`)),
1421
+ (scenario.tickets ?? []).map((ticket) => /* @__PURE__ */ jsx25("li", { children: ticket.url ? /* @__PURE__ */ jsx25("a", { href: ticket.url, target: "_blank", rel: "noreferrer noopener", children: /* @__PURE__ */ jsx25(Badge, { variant: "outline", children: ticket.id }) }) : /* @__PURE__ */ jsx25(Badge, { variant: "outline", children: ticket.id }) }, `ticket-${ticket.id}`))
1248
1422
  ] }) : null
1249
1423
  ] }),
1250
1424
  /* @__PURE__ */ jsxs16(CardContent, { id: bodyId, hidden: collapsed, className: "px-4 pt-0 pb-4", children: [
1251
- scenario.errorMessage ? /* @__PURE__ */ jsx24(
1425
+ scenario.errorMessage ? /* @__PURE__ */ jsx25(
1252
1426
  "pre",
1253
1427
  {
1254
1428
  role: "alert",
@@ -1256,11 +1430,11 @@ function ReportScenario({ scenario, hideTitle = false }) {
1256
1430
  children: scenario.errorMessage
1257
1431
  }
1258
1432
  ) : null,
1259
- /* @__PURE__ */ jsx24(ReportStoryboard, { scenario }),
1260
- /* @__PURE__ */ jsx24(ReportSteps, { scenario }),
1261
- scenario.docEntries.length > 0 ? /* @__PURE__ */ jsx24("div", { "data-es-docs": true, className: "mt-3", children: /* @__PURE__ */ jsx24(ReportDocEntries, { entries: scenario.docEntries }) }) : null,
1262
- /* @__PURE__ */ jsx24(ReportAttachments, { attachments: scenario.attachments }),
1263
- /* @__PURE__ */ jsx24(ReportTrace, { spans: scenario.otelSpans })
1433
+ /* @__PURE__ */ jsx25(ReportStoryboard, { scenario }),
1434
+ /* @__PURE__ */ jsx25(ReportSteps, { scenario }),
1435
+ scenario.docEntries.length > 0 ? /* @__PURE__ */ jsx25("div", { "data-es-docs": true, className: "mt-3", children: /* @__PURE__ */ jsx25(ReportDocEntries, { entries: scenario.docEntries }) }) : null,
1436
+ /* @__PURE__ */ jsx25(ReportAttachments, { attachments: scenario.attachments }),
1437
+ /* @__PURE__ */ jsx25(ReportTrace, { spans: scenario.otelSpans })
1264
1438
  ] })
1265
1439
  ]
1266
1440
  }
@@ -1268,13 +1442,13 @@ function ReportScenario({ scenario, hideTitle = false }) {
1268
1442
  }
1269
1443
 
1270
1444
  // src/components/ReportScenarioList.tsx
1271
- import { Fragment as Fragment8, jsx as jsx25 } from "react/jsx-runtime";
1445
+ import { Fragment as Fragment8, jsx as jsx26 } from "react/jsx-runtime";
1272
1446
  function ReportScenarioList({ feature }) {
1273
- return /* @__PURE__ */ jsx25(Fragment8, { children: feature.scenarios.map((scenario) => /* @__PURE__ */ jsx25(ReportScenario, { scenario }, scenario.id)) });
1447
+ return /* @__PURE__ */ jsx26(Fragment8, { children: feature.scenarios.map((scenario) => /* @__PURE__ */ jsx26(ReportScenario, { scenario }, scenario.id)) });
1274
1448
  }
1275
1449
 
1276
1450
  // src/components/ReportFeature.tsx
1277
- import { Fragment as Fragment9, jsx as jsx26, jsxs as jsxs17 } from "react/jsx-runtime";
1451
+ import { Fragment as Fragment9, jsx as jsx27, jsxs as jsxs17 } from "react/jsx-runtime";
1278
1452
  function ReportFeature({ feature }) {
1279
1453
  const titleId = `${feature.id}-title`;
1280
1454
  const bodyId = `${feature.id}-body`;
@@ -1295,7 +1469,7 @@ function ReportFeature({ feature }) {
1295
1469
  children: [
1296
1470
  /* @__PURE__ */ jsxs17("div", { className: "flex items-end justify-between gap-4 border-b border-border pb-2", children: [
1297
1471
  /* @__PURE__ */ jsxs17("div", { className: "min-w-0", children: [
1298
- /* @__PURE__ */ jsx26("h2", { id: titleId, className: "text-base font-semibold tracking-tight text-foreground", children: collapse ? /* @__PURE__ */ jsxs17(
1472
+ /* @__PURE__ */ jsx27("h2", { id: titleId, className: "text-base font-semibold tracking-tight text-foreground", children: collapse ? /* @__PURE__ */ jsxs17(
1299
1473
  "button",
1300
1474
  {
1301
1475
  type: "button",
@@ -1304,12 +1478,12 @@ function ReportFeature({ feature }) {
1304
1478
  "aria-controls": bodyId,
1305
1479
  className: "flex w-full cursor-pointer items-center gap-2 text-left hover:text-foreground/80",
1306
1480
  children: [
1307
- /* @__PURE__ */ jsx26("span", { "aria-hidden": true, className: cn("shrink-0 text-xs text-muted-foreground transition-transform", !collapsed && "rotate-90"), children: "\u25B8" }),
1308
- /* @__PURE__ */ jsx26("span", { className: "truncate", children: feature.title })
1481
+ /* @__PURE__ */ jsx27("span", { "aria-hidden": true, className: cn("shrink-0 text-xs text-muted-foreground transition-transform", !collapsed && "rotate-90"), children: "\u25B8" }),
1482
+ /* @__PURE__ */ jsx27("span", { className: "truncate", children: feature.title })
1309
1483
  ]
1310
1484
  }
1311
1485
  ) : feature.title }),
1312
- /* @__PURE__ */ jsx26("p", { className: cn("mt-0.5 truncate font-mono text-xs text-muted-foreground", collapse && "pl-5"), children: feature.sourceFile })
1486
+ /* @__PURE__ */ jsx27("p", { className: cn("mt-0.5 truncate font-mono text-xs text-muted-foreground", collapse && "pl-5"), children: feature.sourceFile })
1313
1487
  ] }),
1314
1488
  /* @__PURE__ */ jsxs17(
1315
1489
  "p",
@@ -1321,13 +1495,13 @@ function ReportFeature({ feature }) {
1321
1495
  s.passed,
1322
1496
  " passed"
1323
1497
  ] }),
1324
- /* @__PURE__ */ jsx26("span", { "aria-hidden": true, children: "\xB7" }),
1498
+ /* @__PURE__ */ jsx27("span", { "aria-hidden": true, children: "\xB7" }),
1325
1499
  /* @__PURE__ */ jsxs17("span", { className: cn(s.failed > 0 && "font-medium text-fail"), children: [
1326
1500
  s.failed,
1327
1501
  " failed"
1328
1502
  ] }),
1329
1503
  skipped > 0 ? /* @__PURE__ */ jsxs17(Fragment9, { children: [
1330
- /* @__PURE__ */ jsx26("span", { "aria-hidden": true, children: "\xB7" }),
1504
+ /* @__PURE__ */ jsx27("span", { "aria-hidden": true, children: "\xB7" }),
1331
1505
  /* @__PURE__ */ jsxs17("span", { children: [
1332
1506
  skipped,
1333
1507
  " skipped"
@@ -1337,7 +1511,7 @@ function ReportFeature({ feature }) {
1337
1511
  }
1338
1512
  )
1339
1513
  ] }),
1340
- /* @__PURE__ */ jsx26("div", { id: bodyId, hidden: collapsed, className: "flex flex-col gap-3", children: /* @__PURE__ */ jsx26(ReportScenarioList, { feature }) })
1514
+ /* @__PURE__ */ jsx27("div", { id: bodyId, hidden: collapsed, className: "flex flex-col gap-3", children: /* @__PURE__ */ jsx27(ReportScenarioList, { feature }) })
1341
1515
  ]
1342
1516
  }
1343
1517
  )
@@ -1345,17 +1519,17 @@ function ReportFeature({ feature }) {
1345
1519
  }
1346
1520
 
1347
1521
  // src/components/ReportFeatureList.tsx
1348
- import { jsx as jsx27 } from "react/jsx-runtime";
1522
+ import { jsx as jsx28 } from "react/jsx-runtime";
1349
1523
  function ReportFeatureList() {
1350
1524
  const report = useReport();
1351
- return /* @__PURE__ */ jsx27("div", { className: "flex flex-col gap-8", children: report.features.map((feature) => /* @__PURE__ */ jsx27(ReportFeature, { feature }, feature.id)) });
1525
+ return /* @__PURE__ */ jsx28("div", { className: "flex flex-col gap-8", children: report.features.map((feature) => /* @__PURE__ */ jsx28(ReportFeature, { feature }, feature.id)) });
1352
1526
  }
1353
1527
 
1354
1528
  // src/components/ui/empty.tsx
1355
1529
  import { cva as cva2 } from "class-variance-authority";
1356
- import { jsx as jsx28 } from "react/jsx-runtime";
1530
+ import { jsx as jsx29 } from "react/jsx-runtime";
1357
1531
  function Empty({ className, ...props }) {
1358
- return /* @__PURE__ */ jsx28(
1532
+ return /* @__PURE__ */ jsx29(
1359
1533
  "div",
1360
1534
  {
1361
1535
  "data-slot": "empty",
@@ -1368,7 +1542,7 @@ function Empty({ className, ...props }) {
1368
1542
  );
1369
1543
  }
1370
1544
  function EmptyHeader({ className, ...props }) {
1371
- return /* @__PURE__ */ jsx28(
1545
+ return /* @__PURE__ */ jsx29(
1372
1546
  "div",
1373
1547
  {
1374
1548
  "data-slot": "empty-header",
@@ -1395,7 +1569,7 @@ var emptyMediaVariants = cva2(
1395
1569
  }
1396
1570
  );
1397
1571
  function EmptyTitle({ className, ...props }) {
1398
- return /* @__PURE__ */ jsx28(
1572
+ return /* @__PURE__ */ jsx29(
1399
1573
  "div",
1400
1574
  {
1401
1575
  "data-slot": "empty-title",
@@ -1406,16 +1580,16 @@ function EmptyTitle({ className, ...props }) {
1406
1580
  }
1407
1581
 
1408
1582
  // src/components/ReportEmpty.tsx
1409
- import { jsx as jsx29 } from "react/jsx-runtime";
1583
+ import { jsx as jsx30 } from "react/jsx-runtime";
1410
1584
  function ReportEmpty({ message }) {
1411
- return /* @__PURE__ */ jsx29(Empty, { "aria-live": "polite", className: "border", children: /* @__PURE__ */ jsx29(EmptyHeader, { children: /* @__PURE__ */ jsx29(EmptyTitle, { children: message ?? "No scenarios in this report." }) }) });
1585
+ return /* @__PURE__ */ jsx30(Empty, { "aria-live": "polite", className: "border", children: /* @__PURE__ */ jsx30(EmptyHeader, { children: /* @__PURE__ */ jsx30(EmptyTitle, { children: message ?? "No scenarios in this report." }) }) });
1412
1586
  }
1413
1587
 
1414
1588
  // src/components/ReportSummary.tsx
1415
- import { jsx as jsx30, jsxs as jsxs18 } from "react/jsx-runtime";
1589
+ import { jsx as jsx31, jsxs as jsxs18 } from "react/jsx-runtime";
1416
1590
  function ReportSummary({ className }) {
1417
1591
  const report = useReport();
1418
- return /* @__PURE__ */ jsx30(
1592
+ return /* @__PURE__ */ jsx31(
1419
1593
  ReportSummaryView,
1420
1594
  {
1421
1595
  summary: report.summary,
@@ -1441,7 +1615,7 @@ function ReportSummaryView({ summary, className, ariaLabel }) {
1441
1615
  if (summary.pending > 0) {
1442
1616
  cards.push({ status: "pending", label: "Pending", value: summary.pending });
1443
1617
  }
1444
- return /* @__PURE__ */ jsx30(
1618
+ return /* @__PURE__ */ jsx31(
1445
1619
  "dl",
1446
1620
  {
1447
1621
  className: cn(
@@ -1461,10 +1635,10 @@ function ReportSummaryView({ summary, className, ariaLabel }) {
1461
1635
  className: "rounded-lg border bg-card px-4 py-3",
1462
1636
  children: [
1463
1637
  /* @__PURE__ */ jsxs18("dt", { className: "flex items-center gap-1.5 font-mono text-[11px] font-medium uppercase tracking-wider text-muted-foreground", children: [
1464
- /* @__PURE__ */ jsx30("span", { className: cn("size-1.5 shrink-0 rounded-full", tone.dot), "aria-hidden": "true" }),
1638
+ /* @__PURE__ */ jsx31("span", { className: cn("size-1.5 shrink-0 rounded-full", tone.dot), "aria-hidden": "true" }),
1465
1639
  c.label
1466
1640
  ] }),
1467
- /* @__PURE__ */ jsx30("dd", { className: cn("mt-2 text-3xl font-semibold leading-none tracking-tight tabular-nums", tone.num), children: c.value })
1641
+ /* @__PURE__ */ jsx31("dd", { className: cn("mt-2 text-3xl font-semibold leading-none tracking-tight tabular-nums", tone.num), children: c.value })
1468
1642
  ]
1469
1643
  },
1470
1644
  c.status
@@ -1524,7 +1698,7 @@ function prUrl(ci) {
1524
1698
  }
1525
1699
 
1526
1700
  // src/components/ReportMeta.tsx
1527
- import { jsx as jsx31, jsxs as jsxs19 } from "react/jsx-runtime";
1701
+ import { jsx as jsx32, jsxs as jsxs19 } from "react/jsx-runtime";
1528
1702
  function ReportMeta() {
1529
1703
  const report = useReport();
1530
1704
  const items = [];
@@ -1547,7 +1721,7 @@ function ReportMeta() {
1547
1721
  const short = sha.slice(0, 8);
1548
1722
  items.push({
1549
1723
  label: "Commit",
1550
- value: url ? /* @__PURE__ */ jsx31("a", { href: url, target: "_blank", rel: "noreferrer noopener", className: linkClass, children: short }) : short
1724
+ value: url ? /* @__PURE__ */ jsx32("a", { href: url, target: "_blank", rel: "noreferrer noopener", className: linkClass, children: short }) : short
1551
1725
  });
1552
1726
  }
1553
1727
  if (report.ci) {
@@ -1564,7 +1738,7 @@ function ReportMeta() {
1564
1738
  const label = `#${report.ci.prNumber}`;
1565
1739
  items.push({
1566
1740
  label: "PR",
1567
- value: url ? /* @__PURE__ */ jsx31("a", { href: url, target: "_blank", rel: "noreferrer noopener", className: linkClass, children: label }) : label
1741
+ value: url ? /* @__PURE__ */ jsx32("a", { href: url, target: "_blank", rel: "noreferrer noopener", className: linkClass, children: label }) : label
1568
1742
  });
1569
1743
  }
1570
1744
  if (items.length === 0) return null;
@@ -1574,26 +1748,26 @@ function ReportMeta() {
1574
1748
  // so it works with no JS (the SSR/no-hydration report still toggles).
1575
1749
  /* @__PURE__ */ jsxs19("details", { "data-es-meta-card": true, className: "es-run-details group rounded-lg border border-border bg-card text-xs", children: [
1576
1750
  /* @__PURE__ */ jsxs19("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: [
1577
- /* @__PURE__ */ jsx31("span", { "aria-hidden": true, className: "text-xs transition-transform group-open:rotate-90", children: "\u25B8" }),
1751
+ /* @__PURE__ */ jsx32("span", { "aria-hidden": true, className: "text-xs transition-transform group-open:rotate-90", children: "\u25B8" }),
1578
1752
  "Run details"
1579
1753
  ] }),
1580
- /* @__PURE__ */ jsx31("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__ */ jsxs19("div", { className: "flex items-baseline gap-1.5", children: [
1581
- /* @__PURE__ */ jsx31("dt", { className: "font-medium", children: item.label }),
1582
- /* @__PURE__ */ jsx31("dd", { className: "font-mono text-foreground", children: item.value })
1754
+ /* @__PURE__ */ jsx32("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__ */ jsxs19("div", { className: "flex items-baseline gap-1.5", children: [
1755
+ /* @__PURE__ */ jsx32("dt", { className: "font-medium", children: item.label }),
1756
+ /* @__PURE__ */ jsx32("dd", { className: "font-mono text-foreground", children: item.value })
1583
1757
  ] }, item.label)) })
1584
1758
  ] })
1585
1759
  );
1586
1760
  }
1587
1761
 
1588
1762
  // src/components/ReportSchemaError.tsx
1589
- import { jsx as jsx32, jsxs as jsxs20 } from "react/jsx-runtime";
1763
+ import { jsx as jsx33, jsxs as jsxs20 } from "react/jsx-runtime";
1590
1764
  function ReportSchemaError({ error }) {
1591
1765
  return /* @__PURE__ */ jsxs20("section", { className: "es-schema-error", role: "alert", "aria-live": "assertive", children: [
1592
- /* @__PURE__ */ jsx32("p", { children: /* @__PURE__ */ jsx32("strong", { children: "Report could not be displayed." }) }),
1593
- /* @__PURE__ */ jsx32("p", { children: error.message }),
1766
+ /* @__PURE__ */ jsx33("p", { children: /* @__PURE__ */ jsx33("strong", { children: "Report could not be displayed." }) }),
1767
+ /* @__PURE__ */ jsx33("p", { children: error.message }),
1594
1768
  error.code === "SCHEMA_VERSION_MISMATCH" ? /* @__PURE__ */ jsxs20("p", { children: [
1595
1769
  "The report bundle is newer than this version of ",
1596
- /* @__PURE__ */ jsx32("code", { children: "executable-stories-react" }),
1770
+ /* @__PURE__ */ jsx33("code", { children: "executable-stories-react" }),
1597
1771
  ". Upgrade the package, or regenerate the report with an older formatters CLI."
1598
1772
  ] }) : null,
1599
1773
  error.issues && error.issues.length > 0 ? /* @__PURE__ */ jsxs20("details", { children: [
@@ -1602,20 +1776,20 @@ function ReportSchemaError({ error }) {
1602
1776
  " validation issue",
1603
1777
  error.issues.length === 1 ? "" : "s"
1604
1778
  ] }),
1605
- /* @__PURE__ */ jsx32("pre", { children: error.issues.slice(0, 20).map((i) => `${i.path}: ${i.message}`).join("\n") })
1779
+ /* @__PURE__ */ jsx33("pre", { children: error.issues.slice(0, 20).map((i) => `${i.path}: ${i.message}`).join("\n") })
1606
1780
  ] }) : null
1607
1781
  ] });
1608
1782
  }
1609
1783
 
1610
1784
  // src/components/ReportShell.tsx
1611
- import { Fragment as Fragment10, jsx as jsx33, jsxs as jsxs21 } from "react/jsx-runtime";
1785
+ import { Fragment as Fragment10, jsx as jsx34, jsxs as jsxs21 } from "react/jsx-runtime";
1612
1786
  function ReportErrorShell({
1613
1787
  error,
1614
1788
  className,
1615
1789
  title,
1616
1790
  dataTheme
1617
1791
  }) {
1618
- return /* @__PURE__ */ jsx33("main", { className: cn("es-report", className), "aria-label": title ?? "Test report", "data-theme": dataTheme, children: /* @__PURE__ */ jsx33(ReportSchemaError, { error }) });
1792
+ return /* @__PURE__ */ jsx34("main", { className: cn("es-report", className), "aria-label": title ?? "Test report", "data-theme": dataTheme, children: /* @__PURE__ */ jsx34(ReportSchemaError, { error }) });
1619
1793
  }
1620
1794
 
1621
1795
  // src/interactive/ReportInteractive.tsx
@@ -1624,12 +1798,12 @@ import { Monitor, Moon, Sun } from "lucide-react";
1624
1798
  // src/components/ui/switch.tsx
1625
1799
  import "react";
1626
1800
  import { Switch as SwitchPrimitive } from "@base-ui/react/switch";
1627
- import { jsx as jsx34 } from "react/jsx-runtime";
1801
+ import { jsx as jsx35 } from "react/jsx-runtime";
1628
1802
  function Switch({
1629
1803
  className,
1630
1804
  ...props
1631
1805
  }) {
1632
- return /* @__PURE__ */ jsx34(
1806
+ return /* @__PURE__ */ jsx35(
1633
1807
  SwitchPrimitive.Root,
1634
1808
  {
1635
1809
  "data-slot": "switch",
@@ -1638,7 +1812,7 @@ function Switch({
1638
1812
  className
1639
1813
  ),
1640
1814
  ...props,
1641
- children: /* @__PURE__ */ jsx34(
1815
+ children: /* @__PURE__ */ jsx35(
1642
1816
  SwitchPrimitive.Thumb,
1643
1817
  {
1644
1818
  "data-slot": "switch-thumb",
@@ -1654,7 +1828,7 @@ import * as React5 from "react";
1654
1828
  import { ToggleGroup as ToggleGroupPrimitive } from "@base-ui/react/toggle-group";
1655
1829
  import { Toggle as TogglePrimitive } from "@base-ui/react/toggle";
1656
1830
  import { cva as cva3 } from "class-variance-authority";
1657
- import { jsx as jsx35 } from "react/jsx-runtime";
1831
+ import { jsx as jsx36 } from "react/jsx-runtime";
1658
1832
  var toggleItemVariants = cva3(
1659
1833
  "inline-flex items-center justify-center gap-1.5 rounded-md font-medium whitespace-nowrap text-muted-foreground transition-[color,background-color,box-shadow] outline-none hover:text-foreground focus-visible:ring-2 focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50 data-[pressed]:bg-background data-[pressed]:text-foreground data-[pressed]:shadow-sm [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
1660
1834
  {
@@ -1676,13 +1850,13 @@ function ToggleGroup({
1676
1850
  children,
1677
1851
  ...props
1678
1852
  }) {
1679
- return /* @__PURE__ */ jsx35(
1853
+ return /* @__PURE__ */ jsx36(
1680
1854
  ToggleGroupPrimitive,
1681
1855
  {
1682
1856
  "data-slot": "toggle-group",
1683
1857
  className: cn("flex w-fit items-center gap-0.5 rounded-lg bg-muted p-0.5", className),
1684
1858
  ...props,
1685
- children: /* @__PURE__ */ jsx35(ToggleGroupContext.Provider, { value: { size }, children })
1859
+ children: /* @__PURE__ */ jsx36(ToggleGroupContext.Provider, { value: { size }, children })
1686
1860
  }
1687
1861
  );
1688
1862
  }
@@ -1693,7 +1867,7 @@ function ToggleGroupItem({
1693
1867
  ...props
1694
1868
  }) {
1695
1869
  const context = React5.useContext(ToggleGroupContext);
1696
- return /* @__PURE__ */ jsx35(
1870
+ return /* @__PURE__ */ jsx36(
1697
1871
  TogglePrimitive,
1698
1872
  {
1699
1873
  "data-slot": "toggle-group-item",
@@ -1713,9 +1887,9 @@ import { Search } from "lucide-react";
1713
1887
 
1714
1888
  // src/components/ui/input.tsx
1715
1889
  import "react";
1716
- import { jsx as jsx36 } from "react/jsx-runtime";
1890
+ import { jsx as jsx37 } from "react/jsx-runtime";
1717
1891
  function Input({ className, type, ...props }) {
1718
- return /* @__PURE__ */ jsx36(
1892
+ return /* @__PURE__ */ jsx37(
1719
1893
  "input",
1720
1894
  {
1721
1895
  type,
@@ -1732,7 +1906,7 @@ function Input({ className, type, ...props }) {
1732
1906
  }
1733
1907
 
1734
1908
  // src/interactive/ReportSearch.tsx
1735
- import { jsx as jsx37, jsxs as jsxs22 } from "react/jsx-runtime";
1909
+ import { jsx as jsx38, jsxs as jsxs22 } from "react/jsx-runtime";
1736
1910
  var ReportSearch = forwardRef(
1737
1911
  function ReportSearch2(props, ref) {
1738
1912
  const {
@@ -1755,16 +1929,16 @@ var ReportSearch = forwardRef(
1755
1929
  }
1756
1930
  }
1757
1931
  return /* @__PURE__ */ jsxs22("div", { className: cn("es-search flex flex-col gap-1", className), children: [
1758
- /* @__PURE__ */ jsx37("label", { htmlFor: inputId, className: "sr-only", children: "Search" }),
1932
+ /* @__PURE__ */ jsx38("label", { htmlFor: inputId, className: "sr-only", children: "Search" }),
1759
1933
  /* @__PURE__ */ jsxs22("div", { className: "relative w-full sm:w-72", children: [
1760
- /* @__PURE__ */ jsx37(
1934
+ /* @__PURE__ */ jsx38(
1761
1935
  Search,
1762
1936
  {
1763
1937
  "aria-hidden": true,
1764
1938
  className: "pointer-events-none absolute top-1/2 left-2.5 size-4 -translate-y-1/2 text-muted-foreground"
1765
1939
  }
1766
1940
  ),
1767
- /* @__PURE__ */ jsx37(
1941
+ /* @__PURE__ */ jsx38(
1768
1942
  Input,
1769
1943
  {
1770
1944
  ref,
@@ -1822,7 +1996,7 @@ function scrollToScenarioId(scenarioId, options = {}) {
1822
1996
  }
1823
1997
 
1824
1998
  // src/interactive/ReportFailureBanner.tsx
1825
- import { jsx as jsx38, jsxs as jsxs23 } from "react/jsx-runtime";
1999
+ import { jsx as jsx39, jsxs as jsxs23 } from "react/jsx-runtime";
1826
2000
  function ReportFailureBanner({ failures }) {
1827
2001
  const first = failures[0];
1828
2002
  const jumpToFirst = useCallback2(() => {
@@ -1839,12 +2013,12 @@ function ReportFailureBanner({ failures }) {
1839
2013
  "aria-label": "Failure summary",
1840
2014
  children: [
1841
2015
  /* @__PURE__ */ jsxs23("span", { className: "es-failure-banner-text", children: [
1842
- /* @__PURE__ */ jsx38("strong", { children: failures.length }),
2016
+ /* @__PURE__ */ jsx39("strong", { children: failures.length }),
1843
2017
  " ",
1844
2018
  "failure",
1845
2019
  failures.length === 1 ? "" : "s"
1846
2020
  ] }),
1847
- /* @__PURE__ */ jsx38(
2021
+ /* @__PURE__ */ jsx39(
1848
2022
  "button",
1849
2023
  {
1850
2024
  type: "button",
@@ -1861,7 +2035,7 @@ function ReportFailureBanner({ failures }) {
1861
2035
 
1862
2036
  // src/interactive/ReportFreshness.tsx
1863
2037
  import { useEffect, useState as useState2 } from "react";
1864
- import { Fragment as Fragment11, jsx as jsx39, jsxs as jsxs24 } from "react/jsx-runtime";
2038
+ import { Fragment as Fragment11, jsx as jsx40, jsxs as jsxs24 } from "react/jsx-runtime";
1865
2039
  function ReportFreshness({ lastRunMs, ciUrl, staleAfterDays, nowMs }) {
1866
2040
  const [now, setNow] = useState2(nowMs);
1867
2041
  useEffect(() => {
@@ -1869,7 +2043,7 @@ function ReportFreshness({ lastRunMs, ciUrl, staleAfterDays, nowMs }) {
1869
2043
  }, [nowMs]);
1870
2044
  if (lastRunMs === void 0 || now === void 0) return null;
1871
2045
  const age = formatRelativeAge(lastRunMs, now);
1872
- const runLink = ciUrl ? /* @__PURE__ */ jsx39(
2046
+ const runLink = ciUrl ? /* @__PURE__ */ jsx40(
1873
2047
  "a",
1874
2048
  {
1875
2049
  href: ciUrl,
@@ -1903,13 +2077,13 @@ function ReportFreshness({ lastRunMs, ciUrl, staleAfterDays, nowMs }) {
1903
2077
  }
1904
2078
 
1905
2079
  // src/interactive/ReportLastRunDelta.tsx
1906
- import { Fragment as Fragment12, jsx as jsx40, jsxs as jsxs25 } from "react/jsx-runtime";
2080
+ import { Fragment as Fragment12, jsx as jsx41, jsxs as jsxs25 } from "react/jsx-runtime";
1907
2081
  var MAX_LINKS = 5;
1908
2082
  function ScenarioLinks({ scenarios, tone }) {
1909
2083
  return /* @__PURE__ */ jsxs25(Fragment12, { children: [
1910
2084
  scenarios.slice(0, MAX_LINKS).map((s, i) => /* @__PURE__ */ jsxs25("span", { children: [
1911
2085
  i > 0 ? ", " : "",
1912
- /* @__PURE__ */ jsx40("a", { href: `#${s.id}`, className: cn("underline underline-offset-2 hover:no-underline", tone), children: s.title })
2086
+ /* @__PURE__ */ jsx41("a", { href: `#${s.id}`, className: cn("underline underline-offset-2 hover:no-underline", tone), children: s.title })
1913
2087
  ] }, s.id)),
1914
2088
  scenarios.length > MAX_LINKS ? /* @__PURE__ */ jsxs25("span", { children: [
1915
2089
  " and ",
@@ -1928,20 +2102,20 @@ function ReportLastRunDelta({
1928
2102
  if (!delta) return null;
1929
2103
  const { newlyFailing, newlyPassing, added } = delta;
1930
2104
  if (newlyFailing.length === 0 && newlyPassing.length === 0 && added.length === 0) {
1931
- return /* @__PURE__ */ jsx40("p", { className: "text-xs text-muted-foreground", "data-testid": "es-last-run-delta", children: "Since last run: no behavior changes." });
2105
+ return /* @__PURE__ */ jsx41("p", { className: "text-xs text-muted-foreground", "data-testid": "es-last-run-delta", children: "Since last run: no behavior changes." });
1932
2106
  }
1933
2107
  return /* @__PURE__ */ jsxs25("p", { className: "text-xs text-muted-foreground", "data-testid": "es-last-run-delta", children: [
1934
- /* @__PURE__ */ jsx40("span", { className: "font-medium text-foreground", children: "Since last run:" }),
2108
+ /* @__PURE__ */ jsx41("span", { className: "font-medium text-foreground", children: "Since last run:" }),
1935
2109
  newlyFailing.length > 0 ? /* @__PURE__ */ jsxs25("span", { className: "ml-2 text-fail", children: [
1936
2110
  newlyFailing.length,
1937
2111
  " newly failing (",
1938
- /* @__PURE__ */ jsx40(ScenarioLinks, { scenarios: newlyFailing, tone: "text-fail" }),
2112
+ /* @__PURE__ */ jsx41(ScenarioLinks, { scenarios: newlyFailing, tone: "text-fail" }),
1939
2113
  ")"
1940
2114
  ] }) : null,
1941
2115
  newlyPassing.length > 0 ? /* @__PURE__ */ jsxs25("span", { className: "ml-2 text-pass", children: [
1942
2116
  newlyPassing.length,
1943
2117
  " fixed (",
1944
- /* @__PURE__ */ jsx40(ScenarioLinks, { scenarios: newlyPassing, tone: "text-pass" }),
2118
+ /* @__PURE__ */ jsx41(ScenarioLinks, { scenarios: newlyPassing, tone: "text-pass" }),
1945
2119
  ")"
1946
2120
  ] }) : null,
1947
2121
  added.length > 0 ? /* @__PURE__ */ jsxs25("span", { className: "ml-2", children: [
@@ -2008,7 +2182,7 @@ function Button({
2008
2182
  }
2009
2183
 
2010
2184
  // src/interactive/ReportShortcutsHelp.tsx
2011
- import { jsx as jsx41, jsxs as jsxs26 } from "react/jsx-runtime";
2185
+ import { jsx as jsx42, jsxs as jsxs26 } from "react/jsx-runtime";
2012
2186
  var SHORTCUTS = [
2013
2187
  { keys: "/", description: "Focus search" },
2014
2188
  { keys: "f", description: "Jump to next failure" },
@@ -2020,9 +2194,9 @@ var SHORTCUTS = [
2020
2194
  ];
2021
2195
  function Keys({ keys }) {
2022
2196
  const parts = keys.split(" ");
2023
- return /* @__PURE__ */ jsx41("span", { className: "inline-flex items-center gap-1", children: parts.map((k, i) => /* @__PURE__ */ jsxs26("span", { className: "inline-flex items-center gap-1", children: [
2024
- i > 0 ? /* @__PURE__ */ jsx41("span", { className: "text-xs text-muted-foreground", children: "+" }) : null,
2025
- /* @__PURE__ */ jsx41("kbd", { className: "inline-flex h-6 min-w-6 items-center justify-center rounded border border-border bg-muted px-1.5 font-mono text-xs font-medium text-muted-foreground", children: k })
2197
+ return /* @__PURE__ */ jsx42("span", { className: "inline-flex items-center gap-1", children: parts.map((k, i) => /* @__PURE__ */ jsxs26("span", { className: "inline-flex items-center gap-1", children: [
2198
+ i > 0 ? /* @__PURE__ */ jsx42("span", { className: "text-xs text-muted-foreground", children: "+" }) : null,
2199
+ /* @__PURE__ */ jsx42("kbd", { className: "inline-flex h-6 min-w-6 items-center justify-center rounded border border-border bg-muted px-1.5 font-mono text-xs font-medium text-muted-foreground", children: k })
2026
2200
  ] }, k)) });
2027
2201
  }
2028
2202
  function ReportShortcutsHelp({ open, onClose }) {
@@ -2041,12 +2215,12 @@ function ReportShortcutsHelp({ open, onClose }) {
2041
2215
  "aria-label": "Keyboard shortcuts",
2042
2216
  onClose,
2043
2217
  children: [
2044
- /* @__PURE__ */ jsx41("h2", { className: "text-base font-semibold", children: "Keyboard shortcuts" }),
2045
- /* @__PURE__ */ jsx41("dl", { className: "mt-4 grid grid-cols-[auto_1fr] items-center gap-x-4 gap-y-2.5", children: SHORTCUTS.map((s) => /* @__PURE__ */ jsxs26("div", { className: "col-span-2 grid grid-cols-subgrid items-center", children: [
2046
- /* @__PURE__ */ jsx41("dt", { className: "justify-self-start", children: /* @__PURE__ */ jsx41(Keys, { keys: s.keys }) }),
2047
- /* @__PURE__ */ jsx41("dd", { className: "text-sm text-muted-foreground", children: s.description })
2218
+ /* @__PURE__ */ jsx42("h2", { className: "text-base font-semibold", children: "Keyboard shortcuts" }),
2219
+ /* @__PURE__ */ jsx42("dl", { className: "mt-4 grid grid-cols-[auto_1fr] items-center gap-x-4 gap-y-2.5", children: SHORTCUTS.map((s) => /* @__PURE__ */ jsxs26("div", { className: "col-span-2 grid grid-cols-subgrid items-center", children: [
2220
+ /* @__PURE__ */ jsx42("dt", { className: "justify-self-start", children: /* @__PURE__ */ jsx42(Keys, { keys: s.keys }) }),
2221
+ /* @__PURE__ */ jsx42("dd", { className: "text-sm text-muted-foreground", children: s.description })
2048
2222
  ] }, s.keys)) }),
2049
- /* @__PURE__ */ jsx41("form", { method: "dialog", className: "mt-6", children: /* @__PURE__ */ jsx41(Button, { type: "submit", variant: "outline", size: "sm", children: "Close" }) })
2223
+ /* @__PURE__ */ jsx42("form", { method: "dialog", className: "mt-6", children: /* @__PURE__ */ jsx42(Button, { type: "submit", variant: "outline", size: "sm", children: "Close" }) })
2050
2224
  ]
2051
2225
  }
2052
2226
  );
@@ -2247,7 +2421,7 @@ function failuresFirst(report) {
2247
2421
 
2248
2422
  // src/interactive/ReportFilters.tsx
2249
2423
  import { useState as useState3 } from "react";
2250
- import { jsx as jsx42, jsxs as jsxs27 } from "react/jsx-runtime";
2424
+ import { jsx as jsx43, jsxs as jsxs27 } from "react/jsx-runtime";
2251
2425
  var TAG_LIMIT = 12;
2252
2426
  function ReportFilters({
2253
2427
  statuses,
@@ -2262,7 +2436,7 @@ function ReportFilters({
2262
2436
  const tagsCollapsed = tags.length > TAG_LIMIT && !showAllTags;
2263
2437
  const visibleTags = tagsCollapsed ? tags.slice(0, TAG_LIMIT) : tags;
2264
2438
  return /* @__PURE__ */ jsxs27("div", { className: "flex flex-col gap-2", children: [
2265
- statuses.length > 0 ? /* @__PURE__ */ jsx42("div", { role: "group", "aria-label": "Filter by status", className: "flex flex-wrap gap-1", children: statuses.map((opt) => {
2439
+ statuses.length > 0 ? /* @__PURE__ */ jsx43("div", { role: "group", "aria-label": "Filter by status", className: "flex flex-wrap gap-1", children: statuses.map((opt) => {
2266
2440
  const active = status === opt.key;
2267
2441
  return /* @__PURE__ */ jsxs27(
2268
2442
  "button",
@@ -2276,7 +2450,7 @@ function ReportFilters({
2276
2450
  ),
2277
2451
  children: [
2278
2452
  opt.label,
2279
- /* @__PURE__ */ jsx42("span", { className: "ml-1 font-mono opacity-70", children: opt.count })
2453
+ /* @__PURE__ */ jsx43("span", { className: "ml-1 font-mono opacity-70", children: opt.count })
2280
2454
  ]
2281
2455
  },
2282
2456
  opt.key
@@ -2285,14 +2459,14 @@ function ReportFilters({
2285
2459
  tags.length > 0 ? /* @__PURE__ */ jsxs27("ul", { "aria-label": "Filter by tag", className: "flex flex-wrap items-center gap-1.5", children: [
2286
2460
  visibleTags.map((tag) => {
2287
2461
  const active = activeTags.includes(tag);
2288
- return /* @__PURE__ */ jsx42("li", { children: /* @__PURE__ */ jsx42(
2462
+ return /* @__PURE__ */ jsx43("li", { children: /* @__PURE__ */ jsx43(
2289
2463
  "button",
2290
2464
  {
2291
2465
  type: "button",
2292
2466
  "aria-pressed": active,
2293
2467
  onClick: () => onToggleTag(tag),
2294
2468
  className: "cursor-pointer",
2295
- children: /* @__PURE__ */ jsx42(
2469
+ children: /* @__PURE__ */ jsx43(
2296
2470
  Badge,
2297
2471
  {
2298
2472
  variant: "tag",
@@ -2305,7 +2479,7 @@ function ReportFilters({
2305
2479
  }
2306
2480
  ) }, tag);
2307
2481
  }),
2308
- tags.length > TAG_LIMIT ? /* @__PURE__ */ jsx42("li", { children: /* @__PURE__ */ jsx42(
2482
+ tags.length > TAG_LIMIT ? /* @__PURE__ */ jsx43("li", { children: /* @__PURE__ */ jsx43(
2309
2483
  "button",
2310
2484
  {
2311
2485
  type: "button",
@@ -2321,7 +2495,7 @@ function ReportFilters({
2321
2495
 
2322
2496
  // src/interactive/ReportToc.tsx
2323
2497
  import { useEffect as useEffect5, useMemo as useMemo2, useState as useState4 } from "react";
2324
- import { jsx as jsx43, jsxs as jsxs28 } from "react/jsx-runtime";
2498
+ import { jsx as jsx44, jsxs as jsxs28 } from "react/jsx-runtime";
2325
2499
  var DOT = {
2326
2500
  passed: "bg-pass",
2327
2501
  failed: "bg-fail",
@@ -2350,11 +2524,11 @@ function TocContent({ onNavigate }) {
2350
2524
  return () => observer.disconnect();
2351
2525
  }, [scenarioIds]);
2352
2526
  if (report.features.length === 0) return null;
2353
- return /* @__PURE__ */ jsx43("ul", { className: "flex list-none flex-col gap-4 pl-0", children: report.features.map((feature) => /* @__PURE__ */ jsxs28("li", { children: [
2354
- /* @__PURE__ */ jsx43("p", { className: "mb-1.5 font-semibold leading-snug text-foreground", children: feature.title }),
2355
- /* @__PURE__ */ jsx43("ul", { className: "flex list-none flex-col gap-0.5 pl-0", children: feature.scenarios.map((scenario) => {
2527
+ return /* @__PURE__ */ jsx44("ul", { className: "flex list-none flex-col gap-4 pl-0", children: report.features.map((feature) => /* @__PURE__ */ jsxs28("li", { children: [
2528
+ /* @__PURE__ */ jsx44("p", { className: "mb-1.5 font-semibold leading-snug text-foreground", children: feature.title }),
2529
+ /* @__PURE__ */ jsx44("ul", { className: "flex list-none flex-col gap-0.5 pl-0", children: feature.scenarios.map((scenario) => {
2356
2530
  const active = activeId === scenario.id;
2357
- return /* @__PURE__ */ jsx43("li", { children: /* @__PURE__ */ jsxs28(
2531
+ return /* @__PURE__ */ jsx44("li", { children: /* @__PURE__ */ jsxs28(
2358
2532
  "a",
2359
2533
  {
2360
2534
  href: `#${scenario.id}`,
@@ -2369,14 +2543,14 @@ function TocContent({ onNavigate }) {
2369
2543
  active ? "border-primary font-medium text-foreground" : "border-border text-muted-foreground"
2370
2544
  ),
2371
2545
  children: [
2372
- /* @__PURE__ */ jsx43(
2546
+ /* @__PURE__ */ jsx44(
2373
2547
  "span",
2374
2548
  {
2375
2549
  "aria-hidden": true,
2376
2550
  className: cn("mt-1 size-1.5 shrink-0 rounded-full", DOT[scenario.status])
2377
2551
  }
2378
2552
  ),
2379
- /* @__PURE__ */ jsx43("span", { className: "break-words", children: scenario.title })
2553
+ /* @__PURE__ */ jsx44("span", { className: "break-words", children: scenario.title })
2380
2554
  ]
2381
2555
  }
2382
2556
  ) }, scenario.id);
@@ -2392,8 +2566,8 @@ function ReportToc() {
2392
2566
  "aria-label": "Table of contents",
2393
2567
  className: "sticky top-4 hidden h-fit w-64 shrink-0 self-start text-xs lg:block",
2394
2568
  children: [
2395
- /* @__PURE__ */ jsx43("p", { className: "mb-3 text-xs font-semibold uppercase tracking-wide text-muted-foreground", children: "Contents" }),
2396
- /* @__PURE__ */ jsx43(TocContent, {})
2569
+ /* @__PURE__ */ jsx44("p", { className: "mb-3 text-xs font-semibold uppercase tracking-wide text-muted-foreground", children: "Contents" }),
2570
+ /* @__PURE__ */ jsx44(TocContent, {})
2397
2571
  ]
2398
2572
  }
2399
2573
  );
@@ -2403,31 +2577,31 @@ function ReportToc() {
2403
2577
  import { useState as useState5 } from "react";
2404
2578
  import { Dialog as DialogPrimitive } from "@base-ui/react/dialog";
2405
2579
  import { ListIcon, XIcon } from "lucide-react";
2406
- import { jsx as jsx44, jsxs as jsxs29 } from "react/jsx-runtime";
2580
+ import { jsx as jsx45, jsxs as jsxs29 } from "react/jsx-runtime";
2407
2581
  function ReportTocDrawer() {
2408
2582
  const report = useReport();
2409
2583
  const [open, setOpen] = useState5(false);
2410
2584
  if (report.features.length === 0) return null;
2411
2585
  return /* @__PURE__ */ jsxs29(DialogPrimitive.Root, { open, onOpenChange: setOpen, children: [
2412
2586
  /* @__PURE__ */ jsxs29(DialogPrimitive.Trigger, { className: "flex cursor-pointer items-center gap-1 rounded-md border border-border px-2 py-1 text-xs text-muted-foreground hover:bg-muted hover:text-foreground lg:hidden [&_svg]:size-3.5", children: [
2413
- /* @__PURE__ */ jsx44(ListIcon, { "aria-hidden": true }),
2587
+ /* @__PURE__ */ jsx45(ListIcon, { "aria-hidden": true }),
2414
2588
  " Contents"
2415
2589
  ] }),
2416
2590
  /* @__PURE__ */ jsxs29(DialogPrimitive.Portal, { children: [
2417
- /* @__PURE__ */ jsx44(DialogPrimitive.Backdrop, { className: "fixed inset-0 z-50 bg-black/50 transition-opacity duration-200 data-[ending-style]:opacity-0 data-[starting-style]:opacity-0" }),
2591
+ /* @__PURE__ */ jsx45(DialogPrimitive.Backdrop, { className: "fixed inset-0 z-50 bg-black/50 transition-opacity duration-200 data-[ending-style]:opacity-0 data-[starting-style]:opacity-0" }),
2418
2592
  /* @__PURE__ */ jsxs29(DialogPrimitive.Popup, { className: "fixed inset-y-0 left-0 z-50 flex w-72 max-w-[80vw] flex-col gap-3 overflow-y-auto border-r border-border bg-background p-4 font-sans text-xs shadow-lg outline-none transition-transform duration-200 data-[ending-style]:-translate-x-full data-[starting-style]:-translate-x-full", children: [
2419
2593
  /* @__PURE__ */ jsxs29("div", { className: "flex items-center justify-between", children: [
2420
- /* @__PURE__ */ jsx44(DialogPrimitive.Title, { className: "text-xs font-semibold tracking-wide text-muted-foreground uppercase", children: "Contents" }),
2421
- /* @__PURE__ */ jsx44(
2594
+ /* @__PURE__ */ jsx45(DialogPrimitive.Title, { className: "text-xs font-semibold tracking-wide text-muted-foreground uppercase", children: "Contents" }),
2595
+ /* @__PURE__ */ jsx45(
2422
2596
  DialogPrimitive.Close,
2423
2597
  {
2424
2598
  "aria-label": "Close contents",
2425
2599
  className: "cursor-pointer rounded p-1 text-muted-foreground hover:bg-muted hover:text-foreground [&_svg]:size-4",
2426
- children: /* @__PURE__ */ jsx44(XIcon, { "aria-hidden": true })
2600
+ children: /* @__PURE__ */ jsx45(XIcon, { "aria-hidden": true })
2427
2601
  }
2428
2602
  )
2429
2603
  ] }),
2430
- /* @__PURE__ */ jsx44(TocContent, { onNavigate: () => setOpen(false) })
2604
+ /* @__PURE__ */ jsx45(TocContent, { onNavigate: () => setOpen(false) })
2431
2605
  ] })
2432
2606
  ] })
2433
2607
  ] });
@@ -2482,14 +2656,14 @@ function useTheme() {
2482
2656
  }
2483
2657
 
2484
2658
  // src/interactive/ReportInteractive.tsx
2485
- import { Fragment as Fragment13, jsx as jsx45, jsxs as jsxs30 } from "react/jsx-runtime";
2659
+ import { Fragment as Fragment13, jsx as jsx46, jsxs as jsxs30 } from "react/jsx-runtime";
2486
2660
  function ReportInteractive(props) {
2487
2661
  const { report, className, title, dataTheme } = props;
2488
2662
  const result = unwrapReport(report);
2489
2663
  if (!result.ok) {
2490
- return /* @__PURE__ */ jsx45(ReportErrorShell, { error: result.error, className, title, dataTheme });
2664
+ return /* @__PURE__ */ jsx46(ReportErrorShell, { error: result.error, className, title, dataTheme });
2491
2665
  }
2492
- return /* @__PURE__ */ jsx45(ReportInteractiveView, { ...props, report: result.data });
2666
+ return /* @__PURE__ */ jsx46(ReportInteractiveView, { ...props, report: result.data });
2493
2667
  }
2494
2668
  var THEME_OPTIONS = [
2495
2669
  { value: "light", label: "Light", Icon: Sun },
@@ -2497,7 +2671,7 @@ var THEME_OPTIONS = [
2497
2671
  { value: "dark", label: "Dark", Icon: Moon }
2498
2672
  ];
2499
2673
  function ThemeSegment({ pref, onPref }) {
2500
- return /* @__PURE__ */ jsx45(
2674
+ return /* @__PURE__ */ jsx46(
2501
2675
  ToggleGroup,
2502
2676
  {
2503
2677
  size: "sm",
@@ -2507,7 +2681,7 @@ function ThemeSegment({ pref, onPref }) {
2507
2681
  if (next) onPref(next);
2508
2682
  },
2509
2683
  "aria-label": "Color theme",
2510
- children: THEME_OPTIONS.map(({ value, label, Icon }) => /* @__PURE__ */ jsx45(ToggleGroupItem, { value, "aria-label": label, title: label, className: "px-2", children: /* @__PURE__ */ jsx45(Icon, {}) }, value))
2684
+ children: THEME_OPTIONS.map(({ value, label, Icon }) => /* @__PURE__ */ jsx46(ToggleGroupItem, { value, "aria-label": label, title: label, className: "px-2", children: /* @__PURE__ */ jsx46(Icon, {}) }, value))
2511
2685
  }
2512
2686
  );
2513
2687
  }
@@ -2629,7 +2803,7 @@ function ReportInteractiveView({
2629
2803
  const totalScenarios = report.summary.total;
2630
2804
  const matchedScenarios = filtered.summary.total;
2631
2805
  const showToc = !hideToc && totalScenarios > 3;
2632
- return /* @__PURE__ */ jsx45(CollapseProvider, { value: collapse.api, children: /* @__PURE__ */ jsx45(ScenarioActionsProvider, { value: scenarioActions, children: /* @__PURE__ */ jsx45(ScenarioHistoryProvider, { value: scenarioHistory ?? null, children: /* @__PURE__ */ jsx45(
2806
+ return /* @__PURE__ */ jsx46(CollapseProvider, { value: collapse.api, children: /* @__PURE__ */ jsx46(ScenarioActionsProvider, { value: scenarioActions, children: /* @__PURE__ */ jsx46(ScenarioHistoryProvider, { value: scenarioHistory ?? null, children: /* @__PURE__ */ jsx46(
2633
2807
  ReportRoot,
2634
2808
  {
2635
2809
  report: filtered,
@@ -2654,9 +2828,9 @@ function ReportInteractiveView({
2654
2828
  hideHeader ? "justify-end" : "justify-between"
2655
2829
  ),
2656
2830
  children: [
2657
- hideHeader ? null : /* @__PURE__ */ jsx45("h1", { className: "min-w-0", children: title ?? "Story Report" }),
2831
+ hideHeader ? null : /* @__PURE__ */ jsx46("h1", { className: "min-w-0", children: title ?? "Story Report" }),
2658
2832
  /* @__PURE__ */ jsxs30("div", { className: "flex items-center gap-2", children: [
2659
- /* @__PURE__ */ jsx45(
2833
+ /* @__PURE__ */ jsx46(
2660
2834
  ReportSearch,
2661
2835
  {
2662
2836
  ref: searchRef,
@@ -2666,16 +2840,16 @@ function ReportInteractiveView({
2666
2840
  totalCount: totalScenarios
2667
2841
  }
2668
2842
  ),
2669
- /* @__PURE__ */ jsx45(ThemeSegment, { pref: themePref, onPref: setThemePref })
2843
+ /* @__PURE__ */ jsx46(ThemeSegment, { pref: themePref, onPref: setThemePref })
2670
2844
  ] })
2671
2845
  ]
2672
2846
  }
2673
2847
  ),
2674
2848
  hideHeader ? null : /* @__PURE__ */ jsxs30(Fragment13, { children: [
2675
- /* @__PURE__ */ jsx45(ReportSummary, {}),
2676
- /* @__PURE__ */ jsx45(ReportMeta, {})
2849
+ /* @__PURE__ */ jsx46(ReportSummary, {}),
2850
+ /* @__PURE__ */ jsx46(ReportMeta, {})
2677
2851
  ] }),
2678
- /* @__PURE__ */ jsx45(
2852
+ /* @__PURE__ */ jsx46(
2679
2853
  ReportFreshness,
2680
2854
  {
2681
2855
  lastRunMs: reportLastRunMs(report),
@@ -2683,8 +2857,8 @@ function ReportInteractiveView({
2683
2857
  staleAfterDays
2684
2858
  }
2685
2859
  ),
2686
- /* @__PURE__ */ jsx45(ReportLastRunDelta, { history: scenarioHistory, report }),
2687
- /* @__PURE__ */ jsx45(
2860
+ /* @__PURE__ */ jsx46(ReportLastRunDelta, { history: scenarioHistory, report }),
2861
+ /* @__PURE__ */ jsx46(
2688
2862
  ReportFilters,
2689
2863
  {
2690
2864
  statuses: statusOptions,
@@ -2696,13 +2870,13 @@ function ReportInteractiveView({
2696
2870
  }
2697
2871
  ),
2698
2872
  /* @__PURE__ */ jsxs30("div", { className: "flex flex-wrap items-center gap-x-6 gap-y-2 border-t border-border/60 pt-3", children: [
2699
- showToc ? /* @__PURE__ */ jsx45(ReportTocDrawer, {}) : null,
2873
+ showToc ? /* @__PURE__ */ jsx46(ReportTocDrawer, {}) : null,
2700
2874
  /* @__PURE__ */ jsxs30("div", { className: "flex items-center gap-2", children: [
2701
- /* @__PURE__ */ jsx45(Switch, { id: expandId, checked: expandedAll, onCheckedChange: setExpanded }),
2702
- /* @__PURE__ */ jsx45("label", { htmlFor: expandId, className: "cursor-pointer text-sm text-muted-foreground select-none", children: "Expand all" })
2875
+ /* @__PURE__ */ jsx46(Switch, { id: expandId, checked: expandedAll, onCheckedChange: setExpanded }),
2876
+ /* @__PURE__ */ jsx46("label", { htmlFor: expandId, className: "cursor-pointer text-sm text-muted-foreground select-none", children: "Expand all" })
2703
2877
  ] }),
2704
2878
  /* @__PURE__ */ jsxs30("div", { className: "flex items-center gap-2", children: [
2705
- /* @__PURE__ */ jsx45(
2879
+ /* @__PURE__ */ jsx46(
2706
2880
  Switch,
2707
2881
  {
2708
2882
  id: docsId,
@@ -2710,16 +2884,16 @@ function ReportInteractiveView({
2710
2884
  onCheckedChange: (checked) => setDetail(checked ? "full" : "minimal")
2711
2885
  }
2712
2886
  ),
2713
- /* @__PURE__ */ jsx45("label", { htmlFor: docsId, className: "cursor-pointer text-sm text-muted-foreground select-none", children: "Show documentation" })
2887
+ /* @__PURE__ */ jsx46("label", { htmlFor: docsId, className: "cursor-pointer text-sm text-muted-foreground select-none", children: "Show documentation" })
2714
2888
  ] })
2715
2889
  ] })
2716
2890
  ] }),
2717
- /* @__PURE__ */ jsx45(ReportFailureBanner, { failures }),
2891
+ /* @__PURE__ */ jsx46(ReportFailureBanner, { failures }),
2718
2892
  hasContent ? showToc ? /* @__PURE__ */ jsxs30("div", { className: "flex gap-6", children: [
2719
- /* @__PURE__ */ jsx45(ReportToc, {}),
2720
- /* @__PURE__ */ jsx45("div", { className: "flex min-w-0 flex-1 flex-col gap-4", children: /* @__PURE__ */ jsx45(ReportFeatureList, {}) })
2721
- ] }) : /* @__PURE__ */ jsx45("div", { className: "flex flex-col gap-4", children: /* @__PURE__ */ jsx45(ReportFeatureList, {}) }) : /* @__PURE__ */ jsx45(ReportEmpty, { message: query ? "No scenarios match the search." : void 0 }),
2722
- /* @__PURE__ */ jsx45(
2893
+ /* @__PURE__ */ jsx46(ReportToc, {}),
2894
+ /* @__PURE__ */ jsx46("div", { className: "flex min-w-0 flex-1 flex-col gap-4", children: /* @__PURE__ */ jsx46(ReportFeatureList, {}) })
2895
+ ] }) : /* @__PURE__ */ jsx46("div", { className: "flex flex-col gap-4", children: /* @__PURE__ */ jsx46(ReportFeatureList, {}) }) : /* @__PURE__ */ jsx46(ReportEmpty, { message: query ? "No scenarios match the search." : void 0 }),
2896
+ /* @__PURE__ */ jsx46(
2723
2897
  "button",
2724
2898
  {
2725
2899
  type: "button",
@@ -2730,8 +2904,8 @@ function ReportInteractiveView({
2730
2904
  children: "?"
2731
2905
  }
2732
2906
  ),
2733
- /* @__PURE__ */ jsx45(ReportShortcutsHelp, { open: helpOpen, onClose: () => setHelpOpen(false) }),
2734
- toast ? /* @__PURE__ */ jsx45(
2907
+ /* @__PURE__ */ jsx46(ReportShortcutsHelp, { open: helpOpen, onClose: () => setHelpOpen(false) }),
2908
+ toast ? /* @__PURE__ */ jsx46(
2735
2909
  "div",
2736
2910
  {
2737
2911
  role: "status",
@@ -2755,7 +2929,7 @@ import { createElement, useEffect as useEffect8, useState as useState9 } from "r
2755
2929
 
2756
2930
  // src/components/doc/MermaidView.tsx
2757
2931
  import { useEffect as useEffect7, useRef as useRef4, useState as useState8 } from "react";
2758
- import { jsx as jsx46, jsxs as jsxs31 } from "react/jsx-runtime";
2932
+ import { jsx as jsx47, jsxs as jsxs31 } from "react/jsx-runtime";
2759
2933
  function prefersDark(el) {
2760
2934
  const themed = el?.closest("[data-theme]");
2761
2935
  if (themed?.dataset.theme === "dark") return true;
@@ -2793,8 +2967,8 @@ function MermaidView({ entry, load }) {
2793
2967
  }, [entry.code, load]);
2794
2968
  if (svg) {
2795
2969
  return /* @__PURE__ */ jsxs31("figure", { ref, className: "my-3", children: [
2796
- entry.title ? /* @__PURE__ */ jsx46("figcaption", { className: "mb-1.5 text-xs font-medium text-muted-foreground", children: entry.title }) : null,
2797
- /* @__PURE__ */ jsx46(
2970
+ entry.title ? /* @__PURE__ */ jsx47("figcaption", { className: "mb-1.5 text-xs font-medium text-muted-foreground", children: entry.title }) : null,
2971
+ /* @__PURE__ */ jsx47(
2798
2972
  "div",
2799
2973
  {
2800
2974
  role: "img",
@@ -2805,11 +2979,11 @@ function MermaidView({ entry, load }) {
2805
2979
  )
2806
2980
  ] });
2807
2981
  }
2808
- return /* @__PURE__ */ jsx46(MermaidSource, { entry, ref });
2982
+ return /* @__PURE__ */ jsx47(MermaidSource, { entry, ref });
2809
2983
  }
2810
2984
 
2811
2985
  // src/interactive/island-renderers.tsx
2812
- import { jsx as jsx47 } from "react/jsx-runtime";
2986
+ import { jsx as jsx48 } from "react/jsx-runtime";
2813
2987
  var HLJS_ESM = "https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/es/highlight.min.js";
2814
2988
  var MERMAID_ESM = "https://cdn.jsdelivr.net/npm/mermaid@10/dist/mermaid.esm.min.mjs";
2815
2989
  function cachedCdnModule(url) {
@@ -2843,13 +3017,13 @@ function CdnHighlightedCode({ entry }) {
2843
3017
  cancelled = true;
2844
3018
  };
2845
3019
  }, [entry.content, entry.lang]);
2846
- return /* @__PURE__ */ jsx47(CodeFigure, { label: entry.label, children: html !== null ? /* @__PURE__ */ jsx47(
3020
+ return /* @__PURE__ */ jsx48(CodeFigure, { label: entry.label, children: html !== null ? /* @__PURE__ */ jsx48(
2847
3021
  "code",
2848
3022
  {
2849
3023
  className: cn("hljs font-mono text-xs", entry.lang && `language-${entry.lang}`),
2850
3024
  dangerouslySetInnerHTML: { __html: html }
2851
3025
  }
2852
- ) : /* @__PURE__ */ jsx47("code", { className: cn("font-mono text-xs", entry.lang && `language-${entry.lang}`), children: entry.content }) });
3026
+ ) : /* @__PURE__ */ jsx48("code", { className: cn("font-mono text-xs", entry.lang && `language-${entry.lang}`), children: entry.content }) });
2853
3027
  }
2854
3028
  function buildIslandRenderers(opts) {
2855
3029
  const renderers = {};
@@ -2863,7 +3037,7 @@ function buildIslandRenderers(opts) {
2863
3037
  }
2864
3038
 
2865
3039
  // src/interactive/ReportInteractiveIsland.tsx
2866
- import { jsx as jsx48 } from "react/jsx-runtime";
3040
+ import { jsx as jsx49 } from "react/jsx-runtime";
2867
3041
  function ReportInteractiveIsland({
2868
3042
  report,
2869
3043
  title,
@@ -2877,7 +3051,7 @@ function ReportInteractiveIsland({
2877
3051
  () => buildIslandRenderers({ syntaxHighlighting, mermaid }),
2878
3052
  [syntaxHighlighting, mermaid]
2879
3053
  );
2880
- return /* @__PURE__ */ jsx48(
3054
+ return /* @__PURE__ */ jsx49(
2881
3055
  ReportInteractive,
2882
3056
  {
2883
3057
  report,