@flytedan/flytebot-design-system 0.6.1 → 0.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1069,6 +1069,9 @@ var BANDS = {
1069
1069
  strong: { n: 3, label: "Strong" },
1070
1070
  dominant: { n: 4, label: "Dominant" }
1071
1071
  };
1072
+ function formatCrp(crp) {
1073
+ return crp.toFixed(1);
1074
+ }
1072
1075
  function CsiMeter({ band = "weak", size = 4, width = 5, gap = 2 }) {
1073
1076
  const n = (BANDS[band] || BANDS.weak).n;
1074
1077
  return /* @__PURE__ */ jsx26("span", { className: "fd-meter", style: { gap: gap + "px" }, "aria-hidden": "true", children: [1, 2, 3, 4].map((i) => /* @__PURE__ */ jsx26(
@@ -1091,7 +1094,7 @@ function CsiBadge({ band = "weak", crp, size = "compact", preview = false, alert
1091
1094
  alert ? /* @__PURE__ */ jsx26("span", { className: "fd-badge-dot", style: { background: "var(--csi-alert)" }, "aria-label": "Fixable" }) : null,
1092
1095
  /* @__PURE__ */ jsx26(CsiMeter, { band, size: size === "medium" ? 11 : 9, width: size === "medium" ? 4 : 3 }),
1093
1096
  b.label,
1094
- crp !== void 0 && crp !== null ? /* @__PURE__ */ jsx26("span", { className: "fd-csi-crp", children: crp }) : null
1097
+ crp !== void 0 && crp !== null ? /* @__PURE__ */ jsx26("span", { className: "fd-csi-crp", children: formatCrp(crp) }) : null
1095
1098
  ]
1096
1099
  }
1097
1100
  );
@@ -1100,7 +1103,7 @@ function CsiHero({ band = "weak", crp, label, className = "" }) {
1100
1103
  const b = BANDS[band] || BANDS.weak;
1101
1104
  const mark = "var(--csi-" + b.n + "-mark)";
1102
1105
  return /* @__PURE__ */ jsxs21("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 10 }, children: [
1103
- /* @__PURE__ */ jsx26("span", { className: "fd-csi-hero-num", style: { color: mark }, children: crp }),
1106
+ /* @__PURE__ */ jsx26("span", { className: "fd-csi-hero-num", style: { color: mark }, children: crp !== void 0 && crp !== null ? formatCrp(crp) : "" }),
1104
1107
  /* @__PURE__ */ jsx26("span", { className: "fd-label-lg", style: { color: "var(--text-2)" }, children: label || b.label }),
1105
1108
  /* @__PURE__ */ jsx26("span", { className: "fd-meter", style: { gap: 3, color: mark, width: 120 }, children: [1, 2, 3, 4].map((i) => /* @__PURE__ */ jsx26("span", { className: "fd-meter-seg" + (i <= b.n ? " is-on" : ""), style: { height: 6, flex: 1 } }, i)) })
1106
1109
  ] });
@@ -2428,56 +2431,140 @@ function StepList({
2428
2431
  ] });
2429
2432
  }
2430
2433
 
2431
- // src/components/forms/Checkbox.tsx
2434
+ // src/components/data/VirtualList.tsx
2432
2435
  import * as React15 from "react";
2433
2436
  import { jsx as jsx37, jsxs as jsxs33 } from "react/jsx-runtime";
2434
- function Checkbox({ label, description, card = false, indeterminate = false, className = "", ...rest }) {
2435
- const ref = React15.useRef(null);
2437
+ var VIRTUAL_LIST_BUFFER_ROWS = 20;
2438
+ function computeVirtualWindow(opts) {
2439
+ const { scrollTop, viewportHeight, itemHeight, itemCount, bufferRows = VIRTUAL_LIST_BUFFER_ROWS } = opts;
2440
+ if (itemCount <= 0 || itemHeight <= 0) {
2441
+ return { visibleStart: 0, visibleEnd: -1, startIndex: 0, endIndex: -1, totalHeight: 0, offsetY: 0 };
2442
+ }
2443
+ const lastPossible = itemCount - 1;
2444
+ const visibleStart = Math.min(lastPossible, Math.max(0, Math.floor(scrollTop / itemHeight)));
2445
+ const visibleRows = Math.max(1, Math.ceil(viewportHeight / itemHeight));
2446
+ const visibleEnd = Math.min(lastPossible, visibleStart + visibleRows - 1);
2447
+ const startIndex = Math.max(0, visibleStart - bufferRows);
2448
+ const endIndex = Math.min(lastPossible, visibleEnd + bufferRows);
2449
+ return {
2450
+ visibleStart,
2451
+ visibleEnd,
2452
+ startIndex,
2453
+ endIndex,
2454
+ totalHeight: itemCount * itemHeight,
2455
+ offsetY: startIndex * itemHeight
2456
+ };
2457
+ }
2458
+ function computeNeedMore(win, itemCount, bufferRows = VIRTUAL_LIST_BUFFER_ROWS) {
2459
+ if (itemCount <= 0) return { start: true, end: true };
2460
+ return {
2461
+ start: win.visibleStart <= bufferRows,
2462
+ end: itemCount - 1 - win.visibleEnd <= bufferRows
2463
+ };
2464
+ }
2465
+ function VirtualList({
2466
+ items,
2467
+ itemHeight,
2468
+ renderItem,
2469
+ onNeedMore,
2470
+ hasMore,
2471
+ loading = false,
2472
+ keyOf,
2473
+ height = 400,
2474
+ emptyState,
2475
+ className = "",
2476
+ style
2477
+ }) {
2478
+ const [scrollTop, setScrollTop] = React15.useState(0);
2479
+ const requested = React15.useRef({ start: null, end: null });
2480
+ const win = React15.useMemo(
2481
+ () => computeVirtualWindow({ scrollTop, viewportHeight: height, itemHeight, itemCount: items.length }),
2482
+ [scrollTop, height, itemHeight, items.length]
2483
+ );
2484
+ const need = React15.useMemo(() => computeNeedMore(win, items.length), [win, items.length]);
2485
+ const wantStart = need.start && hasMore?.start !== false;
2486
+ const wantEnd = need.end && hasMore?.end !== false;
2436
2487
  React15.useEffect(() => {
2437
- if (ref.current) ref.current.indeterminate = indeterminate;
2438
- }, [indeterminate]);
2439
- return /* @__PURE__ */ jsxs33("label", { className: ["fd-choice", card ? "fd-choice-card" : "", className].filter(Boolean).join(" "), children: [
2440
- /* @__PURE__ */ jsxs33("span", { className: "fd-choice-input", children: [
2441
- /* @__PURE__ */ jsx37("input", { ref, type: "checkbox", ...rest }),
2442
- /* @__PURE__ */ jsx37("span", { className: "fd-choice-box", "aria-hidden": "true", children: /* @__PURE__ */ jsx37("i", { className: indeterminate ? "ph ph-minus" : "ph ph-check" }) })
2443
- ] }),
2444
- /* @__PURE__ */ jsxs33("span", { className: "fd-choice-text", children: [
2445
- /* @__PURE__ */ jsx37("span", { className: "fd-choice-title", children: label }),
2446
- description ? /* @__PURE__ */ jsx37("span", { className: "fd-choice-desc", children: description }) : null
2447
- ] })
2448
- ] });
2488
+ if (loading || !wantStart || requested.current.start === items.length) return;
2489
+ requested.current.start = items.length;
2490
+ onNeedMore("start");
2491
+ }, [wantStart, loading, items.length, onNeedMore]);
2492
+ React15.useEffect(() => {
2493
+ if (loading || !wantEnd || requested.current.end === items.length) return;
2494
+ requested.current.end = items.length;
2495
+ onNeedMore("end");
2496
+ }, [wantEnd, loading, items.length, onNeedMore]);
2497
+ if (!items.length && !loading && emptyState) {
2498
+ return /* @__PURE__ */ jsx37("div", { className: ["fd-vlist", className].filter(Boolean).join(" "), style: { height, overflow: "auto", ...style }, children: emptyState });
2499
+ }
2500
+ const rows = [];
2501
+ for (let i = win.startIndex; i <= win.endIndex; i++) {
2502
+ const item = items[i];
2503
+ if (item === void 0) continue;
2504
+ rows.push(
2505
+ /* @__PURE__ */ jsx37("div", { style: { height: itemHeight, boxSizing: "border-box" }, children: renderItem(item, i) }, keyOf(item))
2506
+ );
2507
+ }
2508
+ return /* @__PURE__ */ jsxs33(
2509
+ "div",
2510
+ {
2511
+ className: ["fd-vlist", className].filter(Boolean).join(" "),
2512
+ style: { height, overflowY: "auto", overflowX: "hidden", position: "relative", ...style },
2513
+ onScroll: (e) => setScrollTop(e.currentTarget.scrollTop),
2514
+ children: [
2515
+ /* @__PURE__ */ jsx37("div", { style: { height: win.totalHeight, position: "relative" }, children: /* @__PURE__ */ jsx37("div", { style: { position: "absolute", top: win.offsetY, left: 0, right: 0 }, children: rows }) }),
2516
+ loading ? /* @__PURE__ */ jsx37("div", { style: { position: "sticky", bottom: 0, left: 0, right: 0, display: "grid", placeItems: "center", padding: "8px 0", background: "var(--surface)" }, children: /* @__PURE__ */ jsx37("span", { className: "fd-spinner", "aria-hidden": "true" }) }) : null
2517
+ ]
2518
+ }
2519
+ );
2449
2520
  }
2450
2521
 
2451
- // src/components/forms/Radio.tsx
2522
+ // src/components/data/EntityRow.tsx
2452
2523
  import { jsx as jsx38, jsxs as jsxs34 } from "react/jsx-runtime";
2453
- function Radio({ label, description, card = false, className = "", ...rest }) {
2454
- return /* @__PURE__ */ jsxs34("label", { className: ["fd-choice", card ? "fd-choice-card" : "", className].filter(Boolean).join(" "), children: [
2455
- /* @__PURE__ */ jsxs34("span", { className: "fd-choice-input", children: [
2456
- /* @__PURE__ */ jsx38("input", { type: "radio", ...rest }),
2457
- /* @__PURE__ */ jsx38("span", { className: "fd-choice-box fd-choice-box-round", "aria-hidden": "true", children: /* @__PURE__ */ jsx38("span", { className: "fd-choice-dot" }) })
2458
- ] }),
2459
- /* @__PURE__ */ jsxs34("span", { className: "fd-choice-text", children: [
2460
- /* @__PURE__ */ jsx38("span", { className: "fd-choice-title", children: label }),
2461
- description ? /* @__PURE__ */ jsx38("span", { className: "fd-choice-desc", children: description }) : null
2462
- ] })
2463
- ] });
2524
+ function EntityRow({ title, meta, action, draggable = false, onDragStart, onDragEnd, style, className = "" }) {
2525
+ return /* @__PURE__ */ jsxs34(
2526
+ "div",
2527
+ {
2528
+ draggable,
2529
+ onDragStart,
2530
+ onDragEnd,
2531
+ className: ["fd-erow", className].filter(Boolean).join(" "),
2532
+ style: {
2533
+ display: "flex",
2534
+ alignItems: "center",
2535
+ gap: 8,
2536
+ height: "100%",
2537
+ padding: "0 8px",
2538
+ borderRadius: 6,
2539
+ cursor: draggable ? "grab" : void 0,
2540
+ ...style
2541
+ },
2542
+ children: [
2543
+ draggable ? /* @__PURE__ */ jsx38("i", { className: "ph ph-dots-six-vertical", "aria-hidden": "true", style: { fontSize: 13, flex: "none", color: "var(--text-muted)" } }) : null,
2544
+ /* @__PURE__ */ jsxs34("span", { style: { flex: 1, minWidth: 0, display: "flex", flexDirection: "column", gap: 1 }, children: [
2545
+ /* @__PURE__ */ jsx38("span", { className: "fd-body-sm", style: { fontWeight: 600, color: "var(--text)", whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis" }, children: title }),
2546
+ meta ? /* @__PURE__ */ jsx38("span", { style: { fontSize: "var(--overline-size)", color: "var(--text-muted)", whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis" }, children: meta }) : null
2547
+ ] }),
2548
+ action ? /* @__PURE__ */ jsx38(
2549
+ IconButton,
2550
+ {
2551
+ icon: action.icon,
2552
+ label: action.label,
2553
+ size: "sm",
2554
+ onClick: action.onClick,
2555
+ style: { color: action.tone === "add" ? "var(--ok-text)" : action.tone === "remove" ? "var(--danger-text)" : void 0 }
2556
+ }
2557
+ ) : null
2558
+ ]
2559
+ }
2560
+ );
2464
2561
  }
2465
2562
 
2466
- // src/components/forms/Switch.tsx
2467
- import { jsx as jsx39, jsxs as jsxs35 } from "react/jsx-runtime";
2468
- function Switch({ label, description, className = "", ...rest }) {
2469
- return /* @__PURE__ */ jsxs35("label", { className: ["fd-switch", className].filter(Boolean).join(" "), children: [
2470
- /* @__PURE__ */ jsx39("input", { type: "checkbox", role: "switch", ...rest }),
2471
- /* @__PURE__ */ jsx39("span", { className: "fd-switch-track", children: /* @__PURE__ */ jsx39("span", { className: "fd-switch-thumb" }) }),
2472
- label ? /* @__PURE__ */ jsxs35("span", { className: "fd-choice-text", children: [
2473
- /* @__PURE__ */ jsx39("span", { className: "fd-switch-label", children: label }),
2474
- description ? /* @__PURE__ */ jsx39("span", { className: "fd-choice-desc", children: description }) : null
2475
- ] }) : null
2476
- ] });
2477
- }
2563
+ // src/components/data/TransferList.tsx
2564
+ import * as React16 from "react";
2478
2565
 
2479
2566
  // src/components/forms/Input.tsx
2480
- import { jsx as jsx40, jsxs as jsxs36 } from "react/jsx-runtime";
2567
+ import { jsx as jsx39, jsxs as jsxs35 } from "react/jsx-runtime";
2481
2568
  function Input({
2482
2569
  label,
2483
2570
  help,
@@ -2505,27 +2592,27 @@ function Input({
2505
2592
  size === "lg" ? "fd-input-lg" : "",
2506
2593
  className
2507
2594
  ].filter(Boolean).join(" ");
2508
- return /* @__PURE__ */ jsxs36("div", { className: "fd-field", style, children: [
2509
- label ? /* @__PURE__ */ jsxs36("label", { className: "fd-field-label", htmlFor: fieldId, children: [
2595
+ return /* @__PURE__ */ jsxs35("div", { className: "fd-field", style, children: [
2596
+ label ? /* @__PURE__ */ jsxs35("label", { className: "fd-field-label", htmlFor: fieldId, children: [
2510
2597
  label,
2511
- required ? /* @__PURE__ */ jsx40("span", { className: "fd-field-req", "aria-hidden": "true", children: "*" }) : null
2598
+ required ? /* @__PURE__ */ jsx39("span", { className: "fd-field-req", "aria-hidden": "true", children: "*" }) : null
2512
2599
  ] }) : null,
2513
- /* @__PURE__ */ jsxs36("div", { className: box, children: [
2514
- icon ? /* @__PURE__ */ jsx40("span", { className: "fd-input-icon", children: /* @__PURE__ */ jsx40("i", { className: "ph ph-" + icon, "aria-hidden": "true" }) }) : null,
2515
- prefix ? /* @__PURE__ */ jsx40("span", { className: "fd-input-affix", children: prefix }) : null,
2516
- /* @__PURE__ */ jsx40("input", { id: fieldId, disabled, style: inputStyle, "aria-invalid": error ? "true" : void 0, ...rest }),
2517
- loading ? /* @__PURE__ */ jsx40("span", { className: "fd-spinner", style: { color: "var(--text-muted)" }, "aria-label": "Loading" }) : null,
2518
- suffix && !loading ? /* @__PURE__ */ jsx40("span", { className: "fd-input-affix", children: suffix }) : null
2600
+ /* @__PURE__ */ jsxs35("div", { className: box, children: [
2601
+ icon ? /* @__PURE__ */ jsx39("span", { className: "fd-input-icon", children: /* @__PURE__ */ jsx39("i", { className: "ph ph-" + icon, "aria-hidden": "true" }) }) : null,
2602
+ prefix ? /* @__PURE__ */ jsx39("span", { className: "fd-input-affix", children: prefix }) : null,
2603
+ /* @__PURE__ */ jsx39("input", { id: fieldId, disabled, style: inputStyle, "aria-invalid": error ? "true" : void 0, ...rest }),
2604
+ loading ? /* @__PURE__ */ jsx39("span", { className: "fd-spinner", style: { color: "var(--text-muted)" }, "aria-label": "Loading" }) : null,
2605
+ suffix && !loading ? /* @__PURE__ */ jsx39("span", { className: "fd-input-affix", children: suffix }) : null
2519
2606
  ] }),
2520
- error ? /* @__PURE__ */ jsxs36("span", { className: "fd-field-error", children: [
2521
- /* @__PURE__ */ jsx40("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
2607
+ error ? /* @__PURE__ */ jsxs35("span", { className: "fd-field-error", children: [
2608
+ /* @__PURE__ */ jsx39("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
2522
2609
  error
2523
- ] }) : help ? /* @__PURE__ */ jsx40("span", { className: "fd-field-help", children: help }) : null
2610
+ ] }) : help ? /* @__PURE__ */ jsx39("span", { className: "fd-field-help", children: help }) : null
2524
2611
  ] });
2525
2612
  }
2526
2613
 
2527
2614
  // src/components/forms/SearchField.tsx
2528
- import { jsx as jsx41 } from "react/jsx-runtime";
2615
+ import { jsx as jsx40 } from "react/jsx-runtime";
2529
2616
  function SearchField({
2530
2617
  value,
2531
2618
  onChange,
@@ -2540,7 +2627,7 @@ function SearchField({
2540
2627
  ...rest
2541
2628
  }) {
2542
2629
  const clear = onClear || (() => onChange(""));
2543
- return /* @__PURE__ */ jsx41(
2630
+ return /* @__PURE__ */ jsx40(
2544
2631
  Input,
2545
2632
  {
2546
2633
  id,
@@ -2553,14 +2640,14 @@ function SearchField({
2553
2640
  style,
2554
2641
  className,
2555
2642
  onChange: (e) => onChange(e.target.value),
2556
- suffix: value ? /* @__PURE__ */ jsx41(
2643
+ suffix: value ? /* @__PURE__ */ jsx40(
2557
2644
  "button",
2558
2645
  {
2559
2646
  type: "button",
2560
2647
  "aria-label": "Clear search",
2561
2648
  onClick: clear,
2562
2649
  style: { all: "unset", cursor: "pointer", color: "var(--text-muted)", display: "grid", placeItems: "center", padding: 2 },
2563
- children: /* @__PURE__ */ jsx41("i", { className: "ph ph-x-circle", style: { fontSize: 15 }, "aria-hidden": "true" })
2650
+ children: /* @__PURE__ */ jsx40("i", { className: "ph ph-x-circle", style: { fontSize: 15 }, "aria-hidden": "true" })
2564
2651
  }
2565
2652
  ) : void 0,
2566
2653
  ...rest
@@ -2568,27 +2655,183 @@ function SearchField({
2568
2655
  );
2569
2656
  }
2570
2657
 
2571
- // src/components/forms/Textarea.tsx
2658
+ // src/components/data/TransferList.tsx
2659
+ import { jsx as jsx41, jsxs as jsxs36 } from "react/jsx-runtime";
2660
+ var emptyHasMore = {};
2661
+ function TransferList({
2662
+ left,
2663
+ right,
2664
+ keyOf,
2665
+ renderLabel,
2666
+ renderMeta,
2667
+ onMove,
2668
+ itemHeight = 44,
2669
+ listHeight = 440,
2670
+ className = ""
2671
+ }) {
2672
+ const [dragging, setDragging] = React16.useState(null);
2673
+ const [dragOverSide, setDragOverSide] = React16.useState(null);
2674
+ const startDrag = (e, item, from) => {
2675
+ const key = keyOf(item);
2676
+ setDragging({ key, from });
2677
+ e.dataTransfer.effectAllowed = "move";
2678
+ e.dataTransfer.setData("text/plain", String(key));
2679
+ };
2680
+ const endDrag = () => {
2681
+ setDragging(null);
2682
+ setDragOverSide(null);
2683
+ };
2684
+ const findItem = (side, key) => (side === "left" ? left.items : right.items).find((it) => keyOf(it) === key);
2685
+ const dropOnSide = (e, side) => {
2686
+ e.preventDefault();
2687
+ setDragOverSide(null);
2688
+ if (!dragging || dragging.from === side) return;
2689
+ const item = findItem(dragging.from, dragging.key);
2690
+ if (item !== void 0) onMove(item, dragging.from, side);
2691
+ setDragging(null);
2692
+ };
2693
+ const renderSide = (side, cfg, opposite) => /* @__PURE__ */ jsxs36(
2694
+ "div",
2695
+ {
2696
+ style: {
2697
+ flex: 1,
2698
+ minWidth: 0,
2699
+ display: "flex",
2700
+ flexDirection: "column",
2701
+ gap: 8,
2702
+ padding: 10,
2703
+ borderRadius: 10,
2704
+ border: "1px solid " + (dragOverSide === side ? "var(--brand)" : "var(--border)"),
2705
+ background: "var(--surface)"
2706
+ },
2707
+ onDragOver: (e) => {
2708
+ if (!dragging || dragging.from === side) return;
2709
+ e.preventDefault();
2710
+ e.dataTransfer.dropEffect = "move";
2711
+ if (dragOverSide !== side) setDragOverSide(side);
2712
+ },
2713
+ onDragLeave: (e) => {
2714
+ if (e.currentTarget.contains(e.relatedTarget)) return;
2715
+ setDragOverSide((s) => s === side ? null : s);
2716
+ },
2717
+ onDrop: (e) => dropOnSide(e, side),
2718
+ children: [
2719
+ cfg.label ? /* @__PURE__ */ jsxs36("span", { className: "fd-overline fd-muted", children: [
2720
+ cfg.label,
2721
+ cfg.total != null ? " (" + cfg.total.toLocaleString() + ")" : ""
2722
+ ] }) : null,
2723
+ /* @__PURE__ */ jsxs36("span", { className: "fd-row", style: { gap: 8 }, children: [
2724
+ /* @__PURE__ */ jsx41(SearchField, { value: cfg.search, onChange: cfg.onSearchChange, placeholder: "Search", "aria-label": (cfg.label || side) + " search", style: { flex: 1 } }),
2725
+ /* @__PURE__ */ jsx41(SortMenu, { fields: cfg.sortFields, sort: cfg.sort, onSort: cfg.onSort })
2726
+ ] }),
2727
+ /* @__PURE__ */ jsx41(
2728
+ VirtualList,
2729
+ {
2730
+ items: cfg.items,
2731
+ itemHeight,
2732
+ height: listHeight,
2733
+ keyOf,
2734
+ loading: cfg.loading,
2735
+ hasMore: cfg.hasMore || emptyHasMore,
2736
+ onNeedMore: cfg.onNeedMore,
2737
+ emptyState: /* @__PURE__ */ jsx41(EmptyState, { icon: "tray", title: "Nothing here" }),
2738
+ renderItem: (item) => /* @__PURE__ */ jsx41(
2739
+ EntityRow,
2740
+ {
2741
+ title: renderLabel(item),
2742
+ meta: renderMeta ? renderMeta(item) : void 0,
2743
+ draggable: true,
2744
+ onDragStart: (e) => startDrag(e, item, side),
2745
+ onDragEnd: endDrag,
2746
+ style: { opacity: dragging && dragging.from === side && dragging.key === keyOf(item) ? 0.4 : 1 },
2747
+ action: {
2748
+ icon: side === "left" ? "plus" : "minus",
2749
+ label: (side === "left" ? "Move to " : "Move from ") + (side === "left" ? right.label || "the other list" : left.label || "the other list"),
2750
+ tone: side === "left" ? "add" : "remove",
2751
+ onClick: () => onMove(item, side, opposite)
2752
+ }
2753
+ }
2754
+ )
2755
+ }
2756
+ )
2757
+ ]
2758
+ }
2759
+ );
2760
+ return /* @__PURE__ */ jsxs36("div", { className: ["fd-tlist", className].filter(Boolean).join(" "), style: { display: "flex", gap: 16, alignItems: "flex-start" }, children: [
2761
+ renderSide("left", left, "right"),
2762
+ renderSide("right", right, "left")
2763
+ ] });
2764
+ }
2765
+
2766
+ // src/components/forms/Checkbox.tsx
2767
+ import * as React17 from "react";
2572
2768
  import { jsx as jsx42, jsxs as jsxs37 } from "react/jsx-runtime";
2769
+ function Checkbox({ label, description, card = false, indeterminate = false, className = "", ...rest }) {
2770
+ const ref = React17.useRef(null);
2771
+ React17.useEffect(() => {
2772
+ if (ref.current) ref.current.indeterminate = indeterminate;
2773
+ }, [indeterminate]);
2774
+ return /* @__PURE__ */ jsxs37("label", { className: ["fd-choice", card ? "fd-choice-card" : "", className].filter(Boolean).join(" "), children: [
2775
+ /* @__PURE__ */ jsxs37("span", { className: "fd-choice-input", children: [
2776
+ /* @__PURE__ */ jsx42("input", { ref, type: "checkbox", ...rest }),
2777
+ /* @__PURE__ */ jsx42("span", { className: "fd-choice-box", "aria-hidden": "true", children: /* @__PURE__ */ jsx42("i", { className: indeterminate ? "ph ph-minus" : "ph ph-check" }) })
2778
+ ] }),
2779
+ /* @__PURE__ */ jsxs37("span", { className: "fd-choice-text", children: [
2780
+ /* @__PURE__ */ jsx42("span", { className: "fd-choice-title", children: label }),
2781
+ description ? /* @__PURE__ */ jsx42("span", { className: "fd-choice-desc", children: description }) : null
2782
+ ] })
2783
+ ] });
2784
+ }
2785
+
2786
+ // src/components/forms/Radio.tsx
2787
+ import { jsx as jsx43, jsxs as jsxs38 } from "react/jsx-runtime";
2788
+ function Radio({ label, description, card = false, className = "", ...rest }) {
2789
+ return /* @__PURE__ */ jsxs38("label", { className: ["fd-choice", card ? "fd-choice-card" : "", className].filter(Boolean).join(" "), children: [
2790
+ /* @__PURE__ */ jsxs38("span", { className: "fd-choice-input", children: [
2791
+ /* @__PURE__ */ jsx43("input", { type: "radio", ...rest }),
2792
+ /* @__PURE__ */ jsx43("span", { className: "fd-choice-box fd-choice-box-round", "aria-hidden": "true", children: /* @__PURE__ */ jsx43("span", { className: "fd-choice-dot" }) })
2793
+ ] }),
2794
+ /* @__PURE__ */ jsxs38("span", { className: "fd-choice-text", children: [
2795
+ /* @__PURE__ */ jsx43("span", { className: "fd-choice-title", children: label }),
2796
+ description ? /* @__PURE__ */ jsx43("span", { className: "fd-choice-desc", children: description }) : null
2797
+ ] })
2798
+ ] });
2799
+ }
2800
+
2801
+ // src/components/forms/Switch.tsx
2802
+ import { jsx as jsx44, jsxs as jsxs39 } from "react/jsx-runtime";
2803
+ function Switch({ label, description, className = "", ...rest }) {
2804
+ return /* @__PURE__ */ jsxs39("label", { className: ["fd-switch", className].filter(Boolean).join(" "), children: [
2805
+ /* @__PURE__ */ jsx44("input", { type: "checkbox", role: "switch", ...rest }),
2806
+ /* @__PURE__ */ jsx44("span", { className: "fd-switch-track", children: /* @__PURE__ */ jsx44("span", { className: "fd-switch-thumb" }) }),
2807
+ label ? /* @__PURE__ */ jsxs39("span", { className: "fd-choice-text", children: [
2808
+ /* @__PURE__ */ jsx44("span", { className: "fd-switch-label", children: label }),
2809
+ description ? /* @__PURE__ */ jsx44("span", { className: "fd-choice-desc", children: description }) : null
2810
+ ] }) : null
2811
+ ] });
2812
+ }
2813
+
2814
+ // src/components/forms/Textarea.tsx
2815
+ import { jsx as jsx45, jsxs as jsxs40 } from "react/jsx-runtime";
2573
2816
  function Textarea({ label, help, error, required = false, rows = 4, disabled = false, id, className = "", style, ...rest }) {
2574
2817
  const fieldId = id || (rest.name ? "fd-" + rest.name : void 0);
2575
2818
  const box = ["fd-input", "fd-input-textarea", error ? "fd-input-error" : "", disabled ? "fd-input-disabled" : "", className].filter(Boolean).join(" ");
2576
- return /* @__PURE__ */ jsxs37("div", { className: "fd-field", style, children: [
2577
- label ? /* @__PURE__ */ jsxs37("label", { className: "fd-field-label", htmlFor: fieldId, children: [
2819
+ return /* @__PURE__ */ jsxs40("div", { className: "fd-field", style, children: [
2820
+ label ? /* @__PURE__ */ jsxs40("label", { className: "fd-field-label", htmlFor: fieldId, children: [
2578
2821
  label,
2579
- required ? /* @__PURE__ */ jsx42("span", { className: "fd-field-req", children: "*" }) : null
2822
+ required ? /* @__PURE__ */ jsx45("span", { className: "fd-field-req", children: "*" }) : null
2580
2823
  ] }) : null,
2581
- /* @__PURE__ */ jsx42("div", { className: box, children: /* @__PURE__ */ jsx42("textarea", { id: fieldId, rows, disabled, "aria-invalid": error ? "true" : void 0, ...rest }) }),
2582
- error ? /* @__PURE__ */ jsxs37("span", { className: "fd-field-error", children: [
2583
- /* @__PURE__ */ jsx42("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
2824
+ /* @__PURE__ */ jsx45("div", { className: box, children: /* @__PURE__ */ jsx45("textarea", { id: fieldId, rows, disabled, "aria-invalid": error ? "true" : void 0, ...rest }) }),
2825
+ error ? /* @__PURE__ */ jsxs40("span", { className: "fd-field-error", children: [
2826
+ /* @__PURE__ */ jsx45("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
2584
2827
  error
2585
- ] }) : help ? /* @__PURE__ */ jsx42("span", { className: "fd-field-help", children: help }) : null
2828
+ ] }) : help ? /* @__PURE__ */ jsx45("span", { className: "fd-field-help", children: help }) : null
2586
2829
  ] });
2587
2830
  }
2588
2831
 
2589
2832
  // src/components/forms/NumberInput.tsx
2590
- import * as React16 from "react";
2591
- import { jsx as jsx43, jsxs as jsxs38 } from "react/jsx-runtime";
2833
+ import * as React18 from "react";
2834
+ import { jsx as jsx46, jsxs as jsxs41 } from "react/jsx-runtime";
2592
2835
  function NumberInput({
2593
2836
  label,
2594
2837
  help,
@@ -2612,10 +2855,10 @@ function NumberInput({
2612
2855
  const n = Number(String(v == null ? "" : v).replace(/[^0-9.-]/g, ""));
2613
2856
  return isNaN(n) ? null : n;
2614
2857
  };
2615
- const [text, setText] = React16.useState(value == null || value === "" ? "" : String(value));
2616
- const [editing, setEditing] = React16.useState(false);
2617
- const timer = React16.useRef(null);
2618
- React16.useEffect(() => {
2858
+ const [text, setText] = React18.useState(value == null || value === "" ? "" : String(value));
2859
+ const [editing, setEditing] = React18.useState(false);
2860
+ const timer = React18.useRef(null);
2861
+ React18.useEffect(() => {
2619
2862
  if (!editing) setText(value == null || value === "" ? "" : String(value));
2620
2863
  }, [value, editing]);
2621
2864
  const clamp = (n) => Math.min(max, Math.max(min, n));
@@ -2639,7 +2882,7 @@ function NumberInput({
2639
2882
  const release = () => {
2640
2883
  if (timer.current) clearTimeout(timer.current);
2641
2884
  };
2642
- React16.useEffect(() => () => {
2885
+ React18.useEffect(() => () => {
2643
2886
  if (timer.current) clearTimeout(timer.current);
2644
2887
  }, []);
2645
2888
  const shown = editing ? text : (() => {
@@ -2647,14 +2890,14 @@ function NumberInput({
2647
2890
  return n == null ? "" : format ? n.toLocaleString() : String(n);
2648
2891
  })();
2649
2892
  const box = ["fd-input", "fd-input-num", error ? "fd-input-error" : "", disabled ? "fd-input-disabled" : ""].filter(Boolean).join(" ");
2650
- return /* @__PURE__ */ jsxs38("div", { className: ["fd-field", className].filter(Boolean).join(" "), style, children: [
2651
- label ? /* @__PURE__ */ jsxs38("label", { className: "fd-field-label", children: [
2893
+ return /* @__PURE__ */ jsxs41("div", { className: ["fd-field", className].filter(Boolean).join(" "), style, children: [
2894
+ label ? /* @__PURE__ */ jsxs41("label", { className: "fd-field-label", children: [
2652
2895
  label,
2653
- required ? /* @__PURE__ */ jsx43("span", { className: "fd-field-req", children: "*" }) : null
2896
+ required ? /* @__PURE__ */ jsx46("span", { className: "fd-field-req", children: "*" }) : null
2654
2897
  ] }) : null,
2655
- /* @__PURE__ */ jsxs38("div", { className: box, style: { gap: 8 }, children: [
2656
- prefix ? /* @__PURE__ */ jsx43("span", { className: "fd-input-affix", children: prefix }) : null,
2657
- /* @__PURE__ */ jsx43(
2898
+ /* @__PURE__ */ jsxs41("div", { className: box, style: { gap: 8 }, children: [
2899
+ prefix ? /* @__PURE__ */ jsx46("span", { className: "fd-input-affix", children: prefix }) : null,
2900
+ /* @__PURE__ */ jsx46(
2658
2901
  "input",
2659
2902
  {
2660
2903
  inputMode: "numeric",
@@ -2687,9 +2930,9 @@ function NumberInput({
2687
2930
  }
2688
2931
  }
2689
2932
  ),
2690
- suffix ? /* @__PURE__ */ jsx43("span", { className: "fd-input-affix", children: suffix }) : null,
2691
- /* @__PURE__ */ jsxs38("span", { className: "fd-row", style: { gap: 4, flex: "none" }, children: [
2692
- /* @__PURE__ */ jsx43(
2933
+ suffix ? /* @__PURE__ */ jsx46("span", { className: "fd-input-affix", children: suffix }) : null,
2934
+ /* @__PURE__ */ jsxs41("span", { className: "fd-row", style: { gap: 4, flex: "none" }, children: [
2935
+ /* @__PURE__ */ jsx46(
2693
2936
  "button",
2694
2937
  {
2695
2938
  type: "button",
@@ -2699,10 +2942,10 @@ function NumberInput({
2699
2942
  onPointerDown: () => hold(-1),
2700
2943
  onPointerUp: release,
2701
2944
  onPointerLeave: release,
2702
- children: /* @__PURE__ */ jsx43("i", { className: "ph ph-minus" })
2945
+ children: /* @__PURE__ */ jsx46("i", { className: "ph ph-minus" })
2703
2946
  }
2704
2947
  ),
2705
- /* @__PURE__ */ jsx43(
2948
+ /* @__PURE__ */ jsx46(
2706
2949
  "button",
2707
2950
  {
2708
2951
  type: "button",
@@ -2712,26 +2955,26 @@ function NumberInput({
2712
2955
  onPointerDown: () => hold(1),
2713
2956
  onPointerUp: release,
2714
2957
  onPointerLeave: release,
2715
- children: /* @__PURE__ */ jsx43("i", { className: "ph ph-plus" })
2958
+ children: /* @__PURE__ */ jsx46("i", { className: "ph ph-plus" })
2716
2959
  }
2717
2960
  )
2718
2961
  ] })
2719
2962
  ] }),
2720
- error ? /* @__PURE__ */ jsxs38("span", { className: "fd-field-error", children: [
2721
- /* @__PURE__ */ jsx43("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
2963
+ error ? /* @__PURE__ */ jsxs41("span", { className: "fd-field-error", children: [
2964
+ /* @__PURE__ */ jsx46("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
2722
2965
  error
2723
- ] }) : help ? /* @__PURE__ */ jsx43("span", { className: "fd-field-help", children: help }) : null
2966
+ ] }) : help ? /* @__PURE__ */ jsx46("span", { className: "fd-field-help", children: help }) : null
2724
2967
  ] });
2725
2968
  }
2726
2969
 
2727
2970
  // src/components/forms/Select.tsx
2728
- import * as React17 from "react";
2971
+ import * as React19 from "react";
2729
2972
  import { createPortal as createPortal4 } from "react-dom";
2730
- import { jsx as jsx44, jsxs as jsxs39 } from "react/jsx-runtime";
2973
+ import { jsx as jsx47, jsxs as jsxs42 } from "react/jsx-runtime";
2731
2974
  var norm = (o) => typeof o === "string" ? { value: o, label: o } : o;
2732
2975
  function usePopPos(open, ref, estH, estW) {
2733
- const [pos, setPos] = React17.useState(null);
2734
- React17.useLayoutEffect(() => {
2976
+ const [pos, setPos] = React19.useState(null);
2977
+ React19.useLayoutEffect(() => {
2735
2978
  if (!open || !ref.current) {
2736
2979
  setPos(null);
2737
2980
  return;
@@ -2795,14 +3038,14 @@ function Select({
2795
3038
  const vals = multiple ? Array.isArray(value) ? value : value ? [value] : [] : [];
2796
3039
  const isOn = (v) => multiple ? vals.includes(v) : v === value;
2797
3040
  const hasSearch = searchable === void 0 ? opts.length > 8 : searchable;
2798
- const [open, setOpen] = React17.useState(false);
2799
- const [q, setQ] = React17.useState("");
2800
- const [active, setActive] = React17.useState(-1);
2801
- const rootRef = React17.useRef(null);
2802
- const boxRef = React17.useRef(null);
2803
- const popRef = React17.useRef(null);
2804
- const listRef = React17.useRef(null);
2805
- const typeBuf = React17.useRef({ s: "", t: 0 });
3041
+ const [open, setOpen] = React19.useState(false);
3042
+ const [q, setQ] = React19.useState("");
3043
+ const [active, setActive] = React19.useState(-1);
3044
+ const rootRef = React19.useRef(null);
3045
+ const boxRef = React19.useRef(null);
3046
+ const popRef = React19.useRef(null);
3047
+ const listRef = React19.useRef(null);
3048
+ const typeBuf = React19.useRef({ s: "", t: 0 });
2806
3049
  const selected = multiple ? null : opts.find((o) => o.value === value);
2807
3050
  const chosen = multiple ? opts.filter((o) => vals.includes(o.value)) : [];
2808
3051
  const pos = usePopPos(open, boxRef, hasSearch ? 390 : 340, 260);
@@ -2828,7 +3071,7 @@ function Select({
2828
3071
  }
2829
3072
  setOpen(!open);
2830
3073
  };
2831
- React17.useEffect(() => {
3074
+ React19.useEffect(() => {
2832
3075
  if (!open) return;
2833
3076
  const away = (e) => {
2834
3077
  if (rootRef.current && rootRef.current.contains(e.target)) return;
@@ -2838,7 +3081,7 @@ function Select({
2838
3081
  document.addEventListener("pointerdown", away);
2839
3082
  return () => document.removeEventListener("pointerdown", away);
2840
3083
  }, [open]);
2841
- React17.useEffect(() => {
3084
+ React19.useEffect(() => {
2842
3085
  if (!open || active < 0 || !listRef.current) return;
2843
3086
  const el = listRef.current.querySelector('[data-i="' + active + '"]');
2844
3087
  if (el) {
@@ -2892,13 +3135,13 @@ function Select({
2892
3135
  });
2893
3136
  const fieldId = id || (rest.name ? "fd-" + rest.name : void 0);
2894
3137
  const box = ["fd-input", "fd-select", error ? "fd-input-error" : "", disabled ? "fd-input-disabled" : ""].filter(Boolean).join(" ");
2895
- return /* @__PURE__ */ jsxs39("div", { className: ["fd-field", "fd-popfield", open ? "is-open" : "", className].filter(Boolean).join(" "), style, ref: rootRef, children: [
2896
- label ? /* @__PURE__ */ jsxs39("label", { className: "fd-field-label", htmlFor: fieldId, onClick: toggle, children: [
3138
+ return /* @__PURE__ */ jsxs42("div", { className: ["fd-field", "fd-popfield", open ? "is-open" : "", className].filter(Boolean).join(" "), style, ref: rootRef, children: [
3139
+ label ? /* @__PURE__ */ jsxs42("label", { className: "fd-field-label", htmlFor: fieldId, onClick: toggle, children: [
2897
3140
  label,
2898
- required ? /* @__PURE__ */ jsx44("span", { className: "fd-field-req", children: "*" }) : null
3141
+ required ? /* @__PURE__ */ jsx47("span", { className: "fd-field-req", children: "*" }) : null
2899
3142
  ] }) : null,
2900
- /* @__PURE__ */ jsxs39("div", { className: box, style: { cursor: disabled ? "not-allowed" : "pointer" }, ref: boxRef, children: [
2901
- /* @__PURE__ */ jsxs39(
3143
+ /* @__PURE__ */ jsxs42("div", { className: box, style: { cursor: disabled ? "not-allowed" : "pointer" }, ref: boxRef, children: [
3144
+ /* @__PURE__ */ jsxs42(
2902
3145
  "button",
2903
3146
  {
2904
3147
  type: "button",
@@ -2911,13 +3154,13 @@ function Select({
2911
3154
  "aria-haspopup": "listbox",
2912
3155
  style: { all: "unset", flex: 1, minWidth: 0, display: "flex", alignItems: "center", gap: 8, cursor: "inherit", overflow: "hidden" },
2913
3156
  children: [
2914
- selected && selected.icon ? /* @__PURE__ */ jsx44("i", { className: "ph ph-" + selected.icon, style: { flex: "none", color: "var(--text-2)" } }) : null,
2915
- /* @__PURE__ */ jsx44("span", { style: { overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap", color: (multiple ? chosen.length : selected) ? "var(--text)" : "var(--text-muted)" }, children: boxText }),
2916
- multiple && chosen.length > 1 ? /* @__PURE__ */ jsx44("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
3157
+ selected && selected.icon ? /* @__PURE__ */ jsx47("i", { className: "ph ph-" + selected.icon, style: { flex: "none", color: "var(--text-2)" } }) : null,
3158
+ /* @__PURE__ */ jsx47("span", { style: { overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap", color: (multiple ? chosen.length : selected) ? "var(--text)" : "var(--text-muted)" }, children: boxText }),
3159
+ multiple && chosen.length > 1 ? /* @__PURE__ */ jsx47("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
2917
3160
  ]
2918
3161
  }
2919
3162
  ),
2920
- clearable && (multiple ? chosen.length > 0 : selected) && !loading ? /* @__PURE__ */ jsx44(
3163
+ clearable && (multiple ? chosen.length > 0 : selected) && !loading ? /* @__PURE__ */ jsx47(
2921
3164
  "button",
2922
3165
  {
2923
3166
  type: "button",
@@ -2927,22 +3170,22 @@ function Select({
2927
3170
  fire(multiple ? [] : "");
2928
3171
  },
2929
3172
  style: { all: "unset", cursor: "pointer", color: "var(--text-muted)", display: "grid", placeItems: "center", padding: 2 },
2930
- children: /* @__PURE__ */ jsx44("i", { className: "ph ph-x-circle", style: { fontSize: 15 } })
3173
+ children: /* @__PURE__ */ jsx47("i", { className: "ph ph-x-circle", style: { fontSize: 15 } })
2931
3174
  }
2932
3175
  ) : null,
2933
- loading ? /* @__PURE__ */ jsx44("span", { className: "fd-spinner", style: { color: "var(--text-muted)" }, "aria-label": "Loading options" }) : /* @__PURE__ */ jsx44("span", { className: "fd-select-caret", onClick: toggle, children: /* @__PURE__ */ jsx44("i", { className: "ph ph-caret-down", "aria-hidden": "true" }) })
3176
+ loading ? /* @__PURE__ */ jsx47("span", { className: "fd-spinner", style: { color: "var(--text-muted)" }, "aria-label": "Loading options" }) : /* @__PURE__ */ jsx47("span", { className: "fd-select-caret", onClick: toggle, children: /* @__PURE__ */ jsx47("i", { className: "ph ph-caret-down", "aria-hidden": "true" }) })
2934
3177
  ] }),
2935
3178
  open && pos ? createPortal4(
2936
- /* @__PURE__ */ jsxs39(
3179
+ /* @__PURE__ */ jsxs42(
2937
3180
  "div",
2938
3181
  {
2939
3182
  className: "fd-pop" + (pos.up ? " is-up" : ""),
2940
3183
  ref: popRef,
2941
3184
  style: popStyle(pos, { minWidth: Math.max(pos.width, 260), maxWidth: 380, zIndex: 130, overflowY: "hidden" }),
2942
3185
  children: [
2943
- hasSearch ? /* @__PURE__ */ jsxs39("div", { className: "fd-pop-search", children: [
2944
- /* @__PURE__ */ jsx44("i", { className: "ph ph-magnifying-glass", style: { color: "var(--text-muted)", fontSize: 14 } }),
2945
- /* @__PURE__ */ jsx44(
3186
+ hasSearch ? /* @__PURE__ */ jsxs42("div", { className: "fd-pop-search", children: [
3187
+ /* @__PURE__ */ jsx47("i", { className: "ph ph-magnifying-glass", style: { color: "var(--text-muted)", fontSize: 14 } }),
3188
+ /* @__PURE__ */ jsx47(
2946
3189
  "input",
2947
3190
  {
2948
3191
  autoFocus: true,
@@ -2955,15 +3198,15 @@ function Select({
2955
3198
  }
2956
3199
  }
2957
3200
  ),
2958
- q ? /* @__PURE__ */ jsx44("span", { className: "fd-body-sm fd-muted", children: visible.length }) : null
3201
+ q ? /* @__PURE__ */ jsx47("span", { className: "fd-body-sm fd-muted", children: visible.length }) : null
2959
3202
  ] }) : null,
2960
- /* @__PURE__ */ jsx44("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__ */ jsxs39("div", { className: "fd-pop-empty", children: [
3203
+ /* @__PURE__ */ jsx47("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__ */ jsxs42("div", { className: "fd-pop-empty", children: [
2961
3204
  'Nothing matches "',
2962
3205
  q,
2963
3206
  '".'
2964
- ] }) : groups.map((grp) => /* @__PURE__ */ jsxs39(React17.Fragment, { children: [
2965
- grp.g ? /* @__PURE__ */ jsx44("div", { className: "fd-pop-group", children: grp.g }) : null,
2966
- grp.items.map(({ o, i }) => /* @__PURE__ */ jsxs39(
3207
+ ] }) : groups.map((grp) => /* @__PURE__ */ jsxs42(React19.Fragment, { children: [
3208
+ grp.g ? /* @__PURE__ */ jsx47("div", { className: "fd-pop-group", children: grp.g }) : null,
3209
+ grp.items.map(({ o, i }) => /* @__PURE__ */ jsxs42(
2967
3210
  "button",
2968
3211
  {
2969
3212
  type: "button",
@@ -2975,21 +3218,21 @@ function Select({
2975
3218
  onMouseEnter: () => setActive(i),
2976
3219
  onClick: () => pick(o),
2977
3220
  children: [
2978
- multiple ? /* @__PURE__ */ jsx44("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__ */ jsx44("i", { className: "ph ph-check", style: { fontSize: 11 } }) : null }) : null,
2979
- o.icon ? /* @__PURE__ */ jsx44("span", { className: "fd-opt-icon", children: /* @__PURE__ */ jsx44("i", { className: "ph ph-" + o.icon }) }) : null,
2980
- /* @__PURE__ */ jsxs39("span", { style: { flex: 1, minWidth: 0 }, children: [
2981
- /* @__PURE__ */ jsx44("span", { className: "fd-opt-label", children: o.label }),
2982
- o.description ? /* @__PURE__ */ jsx44("span", { className: "fd-opt-desc", children: o.description }) : null
3221
+ multiple ? /* @__PURE__ */ jsx47("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__ */ jsx47("i", { className: "ph ph-check", style: { fontSize: 11 } }) : null }) : null,
3222
+ o.icon ? /* @__PURE__ */ jsx47("span", { className: "fd-opt-icon", children: /* @__PURE__ */ jsx47("i", { className: "ph ph-" + o.icon }) }) : null,
3223
+ /* @__PURE__ */ jsxs42("span", { style: { flex: 1, minWidth: 0 }, children: [
3224
+ /* @__PURE__ */ jsx47("span", { className: "fd-opt-label", children: o.label }),
3225
+ o.description ? /* @__PURE__ */ jsx47("span", { className: "fd-opt-desc", children: o.description }) : null
2983
3226
  ] }),
2984
- o.meta ? /* @__PURE__ */ jsx44("span", { className: "fd-opt-meta", children: o.meta }) : null,
2985
- multiple ? null : /* @__PURE__ */ jsx44("span", { className: "fd-opt-check", children: o.value === value ? /* @__PURE__ */ jsx44("i", { className: "ph ph-check" }) : null })
3227
+ o.meta ? /* @__PURE__ */ jsx47("span", { className: "fd-opt-meta", children: o.meta }) : null,
3228
+ multiple ? null : /* @__PURE__ */ jsx47("span", { className: "fd-opt-check", children: o.value === value ? /* @__PURE__ */ jsx47("i", { className: "ph ph-check" }) : null })
2986
3229
  ]
2987
3230
  },
2988
3231
  String(o.value)
2989
3232
  ))
2990
3233
  ] }, grp.g || "_")) }),
2991
- multiple ? /* @__PURE__ */ jsxs39("div", { className: "fd-row", style: { gap: 10, padding: "8px 12px", borderTop: "1px solid var(--border)" }, children: [
2992
- /* @__PURE__ */ jsx44(
3234
+ multiple ? /* @__PURE__ */ jsxs42("div", { className: "fd-row", style: { gap: 10, padding: "8px 12px", borderTop: "1px solid var(--border)" }, children: [
3235
+ /* @__PURE__ */ jsx47(
2993
3236
  "button",
2994
3237
  {
2995
3238
  type: "button",
@@ -2998,13 +3241,13 @@ function Select({
2998
3241
  children: "Select all"
2999
3242
  }
3000
3243
  ),
3001
- /* @__PURE__ */ jsx44("span", { style: { flex: 1 } }),
3002
- /* @__PURE__ */ jsxs39("span", { className: "fd-body-sm fd-muted", children: [
3244
+ /* @__PURE__ */ jsx47("span", { style: { flex: 1 } }),
3245
+ /* @__PURE__ */ jsxs42("span", { className: "fd-body-sm fd-muted", children: [
3003
3246
  vals.length,
3004
3247
  " of ",
3005
3248
  opts.length
3006
3249
  ] }),
3007
- /* @__PURE__ */ jsx44(
3250
+ /* @__PURE__ */ jsx47(
3008
3251
  "button",
3009
3252
  {
3010
3253
  type: "button",
@@ -3020,17 +3263,17 @@ function Select({
3020
3263
  ),
3021
3264
  document.body
3022
3265
  ) : null,
3023
- error ? /* @__PURE__ */ jsxs39("span", { className: "fd-field-error", children: [
3024
- /* @__PURE__ */ jsx44("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
3266
+ error ? /* @__PURE__ */ jsxs42("span", { className: "fd-field-error", children: [
3267
+ /* @__PURE__ */ jsx47("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
3025
3268
  error
3026
- ] }) : help ? /* @__PURE__ */ jsx44("span", { className: "fd-field-help", children: help }) : null
3269
+ ] }) : help ? /* @__PURE__ */ jsx47("span", { className: "fd-field-help", children: help }) : null
3027
3270
  ] });
3028
3271
  }
3029
3272
 
3030
3273
  // src/components/forms/DatePicker.tsx
3031
- import * as React18 from "react";
3274
+ import * as React20 from "react";
3032
3275
  import { createPortal as createPortal5 } from "react-dom";
3033
- import { jsx as jsx45, jsxs as jsxs40 } from "react/jsx-runtime";
3276
+ import { jsx as jsx48, jsxs as jsxs43 } from "react/jsx-runtime";
3034
3277
  var MONTHS = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
3035
3278
  var DOW = ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"];
3036
3279
  var iso = (d) => d.getFullYear() + "-" + String(d.getMonth() + 1).padStart(2, "0") + "-" + String(d.getDate()).padStart(2, "0");
@@ -3044,8 +3287,8 @@ var fmt = (s) => {
3044
3287
  return d ? MONTHS[d.getMonth()].slice(0, 3) + " " + d.getDate() + ", " + d.getFullYear() : "";
3045
3288
  };
3046
3289
  function usePopPos2(open, ref, estH, estW) {
3047
- const [pos, setPos] = React18.useState(null);
3048
- React18.useLayoutEffect(() => {
3290
+ const [pos, setPos] = React20.useState(null);
3291
+ React20.useLayoutEffect(() => {
3049
3292
  if (!open || !ref.current) {
3050
3293
  setPos(null);
3051
3294
  return;
@@ -3089,10 +3332,10 @@ function Calendar({ value, range = false, onPick, initialMonth, months = 1 }) {
3089
3332
  const today = /* @__PURE__ */ new Date();
3090
3333
  const sel = range ? value || {} : { start: value, end: value };
3091
3334
  const anchor = parse(sel.start) || parse(initialMonth) || today;
3092
- const [vy, setVy] = React18.useState(anchor.getFullYear());
3093
- const [vm, setVm] = React18.useState(anchor.getMonth());
3094
- const [mode2, setMode] = React18.useState("days");
3095
- const [hover, setHover] = React18.useState(null);
3335
+ const [vy, setVy] = React20.useState(anchor.getFullYear());
3336
+ const [vm, setVm] = React20.useState(anchor.getMonth());
3337
+ const [mode2, setMode] = React20.useState("days");
3338
+ const [hover, setHover] = React20.useState(null);
3096
3339
  const s = parse(sel.start), e = parse(sel.end);
3097
3340
  const hoverEnd = range && s && !e && hover ? parse(hover) : null;
3098
3341
  const inRange = (d) => {
@@ -3129,9 +3372,9 @@ function Calendar({ value, range = false, onPick, initialMonth, months = 1 }) {
3129
3372
  const startPad = new Date(y, m, 1).getDay();
3130
3373
  const cells = [];
3131
3374
  for (let i = 0; i < 42; i++) cells.push(new Date(y, m, i - startPad + 1));
3132
- return /* @__PURE__ */ jsxs40("div", { className: "fd-cal-grid", style: { width: months > 1 ? 252 : "auto", flex: "none" }, onMouseLeave: () => setHover(null), children: [
3133
- DOW.map((d) => /* @__PURE__ */ jsx45("span", { className: "fd-cal-dow", children: d }, d)),
3134
- cells.map((d, i) => /* @__PURE__ */ jsx45(
3375
+ return /* @__PURE__ */ jsxs43("div", { className: "fd-cal-grid", style: { width: months > 1 ? 252 : "auto", flex: "none" }, onMouseLeave: () => setHover(null), children: [
3376
+ DOW.map((d) => /* @__PURE__ */ jsx48("span", { className: "fd-cal-dow", children: d }, d)),
3377
+ cells.map((d, i) => /* @__PURE__ */ jsx48(
3135
3378
  "button",
3136
3379
  {
3137
3380
  type: "button",
@@ -3145,20 +3388,20 @@ function Calendar({ value, range = false, onPick, initialMonth, months = 1 }) {
3145
3388
  ] });
3146
3389
  };
3147
3390
  const nextY = vm === 11 ? vy + 1 : vy, nextM = (vm + 1) % 12;
3148
- return /* @__PURE__ */ jsxs40("div", { className: "fd-cal", style: { width: months > 1 && mode2 === "days" ? "auto" : void 0 }, children: [
3149
- /* @__PURE__ */ jsxs40("div", { className: "fd-cal-head", children: [
3150
- /* @__PURE__ */ jsx45("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__ */ jsx45("i", { className: "ph ph-caret-left" }) }),
3151
- /* @__PURE__ */ jsxs40("button", { type: "button", className: "fd-cal-title", onClick: () => setMode(mode2 === "days" ? "months" : mode2 === "months" ? "years" : "days"), children: [
3391
+ return /* @__PURE__ */ jsxs43("div", { className: "fd-cal", style: { width: months > 1 && mode2 === "days" ? "auto" : void 0 }, children: [
3392
+ /* @__PURE__ */ jsxs43("div", { className: "fd-cal-head", children: [
3393
+ /* @__PURE__ */ jsx48("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__ */ jsx48("i", { className: "ph ph-caret-left" }) }),
3394
+ /* @__PURE__ */ jsxs43("button", { type: "button", className: "fd-cal-title", onClick: () => setMode(mode2 === "days" ? "months" : mode2 === "months" ? "years" : "days"), children: [
3152
3395
  mode2 === "days" ? MONTHS[vm] + " " + vy : mode2 === "months" ? vy : vy - 5 + " \u2013 " + (vy + 6),
3153
- /* @__PURE__ */ jsx45("i", { className: "ph ph-caret-down", style: { fontSize: 10, marginLeft: 6, color: "var(--text-muted)" } })
3396
+ /* @__PURE__ */ jsx48("i", { className: "ph ph-caret-down", style: { fontSize: 10, marginLeft: 6, color: "var(--text-muted)" } })
3154
3397
  ] }),
3155
- months > 1 && mode2 === "days" ? /* @__PURE__ */ jsx45("span", { className: "fd-cal-title", style: { cursor: "default", background: "none" }, children: MONTHS[nextM] + " " + nextY }) : null,
3156
- /* @__PURE__ */ jsx45("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__ */ jsx45("i", { className: "ph ph-caret-right" }) })
3398
+ months > 1 && mode2 === "days" ? /* @__PURE__ */ jsx48("span", { className: "fd-cal-title", style: { cursor: "default", background: "none" }, children: MONTHS[nextM] + " " + nextY }) : null,
3399
+ /* @__PURE__ */ jsx48("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__ */ jsx48("i", { className: "ph ph-caret-right" }) })
3157
3400
  ] }),
3158
- mode2 === "days" ? /* @__PURE__ */ jsxs40("div", { style: { display: "flex", gap: 18 }, children: [
3401
+ mode2 === "days" ? /* @__PURE__ */ jsxs43("div", { style: { display: "flex", gap: 18 }, children: [
3159
3402
  monthGrid(vy, vm),
3160
3403
  months > 1 ? monthGrid(nextY, nextM) : null
3161
- ] }) : mode2 === "months" ? /* @__PURE__ */ jsx45("div", { className: "fd-cal-grid-months", children: MONTHS.map((m, i) => /* @__PURE__ */ jsx45(
3404
+ ] }) : mode2 === "months" ? /* @__PURE__ */ jsx48("div", { className: "fd-cal-grid-months", children: MONTHS.map((m, i) => /* @__PURE__ */ jsx48(
3162
3405
  "button",
3163
3406
  {
3164
3407
  type: "button",
@@ -3170,7 +3413,7 @@ function Calendar({ value, range = false, onPick, initialMonth, months = 1 }) {
3170
3413
  children: m.slice(0, 3)
3171
3414
  },
3172
3415
  m
3173
- )) }) : /* @__PURE__ */ jsx45("div", { className: "fd-cal-grid-months", children: Array.from({ length: 12 }, (_, i) => vy - 5 + i).map((y) => /* @__PURE__ */ jsx45(
3416
+ )) }) : /* @__PURE__ */ jsx48("div", { className: "fd-cal-grid-months", children: Array.from({ length: 12 }, (_, i) => vy - 5 + i).map((y) => /* @__PURE__ */ jsx48(
3174
3417
  "button",
3175
3418
  {
3176
3419
  type: "button",
@@ -3183,8 +3426,8 @@ function Calendar({ value, range = false, onPick, initialMonth, months = 1 }) {
3183
3426
  },
3184
3427
  y
3185
3428
  )) }),
3186
- /* @__PURE__ */ jsxs40("div", { className: "fd-cal-foot", children: [
3187
- /* @__PURE__ */ jsx45(
3429
+ /* @__PURE__ */ jsxs43("div", { className: "fd-cal-foot", children: [
3430
+ /* @__PURE__ */ jsx48(
3188
3431
  "button",
3189
3432
  {
3190
3433
  type: "button",
@@ -3198,8 +3441,8 @@ function Calendar({ value, range = false, onPick, initialMonth, months = 1 }) {
3198
3441
  children: "Today"
3199
3442
  }
3200
3443
  ),
3201
- /* @__PURE__ */ jsx45("span", { style: { flex: 1 } }),
3202
- range && sel.start ? /* @__PURE__ */ jsxs40("span", { className: "fd-body-sm fd-muted", children: [
3444
+ /* @__PURE__ */ jsx48("span", { style: { flex: 1 } }),
3445
+ range && sel.start ? /* @__PURE__ */ jsxs43("span", { className: "fd-body-sm fd-muted", children: [
3203
3446
  fmt(sel.start),
3204
3447
  sel.end ? " \u2192 " + fmt(sel.end) : " \u2192 pick an end"
3205
3448
  ] }) : null
@@ -3207,12 +3450,12 @@ function Calendar({ value, range = false, onPick, initialMonth, months = 1 }) {
3207
3450
  ] });
3208
3451
  }
3209
3452
  function DatePicker({ label, help, error, required = false, disabled = false, range = false, value, onChange, placeholder, className = "", style, ...rest }) {
3210
- const [open, setOpen] = React18.useState(false);
3211
- const rootRef = React18.useRef(null);
3212
- const boxRef = React18.useRef(null);
3213
- const popRef = React18.useRef(null);
3453
+ const [open, setOpen] = React20.useState(false);
3454
+ const rootRef = React20.useRef(null);
3455
+ const boxRef = React20.useRef(null);
3456
+ const popRef = React20.useRef(null);
3214
3457
  const pos = usePopPos2(open, boxRef, 430, range ? 600 : 316);
3215
- React18.useEffect(() => {
3458
+ React20.useEffect(() => {
3216
3459
  if (!open) return;
3217
3460
  const away = (e) => {
3218
3461
  if (rootRef.current && rootRef.current.contains(e.target)) return;
@@ -3233,14 +3476,14 @@ function DatePicker({ label, help, error, required = false, disabled = false, ra
3233
3476
  const toggle = () => {
3234
3477
  if (!disabled) setOpen(!open);
3235
3478
  };
3236
- return /* @__PURE__ */ jsxs40("div", { className: ["fd-field", "fd-popfield", open ? "is-open" : "", className].filter(Boolean).join(" "), style, ref: rootRef, children: [
3237
- label ? /* @__PURE__ */ jsxs40("label", { className: "fd-field-label", onClick: toggle, children: [
3479
+ return /* @__PURE__ */ jsxs43("div", { className: ["fd-field", "fd-popfield", open ? "is-open" : "", className].filter(Boolean).join(" "), style, ref: rootRef, children: [
3480
+ label ? /* @__PURE__ */ jsxs43("label", { className: "fd-field-label", onClick: toggle, children: [
3238
3481
  label,
3239
- required ? /* @__PURE__ */ jsx45("span", { className: "fd-field-req", children: "*" }) : null
3482
+ required ? /* @__PURE__ */ jsx48("span", { className: "fd-field-req", children: "*" }) : null
3240
3483
  ] }) : null,
3241
- /* @__PURE__ */ jsxs40("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: [
3242
- /* @__PURE__ */ jsx45("span", { className: "fd-input-icon", children: /* @__PURE__ */ jsx45("i", { className: "ph ph-calendar-blank", "aria-hidden": "true" }) }),
3243
- /* @__PURE__ */ jsx45(
3484
+ /* @__PURE__ */ jsxs43("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: [
3485
+ /* @__PURE__ */ jsx48("span", { className: "fd-input-icon", children: /* @__PURE__ */ jsx48("i", { className: "ph ph-calendar-blank", "aria-hidden": "true" }) }),
3486
+ /* @__PURE__ */ jsx48(
3244
3487
  "button",
3245
3488
  {
3246
3489
  type: "button",
@@ -3256,10 +3499,10 @@ function DatePicker({ label, help, error, required = false, disabled = false, ra
3256
3499
  children: display || placeholder || (range ? "Pick a date range" : "Pick a date")
3257
3500
  }
3258
3501
  ),
3259
- /* @__PURE__ */ jsx45("span", { className: "fd-select-caret", children: /* @__PURE__ */ jsx45("i", { className: "ph ph-caret-down", "aria-hidden": "true" }) })
3502
+ /* @__PURE__ */ jsx48("span", { className: "fd-select-caret", children: /* @__PURE__ */ jsx48("i", { className: "ph ph-caret-down", "aria-hidden": "true" }) })
3260
3503
  ] }),
3261
3504
  open && pos ? createPortal5(
3262
- /* @__PURE__ */ jsx45("div", { className: "fd-pop" + (pos.up ? " is-up" : ""), ref: popRef, style: popStyle2(pos, { width: "max-content", minWidth: 0, zIndex: 130 }), children: /* @__PURE__ */ jsx45(
3505
+ /* @__PURE__ */ jsx48("div", { className: "fd-pop" + (pos.up ? " is-up" : ""), ref: popRef, style: popStyle2(pos, { width: "max-content", minWidth: 0, zIndex: 130 }), children: /* @__PURE__ */ jsx48(
3263
3506
  Calendar,
3264
3507
  {
3265
3508
  range,
@@ -3273,21 +3516,21 @@ function DatePicker({ label, help, error, required = false, disabled = false, ra
3273
3516
  ) }),
3274
3517
  document.body
3275
3518
  ) : null,
3276
- error ? /* @__PURE__ */ jsxs40("span", { className: "fd-field-error", children: [
3277
- /* @__PURE__ */ jsx45("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
3519
+ error ? /* @__PURE__ */ jsxs43("span", { className: "fd-field-error", children: [
3520
+ /* @__PURE__ */ jsx48("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
3278
3521
  error
3279
- ] }) : help ? /* @__PURE__ */ jsx45("span", { className: "fd-field-help", children: help }) : null
3522
+ ] }) : help ? /* @__PURE__ */ jsx48("span", { className: "fd-field-help", children: help }) : null
3280
3523
  ] });
3281
3524
  }
3282
3525
 
3283
3526
  // src/components/forms/TimePicker.tsx
3284
- import * as React19 from "react";
3527
+ import * as React21 from "react";
3285
3528
  import { createPortal as createPortal6 } from "react-dom";
3286
- import { jsx as jsx46, jsxs as jsxs41 } from "react/jsx-runtime";
3529
+ import { jsx as jsx49, jsxs as jsxs44 } from "react/jsx-runtime";
3287
3530
  var pad = (n) => String(n).padStart(2, "0");
3288
3531
  function usePopPos3(open, ref, estH, estW) {
3289
- const [pos, setPos] = React19.useState(null);
3290
- React19.useLayoutEffect(() => {
3532
+ const [pos, setPos] = React21.useState(null);
3533
+ React21.useLayoutEffect(() => {
3291
3534
  if (!open || !ref.current) {
3292
3535
  setPos(null);
3293
3536
  return;
@@ -3333,9 +3576,9 @@ function ClockFace({ value = "09:00", onChange }) {
3333
3576
  if (isNaN(m)) m = 0;
3334
3577
  const pm = h24 >= 12;
3335
3578
  const h12 = h24 % 12 === 0 ? 12 : h24 % 12;
3336
- const [mode2, setMode] = React19.useState("h");
3337
- const faceRef = React19.useRef(null);
3338
- const dragging = React19.useRef(false);
3579
+ const [mode2, setMode] = React21.useState("h");
3580
+ const faceRef = React21.useRef(null);
3581
+ const dragging = React21.useRef(false);
3339
3582
  const set = (h, mm, isPm) => onChange((isPm ? h % 12 + 12 : h % 12) + ":" + pad(mm));
3340
3583
  const R = 108, NR = 80;
3341
3584
  const nums = mode2 === "h" ? Array.from({ length: 12 }, (_, i) => i + 1) : Array.from({ length: 12 }, (_, i) => i * 5);
@@ -3370,12 +3613,12 @@ function ClockFace({ value = "09:00", onChange }) {
3370
3613
  };
3371
3614
  const handAngle = mode2 === "h" ? h12 % 12 * 30 : m * 6;
3372
3615
  const minuteOff = mode2 === "m" && m % 5 !== 0;
3373
- return /* @__PURE__ */ jsxs41("div", { style: { padding: "4px 14px 14px" }, children: [
3374
- /* @__PURE__ */ jsxs41("div", { className: "fd-clock-digits", children: [
3375
- /* @__PURE__ */ jsx46("button", { type: "button", className: "fd-clock-digit" + (mode2 === "h" ? " is-active" : ""), onClick: () => setMode("h"), children: pad(h12) }),
3376
- /* @__PURE__ */ jsx46("span", { style: { fontSize: 24, fontWeight: 700, color: "var(--text-muted)" }, children: ":" }),
3377
- /* @__PURE__ */ jsx46("button", { type: "button", className: "fd-clock-digit" + (mode2 === "m" ? " is-active" : ""), onClick: () => setMode("m"), children: pad(m) }),
3378
- /* @__PURE__ */ jsx46("span", { className: "fd-stack", style: { gap: 3, marginLeft: 8 }, children: ["AM", "PM"].map((ap) => /* @__PURE__ */ jsx46(
3616
+ return /* @__PURE__ */ jsxs44("div", { style: { padding: "4px 14px 14px" }, children: [
3617
+ /* @__PURE__ */ jsxs44("div", { className: "fd-clock-digits", children: [
3618
+ /* @__PURE__ */ jsx49("button", { type: "button", className: "fd-clock-digit" + (mode2 === "h" ? " is-active" : ""), onClick: () => setMode("h"), children: pad(h12) }),
3619
+ /* @__PURE__ */ jsx49("span", { style: { fontSize: 24, fontWeight: 700, color: "var(--text-muted)" }, children: ":" }),
3620
+ /* @__PURE__ */ jsx49("button", { type: "button", className: "fd-clock-digit" + (mode2 === "m" ? " is-active" : ""), onClick: () => setMode("m"), children: pad(m) }),
3621
+ /* @__PURE__ */ jsx49("span", { className: "fd-stack", style: { gap: 3, marginLeft: 8 }, children: ["AM", "PM"].map((ap) => /* @__PURE__ */ jsx49(
3379
3622
  "button",
3380
3623
  {
3381
3624
  type: "button",
@@ -3386,13 +3629,13 @@ function ClockFace({ value = "09:00", onChange }) {
3386
3629
  ap
3387
3630
  )) })
3388
3631
  ] }),
3389
- /* @__PURE__ */ jsxs41("div", { className: "fd-clock", ref: faceRef, onPointerDown: down, onPointerMove: move, onPointerUp: upH, children: [
3390
- /* @__PURE__ */ jsx46("span", { className: "fd-clock-hand", style: { height: NR - (minuteOff ? 14 : 16), transform: "translateX(-50%) rotate(" + handAngle + "deg)", bottom: "50%" } }),
3391
- /* @__PURE__ */ jsx46("span", { className: "fd-clock-pivot" }),
3392
- minuteOff ? /* @__PURE__ */ jsx46("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,
3632
+ /* @__PURE__ */ jsxs44("div", { className: "fd-clock", ref: faceRef, onPointerDown: down, onPointerMove: move, onPointerUp: upH, children: [
3633
+ /* @__PURE__ */ jsx49("span", { className: "fd-clock-hand", style: { height: NR - (minuteOff ? 14 : 16), transform: "translateX(-50%) rotate(" + handAngle + "deg)", bottom: "50%" } }),
3634
+ /* @__PURE__ */ jsx49("span", { className: "fd-clock-pivot" }),
3635
+ minuteOff ? /* @__PURE__ */ jsx49("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,
3393
3636
  nums.map((n) => {
3394
3637
  const a = angleOf(n) * Math.PI / 180;
3395
- return /* @__PURE__ */ jsx46(
3638
+ return /* @__PURE__ */ jsx49(
3396
3639
  "span",
3397
3640
  {
3398
3641
  className: "fd-clock-num" + (n === selNum || mode2 === "m" && n === Math.round(m / 5) * 5 % 60 && m % 5 === 0 ? " is-sel" : ""),
@@ -3403,16 +3646,16 @@ function ClockFace({ value = "09:00", onChange }) {
3403
3646
  );
3404
3647
  })
3405
3648
  ] }),
3406
- /* @__PURE__ */ jsx46("div", { className: "fd-row", style: { justifyContent: "center", gap: 6 }, children: /* @__PURE__ */ jsx46("span", { className: "fd-body-sm fd-muted", children: mode2 === "h" ? "Pick the hour \u2014 drag or tap" : "Now the minutes" }) })
3649
+ /* @__PURE__ */ jsx49("div", { className: "fd-row", style: { justifyContent: "center", gap: 6 }, children: /* @__PURE__ */ jsx49("span", { className: "fd-body-sm fd-muted", children: mode2 === "h" ? "Pick the hour \u2014 drag or tap" : "Now the minutes" }) })
3407
3650
  ] });
3408
3651
  }
3409
3652
  function TimePicker({ label, help, error, required = false, disabled = false, value = "", onChange, placeholder = "Pick a time", className = "", style }) {
3410
- const [open, setOpen] = React19.useState(false);
3411
- const rootRef = React19.useRef(null);
3412
- const boxRef = React19.useRef(null);
3413
- const popRef = React19.useRef(null);
3653
+ const [open, setOpen] = React21.useState(false);
3654
+ const rootRef = React21.useRef(null);
3655
+ const boxRef = React21.useRef(null);
3656
+ const popRef = React21.useRef(null);
3414
3657
  const pos = usePopPos3(open, boxRef, 420, 262);
3415
- React19.useEffect(() => {
3658
+ React21.useEffect(() => {
3416
3659
  if (!open) return;
3417
3660
  const away = (e) => {
3418
3661
  if (rootRef.current && rootRef.current.contains(e.target)) return;
@@ -3437,14 +3680,14 @@ function TimePicker({ label, help, error, required = false, disabled = false, va
3437
3680
  const toggle = () => {
3438
3681
  if (!disabled) setOpen(!open);
3439
3682
  };
3440
- return /* @__PURE__ */ jsxs41("div", { className: ["fd-field", "fd-popfield", open ? "is-open" : "", className].filter(Boolean).join(" "), style, ref: rootRef, children: [
3441
- label ? /* @__PURE__ */ jsxs41("label", { className: "fd-field-label", onClick: toggle, children: [
3683
+ return /* @__PURE__ */ jsxs44("div", { className: ["fd-field", "fd-popfield", open ? "is-open" : "", className].filter(Boolean).join(" "), style, ref: rootRef, children: [
3684
+ label ? /* @__PURE__ */ jsxs44("label", { className: "fd-field-label", onClick: toggle, children: [
3442
3685
  label,
3443
- required ? /* @__PURE__ */ jsx46("span", { className: "fd-field-req", children: "*" }) : null
3686
+ required ? /* @__PURE__ */ jsx49("span", { className: "fd-field-req", children: "*" }) : null
3444
3687
  ] }) : null,
3445
- /* @__PURE__ */ jsxs41("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: [
3446
- /* @__PURE__ */ jsx46("span", { className: "fd-input-icon", children: /* @__PURE__ */ jsx46("i", { className: "ph ph-clock", "aria-hidden": "true" }) }),
3447
- /* @__PURE__ */ jsx46(
3688
+ /* @__PURE__ */ jsxs44("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: [
3689
+ /* @__PURE__ */ jsx49("span", { className: "fd-input-icon", children: /* @__PURE__ */ jsx49("i", { className: "ph ph-clock", "aria-hidden": "true" }) }),
3690
+ /* @__PURE__ */ jsx49(
3448
3691
  "button",
3449
3692
  {
3450
3693
  type: "button",
@@ -3459,13 +3702,13 @@ function TimePicker({ label, help, error, required = false, disabled = false, va
3459
3702
  children: disp() || placeholder
3460
3703
  }
3461
3704
  ),
3462
- /* @__PURE__ */ jsx46("span", { className: "fd-select-caret", children: /* @__PURE__ */ jsx46("i", { className: "ph ph-caret-down", "aria-hidden": "true" }) })
3705
+ /* @__PURE__ */ jsx49("span", { className: "fd-select-caret", children: /* @__PURE__ */ jsx49("i", { className: "ph ph-caret-down", "aria-hidden": "true" }) })
3463
3706
  ] }),
3464
3707
  open && pos ? createPortal6(
3465
- /* @__PURE__ */ jsxs41("div", { className: "fd-pop" + (pos.up ? " is-up" : ""), ref: popRef, style: popStyle3(pos, { width: 262, minWidth: 0, zIndex: 130 }), children: [
3466
- /* @__PURE__ */ jsx46(ClockFace, { value: value || "09:00", onChange: (v) => onChange && onChange({ target: { value: v } }) }),
3467
- /* @__PURE__ */ jsxs41("div", { className: "fd-cal-foot", style: { margin: "0 14px 12px", paddingTop: 10 }, children: [
3468
- /* @__PURE__ */ jsx46(
3708
+ /* @__PURE__ */ jsxs44("div", { className: "fd-pop" + (pos.up ? " is-up" : ""), ref: popRef, style: popStyle3(pos, { width: 262, minWidth: 0, zIndex: 130 }), children: [
3709
+ /* @__PURE__ */ jsx49(ClockFace, { value: value || "09:00", onChange: (v) => onChange && onChange({ target: { value: v } }) }),
3710
+ /* @__PURE__ */ jsxs44("div", { className: "fd-cal-foot", style: { margin: "0 14px 12px", paddingTop: 10 }, children: [
3711
+ /* @__PURE__ */ jsx49(
3469
3712
  "button",
3470
3713
  {
3471
3714
  type: "button",
@@ -3478,22 +3721,22 @@ function TimePicker({ label, help, error, required = false, disabled = false, va
3478
3721
  children: "Now"
3479
3722
  }
3480
3723
  ),
3481
- /* @__PURE__ */ jsx46("span", { style: { flex: 1 } }),
3482
- /* @__PURE__ */ jsx46("button", { type: "button", className: "fd-btn fd-btn-primary fd-btn-sm", onClick: () => setOpen(false), children: "Done" })
3724
+ /* @__PURE__ */ jsx49("span", { style: { flex: 1 } }),
3725
+ /* @__PURE__ */ jsx49("button", { type: "button", className: "fd-btn fd-btn-primary fd-btn-sm", onClick: () => setOpen(false), children: "Done" })
3483
3726
  ] })
3484
3727
  ] }),
3485
3728
  document.body
3486
3729
  ) : null,
3487
- error ? /* @__PURE__ */ jsxs41("span", { className: "fd-field-error", children: [
3488
- /* @__PURE__ */ jsx46("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
3730
+ error ? /* @__PURE__ */ jsxs44("span", { className: "fd-field-error", children: [
3731
+ /* @__PURE__ */ jsx49("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
3489
3732
  error
3490
- ] }) : help ? /* @__PURE__ */ jsx46("span", { className: "fd-field-help", children: help }) : null
3733
+ ] }) : help ? /* @__PURE__ */ jsx49("span", { className: "fd-field-help", children: help }) : null
3491
3734
  ] });
3492
3735
  }
3493
3736
 
3494
3737
  // src/components/forms/Slider.tsx
3495
- import * as React20 from "react";
3496
- import { jsx as jsx47, jsxs as jsxs42 } from "react/jsx-runtime";
3738
+ import * as React22 from "react";
3739
+ import { jsx as jsx50, jsxs as jsxs45 } from "react/jsx-runtime";
3497
3740
  function Slider({
3498
3741
  label,
3499
3742
  min = 0,
@@ -3507,18 +3750,18 @@ function Slider({
3507
3750
  className = "",
3508
3751
  ...rest
3509
3752
  }) {
3510
- const [dragging, setDragging] = React20.useState(false);
3753
+ const [dragging, setDragging] = React22.useState(false);
3511
3754
  const v = value === void 0 ? min : Number(value);
3512
3755
  const pct = max === min ? 0 : (v - min) / (max - min) * 100;
3513
- return /* @__PURE__ */ jsxs42("div", { className: ["fd-field", className].filter(Boolean).join(" "), children: [
3514
- label ? /* @__PURE__ */ jsxs42("div", { className: "fd-row", style: { justifyContent: "space-between", gap: 12 }, children: [
3515
- /* @__PURE__ */ jsx47("span", { className: "fd-field-label", children: label }),
3516
- /* @__PURE__ */ jsx47("span", { className: "fd-num", style: { color: "var(--text-2)" }, children: format(v) })
3756
+ return /* @__PURE__ */ jsxs45("div", { className: ["fd-field", className].filter(Boolean).join(" "), children: [
3757
+ label ? /* @__PURE__ */ jsxs45("div", { className: "fd-row", style: { justifyContent: "space-between", gap: 12 }, children: [
3758
+ /* @__PURE__ */ jsx50("span", { className: "fd-field-label", children: label }),
3759
+ /* @__PURE__ */ jsx50("span", { className: "fd-num", style: { color: "var(--text-2)" }, children: format(v) })
3517
3760
  ] }) : null,
3518
- /* @__PURE__ */ jsxs42("div", { className: "fd-slider", children: [
3519
- /* @__PURE__ */ jsx47("span", { className: "fd-slider-fill", style: { width: pct + "%" } }),
3520
- showChip && dragging ? /* @__PURE__ */ jsx47("span", { className: "fd-slider-chip", style: { left: pct + "%" }, children: format(v) }) : null,
3521
- /* @__PURE__ */ jsx47(
3761
+ /* @__PURE__ */ jsxs45("div", { className: "fd-slider", children: [
3762
+ /* @__PURE__ */ jsx50("span", { className: "fd-slider-fill", style: { width: pct + "%" } }),
3763
+ showChip && dragging ? /* @__PURE__ */ jsx50("span", { className: "fd-slider-chip", style: { left: pct + "%" }, children: format(v) }) : null,
3764
+ /* @__PURE__ */ jsx50(
3522
3765
  "input",
3523
3766
  {
3524
3767
  type: "range",
@@ -3535,13 +3778,13 @@ function Slider({
3535
3778
  }
3536
3779
  )
3537
3780
  ] }),
3538
- help ? /* @__PURE__ */ jsx47("span", { className: "fd-field-help", children: help }) : null
3781
+ help ? /* @__PURE__ */ jsx50("span", { className: "fd-field-help", children: help }) : null
3539
3782
  ] });
3540
3783
  }
3541
3784
 
3542
3785
  // src/components/forms/RangeSlider.tsx
3543
- import * as React21 from "react";
3544
- import { jsx as jsx48, jsxs as jsxs43 } from "react/jsx-runtime";
3786
+ import * as React23 from "react";
3787
+ import { jsx as jsx51, jsxs as jsxs46 } from "react/jsx-runtime";
3545
3788
  function RangeSlider({
3546
3789
  label,
3547
3790
  min = 0,
@@ -3560,9 +3803,9 @@ function RangeSlider({
3560
3803
  }) {
3561
3804
  const fmt2 = format || ((v) => String(v));
3562
3805
  const [a, b] = value || [min, max];
3563
- const [drag, setDrag] = React21.useState(null);
3564
- const [focus, setFocus] = React21.useState(null);
3565
- const railRef = React21.useRef(null);
3806
+ const [drag, setDrag] = React23.useState(null);
3807
+ const [focus, setFocus] = React23.useState(null);
3808
+ const railRef = React23.useRef(null);
3566
3809
  const pct = (v) => max === min ? 0 : (v - min) / (max - min) * 100;
3567
3810
  const clampPair = (i, v) => {
3568
3811
  v = Math.min(max, Math.max(min, Math.round(v / step) * step));
@@ -3577,7 +3820,7 @@ function RangeSlider({
3577
3820
  const r = railRef.current.getBoundingClientRect();
3578
3821
  return min + Math.min(1, Math.max(0, (e.clientX - r.left) / r.width)) * (max - min);
3579
3822
  };
3580
- React21.useEffect(() => {
3823
+ React23.useEffect(() => {
3581
3824
  if (drag === null) return;
3582
3825
  const mv = (e) => onChange && onChange(clampPair(drag, fromEvent(e)));
3583
3826
  const upH = () => setDrag(null);
@@ -3598,7 +3841,7 @@ function RangeSlider({
3598
3841
  };
3599
3842
  const thin = S.length > 7 ? Math.ceil(S.length / 5) : 1;
3600
3843
  const pair = value || [S[0].value, S[S.length - 1].value];
3601
- return /* @__PURE__ */ jsx48(
3844
+ return /* @__PURE__ */ jsx51(
3602
3845
  RangeSlider,
3603
3846
  {
3604
3847
  ...rest,
@@ -3646,23 +3889,23 @@ function RangeSlider({
3646
3889
  };
3647
3890
  const showChip = (i) => drag === i || focus === i;
3648
3891
  const hasLabels = marks.some((m) => m.label);
3649
- return /* @__PURE__ */ jsxs43("div", { className: ["fd-field", className].filter(Boolean).join(" "), ...rest, children: [
3650
- label ? /* @__PURE__ */ jsxs43("div", { className: "fd-row", style: { justifyContent: "space-between", gap: 12 }, children: [
3651
- /* @__PURE__ */ jsx48("span", { className: "fd-field-label", children: label }),
3652
- /* @__PURE__ */ jsxs43("span", { className: "fd-num", style: { color: "var(--text-2)" }, children: [
3892
+ return /* @__PURE__ */ jsxs46("div", { className: ["fd-field", className].filter(Boolean).join(" "), ...rest, children: [
3893
+ label ? /* @__PURE__ */ jsxs46("div", { className: "fd-row", style: { justifyContent: "space-between", gap: 12 }, children: [
3894
+ /* @__PURE__ */ jsx51("span", { className: "fd-field-label", children: label }),
3895
+ /* @__PURE__ */ jsxs46("span", { className: "fd-num", style: { color: "var(--text-2)" }, children: [
3653
3896
  fmt2(a),
3654
3897
  " \u2013 ",
3655
3898
  fmt2(b)
3656
3899
  ] })
3657
3900
  ] }) : null,
3658
- /* @__PURE__ */ jsxs43("div", { className: "fd-range" + (hasLabels ? " has-labels" : ""), onPointerDown: onRailDown, children: [
3659
- /* @__PURE__ */ jsx48("span", { className: "fd-range-rail", ref: railRef }),
3660
- /* @__PURE__ */ jsx48("span", { className: "fd-range-fill", style: { left: pct(a) + "%", width: pct(b) - pct(a) + "%" } }),
3661
- marks.map((m) => /* @__PURE__ */ jsxs43(React21.Fragment, { children: [
3662
- /* @__PURE__ */ jsx48("span", { className: "fd-range-mark" + (m.value >= a && m.value <= b ? " is-in" : ""), style: { left: pct(m.value) + "%" } }),
3663
- m.label ? /* @__PURE__ */ jsx48("span", { className: "fd-range-mark-label", style: { left: pct(m.value) + "%" }, children: m.label }) : null
3901
+ /* @__PURE__ */ jsxs46("div", { className: "fd-range" + (hasLabels ? " has-labels" : ""), onPointerDown: onRailDown, children: [
3902
+ /* @__PURE__ */ jsx51("span", { className: "fd-range-rail", ref: railRef }),
3903
+ /* @__PURE__ */ jsx51("span", { className: "fd-range-fill", style: { left: pct(a) + "%", width: pct(b) - pct(a) + "%" } }),
3904
+ marks.map((m) => /* @__PURE__ */ jsxs46(React23.Fragment, { children: [
3905
+ /* @__PURE__ */ jsx51("span", { className: "fd-range-mark" + (m.value >= a && m.value <= b ? " is-in" : ""), style: { left: pct(m.value) + "%" } }),
3906
+ m.label ? /* @__PURE__ */ jsx51("span", { className: "fd-range-mark-label", style: { left: pct(m.value) + "%" }, children: m.label }) : null
3664
3907
  ] }, m.value)),
3665
- [a, b].map((v, i) => /* @__PURE__ */ jsx48(
3908
+ [a, b].map((v, i) => /* @__PURE__ */ jsx51(
3666
3909
  "span",
3667
3910
  {
3668
3911
  className: "fd-range-thumb" + (drag === i ? " is-drag" : ""),
@@ -3677,18 +3920,18 @@ function RangeSlider({
3677
3920
  onKeyDown: key(i),
3678
3921
  onFocus: () => setFocus(i),
3679
3922
  onBlur: () => setFocus(null),
3680
- children: /* @__PURE__ */ jsx48("span", { className: "fd-range-chip", style: { opacity: showChip(i) ? 1 : void 0 }, children: fmt2(v) })
3923
+ children: /* @__PURE__ */ jsx51("span", { className: "fd-range-chip", style: { opacity: showChip(i) ? 1 : void 0 }, children: fmt2(v) })
3681
3924
  },
3682
3925
  i
3683
3926
  ))
3684
3927
  ] }),
3685
- help ? /* @__PURE__ */ jsx48("span", { className: "fd-field-help", children: help }) : null
3928
+ help ? /* @__PURE__ */ jsx51("span", { className: "fd-field-help", children: help }) : null
3686
3929
  ] });
3687
3930
  }
3688
3931
 
3689
3932
  // src/components/forms/Dropzone.tsx
3690
- import * as React22 from "react";
3691
- import { jsx as jsx49, jsxs as jsxs44 } from "react/jsx-runtime";
3933
+ import * as React24 from "react";
3934
+ import { jsx as jsx52, jsxs as jsxs47 } from "react/jsx-runtime";
3692
3935
  function Dropzone({
3693
3936
  onFiles,
3694
3937
  onReject,
@@ -3702,8 +3945,8 @@ function Dropzone({
3702
3945
  className = "",
3703
3946
  style
3704
3947
  }) {
3705
- const [over, setOver] = React22.useState(false);
3706
- const depth = React22.useRef(0);
3948
+ const [over, setOver] = React24.useState(false);
3949
+ const depth = React24.useRef(0);
3707
3950
  const has = (e) => {
3708
3951
  const dt = e.dataTransfer;
3709
3952
  if (!dt) return false;
@@ -3733,7 +3976,7 @@ function Dropzone({
3733
3976
  if (rejected.length && onReject) onReject(rejected);
3734
3977
  if (accepted.length && onFiles) onFiles(accepted);
3735
3978
  };
3736
- return /* @__PURE__ */ jsxs44(
3979
+ return /* @__PURE__ */ jsxs47(
3737
3980
  "div",
3738
3981
  {
3739
3982
  className: ["fd-dropzone", over ? "is-over" : "", className].filter(Boolean).join(" "),
@@ -3744,10 +3987,10 @@ function Dropzone({
3744
3987
  onDrop: drop,
3745
3988
  children: [
3746
3989
  children,
3747
- over ? /* @__PURE__ */ jsx49("div", { className: "fd-dropzone-veil", "aria-hidden": "true", children: /* @__PURE__ */ jsxs44("div", { className: "fd-dropzone-card", children: [
3748
- /* @__PURE__ */ jsx49("i", { className: "ph ph-tray-arrow-down" }),
3749
- /* @__PURE__ */ jsx49("span", { className: "fd-dropzone-label", children: label }),
3750
- hint ? /* @__PURE__ */ jsx49("span", { className: "fd-dropzone-hint", children: hint }) : null
3990
+ over ? /* @__PURE__ */ jsx52("div", { className: "fd-dropzone-veil", "aria-hidden": "true", children: /* @__PURE__ */ jsxs47("div", { className: "fd-dropzone-card", children: [
3991
+ /* @__PURE__ */ jsx52("i", { className: "ph ph-tray-arrow-down" }),
3992
+ /* @__PURE__ */ jsx52("span", { className: "fd-dropzone-label", children: label }),
3993
+ hint ? /* @__PURE__ */ jsx52("span", { className: "fd-dropzone-hint", children: hint }) : null
3751
3994
  ] }) }) : null
3752
3995
  ]
3753
3996
  }
@@ -3765,9 +4008,9 @@ function FilePickButton({
3765
4008
  className = "",
3766
4009
  children
3767
4010
  }) {
3768
- const ref = React22.useRef(null);
3769
- return /* @__PURE__ */ jsxs44(React22.Fragment, { children: [
3770
- /* @__PURE__ */ jsx49(
4011
+ const ref = React24.useRef(null);
4012
+ return /* @__PURE__ */ jsxs47(React24.Fragment, { children: [
4013
+ /* @__PURE__ */ jsx52(
3771
4014
  "button",
3772
4015
  {
3773
4016
  type: "button",
@@ -3776,10 +4019,10 @@ function FilePickButton({
3776
4019
  "aria-label": label,
3777
4020
  title: label,
3778
4021
  onClick: () => ref.current && ref.current.click(),
3779
- children: children != null ? children : /* @__PURE__ */ jsx49("i", { className: "ph ph-" + icon, "aria-hidden": "true" })
4022
+ children: children != null ? children : /* @__PURE__ */ jsx52("i", { className: "ph ph-" + icon, "aria-hidden": "true" })
3780
4023
  }
3781
4024
  ),
3782
- /* @__PURE__ */ jsx49(
4025
+ /* @__PURE__ */ jsx52(
3783
4026
  "input",
3784
4027
  {
3785
4028
  ref,
@@ -3799,10 +4042,10 @@ function FilePickButton({
3799
4042
  }
3800
4043
  function useStagedFiles(upload, opts) {
3801
4044
  const o = opts || {};
3802
- const [items, setItems] = React22.useState([]);
3803
- const controllers = React22.useRef({});
4045
+ const [items, setItems] = React24.useState([]);
4046
+ const controllers = React24.useRef({});
3804
4047
  const patch = (id, next) => setItems((list) => list.map((f) => f.id === id ? Object.assign({}, f, next) : f));
3805
- const run = React22.useCallback((att) => {
4048
+ const run = React24.useCallback((att) => {
3806
4049
  if (!upload) return;
3807
4050
  const ac = typeof AbortController !== "undefined" ? new AbortController() : null;
3808
4051
  controllers.current[att.id] = ac;
@@ -3819,14 +4062,14 @@ function useStagedFiles(upload, opts) {
3819
4062
  delete controllers.current[att.id];
3820
4063
  });
3821
4064
  }, [upload]);
3822
- const add = React22.useCallback((files) => {
4065
+ const add = React24.useCallback((files) => {
3823
4066
  if (!upload) return [];
3824
4067
  const atts = Array.from(files).map((f) => toAttachment(f));
3825
4068
  setItems((list) => list.concat(atts));
3826
4069
  atts.forEach(run);
3827
4070
  return atts;
3828
4071
  }, [upload, run]);
3829
- const remove = React22.useCallback((att) => {
4072
+ const remove = React24.useCallback((att) => {
3830
4073
  const ac = controllers.current[att.id];
3831
4074
  if (ac) {
3832
4075
  try {
@@ -3837,10 +4080,10 @@ function useStagedFiles(upload, opts) {
3837
4080
  }
3838
4081
  setItems((list) => list.filter((f) => f.id !== att.id));
3839
4082
  }, []);
3840
- const retry = React22.useCallback((att) => {
4083
+ const retry = React24.useCallback((att) => {
3841
4084
  run(att);
3842
4085
  }, [run]);
3843
- const clear = React22.useCallback(() => {
4086
+ const clear = React24.useCallback(() => {
3844
4087
  Object.values(controllers.current).forEach((ac) => {
3845
4088
  try {
3846
4089
  ac && ac.abort();
@@ -3856,7 +4099,7 @@ function useStagedFiles(upload, opts) {
3856
4099
  var DropzoneKit = { useStagedFiles };
3857
4100
 
3858
4101
  // src/components/forms/FileGrid.tsx
3859
- import { jsx as jsx50, jsxs as jsxs45 } from "react/jsx-runtime";
4102
+ import { jsx as jsx53, jsxs as jsxs48 } from "react/jsx-runtime";
3860
4103
  var truncateMiddle = (name, max = 34) => {
3861
4104
  if (!name || name.length <= max) return name;
3862
4105
  const ext = /\.[A-Za-z0-9]+$/.exec(name);
@@ -3865,7 +4108,7 @@ var truncateMiddle = (name, max = 34) => {
3865
4108
  return head + "\u2026" + tail;
3866
4109
  };
3867
4110
  function Progress({ value }) {
3868
- return /* @__PURE__ */ jsx50("span", { className: "fd-file-prog", role: "progressbar", "aria-valuenow": Math.round(value), "aria-valuemin": 0, "aria-valuemax": 100, children: /* @__PURE__ */ jsx50("span", { className: "fd-file-prog-fill", style: { width: Math.max(4, Math.min(100, value)) + "%" } }) });
4111
+ return /* @__PURE__ */ jsx53("span", { className: "fd-file-prog", role: "progressbar", "aria-valuenow": Math.round(value), "aria-valuemin": 0, "aria-valuemax": 100, children: /* @__PURE__ */ jsx53("span", { className: "fd-file-prog-fill", style: { width: Math.max(4, Math.min(100, value)) + "%" } }) });
3869
4112
  }
3870
4113
  function FileChip({ file, onOpen, onRemove, onRetry, compact: compact3 = false, className = "" }) {
3871
4114
  if (!file) return null;
@@ -3874,8 +4117,8 @@ function FileChip({ file, onOpen, onRemove, onRetry, compact: compact3 = false,
3874
4117
  const thumb = file.thumb && file.thumb.url || (image ? file.blobUrl || file.url : null);
3875
4118
  const meta = file.meta || (file.size ? formatBytes(file.size) : "");
3876
4119
  const clickable = !!onOpen && !uploading;
3877
- return /* @__PURE__ */ jsxs45("div", { className: ["fd-file", compact3 ? "is-compact" : "", file.error ? "is-error" : "", uploading ? "is-uploading" : "", className].filter(Boolean).join(" "), children: [
3878
- /* @__PURE__ */ jsxs45(
4120
+ return /* @__PURE__ */ jsxs48("div", { className: ["fd-file", compact3 ? "is-compact" : "", file.error ? "is-error" : "", uploading ? "is-uploading" : "", className].filter(Boolean).join(" "), children: [
4121
+ /* @__PURE__ */ jsxs48(
3879
4122
  "button",
3880
4123
  {
3881
4124
  type: "button",
@@ -3884,16 +4127,16 @@ function FileChip({ file, onOpen, onRemove, onRetry, compact: compact3 = false,
3884
4127
  onClick: clickable ? () => onOpen(file) : void 0,
3885
4128
  title: file.name + (meta ? " \xB7 " + meta : ""),
3886
4129
  children: [
3887
- /* @__PURE__ */ jsxs45("span", { className: "fd-file-icon", children: [
3888
- thumb ? /* @__PURE__ */ jsx50("img", { src: thumb, alt: "" }) : /* @__PURE__ */ jsx50("i", { className: "ph ph-" + iconForMime(file.mime, file.name), "aria-hidden": "true" }),
3889
- (file.mime || "").startsWith("video/") ? /* @__PURE__ */ jsx50("i", { className: "ph ph-play fd-file-play", "aria-hidden": "true" }) : null
4130
+ /* @__PURE__ */ jsxs48("span", { className: "fd-file-icon", children: [
4131
+ thumb ? /* @__PURE__ */ jsx53("img", { src: thumb, alt: "" }) : /* @__PURE__ */ jsx53("i", { className: "ph ph-" + iconForMime(file.mime, file.name), "aria-hidden": "true" }),
4132
+ (file.mime || "").startsWith("video/") ? /* @__PURE__ */ jsx53("i", { className: "ph ph-play fd-file-play", "aria-hidden": "true" }) : null
3890
4133
  ] }),
3891
- /* @__PURE__ */ jsxs45("span", { className: "fd-file-text", children: [
3892
- /* @__PURE__ */ jsx50("span", { className: "fd-file-name", children: truncateMiddle(file.name, compact3 ? 26 : 40) }),
3893
- /* @__PURE__ */ jsx50("span", { className: "fd-file-meta", children: file.error ? /* @__PURE__ */ jsxs45("span", { className: "fd-file-err", children: [
3894
- /* @__PURE__ */ jsx50("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
4134
+ /* @__PURE__ */ jsxs48("span", { className: "fd-file-text", children: [
4135
+ /* @__PURE__ */ jsx53("span", { className: "fd-file-name", children: truncateMiddle(file.name, compact3 ? 26 : 40) }),
4136
+ /* @__PURE__ */ jsx53("span", { className: "fd-file-meta", children: file.error ? /* @__PURE__ */ jsxs48("span", { className: "fd-file-err", children: [
4137
+ /* @__PURE__ */ jsx53("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
3895
4138
  file.error
3896
- ] }) : uploading ? /* @__PURE__ */ jsxs45("span", { className: "fd-tabular", children: [
4139
+ ] }) : uploading ? /* @__PURE__ */ jsxs48("span", { className: "fd-tabular", children: [
3897
4140
  Math.round(file.progress),
3898
4141
  "% uploaded"
3899
4142
  ] }) : meta })
@@ -3901,29 +4144,29 @@ function FileChip({ file, onOpen, onRemove, onRetry, compact: compact3 = false,
3901
4144
  ]
3902
4145
  }
3903
4146
  ),
3904
- uploading ? /* @__PURE__ */ jsx50(Progress, { value: file.progress }) : null,
3905
- file.error && onRetry ? /* @__PURE__ */ jsx50("button", { type: "button", className: "fd-file-act", onClick: () => onRetry(file), "aria-label": "Retry upload of " + file.name, children: /* @__PURE__ */ jsx50("i", { className: "ph ph-arrow-clockwise", "aria-hidden": "true" }) }) : null,
3906
- onRemove ? /* @__PURE__ */ jsx50("button", { type: "button", className: "fd-file-act", onClick: () => onRemove(file), "aria-label": "Remove " + file.name, children: /* @__PURE__ */ jsx50("i", { className: "ph ph-x", "aria-hidden": "true" }) }) : null
4147
+ uploading ? /* @__PURE__ */ jsx53(Progress, { value: file.progress }) : null,
4148
+ file.error && onRetry ? /* @__PURE__ */ jsx53("button", { type: "button", className: "fd-file-act", onClick: () => onRetry(file), "aria-label": "Retry upload of " + file.name, children: /* @__PURE__ */ jsx53("i", { className: "ph ph-arrow-clockwise", "aria-hidden": "true" }) }) : null,
4149
+ onRemove ? /* @__PURE__ */ jsx53("button", { type: "button", className: "fd-file-act", onClick: () => onRemove(file), "aria-label": "Remove " + file.name, children: /* @__PURE__ */ jsx53("i", { className: "ph ph-x", "aria-hidden": "true" }) }) : null
3907
4150
  ] });
3908
4151
  }
3909
4152
  function FileTile({ file, onOpen, onRemove, maxHeight = 200, className = "" }) {
3910
4153
  if (!file) return null;
3911
4154
  const src = file.thumb && file.thumb.url || file.blobUrl || file.url;
3912
4155
  const uploading = file.progress != null && file.progress < 100 && !file.error;
3913
- return /* @__PURE__ */ jsxs45("figure", { className: ["fd-tile", uploading ? "is-uploading" : "", file.error ? "is-error" : "", className].filter(Boolean).join(" "), children: [
3914
- /* @__PURE__ */ jsx50("button", { type: "button", className: "fd-tile-btn", onClick: onOpen ? () => onOpen(file) : void 0, disabled: !onOpen, children: src ? /* @__PURE__ */ jsx50("img", { src, alt: file.name || "", style: { maxHeight }, loading: "lazy" }) : /* @__PURE__ */ jsx50("span", { className: "fd-tile-fallback", children: /* @__PURE__ */ jsx50("i", { className: "ph ph-" + iconForMime(file.mime, file.name), "aria-hidden": "true" }) }) }),
3915
- uploading ? /* @__PURE__ */ jsx50(Progress, { value: file.progress }) : null,
3916
- file.error ? /* @__PURE__ */ jsxs45("figcaption", { className: "fd-tile-err", children: [
3917
- /* @__PURE__ */ jsx50("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
4156
+ return /* @__PURE__ */ jsxs48("figure", { className: ["fd-tile", uploading ? "is-uploading" : "", file.error ? "is-error" : "", className].filter(Boolean).join(" "), children: [
4157
+ /* @__PURE__ */ jsx53("button", { type: "button", className: "fd-tile-btn", onClick: onOpen ? () => onOpen(file) : void 0, disabled: !onOpen, children: src ? /* @__PURE__ */ jsx53("img", { src, alt: file.name || "", style: { maxHeight }, loading: "lazy" }) : /* @__PURE__ */ jsx53("span", { className: "fd-tile-fallback", children: /* @__PURE__ */ jsx53("i", { className: "ph ph-" + iconForMime(file.mime, file.name), "aria-hidden": "true" }) }) }),
4158
+ uploading ? /* @__PURE__ */ jsx53(Progress, { value: file.progress }) : null,
4159
+ file.error ? /* @__PURE__ */ jsxs48("figcaption", { className: "fd-tile-err", children: [
4160
+ /* @__PURE__ */ jsx53("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
3918
4161
  file.error
3919
4162
  ] }) : null,
3920
- onRemove ? /* @__PURE__ */ jsx50("button", { type: "button", className: "fd-tile-x", onClick: () => onRemove(file), "aria-label": "Remove " + file.name, children: /* @__PURE__ */ jsx50("i", { className: "ph ph-x", "aria-hidden": "true" }) }) : null
4163
+ onRemove ? /* @__PURE__ */ jsx53("button", { type: "button", className: "fd-tile-x", onClick: () => onRemove(file), "aria-label": "Remove " + file.name, children: /* @__PURE__ */ jsx53("i", { className: "ph ph-x", "aria-hidden": "true" }) }) : null
3921
4164
  ] });
3922
4165
  }
3923
4166
  function FileStrip({ files = [], size = 68, onOpen, onRemove, onRetry, className = "" }) {
3924
4167
  const list = files.filter(Boolean);
3925
4168
  if (!list.length) return null;
3926
- return /* @__PURE__ */ jsx50("div", { className: ["fd-filestrip", className].filter(Boolean).join(" "), style: { "--fd-cell": size + "px" }, children: list.map((f) => /* @__PURE__ */ jsx50(FileCell, { file: f, onOpen, onRemove, onRetry }, f.id || f.name)) });
4169
+ return /* @__PURE__ */ jsx53("div", { className: ["fd-filestrip", className].filter(Boolean).join(" "), style: { "--fd-cell": size + "px" }, children: list.map((f) => /* @__PURE__ */ jsx53(FileCell, { file: f, onOpen, onRemove, onRetry }, f.id || f.name)) });
3927
4170
  }
3928
4171
  var shortName = (name, keep = 5) => {
3929
4172
  const s = String(name || "file");
@@ -3937,19 +4180,19 @@ function FileCell({ file, onOpen, onRemove, onRetry }) {
3937
4180
  const image = isImage(file.mime, file.name);
3938
4181
  const thumb = file.thumb && file.thumb.url || (image ? file.blobUrl || file.url : null);
3939
4182
  const label = file.name + (file.size ? " \xB7 " + formatBytes(file.size) : "");
3940
- return /* @__PURE__ */ jsxs45("div", { className: ["fd-cell", file.error ? "is-error" : "", uploading ? "is-uploading" : ""].filter(Boolean).join(" "), title: file.error ? file.name + " \u2014 " + file.error : label, children: [
3941
- /* @__PURE__ */ jsxs45("button", { type: "button", className: "fd-cell-main", onClick: onOpen ? () => onOpen(file) : void 0, disabled: !onOpen || uploading, "aria-label": "Open " + file.name, children: [
3942
- thumb ? /* @__PURE__ */ jsx50("img", { src: thumb, alt: "" }) : /* @__PURE__ */ jsxs45("span", { className: "fd-cell-doc", children: [
3943
- /* @__PURE__ */ jsx50("i", { className: "ph ph-" + iconForMime(file.mime, file.name), "aria-hidden": "true" }),
3944
- /* @__PURE__ */ jsx50("span", { className: "fd-cell-name", children: shortName(file.name) }),
3945
- /* @__PURE__ */ jsx50("span", { className: "fd-cell-size", children: file.meta || formatBytes(file.size) })
4183
+ return /* @__PURE__ */ jsxs48("div", { className: ["fd-cell", file.error ? "is-error" : "", uploading ? "is-uploading" : ""].filter(Boolean).join(" "), title: file.error ? file.name + " \u2014 " + file.error : label, children: [
4184
+ /* @__PURE__ */ jsxs48("button", { type: "button", className: "fd-cell-main", onClick: onOpen ? () => onOpen(file) : void 0, disabled: !onOpen || uploading, "aria-label": "Open " + file.name, children: [
4185
+ thumb ? /* @__PURE__ */ jsx53("img", { src: thumb, alt: "" }) : /* @__PURE__ */ jsxs48("span", { className: "fd-cell-doc", children: [
4186
+ /* @__PURE__ */ jsx53("i", { className: "ph ph-" + iconForMime(file.mime, file.name), "aria-hidden": "true" }),
4187
+ /* @__PURE__ */ jsx53("span", { className: "fd-cell-name", children: shortName(file.name) }),
4188
+ /* @__PURE__ */ jsx53("span", { className: "fd-cell-size", children: file.meta || formatBytes(file.size) })
3946
4189
  ] }),
3947
- (file.mime || "").startsWith("video/") ? /* @__PURE__ */ jsx50("i", { className: "ph ph-play fd-cell-play", "aria-hidden": "true" }) : null
4190
+ (file.mime || "").startsWith("video/") ? /* @__PURE__ */ jsx53("i", { className: "ph ph-play fd-cell-play", "aria-hidden": "true" }) : null
3948
4191
  ] }),
3949
- uploading ? /* @__PURE__ */ jsx50(Progress, { value: file.progress }) : null,
3950
- file.error ? /* @__PURE__ */ jsx50("span", { className: "fd-cell-err", "aria-hidden": "true", children: /* @__PURE__ */ jsx50("i", { className: "ph ph-warning-circle" }) }) : null,
3951
- file.error && onRetry ? /* @__PURE__ */ jsx50("button", { type: "button", className: "fd-cell-x is-retry", onClick: () => onRetry(file), "aria-label": "Retry upload of " + file.name, children: /* @__PURE__ */ jsx50("i", { className: "ph ph-arrow-clockwise", "aria-hidden": "true" }) }) : null,
3952
- onRemove ? /* @__PURE__ */ jsx50("button", { type: "button", className: "fd-cell-x", onClick: () => onRemove(file), "aria-label": "Remove " + file.name, children: /* @__PURE__ */ jsx50("i", { className: "ph ph-x", "aria-hidden": "true" }) }) : null
4192
+ uploading ? /* @__PURE__ */ jsx53(Progress, { value: file.progress }) : null,
4193
+ file.error ? /* @__PURE__ */ jsx53("span", { className: "fd-cell-err", "aria-hidden": "true", children: /* @__PURE__ */ jsx53("i", { className: "ph ph-warning-circle" }) }) : null,
4194
+ file.error && onRetry ? /* @__PURE__ */ jsx53("button", { type: "button", className: "fd-cell-x is-retry", onClick: () => onRetry(file), "aria-label": "Retry upload of " + file.name, children: /* @__PURE__ */ jsx53("i", { className: "ph ph-arrow-clockwise", "aria-hidden": "true" }) }) : null,
4195
+ onRemove ? /* @__PURE__ */ jsx53("button", { type: "button", className: "fd-cell-x", onClick: () => onRemove(file), "aria-label": "Remove " + file.name, children: /* @__PURE__ */ jsx53("i", { className: "ph ph-x", "aria-hidden": "true" }) }) : null
3953
4196
  ] });
3954
4197
  }
3955
4198
  function FileGrid({ files = [], onOpen, onRemove, onRetry, tiles = true, maxHeight = 200, compact: compact3 = false, className = "" }) {
@@ -3957,15 +4200,15 @@ function FileGrid({ files = [], onOpen, onRemove, onRetry, tiles = true, maxHeig
3957
4200
  if (!list.length) return null;
3958
4201
  const pics = tiles ? list.filter((f) => isImage(f.mime, f.name)) : [];
3959
4202
  const rest = list.filter((f) => pics.indexOf(f) === -1);
3960
- return /* @__PURE__ */ jsxs45("div", { className: ["fd-filegrid", className].filter(Boolean).join(" "), children: [
3961
- pics.length ? /* @__PURE__ */ jsx50("div", { className: "fd-filegrid-tiles", children: pics.map((f) => /* @__PURE__ */ jsx50(FileTile, { file: f, onOpen, onRemove, maxHeight }, f.id || f.name)) }) : null,
3962
- rest.length ? /* @__PURE__ */ jsx50("div", { className: "fd-filegrid-chips", children: rest.map((f) => /* @__PURE__ */ jsx50(FileChip, { file: f, onOpen, onRemove, onRetry, compact: compact3 }, f.id || f.name)) }) : null
4203
+ return /* @__PURE__ */ jsxs48("div", { className: ["fd-filegrid", className].filter(Boolean).join(" "), children: [
4204
+ pics.length ? /* @__PURE__ */ jsx53("div", { className: "fd-filegrid-tiles", children: pics.map((f) => /* @__PURE__ */ jsx53(FileTile, { file: f, onOpen, onRemove, maxHeight }, f.id || f.name)) }) : null,
4205
+ rest.length ? /* @__PURE__ */ jsx53("div", { className: "fd-filegrid-chips", children: rest.map((f) => /* @__PURE__ */ jsx53(FileChip, { file: f, onOpen, onRemove, onRetry, compact: compact3 }, f.id || f.name)) }) : null
3963
4206
  ] });
3964
4207
  }
3965
4208
 
3966
4209
  // src/components/forms/MarkdownEditor.tsx
3967
- import * as React23 from "react";
3968
- import { jsx as jsx51, jsxs as jsxs46 } from "react/jsx-runtime";
4210
+ import * as React25 from "react";
4211
+ import { jsx as jsx54, jsxs as jsxs49 } from "react/jsx-runtime";
3969
4212
  var isMac = typeof navigator !== "undefined" && /Mac|iPhone|iPad/.test(navigator.platform || navigator.userAgent || "");
3970
4213
  var INLINE_RE = /(\*\*\*[^*\n]+\*\*\*|\*\*[^*\n]+\*\*|__[^_\n]+__|~~[^~\n]+~~|`[^`\n]+`|\*[^*\s][^*\n]*\*|(?<![A-Za-z0-9_])_[^_\s][^_\n]*_|\[[^\]\n]*\]\([^)\s\n]*\)|https?:\/\/\S+)/g;
3971
4214
  function inlineParts(text) {
@@ -4178,7 +4421,7 @@ function syncDom(root, value) {
4178
4421
  while (root.children.length > lines.length) root.removeChild(root.lastChild);
4179
4422
  }
4180
4423
  var LIST_CONT = RE_LI;
4181
- var MarkdownEditor = React23.forwardRef(function MarkdownEditor2({
4424
+ var MarkdownEditor = React25.forwardRef(function MarkdownEditor2({
4182
4425
  value = "",
4183
4426
  onChange,
4184
4427
  onSubmit,
@@ -4197,10 +4440,10 @@ var MarkdownEditor = React23.forwardRef(function MarkdownEditor2({
4197
4440
  className = "",
4198
4441
  id
4199
4442
  }, ref) {
4200
- const boxRef = React23.useRef(null);
4201
- const composing = React23.useRef(false);
4202
- const pendingCaret = React23.useRef(null);
4203
- React23.useLayoutEffect(() => {
4443
+ const boxRef = React25.useRef(null);
4444
+ const composing = React25.useRef(false);
4445
+ const pendingCaret = React25.useRef(null);
4446
+ React25.useLayoutEffect(() => {
4204
4447
  const root = boxRef.current;
4205
4448
  if (!root || composing.current) return;
4206
4449
  const active = document.activeElement === root || root.contains(document.activeElement);
@@ -4209,7 +4452,7 @@ var MarkdownEditor = React23.forwardRef(function MarkdownEditor2({
4209
4452
  pendingCaret.current = null;
4210
4453
  if (active && caret != null) placeCaret(root, caret);
4211
4454
  }, [value]);
4212
- React23.useEffect(() => {
4455
+ React25.useEffect(() => {
4213
4456
  if (autoFocus && boxRef.current) boxRef.current.focus();
4214
4457
  }, [autoFocus]);
4215
4458
  const caretNow = () => {
@@ -4276,7 +4519,7 @@ var MarkdownEditor = React23.forwardRef(function MarkdownEditor2({
4276
4519
  api.replaceRange(from, to, next, from + next.length);
4277
4520
  }
4278
4521
  };
4279
- React23.useImperativeHandle(ref, () => api);
4522
+ React25.useImperativeHandle(ref, () => api);
4280
4523
  function detect(text, caret) {
4281
4524
  if (!onTrigger) return;
4282
4525
  const upto = text.slice(0, caret);
@@ -4389,8 +4632,8 @@ var MarkdownEditor = React23.forwardRef(function MarkdownEditor2({
4389
4632
  api.replaceRange(s.start, s.end, text.replace(/\r\n?/g, "\n"));
4390
4633
  };
4391
4634
  const lh = 1.55;
4392
- return /* @__PURE__ */ jsxs46("div", { className: ["fd-rme-wrap", disabled ? "is-disabled" : "", className].filter(Boolean).join(" "), children: [
4393
- /* @__PURE__ */ jsx51(
4635
+ return /* @__PURE__ */ jsxs49("div", { className: ["fd-rme-wrap", disabled ? "is-disabled" : "", className].filter(Boolean).join(" "), children: [
4636
+ /* @__PURE__ */ jsx54(
4394
4637
  "div",
4395
4638
  {
4396
4639
  ref: boxRef,
@@ -4423,15 +4666,15 @@ var MarkdownEditor = React23.forwardRef(function MarkdownEditor2({
4423
4666
  }
4424
4667
  }
4425
4668
  ),
4426
- !value ? /* @__PURE__ */ jsx51("span", { className: "fd-rme-ph", "aria-hidden": "true", children: placeholder }) : null
4669
+ !value ? /* @__PURE__ */ jsx54("span", { className: "fd-rme-ph", "aria-hidden": "true", children: placeholder }) : null
4427
4670
  ] });
4428
4671
  });
4429
4672
 
4430
4673
  // src/components/platform/AccountMenu.tsx
4431
- import * as React25 from "react";
4674
+ import * as React27 from "react";
4432
4675
 
4433
4676
  // src/kits/session.ts
4434
- import * as React24 from "react";
4677
+ import * as React26 from "react";
4435
4678
  var PERMISSION_CATALOG = [
4436
4679
  { group: "Plans", items: [
4437
4680
  { key: "plan.view", label: "View plans", detail: "Read any plan in the workspace." },
@@ -5998,8 +6241,8 @@ function roadmap(overrides) {
5998
6241
  };
5999
6242
  }
6000
6243
  function useSession() {
6001
- const [s, setS] = React24.useState(getSession);
6002
- React24.useEffect(() => subscribe(setS), []);
6244
+ const [s, setS] = React26.useState(getSession);
6245
+ React26.useEffect(() => subscribe(setS), []);
6003
6246
  return s;
6004
6247
  }
6005
6248
  var SessionKit = {
@@ -6032,7 +6275,7 @@ var SessionKit = {
6032
6275
  };
6033
6276
 
6034
6277
  // src/components/platform/AccountMenu.tsx
6035
- import { Fragment as Fragment11, jsx as jsx52, jsxs as jsxs47 } from "react/jsx-runtime";
6278
+ import { Fragment as Fragment11, jsx as jsx55, jsxs as jsxs50 } from "react/jsx-runtime";
6036
6279
  var DEFAULT_LINKS = [
6037
6280
  { id: "profile", label: "Your profile", icon: "user-circle", href: "../admin/index.html#profile" },
6038
6281
  { id: "preferences", label: "Preferences", icon: "sliders-horizontal", href: "../admin/index.html#preferences" }
@@ -6043,7 +6286,7 @@ var DEFAULT_ADMIN_LINKS = [
6043
6286
  { id: "flags", label: "Feature flags", icon: "toggle-right", href: "../admin/index.html#flags", perm: "flags.manage" }
6044
6287
  ];
6045
6288
  function Item({ item, onPick }) {
6046
- return /* @__PURE__ */ jsxs47(
6289
+ return /* @__PURE__ */ jsxs50(
6047
6290
  "button",
6048
6291
  {
6049
6292
  type: "button",
@@ -6051,9 +6294,9 @@ function Item({ item, onPick }) {
6051
6294
  className: "fd-acct-item",
6052
6295
  onClick: () => onPick(item),
6053
6296
  children: [
6054
- /* @__PURE__ */ jsx52("i", { className: "ph ph-" + item.icon, "aria-hidden": "true" }),
6055
- /* @__PURE__ */ jsx52("span", { style: { flex: 1 }, children: item.label }),
6056
- item.badge ? /* @__PURE__ */ jsx52(Badge, { tone: "neutral", children: item.badge }) : null
6297
+ /* @__PURE__ */ jsx55("i", { className: "ph ph-" + item.icon, "aria-hidden": "true" }),
6298
+ /* @__PURE__ */ jsx55("span", { style: { flex: 1 }, children: item.label }),
6299
+ item.badge ? /* @__PURE__ */ jsx55(Badge, { tone: "neutral", children: item.badge }) : null
6057
6300
  ]
6058
6301
  }
6059
6302
  );
@@ -6069,9 +6312,9 @@ function AccountMenu({
6069
6312
  ...rest
6070
6313
  }) {
6071
6314
  const session = SessionKit.useSession();
6072
- const [open, setOpen] = React25.useState(false);
6073
- const [switching, setSwitching] = React25.useState(false);
6074
- const ref = React25.useRef(null);
6315
+ const [open, setOpen] = React27.useState(false);
6316
+ const [switching, setSwitching] = React27.useState(false);
6317
+ const ref = React27.useRef(null);
6075
6318
  const user = session.user;
6076
6319
  const visibleAdmin = adminLinks.filter((l) => !l.perm || SessionKit.can(l.perm));
6077
6320
  const pick = (item) => {
@@ -6085,8 +6328,8 @@ function AccountMenu({
6085
6328
  if (onSignOut) return onSignOut();
6086
6329
  window.alert("Signed out. (Simulated \u2014 no auth provider is wired up.)");
6087
6330
  };
6088
- return /* @__PURE__ */ jsxs47(Fragment11, { children: [
6089
- /* @__PURE__ */ jsxs47(
6331
+ return /* @__PURE__ */ jsxs50(Fragment11, { children: [
6332
+ /* @__PURE__ */ jsxs50(
6090
6333
  "button",
6091
6334
  {
6092
6335
  type: "button",
@@ -6098,32 +6341,32 @@ function AccountMenu({
6098
6341
  onClick: () => setOpen((o) => !o),
6099
6342
  ...rest,
6100
6343
  children: [
6101
- /* @__PURE__ */ jsx52(Avatar, { name: user.name, size: "sm" }),
6102
- /* @__PURE__ */ jsx52("i", { className: "ph ph-caret-down", "aria-hidden": "true", style: { fontSize: 11, color: "var(--text-muted)" } })
6344
+ /* @__PURE__ */ jsx55(Avatar, { name: user.name, size: "sm" }),
6345
+ /* @__PURE__ */ jsx55("i", { className: "ph ph-caret-down", "aria-hidden": "true", style: { fontSize: 11, color: "var(--text-muted)" } })
6103
6346
  ]
6104
6347
  }
6105
6348
  ),
6106
- /* @__PURE__ */ jsx52(Popover, { open, anchorRef: ref, onClose: () => setOpen(false), placement: "bottom-end", width: 272, children: /* @__PURE__ */ jsxs47("div", { role: "menu", className: "fd-stack", style: { gap: 0 }, children: [
6107
- /* @__PURE__ */ jsxs47("div", { className: "fd-row", style: { gap: 10, padding: "12px 14px", borderBottom: "1px solid var(--border)" }, children: [
6108
- /* @__PURE__ */ jsx52(Avatar, { name: user.name }),
6109
- /* @__PURE__ */ jsxs47("span", { className: "fd-stack", style: { gap: 1, minWidth: 0, flex: 1 }, children: [
6110
- /* @__PURE__ */ jsx52("span", { className: "fd-body-sm", style: { fontWeight: 700 }, children: user.name }),
6111
- /* @__PURE__ */ jsx52("span", { className: "fd-body-sm fd-muted fd-table-trunc", children: user.email })
6349
+ /* @__PURE__ */ jsx55(Popover, { open, anchorRef: ref, onClose: () => setOpen(false), placement: "bottom-end", width: 272, children: /* @__PURE__ */ jsxs50("div", { role: "menu", className: "fd-stack", style: { gap: 0 }, children: [
6350
+ /* @__PURE__ */ jsxs50("div", { className: "fd-row", style: { gap: 10, padding: "12px 14px", borderBottom: "1px solid var(--border)" }, children: [
6351
+ /* @__PURE__ */ jsx55(Avatar, { name: user.name }),
6352
+ /* @__PURE__ */ jsxs50("span", { className: "fd-stack", style: { gap: 1, minWidth: 0, flex: 1 }, children: [
6353
+ /* @__PURE__ */ jsx55("span", { className: "fd-body-sm", style: { fontWeight: 700 }, children: user.name }),
6354
+ /* @__PURE__ */ jsx55("span", { className: "fd-body-sm fd-muted fd-table-trunc", children: user.email })
6112
6355
  ] })
6113
6356
  ] }),
6114
- showRoles && session.roles.length ? /* @__PURE__ */ jsx52("div", { className: "fd-row", style: { gap: 6, padding: "10px 14px", flexWrap: "wrap", borderBottom: "1px solid var(--border)" }, children: session.roles.map((r) => /* @__PURE__ */ jsx52(Badge, { tone: r.id === "owner" ? "success" : "neutral", children: r.name }, r.id)) }) : null,
6115
- /* @__PURE__ */ jsx52("div", { className: "fd-acct-group", children: links.map((l) => /* @__PURE__ */ jsx52(Item, { item: l, onPick: pick }, l.id)) }),
6116
- visibleAdmin.length ? /* @__PURE__ */ jsxs47("div", { className: "fd-acct-group", style: { borderTop: "1px solid var(--border)" }, children: [
6117
- /* @__PURE__ */ jsx52("span", { className: "fd-overline fd-muted", style: { padding: "8px 14px 4px", display: "block" }, children: "Administration" }),
6118
- visibleAdmin.map((l) => /* @__PURE__ */ jsx52(Item, { item: l, onPick: pick }, l.id))
6357
+ showRoles && session.roles.length ? /* @__PURE__ */ jsx55("div", { className: "fd-row", style: { gap: 6, padding: "10px 14px", flexWrap: "wrap", borderBottom: "1px solid var(--border)" }, children: session.roles.map((r) => /* @__PURE__ */ jsx55(Badge, { tone: r.id === "owner" ? "success" : "neutral", children: r.name }, r.id)) }) : null,
6358
+ /* @__PURE__ */ jsx55("div", { className: "fd-acct-group", children: links.map((l) => /* @__PURE__ */ jsx55(Item, { item: l, onPick: pick }, l.id)) }),
6359
+ visibleAdmin.length ? /* @__PURE__ */ jsxs50("div", { className: "fd-acct-group", style: { borderTop: "1px solid var(--border)" }, children: [
6360
+ /* @__PURE__ */ jsx55("span", { className: "fd-overline fd-muted", style: { padding: "8px 14px 4px", display: "block" }, children: "Administration" }),
6361
+ visibleAdmin.map((l) => /* @__PURE__ */ jsx55(Item, { item: l, onPick: pick }, l.id))
6119
6362
  ] }) : null,
6120
- allowUserSwitch ? /* @__PURE__ */ jsxs47("div", { className: "fd-acct-group", style: { borderTop: "1px solid var(--border)" }, children: [
6121
- /* @__PURE__ */ jsxs47("button", { type: "button", role: "menuitem", className: "fd-acct-item", onClick: () => setSwitching((s) => !s), children: [
6122
- /* @__PURE__ */ jsx52("i", { className: "ph ph-user-switch", "aria-hidden": "true" }),
6123
- /* @__PURE__ */ jsx52("span", { style: { flex: 1 }, children: "View as another member" }),
6124
- /* @__PURE__ */ jsx52("i", { className: "ph ph-caret-" + (switching ? "up" : "down"), "aria-hidden": "true", style: { fontSize: 11 } })
6363
+ allowUserSwitch ? /* @__PURE__ */ jsxs50("div", { className: "fd-acct-group", style: { borderTop: "1px solid var(--border)" }, children: [
6364
+ /* @__PURE__ */ jsxs50("button", { type: "button", role: "menuitem", className: "fd-acct-item", onClick: () => setSwitching((s) => !s), children: [
6365
+ /* @__PURE__ */ jsx55("i", { className: "ph ph-user-switch", "aria-hidden": "true" }),
6366
+ /* @__PURE__ */ jsx55("span", { style: { flex: 1 }, children: "View as another member" }),
6367
+ /* @__PURE__ */ jsx55("i", { className: "ph ph-caret-" + (switching ? "up" : "down"), "aria-hidden": "true", style: { fontSize: 11 } })
6125
6368
  ] }),
6126
- switching ? /* @__PURE__ */ jsx52("div", { className: "fd-stack", style: { gap: 0, maxHeight: 208, overflowY: "auto" }, children: session.allUsers.filter((u) => u.status === "active").map((u) => /* @__PURE__ */ jsxs47(
6369
+ switching ? /* @__PURE__ */ jsx55("div", { className: "fd-stack", style: { gap: 0, maxHeight: 208, overflowY: "auto" }, children: session.allUsers.filter((u) => u.status === "active").map((u) => /* @__PURE__ */ jsxs50(
6127
6370
  "button",
6128
6371
  {
6129
6372
  type: "button",
@@ -6135,34 +6378,34 @@ function AccountMenu({
6135
6378
  setSwitching(false);
6136
6379
  },
6137
6380
  children: [
6138
- /* @__PURE__ */ jsx52(Avatar, { name: u.name, size: "sm" }),
6139
- /* @__PURE__ */ jsxs47("span", { className: "fd-stack", style: { gap: 0, flex: 1, minWidth: 0, alignItems: "flex-start" }, children: [
6140
- /* @__PURE__ */ jsx52("span", { style: { fontWeight: u.id === user.id ? 700 : 500 }, children: u.name }),
6141
- /* @__PURE__ */ jsx52("span", { className: "fd-muted", style: { fontSize: 11.5 }, children: u.roles.join(", ") })
6381
+ /* @__PURE__ */ jsx55(Avatar, { name: u.name, size: "sm" }),
6382
+ /* @__PURE__ */ jsxs50("span", { className: "fd-stack", style: { gap: 0, flex: 1, minWidth: 0, alignItems: "flex-start" }, children: [
6383
+ /* @__PURE__ */ jsx55("span", { style: { fontWeight: u.id === user.id ? 700 : 500 }, children: u.name }),
6384
+ /* @__PURE__ */ jsx55("span", { className: "fd-muted", style: { fontSize: 11.5 }, children: u.roles.join(", ") })
6142
6385
  ] }),
6143
- u.id === user.id ? /* @__PURE__ */ jsx52("i", { className: "ph ph-check", "aria-hidden": "true", style: { color: "var(--ok-text)" } }) : null
6386
+ u.id === user.id ? /* @__PURE__ */ jsx55("i", { className: "ph ph-check", "aria-hidden": "true", style: { color: "var(--ok-text)" } }) : null
6144
6387
  ]
6145
6388
  },
6146
6389
  u.id
6147
6390
  )) }) : null
6148
6391
  ] }) : null,
6149
- /* @__PURE__ */ jsx52("div", { className: "fd-acct-group", style: { borderTop: "1px solid var(--border)" }, children: /* @__PURE__ */ jsxs47("button", { type: "button", role: "menuitem", className: "fd-acct-item", "data-danger": "true", onClick: signOut, children: [
6150
- /* @__PURE__ */ jsx52("i", { className: "ph ph-sign-out", "aria-hidden": "true" }),
6151
- /* @__PURE__ */ jsx52("span", { style: { flex: 1 }, children: "Sign out" })
6392
+ /* @__PURE__ */ jsx55("div", { className: "fd-acct-group", style: { borderTop: "1px solid var(--border)" }, children: /* @__PURE__ */ jsxs50("button", { type: "button", role: "menuitem", className: "fd-acct-item", "data-danger": "true", onClick: signOut, children: [
6393
+ /* @__PURE__ */ jsx55("i", { className: "ph ph-sign-out", "aria-hidden": "true" }),
6394
+ /* @__PURE__ */ jsx55("span", { style: { flex: 1 }, children: "Sign out" })
6152
6395
  ] }) })
6153
6396
  ] }) })
6154
6397
  ] });
6155
6398
  }
6156
6399
 
6157
6400
  // src/components/platform/ApiSpecBrowser.tsx
6158
- import * as React26 from "react";
6159
- import { jsx as jsx53, jsxs as jsxs48 } from "react/jsx-runtime";
6401
+ import * as React28 from "react";
6402
+ import { jsx as jsx56, jsxs as jsxs51 } from "react/jsx-runtime";
6160
6403
  var METHOD_TONE = { GET: "success", POST: "info", PATCH: "warning", PUT: "warning", DELETE: "danger" };
6161
6404
  function Json({ obj }) {
6162
- return /* @__PURE__ */ jsx53("pre", { className: "fd-json", children: JSON.stringify(obj, null, 2) });
6405
+ return /* @__PURE__ */ jsx56("pre", { className: "fd-json", children: JSON.stringify(obj, null, 2) });
6163
6406
  }
6164
6407
  function Endpoint({ s, onRequest }) {
6165
- const [tried, setTried] = React26.useState(null);
6408
+ const [tried, setTried] = React28.useState(null);
6166
6409
  const run = async () => {
6167
6410
  setTried("busy");
6168
6411
  const t0 = (window.performance || Date).now();
@@ -6173,50 +6416,50 @@ function Endpoint({ s, onRequest }) {
6173
6416
  setTried({ ms: Math.round((window.performance || Date).now() - t0), error: String(e && e.message || e) });
6174
6417
  }
6175
6418
  };
6176
- return /* @__PURE__ */ jsx53(Card, { elevation: "flat", padded: false, children: /* @__PURE__ */ jsxs48("div", { className: "fd-stack", style: { gap: 0 }, children: [
6177
- /* @__PURE__ */ jsxs48("div", { className: "fd-row", style: { gap: 10, padding: "14px 18px", flexWrap: "wrap" }, children: [
6178
- /* @__PURE__ */ jsx53(Badge, { tone: METHOD_TONE[s.method] || "neutral", children: s.method }),
6179
- /* @__PURE__ */ jsx53("code", { className: "fd-mono", style: { fontSize: 12.5, fontWeight: 600, color: "var(--text)", wordBreak: "break-all" }, children: s.path }),
6180
- s.isList ? /* @__PURE__ */ jsx53(Badge, { tone: "neutral", icon: "rows", children: "Paged list" }) : null,
6181
- /* @__PURE__ */ jsx53("span", { style: { flex: 1 } }),
6182
- /* @__PURE__ */ jsxs48("span", { className: "fd-body-sm fd-muted fd-mono", children: [
6419
+ return /* @__PURE__ */ jsx56(Card, { elevation: "flat", padded: false, children: /* @__PURE__ */ jsxs51("div", { className: "fd-stack", style: { gap: 0 }, children: [
6420
+ /* @__PURE__ */ jsxs51("div", { className: "fd-row", style: { gap: 10, padding: "14px 18px", flexWrap: "wrap" }, children: [
6421
+ /* @__PURE__ */ jsx56(Badge, { tone: METHOD_TONE[s.method] || "neutral", children: s.method }),
6422
+ /* @__PURE__ */ jsx56("code", { className: "fd-mono", style: { fontSize: 12.5, fontWeight: 600, color: "var(--text)", wordBreak: "break-all" }, children: s.path }),
6423
+ s.isList ? /* @__PURE__ */ jsx56(Badge, { tone: "neutral", icon: "rows", children: "Paged list" }) : null,
6424
+ /* @__PURE__ */ jsx56("span", { style: { flex: 1 } }),
6425
+ /* @__PURE__ */ jsxs51("span", { className: "fd-body-sm fd-muted fd-mono", children: [
6183
6426
  s.latency[0],
6184
6427
  "\u2013",
6185
6428
  s.latency[1],
6186
6429
  "ms"
6187
6430
  ] }),
6188
- /* @__PURE__ */ jsx53(Button, { size: "sm", variant: "secondary", icon: "play", loading: tried === "busy", onClick: run, children: "Try it" })
6431
+ /* @__PURE__ */ jsx56(Button, { size: "sm", variant: "secondary", icon: "play", loading: tried === "busy", onClick: run, children: "Try it" })
6189
6432
  ] }),
6190
- /* @__PURE__ */ jsxs48("div", { className: "fd-stack", style: { gap: 14, padding: "0 18px 16px" }, children: [
6191
- /* @__PURE__ */ jsxs48("div", { className: "fd-stack", style: { gap: 6 }, children: [
6192
- /* @__PURE__ */ jsx53("span", { className: "fd-body-sm", style: { fontWeight: 700 }, children: s.title }),
6193
- /* @__PURE__ */ jsx53("p", { className: "fd-body-sm fd-secondary", style: { margin: 0, textWrap: "pretty" }, children: s.purpose }),
6194
- s.usedBy && s.usedBy.length ? /* @__PURE__ */ jsx53("span", { className: "fd-row", style: { gap: 6, flexWrap: "wrap" }, children: s.usedBy.map((u) => /* @__PURE__ */ jsx53(Tag, { children: u }, u)) }) : null
6433
+ /* @__PURE__ */ jsxs51("div", { className: "fd-stack", style: { gap: 14, padding: "0 18px 16px" }, children: [
6434
+ /* @__PURE__ */ jsxs51("div", { className: "fd-stack", style: { gap: 6 }, children: [
6435
+ /* @__PURE__ */ jsx56("span", { className: "fd-body-sm", style: { fontWeight: 700 }, children: s.title }),
6436
+ /* @__PURE__ */ jsx56("p", { className: "fd-body-sm fd-secondary", style: { margin: 0, textWrap: "pretty" }, children: s.purpose }),
6437
+ s.usedBy && s.usedBy.length ? /* @__PURE__ */ jsx56("span", { className: "fd-row", style: { gap: 6, flexWrap: "wrap" }, children: s.usedBy.map((u) => /* @__PURE__ */ jsx56(Tag, { children: u }, u)) }) : null
6195
6438
  ] }),
6196
- /* @__PURE__ */ jsxs48("div", { style: { display: "grid", gridTemplateColumns: "repeat(auto-fit,minmax(280px,1fr))", gap: 12, alignItems: "start" }, children: [
6197
- s.request ? /* @__PURE__ */ jsxs48("div", { className: "fd-stack", style: { gap: 6 }, children: [
6198
- /* @__PURE__ */ jsx53("span", { className: "fd-overline fd-muted", children: "Request body" }),
6199
- /* @__PURE__ */ jsx53(Json, { obj: s.request })
6439
+ /* @__PURE__ */ jsxs51("div", { style: { display: "grid", gridTemplateColumns: "repeat(auto-fit,minmax(280px,1fr))", gap: 12, alignItems: "start" }, children: [
6440
+ s.request ? /* @__PURE__ */ jsxs51("div", { className: "fd-stack", style: { gap: 6 }, children: [
6441
+ /* @__PURE__ */ jsx56("span", { className: "fd-overline fd-muted", children: "Request body" }),
6442
+ /* @__PURE__ */ jsx56(Json, { obj: s.request })
6200
6443
  ] }) : null,
6201
- s.query ? /* @__PURE__ */ jsxs48("div", { className: "fd-stack", style: { gap: 6 }, children: [
6202
- /* @__PURE__ */ jsx53("span", { className: "fd-overline fd-muted", children: "Query" }),
6203
- /* @__PURE__ */ jsx53(Json, { obj: s.query })
6444
+ s.query ? /* @__PURE__ */ jsxs51("div", { className: "fd-stack", style: { gap: 6 }, children: [
6445
+ /* @__PURE__ */ jsx56("span", { className: "fd-overline fd-muted", children: "Query" }),
6446
+ /* @__PURE__ */ jsx56(Json, { obj: s.query })
6204
6447
  ] }) : null,
6205
- /* @__PURE__ */ jsxs48("div", { className: "fd-stack", style: { gap: 6 }, children: [
6206
- /* @__PURE__ */ jsx53("span", { className: "fd-overline fd-muted", children: "Response 200" }),
6207
- /* @__PURE__ */ jsx53(Json, { obj: s.response })
6448
+ /* @__PURE__ */ jsxs51("div", { className: "fd-stack", style: { gap: 6 }, children: [
6449
+ /* @__PURE__ */ jsx56("span", { className: "fd-overline fd-muted", children: "Response 200" }),
6450
+ /* @__PURE__ */ jsx56(Json, { obj: s.response })
6208
6451
  ] })
6209
6452
  ] }),
6210
- s.notes ? /* @__PURE__ */ jsx53(Flag, { tone: "info", statement: "Implementation note", cost: s.notes, actions: null }) : null,
6211
- tried && tried !== "busy" ? /* @__PURE__ */ jsxs48("div", { className: "fd-stack", style: { gap: 6 }, children: [
6212
- /* @__PURE__ */ jsxs48("span", { className: "fd-row", style: { gap: 8 }, children: [
6213
- /* @__PURE__ */ jsx53("span", { className: "fd-overline fd-muted", children: "Simulated response" }),
6214
- /* @__PURE__ */ jsxs48(Badge, { tone: tried.error ? "danger" : "success", icon: "timer", children: [
6453
+ s.notes ? /* @__PURE__ */ jsx56(Flag, { tone: "info", statement: "Implementation note", cost: s.notes, actions: null }) : null,
6454
+ tried && tried !== "busy" ? /* @__PURE__ */ jsxs51("div", { className: "fd-stack", style: { gap: 6 }, children: [
6455
+ /* @__PURE__ */ jsxs51("span", { className: "fd-row", style: { gap: 8 }, children: [
6456
+ /* @__PURE__ */ jsx56("span", { className: "fd-overline fd-muted", children: "Simulated response" }),
6457
+ /* @__PURE__ */ jsxs51(Badge, { tone: tried.error ? "danger" : "success", icon: "timer", children: [
6215
6458
  tried.ms,
6216
6459
  "ms"
6217
6460
  ] })
6218
6461
  ] }),
6219
- /* @__PURE__ */ jsx53(Json, { obj: tried.error ? { error: tried.error } : tried.data })
6462
+ /* @__PURE__ */ jsx56(Json, { obj: tried.error ? { error: tried.error } : tried.data })
6220
6463
  ] }) : null
6221
6464
  ] })
6222
6465
  ] }) });
@@ -6235,58 +6478,58 @@ function ApiSpecBrowser({
6235
6478
  className = "",
6236
6479
  ...rest
6237
6480
  }) {
6238
- const [q, setQ] = React26.useState("");
6239
- const [method, setMethod] = React26.useState(null);
6240
- const [mod, setMod] = React26.useState(null);
6241
- const [listOnly, setListOnly] = React26.useState(false);
6481
+ const [q, setQ] = React28.useState("");
6482
+ const [method, setMethod] = React28.useState(null);
6483
+ const [mod, setMod] = React28.useState(null);
6484
+ const [listOnly, setListOnly] = React28.useState(false);
6242
6485
  const activeModule = modules && modules.find((m) => m.id === mod);
6243
6486
  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())));
6244
6487
  const effGroups = groups && groups.length ? groups : [["All endpoints", spec.map((s) => s.id)]];
6245
6488
  const methods = [...new Set(spec.map((s) => s.method))];
6246
6489
  const listCount = spec.filter((s) => s.isList).length;
6247
- return /* @__PURE__ */ jsxs48("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 20, maxWidth: 1100 }, ...rest, children: [
6248
- /* @__PURE__ */ jsxs48("div", { className: "fd-stack", style: { gap: 10 }, children: [
6249
- kicker ? /* @__PURE__ */ jsx53("span", { className: "fd-overline fd-muted", children: kicker }) : null,
6250
- /* @__PURE__ */ jsx53("h1", { className: "fd-h1", style: { margin: 0 }, children: title }),
6251
- lede ? /* @__PURE__ */ jsx53("p", { className: "fd-body fd-secondary fd-prose", style: { margin: 0 }, children: lede }) : null
6490
+ return /* @__PURE__ */ jsxs51("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 20, maxWidth: 1100 }, ...rest, children: [
6491
+ /* @__PURE__ */ jsxs51("div", { className: "fd-stack", style: { gap: 10 }, children: [
6492
+ kicker ? /* @__PURE__ */ jsx56("span", { className: "fd-overline fd-muted", children: kicker }) : null,
6493
+ /* @__PURE__ */ jsx56("h1", { className: "fd-h1", style: { margin: 0 }, children: title }),
6494
+ lede ? /* @__PURE__ */ jsx56("p", { className: "fd-body fd-secondary fd-prose", style: { margin: 0 }, children: lede }) : null
6252
6495
  ] }),
6253
- modules && modules.length ? /* @__PURE__ */ jsxs48("div", { className: "fd-stack", style: { gap: 8 }, children: [
6254
- /* @__PURE__ */ jsx53("span", { className: "fd-overline fd-muted", children: "Filter by screen \u2014 every endpoint that screen depends on" }),
6255
- /* @__PURE__ */ jsxs48("div", { className: "fd-row", style: { gap: 8, flexWrap: "wrap" }, children: [
6256
- /* @__PURE__ */ jsxs48(Tag, { icon: "stack", selected: !mod, onClick: () => setMod(null), children: [
6496
+ modules && modules.length ? /* @__PURE__ */ jsxs51("div", { className: "fd-stack", style: { gap: 8 }, children: [
6497
+ /* @__PURE__ */ jsx56("span", { className: "fd-overline fd-muted", children: "Filter by screen \u2014 every endpoint that screen depends on" }),
6498
+ /* @__PURE__ */ jsxs51("div", { className: "fd-row", style: { gap: 8, flexWrap: "wrap" }, children: [
6499
+ /* @__PURE__ */ jsxs51(Tag, { icon: "stack", selected: !mod, onClick: () => setMod(null), children: [
6257
6500
  "All screens ",
6258
- /* @__PURE__ */ jsx53("span", { className: "fd-mono", children: spec.length })
6501
+ /* @__PURE__ */ jsx56("span", { className: "fd-mono", children: spec.length })
6259
6502
  ] }),
6260
- modules.map((m) => /* @__PURE__ */ jsxs48(Tag, { icon: m.icon, selected: mod === m.id, onClick: () => setMod(mod === m.id ? null : m.id), children: [
6503
+ modules.map((m) => /* @__PURE__ */ jsxs51(Tag, { icon: m.icon, selected: mod === m.id, onClick: () => setMod(mod === m.id ? null : m.id), children: [
6261
6504
  m.label,
6262
6505
  " ",
6263
- /* @__PURE__ */ jsx53("span", { className: "fd-mono", children: m.endpoints.length })
6506
+ /* @__PURE__ */ jsx56("span", { className: "fd-mono", children: m.endpoints.length })
6264
6507
  ] }, m.id))
6265
6508
  ] }),
6266
- activeModule ? /* @__PURE__ */ jsx53(
6509
+ activeModule ? /* @__PURE__ */ jsx56(
6267
6510
  Flag,
6268
6511
  {
6269
6512
  tone: "info",
6270
6513
  statement: activeModule.label + " calls " + activeModule.endpoints.length + " endpoints.",
6271
6514
  cost: "Integration checklist for this screen: " + activeModule.endpoints.join(", ") + ". Wire these and the screen is done.",
6272
- actions: /* @__PURE__ */ jsx53(Button, { size: "sm", variant: "ghost", icon: "x", onClick: () => setMod(null), children: "Show all screens" })
6515
+ actions: /* @__PURE__ */ jsx56(Button, { size: "sm", variant: "ghost", icon: "x", onClick: () => setMod(null), children: "Show all screens" })
6273
6516
  }
6274
6517
  ) : null
6275
6518
  ] }) : null,
6276
- sourceNote ? /* @__PURE__ */ jsx53(Flag, { tone: "info", statement: "Design-first: this page is the spec.", cost: sourceNote, actions: null }) : null,
6277
- /* @__PURE__ */ jsxs48("div", { className: "fd-row", style: { gap: 10, flexWrap: "wrap" }, children: [
6278
- /* @__PURE__ */ jsx53(Input, { icon: "magnifying-glass", placeholder: "Find an endpoint, screen, or behavior", value: q, onChange: (e) => setQ(e.target.value), style: { width: 300 } }),
6279
- methods.map((m) => /* @__PURE__ */ jsxs48(Tag, { selected: method === m, onClick: () => setMethod(method === m ? null : m), children: [
6519
+ sourceNote ? /* @__PURE__ */ jsx56(Flag, { tone: "info", statement: "Design-first: this page is the spec.", cost: sourceNote, actions: null }) : null,
6520
+ /* @__PURE__ */ jsxs51("div", { className: "fd-row", style: { gap: 10, flexWrap: "wrap" }, children: [
6521
+ /* @__PURE__ */ jsx56(Input, { icon: "magnifying-glass", placeholder: "Find an endpoint, screen, or behavior", value: q, onChange: (e) => setQ(e.target.value), style: { width: 300 } }),
6522
+ methods.map((m) => /* @__PURE__ */ jsxs51(Tag, { selected: method === m, onClick: () => setMethod(method === m ? null : m), children: [
6280
6523
  m,
6281
6524
  " ",
6282
- /* @__PURE__ */ jsx53("span", { className: "fd-mono", children: spec.filter((s) => s.method === m).length })
6525
+ /* @__PURE__ */ jsx56("span", { className: "fd-mono", children: spec.filter((s) => s.method === m).length })
6283
6526
  ] }, m)),
6284
- listCount ? /* @__PURE__ */ jsxs48(Tag, { icon: "rows", selected: listOnly, onClick: () => setListOnly(!listOnly), children: [
6527
+ listCount ? /* @__PURE__ */ jsxs51(Tag, { icon: "rows", selected: listOnly, onClick: () => setListOnly(!listOnly), children: [
6285
6528
  "Paged lists ",
6286
- /* @__PURE__ */ jsx53("span", { className: "fd-mono", children: listCount })
6529
+ /* @__PURE__ */ jsx56("span", { className: "fd-mono", children: listCount })
6287
6530
  ] }) : null,
6288
- /* @__PURE__ */ jsx53("span", { style: { flex: 1 } }),
6289
- /* @__PURE__ */ jsxs48("span", { className: "fd-body-sm fd-muted", children: [
6531
+ /* @__PURE__ */ jsx56("span", { style: { flex: 1 } }),
6532
+ /* @__PURE__ */ jsxs51("span", { className: "fd-body-sm fd-muted", children: [
6290
6533
  hits.length,
6291
6534
  " of ",
6292
6535
  spec.length,
@@ -6294,31 +6537,31 @@ function ApiSpecBrowser({
6294
6537
  listCount ? " \xB7 " + listCount + " paged" : ""
6295
6538
  ] })
6296
6539
  ] }),
6297
- hits.length === 0 ? /* @__PURE__ */ jsx53(Card, { elevation: "flat", children: /* @__PURE__ */ jsx53("p", { className: "fd-body-sm fd-muted", style: { margin: 0 }, children: "No endpoint matches those filters." }) }) : effGroups.map(([g, ids]) => {
6540
+ hits.length === 0 ? /* @__PURE__ */ jsx56(Card, { elevation: "flat", children: /* @__PURE__ */ jsx56("p", { className: "fd-body-sm fd-muted", style: { margin: 0 }, children: "No endpoint matches those filters." }) }) : effGroups.map(([g, ids]) => {
6298
6541
  const items = hits.filter((s) => ids.indexOf(s.id) >= 0);
6299
6542
  if (!items.length) return null;
6300
- return /* @__PURE__ */ jsxs48("div", { className: "fd-stack", style: { gap: 12 }, children: [
6301
- /* @__PURE__ */ jsx53("span", { className: "fd-label-lg", children: g }),
6302
- items.map((s) => /* @__PURE__ */ jsx53(Endpoint, { s, onRequest }, s.id))
6543
+ return /* @__PURE__ */ jsxs51("div", { className: "fd-stack", style: { gap: 12 }, children: [
6544
+ /* @__PURE__ */ jsx56("span", { className: "fd-label-lg", children: g }),
6545
+ items.map((s) => /* @__PURE__ */ jsx56(Endpoint, { s, onRequest }, s.id))
6303
6546
  ] }, g);
6304
6547
  }),
6305
- conventions && conventions.length ? /* @__PURE__ */ jsx53(Card, { title: "Cross-cutting conventions", elevation: "flat", children: /* @__PURE__ */ jsx53("div", { className: "fd-stack", style: { gap: 10 }, children: conventions.map(([k, v]) => /* @__PURE__ */ jsxs48("div", { className: "fd-row", style: { gap: 12, alignItems: "flex-start" }, children: [
6306
- /* @__PURE__ */ jsx53("span", { className: "fd-overline fd-muted", style: { width: 110, flex: "none", paddingTop: 2 }, children: k }),
6307
- /* @__PURE__ */ jsx53("span", { className: "fd-body-sm fd-secondary", style: { textWrap: "pretty" }, children: v })
6548
+ conventions && conventions.length ? /* @__PURE__ */ jsx56(Card, { title: "Cross-cutting conventions", elevation: "flat", children: /* @__PURE__ */ jsx56("div", { className: "fd-stack", style: { gap: 10 }, children: conventions.map(([k, v]) => /* @__PURE__ */ jsxs51("div", { className: "fd-row", style: { gap: 12, alignItems: "flex-start" }, children: [
6549
+ /* @__PURE__ */ jsx56("span", { className: "fd-overline fd-muted", style: { width: 110, flex: "none", paddingTop: 2 }, children: k }),
6550
+ /* @__PURE__ */ jsx56("span", { className: "fd-body-sm fd-secondary", style: { textWrap: "pretty" }, children: v })
6308
6551
  ] }, k)) }) }) : null,
6309
- openQuestions && openQuestions.length ? /* @__PURE__ */ jsx53(Collapsible, { icon: "list-checks", title: "Open questions before implementation", subtitle: openQuestions.length + " unresolved", children: /* @__PURE__ */ jsx53("div", { className: "fd-stack", style: { gap: 8 }, children: openQuestions.map(([id, question, why]) => /* @__PURE__ */ jsxs48("div", { className: "fd-row", style: { gap: 10, alignItems: "flex-start", padding: "8px 0", borderTop: "1px solid var(--border)" }, children: [
6310
- /* @__PURE__ */ jsx53(Badge, { tone: "danger", children: id }),
6311
- /* @__PURE__ */ jsxs48("span", { className: "fd-stack", style: { gap: 2, flex: 1 }, children: [
6312
- /* @__PURE__ */ jsx53("span", { className: "fd-body-sm", style: { fontWeight: 600 }, children: question }),
6313
- /* @__PURE__ */ jsx53("span", { className: "fd-body-sm fd-muted", children: why })
6552
+ openQuestions && openQuestions.length ? /* @__PURE__ */ jsx56(Collapsible, { icon: "list-checks", title: "Open questions before implementation", subtitle: openQuestions.length + " unresolved", children: /* @__PURE__ */ jsx56("div", { className: "fd-stack", style: { gap: 8 }, children: openQuestions.map(([id, question, why]) => /* @__PURE__ */ jsxs51("div", { className: "fd-row", style: { gap: 10, alignItems: "flex-start", padding: "8px 0", borderTop: "1px solid var(--border)" }, children: [
6553
+ /* @__PURE__ */ jsx56(Badge, { tone: "danger", children: id }),
6554
+ /* @__PURE__ */ jsxs51("span", { className: "fd-stack", style: { gap: 2, flex: 1 }, children: [
6555
+ /* @__PURE__ */ jsx56("span", { className: "fd-body-sm", style: { fontWeight: 600 }, children: question }),
6556
+ /* @__PURE__ */ jsx56("span", { className: "fd-body-sm fd-muted", children: why })
6314
6557
  ] })
6315
6558
  ] }, id)) }) }) : null
6316
6559
  ] });
6317
6560
  }
6318
6561
 
6319
6562
  // src/components/platform/ProfilePage.tsx
6320
- import * as React27 from "react";
6321
- import { jsx as jsx54, jsxs as jsxs49 } from "react/jsx-runtime";
6563
+ import * as React29 from "react";
6564
+ import { jsx as jsx57, jsxs as jsxs52 } from "react/jsx-runtime";
6322
6565
  var TIMEZONES = ["America/New_York", "America/Chicago", "America/Denver", "America/Los_Angeles", "America/Anchorage", "Pacific/Honolulu", "Europe/London", "Europe/Berlin"];
6323
6566
  var NOTIFY = [
6324
6567
  { key: "planShared", label: "A plan is shared with me", detail: "Someone sends you a plan or a client link." },
@@ -6330,7 +6573,7 @@ var NOTIFY = [
6330
6573
  function ProfilePage({ user: userProp, onSave, onNavigate, sessions, showSessions = true, className = "", ...rest }) {
6331
6574
  const session = SessionKit.useSession();
6332
6575
  const user = userProp || session.user;
6333
- const [draft, setDraft] = React27.useState(() => ({
6576
+ const [draft, setDraft] = React29.useState(() => ({
6334
6577
  name: user.name || "",
6335
6578
  title: user.title || "",
6336
6579
  email: user.email || "",
@@ -6339,8 +6582,8 @@ function ProfilePage({ user: userProp, onSave, onNavigate, sessions, showSession
6339
6582
  bio: user.bio || "",
6340
6583
  notify: user.notify || { planShared: true, planChanged: true, goalMissed: true, flagChanged: false, weekly: true }
6341
6584
  }));
6342
- const [saving, setSaving] = React27.useState(false);
6343
- const [saved, setSaved] = React27.useState(false);
6585
+ const [saving, setSaving] = React29.useState(false);
6586
+ const [saved, setSaved] = React29.useState(false);
6344
6587
  const set = (k, v) => {
6345
6588
  setDraft((d) => Object.assign({}, d, { [k]: v }));
6346
6589
  setSaved(false);
@@ -6362,43 +6605,43 @@ function ProfilePage({ user: userProp, onSave, onNavigate, sessions, showSession
6362
6605
  { id: "s2", device: "iPhone 15 \xB7 Safari", where: "Denver, CO", when: "2 hours ago" },
6363
6606
  { id: "s3", device: "Windows \xB7 Edge", where: "Chicago, IL", when: "Aug 12" }
6364
6607
  ];
6365
- return /* @__PURE__ */ jsxs49("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 20, maxWidth: 860 }, ...rest, children: [
6366
- /* @__PURE__ */ jsxs49("div", { className: "fd-stack", style: { gap: 10 }, children: [
6367
- /* @__PURE__ */ jsx54("span", { className: "fd-overline fd-muted", children: "Account" }),
6368
- /* @__PURE__ */ jsx54("h1", { className: "fd-h1", style: { margin: 0 }, children: "Your profile" }),
6369
- /* @__PURE__ */ jsx54("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." })
6608
+ return /* @__PURE__ */ jsxs52("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 20, maxWidth: 860 }, ...rest, children: [
6609
+ /* @__PURE__ */ jsxs52("div", { className: "fd-stack", style: { gap: 10 }, children: [
6610
+ /* @__PURE__ */ jsx57("span", { className: "fd-overline fd-muted", children: "Account" }),
6611
+ /* @__PURE__ */ jsx57("h1", { className: "fd-h1", style: { margin: 0 }, children: "Your profile" }),
6612
+ /* @__PURE__ */ jsx57("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." })
6370
6613
  ] }),
6371
- /* @__PURE__ */ jsx54(Card, { elevation: "flat", children: /* @__PURE__ */ jsxs49("div", { className: "fd-row", style: { gap: 16, flexWrap: "wrap", alignItems: "flex-start" }, children: [
6372
- /* @__PURE__ */ jsx54(Avatar, { name: draft.name || user.name, size: "lg" }),
6373
- /* @__PURE__ */ jsxs49("div", { className: "fd-stack", style: { gap: 4, flex: 1, minWidth: 200 }, children: [
6374
- /* @__PURE__ */ jsx54("span", { className: "fd-h3", style: { margin: 0 }, children: draft.name || user.name }),
6375
- /* @__PURE__ */ jsxs49("span", { className: "fd-body-sm fd-muted", children: [
6614
+ /* @__PURE__ */ jsx57(Card, { elevation: "flat", children: /* @__PURE__ */ jsxs52("div", { className: "fd-row", style: { gap: 16, flexWrap: "wrap", alignItems: "flex-start" }, children: [
6615
+ /* @__PURE__ */ jsx57(Avatar, { name: draft.name || user.name, size: "lg" }),
6616
+ /* @__PURE__ */ jsxs52("div", { className: "fd-stack", style: { gap: 4, flex: 1, minWidth: 200 }, children: [
6617
+ /* @__PURE__ */ jsx57("span", { className: "fd-h3", style: { margin: 0 }, children: draft.name || user.name }),
6618
+ /* @__PURE__ */ jsxs52("span", { className: "fd-body-sm fd-muted", children: [
6376
6619
  draft.title || "No title set",
6377
6620
  " \xB7 ",
6378
6621
  user.team || "No team"
6379
6622
  ] }),
6380
- /* @__PURE__ */ jsxs49("span", { className: "fd-row", style: { gap: 6, flexWrap: "wrap", paddingTop: 4 }, children: [
6381
- session.roles.map((r) => /* @__PURE__ */ jsx54(Badge, { tone: r.id === "owner" ? "success" : "neutral", children: r.name }, r.id)),
6382
- user.sso ? /* @__PURE__ */ jsx54(Badge, { tone: "info", icon: "shield-check", children: "SSO" }) : null
6623
+ /* @__PURE__ */ jsxs52("span", { className: "fd-row", style: { gap: 6, flexWrap: "wrap", paddingTop: 4 }, children: [
6624
+ session.roles.map((r) => /* @__PURE__ */ jsx57(Badge, { tone: r.id === "owner" ? "success" : "neutral", children: r.name }, r.id)),
6625
+ user.sso ? /* @__PURE__ */ jsx57(Badge, { tone: "info", icon: "shield-check", children: "SSO" }) : null
6383
6626
  ] })
6384
6627
  ] }),
6385
- /* @__PURE__ */ jsx54(Button, { variant: "secondary", size: "sm", icon: "image", children: "Change photo" })
6628
+ /* @__PURE__ */ jsx57(Button, { variant: "secondary", size: "sm", icon: "image", children: "Change photo" })
6386
6629
  ] }) }),
6387
- /* @__PURE__ */ jsx54(
6630
+ /* @__PURE__ */ jsx57(
6388
6631
  Card,
6389
6632
  {
6390
- title: /* @__PURE__ */ jsxs49("span", { className: "fd-stack", style: { gap: 2 }, children: [
6391
- /* @__PURE__ */ jsx54("span", { children: "Identity" }),
6392
- /* @__PURE__ */ jsx54("span", { className: "fd-body-sm fd-muted", style: { fontWeight: 400 }, children: "Name and title appear on plans you share" })
6633
+ title: /* @__PURE__ */ jsxs52("span", { className: "fd-stack", style: { gap: 2 }, children: [
6634
+ /* @__PURE__ */ jsx57("span", { children: "Identity" }),
6635
+ /* @__PURE__ */ jsx57("span", { className: "fd-body-sm fd-muted", style: { fontWeight: 400 }, children: "Name and title appear on plans you share" })
6393
6636
  ] }),
6394
6637
  elevation: "flat",
6395
- children: /* @__PURE__ */ jsxs49("div", { className: "fd-stack", style: { gap: 14 }, children: [
6396
- /* @__PURE__ */ jsxs49("div", { style: { display: "grid", gridTemplateColumns: "repeat(auto-fit,minmax(220px,1fr))", gap: 14 }, children: [
6397
- /* @__PURE__ */ jsx54(Input, { label: "Full name", value: draft.name, onChange: (e) => set("name", e.target.value) }),
6398
- /* @__PURE__ */ jsx54(Input, { label: "Job title", value: draft.title, onChange: (e) => set("title", e.target.value), placeholder: "e.g. Senior media planner" })
6638
+ children: /* @__PURE__ */ jsxs52("div", { className: "fd-stack", style: { gap: 14 }, children: [
6639
+ /* @__PURE__ */ jsxs52("div", { style: { display: "grid", gridTemplateColumns: "repeat(auto-fit,minmax(220px,1fr))", gap: 14 }, children: [
6640
+ /* @__PURE__ */ jsx57(Input, { label: "Full name", value: draft.name, onChange: (e) => set("name", e.target.value) }),
6641
+ /* @__PURE__ */ jsx57(Input, { label: "Job title", value: draft.title, onChange: (e) => set("title", e.target.value), placeholder: "e.g. Senior media planner" })
6399
6642
  ] }),
6400
- /* @__PURE__ */ jsxs49("div", { style: { display: "grid", gridTemplateColumns: "repeat(auto-fit,minmax(220px,1fr))", gap: 14 }, children: [
6401
- /* @__PURE__ */ jsx54(
6643
+ /* @__PURE__ */ jsxs52("div", { style: { display: "grid", gridTemplateColumns: "repeat(auto-fit,minmax(220px,1fr))", gap: 14 }, children: [
6644
+ /* @__PURE__ */ jsx57(
6402
6645
  Input,
6403
6646
  {
6404
6647
  label: "Work email",
@@ -6408,9 +6651,9 @@ function ProfilePage({ user: userProp, onSave, onNavigate, sessions, showSession
6408
6651
  help: user.sso ? "Managed by your identity provider \u2014 change it there." : "Contact an administrator to change this."
6409
6652
  }
6410
6653
  ),
6411
- /* @__PURE__ */ jsx54(Input, { label: "Phone", value: draft.phone, onChange: (e) => set("phone", e.target.value), placeholder: "Optional" })
6654
+ /* @__PURE__ */ jsx57(Input, { label: "Phone", value: draft.phone, onChange: (e) => set("phone", e.target.value), placeholder: "Optional" })
6412
6655
  ] }),
6413
- /* @__PURE__ */ jsx54(
6656
+ /* @__PURE__ */ jsx57(
6414
6657
  Textarea,
6415
6658
  {
6416
6659
  label: "Short bio",
@@ -6424,8 +6667,8 @@ function ProfilePage({ user: userProp, onSave, onNavigate, sessions, showSession
6424
6667
  ] })
6425
6668
  }
6426
6669
  ),
6427
- /* @__PURE__ */ jsx54(Card, { title: "Working preferences", elevation: "flat", children: /* @__PURE__ */ jsxs49("div", { style: { display: "grid", gridTemplateColumns: "repeat(auto-fit,minmax(220px,1fr))", gap: 14 }, children: [
6428
- /* @__PURE__ */ jsx54(
6670
+ /* @__PURE__ */ jsx57(Card, { title: "Working preferences", elevation: "flat", children: /* @__PURE__ */ jsxs52("div", { style: { display: "grid", gridTemplateColumns: "repeat(auto-fit,minmax(220px,1fr))", gap: 14 }, children: [
6671
+ /* @__PURE__ */ jsx57(
6429
6672
  Select,
6430
6673
  {
6431
6674
  label: "Time zone",
@@ -6435,28 +6678,28 @@ function ProfilePage({ user: userProp, onSave, onNavigate, sessions, showSession
6435
6678
  help: "Flight dates and schedules render in this zone."
6436
6679
  }
6437
6680
  ),
6438
- /* @__PURE__ */ jsx54(Select, { label: "Start of week", options: ["Monday", "Sunday"], placeholder: "Monday" })
6681
+ /* @__PURE__ */ jsx57(Select, { label: "Start of week", options: ["Monday", "Sunday"], placeholder: "Monday" })
6439
6682
  ] }) }),
6440
- /* @__PURE__ */ jsx54(
6683
+ /* @__PURE__ */ jsx57(
6441
6684
  Card,
6442
6685
  {
6443
- title: /* @__PURE__ */ jsxs49("span", { className: "fd-stack", style: { gap: 2 }, children: [
6444
- /* @__PURE__ */ jsx54("span", { children: "Notifications" }),
6445
- /* @__PURE__ */ jsx54("span", { className: "fd-body-sm fd-muted", style: { fontWeight: 400 }, children: "Email only for now \u2014 in-app notifications are on the roadmap" })
6686
+ title: /* @__PURE__ */ jsxs52("span", { className: "fd-stack", style: { gap: 2 }, children: [
6687
+ /* @__PURE__ */ jsx57("span", { children: "Notifications" }),
6688
+ /* @__PURE__ */ jsx57("span", { className: "fd-body-sm fd-muted", style: { fontWeight: 400 }, children: "Email only for now \u2014 in-app notifications are on the roadmap" })
6446
6689
  ] }),
6447
6690
  elevation: "flat",
6448
- children: /* @__PURE__ */ jsx54("div", { className: "fd-stack", style: { gap: 14 }, children: NOTIFY.map((n) => /* @__PURE__ */ jsx54(Switch, { checked: !!draft.notify[n.key], onChange: () => setNotify(n.key), label: n.label, description: n.detail }, n.key)) })
6691
+ children: /* @__PURE__ */ jsx57("div", { className: "fd-stack", style: { gap: 14 }, children: NOTIFY.map((n) => /* @__PURE__ */ jsx57(Switch, { checked: !!draft.notify[n.key], onChange: () => setNotify(n.key), label: n.label, description: n.detail }, n.key)) })
6449
6692
  }
6450
6693
  ),
6451
- /* @__PURE__ */ jsxs49(
6694
+ /* @__PURE__ */ jsxs52(
6452
6695
  Card,
6453
6696
  {
6454
- title: /* @__PURE__ */ jsxs49("span", { className: "fd-stack", style: { gap: 2 }, children: [
6455
- /* @__PURE__ */ jsx54("span", { children: "Access" }),
6456
- /* @__PURE__ */ jsx54("span", { className: "fd-body-sm fd-muted", style: { fontWeight: 400 }, children: "What your roles grant you" })
6697
+ title: /* @__PURE__ */ jsxs52("span", { className: "fd-stack", style: { gap: 2 }, children: [
6698
+ /* @__PURE__ */ jsx57("span", { children: "Access" }),
6699
+ /* @__PURE__ */ jsx57("span", { className: "fd-body-sm fd-muted", style: { fontWeight: 400 }, children: "What your roles grant you" })
6457
6700
  ] }),
6458
6701
  elevation: "flat",
6459
- action: /* @__PURE__ */ jsx54(
6702
+ action: /* @__PURE__ */ jsx57(
6460
6703
  Button,
6461
6704
  {
6462
6705
  size: "sm",
@@ -6467,39 +6710,39 @@ function ProfilePage({ user: userProp, onSave, onNavigate, sessions, showSession
6467
6710
  }
6468
6711
  ),
6469
6712
  children: [
6470
- /* @__PURE__ */ jsxs49("div", { className: "fd-stack", style: { gap: 0 }, children: [
6471
- /* @__PURE__ */ jsx54(CardRow, { label: "Roles", children: session.roles.map((r) => r.name).join(", ") || "None" }),
6472
- /* @__PURE__ */ jsxs49(CardRow, { label: "Permissions", children: [
6713
+ /* @__PURE__ */ jsxs52("div", { className: "fd-stack", style: { gap: 0 }, children: [
6714
+ /* @__PURE__ */ jsx57(CardRow, { label: "Roles", children: session.roles.map((r) => r.name).join(", ") || "None" }),
6715
+ /* @__PURE__ */ jsxs52(CardRow, { label: "Permissions", children: [
6473
6716
  session.permissions.length,
6474
6717
  " granted"
6475
6718
  ] }),
6476
- /* @__PURE__ */ jsx54(CardRow, { label: "Member since", children: user.joined || "\u2014" })
6719
+ /* @__PURE__ */ jsx57(CardRow, { label: "Member since", children: user.joined || "\u2014" })
6477
6720
  ] }),
6478
- /* @__PURE__ */ jsx54("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." })
6721
+ /* @__PURE__ */ jsx57("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." })
6479
6722
  ]
6480
6723
  }
6481
6724
  ),
6482
- showSessions ? /* @__PURE__ */ jsx54(
6725
+ showSessions ? /* @__PURE__ */ jsx57(
6483
6726
  Card,
6484
6727
  {
6485
6728
  title: "Signed-in devices",
6486
6729
  elevation: "flat",
6487
- action: /* @__PURE__ */ jsx54(Button, { size: "sm", variant: "ghost", icon: "sign-out", children: "Sign out everywhere" }),
6488
- children: /* @__PURE__ */ jsx54("div", { className: "fd-stack", style: { gap: 0 }, children: liveSessions.map((s) => /* @__PURE__ */ jsxs49("div", { className: "fd-row", style: { gap: 12, padding: "10px 0", borderTop: "1px solid var(--border)", flexWrap: "wrap" }, children: [
6489
- /* @__PURE__ */ jsx54("i", { className: "ph ph-device-mobile", style: { fontSize: 16, color: "var(--text-muted)" }, "aria-hidden": "true" }),
6490
- /* @__PURE__ */ jsxs49("span", { className: "fd-stack", style: { gap: 1, flex: 1, minWidth: 160 }, children: [
6491
- /* @__PURE__ */ jsx54("span", { className: "fd-body-sm", style: { fontWeight: 600 }, children: s.device }),
6492
- /* @__PURE__ */ jsxs49("span", { className: "fd-body-sm fd-muted", children: [
6730
+ action: /* @__PURE__ */ jsx57(Button, { size: "sm", variant: "ghost", icon: "sign-out", children: "Sign out everywhere" }),
6731
+ children: /* @__PURE__ */ jsx57("div", { className: "fd-stack", style: { gap: 0 }, children: liveSessions.map((s) => /* @__PURE__ */ jsxs52("div", { className: "fd-row", style: { gap: 12, padding: "10px 0", borderTop: "1px solid var(--border)", flexWrap: "wrap" }, children: [
6732
+ /* @__PURE__ */ jsx57("i", { className: "ph ph-device-mobile", style: { fontSize: 16, color: "var(--text-muted)" }, "aria-hidden": "true" }),
6733
+ /* @__PURE__ */ jsxs52("span", { className: "fd-stack", style: { gap: 1, flex: 1, minWidth: 160 }, children: [
6734
+ /* @__PURE__ */ jsx57("span", { className: "fd-body-sm", style: { fontWeight: 600 }, children: s.device }),
6735
+ /* @__PURE__ */ jsxs52("span", { className: "fd-body-sm fd-muted", children: [
6493
6736
  s.where,
6494
6737
  " \xB7 ",
6495
6738
  s.when
6496
6739
  ] })
6497
6740
  ] }),
6498
- s.current ? /* @__PURE__ */ jsx54(Badge, { tone: "success", dot: true, children: "This device" }) : /* @__PURE__ */ jsx54(Button, { size: "sm", variant: "ghost", children: "Revoke" })
6741
+ s.current ? /* @__PURE__ */ jsx57(Badge, { tone: "success", dot: true, children: "This device" }) : /* @__PURE__ */ jsx57(Button, { size: "sm", variant: "ghost", children: "Revoke" })
6499
6742
  ] }, s.id)) })
6500
6743
  }
6501
6744
  ) : null,
6502
- /* @__PURE__ */ jsxs49("div", { className: "fd-row", style: {
6745
+ /* @__PURE__ */ jsxs52("div", { className: "fd-row", style: {
6503
6746
  gap: 10,
6504
6747
  flexWrap: "wrap",
6505
6748
  position: "sticky",
@@ -6510,8 +6753,8 @@ function ProfilePage({ user: userProp, onSave, onNavigate, sessions, showSession
6510
6753
  border: "1px solid var(--border)",
6511
6754
  boxShadow: "0 -4px 16px rgba(11,13,17,.06)"
6512
6755
  }, children: [
6513
- /* @__PURE__ */ jsx54("span", { className: "fd-body-sm", style: { fontWeight: 600, flex: 1 }, children: saved ? "Saved." : dirty ? "Unsaved changes" : "No pending changes" }),
6514
- /* @__PURE__ */ jsx54(
6756
+ /* @__PURE__ */ jsx57("span", { className: "fd-body-sm", style: { fontWeight: 600, flex: 1 }, children: saved ? "Saved." : dirty ? "Unsaved changes" : "No pending changes" }),
6757
+ /* @__PURE__ */ jsx57(
6515
6758
  Button,
6516
6759
  {
6517
6760
  size: "sm",
@@ -6524,16 +6767,16 @@ function ProfilePage({ user: userProp, onSave, onNavigate, sessions, showSession
6524
6767
  children: "Discard"
6525
6768
  }
6526
6769
  ),
6527
- /* @__PURE__ */ jsx54(Button, { size: "sm", icon: "check", disabled: !dirty, loading: saving, onClick: save, children: "Save changes" })
6770
+ /* @__PURE__ */ jsx57(Button, { size: "sm", icon: "check", disabled: !dirty, loading: saving, onClick: save, children: "Save changes" })
6528
6771
  ] })
6529
6772
  ] });
6530
6773
  }
6531
6774
 
6532
6775
  // src/components/platform/RoadmapTimeline.tsx
6533
- import * as React29 from "react";
6776
+ import * as React31 from "react";
6534
6777
 
6535
6778
  // src/kits/runtime.ts
6536
- import * as React28 from "react";
6779
+ import * as React30 from "react";
6537
6780
  var WIRED_ENDPOINTS = [
6538
6781
  // Nothing yet. Every id below would come from a real service:
6539
6782
  // "plan.get", "placements.list", …
@@ -6704,8 +6947,8 @@ var RuntimeKit = {
6704
6947
  };
6705
6948
  RuntimeKit.declare(FEATURE_NEEDS);
6706
6949
  function useRuntimeMode() {
6707
- const [m, setM] = React28.useState(RuntimeKit.getMode());
6708
- React28.useEffect(() => RuntimeKit.subscribe(setM), []);
6950
+ const [m, setM] = React30.useState(RuntimeKit.getMode());
6951
+ React30.useEffect(() => RuntimeKit.subscribe(setM), []);
6709
6952
  return m;
6710
6953
  }
6711
6954
  function useFeatureStatus(key) {
@@ -6724,7 +6967,7 @@ var UseRuntimeMode = useRuntimeMode;
6724
6967
  var UseFeatureStatus = useFeatureStatus;
6725
6968
 
6726
6969
  // src/components/platform/RoadmapTimeline.tsx
6727
- import { jsx as jsx55, jsxs as jsxs50 } from "react/jsx-runtime";
6970
+ import { jsx as jsx58, jsxs as jsxs53 } from "react/jsx-runtime";
6728
6971
  var STATUS = {
6729
6972
  shipped: { tone: "success", icon: "check-circle", label: "Wired" },
6730
6973
  next: { tone: "warning", icon: "traffic-cone", label: "Not wired" },
@@ -6739,45 +6982,45 @@ function RoadmapCard({ item, byKey, onOpenFlag }) {
6739
6982
  const s = STATUS[item.status] || STATUS.planned;
6740
6983
  const deps = (item.dependsOn || []).map((k) => byKey[k]).filter(Boolean);
6741
6984
  const blocking = deps.filter((d) => !d.implemented);
6742
- return /* @__PURE__ */ jsx55(Card, { elevation: "flat", children: /* @__PURE__ */ jsxs50("div", { className: "fd-stack", style: { gap: 10 }, children: [
6743
- /* @__PURE__ */ jsxs50("div", { className: "fd-row", style: { gap: 8, flexWrap: "wrap" }, children: [
6744
- /* @__PURE__ */ jsx55("span", { className: "fd-body", style: { fontWeight: 700, flex: 1, minWidth: 140 }, children: item.label }),
6745
- /* @__PURE__ */ jsx55(Badge, { tone: "neutral", icon: PROJECT_ICON[item.project] || "squares-four", children: item.project }),
6746
- /* @__PURE__ */ jsx55(Badge, { tone: s.tone, icon: s.icon, children: s.label })
6985
+ return /* @__PURE__ */ jsx58(Card, { elevation: "flat", children: /* @__PURE__ */ jsxs53("div", { className: "fd-stack", style: { gap: 10 }, children: [
6986
+ /* @__PURE__ */ jsxs53("div", { className: "fd-row", style: { gap: 8, flexWrap: "wrap" }, children: [
6987
+ /* @__PURE__ */ jsx58("span", { className: "fd-body", style: { fontWeight: 700, flex: 1, minWidth: 140 }, children: item.label }),
6988
+ /* @__PURE__ */ jsx58(Badge, { tone: "neutral", icon: PROJECT_ICON[item.project] || "squares-four", children: item.project }),
6989
+ /* @__PURE__ */ jsx58(Badge, { tone: s.tone, icon: s.icon, children: s.label })
6747
6990
  ] }),
6748
- /* @__PURE__ */ jsx55("p", { className: "fd-body-sm fd-secondary", style: { margin: 0, textWrap: "pretty" }, children: item.description }),
6749
- item.backend ? /* @__PURE__ */ jsxs50("div", { className: "fd-row", style: { gap: 10, alignItems: "flex-start" }, children: [
6750
- /* @__PURE__ */ jsx55("span", { className: "fd-overline fd-muted", style: { width: 62, flex: "none", paddingTop: 2 }, children: "Backend" }),
6751
- /* @__PURE__ */ jsx55("span", { className: "fd-body-sm", style: { flex: 1, textWrap: "pretty" }, children: item.backend })
6991
+ /* @__PURE__ */ jsx58("p", { className: "fd-body-sm fd-secondary", style: { margin: 0, textWrap: "pretty" }, children: item.description }),
6992
+ item.backend ? /* @__PURE__ */ jsxs53("div", { className: "fd-row", style: { gap: 10, alignItems: "flex-start" }, children: [
6993
+ /* @__PURE__ */ jsx58("span", { className: "fd-overline fd-muted", style: { width: 62, flex: "none", paddingTop: 2 }, children: "Backend" }),
6994
+ /* @__PURE__ */ jsx58("span", { className: "fd-body-sm", style: { flex: 1, textWrap: "pretty" }, children: item.backend })
6752
6995
  ] }) : null,
6753
- /* @__PURE__ */ jsxs50("div", { className: "fd-row", style: { gap: 12, flexWrap: "wrap" }, children: [
6754
- item.effort ? /* @__PURE__ */ jsxs50("span", { className: "fd-body-sm fd-muted", children: [
6755
- /* @__PURE__ */ jsx55("i", { className: "ph ph-hourglass-medium" }),
6996
+ /* @__PURE__ */ jsxs53("div", { className: "fd-row", style: { gap: 12, flexWrap: "wrap" }, children: [
6997
+ item.effort ? /* @__PURE__ */ jsxs53("span", { className: "fd-body-sm fd-muted", children: [
6998
+ /* @__PURE__ */ jsx58("i", { className: "ph ph-hourglass-medium" }),
6756
6999
  " ",
6757
7000
  item.effort
6758
7001
  ] }) : null,
6759
- /* @__PURE__ */ jsxs50("span", { className: "fd-body-sm fd-muted", children: [
6760
- /* @__PURE__ */ jsx55("i", { className: "ph ph-user" }),
7002
+ /* @__PURE__ */ jsxs53("span", { className: "fd-body-sm fd-muted", children: [
7003
+ /* @__PURE__ */ jsx58("i", { className: "ph ph-user" }),
6761
7004
  " ",
6762
7005
  item.owner
6763
7006
  ] }),
6764
- item.screen ? /* @__PURE__ */ jsx55(Badge, { tone: "neutral", icon: "browser", children: "screen" }) : null,
6765
- /* @__PURE__ */ jsx55("span", { style: { flex: 1 } }),
6766
- /* @__PURE__ */ jsx55(
7007
+ item.screen ? /* @__PURE__ */ jsx58(Badge, { tone: "neutral", icon: "browser", children: "screen" }) : null,
7008
+ /* @__PURE__ */ jsx58("span", { style: { flex: 1 } }),
7009
+ /* @__PURE__ */ jsx58(
6767
7010
  "button",
6768
7011
  {
6769
7012
  type: "button",
6770
7013
  onClick: () => onOpenFlag && onOpenFlag(item.key),
6771
7014
  style: { all: "unset", cursor: "pointer", display: "inline-flex", alignItems: "center", gap: 5 },
6772
- children: /* @__PURE__ */ jsx55("code", { className: "fd-mono", style: { fontSize: 11, color: "var(--brand)" }, children: item.key })
7015
+ children: /* @__PURE__ */ jsx58("code", { className: "fd-mono", style: { fontSize: 11, color: "var(--brand)" }, children: item.key })
6773
7016
  }
6774
7017
  )
6775
7018
  ] }),
6776
- deps.length ? /* @__PURE__ */ jsxs50("div", { className: "fd-row", style: { gap: 6, flexWrap: "wrap", paddingTop: 6, borderTop: "1px solid var(--border)" }, children: [
6777
- /* @__PURE__ */ jsx55("span", { className: "fd-overline fd-muted", style: { paddingTop: 3 }, children: "After" }),
6778
- deps.map((d) => /* @__PURE__ */ jsx55(Tag, { icon: d.implemented ? "check" : "clock", children: d.label }, d.key))
7019
+ deps.length ? /* @__PURE__ */ jsxs53("div", { className: "fd-row", style: { gap: 6, flexWrap: "wrap", paddingTop: 6, borderTop: "1px solid var(--border)" }, children: [
7020
+ /* @__PURE__ */ jsx58("span", { className: "fd-overline fd-muted", style: { paddingTop: 3 }, children: "After" }),
7021
+ deps.map((d) => /* @__PURE__ */ jsx58(Tag, { icon: d.implemented ? "check" : "clock", children: d.label }, d.key))
6779
7022
  ] }) : null,
6780
- blocking.length && !item.implemented ? /* @__PURE__ */ jsxs50("span", { className: "fd-body-sm", style: { color: "var(--warn-text)" }, children: [
7023
+ blocking.length && !item.implemented ? /* @__PURE__ */ jsxs53("span", { className: "fd-body-sm", style: { color: "var(--warn-text)" }, children: [
6781
7024
  "Blocked until ",
6782
7025
  blocking.map((d) => d.label).join(" and "),
6783
7026
  " ",
@@ -6788,12 +7031,12 @@ function RoadmapCard({ item, byKey, onOpenFlag }) {
6788
7031
  }
6789
7032
  function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
6790
7033
  const session = SessionKit.useSession();
6791
- const [project, setProject] = React29.useState("");
6792
- const [q, setQ] = React29.useState("");
6793
- const scrollRef = React29.useRef(null);
6794
- const nowRef = React29.useRef(null);
6795
- const rm = React29.useMemo(() => SessionKit.roadmap({ isComplete: RuntimeKit.isComplete }), [session]);
6796
- const byKey = React29.useMemo(() => {
7034
+ const [project, setProject] = React31.useState("");
7035
+ const [q, setQ] = React31.useState("");
7036
+ const scrollRef = React31.useRef(null);
7037
+ const nowRef = React31.useRef(null);
7038
+ const rm = React31.useMemo(() => SessionKit.roadmap({ isComplete: RuntimeKit.isComplete }), [session]);
7039
+ const byKey = React31.useMemo(() => {
6797
7040
  const m = {};
6798
7041
  rm.items.forEach((i) => {
6799
7042
  m[i.key] = i;
@@ -6802,7 +7045,7 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
6802
7045
  }, [rm]);
6803
7046
  const items = rm.items.filter((i) => (!project || i.project === project) && (!q || (i.label + " " + i.description + " " + (i.backend || "") + " " + i.key).toLowerCase().includes(q.toLowerCase())));
6804
7047
  const projects = [...new Set(rm.items.map((i) => i.project))];
6805
- React29.useEffect(() => {
7048
+ React31.useEffect(() => {
6806
7049
  let raf1 = 0, raf2 = 0;
6807
7050
  const place = () => {
6808
7051
  const box = scrollRef.current, mark = nowRef.current;
@@ -6830,23 +7073,23 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
6830
7073
  }, 0);
6831
7074
  const nextPhase = items.find((i) => !i.implemented);
6832
7075
  let lastPhase = null;
6833
- return /* @__PURE__ */ jsxs50("div", { className: "fd-stack", style: { gap: 16, maxWidth: 1e3 }, children: [
6834
- /* @__PURE__ */ jsxs50("div", { className: "fd-stack", style: { gap: 10 }, children: [
6835
- /* @__PURE__ */ jsx55("span", { className: "fd-overline fd-muted", children: "Architecture" }),
6836
- /* @__PURE__ */ jsx55("h1", { className: "fd-h1", style: { margin: 0 }, children: title }),
6837
- /* @__PURE__ */ jsx55("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." })
7076
+ return /* @__PURE__ */ jsxs53("div", { className: "fd-stack", style: { gap: 16, maxWidth: 1e3 }, children: [
7077
+ /* @__PURE__ */ jsxs53("div", { className: "fd-stack", style: { gap: 10 }, children: [
7078
+ /* @__PURE__ */ jsx58("span", { className: "fd-overline fd-muted", children: "Architecture" }),
7079
+ /* @__PURE__ */ jsx58("h1", { className: "fd-h1", style: { margin: 0 }, children: title }),
7080
+ /* @__PURE__ */ jsx58("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." })
6838
7081
  ] }),
6839
- /* @__PURE__ */ jsxs50("div", { className: "fd-grid-stats is-thin", children: [
6840
- /* @__PURE__ */ jsx55(StatTile, { compact: true, label: "Wired", value: String(rm.shipped), sub: "of " + rm.items.length + " features" }),
6841
- /* @__PURE__ */ jsx55(StatTile, { compact: true, label: "Remaining", value: String(rm.remaining), sub: "backend work" }),
6842
- /* @__PURE__ */ jsx55(StatTile, { compact: true, label: "Est. effort", value: days ? days + " days" : "\u2014", sub: "sum of estimates, not calendar" }),
6843
- /* @__PURE__ */ jsx55(StatTile, { compact: true, label: "Up next", value: nextPhase ? "Phase " + nextPhase.phase : "\u2014", sub: nextPhase ? nextPhase.phaseName : "all wired" })
7082
+ /* @__PURE__ */ jsxs53("div", { className: "fd-grid-stats is-thin", children: [
7083
+ /* @__PURE__ */ jsx58(StatTile, { compact: true, label: "Wired", value: String(rm.shipped), sub: "of " + rm.items.length + " features" }),
7084
+ /* @__PURE__ */ jsx58(StatTile, { compact: true, label: "Remaining", value: String(rm.remaining), sub: "backend work" }),
7085
+ /* @__PURE__ */ jsx58(StatTile, { compact: true, label: "Est. effort", value: days ? days + " days" : "\u2014", sub: "sum of estimates, not calendar" }),
7086
+ /* @__PURE__ */ jsx58(StatTile, { compact: true, label: "Up next", value: nextPhase ? "Phase " + nextPhase.phase : "\u2014", sub: nextPhase ? nextPhase.phaseName : "all wired" })
6844
7087
  ] }),
6845
- /* @__PURE__ */ jsxs50("div", { className: "fd-row", style: { gap: 10, flexWrap: "wrap" }, children: [
6846
- /* @__PURE__ */ jsx55(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 } }),
6847
- /* @__PURE__ */ jsx55(Select, { placeholder: "All projects", value: project, onChange: (e) => setProject(e.target.value), options: projects, style: { width: 190 } }),
6848
- /* @__PURE__ */ jsx55("span", { style: { flex: 1 } }),
6849
- /* @__PURE__ */ jsx55(
7088
+ /* @__PURE__ */ jsxs53("div", { className: "fd-row", style: { gap: 10, flexWrap: "wrap" }, children: [
7089
+ /* @__PURE__ */ jsx58(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 } }),
7090
+ /* @__PURE__ */ jsx58(Select, { placeholder: "All projects", value: project, onChange: (e) => setProject(e.target.value), options: projects, style: { width: 190 } }),
7091
+ /* @__PURE__ */ jsx58("span", { style: { flex: 1 } }),
7092
+ /* @__PURE__ */ jsx58(
6850
7093
  Button,
6851
7094
  {
6852
7095
  size: "sm",
@@ -6860,7 +7103,7 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
6860
7103
  }
6861
7104
  )
6862
7105
  ] }),
6863
- /* @__PURE__ */ jsx55(
7106
+ /* @__PURE__ */ jsx58(
6864
7107
  Flag,
6865
7108
  {
6866
7109
  tone: "info",
@@ -6869,60 +7112,60 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
6869
7112
  actions: null
6870
7113
  }
6871
7114
  ),
6872
- /* @__PURE__ */ jsx55("div", { className: "fd-rm", children: /* @__PURE__ */ jsx55("div", { className: "fd-rm-scroll", ref: scrollRef, children: /* @__PURE__ */ jsxs50("div", { className: "fd-rm-track", children: [
6873
- /* @__PURE__ */ jsx55("span", { className: "fd-rm-spine", children: /* @__PURE__ */ jsx55("span", { className: "fd-rm-spine-done", style: { height: items.length ? 100 * shippedShown / items.length + "%" : "0%" } }) }),
7115
+ /* @__PURE__ */ jsx58("div", { className: "fd-rm", children: /* @__PURE__ */ jsx58("div", { className: "fd-rm-scroll", ref: scrollRef, children: /* @__PURE__ */ jsxs53("div", { className: "fd-rm-track", children: [
7116
+ /* @__PURE__ */ jsx58("span", { className: "fd-rm-spine", children: /* @__PURE__ */ jsx58("span", { className: "fd-rm-spine-done", style: { height: items.length ? 100 * shippedShown / items.length + "%" : "0%" } }) }),
6874
7117
  items.map((item, n) => {
6875
7118
  const showPhase = item.phase !== lastPhase;
6876
7119
  lastPhase = item.phase;
6877
7120
  const inPhase = items.filter((i) => i.phase === item.phase).length;
6878
7121
  const isBoundary = n === firstPending;
6879
- return /* @__PURE__ */ jsxs50(React29.Fragment, { children: [
6880
- showPhase ? /* @__PURE__ */ jsxs50("div", { className: "fd-rm-era", children: [
6881
- /* @__PURE__ */ jsxs50("span", { className: "fd-row", style: { gap: 8, flexWrap: "wrap", alignItems: "baseline" }, children: [
6882
- /* @__PURE__ */ jsx55("span", { style: { fontWeight: 700 }, children: item.phase === 0 ? "Shipped" : "Phase " + item.phase + " \u2014 " + item.phaseName }),
6883
- item.phase === 0 ? null : /* @__PURE__ */ jsxs50("span", { className: "fd-mono", style: { opacity: 0.7, fontWeight: 400 }, children: [
7122
+ return /* @__PURE__ */ jsxs53(React31.Fragment, { children: [
7123
+ showPhase ? /* @__PURE__ */ jsxs53("div", { className: "fd-rm-era", children: [
7124
+ /* @__PURE__ */ jsxs53("span", { className: "fd-row", style: { gap: 8, flexWrap: "wrap", alignItems: "baseline" }, children: [
7125
+ /* @__PURE__ */ jsx58("span", { style: { fontWeight: 700 }, children: item.phase === 0 ? "Shipped" : "Phase " + item.phase + " \u2014 " + item.phaseName }),
7126
+ item.phase === 0 ? null : /* @__PURE__ */ jsxs53("span", { className: "fd-mono", style: { opacity: 0.7, fontWeight: 400 }, children: [
6884
7127
  fmtDate(item.phaseStart),
6885
7128
  " \u2013 ",
6886
7129
  fmtDate(item.date)
6887
7130
  ] }),
6888
- /* @__PURE__ */ jsxs50("span", { style: { opacity: 0.7, fontWeight: 400 }, children: [
7131
+ /* @__PURE__ */ jsxs53("span", { style: { opacity: 0.7, fontWeight: 400 }, children: [
6889
7132
  "\xB7 ",
6890
7133
  inPhase,
6891
7134
  " feature",
6892
7135
  inPhase === 1 ? "" : "s"
6893
7136
  ] })
6894
7137
  ] }),
6895
- item.phaseWhy ? /* @__PURE__ */ jsx55("p", { className: "fd-rm-era-why", children: item.phaseWhy }) : null
7138
+ item.phaseWhy ? /* @__PURE__ */ jsx58("p", { className: "fd-rm-era-why", children: item.phaseWhy }) : null
6896
7139
  ] }) : null,
6897
- isBoundary ? /* @__PURE__ */ jsx55("div", { className: "fd-rm-now", ref: nowRef, children: /* @__PURE__ */ jsxs50("span", { className: "fd-rm-now-pill", children: [
6898
- /* @__PURE__ */ jsx55("i", { className: "ph ph-map-pin" }),
7140
+ isBoundary ? /* @__PURE__ */ jsx58("div", { className: "fd-rm-now", ref: nowRef, children: /* @__PURE__ */ jsxs53("span", { className: "fd-rm-now-pill", children: [
7141
+ /* @__PURE__ */ jsx58("i", { className: "ph ph-map-pin" }),
6899
7142
  " You are here \u2014 everything above is wired"
6900
7143
  ] }) }) : null,
6901
- /* @__PURE__ */ jsxs50("div", { className: "fd-rm-row", children: [
6902
- /* @__PURE__ */ jsx55("span", { className: "fd-rm-dot " + (item.implemented ? "is-shipped" : item.status === "next" ? "is-next" : "") }),
6903
- /* @__PURE__ */ jsxs50("div", { className: "fd-rm-date", children: [
7144
+ /* @__PURE__ */ jsxs53("div", { className: "fd-rm-row", children: [
7145
+ /* @__PURE__ */ jsx58("span", { className: "fd-rm-dot " + (item.implemented ? "is-shipped" : item.status === "next" ? "is-next" : "") }),
7146
+ /* @__PURE__ */ jsxs53("div", { className: "fd-rm-date", children: [
6904
7147
  fmtDate(item.date),
6905
- /* @__PURE__ */ jsx55("br", {}),
6906
- /* @__PURE__ */ jsx55("span", { style: { opacity: 0.75 }, children: item.implemented ? "shipped" : "phase " + item.phase })
7148
+ /* @__PURE__ */ jsx58("br", {}),
7149
+ /* @__PURE__ */ jsx58("span", { style: { opacity: 0.75 }, children: item.implemented ? "shipped" : "phase " + item.phase })
6907
7150
  ] }),
6908
- /* @__PURE__ */ jsx55(RoadmapCard, { item, byKey, onOpenFlag })
7151
+ /* @__PURE__ */ jsx58(RoadmapCard, { item, byKey, onOpenFlag })
6909
7152
  ] })
6910
7153
  ] }, item.key);
6911
7154
  }),
6912
- !items.length ? /* @__PURE__ */ jsx55("p", { className: "fd-body-sm fd-muted", children: "Nothing matches that filter." }) : null
7155
+ !items.length ? /* @__PURE__ */ jsx58("p", { className: "fd-body-sm fd-muted", children: "Nothing matches that filter." }) : null
6913
7156
  ] }) }) }),
6914
- /* @__PURE__ */ jsxs50("p", { className: "fd-body-sm fd-muted", style: { margin: 0 }, children: [
7157
+ /* @__PURE__ */ jsxs53("p", { className: "fd-body-sm fd-muted", style: { margin: 0 }, children: [
6915
7158
  "Derived from the feature-flag registry \u2014 each entry's status is its flag's ",
6916
- /* @__PURE__ */ jsx55("code", { className: "fd-mono", children: "implemented" }),
7159
+ /* @__PURE__ */ jsx58("code", { className: "fd-mono", children: "implemented" }),
6917
7160
  " field, so this page cannot drift from what the apps actually do."
6918
7161
  ] })
6919
7162
  ] });
6920
7163
  }
6921
7164
 
6922
7165
  // src/components/platform/ComingSoon.tsx
6923
- import * as React30 from "react";
7166
+ import * as React32 from "react";
6924
7167
  import { createPortal as createPortal7 } from "react-dom";
6925
- import { Fragment as Fragment13, jsx as jsx56, jsxs as jsxs51 } from "react/jsx-runtime";
7168
+ import { Fragment as Fragment13, jsx as jsx59, jsxs as jsxs54 } from "react/jsx-runtime";
6926
7169
  var BYPASS_STORE = "fd.soon.bypass.v1";
6927
7170
  function readBypassed() {
6928
7171
  try {
@@ -6938,8 +7181,8 @@ function writeBypassed(list) {
6938
7181
  }
6939
7182
  }
6940
7183
  function useBypass(key) {
6941
- const [on, setOn] = React30.useState(() => !!key && readBypassed().indexOf(key) >= 0);
6942
- React30.useEffect(() => {
7184
+ const [on, setOn] = React32.useState(() => !!key && readBypassed().indexOf(key) >= 0);
7185
+ React32.useEffect(() => {
6943
7186
  setOn(!!key && readBypassed().indexOf(key) >= 0);
6944
7187
  }, [key]);
6945
7188
  const set = (next) => {
@@ -6952,43 +7195,43 @@ function useBypass(key) {
6952
7195
  return [on, set];
6953
7196
  }
6954
7197
  function SoonCard({ label, detail, backend, eta, effort, onRoadmap, allowed, onBypass }) {
6955
- return /* @__PURE__ */ jsxs51(Fragment13, { children: [
6956
- /* @__PURE__ */ jsxs51("span", { className: "fd-soon-badge", children: [
6957
- /* @__PURE__ */ jsx56("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" }),
7198
+ return /* @__PURE__ */ jsxs54(Fragment13, { children: [
7199
+ /* @__PURE__ */ jsxs54("span", { className: "fd-soon-badge", children: [
7200
+ /* @__PURE__ */ jsx59("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" }),
6958
7201
  label
6959
7202
  ] }),
6960
- detail ? /* @__PURE__ */ jsx56("span", { className: "fd-soon-detail", children: detail }) : null,
6961
- backend ? /* @__PURE__ */ jsxs51("span", { className: "fd-soon-backend", children: [
6962
- /* @__PURE__ */ jsx56("span", { className: "fd-overline", children: "Needs" }),
7203
+ detail ? /* @__PURE__ */ jsx59("span", { className: "fd-soon-detail", children: detail }) : null,
7204
+ backend ? /* @__PURE__ */ jsxs54("span", { className: "fd-soon-backend", children: [
7205
+ /* @__PURE__ */ jsx59("span", { className: "fd-overline", children: "Needs" }),
6963
7206
  " ",
6964
7207
  backend
6965
7208
  ] }) : null,
6966
- eta || effort || onRoadmap ? /* @__PURE__ */ jsxs51("span", { className: "fd-soon-meta", children: [
6967
- eta ? /* @__PURE__ */ jsxs51("span", { children: [
6968
- /* @__PURE__ */ jsx56("i", { className: "ph ph-calendar-blank", "aria-hidden": "true" }),
7209
+ eta || effort || onRoadmap ? /* @__PURE__ */ jsxs54("span", { className: "fd-soon-meta", children: [
7210
+ eta ? /* @__PURE__ */ jsxs54("span", { children: [
7211
+ /* @__PURE__ */ jsx59("i", { className: "ph ph-calendar-blank", "aria-hidden": "true" }),
6969
7212
  " ",
6970
7213
  eta
6971
7214
  ] }) : null,
6972
- effort ? /* @__PURE__ */ jsxs51("span", { children: [
6973
- /* @__PURE__ */ jsx56("i", { className: "ph ph-hourglass-medium", "aria-hidden": "true" }),
7215
+ effort ? /* @__PURE__ */ jsxs54("span", { children: [
7216
+ /* @__PURE__ */ jsx59("i", { className: "ph ph-hourglass-medium", "aria-hidden": "true" }),
6974
7217
  " ",
6975
7218
  effort
6976
7219
  ] }) : null,
6977
- onRoadmap ? /* @__PURE__ */ jsxs51("button", { type: "button", className: "fd-soon-link", onClick: onRoadmap, children: [
7220
+ onRoadmap ? /* @__PURE__ */ jsxs54("button", { type: "button", className: "fd-soon-link", onClick: onRoadmap, children: [
6978
7221
  "See the roadmap ",
6979
- /* @__PURE__ */ jsx56("i", { className: "ph ph-arrow-right", "aria-hidden": "true" })
7222
+ /* @__PURE__ */ jsx59("i", { className: "ph ph-arrow-right", "aria-hidden": "true" })
6980
7223
  ] }) : null
6981
7224
  ] }) : null,
6982
- allowed ? /* @__PURE__ */ jsxs51("button", { type: "button", className: "fd-soon-view", onClick: onBypass, children: [
6983
- /* @__PURE__ */ jsx56("i", { className: "ph ph-eye", "aria-hidden": "true" }),
7225
+ allowed ? /* @__PURE__ */ jsxs54("button", { type: "button", className: "fd-soon-view", onClick: onBypass, children: [
7226
+ /* @__PURE__ */ jsx59("i", { className: "ph ph-eye", "aria-hidden": "true" }),
6984
7227
  " View and use it anyway"
6985
7228
  ] }) : null
6986
7229
  ] });
6987
7230
  }
6988
7231
  function useHoverCard(open) {
6989
- const anchor = React30.useRef(null);
6990
- const [pos, setPos] = React30.useState(null);
6991
- React30.useLayoutEffect(() => {
7232
+ const anchor = React32.useRef(null);
7233
+ const [pos, setPos] = React32.useState(null);
7234
+ React32.useLayoutEffect(() => {
6992
7235
  if (!open || !anchor.current) {
6993
7236
  setPos(null);
6994
7237
  return;
@@ -7040,9 +7283,9 @@ function ComingSoon({
7040
7283
  const tip = [label, detail, backend ? "Needs " + backend : null, eta ? "ETA " + eta : null, effort].filter(Boolean).join(" \xB7 ");
7041
7284
  if (inline) {
7042
7285
  if (allowed && bypassed) {
7043
- return /* @__PURE__ */ jsxs51("span", { className: ["fd-soon-inline-on", className].filter(Boolean).join(" "), ...rest, children: [
7286
+ return /* @__PURE__ */ jsxs54("span", { className: ["fd-soon-inline-on", className].filter(Boolean).join(" "), ...rest, children: [
7044
7287
  children,
7045
- /* @__PURE__ */ jsx56(
7288
+ /* @__PURE__ */ jsx59(
7046
7289
  "button",
7047
7290
  {
7048
7291
  type: "button",
@@ -7050,12 +7293,12 @@ function ComingSoon({
7050
7293
  title: "Unwired \u2014 writes go to the simulated backend. " + tip + " Click to re-blur.",
7051
7294
  onClick: () => setBypassed(false),
7052
7295
  "aria-label": "Re-blur this unwired feature",
7053
- children: /* @__PURE__ */ jsx56("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" })
7296
+ children: /* @__PURE__ */ jsx59("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" })
7054
7297
  }
7055
7298
  )
7056
7299
  ] });
7057
7300
  }
7058
- return /* @__PURE__ */ jsx56(
7301
+ return /* @__PURE__ */ jsx59(
7059
7302
  InlineSoon,
7060
7303
  {
7061
7304
  label,
@@ -7075,20 +7318,20 @@ function ComingSoon({
7075
7318
  );
7076
7319
  }
7077
7320
  if (allowed && bypassed) {
7078
- return /* @__PURE__ */ jsxs51("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 14 }, ...rest, children: [
7079
- /* @__PURE__ */ jsxs51("div", { className: "fd-soon-bar", role: "status", children: [
7080
- /* @__PURE__ */ jsxs51("span", { className: "fd-soon-badge", children: [
7081
- /* @__PURE__ */ jsx56("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" }),
7321
+ return /* @__PURE__ */ jsxs54("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 14 }, ...rest, children: [
7322
+ /* @__PURE__ */ jsxs54("div", { className: "fd-soon-bar", role: "status", children: [
7323
+ /* @__PURE__ */ jsxs54("span", { className: "fd-soon-badge", children: [
7324
+ /* @__PURE__ */ jsx59("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" }),
7082
7325
  "Unwired feature \u2014 you are using it anyway"
7083
7326
  ] }),
7084
- /* @__PURE__ */ jsx56("span", { className: "fd-soon-bar-detail", children: "Every action here writes to the simulated backend, so nothing you do persists beyond this session." }),
7085
- /* @__PURE__ */ jsxs51("span", { className: "fd-soon-bar-actions", children: [
7086
- onRoadmap ? /* @__PURE__ */ jsxs51("button", { type: "button", className: "fd-soon-link", onClick: onRoadmap, children: [
7327
+ /* @__PURE__ */ jsx59("span", { className: "fd-soon-bar-detail", children: "Every action here writes to the simulated backend, so nothing you do persists beyond this session." }),
7328
+ /* @__PURE__ */ jsxs54("span", { className: "fd-soon-bar-actions", children: [
7329
+ onRoadmap ? /* @__PURE__ */ jsxs54("button", { type: "button", className: "fd-soon-link", onClick: onRoadmap, children: [
7087
7330
  "Roadmap ",
7088
- /* @__PURE__ */ jsx56("i", { className: "ph ph-arrow-right", "aria-hidden": "true" })
7331
+ /* @__PURE__ */ jsx59("i", { className: "ph ph-arrow-right", "aria-hidden": "true" })
7089
7332
  ] }) : null,
7090
- /* @__PURE__ */ jsxs51("button", { type: "button", className: "fd-soon-link", onClick: () => setBypassed(false), children: [
7091
- /* @__PURE__ */ jsx56("i", { className: "ph ph-eye-slash", "aria-hidden": "true" }),
7333
+ /* @__PURE__ */ jsxs54("button", { type: "button", className: "fd-soon-link", onClick: () => setBypassed(false), children: [
7334
+ /* @__PURE__ */ jsx59("i", { className: "ph ph-eye-slash", "aria-hidden": "true" }),
7092
7335
  " Re-blur"
7093
7336
  ] })
7094
7337
  ] })
@@ -7096,10 +7339,10 @@ function ComingSoon({
7096
7339
  children
7097
7340
  ] });
7098
7341
  }
7099
- return /* @__PURE__ */ jsxs51("div", { className: ["fd-soon", className].filter(Boolean).join(" "), style: minHeight ? { minHeight } : void 0, ...rest, children: [
7100
- /* @__PURE__ */ jsx56("div", { className: "fd-soon-under", style: { filter: "blur(" + blur + "px) saturate(.62)" }, ...{ inert: "" }, "aria-hidden": "true", children }),
7101
- /* @__PURE__ */ jsx56("div", { className: "fd-soon-veil" }),
7102
- /* @__PURE__ */ jsx56("div", { className: "fd-soon-note", role: "note", children: /* @__PURE__ */ jsx56(
7342
+ return /* @__PURE__ */ jsxs54("div", { className: ["fd-soon", className].filter(Boolean).join(" "), style: minHeight ? { minHeight } : void 0, ...rest, children: [
7343
+ /* @__PURE__ */ jsx59("div", { className: "fd-soon-under", style: { filter: "blur(" + blur + "px) saturate(.62)" }, ...{ inert: "" }, "aria-hidden": "true", children }),
7344
+ /* @__PURE__ */ jsx59("div", { className: "fd-soon-veil" }),
7345
+ /* @__PURE__ */ jsx59("div", { className: "fd-soon-note", role: "note", children: /* @__PURE__ */ jsx59(
7103
7346
  SoonCard,
7104
7347
  {
7105
7348
  label,
@@ -7115,9 +7358,9 @@ function ComingSoon({
7115
7358
  ] });
7116
7359
  }
7117
7360
  function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, onBypass, blur, tip, className, rest, children }) {
7118
- const [open, setOpen] = React30.useState(false);
7361
+ const [open, setOpen] = React32.useState(false);
7119
7362
  const [anchor, pos] = useHoverCard(open);
7120
- const close = React30.useRef(null);
7363
+ const close = React32.useRef(null);
7121
7364
  const show = () => {
7122
7365
  if (close.current) {
7123
7366
  clearTimeout(close.current);
@@ -7133,10 +7376,10 @@ function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, o
7133
7376
  setOpen(false);
7134
7377
  }, 140);
7135
7378
  };
7136
- React30.useEffect(() => () => {
7379
+ React32.useEffect(() => () => {
7137
7380
  if (close.current) clearTimeout(close.current);
7138
7381
  }, []);
7139
- return /* @__PURE__ */ jsxs51(
7382
+ return /* @__PURE__ */ jsxs54(
7140
7383
  "span",
7141
7384
  {
7142
7385
  ref: anchor,
@@ -7147,8 +7390,8 @@ function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, o
7147
7390
  onBlur: hide,
7148
7391
  ...rest,
7149
7392
  children: [
7150
- /* @__PURE__ */ jsx56("span", { className: "fd-soon-under", style: { filter: "blur(" + Math.min(blur, 1.1) + "px) saturate(.66)" }, ...{ inert: "" }, "aria-hidden": "true", children }),
7151
- /* @__PURE__ */ jsx56(
7393
+ /* @__PURE__ */ jsx59("span", { className: "fd-soon-under", style: { filter: "blur(" + Math.min(blur, 1.1) + "px) saturate(.66)" }, ...{ inert: "" }, "aria-hidden": "true", children }),
7394
+ /* @__PURE__ */ jsx59(
7152
7395
  "button",
7153
7396
  {
7154
7397
  type: "button",
@@ -7159,11 +7402,11 @@ function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, o
7159
7402
  onFocus: show,
7160
7403
  onBlur: hide,
7161
7404
  onClick: () => open ? setOpen(false) : show(),
7162
- children: /* @__PURE__ */ jsx56("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" })
7405
+ children: /* @__PURE__ */ jsx59("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" })
7163
7406
  }
7164
7407
  ),
7165
7408
  open && pos ? createPortal7(
7166
- /* @__PURE__ */ jsx56(
7409
+ /* @__PURE__ */ jsx59(
7167
7410
  "div",
7168
7411
  {
7169
7412
  className: "fd-soon-note fd-soon-hovercard",
@@ -7171,7 +7414,7 @@ function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, o
7171
7414
  style: { position: "fixed", left: pos.left, top: pos.top, bottom: pos.bottom, width: pos.width },
7172
7415
  onMouseEnter: show,
7173
7416
  onMouseLeave: hide,
7174
- children: /* @__PURE__ */ jsx56(
7417
+ children: /* @__PURE__ */ jsx59(
7175
7418
  SoonCard,
7176
7419
  {
7177
7420
  label,
@@ -7201,10 +7444,10 @@ function formatEta(iso2) {
7201
7444
  var FormatEta = formatEta;
7202
7445
 
7203
7446
  // src/components/platform/Gate.tsx
7204
- import { jsx as jsx57, jsxs as jsxs52 } from "react/jsx-runtime";
7447
+ import { jsx as jsx60, jsxs as jsxs55 } from "react/jsx-runtime";
7205
7448
  function PermissionDenied({ permission, title, detail, compact: compact3 = false, className = "", ...rest }) {
7206
7449
  const need = Array.isArray(permission) ? permission : [permission].filter(Boolean);
7207
- return /* @__PURE__ */ jsxs52(
7450
+ return /* @__PURE__ */ jsxs55(
7208
7451
  "div",
7209
7452
  {
7210
7453
  className: ["fd-stack", className].filter(Boolean).join(" "),
@@ -7220,14 +7463,14 @@ function PermissionDenied({ permission, title, detail, compact: compact3 = false
7220
7463
  },
7221
7464
  ...rest,
7222
7465
  children: [
7223
- /* @__PURE__ */ jsxs52("span", { className: "fd-row", style: { gap: 8 }, children: [
7224
- /* @__PURE__ */ jsx57("i", { className: "ph ph-lock-simple", style: { fontSize: 16, color: "var(--text-muted)" }, "aria-hidden": "true" }),
7225
- /* @__PURE__ */ jsx57("span", { className: compact3 ? "fd-label-lg" : "fd-h3", children: title || "You do not have access to this" })
7466
+ /* @__PURE__ */ jsxs55("span", { className: "fd-row", style: { gap: 8 }, children: [
7467
+ /* @__PURE__ */ jsx60("i", { className: "ph ph-lock-simple", style: { fontSize: 16, color: "var(--text-muted)" }, "aria-hidden": "true" }),
7468
+ /* @__PURE__ */ jsx60("span", { className: compact3 ? "fd-label-lg" : "fd-h3", children: title || "You do not have access to this" })
7226
7469
  ] }),
7227
- /* @__PURE__ */ jsx57("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." }),
7228
- need.length ? /* @__PURE__ */ jsxs52("span", { className: "fd-row", style: { gap: 6, flexWrap: "wrap" }, children: [
7229
- /* @__PURE__ */ jsx57("span", { className: "fd-overline fd-muted", children: "Requires" }),
7230
- need.map((p) => /* @__PURE__ */ jsx57("code", { className: "fd-mono", style: {
7470
+ /* @__PURE__ */ jsx60("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." }),
7471
+ need.length ? /* @__PURE__ */ jsxs55("span", { className: "fd-row", style: { gap: 6, flexWrap: "wrap" }, children: [
7472
+ /* @__PURE__ */ jsx60("span", { className: "fd-overline fd-muted", children: "Requires" }),
7473
+ need.map((p) => /* @__PURE__ */ jsx60("code", { className: "fd-mono", style: {
7231
7474
  fontSize: 11.5,
7232
7475
  padding: "2px 7px",
7233
7476
  borderRadius: 5,
@@ -7248,7 +7491,7 @@ function Gate({ perm, anyOf, role, silent = false, fallback, compact: compact3 =
7248
7491
  if (ok) return children;
7249
7492
  if (fallback !== void 0) return fallback;
7250
7493
  if (silent) return null;
7251
- return /* @__PURE__ */ jsx57(PermissionDenied, { permission: perm || anyOf, compact: compact3 });
7494
+ return /* @__PURE__ */ jsx60(PermissionDenied, { permission: perm || anyOf, compact: compact3 });
7252
7495
  }
7253
7496
  function FeatureGate({
7254
7497
  flag,
@@ -7269,7 +7512,7 @@ function FeatureGate({
7269
7512
  if (!preview) return fallback;
7270
7513
  const f = SessionKit.findFlag(flag) || {};
7271
7514
  const missing = rt.missing || [];
7272
- return /* @__PURE__ */ jsx57(
7515
+ return /* @__PURE__ */ jsx60(
7273
7516
  ComingSoon,
7274
7517
  {
7275
7518
  label: label || (variant === "inline" ? f.label || "Not wired yet" : "Designed \u2014 backend not wired yet"),
@@ -7290,25 +7533,25 @@ function FeatureGate({
7290
7533
  function PermissionHint({ perm, children }) {
7291
7534
  SessionKit.useSession();
7292
7535
  if (SessionKit.can(perm)) return children;
7293
- return /* @__PURE__ */ jsx57(
7536
+ return /* @__PURE__ */ jsx60(
7294
7537
  "span",
7295
7538
  {
7296
7539
  title: "Requires " + (Array.isArray(perm) ? perm.join(", ") : perm),
7297
7540
  style: { display: "inline-flex", opacity: 0.45, cursor: "not-allowed" },
7298
7541
  "aria-disabled": "true",
7299
- children: /* @__PURE__ */ jsx57("span", { style: { pointerEvents: "none" }, children })
7542
+ children: /* @__PURE__ */ jsx60("span", { style: { pointerEvents: "none" }, children })
7300
7543
  }
7301
7544
  );
7302
7545
  }
7303
7546
 
7304
7547
  // src/components/platform/ModeSwitch.tsx
7305
- import * as React31 from "react";
7306
- import { Fragment as Fragment14, jsx as jsx58, jsxs as jsxs53 } from "react/jsx-runtime";
7548
+ import * as React33 from "react";
7549
+ import { Fragment as Fragment14, jsx as jsx61, jsxs as jsxs56 } from "react/jsx-runtime";
7307
7550
  function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog, onOpenSpec, summary }) {
7308
7551
  const mode2 = useRuntimeMode();
7309
- const [open, setOpen] = React31.useState(false);
7310
- const ref = React31.useRef(null);
7311
- React31.useEffect(() => {
7552
+ const [open, setOpen] = React33.useState(false);
7553
+ const ref = React33.useRef(null);
7554
+ React33.useEffect(() => {
7312
7555
  if (!open) return;
7313
7556
  const away = (e) => {
7314
7557
  if (ref.current && !ref.current.contains(e.target)) setOpen(false);
@@ -7330,8 +7573,8 @@ function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog
7330
7573
  RuntimeKit.setMode(next);
7331
7574
  setOpen(false);
7332
7575
  };
7333
- return /* @__PURE__ */ jsxs53("span", { style: { position: "relative", display: "inline-flex" }, ref, children: [
7334
- /* @__PURE__ */ jsxs53(
7576
+ return /* @__PURE__ */ jsxs56("span", { style: { position: "relative", display: "inline-flex" }, ref, children: [
7577
+ /* @__PURE__ */ jsxs56(
7335
7578
  "button",
7336
7579
  {
7337
7580
  type: "button",
@@ -7341,29 +7584,29 @@ function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog
7341
7584
  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.",
7342
7585
  className: "fd-mode-btn" + (test ? " is-test" : "") + (open ? " is-open" : ""),
7343
7586
  children: [
7344
- /* @__PURE__ */ jsx58("i", { className: "ph " + (test ? "ph-flask" : "ph-lightning"), style: { fontSize: 17 } }),
7345
- test && requestCount ? /* @__PURE__ */ jsx58("span", { className: "fd-mono fd-mode-count", children: requestCount > 99 ? "99+" : requestCount }, requestCount) : null
7587
+ /* @__PURE__ */ jsx61("i", { className: "ph " + (test ? "ph-flask" : "ph-lightning"), style: { fontSize: 17 } }),
7588
+ test && requestCount ? /* @__PURE__ */ jsx61("span", { className: "fd-mono fd-mode-count", children: requestCount > 99 ? "99+" : requestCount }, requestCount) : null
7346
7589
  ]
7347
7590
  }
7348
7591
  ),
7349
- open ? /* @__PURE__ */ jsxs53("span", { className: "fd-view-enter fd-mode-pop", children: [
7350
- /* @__PURE__ */ jsxs53("span", { className: "fd-row", style: { gap: 10, padding: "12px 14px", borderBottom: "1px solid var(--border)" }, children: [
7351
- /* @__PURE__ */ jsxs53("span", { className: "fd-badge " + (test ? "fd-badge-warning" : "fd-badge-neutral"), children: [
7352
- /* @__PURE__ */ jsx58("i", { className: "ph " + (test ? "ph-flask" : "ph-lightning"), "aria-hidden": "true" }),
7592
+ open ? /* @__PURE__ */ jsxs56("span", { className: "fd-view-enter fd-mode-pop", children: [
7593
+ /* @__PURE__ */ jsxs56("span", { className: "fd-row", style: { gap: 10, padding: "12px 14px", borderBottom: "1px solid var(--border)" }, children: [
7594
+ /* @__PURE__ */ jsxs56("span", { className: "fd-badge " + (test ? "fd-badge-warning" : "fd-badge-neutral"), children: [
7595
+ /* @__PURE__ */ jsx61("i", { className: "ph " + (test ? "ph-flask" : "ph-lightning"), "aria-hidden": "true" }),
7353
7596
  test ? "Test mode" : "Live mode"
7354
7597
  ] }),
7355
- test ? /* @__PURE__ */ jsxs53("span", { className: "fd-body-sm fd-muted fd-mono", children: [
7598
+ test ? /* @__PURE__ */ jsxs56("span", { className: "fd-body-sm fd-muted fd-mono", children: [
7356
7599
  requestCount,
7357
7600
  " simulated request",
7358
7601
  requestCount === 1 ? "" : "s"
7359
7602
  ] }) : null,
7360
- /* @__PURE__ */ jsx58("span", { style: { flex: 1 } }),
7361
- test && onClearLog ? /* @__PURE__ */ jsx58("button", { type: "button", className: "fd-soon-link", onClick: onClearLog, children: "Clear" }) : null
7603
+ /* @__PURE__ */ jsx61("span", { style: { flex: 1 } }),
7604
+ test && onClearLog ? /* @__PURE__ */ jsx61("button", { type: "button", className: "fd-soon-link", onClick: onClearLog, children: "Clear" }) : null
7362
7605
  ] }),
7363
- /* @__PURE__ */ jsxs53("span", { style: { display: "block", padding: "12px 14px", borderBottom: "1px solid var(--border)" }, children: [
7364
- /* @__PURE__ */ jsx58("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." }),
7365
- /* @__PURE__ */ jsxs53("span", { className: "fd-row", style: { gap: 8, marginTop: 10, flexWrap: "wrap" }, children: [
7366
- /* @__PURE__ */ jsxs53("span", { className: "fd-body-sm fd-muted fd-mono", children: [
7606
+ /* @__PURE__ */ jsxs56("span", { style: { display: "block", padding: "12px 14px", borderBottom: "1px solid var(--border)" }, children: [
7607
+ /* @__PURE__ */ jsx61("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." }),
7608
+ /* @__PURE__ */ jsxs56("span", { className: "fd-row", style: { gap: 8, marginTop: 10, flexWrap: "wrap" }, children: [
7609
+ /* @__PURE__ */ jsxs56("span", { className: "fd-body-sm fd-muted fd-mono", children: [
7367
7610
  s.endpointsWired,
7368
7611
  " endpoint",
7369
7612
  s.endpointsWired === 1 ? "" : "s",
@@ -7373,58 +7616,58 @@ function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog
7373
7616
  s.total,
7374
7617
  " features complete"
7375
7618
  ] }),
7376
- onOpenSpec ? /* @__PURE__ */ jsxs53(Fragment14, { children: [
7377
- /* @__PURE__ */ jsx58("span", { style: { flex: 1 } }),
7378
- /* @__PURE__ */ jsxs53("button", { type: "button", className: "fd-soon-link", onClick: () => {
7619
+ onOpenSpec ? /* @__PURE__ */ jsxs56(Fragment14, { children: [
7620
+ /* @__PURE__ */ jsx61("span", { style: { flex: 1 } }),
7621
+ /* @__PURE__ */ jsxs56("button", { type: "button", className: "fd-soon-link", onClick: () => {
7379
7622
  setOpen(false);
7380
7623
  onOpenSpec();
7381
7624
  }, children: [
7382
7625
  "API spec ",
7383
- /* @__PURE__ */ jsx58("i", { className: "ph ph-arrow-right", "aria-hidden": "true" })
7626
+ /* @__PURE__ */ jsx61("i", { className: "ph ph-arrow-right", "aria-hidden": "true" })
7384
7627
  ] })
7385
7628
  ] }) : null
7386
7629
  ] })
7387
7630
  ] }),
7388
- /* @__PURE__ */ jsxs53("span", { className: "fd-mode-choice", children: [
7389
- /* @__PURE__ */ jsxs53("button", { type: "button", className: "fd-mode-opt" + (!test ? " is-on" : ""), onClick: () => go("live"), children: [
7390
- /* @__PURE__ */ jsx58("i", { className: "ph ph-lightning", "aria-hidden": "true" }),
7391
- /* @__PURE__ */ jsxs53("span", { className: "fd-mode-opt-text", children: [
7392
- /* @__PURE__ */ jsx58("span", { className: "fd-mode-opt-title", children: "Live mode" }),
7393
- /* @__PURE__ */ jsx58("span", { className: "fd-mode-opt-desc", children: "Incomplete features under construction" })
7631
+ /* @__PURE__ */ jsxs56("span", { className: "fd-mode-choice", children: [
7632
+ /* @__PURE__ */ jsxs56("button", { type: "button", className: "fd-mode-opt" + (!test ? " is-on" : ""), onClick: () => go("live"), children: [
7633
+ /* @__PURE__ */ jsx61("i", { className: "ph ph-lightning", "aria-hidden": "true" }),
7634
+ /* @__PURE__ */ jsxs56("span", { className: "fd-mode-opt-text", children: [
7635
+ /* @__PURE__ */ jsx61("span", { className: "fd-mode-opt-title", children: "Live mode" }),
7636
+ /* @__PURE__ */ jsx61("span", { className: "fd-mode-opt-desc", children: "Incomplete features under construction" })
7394
7637
  ] }),
7395
- !test ? /* @__PURE__ */ jsx58("i", { className: "ph ph-check", "aria-hidden": "true" }) : null
7638
+ !test ? /* @__PURE__ */ jsx61("i", { className: "ph ph-check", "aria-hidden": "true" }) : null
7396
7639
  ] }),
7397
- /* @__PURE__ */ jsxs53("button", { type: "button", className: "fd-mode-opt" + (test ? " is-on" : ""), onClick: () => go("test"), children: [
7398
- /* @__PURE__ */ jsx58("i", { className: "ph ph-flask", "aria-hidden": "true" }),
7399
- /* @__PURE__ */ jsxs53("span", { className: "fd-mode-opt-text", children: [
7400
- /* @__PURE__ */ jsx58("span", { className: "fd-mode-opt-title", children: "Test mode" }),
7401
- /* @__PURE__ */ jsx58("span", { className: "fd-mode-opt-desc", children: "Everything usable, all data simulated" })
7640
+ /* @__PURE__ */ jsxs56("button", { type: "button", className: "fd-mode-opt" + (test ? " is-on" : ""), onClick: () => go("test"), children: [
7641
+ /* @__PURE__ */ jsx61("i", { className: "ph ph-flask", "aria-hidden": "true" }),
7642
+ /* @__PURE__ */ jsxs56("span", { className: "fd-mode-opt-text", children: [
7643
+ /* @__PURE__ */ jsx61("span", { className: "fd-mode-opt-title", children: "Test mode" }),
7644
+ /* @__PURE__ */ jsx61("span", { className: "fd-mode-opt-desc", children: "Everything usable, all data simulated" })
7402
7645
  ] }),
7403
- test ? /* @__PURE__ */ jsx58("i", { className: "ph ph-check", "aria-hidden": "true" }) : null
7646
+ test ? /* @__PURE__ */ jsx61("i", { className: "ph ph-check", "aria-hidden": "true" }) : null
7404
7647
  ] })
7405
7648
  ] }),
7406
- test && renderLog ? /* @__PURE__ */ jsx58("span", { style: { display: "block", maxHeight: 340, overflowY: "auto", borderTop: "1px solid var(--border)" }, children: renderLog() }) : null
7649
+ test && renderLog ? /* @__PURE__ */ jsx61("span", { style: { display: "block", maxHeight: 340, overflowY: "auto", borderTop: "1px solid var(--border)" }, children: renderLog() }) : null
7407
7650
  ] }) : null
7408
7651
  ] });
7409
7652
  }
7410
7653
  function TestModeBar({ onExit }) {
7411
7654
  const mode2 = useRuntimeMode();
7412
7655
  if (mode2 !== "test") return null;
7413
- return /* @__PURE__ */ jsxs53("div", { className: "fd-testbar", role: "status", children: [
7414
- /* @__PURE__ */ jsxs53("span", { className: "fd-badge fd-badge-warning", children: [
7415
- /* @__PURE__ */ jsx58("i", { className: "ph ph-flask", "aria-hidden": "true" }),
7656
+ return /* @__PURE__ */ jsxs56("div", { className: "fd-testbar", role: "status", children: [
7657
+ /* @__PURE__ */ jsxs56("span", { className: "fd-badge fd-badge-warning", children: [
7658
+ /* @__PURE__ */ jsx61("i", { className: "ph ph-flask", "aria-hidden": "true" }),
7416
7659
  "Test mode"
7417
7660
  ] }),
7418
- /* @__PURE__ */ jsx58("span", { className: "fd-testbar-detail", children: "Every feature is unlocked and every response is simulated \u2014 nothing here persists." }),
7419
- /* @__PURE__ */ jsxs53("button", { type: "button", className: "fd-soon-link", onClick: () => onExit ? onExit() : RuntimeKit.setMode("live"), children: [
7420
- /* @__PURE__ */ jsx58("i", { className: "ph ph-lightning", "aria-hidden": "true" }),
7661
+ /* @__PURE__ */ jsx61("span", { className: "fd-testbar-detail", children: "Every feature is unlocked and every response is simulated \u2014 nothing here persists." }),
7662
+ /* @__PURE__ */ jsxs56("button", { type: "button", className: "fd-soon-link", onClick: () => onExit ? onExit() : RuntimeKit.setMode("live"), children: [
7663
+ /* @__PURE__ */ jsx61("i", { className: "ph ph-lightning", "aria-hidden": "true" }),
7421
7664
  " Back to live mode"
7422
7665
  ] })
7423
7666
  ] });
7424
7667
  }
7425
7668
 
7426
7669
  // src/components/planner/ChannelMeta.tsx
7427
- import { jsx as jsx59, jsxs as jsxs54 } from "react/jsx-runtime";
7670
+ import { jsx as jsx62, jsxs as jsxs57 } from "react/jsx-runtime";
7428
7671
  var CHANNEL_WEIGHTS = {
7429
7672
  "OOH": 50,
7430
7673
  "DOOH": 50,
@@ -7477,9 +7720,9 @@ function ChannelTag({ channel, size = "md", showLabel = true, dot = false, weigh
7477
7720
  const m = ChannelMeta(channel);
7478
7721
  const wt = channelWeightOf(channel || "");
7479
7722
  if (dot) {
7480
- return /* @__PURE__ */ jsx59("span", { className: ["fd-chan-dot", className].filter(Boolean).join(" "), title: m.name, style: { background: m.color }, ...rest });
7723
+ return /* @__PURE__ */ jsx62("span", { className: ["fd-chan-dot", className].filter(Boolean).join(" "), title: m.name, style: { background: m.color }, ...rest });
7481
7724
  }
7482
- return /* @__PURE__ */ jsxs54(
7725
+ return /* @__PURE__ */ jsxs57(
7483
7726
  "span",
7484
7727
  {
7485
7728
  className: ["fd-chan", size === "sm" ? "fd-chan-sm" : "", className].filter(Boolean).join(" "),
@@ -7487,16 +7730,16 @@ function ChannelTag({ channel, size = "md", showLabel = true, dot = false, weigh
7487
7730
  style: { "--chan": m.color },
7488
7731
  ...rest,
7489
7732
  children: [
7490
- /* @__PURE__ */ jsx59("i", { className: "ph ph-" + m.icon, "aria-hidden": "true" }),
7491
- showLabel ? /* @__PURE__ */ jsx59("span", { className: "fd-chan-label", children: m.label }) : null,
7492
- weight ? /* @__PURE__ */ jsx59("span", { className: "fd-chan-weight", children: wt || 0 }) : null
7733
+ /* @__PURE__ */ jsx62("i", { className: "ph ph-" + m.icon, "aria-hidden": "true" }),
7734
+ showLabel ? /* @__PURE__ */ jsx62("span", { className: "fd-chan-label", children: m.label }) : null,
7735
+ weight ? /* @__PURE__ */ jsx62("span", { className: "fd-chan-weight", children: wt || 0 }) : null
7493
7736
  ]
7494
7737
  }
7495
7738
  );
7496
7739
  }
7497
7740
 
7498
7741
  // src/components/planner/SaturationDistribution.tsx
7499
- import { jsx as jsx60, jsxs as jsxs55 } from "react/jsx-runtime";
7742
+ import { jsx as jsx63, jsxs as jsxs58 } from "react/jsx-runtime";
7500
7743
  var BANDS2 = [
7501
7744
  { key: "weak", label: "Weak", n: 1, range: "< 50" },
7502
7745
  { key: "adequate", label: "Adequate", n: 2, range: "50\u2013100" },
@@ -7507,18 +7750,18 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
7507
7750
  const grouped = BANDS2.map((b) => ({ ...b, items: campuses.filter((c) => c.band === b.key) }));
7508
7751
  const tallest = Math.max(1, ...grouped.map((g) => g.items.length));
7509
7752
  const floor = BANDS2.find((b) => b.key === floorBand) || BANDS2[0];
7510
- return /* @__PURE__ */ jsxs55("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 16 }, children: [
7511
- /* @__PURE__ */ jsx60("div", { style: { display: "grid", gridTemplateColumns: "repeat(4,1fr)", gap: 12, alignItems: "end" }, children: grouped.map((g) => {
7753
+ return /* @__PURE__ */ jsxs58("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 16 }, children: [
7754
+ /* @__PURE__ */ jsx63("div", { style: { display: "grid", gridTemplateColumns: "repeat(4,1fr)", gap: 12, alignItems: "end" }, children: grouped.map((g) => {
7512
7755
  const mark = "var(--csi-" + g.n + "-mark)";
7513
7756
  const active = selectedBand === g.key;
7514
- return /* @__PURE__ */ jsxs55(
7757
+ return /* @__PURE__ */ jsxs58(
7515
7758
  "button",
7516
7759
  {
7517
7760
  type: "button",
7518
7761
  onClick: onSelectBand ? () => onSelectBand(active ? null : g.key) : void 0,
7519
7762
  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)" },
7520
7763
  children: [
7521
- /* @__PURE__ */ jsx60("span", { style: { display: "flex", flexDirection: "column-reverse", gap: 4, minHeight: tallest * 24 }, children: loading ? Array.from({ length: 3 }).map((_, i) => /* @__PURE__ */ jsx60("span", { className: "fd-skel", style: { height: 16, borderRadius: 4 } }, i)) : g.items.map((c) => /* @__PURE__ */ jsx60(
7764
+ /* @__PURE__ */ jsx63("span", { style: { display: "flex", flexDirection: "column-reverse", gap: 4, minHeight: tallest * 24 }, children: loading ? Array.from({ length: 3 }).map((_, i) => /* @__PURE__ */ jsx63("span", { className: "fd-skel", style: { height: 16, borderRadius: 4 } }, i)) : g.items.map((c) => /* @__PURE__ */ jsx63(
7522
7765
  "span",
7523
7766
  {
7524
7767
  title: c.name + " \xB7 " + c.crp,
@@ -7527,13 +7770,13 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
7527
7770
  },
7528
7771
  c.name
7529
7772
  )) }),
7530
- /* @__PURE__ */ jsxs55("span", { className: "fd-row", style: { gap: 8, alignItems: "baseline" }, children: [
7531
- /* @__PURE__ */ jsx60("span", { className: "fd-num-hero", style: { fontSize: 30, color: g.items.length ? "var(--text)" : "var(--text-disabled)" }, children: loading ? "\u2013" : g.items.length }),
7532
- /* @__PURE__ */ jsx60("span", { className: "fd-meter", style: { gap: 2, color: mark }, "aria-hidden": "true", children: [1, 2, 3, 4].map((i) => /* @__PURE__ */ jsx60("span", { className: "fd-meter-seg" + (i <= g.n ? " is-on" : ""), style: { width: 4, height: 9 } }, i)) })
7773
+ /* @__PURE__ */ jsxs58("span", { className: "fd-row", style: { gap: 8, alignItems: "baseline" }, children: [
7774
+ /* @__PURE__ */ jsx63("span", { className: "fd-num-hero", style: { fontSize: 30, color: g.items.length ? "var(--text)" : "var(--text-disabled)" }, children: loading ? "\u2013" : g.items.length }),
7775
+ /* @__PURE__ */ jsx63("span", { className: "fd-meter", style: { gap: 2, color: mark }, "aria-hidden": "true", children: [1, 2, 3, 4].map((i) => /* @__PURE__ */ jsx63("span", { className: "fd-meter-seg" + (i <= g.n ? " is-on" : ""), style: { width: 4, height: 9 } }, i)) })
7533
7776
  ] }),
7534
- /* @__PURE__ */ jsxs55("span", { className: "fd-stack", style: { gap: 1 }, children: [
7535
- /* @__PURE__ */ jsx60("span", { className: "fd-label-lg", children: g.label }),
7536
- /* @__PURE__ */ jsxs55("span", { className: "fd-body-sm fd-muted", style: { fontSize: 11.5 }, children: [
7777
+ /* @__PURE__ */ jsxs58("span", { className: "fd-stack", style: { gap: 1 }, children: [
7778
+ /* @__PURE__ */ jsx63("span", { className: "fd-label-lg", children: g.label }),
7779
+ /* @__PURE__ */ jsxs58("span", { className: "fd-body-sm fd-muted", style: { fontSize: 11.5 }, children: [
7537
7780
  "CRP ",
7538
7781
  g.range
7539
7782
  ] })
@@ -7543,10 +7786,10 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
7543
7786
  g.key
7544
7787
  );
7545
7788
  }) }),
7546
- floorBand ? /* @__PURE__ */ jsxs55("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: [
7547
- /* @__PURE__ */ jsx60("span", { className: "fd-meter", style: { gap: 2, color: "var(--csi-" + floor.n + "-mark)" }, "aria-hidden": "true", children: [1, 2, 3, 4].map((i) => /* @__PURE__ */ jsx60("span", { className: "fd-meter-seg" + (i <= floor.n ? " is-on" : ""), style: { width: 5, height: 12 } }, i)) }),
7548
- /* @__PURE__ */ jsxs55("span", { className: "fd-body-sm fd-secondary", style: { flex: 1, minWidth: 240 }, children: [
7549
- /* @__PURE__ */ jsxs55("strong", { style: { color: "var(--text)" }, children: [
7789
+ floorBand ? /* @__PURE__ */ jsxs58("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: [
7790
+ /* @__PURE__ */ jsx63("span", { className: "fd-meter", style: { gap: 2, color: "var(--csi-" + floor.n + "-mark)" }, "aria-hidden": "true", children: [1, 2, 3, 4].map((i) => /* @__PURE__ */ jsx63("span", { className: "fd-meter-seg" + (i <= floor.n ? " is-on" : ""), style: { width: 5, height: 12 } }, i)) }),
7791
+ /* @__PURE__ */ jsxs58("span", { className: "fd-body-sm fd-secondary", style: { flex: 1, minWidth: 240 }, children: [
7792
+ /* @__PURE__ */ jsxs58("strong", { style: { color: "var(--text)" }, children: [
7550
7793
  "Plan floor ",
7551
7794
  floorScore
7552
7795
  ] }),
@@ -7557,21 +7800,21 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
7557
7800
  }
7558
7801
 
7559
7802
  // src/components/planner/MixGap.tsx
7560
- import * as React32 from "react";
7561
- import { Fragment as Fragment15, jsx as jsx61, jsxs as jsxs56 } from "react/jsx-runtime";
7803
+ import * as React34 from "react";
7804
+ import { Fragment as Fragment15, jsx as jsx64, jsxs as jsxs59 } from "react/jsx-runtime";
7562
7805
  function MixGap({ rows = [], loading = false, className = "" }) {
7563
7806
  const max = Math.max(1, ...rows.flatMap((r) => [r.target, r.realized]));
7564
- const [hover, setHover] = React32.useState(null);
7807
+ const [hover, setHover] = React34.useState(null);
7565
7808
  const toneOf = (gap) => gap >= -1 ? "ok" : gap >= -4 ? "warn" : "danger";
7566
7809
  const TONE = { ok: "var(--ok-solid)", warn: "var(--warn-solid)", danger: "var(--danger-solid)" };
7567
- return /* @__PURE__ */ jsxs56("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 4 }, children: [
7568
- /* @__PURE__ */ jsxs56("div", { className: "fd-row", style: { gap: 16, justifyContent: "flex-end", paddingBottom: 6, flexWrap: "wrap" }, children: [
7569
- [["On target", TONE.ok], ["Close", TONE.warn], ["Short", TONE.danger]].map(([l, c]) => /* @__PURE__ */ jsxs56("span", { className: "fd-row fd-body-sm fd-muted", style: { gap: 6 }, children: [
7570
- /* @__PURE__ */ jsx61("span", { style: { width: 14, height: 9, borderRadius: 2, background: c } }),
7810
+ return /* @__PURE__ */ jsxs59("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 4 }, children: [
7811
+ /* @__PURE__ */ jsxs59("div", { className: "fd-row", style: { gap: 16, justifyContent: "flex-end", paddingBottom: 6, flexWrap: "wrap" }, children: [
7812
+ [["On target", TONE.ok], ["Close", TONE.warn], ["Short", TONE.danger]].map(([l, c]) => /* @__PURE__ */ jsxs59("span", { className: "fd-row fd-body-sm fd-muted", style: { gap: 6 }, children: [
7813
+ /* @__PURE__ */ jsx64("span", { style: { width: 14, height: 9, borderRadius: 2, background: c } }),
7571
7814
  l
7572
7815
  ] }, l)),
7573
- /* @__PURE__ */ jsxs56("span", { className: "fd-row fd-body-sm fd-muted", style: { gap: 6 }, children: [
7574
- /* @__PURE__ */ jsx61("span", { style: { width: 3, height: 14, background: "var(--n-500)" } }),
7816
+ /* @__PURE__ */ jsxs59("span", { className: "fd-row fd-body-sm fd-muted", style: { gap: 6 }, children: [
7817
+ /* @__PURE__ */ jsx64("span", { style: { width: 3, height: 14, background: "var(--n-500)" } }),
7575
7818
  "Target"
7576
7819
  ] })
7577
7820
  ] }),
@@ -7579,7 +7822,7 @@ function MixGap({ rows = [], loading = false, className = "" }) {
7579
7822
  const gap = r.realized - r.target;
7580
7823
  const tone = toneOf(gap);
7581
7824
  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 : "");
7582
- return /* @__PURE__ */ jsxs56(
7825
+ return /* @__PURE__ */ jsxs59(
7583
7826
  "div",
7584
7827
  {
7585
7828
  className: "fd-row",
@@ -7587,15 +7830,15 @@ function MixGap({ rows = [], loading = false, className = "" }) {
7587
7830
  onMouseEnter: () => setHover(r.channel),
7588
7831
  onMouseLeave: () => setHover(null),
7589
7832
  children: [
7590
- /* @__PURE__ */ jsx61("span", { style: { width: 128, flex: "none" }, children: /* @__PURE__ */ jsx61(ChannelTag, { channel: r.channel, size: "sm" }) }),
7591
- /* @__PURE__ */ jsx61("span", { style: { position: "relative", flex: 1, height: 22, minWidth: 120 }, children: loading ? /* @__PURE__ */ jsx61("span", { className: "fd-skel", style: { position: "absolute", inset: "5px 0", borderRadius: 3 } }) : /* @__PURE__ */ jsxs56(Fragment15, { children: [
7592
- /* @__PURE__ */ jsx61("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)" } }),
7593
- /* @__PURE__ */ jsx61("span", { style: { position: "absolute", left: r.target / max * 100 + "%", top: 0, width: 3, height: 22, background: "var(--n-500)", borderRadius: 1 } }),
7594
- /* @__PURE__ */ jsxs56("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: [
7833
+ /* @__PURE__ */ jsx64("span", { style: { width: 128, flex: "none" }, children: /* @__PURE__ */ jsx64(ChannelTag, { channel: r.channel, size: "sm" }) }),
7834
+ /* @__PURE__ */ jsx64("span", { style: { position: "relative", flex: 1, height: 22, minWidth: 120 }, children: loading ? /* @__PURE__ */ jsx64("span", { className: "fd-skel", style: { position: "absolute", inset: "5px 0", borderRadius: 3 } }) : /* @__PURE__ */ jsxs59(Fragment15, { children: [
7835
+ /* @__PURE__ */ jsx64("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)" } }),
7836
+ /* @__PURE__ */ jsx64("span", { style: { position: "absolute", left: r.target / max * 100 + "%", top: 0, width: 3, height: 22, background: "var(--n-500)", borderRadius: 1 } }),
7837
+ /* @__PURE__ */ jsxs59("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: [
7595
7838
  r.realized,
7596
7839
  "%"
7597
7840
  ] }),
7598
- hover === r.channel ? /* @__PURE__ */ jsx61("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
7841
+ hover === r.channel ? /* @__PURE__ */ jsx64("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
7599
7842
  ] }) })
7600
7843
  ]
7601
7844
  },
@@ -7606,7 +7849,7 @@ function MixGap({ rows = [], loading = false, className = "" }) {
7606
7849
  }
7607
7850
 
7608
7851
  // src/components/planner/ChannelContribution.tsx
7609
- import { jsx as jsx62, jsxs as jsxs57 } from "react/jsx-runtime";
7852
+ import { jsx as jsx65, jsxs as jsxs60 } from "react/jsx-runtime";
7610
7853
  var money = (n) => "$" + Math.round(n).toLocaleString();
7611
7854
  function ChannelContribution({
7612
7855
  channels = [],
@@ -7622,9 +7865,9 @@ function ChannelContribution({
7622
7865
  const grand = total !== void 0 ? total : base + bonus;
7623
7866
  const pct = (v) => grand ? v / grand * 100 : 0;
7624
7867
  const spendTotal = channels.reduce((s, c) => s + Number(String(c.spend || 0).replace(/[^0-9.]/g, "")), 0);
7625
- return /* @__PURE__ */ jsxs57("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 16 }, children: [
7626
- loading ? /* @__PURE__ */ jsx62("span", { className: "fd-skel", style: { height: 34, borderRadius: "var(--r-sm)" } }) : /* @__PURE__ */ jsxs57("div", { className: "fd-row", style: { height: 34, borderRadius: "var(--r-sm)", overflow: "hidden", gap: 2, background: "var(--surface-3)" }, children: [
7627
- channels.map((c) => /* @__PURE__ */ jsx62(
7868
+ return /* @__PURE__ */ jsxs60("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 16 }, children: [
7869
+ loading ? /* @__PURE__ */ jsx65("span", { className: "fd-skel", style: { height: 34, borderRadius: "var(--r-sm)" } }) : /* @__PURE__ */ jsxs60("div", { className: "fd-row", style: { height: 34, borderRadius: "var(--r-sm)", overflow: "hidden", gap: 2, background: "var(--surface-3)" }, children: [
7870
+ channels.map((c) => /* @__PURE__ */ jsx65(
7628
7871
  "span",
7629
7872
  {
7630
7873
  title: c.name + " \xB7 " + c.crp.toFixed(1) + " CRP",
@@ -7633,7 +7876,7 @@ function ChannelContribution({
7633
7876
  },
7634
7877
  c.name
7635
7878
  )),
7636
- bonus > 0 ? /* @__PURE__ */ jsx62(
7879
+ bonus > 0 ? /* @__PURE__ */ jsx65(
7637
7880
  "span",
7638
7881
  {
7639
7882
  title: "Surround-sound bonus +" + bonusPct + "%",
@@ -7642,18 +7885,18 @@ function ChannelContribution({
7642
7885
  }
7643
7886
  ) : null
7644
7887
  ] }),
7645
- showTable ? /* @__PURE__ */ jsxs57("table", { className: "fd-table", style: { fontSize: "var(--body-sm-size)" }, children: [
7646
- /* @__PURE__ */ jsx62("thead", { children: /* @__PURE__ */ jsxs57("tr", { children: [
7647
- /* @__PURE__ */ jsx62("th", { style: { width: "34%" }, children: "Channel" }),
7648
- /* @__PURE__ */ jsx62("th", { style: { width: "16%" }, children: "Weight" }),
7649
- /* @__PURE__ */ jsx62("th", { className: "is-num", style: { width: "16%" }, children: "Spend" }),
7650
- /* @__PURE__ */ jsx62("th", { className: "is-num", style: { width: "17%" }, children: "CRP" }),
7651
- /* @__PURE__ */ jsx62("th", { className: "is-num", style: { width: "17%" }, children: "Share" })
7888
+ showTable ? /* @__PURE__ */ jsxs60("table", { className: "fd-table", style: { fontSize: "var(--body-sm-size)" }, children: [
7889
+ /* @__PURE__ */ jsx65("thead", { children: /* @__PURE__ */ jsxs60("tr", { children: [
7890
+ /* @__PURE__ */ jsx65("th", { style: { width: "34%" }, children: "Channel" }),
7891
+ /* @__PURE__ */ jsx65("th", { style: { width: "16%" }, children: "Weight" }),
7892
+ /* @__PURE__ */ jsx65("th", { className: "is-num", style: { width: "16%" }, children: "Spend" }),
7893
+ /* @__PURE__ */ jsx65("th", { className: "is-num", style: { width: "17%" }, children: "CRP" }),
7894
+ /* @__PURE__ */ jsx65("th", { className: "is-num", style: { width: "17%" }, children: "Share" })
7652
7895
  ] }) }),
7653
- /* @__PURE__ */ jsxs57("tbody", { children: [
7654
- channels.map((c) => /* @__PURE__ */ jsxs57("tr", { children: [
7655
- /* @__PURE__ */ jsx62("td", { children: /* @__PURE__ */ jsx62(ChannelTag, { channel: c.name, size: "sm" }) }),
7656
- /* @__PURE__ */ jsx62("td", { children: /* @__PURE__ */ jsx62(
7896
+ /* @__PURE__ */ jsxs60("tbody", { children: [
7897
+ channels.map((c) => /* @__PURE__ */ jsxs60("tr", { children: [
7898
+ /* @__PURE__ */ jsx65("td", { children: /* @__PURE__ */ jsx65(ChannelTag, { channel: c.name, size: "sm" }) }),
7899
+ /* @__PURE__ */ jsx65("td", { children: /* @__PURE__ */ jsx65(
7657
7900
  "span",
7658
7901
  {
7659
7902
  className: "fd-badge fd-badge-neutral",
@@ -7662,38 +7905,38 @@ function ChannelContribution({
7662
7905
  children: "weight " + (channelWeightOf(c.name) || 0)
7663
7906
  }
7664
7907
  ) }),
7665
- /* @__PURE__ */ jsx62("td", { className: "is-num", children: c.spend }),
7666
- /* @__PURE__ */ jsx62("td", { className: "is-num", children: c.crp.toFixed(1) }),
7667
- /* @__PURE__ */ jsxs57("td", { className: "is-num", children: [
7908
+ /* @__PURE__ */ jsx65("td", { className: "is-num", children: c.spend }),
7909
+ /* @__PURE__ */ jsx65("td", { className: "is-num", children: c.crp.toFixed(1) }),
7910
+ /* @__PURE__ */ jsxs60("td", { className: "is-num", children: [
7668
7911
  pct(c.crp).toFixed(0),
7669
7912
  "%"
7670
7913
  ] })
7671
7914
  ] }, c.name)),
7672
- bonus > 0 ? /* @__PURE__ */ jsxs57("tr", { children: [
7673
- /* @__PURE__ */ jsx62("td", { children: /* @__PURE__ */ jsxs57("span", { className: "fd-row", style: { gap: 9, fontWeight: 600 }, children: [
7674
- /* @__PURE__ */ jsx62("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" } }),
7915
+ bonus > 0 ? /* @__PURE__ */ jsxs60("tr", { children: [
7916
+ /* @__PURE__ */ jsx65("td", { children: /* @__PURE__ */ jsxs60("span", { className: "fd-row", style: { gap: 9, fontWeight: 600 }, children: [
7917
+ /* @__PURE__ */ jsx65("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" } }),
7675
7918
  "Surround-sound bonus"
7676
7919
  ] }) }),
7677
- /* @__PURE__ */ jsx62("td", { children: /* @__PURE__ */ jsxs57("span", { className: "fd-badge fd-badge-success", style: { height: 20, fontSize: 11 }, children: [
7920
+ /* @__PURE__ */ jsx65("td", { children: /* @__PURE__ */ jsxs60("span", { className: "fd-badge fd-badge-success", style: { height: 20, fontSize: 11 }, children: [
7678
7921
  "+",
7679
7922
  bonusPct,
7680
7923
  "% of +",
7681
7924
  bonusMax,
7682
7925
  "%"
7683
7926
  ] }) }),
7684
- /* @__PURE__ */ jsx62("td", { className: "is-num fd-muted", children: "\u2014" }),
7685
- /* @__PURE__ */ jsx62("td", { className: "is-num", children: bonus.toFixed(1) }),
7686
- /* @__PURE__ */ jsxs57("td", { className: "is-num", children: [
7927
+ /* @__PURE__ */ jsx65("td", { className: "is-num fd-muted", children: "\u2014" }),
7928
+ /* @__PURE__ */ jsx65("td", { className: "is-num", children: bonus.toFixed(1) }),
7929
+ /* @__PURE__ */ jsxs60("td", { className: "is-num", children: [
7687
7930
  pct(bonus).toFixed(0),
7688
7931
  "%"
7689
7932
  ] })
7690
7933
  ] }) : null,
7691
- /* @__PURE__ */ jsxs57("tr", { style: { background: "var(--surface-2)" }, children: [
7692
- /* @__PURE__ */ jsx62("td", { style: { fontWeight: 700 }, children: "Campus total" }),
7693
- /* @__PURE__ */ jsx62("td", {}),
7694
- /* @__PURE__ */ jsx62("td", { className: "is-num", style: { fontWeight: 700 }, children: money(spendTotal) }),
7695
- /* @__PURE__ */ jsx62("td", { className: "is-num", style: { fontWeight: 700 }, children: grand.toFixed(1) }),
7696
- /* @__PURE__ */ jsx62("td", { className: "is-num", style: { fontWeight: 700 }, children: "100%" })
7934
+ /* @__PURE__ */ jsxs60("tr", { style: { background: "var(--surface-2)" }, children: [
7935
+ /* @__PURE__ */ jsx65("td", { style: { fontWeight: 700 }, children: "Campus total" }),
7936
+ /* @__PURE__ */ jsx65("td", {}),
7937
+ /* @__PURE__ */ jsx65("td", { className: "is-num", style: { fontWeight: 700 }, children: money(spendTotal) }),
7938
+ /* @__PURE__ */ jsx65("td", { className: "is-num", style: { fontWeight: 700 }, children: grand.toFixed(1) }),
7939
+ /* @__PURE__ */ jsx65("td", { className: "is-num", style: { fontWeight: 700 }, children: "100%" })
7697
7940
  ] })
7698
7941
  ] })
7699
7942
  ] }) : null
@@ -7701,8 +7944,8 @@ function ChannelContribution({
7701
7944
  }
7702
7945
 
7703
7946
  // src/components/planner/BudgetReallocator.tsx
7704
- import * as React33 from "react";
7705
- import { Fragment as Fragment16, jsx as jsx63, jsxs as jsxs58 } from "react/jsx-runtime";
7947
+ import * as React35 from "react";
7948
+ import { Fragment as Fragment16, jsx as jsx66, jsxs as jsxs61 } from "react/jsx-runtime";
7706
7949
  var bandFor = (crp) => crp >= 200 ? "dominant" : crp >= 100 ? "strong" : crp >= 50 ? "adequate" : "weak";
7707
7950
  function BudgetReallocator({
7708
7951
  campus,
@@ -7717,8 +7960,8 @@ function BudgetReallocator({
7717
7960
  onCancel,
7718
7961
  className = ""
7719
7962
  }) {
7720
- const [draft, setDraft] = React33.useState(spend);
7721
- React33.useEffect(() => setDraft(spend), [spend]);
7963
+ const [draft, setDraft] = React35.useState(spend);
7964
+ React35.useEffect(() => setDraft(spend), [spend]);
7722
7965
  const dirty = draft !== spend;
7723
7966
  const nextCrp = scoreFor ? scoreFor(draft) : crp;
7724
7967
  const nextBand = bandFor(nextCrp);
@@ -7733,24 +7976,24 @@ function BudgetReallocator({
7733
7976
  setDraft(spend);
7734
7977
  if (onCancel) onCancel();
7735
7978
  };
7736
- return /* @__PURE__ */ jsxs58(
7979
+ return /* @__PURE__ */ jsxs61(
7737
7980
  "div",
7738
7981
  {
7739
7982
  className: ["fd-stack", className].filter(Boolean).join(" "),
7740
7983
  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)" },
7741
7984
  children: [
7742
- /* @__PURE__ */ jsxs58("div", { className: "fd-row", style: { gap: 12, flexWrap: "wrap" }, children: [
7743
- /* @__PURE__ */ jsx63("span", { className: "fd-h4", style: { flex: 1, minWidth: 140 }, children: campus }),
7744
- /* @__PURE__ */ jsx63(CsiBadge, { band: nowBand, crp: Number(crp.toFixed(1)), size: "medium" }),
7745
- dirty ? /* @__PURE__ */ jsxs58(Fragment16, { children: [
7746
- /* @__PURE__ */ jsx63("i", { className: "ph ph-arrow-right fd-muted", "aria-hidden": "true" }),
7747
- /* @__PURE__ */ jsx63(CsiBadge, { band: nextBand, crp: Number(nextCrp.toFixed(1)), size: "medium", preview: true })
7985
+ /* @__PURE__ */ jsxs61("div", { className: "fd-row", style: { gap: 12, flexWrap: "wrap" }, children: [
7986
+ /* @__PURE__ */ jsx66("span", { className: "fd-h4", style: { flex: 1, minWidth: 140 }, children: campus }),
7987
+ /* @__PURE__ */ jsx66(CsiBadge, { band: nowBand, crp, size: "medium" }),
7988
+ dirty ? /* @__PURE__ */ jsxs61(Fragment16, { children: [
7989
+ /* @__PURE__ */ jsx66("i", { className: "ph ph-arrow-right fd-muted", "aria-hidden": "true" }),
7990
+ /* @__PURE__ */ jsx66(CsiBadge, { band: nextBand, crp: nextCrp, size: "medium", preview: true })
7748
7991
  ] }) : null
7749
7992
  ] }),
7750
- /* @__PURE__ */ jsxs58("div", { className: "fd-slider", children: [
7751
- /* @__PURE__ */ jsx63("span", { className: "fd-slider-fill", style: { width: pct + "%" } }),
7752
- dirty ? /* @__PURE__ */ jsx63("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,
7753
- /* @__PURE__ */ jsx63(
7993
+ /* @__PURE__ */ jsxs61("div", { className: "fd-slider", children: [
7994
+ /* @__PURE__ */ jsx66("span", { className: "fd-slider-fill", style: { width: pct + "%" } }),
7995
+ dirty ? /* @__PURE__ */ jsx66("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,
7996
+ /* @__PURE__ */ jsx66(
7754
7997
  "input",
7755
7998
  {
7756
7999
  type: "range",
@@ -7766,13 +8009,13 @@ function BudgetReallocator({
7766
8009
  }
7767
8010
  )
7768
8011
  ] }),
7769
- /* @__PURE__ */ jsxs58("div", { className: "fd-row", style: { gap: 12, flexWrap: "wrap" }, children: [
7770
- /* @__PURE__ */ jsxs58("span", { className: "fd-stack", style: { gap: 2, flex: 1, minWidth: 150 }, children: [
7771
- /* @__PURE__ */ jsx63("span", { className: "fd-num", style: { fontSize: 19, fontWeight: 700 }, children: "$" + draft.toLocaleString() }),
7772
- /* @__PURE__ */ jsx63("span", { className: "fd-body-sm fd-muted", children: "Arrow keys step $100, shift+arrow $1,000. Escape reverts." })
8012
+ /* @__PURE__ */ jsxs61("div", { className: "fd-row", style: { gap: 12, flexWrap: "wrap" }, children: [
8013
+ /* @__PURE__ */ jsxs61("span", { className: "fd-stack", style: { gap: 2, flex: 1, minWidth: 150 }, children: [
8014
+ /* @__PURE__ */ jsx66("span", { className: "fd-num", style: { fontSize: 19, fontWeight: 700 }, children: "$" + draft.toLocaleString() }),
8015
+ /* @__PURE__ */ jsx66("span", { className: "fd-body-sm fd-muted", children: "Arrow keys step $100, shift+arrow $1,000. Escape reverts." })
7773
8016
  ] }),
7774
- /* @__PURE__ */ jsx63("button", { type: "button", className: "fd-btn fd-btn-ghost", disabled: !dirty, onClick: revert, children: "Cancel" }),
7775
- /* @__PURE__ */ jsx63(
8017
+ /* @__PURE__ */ jsx66("button", { type: "button", className: "fd-btn fd-btn-ghost", disabled: !dirty, onClick: revert, children: "Cancel" }),
8018
+ /* @__PURE__ */ jsx66(
7776
8019
  "button",
7777
8020
  {
7778
8021
  type: "button",
@@ -7791,7 +8034,7 @@ function BudgetReallocator({
7791
8034
  }
7792
8035
 
7793
8036
  // src/components/planner/SurroundSound.tsx
7794
- import { jsx as jsx64, jsxs as jsxs59 } from "react/jsx-runtime";
8037
+ import { jsx as jsx67, jsxs as jsxs62 } from "react/jsx-runtime";
7795
8038
  var CATEGORIES = [
7796
8039
  { key: "ooh", label: "OOH", icon: "flag-banner", color: "var(--ch-ooh)" },
7797
8040
  { key: "transit", label: "Transit", icon: "bus", color: "var(--ch-transit)" },
@@ -7803,26 +8046,26 @@ var CATEGORIES = [
7803
8046
  function SurroundSound({ present = [], bonusPct = 0, bonusMax = 40, missedCost, className = "" }) {
7804
8047
  const earned = Math.max(0, Math.min(1, bonusPct / bonusMax));
7805
8048
  const single = present.length <= 2;
7806
- return /* @__PURE__ */ jsxs59("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 14 }, children: [
7807
- /* @__PURE__ */ jsx64("div", { className: "fd-row", style: { gap: 8, flexWrap: "wrap" }, children: CATEGORIES.map((c) => {
8049
+ return /* @__PURE__ */ jsxs62("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 14 }, children: [
8050
+ /* @__PURE__ */ jsx67("div", { className: "fd-row", style: { gap: 8, flexWrap: "wrap" }, children: CATEGORIES.map((c) => {
7808
8051
  const on = present.includes(c.key);
7809
- return /* @__PURE__ */ jsxs59(
8052
+ return /* @__PURE__ */ jsxs62(
7810
8053
  "span",
7811
8054
  {
7812
8055
  title: c.label + (on ? " \u2014 present" : " \u2014 not bought"),
7813
8056
  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)" },
7814
8057
  children: [
7815
- /* @__PURE__ */ jsx64("i", { className: "ph ph-" + c.icon, style: { fontSize: 19, color: on ? c.color : "var(--text-muted)" }, "aria-hidden": "true" }),
7816
- /* @__PURE__ */ jsx64("span", { style: { fontSize: 10.5, fontWeight: 700 }, children: c.label })
8058
+ /* @__PURE__ */ jsx67("i", { className: "ph ph-" + c.icon, style: { fontSize: 19, color: on ? c.color : "var(--text-muted)" }, "aria-hidden": "true" }),
8059
+ /* @__PURE__ */ jsx67("span", { style: { fontSize: 10.5, fontWeight: 700 }, children: c.label })
7817
8060
  ]
7818
8061
  },
7819
8062
  c.key
7820
8063
  );
7821
8064
  }) }),
7822
- /* @__PURE__ */ jsxs59("div", { className: "fd-stack", style: { gap: 8 }, children: [
7823
- /* @__PURE__ */ jsxs59("div", { className: "fd-row", style: { justifyContent: "space-between", gap: 12 }, children: [
7824
- /* @__PURE__ */ jsx64("span", { className: "fd-label-lg", children: "Surround-sound bonus earned" }),
7825
- /* @__PURE__ */ jsxs59("span", { className: "fd-num", style: { color: single ? "var(--warn-text)" : "var(--csi-3-mark)", fontWeight: 700 }, children: [
8065
+ /* @__PURE__ */ jsxs62("div", { className: "fd-stack", style: { gap: 8 }, children: [
8066
+ /* @__PURE__ */ jsxs62("div", { className: "fd-row", style: { justifyContent: "space-between", gap: 12 }, children: [
8067
+ /* @__PURE__ */ jsx67("span", { className: "fd-label-lg", children: "Surround-sound bonus earned" }),
8068
+ /* @__PURE__ */ jsxs62("span", { className: "fd-num", style: { color: single ? "var(--warn-text)" : "var(--csi-3-mark)", fontWeight: 700 }, children: [
7826
8069
  "+",
7827
8070
  bonusPct,
7828
8071
  "% of +",
@@ -7830,8 +8073,8 @@ function SurroundSound({ present = [], bonusPct = 0, bonusMax = 40, missedCost,
7830
8073
  "%"
7831
8074
  ] })
7832
8075
  ] }),
7833
- /* @__PURE__ */ jsx64("div", { style: { height: 8, borderRadius: "var(--r-xs)", background: "var(--surface-3)", overflow: "hidden" }, children: /* @__PURE__ */ jsx64("div", { style: { height: "100%", width: earned * 100 + "%", background: "var(--csi-3-mark)", borderRadius: "inherit", transition: "width var(--dur-slow) var(--ease)" } }) }),
7834
- /* @__PURE__ */ jsxs59("span", { className: "fd-body-sm fd-secondary", style: { textWrap: "pretty" }, children: [
8076
+ /* @__PURE__ */ jsx67("div", { style: { height: 8, borderRadius: "var(--r-xs)", background: "var(--surface-3)", overflow: "hidden" }, children: /* @__PURE__ */ jsx67("div", { style: { height: "100%", width: earned * 100 + "%", background: "var(--csi-3-mark)", borderRadius: "inherit", transition: "width var(--dur-slow) var(--ease)" } }) }),
8077
+ /* @__PURE__ */ jsxs62("span", { className: "fd-body-sm fd-secondary", style: { textWrap: "pretty" }, children: [
7835
8078
  present.length,
7836
8079
  " of 6 channel categories present.",
7837
8080
  " ",
@@ -7843,10 +8086,10 @@ function SurroundSound({ present = [], bonusPct = 0, bonusMax = 40, missedCost,
7843
8086
  }
7844
8087
 
7845
8088
  // src/components/chat/AgentChatPanel.tsx
7846
- import * as React39 from "react";
8089
+ import * as React41 from "react";
7847
8090
 
7848
8091
  // src/components/chat/chatEngine.ts
7849
- import * as React34 from "react";
8092
+ import * as React36 from "react";
7850
8093
  var CHAT_UNAVAILABLE = "chat_unavailable";
7851
8094
  var JOB_PENDING = ["queued", "running"];
7852
8095
  var JOB_SUCCESS = ["completed", "recovered"];
@@ -7900,22 +8143,22 @@ function useChatEngine(opts) {
7900
8143
  onClear,
7901
8144
  onFeedback
7902
8145
  } = opts || {};
7903
- const [status, setStatus] = React34.useState("idle");
7904
- const [threadId, setThreadId] = React34.useState(null);
7905
- const [messages, setMessages] = React34.useState([]);
7906
- const [queue, setQueue] = React34.useState([]);
7907
- const [fatal, setFatal] = React34.useState(null);
7908
- const [busy, setBusy] = React34.useState(false);
7909
- const [turnStartedAt, setTurnStartedAt] = React34.useState(null);
7910
- const listRef = React34.useRef([]);
7911
- const queueRef = React34.useRef([]);
7912
- const busyRef = React34.useRef(false);
7913
- const stoppedRef = React34.useRef(false);
7914
- const abortRef = React34.useRef(null);
7915
- const serverCount = React34.useRef(0);
7916
- const threadRef = React34.useRef(null);
7917
- const mounted = React34.useRef(true);
7918
- React34.useEffect(() => {
8146
+ const [status, setStatus] = React36.useState("idle");
8147
+ const [threadId, setThreadId] = React36.useState(null);
8148
+ const [messages, setMessages] = React36.useState([]);
8149
+ const [queue, setQueue] = React36.useState([]);
8150
+ const [fatal, setFatal] = React36.useState(null);
8151
+ const [busy, setBusy] = React36.useState(false);
8152
+ const [turnStartedAt, setTurnStartedAt] = React36.useState(null);
8153
+ const listRef = React36.useRef([]);
8154
+ const queueRef = React36.useRef([]);
8155
+ const busyRef = React36.useRef(false);
8156
+ const stoppedRef = React36.useRef(false);
8157
+ const abortRef = React36.useRef(null);
8158
+ const serverCount = React36.useRef(0);
8159
+ const threadRef = React36.useRef(null);
8160
+ const mounted = React36.useRef(true);
8161
+ React36.useEffect(() => {
7919
8162
  mounted.current = true;
7920
8163
  return () => {
7921
8164
  mounted.current = false;
@@ -7937,14 +8180,14 @@ function useChatEngine(opts) {
7937
8180
  }
7938
8181
  return false;
7939
8182
  };
7940
- const loadThread = React34.useCallback(async (id) => {
8183
+ const loadThread = React36.useCallback(async (id) => {
7941
8184
  const data = await apiAdapter.getThread(id);
7942
8185
  const list = [...data && data.messages || []];
7943
8186
  serverCount.current = list.length;
7944
8187
  commit(list);
7945
8188
  return list;
7946
8189
  }, [apiAdapter]);
7947
- React34.useEffect(() => {
8190
+ React36.useEffect(() => {
7948
8191
  if (!apiAdapter) {
7949
8192
  setStatus("idle");
7950
8193
  setFatal(null);
@@ -8157,7 +8400,7 @@ function useChatEngine(opts) {
8157
8400
  await dispatchTurn(turn);
8158
8401
  }
8159
8402
  }
8160
- const send = React34.useCallback((text, attachments) => {
8403
+ const send = React36.useCallback((text, attachments) => {
8161
8404
  const body = (text || "").trim();
8162
8405
  if (!body && !(attachments && attachments.length)) return;
8163
8406
  if (status === "disconnected") return;
@@ -8167,7 +8410,7 @@ function useChatEngine(opts) {
8167
8410
  stoppedRef.current = false;
8168
8411
  drain();
8169
8412
  }, [status]);
8170
- const stop = React34.useCallback(() => {
8413
+ const stop = React36.useCallback(() => {
8171
8414
  stoppedRef.current = true;
8172
8415
  const ac = abortRef.current;
8173
8416
  if (ac) {
@@ -8186,11 +8429,11 @@ function useChatEngine(opts) {
8186
8429
  store.del(STORAGE_PREFIX + threadRef.current);
8187
8430
  }
8188
8431
  }, [apiAdapter]);
8189
- const removeQueued = React34.useCallback((id) => {
8432
+ const removeQueued = React36.useCallback((id) => {
8190
8433
  queueRef.current = queueRef.current.filter((t) => t.id !== id);
8191
8434
  setQueue(queueRef.current.slice());
8192
8435
  }, []);
8193
- const retry = React34.useCallback(() => {
8436
+ const retry = React36.useCallback(() => {
8194
8437
  const list = listRef.current;
8195
8438
  let at = -1;
8196
8439
  for (let i = list.length - 1; i >= 0; i--) if (list[i].role === "user") {
@@ -8206,19 +8449,19 @@ function useChatEngine(opts) {
8206
8449
  setQueue(queueRef.current.slice());
8207
8450
  drain();
8208
8451
  }, []);
8209
- const clear = React34.useCallback(() => {
8452
+ const clear = React36.useCallback(() => {
8210
8453
  commit([]);
8211
8454
  serverCount.current = 0;
8212
8455
  queueRef.current = [];
8213
8456
  setQueue([]);
8214
8457
  onClear && onClear();
8215
8458
  }, [onClear]);
8216
- const setFeedback = React34.useCallback((id, value) => {
8459
+ const setFeedback = React36.useCallback((id, value) => {
8217
8460
  patch(id, (m) => ({ feedback: m.feedback === value ? null : value }));
8218
8461
  const msg = listRef.current.find((m) => m.id === id);
8219
8462
  onFeedback && onFeedback({ message: msg, feedback: msg ? msg.feedback : value });
8220
8463
  }, [onFeedback]);
8221
- const reload = React34.useCallback(async () => {
8464
+ const reload = React36.useCallback(async () => {
8222
8465
  if (!threadRef.current) return;
8223
8466
  setStatus("loading");
8224
8467
  try {
@@ -8256,11 +8499,11 @@ var ChatKit = {
8256
8499
  };
8257
8500
 
8258
8501
  // src/components/chat/ChatTranscript.tsx
8259
- import * as React36 from "react";
8502
+ import * as React38 from "react";
8260
8503
 
8261
8504
  // src/components/chat/ChatTurn.tsx
8262
- import * as React35 from "react";
8263
- import { jsx as jsx65, jsxs as jsxs60 } from "react/jsx-runtime";
8505
+ import * as React37 from "react";
8506
+ import { jsx as jsx68, jsxs as jsxs63 } from "react/jsx-runtime";
8264
8507
  function JsonView({ value }) {
8265
8508
  let text;
8266
8509
  try {
@@ -8268,67 +8511,67 @@ function JsonView({ value }) {
8268
8511
  } catch (e) {
8269
8512
  text = String(value);
8270
8513
  }
8271
- return /* @__PURE__ */ jsx65(CodeBlock, { code: text, language: "json", collapseAfter: 18 });
8514
+ return /* @__PURE__ */ jsx68(CodeBlock, { code: text, language: "json", collapseAfter: 18 });
8272
8515
  }
8273
8516
  function PacketCard({ packet, schema, render, onApply, applied }) {
8274
8517
  if (!packet) return null;
8275
8518
  const s = schema || {};
8276
8519
  const invalid = packet.valid === false;
8277
8520
  const title = s.heading || packet.type;
8278
- return /* @__PURE__ */ jsxs60("section", { className: "fdc-packet" + (invalid ? " is-invalid" : ""), "aria-label": title, children: [
8279
- /* @__PURE__ */ jsxs60("header", { className: "fdc-packet-head", children: [
8280
- /* @__PURE__ */ jsx65("i", { className: "ph ph-" + (s.icon || "package"), "aria-hidden": "true" }),
8281
- /* @__PURE__ */ jsx65("span", { className: "fdc-packet-title", children: title }),
8282
- packet.repaired ? /* @__PURE__ */ jsx65("span", { className: "fdc-packet-badge", children: "Repaired" }) : null,
8283
- invalid ? /* @__PURE__ */ jsx65("span", { className: "fdc-packet-badge is-danger", children: "Invalid" }) : null
8521
+ return /* @__PURE__ */ jsxs63("section", { className: "fdc-packet" + (invalid ? " is-invalid" : ""), "aria-label": title, children: [
8522
+ /* @__PURE__ */ jsxs63("header", { className: "fdc-packet-head", children: [
8523
+ /* @__PURE__ */ jsx68("i", { className: "ph ph-" + (s.icon || "package"), "aria-hidden": "true" }),
8524
+ /* @__PURE__ */ jsx68("span", { className: "fdc-packet-title", children: title }),
8525
+ packet.repaired ? /* @__PURE__ */ jsx68("span", { className: "fdc-packet-badge", children: "Repaired" }) : null,
8526
+ invalid ? /* @__PURE__ */ jsx68("span", { className: "fdc-packet-badge is-danger", children: "Invalid" }) : null
8284
8527
  ] }),
8285
- invalid ? /* @__PURE__ */ jsxs60("div", { className: "fdc-packet-alert", role: "alert", children: [
8286
- /* @__PURE__ */ jsx65("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
8287
- /* @__PURE__ */ jsx65("span", { children: packet.error || "This result failed validation and can\u2019t be applied." })
8288
- ] }) : /* @__PURE__ */ jsx65("div", { className: "fdc-packet-body", children: render ? render(packet) : /* @__PURE__ */ jsx65(JsonView, { value: packet.payload }) }),
8289
- !invalid && onApply ? /* @__PURE__ */ jsxs60("footer", { className: "fdc-packet-foot", children: [
8290
- packet.repaired ? /* @__PURE__ */ jsx65("span", { className: "fdc-packet-note", children: "Corrected by the backend after a first attempt." }) : /* @__PURE__ */ jsx65("span", {}),
8291
- /* @__PURE__ */ jsxs60("button", { type: "button", className: "fd-btn fd-btn-primary fd-btn-sm", disabled: applied, onClick: () => onApply(packet), children: [
8292
- /* @__PURE__ */ jsx65("i", { className: "ph ph-" + (applied ? "check" : "arrow-square-in"), "aria-hidden": "true" }),
8528
+ invalid ? /* @__PURE__ */ jsxs63("div", { className: "fdc-packet-alert", role: "alert", children: [
8529
+ /* @__PURE__ */ jsx68("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
8530
+ /* @__PURE__ */ jsx68("span", { children: packet.error || "This result failed validation and can\u2019t be applied." })
8531
+ ] }) : /* @__PURE__ */ jsx68("div", { className: "fdc-packet-body", children: render ? render(packet) : /* @__PURE__ */ jsx68(JsonView, { value: packet.payload }) }),
8532
+ !invalid && onApply ? /* @__PURE__ */ jsxs63("footer", { className: "fdc-packet-foot", children: [
8533
+ packet.repaired ? /* @__PURE__ */ jsx68("span", { className: "fdc-packet-note", children: "Corrected by the backend after a first attempt." }) : /* @__PURE__ */ jsx68("span", {}),
8534
+ /* @__PURE__ */ jsxs63("button", { type: "button", className: "fd-btn fd-btn-primary fd-btn-sm", disabled: applied, onClick: () => onApply(packet), children: [
8535
+ /* @__PURE__ */ jsx68("i", { className: "ph ph-" + (applied ? "check" : "arrow-square-in"), "aria-hidden": "true" }),
8293
8536
  applied ? "Applied" : s.applyLabel || "Apply"
8294
8537
  ] })
8295
8538
  ] }) : null
8296
8539
  ] });
8297
8540
  }
8298
8541
  function ThinkingBlock({ text, durationMs, streaming, defaultOpen = false }) {
8299
- const [open, setOpen] = React35.useState(defaultOpen);
8542
+ const [open, setOpen] = React37.useState(defaultOpen);
8300
8543
  if (!text) return null;
8301
- return /* @__PURE__ */ jsxs60("div", { className: "fdc-think" + (open ? " is-open" : ""), children: [
8302
- /* @__PURE__ */ jsxs60("button", { type: "button", className: "fdc-think-head", onClick: () => setOpen((v) => !v), "aria-expanded": open, children: [
8303
- /* @__PURE__ */ jsx65("i", { className: "ph ph-brain", "aria-hidden": "true" }),
8304
- /* @__PURE__ */ jsx65("span", { children: streaming ? "Thinking" : durationMs ? "Thought for " + formatDuration(durationMs) : "Thought process" }),
8305
- streaming ? /* @__PURE__ */ jsxs60("span", { className: "fdc-dots", "aria-hidden": "true", children: [
8306
- /* @__PURE__ */ jsx65("span", {}),
8307
- /* @__PURE__ */ jsx65("span", {}),
8308
- /* @__PURE__ */ jsx65("span", {})
8544
+ return /* @__PURE__ */ jsxs63("div", { className: "fdc-think" + (open ? " is-open" : ""), children: [
8545
+ /* @__PURE__ */ jsxs63("button", { type: "button", className: "fdc-think-head", onClick: () => setOpen((v) => !v), "aria-expanded": open, children: [
8546
+ /* @__PURE__ */ jsx68("i", { className: "ph ph-brain", "aria-hidden": "true" }),
8547
+ /* @__PURE__ */ jsx68("span", { children: streaming ? "Thinking" : durationMs ? "Thought for " + formatDuration(durationMs) : "Thought process" }),
8548
+ streaming ? /* @__PURE__ */ jsxs63("span", { className: "fdc-dots", "aria-hidden": "true", children: [
8549
+ /* @__PURE__ */ jsx68("span", {}),
8550
+ /* @__PURE__ */ jsx68("span", {}),
8551
+ /* @__PURE__ */ jsx68("span", {})
8309
8552
  ] }) : null,
8310
- /* @__PURE__ */ jsx65("i", { className: "ph ph-caret-" + (open ? "up" : "down"), "aria-hidden": "true" })
8553
+ /* @__PURE__ */ jsx68("i", { className: "ph ph-caret-" + (open ? "up" : "down"), "aria-hidden": "true" })
8311
8554
  ] }),
8312
- open ? /* @__PURE__ */ jsx65("div", { className: "fdc-think-body", children: text }) : null
8555
+ open ? /* @__PURE__ */ jsx68("div", { className: "fdc-think-body", children: text }) : null
8313
8556
  ] });
8314
8557
  }
8315
8558
  function Citations({ items = [], onOpen }) {
8316
- const [open, setOpen] = React35.useState(false);
8559
+ const [open, setOpen] = React37.useState(false);
8317
8560
  if (!items.length) return null;
8318
- return /* @__PURE__ */ jsxs60("div", { className: "fdc-cites", children: [
8319
- /* @__PURE__ */ jsxs60("button", { type: "button", className: "fdc-cites-head", onClick: () => setOpen((v) => !v), "aria-expanded": open, children: [
8320
- /* @__PURE__ */ jsx65("i", { className: "ph ph-quotes", "aria-hidden": "true" }),
8321
- /* @__PURE__ */ jsxs60("span", { children: [
8561
+ return /* @__PURE__ */ jsxs63("div", { className: "fdc-cites", children: [
8562
+ /* @__PURE__ */ jsxs63("button", { type: "button", className: "fdc-cites-head", onClick: () => setOpen((v) => !v), "aria-expanded": open, children: [
8563
+ /* @__PURE__ */ jsx68("i", { className: "ph ph-quotes", "aria-hidden": "true" }),
8564
+ /* @__PURE__ */ jsxs63("span", { children: [
8322
8565
  items.length,
8323
8566
  " source",
8324
8567
  items.length === 1 ? "" : "s"
8325
8568
  ] }),
8326
- /* @__PURE__ */ jsx65("i", { className: "ph ph-caret-" + (open ? "up" : "down"), "aria-hidden": "true" })
8569
+ /* @__PURE__ */ jsx68("i", { className: "ph ph-caret-" + (open ? "up" : "down"), "aria-hidden": "true" })
8327
8570
  ] }),
8328
- open ? /* @__PURE__ */ jsx65("ol", { className: "fdc-cites-list", children: items.map((c, i) => /* @__PURE__ */ jsxs60("li", { children: [
8329
- /* @__PURE__ */ jsx65("span", { className: "fdc-cite-n fd-tabular", children: c.marker || i + 1 }),
8330
- c.url ? /* @__PURE__ */ jsx65("a", { href: c.url, target: "_blank", rel: "noopener noreferrer", onClick: onOpen ? (e) => onOpen(c, e) : void 0, children: c.title || c.url }) : /* @__PURE__ */ jsx65("span", { children: c.title || "Source" }),
8331
- c.detail ? /* @__PURE__ */ jsx65("span", { className: "fdc-cite-detail", children: c.detail }) : null
8571
+ open ? /* @__PURE__ */ jsx68("ol", { className: "fdc-cites-list", children: items.map((c, i) => /* @__PURE__ */ jsxs63("li", { children: [
8572
+ /* @__PURE__ */ jsx68("span", { className: "fdc-cite-n fd-tabular", children: c.marker || i + 1 }),
8573
+ c.url ? /* @__PURE__ */ jsx68("a", { href: c.url, target: "_blank", rel: "noopener noreferrer", onClick: onOpen ? (e) => onOpen(c, e) : void 0, children: c.title || c.url }) : /* @__PURE__ */ jsx68("span", { children: c.title || "Source" }),
8574
+ c.detail ? /* @__PURE__ */ jsx68("span", { className: "fdc-cite-detail", children: c.detail }) : null
8332
8575
  ] }, c.id || i)) }) : null
8333
8576
  ] });
8334
8577
  }
@@ -8339,29 +8582,29 @@ function clampText(text, max) {
8339
8582
  return (at > max * 0.6 ? cut.slice(0, at) : cut).trimEnd() + "\u2026";
8340
8583
  }
8341
8584
  function MessageBody({ message: m, ctx }) {
8342
- const [expanded, setExpanded] = React35.useState(false);
8585
+ const [expanded, setExpanded] = React37.useState(false);
8343
8586
  const isUser = m.role === "user";
8344
8587
  const raw = m.text || "";
8345
8588
  const clamped = !expanded && !m.streaming ? clampText(raw, ctx.maxVisibleChars) : null;
8346
8589
  const body = clamped != null ? clamped : raw;
8347
8590
  const showMd = ctx.markdown && !isUser;
8348
- return /* @__PURE__ */ jsxs60("div", { className: "fdc-body", children: [
8349
- m.thinking && ctx.showThinking ? /* @__PURE__ */ jsx65(ThinkingBlock, { text: m.thinking, durationMs: m.thinkingMs, streaming: m.streaming && !m.text }) : null,
8350
- m.steps && m.steps.length && ctx.showSteps ? /* @__PURE__ */ jsx65(StepList, { steps: m.steps, defaultOpen: m.steps.some((s) => s.status === "running"), dense: true }) : null,
8351
- body ? /* @__PURE__ */ jsxs60("div", { className: "fdc-text" + (isUser ? " is-user" : ""), children: [
8352
- showMd ? /* @__PURE__ */ jsx65(Markdown, { source: body, headingOffset: 2, codeProps: { collapseAfter: 22 }, renderCitation: ctx.renderCitation }) : /* @__PURE__ */ jsx65("div", { className: "fdc-plain", children: body }),
8353
- m.streaming ? /* @__PURE__ */ jsx65("span", { className: "fdc-caret", "aria-hidden": "true" }) : null
8591
+ return /* @__PURE__ */ jsxs63("div", { className: "fdc-body", children: [
8592
+ m.thinking && ctx.showThinking ? /* @__PURE__ */ jsx68(ThinkingBlock, { text: m.thinking, durationMs: m.thinkingMs, streaming: m.streaming && !m.text }) : null,
8593
+ m.steps && m.steps.length && ctx.showSteps ? /* @__PURE__ */ jsx68(StepList, { steps: m.steps, defaultOpen: m.steps.some((s) => s.status === "running"), dense: true }) : null,
8594
+ body ? /* @__PURE__ */ jsxs63("div", { className: "fdc-text" + (isUser ? " is-user" : ""), children: [
8595
+ showMd ? /* @__PURE__ */ jsx68(Markdown, { source: body, headingOffset: 2, codeProps: { collapseAfter: 22 }, renderCitation: ctx.renderCitation }) : /* @__PURE__ */ jsx68("div", { className: "fdc-plain", children: body }),
8596
+ m.streaming ? /* @__PURE__ */ jsx68("span", { className: "fdc-caret", "aria-hidden": "true" }) : null
8354
8597
  ] }) : null,
8355
- clamped != null ? /* @__PURE__ */ jsxs60("button", { type: "button", className: "fdc-more", onClick: () => setExpanded(true), children: [
8356
- /* @__PURE__ */ jsx65("i", { className: "ph ph-caret-down", "aria-hidden": "true" }),
8598
+ clamped != null ? /* @__PURE__ */ jsxs63("button", { type: "button", className: "fdc-more", onClick: () => setExpanded(true), children: [
8599
+ /* @__PURE__ */ jsx68("i", { className: "ph ph-caret-down", "aria-hidden": "true" }),
8357
8600
  "Show more",
8358
- /* @__PURE__ */ jsx65("span", { className: "fdc-more-len fd-tabular", children: raw.length < 2e3 ? raw.length.toLocaleString() + " characters" : Math.round(raw.length / 100) / 10 + "k characters" })
8359
- ] }) : expanded && ctx.maxVisibleChars && raw.length > ctx.maxVisibleChars ? /* @__PURE__ */ jsxs60("button", { type: "button", className: "fdc-more", onClick: () => setExpanded(false), children: [
8360
- /* @__PURE__ */ jsx65("i", { className: "ph ph-caret-up", "aria-hidden": "true" }),
8601
+ /* @__PURE__ */ jsx68("span", { className: "fdc-more-len fd-tabular", children: raw.length < 2e3 ? raw.length.toLocaleString() + " characters" : Math.round(raw.length / 100) / 10 + "k characters" })
8602
+ ] }) : expanded && ctx.maxVisibleChars && raw.length > ctx.maxVisibleChars ? /* @__PURE__ */ jsxs63("button", { type: "button", className: "fdc-more", onClick: () => setExpanded(false), children: [
8603
+ /* @__PURE__ */ jsx68("i", { className: "ph ph-caret-up", "aria-hidden": "true" }),
8361
8604
  "Show less"
8362
8605
  ] }) : null,
8363
- m.attachments && m.attachments.length ? /* @__PURE__ */ jsx65(FileGrid, { files: m.attachments, onOpen: ctx.onOpenAttachment, tiles: true, maxHeight: ctx.attachmentHeight || 220, compact: ctx.narrow }) : null,
8364
- m.packet ? /* @__PURE__ */ jsx65(
8606
+ m.attachments && m.attachments.length ? /* @__PURE__ */ jsx68(FileGrid, { files: m.attachments, onOpen: ctx.onOpenAttachment, tiles: true, maxHeight: ctx.attachmentHeight || 220, compact: ctx.narrow }) : null,
8607
+ m.packet ? /* @__PURE__ */ jsx68(
8365
8608
  PacketCard,
8366
8609
  {
8367
8610
  packet: m.packet,
@@ -8371,44 +8614,44 @@ function MessageBody({ message: m, ctx }) {
8371
8614
  applied: ctx.appliedPackets && ctx.appliedPackets[m.id]
8372
8615
  }
8373
8616
  ) : null,
8374
- m.citations && m.citations.length ? /* @__PURE__ */ jsx65(Citations, { items: m.citations, onOpen: ctx.onOpenCitation }) : null,
8375
- m.working ? /* @__PURE__ */ jsxs60("div", { className: "fdc-working", role: "status", children: [
8376
- /* @__PURE__ */ jsxs60("span", { className: "fdc-dots", "aria-hidden": "true", children: [
8377
- /* @__PURE__ */ jsx65("span", {}),
8378
- /* @__PURE__ */ jsx65("span", {}),
8379
- /* @__PURE__ */ jsx65("span", {})
8617
+ m.citations && m.citations.length ? /* @__PURE__ */ jsx68(Citations, { items: m.citations, onOpen: ctx.onOpenCitation }) : null,
8618
+ m.working ? /* @__PURE__ */ jsxs63("div", { className: "fdc-working", role: "status", children: [
8619
+ /* @__PURE__ */ jsxs63("span", { className: "fdc-dots", "aria-hidden": "true", children: [
8620
+ /* @__PURE__ */ jsx68("span", {}),
8621
+ /* @__PURE__ */ jsx68("span", {}),
8622
+ /* @__PURE__ */ jsx68("span", {})
8380
8623
  ] }),
8381
- /* @__PURE__ */ jsxs60("span", { className: "fdc-working-label", children: [
8624
+ /* @__PURE__ */ jsxs63("span", { className: "fdc-working-label", children: [
8382
8625
  m.resumed ? "Resuming" : "Working",
8383
- m.job && m.job.status ? /* @__PURE__ */ jsxs60("span", { className: "fdc-working-job", children: [
8626
+ m.job && m.job.status ? /* @__PURE__ */ jsxs63("span", { className: "fdc-working-job", children: [
8384
8627
  " \xB7 ",
8385
8628
  m.job.status
8386
8629
  ] }) : null,
8387
- m.job && m.job.detail ? /* @__PURE__ */ jsxs60("span", { className: "fdc-working-job", children: [
8630
+ m.job && m.job.detail ? /* @__PURE__ */ jsxs63("span", { className: "fdc-working-job", children: [
8388
8631
  " \xB7 ",
8389
8632
  m.job.detail
8390
8633
  ] }) : null
8391
8634
  ] }),
8392
- m.jobId ? /* @__PURE__ */ jsx65("span", { className: "fdc-working-id fd-mono", children: String(m.jobId).slice(0, 12) }) : null
8635
+ m.jobId ? /* @__PURE__ */ jsx68("span", { className: "fdc-working-id fd-mono", children: String(m.jobId).slice(0, 12) }) : null
8393
8636
  ] }) : null,
8394
- m.stopped ? /* @__PURE__ */ jsxs60("div", { className: "fdc-stopped", children: [
8395
- /* @__PURE__ */ jsx65("i", { className: "ph ph-stop-circle", "aria-hidden": "true" }),
8637
+ m.stopped ? /* @__PURE__ */ jsxs63("div", { className: "fdc-stopped", children: [
8638
+ /* @__PURE__ */ jsx68("i", { className: "ph ph-stop-circle", "aria-hidden": "true" }),
8396
8639
  "Stopped"
8397
8640
  ] }) : null,
8398
- m.error ? /* @__PURE__ */ jsxs60("div", { className: "fdc-error", role: "alert", children: [
8399
- /* @__PURE__ */ jsx65("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
8400
- /* @__PURE__ */ jsx65("span", { className: "fdc-error-text", children: ctx.errorCopy ? ctx.errorCopy(m.error) : m.error }),
8401
- m.retryable && ctx.onRetry ? /* @__PURE__ */ jsxs60("button", { type: "button", className: "fdc-error-retry", onClick: ctx.onRetry, children: [
8402
- /* @__PURE__ */ jsx65("i", { className: "ph ph-arrow-clockwise", "aria-hidden": "true" }),
8641
+ m.error ? /* @__PURE__ */ jsxs63("div", { className: "fdc-error", role: "alert", children: [
8642
+ /* @__PURE__ */ jsx68("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
8643
+ /* @__PURE__ */ jsx68("span", { className: "fdc-error-text", children: ctx.errorCopy ? ctx.errorCopy(m.error) : m.error }),
8644
+ m.retryable && ctx.onRetry ? /* @__PURE__ */ jsxs63("button", { type: "button", className: "fdc-error-retry", onClick: ctx.onRetry, children: [
8645
+ /* @__PURE__ */ jsx68("i", { className: "ph ph-arrow-clockwise", "aria-hidden": "true" }),
8403
8646
  "Retry"
8404
8647
  ] }) : null
8405
8648
  ] }) : null
8406
8649
  ] });
8407
8650
  }
8408
8651
  function useCopyRun() {
8409
- const [done, setDone] = React35.useState(false);
8410
- const t = React35.useRef(null);
8411
- React35.useEffect(() => () => {
8652
+ const [done, setDone] = React37.useState(false);
8653
+ const t = React37.useRef(null);
8654
+ React37.useEffect(() => () => {
8412
8655
  if (t.current) clearTimeout(t.current);
8413
8656
  }, []);
8414
8657
  return [done, (text) => {
@@ -8428,16 +8671,16 @@ function RunActions({ group, ctx }) {
8428
8671
  const isAssistant = group.role === "assistant";
8429
8672
  const fb = last.feedback;
8430
8673
  if (!ctx.messageActions) return null;
8431
- return /* @__PURE__ */ jsxs60("div", { className: "fdc-actions", role: "group", "aria-label": "Message actions", children: [
8432
- /* @__PURE__ */ jsxs60("button", { type: "button", className: "fdc-act" + (copied ? " is-done" : ""), onClick: () => copy(markdownToText(text)), "aria-label": "Copy message", children: [
8433
- /* @__PURE__ */ jsx65("i", { className: "ph ph-" + (copied ? "check" : "copy"), "aria-hidden": "true" }),
8434
- /* @__PURE__ */ jsx65("span", { className: "fdc-act-label", children: copied ? "Copied" : "Copy" })
8674
+ return /* @__PURE__ */ jsxs63("div", { className: "fdc-actions", role: "group", "aria-label": "Message actions", children: [
8675
+ /* @__PURE__ */ jsxs63("button", { type: "button", className: "fdc-act" + (copied ? " is-done" : ""), onClick: () => copy(markdownToText(text)), "aria-label": "Copy message", children: [
8676
+ /* @__PURE__ */ jsx68("i", { className: "ph ph-" + (copied ? "check" : "copy"), "aria-hidden": "true" }),
8677
+ /* @__PURE__ */ jsx68("span", { className: "fdc-act-label", children: copied ? "Copied" : "Copy" })
8435
8678
  ] }),
8436
- isAssistant && ctx.onRetry ? /* @__PURE__ */ jsx65("button", { type: "button", className: "fdc-act", onClick: ctx.onRetry, "aria-label": "Retry this turn", children: /* @__PURE__ */ jsx65("i", { className: "ph ph-arrow-clockwise", "aria-hidden": "true" }) }) : null,
8437
- group.role === "user" && ctx.onEdit ? /* @__PURE__ */ jsx65("button", { type: "button", className: "fdc-act", onClick: () => ctx.onEdit(last), "aria-label": "Edit and resend", children: /* @__PURE__ */ jsx65("i", { className: "ph ph-pencil-simple", "aria-hidden": "true" }) }) : null,
8438
- isAssistant && ctx.onFeedback ? /* @__PURE__ */ jsxs60(React35.Fragment, { children: [
8439
- /* @__PURE__ */ jsx65("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__ */ jsx65("i", { className: "ph ph-thumbs-up", "aria-hidden": "true" }) }),
8440
- /* @__PURE__ */ jsx65("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__ */ jsx65("i", { className: "ph ph-thumbs-down", "aria-hidden": "true" }) })
8679
+ isAssistant && ctx.onRetry ? /* @__PURE__ */ jsx68("button", { type: "button", className: "fdc-act", onClick: ctx.onRetry, "aria-label": "Retry this turn", children: /* @__PURE__ */ jsx68("i", { className: "ph ph-arrow-clockwise", "aria-hidden": "true" }) }) : null,
8680
+ group.role === "user" && ctx.onEdit ? /* @__PURE__ */ jsx68("button", { type: "button", className: "fdc-act", onClick: () => ctx.onEdit(last), "aria-label": "Edit and resend", children: /* @__PURE__ */ jsx68("i", { className: "ph ph-pencil-simple", "aria-hidden": "true" }) }) : null,
8681
+ isAssistant && ctx.onFeedback ? /* @__PURE__ */ jsxs63(React37.Fragment, { children: [
8682
+ /* @__PURE__ */ jsx68("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__ */ jsx68("i", { className: "ph ph-thumbs-up", "aria-hidden": "true" }) }),
8683
+ /* @__PURE__ */ jsx68("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__ */ jsx68("i", { className: "ph ph-thumbs-down", "aria-hidden": "true" }) })
8441
8684
  ] }) : null,
8442
8685
  ctx.extraActions ? ctx.extraActions(group) : null
8443
8686
  ] });
@@ -8447,22 +8690,22 @@ function ChatTurn({ group, ctx }) {
8447
8690
  const name = isUser ? ctx.userName : group.author || ctx.assistantName;
8448
8691
  const avatar = isUser ? ctx.userAvatar : ctx.assistantAvatar;
8449
8692
  const stamp = group.messages[0].timestamp;
8450
- return /* @__PURE__ */ jsxs60("article", { className: "fdc-turn is-" + group.role, "aria-label": String(name) + (stamp ? " at " + formatClock(stamp) : ""), children: [
8451
- /* @__PURE__ */ jsxs60("div", { className: "fdc-turn-head", children: [
8452
- ctx.showAvatars ? /* @__PURE__ */ jsx65("span", { className: "fdc-avatar is-" + group.role, "aria-hidden": "true", children: avatar ? /* @__PURE__ */ jsx65("img", { src: avatar, alt: "" }) : isUser ? /* @__PURE__ */ jsx65("span", { className: "fdc-avatar-txt", children: (name || "You").slice(0, 1).toUpperCase() }) : /* @__PURE__ */ jsx65("i", { className: "ph ph-" + (ctx.assistantIcon || "sparkle") }) }) : null,
8453
- /* @__PURE__ */ jsx65("span", { className: "fdc-who", children: name }),
8454
- stamp ? /* @__PURE__ */ jsx65(RelativeTime, { className: "fdc-when", value: stamp }) : null,
8455
- group.messages.some((m) => m.model) ? /* @__PURE__ */ jsx65("span", { className: "fdc-turn-model", children: group.messages.find((m) => m.model).model }) : null
8693
+ return /* @__PURE__ */ jsxs63("article", { className: "fdc-turn is-" + group.role, "aria-label": String(name) + (stamp ? " at " + formatClock(stamp) : ""), children: [
8694
+ /* @__PURE__ */ jsxs63("div", { className: "fdc-turn-head", children: [
8695
+ ctx.showAvatars ? /* @__PURE__ */ jsx68("span", { className: "fdc-avatar is-" + group.role, "aria-hidden": "true", children: avatar ? /* @__PURE__ */ jsx68("img", { src: avatar, alt: "" }) : isUser ? /* @__PURE__ */ jsx68("span", { className: "fdc-avatar-txt", children: (name || "You").slice(0, 1).toUpperCase() }) : /* @__PURE__ */ jsx68("i", { className: "ph ph-" + (ctx.assistantIcon || "sparkle") }) }) : null,
8696
+ /* @__PURE__ */ jsx68("span", { className: "fdc-who", children: name }),
8697
+ stamp ? /* @__PURE__ */ jsx68(RelativeTime, { className: "fdc-when", value: stamp }) : null,
8698
+ group.messages.some((m) => m.model) ? /* @__PURE__ */ jsx68("span", { className: "fdc-turn-model", children: group.messages.find((m) => m.model).model }) : null
8456
8699
  ] }),
8457
- /* @__PURE__ */ jsxs60("div", { className: "fdc-turn-body", children: [
8458
- group.messages.map((m) => /* @__PURE__ */ jsx65("div", { className: "fdc-msg" + (m.pending ? " is-pending" : ""), children: /* @__PURE__ */ jsx65(MessageBody, { message: m, ctx }) }, m.id)),
8459
- /* @__PURE__ */ jsx65(RunActions, { group, ctx })
8700
+ /* @__PURE__ */ jsxs63("div", { className: "fdc-turn-body", children: [
8701
+ group.messages.map((m) => /* @__PURE__ */ jsx68("div", { className: "fdc-msg" + (m.pending ? " is-pending" : ""), children: /* @__PURE__ */ jsx68(MessageBody, { message: m, ctx }) }, m.id)),
8702
+ /* @__PURE__ */ jsx68(RunActions, { group, ctx })
8460
8703
  ] })
8461
8704
  ] });
8462
8705
  }
8463
8706
 
8464
8707
  // src/components/chat/ChatTranscript.tsx
8465
- import { jsx as jsx66, jsxs as jsxs61 } from "react/jsx-runtime";
8708
+ import { jsx as jsx69, jsxs as jsxs64 } from "react/jsx-runtime";
8466
8709
  var GROUP_WINDOW = 6e4;
8467
8710
  var STICK_PX = 100;
8468
8711
  function groupMessages(list) {
@@ -8495,25 +8738,25 @@ function dayLabel(key) {
8495
8738
  }
8496
8739
  function Suggestions({ items = [], onPick }) {
8497
8740
  if (!items.length) return null;
8498
- return /* @__PURE__ */ jsx66("div", { className: "fdc-suggest", children: items.map((s, i) => {
8741
+ return /* @__PURE__ */ jsx69("div", { className: "fdc-suggest", children: items.map((s, i) => {
8499
8742
  const it = typeof s === "string" ? { label: s, text: s } : s;
8500
- return /* @__PURE__ */ jsxs61("button", { type: "button", className: "fdc-suggest-item", onClick: () => onPick && onPick(it.text || it.label), children: [
8501
- it.icon ? /* @__PURE__ */ jsx66("i", { className: "ph ph-" + it.icon, "aria-hidden": "true" }) : null,
8502
- /* @__PURE__ */ jsxs61("span", { className: "fdc-suggest-text", children: [
8503
- /* @__PURE__ */ jsx66("span", { className: "fdc-suggest-label", children: it.label }),
8504
- it.description ? /* @__PURE__ */ jsx66("span", { className: "fdc-suggest-desc", children: it.description }) : null
8743
+ return /* @__PURE__ */ jsxs64("button", { type: "button", className: "fdc-suggest-item", onClick: () => onPick && onPick(it.text || it.label), children: [
8744
+ it.icon ? /* @__PURE__ */ jsx69("i", { className: "ph ph-" + it.icon, "aria-hidden": "true" }) : null,
8745
+ /* @__PURE__ */ jsxs64("span", { className: "fdc-suggest-text", children: [
8746
+ /* @__PURE__ */ jsx69("span", { className: "fdc-suggest-label", children: it.label }),
8747
+ it.description ? /* @__PURE__ */ jsx69("span", { className: "fdc-suggest-desc", children: it.description }) : null
8505
8748
  ] }),
8506
- /* @__PURE__ */ jsx66("i", { className: "ph ph-arrow-up-right fdc-suggest-go", "aria-hidden": "true" })
8749
+ /* @__PURE__ */ jsx69("i", { className: "ph ph-arrow-up-right fdc-suggest-go", "aria-hidden": "true" })
8507
8750
  ] }, it.id || i);
8508
8751
  }) });
8509
8752
  }
8510
8753
  function LoadingTurns() {
8511
- return /* @__PURE__ */ jsx66("div", { className: "fdc-skel", "aria-hidden": "true", children: [0, 1].map((i) => /* @__PURE__ */ jsxs61("div", { className: "fdc-skel-turn", children: [
8512
- /* @__PURE__ */ jsx66("div", { className: "fd-skel fd-skel-circle", style: { width: 22, height: 22 } }),
8513
- /* @__PURE__ */ jsxs61("div", { className: "fdc-skel-lines", children: [
8514
- /* @__PURE__ */ jsx66("div", { className: "fd-skel", style: { width: i ? "62%" : "44%", height: 11 } }),
8515
- /* @__PURE__ */ jsx66("div", { className: "fd-skel", style: { width: i ? "94%" : "78%", height: 11 } }),
8516
- /* @__PURE__ */ jsx66("div", { className: "fd-skel", style: { width: i ? "71%" : "56%", height: 11 } })
8754
+ return /* @__PURE__ */ jsx69("div", { className: "fdc-skel", "aria-hidden": "true", children: [0, 1].map((i) => /* @__PURE__ */ jsxs64("div", { className: "fdc-skel-turn", children: [
8755
+ /* @__PURE__ */ jsx69("div", { className: "fd-skel fd-skel-circle", style: { width: 22, height: 22 } }),
8756
+ /* @__PURE__ */ jsxs64("div", { className: "fdc-skel-lines", children: [
8757
+ /* @__PURE__ */ jsx69("div", { className: "fd-skel", style: { width: i ? "62%" : "44%", height: 11 } }),
8758
+ /* @__PURE__ */ jsx69("div", { className: "fd-skel", style: { width: i ? "94%" : "78%", height: 11 } }),
8759
+ /* @__PURE__ */ jsx69("div", { className: "fd-skel", style: { width: i ? "71%" : "56%", height: 11 } })
8517
8760
  ] })
8518
8761
  ] }, i)) });
8519
8762
  }
@@ -8530,10 +8773,10 @@ function ChatTranscript({
8530
8773
  renderEmpty,
8531
8774
  className = ""
8532
8775
  }) {
8533
- const scroller = React36.useRef(null);
8534
- const stick = React36.useRef(true);
8535
- const [pill, setPill] = React36.useState(0);
8536
- const seen = React36.useRef(0);
8776
+ const scroller = React38.useRef(null);
8777
+ const stick = React38.useRef(true);
8778
+ const [pill, setPill] = React38.useState(0);
8779
+ const seen = React38.useRef(0);
8537
8780
  const toBottom = (smooth) => {
8538
8781
  const el = scroller.current;
8539
8782
  if (!el) return;
@@ -8552,7 +8795,7 @@ function ChatTranscript({
8552
8795
  seen.current = messages.length;
8553
8796
  }
8554
8797
  };
8555
- React36.useLayoutEffect(() => {
8798
+ React38.useLayoutEffect(() => {
8556
8799
  const el = scroller.current;
8557
8800
  if (!el) return;
8558
8801
  if (stick.current) {
@@ -8560,7 +8803,7 @@ function ChatTranscript({
8560
8803
  seen.current = messages.length;
8561
8804
  } else setPill(Math.max(0, messages.length - seen.current));
8562
8805
  }, [messages]);
8563
- React36.useEffect(() => {
8806
+ React38.useEffect(() => {
8564
8807
  const el = scroller.current;
8565
8808
  const inner = el && el.firstChild;
8566
8809
  if (!el || !inner || typeof ResizeObserver === "undefined") return;
@@ -8570,38 +8813,38 @@ function ChatTranscript({
8570
8813
  ro.observe(inner);
8571
8814
  return () => ro.disconnect();
8572
8815
  }, []);
8573
- const groups = React36.useMemo(() => groupMessages(messages), [messages]);
8816
+ const groups = React38.useMemo(() => groupMessages(messages), [messages]);
8574
8817
  const empty = !messages.length && status === "ready";
8575
- return /* @__PURE__ */ jsxs61("div", { className: ["fdc-scroll", className].filter(Boolean).join(" "), ref: scroller, onScroll, children: [
8576
- /* @__PURE__ */ jsxs61("div", { className: "fdc-log", role: "log", "aria-label": "Conversation", children: [
8577
- status === "loading" || status === "resolving" ? /* @__PURE__ */ jsx66(LoadingTurns, {}) : null,
8578
- status === "disconnected" ? /* @__PURE__ */ jsxs61("div", { className: "fdc-dead", children: [
8579
- /* @__PURE__ */ jsx66("span", { className: "fdc-dead-icon", children: /* @__PURE__ */ jsx66("i", { className: "ph ph-plugs", "aria-hidden": "true" }) }),
8580
- /* @__PURE__ */ jsx66("h3", { className: "fdc-dead-title", children: ctx.deadTitle || "The assistant isn\u2019t reachable" }),
8581
- /* @__PURE__ */ jsx66("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." }),
8582
- ctx.onReconnect ? /* @__PURE__ */ jsxs61("button", { type: "button", className: "fd-btn fd-btn-secondary fd-btn-sm", onClick: ctx.onReconnect, children: [
8583
- /* @__PURE__ */ jsx66("i", { className: "ph ph-arrow-clockwise", "aria-hidden": "true" }),
8818
+ return /* @__PURE__ */ jsxs64("div", { className: ["fdc-scroll", className].filter(Boolean).join(" "), ref: scroller, onScroll, children: [
8819
+ /* @__PURE__ */ jsxs64("div", { className: "fdc-log", role: "log", "aria-label": "Conversation", children: [
8820
+ status === "loading" || status === "resolving" ? /* @__PURE__ */ jsx69(LoadingTurns, {}) : null,
8821
+ status === "disconnected" ? /* @__PURE__ */ jsxs64("div", { className: "fdc-dead", children: [
8822
+ /* @__PURE__ */ jsx69("span", { className: "fdc-dead-icon", children: /* @__PURE__ */ jsx69("i", { className: "ph ph-plugs", "aria-hidden": "true" }) }),
8823
+ /* @__PURE__ */ jsx69("h3", { className: "fdc-dead-title", children: ctx.deadTitle || "The assistant isn\u2019t reachable" }),
8824
+ /* @__PURE__ */ jsx69("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." }),
8825
+ ctx.onReconnect ? /* @__PURE__ */ jsxs64("button", { type: "button", className: "fd-btn fd-btn-secondary fd-btn-sm", onClick: ctx.onReconnect, children: [
8826
+ /* @__PURE__ */ jsx69("i", { className: "ph ph-arrow-clockwise", "aria-hidden": "true" }),
8584
8827
  "Try again"
8585
8828
  ] }) : null
8586
8829
  ] }) : null,
8587
- empty ? renderEmpty ? renderEmpty() : /* @__PURE__ */ jsxs61("div", { className: "fdc-empty", children: [
8588
- /* @__PURE__ */ jsx66("span", { className: "fdc-empty-icon", children: /* @__PURE__ */ jsx66("i", { className: "ph ph-" + emptyIcon, "aria-hidden": "true" }) }),
8589
- /* @__PURE__ */ jsx66("h3", { className: "fdc-empty-title", children: emptyTitle }),
8590
- emptyDescription ? /* @__PURE__ */ jsx66("p", { className: "fdc-empty-body", children: emptyDescription }) : null,
8591
- /* @__PURE__ */ jsx66(Suggestions, { items: suggestions, onPick })
8830
+ empty ? renderEmpty ? renderEmpty() : /* @__PURE__ */ jsxs64("div", { className: "fdc-empty", children: [
8831
+ /* @__PURE__ */ jsx69("span", { className: "fdc-empty-icon", children: /* @__PURE__ */ jsx69("i", { className: "ph ph-" + emptyIcon, "aria-hidden": "true" }) }),
8832
+ /* @__PURE__ */ jsx69("h3", { className: "fdc-empty-title", children: emptyTitle }),
8833
+ emptyDescription ? /* @__PURE__ */ jsx69("p", { className: "fdc-empty-body", children: emptyDescription }) : null,
8834
+ /* @__PURE__ */ jsx69(Suggestions, { items: suggestions, onPick })
8592
8835
  ] }) : null,
8593
8836
  groups.map((g, i) => {
8594
8837
  const prev = groups[i - 1];
8595
8838
  const k = dayKey(g.messages[0].timestamp);
8596
8839
  const showDay = !!k && (!prev || dayKey(prev.messages[0].timestamp) !== k);
8597
- return /* @__PURE__ */ jsxs61(React36.Fragment, { children: [
8598
- showDay ? /* @__PURE__ */ jsx66("div", { className: "fdc-day", children: /* @__PURE__ */ jsx66("span", { children: dayLabel(k) }) }) : null,
8599
- /* @__PURE__ */ jsx66(ChatTurn, { group: g, ctx })
8840
+ return /* @__PURE__ */ jsxs64(React38.Fragment, { children: [
8841
+ showDay ? /* @__PURE__ */ jsx69("div", { className: "fdc-day", children: /* @__PURE__ */ jsx69("span", { children: dayLabel(k) }) }) : null,
8842
+ /* @__PURE__ */ jsx69(ChatTurn, { group: g, ctx })
8600
8843
  ] }, g.key || i);
8601
8844
  })
8602
8845
  ] }),
8603
- pill ? /* @__PURE__ */ jsxs61("button", { type: "button", className: "fdc-pill", onClick: () => toBottom(true), children: [
8604
- /* @__PURE__ */ jsx66("i", { className: "ph ph-arrow-down", "aria-hidden": "true" }),
8846
+ pill ? /* @__PURE__ */ jsxs64("button", { type: "button", className: "fdc-pill", onClick: () => toBottom(true), children: [
8847
+ /* @__PURE__ */ jsx69("i", { className: "ph ph-arrow-down", "aria-hidden": "true" }),
8605
8848
  pill,
8606
8849
  " new message",
8607
8850
  pill === 1 ? "" : "s"
@@ -8611,8 +8854,8 @@ function ChatTranscript({
8611
8854
  var TranscriptKit = { groupMessages };
8612
8855
 
8613
8856
  // src/components/chat/ChatComposer.tsx
8614
- import * as React37 from "react";
8615
- import { jsx as jsx67, jsxs as jsxs62 } from "react/jsx-runtime";
8857
+ import * as React39 from "react";
8858
+ import { jsx as jsx70, jsxs as jsxs65 } from "react/jsx-runtime";
8616
8859
  function ChatComposer({
8617
8860
  onSubmit,
8618
8861
  onStop,
@@ -8639,17 +8882,17 @@ function ChatComposer({
8639
8882
  onReject,
8640
8883
  onOpenAttachment
8641
8884
  }) {
8642
- const [text, setText] = React37.useState(draft || "");
8643
- const [trigger, setTrigger] = React37.useState(null);
8644
- const [mentionItems, setMentionItems] = React37.useState([]);
8645
- const [listening, setListening] = React37.useState(false);
8646
- const [notice, setNotice] = React37.useState(null);
8647
- const editor = React37.useRef(null);
8648
- const wrap = React37.useRef(null);
8649
- const stopVoice = React37.useRef(null);
8885
+ const [text, setText] = React39.useState(draft || "");
8886
+ const [trigger, setTrigger] = React39.useState(null);
8887
+ const [mentionItems, setMentionItems] = React39.useState([]);
8888
+ const [listening, setListening] = React39.useState(false);
8889
+ const [notice, setNotice] = React39.useState(null);
8890
+ const editor = React39.useRef(null);
8891
+ const wrap = React39.useRef(null);
8892
+ const stopVoice = React39.useRef(null);
8650
8893
  const staged = useStagedFiles(fileUploadHandler, { onError: () => {
8651
8894
  } });
8652
- React37.useEffect(() => {
8895
+ React39.useEffect(() => {
8653
8896
  if (draft != null && draft !== text) setText(draft);
8654
8897
  }, [draft]);
8655
8898
  const change = (v) => {
@@ -8683,7 +8926,7 @@ function ChatComposer({
8683
8926
  e.preventDefault();
8684
8927
  staged.add(found.files);
8685
8928
  };
8686
- React37.useEffect(() => {
8929
+ React39.useEffect(() => {
8687
8930
  if (!trigger || trigger.type !== "mention" || !mentionSources) {
8688
8931
  setMentionItems([]);
8689
8932
  return;
@@ -8701,7 +8944,7 @@ function ChatComposer({
8701
8944
  const q = (trigger.query || "").toLowerCase();
8702
8945
  setMentionItems(mentionSources.filter((m) => !q || (m.label + " " + (m.description || "")).toLowerCase().includes(q)));
8703
8946
  }, [trigger, mentionSources]);
8704
- const slashItems = React37.useMemo(() => {
8947
+ const slashItems = React39.useMemo(() => {
8705
8948
  if (!trigger || trigger.type !== "slash" || !slashCommands) return [];
8706
8949
  const q = (trigger.query || "").toLowerCase();
8707
8950
  return slashCommands.filter((c) => !q || (c.id + " " + c.label + " " + (c.description || "")).toLowerCase().includes(q));
@@ -8715,7 +8958,7 @@ function ChatComposer({
8715
8958
  description: it.description,
8716
8959
  icon: it.icon,
8717
8960
  meta: mention.meta,
8718
- shortcut: slash.shortcut ? /* @__PURE__ */ jsx67(KeyHint, { keys: slash.shortcut, size: "sm" }) : void 0,
8961
+ shortcut: slash.shortcut ? /* @__PURE__ */ jsx70(KeyHint, { keys: slash.shortcut, size: "sm" }) : void 0,
8719
8962
  onSelect: () => {
8720
8963
  const insert = trigger.type === "slash" ? slash.immediate ? "/" + slash.id : "/" + slash.id + " " : "@" + (mention.value || mention.label) + " ";
8721
8964
  editor.current && editor.current.replaceRange(trigger.from, trigger.to, insert);
@@ -8778,14 +9021,14 @@ function ChatComposer({
8778
9021
  stopVoice.current = typeof res === "function" ? res : () => {
8779
9022
  };
8780
9023
  };
8781
- return /* @__PURE__ */ jsxs62("div", { className: "fdc-composer" + (disabled ? " is-disabled" : "") + (narrow ? " is-narrow" : ""), children: [
8782
- queue.length ? /* @__PURE__ */ jsx67("div", { className: "fdc-queue", "aria-label": "Queued messages", children: queue.map((q) => /* @__PURE__ */ jsxs62("div", { className: "fdc-queue-row", children: [
8783
- /* @__PURE__ */ jsx67("i", { className: "ph ph-clock-countdown", "aria-hidden": "true" }),
8784
- /* @__PURE__ */ jsx67("span", { className: "fdc-queue-text", children: q.text || (q.attachments ? q.attachments.length + " file(s)" : "") }),
8785
- onRemoveQueued ? /* @__PURE__ */ jsx67("button", { type: "button", className: "fdc-queue-x", onClick: () => onRemoveQueued(q.id), "aria-label": "Remove queued message", children: /* @__PURE__ */ jsx67("i", { className: "ph ph-x", "aria-hidden": "true" }) }) : null
9024
+ return /* @__PURE__ */ jsxs65("div", { className: "fdc-composer" + (disabled ? " is-disabled" : "") + (narrow ? " is-narrow" : ""), children: [
9025
+ queue.length ? /* @__PURE__ */ jsx70("div", { className: "fdc-queue", "aria-label": "Queued messages", children: queue.map((q) => /* @__PURE__ */ jsxs65("div", { className: "fdc-queue-row", children: [
9026
+ /* @__PURE__ */ jsx70("i", { className: "ph ph-clock-countdown", "aria-hidden": "true" }),
9027
+ /* @__PURE__ */ jsx70("span", { className: "fdc-queue-text", children: q.text || (q.attachments ? q.attachments.length + " file(s)" : "") }),
9028
+ onRemoveQueued ? /* @__PURE__ */ jsx70("button", { type: "button", className: "fdc-queue-x", onClick: () => onRemoveQueued(q.id), "aria-label": "Remove queued message", children: /* @__PURE__ */ jsx70("i", { className: "ph ph-x", "aria-hidden": "true" }) }) : null
8786
9029
  ] }, q.id)) }) : null,
8787
9030
  sessionBar,
8788
- /* @__PURE__ */ jsx67(
9031
+ /* @__PURE__ */ jsx70(
8789
9032
  Dropzone,
8790
9033
  {
8791
9034
  className: "fdc-field",
@@ -8799,9 +9042,9 @@ function ChatComposer({
8799
9042
  disabled: !fileUploadHandler || disabled,
8800
9043
  label: "Drop to attach",
8801
9044
  hint: acceptFiles ? acceptFiles.replace(/,/g, " \xB7 ") : void 0,
8802
- children: /* @__PURE__ */ jsxs62("div", { ref: wrap, className: "fdc-field-inner", children: [
8803
- staged.items.length ? /* @__PURE__ */ jsx67("div", { className: "fdc-staged", children: /* @__PURE__ */ jsx67(FileStrip, { files: staged.items, size: narrow ? 60 : 68, onRemove: staged.remove, onRetry: staged.retry, onOpen: onOpenAttachment }) }) : null,
8804
- /* @__PURE__ */ jsx67(
9045
+ children: /* @__PURE__ */ jsxs65("div", { ref: wrap, className: "fdc-field-inner", children: [
9046
+ staged.items.length ? /* @__PURE__ */ jsx70("div", { className: "fdc-staged", children: /* @__PURE__ */ jsx70(FileStrip, { files: staged.items, size: narrow ? 60 : 68, onRemove: staged.remove, onRetry: staged.retry, onOpen: onOpenAttachment }) }) : null,
9047
+ /* @__PURE__ */ jsx70(
8805
9048
  MarkdownEditor,
8806
9049
  {
8807
9050
  ref: editor,
@@ -8820,33 +9063,33 @@ function ChatComposer({
8820
9063
  ariaLabel: "Message"
8821
9064
  }
8822
9065
  ),
8823
- /* @__PURE__ */ jsxs62("div", { className: "fdc-tools", children: [
8824
- fileUploadHandler ? /* @__PURE__ */ jsx67(FilePickButton, { onFiles: staged.add, onReject: (r) => flash(r[0].message), accept: acceptFiles, maxFileSize, label: "Attach files", icon: "plus" }) : null,
8825
- voiceHandler ? /* @__PURE__ */ jsx67("button", { type: "button", className: "fd-attachbtn" + (listening ? " is-live" : ""), onClick: voice, "aria-pressed": listening, "aria-label": listening ? "Stop dictation" : "Dictate", children: /* @__PURE__ */ jsx67("i", { className: "ph ph-" + (listening ? "waveform" : "microphone"), "aria-hidden": "true" }) }) : null,
9066
+ /* @__PURE__ */ jsxs65("div", { className: "fdc-tools", children: [
9067
+ fileUploadHandler ? /* @__PURE__ */ jsx70(FilePickButton, { onFiles: staged.add, onReject: (r) => flash(r[0].message), accept: acceptFiles, maxFileSize, label: "Attach files", icon: "plus" }) : null,
9068
+ voiceHandler ? /* @__PURE__ */ jsx70("button", { type: "button", className: "fd-attachbtn" + (listening ? " is-live" : ""), onClick: voice, "aria-pressed": listening, "aria-label": listening ? "Stop dictation" : "Dictate", children: /* @__PURE__ */ jsx70("i", { className: "ph ph-" + (listening ? "waveform" : "microphone"), "aria-hidden": "true" }) }) : null,
8826
9069
  toolbarExtras,
8827
- /* @__PURE__ */ jsx67("span", { className: "fdc-tools-gap" }),
8828
- maxLength && text.length > maxLength * 0.6 ? /* @__PURE__ */ jsxs62("span", { className: "fdc-count fd-tabular" + (text.length > maxLength * 0.95 ? " is-hot" : ""), children: [
9070
+ /* @__PURE__ */ jsx70("span", { className: "fdc-tools-gap" }),
9071
+ maxLength && text.length > maxLength * 0.6 ? /* @__PURE__ */ jsxs65("span", { className: "fdc-count fd-tabular" + (text.length > maxLength * 0.95 ? " is-hot" : ""), children: [
8829
9072
  text.length,
8830
9073
  "/",
8831
9074
  maxLength
8832
9075
  ] }) : null,
8833
- busy ? /* @__PURE__ */ jsxs62("button", { type: "button", className: "fdc-stop", onClick: onStop, "aria-label": "Stop generating", children: [
8834
- /* @__PURE__ */ jsx67("i", { className: "ph ph-stop-circle", "aria-hidden": "true" }),
8835
- /* @__PURE__ */ jsx67("span", { children: "Stop" })
8836
- ] }) : /* @__PURE__ */ jsxs62("button", { type: "button", className: "fdc-send", onClick: submit, disabled: !canSend, "aria-label": "Send message", children: [
8837
- /* @__PURE__ */ jsx67("i", { className: "ph ph-paper-plane-right", "aria-hidden": "true" }),
8838
- /* @__PURE__ */ jsx67("span", { className: "fdc-send-label", children: "Send" })
9076
+ busy ? /* @__PURE__ */ jsxs65("button", { type: "button", className: "fdc-stop", onClick: onStop, "aria-label": "Stop generating", children: [
9077
+ /* @__PURE__ */ jsx70("i", { className: "ph ph-stop-circle", "aria-hidden": "true" }),
9078
+ /* @__PURE__ */ jsx70("span", { children: "Stop" })
9079
+ ] }) : /* @__PURE__ */ jsxs65("button", { type: "button", className: "fdc-send", onClick: submit, disabled: !canSend, "aria-label": "Send message", children: [
9080
+ /* @__PURE__ */ jsx70("i", { className: "ph ph-paper-plane-right", "aria-hidden": "true" }),
9081
+ /* @__PURE__ */ jsx70("span", { className: "fdc-send-label", children: "Send" })
8839
9082
  ] })
8840
9083
  ] })
8841
9084
  ] })
8842
9085
  }
8843
9086
  ),
8844
- notice ? /* @__PURE__ */ jsxs62("div", { className: "fdc-notice", role: "status", children: [
8845
- /* @__PURE__ */ jsx67("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
9087
+ notice ? /* @__PURE__ */ jsxs65("div", { className: "fdc-notice", role: "status", children: [
9088
+ /* @__PURE__ */ jsx70("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
8846
9089
  notice
8847
9090
  ] }) : null,
8848
- hint && !notice ? /* @__PURE__ */ jsx67("div", { className: "fdc-hint", children: hint }) : null,
8849
- /* @__PURE__ */ jsx67(
9091
+ hint && !notice ? /* @__PURE__ */ jsx70("div", { className: "fdc-hint", children: hint }) : null,
9092
+ /* @__PURE__ */ jsx70(
8850
9093
  Popover,
8851
9094
  {
8852
9095
  open: menuOpen,
@@ -8860,12 +9103,12 @@ function ChatComposer({
8860
9103
  returnFocus: false,
8861
9104
  closeOnOutside: true,
8862
9105
  label: trigger && trigger.type === "slash" ? "Commands" : "Mentions",
8863
- children: /* @__PURE__ */ jsx67(
9106
+ children: /* @__PURE__ */ jsx70(
8864
9107
  Menu,
8865
9108
  {
8866
9109
  items: menuItems,
8867
9110
  autoFocus: false,
8868
- header: /* @__PURE__ */ jsx67("div", { className: "fd-pop-group", children: trigger && trigger.type === "slash" ? "Commands" : "Attach context" }),
9111
+ header: /* @__PURE__ */ jsx70("div", { className: "fd-pop-group", children: trigger && trigger.type === "slash" ? "Commands" : "Attach context" }),
8869
9112
  onClose: () => setTrigger(null)
8870
9113
  }
8871
9114
  )
@@ -8875,12 +9118,12 @@ function ChatComposer({
8875
9118
  }
8876
9119
 
8877
9120
  // src/components/chat/ChatSessionBar.tsx
8878
- import * as React38 from "react";
8879
- import { jsx as jsx68, jsxs as jsxs63 } from "react/jsx-runtime";
9121
+ import * as React40 from "react";
9122
+ import { jsx as jsx71, jsxs as jsxs66 } from "react/jsx-runtime";
8880
9123
  var compact2 = meterFormats.compact;
8881
9124
  function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extras }) {
8882
- const [open, setOpen] = React38.useState(false);
8883
- const anchor = React38.useRef(null);
9125
+ const [open, setOpen] = React40.useState(false);
9126
+ const anchor = React40.useRef(null);
8884
9127
  const stats = sessionStats || null;
8885
9128
  const cu = contextUsage || null;
8886
9129
  const limits = usageLimits || null;
@@ -8895,9 +9138,9 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
8895
9138
  if (stats && stats.runningTasks) bits.push(stats.runningTasks + " running task" + (stats.runningTasks === 1 ? "" : "s"));
8896
9139
  if (cu) bits.push(pct + "% context");
8897
9140
  const expandable = !!(cu || limits);
8898
- return /* @__PURE__ */ jsxs63(React38.Fragment, { children: [
8899
- /* @__PURE__ */ jsxs63("div", { className: "fdc-bar", children: [
8900
- /* @__PURE__ */ jsxs63(
9141
+ return /* @__PURE__ */ jsxs66(React40.Fragment, { children: [
9142
+ /* @__PURE__ */ jsxs66("div", { className: "fdc-bar", children: [
9143
+ /* @__PURE__ */ jsxs66(
8901
9144
  "button",
8902
9145
  {
8903
9146
  type: "button",
@@ -8908,16 +9151,16 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
8908
9151
  "aria-expanded": expandable ? open : void 0,
8909
9152
  "aria-label": expandable ? "Usage details" : void 0,
8910
9153
  children: [
8911
- cu ? /* @__PURE__ */ jsx68("span", { className: "fdc-bar-mini", "aria-hidden": "true", children: /* @__PURE__ */ jsx68(SegmentedMeter, { total, segments: cu.segments, height: 4, showTotal: false }) }) : null,
8912
- /* @__PURE__ */ jsx68("span", { className: "fdc-bar-text", children: bits.join(" \xB7 ") }),
8913
- expandable ? /* @__PURE__ */ jsx68("i", { className: "ph ph-caret-right fdc-bar-caret", "aria-hidden": "true" }) : null
9154
+ cu ? /* @__PURE__ */ jsx71("span", { className: "fdc-bar-mini", "aria-hidden": "true", children: /* @__PURE__ */ jsx71(SegmentedMeter, { total, segments: cu.segments, height: 4, showTotal: false }) }) : null,
9155
+ /* @__PURE__ */ jsx71("span", { className: "fdc-bar-text", children: bits.join(" \xB7 ") }),
9156
+ expandable ? /* @__PURE__ */ jsx71("i", { className: "ph ph-caret-right fdc-bar-caret", "aria-hidden": "true" }) : null
8914
9157
  ]
8915
9158
  }
8916
9159
  ),
8917
9160
  extras
8918
9161
  ] }),
8919
- /* @__PURE__ */ jsx68(Popover, { open, anchorRef: anchor, placement: "top-start", onClose: () => setOpen(false), minWidth: 330, maxHeight: 460, padded: true, label: "Usage", children: /* @__PURE__ */ jsxs63("div", { className: "fdc-usage", children: [
8920
- cu ? /* @__PURE__ */ jsx68("section", { className: "fdc-usage-sec", children: /* @__PURE__ */ jsx68(
9162
+ /* @__PURE__ */ jsx71(Popover, { open, anchorRef: anchor, placement: "top-start", onClose: () => setOpen(false), minWidth: 330, maxHeight: 460, padded: true, label: "Usage", children: /* @__PURE__ */ jsxs66("div", { className: "fdc-usage", children: [
9163
+ cu ? /* @__PURE__ */ jsx71("section", { className: "fdc-usage-sec", children: /* @__PURE__ */ jsx71(
8921
9164
  SegmentedMeter,
8922
9165
  {
8923
9166
  total,
@@ -8929,9 +9172,9 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
8929
9172
  remainderLabel: "Free"
8930
9173
  }
8931
9174
  ) }) : null,
8932
- limits && limits.length ? /* @__PURE__ */ jsxs63("section", { className: "fdc-usage-sec", children: [
8933
- /* @__PURE__ */ jsx68("h4", { className: "fdc-usage-h", children: "Usage limits" }),
8934
- /* @__PURE__ */ jsx68("div", { className: "fdc-usage-rows", children: limits.map((l) => /* @__PURE__ */ jsx68(
9175
+ limits && limits.length ? /* @__PURE__ */ jsxs66("section", { className: "fdc-usage-sec", children: [
9176
+ /* @__PURE__ */ jsx71("h4", { className: "fdc-usage-h", children: "Usage limits" }),
9177
+ /* @__PURE__ */ jsx71("div", { className: "fdc-usage-rows", children: limits.map((l) => /* @__PURE__ */ jsx71(
8935
9178
  QuotaRow,
8936
9179
  {
8937
9180
  label: l.label,
@@ -8941,32 +9184,32 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
8941
9184
  l.id
8942
9185
  )) })
8943
9186
  ] }) : null,
8944
- stats ? /* @__PURE__ */ jsxs63("section", { className: "fdc-usage-sec fdc-usage-stats", children: [
8945
- stats.elapsedMs ? /* @__PURE__ */ jsxs63("div", { children: [
8946
- /* @__PURE__ */ jsx68("span", { children: "Session" }),
8947
- /* @__PURE__ */ jsx68("b", { className: "fd-tabular", children: formatDuration(stats.elapsedMs) })
9187
+ stats ? /* @__PURE__ */ jsxs66("section", { className: "fdc-usage-sec fdc-usage-stats", children: [
9188
+ stats.elapsedMs ? /* @__PURE__ */ jsxs66("div", { children: [
9189
+ /* @__PURE__ */ jsx71("span", { children: "Session" }),
9190
+ /* @__PURE__ */ jsx71("b", { className: "fd-tabular", children: formatDuration(stats.elapsedMs) })
8948
9191
  ] }) : null,
8949
- stats.tokens ? /* @__PURE__ */ jsxs63("div", { children: [
8950
- /* @__PURE__ */ jsx68("span", { children: "Tokens" }),
8951
- /* @__PURE__ */ jsx68("b", { className: "fd-tabular", children: stats.tokens.toLocaleString() })
9192
+ stats.tokens ? /* @__PURE__ */ jsxs66("div", { children: [
9193
+ /* @__PURE__ */ jsx71("span", { children: "Tokens" }),
9194
+ /* @__PURE__ */ jsx71("b", { className: "fd-tabular", children: stats.tokens.toLocaleString() })
8952
9195
  ] }) : null,
8953
- stats.costUsd != null ? /* @__PURE__ */ jsxs63("div", { children: [
8954
- /* @__PURE__ */ jsx68("span", { children: "Cost" }),
8955
- /* @__PURE__ */ jsxs63("b", { className: "fd-tabular", children: [
9196
+ stats.costUsd != null ? /* @__PURE__ */ jsxs66("div", { children: [
9197
+ /* @__PURE__ */ jsx71("span", { children: "Cost" }),
9198
+ /* @__PURE__ */ jsxs66("b", { className: "fd-tabular", children: [
8956
9199
  "$",
8957
9200
  Number(stats.costUsd).toFixed(3)
8958
9201
  ] })
8959
9202
  ] }) : null,
8960
- stats.turns ? /* @__PURE__ */ jsxs63("div", { children: [
8961
- /* @__PURE__ */ jsx68("span", { children: "Turns" }),
8962
- /* @__PURE__ */ jsx68("b", { className: "fd-tabular", children: stats.turns })
9203
+ stats.turns ? /* @__PURE__ */ jsxs66("div", { children: [
9204
+ /* @__PURE__ */ jsx71("span", { children: "Turns" }),
9205
+ /* @__PURE__ */ jsx71("b", { className: "fd-tabular", children: stats.turns })
8963
9206
  ] }) : null
8964
9207
  ] }) : null,
8965
- onClear ? /* @__PURE__ */ jsx68("footer", { className: "fdc-usage-foot", children: /* @__PURE__ */ jsxs63("button", { type: "button", className: "fdc-usage-clear", onClick: () => {
9208
+ onClear ? /* @__PURE__ */ jsx71("footer", { className: "fdc-usage-foot", children: /* @__PURE__ */ jsxs66("button", { type: "button", className: "fdc-usage-clear", onClick: () => {
8966
9209
  setOpen(false);
8967
9210
  onClear();
8968
9211
  }, children: [
8969
- /* @__PURE__ */ jsx68("i", { className: "ph ph-trash", "aria-hidden": "true" }),
9212
+ /* @__PURE__ */ jsx71("i", { className: "ph ph-trash", "aria-hidden": "true" }),
8970
9213
  "Clear conversation"
8971
9214
  ] }) }) : null
8972
9215
  ] }) })
@@ -9003,7 +9246,7 @@ function ModelControls({
9003
9246
  disabled: m.disabled,
9004
9247
  checked: m.id === (current2 && current2.id),
9005
9248
  meta: m.meta,
9006
- shortcut: m.shortcut ? /* @__PURE__ */ jsx68(KeyHint, { keys: m.shortcut, size: "sm" }) : void 0,
9249
+ shortcut: m.shortcut ? /* @__PURE__ */ jsx71(KeyHint, { keys: m.shortcut, size: "sm" }) : void 0,
9007
9250
  onSelect: () => onModelChange && onModelChange(m.id)
9008
9251
  });
9009
9252
  const items = [{ kind: "section", label: "Models" }].concat(flat.map(item));
@@ -9016,15 +9259,15 @@ function ModelControls({
9016
9259
  items.push({ kind: "section", label: "Fast mode" });
9017
9260
  items.push({
9018
9261
  kind: "custom",
9019
- render: () => /* @__PURE__ */ jsxs63("label", { className: "fdc-switchrow", children: [
9020
- /* @__PURE__ */ jsx68("span", { children: fastModeLabel }),
9021
- /* @__PURE__ */ jsx68("input", { type: "checkbox", className: "fd-sr", checked: !!fastMode, onChange: (e) => onFastModeChange(e.target.checked) }),
9022
- /* @__PURE__ */ jsx68("span", { className: "fd-switch-track" + (fastMode ? " is-on" : ""), "aria-hidden": "true", children: /* @__PURE__ */ jsx68("span", { className: "fd-switch-thumb" }) })
9262
+ render: () => /* @__PURE__ */ jsxs66("label", { className: "fdc-switchrow", children: [
9263
+ /* @__PURE__ */ jsx71("span", { children: fastModeLabel }),
9264
+ /* @__PURE__ */ jsx71("input", { type: "checkbox", className: "fd-sr", checked: !!fastMode, onChange: (e) => onFastModeChange(e.target.checked) }),
9265
+ /* @__PURE__ */ jsx71("span", { className: "fd-switch-track" + (fastMode ? " is-on" : ""), "aria-hidden": "true", children: /* @__PURE__ */ jsx71("span", { className: "fd-switch-thumb" }) })
9023
9266
  ] })
9024
9267
  });
9025
9268
  }
9026
- return /* @__PURE__ */ jsxs63(React38.Fragment, { children: [
9027
- /* @__PURE__ */ jsx68(
9269
+ return /* @__PURE__ */ jsxs66(React40.Fragment, { children: [
9270
+ /* @__PURE__ */ jsx71(
9028
9271
  MenuButton,
9029
9272
  {
9030
9273
  items,
@@ -9035,7 +9278,7 @@ function ModelControls({
9035
9278
  title: "Choose a model"
9036
9279
  }
9037
9280
  ),
9038
- effortLevels && effortLevels.length ? /* @__PURE__ */ jsx68(
9281
+ effortLevels && effortLevels.length ? /* @__PURE__ */ jsx71(
9039
9282
  MenuButton,
9040
9283
  {
9041
9284
  placement: "top-end",
@@ -9056,7 +9299,7 @@ function ModelControls({
9056
9299
  }
9057
9300
 
9058
9301
  // src/components/chat/AgentChatPanel.tsx
9059
- import { jsx as jsx69, jsxs as jsxs64 } from "react/jsx-runtime";
9302
+ import { jsx as jsx72, jsxs as jsxs67 } from "react/jsx-runtime";
9060
9303
  var SURFACES = { sidebar: "is-sidebar", inline: "is-inline", page: "is-page", modal: "is-modal", sheet: "is-sheet" };
9061
9304
  function AgentChatPanel({
9062
9305
  /* required */
@@ -9140,11 +9383,11 @@ function AgentChatPanel({
9140
9383
  onFeedback,
9141
9384
  onEditMessage
9142
9385
  }) {
9143
- const [panelWidth, setPanelWidth] = React39.useState(width);
9144
- const [applied, setApplied] = React39.useState({});
9145
- const [draft, setDraft] = React39.useState("");
9146
- const dragging = React39.useRef(null);
9147
- React39.useEffect(() => setPanelWidth(width), [width]);
9386
+ const [panelWidth, setPanelWidth] = React41.useState(width);
9387
+ const [applied, setApplied] = React41.useState({});
9388
+ const [draft, setDraft] = React41.useState("");
9389
+ const dragging = React41.useRef(null);
9390
+ React41.useEffect(() => setPanelWidth(width), [width]);
9148
9391
  const engine = useChatEngine({
9149
9392
  contextType,
9150
9393
  contextId,
@@ -9210,7 +9453,7 @@ function AgentChatPanel({
9210
9453
  onReconnect: engine.reload,
9211
9454
  deadTitle: "The assistant isn\u2019t reachable"
9212
9455
  };
9213
- const sessionBar = /* @__PURE__ */ jsx69(
9456
+ const sessionBar = /* @__PURE__ */ jsx72(
9214
9457
  ChatSessionBar,
9215
9458
  {
9216
9459
  sessionStats,
@@ -9219,7 +9462,7 @@ function AgentChatPanel({
9219
9462
  onClear: engine.visible.length ? engine.clear : void 0
9220
9463
  }
9221
9464
  );
9222
- const modelControls = /* @__PURE__ */ jsx69(
9465
+ const modelControls = /* @__PURE__ */ jsx72(
9223
9466
  ModelControls,
9224
9467
  {
9225
9468
  models,
@@ -9234,7 +9477,7 @@ function AgentChatPanel({
9234
9477
  narrow
9235
9478
  }
9236
9479
  );
9237
- const threadMenu = threads && threads.length ? /* @__PURE__ */ jsx69(
9480
+ const threadMenu = threads && threads.length ? /* @__PURE__ */ jsx72(
9238
9481
  MenuButton,
9239
9482
  {
9240
9483
  variant: "ghost",
@@ -9261,7 +9504,7 @@ function AgentChatPanel({
9261
9504
  })))
9262
9505
  }
9263
9506
  ) : null;
9264
- return /* @__PURE__ */ jsxs64(
9507
+ return /* @__PURE__ */ jsxs67(
9265
9508
  "aside",
9266
9509
  {
9267
9510
  className: ["fdc-panel", SURFACES[surface] || SURFACES.sidebar, narrow ? "is-narrow" : "", className].filter(Boolean).join(" "),
@@ -9272,7 +9515,7 @@ function AgentChatPanel({
9272
9515
  },
9273
9516
  "aria-label": title,
9274
9517
  children: [
9275
- surface === "sidebar" && resizable ? /* @__PURE__ */ jsx69(
9518
+ surface === "sidebar" && resizable ? /* @__PURE__ */ jsx72(
9276
9519
  "div",
9277
9520
  {
9278
9521
  className: "fdc-grip",
@@ -9287,20 +9530,20 @@ function AgentChatPanel({
9287
9530
  }
9288
9531
  }
9289
9532
  ) : null,
9290
- showHeader ? /* @__PURE__ */ jsxs64("header", { className: "fdc-head", children: [
9291
- /* @__PURE__ */ jsx69("span", { className: "fdc-head-mark", "aria-hidden": "true", children: /* @__PURE__ */ jsx69("i", { className: "ph ph-" + assistantIcon }) }),
9292
- /* @__PURE__ */ jsxs64("span", { className: "fdc-head-titles", children: [
9293
- /* @__PURE__ */ jsx69("span", { className: "fdc-head-title", children: title }),
9294
- subtitle ? /* @__PURE__ */ jsx69("span", { className: "fdc-head-sub", children: subtitle }) : null
9533
+ showHeader ? /* @__PURE__ */ jsxs67("header", { className: "fdc-head", children: [
9534
+ /* @__PURE__ */ jsx72("span", { className: "fdc-head-mark", "aria-hidden": "true", children: /* @__PURE__ */ jsx72("i", { className: "ph ph-" + assistantIcon }) }),
9535
+ /* @__PURE__ */ jsxs67("span", { className: "fdc-head-titles", children: [
9536
+ /* @__PURE__ */ jsx72("span", { className: "fdc-head-title", children: title }),
9537
+ subtitle ? /* @__PURE__ */ jsx72("span", { className: "fdc-head-sub", children: subtitle }) : null
9295
9538
  ] }),
9296
- /* @__PURE__ */ jsxs64("span", { className: "fdc-head-acts", children: [
9539
+ /* @__PURE__ */ jsxs67("span", { className: "fdc-head-acts", children: [
9297
9540
  headerActions,
9298
9541
  threadMenu,
9299
- onNewThread ? /* @__PURE__ */ jsx69("button", { type: "button", className: "fdc-iconbtn", onClick: onNewThread, "aria-label": "New conversation", title: "New conversation", children: /* @__PURE__ */ jsx69("i", { className: "ph ph-plus", "aria-hidden": "true" }) }) : null,
9300
- onClose ? /* @__PURE__ */ jsx69("button", { type: "button", className: "fdc-iconbtn", onClick: onClose, "aria-label": "Close panel", title: "Close", children: /* @__PURE__ */ jsx69("i", { className: "ph ph-x", "aria-hidden": "true" }) }) : null
9542
+ onNewThread ? /* @__PURE__ */ jsx72("button", { type: "button", className: "fdc-iconbtn", onClick: onNewThread, "aria-label": "New conversation", title: "New conversation", children: /* @__PURE__ */ jsx72("i", { className: "ph ph-plus", "aria-hidden": "true" }) }) : null,
9543
+ onClose ? /* @__PURE__ */ jsx72("button", { type: "button", className: "fdc-iconbtn", onClick: onClose, "aria-label": "Close panel", title: "Close", children: /* @__PURE__ */ jsx72("i", { className: "ph ph-x", "aria-hidden": "true" }) }) : null
9301
9544
  ] })
9302
9545
  ] }) : null,
9303
- /* @__PURE__ */ jsx69(
9546
+ /* @__PURE__ */ jsx72(
9304
9547
  ChatTranscript,
9305
9548
  {
9306
9549
  messages: engine.visible,
@@ -9315,7 +9558,7 @@ function AgentChatPanel({
9315
9558
  renderEmpty
9316
9559
  }
9317
9560
  ),
9318
- /* @__PURE__ */ jsx69(
9561
+ /* @__PURE__ */ jsx72(
9319
9562
  ChatComposer,
9320
9563
  {
9321
9564
  onSubmit: (text, atts) => engine.send(text, atts),
@@ -9348,7 +9591,7 @@ function AgentChatPanel({
9348
9591
  }
9349
9592
 
9350
9593
  // src/kits/query.ts
9351
- import * as React40 from "react";
9594
+ import * as React42 from "react";
9352
9595
  function eqFilter(get2) {
9353
9596
  return (row, value) => Array.isArray(value) ? value.includes(get2(row)) : get2(row) === value;
9354
9597
  }
@@ -9380,22 +9623,22 @@ function compare(a, b, dir) {
9380
9623
  var API = null;
9381
9624
  var PREFS = null;
9382
9625
  function useServerTable({ endpoint, params, defaults, deps, prefsKey }) {
9383
- const [query, setQuery] = React40.useState(() => {
9626
+ const [query, setQuery] = React42.useState(() => {
9384
9627
  const store = PREFS || window.PlannerPrefs;
9385
9628
  const saved = prefsKey && store ? store.getTable(prefsKey) : {};
9386
9629
  return { ...DEFAULTS, ...defaults || {}, ...saved.pageSize ? { pageSize: saved.pageSize } : {}, ...saved.sort ? { sort: saved.sort, dir: saved.dir || "desc" } : {} };
9387
9630
  });
9388
- const savePref = React40.useCallback((patch2) => {
9631
+ const savePref = React42.useCallback((patch2) => {
9389
9632
  const store = PREFS || window.PlannerPrefs;
9390
9633
  if (prefsKey && store) store.setTable(prefsKey, patch2);
9391
9634
  }, [prefsKey]);
9392
- const [res, setRes] = React40.useState(null);
9393
- const [loading, setLoading] = React40.useState(true);
9394
- const seq2 = React40.useRef(0);
9635
+ const [res, setRes] = React42.useState(null);
9636
+ const [loading, setLoading] = React42.useState(true);
9637
+ const seq2 = React42.useRef(0);
9395
9638
  const depKey = (deps || []).join("|");
9396
9639
  const paramKey = JSON.stringify(params || {});
9397
9640
  const queryKey = JSON.stringify(query);
9398
- React40.useEffect(() => {
9641
+ React42.useEffect(() => {
9399
9642
  const id = ++seq2.current;
9400
9643
  setLoading(true);
9401
9644
  const t = setTimeout(() => {
@@ -9733,6 +9976,7 @@ export {
9733
9976
  Dropzone,
9734
9977
  DropzoneKit,
9735
9978
  EmptyState,
9979
+ EntityRow,
9736
9980
  FeatureGate,
9737
9981
  FileChip,
9738
9982
  FileGrid,
@@ -9805,11 +10049,16 @@ export {
9805
10049
  Tooltip,
9806
10050
  Topbar,
9807
10051
  TranscriptKit,
10052
+ TransferList,
9808
10053
  UseFeatureStatus,
9809
10054
  UseRuntimeMode,
10055
+ VIRTUAL_LIST_BUFFER_ROWS,
10056
+ VirtualList,
9810
10057
  acceptMatches,
9811
10058
  anyOfFilter,
9812
10059
  channelWeightOf,
10060
+ computeNeedMore,
10061
+ computeVirtualWindow,
9813
10062
  createVersionStore,
9814
10063
  eqFilter,
9815
10064
  extensionOf,