executable-stories-react 0.5.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.
@@ -241,7 +241,7 @@ function DocTable({ entry }) {
241
241
  entry.label ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("figcaption", { className: "mb-1.5 text-xs font-medium text-muted-foreground", children: entry.label }) : null,
242
242
  /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { tabIndex: 0, className: "overflow-x-auto rounded-md border border-border", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("table", { className: "w-full border-collapse text-sm", children: [
243
243
  /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("tr", { className: "bg-muted/50", children: entry.columns.map((c) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("th", { scope: "col", className: "border-b border-border px-3 py-2 text-left font-semibold", children: c }, c)) }) }),
244
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("tbody", { children: entry.rows.map((row, i) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("tr", { children: row.map((cell, j) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("td", { className: "border-b border-border px-3 py-2 text-foreground", children: cell }, j)) }, i)) })
244
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("tbody", { children: entry.rows.map((row, i) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("tr", { children: row.map((cell2, j) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("td", { className: "border-b border-border px-3 py-2 text-foreground", children: cell2 }, j)) }, i)) })
245
245
  ] }) })
246
246
  ] });
247
247
  }
@@ -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,
@@ -894,20 +977,118 @@ function useCollapseState(computeDefault) {
894
977
 
895
978
  // src/interactive/scenario-actions.tsx
896
979
  var import_react7 = require("react");
980
+
981
+ // ../executable-stories-core/dist/utils/scenario-markdown.js
982
+ function cell(value) {
983
+ return value.replaceAll("|", "\\|").replaceAll("\n", " ");
984
+ }
985
+ function stringify(value) {
986
+ if (typeof value === "string") return value;
987
+ try {
988
+ return JSON.stringify(value, null, 2) ?? String(value);
989
+ } catch {
990
+ return String(value);
991
+ }
992
+ }
993
+ function docEntryToMarkdown(entry) {
994
+ const lines = [];
995
+ switch (entry.kind) {
996
+ case "note":
997
+ lines.push(entry.text);
998
+ break;
999
+ case "tag":
1000
+ lines.push(entry.names.map((n) => `\`@${n}\``).join(" "));
1001
+ break;
1002
+ case "kv":
1003
+ lines.push(`**${entry.label}:** ${stringify(entry.value)}`);
1004
+ break;
1005
+ case "code":
1006
+ lines.push(`**${entry.label}**`, "", "```" + (entry.lang ?? ""), entry.content, "```");
1007
+ break;
1008
+ case "table": {
1009
+ lines.push(`**${entry.label}**`, "");
1010
+ lines.push(`| ${entry.columns.map(cell).join(" | ")} |`);
1011
+ lines.push(`| ${entry.columns.map(() => "---").join(" | ")} |`);
1012
+ for (const row of entry.rows) lines.push(`| ${row.map(cell).join(" | ")} |`);
1013
+ break;
1014
+ }
1015
+ case "link":
1016
+ lines.push(`[${entry.label}](${entry.url})`);
1017
+ break;
1018
+ case "section":
1019
+ lines.push(`### ${entry.title}`, "", entry.markdown);
1020
+ break;
1021
+ case "mermaid":
1022
+ if (entry.title) lines.push(`**${entry.title}**`, "");
1023
+ lines.push("```mermaid", entry.code, "```");
1024
+ break;
1025
+ case "screenshot":
1026
+ lines.push(`![${entry.alt ?? "screenshot"}](${entry.path})`);
1027
+ break;
1028
+ case "video":
1029
+ lines.push(`Video: ${entry.path}${entry.caption ? ` \u2014 ${entry.caption}` : ""}`);
1030
+ break;
1031
+ case "html": {
1032
+ const htmlTitle = entry.title ?? "Embedded HTML";
1033
+ if (entry.content) {
1034
+ lines.push(`**${htmlTitle}**`, "", "```html", entry.content, "```");
1035
+ } else if (entry.url) {
1036
+ lines.push(`[${htmlTitle}](${entry.url})`);
1037
+ } else {
1038
+ lines.push(`Embedded HTML: ${entry.path ?? "(inline)"}`);
1039
+ }
1040
+ break;
1041
+ }
1042
+ case "custom":
1043
+ lines.push(`**${entry.type}**`, "", "```json", stringify(entry.data), "```");
1044
+ break;
1045
+ }
1046
+ for (const child of entry.children ?? []) {
1047
+ lines.push("", ...docEntryToMarkdown(child));
1048
+ }
1049
+ return lines;
1050
+ }
1051
+ function stepLines(step, ordinal, full) {
1052
+ const status = step.status === "passed" ? "" : ` \u2014 **${step.status}**`;
1053
+ const lines = [`${ordinal}. **${step.keyword}** ${step.text}${status}`];
1054
+ if (!full) return lines;
1055
+ if (step.errorMessage) {
1056
+ lines.push(...step.errorMessage.split("\n").map((l) => ` > ${l}`));
1057
+ }
1058
+ for (const entry of step.docEntries) {
1059
+ lines.push("", ...docEntryToMarkdown(entry).map((l) => l === "" ? l : ` ${l}`));
1060
+ }
1061
+ return lines;
1062
+ }
1063
+ function scenarioToMarkdown(scenario, options = {}) {
1064
+ const { variant = "full", meta = [] } = options;
1065
+ const full = variant === "full";
1066
+ const lines = full ? [`# ${scenario.title}`, ""] : [`## ${scenario.title} _(${scenario.status})_`, ""];
1067
+ if (full && meta.length > 0) lines.push(...meta);
1068
+ if (scenario.steps.length > 0) {
1069
+ if (full) lines.push("", "## Steps", "");
1070
+ scenario.steps.forEach((step, i) => lines.push(...stepLines(step, i + 1, full)));
1071
+ }
1072
+ if (scenario.errorMessage) {
1073
+ if (full) lines.push("", "## Failure", "");
1074
+ else lines.push("");
1075
+ lines.push("```", scenario.errorMessage.trim(), "```");
1076
+ }
1077
+ if (full && scenario.docEntries.length > 0) {
1078
+ lines.push("", "## Docs", "");
1079
+ for (const entry of scenario.docEntries) lines.push(...docEntryToMarkdown(entry), "");
1080
+ }
1081
+ return lines.join("\n").replaceAll(/\n{3,}/g, "\n\n").trimEnd() + (full ? "\n" : "");
1082
+ }
1083
+
1084
+ // src/interactive/scenario-actions.tsx
897
1085
  var ScenarioActionsContext = (0, import_react7.createContext)(null);
898
1086
  var ScenarioActionsProvider = ScenarioActionsContext.Provider;
899
1087
  function useScenarioActions() {
900
1088
  return (0, import_react7.useContext)(ScenarioActionsContext);
901
1089
  }
902
- function scenarioToMarkdown(scenario) {
903
- const lines = [`## ${scenario.title} _(${scenario.status})_`, ""];
904
- for (const step of scenario.steps) {
905
- lines.push(`- **${step.keyword}** ${step.text}`);
906
- }
907
- if (scenario.errorMessage) {
908
- lines.push("", "```", scenario.errorMessage.trim(), "```");
909
- }
910
- return lines.join("\n");
1090
+ function scenarioToMarkdown2(scenario) {
1091
+ return scenarioToMarkdown(scenario, { variant: "compact" });
911
1092
  }
912
1093
  function scenarioToPrompt(scenario) {
913
1094
  const lines = [
@@ -935,9 +1116,9 @@ function scenarioPermalink(scenario) {
935
1116
 
936
1117
  // src/components/ui/card.tsx
937
1118
  var React2 = require("react");
938
- var import_jsx_runtime21 = require("react/jsx-runtime");
1119
+ var import_jsx_runtime22 = require("react/jsx-runtime");
939
1120
  function Card({ className, ...props }) {
940
- return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
1121
+ return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
941
1122
  "div",
942
1123
  {
943
1124
  "data-slot": "card",
@@ -950,7 +1131,7 @@ function Card({ className, ...props }) {
950
1131
  );
951
1132
  }
952
1133
  function CardHeader({ className, ...props }) {
953
- return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
1134
+ return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
954
1135
  "div",
955
1136
  {
956
1137
  "data-slot": "card-header",
@@ -963,7 +1144,7 @@ function CardHeader({ className, ...props }) {
963
1144
  );
964
1145
  }
965
1146
  function CardContent({ className, ...props }) {
966
- return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
1147
+ return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
967
1148
  "div",
968
1149
  {
969
1150
  "data-slot": "card-content",
@@ -977,13 +1158,13 @@ function CardContent({ className, ...props }) {
977
1158
  var React3 = require("react");
978
1159
  var import_menu = require("@base-ui/react/menu");
979
1160
  var import_lucide_react = require("lucide-react");
980
- var import_jsx_runtime22 = require("react/jsx-runtime");
1161
+ var import_jsx_runtime23 = require("react/jsx-runtime");
981
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";
982
1163
  function DropdownMenu(props) {
983
- 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 });
984
1165
  }
985
1166
  function DropdownMenuTrigger(props) {
986
- 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 });
987
1168
  }
988
1169
  function DropdownMenuContent({
989
1170
  className,
@@ -991,14 +1172,14 @@ function DropdownMenuContent({
991
1172
  sideOffset = 4,
992
1173
  ...props
993
1174
  }) {
994
- 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)(
995
1176
  import_menu.Menu.Positioner,
996
1177
  {
997
1178
  "data-slot": "dropdown-menu-positioner",
998
1179
  className: "z-50",
999
1180
  align,
1000
1181
  sideOffset,
1001
- children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
1182
+ children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
1002
1183
  import_menu.Menu.Popup,
1003
1184
  {
1004
1185
  "data-slot": "dropdown-menu-content",
@@ -1016,7 +1197,7 @@ function DropdownMenuItem({
1016
1197
  className,
1017
1198
  ...props
1018
1199
  }) {
1019
- return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
1200
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
1020
1201
  import_menu.Menu.Item,
1021
1202
  {
1022
1203
  "data-slot": "dropdown-menu-item",
@@ -1028,7 +1209,7 @@ function DropdownMenuItem({
1028
1209
 
1029
1210
  // src/components/ReportScenario.tsx
1030
1211
  var import_lucide_react2 = require("lucide-react");
1031
- var import_jsx_runtime23 = require("react/jsx-runtime");
1212
+ var import_jsx_runtime24 = require("react/jsx-runtime");
1032
1213
  var STATUS_META = {
1033
1214
  passed: { label: "Passed", glyph: "\u2713", glyphColor: "text-pass", badgeVariant: "passed", showPill: false },
1034
1215
  failed: { label: "Failed", glyph: "\u2717", glyphColor: "text-fail", badgeVariant: "failed", showPill: true },
@@ -1044,7 +1225,7 @@ function ReportScenario({ scenario, hideTitle = false }) {
1044
1225
  const collapsible = collapse !== null && !hideTitle;
1045
1226
  const collapsed = collapsible ? collapse.isCollapsed(scenario.id) : false;
1046
1227
  const actions = useScenarioActions();
1047
- return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(
1228
+ return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
1048
1229
  Card,
1049
1230
  {
1050
1231
  id: scenario.id,
@@ -1052,10 +1233,10 @@ function ReportScenario({ scenario, hideTitle = false }) {
1052
1233
  ...hideTitle ? { "aria-label": `${scenario.title}, ${label}` } : { "aria-labelledby": titleId },
1053
1234
  className: "gap-0 py-0",
1054
1235
  children: [
1055
- /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(CardHeader, { className: "px-4 py-3", children: [
1056
- /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: cn("flex items-start gap-4", hideTitle ? "justify-end" : "justify-between"), children: [
1057
- hideTitle ? null : /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("h3", { id: titleId, className: "flex items-center gap-2 text-sm font-medium text-foreground", children: [
1058
- 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)(
1059
1240
  "button",
1060
1241
  {
1061
1242
  type: "button",
@@ -1064,49 +1245,49 @@ function ReportScenario({ scenario, hideTitle = false }) {
1064
1245
  "aria-controls": bodyId,
1065
1246
  "aria-label": `Toggle ${scenario.title}`,
1066
1247
  className: "shrink-0 cursor-pointer text-muted-foreground hover:text-foreground",
1067
- 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" })
1068
1249
  }
1069
1250
  ) : null,
1070
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { "aria-hidden": true, className: cn("text-sm leading-none", meta.glyphColor), children: meta.glyph }),
1071
- /* @__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 })
1072
1253
  ] }),
1073
- /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex shrink-0 items-center gap-2", children: [
1074
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(ScenarioRunHistory, { scenarioId: scenario.id }),
1075
- 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,
1076
- 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}` }),
1077
- actions ? /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(DropdownMenu, { children: [
1078
- /* @__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)(
1079
1260
  DropdownMenuTrigger,
1080
1261
  {
1081
1262
  "aria-label": `Actions for ${scenario.title}`,
1082
1263
  className: "cursor-pointer rounded p-1 text-muted-foreground hover:bg-muted hover:text-foreground [&_svg]:size-4",
1083
- 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 })
1084
1265
  }
1085
1266
  ),
1086
- /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(DropdownMenuContent, { align: "end", children: [
1087
- /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(DropdownMenuItem, { onClick: () => actions.copyLink(scenario), children: [
1088
- /* @__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, {}),
1089
1270
  " Copy link"
1090
1271
  ] }),
1091
- /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(DropdownMenuItem, { onClick: () => actions.copyMarkdown(scenario), children: [
1092
- /* @__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, {}),
1093
1274
  " Copy as Markdown"
1094
1275
  ] }),
1095
- /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(DropdownMenuItem, { onClick: () => actions.copyPrompt(scenario), children: [
1096
- /* @__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, {}),
1097
1278
  " Explain with AI"
1098
1279
  ] })
1099
1280
  ] })
1100
1281
  ] }) : null
1101
1282
  ] })
1102
1283
  ] }),
1103
- 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: [
1104
- 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}`)),
1105
- (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}`))
1106
1287
  ] }) : null
1107
1288
  ] }),
1108
- /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(CardContent, { id: bodyId, hidden: collapsed, className: "px-4 pt-0 pb-4", children: [
1109
- 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)(
1110
1291
  "pre",
1111
1292
  {
1112
1293
  role: "alert",
@@ -1114,10 +1295,11 @@ function ReportScenario({ scenario, hideTitle = false }) {
1114
1295
  children: scenario.errorMessage
1115
1296
  }
1116
1297
  ) : null,
1117
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(ReportSteps, { scenario }),
1118
- 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,
1119
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(ReportAttachments, { attachments: scenario.attachments }),
1120
- /* @__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 })
1121
1303
  ] })
1122
1304
  ]
1123
1305
  }
@@ -1125,13 +1307,13 @@ function ReportScenario({ scenario, hideTitle = false }) {
1125
1307
  }
1126
1308
 
1127
1309
  // src/components/ReportScenarioList.tsx
1128
- var import_jsx_runtime24 = require("react/jsx-runtime");
1310
+ var import_jsx_runtime25 = require("react/jsx-runtime");
1129
1311
  function ReportScenarioList({ feature }) {
1130
- 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)) });
1131
1313
  }
1132
1314
 
1133
1315
  // src/components/ReportFeature.tsx
1134
- var import_jsx_runtime25 = require("react/jsx-runtime");
1316
+ var import_jsx_runtime26 = require("react/jsx-runtime");
1135
1317
  function ReportFeature({ feature }) {
1136
1318
  const titleId = `${feature.id}-title`;
1137
1319
  const bodyId = `${feature.id}-body`;
@@ -1142,7 +1324,7 @@ function ReportFeature({ feature }) {
1142
1324
  return (
1143
1325
  // Suite = a section heading + a divider, NOT another bordered card. Drops a
1144
1326
  // layer of nesting so the scenario cards below read as the primary unit.
1145
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
1327
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(
1146
1328
  "section",
1147
1329
  {
1148
1330
  id: feature.id,
@@ -1150,9 +1332,9 @@ function ReportFeature({ feature }) {
1150
1332
  "aria-labelledby": titleId,
1151
1333
  className: "flex flex-col gap-3",
1152
1334
  children: [
1153
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex items-end justify-between gap-4 border-b border-border pb-2", children: [
1154
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "min-w-0", children: [
1155
- /* @__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)(
1156
1338
  "button",
1157
1339
  {
1158
1340
  type: "button",
@@ -1161,31 +1343,31 @@ function ReportFeature({ feature }) {
1161
1343
  "aria-controls": bodyId,
1162
1344
  className: "flex w-full cursor-pointer items-center gap-2 text-left hover:text-foreground/80",
1163
1345
  children: [
1164
- /* @__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" }),
1165
- /* @__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 })
1166
1348
  ]
1167
1349
  }
1168
1350
  ) : feature.title }),
1169
- /* @__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 })
1170
1352
  ] }),
1171
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
1353
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(
1172
1354
  "p",
1173
1355
  {
1174
1356
  className: "flex shrink-0 items-center gap-1.5 text-xs text-muted-foreground",
1175
1357
  "aria-label": `${s.passed} passed, ${s.failed} failed, ${skipped} skipped`,
1176
1358
  children: [
1177
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("span", { children: [
1359
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("span", { children: [
1178
1360
  s.passed,
1179
1361
  " passed"
1180
1362
  ] }),
1181
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { "aria-hidden": true, children: "\xB7" }),
1182
- /* @__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: [
1183
1365
  s.failed,
1184
1366
  " failed"
1185
1367
  ] }),
1186
- skipped > 0 ? /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(import_jsx_runtime25.Fragment, { children: [
1187
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { "aria-hidden": true, children: "\xB7" }),
1188
- /* @__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: [
1189
1371
  skipped,
1190
1372
  " skipped"
1191
1373
  ] })
@@ -1194,7 +1376,7 @@ function ReportFeature({ feature }) {
1194
1376
  }
1195
1377
  )
1196
1378
  ] }),
1197
- /* @__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 }) })
1198
1380
  ]
1199
1381
  }
1200
1382
  )
@@ -1202,17 +1384,17 @@ function ReportFeature({ feature }) {
1202
1384
  }
1203
1385
 
1204
1386
  // src/components/ReportFeatureList.tsx
1205
- var import_jsx_runtime26 = require("react/jsx-runtime");
1387
+ var import_jsx_runtime27 = require("react/jsx-runtime");
1206
1388
  function ReportFeatureList() {
1207
1389
  const report = useReport();
1208
- 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)) });
1209
1391
  }
1210
1392
 
1211
1393
  // src/components/ui/empty.tsx
1212
1394
  var import_class_variance_authority2 = require("class-variance-authority");
1213
- var import_jsx_runtime27 = require("react/jsx-runtime");
1395
+ var import_jsx_runtime28 = require("react/jsx-runtime");
1214
1396
  function Empty({ className, ...props }) {
1215
- return /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
1397
+ return /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
1216
1398
  "div",
1217
1399
  {
1218
1400
  "data-slot": "empty",
@@ -1225,7 +1407,7 @@ function Empty({ className, ...props }) {
1225
1407
  );
1226
1408
  }
1227
1409
  function EmptyHeader({ className, ...props }) {
1228
- return /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
1410
+ return /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
1229
1411
  "div",
1230
1412
  {
1231
1413
  "data-slot": "empty-header",
@@ -1252,7 +1434,7 @@ var emptyMediaVariants = (0, import_class_variance_authority2.cva)(
1252
1434
  }
1253
1435
  );
1254
1436
  function EmptyTitle({ className, ...props }) {
1255
- return /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
1437
+ return /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
1256
1438
  "div",
1257
1439
  {
1258
1440
  "data-slot": "empty-title",
@@ -1263,16 +1445,16 @@ function EmptyTitle({ className, ...props }) {
1263
1445
  }
1264
1446
 
1265
1447
  // src/components/ReportEmpty.tsx
1266
- var import_jsx_runtime28 = require("react/jsx-runtime");
1448
+ var import_jsx_runtime29 = require("react/jsx-runtime");
1267
1449
  function ReportEmpty({ message }) {
1268
- 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." }) }) });
1269
1451
  }
1270
1452
 
1271
1453
  // src/components/ReportSummary.tsx
1272
- var import_jsx_runtime29 = require("react/jsx-runtime");
1454
+ var import_jsx_runtime30 = require("react/jsx-runtime");
1273
1455
  function ReportSummary({ className }) {
1274
1456
  const report = useReport();
1275
- return /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
1457
+ return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
1276
1458
  ReportSummaryView,
1277
1459
  {
1278
1460
  summary: report.summary,
@@ -1298,7 +1480,7 @@ function ReportSummaryView({ summary, className, ariaLabel }) {
1298
1480
  if (summary.pending > 0) {
1299
1481
  cards.push({ status: "pending", label: "Pending", value: summary.pending });
1300
1482
  }
1301
- return /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
1483
+ return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
1302
1484
  "dl",
1303
1485
  {
1304
1486
  className: cn(
@@ -1311,17 +1493,17 @@ function ReportSummaryView({ summary, className, ariaLabel }) {
1311
1493
  "aria-label": ariaLabel,
1312
1494
  children: cards.map((c) => {
1313
1495
  const tone = TONE[c.status];
1314
- return /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(
1496
+ return /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(
1315
1497
  "div",
1316
1498
  {
1317
1499
  "data-status": c.status,
1318
1500
  className: "rounded-lg border bg-card px-4 py-3",
1319
1501
  children: [
1320
- /* @__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: [
1321
- /* @__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" }),
1322
1504
  c.label
1323
1505
  ] }),
1324
- /* @__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 })
1325
1507
  ]
1326
1508
  },
1327
1509
  c.status
@@ -1381,7 +1563,7 @@ function prUrl(ci) {
1381
1563
  }
1382
1564
 
1383
1565
  // src/components/ReportMeta.tsx
1384
- var import_jsx_runtime30 = require("react/jsx-runtime");
1566
+ var import_jsx_runtime31 = require("react/jsx-runtime");
1385
1567
  function ReportMeta() {
1386
1568
  const report = useReport();
1387
1569
  const items = [];
@@ -1404,13 +1586,13 @@ function ReportMeta() {
1404
1586
  const short = sha.slice(0, 8);
1405
1587
  items.push({
1406
1588
  label: "Commit",
1407
- 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
1408
1590
  });
1409
1591
  }
1410
1592
  if (report.ci) {
1411
1593
  items.push({
1412
1594
  label: "CI",
1413
- 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: [
1414
1596
  ciDisplayName(report.ci.name),
1415
1597
  report.ci.buildNumber ? ` #${report.ci.buildNumber}` : ""
1416
1598
  ] }) : `${ciDisplayName(report.ci.name)}${report.ci.buildNumber ? ` #${report.ci.buildNumber}` : ""}`
@@ -1421,7 +1603,7 @@ function ReportMeta() {
1421
1603
  const label = `#${report.ci.prNumber}`;
1422
1604
  items.push({
1423
1605
  label: "PR",
1424
- 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
1425
1607
  });
1426
1608
  }
1427
1609
  if (items.length === 0) return null;
@@ -1429,50 +1611,50 @@ function ReportMeta() {
1429
1611
  // Run metadata is useful but secondary to "what failed" — tuck it into a
1430
1612
  // collapsed disclosure so it doesn't push the result down. Native <details>
1431
1613
  // so it works with no JS (the SSR/no-hydration report still toggles).
1432
- /* @__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: [
1433
- /* @__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: [
1434
- /* @__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" }),
1435
1617
  "Run details"
1436
1618
  ] }),
1437
- /* @__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: [
1438
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("dt", { className: "font-medium", children: item.label }),
1439
- /* @__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 })
1440
1622
  ] }, item.label)) })
1441
1623
  ] })
1442
1624
  );
1443
1625
  }
1444
1626
 
1445
1627
  // src/components/ReportSchemaError.tsx
1446
- var import_jsx_runtime31 = require("react/jsx-runtime");
1628
+ var import_jsx_runtime32 = require("react/jsx-runtime");
1447
1629
  function ReportSchemaError({ error }) {
1448
- return /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("section", { className: "es-schema-error", role: "alert", "aria-live": "assertive", children: [
1449
- /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("p", { children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("strong", { children: "Report could not be displayed." }) }),
1450
- /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("p", { children: error.message }),
1451
- 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: [
1452
1634
  "The report bundle is newer than this version of ",
1453
- /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("code", { children: "executable-stories-react" }),
1635
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("code", { children: "executable-stories-react" }),
1454
1636
  ". Upgrade the package, or regenerate the report with an older formatters CLI."
1455
1637
  ] }) : null,
1456
- error.issues && error.issues.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("details", { children: [
1457
- /* @__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: [
1458
1640
  error.issues.length,
1459
1641
  " validation issue",
1460
1642
  error.issues.length === 1 ? "" : "s"
1461
1643
  ] }),
1462
- /* @__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") })
1463
1645
  ] }) : null
1464
1646
  ] });
1465
1647
  }
1466
1648
 
1467
1649
  // src/components/ReportShell.tsx
1468
- var import_jsx_runtime32 = require("react/jsx-runtime");
1650
+ var import_jsx_runtime33 = require("react/jsx-runtime");
1469
1651
  function ReportErrorShell({
1470
1652
  error,
1471
1653
  className,
1472
1654
  title,
1473
1655
  dataTheme
1474
1656
  }) {
1475
- 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 }) });
1476
1658
  }
1477
1659
 
1478
1660
  // src/interactive/ReportInteractive.tsx
@@ -1481,12 +1663,12 @@ var import_lucide_react5 = require("lucide-react");
1481
1663
  // src/components/ui/switch.tsx
1482
1664
  var React4 = require("react");
1483
1665
  var import_switch = require("@base-ui/react/switch");
1484
- var import_jsx_runtime33 = require("react/jsx-runtime");
1666
+ var import_jsx_runtime34 = require("react/jsx-runtime");
1485
1667
  function Switch({
1486
1668
  className,
1487
1669
  ...props
1488
1670
  }) {
1489
- return /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
1671
+ return /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
1490
1672
  import_switch.Switch.Root,
1491
1673
  {
1492
1674
  "data-slot": "switch",
@@ -1495,7 +1677,7 @@ function Switch({
1495
1677
  className
1496
1678
  ),
1497
1679
  ...props,
1498
- children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
1680
+ children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
1499
1681
  import_switch.Switch.Thumb,
1500
1682
  {
1501
1683
  "data-slot": "switch-thumb",
@@ -1511,7 +1693,7 @@ var React5 = __toESM(require("react"), 1);
1511
1693
  var import_toggle_group = require("@base-ui/react/toggle-group");
1512
1694
  var import_toggle = require("@base-ui/react/toggle");
1513
1695
  var import_class_variance_authority3 = require("class-variance-authority");
1514
- var import_jsx_runtime34 = require("react/jsx-runtime");
1696
+ var import_jsx_runtime35 = require("react/jsx-runtime");
1515
1697
  var toggleItemVariants = (0, import_class_variance_authority3.cva)(
1516
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",
1517
1699
  {
@@ -1533,13 +1715,13 @@ function ToggleGroup({
1533
1715
  children,
1534
1716
  ...props
1535
1717
  }) {
1536
- return /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
1718
+ return /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
1537
1719
  import_toggle_group.ToggleGroup,
1538
1720
  {
1539
1721
  "data-slot": "toggle-group",
1540
1722
  className: cn("flex w-fit items-center gap-0.5 rounded-lg bg-muted p-0.5", className),
1541
1723
  ...props,
1542
- 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 })
1543
1725
  }
1544
1726
  );
1545
1727
  }
@@ -1550,7 +1732,7 @@ function ToggleGroupItem({
1550
1732
  ...props
1551
1733
  }) {
1552
1734
  const context = React5.useContext(ToggleGroupContext);
1553
- return /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
1735
+ return /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
1554
1736
  import_toggle.Toggle,
1555
1737
  {
1556
1738
  "data-slot": "toggle-group-item",
@@ -1567,9 +1749,9 @@ var import_lucide_react3 = require("lucide-react");
1567
1749
 
1568
1750
  // src/components/ui/input.tsx
1569
1751
  var React6 = require("react");
1570
- var import_jsx_runtime35 = require("react/jsx-runtime");
1752
+ var import_jsx_runtime36 = require("react/jsx-runtime");
1571
1753
  function Input({ className, type, ...props }) {
1572
- return /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
1754
+ return /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
1573
1755
  "input",
1574
1756
  {
1575
1757
  type,
@@ -1586,7 +1768,7 @@ function Input({ className, type, ...props }) {
1586
1768
  }
1587
1769
 
1588
1770
  // src/interactive/ReportSearch.tsx
1589
- var import_jsx_runtime36 = require("react/jsx-runtime");
1771
+ var import_jsx_runtime37 = require("react/jsx-runtime");
1590
1772
  var ReportSearch = (0, import_react8.forwardRef)(
1591
1773
  function ReportSearch2(props, ref) {
1592
1774
  const {
@@ -1608,17 +1790,17 @@ var ReportSearch = (0, import_react8.forwardRef)(
1608
1790
  e.preventDefault();
1609
1791
  }
1610
1792
  }
1611
- return /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("div", { className: cn("es-search flex flex-col gap-1", className), children: [
1612
- /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("label", { htmlFor: inputId, className: "sr-only", children: "Search" }),
1613
- /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("div", { className: "relative w-full sm:w-72", children: [
1614
- /* @__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)(
1615
1797
  import_lucide_react3.Search,
1616
1798
  {
1617
1799
  "aria-hidden": true,
1618
1800
  className: "pointer-events-none absolute top-1/2 left-2.5 size-4 -translate-y-1/2 text-muted-foreground"
1619
1801
  }
1620
1802
  ),
1621
- /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
1803
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
1622
1804
  Input,
1623
1805
  {
1624
1806
  ref,
@@ -1635,7 +1817,7 @@ var ReportSearch = (0, import_react8.forwardRef)(
1635
1817
  }
1636
1818
  )
1637
1819
  ] }),
1638
- showCounts ? /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(
1820
+ showCounts ? /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)(
1639
1821
  "span",
1640
1822
  {
1641
1823
  className: "text-xs tabular-nums text-muted-foreground",
@@ -1676,7 +1858,7 @@ function scrollToScenarioId(scenarioId, options = {}) {
1676
1858
  }
1677
1859
 
1678
1860
  // src/interactive/ReportFailureBanner.tsx
1679
- var import_jsx_runtime37 = require("react/jsx-runtime");
1861
+ var import_jsx_runtime38 = require("react/jsx-runtime");
1680
1862
  function ReportFailureBanner({ failures }) {
1681
1863
  const first = failures[0];
1682
1864
  const jumpToFirst = (0, import_react9.useCallback)(() => {
@@ -1684,7 +1866,7 @@ function ReportFailureBanner({ failures }) {
1684
1866
  scrollToScenarioId(first.scenarioId);
1685
1867
  }, [first]);
1686
1868
  if (failures.length === 0) return null;
1687
- return /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)(
1869
+ return /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)(
1688
1870
  "div",
1689
1871
  {
1690
1872
  className: "es-failure-banner",
@@ -1692,13 +1874,13 @@ function ReportFailureBanner({ failures }) {
1692
1874
  "aria-live": "polite",
1693
1875
  "aria-label": "Failure summary",
1694
1876
  children: [
1695
- /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("span", { className: "es-failure-banner-text", children: [
1696
- /* @__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 }),
1697
1879
  " ",
1698
1880
  "failure",
1699
1881
  failures.length === 1 ? "" : "s"
1700
1882
  ] }),
1701
- /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
1883
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
1702
1884
  "button",
1703
1885
  {
1704
1886
  type: "button",
@@ -1715,7 +1897,7 @@ function ReportFailureBanner({ failures }) {
1715
1897
 
1716
1898
  // src/interactive/ReportFreshness.tsx
1717
1899
  var import_react10 = require("react");
1718
- var import_jsx_runtime38 = require("react/jsx-runtime");
1900
+ var import_jsx_runtime39 = require("react/jsx-runtime");
1719
1901
  function ReportFreshness({ lastRunMs, ciUrl, staleAfterDays, nowMs }) {
1720
1902
  const [now, setNow] = (0, import_react10.useState)(nowMs);
1721
1903
  (0, import_react10.useEffect)(() => {
@@ -1723,7 +1905,7 @@ function ReportFreshness({ lastRunMs, ciUrl, staleAfterDays, nowMs }) {
1723
1905
  }, [nowMs]);
1724
1906
  if (lastRunMs === void 0 || now === void 0) return null;
1725
1907
  const age = formatRelativeAge(lastRunMs, now);
1726
- const runLink = ciUrl ? /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
1908
+ const runLink = ciUrl ? /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
1727
1909
  "a",
1728
1910
  {
1729
1911
  href: ciUrl,
@@ -1734,9 +1916,9 @@ function ReportFreshness({ lastRunMs, ciUrl, staleAfterDays, nowMs }) {
1734
1916
  }
1735
1917
  ) : null;
1736
1918
  if (isReportStale(lastRunMs, staleAfterDays, now)) {
1737
- return /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("div", { className: "es-stale-banner", role: "status", "aria-label": "Report freshness", children: [
1738
- /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("span", { children: [
1739
- /* @__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: [
1740
1922
  "Last verified ",
1741
1923
  age,
1742
1924
  "."
@@ -1746,10 +1928,10 @@ function ReportFreshness({ lastRunMs, ciUrl, staleAfterDays, nowMs }) {
1746
1928
  runLink
1747
1929
  ] });
1748
1930
  }
1749
- 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: [
1750
1932
  "Verified ",
1751
1933
  age,
1752
- 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: [
1753
1935
  " \xB7 ",
1754
1936
  runLink
1755
1937
  ] }) : null
@@ -1757,15 +1939,15 @@ function ReportFreshness({ lastRunMs, ciUrl, staleAfterDays, nowMs }) {
1757
1939
  }
1758
1940
 
1759
1941
  // src/interactive/ReportLastRunDelta.tsx
1760
- var import_jsx_runtime39 = require("react/jsx-runtime");
1942
+ var import_jsx_runtime40 = require("react/jsx-runtime");
1761
1943
  var MAX_LINKS = 5;
1762
1944
  function ScenarioLinks({ scenarios, tone }) {
1763
- return /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)(import_jsx_runtime39.Fragment, { children: [
1764
- 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: [
1765
1947
  i > 0 ? ", " : "",
1766
- /* @__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 })
1767
1949
  ] }, s.id)),
1768
- 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: [
1769
1951
  " and ",
1770
1952
  scenarios.length - MAX_LINKS,
1771
1953
  " more"
@@ -1782,23 +1964,23 @@ function ReportLastRunDelta({
1782
1964
  if (!delta) return null;
1783
1965
  const { newlyFailing, newlyPassing, added } = delta;
1784
1966
  if (newlyFailing.length === 0 && newlyPassing.length === 0 && added.length === 0) {
1785
- 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." });
1786
1968
  }
1787
- return /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("p", { className: "text-xs text-muted-foreground", "data-testid": "es-last-run-delta", children: [
1788
- /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("span", { className: "font-medium text-foreground", children: "Since last run:" }),
1789
- 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: [
1790
1972
  newlyFailing.length,
1791
1973
  " newly failing (",
1792
- /* @__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" }),
1793
1975
  ")"
1794
1976
  ] }) : null,
1795
- 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: [
1796
1978
  newlyPassing.length,
1797
1979
  " fixed (",
1798
- /* @__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" }),
1799
1981
  ")"
1800
1982
  ] }) : null,
1801
- 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: [
1802
1984
  added.length,
1803
1985
  " new"
1804
1986
  ] }) : null
@@ -1862,7 +2044,7 @@ function Button({
1862
2044
  }
1863
2045
 
1864
2046
  // src/interactive/ReportShortcutsHelp.tsx
1865
- var import_jsx_runtime40 = require("react/jsx-runtime");
2047
+ var import_jsx_runtime41 = require("react/jsx-runtime");
1866
2048
  var SHORTCUTS = [
1867
2049
  { keys: "/", description: "Focus search" },
1868
2050
  { keys: "f", description: "Jump to next failure" },
@@ -1874,9 +2056,9 @@ var SHORTCUTS = [
1874
2056
  ];
1875
2057
  function Keys({ keys }) {
1876
2058
  const parts = keys.split(" ");
1877
- 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: [
1878
- i > 0 ? /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("span", { className: "text-xs text-muted-foreground", children: "+" }) : null,
1879
- /* @__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 })
1880
2062
  ] }, k)) });
1881
2063
  }
1882
2064
  function ReportShortcutsHelp({ open, onClose }) {
@@ -1887,7 +2069,7 @@ function ReportShortcutsHelp({ open, onClose }) {
1887
2069
  if (open && !dialog.open) dialog.showModal();
1888
2070
  else if (!open && dialog.open) dialog.close();
1889
2071
  }, [open]);
1890
- return /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(
2072
+ return /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)(
1891
2073
  "dialog",
1892
2074
  {
1893
2075
  ref: dialogRef,
@@ -1895,12 +2077,12 @@ function ReportShortcutsHelp({ open, onClose }) {
1895
2077
  "aria-label": "Keyboard shortcuts",
1896
2078
  onClose,
1897
2079
  children: [
1898
- /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("h2", { className: "text-base font-semibold", children: "Keyboard shortcuts" }),
1899
- /* @__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: [
1900
- /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("dt", { className: "justify-self-start", children: /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(Keys, { keys: s.keys }) }),
1901
- /* @__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 })
1902
2084
  ] }, s.keys)) }),
1903
- /* @__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" }) })
1904
2086
  ]
1905
2087
  }
1906
2088
  );
@@ -2072,9 +2254,36 @@ function listFailures(report) {
2072
2254
  return out;
2073
2255
  }
2074
2256
 
2257
+ // src/interactive/triage-default.ts
2258
+ function needsAttention(status) {
2259
+ return status === "failed";
2260
+ }
2261
+ function defaultCollapsedIds(report) {
2262
+ const collapsed = /* @__PURE__ */ new Set();
2263
+ if (report.summary.failed === 0) return collapsed;
2264
+ for (const feature of report.features) {
2265
+ const featureHasFailure = feature.scenarios.some((s) => needsAttention(s.status));
2266
+ if (!featureHasFailure) collapsed.add(feature.id);
2267
+ for (const scenario of feature.scenarios) {
2268
+ if (!needsAttention(scenario.status)) collapsed.add(scenario.id);
2269
+ }
2270
+ }
2271
+ return collapsed;
2272
+ }
2273
+ function failuresFirst(report) {
2274
+ if (report.summary.failed === 0) return report;
2275
+ const withFailures = [];
2276
+ const rest = [];
2277
+ for (const feature of report.features) {
2278
+ (feature.scenarios.some((s) => needsAttention(s.status)) ? withFailures : rest).push(feature);
2279
+ }
2280
+ if (withFailures.length === 0) return report;
2281
+ return { ...report, features: [...withFailures, ...rest] };
2282
+ }
2283
+
2075
2284
  // src/interactive/ReportFilters.tsx
2076
2285
  var import_react14 = require("react");
2077
- var import_jsx_runtime41 = require("react/jsx-runtime");
2286
+ var import_jsx_runtime42 = require("react/jsx-runtime");
2078
2287
  var TAG_LIMIT = 12;
2079
2288
  function ReportFilters({
2080
2289
  statuses,
@@ -2088,10 +2297,10 @@ function ReportFilters({
2088
2297
  if (statuses.length === 0 && tags.length === 0) return null;
2089
2298
  const tagsCollapsed = tags.length > TAG_LIMIT && !showAllTags;
2090
2299
  const visibleTags = tagsCollapsed ? tags.slice(0, TAG_LIMIT) : tags;
2091
- return /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { className: "flex flex-col gap-2", children: [
2092
- 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) => {
2093
2302
  const active = status === opt.key;
2094
- return /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)(
2303
+ return /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(
2095
2304
  "button",
2096
2305
  {
2097
2306
  type: "button",
@@ -2103,23 +2312,23 @@ function ReportFilters({
2103
2312
  ),
2104
2313
  children: [
2105
2314
  opt.label,
2106
- /* @__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 })
2107
2316
  ]
2108
2317
  },
2109
2318
  opt.key
2110
2319
  );
2111
2320
  }) }) : null,
2112
- 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: [
2113
2322
  visibleTags.map((tag) => {
2114
2323
  const active = activeTags.includes(tag);
2115
- 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)(
2116
2325
  "button",
2117
2326
  {
2118
2327
  type: "button",
2119
2328
  "aria-pressed": active,
2120
2329
  onClick: () => onToggleTag(tag),
2121
2330
  className: "cursor-pointer",
2122
- children: /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
2331
+ children: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
2123
2332
  Badge,
2124
2333
  {
2125
2334
  variant: "tag",
@@ -2132,7 +2341,7 @@ function ReportFilters({
2132
2341
  }
2133
2342
  ) }, tag);
2134
2343
  }),
2135
- 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)(
2136
2345
  "button",
2137
2346
  {
2138
2347
  type: "button",
@@ -2148,7 +2357,7 @@ function ReportFilters({
2148
2357
 
2149
2358
  // src/interactive/ReportToc.tsx
2150
2359
  var import_react15 = require("react");
2151
- var import_jsx_runtime42 = require("react/jsx-runtime");
2360
+ var import_jsx_runtime43 = require("react/jsx-runtime");
2152
2361
  var DOT = {
2153
2362
  passed: "bg-pass",
2154
2363
  failed: "bg-fail",
@@ -2177,11 +2386,11 @@ function TocContent({ onNavigate }) {
2177
2386
  return () => observer.disconnect();
2178
2387
  }, [scenarioIds]);
2179
2388
  if (report.features.length === 0) return null;
2180
- 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: [
2181
- /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("p", { className: "mb-1.5 font-semibold leading-snug text-foreground", children: feature.title }),
2182
- /* @__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) => {
2183
2392
  const active = activeId === scenario.id;
2184
- 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)(
2185
2394
  "a",
2186
2395
  {
2187
2396
  href: `#${scenario.id}`,
@@ -2196,14 +2405,14 @@ function TocContent({ onNavigate }) {
2196
2405
  active ? "border-primary font-medium text-foreground" : "border-border text-muted-foreground"
2197
2406
  ),
2198
2407
  children: [
2199
- /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
2408
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
2200
2409
  "span",
2201
2410
  {
2202
2411
  "aria-hidden": true,
2203
2412
  className: cn("mt-1 size-1.5 shrink-0 rounded-full", DOT[scenario.status])
2204
2413
  }
2205
2414
  ),
2206
- /* @__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 })
2207
2416
  ]
2208
2417
  }
2209
2418
  ) }, scenario.id);
@@ -2213,14 +2422,14 @@ function TocContent({ onNavigate }) {
2213
2422
  function ReportToc() {
2214
2423
  const report = useReport();
2215
2424
  if (report.features.length === 0) return null;
2216
- return /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(
2425
+ return /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)(
2217
2426
  "nav",
2218
2427
  {
2219
2428
  "aria-label": "Table of contents",
2220
2429
  className: "sticky top-4 hidden h-fit w-64 shrink-0 self-start text-xs lg:block",
2221
2430
  children: [
2222
- /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("p", { className: "mb-3 text-xs font-semibold uppercase tracking-wide text-muted-foreground", children: "Contents" }),
2223
- /* @__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, {})
2224
2433
  ]
2225
2434
  }
2226
2435
  );
@@ -2230,31 +2439,31 @@ function ReportToc() {
2230
2439
  var import_react16 = require("react");
2231
2440
  var import_dialog = require("@base-ui/react/dialog");
2232
2441
  var import_lucide_react4 = require("lucide-react");
2233
- var import_jsx_runtime43 = require("react/jsx-runtime");
2442
+ var import_jsx_runtime44 = require("react/jsx-runtime");
2234
2443
  function ReportTocDrawer() {
2235
2444
  const report = useReport();
2236
2445
  const [open, setOpen] = (0, import_react16.useState)(false);
2237
2446
  if (report.features.length === 0) return null;
2238
- return /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)(import_dialog.Dialog.Root, { open, onOpenChange: setOpen, children: [
2239
- /* @__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: [
2240
- /* @__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 }),
2241
2450
  " Contents"
2242
2451
  ] }),
2243
- /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)(import_dialog.Dialog.Portal, { children: [
2244
- /* @__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" }),
2245
- /* @__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: [
2246
- /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("div", { className: "flex items-center justify-between", children: [
2247
- /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(import_dialog.Dialog.Title, { className: "text-xs font-semibold tracking-wide text-muted-foreground uppercase", children: "Contents" }),
2248
- /* @__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)(
2249
2458
  import_dialog.Dialog.Close,
2250
2459
  {
2251
2460
  "aria-label": "Close contents",
2252
2461
  className: "cursor-pointer rounded p-1 text-muted-foreground hover:bg-muted hover:text-foreground [&_svg]:size-4",
2253
- 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 })
2254
2463
  }
2255
2464
  )
2256
2465
  ] }),
2257
- /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(TocContent, { onNavigate: () => setOpen(false) })
2466
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(TocContent, { onNavigate: () => setOpen(false) })
2258
2467
  ] })
2259
2468
  ] })
2260
2469
  ] });
@@ -2309,14 +2518,14 @@ function useTheme() {
2309
2518
  }
2310
2519
 
2311
2520
  // src/interactive/ReportInteractive.tsx
2312
- var import_jsx_runtime44 = require("react/jsx-runtime");
2521
+ var import_jsx_runtime45 = require("react/jsx-runtime");
2313
2522
  function ReportInteractive(props) {
2314
2523
  const { report, className, title, dataTheme } = props;
2315
2524
  const result = unwrapReport(report);
2316
2525
  if (!result.ok) {
2317
- 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 });
2318
2527
  }
2319
- 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 });
2320
2529
  }
2321
2530
  var THEME_OPTIONS = [
2322
2531
  { value: "light", label: "Light", Icon: import_lucide_react5.Sun },
@@ -2324,7 +2533,7 @@ var THEME_OPTIONS = [
2324
2533
  { value: "dark", label: "Dark", Icon: import_lucide_react5.Moon }
2325
2534
  ];
2326
2535
  function ThemeSegment({ pref, onPref }) {
2327
- return /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
2536
+ return /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
2328
2537
  ToggleGroup,
2329
2538
  {
2330
2539
  size: "sm",
@@ -2334,7 +2543,7 @@ function ThemeSegment({ pref, onPref }) {
2334
2543
  if (next) onPref(next);
2335
2544
  },
2336
2545
  "aria-label": "Color theme",
2337
- 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))
2338
2547
  }
2339
2548
  );
2340
2549
  }
@@ -2362,7 +2571,9 @@ function ReportInteractiveView({
2362
2571
  const deferredQuery = (0, import_react18.useDeferredValue)(query);
2363
2572
  const failures = (0, import_react18.useMemo)(() => listFailures(report), [report]);
2364
2573
  const filtered = (0, import_react18.useMemo)(
2365
- () => filterReport(report, { query: deferredQuery, status: statusFilter, tags: activeTags }),
2574
+ // Features carrying failures float to the top so the first thing on screen
2575
+ // is the thing that needs attention; an all-green run keeps source order.
2576
+ () => failuresFirst(filterReport(report, { query: deferredQuery, status: statusFilter, tags: activeTags })),
2366
2577
  [report, deferredQuery, statusFilter, activeTags]
2367
2578
  );
2368
2579
  const isFiltering = query !== deferredQuery;
@@ -2400,7 +2611,7 @@ function ReportInteractiveView({
2400
2611
  const scenarioActions = (0, import_react18.useMemo)(
2401
2612
  () => ({
2402
2613
  copyLink: (s) => copy(scenarioPermalink(s), "Link copied"),
2403
- copyMarkdown: (s) => copy(scenarioToMarkdown(s), "Markdown copied"),
2614
+ copyMarkdown: (s) => copy(scenarioToMarkdown2(s), "Markdown copied"),
2404
2615
  copyPrompt: (s) => copy(scenarioToPrompt(s), "Prompt copied")
2405
2616
  }),
2406
2617
  [copy]
@@ -2410,9 +2621,9 @@ function ReportInteractiveView({
2410
2621
  () => report.features.flatMap((f) => [f.id, ...f.scenarios.map((s) => s.id)]),
2411
2622
  [report]
2412
2623
  );
2413
- const collapse = useCollapseState();
2624
+ const collapse = useCollapseState((0, import_react18.useCallback)(() => defaultCollapsedIds(report), [report]));
2414
2625
  const collapseAll = (0, import_react18.useCallback)(() => collapse.collapseAll(allCollapsibleIds), [collapse, allCollapsibleIds]);
2415
- const [expandedAll, setExpandedAll] = (0, import_react18.useState)(true);
2626
+ const [expandedAll, setExpandedAll] = (0, import_react18.useState)(() => report.summary.failed === 0);
2416
2627
  const setExpanded = (0, import_react18.useCallback)(
2417
2628
  (expanded) => {
2418
2629
  if (expanded) collapse.expandAll();
@@ -2454,13 +2665,13 @@ function ReportInteractiveView({
2454
2665
  const totalScenarios = report.summary.total;
2455
2666
  const matchedScenarios = filtered.summary.total;
2456
2667
  const showToc = !hideToc && totalScenarios > 3;
2457
- 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)(
2458
2669
  ReportRoot,
2459
2670
  {
2460
2671
  report: filtered,
2461
2672
  customRenderers,
2462
2673
  renderers,
2463
- children: /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)(
2674
+ children: /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)(
2464
2675
  "main",
2465
2676
  {
2466
2677
  className: cn("es-report", "es-report-interactive", className),
@@ -2469,8 +2680,8 @@ function ReportInteractiveView({
2469
2680
  "data-theme": dataTheme,
2470
2681
  "data-detail-level": detail,
2471
2682
  children: [
2472
- /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("header", { className: "es-report-header", children: [
2473
- /* @__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)(
2474
2685
  "div",
2475
2686
  {
2476
2687
  "data-es-navbar": true,
@@ -2479,9 +2690,9 @@ function ReportInteractiveView({
2479
2690
  hideHeader ? "justify-end" : "justify-between"
2480
2691
  ),
2481
2692
  children: [
2482
- hideHeader ? null : /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("h1", { className: "min-w-0", children: title ?? "Story Report" }),
2483
- /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("div", { className: "flex items-center gap-2", children: [
2484
- /* @__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)(
2485
2696
  ReportSearch,
2486
2697
  {
2487
2698
  ref: searchRef,
@@ -2491,16 +2702,16 @@ function ReportInteractiveView({
2491
2702
  totalCount: totalScenarios
2492
2703
  }
2493
2704
  ),
2494
- /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(ThemeSegment, { pref: themePref, onPref: setThemePref })
2705
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(ThemeSegment, { pref: themePref, onPref: setThemePref })
2495
2706
  ] })
2496
2707
  ]
2497
2708
  }
2498
2709
  ),
2499
- hideHeader ? null : /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)(import_jsx_runtime44.Fragment, { children: [
2500
- /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(ReportSummary, {}),
2501
- /* @__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, {})
2502
2713
  ] }),
2503
- /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
2714
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
2504
2715
  ReportFreshness,
2505
2716
  {
2506
2717
  lastRunMs: reportLastRunMs(report),
@@ -2508,8 +2719,8 @@ function ReportInteractiveView({
2508
2719
  staleAfterDays
2509
2720
  }
2510
2721
  ),
2511
- /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(ReportLastRunDelta, { history: scenarioHistory, report }),
2512
- /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
2722
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(ReportLastRunDelta, { history: scenarioHistory, report }),
2723
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
2513
2724
  ReportFilters,
2514
2725
  {
2515
2726
  statuses: statusOptions,
@@ -2520,14 +2731,14 @@ function ReportInteractiveView({
2520
2731
  onToggleTag: toggleTag
2521
2732
  }
2522
2733
  ),
2523
- /* @__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: [
2524
- showToc ? /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(ReportTocDrawer, {}) : null,
2525
- /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("div", { className: "flex items-center gap-2", children: [
2526
- /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(Switch, { id: expandId, checked: expandedAll, onCheckedChange: setExpanded }),
2527
- /* @__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" })
2528
2739
  ] }),
2529
- /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("div", { className: "flex items-center gap-2", children: [
2530
- /* @__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)(
2531
2742
  Switch,
2532
2743
  {
2533
2744
  id: docsId,
@@ -2535,16 +2746,16 @@ function ReportInteractiveView({
2535
2746
  onCheckedChange: (checked) => setDetail(checked ? "full" : "minimal")
2536
2747
  }
2537
2748
  ),
2538
- /* @__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" })
2539
2750
  ] })
2540
2751
  ] })
2541
2752
  ] }),
2542
- /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(ReportFailureBanner, { failures }),
2543
- hasContent ? showToc ? /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("div", { className: "flex gap-6", children: [
2544
- /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(ReportToc, {}),
2545
- /* @__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, {}) })
2546
- ] }) : /* @__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 }),
2547
- /* @__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)(
2548
2759
  "button",
2549
2760
  {
2550
2761
  type: "button",
@@ -2555,8 +2766,8 @@ function ReportInteractiveView({
2555
2766
  children: "?"
2556
2767
  }
2557
2768
  ),
2558
- /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(ReportShortcutsHelp, { open: helpOpen, onClose: () => setHelpOpen(false) }),
2559
- 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)(
2560
2771
  "div",
2561
2772
  {
2562
2773
  role: "status",
@@ -2580,7 +2791,7 @@ var import_react20 = require("react");
2580
2791
 
2581
2792
  // src/components/doc/MermaidView.tsx
2582
2793
  var import_react19 = require("react");
2583
- var import_jsx_runtime45 = require("react/jsx-runtime");
2794
+ var import_jsx_runtime46 = require("react/jsx-runtime");
2584
2795
  function prefersDark(el) {
2585
2796
  const themed = el?.closest("[data-theme]");
2586
2797
  if (themed?.dataset.theme === "dark") return true;
@@ -2617,9 +2828,9 @@ function MermaidView({ entry, load }) {
2617
2828
  };
2618
2829
  }, [entry.code, load]);
2619
2830
  if (svg) {
2620
- return /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("figure", { ref, className: "my-3", children: [
2621
- entry.title ? /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("figcaption", { className: "mb-1.5 text-xs font-medium text-muted-foreground", children: entry.title }) : null,
2622
- /* @__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)(
2623
2834
  "div",
2624
2835
  {
2625
2836
  role: "img",
@@ -2630,11 +2841,11 @@ function MermaidView({ entry, load }) {
2630
2841
  )
2631
2842
  ] });
2632
2843
  }
2633
- return /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(MermaidSource, { entry, ref });
2844
+ return /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(MermaidSource, { entry, ref });
2634
2845
  }
2635
2846
 
2636
2847
  // src/interactive/island-renderers.tsx
2637
- var import_jsx_runtime46 = require("react/jsx-runtime");
2848
+ var import_jsx_runtime47 = require("react/jsx-runtime");
2638
2849
  var HLJS_ESM = "https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/es/highlight.min.js";
2639
2850
  var MERMAID_ESM = "https://cdn.jsdelivr.net/npm/mermaid@10/dist/mermaid.esm.min.mjs";
2640
2851
  function cachedCdnModule(url) {
@@ -2668,13 +2879,13 @@ function CdnHighlightedCode({ entry }) {
2668
2879
  cancelled = true;
2669
2880
  };
2670
2881
  }, [entry.content, entry.lang]);
2671
- 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)(
2672
2883
  "code",
2673
2884
  {
2674
2885
  className: cn("hljs font-mono text-xs", entry.lang && `language-${entry.lang}`),
2675
2886
  dangerouslySetInnerHTML: { __html: html }
2676
2887
  }
2677
- ) : /* @__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 }) });
2678
2889
  }
2679
2890
  function buildIslandRenderers(opts) {
2680
2891
  const renderers = {};
@@ -2688,7 +2899,7 @@ function buildIslandRenderers(opts) {
2688
2899
  }
2689
2900
 
2690
2901
  // src/interactive/ReportInteractiveIsland.tsx
2691
- var import_jsx_runtime47 = require("react/jsx-runtime");
2902
+ var import_jsx_runtime48 = require("react/jsx-runtime");
2692
2903
  function ReportInteractiveIsland({
2693
2904
  report,
2694
2905
  title,
@@ -2702,7 +2913,7 @@ function ReportInteractiveIsland({
2702
2913
  () => buildIslandRenderers({ syntaxHighlighting, mermaid }),
2703
2914
  [syntaxHighlighting, mermaid]
2704
2915
  );
2705
- return /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
2916
+ return /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
2706
2917
  ReportInteractive,
2707
2918
  {
2708
2919
  report,