@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.js CHANGED
@@ -202,6 +202,8 @@ function open(layer) {
202
202
  layer.order = ++lastOrder;
203
203
  lastClosed = null;
204
204
  if (layer.options.trap && !contains(scopeOf(layer), document.activeElement)) focusInto(layer);
205
+ zIndexVersion++;
206
+ notifyZIndexListeners();
205
207
  }
206
208
  function close(layer) {
207
209
  openLayers.delete(layer);
@@ -212,7 +214,53 @@ function close(layer) {
212
214
  document.removeEventListener("keydown", onKeydown);
213
215
  pendingEscape = null;
214
216
  }
217
+ zIndexVersion++;
218
+ notifyZIndexListeners();
215
219
  }
220
+ var LAYER_STEP = 10;
221
+ var ROOT_STEP = 100;
222
+ var OVERLAY_CEILING = 1e4;
223
+ var zIndexListeners = /* @__PURE__ */ new Set();
224
+ var notifyZIndexListeners = () => {
225
+ zIndexListeners.forEach((listener) => listener());
226
+ };
227
+ var subscribeZIndex = (listener) => {
228
+ zIndexListeners.add(listener);
229
+ return () => {
230
+ zIndexListeners.delete(listener);
231
+ };
232
+ };
233
+ var zIndexVersion = 0;
234
+ var getZIndexVersion = () => zIndexVersion;
235
+ function openSiblingsOf(layer) {
236
+ const siblings = [];
237
+ for (const l of openLayers) if (l.parent === layer.parent) siblings.push(l);
238
+ return siblings.sort((a, b) => a.order - b.order);
239
+ }
240
+ function computeZIndex(layer) {
241
+ const path = [];
242
+ for (let l = layer; l; l = l.parent) path.push(l);
243
+ path.reverse();
244
+ let z = 0;
245
+ for (const l of path) {
246
+ const siblings = openSiblingsOf(l);
247
+ const index = Math.max(0, siblings.indexOf(l));
248
+ z = l.parent === null ? (index + 1) * ROOT_STEP : z + LAYER_STEP + index;
249
+ }
250
+ return z;
251
+ }
252
+ function useLayerZIndex(layer) {
253
+ React2.useSyncExternalStore(subscribeZIndex, getZIndexVersion, getZIndexVersion);
254
+ const l = layer;
255
+ return l.order > 0 ? computeZIndex(l) : 0;
256
+ }
257
+ var __resetLayerStackForTests = () => {
258
+ openLayers.clear();
259
+ lastOrder = 0;
260
+ pendingEscape = null;
261
+ lastClosed = null;
262
+ notifyZIndexListeners();
263
+ };
216
264
  function returnFocus(layer) {
217
265
  if (layer.options.returnFocus === false) return;
218
266
  const current2 = document.activeElement;
@@ -369,50 +417,6 @@ var portal = (node) => {
369
417
  if (typeof document !== "undefined") return createPortal(node, document.body);
370
418
  return node;
371
419
  };
372
- var ROOT_LAYER = 0;
373
- var LAYER_STEP = 10;
374
- var ROOT_STEP = 100;
375
- var OVERLAY_CEILING = 1e4;
376
- var LayerContext2 = React3.createContext(ROOT_LAYER);
377
- var openRootIds = [];
378
- var rootListeners = /* @__PURE__ */ new Set();
379
- var notifyRootListeners = () => {
380
- rootListeners.forEach((listener) => listener());
381
- };
382
- var subscribeRootOverlays = (listener) => {
383
- rootListeners.add(listener);
384
- return () => {
385
- rootListeners.delete(listener);
386
- };
387
- };
388
- var getRootOverlaysSnapshot = () => openRootIds;
389
- var registerRootOverlay = (id) => {
390
- if (openRootIds.includes(id)) return;
391
- openRootIds = [...openRootIds, id];
392
- notifyRootListeners();
393
- };
394
- var unregisterRootOverlay = (id) => {
395
- if (!openRootIds.includes(id)) return;
396
- openRootIds = openRootIds.filter((existing) => existing !== id);
397
- notifyRootListeners();
398
- };
399
- var useLayer = () => React3.useContext(LayerContext2);
400
- var useOverlayLayer = (isOpen) => {
401
- const parent = useLayer();
402
- const isRoot = parent === ROOT_LAYER;
403
- const id = React3.useId();
404
- const openIds = React3.useSyncExternalStore(subscribeRootOverlays, getRootOverlaysSnapshot, getRootOverlaysSnapshot);
405
- React3.useLayoutEffect(() => {
406
- if (!isRoot || !isOpen) return;
407
- registerRootOverlay(id);
408
- return () => unregisterRootOverlay(id);
409
- }, [isRoot, isOpen, id]);
410
- if (!isRoot) return parent + LAYER_STEP;
411
- if (!isOpen) return ROOT_LAYER;
412
- const index = openIds.indexOf(id);
413
- return index === -1 ? ROOT_LAYER : (index + 1) * ROOT_STEP;
414
- };
415
- var LayerProvider = ({ zIndex, children }) => /* @__PURE__ */ jsx4(LayerContext2.Provider, { value: zIndex, children });
416
420
  function Popover({
417
421
  open: open2,
418
422
  anchorRef,
@@ -448,8 +452,8 @@ function Popover({
448
452
  onDetach: onClose,
449
453
  layerRef: ref
450
454
  });
451
- const zIndex = useOverlayLayer(!!open2);
452
455
  const layer = useStackedLayer({ active: !!open2, containerRef: ref, onEscape: closeOnEscape ? onClose : void 0, returnFocus: returnFocus2 });
456
+ const zIndex = useLayerZIndex(layer);
453
457
  React3.useEffect(() => {
454
458
  if (!open2) return;
455
459
  const away = (e) => {
@@ -465,7 +469,7 @@ function Popover({
465
469
  }, [open2, closeOnOutside, onClose, anchorRef, triggerRef, layer]);
466
470
  if (!open2 || !pos) return null;
467
471
  return portal(
468
- /* @__PURE__ */ jsx4(LayerProvider, { zIndex, children: /* @__PURE__ */ jsx4(StackedLayerProvider, { layer, children: /* @__PURE__ */ jsxs3(
472
+ /* @__PURE__ */ jsx4(StackedLayerProvider, { layer, children: /* @__PURE__ */ jsxs3(
469
473
  "div",
470
474
  {
471
475
  ref,
@@ -508,7 +512,7 @@ function Popover({
508
512
  footer != null ? /* @__PURE__ */ jsx4("div", { className: "fd-pop-footer", children: footer }) : null
509
513
  ]
510
514
  }
511
- ) }) })
515
+ ) })
512
516
  );
513
517
  }
514
518
  var isItem = (it) => !!it && it.kind !== "separator" && it.kind !== "section" && it.kind !== "custom" && !it.disabled;
@@ -760,6 +764,7 @@ import { jsx as jsx6 } from "react/jsx-runtime";
760
764
  function AnchoredPopover({ rect, width = 620, onClose, children }) {
761
765
  const ref = React4.useRef(null);
762
766
  const layer = useStackedLayer({ active: !!rect, containerRef: ref, onEscape: onClose });
767
+ const zIndex = useLayerZIndex(layer);
763
768
  const w = Math.min(width, window.innerWidth - 32);
764
769
  const [h, setH] = React4.useState(0);
765
770
  React4.useLayoutEffect(() => {
@@ -801,7 +806,7 @@ function AnchoredPopover({ rect, width = 620, onClose, children }) {
801
806
  left,
802
807
  top,
803
808
  width: w,
804
- zIndex: 150,
809
+ zIndex,
805
810
  maxHeight: `calc(100vh - ${PAD * 2}px)`,
806
811
  overflowY: "auto",
807
812
  background: "var(--surface)",
@@ -924,7 +929,6 @@ import * as React6 from "react";
924
929
  import { createPortal as createPortal2 } from "react-dom";
925
930
  import { jsx as jsx9, jsxs as jsxs6 } from "react/jsx-runtime";
926
931
  function Drawer({ open: open2 = true, title, onClose, footer, children, className = "", ...rest }) {
927
- const zIndex = useOverlayLayer(open2);
928
932
  const asideRef = React6.useRef(null);
929
933
  const [closing, setClosing] = React6.useState(false);
930
934
  const close2 = React6.useCallback(() => {
@@ -933,9 +937,10 @@ function Drawer({ open: open2 = true, title, onClose, footer, children, classNam
933
937
  setTimeout(onClose, 210);
934
938
  }, [onClose]);
935
939
  const layer = useStackedLayer({ active: !!open2, containerRef: asideRef, trap: true, onEscape: onClose ? close2 : void 0 });
940
+ const zIndex = useLayerZIndex(layer);
936
941
  if (!open2) return null;
937
942
  return createPortal2(
938
- /* @__PURE__ */ jsx9(LayerProvider, { zIndex, children: /* @__PURE__ */ jsxs6(StackedLayerProvider, { layer, children: [
943
+ /* @__PURE__ */ jsxs6(StackedLayerProvider, { layer, children: [
939
944
  /* @__PURE__ */ jsx9("div", { className: "fd-scrim" + (closing ? " is-closing" : ""), style: { display: "block", zIndex: zIndex - LAYER_STEP }, onClick: close2 }),
940
945
  /* @__PURE__ */ jsxs6("aside", { ref: asideRef, className: ["fd-drawer", closing ? "is-closing" : "", className].filter(Boolean).join(" "), role: "dialog", "aria-modal": "true", ...rest, style: { zIndex }, children: [
941
946
  /* @__PURE__ */ jsxs6("div", { className: "fd-card-head", style: { flex: "none" }, children: [
@@ -945,7 +950,7 @@ function Drawer({ open: open2 = true, title, onClose, footer, children, classNam
945
950
  /* @__PURE__ */ jsx9("div", { style: { flex: "1 1 auto", minHeight: 0, overflow: "auto", padding: 20 }, children }),
946
951
  footer ? /* @__PURE__ */ jsx9("div", { className: "fd-card-foot", style: { flex: "none" }, children: typeof footer === "function" ? footer(close2) : footer }) : null
947
952
  ] })
948
- ] }) }),
953
+ ] }),
949
954
  document.body
950
955
  );
951
956
  }
@@ -957,16 +962,16 @@ import { jsx as jsx10, jsxs as jsxs7 } from "react/jsx-runtime";
957
962
  function Modal({ open: open2 = true, title, description, onClose, footer, wide = false, children, className = "", ...rest }) {
958
963
  const [closing, setClosing] = React7.useState(false);
959
964
  const boxRef = React7.useRef(null);
960
- const zIndex = useOverlayLayer(!!open2);
961
965
  const close2 = React7.useCallback(() => {
962
966
  if (!onClose) return;
963
967
  setClosing(true);
964
968
  setTimeout(onClose, 190);
965
969
  }, [onClose]);
966
970
  const layer = useStackedLayer({ active: !!open2, containerRef: boxRef, trap: true, onEscape: onClose ? close2 : void 0 });
971
+ const zIndex = useLayerZIndex(layer);
967
972
  if (!open2) return null;
968
973
  return createPortal3(
969
- /* @__PURE__ */ jsx10(LayerProvider, { zIndex, children: /* @__PURE__ */ jsx10(StackedLayerProvider, { layer, children: /* @__PURE__ */ jsx10(
974
+ /* @__PURE__ */ jsx10(StackedLayerProvider, { layer, children: /* @__PURE__ */ jsx10(
970
975
  "div",
971
976
  {
972
977
  className: "fd-scrim" + (closing ? " is-closing" : ""),
@@ -997,7 +1002,7 @@ function Modal({ open: open2 = true, title, description, onClose, footer, wide =
997
1002
  }
998
1003
  )
999
1004
  }
1000
- ) }) }),
1005
+ ) }),
1001
1006
  document.body
1002
1007
  );
1003
1008
  }
@@ -1860,8 +1865,8 @@ function Tooltip({ label, placement = "top", children, className = "" }) {
1860
1865
  layerRef: bubbleRef,
1861
1866
  onDetach: hide
1862
1867
  });
1863
- const zIndex = useOverlayLayer(open2);
1864
- useStackedLayer({ active: open2, containerRef: bubbleRef, onEscape: hide, returnFocus: false });
1868
+ const layer = useStackedLayer({ active: open2, containerRef: bubbleRef, onEscape: hide, returnFocus: false });
1869
+ const zIndex = useLayerZIndex(layer);
1865
1870
  React14.useEffect(() => {
1866
1871
  if (!open2) return;
1867
1872
  const away = (e) => {
@@ -4641,7 +4646,7 @@ function CodeBlock({
4641
4646
  code = "",
4642
4647
  language,
4643
4648
  filename,
4644
- lineNumbers = false,
4649
+ lineNumbers: lineNumbers2 = false,
4645
4650
  wrap: wrapDefault = false,
4646
4651
  collapseAfter = 26,
4647
4652
  copyable = true,
@@ -4668,7 +4673,7 @@ function CodeBlock({
4668
4673
  ] }) : null
4669
4674
  ] }),
4670
4675
  /* @__PURE__ */ jsxs41("div", { className: "fd-code-body", children: [
4671
- lineNumbers ? /* @__PURE__ */ jsx49("pre", { className: "fd-code-gutter", "aria-hidden": "true", children: shown.split("\n").map((_, i) => i + 1 + "\n").join("") }) : null,
4676
+ lineNumbers2 ? /* @__PURE__ */ jsx49("pre", { className: "fd-code-gutter", "aria-hidden": "true", children: shown.split("\n").map((_, i) => i + 1 + "\n").join("") }) : null,
4672
4677
  /* @__PURE__ */ jsx49("pre", { className: "fd-code-pre", tabIndex: 0, children: /* @__PURE__ */ jsx49("code", { children: /* @__PURE__ */ jsx49(Highlighted, { code: shown, lang: language }) }) })
4673
4678
  ] }),
4674
4679
  foldable ? /* @__PURE__ */ jsxs41("button", { type: "button", className: "fd-code-fold", onClick: () => setOpen((v) => !v), "aria-expanded": open2, children: [
@@ -5184,9 +5189,9 @@ import * as React31 from "react";
5184
5189
  import { jsx as jsx54 } from "react/jsx-runtime";
5185
5190
  function useInlinePanel() {
5186
5191
  const [open2, setOpen] = React31.useState(false);
5187
- const zIndex = useOverlayLayer(open2);
5188
5192
  const ref = React31.useRef(null);
5189
5193
  const layer = useStackedLayer({ active: open2, containerRef: ref, onEscape: () => setOpen(false) });
5194
+ const zIndex = useLayerZIndex(layer);
5190
5195
  React31.useEffect(() => {
5191
5196
  if (!open2) return;
5192
5197
  const away = (e) => {
@@ -5198,7 +5203,7 @@ function useInlinePanel() {
5198
5203
  return { open: open2, setOpen, ref, zIndex, layer };
5199
5204
  }
5200
5205
  function InlinePanelLayers({ panel, children }) {
5201
- return /* @__PURE__ */ jsx54(LayerProvider, { zIndex: panel.zIndex, children: /* @__PURE__ */ jsx54(StackedLayerProvider, { layer: panel.layer, children }) });
5206
+ return /* @__PURE__ */ jsx54(StackedLayerProvider, { layer: panel.layer, children });
5202
5207
  }
5203
5208
 
5204
5209
  // src/components/data/SortMenu.tsx
@@ -7251,17 +7256,254 @@ var MarkdownEditor = React42.forwardRef(function MarkdownEditor2({
7251
7256
  ] });
7252
7257
  });
7253
7258
 
7259
+ // src/components/forms/CodeEditor.tsx
7260
+ import * as React43 from "react";
7261
+ import { EditorView, keymap, lineNumbers, placeholder as cmPlaceholder, drawSelection, Decoration } from "@codemirror/view";
7262
+ import { EditorState, StateEffect, StateField, Compartment } from "@codemirror/state";
7263
+ import { defaultKeymap, history, historyKeymap, indentMore, indentLess } from "@codemirror/commands";
7264
+ import { sql as sqlLang } from "@codemirror/lang-sql";
7265
+ import { syntaxHighlighting, HighlightStyle, indentOnInput, bracketMatching } from "@codemirror/language";
7266
+ import { tags } from "@lezer/highlight";
7267
+ import { jsx as jsx72, jsxs as jsxs63 } from "react/jsx-runtime";
7268
+ function clampOffset(state, line, column) {
7269
+ const total = state.doc.lines;
7270
+ const ln = state.doc.line(Math.min(Math.max(1, line), total));
7271
+ const col = Math.max(0, (column || 1) - 1);
7272
+ return Math.min(ln.from + col, ln.to);
7273
+ }
7274
+ function toCmDiagnostics(state, diags) {
7275
+ return diags.map((d) => {
7276
+ const from = clampOffset(state, d.line, d.column ?? 1);
7277
+ const endLine = d.endLine ?? d.line;
7278
+ const endColumn = d.endColumn ?? state.doc.line(Math.min(Math.max(1, endLine), state.doc.lines)).length + 1;
7279
+ let to = clampOffset(state, endLine, endColumn);
7280
+ if (to <= from) to = Math.min(from + 1, state.doc.length);
7281
+ return { from, to, severity: d.severity || "error", message: d.message, source: void 0 };
7282
+ });
7283
+ }
7284
+ var setDiagnosticsEffect = StateEffect.define();
7285
+ var diagnosticsField = StateField.define({
7286
+ create: () => [],
7287
+ update(value, tr) {
7288
+ for (const e of tr.effects) if (e.is(setDiagnosticsEffect)) return e.value;
7289
+ if (!tr.docChanged) return value;
7290
+ return value.map((d) => ({ ...d, from: tr.changes.mapPos(d.from), to: tr.changes.mapPos(d.to) }));
7291
+ }
7292
+ });
7293
+ var tokenHighlight = HighlightStyle.define([
7294
+ { tag: tags.keyword, class: "tok-kw" },
7295
+ { tag: tags.string, class: "tok-str" },
7296
+ { tag: [tags.number, tags.bool], class: "tok-num" },
7297
+ { tag: tags.comment, class: "tok-com" },
7298
+ { tag: [tags.function(tags.variableName), tags.function(tags.propertyName)], class: "tok-fn" },
7299
+ { tag: tags.typeName, class: "tok-type" },
7300
+ { tag: tags.propertyName, class: "tok-prop" },
7301
+ { tag: tags.null, class: "tok-lit" },
7302
+ { tag: [tags.punctuation, tags.paren, tags.bracket], class: "tok-pun" },
7303
+ { tag: tags.operator, class: "tok-op" }
7304
+ ]);
7305
+ var editorTheme = EditorView.theme({
7306
+ "&": {
7307
+ fontFamily: "var(--font-mono)",
7308
+ fontSize: "12.5px",
7309
+ color: "var(--text)",
7310
+ backgroundColor: "transparent",
7311
+ height: "100%"
7312
+ },
7313
+ ".cm-content": { padding: "10px 12px", caretColor: "var(--text)" },
7314
+ ".cm-scroller": { fontFamily: "var(--font-mono)", lineHeight: "1.62" },
7315
+ ".cm-gutters": {
7316
+ backgroundColor: "transparent",
7317
+ color: "var(--text-disabled)",
7318
+ border: "0",
7319
+ borderRight: "1px solid var(--chat-code-border)"
7320
+ },
7321
+ ".cm-lineNumbers .cm-gutterElement": { padding: "0 8px 0 12px" },
7322
+ ".cm-activeLine": { backgroundColor: "var(--surface-2)" },
7323
+ ".cm-activeLineGutter": { backgroundColor: "var(--surface-2)", color: "var(--text-2)" },
7324
+ "&.cm-focused": { outline: "none" },
7325
+ ".cm-cursor": { borderLeftColor: "var(--text)" },
7326
+ ".cm-selectionBackground, &.cm-focused .cm-selectionBackground": { backgroundColor: "var(--blue-100) !important" },
7327
+ ".cm-placeholder": { color: "var(--text-disabled)" },
7328
+ ".fd-cm-diag-error": { textDecoration: "underline wavy var(--danger-solid)", textUnderlineOffset: "3px" },
7329
+ ".fd-cm-diag-warning": { textDecoration: "underline wavy var(--warn-solid)", textUnderlineOffset: "3px" },
7330
+ ".fd-cm-diag-info": { textDecoration: "underline wavy var(--info-solid)", textUnderlineOffset: "3px" }
7331
+ }, { dark: false });
7332
+ function severityClass(sev) {
7333
+ return sev === "warning" ? "fd-cm-diag-warning" : sev === "info" ? "fd-cm-diag-info" : "fd-cm-diag-error";
7334
+ }
7335
+ function decorationsFromDiagnostics() {
7336
+ return EditorView.decorations.compute([diagnosticsField], (state) => {
7337
+ const diags = state.field(diagnosticsField);
7338
+ if (!diags.length) return Decoration.none;
7339
+ const marks = diags.filter((d) => d.from < d.to).sort((a, b) => a.from - b.from).map((d) => Decoration.mark({ class: severityClass(d.severity) }).range(d.from, d.to));
7340
+ return Decoration.set(marks, true);
7341
+ });
7342
+ }
7343
+ function CodeEditor({
7344
+ value,
7345
+ onChange,
7346
+ label,
7347
+ help,
7348
+ error,
7349
+ required = false,
7350
+ disabled = false,
7351
+ readOnly = false,
7352
+ placeholder: placeholderText = "",
7353
+ diagnostics = [],
7354
+ showEscapeHint = true,
7355
+ minHeight = 160,
7356
+ id,
7357
+ className = "",
7358
+ style,
7359
+ autoFocus = false
7360
+ }) {
7361
+ const fieldId = useFieldId(id);
7362
+ const descId = fieldId + "-desc";
7363
+ const liveId = fieldId + "-live";
7364
+ const hostRef = React43.useRef(null);
7365
+ const viewRef = React43.useRef(null);
7366
+ const valueRef = React43.useRef(value);
7367
+ const onChangeRef = React43.useRef(onChange);
7368
+ onChangeRef.current = onChange;
7369
+ const editableCompartment = React43.useRef(new Compartment()).current;
7370
+ const attributesCompartment = React43.useRef(new Compartment()).current;
7371
+ const errorRef = React43.useRef(error);
7372
+ errorRef.current = error;
7373
+ const diagnosticsCountRef = React43.useRef(diagnostics.length);
7374
+ diagnosticsCountRef.current = diagnostics.length;
7375
+ function contentAttributes() {
7376
+ return {
7377
+ id: fieldId,
7378
+ "aria-describedby": descId + " " + liveId,
7379
+ "aria-invalid": errorRef.current || diagnosticsCountRef.current ? "true" : "false",
7380
+ ...label ? { "aria-label": label } : {}
7381
+ };
7382
+ }
7383
+ React43.useEffect(() => {
7384
+ const host = hostRef.current;
7385
+ if (!host) return;
7386
+ const updateListener = EditorView.updateListener.of((update) => {
7387
+ if (!update.docChanged) return;
7388
+ const next = update.state.doc.toString();
7389
+ valueRef.current = next;
7390
+ onChangeRef.current && onChangeRef.current(next);
7391
+ });
7392
+ const state = EditorState.create({
7393
+ doc: value,
7394
+ extensions: [
7395
+ lineNumbers(),
7396
+ history(),
7397
+ drawSelection(),
7398
+ indentOnInput(),
7399
+ bracketMatching(),
7400
+ sqlLang(),
7401
+ syntaxHighlighting(tokenHighlight),
7402
+ diagnosticsField,
7403
+ decorationsFromDiagnostics(),
7404
+ editorTheme,
7405
+ cmPlaceholder(placeholderText),
7406
+ keymap.of([
7407
+ { key: "Tab", run: indentMore, shift: indentLess },
7408
+ ...defaultKeymap,
7409
+ ...historyKeymap
7410
+ ]),
7411
+ editableCompartment.of(EditorView.editable.of(!disabled)),
7412
+ EditorState.readOnly.of(readOnly),
7413
+ updateListener,
7414
+ attributesCompartment.of(EditorView.contentAttributes.of(contentAttributes()))
7415
+ ]
7416
+ });
7417
+ const view = new EditorView({ state, parent: host });
7418
+ viewRef.current = view;
7419
+ if (autoFocus) view.focus();
7420
+ return () => {
7421
+ view.destroy();
7422
+ viewRef.current = null;
7423
+ };
7424
+ }, []);
7425
+ React43.useEffect(() => {
7426
+ const view = viewRef.current;
7427
+ if (!view) return;
7428
+ const current2 = view.state.doc.toString();
7429
+ if (current2 !== value) {
7430
+ view.dispatch({ changes: { from: 0, to: current2.length, insert: value } });
7431
+ }
7432
+ valueRef.current = value;
7433
+ }, [value]);
7434
+ React43.useEffect(() => {
7435
+ const view = viewRef.current;
7436
+ if (!view) return;
7437
+ view.dispatch({ effects: editableCompartment.reconfigure(EditorView.editable.of(!disabled)) });
7438
+ }, [disabled, editableCompartment]);
7439
+ React43.useEffect(() => {
7440
+ const view = viewRef.current;
7441
+ if (!view) return;
7442
+ view.dispatch({
7443
+ effects: [
7444
+ setDiagnosticsEffect.of(toCmDiagnostics(view.state, diagnostics)),
7445
+ attributesCompartment.reconfigure(EditorView.contentAttributes.of(contentAttributes()))
7446
+ ]
7447
+ });
7448
+ }, [diagnostics, error]);
7449
+ const box = ["fd-input", "fd-code-editor", error ? "fd-input-error" : "", disabled ? "fd-input-disabled" : ""].filter(Boolean).join(" ");
7450
+ 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("; ") : "";
7451
+ return /* @__PURE__ */ jsxs63("div", { className: ["fd-field", className].filter(Boolean).join(" "), style, children: [
7452
+ label ? /* @__PURE__ */ jsx72(FieldLabel, { htmlFor: fieldId, required, children: label }) : null,
7453
+ /* @__PURE__ */ jsx72(
7454
+ "div",
7455
+ {
7456
+ className: box,
7457
+ style: { minHeight },
7458
+ children: /* @__PURE__ */ jsx72(
7459
+ "div",
7460
+ {
7461
+ ref: hostRef,
7462
+ className: "fd-code-editor-host",
7463
+ style: { minHeight }
7464
+ }
7465
+ )
7466
+ }
7467
+ ),
7468
+ /* @__PURE__ */ jsxs63("span", { id: descId, className: "fd-sr", children: [
7469
+ help ? help + ". " : "",
7470
+ showEscapeHint ? "Tab indents. Press Escape, then Tab, to move focus out of the editor." : ""
7471
+ ] }),
7472
+ /* @__PURE__ */ jsx72("div", { id: liveId, className: "fd-sr", role: "status", "aria-live": "polite", children: announce }),
7473
+ diagnostics.length ? /* @__PURE__ */ jsx72("ul", { className: "fd-code-editor-diagnostics", children: diagnostics.map((d, i) => /* @__PURE__ */ jsxs63("li", { className: "fd-code-editor-diag is-" + (d.severity || "error"), children: [
7474
+ /* @__PURE__ */ jsx72(
7475
+ "i",
7476
+ {
7477
+ className: "ph ph-" + (d.severity === "warning" ? "warning" : d.severity === "info" ? "info" : "warning-circle"),
7478
+ "aria-hidden": "true"
7479
+ }
7480
+ ),
7481
+ /* @__PURE__ */ jsxs63("span", { className: "fd-code-editor-diag-loc", children: [
7482
+ "Line ",
7483
+ d.line,
7484
+ d.column ? ":" + d.column : ""
7485
+ ] }),
7486
+ /* @__PURE__ */ jsx72("span", { children: d.message })
7487
+ ] }, i)) }) : null,
7488
+ error ? /* @__PURE__ */ jsxs63("span", { className: "fd-field-error", children: [
7489
+ /* @__PURE__ */ jsx72("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
7490
+ error
7491
+ ] }) : !diagnostics.length && help ? /* @__PURE__ */ jsx72("span", { className: "fd-field-help", children: help }) : null,
7492
+ showEscapeHint ? /* @__PURE__ */ jsx72("span", { className: "fd-field-help fd-code-editor-hint", children: "Tab indents. Escape, then Tab, moves focus out." }) : null
7493
+ ] });
7494
+ }
7495
+
7254
7496
  // src/components/platform/AccountMenu.tsx
7255
- import * as React44 from "react";
7497
+ import * as React45 from "react";
7256
7498
 
7257
7499
  // src/kits/sessionContext.tsx
7258
- import * as React43 from "react";
7259
- var SessionContext = React43.createContext(null);
7500
+ import * as React44 from "react";
7501
+ var SessionContext = React44.createContext(null);
7260
7502
  function SessionProvider({ value, children }) {
7261
- return React43.createElement(SessionContext.Provider, { value }, children);
7503
+ return React44.createElement(SessionContext.Provider, { value }, children);
7262
7504
  }
7263
7505
  function useSessionContext() {
7264
- const ctx = React43.useContext(SessionContext);
7506
+ const ctx = React44.useContext(SessionContext);
7265
7507
  if (!ctx) {
7266
7508
  throw new Error(
7267
7509
  "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."
@@ -7271,11 +7513,11 @@ function useSessionContext() {
7271
7513
  }
7272
7514
 
7273
7515
  // src/components/platform/AccountMenu.tsx
7274
- import { Fragment as Fragment16, jsx as jsx72, jsxs as jsxs63 } from "react/jsx-runtime";
7516
+ import { Fragment as Fragment16, jsx as jsx73, jsxs as jsxs64 } from "react/jsx-runtime";
7275
7517
  var DEFAULT_LINKS = [];
7276
7518
  var DEFAULT_GROUPS = [];
7277
7519
  function Item({ item, onPick }) {
7278
- return /* @__PURE__ */ jsxs63(
7520
+ return /* @__PURE__ */ jsxs64(
7279
7521
  "button",
7280
7522
  {
7281
7523
  type: "button",
@@ -7283,9 +7525,9 @@ function Item({ item, onPick }) {
7283
7525
  className: "fd-acct-item",
7284
7526
  onClick: () => onPick(item),
7285
7527
  children: [
7286
- item.icon ? /* @__PURE__ */ jsx72("i", { className: "ph ph-" + item.icon, "aria-hidden": "true" }) : null,
7287
- /* @__PURE__ */ jsx72("span", { style: { flex: 1 }, children: item.label }),
7288
- item.badge ? /* @__PURE__ */ jsx72(Badge, { tone: "neutral", children: item.badge }) : null
7528
+ item.icon ? /* @__PURE__ */ jsx73("i", { className: "ph ph-" + item.icon, "aria-hidden": "true" }) : null,
7529
+ /* @__PURE__ */ jsx73("span", { style: { flex: 1 }, children: item.label }),
7530
+ item.badge ? /* @__PURE__ */ jsx73(Badge, { tone: "neutral", children: item.badge }) : null
7289
7531
  ]
7290
7532
  }
7291
7533
  );
@@ -7301,11 +7543,11 @@ function AccountMenu({
7301
7543
  ...rest
7302
7544
  }) {
7303
7545
  const { user, roles, can: can2, signOut: ctxSignOut, demo, pending } = useSessionContext();
7304
- const [open2, setOpen] = React44.useState(false);
7305
- const [switching, setSwitching] = React44.useState(false);
7306
- const [signingOut, setSigningOut] = React44.useState(false);
7307
- const [signOutError, setSignOutError] = React44.useState(null);
7308
- const ref = React44.useRef(null);
7546
+ const [open2, setOpen] = React45.useState(false);
7547
+ const [switching, setSwitching] = React45.useState(false);
7548
+ const [signingOut, setSigningOut] = React45.useState(false);
7549
+ const [signOutError, setSignOutError] = React45.useState(null);
7550
+ const ref = React45.useRef(null);
7309
7551
  const visibleLinks = links.filter((l) => !l.perm || !pending && can2(l.perm));
7310
7552
  const visibleGroups = groups.map((g) => ({ label: g.label, links: g.links.filter((l) => !l.perm || !pending && can2(l.perm)) })).filter((g) => g.links.length);
7311
7553
  const closeMenu = () => {
@@ -7333,8 +7575,8 @@ function AccountMenu({
7333
7575
  }
7334
7576
  };
7335
7577
  const showSwitcher = allowUserSwitch && !!demo;
7336
- return /* @__PURE__ */ jsxs63(Fragment16, { children: [
7337
- /* @__PURE__ */ jsxs63(
7578
+ return /* @__PURE__ */ jsxs64(Fragment16, { children: [
7579
+ /* @__PURE__ */ jsxs64(
7338
7580
  "button",
7339
7581
  {
7340
7582
  type: "button",
@@ -7346,12 +7588,12 @@ function AccountMenu({
7346
7588
  onClick: () => open2 ? closeMenu() : setOpen(true),
7347
7589
  ...rest,
7348
7590
  children: [
7349
- /* @__PURE__ */ jsx72(Avatar, { name: user.name, size: "sm" }),
7350
- /* @__PURE__ */ jsx72("i", { className: "ph ph-caret-down", "aria-hidden": "true", style: { fontSize: 11, color: "var(--text-muted)" } })
7591
+ /* @__PURE__ */ jsx73(Avatar, { name: user.name, size: "sm" }),
7592
+ /* @__PURE__ */ jsx73("i", { className: "ph ph-caret-down", "aria-hidden": "true", style: { fontSize: 11, color: "var(--text-muted)" } })
7351
7593
  ]
7352
7594
  }
7353
7595
  ),
7354
- /* @__PURE__ */ jsx72(
7596
+ /* @__PURE__ */ jsx73(
7355
7597
  Popover,
7356
7598
  {
7357
7599
  open: open2,
@@ -7359,27 +7601,27 @@ function AccountMenu({
7359
7601
  onClose: closeMenu,
7360
7602
  placement: "bottom-end",
7361
7603
  width: 272,
7362
- children: /* @__PURE__ */ jsxs63("div", { role: "menu", className: "fd-stack", style: { gap: 0 }, children: [
7363
- /* @__PURE__ */ jsxs63("div", { className: "fd-row", style: { gap: 10, padding: "12px 14px", borderBottom: "1px solid var(--border)" }, children: [
7364
- /* @__PURE__ */ jsx72(Avatar, { name: user.name }),
7365
- /* @__PURE__ */ jsxs63("span", { className: "fd-stack", style: { gap: 1, minWidth: 0, flex: 1 }, children: [
7366
- /* @__PURE__ */ jsx72("span", { className: "fd-body-sm", style: { fontWeight: 700 }, children: user.name }),
7367
- /* @__PURE__ */ jsx72("span", { className: "fd-body-sm fd-muted fd-table-trunc", title: truncationTitle(user.email), children: user.email })
7604
+ children: /* @__PURE__ */ jsxs64("div", { role: "menu", className: "fd-stack", style: { gap: 0 }, children: [
7605
+ /* @__PURE__ */ jsxs64("div", { className: "fd-row", style: { gap: 10, padding: "12px 14px", borderBottom: "1px solid var(--border)" }, children: [
7606
+ /* @__PURE__ */ jsx73(Avatar, { name: user.name }),
7607
+ /* @__PURE__ */ jsxs64("span", { className: "fd-stack", style: { gap: 1, minWidth: 0, flex: 1 }, children: [
7608
+ /* @__PURE__ */ jsx73("span", { className: "fd-body-sm", style: { fontWeight: 700 }, children: user.name }),
7609
+ /* @__PURE__ */ jsx73("span", { className: "fd-body-sm fd-muted fd-table-trunc", title: truncationTitle(user.email), children: user.email })
7368
7610
  ] })
7369
7611
  ] }),
7370
- showRoles && roles.length ? /* @__PURE__ */ jsx72("div", { className: "fd-row", style: { gap: 6, padding: "10px 14px", flexWrap: "wrap", borderBottom: "1px solid var(--border)" }, children: roles.map((r) => /* @__PURE__ */ jsx72(Badge, { tone: r.id === "owner" ? "success" : "neutral", children: r.name }, r.id)) }) : null,
7371
- visibleLinks.length ? /* @__PURE__ */ jsx72("div", { className: "fd-acct-group", children: visibleLinks.map((l) => /* @__PURE__ */ jsx72(Item, { item: l, onPick: pick }, l.id)) }) : null,
7372
- visibleGroups.map((g) => /* @__PURE__ */ jsxs63("div", { className: "fd-acct-group", style: { borderTop: "1px solid var(--border)" }, children: [
7373
- /* @__PURE__ */ jsx72("span", { className: "fd-overline fd-muted", style: { padding: "8px 14px 4px", display: "block" }, children: g.label }),
7374
- g.links.map((l) => /* @__PURE__ */ jsx72(Item, { item: l, onPick: pick }, l.id))
7612
+ showRoles && roles.length ? /* @__PURE__ */ jsx73("div", { className: "fd-row", style: { gap: 6, padding: "10px 14px", flexWrap: "wrap", borderBottom: "1px solid var(--border)" }, children: roles.map((r) => /* @__PURE__ */ jsx73(Badge, { tone: r.id === "owner" ? "success" : "neutral", children: r.name }, r.id)) }) : null,
7613
+ visibleLinks.length ? /* @__PURE__ */ jsx73("div", { className: "fd-acct-group", children: visibleLinks.map((l) => /* @__PURE__ */ jsx73(Item, { item: l, onPick: pick }, l.id)) }) : null,
7614
+ visibleGroups.map((g) => /* @__PURE__ */ jsxs64("div", { className: "fd-acct-group", style: { borderTop: "1px solid var(--border)" }, children: [
7615
+ /* @__PURE__ */ jsx73("span", { className: "fd-overline fd-muted", style: { padding: "8px 14px 4px", display: "block" }, children: g.label }),
7616
+ g.links.map((l) => /* @__PURE__ */ jsx73(Item, { item: l, onPick: pick }, l.id))
7375
7617
  ] }, g.label)),
7376
- showSwitcher && demo ? /* @__PURE__ */ jsxs63("div", { className: "fd-acct-group", style: { borderTop: "1px solid var(--border)" }, children: [
7377
- /* @__PURE__ */ jsxs63("button", { type: "button", role: "menuitem", className: "fd-acct-item", onClick: () => setSwitching((s) => !s), children: [
7378
- /* @__PURE__ */ jsx72("i", { className: "ph ph-user-switch", "aria-hidden": "true" }),
7379
- /* @__PURE__ */ jsx72("span", { style: { flex: 1 }, children: "View as another member" }),
7380
- /* @__PURE__ */ jsx72("i", { className: "ph ph-caret-" + (switching ? "up" : "down"), "aria-hidden": "true", style: { fontSize: 11 } })
7618
+ showSwitcher && demo ? /* @__PURE__ */ jsxs64("div", { className: "fd-acct-group", style: { borderTop: "1px solid var(--border)" }, children: [
7619
+ /* @__PURE__ */ jsxs64("button", { type: "button", role: "menuitem", className: "fd-acct-item", onClick: () => setSwitching((s) => !s), children: [
7620
+ /* @__PURE__ */ jsx73("i", { className: "ph ph-user-switch", "aria-hidden": "true" }),
7621
+ /* @__PURE__ */ jsx73("span", { style: { flex: 1 }, children: "View as another member" }),
7622
+ /* @__PURE__ */ jsx73("i", { className: "ph ph-caret-" + (switching ? "up" : "down"), "aria-hidden": "true", style: { fontSize: 11 } })
7381
7623
  ] }),
7382
- switching ? /* @__PURE__ */ jsx72("div", { className: "fd-stack", style: { gap: 0 }, children: demo.allUsers.map((u) => /* @__PURE__ */ jsxs63(
7624
+ switching ? /* @__PURE__ */ jsx73("div", { className: "fd-stack", style: { gap: 0 }, children: demo.allUsers.map((u) => /* @__PURE__ */ jsxs64(
7383
7625
  "button",
7384
7626
  {
7385
7627
  type: "button",
@@ -7391,19 +7633,19 @@ function AccountMenu({
7391
7633
  setSwitching(false);
7392
7634
  },
7393
7635
  children: [
7394
- /* @__PURE__ */ jsx72(Avatar, { name: u.name, size: "sm" }),
7395
- /* @__PURE__ */ jsxs63("span", { className: "fd-stack", style: { gap: 0, flex: 1, minWidth: 0, alignItems: "flex-start" }, children: [
7396
- /* @__PURE__ */ jsx72("span", { style: { fontWeight: u.id === user.id ? 700 : 500 }, children: u.name }),
7397
- u.roles ? /* @__PURE__ */ jsx72("span", { className: "fd-muted", style: { fontSize: 11.5 }, children: u.roles.join(", ") }) : null
7636
+ /* @__PURE__ */ jsx73(Avatar, { name: u.name, size: "sm" }),
7637
+ /* @__PURE__ */ jsxs64("span", { className: "fd-stack", style: { gap: 0, flex: 1, minWidth: 0, alignItems: "flex-start" }, children: [
7638
+ /* @__PURE__ */ jsx73("span", { style: { fontWeight: u.id === user.id ? 700 : 500 }, children: u.name }),
7639
+ u.roles ? /* @__PURE__ */ jsx73("span", { className: "fd-muted", style: { fontSize: 11.5 }, children: u.roles.join(", ") }) : null
7398
7640
  ] }),
7399
- u.id === user.id ? /* @__PURE__ */ jsx72("i", { className: "ph ph-check", "aria-hidden": "true", style: { color: "var(--ok-text)" } }) : null
7641
+ u.id === user.id ? /* @__PURE__ */ jsx73("i", { className: "ph ph-check", "aria-hidden": "true", style: { color: "var(--ok-text)" } }) : null
7400
7642
  ]
7401
7643
  },
7402
7644
  u.id
7403
7645
  )) }) : null
7404
7646
  ] }) : null,
7405
- /* @__PURE__ */ jsxs63("div", { className: "fd-acct-group", style: { borderTop: "1px solid var(--border)" }, children: [
7406
- /* @__PURE__ */ jsxs63(
7647
+ /* @__PURE__ */ jsxs64("div", { className: "fd-acct-group", style: { borderTop: "1px solid var(--border)" }, children: [
7648
+ /* @__PURE__ */ jsxs64(
7407
7649
  "button",
7408
7650
  {
7409
7651
  type: "button",
@@ -7413,14 +7655,14 @@ function AccountMenu({
7413
7655
  disabled: signingOut,
7414
7656
  onClick: signOut,
7415
7657
  children: [
7416
- signingOut ? /* @__PURE__ */ jsx72(Spinner, { size: "sm" }) : /* @__PURE__ */ jsx72("i", { className: "ph ph-sign-out", "aria-hidden": "true" }),
7417
- /* @__PURE__ */ jsx72("span", { style: { flex: 1 }, children: signingOut ? "Signing out\u2026" : "Sign out" })
7658
+ signingOut ? /* @__PURE__ */ jsx73(Spinner, { size: "sm" }) : /* @__PURE__ */ jsx73("i", { className: "ph ph-sign-out", "aria-hidden": "true" }),
7659
+ /* @__PURE__ */ jsx73("span", { style: { flex: 1 }, children: signingOut ? "Signing out\u2026" : "Sign out" })
7418
7660
  ]
7419
7661
  }
7420
7662
  ),
7421
- signOutError ? /* @__PURE__ */ jsxs63("div", { role: "alert", className: "fd-body-sm", style: { padding: "0 14px 12px" }, children: [
7422
- /* @__PURE__ */ jsx72("span", { style: { display: "block", color: "var(--danger-text)", marginBottom: 6 }, children: signOutError }),
7423
- /* @__PURE__ */ jsx72("button", { type: "button", className: "fd-soon-link", disabled: signingOut, onClick: signOut, children: "Retry" })
7663
+ signOutError ? /* @__PURE__ */ jsxs64("div", { role: "alert", className: "fd-body-sm", style: { padding: "0 14px 12px" }, children: [
7664
+ /* @__PURE__ */ jsx73("span", { style: { display: "block", color: "var(--danger-text)", marginBottom: 6 }, children: signOutError }),
7665
+ /* @__PURE__ */ jsx73("button", { type: "button", className: "fd-soon-link", disabled: signingOut, onClick: signOut, children: "Retry" })
7424
7666
  ] }) : null
7425
7667
  ] })
7426
7668
  ] })
@@ -7430,13 +7672,13 @@ function AccountMenu({
7430
7672
  }
7431
7673
 
7432
7674
  // src/components/platform/AppSwitcher.tsx
7433
- import * as React45 from "react";
7434
- import { jsx as jsx73, jsxs as jsxs64 } from "react/jsx-runtime";
7675
+ import * as React46 from "react";
7676
+ import { jsx as jsx74, jsxs as jsxs65 } from "react/jsx-runtime";
7435
7677
  function AppSwitcher({ apps: appsProp, onNavigate, className = "" }) {
7436
7678
  const { apps: contextApps } = useSessionContext();
7437
7679
  const apps = appsProp ?? contextApps ?? [];
7438
- const [open2, setOpen] = React45.useState(false);
7439
- const anchorRef = React45.useRef(null);
7680
+ const [open2, setOpen] = React46.useState(false);
7681
+ const anchorRef = React46.useRef(null);
7440
7682
  if (!apps.length) return null;
7441
7683
  const items = apps.map((app) => ({
7442
7684
  id: app.key,
@@ -7450,8 +7692,8 @@ function AppSwitcher({ apps: appsProp, onNavigate, className = "" }) {
7450
7692
  window.location.href = app.url;
7451
7693
  }
7452
7694
  }));
7453
- return /* @__PURE__ */ jsxs64(React45.Fragment, { children: [
7454
- /* @__PURE__ */ jsx73("span", { ref: anchorRef, className: ["fd-appswitch-anchor", className].filter(Boolean).join(" "), style: { display: "inline-flex" }, children: /* @__PURE__ */ jsx73(
7695
+ return /* @__PURE__ */ jsxs65(React46.Fragment, { children: [
7696
+ /* @__PURE__ */ jsx74("span", { ref: anchorRef, className: ["fd-appswitch-anchor", className].filter(Boolean).join(" "), style: { display: "inline-flex" }, children: /* @__PURE__ */ jsx74(
7455
7697
  IconButton,
7456
7698
  {
7457
7699
  icon: "squares-four",
@@ -7461,7 +7703,7 @@ function AppSwitcher({ apps: appsProp, onNavigate, className = "" }) {
7461
7703
  onClick: () => setOpen((v) => !v)
7462
7704
  }
7463
7705
  ) }),
7464
- /* @__PURE__ */ jsx73(
7706
+ /* @__PURE__ */ jsx74(
7465
7707
  Popover,
7466
7708
  {
7467
7709
  open: open2,
@@ -7472,17 +7714,17 @@ function AppSwitcher({ apps: appsProp, onNavigate, className = "" }) {
7472
7714
  label: "All flytedesk apps",
7473
7715
  width: 240,
7474
7716
  maxHeight: 360,
7475
- children: /* @__PURE__ */ jsx73(Menu, { items, onClose: () => setOpen(false) })
7717
+ children: /* @__PURE__ */ jsx74(Menu, { items, onClose: () => setOpen(false) })
7476
7718
  }
7477
7719
  )
7478
7720
  ] });
7479
7721
  }
7480
7722
 
7481
7723
  // src/components/platform/AppearanceMenu.tsx
7482
- import * as React47 from "react";
7724
+ import * as React48 from "react";
7483
7725
 
7484
7726
  // src/kits/appearance.ts
7485
- import * as React46 from "react";
7727
+ import * as React47 from "react";
7486
7728
  var DEFAULT_STORAGE_KEY = "fd-appearance";
7487
7729
  var DEFAULT_PREFS = {
7488
7730
  theme: "system",
@@ -7577,11 +7819,11 @@ function applyPrefs(prefs, root = document.documentElement) {
7577
7819
  else root.removeAttribute("data-motion");
7578
7820
  }
7579
7821
  function useAppearancePrefs(store) {
7580
- const prefs = React46.useSyncExternalStore(store.subscribe, store.getSnapshot);
7581
- React46.useEffect(() => {
7822
+ const prefs = React47.useSyncExternalStore(store.subscribe, store.getSnapshot);
7823
+ React47.useEffect(() => {
7582
7824
  applyPrefs(prefs);
7583
7825
  }, [prefs]);
7584
- React46.useEffect(() => {
7826
+ React47.useEffect(() => {
7585
7827
  if (prefs.theme !== "system" || typeof window === "undefined" || typeof window.matchMedia !== "function") {
7586
7828
  return;
7587
7829
  }
@@ -7590,7 +7832,7 @@ function useAppearancePrefs(store) {
7590
7832
  mq.addEventListener("change", onChange);
7591
7833
  return () => mq.removeEventListener("change", onChange);
7592
7834
  }, [prefs]);
7593
- const update = React46.useCallback(
7835
+ const update = React47.useCallback(
7594
7836
  (patch) => {
7595
7837
  store.write({ ...store.getSnapshot(), ...patch });
7596
7838
  },
@@ -7600,7 +7842,7 @@ function useAppearancePrefs(store) {
7600
7842
  }
7601
7843
 
7602
7844
  // src/components/platform/AppearanceMenu.tsx
7603
- import { jsx as jsx74, jsxs as jsxs65 } from "react/jsx-runtime";
7845
+ import { jsx as jsx75, jsxs as jsxs66 } from "react/jsx-runtime";
7604
7846
  var THEME_OPTIONS = [
7605
7847
  { value: "light", label: "Light" },
7606
7848
  { value: "dark", label: "Dark" },
@@ -7613,16 +7855,16 @@ var TEXT_SCALE_OPTIONS = [
7613
7855
  { value: "xl", label: "XL" }
7614
7856
  ];
7615
7857
  function AppearanceMenu({ className = "", store: storeProp, storageKey, storage, defaults }) {
7616
- const store = React47.useMemo(
7858
+ const store = React48.useMemo(
7617
7859
  () => storeProp ?? createLocalStorageAppearanceStore({ storageKey, storage, defaults }),
7618
7860
  [storeProp, storageKey, storage, defaults]
7619
7861
  );
7620
7862
  const [prefs, update] = useAppearancePrefs(store);
7621
- const [open2, setOpen] = React47.useState(false);
7622
- const anchorRef = React47.useRef(null);
7863
+ const [open2, setOpen] = React48.useState(false);
7864
+ const anchorRef = React48.useRef(null);
7623
7865
  const patch = (p) => update(p);
7624
- return /* @__PURE__ */ jsxs65(React47.Fragment, { children: [
7625
- /* @__PURE__ */ jsx74("span", { ref: anchorRef, className: ["fd-appearance-anchor", className].filter(Boolean).join(" "), style: { display: "inline-flex" }, children: /* @__PURE__ */ jsx74(
7866
+ return /* @__PURE__ */ jsxs66(React48.Fragment, { children: [
7867
+ /* @__PURE__ */ jsx75("span", { ref: anchorRef, className: ["fd-appearance-anchor", className].filter(Boolean).join(" "), style: { display: "inline-flex" }, children: /* @__PURE__ */ jsx75(
7626
7868
  IconButton,
7627
7869
  {
7628
7870
  icon: "circle-half",
@@ -7630,7 +7872,7 @@ function AppearanceMenu({ className = "", store: storeProp, storageKey, storage,
7630
7872
  onClick: () => setOpen((v) => !v)
7631
7873
  }
7632
7874
  ) }),
7633
- /* @__PURE__ */ jsx74(
7875
+ /* @__PURE__ */ jsx75(
7634
7876
  Popover,
7635
7877
  {
7636
7878
  open: open2,
@@ -7640,10 +7882,10 @@ function AppearanceMenu({ className = "", store: storeProp, storageKey, storage,
7640
7882
  padded: true,
7641
7883
  width: 260,
7642
7884
  label: "Appearance settings",
7643
- children: /* @__PURE__ */ jsxs65("div", { className: "fd-stack", style: { display: "flex", flexDirection: "column", gap: 16 }, children: [
7644
- /* @__PURE__ */ jsxs65("div", { style: { display: "flex", flexDirection: "column", gap: 6 }, children: [
7645
- /* @__PURE__ */ jsx74("span", { className: "fd-field-label", children: "Theme" }),
7646
- /* @__PURE__ */ jsx74(
7885
+ children: /* @__PURE__ */ jsxs66("div", { className: "fd-stack", style: { display: "flex", flexDirection: "column", gap: 16 }, children: [
7886
+ /* @__PURE__ */ jsxs66("div", { style: { display: "flex", flexDirection: "column", gap: 6 }, children: [
7887
+ /* @__PURE__ */ jsx75("span", { className: "fd-field-label", children: "Theme" }),
7888
+ /* @__PURE__ */ jsx75(
7647
7889
  SegmentedControl,
7648
7890
  {
7649
7891
  options: THEME_OPTIONS,
@@ -7653,9 +7895,9 @@ function AppearanceMenu({ className = "", store: storeProp, storageKey, storage,
7653
7895
  }
7654
7896
  )
7655
7897
  ] }),
7656
- /* @__PURE__ */ jsxs65("div", { style: { display: "flex", flexDirection: "column", gap: 6 }, children: [
7657
- /* @__PURE__ */ jsx74("span", { className: "fd-field-label", children: "Text size" }),
7658
- /* @__PURE__ */ jsx74(
7898
+ /* @__PURE__ */ jsxs66("div", { style: { display: "flex", flexDirection: "column", gap: 6 }, children: [
7899
+ /* @__PURE__ */ jsx75("span", { className: "fd-field-label", children: "Text size" }),
7900
+ /* @__PURE__ */ jsx75(
7659
7901
  SegmentedControl,
7660
7902
  {
7661
7903
  options: TEXT_SCALE_OPTIONS,
@@ -7665,7 +7907,7 @@ function AppearanceMenu({ className = "", store: storeProp, storageKey, storage,
7665
7907
  }
7666
7908
  )
7667
7909
  ] }),
7668
- /* @__PURE__ */ jsx74(
7910
+ /* @__PURE__ */ jsx75(
7669
7911
  Switch,
7670
7912
  {
7671
7913
  label: "High contrast",
@@ -7674,7 +7916,7 @@ function AppearanceMenu({ className = "", store: storeProp, storageKey, storage,
7674
7916
  onChange: (e) => patch({ highContrast: e.target.checked })
7675
7917
  }
7676
7918
  ),
7677
- /* @__PURE__ */ jsx74(
7919
+ /* @__PURE__ */ jsx75(
7678
7920
  Switch,
7679
7921
  {
7680
7922
  label: "Reduce motion",
@@ -7690,14 +7932,14 @@ function AppearanceMenu({ className = "", store: storeProp, storageKey, storage,
7690
7932
  }
7691
7933
 
7692
7934
  // src/components/platform/ApiSpecBrowser.tsx
7693
- import * as React48 from "react";
7694
- import { jsx as jsx75, jsxs as jsxs66 } from "react/jsx-runtime";
7935
+ import * as React49 from "react";
7936
+ import { jsx as jsx76, jsxs as jsxs67 } from "react/jsx-runtime";
7695
7937
  var METHOD_TONE = { GET: "success", POST: "info", PATCH: "warning", PUT: "warning", DELETE: "danger" };
7696
7938
  function Json({ obj }) {
7697
- return /* @__PURE__ */ jsx75("pre", { className: "fd-json", children: JSON.stringify(obj, null, 2) });
7939
+ return /* @__PURE__ */ jsx76("pre", { className: "fd-json", children: JSON.stringify(obj, null, 2) });
7698
7940
  }
7699
7941
  function Endpoint({ s, onRequest }) {
7700
- const [tried, setTried] = React48.useState(null);
7942
+ const [tried, setTried] = React49.useState(null);
7701
7943
  const run = async () => {
7702
7944
  setTried("busy");
7703
7945
  const t0 = (window.performance || Date).now();
@@ -7708,50 +7950,50 @@ function Endpoint({ s, onRequest }) {
7708
7950
  setTried({ ms: Math.round((window.performance || Date).now() - t0), error: String(e && e.message || e) });
7709
7951
  }
7710
7952
  };
7711
- return /* @__PURE__ */ jsx75(Card, { elevation: "flat", padded: false, children: /* @__PURE__ */ jsxs66("div", { className: "fd-stack", style: { gap: 0 }, children: [
7712
- /* @__PURE__ */ jsxs66("div", { className: "fd-row", style: { gap: 10, padding: "14px 18px", flexWrap: "wrap" }, children: [
7713
- /* @__PURE__ */ jsx75(Badge, { tone: METHOD_TONE[s.method] || "neutral", children: s.method }),
7714
- /* @__PURE__ */ jsx75("code", { className: "fd-mono", style: { fontSize: 12.5, fontWeight: 600, color: "var(--text)", wordBreak: "break-all" }, children: s.path }),
7715
- s.isList ? /* @__PURE__ */ jsx75(Badge, { tone: "neutral", icon: "rows", children: "Paged list" }) : null,
7716
- /* @__PURE__ */ jsx75("span", { style: { flex: 1 } }),
7717
- /* @__PURE__ */ jsxs66("span", { className: "fd-body-sm fd-muted fd-mono", children: [
7953
+ return /* @__PURE__ */ jsx76(Card, { elevation: "flat", padded: false, children: /* @__PURE__ */ jsxs67("div", { className: "fd-stack", style: { gap: 0 }, children: [
7954
+ /* @__PURE__ */ jsxs67("div", { className: "fd-row", style: { gap: 10, padding: "14px 18px", flexWrap: "wrap" }, children: [
7955
+ /* @__PURE__ */ jsx76(Badge, { tone: METHOD_TONE[s.method] || "neutral", children: s.method }),
7956
+ /* @__PURE__ */ jsx76("code", { className: "fd-mono", style: { fontSize: 12.5, fontWeight: 600, color: "var(--text)", wordBreak: "break-all" }, children: s.path }),
7957
+ s.isList ? /* @__PURE__ */ jsx76(Badge, { tone: "neutral", icon: "rows", children: "Paged list" }) : null,
7958
+ /* @__PURE__ */ jsx76("span", { style: { flex: 1 } }),
7959
+ /* @__PURE__ */ jsxs67("span", { className: "fd-body-sm fd-muted fd-mono", children: [
7718
7960
  s.latency[0],
7719
7961
  "\u2013",
7720
7962
  s.latency[1],
7721
7963
  "ms"
7722
7964
  ] }),
7723
- /* @__PURE__ */ jsx75(Button, { size: "sm", variant: "secondary", icon: "play", loading: tried === "busy", onClick: run, children: "Try it" })
7965
+ /* @__PURE__ */ jsx76(Button, { size: "sm", variant: "secondary", icon: "play", loading: tried === "busy", onClick: run, children: "Try it" })
7724
7966
  ] }),
7725
- /* @__PURE__ */ jsxs66("div", { className: "fd-stack", style: { gap: 14, padding: "0 18px 16px" }, children: [
7726
- /* @__PURE__ */ jsxs66("div", { className: "fd-stack", style: { gap: 6 }, children: [
7727
- /* @__PURE__ */ jsx75("span", { className: "fd-body-sm", style: { fontWeight: 700 }, children: s.title }),
7728
- /* @__PURE__ */ jsx75("p", { className: "fd-body-sm fd-secondary", style: { margin: 0, textWrap: "pretty" }, children: s.purpose }),
7729
- s.usedBy && s.usedBy.length ? /* @__PURE__ */ jsx75("span", { className: "fd-row", style: { gap: 6, flexWrap: "wrap" }, children: s.usedBy.map((u) => /* @__PURE__ */ jsx75(Tag, { children: u }, u)) }) : null
7967
+ /* @__PURE__ */ jsxs67("div", { className: "fd-stack", style: { gap: 14, padding: "0 18px 16px" }, children: [
7968
+ /* @__PURE__ */ jsxs67("div", { className: "fd-stack", style: { gap: 6 }, children: [
7969
+ /* @__PURE__ */ jsx76("span", { className: "fd-body-sm", style: { fontWeight: 700 }, children: s.title }),
7970
+ /* @__PURE__ */ jsx76("p", { className: "fd-body-sm fd-secondary", style: { margin: 0, textWrap: "pretty" }, children: s.purpose }),
7971
+ s.usedBy && s.usedBy.length ? /* @__PURE__ */ jsx76("span", { className: "fd-row", style: { gap: 6, flexWrap: "wrap" }, children: s.usedBy.map((u) => /* @__PURE__ */ jsx76(Tag, { children: u }, u)) }) : null
7730
7972
  ] }),
7731
- /* @__PURE__ */ jsxs66("div", { style: { display: "grid", gridTemplateColumns: "repeat(auto-fit,minmax(280px,1fr))", gap: 12, alignItems: "start" }, children: [
7732
- s.request ? /* @__PURE__ */ jsxs66("div", { className: "fd-stack", style: { gap: 6 }, children: [
7733
- /* @__PURE__ */ jsx75("span", { className: "fd-overline fd-muted", children: "Request body" }),
7734
- /* @__PURE__ */ jsx75(Json, { obj: s.request })
7973
+ /* @__PURE__ */ jsxs67("div", { style: { display: "grid", gridTemplateColumns: "repeat(auto-fit,minmax(280px,1fr))", gap: 12, alignItems: "start" }, children: [
7974
+ s.request ? /* @__PURE__ */ jsxs67("div", { className: "fd-stack", style: { gap: 6 }, children: [
7975
+ /* @__PURE__ */ jsx76("span", { className: "fd-overline fd-muted", children: "Request body" }),
7976
+ /* @__PURE__ */ jsx76(Json, { obj: s.request })
7735
7977
  ] }) : null,
7736
- s.query ? /* @__PURE__ */ jsxs66("div", { className: "fd-stack", style: { gap: 6 }, children: [
7737
- /* @__PURE__ */ jsx75("span", { className: "fd-overline fd-muted", children: "Query" }),
7738
- /* @__PURE__ */ jsx75(Json, { obj: s.query })
7978
+ s.query ? /* @__PURE__ */ jsxs67("div", { className: "fd-stack", style: { gap: 6 }, children: [
7979
+ /* @__PURE__ */ jsx76("span", { className: "fd-overline fd-muted", children: "Query" }),
7980
+ /* @__PURE__ */ jsx76(Json, { obj: s.query })
7739
7981
  ] }) : null,
7740
- /* @__PURE__ */ jsxs66("div", { className: "fd-stack", style: { gap: 6 }, children: [
7741
- /* @__PURE__ */ jsx75("span", { className: "fd-overline fd-muted", children: "Response 200" }),
7742
- /* @__PURE__ */ jsx75(Json, { obj: s.response })
7982
+ /* @__PURE__ */ jsxs67("div", { className: "fd-stack", style: { gap: 6 }, children: [
7983
+ /* @__PURE__ */ jsx76("span", { className: "fd-overline fd-muted", children: "Response 200" }),
7984
+ /* @__PURE__ */ jsx76(Json, { obj: s.response })
7743
7985
  ] })
7744
7986
  ] }),
7745
- s.notes ? /* @__PURE__ */ jsx75(Flag, { tone: "info", statement: "Implementation note", cost: s.notes, actions: null }) : null,
7746
- tried && tried !== "busy" ? /* @__PURE__ */ jsxs66("div", { className: "fd-stack", style: { gap: 6 }, children: [
7747
- /* @__PURE__ */ jsxs66("span", { className: "fd-row", style: { gap: 8 }, children: [
7748
- /* @__PURE__ */ jsx75("span", { className: "fd-overline fd-muted", children: "Simulated response" }),
7749
- /* @__PURE__ */ jsxs66(Badge, { tone: tried.error ? "danger" : "success", icon: "timer", children: [
7987
+ s.notes ? /* @__PURE__ */ jsx76(Flag, { tone: "info", statement: "Implementation note", cost: s.notes, actions: null }) : null,
7988
+ tried && tried !== "busy" ? /* @__PURE__ */ jsxs67("div", { className: "fd-stack", style: { gap: 6 }, children: [
7989
+ /* @__PURE__ */ jsxs67("span", { className: "fd-row", style: { gap: 8 }, children: [
7990
+ /* @__PURE__ */ jsx76("span", { className: "fd-overline fd-muted", children: "Simulated response" }),
7991
+ /* @__PURE__ */ jsxs67(Badge, { tone: tried.error ? "danger" : "success", icon: "timer", children: [
7750
7992
  tried.ms,
7751
7993
  "ms"
7752
7994
  ] })
7753
7995
  ] }),
7754
- /* @__PURE__ */ jsx75(Json, { obj: tried.error ? { error: tried.error } : tried.data })
7996
+ /* @__PURE__ */ jsx76(Json, { obj: tried.error ? { error: tried.error } : tried.data })
7755
7997
  ] }) : null
7756
7998
  ] })
7757
7999
  ] }) });
@@ -7770,58 +8012,58 @@ function ApiSpecBrowser({
7770
8012
  className = "",
7771
8013
  ...rest
7772
8014
  }) {
7773
- const [q, setQ] = React48.useState("");
7774
- const [method, setMethod] = React48.useState(null);
7775
- const [mod, setMod] = React48.useState(null);
7776
- const [listOnly, setListOnly] = React48.useState(false);
8015
+ const [q, setQ] = React49.useState("");
8016
+ const [method, setMethod] = React49.useState(null);
8017
+ const [mod, setMod] = React49.useState(null);
8018
+ const [listOnly, setListOnly] = React49.useState(false);
7777
8019
  const activeModule = modules && modules.find((m) => m.id === mod);
7778
8020
  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())));
7779
8021
  const effGroups = groups && groups.length ? groups : [["All endpoints", spec.map((s) => s.id)]];
7780
8022
  const methods = [...new Set(spec.map((s) => s.method))];
7781
8023
  const listCount = spec.filter((s) => s.isList).length;
7782
- return /* @__PURE__ */ jsxs66("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 20, maxWidth: 1100 }, ...rest, children: [
7783
- /* @__PURE__ */ jsxs66("div", { className: "fd-stack", style: { gap: 10 }, children: [
7784
- kicker ? /* @__PURE__ */ jsx75("span", { className: "fd-overline fd-muted", children: kicker }) : null,
7785
- /* @__PURE__ */ jsx75("h1", { className: "fd-h1", style: { margin: 0 }, children: title }),
7786
- lede ? /* @__PURE__ */ jsx75("p", { className: "fd-body fd-secondary fd-prose", style: { margin: 0 }, children: lede }) : null
8024
+ return /* @__PURE__ */ jsxs67("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 20, maxWidth: 1100 }, ...rest, children: [
8025
+ /* @__PURE__ */ jsxs67("div", { className: "fd-stack", style: { gap: 10 }, children: [
8026
+ kicker ? /* @__PURE__ */ jsx76("span", { className: "fd-overline fd-muted", children: kicker }) : null,
8027
+ /* @__PURE__ */ jsx76("h1", { className: "fd-h1", style: { margin: 0 }, children: title }),
8028
+ lede ? /* @__PURE__ */ jsx76("p", { className: "fd-body fd-secondary fd-prose", style: { margin: 0 }, children: lede }) : null
7787
8029
  ] }),
7788
- modules && modules.length ? /* @__PURE__ */ jsxs66("div", { className: "fd-stack", style: { gap: 8 }, children: [
7789
- /* @__PURE__ */ jsx75("span", { className: "fd-overline fd-muted", children: "Filter by screen \u2014 every endpoint that screen depends on" }),
7790
- /* @__PURE__ */ jsxs66("div", { className: "fd-row", style: { gap: 8, flexWrap: "wrap" }, children: [
7791
- /* @__PURE__ */ jsxs66(Tag, { icon: "stack", selected: !mod, onClick: () => setMod(null), children: [
8030
+ modules && modules.length ? /* @__PURE__ */ jsxs67("div", { className: "fd-stack", style: { gap: 8 }, children: [
8031
+ /* @__PURE__ */ jsx76("span", { className: "fd-overline fd-muted", children: "Filter by screen \u2014 every endpoint that screen depends on" }),
8032
+ /* @__PURE__ */ jsxs67("div", { className: "fd-row", style: { gap: 8, flexWrap: "wrap" }, children: [
8033
+ /* @__PURE__ */ jsxs67(Tag, { icon: "stack", selected: !mod, onClick: () => setMod(null), children: [
7792
8034
  "All screens ",
7793
- /* @__PURE__ */ jsx75("span", { className: "fd-mono", children: spec.length })
8035
+ /* @__PURE__ */ jsx76("span", { className: "fd-mono", children: spec.length })
7794
8036
  ] }),
7795
- modules.map((m) => /* @__PURE__ */ jsxs66(Tag, { icon: m.icon, selected: mod === m.id, onClick: () => setMod(mod === m.id ? null : m.id), children: [
8037
+ modules.map((m) => /* @__PURE__ */ jsxs67(Tag, { icon: m.icon, selected: mod === m.id, onClick: () => setMod(mod === m.id ? null : m.id), children: [
7796
8038
  m.label,
7797
8039
  " ",
7798
- /* @__PURE__ */ jsx75("span", { className: "fd-mono", children: m.endpoints.length })
8040
+ /* @__PURE__ */ jsx76("span", { className: "fd-mono", children: m.endpoints.length })
7799
8041
  ] }, m.id))
7800
8042
  ] }),
7801
- activeModule ? /* @__PURE__ */ jsx75(
8043
+ activeModule ? /* @__PURE__ */ jsx76(
7802
8044
  Flag,
7803
8045
  {
7804
8046
  tone: "info",
7805
8047
  statement: activeModule.label + " calls " + activeModule.endpoints.length + " endpoints.",
7806
8048
  cost: "Integration checklist for this screen: " + activeModule.endpoints.join(", ") + ". Wire these and the screen is done.",
7807
- actions: /* @__PURE__ */ jsx75(Button, { size: "sm", variant: "ghost", icon: "x", onClick: () => setMod(null), children: "Show all screens" })
8049
+ actions: /* @__PURE__ */ jsx76(Button, { size: "sm", variant: "ghost", icon: "x", onClick: () => setMod(null), children: "Show all screens" })
7808
8050
  }
7809
8051
  ) : null
7810
8052
  ] }) : null,
7811
- sourceNote ? /* @__PURE__ */ jsx75(Flag, { tone: "info", statement: "Design-first: this page is the spec.", cost: sourceNote, actions: null }) : null,
7812
- /* @__PURE__ */ jsxs66("div", { className: "fd-row", style: { gap: 10, flexWrap: "wrap" }, children: [
7813
- /* @__PURE__ */ jsx75(Input, { icon: "magnifying-glass", placeholder: "Find an endpoint, screen, or behavior", value: q, onChange: (e) => setQ(e.target.value), style: { width: 300 } }),
7814
- methods.map((m) => /* @__PURE__ */ jsxs66(Tag, { selected: method === m, onClick: () => setMethod(method === m ? null : m), children: [
8053
+ sourceNote ? /* @__PURE__ */ jsx76(Flag, { tone: "info", statement: "Design-first: this page is the spec.", cost: sourceNote, actions: null }) : null,
8054
+ /* @__PURE__ */ jsxs67("div", { className: "fd-row", style: { gap: 10, flexWrap: "wrap" }, children: [
8055
+ /* @__PURE__ */ jsx76(Input, { icon: "magnifying-glass", placeholder: "Find an endpoint, screen, or behavior", value: q, onChange: (e) => setQ(e.target.value), style: { width: 300 } }),
8056
+ methods.map((m) => /* @__PURE__ */ jsxs67(Tag, { selected: method === m, onClick: () => setMethod(method === m ? null : m), children: [
7815
8057
  m,
7816
8058
  " ",
7817
- /* @__PURE__ */ jsx75("span", { className: "fd-mono", children: spec.filter((s) => s.method === m).length })
8059
+ /* @__PURE__ */ jsx76("span", { className: "fd-mono", children: spec.filter((s) => s.method === m).length })
7818
8060
  ] }, m)),
7819
- listCount ? /* @__PURE__ */ jsxs66(Tag, { icon: "rows", selected: listOnly, onClick: () => setListOnly(!listOnly), children: [
8061
+ listCount ? /* @__PURE__ */ jsxs67(Tag, { icon: "rows", selected: listOnly, onClick: () => setListOnly(!listOnly), children: [
7820
8062
  "Paged lists ",
7821
- /* @__PURE__ */ jsx75("span", { className: "fd-mono", children: listCount })
8063
+ /* @__PURE__ */ jsx76("span", { className: "fd-mono", children: listCount })
7822
8064
  ] }) : null,
7823
- /* @__PURE__ */ jsx75("span", { style: { flex: 1 } }),
7824
- /* @__PURE__ */ jsxs66("span", { className: "fd-body-sm fd-muted", children: [
8065
+ /* @__PURE__ */ jsx76("span", { style: { flex: 1 } }),
8066
+ /* @__PURE__ */ jsxs67("span", { className: "fd-body-sm fd-muted", children: [
7825
8067
  hits.length,
7826
8068
  " of ",
7827
8069
  spec.length,
@@ -7829,31 +8071,31 @@ function ApiSpecBrowser({
7829
8071
  listCount ? " \xB7 " + listCount + " paged" : ""
7830
8072
  ] })
7831
8073
  ] }),
7832
- hits.length === 0 ? /* @__PURE__ */ jsx75(Card, { elevation: "flat", children: /* @__PURE__ */ jsx75("p", { className: "fd-body-sm fd-muted", style: { margin: 0 }, children: "No endpoint matches those filters." }) }) : effGroups.map(([g, ids]) => {
8074
+ hits.length === 0 ? /* @__PURE__ */ jsx76(Card, { elevation: "flat", children: /* @__PURE__ */ jsx76("p", { className: "fd-body-sm fd-muted", style: { margin: 0 }, children: "No endpoint matches those filters." }) }) : effGroups.map(([g, ids]) => {
7833
8075
  const items = hits.filter((s) => ids.indexOf(s.id) >= 0);
7834
8076
  if (!items.length) return null;
7835
- return /* @__PURE__ */ jsxs66("div", { className: "fd-stack", style: { gap: 12 }, children: [
7836
- /* @__PURE__ */ jsx75("span", { className: "fd-label-lg", children: g }),
7837
- items.map((s) => /* @__PURE__ */ jsx75(Endpoint, { s, onRequest }, s.id))
8077
+ return /* @__PURE__ */ jsxs67("div", { className: "fd-stack", style: { gap: 12 }, children: [
8078
+ /* @__PURE__ */ jsx76("span", { className: "fd-label-lg", children: g }),
8079
+ items.map((s) => /* @__PURE__ */ jsx76(Endpoint, { s, onRequest }, s.id))
7838
8080
  ] }, g);
7839
8081
  }),
7840
- conventions && conventions.length ? /* @__PURE__ */ jsx75(Card, { title: "Cross-cutting conventions", elevation: "flat", children: /* @__PURE__ */ jsx75("div", { className: "fd-stack", style: { gap: 10 }, children: conventions.map(([k, v]) => /* @__PURE__ */ jsxs66("div", { className: "fd-row", style: { gap: 12, alignItems: "flex-start" }, children: [
7841
- /* @__PURE__ */ jsx75("span", { className: "fd-overline fd-muted", style: { width: 110, flex: "none", paddingTop: 2 }, children: k }),
7842
- /* @__PURE__ */ jsx75("span", { className: "fd-body-sm fd-secondary", style: { textWrap: "pretty" }, children: v })
8082
+ conventions && conventions.length ? /* @__PURE__ */ jsx76(Card, { title: "Cross-cutting conventions", elevation: "flat", children: /* @__PURE__ */ jsx76("div", { className: "fd-stack", style: { gap: 10 }, children: conventions.map(([k, v]) => /* @__PURE__ */ jsxs67("div", { className: "fd-row", style: { gap: 12, alignItems: "flex-start" }, children: [
8083
+ /* @__PURE__ */ jsx76("span", { className: "fd-overline fd-muted", style: { width: 110, flex: "none", paddingTop: 2 }, children: k }),
8084
+ /* @__PURE__ */ jsx76("span", { className: "fd-body-sm fd-secondary", style: { textWrap: "pretty" }, children: v })
7843
8085
  ] }, k)) }) }) : null,
7844
- openQuestions && openQuestions.length ? /* @__PURE__ */ jsx75(Collapsible, { icon: "list-checks", title: "Open questions before implementation", subtitle: openQuestions.length + " unresolved", children: /* @__PURE__ */ jsx75("div", { className: "fd-stack", style: { gap: 8 }, children: openQuestions.map(([id, question, why]) => /* @__PURE__ */ jsxs66("div", { className: "fd-row", style: { gap: 10, alignItems: "flex-start", padding: "8px 0", borderTop: "1px solid var(--border)" }, children: [
7845
- /* @__PURE__ */ jsx75(Badge, { tone: "danger", children: id }),
7846
- /* @__PURE__ */ jsxs66("span", { className: "fd-stack", style: { gap: 2, flex: 1 }, children: [
7847
- /* @__PURE__ */ jsx75("span", { className: "fd-body-sm", style: { fontWeight: 600 }, children: question }),
7848
- /* @__PURE__ */ jsx75("span", { className: "fd-body-sm fd-muted", children: why })
8086
+ openQuestions && openQuestions.length ? /* @__PURE__ */ jsx76(Collapsible, { icon: "list-checks", title: "Open questions before implementation", subtitle: openQuestions.length + " unresolved", children: /* @__PURE__ */ jsx76("div", { className: "fd-stack", style: { gap: 8 }, children: openQuestions.map(([id, question, why]) => /* @__PURE__ */ jsxs67("div", { className: "fd-row", style: { gap: 10, alignItems: "flex-start", padding: "8px 0", borderTop: "1px solid var(--border)" }, children: [
8087
+ /* @__PURE__ */ jsx76(Badge, { tone: "danger", children: id }),
8088
+ /* @__PURE__ */ jsxs67("span", { className: "fd-stack", style: { gap: 2, flex: 1 }, children: [
8089
+ /* @__PURE__ */ jsx76("span", { className: "fd-body-sm", style: { fontWeight: 600 }, children: question }),
8090
+ /* @__PURE__ */ jsx76("span", { className: "fd-body-sm fd-muted", children: why })
7849
8091
  ] })
7850
8092
  ] }, id)) }) }) : null
7851
8093
  ] });
7852
8094
  }
7853
8095
 
7854
8096
  // src/components/platform/ProfilePage.tsx
7855
- import * as React49 from "react";
7856
- import { jsx as jsx76, jsxs as jsxs67 } from "react/jsx-runtime";
8097
+ import * as React50 from "react";
8098
+ import { jsx as jsx77, jsxs as jsxs68 } from "react/jsx-runtime";
7857
8099
  function fieldInitialValue(field, user) {
7858
8100
  if (field.value) return field.value(user);
7859
8101
  const raw = user[field.key];
@@ -7888,21 +8130,21 @@ function ProfilePage({
7888
8130
  }) {
7889
8131
  const { user: sessionUser, roles, permissions, saveProfile: saveProfile2 } = useSessionContext();
7890
8132
  const user = userProp || sessionUser;
7891
- const initialFieldValues = React49.useMemo(() => {
8133
+ const initialFieldValues = React50.useMemo(() => {
7892
8134
  const values2 = {};
7893
8135
  for (const field of fields) values2[field.key] = fieldInitialValue(field, user);
7894
8136
  return values2;
7895
8137
  }, [user.id, fields]);
7896
- const initialNotify = React49.useMemo(() => {
8138
+ const initialNotify = React50.useMemo(() => {
7897
8139
  const values2 = {};
7898
8140
  for (const n of notifications) values2[n.key] = !!user.notify?.[n.key];
7899
8141
  return values2;
7900
8142
  }, [user.id, notifications]);
7901
- const [values, setValues] = React49.useState(initialFieldValues);
7902
- const [notify, setNotify] = React49.useState(initialNotify);
7903
- const [saving, setSaving] = React49.useState(false);
7904
- const [saved, setSaved] = React49.useState(false);
7905
- const [prevUserId, setPrevUserId] = React49.useState(user.id);
8143
+ const [values, setValues] = React50.useState(initialFieldValues);
8144
+ const [notify, setNotify] = React50.useState(initialNotify);
8145
+ const [saving, setSaving] = React50.useState(false);
8146
+ const [saved, setSaved] = React50.useState(false);
8147
+ const [prevUserId, setPrevUserId] = React50.useState(user.id);
7906
8148
  if (user.id !== prevUserId) {
7907
8149
  setPrevUserId(user.id);
7908
8150
  setValues(initialFieldValues);
@@ -7939,37 +8181,37 @@ function ProfilePage({
7939
8181
  };
7940
8182
  const displayName = fields.some((f) => f.key === "name") ? values.name || user.name : user.name;
7941
8183
  const fieldGroups = groupFields(fields);
7942
- return /* @__PURE__ */ jsxs67("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 20, maxWidth: 860 }, children: [
7943
- /* @__PURE__ */ jsxs67("div", { className: "fd-stack", style: { gap: 10 }, children: [
7944
- /* @__PURE__ */ jsx76("span", { className: "fd-overline fd-muted", children: "Account" }),
7945
- /* @__PURE__ */ jsx76("h1", { className: "fd-h1", style: { margin: 0 }, children: "Your profile" }),
7946
- /* @__PURE__ */ jsx76("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." })
8184
+ return /* @__PURE__ */ jsxs68("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 20, maxWidth: 860 }, children: [
8185
+ /* @__PURE__ */ jsxs68("div", { className: "fd-stack", style: { gap: 10 }, children: [
8186
+ /* @__PURE__ */ jsx77("span", { className: "fd-overline fd-muted", children: "Account" }),
8187
+ /* @__PURE__ */ jsx77("h1", { className: "fd-h1", style: { margin: 0 }, children: "Your profile" }),
8188
+ /* @__PURE__ */ jsx77("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." })
7947
8189
  ] }),
7948
- /* @__PURE__ */ jsx76(Card, { elevation: "flat", children: /* @__PURE__ */ jsxs67("div", { className: "fd-row", style: { gap: 16, flexWrap: "wrap", alignItems: "flex-start" }, children: [
7949
- /* @__PURE__ */ jsx76(Avatar, { name: displayName, size: "lg" }),
7950
- /* @__PURE__ */ jsxs67("div", { className: "fd-stack", style: { gap: 4, flex: 1, minWidth: 200 }, children: [
7951
- /* @__PURE__ */ jsx76("span", { className: "fd-h3", style: { margin: 0 }, children: displayName }),
7952
- /* @__PURE__ */ jsxs67("span", { className: "fd-row", style: { gap: 6, flexWrap: "wrap", paddingTop: 4 }, children: [
7953
- roles.map((r) => /* @__PURE__ */ jsx76(Badge, { tone: r.id === "owner" ? "success" : "neutral", children: r.name }, r.id)),
7954
- user.sso ? /* @__PURE__ */ jsx76(Badge, { tone: "info", icon: "shield-check", children: "SSO" }) : null
8190
+ /* @__PURE__ */ jsx77(Card, { elevation: "flat", children: /* @__PURE__ */ jsxs68("div", { className: "fd-row", style: { gap: 16, flexWrap: "wrap", alignItems: "flex-start" }, children: [
8191
+ /* @__PURE__ */ jsx77(Avatar, { name: displayName, size: "lg" }),
8192
+ /* @__PURE__ */ jsxs68("div", { className: "fd-stack", style: { gap: 4, flex: 1, minWidth: 200 }, children: [
8193
+ /* @__PURE__ */ jsx77("span", { className: "fd-h3", style: { margin: 0 }, children: displayName }),
8194
+ /* @__PURE__ */ jsxs68("span", { className: "fd-row", style: { gap: 6, flexWrap: "wrap", paddingTop: 4 }, children: [
8195
+ roles.map((r) => /* @__PURE__ */ jsx77(Badge, { tone: r.id === "owner" ? "success" : "neutral", children: r.name }, r.id)),
8196
+ user.sso ? /* @__PURE__ */ jsx77(Badge, { tone: "info", icon: "shield-check", children: "SSO" }) : null
7955
8197
  ] })
7956
8198
  ] }),
7957
- onChangePhoto ? /* @__PURE__ */ jsx76(Button, { variant: "secondary", size: "sm", icon: "image", onClick: onChangePhoto, children: "Change photo" }) : null
8199
+ onChangePhoto ? /* @__PURE__ */ jsx77(Button, { variant: "secondary", size: "sm", icon: "image", onClick: onChangePhoto, children: "Change photo" }) : null
7958
8200
  ] }) }),
7959
- fieldGroups.map(({ group, description, fields: groupFieldDefs }) => /* @__PURE__ */ jsx76(
8201
+ fieldGroups.map(({ group, description, fields: groupFieldDefs }) => /* @__PURE__ */ jsx77(
7960
8202
  Card,
7961
8203
  {
7962
- title: description ? /* @__PURE__ */ jsxs67("span", { className: "fd-stack", style: { gap: 2 }, children: [
7963
- /* @__PURE__ */ jsx76("span", { children: group }),
7964
- /* @__PURE__ */ jsx76("span", { className: "fd-body-sm fd-muted", style: { fontWeight: 400 }, children: description })
8204
+ title: description ? /* @__PURE__ */ jsxs68("span", { className: "fd-stack", style: { gap: 2 }, children: [
8205
+ /* @__PURE__ */ jsx77("span", { children: group }),
8206
+ /* @__PURE__ */ jsx77("span", { className: "fd-body-sm fd-muted", style: { fontWeight: 400 }, children: description })
7965
8207
  ] }) : group,
7966
8208
  elevation: "flat",
7967
- children: /* @__PURE__ */ jsxs67("div", { className: "fd-stack", style: { gap: 14 }, children: [
7968
- /* @__PURE__ */ jsx76("div", { style: { display: "grid", gridTemplateColumns: "repeat(auto-fit,minmax(220px,1fr))", gap: 14 }, children: groupFieldDefs.filter((f) => f.type !== "textarea").map((field) => {
8209
+ children: /* @__PURE__ */ jsxs68("div", { className: "fd-stack", style: { gap: 14 }, children: [
8210
+ /* @__PURE__ */ jsx77("div", { style: { display: "grid", gridTemplateColumns: "repeat(auto-fit,minmax(220px,1fr))", gap: 14 }, children: groupFieldDefs.filter((f) => f.type !== "textarea").map((field) => {
7969
8211
  const help = typeof field.help === "function" ? field.help(user) : field.help;
7970
8212
  const readOnly = field.readOnly || field.type === "readonly";
7971
8213
  if (field.type === "select") {
7972
- return /* @__PURE__ */ jsx76(
8214
+ return /* @__PURE__ */ jsx77(
7973
8215
  Select,
7974
8216
  {
7975
8217
  label: field.label,
@@ -7983,7 +8225,7 @@ function ProfilePage({
7983
8225
  field.key
7984
8226
  );
7985
8227
  }
7986
- return /* @__PURE__ */ jsx76(
8228
+ return /* @__PURE__ */ jsx77(
7987
8229
  Input,
7988
8230
  {
7989
8231
  label: field.label,
@@ -7999,7 +8241,7 @@ function ProfilePage({
7999
8241
  }) }),
8000
8242
  groupFieldDefs.filter((f) => f.type === "textarea").map((field) => {
8001
8243
  const help = typeof field.help === "function" ? field.help(user) : field.help;
8002
- return /* @__PURE__ */ jsx76(
8244
+ return /* @__PURE__ */ jsx77(
8003
8245
  Textarea,
8004
8246
  {
8005
8247
  label: field.label,
@@ -8019,16 +8261,16 @@ function ProfilePage({
8019
8261
  group
8020
8262
  )),
8021
8263
  extra,
8022
- notifications.length > 0 ? /* @__PURE__ */ jsx76(Card, { title: "Notifications", elevation: "flat", children: /* @__PURE__ */ jsx76("div", { className: "fd-stack", style: { gap: 14 }, children: notifications.map((n) => /* @__PURE__ */ jsx76(Switch, { checked: !!notify[n.key], onChange: () => toggleNotify(n.key), label: n.label, description: n.description }, n.key)) }) }) : null,
8023
- /* @__PURE__ */ jsxs67(
8264
+ notifications.length > 0 ? /* @__PURE__ */ jsx77(Card, { title: "Notifications", elevation: "flat", children: /* @__PURE__ */ jsx77("div", { className: "fd-stack", style: { gap: 14 }, children: notifications.map((n) => /* @__PURE__ */ jsx77(Switch, { checked: !!notify[n.key], onChange: () => toggleNotify(n.key), label: n.label, description: n.description }, n.key)) }) }) : null,
8265
+ /* @__PURE__ */ jsxs68(
8024
8266
  Card,
8025
8267
  {
8026
- title: /* @__PURE__ */ jsxs67("span", { className: "fd-stack", style: { gap: 2 }, children: [
8027
- /* @__PURE__ */ jsx76("span", { children: "Access" }),
8028
- /* @__PURE__ */ jsx76("span", { className: "fd-body-sm fd-muted", style: { fontWeight: 400 }, children: "What your roles grant you" })
8268
+ title: /* @__PURE__ */ jsxs68("span", { className: "fd-stack", style: { gap: 2 }, children: [
8269
+ /* @__PURE__ */ jsx77("span", { children: "Access" }),
8270
+ /* @__PURE__ */ jsx77("span", { className: "fd-body-sm fd-muted", style: { fontWeight: 400 }, children: "What your roles grant you" })
8029
8271
  ] }),
8030
8272
  elevation: "flat",
8031
- action: /* @__PURE__ */ jsx76(
8273
+ action: /* @__PURE__ */ jsx77(
8032
8274
  Button,
8033
8275
  {
8034
8276
  size: "sm",
@@ -8039,39 +8281,39 @@ function ProfilePage({
8039
8281
  }
8040
8282
  ),
8041
8283
  children: [
8042
- /* @__PURE__ */ jsxs67("div", { className: "fd-stack", style: { gap: 0 }, children: [
8043
- /* @__PURE__ */ jsx76(CardRow, { label: "Roles", children: roles.map((r) => r.name).join(", ") || "None" }),
8044
- /* @__PURE__ */ jsxs67(CardRow, { label: "Permissions", children: [
8284
+ /* @__PURE__ */ jsxs68("div", { className: "fd-stack", style: { gap: 0 }, children: [
8285
+ /* @__PURE__ */ jsx77(CardRow, { label: "Roles", children: roles.map((r) => r.name).join(", ") || "None" }),
8286
+ /* @__PURE__ */ jsxs68(CardRow, { label: "Permissions", children: [
8045
8287
  permissions.length,
8046
8288
  " granted"
8047
8289
  ] }),
8048
- /* @__PURE__ */ jsx76(CardRow, { label: "Member since", children: user.joined || "\u2014" })
8290
+ /* @__PURE__ */ jsx77(CardRow, { label: "Member since", children: user.joined || "\u2014" })
8049
8291
  ] }),
8050
- /* @__PURE__ */ jsx76("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." })
8292
+ /* @__PURE__ */ jsx77("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." })
8051
8293
  ]
8052
8294
  }
8053
8295
  ),
8054
- sessions ? /* @__PURE__ */ jsx76(
8296
+ sessions ? /* @__PURE__ */ jsx77(
8055
8297
  Card,
8056
8298
  {
8057
8299
  title: "Signed-in devices",
8058
8300
  elevation: "flat",
8059
- action: /* @__PURE__ */ jsx76(Button, { size: "sm", variant: "ghost", icon: "sign-out", onClick: onSignOutEverywhere, children: "Sign out everywhere" }),
8060
- children: /* @__PURE__ */ jsx76("div", { className: "fd-stack", style: { gap: 0 }, children: sessions.length === 0 ? /* @__PURE__ */ jsx76("p", { className: "fd-body-sm fd-muted", style: { margin: 0 }, children: "No other signed-in devices." }) : sessions.map((s) => /* @__PURE__ */ jsxs67("div", { className: "fd-row", style: { gap: 12, padding: "10px 0", borderTop: "1px solid var(--border)", flexWrap: "wrap" }, children: [
8061
- /* @__PURE__ */ jsx76("i", { className: "ph ph-device-mobile", style: { fontSize: 16, color: "var(--text-muted)" }, "aria-hidden": "true" }),
8062
- /* @__PURE__ */ jsxs67("span", { className: "fd-stack", style: { gap: 1, flex: 1, minWidth: 160 }, children: [
8063
- /* @__PURE__ */ jsx76("span", { className: "fd-body-sm", style: { fontWeight: 600 }, children: s.device }),
8064
- /* @__PURE__ */ jsxs67("span", { className: "fd-body-sm fd-muted", children: [
8301
+ action: /* @__PURE__ */ jsx77(Button, { size: "sm", variant: "ghost", icon: "sign-out", onClick: onSignOutEverywhere, children: "Sign out everywhere" }),
8302
+ children: /* @__PURE__ */ jsx77("div", { className: "fd-stack", style: { gap: 0 }, children: sessions.length === 0 ? /* @__PURE__ */ jsx77("p", { className: "fd-body-sm fd-muted", style: { margin: 0 }, children: "No other signed-in devices." }) : sessions.map((s) => /* @__PURE__ */ jsxs68("div", { className: "fd-row", style: { gap: 12, padding: "10px 0", borderTop: "1px solid var(--border)", flexWrap: "wrap" }, children: [
8303
+ /* @__PURE__ */ jsx77("i", { className: "ph ph-device-mobile", style: { fontSize: 16, color: "var(--text-muted)" }, "aria-hidden": "true" }),
8304
+ /* @__PURE__ */ jsxs68("span", { className: "fd-stack", style: { gap: 1, flex: 1, minWidth: 160 }, children: [
8305
+ /* @__PURE__ */ jsx77("span", { className: "fd-body-sm", style: { fontWeight: 600 }, children: s.device }),
8306
+ /* @__PURE__ */ jsxs68("span", { className: "fd-body-sm fd-muted", children: [
8065
8307
  s.where,
8066
8308
  " \xB7 ",
8067
8309
  s.when
8068
8310
  ] })
8069
8311
  ] }),
8070
- s.current ? /* @__PURE__ */ jsx76(Badge, { tone: "success", dot: true, children: "This device" }) : /* @__PURE__ */ jsx76(Button, { size: "sm", variant: "ghost", children: "Revoke" })
8312
+ s.current ? /* @__PURE__ */ jsx77(Badge, { tone: "success", dot: true, children: "This device" }) : /* @__PURE__ */ jsx77(Button, { size: "sm", variant: "ghost", children: "Revoke" })
8071
8313
  ] }, s.id)) })
8072
8314
  }
8073
8315
  ) : null,
8074
- /* @__PURE__ */ jsxs67("div", { className: "fd-row", style: {
8316
+ /* @__PURE__ */ jsxs68("div", { className: "fd-row", style: {
8075
8317
  gap: 10,
8076
8318
  flexWrap: "wrap",
8077
8319
  position: "sticky",
@@ -8082,19 +8324,19 @@ function ProfilePage({
8082
8324
  border: "1px solid var(--border)",
8083
8325
  boxShadow: "0 -4px 16px rgba(11,13,17,.06)"
8084
8326
  }, children: [
8085
- /* @__PURE__ */ jsx76("span", { className: "fd-body-sm", style: { fontWeight: 600, flex: 1 }, children: saved ? "Saved." : dirty ? "Unsaved changes" : "No pending changes" }),
8086
- /* @__PURE__ */ jsx76(Button, { size: "sm", variant: "ghost", disabled: !dirty || saving, onClick: discard, children: "Discard" }),
8087
- /* @__PURE__ */ jsx76(Button, { size: "sm", icon: "check", disabled: !dirty || !canSave, loading: saving, onClick: save, children: "Save changes" })
8327
+ /* @__PURE__ */ jsx77("span", { className: "fd-body-sm", style: { fontWeight: 600, flex: 1 }, children: saved ? "Saved." : dirty ? "Unsaved changes" : "No pending changes" }),
8328
+ /* @__PURE__ */ jsx77(Button, { size: "sm", variant: "ghost", disabled: !dirty || saving, onClick: discard, children: "Discard" }),
8329
+ /* @__PURE__ */ jsx77(Button, { size: "sm", icon: "check", disabled: !dirty || !canSave, loading: saving, onClick: save, children: "Save changes" })
8088
8330
  ] })
8089
8331
  ] });
8090
8332
  }
8091
8333
 
8092
8334
  // src/components/platform/SignInPage.tsx
8093
- import * as React50 from "react";
8094
- import { Fragment as Fragment19, jsx as jsx77, jsxs as jsxs68 } from "react/jsx-runtime";
8335
+ import * as React51 from "react";
8336
+ import { Fragment as Fragment19, jsx as jsx78, jsxs as jsxs69 } from "react/jsx-runtime";
8095
8337
  function SignInPage({ productName, onSignIn, continueAs, error }) {
8096
- const [signingIn, setSigningIn] = React50.useState(false);
8097
- const [resuming, setResuming] = React50.useState(false);
8338
+ const [signingIn, setSigningIn] = React51.useState(false);
8339
+ const [resuming, setResuming] = React51.useState(false);
8098
8340
  function handleSignIn() {
8099
8341
  setSigningIn(true);
8100
8342
  onSignIn();
@@ -8103,7 +8345,7 @@ function SignInPage({ productName, onSignIn, continueAs, error }) {
8103
8345
  setResuming(true);
8104
8346
  continueAs.onContinue().finally(() => setResuming(false));
8105
8347
  }
8106
- return /* @__PURE__ */ jsxs68(
8348
+ return /* @__PURE__ */ jsxs69(
8107
8349
  "div",
8108
8350
  {
8109
8351
  style: {
@@ -8117,7 +8359,7 @@ function SignInPage({ productName, onSignIn, continueAs, error }) {
8117
8359
  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%)"
8118
8360
  },
8119
8361
  children: [
8120
- /* @__PURE__ */ jsx77(
8362
+ /* @__PURE__ */ jsx78(
8121
8363
  "div",
8122
8364
  {
8123
8365
  "aria-hidden": true,
@@ -8130,7 +8372,7 @@ function SignInPage({ productName, onSignIn, continueAs, error }) {
8130
8372
  }
8131
8373
  }
8132
8374
  ),
8133
- /* @__PURE__ */ jsxs68(
8375
+ /* @__PURE__ */ jsxs69(
8134
8376
  "div",
8135
8377
  {
8136
8378
  style: {
@@ -8142,8 +8384,8 @@ function SignInPage({ productName, onSignIn, continueAs, error }) {
8142
8384
  alignItems: "center"
8143
8385
  },
8144
8386
  children: [
8145
- /* @__PURE__ */ jsx77("div", { style: { marginBottom: "var(--s-32)" }, "data-theme": "dark", children: /* @__PURE__ */ jsx77(FlytedeskMark, { size: "lg" }) }),
8146
- /* @__PURE__ */ jsxs68(
8387
+ /* @__PURE__ */ jsx78("div", { style: { marginBottom: "var(--s-32)" }, "data-theme": "dark", children: /* @__PURE__ */ jsx78(FlytedeskMark, { size: "lg" }) }),
8388
+ /* @__PURE__ */ jsxs69(
8147
8389
  "div",
8148
8390
  {
8149
8391
  style: {
@@ -8153,7 +8395,7 @@ function SignInPage({ productName, onSignIn, continueAs, error }) {
8153
8395
  boxShadow: "0 24px 64px -12px rgba(2, 8, 20, 0.55), 0 2px 8px rgba(2, 8, 20, 0.3)"
8154
8396
  },
8155
8397
  children: [
8156
- /* @__PURE__ */ jsx77(
8398
+ /* @__PURE__ */ jsx78(
8157
8399
  "div",
8158
8400
  {
8159
8401
  style: {
@@ -8162,7 +8404,7 @@ function SignInPage({ productName, onSignIn, continueAs, error }) {
8162
8404
  }
8163
8405
  }
8164
8406
  ),
8165
- /* @__PURE__ */ jsx77(Card, { children: /* @__PURE__ */ jsxs68(
8407
+ /* @__PURE__ */ jsx78(Card, { children: /* @__PURE__ */ jsxs69(
8166
8408
  "div",
8167
8409
  {
8168
8410
  style: {
@@ -8174,13 +8416,13 @@ function SignInPage({ productName, onSignIn, continueAs, error }) {
8174
8416
  padding: "var(--s-8) 0"
8175
8417
  },
8176
8418
  children: [
8177
- /* @__PURE__ */ jsxs68("div", { children: [
8178
- /* @__PURE__ */ jsx77("h1", { className: "fd-h3", style: { color: "var(--navy)" }, children: productName }),
8179
- /* @__PURE__ */ jsx77("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" })
8419
+ /* @__PURE__ */ jsxs69("div", { children: [
8420
+ /* @__PURE__ */ jsx78("h1", { className: "fd-h3", style: { color: "var(--navy)" }, children: productName }),
8421
+ /* @__PURE__ */ jsx78("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" })
8180
8422
  ] }),
8181
- error ? /* @__PURE__ */ jsx77("div", { role: "alert", style: { width: "100%" }, children: /* @__PURE__ */ jsx77(Banner, { tone: "danger", title: error }) }) : null,
8182
- continueAs ? /* @__PURE__ */ jsxs68(Fragment19, { children: [
8183
- /* @__PURE__ */ jsx77(
8423
+ error ? /* @__PURE__ */ jsx78("div", { role: "alert", style: { width: "100%" }, children: /* @__PURE__ */ jsx78(Banner, { tone: "danger", title: error }) }) : null,
8424
+ continueAs ? /* @__PURE__ */ jsxs69(Fragment19, { children: [
8425
+ /* @__PURE__ */ jsx78(
8184
8426
  Button,
8185
8427
  {
8186
8428
  variant: "primary",
@@ -8191,7 +8433,7 @@ function SignInPage({ productName, onSignIn, continueAs, error }) {
8191
8433
  children: resuming ? "Resuming\u2026" : `Continue as ${continueAs.name}`
8192
8434
  }
8193
8435
  ),
8194
- /* @__PURE__ */ jsx77(
8436
+ /* @__PURE__ */ jsx78(
8195
8437
  "button",
8196
8438
  {
8197
8439
  type: "button",
@@ -8208,7 +8450,7 @@ function SignInPage({ productName, onSignIn, continueAs, error }) {
8208
8450
  children: "Not you? Sign in with flytedesk ID"
8209
8451
  }
8210
8452
  )
8211
- ] }) : /* @__PURE__ */ jsx77(
8453
+ ] }) : /* @__PURE__ */ jsx78(
8212
8454
  Button,
8213
8455
  {
8214
8456
  variant: "primary",
@@ -8216,7 +8458,7 @@ function SignInPage({ productName, onSignIn, continueAs, error }) {
8216
8458
  loading: signingIn,
8217
8459
  disabled: signingIn,
8218
8460
  onClick: handleSignIn,
8219
- children: /* @__PURE__ */ jsxs68(
8461
+ children: /* @__PURE__ */ jsxs69(
8220
8462
  "span",
8221
8463
  {
8222
8464
  style: {
@@ -8228,14 +8470,14 @@ function SignInPage({ productName, onSignIn, continueAs, error }) {
8228
8470
  flexWrap: "nowrap"
8229
8471
  },
8230
8472
  children: [
8231
- /* @__PURE__ */ jsx77(GoogleGlyph, {}),
8232
- /* @__PURE__ */ jsx77("span", { children: signingIn ? "Signing in\u2026" : "Sign in with flytedesk ID" })
8473
+ /* @__PURE__ */ jsx78(GoogleGlyph, {}),
8474
+ /* @__PURE__ */ jsx78("span", { children: signingIn ? "Signing in\u2026" : "Sign in with flytedesk ID" })
8233
8475
  ]
8234
8476
  }
8235
8477
  )
8236
8478
  }
8237
8479
  ),
8238
- /* @__PURE__ */ jsx77("p", { className: "fd-body-sm fd-muted", style: { fontSize: "12px" }, children: "One account, every flytedesk app." })
8480
+ /* @__PURE__ */ jsx78("p", { className: "fd-body-sm fd-muted", style: { fontSize: "12px" }, children: "One account, every flytedesk app." })
8239
8481
  ]
8240
8482
  }
8241
8483
  ) })
@@ -8250,29 +8492,29 @@ function SignInPage({ productName, onSignIn, continueAs, error }) {
8250
8492
  );
8251
8493
  }
8252
8494
  function GoogleGlyph() {
8253
- return /* @__PURE__ */ jsxs68("svg", { width: "18", height: "18", viewBox: "0 0 18 18", "aria-hidden": true, children: [
8254
- /* @__PURE__ */ jsx77(
8495
+ return /* @__PURE__ */ jsxs69("svg", { width: "18", height: "18", viewBox: "0 0 18 18", "aria-hidden": true, children: [
8496
+ /* @__PURE__ */ jsx78(
8255
8497
  "path",
8256
8498
  {
8257
8499
  fill: "#4285F4",
8258
8500
  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"
8259
8501
  }
8260
8502
  ),
8261
- /* @__PURE__ */ jsx77(
8503
+ /* @__PURE__ */ jsx78(
8262
8504
  "path",
8263
8505
  {
8264
8506
  fill: "#34A853",
8265
8507
  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"
8266
8508
  }
8267
8509
  ),
8268
- /* @__PURE__ */ jsx77(
8510
+ /* @__PURE__ */ jsx78(
8269
8511
  "path",
8270
8512
  {
8271
8513
  fill: "#FBBC05",
8272
8514
  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"
8273
8515
  }
8274
8516
  ),
8275
- /* @__PURE__ */ jsx77(
8517
+ /* @__PURE__ */ jsx78(
8276
8518
  "path",
8277
8519
  {
8278
8520
  fill: "#EA4335",
@@ -8283,10 +8525,10 @@ function GoogleGlyph() {
8283
8525
  }
8284
8526
 
8285
8527
  // src/components/platform/RoadmapTimeline.tsx
8286
- import * as React53 from "react";
8528
+ import * as React54 from "react";
8287
8529
 
8288
8530
  // src/kits/session.ts
8289
- import * as React51 from "react";
8531
+ import * as React52 from "react";
8290
8532
  var PERMISSION_CATALOG = [
8291
8533
  { group: "Plans", items: [
8292
8534
  { key: "plan.view", label: "View plans", detail: "Read any plan in the workspace." },
@@ -9853,8 +10095,8 @@ function roadmap(overrides) {
9853
10095
  };
9854
10096
  }
9855
10097
  function useSession() {
9856
- const [s, setS] = React51.useState(getSession);
9857
- React51.useEffect(() => subscribe(setS), []);
10098
+ const [s, setS] = React52.useState(getSession);
10099
+ React52.useEffect(() => subscribe(setS), []);
9858
10100
  return s;
9859
10101
  }
9860
10102
  var SessionKit = {
@@ -9887,7 +10129,7 @@ var SessionKit = {
9887
10129
  };
9888
10130
  function DemoSessionProvider({ children }) {
9889
10131
  const session = useSession();
9890
- const value = React51.useMemo(
10132
+ const value = React52.useMemo(
9891
10133
  () => ({
9892
10134
  user: session.user,
9893
10135
  roles: session.roles,
@@ -9903,11 +10145,11 @@ function DemoSessionProvider({ children }) {
9903
10145
  }),
9904
10146
  [session]
9905
10147
  );
9906
- return React51.createElement(SessionProvider, { value }, children);
10148
+ return React52.createElement(SessionProvider, { value }, children);
9907
10149
  }
9908
10150
 
9909
10151
  // src/kits/runtime.ts
9910
- import * as React52 from "react";
10152
+ import * as React53 from "react";
9911
10153
  var WIRED_ENDPOINTS = [
9912
10154
  // Nothing yet. Every id below would come from a real service:
9913
10155
  // "plan.get", "placements.list", …
@@ -10078,8 +10320,8 @@ var RuntimeKit = {
10078
10320
  };
10079
10321
  RuntimeKit.declare(FEATURE_NEEDS);
10080
10322
  function useRuntimeMode() {
10081
- const [m, setM] = React52.useState(RuntimeKit.getMode());
10082
- React52.useEffect(() => RuntimeKit.subscribe(setM), []);
10323
+ const [m, setM] = React53.useState(RuntimeKit.getMode());
10324
+ React53.useEffect(() => RuntimeKit.subscribe(setM), []);
10083
10325
  return m;
10084
10326
  }
10085
10327
  function useFeatureStatus(key) {
@@ -10098,7 +10340,7 @@ var UseRuntimeMode = useRuntimeMode;
10098
10340
  var UseFeatureStatus = useFeatureStatus;
10099
10341
 
10100
10342
  // src/components/platform/RoadmapTimeline.tsx
10101
- import { jsx as jsx78, jsxs as jsxs69 } from "react/jsx-runtime";
10343
+ import { jsx as jsx79, jsxs as jsxs70 } from "react/jsx-runtime";
10102
10344
  var STATUS = {
10103
10345
  shipped: { tone: "success", icon: "check-circle", label: "Wired" },
10104
10346
  next: { tone: "warning", icon: "traffic-cone", label: "Not wired" },
@@ -10113,45 +10355,45 @@ function RoadmapCard({ item, byKey, onOpenFlag }) {
10113
10355
  const s = STATUS[item.status] || STATUS.planned;
10114
10356
  const deps = (item.dependsOn || []).map((k) => byKey[k]).filter(Boolean);
10115
10357
  const blocking = deps.filter((d) => !d.implemented);
10116
- return /* @__PURE__ */ jsx78(Card, { elevation: "flat", children: /* @__PURE__ */ jsxs69("div", { className: "fd-stack", style: { gap: 10 }, children: [
10117
- /* @__PURE__ */ jsxs69("div", { className: "fd-row", style: { gap: 8, flexWrap: "wrap" }, children: [
10118
- /* @__PURE__ */ jsx78("span", { className: "fd-body", style: { fontWeight: 700, flex: 1, minWidth: 140 }, children: item.label }),
10119
- /* @__PURE__ */ jsx78(Badge, { tone: "neutral", icon: PROJECT_ICON[item.project] || "squares-four", children: item.project }),
10120
- /* @__PURE__ */ jsx78(Badge, { tone: s.tone, icon: s.icon, children: s.label })
10358
+ return /* @__PURE__ */ jsx79(Card, { elevation: "flat", children: /* @__PURE__ */ jsxs70("div", { className: "fd-stack", style: { gap: 10 }, children: [
10359
+ /* @__PURE__ */ jsxs70("div", { className: "fd-row", style: { gap: 8, flexWrap: "wrap" }, children: [
10360
+ /* @__PURE__ */ jsx79("span", { className: "fd-body", style: { fontWeight: 700, flex: 1, minWidth: 140 }, children: item.label }),
10361
+ /* @__PURE__ */ jsx79(Badge, { tone: "neutral", icon: PROJECT_ICON[item.project] || "squares-four", children: item.project }),
10362
+ /* @__PURE__ */ jsx79(Badge, { tone: s.tone, icon: s.icon, children: s.label })
10121
10363
  ] }),
10122
- /* @__PURE__ */ jsx78("p", { className: "fd-body-sm fd-secondary", style: { margin: 0, textWrap: "pretty" }, children: item.description }),
10123
- item.backend ? /* @__PURE__ */ jsxs69("div", { className: "fd-row", style: { gap: 10, alignItems: "flex-start" }, children: [
10124
- /* @__PURE__ */ jsx78("span", { className: "fd-overline fd-muted", style: { width: 62, flex: "none", paddingTop: 2 }, children: "Backend" }),
10125
- /* @__PURE__ */ jsx78("span", { className: "fd-body-sm", style: { flex: 1, textWrap: "pretty" }, children: item.backend })
10364
+ /* @__PURE__ */ jsx79("p", { className: "fd-body-sm fd-secondary", style: { margin: 0, textWrap: "pretty" }, children: item.description }),
10365
+ item.backend ? /* @__PURE__ */ jsxs70("div", { className: "fd-row", style: { gap: 10, alignItems: "flex-start" }, children: [
10366
+ /* @__PURE__ */ jsx79("span", { className: "fd-overline fd-muted", style: { width: 62, flex: "none", paddingTop: 2 }, children: "Backend" }),
10367
+ /* @__PURE__ */ jsx79("span", { className: "fd-body-sm", style: { flex: 1, textWrap: "pretty" }, children: item.backend })
10126
10368
  ] }) : null,
10127
- /* @__PURE__ */ jsxs69("div", { className: "fd-row", style: { gap: 12, flexWrap: "wrap" }, children: [
10128
- item.effort ? /* @__PURE__ */ jsxs69("span", { className: "fd-body-sm fd-muted", children: [
10129
- /* @__PURE__ */ jsx78("i", { className: "ph ph-hourglass-medium" }),
10369
+ /* @__PURE__ */ jsxs70("div", { className: "fd-row", style: { gap: 12, flexWrap: "wrap" }, children: [
10370
+ item.effort ? /* @__PURE__ */ jsxs70("span", { className: "fd-body-sm fd-muted", children: [
10371
+ /* @__PURE__ */ jsx79("i", { className: "ph ph-hourglass-medium" }),
10130
10372
  " ",
10131
10373
  item.effort
10132
10374
  ] }) : null,
10133
- /* @__PURE__ */ jsxs69("span", { className: "fd-body-sm fd-muted", children: [
10134
- /* @__PURE__ */ jsx78("i", { className: "ph ph-user" }),
10375
+ /* @__PURE__ */ jsxs70("span", { className: "fd-body-sm fd-muted", children: [
10376
+ /* @__PURE__ */ jsx79("i", { className: "ph ph-user" }),
10135
10377
  " ",
10136
10378
  item.owner
10137
10379
  ] }),
10138
- item.screen ? /* @__PURE__ */ jsx78(Badge, { tone: "neutral", icon: "browser", children: "screen" }) : null,
10139
- /* @__PURE__ */ jsx78("span", { style: { flex: 1 } }),
10140
- /* @__PURE__ */ jsx78(
10380
+ item.screen ? /* @__PURE__ */ jsx79(Badge, { tone: "neutral", icon: "browser", children: "screen" }) : null,
10381
+ /* @__PURE__ */ jsx79("span", { style: { flex: 1 } }),
10382
+ /* @__PURE__ */ jsx79(
10141
10383
  "button",
10142
10384
  {
10143
10385
  type: "button",
10144
10386
  onClick: () => onOpenFlag && onOpenFlag(item.key),
10145
10387
  style: { all: "unset", cursor: "pointer", display: "inline-flex", alignItems: "center", gap: 5 },
10146
- children: /* @__PURE__ */ jsx78("code", { className: "fd-mono", style: { fontSize: 11, color: "var(--brand)" }, children: item.key })
10388
+ children: /* @__PURE__ */ jsx79("code", { className: "fd-mono", style: { fontSize: 11, color: "var(--brand)" }, children: item.key })
10147
10389
  }
10148
10390
  )
10149
10391
  ] }),
10150
- deps.length ? /* @__PURE__ */ jsxs69("div", { className: "fd-row", style: { gap: 6, flexWrap: "wrap", paddingTop: 6, borderTop: "1px solid var(--border)" }, children: [
10151
- /* @__PURE__ */ jsx78("span", { className: "fd-overline fd-muted", style: { paddingTop: 3 }, children: "After" }),
10152
- deps.map((d) => /* @__PURE__ */ jsx78(Tag, { icon: d.implemented ? "check" : "clock", children: d.label }, d.key))
10392
+ deps.length ? /* @__PURE__ */ jsxs70("div", { className: "fd-row", style: { gap: 6, flexWrap: "wrap", paddingTop: 6, borderTop: "1px solid var(--border)" }, children: [
10393
+ /* @__PURE__ */ jsx79("span", { className: "fd-overline fd-muted", style: { paddingTop: 3 }, children: "After" }),
10394
+ deps.map((d) => /* @__PURE__ */ jsx79(Tag, { icon: d.implemented ? "check" : "clock", children: d.label }, d.key))
10153
10395
  ] }) : null,
10154
- blocking.length && !item.implemented ? /* @__PURE__ */ jsxs69("span", { className: "fd-body-sm", style: { color: "var(--warn-text)" }, children: [
10396
+ blocking.length && !item.implemented ? /* @__PURE__ */ jsxs70("span", { className: "fd-body-sm", style: { color: "var(--warn-text)" }, children: [
10155
10397
  "Blocked until ",
10156
10398
  blocking.map((d) => d.label).join(" and "),
10157
10399
  " ",
@@ -10162,12 +10404,12 @@ function RoadmapCard({ item, byKey, onOpenFlag }) {
10162
10404
  }
10163
10405
  function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
10164
10406
  const session = SessionKit.useSession();
10165
- const [project, setProject] = React53.useState("");
10166
- const [q, setQ] = React53.useState("");
10167
- const scrollRef = React53.useRef(null);
10168
- const nowRef = React53.useRef(null);
10169
- const rm = React53.useMemo(() => SessionKit.roadmap({ isComplete: RuntimeKit.isComplete }), [session]);
10170
- const byKey = React53.useMemo(() => {
10407
+ const [project, setProject] = React54.useState("");
10408
+ const [q, setQ] = React54.useState("");
10409
+ const scrollRef = React54.useRef(null);
10410
+ const nowRef = React54.useRef(null);
10411
+ const rm = React54.useMemo(() => SessionKit.roadmap({ isComplete: RuntimeKit.isComplete }), [session]);
10412
+ const byKey = React54.useMemo(() => {
10171
10413
  const m = {};
10172
10414
  rm.items.forEach((i) => {
10173
10415
  m[i.key] = i;
@@ -10176,7 +10418,7 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
10176
10418
  }, [rm]);
10177
10419
  const items = rm.items.filter((i) => (!project || i.project === project) && (!q || (i.label + " " + i.description + " " + (i.backend || "") + " " + i.key).toLowerCase().includes(q.toLowerCase())));
10178
10420
  const projects = [...new Set(rm.items.map((i) => i.project))];
10179
- React53.useEffect(() => {
10421
+ React54.useEffect(() => {
10180
10422
  let raf1 = 0, raf2 = 0;
10181
10423
  const place = () => {
10182
10424
  const box = scrollRef.current, mark = nowRef.current;
@@ -10204,23 +10446,23 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
10204
10446
  }, 0);
10205
10447
  const nextPhase = items.find((i) => !i.implemented);
10206
10448
  let lastPhase = null;
10207
- return /* @__PURE__ */ jsxs69("div", { className: "fd-stack", style: { gap: 16, maxWidth: 1e3 }, children: [
10208
- /* @__PURE__ */ jsxs69("div", { className: "fd-stack", style: { gap: 10 }, children: [
10209
- /* @__PURE__ */ jsx78("span", { className: "fd-overline fd-muted", children: "Architecture" }),
10210
- /* @__PURE__ */ jsx78("h1", { className: "fd-h1", style: { margin: 0 }, children: title }),
10211
- /* @__PURE__ */ jsx78("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." })
10449
+ return /* @__PURE__ */ jsxs70("div", { className: "fd-stack", style: { gap: 16, maxWidth: 1e3 }, children: [
10450
+ /* @__PURE__ */ jsxs70("div", { className: "fd-stack", style: { gap: 10 }, children: [
10451
+ /* @__PURE__ */ jsx79("span", { className: "fd-overline fd-muted", children: "Architecture" }),
10452
+ /* @__PURE__ */ jsx79("h1", { className: "fd-h1", style: { margin: 0 }, children: title }),
10453
+ /* @__PURE__ */ jsx79("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." })
10212
10454
  ] }),
10213
- /* @__PURE__ */ jsxs69("div", { className: "fd-grid-stats is-thin", children: [
10214
- /* @__PURE__ */ jsx78(StatTile, { compact: true, label: "Wired", value: String(rm.shipped), sub: "of " + rm.items.length + " features" }),
10215
- /* @__PURE__ */ jsx78(StatTile, { compact: true, label: "Remaining", value: String(rm.remaining), sub: "backend work" }),
10216
- /* @__PURE__ */ jsx78(StatTile, { compact: true, label: "Est. effort", value: days ? days + " days" : "\u2014", sub: "sum of estimates, not calendar" }),
10217
- /* @__PURE__ */ jsx78(StatTile, { compact: true, label: "Up next", value: nextPhase ? "Phase " + nextPhase.phase : "\u2014", sub: nextPhase ? nextPhase.phaseName : "all wired" })
10455
+ /* @__PURE__ */ jsxs70("div", { className: "fd-grid-stats is-thin", children: [
10456
+ /* @__PURE__ */ jsx79(StatTile, { compact: true, label: "Wired", value: String(rm.shipped), sub: "of " + rm.items.length + " features" }),
10457
+ /* @__PURE__ */ jsx79(StatTile, { compact: true, label: "Remaining", value: String(rm.remaining), sub: "backend work" }),
10458
+ /* @__PURE__ */ jsx79(StatTile, { compact: true, label: "Est. effort", value: days ? days + " days" : "\u2014", sub: "sum of estimates, not calendar" }),
10459
+ /* @__PURE__ */ jsx79(StatTile, { compact: true, label: "Up next", value: nextPhase ? "Phase " + nextPhase.phase : "\u2014", sub: nextPhase ? nextPhase.phaseName : "all wired" })
10218
10460
  ] }),
10219
- /* @__PURE__ */ jsxs69("div", { className: "fd-row", style: { gap: 10, flexWrap: "wrap" }, children: [
10220
- /* @__PURE__ */ jsx78(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 } }),
10221
- /* @__PURE__ */ jsx78(Select, { placeholder: "All projects", value: project, onChange: (e) => setProject(e.target.value), options: projects, style: { width: 190 } }),
10222
- /* @__PURE__ */ jsx78("span", { style: { flex: 1 } }),
10223
- /* @__PURE__ */ jsx78(
10461
+ /* @__PURE__ */ jsxs70("div", { className: "fd-row", style: { gap: 10, flexWrap: "wrap" }, children: [
10462
+ /* @__PURE__ */ jsx79(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 } }),
10463
+ /* @__PURE__ */ jsx79(Select, { placeholder: "All projects", value: project, onChange: (e) => setProject(e.target.value), options: projects, style: { width: 190 } }),
10464
+ /* @__PURE__ */ jsx79("span", { style: { flex: 1 } }),
10465
+ /* @__PURE__ */ jsx79(
10224
10466
  Button,
10225
10467
  {
10226
10468
  size: "sm",
@@ -10234,7 +10476,7 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
10234
10476
  }
10235
10477
  )
10236
10478
  ] }),
10237
- /* @__PURE__ */ jsx78(
10479
+ /* @__PURE__ */ jsx79(
10238
10480
  Flag,
10239
10481
  {
10240
10482
  tone: "info",
@@ -10243,60 +10485,60 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
10243
10485
  actions: null
10244
10486
  }
10245
10487
  ),
10246
- /* @__PURE__ */ jsx78("div", { className: "fd-rm", children: /* @__PURE__ */ jsx78("div", { className: "fd-rm-scroll", ref: scrollRef, children: /* @__PURE__ */ jsxs69("div", { className: "fd-rm-track", children: [
10247
- /* @__PURE__ */ jsx78("span", { className: "fd-rm-spine", children: /* @__PURE__ */ jsx78("span", { className: "fd-rm-spine-done", style: { height: items.length ? 100 * shippedShown / items.length + "%" : "0%" } }) }),
10488
+ /* @__PURE__ */ jsx79("div", { className: "fd-rm", children: /* @__PURE__ */ jsx79("div", { className: "fd-rm-scroll", ref: scrollRef, children: /* @__PURE__ */ jsxs70("div", { className: "fd-rm-track", children: [
10489
+ /* @__PURE__ */ jsx79("span", { className: "fd-rm-spine", children: /* @__PURE__ */ jsx79("span", { className: "fd-rm-spine-done", style: { height: items.length ? 100 * shippedShown / items.length + "%" : "0%" } }) }),
10248
10490
  items.map((item, n) => {
10249
10491
  const showPhase = item.phase !== lastPhase;
10250
10492
  lastPhase = item.phase;
10251
10493
  const inPhase = items.filter((i) => i.phase === item.phase).length;
10252
10494
  const isBoundary = n === firstPending;
10253
- return /* @__PURE__ */ jsxs69(React53.Fragment, { children: [
10254
- showPhase ? /* @__PURE__ */ jsxs69("div", { className: "fd-rm-era", children: [
10255
- /* @__PURE__ */ jsxs69("span", { className: "fd-row", style: { gap: 8, flexWrap: "wrap", alignItems: "baseline" }, children: [
10256
- /* @__PURE__ */ jsx78("span", { style: { fontWeight: 700 }, children: item.phase === 0 ? "Shipped" : "Phase " + item.phase + " \u2014 " + item.phaseName }),
10257
- item.phase === 0 ? null : /* @__PURE__ */ jsxs69("span", { className: "fd-mono", style: { opacity: 0.7, fontWeight: 400 }, children: [
10495
+ return /* @__PURE__ */ jsxs70(React54.Fragment, { children: [
10496
+ showPhase ? /* @__PURE__ */ jsxs70("div", { className: "fd-rm-era", children: [
10497
+ /* @__PURE__ */ jsxs70("span", { className: "fd-row", style: { gap: 8, flexWrap: "wrap", alignItems: "baseline" }, children: [
10498
+ /* @__PURE__ */ jsx79("span", { style: { fontWeight: 700 }, children: item.phase === 0 ? "Shipped" : "Phase " + item.phase + " \u2014 " + item.phaseName }),
10499
+ item.phase === 0 ? null : /* @__PURE__ */ jsxs70("span", { className: "fd-mono", style: { opacity: 0.7, fontWeight: 400 }, children: [
10258
10500
  fmtDate(item.phaseStart),
10259
10501
  " \u2013 ",
10260
10502
  fmtDate(item.date)
10261
10503
  ] }),
10262
- /* @__PURE__ */ jsxs69("span", { style: { opacity: 0.7, fontWeight: 400 }, children: [
10504
+ /* @__PURE__ */ jsxs70("span", { style: { opacity: 0.7, fontWeight: 400 }, children: [
10263
10505
  "\xB7 ",
10264
10506
  inPhase,
10265
10507
  " feature",
10266
10508
  inPhase === 1 ? "" : "s"
10267
10509
  ] })
10268
10510
  ] }),
10269
- item.phaseWhy ? /* @__PURE__ */ jsx78("p", { className: "fd-rm-era-why", children: item.phaseWhy }) : null
10511
+ item.phaseWhy ? /* @__PURE__ */ jsx79("p", { className: "fd-rm-era-why", children: item.phaseWhy }) : null
10270
10512
  ] }) : null,
10271
- isBoundary ? /* @__PURE__ */ jsx78("div", { className: "fd-rm-now", ref: nowRef, children: /* @__PURE__ */ jsxs69("span", { className: "fd-rm-now-pill", children: [
10272
- /* @__PURE__ */ jsx78("i", { className: "ph ph-map-pin" }),
10513
+ isBoundary ? /* @__PURE__ */ jsx79("div", { className: "fd-rm-now", ref: nowRef, children: /* @__PURE__ */ jsxs70("span", { className: "fd-rm-now-pill", children: [
10514
+ /* @__PURE__ */ jsx79("i", { className: "ph ph-map-pin" }),
10273
10515
  " You are here \u2014 everything above is wired"
10274
10516
  ] }) }) : null,
10275
- /* @__PURE__ */ jsxs69("div", { className: "fd-rm-row", children: [
10276
- /* @__PURE__ */ jsx78("span", { className: "fd-rm-dot " + (item.implemented ? "is-shipped" : item.status === "next" ? "is-next" : "") }),
10277
- /* @__PURE__ */ jsxs69("div", { className: "fd-rm-date", children: [
10517
+ /* @__PURE__ */ jsxs70("div", { className: "fd-rm-row", children: [
10518
+ /* @__PURE__ */ jsx79("span", { className: "fd-rm-dot " + (item.implemented ? "is-shipped" : item.status === "next" ? "is-next" : "") }),
10519
+ /* @__PURE__ */ jsxs70("div", { className: "fd-rm-date", children: [
10278
10520
  fmtDate(item.date),
10279
- /* @__PURE__ */ jsx78("br", {}),
10280
- /* @__PURE__ */ jsx78("span", { style: { opacity: 0.75 }, children: item.implemented ? "shipped" : "phase " + item.phase })
10521
+ /* @__PURE__ */ jsx79("br", {}),
10522
+ /* @__PURE__ */ jsx79("span", { style: { opacity: 0.75 }, children: item.implemented ? "shipped" : "phase " + item.phase })
10281
10523
  ] }),
10282
- /* @__PURE__ */ jsx78(RoadmapCard, { item, byKey, onOpenFlag })
10524
+ /* @__PURE__ */ jsx79(RoadmapCard, { item, byKey, onOpenFlag })
10283
10525
  ] })
10284
10526
  ] }, item.key);
10285
10527
  }),
10286
- !items.length ? /* @__PURE__ */ jsx78("p", { className: "fd-body-sm fd-muted", children: "Nothing matches that filter." }) : null
10528
+ !items.length ? /* @__PURE__ */ jsx79("p", { className: "fd-body-sm fd-muted", children: "Nothing matches that filter." }) : null
10287
10529
  ] }) }) }),
10288
- /* @__PURE__ */ jsxs69("p", { className: "fd-body-sm fd-muted", style: { margin: 0 }, children: [
10530
+ /* @__PURE__ */ jsxs70("p", { className: "fd-body-sm fd-muted", style: { margin: 0 }, children: [
10289
10531
  "Derived from the feature-flag registry \u2014 each entry's status is its flag's ",
10290
- /* @__PURE__ */ jsx78("code", { className: "fd-mono", children: "implemented" }),
10532
+ /* @__PURE__ */ jsx79("code", { className: "fd-mono", children: "implemented" }),
10291
10533
  " field, so this page cannot drift from what the apps actually do."
10292
10534
  ] })
10293
10535
  ] });
10294
10536
  }
10295
10537
 
10296
10538
  // src/components/platform/ComingSoon.tsx
10297
- import * as React54 from "react";
10539
+ import * as React55 from "react";
10298
10540
  import { createPortal as createPortal5 } from "react-dom";
10299
- import { Fragment as Fragment21, jsx as jsx79, jsxs as jsxs70 } from "react/jsx-runtime";
10541
+ import { Fragment as Fragment21, jsx as jsx80, jsxs as jsxs71 } from "react/jsx-runtime";
10300
10542
  var BYPASS_STORE = "fd.soon.bypass.v1";
10301
10543
  function readBypassed() {
10302
10544
  try {
@@ -10312,8 +10554,8 @@ function writeBypassed(list) {
10312
10554
  }
10313
10555
  }
10314
10556
  function useBypass(key) {
10315
- const [on, setOn] = React54.useState(() => !!key && readBypassed().indexOf(key) >= 0);
10316
- React54.useEffect(() => {
10557
+ const [on, setOn] = React55.useState(() => !!key && readBypassed().indexOf(key) >= 0);
10558
+ React55.useEffect(() => {
10317
10559
  setOn(!!key && readBypassed().indexOf(key) >= 0);
10318
10560
  }, [key]);
10319
10561
  const set = (next) => {
@@ -10326,43 +10568,43 @@ function useBypass(key) {
10326
10568
  return [on, set];
10327
10569
  }
10328
10570
  function SoonCard({ label, detail, backend, eta, effort, onRoadmap, allowed, onBypass }) {
10329
- return /* @__PURE__ */ jsxs70(Fragment21, { children: [
10330
- /* @__PURE__ */ jsxs70("span", { className: "fd-soon-badge", children: [
10331
- /* @__PURE__ */ jsx79("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" }),
10571
+ return /* @__PURE__ */ jsxs71(Fragment21, { children: [
10572
+ /* @__PURE__ */ jsxs71("span", { className: "fd-soon-badge", children: [
10573
+ /* @__PURE__ */ jsx80("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" }),
10332
10574
  label
10333
10575
  ] }),
10334
- detail ? /* @__PURE__ */ jsx79("span", { className: "fd-soon-detail", children: detail }) : null,
10335
- backend ? /* @__PURE__ */ jsxs70("span", { className: "fd-soon-backend", children: [
10336
- /* @__PURE__ */ jsx79("span", { className: "fd-overline", children: "Needs" }),
10576
+ detail ? /* @__PURE__ */ jsx80("span", { className: "fd-soon-detail", children: detail }) : null,
10577
+ backend ? /* @__PURE__ */ jsxs71("span", { className: "fd-soon-backend", children: [
10578
+ /* @__PURE__ */ jsx80("span", { className: "fd-overline", children: "Needs" }),
10337
10579
  " ",
10338
10580
  backend
10339
10581
  ] }) : null,
10340
- eta || effort || onRoadmap ? /* @__PURE__ */ jsxs70("span", { className: "fd-soon-meta", children: [
10341
- eta ? /* @__PURE__ */ jsxs70("span", { children: [
10342
- /* @__PURE__ */ jsx79("i", { className: "ph ph-calendar-blank", "aria-hidden": "true" }),
10582
+ eta || effort || onRoadmap ? /* @__PURE__ */ jsxs71("span", { className: "fd-soon-meta", children: [
10583
+ eta ? /* @__PURE__ */ jsxs71("span", { children: [
10584
+ /* @__PURE__ */ jsx80("i", { className: "ph ph-calendar-blank", "aria-hidden": "true" }),
10343
10585
  " ",
10344
10586
  eta
10345
10587
  ] }) : null,
10346
- effort ? /* @__PURE__ */ jsxs70("span", { children: [
10347
- /* @__PURE__ */ jsx79("i", { className: "ph ph-hourglass-medium", "aria-hidden": "true" }),
10588
+ effort ? /* @__PURE__ */ jsxs71("span", { children: [
10589
+ /* @__PURE__ */ jsx80("i", { className: "ph ph-hourglass-medium", "aria-hidden": "true" }),
10348
10590
  " ",
10349
10591
  effort
10350
10592
  ] }) : null,
10351
- onRoadmap ? /* @__PURE__ */ jsxs70("button", { type: "button", className: "fd-soon-link", onClick: onRoadmap, children: [
10593
+ onRoadmap ? /* @__PURE__ */ jsxs71("button", { type: "button", className: "fd-soon-link", onClick: onRoadmap, children: [
10352
10594
  "See the roadmap ",
10353
- /* @__PURE__ */ jsx79("i", { className: "ph ph-arrow-right", "aria-hidden": "true" })
10595
+ /* @__PURE__ */ jsx80("i", { className: "ph ph-arrow-right", "aria-hidden": "true" })
10354
10596
  ] }) : null
10355
10597
  ] }) : null,
10356
- allowed ? /* @__PURE__ */ jsxs70("button", { type: "button", className: "fd-soon-view", onClick: onBypass, children: [
10357
- /* @__PURE__ */ jsx79("i", { className: "ph ph-eye", "aria-hidden": "true" }),
10598
+ allowed ? /* @__PURE__ */ jsxs71("button", { type: "button", className: "fd-soon-view", onClick: onBypass, children: [
10599
+ /* @__PURE__ */ jsx80("i", { className: "ph ph-eye", "aria-hidden": "true" }),
10358
10600
  " View and use it anyway"
10359
10601
  ] }) : null
10360
10602
  ] });
10361
10603
  }
10362
10604
  function useHoverCard(open2) {
10363
- const anchor = React54.useRef(null);
10364
- const [pos, setPos] = React54.useState(null);
10365
- React54.useLayoutEffect(() => {
10605
+ const anchor = React55.useRef(null);
10606
+ const [pos, setPos] = React55.useState(null);
10607
+ React55.useLayoutEffect(() => {
10366
10608
  if (!open2 || !anchor.current) {
10367
10609
  setPos(null);
10368
10610
  return;
@@ -10414,9 +10656,9 @@ function ComingSoon({
10414
10656
  const tip = [label, detail, backend ? "Needs " + backend : null, eta ? "ETA " + eta : null, effort].filter(Boolean).join(" \xB7 ");
10415
10657
  if (inline) {
10416
10658
  if (allowed && bypassed) {
10417
- return /* @__PURE__ */ jsxs70("span", { className: ["fd-soon-inline-on", className].filter(Boolean).join(" "), ...rest, children: [
10659
+ return /* @__PURE__ */ jsxs71("span", { className: ["fd-soon-inline-on", className].filter(Boolean).join(" "), ...rest, children: [
10418
10660
  children,
10419
- /* @__PURE__ */ jsx79(
10661
+ /* @__PURE__ */ jsx80(
10420
10662
  "button",
10421
10663
  {
10422
10664
  type: "button",
@@ -10424,12 +10666,12 @@ function ComingSoon({
10424
10666
  title: "Unwired \u2014 writes go to the simulated backend. " + tip + " Click to re-blur.",
10425
10667
  onClick: () => setBypassed(false),
10426
10668
  "aria-label": "Re-blur this unwired feature",
10427
- children: /* @__PURE__ */ jsx79("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" })
10669
+ children: /* @__PURE__ */ jsx80("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" })
10428
10670
  }
10429
10671
  )
10430
10672
  ] });
10431
10673
  }
10432
- return /* @__PURE__ */ jsx79(
10674
+ return /* @__PURE__ */ jsx80(
10433
10675
  InlineSoon,
10434
10676
  {
10435
10677
  label,
@@ -10449,20 +10691,20 @@ function ComingSoon({
10449
10691
  );
10450
10692
  }
10451
10693
  if (allowed && bypassed) {
10452
- return /* @__PURE__ */ jsxs70("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 14 }, ...rest, children: [
10453
- /* @__PURE__ */ jsxs70("div", { className: "fd-soon-bar", role: "status", children: [
10454
- /* @__PURE__ */ jsxs70("span", { className: "fd-soon-badge", children: [
10455
- /* @__PURE__ */ jsx79("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" }),
10694
+ return /* @__PURE__ */ jsxs71("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 14 }, ...rest, children: [
10695
+ /* @__PURE__ */ jsxs71("div", { className: "fd-soon-bar", role: "status", children: [
10696
+ /* @__PURE__ */ jsxs71("span", { className: "fd-soon-badge", children: [
10697
+ /* @__PURE__ */ jsx80("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" }),
10456
10698
  "Unwired feature \u2014 you are using it anyway"
10457
10699
  ] }),
10458
- /* @__PURE__ */ jsx79("span", { className: "fd-soon-bar-detail", children: "Every action here writes to the simulated backend, so nothing you do persists beyond this session." }),
10459
- /* @__PURE__ */ jsxs70("span", { className: "fd-soon-bar-actions", children: [
10460
- onRoadmap ? /* @__PURE__ */ jsxs70("button", { type: "button", className: "fd-soon-link", onClick: onRoadmap, children: [
10700
+ /* @__PURE__ */ jsx80("span", { className: "fd-soon-bar-detail", children: "Every action here writes to the simulated backend, so nothing you do persists beyond this session." }),
10701
+ /* @__PURE__ */ jsxs71("span", { className: "fd-soon-bar-actions", children: [
10702
+ onRoadmap ? /* @__PURE__ */ jsxs71("button", { type: "button", className: "fd-soon-link", onClick: onRoadmap, children: [
10461
10703
  "Roadmap ",
10462
- /* @__PURE__ */ jsx79("i", { className: "ph ph-arrow-right", "aria-hidden": "true" })
10704
+ /* @__PURE__ */ jsx80("i", { className: "ph ph-arrow-right", "aria-hidden": "true" })
10463
10705
  ] }) : null,
10464
- /* @__PURE__ */ jsxs70("button", { type: "button", className: "fd-soon-link", onClick: () => setBypassed(false), children: [
10465
- /* @__PURE__ */ jsx79("i", { className: "ph ph-eye-slash", "aria-hidden": "true" }),
10706
+ /* @__PURE__ */ jsxs71("button", { type: "button", className: "fd-soon-link", onClick: () => setBypassed(false), children: [
10707
+ /* @__PURE__ */ jsx80("i", { className: "ph ph-eye-slash", "aria-hidden": "true" }),
10466
10708
  " Re-blur"
10467
10709
  ] })
10468
10710
  ] })
@@ -10470,10 +10712,10 @@ function ComingSoon({
10470
10712
  children
10471
10713
  ] });
10472
10714
  }
10473
- return /* @__PURE__ */ jsxs70("div", { className: ["fd-soon", className].filter(Boolean).join(" "), style: minHeight ? { minHeight } : void 0, ...rest, children: [
10474
- /* @__PURE__ */ jsx79("div", { className: "fd-soon-under", style: { filter: "blur(" + blur + "px) saturate(.62)" }, ...{ inert: "" }, "aria-hidden": "true", children }),
10475
- /* @__PURE__ */ jsx79("div", { className: "fd-soon-veil" }),
10476
- /* @__PURE__ */ jsx79("div", { className: "fd-soon-note", role: "note", children: /* @__PURE__ */ jsx79(
10715
+ return /* @__PURE__ */ jsxs71("div", { className: ["fd-soon", className].filter(Boolean).join(" "), style: minHeight ? { minHeight } : void 0, ...rest, children: [
10716
+ /* @__PURE__ */ jsx80("div", { className: "fd-soon-under", style: { filter: "blur(" + blur + "px) saturate(.62)" }, ...{ inert: "" }, "aria-hidden": "true", children }),
10717
+ /* @__PURE__ */ jsx80("div", { className: "fd-soon-veil" }),
10718
+ /* @__PURE__ */ jsx80("div", { className: "fd-soon-note", role: "note", children: /* @__PURE__ */ jsx80(
10477
10719
  SoonCard,
10478
10720
  {
10479
10721
  label,
@@ -10489,10 +10731,12 @@ function ComingSoon({
10489
10731
  ] });
10490
10732
  }
10491
10733
  function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, onBypass, blur, tip, className, rest, children }) {
10492
- const [open2, setOpen] = React54.useState(false);
10734
+ const [open2, setOpen] = React55.useState(false);
10493
10735
  const [anchor, pos] = useHoverCard(open2);
10494
- const zIndex = useOverlayLayer(open2);
10495
- const close2 = React54.useRef(null);
10736
+ const hoverCardRef = React55.useRef(null);
10737
+ const hoverLayer = useStackedLayer({ active: open2, containerRef: hoverCardRef, returnFocus: false });
10738
+ const zIndex = useLayerZIndex(hoverLayer);
10739
+ const close2 = React55.useRef(null);
10496
10740
  const show = () => {
10497
10741
  if (close2.current) {
10498
10742
  clearTimeout(close2.current);
@@ -10508,10 +10752,10 @@ function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, o
10508
10752
  setOpen(false);
10509
10753
  }, 140);
10510
10754
  };
10511
- React54.useEffect(() => () => {
10755
+ React55.useEffect(() => () => {
10512
10756
  if (close2.current) clearTimeout(close2.current);
10513
10757
  }, []);
10514
- return /* @__PURE__ */ jsxs70(
10758
+ return /* @__PURE__ */ jsxs71(
10515
10759
  "span",
10516
10760
  {
10517
10761
  ref: anchor,
@@ -10522,8 +10766,8 @@ function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, o
10522
10766
  onBlur: hide,
10523
10767
  ...rest,
10524
10768
  children: [
10525
- /* @__PURE__ */ jsx79("span", { className: "fd-soon-under", style: { filter: "blur(" + Math.min(blur, 1.1) + "px) saturate(.66)" }, ...{ inert: "" }, "aria-hidden": "true", children }),
10526
- /* @__PURE__ */ jsx79(
10769
+ /* @__PURE__ */ jsx80("span", { className: "fd-soon-under", style: { filter: "blur(" + Math.min(blur, 1.1) + "px) saturate(.66)" }, ...{ inert: "" }, "aria-hidden": "true", children }),
10770
+ /* @__PURE__ */ jsx80(
10527
10771
  "button",
10528
10772
  {
10529
10773
  type: "button",
@@ -10534,19 +10778,20 @@ function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, o
10534
10778
  onFocus: show,
10535
10779
  onBlur: hide,
10536
10780
  onClick: () => open2 ? setOpen(false) : show(),
10537
- children: /* @__PURE__ */ jsx79("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" })
10781
+ children: /* @__PURE__ */ jsx80("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" })
10538
10782
  }
10539
10783
  ),
10540
10784
  open2 && pos ? createPortal5(
10541
- /* @__PURE__ */ jsx79(LayerProvider, { zIndex, children: /* @__PURE__ */ jsx79(
10785
+ /* @__PURE__ */ jsx80(
10542
10786
  "div",
10543
10787
  {
10788
+ ref: hoverCardRef,
10544
10789
  className: "fd-soon-note fd-soon-hovercard",
10545
10790
  role: "tooltip",
10546
10791
  style: { position: "fixed", left: pos.left, top: pos.top, bottom: pos.bottom, width: pos.width, zIndex },
10547
10792
  onMouseEnter: show,
10548
10793
  onMouseLeave: hide,
10549
- children: /* @__PURE__ */ jsx79(
10794
+ children: /* @__PURE__ */ jsx80(
10550
10795
  SoonCard,
10551
10796
  {
10552
10797
  label,
@@ -10560,7 +10805,7 @@ function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, o
10560
10805
  }
10561
10806
  )
10562
10807
  }
10563
- ) }),
10808
+ ),
10564
10809
  document.body
10565
10810
  ) : null
10566
10811
  ]
@@ -10576,10 +10821,10 @@ function formatEta(iso2) {
10576
10821
  var FormatEta = formatEta;
10577
10822
 
10578
10823
  // src/components/platform/Gate.tsx
10579
- import { jsx as jsx80, jsxs as jsxs71 } from "react/jsx-runtime";
10824
+ import { jsx as jsx81, jsxs as jsxs72 } from "react/jsx-runtime";
10580
10825
  function PermissionDenied({ permission, title, detail, compact: compact3 = false, className = "", ...rest }) {
10581
10826
  const need = Array.isArray(permission) ? permission : [permission].filter(Boolean);
10582
- return /* @__PURE__ */ jsxs71(
10827
+ return /* @__PURE__ */ jsxs72(
10583
10828
  "div",
10584
10829
  {
10585
10830
  className: ["fd-stack", className].filter(Boolean).join(" "),
@@ -10595,14 +10840,14 @@ function PermissionDenied({ permission, title, detail, compact: compact3 = false
10595
10840
  },
10596
10841
  ...rest,
10597
10842
  children: [
10598
- /* @__PURE__ */ jsxs71("span", { className: "fd-row", style: { gap: 8 }, children: [
10599
- /* @__PURE__ */ jsx80("i", { className: "ph ph-lock-simple", style: { fontSize: 16, color: "var(--text-muted)" }, "aria-hidden": "true" }),
10600
- /* @__PURE__ */ jsx80("span", { className: compact3 ? "fd-label-lg" : "fd-h3", children: title || "You do not have access to this" })
10843
+ /* @__PURE__ */ jsxs72("span", { className: "fd-row", style: { gap: 8 }, children: [
10844
+ /* @__PURE__ */ jsx81("i", { className: "ph ph-lock-simple", style: { fontSize: 16, color: "var(--text-muted)" }, "aria-hidden": "true" }),
10845
+ /* @__PURE__ */ jsx81("span", { className: compact3 ? "fd-label-lg" : "fd-h3", children: title || "You do not have access to this" })
10601
10846
  ] }),
10602
- /* @__PURE__ */ jsx80("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." }),
10603
- need.length ? /* @__PURE__ */ jsxs71("span", { className: "fd-row", style: { gap: 6, flexWrap: "wrap" }, children: [
10604
- /* @__PURE__ */ jsx80("span", { className: "fd-overline fd-muted", children: "Requires" }),
10605
- need.map((p) => /* @__PURE__ */ jsx80("code", { className: "fd-mono", style: {
10847
+ /* @__PURE__ */ jsx81("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." }),
10848
+ need.length ? /* @__PURE__ */ jsxs72("span", { className: "fd-row", style: { gap: 6, flexWrap: "wrap" }, children: [
10849
+ /* @__PURE__ */ jsx81("span", { className: "fd-overline fd-muted", children: "Requires" }),
10850
+ need.map((p) => /* @__PURE__ */ jsx81("code", { className: "fd-mono", style: {
10606
10851
  fontSize: 11.5,
10607
10852
  padding: "2px 7px",
10608
10853
  borderRadius: 5,
@@ -10615,7 +10860,7 @@ function PermissionDenied({ permission, title, detail, compact: compact3 = false
10615
10860
  );
10616
10861
  }
10617
10862
  function GatePending({ compact: compact3 = false, className = "" }) {
10618
- return /* @__PURE__ */ jsxs71(
10863
+ return /* @__PURE__ */ jsxs72(
10619
10864
  "div",
10620
10865
  {
10621
10866
  className: ["fd-stack", className].filter(Boolean).join(" "),
@@ -10631,11 +10876,11 @@ function GatePending({ compact: compact3 = false, className = "" }) {
10631
10876
  textAlign: "left"
10632
10877
  },
10633
10878
  children: [
10634
- /* @__PURE__ */ jsxs71("span", { className: "fd-row", style: { gap: 8 }, children: [
10635
- /* @__PURE__ */ jsx80("i", { className: "ph ph-arrows-clockwise", style: { fontSize: 16, color: "var(--text-muted)" }, "aria-hidden": "true" }),
10636
- /* @__PURE__ */ jsx80("span", { className: compact3 ? "fd-label-lg" : "fd-h3", children: "Reconnecting\u2026" })
10879
+ /* @__PURE__ */ jsxs72("span", { className: "fd-row", style: { gap: 8 }, children: [
10880
+ /* @__PURE__ */ jsx81("i", { className: "ph ph-arrows-clockwise", style: { fontSize: 16, color: "var(--text-muted)" }, "aria-hidden": "true" }),
10881
+ /* @__PURE__ */ jsx81("span", { className: compact3 ? "fd-label-lg" : "fd-h3", children: "Reconnecting\u2026" })
10637
10882
  ] }),
10638
- /* @__PURE__ */ jsx80("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
+ /* @__PURE__ */ jsx81("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." })
10639
10884
  ]
10640
10885
  }
10641
10886
  );
@@ -10645,7 +10890,7 @@ function Gate({ perm, anyOf, role, silent = false, fallback, pendingFallback, co
10645
10890
  if (pending) {
10646
10891
  if (pendingFallback !== void 0) return pendingFallback;
10647
10892
  if (silent) return null;
10648
- return /* @__PURE__ */ jsx80(GatePending, { compact: compact3 });
10893
+ return /* @__PURE__ */ jsx81(GatePending, { compact: compact3 });
10649
10894
  }
10650
10895
  let ok = true;
10651
10896
  if (perm) ok = ok && can2(perm);
@@ -10654,7 +10899,7 @@ function Gate({ perm, anyOf, role, silent = false, fallback, pendingFallback, co
10654
10899
  if (ok) return children;
10655
10900
  if (fallback !== void 0) return fallback;
10656
10901
  if (silent) return null;
10657
- return /* @__PURE__ */ jsx80(PermissionDenied, { permission: perm || anyOf, compact: compact3 });
10902
+ return /* @__PURE__ */ jsx81(PermissionDenied, { permission: perm || anyOf, compact: compact3 });
10658
10903
  }
10659
10904
  function FeatureGate({
10660
10905
  flag,
@@ -10677,7 +10922,7 @@ function FeatureGate({
10677
10922
  const f = SessionKit.findFlag(flag) || {};
10678
10923
  const missing = rt.missing || [];
10679
10924
  const canBypass = pending ? false : bypassPerm === null ? false : !bypassPerm || can2(bypassPerm);
10680
- return /* @__PURE__ */ jsx80(
10925
+ return /* @__PURE__ */ jsx81(
10681
10926
  ComingSoon,
10682
10927
  {
10683
10928
  label: label || (variant === "inline" ? f.label || "Not wired yet" : "Designed \u2014 backend not wired yet"),
@@ -10698,22 +10943,22 @@ function FeatureGate({
10698
10943
  function PermissionHint({ perm, children }) {
10699
10944
  const { can: can2, pending } = useSessionContext();
10700
10945
  if (pending) {
10701
- return /* @__PURE__ */ jsx80("span", { title: "Access can't be verified right now", style: { display: "inline-flex", opacity: 0.45, cursor: "not-allowed" }, "aria-disabled": "true", children: /* @__PURE__ */ jsx80("span", { style: { pointerEvents: "none" }, children }) });
10946
+ return /* @__PURE__ */ jsx81("span", { title: "Access can't be verified right now", style: { display: "inline-flex", opacity: 0.45, cursor: "not-allowed" }, "aria-disabled": "true", children: /* @__PURE__ */ jsx81("span", { style: { pointerEvents: "none" }, children }) });
10702
10947
  }
10703
10948
  if (can2(perm)) return children;
10704
- return /* @__PURE__ */ jsx80(
10949
+ return /* @__PURE__ */ jsx81(
10705
10950
  "span",
10706
10951
  {
10707
10952
  title: "Requires " + (Array.isArray(perm) ? perm.join(", ") : perm),
10708
10953
  style: { display: "inline-flex", opacity: 0.45, cursor: "not-allowed" },
10709
10954
  "aria-disabled": "true",
10710
- children: /* @__PURE__ */ jsx80("span", { style: { pointerEvents: "none" }, children })
10955
+ children: /* @__PURE__ */ jsx81("span", { style: { pointerEvents: "none" }, children })
10711
10956
  }
10712
10957
  );
10713
10958
  }
10714
10959
 
10715
10960
  // src/components/platform/ModeSwitch.tsx
10716
- import { Fragment as Fragment22, jsx as jsx81, jsxs as jsxs72 } from "react/jsx-runtime";
10961
+ import { Fragment as Fragment22, jsx as jsx82, jsxs as jsxs73 } from "react/jsx-runtime";
10717
10962
  function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog, onOpenSpec, summary }) {
10718
10963
  const mode2 = useRuntimeMode();
10719
10964
  const panel = useInlinePanel();
@@ -10725,8 +10970,8 @@ function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog
10725
10970
  RuntimeKit.setMode(next);
10726
10971
  setOpen(false);
10727
10972
  };
10728
- return /* @__PURE__ */ jsxs72("span", { style: { position: "relative", display: "inline-flex" }, ref, children: [
10729
- /* @__PURE__ */ jsxs72(
10973
+ return /* @__PURE__ */ jsxs73("span", { style: { position: "relative", display: "inline-flex" }, ref, children: [
10974
+ /* @__PURE__ */ jsxs73(
10730
10975
  "button",
10731
10976
  {
10732
10977
  type: "button",
@@ -10736,29 +10981,29 @@ function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog
10736
10981
  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.",
10737
10982
  className: "fd-mode-btn" + (test ? " is-test" : "") + (open2 ? " is-open" : ""),
10738
10983
  children: [
10739
- /* @__PURE__ */ jsx81("i", { className: "ph " + (test ? "ph-flask" : "ph-lightning"), style: { fontSize: 17 } }),
10740
- test && requestCount ? /* @__PURE__ */ jsx81("span", { className: "fd-mono fd-mode-count", children: requestCount > 99 ? "99+" : requestCount }, requestCount) : null
10984
+ /* @__PURE__ */ jsx82("i", { className: "ph " + (test ? "ph-flask" : "ph-lightning"), style: { fontSize: 17 } }),
10985
+ test && requestCount ? /* @__PURE__ */ jsx82("span", { className: "fd-mono fd-mode-count", children: requestCount > 99 ? "99+" : requestCount }, requestCount) : null
10741
10986
  ]
10742
10987
  }
10743
10988
  ),
10744
- open2 ? /* @__PURE__ */ jsx81(InlinePanelLayers, { panel, children: /* @__PURE__ */ jsxs72("span", { className: "fd-view-enter fd-mode-pop", style: { zIndex }, children: [
10745
- /* @__PURE__ */ jsxs72("span", { className: "fd-row", style: { gap: 10, padding: "12px 14px", borderBottom: "1px solid var(--border)" }, children: [
10746
- /* @__PURE__ */ jsxs72("span", { className: "fd-badge " + (test ? "fd-badge-warning" : "fd-badge-neutral"), children: [
10747
- /* @__PURE__ */ jsx81("i", { className: "ph " + (test ? "ph-flask" : "ph-lightning"), "aria-hidden": "true" }),
10989
+ open2 ? /* @__PURE__ */ jsx82(InlinePanelLayers, { panel, children: /* @__PURE__ */ jsxs73("span", { className: "fd-view-enter fd-mode-pop", style: { zIndex }, children: [
10990
+ /* @__PURE__ */ jsxs73("span", { className: "fd-row", style: { gap: 10, padding: "12px 14px", borderBottom: "1px solid var(--border)" }, children: [
10991
+ /* @__PURE__ */ jsxs73("span", { className: "fd-badge " + (test ? "fd-badge-warning" : "fd-badge-neutral"), children: [
10992
+ /* @__PURE__ */ jsx82("i", { className: "ph " + (test ? "ph-flask" : "ph-lightning"), "aria-hidden": "true" }),
10748
10993
  test ? "Test mode" : "Live mode"
10749
10994
  ] }),
10750
- test ? /* @__PURE__ */ jsxs72("span", { className: "fd-body-sm fd-muted fd-mono", children: [
10995
+ test ? /* @__PURE__ */ jsxs73("span", { className: "fd-body-sm fd-muted fd-mono", children: [
10751
10996
  requestCount,
10752
10997
  " simulated request",
10753
10998
  requestCount === 1 ? "" : "s"
10754
10999
  ] }) : null,
10755
- /* @__PURE__ */ jsx81("span", { style: { flex: 1 } }),
10756
- test && onClearLog ? /* @__PURE__ */ jsx81("button", { type: "button", className: "fd-soon-link", onClick: onClearLog, children: "Clear" }) : null
11000
+ /* @__PURE__ */ jsx82("span", { style: { flex: 1 } }),
11001
+ test && onClearLog ? /* @__PURE__ */ jsx82("button", { type: "button", className: "fd-soon-link", onClick: onClearLog, children: "Clear" }) : null
10757
11002
  ] }),
10758
- /* @__PURE__ */ jsxs72("span", { style: { display: "block", padding: "12px 14px", borderBottom: "1px solid var(--border)" }, children: [
10759
- /* @__PURE__ */ jsx81("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." }),
10760
- /* @__PURE__ */ jsxs72("span", { className: "fd-row", style: { gap: 8, marginTop: 10, flexWrap: "wrap" }, children: [
10761
- /* @__PURE__ */ jsxs72("span", { className: "fd-body-sm fd-muted fd-mono", children: [
11003
+ /* @__PURE__ */ jsxs73("span", { style: { display: "block", padding: "12px 14px", borderBottom: "1px solid var(--border)" }, children: [
11004
+ /* @__PURE__ */ jsx82("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." }),
11005
+ /* @__PURE__ */ jsxs73("span", { className: "fd-row", style: { gap: 8, marginTop: 10, flexWrap: "wrap" }, children: [
11006
+ /* @__PURE__ */ jsxs73("span", { className: "fd-body-sm fd-muted fd-mono", children: [
10762
11007
  s.endpointsWired,
10763
11008
  " endpoint",
10764
11009
  s.endpointsWired === 1 ? "" : "s",
@@ -10768,58 +11013,58 @@ function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog
10768
11013
  s.total,
10769
11014
  " features complete"
10770
11015
  ] }),
10771
- onOpenSpec ? /* @__PURE__ */ jsxs72(Fragment22, { children: [
10772
- /* @__PURE__ */ jsx81("span", { style: { flex: 1 } }),
10773
- /* @__PURE__ */ jsxs72("button", { type: "button", className: "fd-soon-link", onClick: () => {
11016
+ onOpenSpec ? /* @__PURE__ */ jsxs73(Fragment22, { children: [
11017
+ /* @__PURE__ */ jsx82("span", { style: { flex: 1 } }),
11018
+ /* @__PURE__ */ jsxs73("button", { type: "button", className: "fd-soon-link", onClick: () => {
10774
11019
  setOpen(false);
10775
11020
  onOpenSpec();
10776
11021
  }, children: [
10777
11022
  "API spec ",
10778
- /* @__PURE__ */ jsx81("i", { className: "ph ph-arrow-right", "aria-hidden": "true" })
11023
+ /* @__PURE__ */ jsx82("i", { className: "ph ph-arrow-right", "aria-hidden": "true" })
10779
11024
  ] })
10780
11025
  ] }) : null
10781
11026
  ] })
10782
11027
  ] }),
10783
- /* @__PURE__ */ jsxs72("span", { className: "fd-mode-choice", children: [
10784
- /* @__PURE__ */ jsxs72("button", { type: "button", className: "fd-mode-opt" + (!test ? " is-on" : ""), onClick: () => go("live"), children: [
10785
- /* @__PURE__ */ jsx81("i", { className: "ph ph-lightning", "aria-hidden": "true" }),
10786
- /* @__PURE__ */ jsxs72("span", { className: "fd-mode-opt-text", children: [
10787
- /* @__PURE__ */ jsx81("span", { className: "fd-mode-opt-title", children: "Live mode" }),
10788
- /* @__PURE__ */ jsx81("span", { className: "fd-mode-opt-desc", children: "Incomplete features under construction" })
11028
+ /* @__PURE__ */ jsxs73("span", { className: "fd-mode-choice", children: [
11029
+ /* @__PURE__ */ jsxs73("button", { type: "button", className: "fd-mode-opt" + (!test ? " is-on" : ""), onClick: () => go("live"), children: [
11030
+ /* @__PURE__ */ jsx82("i", { className: "ph ph-lightning", "aria-hidden": "true" }),
11031
+ /* @__PURE__ */ jsxs73("span", { className: "fd-mode-opt-text", children: [
11032
+ /* @__PURE__ */ jsx82("span", { className: "fd-mode-opt-title", children: "Live mode" }),
11033
+ /* @__PURE__ */ jsx82("span", { className: "fd-mode-opt-desc", children: "Incomplete features under construction" })
10789
11034
  ] }),
10790
- !test ? /* @__PURE__ */ jsx81("i", { className: "ph ph-check", "aria-hidden": "true" }) : null
11035
+ !test ? /* @__PURE__ */ jsx82("i", { className: "ph ph-check", "aria-hidden": "true" }) : null
10791
11036
  ] }),
10792
- /* @__PURE__ */ jsxs72("button", { type: "button", className: "fd-mode-opt" + (test ? " is-on" : ""), onClick: () => go("test"), children: [
10793
- /* @__PURE__ */ jsx81("i", { className: "ph ph-flask", "aria-hidden": "true" }),
10794
- /* @__PURE__ */ jsxs72("span", { className: "fd-mode-opt-text", children: [
10795
- /* @__PURE__ */ jsx81("span", { className: "fd-mode-opt-title", children: "Test mode" }),
10796
- /* @__PURE__ */ jsx81("span", { className: "fd-mode-opt-desc", children: "Everything usable, all data simulated" })
11037
+ /* @__PURE__ */ jsxs73("button", { type: "button", className: "fd-mode-opt" + (test ? " is-on" : ""), onClick: () => go("test"), children: [
11038
+ /* @__PURE__ */ jsx82("i", { className: "ph ph-flask", "aria-hidden": "true" }),
11039
+ /* @__PURE__ */ jsxs73("span", { className: "fd-mode-opt-text", children: [
11040
+ /* @__PURE__ */ jsx82("span", { className: "fd-mode-opt-title", children: "Test mode" }),
11041
+ /* @__PURE__ */ jsx82("span", { className: "fd-mode-opt-desc", children: "Everything usable, all data simulated" })
10797
11042
  ] }),
10798
- test ? /* @__PURE__ */ jsx81("i", { className: "ph ph-check", "aria-hidden": "true" }) : null
11043
+ test ? /* @__PURE__ */ jsx82("i", { className: "ph ph-check", "aria-hidden": "true" }) : null
10799
11044
  ] })
10800
11045
  ] }),
10801
- test && renderLog ? /* @__PURE__ */ jsx81("span", { style: { display: "block", maxHeight: 340, overflowY: "auto", borderTop: "1px solid var(--border)" }, children: renderLog() }) : null
11046
+ test && renderLog ? /* @__PURE__ */ jsx82("span", { style: { display: "block", maxHeight: 340, overflowY: "auto", borderTop: "1px solid var(--border)" }, children: renderLog() }) : null
10802
11047
  ] }) }) : null
10803
11048
  ] });
10804
11049
  }
10805
11050
  function TestModeBar({ onExit }) {
10806
11051
  const mode2 = useRuntimeMode();
10807
11052
  if (mode2 !== "test") return null;
10808
- return /* @__PURE__ */ jsxs72("div", { className: "fd-testbar", role: "status", children: [
10809
- /* @__PURE__ */ jsxs72("span", { className: "fd-badge fd-badge-warning", children: [
10810
- /* @__PURE__ */ jsx81("i", { className: "ph ph-flask", "aria-hidden": "true" }),
11053
+ return /* @__PURE__ */ jsxs73("div", { className: "fd-testbar", role: "status", children: [
11054
+ /* @__PURE__ */ jsxs73("span", { className: "fd-badge fd-badge-warning", children: [
11055
+ /* @__PURE__ */ jsx82("i", { className: "ph ph-flask", "aria-hidden": "true" }),
10811
11056
  "Test mode"
10812
11057
  ] }),
10813
- /* @__PURE__ */ jsx81("span", { className: "fd-testbar-detail", children: "Every feature is unlocked and every response is simulated \u2014 nothing here persists." }),
10814
- /* @__PURE__ */ jsxs72("button", { type: "button", className: "fd-soon-link", onClick: () => onExit ? onExit() : RuntimeKit.setMode("live"), children: [
10815
- /* @__PURE__ */ jsx81("i", { className: "ph ph-lightning", "aria-hidden": "true" }),
11058
+ /* @__PURE__ */ jsx82("span", { className: "fd-testbar-detail", children: "Every feature is unlocked and every response is simulated \u2014 nothing here persists." }),
11059
+ /* @__PURE__ */ jsxs73("button", { type: "button", className: "fd-soon-link", onClick: () => onExit ? onExit() : RuntimeKit.setMode("live"), children: [
11060
+ /* @__PURE__ */ jsx82("i", { className: "ph ph-lightning", "aria-hidden": "true" }),
10816
11061
  " Back to live mode"
10817
11062
  ] })
10818
11063
  ] });
10819
11064
  }
10820
11065
 
10821
11066
  // src/components/planner/ChannelMeta.tsx
10822
- import { jsx as jsx82, jsxs as jsxs73 } from "react/jsx-runtime";
11067
+ import { jsx as jsx83, jsxs as jsxs74 } from "react/jsx-runtime";
10823
11068
  var CHANNEL_WEIGHTS = {
10824
11069
  "OOH": 50,
10825
11070
  "DOOH": 50,
@@ -10872,9 +11117,9 @@ function ChannelTag({ channel, size = "md", showLabel = true, dot = false, weigh
10872
11117
  const m = ChannelMeta(channel);
10873
11118
  const wt = channelWeightOf(channel || "");
10874
11119
  if (dot) {
10875
- return /* @__PURE__ */ jsx82("span", { className: ["fd-chan-dot", className].filter(Boolean).join(" "), title: m.name, style: { background: m.color }, ...rest });
11120
+ return /* @__PURE__ */ jsx83("span", { className: ["fd-chan-dot", className].filter(Boolean).join(" "), title: m.name, style: { background: m.color }, ...rest });
10876
11121
  }
10877
- return /* @__PURE__ */ jsxs73(
11122
+ return /* @__PURE__ */ jsxs74(
10878
11123
  "span",
10879
11124
  {
10880
11125
  className: ["fd-chan", size === "sm" ? "fd-chan-sm" : "", className].filter(Boolean).join(" "),
@@ -10882,16 +11127,16 @@ function ChannelTag({ channel, size = "md", showLabel = true, dot = false, weigh
10882
11127
  style: { "--chan": m.color },
10883
11128
  ...rest,
10884
11129
  children: [
10885
- /* @__PURE__ */ jsx82("i", { className: "ph ph-" + m.icon, "aria-hidden": "true" }),
10886
- showLabel ? /* @__PURE__ */ jsx82("span", { className: "fd-chan-label", children: m.label }) : null,
10887
- weight ? /* @__PURE__ */ jsx82("span", { className: "fd-chan-weight", children: wt || 0 }) : null
11130
+ /* @__PURE__ */ jsx83("i", { className: "ph ph-" + m.icon, "aria-hidden": "true" }),
11131
+ showLabel ? /* @__PURE__ */ jsx83("span", { className: "fd-chan-label", children: m.label }) : null,
11132
+ weight ? /* @__PURE__ */ jsx83("span", { className: "fd-chan-weight", children: wt || 0 }) : null
10888
11133
  ]
10889
11134
  }
10890
11135
  );
10891
11136
  }
10892
11137
 
10893
11138
  // src/components/planner/SaturationDistribution.tsx
10894
- import { jsx as jsx83, jsxs as jsxs74 } from "react/jsx-runtime";
11139
+ import { jsx as jsx84, jsxs as jsxs75 } from "react/jsx-runtime";
10895
11140
  var BANDS2 = [
10896
11141
  { key: "weak", label: "Weak", n: 1, range: "< 50" },
10897
11142
  { key: "adequate", label: "Adequate", n: 2, range: "50\u2013100" },
@@ -10902,24 +11147,24 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
10902
11147
  const grouped = BANDS2.map((b) => ({ ...b, items: campuses.filter((c) => c.band === b.key) }));
10903
11148
  const tallest = Math.max(1, ...grouped.map((g) => g.items.length));
10904
11149
  const floor = BANDS2.find((b) => b.key === floorBand) || BANDS2[0];
10905
- return /* @__PURE__ */ jsxs74("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 16 }, children: [
10906
- /* @__PURE__ */ jsx83("div", { style: { display: "grid", gridTemplateColumns: "repeat(4,minmax(0,1fr))", gap: 12, alignItems: "end" }, children: grouped.map((g) => {
11150
+ return /* @__PURE__ */ jsxs75("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 16 }, children: [
11151
+ /* @__PURE__ */ jsx84("div", { style: { display: "grid", gridTemplateColumns: "repeat(4,minmax(0,1fr))", gap: 12, alignItems: "end" }, children: grouped.map((g) => {
10907
11152
  const mark = "var(--csi-" + g.n + "-mark)";
10908
11153
  const active = selectedBand === g.key;
10909
- return /* @__PURE__ */ jsxs74(
11154
+ return /* @__PURE__ */ jsxs75(
10910
11155
  "button",
10911
11156
  {
10912
11157
  type: "button",
10913
11158
  onClick: onSelectBand ? () => onSelectBand(active ? null : g.key) : void 0,
10914
11159
  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)" },
10915
11160
  children: [
10916
- /* @__PURE__ */ jsx83("span", { style: { display: "flex", flexDirection: "column-reverse", gap: 4, minHeight: tallest * 24, minWidth: 0 }, children: loading ? Array.from({ length: 3 }).map((_, i) => /* @__PURE__ */ jsx83("span", { className: "fd-skel", style: { height: 16, borderRadius: 4 } }, i)) : g.items.map((c) => (
11161
+ /* @__PURE__ */ jsx84("span", { style: { display: "flex", flexDirection: "column-reverse", gap: 4, minHeight: tallest * 24, minWidth: 0 }, children: loading ? Array.from({ length: 3 }).map((_, i) => /* @__PURE__ */ jsx84("span", { className: "fd-skel", style: { height: 16, borderRadius: 4 } }, i)) : g.items.map((c) => (
10917
11162
  // `overflow: hidden` + `white-space: nowrap` only clips once the span
10918
11163
  // actually HAS a bounded width to clip against (see the grid/flex
10919
11164
  // `minWidth: 0` chain above) — `textOverflow: ellipsis` then makes
10920
11165
  // that clip readable instead of a hard cut mid-letter; the full name
10921
11166
  // is still one hover away via `title`.
10922
- /* @__PURE__ */ jsx83(
11167
+ /* @__PURE__ */ jsx84(
10923
11168
  "span",
10924
11169
  {
10925
11170
  title: c.name + " \xB7 " + c.crp,
@@ -10929,13 +11174,13 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
10929
11174
  c.name
10930
11175
  )
10931
11176
  )) }),
10932
- /* @__PURE__ */ jsxs74("span", { className: "fd-row", style: { gap: 8, alignItems: "baseline" }, children: [
10933
- /* @__PURE__ */ jsx83("span", { className: "fd-num-hero", style: { fontSize: 30, color: g.items.length ? "var(--text)" : "var(--text-disabled)" }, children: loading ? "\u2013" : g.items.length }),
10934
- /* @__PURE__ */ jsx83("span", { className: "fd-meter", style: { gap: 2, color: mark }, "aria-hidden": "true", children: [1, 2, 3, 4].map((i) => /* @__PURE__ */ jsx83("span", { className: "fd-meter-seg" + (i <= g.n ? " is-on" : ""), style: { width: 4, height: 9 } }, i)) })
11177
+ /* @__PURE__ */ jsxs75("span", { className: "fd-row", style: { gap: 8, alignItems: "baseline" }, children: [
11178
+ /* @__PURE__ */ jsx84("span", { className: "fd-num-hero", style: { fontSize: 30, color: g.items.length ? "var(--text)" : "var(--text-disabled)" }, children: loading ? "\u2013" : g.items.length }),
11179
+ /* @__PURE__ */ jsx84("span", { className: "fd-meter", style: { gap: 2, color: mark }, "aria-hidden": "true", children: [1, 2, 3, 4].map((i) => /* @__PURE__ */ jsx84("span", { className: "fd-meter-seg" + (i <= g.n ? " is-on" : ""), style: { width: 4, height: 9 } }, i)) })
10935
11180
  ] }),
10936
- /* @__PURE__ */ jsxs74("span", { className: "fd-stack", style: { gap: 1 }, children: [
10937
- /* @__PURE__ */ jsx83("span", { className: "fd-label-lg", children: g.label }),
10938
- /* @__PURE__ */ jsxs74("span", { className: "fd-body-sm fd-muted", style: { fontSize: 11.5 }, children: [
11181
+ /* @__PURE__ */ jsxs75("span", { className: "fd-stack", style: { gap: 1 }, children: [
11182
+ /* @__PURE__ */ jsx84("span", { className: "fd-label-lg", children: g.label }),
11183
+ /* @__PURE__ */ jsxs75("span", { className: "fd-body-sm fd-muted", style: { fontSize: 11.5 }, children: [
10939
11184
  "CRP ",
10940
11185
  g.range
10941
11186
  ] })
@@ -10945,10 +11190,10 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
10945
11190
  g.key
10946
11191
  );
10947
11192
  }) }),
10948
- floorBand ? /* @__PURE__ */ jsxs74("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: [
10949
- /* @__PURE__ */ jsx83("span", { className: "fd-meter", style: { gap: 2, color: "var(--csi-" + floor.n + "-mark)" }, "aria-hidden": "true", children: [1, 2, 3, 4].map((i) => /* @__PURE__ */ jsx83("span", { className: "fd-meter-seg" + (i <= floor.n ? " is-on" : ""), style: { width: 5, height: 12 } }, i)) }),
10950
- /* @__PURE__ */ jsxs74("span", { className: "fd-body-sm fd-secondary", style: { flex: 1, minWidth: 240 }, children: [
10951
- /* @__PURE__ */ jsxs74("strong", { style: { color: "var(--text)" }, children: [
11193
+ floorBand ? /* @__PURE__ */ jsxs75("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: [
11194
+ /* @__PURE__ */ jsx84("span", { className: "fd-meter", style: { gap: 2, color: "var(--csi-" + floor.n + "-mark)" }, "aria-hidden": "true", children: [1, 2, 3, 4].map((i) => /* @__PURE__ */ jsx84("span", { className: "fd-meter-seg" + (i <= floor.n ? " is-on" : ""), style: { width: 5, height: 12 } }, i)) }),
11195
+ /* @__PURE__ */ jsxs75("span", { className: "fd-body-sm fd-secondary", style: { flex: 1, minWidth: 240 }, children: [
11196
+ /* @__PURE__ */ jsxs75("strong", { style: { color: "var(--text)" }, children: [
10952
11197
  "Plan floor ",
10953
11198
  floorScore
10954
11199
  ] }),
@@ -10959,8 +11204,8 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
10959
11204
  }
10960
11205
 
10961
11206
  // src/components/planner/MixGap.tsx
10962
- import * as React55 from "react";
10963
- import { Fragment as Fragment23, jsx as jsx84, jsxs as jsxs75 } from "react/jsx-runtime";
11207
+ import * as React56 from "react";
11208
+ import { Fragment as Fragment23, jsx as jsx85, jsxs as jsxs76 } from "react/jsx-runtime";
10964
11209
  var MIX_GAP_LAYOUT = {
10965
11210
  trackHeight: 30,
10966
11211
  barHeight: 20,
@@ -10974,19 +11219,19 @@ function mixGapOffset(value, max) {
10974
11219
  }
10975
11220
  function MixGap({ rows = [], loading = false, className = "" }) {
10976
11221
  const max = Math.max(1, ...rows.flatMap((r) => [r.target, r.realized]));
10977
- const [hover, setHover] = React55.useState(null);
11222
+ const [hover, setHover] = React56.useState(null);
10978
11223
  const toneOf = (gap) => gap >= -1 ? "ok" : gap >= -4 ? "warn" : "danger";
10979
11224
  const TONE = { ok: "var(--ok-solid)", warn: "var(--warn-solid)", danger: "var(--danger-solid)" };
10980
11225
  const { trackHeight, barHeight, targetWidth, labelGap } = MIX_GAP_LAYOUT;
10981
11226
  const barTop = (trackHeight - barHeight) / 2;
10982
- return /* @__PURE__ */ jsxs75("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 4 }, children: [
10983
- /* @__PURE__ */ jsxs75("div", { className: "fd-row", style: { gap: 16, justifyContent: "flex-end", paddingBottom: 6, flexWrap: "wrap" }, children: [
10984
- [["On target", TONE.ok], ["Close", TONE.warn], ["Short", TONE.danger]].map(([l, c]) => /* @__PURE__ */ jsxs75("span", { className: "fd-row fd-body-sm fd-muted", style: { gap: 6 }, children: [
10985
- /* @__PURE__ */ jsx84("span", { style: { width: 14, height: 9, borderRadius: 2, background: c } }),
11227
+ return /* @__PURE__ */ jsxs76("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 4 }, children: [
11228
+ /* @__PURE__ */ jsxs76("div", { className: "fd-row", style: { gap: 16, justifyContent: "flex-end", paddingBottom: 6, flexWrap: "wrap" }, children: [
11229
+ [["On target", TONE.ok], ["Close", TONE.warn], ["Short", TONE.danger]].map(([l, c]) => /* @__PURE__ */ jsxs76("span", { className: "fd-row fd-body-sm fd-muted", style: { gap: 6 }, children: [
11230
+ /* @__PURE__ */ jsx85("span", { style: { width: 14, height: 9, borderRadius: 2, background: c } }),
10986
11231
  l
10987
11232
  ] }, l)),
10988
- /* @__PURE__ */ jsxs75("span", { className: "fd-row fd-body-sm fd-muted", style: { gap: 6 }, children: [
10989
- /* @__PURE__ */ jsx84("span", { "data-mixgap-legend-target": "", style: { width: targetWidth, height: 16, borderRadius: 1, background: MIX_GAP_TARGET_STRIPE } }),
11233
+ /* @__PURE__ */ jsxs76("span", { className: "fd-row fd-body-sm fd-muted", style: { gap: 6 }, children: [
11234
+ /* @__PURE__ */ jsx85("span", { "data-mixgap-legend-target": "", style: { width: targetWidth, height: 16, borderRadius: 1, background: MIX_GAP_TARGET_STRIPE } }),
10990
11235
  "Target"
10991
11236
  ] })
10992
11237
  ] }),
@@ -10995,7 +11240,7 @@ function MixGap({ rows = [], loading = false, className = "" }) {
10995
11240
  const tone = toneOf(gap);
10996
11241
  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 : "");
10997
11242
  const labelLeft = r.realized > r.target ? `calc(${mixGapOffset(r.realized, max)} + ${labelGap}px)` : `calc(${mixGapOffset(r.target, max)} + ${targetWidth / 2 + labelGap}px)`;
10998
- return /* @__PURE__ */ jsxs75(
11243
+ return /* @__PURE__ */ jsxs76(
10999
11244
  "div",
11000
11245
  {
11001
11246
  className: "fd-row",
@@ -11003,15 +11248,15 @@ function MixGap({ rows = [], loading = false, className = "" }) {
11003
11248
  onMouseEnter: () => setHover(r.channel),
11004
11249
  onMouseLeave: () => setHover(null),
11005
11250
  children: [
11006
- /* @__PURE__ */ jsx84("span", { style: { width: 128, flex: "none" }, children: /* @__PURE__ */ jsx84(ChannelTag, { channel: r.channel, size: "sm" }) }),
11007
- /* @__PURE__ */ jsx84("span", { style: { position: "relative", flex: 1, height: trackHeight, minWidth: 120 }, children: loading ? /* @__PURE__ */ jsx84("span", { className: "fd-skel", style: { position: "absolute", left: 0, right: 0, top: barTop, height: barHeight, borderRadius: 3 } }) : /* @__PURE__ */ jsxs75(Fragment23, { children: [
11008
- /* @__PURE__ */ jsx84("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)" } }),
11009
- /* @__PURE__ */ jsx84("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 } }),
11010
- /* @__PURE__ */ jsxs75("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: [
11251
+ /* @__PURE__ */ jsx85("span", { style: { width: 128, flex: "none" }, children: /* @__PURE__ */ jsx85(ChannelTag, { channel: r.channel, size: "sm" }) }),
11252
+ /* @__PURE__ */ jsx85("span", { style: { position: "relative", flex: 1, height: trackHeight, minWidth: 120 }, children: loading ? /* @__PURE__ */ jsx85("span", { className: "fd-skel", style: { position: "absolute", left: 0, right: 0, top: barTop, height: barHeight, borderRadius: 3 } }) : /* @__PURE__ */ jsxs76(Fragment23, { children: [
11253
+ /* @__PURE__ */ jsx85("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)" } }),
11254
+ /* @__PURE__ */ jsx85("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 } }),
11255
+ /* @__PURE__ */ jsxs76("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: [
11011
11256
  r.realized,
11012
11257
  "%"
11013
11258
  ] }),
11014
- hover === r.channel ? /* @__PURE__ */ jsx84("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
+ hover === r.channel ? /* @__PURE__ */ jsx85("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
11015
11260
  ] }) })
11016
11261
  ]
11017
11262
  },
@@ -11022,7 +11267,7 @@ function MixGap({ rows = [], loading = false, className = "" }) {
11022
11267
  }
11023
11268
 
11024
11269
  // src/components/planner/ChannelContribution.tsx
11025
- import { jsx as jsx85, jsxs as jsxs76 } from "react/jsx-runtime";
11270
+ import { jsx as jsx86, jsxs as jsxs77 } from "react/jsx-runtime";
11026
11271
  var money = (n) => "$" + Math.round(n).toLocaleString();
11027
11272
  function ChannelContribution({
11028
11273
  channels = [],
@@ -11038,9 +11283,9 @@ function ChannelContribution({
11038
11283
  const grand = total !== void 0 ? total : base + bonus;
11039
11284
  const pct = (v) => grand ? v / grand * 100 : 0;
11040
11285
  const spendTotal = channels.reduce((s, c) => s + Number(String(c.spend || 0).replace(/[^0-9.]/g, "")), 0);
11041
- return /* @__PURE__ */ jsxs76("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 16 }, children: [
11042
- loading ? /* @__PURE__ */ jsx85("span", { className: "fd-skel", style: { height: 34, borderRadius: "var(--r-sm)" } }) : /* @__PURE__ */ jsxs76("div", { className: "fd-row", style: { height: 34, borderRadius: "var(--r-sm)", overflow: "hidden", gap: 2, background: "var(--surface-3)" }, children: [
11043
- channels.map((c) => /* @__PURE__ */ jsx85(
11286
+ return /* @__PURE__ */ jsxs77("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 16 }, children: [
11287
+ loading ? /* @__PURE__ */ jsx86("span", { className: "fd-skel", style: { height: 34, borderRadius: "var(--r-sm)" } }) : /* @__PURE__ */ jsxs77("div", { className: "fd-row", style: { height: 34, borderRadius: "var(--r-sm)", overflow: "hidden", gap: 2, background: "var(--surface-3)" }, children: [
11288
+ channels.map((c) => /* @__PURE__ */ jsx86(
11044
11289
  "span",
11045
11290
  {
11046
11291
  title: c.name + " \xB7 " + c.crp.toFixed(1) + " CRP",
@@ -11049,7 +11294,7 @@ function ChannelContribution({
11049
11294
  },
11050
11295
  c.name
11051
11296
  )),
11052
- bonus > 0 ? /* @__PURE__ */ jsx85(
11297
+ bonus > 0 ? /* @__PURE__ */ jsx86(
11053
11298
  "span",
11054
11299
  {
11055
11300
  title: "Surround-sound bonus +" + bonusPct + "%",
@@ -11058,18 +11303,18 @@ function ChannelContribution({
11058
11303
  }
11059
11304
  ) : null
11060
11305
  ] }),
11061
- showTable ? /* @__PURE__ */ jsxs76("table", { className: "fd-table", style: { fontSize: "var(--body-sm-size)" }, children: [
11062
- /* @__PURE__ */ jsx85("thead", { children: /* @__PURE__ */ jsxs76("tr", { children: [
11063
- /* @__PURE__ */ jsx85("th", { style: { width: "34%" }, children: "Channel" }),
11064
- /* @__PURE__ */ jsx85("th", { style: { width: "16%" }, children: "Weight" }),
11065
- /* @__PURE__ */ jsx85("th", { className: "is-num", style: { width: "16%" }, children: "Spend" }),
11066
- /* @__PURE__ */ jsx85("th", { className: "is-num", style: { width: "17%" }, children: "CRP" }),
11067
- /* @__PURE__ */ jsx85("th", { className: "is-num", style: { width: "17%" }, children: "Share" })
11306
+ showTable ? /* @__PURE__ */ jsxs77("table", { className: "fd-table", style: { fontSize: "var(--body-sm-size)" }, children: [
11307
+ /* @__PURE__ */ jsx86("thead", { children: /* @__PURE__ */ jsxs77("tr", { children: [
11308
+ /* @__PURE__ */ jsx86("th", { style: { width: "34%" }, children: "Channel" }),
11309
+ /* @__PURE__ */ jsx86("th", { style: { width: "16%" }, children: "Weight" }),
11310
+ /* @__PURE__ */ jsx86("th", { className: "is-num", style: { width: "16%" }, children: "Spend" }),
11311
+ /* @__PURE__ */ jsx86("th", { className: "is-num", style: { width: "17%" }, children: "CRP" }),
11312
+ /* @__PURE__ */ jsx86("th", { className: "is-num", style: { width: "17%" }, children: "Share" })
11068
11313
  ] }) }),
11069
- /* @__PURE__ */ jsxs76("tbody", { children: [
11070
- channels.map((c) => /* @__PURE__ */ jsxs76("tr", { children: [
11071
- /* @__PURE__ */ jsx85("td", { children: /* @__PURE__ */ jsx85(ChannelTag, { channel: c.name, size: "sm" }) }),
11072
- /* @__PURE__ */ jsx85("td", { children: /* @__PURE__ */ jsx85(
11314
+ /* @__PURE__ */ jsxs77("tbody", { children: [
11315
+ channels.map((c) => /* @__PURE__ */ jsxs77("tr", { children: [
11316
+ /* @__PURE__ */ jsx86("td", { children: /* @__PURE__ */ jsx86(ChannelTag, { channel: c.name, size: "sm" }) }),
11317
+ /* @__PURE__ */ jsx86("td", { children: /* @__PURE__ */ jsx86(
11073
11318
  "span",
11074
11319
  {
11075
11320
  className: "fd-badge fd-badge-neutral",
@@ -11078,38 +11323,38 @@ function ChannelContribution({
11078
11323
  children: "weight " + (channelWeightOf(c.name) || 0)
11079
11324
  }
11080
11325
  ) }),
11081
- /* @__PURE__ */ jsx85("td", { className: "is-num", children: c.spend }),
11082
- /* @__PURE__ */ jsx85("td", { className: "is-num", children: c.crp.toFixed(1) }),
11083
- /* @__PURE__ */ jsxs76("td", { className: "is-num", children: [
11326
+ /* @__PURE__ */ jsx86("td", { className: "is-num", children: c.spend }),
11327
+ /* @__PURE__ */ jsx86("td", { className: "is-num", children: c.crp.toFixed(1) }),
11328
+ /* @__PURE__ */ jsxs77("td", { className: "is-num", children: [
11084
11329
  pct(c.crp).toFixed(0),
11085
11330
  "%"
11086
11331
  ] })
11087
11332
  ] }, c.name)),
11088
- bonus > 0 ? /* @__PURE__ */ jsxs76("tr", { children: [
11089
- /* @__PURE__ */ jsx85("td", { children: /* @__PURE__ */ jsxs76("span", { className: "fd-row", style: { gap: 9, fontWeight: 600 }, children: [
11090
- /* @__PURE__ */ jsx85("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" } }),
11333
+ bonus > 0 ? /* @__PURE__ */ jsxs77("tr", { children: [
11334
+ /* @__PURE__ */ jsx86("td", { children: /* @__PURE__ */ jsxs77("span", { className: "fd-row", style: { gap: 9, fontWeight: 600 }, children: [
11335
+ /* @__PURE__ */ jsx86("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" } }),
11091
11336
  "Surround-sound bonus"
11092
11337
  ] }) }),
11093
- /* @__PURE__ */ jsx85("td", { children: /* @__PURE__ */ jsxs76("span", { className: "fd-badge fd-badge-success", style: { height: 20, fontSize: 11 }, children: [
11338
+ /* @__PURE__ */ jsx86("td", { children: /* @__PURE__ */ jsxs77("span", { className: "fd-badge fd-badge-success", style: { height: 20, fontSize: 11 }, children: [
11094
11339
  "+",
11095
11340
  bonusPct,
11096
11341
  "% of +",
11097
11342
  bonusMax,
11098
11343
  "%"
11099
11344
  ] }) }),
11100
- /* @__PURE__ */ jsx85("td", { className: "is-num fd-muted", children: "\u2014" }),
11101
- /* @__PURE__ */ jsx85("td", { className: "is-num", children: bonus.toFixed(1) }),
11102
- /* @__PURE__ */ jsxs76("td", { className: "is-num", children: [
11345
+ /* @__PURE__ */ jsx86("td", { className: "is-num fd-muted", children: "\u2014" }),
11346
+ /* @__PURE__ */ jsx86("td", { className: "is-num", children: bonus.toFixed(1) }),
11347
+ /* @__PURE__ */ jsxs77("td", { className: "is-num", children: [
11103
11348
  pct(bonus).toFixed(0),
11104
11349
  "%"
11105
11350
  ] })
11106
11351
  ] }) : null,
11107
- /* @__PURE__ */ jsxs76("tr", { style: { background: "var(--surface-2)" }, children: [
11108
- /* @__PURE__ */ jsx85("td", { style: { fontWeight: 700 }, children: "Campus total" }),
11109
- /* @__PURE__ */ jsx85("td", {}),
11110
- /* @__PURE__ */ jsx85("td", { className: "is-num", style: { fontWeight: 700 }, children: money(spendTotal) }),
11111
- /* @__PURE__ */ jsx85("td", { className: "is-num", style: { fontWeight: 700 }, children: grand.toFixed(1) }),
11112
- /* @__PURE__ */ jsx85("td", { className: "is-num", style: { fontWeight: 700 }, children: "100%" })
11352
+ /* @__PURE__ */ jsxs77("tr", { style: { background: "var(--surface-2)" }, children: [
11353
+ /* @__PURE__ */ jsx86("td", { style: { fontWeight: 700 }, children: "Campus total" }),
11354
+ /* @__PURE__ */ jsx86("td", {}),
11355
+ /* @__PURE__ */ jsx86("td", { className: "is-num", style: { fontWeight: 700 }, children: money(spendTotal) }),
11356
+ /* @__PURE__ */ jsx86("td", { className: "is-num", style: { fontWeight: 700 }, children: grand.toFixed(1) }),
11357
+ /* @__PURE__ */ jsx86("td", { className: "is-num", style: { fontWeight: 700 }, children: "100%" })
11113
11358
  ] })
11114
11359
  ] })
11115
11360
  ] }) : null
@@ -11117,8 +11362,8 @@ function ChannelContribution({
11117
11362
  }
11118
11363
 
11119
11364
  // src/components/planner/BudgetReallocator.tsx
11120
- import * as React56 from "react";
11121
- import { Fragment as Fragment24, jsx as jsx86, jsxs as jsxs77 } from "react/jsx-runtime";
11365
+ import * as React57 from "react";
11366
+ import { Fragment as Fragment24, jsx as jsx87, jsxs as jsxs78 } from "react/jsx-runtime";
11122
11367
  var bandFor = (crp) => crp >= 200 ? "dominant" : crp >= 100 ? "strong" : crp >= 50 ? "adequate" : "weak";
11123
11368
  function BudgetReallocator({
11124
11369
  campus,
@@ -11133,8 +11378,8 @@ function BudgetReallocator({
11133
11378
  onCancel,
11134
11379
  className = ""
11135
11380
  }) {
11136
- const [draft, setDraft] = React56.useState(spend);
11137
- React56.useEffect(() => setDraft(spend), [spend]);
11381
+ const [draft, setDraft] = React57.useState(spend);
11382
+ React57.useEffect(() => setDraft(spend), [spend]);
11138
11383
  const dirty = draft !== spend;
11139
11384
  const nextCrp = scoreFor ? scoreFor(draft) : crp;
11140
11385
  const nextBand = bandFor(nextCrp);
@@ -11149,10 +11394,10 @@ function BudgetReallocator({
11149
11394
  setDraft(spend);
11150
11395
  if (onCancel) onCancel();
11151
11396
  };
11152
- const trackRef = React56.useRef(null);
11153
- const chipRef = React56.useRef(null);
11154
- const [chipLeft, setChipLeft] = React56.useState(null);
11155
- React56.useLayoutEffect(() => {
11397
+ const trackRef = React57.useRef(null);
11398
+ const chipRef = React57.useRef(null);
11399
+ const [chipLeft, setChipLeft] = React57.useState(null);
11400
+ React57.useLayoutEffect(() => {
11156
11401
  const track = trackRef.current;
11157
11402
  if (!dirty || !track) {
11158
11403
  setChipLeft(null);
@@ -11173,23 +11418,23 @@ function BudgetReallocator({
11173
11418
  ro.observe(track);
11174
11419
  return () => ro.disconnect();
11175
11420
  }, [dirty, pct]);
11176
- return /* @__PURE__ */ jsxs77(
11421
+ return /* @__PURE__ */ jsxs78(
11177
11422
  "div",
11178
11423
  {
11179
11424
  className: ["fd-stack", className].filter(Boolean).join(" "),
11180
11425
  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)" },
11181
11426
  children: [
11182
- /* @__PURE__ */ jsxs77("div", { className: "fd-row", style: { gap: 12, flexWrap: "wrap" }, children: [
11183
- /* @__PURE__ */ jsx86("span", { className: "fd-h4", style: { flex: 1, minWidth: 140 }, children: campus }),
11184
- /* @__PURE__ */ jsx86(CsiBadge, { band: nowBand, crp, size: "medium" }),
11185
- dirty ? /* @__PURE__ */ jsxs77(Fragment24, { children: [
11186
- /* @__PURE__ */ jsx86("i", { className: "ph ph-arrow-right fd-muted", "aria-hidden": "true" }),
11187
- /* @__PURE__ */ jsx86(CsiBadge, { band: nextBand, crp: nextCrp, size: "medium", preview: true })
11427
+ /* @__PURE__ */ jsxs78("div", { className: "fd-row", style: { gap: 12, flexWrap: "wrap" }, children: [
11428
+ /* @__PURE__ */ jsx87("span", { className: "fd-h4", style: { flex: 1, minWidth: 140 }, children: campus }),
11429
+ /* @__PURE__ */ jsx87(CsiBadge, { band: nowBand, crp, size: "medium" }),
11430
+ dirty ? /* @__PURE__ */ jsxs78(Fragment24, { children: [
11431
+ /* @__PURE__ */ jsx87("i", { className: "ph ph-arrow-right fd-muted", "aria-hidden": "true" }),
11432
+ /* @__PURE__ */ jsx87(CsiBadge, { band: nextBand, crp: nextCrp, size: "medium", preview: true })
11188
11433
  ] }) : null
11189
11434
  ] }),
11190
- /* @__PURE__ */ jsxs77("div", { className: "fd-slider", ref: trackRef, children: [
11191
- /* @__PURE__ */ jsx86("span", { className: "fd-slider-fill", style: { width: pct + "%" } }),
11192
- dirty ? /* @__PURE__ */ jsx86(
11435
+ /* @__PURE__ */ jsxs78("div", { className: "fd-slider", ref: trackRef, children: [
11436
+ /* @__PURE__ */ jsx87("span", { className: "fd-slider-fill", style: { width: pct + "%" } }),
11437
+ dirty ? /* @__PURE__ */ jsx87(
11193
11438
  "span",
11194
11439
  {
11195
11440
  ref: chipRef,
@@ -11201,7 +11446,7 @@ function BudgetReallocator({
11201
11446
  children: (delta < 0 ? "\u2212$" : "+$") + Math.abs(delta).toLocaleString()
11202
11447
  }
11203
11448
  ) : null,
11204
- /* @__PURE__ */ jsx86(
11449
+ /* @__PURE__ */ jsx87(
11205
11450
  "input",
11206
11451
  {
11207
11452
  type: "range",
@@ -11217,13 +11462,13 @@ function BudgetReallocator({
11217
11462
  }
11218
11463
  )
11219
11464
  ] }),
11220
- /* @__PURE__ */ jsxs77("div", { className: "fd-row", style: { gap: 12, flexWrap: "wrap" }, children: [
11221
- /* @__PURE__ */ jsxs77("span", { className: "fd-stack", style: { gap: 2, flex: 1, minWidth: 150 }, children: [
11222
- /* @__PURE__ */ jsx86("span", { className: "fd-num", style: { fontSize: 19, fontWeight: 700 }, children: "$" + draft.toLocaleString() }),
11223
- /* @__PURE__ */ jsx86("span", { className: "fd-body-sm fd-muted", children: "Arrow keys step $100, shift+arrow $1,000. Escape reverts." })
11465
+ /* @__PURE__ */ jsxs78("div", { className: "fd-row", style: { gap: 12, flexWrap: "wrap" }, children: [
11466
+ /* @__PURE__ */ jsxs78("span", { className: "fd-stack", style: { gap: 2, flex: 1, minWidth: 150 }, children: [
11467
+ /* @__PURE__ */ jsx87("span", { className: "fd-num", style: { fontSize: 19, fontWeight: 700 }, children: "$" + draft.toLocaleString() }),
11468
+ /* @__PURE__ */ jsx87("span", { className: "fd-body-sm fd-muted", children: "Arrow keys step $100, shift+arrow $1,000. Escape reverts." })
11224
11469
  ] }),
11225
- /* @__PURE__ */ jsx86("button", { type: "button", className: "fd-btn fd-btn-ghost", disabled: !dirty, onClick: revert, children: "Cancel" }),
11226
- /* @__PURE__ */ jsx86(
11470
+ /* @__PURE__ */ jsx87("button", { type: "button", className: "fd-btn fd-btn-ghost", disabled: !dirty, onClick: revert, children: "Cancel" }),
11471
+ /* @__PURE__ */ jsx87(
11227
11472
  "button",
11228
11473
  {
11229
11474
  type: "button",
@@ -11242,7 +11487,7 @@ function BudgetReallocator({
11242
11487
  }
11243
11488
 
11244
11489
  // src/components/planner/SurroundSound.tsx
11245
- import { jsx as jsx87, jsxs as jsxs78 } from "react/jsx-runtime";
11490
+ import { jsx as jsx88, jsxs as jsxs79 } from "react/jsx-runtime";
11246
11491
  var CATEGORIES = [
11247
11492
  { key: "ooh", label: "OOH", icon: "flag-banner", color: "var(--ch-ooh)" },
11248
11493
  { key: "transit", label: "Transit", icon: "bus", color: "var(--ch-transit)" },
@@ -11254,26 +11499,26 @@ var CATEGORIES = [
11254
11499
  function SurroundSound({ present = [], bonusPct = 0, bonusMax = 40, missedCost, className = "" }) {
11255
11500
  const earned = Math.max(0, Math.min(1, bonusPct / bonusMax));
11256
11501
  const single = present.length <= 2;
11257
- return /* @__PURE__ */ jsxs78("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 14 }, children: [
11258
- /* @__PURE__ */ jsx87("div", { className: "fd-row", style: { gap: 8, flexWrap: "wrap" }, children: CATEGORIES.map((c) => {
11502
+ return /* @__PURE__ */ jsxs79("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 14 }, children: [
11503
+ /* @__PURE__ */ jsx88("div", { className: "fd-row", style: { gap: 8, flexWrap: "wrap" }, children: CATEGORIES.map((c) => {
11259
11504
  const on = present.includes(c.key);
11260
- return /* @__PURE__ */ jsxs78(
11505
+ return /* @__PURE__ */ jsxs79(
11261
11506
  "span",
11262
11507
  {
11263
11508
  title: c.label + (on ? " \u2014 present" : " \u2014 not bought"),
11264
11509
  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)" },
11265
11510
  children: [
11266
- /* @__PURE__ */ jsx87("i", { className: "ph ph-" + c.icon, style: { fontSize: 19, color: on ? c.color : "var(--text-muted)" }, "aria-hidden": "true" }),
11267
- /* @__PURE__ */ jsx87("span", { style: { fontSize: 10.5, fontWeight: 700 }, children: c.label })
11511
+ /* @__PURE__ */ jsx88("i", { className: "ph ph-" + c.icon, style: { fontSize: 19, color: on ? c.color : "var(--text-muted)" }, "aria-hidden": "true" }),
11512
+ /* @__PURE__ */ jsx88("span", { style: { fontSize: 10.5, fontWeight: 700 }, children: c.label })
11268
11513
  ]
11269
11514
  },
11270
11515
  c.key
11271
11516
  );
11272
11517
  }) }),
11273
- /* @__PURE__ */ jsxs78("div", { className: "fd-stack", style: { gap: 8 }, children: [
11274
- /* @__PURE__ */ jsxs78("div", { className: "fd-row", style: { justifyContent: "space-between", gap: 12 }, children: [
11275
- /* @__PURE__ */ jsx87("span", { className: "fd-label-lg", children: "Surround-sound bonus earned" }),
11276
- /* @__PURE__ */ jsxs78("span", { className: "fd-num", style: { color: single ? "var(--warn-text)" : "var(--csi-3-mark)", fontWeight: 700 }, children: [
11518
+ /* @__PURE__ */ jsxs79("div", { className: "fd-stack", style: { gap: 8 }, children: [
11519
+ /* @__PURE__ */ jsxs79("div", { className: "fd-row", style: { justifyContent: "space-between", gap: 12 }, children: [
11520
+ /* @__PURE__ */ jsx88("span", { className: "fd-label-lg", children: "Surround-sound bonus earned" }),
11521
+ /* @__PURE__ */ jsxs79("span", { className: "fd-num", style: { color: single ? "var(--warn-text)" : "var(--csi-3-mark)", fontWeight: 700 }, children: [
11277
11522
  "+",
11278
11523
  bonusPct,
11279
11524
  "% of +",
@@ -11281,8 +11526,8 @@ function SurroundSound({ present = [], bonusPct = 0, bonusMax = 40, missedCost,
11281
11526
  "%"
11282
11527
  ] })
11283
11528
  ] }),
11284
- /* @__PURE__ */ jsx87("div", { style: { height: 8, borderRadius: "var(--r-xs)", background: "var(--surface-3)", overflow: "hidden" }, children: /* @__PURE__ */ jsx87("div", { style: { height: "100%", width: earned * 100 + "%", background: "var(--csi-3-mark)", borderRadius: "inherit", transition: "width var(--dur-slow) var(--ease)" } }) }),
11285
- /* @__PURE__ */ jsxs78("span", { className: "fd-body-sm fd-secondary", style: { textWrap: "pretty" }, children: [
11529
+ /* @__PURE__ */ jsx88("div", { style: { height: 8, borderRadius: "var(--r-xs)", background: "var(--surface-3)", overflow: "hidden" }, children: /* @__PURE__ */ jsx88("div", { style: { height: "100%", width: earned * 100 + "%", background: "var(--csi-3-mark)", borderRadius: "inherit", transition: "width var(--dur-slow) var(--ease)" } }) }),
11530
+ /* @__PURE__ */ jsxs79("span", { className: "fd-body-sm fd-secondary", style: { textWrap: "pretty" }, children: [
11286
11531
  present.length,
11287
11532
  " of 6 channel categories present.",
11288
11533
  " ",
@@ -11294,7 +11539,7 @@ function SurroundSound({ present = [], bonusPct = 0, bonusMax = 40, missedCost,
11294
11539
  }
11295
11540
 
11296
11541
  // src/components/planner/Importance.tsx
11297
- import { jsx as jsx88, jsxs as jsxs79 } from "react/jsx-runtime";
11542
+ import { jsx as jsx89, jsxs as jsxs80 } from "react/jsx-runtime";
11298
11543
  var IMPORTANCE_LEVELS = [
11299
11544
  { id: "nudge", rank: 1, label: "Nudge", icon: "feather", description: "Breaks a tie, nothing more." },
11300
11545
  { id: "lean", rank: 2, label: "Lean", icon: "arrow-bend-up-right", description: "A mild preference between otherwise equal options." },
@@ -11324,7 +11569,7 @@ function importanceTokens(id) {
11324
11569
  function ImportanceTag({ level, showLabel = true, size = "sm", className = "", disabled = false }) {
11325
11570
  const lvl = importanceLevel(level);
11326
11571
  const t = importanceTokens(level);
11327
- return /* @__PURE__ */ jsxs79(
11572
+ return /* @__PURE__ */ jsxs80(
11328
11573
  "span",
11329
11574
  {
11330
11575
  className: ["fd-imp-tag", size === "md" ? "is-md" : "", disabled ? "is-disabled" : "", className].filter(Boolean).join(" "),
@@ -11332,16 +11577,16 @@ function ImportanceTag({ level, showLabel = true, size = "sm", className = "", d
11332
11577
  title: lvl.label + " \u2014 " + lvl.description,
11333
11578
  "aria-disabled": disabled ? "true" : void 0,
11334
11579
  children: [
11335
- /* @__PURE__ */ jsx88("i", { className: "ph ph-" + lvl.icon, "aria-hidden": "true" }),
11336
- showLabel ? lvl.label : /* @__PURE__ */ jsx88("span", { className: "fd-sr", children: lvl.label })
11580
+ /* @__PURE__ */ jsx89("i", { className: "ph ph-" + lvl.icon, "aria-hidden": "true" }),
11581
+ showLabel ? lvl.label : /* @__PURE__ */ jsx89("span", { className: "fd-sr", children: lvl.label })
11337
11582
  ]
11338
11583
  }
11339
11584
  );
11340
11585
  }
11341
11586
 
11342
11587
  // src/components/planner/PreferenceMeter.tsx
11343
- import * as React57 from "react";
11344
- import { jsx as jsx89, jsxs as jsxs80 } from "react/jsx-runtime";
11588
+ import * as React58 from "react";
11589
+ import { jsx as jsx90, jsxs as jsxs81 } from "react/jsx-runtime";
11345
11590
  function preferenceScore(criteria) {
11346
11591
  const earned = criteria.reduce((n, c) => n + (Number(c.earned) || 0), 0);
11347
11592
  const weight = criteria.reduce((n, c) => n + (Number(c.weight) || 0), 0);
@@ -11370,8 +11615,8 @@ function PreferenceMeter({
11370
11615
  className = ""
11371
11616
  }) {
11372
11617
  const value = score == null ? preferenceScore(criteria) : score;
11373
- const segments = React57.useMemo(() => preferenceSegments(criteria), [criteria]);
11374
- return /* @__PURE__ */ jsx89(
11618
+ const segments = React58.useMemo(() => preferenceSegments(criteria), [criteria]);
11619
+ return /* @__PURE__ */ jsx90(
11375
11620
  ScoreMeter,
11376
11621
  {
11377
11622
  score: value,
@@ -11383,22 +11628,22 @@ function PreferenceMeter({
11383
11628
  placement,
11384
11629
  className,
11385
11630
  breakdownLabel: breakdownTitle,
11386
- breakdown: /* @__PURE__ */ jsxs80("div", { className: "fd-prefbreak", children: [
11387
- /* @__PURE__ */ jsxs80("div", { className: "fd-prefbreak-head", children: [
11388
- /* @__PURE__ */ jsx89("span", { className: "fd-label-lg", children: breakdownTitle }),
11389
- /* @__PURE__ */ jsx89("span", { className: "fd-prefbreak-score fd-tabular", children: Math.round(value) })
11631
+ breakdown: /* @__PURE__ */ jsxs81("div", { className: "fd-prefbreak", children: [
11632
+ /* @__PURE__ */ jsxs81("div", { className: "fd-prefbreak-head", children: [
11633
+ /* @__PURE__ */ jsx90("span", { className: "fd-label-lg", children: breakdownTitle }),
11634
+ /* @__PURE__ */ jsx90("span", { className: "fd-prefbreak-score fd-tabular", children: Math.round(value) })
11390
11635
  ] }),
11391
- /* @__PURE__ */ jsx89("ul", { className: "fd-prefbreak-list", children: criteria.map((c) => {
11636
+ /* @__PURE__ */ jsx90("ul", { className: "fd-prefbreak-list", children: criteria.map((c) => {
11392
11637
  const pct = c.weight > 0 ? Math.round((Number(c.earned) || 0) / c.weight * 100) : 0;
11393
- return /* @__PURE__ */ jsxs80("li", { className: pct === 0 ? "fd-prefbreak-item is-unmet" : "fd-prefbreak-item", children: [
11394
- /* @__PURE__ */ jsx89(ImportanceTag, { level: c.importance }),
11395
- /* @__PURE__ */ jsxs80("span", { className: "fd-prefbreak-text", children: [
11396
- /* @__PURE__ */ jsx89("span", { className: "fd-prefbreak-label", children: c.label }),
11397
- c.note ? /* @__PURE__ */ jsx89("span", { className: "fd-prefbreak-note", children: c.note }) : null
11638
+ return /* @__PURE__ */ jsxs81("li", { className: pct === 0 ? "fd-prefbreak-item is-unmet" : "fd-prefbreak-item", children: [
11639
+ /* @__PURE__ */ jsx90(ImportanceTag, { level: c.importance }),
11640
+ /* @__PURE__ */ jsxs81("span", { className: "fd-prefbreak-text", children: [
11641
+ /* @__PURE__ */ jsx90("span", { className: "fd-prefbreak-label", children: c.label }),
11642
+ c.note ? /* @__PURE__ */ jsx90("span", { className: "fd-prefbreak-note", children: c.note }) : null
11398
11643
  ] }),
11399
- /* @__PURE__ */ jsxs80("span", { className: "fd-prefbreak-val fd-tabular", children: [
11644
+ /* @__PURE__ */ jsxs81("span", { className: "fd-prefbreak-val fd-tabular", children: [
11400
11645
  Math.round(Number(c.earned) || 0),
11401
- /* @__PURE__ */ jsx89("span", { className: "fd-prefbreak-sep", children: "/" }),
11646
+ /* @__PURE__ */ jsx90("span", { className: "fd-prefbreak-sep", children: "/" }),
11402
11647
  Math.round(c.weight)
11403
11648
  ] })
11404
11649
  ] }, c.id);
@@ -11409,10 +11654,10 @@ function PreferenceMeter({
11409
11654
  }
11410
11655
 
11411
11656
  // src/components/chat/AgentChatPanel.tsx
11412
- import * as React63 from "react";
11657
+ import * as React64 from "react";
11413
11658
 
11414
11659
  // src/components/chat/chatEngine.ts
11415
- import * as React58 from "react";
11660
+ import * as React59 from "react";
11416
11661
  var CHAT_UNAVAILABLE = "chat_unavailable";
11417
11662
  var JOB_PENDING = ["queued", "running"];
11418
11663
  var JOB_SUCCESS = ["completed", "recovered"];
@@ -11466,22 +11711,22 @@ function useChatEngine(opts) {
11466
11711
  onClear,
11467
11712
  onFeedback
11468
11713
  } = opts || {};
11469
- const [status, setStatus] = React58.useState("idle");
11470
- const [threadId, setThreadId] = React58.useState(null);
11471
- const [messages, setMessages] = React58.useState([]);
11472
- const [queue, setQueue] = React58.useState([]);
11473
- const [fatal, setFatal] = React58.useState(null);
11474
- const [busy, setBusy] = React58.useState(false);
11475
- const [turnStartedAt, setTurnStartedAt] = React58.useState(null);
11476
- const listRef = React58.useRef([]);
11477
- const queueRef = React58.useRef([]);
11478
- const busyRef = React58.useRef(false);
11479
- const stoppedRef = React58.useRef(false);
11480
- const abortRef = React58.useRef(null);
11481
- const serverCount = React58.useRef(0);
11482
- const threadRef = React58.useRef(null);
11483
- const mounted = React58.useRef(true);
11484
- React58.useEffect(() => {
11714
+ const [status, setStatus] = React59.useState("idle");
11715
+ const [threadId, setThreadId] = React59.useState(null);
11716
+ const [messages, setMessages] = React59.useState([]);
11717
+ const [queue, setQueue] = React59.useState([]);
11718
+ const [fatal, setFatal] = React59.useState(null);
11719
+ const [busy, setBusy] = React59.useState(false);
11720
+ const [turnStartedAt, setTurnStartedAt] = React59.useState(null);
11721
+ const listRef = React59.useRef([]);
11722
+ const queueRef = React59.useRef([]);
11723
+ const busyRef = React59.useRef(false);
11724
+ const stoppedRef = React59.useRef(false);
11725
+ const abortRef = React59.useRef(null);
11726
+ const serverCount = React59.useRef(0);
11727
+ const threadRef = React59.useRef(null);
11728
+ const mounted = React59.useRef(true);
11729
+ React59.useEffect(() => {
11485
11730
  mounted.current = true;
11486
11731
  return () => {
11487
11732
  mounted.current = false;
@@ -11503,14 +11748,14 @@ function useChatEngine(opts) {
11503
11748
  }
11504
11749
  return false;
11505
11750
  };
11506
- const loadThread = React58.useCallback(async (id) => {
11751
+ const loadThread = React59.useCallback(async (id) => {
11507
11752
  const data = await apiAdapter.getThread(id);
11508
11753
  const list = [...data && data.messages || []];
11509
11754
  serverCount.current = list.length;
11510
11755
  commit(list);
11511
11756
  return list;
11512
11757
  }, [apiAdapter]);
11513
- React58.useEffect(() => {
11758
+ React59.useEffect(() => {
11514
11759
  if (!apiAdapter) {
11515
11760
  setStatus("idle");
11516
11761
  setFatal(null);
@@ -11723,7 +11968,7 @@ function useChatEngine(opts) {
11723
11968
  await dispatchTurn(turn);
11724
11969
  }
11725
11970
  }
11726
- const send = React58.useCallback((text, attachments) => {
11971
+ const send = React59.useCallback((text, attachments) => {
11727
11972
  const body = (text || "").trim();
11728
11973
  if (!body && !(attachments && attachments.length)) return;
11729
11974
  if (status === "disconnected") return;
@@ -11733,7 +11978,7 @@ function useChatEngine(opts) {
11733
11978
  stoppedRef.current = false;
11734
11979
  drain();
11735
11980
  }, [status]);
11736
- const stop = React58.useCallback(() => {
11981
+ const stop = React59.useCallback(() => {
11737
11982
  stoppedRef.current = true;
11738
11983
  const ac = abortRef.current;
11739
11984
  if (ac) {
@@ -11752,11 +11997,11 @@ function useChatEngine(opts) {
11752
11997
  store.del(STORAGE_PREFIX + threadRef.current);
11753
11998
  }
11754
11999
  }, [apiAdapter]);
11755
- const removeQueued = React58.useCallback((id) => {
12000
+ const removeQueued = React59.useCallback((id) => {
11756
12001
  queueRef.current = queueRef.current.filter((t) => t.id !== id);
11757
12002
  setQueue(queueRef.current.slice());
11758
12003
  }, []);
11759
- const retry = React58.useCallback(() => {
12004
+ const retry = React59.useCallback(() => {
11760
12005
  const list = listRef.current;
11761
12006
  let at = -1;
11762
12007
  for (let i = list.length - 1; i >= 0; i--) if (list[i].role === "user") {
@@ -11772,19 +12017,19 @@ function useChatEngine(opts) {
11772
12017
  setQueue(queueRef.current.slice());
11773
12018
  drain();
11774
12019
  }, []);
11775
- const clear = React58.useCallback(() => {
12020
+ const clear = React59.useCallback(() => {
11776
12021
  commit([]);
11777
12022
  serverCount.current = 0;
11778
12023
  queueRef.current = [];
11779
12024
  setQueue([]);
11780
12025
  onClear && onClear();
11781
12026
  }, [onClear]);
11782
- const setFeedback = React58.useCallback((id, value) => {
12027
+ const setFeedback = React59.useCallback((id, value) => {
11783
12028
  patch(id, (m) => ({ feedback: m.feedback === value ? null : value }));
11784
12029
  const msg = listRef.current.find((m) => m.id === id);
11785
12030
  onFeedback && onFeedback({ message: msg, feedback: msg ? msg.feedback : value });
11786
12031
  }, [onFeedback]);
11787
- const reload = React58.useCallback(async () => {
12032
+ const reload = React59.useCallback(async () => {
11788
12033
  if (!threadRef.current) return;
11789
12034
  setStatus("loading");
11790
12035
  try {
@@ -11822,11 +12067,11 @@ var ChatKit = {
11822
12067
  };
11823
12068
 
11824
12069
  // src/components/chat/ChatTranscript.tsx
11825
- import * as React60 from "react";
12070
+ import * as React61 from "react";
11826
12071
 
11827
12072
  // src/components/chat/ChatTurn.tsx
11828
- import * as React59 from "react";
11829
- import { jsx as jsx90, jsxs as jsxs81 } from "react/jsx-runtime";
12073
+ import * as React60 from "react";
12074
+ import { jsx as jsx91, jsxs as jsxs82 } from "react/jsx-runtime";
11830
12075
  function JsonView({ value }) {
11831
12076
  let text;
11832
12077
  try {
@@ -11834,67 +12079,67 @@ function JsonView({ value }) {
11834
12079
  } catch (e) {
11835
12080
  text = String(value);
11836
12081
  }
11837
- return /* @__PURE__ */ jsx90(CodeBlock, { code: text, language: "json", collapseAfter: 18 });
12082
+ return /* @__PURE__ */ jsx91(CodeBlock, { code: text, language: "json", collapseAfter: 18 });
11838
12083
  }
11839
12084
  function PacketCard({ packet, schema, render, onApply, applied }) {
11840
12085
  if (!packet) return null;
11841
12086
  const s = schema || {};
11842
12087
  const invalid = packet.valid === false;
11843
12088
  const title = s.heading || packet.type;
11844
- return /* @__PURE__ */ jsxs81("section", { className: "fdc-packet" + (invalid ? " is-invalid" : ""), "aria-label": title, children: [
11845
- /* @__PURE__ */ jsxs81("header", { className: "fdc-packet-head", children: [
11846
- /* @__PURE__ */ jsx90("i", { className: "ph ph-" + (s.icon || "package"), "aria-hidden": "true" }),
11847
- /* @__PURE__ */ jsx90("span", { className: "fdc-packet-title", title: truncationTitle(title), children: title }),
11848
- packet.repaired ? /* @__PURE__ */ jsx90("span", { className: "fdc-packet-badge", children: "Repaired" }) : null,
11849
- invalid ? /* @__PURE__ */ jsx90("span", { className: "fdc-packet-badge is-danger", children: "Invalid" }) : null
12089
+ return /* @__PURE__ */ jsxs82("section", { className: "fdc-packet" + (invalid ? " is-invalid" : ""), "aria-label": title, children: [
12090
+ /* @__PURE__ */ jsxs82("header", { className: "fdc-packet-head", children: [
12091
+ /* @__PURE__ */ jsx91("i", { className: "ph ph-" + (s.icon || "package"), "aria-hidden": "true" }),
12092
+ /* @__PURE__ */ jsx91("span", { className: "fdc-packet-title", title: truncationTitle(title), children: title }),
12093
+ packet.repaired ? /* @__PURE__ */ jsx91("span", { className: "fdc-packet-badge", children: "Repaired" }) : null,
12094
+ invalid ? /* @__PURE__ */ jsx91("span", { className: "fdc-packet-badge is-danger", children: "Invalid" }) : null
11850
12095
  ] }),
11851
- invalid ? /* @__PURE__ */ jsxs81("div", { className: "fdc-packet-alert", role: "alert", children: [
11852
- /* @__PURE__ */ jsx90("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
11853
- /* @__PURE__ */ jsx90("span", { children: packet.error || "This result failed validation and can\u2019t be applied." })
11854
- ] }) : /* @__PURE__ */ jsx90("div", { className: "fdc-packet-body", children: render ? render(packet) : /* @__PURE__ */ jsx90(JsonView, { value: packet.payload }) }),
11855
- !invalid && onApply ? /* @__PURE__ */ jsxs81("footer", { className: "fdc-packet-foot", children: [
11856
- packet.repaired ? /* @__PURE__ */ jsx90("span", { className: "fdc-packet-note", children: "Corrected by the backend after a first attempt." }) : /* @__PURE__ */ jsx90("span", {}),
11857
- /* @__PURE__ */ jsxs81("button", { type: "button", className: "fd-btn fd-btn-primary fd-btn-sm", disabled: applied, onClick: () => onApply(packet), children: [
11858
- /* @__PURE__ */ jsx90("i", { className: "ph ph-" + (applied ? "check" : "arrow-square-in"), "aria-hidden": "true" }),
12096
+ invalid ? /* @__PURE__ */ jsxs82("div", { className: "fdc-packet-alert", role: "alert", children: [
12097
+ /* @__PURE__ */ jsx91("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
12098
+ /* @__PURE__ */ jsx91("span", { children: packet.error || "This result failed validation and can\u2019t be applied." })
12099
+ ] }) : /* @__PURE__ */ jsx91("div", { className: "fdc-packet-body", children: render ? render(packet) : /* @__PURE__ */ jsx91(JsonView, { value: packet.payload }) }),
12100
+ !invalid && onApply ? /* @__PURE__ */ jsxs82("footer", { className: "fdc-packet-foot", children: [
12101
+ packet.repaired ? /* @__PURE__ */ jsx91("span", { className: "fdc-packet-note", children: "Corrected by the backend after a first attempt." }) : /* @__PURE__ */ jsx91("span", {}),
12102
+ /* @__PURE__ */ jsxs82("button", { type: "button", className: "fd-btn fd-btn-primary fd-btn-sm", disabled: applied, onClick: () => onApply(packet), children: [
12103
+ /* @__PURE__ */ jsx91("i", { className: "ph ph-" + (applied ? "check" : "arrow-square-in"), "aria-hidden": "true" }),
11859
12104
  applied ? "Applied" : s.applyLabel || "Apply"
11860
12105
  ] })
11861
12106
  ] }) : null
11862
12107
  ] });
11863
12108
  }
11864
12109
  function ThinkingBlock({ text, durationMs, streaming, defaultOpen = false }) {
11865
- const [open2, setOpen] = React59.useState(defaultOpen);
12110
+ const [open2, setOpen] = React60.useState(defaultOpen);
11866
12111
  if (!text) return null;
11867
- return /* @__PURE__ */ jsxs81("div", { className: "fdc-think" + (open2 ? " is-open" : ""), children: [
11868
- /* @__PURE__ */ jsxs81("button", { type: "button", className: "fdc-think-head", onClick: () => setOpen((v) => !v), "aria-expanded": open2, children: [
11869
- /* @__PURE__ */ jsx90("i", { className: "ph ph-brain", "aria-hidden": "true" }),
11870
- /* @__PURE__ */ jsx90("span", { children: streaming ? "Thinking" : durationMs ? "Thought for " + formatDuration(durationMs) : "Thought process" }),
11871
- streaming ? /* @__PURE__ */ jsxs81("span", { className: "fdc-dots", "aria-hidden": "true", children: [
11872
- /* @__PURE__ */ jsx90("span", {}),
11873
- /* @__PURE__ */ jsx90("span", {}),
11874
- /* @__PURE__ */ jsx90("span", {})
12112
+ return /* @__PURE__ */ jsxs82("div", { className: "fdc-think" + (open2 ? " is-open" : ""), children: [
12113
+ /* @__PURE__ */ jsxs82("button", { type: "button", className: "fdc-think-head", onClick: () => setOpen((v) => !v), "aria-expanded": open2, children: [
12114
+ /* @__PURE__ */ jsx91("i", { className: "ph ph-brain", "aria-hidden": "true" }),
12115
+ /* @__PURE__ */ jsx91("span", { children: streaming ? "Thinking" : durationMs ? "Thought for " + formatDuration(durationMs) : "Thought process" }),
12116
+ streaming ? /* @__PURE__ */ jsxs82("span", { className: "fdc-dots", "aria-hidden": "true", children: [
12117
+ /* @__PURE__ */ jsx91("span", {}),
12118
+ /* @__PURE__ */ jsx91("span", {}),
12119
+ /* @__PURE__ */ jsx91("span", {})
11875
12120
  ] }) : null,
11876
- /* @__PURE__ */ jsx90("i", { className: "ph ph-caret-" + (open2 ? "up" : "down"), "aria-hidden": "true" })
12121
+ /* @__PURE__ */ jsx91("i", { className: "ph ph-caret-" + (open2 ? "up" : "down"), "aria-hidden": "true" })
11877
12122
  ] }),
11878
- open2 ? /* @__PURE__ */ jsx90("div", { className: "fdc-think-body", children: text }) : null
12123
+ open2 ? /* @__PURE__ */ jsx91("div", { className: "fdc-think-body", children: text }) : null
11879
12124
  ] });
11880
12125
  }
11881
12126
  function Citations({ items = [], onOpen }) {
11882
- const [open2, setOpen] = React59.useState(false);
12127
+ const [open2, setOpen] = React60.useState(false);
11883
12128
  if (!items.length) return null;
11884
- return /* @__PURE__ */ jsxs81("div", { className: "fdc-cites", children: [
11885
- /* @__PURE__ */ jsxs81("button", { type: "button", className: "fdc-cites-head", onClick: () => setOpen((v) => !v), "aria-expanded": open2, children: [
11886
- /* @__PURE__ */ jsx90("i", { className: "ph ph-quotes", "aria-hidden": "true" }),
11887
- /* @__PURE__ */ jsxs81("span", { children: [
12129
+ return /* @__PURE__ */ jsxs82("div", { className: "fdc-cites", children: [
12130
+ /* @__PURE__ */ jsxs82("button", { type: "button", className: "fdc-cites-head", onClick: () => setOpen((v) => !v), "aria-expanded": open2, children: [
12131
+ /* @__PURE__ */ jsx91("i", { className: "ph ph-quotes", "aria-hidden": "true" }),
12132
+ /* @__PURE__ */ jsxs82("span", { children: [
11888
12133
  items.length,
11889
12134
  " source",
11890
12135
  items.length === 1 ? "" : "s"
11891
12136
  ] }),
11892
- /* @__PURE__ */ jsx90("i", { className: "ph ph-caret-" + (open2 ? "up" : "down"), "aria-hidden": "true" })
12137
+ /* @__PURE__ */ jsx91("i", { className: "ph ph-caret-" + (open2 ? "up" : "down"), "aria-hidden": "true" })
11893
12138
  ] }),
11894
- open2 ? /* @__PURE__ */ jsx90("ol", { className: "fdc-cites-list", children: items.map((c, i) => /* @__PURE__ */ jsxs81("li", { children: [
11895
- /* @__PURE__ */ jsx90("span", { className: "fdc-cite-n fd-tabular", children: c.marker || i + 1 }),
11896
- c.url ? /* @__PURE__ */ jsx90("a", { href: c.url, target: "_blank", rel: "noopener noreferrer", onClick: onOpen ? (e) => onOpen(c, e) : void 0, children: c.title || c.url }) : /* @__PURE__ */ jsx90("span", { children: c.title || "Source" }),
11897
- c.detail ? /* @__PURE__ */ jsx90("span", { className: "fdc-cite-detail", children: c.detail }) : null
12139
+ open2 ? /* @__PURE__ */ jsx91("ol", { className: "fdc-cites-list", children: items.map((c, i) => /* @__PURE__ */ jsxs82("li", { children: [
12140
+ /* @__PURE__ */ jsx91("span", { className: "fdc-cite-n fd-tabular", children: c.marker || i + 1 }),
12141
+ c.url ? /* @__PURE__ */ jsx91("a", { href: c.url, target: "_blank", rel: "noopener noreferrer", onClick: onOpen ? (e) => onOpen(c, e) : void 0, children: c.title || c.url }) : /* @__PURE__ */ jsx91("span", { children: c.title || "Source" }),
12142
+ c.detail ? /* @__PURE__ */ jsx91("span", { className: "fdc-cite-detail", children: c.detail }) : null
11898
12143
  ] }, c.id || i)) }) : null
11899
12144
  ] });
11900
12145
  }
@@ -11905,29 +12150,29 @@ function clampText(text, max) {
11905
12150
  return (at > max * 0.6 ? cut.slice(0, at) : cut).trimEnd() + "\u2026";
11906
12151
  }
11907
12152
  function MessageBody({ message: m, ctx }) {
11908
- const [expanded, setExpanded] = React59.useState(false);
12153
+ const [expanded, setExpanded] = React60.useState(false);
11909
12154
  const isUser = m.role === "user";
11910
12155
  const raw = m.text || "";
11911
12156
  const clamped = !expanded && !m.streaming ? clampText(raw, ctx.maxVisibleChars) : null;
11912
12157
  const body = clamped != null ? clamped : raw;
11913
12158
  const showMd = ctx.markdown && !isUser;
11914
- return /* @__PURE__ */ jsxs81("div", { className: "fdc-body", children: [
11915
- m.thinking && ctx.showThinking ? /* @__PURE__ */ jsx90(ThinkingBlock, { text: m.thinking, durationMs: m.thinkingMs, streaming: m.streaming && !m.text }) : null,
11916
- m.steps && m.steps.length && ctx.showSteps ? /* @__PURE__ */ jsx90(StepList, { steps: m.steps, defaultOpen: m.steps.some((s) => s.status === "running"), dense: true }) : null,
11917
- body ? /* @__PURE__ */ jsxs81("div", { className: "fdc-text" + (isUser ? " is-user" : ""), children: [
11918
- showMd ? /* @__PURE__ */ jsx90(Markdown, { source: body, headingOffset: 2, codeProps: { collapseAfter: 22 }, renderCitation: ctx.renderCitation }) : /* @__PURE__ */ jsx90("div", { className: "fdc-plain", children: body }),
11919
- m.streaming ? /* @__PURE__ */ jsx90("span", { className: "fdc-caret", "aria-hidden": "true" }) : null
12159
+ return /* @__PURE__ */ jsxs82("div", { className: "fdc-body", children: [
12160
+ m.thinking && ctx.showThinking ? /* @__PURE__ */ jsx91(ThinkingBlock, { text: m.thinking, durationMs: m.thinkingMs, streaming: m.streaming && !m.text }) : null,
12161
+ m.steps && m.steps.length && ctx.showSteps ? /* @__PURE__ */ jsx91(StepList, { steps: m.steps, defaultOpen: m.steps.some((s) => s.status === "running"), dense: true }) : null,
12162
+ body ? /* @__PURE__ */ jsxs82("div", { className: "fdc-text" + (isUser ? " is-user" : ""), children: [
12163
+ showMd ? /* @__PURE__ */ jsx91(Markdown, { source: body, headingOffset: 2, codeProps: { collapseAfter: 22 }, renderCitation: ctx.renderCitation }) : /* @__PURE__ */ jsx91("div", { className: "fdc-plain", children: body }),
12164
+ m.streaming ? /* @__PURE__ */ jsx91("span", { className: "fdc-caret", "aria-hidden": "true" }) : null
11920
12165
  ] }) : null,
11921
- clamped != null ? /* @__PURE__ */ jsxs81("button", { type: "button", className: "fdc-more", onClick: () => setExpanded(true), children: [
11922
- /* @__PURE__ */ jsx90("i", { className: "ph ph-caret-down", "aria-hidden": "true" }),
12166
+ clamped != null ? /* @__PURE__ */ jsxs82("button", { type: "button", className: "fdc-more", onClick: () => setExpanded(true), children: [
12167
+ /* @__PURE__ */ jsx91("i", { className: "ph ph-caret-down", "aria-hidden": "true" }),
11923
12168
  "Show more",
11924
- /* @__PURE__ */ jsx90("span", { className: "fdc-more-len fd-tabular", children: raw.length < 2e3 ? raw.length.toLocaleString() + " characters" : Math.round(raw.length / 100) / 10 + "k characters" })
11925
- ] }) : expanded && ctx.maxVisibleChars && raw.length > ctx.maxVisibleChars ? /* @__PURE__ */ jsxs81("button", { type: "button", className: "fdc-more", onClick: () => setExpanded(false), children: [
11926
- /* @__PURE__ */ jsx90("i", { className: "ph ph-caret-up", "aria-hidden": "true" }),
12169
+ /* @__PURE__ */ jsx91("span", { className: "fdc-more-len fd-tabular", children: raw.length < 2e3 ? raw.length.toLocaleString() + " characters" : Math.round(raw.length / 100) / 10 + "k characters" })
12170
+ ] }) : expanded && ctx.maxVisibleChars && raw.length > ctx.maxVisibleChars ? /* @__PURE__ */ jsxs82("button", { type: "button", className: "fdc-more", onClick: () => setExpanded(false), children: [
12171
+ /* @__PURE__ */ jsx91("i", { className: "ph ph-caret-up", "aria-hidden": "true" }),
11927
12172
  "Show less"
11928
12173
  ] }) : null,
11929
- m.attachments && m.attachments.length ? /* @__PURE__ */ jsx90(FileGrid, { files: m.attachments, onOpen: ctx.onOpenAttachment, tiles: true, maxHeight: ctx.attachmentHeight || 220, compact: ctx.narrow }) : null,
11930
- m.packet ? /* @__PURE__ */ jsx90(
12174
+ m.attachments && m.attachments.length ? /* @__PURE__ */ jsx91(FileGrid, { files: m.attachments, onOpen: ctx.onOpenAttachment, tiles: true, maxHeight: ctx.attachmentHeight || 220, compact: ctx.narrow }) : null,
12175
+ m.packet ? /* @__PURE__ */ jsx91(
11931
12176
  PacketCard,
11932
12177
  {
11933
12178
  packet: m.packet,
@@ -11937,44 +12182,44 @@ function MessageBody({ message: m, ctx }) {
11937
12182
  applied: ctx.appliedPackets && ctx.appliedPackets[m.id]
11938
12183
  }
11939
12184
  ) : null,
11940
- m.citations && m.citations.length ? /* @__PURE__ */ jsx90(Citations, { items: m.citations, onOpen: ctx.onOpenCitation }) : null,
11941
- m.working ? /* @__PURE__ */ jsxs81("div", { className: "fdc-working", role: "status", children: [
11942
- /* @__PURE__ */ jsxs81("span", { className: "fdc-dots", "aria-hidden": "true", children: [
11943
- /* @__PURE__ */ jsx90("span", {}),
11944
- /* @__PURE__ */ jsx90("span", {}),
11945
- /* @__PURE__ */ jsx90("span", {})
12185
+ m.citations && m.citations.length ? /* @__PURE__ */ jsx91(Citations, { items: m.citations, onOpen: ctx.onOpenCitation }) : null,
12186
+ m.working ? /* @__PURE__ */ jsxs82("div", { className: "fdc-working", role: "status", children: [
12187
+ /* @__PURE__ */ jsxs82("span", { className: "fdc-dots", "aria-hidden": "true", children: [
12188
+ /* @__PURE__ */ jsx91("span", {}),
12189
+ /* @__PURE__ */ jsx91("span", {}),
12190
+ /* @__PURE__ */ jsx91("span", {})
11946
12191
  ] }),
11947
- /* @__PURE__ */ jsxs81("span", { className: "fdc-working-label", children: [
12192
+ /* @__PURE__ */ jsxs82("span", { className: "fdc-working-label", children: [
11948
12193
  m.resumed ? "Resuming" : "Working",
11949
- m.job && m.job.status ? /* @__PURE__ */ jsxs81("span", { className: "fdc-working-job", children: [
12194
+ m.job && m.job.status ? /* @__PURE__ */ jsxs82("span", { className: "fdc-working-job", children: [
11950
12195
  " \xB7 ",
11951
12196
  m.job.status
11952
12197
  ] }) : null,
11953
- m.job && m.job.detail ? /* @__PURE__ */ jsxs81("span", { className: "fdc-working-job", children: [
12198
+ m.job && m.job.detail ? /* @__PURE__ */ jsxs82("span", { className: "fdc-working-job", children: [
11954
12199
  " \xB7 ",
11955
12200
  m.job.detail
11956
12201
  ] }) : null
11957
12202
  ] }),
11958
- m.jobId ? /* @__PURE__ */ jsx90("span", { className: "fdc-working-id fd-mono", children: String(m.jobId).slice(0, 12) }) : null
12203
+ m.jobId ? /* @__PURE__ */ jsx91("span", { className: "fdc-working-id fd-mono", children: String(m.jobId).slice(0, 12) }) : null
11959
12204
  ] }) : null,
11960
- m.stopped ? /* @__PURE__ */ jsxs81("div", { className: "fdc-stopped", children: [
11961
- /* @__PURE__ */ jsx90("i", { className: "ph ph-stop-circle", "aria-hidden": "true" }),
12205
+ m.stopped ? /* @__PURE__ */ jsxs82("div", { className: "fdc-stopped", children: [
12206
+ /* @__PURE__ */ jsx91("i", { className: "ph ph-stop-circle", "aria-hidden": "true" }),
11962
12207
  "Stopped"
11963
12208
  ] }) : null,
11964
- m.error ? /* @__PURE__ */ jsxs81("div", { className: "fdc-error", role: "alert", children: [
11965
- /* @__PURE__ */ jsx90("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
11966
- /* @__PURE__ */ jsx90("span", { className: "fdc-error-text", children: ctx.errorCopy ? ctx.errorCopy(m.error) : m.error }),
11967
- m.retryable && ctx.onRetry ? /* @__PURE__ */ jsxs81("button", { type: "button", className: "fdc-error-retry", onClick: ctx.onRetry, children: [
11968
- /* @__PURE__ */ jsx90("i", { className: "ph ph-arrow-clockwise", "aria-hidden": "true" }),
12209
+ m.error ? /* @__PURE__ */ jsxs82("div", { className: "fdc-error", role: "alert", children: [
12210
+ /* @__PURE__ */ jsx91("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
12211
+ /* @__PURE__ */ jsx91("span", { className: "fdc-error-text", children: ctx.errorCopy ? ctx.errorCopy(m.error) : m.error }),
12212
+ m.retryable && ctx.onRetry ? /* @__PURE__ */ jsxs82("button", { type: "button", className: "fdc-error-retry", onClick: ctx.onRetry, children: [
12213
+ /* @__PURE__ */ jsx91("i", { className: "ph ph-arrow-clockwise", "aria-hidden": "true" }),
11969
12214
  "Retry"
11970
12215
  ] }) : null
11971
12216
  ] }) : null
11972
12217
  ] });
11973
12218
  }
11974
12219
  function useCopyRun() {
11975
- const [done, setDone] = React59.useState(false);
11976
- const t = React59.useRef(null);
11977
- React59.useEffect(() => () => {
12220
+ const [done, setDone] = React60.useState(false);
12221
+ const t = React60.useRef(null);
12222
+ React60.useEffect(() => () => {
11978
12223
  if (t.current) clearTimeout(t.current);
11979
12224
  }, []);
11980
12225
  return [done, (text) => {
@@ -11994,16 +12239,16 @@ function RunActions({ group, ctx }) {
11994
12239
  const isAssistant = group.role === "assistant";
11995
12240
  const fb = last.feedback;
11996
12241
  if (!ctx.messageActions) return null;
11997
- return /* @__PURE__ */ jsxs81("div", { className: "fdc-actions", role: "group", "aria-label": "Message actions", children: [
11998
- /* @__PURE__ */ jsxs81("button", { type: "button", className: "fdc-act" + (copied ? " is-done" : ""), onClick: () => copy(markdownToText(text)), "aria-label": "Copy message", children: [
11999
- /* @__PURE__ */ jsx90("i", { className: "ph ph-" + (copied ? "check" : "copy"), "aria-hidden": "true" }),
12000
- /* @__PURE__ */ jsx90("span", { className: "fdc-act-label", children: copied ? "Copied" : "Copy" })
12242
+ return /* @__PURE__ */ jsxs82("div", { className: "fdc-actions", role: "group", "aria-label": "Message actions", children: [
12243
+ /* @__PURE__ */ jsxs82("button", { type: "button", className: "fdc-act" + (copied ? " is-done" : ""), onClick: () => copy(markdownToText(text)), "aria-label": "Copy message", children: [
12244
+ /* @__PURE__ */ jsx91("i", { className: "ph ph-" + (copied ? "check" : "copy"), "aria-hidden": "true" }),
12245
+ /* @__PURE__ */ jsx91("span", { className: "fdc-act-label", children: copied ? "Copied" : "Copy" })
12001
12246
  ] }),
12002
- isAssistant && ctx.onRetry ? /* @__PURE__ */ jsx90("button", { type: "button", className: "fdc-act", onClick: ctx.onRetry, "aria-label": "Retry this turn", children: /* @__PURE__ */ jsx90("i", { className: "ph ph-arrow-clockwise", "aria-hidden": "true" }) }) : null,
12003
- group.role === "user" && ctx.onEdit ? /* @__PURE__ */ jsx90("button", { type: "button", className: "fdc-act", onClick: () => ctx.onEdit(last), "aria-label": "Edit and resend", children: /* @__PURE__ */ jsx90("i", { className: "ph ph-pencil-simple", "aria-hidden": "true" }) }) : null,
12004
- isAssistant && ctx.onFeedback ? /* @__PURE__ */ jsxs81(React59.Fragment, { children: [
12005
- /* @__PURE__ */ jsx90("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__ */ jsx90("i", { className: "ph ph-thumbs-up", "aria-hidden": "true" }) }),
12006
- /* @__PURE__ */ jsx90("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__ */ jsx90("i", { className: "ph ph-thumbs-down", "aria-hidden": "true" }) })
12247
+ isAssistant && ctx.onRetry ? /* @__PURE__ */ jsx91("button", { type: "button", className: "fdc-act", onClick: ctx.onRetry, "aria-label": "Retry this turn", children: /* @__PURE__ */ jsx91("i", { className: "ph ph-arrow-clockwise", "aria-hidden": "true" }) }) : null,
12248
+ group.role === "user" && ctx.onEdit ? /* @__PURE__ */ jsx91("button", { type: "button", className: "fdc-act", onClick: () => ctx.onEdit(last), "aria-label": "Edit and resend", children: /* @__PURE__ */ jsx91("i", { className: "ph ph-pencil-simple", "aria-hidden": "true" }) }) : null,
12249
+ isAssistant && ctx.onFeedback ? /* @__PURE__ */ jsxs82(React60.Fragment, { children: [
12250
+ /* @__PURE__ */ jsx91("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__ */ jsx91("i", { className: "ph ph-thumbs-up", "aria-hidden": "true" }) }),
12251
+ /* @__PURE__ */ jsx91("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__ */ jsx91("i", { className: "ph ph-thumbs-down", "aria-hidden": "true" }) })
12007
12252
  ] }) : null,
12008
12253
  ctx.extraActions ? ctx.extraActions(group) : null
12009
12254
  ] });
@@ -12013,22 +12258,22 @@ function ChatTurn({ group, ctx }) {
12013
12258
  const name = isUser ? ctx.userName : group.author || ctx.assistantName;
12014
12259
  const avatar = isUser ? ctx.userAvatar : ctx.assistantAvatar;
12015
12260
  const stamp = group.messages[0].timestamp;
12016
- return /* @__PURE__ */ jsxs81("article", { className: "fdc-turn is-" + group.role, "aria-label": String(name) + (stamp ? " at " + formatClock(stamp) : ""), children: [
12017
- /* @__PURE__ */ jsxs81("div", { className: "fdc-turn-head", children: [
12018
- ctx.showAvatars ? /* @__PURE__ */ jsx90("span", { className: "fdc-avatar is-" + group.role, "aria-hidden": "true", children: avatar ? /* @__PURE__ */ jsx90("img", { src: avatar, alt: "" }) : isUser ? /* @__PURE__ */ jsx90("span", { className: "fdc-avatar-txt", children: (name || "You").slice(0, 1).toUpperCase() }) : /* @__PURE__ */ jsx90("i", { className: "ph ph-" + (ctx.assistantIcon || "sparkle") }) }) : null,
12019
- /* @__PURE__ */ jsx90("span", { className: "fdc-who", children: name }),
12020
- stamp ? /* @__PURE__ */ jsx90(RelativeTime, { className: "fdc-when", value: stamp }) : null,
12021
- group.messages.some((m) => m.model) ? /* @__PURE__ */ jsx90("span", { className: "fdc-turn-model", children: group.messages.find((m) => m.model).model }) : null
12261
+ return /* @__PURE__ */ jsxs82("article", { className: "fdc-turn is-" + group.role, "aria-label": String(name) + (stamp ? " at " + formatClock(stamp) : ""), children: [
12262
+ /* @__PURE__ */ jsxs82("div", { className: "fdc-turn-head", children: [
12263
+ ctx.showAvatars ? /* @__PURE__ */ jsx91("span", { className: "fdc-avatar is-" + group.role, "aria-hidden": "true", children: avatar ? /* @__PURE__ */ jsx91("img", { src: avatar, alt: "" }) : isUser ? /* @__PURE__ */ jsx91("span", { className: "fdc-avatar-txt", children: (name || "You").slice(0, 1).toUpperCase() }) : /* @__PURE__ */ jsx91("i", { className: "ph ph-" + (ctx.assistantIcon || "sparkle") }) }) : null,
12264
+ /* @__PURE__ */ jsx91("span", { className: "fdc-who", children: name }),
12265
+ stamp ? /* @__PURE__ */ jsx91(RelativeTime, { className: "fdc-when", value: stamp }) : null,
12266
+ group.messages.some((m) => m.model) ? /* @__PURE__ */ jsx91("span", { className: "fdc-turn-model", children: group.messages.find((m) => m.model).model }) : null
12022
12267
  ] }),
12023
- /* @__PURE__ */ jsxs81("div", { className: "fdc-turn-body", children: [
12024
- group.messages.map((m) => /* @__PURE__ */ jsx90("div", { className: "fdc-msg" + (m.pending ? " is-pending" : ""), children: /* @__PURE__ */ jsx90(MessageBody, { message: m, ctx }) }, m.id)),
12025
- /* @__PURE__ */ jsx90(RunActions, { group, ctx })
12268
+ /* @__PURE__ */ jsxs82("div", { className: "fdc-turn-body", children: [
12269
+ group.messages.map((m) => /* @__PURE__ */ jsx91("div", { className: "fdc-msg" + (m.pending ? " is-pending" : ""), children: /* @__PURE__ */ jsx91(MessageBody, { message: m, ctx }) }, m.id)),
12270
+ /* @__PURE__ */ jsx91(RunActions, { group, ctx })
12026
12271
  ] })
12027
12272
  ] });
12028
12273
  }
12029
12274
 
12030
12275
  // src/components/chat/ChatTranscript.tsx
12031
- import { jsx as jsx91, jsxs as jsxs82 } from "react/jsx-runtime";
12276
+ import { jsx as jsx92, jsxs as jsxs83 } from "react/jsx-runtime";
12032
12277
  var GROUP_WINDOW = 6e4;
12033
12278
  var STICK_PX = 100;
12034
12279
  function groupMessages(list) {
@@ -12061,25 +12306,25 @@ function dayLabel(key) {
12061
12306
  }
12062
12307
  function Suggestions({ items = [], onPick }) {
12063
12308
  if (!items.length) return null;
12064
- return /* @__PURE__ */ jsx91("div", { className: "fdc-suggest", children: items.map((s, i) => {
12309
+ return /* @__PURE__ */ jsx92("div", { className: "fdc-suggest", children: items.map((s, i) => {
12065
12310
  const it = typeof s === "string" ? { label: s, text: s } : s;
12066
- return /* @__PURE__ */ jsxs82("button", { type: "button", className: "fdc-suggest-item", onClick: () => onPick && onPick(it.text || it.label), children: [
12067
- it.icon ? /* @__PURE__ */ jsx91("i", { className: "ph ph-" + it.icon, "aria-hidden": "true" }) : null,
12068
- /* @__PURE__ */ jsxs82("span", { className: "fdc-suggest-text", children: [
12069
- /* @__PURE__ */ jsx91("span", { className: "fdc-suggest-label", children: it.label }),
12070
- it.description ? /* @__PURE__ */ jsx91("span", { className: "fdc-suggest-desc", children: it.description }) : null
12311
+ return /* @__PURE__ */ jsxs83("button", { type: "button", className: "fdc-suggest-item", onClick: () => onPick && onPick(it.text || it.label), children: [
12312
+ it.icon ? /* @__PURE__ */ jsx92("i", { className: "ph ph-" + it.icon, "aria-hidden": "true" }) : null,
12313
+ /* @__PURE__ */ jsxs83("span", { className: "fdc-suggest-text", children: [
12314
+ /* @__PURE__ */ jsx92("span", { className: "fdc-suggest-label", children: it.label }),
12315
+ it.description ? /* @__PURE__ */ jsx92("span", { className: "fdc-suggest-desc", children: it.description }) : null
12071
12316
  ] }),
12072
- /* @__PURE__ */ jsx91("i", { className: "ph ph-arrow-up-right fdc-suggest-go", "aria-hidden": "true" })
12317
+ /* @__PURE__ */ jsx92("i", { className: "ph ph-arrow-up-right fdc-suggest-go", "aria-hidden": "true" })
12073
12318
  ] }, it.id || i);
12074
12319
  }) });
12075
12320
  }
12076
12321
  function LoadingTurns() {
12077
- return /* @__PURE__ */ jsx91("div", { className: "fdc-skel", "aria-hidden": "true", children: [0, 1].map((i) => /* @__PURE__ */ jsxs82("div", { className: "fdc-skel-turn", children: [
12078
- /* @__PURE__ */ jsx91("div", { className: "fd-skel fd-skel-circle", style: { width: 22, height: 22 } }),
12079
- /* @__PURE__ */ jsxs82("div", { className: "fdc-skel-lines", children: [
12080
- /* @__PURE__ */ jsx91("div", { className: "fd-skel", style: { width: i ? "62%" : "44%", height: 11 } }),
12081
- /* @__PURE__ */ jsx91("div", { className: "fd-skel", style: { width: i ? "94%" : "78%", height: 11 } }),
12082
- /* @__PURE__ */ jsx91("div", { className: "fd-skel", style: { width: i ? "71%" : "56%", height: 11 } })
12322
+ return /* @__PURE__ */ jsx92("div", { className: "fdc-skel", "aria-hidden": "true", children: [0, 1].map((i) => /* @__PURE__ */ jsxs83("div", { className: "fdc-skel-turn", children: [
12323
+ /* @__PURE__ */ jsx92("div", { className: "fd-skel fd-skel-circle", style: { width: 22, height: 22 } }),
12324
+ /* @__PURE__ */ jsxs83("div", { className: "fdc-skel-lines", children: [
12325
+ /* @__PURE__ */ jsx92("div", { className: "fd-skel", style: { width: i ? "62%" : "44%", height: 11 } }),
12326
+ /* @__PURE__ */ jsx92("div", { className: "fd-skel", style: { width: i ? "94%" : "78%", height: 11 } }),
12327
+ /* @__PURE__ */ jsx92("div", { className: "fd-skel", style: { width: i ? "71%" : "56%", height: 11 } })
12083
12328
  ] })
12084
12329
  ] }, i)) });
12085
12330
  }
@@ -12096,10 +12341,10 @@ function ChatTranscript({
12096
12341
  renderEmpty,
12097
12342
  className = ""
12098
12343
  }) {
12099
- const scroller = React60.useRef(null);
12100
- const stick = React60.useRef(true);
12101
- const [pill, setPill] = React60.useState(0);
12102
- const seen = React60.useRef(0);
12344
+ const scroller = React61.useRef(null);
12345
+ const stick = React61.useRef(true);
12346
+ const [pill, setPill] = React61.useState(0);
12347
+ const seen = React61.useRef(0);
12103
12348
  const toBottom = (smooth) => {
12104
12349
  const el = scroller.current;
12105
12350
  if (!el) return;
@@ -12118,7 +12363,7 @@ function ChatTranscript({
12118
12363
  seen.current = messages.length;
12119
12364
  }
12120
12365
  };
12121
- React60.useLayoutEffect(() => {
12366
+ React61.useLayoutEffect(() => {
12122
12367
  const el = scroller.current;
12123
12368
  if (!el) return;
12124
12369
  if (stick.current) {
@@ -12126,7 +12371,7 @@ function ChatTranscript({
12126
12371
  seen.current = messages.length;
12127
12372
  } else setPill(Math.max(0, messages.length - seen.current));
12128
12373
  }, [messages]);
12129
- React60.useEffect(() => {
12374
+ React61.useEffect(() => {
12130
12375
  const el = scroller.current;
12131
12376
  const inner = el && el.firstChild;
12132
12377
  if (!el || !inner || typeof ResizeObserver === "undefined") return;
@@ -12136,38 +12381,38 @@ function ChatTranscript({
12136
12381
  ro.observe(inner);
12137
12382
  return () => ro.disconnect();
12138
12383
  }, []);
12139
- const groups = React60.useMemo(() => groupMessages(messages), [messages]);
12384
+ const groups = React61.useMemo(() => groupMessages(messages), [messages]);
12140
12385
  const empty = !messages.length && status === "ready";
12141
- return /* @__PURE__ */ jsxs82("div", { className: ["fdc-scroll", className].filter(Boolean).join(" "), ref: scroller, onScroll, children: [
12142
- /* @__PURE__ */ jsxs82("div", { className: "fdc-log", role: "log", "aria-label": "Conversation", children: [
12143
- status === "loading" || status === "resolving" ? /* @__PURE__ */ jsx91(LoadingTurns, {}) : null,
12144
- status === "disconnected" ? /* @__PURE__ */ jsxs82("div", { className: "fdc-dead", children: [
12145
- /* @__PURE__ */ jsx91("span", { className: "fdc-dead-icon", children: /* @__PURE__ */ jsx91("i", { className: "ph ph-plugs", "aria-hidden": "true" }) }),
12146
- /* @__PURE__ */ jsx91("h3", { className: "fdc-dead-title", children: ctx.deadTitle || "The assistant isn\u2019t reachable" }),
12147
- /* @__PURE__ */ jsx91("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." }),
12148
- ctx.onReconnect ? /* @__PURE__ */ jsxs82("button", { type: "button", className: "fd-btn fd-btn-secondary fd-btn-sm", onClick: ctx.onReconnect, children: [
12149
- /* @__PURE__ */ jsx91("i", { className: "ph ph-arrow-clockwise", "aria-hidden": "true" }),
12386
+ return /* @__PURE__ */ jsxs83("div", { className: ["fdc-scroll", className].filter(Boolean).join(" "), ref: scroller, onScroll, children: [
12387
+ /* @__PURE__ */ jsxs83("div", { className: "fdc-log", role: "log", "aria-label": "Conversation", children: [
12388
+ status === "loading" || status === "resolving" ? /* @__PURE__ */ jsx92(LoadingTurns, {}) : null,
12389
+ status === "disconnected" ? /* @__PURE__ */ jsxs83("div", { className: "fdc-dead", children: [
12390
+ /* @__PURE__ */ jsx92("span", { className: "fdc-dead-icon", children: /* @__PURE__ */ jsx92("i", { className: "ph ph-plugs", "aria-hidden": "true" }) }),
12391
+ /* @__PURE__ */ jsx92("h3", { className: "fdc-dead-title", children: ctx.deadTitle || "The assistant isn\u2019t reachable" }),
12392
+ /* @__PURE__ */ jsx92("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." }),
12393
+ ctx.onReconnect ? /* @__PURE__ */ jsxs83("button", { type: "button", className: "fd-btn fd-btn-secondary fd-btn-sm", onClick: ctx.onReconnect, children: [
12394
+ /* @__PURE__ */ jsx92("i", { className: "ph ph-arrow-clockwise", "aria-hidden": "true" }),
12150
12395
  "Try again"
12151
12396
  ] }) : null
12152
12397
  ] }) : null,
12153
- empty ? renderEmpty ? renderEmpty() : /* @__PURE__ */ jsxs82("div", { className: "fdc-empty", children: [
12154
- /* @__PURE__ */ jsx91("span", { className: "fdc-empty-icon", children: /* @__PURE__ */ jsx91("i", { className: "ph ph-" + emptyIcon, "aria-hidden": "true" }) }),
12155
- /* @__PURE__ */ jsx91("h3", { className: "fdc-empty-title", children: emptyTitle }),
12156
- emptyDescription ? /* @__PURE__ */ jsx91("p", { className: "fdc-empty-body", children: emptyDescription }) : null,
12157
- /* @__PURE__ */ jsx91(Suggestions, { items: suggestions, onPick })
12398
+ empty ? renderEmpty ? renderEmpty() : /* @__PURE__ */ jsxs83("div", { className: "fdc-empty", children: [
12399
+ /* @__PURE__ */ jsx92("span", { className: "fdc-empty-icon", children: /* @__PURE__ */ jsx92("i", { className: "ph ph-" + emptyIcon, "aria-hidden": "true" }) }),
12400
+ /* @__PURE__ */ jsx92("h3", { className: "fdc-empty-title", children: emptyTitle }),
12401
+ emptyDescription ? /* @__PURE__ */ jsx92("p", { className: "fdc-empty-body", children: emptyDescription }) : null,
12402
+ /* @__PURE__ */ jsx92(Suggestions, { items: suggestions, onPick })
12158
12403
  ] }) : null,
12159
12404
  groups.map((g, i) => {
12160
12405
  const prev = groups[i - 1];
12161
12406
  const k = dayKey(g.messages[0].timestamp);
12162
12407
  const showDay = !!k && (!prev || dayKey(prev.messages[0].timestamp) !== k);
12163
- return /* @__PURE__ */ jsxs82(React60.Fragment, { children: [
12164
- showDay ? /* @__PURE__ */ jsx91("div", { className: "fdc-day", children: /* @__PURE__ */ jsx91("span", { children: dayLabel(k) }) }) : null,
12165
- /* @__PURE__ */ jsx91(ChatTurn, { group: g, ctx })
12408
+ return /* @__PURE__ */ jsxs83(React61.Fragment, { children: [
12409
+ showDay ? /* @__PURE__ */ jsx92("div", { className: "fdc-day", children: /* @__PURE__ */ jsx92("span", { children: dayLabel(k) }) }) : null,
12410
+ /* @__PURE__ */ jsx92(ChatTurn, { group: g, ctx })
12166
12411
  ] }, g.key || i);
12167
12412
  })
12168
12413
  ] }),
12169
- pill ? /* @__PURE__ */ jsxs82("button", { type: "button", className: "fdc-pill", onClick: () => toBottom(true), children: [
12170
- /* @__PURE__ */ jsx91("i", { className: "ph ph-arrow-down", "aria-hidden": "true" }),
12414
+ pill ? /* @__PURE__ */ jsxs83("button", { type: "button", className: "fdc-pill", onClick: () => toBottom(true), children: [
12415
+ /* @__PURE__ */ jsx92("i", { className: "ph ph-arrow-down", "aria-hidden": "true" }),
12171
12416
  pill,
12172
12417
  " new message",
12173
12418
  pill === 1 ? "" : "s"
@@ -12177,8 +12422,8 @@ function ChatTranscript({
12177
12422
  var TranscriptKit = { groupMessages };
12178
12423
 
12179
12424
  // src/components/chat/ChatComposer.tsx
12180
- import * as React61 from "react";
12181
- import { jsx as jsx92, jsxs as jsxs83 } from "react/jsx-runtime";
12425
+ import * as React62 from "react";
12426
+ import { jsx as jsx93, jsxs as jsxs84 } from "react/jsx-runtime";
12182
12427
  function ChatComposer({
12183
12428
  onSubmit,
12184
12429
  onStop,
@@ -12205,17 +12450,17 @@ function ChatComposer({
12205
12450
  onReject,
12206
12451
  onOpenAttachment
12207
12452
  }) {
12208
- const [text, setText] = React61.useState(draft || "");
12209
- const [trigger, setTrigger] = React61.useState(null);
12210
- const [mentionItems, setMentionItems] = React61.useState([]);
12211
- const [listening, setListening] = React61.useState(false);
12212
- const [notice, setNotice] = React61.useState(null);
12213
- const editor = React61.useRef(null);
12214
- const wrap = React61.useRef(null);
12215
- const stopVoice = React61.useRef(null);
12453
+ const [text, setText] = React62.useState(draft || "");
12454
+ const [trigger, setTrigger] = React62.useState(null);
12455
+ const [mentionItems, setMentionItems] = React62.useState([]);
12456
+ const [listening, setListening] = React62.useState(false);
12457
+ const [notice, setNotice] = React62.useState(null);
12458
+ const editor = React62.useRef(null);
12459
+ const wrap = React62.useRef(null);
12460
+ const stopVoice = React62.useRef(null);
12216
12461
  const staged = useStagedFiles(fileUploadHandler, { onError: () => {
12217
12462
  } });
12218
- React61.useEffect(() => {
12463
+ React62.useEffect(() => {
12219
12464
  if (draft != null && draft !== text) setText(draft);
12220
12465
  }, [draft]);
12221
12466
  const change = (v) => {
@@ -12251,7 +12496,7 @@ function ChatComposer({
12251
12496
  e.preventDefault();
12252
12497
  staged.add(found.files);
12253
12498
  };
12254
- React61.useEffect(() => {
12499
+ React62.useEffect(() => {
12255
12500
  if (!trigger || trigger.type !== "mention" || !mentionSources) {
12256
12501
  setMentionItems([]);
12257
12502
  return;
@@ -12269,7 +12514,7 @@ function ChatComposer({
12269
12514
  const q = (trigger.query || "").toLowerCase();
12270
12515
  setMentionItems(mentionSources.filter((m) => !q || (m.label + " " + (m.description || "")).toLowerCase().includes(q)));
12271
12516
  }, [trigger, mentionSources]);
12272
- const slashItems = React61.useMemo(() => {
12517
+ const slashItems = React62.useMemo(() => {
12273
12518
  if (!trigger || trigger.type !== "slash" || !slashCommands) return [];
12274
12519
  const q = (trigger.query || "").toLowerCase();
12275
12520
  return slashCommands.filter((c) => !q || (c.id + " " + c.label + " " + (c.description || "")).toLowerCase().includes(q));
@@ -12283,7 +12528,7 @@ function ChatComposer({
12283
12528
  description: it.description,
12284
12529
  icon: it.icon,
12285
12530
  meta: mention.meta,
12286
- shortcut: slash.shortcut ? /* @__PURE__ */ jsx92(KeyHint, { keys: slash.shortcut, size: "sm" }) : void 0,
12531
+ shortcut: slash.shortcut ? /* @__PURE__ */ jsx93(KeyHint, { keys: slash.shortcut, size: "sm" }) : void 0,
12287
12532
  onSelect: () => {
12288
12533
  const insert = trigger.type === "slash" ? slash.immediate ? "/" + slash.id : "/" + slash.id + " " : "@" + (mention.value || mention.label) + " ";
12289
12534
  editor.current && editor.current.replaceRange(trigger.from, trigger.to, insert);
@@ -12342,14 +12587,14 @@ function ChatComposer({
12342
12587
  stopVoice.current = typeof res === "function" ? res : () => {
12343
12588
  };
12344
12589
  };
12345
- return /* @__PURE__ */ jsxs83("div", { className: "fdc-composer" + (disabled ? " is-disabled" : "") + (narrow ? " is-narrow" : ""), children: [
12346
- queue.length ? /* @__PURE__ */ jsx92("div", { className: "fdc-queue", "aria-label": "Queued messages", children: queue.map((q) => /* @__PURE__ */ jsxs83("div", { className: "fdc-queue-row", children: [
12347
- /* @__PURE__ */ jsx92("i", { className: "ph ph-clock-countdown", "aria-hidden": "true" }),
12348
- /* @__PURE__ */ jsx92("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)" : "") }),
12349
- onRemoveQueued ? /* @__PURE__ */ jsx92("button", { type: "button", className: "fdc-queue-x", onClick: () => onRemoveQueued(q.id), "aria-label": "Remove queued message", children: /* @__PURE__ */ jsx92("i", { className: "ph ph-x", "aria-hidden": "true" }) }) : null
12590
+ return /* @__PURE__ */ jsxs84("div", { className: "fdc-composer" + (disabled ? " is-disabled" : "") + (narrow ? " is-narrow" : ""), children: [
12591
+ queue.length ? /* @__PURE__ */ jsx93("div", { className: "fdc-queue", "aria-label": "Queued messages", children: queue.map((q) => /* @__PURE__ */ jsxs84("div", { className: "fdc-queue-row", children: [
12592
+ /* @__PURE__ */ jsx93("i", { className: "ph ph-clock-countdown", "aria-hidden": "true" }),
12593
+ /* @__PURE__ */ jsx93("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)" : "") }),
12594
+ onRemoveQueued ? /* @__PURE__ */ jsx93("button", { type: "button", className: "fdc-queue-x", onClick: () => onRemoveQueued(q.id), "aria-label": "Remove queued message", children: /* @__PURE__ */ jsx93("i", { className: "ph ph-x", "aria-hidden": "true" }) }) : null
12350
12595
  ] }, q.id)) }) : null,
12351
12596
  sessionBar,
12352
- /* @__PURE__ */ jsx92(
12597
+ /* @__PURE__ */ jsx93(
12353
12598
  Dropzone,
12354
12599
  {
12355
12600
  className: "fdc-field",
@@ -12363,9 +12608,9 @@ function ChatComposer({
12363
12608
  disabled: !fileUploadHandler || disabled,
12364
12609
  label: "Drop to attach",
12365
12610
  hint: acceptFiles ? acceptFiles.replace(/,/g, " \xB7 ") : void 0,
12366
- children: /* @__PURE__ */ jsxs83("div", { ref: wrap, className: "fdc-field-inner", children: [
12367
- staged.items.length ? /* @__PURE__ */ jsx92("div", { className: "fdc-staged", children: /* @__PURE__ */ jsx92(FileStrip, { files: staged.items, size: narrow ? 60 : 68, onRemove: staged.remove, onRetry: staged.retry, onOpen: onOpenAttachment }) }) : null,
12368
- /* @__PURE__ */ jsx92(
12611
+ children: /* @__PURE__ */ jsxs84("div", { ref: wrap, className: "fdc-field-inner", children: [
12612
+ staged.items.length ? /* @__PURE__ */ jsx93("div", { className: "fdc-staged", children: /* @__PURE__ */ jsx93(FileStrip, { files: staged.items, size: narrow ? 60 : 68, onRemove: staged.remove, onRetry: staged.retry, onOpen: onOpenAttachment }) }) : null,
12613
+ /* @__PURE__ */ jsx93(
12369
12614
  MarkdownEditor,
12370
12615
  {
12371
12616
  ref: editor,
@@ -12384,33 +12629,33 @@ function ChatComposer({
12384
12629
  ariaLabel: "Message"
12385
12630
  }
12386
12631
  ),
12387
- /* @__PURE__ */ jsxs83("div", { className: "fdc-tools", children: [
12388
- fileUploadHandler ? /* @__PURE__ */ jsx92(FilePickButton, { onFiles: staged.add, onReject: (r) => flash(r[0].message), accept: acceptFiles, maxFileSize, label: "Attach files", icon: "plus" }) : null,
12389
- voiceHandler ? /* @__PURE__ */ jsx92("button", { type: "button", className: "fd-attachbtn" + (listening ? " is-live" : ""), onClick: voice, "aria-pressed": listening, "aria-label": listening ? "Stop dictation" : "Dictate", children: /* @__PURE__ */ jsx92("i", { className: "ph ph-" + (listening ? "waveform" : "microphone"), "aria-hidden": "true" }) }) : null,
12632
+ /* @__PURE__ */ jsxs84("div", { className: "fdc-tools", children: [
12633
+ fileUploadHandler ? /* @__PURE__ */ jsx93(FilePickButton, { onFiles: staged.add, onReject: (r) => flash(r[0].message), accept: acceptFiles, maxFileSize, label: "Attach files", icon: "plus" }) : null,
12634
+ voiceHandler ? /* @__PURE__ */ jsx93("button", { type: "button", className: "fd-attachbtn" + (listening ? " is-live" : ""), onClick: voice, "aria-pressed": listening, "aria-label": listening ? "Stop dictation" : "Dictate", children: /* @__PURE__ */ jsx93("i", { className: "ph ph-" + (listening ? "waveform" : "microphone"), "aria-hidden": "true" }) }) : null,
12390
12635
  toolbarExtras,
12391
- /* @__PURE__ */ jsx92("span", { className: "fdc-tools-gap" }),
12392
- maxLength && text.length > maxLength * 0.6 ? /* @__PURE__ */ jsxs83("span", { className: "fdc-count fd-tabular" + (text.length > maxLength * 0.95 ? " is-hot" : ""), children: [
12636
+ /* @__PURE__ */ jsx93("span", { className: "fdc-tools-gap" }),
12637
+ maxLength && text.length > maxLength * 0.6 ? /* @__PURE__ */ jsxs84("span", { className: "fdc-count fd-tabular" + (text.length > maxLength * 0.95 ? " is-hot" : ""), children: [
12393
12638
  text.length,
12394
12639
  "/",
12395
12640
  maxLength
12396
12641
  ] }) : null,
12397
- busy ? /* @__PURE__ */ jsxs83("button", { type: "button", className: "fdc-stop", onClick: onStop, "aria-label": "Stop generating", children: [
12398
- /* @__PURE__ */ jsx92("i", { className: "ph ph-stop-circle", "aria-hidden": "true" }),
12399
- /* @__PURE__ */ jsx92("span", { children: "Stop" })
12400
- ] }) : /* @__PURE__ */ jsxs83("button", { type: "button", className: "fdc-send", onClick: submit, disabled: !canSend, "aria-label": "Send message", children: [
12401
- /* @__PURE__ */ jsx92("i", { className: "ph ph-paper-plane-right", "aria-hidden": "true" }),
12402
- /* @__PURE__ */ jsx92("span", { className: "fdc-send-label", children: "Send" })
12642
+ busy ? /* @__PURE__ */ jsxs84("button", { type: "button", className: "fdc-stop", onClick: onStop, "aria-label": "Stop generating", children: [
12643
+ /* @__PURE__ */ jsx93("i", { className: "ph ph-stop-circle", "aria-hidden": "true" }),
12644
+ /* @__PURE__ */ jsx93("span", { children: "Stop" })
12645
+ ] }) : /* @__PURE__ */ jsxs84("button", { type: "button", className: "fdc-send", onClick: submit, disabled: !canSend, "aria-label": "Send message", children: [
12646
+ /* @__PURE__ */ jsx93("i", { className: "ph ph-paper-plane-right", "aria-hidden": "true" }),
12647
+ /* @__PURE__ */ jsx93("span", { className: "fdc-send-label", children: "Send" })
12403
12648
  ] })
12404
12649
  ] })
12405
12650
  ] })
12406
12651
  }
12407
12652
  ),
12408
- notice ? /* @__PURE__ */ jsxs83("div", { className: "fdc-notice", role: "status", children: [
12409
- /* @__PURE__ */ jsx92("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
12653
+ notice ? /* @__PURE__ */ jsxs84("div", { className: "fdc-notice", role: "status", children: [
12654
+ /* @__PURE__ */ jsx93("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
12410
12655
  notice
12411
12656
  ] }) : null,
12412
- hint && !notice ? /* @__PURE__ */ jsx92("div", { className: "fdc-hint", children: hint }) : null,
12413
- /* @__PURE__ */ jsx92(
12657
+ hint && !notice ? /* @__PURE__ */ jsx93("div", { className: "fdc-hint", children: hint }) : null,
12658
+ /* @__PURE__ */ jsx93(
12414
12659
  Popover,
12415
12660
  {
12416
12661
  open: menuOpen,
@@ -12424,12 +12669,12 @@ function ChatComposer({
12424
12669
  returnFocus: false,
12425
12670
  closeOnOutside: true,
12426
12671
  label: trigger && trigger.type === "slash" ? "Commands" : "Mentions",
12427
- children: /* @__PURE__ */ jsx92(
12672
+ children: /* @__PURE__ */ jsx93(
12428
12673
  Menu,
12429
12674
  {
12430
12675
  items: menuItems,
12431
12676
  autoFocus: false,
12432
- header: /* @__PURE__ */ jsx92("div", { className: "fd-pop-group", children: trigger && trigger.type === "slash" ? "Commands" : "Attach context" }),
12677
+ header: /* @__PURE__ */ jsx93("div", { className: "fd-pop-group", children: trigger && trigger.type === "slash" ? "Commands" : "Attach context" }),
12433
12678
  onClose: () => setTrigger(null)
12434
12679
  }
12435
12680
  )
@@ -12439,12 +12684,12 @@ function ChatComposer({
12439
12684
  }
12440
12685
 
12441
12686
  // src/components/chat/ChatSessionBar.tsx
12442
- import * as React62 from "react";
12443
- import { jsx as jsx93, jsxs as jsxs84 } from "react/jsx-runtime";
12687
+ import * as React63 from "react";
12688
+ import { jsx as jsx94, jsxs as jsxs85 } from "react/jsx-runtime";
12444
12689
  var compact2 = meterFormats.compact;
12445
12690
  function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extras }) {
12446
- const [open2, setOpen] = React62.useState(false);
12447
- const anchor = React62.useRef(null);
12691
+ const [open2, setOpen] = React63.useState(false);
12692
+ const anchor = React63.useRef(null);
12448
12693
  const stats = sessionStats || null;
12449
12694
  const cu = contextUsage || null;
12450
12695
  const limits = usageLimits || null;
@@ -12459,9 +12704,9 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
12459
12704
  if (stats && stats.runningTasks) bits.push(stats.runningTasks + " running task" + (stats.runningTasks === 1 ? "" : "s"));
12460
12705
  if (cu) bits.push(pct + "% context");
12461
12706
  const expandable = !!(cu || limits);
12462
- return /* @__PURE__ */ jsxs84(React62.Fragment, { children: [
12463
- /* @__PURE__ */ jsxs84("div", { className: "fdc-bar", children: [
12464
- /* @__PURE__ */ jsxs84(
12707
+ return /* @__PURE__ */ jsxs85(React63.Fragment, { children: [
12708
+ /* @__PURE__ */ jsxs85("div", { className: "fdc-bar", children: [
12709
+ /* @__PURE__ */ jsxs85(
12465
12710
  "button",
12466
12711
  {
12467
12712
  type: "button",
@@ -12472,15 +12717,15 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
12472
12717
  "aria-expanded": expandable ? open2 : void 0,
12473
12718
  "aria-label": expandable ? "Usage details" : void 0,
12474
12719
  children: [
12475
- cu ? /* @__PURE__ */ jsx93("span", { className: "fdc-bar-mini", "aria-hidden": "true", children: /* @__PURE__ */ jsx93(SegmentedMeter, { total, segments: cu.segments, height: 4, showTotal: false }) }) : null,
12476
- /* @__PURE__ */ jsx93("span", { className: "fdc-bar-text", title: truncationTitle(bits.join(" \xB7 ")), children: bits.join(" \xB7 ") }),
12477
- expandable ? /* @__PURE__ */ jsx93("i", { className: "ph ph-caret-right fdc-bar-caret", "aria-hidden": "true" }) : null
12720
+ cu ? /* @__PURE__ */ jsx94("span", { className: "fdc-bar-mini", "aria-hidden": "true", children: /* @__PURE__ */ jsx94(SegmentedMeter, { total, segments: cu.segments, height: 4, showTotal: false }) }) : null,
12721
+ /* @__PURE__ */ jsx94("span", { className: "fdc-bar-text", title: truncationTitle(bits.join(" \xB7 ")), children: bits.join(" \xB7 ") }),
12722
+ expandable ? /* @__PURE__ */ jsx94("i", { className: "ph ph-caret-right fdc-bar-caret", "aria-hidden": "true" }) : null
12478
12723
  ]
12479
12724
  }
12480
12725
  ),
12481
12726
  extras
12482
12727
  ] }),
12483
- /* @__PURE__ */ jsx93(
12728
+ /* @__PURE__ */ jsx94(
12484
12729
  Popover,
12485
12730
  {
12486
12731
  open: open2,
@@ -12491,15 +12736,15 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
12491
12736
  maxHeight: 460,
12492
12737
  padded: true,
12493
12738
  label: "Usage",
12494
- footer: onClear ? /* @__PURE__ */ jsxs84("button", { type: "button", className: "fdc-usage-clear", onClick: () => {
12739
+ footer: onClear ? /* @__PURE__ */ jsxs85("button", { type: "button", className: "fdc-usage-clear", onClick: () => {
12495
12740
  setOpen(false);
12496
12741
  onClear();
12497
12742
  }, children: [
12498
- /* @__PURE__ */ jsx93("i", { className: "ph ph-trash", "aria-hidden": "true" }),
12743
+ /* @__PURE__ */ jsx94("i", { className: "ph ph-trash", "aria-hidden": "true" }),
12499
12744
  "Clear conversation"
12500
12745
  ] }) : void 0,
12501
- children: /* @__PURE__ */ jsxs84("div", { className: "fdc-usage", children: [
12502
- cu ? /* @__PURE__ */ jsx93("section", { className: "fdc-usage-sec", children: /* @__PURE__ */ jsx93(
12746
+ children: /* @__PURE__ */ jsxs85("div", { className: "fdc-usage", children: [
12747
+ cu ? /* @__PURE__ */ jsx94("section", { className: "fdc-usage-sec", children: /* @__PURE__ */ jsx94(
12503
12748
  SegmentedMeter,
12504
12749
  {
12505
12750
  total,
@@ -12511,9 +12756,9 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
12511
12756
  remainderLabel: "Free"
12512
12757
  }
12513
12758
  ) }) : null,
12514
- limits && limits.length ? /* @__PURE__ */ jsxs84("section", { className: "fdc-usage-sec", children: [
12515
- /* @__PURE__ */ jsx93("h4", { className: "fdc-usage-h", children: "Usage limits" }),
12516
- /* @__PURE__ */ jsx93("div", { className: "fdc-usage-rows", children: limits.map((l) => /* @__PURE__ */ jsx93(
12759
+ limits && limits.length ? /* @__PURE__ */ jsxs85("section", { className: "fdc-usage-sec", children: [
12760
+ /* @__PURE__ */ jsx94("h4", { className: "fdc-usage-h", children: "Usage limits" }),
12761
+ /* @__PURE__ */ jsx94("div", { className: "fdc-usage-rows", children: limits.map((l) => /* @__PURE__ */ jsx94(
12517
12762
  QuotaRow,
12518
12763
  {
12519
12764
  label: l.label,
@@ -12523,25 +12768,25 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
12523
12768
  l.id
12524
12769
  )) })
12525
12770
  ] }) : null,
12526
- stats ? /* @__PURE__ */ jsxs84("section", { className: "fdc-usage-sec fdc-usage-stats", children: [
12527
- stats.elapsedMs ? /* @__PURE__ */ jsxs84("div", { children: [
12528
- /* @__PURE__ */ jsx93("span", { children: "Session" }),
12529
- /* @__PURE__ */ jsx93("b", { className: "fd-tabular", children: formatDuration(stats.elapsedMs) })
12771
+ stats ? /* @__PURE__ */ jsxs85("section", { className: "fdc-usage-sec fdc-usage-stats", children: [
12772
+ stats.elapsedMs ? /* @__PURE__ */ jsxs85("div", { children: [
12773
+ /* @__PURE__ */ jsx94("span", { children: "Session" }),
12774
+ /* @__PURE__ */ jsx94("b", { className: "fd-tabular", children: formatDuration(stats.elapsedMs) })
12530
12775
  ] }) : null,
12531
- stats.tokens ? /* @__PURE__ */ jsxs84("div", { children: [
12532
- /* @__PURE__ */ jsx93("span", { children: "Tokens" }),
12533
- /* @__PURE__ */ jsx93("b", { className: "fd-tabular", children: stats.tokens.toLocaleString() })
12776
+ stats.tokens ? /* @__PURE__ */ jsxs85("div", { children: [
12777
+ /* @__PURE__ */ jsx94("span", { children: "Tokens" }),
12778
+ /* @__PURE__ */ jsx94("b", { className: "fd-tabular", children: stats.tokens.toLocaleString() })
12534
12779
  ] }) : null,
12535
- stats.costUsd != null ? /* @__PURE__ */ jsxs84("div", { children: [
12536
- /* @__PURE__ */ jsx93("span", { children: "Cost" }),
12537
- /* @__PURE__ */ jsxs84("b", { className: "fd-tabular", children: [
12780
+ stats.costUsd != null ? /* @__PURE__ */ jsxs85("div", { children: [
12781
+ /* @__PURE__ */ jsx94("span", { children: "Cost" }),
12782
+ /* @__PURE__ */ jsxs85("b", { className: "fd-tabular", children: [
12538
12783
  "$",
12539
12784
  Number(stats.costUsd).toFixed(3)
12540
12785
  ] })
12541
12786
  ] }) : null,
12542
- stats.turns ? /* @__PURE__ */ jsxs84("div", { children: [
12543
- /* @__PURE__ */ jsx93("span", { children: "Turns" }),
12544
- /* @__PURE__ */ jsx93("b", { className: "fd-tabular", children: stats.turns })
12787
+ stats.turns ? /* @__PURE__ */ jsxs85("div", { children: [
12788
+ /* @__PURE__ */ jsx94("span", { children: "Turns" }),
12789
+ /* @__PURE__ */ jsx94("b", { className: "fd-tabular", children: stats.turns })
12545
12790
  ] }) : null
12546
12791
  ] }) : null
12547
12792
  ] })
@@ -12580,7 +12825,7 @@ function ModelControls({
12580
12825
  disabled: m.disabled,
12581
12826
  checked: m.id === (current2 && current2.id),
12582
12827
  meta: m.meta,
12583
- shortcut: m.shortcut ? /* @__PURE__ */ jsx93(KeyHint, { keys: m.shortcut, size: "sm" }) : void 0,
12828
+ shortcut: m.shortcut ? /* @__PURE__ */ jsx94(KeyHint, { keys: m.shortcut, size: "sm" }) : void 0,
12584
12829
  onSelect: () => onModelChange && onModelChange(m.id)
12585
12830
  });
12586
12831
  const items = [{ kind: "section", label: "Models" }].concat(flat.map(item));
@@ -12593,15 +12838,15 @@ function ModelControls({
12593
12838
  items.push({ kind: "section", label: "Fast mode" });
12594
12839
  items.push({
12595
12840
  kind: "custom",
12596
- render: () => /* @__PURE__ */ jsxs84("label", { className: "fdc-switchrow", children: [
12597
- /* @__PURE__ */ jsx93("span", { children: fastModeLabel }),
12598
- /* @__PURE__ */ jsx93("input", { type: "checkbox", className: "fd-sr", checked: !!fastMode, onChange: (e) => onFastModeChange(e.target.checked) }),
12599
- /* @__PURE__ */ jsx93("span", { className: "fd-switch-track" + (fastMode ? " is-on" : ""), "aria-hidden": "true", children: /* @__PURE__ */ jsx93("span", { className: "fd-switch-thumb" }) })
12841
+ render: () => /* @__PURE__ */ jsxs85("label", { className: "fdc-switchrow", children: [
12842
+ /* @__PURE__ */ jsx94("span", { children: fastModeLabel }),
12843
+ /* @__PURE__ */ jsx94("input", { type: "checkbox", className: "fd-sr", checked: !!fastMode, onChange: (e) => onFastModeChange(e.target.checked) }),
12844
+ /* @__PURE__ */ jsx94("span", { className: "fd-switch-track" + (fastMode ? " is-on" : ""), "aria-hidden": "true", children: /* @__PURE__ */ jsx94("span", { className: "fd-switch-thumb" }) })
12600
12845
  ] })
12601
12846
  });
12602
12847
  }
12603
- return /* @__PURE__ */ jsxs84(React62.Fragment, { children: [
12604
- /* @__PURE__ */ jsx93(
12848
+ return /* @__PURE__ */ jsxs85(React63.Fragment, { children: [
12849
+ /* @__PURE__ */ jsx94(
12605
12850
  MenuButton,
12606
12851
  {
12607
12852
  items,
@@ -12612,7 +12857,7 @@ function ModelControls({
12612
12857
  title: "Choose a model"
12613
12858
  }
12614
12859
  ),
12615
- effortLevels && effortLevels.length ? /* @__PURE__ */ jsx93(
12860
+ effortLevels && effortLevels.length ? /* @__PURE__ */ jsx94(
12616
12861
  MenuButton,
12617
12862
  {
12618
12863
  placement: "top-end",
@@ -12633,7 +12878,7 @@ function ModelControls({
12633
12878
  }
12634
12879
 
12635
12880
  // src/components/chat/AgentChatPanel.tsx
12636
- import { jsx as jsx94, jsxs as jsxs85 } from "react/jsx-runtime";
12881
+ import { jsx as jsx95, jsxs as jsxs86 } from "react/jsx-runtime";
12637
12882
  var SURFACES = { sidebar: "is-sidebar", inline: "is-inline", page: "is-page", modal: "is-modal", sheet: "is-sheet" };
12638
12883
  function AgentChatPanel({
12639
12884
  /* required */
@@ -12717,11 +12962,11 @@ function AgentChatPanel({
12717
12962
  onFeedback,
12718
12963
  onEditMessage
12719
12964
  }) {
12720
- const [panelWidth, setPanelWidth] = React63.useState(width);
12721
- const [applied, setApplied] = React63.useState({});
12722
- const [draft, setDraft] = React63.useState("");
12723
- const dragging = React63.useRef(null);
12724
- React63.useEffect(() => setPanelWidth(width), [width]);
12965
+ const [panelWidth, setPanelWidth] = React64.useState(width);
12966
+ const [applied, setApplied] = React64.useState({});
12967
+ const [draft, setDraft] = React64.useState("");
12968
+ const dragging = React64.useRef(null);
12969
+ React64.useEffect(() => setPanelWidth(width), [width]);
12725
12970
  const engine = useChatEngine({
12726
12971
  contextType,
12727
12972
  contextId,
@@ -12787,7 +13032,7 @@ function AgentChatPanel({
12787
13032
  onReconnect: engine.reload,
12788
13033
  deadTitle: "The assistant isn\u2019t reachable"
12789
13034
  };
12790
- const sessionBar = /* @__PURE__ */ jsx94(
13035
+ const sessionBar = /* @__PURE__ */ jsx95(
12791
13036
  ChatSessionBar,
12792
13037
  {
12793
13038
  sessionStats,
@@ -12796,7 +13041,7 @@ function AgentChatPanel({
12796
13041
  onClear: engine.visible.length ? engine.clear : void 0
12797
13042
  }
12798
13043
  );
12799
- const modelControls = /* @__PURE__ */ jsx94(
13044
+ const modelControls = /* @__PURE__ */ jsx95(
12800
13045
  ModelControls,
12801
13046
  {
12802
13047
  models,
@@ -12811,7 +13056,7 @@ function AgentChatPanel({
12811
13056
  narrow
12812
13057
  }
12813
13058
  );
12814
- const threadMenu = threads && threads.length ? /* @__PURE__ */ jsx94(
13059
+ const threadMenu = threads && threads.length ? /* @__PURE__ */ jsx95(
12815
13060
  MenuButton,
12816
13061
  {
12817
13062
  variant: "ghost",
@@ -12838,7 +13083,7 @@ function AgentChatPanel({
12838
13083
  })))
12839
13084
  }
12840
13085
  ) : null;
12841
- return /* @__PURE__ */ jsxs85(
13086
+ return /* @__PURE__ */ jsxs86(
12842
13087
  "aside",
12843
13088
  {
12844
13089
  className: ["fdc-panel", SURFACES[surface] || SURFACES.sidebar, narrow ? "is-narrow" : "", className].filter(Boolean).join(" "),
@@ -12849,7 +13094,7 @@ function AgentChatPanel({
12849
13094
  },
12850
13095
  "aria-label": title,
12851
13096
  children: [
12852
- surface === "sidebar" && resizable ? /* @__PURE__ */ jsx94(
13097
+ surface === "sidebar" && resizable ? /* @__PURE__ */ jsx95(
12853
13098
  "div",
12854
13099
  {
12855
13100
  className: "fdc-grip",
@@ -12864,20 +13109,20 @@ function AgentChatPanel({
12864
13109
  }
12865
13110
  }
12866
13111
  ) : null,
12867
- showHeader ? /* @__PURE__ */ jsxs85("header", { className: "fdc-head", children: [
12868
- /* @__PURE__ */ jsx94("span", { className: "fdc-head-mark", "aria-hidden": "true", children: /* @__PURE__ */ jsx94("i", { className: "ph ph-" + assistantIcon }) }),
12869
- /* @__PURE__ */ jsxs85("span", { className: "fdc-head-titles", children: [
12870
- /* @__PURE__ */ jsx94("span", { className: "fdc-head-title", title: truncationTitle(title), children: title }),
12871
- subtitle ? /* @__PURE__ */ jsx94("span", { className: "fdc-head-sub", title: truncationTitle(subtitle), children: subtitle }) : null
13112
+ showHeader ? /* @__PURE__ */ jsxs86("header", { className: "fdc-head", children: [
13113
+ /* @__PURE__ */ jsx95("span", { className: "fdc-head-mark", "aria-hidden": "true", children: /* @__PURE__ */ jsx95("i", { className: "ph ph-" + assistantIcon }) }),
13114
+ /* @__PURE__ */ jsxs86("span", { className: "fdc-head-titles", children: [
13115
+ /* @__PURE__ */ jsx95("span", { className: "fdc-head-title", title: truncationTitle(title), children: title }),
13116
+ subtitle ? /* @__PURE__ */ jsx95("span", { className: "fdc-head-sub", title: truncationTitle(subtitle), children: subtitle }) : null
12872
13117
  ] }),
12873
- /* @__PURE__ */ jsxs85("span", { className: "fdc-head-acts", children: [
13118
+ /* @__PURE__ */ jsxs86("span", { className: "fdc-head-acts", children: [
12874
13119
  headerActions,
12875
13120
  threadMenu,
12876
- onNewThread ? /* @__PURE__ */ jsx94("button", { type: "button", className: "fdc-iconbtn", onClick: onNewThread, "aria-label": "New conversation", title: "New conversation", children: /* @__PURE__ */ jsx94("i", { className: "ph ph-plus", "aria-hidden": "true" }) }) : null,
12877
- onClose ? /* @__PURE__ */ jsx94("button", { type: "button", className: "fdc-iconbtn", onClick: onClose, "aria-label": "Close panel", title: "Close", children: /* @__PURE__ */ jsx94("i", { className: "ph ph-x", "aria-hidden": "true" }) }) : null
13121
+ onNewThread ? /* @__PURE__ */ jsx95("button", { type: "button", className: "fdc-iconbtn", onClick: onNewThread, "aria-label": "New conversation", title: "New conversation", children: /* @__PURE__ */ jsx95("i", { className: "ph ph-plus", "aria-hidden": "true" }) }) : null,
13122
+ onClose ? /* @__PURE__ */ jsx95("button", { type: "button", className: "fdc-iconbtn", onClick: onClose, "aria-label": "Close panel", title: "Close", children: /* @__PURE__ */ jsx95("i", { className: "ph ph-x", "aria-hidden": "true" }) }) : null
12878
13123
  ] })
12879
13124
  ] }) : null,
12880
- /* @__PURE__ */ jsx94(
13125
+ /* @__PURE__ */ jsx95(
12881
13126
  ChatTranscript,
12882
13127
  {
12883
13128
  messages: engine.visible,
@@ -12892,7 +13137,7 @@ function AgentChatPanel({
12892
13137
  renderEmpty
12893
13138
  }
12894
13139
  ),
12895
- /* @__PURE__ */ jsx94(
13140
+ /* @__PURE__ */ jsx95(
12896
13141
  ChatComposer,
12897
13142
  {
12898
13143
  onSubmit: (text, atts) => engine.send(text, atts),
@@ -12925,8 +13170,8 @@ function AgentChatPanel({
12925
13170
  }
12926
13171
 
12927
13172
  // src/components/files/FileViewer.tsx
12928
- import * as React64 from "react";
12929
- import { jsx as jsx95, jsxs as jsxs86 } from "react/jsx-runtime";
13173
+ import * as React65 from "react";
13174
+ import { jsx as jsx96, jsxs as jsxs87 } from "react/jsx-runtime";
12930
13175
  function previewKindOf(file) {
12931
13176
  const mime = (file.mime || "").toLowerCase();
12932
13177
  const ext = extensionOf(file.name || "");
@@ -12982,13 +13227,13 @@ function parseDelimited(text, delimiter) {
12982
13227
  return rows;
12983
13228
  }
12984
13229
  function usePreview(file, kind, resolveUrl) {
12985
- const [state, setState] = React64.useState({ status: "loading" });
12986
- const [attempt, setAttempt] = React64.useState(0);
12987
- const resolveRef = React64.useRef(resolveUrl);
12988
- React64.useEffect(() => {
13230
+ const [state, setState] = React65.useState({ status: "loading" });
13231
+ const [attempt, setAttempt] = React65.useState(0);
13232
+ const resolveRef = React65.useRef(resolveUrl);
13233
+ React65.useEffect(() => {
12989
13234
  resolveRef.current = resolveUrl;
12990
13235
  }, [resolveUrl]);
12991
- React64.useEffect(() => {
13236
+ React65.useEffect(() => {
12992
13237
  if (kind === "none") {
12993
13238
  setState({ status: "ready" });
12994
13239
  return;
@@ -13018,19 +13263,19 @@ function usePreview(file, kind, resolveUrl) {
13018
13263
  if (ac) ac.abort();
13019
13264
  };
13020
13265
  }, [file.id, kind, attempt]);
13021
- return { ...state, retry: React64.useCallback(() => setAttempt((a) => a + 1), []) };
13266
+ return { ...state, retry: React65.useCallback(() => setAttempt((a) => a + 1), []) };
13022
13267
  }
13023
13268
  function PreviewBody({ file, kind, state }) {
13024
- if (kind === "image") return /* @__PURE__ */ jsx95("img", { className: "fd-fv-image", src: state.url, alt: file.name || "Preview" });
13025
- if (kind === "pdf") return /* @__PURE__ */ jsx95("iframe", { className: "fd-fv-pdf", src: state.url, title: file.name || "PDF preview" });
13026
- if (kind === "markdown") return /* @__PURE__ */ jsx95(Markdown, { className: "fd-fv-markdown", source: state.text || "" });
13269
+ if (kind === "image") return /* @__PURE__ */ jsx96("img", { className: "fd-fv-image", src: state.url, alt: file.name || "Preview" });
13270
+ if (kind === "pdf") return /* @__PURE__ */ jsx96("iframe", { className: "fd-fv-pdf", src: state.url, title: file.name || "PDF preview" });
13271
+ if (kind === "markdown") return /* @__PURE__ */ jsx96(Markdown, { className: "fd-fv-markdown", source: state.text || "" });
13027
13272
  if (kind === "json") {
13028
13273
  let pretty = state.text || "";
13029
13274
  try {
13030
13275
  pretty = JSON.stringify(JSON.parse(pretty), null, 2);
13031
13276
  } catch {
13032
13277
  }
13033
- return /* @__PURE__ */ jsx95(CodeBlock, { code: pretty, language: "json" });
13278
+ return /* @__PURE__ */ jsx96(CodeBlock, { code: pretty, language: "json" });
13034
13279
  }
13035
13280
  if (kind === "csv") {
13036
13281
  const tsv = extensionOf(file.name || "") === "tsv" || (file.mime || "").toLowerCase().includes("tab-separated");
@@ -13038,12 +13283,12 @@ function PreviewBody({ file, kind, state }) {
13038
13283
  const head = rows[0] || [];
13039
13284
  const dataRows = rows.slice(1);
13040
13285
  const shown = dataRows.slice(0, FILE_VIEWER_CSV_ROW_LIMIT);
13041
- return /* @__PURE__ */ jsxs86("div", { className: "fd-fv-csv", children: [
13042
- /* @__PURE__ */ jsxs86("table", { className: "fd-fv-csv-table", children: [
13043
- /* @__PURE__ */ jsx95("thead", { children: /* @__PURE__ */ jsx95("tr", { children: head.map((c, i) => /* @__PURE__ */ jsx95("th", { children: c }, i)) }) }),
13044
- /* @__PURE__ */ jsx95("tbody", { children: shown.map((r, ri) => /* @__PURE__ */ jsx95("tr", { children: head.map((_, ci) => /* @__PURE__ */ jsx95("td", { children: r[ci] ?? "" }, ci)) }, ri)) })
13286
+ return /* @__PURE__ */ jsxs87("div", { className: "fd-fv-csv", children: [
13287
+ /* @__PURE__ */ jsxs87("table", { className: "fd-fv-csv-table", children: [
13288
+ /* @__PURE__ */ jsx96("thead", { children: /* @__PURE__ */ jsx96("tr", { children: head.map((c, i) => /* @__PURE__ */ jsx96("th", { children: c }, i)) }) }),
13289
+ /* @__PURE__ */ jsx96("tbody", { children: shown.map((r, ri) => /* @__PURE__ */ jsx96("tr", { children: head.map((_, ci) => /* @__PURE__ */ jsx96("td", { children: r[ci] ?? "" }, ci)) }, ri)) })
13045
13290
  ] }),
13046
- dataRows.length > FILE_VIEWER_CSV_ROW_LIMIT ? /* @__PURE__ */ jsxs86("p", { className: "fd-fv-csv-note fd-body-sm fd-muted", children: [
13291
+ dataRows.length > FILE_VIEWER_CSV_ROW_LIMIT ? /* @__PURE__ */ jsxs87("p", { className: "fd-fv-csv-note fd-body-sm fd-muted", children: [
13047
13292
  "Showing the first ",
13048
13293
  FILE_VIEWER_CSV_ROW_LIMIT.toLocaleString(),
13049
13294
  " of ",
@@ -13052,24 +13297,24 @@ function PreviewBody({ file, kind, state }) {
13052
13297
  ] }) : null
13053
13298
  ] });
13054
13299
  }
13055
- if (kind === "text") return /* @__PURE__ */ jsx95(CodeBlock, { code: state.text || "", language: extensionOf(file.name || "") || void 0 });
13056
- return /* @__PURE__ */ jsxs86("div", { className: "fd-fv-fallback", children: [
13057
- /* @__PURE__ */ jsx95("span", { className: "fd-fv-fallback-icon", "aria-hidden": "true", children: /* @__PURE__ */ jsx95("i", { className: "ph ph-" + iconForMime(file.mime, file.name) }) }),
13058
- /* @__PURE__ */ jsx95("span", { className: "fd-fv-fallback-title", children: "No preview available" }),
13059
- /* @__PURE__ */ jsxs86("span", { className: "fd-fv-fallback-meta", children: [
13300
+ if (kind === "text") return /* @__PURE__ */ jsx96(CodeBlock, { code: state.text || "", language: extensionOf(file.name || "") || void 0 });
13301
+ return /* @__PURE__ */ jsxs87("div", { className: "fd-fv-fallback", children: [
13302
+ /* @__PURE__ */ jsx96("span", { className: "fd-fv-fallback-icon", "aria-hidden": "true", children: /* @__PURE__ */ jsx96("i", { className: "ph ph-" + iconForMime(file.mime, file.name) }) }),
13303
+ /* @__PURE__ */ jsx96("span", { className: "fd-fv-fallback-title", children: "No preview available" }),
13304
+ /* @__PURE__ */ jsxs87("span", { className: "fd-fv-fallback-meta", children: [
13060
13305
  file.mime || "Unknown type",
13061
13306
  file.size ? " \xB7 " + formatBytes(file.size) : ""
13062
13307
  ] })
13063
13308
  ] });
13064
13309
  }
13065
13310
  function FileViewer({ file, resolveUrl, sidePanel, sidePanelLabel = "Details", onClose, actions, className = "" }) {
13066
- const kind = React64.useMemo(() => previewKindOf(file), [file]);
13311
+ const kind = React65.useMemo(() => previewKindOf(file), [file]);
13067
13312
  const preview = usePreview(file, kind, resolveUrl);
13068
- const [tab, setTab] = React64.useState("preview");
13069
- const [downloading, setDownloading] = React64.useState(false);
13070
- const [downloadError, setDownloadError] = React64.useState(null);
13313
+ const [tab, setTab] = React65.useState("preview");
13314
+ const [downloading, setDownloading] = React65.useState(false);
13315
+ const [downloadError, setDownloadError] = React65.useState(null);
13071
13316
  const hasSide = sidePanel != null;
13072
- React64.useEffect(() => {
13317
+ React65.useEffect(() => {
13073
13318
  setTab("preview");
13074
13319
  }, [file.id]);
13075
13320
  const download = () => {
@@ -13085,29 +13330,29 @@ function FileViewer({ file, resolveUrl, sidePanel, sidePanelLabel = "Details", o
13085
13330
  a.remove();
13086
13331
  }).catch((err) => setDownloadError(err && err.message || "Download failed.")).finally(() => setDownloading(false));
13087
13332
  };
13088
- return /* @__PURE__ */ jsxs86(
13333
+ return /* @__PURE__ */ jsxs87(
13089
13334
  "section",
13090
13335
  {
13091
13336
  className: ["fd-fv", hasSide && tab === "side" ? "is-tab-side" : "is-tab-preview", className].filter(Boolean).join(" "),
13092
13337
  "aria-label": file.name || "File",
13093
13338
  children: [
13094
- /* @__PURE__ */ jsxs86("header", { className: "fd-fv-head", children: [
13095
- /* @__PURE__ */ jsx95("span", { className: "fd-fv-head-icon", "aria-hidden": "true", children: /* @__PURE__ */ jsx95("i", { className: "ph ph-" + iconForMime(file.mime, file.name) }) }),
13096
- /* @__PURE__ */ jsxs86("span", { className: "fd-fv-head-titles", children: [
13097
- /* @__PURE__ */ jsx95("span", { className: "fd-fv-head-title", title: file.name, children: file.name }),
13098
- /* @__PURE__ */ jsxs86("span", { className: "fd-fv-head-meta", children: [
13339
+ /* @__PURE__ */ jsxs87("header", { className: "fd-fv-head", children: [
13340
+ /* @__PURE__ */ jsx96("span", { className: "fd-fv-head-icon", "aria-hidden": "true", children: /* @__PURE__ */ jsx96("i", { className: "ph ph-" + iconForMime(file.mime, file.name) }) }),
13341
+ /* @__PURE__ */ jsxs87("span", { className: "fd-fv-head-titles", children: [
13342
+ /* @__PURE__ */ jsx96("span", { className: "fd-fv-head-title", title: file.name, children: file.name }),
13343
+ /* @__PURE__ */ jsxs87("span", { className: "fd-fv-head-meta", children: [
13099
13344
  file.mime || "Unknown type",
13100
13345
  file.size ? " \xB7 " + formatBytes(file.size) : ""
13101
13346
  ] })
13102
13347
  ] }),
13103
- /* @__PURE__ */ jsxs86("span", { className: "fd-fv-head-actions", children: [
13348
+ /* @__PURE__ */ jsxs87("span", { className: "fd-fv-head-actions", children: [
13104
13349
  actions,
13105
- /* @__PURE__ */ jsx95(Button, { variant: "secondary", size: "sm", icon: "download-simple", loading: downloading, onClick: download, children: "Download" }),
13106
- onClose ? /* @__PURE__ */ jsx95(IconButton, { icon: "x", label: "Close", onClick: onClose }) : null
13350
+ /* @__PURE__ */ jsx96(Button, { variant: "secondary", size: "sm", icon: "download-simple", loading: downloading, onClick: download, children: "Download" }),
13351
+ onClose ? /* @__PURE__ */ jsx96(IconButton, { icon: "x", label: "Close", onClick: onClose }) : null
13107
13352
  ] })
13108
13353
  ] }),
13109
- downloadError ? /* @__PURE__ */ jsx95("div", { className: "fd-fv-download-error", role: "alert", children: downloadError }) : null,
13110
- hasSide ? /* @__PURE__ */ jsx95(
13354
+ downloadError ? /* @__PURE__ */ jsx96("div", { className: "fd-fv-download-error", role: "alert", children: downloadError }) : null,
13355
+ hasSide ? /* @__PURE__ */ jsx96(
13111
13356
  Tabs,
13112
13357
  {
13113
13358
  className: "fd-fv-tabs",
@@ -13116,19 +13361,19 @@ function FileViewer({ file, resolveUrl, sidePanel, sidePanelLabel = "Details", o
13116
13361
  onChange: (v) => setTab(v)
13117
13362
  }
13118
13363
  ) : null,
13119
- /* @__PURE__ */ jsxs86("div", { className: "fd-fv-body", children: [
13120
- /* @__PURE__ */ jsx95("div", { className: "fd-fv-preview", role: "region", "aria-label": "Preview of " + (file.name || "file"), children: /* @__PURE__ */ jsx95(
13364
+ /* @__PURE__ */ jsxs87("div", { className: "fd-fv-body", children: [
13365
+ /* @__PURE__ */ jsx96("div", { className: "fd-fv-preview", role: "region", "aria-label": "Preview of " + (file.name || "file"), children: /* @__PURE__ */ jsx96(
13121
13366
  LoadingRegion,
13122
13367
  {
13123
13368
  state: preview.status === "loading" ? "loading" : preview.status === "error" ? "error" : "ready",
13124
13369
  error: preview.error,
13125
13370
  label: "Loading preview of " + (file.name || "file"),
13126
13371
  onRetry: preview.status === "error" ? preview.retry : void 0,
13127
- skeleton: /* @__PURE__ */ jsx95(Skeleton, { shape: "card", h: 220 }),
13128
- children: /* @__PURE__ */ jsx95(PreviewBody, { file, kind, state: preview })
13372
+ skeleton: /* @__PURE__ */ jsx96(Skeleton, { shape: "card", h: 220 }),
13373
+ children: /* @__PURE__ */ jsx96(PreviewBody, { file, kind, state: preview })
13129
13374
  }
13130
13375
  ) }),
13131
- hasSide ? /* @__PURE__ */ jsx95("div", { className: "fd-fv-side", role: "region", "aria-label": sidePanelLabel, children: sidePanel }) : null
13376
+ hasSide ? /* @__PURE__ */ jsx96("div", { className: "fd-fv-side", role: "region", "aria-label": sidePanelLabel, children: sidePanel }) : null
13132
13377
  ] })
13133
13378
  ]
13134
13379
  }
@@ -13136,8 +13381,8 @@ function FileViewer({ file, resolveUrl, sidePanel, sidePanelLabel = "Details", o
13136
13381
  }
13137
13382
 
13138
13383
  // src/components/files/FileBrowser.tsx
13139
- import * as React65 from "react";
13140
- import { Fragment as Fragment28, jsx as jsx96, jsxs as jsxs87 } from "react/jsx-runtime";
13384
+ import * as React66 from "react";
13385
+ import { Fragment as Fragment28, jsx as jsx97, jsxs as jsxs88 } from "react/jsx-runtime";
13141
13386
  function childrenOf(folders, parentId) {
13142
13387
  return folders.filter((f) => f.parentId === parentId).sort((a, b) => a.name.localeCompare(b.name));
13143
13388
  }
@@ -13209,8 +13454,8 @@ function FolderPickerMenu({
13209
13454
  }) {
13210
13455
  const panel = useInlinePanel();
13211
13456
  const { open: open2, setOpen, ref, zIndex } = panel;
13212
- return /* @__PURE__ */ jsxs87("span", { className: "fd-fb-menu-anchor", ref, children: [
13213
- /* @__PURE__ */ jsx96(
13457
+ return /* @__PURE__ */ jsxs88("span", { className: "fd-fb-menu-anchor", ref, children: [
13458
+ /* @__PURE__ */ jsx97(
13214
13459
  IconButton,
13215
13460
  {
13216
13461
  icon: "arrows-out-cardinal",
@@ -13222,9 +13467,9 @@ function FolderPickerMenu({
13222
13467
  onClick: () => setOpen((v) => !v)
13223
13468
  }
13224
13469
  ),
13225
- open2 ? /* @__PURE__ */ jsx96(InlinePanelLayers, { panel, children: /* @__PURE__ */ jsxs87("div", { className: "fd-fb-menu", role: "menu", "aria-label": label, style: { zIndex }, children: [
13226
- /* @__PURE__ */ jsx96("span", { className: "fd-overline fd-muted fd-fb-menu-title", children: "Move to\u2026" }),
13227
- destinations.map((d) => /* @__PURE__ */ jsxs87(
13470
+ open2 ? /* @__PURE__ */ jsx97(InlinePanelLayers, { panel, children: /* @__PURE__ */ jsxs88("div", { className: "fd-fb-menu", role: "menu", "aria-label": label, style: { zIndex }, children: [
13471
+ /* @__PURE__ */ jsx97("span", { className: "fd-overline fd-muted fd-fb-menu-title", children: "Move to\u2026" }),
13472
+ destinations.map((d) => /* @__PURE__ */ jsxs88(
13228
13473
  "button",
13229
13474
  {
13230
13475
  type: "button",
@@ -13236,7 +13481,7 @@ function FolderPickerMenu({
13236
13481
  setOpen(false);
13237
13482
  },
13238
13483
  children: [
13239
- /* @__PURE__ */ jsx96("i", { className: "ph ph-" + (d.id == null ? "house-simple" : "folder-simple"), "aria-hidden": "true" }),
13484
+ /* @__PURE__ */ jsx97("i", { className: "ph ph-" + (d.id == null ? "house-simple" : "folder-simple"), "aria-hidden": "true" }),
13240
13485
  d.name
13241
13486
  ]
13242
13487
  },
@@ -13246,8 +13491,8 @@ function FolderPickerMenu({
13246
13491
  ] });
13247
13492
  }
13248
13493
  function RowShell({ icon, name, meta, onOpen, draggableId, isDropTarget, onDropPayload, actions, className = "" }) {
13249
- const [over, setOver] = React65.useState(false);
13250
- const dragCounter = React65.useRef(0);
13494
+ const [over, setOver] = React66.useState(false);
13495
+ const dragCounter = React66.useRef(0);
13251
13496
  const dropHandlers = isDropTarget ? {
13252
13497
  onDragEnter: (e) => {
13253
13498
  if (!hasInternalPayload(e)) return;
@@ -13272,8 +13517,8 @@ function RowShell({ icon, name, meta, onOpen, draggableId, isDropTarget, onDropP
13272
13517
  if (payload && onDropPayload) onDropPayload(payload);
13273
13518
  }
13274
13519
  } : {};
13275
- return /* @__PURE__ */ jsxs87("div", { className: ["fd-fb-row", over ? "is-drop-target" : "", className].filter(Boolean).join(" "), ...dropHandlers, children: [
13276
- /* @__PURE__ */ jsxs87(
13520
+ return /* @__PURE__ */ jsxs88("div", { className: ["fd-fb-row", over ? "is-drop-target" : "", className].filter(Boolean).join(" "), ...dropHandlers, children: [
13521
+ /* @__PURE__ */ jsxs88(
13277
13522
  "button",
13278
13523
  {
13279
13524
  type: "button",
@@ -13282,26 +13527,26 @@ function RowShell({ icon, name, meta, onOpen, draggableId, isDropTarget, onDropP
13282
13527
  draggable: !!draggableId,
13283
13528
  onDragStart: draggableId ? (e) => writeDragPayload(e, draggableId) : void 0,
13284
13529
  children: [
13285
- /* @__PURE__ */ jsx96("span", { className: "fd-fb-row-icon", "aria-hidden": "true", children: /* @__PURE__ */ jsx96("i", { className: "ph ph-" + icon }) }),
13286
- /* @__PURE__ */ jsxs87("span", { className: "fd-fb-row-text", children: [
13287
- /* @__PURE__ */ jsx96("span", { className: "fd-fb-row-name", title: name, children: name }),
13288
- meta ? /* @__PURE__ */ jsx96("span", { className: "fd-fb-row-meta", children: meta }) : null
13530
+ /* @__PURE__ */ jsx97("span", { className: "fd-fb-row-icon", "aria-hidden": "true", children: /* @__PURE__ */ jsx97("i", { className: "ph ph-" + icon }) }),
13531
+ /* @__PURE__ */ jsxs88("span", { className: "fd-fb-row-text", children: [
13532
+ /* @__PURE__ */ jsx97("span", { className: "fd-fb-row-name", title: name, children: name }),
13533
+ meta ? /* @__PURE__ */ jsx97("span", { className: "fd-fb-row-meta", children: meta }) : null
13289
13534
  ] })
13290
13535
  ]
13291
13536
  }
13292
13537
  ),
13293
- actions ? /* @__PURE__ */ jsx96("span", { className: "fd-fb-row-actions", children: actions }) : null
13538
+ actions ? /* @__PURE__ */ jsx97("span", { className: "fd-fb-row-actions", children: actions }) : null
13294
13539
  ] });
13295
13540
  }
13296
13541
  function TreeNode({ folder, depth, folders, currentFolderId, onNavigate, onMoveInto, canMove }) {
13297
13542
  const kids = childrenOf(folders, folder.id);
13298
- const [expanded, setExpanded] = React65.useState(() => currentFolderId != null && isSelfOrDescendant(folders, folder.id, currentFolderId));
13299
- React65.useEffect(() => {
13543
+ const [expanded, setExpanded] = React66.useState(() => currentFolderId != null && isSelfOrDescendant(folders, folder.id, currentFolderId));
13544
+ React66.useEffect(() => {
13300
13545
  if (currentFolderId != null && isSelfOrDescendant(folders, folder.id, currentFolderId)) setExpanded(true);
13301
13546
  }, [currentFolderId, folder.id, folders]);
13302
13547
  const isCurrent = folder.id === currentFolderId;
13303
- return /* @__PURE__ */ jsxs87("div", { className: "fd-fb-tree-node", children: [
13304
- /* @__PURE__ */ jsx96(
13548
+ return /* @__PURE__ */ jsxs88("div", { className: "fd-fb-tree-node", children: [
13549
+ /* @__PURE__ */ jsx97(
13305
13550
  RowShell,
13306
13551
  {
13307
13552
  icon: folder.id === currentFolderId ? "folder-open" : "folder-simple",
@@ -13311,7 +13556,7 @@ function TreeNode({ folder, depth, folders, currentFolderId, onNavigate, onMoveI
13311
13556
  isDropTarget: canMove,
13312
13557
  onDropPayload: (payload) => onMoveInto(payload, folder.id),
13313
13558
  className: ["fd-fb-tree-row", isCurrent ? "is-current" : ""].filter(Boolean).join(" "),
13314
- actions: kids.length ? /* @__PURE__ */ jsx96(
13559
+ actions: kids.length ? /* @__PURE__ */ jsx97(
13315
13560
  IconButton,
13316
13561
  {
13317
13562
  icon: expanded ? "caret-down" : "caret-right",
@@ -13323,7 +13568,7 @@ function TreeNode({ folder, depth, folders, currentFolderId, onNavigate, onMoveI
13323
13568
  ) : void 0
13324
13569
  }
13325
13570
  ),
13326
- expanded && kids.length ? /* @__PURE__ */ jsx96("div", { className: "fd-fb-tree-children", style: { paddingLeft: 14 }, children: kids.map((k) => /* @__PURE__ */ jsx96(
13571
+ expanded && kids.length ? /* @__PURE__ */ jsx97("div", { className: "fd-fb-tree-children", style: { paddingLeft: 14 }, children: kids.map((k) => /* @__PURE__ */ jsx97(
13327
13572
  TreeNode,
13328
13573
  {
13329
13574
  folder: k,
@@ -13362,15 +13607,15 @@ function FileBrowser({
13362
13607
  const canUpload = perm.canUpload !== false && !!onUpload;
13363
13608
  const canRemoveFile = perm.canRemoveFile !== false && !!onRemoveFile;
13364
13609
  const canDeleteFolder = perm.canDeleteFolder !== false && !!onDeleteFolder;
13365
- const [createOpen, setCreateOpen] = React65.useState(false);
13366
- const [createName, setCreateName] = React65.useState("");
13367
- const [renameTarget, setRenameTarget] = React65.useState(null);
13368
- const [renameValue, setRenameValue] = React65.useState("");
13369
- const [deleteTarget, setDeleteTarget] = React65.useState(null);
13370
- const uploadInputRef = React65.useRef(null);
13371
- const crumbFolders = React65.useMemo(() => ancestorsOf(folders, currentFolderId), [folders, currentFolderId]);
13372
- const subfolders = React65.useMemo(() => childrenOf(folders, currentFolderId), [folders, currentFolderId]);
13373
- const currentFiles = React65.useMemo(
13610
+ const [createOpen, setCreateOpen] = React66.useState(false);
13611
+ const [createName, setCreateName] = React66.useState("");
13612
+ const [renameTarget, setRenameTarget] = React66.useState(null);
13613
+ const [renameValue, setRenameValue] = React66.useState("");
13614
+ const [deleteTarget, setDeleteTarget] = React66.useState(null);
13615
+ const uploadInputRef = React66.useRef(null);
13616
+ const crumbFolders = React66.useMemo(() => ancestorsOf(folders, currentFolderId), [folders, currentFolderId]);
13617
+ const subfolders = React66.useMemo(() => childrenOf(folders, currentFolderId), [folders, currentFolderId]);
13618
+ const currentFiles = React66.useMemo(
13374
13619
  () => files.filter((f) => f.folderId === currentFolderId).sort((a, b) => a.name.localeCompare(b.name)),
13375
13620
  [files, currentFolderId]
13376
13621
  );
@@ -13409,10 +13654,10 @@ function FileBrowser({
13409
13654
  if (deleteTarget && onDeleteFolder) onDeleteFolder(deleteTarget);
13410
13655
  setDeleteTarget(null);
13411
13656
  };
13412
- const content = /* @__PURE__ */ jsxs87("div", { className: ["fd-fb", className].filter(Boolean).join(" "), children: [
13413
- /* @__PURE__ */ jsxs87("div", { className: "fd-fb-head", children: [
13414
- /* @__PURE__ */ jsxs87("nav", { className: "fd-fb-crumbs", "aria-label": "Folder path", children: [
13415
- /* @__PURE__ */ jsx96(
13657
+ const content = /* @__PURE__ */ jsxs88("div", { className: ["fd-fb", className].filter(Boolean).join(" "), children: [
13658
+ /* @__PURE__ */ jsxs88("div", { className: "fd-fb-head", children: [
13659
+ /* @__PURE__ */ jsxs88("nav", { className: "fd-fb-crumbs", "aria-label": "Folder path", children: [
13660
+ /* @__PURE__ */ jsx97(
13416
13661
  BreadcrumbCrumb,
13417
13662
  {
13418
13663
  label: "Home",
@@ -13422,7 +13667,7 @@ function FileBrowser({
13422
13667
  onDropPayload: (p) => moveIntoFolder(p, null)
13423
13668
  }
13424
13669
  ),
13425
- crumbFolders.map((f, i) => /* @__PURE__ */ jsx96(
13670
+ crumbFolders.map((f, i) => /* @__PURE__ */ jsx97(
13426
13671
  BreadcrumbCrumb,
13427
13672
  {
13428
13673
  label: f.name,
@@ -13434,11 +13679,11 @@ function FileBrowser({
13434
13679
  f.id
13435
13680
  ))
13436
13681
  ] }),
13437
- /* @__PURE__ */ jsxs87("span", { className: "fd-fb-actions", children: [
13438
- canCreateFolder ? /* @__PURE__ */ jsx96(Button, { variant: "secondary", size: "sm", icon: "folder-simple-plus", onClick: openCreate, children: "New folder" }) : null,
13439
- canUpload ? /* @__PURE__ */ jsxs87(Fragment28, { children: [
13440
- /* @__PURE__ */ jsx96(Button, { variant: "secondary", size: "sm", icon: "upload-simple", onClick: () => uploadInputRef.current && uploadInputRef.current.click(), children: "Upload" }),
13441
- /* @__PURE__ */ jsx96(
13682
+ /* @__PURE__ */ jsxs88("span", { className: "fd-fb-actions", children: [
13683
+ canCreateFolder ? /* @__PURE__ */ jsx97(Button, { variant: "secondary", size: "sm", icon: "folder-simple-plus", onClick: openCreate, children: "New folder" }) : null,
13684
+ canUpload ? /* @__PURE__ */ jsxs88(Fragment28, { children: [
13685
+ /* @__PURE__ */ jsx97(Button, { variant: "secondary", size: "sm", icon: "upload-simple", onClick: () => uploadInputRef.current && uploadInputRef.current.click(), children: "Upload" }),
13686
+ /* @__PURE__ */ jsx97(
13442
13687
  "input",
13443
13688
  {
13444
13689
  ref: uploadInputRef,
@@ -13456,9 +13701,9 @@ function FileBrowser({
13456
13701
  ] }) : null
13457
13702
  ] })
13458
13703
  ] }),
13459
- /* @__PURE__ */ jsxs87("div", { className: "fd-fb-body", children: [
13460
- /* @__PURE__ */ jsxs87("div", { className: "fd-fb-tree", role: "region", "aria-label": "Folder tree", children: [
13461
- /* @__PURE__ */ jsx96(
13704
+ /* @__PURE__ */ jsxs88("div", { className: "fd-fb-body", children: [
13705
+ /* @__PURE__ */ jsxs88("div", { className: "fd-fb-tree", role: "region", "aria-label": "Folder tree", children: [
13706
+ /* @__PURE__ */ jsx97(
13462
13707
  RowShell,
13463
13708
  {
13464
13709
  icon: "house-simple",
@@ -13469,7 +13714,7 @@ function FileBrowser({
13469
13714
  className: ["fd-fb-tree-row", currentFolderId == null ? "is-current" : ""].filter(Boolean).join(" ")
13470
13715
  }
13471
13716
  ),
13472
- childrenOf(folders, null).map((f) => /* @__PURE__ */ jsx96(
13717
+ childrenOf(folders, null).map((f) => /* @__PURE__ */ jsx97(
13473
13718
  TreeNode,
13474
13719
  {
13475
13720
  folder: f,
@@ -13483,18 +13728,18 @@ function FileBrowser({
13483
13728
  f.id
13484
13729
  ))
13485
13730
  ] }),
13486
- /* @__PURE__ */ jsx96("div", { className: "fd-fb-main", role: "region", "aria-label": "Folder contents", children: /* @__PURE__ */ jsx96(
13731
+ /* @__PURE__ */ jsx97("div", { className: "fd-fb-main", role: "region", "aria-label": "Folder contents", children: /* @__PURE__ */ jsx97(
13487
13732
  LoadingRegion,
13488
13733
  {
13489
13734
  state: loading ? "loading" : "ready",
13490
13735
  label: "Loading folder contents",
13491
- skeleton: /* @__PURE__ */ jsxs87("div", { className: "fd-stack", style: { gap: 8, padding: 12 }, children: [
13492
- /* @__PURE__ */ jsx96(Skeleton, { h: 44, radius: "10px" }),
13493
- /* @__PURE__ */ jsx96(Skeleton, { h: 44, radius: "10px" }),
13494
- /* @__PURE__ */ jsx96(Skeleton, { h: 44, radius: "10px" })
13736
+ skeleton: /* @__PURE__ */ jsxs88("div", { className: "fd-stack", style: { gap: 8, padding: 12 }, children: [
13737
+ /* @__PURE__ */ jsx97(Skeleton, { h: 44, radius: "10px" }),
13738
+ /* @__PURE__ */ jsx97(Skeleton, { h: 44, radius: "10px" }),
13739
+ /* @__PURE__ */ jsx97(Skeleton, { h: 44, radius: "10px" })
13495
13740
  ] }),
13496
- children: isEmpty ? /* @__PURE__ */ jsx96(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__ */ jsxs87("div", { className: "fd-fb-list", children: [
13497
- subfolders.map((f) => /* @__PURE__ */ jsx96(
13741
+ children: isEmpty ? /* @__PURE__ */ jsx97(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__ */ jsxs88("div", { className: "fd-fb-list", children: [
13742
+ subfolders.map((f) => /* @__PURE__ */ jsx97(
13498
13743
  RowShell,
13499
13744
  {
13500
13745
  icon: "folder-simple",
@@ -13503,9 +13748,9 @@ function FileBrowser({
13503
13748
  draggableId: canMove ? { kind: "folder", id: f.id } : void 0,
13504
13749
  isDropTarget: canMove,
13505
13750
  onDropPayload: (p) => moveIntoFolder(p, f.id),
13506
- actions: /* @__PURE__ */ jsxs87(Fragment28, { children: [
13507
- canRenameFolder ? /* @__PURE__ */ jsx96(IconButton, { icon: "pencil-simple", label: "Rename " + f.name, size: "sm", variant: "ghost", onClick: () => openRename(f) }) : null,
13508
- canMove ? /* @__PURE__ */ jsx96(
13751
+ actions: /* @__PURE__ */ jsxs88(Fragment28, { children: [
13752
+ canRenameFolder ? /* @__PURE__ */ jsx97(IconButton, { icon: "pencil-simple", label: "Rename " + f.name, size: "sm", variant: "ghost", onClick: () => openRename(f) }) : null,
13753
+ canMove ? /* @__PURE__ */ jsx97(
13509
13754
  FolderPickerMenu,
13510
13755
  {
13511
13756
  label: "Move " + f.name,
@@ -13513,12 +13758,12 @@ function FileBrowser({
13513
13758
  onPick: (target) => moveIntoFolder({ kind: "folder", id: f.id }, target)
13514
13759
  }
13515
13760
  ) : null,
13516
- canDeleteFolder ? /* @__PURE__ */ jsx96(IconButton, { icon: "trash-simple", label: "Delete " + f.name, size: "sm", variant: "ghost", onClick: () => openDelete(f) }) : null
13761
+ canDeleteFolder ? /* @__PURE__ */ jsx97(IconButton, { icon: "trash-simple", label: "Delete " + f.name, size: "sm", variant: "ghost", onClick: () => openDelete(f) }) : null
13517
13762
  ] })
13518
13763
  },
13519
13764
  f.id
13520
13765
  )),
13521
- currentFiles.map((file) => /* @__PURE__ */ jsx96(
13766
+ currentFiles.map((file) => /* @__PURE__ */ jsx97(
13522
13767
  RowShell,
13523
13768
  {
13524
13769
  icon: iconForMime(file.mime, file.name),
@@ -13526,8 +13771,8 @@ function FileBrowser({
13526
13771
  meta: file.size ? formatBytes(file.size) : void 0,
13527
13772
  onOpen: onOpenFile ? () => onOpenFile(file) : void 0,
13528
13773
  draggableId: canMove ? { kind: "file", id: file.id } : void 0,
13529
- actions: /* @__PURE__ */ jsxs87(Fragment28, { children: [
13530
- canMove ? /* @__PURE__ */ jsx96(
13774
+ actions: /* @__PURE__ */ jsxs88(Fragment28, { children: [
13775
+ canMove ? /* @__PURE__ */ jsx97(
13531
13776
  FolderPickerMenu,
13532
13777
  {
13533
13778
  label: "Move " + file.name,
@@ -13535,7 +13780,7 @@ function FileBrowser({
13535
13780
  onPick: (target) => onMoveFile && onMoveFile(file.id, target)
13536
13781
  }
13537
13782
  ) : null,
13538
- canRemoveFile ? /* @__PURE__ */ jsx96(IconButton, { icon: "trash-simple", label: "Remove " + file.name, size: "sm", variant: "ghost", onClick: () => onRemoveFile && onRemoveFile(file) }) : null
13783
+ canRemoveFile ? /* @__PURE__ */ jsx97(IconButton, { icon: "trash-simple", label: "Remove " + file.name, size: "sm", variant: "ghost", onClick: () => onRemoveFile && onRemoveFile(file) }) : null
13539
13784
  ] })
13540
13785
  },
13541
13786
  file.id
@@ -13544,10 +13789,10 @@ function FileBrowser({
13544
13789
  }
13545
13790
  ) })
13546
13791
  ] }),
13547
- /* @__PURE__ */ jsx96(Modal, { open: createOpen, title: "New folder", onClose: () => setCreateOpen(false), footer: /* @__PURE__ */ jsxs87(Fragment28, { children: [
13548
- /* @__PURE__ */ jsx96(Button, { variant: "secondary", onClick: () => setCreateOpen(false), children: "Cancel" }),
13549
- /* @__PURE__ */ jsx96(Button, { onClick: submitCreate, disabled: !createName.trim(), children: "Create" })
13550
- ] }), children: /* @__PURE__ */ jsx96(
13792
+ /* @__PURE__ */ jsx97(Modal, { open: createOpen, title: "New folder", onClose: () => setCreateOpen(false), footer: /* @__PURE__ */ jsxs88(Fragment28, { children: [
13793
+ /* @__PURE__ */ jsx97(Button, { variant: "secondary", onClick: () => setCreateOpen(false), children: "Cancel" }),
13794
+ /* @__PURE__ */ jsx97(Button, { onClick: submitCreate, disabled: !createName.trim(), children: "Create" })
13795
+ ] }), children: /* @__PURE__ */ jsx97(
13551
13796
  "input",
13552
13797
  {
13553
13798
  className: "fd-fb-input",
@@ -13561,10 +13806,10 @@ function FileBrowser({
13561
13806
  autoFocus: true
13562
13807
  }
13563
13808
  ) }),
13564
- /* @__PURE__ */ jsx96(Modal, { open: renameTarget != null, title: "Rename folder", onClose: () => setRenameTarget(null), footer: /* @__PURE__ */ jsxs87(Fragment28, { children: [
13565
- /* @__PURE__ */ jsx96(Button, { variant: "secondary", onClick: () => setRenameTarget(null), children: "Cancel" }),
13566
- /* @__PURE__ */ jsx96(Button, { onClick: submitRename, disabled: !renameValue.trim(), children: "Save" })
13567
- ] }), children: /* @__PURE__ */ jsx96(
13809
+ /* @__PURE__ */ jsx97(Modal, { open: renameTarget != null, title: "Rename folder", onClose: () => setRenameTarget(null), footer: /* @__PURE__ */ jsxs88(Fragment28, { children: [
13810
+ /* @__PURE__ */ jsx97(Button, { variant: "secondary", onClick: () => setRenameTarget(null), children: "Cancel" }),
13811
+ /* @__PURE__ */ jsx97(Button, { onClick: submitRename, disabled: !renameValue.trim(), children: "Save" })
13812
+ ] }), children: /* @__PURE__ */ jsx97(
13568
13813
  "input",
13569
13814
  {
13570
13815
  className: "fd-fb-input",
@@ -13578,22 +13823,22 @@ function FileBrowser({
13578
13823
  autoFocus: true
13579
13824
  }
13580
13825
  ) }),
13581
- /* @__PURE__ */ jsx96(
13826
+ /* @__PURE__ */ jsx97(
13582
13827
  Modal,
13583
13828
  {
13584
13829
  open: deleteTarget != null,
13585
13830
  title: deleteTarget ? "Delete \u201C" + deleteTarget.name + "\u201D?" : "Delete folder?",
13586
13831
  description: "This can't be undone. The folder must be empty.",
13587
13832
  onClose: () => setDeleteTarget(null),
13588
- footer: /* @__PURE__ */ jsxs87(Fragment28, { children: [
13589
- /* @__PURE__ */ jsx96(Button, { variant: "secondary", onClick: () => setDeleteTarget(null), children: "Cancel" }),
13590
- /* @__PURE__ */ jsx96(Button, { variant: "danger", onClick: confirmDelete, children: "Delete" })
13833
+ footer: /* @__PURE__ */ jsxs88(Fragment28, { children: [
13834
+ /* @__PURE__ */ jsx97(Button, { variant: "secondary", onClick: () => setDeleteTarget(null), children: "Cancel" }),
13835
+ /* @__PURE__ */ jsx97(Button, { variant: "danger", onClick: confirmDelete, children: "Delete" })
13591
13836
  ] })
13592
13837
  }
13593
13838
  )
13594
13839
  ] });
13595
13840
  if (!canUpload) return content;
13596
- return /* @__PURE__ */ jsx96(Dropzone, { className: "fd-fb-dropzone", onFiles: (picked) => onUpload && onUpload(picked, currentFolderId), label: "Drop files to upload", children: content });
13841
+ return /* @__PURE__ */ jsx97(Dropzone, { className: "fd-fb-dropzone", onFiles: (picked) => onUpload && onUpload(picked, currentFolderId), label: "Drop files to upload", children: content });
13597
13842
  }
13598
13843
  function BreadcrumbCrumb({
13599
13844
  label,
@@ -13602,8 +13847,8 @@ function BreadcrumbCrumb({
13602
13847
  isDropTarget,
13603
13848
  onDropPayload
13604
13849
  }) {
13605
- const [over, setOver] = React65.useState(false);
13606
- const dragCounter = React65.useRef(0);
13850
+ const [over, setOver] = React66.useState(false);
13851
+ const dragCounter = React66.useRef(0);
13607
13852
  const dropHandlers = isDropTarget ? {
13608
13853
  onDragEnter: (e) => {
13609
13854
  if (!hasInternalPayload(e)) return;
@@ -13628,11 +13873,11 @@ function BreadcrumbCrumb({
13628
13873
  if (payload && onDropPayload) onDropPayload(payload);
13629
13874
  }
13630
13875
  } : {};
13631
- return /* @__PURE__ */ jsx96("span", { className: ["fd-fb-crumb", over ? "is-drop-target" : ""].filter(Boolean).join(" "), ...dropHandlers, children: isCurrent ? /* @__PURE__ */ jsx96("span", { className: "fd-fb-crumb-current", "aria-current": "page", children: label }) : /* @__PURE__ */ jsx96("button", { type: "button", className: "fd-fb-crumb-link", onClick, children: label }) });
13876
+ return /* @__PURE__ */ jsx97("span", { className: ["fd-fb-crumb", over ? "is-drop-target" : ""].filter(Boolean).join(" "), ...dropHandlers, children: isCurrent ? /* @__PURE__ */ jsx97("span", { className: "fd-fb-crumb-current", "aria-current": "page", children: label }) : /* @__PURE__ */ jsx97("button", { type: "button", className: "fd-fb-crumb-link", onClick, children: label }) });
13632
13877
  }
13633
13878
 
13634
13879
  // src/kits/query.ts
13635
- import * as React66 from "react";
13880
+ import * as React67 from "react";
13636
13881
  var isMultiSelectShaped = (v) => !!v && typeof v === "object" && Array.isArray(v.values);
13637
13882
  var isRangeShaped = (v) => !!v && typeof v === "object" && ("min" in v || "max" in v);
13638
13883
  var isDateShaped = (v) => !!v && typeof v === "object" && "kind" in v;
@@ -13687,22 +13932,22 @@ function compare(a, b, dir) {
13687
13932
  var API = null;
13688
13933
  var PREFS = null;
13689
13934
  function useServerTable({ endpoint, params, defaults, deps, prefsKey }) {
13690
- const [query, setQuery] = React66.useState(() => {
13935
+ const [query, setQuery] = React67.useState(() => {
13691
13936
  const store = PREFS || window.PlannerPrefs;
13692
13937
  const saved = prefsKey && store ? store.getTable(prefsKey) : {};
13693
13938
  return { ...DEFAULTS, ...defaults || {}, ...saved.pageSize ? { pageSize: saved.pageSize } : {}, ...saved.sort ? { sort: saved.sort, dir: saved.dir || "desc" } : {} };
13694
13939
  });
13695
- const savePref = React66.useCallback((patch2) => {
13940
+ const savePref = React67.useCallback((patch2) => {
13696
13941
  const store = PREFS || window.PlannerPrefs;
13697
13942
  if (prefsKey && store) store.setTable(prefsKey, patch2);
13698
13943
  }, [prefsKey]);
13699
- const [res, setRes] = React66.useState(null);
13700
- const [loading, setLoading] = React66.useState(true);
13701
- const seq2 = React66.useRef(0);
13944
+ const [res, setRes] = React67.useState(null);
13945
+ const [loading, setLoading] = React67.useState(true);
13946
+ const seq2 = React67.useRef(0);
13702
13947
  const depKey = (deps || []).join("|");
13703
13948
  const paramKey = JSON.stringify(params || {});
13704
13949
  const queryKey = JSON.stringify(query);
13705
- React66.useEffect(() => {
13950
+ React67.useEffect(() => {
13706
13951
  const id = ++seq2.current;
13707
13952
  setLoading(true);
13708
13953
  const t = setTimeout(() => {
@@ -14021,12 +14266,12 @@ function createVersionStore(initialState, options) {
14021
14266
  }
14022
14267
 
14023
14268
  // src/kits/documentTitle.ts
14024
- import * as React67 from "react";
14269
+ import * as React68 from "react";
14025
14270
  function formatDocumentTitle(routeTitle, appName) {
14026
14271
  return [routeTitle, appName, "Flytedesk"].filter((part) => !!part && part.length > 0).join(" \xB7 ");
14027
14272
  }
14028
14273
  function useDocumentTitle(routeTitle, appName) {
14029
- React67.useEffect(() => {
14274
+ React68.useEffect(() => {
14030
14275
  if (typeof document === "undefined") return;
14031
14276
  document.title = formatDocumentTitle(routeTitle, appName);
14032
14277
  }, [routeTitle, appName]);
@@ -14068,6 +14313,7 @@ export {
14068
14313
  Clamp,
14069
14314
  ClockFace,
14070
14315
  CodeBlock,
14316
+ CodeEditor,
14071
14317
  Collapsible,
14072
14318
  ComingSoon,
14073
14319
  CsiBadge,
@@ -14113,6 +14359,7 @@ export {
14113
14359
  JobTray,
14114
14360
  Json,
14115
14361
  KeyHint,
14362
+ LAYER_STEP,
14116
14363
  LoadingRegion,
14117
14364
  Markdown,
14118
14365
  MarkdownEditor,
@@ -14127,6 +14374,7 @@ export {
14127
14374
  ModeSwitch,
14128
14375
  ModelControls,
14129
14376
  NumberInput,
14377
+ OVERLAY_CEILING,
14130
14378
  POPOVER_BODY_MIN,
14131
14379
  PacketCard,
14132
14380
  Pagination,
@@ -14139,6 +14387,7 @@ export {
14139
14387
  ProgressBar,
14140
14388
  QueryKit,
14141
14389
  QuotaRow,
14390
+ ROOT_STEP,
14142
14391
  Radio,
14143
14392
  RangeSlider,
14144
14393
  RelativeTime,
@@ -14183,6 +14432,7 @@ export {
14183
14432
  VIRTUAL_LIST_BUFFER_ROWS,
14184
14433
  VIRTUAL_LIST_ROW_GAP,
14185
14434
  VirtualList,
14435
+ __resetLayerStackForTests,
14186
14436
  acceptMatches,
14187
14437
  anyOfFilter,
14188
14438
  applyPrefs,
@@ -14232,6 +14482,7 @@ export {
14232
14482
  useChatEngine,
14233
14483
  useDocumentTitle,
14234
14484
  useFeatureStatus,
14485
+ useLayerZIndex,
14235
14486
  usePopoverPosition,
14236
14487
  useResponsiveRail,
14237
14488
  useRuntimeMode,