@flytedan/flytebot-design-system 0.6.1 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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,
@@ -2613,56 +2619,140 @@ function StepList({
2613
2619
  ] });
2614
2620
  }
2615
2621
 
2616
- // src/components/forms/Checkbox.tsx
2622
+ // src/components/data/VirtualList.tsx
2617
2623
  var React15 = __toESM(require("react"), 1);
2618
2624
  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);
2625
+ var VIRTUAL_LIST_BUFFER_ROWS = 20;
2626
+ function computeVirtualWindow(opts) {
2627
+ const { scrollTop, viewportHeight, itemHeight, itemCount, bufferRows = VIRTUAL_LIST_BUFFER_ROWS } = opts;
2628
+ if (itemCount <= 0 || itemHeight <= 0) {
2629
+ return { visibleStart: 0, visibleEnd: -1, startIndex: 0, endIndex: -1, totalHeight: 0, offsetY: 0 };
2630
+ }
2631
+ const lastPossible = itemCount - 1;
2632
+ const visibleStart = Math.min(lastPossible, Math.max(0, Math.floor(scrollTop / itemHeight)));
2633
+ const visibleRows = Math.max(1, Math.ceil(viewportHeight / itemHeight));
2634
+ const visibleEnd = Math.min(lastPossible, visibleStart + visibleRows - 1);
2635
+ const startIndex = Math.max(0, visibleStart - bufferRows);
2636
+ const endIndex = Math.min(lastPossible, visibleEnd + bufferRows);
2637
+ return {
2638
+ visibleStart,
2639
+ visibleEnd,
2640
+ startIndex,
2641
+ endIndex,
2642
+ totalHeight: itemCount * itemHeight,
2643
+ offsetY: startIndex * itemHeight
2644
+ };
2645
+ }
2646
+ function computeNeedMore(win, itemCount, bufferRows = VIRTUAL_LIST_BUFFER_ROWS) {
2647
+ if (itemCount <= 0) return { start: true, end: true };
2648
+ return {
2649
+ start: win.visibleStart <= bufferRows,
2650
+ end: itemCount - 1 - win.visibleEnd <= bufferRows
2651
+ };
2652
+ }
2653
+ function VirtualList({
2654
+ items,
2655
+ itemHeight,
2656
+ renderItem,
2657
+ onNeedMore,
2658
+ hasMore,
2659
+ loading = false,
2660
+ keyOf,
2661
+ height = 400,
2662
+ emptyState,
2663
+ className = "",
2664
+ style
2665
+ }) {
2666
+ const [scrollTop, setScrollTop] = React15.useState(0);
2667
+ const requested = React15.useRef({ start: null, end: null });
2668
+ const win = React15.useMemo(
2669
+ () => computeVirtualWindow({ scrollTop, viewportHeight: height, itemHeight, itemCount: items.length }),
2670
+ [scrollTop, height, itemHeight, items.length]
2671
+ );
2672
+ const need = React15.useMemo(() => computeNeedMore(win, items.length), [win, items.length]);
2673
+ const wantStart = need.start && hasMore?.start !== false;
2674
+ const wantEnd = need.end && hasMore?.end !== false;
2621
2675
  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
- ] });
2676
+ if (loading || !wantStart || requested.current.start === items.length) return;
2677
+ requested.current.start = items.length;
2678
+ onNeedMore("start");
2679
+ }, [wantStart, loading, items.length, onNeedMore]);
2680
+ React15.useEffect(() => {
2681
+ if (loading || !wantEnd || requested.current.end === items.length) return;
2682
+ requested.current.end = items.length;
2683
+ onNeedMore("end");
2684
+ }, [wantEnd, loading, items.length, onNeedMore]);
2685
+ if (!items.length && !loading && emptyState) {
2686
+ return /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("div", { className: ["fd-vlist", className].filter(Boolean).join(" "), style: { height, overflow: "auto", ...style }, children: emptyState });
2687
+ }
2688
+ const rows = [];
2689
+ for (let i = win.startIndex; i <= win.endIndex; i++) {
2690
+ const item = items[i];
2691
+ if (item === void 0) continue;
2692
+ rows.push(
2693
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("div", { style: { height: itemHeight, boxSizing: "border-box" }, children: renderItem(item, i) }, keyOf(item))
2694
+ );
2695
+ }
2696
+ return /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)(
2697
+ "div",
2698
+ {
2699
+ className: ["fd-vlist", className].filter(Boolean).join(" "),
2700
+ style: { height, overflowY: "auto", overflowX: "hidden", position: "relative", ...style },
2701
+ onScroll: (e) => setScrollTop(e.currentTarget.scrollTop),
2702
+ children: [
2703
+ /* @__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 }) }),
2704
+ 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
2705
+ ]
2706
+ }
2707
+ );
2634
2708
  }
2635
2709
 
2636
- // src/components/forms/Radio.tsx
2710
+ // src/components/data/EntityRow.tsx
2637
2711
  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
- ] });
2712
+ function EntityRow({ title, meta, action, draggable = false, onDragStart, onDragEnd, style, className = "" }) {
2713
+ return /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)(
2714
+ "div",
2715
+ {
2716
+ draggable,
2717
+ onDragStart,
2718
+ onDragEnd,
2719
+ className: ["fd-erow", className].filter(Boolean).join(" "),
2720
+ style: {
2721
+ display: "flex",
2722
+ alignItems: "center",
2723
+ gap: 8,
2724
+ height: "100%",
2725
+ padding: "0 8px",
2726
+ borderRadius: 6,
2727
+ cursor: draggable ? "grab" : void 0,
2728
+ ...style
2729
+ },
2730
+ children: [
2731
+ 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,
2732
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("span", { style: { flex: 1, minWidth: 0, display: "flex", flexDirection: "column", gap: 1 }, children: [
2733
+ /* @__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 }),
2734
+ 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
2735
+ ] }),
2736
+ action ? /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
2737
+ IconButton,
2738
+ {
2739
+ icon: action.icon,
2740
+ label: action.label,
2741
+ size: "sm",
2742
+ onClick: action.onClick,
2743
+ style: { color: action.tone === "add" ? "var(--ok-text)" : action.tone === "remove" ? "var(--danger-text)" : void 0 }
2744
+ }
2745
+ ) : null
2746
+ ]
2747
+ }
2748
+ );
2649
2749
  }
2650
2750
 
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
- }
2751
+ // src/components/data/TransferList.tsx
2752
+ var React16 = __toESM(require("react"), 1);
2663
2753
 
2664
2754
  // src/components/forms/Input.tsx
2665
- var import_jsx_runtime41 = require("react/jsx-runtime");
2755
+ var import_jsx_runtime40 = require("react/jsx-runtime");
2666
2756
  function Input({
2667
2757
  label,
2668
2758
  help,
@@ -2690,27 +2780,27 @@ function Input({
2690
2780
  size === "lg" ? "fd-input-lg" : "",
2691
2781
  className
2692
2782
  ].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: [
2783
+ return /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("div", { className: "fd-field", style, children: [
2784
+ label ? /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("label", { className: "fd-field-label", htmlFor: fieldId, children: [
2695
2785
  label,
2696
- required ? /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("span", { className: "fd-field-req", "aria-hidden": "true", children: "*" }) : null
2786
+ required ? /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("span", { className: "fd-field-req", "aria-hidden": "true", children: "*" }) : null
2697
2787
  ] }) : 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
2788
+ /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("div", { className: box, children: [
2789
+ 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,
2790
+ prefix ? /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("span", { className: "fd-input-affix", children: prefix }) : null,
2791
+ /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("input", { id: fieldId, disabled, style: inputStyle, "aria-invalid": error ? "true" : void 0, ...rest }),
2792
+ loading ? /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("span", { className: "fd-spinner", style: { color: "var(--text-muted)" }, "aria-label": "Loading" }) : null,
2793
+ suffix && !loading ? /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("span", { className: "fd-input-affix", children: suffix }) : null
2704
2794
  ] }),
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" }),
2795
+ error ? /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("span", { className: "fd-field-error", children: [
2796
+ /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
2707
2797
  error
2708
- ] }) : help ? /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("span", { className: "fd-field-help", children: help }) : null
2798
+ ] }) : help ? /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("span", { className: "fd-field-help", children: help }) : null
2709
2799
  ] });
2710
2800
  }
2711
2801
 
2712
2802
  // src/components/forms/SearchField.tsx
2713
- var import_jsx_runtime42 = require("react/jsx-runtime");
2803
+ var import_jsx_runtime41 = require("react/jsx-runtime");
2714
2804
  function SearchField({
2715
2805
  value,
2716
2806
  onChange,
@@ -2725,7 +2815,7 @@ function SearchField({
2725
2815
  ...rest
2726
2816
  }) {
2727
2817
  const clear = onClear || (() => onChange(""));
2728
- return /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
2818
+ return /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
2729
2819
  Input,
2730
2820
  {
2731
2821
  id,
@@ -2738,14 +2828,14 @@ function SearchField({
2738
2828
  style,
2739
2829
  className,
2740
2830
  onChange: (e) => onChange(e.target.value),
2741
- suffix: value ? /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
2831
+ suffix: value ? /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
2742
2832
  "button",
2743
2833
  {
2744
2834
  type: "button",
2745
2835
  "aria-label": "Clear search",
2746
2836
  onClick: clear,
2747
2837
  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" })
2838
+ children: /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("i", { className: "ph ph-x-circle", style: { fontSize: 15 }, "aria-hidden": "true" })
2749
2839
  }
2750
2840
  ) : void 0,
2751
2841
  ...rest
@@ -2753,27 +2843,183 @@ function SearchField({
2753
2843
  );
2754
2844
  }
2755
2845
 
2756
- // src/components/forms/Textarea.tsx
2846
+ // src/components/data/TransferList.tsx
2847
+ var import_jsx_runtime42 = require("react/jsx-runtime");
2848
+ var emptyHasMore = {};
2849
+ function TransferList({
2850
+ left,
2851
+ right,
2852
+ keyOf,
2853
+ renderLabel,
2854
+ renderMeta,
2855
+ onMove,
2856
+ itemHeight = 44,
2857
+ listHeight = 440,
2858
+ className = ""
2859
+ }) {
2860
+ const [dragging, setDragging] = React16.useState(null);
2861
+ const [dragOverSide, setDragOverSide] = React16.useState(null);
2862
+ const startDrag = (e, item, from) => {
2863
+ const key = keyOf(item);
2864
+ setDragging({ key, from });
2865
+ e.dataTransfer.effectAllowed = "move";
2866
+ e.dataTransfer.setData("text/plain", String(key));
2867
+ };
2868
+ const endDrag = () => {
2869
+ setDragging(null);
2870
+ setDragOverSide(null);
2871
+ };
2872
+ const findItem = (side, key) => (side === "left" ? left.items : right.items).find((it) => keyOf(it) === key);
2873
+ const dropOnSide = (e, side) => {
2874
+ e.preventDefault();
2875
+ setDragOverSide(null);
2876
+ if (!dragging || dragging.from === side) return;
2877
+ const item = findItem(dragging.from, dragging.key);
2878
+ if (item !== void 0) onMove(item, dragging.from, side);
2879
+ setDragging(null);
2880
+ };
2881
+ const renderSide = (side, cfg, opposite) => /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(
2882
+ "div",
2883
+ {
2884
+ style: {
2885
+ flex: 1,
2886
+ minWidth: 0,
2887
+ display: "flex",
2888
+ flexDirection: "column",
2889
+ gap: 8,
2890
+ padding: 10,
2891
+ borderRadius: 10,
2892
+ border: "1px solid " + (dragOverSide === side ? "var(--brand)" : "var(--border)"),
2893
+ background: "var(--surface)"
2894
+ },
2895
+ onDragOver: (e) => {
2896
+ if (!dragging || dragging.from === side) return;
2897
+ e.preventDefault();
2898
+ e.dataTransfer.dropEffect = "move";
2899
+ if (dragOverSide !== side) setDragOverSide(side);
2900
+ },
2901
+ onDragLeave: (e) => {
2902
+ if (e.currentTarget.contains(e.relatedTarget)) return;
2903
+ setDragOverSide((s) => s === side ? null : s);
2904
+ },
2905
+ onDrop: (e) => dropOnSide(e, side),
2906
+ children: [
2907
+ cfg.label ? /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("span", { className: "fd-overline fd-muted", children: [
2908
+ cfg.label,
2909
+ cfg.total != null ? " (" + cfg.total.toLocaleString() + ")" : ""
2910
+ ] }) : null,
2911
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("span", { className: "fd-row", style: { gap: 8 }, children: [
2912
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(SearchField, { value: cfg.search, onChange: cfg.onSearchChange, placeholder: "Search", "aria-label": (cfg.label || side) + " search", style: { flex: 1 } }),
2913
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(SortMenu, { fields: cfg.sortFields, sort: cfg.sort, onSort: cfg.onSort })
2914
+ ] }),
2915
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
2916
+ VirtualList,
2917
+ {
2918
+ items: cfg.items,
2919
+ itemHeight,
2920
+ height: listHeight,
2921
+ keyOf,
2922
+ loading: cfg.loading,
2923
+ hasMore: cfg.hasMore || emptyHasMore,
2924
+ onNeedMore: cfg.onNeedMore,
2925
+ emptyState: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(EmptyState, { icon: "tray", title: "Nothing here" }),
2926
+ renderItem: (item) => /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
2927
+ EntityRow,
2928
+ {
2929
+ title: renderLabel(item),
2930
+ meta: renderMeta ? renderMeta(item) : void 0,
2931
+ draggable: true,
2932
+ onDragStart: (e) => startDrag(e, item, side),
2933
+ onDragEnd: endDrag,
2934
+ style: { opacity: dragging && dragging.from === side && dragging.key === keyOf(item) ? 0.4 : 1 },
2935
+ action: {
2936
+ icon: side === "left" ? "plus" : "minus",
2937
+ label: (side === "left" ? "Move to " : "Move from ") + (side === "left" ? right.label || "the other list" : left.label || "the other list"),
2938
+ tone: side === "left" ? "add" : "remove",
2939
+ onClick: () => onMove(item, side, opposite)
2940
+ }
2941
+ }
2942
+ )
2943
+ }
2944
+ )
2945
+ ]
2946
+ }
2947
+ );
2948
+ return /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: ["fd-tlist", className].filter(Boolean).join(" "), style: { display: "flex", gap: 16, alignItems: "flex-start" }, children: [
2949
+ renderSide("left", left, "right"),
2950
+ renderSide("right", right, "left")
2951
+ ] });
2952
+ }
2953
+
2954
+ // src/components/forms/Checkbox.tsx
2955
+ var React17 = __toESM(require("react"), 1);
2757
2956
  var import_jsx_runtime43 = require("react/jsx-runtime");
2957
+ function Checkbox({ label, description, card = false, indeterminate = false, className = "", ...rest }) {
2958
+ const ref = React17.useRef(null);
2959
+ React17.useEffect(() => {
2960
+ if (ref.current) ref.current.indeterminate = indeterminate;
2961
+ }, [indeterminate]);
2962
+ return /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("label", { className: ["fd-choice", card ? "fd-choice-card" : "", className].filter(Boolean).join(" "), children: [
2963
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("span", { className: "fd-choice-input", children: [
2964
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("input", { ref, type: "checkbox", ...rest }),
2965
+ /* @__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" }) })
2966
+ ] }),
2967
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("span", { className: "fd-choice-text", children: [
2968
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: "fd-choice-title", children: label }),
2969
+ description ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: "fd-choice-desc", children: description }) : null
2970
+ ] })
2971
+ ] });
2972
+ }
2973
+
2974
+ // src/components/forms/Radio.tsx
2975
+ var import_jsx_runtime44 = require("react/jsx-runtime");
2976
+ function Radio({ label, description, card = false, className = "", ...rest }) {
2977
+ return /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("label", { className: ["fd-choice", card ? "fd-choice-card" : "", className].filter(Boolean).join(" "), children: [
2978
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("span", { className: "fd-choice-input", children: [
2979
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("input", { type: "radio", ...rest }),
2980
+ /* @__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" }) })
2981
+ ] }),
2982
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("span", { className: "fd-choice-text", children: [
2983
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("span", { className: "fd-choice-title", children: label }),
2984
+ description ? /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("span", { className: "fd-choice-desc", children: description }) : null
2985
+ ] })
2986
+ ] });
2987
+ }
2988
+
2989
+ // src/components/forms/Switch.tsx
2990
+ var import_jsx_runtime45 = require("react/jsx-runtime");
2991
+ function Switch({ label, description, className = "", ...rest }) {
2992
+ return /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("label", { className: ["fd-switch", className].filter(Boolean).join(" "), children: [
2993
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("input", { type: "checkbox", role: "switch", ...rest }),
2994
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("span", { className: "fd-switch-track", children: /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("span", { className: "fd-switch-thumb" }) }),
2995
+ label ? /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("span", { className: "fd-choice-text", children: [
2996
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("span", { className: "fd-switch-label", children: label }),
2997
+ description ? /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("span", { className: "fd-choice-desc", children: description }) : null
2998
+ ] }) : null
2999
+ ] });
3000
+ }
3001
+
3002
+ // src/components/forms/Textarea.tsx
3003
+ var import_jsx_runtime46 = require("react/jsx-runtime");
2758
3004
  function Textarea({ label, help, error, required = false, rows = 4, disabled = false, id, className = "", style, ...rest }) {
2759
3005
  const fieldId = id || (rest.name ? "fd-" + rest.name : void 0);
2760
3006
  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: [
3007
+ return /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: "fd-field", style, children: [
3008
+ label ? /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("label", { className: "fd-field-label", htmlFor: fieldId, children: [
2763
3009
  label,
2764
- required ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: "fd-field-req", children: "*" }) : null
3010
+ required ? /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("span", { className: "fd-field-req", children: "*" }) : null
2765
3011
  ] }) : 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" }),
3012
+ /* @__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 }) }),
3013
+ error ? /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("span", { className: "fd-field-error", children: [
3014
+ /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
2769
3015
  error
2770
- ] }) : help ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: "fd-field-help", children: help }) : null
3016
+ ] }) : help ? /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("span", { className: "fd-field-help", children: help }) : null
2771
3017
  ] });
2772
3018
  }
2773
3019
 
2774
3020
  // src/components/forms/NumberInput.tsx
2775
- var React16 = __toESM(require("react"), 1);
2776
- var import_jsx_runtime44 = require("react/jsx-runtime");
3021
+ var React18 = __toESM(require("react"), 1);
3022
+ var import_jsx_runtime47 = require("react/jsx-runtime");
2777
3023
  function NumberInput({
2778
3024
  label,
2779
3025
  help,
@@ -2797,10 +3043,10 @@ function NumberInput({
2797
3043
  const n = Number(String(v == null ? "" : v).replace(/[^0-9.-]/g, ""));
2798
3044
  return isNaN(n) ? null : n;
2799
3045
  };
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(() => {
3046
+ const [text, setText] = React18.useState(value == null || value === "" ? "" : String(value));
3047
+ const [editing, setEditing] = React18.useState(false);
3048
+ const timer = React18.useRef(null);
3049
+ React18.useEffect(() => {
2804
3050
  if (!editing) setText(value == null || value === "" ? "" : String(value));
2805
3051
  }, [value, editing]);
2806
3052
  const clamp = (n) => Math.min(max, Math.max(min, n));
@@ -2824,7 +3070,7 @@ function NumberInput({
2824
3070
  const release = () => {
2825
3071
  if (timer.current) clearTimeout(timer.current);
2826
3072
  };
2827
- React16.useEffect(() => () => {
3073
+ React18.useEffect(() => () => {
2828
3074
  if (timer.current) clearTimeout(timer.current);
2829
3075
  }, []);
2830
3076
  const shown = editing ? text : (() => {
@@ -2832,14 +3078,14 @@ function NumberInput({
2832
3078
  return n == null ? "" : format ? n.toLocaleString() : String(n);
2833
3079
  })();
2834
3080
  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: [
3081
+ return /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: ["fd-field", className].filter(Boolean).join(" "), style, children: [
3082
+ label ? /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("label", { className: "fd-field-label", children: [
2837
3083
  label,
2838
- required ? /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("span", { className: "fd-field-req", children: "*" }) : null
3084
+ required ? /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("span", { className: "fd-field-req", children: "*" }) : null
2839
3085
  ] }) : 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)(
3086
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: box, style: { gap: 8 }, children: [
3087
+ prefix ? /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("span", { className: "fd-input-affix", children: prefix }) : null,
3088
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
2843
3089
  "input",
2844
3090
  {
2845
3091
  inputMode: "numeric",
@@ -2872,9 +3118,9 @@ function NumberInput({
2872
3118
  }
2873
3119
  }
2874
3120
  ),
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)(
3121
+ suffix ? /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("span", { className: "fd-input-affix", children: suffix }) : null,
3122
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("span", { className: "fd-row", style: { gap: 4, flex: "none" }, children: [
3123
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
2878
3124
  "button",
2879
3125
  {
2880
3126
  type: "button",
@@ -2884,10 +3130,10 @@ function NumberInput({
2884
3130
  onPointerDown: () => hold(-1),
2885
3131
  onPointerUp: release,
2886
3132
  onPointerLeave: release,
2887
- children: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("i", { className: "ph ph-minus" })
3133
+ children: /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("i", { className: "ph ph-minus" })
2888
3134
  }
2889
3135
  ),
2890
- /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
3136
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
2891
3137
  "button",
2892
3138
  {
2893
3139
  type: "button",
@@ -2897,26 +3143,26 @@ function NumberInput({
2897
3143
  onPointerDown: () => hold(1),
2898
3144
  onPointerUp: release,
2899
3145
  onPointerLeave: release,
2900
- children: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("i", { className: "ph ph-plus" })
3146
+ children: /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("i", { className: "ph ph-plus" })
2901
3147
  }
2902
3148
  )
2903
3149
  ] })
2904
3150
  ] }),
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" }),
3151
+ error ? /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("span", { className: "fd-field-error", children: [
3152
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
2907
3153
  error
2908
- ] }) : help ? /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("span", { className: "fd-field-help", children: help }) : null
3154
+ ] }) : help ? /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("span", { className: "fd-field-help", children: help }) : null
2909
3155
  ] });
2910
3156
  }
2911
3157
 
2912
3158
  // src/components/forms/Select.tsx
2913
- var React17 = __toESM(require("react"), 1);
3159
+ var React19 = __toESM(require("react"), 1);
2914
3160
  var import_react_dom4 = require("react-dom");
2915
- var import_jsx_runtime45 = require("react/jsx-runtime");
3161
+ var import_jsx_runtime48 = require("react/jsx-runtime");
2916
3162
  var norm = (o) => typeof o === "string" ? { value: o, label: o } : o;
2917
3163
  function usePopPos(open, ref, estH, estW) {
2918
- const [pos, setPos] = React17.useState(null);
2919
- React17.useLayoutEffect(() => {
3164
+ const [pos, setPos] = React19.useState(null);
3165
+ React19.useLayoutEffect(() => {
2920
3166
  if (!open || !ref.current) {
2921
3167
  setPos(null);
2922
3168
  return;
@@ -2980,14 +3226,14 @@ function Select({
2980
3226
  const vals = multiple ? Array.isArray(value) ? value : value ? [value] : [] : [];
2981
3227
  const isOn = (v) => multiple ? vals.includes(v) : v === value;
2982
3228
  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 });
3229
+ const [open, setOpen] = React19.useState(false);
3230
+ const [q, setQ] = React19.useState("");
3231
+ const [active, setActive] = React19.useState(-1);
3232
+ const rootRef = React19.useRef(null);
3233
+ const boxRef = React19.useRef(null);
3234
+ const popRef = React19.useRef(null);
3235
+ const listRef = React19.useRef(null);
3236
+ const typeBuf = React19.useRef({ s: "", t: 0 });
2991
3237
  const selected = multiple ? null : opts.find((o) => o.value === value);
2992
3238
  const chosen = multiple ? opts.filter((o) => vals.includes(o.value)) : [];
2993
3239
  const pos = usePopPos(open, boxRef, hasSearch ? 390 : 340, 260);
@@ -3013,7 +3259,7 @@ function Select({
3013
3259
  }
3014
3260
  setOpen(!open);
3015
3261
  };
3016
- React17.useEffect(() => {
3262
+ React19.useEffect(() => {
3017
3263
  if (!open) return;
3018
3264
  const away = (e) => {
3019
3265
  if (rootRef.current && rootRef.current.contains(e.target)) return;
@@ -3023,7 +3269,7 @@ function Select({
3023
3269
  document.addEventListener("pointerdown", away);
3024
3270
  return () => document.removeEventListener("pointerdown", away);
3025
3271
  }, [open]);
3026
- React17.useEffect(() => {
3272
+ React19.useEffect(() => {
3027
3273
  if (!open || active < 0 || !listRef.current) return;
3028
3274
  const el = listRef.current.querySelector('[data-i="' + active + '"]');
3029
3275
  if (el) {
@@ -3077,13 +3323,13 @@ function Select({
3077
3323
  });
3078
3324
  const fieldId = id || (rest.name ? "fd-" + rest.name : void 0);
3079
3325
  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: [
3326
+ return /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("div", { className: ["fd-field", "fd-popfield", open ? "is-open" : "", className].filter(Boolean).join(" "), style, ref: rootRef, children: [
3327
+ label ? /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("label", { className: "fd-field-label", htmlFor: fieldId, onClick: toggle, children: [
3082
3328
  label,
3083
- required ? /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("span", { className: "fd-field-req", children: "*" }) : null
3329
+ required ? /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("span", { className: "fd-field-req", children: "*" }) : null
3084
3330
  ] }) : 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)(
3331
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("div", { className: box, style: { cursor: disabled ? "not-allowed" : "pointer" }, ref: boxRef, children: [
3332
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)(
3087
3333
  "button",
3088
3334
  {
3089
3335
  type: "button",
@@ -3096,13 +3342,13 @@ function Select({
3096
3342
  "aria-haspopup": "listbox",
3097
3343
  style: { all: "unset", flex: 1, minWidth: 0, display: "flex", alignItems: "center", gap: 8, cursor: "inherit", overflow: "hidden" },
3098
3344
  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
3345
+ selected && selected.icon ? /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("i", { className: "ph ph-" + selected.icon, style: { flex: "none", color: "var(--text-2)" } }) : null,
3346
+ /* @__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 }),
3347
+ 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
3348
  ]
3103
3349
  }
3104
3350
  ),
3105
- clearable && (multiple ? chosen.length > 0 : selected) && !loading ? /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
3351
+ clearable && (multiple ? chosen.length > 0 : selected) && !loading ? /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
3106
3352
  "button",
3107
3353
  {
3108
3354
  type: "button",
@@ -3112,22 +3358,22 @@ function Select({
3112
3358
  fire(multiple ? [] : "");
3113
3359
  },
3114
3360
  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 } })
3361
+ children: /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("i", { className: "ph ph-x-circle", style: { fontSize: 15 } })
3116
3362
  }
3117
3363
  ) : 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" }) })
3364
+ 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
3365
  ] }),
3120
3366
  open && pos ? (0, import_react_dom4.createPortal)(
3121
- /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)(
3367
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)(
3122
3368
  "div",
3123
3369
  {
3124
3370
  className: "fd-pop" + (pos.up ? " is-up" : ""),
3125
3371
  ref: popRef,
3126
3372
  style: popStyle(pos, { minWidth: Math.max(pos.width, 260), maxWidth: 380, zIndex: 130, overflowY: "hidden" }),
3127
3373
  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)(
3374
+ hasSearch ? /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("div", { className: "fd-pop-search", children: [
3375
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("i", { className: "ph ph-magnifying-glass", style: { color: "var(--text-muted)", fontSize: 14 } }),
3376
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
3131
3377
  "input",
3132
3378
  {
3133
3379
  autoFocus: true,
@@ -3140,15 +3386,15 @@ function Select({
3140
3386
  }
3141
3387
  }
3142
3388
  ),
3143
- q ? /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("span", { className: "fd-body-sm fd-muted", children: visible.length }) : null
3389
+ q ? /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("span", { className: "fd-body-sm fd-muted", children: visible.length }) : null
3144
3390
  ] }) : 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: [
3391
+ /* @__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
3392
  'Nothing matches "',
3147
3393
  q,
3148
3394
  '".'
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)(
3395
+ ] }) : groups.map((grp) => /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)(React19.Fragment, { children: [
3396
+ grp.g ? /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("div", { className: "fd-pop-group", children: grp.g }) : null,
3397
+ grp.items.map(({ o, i }) => /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)(
3152
3398
  "button",
3153
3399
  {
3154
3400
  type: "button",
@@ -3160,21 +3406,21 @@ function Select({
3160
3406
  onMouseEnter: () => setActive(i),
3161
3407
  onClick: () => pick(o),
3162
3408
  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
3409
+ 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,
3410
+ 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,
3411
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("span", { style: { flex: 1, minWidth: 0 }, children: [
3412
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("span", { className: "fd-opt-label", children: o.label }),
3413
+ o.description ? /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("span", { className: "fd-opt-desc", children: o.description }) : null
3168
3414
  ] }),
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 })
3415
+ o.meta ? /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("span", { className: "fd-opt-meta", children: o.meta }) : null,
3416
+ 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
3417
  ]
3172
3418
  },
3173
3419
  String(o.value)
3174
3420
  ))
3175
3421
  ] }, 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)(
3422
+ multiple ? /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("div", { className: "fd-row", style: { gap: 10, padding: "8px 12px", borderTop: "1px solid var(--border)" }, children: [
3423
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
3178
3424
  "button",
3179
3425
  {
3180
3426
  type: "button",
@@ -3183,13 +3429,13 @@ function Select({
3183
3429
  children: "Select all"
3184
3430
  }
3185
3431
  ),
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: [
3432
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("span", { style: { flex: 1 } }),
3433
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("span", { className: "fd-body-sm fd-muted", children: [
3188
3434
  vals.length,
3189
3435
  " of ",
3190
3436
  opts.length
3191
3437
  ] }),
3192
- /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
3438
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
3193
3439
  "button",
3194
3440
  {
3195
3441
  type: "button",
@@ -3205,17 +3451,17 @@ function Select({
3205
3451
  ),
3206
3452
  document.body
3207
3453
  ) : 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" }),
3454
+ error ? /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("span", { className: "fd-field-error", children: [
3455
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
3210
3456
  error
3211
- ] }) : help ? /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("span", { className: "fd-field-help", children: help }) : null
3457
+ ] }) : help ? /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("span", { className: "fd-field-help", children: help }) : null
3212
3458
  ] });
3213
3459
  }
3214
3460
 
3215
3461
  // src/components/forms/DatePicker.tsx
3216
- var React18 = __toESM(require("react"), 1);
3462
+ var React20 = __toESM(require("react"), 1);
3217
3463
  var import_react_dom5 = require("react-dom");
3218
- var import_jsx_runtime46 = require("react/jsx-runtime");
3464
+ var import_jsx_runtime49 = require("react/jsx-runtime");
3219
3465
  var MONTHS = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
3220
3466
  var DOW = ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"];
3221
3467
  var iso = (d) => d.getFullYear() + "-" + String(d.getMonth() + 1).padStart(2, "0") + "-" + String(d.getDate()).padStart(2, "0");
@@ -3229,8 +3475,8 @@ var fmt = (s) => {
3229
3475
  return d ? MONTHS[d.getMonth()].slice(0, 3) + " " + d.getDate() + ", " + d.getFullYear() : "";
3230
3476
  };
3231
3477
  function usePopPos2(open, ref, estH, estW) {
3232
- const [pos, setPos] = React18.useState(null);
3233
- React18.useLayoutEffect(() => {
3478
+ const [pos, setPos] = React20.useState(null);
3479
+ React20.useLayoutEffect(() => {
3234
3480
  if (!open || !ref.current) {
3235
3481
  setPos(null);
3236
3482
  return;
@@ -3274,10 +3520,10 @@ function Calendar({ value, range = false, onPick, initialMonth, months = 1 }) {
3274
3520
  const today = /* @__PURE__ */ new Date();
3275
3521
  const sel = range ? value || {} : { start: value, end: value };
3276
3522
  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);
3523
+ const [vy, setVy] = React20.useState(anchor.getFullYear());
3524
+ const [vm, setVm] = React20.useState(anchor.getMonth());
3525
+ const [mode2, setMode] = React20.useState("days");
3526
+ const [hover, setHover] = React20.useState(null);
3281
3527
  const s = parse(sel.start), e = parse(sel.end);
3282
3528
  const hoverEnd = range && s && !e && hover ? parse(hover) : null;
3283
3529
  const inRange = (d) => {
@@ -3314,9 +3560,9 @@ function Calendar({ value, range = false, onPick, initialMonth, months = 1 }) {
3314
3560
  const startPad = new Date(y, m, 1).getDay();
3315
3561
  const cells = [];
3316
3562
  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)(
3563
+ return /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("div", { className: "fd-cal-grid", style: { width: months > 1 ? 252 : "auto", flex: "none" }, onMouseLeave: () => setHover(null), children: [
3564
+ DOW.map((d) => /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("span", { className: "fd-cal-dow", children: d }, d)),
3565
+ cells.map((d, i) => /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(
3320
3566
  "button",
3321
3567
  {
3322
3568
  type: "button",
@@ -3330,20 +3576,20 @@ function Calendar({ value, range = false, onPick, initialMonth, months = 1 }) {
3330
3576
  ] });
3331
3577
  };
3332
3578
  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: [
3579
+ return /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("div", { className: "fd-cal", style: { width: months > 1 && mode2 === "days" ? "auto" : void 0 }, children: [
3580
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("div", { className: "fd-cal-head", children: [
3581
+ /* @__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" }) }),
3582
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("button", { type: "button", className: "fd-cal-title", onClick: () => setMode(mode2 === "days" ? "months" : mode2 === "months" ? "years" : "days"), children: [
3337
3583
  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)" } })
3584
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("i", { className: "ph ph-caret-down", style: { fontSize: 10, marginLeft: 6, color: "var(--text-muted)" } })
3339
3585
  ] }),
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" }) })
3586
+ 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,
3587
+ /* @__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
3588
  ] }),
3343
- mode2 === "days" ? /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { style: { display: "flex", gap: 18 }, children: [
3589
+ mode2 === "days" ? /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("div", { style: { display: "flex", gap: 18 }, children: [
3344
3590
  monthGrid(vy, vm),
3345
3591
  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)(
3592
+ ] }) : 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
3593
  "button",
3348
3594
  {
3349
3595
  type: "button",
@@ -3355,7 +3601,7 @@ function Calendar({ value, range = false, onPick, initialMonth, months = 1 }) {
3355
3601
  children: m.slice(0, 3)
3356
3602
  },
3357
3603
  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)(
3604
+ )) }) : /* @__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
3605
  "button",
3360
3606
  {
3361
3607
  type: "button",
@@ -3368,8 +3614,8 @@ function Calendar({ value, range = false, onPick, initialMonth, months = 1 }) {
3368
3614
  },
3369
3615
  y
3370
3616
  )) }),
3371
- /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: "fd-cal-foot", children: [
3372
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
3617
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("div", { className: "fd-cal-foot", children: [
3618
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(
3373
3619
  "button",
3374
3620
  {
3375
3621
  type: "button",
@@ -3383,8 +3629,8 @@ function Calendar({ value, range = false, onPick, initialMonth, months = 1 }) {
3383
3629
  children: "Today"
3384
3630
  }
3385
3631
  ),
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: [
3632
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("span", { style: { flex: 1 } }),
3633
+ range && sel.start ? /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("span", { className: "fd-body-sm fd-muted", children: [
3388
3634
  fmt(sel.start),
3389
3635
  sel.end ? " \u2192 " + fmt(sel.end) : " \u2192 pick an end"
3390
3636
  ] }) : null
@@ -3392,12 +3638,12 @@ function Calendar({ value, range = false, onPick, initialMonth, months = 1 }) {
3392
3638
  ] });
3393
3639
  }
3394
3640
  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);
3641
+ const [open, setOpen] = React20.useState(false);
3642
+ const rootRef = React20.useRef(null);
3643
+ const boxRef = React20.useRef(null);
3644
+ const popRef = React20.useRef(null);
3399
3645
  const pos = usePopPos2(open, boxRef, 430, range ? 600 : 316);
3400
- React18.useEffect(() => {
3646
+ React20.useEffect(() => {
3401
3647
  if (!open) return;
3402
3648
  const away = (e) => {
3403
3649
  if (rootRef.current && rootRef.current.contains(e.target)) return;
@@ -3418,14 +3664,14 @@ function DatePicker({ label, help, error, required = false, disabled = false, ra
3418
3664
  const toggle = () => {
3419
3665
  if (!disabled) setOpen(!open);
3420
3666
  };
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: [
3667
+ return /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("div", { className: ["fd-field", "fd-popfield", open ? "is-open" : "", className].filter(Boolean).join(" "), style, ref: rootRef, children: [
3668
+ label ? /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("label", { className: "fd-field-label", onClick: toggle, children: [
3423
3669
  label,
3424
- required ? /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("span", { className: "fd-field-req", children: "*" }) : null
3670
+ required ? /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("span", { className: "fd-field-req", children: "*" }) : null
3425
3671
  ] }) : 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)(
3672
+ /* @__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: [
3673
+ /* @__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" }) }),
3674
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(
3429
3675
  "button",
3430
3676
  {
3431
3677
  type: "button",
@@ -3441,10 +3687,10 @@ function DatePicker({ label, help, error, required = false, disabled = false, ra
3441
3687
  children: display || placeholder || (range ? "Pick a date range" : "Pick a date")
3442
3688
  }
3443
3689
  ),
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" }) })
3690
+ /* @__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
3691
  ] }),
3446
3692
  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)(
3693
+ /* @__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
3694
  Calendar,
3449
3695
  {
3450
3696
  range,
@@ -3458,21 +3704,21 @@ function DatePicker({ label, help, error, required = false, disabled = false, ra
3458
3704
  ) }),
3459
3705
  document.body
3460
3706
  ) : 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" }),
3707
+ error ? /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("span", { className: "fd-field-error", children: [
3708
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
3463
3709
  error
3464
- ] }) : help ? /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("span", { className: "fd-field-help", children: help }) : null
3710
+ ] }) : help ? /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("span", { className: "fd-field-help", children: help }) : null
3465
3711
  ] });
3466
3712
  }
3467
3713
 
3468
3714
  // src/components/forms/TimePicker.tsx
3469
- var React19 = __toESM(require("react"), 1);
3715
+ var React21 = __toESM(require("react"), 1);
3470
3716
  var import_react_dom6 = require("react-dom");
3471
- var import_jsx_runtime47 = require("react/jsx-runtime");
3717
+ var import_jsx_runtime50 = require("react/jsx-runtime");
3472
3718
  var pad = (n) => String(n).padStart(2, "0");
3473
3719
  function usePopPos3(open, ref, estH, estW) {
3474
- const [pos, setPos] = React19.useState(null);
3475
- React19.useLayoutEffect(() => {
3720
+ const [pos, setPos] = React21.useState(null);
3721
+ React21.useLayoutEffect(() => {
3476
3722
  if (!open || !ref.current) {
3477
3723
  setPos(null);
3478
3724
  return;
@@ -3518,9 +3764,9 @@ function ClockFace({ value = "09:00", onChange }) {
3518
3764
  if (isNaN(m)) m = 0;
3519
3765
  const pm = h24 >= 12;
3520
3766
  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);
3767
+ const [mode2, setMode] = React21.useState("h");
3768
+ const faceRef = React21.useRef(null);
3769
+ const dragging = React21.useRef(false);
3524
3770
  const set = (h, mm, isPm) => onChange((isPm ? h % 12 + 12 : h % 12) + ":" + pad(mm));
3525
3771
  const R = 108, NR = 80;
3526
3772
  const nums = mode2 === "h" ? Array.from({ length: 12 }, (_, i) => i + 1) : Array.from({ length: 12 }, (_, i) => i * 5);
@@ -3555,12 +3801,12 @@ function ClockFace({ value = "09:00", onChange }) {
3555
3801
  };
3556
3802
  const handAngle = mode2 === "h" ? h12 % 12 * 30 : m * 6;
3557
3803
  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)(
3804
+ return /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)("div", { style: { padding: "4px 14px 14px" }, children: [
3805
+ /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)("div", { className: "fd-clock-digits", children: [
3806
+ /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("button", { type: "button", className: "fd-clock-digit" + (mode2 === "h" ? " is-active" : ""), onClick: () => setMode("h"), children: pad(h12) }),
3807
+ /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("span", { style: { fontSize: 24, fontWeight: 700, color: "var(--text-muted)" }, children: ":" }),
3808
+ /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("button", { type: "button", className: "fd-clock-digit" + (mode2 === "m" ? " is-active" : ""), onClick: () => setMode("m"), children: pad(m) }),
3809
+ /* @__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
3810
  "button",
3565
3811
  {
3566
3812
  type: "button",
@@ -3571,13 +3817,13 @@ function ClockFace({ value = "09:00", onChange }) {
3571
3817
  ap
3572
3818
  )) })
3573
3819
  ] }),
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,
3820
+ /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)("div", { className: "fd-clock", ref: faceRef, onPointerDown: down, onPointerMove: move, onPointerUp: upH, children: [
3821
+ /* @__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%" } }),
3822
+ /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("span", { className: "fd-clock-pivot" }),
3823
+ 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
3824
  nums.map((n) => {
3579
3825
  const a = angleOf(n) * Math.PI / 180;
3580
- return /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
3826
+ return /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(
3581
3827
  "span",
3582
3828
  {
3583
3829
  className: "fd-clock-num" + (n === selNum || mode2 === "m" && n === Math.round(m / 5) * 5 % 60 && m % 5 === 0 ? " is-sel" : ""),
@@ -3588,16 +3834,16 @@ function ClockFace({ value = "09:00", onChange }) {
3588
3834
  );
3589
3835
  })
3590
3836
  ] }),
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" }) })
3837
+ /* @__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
3838
  ] });
3593
3839
  }
3594
3840
  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);
3841
+ const [open, setOpen] = React21.useState(false);
3842
+ const rootRef = React21.useRef(null);
3843
+ const boxRef = React21.useRef(null);
3844
+ const popRef = React21.useRef(null);
3599
3845
  const pos = usePopPos3(open, boxRef, 420, 262);
3600
- React19.useEffect(() => {
3846
+ React21.useEffect(() => {
3601
3847
  if (!open) return;
3602
3848
  const away = (e) => {
3603
3849
  if (rootRef.current && rootRef.current.contains(e.target)) return;
@@ -3622,14 +3868,14 @@ function TimePicker({ label, help, error, required = false, disabled = false, va
3622
3868
  const toggle = () => {
3623
3869
  if (!disabled) setOpen(!open);
3624
3870
  };
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: [
3871
+ return /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)("div", { className: ["fd-field", "fd-popfield", open ? "is-open" : "", className].filter(Boolean).join(" "), style, ref: rootRef, children: [
3872
+ label ? /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)("label", { className: "fd-field-label", onClick: toggle, children: [
3627
3873
  label,
3628
- required ? /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("span", { className: "fd-field-req", children: "*" }) : null
3874
+ required ? /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("span", { className: "fd-field-req", children: "*" }) : null
3629
3875
  ] }) : 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)(
3876
+ /* @__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: [
3877
+ /* @__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" }) }),
3878
+ /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(
3633
3879
  "button",
3634
3880
  {
3635
3881
  type: "button",
@@ -3644,13 +3890,13 @@ function TimePicker({ label, help, error, required = false, disabled = false, va
3644
3890
  children: disp() || placeholder
3645
3891
  }
3646
3892
  ),
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" }) })
3893
+ /* @__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
3894
  ] }),
3649
3895
  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)(
3896
+ /* @__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: [
3897
+ /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(ClockFace, { value: value || "09:00", onChange: (v) => onChange && onChange({ target: { value: v } }) }),
3898
+ /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)("div", { className: "fd-cal-foot", style: { margin: "0 14px 12px", paddingTop: 10 }, children: [
3899
+ /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(
3654
3900
  "button",
3655
3901
  {
3656
3902
  type: "button",
@@ -3663,22 +3909,22 @@ function TimePicker({ label, help, error, required = false, disabled = false, va
3663
3909
  children: "Now"
3664
3910
  }
3665
3911
  ),
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" })
3912
+ /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("span", { style: { flex: 1 } }),
3913
+ /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("button", { type: "button", className: "fd-btn fd-btn-primary fd-btn-sm", onClick: () => setOpen(false), children: "Done" })
3668
3914
  ] })
3669
3915
  ] }),
3670
3916
  document.body
3671
3917
  ) : 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" }),
3918
+ error ? /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)("span", { className: "fd-field-error", children: [
3919
+ /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
3674
3920
  error
3675
- ] }) : help ? /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("span", { className: "fd-field-help", children: help }) : null
3921
+ ] }) : help ? /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("span", { className: "fd-field-help", children: help }) : null
3676
3922
  ] });
3677
3923
  }
3678
3924
 
3679
3925
  // src/components/forms/Slider.tsx
3680
- var React20 = __toESM(require("react"), 1);
3681
- var import_jsx_runtime48 = require("react/jsx-runtime");
3926
+ var React22 = __toESM(require("react"), 1);
3927
+ var import_jsx_runtime51 = require("react/jsx-runtime");
3682
3928
  function Slider({
3683
3929
  label,
3684
3930
  min = 0,
@@ -3692,18 +3938,18 @@ function Slider({
3692
3938
  className = "",
3693
3939
  ...rest
3694
3940
  }) {
3695
- const [dragging, setDragging] = React20.useState(false);
3941
+ const [dragging, setDragging] = React22.useState(false);
3696
3942
  const v = value === void 0 ? min : Number(value);
3697
3943
  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) })
3944
+ return /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)("div", { className: ["fd-field", className].filter(Boolean).join(" "), children: [
3945
+ label ? /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)("div", { className: "fd-row", style: { justifyContent: "space-between", gap: 12 }, children: [
3946
+ /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("span", { className: "fd-field-label", children: label }),
3947
+ /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("span", { className: "fd-num", style: { color: "var(--text-2)" }, children: format(v) })
3702
3948
  ] }) : 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)(
3949
+ /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)("div", { className: "fd-slider", children: [
3950
+ /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("span", { className: "fd-slider-fill", style: { width: pct + "%" } }),
3951
+ showChip && dragging ? /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("span", { className: "fd-slider-chip", style: { left: pct + "%" }, children: format(v) }) : null,
3952
+ /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(
3707
3953
  "input",
3708
3954
  {
3709
3955
  type: "range",
@@ -3720,13 +3966,13 @@ function Slider({
3720
3966
  }
3721
3967
  )
3722
3968
  ] }),
3723
- help ? /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("span", { className: "fd-field-help", children: help }) : null
3969
+ help ? /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("span", { className: "fd-field-help", children: help }) : null
3724
3970
  ] });
3725
3971
  }
3726
3972
 
3727
3973
  // src/components/forms/RangeSlider.tsx
3728
- var React21 = __toESM(require("react"), 1);
3729
- var import_jsx_runtime49 = require("react/jsx-runtime");
3974
+ var React23 = __toESM(require("react"), 1);
3975
+ var import_jsx_runtime52 = require("react/jsx-runtime");
3730
3976
  function RangeSlider({
3731
3977
  label,
3732
3978
  min = 0,
@@ -3745,9 +3991,9 @@ function RangeSlider({
3745
3991
  }) {
3746
3992
  const fmt2 = format || ((v) => String(v));
3747
3993
  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);
3994
+ const [drag, setDrag] = React23.useState(null);
3995
+ const [focus, setFocus] = React23.useState(null);
3996
+ const railRef = React23.useRef(null);
3751
3997
  const pct = (v) => max === min ? 0 : (v - min) / (max - min) * 100;
3752
3998
  const clampPair = (i, v) => {
3753
3999
  v = Math.min(max, Math.max(min, Math.round(v / step) * step));
@@ -3762,7 +4008,7 @@ function RangeSlider({
3762
4008
  const r = railRef.current.getBoundingClientRect();
3763
4009
  return min + Math.min(1, Math.max(0, (e.clientX - r.left) / r.width)) * (max - min);
3764
4010
  };
3765
- React21.useEffect(() => {
4011
+ React23.useEffect(() => {
3766
4012
  if (drag === null) return;
3767
4013
  const mv = (e) => onChange && onChange(clampPair(drag, fromEvent(e)));
3768
4014
  const upH = () => setDrag(null);
@@ -3783,7 +4029,7 @@ function RangeSlider({
3783
4029
  };
3784
4030
  const thin = S.length > 7 ? Math.ceil(S.length / 5) : 1;
3785
4031
  const pair = value || [S[0].value, S[S.length - 1].value];
3786
- return /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(
4032
+ return /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(
3787
4033
  RangeSlider,
3788
4034
  {
3789
4035
  ...rest,
@@ -3831,23 +4077,23 @@ function RangeSlider({
3831
4077
  };
3832
4078
  const showChip = (i) => drag === i || focus === i;
3833
4079
  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: [
4080
+ return /* @__PURE__ */ (0, import_jsx_runtime52.jsxs)("div", { className: ["fd-field", className].filter(Boolean).join(" "), ...rest, children: [
4081
+ label ? /* @__PURE__ */ (0, import_jsx_runtime52.jsxs)("div", { className: "fd-row", style: { justifyContent: "space-between", gap: 12 }, children: [
4082
+ /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("span", { className: "fd-field-label", children: label }),
4083
+ /* @__PURE__ */ (0, import_jsx_runtime52.jsxs)("span", { className: "fd-num", style: { color: "var(--text-2)" }, children: [
3838
4084
  fmt2(a),
3839
4085
  " \u2013 ",
3840
4086
  fmt2(b)
3841
4087
  ] })
3842
4088
  ] }) : 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
4089
+ /* @__PURE__ */ (0, import_jsx_runtime52.jsxs)("div", { className: "fd-range" + (hasLabels ? " has-labels" : ""), onPointerDown: onRailDown, children: [
4090
+ /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("span", { className: "fd-range-rail", ref: railRef }),
4091
+ /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("span", { className: "fd-range-fill", style: { left: pct(a) + "%", width: pct(b) - pct(a) + "%" } }),
4092
+ marks.map((m) => /* @__PURE__ */ (0, import_jsx_runtime52.jsxs)(React23.Fragment, { children: [
4093
+ /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("span", { className: "fd-range-mark" + (m.value >= a && m.value <= b ? " is-in" : ""), style: { left: pct(m.value) + "%" } }),
4094
+ m.label ? /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("span", { className: "fd-range-mark-label", style: { left: pct(m.value) + "%" }, children: m.label }) : null
3849
4095
  ] }, m.value)),
3850
- [a, b].map((v, i) => /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(
4096
+ [a, b].map((v, i) => /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(
3851
4097
  "span",
3852
4098
  {
3853
4099
  className: "fd-range-thumb" + (drag === i ? " is-drag" : ""),
@@ -3862,18 +4108,18 @@ function RangeSlider({
3862
4108
  onKeyDown: key(i),
3863
4109
  onFocus: () => setFocus(i),
3864
4110
  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) })
4111
+ children: /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("span", { className: "fd-range-chip", style: { opacity: showChip(i) ? 1 : void 0 }, children: fmt2(v) })
3866
4112
  },
3867
4113
  i
3868
4114
  ))
3869
4115
  ] }),
3870
- help ? /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("span", { className: "fd-field-help", children: help }) : null
4116
+ help ? /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("span", { className: "fd-field-help", children: help }) : null
3871
4117
  ] });
3872
4118
  }
3873
4119
 
3874
4120
  // src/components/forms/Dropzone.tsx
3875
- var React22 = __toESM(require("react"), 1);
3876
- var import_jsx_runtime50 = require("react/jsx-runtime");
4121
+ var React24 = __toESM(require("react"), 1);
4122
+ var import_jsx_runtime53 = require("react/jsx-runtime");
3877
4123
  function Dropzone({
3878
4124
  onFiles,
3879
4125
  onReject,
@@ -3887,8 +4133,8 @@ function Dropzone({
3887
4133
  className = "",
3888
4134
  style
3889
4135
  }) {
3890
- const [over, setOver] = React22.useState(false);
3891
- const depth = React22.useRef(0);
4136
+ const [over, setOver] = React24.useState(false);
4137
+ const depth = React24.useRef(0);
3892
4138
  const has = (e) => {
3893
4139
  const dt = e.dataTransfer;
3894
4140
  if (!dt) return false;
@@ -3918,7 +4164,7 @@ function Dropzone({
3918
4164
  if (rejected.length && onReject) onReject(rejected);
3919
4165
  if (accepted.length && onFiles) onFiles(accepted);
3920
4166
  };
3921
- return /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)(
4167
+ return /* @__PURE__ */ (0, import_jsx_runtime53.jsxs)(
3922
4168
  "div",
3923
4169
  {
3924
4170
  className: ["fd-dropzone", over ? "is-over" : "", className].filter(Boolean).join(" "),
@@ -3929,10 +4175,10 @@ function Dropzone({
3929
4175
  onDrop: drop,
3930
4176
  children: [
3931
4177
  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
4178
+ 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: [
4179
+ /* @__PURE__ */ (0, import_jsx_runtime53.jsx)("i", { className: "ph ph-tray-arrow-down" }),
4180
+ /* @__PURE__ */ (0, import_jsx_runtime53.jsx)("span", { className: "fd-dropzone-label", children: label }),
4181
+ hint ? /* @__PURE__ */ (0, import_jsx_runtime53.jsx)("span", { className: "fd-dropzone-hint", children: hint }) : null
3936
4182
  ] }) }) : null
3937
4183
  ]
3938
4184
  }
@@ -3950,9 +4196,9 @@ function FilePickButton({
3950
4196
  className = "",
3951
4197
  children
3952
4198
  }) {
3953
- const ref = React22.useRef(null);
3954
- return /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)(React22.Fragment, { children: [
3955
- /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(
4199
+ const ref = React24.useRef(null);
4200
+ return /* @__PURE__ */ (0, import_jsx_runtime53.jsxs)(React24.Fragment, { children: [
4201
+ /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(
3956
4202
  "button",
3957
4203
  {
3958
4204
  type: "button",
@@ -3961,10 +4207,10 @@ function FilePickButton({
3961
4207
  "aria-label": label,
3962
4208
  title: label,
3963
4209
  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" })
4210
+ children: children != null ? children : /* @__PURE__ */ (0, import_jsx_runtime53.jsx)("i", { className: "ph ph-" + icon, "aria-hidden": "true" })
3965
4211
  }
3966
4212
  ),
3967
- /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(
4213
+ /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(
3968
4214
  "input",
3969
4215
  {
3970
4216
  ref,
@@ -3984,10 +4230,10 @@ function FilePickButton({
3984
4230
  }
3985
4231
  function useStagedFiles(upload, opts) {
3986
4232
  const o = opts || {};
3987
- const [items, setItems] = React22.useState([]);
3988
- const controllers = React22.useRef({});
4233
+ const [items, setItems] = React24.useState([]);
4234
+ const controllers = React24.useRef({});
3989
4235
  const patch = (id, next) => setItems((list) => list.map((f) => f.id === id ? Object.assign({}, f, next) : f));
3990
- const run = React22.useCallback((att) => {
4236
+ const run = React24.useCallback((att) => {
3991
4237
  if (!upload) return;
3992
4238
  const ac = typeof AbortController !== "undefined" ? new AbortController() : null;
3993
4239
  controllers.current[att.id] = ac;
@@ -4004,14 +4250,14 @@ function useStagedFiles(upload, opts) {
4004
4250
  delete controllers.current[att.id];
4005
4251
  });
4006
4252
  }, [upload]);
4007
- const add = React22.useCallback((files) => {
4253
+ const add = React24.useCallback((files) => {
4008
4254
  if (!upload) return [];
4009
4255
  const atts = Array.from(files).map((f) => toAttachment(f));
4010
4256
  setItems((list) => list.concat(atts));
4011
4257
  atts.forEach(run);
4012
4258
  return atts;
4013
4259
  }, [upload, run]);
4014
- const remove = React22.useCallback((att) => {
4260
+ const remove = React24.useCallback((att) => {
4015
4261
  const ac = controllers.current[att.id];
4016
4262
  if (ac) {
4017
4263
  try {
@@ -4022,10 +4268,10 @@ function useStagedFiles(upload, opts) {
4022
4268
  }
4023
4269
  setItems((list) => list.filter((f) => f.id !== att.id));
4024
4270
  }, []);
4025
- const retry = React22.useCallback((att) => {
4271
+ const retry = React24.useCallback((att) => {
4026
4272
  run(att);
4027
4273
  }, [run]);
4028
- const clear = React22.useCallback(() => {
4274
+ const clear = React24.useCallback(() => {
4029
4275
  Object.values(controllers.current).forEach((ac) => {
4030
4276
  try {
4031
4277
  ac && ac.abort();
@@ -4041,7 +4287,7 @@ function useStagedFiles(upload, opts) {
4041
4287
  var DropzoneKit = { useStagedFiles };
4042
4288
 
4043
4289
  // src/components/forms/FileGrid.tsx
4044
- var import_jsx_runtime51 = require("react/jsx-runtime");
4290
+ var import_jsx_runtime54 = require("react/jsx-runtime");
4045
4291
  var truncateMiddle = (name, max = 34) => {
4046
4292
  if (!name || name.length <= max) return name;
4047
4293
  const ext = /\.[A-Za-z0-9]+$/.exec(name);
@@ -4050,7 +4296,7 @@ var truncateMiddle = (name, max = 34) => {
4050
4296
  return head + "\u2026" + tail;
4051
4297
  };
4052
4298
  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)) + "%" } }) });
4299
+ 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
4300
  }
4055
4301
  function FileChip({ file, onOpen, onRemove, onRetry, compact: compact3 = false, className = "" }) {
4056
4302
  if (!file) return null;
@@ -4059,8 +4305,8 @@ function FileChip({ file, onOpen, onRemove, onRetry, compact: compact3 = false,
4059
4305
  const thumb = file.thumb && file.thumb.url || (image ? file.blobUrl || file.url : null);
4060
4306
  const meta = file.meta || (file.size ? formatBytes(file.size) : "");
4061
4307
  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)(
4308
+ 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: [
4309
+ /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)(
4064
4310
  "button",
4065
4311
  {
4066
4312
  type: "button",
@@ -4069,16 +4315,16 @@ function FileChip({ file, onOpen, onRemove, onRetry, compact: compact3 = false,
4069
4315
  onClick: clickable ? () => onOpen(file) : void 0,
4070
4316
  title: file.name + (meta ? " \xB7 " + meta : ""),
4071
4317
  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
4318
+ /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("span", { className: "fd-file-icon", children: [
4319
+ 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" }),
4320
+ (file.mime || "").startsWith("video/") ? /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("i", { className: "ph ph-play fd-file-play", "aria-hidden": "true" }) : null
4075
4321
  ] }),
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" }),
4322
+ /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("span", { className: "fd-file-text", children: [
4323
+ /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("span", { className: "fd-file-name", children: truncateMiddle(file.name, compact3 ? 26 : 40) }),
4324
+ /* @__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: [
4325
+ /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
4080
4326
  file.error
4081
- ] }) : uploading ? /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)("span", { className: "fd-tabular", children: [
4327
+ ] }) : uploading ? /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("span", { className: "fd-tabular", children: [
4082
4328
  Math.round(file.progress),
4083
4329
  "% uploaded"
4084
4330
  ] }) : meta })
@@ -4086,29 +4332,29 @@ function FileChip({ file, onOpen, onRemove, onRetry, compact: compact3 = false,
4086
4332
  ]
4087
4333
  }
4088
4334
  ),
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
4335
+ uploading ? /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(Progress, { value: file.progress }) : null,
4336
+ 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,
4337
+ 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
4338
  ] });
4093
4339
  }
4094
4340
  function FileTile({ file, onOpen, onRemove, maxHeight = 200, className = "" }) {
4095
4341
  if (!file) return null;
4096
4342
  const src = file.thumb && file.thumb.url || file.blobUrl || file.url;
4097
4343
  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" }),
4344
+ return /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("figure", { className: ["fd-tile", uploading ? "is-uploading" : "", file.error ? "is-error" : "", className].filter(Boolean).join(" "), children: [
4345
+ /* @__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" }) }) }),
4346
+ uploading ? /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(Progress, { value: file.progress }) : null,
4347
+ file.error ? /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("figcaption", { className: "fd-tile-err", children: [
4348
+ /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
4103
4349
  file.error
4104
4350
  ] }) : 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
4351
+ 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
4352
  ] });
4107
4353
  }
4108
4354
  function FileStrip({ files = [], size = 68, onOpen, onRemove, onRetry, className = "" }) {
4109
4355
  const list = files.filter(Boolean);
4110
4356
  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)) });
4357
+ 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
4358
  }
4113
4359
  var shortName = (name, keep = 5) => {
4114
4360
  const s = String(name || "file");
@@ -4122,19 +4368,19 @@ function FileCell({ file, onOpen, onRemove, onRetry }) {
4122
4368
  const image = isImage(file.mime, file.name);
4123
4369
  const thumb = file.thumb && file.thumb.url || (image ? file.blobUrl || file.url : null);
4124
4370
  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) })
4371
+ 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: [
4372
+ /* @__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: [
4373
+ thumb ? /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("img", { src: thumb, alt: "" }) : /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("span", { className: "fd-cell-doc", children: [
4374
+ /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("i", { className: "ph ph-" + iconForMime(file.mime, file.name), "aria-hidden": "true" }),
4375
+ /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("span", { className: "fd-cell-name", children: shortName(file.name) }),
4376
+ /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("span", { className: "fd-cell-size", children: file.meta || formatBytes(file.size) })
4131
4377
  ] }),
4132
- (file.mime || "").startsWith("video/") ? /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("i", { className: "ph ph-play fd-cell-play", "aria-hidden": "true" }) : null
4378
+ (file.mime || "").startsWith("video/") ? /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("i", { className: "ph ph-play fd-cell-play", "aria-hidden": "true" }) : null
4133
4379
  ] }),
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
4380
+ uploading ? /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(Progress, { value: file.progress }) : null,
4381
+ 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,
4382
+ 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,
4383
+ 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
4384
  ] });
4139
4385
  }
4140
4386
  function FileGrid({ files = [], onOpen, onRemove, onRetry, tiles = true, maxHeight = 200, compact: compact3 = false, className = "" }) {
@@ -4142,15 +4388,15 @@ function FileGrid({ files = [], onOpen, onRemove, onRetry, tiles = true, maxHeig
4142
4388
  if (!list.length) return null;
4143
4389
  const pics = tiles ? list.filter((f) => isImage(f.mime, f.name)) : [];
4144
4390
  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
4391
+ return /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("div", { className: ["fd-filegrid", className].filter(Boolean).join(" "), children: [
4392
+ 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,
4393
+ 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
4394
  ] });
4149
4395
  }
4150
4396
 
4151
4397
  // src/components/forms/MarkdownEditor.tsx
4152
- var React23 = __toESM(require("react"), 1);
4153
- var import_jsx_runtime52 = require("react/jsx-runtime");
4398
+ var React25 = __toESM(require("react"), 1);
4399
+ var import_jsx_runtime55 = require("react/jsx-runtime");
4154
4400
  var isMac = typeof navigator !== "undefined" && /Mac|iPhone|iPad/.test(navigator.platform || navigator.userAgent || "");
4155
4401
  var INLINE_RE = /(\*\*\*[^*\n]+\*\*\*|\*\*[^*\n]+\*\*|__[^_\n]+__|~~[^~\n]+~~|`[^`\n]+`|\*[^*\s][^*\n]*\*|(?<![A-Za-z0-9_])_[^_\s][^_\n]*_|\[[^\]\n]*\]\([^)\s\n]*\)|https?:\/\/\S+)/g;
4156
4402
  function inlineParts(text) {
@@ -4363,7 +4609,7 @@ function syncDom(root, value) {
4363
4609
  while (root.children.length > lines.length) root.removeChild(root.lastChild);
4364
4610
  }
4365
4611
  var LIST_CONT = RE_LI;
4366
- var MarkdownEditor = React23.forwardRef(function MarkdownEditor2({
4612
+ var MarkdownEditor = React25.forwardRef(function MarkdownEditor2({
4367
4613
  value = "",
4368
4614
  onChange,
4369
4615
  onSubmit,
@@ -4382,10 +4628,10 @@ var MarkdownEditor = React23.forwardRef(function MarkdownEditor2({
4382
4628
  className = "",
4383
4629
  id
4384
4630
  }, ref) {
4385
- const boxRef = React23.useRef(null);
4386
- const composing = React23.useRef(false);
4387
- const pendingCaret = React23.useRef(null);
4388
- React23.useLayoutEffect(() => {
4631
+ const boxRef = React25.useRef(null);
4632
+ const composing = React25.useRef(false);
4633
+ const pendingCaret = React25.useRef(null);
4634
+ React25.useLayoutEffect(() => {
4389
4635
  const root = boxRef.current;
4390
4636
  if (!root || composing.current) return;
4391
4637
  const active = document.activeElement === root || root.contains(document.activeElement);
@@ -4394,7 +4640,7 @@ var MarkdownEditor = React23.forwardRef(function MarkdownEditor2({
4394
4640
  pendingCaret.current = null;
4395
4641
  if (active && caret != null) placeCaret(root, caret);
4396
4642
  }, [value]);
4397
- React23.useEffect(() => {
4643
+ React25.useEffect(() => {
4398
4644
  if (autoFocus && boxRef.current) boxRef.current.focus();
4399
4645
  }, [autoFocus]);
4400
4646
  const caretNow = () => {
@@ -4461,7 +4707,7 @@ var MarkdownEditor = React23.forwardRef(function MarkdownEditor2({
4461
4707
  api.replaceRange(from, to, next, from + next.length);
4462
4708
  }
4463
4709
  };
4464
- React23.useImperativeHandle(ref, () => api);
4710
+ React25.useImperativeHandle(ref, () => api);
4465
4711
  function detect(text, caret) {
4466
4712
  if (!onTrigger) return;
4467
4713
  const upto = text.slice(0, caret);
@@ -4574,8 +4820,8 @@ var MarkdownEditor = React23.forwardRef(function MarkdownEditor2({
4574
4820
  api.replaceRange(s.start, s.end, text.replace(/\r\n?/g, "\n"));
4575
4821
  };
4576
4822
  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)(
4823
+ return /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)("div", { className: ["fd-rme-wrap", disabled ? "is-disabled" : "", className].filter(Boolean).join(" "), children: [
4824
+ /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(
4579
4825
  "div",
4580
4826
  {
4581
4827
  ref: boxRef,
@@ -4608,15 +4854,15 @@ var MarkdownEditor = React23.forwardRef(function MarkdownEditor2({
4608
4854
  }
4609
4855
  }
4610
4856
  ),
4611
- !value ? /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("span", { className: "fd-rme-ph", "aria-hidden": "true", children: placeholder }) : null
4857
+ !value ? /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("span", { className: "fd-rme-ph", "aria-hidden": "true", children: placeholder }) : null
4612
4858
  ] });
4613
4859
  });
4614
4860
 
4615
4861
  // src/components/platform/AccountMenu.tsx
4616
- var React25 = __toESM(require("react"), 1);
4862
+ var React27 = __toESM(require("react"), 1);
4617
4863
 
4618
4864
  // src/kits/session.ts
4619
- var React24 = __toESM(require("react"), 1);
4865
+ var React26 = __toESM(require("react"), 1);
4620
4866
  var PERMISSION_CATALOG = [
4621
4867
  { group: "Plans", items: [
4622
4868
  { key: "plan.view", label: "View plans", detail: "Read any plan in the workspace." },
@@ -6183,8 +6429,8 @@ function roadmap(overrides) {
6183
6429
  };
6184
6430
  }
6185
6431
  function useSession() {
6186
- const [s, setS] = React24.useState(getSession);
6187
- React24.useEffect(() => subscribe(setS), []);
6432
+ const [s, setS] = React26.useState(getSession);
6433
+ React26.useEffect(() => subscribe(setS), []);
6188
6434
  return s;
6189
6435
  }
6190
6436
  var SessionKit = {
@@ -6217,7 +6463,7 @@ var SessionKit = {
6217
6463
  };
6218
6464
 
6219
6465
  // src/components/platform/AccountMenu.tsx
6220
- var import_jsx_runtime53 = require("react/jsx-runtime");
6466
+ var import_jsx_runtime56 = require("react/jsx-runtime");
6221
6467
  var DEFAULT_LINKS = [
6222
6468
  { id: "profile", label: "Your profile", icon: "user-circle", href: "../admin/index.html#profile" },
6223
6469
  { id: "preferences", label: "Preferences", icon: "sliders-horizontal", href: "../admin/index.html#preferences" }
@@ -6228,7 +6474,7 @@ var DEFAULT_ADMIN_LINKS = [
6228
6474
  { id: "flags", label: "Feature flags", icon: "toggle-right", href: "../admin/index.html#flags", perm: "flags.manage" }
6229
6475
  ];
6230
6476
  function Item({ item, onPick }) {
6231
- return /* @__PURE__ */ (0, import_jsx_runtime53.jsxs)(
6477
+ return /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)(
6232
6478
  "button",
6233
6479
  {
6234
6480
  type: "button",
@@ -6236,9 +6482,9 @@ function Item({ item, onPick }) {
6236
6482
  className: "fd-acct-item",
6237
6483
  onClick: () => onPick(item),
6238
6484
  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
6485
+ /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("i", { className: "ph ph-" + item.icon, "aria-hidden": "true" }),
6486
+ /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("span", { style: { flex: 1 }, children: item.label }),
6487
+ item.badge ? /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(Badge, { tone: "neutral", children: item.badge }) : null
6242
6488
  ]
6243
6489
  }
6244
6490
  );
@@ -6254,9 +6500,9 @@ function AccountMenu({
6254
6500
  ...rest
6255
6501
  }) {
6256
6502
  const session = SessionKit.useSession();
6257
- const [open, setOpen] = React25.useState(false);
6258
- const [switching, setSwitching] = React25.useState(false);
6259
- const ref = React25.useRef(null);
6503
+ const [open, setOpen] = React27.useState(false);
6504
+ const [switching, setSwitching] = React27.useState(false);
6505
+ const ref = React27.useRef(null);
6260
6506
  const user = session.user;
6261
6507
  const visibleAdmin = adminLinks.filter((l) => !l.perm || SessionKit.can(l.perm));
6262
6508
  const pick = (item) => {
@@ -6270,8 +6516,8 @@ function AccountMenu({
6270
6516
  if (onSignOut) return onSignOut();
6271
6517
  window.alert("Signed out. (Simulated \u2014 no auth provider is wired up.)");
6272
6518
  };
6273
- return /* @__PURE__ */ (0, import_jsx_runtime53.jsxs)(import_jsx_runtime53.Fragment, { children: [
6274
- /* @__PURE__ */ (0, import_jsx_runtime53.jsxs)(
6519
+ return /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)(import_jsx_runtime56.Fragment, { children: [
6520
+ /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)(
6275
6521
  "button",
6276
6522
  {
6277
6523
  type: "button",
@@ -6283,32 +6529,32 @@ function AccountMenu({
6283
6529
  onClick: () => setOpen((o) => !o),
6284
6530
  ...rest,
6285
6531
  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)" } })
6532
+ /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(Avatar, { name: user.name, size: "sm" }),
6533
+ /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("i", { className: "ph ph-caret-down", "aria-hidden": "true", style: { fontSize: 11, color: "var(--text-muted)" } })
6288
6534
  ]
6289
6535
  }
6290
6536
  ),
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 })
6537
+ /* @__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: [
6538
+ /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("div", { className: "fd-row", style: { gap: 10, padding: "12px 14px", borderBottom: "1px solid var(--border)" }, children: [
6539
+ /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(Avatar, { name: user.name }),
6540
+ /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("span", { className: "fd-stack", style: { gap: 1, minWidth: 0, flex: 1 }, children: [
6541
+ /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("span", { className: "fd-body-sm", style: { fontWeight: 700 }, children: user.name }),
6542
+ /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("span", { className: "fd-body-sm fd-muted fd-table-trunc", children: user.email })
6297
6543
  ] })
6298
6544
  ] }),
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))
6545
+ 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,
6546
+ /* @__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)) }),
6547
+ visibleAdmin.length ? /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("div", { className: "fd-acct-group", style: { borderTop: "1px solid var(--border)" }, children: [
6548
+ /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("span", { className: "fd-overline fd-muted", style: { padding: "8px 14px 4px", display: "block" }, children: "Administration" }),
6549
+ visibleAdmin.map((l) => /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(Item, { item: l, onPick: pick }, l.id))
6304
6550
  ] }) : 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 } })
6551
+ allowUserSwitch ? /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("div", { className: "fd-acct-group", style: { borderTop: "1px solid var(--border)" }, children: [
6552
+ /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("button", { type: "button", role: "menuitem", className: "fd-acct-item", onClick: () => setSwitching((s) => !s), children: [
6553
+ /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("i", { className: "ph ph-user-switch", "aria-hidden": "true" }),
6554
+ /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("span", { style: { flex: 1 }, children: "View as another member" }),
6555
+ /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("i", { className: "ph ph-caret-" + (switching ? "up" : "down"), "aria-hidden": "true", style: { fontSize: 11 } })
6310
6556
  ] }),
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)(
6557
+ 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
6558
  "button",
6313
6559
  {
6314
6560
  type: "button",
@@ -6320,34 +6566,34 @@ function AccountMenu({
6320
6566
  setSwitching(false);
6321
6567
  },
6322
6568
  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(", ") })
6569
+ /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(Avatar, { name: u.name, size: "sm" }),
6570
+ /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("span", { className: "fd-stack", style: { gap: 0, flex: 1, minWidth: 0, alignItems: "flex-start" }, children: [
6571
+ /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("span", { style: { fontWeight: u.id === user.id ? 700 : 500 }, children: u.name }),
6572
+ /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("span", { className: "fd-muted", style: { fontSize: 11.5 }, children: u.roles.join(", ") })
6327
6573
  ] }),
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
6574
+ 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
6575
  ]
6330
6576
  },
6331
6577
  u.id
6332
6578
  )) }) : null
6333
6579
  ] }) : 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" })
6580
+ /* @__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: [
6581
+ /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("i", { className: "ph ph-sign-out", "aria-hidden": "true" }),
6582
+ /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("span", { style: { flex: 1 }, children: "Sign out" })
6337
6583
  ] }) })
6338
6584
  ] }) })
6339
6585
  ] });
6340
6586
  }
6341
6587
 
6342
6588
  // src/components/platform/ApiSpecBrowser.tsx
6343
- var React26 = __toESM(require("react"), 1);
6344
- var import_jsx_runtime54 = require("react/jsx-runtime");
6589
+ var React28 = __toESM(require("react"), 1);
6590
+ var import_jsx_runtime57 = require("react/jsx-runtime");
6345
6591
  var METHOD_TONE = { GET: "success", POST: "info", PATCH: "warning", PUT: "warning", DELETE: "danger" };
6346
6592
  function Json({ obj }) {
6347
- return /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("pre", { className: "fd-json", children: JSON.stringify(obj, null, 2) });
6593
+ return /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("pre", { className: "fd-json", children: JSON.stringify(obj, null, 2) });
6348
6594
  }
6349
6595
  function Endpoint({ s, onRequest }) {
6350
- const [tried, setTried] = React26.useState(null);
6596
+ const [tried, setTried] = React28.useState(null);
6351
6597
  const run = async () => {
6352
6598
  setTried("busy");
6353
6599
  const t0 = (window.performance || Date).now();
@@ -6358,50 +6604,50 @@ function Endpoint({ s, onRequest }) {
6358
6604
  setTried({ ms: Math.round((window.performance || Date).now() - t0), error: String(e && e.message || e) });
6359
6605
  }
6360
6606
  };
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: [
6607
+ 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: [
6608
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { className: "fd-row", style: { gap: 10, padding: "14px 18px", flexWrap: "wrap" }, children: [
6609
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(Badge, { tone: METHOD_TONE[s.method] || "neutral", children: s.method }),
6610
+ /* @__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 }),
6611
+ s.isList ? /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(Badge, { tone: "neutral", icon: "rows", children: "Paged list" }) : null,
6612
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { style: { flex: 1 } }),
6613
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("span", { className: "fd-body-sm fd-muted fd-mono", children: [
6368
6614
  s.latency[0],
6369
6615
  "\u2013",
6370
6616
  s.latency[1],
6371
6617
  "ms"
6372
6618
  ] }),
6373
- /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(Button, { size: "sm", variant: "secondary", icon: "play", loading: tried === "busy", onClick: run, children: "Try it" })
6619
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(Button, { size: "sm", variant: "secondary", icon: "play", loading: tried === "busy", onClick: run, children: "Try it" })
6374
6620
  ] }),
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
6621
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { className: "fd-stack", style: { gap: 14, padding: "0 18px 16px" }, children: [
6622
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { className: "fd-stack", style: { gap: 6 }, children: [
6623
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { className: "fd-body-sm", style: { fontWeight: 700 }, children: s.title }),
6624
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("p", { className: "fd-body-sm fd-secondary", style: { margin: 0, textWrap: "pretty" }, children: s.purpose }),
6625
+ 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
6626
  ] }),
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 })
6627
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { style: { display: "grid", gridTemplateColumns: "repeat(auto-fit,minmax(280px,1fr))", gap: 12, alignItems: "start" }, children: [
6628
+ s.request ? /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { className: "fd-stack", style: { gap: 6 }, children: [
6629
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { className: "fd-overline fd-muted", children: "Request body" }),
6630
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(Json, { obj: s.request })
6385
6631
  ] }) : 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 })
6632
+ s.query ? /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { className: "fd-stack", style: { gap: 6 }, children: [
6633
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { className: "fd-overline fd-muted", children: "Query" }),
6634
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(Json, { obj: s.query })
6389
6635
  ] }) : 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 })
6636
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { className: "fd-stack", style: { gap: 6 }, children: [
6637
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { className: "fd-overline fd-muted", children: "Response 200" }),
6638
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(Json, { obj: s.response })
6393
6639
  ] })
6394
6640
  ] }),
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: [
6641
+ s.notes ? /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(Flag, { tone: "info", statement: "Implementation note", cost: s.notes, actions: null }) : null,
6642
+ tried && tried !== "busy" ? /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { className: "fd-stack", style: { gap: 6 }, children: [
6643
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("span", { className: "fd-row", style: { gap: 8 }, children: [
6644
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { className: "fd-overline fd-muted", children: "Simulated response" }),
6645
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(Badge, { tone: tried.error ? "danger" : "success", icon: "timer", children: [
6400
6646
  tried.ms,
6401
6647
  "ms"
6402
6648
  ] })
6403
6649
  ] }),
6404
- /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(Json, { obj: tried.error ? { error: tried.error } : tried.data })
6650
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(Json, { obj: tried.error ? { error: tried.error } : tried.data })
6405
6651
  ] }) : null
6406
6652
  ] })
6407
6653
  ] }) });
@@ -6420,58 +6666,58 @@ function ApiSpecBrowser({
6420
6666
  className = "",
6421
6667
  ...rest
6422
6668
  }) {
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);
6669
+ const [q, setQ] = React28.useState("");
6670
+ const [method, setMethod] = React28.useState(null);
6671
+ const [mod, setMod] = React28.useState(null);
6672
+ const [listOnly, setListOnly] = React28.useState(false);
6427
6673
  const activeModule = modules && modules.find((m) => m.id === mod);
6428
6674
  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
6675
  const effGroups = groups && groups.length ? groups : [["All endpoints", spec.map((s) => s.id)]];
6430
6676
  const methods = [...new Set(spec.map((s) => s.method))];
6431
6677
  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
6678
+ return /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 20, maxWidth: 1100 }, ...rest, children: [
6679
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { className: "fd-stack", style: { gap: 10 }, children: [
6680
+ kicker ? /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { className: "fd-overline fd-muted", children: kicker }) : null,
6681
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("h1", { className: "fd-h1", style: { margin: 0 }, children: title }),
6682
+ lede ? /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("p", { className: "fd-body fd-secondary fd-prose", style: { margin: 0 }, children: lede }) : null
6437
6683
  ] }),
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: [
6684
+ modules && modules.length ? /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { className: "fd-stack", style: { gap: 8 }, children: [
6685
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { className: "fd-overline fd-muted", children: "Filter by screen \u2014 every endpoint that screen depends on" }),
6686
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { className: "fd-row", style: { gap: 8, flexWrap: "wrap" }, children: [
6687
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(Tag, { icon: "stack", selected: !mod, onClick: () => setMod(null), children: [
6442
6688
  "All screens ",
6443
- /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("span", { className: "fd-mono", children: spec.length })
6689
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { className: "fd-mono", children: spec.length })
6444
6690
  ] }),
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: [
6691
+ 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
6692
  m.label,
6447
6693
  " ",
6448
- /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("span", { className: "fd-mono", children: m.endpoints.length })
6694
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { className: "fd-mono", children: m.endpoints.length })
6449
6695
  ] }, m.id))
6450
6696
  ] }),
6451
- activeModule ? /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(
6697
+ activeModule ? /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
6452
6698
  Flag,
6453
6699
  {
6454
6700
  tone: "info",
6455
6701
  statement: activeModule.label + " calls " + activeModule.endpoints.length + " endpoints.",
6456
6702
  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" })
6703
+ actions: /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(Button, { size: "sm", variant: "ghost", icon: "x", onClick: () => setMod(null), children: "Show all screens" })
6458
6704
  }
6459
6705
  ) : null
6460
6706
  ] }) : 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: [
6707
+ sourceNote ? /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(Flag, { tone: "info", statement: "Design-first: this page is the spec.", cost: sourceNote, actions: null }) : null,
6708
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { className: "fd-row", style: { gap: 10, flexWrap: "wrap" }, children: [
6709
+ /* @__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 } }),
6710
+ methods.map((m) => /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(Tag, { selected: method === m, onClick: () => setMethod(method === m ? null : m), children: [
6465
6711
  m,
6466
6712
  " ",
6467
- /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("span", { className: "fd-mono", children: spec.filter((s) => s.method === m).length })
6713
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { className: "fd-mono", children: spec.filter((s) => s.method === m).length })
6468
6714
  ] }, m)),
6469
- listCount ? /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)(Tag, { icon: "rows", selected: listOnly, onClick: () => setListOnly(!listOnly), children: [
6715
+ listCount ? /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(Tag, { icon: "rows", selected: listOnly, onClick: () => setListOnly(!listOnly), children: [
6470
6716
  "Paged lists ",
6471
- /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("span", { className: "fd-mono", children: listCount })
6717
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { className: "fd-mono", children: listCount })
6472
6718
  ] }) : 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: [
6719
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { style: { flex: 1 } }),
6720
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("span", { className: "fd-body-sm fd-muted", children: [
6475
6721
  hits.length,
6476
6722
  " of ",
6477
6723
  spec.length,
@@ -6479,31 +6725,31 @@ function ApiSpecBrowser({
6479
6725
  listCount ? " \xB7 " + listCount + " paged" : ""
6480
6726
  ] })
6481
6727
  ] }),
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]) => {
6728
+ 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
6729
  const items = hits.filter((s) => ids.indexOf(s.id) >= 0);
6484
6730
  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))
6731
+ return /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { className: "fd-stack", style: { gap: 12 }, children: [
6732
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { className: "fd-label-lg", children: g }),
6733
+ items.map((s) => /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(Endpoint, { s, onRequest }, s.id))
6488
6734
  ] }, g);
6489
6735
  }),
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 })
6736
+ 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: [
6737
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { className: "fd-overline fd-muted", style: { width: 110, flex: "none", paddingTop: 2 }, children: k }),
6738
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { className: "fd-body-sm fd-secondary", style: { textWrap: "pretty" }, children: v })
6493
6739
  ] }, 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 })
6740
+ 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: [
6741
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(Badge, { tone: "danger", children: id }),
6742
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("span", { className: "fd-stack", style: { gap: 2, flex: 1 }, children: [
6743
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { className: "fd-body-sm", style: { fontWeight: 600 }, children: question }),
6744
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { className: "fd-body-sm fd-muted", children: why })
6499
6745
  ] })
6500
6746
  ] }, id)) }) }) : null
6501
6747
  ] });
6502
6748
  }
6503
6749
 
6504
6750
  // src/components/platform/ProfilePage.tsx
6505
- var React27 = __toESM(require("react"), 1);
6506
- var import_jsx_runtime55 = require("react/jsx-runtime");
6751
+ var React29 = __toESM(require("react"), 1);
6752
+ var import_jsx_runtime58 = require("react/jsx-runtime");
6507
6753
  var TIMEZONES = ["America/New_York", "America/Chicago", "America/Denver", "America/Los_Angeles", "America/Anchorage", "Pacific/Honolulu", "Europe/London", "Europe/Berlin"];
6508
6754
  var NOTIFY = [
6509
6755
  { key: "planShared", label: "A plan is shared with me", detail: "Someone sends you a plan or a client link." },
@@ -6515,7 +6761,7 @@ var NOTIFY = [
6515
6761
  function ProfilePage({ user: userProp, onSave, onNavigate, sessions, showSessions = true, className = "", ...rest }) {
6516
6762
  const session = SessionKit.useSession();
6517
6763
  const user = userProp || session.user;
6518
- const [draft, setDraft] = React27.useState(() => ({
6764
+ const [draft, setDraft] = React29.useState(() => ({
6519
6765
  name: user.name || "",
6520
6766
  title: user.title || "",
6521
6767
  email: user.email || "",
@@ -6524,8 +6770,8 @@ function ProfilePage({ user: userProp, onSave, onNavigate, sessions, showSession
6524
6770
  bio: user.bio || "",
6525
6771
  notify: user.notify || { planShared: true, planChanged: true, goalMissed: true, flagChanged: false, weekly: true }
6526
6772
  }));
6527
- const [saving, setSaving] = React27.useState(false);
6528
- const [saved, setSaved] = React27.useState(false);
6773
+ const [saving, setSaving] = React29.useState(false);
6774
+ const [saved, setSaved] = React29.useState(false);
6529
6775
  const set = (k, v) => {
6530
6776
  setDraft((d) => Object.assign({}, d, { [k]: v }));
6531
6777
  setSaved(false);
@@ -6547,43 +6793,43 @@ function ProfilePage({ user: userProp, onSave, onNavigate, sessions, showSession
6547
6793
  { id: "s2", device: "iPhone 15 \xB7 Safari", where: "Denver, CO", when: "2 hours ago" },
6548
6794
  { id: "s3", device: "Windows \xB7 Edge", where: "Chicago, IL", when: "Aug 12" }
6549
6795
  ];
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." })
6796
+ return /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 20, maxWidth: 860 }, ...rest, children: [
6797
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("div", { className: "fd-stack", style: { gap: 10 }, children: [
6798
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("span", { className: "fd-overline fd-muted", children: "Account" }),
6799
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("h1", { className: "fd-h1", style: { margin: 0 }, children: "Your profile" }),
6800
+ /* @__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
6801
  ] }),
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: [
6802
+ /* @__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: [
6803
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(Avatar, { name: draft.name || user.name, size: "lg" }),
6804
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("div", { className: "fd-stack", style: { gap: 4, flex: 1, minWidth: 200 }, children: [
6805
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("span", { className: "fd-h3", style: { margin: 0 }, children: draft.name || user.name }),
6806
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("span", { className: "fd-body-sm fd-muted", children: [
6561
6807
  draft.title || "No title set",
6562
6808
  " \xB7 ",
6563
6809
  user.team || "No team"
6564
6810
  ] }),
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
6811
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("span", { className: "fd-row", style: { gap: 6, flexWrap: "wrap", paddingTop: 4 }, children: [
6812
+ session.roles.map((r) => /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(Badge, { tone: r.id === "owner" ? "success" : "neutral", children: r.name }, r.id)),
6813
+ user.sso ? /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(Badge, { tone: "info", icon: "shield-check", children: "SSO" }) : null
6568
6814
  ] })
6569
6815
  ] }),
6570
- /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(Button, { variant: "secondary", size: "sm", icon: "image", children: "Change photo" })
6816
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(Button, { variant: "secondary", size: "sm", icon: "image", children: "Change photo" })
6571
6817
  ] }) }),
6572
- /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(
6818
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
6573
6819
  Card,
6574
6820
  {
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" })
6821
+ title: /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("span", { className: "fd-stack", style: { gap: 2 }, children: [
6822
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("span", { children: "Identity" }),
6823
+ /* @__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
6824
  ] }),
6579
6825
  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" })
6826
+ children: /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("div", { className: "fd-stack", style: { gap: 14 }, children: [
6827
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("div", { style: { display: "grid", gridTemplateColumns: "repeat(auto-fit,minmax(220px,1fr))", gap: 14 }, children: [
6828
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(Input, { label: "Full name", value: draft.name, onChange: (e) => set("name", e.target.value) }),
6829
+ /* @__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
6830
  ] }),
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)(
6831
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("div", { style: { display: "grid", gridTemplateColumns: "repeat(auto-fit,minmax(220px,1fr))", gap: 14 }, children: [
6832
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
6587
6833
  Input,
6588
6834
  {
6589
6835
  label: "Work email",
@@ -6593,9 +6839,9 @@ function ProfilePage({ user: userProp, onSave, onNavigate, sessions, showSession
6593
6839
  help: user.sso ? "Managed by your identity provider \u2014 change it there." : "Contact an administrator to change this."
6594
6840
  }
6595
6841
  ),
6596
- /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(Input, { label: "Phone", value: draft.phone, onChange: (e) => set("phone", e.target.value), placeholder: "Optional" })
6842
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(Input, { label: "Phone", value: draft.phone, onChange: (e) => set("phone", e.target.value), placeholder: "Optional" })
6597
6843
  ] }),
6598
- /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(
6844
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
6599
6845
  Textarea,
6600
6846
  {
6601
6847
  label: "Short bio",
@@ -6609,8 +6855,8 @@ function ProfilePage({ user: userProp, onSave, onNavigate, sessions, showSession
6609
6855
  ] })
6610
6856
  }
6611
6857
  ),
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)(
6858
+ /* @__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: [
6859
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
6614
6860
  Select,
6615
6861
  {
6616
6862
  label: "Time zone",
@@ -6620,28 +6866,28 @@ function ProfilePage({ user: userProp, onSave, onNavigate, sessions, showSession
6620
6866
  help: "Flight dates and schedules render in this zone."
6621
6867
  }
6622
6868
  ),
6623
- /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(Select, { label: "Start of week", options: ["Monday", "Sunday"], placeholder: "Monday" })
6869
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(Select, { label: "Start of week", options: ["Monday", "Sunday"], placeholder: "Monday" })
6624
6870
  ] }) }),
6625
- /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(
6871
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
6626
6872
  Card,
6627
6873
  {
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" })
6874
+ title: /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("span", { className: "fd-stack", style: { gap: 2 }, children: [
6875
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("span", { children: "Notifications" }),
6876
+ /* @__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
6877
  ] }),
6632
6878
  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)) })
6879
+ 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
6880
  }
6635
6881
  ),
6636
- /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)(
6882
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)(
6637
6883
  Card,
6638
6884
  {
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" })
6885
+ title: /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("span", { className: "fd-stack", style: { gap: 2 }, children: [
6886
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("span", { children: "Access" }),
6887
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("span", { className: "fd-body-sm fd-muted", style: { fontWeight: 400 }, children: "What your roles grant you" })
6642
6888
  ] }),
6643
6889
  elevation: "flat",
6644
- action: /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(
6890
+ action: /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
6645
6891
  Button,
6646
6892
  {
6647
6893
  size: "sm",
@@ -6652,39 +6898,39 @@ function ProfilePage({ user: userProp, onSave, onNavigate, sessions, showSession
6652
6898
  }
6653
6899
  ),
6654
6900
  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: [
6901
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("div", { className: "fd-stack", style: { gap: 0 }, children: [
6902
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(CardRow, { label: "Roles", children: session.roles.map((r) => r.name).join(", ") || "None" }),
6903
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)(CardRow, { label: "Permissions", children: [
6658
6904
  session.permissions.length,
6659
6905
  " granted"
6660
6906
  ] }),
6661
- /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(CardRow, { label: "Member since", children: user.joined || "\u2014" })
6907
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(CardRow, { label: "Member since", children: user.joined || "\u2014" })
6662
6908
  ] }),
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." })
6909
+ /* @__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
6910
  ]
6665
6911
  }
6666
6912
  ),
6667
- showSessions ? /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(
6913
+ showSessions ? /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
6668
6914
  Card,
6669
6915
  {
6670
6916
  title: "Signed-in devices",
6671
6917
  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: [
6918
+ action: /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(Button, { size: "sm", variant: "ghost", icon: "sign-out", children: "Sign out everywhere" }),
6919
+ 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: [
6920
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("i", { className: "ph ph-device-mobile", style: { fontSize: 16, color: "var(--text-muted)" }, "aria-hidden": "true" }),
6921
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("span", { className: "fd-stack", style: { gap: 1, flex: 1, minWidth: 160 }, children: [
6922
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("span", { className: "fd-body-sm", style: { fontWeight: 600 }, children: s.device }),
6923
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("span", { className: "fd-body-sm fd-muted", children: [
6678
6924
  s.where,
6679
6925
  " \xB7 ",
6680
6926
  s.when
6681
6927
  ] })
6682
6928
  ] }),
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" })
6929
+ 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
6930
  ] }, s.id)) })
6685
6931
  }
6686
6932
  ) : null,
6687
- /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)("div", { className: "fd-row", style: {
6933
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("div", { className: "fd-row", style: {
6688
6934
  gap: 10,
6689
6935
  flexWrap: "wrap",
6690
6936
  position: "sticky",
@@ -6695,8 +6941,8 @@ function ProfilePage({ user: userProp, onSave, onNavigate, sessions, showSession
6695
6941
  border: "1px solid var(--border)",
6696
6942
  boxShadow: "0 -4px 16px rgba(11,13,17,.06)"
6697
6943
  }, 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)(
6944
+ /* @__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" }),
6945
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
6700
6946
  Button,
6701
6947
  {
6702
6948
  size: "sm",
@@ -6709,16 +6955,16 @@ function ProfilePage({ user: userProp, onSave, onNavigate, sessions, showSession
6709
6955
  children: "Discard"
6710
6956
  }
6711
6957
  ),
6712
- /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(Button, { size: "sm", icon: "check", disabled: !dirty, loading: saving, onClick: save, children: "Save changes" })
6958
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(Button, { size: "sm", icon: "check", disabled: !dirty, loading: saving, onClick: save, children: "Save changes" })
6713
6959
  ] })
6714
6960
  ] });
6715
6961
  }
6716
6962
 
6717
6963
  // src/components/platform/RoadmapTimeline.tsx
6718
- var React29 = __toESM(require("react"), 1);
6964
+ var React31 = __toESM(require("react"), 1);
6719
6965
 
6720
6966
  // src/kits/runtime.ts
6721
- var React28 = __toESM(require("react"), 1);
6967
+ var React30 = __toESM(require("react"), 1);
6722
6968
  var WIRED_ENDPOINTS = [
6723
6969
  // Nothing yet. Every id below would come from a real service:
6724
6970
  // "plan.get", "placements.list", …
@@ -6889,8 +7135,8 @@ var RuntimeKit = {
6889
7135
  };
6890
7136
  RuntimeKit.declare(FEATURE_NEEDS);
6891
7137
  function useRuntimeMode() {
6892
- const [m, setM] = React28.useState(RuntimeKit.getMode());
6893
- React28.useEffect(() => RuntimeKit.subscribe(setM), []);
7138
+ const [m, setM] = React30.useState(RuntimeKit.getMode());
7139
+ React30.useEffect(() => RuntimeKit.subscribe(setM), []);
6894
7140
  return m;
6895
7141
  }
6896
7142
  function useFeatureStatus(key) {
@@ -6909,7 +7155,7 @@ var UseRuntimeMode = useRuntimeMode;
6909
7155
  var UseFeatureStatus = useFeatureStatus;
6910
7156
 
6911
7157
  // src/components/platform/RoadmapTimeline.tsx
6912
- var import_jsx_runtime56 = require("react/jsx-runtime");
7158
+ var import_jsx_runtime59 = require("react/jsx-runtime");
6913
7159
  var STATUS = {
6914
7160
  shipped: { tone: "success", icon: "check-circle", label: "Wired" },
6915
7161
  next: { tone: "warning", icon: "traffic-cone", label: "Not wired" },
@@ -6924,45 +7170,45 @@ function RoadmapCard({ item, byKey, onOpenFlag }) {
6924
7170
  const s = STATUS[item.status] || STATUS.planned;
6925
7171
  const deps = (item.dependsOn || []).map((k) => byKey[k]).filter(Boolean);
6926
7172
  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 })
7173
+ 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: [
7174
+ /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("div", { className: "fd-row", style: { gap: 8, flexWrap: "wrap" }, children: [
7175
+ /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("span", { className: "fd-body", style: { fontWeight: 700, flex: 1, minWidth: 140 }, children: item.label }),
7176
+ /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(Badge, { tone: "neutral", icon: PROJECT_ICON[item.project] || "squares-four", children: item.project }),
7177
+ /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(Badge, { tone: s.tone, icon: s.icon, children: s.label })
6932
7178
  ] }),
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 })
7179
+ /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("p", { className: "fd-body-sm fd-secondary", style: { margin: 0, textWrap: "pretty" }, children: item.description }),
7180
+ item.backend ? /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("div", { className: "fd-row", style: { gap: 10, alignItems: "flex-start" }, children: [
7181
+ /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("span", { className: "fd-overline fd-muted", style: { width: 62, flex: "none", paddingTop: 2 }, children: "Backend" }),
7182
+ /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("span", { className: "fd-body-sm", style: { flex: 1, textWrap: "pretty" }, children: item.backend })
6937
7183
  ] }) : 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" }),
7184
+ /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("div", { className: "fd-row", style: { gap: 12, flexWrap: "wrap" }, children: [
7185
+ item.effort ? /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("span", { className: "fd-body-sm fd-muted", children: [
7186
+ /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("i", { className: "ph ph-hourglass-medium" }),
6941
7187
  " ",
6942
7188
  item.effort
6943
7189
  ] }) : 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" }),
7190
+ /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("span", { className: "fd-body-sm fd-muted", children: [
7191
+ /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("i", { className: "ph ph-user" }),
6946
7192
  " ",
6947
7193
  item.owner
6948
7194
  ] }),
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)(
7195
+ item.screen ? /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(Badge, { tone: "neutral", icon: "browser", children: "screen" }) : null,
7196
+ /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("span", { style: { flex: 1 } }),
7197
+ /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(
6952
7198
  "button",
6953
7199
  {
6954
7200
  type: "button",
6955
7201
  onClick: () => onOpenFlag && onOpenFlag(item.key),
6956
7202
  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 })
7203
+ children: /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("code", { className: "fd-mono", style: { fontSize: 11, color: "var(--brand)" }, children: item.key })
6958
7204
  }
6959
7205
  )
6960
7206
  ] }),
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))
7207
+ 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: [
7208
+ /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("span", { className: "fd-overline fd-muted", style: { paddingTop: 3 }, children: "After" }),
7209
+ deps.map((d) => /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(Tag, { icon: d.implemented ? "check" : "clock", children: d.label }, d.key))
6964
7210
  ] }) : null,
6965
- blocking.length && !item.implemented ? /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("span", { className: "fd-body-sm", style: { color: "var(--warn-text)" }, children: [
7211
+ blocking.length && !item.implemented ? /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("span", { className: "fd-body-sm", style: { color: "var(--warn-text)" }, children: [
6966
7212
  "Blocked until ",
6967
7213
  blocking.map((d) => d.label).join(" and "),
6968
7214
  " ",
@@ -6973,12 +7219,12 @@ function RoadmapCard({ item, byKey, onOpenFlag }) {
6973
7219
  }
6974
7220
  function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
6975
7221
  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(() => {
7222
+ const [project, setProject] = React31.useState("");
7223
+ const [q, setQ] = React31.useState("");
7224
+ const scrollRef = React31.useRef(null);
7225
+ const nowRef = React31.useRef(null);
7226
+ const rm = React31.useMemo(() => SessionKit.roadmap({ isComplete: RuntimeKit.isComplete }), [session]);
7227
+ const byKey = React31.useMemo(() => {
6982
7228
  const m = {};
6983
7229
  rm.items.forEach((i) => {
6984
7230
  m[i.key] = i;
@@ -6987,7 +7233,7 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
6987
7233
  }, [rm]);
6988
7234
  const items = rm.items.filter((i) => (!project || i.project === project) && (!q || (i.label + " " + i.description + " " + (i.backend || "") + " " + i.key).toLowerCase().includes(q.toLowerCase())));
6989
7235
  const projects = [...new Set(rm.items.map((i) => i.project))];
6990
- React29.useEffect(() => {
7236
+ React31.useEffect(() => {
6991
7237
  let raf1 = 0, raf2 = 0;
6992
7238
  const place = () => {
6993
7239
  const box = scrollRef.current, mark = nowRef.current;
@@ -7015,23 +7261,23 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
7015
7261
  }, 0);
7016
7262
  const nextPhase = items.find((i) => !i.implemented);
7017
7263
  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." })
7264
+ return /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("div", { className: "fd-stack", style: { gap: 16, maxWidth: 1e3 }, children: [
7265
+ /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("div", { className: "fd-stack", style: { gap: 10 }, children: [
7266
+ /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("span", { className: "fd-overline fd-muted", children: "Architecture" }),
7267
+ /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("h1", { className: "fd-h1", style: { margin: 0 }, children: title }),
7268
+ /* @__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
7269
  ] }),
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" })
7270
+ /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("div", { className: "fd-grid-stats is-thin", children: [
7271
+ /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(StatTile, { compact: true, label: "Wired", value: String(rm.shipped), sub: "of " + rm.items.length + " features" }),
7272
+ /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(StatTile, { compact: true, label: "Remaining", value: String(rm.remaining), sub: "backend work" }),
7273
+ /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(StatTile, { compact: true, label: "Est. effort", value: days ? days + " days" : "\u2014", sub: "sum of estimates, not calendar" }),
7274
+ /* @__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
7275
  ] }),
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)(
7276
+ /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("div", { className: "fd-row", style: { gap: 10, flexWrap: "wrap" }, children: [
7277
+ /* @__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 } }),
7278
+ /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(Select, { placeholder: "All projects", value: project, onChange: (e) => setProject(e.target.value), options: projects, style: { width: 190 } }),
7279
+ /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("span", { style: { flex: 1 } }),
7280
+ /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(
7035
7281
  Button,
7036
7282
  {
7037
7283
  size: "sm",
@@ -7045,7 +7291,7 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
7045
7291
  }
7046
7292
  )
7047
7293
  ] }),
7048
- /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(
7294
+ /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(
7049
7295
  Flag,
7050
7296
  {
7051
7297
  tone: "info",
@@ -7054,60 +7300,60 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
7054
7300
  actions: null
7055
7301
  }
7056
7302
  ),
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%" } }) }),
7303
+ /* @__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: [
7304
+ /* @__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
7305
  items.map((item, n) => {
7060
7306
  const showPhase = item.phase !== lastPhase;
7061
7307
  lastPhase = item.phase;
7062
7308
  const inPhase = items.filter((i) => i.phase === item.phase).length;
7063
7309
  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: [
7310
+ return /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)(React31.Fragment, { children: [
7311
+ showPhase ? /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("div", { className: "fd-rm-era", children: [
7312
+ /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("span", { className: "fd-row", style: { gap: 8, flexWrap: "wrap", alignItems: "baseline" }, children: [
7313
+ /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("span", { style: { fontWeight: 700 }, children: item.phase === 0 ? "Shipped" : "Phase " + item.phase + " \u2014 " + item.phaseName }),
7314
+ item.phase === 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("span", { className: "fd-mono", style: { opacity: 0.7, fontWeight: 400 }, children: [
7069
7315
  fmtDate(item.phaseStart),
7070
7316
  " \u2013 ",
7071
7317
  fmtDate(item.date)
7072
7318
  ] }),
7073
- /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("span", { style: { opacity: 0.7, fontWeight: 400 }, children: [
7319
+ /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("span", { style: { opacity: 0.7, fontWeight: 400 }, children: [
7074
7320
  "\xB7 ",
7075
7321
  inPhase,
7076
7322
  " feature",
7077
7323
  inPhase === 1 ? "" : "s"
7078
7324
  ] })
7079
7325
  ] }),
7080
- item.phaseWhy ? /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("p", { className: "fd-rm-era-why", children: item.phaseWhy }) : null
7326
+ item.phaseWhy ? /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("p", { className: "fd-rm-era-why", children: item.phaseWhy }) : null
7081
7327
  ] }) : 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" }),
7328
+ 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: [
7329
+ /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("i", { className: "ph ph-map-pin" }),
7084
7330
  " You are here \u2014 everything above is wired"
7085
7331
  ] }) }) : 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: [
7332
+ /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("div", { className: "fd-rm-row", children: [
7333
+ /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("span", { className: "fd-rm-dot " + (item.implemented ? "is-shipped" : item.status === "next" ? "is-next" : "") }),
7334
+ /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("div", { className: "fd-rm-date", children: [
7089
7335
  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 })
7336
+ /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("br", {}),
7337
+ /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("span", { style: { opacity: 0.75 }, children: item.implemented ? "shipped" : "phase " + item.phase })
7092
7338
  ] }),
7093
- /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(RoadmapCard, { item, byKey, onOpenFlag })
7339
+ /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(RoadmapCard, { item, byKey, onOpenFlag })
7094
7340
  ] })
7095
7341
  ] }, item.key);
7096
7342
  }),
7097
- !items.length ? /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("p", { className: "fd-body-sm fd-muted", children: "Nothing matches that filter." }) : null
7343
+ !items.length ? /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("p", { className: "fd-body-sm fd-muted", children: "Nothing matches that filter." }) : null
7098
7344
  ] }) }) }),
7099
- /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("p", { className: "fd-body-sm fd-muted", style: { margin: 0 }, children: [
7345
+ /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("p", { className: "fd-body-sm fd-muted", style: { margin: 0 }, children: [
7100
7346
  "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" }),
7347
+ /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("code", { className: "fd-mono", children: "implemented" }),
7102
7348
  " field, so this page cannot drift from what the apps actually do."
7103
7349
  ] })
7104
7350
  ] });
7105
7351
  }
7106
7352
 
7107
7353
  // src/components/platform/ComingSoon.tsx
7108
- var React30 = __toESM(require("react"), 1);
7354
+ var React32 = __toESM(require("react"), 1);
7109
7355
  var import_react_dom7 = require("react-dom");
7110
- var import_jsx_runtime57 = require("react/jsx-runtime");
7356
+ var import_jsx_runtime60 = require("react/jsx-runtime");
7111
7357
  var BYPASS_STORE = "fd.soon.bypass.v1";
7112
7358
  function readBypassed() {
7113
7359
  try {
@@ -7123,8 +7369,8 @@ function writeBypassed(list) {
7123
7369
  }
7124
7370
  }
7125
7371
  function useBypass(key) {
7126
- const [on, setOn] = React30.useState(() => !!key && readBypassed().indexOf(key) >= 0);
7127
- React30.useEffect(() => {
7372
+ const [on, setOn] = React32.useState(() => !!key && readBypassed().indexOf(key) >= 0);
7373
+ React32.useEffect(() => {
7128
7374
  setOn(!!key && readBypassed().indexOf(key) >= 0);
7129
7375
  }, [key]);
7130
7376
  const set = (next) => {
@@ -7137,43 +7383,43 @@ function useBypass(key) {
7137
7383
  return [on, set];
7138
7384
  }
7139
7385
  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" }),
7386
+ return /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)(import_jsx_runtime60.Fragment, { children: [
7387
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("span", { className: "fd-soon-badge", children: [
7388
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" }),
7143
7389
  label
7144
7390
  ] }),
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" }),
7391
+ detail ? /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("span", { className: "fd-soon-detail", children: detail }) : null,
7392
+ backend ? /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("span", { className: "fd-soon-backend", children: [
7393
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("span", { className: "fd-overline", children: "Needs" }),
7148
7394
  " ",
7149
7395
  backend
7150
7396
  ] }) : 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" }),
7397
+ eta || effort || onRoadmap ? /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("span", { className: "fd-soon-meta", children: [
7398
+ eta ? /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("span", { children: [
7399
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("i", { className: "ph ph-calendar-blank", "aria-hidden": "true" }),
7154
7400
  " ",
7155
7401
  eta
7156
7402
  ] }) : 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" }),
7403
+ effort ? /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("span", { children: [
7404
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("i", { className: "ph ph-hourglass-medium", "aria-hidden": "true" }),
7159
7405
  " ",
7160
7406
  effort
7161
7407
  ] }) : null,
7162
- onRoadmap ? /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("button", { type: "button", className: "fd-soon-link", onClick: onRoadmap, children: [
7408
+ onRoadmap ? /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("button", { type: "button", className: "fd-soon-link", onClick: onRoadmap, children: [
7163
7409
  "See the roadmap ",
7164
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("i", { className: "ph ph-arrow-right", "aria-hidden": "true" })
7410
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("i", { className: "ph ph-arrow-right", "aria-hidden": "true" })
7165
7411
  ] }) : null
7166
7412
  ] }) : 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" }),
7413
+ allowed ? /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("button", { type: "button", className: "fd-soon-view", onClick: onBypass, children: [
7414
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("i", { className: "ph ph-eye", "aria-hidden": "true" }),
7169
7415
  " View and use it anyway"
7170
7416
  ] }) : null
7171
7417
  ] });
7172
7418
  }
7173
7419
  function useHoverCard(open) {
7174
- const anchor = React30.useRef(null);
7175
- const [pos, setPos] = React30.useState(null);
7176
- React30.useLayoutEffect(() => {
7420
+ const anchor = React32.useRef(null);
7421
+ const [pos, setPos] = React32.useState(null);
7422
+ React32.useLayoutEffect(() => {
7177
7423
  if (!open || !anchor.current) {
7178
7424
  setPos(null);
7179
7425
  return;
@@ -7225,9 +7471,9 @@ function ComingSoon({
7225
7471
  const tip = [label, detail, backend ? "Needs " + backend : null, eta ? "ETA " + eta : null, effort].filter(Boolean).join(" \xB7 ");
7226
7472
  if (inline) {
7227
7473
  if (allowed && bypassed) {
7228
- return /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("span", { className: ["fd-soon-inline-on", className].filter(Boolean).join(" "), ...rest, children: [
7474
+ return /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("span", { className: ["fd-soon-inline-on", className].filter(Boolean).join(" "), ...rest, children: [
7229
7475
  children,
7230
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
7476
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
7231
7477
  "button",
7232
7478
  {
7233
7479
  type: "button",
@@ -7235,12 +7481,12 @@ function ComingSoon({
7235
7481
  title: "Unwired \u2014 writes go to the simulated backend. " + tip + " Click to re-blur.",
7236
7482
  onClick: () => setBypassed(false),
7237
7483
  "aria-label": "Re-blur this unwired feature",
7238
- children: /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" })
7484
+ children: /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" })
7239
7485
  }
7240
7486
  )
7241
7487
  ] });
7242
7488
  }
7243
- return /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
7489
+ return /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
7244
7490
  InlineSoon,
7245
7491
  {
7246
7492
  label,
@@ -7260,20 +7506,20 @@ function ComingSoon({
7260
7506
  );
7261
7507
  }
7262
7508
  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" }),
7509
+ return /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 14 }, ...rest, children: [
7510
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("div", { className: "fd-soon-bar", role: "status", children: [
7511
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("span", { className: "fd-soon-badge", children: [
7512
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" }),
7267
7513
  "Unwired feature \u2014 you are using it anyway"
7268
7514
  ] }),
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: [
7515
+ /* @__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." }),
7516
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("span", { className: "fd-soon-bar-actions", children: [
7517
+ onRoadmap ? /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("button", { type: "button", className: "fd-soon-link", onClick: onRoadmap, children: [
7272
7518
  "Roadmap ",
7273
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("i", { className: "ph ph-arrow-right", "aria-hidden": "true" })
7519
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("i", { className: "ph ph-arrow-right", "aria-hidden": "true" })
7274
7520
  ] }) : 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" }),
7521
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("button", { type: "button", className: "fd-soon-link", onClick: () => setBypassed(false), children: [
7522
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("i", { className: "ph ph-eye-slash", "aria-hidden": "true" }),
7277
7523
  " Re-blur"
7278
7524
  ] })
7279
7525
  ] })
@@ -7281,10 +7527,10 @@ function ComingSoon({
7281
7527
  children
7282
7528
  ] });
7283
7529
  }
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)(
7530
+ return /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("div", { className: ["fd-soon", className].filter(Boolean).join(" "), style: minHeight ? { minHeight } : void 0, ...rest, children: [
7531
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("div", { className: "fd-soon-under", style: { filter: "blur(" + blur + "px) saturate(.62)" }, ...{ inert: "" }, "aria-hidden": "true", children }),
7532
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("div", { className: "fd-soon-veil" }),
7533
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("div", { className: "fd-soon-note", role: "note", children: /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
7288
7534
  SoonCard,
7289
7535
  {
7290
7536
  label,
@@ -7300,9 +7546,9 @@ function ComingSoon({
7300
7546
  ] });
7301
7547
  }
7302
7548
  function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, onBypass, blur, tip, className, rest, children }) {
7303
- const [open, setOpen] = React30.useState(false);
7549
+ const [open, setOpen] = React32.useState(false);
7304
7550
  const [anchor, pos] = useHoverCard(open);
7305
- const close = React30.useRef(null);
7551
+ const close = React32.useRef(null);
7306
7552
  const show = () => {
7307
7553
  if (close.current) {
7308
7554
  clearTimeout(close.current);
@@ -7318,10 +7564,10 @@ function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, o
7318
7564
  setOpen(false);
7319
7565
  }, 140);
7320
7566
  };
7321
- React30.useEffect(() => () => {
7567
+ React32.useEffect(() => () => {
7322
7568
  if (close.current) clearTimeout(close.current);
7323
7569
  }, []);
7324
- return /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(
7570
+ return /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)(
7325
7571
  "span",
7326
7572
  {
7327
7573
  ref: anchor,
@@ -7332,8 +7578,8 @@ function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, o
7332
7578
  onBlur: hide,
7333
7579
  ...rest,
7334
7580
  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)(
7581
+ /* @__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 }),
7582
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
7337
7583
  "button",
7338
7584
  {
7339
7585
  type: "button",
@@ -7344,11 +7590,11 @@ function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, o
7344
7590
  onFocus: show,
7345
7591
  onBlur: hide,
7346
7592
  onClick: () => open ? setOpen(false) : show(),
7347
- children: /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" })
7593
+ children: /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" })
7348
7594
  }
7349
7595
  ),
7350
7596
  open && pos ? (0, import_react_dom7.createPortal)(
7351
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
7597
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
7352
7598
  "div",
7353
7599
  {
7354
7600
  className: "fd-soon-note fd-soon-hovercard",
@@ -7356,7 +7602,7 @@ function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, o
7356
7602
  style: { position: "fixed", left: pos.left, top: pos.top, bottom: pos.bottom, width: pos.width },
7357
7603
  onMouseEnter: show,
7358
7604
  onMouseLeave: hide,
7359
- children: /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
7605
+ children: /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
7360
7606
  SoonCard,
7361
7607
  {
7362
7608
  label,
@@ -7386,10 +7632,10 @@ function formatEta(iso2) {
7386
7632
  var FormatEta = formatEta;
7387
7633
 
7388
7634
  // src/components/platform/Gate.tsx
7389
- var import_jsx_runtime58 = require("react/jsx-runtime");
7635
+ var import_jsx_runtime61 = require("react/jsx-runtime");
7390
7636
  function PermissionDenied({ permission, title, detail, compact: compact3 = false, className = "", ...rest }) {
7391
7637
  const need = Array.isArray(permission) ? permission : [permission].filter(Boolean);
7392
- return /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)(
7638
+ return /* @__PURE__ */ (0, import_jsx_runtime61.jsxs)(
7393
7639
  "div",
7394
7640
  {
7395
7641
  className: ["fd-stack", className].filter(Boolean).join(" "),
@@ -7405,14 +7651,14 @@ function PermissionDenied({ permission, title, detail, compact: compact3 = false
7405
7651
  },
7406
7652
  ...rest,
7407
7653
  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" })
7654
+ /* @__PURE__ */ (0, import_jsx_runtime61.jsxs)("span", { className: "fd-row", style: { gap: 8 }, children: [
7655
+ /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("i", { className: "ph ph-lock-simple", style: { fontSize: 16, color: "var(--text-muted)" }, "aria-hidden": "true" }),
7656
+ /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("span", { className: compact3 ? "fd-label-lg" : "fd-h3", children: title || "You do not have access to this" })
7411
7657
  ] }),
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: {
7658
+ /* @__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." }),
7659
+ need.length ? /* @__PURE__ */ (0, import_jsx_runtime61.jsxs)("span", { className: "fd-row", style: { gap: 6, flexWrap: "wrap" }, children: [
7660
+ /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("span", { className: "fd-overline fd-muted", children: "Requires" }),
7661
+ need.map((p) => /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("code", { className: "fd-mono", style: {
7416
7662
  fontSize: 11.5,
7417
7663
  padding: "2px 7px",
7418
7664
  borderRadius: 5,
@@ -7433,7 +7679,7 @@ function Gate({ perm, anyOf, role, silent = false, fallback, compact: compact3 =
7433
7679
  if (ok) return children;
7434
7680
  if (fallback !== void 0) return fallback;
7435
7681
  if (silent) return null;
7436
- return /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(PermissionDenied, { permission: perm || anyOf, compact: compact3 });
7682
+ return /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(PermissionDenied, { permission: perm || anyOf, compact: compact3 });
7437
7683
  }
7438
7684
  function FeatureGate({
7439
7685
  flag,
@@ -7454,7 +7700,7 @@ function FeatureGate({
7454
7700
  if (!preview) return fallback;
7455
7701
  const f = SessionKit.findFlag(flag) || {};
7456
7702
  const missing = rt.missing || [];
7457
- return /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
7703
+ return /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(
7458
7704
  ComingSoon,
7459
7705
  {
7460
7706
  label: label || (variant === "inline" ? f.label || "Not wired yet" : "Designed \u2014 backend not wired yet"),
@@ -7475,25 +7721,25 @@ function FeatureGate({
7475
7721
  function PermissionHint({ perm, children }) {
7476
7722
  SessionKit.useSession();
7477
7723
  if (SessionKit.can(perm)) return children;
7478
- return /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
7724
+ return /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(
7479
7725
  "span",
7480
7726
  {
7481
7727
  title: "Requires " + (Array.isArray(perm) ? perm.join(", ") : perm),
7482
7728
  style: { display: "inline-flex", opacity: 0.45, cursor: "not-allowed" },
7483
7729
  "aria-disabled": "true",
7484
- children: /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("span", { style: { pointerEvents: "none" }, children })
7730
+ children: /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("span", { style: { pointerEvents: "none" }, children })
7485
7731
  }
7486
7732
  );
7487
7733
  }
7488
7734
 
7489
7735
  // src/components/platform/ModeSwitch.tsx
7490
- var React31 = __toESM(require("react"), 1);
7491
- var import_jsx_runtime59 = require("react/jsx-runtime");
7736
+ var React33 = __toESM(require("react"), 1);
7737
+ var import_jsx_runtime62 = require("react/jsx-runtime");
7492
7738
  function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog, onOpenSpec, summary }) {
7493
7739
  const mode2 = useRuntimeMode();
7494
- const [open, setOpen] = React31.useState(false);
7495
- const ref = React31.useRef(null);
7496
- React31.useEffect(() => {
7740
+ const [open, setOpen] = React33.useState(false);
7741
+ const ref = React33.useRef(null);
7742
+ React33.useEffect(() => {
7497
7743
  if (!open) return;
7498
7744
  const away = (e) => {
7499
7745
  if (ref.current && !ref.current.contains(e.target)) setOpen(false);
@@ -7515,8 +7761,8 @@ function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog
7515
7761
  RuntimeKit.setMode(next);
7516
7762
  setOpen(false);
7517
7763
  };
7518
- return /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("span", { style: { position: "relative", display: "inline-flex" }, ref, children: [
7519
- /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)(
7764
+ return /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("span", { style: { position: "relative", display: "inline-flex" }, ref, children: [
7765
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)(
7520
7766
  "button",
7521
7767
  {
7522
7768
  type: "button",
@@ -7526,29 +7772,29 @@ function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog
7526
7772
  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
7773
  className: "fd-mode-btn" + (test ? " is-test" : "") + (open ? " is-open" : ""),
7528
7774
  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
7775
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("i", { className: "ph " + (test ? "ph-flask" : "ph-lightning"), style: { fontSize: 17 } }),
7776
+ test && requestCount ? /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("span", { className: "fd-mono fd-mode-count", children: requestCount > 99 ? "99+" : requestCount }, requestCount) : null
7531
7777
  ]
7532
7778
  }
7533
7779
  ),
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" }),
7780
+ open ? /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("span", { className: "fd-view-enter fd-mode-pop", children: [
7781
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("span", { className: "fd-row", style: { gap: 10, padding: "12px 14px", borderBottom: "1px solid var(--border)" }, children: [
7782
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("span", { className: "fd-badge " + (test ? "fd-badge-warning" : "fd-badge-neutral"), children: [
7783
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("i", { className: "ph " + (test ? "ph-flask" : "ph-lightning"), "aria-hidden": "true" }),
7538
7784
  test ? "Test mode" : "Live mode"
7539
7785
  ] }),
7540
- test ? /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("span", { className: "fd-body-sm fd-muted fd-mono", children: [
7786
+ test ? /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("span", { className: "fd-body-sm fd-muted fd-mono", children: [
7541
7787
  requestCount,
7542
7788
  " simulated request",
7543
7789
  requestCount === 1 ? "" : "s"
7544
7790
  ] }) : 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
7791
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("span", { style: { flex: 1 } }),
7792
+ test && onClearLog ? /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("button", { type: "button", className: "fd-soon-link", onClick: onClearLog, children: "Clear" }) : null
7547
7793
  ] }),
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: [
7794
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("span", { style: { display: "block", padding: "12px 14px", borderBottom: "1px solid var(--border)" }, children: [
7795
+ /* @__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." }),
7796
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("span", { className: "fd-row", style: { gap: 8, marginTop: 10, flexWrap: "wrap" }, children: [
7797
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("span", { className: "fd-body-sm fd-muted fd-mono", children: [
7552
7798
  s.endpointsWired,
7553
7799
  " endpoint",
7554
7800
  s.endpointsWired === 1 ? "" : "s",
@@ -7558,58 +7804,58 @@ function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog
7558
7804
  s.total,
7559
7805
  " features complete"
7560
7806
  ] }),
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: () => {
7807
+ onOpenSpec ? /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)(import_jsx_runtime62.Fragment, { children: [
7808
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("span", { style: { flex: 1 } }),
7809
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("button", { type: "button", className: "fd-soon-link", onClick: () => {
7564
7810
  setOpen(false);
7565
7811
  onOpenSpec();
7566
7812
  }, children: [
7567
7813
  "API spec ",
7568
- /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("i", { className: "ph ph-arrow-right", "aria-hidden": "true" })
7814
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("i", { className: "ph ph-arrow-right", "aria-hidden": "true" })
7569
7815
  ] })
7570
7816
  ] }) : null
7571
7817
  ] })
7572
7818
  ] }),
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" })
7819
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("span", { className: "fd-mode-choice", children: [
7820
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("button", { type: "button", className: "fd-mode-opt" + (!test ? " is-on" : ""), onClick: () => go("live"), children: [
7821
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("i", { className: "ph ph-lightning", "aria-hidden": "true" }),
7822
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("span", { className: "fd-mode-opt-text", children: [
7823
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("span", { className: "fd-mode-opt-title", children: "Live mode" }),
7824
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("span", { className: "fd-mode-opt-desc", children: "Incomplete features under construction" })
7579
7825
  ] }),
7580
- !test ? /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("i", { className: "ph ph-check", "aria-hidden": "true" }) : null
7826
+ !test ? /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("i", { className: "ph ph-check", "aria-hidden": "true" }) : null
7581
7827
  ] }),
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" })
7828
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("button", { type: "button", className: "fd-mode-opt" + (test ? " is-on" : ""), onClick: () => go("test"), children: [
7829
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("i", { className: "ph ph-flask", "aria-hidden": "true" }),
7830
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("span", { className: "fd-mode-opt-text", children: [
7831
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("span", { className: "fd-mode-opt-title", children: "Test mode" }),
7832
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("span", { className: "fd-mode-opt-desc", children: "Everything usable, all data simulated" })
7587
7833
  ] }),
7588
- test ? /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("i", { className: "ph ph-check", "aria-hidden": "true" }) : null
7834
+ test ? /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("i", { className: "ph ph-check", "aria-hidden": "true" }) : null
7589
7835
  ] })
7590
7836
  ] }),
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
7837
+ 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
7838
  ] }) : null
7593
7839
  ] });
7594
7840
  }
7595
7841
  function TestModeBar({ onExit }) {
7596
7842
  const mode2 = useRuntimeMode();
7597
7843
  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" }),
7844
+ return /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("div", { className: "fd-testbar", role: "status", children: [
7845
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("span", { className: "fd-badge fd-badge-warning", children: [
7846
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("i", { className: "ph ph-flask", "aria-hidden": "true" }),
7601
7847
  "Test mode"
7602
7848
  ] }),
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" }),
7849
+ /* @__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." }),
7850
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("button", { type: "button", className: "fd-soon-link", onClick: () => onExit ? onExit() : RuntimeKit.setMode("live"), children: [
7851
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("i", { className: "ph ph-lightning", "aria-hidden": "true" }),
7606
7852
  " Back to live mode"
7607
7853
  ] })
7608
7854
  ] });
7609
7855
  }
7610
7856
 
7611
7857
  // src/components/planner/ChannelMeta.tsx
7612
- var import_jsx_runtime60 = require("react/jsx-runtime");
7858
+ var import_jsx_runtime63 = require("react/jsx-runtime");
7613
7859
  var CHANNEL_WEIGHTS = {
7614
7860
  "OOH": 50,
7615
7861
  "DOOH": 50,
@@ -7662,9 +7908,9 @@ function ChannelTag({ channel, size = "md", showLabel = true, dot = false, weigh
7662
7908
  const m = ChannelMeta(channel);
7663
7909
  const wt = channelWeightOf(channel || "");
7664
7910
  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 });
7911
+ 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
7912
  }
7667
- return /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)(
7913
+ return /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)(
7668
7914
  "span",
7669
7915
  {
7670
7916
  className: ["fd-chan", size === "sm" ? "fd-chan-sm" : "", className].filter(Boolean).join(" "),
@@ -7672,16 +7918,16 @@ function ChannelTag({ channel, size = "md", showLabel = true, dot = false, weigh
7672
7918
  style: { "--chan": m.color },
7673
7919
  ...rest,
7674
7920
  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
7921
+ /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("i", { className: "ph ph-" + m.icon, "aria-hidden": "true" }),
7922
+ showLabel ? /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("span", { className: "fd-chan-label", children: m.label }) : null,
7923
+ weight ? /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("span", { className: "fd-chan-weight", children: wt || 0 }) : null
7678
7924
  ]
7679
7925
  }
7680
7926
  );
7681
7927
  }
7682
7928
 
7683
7929
  // src/components/planner/SaturationDistribution.tsx
7684
- var import_jsx_runtime61 = require("react/jsx-runtime");
7930
+ var import_jsx_runtime64 = require("react/jsx-runtime");
7685
7931
  var BANDS2 = [
7686
7932
  { key: "weak", label: "Weak", n: 1, range: "< 50" },
7687
7933
  { key: "adequate", label: "Adequate", n: 2, range: "50\u2013100" },
@@ -7692,18 +7938,18 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
7692
7938
  const grouped = BANDS2.map((b) => ({ ...b, items: campuses.filter((c) => c.band === b.key) }));
7693
7939
  const tallest = Math.max(1, ...grouped.map((g) => g.items.length));
7694
7940
  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) => {
7941
+ return /* @__PURE__ */ (0, import_jsx_runtime64.jsxs)("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 16 }, children: [
7942
+ /* @__PURE__ */ (0, import_jsx_runtime64.jsx)("div", { style: { display: "grid", gridTemplateColumns: "repeat(4,1fr)", gap: 12, alignItems: "end" }, children: grouped.map((g) => {
7697
7943
  const mark = "var(--csi-" + g.n + "-mark)";
7698
7944
  const active = selectedBand === g.key;
7699
- return /* @__PURE__ */ (0, import_jsx_runtime61.jsxs)(
7945
+ return /* @__PURE__ */ (0, import_jsx_runtime64.jsxs)(
7700
7946
  "button",
7701
7947
  {
7702
7948
  type: "button",
7703
7949
  onClick: onSelectBand ? () => onSelectBand(active ? null : g.key) : void 0,
7704
7950
  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
7951
  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)(
7952
+ /* @__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
7953
  "span",
7708
7954
  {
7709
7955
  title: c.name + " \xB7 " + c.crp,
@@ -7712,13 +7958,13 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
7712
7958
  },
7713
7959
  c.name
7714
7960
  )) }),
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)) })
7961
+ /* @__PURE__ */ (0, import_jsx_runtime64.jsxs)("span", { className: "fd-row", style: { gap: 8, alignItems: "baseline" }, children: [
7962
+ /* @__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 }),
7963
+ /* @__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
7964
  ] }),
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: [
7965
+ /* @__PURE__ */ (0, import_jsx_runtime64.jsxs)("span", { className: "fd-stack", style: { gap: 1 }, children: [
7966
+ /* @__PURE__ */ (0, import_jsx_runtime64.jsx)("span", { className: "fd-label-lg", children: g.label }),
7967
+ /* @__PURE__ */ (0, import_jsx_runtime64.jsxs)("span", { className: "fd-body-sm fd-muted", style: { fontSize: 11.5 }, children: [
7722
7968
  "CRP ",
7723
7969
  g.range
7724
7970
  ] })
@@ -7728,10 +7974,10 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
7728
7974
  g.key
7729
7975
  );
7730
7976
  }) }),
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: [
7977
+ 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: [
7978
+ /* @__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)) }),
7979
+ /* @__PURE__ */ (0, import_jsx_runtime64.jsxs)("span", { className: "fd-body-sm fd-secondary", style: { flex: 1, minWidth: 240 }, children: [
7980
+ /* @__PURE__ */ (0, import_jsx_runtime64.jsxs)("strong", { style: { color: "var(--text)" }, children: [
7735
7981
  "Plan floor ",
7736
7982
  floorScore
7737
7983
  ] }),
@@ -7742,21 +7988,21 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
7742
7988
  }
7743
7989
 
7744
7990
  // src/components/planner/MixGap.tsx
7745
- var React32 = __toESM(require("react"), 1);
7746
- var import_jsx_runtime62 = require("react/jsx-runtime");
7991
+ var React34 = __toESM(require("react"), 1);
7992
+ var import_jsx_runtime65 = require("react/jsx-runtime");
7747
7993
  function MixGap({ rows = [], loading = false, className = "" }) {
7748
7994
  const max = Math.max(1, ...rows.flatMap((r) => [r.target, r.realized]));
7749
- const [hover, setHover] = React32.useState(null);
7995
+ const [hover, setHover] = React34.useState(null);
7750
7996
  const toneOf = (gap) => gap >= -1 ? "ok" : gap >= -4 ? "warn" : "danger";
7751
7997
  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 } }),
7998
+ return /* @__PURE__ */ (0, import_jsx_runtime65.jsxs)("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 4 }, children: [
7999
+ /* @__PURE__ */ (0, import_jsx_runtime65.jsxs)("div", { className: "fd-row", style: { gap: 16, justifyContent: "flex-end", paddingBottom: 6, flexWrap: "wrap" }, children: [
8000
+ [["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: [
8001
+ /* @__PURE__ */ (0, import_jsx_runtime65.jsx)("span", { style: { width: 14, height: 9, borderRadius: 2, background: c } }),
7756
8002
  l
7757
8003
  ] }, 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)" } }),
8004
+ /* @__PURE__ */ (0, import_jsx_runtime65.jsxs)("span", { className: "fd-row fd-body-sm fd-muted", style: { gap: 6 }, children: [
8005
+ /* @__PURE__ */ (0, import_jsx_runtime65.jsx)("span", { style: { width: 3, height: 14, background: "var(--n-500)" } }),
7760
8006
  "Target"
7761
8007
  ] })
7762
8008
  ] }),
@@ -7764,7 +8010,7 @@ function MixGap({ rows = [], loading = false, className = "" }) {
7764
8010
  const gap = r.realized - r.target;
7765
8011
  const tone = toneOf(gap);
7766
8012
  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)(
8013
+ return /* @__PURE__ */ (0, import_jsx_runtime65.jsxs)(
7768
8014
  "div",
7769
8015
  {
7770
8016
  className: "fd-row",
@@ -7772,15 +8018,15 @@ function MixGap({ rows = [], loading = false, className = "" }) {
7772
8018
  onMouseEnter: () => setHover(r.channel),
7773
8019
  onMouseLeave: () => setHover(null),
7774
8020
  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: [
8021
+ /* @__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" }) }),
8022
+ /* @__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: [
8023
+ /* @__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)" } }),
8024
+ /* @__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 } }),
8025
+ /* @__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
8026
  r.realized,
7781
8027
  "%"
7782
8028
  ] }),
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
8029
+ 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
8030
  ] }) })
7785
8031
  ]
7786
8032
  },
@@ -7791,7 +8037,7 @@ function MixGap({ rows = [], loading = false, className = "" }) {
7791
8037
  }
7792
8038
 
7793
8039
  // src/components/planner/ChannelContribution.tsx
7794
- var import_jsx_runtime63 = require("react/jsx-runtime");
8040
+ var import_jsx_runtime66 = require("react/jsx-runtime");
7795
8041
  var money = (n) => "$" + Math.round(n).toLocaleString();
7796
8042
  function ChannelContribution({
7797
8043
  channels = [],
@@ -7807,9 +8053,9 @@ function ChannelContribution({
7807
8053
  const grand = total !== void 0 ? total : base + bonus;
7808
8054
  const pct = (v) => grand ? v / grand * 100 : 0;
7809
8055
  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)(
8056
+ return /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 16 }, children: [
8057
+ 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: [
8058
+ channels.map((c) => /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(
7813
8059
  "span",
7814
8060
  {
7815
8061
  title: c.name + " \xB7 " + c.crp.toFixed(1) + " CRP",
@@ -7818,7 +8064,7 @@ function ChannelContribution({
7818
8064
  },
7819
8065
  c.name
7820
8066
  )),
7821
- bonus > 0 ? /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(
8067
+ bonus > 0 ? /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(
7822
8068
  "span",
7823
8069
  {
7824
8070
  title: "Surround-sound bonus +" + bonusPct + "%",
@@ -7827,18 +8073,18 @@ function ChannelContribution({
7827
8073
  }
7828
8074
  ) : null
7829
8075
  ] }),
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" })
8076
+ showTable ? /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("table", { className: "fd-table", style: { fontSize: "var(--body-sm-size)" }, children: [
8077
+ /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("tr", { children: [
8078
+ /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("th", { style: { width: "34%" }, children: "Channel" }),
8079
+ /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("th", { style: { width: "16%" }, children: "Weight" }),
8080
+ /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("th", { className: "is-num", style: { width: "16%" }, children: "Spend" }),
8081
+ /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("th", { className: "is-num", style: { width: "17%" }, children: "CRP" }),
8082
+ /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("th", { className: "is-num", style: { width: "17%" }, children: "Share" })
7837
8083
  ] }) }),
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)(
8084
+ /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("tbody", { children: [
8085
+ channels.map((c) => /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("tr", { children: [
8086
+ /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("td", { children: /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(ChannelTag, { channel: c.name, size: "sm" }) }),
8087
+ /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("td", { children: /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(
7842
8088
  "span",
7843
8089
  {
7844
8090
  className: "fd-badge fd-badge-neutral",
@@ -7847,38 +8093,38 @@ function ChannelContribution({
7847
8093
  children: "weight " + (channelWeightOf(c.name) || 0)
7848
8094
  }
7849
8095
  ) }),
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: [
8096
+ /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("td", { className: "is-num", children: c.spend }),
8097
+ /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("td", { className: "is-num", children: c.crp.toFixed(1) }),
8098
+ /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("td", { className: "is-num", children: [
7853
8099
  pct(c.crp).toFixed(0),
7854
8100
  "%"
7855
8101
  ] })
7856
8102
  ] }, 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" } }),
8103
+ bonus > 0 ? /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("tr", { children: [
8104
+ /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("td", { children: /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("span", { className: "fd-row", style: { gap: 9, fontWeight: 600 }, children: [
8105
+ /* @__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
8106
  "Surround-sound bonus"
7861
8107
  ] }) }),
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: [
8108
+ /* @__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
8109
  "+",
7864
8110
  bonusPct,
7865
8111
  "% of +",
7866
8112
  bonusMax,
7867
8113
  "%"
7868
8114
  ] }) }),
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: [
8115
+ /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("td", { className: "is-num fd-muted", children: "\u2014" }),
8116
+ /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("td", { className: "is-num", children: bonus.toFixed(1) }),
8117
+ /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("td", { className: "is-num", children: [
7872
8118
  pct(bonus).toFixed(0),
7873
8119
  "%"
7874
8120
  ] })
7875
8121
  ] }) : 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%" })
8122
+ /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("tr", { style: { background: "var(--surface-2)" }, children: [
8123
+ /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("td", { style: { fontWeight: 700 }, children: "Campus total" }),
8124
+ /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("td", {}),
8125
+ /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("td", { className: "is-num", style: { fontWeight: 700 }, children: money(spendTotal) }),
8126
+ /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("td", { className: "is-num", style: { fontWeight: 700 }, children: grand.toFixed(1) }),
8127
+ /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("td", { className: "is-num", style: { fontWeight: 700 }, children: "100%" })
7882
8128
  ] })
7883
8129
  ] })
7884
8130
  ] }) : null
@@ -7886,8 +8132,8 @@ function ChannelContribution({
7886
8132
  }
7887
8133
 
7888
8134
  // src/components/planner/BudgetReallocator.tsx
7889
- var React33 = __toESM(require("react"), 1);
7890
- var import_jsx_runtime64 = require("react/jsx-runtime");
8135
+ var React35 = __toESM(require("react"), 1);
8136
+ var import_jsx_runtime67 = require("react/jsx-runtime");
7891
8137
  var bandFor = (crp) => crp >= 200 ? "dominant" : crp >= 100 ? "strong" : crp >= 50 ? "adequate" : "weak";
7892
8138
  function BudgetReallocator({
7893
8139
  campus,
@@ -7902,8 +8148,8 @@ function BudgetReallocator({
7902
8148
  onCancel,
7903
8149
  className = ""
7904
8150
  }) {
7905
- const [draft, setDraft] = React33.useState(spend);
7906
- React33.useEffect(() => setDraft(spend), [spend]);
8151
+ const [draft, setDraft] = React35.useState(spend);
8152
+ React35.useEffect(() => setDraft(spend), [spend]);
7907
8153
  const dirty = draft !== spend;
7908
8154
  const nextCrp = scoreFor ? scoreFor(draft) : crp;
7909
8155
  const nextBand = bandFor(nextCrp);
@@ -7918,24 +8164,24 @@ function BudgetReallocator({
7918
8164
  setDraft(spend);
7919
8165
  if (onCancel) onCancel();
7920
8166
  };
7921
- return /* @__PURE__ */ (0, import_jsx_runtime64.jsxs)(
8167
+ return /* @__PURE__ */ (0, import_jsx_runtime67.jsxs)(
7922
8168
  "div",
7923
8169
  {
7924
8170
  className: ["fd-stack", className].filter(Boolean).join(" "),
7925
8171
  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
8172
  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 })
8173
+ /* @__PURE__ */ (0, import_jsx_runtime67.jsxs)("div", { className: "fd-row", style: { gap: 12, flexWrap: "wrap" }, children: [
8174
+ /* @__PURE__ */ (0, import_jsx_runtime67.jsx)("span", { className: "fd-h4", style: { flex: 1, minWidth: 140 }, children: campus }),
8175
+ /* @__PURE__ */ (0, import_jsx_runtime67.jsx)(CsiBadge, { band: nowBand, crp: Number(crp.toFixed(1)), size: "medium" }),
8176
+ dirty ? /* @__PURE__ */ (0, import_jsx_runtime67.jsxs)(import_jsx_runtime67.Fragment, { children: [
8177
+ /* @__PURE__ */ (0, import_jsx_runtime67.jsx)("i", { className: "ph ph-arrow-right fd-muted", "aria-hidden": "true" }),
8178
+ /* @__PURE__ */ (0, import_jsx_runtime67.jsx)(CsiBadge, { band: nextBand, crp: Number(nextCrp.toFixed(1)), size: "medium", preview: true })
7933
8179
  ] }) : null
7934
8180
  ] }),
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)(
8181
+ /* @__PURE__ */ (0, import_jsx_runtime67.jsxs)("div", { className: "fd-slider", children: [
8182
+ /* @__PURE__ */ (0, import_jsx_runtime67.jsx)("span", { className: "fd-slider-fill", style: { width: pct + "%" } }),
8183
+ 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,
8184
+ /* @__PURE__ */ (0, import_jsx_runtime67.jsx)(
7939
8185
  "input",
7940
8186
  {
7941
8187
  type: "range",
@@ -7951,13 +8197,13 @@ function BudgetReallocator({
7951
8197
  }
7952
8198
  )
7953
8199
  ] }),
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." })
8200
+ /* @__PURE__ */ (0, import_jsx_runtime67.jsxs)("div", { className: "fd-row", style: { gap: 12, flexWrap: "wrap" }, children: [
8201
+ /* @__PURE__ */ (0, import_jsx_runtime67.jsxs)("span", { className: "fd-stack", style: { gap: 2, flex: 1, minWidth: 150 }, children: [
8202
+ /* @__PURE__ */ (0, import_jsx_runtime67.jsx)("span", { className: "fd-num", style: { fontSize: 19, fontWeight: 700 }, children: "$" + draft.toLocaleString() }),
8203
+ /* @__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
8204
  ] }),
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)(
8205
+ /* @__PURE__ */ (0, import_jsx_runtime67.jsx)("button", { type: "button", className: "fd-btn fd-btn-ghost", disabled: !dirty, onClick: revert, children: "Cancel" }),
8206
+ /* @__PURE__ */ (0, import_jsx_runtime67.jsx)(
7961
8207
  "button",
7962
8208
  {
7963
8209
  type: "button",
@@ -7976,7 +8222,7 @@ function BudgetReallocator({
7976
8222
  }
7977
8223
 
7978
8224
  // src/components/planner/SurroundSound.tsx
7979
- var import_jsx_runtime65 = require("react/jsx-runtime");
8225
+ var import_jsx_runtime68 = require("react/jsx-runtime");
7980
8226
  var CATEGORIES = [
7981
8227
  { key: "ooh", label: "OOH", icon: "flag-banner", color: "var(--ch-ooh)" },
7982
8228
  { key: "transit", label: "Transit", icon: "bus", color: "var(--ch-transit)" },
@@ -7988,26 +8234,26 @@ var CATEGORIES = [
7988
8234
  function SurroundSound({ present = [], bonusPct = 0, bonusMax = 40, missedCost, className = "" }) {
7989
8235
  const earned = Math.max(0, Math.min(1, bonusPct / bonusMax));
7990
8236
  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) => {
8237
+ return /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 14 }, children: [
8238
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("div", { className: "fd-row", style: { gap: 8, flexWrap: "wrap" }, children: CATEGORIES.map((c) => {
7993
8239
  const on = present.includes(c.key);
7994
- return /* @__PURE__ */ (0, import_jsx_runtime65.jsxs)(
8240
+ return /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)(
7995
8241
  "span",
7996
8242
  {
7997
8243
  title: c.label + (on ? " \u2014 present" : " \u2014 not bought"),
7998
8244
  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
8245
  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 })
8246
+ /* @__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" }),
8247
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("span", { style: { fontSize: 10.5, fontWeight: 700 }, children: c.label })
8002
8248
  ]
8003
8249
  },
8004
8250
  c.key
8005
8251
  );
8006
8252
  }) }),
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: [
8253
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)("div", { className: "fd-stack", style: { gap: 8 }, children: [
8254
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)("div", { className: "fd-row", style: { justifyContent: "space-between", gap: 12 }, children: [
8255
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("span", { className: "fd-label-lg", children: "Surround-sound bonus earned" }),
8256
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)("span", { className: "fd-num", style: { color: single ? "var(--warn-text)" : "var(--csi-3-mark)", fontWeight: 700 }, children: [
8011
8257
  "+",
8012
8258
  bonusPct,
8013
8259
  "% of +",
@@ -8015,8 +8261,8 @@ function SurroundSound({ present = [], bonusPct = 0, bonusMax = 40, missedCost,
8015
8261
  "%"
8016
8262
  ] })
8017
8263
  ] }),
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: [
8264
+ /* @__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)" } }) }),
8265
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)("span", { className: "fd-body-sm fd-secondary", style: { textWrap: "pretty" }, children: [
8020
8266
  present.length,
8021
8267
  " of 6 channel categories present.",
8022
8268
  " ",
@@ -8028,10 +8274,10 @@ function SurroundSound({ present = [], bonusPct = 0, bonusMax = 40, missedCost,
8028
8274
  }
8029
8275
 
8030
8276
  // src/components/chat/AgentChatPanel.tsx
8031
- var React39 = __toESM(require("react"), 1);
8277
+ var React41 = __toESM(require("react"), 1);
8032
8278
 
8033
8279
  // src/components/chat/chatEngine.ts
8034
- var React34 = __toESM(require("react"), 1);
8280
+ var React36 = __toESM(require("react"), 1);
8035
8281
  var CHAT_UNAVAILABLE = "chat_unavailable";
8036
8282
  var JOB_PENDING = ["queued", "running"];
8037
8283
  var JOB_SUCCESS = ["completed", "recovered"];
@@ -8085,22 +8331,22 @@ function useChatEngine(opts) {
8085
8331
  onClear,
8086
8332
  onFeedback
8087
8333
  } = 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(() => {
8334
+ const [status, setStatus] = React36.useState("idle");
8335
+ const [threadId, setThreadId] = React36.useState(null);
8336
+ const [messages, setMessages] = React36.useState([]);
8337
+ const [queue, setQueue] = React36.useState([]);
8338
+ const [fatal, setFatal] = React36.useState(null);
8339
+ const [busy, setBusy] = React36.useState(false);
8340
+ const [turnStartedAt, setTurnStartedAt] = React36.useState(null);
8341
+ const listRef = React36.useRef([]);
8342
+ const queueRef = React36.useRef([]);
8343
+ const busyRef = React36.useRef(false);
8344
+ const stoppedRef = React36.useRef(false);
8345
+ const abortRef = React36.useRef(null);
8346
+ const serverCount = React36.useRef(0);
8347
+ const threadRef = React36.useRef(null);
8348
+ const mounted = React36.useRef(true);
8349
+ React36.useEffect(() => {
8104
8350
  mounted.current = true;
8105
8351
  return () => {
8106
8352
  mounted.current = false;
@@ -8122,14 +8368,14 @@ function useChatEngine(opts) {
8122
8368
  }
8123
8369
  return false;
8124
8370
  };
8125
- const loadThread = React34.useCallback(async (id) => {
8371
+ const loadThread = React36.useCallback(async (id) => {
8126
8372
  const data = await apiAdapter.getThread(id);
8127
8373
  const list = [...data && data.messages || []];
8128
8374
  serverCount.current = list.length;
8129
8375
  commit(list);
8130
8376
  return list;
8131
8377
  }, [apiAdapter]);
8132
- React34.useEffect(() => {
8378
+ React36.useEffect(() => {
8133
8379
  if (!apiAdapter) {
8134
8380
  setStatus("idle");
8135
8381
  setFatal(null);
@@ -8342,7 +8588,7 @@ function useChatEngine(opts) {
8342
8588
  await dispatchTurn(turn);
8343
8589
  }
8344
8590
  }
8345
- const send = React34.useCallback((text, attachments) => {
8591
+ const send = React36.useCallback((text, attachments) => {
8346
8592
  const body = (text || "").trim();
8347
8593
  if (!body && !(attachments && attachments.length)) return;
8348
8594
  if (status === "disconnected") return;
@@ -8352,7 +8598,7 @@ function useChatEngine(opts) {
8352
8598
  stoppedRef.current = false;
8353
8599
  drain();
8354
8600
  }, [status]);
8355
- const stop = React34.useCallback(() => {
8601
+ const stop = React36.useCallback(() => {
8356
8602
  stoppedRef.current = true;
8357
8603
  const ac = abortRef.current;
8358
8604
  if (ac) {
@@ -8371,11 +8617,11 @@ function useChatEngine(opts) {
8371
8617
  store.del(STORAGE_PREFIX + threadRef.current);
8372
8618
  }
8373
8619
  }, [apiAdapter]);
8374
- const removeQueued = React34.useCallback((id) => {
8620
+ const removeQueued = React36.useCallback((id) => {
8375
8621
  queueRef.current = queueRef.current.filter((t) => t.id !== id);
8376
8622
  setQueue(queueRef.current.slice());
8377
8623
  }, []);
8378
- const retry = React34.useCallback(() => {
8624
+ const retry = React36.useCallback(() => {
8379
8625
  const list = listRef.current;
8380
8626
  let at = -1;
8381
8627
  for (let i = list.length - 1; i >= 0; i--) if (list[i].role === "user") {
@@ -8391,19 +8637,19 @@ function useChatEngine(opts) {
8391
8637
  setQueue(queueRef.current.slice());
8392
8638
  drain();
8393
8639
  }, []);
8394
- const clear = React34.useCallback(() => {
8640
+ const clear = React36.useCallback(() => {
8395
8641
  commit([]);
8396
8642
  serverCount.current = 0;
8397
8643
  queueRef.current = [];
8398
8644
  setQueue([]);
8399
8645
  onClear && onClear();
8400
8646
  }, [onClear]);
8401
- const setFeedback = React34.useCallback((id, value) => {
8647
+ const setFeedback = React36.useCallback((id, value) => {
8402
8648
  patch(id, (m) => ({ feedback: m.feedback === value ? null : value }));
8403
8649
  const msg = listRef.current.find((m) => m.id === id);
8404
8650
  onFeedback && onFeedback({ message: msg, feedback: msg ? msg.feedback : value });
8405
8651
  }, [onFeedback]);
8406
- const reload = React34.useCallback(async () => {
8652
+ const reload = React36.useCallback(async () => {
8407
8653
  if (!threadRef.current) return;
8408
8654
  setStatus("loading");
8409
8655
  try {
@@ -8441,11 +8687,11 @@ var ChatKit = {
8441
8687
  };
8442
8688
 
8443
8689
  // src/components/chat/ChatTranscript.tsx
8444
- var React36 = __toESM(require("react"), 1);
8690
+ var React38 = __toESM(require("react"), 1);
8445
8691
 
8446
8692
  // src/components/chat/ChatTurn.tsx
8447
- var React35 = __toESM(require("react"), 1);
8448
- var import_jsx_runtime66 = require("react/jsx-runtime");
8693
+ var React37 = __toESM(require("react"), 1);
8694
+ var import_jsx_runtime69 = require("react/jsx-runtime");
8449
8695
  function JsonView({ value }) {
8450
8696
  let text;
8451
8697
  try {
@@ -8453,67 +8699,67 @@ function JsonView({ value }) {
8453
8699
  } catch (e) {
8454
8700
  text = String(value);
8455
8701
  }
8456
- return /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(CodeBlock, { code: text, language: "json", collapseAfter: 18 });
8702
+ return /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(CodeBlock, { code: text, language: "json", collapseAfter: 18 });
8457
8703
  }
8458
8704
  function PacketCard({ packet, schema, render, onApply, applied }) {
8459
8705
  if (!packet) return null;
8460
8706
  const s = schema || {};
8461
8707
  const invalid = packet.valid === false;
8462
8708
  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
8709
+ return /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("section", { className: "fdc-packet" + (invalid ? " is-invalid" : ""), "aria-label": title, children: [
8710
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("header", { className: "fdc-packet-head", children: [
8711
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("i", { className: "ph ph-" + (s.icon || "package"), "aria-hidden": "true" }),
8712
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("span", { className: "fdc-packet-title", children: title }),
8713
+ packet.repaired ? /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("span", { className: "fdc-packet-badge", children: "Repaired" }) : null,
8714
+ invalid ? /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("span", { className: "fdc-packet-badge is-danger", children: "Invalid" }) : null
8469
8715
  ] }),
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" }),
8716
+ invalid ? /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("div", { className: "fdc-packet-alert", role: "alert", children: [
8717
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
8718
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("span", { children: packet.error || "This result failed validation and can\u2019t be applied." })
8719
+ ] }) : /* @__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 }) }),
8720
+ !invalid && onApply ? /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("footer", { className: "fdc-packet-foot", children: [
8721
+ 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", {}),
8722
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("button", { type: "button", className: "fd-btn fd-btn-primary fd-btn-sm", disabled: applied, onClick: () => onApply(packet), children: [
8723
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("i", { className: "ph ph-" + (applied ? "check" : "arrow-square-in"), "aria-hidden": "true" }),
8478
8724
  applied ? "Applied" : s.applyLabel || "Apply"
8479
8725
  ] })
8480
8726
  ] }) : null
8481
8727
  ] });
8482
8728
  }
8483
8729
  function ThinkingBlock({ text, durationMs, streaming, defaultOpen = false }) {
8484
- const [open, setOpen] = React35.useState(defaultOpen);
8730
+ const [open, setOpen] = React37.useState(defaultOpen);
8485
8731
  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", {})
8732
+ return /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("div", { className: "fdc-think" + (open ? " is-open" : ""), children: [
8733
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("button", { type: "button", className: "fdc-think-head", onClick: () => setOpen((v) => !v), "aria-expanded": open, children: [
8734
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("i", { className: "ph ph-brain", "aria-hidden": "true" }),
8735
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("span", { children: streaming ? "Thinking" : durationMs ? "Thought for " + formatDuration(durationMs) : "Thought process" }),
8736
+ streaming ? /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("span", { className: "fdc-dots", "aria-hidden": "true", children: [
8737
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("span", {}),
8738
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("span", {}),
8739
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("span", {})
8494
8740
  ] }) : null,
8495
- /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("i", { className: "ph ph-caret-" + (open ? "up" : "down"), "aria-hidden": "true" })
8741
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("i", { className: "ph ph-caret-" + (open ? "up" : "down"), "aria-hidden": "true" })
8496
8742
  ] }),
8497
- open ? /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("div", { className: "fdc-think-body", children: text }) : null
8743
+ open ? /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("div", { className: "fdc-think-body", children: text }) : null
8498
8744
  ] });
8499
8745
  }
8500
8746
  function Citations({ items = [], onOpen }) {
8501
- const [open, setOpen] = React35.useState(false);
8747
+ const [open, setOpen] = React37.useState(false);
8502
8748
  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: [
8749
+ return /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("div", { className: "fdc-cites", children: [
8750
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("button", { type: "button", className: "fdc-cites-head", onClick: () => setOpen((v) => !v), "aria-expanded": open, children: [
8751
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("i", { className: "ph ph-quotes", "aria-hidden": "true" }),
8752
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("span", { children: [
8507
8753
  items.length,
8508
8754
  " source",
8509
8755
  items.length === 1 ? "" : "s"
8510
8756
  ] }),
8511
- /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("i", { className: "ph ph-caret-" + (open ? "up" : "down"), "aria-hidden": "true" })
8757
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("i", { className: "ph ph-caret-" + (open ? "up" : "down"), "aria-hidden": "true" })
8512
8758
  ] }),
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
8759
+ 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: [
8760
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("span", { className: "fdc-cite-n fd-tabular", children: c.marker || i + 1 }),
8761
+ 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" }),
8762
+ c.detail ? /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("span", { className: "fdc-cite-detail", children: c.detail }) : null
8517
8763
  ] }, c.id || i)) }) : null
8518
8764
  ] });
8519
8765
  }
@@ -8524,29 +8770,29 @@ function clampText(text, max) {
8524
8770
  return (at > max * 0.6 ? cut.slice(0, at) : cut).trimEnd() + "\u2026";
8525
8771
  }
8526
8772
  function MessageBody({ message: m, ctx }) {
8527
- const [expanded, setExpanded] = React35.useState(false);
8773
+ const [expanded, setExpanded] = React37.useState(false);
8528
8774
  const isUser = m.role === "user";
8529
8775
  const raw = m.text || "";
8530
8776
  const clamped = !expanded && !m.streaming ? clampText(raw, ctx.maxVisibleChars) : null;
8531
8777
  const body = clamped != null ? clamped : raw;
8532
8778
  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
8779
+ return /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("div", { className: "fdc-body", children: [
8780
+ m.thinking && ctx.showThinking ? /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(ThinkingBlock, { text: m.thinking, durationMs: m.thinkingMs, streaming: m.streaming && !m.text }) : null,
8781
+ 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,
8782
+ body ? /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("div", { className: "fdc-text" + (isUser ? " is-user" : ""), children: [
8783
+ 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 }),
8784
+ m.streaming ? /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("span", { className: "fdc-caret", "aria-hidden": "true" }) : null
8539
8785
  ] }) : 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" }),
8786
+ clamped != null ? /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("button", { type: "button", className: "fdc-more", onClick: () => setExpanded(true), children: [
8787
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("i", { className: "ph ph-caret-down", "aria-hidden": "true" }),
8542
8788
  "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" }),
8789
+ /* @__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" })
8790
+ ] }) : expanded && ctx.maxVisibleChars && raw.length > ctx.maxVisibleChars ? /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("button", { type: "button", className: "fdc-more", onClick: () => setExpanded(false), children: [
8791
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("i", { className: "ph ph-caret-up", "aria-hidden": "true" }),
8546
8792
  "Show less"
8547
8793
  ] }) : 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)(
8794
+ 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,
8795
+ m.packet ? /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(
8550
8796
  PacketCard,
8551
8797
  {
8552
8798
  packet: m.packet,
@@ -8556,44 +8802,44 @@ function MessageBody({ message: m, ctx }) {
8556
8802
  applied: ctx.appliedPackets && ctx.appliedPackets[m.id]
8557
8803
  }
8558
8804
  ) : 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", {})
8805
+ m.citations && m.citations.length ? /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(Citations, { items: m.citations, onOpen: ctx.onOpenCitation }) : null,
8806
+ m.working ? /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("div", { className: "fdc-working", role: "status", children: [
8807
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("span", { className: "fdc-dots", "aria-hidden": "true", children: [
8808
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("span", {}),
8809
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("span", {}),
8810
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("span", {})
8565
8811
  ] }),
8566
- /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("span", { className: "fdc-working-label", children: [
8812
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("span", { className: "fdc-working-label", children: [
8567
8813
  m.resumed ? "Resuming" : "Working",
8568
- m.job && m.job.status ? /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("span", { className: "fdc-working-job", children: [
8814
+ m.job && m.job.status ? /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("span", { className: "fdc-working-job", children: [
8569
8815
  " \xB7 ",
8570
8816
  m.job.status
8571
8817
  ] }) : null,
8572
- m.job && m.job.detail ? /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("span", { className: "fdc-working-job", children: [
8818
+ m.job && m.job.detail ? /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("span", { className: "fdc-working-job", children: [
8573
8819
  " \xB7 ",
8574
8820
  m.job.detail
8575
8821
  ] }) : null
8576
8822
  ] }),
8577
- m.jobId ? /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("span", { className: "fdc-working-id fd-mono", children: String(m.jobId).slice(0, 12) }) : null
8823
+ m.jobId ? /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("span", { className: "fdc-working-id fd-mono", children: String(m.jobId).slice(0, 12) }) : null
8578
8824
  ] }) : 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" }),
8825
+ m.stopped ? /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("div", { className: "fdc-stopped", children: [
8826
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("i", { className: "ph ph-stop-circle", "aria-hidden": "true" }),
8581
8827
  "Stopped"
8582
8828
  ] }) : 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" }),
8829
+ m.error ? /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("div", { className: "fdc-error", role: "alert", children: [
8830
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
8831
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("span", { className: "fdc-error-text", children: ctx.errorCopy ? ctx.errorCopy(m.error) : m.error }),
8832
+ m.retryable && ctx.onRetry ? /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("button", { type: "button", className: "fdc-error-retry", onClick: ctx.onRetry, children: [
8833
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("i", { className: "ph ph-arrow-clockwise", "aria-hidden": "true" }),
8588
8834
  "Retry"
8589
8835
  ] }) : null
8590
8836
  ] }) : null
8591
8837
  ] });
8592
8838
  }
8593
8839
  function useCopyRun() {
8594
- const [done, setDone] = React35.useState(false);
8595
- const t = React35.useRef(null);
8596
- React35.useEffect(() => () => {
8840
+ const [done, setDone] = React37.useState(false);
8841
+ const t = React37.useRef(null);
8842
+ React37.useEffect(() => () => {
8597
8843
  if (t.current) clearTimeout(t.current);
8598
8844
  }, []);
8599
8845
  return [done, (text) => {
@@ -8613,16 +8859,16 @@ function RunActions({ group, ctx }) {
8613
8859
  const isAssistant = group.role === "assistant";
8614
8860
  const fb = last.feedback;
8615
8861
  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" })
8862
+ return /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("div", { className: "fdc-actions", role: "group", "aria-label": "Message actions", children: [
8863
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("button", { type: "button", className: "fdc-act" + (copied ? " is-done" : ""), onClick: () => copy(markdownToText(text)), "aria-label": "Copy message", children: [
8864
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("i", { className: "ph ph-" + (copied ? "check" : "copy"), "aria-hidden": "true" }),
8865
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("span", { className: "fdc-act-label", children: copied ? "Copied" : "Copy" })
8620
8866
  ] }),
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" }) })
8867
+ 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,
8868
+ 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,
8869
+ isAssistant && ctx.onFeedback ? /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)(React37.Fragment, { children: [
8870
+ /* @__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" }) }),
8871
+ /* @__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
8872
  ] }) : null,
8627
8873
  ctx.extraActions ? ctx.extraActions(group) : null
8628
8874
  ] });
@@ -8632,22 +8878,22 @@ function ChatTurn({ group, ctx }) {
8632
8878
  const name = isUser ? ctx.userName : group.author || ctx.assistantName;
8633
8879
  const avatar = isUser ? ctx.userAvatar : ctx.assistantAvatar;
8634
8880
  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
8881
+ return /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("article", { className: "fdc-turn is-" + group.role, "aria-label": String(name) + (stamp ? " at " + formatClock(stamp) : ""), children: [
8882
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("div", { className: "fdc-turn-head", children: [
8883
+ 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,
8884
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("span", { className: "fdc-who", children: name }),
8885
+ stamp ? /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(RelativeTime, { className: "fdc-when", value: stamp }) : null,
8886
+ 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
8887
  ] }),
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 })
8888
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("div", { className: "fdc-turn-body", children: [
8889
+ 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)),
8890
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(RunActions, { group, ctx })
8645
8891
  ] })
8646
8892
  ] });
8647
8893
  }
8648
8894
 
8649
8895
  // src/components/chat/ChatTranscript.tsx
8650
- var import_jsx_runtime67 = require("react/jsx-runtime");
8896
+ var import_jsx_runtime70 = require("react/jsx-runtime");
8651
8897
  var GROUP_WINDOW = 6e4;
8652
8898
  var STICK_PX = 100;
8653
8899
  function groupMessages(list) {
@@ -8680,25 +8926,25 @@ function dayLabel(key) {
8680
8926
  }
8681
8927
  function Suggestions({ items = [], onPick }) {
8682
8928
  if (!items.length) return null;
8683
- return /* @__PURE__ */ (0, import_jsx_runtime67.jsx)("div", { className: "fdc-suggest", children: items.map((s, i) => {
8929
+ return /* @__PURE__ */ (0, import_jsx_runtime70.jsx)("div", { className: "fdc-suggest", children: items.map((s, i) => {
8684
8930
  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
8931
+ return /* @__PURE__ */ (0, import_jsx_runtime70.jsxs)("button", { type: "button", className: "fdc-suggest-item", onClick: () => onPick && onPick(it.text || it.label), children: [
8932
+ it.icon ? /* @__PURE__ */ (0, import_jsx_runtime70.jsx)("i", { className: "ph ph-" + it.icon, "aria-hidden": "true" }) : null,
8933
+ /* @__PURE__ */ (0, import_jsx_runtime70.jsxs)("span", { className: "fdc-suggest-text", children: [
8934
+ /* @__PURE__ */ (0, import_jsx_runtime70.jsx)("span", { className: "fdc-suggest-label", children: it.label }),
8935
+ it.description ? /* @__PURE__ */ (0, import_jsx_runtime70.jsx)("span", { className: "fdc-suggest-desc", children: it.description }) : null
8690
8936
  ] }),
8691
- /* @__PURE__ */ (0, import_jsx_runtime67.jsx)("i", { className: "ph ph-arrow-up-right fdc-suggest-go", "aria-hidden": "true" })
8937
+ /* @__PURE__ */ (0, import_jsx_runtime70.jsx)("i", { className: "ph ph-arrow-up-right fdc-suggest-go", "aria-hidden": "true" })
8692
8938
  ] }, it.id || i);
8693
8939
  }) });
8694
8940
  }
8695
8941
  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 } })
8942
+ 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: [
8943
+ /* @__PURE__ */ (0, import_jsx_runtime70.jsx)("div", { className: "fd-skel fd-skel-circle", style: { width: 22, height: 22 } }),
8944
+ /* @__PURE__ */ (0, import_jsx_runtime70.jsxs)("div", { className: "fdc-skel-lines", children: [
8945
+ /* @__PURE__ */ (0, import_jsx_runtime70.jsx)("div", { className: "fd-skel", style: { width: i ? "62%" : "44%", height: 11 } }),
8946
+ /* @__PURE__ */ (0, import_jsx_runtime70.jsx)("div", { className: "fd-skel", style: { width: i ? "94%" : "78%", height: 11 } }),
8947
+ /* @__PURE__ */ (0, import_jsx_runtime70.jsx)("div", { className: "fd-skel", style: { width: i ? "71%" : "56%", height: 11 } })
8702
8948
  ] })
8703
8949
  ] }, i)) });
8704
8950
  }
@@ -8715,10 +8961,10 @@ function ChatTranscript({
8715
8961
  renderEmpty,
8716
8962
  className = ""
8717
8963
  }) {
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);
8964
+ const scroller = React38.useRef(null);
8965
+ const stick = React38.useRef(true);
8966
+ const [pill, setPill] = React38.useState(0);
8967
+ const seen = React38.useRef(0);
8722
8968
  const toBottom = (smooth) => {
8723
8969
  const el = scroller.current;
8724
8970
  if (!el) return;
@@ -8737,7 +8983,7 @@ function ChatTranscript({
8737
8983
  seen.current = messages.length;
8738
8984
  }
8739
8985
  };
8740
- React36.useLayoutEffect(() => {
8986
+ React38.useLayoutEffect(() => {
8741
8987
  const el = scroller.current;
8742
8988
  if (!el) return;
8743
8989
  if (stick.current) {
@@ -8745,7 +8991,7 @@ function ChatTranscript({
8745
8991
  seen.current = messages.length;
8746
8992
  } else setPill(Math.max(0, messages.length - seen.current));
8747
8993
  }, [messages]);
8748
- React36.useEffect(() => {
8994
+ React38.useEffect(() => {
8749
8995
  const el = scroller.current;
8750
8996
  const inner = el && el.firstChild;
8751
8997
  if (!el || !inner || typeof ResizeObserver === "undefined") return;
@@ -8755,38 +9001,38 @@ function ChatTranscript({
8755
9001
  ro.observe(inner);
8756
9002
  return () => ro.disconnect();
8757
9003
  }, []);
8758
- const groups = React36.useMemo(() => groupMessages(messages), [messages]);
9004
+ const groups = React38.useMemo(() => groupMessages(messages), [messages]);
8759
9005
  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" }),
9006
+ return /* @__PURE__ */ (0, import_jsx_runtime70.jsxs)("div", { className: ["fdc-scroll", className].filter(Boolean).join(" "), ref: scroller, onScroll, children: [
9007
+ /* @__PURE__ */ (0, import_jsx_runtime70.jsxs)("div", { className: "fdc-log", role: "log", "aria-label": "Conversation", children: [
9008
+ status === "loading" || status === "resolving" ? /* @__PURE__ */ (0, import_jsx_runtime70.jsx)(LoadingTurns, {}) : null,
9009
+ status === "disconnected" ? /* @__PURE__ */ (0, import_jsx_runtime70.jsxs)("div", { className: "fdc-dead", children: [
9010
+ /* @__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" }) }),
9011
+ /* @__PURE__ */ (0, import_jsx_runtime70.jsx)("h3", { className: "fdc-dead-title", children: ctx.deadTitle || "The assistant isn\u2019t reachable" }),
9012
+ /* @__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." }),
9013
+ ctx.onReconnect ? /* @__PURE__ */ (0, import_jsx_runtime70.jsxs)("button", { type: "button", className: "fd-btn fd-btn-secondary fd-btn-sm", onClick: ctx.onReconnect, children: [
9014
+ /* @__PURE__ */ (0, import_jsx_runtime70.jsx)("i", { className: "ph ph-arrow-clockwise", "aria-hidden": "true" }),
8769
9015
  "Try again"
8770
9016
  ] }) : null
8771
9017
  ] }) : 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 })
9018
+ empty ? renderEmpty ? renderEmpty() : /* @__PURE__ */ (0, import_jsx_runtime70.jsxs)("div", { className: "fdc-empty", children: [
9019
+ /* @__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" }) }),
9020
+ /* @__PURE__ */ (0, import_jsx_runtime70.jsx)("h3", { className: "fdc-empty-title", children: emptyTitle }),
9021
+ emptyDescription ? /* @__PURE__ */ (0, import_jsx_runtime70.jsx)("p", { className: "fdc-empty-body", children: emptyDescription }) : null,
9022
+ /* @__PURE__ */ (0, import_jsx_runtime70.jsx)(Suggestions, { items: suggestions, onPick })
8777
9023
  ] }) : null,
8778
9024
  groups.map((g, i) => {
8779
9025
  const prev = groups[i - 1];
8780
9026
  const k = dayKey(g.messages[0].timestamp);
8781
9027
  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 })
9028
+ return /* @__PURE__ */ (0, import_jsx_runtime70.jsxs)(React38.Fragment, { children: [
9029
+ showDay ? /* @__PURE__ */ (0, import_jsx_runtime70.jsx)("div", { className: "fdc-day", children: /* @__PURE__ */ (0, import_jsx_runtime70.jsx)("span", { children: dayLabel(k) }) }) : null,
9030
+ /* @__PURE__ */ (0, import_jsx_runtime70.jsx)(ChatTurn, { group: g, ctx })
8785
9031
  ] }, g.key || i);
8786
9032
  })
8787
9033
  ] }),
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" }),
9034
+ pill ? /* @__PURE__ */ (0, import_jsx_runtime70.jsxs)("button", { type: "button", className: "fdc-pill", onClick: () => toBottom(true), children: [
9035
+ /* @__PURE__ */ (0, import_jsx_runtime70.jsx)("i", { className: "ph ph-arrow-down", "aria-hidden": "true" }),
8790
9036
  pill,
8791
9037
  " new message",
8792
9038
  pill === 1 ? "" : "s"
@@ -8796,8 +9042,8 @@ function ChatTranscript({
8796
9042
  var TranscriptKit = { groupMessages };
8797
9043
 
8798
9044
  // src/components/chat/ChatComposer.tsx
8799
- var React37 = __toESM(require("react"), 1);
8800
- var import_jsx_runtime68 = require("react/jsx-runtime");
9045
+ var React39 = __toESM(require("react"), 1);
9046
+ var import_jsx_runtime71 = require("react/jsx-runtime");
8801
9047
  function ChatComposer({
8802
9048
  onSubmit,
8803
9049
  onStop,
@@ -8824,17 +9070,17 @@ function ChatComposer({
8824
9070
  onReject,
8825
9071
  onOpenAttachment
8826
9072
  }) {
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);
9073
+ const [text, setText] = React39.useState(draft || "");
9074
+ const [trigger, setTrigger] = React39.useState(null);
9075
+ const [mentionItems, setMentionItems] = React39.useState([]);
9076
+ const [listening, setListening] = React39.useState(false);
9077
+ const [notice, setNotice] = React39.useState(null);
9078
+ const editor = React39.useRef(null);
9079
+ const wrap = React39.useRef(null);
9080
+ const stopVoice = React39.useRef(null);
8835
9081
  const staged = useStagedFiles(fileUploadHandler, { onError: () => {
8836
9082
  } });
8837
- React37.useEffect(() => {
9083
+ React39.useEffect(() => {
8838
9084
  if (draft != null && draft !== text) setText(draft);
8839
9085
  }, [draft]);
8840
9086
  const change = (v) => {
@@ -8868,7 +9114,7 @@ function ChatComposer({
8868
9114
  e.preventDefault();
8869
9115
  staged.add(found.files);
8870
9116
  };
8871
- React37.useEffect(() => {
9117
+ React39.useEffect(() => {
8872
9118
  if (!trigger || trigger.type !== "mention" || !mentionSources) {
8873
9119
  setMentionItems([]);
8874
9120
  return;
@@ -8886,7 +9132,7 @@ function ChatComposer({
8886
9132
  const q = (trigger.query || "").toLowerCase();
8887
9133
  setMentionItems(mentionSources.filter((m) => !q || (m.label + " " + (m.description || "")).toLowerCase().includes(q)));
8888
9134
  }, [trigger, mentionSources]);
8889
- const slashItems = React37.useMemo(() => {
9135
+ const slashItems = React39.useMemo(() => {
8890
9136
  if (!trigger || trigger.type !== "slash" || !slashCommands) return [];
8891
9137
  const q = (trigger.query || "").toLowerCase();
8892
9138
  return slashCommands.filter((c) => !q || (c.id + " " + c.label + " " + (c.description || "")).toLowerCase().includes(q));
@@ -8900,7 +9146,7 @@ function ChatComposer({
8900
9146
  description: it.description,
8901
9147
  icon: it.icon,
8902
9148
  meta: mention.meta,
8903
- shortcut: slash.shortcut ? /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(KeyHint, { keys: slash.shortcut, size: "sm" }) : void 0,
9149
+ shortcut: slash.shortcut ? /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(KeyHint, { keys: slash.shortcut, size: "sm" }) : void 0,
8904
9150
  onSelect: () => {
8905
9151
  const insert = trigger.type === "slash" ? slash.immediate ? "/" + slash.id : "/" + slash.id + " " : "@" + (mention.value || mention.label) + " ";
8906
9152
  editor.current && editor.current.replaceRange(trigger.from, trigger.to, insert);
@@ -8963,14 +9209,14 @@ function ChatComposer({
8963
9209
  stopVoice.current = typeof res === "function" ? res : () => {
8964
9210
  };
8965
9211
  };
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
9212
+ return /* @__PURE__ */ (0, import_jsx_runtime71.jsxs)("div", { className: "fdc-composer" + (disabled ? " is-disabled" : "") + (narrow ? " is-narrow" : ""), children: [
9213
+ 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: [
9214
+ /* @__PURE__ */ (0, import_jsx_runtime71.jsx)("i", { className: "ph ph-clock-countdown", "aria-hidden": "true" }),
9215
+ /* @__PURE__ */ (0, import_jsx_runtime71.jsx)("span", { className: "fdc-queue-text", children: q.text || (q.attachments ? q.attachments.length + " file(s)" : "") }),
9216
+ 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
9217
  ] }, q.id)) }) : null,
8972
9218
  sessionBar,
8973
- /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(
9219
+ /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
8974
9220
  Dropzone,
8975
9221
  {
8976
9222
  className: "fdc-field",
@@ -8984,9 +9230,9 @@ function ChatComposer({
8984
9230
  disabled: !fileUploadHandler || disabled,
8985
9231
  label: "Drop to attach",
8986
9232
  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)(
9233
+ children: /* @__PURE__ */ (0, import_jsx_runtime71.jsxs)("div", { ref: wrap, className: "fdc-field-inner", children: [
9234
+ 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,
9235
+ /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
8990
9236
  MarkdownEditor,
8991
9237
  {
8992
9238
  ref: editor,
@@ -9005,33 +9251,33 @@ function ChatComposer({
9005
9251
  ariaLabel: "Message"
9006
9252
  }
9007
9253
  ),
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,
9254
+ /* @__PURE__ */ (0, import_jsx_runtime71.jsxs)("div", { className: "fdc-tools", children: [
9255
+ 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,
9256
+ 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
9257
  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: [
9258
+ /* @__PURE__ */ (0, import_jsx_runtime71.jsx)("span", { className: "fdc-tools-gap" }),
9259
+ 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
9260
  text.length,
9015
9261
  "/",
9016
9262
  maxLength
9017
9263
  ] }) : 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" })
9264
+ busy ? /* @__PURE__ */ (0, import_jsx_runtime71.jsxs)("button", { type: "button", className: "fdc-stop", onClick: onStop, "aria-label": "Stop generating", children: [
9265
+ /* @__PURE__ */ (0, import_jsx_runtime71.jsx)("i", { className: "ph ph-stop-circle", "aria-hidden": "true" }),
9266
+ /* @__PURE__ */ (0, import_jsx_runtime71.jsx)("span", { children: "Stop" })
9267
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime71.jsxs)("button", { type: "button", className: "fdc-send", onClick: submit, disabled: !canSend, "aria-label": "Send message", children: [
9268
+ /* @__PURE__ */ (0, import_jsx_runtime71.jsx)("i", { className: "ph ph-paper-plane-right", "aria-hidden": "true" }),
9269
+ /* @__PURE__ */ (0, import_jsx_runtime71.jsx)("span", { className: "fdc-send-label", children: "Send" })
9024
9270
  ] })
9025
9271
  ] })
9026
9272
  ] })
9027
9273
  }
9028
9274
  ),
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" }),
9275
+ notice ? /* @__PURE__ */ (0, import_jsx_runtime71.jsxs)("div", { className: "fdc-notice", role: "status", children: [
9276
+ /* @__PURE__ */ (0, import_jsx_runtime71.jsx)("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
9031
9277
  notice
9032
9278
  ] }) : null,
9033
- hint && !notice ? /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("div", { className: "fdc-hint", children: hint }) : null,
9034
- /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(
9279
+ hint && !notice ? /* @__PURE__ */ (0, import_jsx_runtime71.jsx)("div", { className: "fdc-hint", children: hint }) : null,
9280
+ /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
9035
9281
  Popover,
9036
9282
  {
9037
9283
  open: menuOpen,
@@ -9045,12 +9291,12 @@ function ChatComposer({
9045
9291
  returnFocus: false,
9046
9292
  closeOnOutside: true,
9047
9293
  label: trigger && trigger.type === "slash" ? "Commands" : "Mentions",
9048
- children: /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(
9294
+ children: /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
9049
9295
  Menu,
9050
9296
  {
9051
9297
  items: menuItems,
9052
9298
  autoFocus: false,
9053
- header: /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("div", { className: "fd-pop-group", children: trigger && trigger.type === "slash" ? "Commands" : "Attach context" }),
9299
+ header: /* @__PURE__ */ (0, import_jsx_runtime71.jsx)("div", { className: "fd-pop-group", children: trigger && trigger.type === "slash" ? "Commands" : "Attach context" }),
9054
9300
  onClose: () => setTrigger(null)
9055
9301
  }
9056
9302
  )
@@ -9060,12 +9306,12 @@ function ChatComposer({
9060
9306
  }
9061
9307
 
9062
9308
  // src/components/chat/ChatSessionBar.tsx
9063
- var React38 = __toESM(require("react"), 1);
9064
- var import_jsx_runtime69 = require("react/jsx-runtime");
9309
+ var React40 = __toESM(require("react"), 1);
9310
+ var import_jsx_runtime72 = require("react/jsx-runtime");
9065
9311
  var compact2 = meterFormats.compact;
9066
9312
  function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extras }) {
9067
- const [open, setOpen] = React38.useState(false);
9068
- const anchor = React38.useRef(null);
9313
+ const [open, setOpen] = React40.useState(false);
9314
+ const anchor = React40.useRef(null);
9069
9315
  const stats = sessionStats || null;
9070
9316
  const cu = contextUsage || null;
9071
9317
  const limits = usageLimits || null;
@@ -9080,9 +9326,9 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
9080
9326
  if (stats && stats.runningTasks) bits.push(stats.runningTasks + " running task" + (stats.runningTasks === 1 ? "" : "s"));
9081
9327
  if (cu) bits.push(pct + "% context");
9082
9328
  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)(
9329
+ return /* @__PURE__ */ (0, import_jsx_runtime72.jsxs)(React40.Fragment, { children: [
9330
+ /* @__PURE__ */ (0, import_jsx_runtime72.jsxs)("div", { className: "fdc-bar", children: [
9331
+ /* @__PURE__ */ (0, import_jsx_runtime72.jsxs)(
9086
9332
  "button",
9087
9333
  {
9088
9334
  type: "button",
@@ -9093,16 +9339,16 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
9093
9339
  "aria-expanded": expandable ? open : void 0,
9094
9340
  "aria-label": expandable ? "Usage details" : void 0,
9095
9341
  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
9342
+ 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,
9343
+ /* @__PURE__ */ (0, import_jsx_runtime72.jsx)("span", { className: "fdc-bar-text", children: bits.join(" \xB7 ") }),
9344
+ expandable ? /* @__PURE__ */ (0, import_jsx_runtime72.jsx)("i", { className: "ph ph-caret-right fdc-bar-caret", "aria-hidden": "true" }) : null
9099
9345
  ]
9100
9346
  }
9101
9347
  ),
9102
9348
  extras
9103
9349
  ] }),
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)(
9350
+ /* @__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: [
9351
+ cu ? /* @__PURE__ */ (0, import_jsx_runtime72.jsx)("section", { className: "fdc-usage-sec", children: /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
9106
9352
  SegmentedMeter,
9107
9353
  {
9108
9354
  total,
@@ -9114,9 +9360,9 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
9114
9360
  remainderLabel: "Free"
9115
9361
  }
9116
9362
  ) }) : 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)(
9363
+ limits && limits.length ? /* @__PURE__ */ (0, import_jsx_runtime72.jsxs)("section", { className: "fdc-usage-sec", children: [
9364
+ /* @__PURE__ */ (0, import_jsx_runtime72.jsx)("h4", { className: "fdc-usage-h", children: "Usage limits" }),
9365
+ /* @__PURE__ */ (0, import_jsx_runtime72.jsx)("div", { className: "fdc-usage-rows", children: limits.map((l) => /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
9120
9366
  QuotaRow,
9121
9367
  {
9122
9368
  label: l.label,
@@ -9126,32 +9372,32 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
9126
9372
  l.id
9127
9373
  )) })
9128
9374
  ] }) : 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) })
9375
+ stats ? /* @__PURE__ */ (0, import_jsx_runtime72.jsxs)("section", { className: "fdc-usage-sec fdc-usage-stats", children: [
9376
+ stats.elapsedMs ? /* @__PURE__ */ (0, import_jsx_runtime72.jsxs)("div", { children: [
9377
+ /* @__PURE__ */ (0, import_jsx_runtime72.jsx)("span", { children: "Session" }),
9378
+ /* @__PURE__ */ (0, import_jsx_runtime72.jsx)("b", { className: "fd-tabular", children: formatDuration(stats.elapsedMs) })
9133
9379
  ] }) : 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() })
9380
+ stats.tokens ? /* @__PURE__ */ (0, import_jsx_runtime72.jsxs)("div", { children: [
9381
+ /* @__PURE__ */ (0, import_jsx_runtime72.jsx)("span", { children: "Tokens" }),
9382
+ /* @__PURE__ */ (0, import_jsx_runtime72.jsx)("b", { className: "fd-tabular", children: stats.tokens.toLocaleString() })
9137
9383
  ] }) : 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: [
9384
+ stats.costUsd != null ? /* @__PURE__ */ (0, import_jsx_runtime72.jsxs)("div", { children: [
9385
+ /* @__PURE__ */ (0, import_jsx_runtime72.jsx)("span", { children: "Cost" }),
9386
+ /* @__PURE__ */ (0, import_jsx_runtime72.jsxs)("b", { className: "fd-tabular", children: [
9141
9387
  "$",
9142
9388
  Number(stats.costUsd).toFixed(3)
9143
9389
  ] })
9144
9390
  ] }) : 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 })
9391
+ stats.turns ? /* @__PURE__ */ (0, import_jsx_runtime72.jsxs)("div", { children: [
9392
+ /* @__PURE__ */ (0, import_jsx_runtime72.jsx)("span", { children: "Turns" }),
9393
+ /* @__PURE__ */ (0, import_jsx_runtime72.jsx)("b", { className: "fd-tabular", children: stats.turns })
9148
9394
  ] }) : null
9149
9395
  ] }) : 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: () => {
9396
+ 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
9397
  setOpen(false);
9152
9398
  onClear();
9153
9399
  }, children: [
9154
- /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("i", { className: "ph ph-trash", "aria-hidden": "true" }),
9400
+ /* @__PURE__ */ (0, import_jsx_runtime72.jsx)("i", { className: "ph ph-trash", "aria-hidden": "true" }),
9155
9401
  "Clear conversation"
9156
9402
  ] }) }) : null
9157
9403
  ] }) })
@@ -9188,7 +9434,7 @@ function ModelControls({
9188
9434
  disabled: m.disabled,
9189
9435
  checked: m.id === (current2 && current2.id),
9190
9436
  meta: m.meta,
9191
- shortcut: m.shortcut ? /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(KeyHint, { keys: m.shortcut, size: "sm" }) : void 0,
9437
+ shortcut: m.shortcut ? /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(KeyHint, { keys: m.shortcut, size: "sm" }) : void 0,
9192
9438
  onSelect: () => onModelChange && onModelChange(m.id)
9193
9439
  });
9194
9440
  const items = [{ kind: "section", label: "Models" }].concat(flat.map(item));
@@ -9201,15 +9447,15 @@ function ModelControls({
9201
9447
  items.push({ kind: "section", label: "Fast mode" });
9202
9448
  items.push({
9203
9449
  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" }) })
9450
+ render: () => /* @__PURE__ */ (0, import_jsx_runtime72.jsxs)("label", { className: "fdc-switchrow", children: [
9451
+ /* @__PURE__ */ (0, import_jsx_runtime72.jsx)("span", { children: fastModeLabel }),
9452
+ /* @__PURE__ */ (0, import_jsx_runtime72.jsx)("input", { type: "checkbox", className: "fd-sr", checked: !!fastMode, onChange: (e) => onFastModeChange(e.target.checked) }),
9453
+ /* @__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
9454
  ] })
9209
9455
  });
9210
9456
  }
9211
- return /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)(React38.Fragment, { children: [
9212
- /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(
9457
+ return /* @__PURE__ */ (0, import_jsx_runtime72.jsxs)(React40.Fragment, { children: [
9458
+ /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
9213
9459
  MenuButton,
9214
9460
  {
9215
9461
  items,
@@ -9220,7 +9466,7 @@ function ModelControls({
9220
9466
  title: "Choose a model"
9221
9467
  }
9222
9468
  ),
9223
- effortLevels && effortLevels.length ? /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(
9469
+ effortLevels && effortLevels.length ? /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
9224
9470
  MenuButton,
9225
9471
  {
9226
9472
  placement: "top-end",
@@ -9241,7 +9487,7 @@ function ModelControls({
9241
9487
  }
9242
9488
 
9243
9489
  // src/components/chat/AgentChatPanel.tsx
9244
- var import_jsx_runtime70 = require("react/jsx-runtime");
9490
+ var import_jsx_runtime73 = require("react/jsx-runtime");
9245
9491
  var SURFACES = { sidebar: "is-sidebar", inline: "is-inline", page: "is-page", modal: "is-modal", sheet: "is-sheet" };
9246
9492
  function AgentChatPanel({
9247
9493
  /* required */
@@ -9325,11 +9571,11 @@ function AgentChatPanel({
9325
9571
  onFeedback,
9326
9572
  onEditMessage
9327
9573
  }) {
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]);
9574
+ const [panelWidth, setPanelWidth] = React41.useState(width);
9575
+ const [applied, setApplied] = React41.useState({});
9576
+ const [draft, setDraft] = React41.useState("");
9577
+ const dragging = React41.useRef(null);
9578
+ React41.useEffect(() => setPanelWidth(width), [width]);
9333
9579
  const engine = useChatEngine({
9334
9580
  contextType,
9335
9581
  contextId,
@@ -9395,7 +9641,7 @@ function AgentChatPanel({
9395
9641
  onReconnect: engine.reload,
9396
9642
  deadTitle: "The assistant isn\u2019t reachable"
9397
9643
  };
9398
- const sessionBar = /* @__PURE__ */ (0, import_jsx_runtime70.jsx)(
9644
+ const sessionBar = /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(
9399
9645
  ChatSessionBar,
9400
9646
  {
9401
9647
  sessionStats,
@@ -9404,7 +9650,7 @@ function AgentChatPanel({
9404
9650
  onClear: engine.visible.length ? engine.clear : void 0
9405
9651
  }
9406
9652
  );
9407
- const modelControls = /* @__PURE__ */ (0, import_jsx_runtime70.jsx)(
9653
+ const modelControls = /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(
9408
9654
  ModelControls,
9409
9655
  {
9410
9656
  models,
@@ -9419,7 +9665,7 @@ function AgentChatPanel({
9419
9665
  narrow
9420
9666
  }
9421
9667
  );
9422
- const threadMenu = threads && threads.length ? /* @__PURE__ */ (0, import_jsx_runtime70.jsx)(
9668
+ const threadMenu = threads && threads.length ? /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(
9423
9669
  MenuButton,
9424
9670
  {
9425
9671
  variant: "ghost",
@@ -9446,7 +9692,7 @@ function AgentChatPanel({
9446
9692
  })))
9447
9693
  }
9448
9694
  ) : null;
9449
- return /* @__PURE__ */ (0, import_jsx_runtime70.jsxs)(
9695
+ return /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)(
9450
9696
  "aside",
9451
9697
  {
9452
9698
  className: ["fdc-panel", SURFACES[surface] || SURFACES.sidebar, narrow ? "is-narrow" : "", className].filter(Boolean).join(" "),
@@ -9457,7 +9703,7 @@ function AgentChatPanel({
9457
9703
  },
9458
9704
  "aria-label": title,
9459
9705
  children: [
9460
- surface === "sidebar" && resizable ? /* @__PURE__ */ (0, import_jsx_runtime70.jsx)(
9706
+ surface === "sidebar" && resizable ? /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(
9461
9707
  "div",
9462
9708
  {
9463
9709
  className: "fdc-grip",
@@ -9472,20 +9718,20 @@ function AgentChatPanel({
9472
9718
  }
9473
9719
  }
9474
9720
  ) : 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
9721
+ showHeader ? /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("header", { className: "fdc-head", children: [
9722
+ /* @__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 }) }),
9723
+ /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("span", { className: "fdc-head-titles", children: [
9724
+ /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("span", { className: "fdc-head-title", children: title }),
9725
+ subtitle ? /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("span", { className: "fdc-head-sub", children: subtitle }) : null
9480
9726
  ] }),
9481
- /* @__PURE__ */ (0, import_jsx_runtime70.jsxs)("span", { className: "fdc-head-acts", children: [
9727
+ /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("span", { className: "fdc-head-acts", children: [
9482
9728
  headerActions,
9483
9729
  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
9730
+ 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,
9731
+ 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
9732
  ] })
9487
9733
  ] }) : null,
9488
- /* @__PURE__ */ (0, import_jsx_runtime70.jsx)(
9734
+ /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(
9489
9735
  ChatTranscript,
9490
9736
  {
9491
9737
  messages: engine.visible,
@@ -9500,7 +9746,7 @@ function AgentChatPanel({
9500
9746
  renderEmpty
9501
9747
  }
9502
9748
  ),
9503
- /* @__PURE__ */ (0, import_jsx_runtime70.jsx)(
9749
+ /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(
9504
9750
  ChatComposer,
9505
9751
  {
9506
9752
  onSubmit: (text, atts) => engine.send(text, atts),
@@ -9533,7 +9779,7 @@ function AgentChatPanel({
9533
9779
  }
9534
9780
 
9535
9781
  // src/kits/query.ts
9536
- var React40 = __toESM(require("react"), 1);
9782
+ var React42 = __toESM(require("react"), 1);
9537
9783
  function eqFilter(get2) {
9538
9784
  return (row, value) => Array.isArray(value) ? value.includes(get2(row)) : get2(row) === value;
9539
9785
  }
@@ -9565,22 +9811,22 @@ function compare(a, b, dir) {
9565
9811
  var API = null;
9566
9812
  var PREFS = null;
9567
9813
  function useServerTable({ endpoint, params, defaults, deps, prefsKey }) {
9568
- const [query, setQuery] = React40.useState(() => {
9814
+ const [query, setQuery] = React42.useState(() => {
9569
9815
  const store = PREFS || window.PlannerPrefs;
9570
9816
  const saved = prefsKey && store ? store.getTable(prefsKey) : {};
9571
9817
  return { ...DEFAULTS, ...defaults || {}, ...saved.pageSize ? { pageSize: saved.pageSize } : {}, ...saved.sort ? { sort: saved.sort, dir: saved.dir || "desc" } : {} };
9572
9818
  });
9573
- const savePref = React40.useCallback((patch2) => {
9819
+ const savePref = React42.useCallback((patch2) => {
9574
9820
  const store = PREFS || window.PlannerPrefs;
9575
9821
  if (prefsKey && store) store.setTable(prefsKey, patch2);
9576
9822
  }, [prefsKey]);
9577
- const [res, setRes] = React40.useState(null);
9578
- const [loading, setLoading] = React40.useState(true);
9579
- const seq2 = React40.useRef(0);
9823
+ const [res, setRes] = React42.useState(null);
9824
+ const [loading, setLoading] = React42.useState(true);
9825
+ const seq2 = React42.useRef(0);
9580
9826
  const depKey = (deps || []).join("|");
9581
9827
  const paramKey = JSON.stringify(params || {});
9582
9828
  const queryKey = JSON.stringify(query);
9583
- React40.useEffect(() => {
9829
+ React42.useEffect(() => {
9584
9830
  const id = ++seq2.current;
9585
9831
  setLoading(true);
9586
9832
  const t = setTimeout(() => {
@@ -9919,6 +10165,7 @@ function createVersionStore(initialState, options) {
9919
10165
  Dropzone,
9920
10166
  DropzoneKit,
9921
10167
  EmptyState,
10168
+ EntityRow,
9922
10169
  FeatureGate,
9923
10170
  FileChip,
9924
10171
  FileGrid,
@@ -9991,11 +10238,16 @@ function createVersionStore(initialState, options) {
9991
10238
  Tooltip,
9992
10239
  Topbar,
9993
10240
  TranscriptKit,
10241
+ TransferList,
9994
10242
  UseFeatureStatus,
9995
10243
  UseRuntimeMode,
10244
+ VIRTUAL_LIST_BUFFER_ROWS,
10245
+ VirtualList,
9996
10246
  acceptMatches,
9997
10247
  anyOfFilter,
9998
10248
  channelWeightOf,
10249
+ computeNeedMore,
10250
+ computeVirtualWindow,
9999
10251
  createVersionStore,
10000
10252
  eqFilter,
10001
10253
  extensionOf,