@flytedan/flytebot-design-system 0.6.0 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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,
@@ -390,7 +396,14 @@ function Popover({
390
396
  bottom: pos.bottom == null ? "auto" : pos.bottom,
391
397
  width: matchWidth ? pos.width : width,
392
398
  minWidth: minWidth || (matchWidth ? void 0 : 200),
393
- maxHeight: Math.min(maxHeight || 420, pos.maxH),
399
+ // Size to content by default — cap only at real available room between the
400
+ // anchor and the viewport edge (pos.maxH, computed by usePopoverPosition).
401
+ // A caller-supplied `maxHeight` narrows that further (e.g. a long menu that
402
+ // should scroll well before it reaches the viewport edge); it must never
403
+ // widen past pos.maxH, which is why it's still Math.min'd against it. There
404
+ // is intentionally no arbitrary default here — an unrequested cap would clip
405
+ // ordinary content that simply happens to be taller than some fixed number.
406
+ maxHeight: maxHeight != null ? Math.min(maxHeight, pos.maxH) : pos.maxH,
394
407
  transformOrigin: pos.side === "top" ? "bottom center" : "top center",
395
408
  zIndex: 140,
396
409
  ...style
@@ -2606,56 +2619,140 @@ function StepList({
2606
2619
  ] });
2607
2620
  }
2608
2621
 
2609
- // src/components/forms/Checkbox.tsx
2622
+ // src/components/data/VirtualList.tsx
2610
2623
  var React15 = __toESM(require("react"), 1);
2611
2624
  var import_jsx_runtime38 = require("react/jsx-runtime");
