@flytedan/flytebot-design-system 0.6.1 → 0.7.0

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