executable-stories-react 0.6.0 → 0.7.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.
@@ -264,7 +264,7 @@ function DocLink({ entry }) {
264
264
  // src/components/doc/DocSection.tsx
265
265
  var import_marked = require("marked");
266
266
 
267
- // src/lib/url.ts
267
+ // ../executable-stories-core/dist/utils/url.js
268
268
  function safeUrl(value) {
269
269
  if (!value) return void 0;
270
270
  const trimmed = value.trim();
@@ -559,18 +559,101 @@ function ReportStepItem({ step }) {
559
559
  );
560
560
  }
561
561
 
562
- // src/components/ReportAttachments.tsx
562
+ // ../executable-stories-core/dist/storyboard.js
563
+ function findScreenshot(entries) {
564
+ for (const entry of entries) {
565
+ if (entry.kind === "screenshot") return entry;
566
+ if (entry.children) {
567
+ const nested = findScreenshot(entry.children);
568
+ if (nested) return nested;
569
+ }
570
+ }
571
+ return void 0;
572
+ }
573
+ function extractStoryboardFrames(scenario) {
574
+ const frames = [];
575
+ for (const step of scenario.steps) {
576
+ const shot = findScreenshot(step.docEntries);
577
+ if (!shot) continue;
578
+ frames.push({
579
+ stepId: step.id,
580
+ stepIndex: step.index,
581
+ keyword: step.keyword,
582
+ text: step.text,
583
+ status: step.status,
584
+ path: shot.path,
585
+ ...shot.alt !== void 0 && { alt: shot.alt }
586
+ });
587
+ }
588
+ return frames;
589
+ }
590
+
591
+ // src/components/ReportStoryboard.tsx
563
592
  var import_jsx_runtime18 = require("react/jsx-runtime");
593
+ var FRAME_GLYPH = {
594
+ passed: "\u2713",
595
+ failed: "\u2717",
596
+ skipped: "\u25CB",
597
+ pending: "\u25CB"
598
+ };
599
+ var FRAME_GLYPH_COLOR = {
600
+ passed: "text-pass",
601
+ failed: "text-fail",
602
+ skipped: "text-skip",
603
+ pending: "text-pend"
604
+ };
605
+ function ReportStoryboard({ scenario }) {
606
+ const frames = extractStoryboardFrames(scenario);
607
+ if (frames.length < 2) return null;
608
+ return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("section", { "data-slot": "storyboard", "aria-label": "Storyboard", className: "mb-3", children: [
609
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("h4", { className: "mb-1.5 text-xs font-semibold tracking-wide text-muted-foreground uppercase", children: "Storyboard" }),
610
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("ol", { className: "flex gap-3 overflow-x-auto pb-2", children: frames.map((frame) => /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(StoryboardFrameItem, { frame }, frame.stepId)) })
611
+ ] });
612
+ }
613
+ function StoryboardFrameItem({ frame }) {
614
+ const src = isLocalFsPath(frame.path) ? void 0 : safeImageUrl(frame.path);
615
+ const label = `${frame.keyword} ${frame.text}`;
616
+ return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("li", { className: "w-40 shrink-0", children: [
617
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
618
+ "a",
619
+ {
620
+ href: `#${frame.stepId}`,
621
+ "aria-label": `Jump to step: ${label}`,
622
+ className: "block overflow-hidden rounded-md border border-border transition-colors hover:border-ring",
623
+ children: src ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
624
+ "img",
625
+ {
626
+ src,
627
+ alt: frame.alt ?? label,
628
+ loading: "lazy",
629
+ className: "h-24 w-full bg-muted object-cover object-top"
630
+ }
631
+ ) : /* @__PURE__ */ (0, import_jsx_runtime18.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" })
632
+ }
633
+ ),
634
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("p", { className: "mt-1 flex items-baseline gap-1.5 text-[0.6875rem] leading-snug", children: [
635
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { "aria-hidden": true, className: cn("shrink-0", FRAME_GLYPH_COLOR[frame.status]), children: FRAME_GLYPH[frame.status] ?? "\u25CB" }),
636
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("span", { className: "min-w-0", children: [
637
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "font-mono font-semibold text-keyword", children: frame.keyword }),
638
+ " ",
639
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "text-muted-foreground", children: frame.alt ?? frame.text })
640
+ ] })
641
+ ] })
642
+ ] });
643
+ }
644
+
645
+ // src/components/ReportAttachments.tsx
646
+ var import_jsx_runtime19 = require("react/jsx-runtime");
564
647
  function ReportAttachments({ attachments }) {
565
648
  if (attachments.length === 0) return null;
566
649
  return (
567
650
  // role="group" (not a labelled <section>) so multiple scenarios' attachment
568
651
  // blocks don't create duplicate "Attachments" region landmarks.
569
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { role: "group", "aria-label": "Attachments", className: "mt-3 flex flex-col gap-2", children: attachments.map((att, i) => {
652
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { role: "group", "aria-label": "Attachments", className: "mt-3 flex flex-col gap-2", children: attachments.map((att, i) => {
570
653
  const dataUri = att.contentEncoding === "BASE64" ? `data:${att.mediaType};base64,${att.body}` : `data:${att.mediaType},${encodeURIComponent(att.body)}`;
571
654
  const isImage = att.mediaType.startsWith("image/");
572
- return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("figure", { className: "m-0", children: isImage ? /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(import_jsx_runtime18.Fragment, { children: [
573
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
655
+ return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("figure", { className: "m-0", children: isImage ? /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(import_jsx_runtime19.Fragment, { children: [
656
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
574
657
  "img",
575
658
  {
576
659
  src: dataUri,
@@ -579,8 +662,8 @@ function ReportAttachments({ attachments }) {
579
662
  className: "max-w-full rounded-md border border-border"
580
663
  }
581
664
  ),
582
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("figcaption", { className: "mt-1 text-xs text-muted-foreground", children: att.name })
583
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
665
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("figcaption", { className: "mt-1 text-xs text-muted-foreground", children: att.name })
666
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(
584
667
  "a",
585
668
  {
586
669
  href: dataUri,
@@ -589,7 +672,7 @@ function ReportAttachments({ attachments }) {
589
672
  children: [
590
673
  att.name,
591
674
  " ",
592
- /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("span", { className: "text-muted-foreground", children: [
675
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("span", { className: "text-muted-foreground", children: [
593
676
  "(",
594
677
  att.mediaType,
595
678
  ")"
@@ -677,7 +760,7 @@ function traceWindow(rows) {
677
760
  }
678
761
 
679
762
  // src/components/ReportTrace.tsx
680
- var import_jsx_runtime19 = require("react/jsx-runtime");
763
+ var import_jsx_runtime20 = require("react/jsx-runtime");
681
764
  var BAR_COLOR = {
682
765
  ok: "bg-pass",
683
766
  error: "bg-fail",
@@ -688,8 +771,8 @@ function ReportTrace({ spans }) {
688
771
  const rows = toTraceRows(spans);
689
772
  if (rows.length === 0) return null;
690
773
  const { minStartMs, totalMs } = traceWindow(rows);
691
- return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("details", { className: "mt-3 rounded-md border border-border bg-muted/30", children: [
692
- /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("summary", { className: "cursor-pointer px-3 py-2 text-xs font-medium text-muted-foreground", children: [
774
+ return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("details", { className: "mt-3 rounded-md border border-border bg-muted/30", children: [
775
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("summary", { className: "cursor-pointer px-3 py-2 text-xs font-medium text-muted-foreground", children: [
693
776
  "Trace (",
694
777
  rows.length,
695
778
  " span",
@@ -698,11 +781,11 @@ function ReportTrace({ spans }) {
698
781
  formatDuration(totalMs),
699
782
  ")"
700
783
  ] }),
701
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("ul", { className: "flex flex-col gap-0.5 px-3 pb-3 font-mono text-[0.6875rem]", children: rows.map((row, i) => {
784
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("ul", { className: "flex flex-col gap-0.5 px-3 pb-3 font-mono text-[0.6875rem]", children: rows.map((row, i) => {
702
785
  const leftPct = (row.startTimeMs - minStartMs) / totalMs * 100;
703
786
  const widthPct = Math.max(row.durationMs / totalMs * 100, 0.5);
704
- return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("li", { className: "flex items-center gap-2", children: [
705
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
787
+ return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("li", { className: "flex items-center gap-2", children: [
788
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
706
789
  "span",
707
790
  {
708
791
  className: "min-w-0 flex-1 truncate text-foreground",
@@ -711,14 +794,14 @@ function ReportTrace({ spans }) {
711
794
  children: row.name
712
795
  }
713
796
  ),
714
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "relative h-3 w-1/2 shrink-0 overflow-hidden rounded-sm bg-border/40", children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
797
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { className: "relative h-3 w-1/2 shrink-0 overflow-hidden rounded-sm bg-border/40", children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
715
798
  "span",
716
799
  {
717
800
  className: cn("absolute top-0 h-full rounded-sm", BAR_COLOR[row.status]),
718
801
  style: { left: `${leftPct}%`, width: `${widthPct}%` }
719
802
  }
720
803
  ) }),
721
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "w-16 shrink-0 text-right text-muted-foreground", children: formatDuration(row.durationMs) })
804
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { className: "w-16 shrink-0 text-right text-muted-foreground", children: formatDuration(row.durationMs) })
722
805
  ] }, `${row.spanId}-${i}`);
723
806
  }) })
724
807
  ] });
@@ -787,7 +870,7 @@ function diffSinceLastRun(history2, scenarios) {
787
870
  }
788
871
 
789
872
  // src/components/ScenarioRunHistory.tsx
790
- var import_jsx_runtime20 = require("react/jsx-runtime");
873
+ var import_jsx_runtime21 = require("react/jsx-runtime");
791
874
  var MAX_DOTS = 10;
792
875
  var DOT_COLOR = {
793
876
  passed: "bg-pass",
@@ -807,16 +890,16 @@ function ScenarioRunHistory({ scenarioId }) {
807
890
  const recent = entries.slice(-MAX_DOTS);
808
891
  const flaky = flakinessOf(recent) === "flaky";
809
892
  const summary = flaky ? `${describeRunHistory(recent)} \xB7 Flaky` : describeRunHistory(recent);
810
- return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(import_jsx_runtime20.Fragment, { children: [
811
- flaky ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(Badge, { variant: "pending", "aria-label": "Flaky: status flips between recent runs", title: summary, children: "Flaky" }) : null,
812
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
893
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_jsx_runtime21.Fragment, { children: [
894
+ flaky ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(Badge, { variant: "pending", "aria-label": "Flaky: status flips between recent runs", title: summary, children: "Flaky" }) : null,
895
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
813
896
  "span",
814
897
  {
815
898
  role: "img",
816
899
  "aria-label": `Run history: ${summary}`,
817
900
  title: summary,
818
901
  className: "flex shrink-0 items-center gap-[3px]",
819
- children: recent.map((e, i) => /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
902
+ children: recent.map((e, i) => /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
820
903
  "span",
821
904
  {
822
905
  "aria-hidden": true,
@@ -1033,9 +1116,9 @@ function scenarioPermalink(scenario) {
1033
1116
 
1034
1117
  // src/components/ui/card.tsx
1035
1118
  var React2 = require("react");
1036
- var import_jsx_runtime21 = require("react/jsx-runtime");
1119
+ var import_jsx_runtime22 = require("react/jsx-runtime");
1037
1120
  function Card({ className, ...props }) {
1038
- return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
1121
+ return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
1039
1122
  "div",
1040
1123
  {
1041
1124
  "data-slot": "card",
@@ -1048,7 +1131,7 @@ function Card({ className, ...props }) {
1048
1131
  );
1049
1132
  }
1050
1133
  function CardHeader({ className, ...props }) {
1051
- return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
1134
+ return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
1052
1135
  "div",
1053
1136
  {
1054
1137
  "data-slot": "card-header",
@@ -1061,7 +1144,7 @@ function CardHeader({ className, ...props }) {
1061
1144
  );
1062
1145
  }
1063
1146
  function CardContent({ className, ...props }) {
1064
- return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
1147
+ return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
1065
1148
  "div",
1066
1149
  {
1067
1150
  "data-slot": "card-content",
@@ -1075,13 +1158,13 @@ function CardContent({ className, ...props }) {
1075
1158
  var React3 = require("react");
1076
1159
  var import_menu = require("@base-ui/react/menu");
1077
1160
  var import_lucide_react = require("lucide-react");
1078
- var import_jsx_runtime22 = require("react/jsx-runtime");
1161
+ var import_jsx_runtime23 = require("react/jsx-runtime");
1079
1162
  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";
1080
1163
  function DropdownMenu(props) {
1081
- return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_menu.Menu.Root, { "data-slot": "dropdown-menu", ...props });
1164
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_menu.Menu.Root, { "data-slot": "dropdown-menu", ...props });
1082
1165
  }
1083
1166
  function DropdownMenuTrigger(props) {
1084
- return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_menu.Menu.Trigger, { "data-slot": "dropdown-menu-trigger", ...props });
1167
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_menu.Menu.Trigger, { "data-slot": "dropdown-menu-trigger", ...props });
1085
1168
  }
1086
1169
  function DropdownMenuContent({
1087
1170
  className,
@@ -1089,14 +1172,14 @@ function DropdownMenuContent({
1089
1172
  sideOffset = 4,
1090
1173
  ...props
1091
1174
  }) {
1092
- return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_menu.Menu.Portal, { children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
1175
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_menu.Menu.Portal, { children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
1093
1176
  import_menu.Menu.Positioner,
1094
1177
  {
1095
1178
  "data-slot": "dropdown-menu-positioner",
1096
1179
  className: "z-50",
1097
1180
  align,
1098
1181
  sideOffset,
1099
- children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
1182
+ children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
1100
1183
  import_menu.Menu.Popup,
1101
1184
  {
1102
1185
  "data-slot": "dropdown-menu-content",
@@ -1114,7 +1197,7 @@ function DropdownMenuItem({
1114
1197
  className,
1115
1198
  ...props
1116
1199
  }) {
1117
- return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
1200
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
1118
1201
  import_menu.Menu.Item,
1119
1202
  {
1120
1203
  "data-slot": "dropdown-menu-item",
@@ -1126,7 +1209,7 @@ function DropdownMenuItem({
1126
1209
 
1127
1210
  // src/components/ReportScenario.tsx
1128
1211
  var import_lucide_react2 = require("lucide-react");
1129
- var import_jsx_runtime23 = require("react/jsx-runtime");
1212
+ var import_jsx_runtime24 = require("react/jsx-runtime");
1130
1213
  var STATUS_META = {
1131
1214
  passed: { label: "Passed", glyph: "\u2713", glyphColor: "text-pass", badgeVariant: "passed", showPill: false },
1132
1215
  failed: { label: "Failed", glyph: "\u2717", glyphColor: "text-fail", badgeVariant: "failed", showPill: true },
@@ -1142,7 +1225,7 @@ function ReportScenario({ scenario, hideTitle = false }) {
1142
1225
  const collapsible = collapse !== null && !hideTitle;
1143
1226
  const collapsed = collapsible ? collapse.isCollapsed(scenario.id) : false;
1144
1227
  const actions = useScenarioActions();
1145
- return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(
1228
+ return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
1146
1229
  Card,
1147
1230
  {
1148
1231
  id: scenario.id,
@@ -1150,10 +1233,10 @@ function ReportScenario({ scenario, hideTitle = false }) {
1150
1233
  ...hideTitle ? { "aria-label": `${scenario.title}, ${label}` } : { "aria-labelledby": titleId },
1151
1234
  className: "gap-0 py-0",
1152
1235
  children: [
1153
- /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(CardHeader, { className: "px-4 py-3", children: [
1154
- /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: cn("flex items-start gap-4", hideTitle ? "justify-end" : "justify-between"), children: [
1155
- hideTitle ? null : /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("h3", { id: titleId, className: "flex items-center gap-2 text-sm font-medium text-foreground", children: [
1156
- collapsible ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
1236
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(CardHeader, { className: "px-4 py-3", children: [
1237
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: cn("flex items-start gap-4", hideTitle ? "justify-end" : "justify-between"), children: [
1238
+ hideTitle ? null : /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("h3", { id: titleId, className: "flex items-center gap-2 text-sm font-medium text-foreground", children: [
1239
+ collapsible ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
1157
1240
  "button",
1158
1241
  {
1159
1242
  type: "button",
@@ -1162,49 +1245,49 @@ function ReportScenario({ scenario, hideTitle = false }) {
1162
1245
  "aria-controls": bodyId,
1163
1246
  "aria-label": `Toggle ${scenario.title}`,
1164
1247
  className: "shrink-0 cursor-pointer text-muted-foreground hover:text-foreground",
1165
- children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { "aria-hidden": true, className: cn("inline-block text-xs transition-transform", !collapsed && "rotate-90"), children: "\u25B8" })
1248
+ children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { "aria-hidden": true, className: cn("inline-block text-xs transition-transform", !collapsed && "rotate-90"), children: "\u25B8" })
1166
1249
  }
1167
1250
  ) : null,
1168
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { "aria-hidden": true, className: cn("text-sm leading-none", meta.glyphColor), children: meta.glyph }),
1169
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { children: scenario.title })
1251
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { "aria-hidden": true, className: cn("text-sm leading-none", meta.glyphColor), children: meta.glyph }),
1252
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { children: scenario.title })
1170
1253
  ] }),
1171
- /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex shrink-0 items-center gap-2", children: [
1172
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(ScenarioRunHistory, { scenarioId: scenario.id }),
1173
- scenario.durationMs > 0 ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "whitespace-nowrap font-mono text-[0.6875rem] text-muted-foreground", children: formatDuration(scenario.durationMs) }) : null,
1174
- meta.showPill ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(Badge, { variant: meta.badgeVariant, "aria-label": `Status: ${label}`, children: label }) : /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "sr-only", children: `Status: ${label}` }),
1175
- actions ? /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(DropdownMenu, { children: [
1176
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
1254
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex shrink-0 items-center gap-2", children: [
1255
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(ScenarioRunHistory, { scenarioId: scenario.id }),
1256
+ scenario.durationMs > 0 ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "whitespace-nowrap font-mono text-[0.6875rem] text-muted-foreground", children: formatDuration(scenario.durationMs) }) : null,
1257
+ meta.showPill ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(Badge, { variant: meta.badgeVariant, "aria-label": `Status: ${label}`, children: label }) : /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "sr-only", children: `Status: ${label}` }),
1258
+ actions ? /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(DropdownMenu, { children: [
1259
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
1177
1260
  DropdownMenuTrigger,
1178
1261
  {
1179
1262
  "aria-label": `Actions for ${scenario.title}`,
1180
1263
  className: "cursor-pointer rounded p-1 text-muted-foreground hover:bg-muted hover:text-foreground [&_svg]:size-4",
1181
- children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_lucide_react2.MoreHorizontalIcon, { "aria-hidden": true })
1264
+ children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_lucide_react2.MoreHorizontalIcon, { "aria-hidden": true })
1182
1265
  }
1183
1266
  ),
1184
- /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(DropdownMenuContent, { align: "end", children: [
1185
- /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(DropdownMenuItem, { onClick: () => actions.copyLink(scenario), children: [
1186
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_lucide_react2.LinkIcon, {}),
1267
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(DropdownMenuContent, { align: "end", children: [
1268
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(DropdownMenuItem, { onClick: () => actions.copyLink(scenario), children: [
1269
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_lucide_react2.LinkIcon, {}),
1187
1270
  " Copy link"
1188
1271
  ] }),
1189
- /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(DropdownMenuItem, { onClick: () => actions.copyMarkdown(scenario), children: [
1190
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_lucide_react2.FileTextIcon, {}),
1272
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(DropdownMenuItem, { onClick: () => actions.copyMarkdown(scenario), children: [
1273
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_lucide_react2.FileTextIcon, {}),
1191
1274
  " Copy as Markdown"
1192
1275
  ] }),
1193
- /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(DropdownMenuItem, { onClick: () => actions.copyPrompt(scenario), children: [
1194
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_lucide_react2.SparklesIcon, {}),
1276
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(DropdownMenuItem, { onClick: () => actions.copyPrompt(scenario), children: [
1277
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_lucide_react2.SparklesIcon, {}),
1195
1278
  " Explain with AI"
1196
1279
  ] })
1197
1280
  ] })
1198
1281
  ] }) : null
1199
1282
  ] })
1200
1283
  ] }),
1201
- scenario.tags.length > 0 || (scenario.tickets?.length ?? 0) > 0 ? /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("ul", { "aria-label": "Tags and tickets", className: "flex flex-wrap gap-1.5", children: [
1202
- scenario.tags.map((t) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(Badge, { variant: "tag", children: t }) }, `tag-${t}`)),
1203
- (scenario.tickets ?? []).map((ticket) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("li", { children: ticket.url ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("a", { href: ticket.url, target: "_blank", rel: "noreferrer noopener", children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(Badge, { variant: "outline", children: ticket.id }) }) : /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(Badge, { variant: "outline", children: ticket.id }) }, `ticket-${ticket.id}`))
1284
+ scenario.tags.length > 0 || (scenario.tickets?.length ?? 0) > 0 ? /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("ul", { "aria-label": "Tags and tickets", className: "flex flex-wrap gap-1.5", children: [
1285
+ scenario.tags.map((t) => /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(Badge, { variant: "tag", children: t }) }, `tag-${t}`)),
1286
+ (scenario.tickets ?? []).map((ticket) => /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("li", { children: ticket.url ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("a", { href: ticket.url, target: "_blank", rel: "noreferrer noopener", children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(Badge, { variant: "outline", children: ticket.id }) }) : /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(Badge, { variant: "outline", children: ticket.id }) }, `ticket-${ticket.id}`))
1204
1287
  ] }) : null
1205
1288
  ] }),
1206
- /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(CardContent, { id: bodyId, hidden: collapsed, className: "px-4 pt-0 pb-4", children: [
1207
- scenario.errorMessage ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
1289
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(CardContent, { id: bodyId, hidden: collapsed, className: "px-4 pt-0 pb-4", children: [
1290
+ scenario.errorMessage ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
1208
1291
  "pre",
1209
1292
  {
1210
1293
  role: "alert",
@@ -1212,10 +1295,11 @@ function ReportScenario({ scenario, hideTitle = false }) {
1212
1295
  children: scenario.errorMessage
1213
1296
  }
1214
1297
  ) : null,
1215
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(ReportSteps, { scenario }),
1216
- scenario.docEntries.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { "data-es-docs": true, className: "mt-3", children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(ReportDocEntries, { entries: scenario.docEntries }) }) : null,
1217
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(ReportAttachments, { attachments: scenario.attachments }),
1218
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(ReportTrace, { spans: scenario.otelSpans })
1298
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(ReportStoryboard, { scenario }),
1299
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(ReportSteps, { scenario }),
1300
+ scenario.docEntries.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { "data-es-docs": true, className: "mt-3", children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(ReportDocEntries, { entries: scenario.docEntries }) }) : null,
1301
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(ReportAttachments, { attachments: scenario.attachments }),
1302
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(ReportTrace, { spans: scenario.otelSpans })
1219
1303
  ] })
1220
1304
  ]
1221
1305
  }
@@ -1223,13 +1307,13 @@ function ReportScenario({ scenario, hideTitle = false }) {
1223
1307
  }
1224
1308
 
1225
1309
  // src/components/ReportScenarioList.tsx
1226
- var import_jsx_runtime24 = require("react/jsx-runtime");
1310
+ var import_jsx_runtime25 = require("react/jsx-runtime");
1227
1311
  function ReportScenarioList({ feature }) {
1228
- return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_jsx_runtime24.Fragment, { children: feature.scenarios.map((scenario) => /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(ReportScenario, { scenario }, scenario.id)) });
1312
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_jsx_runtime25.Fragment, { children: feature.scenarios.map((scenario) => /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ReportScenario, { scenario }, scenario.id)) });
1229
1313
  }
1230
1314
 
1231
1315
  // src/components/ReportFeature.tsx
1232
- var import_jsx_runtime25 = require("react/jsx-runtime");
1316
+ var import_jsx_runtime26 = require("react/jsx-runtime");
1233
1317
  function ReportFeature({ feature }) {
1234
1318
  const titleId = `${feature.id}-title`;
1235
1319
  const bodyId = `${feature.id}-body`;
@@ -1240,7 +1324,7 @@ function ReportFeature({ feature }) {
1240
1324
  return (
1241
1325
  // Suite = a section heading + a divider, NOT another bordered card. Drops a
1242
1326
  // layer of nesting so the scenario cards below read as the primary unit.
1243
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
1327
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(
1244
1328
  "section",
1245
1329
  {
1246
1330
  id: feature.id,
@@ -1248,9 +1332,9 @@ function ReportFeature({ feature }) {
1248
1332
  "aria-labelledby": titleId,
1249
1333
  className: "flex flex-col gap-3",
1250
1334
  children: [
1251
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex items-end justify-between gap-4 border-b border-border pb-2", children: [
1252
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "min-w-0", children: [
1253
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("h2", { id: titleId, className: "text-base font-semibold tracking-tight text-foreground", children: collapse ? /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
1335
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "flex items-end justify-between gap-4 border-b border-border pb-2", children: [
1336
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "min-w-0", children: [
1337
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("h2", { id: titleId, className: "text-base font-semibold tracking-tight text-foreground", children: collapse ? /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(
1254
1338
  "button",
1255
1339
  {
1256
1340
  type: "button",
@@ -1259,31 +1343,31 @@ function ReportFeature({ feature }) {
1259
1343
  "aria-controls": bodyId,
1260
1344
  className: "flex w-full cursor-pointer items-center gap-2 text-left hover:text-foreground/80",
1261
1345
  children: [
1262
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { "aria-hidden": true, className: cn("shrink-0 text-xs text-muted-foreground transition-transform", !collapsed && "rotate-90"), children: "\u25B8" }),
1263
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { className: "truncate", children: feature.title })
1346
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { "aria-hidden": true, className: cn("shrink-0 text-xs text-muted-foreground transition-transform", !collapsed && "rotate-90"), children: "\u25B8" }),
1347
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "truncate", children: feature.title })
1264
1348
  ]
1265
1349
  }
1266
1350
  ) : feature.title }),
1267
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("p", { className: cn("mt-0.5 truncate font-mono text-xs text-muted-foreground", collapse && "pl-5"), children: feature.sourceFile })
1351
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("p", { className: cn("mt-0.5 truncate font-mono text-xs text-muted-foreground", collapse && "pl-5"), children: feature.sourceFile })
1268
1352
  ] }),
1269
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
1353
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(
1270
1354
  "p",
1271
1355
  {
1272
1356
  className: "flex shrink-0 items-center gap-1.5 text-xs text-muted-foreground",
1273
1357
  "aria-label": `${s.passed} passed, ${s.failed} failed, ${skipped} skipped`,
1274
1358
  children: [
1275
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("span", { children: [
1359
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("span", { children: [
1276
1360
  s.passed,
1277
1361
  " passed"
1278
1362
  ] }),
1279
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { "aria-hidden": true, children: "\xB7" }),
1280
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("span", { className: cn(s.failed > 0 && "font-medium text-fail"), children: [
1363
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { "aria-hidden": true, children: "\xB7" }),
1364
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("span", { className: cn(s.failed > 0 && "font-medium text-fail"), children: [
1281
1365
  s.failed,
1282
1366
  " failed"
1283
1367
  ] }),
1284
- skipped > 0 ? /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(import_jsx_runtime25.Fragment, { children: [
1285
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { "aria-hidden": true, children: "\xB7" }),
1286
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("span", { children: [
1368
+ skipped > 0 ? /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(import_jsx_runtime26.Fragment, { children: [
1369
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { "aria-hidden": true, children: "\xB7" }),
1370
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("span", { children: [
1287
1371
  skipped,
1288
1372
  " skipped"
1289
1373
  ] })
@@ -1292,7 +1376,7 @@ function ReportFeature({ feature }) {
1292
1376
  }
1293
1377
  )
1294
1378
  ] }),
1295
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { id: bodyId, hidden: collapsed, className: "flex flex-col gap-3", children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ReportScenarioList, { feature }) })
1379
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { id: bodyId, hidden: collapsed, className: "flex flex-col gap-3", children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(ReportScenarioList, { feature }) })
1296
1380
  ]
1297
1381
  }
1298
1382
  )
@@ -1300,17 +1384,17 @@ function ReportFeature({ feature }) {
1300
1384
  }
1301
1385
 
1302
1386
  // src/components/ReportFeatureList.tsx
1303
- var import_jsx_runtime26 = require("react/jsx-runtime");
1387
+ var import_jsx_runtime27 = require("react/jsx-runtime");
1304
1388
  function ReportFeatureList() {
1305
1389
  const report = useReport();
1306
- return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { className: "flex flex-col gap-8", children: report.features.map((feature) => /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(ReportFeature, { feature }, feature.id)) });
1390
+ return /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { className: "flex flex-col gap-8", children: report.features.map((feature) => /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(ReportFeature, { feature }, feature.id)) });
1307
1391
  }
1308
1392
 
1309
1393
  // src/components/ui/empty.tsx
1310
1394
  var import_class_variance_authority2 = require("class-variance-authority");
1311
- var import_jsx_runtime27 = require("react/jsx-runtime");
1395
+ var import_jsx_runtime28 = require("react/jsx-runtime");
1312
1396
  function Empty({ className, ...props }) {
1313
- return /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
1397
+ return /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
1314
1398
  "div",
1315
1399
  {
1316
1400
  "data-slot": "empty",
@@ -1323,7 +1407,7 @@ function Empty({ className, ...props }) {
1323
1407
  );
1324
1408
  }
1325
1409
  function EmptyHeader({ className, ...props }) {
1326
- return /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
1410
+ return /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
1327
1411
  "div",
1328
1412
  {
1329
1413
  "data-slot": "empty-header",
@@ -1350,7 +1434,7 @@ var emptyMediaVariants = (0, import_class_variance_authority2.cva)(
1350
1434
  }
1351
1435
  );
1352
1436
  function EmptyTitle({ className, ...props }) {
1353
- return /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
1437
+ return /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
1354
1438
  "div",
1355
1439
  {
1356
1440
  "data-slot": "empty-title",
@@ -1361,16 +1445,16 @@ function EmptyTitle({ className, ...props }) {
1361
1445
  }
1362
1446
 
1363
1447
  // src/components/ReportEmpty.tsx
1364
- var import_jsx_runtime28 = require("react/jsx-runtime");
1448
+ var import_jsx_runtime29 = require("react/jsx-runtime");
1365
1449
  function ReportEmpty({ message }) {
1366
- return /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(Empty, { "aria-live": "polite", className: "border", children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(EmptyHeader, { children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(EmptyTitle, { children: message ?? "No scenarios in this report." }) }) });
1450
+ return /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(Empty, { "aria-live": "polite", className: "border", children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(EmptyHeader, { children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(EmptyTitle, { children: message ?? "No scenarios in this report." }) }) });
1367
1451
  }
1368
1452
 
1369
1453
  // src/components/ReportSummary.tsx
1370
- var import_jsx_runtime29 = require("react/jsx-runtime");
1454
+ var import_jsx_runtime30 = require("react/jsx-runtime");
1371
1455
  function ReportSummary({ className }) {
1372
1456
  const report = useReport();
1373
- return /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
1457
+ return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
1374
1458
  ReportSummaryView,
1375
1459
  {
1376
1460
  summary: report.summary,
@@ -1396,7 +1480,7 @@ function ReportSummaryView({ summary, className, ariaLabel }) {
1396
1480
  if (summary.pending > 0) {
1397
1481
  cards.push({ status: "pending", label: "Pending", value: summary.pending });
1398
1482
  }
1399
- return /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
1483
+ return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
1400
1484
  "dl",
1401
1485
  {
1402
1486
  className: cn(
@@ -1409,17 +1493,17 @@ function ReportSummaryView({ summary, className, ariaLabel }) {
1409
1493
  "aria-label": ariaLabel,
1410
1494
  children: cards.map((c) => {
1411
1495
  const tone = TONE[c.status];
1412
- return /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(
1496
+ return /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(
1413
1497
  "div",
1414
1498
  {
1415
1499
  "data-status": c.status,
1416
1500
  className: "rounded-lg border bg-card px-4 py-3",
1417
1501
  children: [
1418
- /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("dt", { className: "flex items-center gap-1.5 font-mono text-[11px] font-medium uppercase tracking-wider text-muted-foreground", children: [
1419
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("span", { className: cn("size-1.5 shrink-0 rounded-full", tone.dot), "aria-hidden": "true" }),
1502
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("dt", { className: "flex items-center gap-1.5 font-mono text-[11px] font-medium uppercase tracking-wider text-muted-foreground", children: [
1503
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { className: cn("size-1.5 shrink-0 rounded-full", tone.dot), "aria-hidden": "true" }),
1420
1504
  c.label
1421
1505
  ] }),
1422
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("dd", { className: cn("mt-2 text-3xl font-semibold leading-none tracking-tight tabular-nums", tone.num), children: c.value })
1506
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("dd", { className: cn("mt-2 text-3xl font-semibold leading-none tracking-tight tabular-nums", tone.num), children: c.value })
1423
1507
  ]
1424
1508
  },
1425
1509
  c.status
@@ -1479,7 +1563,7 @@ function prUrl(ci) {
1479
1563
  }
1480
1564
 
1481
1565
  // src/components/ReportMeta.tsx
1482
- var import_jsx_runtime30 = require("react/jsx-runtime");
1566
+ var import_jsx_runtime31 = require("react/jsx-runtime");
1483
1567
  function ReportMeta() {
1484
1568
  const report = useReport();
1485
1569
  const items = [];
@@ -1502,13 +1586,13 @@ function ReportMeta() {
1502
1586
  const short = sha.slice(0, 8);
1503
1587
  items.push({
1504
1588
  label: "Commit",
1505
- value: url ? /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("a", { href: url, target: "_blank", rel: "noreferrer noopener", className: linkClass, children: short }) : short
1589
+ value: url ? /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("a", { href: url, target: "_blank", rel: "noreferrer noopener", className: linkClass, children: short }) : short
1506
1590
  });
1507
1591
  }
1508
1592
  if (report.ci) {
1509
1593
  items.push({
1510
1594
  label: "CI",
1511
- value: report.ci.url ? /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("a", { href: report.ci.url, target: "_blank", rel: "noreferrer noopener", className: linkClass, children: [
1595
+ value: report.ci.url ? /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("a", { href: report.ci.url, target: "_blank", rel: "noreferrer noopener", className: linkClass, children: [
1512
1596
  ciDisplayName(report.ci.name),
1513
1597
  report.ci.buildNumber ? ` #${report.ci.buildNumber}` : ""
1514
1598
  ] }) : `${ciDisplayName(report.ci.name)}${report.ci.buildNumber ? ` #${report.ci.buildNumber}` : ""}`
@@ -1519,7 +1603,7 @@ function ReportMeta() {
1519
1603
  const label = `#${report.ci.prNumber}`;
1520
1604
  items.push({
1521
1605
  label: "PR",
1522
- value: url ? /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("a", { href: url, target: "_blank", rel: "noreferrer noopener", className: linkClass, children: label }) : label
1606
+ value: url ? /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("a", { href: url, target: "_blank", rel: "noreferrer noopener", className: linkClass, children: label }) : label
1523
1607
  });
1524
1608
  }
1525
1609
  if (items.length === 0) return null;
@@ -1527,50 +1611,50 @@ function ReportMeta() {
1527
1611
  // Run metadata is useful but secondary to "what failed" — tuck it into a
1528
1612
  // collapsed disclosure so it doesn't push the result down. Native <details>
1529
1613
  // so it works with no JS (the SSR/no-hydration report still toggles).
1530
- /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("details", { "data-es-meta-card": true, className: "es-run-details group rounded-lg border border-border bg-card text-xs", children: [
1531
- /* @__PURE__ */ (0, import_jsx_runtime30.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: [
1532
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { "aria-hidden": true, className: "text-xs transition-transform group-open:rotate-90", children: "\u25B8" }),
1614
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("details", { "data-es-meta-card": true, className: "es-run-details group rounded-lg border border-border bg-card text-xs", children: [
1615
+ /* @__PURE__ */ (0, import_jsx_runtime31.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: [
1616
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("span", { "aria-hidden": true, className: "text-xs transition-transform group-open:rotate-90", children: "\u25B8" }),
1533
1617
  "Run details"
1534
1618
  ] }),
1535
- /* @__PURE__ */ (0, import_jsx_runtime30.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_runtime30.jsxs)("div", { className: "flex items-baseline gap-1.5", children: [
1536
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("dt", { className: "font-medium", children: item.label }),
1537
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("dd", { className: "font-mono text-foreground", children: item.value })
1619
+ /* @__PURE__ */ (0, import_jsx_runtime31.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_runtime31.jsxs)("div", { className: "flex items-baseline gap-1.5", children: [
1620
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("dt", { className: "font-medium", children: item.label }),
1621
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("dd", { className: "font-mono text-foreground", children: item.value })
1538
1622
  ] }, item.label)) })
1539
1623
  ] })
1540
1624
  );
1541
1625
  }
1542
1626
 
1543
1627
  // src/components/ReportSchemaError.tsx
1544
- var import_jsx_runtime31 = require("react/jsx-runtime");
1628
+ var import_jsx_runtime32 = require("react/jsx-runtime");
1545
1629
  function ReportSchemaError({ error }) {
1546
- return /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("section", { className: "es-schema-error", role: "alert", "aria-live": "assertive", children: [
1547
- /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("p", { children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("strong", { children: "Report could not be displayed." }) }),
1548
- /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("p", { children: error.message }),
1549
- error.code === "SCHEMA_VERSION_MISMATCH" ? /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("p", { children: [
1630
+ return /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("section", { className: "es-schema-error", role: "alert", "aria-live": "assertive", children: [
1631
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("p", { children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("strong", { children: "Report could not be displayed." }) }),
1632
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("p", { children: error.message }),
1633
+ error.code === "SCHEMA_VERSION_MISMATCH" ? /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("p", { children: [
1550
1634
  "The report bundle is newer than this version of ",
1551
- /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("code", { children: "executable-stories-react" }),
1635
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("code", { children: "executable-stories-react" }),
1552
1636
  ". Upgrade the package, or regenerate the report with an older formatters CLI."
1553
1637
  ] }) : null,
1554
- error.issues && error.issues.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("details", { children: [
1555
- /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("summary", { children: [
1638
+ error.issues && error.issues.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("details", { children: [
1639
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("summary", { children: [
1556
1640
  error.issues.length,
1557
1641
  " validation issue",
1558
1642
  error.issues.length === 1 ? "" : "s"
1559
1643
  ] }),
1560
- /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("pre", { children: error.issues.slice(0, 20).map((i) => `${i.path}: ${i.message}`).join("\n") })
1644
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("pre", { children: error.issues.slice(0, 20).map((i) => `${i.path}: ${i.message}`).join("\n") })
1561
1645
  ] }) : null
1562
1646
  ] });
1563
1647
  }
1564
1648
 
1565
1649
  // src/components/ReportShell.tsx
1566
- var import_jsx_runtime32 = require("react/jsx-runtime");
1650
+ var import_jsx_runtime33 = require("react/jsx-runtime");
1567
1651
  function ReportErrorShell({
1568
1652
  error,
1569
1653
  className,
1570
1654
  title,
1571
1655
  dataTheme
1572
1656
  }) {
1573
- return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("main", { className: cn("es-report", className), "aria-label": title ?? "Test report", "data-theme": dataTheme, children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(ReportSchemaError, { error }) });
1657
+ return /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("main", { className: cn("es-report", className), "aria-label": title ?? "Test report", "data-theme": dataTheme, children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(ReportSchemaError, { error }) });
1574
1658
  }
1575
1659
 
1576
1660
  // src/interactive/ReportInteractive.tsx
@@ -1579,12 +1663,12 @@ var import_lucide_react5 = require("lucide-react");
1579
1663
  // src/components/ui/switch.tsx
1580
1664
  var React4 = require("react");
1581
1665
  var import_switch = require("@base-ui/react/switch");
1582
- var import_jsx_runtime33 = require("react/jsx-runtime");
1666
+ var import_jsx_runtime34 = require("react/jsx-runtime");
1583
1667
  function Switch({
1584
1668
  className,
1585
1669
  ...props
1586
1670
  }) {
1587
- return /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
1671
+ return /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
1588
1672
  import_switch.Switch.Root,
1589
1673
  {
1590
1674
  "data-slot": "switch",
@@ -1593,7 +1677,7 @@ function Switch({
1593
1677
  className
1594
1678
  ),
1595
1679
  ...props,
1596
- children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
1680
+ children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
1597
1681
  import_switch.Switch.Thumb,
1598
1682
  {
1599
1683
  "data-slot": "switch-thumb",
@@ -1609,7 +1693,7 @@ var React5 = __toESM(require("react"), 1);
1609
1693
  var import_toggle_group = require("@base-ui/react/toggle-group");
1610
1694
  var import_toggle = require("@base-ui/react/toggle");
1611
1695
  var import_class_variance_authority3 = require("class-variance-authority");
1612
- var import_jsx_runtime34 = require("react/jsx-runtime");
1696
+ var import_jsx_runtime35 = require("react/jsx-runtime");
1613
1697
  var toggleItemVariants = (0, import_class_variance_authority3.cva)(
1614
1698
  "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",
1615
1699
  {
@@ -1631,13 +1715,13 @@ function ToggleGroup({
1631
1715
  children,
1632
1716
  ...props
1633
1717
  }) {
1634
- return /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
1718
+ return /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
1635
1719
  import_toggle_group.ToggleGroup,
1636
1720
  {
1637
1721
  "data-slot": "toggle-group",
1638
1722
  className: cn("flex w-fit items-center gap-0.5 rounded-lg bg-muted p-0.5", className),
1639
1723
  ...props,
1640
- children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(ToggleGroupContext.Provider, { value: { size }, children })
1724
+ children: /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(ToggleGroupContext.Provider, { value: { size }, children })
1641
1725
  }
1642
1726
  );
1643
1727
  }
@@ -1648,7 +1732,7 @@ function ToggleGroupItem({
1648
1732
  ...props
1649
1733
  }) {
1650
1734
  const context = React5.useContext(ToggleGroupContext);
1651
- return /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
1735
+ return /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
1652
1736
  import_toggle.Toggle,
1653
1737
  {
1654
1738
  "data-slot": "toggle-group-item",
@@ -1665,9 +1749,9 @@ var import_lucide_react3 = require("lucide-react");
1665
1749
 
1666
1750
  // src/components/ui/input.tsx
1667
1751
  var React6 = require("react");
1668
- var import_jsx_runtime35 = require("react/jsx-runtime");
1752
+ var import_jsx_runtime36 = require("react/jsx-runtime");
1669
1753
  function Input({ className, type, ...props }) {
1670
- return /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
1754
+ return /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
1671
1755
  "input",
1672
1756
  {
1673
1757
  type,
@@ -1684,7 +1768,7 @@ function Input({ className, type, ...props }) {
1684
1768
  }
1685
1769
 
1686
1770
  // src/interactive/ReportSearch.tsx
1687
- var import_jsx_runtime36 = require("react/jsx-runtime");
1771
+ var import_jsx_runtime37 = require("react/jsx-runtime");
1688
1772
  var ReportSearch = (0, import_react8.forwardRef)(
1689
1773
  function ReportSearch2(props, ref) {
1690
1774
  const {
@@ -1706,17 +1790,17 @@ var ReportSearch = (0, import_react8.forwardRef)(
1706
1790
  e.preventDefault();
1707
1791
  }
1708
1792
  }
1709
- return /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("div", { className: cn("es-search flex flex-col gap-1", className), children: [
1710
- /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("label", { htmlFor: inputId, className: "sr-only", children: "Search" }),
1711
- /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("div", { className: "relative w-full sm:w-72", children: [
1712
- /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
1793
+ return /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("div", { className: cn("es-search flex flex-col gap-1", className), children: [
1794
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("label", { htmlFor: inputId, className: "sr-only", children: "Search" }),
1795
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("div", { className: "relative w-full sm:w-72", children: [
1796
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
1713
1797
  import_lucide_react3.Search,
1714
1798
  {
1715
1799
  "aria-hidden": true,
1716
1800
  className: "pointer-events-none absolute top-1/2 left-2.5 size-4 -translate-y-1/2 text-muted-foreground"
1717
1801
  }
1718
1802
  ),
1719
- /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
1803
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
1720
1804
  Input,
1721
1805
  {
1722
1806
  ref,
@@ -1733,7 +1817,7 @@ var ReportSearch = (0, import_react8.forwardRef)(
1733
1817
  }
1734
1818
  )
1735
1819
  ] }),
1736
- showCounts ? /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(
1820
+ showCounts ? /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)(
1737
1821
  "span",
1738
1822
  {
1739
1823
  className: "text-xs tabular-nums text-muted-foreground",
@@ -1774,7 +1858,7 @@ function scrollToScenarioId(scenarioId, options = {}) {
1774
1858
  }
1775
1859
 
1776
1860
  // src/interactive/ReportFailureBanner.tsx
1777
- var import_jsx_runtime37 = require("react/jsx-runtime");
1861
+ var import_jsx_runtime38 = require("react/jsx-runtime");
1778
1862
  function ReportFailureBanner({ failures }) {
1779
1863
  const first = failures[0];
1780
1864
  const jumpToFirst = (0, import_react9.useCallback)(() => {
@@ -1782,7 +1866,7 @@ function ReportFailureBanner({ failures }) {
1782
1866
  scrollToScenarioId(first.scenarioId);
1783
1867
  }, [first]);
1784
1868
  if (failures.length === 0) return null;
1785
- return /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)(
1869
+ return /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)(
1786
1870
  "div",
1787
1871
  {
1788
1872
  className: "es-failure-banner",
@@ -1790,13 +1874,13 @@ function ReportFailureBanner({ failures }) {
1790
1874
  "aria-live": "polite",
1791
1875
  "aria-label": "Failure summary",
1792
1876
  children: [
1793
- /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("span", { className: "es-failure-banner-text", children: [
1794
- /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("strong", { children: failures.length }),
1877
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("span", { className: "es-failure-banner-text", children: [
1878
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("strong", { children: failures.length }),
1795
1879
  " ",
1796
1880
  "failure",
1797
1881
  failures.length === 1 ? "" : "s"
1798
1882
  ] }),
1799
- /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
1883
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
1800
1884
  "button",
1801
1885
  {
1802
1886
  type: "button",
@@ -1813,7 +1897,7 @@ function ReportFailureBanner({ failures }) {
1813
1897
 
1814
1898
  // src/interactive/ReportFreshness.tsx
1815
1899
  var import_react10 = require("react");
1816
- var import_jsx_runtime38 = require("react/jsx-runtime");
1900
+ var import_jsx_runtime39 = require("react/jsx-runtime");
1817
1901
  function ReportFreshness({ lastRunMs, ciUrl, staleAfterDays, nowMs }) {
1818
1902
  const [now, setNow] = (0, import_react10.useState)(nowMs);
1819
1903
  (0, import_react10.useEffect)(() => {
@@ -1821,7 +1905,7 @@ function ReportFreshness({ lastRunMs, ciUrl, staleAfterDays, nowMs }) {
1821
1905
  }, [nowMs]);
1822
1906
  if (lastRunMs === void 0 || now === void 0) return null;
1823
1907
  const age = formatRelativeAge(lastRunMs, now);
1824
- const runLink = ciUrl ? /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
1908
+ const runLink = ciUrl ? /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
1825
1909
  "a",
1826
1910
  {
1827
1911
  href: ciUrl,
@@ -1832,9 +1916,9 @@ function ReportFreshness({ lastRunMs, ciUrl, staleAfterDays, nowMs }) {
1832
1916
  }
1833
1917
  ) : null;
1834
1918
  if (isReportStale(lastRunMs, staleAfterDays, now)) {
1835
- return /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("div", { className: "es-stale-banner", role: "status", "aria-label": "Report freshness", children: [
1836
- /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("span", { children: [
1837
- /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("strong", { children: [
1919
+ return /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { className: "es-stale-banner", role: "status", "aria-label": "Report freshness", children: [
1920
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("span", { children: [
1921
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("strong", { children: [
1838
1922
  "Last verified ",
1839
1923
  age,
1840
1924
  "."
@@ -1844,10 +1928,10 @@ function ReportFreshness({ lastRunMs, ciUrl, staleAfterDays, nowMs }) {
1844
1928
  runLink
1845
1929
  ] });
1846
1930
  }
1847
- return /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("p", { className: "es-freshness", "aria-label": "Report freshness", children: [
1931
+ return /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("p", { className: "es-freshness", "aria-label": "Report freshness", children: [
1848
1932
  "Verified ",
1849
1933
  age,
1850
- runLink ? /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)(import_jsx_runtime38.Fragment, { children: [
1934
+ runLink ? /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)(import_jsx_runtime39.Fragment, { children: [
1851
1935
  " \xB7 ",
1852
1936
  runLink
1853
1937
  ] }) : null
@@ -1855,15 +1939,15 @@ function ReportFreshness({ lastRunMs, ciUrl, staleAfterDays, nowMs }) {
1855
1939
  }
1856
1940
 
1857
1941
  // src/interactive/ReportLastRunDelta.tsx
1858
- var import_jsx_runtime39 = require("react/jsx-runtime");
1942
+ var import_jsx_runtime40 = require("react/jsx-runtime");
1859
1943
  var MAX_LINKS = 5;
1860
1944
  function ScenarioLinks({ scenarios, tone }) {
1861
- return /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)(import_jsx_runtime39.Fragment, { children: [
1862
- scenarios.slice(0, MAX_LINKS).map((s, i) => /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("span", { children: [
1945
+ return /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(import_jsx_runtime40.Fragment, { children: [
1946
+ scenarios.slice(0, MAX_LINKS).map((s, i) => /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("span", { children: [
1863
1947
  i > 0 ? ", " : "",
1864
- /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("a", { href: `#${s.id}`, className: cn("underline underline-offset-2 hover:no-underline", tone), children: s.title })
1948
+ /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("a", { href: `#${s.id}`, className: cn("underline underline-offset-2 hover:no-underline", tone), children: s.title })
1865
1949
  ] }, s.id)),
1866
- scenarios.length > MAX_LINKS ? /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("span", { children: [
1950
+ scenarios.length > MAX_LINKS ? /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("span", { children: [
1867
1951
  " and ",
1868
1952
  scenarios.length - MAX_LINKS,
1869
1953
  " more"
@@ -1880,23 +1964,23 @@ function ReportLastRunDelta({
1880
1964
  if (!delta) return null;
1881
1965
  const { newlyFailing, newlyPassing, added } = delta;
1882
1966
  if (newlyFailing.length === 0 && newlyPassing.length === 0 && added.length === 0) {
1883
- return /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("p", { className: "text-xs text-muted-foreground", "data-testid": "es-last-run-delta", children: "Since last run: no behavior changes." });
1967
+ return /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("p", { className: "text-xs text-muted-foreground", "data-testid": "es-last-run-delta", children: "Since last run: no behavior changes." });
1884
1968
  }
1885
- return /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("p", { className: "text-xs text-muted-foreground", "data-testid": "es-last-run-delta", children: [
1886
- /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("span", { className: "font-medium text-foreground", children: "Since last run:" }),
1887
- newlyFailing.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("span", { className: "ml-2 text-fail", children: [
1969
+ return /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("p", { className: "text-xs text-muted-foreground", "data-testid": "es-last-run-delta", children: [
1970
+ /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("span", { className: "font-medium text-foreground", children: "Since last run:" }),
1971
+ newlyFailing.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("span", { className: "ml-2 text-fail", children: [
1888
1972
  newlyFailing.length,
1889
1973
  " newly failing (",
1890
- /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(ScenarioLinks, { scenarios: newlyFailing, tone: "text-fail" }),
1974
+ /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(ScenarioLinks, { scenarios: newlyFailing, tone: "text-fail" }),
1891
1975
  ")"
1892
1976
  ] }) : null,
1893
- newlyPassing.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("span", { className: "ml-2 text-pass", children: [
1977
+ newlyPassing.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("span", { className: "ml-2 text-pass", children: [
1894
1978
  newlyPassing.length,
1895
1979
  " fixed (",
1896
- /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(ScenarioLinks, { scenarios: newlyPassing, tone: "text-pass" }),
1980
+ /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(ScenarioLinks, { scenarios: newlyPassing, tone: "text-pass" }),
1897
1981
  ")"
1898
1982
  ] }) : null,
1899
- added.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("span", { className: "ml-2", children: [
1983
+ added.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("span", { className: "ml-2", children: [
1900
1984
  added.length,
1901
1985
  " new"
1902
1986
  ] }) : null
@@ -1960,7 +2044,7 @@ function Button({
1960
2044
  }
1961
2045
 
1962
2046
  // src/interactive/ReportShortcutsHelp.tsx
1963
- var import_jsx_runtime40 = require("react/jsx-runtime");
2047
+ var import_jsx_runtime41 = require("react/jsx-runtime");
1964
2048
  var SHORTCUTS = [
1965
2049
  { keys: "/", description: "Focus search" },
1966
2050
  { keys: "f", description: "Jump to next failure" },
@@ -1972,9 +2056,9 @@ var SHORTCUTS = [
1972
2056
  ];
1973
2057
  function Keys({ keys }) {
1974
2058
  const parts = keys.split(" ");
1975
- return /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("span", { className: "inline-flex items-center gap-1", children: parts.map((k, i) => /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("span", { className: "inline-flex items-center gap-1", children: [
1976
- i > 0 ? /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("span", { className: "text-xs text-muted-foreground", children: "+" }) : null,
1977
- /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("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 })
2059
+ return /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("span", { className: "inline-flex items-center gap-1", children: parts.map((k, i) => /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("span", { className: "inline-flex items-center gap-1", children: [
2060
+ i > 0 ? /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("span", { className: "text-xs text-muted-foreground", children: "+" }) : null,
2061
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("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 })
1978
2062
  ] }, k)) });
1979
2063
  }
1980
2064
  function ReportShortcutsHelp({ open, onClose }) {
@@ -1985,7 +2069,7 @@ function ReportShortcutsHelp({ open, onClose }) {
1985
2069
  if (open && !dialog.open) dialog.showModal();
1986
2070
  else if (!open && dialog.open) dialog.close();
1987
2071
  }, [open]);
1988
- return /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(
2072
+ return /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)(
1989
2073
  "dialog",
1990
2074
  {
1991
2075
  ref: dialogRef,
@@ -1993,12 +2077,12 @@ function ReportShortcutsHelp({ open, onClose }) {
1993
2077
  "aria-label": "Keyboard shortcuts",
1994
2078
  onClose,
1995
2079
  children: [
1996
- /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("h2", { className: "text-base font-semibold", children: "Keyboard shortcuts" }),
1997
- /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("dl", { className: "mt-4 grid grid-cols-[auto_1fr] items-center gap-x-4 gap-y-2.5", children: SHORTCUTS.map((s) => /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("div", { className: "col-span-2 grid grid-cols-subgrid items-center", children: [
1998
- /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("dt", { className: "justify-self-start", children: /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(Keys, { keys: s.keys }) }),
1999
- /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("dd", { className: "text-sm text-muted-foreground", children: s.description })
2080
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("h2", { className: "text-base font-semibold", children: "Keyboard shortcuts" }),
2081
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("dl", { className: "mt-4 grid grid-cols-[auto_1fr] items-center gap-x-4 gap-y-2.5", children: SHORTCUTS.map((s) => /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { className: "col-span-2 grid grid-cols-subgrid items-center", children: [
2082
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("dt", { className: "justify-self-start", children: /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(Keys, { keys: s.keys }) }),
2083
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("dd", { className: "text-sm text-muted-foreground", children: s.description })
2000
2084
  ] }, s.keys)) }),
2001
- /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("form", { method: "dialog", className: "mt-6", children: /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(Button, { type: "submit", variant: "outline", size: "sm", children: "Close" }) })
2085
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("form", { method: "dialog", className: "mt-6", children: /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(Button, { type: "submit", variant: "outline", size: "sm", children: "Close" }) })
2002
2086
  ]
2003
2087
  }
2004
2088
  );
@@ -2199,7 +2283,7 @@ function failuresFirst(report) {
2199
2283
 
2200
2284
  // src/interactive/ReportFilters.tsx
2201
2285
  var import_react14 = require("react");
2202
- var import_jsx_runtime41 = require("react/jsx-runtime");
2286
+ var import_jsx_runtime42 = require("react/jsx-runtime");
2203
2287
  var TAG_LIMIT = 12;
2204
2288
  function ReportFilters({
2205
2289
  statuses,
@@ -2213,10 +2297,10 @@ function ReportFilters({
2213
2297
  if (statuses.length === 0 && tags.length === 0) return null;
2214
2298
  const tagsCollapsed = tags.length > TAG_LIMIT && !showAllTags;
2215
2299
  const visibleTags = tagsCollapsed ? tags.slice(0, TAG_LIMIT) : tags;
2216
- return /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { className: "flex flex-col gap-2", children: [
2217
- statuses.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("div", { role: "group", "aria-label": "Filter by status", className: "flex flex-wrap gap-1", children: statuses.map((opt) => {
2300
+ return /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "flex flex-col gap-2", children: [
2301
+ statuses.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("div", { role: "group", "aria-label": "Filter by status", className: "flex flex-wrap gap-1", children: statuses.map((opt) => {
2218
2302
  const active = status === opt.key;
2219
- return /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)(
2303
+ return /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(
2220
2304
  "button",
2221
2305
  {
2222
2306
  type: "button",
@@ -2228,23 +2312,23 @@ function ReportFilters({
2228
2312
  ),
2229
2313
  children: [
2230
2314
  opt.label,
2231
- /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("span", { className: "ml-1 font-mono opacity-70", children: opt.count })
2315
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("span", { className: "ml-1 font-mono opacity-70", children: opt.count })
2232
2316
  ]
2233
2317
  },
2234
2318
  opt.key
2235
2319
  );
2236
2320
  }) }) : null,
2237
- tags.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("ul", { "aria-label": "Filter by tag", className: "flex flex-wrap items-center gap-1.5", children: [
2321
+ tags.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("ul", { "aria-label": "Filter by tag", className: "flex flex-wrap items-center gap-1.5", children: [
2238
2322
  visibleTags.map((tag) => {
2239
2323
  const active = activeTags.includes(tag);
2240
- return /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
2324
+ return /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
2241
2325
  "button",
2242
2326
  {
2243
2327
  type: "button",
2244
2328
  "aria-pressed": active,
2245
2329
  onClick: () => onToggleTag(tag),
2246
2330
  className: "cursor-pointer",
2247
- children: /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
2331
+ children: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
2248
2332
  Badge,
2249
2333
  {
2250
2334
  variant: "tag",
@@ -2257,7 +2341,7 @@ function ReportFilters({
2257
2341
  }
2258
2342
  ) }, tag);
2259
2343
  }),
2260
- tags.length > TAG_LIMIT ? /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
2344
+ tags.length > TAG_LIMIT ? /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
2261
2345
  "button",
2262
2346
  {
2263
2347
  type: "button",
@@ -2273,7 +2357,7 @@ function ReportFilters({
2273
2357
 
2274
2358
  // src/interactive/ReportToc.tsx
2275
2359
  var import_react15 = require("react");
2276
- var import_jsx_runtime42 = require("react/jsx-runtime");
2360
+ var import_jsx_runtime43 = require("react/jsx-runtime");
2277
2361
  var DOT = {
2278
2362
  passed: "bg-pass",
2279
2363
  failed: "bg-fail",
@@ -2302,11 +2386,11 @@ function TocContent({ onNavigate }) {
2302
2386
  return () => observer.disconnect();
2303
2387
  }, [scenarioIds]);
2304
2388
  if (report.features.length === 0) return null;
2305
- return /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("ul", { className: "flex list-none flex-col gap-4 pl-0", children: report.features.map((feature) => /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("li", { children: [
2306
- /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("p", { className: "mb-1.5 font-semibold leading-snug text-foreground", children: feature.title }),
2307
- /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("ul", { className: "flex list-none flex-col gap-0.5 pl-0", children: feature.scenarios.map((scenario) => {
2389
+ return /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("ul", { className: "flex list-none flex-col gap-4 pl-0", children: report.features.map((feature) => /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("li", { children: [
2390
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("p", { className: "mb-1.5 font-semibold leading-snug text-foreground", children: feature.title }),
2391
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("ul", { className: "flex list-none flex-col gap-0.5 pl-0", children: feature.scenarios.map((scenario) => {
2308
2392
  const active = activeId === scenario.id;
2309
- return /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(
2393
+ return /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)(
2310
2394
  "a",
2311
2395
  {
2312
2396
  href: `#${scenario.id}`,
@@ -2321,14 +2405,14 @@ function TocContent({ onNavigate }) {
2321
2405
  active ? "border-primary font-medium text-foreground" : "border-border text-muted-foreground"
2322
2406
  ),
2323
2407
  children: [
2324
- /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
2408
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
2325
2409
  "span",
2326
2410
  {
2327
2411
  "aria-hidden": true,
2328
2412
  className: cn("mt-1 size-1.5 shrink-0 rounded-full", DOT[scenario.status])
2329
2413
  }
2330
2414
  ),
2331
- /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("span", { className: "break-words", children: scenario.title })
2415
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: "break-words", children: scenario.title })
2332
2416
  ]
2333
2417
  }
2334
2418
  ) }, scenario.id);
@@ -2338,14 +2422,14 @@ function TocContent({ onNavigate }) {
2338
2422
  function ReportToc() {
2339
2423
  const report = useReport();
2340
2424
  if (report.features.length === 0) return null;
2341
- return /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(
2425
+ return /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)(
2342
2426
  "nav",
2343
2427
  {
2344
2428
  "aria-label": "Table of contents",
2345
2429
  className: "sticky top-4 hidden h-fit w-64 shrink-0 self-start text-xs lg:block",
2346
2430
  children: [
2347
- /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("p", { className: "mb-3 text-xs font-semibold uppercase tracking-wide text-muted-foreground", children: "Contents" }),
2348
- /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(TocContent, {})
2431
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("p", { className: "mb-3 text-xs font-semibold uppercase tracking-wide text-muted-foreground", children: "Contents" }),
2432
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(TocContent, {})
2349
2433
  ]
2350
2434
  }
2351
2435
  );
@@ -2355,31 +2439,31 @@ function ReportToc() {
2355
2439
  var import_react16 = require("react");
2356
2440
  var import_dialog = require("@base-ui/react/dialog");
2357
2441
  var import_lucide_react4 = require("lucide-react");
2358
- var import_jsx_runtime43 = require("react/jsx-runtime");
2442
+ var import_jsx_runtime44 = require("react/jsx-runtime");
2359
2443
  function ReportTocDrawer() {
2360
2444
  const report = useReport();
2361
2445
  const [open, setOpen] = (0, import_react16.useState)(false);
2362
2446
  if (report.features.length === 0) return null;
2363
- return /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)(import_dialog.Dialog.Root, { open, onOpenChange: setOpen, children: [
2364
- /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)(import_dialog.Dialog.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: [
2365
- /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(import_lucide_react4.ListIcon, { "aria-hidden": true }),
2447
+ return /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)(import_dialog.Dialog.Root, { open, onOpenChange: setOpen, children: [
2448
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)(import_dialog.Dialog.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: [
2449
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(import_lucide_react4.ListIcon, { "aria-hidden": true }),
2366
2450
  " Contents"
2367
2451
  ] }),
2368
- /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)(import_dialog.Dialog.Portal, { children: [
2369
- /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(import_dialog.Dialog.Backdrop, { className: "fixed inset-0 z-50 bg-black/50 transition-opacity duration-200 data-[ending-style]:opacity-0 data-[starting-style]:opacity-0" }),
2370
- /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)(import_dialog.Dialog.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: [
2371
- /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("div", { className: "flex items-center justify-between", children: [
2372
- /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(import_dialog.Dialog.Title, { className: "text-xs font-semibold tracking-wide text-muted-foreground uppercase", children: "Contents" }),
2373
- /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
2452
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)(import_dialog.Dialog.Portal, { children: [
2453
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(import_dialog.Dialog.Backdrop, { className: "fixed inset-0 z-50 bg-black/50 transition-opacity duration-200 data-[ending-style]:opacity-0 data-[starting-style]:opacity-0" }),
2454
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)(import_dialog.Dialog.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: [
2455
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("div", { className: "flex items-center justify-between", children: [
2456
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(import_dialog.Dialog.Title, { className: "text-xs font-semibold tracking-wide text-muted-foreground uppercase", children: "Contents" }),
2457
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
2374
2458
  import_dialog.Dialog.Close,
2375
2459
  {
2376
2460
  "aria-label": "Close contents",
2377
2461
  className: "cursor-pointer rounded p-1 text-muted-foreground hover:bg-muted hover:text-foreground [&_svg]:size-4",
2378
- children: /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(import_lucide_react4.XIcon, { "aria-hidden": true })
2462
+ children: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(import_lucide_react4.XIcon, { "aria-hidden": true })
2379
2463
  }
2380
2464
  )
2381
2465
  ] }),
2382
- /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(TocContent, { onNavigate: () => setOpen(false) })
2466
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(TocContent, { onNavigate: () => setOpen(false) })
2383
2467
  ] })
2384
2468
  ] })
2385
2469
  ] });
@@ -2434,14 +2518,14 @@ function useTheme() {
2434
2518
  }
2435
2519
 
2436
2520
  // src/interactive/ReportInteractive.tsx
2437
- var import_jsx_runtime44 = require("react/jsx-runtime");
2521
+ var import_jsx_runtime45 = require("react/jsx-runtime");
2438
2522
  function ReportInteractive(props) {
2439
2523
  const { report, className, title, dataTheme } = props;
2440
2524
  const result = unwrapReport(report);
2441
2525
  if (!result.ok) {
2442
- return /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(ReportErrorShell, { error: result.error, className, title, dataTheme });
2526
+ return /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(ReportErrorShell, { error: result.error, className, title, dataTheme });
2443
2527
  }
2444
- return /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(ReportInteractiveView, { ...props, report: result.data });
2528
+ return /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(ReportInteractiveView, { ...props, report: result.data });
2445
2529
  }
2446
2530
  var THEME_OPTIONS = [
2447
2531
  { value: "light", label: "Light", Icon: import_lucide_react5.Sun },
@@ -2449,7 +2533,7 @@ var THEME_OPTIONS = [
2449
2533
  { value: "dark", label: "Dark", Icon: import_lucide_react5.Moon }
2450
2534
  ];
2451
2535
  function ThemeSegment({ pref, onPref }) {
2452
- return /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
2536
+ return /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
2453
2537
  ToggleGroup,
2454
2538
  {
2455
2539
  size: "sm",
@@ -2459,7 +2543,7 @@ function ThemeSegment({ pref, onPref }) {
2459
2543
  if (next) onPref(next);
2460
2544
  },
2461
2545
  "aria-label": "Color theme",
2462
- children: THEME_OPTIONS.map(({ value, label, Icon }) => /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(ToggleGroupItem, { value, "aria-label": label, title: label, className: "px-2", children: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(Icon, {}) }, value))
2546
+ children: THEME_OPTIONS.map(({ value, label, Icon }) => /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(ToggleGroupItem, { value, "aria-label": label, title: label, className: "px-2", children: /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(Icon, {}) }, value))
2463
2547
  }
2464
2548
  );
2465
2549
  }
@@ -2581,13 +2665,13 @@ function ReportInteractiveView({
2581
2665
  const totalScenarios = report.summary.total;
2582
2666
  const matchedScenarios = filtered.summary.total;
2583
2667
  const showToc = !hideToc && totalScenarios > 3;
2584
- return /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(CollapseProvider, { value: collapse.api, children: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(ScenarioActionsProvider, { value: scenarioActions, children: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(ScenarioHistoryProvider, { value: scenarioHistory ?? null, children: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
2668
+ return /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(CollapseProvider, { value: collapse.api, children: /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(ScenarioActionsProvider, { value: scenarioActions, children: /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(ScenarioHistoryProvider, { value: scenarioHistory ?? null, children: /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
2585
2669
  ReportRoot,
2586
2670
  {
2587
2671
  report: filtered,
2588
2672
  customRenderers,
2589
2673
  renderers,
2590
- children: /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)(
2674
+ children: /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)(
2591
2675
  "main",
2592
2676
  {
2593
2677
  className: cn("es-report", "es-report-interactive", className),
@@ -2596,8 +2680,8 @@ function ReportInteractiveView({
2596
2680
  "data-theme": dataTheme,
2597
2681
  "data-detail-level": detail,
2598
2682
  children: [
2599
- /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("header", { className: "es-report-header", children: [
2600
- /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)(
2683
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("header", { className: "es-report-header", children: [
2684
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)(
2601
2685
  "div",
2602
2686
  {
2603
2687
  "data-es-navbar": true,
@@ -2606,9 +2690,9 @@ function ReportInteractiveView({
2606
2690
  hideHeader ? "justify-end" : "justify-between"
2607
2691
  ),
2608
2692
  children: [
2609
- hideHeader ? null : /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("h1", { className: "min-w-0", children: title ?? "Story Report" }),
2610
- /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("div", { className: "flex items-center gap-2", children: [
2611
- /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
2693
+ hideHeader ? null : /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("h1", { className: "min-w-0", children: title ?? "Story Report" }),
2694
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("div", { className: "flex items-center gap-2", children: [
2695
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
2612
2696
  ReportSearch,
2613
2697
  {
2614
2698
  ref: searchRef,
@@ -2618,16 +2702,16 @@ function ReportInteractiveView({
2618
2702
  totalCount: totalScenarios
2619
2703
  }
2620
2704
  ),
2621
- /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(ThemeSegment, { pref: themePref, onPref: setThemePref })
2705
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(ThemeSegment, { pref: themePref, onPref: setThemePref })
2622
2706
  ] })
2623
2707
  ]
2624
2708
  }
2625
2709
  ),
2626
- hideHeader ? null : /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)(import_jsx_runtime44.Fragment, { children: [
2627
- /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(ReportSummary, {}),
2628
- /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(ReportMeta, {})
2710
+ hideHeader ? null : /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)(import_jsx_runtime45.Fragment, { children: [
2711
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(ReportSummary, {}),
2712
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(ReportMeta, {})
2629
2713
  ] }),
2630
- /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
2714
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
2631
2715
  ReportFreshness,
2632
2716
  {
2633
2717
  lastRunMs: reportLastRunMs(report),
@@ -2635,8 +2719,8 @@ function ReportInteractiveView({
2635
2719
  staleAfterDays
2636
2720
  }
2637
2721
  ),
2638
- /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(ReportLastRunDelta, { history: scenarioHistory, report }),
2639
- /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
2722
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(ReportLastRunDelta, { history: scenarioHistory, report }),
2723
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
2640
2724
  ReportFilters,
2641
2725
  {
2642
2726
  statuses: statusOptions,
@@ -2647,14 +2731,14 @@ function ReportInteractiveView({
2647
2731
  onToggleTag: toggleTag
2648
2732
  }
2649
2733
  ),
2650
- /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("div", { className: "flex flex-wrap items-center gap-x-6 gap-y-2 border-t border-border/60 pt-3", children: [
2651
- showToc ? /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(ReportTocDrawer, {}) : null,
2652
- /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("div", { className: "flex items-center gap-2", children: [
2653
- /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(Switch, { id: expandId, checked: expandedAll, onCheckedChange: setExpanded }),
2654
- /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("label", { htmlFor: expandId, className: "cursor-pointer text-sm text-muted-foreground select-none", children: "Expand all" })
2734
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("div", { className: "flex flex-wrap items-center gap-x-6 gap-y-2 border-t border-border/60 pt-3", children: [
2735
+ showToc ? /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(ReportTocDrawer, {}) : null,
2736
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("div", { className: "flex items-center gap-2", children: [
2737
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(Switch, { id: expandId, checked: expandedAll, onCheckedChange: setExpanded }),
2738
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("label", { htmlFor: expandId, className: "cursor-pointer text-sm text-muted-foreground select-none", children: "Expand all" })
2655
2739
  ] }),
2656
- /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("div", { className: "flex items-center gap-2", children: [
2657
- /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
2740
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("div", { className: "flex items-center gap-2", children: [
2741
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
2658
2742
  Switch,
2659
2743
  {
2660
2744
  id: docsId,
@@ -2662,16 +2746,16 @@ function ReportInteractiveView({
2662
2746
  onCheckedChange: (checked) => setDetail(checked ? "full" : "minimal")
2663
2747
  }
2664
2748
  ),
2665
- /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("label", { htmlFor: docsId, className: "cursor-pointer text-sm text-muted-foreground select-none", children: "Show documentation" })
2749
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("label", { htmlFor: docsId, className: "cursor-pointer text-sm text-muted-foreground select-none", children: "Show documentation" })
2666
2750
  ] })
2667
2751
  ] })
2668
2752
  ] }),
2669
- /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(ReportFailureBanner, { failures }),
2670
- hasContent ? showToc ? /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("div", { className: "flex gap-6", children: [
2671
- /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(ReportToc, {}),
2672
- /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("div", { className: "flex min-w-0 flex-1 flex-col gap-4", children: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(ReportFeatureList, {}) })
2673
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("div", { className: "flex flex-col gap-4", children: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(ReportFeatureList, {}) }) : /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(ReportEmpty, { message: query ? "No scenarios match the search." : void 0 }),
2674
- /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
2753
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(ReportFailureBanner, { failures }),
2754
+ hasContent ? showToc ? /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("div", { className: "flex gap-6", children: [
2755
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(ReportToc, {}),
2756
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("div", { className: "flex min-w-0 flex-1 flex-col gap-4", children: /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(ReportFeatureList, {}) })
2757
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("div", { className: "flex flex-col gap-4", children: /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(ReportFeatureList, {}) }) : /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(ReportEmpty, { message: query ? "No scenarios match the search." : void 0 }),
2758
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
2675
2759
  "button",
2676
2760
  {
2677
2761
  type: "button",
@@ -2682,8 +2766,8 @@ function ReportInteractiveView({
2682
2766
  children: "?"
2683
2767
  }
2684
2768
  ),
2685
- /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(ReportShortcutsHelp, { open: helpOpen, onClose: () => setHelpOpen(false) }),
2686
- toast ? /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
2769
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(ReportShortcutsHelp, { open: helpOpen, onClose: () => setHelpOpen(false) }),
2770
+ toast ? /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
2687
2771
  "div",
2688
2772
  {
2689
2773
  role: "status",
@@ -2707,7 +2791,7 @@ var import_react20 = require("react");
2707
2791
 
2708
2792
  // src/components/doc/MermaidView.tsx
2709
2793
  var import_react19 = require("react");
2710
- var import_jsx_runtime45 = require("react/jsx-runtime");
2794
+ var import_jsx_runtime46 = require("react/jsx-runtime");
2711
2795
  function prefersDark(el) {
2712
2796
  const themed = el?.closest("[data-theme]");
2713
2797
  if (themed?.dataset.theme === "dark") return true;
@@ -2744,9 +2828,9 @@ function MermaidView({ entry, load }) {
2744
2828
  };
2745
2829
  }, [entry.code, load]);
2746
2830
  if (svg) {
2747
- return /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("figure", { ref, className: "my-3", children: [
2748
- entry.title ? /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("figcaption", { className: "mb-1.5 text-xs font-medium text-muted-foreground", children: entry.title }) : null,
2749
- /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
2831
+ return /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("figure", { ref, className: "my-3", children: [
2832
+ entry.title ? /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("figcaption", { className: "mb-1.5 text-xs font-medium text-muted-foreground", children: entry.title }) : null,
2833
+ /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
2750
2834
  "div",
2751
2835
  {
2752
2836
  role: "img",
@@ -2757,11 +2841,11 @@ function MermaidView({ entry, load }) {
2757
2841
  )
2758
2842
  ] });
2759
2843
  }
2760
- return /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(MermaidSource, { entry, ref });
2844
+ return /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(MermaidSource, { entry, ref });
2761
2845
  }
2762
2846
 
2763
2847
  // src/interactive/island-renderers.tsx
2764
- var import_jsx_runtime46 = require("react/jsx-runtime");
2848
+ var import_jsx_runtime47 = require("react/jsx-runtime");
2765
2849
  var HLJS_ESM = "https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/es/highlight.min.js";
2766
2850
  var MERMAID_ESM = "https://cdn.jsdelivr.net/npm/mermaid@10/dist/mermaid.esm.min.mjs";
2767
2851
  function cachedCdnModule(url) {
@@ -2795,13 +2879,13 @@ function CdnHighlightedCode({ entry }) {
2795
2879
  cancelled = true;
2796
2880
  };
2797
2881
  }, [entry.content, entry.lang]);
2798
- return /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(CodeFigure, { label: entry.label, children: html !== null ? /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
2882
+ return /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(CodeFigure, { label: entry.label, children: html !== null ? /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
2799
2883
  "code",
2800
2884
  {
2801
2885
  className: cn("hljs font-mono text-xs", entry.lang && `language-${entry.lang}`),
2802
2886
  dangerouslySetInnerHTML: { __html: html }
2803
2887
  }
2804
- ) : /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("code", { className: cn("font-mono text-xs", entry.lang && `language-${entry.lang}`), children: entry.content }) });
2888
+ ) : /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("code", { className: cn("font-mono text-xs", entry.lang && `language-${entry.lang}`), children: entry.content }) });
2805
2889
  }
2806
2890
  function buildIslandRenderers(opts) {
2807
2891
  const renderers = {};
@@ -2815,7 +2899,7 @@ function buildIslandRenderers(opts) {
2815
2899
  }
2816
2900
 
2817
2901
  // src/interactive/ReportInteractiveIsland.tsx
2818
- var import_jsx_runtime47 = require("react/jsx-runtime");
2902
+ var import_jsx_runtime48 = require("react/jsx-runtime");
2819
2903
  function ReportInteractiveIsland({
2820
2904
  report,
2821
2905
  title,
@@ -2829,7 +2913,7 @@ function ReportInteractiveIsland({
2829
2913
  () => buildIslandRenderers({ syntaxHighlighting, mermaid }),
2830
2914
  [syntaxHighlighting, mermaid]
2831
2915
  );
2832
- return /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
2916
+ return /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
2833
2917
  ReportInteractive,
2834
2918
  {
2835
2919
  report,