2612
- function Checkbox({ label, description, card = false, indeterminate = false, className = "", ...rest }) {
2613
- 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;
2614
2675
  React15.useEffect(() => {
2615
- if (ref.current) ref.current.indeterminate = indeterminate;
2616
- }, [indeterminate]);
2617
- return /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("label", { className: ["fd-choice", card ? "fd-choice-card" : "", className].filter(Boolean).join(" "), children: [
2618
- /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("span", { className: "fd-choice-input", children: [
2619
- /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("input", { ref, type: "checkbox", ...rest }),
2620
- /* @__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" }) })
2621
- ] }),
2622
- /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("span", { className: "fd-choice-text", children: [
2623
- /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("span", { className: "fd-choice-title", children: label }),
2624
- description ? /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("span", { className: "fd-choice-desc", children: description }) : null
2625
- ] })
2626
- ] });
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
+ );
2627
2708
  }
2628
2709
 
2629
- // src/components/forms/Radio.tsx
2710
+ // src/components/data/EntityRow.tsx
2630
2711
  var import_jsx_runtime39 = require("react/jsx-runtime");
2631
- function Radio({ label, description, card = false, className = "", ...rest }) {
2632
- return /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("label", { className: ["fd-choice", card ? "fd-choice-card" : "", className].filter(Boolean).join(" "), children: [
2633
- /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("span", { className: "fd-choice-input", children: [
2634
- /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("input", { type: "radio", ...rest }),
2635
- /* @__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" }) })
2636
- ] }),
2637
- /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("span", { className: "fd-choice-text", children: [
2638
- /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("span", { className: "fd-choice-title", children: label }),
2639
- description ? /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("span", { className: "fd-choice-desc", children: description }) : null
2640
- ] })
2641
- ] });
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
+ );
2642
2749
  }
2643
2750
 
2644
- // src/components/forms/Switch.tsx
2645
- var import_jsx_runtime40 = require("react/jsx-runtime");
2646
- function Switch({ label, description, className = "", ...rest }) {
2647
- return /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("label", { className: ["fd-switch", className].filter(Boolean).join(" "), children: [
2648
- /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("input", { type: "checkbox", role: "switch", ...rest }),
2649
- /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("span", { className: "fd-switch-track", children: /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("span", { className: "fd-switch-thumb" }) }),
2650
- label ? /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("span", { className: "fd-choice-text", children: [
2651
- /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("span", { className: "fd-switch-label", children: label }),
2652
- description ? /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("span", { className: "fd-choice-desc", children: description }) : null
2653
- ] }) : null
2654
- ] });
2655
- }
2751
+ // src/components/data/TransferList.tsx
2752
+ var React16 = __toESM(require("react"), 1);
2656
2753
 
2657
2754
  // src/components/forms/Input.tsx
2658
- var import_jsx_runtime41 = require("react/jsx-runtime");
2755
+ var import_jsx_runtime40 = require("react/jsx-runtime");
2659
2756
  function Input({
2660
2757
  label,
2661
2758
  help,
@@ -2683,27 +2780,27 @@ function Input({
2683
2780
  size === "lg" ? "fd-input-lg" : "",
2684
2781
  className
2685
2782
  ].filter(Boolean).join(" ");
2686
- return /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { className: "fd-field", style, children: [
2687
- 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: [
2688
2785
  label,
2689
- 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
2690
2787
  ] }) : null,
2691
- /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { className: box, children: [
2692
- 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,
2693
- prefix ? /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("span", { className: "fd-input-affix", children: prefix }) : null,
2694
- /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("input", { id: fieldId, disabled, style: inputStyle, "aria-invalid": error ? "true" : void 0, ...rest }),
2695
- loading ? /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("span", { className: "fd-spinner", style: { color: "var(--text-muted)" }, "aria-label": "Loading" }) : null,
2696
- 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
2697
2794
  ] }),
2698
- error ? /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("span", { className: "fd-field-error", children: [
2699
- /* @__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" }),
2700
2797
  error
2701
- ] }) : 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
2702
2799
  ] });
2703
2800
  }
2704
2801
 
2705
2802
  // src/components/forms/SearchField.tsx
2706
- var import_jsx_runtime42 = require("react/jsx-runtime");
2803
+ var import_jsx_runtime41 = require("react/jsx-runtime");
2707
2804
  function SearchField({
2708
2805
  value,
2709
2806
  onChange,
@@ -2718,7 +2815,7 @@ function SearchField({
2718
2815
  ...rest
2719
2816
  }) {
2720
2817
  const clear = onClear || (() => onChange(""));
2721
- return /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
2818
+ return /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
2722
2819
  Input,
2723
2820
  {
2724
2821
  id,
@@ -2731,14 +2828,14 @@ function SearchField({
2731
2828
  style,
2732
2829
  className,
2733
2830
  onChange: (e) => onChange(e.target.value),
2734
- suffix: value ? /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
2831
+ suffix: value ? /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
2735
2832
  "button",
2736
2833
  {
2737
2834
  type: "button",
2738
2835
  "aria-label": "Clear search",
2739
2836
  onClick: clear,
2740
2837
  style: { all: "unset", cursor: "pointer", color: "var(--text-muted)", display: "grid", placeItems: "center", padding: 2 },
2741
- 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" })
2742
2839
  }
2743
2840
  ) : void 0,
2744
2841
  ...rest
@@ -2746,27 +2843,183 @@ function SearchField({
2746
2843
  );
2747
2844
  }
2748
2845
 
2749
- // 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);
2750
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");
2751
3004
  function Textarea({ label, help, error, required = false, rows = 4, disabled = false, id, className = "", style, ...rest }) {
2752
3005
  const fieldId = id || (rest.name ? "fd-" + rest.name : void 0);
2753
3006
  const box = ["fd-input", "fd-input-textarea", error ? "fd-input-error" : "", disabled ? "fd-input-disabled" : "", className].filter(Boolean).join(" ");
2754
- return /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("div", { className: "fd-field", style, children: [
2755
- 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: [
2756
3009
  label,
2757
- 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
2758
3011
  ] }) : null,
2759
- /* @__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 }) }),
2760
- error ? /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("span", { className: "fd-field-error", children: [
2761
- /* @__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" }),
2762
3015
  error
2763
- ] }) : 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
2764
3017
  ] });
2765
3018
  }
2766
3019
 
2767
3020
  // src/components/forms/NumberInput.tsx
2768
- var React16 = __toESM(require("react"), 1);
2769
- var import_jsx_runtime44 = require("react/jsx-runtime");
3021
+ var React18 = __toESM(require("react"), 1);
3022
+ var import_jsx_runtime47 = require("react/jsx-runtime");
2770
3023
  function NumberInput({
2771
3024
  label,
2772
3025
  help,
@@ -2790,10 +3043,10 @@ function NumberInput({
2790
3043
  const n = Number(String(v == null ? "" : v).replace(/[^0-9.-]/g, ""));
2791
3044
  return isNaN(n) ? null : n;
2792
3045
  };
2793
- const [text, setText] = React16.useState(value == null || value === "" ? "" : String(value));
2794
- const [editing, setEditing] = React16.useState(false);
2795
- const timer = React16.useRef(null);
2796
- 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(() => {
2797
3050
  if (!editing) setText(value == null || value === "" ? "" : String(value));
2798
3051
  }, [value, editing]);
2799
3052
  const clamp = (n) => Math.min(max, Math.max(min, n));
@@ -2817,7 +3070,7 @@ function NumberInput({
2817
3070
  const release = () => {
2818
3071
  if (timer.current) clearTimeout(timer.current);
2819
3072
  };
2820
- React16.useEffect(() => () => {
3073
+ React18.useEffect(() => () => {
2821
3074
  if (timer.current) clearTimeout(timer.current);
2822
3075
  }, []);
2823
3076
  const shown = editing ? text : (() => {
@@ -2825,14 +3078,14 @@ function NumberInput({
2825
3078
  return n == null ? "" : format ? n.toLocaleString() : String(n);
2826
3079
  })();
2827
3080
  const box = ["fd-input", "fd-input-num", error ? "fd-input-error" : "", disabled ? "fd-input-disabled" : ""].filter(Boolean).join(" ");
2828
- return /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("div", { className: ["fd-field", className].filter(Boolean).join(" "), style, children: [
2829
- 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: [
2830
3083
  label,
2831
- 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
2832
3085
  ] }) : null,
2833
- /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("div", { className: box, style: { gap: 8 }, children: [
2834
- prefix ? /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("span", { className: "fd-input-affix", children: prefix }) : null,
2835
- /* @__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)(
2836
3089
  "input",
2837
3090
  {
2838
3091
  inputMode: "numeric",
@@ -2865,9 +3118,9 @@ function NumberInput({
2865
3118
  }
2866
3119
  }
2867
3120
  ),
2868
- suffix ? /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("span", { className: "fd-input-affix", children: suffix }) : null,
2869
- /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("span", { className: "fd-row", style: { gap: 4, flex: "none" }, children: [
2870
- /* @__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)(
2871
3124
  "button",
2872
3125
  {
2873
3126
  type: "button",
@@ -2877,10 +3130,10 @@ function NumberInput({
2877
3130
  onPointerDown: () => hold(-1),
2878
3131
  onPointerUp: release,
2879
3132
  onPointerLeave: release,
2880
- 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" })
2881
3134
  }
2882
3135
  ),
2883
- /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
3136
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
2884
3137
  "button",
2885
3138
  {
2886
3139
  type: "button",
@@ -2890,26 +3143,26 @@ function NumberInput({
2890
3143
  onPointerDown: () => hold(1),
2891
3144
  onPointerUp: release,
2892
3145
  onPointerLeave: release,
2893
- 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" })
2894
3147
  }
2895
3148
  )
2896
3149
  ] })
2897
3150
  ] }),
2898
- error ? /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("span", { className: "fd-field-error", children: [
2899
- /* @__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" }),
2900
3153
  error
2901
- ] }) : 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
2902
3155
  ] });
2903
3156
  }
2904
3157
 
2905
3158
  // src/components/forms/Select.tsx
2906
- var React17 = __toESM(require("react"), 1);
3159
+ var React19 = __toESM(require("react"), 1);
2907
3160
  var import_react_dom4 = require("react-dom");
2908
- var import_jsx_runtime45 = require("react/jsx-runtime");
3161
+ var import_jsx_runtime48 = require("react/jsx-runtime");
2909
3162
  var norm = (o) => typeof o === "string" ? { value: o, label: o } : o;
2910
3163
  function usePopPos(open, ref, estH, estW) {
2911
- const [pos, setPos] = React17.useState(null);
2912
- React17.useLayoutEffect(() => {
3164
+ const [pos, setPos] = React19.useState(null);
3165
+ React19.useLayoutEffect(() => {
2913
3166
  if (!open || !ref.current) {
2914
3167
  setPos(null);
2915
3168
  return;
@@ -2973,14 +3226,14 @@ function Select({
2973
3226
  const vals = multiple ? Array.isArray(value) ? value : value ? [value] : [] : [];
2974
3227
  const isOn = (v) => multiple ? vals.includes(v) : v === value;
2975
3228
  const hasSearch = searchable === void 0 ? opts.length > 8 : searchable;
2976
- const [open, setOpen] = React17.useState(false);
2977
- const [q, setQ] = React17.useState("");
2978
- const [active, setActive] = React17.useState(-1);
2979
- const rootRef = React17.useRef(null);
2980
- const boxRef = React17.useRef(null);
2981
- const popRef = React17.useRef(null);
2982
- const listRef = React17.useRef(null);
2983
- 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 });
2984
3237
  const selected = multiple ? null : opts.find((o) => o.value === value);
2985
3238
  const chosen = multiple ? opts.filter((o) => vals.includes(o.value)) : [];
2986
3239
  const pos = usePopPos(open, boxRef, hasSearch ? 390 : 340, 260);
@@ -3006,7 +3259,7 @@ function Select({
3006
3259
  }
3007
3260
  setOpen(!open);
3008
3261
  };
3009
- React17.useEffect(() => {
3262
+ React19.useEffect(() => {
3010
3263
  if (!open) return;
3011
3264
  const away = (e) => {
3012
3265
  if (rootRef.current && rootRef.current.contains(e.target)) return;
@@ -3016,7 +3269,7 @@ function Select({
3016
3269
  document.addEventListener("pointerdown", away);
3017
3270
  return () => document.removeEventListener("pointerdown", away);
3018
3271
  }, [open]);
3019
- React17.useEffect(() => {
3272
+ React19.useEffect(() => {
3020
3273
  if (!open || active < 0 || !listRef.current) return;
3021
3274
  const el = listRef.current.querySelector('[data-i="' + active + '"]');
3022
3275
  if (el) {
@@ -3070,13 +3323,13 @@ function Select({
3070
3323
  });
3071
3324
  const fieldId = id || (rest.name ? "fd-" + rest.name : void 0);
3072
3325
  const box = ["fd-input", "fd-select", error ? "fd-input-error" : "", disabled ? "fd-input-disabled" : ""].filter(Boolean).join(" ");
3073
- return /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("div", { className: ["fd-field", "fd-popfield", open ? "is-open" : "", className].filter(Boolean).join(" "), style, ref: rootRef, children: [
3074
- 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: [
3075
3328
  label,
3076
- 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
3077
3330
  ] }) : null,
3078
- /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("div", { className: box, style: { cursor: disabled ? "not-allowed" : "pointer" }, ref: boxRef, children: [
3079
- /* @__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)(
3080
3333
  "button",
3081
3334
  {
3082
3335
  type: "button",
@@ -3089,13 +3342,13 @@ function Select({
3089
3342
  "aria-haspopup": "listbox",
3090
3343
  style: { all: "unset", flex: 1, minWidth: 0, display: "flex", alignItems: "center", gap: 8, cursor: "inherit", overflow: "hidden" },
3091
3344
  children: [
3092
- selected && selected.icon ? /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("i", { className: "ph ph-" + selected.icon, style: { flex: "none", color: "var(--text-2)" } }) : null,
3093
- /* @__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 }),
3094
- 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
3095
3348
  ]
3096
3349
  }
3097
3350
  ),
3098
- 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)(
3099
3352
  "button",
3100
3353
  {
3101
3354
  type: "button",
@@ -3105,22 +3358,22 @@ function Select({
3105
3358
  fire(multiple ? [] : "");
3106
3359
  },
3107
3360
  style: { all: "unset", cursor: "pointer", color: "var(--text-muted)", display: "grid", placeItems: "center", padding: 2 },
3108
- 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 } })
3109
3362
  }
3110
3363
  ) : null,
3111
- 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" }) })
3112
3365
  ] }),
3113
3366
  open && pos ? (0, import_react_dom4.createPortal)(
3114
- /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)(
3367
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)(
3115
3368
  "div",
3116
3369
  {
3117
3370
  className: "fd-pop" + (pos.up ? " is-up" : ""),
3118
3371
  ref: popRef,
3119
3372
  style: popStyle(pos, { minWidth: Math.max(pos.width, 260), maxWidth: 380, zIndex: 130, overflowY: "hidden" }),
3120
3373
  children: [
3121
- hasSearch ? /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("div", { className: "fd-pop-search", children: [
3122
- /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("i", { className: "ph ph-magnifying-glass", style: { color: "var(--text-muted)", fontSize: 14 } }),
3123
- /* @__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)(
3124
3377
  "input",
3125
3378
  {
3126
3379
  autoFocus: true,
@@ -3133,15 +3386,15 @@ function Select({
3133
3386
  }
3134
3387
  }
3135
3388
  ),
3136
- 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
3137
3390
  ] }) : null,
3138
- /* @__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: [
3139
3392
  'Nothing matches "',
3140
3393
  q,
3141
3394
  '".'
3142
- ] }) : groups.map((grp) => /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)(React17.Fragment, { children: [
3143
- grp.g ? /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("div", { className: "fd-pop-group", children: grp.g }) : null,
3144
- 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)(
3145
3398
  "button",
3146
3399
  {
3147
3400
  type: "button",
@@ -3153,21 +3406,21 @@ function Select({
3153
3406
  onMouseEnter: () => setActive(i),
3154
3407
  onClick: () => pick(o),
3155
3408
  children: [
3156
- 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,
3157
- 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,
3158
- /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("span", { style: { flex: 1, minWidth: 0 }, children: [
3159
- /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("span", { className: "fd-opt-label", children: o.label }),
3160
- 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
3161
3414
  ] }),
3162
- o.meta ? /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("span", { className: "fd-opt-meta", children: o.meta }) : null,
3163
- 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 })
3164
3417
  ]
3165
3418
  },
3166
3419
  String(o.value)
3167
3420
  ))
3168
3421
  ] }, grp.g || "_")) }),
3169
- multiple ? /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("div", { className: "fd-row", style: { gap: 10, padding: "8px 12px", borderTop: "1px solid var(--border)" }, children: [
3170
- /* @__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)(
3171
3424
  "button",
3172
3425
  {
3173
3426
  type: "button",
@@ -3176,13 +3429,13 @@ function Select({
3176
3429
  children: "Select all"
3177
3430
  }
3178
3431
  ),
3179
- /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("span", { style: { flex: 1 } }),
3180
- /* @__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: [
3181
3434
  vals.length,
3182
3435
  " of ",
3183
3436
  opts.length
3184
3437
  ] }),
3185
- /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
3438
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
3186
3439
  "button",
3187
3440
  {
3188
3441
  type: "button",
@@ -3198,17 +3451,17 @@ function Select({
3198
3451
  ),
3199
3452
  document.body
3200
3453
  ) : null,
3201
- error ? /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("span", { className: "fd-field-error", children: [
3202
- /* @__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" }),
3203
3456
  error
3204
- ] }) : 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
3205
3458
  ] });
3206
3459
  }
3207
3460
 
3208
3461
  // src/components/forms/DatePicker.tsx
3209
- var React18 = __toESM(require("react"), 1);
3462
+ var React20 = __toESM(require("react"), 1);
3210
3463
  var import_react_dom5 = require("react-dom");
3211
- var import_jsx_runtime46 = require("react/jsx-runtime");
3464
+ var import_jsx_runtime49 = require("react/jsx-runtime");
3212
3465
  var MONTHS = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
3213
3466
  var DOW = ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"];
3214
3467
  var iso = (d) => d.getFullYear() + "-" + String(d.getMonth() + 1).padStart(2, "0") + "-" + String(d.getDate()).padStart(2, "0");
@@ -3222,8 +3475,8 @@ var fmt = (s) => {
3222
3475
  return d ? MONTHS[d.getMonth()].slice(0, 3) + " " + d.getDate() + ", " + d.getFullYear() : "";
3223
3476
  };
3224
3477
  function usePopPos2(open, ref, estH, estW) {
3225
- const [pos, setPos] = React18.useState(null);
3226
- React18.useLayoutEffect(() => {
3478
+ const [pos, setPos] = React20.useState(null);
3479
+ React20.useLayoutEffect(() => {
3227
3480
  if (!open || !ref.current) {
3228
3481
  setPos(null);
3229
3482
  return;
@@ -3267,10 +3520,10 @@ function Calendar({ value, range = false, onPick, initialMonth, months = 1 }) {
3267
3520
  const today = /* @__PURE__ */ new Date();
3268
3521
  const sel = range ? value || {} : { start: value, end: value };
3269
3522
  const anchor = parse(sel.start) || parse(initialMonth) || today;
3270
- const [vy, setVy] = React18.useState(anchor.getFullYear());
3271
- const [vm, setVm] = React18.useState(anchor.getMonth());
3272
- const [mode2, setMode] = React18.useState("days");
3273
- 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);
3274
3527
  const s = parse(sel.start), e = parse(sel.end);
3275
3528
  const hoverEnd = range && s && !e && hover ? parse(hover) : null;
3276
3529
  const inRange = (d) => {
@@ -3307,9 +3560,9 @@ function Calendar({ value, range = false, onPick, initialMonth, months = 1 }) {
3307
3560
  const startPad = new Date(y, m, 1).getDay();
3308
3561
  const cells = [];
3309
3562
  for (let i = 0; i < 42; i++) cells.push(new Date(y, m, i - startPad + 1));
3310
- return /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: "fd-cal-grid", style: { width: months > 1 ? 252 : "auto", flex: "none" }, onMouseLeave: () => setHover(null), children: [
3311
- DOW.map((d) => /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("span", { className: "fd-cal-dow", children: d }, d)),
3312
- 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)(
3313
3566
  "button",
3314
3567
  {
3315
3568
  type: "button",
@@ -3323,20 +3576,20 @@ function Calendar({ value, range = false, onPick, initialMonth, months = 1 }) {
3323
3576
  ] });
3324
3577
  };
3325
3578
  const nextY = vm === 11 ? vy + 1 : vy, nextM = (vm + 1) % 12;
3326
- return /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: "fd-cal", style: { width: months > 1 && mode2 === "days" ? "auto" : void 0 }, children: [
3327
- /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: "fd-cal-head", children: [
3328
- /* @__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" }) }),
3329
- /* @__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: [
3330
3583
  mode2 === "days" ? MONTHS[vm] + " " + vy : mode2 === "months" ? vy : vy - 5 + " \u2013 " + (vy + 6),
3331
- /* @__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)" } })
3332
3585
  ] }),
3333
- 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,
3334
- /* @__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" }) })
3335
3588
  ] }),
3336
- 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: [
3337
3590
  monthGrid(vy, vm),
3338
3591
  months > 1 ? monthGrid(nextY, nextM) : null
3339
- ] }) : 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)(
3340
3593
  "button",
3341
3594
  {
3342
3595
  type: "button",
@@ -3348,7 +3601,7 @@ function Calendar({ value, range = false, onPick, initialMonth, months = 1 }) {
3348
3601
  children: m.slice(0, 3)
3349
3602
  },
3350
3603
  m
3351
- )) }) : /* @__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)(
3352
3605
  "button",
3353
3606
  {
3354
3607
  type: "button",
@@ -3361,8 +3614,8 @@ function Calendar({ value, range = false, onPick, initialMonth, months = 1 }) {
3361
3614
  },
3362
3615
  y
3363
3616
  )) }),
3364
- /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: "fd-cal-foot", children: [
3365
- /* @__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)(
3366
3619
  "button",
3367
3620
  {
3368
3621
  type: "button",
@@ -3376,8 +3629,8 @@ function Calendar({ value, range = false, onPick, initialMonth, months = 1 }) {
3376
3629
  children: "Today"
3377
3630
  }
3378
3631
  ),
3379
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("span", { style: { flex: 1 } }),
3380
- 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: [
3381
3634
  fmt(sel.start),
3382
3635
  sel.end ? " \u2192 " + fmt(sel.end) : " \u2192 pick an end"
3383
3636
  ] }) : null
@@ -3385,12 +3638,12 @@ function Calendar({ value, range = false, onPick, initialMonth, months = 1 }) {
3385
3638
  ] });
3386
3639
  }
3387
3640
  function DatePicker({ label, help, error, required = false, disabled = false, range = false, value, onChange, placeholder, className = "", style, ...rest }) {
3388
- const [open, setOpen] = React18.useState(false);
3389
- const rootRef = React18.useRef(null);
3390
- const boxRef = React18.useRef(null);
3391
- 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);
3392
3645
  const pos = usePopPos2(open, boxRef, 430, range ? 600 : 316);
3393
- React18.useEffect(() => {
3646
+ React20.useEffect(() => {
3394
3647
  if (!open) return;
3395
3648
  const away = (e) => {
3396
3649
  if (rootRef.current && rootRef.current.contains(e.target)) return;
@@ -3411,14 +3664,14 @@ function DatePicker({ label, help, error, required = false, disabled = false, ra
3411
3664
  const toggle = () => {
3412
3665
  if (!disabled) setOpen(!open);
3413
3666
  };
3414
- return /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: ["fd-field", "fd-popfield", open ? "is-open" : "", className].filter(Boolean).join(" "), style, ref: rootRef, children: [
3415
- 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: [
3416
3669
  label,
3417
- 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
3418
3671
  ] }) : null,
3419
- /* @__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: [
3420
- /* @__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" }) }),
3421
- /* @__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)(
3422
3675
  "button",
3423
3676
  {
3424
3677
  type: "button",
@@ -3434,10 +3687,10 @@ function DatePicker({ label, help, error, required = false, disabled = false, ra
3434
3687
  children: display || placeholder || (range ? "Pick a date range" : "Pick a date")
3435
3688
  }
3436
3689
  ),
3437
- /* @__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" }) })
3438
3691
  ] }),
3439
3692
  open && pos ? (0, import_react_dom5.createPortal)(
3440
- /* @__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)(
3441
3694
  Calendar,
3442
3695
  {
3443
3696
  range,
@@ -3451,21 +3704,21 @@ function DatePicker({ label, help, error, required = false, disabled = false, ra
3451
3704
  ) }),
3452
3705
  document.body
3453
3706
  ) : null,
3454
- error ? /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("span", { className: "fd-field-error", children: [
3455
- /* @__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" }),
3456
3709
  error
3457
- ] }) : 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
3458
3711
  ] });
3459
3712
  }
3460
3713
 
3461
3714
  // src/components/forms/TimePicker.tsx
3462
- var React19 = __toESM(require("react"), 1);
3715
+ var React21 = __toESM(require("react"), 1);
3463
3716
  var import_react_dom6 = require("react-dom");
3464
- var import_jsx_runtime47 = require("react/jsx-runtime");
3717
+ var import_jsx_runtime50 = require("react/jsx-runtime");
3465
3718
  var pad = (n) => String(n).padStart(2, "0");
3466
3719
  function usePopPos3(open, ref, estH, estW) {
3467
- const [pos, setPos] = React19.useState(null);
3468
- React19.useLayoutEffect(() => {
3720
+ const [pos, setPos] = React21.useState(null);
3721
+ React21.useLayoutEffect(() => {
3469
3722
  if (!open || !ref.current) {
3470
3723
  setPos(null);
3471
3724
  return;
@@ -3511,9 +3764,9 @@ function ClockFace({ value = "09:00", onChange }) {
3511
3764
  if (isNaN(m)) m = 0;
3512
3765
  const pm = h24 >= 12;
3513
3766
  const h12 = h24 % 12 === 0 ? 12 : h24 % 12;
3514
- const [mode2, setMode] = React19.useState("h");
3515
- const faceRef = React19.useRef(null);
3516
- const dragging = React19.useRef(false);
3767
+ const [mode2, setMode] = React21.useState("h");
3768
+ const faceRef = React21.useRef(null);
3769
+ const dragging = React21.useRef(false);
3517
3770
  const set = (h, mm, isPm) => onChange((isPm ? h % 12 + 12 : h % 12) + ":" + pad(mm));
3518
3771
  const R = 108, NR = 80;
3519
3772
  const nums = mode2 === "h" ? Array.from({ length: 12 }, (_, i) => i + 1) : Array.from({ length: 12 }, (_, i) => i * 5);
@@ -3548,12 +3801,12 @@ function ClockFace({ value = "09:00", onChange }) {
3548
3801
  };
3549
3802
  const handAngle = mode2 === "h" ? h12 % 12 * 30 : m * 6;
3550
3803
  const minuteOff = mode2 === "m" && m % 5 !== 0;
3551
- return /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { style: { padding: "4px 14px 14px" }, children: [
3552
- /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: "fd-clock-digits", children: [
3553
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("button", { type: "button", className: "fd-clock-digit" + (mode2 === "h" ? " is-active" : ""), onClick: () => setMode("h"), children: pad(h12) }),
3554
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("span", { style: { fontSize: 24, fontWeight: 700, color: "var(--text-muted)" }, children: ":" }),
3555
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("button", { type: "button", className: "fd-clock-digit" + (mode2 === "m" ? " is-active" : ""), onClick: () => setMode("m"), children: pad(m) }),
3556
- /* @__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)(
3557
3810
  "button",
3558
3811
  {
3559
3812
  type: "button",
@@ -3564,13 +3817,13 @@ function ClockFace({ value = "09:00", onChange }) {
3564
3817
  ap
3565
3818
  )) })
3566
3819
  ] }),
3567
- /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: "fd-clock", ref: faceRef, onPointerDown: down, onPointerMove: move, onPointerUp: upH, children: [
3568
- /* @__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%" } }),
3569
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("span", { className: "fd-clock-pivot" }),
3570
- 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,
3571
3824
  nums.map((n) => {
3572
3825
  const a = angleOf(n) * Math.PI / 180;
3573
- return /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
3826
+ return /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(
3574
3827
  "span",
3575
3828
  {
3576
3829
  className: "fd-clock-num" + (n === selNum || mode2 === "m" && n === Math.round(m / 5) * 5 % 60 && m % 5 === 0 ? " is-sel" : ""),
@@ -3581,16 +3834,16 @@ function ClockFace({ value = "09:00", onChange }) {
3581
3834
  );
3582
3835
  })
3583
3836
  ] }),
3584
- /* @__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" }) })
3585
3838
  ] });
3586
3839
  }
3587
3840
  function TimePicker({ label, help, error, required = false, disabled = false, value = "", onChange, placeholder = "Pick a time", className = "", style }) {
3588
- const [open, setOpen] = React19.useState(false);
3589
- const rootRef = React19.useRef(null);
3590
- const boxRef = React19.useRef(null);
3591
- 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);
3592
3845
  const pos = usePopPos3(open, boxRef, 420, 262);
3593
- React19.useEffect(() => {
3846
+ React21.useEffect(() => {
3594
3847
  if (!open) return;
3595
3848
  const away = (e) => {
3596
3849
  if (rootRef.current && rootRef.current.contains(e.target)) return;
@@ -3615,14 +3868,14 @@ function TimePicker({ label, help, error, required = false, disabled = false, va
3615
3868
  const toggle = () => {
3616
3869
  if (!disabled) setOpen(!open);
3617
3870
  };
3618
- return /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: ["fd-field", "fd-popfield", open ? "is-open" : "", className].filter(Boolean).join(" "), style, ref: rootRef, children: [
3619
- 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: [
3620
3873
  label,
3621
- 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
3622
3875
  ] }) : null,
3623
- /* @__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: [
3624
- /* @__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" }) }),
3625
- /* @__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)(
3626
3879
  "button",
3627
3880
  {
3628
3881
  type: "button",
@@ -3637,13 +3890,13 @@ function TimePicker({ label, help, error, required = false, disabled = false, va
3637
3890
  children: disp() || placeholder
3638
3891
  }
3639
3892
  ),
3640
- /* @__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" }) })
3641
3894
  ] }),
3642
3895
  open && pos ? (0, import_react_dom6.createPortal)(
3643
- /* @__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: [
3644
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(ClockFace, { value: value || "09:00", onChange: (v) => onChange && onChange({ target: { value: v } }) }),
3645
- /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: "fd-cal-foot", style: { margin: "0 14px 12px", paddingTop: 10 }, children: [
3646
- /* @__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)(
3647
3900
  "button",
3648
3901
  {
3649
3902
  type: "button",
@@ -3656,22 +3909,22 @@ function TimePicker({ label, help, error, required = false, disabled = false, va
3656
3909
  children: "Now"
3657
3910
  }
3658
3911
  ),
3659
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("span", { style: { flex: 1 } }),
3660
- /* @__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" })
3661
3914
  ] })
3662
3915
  ] }),
3663
3916
  document.body
3664
3917
  ) : null,
3665
- error ? /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("span", { className: "fd-field-error", children: [
3666
- /* @__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" }),
3667
3920
  error
3668
- ] }) : 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
3669
3922
  ] });
3670
3923
  }
3671
3924
 
3672
3925
  // src/components/forms/Slider.tsx
3673
- var React20 = __toESM(require("react"), 1);
3674
- var import_jsx_runtime48 = require("react/jsx-runtime");
3926
+ var React22 = __toESM(require("react"), 1);
3927
+ var import_jsx_runtime51 = require("react/jsx-runtime");
3675
3928
  function Slider({
3676
3929
  label,
3677
3930
  min = 0,
@@ -3685,18 +3938,18 @@ function Slider({
3685
3938
  className = "",
3686
3939
  ...rest
3687
3940
  }) {
3688
- const [dragging, setDragging] = React20.useState(false);
3941
+ const [dragging, setDragging] = React22.useState(false);
3689
3942
  const v = value === void 0 ? min : Number(value);
3690
3943
  const pct = max === min ? 0 : (v - min) / (max - min) * 100;
3691
- return /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("div", { className: ["fd-field", className].filter(Boolean).join(" "), children: [
3692
- label ? /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("div", { className: "fd-row", style: { justifyContent: "space-between", gap: 12 }, children: [
3693
- /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("span", { className: "fd-field-label", children: label }),
3694
- /* @__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) })
3695
3948
  ] }) : null,
3696
- /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("div", { className: "fd-slider", children: [
3697
- /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("span", { className: "fd-slider-fill", style: { width: pct + "%" } }),
3698
- showChip && dragging ? /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("span", { className: "fd-slider-chip", style: { left: pct + "%" }, children: format(v) }) : null,
3699
- /* @__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)(
3700
3953
  "input",
3701
3954
  {
3702
3955
  type: "range",
@@ -3713,13 +3966,13 @@ function Slider({
3713
3966
  }
3714
3967
  )
3715
3968
  ] }),
3716
- 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
3717
3970
  ] });
3718
3971
  }
3719
3972
 
3720
3973
  // src/components/forms/RangeSlider.tsx
3721
- var React21 = __toESM(require("react"), 1);
3722
- var import_jsx_runtime49 = require("react/jsx-runtime");
3974
+ var React23 = __toESM(require("react"), 1);
3975
+ var import_jsx_runtime52 = require("react/jsx-runtime");
3723
3976
  function RangeSlider({
3724
3977
  label,
3725
3978
  min = 0,
@@ -3738,9 +3991,9 @@ function RangeSlider({
3738
3991
  }) {
3739
3992
  const fmt2 = format || ((v) => String(v));
3740
3993
  const [a, b] = value || [min, max];
3741
- const [drag, setDrag] = React21.useState(null);
3742
- const [focus, setFocus] = React21.useState(null);
3743
- 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);
3744
3997
  const pct = (v) => max === min ? 0 : (v - min) / (max - min) * 100;
3745
3998
  const clampPair = (i, v) => {
3746
3999
  v = Math.min(max, Math.max(min, Math.round(v / step) * step));
@@ -3755,7 +4008,7 @@ function RangeSlider({
3755
4008
  const r = railRef.current.getBoundingClientRect();
3756
4009
  return min + Math.min(1, Math.max(0, (e.clientX - r.left) / r.width)) * (max - min);
3757
4010
  };
3758
- React21.useEffect(() => {
4011
+ React23.useEffect(() => {
3759
4012
  if (drag === null) return;
3760
4013
  const mv = (e) => onChange && onChange(clampPair(drag, fromEvent(e)));
3761
4014
  const upH = () => setDrag(null);
@@ -3776,7 +4029,7 @@ function RangeSlider({
3776
4029
  };
3777
4030
  const thin = S.length > 7 ? Math.ceil(S.length / 5) : 1;
3778
4031
  const pair = value || [S[0].value, S[S.length - 1].value];
3779
- return /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(
4032
+ return /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(
3780
4033
  RangeSlider,
3781
4034
  {
3782
4035
  ...rest,
@@ -3824,23 +4077,23 @@ function RangeSlider({
3824
4077
  };
3825
4078
  const showChip = (i) => drag === i || focus === i;
3826
4079
  const hasLabels = marks.some((m) => m.label);
3827
- return /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("div", { className: ["fd-field", className].filter(Boolean).join(" "), ...rest, children: [
3828
- label ? /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("div", { className: "fd-row", style: { justifyContent: "space-between", gap: 12 }, children: [
3829
- /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("span", { className: "fd-field-label", children: label }),
3830
- /* @__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: [
3831
4084
  fmt2(a),
3832
4085
  " \u2013 ",
3833
4086
  fmt2(b)
3834
4087
  ] })
3835
4088
  ] }) : null,
3836
- /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("div", { className: "fd-range" + (hasLabels ? " has-labels" : ""), onPointerDown: onRailDown, children: [
3837
- /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("span", { className: "fd-range-rail", ref: railRef }),
3838
- /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("span", { className: "fd-range-fill", style: { left: pct(a) + "%", width: pct(b) - pct(a) + "%" } }),
3839
- marks.map((m) => /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)(React21.Fragment, { children: [
3840
- /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("span", { className: "fd-range-mark" + (m.value >= a && m.value <= b ? " is-in" : ""), style: { left: pct(m.value) + "%" } }),
3841
- 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
3842
4095
  ] }, m.value)),
3843
- [a, b].map((v, i) => /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(
4096
+ [a, b].map((v, i) => /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(
3844
4097
  "span",
3845
4098
  {
3846
4099
  className: "fd-range-thumb" + (drag === i ? " is-drag" : ""),
@@ -3855,18 +4108,18 @@ function RangeSlider({
3855
4108
  onKeyDown: key(i),
3856
4109
  onFocus: () => setFocus(i),
3857
4110
  onBlur: () => setFocus(null),
3858
- 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) })
3859
4112
  },
3860
4113
  i
3861
4114
  ))
3862
4115
  ] }),
3863
- 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
3864
4117
  ] });
3865
4118
  }
3866
4119
 
3867
4120
  // src/components/forms/Dropzone.tsx
3868
- var React22 = __toESM(require("react"), 1);
3869
- var import_jsx_runtime50 = require("react/jsx-runtime");
4121
+ var React24 = __toESM(require("react"), 1);
4122
+ var import_jsx_runtime53 = require("react/jsx-runtime");
3870
4123
  function Dropzone({
3871
4124
  onFiles,
3872
4125
  onReject,
@@ -3880,8 +4133,8 @@ function Dropzone({
3880
4133
  className = "",
3881
4134
  style
3882
4135
  }) {
3883
- const [over, setOver] = React22.useState(false);
3884
- const depth = React22.useRef(0);
4136
+ const [over, setOver] = React24.useState(false);
4137
+ const depth = React24.useRef(0);
3885
4138
  const has = (e) => {
3886
4139
  const dt = e.dataTransfer;
3887
4140
  if (!dt) return false;
@@ -3911,7 +4164,7 @@ function Dropzone({
3911
4164
  if (rejected.length && onReject) onReject(rejected);
3912
4165
  if (accepted.length && onFiles) onFiles(accepted);
3913
4166
  };
3914
- return /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)(
4167
+ return /* @__PURE__ */ (0, import_jsx_runtime53.jsxs)(
3915
4168
  "div",
3916
4169
  {
3917
4170
  className: ["fd-dropzone", over ? "is-over" : "", className].filter(Boolean).join(" "),
@@ -3922,10 +4175,10 @@ function Dropzone({
3922
4175
  onDrop: drop,
3923
4176
  children: [
3924
4177
  children,
3925
- 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: [
3926
- /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("i", { className: "ph ph-tray-arrow-down" }),
3927
- /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("span", { className: "fd-dropzone-label", children: label }),
3928
- 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
3929
4182
  ] }) }) : null
3930
4183
  ]
3931
4184
  }
@@ -3943,9 +4196,9 @@ function FilePickButton({
3943
4196
  className = "",
3944
4197
  children
3945
4198
  }) {
3946
- const ref = React22.useRef(null);
3947
- return /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)(React22.Fragment, { children: [
3948
- /* @__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)(
3949
4202
  "button",
3950
4203
  {
3951
4204
  type: "button",
@@ -3954,10 +4207,10 @@ function FilePickButton({
3954
4207
  "aria-label": label,
3955
4208
  title: label,
3956
4209
  onClick: () => ref.current && ref.current.click(),
3957
- 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" })
3958
4211
  }
3959
4212
  ),
3960
- /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(
4213
+ /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(
3961
4214
  "input",
3962
4215
  {
3963
4216
  ref,
@@ -3977,10 +4230,10 @@ function FilePickButton({
3977
4230
  }
3978
4231
  function useStagedFiles(upload, opts) {
3979
4232
  const o = opts || {};
3980
- const [items, setItems] = React22.useState([]);
3981
- const controllers = React22.useRef({});
4233
+ const [items, setItems] = React24.useState([]);
4234
+ const controllers = React24.useRef({});
3982
4235
  const patch = (id, next) => setItems((list) => list.map((f) => f.id === id ? Object.assign({}, f, next) : f));
3983
- const run = React22.useCallback((att) => {
4236
+ const run = React24.useCallback((att) => {
3984
4237
  if (!upload) return;
3985
4238
  const ac = typeof AbortController !== "undefined" ? new AbortController() : null;
3986
4239
  controllers.current[att.id] = ac;
@@ -3997,14 +4250,14 @@ function useStagedFiles(upload, opts) {
3997
4250
  delete controllers.current[att.id];
3998
4251
  });
3999
4252
  }, [upload]);
4000
- const add = React22.useCallback((files) => {
4253
+ const add = React24.useCallback((files) => {
4001
4254
  if (!upload) return [];
4002
4255
  const atts = Array.from(files).map((f) => toAttachment(f));
4003
4256
  setItems((list) => list.concat(atts));
4004
4257
  atts.forEach(run);
4005
4258
  return atts;
4006
4259
  }, [upload, run]);
4007
- const remove = React22.useCallback((att) => {
4260
+ const remove = React24.useCallback((att) => {
4008
4261
  const ac = controllers.current[att.id];
4009
4262
  if (ac) {
4010
4263
  try {
@@ -4015,10 +4268,10 @@ function useStagedFiles(upload, opts) {
4015
4268
  }
4016
4269
  setItems((list) => list.filter((f) => f.id !== att.id));
4017
4270
  }, []);
4018
- const retry = React22.useCallback((att) => {
4271
+ const retry = React24.useCallback((att) => {
4019
4272
  run(att);
4020
4273
  }, [run]);
4021
- const clear = React22.useCallback(() => {
4274
+ const clear = React24.useCallback(() => {
4022
4275
  Object.values(controllers.current).forEach((ac) => {
4023
4276
  try {
4024
4277
  ac && ac.abort();
@@ -4034,7 +4287,7 @@ function useStagedFiles(upload, opts) {
4034
4287
  var DropzoneKit = { useStagedFiles };
4035
4288
 
4036
4289
  // src/components/forms/FileGrid.tsx
4037
- var import_jsx_runtime51 = require("react/jsx-runtime");
4290
+ var import_jsx_runtime54 = require("react/jsx-runtime");
4038
4291
  var truncateMiddle = (name, max = 34) => {
4039
4292
  if (!name || name.length <= max) return name;
4040
4293
  const ext = /\.[A-Za-z0-9]+$/.exec(name);
@@ -4043,7 +4296,7 @@ var truncateMiddle = (name, max = 34) => {
4043
4296
  return head + "\u2026" + tail;
4044
4297
  };
4045
4298
  function Progress({ value }) {
4046
- 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)) + "%" } }) });
4047
4300
  }
4048
4301
  function FileChip({ file, onOpen, onRemove, onRetry, compact: compact3 = false, className = "" }) {
4049
4302
  if (!file) return null;
@@ -4052,8 +4305,8 @@ function FileChip({ file, onOpen, onRemove, onRetry, compact: compact3 = false,
4052
4305
  const thumb = file.thumb && file.thumb.url || (image ? file.blobUrl || file.url : null);
4053
4306
  const meta = file.meta || (file.size ? formatBytes(file.size) : "");
4054
4307
  const clickable = !!onOpen && !uploading;
4055
- 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: [
4056
- /* @__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)(
4057
4310
  "button",
4058
4311
  {
4059
4312
  type: "button",
@@ -4062,16 +4315,16 @@ function FileChip({ file, onOpen, onRemove, onRetry, compact: compact3 = false,
4062
4315
  onClick: clickable ? () => onOpen(file) : void 0,
4063
4316
  title: file.name + (meta ? " \xB7 " + meta : ""),
4064
4317
  children: [
4065
- /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)("span", { className: "fd-file-icon", children: [
4066
- 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" }),
4067
- (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
4068
4321
  ] }),
4069
- /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)("span", { className: "fd-file-text", children: [
4070
- /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("span", { className: "fd-file-name", children: truncateMiddle(file.name, compact3 ? 26 : 40) }),
4071
- /* @__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: [
4072
- /* @__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" }),
4073
4326
  file.error
4074
- ] }) : 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: [
4075
4328
  Math.round(file.progress),
4076
4329
  "% uploaded"
4077
4330
  ] }) : meta })
@@ -4079,29 +4332,29 @@ function FileChip({ file, onOpen, onRemove, onRetry, compact: compact3 = false,
4079
4332
  ]
4080
4333
  }
4081
4334
  ),
4082
- uploading ? /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(Progress, { value: file.progress }) : null,
4083
- 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,
4084
- 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
4085
4338
  ] });
4086
4339
  }
4087
4340
  function FileTile({ file, onOpen, onRemove, maxHeight = 200, className = "" }) {
4088
4341
  if (!file) return null;
4089
4342
  const src = file.thumb && file.thumb.url || file.blobUrl || file.url;
4090
4343
  const uploading = file.progress != null && file.progress < 100 && !file.error;
4091
- return /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)("figure", { className: ["fd-tile", uploading ? "is-uploading" : "", file.error ? "is-error" : "", className].filter(Boolean).join(" "), children: [
4092
- /* @__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" }) }) }),
4093
- uploading ? /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(Progress, { value: file.progress }) : null,
4094
- file.error ? /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)("figcaption", { className: "fd-tile-err", children: [
4095
- /* @__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" }),
4096
4349
  file.error
4097
4350
  ] }) : null,
4098
- 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
4099
4352
  ] });
4100
4353
  }
4101
4354
  function FileStrip({ files = [], size = 68, onOpen, onRemove, onRetry, className = "" }) {
4102
4355
  const list = files.filter(Boolean);
4103
4356
  if (!list.length) return null;
4104
- 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)) });
4105
4358
  }
4106
4359
  var shortName = (name, keep = 5) => {
4107
4360
  const s = String(name || "file");
@@ -4115,19 +4368,19 @@ function FileCell({ file, onOpen, onRemove, onRetry }) {
4115
4368
  const image = isImage(file.mime, file.name);
4116
4369
  const thumb = file.thumb && file.thumb.url || (image ? file.blobUrl || file.url : null);
4117
4370
  const label = file.name + (file.size ? " \xB7 " + formatBytes(file.size) : "");
4118
- 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: [
4119
- /* @__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: [
4120
- thumb ? /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("img", { src: thumb, alt: "" }) : /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)("span", { className: "fd-cell-doc", children: [
4121
- /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("i", { className: "ph ph-" + iconForMime(file.mime, file.name), "aria-hidden": "true" }),
4122
- /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("span", { className: "fd-cell-name", children: shortName(file.name) }),
4123
- /* @__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) })
4124
4377
  ] }),
4125
- (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
4126
4379
  ] }),
4127
- uploading ? /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(Progress, { value: file.progress }) : null,
4128
- 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,
4129
- 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,
4130
- 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
4131
4384
  ] });
4132
4385
  }
4133
4386
  function FileGrid({ files = [], onOpen, onRemove, onRetry, tiles = true, maxHeight = 200, compact: compact3 = false, className = "" }) {
@@ -4135,15 +4388,15 @@ function FileGrid({ files = [], onOpen, onRemove, onRetry, tiles = true, maxHeig
4135
4388
  if (!list.length) return null;
4136
4389
  const pics = tiles ? list.filter((f) => isImage(f.mime, f.name)) : [];
4137
4390
  const rest = list.filter((f) => pics.indexOf(f) === -1);
4138
- return /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)("div", { className: ["fd-filegrid", className].filter(Boolean).join(" "), children: [
4139
- 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,
4140
- 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
4141
4394
  ] });
4142
4395
  }
4143
4396
 
4144
4397
  // src/components/forms/MarkdownEditor.tsx
4145
- var React23 = __toESM(require("react"), 1);
4146
- var import_jsx_runtime52 = require("react/jsx-runtime");
4398
+ var React25 = __toESM(require("react"), 1);
4399
+ var import_jsx_runtime55 = require("react/jsx-runtime");
4147
4400
  var isMac = typeof navigator !== "undefined" && /Mac|iPhone|iPad/.test(navigator.platform || navigator.userAgent || "");
4148
4401
  var INLINE_RE = /(\*\*\*[^*\n]+\*\*\*|\*\*[^*\n]+\*\*|__[^_\n]+__|~~[^~\n]+~~|`[^`\n]+`|\*[^*\s][^*\n]*\*|(?<![A-Za-z0-9_])_[^_\s][^_\n]*_|\[[^\]\n]*\]\([^)\s\n]*\)|https?:\/\/\S+)/g;
4149
4402
  function inlineParts(text) {
@@ -4356,7 +4609,7 @@ function syncDom(root, value) {
4356
4609
  while (root.children.length > lines.length) root.removeChild(root.lastChild);
4357
4610
  }
4358
4611
  var LIST_CONT = RE_LI;
4359
- var MarkdownEditor = React23.forwardRef(function MarkdownEditor2({
4612
+ var MarkdownEditor = React25.forwardRef(function MarkdownEditor2({
4360
4613
  value = "",
4361
4614
  onChange,
4362
4615
  onSubmit,
@@ -4375,10 +4628,10 @@ var MarkdownEditor = React23.forwardRef(function MarkdownEditor2({
4375
4628
  className = "",
4376
4629
  id
4377
4630
  }, ref) {
4378
- const boxRef = React23.useRef(null);
4379
- const composing = React23.useRef(false);
4380
- const pendingCaret = React23.useRef(null);
4381
- React23.useLayoutEffect(() => {
4631
+ const boxRef = React25.useRef(null);
4632
+ const composing = React25.useRef(false);
4633
+ const pendingCaret = React25.useRef(null);
4634
+ React25.useLayoutEffect(() => {
4382
4635
  const root = boxRef.current;
4383
4636
  if (!root || composing.current) return;
4384
4637
  const active = document.activeElement === root || root.contains(document.activeElement);
@@ -4387,7 +4640,7 @@ var MarkdownEditor = React23.forwardRef(function MarkdownEditor2({
4387
4640
  pendingCaret.current = null;
4388
4641
  if (active && caret != null) placeCaret(root, caret);
4389
4642
  }, [value]);
4390
- React23.useEffect(() => {
4643
+ React25.useEffect(() => {
4391
4644
  if (autoFocus && boxRef.current) boxRef.current.focus();
4392
4645
  }, [autoFocus]);
4393
4646
  const caretNow = () => {
@@ -4454,7 +4707,7 @@ var MarkdownEditor = React23.forwardRef(function MarkdownEditor2({
4454
4707
  api.replaceRange(from, to, next, from + next.length);
4455
4708
  }
4456
4709
  };
4457
- React23.useImperativeHandle(ref, () => api);
4710
+ React25.useImperativeHandle(ref, () => api);
4458
4711
  function detect(text, caret) {
4459
4712
  if (!onTrigger) return;
4460
4713
  const upto = text.slice(0, caret);
@@ -4567,8 +4820,8 @@ var MarkdownEditor = React23.forwardRef(function MarkdownEditor2({
4567
4820
  api.replaceRange(s.start, s.end, text.replace(/\r\n?/g, "\n"));
4568
4821
  };
4569
4822
  const lh = 1.55;
4570
- return /* @__PURE__ */ (0, import_jsx_runtime52.jsxs)("div", { className: ["fd-rme-wrap", disabled ? "is-disabled" : "", className].filter(Boolean).join(" "), children: [
4571
- /* @__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)(
4572
4825
  "div",
4573
4826
  {
4574
4827
  ref: boxRef,
@@ -4601,15 +4854,15 @@ var MarkdownEditor = React23.forwardRef(function MarkdownEditor2({
4601
4854
  }
4602
4855
  }
4603
4856
  ),
4604
- !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
4605
4858
  ] });
4606
4859
  });
4607
4860
 
4608
4861
  // src/components/platform/AccountMenu.tsx
4609
- var React25 = __toESM(require("react"), 1);
4862
+ var React27 = __toESM(require("react"), 1);
4610
4863
 
4611
4864
  // src/kits/session.ts
4612
- var React24 = __toESM(require("react"), 1);
4865
+ var React26 = __toESM(require("react"), 1);
4613
4866
  var PERMISSION_CATALOG = [
4614
4867
  { group: "Plans", items: [
4615
4868
  { key: "plan.view", label: "View plans", detail: "Read any plan in the workspace." },
@@ -6176,8 +6429,8 @@ function roadmap(overrides) {
6176
6429
  };
6177
6430
  }
6178
6431
  function useSession() {
6179
- const [s, setS] = React24.useState(getSession);
6180
- React24.useEffect(() => subscribe(setS), []);
6432
+ const [s, setS] = React26.useState(getSession);
6433
+ React26.useEffect(() => subscribe(setS), []);
6181
6434
  return s;
6182
6435
  }
6183
6436
  var SessionKit = {
@@ -6210,7 +6463,7 @@ var SessionKit = {
6210
6463
  };
6211
6464
 
6212
6465
  // src/components/platform/AccountMenu.tsx
6213
- var import_jsx_runtime53 = require("react/jsx-runtime");
6466
+ var import_jsx_runtime56 = require("react/jsx-runtime");
6214
6467
  var DEFAULT_LINKS = [
6215
6468
  { id: "profile", label: "Your profile", icon: "user-circle", href: "../admin/index.html#profile" },
6216
6469
  { id: "preferences", label: "Preferences", icon: "sliders-horizontal", href: "../admin/index.html#preferences" }
@@ -6221,7 +6474,7 @@ var DEFAULT_ADMIN_LINKS = [
6221
6474
  { id: "flags", label: "Feature flags", icon: "toggle-right", href: "../admin/index.html#flags", perm: "flags.manage" }
6222
6475
  ];
6223
6476
  function Item({ item, onPick }) {
6224
- return /* @__PURE__ */ (0, import_jsx_runtime53.jsxs)(
6477
+ return /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)(
6225
6478
  "button",
6226
6479
  {
6227
6480
  type: "button",
@@ -6229,9 +6482,9 @@ function Item({ item, onPick }) {
6229
6482
  className: "fd-acct-item",
6230
6483
  onClick: () => onPick(item),
6231
6484
  children: [
6232
- /* @__PURE__ */ (0, import_jsx_runtime53.jsx)("i", { className: "ph ph-" + item.icon, "aria-hidden": "true" }),
6233
- /* @__PURE__ */ (0, import_jsx_runtime53.jsx)("span", { style: { flex: 1 }, children: item.label }),
6234
- 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
6235
6488
  ]
6236
6489
  }
6237
6490
  );
@@ -6247,9 +6500,9 @@ function AccountMenu({
6247
6500
  ...rest
6248
6501
  }) {
6249
6502
  const session = SessionKit.useSession();
6250
- const [open, setOpen] = React25.useState(false);
6251
- const [switching, setSwitching] = React25.useState(false);
6252
- 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);
6253
6506
  const user = session.user;
6254
6507
  const visibleAdmin = adminLinks.filter((l) => !l.perm || SessionKit.can(l.perm));
6255
6508
  const pick = (item) => {
@@ -6263,8 +6516,8 @@ function AccountMenu({
6263
6516
  if (onSignOut) return onSignOut();
6264
6517
  window.alert("Signed out. (Simulated \u2014 no auth provider is wired up.)");
6265
6518
  };
6266
- return /* @__PURE__ */ (0, import_jsx_runtime53.jsxs)(import_jsx_runtime53.Fragment, { children: [
6267
- /* @__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)(
6268
6521
  "button",
6269
6522
  {
6270
6523
  type: "button",
@@ -6276,32 +6529,32 @@ function AccountMenu({
6276
6529
  onClick: () => setOpen((o) => !o),
6277
6530
  ...rest,
6278
6531
  children: [
6279
- /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(Avatar, { name: user.name, size: "sm" }),
6280
- /* @__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)" } })
6281
6534
  ]
6282
6535
  }
6283
6536
  ),
6284
- /* @__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: [
6285
- /* @__PURE__ */ (0, import_jsx_runtime53.jsxs)("div", { className: "fd-row", style: { gap: 10, padding: "12px 14px", borderBottom: "1px solid var(--border)" }, children: [
6286
- /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(Avatar, { name: user.name }),
6287
- /* @__PURE__ */ (0, import_jsx_runtime53.jsxs)("span", { className: "fd-stack", style: { gap: 1, minWidth: 0, flex: 1 }, children: [
6288
- /* @__PURE__ */ (0, import_jsx_runtime53.jsx)("span", { className: "fd-body-sm", style: { fontWeight: 700 }, children: user.name }),
6289
- /* @__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 })
6290
6543
  ] })
6291
6544
  ] }),
6292
- 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,
6293
- /* @__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)) }),
6294
- visibleAdmin.length ? /* @__PURE__ */ (0, import_jsx_runtime53.jsxs)("div", { className: "fd-acct-group", style: { borderTop: "1px solid var(--border)" }, children: [
6295
- /* @__PURE__ */ (0, import_jsx_runtime53.jsx)("span", { className: "fd-overline fd-muted", style: { padding: "8px 14px 4px", display: "block" }, children: "Administration" }),
6296
- 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))
6297
6550
  ] }) : null,
6298
- allowUserSwitch ? /* @__PURE__ */ (0, import_jsx_runtime53.jsxs)("div", { className: "fd-acct-group", style: { borderTop: "1px solid var(--border)" }, children: [
6299
- /* @__PURE__ */ (0, import_jsx_runtime53.jsxs)("button", { type: "button", role: "menuitem", className: "fd-acct-item", onClick: () => setSwitching((s) => !s), children: [
6300
- /* @__PURE__ */ (0, import_jsx_runtime53.jsx)("i", { className: "ph ph-user-switch", "aria-hidden": "true" }),
6301
- /* @__PURE__ */ (0, import_jsx_runtime53.jsx)("span", { style: { flex: 1 }, children: "View as another member" }),
6302
- /* @__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 } })
6303
6556
  ] }),
6304
- 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)(
6305
6558
  "button",
6306
6559
  {
6307
6560
  type: "button",
@@ -6313,34 +6566,34 @@ function AccountMenu({
6313
6566
  setSwitching(false);
6314
6567
  },
6315
6568
  children: [
6316
- /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(Avatar, { name: u.name, size: "sm" }),
6317
- /* @__PURE__ */ (0, import_jsx_runtime53.jsxs)("span", { className: "fd-stack", style: { gap: 0, flex: 1, minWidth: 0, alignItems: "flex-start" }, children: [
6318
- /* @__PURE__ */ (0, import_jsx_runtime53.jsx)("span", { style: { fontWeight: u.id === user.id ? 700 : 500 }, children: u.name }),
6319
- /* @__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(", ") })
6320
6573
  ] }),
6321
- 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
6322
6575
  ]
6323
6576
  },
6324
6577
  u.id
6325
6578
  )) }) : null
6326
6579
  ] }) : null,
6327
- /* @__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: [
6328
- /* @__PURE__ */ (0, import_jsx_runtime53.jsx)("i", { className: "ph ph-sign-out", "aria-hidden": "true" }),
6329
- /* @__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" })
6330
6583
  ] }) })
6331
6584
  ] }) })
6332
6585
  ] });
6333
6586
  }
6334
6587
 
6335
6588
  // src/components/platform/ApiSpecBrowser.tsx
6336
- var React26 = __toESM(require("react"), 1);
6337
- var import_jsx_runtime54 = require("react/jsx-runtime");
6589
+ var React28 = __toESM(require("react"), 1);
6590
+ var import_jsx_runtime57 = require("react/jsx-runtime");
6338
6591
  var METHOD_TONE = { GET: "success", POST: "info", PATCH: "warning", PUT: "warning", DELETE: "danger" };
6339
6592
  function Json({ obj }) {
6340
- 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) });
6341
6594
  }
6342
6595
  function Endpoint({ s, onRequest }) {
6343
- const [tried, setTried] = React26.useState(null);
6596
+ const [tried, setTried] = React28.useState(null);
6344
6597
  const run = async () => {
6345
6598
  setTried("busy");
6346
6599
  const t0 = (window.performance || Date).now();
@@ -6351,50 +6604,50 @@ function Endpoint({ s, onRequest }) {
6351
6604
  setTried({ ms: Math.round((window.performance || Date).now() - t0), error: String(e && e.message || e) });
6352
6605
  }
6353
6606
  };
6354
- 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: [
6355
- /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("div", { className: "fd-row", style: { gap: 10, padding: "14px 18px", flexWrap: "wrap" }, children: [
6356
- /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(Badge, { tone: METHOD_TONE[s.method] || "neutral", children: s.method }),
6357
- /* @__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 }),
6358
- s.isList ? /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(Badge, { tone: "neutral", icon: "rows", children: "Paged list" }) : null,
6359
- /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("span", { style: { flex: 1 } }),
6360
- /* @__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: [
6361
6614
  s.latency[0],
6362
6615
  "\u2013",
6363
6616
  s.latency[1],
6364
6617
  "ms"
6365
6618
  ] }),
6366
- /* @__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" })
6367
6620
  ] }),
6368
- /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("div", { className: "fd-stack", style: { gap: 14, padding: "0 18px 16px" }, children: [
6369
- /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("div", { className: "fd-stack", style: { gap: 6 }, children: [
6370
- /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("span", { className: "fd-body-sm", style: { fontWeight: 700 }, children: s.title }),
6371
- /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("p", { className: "fd-body-sm fd-secondary", style: { margin: 0, textWrap: "pretty" }, children: s.purpose }),
6372
- 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
6373
6626
  ] }),
6374
- /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("div", { style: { display: "grid", gridTemplateColumns: "repeat(auto-fit,minmax(280px,1fr))", gap: 12, alignItems: "start" }, children: [
6375
- s.request ? /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("div", { className: "fd-stack", style: { gap: 6 }, children: [
6376
- /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("span", { className: "fd-overline fd-muted", children: "Request body" }),
6377
- /* @__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 })
6378
6631
  ] }) : null,
6379
- s.query ? /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("div", { className: "fd-stack", style: { gap: 6 }, children: [
6380
- /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("span", { className: "fd-overline fd-muted", children: "Query" }),
6381
- /* @__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 })
6382
6635
  ] }) : null,
6383
- /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("div", { className: "fd-stack", style: { gap: 6 }, children: [
6384
- /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("span", { className: "fd-overline fd-muted", children: "Response 200" }),
6385
- /* @__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 })
6386
6639
  ] })
6387
6640
  ] }),
6388
- s.notes ? /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(Flag, { tone: "info", statement: "Implementation note", cost: s.notes, actions: null }) : null,
6389
- tried && tried !== "busy" ? /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("div", { className: "fd-stack", style: { gap: 6 }, children: [
6390
- /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("span", { className: "fd-row", style: { gap: 8 }, children: [
6391
- /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("span", { className: "fd-overline fd-muted", children: "Simulated response" }),
6392
- /* @__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: [
6393
6646
  tried.ms,
6394
6647
  "ms"
6395
6648
  ] })
6396
6649
  ] }),
6397
- /* @__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 })
6398
6651
  ] }) : null
6399
6652
  ] })
6400
6653
  ] }) });
@@ -6413,58 +6666,58 @@ function ApiSpecBrowser({
6413
6666
  className = "",
6414
6667
  ...rest
6415
6668
  }) {
6416
- const [q, setQ] = React26.useState("");
6417
- const [method, setMethod] = React26.useState(null);
6418
- const [mod, setMod] = React26.useState(null);
6419
- 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);
6420
6673
  const activeModule = modules && modules.find((m) => m.id === mod);
6421
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())));
6422
6675
  const effGroups = groups && groups.length ? groups : [["All endpoints", spec.map((s) => s.id)]];
6423
6676
  const methods = [...new Set(spec.map((s) => s.method))];
6424
6677
  const listCount = spec.filter((s) => s.isList).length;
6425
- return /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 20, maxWidth: 1100 }, ...rest, children: [
6426
- /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("div", { className: "fd-stack", style: { gap: 10 }, children: [
6427
- kicker ? /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("span", { className: "fd-overline fd-muted", children: kicker }) : null,
6428
- /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("h1", { className: "fd-h1", style: { margin: 0 }, children: title }),
6429
- 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
6430
6683
  ] }),
6431
- modules && modules.length ? /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("div", { className: "fd-stack", style: { gap: 8 }, children: [
6432
- /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("span", { className: "fd-overline fd-muted", children: "Filter by screen \u2014 every endpoint that screen depends on" }),
6433
- /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("div", { className: "fd-row", style: { gap: 8, flexWrap: "wrap" }, children: [
6434
- /* @__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: [
6435
6688
  "All screens ",
6436
- /* @__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 })
6437
6690
  ] }),
6438
- 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: [
6439
6692
  m.label,
6440
6693
  " ",
6441
- /* @__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 })
6442
6695
  ] }, m.id))
6443
6696
  ] }),
6444
- activeModule ? /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(
6697
+ activeModule ? /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
6445
6698
  Flag,
6446
6699
  {
6447
6700
  tone: "info",
6448
6701
  statement: activeModule.label + " calls " + activeModule.endpoints.length + " endpoints.",
6449
6702
  cost: "Integration checklist for this screen: " + activeModule.endpoints.join(", ") + ". Wire these and the screen is done.",
6450
- 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" })
6451
6704
  }
6452
6705
  ) : null
6453
6706
  ] }) : null,
6454
- sourceNote ? /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(Flag, { tone: "info", statement: "Design-first: this page is the spec.", cost: sourceNote, actions: null }) : null,
6455
- /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("div", { className: "fd-row", style: { gap: 10, flexWrap: "wrap" }, children: [
6456
- /* @__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 } }),
6457
- 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: [
6458
6711
  m,
6459
6712
  " ",
6460
- /* @__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 })
6461
6714
  ] }, m)),
6462
- 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: [
6463
6716
  "Paged lists ",
6464
- /* @__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 })
6465
6718
  ] }) : null,
6466
- /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("span", { style: { flex: 1 } }),
6467
- /* @__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: [
6468
6721
  hits.length,
6469
6722
  " of ",
6470
6723
  spec.length,
@@ -6472,31 +6725,31 @@ function ApiSpecBrowser({
6472
6725
  listCount ? " \xB7 " + listCount + " paged" : ""
6473
6726
  ] })
6474
6727
  ] }),
6475
- 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]) => {
6476
6729
  const items = hits.filter((s) => ids.indexOf(s.id) >= 0);
6477
6730
  if (!items.length) return null;
6478
- return /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("div", { className: "fd-stack", style: { gap: 12 }, children: [
6479
- /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("span", { className: "fd-label-lg", children: g }),
6480
- 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))
6481
6734
  ] }, g);
6482
6735
  }),
6483
- 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: [
6484
- /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("span", { className: "fd-overline fd-muted", style: { width: 110, flex: "none", paddingTop: 2 }, children: k }),
6485
- /* @__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 })
6486
6739
  ] }, k)) }) }) : null,
6487
- 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: [
6488
- /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(Badge, { tone: "danger", children: id }),
6489
- /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("span", { className: "fd-stack", style: { gap: 2, flex: 1 }, children: [
6490
- /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("span", { className: "fd-body-sm", style: { fontWeight: 600 }, children: question }),
6491
- /* @__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 })
6492
6745
  ] })
6493
6746
  ] }, id)) }) }) : null
6494
6747
  ] });
6495
6748
  }
6496
6749
 
6497
6750
  // src/components/platform/ProfilePage.tsx
6498
- var React27 = __toESM(require("react"), 1);
6499
- var import_jsx_runtime55 = require("react/jsx-runtime");
6751
+ var React29 = __toESM(require("react"), 1);
6752
+ var import_jsx_runtime58 = require("react/jsx-runtime");
6500
6753
  var TIMEZONES = ["America/New_York", "America/Chicago", "America/Denver", "America/Los_Angeles", "America/Anchorage", "Pacific/Honolulu", "Europe/London", "Europe/Berlin"];
6501
6754
  var NOTIFY = [
6502
6755
  { key: "planShared", label: "A plan is shared with me", detail: "Someone sends you a plan or a client link." },
@@ -6508,7 +6761,7 @@ var NOTIFY = [
6508
6761
  function ProfilePage({ user: userProp, onSave, onNavigate, sessions, showSessions = true, className = "", ...rest }) {
6509
6762
  const session = SessionKit.useSession();
6510
6763
  const user = userProp || session.user;
6511
- const [draft, setDraft] = React27.useState(() => ({
6764
+ const [draft, setDraft] = React29.useState(() => ({
6512
6765
  name: user.name || "",
6513
6766
  title: user.title || "",
6514
6767
  email: user.email || "",
@@ -6517,8 +6770,8 @@ function ProfilePage({ user: userProp, onSave, onNavigate, sessions, showSession
6517
6770
  bio: user.bio || "",
6518
6771
  notify: user.notify || { planShared: true, planChanged: true, goalMissed: true, flagChanged: false, weekly: true }
6519
6772
  }));
6520
- const [saving, setSaving] = React27.useState(false);
6521
- const [saved, setSaved] = React27.useState(false);
6773
+ const [saving, setSaving] = React29.useState(false);
6774
+ const [saved, setSaved] = React29.useState(false);
6522
6775
  const set = (k, v) => {
6523
6776
  setDraft((d) => Object.assign({}, d, { [k]: v }));
6524
6777
  setSaved(false);
@@ -6540,43 +6793,43 @@ function ProfilePage({ user: userProp, onSave, onNavigate, sessions, showSession
6540
6793
  { id: "s2", device: "iPhone 15 \xB7 Safari", where: "Denver, CO", when: "2 hours ago" },
6541
6794
  { id: "s3", device: "Windows \xB7 Edge", where: "Chicago, IL", when: "Aug 12" }
6542
6795
  ];
6543
- return /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 20, maxWidth: 860 }, ...rest, children: [
6544
- /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)("div", { className: "fd-stack", style: { gap: 10 }, children: [
6545
- /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("span", { className: "fd-overline fd-muted", children: "Account" }),
6546
- /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("h1", { className: "fd-h1", style: { margin: 0 }, children: "Your profile" }),
6547
- /* @__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." })
6548
6801
  ] }),
6549
- /* @__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: [
6550
- /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(Avatar, { name: draft.name || user.name, size: "lg" }),
6551
- /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)("div", { className: "fd-stack", style: { gap: 4, flex: 1, minWidth: 200 }, children: [
6552
- /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("span", { className: "fd-h3", style: { margin: 0 }, children: draft.name || user.name }),
6553
- /* @__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: [
6554
6807
  draft.title || "No title set",
6555
6808
  " \xB7 ",
6556
6809
  user.team || "No team"
6557
6810
  ] }),
6558
- /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)("span", { className: "fd-row", style: { gap: 6, flexWrap: "wrap", paddingTop: 4 }, children: [
6559
- session.roles.map((r) => /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(Badge, { tone: r.id === "owner" ? "success" : "neutral", children: r.name }, r.id)),
6560
- 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
6561
6814
  ] })
6562
6815
  ] }),
6563
- /* @__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" })
6564
6817
  ] }) }),
6565
- /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(
6818
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
6566
6819
  Card,
6567
6820
  {
6568
- title: /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)("span", { className: "fd-stack", style: { gap: 2 }, children: [
6569
- /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("span", { children: "Identity" }),
6570
- /* @__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" })
6571
6824
  ] }),
6572
6825
  elevation: "flat",
6573
- children: /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)("div", { className: "fd-stack", style: { gap: 14 }, children: [
6574
- /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)("div", { style: { display: "grid", gridTemplateColumns: "repeat(auto-fit,minmax(220px,1fr))", gap: 14 }, children: [
6575
- /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(Input, { label: "Full name", value: draft.name, onChange: (e) => set("name", e.target.value) }),
6576
- /* @__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" })
6577
6830
  ] }),
6578
- /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)("div", { style: { display: "grid", gridTemplateColumns: "repeat(auto-fit,minmax(220px,1fr))", gap: 14 }, children: [
6579
- /* @__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)(
6580
6833
  Input,
6581
6834
  {
6582
6835
  label: "Work email",
@@ -6586,9 +6839,9 @@ function ProfilePage({ user: userProp, onSave, onNavigate, sessions, showSession
6586
6839
  help: user.sso ? "Managed by your identity provider \u2014 change it there." : "Contact an administrator to change this."
6587
6840
  }
6588
6841
  ),
6589
- /* @__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" })
6590
6843
  ] }),
6591
- /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(
6844
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
6592
6845
  Textarea,
6593
6846
  {
6594
6847
  label: "Short bio",
@@ -6602,8 +6855,8 @@ function ProfilePage({ user: userProp, onSave, onNavigate, sessions, showSession
6602
6855
  ] })
6603
6856
  }
6604
6857
  ),
6605
- /* @__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: [
6606
- /* @__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)(
6607
6860
  Select,
6608
6861
  {
6609
6862
  label: "Time zone",
@@ -6613,28 +6866,28 @@ function ProfilePage({ user: userProp, onSave, onNavigate, sessions, showSession
6613
6866
  help: "Flight dates and schedules render in this zone."
6614
6867
  }
6615
6868
  ),
6616
- /* @__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" })
6617
6870
  ] }) }),
6618
- /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(
6871
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
6619
6872
  Card,
6620
6873
  {
6621
- title: /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)("span", { className: "fd-stack", style: { gap: 2 }, children: [
6622
- /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("span", { children: "Notifications" }),
6623
- /* @__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" })
6624
6877
  ] }),
6625
6878
  elevation: "flat",
6626
- 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)) })
6627
6880
  }
6628
6881
  ),
6629
- /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)(
6882
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)(
6630
6883
  Card,
6631
6884
  {
6632
- title: /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)("span", { className: "fd-stack", style: { gap: 2 }, children: [
6633
- /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("span", { children: "Access" }),
6634
- /* @__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" })
6635
6888
  ] }),
6636
6889
  elevation: "flat",
6637
- action: /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(
6890
+ action: /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
6638
6891
  Button,
6639
6892
  {
6640
6893
  size: "sm",
@@ -6645,39 +6898,39 @@ function ProfilePage({ user: userProp, onSave, onNavigate, sessions, showSession
6645
6898
  }
6646
6899
  ),
6647
6900
  children: [
6648
- /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)("div", { className: "fd-stack", style: { gap: 0 }, children: [
6649
- /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(CardRow, { label: "Roles", children: session.roles.map((r) => r.name).join(", ") || "None" }),
6650
- /* @__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: [
6651
6904
  session.permissions.length,
6652
6905
  " granted"
6653
6906
  ] }),
6654
- /* @__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" })
6655
6908
  ] }),
6656
- /* @__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." })
6657
6910
  ]
6658
6911
  }
6659
6912
  ),
6660
- showSessions ? /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(
6913
+ showSessions ? /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
6661
6914
  Card,
6662
6915
  {
6663
6916
  title: "Signed-in devices",
6664
6917
  elevation: "flat",
6665
- action: /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(Button, { size: "sm", variant: "ghost", icon: "sign-out", children: "Sign out everywhere" }),
6666
- 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: [
6667
- /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("i", { className: "ph ph-device-mobile", style: { fontSize: 16, color: "var(--text-muted)" }, "aria-hidden": "true" }),
6668
- /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)("span", { className: "fd-stack", style: { gap: 1, flex: 1, minWidth: 160 }, children: [
6669
- /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("span", { className: "fd-body-sm", style: { fontWeight: 600 }, children: s.device }),
6670
- /* @__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: [
6671
6924
  s.where,
6672
6925
  " \xB7 ",
6673
6926
  s.when
6674
6927
  ] })
6675
6928
  ] }),
6676
- 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" })
6677
6930
  ] }, s.id)) })
6678
6931
  }
6679
6932
  ) : null,
6680
- /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)("div", { className: "fd-row", style: {
6933
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("div", { className: "fd-row", style: {
6681
6934
  gap: 10,
6682
6935
  flexWrap: "wrap",
6683
6936
  position: "sticky",
@@ -6688,8 +6941,8 @@ function ProfilePage({ user: userProp, onSave, onNavigate, sessions, showSession
6688
6941
  border: "1px solid var(--border)",
6689
6942
  boxShadow: "0 -4px 16px rgba(11,13,17,.06)"
6690
6943
  }, children: [
6691
- /* @__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" }),
6692
- /* @__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)(
6693
6946
  Button,
6694
6947
  {
6695
6948
  size: "sm",
@@ -6702,16 +6955,16 @@ function ProfilePage({ user: userProp, onSave, onNavigate, sessions, showSession
6702
6955
  children: "Discard"
6703
6956
  }
6704
6957
  ),
6705
- /* @__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" })
6706
6959
  ] })
6707
6960
  ] });
6708
6961
  }
6709
6962
 
6710
6963
  // src/components/platform/RoadmapTimeline.tsx
6711
- var React29 = __toESM(require("react"), 1);
6964
+ var React31 = __toESM(require("react"), 1);
6712
6965
 
6713
6966
  // src/kits/runtime.ts
6714
- var React28 = __toESM(require("react"), 1);
6967
+ var React30 = __toESM(require("react"), 1);
6715
6968
  var WIRED_ENDPOINTS = [
6716
6969
  // Nothing yet. Every id below would come from a real service:
6717
6970
  // "plan.get", "placements.list", …
@@ -6882,8 +7135,8 @@ var RuntimeKit = {
6882
7135
  };
6883
7136
  RuntimeKit.declare(FEATURE_NEEDS);
6884
7137
  function useRuntimeMode() {
6885
- const [m, setM] = React28.useState(RuntimeKit.getMode());
6886
- React28.useEffect(() => RuntimeKit.subscribe(setM), []);
7138
+ const [m, setM] = React30.useState(RuntimeKit.getMode());
7139
+ React30.useEffect(() => RuntimeKit.subscribe(setM), []);
6887
7140
  return m;
6888
7141
  }
6889
7142
  function useFeatureStatus(key) {
@@ -6902,7 +7155,7 @@ var UseRuntimeMode = useRuntimeMode;
6902
7155
  var UseFeatureStatus = useFeatureStatus;
6903
7156
 
6904
7157
  // src/components/platform/RoadmapTimeline.tsx
6905
- var import_jsx_runtime56 = require("react/jsx-runtime");
7158
+ var import_jsx_runtime59 = require("react/jsx-runtime");
6906
7159
  var STATUS = {
6907
7160
  shipped: { tone: "success", icon: "check-circle", label: "Wired" },
6908
7161
  next: { tone: "warning", icon: "traffic-cone", label: "Not wired" },
@@ -6917,45 +7170,45 @@ function RoadmapCard({ item, byKey, onOpenFlag }) {
6917
7170
  const s = STATUS[item.status] || STATUS.planned;
6918
7171
  const deps = (item.dependsOn || []).map((k) => byKey[k]).filter(Boolean);
6919
7172
  const blocking = deps.filter((d) => !d.implemented);
6920
- 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: [
6921
- /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("div", { className: "fd-row", style: { gap: 8, flexWrap: "wrap" }, children: [
6922
- /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("span", { className: "fd-body", style: { fontWeight: 700, flex: 1, minWidth: 140 }, children: item.label }),
6923
- /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(Badge, { tone: "neutral", icon: PROJECT_ICON[item.project] || "squares-four", children: item.project }),
6924
- /* @__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 })
6925
7178
  ] }),
6926
- /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("p", { className: "fd-body-sm fd-secondary", style: { margin: 0, textWrap: "pretty" }, children: item.description }),
6927
- item.backend ? /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("div", { className: "fd-row", style: { gap: 10, alignItems: "flex-start" }, children: [
6928
- /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("span", { className: "fd-overline fd-muted", style: { width: 62, flex: "none", paddingTop: 2 }, children: "Backend" }),
6929
- /* @__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 })
6930
7183
  ] }) : null,
6931
- /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("div", { className: "fd-row", style: { gap: 12, flexWrap: "wrap" }, children: [
6932
- item.effort ? /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("span", { className: "fd-body-sm fd-muted", children: [
6933
- /* @__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" }),
6934
7187
  " ",
6935
7188
  item.effort
6936
7189
  ] }) : null,
6937
- /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("span", { className: "fd-body-sm fd-muted", children: [
6938
- /* @__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" }),
6939
7192
  " ",
6940
7193
  item.owner
6941
7194
  ] }),
6942
- item.screen ? /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(Badge, { tone: "neutral", icon: "browser", children: "screen" }) : null,
6943
- /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("span", { style: { flex: 1 } }),
6944
- /* @__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)(
6945
7198
  "button",
6946
7199
  {
6947
7200
  type: "button",
6948
7201
  onClick: () => onOpenFlag && onOpenFlag(item.key),
6949
7202
  style: { all: "unset", cursor: "pointer", display: "inline-flex", alignItems: "center", gap: 5 },
6950
- 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 })
6951
7204
  }
6952
7205
  )
6953
7206
  ] }),
6954
- 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: [
6955
- /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("span", { className: "fd-overline fd-muted", style: { paddingTop: 3 }, children: "After" }),
6956
- 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))
6957
7210
  ] }) : null,
6958
- 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: [
6959
7212
  "Blocked until ",
6960
7213
  blocking.map((d) => d.label).join(" and "),
6961
7214
  " ",
@@ -6966,12 +7219,12 @@ function RoadmapCard({ item, byKey, onOpenFlag }) {
6966
7219
  }
6967
7220
  function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
6968
7221
  const session = SessionKit.useSession();
6969
- const [project, setProject] = React29.useState("");
6970
- const [q, setQ] = React29.useState("");
6971
- const scrollRef = React29.useRef(null);
6972
- const nowRef = React29.useRef(null);
6973
- const rm = React29.useMemo(() => SessionKit.roadmap({ isComplete: RuntimeKit.isComplete }), [session]);
6974
- 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(() => {
6975
7228
  const m = {};
6976
7229
  rm.items.forEach((i) => {
6977
7230
  m[i.key] = i;
@@ -6980,7 +7233,7 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
6980
7233
  }, [rm]);
6981
7234
  const items = rm.items.filter((i) => (!project || i.project === project) && (!q || (i.label + " " + i.description + " " + (i.backend || "") + " " + i.key).toLowerCase().includes(q.toLowerCase())));
6982
7235
  const projects = [...new Set(rm.items.map((i) => i.project))];
6983
- React29.useEffect(() => {
7236
+ React31.useEffect(() => {
6984
7237
  let raf1 = 0, raf2 = 0;
6985
7238
  const place = () => {
6986
7239
  const box = scrollRef.current, mark = nowRef.current;
@@ -7008,23 +7261,23 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
7008
7261
  }, 0);
7009
7262
  const nextPhase = items.find((i) => !i.implemented);
7010
7263
  let lastPhase = null;
7011
- return /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("div", { className: "fd-stack", style: { gap: 16, maxWidth: 1e3 }, children: [
7012
- /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("div", { className: "fd-stack", style: { gap: 10 }, children: [
7013
- /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("span", { className: "fd-overline fd-muted", children: "Architecture" }),
7014
- /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("h1", { className: "fd-h1", style: { margin: 0 }, children: title }),
7015
- /* @__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." })
7016
7269
  ] }),
7017
- /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("div", { className: "fd-grid-stats is-thin", children: [
7018
- /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(StatTile, { compact: true, label: "Wired", value: String(rm.shipped), sub: "of " + rm.items.length + " features" }),
7019
- /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(StatTile, { compact: true, label: "Remaining", value: String(rm.remaining), sub: "backend work" }),
7020
- /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(StatTile, { compact: true, label: "Est. effort", value: days ? days + " days" : "\u2014", sub: "sum of estimates, not calendar" }),
7021
- /* @__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" })
7022
7275
  ] }),
7023
- /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("div", { className: "fd-row", style: { gap: 10, flexWrap: "wrap" }, children: [
7024
- /* @__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 } }),
7025
- /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(Select, { placeholder: "All projects", value: project, onChange: (e) => setProject(e.target.value), options: projects, style: { width: 190 } }),
7026
- /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("span", { style: { flex: 1 } }),
7027
- /* @__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)(
7028
7281
  Button,
7029
7282
  {
7030
7283
  size: "sm",
@@ -7038,7 +7291,7 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
7038
7291
  }
7039
7292
  )
7040
7293
  ] }),
7041
- /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(
7294
+ /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(
7042
7295
  Flag,
7043
7296
  {
7044
7297
  tone: "info",
@@ -7047,60 +7300,60 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
7047
7300
  actions: null
7048
7301
  }
7049
7302
  ),
7050
- /* @__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: [
7051
- /* @__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%" } }) }),
7052
7305
  items.map((item, n) => {
7053
7306
  const showPhase = item.phase !== lastPhase;
7054
7307
  lastPhase = item.phase;
7055
7308
  const inPhase = items.filter((i) => i.phase === item.phase).length;
7056
7309
  const isBoundary = n === firstPending;
7057
- return /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)(React29.Fragment, { children: [
7058
- showPhase ? /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("div", { className: "fd-rm-era", children: [
7059
- /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("span", { className: "fd-row", style: { gap: 8, flexWrap: "wrap", alignItems: "baseline" }, children: [
7060
- /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("span", { style: { fontWeight: 700 }, children: item.phase === 0 ? "Shipped" : "Phase " + item.phase + " \u2014 " + item.phaseName }),
7061
- 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: [
7062
7315
  fmtDate(item.phaseStart),
7063
7316
  " \u2013 ",
7064
7317
  fmtDate(item.date)
7065
7318
  ] }),
7066
- /* @__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: [
7067
7320
  "\xB7 ",
7068
7321
  inPhase,
7069
7322
  " feature",
7070
7323
  inPhase === 1 ? "" : "s"
7071
7324
  ] })
7072
7325
  ] }),
7073
- 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
7074
7327
  ] }) : null,
7075
- 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: [
7076
- /* @__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" }),
7077
7330
  " You are here \u2014 everything above is wired"
7078
7331
  ] }) }) : null,
7079
- /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("div", { className: "fd-rm-row", children: [
7080
- /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("span", { className: "fd-rm-dot " + (item.implemented ? "is-shipped" : item.status === "next" ? "is-next" : "") }),
7081
- /* @__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: [
7082
7335
  fmtDate(item.date),
7083
- /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("br", {}),
7084
- /* @__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 })
7085
7338
  ] }),
7086
- /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(RoadmapCard, { item, byKey, onOpenFlag })
7339
+ /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(RoadmapCard, { item, byKey, onOpenFlag })
7087
7340
  ] })
7088
7341
  ] }, item.key);
7089
7342
  }),
7090
- !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
7091
7344
  ] }) }) }),
7092
- /* @__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: [
7093
7346
  "Derived from the feature-flag registry \u2014 each entry's status is its flag's ",
7094
- /* @__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" }),
7095
7348
  " field, so this page cannot drift from what the apps actually do."
7096
7349
  ] })
7097
7350
  ] });
7098
7351
  }
7099
7352
 
7100
7353
  // src/components/platform/ComingSoon.tsx
7101
- var React30 = __toESM(require("react"), 1);
7354
+ var React32 = __toESM(require("react"), 1);
7102
7355
  var import_react_dom7 = require("react-dom");
7103
- var import_jsx_runtime57 = require("react/jsx-runtime");
7356
+ var import_jsx_runtime60 = require("react/jsx-runtime");
7104
7357
  var BYPASS_STORE = "fd.soon.bypass.v1";
7105
7358
  function readBypassed() {
7106
7359
  try {
@@ -7116,8 +7369,8 @@ function writeBypassed(list) {
7116
7369
  }
7117
7370
  }
7118
7371
  function useBypass(key) {
7119
- const [on, setOn] = React30.useState(() => !!key && readBypassed().indexOf(key) >= 0);
7120
- React30.useEffect(() => {
7372
+ const [on, setOn] = React32.useState(() => !!key && readBypassed().indexOf(key) >= 0);
7373
+ React32.useEffect(() => {
7121
7374
  setOn(!!key && readBypassed().indexOf(key) >= 0);
7122
7375
  }, [key]);
7123
7376
  const set = (next) => {
@@ -7130,43 +7383,43 @@ function useBypass(key) {
7130
7383
  return [on, set];
7131
7384
  }
7132
7385
  function SoonCard({ label, detail, backend, eta, effort, onRoadmap, allowed, onBypass }) {
7133
- return /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(import_jsx_runtime57.Fragment, { children: [
7134
- /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("span", { className: "fd-soon-badge", children: [
7135
- /* @__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" }),
7136
7389
  label
7137
7390
  ] }),
7138
- detail ? /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { className: "fd-soon-detail", children: detail }) : null,
7139
- backend ? /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("span", { className: "fd-soon-backend", children: [
7140
- /* @__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" }),
7141
7394
  " ",
7142
7395
  backend
7143
7396
  ] }) : null,
7144
- eta || effort || onRoadmap ? /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("span", { className: "fd-soon-meta", children: [
7145
- eta ? /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("span", { children: [
7146
- /* @__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" }),
7147
7400
  " ",
7148
7401
  eta
7149
7402
  ] }) : null,
7150
- effort ? /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("span", { children: [
7151
- /* @__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" }),
7152
7405
  " ",
7153
7406
  effort
7154
7407
  ] }) : null,
7155
- 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: [
7156
7409
  "See the roadmap ",
7157
- /* @__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" })
7158
7411
  ] }) : null
7159
7412
  ] }) : null,
7160
- allowed ? /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("button", { type: "button", className: "fd-soon-view", onClick: onBypass, children: [
7161
- /* @__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" }),
7162
7415
  " View and use it anyway"
7163
7416
  ] }) : null
7164
7417
  ] });
7165
7418
  }
7166
7419
  function useHoverCard(open) {
7167
- const anchor = React30.useRef(null);
7168
- const [pos, setPos] = React30.useState(null);
7169
- React30.useLayoutEffect(() => {
7420
+ const anchor = React32.useRef(null);
7421
+ const [pos, setPos] = React32.useState(null);
7422
+ React32.useLayoutEffect(() => {
7170
7423
  if (!open || !anchor.current) {
7171
7424
  setPos(null);
7172
7425
  return;
@@ -7218,9 +7471,9 @@ function ComingSoon({
7218
7471
  const tip = [label, detail, backend ? "Needs " + backend : null, eta ? "ETA " + eta : null, effort].filter(Boolean).join(" \xB7 ");
7219
7472
  if (inline) {
7220
7473
  if (allowed && bypassed) {
7221
- 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: [
7222
7475
  children,
7223
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
7476
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
7224
7477
  "button",
7225
7478
  {
7226
7479
  type: "button",
@@ -7228,12 +7481,12 @@ function ComingSoon({
7228
7481
  title: "Unwired \u2014 writes go to the simulated backend. " + tip + " Click to re-blur.",
7229
7482
  onClick: () => setBypassed(false),
7230
7483
  "aria-label": "Re-blur this unwired feature",
7231
- 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" })
7232
7485
  }
7233
7486
  )
7234
7487
  ] });
7235
7488
  }
7236
- return /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
7489
+ return /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
7237
7490
  InlineSoon,
7238
7491
  {
7239
7492
  label,
@@ -7253,20 +7506,20 @@ function ComingSoon({
7253
7506
  );
7254
7507
  }
7255
7508
  if (allowed && bypassed) {
7256
- return /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 14 }, ...rest, children: [
7257
- /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { className: "fd-soon-bar", role: "status", children: [
7258
- /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("span", { className: "fd-soon-badge", children: [
7259
- /* @__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" }),
7260
7513
  "Unwired feature \u2014 you are using it anyway"
7261
7514
  ] }),
7262
- /* @__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." }),
7263
- /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("span", { className: "fd-soon-bar-actions", children: [
7264
- 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: [
7265
7518
  "Roadmap ",
7266
- /* @__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" })
7267
7520
  ] }) : null,
7268
- /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("button", { type: "button", className: "fd-soon-link", onClick: () => setBypassed(false), children: [
7269
- /* @__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" }),
7270
7523
  " Re-blur"
7271
7524
  ] })
7272
7525
  ] })
@@ -7274,10 +7527,10 @@ function ComingSoon({
7274
7527
  children
7275
7528
  ] });
7276
7529
  }
7277
- return /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { className: ["fd-soon", className].filter(Boolean).join(" "), style: minHeight ? { minHeight } : void 0, ...rest, children: [
7278
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("div", { className: "fd-soon-under", style: { filter: "blur(" + blur + "px) saturate(.62)" }, ...{ inert: "" }, "aria-hidden": "true", children }),
7279
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("div", { className: "fd-soon-veil" }),
7280
- /* @__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)(
7281
7534
  SoonCard,
7282
7535
  {
7283
7536
  label,
@@ -7293,9 +7546,9 @@ function ComingSoon({
7293
7546
  ] });
7294
7547
  }
7295
7548
  function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, onBypass, blur, tip, className, rest, children }) {
7296
- const [open, setOpen] = React30.useState(false);
7549
+ const [open, setOpen] = React32.useState(false);
7297
7550
  const [anchor, pos] = useHoverCard(open);
7298
- const close = React30.useRef(null);
7551
+ const close = React32.useRef(null);
7299
7552
  const show = () => {
7300
7553
  if (close.current) {
7301
7554
  clearTimeout(close.current);
@@ -7311,10 +7564,10 @@ function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, o
7311
7564
  setOpen(false);
7312
7565
  }, 140);
7313
7566
  };
7314
- React30.useEffect(() => () => {
7567
+ React32.useEffect(() => () => {
7315
7568
  if (close.current) clearTimeout(close.current);
7316
7569
  }, []);
7317
- return /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(
7570
+ return /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)(
7318
7571
  "span",
7319
7572
  {
7320
7573
  ref: anchor,
@@ -7325,8 +7578,8 @@ function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, o
7325
7578
  onBlur: hide,
7326
7579
  ...rest,
7327
7580
  children: [
7328
- /* @__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 }),
7329
- /* @__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)(
7330
7583
  "button",
7331
7584
  {
7332
7585
  type: "button",
@@ -7337,11 +7590,11 @@ function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, o
7337
7590
  onFocus: show,
7338
7591
  onBlur: hide,
7339
7592
  onClick: () => open ? setOpen(false) : show(),
7340
- 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" })
7341
7594
  }
7342
7595
  ),
7343
7596
  open && pos ? (0, import_react_dom7.createPortal)(
7344
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
7597
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
7345
7598
  "div",
7346
7599
  {
7347
7600
  className: "fd-soon-note fd-soon-hovercard",
@@ -7349,7 +7602,7 @@ function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, o
7349
7602
  style: { position: "fixed", left: pos.left, top: pos.top, bottom: pos.bottom, width: pos.width },
7350
7603
  onMouseEnter: show,
7351
7604
  onMouseLeave: hide,
7352
- children: /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
7605
+ children: /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
7353
7606
  SoonCard,
7354
7607
  {
7355
7608
  label,
@@ -7379,10 +7632,10 @@ function formatEta(iso2) {
7379
7632
  var FormatEta = formatEta;
7380
7633
 
7381
7634
  // src/components/platform/Gate.tsx
7382
- var import_jsx_runtime58 = require("react/jsx-runtime");
7635
+ var import_jsx_runtime61 = require("react/jsx-runtime");
7383
7636
  function PermissionDenied({ permission, title, detail, compact: compact3 = false, className = "", ...rest }) {
7384
7637
  const need = Array.isArray(permission) ? permission : [permission].filter(Boolean);
7385
- return /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)(
7638
+ return /* @__PURE__ */ (0, import_jsx_runtime61.jsxs)(
7386
7639
  "div",
7387
7640
  {
7388
7641
  className: ["fd-stack", className].filter(Boolean).join(" "),
@@ -7398,14 +7651,14 @@ function PermissionDenied({ permission, title, detail, compact: compact3 = false
7398
7651
  },
7399
7652
  ...rest,
7400
7653
  children: [
7401
- /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("span", { className: "fd-row", style: { gap: 8 }, children: [
7402
- /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("i", { className: "ph ph-lock-simple", style: { fontSize: 16, color: "var(--text-muted)" }, "aria-hidden": "true" }),
7403
- /* @__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" })
7404
7657
  ] }),
7405
- /* @__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." }),
7406
- need.length ? /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("span", { className: "fd-row", style: { gap: 6, flexWrap: "wrap" }, children: [
7407
- /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("span", { className: "fd-overline fd-muted", children: "Requires" }),
7408
- 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: {
7409
7662
  fontSize: 11.5,
7410
7663
  padding: "2px 7px",
7411
7664
  borderRadius: 5,
@@ -7426,7 +7679,7 @@ function Gate({ perm, anyOf, role, silent = false, fallback, compact: compact3 =
7426
7679
  if (ok) return children;
7427
7680
  if (fallback !== void 0) return fallback;
7428
7681
  if (silent) return null;
7429
- 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 });
7430
7683
  }
7431
7684
  function FeatureGate({
7432
7685
  flag,
@@ -7447,7 +7700,7 @@ function FeatureGate({
7447
7700
  if (!preview) return fallback;
7448
7701
  const f = SessionKit.findFlag(flag) || {};
7449
7702
  const missing = rt.missing || [];
7450
- return /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
7703
+ return /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(
7451
7704
  ComingSoon,
7452
7705
  {
7453
7706
  label: label || (variant === "inline" ? f.label || "Not wired yet" : "Designed \u2014 backend not wired yet"),
@@ -7468,25 +7721,25 @@ function FeatureGate({
7468
7721
  function PermissionHint({ perm, children }) {
7469
7722
  SessionKit.useSession();
7470
7723
  if (SessionKit.can(perm)) return children;
7471
- return /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
7724
+ return /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(
7472
7725
  "span",
7473
7726
  {
7474
7727
  title: "Requires " + (Array.isArray(perm) ? perm.join(", ") : perm),
7475
7728
  style: { display: "inline-flex", opacity: 0.45, cursor: "not-allowed" },
7476
7729
  "aria-disabled": "true",
7477
- 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 })
7478
7731
  }
7479
7732
  );
7480
7733
  }
7481
7734
 
7482
7735
  // src/components/platform/ModeSwitch.tsx
7483
- var React31 = __toESM(require("react"), 1);
7484
- var import_jsx_runtime59 = require("react/jsx-runtime");
7736
+ var React33 = __toESM(require("react"), 1);
7737
+ var import_jsx_runtime62 = require("react/jsx-runtime");
7485
7738
  function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog, onOpenSpec, summary }) {
7486
7739
  const mode2 = useRuntimeMode();
7487
- const [open, setOpen] = React31.useState(false);
7488
- const ref = React31.useRef(null);
7489
- React31.useEffect(() => {
7740
+ const [open, setOpen] = React33.useState(false);
7741
+ const ref = React33.useRef(null);
7742
+ React33.useEffect(() => {
7490
7743
  if (!open) return;
7491
7744
  const away = (e) => {
7492
7745
  if (ref.current && !ref.current.contains(e.target)) setOpen(false);
@@ -7508,8 +7761,8 @@ function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog
7508
7761
  RuntimeKit.setMode(next);
7509
7762
  setOpen(false);
7510
7763
  };
7511
- return /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("span", { style: { position: "relative", display: "inline-flex" }, ref, children: [
7512
- /* @__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)(
7513
7766
  "button",
7514
7767
  {
7515
7768
  type: "button",
@@ -7519,29 +7772,29 @@ function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog
7519
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.",
7520
7773
  className: "fd-mode-btn" + (test ? " is-test" : "") + (open ? " is-open" : ""),
7521
7774
  children: [
7522
- /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("i", { className: "ph " + (test ? "ph-flask" : "ph-lightning"), style: { fontSize: 17 } }),
7523
- 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
7524
7777
  ]
7525
7778
  }
7526
7779
  ),
7527
- open ? /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("span", { className: "fd-view-enter fd-mode-pop", children: [
7528
- /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("span", { className: "fd-row", style: { gap: 10, padding: "12px 14px", borderBottom: "1px solid var(--border)" }, children: [
7529
- /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("span", { className: "fd-badge " + (test ? "fd-badge-warning" : "fd-badge-neutral"), children: [
7530
- /* @__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" }),
7531
7784
  test ? "Test mode" : "Live mode"
7532
7785
  ] }),
7533
- 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: [
7534
7787
  requestCount,
7535
7788
  " simulated request",
7536
7789
  requestCount === 1 ? "" : "s"
7537
7790
  ] }) : null,
7538
- /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("span", { style: { flex: 1 } }),
7539
- 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
7540
7793
  ] }),
7541
- /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("span", { style: { display: "block", padding: "12px 14px", borderBottom: "1px solid var(--border)" }, children: [
7542
- /* @__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." }),
7543
- /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("span", { className: "fd-row", style: { gap: 8, marginTop: 10, flexWrap: "wrap" }, children: [
7544
- /* @__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: [
7545
7798
  s.endpointsWired,
7546
7799
  " endpoint",
7547
7800
  s.endpointsWired === 1 ? "" : "s",
@@ -7551,58 +7804,58 @@ function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog
7551
7804
  s.total,
7552
7805
  " features complete"
7553
7806
  ] }),
7554
- onOpenSpec ? /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)(import_jsx_runtime59.Fragment, { children: [
7555
- /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("span", { style: { flex: 1 } }),
7556
- /* @__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: () => {
7557
7810
  setOpen(false);
7558
7811
  onOpenSpec();
7559
7812
  }, children: [
7560
7813
  "API spec ",
7561
- /* @__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" })
7562
7815
  ] })
7563
7816
  ] }) : null
7564
7817
  ] })
7565
7818
  ] }),
7566
- /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("span", { className: "fd-mode-choice", children: [
7567
- /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("button", { type: "button", className: "fd-mode-opt" + (!test ? " is-on" : ""), onClick: () => go("live"), children: [
7568
- /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("i", { className: "ph ph-lightning", "aria-hidden": "true" }),
7569
- /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("span", { className: "fd-mode-opt-text", children: [
7570
- /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("span", { className: "fd-mode-opt-title", children: "Live mode" }),
7571
- /* @__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" })
7572
7825
  ] }),
7573
- !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
7574
7827
  ] }),
7575
- /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("button", { type: "button", className: "fd-mode-opt" + (test ? " is-on" : ""), onClick: () => go("test"), children: [
7576
- /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("i", { className: "ph ph-flask", "aria-hidden": "true" }),
7577
- /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("span", { className: "fd-mode-opt-text", children: [
7578
- /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("span", { className: "fd-mode-opt-title", children: "Test mode" }),
7579
- /* @__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" })
7580
7833
  ] }),
7581
- 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
7582
7835
  ] })
7583
7836
  ] }),
7584
- 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
7585
7838
  ] }) : null
7586
7839
  ] });
7587
7840
  }
7588
7841
  function TestModeBar({ onExit }) {
7589
7842
  const mode2 = useRuntimeMode();
7590
7843
  if (mode2 !== "test") return null;
7591
- return /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("div", { className: "fd-testbar", role: "status", children: [
7592
- /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("span", { className: "fd-badge fd-badge-warning", children: [
7593
- /* @__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" }),
7594
7847
  "Test mode"
7595
7848
  ] }),
7596
- /* @__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." }),
7597
- /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("button", { type: "button", className: "fd-soon-link", onClick: () => onExit ? onExit() : RuntimeKit.setMode("live"), children: [
7598
- /* @__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" }),
7599
7852
  " Back to live mode"
7600
7853
  ] })
7601
7854
  ] });
7602
7855
  }
7603
7856
 
7604
7857
  // src/components/planner/ChannelMeta.tsx
7605
- var import_jsx_runtime60 = require("react/jsx-runtime");
7858
+ var import_jsx_runtime63 = require("react/jsx-runtime");
7606
7859
  var CHANNEL_WEIGHTS = {
7607
7860
  "OOH": 50,
7608
7861
  "DOOH": 50,
@@ -7655,9 +7908,9 @@ function ChannelTag({ channel, size = "md", showLabel = true, dot = false, weigh
7655
7908
  const m = ChannelMeta(channel);
7656
7909
  const wt = channelWeightOf(channel || "");
7657
7910
  if (dot) {
7658
- 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 });
7659
7912
  }
7660
- return /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)(
7913
+ return /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)(
7661
7914
  "span",
7662
7915
  {
7663
7916
  className: ["fd-chan", size === "sm" ? "fd-chan-sm" : "", className].filter(Boolean).join(" "),
@@ -7665,16 +7918,16 @@ function ChannelTag({ channel, size = "md", showLabel = true, dot = false, weigh
7665
7918
  style: { "--chan": m.color },
7666
7919
  ...rest,
7667
7920
  children: [
7668
- /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("i", { className: "ph ph-" + m.icon, "aria-hidden": "true" }),
7669
- showLabel ? /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("span", { className: "fd-chan-label", children: m.label }) : null,
7670
- 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
7671
7924
  ]
7672
7925
  }
7673
7926
  );
7674
7927
  }
7675
7928
 
7676
7929
  // src/components/planner/SaturationDistribution.tsx
7677
- var import_jsx_runtime61 = require("react/jsx-runtime");
7930
+ var import_jsx_runtime64 = require("react/jsx-runtime");
7678
7931
  var BANDS2 = [
7679
7932
  { key: "weak", label: "Weak", n: 1, range: "< 50" },
7680
7933
  { key: "adequate", label: "Adequate", n: 2, range: "50\u2013100" },
@@ -7685,18 +7938,18 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
7685
7938
  const grouped = BANDS2.map((b) => ({ ...b, items: campuses.filter((c) => c.band === b.key) }));
7686
7939
  const tallest = Math.max(1, ...grouped.map((g) => g.items.length));
7687
7940
  const floor = BANDS2.find((b) => b.key === floorBand) || BANDS2[0];
7688
- return /* @__PURE__ */ (0, import_jsx_runtime61.jsxs)("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 16 }, children: [
7689
- /* @__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) => {
7690
7943
  const mark = "var(--csi-" + g.n + "-mark)";
7691
7944
  const active = selectedBand === g.key;
7692
- return /* @__PURE__ */ (0, import_jsx_runtime61.jsxs)(
7945
+ return /* @__PURE__ */ (0, import_jsx_runtime64.jsxs)(
7693
7946
  "button",
7694
7947
  {
7695
7948
  type: "button",
7696
7949
  onClick: onSelectBand ? () => onSelectBand(active ? null : g.key) : void 0,
7697
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)" },
7698
7951
  children: [
7699
- /* @__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)(
7700
7953
  "span",
7701
7954
  {
7702
7955
  title: c.name + " \xB7 " + c.crp,
@@ -7705,13 +7958,13 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
7705
7958
  },
7706
7959
  c.name
7707
7960
  )) }),
7708
- /* @__PURE__ */ (0, import_jsx_runtime61.jsxs)("span", { className: "fd-row", style: { gap: 8, alignItems: "baseline" }, children: [
7709
- /* @__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 }),
7710
- /* @__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)) })
7711
7964
  ] }),
7712
- /* @__PURE__ */ (0, import_jsx_runtime61.jsxs)("span", { className: "fd-stack", style: { gap: 1 }, children: [
7713
- /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("span", { className: "fd-label-lg", children: g.label }),
7714
- /* @__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: [
7715
7968
  "CRP ",
7716
7969
  g.range
7717
7970
  ] })
@@ -7721,10 +7974,10 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
7721
7974
  g.key
7722
7975
  );
7723
7976
  }) }),
7724
- 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: [
7725
- /* @__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)) }),
7726
- /* @__PURE__ */ (0, import_jsx_runtime61.jsxs)("span", { className: "fd-body-sm fd-secondary", style: { flex: 1, minWidth: 240 }, children: [
7727
- /* @__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: [
7728
7981
  "Plan floor ",
7729
7982
  floorScore
7730
7983
  ] }),
@@ -7735,21 +7988,21 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
7735
7988
  }
7736
7989
 
7737
7990
  // src/components/planner/MixGap.tsx
7738
- var React32 = __toESM(require("react"), 1);
7739
- var import_jsx_runtime62 = require("react/jsx-runtime");
7991
+ var React34 = __toESM(require("react"), 1);
7992
+ var import_jsx_runtime65 = require("react/jsx-runtime");
7740
7993
  function MixGap({ rows = [], loading = false, className = "" }) {
7741
7994
  const max = Math.max(1, ...rows.flatMap((r) => [r.target, r.realized]));
7742
- const [hover, setHover] = React32.useState(null);
7995
+ const [hover, setHover] = React34.useState(null);
7743
7996
  const toneOf = (gap) => gap >= -1 ? "ok" : gap >= -4 ? "warn" : "danger";
7744
7997
  const TONE = { ok: "var(--ok-solid)", warn: "var(--warn-solid)", danger: "var(--danger-solid)" };
7745
- return /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 4 }, children: [
7746
- /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("div", { className: "fd-row", style: { gap: 16, justifyContent: "flex-end", paddingBottom: 6, flexWrap: "wrap" }, children: [
7747
- [["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: [
7748
- /* @__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 } }),
7749
8002
  l
7750
8003
  ] }, l)),
7751
- /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("span", { className: "fd-row fd-body-sm fd-muted", style: { gap: 6 }, children: [
7752
- /* @__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)" } }),
7753
8006
  "Target"
7754
8007
  ] })
7755
8008
  ] }),
@@ -7757,7 +8010,7 @@ function MixGap({ rows = [], loading = false, className = "" }) {
7757
8010
  const gap = r.realized - r.target;
7758
8011
  const tone = toneOf(gap);
7759
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 : "");
7760
- return /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)(
8013
+ return /* @__PURE__ */ (0, import_jsx_runtime65.jsxs)(
7761
8014
  "div",
7762
8015
  {
7763
8016
  className: "fd-row",
@@ -7765,15 +8018,15 @@ function MixGap({ rows = [], loading = false, className = "" }) {
7765
8018
  onMouseEnter: () => setHover(r.channel),
7766
8019
  onMouseLeave: () => setHover(null),
7767
8020
  children: [
7768
- /* @__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" }) }),
7769
- /* @__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: [
7770
- /* @__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)" } }),
7771
- /* @__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 } }),
7772
- /* @__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: [
7773
8026
  r.realized,
7774
8027
  "%"
7775
8028
  ] }),
7776
- 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
7777
8030
  ] }) })
7778
8031
  ]
7779
8032
  },
@@ -7784,7 +8037,7 @@ function MixGap({ rows = [], loading = false, className = "" }) {
7784
8037
  }
7785
8038
 
7786
8039
  // src/components/planner/ChannelContribution.tsx
7787
- var import_jsx_runtime63 = require("react/jsx-runtime");
8040
+ var import_jsx_runtime66 = require("react/jsx-runtime");
7788
8041
  var money = (n) => "$" + Math.round(n).toLocaleString();
7789
8042
  function ChannelContribution({
7790
8043
  channels = [],
@@ -7800,9 +8053,9 @@ function ChannelContribution({
7800
8053
  const grand = total !== void 0 ? total : base + bonus;
7801
8054
  const pct = (v) => grand ? v / grand * 100 : 0;
7802
8055
  const spendTotal = channels.reduce((s, c) => s + Number(String(c.spend || 0).replace(/[^0-9.]/g, "")), 0);
7803
- return /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 16 }, children: [
7804
- 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: [
7805
- 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)(
7806
8059
  "span",
7807
8060
  {
7808
8061
  title: c.name + " \xB7 " + c.crp.toFixed(1) + " CRP",
@@ -7811,7 +8064,7 @@ function ChannelContribution({
7811
8064
  },
7812
8065
  c.name
7813
8066
  )),
7814
- bonus > 0 ? /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(
8067
+ bonus > 0 ? /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(
7815
8068
  "span",
7816
8069
  {
7817
8070
  title: "Surround-sound bonus +" + bonusPct + "%",
@@ -7820,18 +8073,18 @@ function ChannelContribution({
7820
8073
  }
7821
8074
  ) : null
7822
8075
  ] }),
7823
- showTable ? /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)("table", { className: "fd-table", style: { fontSize: "var(--body-sm-size)" }, children: [
7824
- /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)("tr", { children: [
7825
- /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("th", { style: { width: "34%" }, children: "Channel" }),
7826
- /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("th", { style: { width: "16%" }, children: "Weight" }),
7827
- /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("th", { className: "is-num", style: { width: "16%" }, children: "Spend" }),
7828
- /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("th", { className: "is-num", style: { width: "17%" }, children: "CRP" }),
7829
- /* @__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" })
7830
8083
  ] }) }),
7831
- /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)("tbody", { children: [
7832
- channels.map((c) => /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)("tr", { children: [
7833
- /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("td", { children: /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(ChannelTag, { channel: c.name, size: "sm" }) }),
7834
- /* @__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)(
7835
8088
  "span",
7836
8089
  {
7837
8090
  className: "fd-badge fd-badge-neutral",
@@ -7840,38 +8093,38 @@ function ChannelContribution({
7840
8093
  children: "weight " + (channelWeightOf(c.name) || 0)
7841
8094
  }
7842
8095
  ) }),
7843
- /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("td", { className: "is-num", children: c.spend }),
7844
- /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("td", { className: "is-num", children: c.crp.toFixed(1) }),
7845
- /* @__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: [
7846
8099
  pct(c.crp).toFixed(0),
7847
8100
  "%"
7848
8101
  ] })
7849
8102
  ] }, c.name)),
7850
- bonus > 0 ? /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)("tr", { children: [
7851
- /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("td", { children: /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)("span", { className: "fd-row", style: { gap: 9, fontWeight: 600 }, children: [
7852
- /* @__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" } }),
7853
8106
  "Surround-sound bonus"
7854
8107
  ] }) }),
7855
- /* @__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: [
7856
8109
  "+",
7857
8110
  bonusPct,
7858
8111
  "% of +",
7859
8112
  bonusMax,
7860
8113
  "%"
7861
8114
  ] }) }),
7862
- /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("td", { className: "is-num fd-muted", children: "\u2014" }),
7863
- /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("td", { className: "is-num", children: bonus.toFixed(1) }),
7864
- /* @__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: [
7865
8118
  pct(bonus).toFixed(0),
7866
8119
  "%"
7867
8120
  ] })
7868
8121
  ] }) : null,
7869
- /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)("tr", { style: { background: "var(--surface-2)" }, children: [
7870
- /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("td", { style: { fontWeight: 700 }, children: "Campus total" }),
7871
- /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("td", {}),
7872
- /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("td", { className: "is-num", style: { fontWeight: 700 }, children: money(spendTotal) }),
7873
- /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("td", { className: "is-num", style: { fontWeight: 700 }, children: grand.toFixed(1) }),
7874
- /* @__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%" })
7875
8128
  ] })
7876
8129
  ] })
7877
8130
  ] }) : null
@@ -7879,8 +8132,8 @@ function ChannelContribution({
7879
8132
  }
7880
8133
 
7881
8134
  // src/components/planner/BudgetReallocator.tsx
7882
- var React33 = __toESM(require("react"), 1);
7883
- var import_jsx_runtime64 = require("react/jsx-runtime");
8135
+ var React35 = __toESM(require("react"), 1);
8136
+ var import_jsx_runtime67 = require("react/jsx-runtime");
7884
8137
  var bandFor = (crp) => crp >= 200 ? "dominant" : crp >= 100 ? "strong" : crp >= 50 ? "adequate" : "weak";
7885
8138
  function BudgetReallocator({
7886
8139
  campus,
@@ -7895,8 +8148,8 @@ function BudgetReallocator({
7895
8148
  onCancel,
7896
8149
  className = ""
7897
8150
  }) {
7898
- const [draft, setDraft] = React33.useState(spend);
7899
- React33.useEffect(() => setDraft(spend), [spend]);
8151
+ const [draft, setDraft] = React35.useState(spend);
8152
+ React35.useEffect(() => setDraft(spend), [spend]);
7900
8153
  const dirty = draft !== spend;
7901
8154
  const nextCrp = scoreFor ? scoreFor(draft) : crp;
7902
8155
  const nextBand = bandFor(nextCrp);
@@ -7911,24 +8164,24 @@ function BudgetReallocator({
7911
8164
  setDraft(spend);
7912
8165
  if (onCancel) onCancel();
7913
8166
  };
7914
- return /* @__PURE__ */ (0, import_jsx_runtime64.jsxs)(
8167
+ return /* @__PURE__ */ (0, import_jsx_runtime67.jsxs)(
7915
8168
  "div",
7916
8169
  {
7917
8170
  className: ["fd-stack", className].filter(Boolean).join(" "),
7918
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)" },
7919
8172
  children: [
7920
- /* @__PURE__ */ (0, import_jsx_runtime64.jsxs)("div", { className: "fd-row", style: { gap: 12, flexWrap: "wrap" }, children: [
7921
- /* @__PURE__ */ (0, import_jsx_runtime64.jsx)("span", { className: "fd-h4", style: { flex: 1, minWidth: 140 }, children: campus }),
7922
- /* @__PURE__ */ (0, import_jsx_runtime64.jsx)(CsiBadge, { band: nowBand, crp: Number(crp.toFixed(1)), size: "medium" }),
7923
- dirty ? /* @__PURE__ */ (0, import_jsx_runtime64.jsxs)(import_jsx_runtime64.Fragment, { children: [
7924
- /* @__PURE__ */ (0, import_jsx_runtime64.jsx)("i", { className: "ph ph-arrow-right fd-muted", "aria-hidden": "true" }),
7925
- /* @__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 })
7926
8179
  ] }) : null
7927
8180
  ] }),
7928
- /* @__PURE__ */ (0, import_jsx_runtime64.jsxs)("div", { className: "fd-slider", children: [
7929
- /* @__PURE__ */ (0, import_jsx_runtime64.jsx)("span", { className: "fd-slider-fill", style: { width: pct + "%" } }),
7930
- 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,
7931
- /* @__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)(
7932
8185
  "input",
7933
8186
  {
7934
8187
  type: "range",
@@ -7944,13 +8197,13 @@ function BudgetReallocator({
7944
8197
  }
7945
8198
  )
7946
8199
  ] }),
7947
- /* @__PURE__ */ (0, import_jsx_runtime64.jsxs)("div", { className: "fd-row", style: { gap: 12, flexWrap: "wrap" }, children: [
7948
- /* @__PURE__ */ (0, import_jsx_runtime64.jsxs)("span", { className: "fd-stack", style: { gap: 2, flex: 1, minWidth: 150 }, children: [
7949
- /* @__PURE__ */ (0, import_jsx_runtime64.jsx)("span", { className: "fd-num", style: { fontSize: 19, fontWeight: 700 }, children: "$" + draft.toLocaleString() }),
7950
- /* @__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." })
7951
8204
  ] }),
7952
- /* @__PURE__ */ (0, import_jsx_runtime64.jsx)("button", { type: "button", className: "fd-btn fd-btn-ghost", disabled: !dirty, onClick: revert, children: "Cancel" }),
7953
- /* @__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)(
7954
8207
  "button",
7955
8208
  {
7956
8209
  type: "button",
@@ -7969,7 +8222,7 @@ function BudgetReallocator({
7969
8222
  }
7970
8223
 
7971
8224
  // src/components/planner/SurroundSound.tsx
7972
- var import_jsx_runtime65 = require("react/jsx-runtime");
8225
+ var import_jsx_runtime68 = require("react/jsx-runtime");
7973
8226
  var CATEGORIES = [
7974
8227
  { key: "ooh", label: "OOH", icon: "flag-banner", color: "var(--ch-ooh)" },
7975
8228
  { key: "transit", label: "Transit", icon: "bus", color: "var(--ch-transit)" },
@@ -7981,26 +8234,26 @@ var CATEGORIES = [
7981
8234
  function SurroundSound({ present = [], bonusPct = 0, bonusMax = 40, missedCost, className = "" }) {
7982
8235
  const earned = Math.max(0, Math.min(1, bonusPct / bonusMax));
7983
8236
  const single = present.length <= 2;
7984
- return /* @__PURE__ */ (0, import_jsx_runtime65.jsxs)("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 14 }, children: [
7985
- /* @__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) => {
7986
8239
  const on = present.includes(c.key);
7987
- return /* @__PURE__ */ (0, import_jsx_runtime65.jsxs)(
8240
+ return /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)(
7988
8241
  "span",
7989
8242
  {
7990
8243
  title: c.label + (on ? " \u2014 present" : " \u2014 not bought"),
7991
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)" },
7992
8245
  children: [
7993
- /* @__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" }),
7994
- /* @__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 })
7995
8248
  ]
7996
8249
  },
7997
8250
  c.key
7998
8251
  );
7999
8252
  }) }),
8000
- /* @__PURE__ */ (0, import_jsx_runtime65.jsxs)("div", { className: "fd-stack", style: { gap: 8 }, children: [
8001
- /* @__PURE__ */ (0, import_jsx_runtime65.jsxs)("div", { className: "fd-row", style: { justifyContent: "space-between", gap: 12 }, children: [
8002
- /* @__PURE__ */ (0, import_jsx_runtime65.jsx)("span", { className: "fd-label-lg", children: "Surround-sound bonus earned" }),
8003
- /* @__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: [
8004
8257
  "+",
8005
8258
  bonusPct,
8006
8259
  "% of +",
@@ -8008,8 +8261,8 @@ function SurroundSound({ present = [], bonusPct = 0, bonusMax = 40, missedCost,
8008
8261
  "%"
8009
8262
  ] })
8010
8263
  ] }),
8011
- /* @__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)" } }) }),
8012
- /* @__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: [
8013
8266
  present.length,
8014
8267
  " of 6 channel categories present.",
8015
8268
  " ",
@@ -8021,10 +8274,10 @@ function SurroundSound({ present = [], bonusPct = 0, bonusMax = 40, missedCost,
8021
8274
  }
8022
8275
 
8023
8276
  // src/components/chat/AgentChatPanel.tsx
8024
- var React39 = __toESM(require("react"), 1);
8277
+ var React41 = __toESM(require("react"), 1);
8025
8278
 
8026
8279
  // src/components/chat/chatEngine.ts
8027
- var React34 = __toESM(require("react"), 1);
8280
+ var React36 = __toESM(require("react"), 1);
8028
8281
  var CHAT_UNAVAILABLE = "chat_unavailable";
8029
8282
  var JOB_PENDING = ["queued", "running"];
8030
8283
  var JOB_SUCCESS = ["completed", "recovered"];
@@ -8078,22 +8331,22 @@ function useChatEngine(opts) {
8078
8331
  onClear,
8079
8332
  onFeedback
8080
8333
  } = opts || {};
8081
- const [status, setStatus] = React34.useState("idle");
8082
- const [threadId, setThreadId] = React34.useState(null);
8083
- const [messages, setMessages] = React34.useState([]);
8084
- const [queue, setQueue] = React34.useState([]);
8085
- const [fatal, setFatal] = React34.useState(null);
8086
- const [busy, setBusy] = React34.useState(false);
8087
- const [turnStartedAt, setTurnStartedAt] = React34.useState(null);
8088
- const listRef = React34.useRef([]);
8089
- const queueRef = React34.useRef([]);
8090
- const busyRef = React34.useRef(false);
8091
- const stoppedRef = React34.useRef(false);
8092
- const abortRef = React34.useRef(null);
8093
- const serverCount = React34.useRef(0);
8094
- const threadRef = React34.useRef(null);
8095
- const mounted = React34.useRef(true);
8096
- 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(() => {
8097
8350
  mounted.current = true;
8098
8351
  return () => {
8099
8352
  mounted.current = false;
@@ -8115,14 +8368,14 @@ function useChatEngine(opts) {
8115
8368
  }
8116
8369
  return false;
8117
8370
  };
8118
- const loadThread = React34.useCallback(async (id) => {
8371
+ const loadThread = React36.useCallback(async (id) => {
8119
8372
  const data = await apiAdapter.getThread(id);
8120
8373
  const list = [...data && data.messages || []];
8121
8374
  serverCount.current = list.length;
8122
8375
  commit(list);
8123
8376
  return list;
8124
8377
  }, [apiAdapter]);
8125
- React34.useEffect(() => {
8378
+ React36.useEffect(() => {
8126
8379
  if (!apiAdapter) {
8127
8380
  setStatus("idle");
8128
8381
  setFatal(null);
@@ -8335,7 +8588,7 @@ function useChatEngine(opts) {
8335
8588
  await dispatchTurn(turn);
8336
8589
  }
8337
8590
  }
8338
- const send = React34.useCallback((text, attachments) => {
8591
+ const send = React36.useCallback((text, attachments) => {
8339
8592
  const body = (text || "").trim();
8340
8593
  if (!body && !(attachments && attachments.length)) return;
8341
8594
  if (status === "disconnected") return;
@@ -8345,7 +8598,7 @@ function useChatEngine(opts) {
8345
8598
  stoppedRef.current = false;
8346
8599
  drain();
8347
8600
  }, [status]);
8348
- const stop = React34.useCallback(() => {
8601
+ const stop = React36.useCallback(() => {
8349
8602
  stoppedRef.current = true;
8350
8603
  const ac = abortRef.current;
8351
8604
  if (ac) {
@@ -8364,11 +8617,11 @@ function useChatEngine(opts) {
8364
8617
  store.del(STORAGE_PREFIX + threadRef.current);
8365
8618
  }
8366
8619
  }, [apiAdapter]);
8367
- const removeQueued = React34.useCallback((id) => {
8620
+ const removeQueued = React36.useCallback((id) => {
8368
8621
  queueRef.current = queueRef.current.filter((t) => t.id !== id);
8369
8622
  setQueue(queueRef.current.slice());
8370
8623
  }, []);
8371
- const retry = React34.useCallback(() => {
8624
+ const retry = React36.useCallback(() => {
8372
8625
  const list = listRef.current;
8373
8626
  let at = -1;
8374
8627
  for (let i = list.length - 1; i >= 0; i--) if (list[i].role === "user") {
@@ -8384,19 +8637,19 @@ function useChatEngine(opts) {
8384
8637
  setQueue(queueRef.current.slice());
8385
8638
  drain();
8386
8639
  }, []);
8387
- const clear = React34.useCallback(() => {
8640
+ const clear = React36.useCallback(() => {
8388
8641
  commit([]);
8389
8642
  serverCount.current = 0;
8390
8643
  queueRef.current = [];
8391
8644
  setQueue([]);
8392
8645
  onClear && onClear();
8393
8646
  }, [onClear]);
8394
- const setFeedback = React34.useCallback((id, value) => {
8647
+ const setFeedback = React36.useCallback((id, value) => {
8395
8648
  patch(id, (m) => ({ feedback: m.feedback === value ? null : value }));
8396
8649
  const msg = listRef.current.find((m) => m.id === id);
8397
8650
  onFeedback && onFeedback({ message: msg, feedback: msg ? msg.feedback : value });
8398
8651
  }, [onFeedback]);
8399
- const reload = React34.useCallback(async () => {
8652
+ const reload = React36.useCallback(async () => {
8400
8653
  if (!threadRef.current) return;
8401
8654
  setStatus("loading");
8402
8655
  try {
@@ -8434,11 +8687,11 @@ var ChatKit = {
8434
8687
  };
8435
8688
 
8436
8689
  // src/components/chat/ChatTranscript.tsx
8437
- var React36 = __toESM(require("react"), 1);
8690
+ var React38 = __toESM(require("react"), 1);
8438
8691
 
8439
8692
  // src/components/chat/ChatTurn.tsx
8440
- var React35 = __toESM(require("react"), 1);
8441
- var import_jsx_runtime66 = require("react/jsx-runtime");
8693
+ var React37 = __toESM(require("react"), 1);
8694
+ var import_jsx_runtime69 = require("react/jsx-runtime");
8442
8695
  function JsonView({ value }) {
8443
8696
  let text;
8444
8697
  try {
@@ -8446,67 +8699,67 @@ function JsonView({ value }) {
8446
8699
  } catch (e) {
8447
8700
  text = String(value);
8448
8701
  }
8449
- 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 });
8450
8703
  }
8451
8704
  function PacketCard({ packet, schema, render, onApply, applied }) {
8452
8705
  if (!packet) return null;
8453
8706
  const s = schema || {};
8454
8707
  const invalid = packet.valid === false;
8455
8708
  const title = s.heading || packet.type;
8456
- return /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("section", { className: "fdc-packet" + (invalid ? " is-invalid" : ""), "aria-label": title, children: [
8457
- /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("header", { className: "fdc-packet-head", children: [
8458
- /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("i", { className: "ph ph-" + (s.icon || "package"), "aria-hidden": "true" }),
8459
- /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("span", { className: "fdc-packet-title", children: title }),
8460
- packet.repaired ? /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("span", { className: "fdc-packet-badge", children: "Repaired" }) : null,
8461
- 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
8462
8715
  ] }),
8463
- invalid ? /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("div", { className: "fdc-packet-alert", role: "alert", children: [
8464
- /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
8465
- /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("span", { children: packet.error || "This result failed validation and can\u2019t be applied." })
8466
- ] }) : /* @__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 }) }),
8467
- !invalid && onApply ? /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("footer", { className: "fdc-packet-foot", children: [
8468
- 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", {}),
8469
- /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("button", { type: "button", className: "fd-btn fd-btn-primary fd-btn-sm", disabled: applied, onClick: () => onApply(packet), children: [
8470
- /* @__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" }),
8471
8724
  applied ? "Applied" : s.applyLabel || "Apply"
8472
8725
  ] })
8473
8726
  ] }) : null
8474
8727
  ] });
8475
8728
  }
8476
8729
  function ThinkingBlock({ text, durationMs, streaming, defaultOpen = false }) {
8477
- const [open, setOpen] = React35.useState(defaultOpen);
8730
+ const [open, setOpen] = React37.useState(defaultOpen);
8478
8731
  if (!text) return null;
8479
- return /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("div", { className: "fdc-think" + (open ? " is-open" : ""), children: [
8480
- /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("button", { type: "button", className: "fdc-think-head", onClick: () => setOpen((v) => !v), "aria-expanded": open, children: [
8481
- /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("i", { className: "ph ph-brain", "aria-hidden": "true" }),
8482
- /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("span", { children: streaming ? "Thinking" : durationMs ? "Thought for " + formatDuration(durationMs) : "Thought process" }),
8483
- streaming ? /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("span", { className: "fdc-dots", "aria-hidden": "true", children: [
8484
- /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("span", {}),
8485
- /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("span", {}),
8486
- /* @__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", {})
8487
8740
  ] }) : null,
8488
- /* @__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" })
8489
8742
  ] }),
8490
- 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
8491
8744
  ] });
8492
8745
  }
8493
8746
  function Citations({ items = [], onOpen }) {
8494
- const [open, setOpen] = React35.useState(false);
8747
+ const [open, setOpen] = React37.useState(false);
8495
8748
  if (!items.length) return null;
8496
- return /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("div", { className: "fdc-cites", children: [
8497
- /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("button", { type: "button", className: "fdc-cites-head", onClick: () => setOpen((v) => !v), "aria-expanded": open, children: [
8498
- /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("i", { className: "ph ph-quotes", "aria-hidden": "true" }),
8499
- /* @__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: [
8500
8753
  items.length,
8501
8754
  " source",
8502
8755
  items.length === 1 ? "" : "s"
8503
8756
  ] }),
8504
- /* @__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" })
8505
8758
  ] }),
8506
- 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: [
8507
- /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("span", { className: "fdc-cite-n fd-tabular", children: c.marker || i + 1 }),
8508
- 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" }),
8509
- 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
8510
8763
  ] }, c.id || i)) }) : null
8511
8764
  ] });
8512
8765
  }
@@ -8517,29 +8770,29 @@ function clampText(text, max) {
8517
8770
  return (at > max * 0.6 ? cut.slice(0, at) : cut).trimEnd() + "\u2026";
8518
8771
  }
8519
8772
  function MessageBody({ message: m, ctx }) {
8520
- const [expanded, setExpanded] = React35.useState(false);
8773
+ const [expanded, setExpanded] = React37.useState(false);
8521
8774
  const isUser = m.role === "user";
8522
8775
  const raw = m.text || "";
8523
8776
  const clamped = !expanded && !m.streaming ? clampText(raw, ctx.maxVisibleChars) : null;
8524
8777
  const body = clamped != null ? clamped : raw;
8525
8778
  const showMd = ctx.markdown && !isUser;
8526
- return /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("div", { className: "fdc-body", children: [
8527
- m.thinking && ctx.showThinking ? /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(ThinkingBlock, { text: m.thinking, durationMs: m.thinkingMs, streaming: m.streaming && !m.text }) : null,
8528
- 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,
8529
- body ? /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("div", { className: "fdc-text" + (isUser ? " is-user" : ""), children: [
8530
- 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 }),
8531
- 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
8532
8785
  ] }) : null,
8533
- clamped != null ? /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("button", { type: "button", className: "fdc-more", onClick: () => setExpanded(true), children: [
8534
- /* @__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" }),
8535
8788
  "Show more",
8536
- /* @__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" })
8537
- ] }) : expanded && ctx.maxVisibleChars && raw.length > ctx.maxVisibleChars ? /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("button", { type: "button", className: "fdc-more", onClick: () => setExpanded(false), children: [
8538
- /* @__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" }),
8539
8792
  "Show less"
8540
8793
  ] }) : null,
8541
- 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,
8542
- 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)(
8543
8796
  PacketCard,
8544
8797
  {
8545
8798
  packet: m.packet,
@@ -8549,44 +8802,44 @@ function MessageBody({ message: m, ctx }) {
8549
8802
  applied: ctx.appliedPackets && ctx.appliedPackets[m.id]
8550
8803
  }
8551
8804
  ) : null,
8552
- m.citations && m.citations.length ? /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(Citations, { items: m.citations, onOpen: ctx.onOpenCitation }) : null,
8553
- m.working ? /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("div", { className: "fdc-working", role: "status", children: [
8554
- /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("span", { className: "fdc-dots", "aria-hidden": "true", children: [
8555
- /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("span", {}),
8556
- /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("span", {}),
8557
- /* @__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", {})
8558
8811
  ] }),
8559
- /* @__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: [
8560
8813
  m.resumed ? "Resuming" : "Working",
8561
- 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: [
8562
8815
  " \xB7 ",
8563
8816
  m.job.status
8564
8817
  ] }) : null,
8565
- 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: [
8566
8819
  " \xB7 ",
8567
8820
  m.job.detail
8568
8821
  ] }) : null
8569
8822
  ] }),
8570
- 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
8571
8824
  ] }) : null,
8572
- m.stopped ? /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("div", { className: "fdc-stopped", children: [
8573
- /* @__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" }),
8574
8827
  "Stopped"
8575
8828
  ] }) : null,
8576
- m.error ? /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("div", { className: "fdc-error", role: "alert", children: [
8577
- /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
8578
- /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("span", { className: "fdc-error-text", children: ctx.errorCopy ? ctx.errorCopy(m.error) : m.error }),
8579
- m.retryable && ctx.onRetry ? /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("button", { type: "button", className: "fdc-error-retry", onClick: ctx.onRetry, children: [
8580
- /* @__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" }),
8581
8834
  "Retry"
8582
8835
  ] }) : null
8583
8836
  ] }) : null
8584
8837
  ] });
8585
8838
  }
8586
8839
  function useCopyRun() {
8587
- const [done, setDone] = React35.useState(false);
8588
- const t = React35.useRef(null);
8589
- React35.useEffect(() => () => {
8840
+ const [done, setDone] = React37.useState(false);
8841
+ const t = React37.useRef(null);
8842
+ React37.useEffect(() => () => {
8590
8843
  if (t.current) clearTimeout(t.current);
8591
8844
  }, []);
8592
8845
  return [done, (text) => {
@@ -8606,16 +8859,16 @@ function RunActions({ group, ctx }) {
8606
8859
  const isAssistant = group.role === "assistant";
8607
8860
  const fb = last.feedback;
8608
8861
  if (!ctx.messageActions) return null;
8609
- return /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("div", { className: "fdc-actions", role: "group", "aria-label": "Message actions", children: [
8610
- /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("button", { type: "button", className: "fdc-act" + (copied ? " is-done" : ""), onClick: () => copy(markdownToText(text)), "aria-label": "Copy message", children: [
8611
- /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("i", { className: "ph ph-" + (copied ? "check" : "copy"), "aria-hidden": "true" }),
8612
- /* @__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" })
8613
8866
  ] }),
8614
- 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,
8615
- 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,
8616
- isAssistant && ctx.onFeedback ? /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)(React35.Fragment, { children: [
8617
- /* @__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" }) }),
8618
- /* @__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" }) })
8619
8872
  ] }) : null,
8620
8873
  ctx.extraActions ? ctx.extraActions(group) : null
8621
8874
  ] });
@@ -8625,22 +8878,22 @@ function ChatTurn({ group, ctx }) {
8625
8878
  const name = isUser ? ctx.userName : group.author || ctx.assistantName;
8626
8879
  const avatar = isUser ? ctx.userAvatar : ctx.assistantAvatar;
8627
8880
  const stamp = group.messages[0].timestamp;
8628
- return /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("article", { className: "fdc-turn is-" + group.role, "aria-label": String(name) + (stamp ? " at " + formatClock(stamp) : ""), children: [
8629
- /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("div", { className: "fdc-turn-head", children: [
8630
- 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,
8631
- /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("span", { className: "fdc-who", children: name }),
8632
- stamp ? /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(RelativeTime, { className: "fdc-when", value: stamp }) : null,
8633
- 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
8634
8887
  ] }),
8635
- /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("div", { className: "fdc-turn-body", children: [
8636
- 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)),
8637
- /* @__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 })
8638
8891
  ] })
8639
8892
  ] });
8640
8893
  }
8641
8894
 
8642
8895
  // src/components/chat/ChatTranscript.tsx
8643
- var import_jsx_runtime67 = require("react/jsx-runtime");
8896
+ var import_jsx_runtime70 = require("react/jsx-runtime");
8644
8897
  var GROUP_WINDOW = 6e4;
8645
8898
  var STICK_PX = 100;
8646
8899
  function groupMessages(list) {
@@ -8673,25 +8926,25 @@ function dayLabel(key) {
8673
8926
  }
8674
8927
  function Suggestions({ items = [], onPick }) {
8675
8928
  if (!items.length) return null;
8676
- 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) => {
8677
8930
  const it = typeof s === "string" ? { label: s, text: s } : s;
8678
- return /* @__PURE__ */ (0, import_jsx_runtime67.jsxs)("button", { type: "button", className: "fdc-suggest-item", onClick: () => onPick && onPick(it.text || it.label), children: [
8679
- it.icon ? /* @__PURE__ */ (0, import_jsx_runtime67.jsx)("i", { className: "ph ph-" + it.icon, "aria-hidden": "true" }) : null,
8680
- /* @__PURE__ */ (0, import_jsx_runtime67.jsxs)("span", { className: "fdc-suggest-text", children: [
8681
- /* @__PURE__ */ (0, import_jsx_runtime67.jsx)("span", { className: "fdc-suggest-label", children: it.label }),
8682
- 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
8683
8936
  ] }),
8684
- /* @__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" })
8685
8938
  ] }, it.id || i);
8686
8939
  }) });
8687
8940
  }
8688
8941
  function LoadingTurns() {
8689
- 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: [
8690
- /* @__PURE__ */ (0, import_jsx_runtime67.jsx)("div", { className: "fd-skel fd-skel-circle", style: { width: 22, height: 22 } }),
8691
- /* @__PURE__ */ (0, import_jsx_runtime67.jsxs)("div", { className: "fdc-skel-lines", children: [
8692
- /* @__PURE__ */ (0, import_jsx_runtime67.jsx)("div", { className: "fd-skel", style: { width: i ? "62%" : "44%", height: 11 } }),
8693
- /* @__PURE__ */ (0, import_jsx_runtime67.jsx)("div", { className: "fd-skel", style: { width: i ? "94%" : "78%", height: 11 } }),
8694
- /* @__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 } })
8695
8948
  ] })
8696
8949
  ] }, i)) });
8697
8950
  }
@@ -8708,10 +8961,10 @@ function ChatTranscript({
8708
8961
  renderEmpty,
8709
8962
  className = ""
8710
8963
  }) {
8711
- const scroller = React36.useRef(null);
8712
- const stick = React36.useRef(true);
8713
- const [pill, setPill] = React36.useState(0);
8714
- 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);
8715
8968
  const toBottom = (smooth) => {
8716
8969
  const el = scroller.current;
8717
8970
  if (!el) return;
@@ -8730,7 +8983,7 @@ function ChatTranscript({
8730
8983
  seen.current = messages.length;
8731
8984
  }
8732
8985
  };
8733
- React36.useLayoutEffect(() => {
8986
+ React38.useLayoutEffect(() => {
8734
8987
  const el = scroller.current;
8735
8988
  if (!el) return;
8736
8989
  if (stick.current) {
@@ -8738,7 +8991,7 @@ function ChatTranscript({
8738
8991
  seen.current = messages.length;
8739
8992
  } else setPill(Math.max(0, messages.length - seen.current));
8740
8993
  }, [messages]);
8741
- React36.useEffect(() => {
8994
+ React38.useEffect(() => {
8742
8995
  const el = scroller.current;
8743
8996
  const inner = el && el.firstChild;
8744
8997
  if (!el || !inner || typeof ResizeObserver === "undefined") return;
@@ -8748,38 +9001,38 @@ function ChatTranscript({
8748
9001
  ro.observe(inner);
8749
9002
  return () => ro.disconnect();
8750
9003
  }, []);
8751
- const groups = React36.useMemo(() => groupMessages(messages), [messages]);
9004
+ const groups = React38.useMemo(() => groupMessages(messages), [messages]);
8752
9005
  const empty = !messages.length && status === "ready";
8753
- return /* @__PURE__ */ (0, import_jsx_runtime67.jsxs)("div", { className: ["fdc-scroll", className].filter(Boolean).join(" "), ref: scroller, onScroll, children: [
8754
- /* @__PURE__ */ (0, import_jsx_runtime67.jsxs)("div", { className: "fdc-log", role: "log", "aria-label": "Conversation", children: [
8755
- status === "loading" || status === "resolving" ? /* @__PURE__ */ (0, import_jsx_runtime67.jsx)(LoadingTurns, {}) : null,
8756
- status === "disconnected" ? /* @__PURE__ */ (0, import_jsx_runtime67.jsxs)("div", { className: "fdc-dead", children: [
8757
- /* @__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" }) }),
8758
- /* @__PURE__ */ (0, import_jsx_runtime67.jsx)("h3", { className: "fdc-dead-title", children: ctx.deadTitle || "The assistant isn\u2019t reachable" }),
8759
- /* @__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." }),
8760
- ctx.onReconnect ? /* @__PURE__ */ (0, import_jsx_runtime67.jsxs)("button", { type: "button", className: "fd-btn fd-btn-secondary fd-btn-sm", onClick: ctx.onReconnect, children: [
8761
- /* @__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" }),
8762
9015
  "Try again"
8763
9016
  ] }) : null
8764
9017
  ] }) : null,
8765
- empty ? renderEmpty ? renderEmpty() : /* @__PURE__ */ (0, import_jsx_runtime67.jsxs)("div", { className: "fdc-empty", children: [
8766
- /* @__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" }) }),
8767
- /* @__PURE__ */ (0, import_jsx_runtime67.jsx)("h3", { className: "fdc-empty-title", children: emptyTitle }),
8768
- emptyDescription ? /* @__PURE__ */ (0, import_jsx_runtime67.jsx)("p", { className: "fdc-empty-body", children: emptyDescription }) : null,
8769
- /* @__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 })
8770
9023
  ] }) : null,
8771
9024
  groups.map((g, i) => {
8772
9025
  const prev = groups[i - 1];
8773
9026
  const k = dayKey(g.messages[0].timestamp);
8774
9027
  const showDay = !!k && (!prev || dayKey(prev.messages[0].timestamp) !== k);
8775
- return /* @__PURE__ */ (0, import_jsx_runtime67.jsxs)(React36.Fragment, { children: [
8776
- showDay ? /* @__PURE__ */ (0, import_jsx_runtime67.jsx)("div", { className: "fdc-day", children: /* @__PURE__ */ (0, import_jsx_runtime67.jsx)("span", { children: dayLabel(k) }) }) : null,
8777
- /* @__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 })
8778
9031
  ] }, g.key || i);
8779
9032
  })
8780
9033
  ] }),
8781
- pill ? /* @__PURE__ */ (0, import_jsx_runtime67.jsxs)("button", { type: "button", className: "fdc-pill", onClick: () => toBottom(true), children: [
8782
- /* @__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" }),
8783
9036
  pill,
8784
9037
  " new message",
8785
9038
  pill === 1 ? "" : "s"
@@ -8789,8 +9042,8 @@ function ChatTranscript({
8789
9042
  var TranscriptKit = { groupMessages };
8790
9043
 
8791
9044
  // src/components/chat/ChatComposer.tsx
8792
- var React37 = __toESM(require("react"), 1);
8793
- var import_jsx_runtime68 = require("react/jsx-runtime");
9045
+ var React39 = __toESM(require("react"), 1);
9046
+ var import_jsx_runtime71 = require("react/jsx-runtime");
8794
9047
  function ChatComposer({
8795
9048
  onSubmit,
8796
9049
  onStop,
@@ -8817,17 +9070,17 @@ function ChatComposer({
8817
9070
  onReject,
8818
9071
  onOpenAttachment
8819
9072
  }) {
8820
- const [text, setText] = React37.useState(draft || "");
8821
- const [trigger, setTrigger] = React37.useState(null);
8822
- const [mentionItems, setMentionItems] = React37.useState([]);
8823
- const [listening, setListening] = React37.useState(false);
8824
- const [notice, setNotice] = React37.useState(null);
8825
- const editor = React37.useRef(null);
8826
- const wrap = React37.useRef(null);
8827
- 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);
8828
9081
  const staged = useStagedFiles(fileUploadHandler, { onError: () => {
8829
9082
  } });
8830
- React37.useEffect(() => {
9083
+ React39.useEffect(() => {
8831
9084
  if (draft != null && draft !== text) setText(draft);
8832
9085
  }, [draft]);
8833
9086
  const change = (v) => {
@@ -8861,7 +9114,7 @@ function ChatComposer({
8861
9114
  e.preventDefault();
8862
9115
  staged.add(found.files);
8863
9116
  };
8864
- React37.useEffect(() => {
9117
+ React39.useEffect(() => {
8865
9118
  if (!trigger || trigger.type !== "mention" || !mentionSources) {
8866
9119
  setMentionItems([]);
8867
9120
  return;
@@ -8879,7 +9132,7 @@ function ChatComposer({
8879
9132
  const q = (trigger.query || "").toLowerCase();
8880
9133
  setMentionItems(mentionSources.filter((m) => !q || (m.label + " " + (m.description || "")).toLowerCase().includes(q)));
8881
9134
  }, [trigger, mentionSources]);
8882
- const slashItems = React37.useMemo(() => {
9135
+ const slashItems = React39.useMemo(() => {
8883
9136
  if (!trigger || trigger.type !== "slash" || !slashCommands) return [];
8884
9137
  const q = (trigger.query || "").toLowerCase();
8885
9138
  return slashCommands.filter((c) => !q || (c.id + " " + c.label + " " + (c.description || "")).toLowerCase().includes(q));
@@ -8893,7 +9146,7 @@ function ChatComposer({
8893
9146
  description: it.description,
8894
9147
  icon: it.icon,
8895
9148
  meta: mention.meta,
8896
- 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,
8897
9150
  onSelect: () => {
8898
9151
  const insert = trigger.type === "slash" ? slash.immediate ? "/" + slash.id : "/" + slash.id + " " : "@" + (mention.value || mention.label) + " ";
8899
9152
  editor.current && editor.current.replaceRange(trigger.from, trigger.to, insert);
@@ -8956,14 +9209,14 @@ function ChatComposer({
8956
9209
  stopVoice.current = typeof res === "function" ? res : () => {
8957
9210
  };
8958
9211
  };
8959
- return /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)("div", { className: "fdc-composer" + (disabled ? " is-disabled" : "") + (narrow ? " is-narrow" : ""), children: [
8960
- 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: [
8961
- /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("i", { className: "ph ph-clock-countdown", "aria-hidden": "true" }),
8962
- /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("span", { className: "fdc-queue-text", children: q.text || (q.attachments ? q.attachments.length + " file(s)" : "") }),
8963
- 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
8964
9217
  ] }, q.id)) }) : null,
8965
9218
  sessionBar,
8966
- /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(
9219
+ /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
8967
9220
  Dropzone,
8968
9221
  {
8969
9222
  className: "fdc-field",
@@ -8977,9 +9230,9 @@ function ChatComposer({
8977
9230
  disabled: !fileUploadHandler || disabled,
8978
9231
  label: "Drop to attach",
8979
9232
  hint: acceptFiles ? acceptFiles.replace(/,/g, " \xB7 ") : void 0,
8980
- children: /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)("div", { ref: wrap, className: "fdc-field-inner", children: [
8981
- 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,
8982
- /* @__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)(
8983
9236
  MarkdownEditor,
8984
9237
  {
8985
9238
  ref: editor,
@@ -8998,33 +9251,33 @@ function ChatComposer({
8998
9251
  ariaLabel: "Message"
8999
9252
  }
9000
9253
  ),
9001
- /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)("div", { className: "fdc-tools", children: [
9002
- 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,
9003
- 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,
9004
9257
  toolbarExtras,
9005
- /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("span", { className: "fdc-tools-gap" }),
9006
- 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: [
9007
9260
  text.length,
9008
9261
  "/",
9009
9262
  maxLength
9010
9263
  ] }) : null,
9011
- busy ? /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)("button", { type: "button", className: "fdc-stop", onClick: onStop, "aria-label": "Stop generating", children: [
9012
- /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("i", { className: "ph ph-stop-circle", "aria-hidden": "true" }),
9013
- /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("span", { children: "Stop" })
9014
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)("button", { type: "button", className: "fdc-send", onClick: submit, disabled: !canSend, "aria-label": "Send message", children: [
9015
- /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("i", { className: "ph ph-paper-plane-right", "aria-hidden": "true" }),
9016
- /* @__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" })
9017
9270
  ] })
9018
9271
  ] })
9019
9272
  ] })
9020
9273
  }
9021
9274
  ),
9022
- notice ? /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)("div", { className: "fdc-notice", role: "status", children: [
9023
- /* @__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" }),
9024
9277
  notice
9025
9278
  ] }) : null,
9026
- hint && !notice ? /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("div", { className: "fdc-hint", children: hint }) : null,
9027
- /* @__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)(
9028
9281
  Popover,
9029
9282
  {
9030
9283
  open: menuOpen,
@@ -9038,12 +9291,12 @@ function ChatComposer({
9038
9291
  returnFocus: false,
9039
9292
  closeOnOutside: true,
9040
9293
  label: trigger && trigger.type === "slash" ? "Commands" : "Mentions",
9041
- children: /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(
9294
+ children: /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
9042
9295
  Menu,
9043
9296
  {
9044
9297
  items: menuItems,
9045
9298
  autoFocus: false,
9046
- 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" }),
9047
9300
  onClose: () => setTrigger(null)
9048
9301
  }
9049
9302
  )
@@ -9053,12 +9306,12 @@ function ChatComposer({
9053
9306
  }
9054
9307
 
9055
9308
  // src/components/chat/ChatSessionBar.tsx
9056
- var React38 = __toESM(require("react"), 1);
9057
- var import_jsx_runtime69 = require("react/jsx-runtime");
9309
+ var React40 = __toESM(require("react"), 1);
9310
+ var import_jsx_runtime72 = require("react/jsx-runtime");
9058
9311
  var compact2 = meterFormats.compact;
9059
9312
  function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extras }) {
9060
- const [open, setOpen] = React38.useState(false);
9061
- const anchor = React38.useRef(null);
9313
+ const [open, setOpen] = React40.useState(false);
9314
+ const anchor = React40.useRef(null);
9062
9315
  const stats = sessionStats || null;
9063
9316
  const cu = contextUsage || null;
9064
9317
  const limits = usageLimits || null;
@@ -9073,9 +9326,9 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
9073
9326
  if (stats && stats.runningTasks) bits.push(stats.runningTasks + " running task" + (stats.runningTasks === 1 ? "" : "s"));
9074
9327
  if (cu) bits.push(pct + "% context");
9075
9328
  const expandable = !!(cu || limits);
9076
- return /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)(React38.Fragment, { children: [
9077
- /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("div", { className: "fdc-bar", children: [
9078
- /* @__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)(
9079
9332
  "button",
9080
9333
  {
9081
9334
  type: "button",
@@ -9086,16 +9339,16 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
9086
9339
  "aria-expanded": expandable ? open : void 0,
9087
9340
  "aria-label": expandable ? "Usage details" : void 0,
9088
9341
  children: [
9089
- 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,
9090
- /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("span", { className: "fdc-bar-text", children: bits.join(" \xB7 ") }),
9091
- 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
9092
9345
  ]
9093
9346
  }
9094
9347
  ),
9095
9348
  extras
9096
9349
  ] }),
9097
- /* @__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: [
9098
- 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)(
9099
9352
  SegmentedMeter,
9100
9353
  {
9101
9354
  total,
@@ -9107,9 +9360,9 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
9107
9360
  remainderLabel: "Free"
9108
9361
  }
9109
9362
  ) }) : null,
9110
- limits && limits.length ? /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("section", { className: "fdc-usage-sec", children: [
9111
- /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("h4", { className: "fdc-usage-h", children: "Usage limits" }),
9112
- /* @__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)(
9113
9366
  QuotaRow,
9114
9367
  {
9115
9368
  label: l.label,
@@ -9119,32 +9372,32 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
9119
9372
  l.id
9120
9373
  )) })
9121
9374
  ] }) : null,
9122
- stats ? /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("section", { className: "fdc-usage-sec fdc-usage-stats", children: [
9123
- stats.elapsedMs ? /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("div", { children: [
9124
- /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("span", { children: "Session" }),
9125
- /* @__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) })
9126
9379
  ] }) : null,
9127
- stats.tokens ? /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("div", { children: [
9128
- /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("span", { children: "Tokens" }),
9129
- /* @__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() })
9130
9383
  ] }) : null,
9131
- stats.costUsd != null ? /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("div", { children: [
9132
- /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("span", { children: "Cost" }),
9133
- /* @__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: [
9134
9387
  "$",
9135
9388
  Number(stats.costUsd).toFixed(3)
9136
9389
  ] })
9137
9390
  ] }) : null,
9138
- stats.turns ? /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("div", { children: [
9139
- /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("span", { children: "Turns" }),
9140
- /* @__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 })
9141
9394
  ] }) : null
9142
9395
  ] }) : null,
9143
- 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: () => {
9144
9397
  setOpen(false);
9145
9398
  onClear();
9146
9399
  }, children: [
9147
- /* @__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" }),
9148
9401
  "Clear conversation"
9149
9402
  ] }) }) : null
9150
9403
  ] }) })
@@ -9181,7 +9434,7 @@ function ModelControls({
9181
9434
  disabled: m.disabled,
9182
9435
  checked: m.id === (current2 && current2.id),
9183
9436
  meta: m.meta,
9184
- 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,
9185
9438
  onSelect: () => onModelChange && onModelChange(m.id)
9186
9439
  });
9187
9440
  const items = [{ kind: "section", label: "Models" }].concat(flat.map(item));
@@ -9194,15 +9447,15 @@ function ModelControls({
9194
9447
  items.push({ kind: "section", label: "Fast mode" });
9195
9448
  items.push({
9196
9449
  kind: "custom",
9197
- render: () => /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("label", { className: "fdc-switchrow", children: [
9198
- /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("span", { children: fastModeLabel }),
9199
- /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("input", { type: "checkbox", className: "fd-sr", checked: !!fastMode, onChange: (e) => onFastModeChange(e.target.checked) }),
9200
- /* @__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" }) })
9201
9454
  ] })
9202
9455
  });
9203
9456
  }
9204
- return /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)(React38.Fragment, { children: [
9205
- /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(
9457
+ return /* @__PURE__ */ (0, import_jsx_runtime72.jsxs)(React40.Fragment, { children: [
9458
+ /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
9206
9459
  MenuButton,
9207
9460
  {
9208
9461
  items,
@@ -9213,7 +9466,7 @@ function ModelControls({
9213
9466
  title: "Choose a model"
9214
9467
  }
9215
9468
  ),
9216
- effortLevels && effortLevels.length ? /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(
9469
+ effortLevels && effortLevels.length ? /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
9217
9470
  MenuButton,
9218
9471
  {
9219
9472
  placement: "top-end",
@@ -9234,7 +9487,7 @@ function ModelControls({
9234
9487
  }
9235
9488
 
9236
9489
  // src/components/chat/AgentChatPanel.tsx
9237
- var import_jsx_runtime70 = require("react/jsx-runtime");
9490
+ var import_jsx_runtime73 = require("react/jsx-runtime");
9238
9491
  var SURFACES = { sidebar: "is-sidebar", inline: "is-inline", page: "is-page", modal: "is-modal", sheet: "is-sheet" };
9239
9492
  function AgentChatPanel({
9240
9493
  /* required */
@@ -9318,11 +9571,11 @@ function AgentChatPanel({
9318
9571
  onFeedback,
9319
9572
  onEditMessage
9320
9573
  }) {
9321
- const [panelWidth, setPanelWidth] = React39.useState(width);
9322
- const [applied, setApplied] = React39.useState({});
9323
- const [draft, setDraft] = React39.useState("");
9324
- const dragging = React39.useRef(null);
9325
- 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]);
9326
9579
  const engine = useChatEngine({
9327
9580
  contextType,
9328
9581
  contextId,
@@ -9388,7 +9641,7 @@ function AgentChatPanel({
9388
9641
  onReconnect: engine.reload,
9389
9642
  deadTitle: "The assistant isn\u2019t reachable"
9390
9643
  };
9391
- const sessionBar = /* @__PURE__ */ (0, import_jsx_runtime70.jsx)(
9644
+ const sessionBar = /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(
9392
9645
  ChatSessionBar,
9393
9646
  {
9394
9647
  sessionStats,
@@ -9397,7 +9650,7 @@ function AgentChatPanel({
9397
9650
  onClear: engine.visible.length ? engine.clear : void 0
9398
9651
  }
9399
9652
  );
9400
- const modelControls = /* @__PURE__ */ (0, import_jsx_runtime70.jsx)(
9653
+ const modelControls = /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(
9401
9654
  ModelControls,
9402
9655
  {
9403
9656
  models,
@@ -9412,7 +9665,7 @@ function AgentChatPanel({
9412
9665
  narrow
9413
9666
  }
9414
9667
  );
9415
- const threadMenu = threads && threads.length ? /* @__PURE__ */ (0, import_jsx_runtime70.jsx)(
9668
+ const threadMenu = threads && threads.length ? /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(
9416
9669
  MenuButton,
9417
9670
  {
9418
9671
  variant: "ghost",
@@ -9439,7 +9692,7 @@ function AgentChatPanel({
9439
9692
  })))
9440
9693
  }
9441
9694
  ) : null;
9442
- return /* @__PURE__ */ (0, import_jsx_runtime70.jsxs)(
9695
+ return /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)(
9443
9696
  "aside",
9444
9697
  {
9445
9698
  className: ["fdc-panel", SURFACES[surface] || SURFACES.sidebar, narrow ? "is-narrow" : "", className].filter(Boolean).join(" "),
@@ -9450,7 +9703,7 @@ function AgentChatPanel({
9450
9703
  },
9451
9704
  "aria-label": title,
9452
9705
  children: [
9453
- surface === "sidebar" && resizable ? /* @__PURE__ */ (0, import_jsx_runtime70.jsx)(
9706
+ surface === "sidebar" && resizable ? /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(
9454
9707
  "div",
9455
9708
  {
9456
9709
  className: "fdc-grip",
@@ -9465,20 +9718,20 @@ function AgentChatPanel({
9465
9718
  }
9466
9719
  }
9467
9720
  ) : null,
9468
- showHeader ? /* @__PURE__ */ (0, import_jsx_runtime70.jsxs)("header", { className: "fdc-head", children: [
9469
- /* @__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 }) }),
9470
- /* @__PURE__ */ (0, import_jsx_runtime70.jsxs)("span", { className: "fdc-head-titles", children: [
9471
- /* @__PURE__ */ (0, import_jsx_runtime70.jsx)("span", { className: "fdc-head-title", children: title }),
9472
- 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
9473
9726
  ] }),
9474
- /* @__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: [
9475
9728
  headerActions,
9476
9729
  threadMenu,
9477
- 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,
9478
- 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
9479
9732
  ] })
9480
9733
  ] }) : null,
9481
- /* @__PURE__ */ (0, import_jsx_runtime70.jsx)(
9734
+ /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(
9482
9735
  ChatTranscript,
9483
9736
  {
9484
9737
  messages: engine.visible,
@@ -9493,7 +9746,7 @@ function AgentChatPanel({
9493
9746
  renderEmpty
9494
9747
  }
9495
9748
  ),
9496
- /* @__PURE__ */ (0, import_jsx_runtime70.jsx)(
9749
+ /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(
9497
9750
  ChatComposer,
9498
9751
  {
9499
9752
  onSubmit: (text, atts) => engine.send(text, atts),
@@ -9526,7 +9779,7 @@ function AgentChatPanel({
9526
9779
  }
9527
9780
 
9528
9781
  // src/kits/query.ts
9529
- var React40 = __toESM(require("react"), 1);
9782
+ var React42 = __toESM(require("react"), 1);
9530
9783
  function eqFilter(get2) {
9531
9784
  return (row, value) => Array.isArray(value) ? value.includes(get2(row)) : get2(row) === value;
9532
9785
  }
@@ -9558,22 +9811,22 @@ function compare(a, b, dir) {
9558
9811
  var API = null;
9559
9812
  var PREFS = null;
9560
9813
  function useServerTable({ endpoint, params, defaults, deps, prefsKey }) {
9561
- const [query, setQuery] = React40.useState(() => {
9814
+ const [query, setQuery] = React42.useState(() => {
9562
9815
  const store = PREFS || window.PlannerPrefs;
9563
9816
  const saved = prefsKey && store ? store.getTable(prefsKey) : {};
9564
9817
  return { ...DEFAULTS, ...defaults || {}, ...saved.pageSize ? { pageSize: saved.pageSize } : {}, ...saved.sort ? { sort: saved.sort, dir: saved.dir || "desc" } : {} };
9565
9818
  });
9566
- const savePref = React40.useCallback((patch2) => {
9819
+ const savePref = React42.useCallback((patch2) => {
9567
9820
  const store = PREFS || window.PlannerPrefs;
9568
9821
  if (prefsKey && store) store.setTable(prefsKey, patch2);
9569
9822
  }, [prefsKey]);
9570
- const [res, setRes] = React40.useState(null);
9571
- const [loading, setLoading] = React40.useState(true);
9572
- 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);
9573
9826
  const depKey = (deps || []).join("|");
9574
9827
  const paramKey = JSON.stringify(params || {});
9575
9828
  const queryKey = JSON.stringify(query);
9576
- React40.useEffect(() => {
9829
+ React42.useEffect(() => {
9577
9830
  const id = ++seq2.current;
9578
9831
  setLoading(true);
9579
9832
  const t = setTimeout(() => {
@@ -9912,6 +10165,7 @@ function createVersionStore(initialState, options) {
9912
10165
  Dropzone,
9913
10166
  DropzoneKit,
9914
10167
  EmptyState,
10168
+ EntityRow,
9915
10169
  FeatureGate,
9916
10170
  FileChip,
9917
10171
  FileGrid,
@@ -9984,11 +10238,16 @@ function createVersionStore(initialState, options) {
9984
10238
  Tooltip,
9985
10239
  Topbar,
9986
10240
  TranscriptKit,
10241
+ TransferList,
9987
10242
  UseFeatureStatus,
9988
10243
  UseRuntimeMode,
10244
+ VIRTUAL_LIST_BUFFER_ROWS,
10245
+ VirtualList,
9989
10246
  acceptMatches,
9990
10247
  anyOfFilter,
9991
10248
  channelWeightOf,
10249
+ computeNeedMore,
10250
+ computeVirtualWindow,
9992
10251
  createVersionStore,
9993
10252
  eqFilter,
9994
10253
  extensionOf,