@flytedan/flytebot-design-system 0.6.1 → 0.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -70,6 +70,7 @@ __export(index_exports, {
70
70
  Dropzone: () => Dropzone,
71
71
  DropzoneKit: () => DropzoneKit,
72
72
  EmptyState: () => EmptyState,
73
+ EntityRow: () => EntityRow,
73
74
  FeatureGate: () => FeatureGate,
74
75
  FileChip: () => FileChip,
75
76
  FileGrid: () => FileGrid,
@@ -142,11 +143,16 @@ __export(index_exports, {
142
143
  Tooltip: () => Tooltip,
143
144
  Topbar: () => Topbar,
144
145
  TranscriptKit: () => TranscriptKit,
146
+ TransferList: () => TransferList,
145
147
  UseFeatureStatus: () => UseFeatureStatus,
146
148
  UseRuntimeMode: () => UseRuntimeMode,
149
+ VIRTUAL_LIST_BUFFER_ROWS: () => VIRTUAL_LIST_BUFFER_ROWS,
150
+ VirtualList: () => VirtualList,
147
151
  acceptMatches: () => acceptMatches,
148
152
  anyOfFilter: () => anyOfFilter,
149
153
  channelWeightOf: () => channelWeightOf,
154
+ computeNeedMore: () => computeNeedMore,
155
+ computeVirtualWindow: () => computeVirtualWindow,
150
156
  createVersionStore: () => createVersionStore,
151
157
  eqFilter: () => eqFilter,
152
158
  extensionOf: () => extensionOf,
@@ -1254,6 +1260,9 @@ var BANDS = {
1254
1260
  strong: { n: 3, label: "Strong" },
1255
1261
  dominant: { n: 4, label: "Dominant" }
1256
1262
  };
1263
+ function formatCrp(crp) {
1264
+ return crp.toFixed(1);
1265
+ }
1257
1266
  function CsiMeter({ band = "weak", size = 4, width = 5, gap = 2 }) {
1258
1267
  const n = (BANDS[band] || BANDS.weak).n;
1259
1268
  return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "fd-meter", style: { gap: gap + "px" }, "aria-hidden": "true", children: [1, 2, 3, 4].map((i) => /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
@@ -1276,7 +1285,7 @@ function CsiBadge({ band = "weak", crp, size = "compact", preview = false, alert
1276
1285
  alert ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "fd-badge-dot", style: { background: "var(--csi-alert)" }, "aria-label": "Fixable" }) : null,
1277
1286
  /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(CsiMeter, { band, size: size === "medium" ? 11 : 9, width: size === "medium" ? 4 : 3 }),
1278
1287
  b.label,
1279
- crp !== void 0 && crp !== null ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "fd-csi-crp", children: crp }) : null
1288
+ crp !== void 0 && crp !== null ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "fd-csi-crp", children: formatCrp(crp) }) : null
1280
1289
  ]
1281
1290
  }
1282
1291
  );
@@ -1285,7 +1294,7 @@ function CsiHero({ band = "weak", crp, label, className = "" }) {
1285
1294
  const b = BANDS[band] || BANDS.weak;
1286
1295
  const mark = "var(--csi-" + b.n + "-mark)";
1287
1296
  return /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 10 }, children: [
1288
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "fd-csi-hero-num", style: { color: mark }, children: crp }),
1297
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "fd-csi-hero-num", style: { color: mark }, children: crp !== void 0 && crp !== null ? formatCrp(crp) : "" }),
1289
1298
  /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "fd-label-lg", style: { color: "var(--text-2)" }, children: label || b.label }),
1290
1299
  /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "fd-meter", style: { gap: 3, color: mark, width: 120 }, children: [1, 2, 3, 4].map((i) => /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "fd-meter-seg" + (i <= b.n ? " is-on" : ""), style: { height: 6, flex: 1 } }, i)) })
1291
1300
  ] });
@@ -2613,56 +2622,140 @@ function StepList({
2613
2622
  ] });
2614
2623
  }
2615
2624
 
2616
- // src/components/forms/Checkbox.tsx
2625
+ // src/components/data/VirtualList.tsx
2617
2626
  var React15 = __toESM(require("react"), 1);
2618
2627
  var import_jsx_runtime38 = require("react/jsx-runtime");
2619
- function Checkbox({ label, description, card = false, indeterminate = false, className = "", ...rest }) {
2620
- const ref = React15.useRef(null);
2628
+ var VIRTUAL_LIST_BUFFER_ROWS = 20;
2629
+ function computeVirtualWindow(opts) {
2630
+ const { scrollTop, viewportHeight, itemHeight, itemCount, bufferRows = VIRTUAL_LIST_BUFFER_ROWS } = opts;
2631
+ if (itemCount <= 0 || itemHeight <= 0) {
2632
+ return { visibleStart: 0, visibleEnd: -1, startIndex: 0, endIndex: -1, totalHeight: 0, offsetY: 0 };
2633
+ }
2634
+ const lastPossible = itemCount - 1;
2635
+ const visibleStart = Math.min(lastPossible, Math.max(0, Math.floor(scrollTop / itemHeight)));
2636
+ const visibleRows = Math.max(1, Math.ceil(viewportHeight / itemHeight));
2637
+ const visibleEnd = Math.min(lastPossible, visibleStart + visibleRows - 1);
2638
+ const startIndex = Math.max(0, visibleStart - bufferRows);
2639
+ const endIndex = Math.min(lastPossible, visibleEnd + bufferRows);
2640
+ return {
2641
+ visibleStart,
2642
+ visibleEnd,
2643
+ startIndex,
2644
+ endIndex,
2645
+ totalHeight: itemCount * itemHeight,
2646
+ offsetY: startIndex * itemHeight
2647
+ };
2648
+ }
2649
+ function computeNeedMore(win, itemCount, bufferRows = VIRTUAL_LIST_BUFFER_ROWS) {
2650
+ if (itemCount <= 0) return { start: true, end: true };
2651
+ return {
2652
+ start: win.visibleStart <= bufferRows,
2653
+ end: itemCount - 1 - win.visibleEnd <= bufferRows
2654
+ };
2655
+ }
2656
+ function VirtualList({
2657
+ items,
2658
+ itemHeight,
2659
+ renderItem,
2660
+ onNeedMore,
2661
+ hasMore,
2662
+ loading = false,
2663
+ keyOf,
2664
+ height = 400,
2665
+ emptyState,
2666
+ className = "",
2667
+ style
2668
+ }) {
2669
+ const [scrollTop, setScrollTop] = React15.useState(0);
2670
+ const requested = React15.useRef({ start: null, end: null });
2671
+ const win = React15.useMemo(
2672
+ () => computeVirtualWindow({ scrollTop, viewportHeight: height, itemHeight, itemCount: items.length }),
2673
+ [scrollTop, height, itemHeight, items.length]
2674
+ );
2675
+ const need = React15.useMemo(() => computeNeedMore(win, items.length), [win, items.length]);
2676
+ const wantStart = need.start && hasMore?.start !== false;
2677
+ const wantEnd = need.end && hasMore?.end !== false;
2621
2678
  React15.useEffect(() => {
2622
- if (ref.current) ref.current.indeterminate = indeterminate;
2623
- }, [indeterminate]);
2624
- return /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("label", { className: ["fd-choice", card ? "fd-choice-card" : "", className].filter(Boolean).join(" "), children: [
2625
- /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("span", { className: "fd-choice-input", children: [
2626
- /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("input", { ref, type: "checkbox", ...rest }),
2627
- /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("span", { className: "fd-choice-box", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("i", { className: indeterminate ? "ph ph-minus" : "ph ph-check" }) })
2628
- ] }),
2629
- /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("span", { className: "fd-choice-text", children: [
2630
- /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("span", { className: "fd-choice-title", children: label }),
2631
- description ? /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("span", { className: "fd-choice-desc", children: description }) : null
2632
- ] })
2633
- ] });
2679
+ if (loading || !wantStart || requested.current.start === items.length) return;
2680
+ requested.current.start = items.length;
2681
+ onNeedMore("start");
2682
+ }, [wantStart, loading, items.length, onNeedMore]);
2683
+ React15.useEffect(() => {
2684
+ if (loading || !wantEnd || requested.current.end === items.length) return;
2685
+ requested.current.end = items.length;
2686
+ onNeedMore("end");
2687
+ }, [wantEnd, loading, items.length, onNeedMore]);
2688
+ if (!items.length && !loading && emptyState) {
2689
+ return /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("div", { className: ["fd-vlist", className].filter(Boolean).join(" "), style: { height, overflow: "auto", ...style }, children: emptyState });
2690
+ }
2691
+ const rows = [];
2692
+ for (let i = win.startIndex; i <= win.endIndex; i++) {
2693
+ const item = items[i];
2694
+ if (item === void 0) continue;
2695
+ rows.push(
2696
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("div", { style: { height: itemHeight, boxSizing: "border-box" }, children: renderItem(item, i) }, keyOf(item))
2697
+ );
2698
+ }
2699
+ return /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)(
2700
+ "div",
2701
+ {
2702
+ className: ["fd-vlist", className].filter(Boolean).join(" "),
2703
+ style: { height, overflowY: "auto", overflowX: "hidden", position: "relative", ...style },
2704
+ onScroll: (e) => setScrollTop(e.currentTarget.scrollTop),
2705
+ children: [
2706
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("div", { style: { height: win.totalHeight, position: "relative" }, children: /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("div", { style: { position: "absolute", top: win.offsetY, left: 0, right: 0 }, children: rows }) }),
2707
+ loading ? /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("div", { style: { position: "sticky", bottom: 0, left: 0, right: 0, display: "grid", placeItems: "center", padding: "8px 0", background: "var(--surface)" }, children: /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("span", { className: "fd-spinner", "aria-hidden": "true" }) }) : null
2708
+ ]
2709
+ }
2710
+ );
2634
2711
  }
2635
2712
 
2636
- // src/components/forms/Radio.tsx
2713
+ // src/components/data/EntityRow.tsx
2637
2714
  var import_jsx_runtime39 = require("react/jsx-runtime");
2638
- function Radio({ label, description, card = false, className = "", ...rest }) {
2639
- return /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("label", { className: ["fd-choice", card ? "fd-choice-card" : "", className].filter(Boolean).join(" "), children: [
2640
- /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("span", { className: "fd-choice-input", children: [
2641
- /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("input", { type: "radio", ...rest }),
2642
- /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("span", { className: "fd-choice-box fd-choice-box-round", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("span", { className: "fd-choice-dot" }) })
2643
- ] }),
2644
- /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("span", { className: "fd-choice-text", children: [
2645
- /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("span", { className: "fd-choice-title", children: label }),
2646
- description ? /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("span", { className: "fd-choice-desc", children: description }) : null
2647
- ] })
2648
- ] });
2715
+ function EntityRow({ title, meta, action, draggable = false, onDragStart, onDragEnd, style, className = "" }) {
2716
+ return /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)(
2717
+ "div",
2718
+ {
2719
+ draggable,
2720
+ onDragStart,
2721
+ onDragEnd,
2722
+ className: ["fd-erow", className].filter(Boolean).join(" "),
2723
+ style: {
2724
+ display: "flex",
2725
+ alignItems: "center",
2726
+ gap: 8,
2727
+ height: "100%",
2728
+ padding: "0 8px",
2729
+ borderRadius: 6,
2730
+ cursor: draggable ? "grab" : void 0,
2731
+ ...style
2732
+ },
2733
+ children: [
2734
+ draggable ? /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("i", { className: "ph ph-dots-six-vertical", "aria-hidden": "true", style: { fontSize: 13, flex: "none", color: "var(--text-muted)" } }) : null,
2735
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("span", { style: { flex: 1, minWidth: 0, display: "flex", flexDirection: "column", gap: 1 }, children: [
2736
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("span", { className: "fd-body-sm", style: { fontWeight: 600, color: "var(--text)", whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis" }, children: title }),
2737
+ meta ? /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("span", { style: { fontSize: "var(--overline-size)", color: "var(--text-muted)", whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis" }, children: meta }) : null
2738
+ ] }),
2739
+ action ? /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
2740
+ IconButton,
2741
+ {
2742
+ icon: action.icon,
2743
+ label: action.label,
2744
+ size: "sm",
2745
+ onClick: action.onClick,
2746
+ style: { color: action.tone === "add" ? "var(--ok-text)" : action.tone === "remove" ? "var(--danger-text)" : void 0 }
2747
+ }
2748
+ ) : null
2749
+ ]
2750
+ }
2751
+ );
2649
2752
  }
2650
2753
 
2651
- // src/components/forms/Switch.tsx
2652
- var import_jsx_runtime40 = require("react/jsx-runtime");
2653
- function Switch({ label, description, className = "", ...rest }) {
2654
- return /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("label", { className: ["fd-switch", className].filter(Boolean).join(" "), children: [
2655
- /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("input", { type: "checkbox", role: "switch", ...rest }),
2656
- /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("span", { className: "fd-switch-track", children: /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("span", { className: "fd-switch-thumb" }) }),
2657
- label ? /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("span", { className: "fd-choice-text", children: [
2658
- /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("span", { className: "fd-switch-label", children: label }),
2659
- description ? /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("span", { className: "fd-choice-desc", children: description }) : null
2660
- ] }) : null
2661
- ] });
2662
- }
2754
+ // src/components/data/TransferList.tsx
2755
+ var React16 = __toESM(require("react"), 1);
2663
2756
 
2664
2757
  // src/components/forms/Input.tsx
2665
- var import_jsx_runtime41 = require("react/jsx-runtime");
2758
+ var import_jsx_runtime40 = require("react/jsx-runtime");
2666
2759
  function Input({
2667
2760
  label,
2668
2761
  help,
@@ -2690,27 +2783,27 @@ function Input({
2690
2783
  size === "lg" ? "fd-input-lg" : "",
2691
2784
  className
2692
2785
  ].filter(Boolean).join(" ");
2693
- return /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { className: "fd-field", style, children: [
2694
- label ? /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("label", { className: "fd-field-label", htmlFor: fieldId, children: [
2786
+ return /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("div", { className: "fd-field", style, children: [
2787
+ label ? /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("label", { className: "fd-field-label", htmlFor: fieldId, children: [
2695
2788
  label,
2696
- required ? /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("span", { className: "fd-field-req", "aria-hidden": "true", children: "*" }) : null
2789
+ required ? /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("span", { className: "fd-field-req", "aria-hidden": "true", children: "*" }) : null
2697
2790
  ] }) : null,
2698
- /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { className: box, children: [
2699
- icon ? /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("span", { className: "fd-input-icon", children: /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("i", { className: "ph ph-" + icon, "aria-hidden": "true" }) }) : null,
2700
- prefix ? /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("span", { className: "fd-input-affix", children: prefix }) : null,
2701
- /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("input", { id: fieldId, disabled, style: inputStyle, "aria-invalid": error ? "true" : void 0, ...rest }),
2702
- loading ? /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("span", { className: "fd-spinner", style: { color: "var(--text-muted)" }, "aria-label": "Loading" }) : null,
2703
- suffix && !loading ? /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("span", { className: "fd-input-affix", children: suffix }) : null
2791
+ /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("div", { className: box, children: [
2792
+ icon ? /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("span", { className: "fd-input-icon", children: /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("i", { className: "ph ph-" + icon, "aria-hidden": "true" }) }) : null,
2793
+ prefix ? /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("span", { className: "fd-input-affix", children: prefix }) : null,
2794
+ /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("input", { id: fieldId, disabled, style: inputStyle, "aria-invalid": error ? "true" : void 0, ...rest }),
2795
+ loading ? /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("span", { className: "fd-spinner", style: { color: "var(--text-muted)" }, "aria-label": "Loading" }) : null,
2796
+ suffix && !loading ? /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("span", { className: "fd-input-affix", children: suffix }) : null
2704
2797
  ] }),
2705
- error ? /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("span", { className: "fd-field-error", children: [
2706
- /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
2798
+ error ? /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("span", { className: "fd-field-error", children: [
2799
+ /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
2707
2800
  error
2708
- ] }) : help ? /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("span", { className: "fd-field-help", children: help }) : null
2801
+ ] }) : help ? /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("span", { className: "fd-field-help", children: help }) : null
2709
2802
  ] });
2710
2803
  }
2711
2804
 
2712
2805
  // src/components/forms/SearchField.tsx
2713
- var import_jsx_runtime42 = require("react/jsx-runtime");
2806
+ var import_jsx_runtime41 = require("react/jsx-runtime");
2714
2807
  function SearchField({
2715
2808
  value,
2716
2809
  onChange,
@@ -2725,7 +2818,7 @@ function SearchField({
2725
2818
  ...rest
2726
2819
  }) {
2727
2820
  const clear = onClear || (() => onChange(""));
2728
- return /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
2821
+ return /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
2729
2822
  Input,
2730
2823
  {
2731
2824
  id,
@@ -2738,14 +2831,14 @@ function SearchField({
2738
2831
  style,
2739
2832
  className,
2740
2833
  onChange: (e) => onChange(e.target.value),
2741
- suffix: value ? /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
2834
+ suffix: value ? /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
2742
2835
  "button",
2743
2836
  {
2744
2837
  type: "button",
2745
2838
  "aria-label": "Clear search",
2746
2839
  onClick: clear,
2747
2840
  style: { all: "unset", cursor: "pointer", color: "var(--text-muted)", display: "grid", placeItems: "center", padding: 2 },
2748
- children: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("i", { className: "ph ph-x-circle", style: { fontSize: 15 }, "aria-hidden": "true" })
2841
+ children: /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("i", { className: "ph ph-x-circle", style: { fontSize: 15 }, "aria-hidden": "true" })
2749
2842
  }
2750
2843
  ) : void 0,
2751
2844
  ...rest
@@ -2753,27 +2846,183 @@ function SearchField({
2753
2846
  );
2754
2847
  }
2755
2848
 
2756
- // src/components/forms/Textarea.tsx
2849
+ // src/components/data/TransferList.tsx
2850
+ var import_jsx_runtime42 = require("react/jsx-runtime");
2851
+ var emptyHasMore = {};
2852
+ function TransferList({
2853
+ left,
2854
+ right,
2855
+ keyOf,
2856
+ renderLabel,
2857
+ renderMeta,
2858
+ onMove,
2859
+ itemHeight = 44,
2860
+ listHeight = 440,
2861
+ className = ""
2862
+ }) {
2863
+ const [dragging, setDragging] = React16.useState(null);
2864
+ const [dragOverSide, setDragOverSide] = React16.useState(null);
2865
+ const startDrag = (e, item, from) => {
2866
+ const key = keyOf(item);
2867
+ setDragging({ key, from });
2868
+ e.dataTransfer.effectAllowed = "move";
2869
+ e.dataTransfer.setData("text/plain", String(key));
2870
+ };
2871
+ const endDrag = () => {
2872
+ setDragging(null);
2873
+ setDragOverSide(null);
2874
+ };
2875
+ const findItem = (side, key) => (side === "left" ? left.items : right.items).find((it) => keyOf(it) === key);
2876
+ const dropOnSide = (e, side) => {
2877
+ e.preventDefault();
2878
+ setDragOverSide(null);
2879
+ if (!dragging || dragging.from === side) return;
2880
+ const item = findItem(dragging.from, dragging.key);
2881
+ if (item !== void 0) onMove(item, dragging.from, side);
2882
+ setDragging(null);
2883
+ };
2884
+ const renderSide = (side, cfg, opposite) => /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(
2885
+ "div",
2886
+ {
2887
+ style: {
2888
+ flex: 1,
2889
+ minWidth: 0,
2890
+ display: "flex",
2891
+ flexDirection: "column",
2892
+ gap: 8,
2893
+ padding: 10,
2894
+ borderRadius: 10,
2895
+ border: "1px solid " + (dragOverSide === side ? "var(--brand)" : "var(--border)"),
2896
+ background: "var(--surface)"
2897
+ },
2898
+ onDragOver: (e) => {
2899
+ if (!dragging || dragging.from === side) return;
2900
+ e.preventDefault();
2901
+ e.dataTransfer.dropEffect = "move";
2902
+ if (dragOverSide !== side) setDragOverSide(side);
2903
+ },
2904
+ onDragLeave: (e) => {
2905
+ if (e.currentTarget.contains(e.relatedTarget)) return;
2906
+ setDragOverSide((s) => s === side ? null : s);
2907
+ },
2908
+ onDrop: (e) => dropOnSide(e, side),
2909
+ children: [
2910
+ cfg.label ? /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("span", { className: "fd-overline fd-muted", children: [
2911
+ cfg.label,
2912
+ cfg.total != null ? " (" + cfg.total.toLocaleString() + ")" : ""
2913
+ ] }) : null,
2914
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("span", { className: "fd-row", style: { gap: 8 }, children: [
2915
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(SearchField, { value: cfg.search, onChange: cfg.onSearchChange, placeholder: "Search", "aria-label": (cfg.label || side) + " search", style: { flex: 1 } }),
2916
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(SortMenu, { fields: cfg.sortFields, sort: cfg.sort, onSort: cfg.onSort })
2917
+ ] }),
2918
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
2919
+ VirtualList,
2920
+ {
2921
+ items: cfg.items,
2922
+ itemHeight,
2923
+ height: listHeight,
2924
+ keyOf,
2925
+ loading: cfg.loading,
2926
+ hasMore: cfg.hasMore || emptyHasMore,
2927
+ onNeedMore: cfg.onNeedMore,
2928
+ emptyState: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(EmptyState, { icon: "tray", title: "Nothing here" }),
2929
+ renderItem: (item) => /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
2930
+ EntityRow,
2931
+ {
2932
+ title: renderLabel(item),
2933
+ meta: renderMeta ? renderMeta(item) : void 0,
2934
+ draggable: true,
2935
+ onDragStart: (e) => startDrag(e, item, side),
2936
+ onDragEnd: endDrag,
2937
+ style: { opacity: dragging && dragging.from === side && dragging.key === keyOf(item) ? 0.4 : 1 },
2938
+ action: {
2939
+ icon: side === "left" ? "plus" : "minus",
2940
+ label: (side === "left" ? "Move to " : "Move from ") + (side === "left" ? right.label || "the other list" : left.label || "the other list"),
2941
+ tone: side === "left" ? "add" : "remove",
2942
+ onClick: () => onMove(item, side, opposite)
2943
+ }
2944
+ }
2945
+ )
2946
+ }
2947
+ )
2948
+ ]
2949
+ }
2950
+ );
2951
+ return /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: ["fd-tlist", className].filter(Boolean).join(" "), style: { display: "flex", gap: 16, alignItems: "flex-start" }, children: [
2952
+ renderSide("left", left, "right"),
2953
+ renderSide("right", right, "left")
2954
+ ] });
2955
+ }
2956
+
2957
+ // src/components/forms/Checkbox.tsx
2958
+ var React17 = __toESM(require("react"), 1);
2757
2959
  var import_jsx_runtime43 = require("react/jsx-runtime");
2960
+ function Checkbox({ label, description, card = false, indeterminate = false, className = "", ...rest }) {
2961
+ const ref = React17.useRef(null);
2962
+ React17.useEffect(() => {
2963
+ if (ref.current) ref.current.indeterminate = indeterminate;
2964
+ }, [indeterminate]);
2965
+ return /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("label", { className: ["fd-choice", card ? "fd-choice-card" : "", className].filter(Boolean).join(" "), children: [
2966
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("span", { className: "fd-choice-input", children: [
2967
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("input", { ref, type: "checkbox", ...rest }),
2968
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: "fd-choice-box", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("i", { className: indeterminate ? "ph ph-minus" : "ph ph-check" }) })
2969
+ ] }),
2970
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("span", { className: "fd-choice-text", children: [
2971
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: "fd-choice-title", children: label }),
2972
+ description ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: "fd-choice-desc", children: description }) : null
2973
+ ] })
2974
+ ] });
2975
+ }
2976
+
2977
+ // src/components/forms/Radio.tsx
2978
+ var import_jsx_runtime44 = require("react/jsx-runtime");
2979
+ function Radio({ label, description, card = false, className = "", ...rest }) {
2980
+ return /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("label", { className: ["fd-choice", card ? "fd-choice-card" : "", className].filter(Boolean).join(" "), children: [
2981
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("span", { className: "fd-choice-input", children: [
2982
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("input", { type: "radio", ...rest }),
2983
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("span", { className: "fd-choice-box fd-choice-box-round", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("span", { className: "fd-choice-dot" }) })
2984
+ ] }),
2985
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("span", { className: "fd-choice-text", children: [
2986
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("span", { className: "fd-choice-title", children: label }),
2987
+ description ? /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("span", { className: "fd-choice-desc", children: description }) : null
2988
+ ] })
2989
+ ] });
2990
+ }
2991
+
2992
+ // src/components/forms/Switch.tsx
2993
+ var import_jsx_runtime45 = require("react/jsx-runtime");
2994
+ function Switch({ label, description, className = "", ...rest }) {
2995
+ return /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("label", { className: ["fd-switch", className].filter(Boolean).join(" "), children: [
2996
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("input", { type: "checkbox", role: "switch", ...rest }),
2997
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("span", { className: "fd-switch-track", children: /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("span", { className: "fd-switch-thumb" }) }),
2998
+ label ? /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("span", { className: "fd-choice-text", children: [
2999
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("span", { className: "fd-switch-label", children: label }),
3000
+ description ? /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("span", { className: "fd-choice-desc", children: description }) : null
3001
+ ] }) : null
3002
+ ] });
3003
+ }
3004
+
3005
+ // src/components/forms/Textarea.tsx
3006
+ var import_jsx_runtime46 = require("react/jsx-runtime");
2758
3007
  function Textarea({ label, help, error, required = false, rows = 4, disabled = false, id, className = "", style, ...rest }) {
2759
3008
  const fieldId = id || (rest.name ? "fd-" + rest.name : void 0);
2760
3009
  const box = ["fd-input", "fd-input-textarea", error ? "fd-input-error" : "", disabled ? "fd-input-disabled" : "", className].filter(Boolean).join(" ");
2761
- return /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("div", { className: "fd-field", style, children: [
2762
- label ? /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("label", { className: "fd-field-label", htmlFor: fieldId, children: [
3010
+ return /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: "fd-field", style, children: [
3011
+ label ? /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("label", { className: "fd-field-label", htmlFor: fieldId, children: [
2763
3012
  label,
2764
- required ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: "fd-field-req", children: "*" }) : null
3013
+ required ? /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("span", { className: "fd-field-req", children: "*" }) : null
2765
3014
  ] }) : null,
2766
- /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("div", { className: box, children: /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("textarea", { id: fieldId, rows, disabled, "aria-invalid": error ? "true" : void 0, ...rest }) }),
2767
- error ? /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("span", { className: "fd-field-error", children: [
2768
- /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
3015
+ /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("div", { className: box, children: /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("textarea", { id: fieldId, rows, disabled, "aria-invalid": error ? "true" : void 0, ...rest }) }),
3016
+ error ? /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("span", { className: "fd-field-error", children: [
3017
+ /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
2769
3018
  error
2770
- ] }) : help ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: "fd-field-help", children: help }) : null
3019
+ ] }) : help ? /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("span", { className: "fd-field-help", children: help }) : null
2771
3020
  ] });
2772
3021
  }
2773
3022
 
2774
3023
  // src/components/forms/NumberInput.tsx
2775
- var React16 = __toESM(require("react"), 1);
2776
- var import_jsx_runtime44 = require("react/jsx-runtime");
3024
+ var React18 = __toESM(require("react"), 1);
3025
+ var import_jsx_runtime47 = require("react/jsx-runtime");
2777
3026
  function NumberInput({
2778
3027
  label,
2779
3028
  help,
@@ -2797,10 +3046,10 @@ function NumberInput({
2797
3046
  const n = Number(String(v == null ? "" : v).replace(/[^0-9.-]/g, ""));
2798
3047
  return isNaN(n) ? null : n;
2799
3048
  };
2800
- const [text, setText] = React16.useState(value == null || value === "" ? "" : String(value));
2801
- const [editing, setEditing] = React16.useState(false);
2802
- const timer = React16.useRef(null);
2803
- React16.useEffect(() => {
3049
+ const [text, setText] = React18.useState(value == null || value === "" ? "" : String(value));
3050
+ const [editing, setEditing] = React18.useState(false);
3051
+ const timer = React18.useRef(null);
3052
+ React18.useEffect(() => {
2804
3053
  if (!editing) setText(value == null || value === "" ? "" : String(value));
2805
3054
  }, [value, editing]);
2806
3055
  const clamp = (n) => Math.min(max, Math.max(min, n));
@@ -2824,7 +3073,7 @@ function NumberInput({
2824
3073
  const release = () => {
2825
3074
  if (timer.current) clearTimeout(timer.current);
2826
3075
  };
2827
- React16.useEffect(() => () => {
3076
+ React18.useEffect(() => () => {
2828
3077
  if (timer.current) clearTimeout(timer.current);
2829
3078
  }, []);
2830
3079
  const shown = editing ? text : (() => {
@@ -2832,14 +3081,14 @@ function NumberInput({
2832
3081
  return n == null ? "" : format ? n.toLocaleString() : String(n);
2833
3082
  })();
2834
3083
  const box = ["fd-input", "fd-input-num", error ? "fd-input-error" : "", disabled ? "fd-input-disabled" : ""].filter(Boolean).join(" ");
2835
- return /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("div", { className: ["fd-field", className].filter(Boolean).join(" "), style, children: [
2836
- label ? /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("label", { className: "fd-field-label", children: [
3084
+ return /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: ["fd-field", className].filter(Boolean).join(" "), style, children: [
3085
+ label ? /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("label", { className: "fd-field-label", children: [
2837
3086
  label,
2838
- required ? /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("span", { className: "fd-field-req", children: "*" }) : null
3087
+ required ? /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("span", { className: "fd-field-req", children: "*" }) : null
2839
3088
  ] }) : null,
2840
- /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("div", { className: box, style: { gap: 8 }, children: [
2841
- prefix ? /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("span", { className: "fd-input-affix", children: prefix }) : null,
2842
- /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
3089
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: box, style: { gap: 8 }, children: [
3090
+ prefix ? /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("span", { className: "fd-input-affix", children: prefix }) : null,
3091
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
2843
3092
  "input",
2844
3093
  {
2845
3094
  inputMode: "numeric",
@@ -2872,9 +3121,9 @@ function NumberInput({
2872
3121
  }
2873
3122
  }
2874
3123
  ),
2875
- suffix ? /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("span", { className: "fd-input-affix", children: suffix }) : null,
2876
- /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("span", { className: "fd-row", style: { gap: 4, flex: "none" }, children: [
2877
- /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
3124
+ suffix ? /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("span", { className: "fd-input-affix", children: suffix }) : null,
3125
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("span", { className: "fd-row", style: { gap: 4, flex: "none" }, children: [
3126
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
2878
3127
  "button",
2879
3128
  {
2880
3129
  type: "button",
@@ -2884,10 +3133,10 @@ function NumberInput({
2884
3133
  onPointerDown: () => hold(-1),
2885
3134
  onPointerUp: release,
2886
3135
  onPointerLeave: release,
2887
- children: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("i", { className: "ph ph-minus" })
3136
+ children: /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("i", { className: "ph ph-minus" })
2888
3137
  }
2889
3138
  ),
2890
- /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
3139
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
2891
3140
  "button",
2892
3141
  {
2893
3142
  type: "button",
@@ -2897,26 +3146,26 @@ function NumberInput({
2897
3146
  onPointerDown: () => hold(1),
2898
3147
  onPointerUp: release,
2899
3148
  onPointerLeave: release,
2900
- children: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("i", { className: "ph ph-plus" })
3149
+ children: /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("i", { className: "ph ph-plus" })
2901
3150
  }
2902
3151
  )
2903
3152
  ] })
2904
3153
  ] }),
2905
- error ? /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("span", { className: "fd-field-error", children: [
2906
- /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
3154
+ error ? /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("span", { className: "fd-field-error", children: [
3155
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
2907
3156
  error
2908
- ] }) : help ? /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("span", { className: "fd-field-help", children: help }) : null
3157
+ ] }) : help ? /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("span", { className: "fd-field-help", children: help }) : null
2909
3158
  ] });
2910
3159
  }
2911
3160
 
2912
3161
  // src/components/forms/Select.tsx
2913
- var React17 = __toESM(require("react"), 1);
3162
+ var React19 = __toESM(require("react"), 1);
2914
3163
  var import_react_dom4 = require("react-dom");
2915
- var import_jsx_runtime45 = require("react/jsx-runtime");
3164
+ var import_jsx_runtime48 = require("react/jsx-runtime");
2916
3165
  var norm = (o) => typeof o === "string" ? { value: o, label: o } : o;
2917
3166
  function usePopPos(open, ref, estH, estW) {
2918
- const [pos, setPos] = React17.useState(null);
2919
- React17.useLayoutEffect(() => {
3167
+ const [pos, setPos] = React19.useState(null);
3168
+ React19.useLayoutEffect(() => {
2920
3169
  if (!open || !ref.current) {
2921
3170
  setPos(null);
2922
3171
  return;
@@ -2980,14 +3229,14 @@ function Select({
2980
3229
  const vals = multiple ? Array.isArray(value) ? value : value ? [value] : [] : [];
2981
3230
  const isOn = (v) => multiple ? vals.includes(v) : v === value;
2982
3231
  const hasSearch = searchable === void 0 ? opts.length > 8 : searchable;
2983
- const [open, setOpen] = React17.useState(false);
2984
- const [q, setQ] = React17.useState("");
2985
- const [active, setActive] = React17.useState(-1);
2986
- const rootRef = React17.useRef(null);
2987
- const boxRef = React17.useRef(null);
2988
- const popRef = React17.useRef(null);
2989
- const listRef = React17.useRef(null);
2990
- const typeBuf = React17.useRef({ s: "", t: 0 });
3232
+ const [open, setOpen] = React19.useState(false);
3233
+ const [q, setQ] = React19.useState("");
3234
+ const [active, setActive] = React19.useState(-1);
3235
+ const rootRef = React19.useRef(null);
3236
+ const boxRef = React19.useRef(null);
3237
+ const popRef = React19.useRef(null);
3238
+ const listRef = React19.useRef(null);
3239
+ const typeBuf = React19.useRef({ s: "", t: 0 });
2991
3240
  const selected = multiple ? null : opts.find((o) => o.value === value);
2992
3241
  const chosen = multiple ? opts.filter((o) => vals.includes(o.value)) : [];
2993
3242
  const pos = usePopPos(open, boxRef, hasSearch ? 390 : 340, 260);
@@ -3013,7 +3262,7 @@ function Select({
3013
3262
  }
3014
3263
  setOpen(!open);
3015
3264
  };
3016
- React17.useEffect(() => {
3265
+ React19.useEffect(() => {
3017
3266
  if (!open) return;
3018
3267
  const away = (e) => {
3019
3268
  if (rootRef.current && rootRef.current.contains(e.target)) return;
@@ -3023,7 +3272,7 @@ function Select({
3023
3272
  document.addEventListener("pointerdown", away);
3024
3273
  return () => document.removeEventListener("pointerdown", away);
3025
3274
  }, [open]);
3026
- React17.useEffect(() => {
3275
+ React19.useEffect(() => {
3027
3276
  if (!open || active < 0 || !listRef.current) return;
3028
3277
  const el = listRef.current.querySelector('[data-i="' + active + '"]');
3029
3278
  if (el) {
@@ -3077,13 +3326,13 @@ function Select({
3077
3326
  });
3078
3327
  const fieldId = id || (rest.name ? "fd-" + rest.name : void 0);
3079
3328
  const box = ["fd-input", "fd-select", error ? "fd-input-error" : "", disabled ? "fd-input-disabled" : ""].filter(Boolean).join(" ");
3080
- return /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("div", { className: ["fd-field", "fd-popfield", open ? "is-open" : "", className].filter(Boolean).join(" "), style, ref: rootRef, children: [
3081
- label ? /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("label", { className: "fd-field-label", htmlFor: fieldId, onClick: toggle, children: [
3329
+ return /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("div", { className: ["fd-field", "fd-popfield", open ? "is-open" : "", className].filter(Boolean).join(" "), style, ref: rootRef, children: [
3330
+ label ? /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("label", { className: "fd-field-label", htmlFor: fieldId, onClick: toggle, children: [
3082
3331
  label,
3083
- required ? /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("span", { className: "fd-field-req", children: "*" }) : null
3332
+ required ? /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("span", { className: "fd-field-req", children: "*" }) : null
3084
3333
  ] }) : null,
3085
- /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("div", { className: box, style: { cursor: disabled ? "not-allowed" : "pointer" }, ref: boxRef, children: [
3086
- /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)(
3334
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("div", { className: box, style: { cursor: disabled ? "not-allowed" : "pointer" }, ref: boxRef, children: [
3335
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)(
3087
3336
  "button",
3088
3337
  {
3089
3338
  type: "button",
@@ -3096,13 +3345,13 @@ function Select({
3096
3345
  "aria-haspopup": "listbox",
3097
3346
  style: { all: "unset", flex: 1, minWidth: 0, display: "flex", alignItems: "center", gap: 8, cursor: "inherit", overflow: "hidden" },
3098
3347
  children: [
3099
- selected && selected.icon ? /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("i", { className: "ph ph-" + selected.icon, style: { flex: "none", color: "var(--text-2)" } }) : null,
3100
- /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("span", { style: { overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap", color: (multiple ? chosen.length : selected) ? "var(--text)" : "var(--text-muted)" }, children: boxText }),
3101
- multiple && chosen.length > 1 ? /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("span", { className: "fd-mono", style: { flex: "none", fontSize: 11, fontWeight: 700, padding: "1px 6px", borderRadius: 99, background: "var(--brand)", color: "#fff" }, children: chosen.length }) : null
3348
+ selected && selected.icon ? /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("i", { className: "ph ph-" + selected.icon, style: { flex: "none", color: "var(--text-2)" } }) : null,
3349
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("span", { style: { overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap", color: (multiple ? chosen.length : selected) ? "var(--text)" : "var(--text-muted)" }, children: boxText }),
3350
+ multiple && chosen.length > 1 ? /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("span", { className: "fd-mono", style: { flex: "none", fontSize: 11, fontWeight: 700, padding: "1px 6px", borderRadius: 99, background: "var(--brand)", color: "#fff" }, children: chosen.length }) : null
3102
3351
  ]
3103
3352
  }
3104
3353
  ),
3105
- clearable && (multiple ? chosen.length > 0 : selected) && !loading ? /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
3354
+ clearable && (multiple ? chosen.length > 0 : selected) && !loading ? /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
3106
3355
  "button",
3107
3356
  {
3108
3357
  type: "button",
@@ -3112,22 +3361,22 @@ function Select({
3112
3361
  fire(multiple ? [] : "");
3113
3362
  },
3114
3363
  style: { all: "unset", cursor: "pointer", color: "var(--text-muted)", display: "grid", placeItems: "center", padding: 2 },
3115
- children: /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("i", { className: "ph ph-x-circle", style: { fontSize: 15 } })
3364
+ children: /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("i", { className: "ph ph-x-circle", style: { fontSize: 15 } })
3116
3365
  }
3117
3366
  ) : null,
3118
- loading ? /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("span", { className: "fd-spinner", style: { color: "var(--text-muted)" }, "aria-label": "Loading options" }) : /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("span", { className: "fd-select-caret", onClick: toggle, children: /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("i", { className: "ph ph-caret-down", "aria-hidden": "true" }) })
3367
+ loading ? /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("span", { className: "fd-spinner", style: { color: "var(--text-muted)" }, "aria-label": "Loading options" }) : /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("span", { className: "fd-select-caret", onClick: toggle, children: /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("i", { className: "ph ph-caret-down", "aria-hidden": "true" }) })
3119
3368
  ] }),
3120
3369
  open && pos ? (0, import_react_dom4.createPortal)(
3121
- /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)(
3370
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)(
3122
3371
  "div",
3123
3372
  {
3124
3373
  className: "fd-pop" + (pos.up ? " is-up" : ""),
3125
3374
  ref: popRef,
3126
3375
  style: popStyle(pos, { minWidth: Math.max(pos.width, 260), maxWidth: 380, zIndex: 130, overflowY: "hidden" }),
3127
3376
  children: [
3128
- hasSearch ? /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("div", { className: "fd-pop-search", children: [
3129
- /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("i", { className: "ph ph-magnifying-glass", style: { color: "var(--text-muted)", fontSize: 14 } }),
3130
- /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
3377
+ hasSearch ? /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("div", { className: "fd-pop-search", children: [
3378
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("i", { className: "ph ph-magnifying-glass", style: { color: "var(--text-muted)", fontSize: 14 } }),
3379
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
3131
3380
  "input",
3132
3381
  {
3133
3382
  autoFocus: true,
@@ -3140,15 +3389,15 @@ function Select({
3140
3389
  }
3141
3390
  }
3142
3391
  ),
3143
- q ? /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("span", { className: "fd-body-sm fd-muted", children: visible.length }) : null
3392
+ q ? /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("span", { className: "fd-body-sm fd-muted", children: visible.length }) : null
3144
3393
  ] }) : null,
3145
- /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("div", { className: "fd-pop-list", role: "listbox", "aria-multiselectable": multiple || void 0, ref: listRef, style: { maxHeight: Math.max(120, pos.maxH - (hasSearch ? 64 : 12) - (multiple ? 42 : 0)) }, children: visible.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("div", { className: "fd-pop-empty", children: [
3394
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("div", { className: "fd-pop-list", role: "listbox", "aria-multiselectable": multiple || void 0, ref: listRef, style: { maxHeight: Math.max(120, pos.maxH - (hasSearch ? 64 : 12) - (multiple ? 42 : 0)) }, children: visible.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("div", { className: "fd-pop-empty", children: [
3146
3395
  'Nothing matches "',
3147
3396
  q,
3148
3397
  '".'
3149
- ] }) : groups.map((grp) => /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)(React17.Fragment, { children: [
3150
- grp.g ? /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("div", { className: "fd-pop-group", children: grp.g }) : null,
3151
- grp.items.map(({ o, i }) => /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)(
3398
+ ] }) : groups.map((grp) => /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)(React19.Fragment, { children: [
3399
+ grp.g ? /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("div", { className: "fd-pop-group", children: grp.g }) : null,
3400
+ grp.items.map(({ o, i }) => /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)(
3152
3401
  "button",
3153
3402
  {
3154
3403
  type: "button",
@@ -3160,21 +3409,21 @@ function Select({
3160
3409
  onMouseEnter: () => setActive(i),
3161
3410
  onClick: () => pick(o),
3162
3411
  children: [
3163
- multiple ? /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("span", { "aria-hidden": "true", style: { flex: "none", display: "grid", placeItems: "center", width: 16, height: 16, borderRadius: 4, border: "1.5px solid " + (isOn(o.value) ? "var(--brand)" : "var(--border-strong, var(--border))"), background: isOn(o.value) ? "var(--brand)" : "var(--surface)", color: "#fff" }, children: isOn(o.value) ? /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("i", { className: "ph ph-check", style: { fontSize: 11 } }) : null }) : null,
3164
- o.icon ? /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("span", { className: "fd-opt-icon", children: /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("i", { className: "ph ph-" + o.icon }) }) : null,
3165
- /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("span", { style: { flex: 1, minWidth: 0 }, children: [
3166
- /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("span", { className: "fd-opt-label", children: o.label }),
3167
- o.description ? /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("span", { className: "fd-opt-desc", children: o.description }) : null
3412
+ multiple ? /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("span", { "aria-hidden": "true", style: { flex: "none", display: "grid", placeItems: "center", width: 16, height: 16, borderRadius: 4, border: "1.5px solid " + (isOn(o.value) ? "var(--brand)" : "var(--border-strong, var(--border))"), background: isOn(o.value) ? "var(--brand)" : "var(--surface)", color: "#fff" }, children: isOn(o.value) ? /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("i", { className: "ph ph-check", style: { fontSize: 11 } }) : null }) : null,
3413
+ o.icon ? /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("span", { className: "fd-opt-icon", children: /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("i", { className: "ph ph-" + o.icon }) }) : null,
3414
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("span", { style: { flex: 1, minWidth: 0 }, children: [
3415
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("span", { className: "fd-opt-label", children: o.label }),
3416
+ o.description ? /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("span", { className: "fd-opt-desc", children: o.description }) : null
3168
3417
  ] }),
3169
- o.meta ? /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("span", { className: "fd-opt-meta", children: o.meta }) : null,
3170
- multiple ? null : /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("span", { className: "fd-opt-check", children: o.value === value ? /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("i", { className: "ph ph-check" }) : null })
3418
+ o.meta ? /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("span", { className: "fd-opt-meta", children: o.meta }) : null,
3419
+ multiple ? null : /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("span", { className: "fd-opt-check", children: o.value === value ? /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("i", { className: "ph ph-check" }) : null })
3171
3420
  ]
3172
3421
  },
3173
3422
  String(o.value)
3174
3423
  ))
3175
3424
  ] }, grp.g || "_")) }),
3176
- multiple ? /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("div", { className: "fd-row", style: { gap: 10, padding: "8px 12px", borderTop: "1px solid var(--border)" }, children: [
3177
- /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
3425
+ multiple ? /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("div", { className: "fd-row", style: { gap: 10, padding: "8px 12px", borderTop: "1px solid var(--border)" }, children: [
3426
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
3178
3427
  "button",
3179
3428
  {
3180
3429
  type: "button",
@@ -3183,13 +3432,13 @@ function Select({
3183
3432
  children: "Select all"
3184
3433
  }
3185
3434
  ),
3186
- /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("span", { style: { flex: 1 } }),
3187
- /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("span", { className: "fd-body-sm fd-muted", children: [
3435
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("span", { style: { flex: 1 } }),
3436
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("span", { className: "fd-body-sm fd-muted", children: [
3188
3437
  vals.length,
3189
3438
  " of ",
3190
3439
  opts.length
3191
3440
  ] }),
3192
- /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
3441
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
3193
3442
  "button",
3194
3443
  {
3195
3444
  type: "button",
@@ -3205,17 +3454,17 @@ function Select({
3205
3454
  ),
3206
3455
  document.body
3207
3456
  ) : null,
3208
- error ? /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("span", { className: "fd-field-error", children: [
3209
- /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
3457
+ error ? /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("span", { className: "fd-field-error", children: [
3458
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
3210
3459
  error
3211
- ] }) : help ? /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("span", { className: "fd-field-help", children: help }) : null
3460
+ ] }) : help ? /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("span", { className: "fd-field-help", children: help }) : null
3212
3461
  ] });
3213
3462
  }
3214
3463
 
3215
3464
  // src/components/forms/DatePicker.tsx
3216
- var React18 = __toESM(require("react"), 1);
3465
+ var React20 = __toESM(require("react"), 1);
3217
3466
  var import_react_dom5 = require("react-dom");
3218
- var import_jsx_runtime46 = require("react/jsx-runtime");
3467
+ var import_jsx_runtime49 = require("react/jsx-runtime");
3219
3468
  var MONTHS = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
3220
3469
  var DOW = ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"];
3221
3470
  var iso = (d) => d.getFullYear() + "-" + String(d.getMonth() + 1).padStart(2, "0") + "-" + String(d.getDate()).padStart(2, "0");
@@ -3229,8 +3478,8 @@ var fmt = (s) => {
3229
3478
  return d ? MONTHS[d.getMonth()].slice(0, 3) + " " + d.getDate() + ", " + d.getFullYear() : "";
3230
3479
  };
3231
3480
  function usePopPos2(open, ref, estH, estW) {
3232
- const [pos, setPos] = React18.useState(null);
3233
- React18.useLayoutEffect(() => {
3481
+ const [pos, setPos] = React20.useState(null);
3482
+ React20.useLayoutEffect(() => {
3234
3483
  if (!open || !ref.current) {
3235
3484
  setPos(null);
3236
3485
  return;
@@ -3274,10 +3523,10 @@ function Calendar({ value, range = false, onPick, initialMonth, months = 1 }) {
3274
3523
  const today = /* @__PURE__ */ new Date();
3275
3524
  const sel = range ? value || {} : { start: value, end: value };
3276
3525
  const anchor = parse(sel.start) || parse(initialMonth) || today;
3277
- const [vy, setVy] = React18.useState(anchor.getFullYear());
3278
- const [vm, setVm] = React18.useState(anchor.getMonth());
3279
- const [mode2, setMode] = React18.useState("days");
3280
- const [hover, setHover] = React18.useState(null);
3526
+ const [vy, setVy] = React20.useState(anchor.getFullYear());
3527
+ const [vm, setVm] = React20.useState(anchor.getMonth());
3528
+ const [mode2, setMode] = React20.useState("days");
3529
+ const [hover, setHover] = React20.useState(null);
3281
3530
  const s = parse(sel.start), e = parse(sel.end);
3282
3531
  const hoverEnd = range && s && !e && hover ? parse(hover) : null;
3283
3532
  const inRange = (d) => {
@@ -3314,9 +3563,9 @@ function Calendar({ value, range = false, onPick, initialMonth, months = 1 }) {
3314
3563
  const startPad = new Date(y, m, 1).getDay();
3315
3564
  const cells = [];
3316
3565
  for (let i = 0; i < 42; i++) cells.push(new Date(y, m, i - startPad + 1));
3317
- return /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: "fd-cal-grid", style: { width: months > 1 ? 252 : "auto", flex: "none" }, onMouseLeave: () => setHover(null), children: [
3318
- DOW.map((d) => /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("span", { className: "fd-cal-dow", children: d }, d)),
3319
- cells.map((d, i) => /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
3566
+ return /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("div", { className: "fd-cal-grid", style: { width: months > 1 ? 252 : "auto", flex: "none" }, onMouseLeave: () => setHover(null), children: [
3567
+ DOW.map((d) => /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("span", { className: "fd-cal-dow", children: d }, d)),
3568
+ cells.map((d, i) => /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(
3320
3569
  "button",
3321
3570
  {
3322
3571
  type: "button",
@@ -3330,20 +3579,20 @@ function Calendar({ value, range = false, onPick, initialMonth, months = 1 }) {
3330
3579
  ] });
3331
3580
  };
3332
3581
  const nextY = vm === 11 ? vy + 1 : vy, nextM = (vm + 1) % 12;
3333
- return /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: "fd-cal", style: { width: months > 1 && mode2 === "days" ? "auto" : void 0 }, children: [
3334
- /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: "fd-cal-head", children: [
3335
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("button", { type: "button", className: "fd-btn-icon", "aria-label": "Previous", onClick: () => mode2 === "years" ? setVy(vy - 12) : mode2 === "months" ? setVy(vy - 1) : nav(-1), children: /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("i", { className: "ph ph-caret-left" }) }),
3336
- /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("button", { type: "button", className: "fd-cal-title", onClick: () => setMode(mode2 === "days" ? "months" : mode2 === "months" ? "years" : "days"), children: [
3582
+ return /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("div", { className: "fd-cal", style: { width: months > 1 && mode2 === "days" ? "auto" : void 0 }, children: [
3583
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("div", { className: "fd-cal-head", children: [
3584
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("button", { type: "button", className: "fd-btn-icon", "aria-label": "Previous", onClick: () => mode2 === "years" ? setVy(vy - 12) : mode2 === "months" ? setVy(vy - 1) : nav(-1), children: /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("i", { className: "ph ph-caret-left" }) }),
3585
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("button", { type: "button", className: "fd-cal-title", onClick: () => setMode(mode2 === "days" ? "months" : mode2 === "months" ? "years" : "days"), children: [
3337
3586
  mode2 === "days" ? MONTHS[vm] + " " + vy : mode2 === "months" ? vy : vy - 5 + " \u2013 " + (vy + 6),
3338
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("i", { className: "ph ph-caret-down", style: { fontSize: 10, marginLeft: 6, color: "var(--text-muted)" } })
3587
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("i", { className: "ph ph-caret-down", style: { fontSize: 10, marginLeft: 6, color: "var(--text-muted)" } })
3339
3588
  ] }),
3340
- months > 1 && mode2 === "days" ? /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("span", { className: "fd-cal-title", style: { cursor: "default", background: "none" }, children: MONTHS[nextM] + " " + nextY }) : null,
3341
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("button", { type: "button", className: "fd-btn-icon", "aria-label": "Next", onClick: () => mode2 === "years" ? setVy(vy + 12) : mode2 === "months" ? setVy(vy + 1) : nav(1), children: /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("i", { className: "ph ph-caret-right" }) })
3589
+ months > 1 && mode2 === "days" ? /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("span", { className: "fd-cal-title", style: { cursor: "default", background: "none" }, children: MONTHS[nextM] + " " + nextY }) : null,
3590
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("button", { type: "button", className: "fd-btn-icon", "aria-label": "Next", onClick: () => mode2 === "years" ? setVy(vy + 12) : mode2 === "months" ? setVy(vy + 1) : nav(1), children: /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("i", { className: "ph ph-caret-right" }) })
3342
3591
  ] }),
3343
- mode2 === "days" ? /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { style: { display: "flex", gap: 18 }, children: [
3592
+ mode2 === "days" ? /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("div", { style: { display: "flex", gap: 18 }, children: [
3344
3593
  monthGrid(vy, vm),
3345
3594
  months > 1 ? monthGrid(nextY, nextM) : null
3346
- ] }) : mode2 === "months" ? /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("div", { className: "fd-cal-grid-months", children: MONTHS.map((m, i) => /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
3595
+ ] }) : mode2 === "months" ? /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("div", { className: "fd-cal-grid-months", children: MONTHS.map((m, i) => /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(
3347
3596
  "button",
3348
3597
  {
3349
3598
  type: "button",
@@ -3355,7 +3604,7 @@ function Calendar({ value, range = false, onPick, initialMonth, months = 1 }) {
3355
3604
  children: m.slice(0, 3)
3356
3605
  },
3357
3606
  m
3358
- )) }) : /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("div", { className: "fd-cal-grid-months", children: Array.from({ length: 12 }, (_, i) => vy - 5 + i).map((y) => /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
3607
+ )) }) : /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("div", { className: "fd-cal-grid-months", children: Array.from({ length: 12 }, (_, i) => vy - 5 + i).map((y) => /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(
3359
3608
  "button",
3360
3609
  {
3361
3610
  type: "button",
@@ -3368,8 +3617,8 @@ function Calendar({ value, range = false, onPick, initialMonth, months = 1 }) {
3368
3617
  },
3369
3618
  y
3370
3619
  )) }),
3371
- /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: "fd-cal-foot", children: [
3372
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
3620
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("div", { className: "fd-cal-foot", children: [
3621
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(
3373
3622
  "button",
3374
3623
  {
3375
3624
  type: "button",
@@ -3383,8 +3632,8 @@ function Calendar({ value, range = false, onPick, initialMonth, months = 1 }) {
3383
3632
  children: "Today"
3384
3633
  }
3385
3634
  ),
3386
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("span", { style: { flex: 1 } }),
3387
- range && sel.start ? /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("span", { className: "fd-body-sm fd-muted", children: [
3635
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("span", { style: { flex: 1 } }),
3636
+ range && sel.start ? /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("span", { className: "fd-body-sm fd-muted", children: [
3388
3637
  fmt(sel.start),
3389
3638
  sel.end ? " \u2192 " + fmt(sel.end) : " \u2192 pick an end"
3390
3639
  ] }) : null
@@ -3392,12 +3641,12 @@ function Calendar({ value, range = false, onPick, initialMonth, months = 1 }) {
3392
3641
  ] });
3393
3642
  }
3394
3643
  function DatePicker({ label, help, error, required = false, disabled = false, range = false, value, onChange, placeholder, className = "", style, ...rest }) {
3395
- const [open, setOpen] = React18.useState(false);
3396
- const rootRef = React18.useRef(null);
3397
- const boxRef = React18.useRef(null);
3398
- const popRef = React18.useRef(null);
3644
+ const [open, setOpen] = React20.useState(false);
3645
+ const rootRef = React20.useRef(null);
3646
+ const boxRef = React20.useRef(null);
3647
+ const popRef = React20.useRef(null);
3399
3648
  const pos = usePopPos2(open, boxRef, 430, range ? 600 : 316);
3400
- React18.useEffect(() => {
3649
+ React20.useEffect(() => {
3401
3650
  if (!open) return;
3402
3651
  const away = (e) => {
3403
3652
  if (rootRef.current && rootRef.current.contains(e.target)) return;
@@ -3418,14 +3667,14 @@ function DatePicker({ label, help, error, required = false, disabled = false, ra
3418
3667
  const toggle = () => {
3419
3668
  if (!disabled) setOpen(!open);
3420
3669
  };
3421
- return /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: ["fd-field", "fd-popfield", open ? "is-open" : "", className].filter(Boolean).join(" "), style, ref: rootRef, children: [
3422
- label ? /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("label", { className: "fd-field-label", onClick: toggle, children: [
3670
+ return /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("div", { className: ["fd-field", "fd-popfield", open ? "is-open" : "", className].filter(Boolean).join(" "), style, ref: rootRef, children: [
3671
+ label ? /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("label", { className: "fd-field-label", onClick: toggle, children: [
3423
3672
  label,
3424
- required ? /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("span", { className: "fd-field-req", children: "*" }) : null
3673
+ required ? /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("span", { className: "fd-field-req", children: "*" }) : null
3425
3674
  ] }) : null,
3426
- /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: ["fd-input", error ? "fd-input-error" : "", disabled ? "fd-input-disabled" : ""].filter(Boolean).join(" "), style: { cursor: disabled ? "not-allowed" : "pointer" }, onClick: toggle, ref: boxRef, children: [
3427
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("span", { className: "fd-input-icon", children: /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("i", { className: "ph ph-calendar-blank", "aria-hidden": "true" }) }),
3428
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
3675
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("div", { className: ["fd-input", error ? "fd-input-error" : "", disabled ? "fd-input-disabled" : ""].filter(Boolean).join(" "), style: { cursor: disabled ? "not-allowed" : "pointer" }, onClick: toggle, ref: boxRef, children: [
3676
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("span", { className: "fd-input-icon", children: /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("i", { className: "ph ph-calendar-blank", "aria-hidden": "true" }) }),
3677
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(
3429
3678
  "button",
3430
3679
  {
3431
3680
  type: "button",
@@ -3441,10 +3690,10 @@ function DatePicker({ label, help, error, required = false, disabled = false, ra
3441
3690
  children: display || placeholder || (range ? "Pick a date range" : "Pick a date")
3442
3691
  }
3443
3692
  ),
3444
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("span", { className: "fd-select-caret", children: /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("i", { className: "ph ph-caret-down", "aria-hidden": "true" }) })
3693
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("span", { className: "fd-select-caret", children: /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("i", { className: "ph ph-caret-down", "aria-hidden": "true" }) })
3445
3694
  ] }),
3446
3695
  open && pos ? (0, import_react_dom5.createPortal)(
3447
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("div", { className: "fd-pop" + (pos.up ? " is-up" : ""), ref: popRef, style: popStyle2(pos, { width: "max-content", minWidth: 0, zIndex: 130 }), children: /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
3696
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("div", { className: "fd-pop" + (pos.up ? " is-up" : ""), ref: popRef, style: popStyle2(pos, { width: "max-content", minWidth: 0, zIndex: 130 }), children: /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(
3448
3697
  Calendar,
3449
3698
  {
3450
3699
  range,
@@ -3458,21 +3707,21 @@ function DatePicker({ label, help, error, required = false, disabled = false, ra
3458
3707
  ) }),
3459
3708
  document.body
3460
3709
  ) : null,
3461
- error ? /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("span", { className: "fd-field-error", children: [
3462
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
3710
+ error ? /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("span", { className: "fd-field-error", children: [
3711
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
3463
3712
  error
3464
- ] }) : help ? /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("span", { className: "fd-field-help", children: help }) : null
3713
+ ] }) : help ? /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("span", { className: "fd-field-help", children: help }) : null
3465
3714
  ] });
3466
3715
  }
3467
3716
 
3468
3717
  // src/components/forms/TimePicker.tsx
3469
- var React19 = __toESM(require("react"), 1);
3718
+ var React21 = __toESM(require("react"), 1);
3470
3719
  var import_react_dom6 = require("react-dom");
3471
- var import_jsx_runtime47 = require("react/jsx-runtime");
3720
+ var import_jsx_runtime50 = require("react/jsx-runtime");
3472
3721
  var pad = (n) => String(n).padStart(2, "0");
3473
3722
  function usePopPos3(open, ref, estH, estW) {
3474
- const [pos, setPos] = React19.useState(null);
3475
- React19.useLayoutEffect(() => {
3723
+ const [pos, setPos] = React21.useState(null);
3724
+ React21.useLayoutEffect(() => {
3476
3725
  if (!open || !ref.current) {
3477
3726
  setPos(null);
3478
3727
  return;
@@ -3518,9 +3767,9 @@ function ClockFace({ value = "09:00", onChange }) {
3518
3767
  if (isNaN(m)) m = 0;
3519
3768
  const pm = h24 >= 12;
3520
3769
  const h12 = h24 % 12 === 0 ? 12 : h24 % 12;
3521
- const [mode2, setMode] = React19.useState("h");
3522
- const faceRef = React19.useRef(null);
3523
- const dragging = React19.useRef(false);
3770
+ const [mode2, setMode] = React21.useState("h");
3771
+ const faceRef = React21.useRef(null);
3772
+ const dragging = React21.useRef(false);
3524
3773
  const set = (h, mm, isPm) => onChange((isPm ? h % 12 + 12 : h % 12) + ":" + pad(mm));
3525
3774
  const R = 108, NR = 80;
3526
3775
  const nums = mode2 === "h" ? Array.from({ length: 12 }, (_, i) => i + 1) : Array.from({ length: 12 }, (_, i) => i * 5);
@@ -3555,12 +3804,12 @@ function ClockFace({ value = "09:00", onChange }) {
3555
3804
  };
3556
3805
  const handAngle = mode2 === "h" ? h12 % 12 * 30 : m * 6;
3557
3806
  const minuteOff = mode2 === "m" && m % 5 !== 0;
3558
- return /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { style: { padding: "4px 14px 14px" }, children: [
3559
- /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: "fd-clock-digits", children: [
3560
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("button", { type: "button", className: "fd-clock-digit" + (mode2 === "h" ? " is-active" : ""), onClick: () => setMode("h"), children: pad(h12) }),
3561
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("span", { style: { fontSize: 24, fontWeight: 700, color: "var(--text-muted)" }, children: ":" }),
3562
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("button", { type: "button", className: "fd-clock-digit" + (mode2 === "m" ? " is-active" : ""), onClick: () => setMode("m"), children: pad(m) }),
3563
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("span", { className: "fd-stack", style: { gap: 3, marginLeft: 8 }, children: ["AM", "PM"].map((ap) => /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
3807
+ return /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)("div", { style: { padding: "4px 14px 14px" }, children: [
3808
+ /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)("div", { className: "fd-clock-digits", children: [
3809
+ /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("button", { type: "button", className: "fd-clock-digit" + (mode2 === "h" ? " is-active" : ""), onClick: () => setMode("h"), children: pad(h12) }),
3810
+ /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("span", { style: { fontSize: 24, fontWeight: 700, color: "var(--text-muted)" }, children: ":" }),
3811
+ /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("button", { type: "button", className: "fd-clock-digit" + (mode2 === "m" ? " is-active" : ""), onClick: () => setMode("m"), children: pad(m) }),
3812
+ /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("span", { className: "fd-stack", style: { gap: 3, marginLeft: 8 }, children: ["AM", "PM"].map((ap) => /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(
3564
3813
  "button",
3565
3814
  {
3566
3815
  type: "button",
@@ -3571,13 +3820,13 @@ function ClockFace({ value = "09:00", onChange }) {
3571
3820
  ap
3572
3821
  )) })
3573
3822
  ] }),
3574
- /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: "fd-clock", ref: faceRef, onPointerDown: down, onPointerMove: move, onPointerUp: upH, children: [
3575
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("span", { className: "fd-clock-hand", style: { height: NR - (minuteOff ? 14 : 16), transform: "translateX(-50%) rotate(" + handAngle + "deg)", bottom: "50%" } }),
3576
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("span", { className: "fd-clock-pivot" }),
3577
- minuteOff ? /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("span", { style: { position: "absolute", left: "50%", top: "50%", width: 10, height: 10, margin: -5, borderRadius: "50%", border: "2px solid var(--brand)", background: "var(--surface)", transform: "rotate(" + handAngle + "deg) translateY(-" + (NR - 6) + "px)", transformOrigin: "center", pointerEvents: "none" } }) : null,
3823
+ /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)("div", { className: "fd-clock", ref: faceRef, onPointerDown: down, onPointerMove: move, onPointerUp: upH, children: [
3824
+ /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("span", { className: "fd-clock-hand", style: { height: NR - (minuteOff ? 14 : 16), transform: "translateX(-50%) rotate(" + handAngle + "deg)", bottom: "50%" } }),
3825
+ /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("span", { className: "fd-clock-pivot" }),
3826
+ minuteOff ? /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("span", { style: { position: "absolute", left: "50%", top: "50%", width: 10, height: 10, margin: -5, borderRadius: "50%", border: "2px solid var(--brand)", background: "var(--surface)", transform: "rotate(" + handAngle + "deg) translateY(-" + (NR - 6) + "px)", transformOrigin: "center", pointerEvents: "none" } }) : null,
3578
3827
  nums.map((n) => {
3579
3828
  const a = angleOf(n) * Math.PI / 180;
3580
- return /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
3829
+ return /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(
3581
3830
  "span",
3582
3831
  {
3583
3832
  className: "fd-clock-num" + (n === selNum || mode2 === "m" && n === Math.round(m / 5) * 5 % 60 && m % 5 === 0 ? " is-sel" : ""),
@@ -3588,16 +3837,16 @@ function ClockFace({ value = "09:00", onChange }) {
3588
3837
  );
3589
3838
  })
3590
3839
  ] }),
3591
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("div", { className: "fd-row", style: { justifyContent: "center", gap: 6 }, children: /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("span", { className: "fd-body-sm fd-muted", children: mode2 === "h" ? "Pick the hour \u2014 drag or tap" : "Now the minutes" }) })
3840
+ /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("div", { className: "fd-row", style: { justifyContent: "center", gap: 6 }, children: /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("span", { className: "fd-body-sm fd-muted", children: mode2 === "h" ? "Pick the hour \u2014 drag or tap" : "Now the minutes" }) })
3592
3841
  ] });
3593
3842
  }
3594
3843
  function TimePicker({ label, help, error, required = false, disabled = false, value = "", onChange, placeholder = "Pick a time", className = "", style }) {
3595
- const [open, setOpen] = React19.useState(false);
3596
- const rootRef = React19.useRef(null);
3597
- const boxRef = React19.useRef(null);
3598
- const popRef = React19.useRef(null);
3844
+ const [open, setOpen] = React21.useState(false);
3845
+ const rootRef = React21.useRef(null);
3846
+ const boxRef = React21.useRef(null);
3847
+ const popRef = React21.useRef(null);
3599
3848
  const pos = usePopPos3(open, boxRef, 420, 262);
3600
- React19.useEffect(() => {
3849
+ React21.useEffect(() => {
3601
3850
  if (!open) return;
3602
3851
  const away = (e) => {
3603
3852
  if (rootRef.current && rootRef.current.contains(e.target)) return;
@@ -3622,14 +3871,14 @@ function TimePicker({ label, help, error, required = false, disabled = false, va
3622
3871
  const toggle = () => {
3623
3872
  if (!disabled) setOpen(!open);
3624
3873
  };
3625
- return /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: ["fd-field", "fd-popfield", open ? "is-open" : "", className].filter(Boolean).join(" "), style, ref: rootRef, children: [
3626
- label ? /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("label", { className: "fd-field-label", onClick: toggle, children: [
3874
+ return /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)("div", { className: ["fd-field", "fd-popfield", open ? "is-open" : "", className].filter(Boolean).join(" "), style, ref: rootRef, children: [
3875
+ label ? /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)("label", { className: "fd-field-label", onClick: toggle, children: [
3627
3876
  label,
3628
- required ? /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("span", { className: "fd-field-req", children: "*" }) : null
3877
+ required ? /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("span", { className: "fd-field-req", children: "*" }) : null
3629
3878
  ] }) : null,
3630
- /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: ["fd-input", error ? "fd-input-error" : "", disabled ? "fd-input-disabled" : ""].filter(Boolean).join(" "), style: { cursor: disabled ? "not-allowed" : "pointer" }, onClick: toggle, ref: boxRef, children: [
3631
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("span", { className: "fd-input-icon", children: /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("i", { className: "ph ph-clock", "aria-hidden": "true" }) }),
3632
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
3879
+ /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)("div", { className: ["fd-input", error ? "fd-input-error" : "", disabled ? "fd-input-disabled" : ""].filter(Boolean).join(" "), style: { cursor: disabled ? "not-allowed" : "pointer" }, onClick: toggle, ref: boxRef, children: [
3880
+ /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("span", { className: "fd-input-icon", children: /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("i", { className: "ph ph-clock", "aria-hidden": "true" }) }),
3881
+ /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(
3633
3882
  "button",
3634
3883
  {
3635
3884
  type: "button",
@@ -3644,13 +3893,13 @@ function TimePicker({ label, help, error, required = false, disabled = false, va
3644
3893
  children: disp() || placeholder
3645
3894
  }
3646
3895
  ),
3647
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("span", { className: "fd-select-caret", children: /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("i", { className: "ph ph-caret-down", "aria-hidden": "true" }) })
3896
+ /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("span", { className: "fd-select-caret", children: /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("i", { className: "ph ph-caret-down", "aria-hidden": "true" }) })
3648
3897
  ] }),
3649
3898
  open && pos ? (0, import_react_dom6.createPortal)(
3650
- /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: "fd-pop" + (pos.up ? " is-up" : ""), ref: popRef, style: popStyle3(pos, { width: 262, minWidth: 0, zIndex: 130 }), children: [
3651
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(ClockFace, { value: value || "09:00", onChange: (v) => onChange && onChange({ target: { value: v } }) }),
3652
- /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: "fd-cal-foot", style: { margin: "0 14px 12px", paddingTop: 10 }, children: [
3653
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
3899
+ /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)("div", { className: "fd-pop" + (pos.up ? " is-up" : ""), ref: popRef, style: popStyle3(pos, { width: 262, minWidth: 0, zIndex: 130 }), children: [
3900
+ /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(ClockFace, { value: value || "09:00", onChange: (v) => onChange && onChange({ target: { value: v } }) }),
3901
+ /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)("div", { className: "fd-cal-foot", style: { margin: "0 14px 12px", paddingTop: 10 }, children: [
3902
+ /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(
3654
3903
  "button",
3655
3904
  {
3656
3905
  type: "button",
@@ -3663,22 +3912,22 @@ function TimePicker({ label, help, error, required = false, disabled = false, va
3663
3912
  children: "Now"
3664
3913
  }
3665
3914
  ),
3666
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("span", { style: { flex: 1 } }),
3667
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("button", { type: "button", className: "fd-btn fd-btn-primary fd-btn-sm", onClick: () => setOpen(false), children: "Done" })
3915
+ /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("span", { style: { flex: 1 } }),
3916
+ /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("button", { type: "button", className: "fd-btn fd-btn-primary fd-btn-sm", onClick: () => setOpen(false), children: "Done" })
3668
3917
  ] })
3669
3918
  ] }),
3670
3919
  document.body
3671
3920
  ) : null,
3672
- error ? /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("span", { className: "fd-field-error", children: [
3673
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
3921
+ error ? /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)("span", { className: "fd-field-error", children: [
3922
+ /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
3674
3923
  error
3675
- ] }) : help ? /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("span", { className: "fd-field-help", children: help }) : null
3924
+ ] }) : help ? /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("span", { className: "fd-field-help", children: help }) : null
3676
3925
  ] });
3677
3926
  }
3678
3927
 
3679
3928
  // src/components/forms/Slider.tsx
3680
- var React20 = __toESM(require("react"), 1);
3681
- var import_jsx_runtime48 = require("react/jsx-runtime");
3929
+ var React22 = __toESM(require("react"), 1);
3930
+ var import_jsx_runtime51 = require("react/jsx-runtime");
3682
3931
  function Slider({
3683
3932
  label,
3684
3933
  min = 0,
@@ -3692,18 +3941,18 @@ function Slider({
3692
3941
  className = "",
3693
3942
  ...rest
3694
3943
  }) {
3695
- const [dragging, setDragging] = React20.useState(false);
3944
+ const [dragging, setDragging] = React22.useState(false);
3696
3945
  const v = value === void 0 ? min : Number(value);
3697
3946
  const pct = max === min ? 0 : (v - min) / (max - min) * 100;
3698
- return /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("div", { className: ["fd-field", className].filter(Boolean).join(" "), children: [
3699
- label ? /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("div", { className: "fd-row", style: { justifyContent: "space-between", gap: 12 }, children: [
3700
- /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("span", { className: "fd-field-label", children: label }),
3701
- /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("span", { className: "fd-num", style: { color: "var(--text-2)" }, children: format(v) })
3947
+ return /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)("div", { className: ["fd-field", className].filter(Boolean).join(" "), children: [
3948
+ label ? /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)("div", { className: "fd-row", style: { justifyContent: "space-between", gap: 12 }, children: [
3949
+ /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("span", { className: "fd-field-label", children: label }),
3950
+ /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("span", { className: "fd-num", style: { color: "var(--text-2)" }, children: format(v) })
3702
3951
  ] }) : null,
3703
- /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("div", { className: "fd-slider", children: [
3704
- /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("span", { className: "fd-slider-fill", style: { width: pct + "%" } }),
3705
- showChip && dragging ? /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("span", { className: "fd-slider-chip", style: { left: pct + "%" }, children: format(v) }) : null,
3706
- /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
3952
+ /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)("div", { className: "fd-slider", children: [
3953
+ /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("span", { className: "fd-slider-fill", style: { width: pct + "%" } }),
3954
+ showChip && dragging ? /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("span", { className: "fd-slider-chip", style: { left: pct + "%" }, children: format(v) }) : null,
3955
+ /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(
3707
3956
  "input",
3708
3957
  {
3709
3958
  type: "range",
@@ -3720,13 +3969,13 @@ function Slider({
3720
3969
  }
3721
3970
  )
3722
3971
  ] }),
3723
- help ? /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("span", { className: "fd-field-help", children: help }) : null
3972
+ help ? /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("span", { className: "fd-field-help", children: help }) : null
3724
3973
  ] });
3725
3974
  }
3726
3975
 
3727
3976
  // src/components/forms/RangeSlider.tsx
3728
- var React21 = __toESM(require("react"), 1);
3729
- var import_jsx_runtime49 = require("react/jsx-runtime");
3977
+ var React23 = __toESM(require("react"), 1);
3978
+ var import_jsx_runtime52 = require("react/jsx-runtime");
3730
3979
  function RangeSlider({
3731
3980
  label,
3732
3981
  min = 0,
@@ -3745,9 +3994,9 @@ function RangeSlider({
3745
3994
  }) {
3746
3995
  const fmt2 = format || ((v) => String(v));
3747
3996
  const [a, b] = value || [min, max];
3748
- const [drag, setDrag] = React21.useState(null);
3749
- const [focus, setFocus] = React21.useState(null);
3750
- const railRef = React21.useRef(null);
3997
+ const [drag, setDrag] = React23.useState(null);
3998
+ const [focus, setFocus] = React23.useState(null);
3999
+ const railRef = React23.useRef(null);
3751
4000
  const pct = (v) => max === min ? 0 : (v - min) / (max - min) * 100;
3752
4001
  const clampPair = (i, v) => {
3753
4002
  v = Math.min(max, Math.max(min, Math.round(v / step) * step));
@@ -3762,7 +4011,7 @@ function RangeSlider({
3762
4011
  const r = railRef.current.getBoundingClientRect();
3763
4012
  return min + Math.min(1, Math.max(0, (e.clientX - r.left) / r.width)) * (max - min);
3764
4013
  };
3765
- React21.useEffect(() => {
4014
+ React23.useEffect(() => {
3766
4015
  if (drag === null) return;
3767
4016
  const mv = (e) => onChange && onChange(clampPair(drag, fromEvent(e)));
3768
4017
  const upH = () => setDrag(null);
@@ -3783,7 +4032,7 @@ function RangeSlider({
3783
4032
  };
3784
4033
  const thin = S.length > 7 ? Math.ceil(S.length / 5) : 1;
3785
4034
  const pair = value || [S[0].value, S[S.length - 1].value];
3786
- return /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(
4035
+ return /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(
3787
4036
  RangeSlider,
3788
4037
  {
3789
4038
  ...rest,
@@ -3831,23 +4080,23 @@ function RangeSlider({
3831
4080
  };
3832
4081
  const showChip = (i) => drag === i || focus === i;
3833
4082
  const hasLabels = marks.some((m) => m.label);
3834
- return /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("div", { className: ["fd-field", className].filter(Boolean).join(" "), ...rest, children: [
3835
- label ? /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("div", { className: "fd-row", style: { justifyContent: "space-between", gap: 12 }, children: [
3836
- /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("span", { className: "fd-field-label", children: label }),
3837
- /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("span", { className: "fd-num", style: { color: "var(--text-2)" }, children: [
4083
+ return /* @__PURE__ */ (0, import_jsx_runtime52.jsxs)("div", { className: ["fd-field", className].filter(Boolean).join(" "), ...rest, children: [
4084
+ label ? /* @__PURE__ */ (0, import_jsx_runtime52.jsxs)("div", { className: "fd-row", style: { justifyContent: "space-between", gap: 12 }, children: [
4085
+ /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("span", { className: "fd-field-label", children: label }),
4086
+ /* @__PURE__ */ (0, import_jsx_runtime52.jsxs)("span", { className: "fd-num", style: { color: "var(--text-2)" }, children: [
3838
4087
  fmt2(a),
3839
4088
  " \u2013 ",
3840
4089
  fmt2(b)
3841
4090
  ] })
3842
4091
  ] }) : null,
3843
- /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("div", { className: "fd-range" + (hasLabels ? " has-labels" : ""), onPointerDown: onRailDown, children: [
3844
- /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("span", { className: "fd-range-rail", ref: railRef }),
3845
- /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("span", { className: "fd-range-fill", style: { left: pct(a) + "%", width: pct(b) - pct(a) + "%" } }),
3846
- marks.map((m) => /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)(React21.Fragment, { children: [
3847
- /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("span", { className: "fd-range-mark" + (m.value >= a && m.value <= b ? " is-in" : ""), style: { left: pct(m.value) + "%" } }),
3848
- m.label ? /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("span", { className: "fd-range-mark-label", style: { left: pct(m.value) + "%" }, children: m.label }) : null
4092
+ /* @__PURE__ */ (0, import_jsx_runtime52.jsxs)("div", { className: "fd-range" + (hasLabels ? " has-labels" : ""), onPointerDown: onRailDown, children: [
4093
+ /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("span", { className: "fd-range-rail", ref: railRef }),
4094
+ /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("span", { className: "fd-range-fill", style: { left: pct(a) + "%", width: pct(b) - pct(a) + "%" } }),
4095
+ marks.map((m) => /* @__PURE__ */ (0, import_jsx_runtime52.jsxs)(React23.Fragment, { children: [
4096
+ /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("span", { className: "fd-range-mark" + (m.value >= a && m.value <= b ? " is-in" : ""), style: { left: pct(m.value) + "%" } }),
4097
+ m.label ? /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("span", { className: "fd-range-mark-label", style: { left: pct(m.value) + "%" }, children: m.label }) : null
3849
4098
  ] }, m.value)),
3850
- [a, b].map((v, i) => /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(
4099
+ [a, b].map((v, i) => /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(
3851
4100
  "span",
3852
4101
  {
3853
4102
  className: "fd-range-thumb" + (drag === i ? " is-drag" : ""),
@@ -3862,18 +4111,18 @@ function RangeSlider({
3862
4111
  onKeyDown: key(i),
3863
4112
  onFocus: () => setFocus(i),
3864
4113
  onBlur: () => setFocus(null),
3865
- children: /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("span", { className: "fd-range-chip", style: { opacity: showChip(i) ? 1 : void 0 }, children: fmt2(v) })
4114
+ children: /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("span", { className: "fd-range-chip", style: { opacity: showChip(i) ? 1 : void 0 }, children: fmt2(v) })
3866
4115
  },
3867
4116
  i
3868
4117
  ))
3869
4118
  ] }),
3870
- help ? /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("span", { className: "fd-field-help", children: help }) : null
4119
+ help ? /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("span", { className: "fd-field-help", children: help }) : null
3871
4120
  ] });
3872
4121
  }
3873
4122
 
3874
4123
  // src/components/forms/Dropzone.tsx
3875
- var React22 = __toESM(require("react"), 1);
3876
- var import_jsx_runtime50 = require("react/jsx-runtime");
4124
+ var React24 = __toESM(require("react"), 1);
4125
+ var import_jsx_runtime53 = require("react/jsx-runtime");
3877
4126
  function Dropzone({
3878
4127
  onFiles,
3879
4128
  onReject,
@@ -3887,8 +4136,8 @@ function Dropzone({
3887
4136
  className = "",
3888
4137
  style
3889
4138
  }) {
3890
- const [over, setOver] = React22.useState(false);
3891
- const depth = React22.useRef(0);
4139
+ const [over, setOver] = React24.useState(false);
4140
+ const depth = React24.useRef(0);
3892
4141
  const has = (e) => {
3893
4142
  const dt = e.dataTransfer;
3894
4143
  if (!dt) return false;
@@ -3918,7 +4167,7 @@ function Dropzone({
3918
4167
  if (rejected.length && onReject) onReject(rejected);
3919
4168
  if (accepted.length && onFiles) onFiles(accepted);
3920
4169
  };
3921
- return /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)(
4170
+ return /* @__PURE__ */ (0, import_jsx_runtime53.jsxs)(
3922
4171
  "div",
3923
4172
  {
3924
4173
  className: ["fd-dropzone", over ? "is-over" : "", className].filter(Boolean).join(" "),
@@ -3929,10 +4178,10 @@ function Dropzone({
3929
4178
  onDrop: drop,
3930
4179
  children: [
3931
4180
  children,
3932
- over ? /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("div", { className: "fd-dropzone-veil", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)("div", { className: "fd-dropzone-card", children: [
3933
- /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("i", { className: "ph ph-tray-arrow-down" }),
3934
- /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("span", { className: "fd-dropzone-label", children: label }),
3935
- hint ? /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("span", { className: "fd-dropzone-hint", children: hint }) : null
4181
+ over ? /* @__PURE__ */ (0, import_jsx_runtime53.jsx)("div", { className: "fd-dropzone-veil", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime53.jsxs)("div", { className: "fd-dropzone-card", children: [
4182
+ /* @__PURE__ */ (0, import_jsx_runtime53.jsx)("i", { className: "ph ph-tray-arrow-down" }),
4183
+ /* @__PURE__ */ (0, import_jsx_runtime53.jsx)("span", { className: "fd-dropzone-label", children: label }),
4184
+ hint ? /* @__PURE__ */ (0, import_jsx_runtime53.jsx)("span", { className: "fd-dropzone-hint", children: hint }) : null
3936
4185
  ] }) }) : null
3937
4186
  ]
3938
4187
  }
@@ -3950,9 +4199,9 @@ function FilePickButton({
3950
4199
  className = "",
3951
4200
  children
3952
4201
  }) {
3953
- const ref = React22.useRef(null);
3954
- return /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)(React22.Fragment, { children: [
3955
- /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(
4202
+ const ref = React24.useRef(null);
4203
+ return /* @__PURE__ */ (0, import_jsx_runtime53.jsxs)(React24.Fragment, { children: [
4204
+ /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(
3956
4205
  "button",
3957
4206
  {
3958
4207
  type: "button",
@@ -3961,10 +4210,10 @@ function FilePickButton({
3961
4210
  "aria-label": label,
3962
4211
  title: label,
3963
4212
  onClick: () => ref.current && ref.current.click(),
3964
- children: children != null ? children : /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("i", { className: "ph ph-" + icon, "aria-hidden": "true" })
4213
+ children: children != null ? children : /* @__PURE__ */ (0, import_jsx_runtime53.jsx)("i", { className: "ph ph-" + icon, "aria-hidden": "true" })
3965
4214
  }
3966
4215
  ),
3967
- /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(
4216
+ /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(
3968
4217
  "input",
3969
4218
  {
3970
4219
  ref,
@@ -3984,10 +4233,10 @@ function FilePickButton({
3984
4233
  }
3985
4234
  function useStagedFiles(upload, opts) {
3986
4235
  const o = opts || {};
3987
- const [items, setItems] = React22.useState([]);
3988
- const controllers = React22.useRef({});
4236
+ const [items, setItems] = React24.useState([]);
4237
+ const controllers = React24.useRef({});
3989
4238
  const patch = (id, next) => setItems((list) => list.map((f) => f.id === id ? Object.assign({}, f, next) : f));
3990
- const run = React22.useCallback((att) => {
4239
+ const run = React24.useCallback((att) => {
3991
4240
  if (!upload) return;
3992
4241
  const ac = typeof AbortController !== "undefined" ? new AbortController() : null;
3993
4242
  controllers.current[att.id] = ac;
@@ -4004,14 +4253,14 @@ function useStagedFiles(upload, opts) {
4004
4253
  delete controllers.current[att.id];
4005
4254
  });
4006
4255
  }, [upload]);
4007
- const add = React22.useCallback((files) => {
4256
+ const add = React24.useCallback((files) => {
4008
4257
  if (!upload) return [];
4009
4258
  const atts = Array.from(files).map((f) => toAttachment(f));
4010
4259
  setItems((list) => list.concat(atts));
4011
4260
  atts.forEach(run);
4012
4261
  return atts;
4013
4262
  }, [upload, run]);
4014
- const remove = React22.useCallback((att) => {
4263
+ const remove = React24.useCallback((att) => {
4015
4264
  const ac = controllers.current[att.id];
4016
4265
  if (ac) {
4017
4266
  try {
@@ -4022,10 +4271,10 @@ function useStagedFiles(upload, opts) {
4022
4271
  }
4023
4272
  setItems((list) => list.filter((f) => f.id !== att.id));
4024
4273
  }, []);
4025
- const retry = React22.useCallback((att) => {
4274
+ const retry = React24.useCallback((att) => {
4026
4275
  run(att);
4027
4276
  }, [run]);
4028
- const clear = React22.useCallback(() => {
4277
+ const clear = React24.useCallback(() => {
4029
4278
  Object.values(controllers.current).forEach((ac) => {
4030
4279
  try {
4031
4280
  ac && ac.abort();
@@ -4041,7 +4290,7 @@ function useStagedFiles(upload, opts) {
4041
4290
  var DropzoneKit = { useStagedFiles };
4042
4291
 
4043
4292
  // src/components/forms/FileGrid.tsx
4044
- var import_jsx_runtime51 = require("react/jsx-runtime");
4293
+ var import_jsx_runtime54 = require("react/jsx-runtime");
4045
4294
  var truncateMiddle = (name, max = 34) => {
4046
4295
  if (!name || name.length <= max) return name;
4047
4296
  const ext = /\.[A-Za-z0-9]+$/.exec(name);
@@ -4050,7 +4299,7 @@ var truncateMiddle = (name, max = 34) => {
4050
4299
  return head + "\u2026" + tail;
4051
4300
  };
4052
4301
  function Progress({ value }) {
4053
- return /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("span", { className: "fd-file-prog", role: "progressbar", "aria-valuenow": Math.round(value), "aria-valuemin": 0, "aria-valuemax": 100, children: /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("span", { className: "fd-file-prog-fill", style: { width: Math.max(4, Math.min(100, value)) + "%" } }) });
4302
+ return /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("span", { className: "fd-file-prog", role: "progressbar", "aria-valuenow": Math.round(value), "aria-valuemin": 0, "aria-valuemax": 100, children: /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("span", { className: "fd-file-prog-fill", style: { width: Math.max(4, Math.min(100, value)) + "%" } }) });
4054
4303
  }
4055
4304
  function FileChip({ file, onOpen, onRemove, onRetry, compact: compact3 = false, className = "" }) {
4056
4305
  if (!file) return null;
@@ -4059,8 +4308,8 @@ function FileChip({ file, onOpen, onRemove, onRetry, compact: compact3 = false,
4059
4308
  const thumb = file.thumb && file.thumb.url || (image ? file.blobUrl || file.url : null);
4060
4309
  const meta = file.meta || (file.size ? formatBytes(file.size) : "");
4061
4310
  const clickable = !!onOpen && !uploading;
4062
- return /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)("div", { className: ["fd-file", compact3 ? "is-compact" : "", file.error ? "is-error" : "", uploading ? "is-uploading" : "", className].filter(Boolean).join(" "), children: [
4063
- /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)(
4311
+ return /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("div", { className: ["fd-file", compact3 ? "is-compact" : "", file.error ? "is-error" : "", uploading ? "is-uploading" : "", className].filter(Boolean).join(" "), children: [
4312
+ /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)(
4064
4313
  "button",
4065
4314
  {
4066
4315
  type: "button",
@@ -4069,16 +4318,16 @@ function FileChip({ file, onOpen, onRemove, onRetry, compact: compact3 = false,
4069
4318
  onClick: clickable ? () => onOpen(file) : void 0,
4070
4319
  title: file.name + (meta ? " \xB7 " + meta : ""),
4071
4320
  children: [
4072
- /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)("span", { className: "fd-file-icon", children: [
4073
- thumb ? /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("img", { src: thumb, alt: "" }) : /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("i", { className: "ph ph-" + iconForMime(file.mime, file.name), "aria-hidden": "true" }),
4074
- (file.mime || "").startsWith("video/") ? /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("i", { className: "ph ph-play fd-file-play", "aria-hidden": "true" }) : null
4321
+ /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("span", { className: "fd-file-icon", children: [
4322
+ thumb ? /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("img", { src: thumb, alt: "" }) : /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("i", { className: "ph ph-" + iconForMime(file.mime, file.name), "aria-hidden": "true" }),
4323
+ (file.mime || "").startsWith("video/") ? /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("i", { className: "ph ph-play fd-file-play", "aria-hidden": "true" }) : null
4075
4324
  ] }),
4076
- /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)("span", { className: "fd-file-text", children: [
4077
- /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("span", { className: "fd-file-name", children: truncateMiddle(file.name, compact3 ? 26 : 40) }),
4078
- /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("span", { className: "fd-file-meta", children: file.error ? /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)("span", { className: "fd-file-err", children: [
4079
- /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
4325
+ /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("span", { className: "fd-file-text", children: [
4326
+ /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("span", { className: "fd-file-name", children: truncateMiddle(file.name, compact3 ? 26 : 40) }),
4327
+ /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("span", { className: "fd-file-meta", children: file.error ? /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("span", { className: "fd-file-err", children: [
4328
+ /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
4080
4329
  file.error
4081
- ] }) : uploading ? /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)("span", { className: "fd-tabular", children: [
4330
+ ] }) : uploading ? /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("span", { className: "fd-tabular", children: [
4082
4331
  Math.round(file.progress),
4083
4332
  "% uploaded"
4084
4333
  ] }) : meta })
@@ -4086,29 +4335,29 @@ function FileChip({ file, onOpen, onRemove, onRetry, compact: compact3 = false,
4086
4335
  ]
4087
4336
  }
4088
4337
  ),
4089
- uploading ? /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(Progress, { value: file.progress }) : null,
4090
- file.error && onRetry ? /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("button", { type: "button", className: "fd-file-act", onClick: () => onRetry(file), "aria-label": "Retry upload of " + file.name, children: /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("i", { className: "ph ph-arrow-clockwise", "aria-hidden": "true" }) }) : null,
4091
- onRemove ? /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("button", { type: "button", className: "fd-file-act", onClick: () => onRemove(file), "aria-label": "Remove " + file.name, children: /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("i", { className: "ph ph-x", "aria-hidden": "true" }) }) : null
4338
+ uploading ? /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(Progress, { value: file.progress }) : null,
4339
+ file.error && onRetry ? /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("button", { type: "button", className: "fd-file-act", onClick: () => onRetry(file), "aria-label": "Retry upload of " + file.name, children: /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("i", { className: "ph ph-arrow-clockwise", "aria-hidden": "true" }) }) : null,
4340
+ onRemove ? /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("button", { type: "button", className: "fd-file-act", onClick: () => onRemove(file), "aria-label": "Remove " + file.name, children: /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("i", { className: "ph ph-x", "aria-hidden": "true" }) }) : null
4092
4341
  ] });
4093
4342
  }
4094
4343
  function FileTile({ file, onOpen, onRemove, maxHeight = 200, className = "" }) {
4095
4344
  if (!file) return null;
4096
4345
  const src = file.thumb && file.thumb.url || file.blobUrl || file.url;
4097
4346
  const uploading = file.progress != null && file.progress < 100 && !file.error;
4098
- return /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)("figure", { className: ["fd-tile", uploading ? "is-uploading" : "", file.error ? "is-error" : "", className].filter(Boolean).join(" "), children: [
4099
- /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("button", { type: "button", className: "fd-tile-btn", onClick: onOpen ? () => onOpen(file) : void 0, disabled: !onOpen, children: src ? /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("img", { src, alt: file.name || "", style: { maxHeight }, loading: "lazy" }) : /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("span", { className: "fd-tile-fallback", children: /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("i", { className: "ph ph-" + iconForMime(file.mime, file.name), "aria-hidden": "true" }) }) }),
4100
- uploading ? /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(Progress, { value: file.progress }) : null,
4101
- file.error ? /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)("figcaption", { className: "fd-tile-err", children: [
4102
- /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
4347
+ return /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("figure", { className: ["fd-tile", uploading ? "is-uploading" : "", file.error ? "is-error" : "", className].filter(Boolean).join(" "), children: [
4348
+ /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("button", { type: "button", className: "fd-tile-btn", onClick: onOpen ? () => onOpen(file) : void 0, disabled: !onOpen, children: src ? /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("img", { src, alt: file.name || "", style: { maxHeight }, loading: "lazy" }) : /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("span", { className: "fd-tile-fallback", children: /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("i", { className: "ph ph-" + iconForMime(file.mime, file.name), "aria-hidden": "true" }) }) }),
4349
+ uploading ? /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(Progress, { value: file.progress }) : null,
4350
+ file.error ? /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("figcaption", { className: "fd-tile-err", children: [
4351
+ /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
4103
4352
  file.error
4104
4353
  ] }) : null,
4105
- onRemove ? /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("button", { type: "button", className: "fd-tile-x", onClick: () => onRemove(file), "aria-label": "Remove " + file.name, children: /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("i", { className: "ph ph-x", "aria-hidden": "true" }) }) : null
4354
+ onRemove ? /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("button", { type: "button", className: "fd-tile-x", onClick: () => onRemove(file), "aria-label": "Remove " + file.name, children: /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("i", { className: "ph ph-x", "aria-hidden": "true" }) }) : null
4106
4355
  ] });
4107
4356
  }
4108
4357
  function FileStrip({ files = [], size = 68, onOpen, onRemove, onRetry, className = "" }) {
4109
4358
  const list = files.filter(Boolean);
4110
4359
  if (!list.length) return null;
4111
- return /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("div", { className: ["fd-filestrip", className].filter(Boolean).join(" "), style: { "--fd-cell": size + "px" }, children: list.map((f) => /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(FileCell, { file: f, onOpen, onRemove, onRetry }, f.id || f.name)) });
4360
+ return /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("div", { className: ["fd-filestrip", className].filter(Boolean).join(" "), style: { "--fd-cell": size + "px" }, children: list.map((f) => /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(FileCell, { file: f, onOpen, onRemove, onRetry }, f.id || f.name)) });
4112
4361
  }
4113
4362
  var shortName = (name, keep = 5) => {
4114
4363
  const s = String(name || "file");
@@ -4122,19 +4371,19 @@ function FileCell({ file, onOpen, onRemove, onRetry }) {
4122
4371
  const image = isImage(file.mime, file.name);
4123
4372
  const thumb = file.thumb && file.thumb.url || (image ? file.blobUrl || file.url : null);
4124
4373
  const label = file.name + (file.size ? " \xB7 " + formatBytes(file.size) : "");
4125
- return /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)("div", { className: ["fd-cell", file.error ? "is-error" : "", uploading ? "is-uploading" : ""].filter(Boolean).join(" "), title: file.error ? file.name + " \u2014 " + file.error : label, children: [
4126
- /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)("button", { type: "button", className: "fd-cell-main", onClick: onOpen ? () => onOpen(file) : void 0, disabled: !onOpen || uploading, "aria-label": "Open " + file.name, children: [
4127
- thumb ? /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("img", { src: thumb, alt: "" }) : /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)("span", { className: "fd-cell-doc", children: [
4128
- /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("i", { className: "ph ph-" + iconForMime(file.mime, file.name), "aria-hidden": "true" }),
4129
- /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("span", { className: "fd-cell-name", children: shortName(file.name) }),
4130
- /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("span", { className: "fd-cell-size", children: file.meta || formatBytes(file.size) })
4374
+ return /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("div", { className: ["fd-cell", file.error ? "is-error" : "", uploading ? "is-uploading" : ""].filter(Boolean).join(" "), title: file.error ? file.name + " \u2014 " + file.error : label, children: [
4375
+ /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("button", { type: "button", className: "fd-cell-main", onClick: onOpen ? () => onOpen(file) : void 0, disabled: !onOpen || uploading, "aria-label": "Open " + file.name, children: [
4376
+ thumb ? /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("img", { src: thumb, alt: "" }) : /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("span", { className: "fd-cell-doc", children: [
4377
+ /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("i", { className: "ph ph-" + iconForMime(file.mime, file.name), "aria-hidden": "true" }),
4378
+ /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("span", { className: "fd-cell-name", children: shortName(file.name) }),
4379
+ /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("span", { className: "fd-cell-size", children: file.meta || formatBytes(file.size) })
4131
4380
  ] }),
4132
- (file.mime || "").startsWith("video/") ? /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("i", { className: "ph ph-play fd-cell-play", "aria-hidden": "true" }) : null
4381
+ (file.mime || "").startsWith("video/") ? /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("i", { className: "ph ph-play fd-cell-play", "aria-hidden": "true" }) : null
4133
4382
  ] }),
4134
- uploading ? /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(Progress, { value: file.progress }) : null,
4135
- file.error ? /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("span", { className: "fd-cell-err", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("i", { className: "ph ph-warning-circle" }) }) : null,
4136
- file.error && onRetry ? /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("button", { type: "button", className: "fd-cell-x is-retry", onClick: () => onRetry(file), "aria-label": "Retry upload of " + file.name, children: /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("i", { className: "ph ph-arrow-clockwise", "aria-hidden": "true" }) }) : null,
4137
- onRemove ? /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("button", { type: "button", className: "fd-cell-x", onClick: () => onRemove(file), "aria-label": "Remove " + file.name, children: /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("i", { className: "ph ph-x", "aria-hidden": "true" }) }) : null
4383
+ uploading ? /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(Progress, { value: file.progress }) : null,
4384
+ file.error ? /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("span", { className: "fd-cell-err", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("i", { className: "ph ph-warning-circle" }) }) : null,
4385
+ file.error && onRetry ? /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("button", { type: "button", className: "fd-cell-x is-retry", onClick: () => onRetry(file), "aria-label": "Retry upload of " + file.name, children: /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("i", { className: "ph ph-arrow-clockwise", "aria-hidden": "true" }) }) : null,
4386
+ onRemove ? /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("button", { type: "button", className: "fd-cell-x", onClick: () => onRemove(file), "aria-label": "Remove " + file.name, children: /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("i", { className: "ph ph-x", "aria-hidden": "true" }) }) : null
4138
4387
  ] });
4139
4388
  }
4140
4389
  function FileGrid({ files = [], onOpen, onRemove, onRetry, tiles = true, maxHeight = 200, compact: compact3 = false, className = "" }) {
@@ -4142,15 +4391,15 @@ function FileGrid({ files = [], onOpen, onRemove, onRetry, tiles = true, maxHeig
4142
4391
  if (!list.length) return null;
4143
4392
  const pics = tiles ? list.filter((f) => isImage(f.mime, f.name)) : [];
4144
4393
  const rest = list.filter((f) => pics.indexOf(f) === -1);
4145
- return /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)("div", { className: ["fd-filegrid", className].filter(Boolean).join(" "), children: [
4146
- pics.length ? /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("div", { className: "fd-filegrid-tiles", children: pics.map((f) => /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(FileTile, { file: f, onOpen, onRemove, maxHeight }, f.id || f.name)) }) : null,
4147
- rest.length ? /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("div", { className: "fd-filegrid-chips", children: rest.map((f) => /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(FileChip, { file: f, onOpen, onRemove, onRetry, compact: compact3 }, f.id || f.name)) }) : null
4394
+ return /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("div", { className: ["fd-filegrid", className].filter(Boolean).join(" "), children: [
4395
+ pics.length ? /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("div", { className: "fd-filegrid-tiles", children: pics.map((f) => /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(FileTile, { file: f, onOpen, onRemove, maxHeight }, f.id || f.name)) }) : null,
4396
+ rest.length ? /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("div", { className: "fd-filegrid-chips", children: rest.map((f) => /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(FileChip, { file: f, onOpen, onRemove, onRetry, compact: compact3 }, f.id || f.name)) }) : null
4148
4397
  ] });
4149
4398
  }
4150
4399
 
4151
4400
  // src/components/forms/MarkdownEditor.tsx
4152
- var React23 = __toESM(require("react"), 1);
4153
- var import_jsx_runtime52 = require("react/jsx-runtime");
4401
+ var React25 = __toESM(require("react"), 1);
4402
+ var import_jsx_runtime55 = require("react/jsx-runtime");
4154
4403
  var isMac = typeof navigator !== "undefined" && /Mac|iPhone|iPad/.test(navigator.platform || navigator.userAgent || "");
4155
4404
  var INLINE_RE = /(\*\*\*[^*\n]+\*\*\*|\*\*[^*\n]+\*\*|__[^_\n]+__|~~[^~\n]+~~|`[^`\n]+`|\*[^*\s][^*\n]*\*|(?<![A-Za-z0-9_])_[^_\s][^_\n]*_|\[[^\]\n]*\]\([^)\s\n]*\)|https?:\/\/\S+)/g;
4156
4405
  function inlineParts(text) {
@@ -4363,7 +4612,7 @@ function syncDom(root, value) {
4363
4612
  while (root.children.length > lines.length) root.removeChild(root.lastChild);
4364
4613
  }
4365
4614
  var LIST_CONT = RE_LI;
4366
- var MarkdownEditor = React23.forwardRef(function MarkdownEditor2({
4615
+ var MarkdownEditor = React25.forwardRef(function MarkdownEditor2({
4367
4616
  value = "",
4368
4617
  onChange,
4369
4618
  onSubmit,
@@ -4382,10 +4631,10 @@ var MarkdownEditor = React23.forwardRef(function MarkdownEditor2({
4382
4631
  className = "",
4383
4632
  id
4384
4633
  }, ref) {
4385
- const boxRef = React23.useRef(null);
4386
- const composing = React23.useRef(false);
4387
- const pendingCaret = React23.useRef(null);
4388
- React23.useLayoutEffect(() => {
4634
+ const boxRef = React25.useRef(null);
4635
+ const composing = React25.useRef(false);
4636
+ const pendingCaret = React25.useRef(null);
4637
+ React25.useLayoutEffect(() => {
4389
4638
  const root = boxRef.current;
4390
4639
  if (!root || composing.current) return;
4391
4640
  const active = document.activeElement === root || root.contains(document.activeElement);
@@ -4394,7 +4643,7 @@ var MarkdownEditor = React23.forwardRef(function MarkdownEditor2({
4394
4643
  pendingCaret.current = null;
4395
4644
  if (active && caret != null) placeCaret(root, caret);
4396
4645
  }, [value]);
4397
- React23.useEffect(() => {
4646
+ React25.useEffect(() => {
4398
4647
  if (autoFocus && boxRef.current) boxRef.current.focus();
4399
4648
  }, [autoFocus]);
4400
4649
  const caretNow = () => {
@@ -4461,7 +4710,7 @@ var MarkdownEditor = React23.forwardRef(function MarkdownEditor2({
4461
4710
  api.replaceRange(from, to, next, from + next.length);
4462
4711
  }
4463
4712
  };
4464
- React23.useImperativeHandle(ref, () => api);
4713
+ React25.useImperativeHandle(ref, () => api);
4465
4714
  function detect(text, caret) {
4466
4715
  if (!onTrigger) return;
4467
4716
  const upto = text.slice(0, caret);
@@ -4574,8 +4823,8 @@ var MarkdownEditor = React23.forwardRef(function MarkdownEditor2({
4574
4823
  api.replaceRange(s.start, s.end, text.replace(/\r\n?/g, "\n"));
4575
4824
  };
4576
4825
  const lh = 1.55;
4577
- return /* @__PURE__ */ (0, import_jsx_runtime52.jsxs)("div", { className: ["fd-rme-wrap", disabled ? "is-disabled" : "", className].filter(Boolean).join(" "), children: [
4578
- /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(
4826
+ return /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)("div", { className: ["fd-rme-wrap", disabled ? "is-disabled" : "", className].filter(Boolean).join(" "), children: [
4827
+ /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(
4579
4828
  "div",
4580
4829
  {
4581
4830
  ref: boxRef,
@@ -4608,15 +4857,15 @@ var MarkdownEditor = React23.forwardRef(function MarkdownEditor2({
4608
4857
  }
4609
4858
  }
4610
4859
  ),
4611
- !value ? /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("span", { className: "fd-rme-ph", "aria-hidden": "true", children: placeholder }) : null
4860
+ !value ? /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("span", { className: "fd-rme-ph", "aria-hidden": "true", children: placeholder }) : null
4612
4861
  ] });
4613
4862
  });
4614
4863
 
4615
4864
  // src/components/platform/AccountMenu.tsx
4616
- var React25 = __toESM(require("react"), 1);
4865
+ var React27 = __toESM(require("react"), 1);
4617
4866
 
4618
4867
  // src/kits/session.ts
4619
- var React24 = __toESM(require("react"), 1);
4868
+ var React26 = __toESM(require("react"), 1);
4620
4869
  var PERMISSION_CATALOG = [
4621
4870
  { group: "Plans", items: [
4622
4871
  { key: "plan.view", label: "View plans", detail: "Read any plan in the workspace." },
@@ -6183,8 +6432,8 @@ function roadmap(overrides) {
6183
6432
  };
6184
6433
  }
6185
6434
  function useSession() {
6186
- const [s, setS] = React24.useState(getSession);
6187
- React24.useEffect(() => subscribe(setS), []);
6435
+ const [s, setS] = React26.useState(getSession);
6436
+ React26.useEffect(() => subscribe(setS), []);
6188
6437
  return s;
6189
6438
  }
6190
6439
  var SessionKit = {
@@ -6217,7 +6466,7 @@ var SessionKit = {
6217
6466
  };
6218
6467
 
6219
6468
  // src/components/platform/AccountMenu.tsx
6220
- var import_jsx_runtime53 = require("react/jsx-runtime");
6469
+ var import_jsx_runtime56 = require("react/jsx-runtime");
6221
6470
  var DEFAULT_LINKS = [
6222
6471
  { id: "profile", label: "Your profile", icon: "user-circle", href: "../admin/index.html#profile" },
6223
6472
  { id: "preferences", label: "Preferences", icon: "sliders-horizontal", href: "../admin/index.html#preferences" }
@@ -6228,7 +6477,7 @@ var DEFAULT_ADMIN_LINKS = [
6228
6477
  { id: "flags", label: "Feature flags", icon: "toggle-right", href: "../admin/index.html#flags", perm: "flags.manage" }
6229
6478
  ];
6230
6479
  function Item({ item, onPick }) {
6231
- return /* @__PURE__ */ (0, import_jsx_runtime53.jsxs)(
6480
+ return /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)(
6232
6481
  "button",
6233
6482
  {
6234
6483
  type: "button",
@@ -6236,9 +6485,9 @@ function Item({ item, onPick }) {
6236
6485
  className: "fd-acct-item",
6237
6486
  onClick: () => onPick(item),
6238
6487
  children: [
6239
- /* @__PURE__ */ (0, import_jsx_runtime53.jsx)("i", { className: "ph ph-" + item.icon, "aria-hidden": "true" }),
6240
- /* @__PURE__ */ (0, import_jsx_runtime53.jsx)("span", { style: { flex: 1 }, children: item.label }),
6241
- item.badge ? /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(Badge, { tone: "neutral", children: item.badge }) : null
6488
+ /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("i", { className: "ph ph-" + item.icon, "aria-hidden": "true" }),
6489
+ /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("span", { style: { flex: 1 }, children: item.label }),
6490
+ item.badge ? /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(Badge, { tone: "neutral", children: item.badge }) : null
6242
6491
  ]
6243
6492
  }
6244
6493
  );
@@ -6254,9 +6503,9 @@ function AccountMenu({
6254
6503
  ...rest
6255
6504
  }) {
6256
6505
  const session = SessionKit.useSession();
6257
- const [open, setOpen] = React25.useState(false);
6258
- const [switching, setSwitching] = React25.useState(false);
6259
- const ref = React25.useRef(null);
6506
+ const [open, setOpen] = React27.useState(false);
6507
+ const [switching, setSwitching] = React27.useState(false);
6508
+ const ref = React27.useRef(null);
6260
6509
  const user = session.user;
6261
6510
  const visibleAdmin = adminLinks.filter((l) => !l.perm || SessionKit.can(l.perm));
6262
6511
  const pick = (item) => {
@@ -6270,8 +6519,8 @@ function AccountMenu({
6270
6519
  if (onSignOut) return onSignOut();
6271
6520
  window.alert("Signed out. (Simulated \u2014 no auth provider is wired up.)");
6272
6521
  };
6273
- return /* @__PURE__ */ (0, import_jsx_runtime53.jsxs)(import_jsx_runtime53.Fragment, { children: [
6274
- /* @__PURE__ */ (0, import_jsx_runtime53.jsxs)(
6522
+ return /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)(import_jsx_runtime56.Fragment, { children: [
6523
+ /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)(
6275
6524
  "button",
6276
6525
  {
6277
6526
  type: "button",
@@ -6283,32 +6532,32 @@ function AccountMenu({
6283
6532
  onClick: () => setOpen((o) => !o),
6284
6533
  ...rest,
6285
6534
  children: [
6286
- /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(Avatar, { name: user.name, size: "sm" }),
6287
- /* @__PURE__ */ (0, import_jsx_runtime53.jsx)("i", { className: "ph ph-caret-down", "aria-hidden": "true", style: { fontSize: 11, color: "var(--text-muted)" } })
6535
+ /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(Avatar, { name: user.name, size: "sm" }),
6536
+ /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("i", { className: "ph ph-caret-down", "aria-hidden": "true", style: { fontSize: 11, color: "var(--text-muted)" } })
6288
6537
  ]
6289
6538
  }
6290
6539
  ),
6291
- /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(Popover, { open, anchorRef: ref, onClose: () => setOpen(false), placement: "bottom-end", width: 272, children: /* @__PURE__ */ (0, import_jsx_runtime53.jsxs)("div", { role: "menu", className: "fd-stack", style: { gap: 0 }, children: [
6292
- /* @__PURE__ */ (0, import_jsx_runtime53.jsxs)("div", { className: "fd-row", style: { gap: 10, padding: "12px 14px", borderBottom: "1px solid var(--border)" }, children: [
6293
- /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(Avatar, { name: user.name }),
6294
- /* @__PURE__ */ (0, import_jsx_runtime53.jsxs)("span", { className: "fd-stack", style: { gap: 1, minWidth: 0, flex: 1 }, children: [
6295
- /* @__PURE__ */ (0, import_jsx_runtime53.jsx)("span", { className: "fd-body-sm", style: { fontWeight: 700 }, children: user.name }),
6296
- /* @__PURE__ */ (0, import_jsx_runtime53.jsx)("span", { className: "fd-body-sm fd-muted fd-table-trunc", children: user.email })
6540
+ /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(Popover, { open, anchorRef: ref, onClose: () => setOpen(false), placement: "bottom-end", width: 272, children: /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("div", { role: "menu", className: "fd-stack", style: { gap: 0 }, children: [
6541
+ /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("div", { className: "fd-row", style: { gap: 10, padding: "12px 14px", borderBottom: "1px solid var(--border)" }, children: [
6542
+ /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(Avatar, { name: user.name }),
6543
+ /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("span", { className: "fd-stack", style: { gap: 1, minWidth: 0, flex: 1 }, children: [
6544
+ /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("span", { className: "fd-body-sm", style: { fontWeight: 700 }, children: user.name }),
6545
+ /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("span", { className: "fd-body-sm fd-muted fd-table-trunc", children: user.email })
6297
6546
  ] })
6298
6547
  ] }),
6299
- showRoles && session.roles.length ? /* @__PURE__ */ (0, import_jsx_runtime53.jsx)("div", { className: "fd-row", style: { gap: 6, padding: "10px 14px", flexWrap: "wrap", borderBottom: "1px solid var(--border)" }, children: session.roles.map((r) => /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(Badge, { tone: r.id === "owner" ? "success" : "neutral", children: r.name }, r.id)) }) : null,
6300
- /* @__PURE__ */ (0, import_jsx_runtime53.jsx)("div", { className: "fd-acct-group", children: links.map((l) => /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(Item, { item: l, onPick: pick }, l.id)) }),
6301
- visibleAdmin.length ? /* @__PURE__ */ (0, import_jsx_runtime53.jsxs)("div", { className: "fd-acct-group", style: { borderTop: "1px solid var(--border)" }, children: [
6302
- /* @__PURE__ */ (0, import_jsx_runtime53.jsx)("span", { className: "fd-overline fd-muted", style: { padding: "8px 14px 4px", display: "block" }, children: "Administration" }),
6303
- visibleAdmin.map((l) => /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(Item, { item: l, onPick: pick }, l.id))
6548
+ showRoles && session.roles.length ? /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("div", { className: "fd-row", style: { gap: 6, padding: "10px 14px", flexWrap: "wrap", borderBottom: "1px solid var(--border)" }, children: session.roles.map((r) => /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(Badge, { tone: r.id === "owner" ? "success" : "neutral", children: r.name }, r.id)) }) : null,
6549
+ /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("div", { className: "fd-acct-group", children: links.map((l) => /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(Item, { item: l, onPick: pick }, l.id)) }),
6550
+ visibleAdmin.length ? /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("div", { className: "fd-acct-group", style: { borderTop: "1px solid var(--border)" }, children: [
6551
+ /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("span", { className: "fd-overline fd-muted", style: { padding: "8px 14px 4px", display: "block" }, children: "Administration" }),
6552
+ visibleAdmin.map((l) => /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(Item, { item: l, onPick: pick }, l.id))
6304
6553
  ] }) : null,
6305
- allowUserSwitch ? /* @__PURE__ */ (0, import_jsx_runtime53.jsxs)("div", { className: "fd-acct-group", style: { borderTop: "1px solid var(--border)" }, children: [
6306
- /* @__PURE__ */ (0, import_jsx_runtime53.jsxs)("button", { type: "button", role: "menuitem", className: "fd-acct-item", onClick: () => setSwitching((s) => !s), children: [
6307
- /* @__PURE__ */ (0, import_jsx_runtime53.jsx)("i", { className: "ph ph-user-switch", "aria-hidden": "true" }),
6308
- /* @__PURE__ */ (0, import_jsx_runtime53.jsx)("span", { style: { flex: 1 }, children: "View as another member" }),
6309
- /* @__PURE__ */ (0, import_jsx_runtime53.jsx)("i", { className: "ph ph-caret-" + (switching ? "up" : "down"), "aria-hidden": "true", style: { fontSize: 11 } })
6554
+ allowUserSwitch ? /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("div", { className: "fd-acct-group", style: { borderTop: "1px solid var(--border)" }, children: [
6555
+ /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("button", { type: "button", role: "menuitem", className: "fd-acct-item", onClick: () => setSwitching((s) => !s), children: [
6556
+ /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("i", { className: "ph ph-user-switch", "aria-hidden": "true" }),
6557
+ /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("span", { style: { flex: 1 }, children: "View as another member" }),
6558
+ /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("i", { className: "ph ph-caret-" + (switching ? "up" : "down"), "aria-hidden": "true", style: { fontSize: 11 } })
6310
6559
  ] }),
6311
- switching ? /* @__PURE__ */ (0, import_jsx_runtime53.jsx)("div", { className: "fd-stack", style: { gap: 0, maxHeight: 208, overflowY: "auto" }, children: session.allUsers.filter((u) => u.status === "active").map((u) => /* @__PURE__ */ (0, import_jsx_runtime53.jsxs)(
6560
+ switching ? /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("div", { className: "fd-stack", style: { gap: 0, maxHeight: 208, overflowY: "auto" }, children: session.allUsers.filter((u) => u.status === "active").map((u) => /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)(
6312
6561
  "button",
6313
6562
  {
6314
6563
  type: "button",
@@ -6320,34 +6569,34 @@ function AccountMenu({
6320
6569
  setSwitching(false);
6321
6570
  },
6322
6571
  children: [
6323
- /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(Avatar, { name: u.name, size: "sm" }),
6324
- /* @__PURE__ */ (0, import_jsx_runtime53.jsxs)("span", { className: "fd-stack", style: { gap: 0, flex: 1, minWidth: 0, alignItems: "flex-start" }, children: [
6325
- /* @__PURE__ */ (0, import_jsx_runtime53.jsx)("span", { style: { fontWeight: u.id === user.id ? 700 : 500 }, children: u.name }),
6326
- /* @__PURE__ */ (0, import_jsx_runtime53.jsx)("span", { className: "fd-muted", style: { fontSize: 11.5 }, children: u.roles.join(", ") })
6572
+ /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(Avatar, { name: u.name, size: "sm" }),
6573
+ /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("span", { className: "fd-stack", style: { gap: 0, flex: 1, minWidth: 0, alignItems: "flex-start" }, children: [
6574
+ /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("span", { style: { fontWeight: u.id === user.id ? 700 : 500 }, children: u.name }),
6575
+ /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("span", { className: "fd-muted", style: { fontSize: 11.5 }, children: u.roles.join(", ") })
6327
6576
  ] }),
6328
- u.id === user.id ? /* @__PURE__ */ (0, import_jsx_runtime53.jsx)("i", { className: "ph ph-check", "aria-hidden": "true", style: { color: "var(--ok-text)" } }) : null
6577
+ u.id === user.id ? /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("i", { className: "ph ph-check", "aria-hidden": "true", style: { color: "var(--ok-text)" } }) : null
6329
6578
  ]
6330
6579
  },
6331
6580
  u.id
6332
6581
  )) }) : null
6333
6582
  ] }) : null,
6334
- /* @__PURE__ */ (0, import_jsx_runtime53.jsx)("div", { className: "fd-acct-group", style: { borderTop: "1px solid var(--border)" }, children: /* @__PURE__ */ (0, import_jsx_runtime53.jsxs)("button", { type: "button", role: "menuitem", className: "fd-acct-item", "data-danger": "true", onClick: signOut, children: [
6335
- /* @__PURE__ */ (0, import_jsx_runtime53.jsx)("i", { className: "ph ph-sign-out", "aria-hidden": "true" }),
6336
- /* @__PURE__ */ (0, import_jsx_runtime53.jsx)("span", { style: { flex: 1 }, children: "Sign out" })
6583
+ /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("div", { className: "fd-acct-group", style: { borderTop: "1px solid var(--border)" }, children: /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("button", { type: "button", role: "menuitem", className: "fd-acct-item", "data-danger": "true", onClick: signOut, children: [
6584
+ /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("i", { className: "ph ph-sign-out", "aria-hidden": "true" }),
6585
+ /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("span", { style: { flex: 1 }, children: "Sign out" })
6337
6586
  ] }) })
6338
6587
  ] }) })
6339
6588
  ] });
6340
6589
  }
6341
6590
 
6342
6591
  // src/components/platform/ApiSpecBrowser.tsx
6343
- var React26 = __toESM(require("react"), 1);
6344
- var import_jsx_runtime54 = require("react/jsx-runtime");
6592
+ var React28 = __toESM(require("react"), 1);
6593
+ var import_jsx_runtime57 = require("react/jsx-runtime");
6345
6594
  var METHOD_TONE = { GET: "success", POST: "info", PATCH: "warning", PUT: "warning", DELETE: "danger" };
6346
6595
  function Json({ obj }) {
6347
- return /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("pre", { className: "fd-json", children: JSON.stringify(obj, null, 2) });
6596
+ return /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("pre", { className: "fd-json", children: JSON.stringify(obj, null, 2) });
6348
6597
  }
6349
6598
  function Endpoint({ s, onRequest }) {
6350
- const [tried, setTried] = React26.useState(null);
6599
+ const [tried, setTried] = React28.useState(null);
6351
6600
  const run = async () => {
6352
6601
  setTried("busy");
6353
6602
  const t0 = (window.performance || Date).now();
@@ -6358,50 +6607,50 @@ function Endpoint({ s, onRequest }) {
6358
6607
  setTried({ ms: Math.round((window.performance || Date).now() - t0), error: String(e && e.message || e) });
6359
6608
  }
6360
6609
  };
6361
- return /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(Card, { elevation: "flat", padded: false, children: /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("div", { className: "fd-stack", style: { gap: 0 }, children: [
6362
- /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("div", { className: "fd-row", style: { gap: 10, padding: "14px 18px", flexWrap: "wrap" }, children: [
6363
- /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(Badge, { tone: METHOD_TONE[s.method] || "neutral", children: s.method }),
6364
- /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("code", { className: "fd-mono", style: { fontSize: 12.5, fontWeight: 600, color: "var(--text)", wordBreak: "break-all" }, children: s.path }),
6365
- s.isList ? /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(Badge, { tone: "neutral", icon: "rows", children: "Paged list" }) : null,
6366
- /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("span", { style: { flex: 1 } }),
6367
- /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("span", { className: "fd-body-sm fd-muted fd-mono", children: [
6610
+ return /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(Card, { elevation: "flat", padded: false, children: /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { className: "fd-stack", style: { gap: 0 }, children: [
6611
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { className: "fd-row", style: { gap: 10, padding: "14px 18px", flexWrap: "wrap" }, children: [
6612
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(Badge, { tone: METHOD_TONE[s.method] || "neutral", children: s.method }),
6613
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("code", { className: "fd-mono", style: { fontSize: 12.5, fontWeight: 600, color: "var(--text)", wordBreak: "break-all" }, children: s.path }),
6614
+ s.isList ? /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(Badge, { tone: "neutral", icon: "rows", children: "Paged list" }) : null,
6615
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { style: { flex: 1 } }),
6616
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("span", { className: "fd-body-sm fd-muted fd-mono", children: [
6368
6617
  s.latency[0],
6369
6618
  "\u2013",
6370
6619
  s.latency[1],
6371
6620
  "ms"
6372
6621
  ] }),
6373
- /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(Button, { size: "sm", variant: "secondary", icon: "play", loading: tried === "busy", onClick: run, children: "Try it" })
6622
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(Button, { size: "sm", variant: "secondary", icon: "play", loading: tried === "busy", onClick: run, children: "Try it" })
6374
6623
  ] }),
6375
- /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("div", { className: "fd-stack", style: { gap: 14, padding: "0 18px 16px" }, children: [
6376
- /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("div", { className: "fd-stack", style: { gap: 6 }, children: [
6377
- /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("span", { className: "fd-body-sm", style: { fontWeight: 700 }, children: s.title }),
6378
- /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("p", { className: "fd-body-sm fd-secondary", style: { margin: 0, textWrap: "pretty" }, children: s.purpose }),
6379
- s.usedBy && s.usedBy.length ? /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("span", { className: "fd-row", style: { gap: 6, flexWrap: "wrap" }, children: s.usedBy.map((u) => /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(Tag, { children: u }, u)) }) : null
6624
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { className: "fd-stack", style: { gap: 14, padding: "0 18px 16px" }, children: [
6625
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { className: "fd-stack", style: { gap: 6 }, children: [
6626
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { className: "fd-body-sm", style: { fontWeight: 700 }, children: s.title }),
6627
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("p", { className: "fd-body-sm fd-secondary", style: { margin: 0, textWrap: "pretty" }, children: s.purpose }),
6628
+ s.usedBy && s.usedBy.length ? /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { className: "fd-row", style: { gap: 6, flexWrap: "wrap" }, children: s.usedBy.map((u) => /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(Tag, { children: u }, u)) }) : null
6380
6629
  ] }),
6381
- /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("div", { style: { display: "grid", gridTemplateColumns: "repeat(auto-fit,minmax(280px,1fr))", gap: 12, alignItems: "start" }, children: [
6382
- s.request ? /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("div", { className: "fd-stack", style: { gap: 6 }, children: [
6383
- /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("span", { className: "fd-overline fd-muted", children: "Request body" }),
6384
- /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(Json, { obj: s.request })
6630
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { style: { display: "grid", gridTemplateColumns: "repeat(auto-fit,minmax(280px,1fr))", gap: 12, alignItems: "start" }, children: [
6631
+ s.request ? /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { className: "fd-stack", style: { gap: 6 }, children: [
6632
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { className: "fd-overline fd-muted", children: "Request body" }),
6633
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(Json, { obj: s.request })
6385
6634
  ] }) : null,
6386
- s.query ? /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("div", { className: "fd-stack", style: { gap: 6 }, children: [
6387
- /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("span", { className: "fd-overline fd-muted", children: "Query" }),
6388
- /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(Json, { obj: s.query })
6635
+ s.query ? /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { className: "fd-stack", style: { gap: 6 }, children: [
6636
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { className: "fd-overline fd-muted", children: "Query" }),
6637
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(Json, { obj: s.query })
6389
6638
  ] }) : null,
6390
- /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("div", { className: "fd-stack", style: { gap: 6 }, children: [
6391
- /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("span", { className: "fd-overline fd-muted", children: "Response 200" }),
6392
- /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(Json, { obj: s.response })
6639
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { className: "fd-stack", style: { gap: 6 }, children: [
6640
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { className: "fd-overline fd-muted", children: "Response 200" }),
6641
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(Json, { obj: s.response })
6393
6642
  ] })
6394
6643
  ] }),
6395
- s.notes ? /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(Flag, { tone: "info", statement: "Implementation note", cost: s.notes, actions: null }) : null,
6396
- tried && tried !== "busy" ? /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("div", { className: "fd-stack", style: { gap: 6 }, children: [
6397
- /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("span", { className: "fd-row", style: { gap: 8 }, children: [
6398
- /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("span", { className: "fd-overline fd-muted", children: "Simulated response" }),
6399
- /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)(Badge, { tone: tried.error ? "danger" : "success", icon: "timer", children: [
6644
+ s.notes ? /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(Flag, { tone: "info", statement: "Implementation note", cost: s.notes, actions: null }) : null,
6645
+ tried && tried !== "busy" ? /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { className: "fd-stack", style: { gap: 6 }, children: [
6646
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("span", { className: "fd-row", style: { gap: 8 }, children: [
6647
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { className: "fd-overline fd-muted", children: "Simulated response" }),
6648
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(Badge, { tone: tried.error ? "danger" : "success", icon: "timer", children: [
6400
6649
  tried.ms,
6401
6650
  "ms"
6402
6651
  ] })
6403
6652
  ] }),
6404
- /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(Json, { obj: tried.error ? { error: tried.error } : tried.data })
6653
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(Json, { obj: tried.error ? { error: tried.error } : tried.data })
6405
6654
  ] }) : null
6406
6655
  ] })
6407
6656
  ] }) });
@@ -6420,58 +6669,58 @@ function ApiSpecBrowser({
6420
6669
  className = "",
6421
6670
  ...rest
6422
6671
  }) {
6423
- const [q, setQ] = React26.useState("");
6424
- const [method, setMethod] = React26.useState(null);
6425
- const [mod, setMod] = React26.useState(null);
6426
- const [listOnly, setListOnly] = React26.useState(false);
6672
+ const [q, setQ] = React28.useState("");
6673
+ const [method, setMethod] = React28.useState(null);
6674
+ const [mod, setMod] = React28.useState(null);
6675
+ const [listOnly, setListOnly] = React28.useState(false);
6427
6676
  const activeModule = modules && modules.find((m) => m.id === mod);
6428
6677
  const hits = spec.filter((s) => (!method || s.method === method) && (!listOnly || s.isList) && (!activeModule || activeModule.endpoints.indexOf(s.id) >= 0) && (!q || (s.path + " " + s.title + " " + s.purpose + " " + (s.usedBy || []).join(" ")).toLowerCase().includes(q.toLowerCase())));
6429
6678
  const effGroups = groups && groups.length ? groups : [["All endpoints", spec.map((s) => s.id)]];
6430
6679
  const methods = [...new Set(spec.map((s) => s.method))];
6431
6680
  const listCount = spec.filter((s) => s.isList).length;
6432
- return /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 20, maxWidth: 1100 }, ...rest, children: [
6433
- /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("div", { className: "fd-stack", style: { gap: 10 }, children: [
6434
- kicker ? /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("span", { className: "fd-overline fd-muted", children: kicker }) : null,
6435
- /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("h1", { className: "fd-h1", style: { margin: 0 }, children: title }),
6436
- lede ? /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("p", { className: "fd-body fd-secondary fd-prose", style: { margin: 0 }, children: lede }) : null
6681
+ return /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 20, maxWidth: 1100 }, ...rest, children: [
6682
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { className: "fd-stack", style: { gap: 10 }, children: [
6683
+ kicker ? /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { className: "fd-overline fd-muted", children: kicker }) : null,
6684
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("h1", { className: "fd-h1", style: { margin: 0 }, children: title }),
6685
+ lede ? /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("p", { className: "fd-body fd-secondary fd-prose", style: { margin: 0 }, children: lede }) : null
6437
6686
  ] }),
6438
- modules && modules.length ? /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("div", { className: "fd-stack", style: { gap: 8 }, children: [
6439
- /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("span", { className: "fd-overline fd-muted", children: "Filter by screen \u2014 every endpoint that screen depends on" }),
6440
- /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("div", { className: "fd-row", style: { gap: 8, flexWrap: "wrap" }, children: [
6441
- /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)(Tag, { icon: "stack", selected: !mod, onClick: () => setMod(null), children: [
6687
+ modules && modules.length ? /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { className: "fd-stack", style: { gap: 8 }, children: [
6688
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { className: "fd-overline fd-muted", children: "Filter by screen \u2014 every endpoint that screen depends on" }),
6689
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { className: "fd-row", style: { gap: 8, flexWrap: "wrap" }, children: [
6690
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(Tag, { icon: "stack", selected: !mod, onClick: () => setMod(null), children: [
6442
6691
  "All screens ",
6443
- /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("span", { className: "fd-mono", children: spec.length })
6692
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { className: "fd-mono", children: spec.length })
6444
6693
  ] }),
6445
- modules.map((m) => /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)(Tag, { icon: m.icon, selected: mod === m.id, onClick: () => setMod(mod === m.id ? null : m.id), children: [
6694
+ modules.map((m) => /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(Tag, { icon: m.icon, selected: mod === m.id, onClick: () => setMod(mod === m.id ? null : m.id), children: [
6446
6695
  m.label,
6447
6696
  " ",
6448
- /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("span", { className: "fd-mono", children: m.endpoints.length })
6697
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { className: "fd-mono", children: m.endpoints.length })
6449
6698
  ] }, m.id))
6450
6699
  ] }),
6451
- activeModule ? /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(
6700
+ activeModule ? /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
6452
6701
  Flag,
6453
6702
  {
6454
6703
  tone: "info",
6455
6704
  statement: activeModule.label + " calls " + activeModule.endpoints.length + " endpoints.",
6456
6705
  cost: "Integration checklist for this screen: " + activeModule.endpoints.join(", ") + ". Wire these and the screen is done.",
6457
- actions: /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(Button, { size: "sm", variant: "ghost", icon: "x", onClick: () => setMod(null), children: "Show all screens" })
6706
+ actions: /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(Button, { size: "sm", variant: "ghost", icon: "x", onClick: () => setMod(null), children: "Show all screens" })
6458
6707
  }
6459
6708
  ) : null
6460
6709
  ] }) : null,
6461
- sourceNote ? /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(Flag, { tone: "info", statement: "Design-first: this page is the spec.", cost: sourceNote, actions: null }) : null,
6462
- /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("div", { className: "fd-row", style: { gap: 10, flexWrap: "wrap" }, children: [
6463
- /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(Input, { icon: "magnifying-glass", placeholder: "Find an endpoint, screen, or behavior", value: q, onChange: (e) => setQ(e.target.value), style: { width: 300 } }),
6464
- methods.map((m) => /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)(Tag, { selected: method === m, onClick: () => setMethod(method === m ? null : m), children: [
6710
+ sourceNote ? /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(Flag, { tone: "info", statement: "Design-first: this page is the spec.", cost: sourceNote, actions: null }) : null,
6711
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { className: "fd-row", style: { gap: 10, flexWrap: "wrap" }, children: [
6712
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(Input, { icon: "magnifying-glass", placeholder: "Find an endpoint, screen, or behavior", value: q, onChange: (e) => setQ(e.target.value), style: { width: 300 } }),
6713
+ methods.map((m) => /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(Tag, { selected: method === m, onClick: () => setMethod(method === m ? null : m), children: [
6465
6714
  m,
6466
6715
  " ",
6467
- /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("span", { className: "fd-mono", children: spec.filter((s) => s.method === m).length })
6716
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { className: "fd-mono", children: spec.filter((s) => s.method === m).length })
6468
6717
  ] }, m)),
6469
- listCount ? /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)(Tag, { icon: "rows", selected: listOnly, onClick: () => setListOnly(!listOnly), children: [
6718
+ listCount ? /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(Tag, { icon: "rows", selected: listOnly, onClick: () => setListOnly(!listOnly), children: [
6470
6719
  "Paged lists ",
6471
- /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("span", { className: "fd-mono", children: listCount })
6720
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { className: "fd-mono", children: listCount })
6472
6721
  ] }) : null,
6473
- /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("span", { style: { flex: 1 } }),
6474
- /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("span", { className: "fd-body-sm fd-muted", children: [
6722
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { style: { flex: 1 } }),
6723
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("span", { className: "fd-body-sm fd-muted", children: [
6475
6724
  hits.length,
6476
6725
  " of ",
6477
6726
  spec.length,
@@ -6479,31 +6728,31 @@ function ApiSpecBrowser({
6479
6728
  listCount ? " \xB7 " + listCount + " paged" : ""
6480
6729
  ] })
6481
6730
  ] }),
6482
- hits.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(Card, { elevation: "flat", children: /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("p", { className: "fd-body-sm fd-muted", style: { margin: 0 }, children: "No endpoint matches those filters." }) }) : effGroups.map(([g, ids]) => {
6731
+ hits.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(Card, { elevation: "flat", children: /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("p", { className: "fd-body-sm fd-muted", style: { margin: 0 }, children: "No endpoint matches those filters." }) }) : effGroups.map(([g, ids]) => {
6483
6732
  const items = hits.filter((s) => ids.indexOf(s.id) >= 0);
6484
6733
  if (!items.length) return null;
6485
- return /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("div", { className: "fd-stack", style: { gap: 12 }, children: [
6486
- /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("span", { className: "fd-label-lg", children: g }),
6487
- items.map((s) => /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(Endpoint, { s, onRequest }, s.id))
6734
+ return /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { className: "fd-stack", style: { gap: 12 }, children: [
6735
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { className: "fd-label-lg", children: g }),
6736
+ items.map((s) => /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(Endpoint, { s, onRequest }, s.id))
6488
6737
  ] }, g);
6489
6738
  }),
6490
- conventions && conventions.length ? /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(Card, { title: "Cross-cutting conventions", elevation: "flat", children: /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("div", { className: "fd-stack", style: { gap: 10 }, children: conventions.map(([k, v]) => /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("div", { className: "fd-row", style: { gap: 12, alignItems: "flex-start" }, children: [
6491
- /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("span", { className: "fd-overline fd-muted", style: { width: 110, flex: "none", paddingTop: 2 }, children: k }),
6492
- /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("span", { className: "fd-body-sm fd-secondary", style: { textWrap: "pretty" }, children: v })
6739
+ conventions && conventions.length ? /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(Card, { title: "Cross-cutting conventions", elevation: "flat", children: /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("div", { className: "fd-stack", style: { gap: 10 }, children: conventions.map(([k, v]) => /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { className: "fd-row", style: { gap: 12, alignItems: "flex-start" }, children: [
6740
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { className: "fd-overline fd-muted", style: { width: 110, flex: "none", paddingTop: 2 }, children: k }),
6741
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { className: "fd-body-sm fd-secondary", style: { textWrap: "pretty" }, children: v })
6493
6742
  ] }, k)) }) }) : null,
6494
- openQuestions && openQuestions.length ? /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(Collapsible, { icon: "list-checks", title: "Open questions before implementation", subtitle: openQuestions.length + " unresolved", children: /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("div", { className: "fd-stack", style: { gap: 8 }, children: openQuestions.map(([id, question, why]) => /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("div", { className: "fd-row", style: { gap: 10, alignItems: "flex-start", padding: "8px 0", borderTop: "1px solid var(--border)" }, children: [
6495
- /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(Badge, { tone: "danger", children: id }),
6496
- /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("span", { className: "fd-stack", style: { gap: 2, flex: 1 }, children: [
6497
- /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("span", { className: "fd-body-sm", style: { fontWeight: 600 }, children: question }),
6498
- /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("span", { className: "fd-body-sm fd-muted", children: why })
6743
+ openQuestions && openQuestions.length ? /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(Collapsible, { icon: "list-checks", title: "Open questions before implementation", subtitle: openQuestions.length + " unresolved", children: /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("div", { className: "fd-stack", style: { gap: 8 }, children: openQuestions.map(([id, question, why]) => /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { className: "fd-row", style: { gap: 10, alignItems: "flex-start", padding: "8px 0", borderTop: "1px solid var(--border)" }, children: [
6744
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(Badge, { tone: "danger", children: id }),
6745
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("span", { className: "fd-stack", style: { gap: 2, flex: 1 }, children: [
6746
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { className: "fd-body-sm", style: { fontWeight: 600 }, children: question }),
6747
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { className: "fd-body-sm fd-muted", children: why })
6499
6748
  ] })
6500
6749
  ] }, id)) }) }) : null
6501
6750
  ] });
6502
6751
  }
6503
6752
 
6504
6753
  // src/components/platform/ProfilePage.tsx
6505
- var React27 = __toESM(require("react"), 1);
6506
- var import_jsx_runtime55 = require("react/jsx-runtime");
6754
+ var React29 = __toESM(require("react"), 1);
6755
+ var import_jsx_runtime58 = require("react/jsx-runtime");
6507
6756
  var TIMEZONES = ["America/New_York", "America/Chicago", "America/Denver", "America/Los_Angeles", "America/Anchorage", "Pacific/Honolulu", "Europe/London", "Europe/Berlin"];
6508
6757
  var NOTIFY = [
6509
6758
  { key: "planShared", label: "A plan is shared with me", detail: "Someone sends you a plan or a client link." },
@@ -6515,7 +6764,7 @@ var NOTIFY = [
6515
6764
  function ProfilePage({ user: userProp, onSave, onNavigate, sessions, showSessions = true, className = "", ...rest }) {
6516
6765
  const session = SessionKit.useSession();
6517
6766
  const user = userProp || session.user;
6518
- const [draft, setDraft] = React27.useState(() => ({
6767
+ const [draft, setDraft] = React29.useState(() => ({
6519
6768
  name: user.name || "",
6520
6769
  title: user.title || "",
6521
6770
  email: user.email || "",
@@ -6524,8 +6773,8 @@ function ProfilePage({ user: userProp, onSave, onNavigate, sessions, showSession
6524
6773
  bio: user.bio || "",
6525
6774
  notify: user.notify || { planShared: true, planChanged: true, goalMissed: true, flagChanged: false, weekly: true }
6526
6775
  }));
6527
- const [saving, setSaving] = React27.useState(false);
6528
- const [saved, setSaved] = React27.useState(false);
6776
+ const [saving, setSaving] = React29.useState(false);
6777
+ const [saved, setSaved] = React29.useState(false);
6529
6778
  const set = (k, v) => {
6530
6779
  setDraft((d) => Object.assign({}, d, { [k]: v }));
6531
6780
  setSaved(false);
@@ -6547,43 +6796,43 @@ function ProfilePage({ user: userProp, onSave, onNavigate, sessions, showSession
6547
6796
  { id: "s2", device: "iPhone 15 \xB7 Safari", where: "Denver, CO", when: "2 hours ago" },
6548
6797
  { id: "s3", device: "Windows \xB7 Edge", where: "Chicago, IL", when: "Aug 12" }
6549
6798
  ];
6550
- return /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 20, maxWidth: 860 }, ...rest, children: [
6551
- /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)("div", { className: "fd-stack", style: { gap: 10 }, children: [
6552
- /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("span", { className: "fd-overline fd-muted", children: "Account" }),
6553
- /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("h1", { className: "fd-h1", style: { margin: 0 }, children: "Your profile" }),
6554
- /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("p", { className: "fd-body fd-secondary fd-prose", style: { margin: 0 }, children: "How you appear to colleagues and clients across every flytedesk app, and what we send you." })
6799
+ return /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 20, maxWidth: 860 }, ...rest, children: [
6800
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("div", { className: "fd-stack", style: { gap: 10 }, children: [
6801
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("span", { className: "fd-overline fd-muted", children: "Account" }),
6802
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("h1", { className: "fd-h1", style: { margin: 0 }, children: "Your profile" }),
6803
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("p", { className: "fd-body fd-secondary fd-prose", style: { margin: 0 }, children: "How you appear to colleagues and clients across every flytedesk app, and what we send you." })
6555
6804
  ] }),
6556
- /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(Card, { elevation: "flat", children: /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)("div", { className: "fd-row", style: { gap: 16, flexWrap: "wrap", alignItems: "flex-start" }, children: [
6557
- /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(Avatar, { name: draft.name || user.name, size: "lg" }),
6558
- /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)("div", { className: "fd-stack", style: { gap: 4, flex: 1, minWidth: 200 }, children: [
6559
- /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("span", { className: "fd-h3", style: { margin: 0 }, children: draft.name || user.name }),
6560
- /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)("span", { className: "fd-body-sm fd-muted", children: [
6805
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(Card, { elevation: "flat", children: /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("div", { className: "fd-row", style: { gap: 16, flexWrap: "wrap", alignItems: "flex-start" }, children: [
6806
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(Avatar, { name: draft.name || user.name, size: "lg" }),
6807
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("div", { className: "fd-stack", style: { gap: 4, flex: 1, minWidth: 200 }, children: [
6808
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("span", { className: "fd-h3", style: { margin: 0 }, children: draft.name || user.name }),
6809
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("span", { className: "fd-body-sm fd-muted", children: [
6561
6810
  draft.title || "No title set",
6562
6811
  " \xB7 ",
6563
6812
  user.team || "No team"
6564
6813
  ] }),
6565
- /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)("span", { className: "fd-row", style: { gap: 6, flexWrap: "wrap", paddingTop: 4 }, children: [
6566
- session.roles.map((r) => /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(Badge, { tone: r.id === "owner" ? "success" : "neutral", children: r.name }, r.id)),
6567
- user.sso ? /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(Badge, { tone: "info", icon: "shield-check", children: "SSO" }) : null
6814
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("span", { className: "fd-row", style: { gap: 6, flexWrap: "wrap", paddingTop: 4 }, children: [
6815
+ session.roles.map((r) => /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(Badge, { tone: r.id === "owner" ? "success" : "neutral", children: r.name }, r.id)),
6816
+ user.sso ? /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(Badge, { tone: "info", icon: "shield-check", children: "SSO" }) : null
6568
6817
  ] })
6569
6818
  ] }),
6570
- /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(Button, { variant: "secondary", size: "sm", icon: "image", children: "Change photo" })
6819
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(Button, { variant: "secondary", size: "sm", icon: "image", children: "Change photo" })
6571
6820
  ] }) }),
6572
- /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(
6821
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
6573
6822
  Card,
6574
6823
  {
6575
- title: /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)("span", { className: "fd-stack", style: { gap: 2 }, children: [
6576
- /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("span", { children: "Identity" }),
6577
- /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("span", { className: "fd-body-sm fd-muted", style: { fontWeight: 400 }, children: "Name and title appear on plans you share" })
6824
+ title: /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("span", { className: "fd-stack", style: { gap: 2 }, children: [
6825
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("span", { children: "Identity" }),
6826
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("span", { className: "fd-body-sm fd-muted", style: { fontWeight: 400 }, children: "Name and title appear on plans you share" })
6578
6827
  ] }),
6579
6828
  elevation: "flat",
6580
- children: /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)("div", { className: "fd-stack", style: { gap: 14 }, children: [
6581
- /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)("div", { style: { display: "grid", gridTemplateColumns: "repeat(auto-fit,minmax(220px,1fr))", gap: 14 }, children: [
6582
- /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(Input, { label: "Full name", value: draft.name, onChange: (e) => set("name", e.target.value) }),
6583
- /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(Input, { label: "Job title", value: draft.title, onChange: (e) => set("title", e.target.value), placeholder: "e.g. Senior media planner" })
6829
+ children: /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("div", { className: "fd-stack", style: { gap: 14 }, children: [
6830
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("div", { style: { display: "grid", gridTemplateColumns: "repeat(auto-fit,minmax(220px,1fr))", gap: 14 }, children: [
6831
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(Input, { label: "Full name", value: draft.name, onChange: (e) => set("name", e.target.value) }),
6832
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(Input, { label: "Job title", value: draft.title, onChange: (e) => set("title", e.target.value), placeholder: "e.g. Senior media planner" })
6584
6833
  ] }),
6585
- /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)("div", { style: { display: "grid", gridTemplateColumns: "repeat(auto-fit,minmax(220px,1fr))", gap: 14 }, children: [
6586
- /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(
6834
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("div", { style: { display: "grid", gridTemplateColumns: "repeat(auto-fit,minmax(220px,1fr))", gap: 14 }, children: [
6835
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
6587
6836
  Input,
6588
6837
  {
6589
6838
  label: "Work email",
@@ -6593,9 +6842,9 @@ function ProfilePage({ user: userProp, onSave, onNavigate, sessions, showSession
6593
6842
  help: user.sso ? "Managed by your identity provider \u2014 change it there." : "Contact an administrator to change this."
6594
6843
  }
6595
6844
  ),
6596
- /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(Input, { label: "Phone", value: draft.phone, onChange: (e) => set("phone", e.target.value), placeholder: "Optional" })
6845
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(Input, { label: "Phone", value: draft.phone, onChange: (e) => set("phone", e.target.value), placeholder: "Optional" })
6597
6846
  ] }),
6598
- /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(
6847
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
6599
6848
  Textarea,
6600
6849
  {
6601
6850
  label: "Short bio",
@@ -6609,8 +6858,8 @@ function ProfilePage({ user: userProp, onSave, onNavigate, sessions, showSession
6609
6858
  ] })
6610
6859
  }
6611
6860
  ),
6612
- /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(Card, { title: "Working preferences", elevation: "flat", children: /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)("div", { style: { display: "grid", gridTemplateColumns: "repeat(auto-fit,minmax(220px,1fr))", gap: 14 }, children: [
6613
- /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(
6861
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(Card, { title: "Working preferences", elevation: "flat", children: /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("div", { style: { display: "grid", gridTemplateColumns: "repeat(auto-fit,minmax(220px,1fr))", gap: 14 }, children: [
6862
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
6614
6863
  Select,
6615
6864
  {
6616
6865
  label: "Time zone",
@@ -6620,28 +6869,28 @@ function ProfilePage({ user: userProp, onSave, onNavigate, sessions, showSession
6620
6869
  help: "Flight dates and schedules render in this zone."
6621
6870
  }
6622
6871
  ),
6623
- /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(Select, { label: "Start of week", options: ["Monday", "Sunday"], placeholder: "Monday" })
6872
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(Select, { label: "Start of week", options: ["Monday", "Sunday"], placeholder: "Monday" })
6624
6873
  ] }) }),
6625
- /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(
6874
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
6626
6875
  Card,
6627
6876
  {
6628
- title: /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)("span", { className: "fd-stack", style: { gap: 2 }, children: [
6629
- /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("span", { children: "Notifications" }),
6630
- /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("span", { className: "fd-body-sm fd-muted", style: { fontWeight: 400 }, children: "Email only for now \u2014 in-app notifications are on the roadmap" })
6877
+ title: /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("span", { className: "fd-stack", style: { gap: 2 }, children: [
6878
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("span", { children: "Notifications" }),
6879
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("span", { className: "fd-body-sm fd-muted", style: { fontWeight: 400 }, children: "Email only for now \u2014 in-app notifications are on the roadmap" })
6631
6880
  ] }),
6632
6881
  elevation: "flat",
6633
- children: /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("div", { className: "fd-stack", style: { gap: 14 }, children: NOTIFY.map((n) => /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(Switch, { checked: !!draft.notify[n.key], onChange: () => setNotify(n.key), label: n.label, description: n.detail }, n.key)) })
6882
+ children: /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("div", { className: "fd-stack", style: { gap: 14 }, children: NOTIFY.map((n) => /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(Switch, { checked: !!draft.notify[n.key], onChange: () => setNotify(n.key), label: n.label, description: n.detail }, n.key)) })
6634
6883
  }
6635
6884
  ),
6636
- /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)(
6885
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)(
6637
6886
  Card,
6638
6887
  {
6639
- title: /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)("span", { className: "fd-stack", style: { gap: 2 }, children: [
6640
- /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("span", { children: "Access" }),
6641
- /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("span", { className: "fd-body-sm fd-muted", style: { fontWeight: 400 }, children: "What your roles grant you" })
6888
+ title: /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("span", { className: "fd-stack", style: { gap: 2 }, children: [
6889
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("span", { children: "Access" }),
6890
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("span", { className: "fd-body-sm fd-muted", style: { fontWeight: 400 }, children: "What your roles grant you" })
6642
6891
  ] }),
6643
6892
  elevation: "flat",
6644
- action: /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(
6893
+ action: /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
6645
6894
  Button,
6646
6895
  {
6647
6896
  size: "sm",
@@ -6652,39 +6901,39 @@ function ProfilePage({ user: userProp, onSave, onNavigate, sessions, showSession
6652
6901
  }
6653
6902
  ),
6654
6903
  children: [
6655
- /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)("div", { className: "fd-stack", style: { gap: 0 }, children: [
6656
- /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(CardRow, { label: "Roles", children: session.roles.map((r) => r.name).join(", ") || "None" }),
6657
- /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)(CardRow, { label: "Permissions", children: [
6904
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("div", { className: "fd-stack", style: { gap: 0 }, children: [
6905
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(CardRow, { label: "Roles", children: session.roles.map((r) => r.name).join(", ") || "None" }),
6906
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)(CardRow, { label: "Permissions", children: [
6658
6907
  session.permissions.length,
6659
6908
  " granted"
6660
6909
  ] }),
6661
- /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(CardRow, { label: "Member since", children: user.joined || "\u2014" })
6910
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(CardRow, { label: "Member since", children: user.joined || "\u2014" })
6662
6911
  ] }),
6663
- /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("p", { className: "fd-body-sm fd-muted", style: { margin: "12px 0 0" }, children: "You cannot change your own roles \u2014 that is the point of them. An administrator manages roles from Admin \u2192 Users." })
6912
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("p", { className: "fd-body-sm fd-muted", style: { margin: "12px 0 0" }, children: "You cannot change your own roles \u2014 that is the point of them. An administrator manages roles from Admin \u2192 Users." })
6664
6913
  ]
6665
6914
  }
6666
6915
  ),
6667
- showSessions ? /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(
6916
+ showSessions ? /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
6668
6917
  Card,
6669
6918
  {
6670
6919
  title: "Signed-in devices",
6671
6920
  elevation: "flat",
6672
- action: /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(Button, { size: "sm", variant: "ghost", icon: "sign-out", children: "Sign out everywhere" }),
6673
- children: /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("div", { className: "fd-stack", style: { gap: 0 }, children: liveSessions.map((s) => /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)("div", { className: "fd-row", style: { gap: 12, padding: "10px 0", borderTop: "1px solid var(--border)", flexWrap: "wrap" }, children: [
6674
- /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("i", { className: "ph ph-device-mobile", style: { fontSize: 16, color: "var(--text-muted)" }, "aria-hidden": "true" }),
6675
- /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)("span", { className: "fd-stack", style: { gap: 1, flex: 1, minWidth: 160 }, children: [
6676
- /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("span", { className: "fd-body-sm", style: { fontWeight: 600 }, children: s.device }),
6677
- /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)("span", { className: "fd-body-sm fd-muted", children: [
6921
+ action: /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(Button, { size: "sm", variant: "ghost", icon: "sign-out", children: "Sign out everywhere" }),
6922
+ children: /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("div", { className: "fd-stack", style: { gap: 0 }, children: liveSessions.map((s) => /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("div", { className: "fd-row", style: { gap: 12, padding: "10px 0", borderTop: "1px solid var(--border)", flexWrap: "wrap" }, children: [
6923
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("i", { className: "ph ph-device-mobile", style: { fontSize: 16, color: "var(--text-muted)" }, "aria-hidden": "true" }),
6924
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("span", { className: "fd-stack", style: { gap: 1, flex: 1, minWidth: 160 }, children: [
6925
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("span", { className: "fd-body-sm", style: { fontWeight: 600 }, children: s.device }),
6926
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("span", { className: "fd-body-sm fd-muted", children: [
6678
6927
  s.where,
6679
6928
  " \xB7 ",
6680
6929
  s.when
6681
6930
  ] })
6682
6931
  ] }),
6683
- s.current ? /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(Badge, { tone: "success", dot: true, children: "This device" }) : /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(Button, { size: "sm", variant: "ghost", children: "Revoke" })
6932
+ s.current ? /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(Badge, { tone: "success", dot: true, children: "This device" }) : /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(Button, { size: "sm", variant: "ghost", children: "Revoke" })
6684
6933
  ] }, s.id)) })
6685
6934
  }
6686
6935
  ) : null,
6687
- /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)("div", { className: "fd-row", style: {
6936
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("div", { className: "fd-row", style: {
6688
6937
  gap: 10,
6689
6938
  flexWrap: "wrap",
6690
6939
  position: "sticky",
@@ -6695,8 +6944,8 @@ function ProfilePage({ user: userProp, onSave, onNavigate, sessions, showSession
6695
6944
  border: "1px solid var(--border)",
6696
6945
  boxShadow: "0 -4px 16px rgba(11,13,17,.06)"
6697
6946
  }, children: [
6698
- /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("span", { className: "fd-body-sm", style: { fontWeight: 600, flex: 1 }, children: saved ? "Saved." : dirty ? "Unsaved changes" : "No pending changes" }),
6699
- /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(
6947
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("span", { className: "fd-body-sm", style: { fontWeight: 600, flex: 1 }, children: saved ? "Saved." : dirty ? "Unsaved changes" : "No pending changes" }),
6948
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
6700
6949
  Button,
6701
6950
  {
6702
6951
  size: "sm",
@@ -6709,16 +6958,16 @@ function ProfilePage({ user: userProp, onSave, onNavigate, sessions, showSession
6709
6958
  children: "Discard"
6710
6959
  }
6711
6960
  ),
6712
- /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(Button, { size: "sm", icon: "check", disabled: !dirty, loading: saving, onClick: save, children: "Save changes" })
6961
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(Button, { size: "sm", icon: "check", disabled: !dirty, loading: saving, onClick: save, children: "Save changes" })
6713
6962
  ] })
6714
6963
  ] });
6715
6964
  }
6716
6965
 
6717
6966
  // src/components/platform/RoadmapTimeline.tsx
6718
- var React29 = __toESM(require("react"), 1);
6967
+ var React31 = __toESM(require("react"), 1);
6719
6968
 
6720
6969
  // src/kits/runtime.ts
6721
- var React28 = __toESM(require("react"), 1);
6970
+ var React30 = __toESM(require("react"), 1);
6722
6971
  var WIRED_ENDPOINTS = [
6723
6972
  // Nothing yet. Every id below would come from a real service:
6724
6973
  // "plan.get", "placements.list", …
@@ -6889,8 +7138,8 @@ var RuntimeKit = {
6889
7138
  };
6890
7139
  RuntimeKit.declare(FEATURE_NEEDS);
6891
7140
  function useRuntimeMode() {
6892
- const [m, setM] = React28.useState(RuntimeKit.getMode());
6893
- React28.useEffect(() => RuntimeKit.subscribe(setM), []);
7141
+ const [m, setM] = React30.useState(RuntimeKit.getMode());
7142
+ React30.useEffect(() => RuntimeKit.subscribe(setM), []);
6894
7143
  return m;
6895
7144
  }
6896
7145
  function useFeatureStatus(key) {
@@ -6909,7 +7158,7 @@ var UseRuntimeMode = useRuntimeMode;
6909
7158
  var UseFeatureStatus = useFeatureStatus;
6910
7159
 
6911
7160
  // src/components/platform/RoadmapTimeline.tsx
6912
- var import_jsx_runtime56 = require("react/jsx-runtime");
7161
+ var import_jsx_runtime59 = require("react/jsx-runtime");
6913
7162
  var STATUS = {
6914
7163
  shipped: { tone: "success", icon: "check-circle", label: "Wired" },
6915
7164
  next: { tone: "warning", icon: "traffic-cone", label: "Not wired" },
@@ -6924,45 +7173,45 @@ function RoadmapCard({ item, byKey, onOpenFlag }) {
6924
7173
  const s = STATUS[item.status] || STATUS.planned;
6925
7174
  const deps = (item.dependsOn || []).map((k) => byKey[k]).filter(Boolean);
6926
7175
  const blocking = deps.filter((d) => !d.implemented);
6927
- return /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(Card, { elevation: "flat", children: /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("div", { className: "fd-stack", style: { gap: 10 }, children: [
6928
- /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("div", { className: "fd-row", style: { gap: 8, flexWrap: "wrap" }, children: [
6929
- /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("span", { className: "fd-body", style: { fontWeight: 700, flex: 1, minWidth: 140 }, children: item.label }),
6930
- /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(Badge, { tone: "neutral", icon: PROJECT_ICON[item.project] || "squares-four", children: item.project }),
6931
- /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(Badge, { tone: s.tone, icon: s.icon, children: s.label })
7176
+ return /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(Card, { elevation: "flat", children: /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("div", { className: "fd-stack", style: { gap: 10 }, children: [
7177
+ /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("div", { className: "fd-row", style: { gap: 8, flexWrap: "wrap" }, children: [
7178
+ /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("span", { className: "fd-body", style: { fontWeight: 700, flex: 1, minWidth: 140 }, children: item.label }),
7179
+ /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(Badge, { tone: "neutral", icon: PROJECT_ICON[item.project] || "squares-four", children: item.project }),
7180
+ /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(Badge, { tone: s.tone, icon: s.icon, children: s.label })
6932
7181
  ] }),
6933
- /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("p", { className: "fd-body-sm fd-secondary", style: { margin: 0, textWrap: "pretty" }, children: item.description }),
6934
- item.backend ? /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("div", { className: "fd-row", style: { gap: 10, alignItems: "flex-start" }, children: [
6935
- /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("span", { className: "fd-overline fd-muted", style: { width: 62, flex: "none", paddingTop: 2 }, children: "Backend" }),
6936
- /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("span", { className: "fd-body-sm", style: { flex: 1, textWrap: "pretty" }, children: item.backend })
7182
+ /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("p", { className: "fd-body-sm fd-secondary", style: { margin: 0, textWrap: "pretty" }, children: item.description }),
7183
+ item.backend ? /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("div", { className: "fd-row", style: { gap: 10, alignItems: "flex-start" }, children: [
7184
+ /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("span", { className: "fd-overline fd-muted", style: { width: 62, flex: "none", paddingTop: 2 }, children: "Backend" }),
7185
+ /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("span", { className: "fd-body-sm", style: { flex: 1, textWrap: "pretty" }, children: item.backend })
6937
7186
  ] }) : null,
6938
- /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("div", { className: "fd-row", style: { gap: 12, flexWrap: "wrap" }, children: [
6939
- item.effort ? /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("span", { className: "fd-body-sm fd-muted", children: [
6940
- /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("i", { className: "ph ph-hourglass-medium" }),
7187
+ /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("div", { className: "fd-row", style: { gap: 12, flexWrap: "wrap" }, children: [
7188
+ item.effort ? /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("span", { className: "fd-body-sm fd-muted", children: [
7189
+ /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("i", { className: "ph ph-hourglass-medium" }),
6941
7190
  " ",
6942
7191
  item.effort
6943
7192
  ] }) : null,
6944
- /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("span", { className: "fd-body-sm fd-muted", children: [
6945
- /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("i", { className: "ph ph-user" }),
7193
+ /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("span", { className: "fd-body-sm fd-muted", children: [
7194
+ /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("i", { className: "ph ph-user" }),
6946
7195
  " ",
6947
7196
  item.owner
6948
7197
  ] }),
6949
- item.screen ? /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(Badge, { tone: "neutral", icon: "browser", children: "screen" }) : null,
6950
- /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("span", { style: { flex: 1 } }),
6951
- /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(
7198
+ item.screen ? /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(Badge, { tone: "neutral", icon: "browser", children: "screen" }) : null,
7199
+ /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("span", { style: { flex: 1 } }),
7200
+ /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(
6952
7201
  "button",
6953
7202
  {
6954
7203
  type: "button",
6955
7204
  onClick: () => onOpenFlag && onOpenFlag(item.key),
6956
7205
  style: { all: "unset", cursor: "pointer", display: "inline-flex", alignItems: "center", gap: 5 },
6957
- children: /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("code", { className: "fd-mono", style: { fontSize: 11, color: "var(--brand)" }, children: item.key })
7206
+ children: /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("code", { className: "fd-mono", style: { fontSize: 11, color: "var(--brand)" }, children: item.key })
6958
7207
  }
6959
7208
  )
6960
7209
  ] }),
6961
- deps.length ? /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("div", { className: "fd-row", style: { gap: 6, flexWrap: "wrap", paddingTop: 6, borderTop: "1px solid var(--border)" }, children: [
6962
- /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("span", { className: "fd-overline fd-muted", style: { paddingTop: 3 }, children: "After" }),
6963
- deps.map((d) => /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(Tag, { icon: d.implemented ? "check" : "clock", children: d.label }, d.key))
7210
+ deps.length ? /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("div", { className: "fd-row", style: { gap: 6, flexWrap: "wrap", paddingTop: 6, borderTop: "1px solid var(--border)" }, children: [
7211
+ /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("span", { className: "fd-overline fd-muted", style: { paddingTop: 3 }, children: "After" }),
7212
+ deps.map((d) => /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(Tag, { icon: d.implemented ? "check" : "clock", children: d.label }, d.key))
6964
7213
  ] }) : null,
6965
- blocking.length && !item.implemented ? /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("span", { className: "fd-body-sm", style: { color: "var(--warn-text)" }, children: [
7214
+ blocking.length && !item.implemented ? /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("span", { className: "fd-body-sm", style: { color: "var(--warn-text)" }, children: [
6966
7215
  "Blocked until ",
6967
7216
  blocking.map((d) => d.label).join(" and "),
6968
7217
  " ",
@@ -6973,12 +7222,12 @@ function RoadmapCard({ item, byKey, onOpenFlag }) {
6973
7222
  }
6974
7223
  function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
6975
7224
  const session = SessionKit.useSession();
6976
- const [project, setProject] = React29.useState("");
6977
- const [q, setQ] = React29.useState("");
6978
- const scrollRef = React29.useRef(null);
6979
- const nowRef = React29.useRef(null);
6980
- const rm = React29.useMemo(() => SessionKit.roadmap({ isComplete: RuntimeKit.isComplete }), [session]);
6981
- const byKey = React29.useMemo(() => {
7225
+ const [project, setProject] = React31.useState("");
7226
+ const [q, setQ] = React31.useState("");
7227
+ const scrollRef = React31.useRef(null);
7228
+ const nowRef = React31.useRef(null);
7229
+ const rm = React31.useMemo(() => SessionKit.roadmap({ isComplete: RuntimeKit.isComplete }), [session]);
7230
+ const byKey = React31.useMemo(() => {
6982
7231
  const m = {};
6983
7232
  rm.items.forEach((i) => {
6984
7233
  m[i.key] = i;
@@ -6987,7 +7236,7 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
6987
7236
  }, [rm]);
6988
7237
  const items = rm.items.filter((i) => (!project || i.project === project) && (!q || (i.label + " " + i.description + " " + (i.backend || "") + " " + i.key).toLowerCase().includes(q.toLowerCase())));
6989
7238
  const projects = [...new Set(rm.items.map((i) => i.project))];
6990
- React29.useEffect(() => {
7239
+ React31.useEffect(() => {
6991
7240
  let raf1 = 0, raf2 = 0;
6992
7241
  const place = () => {
6993
7242
  const box = scrollRef.current, mark = nowRef.current;
@@ -7015,23 +7264,23 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
7015
7264
  }, 0);
7016
7265
  const nextPhase = items.find((i) => !i.implemented);
7017
7266
  let lastPhase = null;
7018
- return /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("div", { className: "fd-stack", style: { gap: 16, maxWidth: 1e3 }, children: [
7019
- /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("div", { className: "fd-stack", style: { gap: 10 }, children: [
7020
- /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("span", { className: "fd-overline fd-muted", children: "Architecture" }),
7021
- /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("h1", { className: "fd-h1", style: { margin: 0 }, children: title }),
7022
- /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("p", { className: "fd-body fd-secondary fd-prose", style: { margin: 0 }, children: lede || "Every screen and feature in these tools is already designed and working against a simulated backend. This is the plan for connecting them to the real one \u2014 so the only work described here is server work." })
7267
+ return /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("div", { className: "fd-stack", style: { gap: 16, maxWidth: 1e3 }, children: [
7268
+ /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("div", { className: "fd-stack", style: { gap: 10 }, children: [
7269
+ /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("span", { className: "fd-overline fd-muted", children: "Architecture" }),
7270
+ /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("h1", { className: "fd-h1", style: { margin: 0 }, children: title }),
7271
+ /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("p", { className: "fd-body fd-secondary fd-prose", style: { margin: 0 }, children: lede || "Every screen and feature in these tools is already designed and working against a simulated backend. This is the plan for connecting them to the real one \u2014 so the only work described here is server work." })
7023
7272
  ] }),
7024
- /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("div", { className: "fd-grid-stats is-thin", children: [
7025
- /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(StatTile, { compact: true, label: "Wired", value: String(rm.shipped), sub: "of " + rm.items.length + " features" }),
7026
- /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(StatTile, { compact: true, label: "Remaining", value: String(rm.remaining), sub: "backend work" }),
7027
- /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(StatTile, { compact: true, label: "Est. effort", value: days ? days + " days" : "\u2014", sub: "sum of estimates, not calendar" }),
7028
- /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(StatTile, { compact: true, label: "Up next", value: nextPhase ? "Phase " + nextPhase.phase : "\u2014", sub: nextPhase ? nextPhase.phaseName : "all wired" })
7273
+ /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("div", { className: "fd-grid-stats is-thin", children: [
7274
+ /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(StatTile, { compact: true, label: "Wired", value: String(rm.shipped), sub: "of " + rm.items.length + " features" }),
7275
+ /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(StatTile, { compact: true, label: "Remaining", value: String(rm.remaining), sub: "backend work" }),
7276
+ /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(StatTile, { compact: true, label: "Est. effort", value: days ? days + " days" : "\u2014", sub: "sum of estimates, not calendar" }),
7277
+ /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(StatTile, { compact: true, label: "Up next", value: nextPhase ? "Phase " + nextPhase.phase : "\u2014", sub: nextPhase ? nextPhase.phaseName : "all wired" })
7029
7278
  ] }),
7030
- /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("div", { className: "fd-row", style: { gap: 10, flexWrap: "wrap" }, children: [
7031
- /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(Input, { icon: "magnifying-glass", placeholder: "Find a feature or a piece of backend work", value: q, onChange: (e) => setQ(e.target.value), style: { width: 300 } }),
7032
- /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(Select, { placeholder: "All projects", value: project, onChange: (e) => setProject(e.target.value), options: projects, style: { width: 190 } }),
7033
- /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("span", { style: { flex: 1 } }),
7034
- /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(
7279
+ /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("div", { className: "fd-row", style: { gap: 10, flexWrap: "wrap" }, children: [
7280
+ /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(Input, { icon: "magnifying-glass", placeholder: "Find a feature or a piece of backend work", value: q, onChange: (e) => setQ(e.target.value), style: { width: 300 } }),
7281
+ /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(Select, { placeholder: "All projects", value: project, onChange: (e) => setProject(e.target.value), options: projects, style: { width: 190 } }),
7282
+ /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("span", { style: { flex: 1 } }),
7283
+ /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(
7035
7284
  Button,
7036
7285
  {
7037
7286
  size: "sm",
@@ -7045,7 +7294,7 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
7045
7294
  }
7046
7295
  )
7047
7296
  ] }),
7048
- /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(
7297
+ /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(
7049
7298
  Flag,
7050
7299
  {
7051
7300
  tone: "info",
@@ -7054,60 +7303,60 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
7054
7303
  actions: null
7055
7304
  }
7056
7305
  ),
7057
- /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("div", { className: "fd-rm", children: /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("div", { className: "fd-rm-scroll", ref: scrollRef, children: /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("div", { className: "fd-rm-track", children: [
7058
- /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("span", { className: "fd-rm-spine", children: /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("span", { className: "fd-rm-spine-done", style: { height: items.length ? 100 * shippedShown / items.length + "%" : "0%" } }) }),
7306
+ /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("div", { className: "fd-rm", children: /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("div", { className: "fd-rm-scroll", ref: scrollRef, children: /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("div", { className: "fd-rm-track", children: [
7307
+ /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("span", { className: "fd-rm-spine", children: /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("span", { className: "fd-rm-spine-done", style: { height: items.length ? 100 * shippedShown / items.length + "%" : "0%" } }) }),
7059
7308
  items.map((item, n) => {
7060
7309
  const showPhase = item.phase !== lastPhase;
7061
7310
  lastPhase = item.phase;
7062
7311
  const inPhase = items.filter((i) => i.phase === item.phase).length;
7063
7312
  const isBoundary = n === firstPending;
7064
- return /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)(React29.Fragment, { children: [
7065
- showPhase ? /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("div", { className: "fd-rm-era", children: [
7066
- /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("span", { className: "fd-row", style: { gap: 8, flexWrap: "wrap", alignItems: "baseline" }, children: [
7067
- /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("span", { style: { fontWeight: 700 }, children: item.phase === 0 ? "Shipped" : "Phase " + item.phase + " \u2014 " + item.phaseName }),
7068
- item.phase === 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("span", { className: "fd-mono", style: { opacity: 0.7, fontWeight: 400 }, children: [
7313
+ return /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)(React31.Fragment, { children: [
7314
+ showPhase ? /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("div", { className: "fd-rm-era", children: [
7315
+ /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("span", { className: "fd-row", style: { gap: 8, flexWrap: "wrap", alignItems: "baseline" }, children: [
7316
+ /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("span", { style: { fontWeight: 700 }, children: item.phase === 0 ? "Shipped" : "Phase " + item.phase + " \u2014 " + item.phaseName }),
7317
+ item.phase === 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("span", { className: "fd-mono", style: { opacity: 0.7, fontWeight: 400 }, children: [
7069
7318
  fmtDate(item.phaseStart),
7070
7319
  " \u2013 ",
7071
7320
  fmtDate(item.date)
7072
7321
  ] }),
7073
- /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("span", { style: { opacity: 0.7, fontWeight: 400 }, children: [
7322
+ /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("span", { style: { opacity: 0.7, fontWeight: 400 }, children: [
7074
7323
  "\xB7 ",
7075
7324
  inPhase,
7076
7325
  " feature",
7077
7326
  inPhase === 1 ? "" : "s"
7078
7327
  ] })
7079
7328
  ] }),
7080
- item.phaseWhy ? /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("p", { className: "fd-rm-era-why", children: item.phaseWhy }) : null
7329
+ item.phaseWhy ? /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("p", { className: "fd-rm-era-why", children: item.phaseWhy }) : null
7081
7330
  ] }) : null,
7082
- isBoundary ? /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("div", { className: "fd-rm-now", ref: nowRef, children: /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("span", { className: "fd-rm-now-pill", children: [
7083
- /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("i", { className: "ph ph-map-pin" }),
7331
+ isBoundary ? /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("div", { className: "fd-rm-now", ref: nowRef, children: /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("span", { className: "fd-rm-now-pill", children: [
7332
+ /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("i", { className: "ph ph-map-pin" }),
7084
7333
  " You are here \u2014 everything above is wired"
7085
7334
  ] }) }) : null,
7086
- /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("div", { className: "fd-rm-row", children: [
7087
- /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("span", { className: "fd-rm-dot " + (item.implemented ? "is-shipped" : item.status === "next" ? "is-next" : "") }),
7088
- /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("div", { className: "fd-rm-date", children: [
7335
+ /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("div", { className: "fd-rm-row", children: [
7336
+ /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("span", { className: "fd-rm-dot " + (item.implemented ? "is-shipped" : item.status === "next" ? "is-next" : "") }),
7337
+ /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("div", { className: "fd-rm-date", children: [
7089
7338
  fmtDate(item.date),
7090
- /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("br", {}),
7091
- /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("span", { style: { opacity: 0.75 }, children: item.implemented ? "shipped" : "phase " + item.phase })
7339
+ /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("br", {}),
7340
+ /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("span", { style: { opacity: 0.75 }, children: item.implemented ? "shipped" : "phase " + item.phase })
7092
7341
  ] }),
7093
- /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(RoadmapCard, { item, byKey, onOpenFlag })
7342
+ /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(RoadmapCard, { item, byKey, onOpenFlag })
7094
7343
  ] })
7095
7344
  ] }, item.key);
7096
7345
  }),
7097
- !items.length ? /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("p", { className: "fd-body-sm fd-muted", children: "Nothing matches that filter." }) : null
7346
+ !items.length ? /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("p", { className: "fd-body-sm fd-muted", children: "Nothing matches that filter." }) : null
7098
7347
  ] }) }) }),
7099
- /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("p", { className: "fd-body-sm fd-muted", style: { margin: 0 }, children: [
7348
+ /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("p", { className: "fd-body-sm fd-muted", style: { margin: 0 }, children: [
7100
7349
  "Derived from the feature-flag registry \u2014 each entry's status is its flag's ",
7101
- /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("code", { className: "fd-mono", children: "implemented" }),
7350
+ /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("code", { className: "fd-mono", children: "implemented" }),
7102
7351
  " field, so this page cannot drift from what the apps actually do."
7103
7352
  ] })
7104
7353
  ] });
7105
7354
  }
7106
7355
 
7107
7356
  // src/components/platform/ComingSoon.tsx
7108
- var React30 = __toESM(require("react"), 1);
7357
+ var React32 = __toESM(require("react"), 1);
7109
7358
  var import_react_dom7 = require("react-dom");
7110
- var import_jsx_runtime57 = require("react/jsx-runtime");
7359
+ var import_jsx_runtime60 = require("react/jsx-runtime");
7111
7360
  var BYPASS_STORE = "fd.soon.bypass.v1";
7112
7361
  function readBypassed() {
7113
7362
  try {
@@ -7123,8 +7372,8 @@ function writeBypassed(list) {
7123
7372
  }
7124
7373
  }
7125
7374
  function useBypass(key) {
7126
- const [on, setOn] = React30.useState(() => !!key && readBypassed().indexOf(key) >= 0);
7127
- React30.useEffect(() => {
7375
+ const [on, setOn] = React32.useState(() => !!key && readBypassed().indexOf(key) >= 0);
7376
+ React32.useEffect(() => {
7128
7377
  setOn(!!key && readBypassed().indexOf(key) >= 0);
7129
7378
  }, [key]);
7130
7379
  const set = (next) => {
@@ -7137,43 +7386,43 @@ function useBypass(key) {
7137
7386
  return [on, set];
7138
7387
  }
7139
7388
  function SoonCard({ label, detail, backend, eta, effort, onRoadmap, allowed, onBypass }) {
7140
- return /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(import_jsx_runtime57.Fragment, { children: [
7141
- /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("span", { className: "fd-soon-badge", children: [
7142
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" }),
7389
+ return /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)(import_jsx_runtime60.Fragment, { children: [
7390
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("span", { className: "fd-soon-badge", children: [
7391
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" }),
7143
7392
  label
7144
7393
  ] }),
7145
- detail ? /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { className: "fd-soon-detail", children: detail }) : null,
7146
- backend ? /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("span", { className: "fd-soon-backend", children: [
7147
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { className: "fd-overline", children: "Needs" }),
7394
+ detail ? /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("span", { className: "fd-soon-detail", children: detail }) : null,
7395
+ backend ? /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("span", { className: "fd-soon-backend", children: [
7396
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("span", { className: "fd-overline", children: "Needs" }),
7148
7397
  " ",
7149
7398
  backend
7150
7399
  ] }) : null,
7151
- eta || effort || onRoadmap ? /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("span", { className: "fd-soon-meta", children: [
7152
- eta ? /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("span", { children: [
7153
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("i", { className: "ph ph-calendar-blank", "aria-hidden": "true" }),
7400
+ eta || effort || onRoadmap ? /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("span", { className: "fd-soon-meta", children: [
7401
+ eta ? /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("span", { children: [
7402
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("i", { className: "ph ph-calendar-blank", "aria-hidden": "true" }),
7154
7403
  " ",
7155
7404
  eta
7156
7405
  ] }) : null,
7157
- effort ? /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("span", { children: [
7158
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("i", { className: "ph ph-hourglass-medium", "aria-hidden": "true" }),
7406
+ effort ? /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("span", { children: [
7407
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("i", { className: "ph ph-hourglass-medium", "aria-hidden": "true" }),
7159
7408
  " ",
7160
7409
  effort
7161
7410
  ] }) : null,
7162
- onRoadmap ? /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("button", { type: "button", className: "fd-soon-link", onClick: onRoadmap, children: [
7411
+ onRoadmap ? /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("button", { type: "button", className: "fd-soon-link", onClick: onRoadmap, children: [
7163
7412
  "See the roadmap ",
7164
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("i", { className: "ph ph-arrow-right", "aria-hidden": "true" })
7413
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("i", { className: "ph ph-arrow-right", "aria-hidden": "true" })
7165
7414
  ] }) : null
7166
7415
  ] }) : null,
7167
- allowed ? /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("button", { type: "button", className: "fd-soon-view", onClick: onBypass, children: [
7168
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("i", { className: "ph ph-eye", "aria-hidden": "true" }),
7416
+ allowed ? /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("button", { type: "button", className: "fd-soon-view", onClick: onBypass, children: [
7417
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("i", { className: "ph ph-eye", "aria-hidden": "true" }),
7169
7418
  " View and use it anyway"
7170
7419
  ] }) : null
7171
7420
  ] });
7172
7421
  }
7173
7422
  function useHoverCard(open) {
7174
- const anchor = React30.useRef(null);
7175
- const [pos, setPos] = React30.useState(null);
7176
- React30.useLayoutEffect(() => {
7423
+ const anchor = React32.useRef(null);
7424
+ const [pos, setPos] = React32.useState(null);
7425
+ React32.useLayoutEffect(() => {
7177
7426
  if (!open || !anchor.current) {
7178
7427
  setPos(null);
7179
7428
  return;
@@ -7225,9 +7474,9 @@ function ComingSoon({
7225
7474
  const tip = [label, detail, backend ? "Needs " + backend : null, eta ? "ETA " + eta : null, effort].filter(Boolean).join(" \xB7 ");
7226
7475
  if (inline) {
7227
7476
  if (allowed && bypassed) {
7228
- return /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("span", { className: ["fd-soon-inline-on", className].filter(Boolean).join(" "), ...rest, children: [
7477
+ return /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("span", { className: ["fd-soon-inline-on", className].filter(Boolean).join(" "), ...rest, children: [
7229
7478
  children,
7230
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
7479
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
7231
7480
  "button",
7232
7481
  {
7233
7482
  type: "button",
@@ -7235,12 +7484,12 @@ function ComingSoon({
7235
7484
  title: "Unwired \u2014 writes go to the simulated backend. " + tip + " Click to re-blur.",
7236
7485
  onClick: () => setBypassed(false),
7237
7486
  "aria-label": "Re-blur this unwired feature",
7238
- children: /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" })
7487
+ children: /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" })
7239
7488
  }
7240
7489
  )
7241
7490
  ] });
7242
7491
  }
7243
- return /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
7492
+ return /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
7244
7493
  InlineSoon,
7245
7494
  {
7246
7495
  label,
@@ -7260,20 +7509,20 @@ function ComingSoon({
7260
7509
  );
7261
7510
  }
7262
7511
  if (allowed && bypassed) {
7263
- return /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 14 }, ...rest, children: [
7264
- /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { className: "fd-soon-bar", role: "status", children: [
7265
- /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("span", { className: "fd-soon-badge", children: [
7266
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" }),
7512
+ return /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 14 }, ...rest, children: [
7513
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("div", { className: "fd-soon-bar", role: "status", children: [
7514
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("span", { className: "fd-soon-badge", children: [
7515
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" }),
7267
7516
  "Unwired feature \u2014 you are using it anyway"
7268
7517
  ] }),
7269
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { className: "fd-soon-bar-detail", children: "Every action here writes to the simulated backend, so nothing you do persists beyond this session." }),
7270
- /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("span", { className: "fd-soon-bar-actions", children: [
7271
- onRoadmap ? /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("button", { type: "button", className: "fd-soon-link", onClick: onRoadmap, children: [
7518
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("span", { className: "fd-soon-bar-detail", children: "Every action here writes to the simulated backend, so nothing you do persists beyond this session." }),
7519
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("span", { className: "fd-soon-bar-actions", children: [
7520
+ onRoadmap ? /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("button", { type: "button", className: "fd-soon-link", onClick: onRoadmap, children: [
7272
7521
  "Roadmap ",
7273
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("i", { className: "ph ph-arrow-right", "aria-hidden": "true" })
7522
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("i", { className: "ph ph-arrow-right", "aria-hidden": "true" })
7274
7523
  ] }) : null,
7275
- /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("button", { type: "button", className: "fd-soon-link", onClick: () => setBypassed(false), children: [
7276
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("i", { className: "ph ph-eye-slash", "aria-hidden": "true" }),
7524
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("button", { type: "button", className: "fd-soon-link", onClick: () => setBypassed(false), children: [
7525
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("i", { className: "ph ph-eye-slash", "aria-hidden": "true" }),
7277
7526
  " Re-blur"
7278
7527
  ] })
7279
7528
  ] })
@@ -7281,10 +7530,10 @@ function ComingSoon({
7281
7530
  children
7282
7531
  ] });
7283
7532
  }
7284
- return /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { className: ["fd-soon", className].filter(Boolean).join(" "), style: minHeight ? { minHeight } : void 0, ...rest, children: [
7285
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("div", { className: "fd-soon-under", style: { filter: "blur(" + blur + "px) saturate(.62)" }, ...{ inert: "" }, "aria-hidden": "true", children }),
7286
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("div", { className: "fd-soon-veil" }),
7287
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("div", { className: "fd-soon-note", role: "note", children: /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
7533
+ return /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("div", { className: ["fd-soon", className].filter(Boolean).join(" "), style: minHeight ? { minHeight } : void 0, ...rest, children: [
7534
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("div", { className: "fd-soon-under", style: { filter: "blur(" + blur + "px) saturate(.62)" }, ...{ inert: "" }, "aria-hidden": "true", children }),
7535
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("div", { className: "fd-soon-veil" }),
7536
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("div", { className: "fd-soon-note", role: "note", children: /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
7288
7537
  SoonCard,
7289
7538
  {
7290
7539
  label,
@@ -7300,9 +7549,9 @@ function ComingSoon({
7300
7549
  ] });
7301
7550
  }
7302
7551
  function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, onBypass, blur, tip, className, rest, children }) {
7303
- const [open, setOpen] = React30.useState(false);
7552
+ const [open, setOpen] = React32.useState(false);
7304
7553
  const [anchor, pos] = useHoverCard(open);
7305
- const close = React30.useRef(null);
7554
+ const close = React32.useRef(null);
7306
7555
  const show = () => {
7307
7556
  if (close.current) {
7308
7557
  clearTimeout(close.current);
@@ -7318,10 +7567,10 @@ function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, o
7318
7567
  setOpen(false);
7319
7568
  }, 140);
7320
7569
  };
7321
- React30.useEffect(() => () => {
7570
+ React32.useEffect(() => () => {
7322
7571
  if (close.current) clearTimeout(close.current);
7323
7572
  }, []);
7324
- return /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(
7573
+ return /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)(
7325
7574
  "span",
7326
7575
  {
7327
7576
  ref: anchor,
@@ -7332,8 +7581,8 @@ function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, o
7332
7581
  onBlur: hide,
7333
7582
  ...rest,
7334
7583
  children: [
7335
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { className: "fd-soon-under", style: { filter: "blur(" + Math.min(blur, 1.1) + "px) saturate(.66)" }, ...{ inert: "" }, "aria-hidden": "true", children }),
7336
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
7584
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("span", { className: "fd-soon-under", style: { filter: "blur(" + Math.min(blur, 1.1) + "px) saturate(.66)" }, ...{ inert: "" }, "aria-hidden": "true", children }),
7585
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
7337
7586
  "button",
7338
7587
  {
7339
7588
  type: "button",
@@ -7344,11 +7593,11 @@ function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, o
7344
7593
  onFocus: show,
7345
7594
  onBlur: hide,
7346
7595
  onClick: () => open ? setOpen(false) : show(),
7347
- children: /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" })
7596
+ children: /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" })
7348
7597
  }
7349
7598
  ),
7350
7599
  open && pos ? (0, import_react_dom7.createPortal)(
7351
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
7600
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
7352
7601
  "div",
7353
7602
  {
7354
7603
  className: "fd-soon-note fd-soon-hovercard",
@@ -7356,7 +7605,7 @@ function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, o
7356
7605
  style: { position: "fixed", left: pos.left, top: pos.top, bottom: pos.bottom, width: pos.width },
7357
7606
  onMouseEnter: show,
7358
7607
  onMouseLeave: hide,
7359
- children: /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
7608
+ children: /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
7360
7609
  SoonCard,
7361
7610
  {
7362
7611
  label,
@@ -7386,10 +7635,10 @@ function formatEta(iso2) {
7386
7635
  var FormatEta = formatEta;
7387
7636
 
7388
7637
  // src/components/platform/Gate.tsx
7389
- var import_jsx_runtime58 = require("react/jsx-runtime");
7638
+ var import_jsx_runtime61 = require("react/jsx-runtime");
7390
7639
  function PermissionDenied({ permission, title, detail, compact: compact3 = false, className = "", ...rest }) {
7391
7640
  const need = Array.isArray(permission) ? permission : [permission].filter(Boolean);
7392
- return /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)(
7641
+ return /* @__PURE__ */ (0, import_jsx_runtime61.jsxs)(
7393
7642
  "div",
7394
7643
  {
7395
7644
  className: ["fd-stack", className].filter(Boolean).join(" "),
@@ -7405,14 +7654,14 @@ function PermissionDenied({ permission, title, detail, compact: compact3 = false
7405
7654
  },
7406
7655
  ...rest,
7407
7656
  children: [
7408
- /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("span", { className: "fd-row", style: { gap: 8 }, children: [
7409
- /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("i", { className: "ph ph-lock-simple", style: { fontSize: 16, color: "var(--text-muted)" }, "aria-hidden": "true" }),
7410
- /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("span", { className: compact3 ? "fd-label-lg" : "fd-h3", children: title || "You do not have access to this" })
7657
+ /* @__PURE__ */ (0, import_jsx_runtime61.jsxs)("span", { className: "fd-row", style: { gap: 8 }, children: [
7658
+ /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("i", { className: "ph ph-lock-simple", style: { fontSize: 16, color: "var(--text-muted)" }, "aria-hidden": "true" }),
7659
+ /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("span", { className: compact3 ? "fd-label-lg" : "fd-h3", children: title || "You do not have access to this" })
7411
7660
  ] }),
7412
- /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("p", { className: "fd-body-sm fd-secondary", style: { margin: 0, textWrap: "pretty" }, children: detail || "Your roles do not grant this. An administrator can change that from Admin \u2192 Users." }),
7413
- need.length ? /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("span", { className: "fd-row", style: { gap: 6, flexWrap: "wrap" }, children: [
7414
- /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("span", { className: "fd-overline fd-muted", children: "Requires" }),
7415
- need.map((p) => /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("code", { className: "fd-mono", style: {
7661
+ /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("p", { className: "fd-body-sm fd-secondary", style: { margin: 0, textWrap: "pretty" }, children: detail || "Your roles do not grant this. An administrator can change that from Admin \u2192 Users." }),
7662
+ need.length ? /* @__PURE__ */ (0, import_jsx_runtime61.jsxs)("span", { className: "fd-row", style: { gap: 6, flexWrap: "wrap" }, children: [
7663
+ /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("span", { className: "fd-overline fd-muted", children: "Requires" }),
7664
+ need.map((p) => /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("code", { className: "fd-mono", style: {
7416
7665
  fontSize: 11.5,
7417
7666
  padding: "2px 7px",
7418
7667
  borderRadius: 5,
@@ -7433,7 +7682,7 @@ function Gate({ perm, anyOf, role, silent = false, fallback, compact: compact3 =
7433
7682
  if (ok) return children;
7434
7683
  if (fallback !== void 0) return fallback;
7435
7684
  if (silent) return null;
7436
- return /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(PermissionDenied, { permission: perm || anyOf, compact: compact3 });
7685
+ return /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(PermissionDenied, { permission: perm || anyOf, compact: compact3 });
7437
7686
  }
7438
7687
  function FeatureGate({
7439
7688
  flag,
@@ -7454,7 +7703,7 @@ function FeatureGate({
7454
7703
  if (!preview) return fallback;
7455
7704
  const f = SessionKit.findFlag(flag) || {};
7456
7705
  const missing = rt.missing || [];
7457
- return /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
7706
+ return /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(
7458
7707
  ComingSoon,
7459
7708
  {
7460
7709
  label: label || (variant === "inline" ? f.label || "Not wired yet" : "Designed \u2014 backend not wired yet"),
@@ -7475,25 +7724,25 @@ function FeatureGate({
7475
7724
  function PermissionHint({ perm, children }) {
7476
7725
  SessionKit.useSession();
7477
7726
  if (SessionKit.can(perm)) return children;
7478
- return /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
7727
+ return /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(
7479
7728
  "span",
7480
7729
  {
7481
7730
  title: "Requires " + (Array.isArray(perm) ? perm.join(", ") : perm),
7482
7731
  style: { display: "inline-flex", opacity: 0.45, cursor: "not-allowed" },
7483
7732
  "aria-disabled": "true",
7484
- children: /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("span", { style: { pointerEvents: "none" }, children })
7733
+ children: /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("span", { style: { pointerEvents: "none" }, children })
7485
7734
  }
7486
7735
  );
7487
7736
  }
7488
7737
 
7489
7738
  // src/components/platform/ModeSwitch.tsx
7490
- var React31 = __toESM(require("react"), 1);
7491
- var import_jsx_runtime59 = require("react/jsx-runtime");
7739
+ var React33 = __toESM(require("react"), 1);
7740
+ var import_jsx_runtime62 = require("react/jsx-runtime");
7492
7741
  function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog, onOpenSpec, summary }) {
7493
7742
  const mode2 = useRuntimeMode();
7494
- const [open, setOpen] = React31.useState(false);
7495
- const ref = React31.useRef(null);
7496
- React31.useEffect(() => {
7743
+ const [open, setOpen] = React33.useState(false);
7744
+ const ref = React33.useRef(null);
7745
+ React33.useEffect(() => {
7497
7746
  if (!open) return;
7498
7747
  const away = (e) => {
7499
7748
  if (ref.current && !ref.current.contains(e.target)) setOpen(false);
@@ -7515,8 +7764,8 @@ function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog
7515
7764
  RuntimeKit.setMode(next);
7516
7765
  setOpen(false);
7517
7766
  };
7518
- return /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("span", { style: { position: "relative", display: "inline-flex" }, ref, children: [
7519
- /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)(
7767
+ return /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("span", { style: { position: "relative", display: "inline-flex" }, ref, children: [
7768
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)(
7520
7769
  "button",
7521
7770
  {
7522
7771
  type: "button",
@@ -7526,29 +7775,29 @@ function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog
7526
7775
  title: test ? "Test mode \u2014 every response is simulated. Click to inspect requests or return to live mode." : "Live mode \u2014 incomplete features are shown under construction. Click for test mode.",
7527
7776
  className: "fd-mode-btn" + (test ? " is-test" : "") + (open ? " is-open" : ""),
7528
7777
  children: [
7529
- /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("i", { className: "ph " + (test ? "ph-flask" : "ph-lightning"), style: { fontSize: 17 } }),
7530
- test && requestCount ? /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("span", { className: "fd-mono fd-mode-count", children: requestCount > 99 ? "99+" : requestCount }, requestCount) : null
7778
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("i", { className: "ph " + (test ? "ph-flask" : "ph-lightning"), style: { fontSize: 17 } }),
7779
+ test && requestCount ? /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("span", { className: "fd-mono fd-mode-count", children: requestCount > 99 ? "99+" : requestCount }, requestCount) : null
7531
7780
  ]
7532
7781
  }
7533
7782
  ),
7534
- open ? /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("span", { className: "fd-view-enter fd-mode-pop", children: [
7535
- /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("span", { className: "fd-row", style: { gap: 10, padding: "12px 14px", borderBottom: "1px solid var(--border)" }, children: [
7536
- /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("span", { className: "fd-badge " + (test ? "fd-badge-warning" : "fd-badge-neutral"), children: [
7537
- /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("i", { className: "ph " + (test ? "ph-flask" : "ph-lightning"), "aria-hidden": "true" }),
7783
+ open ? /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("span", { className: "fd-view-enter fd-mode-pop", children: [
7784
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("span", { className: "fd-row", style: { gap: 10, padding: "12px 14px", borderBottom: "1px solid var(--border)" }, children: [
7785
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("span", { className: "fd-badge " + (test ? "fd-badge-warning" : "fd-badge-neutral"), children: [
7786
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("i", { className: "ph " + (test ? "ph-flask" : "ph-lightning"), "aria-hidden": "true" }),
7538
7787
  test ? "Test mode" : "Live mode"
7539
7788
  ] }),
7540
- test ? /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("span", { className: "fd-body-sm fd-muted fd-mono", children: [
7789
+ test ? /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("span", { className: "fd-body-sm fd-muted fd-mono", children: [
7541
7790
  requestCount,
7542
7791
  " simulated request",
7543
7792
  requestCount === 1 ? "" : "s"
7544
7793
  ] }) : null,
7545
- /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("span", { style: { flex: 1 } }),
7546
- test && onClearLog ? /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("button", { type: "button", className: "fd-soon-link", onClick: onClearLog, children: "Clear" }) : null
7794
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("span", { style: { flex: 1 } }),
7795
+ test && onClearLog ? /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("button", { type: "button", className: "fd-soon-link", onClick: onClearLog, children: "Clear" }) : null
7547
7796
  ] }),
7548
- /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("span", { style: { display: "block", padding: "12px 14px", borderBottom: "1px solid var(--border)" }, children: [
7549
- /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("span", { className: "fd-body-sm fd-secondary", style: { display: "block", textWrap: "pretty" }, children: test ? "Every feature is usable and nothing is obstructed, but no response comes from a real service \u2014 nothing you do here persists. Use this to review and demo the design." : "This is what a user would see today. " + s.incomplete + " of " + s.total + " features depend on backend work that is not wired yet, so they render under construction." }),
7550
- /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("span", { className: "fd-row", style: { gap: 8, marginTop: 10, flexWrap: "wrap" }, children: [
7551
- /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("span", { className: "fd-body-sm fd-muted fd-mono", children: [
7797
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("span", { style: { display: "block", padding: "12px 14px", borderBottom: "1px solid var(--border)" }, children: [
7798
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("span", { className: "fd-body-sm fd-secondary", style: { display: "block", textWrap: "pretty" }, children: test ? "Every feature is usable and nothing is obstructed, but no response comes from a real service \u2014 nothing you do here persists. Use this to review and demo the design." : "This is what a user would see today. " + s.incomplete + " of " + s.total + " features depend on backend work that is not wired yet, so they render under construction." }),
7799
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("span", { className: "fd-row", style: { gap: 8, marginTop: 10, flexWrap: "wrap" }, children: [
7800
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("span", { className: "fd-body-sm fd-muted fd-mono", children: [
7552
7801
  s.endpointsWired,
7553
7802
  " endpoint",
7554
7803
  s.endpointsWired === 1 ? "" : "s",
@@ -7558,58 +7807,58 @@ function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog
7558
7807
  s.total,
7559
7808
  " features complete"
7560
7809
  ] }),
7561
- onOpenSpec ? /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)(import_jsx_runtime59.Fragment, { children: [
7562
- /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("span", { style: { flex: 1 } }),
7563
- /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("button", { type: "button", className: "fd-soon-link", onClick: () => {
7810
+ onOpenSpec ? /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)(import_jsx_runtime62.Fragment, { children: [
7811
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("span", { style: { flex: 1 } }),
7812
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("button", { type: "button", className: "fd-soon-link", onClick: () => {
7564
7813
  setOpen(false);
7565
7814
  onOpenSpec();
7566
7815
  }, children: [
7567
7816
  "API spec ",
7568
- /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("i", { className: "ph ph-arrow-right", "aria-hidden": "true" })
7817
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("i", { className: "ph ph-arrow-right", "aria-hidden": "true" })
7569
7818
  ] })
7570
7819
  ] }) : null
7571
7820
  ] })
7572
7821
  ] }),
7573
- /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("span", { className: "fd-mode-choice", children: [
7574
- /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("button", { type: "button", className: "fd-mode-opt" + (!test ? " is-on" : ""), onClick: () => go("live"), children: [
7575
- /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("i", { className: "ph ph-lightning", "aria-hidden": "true" }),
7576
- /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("span", { className: "fd-mode-opt-text", children: [
7577
- /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("span", { className: "fd-mode-opt-title", children: "Live mode" }),
7578
- /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("span", { className: "fd-mode-opt-desc", children: "Incomplete features under construction" })
7822
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("span", { className: "fd-mode-choice", children: [
7823
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("button", { type: "button", className: "fd-mode-opt" + (!test ? " is-on" : ""), onClick: () => go("live"), children: [
7824
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("i", { className: "ph ph-lightning", "aria-hidden": "true" }),
7825
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("span", { className: "fd-mode-opt-text", children: [
7826
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("span", { className: "fd-mode-opt-title", children: "Live mode" }),
7827
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("span", { className: "fd-mode-opt-desc", children: "Incomplete features under construction" })
7579
7828
  ] }),
7580
- !test ? /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("i", { className: "ph ph-check", "aria-hidden": "true" }) : null
7829
+ !test ? /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("i", { className: "ph ph-check", "aria-hidden": "true" }) : null
7581
7830
  ] }),
7582
- /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("button", { type: "button", className: "fd-mode-opt" + (test ? " is-on" : ""), onClick: () => go("test"), children: [
7583
- /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("i", { className: "ph ph-flask", "aria-hidden": "true" }),
7584
- /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("span", { className: "fd-mode-opt-text", children: [
7585
- /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("span", { className: "fd-mode-opt-title", children: "Test mode" }),
7586
- /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("span", { className: "fd-mode-opt-desc", children: "Everything usable, all data simulated" })
7831
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("button", { type: "button", className: "fd-mode-opt" + (test ? " is-on" : ""), onClick: () => go("test"), children: [
7832
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("i", { className: "ph ph-flask", "aria-hidden": "true" }),
7833
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("span", { className: "fd-mode-opt-text", children: [
7834
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("span", { className: "fd-mode-opt-title", children: "Test mode" }),
7835
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("span", { className: "fd-mode-opt-desc", children: "Everything usable, all data simulated" })
7587
7836
  ] }),
7588
- test ? /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("i", { className: "ph ph-check", "aria-hidden": "true" }) : null
7837
+ test ? /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("i", { className: "ph ph-check", "aria-hidden": "true" }) : null
7589
7838
  ] })
7590
7839
  ] }),
7591
- test && renderLog ? /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("span", { style: { display: "block", maxHeight: 340, overflowY: "auto", borderTop: "1px solid var(--border)" }, children: renderLog() }) : null
7840
+ test && renderLog ? /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("span", { style: { display: "block", maxHeight: 340, overflowY: "auto", borderTop: "1px solid var(--border)" }, children: renderLog() }) : null
7592
7841
  ] }) : null
7593
7842
  ] });
7594
7843
  }
7595
7844
  function TestModeBar({ onExit }) {
7596
7845
  const mode2 = useRuntimeMode();
7597
7846
  if (mode2 !== "test") return null;
7598
- return /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("div", { className: "fd-testbar", role: "status", children: [
7599
- /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("span", { className: "fd-badge fd-badge-warning", children: [
7600
- /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("i", { className: "ph ph-flask", "aria-hidden": "true" }),
7847
+ return /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("div", { className: "fd-testbar", role: "status", children: [
7848
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("span", { className: "fd-badge fd-badge-warning", children: [
7849
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("i", { className: "ph ph-flask", "aria-hidden": "true" }),
7601
7850
  "Test mode"
7602
7851
  ] }),
7603
- /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("span", { className: "fd-testbar-detail", children: "Every feature is unlocked and every response is simulated \u2014 nothing here persists." }),
7604
- /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("button", { type: "button", className: "fd-soon-link", onClick: () => onExit ? onExit() : RuntimeKit.setMode("live"), children: [
7605
- /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("i", { className: "ph ph-lightning", "aria-hidden": "true" }),
7852
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("span", { className: "fd-testbar-detail", children: "Every feature is unlocked and every response is simulated \u2014 nothing here persists." }),
7853
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("button", { type: "button", className: "fd-soon-link", onClick: () => onExit ? onExit() : RuntimeKit.setMode("live"), children: [
7854
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("i", { className: "ph ph-lightning", "aria-hidden": "true" }),
7606
7855
  " Back to live mode"
7607
7856
  ] })
7608
7857
  ] });
7609
7858
  }
7610
7859
 
7611
7860
  // src/components/planner/ChannelMeta.tsx
7612
- var import_jsx_runtime60 = require("react/jsx-runtime");
7861
+ var import_jsx_runtime63 = require("react/jsx-runtime");
7613
7862
  var CHANNEL_WEIGHTS = {
7614
7863
  "OOH": 50,
7615
7864
  "DOOH": 50,
@@ -7662,9 +7911,9 @@ function ChannelTag({ channel, size = "md", showLabel = true, dot = false, weigh
7662
7911
  const m = ChannelMeta(channel);
7663
7912
  const wt = channelWeightOf(channel || "");
7664
7913
  if (dot) {
7665
- return /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("span", { className: ["fd-chan-dot", className].filter(Boolean).join(" "), title: m.name, style: { background: m.color }, ...rest });
7914
+ return /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("span", { className: ["fd-chan-dot", className].filter(Boolean).join(" "), title: m.name, style: { background: m.color }, ...rest });
7666
7915
  }
7667
- return /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)(
7916
+ return /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)(
7668
7917
  "span",
7669
7918
  {
7670
7919
  className: ["fd-chan", size === "sm" ? "fd-chan-sm" : "", className].filter(Boolean).join(" "),
@@ -7672,16 +7921,16 @@ function ChannelTag({ channel, size = "md", showLabel = true, dot = false, weigh
7672
7921
  style: { "--chan": m.color },
7673
7922
  ...rest,
7674
7923
  children: [
7675
- /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("i", { className: "ph ph-" + m.icon, "aria-hidden": "true" }),
7676
- showLabel ? /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("span", { className: "fd-chan-label", children: m.label }) : null,
7677
- weight ? /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("span", { className: "fd-chan-weight", children: wt || 0 }) : null
7924
+ /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("i", { className: "ph ph-" + m.icon, "aria-hidden": "true" }),
7925
+ showLabel ? /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("span", { className: "fd-chan-label", children: m.label }) : null,
7926
+ weight ? /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("span", { className: "fd-chan-weight", children: wt || 0 }) : null
7678
7927
  ]
7679
7928
  }
7680
7929
  );
7681
7930
  }
7682
7931
 
7683
7932
  // src/components/planner/SaturationDistribution.tsx
7684
- var import_jsx_runtime61 = require("react/jsx-runtime");
7933
+ var import_jsx_runtime64 = require("react/jsx-runtime");
7685
7934
  var BANDS2 = [
7686
7935
  { key: "weak", label: "Weak", n: 1, range: "< 50" },
7687
7936
  { key: "adequate", label: "Adequate", n: 2, range: "50\u2013100" },
@@ -7692,18 +7941,18 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
7692
7941
  const grouped = BANDS2.map((b) => ({ ...b, items: campuses.filter((c) => c.band === b.key) }));
7693
7942
  const tallest = Math.max(1, ...grouped.map((g) => g.items.length));
7694
7943
  const floor = BANDS2.find((b) => b.key === floorBand) || BANDS2[0];
7695
- return /* @__PURE__ */ (0, import_jsx_runtime61.jsxs)("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 16 }, children: [
7696
- /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("div", { style: { display: "grid", gridTemplateColumns: "repeat(4,1fr)", gap: 12, alignItems: "end" }, children: grouped.map((g) => {
7944
+ return /* @__PURE__ */ (0, import_jsx_runtime64.jsxs)("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 16 }, children: [
7945
+ /* @__PURE__ */ (0, import_jsx_runtime64.jsx)("div", { style: { display: "grid", gridTemplateColumns: "repeat(4,1fr)", gap: 12, alignItems: "end" }, children: grouped.map((g) => {
7697
7946
  const mark = "var(--csi-" + g.n + "-mark)";
7698
7947
  const active = selectedBand === g.key;
7699
- return /* @__PURE__ */ (0, import_jsx_runtime61.jsxs)(
7948
+ return /* @__PURE__ */ (0, import_jsx_runtime64.jsxs)(
7700
7949
  "button",
7701
7950
  {
7702
7951
  type: "button",
7703
7952
  onClick: onSelectBand ? () => onSelectBand(active ? null : g.key) : void 0,
7704
7953
  style: { display: "flex", flexDirection: "column", justifyContent: "flex-end", gap: 10, padding: 12, border: "1px solid " + (active ? "var(--border-strong)" : "var(--border)"), borderRadius: "var(--r-lg)", background: active ? "var(--surface-2)" : "var(--surface)", cursor: onSelectBand ? "pointer" : "default", textAlign: "left", minHeight: 190, transition: "background var(--dur-fast) var(--ease),border-color var(--dur-fast) var(--ease)" },
7705
7954
  children: [
7706
- /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("span", { style: { display: "flex", flexDirection: "column-reverse", gap: 4, minHeight: tallest * 24 }, children: loading ? Array.from({ length: 3 }).map((_, i) => /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("span", { className: "fd-skel", style: { height: 16, borderRadius: 4 } }, i)) : g.items.map((c) => /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(
7955
+ /* @__PURE__ */ (0, import_jsx_runtime64.jsx)("span", { style: { display: "flex", flexDirection: "column-reverse", gap: 4, minHeight: tallest * 24 }, children: loading ? Array.from({ length: 3 }).map((_, i) => /* @__PURE__ */ (0, import_jsx_runtime64.jsx)("span", { className: "fd-skel", style: { height: 16, borderRadius: 4 } }, i)) : g.items.map((c) => /* @__PURE__ */ (0, import_jsx_runtime64.jsx)(
7707
7956
  "span",
7708
7957
  {
7709
7958
  title: c.name + " \xB7 " + c.crp,
@@ -7712,13 +7961,13 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
7712
7961
  },
7713
7962
  c.name
7714
7963
  )) }),
7715
- /* @__PURE__ */ (0, import_jsx_runtime61.jsxs)("span", { className: "fd-row", style: { gap: 8, alignItems: "baseline" }, children: [
7716
- /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("span", { className: "fd-num-hero", style: { fontSize: 30, color: g.items.length ? "var(--text)" : "var(--text-disabled)" }, children: loading ? "\u2013" : g.items.length }),
7717
- /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("span", { className: "fd-meter", style: { gap: 2, color: mark }, "aria-hidden": "true", children: [1, 2, 3, 4].map((i) => /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("span", { className: "fd-meter-seg" + (i <= g.n ? " is-on" : ""), style: { width: 4, height: 9 } }, i)) })
7964
+ /* @__PURE__ */ (0, import_jsx_runtime64.jsxs)("span", { className: "fd-row", style: { gap: 8, alignItems: "baseline" }, children: [
7965
+ /* @__PURE__ */ (0, import_jsx_runtime64.jsx)("span", { className: "fd-num-hero", style: { fontSize: 30, color: g.items.length ? "var(--text)" : "var(--text-disabled)" }, children: loading ? "\u2013" : g.items.length }),
7966
+ /* @__PURE__ */ (0, import_jsx_runtime64.jsx)("span", { className: "fd-meter", style: { gap: 2, color: mark }, "aria-hidden": "true", children: [1, 2, 3, 4].map((i) => /* @__PURE__ */ (0, import_jsx_runtime64.jsx)("span", { className: "fd-meter-seg" + (i <= g.n ? " is-on" : ""), style: { width: 4, height: 9 } }, i)) })
7718
7967
  ] }),
7719
- /* @__PURE__ */ (0, import_jsx_runtime61.jsxs)("span", { className: "fd-stack", style: { gap: 1 }, children: [
7720
- /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("span", { className: "fd-label-lg", children: g.label }),
7721
- /* @__PURE__ */ (0, import_jsx_runtime61.jsxs)("span", { className: "fd-body-sm fd-muted", style: { fontSize: 11.5 }, children: [
7968
+ /* @__PURE__ */ (0, import_jsx_runtime64.jsxs)("span", { className: "fd-stack", style: { gap: 1 }, children: [
7969
+ /* @__PURE__ */ (0, import_jsx_runtime64.jsx)("span", { className: "fd-label-lg", children: g.label }),
7970
+ /* @__PURE__ */ (0, import_jsx_runtime64.jsxs)("span", { className: "fd-body-sm fd-muted", style: { fontSize: 11.5 }, children: [
7722
7971
  "CRP ",
7723
7972
  g.range
7724
7973
  ] })
@@ -7728,10 +7977,10 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
7728
7977
  g.key
7729
7978
  );
7730
7979
  }) }),
7731
- floorBand ? /* @__PURE__ */ (0, import_jsx_runtime61.jsxs)("div", { className: "fd-row", style: { gap: 10, padding: "12px 14px", borderRadius: "var(--r-md)", background: "var(--surface-2)", border: "1px solid var(--border)", flexWrap: "wrap" }, children: [
7732
- /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("span", { className: "fd-meter", style: { gap: 2, color: "var(--csi-" + floor.n + "-mark)" }, "aria-hidden": "true", children: [1, 2, 3, 4].map((i) => /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("span", { className: "fd-meter-seg" + (i <= floor.n ? " is-on" : ""), style: { width: 5, height: 12 } }, i)) }),
7733
- /* @__PURE__ */ (0, import_jsx_runtime61.jsxs)("span", { className: "fd-body-sm fd-secondary", style: { flex: 1, minWidth: 240 }, children: [
7734
- /* @__PURE__ */ (0, import_jsx_runtime61.jsxs)("strong", { style: { color: "var(--text)" }, children: [
7980
+ floorBand ? /* @__PURE__ */ (0, import_jsx_runtime64.jsxs)("div", { className: "fd-row", style: { gap: 10, padding: "12px 14px", borderRadius: "var(--r-md)", background: "var(--surface-2)", border: "1px solid var(--border)", flexWrap: "wrap" }, children: [
7981
+ /* @__PURE__ */ (0, import_jsx_runtime64.jsx)("span", { className: "fd-meter", style: { gap: 2, color: "var(--csi-" + floor.n + "-mark)" }, "aria-hidden": "true", children: [1, 2, 3, 4].map((i) => /* @__PURE__ */ (0, import_jsx_runtime64.jsx)("span", { className: "fd-meter-seg" + (i <= floor.n ? " is-on" : ""), style: { width: 5, height: 12 } }, i)) }),
7982
+ /* @__PURE__ */ (0, import_jsx_runtime64.jsxs)("span", { className: "fd-body-sm fd-secondary", style: { flex: 1, minWidth: 240 }, children: [
7983
+ /* @__PURE__ */ (0, import_jsx_runtime64.jsxs)("strong", { style: { color: "var(--text)" }, children: [
7735
7984
  "Plan floor ",
7736
7985
  floorScore
7737
7986
  ] }),
@@ -7742,21 +7991,21 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
7742
7991
  }
7743
7992
 
7744
7993
  // src/components/planner/MixGap.tsx
7745
- var React32 = __toESM(require("react"), 1);
7746
- var import_jsx_runtime62 = require("react/jsx-runtime");
7994
+ var React34 = __toESM(require("react"), 1);
7995
+ var import_jsx_runtime65 = require("react/jsx-runtime");
7747
7996
  function MixGap({ rows = [], loading = false, className = "" }) {
7748
7997
  const max = Math.max(1, ...rows.flatMap((r) => [r.target, r.realized]));
7749
- const [hover, setHover] = React32.useState(null);
7998
+ const [hover, setHover] = React34.useState(null);
7750
7999
  const toneOf = (gap) => gap >= -1 ? "ok" : gap >= -4 ? "warn" : "danger";
7751
8000
  const TONE = { ok: "var(--ok-solid)", warn: "var(--warn-solid)", danger: "var(--danger-solid)" };
7752
- return /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 4 }, children: [
7753
- /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("div", { className: "fd-row", style: { gap: 16, justifyContent: "flex-end", paddingBottom: 6, flexWrap: "wrap" }, children: [
7754
- [["On target", TONE.ok], ["Close", TONE.warn], ["Short", TONE.danger]].map(([l, c]) => /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("span", { className: "fd-row fd-body-sm fd-muted", style: { gap: 6 }, children: [
7755
- /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("span", { style: { width: 14, height: 9, borderRadius: 2, background: c } }),
8001
+ return /* @__PURE__ */ (0, import_jsx_runtime65.jsxs)("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 4 }, children: [
8002
+ /* @__PURE__ */ (0, import_jsx_runtime65.jsxs)("div", { className: "fd-row", style: { gap: 16, justifyContent: "flex-end", paddingBottom: 6, flexWrap: "wrap" }, children: [
8003
+ [["On target", TONE.ok], ["Close", TONE.warn], ["Short", TONE.danger]].map(([l, c]) => /* @__PURE__ */ (0, import_jsx_runtime65.jsxs)("span", { className: "fd-row fd-body-sm fd-muted", style: { gap: 6 }, children: [
8004
+ /* @__PURE__ */ (0, import_jsx_runtime65.jsx)("span", { style: { width: 14, height: 9, borderRadius: 2, background: c } }),
7756
8005
  l
7757
8006
  ] }, l)),
7758
- /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("span", { className: "fd-row fd-body-sm fd-muted", style: { gap: 6 }, children: [
7759
- /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("span", { style: { width: 3, height: 14, background: "var(--n-500)" } }),
8007
+ /* @__PURE__ */ (0, import_jsx_runtime65.jsxs)("span", { className: "fd-row fd-body-sm fd-muted", style: { gap: 6 }, children: [
8008
+ /* @__PURE__ */ (0, import_jsx_runtime65.jsx)("span", { style: { width: 3, height: 14, background: "var(--n-500)" } }),
7760
8009
  "Target"
7761
8010
  ] })
7762
8011
  ] }),
@@ -7764,7 +8013,7 @@ function MixGap({ rows = [], loading = false, className = "" }) {
7764
8013
  const gap = r.realized - r.target;
7765
8014
  const tone = toneOf(gap);
7766
8015
  const tip = "Realized " + r.realized + "% vs " + r.target + "% target" + (gap < -1 ? " \xB7 " + Math.abs(gap).toFixed(0) + " pts short" : gap > 1 ? " \xB7 " + gap.toFixed(0) + " pts over" : " \xB7 on target") + (r.note ? " \u2014 " + r.note : "");
7767
- return /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)(
8016
+ return /* @__PURE__ */ (0, import_jsx_runtime65.jsxs)(
7768
8017
  "div",
7769
8018
  {
7770
8019
  className: "fd-row",
@@ -7772,15 +8021,15 @@ function MixGap({ rows = [], loading = false, className = "" }) {
7772
8021
  onMouseEnter: () => setHover(r.channel),
7773
8022
  onMouseLeave: () => setHover(null),
7774
8023
  children: [
7775
- /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("span", { style: { width: 128, flex: "none" }, children: /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(ChannelTag, { channel: r.channel, size: "sm" }) }),
7776
- /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("span", { style: { position: "relative", flex: 1, height: 22, minWidth: 120 }, children: loading ? /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("span", { className: "fd-skel", style: { position: "absolute", inset: "5px 0", borderRadius: 3 } }) : /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)(import_jsx_runtime62.Fragment, { children: [
7777
- /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("span", { style: { position: "absolute", left: 0, top: 5, height: 12, width: r.realized / max * 100 + "%", background: TONE[tone], borderRadius: "2px 3px 3px 2px", transition: "width var(--dur-slow) var(--ease), background var(--dur-base) var(--ease)" } }),
7778
- /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("span", { style: { position: "absolute", left: r.target / max * 100 + "%", top: 0, width: 3, height: 22, background: "var(--n-500)", borderRadius: 1 } }),
7779
- /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("span", { className: "fd-num", style: { position: "absolute", right: Math.max(r.realized, r.target) / max > 0.82 ? 0 : "auto", left: Math.max(r.realized, r.target) / max > 0.82 ? "auto" : "calc(" + Math.max(r.realized, r.target) / max * 100 + "% + 10px)", top: 2, fontSize: 12, color: "var(--text-muted)", whiteSpace: "nowrap", background: Math.max(r.realized, r.target) / max > 0.82 ? "var(--surface)" : "none", paddingLeft: 3 }, children: [
8024
+ /* @__PURE__ */ (0, import_jsx_runtime65.jsx)("span", { style: { width: 128, flex: "none" }, children: /* @__PURE__ */ (0, import_jsx_runtime65.jsx)(ChannelTag, { channel: r.channel, size: "sm" }) }),
8025
+ /* @__PURE__ */ (0, import_jsx_runtime65.jsx)("span", { style: { position: "relative", flex: 1, height: 22, minWidth: 120 }, children: loading ? /* @__PURE__ */ (0, import_jsx_runtime65.jsx)("span", { className: "fd-skel", style: { position: "absolute", inset: "5px 0", borderRadius: 3 } }) : /* @__PURE__ */ (0, import_jsx_runtime65.jsxs)(import_jsx_runtime65.Fragment, { children: [
8026
+ /* @__PURE__ */ (0, import_jsx_runtime65.jsx)("span", { style: { position: "absolute", left: 0, top: 5, height: 12, width: r.realized / max * 100 + "%", background: TONE[tone], borderRadius: "2px 3px 3px 2px", transition: "width var(--dur-slow) var(--ease), background var(--dur-base) var(--ease)" } }),
8027
+ /* @__PURE__ */ (0, import_jsx_runtime65.jsx)("span", { style: { position: "absolute", left: r.target / max * 100 + "%", top: 0, width: 3, height: 22, background: "var(--n-500)", borderRadius: 1 } }),
8028
+ /* @__PURE__ */ (0, import_jsx_runtime65.jsxs)("span", { className: "fd-num", style: { position: "absolute", right: Math.max(r.realized, r.target) / max > 0.82 ? 0 : "auto", left: Math.max(r.realized, r.target) / max > 0.82 ? "auto" : "calc(" + Math.max(r.realized, r.target) / max * 100 + "% + 10px)", top: 2, fontSize: 12, color: "var(--text-muted)", whiteSpace: "nowrap", background: Math.max(r.realized, r.target) / max > 0.82 ? "var(--surface)" : "none", paddingLeft: 3 }, children: [
7780
8029
  r.realized,
7781
8030
  "%"
7782
8031
  ] }),
7783
- hover === r.channel ? /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("span", { className: "fd-tooltip", role: "tooltip", style: { position: "absolute", left: 0, right: "auto", bottom: 26, maxWidth: "min(340px, 100%)", whiteSpace: "normal", textAlign: "left", width: "max-content" }, children: tip }) : null
8032
+ hover === r.channel ? /* @__PURE__ */ (0, import_jsx_runtime65.jsx)("span", { className: "fd-tooltip", role: "tooltip", style: { position: "absolute", left: 0, right: "auto", bottom: 26, maxWidth: "min(340px, 100%)", whiteSpace: "normal", textAlign: "left", width: "max-content" }, children: tip }) : null
7784
8033
  ] }) })
7785
8034
  ]
7786
8035
  },
@@ -7791,7 +8040,7 @@ function MixGap({ rows = [], loading = false, className = "" }) {
7791
8040
  }
7792
8041
 
7793
8042
  // src/components/planner/ChannelContribution.tsx
7794
- var import_jsx_runtime63 = require("react/jsx-runtime");
8043
+ var import_jsx_runtime66 = require("react/jsx-runtime");
7795
8044
  var money = (n) => "$" + Math.round(n).toLocaleString();
7796
8045
  function ChannelContribution({
7797
8046
  channels = [],
@@ -7807,9 +8056,9 @@ function ChannelContribution({
7807
8056
  const grand = total !== void 0 ? total : base + bonus;
7808
8057
  const pct = (v) => grand ? v / grand * 100 : 0;
7809
8058
  const spendTotal = channels.reduce((s, c) => s + Number(String(c.spend || 0).replace(/[^0-9.]/g, "")), 0);
7810
- return /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 16 }, children: [
7811
- loading ? /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("span", { className: "fd-skel", style: { height: 34, borderRadius: "var(--r-sm)" } }) : /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)("div", { className: "fd-row", style: { height: 34, borderRadius: "var(--r-sm)", overflow: "hidden", gap: 2, background: "var(--surface-3)" }, children: [
7812
- channels.map((c) => /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(
8059
+ return /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 16 }, children: [
8060
+ loading ? /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("span", { className: "fd-skel", style: { height: 34, borderRadius: "var(--r-sm)" } }) : /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("div", { className: "fd-row", style: { height: 34, borderRadius: "var(--r-sm)", overflow: "hidden", gap: 2, background: "var(--surface-3)" }, children: [
8061
+ channels.map((c) => /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(
7813
8062
  "span",
7814
8063
  {
7815
8064
  title: c.name + " \xB7 " + c.crp.toFixed(1) + " CRP",
@@ -7818,7 +8067,7 @@ function ChannelContribution({
7818
8067
  },
7819
8068
  c.name
7820
8069
  )),
7821
- bonus > 0 ? /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(
8070
+ bonus > 0 ? /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(
7822
8071
  "span",
7823
8072
  {
7824
8073
  title: "Surround-sound bonus +" + bonusPct + "%",
@@ -7827,18 +8076,18 @@ function ChannelContribution({
7827
8076
  }
7828
8077
  ) : null
7829
8078
  ] }),
7830
- showTable ? /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)("table", { className: "fd-table", style: { fontSize: "var(--body-sm-size)" }, children: [
7831
- /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)("tr", { children: [
7832
- /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("th", { style: { width: "34%" }, children: "Channel" }),
7833
- /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("th", { style: { width: "16%" }, children: "Weight" }),
7834
- /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("th", { className: "is-num", style: { width: "16%" }, children: "Spend" }),
7835
- /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("th", { className: "is-num", style: { width: "17%" }, children: "CRP" }),
7836
- /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("th", { className: "is-num", style: { width: "17%" }, children: "Share" })
8079
+ showTable ? /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("table", { className: "fd-table", style: { fontSize: "var(--body-sm-size)" }, children: [
8080
+ /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("tr", { children: [
8081
+ /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("th", { style: { width: "34%" }, children: "Channel" }),
8082
+ /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("th", { style: { width: "16%" }, children: "Weight" }),
8083
+ /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("th", { className: "is-num", style: { width: "16%" }, children: "Spend" }),
8084
+ /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("th", { className: "is-num", style: { width: "17%" }, children: "CRP" }),
8085
+ /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("th", { className: "is-num", style: { width: "17%" }, children: "Share" })
7837
8086
  ] }) }),
7838
- /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)("tbody", { children: [
7839
- channels.map((c) => /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)("tr", { children: [
7840
- /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("td", { children: /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(ChannelTag, { channel: c.name, size: "sm" }) }),
7841
- /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("td", { children: /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(
8087
+ /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("tbody", { children: [
8088
+ channels.map((c) => /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("tr", { children: [
8089
+ /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("td", { children: /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(ChannelTag, { channel: c.name, size: "sm" }) }),
8090
+ /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("td", { children: /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(
7842
8091
  "span",
7843
8092
  {
7844
8093
  className: "fd-badge fd-badge-neutral",
@@ -7847,38 +8096,38 @@ function ChannelContribution({
7847
8096
  children: "weight " + (channelWeightOf(c.name) || 0)
7848
8097
  }
7849
8098
  ) }),
7850
- /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("td", { className: "is-num", children: c.spend }),
7851
- /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("td", { className: "is-num", children: c.crp.toFixed(1) }),
7852
- /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)("td", { className: "is-num", children: [
8099
+ /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("td", { className: "is-num", children: c.spend }),
8100
+ /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("td", { className: "is-num", children: c.crp.toFixed(1) }),
8101
+ /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("td", { className: "is-num", children: [
7853
8102
  pct(c.crp).toFixed(0),
7854
8103
  "%"
7855
8104
  ] })
7856
8105
  ] }, c.name)),
7857
- bonus > 0 ? /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)("tr", { children: [
7858
- /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("td", { children: /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)("span", { className: "fd-row", style: { gap: 9, fontWeight: 600 }, children: [
7859
- /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("span", { style: { width: 9, height: 9, borderRadius: 2, background: "repeating-linear-gradient(135deg,var(--csi-3-mark) 0 3px,var(--csi-2-mark) 3px 6px)", flex: "none" } }),
8106
+ bonus > 0 ? /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("tr", { children: [
8107
+ /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("td", { children: /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("span", { className: "fd-row", style: { gap: 9, fontWeight: 600 }, children: [
8108
+ /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("span", { style: { width: 9, height: 9, borderRadius: 2, background: "repeating-linear-gradient(135deg,var(--csi-3-mark) 0 3px,var(--csi-2-mark) 3px 6px)", flex: "none" } }),
7860
8109
  "Surround-sound bonus"
7861
8110
  ] }) }),
7862
- /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("td", { children: /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)("span", { className: "fd-badge fd-badge-success", style: { height: 20, fontSize: 11 }, children: [
8111
+ /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("td", { children: /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("span", { className: "fd-badge fd-badge-success", style: { height: 20, fontSize: 11 }, children: [
7863
8112
  "+",
7864
8113
  bonusPct,
7865
8114
  "% of +",
7866
8115
  bonusMax,
7867
8116
  "%"
7868
8117
  ] }) }),
7869
- /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("td", { className: "is-num fd-muted", children: "\u2014" }),
7870
- /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("td", { className: "is-num", children: bonus.toFixed(1) }),
7871
- /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)("td", { className: "is-num", children: [
8118
+ /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("td", { className: "is-num fd-muted", children: "\u2014" }),
8119
+ /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("td", { className: "is-num", children: bonus.toFixed(1) }),
8120
+ /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("td", { className: "is-num", children: [
7872
8121
  pct(bonus).toFixed(0),
7873
8122
  "%"
7874
8123
  ] })
7875
8124
  ] }) : null,
7876
- /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)("tr", { style: { background: "var(--surface-2)" }, children: [
7877
- /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("td", { style: { fontWeight: 700 }, children: "Campus total" }),
7878
- /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("td", {}),
7879
- /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("td", { className: "is-num", style: { fontWeight: 700 }, children: money(spendTotal) }),
7880
- /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("td", { className: "is-num", style: { fontWeight: 700 }, children: grand.toFixed(1) }),
7881
- /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("td", { className: "is-num", style: { fontWeight: 700 }, children: "100%" })
8125
+ /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("tr", { style: { background: "var(--surface-2)" }, children: [
8126
+ /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("td", { style: { fontWeight: 700 }, children: "Campus total" }),
8127
+ /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("td", {}),
8128
+ /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("td", { className: "is-num", style: { fontWeight: 700 }, children: money(spendTotal) }),
8129
+ /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("td", { className: "is-num", style: { fontWeight: 700 }, children: grand.toFixed(1) }),
8130
+ /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("td", { className: "is-num", style: { fontWeight: 700 }, children: "100%" })
7882
8131
  ] })
7883
8132
  ] })
7884
8133
  ] }) : null
@@ -7886,8 +8135,8 @@ function ChannelContribution({
7886
8135
  }
7887
8136
 
7888
8137
  // src/components/planner/BudgetReallocator.tsx
7889
- var React33 = __toESM(require("react"), 1);
7890
- var import_jsx_runtime64 = require("react/jsx-runtime");
8138
+ var React35 = __toESM(require("react"), 1);
8139
+ var import_jsx_runtime67 = require("react/jsx-runtime");
7891
8140
  var bandFor = (crp) => crp >= 200 ? "dominant" : crp >= 100 ? "strong" : crp >= 50 ? "adequate" : "weak";
7892
8141
  function BudgetReallocator({
7893
8142
  campus,
@@ -7902,8 +8151,8 @@ function BudgetReallocator({
7902
8151
  onCancel,
7903
8152
  className = ""
7904
8153
  }) {
7905
- const [draft, setDraft] = React33.useState(spend);
7906
- React33.useEffect(() => setDraft(spend), [spend]);
8154
+ const [draft, setDraft] = React35.useState(spend);
8155
+ React35.useEffect(() => setDraft(spend), [spend]);
7907
8156
  const dirty = draft !== spend;
7908
8157
  const nextCrp = scoreFor ? scoreFor(draft) : crp;
7909
8158
  const nextBand = bandFor(nextCrp);
@@ -7918,24 +8167,24 @@ function BudgetReallocator({
7918
8167
  setDraft(spend);
7919
8168
  if (onCancel) onCancel();
7920
8169
  };
7921
- return /* @__PURE__ */ (0, import_jsx_runtime64.jsxs)(
8170
+ return /* @__PURE__ */ (0, import_jsx_runtime67.jsxs)(
7922
8171
  "div",
7923
8172
  {
7924
8173
  className: ["fd-stack", className].filter(Boolean).join(" "),
7925
8174
  style: { gap: 14, padding: 18, border: "1px solid " + (dirty ? "var(--border-brand)" : "var(--border)"), borderRadius: "var(--r-lg)", background: dirty ? "var(--surface-brand)" : "var(--surface)", color: "var(--text)", transition: "background var(--dur-base) var(--ease),border-color var(--dur-base) var(--ease)" },
7926
8175
  children: [
7927
- /* @__PURE__ */ (0, import_jsx_runtime64.jsxs)("div", { className: "fd-row", style: { gap: 12, flexWrap: "wrap" }, children: [
7928
- /* @__PURE__ */ (0, import_jsx_runtime64.jsx)("span", { className: "fd-h4", style: { flex: 1, minWidth: 140 }, children: campus }),
7929
- /* @__PURE__ */ (0, import_jsx_runtime64.jsx)(CsiBadge, { band: nowBand, crp: Number(crp.toFixed(1)), size: "medium" }),
7930
- dirty ? /* @__PURE__ */ (0, import_jsx_runtime64.jsxs)(import_jsx_runtime64.Fragment, { children: [
7931
- /* @__PURE__ */ (0, import_jsx_runtime64.jsx)("i", { className: "ph ph-arrow-right fd-muted", "aria-hidden": "true" }),
7932
- /* @__PURE__ */ (0, import_jsx_runtime64.jsx)(CsiBadge, { band: nextBand, crp: Number(nextCrp.toFixed(1)), size: "medium", preview: true })
8176
+ /* @__PURE__ */ (0, import_jsx_runtime67.jsxs)("div", { className: "fd-row", style: { gap: 12, flexWrap: "wrap" }, children: [
8177
+ /* @__PURE__ */ (0, import_jsx_runtime67.jsx)("span", { className: "fd-h4", style: { flex: 1, minWidth: 140 }, children: campus }),
8178
+ /* @__PURE__ */ (0, import_jsx_runtime67.jsx)(CsiBadge, { band: nowBand, crp, size: "medium" }),
8179
+ dirty ? /* @__PURE__ */ (0, import_jsx_runtime67.jsxs)(import_jsx_runtime67.Fragment, { children: [
8180
+ /* @__PURE__ */ (0, import_jsx_runtime67.jsx)("i", { className: "ph ph-arrow-right fd-muted", "aria-hidden": "true" }),
8181
+ /* @__PURE__ */ (0, import_jsx_runtime67.jsx)(CsiBadge, { band: nextBand, crp: nextCrp, size: "medium", preview: true })
7933
8182
  ] }) : null
7934
8183
  ] }),
7935
- /* @__PURE__ */ (0, import_jsx_runtime64.jsxs)("div", { className: "fd-slider", children: [
7936
- /* @__PURE__ */ (0, import_jsx_runtime64.jsx)("span", { className: "fd-slider-fill", style: { width: pct + "%" } }),
7937
- dirty ? /* @__PURE__ */ (0, import_jsx_runtime64.jsx)("span", { className: "fd-slider-chip", style: { left: pct + "%", background: delta < 0 ? "var(--danger-solid)" : "var(--ok-solid)" }, children: (delta < 0 ? "\u2212$" : "+$") + Math.abs(delta).toLocaleString() }) : null,
7938
- /* @__PURE__ */ (0, import_jsx_runtime64.jsx)(
8184
+ /* @__PURE__ */ (0, import_jsx_runtime67.jsxs)("div", { className: "fd-slider", children: [
8185
+ /* @__PURE__ */ (0, import_jsx_runtime67.jsx)("span", { className: "fd-slider-fill", style: { width: pct + "%" } }),
8186
+ dirty ? /* @__PURE__ */ (0, import_jsx_runtime67.jsx)("span", { className: "fd-slider-chip", style: { left: pct + "%", background: delta < 0 ? "var(--danger-solid)" : "var(--ok-solid)" }, children: (delta < 0 ? "\u2212$" : "+$") + Math.abs(delta).toLocaleString() }) : null,
8187
+ /* @__PURE__ */ (0, import_jsx_runtime67.jsx)(
7939
8188
  "input",
7940
8189
  {
7941
8190
  type: "range",
@@ -7951,13 +8200,13 @@ function BudgetReallocator({
7951
8200
  }
7952
8201
  )
7953
8202
  ] }),
7954
- /* @__PURE__ */ (0, import_jsx_runtime64.jsxs)("div", { className: "fd-row", style: { gap: 12, flexWrap: "wrap" }, children: [
7955
- /* @__PURE__ */ (0, import_jsx_runtime64.jsxs)("span", { className: "fd-stack", style: { gap: 2, flex: 1, minWidth: 150 }, children: [
7956
- /* @__PURE__ */ (0, import_jsx_runtime64.jsx)("span", { className: "fd-num", style: { fontSize: 19, fontWeight: 700 }, children: "$" + draft.toLocaleString() }),
7957
- /* @__PURE__ */ (0, import_jsx_runtime64.jsx)("span", { className: "fd-body-sm fd-muted", children: "Arrow keys step $100, shift+arrow $1,000. Escape reverts." })
8203
+ /* @__PURE__ */ (0, import_jsx_runtime67.jsxs)("div", { className: "fd-row", style: { gap: 12, flexWrap: "wrap" }, children: [
8204
+ /* @__PURE__ */ (0, import_jsx_runtime67.jsxs)("span", { className: "fd-stack", style: { gap: 2, flex: 1, minWidth: 150 }, children: [
8205
+ /* @__PURE__ */ (0, import_jsx_runtime67.jsx)("span", { className: "fd-num", style: { fontSize: 19, fontWeight: 700 }, children: "$" + draft.toLocaleString() }),
8206
+ /* @__PURE__ */ (0, import_jsx_runtime67.jsx)("span", { className: "fd-body-sm fd-muted", children: "Arrow keys step $100, shift+arrow $1,000. Escape reverts." })
7958
8207
  ] }),
7959
- /* @__PURE__ */ (0, import_jsx_runtime64.jsx)("button", { type: "button", className: "fd-btn fd-btn-ghost", disabled: !dirty, onClick: revert, children: "Cancel" }),
7960
- /* @__PURE__ */ (0, import_jsx_runtime64.jsx)(
8208
+ /* @__PURE__ */ (0, import_jsx_runtime67.jsx)("button", { type: "button", className: "fd-btn fd-btn-ghost", disabled: !dirty, onClick: revert, children: "Cancel" }),
8209
+ /* @__PURE__ */ (0, import_jsx_runtime67.jsx)(
7961
8210
  "button",
7962
8211
  {
7963
8212
  type: "button",
@@ -7976,7 +8225,7 @@ function BudgetReallocator({
7976
8225
  }
7977
8226
 
7978
8227
  // src/components/planner/SurroundSound.tsx
7979
- var import_jsx_runtime65 = require("react/jsx-runtime");
8228
+ var import_jsx_runtime68 = require("react/jsx-runtime");
7980
8229
  var CATEGORIES = [
7981
8230
  { key: "ooh", label: "OOH", icon: "flag-banner", color: "var(--ch-ooh)" },
7982
8231
  { key: "transit", label: "Transit", icon: "bus", color: "var(--ch-transit)" },
@@ -7988,26 +8237,26 @@ var CATEGORIES = [
7988
8237
  function SurroundSound({ present = [], bonusPct = 0, bonusMax = 40, missedCost, className = "" }) {
7989
8238
  const earned = Math.max(0, Math.min(1, bonusPct / bonusMax));
7990
8239
  const single = present.length <= 2;
7991
- return /* @__PURE__ */ (0, import_jsx_runtime65.jsxs)("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 14 }, children: [
7992
- /* @__PURE__ */ (0, import_jsx_runtime65.jsx)("div", { className: "fd-row", style: { gap: 8, flexWrap: "wrap" }, children: CATEGORIES.map((c) => {
8240
+ return /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 14 }, children: [
8241
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("div", { className: "fd-row", style: { gap: 8, flexWrap: "wrap" }, children: CATEGORIES.map((c) => {
7993
8242
  const on = present.includes(c.key);
7994
- return /* @__PURE__ */ (0, import_jsx_runtime65.jsxs)(
8243
+ return /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)(
7995
8244
  "span",
7996
8245
  {
7997
8246
  title: c.label + (on ? " \u2014 present" : " \u2014 not bought"),
7998
8247
  style: { display: "flex", flexDirection: "column", alignItems: "center", gap: 5, width: 62, padding: "10px 0", borderRadius: "var(--r-md)", border: "1px solid " + (on ? "var(--csi-2-edge)" : "var(--border)"), background: on ? "var(--csi-2-fill)" : "var(--surface-2)", color: on ? "var(--csi-2-text)" : "var(--text-disabled)" },
7999
8248
  children: [
8000
- /* @__PURE__ */ (0, import_jsx_runtime65.jsx)("i", { className: "ph ph-" + c.icon, style: { fontSize: 19, color: on ? c.color : "var(--text-muted)" }, "aria-hidden": "true" }),
8001
- /* @__PURE__ */ (0, import_jsx_runtime65.jsx)("span", { style: { fontSize: 10.5, fontWeight: 700 }, children: c.label })
8249
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("i", { className: "ph ph-" + c.icon, style: { fontSize: 19, color: on ? c.color : "var(--text-muted)" }, "aria-hidden": "true" }),
8250
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("span", { style: { fontSize: 10.5, fontWeight: 700 }, children: c.label })
8002
8251
  ]
8003
8252
  },
8004
8253
  c.key
8005
8254
  );
8006
8255
  }) }),
8007
- /* @__PURE__ */ (0, import_jsx_runtime65.jsxs)("div", { className: "fd-stack", style: { gap: 8 }, children: [
8008
- /* @__PURE__ */ (0, import_jsx_runtime65.jsxs)("div", { className: "fd-row", style: { justifyContent: "space-between", gap: 12 }, children: [
8009
- /* @__PURE__ */ (0, import_jsx_runtime65.jsx)("span", { className: "fd-label-lg", children: "Surround-sound bonus earned" }),
8010
- /* @__PURE__ */ (0, import_jsx_runtime65.jsxs)("span", { className: "fd-num", style: { color: single ? "var(--warn-text)" : "var(--csi-3-mark)", fontWeight: 700 }, children: [
8256
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)("div", { className: "fd-stack", style: { gap: 8 }, children: [
8257
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)("div", { className: "fd-row", style: { justifyContent: "space-between", gap: 12 }, children: [
8258
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("span", { className: "fd-label-lg", children: "Surround-sound bonus earned" }),
8259
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)("span", { className: "fd-num", style: { color: single ? "var(--warn-text)" : "var(--csi-3-mark)", fontWeight: 700 }, children: [
8011
8260
  "+",
8012
8261
  bonusPct,
8013
8262
  "% of +",
@@ -8015,8 +8264,8 @@ function SurroundSound({ present = [], bonusPct = 0, bonusMax = 40, missedCost,
8015
8264
  "%"
8016
8265
  ] })
8017
8266
  ] }),
8018
- /* @__PURE__ */ (0, import_jsx_runtime65.jsx)("div", { style: { height: 8, borderRadius: "var(--r-xs)", background: "var(--surface-3)", overflow: "hidden" }, children: /* @__PURE__ */ (0, import_jsx_runtime65.jsx)("div", { style: { height: "100%", width: earned * 100 + "%", background: "var(--csi-3-mark)", borderRadius: "inherit", transition: "width var(--dur-slow) var(--ease)" } }) }),
8019
- /* @__PURE__ */ (0, import_jsx_runtime65.jsxs)("span", { className: "fd-body-sm fd-secondary", style: { textWrap: "pretty" }, children: [
8267
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("div", { style: { height: 8, borderRadius: "var(--r-xs)", background: "var(--surface-3)", overflow: "hidden" }, children: /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("div", { style: { height: "100%", width: earned * 100 + "%", background: "var(--csi-3-mark)", borderRadius: "inherit", transition: "width var(--dur-slow) var(--ease)" } }) }),
8268
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)("span", { className: "fd-body-sm fd-secondary", style: { textWrap: "pretty" }, children: [
8020
8269
  present.length,
8021
8270
  " of 6 channel categories present.",
8022
8271
  " ",
@@ -8028,10 +8277,10 @@ function SurroundSound({ present = [], bonusPct = 0, bonusMax = 40, missedCost,
8028
8277
  }
8029
8278
 
8030
8279
  // src/components/chat/AgentChatPanel.tsx
8031
- var React39 = __toESM(require("react"), 1);
8280
+ var React41 = __toESM(require("react"), 1);
8032
8281
 
8033
8282
  // src/components/chat/chatEngine.ts
8034
- var React34 = __toESM(require("react"), 1);
8283
+ var React36 = __toESM(require("react"), 1);
8035
8284
  var CHAT_UNAVAILABLE = "chat_unavailable";
8036
8285
  var JOB_PENDING = ["queued", "running"];
8037
8286
  var JOB_SUCCESS = ["completed", "recovered"];
@@ -8085,22 +8334,22 @@ function useChatEngine(opts) {
8085
8334
  onClear,
8086
8335
  onFeedback
8087
8336
  } = opts || {};
8088
- const [status, setStatus] = React34.useState("idle");
8089
- const [threadId, setThreadId] = React34.useState(null);
8090
- const [messages, setMessages] = React34.useState([]);
8091
- const [queue, setQueue] = React34.useState([]);
8092
- const [fatal, setFatal] = React34.useState(null);
8093
- const [busy, setBusy] = React34.useState(false);
8094
- const [turnStartedAt, setTurnStartedAt] = React34.useState(null);
8095
- const listRef = React34.useRef([]);
8096
- const queueRef = React34.useRef([]);
8097
- const busyRef = React34.useRef(false);
8098
- const stoppedRef = React34.useRef(false);
8099
- const abortRef = React34.useRef(null);
8100
- const serverCount = React34.useRef(0);
8101
- const threadRef = React34.useRef(null);
8102
- const mounted = React34.useRef(true);
8103
- React34.useEffect(() => {
8337
+ const [status, setStatus] = React36.useState("idle");
8338
+ const [threadId, setThreadId] = React36.useState(null);
8339
+ const [messages, setMessages] = React36.useState([]);
8340
+ const [queue, setQueue] = React36.useState([]);
8341
+ const [fatal, setFatal] = React36.useState(null);
8342
+ const [busy, setBusy] = React36.useState(false);
8343
+ const [turnStartedAt, setTurnStartedAt] = React36.useState(null);
8344
+ const listRef = React36.useRef([]);
8345
+ const queueRef = React36.useRef([]);
8346
+ const busyRef = React36.useRef(false);
8347
+ const stoppedRef = React36.useRef(false);
8348
+ const abortRef = React36.useRef(null);
8349
+ const serverCount = React36.useRef(0);
8350
+ const threadRef = React36.useRef(null);
8351
+ const mounted = React36.useRef(true);
8352
+ React36.useEffect(() => {
8104
8353
  mounted.current = true;
8105
8354
  return () => {
8106
8355
  mounted.current = false;
@@ -8122,14 +8371,14 @@ function useChatEngine(opts) {
8122
8371
  }
8123
8372
  return false;
8124
8373
  };
8125
- const loadThread = React34.useCallback(async (id) => {
8374
+ const loadThread = React36.useCallback(async (id) => {
8126
8375
  const data = await apiAdapter.getThread(id);
8127
8376
  const list = [...data && data.messages || []];
8128
8377
  serverCount.current = list.length;
8129
8378
  commit(list);
8130
8379
  return list;
8131
8380
  }, [apiAdapter]);
8132
- React34.useEffect(() => {
8381
+ React36.useEffect(() => {
8133
8382
  if (!apiAdapter) {
8134
8383
  setStatus("idle");
8135
8384
  setFatal(null);
@@ -8342,7 +8591,7 @@ function useChatEngine(opts) {
8342
8591
  await dispatchTurn(turn);
8343
8592
  }
8344
8593
  }
8345
- const send = React34.useCallback((text, attachments) => {
8594
+ const send = React36.useCallback((text, attachments) => {
8346
8595
  const body = (text || "").trim();
8347
8596
  if (!body && !(attachments && attachments.length)) return;
8348
8597
  if (status === "disconnected") return;
@@ -8352,7 +8601,7 @@ function useChatEngine(opts) {
8352
8601
  stoppedRef.current = false;
8353
8602
  drain();
8354
8603
  }, [status]);
8355
- const stop = React34.useCallback(() => {
8604
+ const stop = React36.useCallback(() => {
8356
8605
  stoppedRef.current = true;
8357
8606
  const ac = abortRef.current;
8358
8607
  if (ac) {
@@ -8371,11 +8620,11 @@ function useChatEngine(opts) {
8371
8620
  store.del(STORAGE_PREFIX + threadRef.current);
8372
8621
  }
8373
8622
  }, [apiAdapter]);
8374
- const removeQueued = React34.useCallback((id) => {
8623
+ const removeQueued = React36.useCallback((id) => {
8375
8624
  queueRef.current = queueRef.current.filter((t) => t.id !== id);
8376
8625
  setQueue(queueRef.current.slice());
8377
8626
  }, []);
8378
- const retry = React34.useCallback(() => {
8627
+ const retry = React36.useCallback(() => {
8379
8628
  const list = listRef.current;
8380
8629
  let at = -1;
8381
8630
  for (let i = list.length - 1; i >= 0; i--) if (list[i].role === "user") {
@@ -8391,19 +8640,19 @@ function useChatEngine(opts) {
8391
8640
  setQueue(queueRef.current.slice());
8392
8641
  drain();
8393
8642
  }, []);
8394
- const clear = React34.useCallback(() => {
8643
+ const clear = React36.useCallback(() => {
8395
8644
  commit([]);
8396
8645
  serverCount.current = 0;
8397
8646
  queueRef.current = [];
8398
8647
  setQueue([]);
8399
8648
  onClear && onClear();
8400
8649
  }, [onClear]);
8401
- const setFeedback = React34.useCallback((id, value) => {
8650
+ const setFeedback = React36.useCallback((id, value) => {
8402
8651
  patch(id, (m) => ({ feedback: m.feedback === value ? null : value }));
8403
8652
  const msg = listRef.current.find((m) => m.id === id);
8404
8653
  onFeedback && onFeedback({ message: msg, feedback: msg ? msg.feedback : value });
8405
8654
  }, [onFeedback]);
8406
- const reload = React34.useCallback(async () => {
8655
+ const reload = React36.useCallback(async () => {
8407
8656
  if (!threadRef.current) return;
8408
8657
  setStatus("loading");
8409
8658
  try {
@@ -8441,11 +8690,11 @@ var ChatKit = {
8441
8690
  };
8442
8691
 
8443
8692
  // src/components/chat/ChatTranscript.tsx
8444
- var React36 = __toESM(require("react"), 1);
8693
+ var React38 = __toESM(require("react"), 1);
8445
8694
 
8446
8695
  // src/components/chat/ChatTurn.tsx
8447
- var React35 = __toESM(require("react"), 1);
8448
- var import_jsx_runtime66 = require("react/jsx-runtime");
8696
+ var React37 = __toESM(require("react"), 1);
8697
+ var import_jsx_runtime69 = require("react/jsx-runtime");
8449
8698
  function JsonView({ value }) {
8450
8699
  let text;
8451
8700
  try {
@@ -8453,67 +8702,67 @@ function JsonView({ value }) {
8453
8702
  } catch (e) {
8454
8703
  text = String(value);
8455
8704
  }
8456
- return /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(CodeBlock, { code: text, language: "json", collapseAfter: 18 });
8705
+ return /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(CodeBlock, { code: text, language: "json", collapseAfter: 18 });
8457
8706
  }
8458
8707
  function PacketCard({ packet, schema, render, onApply, applied }) {
8459
8708
  if (!packet) return null;
8460
8709
  const s = schema || {};
8461
8710
  const invalid = packet.valid === false;
8462
8711
  const title = s.heading || packet.type;
8463
- return /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("section", { className: "fdc-packet" + (invalid ? " is-invalid" : ""), "aria-label": title, children: [
8464
- /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("header", { className: "fdc-packet-head", children: [
8465
- /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("i", { className: "ph ph-" + (s.icon || "package"), "aria-hidden": "true" }),
8466
- /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("span", { className: "fdc-packet-title", children: title }),
8467
- packet.repaired ? /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("span", { className: "fdc-packet-badge", children: "Repaired" }) : null,
8468
- invalid ? /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("span", { className: "fdc-packet-badge is-danger", children: "Invalid" }) : null
8712
+ return /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("section", { className: "fdc-packet" + (invalid ? " is-invalid" : ""), "aria-label": title, children: [
8713
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("header", { className: "fdc-packet-head", children: [
8714
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("i", { className: "ph ph-" + (s.icon || "package"), "aria-hidden": "true" }),
8715
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("span", { className: "fdc-packet-title", children: title }),
8716
+ packet.repaired ? /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("span", { className: "fdc-packet-badge", children: "Repaired" }) : null,
8717
+ invalid ? /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("span", { className: "fdc-packet-badge is-danger", children: "Invalid" }) : null
8469
8718
  ] }),
8470
- invalid ? /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("div", { className: "fdc-packet-alert", role: "alert", children: [
8471
- /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
8472
- /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("span", { children: packet.error || "This result failed validation and can\u2019t be applied." })
8473
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("div", { className: "fdc-packet-body", children: render ? render(packet) : /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(JsonView, { value: packet.payload }) }),
8474
- !invalid && onApply ? /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("footer", { className: "fdc-packet-foot", children: [
8475
- packet.repaired ? /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("span", { className: "fdc-packet-note", children: "Corrected by the backend after a first attempt." }) : /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("span", {}),
8476
- /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("button", { type: "button", className: "fd-btn fd-btn-primary fd-btn-sm", disabled: applied, onClick: () => onApply(packet), children: [
8477
- /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("i", { className: "ph ph-" + (applied ? "check" : "arrow-square-in"), "aria-hidden": "true" }),
8719
+ invalid ? /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("div", { className: "fdc-packet-alert", role: "alert", children: [
8720
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
8721
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("span", { children: packet.error || "This result failed validation and can\u2019t be applied." })
8722
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("div", { className: "fdc-packet-body", children: render ? render(packet) : /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(JsonView, { value: packet.payload }) }),
8723
+ !invalid && onApply ? /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("footer", { className: "fdc-packet-foot", children: [
8724
+ packet.repaired ? /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("span", { className: "fdc-packet-note", children: "Corrected by the backend after a first attempt." }) : /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("span", {}),
8725
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("button", { type: "button", className: "fd-btn fd-btn-primary fd-btn-sm", disabled: applied, onClick: () => onApply(packet), children: [
8726
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("i", { className: "ph ph-" + (applied ? "check" : "arrow-square-in"), "aria-hidden": "true" }),
8478
8727
  applied ? "Applied" : s.applyLabel || "Apply"
8479
8728
  ] })
8480
8729
  ] }) : null
8481
8730
  ] });
8482
8731
  }
8483
8732
  function ThinkingBlock({ text, durationMs, streaming, defaultOpen = false }) {
8484
- const [open, setOpen] = React35.useState(defaultOpen);
8733
+ const [open, setOpen] = React37.useState(defaultOpen);
8485
8734
  if (!text) return null;
8486
- return /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("div", { className: "fdc-think" + (open ? " is-open" : ""), children: [
8487
- /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("button", { type: "button", className: "fdc-think-head", onClick: () => setOpen((v) => !v), "aria-expanded": open, children: [
8488
- /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("i", { className: "ph ph-brain", "aria-hidden": "true" }),
8489
- /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("span", { children: streaming ? "Thinking" : durationMs ? "Thought for " + formatDuration(durationMs) : "Thought process" }),
8490
- streaming ? /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("span", { className: "fdc-dots", "aria-hidden": "true", children: [
8491
- /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("span", {}),
8492
- /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("span", {}),
8493
- /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("span", {})
8735
+ return /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("div", { className: "fdc-think" + (open ? " is-open" : ""), children: [
8736
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("button", { type: "button", className: "fdc-think-head", onClick: () => setOpen((v) => !v), "aria-expanded": open, children: [
8737
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("i", { className: "ph ph-brain", "aria-hidden": "true" }),
8738
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("span", { children: streaming ? "Thinking" : durationMs ? "Thought for " + formatDuration(durationMs) : "Thought process" }),
8739
+ streaming ? /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("span", { className: "fdc-dots", "aria-hidden": "true", children: [
8740
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("span", {}),
8741
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("span", {}),
8742
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("span", {})
8494
8743
  ] }) : null,
8495
- /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("i", { className: "ph ph-caret-" + (open ? "up" : "down"), "aria-hidden": "true" })
8744
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("i", { className: "ph ph-caret-" + (open ? "up" : "down"), "aria-hidden": "true" })
8496
8745
  ] }),
8497
- open ? /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("div", { className: "fdc-think-body", children: text }) : null
8746
+ open ? /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("div", { className: "fdc-think-body", children: text }) : null
8498
8747
  ] });
8499
8748
  }
8500
8749
  function Citations({ items = [], onOpen }) {
8501
- const [open, setOpen] = React35.useState(false);
8750
+ const [open, setOpen] = React37.useState(false);
8502
8751
  if (!items.length) return null;
8503
- return /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("div", { className: "fdc-cites", children: [
8504
- /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("button", { type: "button", className: "fdc-cites-head", onClick: () => setOpen((v) => !v), "aria-expanded": open, children: [
8505
- /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("i", { className: "ph ph-quotes", "aria-hidden": "true" }),
8506
- /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("span", { children: [
8752
+ return /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("div", { className: "fdc-cites", children: [
8753
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("button", { type: "button", className: "fdc-cites-head", onClick: () => setOpen((v) => !v), "aria-expanded": open, children: [
8754
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("i", { className: "ph ph-quotes", "aria-hidden": "true" }),
8755
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("span", { children: [
8507
8756
  items.length,
8508
8757
  " source",
8509
8758
  items.length === 1 ? "" : "s"
8510
8759
  ] }),
8511
- /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("i", { className: "ph ph-caret-" + (open ? "up" : "down"), "aria-hidden": "true" })
8760
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("i", { className: "ph ph-caret-" + (open ? "up" : "down"), "aria-hidden": "true" })
8512
8761
  ] }),
8513
- open ? /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("ol", { className: "fdc-cites-list", children: items.map((c, i) => /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("li", { children: [
8514
- /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("span", { className: "fdc-cite-n fd-tabular", children: c.marker || i + 1 }),
8515
- c.url ? /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("a", { href: c.url, target: "_blank", rel: "noopener noreferrer", onClick: onOpen ? (e) => onOpen(c, e) : void 0, children: c.title || c.url }) : /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("span", { children: c.title || "Source" }),
8516
- c.detail ? /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("span", { className: "fdc-cite-detail", children: c.detail }) : null
8762
+ open ? /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("ol", { className: "fdc-cites-list", children: items.map((c, i) => /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("li", { children: [
8763
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("span", { className: "fdc-cite-n fd-tabular", children: c.marker || i + 1 }),
8764
+ c.url ? /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("a", { href: c.url, target: "_blank", rel: "noopener noreferrer", onClick: onOpen ? (e) => onOpen(c, e) : void 0, children: c.title || c.url }) : /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("span", { children: c.title || "Source" }),
8765
+ c.detail ? /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("span", { className: "fdc-cite-detail", children: c.detail }) : null
8517
8766
  ] }, c.id || i)) }) : null
8518
8767
  ] });
8519
8768
  }
@@ -8524,29 +8773,29 @@ function clampText(text, max) {
8524
8773
  return (at > max * 0.6 ? cut.slice(0, at) : cut).trimEnd() + "\u2026";
8525
8774
  }
8526
8775
  function MessageBody({ message: m, ctx }) {
8527
- const [expanded, setExpanded] = React35.useState(false);
8776
+ const [expanded, setExpanded] = React37.useState(false);
8528
8777
  const isUser = m.role === "user";
8529
8778
  const raw = m.text || "";
8530
8779
  const clamped = !expanded && !m.streaming ? clampText(raw, ctx.maxVisibleChars) : null;
8531
8780
  const body = clamped != null ? clamped : raw;
8532
8781
  const showMd = ctx.markdown && !isUser;
8533
- return /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("div", { className: "fdc-body", children: [
8534
- m.thinking && ctx.showThinking ? /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(ThinkingBlock, { text: m.thinking, durationMs: m.thinkingMs, streaming: m.streaming && !m.text }) : null,
8535
- m.steps && m.steps.length && ctx.showSteps ? /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(StepList, { steps: m.steps, defaultOpen: m.steps.some((s) => s.status === "running"), dense: true }) : null,
8536
- body ? /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("div", { className: "fdc-text" + (isUser ? " is-user" : ""), children: [
8537
- showMd ? /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(Markdown, { source: body, headingOffset: 2, codeProps: { collapseAfter: 22 }, renderCitation: ctx.renderCitation }) : /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("div", { className: "fdc-plain", children: body }),
8538
- m.streaming ? /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("span", { className: "fdc-caret", "aria-hidden": "true" }) : null
8782
+ return /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("div", { className: "fdc-body", children: [
8783
+ m.thinking && ctx.showThinking ? /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(ThinkingBlock, { text: m.thinking, durationMs: m.thinkingMs, streaming: m.streaming && !m.text }) : null,
8784
+ m.steps && m.steps.length && ctx.showSteps ? /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(StepList, { steps: m.steps, defaultOpen: m.steps.some((s) => s.status === "running"), dense: true }) : null,
8785
+ body ? /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("div", { className: "fdc-text" + (isUser ? " is-user" : ""), children: [
8786
+ showMd ? /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(Markdown, { source: body, headingOffset: 2, codeProps: { collapseAfter: 22 }, renderCitation: ctx.renderCitation }) : /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("div", { className: "fdc-plain", children: body }),
8787
+ m.streaming ? /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("span", { className: "fdc-caret", "aria-hidden": "true" }) : null
8539
8788
  ] }) : null,
8540
- clamped != null ? /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("button", { type: "button", className: "fdc-more", onClick: () => setExpanded(true), children: [
8541
- /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("i", { className: "ph ph-caret-down", "aria-hidden": "true" }),
8789
+ clamped != null ? /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("button", { type: "button", className: "fdc-more", onClick: () => setExpanded(true), children: [
8790
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("i", { className: "ph ph-caret-down", "aria-hidden": "true" }),
8542
8791
  "Show more",
8543
- /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("span", { className: "fdc-more-len fd-tabular", children: raw.length < 2e3 ? raw.length.toLocaleString() + " characters" : Math.round(raw.length / 100) / 10 + "k characters" })
8544
- ] }) : expanded && ctx.maxVisibleChars && raw.length > ctx.maxVisibleChars ? /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("button", { type: "button", className: "fdc-more", onClick: () => setExpanded(false), children: [
8545
- /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("i", { className: "ph ph-caret-up", "aria-hidden": "true" }),
8792
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("span", { className: "fdc-more-len fd-tabular", children: raw.length < 2e3 ? raw.length.toLocaleString() + " characters" : Math.round(raw.length / 100) / 10 + "k characters" })
8793
+ ] }) : expanded && ctx.maxVisibleChars && raw.length > ctx.maxVisibleChars ? /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("button", { type: "button", className: "fdc-more", onClick: () => setExpanded(false), children: [
8794
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("i", { className: "ph ph-caret-up", "aria-hidden": "true" }),
8546
8795
  "Show less"
8547
8796
  ] }) : null,
8548
- m.attachments && m.attachments.length ? /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(FileGrid, { files: m.attachments, onOpen: ctx.onOpenAttachment, tiles: true, maxHeight: ctx.attachmentHeight || 220, compact: ctx.narrow }) : null,
8549
- m.packet ? /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(
8797
+ m.attachments && m.attachments.length ? /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(FileGrid, { files: m.attachments, onOpen: ctx.onOpenAttachment, tiles: true, maxHeight: ctx.attachmentHeight || 220, compact: ctx.narrow }) : null,
8798
+ m.packet ? /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(
8550
8799
  PacketCard,
8551
8800
  {
8552
8801
  packet: m.packet,
@@ -8556,44 +8805,44 @@ function MessageBody({ message: m, ctx }) {
8556
8805
  applied: ctx.appliedPackets && ctx.appliedPackets[m.id]
8557
8806
  }
8558
8807
  ) : null,
8559
- m.citations && m.citations.length ? /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(Citations, { items: m.citations, onOpen: ctx.onOpenCitation }) : null,
8560
- m.working ? /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("div", { className: "fdc-working", role: "status", children: [
8561
- /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("span", { className: "fdc-dots", "aria-hidden": "true", children: [
8562
- /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("span", {}),
8563
- /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("span", {}),
8564
- /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("span", {})
8808
+ m.citations && m.citations.length ? /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(Citations, { items: m.citations, onOpen: ctx.onOpenCitation }) : null,
8809
+ m.working ? /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("div", { className: "fdc-working", role: "status", children: [
8810
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("span", { className: "fdc-dots", "aria-hidden": "true", children: [
8811
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("span", {}),
8812
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("span", {}),
8813
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("span", {})
8565
8814
  ] }),
8566
- /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("span", { className: "fdc-working-label", children: [
8815
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("span", { className: "fdc-working-label", children: [
8567
8816
  m.resumed ? "Resuming" : "Working",
8568
- m.job && m.job.status ? /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("span", { className: "fdc-working-job", children: [
8817
+ m.job && m.job.status ? /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("span", { className: "fdc-working-job", children: [
8569
8818
  " \xB7 ",
8570
8819
  m.job.status
8571
8820
  ] }) : null,
8572
- m.job && m.job.detail ? /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("span", { className: "fdc-working-job", children: [
8821
+ m.job && m.job.detail ? /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("span", { className: "fdc-working-job", children: [
8573
8822
  " \xB7 ",
8574
8823
  m.job.detail
8575
8824
  ] }) : null
8576
8825
  ] }),
8577
- m.jobId ? /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("span", { className: "fdc-working-id fd-mono", children: String(m.jobId).slice(0, 12) }) : null
8826
+ m.jobId ? /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("span", { className: "fdc-working-id fd-mono", children: String(m.jobId).slice(0, 12) }) : null
8578
8827
  ] }) : null,
8579
- m.stopped ? /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("div", { className: "fdc-stopped", children: [
8580
- /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("i", { className: "ph ph-stop-circle", "aria-hidden": "true" }),
8828
+ m.stopped ? /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("div", { className: "fdc-stopped", children: [
8829
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("i", { className: "ph ph-stop-circle", "aria-hidden": "true" }),
8581
8830
  "Stopped"
8582
8831
  ] }) : null,
8583
- m.error ? /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("div", { className: "fdc-error", role: "alert", children: [
8584
- /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
8585
- /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("span", { className: "fdc-error-text", children: ctx.errorCopy ? ctx.errorCopy(m.error) : m.error }),
8586
- m.retryable && ctx.onRetry ? /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("button", { type: "button", className: "fdc-error-retry", onClick: ctx.onRetry, children: [
8587
- /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("i", { className: "ph ph-arrow-clockwise", "aria-hidden": "true" }),
8832
+ m.error ? /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("div", { className: "fdc-error", role: "alert", children: [
8833
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
8834
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("span", { className: "fdc-error-text", children: ctx.errorCopy ? ctx.errorCopy(m.error) : m.error }),
8835
+ m.retryable && ctx.onRetry ? /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("button", { type: "button", className: "fdc-error-retry", onClick: ctx.onRetry, children: [
8836
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("i", { className: "ph ph-arrow-clockwise", "aria-hidden": "true" }),
8588
8837
  "Retry"
8589
8838
  ] }) : null
8590
8839
  ] }) : null
8591
8840
  ] });
8592
8841
  }
8593
8842
  function useCopyRun() {
8594
- const [done, setDone] = React35.useState(false);
8595
- const t = React35.useRef(null);
8596
- React35.useEffect(() => () => {
8843
+ const [done, setDone] = React37.useState(false);
8844
+ const t = React37.useRef(null);
8845
+ React37.useEffect(() => () => {
8597
8846
  if (t.current) clearTimeout(t.current);
8598
8847
  }, []);
8599
8848
  return [done, (text) => {
@@ -8613,16 +8862,16 @@ function RunActions({ group, ctx }) {
8613
8862
  const isAssistant = group.role === "assistant";
8614
8863
  const fb = last.feedback;
8615
8864
  if (!ctx.messageActions) return null;
8616
- return /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("div", { className: "fdc-actions", role: "group", "aria-label": "Message actions", children: [
8617
- /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("button", { type: "button", className: "fdc-act" + (copied ? " is-done" : ""), onClick: () => copy(markdownToText(text)), "aria-label": "Copy message", children: [
8618
- /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("i", { className: "ph ph-" + (copied ? "check" : "copy"), "aria-hidden": "true" }),
8619
- /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("span", { className: "fdc-act-label", children: copied ? "Copied" : "Copy" })
8865
+ return /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("div", { className: "fdc-actions", role: "group", "aria-label": "Message actions", children: [
8866
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("button", { type: "button", className: "fdc-act" + (copied ? " is-done" : ""), onClick: () => copy(markdownToText(text)), "aria-label": "Copy message", children: [
8867
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("i", { className: "ph ph-" + (copied ? "check" : "copy"), "aria-hidden": "true" }),
8868
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("span", { className: "fdc-act-label", children: copied ? "Copied" : "Copy" })
8620
8869
  ] }),
8621
- isAssistant && ctx.onRetry ? /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("button", { type: "button", className: "fdc-act", onClick: ctx.onRetry, "aria-label": "Retry this turn", children: /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("i", { className: "ph ph-arrow-clockwise", "aria-hidden": "true" }) }) : null,
8622
- group.role === "user" && ctx.onEdit ? /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("button", { type: "button", className: "fdc-act", onClick: () => ctx.onEdit(last), "aria-label": "Edit and resend", children: /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("i", { className: "ph ph-pencil-simple", "aria-hidden": "true" }) }) : null,
8623
- isAssistant && ctx.onFeedback ? /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)(React35.Fragment, { children: [
8624
- /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("button", { type: "button", className: "fdc-act" + (fb === "up" ? " is-on" : ""), onClick: () => ctx.onFeedback(last.id, "up"), "aria-pressed": fb === "up", "aria-label": "Good response", children: /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("i", { className: "ph ph-thumbs-up", "aria-hidden": "true" }) }),
8625
- /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("button", { type: "button", className: "fdc-act" + (fb === "down" ? " is-on" : ""), onClick: () => ctx.onFeedback(last.id, "down"), "aria-pressed": fb === "down", "aria-label": "Bad response", children: /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("i", { className: "ph ph-thumbs-down", "aria-hidden": "true" }) })
8870
+ isAssistant && ctx.onRetry ? /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("button", { type: "button", className: "fdc-act", onClick: ctx.onRetry, "aria-label": "Retry this turn", children: /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("i", { className: "ph ph-arrow-clockwise", "aria-hidden": "true" }) }) : null,
8871
+ group.role === "user" && ctx.onEdit ? /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("button", { type: "button", className: "fdc-act", onClick: () => ctx.onEdit(last), "aria-label": "Edit and resend", children: /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("i", { className: "ph ph-pencil-simple", "aria-hidden": "true" }) }) : null,
8872
+ isAssistant && ctx.onFeedback ? /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)(React37.Fragment, { children: [
8873
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("button", { type: "button", className: "fdc-act" + (fb === "up" ? " is-on" : ""), onClick: () => ctx.onFeedback(last.id, "up"), "aria-pressed": fb === "up", "aria-label": "Good response", children: /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("i", { className: "ph ph-thumbs-up", "aria-hidden": "true" }) }),
8874
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("button", { type: "button", className: "fdc-act" + (fb === "down" ? " is-on" : ""), onClick: () => ctx.onFeedback(last.id, "down"), "aria-pressed": fb === "down", "aria-label": "Bad response", children: /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("i", { className: "ph ph-thumbs-down", "aria-hidden": "true" }) })
8626
8875
  ] }) : null,
8627
8876
  ctx.extraActions ? ctx.extraActions(group) : null
8628
8877
  ] });
@@ -8632,22 +8881,22 @@ function ChatTurn({ group, ctx }) {
8632
8881
  const name = isUser ? ctx.userName : group.author || ctx.assistantName;
8633
8882
  const avatar = isUser ? ctx.userAvatar : ctx.assistantAvatar;
8634
8883
  const stamp = group.messages[0].timestamp;
8635
- return /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("article", { className: "fdc-turn is-" + group.role, "aria-label": String(name) + (stamp ? " at " + formatClock(stamp) : ""), children: [
8636
- /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("div", { className: "fdc-turn-head", children: [
8637
- ctx.showAvatars ? /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("span", { className: "fdc-avatar is-" + group.role, "aria-hidden": "true", children: avatar ? /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("img", { src: avatar, alt: "" }) : isUser ? /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("span", { className: "fdc-avatar-txt", children: (name || "You").slice(0, 1).toUpperCase() }) : /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("i", { className: "ph ph-" + (ctx.assistantIcon || "sparkle") }) }) : null,
8638
- /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("span", { className: "fdc-who", children: name }),
8639
- stamp ? /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(RelativeTime, { className: "fdc-when", value: stamp }) : null,
8640
- group.messages.some((m) => m.model) ? /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("span", { className: "fdc-turn-model", children: group.messages.find((m) => m.model).model }) : null
8884
+ return /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("article", { className: "fdc-turn is-" + group.role, "aria-label": String(name) + (stamp ? " at " + formatClock(stamp) : ""), children: [
8885
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("div", { className: "fdc-turn-head", children: [
8886
+ ctx.showAvatars ? /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("span", { className: "fdc-avatar is-" + group.role, "aria-hidden": "true", children: avatar ? /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("img", { src: avatar, alt: "" }) : isUser ? /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("span", { className: "fdc-avatar-txt", children: (name || "You").slice(0, 1).toUpperCase() }) : /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("i", { className: "ph ph-" + (ctx.assistantIcon || "sparkle") }) }) : null,
8887
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("span", { className: "fdc-who", children: name }),
8888
+ stamp ? /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(RelativeTime, { className: "fdc-when", value: stamp }) : null,
8889
+ group.messages.some((m) => m.model) ? /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("span", { className: "fdc-turn-model", children: group.messages.find((m) => m.model).model }) : null
8641
8890
  ] }),
8642
- /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("div", { className: "fdc-turn-body", children: [
8643
- group.messages.map((m) => /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("div", { className: "fdc-msg" + (m.pending ? " is-pending" : ""), children: /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(MessageBody, { message: m, ctx }) }, m.id)),
8644
- /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(RunActions, { group, ctx })
8891
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("div", { className: "fdc-turn-body", children: [
8892
+ group.messages.map((m) => /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("div", { className: "fdc-msg" + (m.pending ? " is-pending" : ""), children: /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(MessageBody, { message: m, ctx }) }, m.id)),
8893
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(RunActions, { group, ctx })
8645
8894
  ] })
8646
8895
  ] });
8647
8896
  }
8648
8897
 
8649
8898
  // src/components/chat/ChatTranscript.tsx
8650
- var import_jsx_runtime67 = require("react/jsx-runtime");
8899
+ var import_jsx_runtime70 = require("react/jsx-runtime");
8651
8900
  var GROUP_WINDOW = 6e4;
8652
8901
  var STICK_PX = 100;
8653
8902
  function groupMessages(list) {
@@ -8680,25 +8929,25 @@ function dayLabel(key) {
8680
8929
  }
8681
8930
  function Suggestions({ items = [], onPick }) {
8682
8931
  if (!items.length) return null;
8683
- return /* @__PURE__ */ (0, import_jsx_runtime67.jsx)("div", { className: "fdc-suggest", children: items.map((s, i) => {
8932
+ return /* @__PURE__ */ (0, import_jsx_runtime70.jsx)("div", { className: "fdc-suggest", children: items.map((s, i) => {
8684
8933
  const it = typeof s === "string" ? { label: s, text: s } : s;
8685
- return /* @__PURE__ */ (0, import_jsx_runtime67.jsxs)("button", { type: "button", className: "fdc-suggest-item", onClick: () => onPick && onPick(it.text || it.label), children: [
8686
- it.icon ? /* @__PURE__ */ (0, import_jsx_runtime67.jsx)("i", { className: "ph ph-" + it.icon, "aria-hidden": "true" }) : null,
8687
- /* @__PURE__ */ (0, import_jsx_runtime67.jsxs)("span", { className: "fdc-suggest-text", children: [
8688
- /* @__PURE__ */ (0, import_jsx_runtime67.jsx)("span", { className: "fdc-suggest-label", children: it.label }),
8689
- it.description ? /* @__PURE__ */ (0, import_jsx_runtime67.jsx)("span", { className: "fdc-suggest-desc", children: it.description }) : null
8934
+ return /* @__PURE__ */ (0, import_jsx_runtime70.jsxs)("button", { type: "button", className: "fdc-suggest-item", onClick: () => onPick && onPick(it.text || it.label), children: [
8935
+ it.icon ? /* @__PURE__ */ (0, import_jsx_runtime70.jsx)("i", { className: "ph ph-" + it.icon, "aria-hidden": "true" }) : null,
8936
+ /* @__PURE__ */ (0, import_jsx_runtime70.jsxs)("span", { className: "fdc-suggest-text", children: [
8937
+ /* @__PURE__ */ (0, import_jsx_runtime70.jsx)("span", { className: "fdc-suggest-label", children: it.label }),
8938
+ it.description ? /* @__PURE__ */ (0, import_jsx_runtime70.jsx)("span", { className: "fdc-suggest-desc", children: it.description }) : null
8690
8939
  ] }),
8691
- /* @__PURE__ */ (0, import_jsx_runtime67.jsx)("i", { className: "ph ph-arrow-up-right fdc-suggest-go", "aria-hidden": "true" })
8940
+ /* @__PURE__ */ (0, import_jsx_runtime70.jsx)("i", { className: "ph ph-arrow-up-right fdc-suggest-go", "aria-hidden": "true" })
8692
8941
  ] }, it.id || i);
8693
8942
  }) });
8694
8943
  }
8695
8944
  function LoadingTurns() {
8696
- return /* @__PURE__ */ (0, import_jsx_runtime67.jsx)("div", { className: "fdc-skel", "aria-hidden": "true", children: [0, 1].map((i) => /* @__PURE__ */ (0, import_jsx_runtime67.jsxs)("div", { className: "fdc-skel-turn", children: [
8697
- /* @__PURE__ */ (0, import_jsx_runtime67.jsx)("div", { className: "fd-skel fd-skel-circle", style: { width: 22, height: 22 } }),
8698
- /* @__PURE__ */ (0, import_jsx_runtime67.jsxs)("div", { className: "fdc-skel-lines", children: [
8699
- /* @__PURE__ */ (0, import_jsx_runtime67.jsx)("div", { className: "fd-skel", style: { width: i ? "62%" : "44%", height: 11 } }),
8700
- /* @__PURE__ */ (0, import_jsx_runtime67.jsx)("div", { className: "fd-skel", style: { width: i ? "94%" : "78%", height: 11 } }),
8701
- /* @__PURE__ */ (0, import_jsx_runtime67.jsx)("div", { className: "fd-skel", style: { width: i ? "71%" : "56%", height: 11 } })
8945
+ return /* @__PURE__ */ (0, import_jsx_runtime70.jsx)("div", { className: "fdc-skel", "aria-hidden": "true", children: [0, 1].map((i) => /* @__PURE__ */ (0, import_jsx_runtime70.jsxs)("div", { className: "fdc-skel-turn", children: [
8946
+ /* @__PURE__ */ (0, import_jsx_runtime70.jsx)("div", { className: "fd-skel fd-skel-circle", style: { width: 22, height: 22 } }),
8947
+ /* @__PURE__ */ (0, import_jsx_runtime70.jsxs)("div", { className: "fdc-skel-lines", children: [
8948
+ /* @__PURE__ */ (0, import_jsx_runtime70.jsx)("div", { className: "fd-skel", style: { width: i ? "62%" : "44%", height: 11 } }),
8949
+ /* @__PURE__ */ (0, import_jsx_runtime70.jsx)("div", { className: "fd-skel", style: { width: i ? "94%" : "78%", height: 11 } }),
8950
+ /* @__PURE__ */ (0, import_jsx_runtime70.jsx)("div", { className: "fd-skel", style: { width: i ? "71%" : "56%", height: 11 } })
8702
8951
  ] })
8703
8952
  ] }, i)) });
8704
8953
  }
@@ -8715,10 +8964,10 @@ function ChatTranscript({
8715
8964
  renderEmpty,
8716
8965
  className = ""
8717
8966
  }) {
8718
- const scroller = React36.useRef(null);
8719
- const stick = React36.useRef(true);
8720
- const [pill, setPill] = React36.useState(0);
8721
- const seen = React36.useRef(0);
8967
+ const scroller = React38.useRef(null);
8968
+ const stick = React38.useRef(true);
8969
+ const [pill, setPill] = React38.useState(0);
8970
+ const seen = React38.useRef(0);
8722
8971
  const toBottom = (smooth) => {
8723
8972
  const el = scroller.current;
8724
8973
  if (!el) return;
@@ -8737,7 +8986,7 @@ function ChatTranscript({
8737
8986
  seen.current = messages.length;
8738
8987
  }
8739
8988
  };
8740
- React36.useLayoutEffect(() => {
8989
+ React38.useLayoutEffect(() => {
8741
8990
  const el = scroller.current;
8742
8991
  if (!el) return;
8743
8992
  if (stick.current) {
@@ -8745,7 +8994,7 @@ function ChatTranscript({
8745
8994
  seen.current = messages.length;
8746
8995
  } else setPill(Math.max(0, messages.length - seen.current));
8747
8996
  }, [messages]);
8748
- React36.useEffect(() => {
8997
+ React38.useEffect(() => {
8749
8998
  const el = scroller.current;
8750
8999
  const inner = el && el.firstChild;
8751
9000
  if (!el || !inner || typeof ResizeObserver === "undefined") return;
@@ -8755,38 +9004,38 @@ function ChatTranscript({
8755
9004
  ro.observe(inner);
8756
9005
  return () => ro.disconnect();
8757
9006
  }, []);
8758
- const groups = React36.useMemo(() => groupMessages(messages), [messages]);
9007
+ const groups = React38.useMemo(() => groupMessages(messages), [messages]);
8759
9008
  const empty = !messages.length && status === "ready";
8760
- return /* @__PURE__ */ (0, import_jsx_runtime67.jsxs)("div", { className: ["fdc-scroll", className].filter(Boolean).join(" "), ref: scroller, onScroll, children: [
8761
- /* @__PURE__ */ (0, import_jsx_runtime67.jsxs)("div", { className: "fdc-log", role: "log", "aria-label": "Conversation", children: [
8762
- status === "loading" || status === "resolving" ? /* @__PURE__ */ (0, import_jsx_runtime67.jsx)(LoadingTurns, {}) : null,
8763
- status === "disconnected" ? /* @__PURE__ */ (0, import_jsx_runtime67.jsxs)("div", { className: "fdc-dead", children: [
8764
- /* @__PURE__ */ (0, import_jsx_runtime67.jsx)("span", { className: "fdc-dead-icon", children: /* @__PURE__ */ (0, import_jsx_runtime67.jsx)("i", { className: "ph ph-plugs", "aria-hidden": "true" }) }),
8765
- /* @__PURE__ */ (0, import_jsx_runtime67.jsx)("h3", { className: "fdc-dead-title", children: ctx.deadTitle || "The assistant isn\u2019t reachable" }),
8766
- /* @__PURE__ */ (0, import_jsx_runtime67.jsx)("p", { className: "fdc-dead-body", children: fatal === "chat_unavailable" ? "The service reported chat_unavailable. Nothing you type will be lost \u2014 reopen the panel once it\u2019s back." : "The thread couldn\u2019t be resolved" + (fatal ? " (" + fatal + ")" : "") + ". The composer stays disabled until it resolves." }),
8767
- ctx.onReconnect ? /* @__PURE__ */ (0, import_jsx_runtime67.jsxs)("button", { type: "button", className: "fd-btn fd-btn-secondary fd-btn-sm", onClick: ctx.onReconnect, children: [
8768
- /* @__PURE__ */ (0, import_jsx_runtime67.jsx)("i", { className: "ph ph-arrow-clockwise", "aria-hidden": "true" }),
9009
+ return /* @__PURE__ */ (0, import_jsx_runtime70.jsxs)("div", { className: ["fdc-scroll", className].filter(Boolean).join(" "), ref: scroller, onScroll, children: [
9010
+ /* @__PURE__ */ (0, import_jsx_runtime70.jsxs)("div", { className: "fdc-log", role: "log", "aria-label": "Conversation", children: [
9011
+ status === "loading" || status === "resolving" ? /* @__PURE__ */ (0, import_jsx_runtime70.jsx)(LoadingTurns, {}) : null,
9012
+ status === "disconnected" ? /* @__PURE__ */ (0, import_jsx_runtime70.jsxs)("div", { className: "fdc-dead", children: [
9013
+ /* @__PURE__ */ (0, import_jsx_runtime70.jsx)("span", { className: "fdc-dead-icon", children: /* @__PURE__ */ (0, import_jsx_runtime70.jsx)("i", { className: "ph ph-plugs", "aria-hidden": "true" }) }),
9014
+ /* @__PURE__ */ (0, import_jsx_runtime70.jsx)("h3", { className: "fdc-dead-title", children: ctx.deadTitle || "The assistant isn\u2019t reachable" }),
9015
+ /* @__PURE__ */ (0, import_jsx_runtime70.jsx)("p", { className: "fdc-dead-body", children: fatal === "chat_unavailable" ? "The service reported chat_unavailable. Nothing you type will be lost \u2014 reopen the panel once it\u2019s back." : "The thread couldn\u2019t be resolved" + (fatal ? " (" + fatal + ")" : "") + ". The composer stays disabled until it resolves." }),
9016
+ ctx.onReconnect ? /* @__PURE__ */ (0, import_jsx_runtime70.jsxs)("button", { type: "button", className: "fd-btn fd-btn-secondary fd-btn-sm", onClick: ctx.onReconnect, children: [
9017
+ /* @__PURE__ */ (0, import_jsx_runtime70.jsx)("i", { className: "ph ph-arrow-clockwise", "aria-hidden": "true" }),
8769
9018
  "Try again"
8770
9019
  ] }) : null
8771
9020
  ] }) : null,
8772
- empty ? renderEmpty ? renderEmpty() : /* @__PURE__ */ (0, import_jsx_runtime67.jsxs)("div", { className: "fdc-empty", children: [
8773
- /* @__PURE__ */ (0, import_jsx_runtime67.jsx)("span", { className: "fdc-empty-icon", children: /* @__PURE__ */ (0, import_jsx_runtime67.jsx)("i", { className: "ph ph-" + emptyIcon, "aria-hidden": "true" }) }),
8774
- /* @__PURE__ */ (0, import_jsx_runtime67.jsx)("h3", { className: "fdc-empty-title", children: emptyTitle }),
8775
- emptyDescription ? /* @__PURE__ */ (0, import_jsx_runtime67.jsx)("p", { className: "fdc-empty-body", children: emptyDescription }) : null,
8776
- /* @__PURE__ */ (0, import_jsx_runtime67.jsx)(Suggestions, { items: suggestions, onPick })
9021
+ empty ? renderEmpty ? renderEmpty() : /* @__PURE__ */ (0, import_jsx_runtime70.jsxs)("div", { className: "fdc-empty", children: [
9022
+ /* @__PURE__ */ (0, import_jsx_runtime70.jsx)("span", { className: "fdc-empty-icon", children: /* @__PURE__ */ (0, import_jsx_runtime70.jsx)("i", { className: "ph ph-" + emptyIcon, "aria-hidden": "true" }) }),
9023
+ /* @__PURE__ */ (0, import_jsx_runtime70.jsx)("h3", { className: "fdc-empty-title", children: emptyTitle }),
9024
+ emptyDescription ? /* @__PURE__ */ (0, import_jsx_runtime70.jsx)("p", { className: "fdc-empty-body", children: emptyDescription }) : null,
9025
+ /* @__PURE__ */ (0, import_jsx_runtime70.jsx)(Suggestions, { items: suggestions, onPick })
8777
9026
  ] }) : null,
8778
9027
  groups.map((g, i) => {
8779
9028
  const prev = groups[i - 1];
8780
9029
  const k = dayKey(g.messages[0].timestamp);
8781
9030
  const showDay = !!k && (!prev || dayKey(prev.messages[0].timestamp) !== k);
8782
- return /* @__PURE__ */ (0, import_jsx_runtime67.jsxs)(React36.Fragment, { children: [
8783
- showDay ? /* @__PURE__ */ (0, import_jsx_runtime67.jsx)("div", { className: "fdc-day", children: /* @__PURE__ */ (0, import_jsx_runtime67.jsx)("span", { children: dayLabel(k) }) }) : null,
8784
- /* @__PURE__ */ (0, import_jsx_runtime67.jsx)(ChatTurn, { group: g, ctx })
9031
+ return /* @__PURE__ */ (0, import_jsx_runtime70.jsxs)(React38.Fragment, { children: [
9032
+ showDay ? /* @__PURE__ */ (0, import_jsx_runtime70.jsx)("div", { className: "fdc-day", children: /* @__PURE__ */ (0, import_jsx_runtime70.jsx)("span", { children: dayLabel(k) }) }) : null,
9033
+ /* @__PURE__ */ (0, import_jsx_runtime70.jsx)(ChatTurn, { group: g, ctx })
8785
9034
  ] }, g.key || i);
8786
9035
  })
8787
9036
  ] }),
8788
- pill ? /* @__PURE__ */ (0, import_jsx_runtime67.jsxs)("button", { type: "button", className: "fdc-pill", onClick: () => toBottom(true), children: [
8789
- /* @__PURE__ */ (0, import_jsx_runtime67.jsx)("i", { className: "ph ph-arrow-down", "aria-hidden": "true" }),
9037
+ pill ? /* @__PURE__ */ (0, import_jsx_runtime70.jsxs)("button", { type: "button", className: "fdc-pill", onClick: () => toBottom(true), children: [
9038
+ /* @__PURE__ */ (0, import_jsx_runtime70.jsx)("i", { className: "ph ph-arrow-down", "aria-hidden": "true" }),
8790
9039
  pill,
8791
9040
  " new message",
8792
9041
  pill === 1 ? "" : "s"
@@ -8796,8 +9045,8 @@ function ChatTranscript({
8796
9045
  var TranscriptKit = { groupMessages };
8797
9046
 
8798
9047
  // src/components/chat/ChatComposer.tsx
8799
- var React37 = __toESM(require("react"), 1);
8800
- var import_jsx_runtime68 = require("react/jsx-runtime");
9048
+ var React39 = __toESM(require("react"), 1);
9049
+ var import_jsx_runtime71 = require("react/jsx-runtime");
8801
9050
  function ChatComposer({
8802
9051
  onSubmit,
8803
9052
  onStop,
@@ -8824,17 +9073,17 @@ function ChatComposer({
8824
9073
  onReject,
8825
9074
  onOpenAttachment
8826
9075
  }) {
8827
- const [text, setText] = React37.useState(draft || "");
8828
- const [trigger, setTrigger] = React37.useState(null);
8829
- const [mentionItems, setMentionItems] = React37.useState([]);
8830
- const [listening, setListening] = React37.useState(false);
8831
- const [notice, setNotice] = React37.useState(null);
8832
- const editor = React37.useRef(null);
8833
- const wrap = React37.useRef(null);
8834
- const stopVoice = React37.useRef(null);
9076
+ const [text, setText] = React39.useState(draft || "");
9077
+ const [trigger, setTrigger] = React39.useState(null);
9078
+ const [mentionItems, setMentionItems] = React39.useState([]);
9079
+ const [listening, setListening] = React39.useState(false);
9080
+ const [notice, setNotice] = React39.useState(null);
9081
+ const editor = React39.useRef(null);
9082
+ const wrap = React39.useRef(null);
9083
+ const stopVoice = React39.useRef(null);
8835
9084
  const staged = useStagedFiles(fileUploadHandler, { onError: () => {
8836
9085
  } });
8837
- React37.useEffect(() => {
9086
+ React39.useEffect(() => {
8838
9087
  if (draft != null && draft !== text) setText(draft);
8839
9088
  }, [draft]);
8840
9089
  const change = (v) => {
@@ -8868,7 +9117,7 @@ function ChatComposer({
8868
9117
  e.preventDefault();
8869
9118
  staged.add(found.files);
8870
9119
  };
8871
- React37.useEffect(() => {
9120
+ React39.useEffect(() => {
8872
9121
  if (!trigger || trigger.type !== "mention" || !mentionSources) {
8873
9122
  setMentionItems([]);
8874
9123
  return;
@@ -8886,7 +9135,7 @@ function ChatComposer({
8886
9135
  const q = (trigger.query || "").toLowerCase();
8887
9136
  setMentionItems(mentionSources.filter((m) => !q || (m.label + " " + (m.description || "")).toLowerCase().includes(q)));
8888
9137
  }, [trigger, mentionSources]);
8889
- const slashItems = React37.useMemo(() => {
9138
+ const slashItems = React39.useMemo(() => {
8890
9139
  if (!trigger || trigger.type !== "slash" || !slashCommands) return [];
8891
9140
  const q = (trigger.query || "").toLowerCase();
8892
9141
  return slashCommands.filter((c) => !q || (c.id + " " + c.label + " " + (c.description || "")).toLowerCase().includes(q));
@@ -8900,7 +9149,7 @@ function ChatComposer({
8900
9149
  description: it.description,
8901
9150
  icon: it.icon,
8902
9151
  meta: mention.meta,
8903
- shortcut: slash.shortcut ? /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(KeyHint, { keys: slash.shortcut, size: "sm" }) : void 0,
9152
+ shortcut: slash.shortcut ? /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(KeyHint, { keys: slash.shortcut, size: "sm" }) : void 0,
8904
9153
  onSelect: () => {
8905
9154
  const insert = trigger.type === "slash" ? slash.immediate ? "/" + slash.id : "/" + slash.id + " " : "@" + (mention.value || mention.label) + " ";
8906
9155
  editor.current && editor.current.replaceRange(trigger.from, trigger.to, insert);
@@ -8963,14 +9212,14 @@ function ChatComposer({
8963
9212
  stopVoice.current = typeof res === "function" ? res : () => {
8964
9213
  };
8965
9214
  };
8966
- return /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)("div", { className: "fdc-composer" + (disabled ? " is-disabled" : "") + (narrow ? " is-narrow" : ""), children: [
8967
- queue.length ? /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("div", { className: "fdc-queue", "aria-label": "Queued messages", children: queue.map((q) => /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)("div", { className: "fdc-queue-row", children: [
8968
- /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("i", { className: "ph ph-clock-countdown", "aria-hidden": "true" }),
8969
- /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("span", { className: "fdc-queue-text", children: q.text || (q.attachments ? q.attachments.length + " file(s)" : "") }),
8970
- onRemoveQueued ? /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("button", { type: "button", className: "fdc-queue-x", onClick: () => onRemoveQueued(q.id), "aria-label": "Remove queued message", children: /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("i", { className: "ph ph-x", "aria-hidden": "true" }) }) : null
9215
+ return /* @__PURE__ */ (0, import_jsx_runtime71.jsxs)("div", { className: "fdc-composer" + (disabled ? " is-disabled" : "") + (narrow ? " is-narrow" : ""), children: [
9216
+ queue.length ? /* @__PURE__ */ (0, import_jsx_runtime71.jsx)("div", { className: "fdc-queue", "aria-label": "Queued messages", children: queue.map((q) => /* @__PURE__ */ (0, import_jsx_runtime71.jsxs)("div", { className: "fdc-queue-row", children: [
9217
+ /* @__PURE__ */ (0, import_jsx_runtime71.jsx)("i", { className: "ph ph-clock-countdown", "aria-hidden": "true" }),
9218
+ /* @__PURE__ */ (0, import_jsx_runtime71.jsx)("span", { className: "fdc-queue-text", children: q.text || (q.attachments ? q.attachments.length + " file(s)" : "") }),
9219
+ onRemoveQueued ? /* @__PURE__ */ (0, import_jsx_runtime71.jsx)("button", { type: "button", className: "fdc-queue-x", onClick: () => onRemoveQueued(q.id), "aria-label": "Remove queued message", children: /* @__PURE__ */ (0, import_jsx_runtime71.jsx)("i", { className: "ph ph-x", "aria-hidden": "true" }) }) : null
8971
9220
  ] }, q.id)) }) : null,
8972
9221
  sessionBar,
8973
- /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(
9222
+ /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
8974
9223
  Dropzone,
8975
9224
  {
8976
9225
  className: "fdc-field",
@@ -8984,9 +9233,9 @@ function ChatComposer({
8984
9233
  disabled: !fileUploadHandler || disabled,
8985
9234
  label: "Drop to attach",
8986
9235
  hint: acceptFiles ? acceptFiles.replace(/,/g, " \xB7 ") : void 0,
8987
- children: /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)("div", { ref: wrap, className: "fdc-field-inner", children: [
8988
- staged.items.length ? /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("div", { className: "fdc-staged", children: /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(FileStrip, { files: staged.items, size: narrow ? 60 : 68, onRemove: staged.remove, onRetry: staged.retry, onOpen: onOpenAttachment }) }) : null,
8989
- /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(
9236
+ children: /* @__PURE__ */ (0, import_jsx_runtime71.jsxs)("div", { ref: wrap, className: "fdc-field-inner", children: [
9237
+ staged.items.length ? /* @__PURE__ */ (0, import_jsx_runtime71.jsx)("div", { className: "fdc-staged", children: /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(FileStrip, { files: staged.items, size: narrow ? 60 : 68, onRemove: staged.remove, onRetry: staged.retry, onOpen: onOpenAttachment }) }) : null,
9238
+ /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
8990
9239
  MarkdownEditor,
8991
9240
  {
8992
9241
  ref: editor,
@@ -9005,33 +9254,33 @@ function ChatComposer({
9005
9254
  ariaLabel: "Message"
9006
9255
  }
9007
9256
  ),
9008
- /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)("div", { className: "fdc-tools", children: [
9009
- fileUploadHandler ? /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(FilePickButton, { onFiles: staged.add, onReject: (r) => flash(r[0].message), accept: acceptFiles, maxFileSize, label: "Attach files", icon: "plus" }) : null,
9010
- voiceHandler ? /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("button", { type: "button", className: "fd-attachbtn" + (listening ? " is-live" : ""), onClick: voice, "aria-pressed": listening, "aria-label": listening ? "Stop dictation" : "Dictate", children: /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("i", { className: "ph ph-" + (listening ? "waveform" : "microphone"), "aria-hidden": "true" }) }) : null,
9257
+ /* @__PURE__ */ (0, import_jsx_runtime71.jsxs)("div", { className: "fdc-tools", children: [
9258
+ fileUploadHandler ? /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(FilePickButton, { onFiles: staged.add, onReject: (r) => flash(r[0].message), accept: acceptFiles, maxFileSize, label: "Attach files", icon: "plus" }) : null,
9259
+ voiceHandler ? /* @__PURE__ */ (0, import_jsx_runtime71.jsx)("button", { type: "button", className: "fd-attachbtn" + (listening ? " is-live" : ""), onClick: voice, "aria-pressed": listening, "aria-label": listening ? "Stop dictation" : "Dictate", children: /* @__PURE__ */ (0, import_jsx_runtime71.jsx)("i", { className: "ph ph-" + (listening ? "waveform" : "microphone"), "aria-hidden": "true" }) }) : null,
9011
9260
  toolbarExtras,
9012
- /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("span", { className: "fdc-tools-gap" }),
9013
- maxLength && text.length > maxLength * 0.6 ? /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)("span", { className: "fdc-count fd-tabular" + (text.length > maxLength * 0.95 ? " is-hot" : ""), children: [
9261
+ /* @__PURE__ */ (0, import_jsx_runtime71.jsx)("span", { className: "fdc-tools-gap" }),
9262
+ maxLength && text.length > maxLength * 0.6 ? /* @__PURE__ */ (0, import_jsx_runtime71.jsxs)("span", { className: "fdc-count fd-tabular" + (text.length > maxLength * 0.95 ? " is-hot" : ""), children: [
9014
9263
  text.length,
9015
9264
  "/",
9016
9265
  maxLength
9017
9266
  ] }) : null,
9018
- busy ? /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)("button", { type: "button", className: "fdc-stop", onClick: onStop, "aria-label": "Stop generating", children: [
9019
- /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("i", { className: "ph ph-stop-circle", "aria-hidden": "true" }),
9020
- /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("span", { children: "Stop" })
9021
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)("button", { type: "button", className: "fdc-send", onClick: submit, disabled: !canSend, "aria-label": "Send message", children: [
9022
- /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("i", { className: "ph ph-paper-plane-right", "aria-hidden": "true" }),
9023
- /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("span", { className: "fdc-send-label", children: "Send" })
9267
+ busy ? /* @__PURE__ */ (0, import_jsx_runtime71.jsxs)("button", { type: "button", className: "fdc-stop", onClick: onStop, "aria-label": "Stop generating", children: [
9268
+ /* @__PURE__ */ (0, import_jsx_runtime71.jsx)("i", { className: "ph ph-stop-circle", "aria-hidden": "true" }),
9269
+ /* @__PURE__ */ (0, import_jsx_runtime71.jsx)("span", { children: "Stop" })
9270
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime71.jsxs)("button", { type: "button", className: "fdc-send", onClick: submit, disabled: !canSend, "aria-label": "Send message", children: [
9271
+ /* @__PURE__ */ (0, import_jsx_runtime71.jsx)("i", { className: "ph ph-paper-plane-right", "aria-hidden": "true" }),
9272
+ /* @__PURE__ */ (0, import_jsx_runtime71.jsx)("span", { className: "fdc-send-label", children: "Send" })
9024
9273
  ] })
9025
9274
  ] })
9026
9275
  ] })
9027
9276
  }
9028
9277
  ),
9029
- notice ? /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)("div", { className: "fdc-notice", role: "status", children: [
9030
- /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
9278
+ notice ? /* @__PURE__ */ (0, import_jsx_runtime71.jsxs)("div", { className: "fdc-notice", role: "status", children: [
9279
+ /* @__PURE__ */ (0, import_jsx_runtime71.jsx)("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
9031
9280
  notice
9032
9281
  ] }) : null,
9033
- hint && !notice ? /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("div", { className: "fdc-hint", children: hint }) : null,
9034
- /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(
9282
+ hint && !notice ? /* @__PURE__ */ (0, import_jsx_runtime71.jsx)("div", { className: "fdc-hint", children: hint }) : null,
9283
+ /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
9035
9284
  Popover,
9036
9285
  {
9037
9286
  open: menuOpen,
@@ -9045,12 +9294,12 @@ function ChatComposer({
9045
9294
  returnFocus: false,
9046
9295
  closeOnOutside: true,
9047
9296
  label: trigger && trigger.type === "slash" ? "Commands" : "Mentions",
9048
- children: /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(
9297
+ children: /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
9049
9298
  Menu,
9050
9299
  {
9051
9300
  items: menuItems,
9052
9301
  autoFocus: false,
9053
- header: /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("div", { className: "fd-pop-group", children: trigger && trigger.type === "slash" ? "Commands" : "Attach context" }),
9302
+ header: /* @__PURE__ */ (0, import_jsx_runtime71.jsx)("div", { className: "fd-pop-group", children: trigger && trigger.type === "slash" ? "Commands" : "Attach context" }),
9054
9303
  onClose: () => setTrigger(null)
9055
9304
  }
9056
9305
  )
@@ -9060,12 +9309,12 @@ function ChatComposer({
9060
9309
  }
9061
9310
 
9062
9311
  // src/components/chat/ChatSessionBar.tsx
9063
- var React38 = __toESM(require("react"), 1);
9064
- var import_jsx_runtime69 = require("react/jsx-runtime");
9312
+ var React40 = __toESM(require("react"), 1);
9313
+ var import_jsx_runtime72 = require("react/jsx-runtime");
9065
9314
  var compact2 = meterFormats.compact;
9066
9315
  function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extras }) {
9067
- const [open, setOpen] = React38.useState(false);
9068
- const anchor = React38.useRef(null);
9316
+ const [open, setOpen] = React40.useState(false);
9317
+ const anchor = React40.useRef(null);
9069
9318
  const stats = sessionStats || null;
9070
9319
  const cu = contextUsage || null;
9071
9320
  const limits = usageLimits || null;
@@ -9080,9 +9329,9 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
9080
9329
  if (stats && stats.runningTasks) bits.push(stats.runningTasks + " running task" + (stats.runningTasks === 1 ? "" : "s"));
9081
9330
  if (cu) bits.push(pct + "% context");
9082
9331
  const expandable = !!(cu || limits);
9083
- return /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)(React38.Fragment, { children: [
9084
- /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("div", { className: "fdc-bar", children: [
9085
- /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)(
9332
+ return /* @__PURE__ */ (0, import_jsx_runtime72.jsxs)(React40.Fragment, { children: [
9333
+ /* @__PURE__ */ (0, import_jsx_runtime72.jsxs)("div", { className: "fdc-bar", children: [
9334
+ /* @__PURE__ */ (0, import_jsx_runtime72.jsxs)(
9086
9335
  "button",
9087
9336
  {
9088
9337
  type: "button",
@@ -9093,16 +9342,16 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
9093
9342
  "aria-expanded": expandable ? open : void 0,
9094
9343
  "aria-label": expandable ? "Usage details" : void 0,
9095
9344
  children: [
9096
- cu ? /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("span", { className: "fdc-bar-mini", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(SegmentedMeter, { total, segments: cu.segments, height: 4, showTotal: false }) }) : null,
9097
- /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("span", { className: "fdc-bar-text", children: bits.join(" \xB7 ") }),
9098
- expandable ? /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("i", { className: "ph ph-caret-right fdc-bar-caret", "aria-hidden": "true" }) : null
9345
+ cu ? /* @__PURE__ */ (0, import_jsx_runtime72.jsx)("span", { className: "fdc-bar-mini", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(SegmentedMeter, { total, segments: cu.segments, height: 4, showTotal: false }) }) : null,
9346
+ /* @__PURE__ */ (0, import_jsx_runtime72.jsx)("span", { className: "fdc-bar-text", children: bits.join(" \xB7 ") }),
9347
+ expandable ? /* @__PURE__ */ (0, import_jsx_runtime72.jsx)("i", { className: "ph ph-caret-right fdc-bar-caret", "aria-hidden": "true" }) : null
9099
9348
  ]
9100
9349
  }
9101
9350
  ),
9102
9351
  extras
9103
9352
  ] }),
9104
- /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(Popover, { open, anchorRef: anchor, placement: "top-start", onClose: () => setOpen(false), minWidth: 330, maxHeight: 460, padded: true, label: "Usage", children: /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("div", { className: "fdc-usage", children: [
9105
- cu ? /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("section", { className: "fdc-usage-sec", children: /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(
9353
+ /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(Popover, { open, anchorRef: anchor, placement: "top-start", onClose: () => setOpen(false), minWidth: 330, maxHeight: 460, padded: true, label: "Usage", children: /* @__PURE__ */ (0, import_jsx_runtime72.jsxs)("div", { className: "fdc-usage", children: [
9354
+ cu ? /* @__PURE__ */ (0, import_jsx_runtime72.jsx)("section", { className: "fdc-usage-sec", children: /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
9106
9355
  SegmentedMeter,
9107
9356
  {
9108
9357
  total,
@@ -9114,9 +9363,9 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
9114
9363
  remainderLabel: "Free"
9115
9364
  }
9116
9365
  ) }) : null,
9117
- limits && limits.length ? /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("section", { className: "fdc-usage-sec", children: [
9118
- /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("h4", { className: "fdc-usage-h", children: "Usage limits" }),
9119
- /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("div", { className: "fdc-usage-rows", children: limits.map((l) => /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(
9366
+ limits && limits.length ? /* @__PURE__ */ (0, import_jsx_runtime72.jsxs)("section", { className: "fdc-usage-sec", children: [
9367
+ /* @__PURE__ */ (0, import_jsx_runtime72.jsx)("h4", { className: "fdc-usage-h", children: "Usage limits" }),
9368
+ /* @__PURE__ */ (0, import_jsx_runtime72.jsx)("div", { className: "fdc-usage-rows", children: limits.map((l) => /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
9120
9369
  QuotaRow,
9121
9370
  {
9122
9371
  label: l.label,
@@ -9126,32 +9375,32 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
9126
9375
  l.id
9127
9376
  )) })
9128
9377
  ] }) : null,
9129
- stats ? /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("section", { className: "fdc-usage-sec fdc-usage-stats", children: [
9130
- stats.elapsedMs ? /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("div", { children: [
9131
- /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("span", { children: "Session" }),
9132
- /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("b", { className: "fd-tabular", children: formatDuration(stats.elapsedMs) })
9378
+ stats ? /* @__PURE__ */ (0, import_jsx_runtime72.jsxs)("section", { className: "fdc-usage-sec fdc-usage-stats", children: [
9379
+ stats.elapsedMs ? /* @__PURE__ */ (0, import_jsx_runtime72.jsxs)("div", { children: [
9380
+ /* @__PURE__ */ (0, import_jsx_runtime72.jsx)("span", { children: "Session" }),
9381
+ /* @__PURE__ */ (0, import_jsx_runtime72.jsx)("b", { className: "fd-tabular", children: formatDuration(stats.elapsedMs) })
9133
9382
  ] }) : null,
9134
- stats.tokens ? /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("div", { children: [
9135
- /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("span", { children: "Tokens" }),
9136
- /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("b", { className: "fd-tabular", children: stats.tokens.toLocaleString() })
9383
+ stats.tokens ? /* @__PURE__ */ (0, import_jsx_runtime72.jsxs)("div", { children: [
9384
+ /* @__PURE__ */ (0, import_jsx_runtime72.jsx)("span", { children: "Tokens" }),
9385
+ /* @__PURE__ */ (0, import_jsx_runtime72.jsx)("b", { className: "fd-tabular", children: stats.tokens.toLocaleString() })
9137
9386
  ] }) : null,
9138
- stats.costUsd != null ? /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("div", { children: [
9139
- /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("span", { children: "Cost" }),
9140
- /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("b", { className: "fd-tabular", children: [
9387
+ stats.costUsd != null ? /* @__PURE__ */ (0, import_jsx_runtime72.jsxs)("div", { children: [
9388
+ /* @__PURE__ */ (0, import_jsx_runtime72.jsx)("span", { children: "Cost" }),
9389
+ /* @__PURE__ */ (0, import_jsx_runtime72.jsxs)("b", { className: "fd-tabular", children: [
9141
9390
  "$",
9142
9391
  Number(stats.costUsd).toFixed(3)
9143
9392
  ] })
9144
9393
  ] }) : null,
9145
- stats.turns ? /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("div", { children: [
9146
- /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("span", { children: "Turns" }),
9147
- /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("b", { className: "fd-tabular", children: stats.turns })
9394
+ stats.turns ? /* @__PURE__ */ (0, import_jsx_runtime72.jsxs)("div", { children: [
9395
+ /* @__PURE__ */ (0, import_jsx_runtime72.jsx)("span", { children: "Turns" }),
9396
+ /* @__PURE__ */ (0, import_jsx_runtime72.jsx)("b", { className: "fd-tabular", children: stats.turns })
9148
9397
  ] }) : null
9149
9398
  ] }) : null,
9150
- onClear ? /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("footer", { className: "fdc-usage-foot", children: /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("button", { type: "button", className: "fdc-usage-clear", onClick: () => {
9399
+ onClear ? /* @__PURE__ */ (0, import_jsx_runtime72.jsx)("footer", { className: "fdc-usage-foot", children: /* @__PURE__ */ (0, import_jsx_runtime72.jsxs)("button", { type: "button", className: "fdc-usage-clear", onClick: () => {
9151
9400
  setOpen(false);
9152
9401
  onClear();
9153
9402
  }, children: [
9154
- /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("i", { className: "ph ph-trash", "aria-hidden": "true" }),
9403
+ /* @__PURE__ */ (0, import_jsx_runtime72.jsx)("i", { className: "ph ph-trash", "aria-hidden": "true" }),
9155
9404
  "Clear conversation"
9156
9405
  ] }) }) : null
9157
9406
  ] }) })
@@ -9188,7 +9437,7 @@ function ModelControls({
9188
9437
  disabled: m.disabled,
9189
9438
  checked: m.id === (current2 && current2.id),
9190
9439
  meta: m.meta,
9191
- shortcut: m.shortcut ? /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(KeyHint, { keys: m.shortcut, size: "sm" }) : void 0,
9440
+ shortcut: m.shortcut ? /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(KeyHint, { keys: m.shortcut, size: "sm" }) : void 0,
9192
9441
  onSelect: () => onModelChange && onModelChange(m.id)
9193
9442
  });
9194
9443
  const items = [{ kind: "section", label: "Models" }].concat(flat.map(item));
@@ -9201,15 +9450,15 @@ function ModelControls({
9201
9450
  items.push({ kind: "section", label: "Fast mode" });
9202
9451
  items.push({
9203
9452
  kind: "custom",
9204
- render: () => /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("label", { className: "fdc-switchrow", children: [
9205
- /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("span", { children: fastModeLabel }),
9206
- /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("input", { type: "checkbox", className: "fd-sr", checked: !!fastMode, onChange: (e) => onFastModeChange(e.target.checked) }),
9207
- /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("span", { className: "fd-switch-track" + (fastMode ? " is-on" : ""), "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("span", { className: "fd-switch-thumb" }) })
9453
+ render: () => /* @__PURE__ */ (0, import_jsx_runtime72.jsxs)("label", { className: "fdc-switchrow", children: [
9454
+ /* @__PURE__ */ (0, import_jsx_runtime72.jsx)("span", { children: fastModeLabel }),
9455
+ /* @__PURE__ */ (0, import_jsx_runtime72.jsx)("input", { type: "checkbox", className: "fd-sr", checked: !!fastMode, onChange: (e) => onFastModeChange(e.target.checked) }),
9456
+ /* @__PURE__ */ (0, import_jsx_runtime72.jsx)("span", { className: "fd-switch-track" + (fastMode ? " is-on" : ""), "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime72.jsx)("span", { className: "fd-switch-thumb" }) })
9208
9457
  ] })
9209
9458
  });
9210
9459
  }
9211
- return /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)(React38.Fragment, { children: [
9212
- /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(
9460
+ return /* @__PURE__ */ (0, import_jsx_runtime72.jsxs)(React40.Fragment, { children: [
9461
+ /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
9213
9462
  MenuButton,
9214
9463
  {
9215
9464
  items,
@@ -9220,7 +9469,7 @@ function ModelControls({
9220
9469
  title: "Choose a model"
9221
9470
  }
9222
9471
  ),
9223
- effortLevels && effortLevels.length ? /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(
9472
+ effortLevels && effortLevels.length ? /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
9224
9473
  MenuButton,
9225
9474
  {
9226
9475
  placement: "top-end",
@@ -9241,7 +9490,7 @@ function ModelControls({
9241
9490
  }
9242
9491
 
9243
9492
  // src/components/chat/AgentChatPanel.tsx
9244
- var import_jsx_runtime70 = require("react/jsx-runtime");
9493
+ var import_jsx_runtime73 = require("react/jsx-runtime");
9245
9494
  var SURFACES = { sidebar: "is-sidebar", inline: "is-inline", page: "is-page", modal: "is-modal", sheet: "is-sheet" };
9246
9495
  function AgentChatPanel({
9247
9496
  /* required */
@@ -9325,11 +9574,11 @@ function AgentChatPanel({
9325
9574
  onFeedback,
9326
9575
  onEditMessage
9327
9576
  }) {
9328
- const [panelWidth, setPanelWidth] = React39.useState(width);
9329
- const [applied, setApplied] = React39.useState({});
9330
- const [draft, setDraft] = React39.useState("");
9331
- const dragging = React39.useRef(null);
9332
- React39.useEffect(() => setPanelWidth(width), [width]);
9577
+ const [panelWidth, setPanelWidth] = React41.useState(width);
9578
+ const [applied, setApplied] = React41.useState({});
9579
+ const [draft, setDraft] = React41.useState("");
9580
+ const dragging = React41.useRef(null);
9581
+ React41.useEffect(() => setPanelWidth(width), [width]);
9333
9582
  const engine = useChatEngine({
9334
9583
  contextType,
9335
9584
  contextId,
@@ -9395,7 +9644,7 @@ function AgentChatPanel({
9395
9644
  onReconnect: engine.reload,
9396
9645
  deadTitle: "The assistant isn\u2019t reachable"
9397
9646
  };
9398
- const sessionBar = /* @__PURE__ */ (0, import_jsx_runtime70.jsx)(
9647
+ const sessionBar = /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(
9399
9648
  ChatSessionBar,
9400
9649
  {
9401
9650
  sessionStats,
@@ -9404,7 +9653,7 @@ function AgentChatPanel({
9404
9653
  onClear: engine.visible.length ? engine.clear : void 0
9405
9654
  }
9406
9655
  );
9407
- const modelControls = /* @__PURE__ */ (0, import_jsx_runtime70.jsx)(
9656
+ const modelControls = /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(
9408
9657
  ModelControls,
9409
9658
  {
9410
9659
  models,
@@ -9419,7 +9668,7 @@ function AgentChatPanel({
9419
9668
  narrow
9420
9669
  }
9421
9670
  );
9422
- const threadMenu = threads && threads.length ? /* @__PURE__ */ (0, import_jsx_runtime70.jsx)(
9671
+ const threadMenu = threads && threads.length ? /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(
9423
9672
  MenuButton,
9424
9673
  {
9425
9674
  variant: "ghost",
@@ -9446,7 +9695,7 @@ function AgentChatPanel({
9446
9695
  })))
9447
9696
  }
9448
9697
  ) : null;
9449
- return /* @__PURE__ */ (0, import_jsx_runtime70.jsxs)(
9698
+ return /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)(
9450
9699
  "aside",
9451
9700
  {
9452
9701
  className: ["fdc-panel", SURFACES[surface] || SURFACES.sidebar, narrow ? "is-narrow" : "", className].filter(Boolean).join(" "),
@@ -9457,7 +9706,7 @@ function AgentChatPanel({
9457
9706
  },
9458
9707
  "aria-label": title,
9459
9708
  children: [
9460
- surface === "sidebar" && resizable ? /* @__PURE__ */ (0, import_jsx_runtime70.jsx)(
9709
+ surface === "sidebar" && resizable ? /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(
9461
9710
  "div",
9462
9711
  {
9463
9712
  className: "fdc-grip",
@@ -9472,20 +9721,20 @@ function AgentChatPanel({
9472
9721
  }
9473
9722
  }
9474
9723
  ) : null,
9475
- showHeader ? /* @__PURE__ */ (0, import_jsx_runtime70.jsxs)("header", { className: "fdc-head", children: [
9476
- /* @__PURE__ */ (0, import_jsx_runtime70.jsx)("span", { className: "fdc-head-mark", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime70.jsx)("i", { className: "ph ph-" + assistantIcon }) }),
9477
- /* @__PURE__ */ (0, import_jsx_runtime70.jsxs)("span", { className: "fdc-head-titles", children: [
9478
- /* @__PURE__ */ (0, import_jsx_runtime70.jsx)("span", { className: "fdc-head-title", children: title }),
9479
- subtitle ? /* @__PURE__ */ (0, import_jsx_runtime70.jsx)("span", { className: "fdc-head-sub", children: subtitle }) : null
9724
+ showHeader ? /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("header", { className: "fdc-head", children: [
9725
+ /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("span", { className: "fdc-head-mark", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("i", { className: "ph ph-" + assistantIcon }) }),
9726
+ /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("span", { className: "fdc-head-titles", children: [
9727
+ /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("span", { className: "fdc-head-title", children: title }),
9728
+ subtitle ? /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("span", { className: "fdc-head-sub", children: subtitle }) : null
9480
9729
  ] }),
9481
- /* @__PURE__ */ (0, import_jsx_runtime70.jsxs)("span", { className: "fdc-head-acts", children: [
9730
+ /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("span", { className: "fdc-head-acts", children: [
9482
9731
  headerActions,
9483
9732
  threadMenu,
9484
- onNewThread ? /* @__PURE__ */ (0, import_jsx_runtime70.jsx)("button", { type: "button", className: "fdc-iconbtn", onClick: onNewThread, "aria-label": "New conversation", title: "New conversation", children: /* @__PURE__ */ (0, import_jsx_runtime70.jsx)("i", { className: "ph ph-plus", "aria-hidden": "true" }) }) : null,
9485
- onClose ? /* @__PURE__ */ (0, import_jsx_runtime70.jsx)("button", { type: "button", className: "fdc-iconbtn", onClick: onClose, "aria-label": "Close panel", title: "Close", children: /* @__PURE__ */ (0, import_jsx_runtime70.jsx)("i", { className: "ph ph-x", "aria-hidden": "true" }) }) : null
9733
+ onNewThread ? /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("button", { type: "button", className: "fdc-iconbtn", onClick: onNewThread, "aria-label": "New conversation", title: "New conversation", children: /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("i", { className: "ph ph-plus", "aria-hidden": "true" }) }) : null,
9734
+ onClose ? /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("button", { type: "button", className: "fdc-iconbtn", onClick: onClose, "aria-label": "Close panel", title: "Close", children: /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("i", { className: "ph ph-x", "aria-hidden": "true" }) }) : null
9486
9735
  ] })
9487
9736
  ] }) : null,
9488
- /* @__PURE__ */ (0, import_jsx_runtime70.jsx)(
9737
+ /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(
9489
9738
  ChatTranscript,
9490
9739
  {
9491
9740
  messages: engine.visible,
@@ -9500,7 +9749,7 @@ function AgentChatPanel({
9500
9749
  renderEmpty
9501
9750
  }
9502
9751
  ),
9503
- /* @__PURE__ */ (0, import_jsx_runtime70.jsx)(
9752
+ /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(
9504
9753
  ChatComposer,
9505
9754
  {
9506
9755
  onSubmit: (text, atts) => engine.send(text, atts),
@@ -9533,7 +9782,7 @@ function AgentChatPanel({
9533
9782
  }
9534
9783
 
9535
9784
  // src/kits/query.ts
9536
- var React40 = __toESM(require("react"), 1);
9785
+ var React42 = __toESM(require("react"), 1);
9537
9786
  function eqFilter(get2) {
9538
9787
  return (row, value) => Array.isArray(value) ? value.includes(get2(row)) : get2(row) === value;
9539
9788
  }
@@ -9565,22 +9814,22 @@ function compare(a, b, dir) {
9565
9814
  var API = null;
9566
9815
  var PREFS = null;
9567
9816
  function useServerTable({ endpoint, params, defaults, deps, prefsKey }) {
9568
- const [query, setQuery] = React40.useState(() => {
9817
+ const [query, setQuery] = React42.useState(() => {
9569
9818
  const store = PREFS || window.PlannerPrefs;
9570
9819
  const saved = prefsKey && store ? store.getTable(prefsKey) : {};
9571
9820
  return { ...DEFAULTS, ...defaults || {}, ...saved.pageSize ? { pageSize: saved.pageSize } : {}, ...saved.sort ? { sort: saved.sort, dir: saved.dir || "desc" } : {} };
9572
9821
  });
9573
- const savePref = React40.useCallback((patch2) => {
9822
+ const savePref = React42.useCallback((patch2) => {
9574
9823
  const store = PREFS || window.PlannerPrefs;
9575
9824
  if (prefsKey && store) store.setTable(prefsKey, patch2);
9576
9825
  }, [prefsKey]);
9577
- const [res, setRes] = React40.useState(null);
9578
- const [loading, setLoading] = React40.useState(true);
9579
- const seq2 = React40.useRef(0);
9826
+ const [res, setRes] = React42.useState(null);
9827
+ const [loading, setLoading] = React42.useState(true);
9828
+ const seq2 = React42.useRef(0);
9580
9829
  const depKey = (deps || []).join("|");
9581
9830
  const paramKey = JSON.stringify(params || {});
9582
9831
  const queryKey = JSON.stringify(query);
9583
- React40.useEffect(() => {
9832
+ React42.useEffect(() => {
9584
9833
  const id = ++seq2.current;
9585
9834
  setLoading(true);
9586
9835
  const t = setTimeout(() => {
@@ -9919,6 +10168,7 @@ function createVersionStore(initialState, options) {
9919
10168
  Dropzone,
9920
10169
  DropzoneKit,
9921
10170
  EmptyState,
10171
+ EntityRow,
9922
10172
  FeatureGate,
9923
10173
  FileChip,
9924
10174
  FileGrid,
@@ -9991,11 +10241,16 @@ function createVersionStore(initialState, options) {
9991
10241
  Tooltip,
9992
10242
  Topbar,
9993
10243
  TranscriptKit,
10244
+ TransferList,
9994
10245
  UseFeatureStatus,
9995
10246
  UseRuntimeMode,
10247
+ VIRTUAL_LIST_BUFFER_ROWS,
10248
+ VirtualList,
9996
10249
  acceptMatches,
9997
10250
  anyOfFilter,
9998
10251
  channelWeightOf,
10252
+ computeNeedMore,
10253
+ computeVirtualWindow,
9999
10254
  createVersionStore,
10000
10255
  eqFilter,
10001
10256
  extensionOf,