@flytedan/flytebot-design-system 0.48.1 → 0.49.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -66,6 +66,7 @@ __export(index_exports, {
66
66
  Clamp: () => Clamp,
67
67
  ClockFace: () => ClockFace,
68
68
  CodeBlock: () => CodeBlock,
69
+ CodeEditor: () => CodeEditor,
69
70
  Collapsible: () => Collapsible,
70
71
  ComingSoon: () => ComingSoon,
71
72
  CsiBadge: () => CsiBadge,
@@ -111,6 +112,7 @@ __export(index_exports, {
111
112
  JobTray: () => JobTray,
112
113
  Json: () => Json,
113
114
  KeyHint: () => KeyHint,
115
+ LAYER_STEP: () => LAYER_STEP,
114
116
  LoadingRegion: () => LoadingRegion,
115
117
  Markdown: () => Markdown,
116
118
  MarkdownEditor: () => MarkdownEditor,
@@ -125,6 +127,7 @@ __export(index_exports, {
125
127
  ModeSwitch: () => ModeSwitch,
126
128
  ModelControls: () => ModelControls,
127
129
  NumberInput: () => NumberInput,
130
+ OVERLAY_CEILING: () => OVERLAY_CEILING,
128
131
  POPOVER_BODY_MIN: () => POPOVER_BODY_MIN,
129
132
  PacketCard: () => PacketCard,
130
133
  Pagination: () => Pagination,
@@ -137,6 +140,7 @@ __export(index_exports, {
137
140
  ProgressBar: () => ProgressBar,
138
141
  QueryKit: () => QueryKit,
139
142
  QuotaRow: () => QuotaRow,
143
+ ROOT_STEP: () => ROOT_STEP,
140
144
  Radio: () => Radio,
141
145
  RangeSlider: () => RangeSlider,
142
146
  RelativeTime: () => RelativeTime,
@@ -181,6 +185,7 @@ __export(index_exports, {
181
185
  VIRTUAL_LIST_BUFFER_ROWS: () => VIRTUAL_LIST_BUFFER_ROWS,
182
186
  VIRTUAL_LIST_ROW_GAP: () => VIRTUAL_LIST_ROW_GAP,
183
187
  VirtualList: () => VirtualList,
188
+ __resetLayerStackForTests: () => __resetLayerStackForTests,
184
189
  acceptMatches: () => acceptMatches,
185
190
  anyOfFilter: () => anyOfFilter,
186
191
  applyPrefs: () => applyPrefs,
@@ -230,6 +235,7 @@ __export(index_exports, {
230
235
  useChatEngine: () => useChatEngine,
231
236
  useDocumentTitle: () => useDocumentTitle,
232
237
  useFeatureStatus: () => useFeatureStatus,
238
+ useLayerZIndex: () => useLayerZIndex,
233
239
  usePopoverPosition: () => usePopoverPosition,
234
240
  useResponsiveRail: () => useResponsiveRail,
235
241
  useRuntimeMode: () => useRuntimeMode,
@@ -446,6 +452,8 @@ function open(layer) {
446
452
  layer.order = ++lastOrder;
447
453
  lastClosed = null;
448
454
  if (layer.options.trap && !contains(scopeOf(layer), document.activeElement)) focusInto(layer);
455
+ zIndexVersion++;
456
+ notifyZIndexListeners();
449
457
  }
450
458
  function close(layer) {
451
459
  openLayers.delete(layer);
@@ -456,7 +464,53 @@ function close(layer) {
456
464
  document.removeEventListener("keydown", onKeydown);
457
465
  pendingEscape = null;
458
466
  }
467
+ zIndexVersion++;
468
+ notifyZIndexListeners();
459
469
  }
470
+ var LAYER_STEP = 10;
471
+ var ROOT_STEP = 100;
472
+ var OVERLAY_CEILING = 1e4;
473
+ var zIndexListeners = /* @__PURE__ */ new Set();
474
+ var notifyZIndexListeners = () => {
475
+ zIndexListeners.forEach((listener) => listener());
476
+ };
477
+ var subscribeZIndex = (listener) => {
478
+ zIndexListeners.add(listener);
479
+ return () => {
480
+ zIndexListeners.delete(listener);
481
+ };
482
+ };
483
+ var zIndexVersion = 0;
484
+ var getZIndexVersion = () => zIndexVersion;
485
+ function openSiblingsOf(layer) {
486
+ const siblings = [];
487
+ for (const l of openLayers) if (l.parent === layer.parent) siblings.push(l);
488
+ return siblings.sort((a, b) => a.order - b.order);
489
+ }
490
+ function computeZIndex(layer) {
491
+ const path = [];
492
+ for (let l = layer; l; l = l.parent) path.push(l);
493
+ path.reverse();
494
+ let z = 0;
495
+ for (const l of path) {
496
+ const siblings = openSiblingsOf(l);
497
+ const index = Math.max(0, siblings.indexOf(l));
498
+ z = l.parent === null ? (index + 1) * ROOT_STEP : z + LAYER_STEP + index;
499
+ }
500
+ return z;
501
+ }
502
+ function useLayerZIndex(layer) {
503
+ React2.useSyncExternalStore(subscribeZIndex, getZIndexVersion, getZIndexVersion);
504
+ const l = layer;
505
+ return l.order > 0 ? computeZIndex(l) : 0;
506
+ }
507
+ var __resetLayerStackForTests = () => {
508
+ openLayers.clear();
509
+ lastOrder = 0;
510
+ pendingEscape = null;
511
+ lastClosed = null;
512
+ notifyZIndexListeners();
513
+ };
460
514
  function returnFocus(layer) {
461
515
  if (layer.options.returnFocus === false) return;
462
516
  const current2 = document.activeElement;
@@ -613,50 +667,6 @@ var portal = (node) => {
613
667
  if (typeof document !== "undefined") return (0, import_react_dom.createPortal)(node, document.body);
614
668
  return node;
615
669
  };
616
- var ROOT_LAYER = 0;
617
- var LAYER_STEP = 10;
618
- var ROOT_STEP = 100;
619
- var OVERLAY_CEILING = 1e4;
620
- var LayerContext2 = React3.createContext(ROOT_LAYER);
621
- var openRootIds = [];
622
- var rootListeners = /* @__PURE__ */ new Set();
623
- var notifyRootListeners = () => {
624
- rootListeners.forEach((listener) => listener());
625
- };
626
- var subscribeRootOverlays = (listener) => {
627
- rootListeners.add(listener);
628
- return () => {
629
- rootListeners.delete(listener);
630
- };
631
- };
632
- var getRootOverlaysSnapshot = () => openRootIds;
633
- var registerRootOverlay = (id) => {
634
- if (openRootIds.includes(id)) return;
635
- openRootIds = [...openRootIds, id];
636
- notifyRootListeners();
637
- };
638
- var unregisterRootOverlay = (id) => {
639
- if (!openRootIds.includes(id)) return;
640
- openRootIds = openRootIds.filter((existing) => existing !== id);
641
- notifyRootListeners();
642
- };
643
- var useLayer = () => React3.useContext(LayerContext2);
644
- var useOverlayLayer = (isOpen) => {
645
- const parent = useLayer();
646
- const isRoot = parent === ROOT_LAYER;
647
- const id = React3.useId();
648
- const openIds = React3.useSyncExternalStore(subscribeRootOverlays, getRootOverlaysSnapshot, getRootOverlaysSnapshot);
649
- React3.useLayoutEffect(() => {
650
- if (!isRoot || !isOpen) return;
651
- registerRootOverlay(id);
652
- return () => unregisterRootOverlay(id);
653
- }, [isRoot, isOpen, id]);
654
- if (!isRoot) return parent + LAYER_STEP;
655
- if (!isOpen) return ROOT_LAYER;
656
- const index = openIds.indexOf(id);
657
- return index === -1 ? ROOT_LAYER : (index + 1) * ROOT_STEP;
658
- };
659
- var LayerProvider = ({ zIndex, children }) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(LayerContext2.Provider, { value: zIndex, children });
660
670
  function Popover({
661
671
  open: open2,
662
672
  anchorRef,
@@ -692,8 +702,8 @@ function Popover({
692
702
  onDetach: onClose,
693
703
  layerRef: ref
694
704
  });
695
- const zIndex = useOverlayLayer(!!open2);
696
705
  const layer = useStackedLayer({ active: !!open2, containerRef: ref, onEscape: closeOnEscape ? onClose : void 0, returnFocus: returnFocus2 });
706
+ const zIndex = useLayerZIndex(layer);
697
707
  React3.useEffect(() => {
698
708
  if (!open2) return;
699
709
  const away = (e) => {
@@ -709,7 +719,7 @@ function Popover({
709
719
  }, [open2, closeOnOutside, onClose, anchorRef, triggerRef, layer]);
710
720
  if (!open2 || !pos) return null;
711
721
  return portal(
712
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(LayerProvider, { zIndex, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(StackedLayerProvider, { layer, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
722
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(StackedLayerProvider, { layer, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
713
723
  "div",
714
724
  {
715
725
  ref,
@@ -752,7 +762,7 @@ function Popover({
752
762
  footer != null ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "fd-pop-footer", children: footer }) : null
753
763
  ]
754
764
  }
755
- ) }) })
765
+ ) })
756
766
  );
757
767
  }
758
768
  var isItem = (it) => !!it && it.kind !== "separator" && it.kind !== "section" && it.kind !== "custom" && !it.disabled;
@@ -1004,6 +1014,7 @@ var import_jsx_runtime6 = require("react/jsx-runtime");
1004
1014
  function AnchoredPopover({ rect, width = 620, onClose, children }) {
1005
1015
  const ref = React4.useRef(null);
1006
1016
  const layer = useStackedLayer({ active: !!rect, containerRef: ref, onEscape: onClose });
1017
+ const zIndex = useLayerZIndex(layer);
1007
1018
  const w = Math.min(width, window.innerWidth - 32);
1008
1019
  const [h, setH] = React4.useState(0);
1009
1020
  React4.useLayoutEffect(() => {
@@ -1045,7 +1056,7 @@ function AnchoredPopover({ rect, width = 620, onClose, children }) {
1045
1056
  left,
1046
1057
  top,
1047
1058
  width: w,
1048
- zIndex: 150,
1059
+ zIndex,
1049
1060
  maxHeight: `calc(100vh - ${PAD * 2}px)`,
1050
1061
  overflowY: "auto",
1051
1062
  background: "var(--surface)",
@@ -1168,7 +1179,6 @@ var React6 = __toESM(require("react"), 1);
1168
1179
  var import_react_dom3 = require("react-dom");
1169
1180
  var import_jsx_runtime9 = require("react/jsx-runtime");
1170
1181
  function Drawer({ open: open2 = true, title, onClose, footer, children, className = "", ...rest }) {
1171
- const zIndex = useOverlayLayer(open2);
1172
1182
  const asideRef = React6.useRef(null);
1173
1183
  const [closing, setClosing] = React6.useState(false);
1174
1184
  const close2 = React6.useCallback(() => {
@@ -1177,9 +1187,10 @@ function Drawer({ open: open2 = true, title, onClose, footer, children, classNam
1177
1187
  setTimeout(onClose, 210);
1178
1188
  }, [onClose]);
1179
1189
  const layer = useStackedLayer({ active: !!open2, containerRef: asideRef, trap: true, onEscape: onClose ? close2 : void 0 });
1190
+ const zIndex = useLayerZIndex(layer);
1180
1191
  if (!open2) return null;
1181
1192
  return (0, import_react_dom3.createPortal)(
1182
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(LayerProvider, { zIndex, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(StackedLayerProvider, { layer, children: [
1193
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(StackedLayerProvider, { layer, children: [
1183
1194
  /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "fd-scrim" + (closing ? " is-closing" : ""), style: { display: "block", zIndex: zIndex - LAYER_STEP }, onClick: close2 }),
1184
1195
  /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("aside", { ref: asideRef, className: ["fd-drawer", closing ? "is-closing" : "", className].filter(Boolean).join(" "), role: "dialog", "aria-modal": "true", ...rest, style: { zIndex }, children: [
1185
1196
  /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "fd-card-head", style: { flex: "none" }, children: [
@@ -1189,7 +1200,7 @@ function Drawer({ open: open2 = true, title, onClose, footer, children, classNam
1189
1200
  /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { style: { flex: "1 1 auto", minHeight: 0, overflow: "auto", padding: 20 }, children }),
1190
1201
  footer ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "fd-card-foot", style: { flex: "none" }, children: typeof footer === "function" ? footer(close2) : footer }) : null
1191
1202
  ] })
1192
- ] }) }),
1203
+ ] }),
1193
1204
  document.body
1194
1205
  );
1195
1206
  }
@@ -1201,16 +1212,16 @@ var import_jsx_runtime10 = require("react/jsx-runtime");
1201
1212
  function Modal({ open: open2 = true, title, description, onClose, footer, wide = false, children, className = "", ...rest }) {
1202
1213
  const [closing, setClosing] = React7.useState(false);
1203
1214
  const boxRef = React7.useRef(null);
1204
- const zIndex = useOverlayLayer(!!open2);
1205
1215
  const close2 = React7.useCallback(() => {
1206
1216
  if (!onClose) return;
1207
1217
  setClosing(true);
1208
1218
  setTimeout(onClose, 190);
1209
1219
  }, [onClose]);
1210
1220
  const layer = useStackedLayer({ active: !!open2, containerRef: boxRef, trap: true, onEscape: onClose ? close2 : void 0 });
1221
+ const zIndex = useLayerZIndex(layer);
1211
1222
  if (!open2) return null;
1212
1223
  return (0, import_react_dom4.createPortal)(
1213
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(LayerProvider, { zIndex, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(StackedLayerProvider, { layer, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
1224
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(StackedLayerProvider, { layer, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
1214
1225
  "div",
1215
1226
  {
1216
1227
  className: "fd-scrim" + (closing ? " is-closing" : ""),
@@ -1241,7 +1252,7 @@ function Modal({ open: open2 = true, title, description, onClose, footer, wide =
1241
1252
  }
1242
1253
  )
1243
1254
  }
1244
- ) }) }),
1255
+ ) }),
1245
1256
  document.body
1246
1257
  );
1247
1258
  }
@@ -2104,8 +2115,8 @@ function Tooltip({ label, placement = "top", children, className = "" }) {
2104
2115
  layerRef: bubbleRef,
2105
2116
  onDetach: hide
2106
2117
  });
2107
- const zIndex = useOverlayLayer(open2);
2108
- useStackedLayer({ active: open2, containerRef: bubbleRef, onEscape: hide, returnFocus: false });
2118
+ const layer = useStackedLayer({ active: open2, containerRef: bubbleRef, onEscape: hide, returnFocus: false });
2119
+ const zIndex = useLayerZIndex(layer);
2109
2120
  React14.useEffect(() => {
2110
2121
  if (!open2) return;
2111
2122
  const away = (e) => {
@@ -4885,7 +4896,7 @@ function CodeBlock({
4885
4896
  code = "",
4886
4897
  language,
4887
4898
  filename,
4888
- lineNumbers = false,
4899
+ lineNumbers: lineNumbers2 = false,
4889
4900
  wrap: wrapDefault = false,
4890
4901
  collapseAfter = 26,
4891
4902
  copyable = true,
@@ -4912,7 +4923,7 @@ function CodeBlock({
4912
4923
  ] }) : null
4913
4924
  ] }),
4914
4925
  /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("div", { className: "fd-code-body", children: [
4915
- lineNumbers ? /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("pre", { className: "fd-code-gutter", "aria-hidden": "true", children: shown.split("\n").map((_, i) => i + 1 + "\n").join("") }) : null,
4926
+ lineNumbers2 ? /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("pre", { className: "fd-code-gutter", "aria-hidden": "true", children: shown.split("\n").map((_, i) => i + 1 + "\n").join("") }) : null,
4916
4927
  /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("pre", { className: "fd-code-pre", tabIndex: 0, children: /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("code", { children: /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(Highlighted, { code: shown, lang: language }) }) })
4917
4928
  ] }),
4918
4929
  foldable ? /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("button", { type: "button", className: "fd-code-fold", onClick: () => setOpen((v) => !v), "aria-expanded": open2, children: [
@@ -5428,9 +5439,9 @@ var React31 = __toESM(require("react"), 1);
5428
5439
  var import_jsx_runtime55 = require("react/jsx-runtime");
5429
5440
  function useInlinePanel() {
5430
5441
  const [open2, setOpen] = React31.useState(false);
5431
- const zIndex = useOverlayLayer(open2);
5432
5442
  const ref = React31.useRef(null);
5433
5443
  const layer = useStackedLayer({ active: open2, containerRef: ref, onEscape: () => setOpen(false) });
5444
+ const zIndex = useLayerZIndex(layer);
5434
5445
  React31.useEffect(() => {
5435
5446
  if (!open2) return;
5436
5447
  const away = (e) => {
@@ -5442,7 +5453,7 @@ function useInlinePanel() {
5442
5453
  return { open: open2, setOpen, ref, zIndex, layer };
5443
5454
  }
5444
5455
  function InlinePanelLayers({ panel, children }) {
5445
- return /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(LayerProvider, { zIndex: panel.zIndex, children: /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(StackedLayerProvider, { layer: panel.layer, children }) });
5456
+ return /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(StackedLayerProvider, { layer: panel.layer, children });
5446
5457
  }
5447
5458
 
5448
5459
  // src/components/data/SortMenu.tsx
@@ -7495,17 +7506,254 @@ var MarkdownEditor = React42.forwardRef(function MarkdownEditor2({
7495
7506
  ] });
7496
7507
  });
7497
7508
 
7509
+ // src/components/forms/CodeEditor.tsx
7510
+ var React43 = __toESM(require("react"), 1);
7511
+ var import_view = require("@codemirror/view");
7512
+ var import_state = require("@codemirror/state");
7513
+ var import_commands = require("@codemirror/commands");
7514
+ var import_lang_sql = require("@codemirror/lang-sql");
7515
+ var import_language = require("@codemirror/language");
7516
+ var import_highlight = require("@lezer/highlight");
7517
+ var import_jsx_runtime73 = require("react/jsx-runtime");
7518
+ function clampOffset(state, line, column) {
7519
+ const total = state.doc.lines;
7520
+ const ln = state.doc.line(Math.min(Math.max(1, line), total));
7521
+ const col = Math.max(0, (column || 1) - 1);
7522
+ return Math.min(ln.from + col, ln.to);
7523
+ }
7524
+ function toCmDiagnostics(state, diags) {
7525
+ return diags.map((d) => {
7526
+ const from = clampOffset(state, d.line, d.column ?? 1);
7527
+ const endLine = d.endLine ?? d.line;
7528
+ const endColumn = d.endColumn ?? state.doc.line(Math.min(Math.max(1, endLine), state.doc.lines)).length + 1;
7529
+ let to = clampOffset(state, endLine, endColumn);
7530
+ if (to <= from) to = Math.min(from + 1, state.doc.length);
7531
+ return { from, to, severity: d.severity || "error", message: d.message, source: void 0 };
7532
+ });
7533
+ }
7534
+ var setDiagnosticsEffect = import_state.StateEffect.define();
7535
+ var diagnosticsField = import_state.StateField.define({
7536
+ create: () => [],
7537
+ update(value, tr) {
7538
+ for (const e of tr.effects) if (e.is(setDiagnosticsEffect)) return e.value;
7539
+ if (!tr.docChanged) return value;
7540
+ return value.map((d) => ({ ...d, from: tr.changes.mapPos(d.from), to: tr.changes.mapPos(d.to) }));
7541
+ }
7542
+ });
7543
+ var tokenHighlight = import_language.HighlightStyle.define([
7544
+ { tag: import_highlight.tags.keyword, class: "tok-kw" },
7545
+ { tag: import_highlight.tags.string, class: "tok-str" },
7546
+ { tag: [import_highlight.tags.number, import_highlight.tags.bool], class: "tok-num" },
7547
+ { tag: import_highlight.tags.comment, class: "tok-com" },
7548
+ { tag: [import_highlight.tags.function(import_highlight.tags.variableName), import_highlight.tags.function(import_highlight.tags.propertyName)], class: "tok-fn" },
7549
+ { tag: import_highlight.tags.typeName, class: "tok-type" },
7550
+ { tag: import_highlight.tags.propertyName, class: "tok-prop" },
7551
+ { tag: import_highlight.tags.null, class: "tok-lit" },
7552
+ { tag: [import_highlight.tags.punctuation, import_highlight.tags.paren, import_highlight.tags.bracket], class: "tok-pun" },
7553
+ { tag: import_highlight.tags.operator, class: "tok-op" }
7554
+ ]);
7555
+ var editorTheme = import_view.EditorView.theme({
7556
+ "&": {
7557
+ fontFamily: "var(--font-mono)",
7558
+ fontSize: "12.5px",
7559
+ color: "var(--text)",
7560
+ backgroundColor: "transparent",
7561
+ height: "100%"
7562
+ },
7563
+ ".cm-content": { padding: "10px 12px", caretColor: "var(--text)" },
7564
+ ".cm-scroller": { fontFamily: "var(--font-mono)", lineHeight: "1.62" },
7565
+ ".cm-gutters": {
7566
+ backgroundColor: "transparent",
7567
+ color: "var(--text-disabled)",
7568
+ border: "0",
7569
+ borderRight: "1px solid var(--chat-code-border)"
7570
+ },
7571
+ ".cm-lineNumbers .cm-gutterElement": { padding: "0 8px 0 12px" },
7572
+ ".cm-activeLine": { backgroundColor: "var(--surface-2)" },
7573
+ ".cm-activeLineGutter": { backgroundColor: "var(--surface-2)", color: "var(--text-2)" },
7574
+ "&.cm-focused": { outline: "none" },
7575
+ ".cm-cursor": { borderLeftColor: "var(--text)" },
7576
+ ".cm-selectionBackground, &.cm-focused .cm-selectionBackground": { backgroundColor: "var(--blue-100) !important" },
7577
+ ".cm-placeholder": { color: "var(--text-disabled)" },
7578
+ ".fd-cm-diag-error": { textDecoration: "underline wavy var(--danger-solid)", textUnderlineOffset: "3px" },
7579
+ ".fd-cm-diag-warning": { textDecoration: "underline wavy var(--warn-solid)", textUnderlineOffset: "3px" },
7580
+ ".fd-cm-diag-info": { textDecoration: "underline wavy var(--info-solid)", textUnderlineOffset: "3px" }
7581
+ }, { dark: false });
7582
+ function severityClass(sev) {
7583
+ return sev === "warning" ? "fd-cm-diag-warning" : sev === "info" ? "fd-cm-diag-info" : "fd-cm-diag-error";
7584
+ }
7585
+ function decorationsFromDiagnostics() {
7586
+ return import_view.EditorView.decorations.compute([diagnosticsField], (state) => {
7587
+ const diags = state.field(diagnosticsField);
7588
+ if (!diags.length) return import_view.Decoration.none;
7589
+ const marks = diags.filter((d) => d.from < d.to).sort((a, b) => a.from - b.from).map((d) => import_view.Decoration.mark({ class: severityClass(d.severity) }).range(d.from, d.to));
7590
+ return import_view.Decoration.set(marks, true);
7591
+ });
7592
+ }
7593
+ function CodeEditor({
7594
+ value,
7595
+ onChange,
7596
+ label,
7597
+ help,
7598
+ error,
7599
+ required = false,
7600
+ disabled = false,
7601
+ readOnly = false,
7602
+ placeholder: placeholderText = "",
7603
+ diagnostics = [],
7604
+ showEscapeHint = true,
7605
+ minHeight = 160,
7606
+ id,
7607
+ className = "",
7608
+ style,
7609
+ autoFocus = false
7610
+ }) {
7611
+ const fieldId = useFieldId(id);
7612
+ const descId = fieldId + "-desc";
7613
+ const liveId = fieldId + "-live";
7614
+ const hostRef = React43.useRef(null);
7615
+ const viewRef = React43.useRef(null);
7616
+ const valueRef = React43.useRef(value);
7617
+ const onChangeRef = React43.useRef(onChange);
7618
+ onChangeRef.current = onChange;
7619
+ const editableCompartment = React43.useRef(new import_state.Compartment()).current;
7620
+ const attributesCompartment = React43.useRef(new import_state.Compartment()).current;
7621
+ const errorRef = React43.useRef(error);
7622
+ errorRef.current = error;
7623
+ const diagnosticsCountRef = React43.useRef(diagnostics.length);
7624
+ diagnosticsCountRef.current = diagnostics.length;
7625
+ function contentAttributes() {
7626
+ return {
7627
+ id: fieldId,
7628
+ "aria-describedby": descId + " " + liveId,
7629
+ "aria-invalid": errorRef.current || diagnosticsCountRef.current ? "true" : "false",
7630
+ ...label ? { "aria-label": label } : {}
7631
+ };
7632
+ }
7633
+ React43.useEffect(() => {
7634
+ const host = hostRef.current;
7635
+ if (!host) return;
7636
+ const updateListener = import_view.EditorView.updateListener.of((update) => {
7637
+ if (!update.docChanged) return;
7638
+ const next = update.state.doc.toString();
7639
+ valueRef.current = next;
7640
+ onChangeRef.current && onChangeRef.current(next);
7641
+ });
7642
+ const state = import_state.EditorState.create({
7643
+ doc: value,
7644
+ extensions: [
7645
+ (0, import_view.lineNumbers)(),
7646
+ (0, import_commands.history)(),
7647
+ (0, import_view.drawSelection)(),
7648
+ (0, import_language.indentOnInput)(),
7649
+ (0, import_language.bracketMatching)(),
7650
+ (0, import_lang_sql.sql)(),
7651
+ (0, import_language.syntaxHighlighting)(tokenHighlight),
7652
+ diagnosticsField,
7653
+ decorationsFromDiagnostics(),
7654
+ editorTheme,
7655
+ (0, import_view.placeholder)(placeholderText),
7656
+ import_view.keymap.of([
7657
+ { key: "Tab", run: import_commands.indentMore, shift: import_commands.indentLess },
7658
+ ...import_commands.defaultKeymap,
7659
+ ...import_commands.historyKeymap
7660
+ ]),
7661
+ editableCompartment.of(import_view.EditorView.editable.of(!disabled)),
7662
+ import_state.EditorState.readOnly.of(readOnly),
7663
+ updateListener,
7664
+ attributesCompartment.of(import_view.EditorView.contentAttributes.of(contentAttributes()))
7665
+ ]
7666
+ });
7667
+ const view = new import_view.EditorView({ state, parent: host });
7668
+ viewRef.current = view;
7669
+ if (autoFocus) view.focus();
7670
+ return () => {
7671
+ view.destroy();
7672
+ viewRef.current = null;
7673
+ };
7674
+ }, []);
7675
+ React43.useEffect(() => {
7676
+ const view = viewRef.current;
7677
+ if (!view) return;
7678
+ const current2 = view.state.doc.toString();
7679
+ if (current2 !== value) {
7680
+ view.dispatch({ changes: { from: 0, to: current2.length, insert: value } });
7681
+ }
7682
+ valueRef.current = value;
7683
+ }, [value]);
7684
+ React43.useEffect(() => {
7685
+ const view = viewRef.current;
7686
+ if (!view) return;
7687
+ view.dispatch({ effects: editableCompartment.reconfigure(import_view.EditorView.editable.of(!disabled)) });
7688
+ }, [disabled, editableCompartment]);
7689
+ React43.useEffect(() => {
7690
+ const view = viewRef.current;
7691
+ if (!view) return;
7692
+ view.dispatch({
7693
+ effects: [
7694
+ setDiagnosticsEffect.of(toCmDiagnostics(view.state, diagnostics)),
7695
+ attributesCompartment.reconfigure(import_view.EditorView.contentAttributes.of(contentAttributes()))
7696
+ ]
7697
+ });
7698
+ }, [diagnostics, error]);
7699
+ const box = ["fd-input", "fd-code-editor", error ? "fd-input-error" : "", disabled ? "fd-input-disabled" : ""].filter(Boolean).join(" ");
7700
+ const announce = diagnostics.length ? diagnostics.length + (diagnostics.length === 1 ? " problem: " : " problems: ") + diagnostics.map((d) => "line " + d.line + (d.column ? ", column " + d.column : "") + ": " + d.message).join("; ") : "";
7701
+ return /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("div", { className: ["fd-field", className].filter(Boolean).join(" "), style, children: [
7702
+ label ? /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(FieldLabel, { htmlFor: fieldId, required, children: label }) : null,
7703
+ /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(
7704
+ "div",
7705
+ {
7706
+ className: box,
7707
+ style: { minHeight },
7708
+ children: /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(
7709
+ "div",
7710
+ {
7711
+ ref: hostRef,
7712
+ className: "fd-code-editor-host",
7713
+ style: { minHeight }
7714
+ }
7715
+ )
7716
+ }
7717
+ ),
7718
+ /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("span", { id: descId, className: "fd-sr", children: [
7719
+ help ? help + ". " : "",
7720
+ showEscapeHint ? "Tab indents. Press Escape, then Tab, to move focus out of the editor." : ""
7721
+ ] }),
7722
+ /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("div", { id: liveId, className: "fd-sr", role: "status", "aria-live": "polite", children: announce }),
7723
+ diagnostics.length ? /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("ul", { className: "fd-code-editor-diagnostics", children: diagnostics.map((d, i) => /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("li", { className: "fd-code-editor-diag is-" + (d.severity || "error"), children: [
7724
+ /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(
7725
+ "i",
7726
+ {
7727
+ className: "ph ph-" + (d.severity === "warning" ? "warning" : d.severity === "info" ? "info" : "warning-circle"),
7728
+ "aria-hidden": "true"
7729
+ }
7730
+ ),
7731
+ /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("span", { className: "fd-code-editor-diag-loc", children: [
7732
+ "Line ",
7733
+ d.line,
7734
+ d.column ? ":" + d.column : ""
7735
+ ] }),
7736
+ /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("span", { children: d.message })
7737
+ ] }, i)) }) : null,
7738
+ error ? /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("span", { className: "fd-field-error", children: [
7739
+ /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
7740
+ error
7741
+ ] }) : !diagnostics.length && help ? /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("span", { className: "fd-field-help", children: help }) : null,
7742
+ showEscapeHint ? /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("span", { className: "fd-field-help fd-code-editor-hint", children: "Tab indents. Escape, then Tab, moves focus out." }) : null
7743
+ ] });
7744
+ }
7745
+
7498
7746
  // src/components/platform/AccountMenu.tsx
7499
- var React44 = __toESM(require("react"), 1);
7747
+ var React45 = __toESM(require("react"), 1);
7500
7748
 
7501
7749
  // src/kits/sessionContext.tsx
7502
- var React43 = __toESM(require("react"), 1);
7503
- var SessionContext = React43.createContext(null);
7750
+ var React44 = __toESM(require("react"), 1);
7751
+ var SessionContext = React44.createContext(null);
7504
7752
  function SessionProvider({ value, children }) {
7505
- return React43.createElement(SessionContext.Provider, { value }, children);
7753
+ return React44.createElement(SessionContext.Provider, { value }, children);
7506
7754
  }
7507
7755
  function useSessionContext() {
7508
- const ctx = React43.useContext(SessionContext);
7756
+ const ctx = React44.useContext(SessionContext);
7509
7757
  if (!ctx) {
7510
7758
  throw new Error(
7511
7759
  "useSessionContext() was called outside a <SessionProvider>. Wrap your app root in <SessionProvider value={...}> with your real session, or \u2014 in the docs site or a demo \u2014 in <DemoSessionProvider>, before rendering AccountMenu, Gate, ProfilePage or AppSwitcher."
@@ -7515,11 +7763,11 @@ function useSessionContext() {
7515
7763
  }
7516
7764
 
7517
7765
  // src/components/platform/AccountMenu.tsx
7518
- var import_jsx_runtime73 = require("react/jsx-runtime");
7766
+ var import_jsx_runtime74 = require("react/jsx-runtime");
7519
7767
  var DEFAULT_LINKS = [];
7520
7768
  var DEFAULT_GROUPS = [];
7521
7769
  function Item({ item, onPick }) {
7522
- return /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)(
7770
+ return /* @__PURE__ */ (0, import_jsx_runtime74.jsxs)(
7523
7771
  "button",
7524
7772
  {
7525
7773
  type: "button",
@@ -7527,9 +7775,9 @@ function Item({ item, onPick }) {
7527
7775
  className: "fd-acct-item",
7528
7776
  onClick: () => onPick(item),
7529
7777
  children: [
7530
- item.icon ? /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("i", { className: "ph ph-" + item.icon, "aria-hidden": "true" }) : null,
7531
- /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("span", { style: { flex: 1 }, children: item.label }),
7532
- item.badge ? /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(Badge, { tone: "neutral", children: item.badge }) : null
7778
+ item.icon ? /* @__PURE__ */ (0, import_jsx_runtime74.jsx)("i", { className: "ph ph-" + item.icon, "aria-hidden": "true" }) : null,
7779
+ /* @__PURE__ */ (0, import_jsx_runtime74.jsx)("span", { style: { flex: 1 }, children: item.label }),
7780
+ item.badge ? /* @__PURE__ */ (0, import_jsx_runtime74.jsx)(Badge, { tone: "neutral", children: item.badge }) : null
7533
7781
  ]
7534
7782
  }
7535
7783
  );
@@ -7545,11 +7793,11 @@ function AccountMenu({
7545
7793
  ...rest
7546
7794
  }) {
7547
7795
  const { user, roles, can: can2, signOut: ctxSignOut, demo, pending } = useSessionContext();
7548
- const [open2, setOpen] = React44.useState(false);
7549
- const [switching, setSwitching] = React44.useState(false);
7550
- const [signingOut, setSigningOut] = React44.useState(false);
7551
- const [signOutError, setSignOutError] = React44.useState(null);
7552
- const ref = React44.useRef(null);
7796
+ const [open2, setOpen] = React45.useState(false);
7797
+ const [switching, setSwitching] = React45.useState(false);
7798
+ const [signingOut, setSigningOut] = React45.useState(false);
7799
+ const [signOutError, setSignOutError] = React45.useState(null);
7800
+ const ref = React45.useRef(null);
7553
7801
  const visibleLinks = links.filter((l) => !l.perm || !pending && can2(l.perm));
7554
7802
  const visibleGroups = groups.map((g) => ({ label: g.label, links: g.links.filter((l) => !l.perm || !pending && can2(l.perm)) })).filter((g) => g.links.length);
7555
7803
  const closeMenu = () => {
@@ -7577,8 +7825,8 @@ function AccountMenu({
7577
7825
  }
7578
7826
  };
7579
7827
  const showSwitcher = allowUserSwitch && !!demo;
7580
- return /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)(import_jsx_runtime73.Fragment, { children: [
7581
- /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)(
7828
+ return /* @__PURE__ */ (0, import_jsx_runtime74.jsxs)(import_jsx_runtime74.Fragment, { children: [
7829
+ /* @__PURE__ */ (0, import_jsx_runtime74.jsxs)(
7582
7830
  "button",
7583
7831
  {
7584
7832
  type: "button",
@@ -7590,12 +7838,12 @@ function AccountMenu({
7590
7838
  onClick: () => open2 ? closeMenu() : setOpen(true),
7591
7839
  ...rest,
7592
7840
  children: [
7593
- /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(Avatar, { name: user.name, size: "sm" }),
7594
- /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("i", { className: "ph ph-caret-down", "aria-hidden": "true", style: { fontSize: 11, color: "var(--text-muted)" } })
7841
+ /* @__PURE__ */ (0, import_jsx_runtime74.jsx)(Avatar, { name: user.name, size: "sm" }),
7842
+ /* @__PURE__ */ (0, import_jsx_runtime74.jsx)("i", { className: "ph ph-caret-down", "aria-hidden": "true", style: { fontSize: 11, color: "var(--text-muted)" } })
7595
7843
  ]
7596
7844
  }
7597
7845
  ),
7598
- /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(
7846
+ /* @__PURE__ */ (0, import_jsx_runtime74.jsx)(
7599
7847
  Popover,
7600
7848
  {
7601
7849
  open: open2,
@@ -7603,27 +7851,27 @@ function AccountMenu({
7603
7851
  onClose: closeMenu,
7604
7852
  placement: "bottom-end",
7605
7853
  width: 272,
7606
- children: /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("div", { role: "menu", className: "fd-stack", style: { gap: 0 }, children: [
7607
- /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("div", { className: "fd-row", style: { gap: 10, padding: "12px 14px", borderBottom: "1px solid var(--border)" }, children: [
7608
- /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(Avatar, { name: user.name }),
7609
- /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("span", { className: "fd-stack", style: { gap: 1, minWidth: 0, flex: 1 }, children: [
7610
- /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("span", { className: "fd-body-sm", style: { fontWeight: 700 }, children: user.name }),
7611
- /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("span", { className: "fd-body-sm fd-muted fd-table-trunc", title: truncationTitle(user.email), children: user.email })
7854
+ children: /* @__PURE__ */ (0, import_jsx_runtime74.jsxs)("div", { role: "menu", className: "fd-stack", style: { gap: 0 }, children: [
7855
+ /* @__PURE__ */ (0, import_jsx_runtime74.jsxs)("div", { className: "fd-row", style: { gap: 10, padding: "12px 14px", borderBottom: "1px solid var(--border)" }, children: [
7856
+ /* @__PURE__ */ (0, import_jsx_runtime74.jsx)(Avatar, { name: user.name }),
7857
+ /* @__PURE__ */ (0, import_jsx_runtime74.jsxs)("span", { className: "fd-stack", style: { gap: 1, minWidth: 0, flex: 1 }, children: [
7858
+ /* @__PURE__ */ (0, import_jsx_runtime74.jsx)("span", { className: "fd-body-sm", style: { fontWeight: 700 }, children: user.name }),
7859
+ /* @__PURE__ */ (0, import_jsx_runtime74.jsx)("span", { className: "fd-body-sm fd-muted fd-table-trunc", title: truncationTitle(user.email), children: user.email })
7612
7860
  ] })
7613
7861
  ] }),
7614
- showRoles && roles.length ? /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("div", { className: "fd-row", style: { gap: 6, padding: "10px 14px", flexWrap: "wrap", borderBottom: "1px solid var(--border)" }, children: roles.map((r) => /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(Badge, { tone: r.id === "owner" ? "success" : "neutral", children: r.name }, r.id)) }) : null,
7615
- visibleLinks.length ? /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("div", { className: "fd-acct-group", children: visibleLinks.map((l) => /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(Item, { item: l, onPick: pick }, l.id)) }) : null,
7616
- visibleGroups.map((g) => /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("div", { className: "fd-acct-group", style: { borderTop: "1px solid var(--border)" }, children: [
7617
- /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("span", { className: "fd-overline fd-muted", style: { padding: "8px 14px 4px", display: "block" }, children: g.label }),
7618
- g.links.map((l) => /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(Item, { item: l, onPick: pick }, l.id))
7862
+ showRoles && roles.length ? /* @__PURE__ */ (0, import_jsx_runtime74.jsx)("div", { className: "fd-row", style: { gap: 6, padding: "10px 14px", flexWrap: "wrap", borderBottom: "1px solid var(--border)" }, children: roles.map((r) => /* @__PURE__ */ (0, import_jsx_runtime74.jsx)(Badge, { tone: r.id === "owner" ? "success" : "neutral", children: r.name }, r.id)) }) : null,
7863
+ visibleLinks.length ? /* @__PURE__ */ (0, import_jsx_runtime74.jsx)("div", { className: "fd-acct-group", children: visibleLinks.map((l) => /* @__PURE__ */ (0, import_jsx_runtime74.jsx)(Item, { item: l, onPick: pick }, l.id)) }) : null,
7864
+ visibleGroups.map((g) => /* @__PURE__ */ (0, import_jsx_runtime74.jsxs)("div", { className: "fd-acct-group", style: { borderTop: "1px solid var(--border)" }, children: [
7865
+ /* @__PURE__ */ (0, import_jsx_runtime74.jsx)("span", { className: "fd-overline fd-muted", style: { padding: "8px 14px 4px", display: "block" }, children: g.label }),
7866
+ g.links.map((l) => /* @__PURE__ */ (0, import_jsx_runtime74.jsx)(Item, { item: l, onPick: pick }, l.id))
7619
7867
  ] }, g.label)),
7620
- showSwitcher && demo ? /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("div", { className: "fd-acct-group", style: { borderTop: "1px solid var(--border)" }, children: [
7621
- /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("button", { type: "button", role: "menuitem", className: "fd-acct-item", onClick: () => setSwitching((s) => !s), children: [
7622
- /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("i", { className: "ph ph-user-switch", "aria-hidden": "true" }),
7623
- /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("span", { style: { flex: 1 }, children: "View as another member" }),
7624
- /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("i", { className: "ph ph-caret-" + (switching ? "up" : "down"), "aria-hidden": "true", style: { fontSize: 11 } })
7868
+ showSwitcher && demo ? /* @__PURE__ */ (0, import_jsx_runtime74.jsxs)("div", { className: "fd-acct-group", style: { borderTop: "1px solid var(--border)" }, children: [
7869
+ /* @__PURE__ */ (0, import_jsx_runtime74.jsxs)("button", { type: "button", role: "menuitem", className: "fd-acct-item", onClick: () => setSwitching((s) => !s), children: [
7870
+ /* @__PURE__ */ (0, import_jsx_runtime74.jsx)("i", { className: "ph ph-user-switch", "aria-hidden": "true" }),
7871
+ /* @__PURE__ */ (0, import_jsx_runtime74.jsx)("span", { style: { flex: 1 }, children: "View as another member" }),
7872
+ /* @__PURE__ */ (0, import_jsx_runtime74.jsx)("i", { className: "ph ph-caret-" + (switching ? "up" : "down"), "aria-hidden": "true", style: { fontSize: 11 } })
7625
7873
  ] }),
7626
- switching ? /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("div", { className: "fd-stack", style: { gap: 0 }, children: demo.allUsers.map((u) => /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)(
7874
+ switching ? /* @__PURE__ */ (0, import_jsx_runtime74.jsx)("div", { className: "fd-stack", style: { gap: 0 }, children: demo.allUsers.map((u) => /* @__PURE__ */ (0, import_jsx_runtime74.jsxs)(
7627
7875
  "button",
7628
7876
  {
7629
7877
  type: "button",
@@ -7635,19 +7883,19 @@ function AccountMenu({
7635
7883
  setSwitching(false);
7636
7884
  },
7637
7885
  children: [
7638
- /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(Avatar, { name: u.name, size: "sm" }),
7639
- /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("span", { className: "fd-stack", style: { gap: 0, flex: 1, minWidth: 0, alignItems: "flex-start" }, children: [
7640
- /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("span", { style: { fontWeight: u.id === user.id ? 700 : 500 }, children: u.name }),
7641
- u.roles ? /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("span", { className: "fd-muted", style: { fontSize: 11.5 }, children: u.roles.join(", ") }) : null
7886
+ /* @__PURE__ */ (0, import_jsx_runtime74.jsx)(Avatar, { name: u.name, size: "sm" }),
7887
+ /* @__PURE__ */ (0, import_jsx_runtime74.jsxs)("span", { className: "fd-stack", style: { gap: 0, flex: 1, minWidth: 0, alignItems: "flex-start" }, children: [
7888
+ /* @__PURE__ */ (0, import_jsx_runtime74.jsx)("span", { style: { fontWeight: u.id === user.id ? 700 : 500 }, children: u.name }),
7889
+ u.roles ? /* @__PURE__ */ (0, import_jsx_runtime74.jsx)("span", { className: "fd-muted", style: { fontSize: 11.5 }, children: u.roles.join(", ") }) : null
7642
7890
  ] }),
7643
- u.id === user.id ? /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("i", { className: "ph ph-check", "aria-hidden": "true", style: { color: "var(--ok-text)" } }) : null
7891
+ u.id === user.id ? /* @__PURE__ */ (0, import_jsx_runtime74.jsx)("i", { className: "ph ph-check", "aria-hidden": "true", style: { color: "var(--ok-text)" } }) : null
7644
7892
  ]
7645
7893
  },
7646
7894
  u.id
7647
7895
  )) }) : null
7648
7896
  ] }) : null,
7649
- /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("div", { className: "fd-acct-group", style: { borderTop: "1px solid var(--border)" }, children: [
7650
- /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)(
7897
+ /* @__PURE__ */ (0, import_jsx_runtime74.jsxs)("div", { className: "fd-acct-group", style: { borderTop: "1px solid var(--border)" }, children: [
7898
+ /* @__PURE__ */ (0, import_jsx_runtime74.jsxs)(
7651
7899
  "button",
7652
7900
  {
7653
7901
  type: "button",
@@ -7657,14 +7905,14 @@ function AccountMenu({
7657
7905
  disabled: signingOut,
7658
7906
  onClick: signOut,
7659
7907
  children: [
7660
- signingOut ? /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(Spinner, { size: "sm" }) : /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("i", { className: "ph ph-sign-out", "aria-hidden": "true" }),
7661
- /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("span", { style: { flex: 1 }, children: signingOut ? "Signing out\u2026" : "Sign out" })
7908
+ signingOut ? /* @__PURE__ */ (0, import_jsx_runtime74.jsx)(Spinner, { size: "sm" }) : /* @__PURE__ */ (0, import_jsx_runtime74.jsx)("i", { className: "ph ph-sign-out", "aria-hidden": "true" }),
7909
+ /* @__PURE__ */ (0, import_jsx_runtime74.jsx)("span", { style: { flex: 1 }, children: signingOut ? "Signing out\u2026" : "Sign out" })
7662
7910
  ]
7663
7911
  }
7664
7912
  ),
7665
- signOutError ? /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("div", { role: "alert", className: "fd-body-sm", style: { padding: "0 14px 12px" }, children: [
7666
- /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("span", { style: { display: "block", color: "var(--danger-text)", marginBottom: 6 }, children: signOutError }),
7667
- /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("button", { type: "button", className: "fd-soon-link", disabled: signingOut, onClick: signOut, children: "Retry" })
7913
+ signOutError ? /* @__PURE__ */ (0, import_jsx_runtime74.jsxs)("div", { role: "alert", className: "fd-body-sm", style: { padding: "0 14px 12px" }, children: [
7914
+ /* @__PURE__ */ (0, import_jsx_runtime74.jsx)("span", { style: { display: "block", color: "var(--danger-text)", marginBottom: 6 }, children: signOutError }),
7915
+ /* @__PURE__ */ (0, import_jsx_runtime74.jsx)("button", { type: "button", className: "fd-soon-link", disabled: signingOut, onClick: signOut, children: "Retry" })
7668
7916
  ] }) : null
7669
7917
  ] })
7670
7918
  ] })
@@ -7674,13 +7922,13 @@ function AccountMenu({
7674
7922
  }
7675
7923
 
7676
7924
  // src/components/platform/AppSwitcher.tsx
7677
- var React45 = __toESM(require("react"), 1);
7678
- var import_jsx_runtime74 = require("react/jsx-runtime");
7925
+ var React46 = __toESM(require("react"), 1);
7926
+ var import_jsx_runtime75 = require("react/jsx-runtime");
7679
7927
  function AppSwitcher({ apps: appsProp, onNavigate, className = "" }) {
7680
7928
  const { apps: contextApps } = useSessionContext();
7681
7929
  const apps = appsProp ?? contextApps ?? [];
7682
- const [open2, setOpen] = React45.useState(false);
7683
- const anchorRef = React45.useRef(null);
7930
+ const [open2, setOpen] = React46.useState(false);
7931
+ const anchorRef = React46.useRef(null);
7684
7932
  if (!apps.length) return null;
7685
7933
  const items = apps.map((app) => ({
7686
7934
  id: app.key,
@@ -7694,8 +7942,8 @@ function AppSwitcher({ apps: appsProp, onNavigate, className = "" }) {
7694
7942
  window.location.href = app.url;
7695
7943
  }
7696
7944
  }));
7697
- return /* @__PURE__ */ (0, import_jsx_runtime74.jsxs)(React45.Fragment, { children: [
7698
- /* @__PURE__ */ (0, import_jsx_runtime74.jsx)("span", { ref: anchorRef, className: ["fd-appswitch-anchor", className].filter(Boolean).join(" "), style: { display: "inline-flex" }, children: /* @__PURE__ */ (0, import_jsx_runtime74.jsx)(
7945
+ return /* @__PURE__ */ (0, import_jsx_runtime75.jsxs)(React46.Fragment, { children: [
7946
+ /* @__PURE__ */ (0, import_jsx_runtime75.jsx)("span", { ref: anchorRef, className: ["fd-appswitch-anchor", className].filter(Boolean).join(" "), style: { display: "inline-flex" }, children: /* @__PURE__ */ (0, import_jsx_runtime75.jsx)(
7699
7947
  IconButton,
7700
7948
  {
7701
7949
  icon: "squares-four",
@@ -7705,7 +7953,7 @@ function AppSwitcher({ apps: appsProp, onNavigate, className = "" }) {
7705
7953
  onClick: () => setOpen((v) => !v)
7706
7954
  }
7707
7955
  ) }),
7708
- /* @__PURE__ */ (0, import_jsx_runtime74.jsx)(
7956
+ /* @__PURE__ */ (0, import_jsx_runtime75.jsx)(
7709
7957
  Popover,
7710
7958
  {
7711
7959
  open: open2,
@@ -7716,17 +7964,17 @@ function AppSwitcher({ apps: appsProp, onNavigate, className = "" }) {
7716
7964
  label: "All flytedesk apps",
7717
7965
  width: 240,
7718
7966
  maxHeight: 360,
7719
- children: /* @__PURE__ */ (0, import_jsx_runtime74.jsx)(Menu, { items, onClose: () => setOpen(false) })
7967
+ children: /* @__PURE__ */ (0, import_jsx_runtime75.jsx)(Menu, { items, onClose: () => setOpen(false) })
7720
7968
  }
7721
7969
  )
7722
7970
  ] });
7723
7971
  }
7724
7972
 
7725
7973
  // src/components/platform/AppearanceMenu.tsx
7726
- var React47 = __toESM(require("react"), 1);
7974
+ var React48 = __toESM(require("react"), 1);
7727
7975
 
7728
7976
  // src/kits/appearance.ts
7729
- var React46 = __toESM(require("react"), 1);
7977
+ var React47 = __toESM(require("react"), 1);
7730
7978
  var DEFAULT_STORAGE_KEY = "fd-appearance";
7731
7979
  var DEFAULT_PREFS = {
7732
7980
  theme: "system",
@@ -7821,11 +8069,11 @@ function applyPrefs(prefs, root = document.documentElement) {
7821
8069
  else root.removeAttribute("data-motion");
7822
8070
  }
7823
8071
  function useAppearancePrefs(store) {
7824
- const prefs = React46.useSyncExternalStore(store.subscribe, store.getSnapshot);
7825
- React46.useEffect(() => {
8072
+ const prefs = React47.useSyncExternalStore(store.subscribe, store.getSnapshot);
8073
+ React47.useEffect(() => {
7826
8074
  applyPrefs(prefs);
7827
8075
  }, [prefs]);
7828
- React46.useEffect(() => {
8076
+ React47.useEffect(() => {
7829
8077
  if (prefs.theme !== "system" || typeof window === "undefined" || typeof window.matchMedia !== "function") {
7830
8078
  return;
7831
8079
  }
@@ -7834,7 +8082,7 @@ function useAppearancePrefs(store) {
7834
8082
  mq.addEventListener("change", onChange);
7835
8083
  return () => mq.removeEventListener("change", onChange);
7836
8084
  }, [prefs]);
7837
- const update = React46.useCallback(
8085
+ const update = React47.useCallback(
7838
8086
  (patch) => {
7839
8087
  store.write({ ...store.getSnapshot(), ...patch });
7840
8088
  },
@@ -7844,7 +8092,7 @@ function useAppearancePrefs(store) {
7844
8092
  }
7845
8093
 
7846
8094
  // src/components/platform/AppearanceMenu.tsx
7847
- var import_jsx_runtime75 = require("react/jsx-runtime");
8095
+ var import_jsx_runtime76 = require("react/jsx-runtime");
7848
8096
  var THEME_OPTIONS = [
7849
8097
  { value: "light", label: "Light" },
7850
8098
  { value: "dark", label: "Dark" },
@@ -7857,16 +8105,16 @@ var TEXT_SCALE_OPTIONS = [
7857
8105
  { value: "xl", label: "XL" }
7858
8106
  ];
7859
8107
  function AppearanceMenu({ className = "", store: storeProp, storageKey, storage, defaults }) {
7860
- const store = React47.useMemo(
8108
+ const store = React48.useMemo(
7861
8109
  () => storeProp ?? createLocalStorageAppearanceStore({ storageKey, storage, defaults }),
7862
8110
  [storeProp, storageKey, storage, defaults]
7863
8111
  );
7864
8112
  const [prefs, update] = useAppearancePrefs(store);
7865
- const [open2, setOpen] = React47.useState(false);
7866
- const anchorRef = React47.useRef(null);
8113
+ const [open2, setOpen] = React48.useState(false);
8114
+ const anchorRef = React48.useRef(null);
7867
8115
  const patch = (p) => update(p);
7868
- return /* @__PURE__ */ (0, import_jsx_runtime75.jsxs)(React47.Fragment, { children: [
7869
- /* @__PURE__ */ (0, import_jsx_runtime75.jsx)("span", { ref: anchorRef, className: ["fd-appearance-anchor", className].filter(Boolean).join(" "), style: { display: "inline-flex" }, children: /* @__PURE__ */ (0, import_jsx_runtime75.jsx)(
8116
+ return /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)(React48.Fragment, { children: [
8117
+ /* @__PURE__ */ (0, import_jsx_runtime76.jsx)("span", { ref: anchorRef, className: ["fd-appearance-anchor", className].filter(Boolean).join(" "), style: { display: "inline-flex" }, children: /* @__PURE__ */ (0, import_jsx_runtime76.jsx)(
7870
8118
  IconButton,
7871
8119
  {
7872
8120
  icon: "circle-half",
@@ -7874,7 +8122,7 @@ function AppearanceMenu({ className = "", store: storeProp, storageKey, storage,
7874
8122
  onClick: () => setOpen((v) => !v)
7875
8123
  }
7876
8124
  ) }),
7877
- /* @__PURE__ */ (0, import_jsx_runtime75.jsx)(
8125
+ /* @__PURE__ */ (0, import_jsx_runtime76.jsx)(
7878
8126
  Popover,
7879
8127
  {
7880
8128
  open: open2,
@@ -7884,10 +8132,10 @@ function AppearanceMenu({ className = "", store: storeProp, storageKey, storage,
7884
8132
  padded: true,
7885
8133
  width: 260,
7886
8134
  label: "Appearance settings",
7887
- children: /* @__PURE__ */ (0, import_jsx_runtime75.jsxs)("div", { className: "fd-stack", style: { display: "flex", flexDirection: "column", gap: 16 }, children: [
7888
- /* @__PURE__ */ (0, import_jsx_runtime75.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: 6 }, children: [
7889
- /* @__PURE__ */ (0, import_jsx_runtime75.jsx)("span", { className: "fd-field-label", children: "Theme" }),
7890
- /* @__PURE__ */ (0, import_jsx_runtime75.jsx)(
8135
+ children: /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)("div", { className: "fd-stack", style: { display: "flex", flexDirection: "column", gap: 16 }, children: [
8136
+ /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: 6 }, children: [
8137
+ /* @__PURE__ */ (0, import_jsx_runtime76.jsx)("span", { className: "fd-field-label", children: "Theme" }),
8138
+ /* @__PURE__ */ (0, import_jsx_runtime76.jsx)(
7891
8139
  SegmentedControl,
7892
8140
  {
7893
8141
  options: THEME_OPTIONS,
@@ -7897,9 +8145,9 @@ function AppearanceMenu({ className = "", store: storeProp, storageKey, storage,
7897
8145
  }
7898
8146
  )
7899
8147
  ] }),
7900
- /* @__PURE__ */ (0, import_jsx_runtime75.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: 6 }, children: [
7901
- /* @__PURE__ */ (0, import_jsx_runtime75.jsx)("span", { className: "fd-field-label", children: "Text size" }),
7902
- /* @__PURE__ */ (0, import_jsx_runtime75.jsx)(
8148
+ /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: 6 }, children: [
8149
+ /* @__PURE__ */ (0, import_jsx_runtime76.jsx)("span", { className: "fd-field-label", children: "Text size" }),
8150
+ /* @__PURE__ */ (0, import_jsx_runtime76.jsx)(
7903
8151
  SegmentedControl,
7904
8152
  {
7905
8153
  options: TEXT_SCALE_OPTIONS,
@@ -7909,7 +8157,7 @@ function AppearanceMenu({ className = "", store: storeProp, storageKey, storage,
7909
8157
  }
7910
8158
  )
7911
8159
  ] }),
7912
- /* @__PURE__ */ (0, import_jsx_runtime75.jsx)(
8160
+ /* @__PURE__ */ (0, import_jsx_runtime76.jsx)(
7913
8161
  Switch,
7914
8162
  {
7915
8163
  label: "High contrast",
@@ -7918,7 +8166,7 @@ function AppearanceMenu({ className = "", store: storeProp, storageKey, storage,
7918
8166
  onChange: (e) => patch({ highContrast: e.target.checked })
7919
8167
  }
7920
8168
  ),
7921
- /* @__PURE__ */ (0, import_jsx_runtime75.jsx)(
8169
+ /* @__PURE__ */ (0, import_jsx_runtime76.jsx)(
7922
8170
  Switch,
7923
8171
  {
7924
8172
  label: "Reduce motion",
@@ -7934,14 +8182,14 @@ function AppearanceMenu({ className = "", store: storeProp, storageKey, storage,
7934
8182
  }
7935
8183
 
7936
8184
  // src/components/platform/ApiSpecBrowser.tsx
7937
- var React48 = __toESM(require("react"), 1);
7938
- var import_jsx_runtime76 = require("react/jsx-runtime");
8185
+ var React49 = __toESM(require("react"), 1);
8186
+ var import_jsx_runtime77 = require("react/jsx-runtime");
7939
8187
  var METHOD_TONE = { GET: "success", POST: "info", PATCH: "warning", PUT: "warning", DELETE: "danger" };
7940
8188
  function Json({ obj }) {
7941
- return /* @__PURE__ */ (0, import_jsx_runtime76.jsx)("pre", { className: "fd-json", children: JSON.stringify(obj, null, 2) });
8189
+ return /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("pre", { className: "fd-json", children: JSON.stringify(obj, null, 2) });
7942
8190
  }
7943
8191
  function Endpoint({ s, onRequest }) {
7944
- const [tried, setTried] = React48.useState(null);
8192
+ const [tried, setTried] = React49.useState(null);
7945
8193
  const run = async () => {
7946
8194
  setTried("busy");
7947
8195
  const t0 = (window.performance || Date).now();
@@ -7952,50 +8200,50 @@ function Endpoint({ s, onRequest }) {
7952
8200
  setTried({ ms: Math.round((window.performance || Date).now() - t0), error: String(e && e.message || e) });
7953
8201
  }
7954
8202
  };
7955
- return /* @__PURE__ */ (0, import_jsx_runtime76.jsx)(Card, { elevation: "flat", padded: false, children: /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)("div", { className: "fd-stack", style: { gap: 0 }, children: [
7956
- /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)("div", { className: "fd-row", style: { gap: 10, padding: "14px 18px", flexWrap: "wrap" }, children: [
7957
- /* @__PURE__ */ (0, import_jsx_runtime76.jsx)(Badge, { tone: METHOD_TONE[s.method] || "neutral", children: s.method }),
7958
- /* @__PURE__ */ (0, import_jsx_runtime76.jsx)("code", { className: "fd-mono", style: { fontSize: 12.5, fontWeight: 600, color: "var(--text)", wordBreak: "break-all" }, children: s.path }),
7959
- s.isList ? /* @__PURE__ */ (0, import_jsx_runtime76.jsx)(Badge, { tone: "neutral", icon: "rows", children: "Paged list" }) : null,
7960
- /* @__PURE__ */ (0, import_jsx_runtime76.jsx)("span", { style: { flex: 1 } }),
7961
- /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)("span", { className: "fd-body-sm fd-muted fd-mono", children: [
8203
+ return /* @__PURE__ */ (0, import_jsx_runtime77.jsx)(Card, { elevation: "flat", padded: false, children: /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)("div", { className: "fd-stack", style: { gap: 0 }, children: [
8204
+ /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)("div", { className: "fd-row", style: { gap: 10, padding: "14px 18px", flexWrap: "wrap" }, children: [
8205
+ /* @__PURE__ */ (0, import_jsx_runtime77.jsx)(Badge, { tone: METHOD_TONE[s.method] || "neutral", children: s.method }),
8206
+ /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("code", { className: "fd-mono", style: { fontSize: 12.5, fontWeight: 600, color: "var(--text)", wordBreak: "break-all" }, children: s.path }),
8207
+ s.isList ? /* @__PURE__ */ (0, import_jsx_runtime77.jsx)(Badge, { tone: "neutral", icon: "rows", children: "Paged list" }) : null,
8208
+ /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("span", { style: { flex: 1 } }),
8209
+ /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)("span", { className: "fd-body-sm fd-muted fd-mono", children: [
7962
8210
  s.latency[0],
7963
8211
  "\u2013",
7964
8212
  s.latency[1],
7965
8213
  "ms"
7966
8214
  ] }),
7967
- /* @__PURE__ */ (0, import_jsx_runtime76.jsx)(Button, { size: "sm", variant: "secondary", icon: "play", loading: tried === "busy", onClick: run, children: "Try it" })
8215
+ /* @__PURE__ */ (0, import_jsx_runtime77.jsx)(Button, { size: "sm", variant: "secondary", icon: "play", loading: tried === "busy", onClick: run, children: "Try it" })
7968
8216
  ] }),
7969
- /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)("div", { className: "fd-stack", style: { gap: 14, padding: "0 18px 16px" }, children: [
7970
- /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)("div", { className: "fd-stack", style: { gap: 6 }, children: [
7971
- /* @__PURE__ */ (0, import_jsx_runtime76.jsx)("span", { className: "fd-body-sm", style: { fontWeight: 700 }, children: s.title }),
7972
- /* @__PURE__ */ (0, import_jsx_runtime76.jsx)("p", { className: "fd-body-sm fd-secondary", style: { margin: 0, textWrap: "pretty" }, children: s.purpose }),
7973
- s.usedBy && s.usedBy.length ? /* @__PURE__ */ (0, import_jsx_runtime76.jsx)("span", { className: "fd-row", style: { gap: 6, flexWrap: "wrap" }, children: s.usedBy.map((u) => /* @__PURE__ */ (0, import_jsx_runtime76.jsx)(Tag, { children: u }, u)) }) : null
8217
+ /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)("div", { className: "fd-stack", style: { gap: 14, padding: "0 18px 16px" }, children: [
8218
+ /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)("div", { className: "fd-stack", style: { gap: 6 }, children: [
8219
+ /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("span", { className: "fd-body-sm", style: { fontWeight: 700 }, children: s.title }),
8220
+ /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("p", { className: "fd-body-sm fd-secondary", style: { margin: 0, textWrap: "pretty" }, children: s.purpose }),
8221
+ s.usedBy && s.usedBy.length ? /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("span", { className: "fd-row", style: { gap: 6, flexWrap: "wrap" }, children: s.usedBy.map((u) => /* @__PURE__ */ (0, import_jsx_runtime77.jsx)(Tag, { children: u }, u)) }) : null
7974
8222
  ] }),
7975
- /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)("div", { style: { display: "grid", gridTemplateColumns: "repeat(auto-fit,minmax(280px,1fr))", gap: 12, alignItems: "start" }, children: [
7976
- s.request ? /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)("div", { className: "fd-stack", style: { gap: 6 }, children: [
7977
- /* @__PURE__ */ (0, import_jsx_runtime76.jsx)("span", { className: "fd-overline fd-muted", children: "Request body" }),
7978
- /* @__PURE__ */ (0, import_jsx_runtime76.jsx)(Json, { obj: s.request })
8223
+ /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)("div", { style: { display: "grid", gridTemplateColumns: "repeat(auto-fit,minmax(280px,1fr))", gap: 12, alignItems: "start" }, children: [
8224
+ s.request ? /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)("div", { className: "fd-stack", style: { gap: 6 }, children: [
8225
+ /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("span", { className: "fd-overline fd-muted", children: "Request body" }),
8226
+ /* @__PURE__ */ (0, import_jsx_runtime77.jsx)(Json, { obj: s.request })
7979
8227
  ] }) : null,
7980
- s.query ? /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)("div", { className: "fd-stack", style: { gap: 6 }, children: [
7981
- /* @__PURE__ */ (0, import_jsx_runtime76.jsx)("span", { className: "fd-overline fd-muted", children: "Query" }),
7982
- /* @__PURE__ */ (0, import_jsx_runtime76.jsx)(Json, { obj: s.query })
8228
+ s.query ? /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)("div", { className: "fd-stack", style: { gap: 6 }, children: [
8229
+ /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("span", { className: "fd-overline fd-muted", children: "Query" }),
8230
+ /* @__PURE__ */ (0, import_jsx_runtime77.jsx)(Json, { obj: s.query })
7983
8231
  ] }) : null,
7984
- /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)("div", { className: "fd-stack", style: { gap: 6 }, children: [
7985
- /* @__PURE__ */ (0, import_jsx_runtime76.jsx)("span", { className: "fd-overline fd-muted", children: "Response 200" }),
7986
- /* @__PURE__ */ (0, import_jsx_runtime76.jsx)(Json, { obj: s.response })
8232
+ /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)("div", { className: "fd-stack", style: { gap: 6 }, children: [
8233
+ /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("span", { className: "fd-overline fd-muted", children: "Response 200" }),
8234
+ /* @__PURE__ */ (0, import_jsx_runtime77.jsx)(Json, { obj: s.response })
7987
8235
  ] })
7988
8236
  ] }),
7989
- s.notes ? /* @__PURE__ */ (0, import_jsx_runtime76.jsx)(Flag, { tone: "info", statement: "Implementation note", cost: s.notes, actions: null }) : null,
7990
- tried && tried !== "busy" ? /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)("div", { className: "fd-stack", style: { gap: 6 }, children: [
7991
- /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)("span", { className: "fd-row", style: { gap: 8 }, children: [
7992
- /* @__PURE__ */ (0, import_jsx_runtime76.jsx)("span", { className: "fd-overline fd-muted", children: "Simulated response" }),
7993
- /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)(Badge, { tone: tried.error ? "danger" : "success", icon: "timer", children: [
8237
+ s.notes ? /* @__PURE__ */ (0, import_jsx_runtime77.jsx)(Flag, { tone: "info", statement: "Implementation note", cost: s.notes, actions: null }) : null,
8238
+ tried && tried !== "busy" ? /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)("div", { className: "fd-stack", style: { gap: 6 }, children: [
8239
+ /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)("span", { className: "fd-row", style: { gap: 8 }, children: [
8240
+ /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("span", { className: "fd-overline fd-muted", children: "Simulated response" }),
8241
+ /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)(Badge, { tone: tried.error ? "danger" : "success", icon: "timer", children: [
7994
8242
  tried.ms,
7995
8243
  "ms"
7996
8244
  ] })
7997
8245
  ] }),
7998
- /* @__PURE__ */ (0, import_jsx_runtime76.jsx)(Json, { obj: tried.error ? { error: tried.error } : tried.data })
8246
+ /* @__PURE__ */ (0, import_jsx_runtime77.jsx)(Json, { obj: tried.error ? { error: tried.error } : tried.data })
7999
8247
  ] }) : null
8000
8248
  ] })
8001
8249
  ] }) });
@@ -8014,58 +8262,58 @@ function ApiSpecBrowser({
8014
8262
  className = "",
8015
8263
  ...rest
8016
8264
  }) {
8017
- const [q, setQ] = React48.useState("");
8018
- const [method, setMethod] = React48.useState(null);
8019
- const [mod, setMod] = React48.useState(null);
8020
- const [listOnly, setListOnly] = React48.useState(false);
8265
+ const [q, setQ] = React49.useState("");
8266
+ const [method, setMethod] = React49.useState(null);
8267
+ const [mod, setMod] = React49.useState(null);
8268
+ const [listOnly, setListOnly] = React49.useState(false);
8021
8269
  const activeModule = modules && modules.find((m) => m.id === mod);
8022
8270
  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())));
8023
8271
  const effGroups = groups && groups.length ? groups : [["All endpoints", spec.map((s) => s.id)]];
8024
8272
  const methods = [...new Set(spec.map((s) => s.method))];
8025
8273
  const listCount = spec.filter((s) => s.isList).length;
8026
- return /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 20, maxWidth: 1100 }, ...rest, children: [
8027
- /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)("div", { className: "fd-stack", style: { gap: 10 }, children: [
8028
- kicker ? /* @__PURE__ */ (0, import_jsx_runtime76.jsx)("span", { className: "fd-overline fd-muted", children: kicker }) : null,
8029
- /* @__PURE__ */ (0, import_jsx_runtime76.jsx)("h1", { className: "fd-h1", style: { margin: 0 }, children: title }),
8030
- lede ? /* @__PURE__ */ (0, import_jsx_runtime76.jsx)("p", { className: "fd-body fd-secondary fd-prose", style: { margin: 0 }, children: lede }) : null
8274
+ return /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 20, maxWidth: 1100 }, ...rest, children: [
8275
+ /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)("div", { className: "fd-stack", style: { gap: 10 }, children: [
8276
+ kicker ? /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("span", { className: "fd-overline fd-muted", children: kicker }) : null,
8277
+ /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("h1", { className: "fd-h1", style: { margin: 0 }, children: title }),
8278
+ lede ? /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("p", { className: "fd-body fd-secondary fd-prose", style: { margin: 0 }, children: lede }) : null
8031
8279
  ] }),
8032
- modules && modules.length ? /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)("div", { className: "fd-stack", style: { gap: 8 }, children: [
8033
- /* @__PURE__ */ (0, import_jsx_runtime76.jsx)("span", { className: "fd-overline fd-muted", children: "Filter by screen \u2014 every endpoint that screen depends on" }),
8034
- /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)("div", { className: "fd-row", style: { gap: 8, flexWrap: "wrap" }, children: [
8035
- /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)(Tag, { icon: "stack", selected: !mod, onClick: () => setMod(null), children: [
8280
+ modules && modules.length ? /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)("div", { className: "fd-stack", style: { gap: 8 }, children: [
8281
+ /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("span", { className: "fd-overline fd-muted", children: "Filter by screen \u2014 every endpoint that screen depends on" }),
8282
+ /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)("div", { className: "fd-row", style: { gap: 8, flexWrap: "wrap" }, children: [
8283
+ /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)(Tag, { icon: "stack", selected: !mod, onClick: () => setMod(null), children: [
8036
8284
  "All screens ",
8037
- /* @__PURE__ */ (0, import_jsx_runtime76.jsx)("span", { className: "fd-mono", children: spec.length })
8285
+ /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("span", { className: "fd-mono", children: spec.length })
8038
8286
  ] }),
8039
- modules.map((m) => /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)(Tag, { icon: m.icon, selected: mod === m.id, onClick: () => setMod(mod === m.id ? null : m.id), children: [
8287
+ modules.map((m) => /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)(Tag, { icon: m.icon, selected: mod === m.id, onClick: () => setMod(mod === m.id ? null : m.id), children: [
8040
8288
  m.label,
8041
8289
  " ",
8042
- /* @__PURE__ */ (0, import_jsx_runtime76.jsx)("span", { className: "fd-mono", children: m.endpoints.length })
8290
+ /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("span", { className: "fd-mono", children: m.endpoints.length })
8043
8291
  ] }, m.id))
8044
8292
  ] }),
8045
- activeModule ? /* @__PURE__ */ (0, import_jsx_runtime76.jsx)(
8293
+ activeModule ? /* @__PURE__ */ (0, import_jsx_runtime77.jsx)(
8046
8294
  Flag,
8047
8295
  {
8048
8296
  tone: "info",
8049
8297
  statement: activeModule.label + " calls " + activeModule.endpoints.length + " endpoints.",
8050
8298
  cost: "Integration checklist for this screen: " + activeModule.endpoints.join(", ") + ". Wire these and the screen is done.",
8051
- actions: /* @__PURE__ */ (0, import_jsx_runtime76.jsx)(Button, { size: "sm", variant: "ghost", icon: "x", onClick: () => setMod(null), children: "Show all screens" })
8299
+ actions: /* @__PURE__ */ (0, import_jsx_runtime77.jsx)(Button, { size: "sm", variant: "ghost", icon: "x", onClick: () => setMod(null), children: "Show all screens" })
8052
8300
  }
8053
8301
  ) : null
8054
8302
  ] }) : null,
8055
- sourceNote ? /* @__PURE__ */ (0, import_jsx_runtime76.jsx)(Flag, { tone: "info", statement: "Design-first: this page is the spec.", cost: sourceNote, actions: null }) : null,
8056
- /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)("div", { className: "fd-row", style: { gap: 10, flexWrap: "wrap" }, children: [
8057
- /* @__PURE__ */ (0, import_jsx_runtime76.jsx)(Input, { icon: "magnifying-glass", placeholder: "Find an endpoint, screen, or behavior", value: q, onChange: (e) => setQ(e.target.value), style: { width: 300 } }),
8058
- methods.map((m) => /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)(Tag, { selected: method === m, onClick: () => setMethod(method === m ? null : m), children: [
8303
+ sourceNote ? /* @__PURE__ */ (0, import_jsx_runtime77.jsx)(Flag, { tone: "info", statement: "Design-first: this page is the spec.", cost: sourceNote, actions: null }) : null,
8304
+ /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)("div", { className: "fd-row", style: { gap: 10, flexWrap: "wrap" }, children: [
8305
+ /* @__PURE__ */ (0, import_jsx_runtime77.jsx)(Input, { icon: "magnifying-glass", placeholder: "Find an endpoint, screen, or behavior", value: q, onChange: (e) => setQ(e.target.value), style: { width: 300 } }),
8306
+ methods.map((m) => /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)(Tag, { selected: method === m, onClick: () => setMethod(method === m ? null : m), children: [
8059
8307
  m,
8060
8308
  " ",
8061
- /* @__PURE__ */ (0, import_jsx_runtime76.jsx)("span", { className: "fd-mono", children: spec.filter((s) => s.method === m).length })
8309
+ /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("span", { className: "fd-mono", children: spec.filter((s) => s.method === m).length })
8062
8310
  ] }, m)),
8063
- listCount ? /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)(Tag, { icon: "rows", selected: listOnly, onClick: () => setListOnly(!listOnly), children: [
8311
+ listCount ? /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)(Tag, { icon: "rows", selected: listOnly, onClick: () => setListOnly(!listOnly), children: [
8064
8312
  "Paged lists ",
8065
- /* @__PURE__ */ (0, import_jsx_runtime76.jsx)("span", { className: "fd-mono", children: listCount })
8313
+ /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("span", { className: "fd-mono", children: listCount })
8066
8314
  ] }) : null,
8067
- /* @__PURE__ */ (0, import_jsx_runtime76.jsx)("span", { style: { flex: 1 } }),
8068
- /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)("span", { className: "fd-body-sm fd-muted", children: [
8315
+ /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("span", { style: { flex: 1 } }),
8316
+ /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)("span", { className: "fd-body-sm fd-muted", children: [
8069
8317
  hits.length,
8070
8318
  " of ",
8071
8319
  spec.length,
@@ -8073,31 +8321,31 @@ function ApiSpecBrowser({
8073
8321
  listCount ? " \xB7 " + listCount + " paged" : ""
8074
8322
  ] })
8075
8323
  ] }),
8076
- hits.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime76.jsx)(Card, { elevation: "flat", children: /* @__PURE__ */ (0, import_jsx_runtime76.jsx)("p", { className: "fd-body-sm fd-muted", style: { margin: 0 }, children: "No endpoint matches those filters." }) }) : effGroups.map(([g, ids]) => {
8324
+ hits.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime77.jsx)(Card, { elevation: "flat", children: /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("p", { className: "fd-body-sm fd-muted", style: { margin: 0 }, children: "No endpoint matches those filters." }) }) : effGroups.map(([g, ids]) => {
8077
8325
  const items = hits.filter((s) => ids.indexOf(s.id) >= 0);
8078
8326
  if (!items.length) return null;
8079
- return /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)("div", { className: "fd-stack", style: { gap: 12 }, children: [
8080
- /* @__PURE__ */ (0, import_jsx_runtime76.jsx)("span", { className: "fd-label-lg", children: g }),
8081
- items.map((s) => /* @__PURE__ */ (0, import_jsx_runtime76.jsx)(Endpoint, { s, onRequest }, s.id))
8327
+ return /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)("div", { className: "fd-stack", style: { gap: 12 }, children: [
8328
+ /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("span", { className: "fd-label-lg", children: g }),
8329
+ items.map((s) => /* @__PURE__ */ (0, import_jsx_runtime77.jsx)(Endpoint, { s, onRequest }, s.id))
8082
8330
  ] }, g);
8083
8331
  }),
8084
- conventions && conventions.length ? /* @__PURE__ */ (0, import_jsx_runtime76.jsx)(Card, { title: "Cross-cutting conventions", elevation: "flat", children: /* @__PURE__ */ (0, import_jsx_runtime76.jsx)("div", { className: "fd-stack", style: { gap: 10 }, children: conventions.map(([k, v]) => /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)("div", { className: "fd-row", style: { gap: 12, alignItems: "flex-start" }, children: [
8085
- /* @__PURE__ */ (0, import_jsx_runtime76.jsx)("span", { className: "fd-overline fd-muted", style: { width: 110, flex: "none", paddingTop: 2 }, children: k }),
8086
- /* @__PURE__ */ (0, import_jsx_runtime76.jsx)("span", { className: "fd-body-sm fd-secondary", style: { textWrap: "pretty" }, children: v })
8332
+ conventions && conventions.length ? /* @__PURE__ */ (0, import_jsx_runtime77.jsx)(Card, { title: "Cross-cutting conventions", elevation: "flat", children: /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("div", { className: "fd-stack", style: { gap: 10 }, children: conventions.map(([k, v]) => /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)("div", { className: "fd-row", style: { gap: 12, alignItems: "flex-start" }, children: [
8333
+ /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("span", { className: "fd-overline fd-muted", style: { width: 110, flex: "none", paddingTop: 2 }, children: k }),
8334
+ /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("span", { className: "fd-body-sm fd-secondary", style: { textWrap: "pretty" }, children: v })
8087
8335
  ] }, k)) }) }) : null,
8088
- openQuestions && openQuestions.length ? /* @__PURE__ */ (0, import_jsx_runtime76.jsx)(Collapsible, { icon: "list-checks", title: "Open questions before implementation", subtitle: openQuestions.length + " unresolved", children: /* @__PURE__ */ (0, import_jsx_runtime76.jsx)("div", { className: "fd-stack", style: { gap: 8 }, children: openQuestions.map(([id, question, why]) => /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)("div", { className: "fd-row", style: { gap: 10, alignItems: "flex-start", padding: "8px 0", borderTop: "1px solid var(--border)" }, children: [
8089
- /* @__PURE__ */ (0, import_jsx_runtime76.jsx)(Badge, { tone: "danger", children: id }),
8090
- /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)("span", { className: "fd-stack", style: { gap: 2, flex: 1 }, children: [
8091
- /* @__PURE__ */ (0, import_jsx_runtime76.jsx)("span", { className: "fd-body-sm", style: { fontWeight: 600 }, children: question }),
8092
- /* @__PURE__ */ (0, import_jsx_runtime76.jsx)("span", { className: "fd-body-sm fd-muted", children: why })
8336
+ openQuestions && openQuestions.length ? /* @__PURE__ */ (0, import_jsx_runtime77.jsx)(Collapsible, { icon: "list-checks", title: "Open questions before implementation", subtitle: openQuestions.length + " unresolved", children: /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("div", { className: "fd-stack", style: { gap: 8 }, children: openQuestions.map(([id, question, why]) => /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)("div", { className: "fd-row", style: { gap: 10, alignItems: "flex-start", padding: "8px 0", borderTop: "1px solid var(--border)" }, children: [
8337
+ /* @__PURE__ */ (0, import_jsx_runtime77.jsx)(Badge, { tone: "danger", children: id }),
8338
+ /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)("span", { className: "fd-stack", style: { gap: 2, flex: 1 }, children: [
8339
+ /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("span", { className: "fd-body-sm", style: { fontWeight: 600 }, children: question }),
8340
+ /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("span", { className: "fd-body-sm fd-muted", children: why })
8093
8341
  ] })
8094
8342
  ] }, id)) }) }) : null
8095
8343
  ] });
8096
8344
  }
8097
8345
 
8098
8346
  // src/components/platform/ProfilePage.tsx
8099
- var React49 = __toESM(require("react"), 1);
8100
- var import_jsx_runtime77 = require("react/jsx-runtime");
8347
+ var React50 = __toESM(require("react"), 1);
8348
+ var import_jsx_runtime78 = require("react/jsx-runtime");
8101
8349
  function fieldInitialValue(field, user) {
8102
8350
  if (field.value) return field.value(user);
8103
8351
  const raw = user[field.key];
@@ -8132,21 +8380,21 @@ function ProfilePage({
8132
8380
  }) {
8133
8381
  const { user: sessionUser, roles, permissions, saveProfile: saveProfile2 } = useSessionContext();
8134
8382
  const user = userProp || sessionUser;
8135
- const initialFieldValues = React49.useMemo(() => {
8383
+ const initialFieldValues = React50.useMemo(() => {
8136
8384
  const values2 = {};
8137
8385
  for (const field of fields) values2[field.key] = fieldInitialValue(field, user);
8138
8386
  return values2;
8139
8387
  }, [user.id, fields]);
8140
- const initialNotify = React49.useMemo(() => {
8388
+ const initialNotify = React50.useMemo(() => {
8141
8389
  const values2 = {};
8142
8390
  for (const n of notifications) values2[n.key] = !!user.notify?.[n.key];
8143
8391
  return values2;
8144
8392
  }, [user.id, notifications]);
8145
- const [values, setValues] = React49.useState(initialFieldValues);
8146
- const [notify, setNotify] = React49.useState(initialNotify);
8147
- const [saving, setSaving] = React49.useState(false);
8148
- const [saved, setSaved] = React49.useState(false);
8149
- const [prevUserId, setPrevUserId] = React49.useState(user.id);
8393
+ const [values, setValues] = React50.useState(initialFieldValues);
8394
+ const [notify, setNotify] = React50.useState(initialNotify);
8395
+ const [saving, setSaving] = React50.useState(false);
8396
+ const [saved, setSaved] = React50.useState(false);
8397
+ const [prevUserId, setPrevUserId] = React50.useState(user.id);
8150
8398
  if (user.id !== prevUserId) {
8151
8399
  setPrevUserId(user.id);
8152
8400
  setValues(initialFieldValues);
@@ -8183,37 +8431,37 @@ function ProfilePage({
8183
8431
  };
8184
8432
  const displayName = fields.some((f) => f.key === "name") ? values.name || user.name : user.name;
8185
8433
  const fieldGroups = groupFields(fields);
8186
- return /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 20, maxWidth: 860 }, children: [
8187
- /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)("div", { className: "fd-stack", style: { gap: 10 }, children: [
8188
- /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("span", { className: "fd-overline fd-muted", children: "Account" }),
8189
- /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("h1", { className: "fd-h1", style: { margin: 0 }, children: "Your profile" }),
8190
- /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("p", { className: "fd-body fd-secondary fd-prose", style: { margin: 0 }, children: "How you appear to colleagues and clients across every flytedesk app, and what we send you." })
8434
+ return /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 20, maxWidth: 860 }, children: [
8435
+ /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)("div", { className: "fd-stack", style: { gap: 10 }, children: [
8436
+ /* @__PURE__ */ (0, import_jsx_runtime78.jsx)("span", { className: "fd-overline fd-muted", children: "Account" }),
8437
+ /* @__PURE__ */ (0, import_jsx_runtime78.jsx)("h1", { className: "fd-h1", style: { margin: 0 }, children: "Your profile" }),
8438
+ /* @__PURE__ */ (0, import_jsx_runtime78.jsx)("p", { className: "fd-body fd-secondary fd-prose", style: { margin: 0 }, children: "How you appear to colleagues and clients across every flytedesk app, and what we send you." })
8191
8439
  ] }),
8192
- /* @__PURE__ */ (0, import_jsx_runtime77.jsx)(Card, { elevation: "flat", children: /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)("div", { className: "fd-row", style: { gap: 16, flexWrap: "wrap", alignItems: "flex-start" }, children: [
8193
- /* @__PURE__ */ (0, import_jsx_runtime77.jsx)(Avatar, { name: displayName, size: "lg" }),
8194
- /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)("div", { className: "fd-stack", style: { gap: 4, flex: 1, minWidth: 200 }, children: [
8195
- /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("span", { className: "fd-h3", style: { margin: 0 }, children: displayName }),
8196
- /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)("span", { className: "fd-row", style: { gap: 6, flexWrap: "wrap", paddingTop: 4 }, children: [
8197
- roles.map((r) => /* @__PURE__ */ (0, import_jsx_runtime77.jsx)(Badge, { tone: r.id === "owner" ? "success" : "neutral", children: r.name }, r.id)),
8198
- user.sso ? /* @__PURE__ */ (0, import_jsx_runtime77.jsx)(Badge, { tone: "info", icon: "shield-check", children: "SSO" }) : null
8440
+ /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(Card, { elevation: "flat", children: /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)("div", { className: "fd-row", style: { gap: 16, flexWrap: "wrap", alignItems: "flex-start" }, children: [
8441
+ /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(Avatar, { name: displayName, size: "lg" }),
8442
+ /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)("div", { className: "fd-stack", style: { gap: 4, flex: 1, minWidth: 200 }, children: [
8443
+ /* @__PURE__ */ (0, import_jsx_runtime78.jsx)("span", { className: "fd-h3", style: { margin: 0 }, children: displayName }),
8444
+ /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)("span", { className: "fd-row", style: { gap: 6, flexWrap: "wrap", paddingTop: 4 }, children: [
8445
+ roles.map((r) => /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(Badge, { tone: r.id === "owner" ? "success" : "neutral", children: r.name }, r.id)),
8446
+ user.sso ? /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(Badge, { tone: "info", icon: "shield-check", children: "SSO" }) : null
8199
8447
  ] })
8200
8448
  ] }),
8201
- onChangePhoto ? /* @__PURE__ */ (0, import_jsx_runtime77.jsx)(Button, { variant: "secondary", size: "sm", icon: "image", onClick: onChangePhoto, children: "Change photo" }) : null
8449
+ onChangePhoto ? /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(Button, { variant: "secondary", size: "sm", icon: "image", onClick: onChangePhoto, children: "Change photo" }) : null
8202
8450
  ] }) }),
8203
- fieldGroups.map(({ group, description, fields: groupFieldDefs }) => /* @__PURE__ */ (0, import_jsx_runtime77.jsx)(
8451
+ fieldGroups.map(({ group, description, fields: groupFieldDefs }) => /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(
8204
8452
  Card,
8205
8453
  {
8206
- title: description ? /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)("span", { className: "fd-stack", style: { gap: 2 }, children: [
8207
- /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("span", { children: group }),
8208
- /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("span", { className: "fd-body-sm fd-muted", style: { fontWeight: 400 }, children: description })
8454
+ title: description ? /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)("span", { className: "fd-stack", style: { gap: 2 }, children: [
8455
+ /* @__PURE__ */ (0, import_jsx_runtime78.jsx)("span", { children: group }),
8456
+ /* @__PURE__ */ (0, import_jsx_runtime78.jsx)("span", { className: "fd-body-sm fd-muted", style: { fontWeight: 400 }, children: description })
8209
8457
  ] }) : group,
8210
8458
  elevation: "flat",
8211
- children: /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)("div", { className: "fd-stack", style: { gap: 14 }, children: [
8212
- /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("div", { style: { display: "grid", gridTemplateColumns: "repeat(auto-fit,minmax(220px,1fr))", gap: 14 }, children: groupFieldDefs.filter((f) => f.type !== "textarea").map((field) => {
8459
+ children: /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)("div", { className: "fd-stack", style: { gap: 14 }, children: [
8460
+ /* @__PURE__ */ (0, import_jsx_runtime78.jsx)("div", { style: { display: "grid", gridTemplateColumns: "repeat(auto-fit,minmax(220px,1fr))", gap: 14 }, children: groupFieldDefs.filter((f) => f.type !== "textarea").map((field) => {
8213
8461
  const help = typeof field.help === "function" ? field.help(user) : field.help;
8214
8462
  const readOnly = field.readOnly || field.type === "readonly";
8215
8463
  if (field.type === "select") {
8216
- return /* @__PURE__ */ (0, import_jsx_runtime77.jsx)(
8464
+ return /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(
8217
8465
  Select,
8218
8466
  {
8219
8467
  label: field.label,
@@ -8227,7 +8475,7 @@ function ProfilePage({
8227
8475
  field.key
8228
8476
  );
8229
8477
  }
8230
- return /* @__PURE__ */ (0, import_jsx_runtime77.jsx)(
8478
+ return /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(
8231
8479
  Input,
8232
8480
  {
8233
8481
  label: field.label,
@@ -8243,7 +8491,7 @@ function ProfilePage({
8243
8491
  }) }),
8244
8492
  groupFieldDefs.filter((f) => f.type === "textarea").map((field) => {
8245
8493
  const help = typeof field.help === "function" ? field.help(user) : field.help;
8246
- return /* @__PURE__ */ (0, import_jsx_runtime77.jsx)(
8494
+ return /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(
8247
8495
  Textarea,
8248
8496
  {
8249
8497
  label: field.label,
@@ -8263,16 +8511,16 @@ function ProfilePage({
8263
8511
  group
8264
8512
  )),
8265
8513
  extra,
8266
- notifications.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime77.jsx)(Card, { title: "Notifications", elevation: "flat", children: /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("div", { className: "fd-stack", style: { gap: 14 }, children: notifications.map((n) => /* @__PURE__ */ (0, import_jsx_runtime77.jsx)(Switch, { checked: !!notify[n.key], onChange: () => toggleNotify(n.key), label: n.label, description: n.description }, n.key)) }) }) : null,
8267
- /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)(
8514
+ notifications.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(Card, { title: "Notifications", elevation: "flat", children: /* @__PURE__ */ (0, import_jsx_runtime78.jsx)("div", { className: "fd-stack", style: { gap: 14 }, children: notifications.map((n) => /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(Switch, { checked: !!notify[n.key], onChange: () => toggleNotify(n.key), label: n.label, description: n.description }, n.key)) }) }) : null,
8515
+ /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)(
8268
8516
  Card,
8269
8517
  {
8270
- title: /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)("span", { className: "fd-stack", style: { gap: 2 }, children: [
8271
- /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("span", { children: "Access" }),
8272
- /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("span", { className: "fd-body-sm fd-muted", style: { fontWeight: 400 }, children: "What your roles grant you" })
8518
+ title: /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)("span", { className: "fd-stack", style: { gap: 2 }, children: [
8519
+ /* @__PURE__ */ (0, import_jsx_runtime78.jsx)("span", { children: "Access" }),
8520
+ /* @__PURE__ */ (0, import_jsx_runtime78.jsx)("span", { className: "fd-body-sm fd-muted", style: { fontWeight: 400 }, children: "What your roles grant you" })
8273
8521
  ] }),
8274
8522
  elevation: "flat",
8275
- action: /* @__PURE__ */ (0, import_jsx_runtime77.jsx)(
8523
+ action: /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(
8276
8524
  Button,
8277
8525
  {
8278
8526
  size: "sm",
@@ -8283,39 +8531,39 @@ function ProfilePage({
8283
8531
  }
8284
8532
  ),
8285
8533
  children: [
8286
- /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)("div", { className: "fd-stack", style: { gap: 0 }, children: [
8287
- /* @__PURE__ */ (0, import_jsx_runtime77.jsx)(CardRow, { label: "Roles", children: roles.map((r) => r.name).join(", ") || "None" }),
8288
- /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)(CardRow, { label: "Permissions", children: [
8534
+ /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)("div", { className: "fd-stack", style: { gap: 0 }, children: [
8535
+ /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(CardRow, { label: "Roles", children: roles.map((r) => r.name).join(", ") || "None" }),
8536
+ /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)(CardRow, { label: "Permissions", children: [
8289
8537
  permissions.length,
8290
8538
  " granted"
8291
8539
  ] }),
8292
- /* @__PURE__ */ (0, import_jsx_runtime77.jsx)(CardRow, { label: "Member since", children: user.joined || "\u2014" })
8540
+ /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(CardRow, { label: "Member since", children: user.joined || "\u2014" })
8293
8541
  ] }),
8294
- /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("p", { className: "fd-body-sm fd-muted", style: { margin: "12px 0 0" }, children: "You cannot change your own roles \u2014 that is the point of them. An administrator manages roles from Admin \u2192 Users." })
8542
+ /* @__PURE__ */ (0, import_jsx_runtime78.jsx)("p", { className: "fd-body-sm fd-muted", style: { margin: "12px 0 0" }, children: "You cannot change your own roles \u2014 that is the point of them. An administrator manages roles from Admin \u2192 Users." })
8295
8543
  ]
8296
8544
  }
8297
8545
  ),
8298
- sessions ? /* @__PURE__ */ (0, import_jsx_runtime77.jsx)(
8546
+ sessions ? /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(
8299
8547
  Card,
8300
8548
  {
8301
8549
  title: "Signed-in devices",
8302
8550
  elevation: "flat",
8303
- action: /* @__PURE__ */ (0, import_jsx_runtime77.jsx)(Button, { size: "sm", variant: "ghost", icon: "sign-out", onClick: onSignOutEverywhere, children: "Sign out everywhere" }),
8304
- children: /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("div", { className: "fd-stack", style: { gap: 0 }, children: sessions.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("p", { className: "fd-body-sm fd-muted", style: { margin: 0 }, children: "No other signed-in devices." }) : sessions.map((s) => /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)("div", { className: "fd-row", style: { gap: 12, padding: "10px 0", borderTop: "1px solid var(--border)", flexWrap: "wrap" }, children: [
8305
- /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("i", { className: "ph ph-device-mobile", style: { fontSize: 16, color: "var(--text-muted)" }, "aria-hidden": "true" }),
8306
- /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)("span", { className: "fd-stack", style: { gap: 1, flex: 1, minWidth: 160 }, children: [
8307
- /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("span", { className: "fd-body-sm", style: { fontWeight: 600 }, children: s.device }),
8308
- /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)("span", { className: "fd-body-sm fd-muted", children: [
8551
+ action: /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(Button, { size: "sm", variant: "ghost", icon: "sign-out", onClick: onSignOutEverywhere, children: "Sign out everywhere" }),
8552
+ children: /* @__PURE__ */ (0, import_jsx_runtime78.jsx)("div", { className: "fd-stack", style: { gap: 0 }, children: sessions.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime78.jsx)("p", { className: "fd-body-sm fd-muted", style: { margin: 0 }, children: "No other signed-in devices." }) : sessions.map((s) => /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)("div", { className: "fd-row", style: { gap: 12, padding: "10px 0", borderTop: "1px solid var(--border)", flexWrap: "wrap" }, children: [
8553
+ /* @__PURE__ */ (0, import_jsx_runtime78.jsx)("i", { className: "ph ph-device-mobile", style: { fontSize: 16, color: "var(--text-muted)" }, "aria-hidden": "true" }),
8554
+ /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)("span", { className: "fd-stack", style: { gap: 1, flex: 1, minWidth: 160 }, children: [
8555
+ /* @__PURE__ */ (0, import_jsx_runtime78.jsx)("span", { className: "fd-body-sm", style: { fontWeight: 600 }, children: s.device }),
8556
+ /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)("span", { className: "fd-body-sm fd-muted", children: [
8309
8557
  s.where,
8310
8558
  " \xB7 ",
8311
8559
  s.when
8312
8560
  ] })
8313
8561
  ] }),
8314
- s.current ? /* @__PURE__ */ (0, import_jsx_runtime77.jsx)(Badge, { tone: "success", dot: true, children: "This device" }) : /* @__PURE__ */ (0, import_jsx_runtime77.jsx)(Button, { size: "sm", variant: "ghost", children: "Revoke" })
8562
+ s.current ? /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(Badge, { tone: "success", dot: true, children: "This device" }) : /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(Button, { size: "sm", variant: "ghost", children: "Revoke" })
8315
8563
  ] }, s.id)) })
8316
8564
  }
8317
8565
  ) : null,
8318
- /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)("div", { className: "fd-row", style: {
8566
+ /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)("div", { className: "fd-row", style: {
8319
8567
  gap: 10,
8320
8568
  flexWrap: "wrap",
8321
8569
  position: "sticky",
@@ -8326,19 +8574,19 @@ function ProfilePage({
8326
8574
  border: "1px solid var(--border)",
8327
8575
  boxShadow: "0 -4px 16px rgba(11,13,17,.06)"
8328
8576
  }, children: [
8329
- /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("span", { className: "fd-body-sm", style: { fontWeight: 600, flex: 1 }, children: saved ? "Saved." : dirty ? "Unsaved changes" : "No pending changes" }),
8330
- /* @__PURE__ */ (0, import_jsx_runtime77.jsx)(Button, { size: "sm", variant: "ghost", disabled: !dirty || saving, onClick: discard, children: "Discard" }),
8331
- /* @__PURE__ */ (0, import_jsx_runtime77.jsx)(Button, { size: "sm", icon: "check", disabled: !dirty || !canSave, loading: saving, onClick: save, children: "Save changes" })
8577
+ /* @__PURE__ */ (0, import_jsx_runtime78.jsx)("span", { className: "fd-body-sm", style: { fontWeight: 600, flex: 1 }, children: saved ? "Saved." : dirty ? "Unsaved changes" : "No pending changes" }),
8578
+ /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(Button, { size: "sm", variant: "ghost", disabled: !dirty || saving, onClick: discard, children: "Discard" }),
8579
+ /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(Button, { size: "sm", icon: "check", disabled: !dirty || !canSave, loading: saving, onClick: save, children: "Save changes" })
8332
8580
  ] })
8333
8581
  ] });
8334
8582
  }
8335
8583
 
8336
8584
  // src/components/platform/SignInPage.tsx
8337
- var React50 = __toESM(require("react"), 1);
8338
- var import_jsx_runtime78 = require("react/jsx-runtime");
8585
+ var React51 = __toESM(require("react"), 1);
8586
+ var import_jsx_runtime79 = require("react/jsx-runtime");
8339
8587
  function SignInPage({ productName, onSignIn, continueAs, error }) {
8340
- const [signingIn, setSigningIn] = React50.useState(false);
8341
- const [resuming, setResuming] = React50.useState(false);
8588
+ const [signingIn, setSigningIn] = React51.useState(false);
8589
+ const [resuming, setResuming] = React51.useState(false);
8342
8590
  function handleSignIn() {
8343
8591
  setSigningIn(true);
8344
8592
  onSignIn();
@@ -8347,7 +8595,7 @@ function SignInPage({ productName, onSignIn, continueAs, error }) {
8347
8595
  setResuming(true);
8348
8596
  continueAs.onContinue().finally(() => setResuming(false));
8349
8597
  }
8350
- return /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)(
8598
+ return /* @__PURE__ */ (0, import_jsx_runtime79.jsxs)(
8351
8599
  "div",
8352
8600
  {
8353
8601
  style: {
@@ -8361,7 +8609,7 @@ function SignInPage({ productName, onSignIn, continueAs, error }) {
8361
8609
  background: "radial-gradient(circle at 15% 15%, var(--blue-700) 0%, transparent 45%), radial-gradient(circle at 85% 85%, var(--blue-600) 0%, transparent 40%), linear-gradient(160deg, var(--navy) 0%, var(--blue-950) 55%, var(--blue-900) 100%)"
8362
8610
  },
8363
8611
  children: [
8364
- /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(
8612
+ /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(
8365
8613
  "div",
8366
8614
  {
8367
8615
  "aria-hidden": true,
@@ -8374,7 +8622,7 @@ function SignInPage({ productName, onSignIn, continueAs, error }) {
8374
8622
  }
8375
8623
  }
8376
8624
  ),
8377
- /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)(
8625
+ /* @__PURE__ */ (0, import_jsx_runtime79.jsxs)(
8378
8626
  "div",
8379
8627
  {
8380
8628
  style: {
@@ -8386,8 +8634,8 @@ function SignInPage({ productName, onSignIn, continueAs, error }) {
8386
8634
  alignItems: "center"
8387
8635
  },
8388
8636
  children: [
8389
- /* @__PURE__ */ (0, import_jsx_runtime78.jsx)("div", { style: { marginBottom: "var(--s-32)" }, "data-theme": "dark", children: /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(FlytedeskMark, { size: "lg" }) }),
8390
- /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)(
8637
+ /* @__PURE__ */ (0, import_jsx_runtime79.jsx)("div", { style: { marginBottom: "var(--s-32)" }, "data-theme": "dark", children: /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(FlytedeskMark, { size: "lg" }) }),
8638
+ /* @__PURE__ */ (0, import_jsx_runtime79.jsxs)(
8391
8639
  "div",
8392
8640
  {
8393
8641
  style: {
@@ -8397,7 +8645,7 @@ function SignInPage({ productName, onSignIn, continueAs, error }) {
8397
8645
  boxShadow: "0 24px 64px -12px rgba(2, 8, 20, 0.55), 0 2px 8px rgba(2, 8, 20, 0.3)"
8398
8646
  },
8399
8647
  children: [
8400
- /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(
8648
+ /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(
8401
8649
  "div",
8402
8650
  {
8403
8651
  style: {
@@ -8406,7 +8654,7 @@ function SignInPage({ productName, onSignIn, continueAs, error }) {
8406
8654
  }
8407
8655
  }
8408
8656
  ),
8409
- /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(Card, { children: /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)(
8657
+ /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(Card, { children: /* @__PURE__ */ (0, import_jsx_runtime79.jsxs)(
8410
8658
  "div",
8411
8659
  {
8412
8660
  style: {
@@ -8418,13 +8666,13 @@ function SignInPage({ productName, onSignIn, continueAs, error }) {
8418
8666
  padding: "var(--s-8) 0"
8419
8667
  },
8420
8668
  children: [
8421
- /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)("div", { children: [
8422
- /* @__PURE__ */ (0, import_jsx_runtime78.jsx)("h1", { className: "fd-h3", style: { color: "var(--navy)" }, children: productName }),
8423
- /* @__PURE__ */ (0, import_jsx_runtime78.jsx)("p", { className: "fd-body-sm fd-muted", style: { marginTop: "var(--s-4)" }, children: continueAs ? "Your session timed out, but you're likely still signed in" : "Sign in with your flytedesk workspace account" })
8669
+ /* @__PURE__ */ (0, import_jsx_runtime79.jsxs)("div", { children: [
8670
+ /* @__PURE__ */ (0, import_jsx_runtime79.jsx)("h1", { className: "fd-h3", style: { color: "var(--navy)" }, children: productName }),
8671
+ /* @__PURE__ */ (0, import_jsx_runtime79.jsx)("p", { className: "fd-body-sm fd-muted", style: { marginTop: "var(--s-4)" }, children: continueAs ? "Your session timed out, but you're likely still signed in" : "Sign in with your flytedesk workspace account" })
8424
8672
  ] }),
8425
- error ? /* @__PURE__ */ (0, import_jsx_runtime78.jsx)("div", { role: "alert", style: { width: "100%" }, children: /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(Banner, { tone: "danger", title: error }) }) : null,
8426
- continueAs ? /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)(import_jsx_runtime78.Fragment, { children: [
8427
- /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(
8673
+ error ? /* @__PURE__ */ (0, import_jsx_runtime79.jsx)("div", { role: "alert", style: { width: "100%" }, children: /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(Banner, { tone: "danger", title: error }) }) : null,
8674
+ continueAs ? /* @__PURE__ */ (0, import_jsx_runtime79.jsxs)(import_jsx_runtime79.Fragment, { children: [
8675
+ /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(
8428
8676
  Button,
8429
8677
  {
8430
8678
  variant: "primary",
@@ -8435,7 +8683,7 @@ function SignInPage({ productName, onSignIn, continueAs, error }) {
8435
8683
  children: resuming ? "Resuming\u2026" : `Continue as ${continueAs.name}`
8436
8684
  }
8437
8685
  ),
8438
- /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(
8686
+ /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(
8439
8687
  "button",
8440
8688
  {
8441
8689
  type: "button",
@@ -8452,7 +8700,7 @@ function SignInPage({ productName, onSignIn, continueAs, error }) {
8452
8700
  children: "Not you? Sign in with flytedesk ID"
8453
8701
  }
8454
8702
  )
8455
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(
8703
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(
8456
8704
  Button,
8457
8705
  {
8458
8706
  variant: "primary",
@@ -8460,7 +8708,7 @@ function SignInPage({ productName, onSignIn, continueAs, error }) {
8460
8708
  loading: signingIn,
8461
8709
  disabled: signingIn,
8462
8710
  onClick: handleSignIn,
8463
- children: /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)(
8711
+ children: /* @__PURE__ */ (0, import_jsx_runtime79.jsxs)(
8464
8712
  "span",
8465
8713
  {
8466
8714
  style: {
@@ -8472,14 +8720,14 @@ function SignInPage({ productName, onSignIn, continueAs, error }) {
8472
8720
  flexWrap: "nowrap"
8473
8721
  },
8474
8722
  children: [
8475
- /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(GoogleGlyph, {}),
8476
- /* @__PURE__ */ (0, import_jsx_runtime78.jsx)("span", { children: signingIn ? "Signing in\u2026" : "Sign in with flytedesk ID" })
8723
+ /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(GoogleGlyph, {}),
8724
+ /* @__PURE__ */ (0, import_jsx_runtime79.jsx)("span", { children: signingIn ? "Signing in\u2026" : "Sign in with flytedesk ID" })
8477
8725
  ]
8478
8726
  }
8479
8727
  )
8480
8728
  }
8481
8729
  ),
8482
- /* @__PURE__ */ (0, import_jsx_runtime78.jsx)("p", { className: "fd-body-sm fd-muted", style: { fontSize: "12px" }, children: "One account, every flytedesk app." })
8730
+ /* @__PURE__ */ (0, import_jsx_runtime79.jsx)("p", { className: "fd-body-sm fd-muted", style: { fontSize: "12px" }, children: "One account, every flytedesk app." })
8483
8731
  ]
8484
8732
  }
8485
8733
  ) })
@@ -8494,29 +8742,29 @@ function SignInPage({ productName, onSignIn, continueAs, error }) {
8494
8742
  );
8495
8743
  }
8496
8744
  function GoogleGlyph() {
8497
- return /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)("svg", { width: "18", height: "18", viewBox: "0 0 18 18", "aria-hidden": true, children: [
8498
- /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(
8745
+ return /* @__PURE__ */ (0, import_jsx_runtime79.jsxs)("svg", { width: "18", height: "18", viewBox: "0 0 18 18", "aria-hidden": true, children: [
8746
+ /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(
8499
8747
  "path",
8500
8748
  {
8501
8749
  fill: "#4285F4",
8502
8750
  d: "M17.64 9.2c0-.64-.06-1.25-.16-1.84H9v3.48h4.84a4.14 4.14 0 0 1-1.8 2.72v2.26h2.92c1.7-1.57 2.68-3.87 2.68-6.62Z"
8503
8751
  }
8504
8752
  ),
8505
- /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(
8753
+ /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(
8506
8754
  "path",
8507
8755
  {
8508
8756
  fill: "#34A853",
8509
8757
  d: "M9 18c2.43 0 4.47-.8 5.96-2.18l-2.92-2.26c-.81.54-1.84.87-3.04.87-2.34 0-4.32-1.58-5.03-3.7H.96v2.33A9 9 0 0 0 9 18Z"
8510
8758
  }
8511
8759
  ),
8512
- /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(
8760
+ /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(
8513
8761
  "path",
8514
8762
  {
8515
8763
  fill: "#FBBC05",
8516
8764
  d: "M3.97 10.73A5.4 5.4 0 0 1 3.68 9c0-.6.1-1.19.29-1.73V4.94H.96A9 9 0 0 0 0 9c0 1.45.35 2.83.96 4.06l3.01-2.33Z"
8517
8765
  }
8518
8766
  ),
8519
- /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(
8767
+ /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(
8520
8768
  "path",
8521
8769
  {
8522
8770
  fill: "#EA4335",
@@ -8527,10 +8775,10 @@ function GoogleGlyph() {
8527
8775
  }
8528
8776
 
8529
8777
  // src/components/platform/RoadmapTimeline.tsx
8530
- var React53 = __toESM(require("react"), 1);
8778
+ var React54 = __toESM(require("react"), 1);
8531
8779
 
8532
8780
  // src/kits/session.ts
8533
- var React51 = __toESM(require("react"), 1);
8781
+ var React52 = __toESM(require("react"), 1);
8534
8782
  var PERMISSION_CATALOG = [
8535
8783
  { group: "Plans", items: [
8536
8784
  { key: "plan.view", label: "View plans", detail: "Read any plan in the workspace." },
@@ -10097,8 +10345,8 @@ function roadmap(overrides) {
10097
10345
  };
10098
10346
  }
10099
10347
  function useSession() {
10100
- const [s, setS] = React51.useState(getSession);
10101
- React51.useEffect(() => subscribe(setS), []);
10348
+ const [s, setS] = React52.useState(getSession);
10349
+ React52.useEffect(() => subscribe(setS), []);
10102
10350
  return s;
10103
10351
  }
10104
10352
  var SessionKit = {
@@ -10131,7 +10379,7 @@ var SessionKit = {
10131
10379
  };
10132
10380
  function DemoSessionProvider({ children }) {
10133
10381
  const session = useSession();
10134
- const value = React51.useMemo(
10382
+ const value = React52.useMemo(
10135
10383
  () => ({
10136
10384
  user: session.user,
10137
10385
  roles: session.roles,
@@ -10147,11 +10395,11 @@ function DemoSessionProvider({ children }) {
10147
10395
  }),
10148
10396
  [session]
10149
10397
  );
10150
- return React51.createElement(SessionProvider, { value }, children);
10398
+ return React52.createElement(SessionProvider, { value }, children);
10151
10399
  }
10152
10400
 
10153
10401
  // src/kits/runtime.ts
10154
- var React52 = __toESM(require("react"), 1);
10402
+ var React53 = __toESM(require("react"), 1);
10155
10403
  var WIRED_ENDPOINTS = [
10156
10404
  // Nothing yet. Every id below would come from a real service:
10157
10405
  // "plan.get", "placements.list", …
@@ -10322,8 +10570,8 @@ var RuntimeKit = {
10322
10570
  };
10323
10571
  RuntimeKit.declare(FEATURE_NEEDS);
10324
10572
  function useRuntimeMode() {
10325
- const [m, setM] = React52.useState(RuntimeKit.getMode());
10326
- React52.useEffect(() => RuntimeKit.subscribe(setM), []);
10573
+ const [m, setM] = React53.useState(RuntimeKit.getMode());
10574
+ React53.useEffect(() => RuntimeKit.subscribe(setM), []);
10327
10575
  return m;
10328
10576
  }
10329
10577
  function useFeatureStatus(key) {
@@ -10342,7 +10590,7 @@ var UseRuntimeMode = useRuntimeMode;
10342
10590
  var UseFeatureStatus = useFeatureStatus;
10343
10591
 
10344
10592
  // src/components/platform/RoadmapTimeline.tsx
10345
- var import_jsx_runtime79 = require("react/jsx-runtime");
10593
+ var import_jsx_runtime80 = require("react/jsx-runtime");
10346
10594
  var STATUS = {
10347
10595
  shipped: { tone: "success", icon: "check-circle", label: "Wired" },
10348
10596
  next: { tone: "warning", icon: "traffic-cone", label: "Not wired" },
@@ -10357,45 +10605,45 @@ function RoadmapCard({ item, byKey, onOpenFlag }) {
10357
10605
  const s = STATUS[item.status] || STATUS.planned;
10358
10606
  const deps = (item.dependsOn || []).map((k) => byKey[k]).filter(Boolean);
10359
10607
  const blocking = deps.filter((d) => !d.implemented);
10360
- return /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(Card, { elevation: "flat", children: /* @__PURE__ */ (0, import_jsx_runtime79.jsxs)("div", { className: "fd-stack", style: { gap: 10 }, children: [
10361
- /* @__PURE__ */ (0, import_jsx_runtime79.jsxs)("div", { className: "fd-row", style: { gap: 8, flexWrap: "wrap" }, children: [
10362
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)("span", { className: "fd-body", style: { fontWeight: 700, flex: 1, minWidth: 140 }, children: item.label }),
10363
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(Badge, { tone: "neutral", icon: PROJECT_ICON[item.project] || "squares-four", children: item.project }),
10364
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(Badge, { tone: s.tone, icon: s.icon, children: s.label })
10608
+ return /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(Card, { elevation: "flat", children: /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("div", { className: "fd-stack", style: { gap: 10 }, children: [
10609
+ /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("div", { className: "fd-row", style: { gap: 8, flexWrap: "wrap" }, children: [
10610
+ /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("span", { className: "fd-body", style: { fontWeight: 700, flex: 1, minWidth: 140 }, children: item.label }),
10611
+ /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(Badge, { tone: "neutral", icon: PROJECT_ICON[item.project] || "squares-four", children: item.project }),
10612
+ /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(Badge, { tone: s.tone, icon: s.icon, children: s.label })
10365
10613
  ] }),
10366
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)("p", { className: "fd-body-sm fd-secondary", style: { margin: 0, textWrap: "pretty" }, children: item.description }),
10367
- item.backend ? /* @__PURE__ */ (0, import_jsx_runtime79.jsxs)("div", { className: "fd-row", style: { gap: 10, alignItems: "flex-start" }, children: [
10368
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)("span", { className: "fd-overline fd-muted", style: { width: 62, flex: "none", paddingTop: 2 }, children: "Backend" }),
10369
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)("span", { className: "fd-body-sm", style: { flex: 1, textWrap: "pretty" }, children: item.backend })
10614
+ /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("p", { className: "fd-body-sm fd-secondary", style: { margin: 0, textWrap: "pretty" }, children: item.description }),
10615
+ item.backend ? /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("div", { className: "fd-row", style: { gap: 10, alignItems: "flex-start" }, children: [
10616
+ /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("span", { className: "fd-overline fd-muted", style: { width: 62, flex: "none", paddingTop: 2 }, children: "Backend" }),
10617
+ /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("span", { className: "fd-body-sm", style: { flex: 1, textWrap: "pretty" }, children: item.backend })
10370
10618
  ] }) : null,
10371
- /* @__PURE__ */ (0, import_jsx_runtime79.jsxs)("div", { className: "fd-row", style: { gap: 12, flexWrap: "wrap" }, children: [
10372
- item.effort ? /* @__PURE__ */ (0, import_jsx_runtime79.jsxs)("span", { className: "fd-body-sm fd-muted", children: [
10373
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)("i", { className: "ph ph-hourglass-medium" }),
10619
+ /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("div", { className: "fd-row", style: { gap: 12, flexWrap: "wrap" }, children: [
10620
+ item.effort ? /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("span", { className: "fd-body-sm fd-muted", children: [
10621
+ /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("i", { className: "ph ph-hourglass-medium" }),
10374
10622
  " ",
10375
10623
  item.effort
10376
10624
  ] }) : null,
10377
- /* @__PURE__ */ (0, import_jsx_runtime79.jsxs)("span", { className: "fd-body-sm fd-muted", children: [
10378
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)("i", { className: "ph ph-user" }),
10625
+ /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("span", { className: "fd-body-sm fd-muted", children: [
10626
+ /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("i", { className: "ph ph-user" }),
10379
10627
  " ",
10380
10628
  item.owner
10381
10629
  ] }),
10382
- item.screen ? /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(Badge, { tone: "neutral", icon: "browser", children: "screen" }) : null,
10383
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)("span", { style: { flex: 1 } }),
10384
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(
10630
+ item.screen ? /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(Badge, { tone: "neutral", icon: "browser", children: "screen" }) : null,
10631
+ /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("span", { style: { flex: 1 } }),
10632
+ /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(
10385
10633
  "button",
10386
10634
  {
10387
10635
  type: "button",
10388
10636
  onClick: () => onOpenFlag && onOpenFlag(item.key),
10389
10637
  style: { all: "unset", cursor: "pointer", display: "inline-flex", alignItems: "center", gap: 5 },
10390
- children: /* @__PURE__ */ (0, import_jsx_runtime79.jsx)("code", { className: "fd-mono", style: { fontSize: 11, color: "var(--brand)" }, children: item.key })
10638
+ children: /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("code", { className: "fd-mono", style: { fontSize: 11, color: "var(--brand)" }, children: item.key })
10391
10639
  }
10392
10640
  )
10393
10641
  ] }),
10394
- deps.length ? /* @__PURE__ */ (0, import_jsx_runtime79.jsxs)("div", { className: "fd-row", style: { gap: 6, flexWrap: "wrap", paddingTop: 6, borderTop: "1px solid var(--border)" }, children: [
10395
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)("span", { className: "fd-overline fd-muted", style: { paddingTop: 3 }, children: "After" }),
10396
- deps.map((d) => /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(Tag, { icon: d.implemented ? "check" : "clock", children: d.label }, d.key))
10642
+ deps.length ? /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("div", { className: "fd-row", style: { gap: 6, flexWrap: "wrap", paddingTop: 6, borderTop: "1px solid var(--border)" }, children: [
10643
+ /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("span", { className: "fd-overline fd-muted", style: { paddingTop: 3 }, children: "After" }),
10644
+ deps.map((d) => /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(Tag, { icon: d.implemented ? "check" : "clock", children: d.label }, d.key))
10397
10645
  ] }) : null,
10398
- blocking.length && !item.implemented ? /* @__PURE__ */ (0, import_jsx_runtime79.jsxs)("span", { className: "fd-body-sm", style: { color: "var(--warn-text)" }, children: [
10646
+ blocking.length && !item.implemented ? /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("span", { className: "fd-body-sm", style: { color: "var(--warn-text)" }, children: [
10399
10647
  "Blocked until ",
10400
10648
  blocking.map((d) => d.label).join(" and "),
10401
10649
  " ",
@@ -10406,12 +10654,12 @@ function RoadmapCard({ item, byKey, onOpenFlag }) {
10406
10654
  }
10407
10655
  function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
10408
10656
  const session = SessionKit.useSession();
10409
- const [project, setProject] = React53.useState("");
10410
- const [q, setQ] = React53.useState("");
10411
- const scrollRef = React53.useRef(null);
10412
- const nowRef = React53.useRef(null);
10413
- const rm = React53.useMemo(() => SessionKit.roadmap({ isComplete: RuntimeKit.isComplete }), [session]);
10414
- const byKey = React53.useMemo(() => {
10657
+ const [project, setProject] = React54.useState("");
10658
+ const [q, setQ] = React54.useState("");
10659
+ const scrollRef = React54.useRef(null);
10660
+ const nowRef = React54.useRef(null);
10661
+ const rm = React54.useMemo(() => SessionKit.roadmap({ isComplete: RuntimeKit.isComplete }), [session]);
10662
+ const byKey = React54.useMemo(() => {
10415
10663
  const m = {};
10416
10664
  rm.items.forEach((i) => {
10417
10665
  m[i.key] = i;
@@ -10420,7 +10668,7 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
10420
10668
  }, [rm]);
10421
10669
  const items = rm.items.filter((i) => (!project || i.project === project) && (!q || (i.label + " " + i.description + " " + (i.backend || "") + " " + i.key).toLowerCase().includes(q.toLowerCase())));
10422
10670
  const projects = [...new Set(rm.items.map((i) => i.project))];
10423
- React53.useEffect(() => {
10671
+ React54.useEffect(() => {
10424
10672
  let raf1 = 0, raf2 = 0;
10425
10673
  const place = () => {
10426
10674
  const box = scrollRef.current, mark = nowRef.current;
@@ -10448,23 +10696,23 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
10448
10696
  }, 0);
10449
10697
  const nextPhase = items.find((i) => !i.implemented);
10450
10698
  let lastPhase = null;
10451
- return /* @__PURE__ */ (0, import_jsx_runtime79.jsxs)("div", { className: "fd-stack", style: { gap: 16, maxWidth: 1e3 }, children: [
10452
- /* @__PURE__ */ (0, import_jsx_runtime79.jsxs)("div", { className: "fd-stack", style: { gap: 10 }, children: [
10453
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)("span", { className: "fd-overline fd-muted", children: "Architecture" }),
10454
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)("h1", { className: "fd-h1", style: { margin: 0 }, children: title }),
10455
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)("p", { className: "fd-body fd-secondary fd-prose", style: { margin: 0 }, children: lede || "Every screen and feature in these tools is already designed and working against a simulated backend. This is the plan for connecting them to the real one \u2014 so the only work described here is server work." })
10699
+ return /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("div", { className: "fd-stack", style: { gap: 16, maxWidth: 1e3 }, children: [
10700
+ /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("div", { className: "fd-stack", style: { gap: 10 }, children: [
10701
+ /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("span", { className: "fd-overline fd-muted", children: "Architecture" }),
10702
+ /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("h1", { className: "fd-h1", style: { margin: 0 }, children: title }),
10703
+ /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("p", { className: "fd-body fd-secondary fd-prose", style: { margin: 0 }, children: lede || "Every screen and feature in these tools is already designed and working against a simulated backend. This is the plan for connecting them to the real one \u2014 so the only work described here is server work." })
10456
10704
  ] }),
10457
- /* @__PURE__ */ (0, import_jsx_runtime79.jsxs)("div", { className: "fd-grid-stats is-thin", children: [
10458
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(StatTile, { compact: true, label: "Wired", value: String(rm.shipped), sub: "of " + rm.items.length + " features" }),
10459
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(StatTile, { compact: true, label: "Remaining", value: String(rm.remaining), sub: "backend work" }),
10460
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(StatTile, { compact: true, label: "Est. effort", value: days ? days + " days" : "\u2014", sub: "sum of estimates, not calendar" }),
10461
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(StatTile, { compact: true, label: "Up next", value: nextPhase ? "Phase " + nextPhase.phase : "\u2014", sub: nextPhase ? nextPhase.phaseName : "all wired" })
10705
+ /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("div", { className: "fd-grid-stats is-thin", children: [
10706
+ /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(StatTile, { compact: true, label: "Wired", value: String(rm.shipped), sub: "of " + rm.items.length + " features" }),
10707
+ /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(StatTile, { compact: true, label: "Remaining", value: String(rm.remaining), sub: "backend work" }),
10708
+ /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(StatTile, { compact: true, label: "Est. effort", value: days ? days + " days" : "\u2014", sub: "sum of estimates, not calendar" }),
10709
+ /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(StatTile, { compact: true, label: "Up next", value: nextPhase ? "Phase " + nextPhase.phase : "\u2014", sub: nextPhase ? nextPhase.phaseName : "all wired" })
10462
10710
  ] }),
10463
- /* @__PURE__ */ (0, import_jsx_runtime79.jsxs)("div", { className: "fd-row", style: { gap: 10, flexWrap: "wrap" }, children: [
10464
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(Input, { icon: "magnifying-glass", placeholder: "Find a feature or a piece of backend work", value: q, onChange: (e) => setQ(e.target.value), style: { width: 300 } }),
10465
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(Select, { placeholder: "All projects", value: project, onChange: (e) => setProject(e.target.value), options: projects, style: { width: 190 } }),
10466
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)("span", { style: { flex: 1 } }),
10467
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(
10711
+ /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("div", { className: "fd-row", style: { gap: 10, flexWrap: "wrap" }, children: [
10712
+ /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(Input, { icon: "magnifying-glass", placeholder: "Find a feature or a piece of backend work", value: q, onChange: (e) => setQ(e.target.value), style: { width: 300 } }),
10713
+ /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(Select, { placeholder: "All projects", value: project, onChange: (e) => setProject(e.target.value), options: projects, style: { width: 190 } }),
10714
+ /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("span", { style: { flex: 1 } }),
10715
+ /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(
10468
10716
  Button,
10469
10717
  {
10470
10718
  size: "sm",
@@ -10478,7 +10726,7 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
10478
10726
  }
10479
10727
  )
10480
10728
  ] }),
10481
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(
10729
+ /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(
10482
10730
  Flag,
10483
10731
  {
10484
10732
  tone: "info",
@@ -10487,60 +10735,60 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
10487
10735
  actions: null
10488
10736
  }
10489
10737
  ),
10490
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)("div", { className: "fd-rm", children: /* @__PURE__ */ (0, import_jsx_runtime79.jsx)("div", { className: "fd-rm-scroll", ref: scrollRef, children: /* @__PURE__ */ (0, import_jsx_runtime79.jsxs)("div", { className: "fd-rm-track", children: [
10491
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)("span", { className: "fd-rm-spine", children: /* @__PURE__ */ (0, import_jsx_runtime79.jsx)("span", { className: "fd-rm-spine-done", style: { height: items.length ? 100 * shippedShown / items.length + "%" : "0%" } }) }),
10738
+ /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("div", { className: "fd-rm", children: /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("div", { className: "fd-rm-scroll", ref: scrollRef, children: /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("div", { className: "fd-rm-track", children: [
10739
+ /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("span", { className: "fd-rm-spine", children: /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("span", { className: "fd-rm-spine-done", style: { height: items.length ? 100 * shippedShown / items.length + "%" : "0%" } }) }),
10492
10740
  items.map((item, n) => {
10493
10741
  const showPhase = item.phase !== lastPhase;
10494
10742
  lastPhase = item.phase;
10495
10743
  const inPhase = items.filter((i) => i.phase === item.phase).length;
10496
10744
  const isBoundary = n === firstPending;
10497
- return /* @__PURE__ */ (0, import_jsx_runtime79.jsxs)(React53.Fragment, { children: [
10498
- showPhase ? /* @__PURE__ */ (0, import_jsx_runtime79.jsxs)("div", { className: "fd-rm-era", children: [
10499
- /* @__PURE__ */ (0, import_jsx_runtime79.jsxs)("span", { className: "fd-row", style: { gap: 8, flexWrap: "wrap", alignItems: "baseline" }, children: [
10500
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)("span", { style: { fontWeight: 700 }, children: item.phase === 0 ? "Shipped" : "Phase " + item.phase + " \u2014 " + item.phaseName }),
10501
- item.phase === 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime79.jsxs)("span", { className: "fd-mono", style: { opacity: 0.7, fontWeight: 400 }, children: [
10745
+ return /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)(React54.Fragment, { children: [
10746
+ showPhase ? /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("div", { className: "fd-rm-era", children: [
10747
+ /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("span", { className: "fd-row", style: { gap: 8, flexWrap: "wrap", alignItems: "baseline" }, children: [
10748
+ /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("span", { style: { fontWeight: 700 }, children: item.phase === 0 ? "Shipped" : "Phase " + item.phase + " \u2014 " + item.phaseName }),
10749
+ item.phase === 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("span", { className: "fd-mono", style: { opacity: 0.7, fontWeight: 400 }, children: [
10502
10750
  fmtDate(item.phaseStart),
10503
10751
  " \u2013 ",
10504
10752
  fmtDate(item.date)
10505
10753
  ] }),
10506
- /* @__PURE__ */ (0, import_jsx_runtime79.jsxs)("span", { style: { opacity: 0.7, fontWeight: 400 }, children: [
10754
+ /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("span", { style: { opacity: 0.7, fontWeight: 400 }, children: [
10507
10755
  "\xB7 ",
10508
10756
  inPhase,
10509
10757
  " feature",
10510
10758
  inPhase === 1 ? "" : "s"
10511
10759
  ] })
10512
10760
  ] }),
10513
- item.phaseWhy ? /* @__PURE__ */ (0, import_jsx_runtime79.jsx)("p", { className: "fd-rm-era-why", children: item.phaseWhy }) : null
10761
+ item.phaseWhy ? /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("p", { className: "fd-rm-era-why", children: item.phaseWhy }) : null
10514
10762
  ] }) : null,
10515
- isBoundary ? /* @__PURE__ */ (0, import_jsx_runtime79.jsx)("div", { className: "fd-rm-now", ref: nowRef, children: /* @__PURE__ */ (0, import_jsx_runtime79.jsxs)("span", { className: "fd-rm-now-pill", children: [
10516
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)("i", { className: "ph ph-map-pin" }),
10763
+ isBoundary ? /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("div", { className: "fd-rm-now", ref: nowRef, children: /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("span", { className: "fd-rm-now-pill", children: [
10764
+ /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("i", { className: "ph ph-map-pin" }),
10517
10765
  " You are here \u2014 everything above is wired"
10518
10766
  ] }) }) : null,
10519
- /* @__PURE__ */ (0, import_jsx_runtime79.jsxs)("div", { className: "fd-rm-row", children: [
10520
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)("span", { className: "fd-rm-dot " + (item.implemented ? "is-shipped" : item.status === "next" ? "is-next" : "") }),
10521
- /* @__PURE__ */ (0, import_jsx_runtime79.jsxs)("div", { className: "fd-rm-date", children: [
10767
+ /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("div", { className: "fd-rm-row", children: [
10768
+ /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("span", { className: "fd-rm-dot " + (item.implemented ? "is-shipped" : item.status === "next" ? "is-next" : "") }),
10769
+ /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("div", { className: "fd-rm-date", children: [
10522
10770
  fmtDate(item.date),
10523
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)("br", {}),
10524
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)("span", { style: { opacity: 0.75 }, children: item.implemented ? "shipped" : "phase " + item.phase })
10771
+ /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("br", {}),
10772
+ /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("span", { style: { opacity: 0.75 }, children: item.implemented ? "shipped" : "phase " + item.phase })
10525
10773
  ] }),
10526
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(RoadmapCard, { item, byKey, onOpenFlag })
10774
+ /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(RoadmapCard, { item, byKey, onOpenFlag })
10527
10775
  ] })
10528
10776
  ] }, item.key);
10529
10777
  }),
10530
- !items.length ? /* @__PURE__ */ (0, import_jsx_runtime79.jsx)("p", { className: "fd-body-sm fd-muted", children: "Nothing matches that filter." }) : null
10778
+ !items.length ? /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("p", { className: "fd-body-sm fd-muted", children: "Nothing matches that filter." }) : null
10531
10779
  ] }) }) }),
10532
- /* @__PURE__ */ (0, import_jsx_runtime79.jsxs)("p", { className: "fd-body-sm fd-muted", style: { margin: 0 }, children: [
10780
+ /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("p", { className: "fd-body-sm fd-muted", style: { margin: 0 }, children: [
10533
10781
  "Derived from the feature-flag registry \u2014 each entry's status is its flag's ",
10534
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)("code", { className: "fd-mono", children: "implemented" }),
10782
+ /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("code", { className: "fd-mono", children: "implemented" }),
10535
10783
  " field, so this page cannot drift from what the apps actually do."
10536
10784
  ] })
10537
10785
  ] });
10538
10786
  }
10539
10787
 
10540
10788
  // src/components/platform/ComingSoon.tsx
10541
- var React54 = __toESM(require("react"), 1);
10789
+ var React55 = __toESM(require("react"), 1);
10542
10790
  var import_react_dom6 = require("react-dom");
10543
- var import_jsx_runtime80 = require("react/jsx-runtime");
10791
+ var import_jsx_runtime81 = require("react/jsx-runtime");
10544
10792
  var BYPASS_STORE = "fd.soon.bypass.v1";
10545
10793
  function readBypassed() {
10546
10794
  try {
@@ -10556,8 +10804,8 @@ function writeBypassed(list) {
10556
10804
  }
10557
10805
  }
10558
10806
  function useBypass(key) {
10559
- const [on, setOn] = React54.useState(() => !!key && readBypassed().indexOf(key) >= 0);
10560
- React54.useEffect(() => {
10807
+ const [on, setOn] = React55.useState(() => !!key && readBypassed().indexOf(key) >= 0);
10808
+ React55.useEffect(() => {
10561
10809
  setOn(!!key && readBypassed().indexOf(key) >= 0);
10562
10810
  }, [key]);
10563
10811
  const set = (next) => {
@@ -10570,43 +10818,43 @@ function useBypass(key) {
10570
10818
  return [on, set];
10571
10819
  }
10572
10820
  function SoonCard({ label, detail, backend, eta, effort, onRoadmap, allowed, onBypass }) {
10573
- return /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)(import_jsx_runtime80.Fragment, { children: [
10574
- /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("span", { className: "fd-soon-badge", children: [
10575
- /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" }),
10821
+ return /* @__PURE__ */ (0, import_jsx_runtime81.jsxs)(import_jsx_runtime81.Fragment, { children: [
10822
+ /* @__PURE__ */ (0, import_jsx_runtime81.jsxs)("span", { className: "fd-soon-badge", children: [
10823
+ /* @__PURE__ */ (0, import_jsx_runtime81.jsx)("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" }),
10576
10824
  label
10577
10825
  ] }),
10578
- detail ? /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("span", { className: "fd-soon-detail", children: detail }) : null,
10579
- backend ? /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("span", { className: "fd-soon-backend", children: [
10580
- /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("span", { className: "fd-overline", children: "Needs" }),
10826
+ detail ? /* @__PURE__ */ (0, import_jsx_runtime81.jsx)("span", { className: "fd-soon-detail", children: detail }) : null,
10827
+ backend ? /* @__PURE__ */ (0, import_jsx_runtime81.jsxs)("span", { className: "fd-soon-backend", children: [
10828
+ /* @__PURE__ */ (0, import_jsx_runtime81.jsx)("span", { className: "fd-overline", children: "Needs" }),
10581
10829
  " ",
10582
10830
  backend
10583
10831
  ] }) : null,
10584
- eta || effort || onRoadmap ? /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("span", { className: "fd-soon-meta", children: [
10585
- eta ? /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("span", { children: [
10586
- /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("i", { className: "ph ph-calendar-blank", "aria-hidden": "true" }),
10832
+ eta || effort || onRoadmap ? /* @__PURE__ */ (0, import_jsx_runtime81.jsxs)("span", { className: "fd-soon-meta", children: [
10833
+ eta ? /* @__PURE__ */ (0, import_jsx_runtime81.jsxs)("span", { children: [
10834
+ /* @__PURE__ */ (0, import_jsx_runtime81.jsx)("i", { className: "ph ph-calendar-blank", "aria-hidden": "true" }),
10587
10835
  " ",
10588
10836
  eta
10589
10837
  ] }) : null,
10590
- effort ? /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("span", { children: [
10591
- /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("i", { className: "ph ph-hourglass-medium", "aria-hidden": "true" }),
10838
+ effort ? /* @__PURE__ */ (0, import_jsx_runtime81.jsxs)("span", { children: [
10839
+ /* @__PURE__ */ (0, import_jsx_runtime81.jsx)("i", { className: "ph ph-hourglass-medium", "aria-hidden": "true" }),
10592
10840
  " ",
10593
10841
  effort
10594
10842
  ] }) : null,
10595
- onRoadmap ? /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("button", { type: "button", className: "fd-soon-link", onClick: onRoadmap, children: [
10843
+ onRoadmap ? /* @__PURE__ */ (0, import_jsx_runtime81.jsxs)("button", { type: "button", className: "fd-soon-link", onClick: onRoadmap, children: [
10596
10844
  "See the roadmap ",
10597
- /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("i", { className: "ph ph-arrow-right", "aria-hidden": "true" })
10845
+ /* @__PURE__ */ (0, import_jsx_runtime81.jsx)("i", { className: "ph ph-arrow-right", "aria-hidden": "true" })
10598
10846
  ] }) : null
10599
10847
  ] }) : null,
10600
- allowed ? /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("button", { type: "button", className: "fd-soon-view", onClick: onBypass, children: [
10601
- /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("i", { className: "ph ph-eye", "aria-hidden": "true" }),
10848
+ allowed ? /* @__PURE__ */ (0, import_jsx_runtime81.jsxs)("button", { type: "button", className: "fd-soon-view", onClick: onBypass, children: [
10849
+ /* @__PURE__ */ (0, import_jsx_runtime81.jsx)("i", { className: "ph ph-eye", "aria-hidden": "true" }),
10602
10850
  " View and use it anyway"
10603
10851
  ] }) : null
10604
10852
  ] });
10605
10853
  }
10606
10854
  function useHoverCard(open2) {
10607
- const anchor = React54.useRef(null);
10608
- const [pos, setPos] = React54.useState(null);
10609
- React54.useLayoutEffect(() => {
10855
+ const anchor = React55.useRef(null);
10856
+ const [pos, setPos] = React55.useState(null);
10857
+ React55.useLayoutEffect(() => {
10610
10858
  if (!open2 || !anchor.current) {
10611
10859
  setPos(null);
10612
10860
  return;
@@ -10658,9 +10906,9 @@ function ComingSoon({
10658
10906
  const tip = [label, detail, backend ? "Needs " + backend : null, eta ? "ETA " + eta : null, effort].filter(Boolean).join(" \xB7 ");
10659
10907
  if (inline) {
10660
10908
  if (allowed && bypassed) {
10661
- return /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("span", { className: ["fd-soon-inline-on", className].filter(Boolean).join(" "), ...rest, children: [
10909
+ return /* @__PURE__ */ (0, import_jsx_runtime81.jsxs)("span", { className: ["fd-soon-inline-on", className].filter(Boolean).join(" "), ...rest, children: [
10662
10910
  children,
10663
- /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(
10911
+ /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(
10664
10912
  "button",
10665
10913
  {
10666
10914
  type: "button",
@@ -10668,12 +10916,12 @@ function ComingSoon({
10668
10916
  title: "Unwired \u2014 writes go to the simulated backend. " + tip + " Click to re-blur.",
10669
10917
  onClick: () => setBypassed(false),
10670
10918
  "aria-label": "Re-blur this unwired feature",
10671
- children: /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" })
10919
+ children: /* @__PURE__ */ (0, import_jsx_runtime81.jsx)("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" })
10672
10920
  }
10673
10921
  )
10674
10922
  ] });
10675
10923
  }
10676
- return /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(
10924
+ return /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(
10677
10925
  InlineSoon,
10678
10926
  {
10679
10927
  label,
@@ -10693,20 +10941,20 @@ function ComingSoon({
10693
10941
  );
10694
10942
  }
10695
10943
  if (allowed && bypassed) {
10696
- return /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 14 }, ...rest, children: [
10697
- /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("div", { className: "fd-soon-bar", role: "status", children: [
10698
- /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("span", { className: "fd-soon-badge", children: [
10699
- /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" }),
10944
+ return /* @__PURE__ */ (0, import_jsx_runtime81.jsxs)("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 14 }, ...rest, children: [
10945
+ /* @__PURE__ */ (0, import_jsx_runtime81.jsxs)("div", { className: "fd-soon-bar", role: "status", children: [
10946
+ /* @__PURE__ */ (0, import_jsx_runtime81.jsxs)("span", { className: "fd-soon-badge", children: [
10947
+ /* @__PURE__ */ (0, import_jsx_runtime81.jsx)("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" }),
10700
10948
  "Unwired feature \u2014 you are using it anyway"
10701
10949
  ] }),
10702
- /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("span", { className: "fd-soon-bar-detail", children: "Every action here writes to the simulated backend, so nothing you do persists beyond this session." }),
10703
- /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("span", { className: "fd-soon-bar-actions", children: [
10704
- onRoadmap ? /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("button", { type: "button", className: "fd-soon-link", onClick: onRoadmap, children: [
10950
+ /* @__PURE__ */ (0, import_jsx_runtime81.jsx)("span", { className: "fd-soon-bar-detail", children: "Every action here writes to the simulated backend, so nothing you do persists beyond this session." }),
10951
+ /* @__PURE__ */ (0, import_jsx_runtime81.jsxs)("span", { className: "fd-soon-bar-actions", children: [
10952
+ onRoadmap ? /* @__PURE__ */ (0, import_jsx_runtime81.jsxs)("button", { type: "button", className: "fd-soon-link", onClick: onRoadmap, children: [
10705
10953
  "Roadmap ",
10706
- /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("i", { className: "ph ph-arrow-right", "aria-hidden": "true" })
10954
+ /* @__PURE__ */ (0, import_jsx_runtime81.jsx)("i", { className: "ph ph-arrow-right", "aria-hidden": "true" })
10707
10955
  ] }) : null,
10708
- /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("button", { type: "button", className: "fd-soon-link", onClick: () => setBypassed(false), children: [
10709
- /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("i", { className: "ph ph-eye-slash", "aria-hidden": "true" }),
10956
+ /* @__PURE__ */ (0, import_jsx_runtime81.jsxs)("button", { type: "button", className: "fd-soon-link", onClick: () => setBypassed(false), children: [
10957
+ /* @__PURE__ */ (0, import_jsx_runtime81.jsx)("i", { className: "ph ph-eye-slash", "aria-hidden": "true" }),
10710
10958
  " Re-blur"
10711
10959
  ] })
10712
10960
  ] })
@@ -10714,10 +10962,10 @@ function ComingSoon({
10714
10962
  children
10715
10963
  ] });
10716
10964
  }
10717
- return /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("div", { className: ["fd-soon", className].filter(Boolean).join(" "), style: minHeight ? { minHeight } : void 0, ...rest, children: [
10718
- /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("div", { className: "fd-soon-under", style: { filter: "blur(" + blur + "px) saturate(.62)" }, ...{ inert: "" }, "aria-hidden": "true", children }),
10719
- /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("div", { className: "fd-soon-veil" }),
10720
- /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("div", { className: "fd-soon-note", role: "note", children: /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(
10965
+ return /* @__PURE__ */ (0, import_jsx_runtime81.jsxs)("div", { className: ["fd-soon", className].filter(Boolean).join(" "), style: minHeight ? { minHeight } : void 0, ...rest, children: [
10966
+ /* @__PURE__ */ (0, import_jsx_runtime81.jsx)("div", { className: "fd-soon-under", style: { filter: "blur(" + blur + "px) saturate(.62)" }, ...{ inert: "" }, "aria-hidden": "true", children }),
10967
+ /* @__PURE__ */ (0, import_jsx_runtime81.jsx)("div", { className: "fd-soon-veil" }),
10968
+ /* @__PURE__ */ (0, import_jsx_runtime81.jsx)("div", { className: "fd-soon-note", role: "note", children: /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(
10721
10969
  SoonCard,
10722
10970
  {
10723
10971
  label,
@@ -10733,10 +10981,12 @@ function ComingSoon({
10733
10981
  ] });
10734
10982
  }
10735
10983
  function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, onBypass, blur, tip, className, rest, children }) {
10736
- const [open2, setOpen] = React54.useState(false);
10984
+ const [open2, setOpen] = React55.useState(false);
10737
10985
  const [anchor, pos] = useHoverCard(open2);
10738
- const zIndex = useOverlayLayer(open2);
10739
- const close2 = React54.useRef(null);
10986
+ const hoverCardRef = React55.useRef(null);
10987
+ const hoverLayer = useStackedLayer({ active: open2, containerRef: hoverCardRef, returnFocus: false });
10988
+ const zIndex = useLayerZIndex(hoverLayer);
10989
+ const close2 = React55.useRef(null);
10740
10990
  const show = () => {
10741
10991
  if (close2.current) {
10742
10992
  clearTimeout(close2.current);
@@ -10752,10 +11002,10 @@ function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, o
10752
11002
  setOpen(false);
10753
11003
  }, 140);
10754
11004
  };
10755
- React54.useEffect(() => () => {
11005
+ React55.useEffect(() => () => {
10756
11006
  if (close2.current) clearTimeout(close2.current);
10757
11007
  }, []);
10758
- return /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)(
11008
+ return /* @__PURE__ */ (0, import_jsx_runtime81.jsxs)(
10759
11009
  "span",
10760
11010
  {
10761
11011
  ref: anchor,
@@ -10766,8 +11016,8 @@ function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, o
10766
11016
  onBlur: hide,
10767
11017
  ...rest,
10768
11018
  children: [
10769
- /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("span", { className: "fd-soon-under", style: { filter: "blur(" + Math.min(blur, 1.1) + "px) saturate(.66)" }, ...{ inert: "" }, "aria-hidden": "true", children }),
10770
- /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(
11019
+ /* @__PURE__ */ (0, import_jsx_runtime81.jsx)("span", { className: "fd-soon-under", style: { filter: "blur(" + Math.min(blur, 1.1) + "px) saturate(.66)" }, ...{ inert: "" }, "aria-hidden": "true", children }),
11020
+ /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(
10771
11021
  "button",
10772
11022
  {
10773
11023
  type: "button",
@@ -10778,19 +11028,20 @@ function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, o
10778
11028
  onFocus: show,
10779
11029
  onBlur: hide,
10780
11030
  onClick: () => open2 ? setOpen(false) : show(),
10781
- children: /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" })
11031
+ children: /* @__PURE__ */ (0, import_jsx_runtime81.jsx)("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" })
10782
11032
  }
10783
11033
  ),
10784
11034
  open2 && pos ? (0, import_react_dom6.createPortal)(
10785
- /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(LayerProvider, { zIndex, children: /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(
11035
+ /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(
10786
11036
  "div",
10787
11037
  {
11038
+ ref: hoverCardRef,
10788
11039
  className: "fd-soon-note fd-soon-hovercard",
10789
11040
  role: "tooltip",
10790
11041
  style: { position: "fixed", left: pos.left, top: pos.top, bottom: pos.bottom, width: pos.width, zIndex },
10791
11042
  onMouseEnter: show,
10792
11043
  onMouseLeave: hide,
10793
- children: /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(
11044
+ children: /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(
10794
11045
  SoonCard,
10795
11046
  {
10796
11047
  label,
@@ -10804,7 +11055,7 @@ function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, o
10804
11055
  }
10805
11056
  )
10806
11057
  }
10807
- ) }),
11058
+ ),
10808
11059
  document.body
10809
11060
  ) : null
10810
11061
  ]
@@ -10820,10 +11071,10 @@ function formatEta(iso2) {
10820
11071
  var FormatEta = formatEta;
10821
11072
 
10822
11073
  // src/components/platform/Gate.tsx
10823
- var import_jsx_runtime81 = require("react/jsx-runtime");
11074
+ var import_jsx_runtime82 = require("react/jsx-runtime");
10824
11075
  function PermissionDenied({ permission, title, detail, compact: compact3 = false, className = "", ...rest }) {
10825
11076
  const need = Array.isArray(permission) ? permission : [permission].filter(Boolean);
10826
- return /* @__PURE__ */ (0, import_jsx_runtime81.jsxs)(
11077
+ return /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)(
10827
11078
  "div",
10828
11079
  {
10829
11080
  className: ["fd-stack", className].filter(Boolean).join(" "),
@@ -10839,14 +11090,14 @@ function PermissionDenied({ permission, title, detail, compact: compact3 = false
10839
11090
  },
10840
11091
  ...rest,
10841
11092
  children: [
10842
- /* @__PURE__ */ (0, import_jsx_runtime81.jsxs)("span", { className: "fd-row", style: { gap: 8 }, children: [
10843
- /* @__PURE__ */ (0, import_jsx_runtime81.jsx)("i", { className: "ph ph-lock-simple", style: { fontSize: 16, color: "var(--text-muted)" }, "aria-hidden": "true" }),
10844
- /* @__PURE__ */ (0, import_jsx_runtime81.jsx)("span", { className: compact3 ? "fd-label-lg" : "fd-h3", children: title || "You do not have access to this" })
11093
+ /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)("span", { className: "fd-row", style: { gap: 8 }, children: [
11094
+ /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("i", { className: "ph ph-lock-simple", style: { fontSize: 16, color: "var(--text-muted)" }, "aria-hidden": "true" }),
11095
+ /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("span", { className: compact3 ? "fd-label-lg" : "fd-h3", children: title || "You do not have access to this" })
10845
11096
  ] }),
10846
- /* @__PURE__ */ (0, import_jsx_runtime81.jsx)("p", { className: "fd-body-sm fd-secondary", style: { margin: 0, textWrap: "pretty" }, children: detail || "Your roles do not grant this. An administrator can change that from Admin \u2192 Users." }),
10847
- need.length ? /* @__PURE__ */ (0, import_jsx_runtime81.jsxs)("span", { className: "fd-row", style: { gap: 6, flexWrap: "wrap" }, children: [
10848
- /* @__PURE__ */ (0, import_jsx_runtime81.jsx)("span", { className: "fd-overline fd-muted", children: "Requires" }),
10849
- need.map((p) => /* @__PURE__ */ (0, import_jsx_runtime81.jsx)("code", { className: "fd-mono", style: {
11097
+ /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("p", { className: "fd-body-sm fd-secondary", style: { margin: 0, textWrap: "pretty" }, children: detail || "Your roles do not grant this. An administrator can change that from Admin \u2192 Users." }),
11098
+ need.length ? /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)("span", { className: "fd-row", style: { gap: 6, flexWrap: "wrap" }, children: [
11099
+ /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("span", { className: "fd-overline fd-muted", children: "Requires" }),
11100
+ need.map((p) => /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("code", { className: "fd-mono", style: {
10850
11101
  fontSize: 11.5,
10851
11102
  padding: "2px 7px",
10852
11103
  borderRadius: 5,
@@ -10859,7 +11110,7 @@ function PermissionDenied({ permission, title, detail, compact: compact3 = false
10859
11110
  );
10860
11111
  }
10861
11112
  function GatePending({ compact: compact3 = false, className = "" }) {
10862
- return /* @__PURE__ */ (0, import_jsx_runtime81.jsxs)(
11113
+ return /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)(
10863
11114
  "div",
10864
11115
  {
10865
11116
  className: ["fd-stack", className].filter(Boolean).join(" "),
@@ -10875,11 +11126,11 @@ function GatePending({ compact: compact3 = false, className = "" }) {
10875
11126
  textAlign: "left"
10876
11127
  },
10877
11128
  children: [
10878
- /* @__PURE__ */ (0, import_jsx_runtime81.jsxs)("span", { className: "fd-row", style: { gap: 8 }, children: [
10879
- /* @__PURE__ */ (0, import_jsx_runtime81.jsx)("i", { className: "ph ph-arrows-clockwise", style: { fontSize: 16, color: "var(--text-muted)" }, "aria-hidden": "true" }),
10880
- /* @__PURE__ */ (0, import_jsx_runtime81.jsx)("span", { className: compact3 ? "fd-label-lg" : "fd-h3", children: "Reconnecting\u2026" })
11129
+ /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)("span", { className: "fd-row", style: { gap: 8 }, children: [
11130
+ /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("i", { className: "ph ph-arrows-clockwise", style: { fontSize: 16, color: "var(--text-muted)" }, "aria-hidden": "true" }),
11131
+ /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("span", { className: compact3 ? "fd-label-lg" : "fd-h3", children: "Reconnecting\u2026" })
10881
11132
  ] }),
10882
- /* @__PURE__ */ (0, import_jsx_runtime81.jsx)("p", { className: "fd-body-sm fd-secondary", style: { margin: 0, textWrap: "pretty" }, children: "Your access can't be verified right now. This will resolve on its own once the connection is back." })
11133
+ /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("p", { className: "fd-body-sm fd-secondary", style: { margin: 0, textWrap: "pretty" }, children: "Your access can't be verified right now. This will resolve on its own once the connection is back." })
10883
11134
  ]
10884
11135
  }
10885
11136
  );
@@ -10889,7 +11140,7 @@ function Gate({ perm, anyOf, role, silent = false, fallback, pendingFallback, co
10889
11140
  if (pending) {
10890
11141
  if (pendingFallback !== void 0) return pendingFallback;
10891
11142
  if (silent) return null;
10892
- return /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(GatePending, { compact: compact3 });
11143
+ return /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(GatePending, { compact: compact3 });
10893
11144
  }
10894
11145
  let ok = true;
10895
11146
  if (perm) ok = ok && can2(perm);
@@ -10898,7 +11149,7 @@ function Gate({ perm, anyOf, role, silent = false, fallback, pendingFallback, co
10898
11149
  if (ok) return children;
10899
11150
  if (fallback !== void 0) return fallback;
10900
11151
  if (silent) return null;
10901
- return /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(PermissionDenied, { permission: perm || anyOf, compact: compact3 });
11152
+ return /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(PermissionDenied, { permission: perm || anyOf, compact: compact3 });
10902
11153
  }
10903
11154
  function FeatureGate({
10904
11155
  flag,
@@ -10921,7 +11172,7 @@ function FeatureGate({
10921
11172
  const f = SessionKit.findFlag(flag) || {};
10922
11173
  const missing = rt.missing || [];
10923
11174
  const canBypass = pending ? false : bypassPerm === null ? false : !bypassPerm || can2(bypassPerm);
10924
- return /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(
11175
+ return /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(
10925
11176
  ComingSoon,
10926
11177
  {
10927
11178
  label: label || (variant === "inline" ? f.label || "Not wired yet" : "Designed \u2014 backend not wired yet"),
@@ -10942,22 +11193,22 @@ function FeatureGate({
10942
11193
  function PermissionHint({ perm, children }) {
10943
11194
  const { can: can2, pending } = useSessionContext();
10944
11195
  if (pending) {
10945
- return /* @__PURE__ */ (0, import_jsx_runtime81.jsx)("span", { title: "Access can't be verified right now", style: { display: "inline-flex", opacity: 0.45, cursor: "not-allowed" }, "aria-disabled": "true", children: /* @__PURE__ */ (0, import_jsx_runtime81.jsx)("span", { style: { pointerEvents: "none" }, children }) });
11196
+ return /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("span", { title: "Access can't be verified right now", style: { display: "inline-flex", opacity: 0.45, cursor: "not-allowed" }, "aria-disabled": "true", children: /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("span", { style: { pointerEvents: "none" }, children }) });
10946
11197
  }
10947
11198
  if (can2(perm)) return children;
10948
- return /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(
11199
+ return /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(
10949
11200
  "span",
10950
11201
  {
10951
11202
  title: "Requires " + (Array.isArray(perm) ? perm.join(", ") : perm),
10952
11203
  style: { display: "inline-flex", opacity: 0.45, cursor: "not-allowed" },
10953
11204
  "aria-disabled": "true",
10954
- children: /* @__PURE__ */ (0, import_jsx_runtime81.jsx)("span", { style: { pointerEvents: "none" }, children })
11205
+ children: /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("span", { style: { pointerEvents: "none" }, children })
10955
11206
  }
10956
11207
  );
10957
11208
  }
10958
11209
 
10959
11210
  // src/components/platform/ModeSwitch.tsx
10960
- var import_jsx_runtime82 = require("react/jsx-runtime");
11211
+ var import_jsx_runtime83 = require("react/jsx-runtime");
10961
11212
  function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog, onOpenSpec, summary }) {
10962
11213
  const mode2 = useRuntimeMode();
10963
11214
  const panel = useInlinePanel();
@@ -10969,8 +11220,8 @@ function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog
10969
11220
  RuntimeKit.setMode(next);
10970
11221
  setOpen(false);
10971
11222
  };
10972
- return /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)("span", { style: { position: "relative", display: "inline-flex" }, ref, children: [
10973
- /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)(
11223
+ return /* @__PURE__ */ (0, import_jsx_runtime83.jsxs)("span", { style: { position: "relative", display: "inline-flex" }, ref, children: [
11224
+ /* @__PURE__ */ (0, import_jsx_runtime83.jsxs)(
10974
11225
  "button",
10975
11226
  {
10976
11227
  type: "button",
@@ -10980,29 +11231,29 @@ function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog
10980
11231
  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.",
10981
11232
  className: "fd-mode-btn" + (test ? " is-test" : "") + (open2 ? " is-open" : ""),
10982
11233
  children: [
10983
- /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("i", { className: "ph " + (test ? "ph-flask" : "ph-lightning"), style: { fontSize: 17 } }),
10984
- test && requestCount ? /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("span", { className: "fd-mono fd-mode-count", children: requestCount > 99 ? "99+" : requestCount }, requestCount) : null
11234
+ /* @__PURE__ */ (0, import_jsx_runtime83.jsx)("i", { className: "ph " + (test ? "ph-flask" : "ph-lightning"), style: { fontSize: 17 } }),
11235
+ test && requestCount ? /* @__PURE__ */ (0, import_jsx_runtime83.jsx)("span", { className: "fd-mono fd-mode-count", children: requestCount > 99 ? "99+" : requestCount }, requestCount) : null
10985
11236
  ]
10986
11237
  }
10987
11238
  ),
10988
- open2 ? /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(InlinePanelLayers, { panel, children: /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)("span", { className: "fd-view-enter fd-mode-pop", style: { zIndex }, children: [
10989
- /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)("span", { className: "fd-row", style: { gap: 10, padding: "12px 14px", borderBottom: "1px solid var(--border)" }, children: [
10990
- /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)("span", { className: "fd-badge " + (test ? "fd-badge-warning" : "fd-badge-neutral"), children: [
10991
- /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("i", { className: "ph " + (test ? "ph-flask" : "ph-lightning"), "aria-hidden": "true" }),
11239
+ open2 ? /* @__PURE__ */ (0, import_jsx_runtime83.jsx)(InlinePanelLayers, { panel, children: /* @__PURE__ */ (0, import_jsx_runtime83.jsxs)("span", { className: "fd-view-enter fd-mode-pop", style: { zIndex }, children: [
11240
+ /* @__PURE__ */ (0, import_jsx_runtime83.jsxs)("span", { className: "fd-row", style: { gap: 10, padding: "12px 14px", borderBottom: "1px solid var(--border)" }, children: [
11241
+ /* @__PURE__ */ (0, import_jsx_runtime83.jsxs)("span", { className: "fd-badge " + (test ? "fd-badge-warning" : "fd-badge-neutral"), children: [
11242
+ /* @__PURE__ */ (0, import_jsx_runtime83.jsx)("i", { className: "ph " + (test ? "ph-flask" : "ph-lightning"), "aria-hidden": "true" }),
10992
11243
  test ? "Test mode" : "Live mode"
10993
11244
  ] }),
10994
- test ? /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)("span", { className: "fd-body-sm fd-muted fd-mono", children: [
11245
+ test ? /* @__PURE__ */ (0, import_jsx_runtime83.jsxs)("span", { className: "fd-body-sm fd-muted fd-mono", children: [
10995
11246
  requestCount,
10996
11247
  " simulated request",
10997
11248
  requestCount === 1 ? "" : "s"
10998
11249
  ] }) : null,
10999
- /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("span", { style: { flex: 1 } }),
11000
- test && onClearLog ? /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("button", { type: "button", className: "fd-soon-link", onClick: onClearLog, children: "Clear" }) : null
11250
+ /* @__PURE__ */ (0, import_jsx_runtime83.jsx)("span", { style: { flex: 1 } }),
11251
+ test && onClearLog ? /* @__PURE__ */ (0, import_jsx_runtime83.jsx)("button", { type: "button", className: "fd-soon-link", onClick: onClearLog, children: "Clear" }) : null
11001
11252
  ] }),
11002
- /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)("span", { style: { display: "block", padding: "12px 14px", borderBottom: "1px solid var(--border)" }, children: [
11003
- /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("span", { className: "fd-body-sm fd-secondary", style: { display: "block", textWrap: "pretty" }, children: test ? "Every feature is usable and nothing is obstructed, but no response comes from a real service \u2014 nothing you do here persists. Use this to review and demo the design." : "This is what a user would see today. " + s.incomplete + " of " + s.total + " features depend on backend work that is not wired yet, so they render under construction." }),
11004
- /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)("span", { className: "fd-row", style: { gap: 8, marginTop: 10, flexWrap: "wrap" }, children: [
11005
- /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)("span", { className: "fd-body-sm fd-muted fd-mono", children: [
11253
+ /* @__PURE__ */ (0, import_jsx_runtime83.jsxs)("span", { style: { display: "block", padding: "12px 14px", borderBottom: "1px solid var(--border)" }, children: [
11254
+ /* @__PURE__ */ (0, import_jsx_runtime83.jsx)("span", { className: "fd-body-sm fd-secondary", style: { display: "block", textWrap: "pretty" }, children: test ? "Every feature is usable and nothing is obstructed, but no response comes from a real service \u2014 nothing you do here persists. Use this to review and demo the design." : "This is what a user would see today. " + s.incomplete + " of " + s.total + " features depend on backend work that is not wired yet, so they render under construction." }),
11255
+ /* @__PURE__ */ (0, import_jsx_runtime83.jsxs)("span", { className: "fd-row", style: { gap: 8, marginTop: 10, flexWrap: "wrap" }, children: [
11256
+ /* @__PURE__ */ (0, import_jsx_runtime83.jsxs)("span", { className: "fd-body-sm fd-muted fd-mono", children: [
11006
11257
  s.endpointsWired,
11007
11258
  " endpoint",
11008
11259
  s.endpointsWired === 1 ? "" : "s",
@@ -11012,58 +11263,58 @@ function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog
11012
11263
  s.total,
11013
11264
  " features complete"
11014
11265
  ] }),
11015
- onOpenSpec ? /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)(import_jsx_runtime82.Fragment, { children: [
11016
- /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("span", { style: { flex: 1 } }),
11017
- /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)("button", { type: "button", className: "fd-soon-link", onClick: () => {
11266
+ onOpenSpec ? /* @__PURE__ */ (0, import_jsx_runtime83.jsxs)(import_jsx_runtime83.Fragment, { children: [
11267
+ /* @__PURE__ */ (0, import_jsx_runtime83.jsx)("span", { style: { flex: 1 } }),
11268
+ /* @__PURE__ */ (0, import_jsx_runtime83.jsxs)("button", { type: "button", className: "fd-soon-link", onClick: () => {
11018
11269
  setOpen(false);
11019
11270
  onOpenSpec();
11020
11271
  }, children: [
11021
11272
  "API spec ",
11022
- /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("i", { className: "ph ph-arrow-right", "aria-hidden": "true" })
11273
+ /* @__PURE__ */ (0, import_jsx_runtime83.jsx)("i", { className: "ph ph-arrow-right", "aria-hidden": "true" })
11023
11274
  ] })
11024
11275
  ] }) : null
11025
11276
  ] })
11026
11277
  ] }),
11027
- /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)("span", { className: "fd-mode-choice", children: [
11028
- /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)("button", { type: "button", className: "fd-mode-opt" + (!test ? " is-on" : ""), onClick: () => go("live"), children: [
11029
- /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("i", { className: "ph ph-lightning", "aria-hidden": "true" }),
11030
- /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)("span", { className: "fd-mode-opt-text", children: [
11031
- /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("span", { className: "fd-mode-opt-title", children: "Live mode" }),
11032
- /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("span", { className: "fd-mode-opt-desc", children: "Incomplete features under construction" })
11278
+ /* @__PURE__ */ (0, import_jsx_runtime83.jsxs)("span", { className: "fd-mode-choice", children: [
11279
+ /* @__PURE__ */ (0, import_jsx_runtime83.jsxs)("button", { type: "button", className: "fd-mode-opt" + (!test ? " is-on" : ""), onClick: () => go("live"), children: [
11280
+ /* @__PURE__ */ (0, import_jsx_runtime83.jsx)("i", { className: "ph ph-lightning", "aria-hidden": "true" }),
11281
+ /* @__PURE__ */ (0, import_jsx_runtime83.jsxs)("span", { className: "fd-mode-opt-text", children: [
11282
+ /* @__PURE__ */ (0, import_jsx_runtime83.jsx)("span", { className: "fd-mode-opt-title", children: "Live mode" }),
11283
+ /* @__PURE__ */ (0, import_jsx_runtime83.jsx)("span", { className: "fd-mode-opt-desc", children: "Incomplete features under construction" })
11033
11284
  ] }),
11034
- !test ? /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("i", { className: "ph ph-check", "aria-hidden": "true" }) : null
11285
+ !test ? /* @__PURE__ */ (0, import_jsx_runtime83.jsx)("i", { className: "ph ph-check", "aria-hidden": "true" }) : null
11035
11286
  ] }),
11036
- /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)("button", { type: "button", className: "fd-mode-opt" + (test ? " is-on" : ""), onClick: () => go("test"), children: [
11037
- /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("i", { className: "ph ph-flask", "aria-hidden": "true" }),
11038
- /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)("span", { className: "fd-mode-opt-text", children: [
11039
- /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("span", { className: "fd-mode-opt-title", children: "Test mode" }),
11040
- /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("span", { className: "fd-mode-opt-desc", children: "Everything usable, all data simulated" })
11287
+ /* @__PURE__ */ (0, import_jsx_runtime83.jsxs)("button", { type: "button", className: "fd-mode-opt" + (test ? " is-on" : ""), onClick: () => go("test"), children: [
11288
+ /* @__PURE__ */ (0, import_jsx_runtime83.jsx)("i", { className: "ph ph-flask", "aria-hidden": "true" }),
11289
+ /* @__PURE__ */ (0, import_jsx_runtime83.jsxs)("span", { className: "fd-mode-opt-text", children: [
11290
+ /* @__PURE__ */ (0, import_jsx_runtime83.jsx)("span", { className: "fd-mode-opt-title", children: "Test mode" }),
11291
+ /* @__PURE__ */ (0, import_jsx_runtime83.jsx)("span", { className: "fd-mode-opt-desc", children: "Everything usable, all data simulated" })
11041
11292
  ] }),
11042
- test ? /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("i", { className: "ph ph-check", "aria-hidden": "true" }) : null
11293
+ test ? /* @__PURE__ */ (0, import_jsx_runtime83.jsx)("i", { className: "ph ph-check", "aria-hidden": "true" }) : null
11043
11294
  ] })
11044
11295
  ] }),
11045
- test && renderLog ? /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("span", { style: { display: "block", maxHeight: 340, overflowY: "auto", borderTop: "1px solid var(--border)" }, children: renderLog() }) : null
11296
+ test && renderLog ? /* @__PURE__ */ (0, import_jsx_runtime83.jsx)("span", { style: { display: "block", maxHeight: 340, overflowY: "auto", borderTop: "1px solid var(--border)" }, children: renderLog() }) : null
11046
11297
  ] }) }) : null
11047
11298
  ] });
11048
11299
  }
11049
11300
  function TestModeBar({ onExit }) {
11050
11301
  const mode2 = useRuntimeMode();
11051
11302
  if (mode2 !== "test") return null;
11052
- return /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)("div", { className: "fd-testbar", role: "status", children: [
11053
- /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)("span", { className: "fd-badge fd-badge-warning", children: [
11054
- /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("i", { className: "ph ph-flask", "aria-hidden": "true" }),
11303
+ return /* @__PURE__ */ (0, import_jsx_runtime83.jsxs)("div", { className: "fd-testbar", role: "status", children: [
11304
+ /* @__PURE__ */ (0, import_jsx_runtime83.jsxs)("span", { className: "fd-badge fd-badge-warning", children: [
11305
+ /* @__PURE__ */ (0, import_jsx_runtime83.jsx)("i", { className: "ph ph-flask", "aria-hidden": "true" }),
11055
11306
  "Test mode"
11056
11307
  ] }),
11057
- /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("span", { className: "fd-testbar-detail", children: "Every feature is unlocked and every response is simulated \u2014 nothing here persists." }),
11058
- /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)("button", { type: "button", className: "fd-soon-link", onClick: () => onExit ? onExit() : RuntimeKit.setMode("live"), children: [
11059
- /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("i", { className: "ph ph-lightning", "aria-hidden": "true" }),
11308
+ /* @__PURE__ */ (0, import_jsx_runtime83.jsx)("span", { className: "fd-testbar-detail", children: "Every feature is unlocked and every response is simulated \u2014 nothing here persists." }),
11309
+ /* @__PURE__ */ (0, import_jsx_runtime83.jsxs)("button", { type: "button", className: "fd-soon-link", onClick: () => onExit ? onExit() : RuntimeKit.setMode("live"), children: [
11310
+ /* @__PURE__ */ (0, import_jsx_runtime83.jsx)("i", { className: "ph ph-lightning", "aria-hidden": "true" }),
11060
11311
  " Back to live mode"
11061
11312
  ] })
11062
11313
  ] });
11063
11314
  }
11064
11315
 
11065
11316
  // src/components/planner/ChannelMeta.tsx
11066
- var import_jsx_runtime83 = require("react/jsx-runtime");
11317
+ var import_jsx_runtime84 = require("react/jsx-runtime");
11067
11318
  var CHANNEL_WEIGHTS = {
11068
11319
  "OOH": 50,
11069
11320
  "DOOH": 50,
@@ -11116,9 +11367,9 @@ function ChannelTag({ channel, size = "md", showLabel = true, dot = false, weigh
11116
11367
  const m = ChannelMeta(channel);
11117
11368
  const wt = channelWeightOf(channel || "");
11118
11369
  if (dot) {
11119
- return /* @__PURE__ */ (0, import_jsx_runtime83.jsx)("span", { className: ["fd-chan-dot", className].filter(Boolean).join(" "), title: m.name, style: { background: m.color }, ...rest });
11370
+ return /* @__PURE__ */ (0, import_jsx_runtime84.jsx)("span", { className: ["fd-chan-dot", className].filter(Boolean).join(" "), title: m.name, style: { background: m.color }, ...rest });
11120
11371
  }
11121
- return /* @__PURE__ */ (0, import_jsx_runtime83.jsxs)(
11372
+ return /* @__PURE__ */ (0, import_jsx_runtime84.jsxs)(
11122
11373
  "span",
11123
11374
  {
11124
11375
  className: ["fd-chan", size === "sm" ? "fd-chan-sm" : "", className].filter(Boolean).join(" "),
@@ -11126,16 +11377,16 @@ function ChannelTag({ channel, size = "md", showLabel = true, dot = false, weigh
11126
11377
  style: { "--chan": m.color },
11127
11378
  ...rest,
11128
11379
  children: [
11129
- /* @__PURE__ */ (0, import_jsx_runtime83.jsx)("i", { className: "ph ph-" + m.icon, "aria-hidden": "true" }),
11130
- showLabel ? /* @__PURE__ */ (0, import_jsx_runtime83.jsx)("span", { className: "fd-chan-label", children: m.label }) : null,
11131
- weight ? /* @__PURE__ */ (0, import_jsx_runtime83.jsx)("span", { className: "fd-chan-weight", children: wt || 0 }) : null
11380
+ /* @__PURE__ */ (0, import_jsx_runtime84.jsx)("i", { className: "ph ph-" + m.icon, "aria-hidden": "true" }),
11381
+ showLabel ? /* @__PURE__ */ (0, import_jsx_runtime84.jsx)("span", { className: "fd-chan-label", children: m.label }) : null,
11382
+ weight ? /* @__PURE__ */ (0, import_jsx_runtime84.jsx)("span", { className: "fd-chan-weight", children: wt || 0 }) : null
11132
11383
  ]
11133
11384
  }
11134
11385
  );
11135
11386
  }
11136
11387
 
11137
11388
  // src/components/planner/SaturationDistribution.tsx
11138
- var import_jsx_runtime84 = require("react/jsx-runtime");
11389
+ var import_jsx_runtime85 = require("react/jsx-runtime");
11139
11390
  var BANDS2 = [
11140
11391
  { key: "weak", label: "Weak", n: 1, range: "< 50" },
11141
11392
  { key: "adequate", label: "Adequate", n: 2, range: "50\u2013100" },
@@ -11146,24 +11397,24 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
11146
11397
  const grouped = BANDS2.map((b) => ({ ...b, items: campuses.filter((c) => c.band === b.key) }));
11147
11398
  const tallest = Math.max(1, ...grouped.map((g) => g.items.length));
11148
11399
  const floor = BANDS2.find((b) => b.key === floorBand) || BANDS2[0];
11149
- return /* @__PURE__ */ (0, import_jsx_runtime84.jsxs)("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 16 }, children: [
11150
- /* @__PURE__ */ (0, import_jsx_runtime84.jsx)("div", { style: { display: "grid", gridTemplateColumns: "repeat(4,minmax(0,1fr))", gap: 12, alignItems: "end" }, children: grouped.map((g) => {
11400
+ return /* @__PURE__ */ (0, import_jsx_runtime85.jsxs)("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 16 }, children: [
11401
+ /* @__PURE__ */ (0, import_jsx_runtime85.jsx)("div", { style: { display: "grid", gridTemplateColumns: "repeat(4,minmax(0,1fr))", gap: 12, alignItems: "end" }, children: grouped.map((g) => {
11151
11402
  const mark = "var(--csi-" + g.n + "-mark)";
11152
11403
  const active = selectedBand === g.key;
11153
- return /* @__PURE__ */ (0, import_jsx_runtime84.jsxs)(
11404
+ return /* @__PURE__ */ (0, import_jsx_runtime85.jsxs)(
11154
11405
  "button",
11155
11406
  {
11156
11407
  type: "button",
11157
11408
  onClick: onSelectBand ? () => onSelectBand(active ? null : g.key) : void 0,
11158
11409
  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, minWidth: 0, transition: "background var(--dur-fast) var(--ease),border-color var(--dur-fast) var(--ease)" },
11159
11410
  children: [
11160
- /* @__PURE__ */ (0, import_jsx_runtime84.jsx)("span", { style: { display: "flex", flexDirection: "column-reverse", gap: 4, minHeight: tallest * 24, minWidth: 0 }, children: loading ? Array.from({ length: 3 }).map((_, i) => /* @__PURE__ */ (0, import_jsx_runtime84.jsx)("span", { className: "fd-skel", style: { height: 16, borderRadius: 4 } }, i)) : g.items.map((c) => (
11411
+ /* @__PURE__ */ (0, import_jsx_runtime85.jsx)("span", { style: { display: "flex", flexDirection: "column-reverse", gap: 4, minHeight: tallest * 24, minWidth: 0 }, children: loading ? Array.from({ length: 3 }).map((_, i) => /* @__PURE__ */ (0, import_jsx_runtime85.jsx)("span", { className: "fd-skel", style: { height: 16, borderRadius: 4 } }, i)) : g.items.map((c) => (
11161
11412
  // `overflow: hidden` + `white-space: nowrap` only clips once the span
11162
11413
  // actually HAS a bounded width to clip against (see the grid/flex
11163
11414
  // `minWidth: 0` chain above) — `textOverflow: ellipsis` then makes
11164
11415
  // that clip readable instead of a hard cut mid-letter; the full name
11165
11416
  // is still one hover away via `title`.
11166
- /* @__PURE__ */ (0, import_jsx_runtime84.jsx)(
11417
+ /* @__PURE__ */ (0, import_jsx_runtime85.jsx)(
11167
11418
  "span",
11168
11419
  {
11169
11420
  title: c.name + " \xB7 " + c.crp,
@@ -11173,13 +11424,13 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
11173
11424
  c.name
11174
11425
  )
11175
11426
  )) }),
11176
- /* @__PURE__ */ (0, import_jsx_runtime84.jsxs)("span", { className: "fd-row", style: { gap: 8, alignItems: "baseline" }, children: [
11177
- /* @__PURE__ */ (0, import_jsx_runtime84.jsx)("span", { className: "fd-num-hero", style: { fontSize: 30, color: g.items.length ? "var(--text)" : "var(--text-disabled)" }, children: loading ? "\u2013" : g.items.length }),
11178
- /* @__PURE__ */ (0, import_jsx_runtime84.jsx)("span", { className: "fd-meter", style: { gap: 2, color: mark }, "aria-hidden": "true", children: [1, 2, 3, 4].map((i) => /* @__PURE__ */ (0, import_jsx_runtime84.jsx)("span", { className: "fd-meter-seg" + (i <= g.n ? " is-on" : ""), style: { width: 4, height: 9 } }, i)) })
11427
+ /* @__PURE__ */ (0, import_jsx_runtime85.jsxs)("span", { className: "fd-row", style: { gap: 8, alignItems: "baseline" }, children: [
11428
+ /* @__PURE__ */ (0, import_jsx_runtime85.jsx)("span", { className: "fd-num-hero", style: { fontSize: 30, color: g.items.length ? "var(--text)" : "var(--text-disabled)" }, children: loading ? "\u2013" : g.items.length }),
11429
+ /* @__PURE__ */ (0, import_jsx_runtime85.jsx)("span", { className: "fd-meter", style: { gap: 2, color: mark }, "aria-hidden": "true", children: [1, 2, 3, 4].map((i) => /* @__PURE__ */ (0, import_jsx_runtime85.jsx)("span", { className: "fd-meter-seg" + (i <= g.n ? " is-on" : ""), style: { width: 4, height: 9 } }, i)) })
11179
11430
  ] }),
11180
- /* @__PURE__ */ (0, import_jsx_runtime84.jsxs)("span", { className: "fd-stack", style: { gap: 1 }, children: [
11181
- /* @__PURE__ */ (0, import_jsx_runtime84.jsx)("span", { className: "fd-label-lg", children: g.label }),
11182
- /* @__PURE__ */ (0, import_jsx_runtime84.jsxs)("span", { className: "fd-body-sm fd-muted", style: { fontSize: 11.5 }, children: [
11431
+ /* @__PURE__ */ (0, import_jsx_runtime85.jsxs)("span", { className: "fd-stack", style: { gap: 1 }, children: [
11432
+ /* @__PURE__ */ (0, import_jsx_runtime85.jsx)("span", { className: "fd-label-lg", children: g.label }),
11433
+ /* @__PURE__ */ (0, import_jsx_runtime85.jsxs)("span", { className: "fd-body-sm fd-muted", style: { fontSize: 11.5 }, children: [
11183
11434
  "CRP ",
11184
11435
  g.range
11185
11436
  ] })
@@ -11189,10 +11440,10 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
11189
11440
  g.key
11190
11441
  );
11191
11442
  }) }),
11192
- floorBand ? /* @__PURE__ */ (0, import_jsx_runtime84.jsxs)("div", { className: "fd-row", style: { gap: 10, padding: "12px 14px", borderRadius: "var(--r-md)", background: "var(--surface-2)", border: "1px solid var(--border)", flexWrap: "wrap" }, children: [
11193
- /* @__PURE__ */ (0, import_jsx_runtime84.jsx)("span", { className: "fd-meter", style: { gap: 2, color: "var(--csi-" + floor.n + "-mark)" }, "aria-hidden": "true", children: [1, 2, 3, 4].map((i) => /* @__PURE__ */ (0, import_jsx_runtime84.jsx)("span", { className: "fd-meter-seg" + (i <= floor.n ? " is-on" : ""), style: { width: 5, height: 12 } }, i)) }),
11194
- /* @__PURE__ */ (0, import_jsx_runtime84.jsxs)("span", { className: "fd-body-sm fd-secondary", style: { flex: 1, minWidth: 240 }, children: [
11195
- /* @__PURE__ */ (0, import_jsx_runtime84.jsxs)("strong", { style: { color: "var(--text)" }, children: [
11443
+ floorBand ? /* @__PURE__ */ (0, import_jsx_runtime85.jsxs)("div", { className: "fd-row", style: { gap: 10, padding: "12px 14px", borderRadius: "var(--r-md)", background: "var(--surface-2)", border: "1px solid var(--border)", flexWrap: "wrap" }, children: [
11444
+ /* @__PURE__ */ (0, import_jsx_runtime85.jsx)("span", { className: "fd-meter", style: { gap: 2, color: "var(--csi-" + floor.n + "-mark)" }, "aria-hidden": "true", children: [1, 2, 3, 4].map((i) => /* @__PURE__ */ (0, import_jsx_runtime85.jsx)("span", { className: "fd-meter-seg" + (i <= floor.n ? " is-on" : ""), style: { width: 5, height: 12 } }, i)) }),
11445
+ /* @__PURE__ */ (0, import_jsx_runtime85.jsxs)("span", { className: "fd-body-sm fd-secondary", style: { flex: 1, minWidth: 240 }, children: [
11446
+ /* @__PURE__ */ (0, import_jsx_runtime85.jsxs)("strong", { style: { color: "var(--text)" }, children: [
11196
11447
  "Plan floor ",
11197
11448
  floorScore
11198
11449
  ] }),
@@ -11203,8 +11454,8 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
11203
11454
  }
11204
11455
 
11205
11456
  // src/components/planner/MixGap.tsx
11206
- var React55 = __toESM(require("react"), 1);
11207
- var import_jsx_runtime85 = require("react/jsx-runtime");
11457
+ var React56 = __toESM(require("react"), 1);
11458
+ var import_jsx_runtime86 = require("react/jsx-runtime");
11208
11459
  var MIX_GAP_LAYOUT = {
11209
11460
  trackHeight: 30,
11210
11461
  barHeight: 20,
@@ -11218,19 +11469,19 @@ function mixGapOffset(value, max) {
11218
11469
  }
11219
11470
  function MixGap({ rows = [], loading = false, className = "" }) {
11220
11471
  const max = Math.max(1, ...rows.flatMap((r) => [r.target, r.realized]));
11221
- const [hover, setHover] = React55.useState(null);
11472
+ const [hover, setHover] = React56.useState(null);
11222
11473
  const toneOf = (gap) => gap >= -1 ? "ok" : gap >= -4 ? "warn" : "danger";
11223
11474
  const TONE = { ok: "var(--ok-solid)", warn: "var(--warn-solid)", danger: "var(--danger-solid)" };
11224
11475
  const { trackHeight, barHeight, targetWidth, labelGap } = MIX_GAP_LAYOUT;
11225
11476
  const barTop = (trackHeight - barHeight) / 2;
11226
- return /* @__PURE__ */ (0, import_jsx_runtime85.jsxs)("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 4 }, children: [
11227
- /* @__PURE__ */ (0, import_jsx_runtime85.jsxs)("div", { className: "fd-row", style: { gap: 16, justifyContent: "flex-end", paddingBottom: 6, flexWrap: "wrap" }, children: [
11228
- [["On target", TONE.ok], ["Close", TONE.warn], ["Short", TONE.danger]].map(([l, c]) => /* @__PURE__ */ (0, import_jsx_runtime85.jsxs)("span", { className: "fd-row fd-body-sm fd-muted", style: { gap: 6 }, children: [
11229
- /* @__PURE__ */ (0, import_jsx_runtime85.jsx)("span", { style: { width: 14, height: 9, borderRadius: 2, background: c } }),
11477
+ return /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 4 }, children: [
11478
+ /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("div", { className: "fd-row", style: { gap: 16, justifyContent: "flex-end", paddingBottom: 6, flexWrap: "wrap" }, children: [
11479
+ [["On target", TONE.ok], ["Close", TONE.warn], ["Short", TONE.danger]].map(([l, c]) => /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("span", { className: "fd-row fd-body-sm fd-muted", style: { gap: 6 }, children: [
11480
+ /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("span", { style: { width: 14, height: 9, borderRadius: 2, background: c } }),
11230
11481
  l
11231
11482
  ] }, l)),
11232
- /* @__PURE__ */ (0, import_jsx_runtime85.jsxs)("span", { className: "fd-row fd-body-sm fd-muted", style: { gap: 6 }, children: [
11233
- /* @__PURE__ */ (0, import_jsx_runtime85.jsx)("span", { "data-mixgap-legend-target": "", style: { width: targetWidth, height: 16, borderRadius: 1, background: MIX_GAP_TARGET_STRIPE } }),
11483
+ /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("span", { className: "fd-row fd-body-sm fd-muted", style: { gap: 6 }, children: [
11484
+ /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("span", { "data-mixgap-legend-target": "", style: { width: targetWidth, height: 16, borderRadius: 1, background: MIX_GAP_TARGET_STRIPE } }),
11234
11485
  "Target"
11235
11486
  ] })
11236
11487
  ] }),
@@ -11239,7 +11490,7 @@ function MixGap({ rows = [], loading = false, className = "" }) {
11239
11490
  const tone = toneOf(gap);
11240
11491
  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 : "");
11241
11492
  const labelLeft = r.realized > r.target ? `calc(${mixGapOffset(r.realized, max)} + ${labelGap}px)` : `calc(${mixGapOffset(r.target, max)} + ${targetWidth / 2 + labelGap}px)`;
11242
- return /* @__PURE__ */ (0, import_jsx_runtime85.jsxs)(
11493
+ return /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)(
11243
11494
  "div",
11244
11495
  {
11245
11496
  className: "fd-row",
@@ -11247,15 +11498,15 @@ function MixGap({ rows = [], loading = false, className = "" }) {
11247
11498
  onMouseEnter: () => setHover(r.channel),
11248
11499
  onMouseLeave: () => setHover(null),
11249
11500
  children: [
11250
- /* @__PURE__ */ (0, import_jsx_runtime85.jsx)("span", { style: { width: 128, flex: "none" }, children: /* @__PURE__ */ (0, import_jsx_runtime85.jsx)(ChannelTag, { channel: r.channel, size: "sm" }) }),
11251
- /* @__PURE__ */ (0, import_jsx_runtime85.jsx)("span", { style: { position: "relative", flex: 1, height: trackHeight, minWidth: 120 }, children: loading ? /* @__PURE__ */ (0, import_jsx_runtime85.jsx)("span", { className: "fd-skel", style: { position: "absolute", left: 0, right: 0, top: barTop, height: barHeight, borderRadius: 3 } }) : /* @__PURE__ */ (0, import_jsx_runtime85.jsxs)(import_jsx_runtime85.Fragment, { children: [
11252
- /* @__PURE__ */ (0, import_jsx_runtime85.jsx)("span", { "data-mixgap-bar": "", style: { position: "absolute", left: 0, top: barTop, height: barHeight, width: mixGapOffset(r.realized, max), background: TONE[tone], borderRadius: "2px 3px 3px 2px", transition: "width var(--dur-slow) var(--ease), background var(--dur-base) var(--ease)" } }),
11253
- /* @__PURE__ */ (0, import_jsx_runtime85.jsx)("span", { "data-mixgap-target": "", style: { position: "absolute", left: `calc(${mixGapOffset(r.target, max)} - ${targetWidth / 2}px)`, top: 0, width: targetWidth, height: trackHeight, background: MIX_GAP_TARGET_STRIPE, borderRadius: 1 } }),
11254
- /* @__PURE__ */ (0, import_jsx_runtime85.jsxs)("span", { "data-mixgap-label": "", className: "fd-num", style: { position: "absolute", left: labelLeft, top: "50%", transform: "translateY(-50%)", fontSize: 12, color: "var(--text-muted)", whiteSpace: "nowrap" }, children: [
11501
+ /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("span", { style: { width: 128, flex: "none" }, children: /* @__PURE__ */ (0, import_jsx_runtime86.jsx)(ChannelTag, { channel: r.channel, size: "sm" }) }),
11502
+ /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("span", { style: { position: "relative", flex: 1, height: trackHeight, minWidth: 120 }, children: loading ? /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("span", { className: "fd-skel", style: { position: "absolute", left: 0, right: 0, top: barTop, height: barHeight, borderRadius: 3 } }) : /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)(import_jsx_runtime86.Fragment, { children: [
11503
+ /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("span", { "data-mixgap-bar": "", style: { position: "absolute", left: 0, top: barTop, height: barHeight, width: mixGapOffset(r.realized, max), background: TONE[tone], borderRadius: "2px 3px 3px 2px", transition: "width var(--dur-slow) var(--ease), background var(--dur-base) var(--ease)" } }),
11504
+ /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("span", { "data-mixgap-target": "", style: { position: "absolute", left: `calc(${mixGapOffset(r.target, max)} - ${targetWidth / 2}px)`, top: 0, width: targetWidth, height: trackHeight, background: MIX_GAP_TARGET_STRIPE, borderRadius: 1 } }),
11505
+ /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("span", { "data-mixgap-label": "", className: "fd-num", style: { position: "absolute", left: labelLeft, top: "50%", transform: "translateY(-50%)", fontSize: 12, color: "var(--text-muted)", whiteSpace: "nowrap" }, children: [
11255
11506
  r.realized,
11256
11507
  "%"
11257
11508
  ] }),
11258
- hover === r.channel ? /* @__PURE__ */ (0, import_jsx_runtime85.jsx)("span", { className: "fd-tooltip", role: "tooltip", style: { position: "absolute", left: 0, right: "auto", bottom: trackHeight + 4, maxWidth: "min(340px, 100%)", whiteSpace: "normal", textAlign: "left", width: "max-content" }, children: tip }) : null
11509
+ hover === r.channel ? /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("span", { className: "fd-tooltip", role: "tooltip", style: { position: "absolute", left: 0, right: "auto", bottom: trackHeight + 4, maxWidth: "min(340px, 100%)", whiteSpace: "normal", textAlign: "left", width: "max-content" }, children: tip }) : null
11259
11510
  ] }) })
11260
11511
  ]
11261
11512
  },
@@ -11266,7 +11517,7 @@ function MixGap({ rows = [], loading = false, className = "" }) {
11266
11517
  }
11267
11518
 
11268
11519
  // src/components/planner/ChannelContribution.tsx
11269
- var import_jsx_runtime86 = require("react/jsx-runtime");
11520
+ var import_jsx_runtime87 = require("react/jsx-runtime");
11270
11521
  var money = (n) => "$" + Math.round(n).toLocaleString();
11271
11522
  function ChannelContribution({
11272
11523
  channels = [],
@@ -11282,9 +11533,9 @@ function ChannelContribution({
11282
11533
  const grand = total !== void 0 ? total : base + bonus;
11283
11534
  const pct = (v) => grand ? v / grand * 100 : 0;
11284
11535
  const spendTotal = channels.reduce((s, c) => s + Number(String(c.spend || 0).replace(/[^0-9.]/g, "")), 0);
11285
- return /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 16 }, children: [
11286
- loading ? /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("span", { className: "fd-skel", style: { height: 34, borderRadius: "var(--r-sm)" } }) : /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("div", { className: "fd-row", style: { height: 34, borderRadius: "var(--r-sm)", overflow: "hidden", gap: 2, background: "var(--surface-3)" }, children: [
11287
- channels.map((c) => /* @__PURE__ */ (0, import_jsx_runtime86.jsx)(
11536
+ return /* @__PURE__ */ (0, import_jsx_runtime87.jsxs)("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 16 }, children: [
11537
+ loading ? /* @__PURE__ */ (0, import_jsx_runtime87.jsx)("span", { className: "fd-skel", style: { height: 34, borderRadius: "var(--r-sm)" } }) : /* @__PURE__ */ (0, import_jsx_runtime87.jsxs)("div", { className: "fd-row", style: { height: 34, borderRadius: "var(--r-sm)", overflow: "hidden", gap: 2, background: "var(--surface-3)" }, children: [
11538
+ channels.map((c) => /* @__PURE__ */ (0, import_jsx_runtime87.jsx)(
11288
11539
  "span",
11289
11540
  {
11290
11541
  title: c.name + " \xB7 " + c.crp.toFixed(1) + " CRP",
@@ -11293,7 +11544,7 @@ function ChannelContribution({
11293
11544
  },
11294
11545
  c.name
11295
11546
  )),
11296
- bonus > 0 ? /* @__PURE__ */ (0, import_jsx_runtime86.jsx)(
11547
+ bonus > 0 ? /* @__PURE__ */ (0, import_jsx_runtime87.jsx)(
11297
11548
  "span",
11298
11549
  {
11299
11550
  title: "Surround-sound bonus +" + bonusPct + "%",
@@ -11302,18 +11553,18 @@ function ChannelContribution({
11302
11553
  }
11303
11554
  ) : null
11304
11555
  ] }),
11305
- showTable ? /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("table", { className: "fd-table", style: { fontSize: "var(--body-sm-size)" }, children: [
11306
- /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("tr", { children: [
11307
- /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("th", { style: { width: "34%" }, children: "Channel" }),
11308
- /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("th", { style: { width: "16%" }, children: "Weight" }),
11309
- /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("th", { className: "is-num", style: { width: "16%" }, children: "Spend" }),
11310
- /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("th", { className: "is-num", style: { width: "17%" }, children: "CRP" }),
11311
- /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("th", { className: "is-num", style: { width: "17%" }, children: "Share" })
11556
+ showTable ? /* @__PURE__ */ (0, import_jsx_runtime87.jsxs)("table", { className: "fd-table", style: { fontSize: "var(--body-sm-size)" }, children: [
11557
+ /* @__PURE__ */ (0, import_jsx_runtime87.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime87.jsxs)("tr", { children: [
11558
+ /* @__PURE__ */ (0, import_jsx_runtime87.jsx)("th", { style: { width: "34%" }, children: "Channel" }),
11559
+ /* @__PURE__ */ (0, import_jsx_runtime87.jsx)("th", { style: { width: "16%" }, children: "Weight" }),
11560
+ /* @__PURE__ */ (0, import_jsx_runtime87.jsx)("th", { className: "is-num", style: { width: "16%" }, children: "Spend" }),
11561
+ /* @__PURE__ */ (0, import_jsx_runtime87.jsx)("th", { className: "is-num", style: { width: "17%" }, children: "CRP" }),
11562
+ /* @__PURE__ */ (0, import_jsx_runtime87.jsx)("th", { className: "is-num", style: { width: "17%" }, children: "Share" })
11312
11563
  ] }) }),
11313
- /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("tbody", { children: [
11314
- channels.map((c) => /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("tr", { children: [
11315
- /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("td", { children: /* @__PURE__ */ (0, import_jsx_runtime86.jsx)(ChannelTag, { channel: c.name, size: "sm" }) }),
11316
- /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("td", { children: /* @__PURE__ */ (0, import_jsx_runtime86.jsx)(
11564
+ /* @__PURE__ */ (0, import_jsx_runtime87.jsxs)("tbody", { children: [
11565
+ channels.map((c) => /* @__PURE__ */ (0, import_jsx_runtime87.jsxs)("tr", { children: [
11566
+ /* @__PURE__ */ (0, import_jsx_runtime87.jsx)("td", { children: /* @__PURE__ */ (0, import_jsx_runtime87.jsx)(ChannelTag, { channel: c.name, size: "sm" }) }),
11567
+ /* @__PURE__ */ (0, import_jsx_runtime87.jsx)("td", { children: /* @__PURE__ */ (0, import_jsx_runtime87.jsx)(
11317
11568
  "span",
11318
11569
  {
11319
11570
  className: "fd-badge fd-badge-neutral",
@@ -11322,38 +11573,38 @@ function ChannelContribution({
11322
11573
  children: "weight " + (channelWeightOf(c.name) || 0)
11323
11574
  }
11324
11575
  ) }),
11325
- /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("td", { className: "is-num", children: c.spend }),
11326
- /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("td", { className: "is-num", children: c.crp.toFixed(1) }),
11327
- /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("td", { className: "is-num", children: [
11576
+ /* @__PURE__ */ (0, import_jsx_runtime87.jsx)("td", { className: "is-num", children: c.spend }),
11577
+ /* @__PURE__ */ (0, import_jsx_runtime87.jsx)("td", { className: "is-num", children: c.crp.toFixed(1) }),
11578
+ /* @__PURE__ */ (0, import_jsx_runtime87.jsxs)("td", { className: "is-num", children: [
11328
11579
  pct(c.crp).toFixed(0),
11329
11580
  "%"
11330
11581
  ] })
11331
11582
  ] }, c.name)),
11332
- bonus > 0 ? /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("tr", { children: [
11333
- /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("td", { children: /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("span", { className: "fd-row", style: { gap: 9, fontWeight: 600 }, children: [
11334
- /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("span", { style: { width: 9, height: 9, borderRadius: 2, background: "repeating-linear-gradient(135deg,var(--csi-3-mark) 0 3px,var(--csi-2-mark) 3px 6px)", flex: "none" } }),
11583
+ bonus > 0 ? /* @__PURE__ */ (0, import_jsx_runtime87.jsxs)("tr", { children: [
11584
+ /* @__PURE__ */ (0, import_jsx_runtime87.jsx)("td", { children: /* @__PURE__ */ (0, import_jsx_runtime87.jsxs)("span", { className: "fd-row", style: { gap: 9, fontWeight: 600 }, children: [
11585
+ /* @__PURE__ */ (0, import_jsx_runtime87.jsx)("span", { style: { width: 9, height: 9, borderRadius: 2, background: "repeating-linear-gradient(135deg,var(--csi-3-mark) 0 3px,var(--csi-2-mark) 3px 6px)", flex: "none" } }),
11335
11586
  "Surround-sound bonus"
11336
11587
  ] }) }),
11337
- /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("td", { children: /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("span", { className: "fd-badge fd-badge-success", style: { height: 20, fontSize: 11 }, children: [
11588
+ /* @__PURE__ */ (0, import_jsx_runtime87.jsx)("td", { children: /* @__PURE__ */ (0, import_jsx_runtime87.jsxs)("span", { className: "fd-badge fd-badge-success", style: { height: 20, fontSize: 11 }, children: [
11338
11589
  "+",
11339
11590
  bonusPct,
11340
11591
  "% of +",
11341
11592
  bonusMax,
11342
11593
  "%"
11343
11594
  ] }) }),
11344
- /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("td", { className: "is-num fd-muted", children: "\u2014" }),
11345
- /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("td", { className: "is-num", children: bonus.toFixed(1) }),
11346
- /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("td", { className: "is-num", children: [
11595
+ /* @__PURE__ */ (0, import_jsx_runtime87.jsx)("td", { className: "is-num fd-muted", children: "\u2014" }),
11596
+ /* @__PURE__ */ (0, import_jsx_runtime87.jsx)("td", { className: "is-num", children: bonus.toFixed(1) }),
11597
+ /* @__PURE__ */ (0, import_jsx_runtime87.jsxs)("td", { className: "is-num", children: [
11347
11598
  pct(bonus).toFixed(0),
11348
11599
  "%"
11349
11600
  ] })
11350
11601
  ] }) : null,
11351
- /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("tr", { style: { background: "var(--surface-2)" }, children: [
11352
- /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("td", { style: { fontWeight: 700 }, children: "Campus total" }),
11353
- /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("td", {}),
11354
- /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("td", { className: "is-num", style: { fontWeight: 700 }, children: money(spendTotal) }),
11355
- /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("td", { className: "is-num", style: { fontWeight: 700 }, children: grand.toFixed(1) }),
11356
- /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("td", { className: "is-num", style: { fontWeight: 700 }, children: "100%" })
11602
+ /* @__PURE__ */ (0, import_jsx_runtime87.jsxs)("tr", { style: { background: "var(--surface-2)" }, children: [
11603
+ /* @__PURE__ */ (0, import_jsx_runtime87.jsx)("td", { style: { fontWeight: 700 }, children: "Campus total" }),
11604
+ /* @__PURE__ */ (0, import_jsx_runtime87.jsx)("td", {}),
11605
+ /* @__PURE__ */ (0, import_jsx_runtime87.jsx)("td", { className: "is-num", style: { fontWeight: 700 }, children: money(spendTotal) }),
11606
+ /* @__PURE__ */ (0, import_jsx_runtime87.jsx)("td", { className: "is-num", style: { fontWeight: 700 }, children: grand.toFixed(1) }),
11607
+ /* @__PURE__ */ (0, import_jsx_runtime87.jsx)("td", { className: "is-num", style: { fontWeight: 700 }, children: "100%" })
11357
11608
  ] })
11358
11609
  ] })
11359
11610
  ] }) : null
@@ -11361,8 +11612,8 @@ function ChannelContribution({
11361
11612
  }
11362
11613
 
11363
11614
  // src/components/planner/BudgetReallocator.tsx
11364
- var React56 = __toESM(require("react"), 1);
11365
- var import_jsx_runtime87 = require("react/jsx-runtime");
11615
+ var React57 = __toESM(require("react"), 1);
11616
+ var import_jsx_runtime88 = require("react/jsx-runtime");
11366
11617
  var bandFor = (crp) => crp >= 200 ? "dominant" : crp >= 100 ? "strong" : crp >= 50 ? "adequate" : "weak";
11367
11618
  function BudgetReallocator({
11368
11619
  campus,
@@ -11377,8 +11628,8 @@ function BudgetReallocator({
11377
11628
  onCancel,
11378
11629
  className = ""
11379
11630
  }) {
11380
- const [draft, setDraft] = React56.useState(spend);
11381
- React56.useEffect(() => setDraft(spend), [spend]);
11631
+ const [draft, setDraft] = React57.useState(spend);
11632
+ React57.useEffect(() => setDraft(spend), [spend]);
11382
11633
  const dirty = draft !== spend;
11383
11634
  const nextCrp = scoreFor ? scoreFor(draft) : crp;
11384
11635
  const nextBand = bandFor(nextCrp);
@@ -11393,10 +11644,10 @@ function BudgetReallocator({
11393
11644
  setDraft(spend);
11394
11645
  if (onCancel) onCancel();
11395
11646
  };
11396
- const trackRef = React56.useRef(null);
11397
- const chipRef = React56.useRef(null);
11398
- const [chipLeft, setChipLeft] = React56.useState(null);
11399
- React56.useLayoutEffect(() => {
11647
+ const trackRef = React57.useRef(null);
11648
+ const chipRef = React57.useRef(null);
11649
+ const [chipLeft, setChipLeft] = React57.useState(null);
11650
+ React57.useLayoutEffect(() => {
11400
11651
  const track = trackRef.current;
11401
11652
  if (!dirty || !track) {
11402
11653
  setChipLeft(null);
@@ -11417,23 +11668,23 @@ function BudgetReallocator({
11417
11668
  ro.observe(track);
11418
11669
  return () => ro.disconnect();
11419
11670
  }, [dirty, pct]);
11420
- return /* @__PURE__ */ (0, import_jsx_runtime87.jsxs)(
11671
+ return /* @__PURE__ */ (0, import_jsx_runtime88.jsxs)(
11421
11672
  "div",
11422
11673
  {
11423
11674
  className: ["fd-stack", className].filter(Boolean).join(" "),
11424
11675
  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)" },
11425
11676
  children: [
11426
- /* @__PURE__ */ (0, import_jsx_runtime87.jsxs)("div", { className: "fd-row", style: { gap: 12, flexWrap: "wrap" }, children: [
11427
- /* @__PURE__ */ (0, import_jsx_runtime87.jsx)("span", { className: "fd-h4", style: { flex: 1, minWidth: 140 }, children: campus }),
11428
- /* @__PURE__ */ (0, import_jsx_runtime87.jsx)(CsiBadge, { band: nowBand, crp, size: "medium" }),
11429
- dirty ? /* @__PURE__ */ (0, import_jsx_runtime87.jsxs)(import_jsx_runtime87.Fragment, { children: [
11430
- /* @__PURE__ */ (0, import_jsx_runtime87.jsx)("i", { className: "ph ph-arrow-right fd-muted", "aria-hidden": "true" }),
11431
- /* @__PURE__ */ (0, import_jsx_runtime87.jsx)(CsiBadge, { band: nextBand, crp: nextCrp, size: "medium", preview: true })
11677
+ /* @__PURE__ */ (0, import_jsx_runtime88.jsxs)("div", { className: "fd-row", style: { gap: 12, flexWrap: "wrap" }, children: [
11678
+ /* @__PURE__ */ (0, import_jsx_runtime88.jsx)("span", { className: "fd-h4", style: { flex: 1, minWidth: 140 }, children: campus }),
11679
+ /* @__PURE__ */ (0, import_jsx_runtime88.jsx)(CsiBadge, { band: nowBand, crp, size: "medium" }),
11680
+ dirty ? /* @__PURE__ */ (0, import_jsx_runtime88.jsxs)(import_jsx_runtime88.Fragment, { children: [
11681
+ /* @__PURE__ */ (0, import_jsx_runtime88.jsx)("i", { className: "ph ph-arrow-right fd-muted", "aria-hidden": "true" }),
11682
+ /* @__PURE__ */ (0, import_jsx_runtime88.jsx)(CsiBadge, { band: nextBand, crp: nextCrp, size: "medium", preview: true })
11432
11683
  ] }) : null
11433
11684
  ] }),
11434
- /* @__PURE__ */ (0, import_jsx_runtime87.jsxs)("div", { className: "fd-slider", ref: trackRef, children: [
11435
- /* @__PURE__ */ (0, import_jsx_runtime87.jsx)("span", { className: "fd-slider-fill", style: { width: pct + "%" } }),
11436
- dirty ? /* @__PURE__ */ (0, import_jsx_runtime87.jsx)(
11685
+ /* @__PURE__ */ (0, import_jsx_runtime88.jsxs)("div", { className: "fd-slider", ref: trackRef, children: [
11686
+ /* @__PURE__ */ (0, import_jsx_runtime88.jsx)("span", { className: "fd-slider-fill", style: { width: pct + "%" } }),
11687
+ dirty ? /* @__PURE__ */ (0, import_jsx_runtime88.jsx)(
11437
11688
  "span",
11438
11689
  {
11439
11690
  ref: chipRef,
@@ -11445,7 +11696,7 @@ function BudgetReallocator({
11445
11696
  children: (delta < 0 ? "\u2212$" : "+$") + Math.abs(delta).toLocaleString()
11446
11697
  }
11447
11698
  ) : null,
11448
- /* @__PURE__ */ (0, import_jsx_runtime87.jsx)(
11699
+ /* @__PURE__ */ (0, import_jsx_runtime88.jsx)(
11449
11700
  "input",
11450
11701
  {
11451
11702
  type: "range",
@@ -11461,13 +11712,13 @@ function BudgetReallocator({
11461
11712
  }
11462
11713
  )
11463
11714
  ] }),
11464
- /* @__PURE__ */ (0, import_jsx_runtime87.jsxs)("div", { className: "fd-row", style: { gap: 12, flexWrap: "wrap" }, children: [
11465
- /* @__PURE__ */ (0, import_jsx_runtime87.jsxs)("span", { className: "fd-stack", style: { gap: 2, flex: 1, minWidth: 150 }, children: [
11466
- /* @__PURE__ */ (0, import_jsx_runtime87.jsx)("span", { className: "fd-num", style: { fontSize: 19, fontWeight: 700 }, children: "$" + draft.toLocaleString() }),
11467
- /* @__PURE__ */ (0, import_jsx_runtime87.jsx)("span", { className: "fd-body-sm fd-muted", children: "Arrow keys step $100, shift+arrow $1,000. Escape reverts." })
11715
+ /* @__PURE__ */ (0, import_jsx_runtime88.jsxs)("div", { className: "fd-row", style: { gap: 12, flexWrap: "wrap" }, children: [
11716
+ /* @__PURE__ */ (0, import_jsx_runtime88.jsxs)("span", { className: "fd-stack", style: { gap: 2, flex: 1, minWidth: 150 }, children: [
11717
+ /* @__PURE__ */ (0, import_jsx_runtime88.jsx)("span", { className: "fd-num", style: { fontSize: 19, fontWeight: 700 }, children: "$" + draft.toLocaleString() }),
11718
+ /* @__PURE__ */ (0, import_jsx_runtime88.jsx)("span", { className: "fd-body-sm fd-muted", children: "Arrow keys step $100, shift+arrow $1,000. Escape reverts." })
11468
11719
  ] }),
11469
- /* @__PURE__ */ (0, import_jsx_runtime87.jsx)("button", { type: "button", className: "fd-btn fd-btn-ghost", disabled: !dirty, onClick: revert, children: "Cancel" }),
11470
- /* @__PURE__ */ (0, import_jsx_runtime87.jsx)(
11720
+ /* @__PURE__ */ (0, import_jsx_runtime88.jsx)("button", { type: "button", className: "fd-btn fd-btn-ghost", disabled: !dirty, onClick: revert, children: "Cancel" }),
11721
+ /* @__PURE__ */ (0, import_jsx_runtime88.jsx)(
11471
11722
  "button",
11472
11723
  {
11473
11724
  type: "button",
@@ -11486,7 +11737,7 @@ function BudgetReallocator({
11486
11737
  }
11487
11738
 
11488
11739
  // src/components/planner/SurroundSound.tsx
11489
- var import_jsx_runtime88 = require("react/jsx-runtime");
11740
+ var import_jsx_runtime89 = require("react/jsx-runtime");
11490
11741
  var CATEGORIES = [
11491
11742
  { key: "ooh", label: "OOH", icon: "flag-banner", color: "var(--ch-ooh)" },
11492
11743
  { key: "transit", label: "Transit", icon: "bus", color: "var(--ch-transit)" },
@@ -11498,26 +11749,26 @@ var CATEGORIES = [
11498
11749
  function SurroundSound({ present = [], bonusPct = 0, bonusMax = 40, missedCost, className = "" }) {
11499
11750
  const earned = Math.max(0, Math.min(1, bonusPct / bonusMax));
11500
11751
  const single = present.length <= 2;
11501
- return /* @__PURE__ */ (0, import_jsx_runtime88.jsxs)("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 14 }, children: [
11502
- /* @__PURE__ */ (0, import_jsx_runtime88.jsx)("div", { className: "fd-row", style: { gap: 8, flexWrap: "wrap" }, children: CATEGORIES.map((c) => {
11752
+ return /* @__PURE__ */ (0, import_jsx_runtime89.jsxs)("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 14 }, children: [
11753
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsx)("div", { className: "fd-row", style: { gap: 8, flexWrap: "wrap" }, children: CATEGORIES.map((c) => {
11503
11754
  const on = present.includes(c.key);
11504
- return /* @__PURE__ */ (0, import_jsx_runtime88.jsxs)(
11755
+ return /* @__PURE__ */ (0, import_jsx_runtime89.jsxs)(
11505
11756
  "span",
11506
11757
  {
11507
11758
  title: c.label + (on ? " \u2014 present" : " \u2014 not bought"),
11508
11759
  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)" },
11509
11760
  children: [
11510
- /* @__PURE__ */ (0, import_jsx_runtime88.jsx)("i", { className: "ph ph-" + c.icon, style: { fontSize: 19, color: on ? c.color : "var(--text-muted)" }, "aria-hidden": "true" }),
11511
- /* @__PURE__ */ (0, import_jsx_runtime88.jsx)("span", { style: { fontSize: 10.5, fontWeight: 700 }, children: c.label })
11761
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsx)("i", { className: "ph ph-" + c.icon, style: { fontSize: 19, color: on ? c.color : "var(--text-muted)" }, "aria-hidden": "true" }),
11762
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsx)("span", { style: { fontSize: 10.5, fontWeight: 700 }, children: c.label })
11512
11763
  ]
11513
11764
  },
11514
11765
  c.key
11515
11766
  );
11516
11767
  }) }),
11517
- /* @__PURE__ */ (0, import_jsx_runtime88.jsxs)("div", { className: "fd-stack", style: { gap: 8 }, children: [
11518
- /* @__PURE__ */ (0, import_jsx_runtime88.jsxs)("div", { className: "fd-row", style: { justifyContent: "space-between", gap: 12 }, children: [
11519
- /* @__PURE__ */ (0, import_jsx_runtime88.jsx)("span", { className: "fd-label-lg", children: "Surround-sound bonus earned" }),
11520
- /* @__PURE__ */ (0, import_jsx_runtime88.jsxs)("span", { className: "fd-num", style: { color: single ? "var(--warn-text)" : "var(--csi-3-mark)", fontWeight: 700 }, children: [
11768
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsxs)("div", { className: "fd-stack", style: { gap: 8 }, children: [
11769
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsxs)("div", { className: "fd-row", style: { justifyContent: "space-between", gap: 12 }, children: [
11770
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsx)("span", { className: "fd-label-lg", children: "Surround-sound bonus earned" }),
11771
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsxs)("span", { className: "fd-num", style: { color: single ? "var(--warn-text)" : "var(--csi-3-mark)", fontWeight: 700 }, children: [
11521
11772
  "+",
11522
11773
  bonusPct,
11523
11774
  "% of +",
@@ -11525,8 +11776,8 @@ function SurroundSound({ present = [], bonusPct = 0, bonusMax = 40, missedCost,
11525
11776
  "%"
11526
11777
  ] })
11527
11778
  ] }),
11528
- /* @__PURE__ */ (0, import_jsx_runtime88.jsx)("div", { style: { height: 8, borderRadius: "var(--r-xs)", background: "var(--surface-3)", overflow: "hidden" }, children: /* @__PURE__ */ (0, import_jsx_runtime88.jsx)("div", { style: { height: "100%", width: earned * 100 + "%", background: "var(--csi-3-mark)", borderRadius: "inherit", transition: "width var(--dur-slow) var(--ease)" } }) }),
11529
- /* @__PURE__ */ (0, import_jsx_runtime88.jsxs)("span", { className: "fd-body-sm fd-secondary", style: { textWrap: "pretty" }, children: [
11779
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsx)("div", { style: { height: 8, borderRadius: "var(--r-xs)", background: "var(--surface-3)", overflow: "hidden" }, children: /* @__PURE__ */ (0, import_jsx_runtime89.jsx)("div", { style: { height: "100%", width: earned * 100 + "%", background: "var(--csi-3-mark)", borderRadius: "inherit", transition: "width var(--dur-slow) var(--ease)" } }) }),
11780
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsxs)("span", { className: "fd-body-sm fd-secondary", style: { textWrap: "pretty" }, children: [
11530
11781
  present.length,
11531
11782
  " of 6 channel categories present.",
11532
11783
  " ",
@@ -11538,7 +11789,7 @@ function SurroundSound({ present = [], bonusPct = 0, bonusMax = 40, missedCost,
11538
11789
  }
11539
11790
 
11540
11791
  // src/components/planner/Importance.tsx
11541
- var import_jsx_runtime89 = require("react/jsx-runtime");
11792
+ var import_jsx_runtime90 = require("react/jsx-runtime");
11542
11793
  var IMPORTANCE_LEVELS = [
11543
11794
  { id: "nudge", rank: 1, label: "Nudge", icon: "feather", description: "Breaks a tie, nothing more." },
11544
11795
  { id: "lean", rank: 2, label: "Lean", icon: "arrow-bend-up-right", description: "A mild preference between otherwise equal options." },
@@ -11568,7 +11819,7 @@ function importanceTokens(id) {
11568
11819
  function ImportanceTag({ level, showLabel = true, size = "sm", className = "", disabled = false }) {
11569
11820
  const lvl = importanceLevel(level);
11570
11821
  const t = importanceTokens(level);
11571
- return /* @__PURE__ */ (0, import_jsx_runtime89.jsxs)(
11822
+ return /* @__PURE__ */ (0, import_jsx_runtime90.jsxs)(
11572
11823
  "span",
11573
11824
  {
11574
11825
  className: ["fd-imp-tag", size === "md" ? "is-md" : "", disabled ? "is-disabled" : "", className].filter(Boolean).join(" "),
@@ -11576,16 +11827,16 @@ function ImportanceTag({ level, showLabel = true, size = "sm", className = "", d
11576
11827
  title: lvl.label + " \u2014 " + lvl.description,
11577
11828
  "aria-disabled": disabled ? "true" : void 0,
11578
11829
  children: [
11579
- /* @__PURE__ */ (0, import_jsx_runtime89.jsx)("i", { className: "ph ph-" + lvl.icon, "aria-hidden": "true" }),
11580
- showLabel ? lvl.label : /* @__PURE__ */ (0, import_jsx_runtime89.jsx)("span", { className: "fd-sr", children: lvl.label })
11830
+ /* @__PURE__ */ (0, import_jsx_runtime90.jsx)("i", { className: "ph ph-" + lvl.icon, "aria-hidden": "true" }),
11831
+ showLabel ? lvl.label : /* @__PURE__ */ (0, import_jsx_runtime90.jsx)("span", { className: "fd-sr", children: lvl.label })
11581
11832
  ]
11582
11833
  }
11583
11834
  );
11584
11835
  }
11585
11836
 
11586
11837
  // src/components/planner/PreferenceMeter.tsx
11587
- var React57 = __toESM(require("react"), 1);
11588
- var import_jsx_runtime90 = require("react/jsx-runtime");
11838
+ var React58 = __toESM(require("react"), 1);
11839
+ var import_jsx_runtime91 = require("react/jsx-runtime");
11589
11840
  function preferenceScore(criteria) {
11590
11841
  const earned = criteria.reduce((n, c) => n + (Number(c.earned) || 0), 0);
11591
11842
  const weight = criteria.reduce((n, c) => n + (Number(c.weight) || 0), 0);
@@ -11614,8 +11865,8 @@ function PreferenceMeter({
11614
11865
  className = ""
11615
11866
  }) {
11616
11867
  const value = score == null ? preferenceScore(criteria) : score;
11617
- const segments = React57.useMemo(() => preferenceSegments(criteria), [criteria]);
11618
- return /* @__PURE__ */ (0, import_jsx_runtime90.jsx)(
11868
+ const segments = React58.useMemo(() => preferenceSegments(criteria), [criteria]);
11869
+ return /* @__PURE__ */ (0, import_jsx_runtime91.jsx)(
11619
11870
  ScoreMeter,
11620
11871
  {
11621
11872
  score: value,
@@ -11627,22 +11878,22 @@ function PreferenceMeter({
11627
11878
  placement,
11628
11879
  className,
11629
11880
  breakdownLabel: breakdownTitle,
11630
- breakdown: /* @__PURE__ */ (0, import_jsx_runtime90.jsxs)("div", { className: "fd-prefbreak", children: [
11631
- /* @__PURE__ */ (0, import_jsx_runtime90.jsxs)("div", { className: "fd-prefbreak-head", children: [
11632
- /* @__PURE__ */ (0, import_jsx_runtime90.jsx)("span", { className: "fd-label-lg", children: breakdownTitle }),
11633
- /* @__PURE__ */ (0, import_jsx_runtime90.jsx)("span", { className: "fd-prefbreak-score fd-tabular", children: Math.round(value) })
11881
+ breakdown: /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)("div", { className: "fd-prefbreak", children: [
11882
+ /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)("div", { className: "fd-prefbreak-head", children: [
11883
+ /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("span", { className: "fd-label-lg", children: breakdownTitle }),
11884
+ /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("span", { className: "fd-prefbreak-score fd-tabular", children: Math.round(value) })
11634
11885
  ] }),
11635
- /* @__PURE__ */ (0, import_jsx_runtime90.jsx)("ul", { className: "fd-prefbreak-list", children: criteria.map((c) => {
11886
+ /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("ul", { className: "fd-prefbreak-list", children: criteria.map((c) => {
11636
11887
  const pct = c.weight > 0 ? Math.round((Number(c.earned) || 0) / c.weight * 100) : 0;
11637
- return /* @__PURE__ */ (0, import_jsx_runtime90.jsxs)("li", { className: pct === 0 ? "fd-prefbreak-item is-unmet" : "fd-prefbreak-item", children: [
11638
- /* @__PURE__ */ (0, import_jsx_runtime90.jsx)(ImportanceTag, { level: c.importance }),
11639
- /* @__PURE__ */ (0, import_jsx_runtime90.jsxs)("span", { className: "fd-prefbreak-text", children: [
11640
- /* @__PURE__ */ (0, import_jsx_runtime90.jsx)("span", { className: "fd-prefbreak-label", children: c.label }),
11641
- c.note ? /* @__PURE__ */ (0, import_jsx_runtime90.jsx)("span", { className: "fd-prefbreak-note", children: c.note }) : null
11888
+ return /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)("li", { className: pct === 0 ? "fd-prefbreak-item is-unmet" : "fd-prefbreak-item", children: [
11889
+ /* @__PURE__ */ (0, import_jsx_runtime91.jsx)(ImportanceTag, { level: c.importance }),
11890
+ /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)("span", { className: "fd-prefbreak-text", children: [
11891
+ /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("span", { className: "fd-prefbreak-label", children: c.label }),
11892
+ c.note ? /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("span", { className: "fd-prefbreak-note", children: c.note }) : null
11642
11893
  ] }),
11643
- /* @__PURE__ */ (0, import_jsx_runtime90.jsxs)("span", { className: "fd-prefbreak-val fd-tabular", children: [
11894
+ /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)("span", { className: "fd-prefbreak-val fd-tabular", children: [
11644
11895
  Math.round(Number(c.earned) || 0),
11645
- /* @__PURE__ */ (0, import_jsx_runtime90.jsx)("span", { className: "fd-prefbreak-sep", children: "/" }),
11896
+ /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("span", { className: "fd-prefbreak-sep", children: "/" }),
11646
11897
  Math.round(c.weight)
11647
11898
  ] })
11648
11899
  ] }, c.id);
@@ -11653,10 +11904,10 @@ function PreferenceMeter({
11653
11904
  }
11654
11905
 
11655
11906
  // src/components/chat/AgentChatPanel.tsx
11656
- var React63 = __toESM(require("react"), 1);
11907
+ var React64 = __toESM(require("react"), 1);
11657
11908
 
11658
11909
  // src/components/chat/chatEngine.ts
11659
- var React58 = __toESM(require("react"), 1);
11910
+ var React59 = __toESM(require("react"), 1);
11660
11911
  var CHAT_UNAVAILABLE = "chat_unavailable";
11661
11912
  var JOB_PENDING = ["queued", "running"];
11662
11913
  var JOB_SUCCESS = ["completed", "recovered"];
@@ -11710,22 +11961,22 @@ function useChatEngine(opts) {
11710
11961
  onClear,
11711
11962
  onFeedback
11712
11963
  } = opts || {};
11713
- const [status, setStatus] = React58.useState("idle");
11714
- const [threadId, setThreadId] = React58.useState(null);
11715
- const [messages, setMessages] = React58.useState([]);
11716
- const [queue, setQueue] = React58.useState([]);
11717
- const [fatal, setFatal] = React58.useState(null);
11718
- const [busy, setBusy] = React58.useState(false);
11719
- const [turnStartedAt, setTurnStartedAt] = React58.useState(null);
11720
- const listRef = React58.useRef([]);
11721
- const queueRef = React58.useRef([]);
11722
- const busyRef = React58.useRef(false);
11723
- const stoppedRef = React58.useRef(false);
11724
- const abortRef = React58.useRef(null);
11725
- const serverCount = React58.useRef(0);
11726
- const threadRef = React58.useRef(null);
11727
- const mounted = React58.useRef(true);
11728
- React58.useEffect(() => {
11964
+ const [status, setStatus] = React59.useState("idle");
11965
+ const [threadId, setThreadId] = React59.useState(null);
11966
+ const [messages, setMessages] = React59.useState([]);
11967
+ const [queue, setQueue] = React59.useState([]);
11968
+ const [fatal, setFatal] = React59.useState(null);
11969
+ const [busy, setBusy] = React59.useState(false);
11970
+ const [turnStartedAt, setTurnStartedAt] = React59.useState(null);
11971
+ const listRef = React59.useRef([]);
11972
+ const queueRef = React59.useRef([]);
11973
+ const busyRef = React59.useRef(false);
11974
+ const stoppedRef = React59.useRef(false);
11975
+ const abortRef = React59.useRef(null);
11976
+ const serverCount = React59.useRef(0);
11977
+ const threadRef = React59.useRef(null);
11978
+ const mounted = React59.useRef(true);
11979
+ React59.useEffect(() => {
11729
11980
  mounted.current = true;
11730
11981
  return () => {
11731
11982
  mounted.current = false;
@@ -11747,14 +11998,14 @@ function useChatEngine(opts) {
11747
11998
  }
11748
11999
  return false;
11749
12000
  };
11750
- const loadThread = React58.useCallback(async (id) => {
12001
+ const loadThread = React59.useCallback(async (id) => {
11751
12002
  const data = await apiAdapter.getThread(id);
11752
12003
  const list = [...data && data.messages || []];
11753
12004
  serverCount.current = list.length;
11754
12005
  commit(list);
11755
12006
  return list;
11756
12007
  }, [apiAdapter]);
11757
- React58.useEffect(() => {
12008
+ React59.useEffect(() => {
11758
12009
  if (!apiAdapter) {
11759
12010
  setStatus("idle");
11760
12011
  setFatal(null);
@@ -11967,7 +12218,7 @@ function useChatEngine(opts) {
11967
12218
  await dispatchTurn(turn);
11968
12219
  }
11969
12220
  }
11970
- const send = React58.useCallback((text, attachments) => {
12221
+ const send = React59.useCallback((text, attachments) => {
11971
12222
  const body = (text || "").trim();
11972
12223
  if (!body && !(attachments && attachments.length)) return;
11973
12224
  if (status === "disconnected") return;
@@ -11977,7 +12228,7 @@ function useChatEngine(opts) {
11977
12228
  stoppedRef.current = false;
11978
12229
  drain();
11979
12230
  }, [status]);
11980
- const stop = React58.useCallback(() => {
12231
+ const stop = React59.useCallback(() => {
11981
12232
  stoppedRef.current = true;
11982
12233
  const ac = abortRef.current;
11983
12234
  if (ac) {
@@ -11996,11 +12247,11 @@ function useChatEngine(opts) {
11996
12247
  store.del(STORAGE_PREFIX + threadRef.current);
11997
12248
  }
11998
12249
  }, [apiAdapter]);
11999
- const removeQueued = React58.useCallback((id) => {
12250
+ const removeQueued = React59.useCallback((id) => {
12000
12251
  queueRef.current = queueRef.current.filter((t) => t.id !== id);
12001
12252
  setQueue(queueRef.current.slice());
12002
12253
  }, []);
12003
- const retry = React58.useCallback(() => {
12254
+ const retry = React59.useCallback(() => {
12004
12255
  const list = listRef.current;
12005
12256
  let at = -1;
12006
12257
  for (let i = list.length - 1; i >= 0; i--) if (list[i].role === "user") {
@@ -12016,19 +12267,19 @@ function useChatEngine(opts) {
12016
12267
  setQueue(queueRef.current.slice());
12017
12268
  drain();
12018
12269
  }, []);
12019
- const clear = React58.useCallback(() => {
12270
+ const clear = React59.useCallback(() => {
12020
12271
  commit([]);
12021
12272
  serverCount.current = 0;
12022
12273
  queueRef.current = [];
12023
12274
  setQueue([]);
12024
12275
  onClear && onClear();
12025
12276
  }, [onClear]);
12026
- const setFeedback = React58.useCallback((id, value) => {
12277
+ const setFeedback = React59.useCallback((id, value) => {
12027
12278
  patch(id, (m) => ({ feedback: m.feedback === value ? null : value }));
12028
12279
  const msg = listRef.current.find((m) => m.id === id);
12029
12280
  onFeedback && onFeedback({ message: msg, feedback: msg ? msg.feedback : value });
12030
12281
  }, [onFeedback]);
12031
- const reload = React58.useCallback(async () => {
12282
+ const reload = React59.useCallback(async () => {
12032
12283
  if (!threadRef.current) return;
12033
12284
  setStatus("loading");
12034
12285
  try {
@@ -12066,11 +12317,11 @@ var ChatKit = {
12066
12317
  };
12067
12318
 
12068
12319
  // src/components/chat/ChatTranscript.tsx
12069
- var React60 = __toESM(require("react"), 1);
12320
+ var React61 = __toESM(require("react"), 1);
12070
12321
 
12071
12322
  // src/components/chat/ChatTurn.tsx
12072
- var React59 = __toESM(require("react"), 1);
12073
- var import_jsx_runtime91 = require("react/jsx-runtime");
12323
+ var React60 = __toESM(require("react"), 1);
12324
+ var import_jsx_runtime92 = require("react/jsx-runtime");
12074
12325
  function JsonView({ value }) {
12075
12326
  let text;
12076
12327
  try {
@@ -12078,67 +12329,67 @@ function JsonView({ value }) {
12078
12329
  } catch (e) {
12079
12330
  text = String(value);
12080
12331
  }
12081
- return /* @__PURE__ */ (0, import_jsx_runtime91.jsx)(CodeBlock, { code: text, language: "json", collapseAfter: 18 });
12332
+ return /* @__PURE__ */ (0, import_jsx_runtime92.jsx)(CodeBlock, { code: text, language: "json", collapseAfter: 18 });
12082
12333
  }
12083
12334
  function PacketCard({ packet, schema, render, onApply, applied }) {
12084
12335
  if (!packet) return null;
12085
12336
  const s = schema || {};
12086
12337
  const invalid = packet.valid === false;
12087
12338
  const title = s.heading || packet.type;
12088
- return /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)("section", { className: "fdc-packet" + (invalid ? " is-invalid" : ""), "aria-label": title, children: [
12089
- /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)("header", { className: "fdc-packet-head", children: [
12090
- /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("i", { className: "ph ph-" + (s.icon || "package"), "aria-hidden": "true" }),
12091
- /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("span", { className: "fdc-packet-title", title: truncationTitle(title), children: title }),
12092
- packet.repaired ? /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("span", { className: "fdc-packet-badge", children: "Repaired" }) : null,
12093
- invalid ? /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("span", { className: "fdc-packet-badge is-danger", children: "Invalid" }) : null
12339
+ return /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("section", { className: "fdc-packet" + (invalid ? " is-invalid" : ""), "aria-label": title, children: [
12340
+ /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("header", { className: "fdc-packet-head", children: [
12341
+ /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("i", { className: "ph ph-" + (s.icon || "package"), "aria-hidden": "true" }),
12342
+ /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("span", { className: "fdc-packet-title", title: truncationTitle(title), children: title }),
12343
+ packet.repaired ? /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("span", { className: "fdc-packet-badge", children: "Repaired" }) : null,
12344
+ invalid ? /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("span", { className: "fdc-packet-badge is-danger", children: "Invalid" }) : null
12094
12345
  ] }),
12095
- invalid ? /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)("div", { className: "fdc-packet-alert", role: "alert", children: [
12096
- /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
12097
- /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("span", { children: packet.error || "This result failed validation and can\u2019t be applied." })
12098
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("div", { className: "fdc-packet-body", children: render ? render(packet) : /* @__PURE__ */ (0, import_jsx_runtime91.jsx)(JsonView, { value: packet.payload }) }),
12099
- !invalid && onApply ? /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)("footer", { className: "fdc-packet-foot", children: [
12100
- packet.repaired ? /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("span", { className: "fdc-packet-note", children: "Corrected by the backend after a first attempt." }) : /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("span", {}),
12101
- /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)("button", { type: "button", className: "fd-btn fd-btn-primary fd-btn-sm", disabled: applied, onClick: () => onApply(packet), children: [
12102
- /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("i", { className: "ph ph-" + (applied ? "check" : "arrow-square-in"), "aria-hidden": "true" }),
12346
+ invalid ? /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("div", { className: "fdc-packet-alert", role: "alert", children: [
12347
+ /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
12348
+ /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("span", { children: packet.error || "This result failed validation and can\u2019t be applied." })
12349
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("div", { className: "fdc-packet-body", children: render ? render(packet) : /* @__PURE__ */ (0, import_jsx_runtime92.jsx)(JsonView, { value: packet.payload }) }),
12350
+ !invalid && onApply ? /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("footer", { className: "fdc-packet-foot", children: [
12351
+ packet.repaired ? /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("span", { className: "fdc-packet-note", children: "Corrected by the backend after a first attempt." }) : /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("span", {}),
12352
+ /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("button", { type: "button", className: "fd-btn fd-btn-primary fd-btn-sm", disabled: applied, onClick: () => onApply(packet), children: [
12353
+ /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("i", { className: "ph ph-" + (applied ? "check" : "arrow-square-in"), "aria-hidden": "true" }),
12103
12354
  applied ? "Applied" : s.applyLabel || "Apply"
12104
12355
  ] })
12105
12356
  ] }) : null
12106
12357
  ] });
12107
12358
  }
12108
12359
  function ThinkingBlock({ text, durationMs, streaming, defaultOpen = false }) {
12109
- const [open2, setOpen] = React59.useState(defaultOpen);
12360
+ const [open2, setOpen] = React60.useState(defaultOpen);
12110
12361
  if (!text) return null;
12111
- return /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)("div", { className: "fdc-think" + (open2 ? " is-open" : ""), children: [
12112
- /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)("button", { type: "button", className: "fdc-think-head", onClick: () => setOpen((v) => !v), "aria-expanded": open2, children: [
12113
- /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("i", { className: "ph ph-brain", "aria-hidden": "true" }),
12114
- /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("span", { children: streaming ? "Thinking" : durationMs ? "Thought for " + formatDuration(durationMs) : "Thought process" }),
12115
- streaming ? /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)("span", { className: "fdc-dots", "aria-hidden": "true", children: [
12116
- /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("span", {}),
12117
- /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("span", {}),
12118
- /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("span", {})
12362
+ return /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("div", { className: "fdc-think" + (open2 ? " is-open" : ""), children: [
12363
+ /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("button", { type: "button", className: "fdc-think-head", onClick: () => setOpen((v) => !v), "aria-expanded": open2, children: [
12364
+ /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("i", { className: "ph ph-brain", "aria-hidden": "true" }),
12365
+ /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("span", { children: streaming ? "Thinking" : durationMs ? "Thought for " + formatDuration(durationMs) : "Thought process" }),
12366
+ streaming ? /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("span", { className: "fdc-dots", "aria-hidden": "true", children: [
12367
+ /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("span", {}),
12368
+ /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("span", {}),
12369
+ /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("span", {})
12119
12370
  ] }) : null,
12120
- /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("i", { className: "ph ph-caret-" + (open2 ? "up" : "down"), "aria-hidden": "true" })
12371
+ /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("i", { className: "ph ph-caret-" + (open2 ? "up" : "down"), "aria-hidden": "true" })
12121
12372
  ] }),
12122
- open2 ? /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("div", { className: "fdc-think-body", children: text }) : null
12373
+ open2 ? /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("div", { className: "fdc-think-body", children: text }) : null
12123
12374
  ] });
12124
12375
  }
12125
12376
  function Citations({ items = [], onOpen }) {
12126
- const [open2, setOpen] = React59.useState(false);
12377
+ const [open2, setOpen] = React60.useState(false);
12127
12378
  if (!items.length) return null;
12128
- return /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)("div", { className: "fdc-cites", children: [
12129
- /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)("button", { type: "button", className: "fdc-cites-head", onClick: () => setOpen((v) => !v), "aria-expanded": open2, children: [
12130
- /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("i", { className: "ph ph-quotes", "aria-hidden": "true" }),
12131
- /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)("span", { children: [
12379
+ return /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("div", { className: "fdc-cites", children: [
12380
+ /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("button", { type: "button", className: "fdc-cites-head", onClick: () => setOpen((v) => !v), "aria-expanded": open2, children: [
12381
+ /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("i", { className: "ph ph-quotes", "aria-hidden": "true" }),
12382
+ /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("span", { children: [
12132
12383
  items.length,
12133
12384
  " source",
12134
12385
  items.length === 1 ? "" : "s"
12135
12386
  ] }),
12136
- /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("i", { className: "ph ph-caret-" + (open2 ? "up" : "down"), "aria-hidden": "true" })
12387
+ /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("i", { className: "ph ph-caret-" + (open2 ? "up" : "down"), "aria-hidden": "true" })
12137
12388
  ] }),
12138
- open2 ? /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("ol", { className: "fdc-cites-list", children: items.map((c, i) => /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)("li", { children: [
12139
- /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("span", { className: "fdc-cite-n fd-tabular", children: c.marker || i + 1 }),
12140
- c.url ? /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("a", { href: c.url, target: "_blank", rel: "noopener noreferrer", onClick: onOpen ? (e) => onOpen(c, e) : void 0, children: c.title || c.url }) : /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("span", { children: c.title || "Source" }),
12141
- c.detail ? /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("span", { className: "fdc-cite-detail", children: c.detail }) : null
12389
+ open2 ? /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("ol", { className: "fdc-cites-list", children: items.map((c, i) => /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("li", { children: [
12390
+ /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("span", { className: "fdc-cite-n fd-tabular", children: c.marker || i + 1 }),
12391
+ c.url ? /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("a", { href: c.url, target: "_blank", rel: "noopener noreferrer", onClick: onOpen ? (e) => onOpen(c, e) : void 0, children: c.title || c.url }) : /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("span", { children: c.title || "Source" }),
12392
+ c.detail ? /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("span", { className: "fdc-cite-detail", children: c.detail }) : null
12142
12393
  ] }, c.id || i)) }) : null
12143
12394
  ] });
12144
12395
  }
@@ -12149,29 +12400,29 @@ function clampText(text, max) {
12149
12400
  return (at > max * 0.6 ? cut.slice(0, at) : cut).trimEnd() + "\u2026";
12150
12401
  }
12151
12402
  function MessageBody({ message: m, ctx }) {
12152
- const [expanded, setExpanded] = React59.useState(false);
12403
+ const [expanded, setExpanded] = React60.useState(false);
12153
12404
  const isUser = m.role === "user";
12154
12405
  const raw = m.text || "";
12155
12406
  const clamped = !expanded && !m.streaming ? clampText(raw, ctx.maxVisibleChars) : null;
12156
12407
  const body = clamped != null ? clamped : raw;
12157
12408
  const showMd = ctx.markdown && !isUser;
12158
- return /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)("div", { className: "fdc-body", children: [
12159
- m.thinking && ctx.showThinking ? /* @__PURE__ */ (0, import_jsx_runtime91.jsx)(ThinkingBlock, { text: m.thinking, durationMs: m.thinkingMs, streaming: m.streaming && !m.text }) : null,
12160
- m.steps && m.steps.length && ctx.showSteps ? /* @__PURE__ */ (0, import_jsx_runtime91.jsx)(StepList, { steps: m.steps, defaultOpen: m.steps.some((s) => s.status === "running"), dense: true }) : null,
12161
- body ? /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)("div", { className: "fdc-text" + (isUser ? " is-user" : ""), children: [
12162
- showMd ? /* @__PURE__ */ (0, import_jsx_runtime91.jsx)(Markdown, { source: body, headingOffset: 2, codeProps: { collapseAfter: 22 }, renderCitation: ctx.renderCitation }) : /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("div", { className: "fdc-plain", children: body }),
12163
- m.streaming ? /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("span", { className: "fdc-caret", "aria-hidden": "true" }) : null
12409
+ return /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("div", { className: "fdc-body", children: [
12410
+ m.thinking && ctx.showThinking ? /* @__PURE__ */ (0, import_jsx_runtime92.jsx)(ThinkingBlock, { text: m.thinking, durationMs: m.thinkingMs, streaming: m.streaming && !m.text }) : null,
12411
+ m.steps && m.steps.length && ctx.showSteps ? /* @__PURE__ */ (0, import_jsx_runtime92.jsx)(StepList, { steps: m.steps, defaultOpen: m.steps.some((s) => s.status === "running"), dense: true }) : null,
12412
+ body ? /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("div", { className: "fdc-text" + (isUser ? " is-user" : ""), children: [
12413
+ showMd ? /* @__PURE__ */ (0, import_jsx_runtime92.jsx)(Markdown, { source: body, headingOffset: 2, codeProps: { collapseAfter: 22 }, renderCitation: ctx.renderCitation }) : /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("div", { className: "fdc-plain", children: body }),
12414
+ m.streaming ? /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("span", { className: "fdc-caret", "aria-hidden": "true" }) : null
12164
12415
  ] }) : null,
12165
- clamped != null ? /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)("button", { type: "button", className: "fdc-more", onClick: () => setExpanded(true), children: [
12166
- /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("i", { className: "ph ph-caret-down", "aria-hidden": "true" }),
12416
+ clamped != null ? /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("button", { type: "button", className: "fdc-more", onClick: () => setExpanded(true), children: [
12417
+ /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("i", { className: "ph ph-caret-down", "aria-hidden": "true" }),
12167
12418
  "Show more",
12168
- /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("span", { className: "fdc-more-len fd-tabular", children: raw.length < 2e3 ? raw.length.toLocaleString() + " characters" : Math.round(raw.length / 100) / 10 + "k characters" })
12169
- ] }) : expanded && ctx.maxVisibleChars && raw.length > ctx.maxVisibleChars ? /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)("button", { type: "button", className: "fdc-more", onClick: () => setExpanded(false), children: [
12170
- /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("i", { className: "ph ph-caret-up", "aria-hidden": "true" }),
12419
+ /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("span", { className: "fdc-more-len fd-tabular", children: raw.length < 2e3 ? raw.length.toLocaleString() + " characters" : Math.round(raw.length / 100) / 10 + "k characters" })
12420
+ ] }) : expanded && ctx.maxVisibleChars && raw.length > ctx.maxVisibleChars ? /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("button", { type: "button", className: "fdc-more", onClick: () => setExpanded(false), children: [
12421
+ /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("i", { className: "ph ph-caret-up", "aria-hidden": "true" }),
12171
12422
  "Show less"
12172
12423
  ] }) : null,
12173
- m.attachments && m.attachments.length ? /* @__PURE__ */ (0, import_jsx_runtime91.jsx)(FileGrid, { files: m.attachments, onOpen: ctx.onOpenAttachment, tiles: true, maxHeight: ctx.attachmentHeight || 220, compact: ctx.narrow }) : null,
12174
- m.packet ? /* @__PURE__ */ (0, import_jsx_runtime91.jsx)(
12424
+ m.attachments && m.attachments.length ? /* @__PURE__ */ (0, import_jsx_runtime92.jsx)(FileGrid, { files: m.attachments, onOpen: ctx.onOpenAttachment, tiles: true, maxHeight: ctx.attachmentHeight || 220, compact: ctx.narrow }) : null,
12425
+ m.packet ? /* @__PURE__ */ (0, import_jsx_runtime92.jsx)(
12175
12426
  PacketCard,
12176
12427
  {
12177
12428
  packet: m.packet,
@@ -12181,44 +12432,44 @@ function MessageBody({ message: m, ctx }) {
12181
12432
  applied: ctx.appliedPackets && ctx.appliedPackets[m.id]
12182
12433
  }
12183
12434
  ) : null,
12184
- m.citations && m.citations.length ? /* @__PURE__ */ (0, import_jsx_runtime91.jsx)(Citations, { items: m.citations, onOpen: ctx.onOpenCitation }) : null,
12185
- m.working ? /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)("div", { className: "fdc-working", role: "status", children: [
12186
- /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)("span", { className: "fdc-dots", "aria-hidden": "true", children: [
12187
- /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("span", {}),
12188
- /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("span", {}),
12189
- /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("span", {})
12435
+ m.citations && m.citations.length ? /* @__PURE__ */ (0, import_jsx_runtime92.jsx)(Citations, { items: m.citations, onOpen: ctx.onOpenCitation }) : null,
12436
+ m.working ? /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("div", { className: "fdc-working", role: "status", children: [
12437
+ /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("span", { className: "fdc-dots", "aria-hidden": "true", children: [
12438
+ /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("span", {}),
12439
+ /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("span", {}),
12440
+ /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("span", {})
12190
12441
  ] }),
12191
- /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)("span", { className: "fdc-working-label", children: [
12442
+ /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("span", { className: "fdc-working-label", children: [
12192
12443
  m.resumed ? "Resuming" : "Working",
12193
- m.job && m.job.status ? /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)("span", { className: "fdc-working-job", children: [
12444
+ m.job && m.job.status ? /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("span", { className: "fdc-working-job", children: [
12194
12445
  " \xB7 ",
12195
12446
  m.job.status
12196
12447
  ] }) : null,
12197
- m.job && m.job.detail ? /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)("span", { className: "fdc-working-job", children: [
12448
+ m.job && m.job.detail ? /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("span", { className: "fdc-working-job", children: [
12198
12449
  " \xB7 ",
12199
12450
  m.job.detail
12200
12451
  ] }) : null
12201
12452
  ] }),
12202
- m.jobId ? /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("span", { className: "fdc-working-id fd-mono", children: String(m.jobId).slice(0, 12) }) : null
12453
+ m.jobId ? /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("span", { className: "fdc-working-id fd-mono", children: String(m.jobId).slice(0, 12) }) : null
12203
12454
  ] }) : null,
12204
- m.stopped ? /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)("div", { className: "fdc-stopped", children: [
12205
- /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("i", { className: "ph ph-stop-circle", "aria-hidden": "true" }),
12455
+ m.stopped ? /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("div", { className: "fdc-stopped", children: [
12456
+ /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("i", { className: "ph ph-stop-circle", "aria-hidden": "true" }),
12206
12457
  "Stopped"
12207
12458
  ] }) : null,
12208
- m.error ? /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)("div", { className: "fdc-error", role: "alert", children: [
12209
- /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
12210
- /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("span", { className: "fdc-error-text", children: ctx.errorCopy ? ctx.errorCopy(m.error) : m.error }),
12211
- m.retryable && ctx.onRetry ? /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)("button", { type: "button", className: "fdc-error-retry", onClick: ctx.onRetry, children: [
12212
- /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("i", { className: "ph ph-arrow-clockwise", "aria-hidden": "true" }),
12459
+ m.error ? /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("div", { className: "fdc-error", role: "alert", children: [
12460
+ /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
12461
+ /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("span", { className: "fdc-error-text", children: ctx.errorCopy ? ctx.errorCopy(m.error) : m.error }),
12462
+ m.retryable && ctx.onRetry ? /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("button", { type: "button", className: "fdc-error-retry", onClick: ctx.onRetry, children: [
12463
+ /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("i", { className: "ph ph-arrow-clockwise", "aria-hidden": "true" }),
12213
12464
  "Retry"
12214
12465
  ] }) : null
12215
12466
  ] }) : null
12216
12467
  ] });
12217
12468
  }
12218
12469
  function useCopyRun() {
12219
- const [done, setDone] = React59.useState(false);
12220
- const t = React59.useRef(null);
12221
- React59.useEffect(() => () => {
12470
+ const [done, setDone] = React60.useState(false);
12471
+ const t = React60.useRef(null);
12472
+ React60.useEffect(() => () => {
12222
12473
  if (t.current) clearTimeout(t.current);
12223
12474
  }, []);
12224
12475
  return [done, (text) => {
@@ -12238,16 +12489,16 @@ function RunActions({ group, ctx }) {
12238
12489
  const isAssistant = group.role === "assistant";
12239
12490
  const fb = last.feedback;
12240
12491
  if (!ctx.messageActions) return null;
12241
- return /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)("div", { className: "fdc-actions", role: "group", "aria-label": "Message actions", children: [
12242
- /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)("button", { type: "button", className: "fdc-act" + (copied ? " is-done" : ""), onClick: () => copy(markdownToText(text)), "aria-label": "Copy message", children: [
12243
- /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("i", { className: "ph ph-" + (copied ? "check" : "copy"), "aria-hidden": "true" }),
12244
- /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("span", { className: "fdc-act-label", children: copied ? "Copied" : "Copy" })
12492
+ return /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("div", { className: "fdc-actions", role: "group", "aria-label": "Message actions", children: [
12493
+ /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("button", { type: "button", className: "fdc-act" + (copied ? " is-done" : ""), onClick: () => copy(markdownToText(text)), "aria-label": "Copy message", children: [
12494
+ /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("i", { className: "ph ph-" + (copied ? "check" : "copy"), "aria-hidden": "true" }),
12495
+ /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("span", { className: "fdc-act-label", children: copied ? "Copied" : "Copy" })
12245
12496
  ] }),
12246
- isAssistant && ctx.onRetry ? /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("button", { type: "button", className: "fdc-act", onClick: ctx.onRetry, "aria-label": "Retry this turn", children: /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("i", { className: "ph ph-arrow-clockwise", "aria-hidden": "true" }) }) : null,
12247
- group.role === "user" && ctx.onEdit ? /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("button", { type: "button", className: "fdc-act", onClick: () => ctx.onEdit(last), "aria-label": "Edit and resend", children: /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("i", { className: "ph ph-pencil-simple", "aria-hidden": "true" }) }) : null,
12248
- isAssistant && ctx.onFeedback ? /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)(React59.Fragment, { children: [
12249
- /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("button", { type: "button", className: "fdc-act" + (fb === "up" ? " is-on" : ""), onClick: () => ctx.onFeedback(last.id, "up"), "aria-pressed": fb === "up", "aria-label": "Good response", children: /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("i", { className: "ph ph-thumbs-up", "aria-hidden": "true" }) }),
12250
- /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("button", { type: "button", className: "fdc-act" + (fb === "down" ? " is-on" : ""), onClick: () => ctx.onFeedback(last.id, "down"), "aria-pressed": fb === "down", "aria-label": "Bad response", children: /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("i", { className: "ph ph-thumbs-down", "aria-hidden": "true" }) })
12497
+ isAssistant && ctx.onRetry ? /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("button", { type: "button", className: "fdc-act", onClick: ctx.onRetry, "aria-label": "Retry this turn", children: /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("i", { className: "ph ph-arrow-clockwise", "aria-hidden": "true" }) }) : null,
12498
+ group.role === "user" && ctx.onEdit ? /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("button", { type: "button", className: "fdc-act", onClick: () => ctx.onEdit(last), "aria-label": "Edit and resend", children: /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("i", { className: "ph ph-pencil-simple", "aria-hidden": "true" }) }) : null,
12499
+ isAssistant && ctx.onFeedback ? /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)(React60.Fragment, { children: [
12500
+ /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("button", { type: "button", className: "fdc-act" + (fb === "up" ? " is-on" : ""), onClick: () => ctx.onFeedback(last.id, "up"), "aria-pressed": fb === "up", "aria-label": "Good response", children: /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("i", { className: "ph ph-thumbs-up", "aria-hidden": "true" }) }),
12501
+ /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("button", { type: "button", className: "fdc-act" + (fb === "down" ? " is-on" : ""), onClick: () => ctx.onFeedback(last.id, "down"), "aria-pressed": fb === "down", "aria-label": "Bad response", children: /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("i", { className: "ph ph-thumbs-down", "aria-hidden": "true" }) })
12251
12502
  ] }) : null,
12252
12503
  ctx.extraActions ? ctx.extraActions(group) : null
12253
12504
  ] });
@@ -12257,22 +12508,22 @@ function ChatTurn({ group, ctx }) {
12257
12508
  const name = isUser ? ctx.userName : group.author || ctx.assistantName;
12258
12509
  const avatar = isUser ? ctx.userAvatar : ctx.assistantAvatar;
12259
12510
  const stamp = group.messages[0].timestamp;
12260
- return /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)("article", { className: "fdc-turn is-" + group.role, "aria-label": String(name) + (stamp ? " at " + formatClock(stamp) : ""), children: [
12261
- /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)("div", { className: "fdc-turn-head", children: [
12262
- ctx.showAvatars ? /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("span", { className: "fdc-avatar is-" + group.role, "aria-hidden": "true", children: avatar ? /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("img", { src: avatar, alt: "" }) : isUser ? /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("span", { className: "fdc-avatar-txt", children: (name || "You").slice(0, 1).toUpperCase() }) : /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("i", { className: "ph ph-" + (ctx.assistantIcon || "sparkle") }) }) : null,
12263
- /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("span", { className: "fdc-who", children: name }),
12264
- stamp ? /* @__PURE__ */ (0, import_jsx_runtime91.jsx)(RelativeTime, { className: "fdc-when", value: stamp }) : null,
12265
- group.messages.some((m) => m.model) ? /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("span", { className: "fdc-turn-model", children: group.messages.find((m) => m.model).model }) : null
12511
+ return /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("article", { className: "fdc-turn is-" + group.role, "aria-label": String(name) + (stamp ? " at " + formatClock(stamp) : ""), children: [
12512
+ /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("div", { className: "fdc-turn-head", children: [
12513
+ ctx.showAvatars ? /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("span", { className: "fdc-avatar is-" + group.role, "aria-hidden": "true", children: avatar ? /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("img", { src: avatar, alt: "" }) : isUser ? /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("span", { className: "fdc-avatar-txt", children: (name || "You").slice(0, 1).toUpperCase() }) : /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("i", { className: "ph ph-" + (ctx.assistantIcon || "sparkle") }) }) : null,
12514
+ /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("span", { className: "fdc-who", children: name }),
12515
+ stamp ? /* @__PURE__ */ (0, import_jsx_runtime92.jsx)(RelativeTime, { className: "fdc-when", value: stamp }) : null,
12516
+ group.messages.some((m) => m.model) ? /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("span", { className: "fdc-turn-model", children: group.messages.find((m) => m.model).model }) : null
12266
12517
  ] }),
12267
- /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)("div", { className: "fdc-turn-body", children: [
12268
- group.messages.map((m) => /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("div", { className: "fdc-msg" + (m.pending ? " is-pending" : ""), children: /* @__PURE__ */ (0, import_jsx_runtime91.jsx)(MessageBody, { message: m, ctx }) }, m.id)),
12269
- /* @__PURE__ */ (0, import_jsx_runtime91.jsx)(RunActions, { group, ctx })
12518
+ /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("div", { className: "fdc-turn-body", children: [
12519
+ group.messages.map((m) => /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("div", { className: "fdc-msg" + (m.pending ? " is-pending" : ""), children: /* @__PURE__ */ (0, import_jsx_runtime92.jsx)(MessageBody, { message: m, ctx }) }, m.id)),
12520
+ /* @__PURE__ */ (0, import_jsx_runtime92.jsx)(RunActions, { group, ctx })
12270
12521
  ] })
12271
12522
  ] });
12272
12523
  }
12273
12524
 
12274
12525
  // src/components/chat/ChatTranscript.tsx
12275
- var import_jsx_runtime92 = require("react/jsx-runtime");
12526
+ var import_jsx_runtime93 = require("react/jsx-runtime");
12276
12527
  var GROUP_WINDOW = 6e4;
12277
12528
  var STICK_PX = 100;
12278
12529
  function groupMessages(list) {
@@ -12305,25 +12556,25 @@ function dayLabel(key) {
12305
12556
  }
12306
12557
  function Suggestions({ items = [], onPick }) {
12307
12558
  if (!items.length) return null;
12308
- return /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("div", { className: "fdc-suggest", children: items.map((s, i) => {
12559
+ return /* @__PURE__ */ (0, import_jsx_runtime93.jsx)("div", { className: "fdc-suggest", children: items.map((s, i) => {
12309
12560
  const it = typeof s === "string" ? { label: s, text: s } : s;
12310
- return /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("button", { type: "button", className: "fdc-suggest-item", onClick: () => onPick && onPick(it.text || it.label), children: [
12311
- it.icon ? /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("i", { className: "ph ph-" + it.icon, "aria-hidden": "true" }) : null,
12312
- /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("span", { className: "fdc-suggest-text", children: [
12313
- /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("span", { className: "fdc-suggest-label", children: it.label }),
12314
- it.description ? /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("span", { className: "fdc-suggest-desc", children: it.description }) : null
12561
+ return /* @__PURE__ */ (0, import_jsx_runtime93.jsxs)("button", { type: "button", className: "fdc-suggest-item", onClick: () => onPick && onPick(it.text || it.label), children: [
12562
+ it.icon ? /* @__PURE__ */ (0, import_jsx_runtime93.jsx)("i", { className: "ph ph-" + it.icon, "aria-hidden": "true" }) : null,
12563
+ /* @__PURE__ */ (0, import_jsx_runtime93.jsxs)("span", { className: "fdc-suggest-text", children: [
12564
+ /* @__PURE__ */ (0, import_jsx_runtime93.jsx)("span", { className: "fdc-suggest-label", children: it.label }),
12565
+ it.description ? /* @__PURE__ */ (0, import_jsx_runtime93.jsx)("span", { className: "fdc-suggest-desc", children: it.description }) : null
12315
12566
  ] }),
12316
- /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("i", { className: "ph ph-arrow-up-right fdc-suggest-go", "aria-hidden": "true" })
12567
+ /* @__PURE__ */ (0, import_jsx_runtime93.jsx)("i", { className: "ph ph-arrow-up-right fdc-suggest-go", "aria-hidden": "true" })
12317
12568
  ] }, it.id || i);
12318
12569
  }) });
12319
12570
  }
12320
12571
  function LoadingTurns() {
12321
- return /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("div", { className: "fdc-skel", "aria-hidden": "true", children: [0, 1].map((i) => /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("div", { className: "fdc-skel-turn", children: [
12322
- /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("div", { className: "fd-skel fd-skel-circle", style: { width: 22, height: 22 } }),
12323
- /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("div", { className: "fdc-skel-lines", children: [
12324
- /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("div", { className: "fd-skel", style: { width: i ? "62%" : "44%", height: 11 } }),
12325
- /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("div", { className: "fd-skel", style: { width: i ? "94%" : "78%", height: 11 } }),
12326
- /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("div", { className: "fd-skel", style: { width: i ? "71%" : "56%", height: 11 } })
12572
+ return /* @__PURE__ */ (0, import_jsx_runtime93.jsx)("div", { className: "fdc-skel", "aria-hidden": "true", children: [0, 1].map((i) => /* @__PURE__ */ (0, import_jsx_runtime93.jsxs)("div", { className: "fdc-skel-turn", children: [
12573
+ /* @__PURE__ */ (0, import_jsx_runtime93.jsx)("div", { className: "fd-skel fd-skel-circle", style: { width: 22, height: 22 } }),
12574
+ /* @__PURE__ */ (0, import_jsx_runtime93.jsxs)("div", { className: "fdc-skel-lines", children: [
12575
+ /* @__PURE__ */ (0, import_jsx_runtime93.jsx)("div", { className: "fd-skel", style: { width: i ? "62%" : "44%", height: 11 } }),
12576
+ /* @__PURE__ */ (0, import_jsx_runtime93.jsx)("div", { className: "fd-skel", style: { width: i ? "94%" : "78%", height: 11 } }),
12577
+ /* @__PURE__ */ (0, import_jsx_runtime93.jsx)("div", { className: "fd-skel", style: { width: i ? "71%" : "56%", height: 11 } })
12327
12578
  ] })
12328
12579
  ] }, i)) });
12329
12580
  }
@@ -12340,10 +12591,10 @@ function ChatTranscript({
12340
12591
  renderEmpty,
12341
12592
  className = ""
12342
12593
  }) {
12343
- const scroller = React60.useRef(null);
12344
- const stick = React60.useRef(true);
12345
- const [pill, setPill] = React60.useState(0);
12346
- const seen = React60.useRef(0);
12594
+ const scroller = React61.useRef(null);
12595
+ const stick = React61.useRef(true);
12596
+ const [pill, setPill] = React61.useState(0);
12597
+ const seen = React61.useRef(0);
12347
12598
  const toBottom = (smooth) => {
12348
12599
  const el = scroller.current;
12349
12600
  if (!el) return;
@@ -12362,7 +12613,7 @@ function ChatTranscript({
12362
12613
  seen.current = messages.length;
12363
12614
  }
12364
12615
  };
12365
- React60.useLayoutEffect(() => {
12616
+ React61.useLayoutEffect(() => {
12366
12617
  const el = scroller.current;
12367
12618
  if (!el) return;
12368
12619
  if (stick.current) {
@@ -12370,7 +12621,7 @@ function ChatTranscript({
12370
12621
  seen.current = messages.length;
12371
12622
  } else setPill(Math.max(0, messages.length - seen.current));
12372
12623
  }, [messages]);
12373
- React60.useEffect(() => {
12624
+ React61.useEffect(() => {
12374
12625
  const el = scroller.current;
12375
12626
  const inner = el && el.firstChild;
12376
12627
  if (!el || !inner || typeof ResizeObserver === "undefined") return;
@@ -12380,38 +12631,38 @@ function ChatTranscript({
12380
12631
  ro.observe(inner);
12381
12632
  return () => ro.disconnect();
12382
12633
  }, []);
12383
- const groups = React60.useMemo(() => groupMessages(messages), [messages]);
12634
+ const groups = React61.useMemo(() => groupMessages(messages), [messages]);
12384
12635
  const empty = !messages.length && status === "ready";
12385
- return /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("div", { className: ["fdc-scroll", className].filter(Boolean).join(" "), ref: scroller, onScroll, children: [
12386
- /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("div", { className: "fdc-log", role: "log", "aria-label": "Conversation", children: [
12387
- status === "loading" || status === "resolving" ? /* @__PURE__ */ (0, import_jsx_runtime92.jsx)(LoadingTurns, {}) : null,
12388
- status === "disconnected" ? /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("div", { className: "fdc-dead", children: [
12389
- /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("span", { className: "fdc-dead-icon", children: /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("i", { className: "ph ph-plugs", "aria-hidden": "true" }) }),
12390
- /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("h3", { className: "fdc-dead-title", children: ctx.deadTitle || "The assistant isn\u2019t reachable" }),
12391
- /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("p", { className: "fdc-dead-body", children: fatal === "chat_unavailable" ? "The service reported chat_unavailable. Nothing you type will be lost \u2014 reopen the panel once it\u2019s back." : "The thread couldn\u2019t be resolved" + (fatal ? " (" + fatal + ")" : "") + ". The composer stays disabled until it resolves." }),
12392
- ctx.onReconnect ? /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("button", { type: "button", className: "fd-btn fd-btn-secondary fd-btn-sm", onClick: ctx.onReconnect, children: [
12393
- /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("i", { className: "ph ph-arrow-clockwise", "aria-hidden": "true" }),
12636
+ return /* @__PURE__ */ (0, import_jsx_runtime93.jsxs)("div", { className: ["fdc-scroll", className].filter(Boolean).join(" "), ref: scroller, onScroll, children: [
12637
+ /* @__PURE__ */ (0, import_jsx_runtime93.jsxs)("div", { className: "fdc-log", role: "log", "aria-label": "Conversation", children: [
12638
+ status === "loading" || status === "resolving" ? /* @__PURE__ */ (0, import_jsx_runtime93.jsx)(LoadingTurns, {}) : null,
12639
+ status === "disconnected" ? /* @__PURE__ */ (0, import_jsx_runtime93.jsxs)("div", { className: "fdc-dead", children: [
12640
+ /* @__PURE__ */ (0, import_jsx_runtime93.jsx)("span", { className: "fdc-dead-icon", children: /* @__PURE__ */ (0, import_jsx_runtime93.jsx)("i", { className: "ph ph-plugs", "aria-hidden": "true" }) }),
12641
+ /* @__PURE__ */ (0, import_jsx_runtime93.jsx)("h3", { className: "fdc-dead-title", children: ctx.deadTitle || "The assistant isn\u2019t reachable" }),
12642
+ /* @__PURE__ */ (0, import_jsx_runtime93.jsx)("p", { className: "fdc-dead-body", children: fatal === "chat_unavailable" ? "The service reported chat_unavailable. Nothing you type will be lost \u2014 reopen the panel once it\u2019s back." : "The thread couldn\u2019t be resolved" + (fatal ? " (" + fatal + ")" : "") + ". The composer stays disabled until it resolves." }),
12643
+ ctx.onReconnect ? /* @__PURE__ */ (0, import_jsx_runtime93.jsxs)("button", { type: "button", className: "fd-btn fd-btn-secondary fd-btn-sm", onClick: ctx.onReconnect, children: [
12644
+ /* @__PURE__ */ (0, import_jsx_runtime93.jsx)("i", { className: "ph ph-arrow-clockwise", "aria-hidden": "true" }),
12394
12645
  "Try again"
12395
12646
  ] }) : null
12396
12647
  ] }) : null,
12397
- empty ? renderEmpty ? renderEmpty() : /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("div", { className: "fdc-empty", children: [
12398
- /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("span", { className: "fdc-empty-icon", children: /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("i", { className: "ph ph-" + emptyIcon, "aria-hidden": "true" }) }),
12399
- /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("h3", { className: "fdc-empty-title", children: emptyTitle }),
12400
- emptyDescription ? /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("p", { className: "fdc-empty-body", children: emptyDescription }) : null,
12401
- /* @__PURE__ */ (0, import_jsx_runtime92.jsx)(Suggestions, { items: suggestions, onPick })
12648
+ empty ? renderEmpty ? renderEmpty() : /* @__PURE__ */ (0, import_jsx_runtime93.jsxs)("div", { className: "fdc-empty", children: [
12649
+ /* @__PURE__ */ (0, import_jsx_runtime93.jsx)("span", { className: "fdc-empty-icon", children: /* @__PURE__ */ (0, import_jsx_runtime93.jsx)("i", { className: "ph ph-" + emptyIcon, "aria-hidden": "true" }) }),
12650
+ /* @__PURE__ */ (0, import_jsx_runtime93.jsx)("h3", { className: "fdc-empty-title", children: emptyTitle }),
12651
+ emptyDescription ? /* @__PURE__ */ (0, import_jsx_runtime93.jsx)("p", { className: "fdc-empty-body", children: emptyDescription }) : null,
12652
+ /* @__PURE__ */ (0, import_jsx_runtime93.jsx)(Suggestions, { items: suggestions, onPick })
12402
12653
  ] }) : null,
12403
12654
  groups.map((g, i) => {
12404
12655
  const prev = groups[i - 1];
12405
12656
  const k = dayKey(g.messages[0].timestamp);
12406
12657
  const showDay = !!k && (!prev || dayKey(prev.messages[0].timestamp) !== k);
12407
- return /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)(React60.Fragment, { children: [
12408
- showDay ? /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("div", { className: "fdc-day", children: /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("span", { children: dayLabel(k) }) }) : null,
12409
- /* @__PURE__ */ (0, import_jsx_runtime92.jsx)(ChatTurn, { group: g, ctx })
12658
+ return /* @__PURE__ */ (0, import_jsx_runtime93.jsxs)(React61.Fragment, { children: [
12659
+ showDay ? /* @__PURE__ */ (0, import_jsx_runtime93.jsx)("div", { className: "fdc-day", children: /* @__PURE__ */ (0, import_jsx_runtime93.jsx)("span", { children: dayLabel(k) }) }) : null,
12660
+ /* @__PURE__ */ (0, import_jsx_runtime93.jsx)(ChatTurn, { group: g, ctx })
12410
12661
  ] }, g.key || i);
12411
12662
  })
12412
12663
  ] }),
12413
- pill ? /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("button", { type: "button", className: "fdc-pill", onClick: () => toBottom(true), children: [
12414
- /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("i", { className: "ph ph-arrow-down", "aria-hidden": "true" }),
12664
+ pill ? /* @__PURE__ */ (0, import_jsx_runtime93.jsxs)("button", { type: "button", className: "fdc-pill", onClick: () => toBottom(true), children: [
12665
+ /* @__PURE__ */ (0, import_jsx_runtime93.jsx)("i", { className: "ph ph-arrow-down", "aria-hidden": "true" }),
12415
12666
  pill,
12416
12667
  " new message",
12417
12668
  pill === 1 ? "" : "s"
@@ -12421,8 +12672,8 @@ function ChatTranscript({
12421
12672
  var TranscriptKit = { groupMessages };
12422
12673
 
12423
12674
  // src/components/chat/ChatComposer.tsx
12424
- var React61 = __toESM(require("react"), 1);
12425
- var import_jsx_runtime93 = require("react/jsx-runtime");
12675
+ var React62 = __toESM(require("react"), 1);
12676
+ var import_jsx_runtime94 = require("react/jsx-runtime");
12426
12677
  function ChatComposer({
12427
12678
  onSubmit,
12428
12679
  onStop,
@@ -12449,17 +12700,17 @@ function ChatComposer({
12449
12700
  onReject,
12450
12701
  onOpenAttachment
12451
12702
  }) {
12452
- const [text, setText] = React61.useState(draft || "");
12453
- const [trigger, setTrigger] = React61.useState(null);
12454
- const [mentionItems, setMentionItems] = React61.useState([]);
12455
- const [listening, setListening] = React61.useState(false);
12456
- const [notice, setNotice] = React61.useState(null);
12457
- const editor = React61.useRef(null);
12458
- const wrap = React61.useRef(null);
12459
- const stopVoice = React61.useRef(null);
12703
+ const [text, setText] = React62.useState(draft || "");
12704
+ const [trigger, setTrigger] = React62.useState(null);
12705
+ const [mentionItems, setMentionItems] = React62.useState([]);
12706
+ const [listening, setListening] = React62.useState(false);
12707
+ const [notice, setNotice] = React62.useState(null);
12708
+ const editor = React62.useRef(null);
12709
+ const wrap = React62.useRef(null);
12710
+ const stopVoice = React62.useRef(null);
12460
12711
  const staged = useStagedFiles(fileUploadHandler, { onError: () => {
12461
12712
  } });
12462
- React61.useEffect(() => {
12713
+ React62.useEffect(() => {
12463
12714
  if (draft != null && draft !== text) setText(draft);
12464
12715
  }, [draft]);
12465
12716
  const change = (v) => {
@@ -12495,7 +12746,7 @@ function ChatComposer({
12495
12746
  e.preventDefault();
12496
12747
  staged.add(found.files);
12497
12748
  };
12498
- React61.useEffect(() => {
12749
+ React62.useEffect(() => {
12499
12750
  if (!trigger || trigger.type !== "mention" || !mentionSources) {
12500
12751
  setMentionItems([]);
12501
12752
  return;
@@ -12513,7 +12764,7 @@ function ChatComposer({
12513
12764
  const q = (trigger.query || "").toLowerCase();
12514
12765
  setMentionItems(mentionSources.filter((m) => !q || (m.label + " " + (m.description || "")).toLowerCase().includes(q)));
12515
12766
  }, [trigger, mentionSources]);
12516
- const slashItems = React61.useMemo(() => {
12767
+ const slashItems = React62.useMemo(() => {
12517
12768
  if (!trigger || trigger.type !== "slash" || !slashCommands) return [];
12518
12769
  const q = (trigger.query || "").toLowerCase();
12519
12770
  return slashCommands.filter((c) => !q || (c.id + " " + c.label + " " + (c.description || "")).toLowerCase().includes(q));
@@ -12527,7 +12778,7 @@ function ChatComposer({
12527
12778
  description: it.description,
12528
12779
  icon: it.icon,
12529
12780
  meta: mention.meta,
12530
- shortcut: slash.shortcut ? /* @__PURE__ */ (0, import_jsx_runtime93.jsx)(KeyHint, { keys: slash.shortcut, size: "sm" }) : void 0,
12781
+ shortcut: slash.shortcut ? /* @__PURE__ */ (0, import_jsx_runtime94.jsx)(KeyHint, { keys: slash.shortcut, size: "sm" }) : void 0,
12531
12782
  onSelect: () => {
12532
12783
  const insert = trigger.type === "slash" ? slash.immediate ? "/" + slash.id : "/" + slash.id + " " : "@" + (mention.value || mention.label) + " ";
12533
12784
  editor.current && editor.current.replaceRange(trigger.from, trigger.to, insert);
@@ -12586,14 +12837,14 @@ function ChatComposer({
12586
12837
  stopVoice.current = typeof res === "function" ? res : () => {
12587
12838
  };
12588
12839
  };
12589
- return /* @__PURE__ */ (0, import_jsx_runtime93.jsxs)("div", { className: "fdc-composer" + (disabled ? " is-disabled" : "") + (narrow ? " is-narrow" : ""), children: [
12590
- queue.length ? /* @__PURE__ */ (0, import_jsx_runtime93.jsx)("div", { className: "fdc-queue", "aria-label": "Queued messages", children: queue.map((q) => /* @__PURE__ */ (0, import_jsx_runtime93.jsxs)("div", { className: "fdc-queue-row", children: [
12591
- /* @__PURE__ */ (0, import_jsx_runtime93.jsx)("i", { className: "ph ph-clock-countdown", "aria-hidden": "true" }),
12592
- /* @__PURE__ */ (0, import_jsx_runtime93.jsx)("span", { className: "fdc-queue-text", title: truncationTitle(q.text || (q.attachments ? q.attachments.length + " file(s)" : "")), children: q.text || (q.attachments ? q.attachments.length + " file(s)" : "") }),
12593
- onRemoveQueued ? /* @__PURE__ */ (0, import_jsx_runtime93.jsx)("button", { type: "button", className: "fdc-queue-x", onClick: () => onRemoveQueued(q.id), "aria-label": "Remove queued message", children: /* @__PURE__ */ (0, import_jsx_runtime93.jsx)("i", { className: "ph ph-x", "aria-hidden": "true" }) }) : null
12840
+ return /* @__PURE__ */ (0, import_jsx_runtime94.jsxs)("div", { className: "fdc-composer" + (disabled ? " is-disabled" : "") + (narrow ? " is-narrow" : ""), children: [
12841
+ queue.length ? /* @__PURE__ */ (0, import_jsx_runtime94.jsx)("div", { className: "fdc-queue", "aria-label": "Queued messages", children: queue.map((q) => /* @__PURE__ */ (0, import_jsx_runtime94.jsxs)("div", { className: "fdc-queue-row", children: [
12842
+ /* @__PURE__ */ (0, import_jsx_runtime94.jsx)("i", { className: "ph ph-clock-countdown", "aria-hidden": "true" }),
12843
+ /* @__PURE__ */ (0, import_jsx_runtime94.jsx)("span", { className: "fdc-queue-text", title: truncationTitle(q.text || (q.attachments ? q.attachments.length + " file(s)" : "")), children: q.text || (q.attachments ? q.attachments.length + " file(s)" : "") }),
12844
+ onRemoveQueued ? /* @__PURE__ */ (0, import_jsx_runtime94.jsx)("button", { type: "button", className: "fdc-queue-x", onClick: () => onRemoveQueued(q.id), "aria-label": "Remove queued message", children: /* @__PURE__ */ (0, import_jsx_runtime94.jsx)("i", { className: "ph ph-x", "aria-hidden": "true" }) }) : null
12594
12845
  ] }, q.id)) }) : null,
12595
12846
  sessionBar,
12596
- /* @__PURE__ */ (0, import_jsx_runtime93.jsx)(
12847
+ /* @__PURE__ */ (0, import_jsx_runtime94.jsx)(
12597
12848
  Dropzone,
12598
12849
  {
12599
12850
  className: "fdc-field",
@@ -12607,9 +12858,9 @@ function ChatComposer({
12607
12858
  disabled: !fileUploadHandler || disabled,
12608
12859
  label: "Drop to attach",
12609
12860
  hint: acceptFiles ? acceptFiles.replace(/,/g, " \xB7 ") : void 0,
12610
- children: /* @__PURE__ */ (0, import_jsx_runtime93.jsxs)("div", { ref: wrap, className: "fdc-field-inner", children: [
12611
- staged.items.length ? /* @__PURE__ */ (0, import_jsx_runtime93.jsx)("div", { className: "fdc-staged", children: /* @__PURE__ */ (0, import_jsx_runtime93.jsx)(FileStrip, { files: staged.items, size: narrow ? 60 : 68, onRemove: staged.remove, onRetry: staged.retry, onOpen: onOpenAttachment }) }) : null,
12612
- /* @__PURE__ */ (0, import_jsx_runtime93.jsx)(
12861
+ children: /* @__PURE__ */ (0, import_jsx_runtime94.jsxs)("div", { ref: wrap, className: "fdc-field-inner", children: [
12862
+ staged.items.length ? /* @__PURE__ */ (0, import_jsx_runtime94.jsx)("div", { className: "fdc-staged", children: /* @__PURE__ */ (0, import_jsx_runtime94.jsx)(FileStrip, { files: staged.items, size: narrow ? 60 : 68, onRemove: staged.remove, onRetry: staged.retry, onOpen: onOpenAttachment }) }) : null,
12863
+ /* @__PURE__ */ (0, import_jsx_runtime94.jsx)(
12613
12864
  MarkdownEditor,
12614
12865
  {
12615
12866
  ref: editor,
@@ -12628,33 +12879,33 @@ function ChatComposer({
12628
12879
  ariaLabel: "Message"
12629
12880
  }
12630
12881
  ),
12631
- /* @__PURE__ */ (0, import_jsx_runtime93.jsxs)("div", { className: "fdc-tools", children: [
12632
- fileUploadHandler ? /* @__PURE__ */ (0, import_jsx_runtime93.jsx)(FilePickButton, { onFiles: staged.add, onReject: (r) => flash(r[0].message), accept: acceptFiles, maxFileSize, label: "Attach files", icon: "plus" }) : null,
12633
- voiceHandler ? /* @__PURE__ */ (0, import_jsx_runtime93.jsx)("button", { type: "button", className: "fd-attachbtn" + (listening ? " is-live" : ""), onClick: voice, "aria-pressed": listening, "aria-label": listening ? "Stop dictation" : "Dictate", children: /* @__PURE__ */ (0, import_jsx_runtime93.jsx)("i", { className: "ph ph-" + (listening ? "waveform" : "microphone"), "aria-hidden": "true" }) }) : null,
12882
+ /* @__PURE__ */ (0, import_jsx_runtime94.jsxs)("div", { className: "fdc-tools", children: [
12883
+ fileUploadHandler ? /* @__PURE__ */ (0, import_jsx_runtime94.jsx)(FilePickButton, { onFiles: staged.add, onReject: (r) => flash(r[0].message), accept: acceptFiles, maxFileSize, label: "Attach files", icon: "plus" }) : null,
12884
+ voiceHandler ? /* @__PURE__ */ (0, import_jsx_runtime94.jsx)("button", { type: "button", className: "fd-attachbtn" + (listening ? " is-live" : ""), onClick: voice, "aria-pressed": listening, "aria-label": listening ? "Stop dictation" : "Dictate", children: /* @__PURE__ */ (0, import_jsx_runtime94.jsx)("i", { className: "ph ph-" + (listening ? "waveform" : "microphone"), "aria-hidden": "true" }) }) : null,
12634
12885
  toolbarExtras,
12635
- /* @__PURE__ */ (0, import_jsx_runtime93.jsx)("span", { className: "fdc-tools-gap" }),
12636
- maxLength && text.length > maxLength * 0.6 ? /* @__PURE__ */ (0, import_jsx_runtime93.jsxs)("span", { className: "fdc-count fd-tabular" + (text.length > maxLength * 0.95 ? " is-hot" : ""), children: [
12886
+ /* @__PURE__ */ (0, import_jsx_runtime94.jsx)("span", { className: "fdc-tools-gap" }),
12887
+ maxLength && text.length > maxLength * 0.6 ? /* @__PURE__ */ (0, import_jsx_runtime94.jsxs)("span", { className: "fdc-count fd-tabular" + (text.length > maxLength * 0.95 ? " is-hot" : ""), children: [
12637
12888
  text.length,
12638
12889
  "/",
12639
12890
  maxLength
12640
12891
  ] }) : null,
12641
- busy ? /* @__PURE__ */ (0, import_jsx_runtime93.jsxs)("button", { type: "button", className: "fdc-stop", onClick: onStop, "aria-label": "Stop generating", children: [
12642
- /* @__PURE__ */ (0, import_jsx_runtime93.jsx)("i", { className: "ph ph-stop-circle", "aria-hidden": "true" }),
12643
- /* @__PURE__ */ (0, import_jsx_runtime93.jsx)("span", { children: "Stop" })
12644
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime93.jsxs)("button", { type: "button", className: "fdc-send", onClick: submit, disabled: !canSend, "aria-label": "Send message", children: [
12645
- /* @__PURE__ */ (0, import_jsx_runtime93.jsx)("i", { className: "ph ph-paper-plane-right", "aria-hidden": "true" }),
12646
- /* @__PURE__ */ (0, import_jsx_runtime93.jsx)("span", { className: "fdc-send-label", children: "Send" })
12892
+ busy ? /* @__PURE__ */ (0, import_jsx_runtime94.jsxs)("button", { type: "button", className: "fdc-stop", onClick: onStop, "aria-label": "Stop generating", children: [
12893
+ /* @__PURE__ */ (0, import_jsx_runtime94.jsx)("i", { className: "ph ph-stop-circle", "aria-hidden": "true" }),
12894
+ /* @__PURE__ */ (0, import_jsx_runtime94.jsx)("span", { children: "Stop" })
12895
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime94.jsxs)("button", { type: "button", className: "fdc-send", onClick: submit, disabled: !canSend, "aria-label": "Send message", children: [
12896
+ /* @__PURE__ */ (0, import_jsx_runtime94.jsx)("i", { className: "ph ph-paper-plane-right", "aria-hidden": "true" }),
12897
+ /* @__PURE__ */ (0, import_jsx_runtime94.jsx)("span", { className: "fdc-send-label", children: "Send" })
12647
12898
  ] })
12648
12899
  ] })
12649
12900
  ] })
12650
12901
  }
12651
12902
  ),
12652
- notice ? /* @__PURE__ */ (0, import_jsx_runtime93.jsxs)("div", { className: "fdc-notice", role: "status", children: [
12653
- /* @__PURE__ */ (0, import_jsx_runtime93.jsx)("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
12903
+ notice ? /* @__PURE__ */ (0, import_jsx_runtime94.jsxs)("div", { className: "fdc-notice", role: "status", children: [
12904
+ /* @__PURE__ */ (0, import_jsx_runtime94.jsx)("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
12654
12905
  notice
12655
12906
  ] }) : null,
12656
- hint && !notice ? /* @__PURE__ */ (0, import_jsx_runtime93.jsx)("div", { className: "fdc-hint", children: hint }) : null,
12657
- /* @__PURE__ */ (0, import_jsx_runtime93.jsx)(
12907
+ hint && !notice ? /* @__PURE__ */ (0, import_jsx_runtime94.jsx)("div", { className: "fdc-hint", children: hint }) : null,
12908
+ /* @__PURE__ */ (0, import_jsx_runtime94.jsx)(
12658
12909
  Popover,
12659
12910
  {
12660
12911
  open: menuOpen,
@@ -12668,12 +12919,12 @@ function ChatComposer({
12668
12919
  returnFocus: false,
12669
12920
  closeOnOutside: true,
12670
12921
  label: trigger && trigger.type === "slash" ? "Commands" : "Mentions",
12671
- children: /* @__PURE__ */ (0, import_jsx_runtime93.jsx)(
12922
+ children: /* @__PURE__ */ (0, import_jsx_runtime94.jsx)(
12672
12923
  Menu,
12673
12924
  {
12674
12925
  items: menuItems,
12675
12926
  autoFocus: false,
12676
- header: /* @__PURE__ */ (0, import_jsx_runtime93.jsx)("div", { className: "fd-pop-group", children: trigger && trigger.type === "slash" ? "Commands" : "Attach context" }),
12927
+ header: /* @__PURE__ */ (0, import_jsx_runtime94.jsx)("div", { className: "fd-pop-group", children: trigger && trigger.type === "slash" ? "Commands" : "Attach context" }),
12677
12928
  onClose: () => setTrigger(null)
12678
12929
  }
12679
12930
  )
@@ -12683,12 +12934,12 @@ function ChatComposer({
12683
12934
  }
12684
12935
 
12685
12936
  // src/components/chat/ChatSessionBar.tsx
12686
- var React62 = __toESM(require("react"), 1);
12687
- var import_jsx_runtime94 = require("react/jsx-runtime");
12937
+ var React63 = __toESM(require("react"), 1);
12938
+ var import_jsx_runtime95 = require("react/jsx-runtime");
12688
12939
  var compact2 = meterFormats.compact;
12689
12940
  function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extras }) {
12690
- const [open2, setOpen] = React62.useState(false);
12691
- const anchor = React62.useRef(null);
12941
+ const [open2, setOpen] = React63.useState(false);
12942
+ const anchor = React63.useRef(null);
12692
12943
  const stats = sessionStats || null;
12693
12944
  const cu = contextUsage || null;
12694
12945
  const limits = usageLimits || null;
@@ -12703,9 +12954,9 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
12703
12954
  if (stats && stats.runningTasks) bits.push(stats.runningTasks + " running task" + (stats.runningTasks === 1 ? "" : "s"));
12704
12955
  if (cu) bits.push(pct + "% context");
12705
12956
  const expandable = !!(cu || limits);
12706
- return /* @__PURE__ */ (0, import_jsx_runtime94.jsxs)(React62.Fragment, { children: [
12707
- /* @__PURE__ */ (0, import_jsx_runtime94.jsxs)("div", { className: "fdc-bar", children: [
12708
- /* @__PURE__ */ (0, import_jsx_runtime94.jsxs)(
12957
+ return /* @__PURE__ */ (0, import_jsx_runtime95.jsxs)(React63.Fragment, { children: [
12958
+ /* @__PURE__ */ (0, import_jsx_runtime95.jsxs)("div", { className: "fdc-bar", children: [
12959
+ /* @__PURE__ */ (0, import_jsx_runtime95.jsxs)(
12709
12960
  "button",
12710
12961
  {
12711
12962
  type: "button",
@@ -12716,15 +12967,15 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
12716
12967
  "aria-expanded": expandable ? open2 : void 0,
12717
12968
  "aria-label": expandable ? "Usage details" : void 0,
12718
12969
  children: [
12719
- cu ? /* @__PURE__ */ (0, import_jsx_runtime94.jsx)("span", { className: "fdc-bar-mini", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime94.jsx)(SegmentedMeter, { total, segments: cu.segments, height: 4, showTotal: false }) }) : null,
12720
- /* @__PURE__ */ (0, import_jsx_runtime94.jsx)("span", { className: "fdc-bar-text", title: truncationTitle(bits.join(" \xB7 ")), children: bits.join(" \xB7 ") }),
12721
- expandable ? /* @__PURE__ */ (0, import_jsx_runtime94.jsx)("i", { className: "ph ph-caret-right fdc-bar-caret", "aria-hidden": "true" }) : null
12970
+ cu ? /* @__PURE__ */ (0, import_jsx_runtime95.jsx)("span", { className: "fdc-bar-mini", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime95.jsx)(SegmentedMeter, { total, segments: cu.segments, height: 4, showTotal: false }) }) : null,
12971
+ /* @__PURE__ */ (0, import_jsx_runtime95.jsx)("span", { className: "fdc-bar-text", title: truncationTitle(bits.join(" \xB7 ")), children: bits.join(" \xB7 ") }),
12972
+ expandable ? /* @__PURE__ */ (0, import_jsx_runtime95.jsx)("i", { className: "ph ph-caret-right fdc-bar-caret", "aria-hidden": "true" }) : null
12722
12973
  ]
12723
12974
  }
12724
12975
  ),
12725
12976
  extras
12726
12977
  ] }),
12727
- /* @__PURE__ */ (0, import_jsx_runtime94.jsx)(
12978
+ /* @__PURE__ */ (0, import_jsx_runtime95.jsx)(
12728
12979
  Popover,
12729
12980
  {
12730
12981
  open: open2,
@@ -12735,15 +12986,15 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
12735
12986
  maxHeight: 460,
12736
12987
  padded: true,
12737
12988
  label: "Usage",
12738
- footer: onClear ? /* @__PURE__ */ (0, import_jsx_runtime94.jsxs)("button", { type: "button", className: "fdc-usage-clear", onClick: () => {
12989
+ footer: onClear ? /* @__PURE__ */ (0, import_jsx_runtime95.jsxs)("button", { type: "button", className: "fdc-usage-clear", onClick: () => {
12739
12990
  setOpen(false);
12740
12991
  onClear();
12741
12992
  }, children: [
12742
- /* @__PURE__ */ (0, import_jsx_runtime94.jsx)("i", { className: "ph ph-trash", "aria-hidden": "true" }),
12993
+ /* @__PURE__ */ (0, import_jsx_runtime95.jsx)("i", { className: "ph ph-trash", "aria-hidden": "true" }),
12743
12994
  "Clear conversation"
12744
12995
  ] }) : void 0,
12745
- children: /* @__PURE__ */ (0, import_jsx_runtime94.jsxs)("div", { className: "fdc-usage", children: [
12746
- cu ? /* @__PURE__ */ (0, import_jsx_runtime94.jsx)("section", { className: "fdc-usage-sec", children: /* @__PURE__ */ (0, import_jsx_runtime94.jsx)(
12996
+ children: /* @__PURE__ */ (0, import_jsx_runtime95.jsxs)("div", { className: "fdc-usage", children: [
12997
+ cu ? /* @__PURE__ */ (0, import_jsx_runtime95.jsx)("section", { className: "fdc-usage-sec", children: /* @__PURE__ */ (0, import_jsx_runtime95.jsx)(
12747
12998
  SegmentedMeter,
12748
12999
  {
12749
13000
  total,
@@ -12755,9 +13006,9 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
12755
13006
  remainderLabel: "Free"
12756
13007
  }
12757
13008
  ) }) : null,
12758
- limits && limits.length ? /* @__PURE__ */ (0, import_jsx_runtime94.jsxs)("section", { className: "fdc-usage-sec", children: [
12759
- /* @__PURE__ */ (0, import_jsx_runtime94.jsx)("h4", { className: "fdc-usage-h", children: "Usage limits" }),
12760
- /* @__PURE__ */ (0, import_jsx_runtime94.jsx)("div", { className: "fdc-usage-rows", children: limits.map((l) => /* @__PURE__ */ (0, import_jsx_runtime94.jsx)(
13009
+ limits && limits.length ? /* @__PURE__ */ (0, import_jsx_runtime95.jsxs)("section", { className: "fdc-usage-sec", children: [
13010
+ /* @__PURE__ */ (0, import_jsx_runtime95.jsx)("h4", { className: "fdc-usage-h", children: "Usage limits" }),
13011
+ /* @__PURE__ */ (0, import_jsx_runtime95.jsx)("div", { className: "fdc-usage-rows", children: limits.map((l) => /* @__PURE__ */ (0, import_jsx_runtime95.jsx)(
12761
13012
  QuotaRow,
12762
13013
  {
12763
13014
  label: l.label,
@@ -12767,25 +13018,25 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
12767
13018
  l.id
12768
13019
  )) })
12769
13020
  ] }) : null,
12770
- stats ? /* @__PURE__ */ (0, import_jsx_runtime94.jsxs)("section", { className: "fdc-usage-sec fdc-usage-stats", children: [
12771
- stats.elapsedMs ? /* @__PURE__ */ (0, import_jsx_runtime94.jsxs)("div", { children: [
12772
- /* @__PURE__ */ (0, import_jsx_runtime94.jsx)("span", { children: "Session" }),
12773
- /* @__PURE__ */ (0, import_jsx_runtime94.jsx)("b", { className: "fd-tabular", children: formatDuration(stats.elapsedMs) })
13021
+ stats ? /* @__PURE__ */ (0, import_jsx_runtime95.jsxs)("section", { className: "fdc-usage-sec fdc-usage-stats", children: [
13022
+ stats.elapsedMs ? /* @__PURE__ */ (0, import_jsx_runtime95.jsxs)("div", { children: [
13023
+ /* @__PURE__ */ (0, import_jsx_runtime95.jsx)("span", { children: "Session" }),
13024
+ /* @__PURE__ */ (0, import_jsx_runtime95.jsx)("b", { className: "fd-tabular", children: formatDuration(stats.elapsedMs) })
12774
13025
  ] }) : null,
12775
- stats.tokens ? /* @__PURE__ */ (0, import_jsx_runtime94.jsxs)("div", { children: [
12776
- /* @__PURE__ */ (0, import_jsx_runtime94.jsx)("span", { children: "Tokens" }),
12777
- /* @__PURE__ */ (0, import_jsx_runtime94.jsx)("b", { className: "fd-tabular", children: stats.tokens.toLocaleString() })
13026
+ stats.tokens ? /* @__PURE__ */ (0, import_jsx_runtime95.jsxs)("div", { children: [
13027
+ /* @__PURE__ */ (0, import_jsx_runtime95.jsx)("span", { children: "Tokens" }),
13028
+ /* @__PURE__ */ (0, import_jsx_runtime95.jsx)("b", { className: "fd-tabular", children: stats.tokens.toLocaleString() })
12778
13029
  ] }) : null,
12779
- stats.costUsd != null ? /* @__PURE__ */ (0, import_jsx_runtime94.jsxs)("div", { children: [
12780
- /* @__PURE__ */ (0, import_jsx_runtime94.jsx)("span", { children: "Cost" }),
12781
- /* @__PURE__ */ (0, import_jsx_runtime94.jsxs)("b", { className: "fd-tabular", children: [
13030
+ stats.costUsd != null ? /* @__PURE__ */ (0, import_jsx_runtime95.jsxs)("div", { children: [
13031
+ /* @__PURE__ */ (0, import_jsx_runtime95.jsx)("span", { children: "Cost" }),
13032
+ /* @__PURE__ */ (0, import_jsx_runtime95.jsxs)("b", { className: "fd-tabular", children: [
12782
13033
  "$",
12783
13034
  Number(stats.costUsd).toFixed(3)
12784
13035
  ] })
12785
13036
  ] }) : null,
12786
- stats.turns ? /* @__PURE__ */ (0, import_jsx_runtime94.jsxs)("div", { children: [
12787
- /* @__PURE__ */ (0, import_jsx_runtime94.jsx)("span", { children: "Turns" }),
12788
- /* @__PURE__ */ (0, import_jsx_runtime94.jsx)("b", { className: "fd-tabular", children: stats.turns })
13037
+ stats.turns ? /* @__PURE__ */ (0, import_jsx_runtime95.jsxs)("div", { children: [
13038
+ /* @__PURE__ */ (0, import_jsx_runtime95.jsx)("span", { children: "Turns" }),
13039
+ /* @__PURE__ */ (0, import_jsx_runtime95.jsx)("b", { className: "fd-tabular", children: stats.turns })
12789
13040
  ] }) : null
12790
13041
  ] }) : null
12791
13042
  ] })
@@ -12824,7 +13075,7 @@ function ModelControls({
12824
13075
  disabled: m.disabled,
12825
13076
  checked: m.id === (current2 && current2.id),
12826
13077
  meta: m.meta,
12827
- shortcut: m.shortcut ? /* @__PURE__ */ (0, import_jsx_runtime94.jsx)(KeyHint, { keys: m.shortcut, size: "sm" }) : void 0,
13078
+ shortcut: m.shortcut ? /* @__PURE__ */ (0, import_jsx_runtime95.jsx)(KeyHint, { keys: m.shortcut, size: "sm" }) : void 0,
12828
13079
  onSelect: () => onModelChange && onModelChange(m.id)
12829
13080
  });
12830
13081
  const items = [{ kind: "section", label: "Models" }].concat(flat.map(item));
@@ -12837,15 +13088,15 @@ function ModelControls({
12837
13088
  items.push({ kind: "section", label: "Fast mode" });
12838
13089
  items.push({
12839
13090
  kind: "custom",
12840
- render: () => /* @__PURE__ */ (0, import_jsx_runtime94.jsxs)("label", { className: "fdc-switchrow", children: [
12841
- /* @__PURE__ */ (0, import_jsx_runtime94.jsx)("span", { children: fastModeLabel }),
12842
- /* @__PURE__ */ (0, import_jsx_runtime94.jsx)("input", { type: "checkbox", className: "fd-sr", checked: !!fastMode, onChange: (e) => onFastModeChange(e.target.checked) }),
12843
- /* @__PURE__ */ (0, import_jsx_runtime94.jsx)("span", { className: "fd-switch-track" + (fastMode ? " is-on" : ""), "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime94.jsx)("span", { className: "fd-switch-thumb" }) })
13091
+ render: () => /* @__PURE__ */ (0, import_jsx_runtime95.jsxs)("label", { className: "fdc-switchrow", children: [
13092
+ /* @__PURE__ */ (0, import_jsx_runtime95.jsx)("span", { children: fastModeLabel }),
13093
+ /* @__PURE__ */ (0, import_jsx_runtime95.jsx)("input", { type: "checkbox", className: "fd-sr", checked: !!fastMode, onChange: (e) => onFastModeChange(e.target.checked) }),
13094
+ /* @__PURE__ */ (0, import_jsx_runtime95.jsx)("span", { className: "fd-switch-track" + (fastMode ? " is-on" : ""), "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime95.jsx)("span", { className: "fd-switch-thumb" }) })
12844
13095
  ] })
12845
13096
  });
12846
13097
  }
12847
- return /* @__PURE__ */ (0, import_jsx_runtime94.jsxs)(React62.Fragment, { children: [
12848
- /* @__PURE__ */ (0, import_jsx_runtime94.jsx)(
13098
+ return /* @__PURE__ */ (0, import_jsx_runtime95.jsxs)(React63.Fragment, { children: [
13099
+ /* @__PURE__ */ (0, import_jsx_runtime95.jsx)(
12849
13100
  MenuButton,
12850
13101
  {
12851
13102
  items,
@@ -12856,7 +13107,7 @@ function ModelControls({
12856
13107
  title: "Choose a model"
12857
13108
  }
12858
13109
  ),
12859
- effortLevels && effortLevels.length ? /* @__PURE__ */ (0, import_jsx_runtime94.jsx)(
13110
+ effortLevels && effortLevels.length ? /* @__PURE__ */ (0, import_jsx_runtime95.jsx)(
12860
13111
  MenuButton,
12861
13112
  {
12862
13113
  placement: "top-end",
@@ -12877,7 +13128,7 @@ function ModelControls({
12877
13128
  }
12878
13129
 
12879
13130
  // src/components/chat/AgentChatPanel.tsx
12880
- var import_jsx_runtime95 = require("react/jsx-runtime");
13131
+ var import_jsx_runtime96 = require("react/jsx-runtime");
12881
13132
  var SURFACES = { sidebar: "is-sidebar", inline: "is-inline", page: "is-page", modal: "is-modal", sheet: "is-sheet" };
12882
13133
  function AgentChatPanel({
12883
13134
  /* required */
@@ -12961,11 +13212,11 @@ function AgentChatPanel({
12961
13212
  onFeedback,
12962
13213
  onEditMessage
12963
13214
  }) {
12964
- const [panelWidth, setPanelWidth] = React63.useState(width);
12965
- const [applied, setApplied] = React63.useState({});
12966
- const [draft, setDraft] = React63.useState("");
12967
- const dragging = React63.useRef(null);
12968
- React63.useEffect(() => setPanelWidth(width), [width]);
13215
+ const [panelWidth, setPanelWidth] = React64.useState(width);
13216
+ const [applied, setApplied] = React64.useState({});
13217
+ const [draft, setDraft] = React64.useState("");
13218
+ const dragging = React64.useRef(null);
13219
+ React64.useEffect(() => setPanelWidth(width), [width]);
12969
13220
  const engine = useChatEngine({
12970
13221
  contextType,
12971
13222
  contextId,
@@ -13031,7 +13282,7 @@ function AgentChatPanel({
13031
13282
  onReconnect: engine.reload,
13032
13283
  deadTitle: "The assistant isn\u2019t reachable"
13033
13284
  };
13034
- const sessionBar = /* @__PURE__ */ (0, import_jsx_runtime95.jsx)(
13285
+ const sessionBar = /* @__PURE__ */ (0, import_jsx_runtime96.jsx)(
13035
13286
  ChatSessionBar,
13036
13287
  {
13037
13288
  sessionStats,
@@ -13040,7 +13291,7 @@ function AgentChatPanel({
13040
13291
  onClear: engine.visible.length ? engine.clear : void 0
13041
13292
  }
13042
13293
  );
13043
- const modelControls = /* @__PURE__ */ (0, import_jsx_runtime95.jsx)(
13294
+ const modelControls = /* @__PURE__ */ (0, import_jsx_runtime96.jsx)(
13044
13295
  ModelControls,
13045
13296
  {
13046
13297
  models,
@@ -13055,7 +13306,7 @@ function AgentChatPanel({
13055
13306
  narrow
13056
13307
  }
13057
13308
  );
13058
- const threadMenu = threads && threads.length ? /* @__PURE__ */ (0, import_jsx_runtime95.jsx)(
13309
+ const threadMenu = threads && threads.length ? /* @__PURE__ */ (0, import_jsx_runtime96.jsx)(
13059
13310
  MenuButton,
13060
13311
  {
13061
13312
  variant: "ghost",
@@ -13082,7 +13333,7 @@ function AgentChatPanel({
13082
13333
  })))
13083
13334
  }
13084
13335
  ) : null;
13085
- return /* @__PURE__ */ (0, import_jsx_runtime95.jsxs)(
13336
+ return /* @__PURE__ */ (0, import_jsx_runtime96.jsxs)(
13086
13337
  "aside",
13087
13338
  {
13088
13339
  className: ["fdc-panel", SURFACES[surface] || SURFACES.sidebar, narrow ? "is-narrow" : "", className].filter(Boolean).join(" "),
@@ -13093,7 +13344,7 @@ function AgentChatPanel({
13093
13344
  },
13094
13345
  "aria-label": title,
13095
13346
  children: [
13096
- surface === "sidebar" && resizable ? /* @__PURE__ */ (0, import_jsx_runtime95.jsx)(
13347
+ surface === "sidebar" && resizable ? /* @__PURE__ */ (0, import_jsx_runtime96.jsx)(
13097
13348
  "div",
13098
13349
  {
13099
13350
  className: "fdc-grip",
@@ -13108,20 +13359,20 @@ function AgentChatPanel({
13108
13359
  }
13109
13360
  }
13110
13361
  ) : null,
13111
- showHeader ? /* @__PURE__ */ (0, import_jsx_runtime95.jsxs)("header", { className: "fdc-head", children: [
13112
- /* @__PURE__ */ (0, import_jsx_runtime95.jsx)("span", { className: "fdc-head-mark", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime95.jsx)("i", { className: "ph ph-" + assistantIcon }) }),
13113
- /* @__PURE__ */ (0, import_jsx_runtime95.jsxs)("span", { className: "fdc-head-titles", children: [
13114
- /* @__PURE__ */ (0, import_jsx_runtime95.jsx)("span", { className: "fdc-head-title", title: truncationTitle(title), children: title }),
13115
- subtitle ? /* @__PURE__ */ (0, import_jsx_runtime95.jsx)("span", { className: "fdc-head-sub", title: truncationTitle(subtitle), children: subtitle }) : null
13362
+ showHeader ? /* @__PURE__ */ (0, import_jsx_runtime96.jsxs)("header", { className: "fdc-head", children: [
13363
+ /* @__PURE__ */ (0, import_jsx_runtime96.jsx)("span", { className: "fdc-head-mark", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime96.jsx)("i", { className: "ph ph-" + assistantIcon }) }),
13364
+ /* @__PURE__ */ (0, import_jsx_runtime96.jsxs)("span", { className: "fdc-head-titles", children: [
13365
+ /* @__PURE__ */ (0, import_jsx_runtime96.jsx)("span", { className: "fdc-head-title", title: truncationTitle(title), children: title }),
13366
+ subtitle ? /* @__PURE__ */ (0, import_jsx_runtime96.jsx)("span", { className: "fdc-head-sub", title: truncationTitle(subtitle), children: subtitle }) : null
13116
13367
  ] }),
13117
- /* @__PURE__ */ (0, import_jsx_runtime95.jsxs)("span", { className: "fdc-head-acts", children: [
13368
+ /* @__PURE__ */ (0, import_jsx_runtime96.jsxs)("span", { className: "fdc-head-acts", children: [
13118
13369
  headerActions,
13119
13370
  threadMenu,
13120
- onNewThread ? /* @__PURE__ */ (0, import_jsx_runtime95.jsx)("button", { type: "button", className: "fdc-iconbtn", onClick: onNewThread, "aria-label": "New conversation", title: "New conversation", children: /* @__PURE__ */ (0, import_jsx_runtime95.jsx)("i", { className: "ph ph-plus", "aria-hidden": "true" }) }) : null,
13121
- onClose ? /* @__PURE__ */ (0, import_jsx_runtime95.jsx)("button", { type: "button", className: "fdc-iconbtn", onClick: onClose, "aria-label": "Close panel", title: "Close", children: /* @__PURE__ */ (0, import_jsx_runtime95.jsx)("i", { className: "ph ph-x", "aria-hidden": "true" }) }) : null
13371
+ onNewThread ? /* @__PURE__ */ (0, import_jsx_runtime96.jsx)("button", { type: "button", className: "fdc-iconbtn", onClick: onNewThread, "aria-label": "New conversation", title: "New conversation", children: /* @__PURE__ */ (0, import_jsx_runtime96.jsx)("i", { className: "ph ph-plus", "aria-hidden": "true" }) }) : null,
13372
+ onClose ? /* @__PURE__ */ (0, import_jsx_runtime96.jsx)("button", { type: "button", className: "fdc-iconbtn", onClick: onClose, "aria-label": "Close panel", title: "Close", children: /* @__PURE__ */ (0, import_jsx_runtime96.jsx)("i", { className: "ph ph-x", "aria-hidden": "true" }) }) : null
13122
13373
  ] })
13123
13374
  ] }) : null,
13124
- /* @__PURE__ */ (0, import_jsx_runtime95.jsx)(
13375
+ /* @__PURE__ */ (0, import_jsx_runtime96.jsx)(
13125
13376
  ChatTranscript,
13126
13377
  {
13127
13378
  messages: engine.visible,
@@ -13136,7 +13387,7 @@ function AgentChatPanel({
13136
13387
  renderEmpty
13137
13388
  }
13138
13389
  ),
13139
- /* @__PURE__ */ (0, import_jsx_runtime95.jsx)(
13390
+ /* @__PURE__ */ (0, import_jsx_runtime96.jsx)(
13140
13391
  ChatComposer,
13141
13392
  {
13142
13393
  onSubmit: (text, atts) => engine.send(text, atts),
@@ -13169,8 +13420,8 @@ function AgentChatPanel({
13169
13420
  }
13170
13421
 
13171
13422
  // src/components/files/FileViewer.tsx
13172
- var React64 = __toESM(require("react"), 1);
13173
- var import_jsx_runtime96 = require("react/jsx-runtime");
13423
+ var React65 = __toESM(require("react"), 1);
13424
+ var import_jsx_runtime97 = require("react/jsx-runtime");
13174
13425
  function previewKindOf(file) {
13175
13426
  const mime = (file.mime || "").toLowerCase();
13176
13427
  const ext = extensionOf(file.name || "");
@@ -13226,13 +13477,13 @@ function parseDelimited(text, delimiter) {
13226
13477
  return rows;
13227
13478
  }
13228
13479
  function usePreview(file, kind, resolveUrl) {
13229
- const [state, setState] = React64.useState({ status: "loading" });
13230
- const [attempt, setAttempt] = React64.useState(0);
13231
- const resolveRef = React64.useRef(resolveUrl);
13232
- React64.useEffect(() => {
13480
+ const [state, setState] = React65.useState({ status: "loading" });
13481
+ const [attempt, setAttempt] = React65.useState(0);
13482
+ const resolveRef = React65.useRef(resolveUrl);
13483
+ React65.useEffect(() => {
13233
13484
  resolveRef.current = resolveUrl;
13234
13485
  }, [resolveUrl]);
13235
- React64.useEffect(() => {
13486
+ React65.useEffect(() => {
13236
13487
  if (kind === "none") {
13237
13488
  setState({ status: "ready" });
13238
13489
  return;
@@ -13262,19 +13513,19 @@ function usePreview(file, kind, resolveUrl) {
13262
13513
  if (ac) ac.abort();
13263
13514
  };
13264
13515
  }, [file.id, kind, attempt]);
13265
- return { ...state, retry: React64.useCallback(() => setAttempt((a) => a + 1), []) };
13516
+ return { ...state, retry: React65.useCallback(() => setAttempt((a) => a + 1), []) };
13266
13517
  }
13267
13518
  function PreviewBody({ file, kind, state }) {
13268
- if (kind === "image") return /* @__PURE__ */ (0, import_jsx_runtime96.jsx)("img", { className: "fd-fv-image", src: state.url, alt: file.name || "Preview" });
13269
- if (kind === "pdf") return /* @__PURE__ */ (0, import_jsx_runtime96.jsx)("iframe", { className: "fd-fv-pdf", src: state.url, title: file.name || "PDF preview" });
13270
- if (kind === "markdown") return /* @__PURE__ */ (0, import_jsx_runtime96.jsx)(Markdown, { className: "fd-fv-markdown", source: state.text || "" });
13519
+ if (kind === "image") return /* @__PURE__ */ (0, import_jsx_runtime97.jsx)("img", { className: "fd-fv-image", src: state.url, alt: file.name || "Preview" });
13520
+ if (kind === "pdf") return /* @__PURE__ */ (0, import_jsx_runtime97.jsx)("iframe", { className: "fd-fv-pdf", src: state.url, title: file.name || "PDF preview" });
13521
+ if (kind === "markdown") return /* @__PURE__ */ (0, import_jsx_runtime97.jsx)(Markdown, { className: "fd-fv-markdown", source: state.text || "" });
13271
13522
  if (kind === "json") {
13272
13523
  let pretty = state.text || "";
13273
13524
  try {
13274
13525
  pretty = JSON.stringify(JSON.parse(pretty), null, 2);
13275
13526
  } catch {
13276
13527
  }
13277
- return /* @__PURE__ */ (0, import_jsx_runtime96.jsx)(CodeBlock, { code: pretty, language: "json" });
13528
+ return /* @__PURE__ */ (0, import_jsx_runtime97.jsx)(CodeBlock, { code: pretty, language: "json" });
13278
13529
  }
13279
13530
  if (kind === "csv") {
13280
13531
  const tsv = extensionOf(file.name || "") === "tsv" || (file.mime || "").toLowerCase().includes("tab-separated");
@@ -13282,12 +13533,12 @@ function PreviewBody({ file, kind, state }) {
13282
13533
  const head = rows[0] || [];
13283
13534
  const dataRows = rows.slice(1);
13284
13535
  const shown = dataRows.slice(0, FILE_VIEWER_CSV_ROW_LIMIT);
13285
- return /* @__PURE__ */ (0, import_jsx_runtime96.jsxs)("div", { className: "fd-fv-csv", children: [
13286
- /* @__PURE__ */ (0, import_jsx_runtime96.jsxs)("table", { className: "fd-fv-csv-table", children: [
13287
- /* @__PURE__ */ (0, import_jsx_runtime96.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime96.jsx)("tr", { children: head.map((c, i) => /* @__PURE__ */ (0, import_jsx_runtime96.jsx)("th", { children: c }, i)) }) }),
13288
- /* @__PURE__ */ (0, import_jsx_runtime96.jsx)("tbody", { children: shown.map((r, ri) => /* @__PURE__ */ (0, import_jsx_runtime96.jsx)("tr", { children: head.map((_, ci) => /* @__PURE__ */ (0, import_jsx_runtime96.jsx)("td", { children: r[ci] ?? "" }, ci)) }, ri)) })
13536
+ return /* @__PURE__ */ (0, import_jsx_runtime97.jsxs)("div", { className: "fd-fv-csv", children: [
13537
+ /* @__PURE__ */ (0, import_jsx_runtime97.jsxs)("table", { className: "fd-fv-csv-table", children: [
13538
+ /* @__PURE__ */ (0, import_jsx_runtime97.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime97.jsx)("tr", { children: head.map((c, i) => /* @__PURE__ */ (0, import_jsx_runtime97.jsx)("th", { children: c }, i)) }) }),
13539
+ /* @__PURE__ */ (0, import_jsx_runtime97.jsx)("tbody", { children: shown.map((r, ri) => /* @__PURE__ */ (0, import_jsx_runtime97.jsx)("tr", { children: head.map((_, ci) => /* @__PURE__ */ (0, import_jsx_runtime97.jsx)("td", { children: r[ci] ?? "" }, ci)) }, ri)) })
13289
13540
  ] }),
13290
- dataRows.length > FILE_VIEWER_CSV_ROW_LIMIT ? /* @__PURE__ */ (0, import_jsx_runtime96.jsxs)("p", { className: "fd-fv-csv-note fd-body-sm fd-muted", children: [
13541
+ dataRows.length > FILE_VIEWER_CSV_ROW_LIMIT ? /* @__PURE__ */ (0, import_jsx_runtime97.jsxs)("p", { className: "fd-fv-csv-note fd-body-sm fd-muted", children: [
13291
13542
  "Showing the first ",
13292
13543
  FILE_VIEWER_CSV_ROW_LIMIT.toLocaleString(),
13293
13544
  " of ",
@@ -13296,24 +13547,24 @@ function PreviewBody({ file, kind, state }) {
13296
13547
  ] }) : null
13297
13548
  ] });
13298
13549
  }
13299
- if (kind === "text") return /* @__PURE__ */ (0, import_jsx_runtime96.jsx)(CodeBlock, { code: state.text || "", language: extensionOf(file.name || "") || void 0 });
13300
- return /* @__PURE__ */ (0, import_jsx_runtime96.jsxs)("div", { className: "fd-fv-fallback", children: [
13301
- /* @__PURE__ */ (0, import_jsx_runtime96.jsx)("span", { className: "fd-fv-fallback-icon", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime96.jsx)("i", { className: "ph ph-" + iconForMime(file.mime, file.name) }) }),
13302
- /* @__PURE__ */ (0, import_jsx_runtime96.jsx)("span", { className: "fd-fv-fallback-title", children: "No preview available" }),
13303
- /* @__PURE__ */ (0, import_jsx_runtime96.jsxs)("span", { className: "fd-fv-fallback-meta", children: [
13550
+ if (kind === "text") return /* @__PURE__ */ (0, import_jsx_runtime97.jsx)(CodeBlock, { code: state.text || "", language: extensionOf(file.name || "") || void 0 });
13551
+ return /* @__PURE__ */ (0, import_jsx_runtime97.jsxs)("div", { className: "fd-fv-fallback", children: [
13552
+ /* @__PURE__ */ (0, import_jsx_runtime97.jsx)("span", { className: "fd-fv-fallback-icon", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime97.jsx)("i", { className: "ph ph-" + iconForMime(file.mime, file.name) }) }),
13553
+ /* @__PURE__ */ (0, import_jsx_runtime97.jsx)("span", { className: "fd-fv-fallback-title", children: "No preview available" }),
13554
+ /* @__PURE__ */ (0, import_jsx_runtime97.jsxs)("span", { className: "fd-fv-fallback-meta", children: [
13304
13555
  file.mime || "Unknown type",
13305
13556
  file.size ? " \xB7 " + formatBytes(file.size) : ""
13306
13557
  ] })
13307
13558
  ] });
13308
13559
  }
13309
13560
  function FileViewer({ file, resolveUrl, sidePanel, sidePanelLabel = "Details", onClose, actions, className = "" }) {
13310
- const kind = React64.useMemo(() => previewKindOf(file), [file]);
13561
+ const kind = React65.useMemo(() => previewKindOf(file), [file]);
13311
13562
  const preview = usePreview(file, kind, resolveUrl);
13312
- const [tab, setTab] = React64.useState("preview");
13313
- const [downloading, setDownloading] = React64.useState(false);
13314
- const [downloadError, setDownloadError] = React64.useState(null);
13563
+ const [tab, setTab] = React65.useState("preview");
13564
+ const [downloading, setDownloading] = React65.useState(false);
13565
+ const [downloadError, setDownloadError] = React65.useState(null);
13315
13566
  const hasSide = sidePanel != null;
13316
- React64.useEffect(() => {
13567
+ React65.useEffect(() => {
13317
13568
  setTab("preview");
13318
13569
  }, [file.id]);
13319
13570
  const download = () => {
@@ -13329,29 +13580,29 @@ function FileViewer({ file, resolveUrl, sidePanel, sidePanelLabel = "Details", o
13329
13580
  a.remove();
13330
13581
  }).catch((err) => setDownloadError(err && err.message || "Download failed.")).finally(() => setDownloading(false));
13331
13582
  };
13332
- return /* @__PURE__ */ (0, import_jsx_runtime96.jsxs)(
13583
+ return /* @__PURE__ */ (0, import_jsx_runtime97.jsxs)(
13333
13584
  "section",
13334
13585
  {
13335
13586
  className: ["fd-fv", hasSide && tab === "side" ? "is-tab-side" : "is-tab-preview", className].filter(Boolean).join(" "),
13336
13587
  "aria-label": file.name || "File",
13337
13588
  children: [
13338
- /* @__PURE__ */ (0, import_jsx_runtime96.jsxs)("header", { className: "fd-fv-head", children: [
13339
- /* @__PURE__ */ (0, import_jsx_runtime96.jsx)("span", { className: "fd-fv-head-icon", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime96.jsx)("i", { className: "ph ph-" + iconForMime(file.mime, file.name) }) }),
13340
- /* @__PURE__ */ (0, import_jsx_runtime96.jsxs)("span", { className: "fd-fv-head-titles", children: [
13341
- /* @__PURE__ */ (0, import_jsx_runtime96.jsx)("span", { className: "fd-fv-head-title", title: file.name, children: file.name }),
13342
- /* @__PURE__ */ (0, import_jsx_runtime96.jsxs)("span", { className: "fd-fv-head-meta", children: [
13589
+ /* @__PURE__ */ (0, import_jsx_runtime97.jsxs)("header", { className: "fd-fv-head", children: [
13590
+ /* @__PURE__ */ (0, import_jsx_runtime97.jsx)("span", { className: "fd-fv-head-icon", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime97.jsx)("i", { className: "ph ph-" + iconForMime(file.mime, file.name) }) }),
13591
+ /* @__PURE__ */ (0, import_jsx_runtime97.jsxs)("span", { className: "fd-fv-head-titles", children: [
13592
+ /* @__PURE__ */ (0, import_jsx_runtime97.jsx)("span", { className: "fd-fv-head-title", title: file.name, children: file.name }),
13593
+ /* @__PURE__ */ (0, import_jsx_runtime97.jsxs)("span", { className: "fd-fv-head-meta", children: [
13343
13594
  file.mime || "Unknown type",
13344
13595
  file.size ? " \xB7 " + formatBytes(file.size) : ""
13345
13596
  ] })
13346
13597
  ] }),
13347
- /* @__PURE__ */ (0, import_jsx_runtime96.jsxs)("span", { className: "fd-fv-head-actions", children: [
13598
+ /* @__PURE__ */ (0, import_jsx_runtime97.jsxs)("span", { className: "fd-fv-head-actions", children: [
13348
13599
  actions,
13349
- /* @__PURE__ */ (0, import_jsx_runtime96.jsx)(Button, { variant: "secondary", size: "sm", icon: "download-simple", loading: downloading, onClick: download, children: "Download" }),
13350
- onClose ? /* @__PURE__ */ (0, import_jsx_runtime96.jsx)(IconButton, { icon: "x", label: "Close", onClick: onClose }) : null
13600
+ /* @__PURE__ */ (0, import_jsx_runtime97.jsx)(Button, { variant: "secondary", size: "sm", icon: "download-simple", loading: downloading, onClick: download, children: "Download" }),
13601
+ onClose ? /* @__PURE__ */ (0, import_jsx_runtime97.jsx)(IconButton, { icon: "x", label: "Close", onClick: onClose }) : null
13351
13602
  ] })
13352
13603
  ] }),
13353
- downloadError ? /* @__PURE__ */ (0, import_jsx_runtime96.jsx)("div", { className: "fd-fv-download-error", role: "alert", children: downloadError }) : null,
13354
- hasSide ? /* @__PURE__ */ (0, import_jsx_runtime96.jsx)(
13604
+ downloadError ? /* @__PURE__ */ (0, import_jsx_runtime97.jsx)("div", { className: "fd-fv-download-error", role: "alert", children: downloadError }) : null,
13605
+ hasSide ? /* @__PURE__ */ (0, import_jsx_runtime97.jsx)(
13355
13606
  Tabs,
13356
13607
  {
13357
13608
  className: "fd-fv-tabs",
@@ -13360,19 +13611,19 @@ function FileViewer({ file, resolveUrl, sidePanel, sidePanelLabel = "Details", o
13360
13611
  onChange: (v) => setTab(v)
13361
13612
  }
13362
13613
  ) : null,
13363
- /* @__PURE__ */ (0, import_jsx_runtime96.jsxs)("div", { className: "fd-fv-body", children: [
13364
- /* @__PURE__ */ (0, import_jsx_runtime96.jsx)("div", { className: "fd-fv-preview", role: "region", "aria-label": "Preview of " + (file.name || "file"), children: /* @__PURE__ */ (0, import_jsx_runtime96.jsx)(
13614
+ /* @__PURE__ */ (0, import_jsx_runtime97.jsxs)("div", { className: "fd-fv-body", children: [
13615
+ /* @__PURE__ */ (0, import_jsx_runtime97.jsx)("div", { className: "fd-fv-preview", role: "region", "aria-label": "Preview of " + (file.name || "file"), children: /* @__PURE__ */ (0, import_jsx_runtime97.jsx)(
13365
13616
  LoadingRegion,
13366
13617
  {
13367
13618
  state: preview.status === "loading" ? "loading" : preview.status === "error" ? "error" : "ready",
13368
13619
  error: preview.error,
13369
13620
  label: "Loading preview of " + (file.name || "file"),
13370
13621
  onRetry: preview.status === "error" ? preview.retry : void 0,
13371
- skeleton: /* @__PURE__ */ (0, import_jsx_runtime96.jsx)(Skeleton, { shape: "card", h: 220 }),
13372
- children: /* @__PURE__ */ (0, import_jsx_runtime96.jsx)(PreviewBody, { file, kind, state: preview })
13622
+ skeleton: /* @__PURE__ */ (0, import_jsx_runtime97.jsx)(Skeleton, { shape: "card", h: 220 }),
13623
+ children: /* @__PURE__ */ (0, import_jsx_runtime97.jsx)(PreviewBody, { file, kind, state: preview })
13373
13624
  }
13374
13625
  ) }),
13375
- hasSide ? /* @__PURE__ */ (0, import_jsx_runtime96.jsx)("div", { className: "fd-fv-side", role: "region", "aria-label": sidePanelLabel, children: sidePanel }) : null
13626
+ hasSide ? /* @__PURE__ */ (0, import_jsx_runtime97.jsx)("div", { className: "fd-fv-side", role: "region", "aria-label": sidePanelLabel, children: sidePanel }) : null
13376
13627
  ] })
13377
13628
  ]
13378
13629
  }
@@ -13380,8 +13631,8 @@ function FileViewer({ file, resolveUrl, sidePanel, sidePanelLabel = "Details", o
13380
13631
  }
13381
13632
 
13382
13633
  // src/components/files/FileBrowser.tsx
13383
- var React65 = __toESM(require("react"), 1);
13384
- var import_jsx_runtime97 = require("react/jsx-runtime");
13634
+ var React66 = __toESM(require("react"), 1);
13635
+ var import_jsx_runtime98 = require("react/jsx-runtime");
13385
13636
  function childrenOf(folders, parentId) {
13386
13637
  return folders.filter((f) => f.parentId === parentId).sort((a, b) => a.name.localeCompare(b.name));
13387
13638
  }
@@ -13453,8 +13704,8 @@ function FolderPickerMenu({
13453
13704
  }) {
13454
13705
  const panel = useInlinePanel();
13455
13706
  const { open: open2, setOpen, ref, zIndex } = panel;
13456
- return /* @__PURE__ */ (0, import_jsx_runtime97.jsxs)("span", { className: "fd-fb-menu-anchor", ref, children: [
13457
- /* @__PURE__ */ (0, import_jsx_runtime97.jsx)(
13707
+ return /* @__PURE__ */ (0, import_jsx_runtime98.jsxs)("span", { className: "fd-fb-menu-anchor", ref, children: [
13708
+ /* @__PURE__ */ (0, import_jsx_runtime98.jsx)(
13458
13709
  IconButton,
13459
13710
  {
13460
13711
  icon: "arrows-out-cardinal",
@@ -13466,9 +13717,9 @@ function FolderPickerMenu({
13466
13717
  onClick: () => setOpen((v) => !v)
13467
13718
  }
13468
13719
  ),
13469
- open2 ? /* @__PURE__ */ (0, import_jsx_runtime97.jsx)(InlinePanelLayers, { panel, children: /* @__PURE__ */ (0, import_jsx_runtime97.jsxs)("div", { className: "fd-fb-menu", role: "menu", "aria-label": label, style: { zIndex }, children: [
13470
- /* @__PURE__ */ (0, import_jsx_runtime97.jsx)("span", { className: "fd-overline fd-muted fd-fb-menu-title", children: "Move to\u2026" }),
13471
- destinations.map((d) => /* @__PURE__ */ (0, import_jsx_runtime97.jsxs)(
13720
+ open2 ? /* @__PURE__ */ (0, import_jsx_runtime98.jsx)(InlinePanelLayers, { panel, children: /* @__PURE__ */ (0, import_jsx_runtime98.jsxs)("div", { className: "fd-fb-menu", role: "menu", "aria-label": label, style: { zIndex }, children: [
13721
+ /* @__PURE__ */ (0, import_jsx_runtime98.jsx)("span", { className: "fd-overline fd-muted fd-fb-menu-title", children: "Move to\u2026" }),
13722
+ destinations.map((d) => /* @__PURE__ */ (0, import_jsx_runtime98.jsxs)(
13472
13723
  "button",
13473
13724
  {
13474
13725
  type: "button",
@@ -13480,7 +13731,7 @@ function FolderPickerMenu({
13480
13731
  setOpen(false);
13481
13732
  },
13482
13733
  children: [
13483
- /* @__PURE__ */ (0, import_jsx_runtime97.jsx)("i", { className: "ph ph-" + (d.id == null ? "house-simple" : "folder-simple"), "aria-hidden": "true" }),
13734
+ /* @__PURE__ */ (0, import_jsx_runtime98.jsx)("i", { className: "ph ph-" + (d.id == null ? "house-simple" : "folder-simple"), "aria-hidden": "true" }),
13484
13735
  d.name
13485
13736
  ]
13486
13737
  },
@@ -13490,8 +13741,8 @@ function FolderPickerMenu({
13490
13741
  ] });
13491
13742
  }
13492
13743
  function RowShell({ icon, name, meta, onOpen, draggableId, isDropTarget, onDropPayload, actions, className = "" }) {
13493
- const [over, setOver] = React65.useState(false);
13494
- const dragCounter = React65.useRef(0);
13744
+ const [over, setOver] = React66.useState(false);
13745
+ const dragCounter = React66.useRef(0);
13495
13746
  const dropHandlers = isDropTarget ? {
13496
13747
  onDragEnter: (e) => {
13497
13748
  if (!hasInternalPayload(e)) return;
@@ -13516,8 +13767,8 @@ function RowShell({ icon, name, meta, onOpen, draggableId, isDropTarget, onDropP
13516
13767
  if (payload && onDropPayload) onDropPayload(payload);
13517
13768
  }
13518
13769
  } : {};
13519
- return /* @__PURE__ */ (0, import_jsx_runtime97.jsxs)("div", { className: ["fd-fb-row", over ? "is-drop-target" : "", className].filter(Boolean).join(" "), ...dropHandlers, children: [
13520
- /* @__PURE__ */ (0, import_jsx_runtime97.jsxs)(
13770
+ return /* @__PURE__ */ (0, import_jsx_runtime98.jsxs)("div", { className: ["fd-fb-row", over ? "is-drop-target" : "", className].filter(Boolean).join(" "), ...dropHandlers, children: [
13771
+ /* @__PURE__ */ (0, import_jsx_runtime98.jsxs)(
13521
13772
  "button",
13522
13773
  {
13523
13774
  type: "button",
@@ -13526,26 +13777,26 @@ function RowShell({ icon, name, meta, onOpen, draggableId, isDropTarget, onDropP
13526
13777
  draggable: !!draggableId,
13527
13778
  onDragStart: draggableId ? (e) => writeDragPayload(e, draggableId) : void 0,
13528
13779
  children: [
13529
- /* @__PURE__ */ (0, import_jsx_runtime97.jsx)("span", { className: "fd-fb-row-icon", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime97.jsx)("i", { className: "ph ph-" + icon }) }),
13530
- /* @__PURE__ */ (0, import_jsx_runtime97.jsxs)("span", { className: "fd-fb-row-text", children: [
13531
- /* @__PURE__ */ (0, import_jsx_runtime97.jsx)("span", { className: "fd-fb-row-name", title: name, children: name }),
13532
- meta ? /* @__PURE__ */ (0, import_jsx_runtime97.jsx)("span", { className: "fd-fb-row-meta", children: meta }) : null
13780
+ /* @__PURE__ */ (0, import_jsx_runtime98.jsx)("span", { className: "fd-fb-row-icon", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime98.jsx)("i", { className: "ph ph-" + icon }) }),
13781
+ /* @__PURE__ */ (0, import_jsx_runtime98.jsxs)("span", { className: "fd-fb-row-text", children: [
13782
+ /* @__PURE__ */ (0, import_jsx_runtime98.jsx)("span", { className: "fd-fb-row-name", title: name, children: name }),
13783
+ meta ? /* @__PURE__ */ (0, import_jsx_runtime98.jsx)("span", { className: "fd-fb-row-meta", children: meta }) : null
13533
13784
  ] })
13534
13785
  ]
13535
13786
  }
13536
13787
  ),
13537
- actions ? /* @__PURE__ */ (0, import_jsx_runtime97.jsx)("span", { className: "fd-fb-row-actions", children: actions }) : null
13788
+ actions ? /* @__PURE__ */ (0, import_jsx_runtime98.jsx)("span", { className: "fd-fb-row-actions", children: actions }) : null
13538
13789
  ] });
13539
13790
  }
13540
13791
  function TreeNode({ folder, depth, folders, currentFolderId, onNavigate, onMoveInto, canMove }) {
13541
13792
  const kids = childrenOf(folders, folder.id);
13542
- const [expanded, setExpanded] = React65.useState(() => currentFolderId != null && isSelfOrDescendant(folders, folder.id, currentFolderId));
13543
- React65.useEffect(() => {
13793
+ const [expanded, setExpanded] = React66.useState(() => currentFolderId != null && isSelfOrDescendant(folders, folder.id, currentFolderId));
13794
+ React66.useEffect(() => {
13544
13795
  if (currentFolderId != null && isSelfOrDescendant(folders, folder.id, currentFolderId)) setExpanded(true);
13545
13796
  }, [currentFolderId, folder.id, folders]);
13546
13797
  const isCurrent = folder.id === currentFolderId;
13547
- return /* @__PURE__ */ (0, import_jsx_runtime97.jsxs)("div", { className: "fd-fb-tree-node", children: [
13548
- /* @__PURE__ */ (0, import_jsx_runtime97.jsx)(
13798
+ return /* @__PURE__ */ (0, import_jsx_runtime98.jsxs)("div", { className: "fd-fb-tree-node", children: [
13799
+ /* @__PURE__ */ (0, import_jsx_runtime98.jsx)(
13549
13800
  RowShell,
13550
13801
  {
13551
13802
  icon: folder.id === currentFolderId ? "folder-open" : "folder-simple",
@@ -13555,7 +13806,7 @@ function TreeNode({ folder, depth, folders, currentFolderId, onNavigate, onMoveI
13555
13806
  isDropTarget: canMove,
13556
13807
  onDropPayload: (payload) => onMoveInto(payload, folder.id),
13557
13808
  className: ["fd-fb-tree-row", isCurrent ? "is-current" : ""].filter(Boolean).join(" "),
13558
- actions: kids.length ? /* @__PURE__ */ (0, import_jsx_runtime97.jsx)(
13809
+ actions: kids.length ? /* @__PURE__ */ (0, import_jsx_runtime98.jsx)(
13559
13810
  IconButton,
13560
13811
  {
13561
13812
  icon: expanded ? "caret-down" : "caret-right",
@@ -13567,7 +13818,7 @@ function TreeNode({ folder, depth, folders, currentFolderId, onNavigate, onMoveI
13567
13818
  ) : void 0
13568
13819
  }
13569
13820
  ),
13570
- expanded && kids.length ? /* @__PURE__ */ (0, import_jsx_runtime97.jsx)("div", { className: "fd-fb-tree-children", style: { paddingLeft: 14 }, children: kids.map((k) => /* @__PURE__ */ (0, import_jsx_runtime97.jsx)(
13821
+ expanded && kids.length ? /* @__PURE__ */ (0, import_jsx_runtime98.jsx)("div", { className: "fd-fb-tree-children", style: { paddingLeft: 14 }, children: kids.map((k) => /* @__PURE__ */ (0, import_jsx_runtime98.jsx)(
13571
13822
  TreeNode,
13572
13823
  {
13573
13824
  folder: k,
@@ -13606,15 +13857,15 @@ function FileBrowser({
13606
13857
  const canUpload = perm.canUpload !== false && !!onUpload;
13607
13858
  const canRemoveFile = perm.canRemoveFile !== false && !!onRemoveFile;
13608
13859
  const canDeleteFolder = perm.canDeleteFolder !== false && !!onDeleteFolder;
13609
- const [createOpen, setCreateOpen] = React65.useState(false);
13610
- const [createName, setCreateName] = React65.useState("");
13611
- const [renameTarget, setRenameTarget] = React65.useState(null);
13612
- const [renameValue, setRenameValue] = React65.useState("");
13613
- const [deleteTarget, setDeleteTarget] = React65.useState(null);
13614
- const uploadInputRef = React65.useRef(null);
13615
- const crumbFolders = React65.useMemo(() => ancestorsOf(folders, currentFolderId), [folders, currentFolderId]);
13616
- const subfolders = React65.useMemo(() => childrenOf(folders, currentFolderId), [folders, currentFolderId]);
13617
- const currentFiles = React65.useMemo(
13860
+ const [createOpen, setCreateOpen] = React66.useState(false);
13861
+ const [createName, setCreateName] = React66.useState("");
13862
+ const [renameTarget, setRenameTarget] = React66.useState(null);
13863
+ const [renameValue, setRenameValue] = React66.useState("");
13864
+ const [deleteTarget, setDeleteTarget] = React66.useState(null);
13865
+ const uploadInputRef = React66.useRef(null);
13866
+ const crumbFolders = React66.useMemo(() => ancestorsOf(folders, currentFolderId), [folders, currentFolderId]);
13867
+ const subfolders = React66.useMemo(() => childrenOf(folders, currentFolderId), [folders, currentFolderId]);
13868
+ const currentFiles = React66.useMemo(
13618
13869
  () => files.filter((f) => f.folderId === currentFolderId).sort((a, b) => a.name.localeCompare(b.name)),
13619
13870
  [files, currentFolderId]
13620
13871
  );
@@ -13653,10 +13904,10 @@ function FileBrowser({
13653
13904
  if (deleteTarget && onDeleteFolder) onDeleteFolder(deleteTarget);
13654
13905
  setDeleteTarget(null);
13655
13906
  };
13656
- const content = /* @__PURE__ */ (0, import_jsx_runtime97.jsxs)("div", { className: ["fd-fb", className].filter(Boolean).join(" "), children: [
13657
- /* @__PURE__ */ (0, import_jsx_runtime97.jsxs)("div", { className: "fd-fb-head", children: [
13658
- /* @__PURE__ */ (0, import_jsx_runtime97.jsxs)("nav", { className: "fd-fb-crumbs", "aria-label": "Folder path", children: [
13659
- /* @__PURE__ */ (0, import_jsx_runtime97.jsx)(
13907
+ const content = /* @__PURE__ */ (0, import_jsx_runtime98.jsxs)("div", { className: ["fd-fb", className].filter(Boolean).join(" "), children: [
13908
+ /* @__PURE__ */ (0, import_jsx_runtime98.jsxs)("div", { className: "fd-fb-head", children: [
13909
+ /* @__PURE__ */ (0, import_jsx_runtime98.jsxs)("nav", { className: "fd-fb-crumbs", "aria-label": "Folder path", children: [
13910
+ /* @__PURE__ */ (0, import_jsx_runtime98.jsx)(
13660
13911
  BreadcrumbCrumb,
13661
13912
  {
13662
13913
  label: "Home",
@@ -13666,7 +13917,7 @@ function FileBrowser({
13666
13917
  onDropPayload: (p) => moveIntoFolder(p, null)
13667
13918
  }
13668
13919
  ),
13669
- crumbFolders.map((f, i) => /* @__PURE__ */ (0, import_jsx_runtime97.jsx)(
13920
+ crumbFolders.map((f, i) => /* @__PURE__ */ (0, import_jsx_runtime98.jsx)(
13670
13921
  BreadcrumbCrumb,
13671
13922
  {
13672
13923
  label: f.name,
@@ -13678,11 +13929,11 @@ function FileBrowser({
13678
13929
  f.id
13679
13930
  ))
13680
13931
  ] }),
13681
- /* @__PURE__ */ (0, import_jsx_runtime97.jsxs)("span", { className: "fd-fb-actions", children: [
13682
- canCreateFolder ? /* @__PURE__ */ (0, import_jsx_runtime97.jsx)(Button, { variant: "secondary", size: "sm", icon: "folder-simple-plus", onClick: openCreate, children: "New folder" }) : null,
13683
- canUpload ? /* @__PURE__ */ (0, import_jsx_runtime97.jsxs)(import_jsx_runtime97.Fragment, { children: [
13684
- /* @__PURE__ */ (0, import_jsx_runtime97.jsx)(Button, { variant: "secondary", size: "sm", icon: "upload-simple", onClick: () => uploadInputRef.current && uploadInputRef.current.click(), children: "Upload" }),
13685
- /* @__PURE__ */ (0, import_jsx_runtime97.jsx)(
13932
+ /* @__PURE__ */ (0, import_jsx_runtime98.jsxs)("span", { className: "fd-fb-actions", children: [
13933
+ canCreateFolder ? /* @__PURE__ */ (0, import_jsx_runtime98.jsx)(Button, { variant: "secondary", size: "sm", icon: "folder-simple-plus", onClick: openCreate, children: "New folder" }) : null,
13934
+ canUpload ? /* @__PURE__ */ (0, import_jsx_runtime98.jsxs)(import_jsx_runtime98.Fragment, { children: [
13935
+ /* @__PURE__ */ (0, import_jsx_runtime98.jsx)(Button, { variant: "secondary", size: "sm", icon: "upload-simple", onClick: () => uploadInputRef.current && uploadInputRef.current.click(), children: "Upload" }),
13936
+ /* @__PURE__ */ (0, import_jsx_runtime98.jsx)(
13686
13937
  "input",
13687
13938
  {
13688
13939
  ref: uploadInputRef,
@@ -13700,9 +13951,9 @@ function FileBrowser({
13700
13951
  ] }) : null
13701
13952
  ] })
13702
13953
  ] }),
13703
- /* @__PURE__ */ (0, import_jsx_runtime97.jsxs)("div", { className: "fd-fb-body", children: [
13704
- /* @__PURE__ */ (0, import_jsx_runtime97.jsxs)("div", { className: "fd-fb-tree", role: "region", "aria-label": "Folder tree", children: [
13705
- /* @__PURE__ */ (0, import_jsx_runtime97.jsx)(
13954
+ /* @__PURE__ */ (0, import_jsx_runtime98.jsxs)("div", { className: "fd-fb-body", children: [
13955
+ /* @__PURE__ */ (0, import_jsx_runtime98.jsxs)("div", { className: "fd-fb-tree", role: "region", "aria-label": "Folder tree", children: [
13956
+ /* @__PURE__ */ (0, import_jsx_runtime98.jsx)(
13706
13957
  RowShell,
13707
13958
  {
13708
13959
  icon: "house-simple",
@@ -13713,7 +13964,7 @@ function FileBrowser({
13713
13964
  className: ["fd-fb-tree-row", currentFolderId == null ? "is-current" : ""].filter(Boolean).join(" ")
13714
13965
  }
13715
13966
  ),
13716
- childrenOf(folders, null).map((f) => /* @__PURE__ */ (0, import_jsx_runtime97.jsx)(
13967
+ childrenOf(folders, null).map((f) => /* @__PURE__ */ (0, import_jsx_runtime98.jsx)(
13717
13968
  TreeNode,
13718
13969
  {
13719
13970
  folder: f,
@@ -13727,18 +13978,18 @@ function FileBrowser({
13727
13978
  f.id
13728
13979
  ))
13729
13980
  ] }),
13730
- /* @__PURE__ */ (0, import_jsx_runtime97.jsx)("div", { className: "fd-fb-main", role: "region", "aria-label": "Folder contents", children: /* @__PURE__ */ (0, import_jsx_runtime97.jsx)(
13981
+ /* @__PURE__ */ (0, import_jsx_runtime98.jsx)("div", { className: "fd-fb-main", role: "region", "aria-label": "Folder contents", children: /* @__PURE__ */ (0, import_jsx_runtime98.jsx)(
13731
13982
  LoadingRegion,
13732
13983
  {
13733
13984
  state: loading ? "loading" : "ready",
13734
13985
  label: "Loading folder contents",
13735
- skeleton: /* @__PURE__ */ (0, import_jsx_runtime97.jsxs)("div", { className: "fd-stack", style: { gap: 8, padding: 12 }, children: [
13736
- /* @__PURE__ */ (0, import_jsx_runtime97.jsx)(Skeleton, { h: 44, radius: "10px" }),
13737
- /* @__PURE__ */ (0, import_jsx_runtime97.jsx)(Skeleton, { h: 44, radius: "10px" }),
13738
- /* @__PURE__ */ (0, import_jsx_runtime97.jsx)(Skeleton, { h: 44, radius: "10px" })
13986
+ skeleton: /* @__PURE__ */ (0, import_jsx_runtime98.jsxs)("div", { className: "fd-stack", style: { gap: 8, padding: 12 }, children: [
13987
+ /* @__PURE__ */ (0, import_jsx_runtime98.jsx)(Skeleton, { h: 44, radius: "10px" }),
13988
+ /* @__PURE__ */ (0, import_jsx_runtime98.jsx)(Skeleton, { h: 44, radius: "10px" }),
13989
+ /* @__PURE__ */ (0, import_jsx_runtime98.jsx)(Skeleton, { h: 44, radius: "10px" })
13739
13990
  ] }),
13740
- children: isEmpty ? /* @__PURE__ */ (0, import_jsx_runtime97.jsx)(EmptyState, { icon: "folder-open", title: "This folder is empty", children: canUpload ? "Drop files here, or use Upload above." : "Nothing has been filed here yet." }) : /* @__PURE__ */ (0, import_jsx_runtime97.jsxs)("div", { className: "fd-fb-list", children: [
13741
- subfolders.map((f) => /* @__PURE__ */ (0, import_jsx_runtime97.jsx)(
13991
+ children: isEmpty ? /* @__PURE__ */ (0, import_jsx_runtime98.jsx)(EmptyState, { icon: "folder-open", title: "This folder is empty", children: canUpload ? "Drop files here, or use Upload above." : "Nothing has been filed here yet." }) : /* @__PURE__ */ (0, import_jsx_runtime98.jsxs)("div", { className: "fd-fb-list", children: [
13992
+ subfolders.map((f) => /* @__PURE__ */ (0, import_jsx_runtime98.jsx)(
13742
13993
  RowShell,
13743
13994
  {
13744
13995
  icon: "folder-simple",
@@ -13747,9 +13998,9 @@ function FileBrowser({
13747
13998
  draggableId: canMove ? { kind: "folder", id: f.id } : void 0,
13748
13999
  isDropTarget: canMove,
13749
14000
  onDropPayload: (p) => moveIntoFolder(p, f.id),
13750
- actions: /* @__PURE__ */ (0, import_jsx_runtime97.jsxs)(import_jsx_runtime97.Fragment, { children: [
13751
- canRenameFolder ? /* @__PURE__ */ (0, import_jsx_runtime97.jsx)(IconButton, { icon: "pencil-simple", label: "Rename " + f.name, size: "sm", variant: "ghost", onClick: () => openRename(f) }) : null,
13752
- canMove ? /* @__PURE__ */ (0, import_jsx_runtime97.jsx)(
14001
+ actions: /* @__PURE__ */ (0, import_jsx_runtime98.jsxs)(import_jsx_runtime98.Fragment, { children: [
14002
+ canRenameFolder ? /* @__PURE__ */ (0, import_jsx_runtime98.jsx)(IconButton, { icon: "pencil-simple", label: "Rename " + f.name, size: "sm", variant: "ghost", onClick: () => openRename(f) }) : null,
14003
+ canMove ? /* @__PURE__ */ (0, import_jsx_runtime98.jsx)(
13753
14004
  FolderPickerMenu,
13754
14005
  {
13755
14006
  label: "Move " + f.name,
@@ -13757,12 +14008,12 @@ function FileBrowser({
13757
14008
  onPick: (target) => moveIntoFolder({ kind: "folder", id: f.id }, target)
13758
14009
  }
13759
14010
  ) : null,
13760
- canDeleteFolder ? /* @__PURE__ */ (0, import_jsx_runtime97.jsx)(IconButton, { icon: "trash-simple", label: "Delete " + f.name, size: "sm", variant: "ghost", onClick: () => openDelete(f) }) : null
14011
+ canDeleteFolder ? /* @__PURE__ */ (0, import_jsx_runtime98.jsx)(IconButton, { icon: "trash-simple", label: "Delete " + f.name, size: "sm", variant: "ghost", onClick: () => openDelete(f) }) : null
13761
14012
  ] })
13762
14013
  },
13763
14014
  f.id
13764
14015
  )),
13765
- currentFiles.map((file) => /* @__PURE__ */ (0, import_jsx_runtime97.jsx)(
14016
+ currentFiles.map((file) => /* @__PURE__ */ (0, import_jsx_runtime98.jsx)(
13766
14017
  RowShell,
13767
14018
  {
13768
14019
  icon: iconForMime(file.mime, file.name),
@@ -13770,8 +14021,8 @@ function FileBrowser({
13770
14021
  meta: file.size ? formatBytes(file.size) : void 0,
13771
14022
  onOpen: onOpenFile ? () => onOpenFile(file) : void 0,
13772
14023
  draggableId: canMove ? { kind: "file", id: file.id } : void 0,
13773
- actions: /* @__PURE__ */ (0, import_jsx_runtime97.jsxs)(import_jsx_runtime97.Fragment, { children: [
13774
- canMove ? /* @__PURE__ */ (0, import_jsx_runtime97.jsx)(
14024
+ actions: /* @__PURE__ */ (0, import_jsx_runtime98.jsxs)(import_jsx_runtime98.Fragment, { children: [
14025
+ canMove ? /* @__PURE__ */ (0, import_jsx_runtime98.jsx)(
13775
14026
  FolderPickerMenu,
13776
14027
  {
13777
14028
  label: "Move " + file.name,
@@ -13779,7 +14030,7 @@ function FileBrowser({
13779
14030
  onPick: (target) => onMoveFile && onMoveFile(file.id, target)
13780
14031
  }
13781
14032
  ) : null,
13782
- canRemoveFile ? /* @__PURE__ */ (0, import_jsx_runtime97.jsx)(IconButton, { icon: "trash-simple", label: "Remove " + file.name, size: "sm", variant: "ghost", onClick: () => onRemoveFile && onRemoveFile(file) }) : null
14033
+ canRemoveFile ? /* @__PURE__ */ (0, import_jsx_runtime98.jsx)(IconButton, { icon: "trash-simple", label: "Remove " + file.name, size: "sm", variant: "ghost", onClick: () => onRemoveFile && onRemoveFile(file) }) : null
13783
14034
  ] })
13784
14035
  },
13785
14036
  file.id
@@ -13788,10 +14039,10 @@ function FileBrowser({
13788
14039
  }
13789
14040
  ) })
13790
14041
  ] }),
13791
- /* @__PURE__ */ (0, import_jsx_runtime97.jsx)(Modal, { open: createOpen, title: "New folder", onClose: () => setCreateOpen(false), footer: /* @__PURE__ */ (0, import_jsx_runtime97.jsxs)(import_jsx_runtime97.Fragment, { children: [
13792
- /* @__PURE__ */ (0, import_jsx_runtime97.jsx)(Button, { variant: "secondary", onClick: () => setCreateOpen(false), children: "Cancel" }),
13793
- /* @__PURE__ */ (0, import_jsx_runtime97.jsx)(Button, { onClick: submitCreate, disabled: !createName.trim(), children: "Create" })
13794
- ] }), children: /* @__PURE__ */ (0, import_jsx_runtime97.jsx)(
14042
+ /* @__PURE__ */ (0, import_jsx_runtime98.jsx)(Modal, { open: createOpen, title: "New folder", onClose: () => setCreateOpen(false), footer: /* @__PURE__ */ (0, import_jsx_runtime98.jsxs)(import_jsx_runtime98.Fragment, { children: [
14043
+ /* @__PURE__ */ (0, import_jsx_runtime98.jsx)(Button, { variant: "secondary", onClick: () => setCreateOpen(false), children: "Cancel" }),
14044
+ /* @__PURE__ */ (0, import_jsx_runtime98.jsx)(Button, { onClick: submitCreate, disabled: !createName.trim(), children: "Create" })
14045
+ ] }), children: /* @__PURE__ */ (0, import_jsx_runtime98.jsx)(
13795
14046
  "input",
13796
14047
  {
13797
14048
  className: "fd-fb-input",
@@ -13805,10 +14056,10 @@ function FileBrowser({
13805
14056
  autoFocus: true
13806
14057
  }
13807
14058
  ) }),
13808
- /* @__PURE__ */ (0, import_jsx_runtime97.jsx)(Modal, { open: renameTarget != null, title: "Rename folder", onClose: () => setRenameTarget(null), footer: /* @__PURE__ */ (0, import_jsx_runtime97.jsxs)(import_jsx_runtime97.Fragment, { children: [
13809
- /* @__PURE__ */ (0, import_jsx_runtime97.jsx)(Button, { variant: "secondary", onClick: () => setRenameTarget(null), children: "Cancel" }),
13810
- /* @__PURE__ */ (0, import_jsx_runtime97.jsx)(Button, { onClick: submitRename, disabled: !renameValue.trim(), children: "Save" })
13811
- ] }), children: /* @__PURE__ */ (0, import_jsx_runtime97.jsx)(
14059
+ /* @__PURE__ */ (0, import_jsx_runtime98.jsx)(Modal, { open: renameTarget != null, title: "Rename folder", onClose: () => setRenameTarget(null), footer: /* @__PURE__ */ (0, import_jsx_runtime98.jsxs)(import_jsx_runtime98.Fragment, { children: [
14060
+ /* @__PURE__ */ (0, import_jsx_runtime98.jsx)(Button, { variant: "secondary", onClick: () => setRenameTarget(null), children: "Cancel" }),
14061
+ /* @__PURE__ */ (0, import_jsx_runtime98.jsx)(Button, { onClick: submitRename, disabled: !renameValue.trim(), children: "Save" })
14062
+ ] }), children: /* @__PURE__ */ (0, import_jsx_runtime98.jsx)(
13812
14063
  "input",
13813
14064
  {
13814
14065
  className: "fd-fb-input",
@@ -13822,22 +14073,22 @@ function FileBrowser({
13822
14073
  autoFocus: true
13823
14074
  }
13824
14075
  ) }),
13825
- /* @__PURE__ */ (0, import_jsx_runtime97.jsx)(
14076
+ /* @__PURE__ */ (0, import_jsx_runtime98.jsx)(
13826
14077
  Modal,
13827
14078
  {
13828
14079
  open: deleteTarget != null,
13829
14080
  title: deleteTarget ? "Delete \u201C" + deleteTarget.name + "\u201D?" : "Delete folder?",
13830
14081
  description: "This can't be undone. The folder must be empty.",
13831
14082
  onClose: () => setDeleteTarget(null),
13832
- footer: /* @__PURE__ */ (0, import_jsx_runtime97.jsxs)(import_jsx_runtime97.Fragment, { children: [
13833
- /* @__PURE__ */ (0, import_jsx_runtime97.jsx)(Button, { variant: "secondary", onClick: () => setDeleteTarget(null), children: "Cancel" }),
13834
- /* @__PURE__ */ (0, import_jsx_runtime97.jsx)(Button, { variant: "danger", onClick: confirmDelete, children: "Delete" })
14083
+ footer: /* @__PURE__ */ (0, import_jsx_runtime98.jsxs)(import_jsx_runtime98.Fragment, { children: [
14084
+ /* @__PURE__ */ (0, import_jsx_runtime98.jsx)(Button, { variant: "secondary", onClick: () => setDeleteTarget(null), children: "Cancel" }),
14085
+ /* @__PURE__ */ (0, import_jsx_runtime98.jsx)(Button, { variant: "danger", onClick: confirmDelete, children: "Delete" })
13835
14086
  ] })
13836
14087
  }
13837
14088
  )
13838
14089
  ] });
13839
14090
  if (!canUpload) return content;
13840
- return /* @__PURE__ */ (0, import_jsx_runtime97.jsx)(Dropzone, { className: "fd-fb-dropzone", onFiles: (picked) => onUpload && onUpload(picked, currentFolderId), label: "Drop files to upload", children: content });
14091
+ return /* @__PURE__ */ (0, import_jsx_runtime98.jsx)(Dropzone, { className: "fd-fb-dropzone", onFiles: (picked) => onUpload && onUpload(picked, currentFolderId), label: "Drop files to upload", children: content });
13841
14092
  }
13842
14093
  function BreadcrumbCrumb({
13843
14094
  label,
@@ -13846,8 +14097,8 @@ function BreadcrumbCrumb({
13846
14097
  isDropTarget,
13847
14098
  onDropPayload
13848
14099
  }) {
13849
- const [over, setOver] = React65.useState(false);
13850
- const dragCounter = React65.useRef(0);
14100
+ const [over, setOver] = React66.useState(false);
14101
+ const dragCounter = React66.useRef(0);
13851
14102
  const dropHandlers = isDropTarget ? {
13852
14103
  onDragEnter: (e) => {
13853
14104
  if (!hasInternalPayload(e)) return;
@@ -13872,11 +14123,11 @@ function BreadcrumbCrumb({
13872
14123
  if (payload && onDropPayload) onDropPayload(payload);
13873
14124
  }
13874
14125
  } : {};
13875
- return /* @__PURE__ */ (0, import_jsx_runtime97.jsx)("span", { className: ["fd-fb-crumb", over ? "is-drop-target" : ""].filter(Boolean).join(" "), ...dropHandlers, children: isCurrent ? /* @__PURE__ */ (0, import_jsx_runtime97.jsx)("span", { className: "fd-fb-crumb-current", "aria-current": "page", children: label }) : /* @__PURE__ */ (0, import_jsx_runtime97.jsx)("button", { type: "button", className: "fd-fb-crumb-link", onClick, children: label }) });
14126
+ return /* @__PURE__ */ (0, import_jsx_runtime98.jsx)("span", { className: ["fd-fb-crumb", over ? "is-drop-target" : ""].filter(Boolean).join(" "), ...dropHandlers, children: isCurrent ? /* @__PURE__ */ (0, import_jsx_runtime98.jsx)("span", { className: "fd-fb-crumb-current", "aria-current": "page", children: label }) : /* @__PURE__ */ (0, import_jsx_runtime98.jsx)("button", { type: "button", className: "fd-fb-crumb-link", onClick, children: label }) });
13876
14127
  }
13877
14128
 
13878
14129
  // src/kits/query.ts
13879
- var React66 = __toESM(require("react"), 1);
14130
+ var React67 = __toESM(require("react"), 1);
13880
14131
  var isMultiSelectShaped = (v) => !!v && typeof v === "object" && Array.isArray(v.values);
13881
14132
  var isRangeShaped = (v) => !!v && typeof v === "object" && ("min" in v || "max" in v);
13882
14133
  var isDateShaped = (v) => !!v && typeof v === "object" && "kind" in v;
@@ -13931,22 +14182,22 @@ function compare(a, b, dir) {
13931
14182
  var API = null;
13932
14183
  var PREFS = null;
13933
14184
  function useServerTable({ endpoint, params, defaults, deps, prefsKey }) {
13934
- const [query, setQuery] = React66.useState(() => {
14185
+ const [query, setQuery] = React67.useState(() => {
13935
14186
  const store = PREFS || window.PlannerPrefs;
13936
14187
  const saved = prefsKey && store ? store.getTable(prefsKey) : {};
13937
14188
  return { ...DEFAULTS, ...defaults || {}, ...saved.pageSize ? { pageSize: saved.pageSize } : {}, ...saved.sort ? { sort: saved.sort, dir: saved.dir || "desc" } : {} };
13938
14189
  });
13939
- const savePref = React66.useCallback((patch2) => {
14190
+ const savePref = React67.useCallback((patch2) => {
13940
14191
  const store = PREFS || window.PlannerPrefs;
13941
14192
  if (prefsKey && store) store.setTable(prefsKey, patch2);
13942
14193
  }, [prefsKey]);
13943
- const [res, setRes] = React66.useState(null);
13944
- const [loading, setLoading] = React66.useState(true);
13945
- const seq2 = React66.useRef(0);
14194
+ const [res, setRes] = React67.useState(null);
14195
+ const [loading, setLoading] = React67.useState(true);
14196
+ const seq2 = React67.useRef(0);
13946
14197
  const depKey = (deps || []).join("|");
13947
14198
  const paramKey = JSON.stringify(params || {});
13948
14199
  const queryKey = JSON.stringify(query);
13949
- React66.useEffect(() => {
14200
+ React67.useEffect(() => {
13950
14201
  const id = ++seq2.current;
13951
14202
  setLoading(true);
13952
14203
  const t = setTimeout(() => {
@@ -14265,12 +14516,12 @@ function createVersionStore(initialState, options) {
14265
14516
  }
14266
14517
 
14267
14518
  // src/kits/documentTitle.ts
14268
- var React67 = __toESM(require("react"), 1);
14519
+ var React68 = __toESM(require("react"), 1);
14269
14520
  function formatDocumentTitle(routeTitle, appName) {
14270
14521
  return [routeTitle, appName, "Flytedesk"].filter((part) => !!part && part.length > 0).join(" \xB7 ");
14271
14522
  }
14272
14523
  function useDocumentTitle(routeTitle, appName) {
14273
- React67.useEffect(() => {
14524
+ React68.useEffect(() => {
14274
14525
  if (typeof document === "undefined") return;
14275
14526
  document.title = formatDocumentTitle(routeTitle, appName);
14276
14527
  }, [routeTitle, appName]);
@@ -14313,6 +14564,7 @@ function useDocumentTitle(routeTitle, appName) {
14313
14564
  Clamp,
14314
14565
  ClockFace,
14315
14566
  CodeBlock,
14567
+ CodeEditor,
14316
14568
  Collapsible,
14317
14569
  ComingSoon,
14318
14570
  CsiBadge,
@@ -14358,6 +14610,7 @@ function useDocumentTitle(routeTitle, appName) {
14358
14610
  JobTray,
14359
14611
  Json,
14360
14612
  KeyHint,
14613
+ LAYER_STEP,
14361
14614
  LoadingRegion,
14362
14615
  Markdown,
14363
14616
  MarkdownEditor,
@@ -14372,6 +14625,7 @@ function useDocumentTitle(routeTitle, appName) {
14372
14625
  ModeSwitch,
14373
14626
  ModelControls,
14374
14627
  NumberInput,
14628
+ OVERLAY_CEILING,
14375
14629
  POPOVER_BODY_MIN,
14376
14630
  PacketCard,
14377
14631
  Pagination,
@@ -14384,6 +14638,7 @@ function useDocumentTitle(routeTitle, appName) {
14384
14638
  ProgressBar,
14385
14639
  QueryKit,
14386
14640
  QuotaRow,
14641
+ ROOT_STEP,
14387
14642
  Radio,
14388
14643
  RangeSlider,
14389
14644
  RelativeTime,
@@ -14428,6 +14683,7 @@ function useDocumentTitle(routeTitle, appName) {
14428
14683
  VIRTUAL_LIST_BUFFER_ROWS,
14429
14684
  VIRTUAL_LIST_ROW_GAP,
14430
14685
  VirtualList,
14686
+ __resetLayerStackForTests,
14431
14687
  acceptMatches,
14432
14688
  anyOfFilter,
14433
14689
  applyPrefs,
@@ -14477,6 +14733,7 @@ function useDocumentTitle(routeTitle, appName) {
14477
14733
  useChatEngine,
14478
14734
  useDocumentTitle,
14479
14735
  useFeatureStatus,
14736
+ useLayerZIndex,
14480
14737
  usePopoverPosition,
14481
14738
  useResponsiveRail,
14482
14739
  useRuntimeMode,