@flytedan/flytebot-design-system 0.48.1 → 0.49.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -66,6 +66,7 @@ __export(index_exports, {
66
66
  Clamp: () => Clamp,
67
67
  ClockFace: () => ClockFace,
68
68
  CodeBlock: () => CodeBlock,
69
+ CodeEditor: () => CodeEditor,
69
70
  Collapsible: () => Collapsible,
70
71
  ComingSoon: () => ComingSoon,
71
72
  CsiBadge: () => CsiBadge,
@@ -4885,7 +4886,7 @@ function CodeBlock({
4885
4886
  code = "",
4886
4887
  language,
4887
4888
  filename,
4888
- lineNumbers = false,
4889
+ lineNumbers: lineNumbers2 = false,
4889
4890
  wrap: wrapDefault = false,
4890
4891
  collapseAfter = 26,
4891
4892
  copyable = true,
@@ -4912,7 +4913,7 @@ function CodeBlock({
4912
4913
  ] }) : null
4913
4914
  ] }),
4914
4915
  /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("div", { className: "fd-code-body", children: [
4915
- lineNumbers ? /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("pre", { className: "fd-code-gutter", "aria-hidden": "true", children: shown.split("\n").map((_, i) => i + 1 + "\n").join("") }) : null,
4916
+ lineNumbers2 ? /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("pre", { className: "fd-code-gutter", "aria-hidden": "true", children: shown.split("\n").map((_, i) => i + 1 + "\n").join("") }) : null,
4916
4917
  /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("pre", { className: "fd-code-pre", tabIndex: 0, children: /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("code", { children: /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(Highlighted, { code: shown, lang: language }) }) })
4917
4918
  ] }),
4918
4919
  foldable ? /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("button", { type: "button", className: "fd-code-fold", onClick: () => setOpen((v) => !v), "aria-expanded": open2, children: [
@@ -7495,17 +7496,254 @@ var MarkdownEditor = React42.forwardRef(function MarkdownEditor2({
7495
7496
  ] });
7496
7497
  });
7497
7498
 
7499
+ // src/components/forms/CodeEditor.tsx
7500
+ var React43 = __toESM(require("react"), 1);
7501
+ var import_view = require("@codemirror/view");
7502
+ var import_state = require("@codemirror/state");
7503
+ var import_commands = require("@codemirror/commands");
7504
+ var import_lang_sql = require("@codemirror/lang-sql");
7505
+ var import_language = require("@codemirror/language");
7506
+ var import_highlight = require("@lezer/highlight");
7507
+ var import_jsx_runtime73 = require("react/jsx-runtime");
7508
+ function clampOffset(state, line, column) {
7509
+ const total = state.doc.lines;
7510
+ const ln = state.doc.line(Math.min(Math.max(1, line), total));
7511
+ const col = Math.max(0, (column || 1) - 1);
7512
+ return Math.min(ln.from + col, ln.to);
7513
+ }
7514
+ function toCmDiagnostics(state, diags) {
7515
+ return diags.map((d) => {
7516
+ const from = clampOffset(state, d.line, d.column ?? 1);
7517
+ const endLine = d.endLine ?? d.line;
7518
+ const endColumn = d.endColumn ?? state.doc.line(Math.min(Math.max(1, endLine), state.doc.lines)).length + 1;
7519
+ let to = clampOffset(state, endLine, endColumn);
7520
+ if (to <= from) to = Math.min(from + 1, state.doc.length);
7521
+ return { from, to, severity: d.severity || "error", message: d.message, source: void 0 };
7522
+ });
7523
+ }
7524
+ var setDiagnosticsEffect = import_state.StateEffect.define();
7525
+ var diagnosticsField = import_state.StateField.define({
7526
+ create: () => [],
7527
+ update(value, tr) {
7528
+ for (const e of tr.effects) if (e.is(setDiagnosticsEffect)) return e.value;
7529
+ if (!tr.docChanged) return value;
7530
+ return value.map((d) => ({ ...d, from: tr.changes.mapPos(d.from), to: tr.changes.mapPos(d.to) }));
7531
+ }
7532
+ });
7533
+ var tokenHighlight = import_language.HighlightStyle.define([
7534
+ { tag: import_highlight.tags.keyword, class: "tok-kw" },
7535
+ { tag: import_highlight.tags.string, class: "tok-str" },
7536
+ { tag: [import_highlight.tags.number, import_highlight.tags.bool], class: "tok-num" },
7537
+ { tag: import_highlight.tags.comment, class: "tok-com" },
7538
+ { tag: [import_highlight.tags.function(import_highlight.tags.variableName), import_highlight.tags.function(import_highlight.tags.propertyName)], class: "tok-fn" },
7539
+ { tag: import_highlight.tags.typeName, class: "tok-type" },
7540
+ { tag: import_highlight.tags.propertyName, class: "tok-prop" },
7541
+ { tag: import_highlight.tags.null, class: "tok-lit" },
7542
+ { tag: [import_highlight.tags.punctuation, import_highlight.tags.paren, import_highlight.tags.bracket], class: "tok-pun" },
7543
+ { tag: import_highlight.tags.operator, class: "tok-op" }
7544
+ ]);
7545
+ var editorTheme = import_view.EditorView.theme({
7546
+ "&": {
7547
+ fontFamily: "var(--font-mono)",
7548
+ fontSize: "12.5px",
7549
+ color: "var(--text)",
7550
+ backgroundColor: "transparent",
7551
+ height: "100%"
7552
+ },
7553
+ ".cm-content": { padding: "10px 12px", caretColor: "var(--text)" },
7554
+ ".cm-scroller": { fontFamily: "var(--font-mono)", lineHeight: "1.62" },
7555
+ ".cm-gutters": {
7556
+ backgroundColor: "transparent",
7557
+ color: "var(--text-disabled)",
7558
+ border: "0",
7559
+ borderRight: "1px solid var(--chat-code-border)"
7560
+ },
7561
+ ".cm-lineNumbers .cm-gutterElement": { padding: "0 8px 0 12px" },
7562
+ ".cm-activeLine": { backgroundColor: "var(--surface-2)" },
7563
+ ".cm-activeLineGutter": { backgroundColor: "var(--surface-2)", color: "var(--text-2)" },
7564
+ "&.cm-focused": { outline: "none" },
7565
+ ".cm-cursor": { borderLeftColor: "var(--text)" },
7566
+ ".cm-selectionBackground, &.cm-focused .cm-selectionBackground": { backgroundColor: "var(--blue-100) !important" },
7567
+ ".cm-placeholder": { color: "var(--text-disabled)" },
7568
+ ".fd-cm-diag-error": { textDecoration: "underline wavy var(--danger-solid)", textUnderlineOffset: "3px" },
7569
+ ".fd-cm-diag-warning": { textDecoration: "underline wavy var(--warn-solid)", textUnderlineOffset: "3px" },
7570
+ ".fd-cm-diag-info": { textDecoration: "underline wavy var(--info-solid)", textUnderlineOffset: "3px" }
7571
+ }, { dark: false });
7572
+ function severityClass(sev) {
7573
+ return sev === "warning" ? "fd-cm-diag-warning" : sev === "info" ? "fd-cm-diag-info" : "fd-cm-diag-error";
7574
+ }
7575
+ function decorationsFromDiagnostics() {
7576
+ return import_view.EditorView.decorations.compute([diagnosticsField], (state) => {
7577
+ const diags = state.field(diagnosticsField);
7578
+ if (!diags.length) return import_view.Decoration.none;
7579
+ const marks = diags.filter((d) => d.from < d.to).sort((a, b) => a.from - b.from).map((d) => import_view.Decoration.mark({ class: severityClass(d.severity) }).range(d.from, d.to));
7580
+ return import_view.Decoration.set(marks, true);
7581
+ });
7582
+ }
7583
+ function CodeEditor({
7584
+ value,
7585
+ onChange,
7586
+ label,
7587
+ help,
7588
+ error,
7589
+ required = false,
7590
+ disabled = false,
7591
+ readOnly = false,
7592
+ placeholder: placeholderText = "",
7593
+ diagnostics = [],
7594
+ showEscapeHint = true,
7595
+ minHeight = 160,
7596
+ id,
7597
+ className = "",
7598
+ style,
7599
+ autoFocus = false
7600
+ }) {
7601
+ const fieldId = useFieldId(id);
7602
+ const descId = fieldId + "-desc";
7603
+ const liveId = fieldId + "-live";
7604
+ const hostRef = React43.useRef(null);
7605
+ const viewRef = React43.useRef(null);
7606
+ const valueRef = React43.useRef(value);
7607
+ const onChangeRef = React43.useRef(onChange);
7608
+ onChangeRef.current = onChange;
7609
+ const editableCompartment = React43.useRef(new import_state.Compartment()).current;
7610
+ const attributesCompartment = React43.useRef(new import_state.Compartment()).current;
7611
+ const errorRef = React43.useRef(error);
7612
+ errorRef.current = error;
7613
+ const diagnosticsCountRef = React43.useRef(diagnostics.length);
7614
+ diagnosticsCountRef.current = diagnostics.length;
7615
+ function contentAttributes() {
7616
+ return {
7617
+ id: fieldId,
7618
+ "aria-describedby": descId + " " + liveId,
7619
+ "aria-invalid": errorRef.current || diagnosticsCountRef.current ? "true" : "false",
7620
+ ...label ? { "aria-label": label } : {}
7621
+ };
7622
+ }
7623
+ React43.useEffect(() => {
7624
+ const host = hostRef.current;
7625
+ if (!host) return;
7626
+ const updateListener = import_view.EditorView.updateListener.of((update) => {
7627
+ if (!update.docChanged) return;
7628
+ const next = update.state.doc.toString();
7629
+ valueRef.current = next;
7630
+ onChangeRef.current && onChangeRef.current(next);
7631
+ });
7632
+ const state = import_state.EditorState.create({
7633
+ doc: value,
7634
+ extensions: [
7635
+ (0, import_view.lineNumbers)(),
7636
+ (0, import_commands.history)(),
7637
+ (0, import_view.drawSelection)(),
7638
+ (0, import_language.indentOnInput)(),
7639
+ (0, import_language.bracketMatching)(),
7640
+ (0, import_lang_sql.sql)(),
7641
+ (0, import_language.syntaxHighlighting)(tokenHighlight),
7642
+ diagnosticsField,
7643
+ decorationsFromDiagnostics(),
7644
+ editorTheme,
7645
+ (0, import_view.placeholder)(placeholderText),
7646
+ import_view.keymap.of([
7647
+ { key: "Tab", run: import_commands.indentMore, shift: import_commands.indentLess },
7648
+ ...import_commands.defaultKeymap,
7649
+ ...import_commands.historyKeymap
7650
+ ]),
7651
+ editableCompartment.of(import_view.EditorView.editable.of(!disabled)),
7652
+ import_state.EditorState.readOnly.of(readOnly),
7653
+ updateListener,
7654
+ attributesCompartment.of(import_view.EditorView.contentAttributes.of(contentAttributes()))
7655
+ ]
7656
+ });
7657
+ const view = new import_view.EditorView({ state, parent: host });
7658
+ viewRef.current = view;
7659
+ if (autoFocus) view.focus();
7660
+ return () => {
7661
+ view.destroy();
7662
+ viewRef.current = null;
7663
+ };
7664
+ }, []);
7665
+ React43.useEffect(() => {
7666
+ const view = viewRef.current;
7667
+ if (!view) return;
7668
+ const current2 = view.state.doc.toString();
7669
+ if (current2 !== value) {
7670
+ view.dispatch({ changes: { from: 0, to: current2.length, insert: value } });
7671
+ }
7672
+ valueRef.current = value;
7673
+ }, [value]);
7674
+ React43.useEffect(() => {
7675
+ const view = viewRef.current;
7676
+ if (!view) return;
7677
+ view.dispatch({ effects: editableCompartment.reconfigure(import_view.EditorView.editable.of(!disabled)) });
7678
+ }, [disabled, editableCompartment]);
7679
+ React43.useEffect(() => {
7680
+ const view = viewRef.current;
7681
+ if (!view) return;
7682
+ view.dispatch({
7683
+ effects: [
7684
+ setDiagnosticsEffect.of(toCmDiagnostics(view.state, diagnostics)),
7685
+ attributesCompartment.reconfigure(import_view.EditorView.contentAttributes.of(contentAttributes()))
7686
+ ]
7687
+ });
7688
+ }, [diagnostics, error]);
7689
+ const box = ["fd-input", "fd-code-editor", error ? "fd-input-error" : "", disabled ? "fd-input-disabled" : ""].filter(Boolean).join(" ");
7690
+ 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("; ") : "";
7691
+ return /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("div", { className: ["fd-field", className].filter(Boolean).join(" "), style, children: [
7692
+ label ? /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(FieldLabel, { htmlFor: fieldId, required, children: label }) : null,
7693
+ /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(
7694
+ "div",
7695
+ {
7696
+ className: box,
7697
+ style: { minHeight },
7698
+ children: /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(
7699
+ "div",
7700
+ {
7701
+ ref: hostRef,
7702
+ className: "fd-code-editor-host",
7703
+ style: { minHeight }
7704
+ }
7705
+ )
7706
+ }
7707
+ ),
7708
+ /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("span", { id: descId, className: "fd-sr", children: [
7709
+ help ? help + ". " : "",
7710
+ showEscapeHint ? "Tab indents. Press Escape, then Tab, to move focus out of the editor." : ""
7711
+ ] }),
7712
+ /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("div", { id: liveId, className: "fd-sr", role: "status", "aria-live": "polite", children: announce }),
7713
+ diagnostics.length ? /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("ul", { className: "fd-code-editor-diagnostics", children: diagnostics.map((d, i) => /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("li", { className: "fd-code-editor-diag is-" + (d.severity || "error"), children: [
7714
+ /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(
7715
+ "i",
7716
+ {
7717
+ className: "ph ph-" + (d.severity === "warning" ? "warning" : d.severity === "info" ? "info" : "warning-circle"),
7718
+ "aria-hidden": "true"
7719
+ }
7720
+ ),
7721
+ /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("span", { className: "fd-code-editor-diag-loc", children: [
7722
+ "Line ",
7723
+ d.line,
7724
+ d.column ? ":" + d.column : ""
7725
+ ] }),
7726
+ /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("span", { children: d.message })
7727
+ ] }, i)) }) : null,
7728
+ error ? /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("span", { className: "fd-field-error", children: [
7729
+ /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
7730
+ error
7731
+ ] }) : !diagnostics.length && help ? /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("span", { className: "fd-field-help", children: help }) : null,
7732
+ showEscapeHint ? /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("span", { className: "fd-field-help fd-code-editor-hint", children: "Tab indents. Escape, then Tab, moves focus out." }) : null
7733
+ ] });
7734
+ }
7735
+
7498
7736
  // src/components/platform/AccountMenu.tsx
7499
- var React44 = __toESM(require("react"), 1);
7737
+ var React45 = __toESM(require("react"), 1);
7500
7738
 
7501
7739
  // src/kits/sessionContext.tsx
7502
- var React43 = __toESM(require("react"), 1);
7503
- var SessionContext = React43.createContext(null);
7740
+ var React44 = __toESM(require("react"), 1);
7741
+ var SessionContext = React44.createContext(null);
7504
7742
  function SessionProvider({ value, children }) {
7505
- return React43.createElement(SessionContext.Provider, { value }, children);
7743
+ return React44.createElement(SessionContext.Provider, { value }, children);
7506
7744
  }
7507
7745
  function useSessionContext() {
7508
- const ctx = React43.useContext(SessionContext);
7746
+ const ctx = React44.useContext(SessionContext);
7509
7747
  if (!ctx) {
7510
7748
  throw new Error(
7511
7749
  "useSessionContext() was called outside a <SessionProvider>. Wrap your app root in <SessionProvider value={...}> with your real session, or \u2014 in the docs site or a demo \u2014 in <DemoSessionProvider>, before rendering AccountMenu, Gate, ProfilePage or AppSwitcher."
@@ -7515,11 +7753,11 @@ function useSessionContext() {
7515
7753
  }
7516
7754
 
7517
7755
  // src/components/platform/AccountMenu.tsx
7518
- var import_jsx_runtime73 = require("react/jsx-runtime");
7756
+ var import_jsx_runtime74 = require("react/jsx-runtime");
7519
7757
  var DEFAULT_LINKS = [];
7520
7758
  var DEFAULT_GROUPS = [];
7521
7759
  function Item({ item, onPick }) {
7522
- return /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)(
7760
+ return /* @__PURE__ */ (0, import_jsx_runtime74.jsxs)(
7523
7761
  "button",
7524
7762
  {
7525
7763
  type: "button",
@@ -7527,9 +7765,9 @@ function Item({ item, onPick }) {
7527
7765
  className: "fd-acct-item",
7528
7766
  onClick: () => onPick(item),
7529
7767
  children: [
7530
- item.icon ? /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("i", { className: "ph ph-" + item.icon, "aria-hidden": "true" }) : null,
7531
- /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("span", { style: { flex: 1 }, children: item.label }),
7532
- item.badge ? /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(Badge, { tone: "neutral", children: item.badge }) : null
7768
+ item.icon ? /* @__PURE__ */ (0, import_jsx_runtime74.jsx)("i", { className: "ph ph-" + item.icon, "aria-hidden": "true" }) : null,
7769
+ /* @__PURE__ */ (0, import_jsx_runtime74.jsx)("span", { style: { flex: 1 }, children: item.label }),
7770
+ item.badge ? /* @__PURE__ */ (0, import_jsx_runtime74.jsx)(Badge, { tone: "neutral", children: item.badge }) : null
7533
7771
  ]
7534
7772
  }
7535
7773
  );
@@ -7545,11 +7783,11 @@ function AccountMenu({
7545
7783
  ...rest
7546
7784
  }) {
7547
7785
  const { user, roles, can: can2, signOut: ctxSignOut, demo, pending } = useSessionContext();
7548
- const [open2, setOpen] = React44.useState(false);
7549
- const [switching, setSwitching] = React44.useState(false);
7550
- const [signingOut, setSigningOut] = React44.useState(false);
7551
- const [signOutError, setSignOutError] = React44.useState(null);
7552
- const ref = React44.useRef(null);
7786
+ const [open2, setOpen] = React45.useState(false);
7787
+ const [switching, setSwitching] = React45.useState(false);
7788
+ const [signingOut, setSigningOut] = React45.useState(false);
7789
+ const [signOutError, setSignOutError] = React45.useState(null);
7790
+ const ref = React45.useRef(null);
7553
7791
  const visibleLinks = links.filter((l) => !l.perm || !pending && can2(l.perm));
7554
7792
  const visibleGroups = groups.map((g) => ({ label: g.label, links: g.links.filter((l) => !l.perm || !pending && can2(l.perm)) })).filter((g) => g.links.length);
7555
7793
  const closeMenu = () => {
@@ -7577,8 +7815,8 @@ function AccountMenu({
7577
7815
  }
7578
7816
  };
7579
7817
  const showSwitcher = allowUserSwitch && !!demo;
7580
- return /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)(import_jsx_runtime73.Fragment, { children: [
7581
- /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)(
7818
+ return /* @__PURE__ */ (0, import_jsx_runtime74.jsxs)(import_jsx_runtime74.Fragment, { children: [
7819
+ /* @__PURE__ */ (0, import_jsx_runtime74.jsxs)(
7582
7820
  "button",
7583
7821
  {
7584
7822
  type: "button",
@@ -7590,12 +7828,12 @@ function AccountMenu({
7590
7828
  onClick: () => open2 ? closeMenu() : setOpen(true),
7591
7829
  ...rest,
7592
7830
  children: [
7593
- /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(Avatar, { name: user.name, size: "sm" }),
7594
- /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("i", { className: "ph ph-caret-down", "aria-hidden": "true", style: { fontSize: 11, color: "var(--text-muted)" } })
7831
+ /* @__PURE__ */ (0, import_jsx_runtime74.jsx)(Avatar, { name: user.name, size: "sm" }),
7832
+ /* @__PURE__ */ (0, import_jsx_runtime74.jsx)("i", { className: "ph ph-caret-down", "aria-hidden": "true", style: { fontSize: 11, color: "var(--text-muted)" } })
7595
7833
  ]
7596
7834
  }
7597
7835
  ),
7598
- /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(
7836
+ /* @__PURE__ */ (0, import_jsx_runtime74.jsx)(
7599
7837
  Popover,
7600
7838
  {
7601
7839
  open: open2,
@@ -7603,27 +7841,27 @@ function AccountMenu({
7603
7841
  onClose: closeMenu,
7604
7842
  placement: "bottom-end",
7605
7843
  width: 272,
7606
- children: /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("div", { role: "menu", className: "fd-stack", style: { gap: 0 }, children: [
7607
- /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("div", { className: "fd-row", style: { gap: 10, padding: "12px 14px", borderBottom: "1px solid var(--border)" }, children: [
7608
- /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(Avatar, { name: user.name }),
7609
- /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("span", { className: "fd-stack", style: { gap: 1, minWidth: 0, flex: 1 }, children: [
7610
- /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("span", { className: "fd-body-sm", style: { fontWeight: 700 }, children: user.name }),
7611
- /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("span", { className: "fd-body-sm fd-muted fd-table-trunc", title: truncationTitle(user.email), children: user.email })
7844
+ children: /* @__PURE__ */ (0, import_jsx_runtime74.jsxs)("div", { role: "menu", className: "fd-stack", style: { gap: 0 }, children: [
7845
+ /* @__PURE__ */ (0, import_jsx_runtime74.jsxs)("div", { className: "fd-row", style: { gap: 10, padding: "12px 14px", borderBottom: "1px solid var(--border)" }, children: [
7846
+ /* @__PURE__ */ (0, import_jsx_runtime74.jsx)(Avatar, { name: user.name }),
7847
+ /* @__PURE__ */ (0, import_jsx_runtime74.jsxs)("span", { className: "fd-stack", style: { gap: 1, minWidth: 0, flex: 1 }, children: [
7848
+ /* @__PURE__ */ (0, import_jsx_runtime74.jsx)("span", { className: "fd-body-sm", style: { fontWeight: 700 }, children: user.name }),
7849
+ /* @__PURE__ */ (0, import_jsx_runtime74.jsx)("span", { className: "fd-body-sm fd-muted fd-table-trunc", title: truncationTitle(user.email), children: user.email })
7612
7850
  ] })
7613
7851
  ] }),
7614
- showRoles && roles.length ? /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("div", { className: "fd-row", style: { gap: 6, padding: "10px 14px", flexWrap: "wrap", borderBottom: "1px solid var(--border)" }, children: roles.map((r) => /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(Badge, { tone: r.id === "owner" ? "success" : "neutral", children: r.name }, r.id)) }) : null,
7615
- visibleLinks.length ? /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("div", { className: "fd-acct-group", children: visibleLinks.map((l) => /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(Item, { item: l, onPick: pick }, l.id)) }) : null,
7616
- visibleGroups.map((g) => /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("div", { className: "fd-acct-group", style: { borderTop: "1px solid var(--border)" }, children: [
7617
- /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("span", { className: "fd-overline fd-muted", style: { padding: "8px 14px 4px", display: "block" }, children: g.label }),
7618
- g.links.map((l) => /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(Item, { item: l, onPick: pick }, l.id))
7852
+ showRoles && roles.length ? /* @__PURE__ */ (0, import_jsx_runtime74.jsx)("div", { className: "fd-row", style: { gap: 6, padding: "10px 14px", flexWrap: "wrap", borderBottom: "1px solid var(--border)" }, children: roles.map((r) => /* @__PURE__ */ (0, import_jsx_runtime74.jsx)(Badge, { tone: r.id === "owner" ? "success" : "neutral", children: r.name }, r.id)) }) : null,
7853
+ visibleLinks.length ? /* @__PURE__ */ (0, import_jsx_runtime74.jsx)("div", { className: "fd-acct-group", children: visibleLinks.map((l) => /* @__PURE__ */ (0, import_jsx_runtime74.jsx)(Item, { item: l, onPick: pick }, l.id)) }) : null,
7854
+ visibleGroups.map((g) => /* @__PURE__ */ (0, import_jsx_runtime74.jsxs)("div", { className: "fd-acct-group", style: { borderTop: "1px solid var(--border)" }, children: [
7855
+ /* @__PURE__ */ (0, import_jsx_runtime74.jsx)("span", { className: "fd-overline fd-muted", style: { padding: "8px 14px 4px", display: "block" }, children: g.label }),
7856
+ g.links.map((l) => /* @__PURE__ */ (0, import_jsx_runtime74.jsx)(Item, { item: l, onPick: pick }, l.id))
7619
7857
  ] }, g.label)),
7620
- showSwitcher && demo ? /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("div", { className: "fd-acct-group", style: { borderTop: "1px solid var(--border)" }, children: [
7621
- /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("button", { type: "button", role: "menuitem", className: "fd-acct-item", onClick: () => setSwitching((s) => !s), children: [
7622
- /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("i", { className: "ph ph-user-switch", "aria-hidden": "true" }),
7623
- /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("span", { style: { flex: 1 }, children: "View as another member" }),
7624
- /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("i", { className: "ph ph-caret-" + (switching ? "up" : "down"), "aria-hidden": "true", style: { fontSize: 11 } })
7858
+ showSwitcher && demo ? /* @__PURE__ */ (0, import_jsx_runtime74.jsxs)("div", { className: "fd-acct-group", style: { borderTop: "1px solid var(--border)" }, children: [
7859
+ /* @__PURE__ */ (0, import_jsx_runtime74.jsxs)("button", { type: "button", role: "menuitem", className: "fd-acct-item", onClick: () => setSwitching((s) => !s), children: [
7860
+ /* @__PURE__ */ (0, import_jsx_runtime74.jsx)("i", { className: "ph ph-user-switch", "aria-hidden": "true" }),
7861
+ /* @__PURE__ */ (0, import_jsx_runtime74.jsx)("span", { style: { flex: 1 }, children: "View as another member" }),
7862
+ /* @__PURE__ */ (0, import_jsx_runtime74.jsx)("i", { className: "ph ph-caret-" + (switching ? "up" : "down"), "aria-hidden": "true", style: { fontSize: 11 } })
7625
7863
  ] }),
7626
- switching ? /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("div", { className: "fd-stack", style: { gap: 0 }, children: demo.allUsers.map((u) => /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)(
7864
+ switching ? /* @__PURE__ */ (0, import_jsx_runtime74.jsx)("div", { className: "fd-stack", style: { gap: 0 }, children: demo.allUsers.map((u) => /* @__PURE__ */ (0, import_jsx_runtime74.jsxs)(
7627
7865
  "button",
7628
7866
  {
7629
7867
  type: "button",
@@ -7635,19 +7873,19 @@ function AccountMenu({
7635
7873
  setSwitching(false);
7636
7874
  },
7637
7875
  children: [
7638
- /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(Avatar, { name: u.name, size: "sm" }),
7639
- /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("span", { className: "fd-stack", style: { gap: 0, flex: 1, minWidth: 0, alignItems: "flex-start" }, children: [
7640
- /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("span", { style: { fontWeight: u.id === user.id ? 700 : 500 }, children: u.name }),
7641
- u.roles ? /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("span", { className: "fd-muted", style: { fontSize: 11.5 }, children: u.roles.join(", ") }) : null
7876
+ /* @__PURE__ */ (0, import_jsx_runtime74.jsx)(Avatar, { name: u.name, size: "sm" }),
7877
+ /* @__PURE__ */ (0, import_jsx_runtime74.jsxs)("span", { className: "fd-stack", style: { gap: 0, flex: 1, minWidth: 0, alignItems: "flex-start" }, children: [
7878
+ /* @__PURE__ */ (0, import_jsx_runtime74.jsx)("span", { style: { fontWeight: u.id === user.id ? 700 : 500 }, children: u.name }),
7879
+ u.roles ? /* @__PURE__ */ (0, import_jsx_runtime74.jsx)("span", { className: "fd-muted", style: { fontSize: 11.5 }, children: u.roles.join(", ") }) : null
7642
7880
  ] }),
7643
- u.id === user.id ? /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("i", { className: "ph ph-check", "aria-hidden": "true", style: { color: "var(--ok-text)" } }) : null
7881
+ u.id === user.id ? /* @__PURE__ */ (0, import_jsx_runtime74.jsx)("i", { className: "ph ph-check", "aria-hidden": "true", style: { color: "var(--ok-text)" } }) : null
7644
7882
  ]
7645
7883
  },
7646
7884
  u.id
7647
7885
  )) }) : null
7648
7886
  ] }) : null,
7649
- /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("div", { className: "fd-acct-group", style: { borderTop: "1px solid var(--border)" }, children: [
7650
- /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)(
7887
+ /* @__PURE__ */ (0, import_jsx_runtime74.jsxs)("div", { className: "fd-acct-group", style: { borderTop: "1px solid var(--border)" }, children: [
7888
+ /* @__PURE__ */ (0, import_jsx_runtime74.jsxs)(
7651
7889
  "button",
7652
7890
  {
7653
7891
  type: "button",
@@ -7657,14 +7895,14 @@ function AccountMenu({
7657
7895
  disabled: signingOut,
7658
7896
  onClick: signOut,
7659
7897
  children: [
7660
- signingOut ? /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(Spinner, { size: "sm" }) : /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("i", { className: "ph ph-sign-out", "aria-hidden": "true" }),
7661
- /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("span", { style: { flex: 1 }, children: signingOut ? "Signing out\u2026" : "Sign out" })
7898
+ signingOut ? /* @__PURE__ */ (0, import_jsx_runtime74.jsx)(Spinner, { size: "sm" }) : /* @__PURE__ */ (0, import_jsx_runtime74.jsx)("i", { className: "ph ph-sign-out", "aria-hidden": "true" }),
7899
+ /* @__PURE__ */ (0, import_jsx_runtime74.jsx)("span", { style: { flex: 1 }, children: signingOut ? "Signing out\u2026" : "Sign out" })
7662
7900
  ]
7663
7901
  }
7664
7902
  ),
7665
- signOutError ? /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("div", { role: "alert", className: "fd-body-sm", style: { padding: "0 14px 12px" }, children: [
7666
- /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("span", { style: { display: "block", color: "var(--danger-text)", marginBottom: 6 }, children: signOutError }),
7667
- /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("button", { type: "button", className: "fd-soon-link", disabled: signingOut, onClick: signOut, children: "Retry" })
7903
+ signOutError ? /* @__PURE__ */ (0, import_jsx_runtime74.jsxs)("div", { role: "alert", className: "fd-body-sm", style: { padding: "0 14px 12px" }, children: [
7904
+ /* @__PURE__ */ (0, import_jsx_runtime74.jsx)("span", { style: { display: "block", color: "var(--danger-text)", marginBottom: 6 }, children: signOutError }),
7905
+ /* @__PURE__ */ (0, import_jsx_runtime74.jsx)("button", { type: "button", className: "fd-soon-link", disabled: signingOut, onClick: signOut, children: "Retry" })
7668
7906
  ] }) : null
7669
7907
  ] })
7670
7908
  ] })
@@ -7674,13 +7912,13 @@ function AccountMenu({
7674
7912
  }
7675
7913
 
7676
7914
  // src/components/platform/AppSwitcher.tsx
7677
- var React45 = __toESM(require("react"), 1);
7678
- var import_jsx_runtime74 = require("react/jsx-runtime");
7915
+ var React46 = __toESM(require("react"), 1);
7916
+ var import_jsx_runtime75 = require("react/jsx-runtime");
7679
7917
  function AppSwitcher({ apps: appsProp, onNavigate, className = "" }) {
7680
7918
  const { apps: contextApps } = useSessionContext();
7681
7919
  const apps = appsProp ?? contextApps ?? [];
7682
- const [open2, setOpen] = React45.useState(false);
7683
- const anchorRef = React45.useRef(null);
7920
+ const [open2, setOpen] = React46.useState(false);
7921
+ const anchorRef = React46.useRef(null);
7684
7922
  if (!apps.length) return null;
7685
7923
  const items = apps.map((app) => ({
7686
7924
  id: app.key,
@@ -7694,8 +7932,8 @@ function AppSwitcher({ apps: appsProp, onNavigate, className = "" }) {
7694
7932
  window.location.href = app.url;
7695
7933
  }
7696
7934
  }));
7697
- return /* @__PURE__ */ (0, import_jsx_runtime74.jsxs)(React45.Fragment, { children: [
7698
- /* @__PURE__ */ (0, import_jsx_runtime74.jsx)("span", { ref: anchorRef, className: ["fd-appswitch-anchor", className].filter(Boolean).join(" "), style: { display: "inline-flex" }, children: /* @__PURE__ */ (0, import_jsx_runtime74.jsx)(
7935
+ return /* @__PURE__ */ (0, import_jsx_runtime75.jsxs)(React46.Fragment, { children: [
7936
+ /* @__PURE__ */ (0, import_jsx_runtime75.jsx)("span", { ref: anchorRef, className: ["fd-appswitch-anchor", className].filter(Boolean).join(" "), style: { display: "inline-flex" }, children: /* @__PURE__ */ (0, import_jsx_runtime75.jsx)(
7699
7937
  IconButton,
7700
7938
  {
7701
7939
  icon: "squares-four",
@@ -7705,7 +7943,7 @@ function AppSwitcher({ apps: appsProp, onNavigate, className = "" }) {
7705
7943
  onClick: () => setOpen((v) => !v)
7706
7944
  }
7707
7945
  ) }),
7708
- /* @__PURE__ */ (0, import_jsx_runtime74.jsx)(
7946
+ /* @__PURE__ */ (0, import_jsx_runtime75.jsx)(
7709
7947
  Popover,
7710
7948
  {
7711
7949
  open: open2,
@@ -7716,17 +7954,17 @@ function AppSwitcher({ apps: appsProp, onNavigate, className = "" }) {
7716
7954
  label: "All flytedesk apps",
7717
7955
  width: 240,
7718
7956
  maxHeight: 360,
7719
- children: /* @__PURE__ */ (0, import_jsx_runtime74.jsx)(Menu, { items, onClose: () => setOpen(false) })
7957
+ children: /* @__PURE__ */ (0, import_jsx_runtime75.jsx)(Menu, { items, onClose: () => setOpen(false) })
7720
7958
  }
7721
7959
  )
7722
7960
  ] });
7723
7961
  }
7724
7962
 
7725
7963
  // src/components/platform/AppearanceMenu.tsx
7726
- var React47 = __toESM(require("react"), 1);
7964
+ var React48 = __toESM(require("react"), 1);
7727
7965
 
7728
7966
  // src/kits/appearance.ts
7729
- var React46 = __toESM(require("react"), 1);
7967
+ var React47 = __toESM(require("react"), 1);
7730
7968
  var DEFAULT_STORAGE_KEY = "fd-appearance";
7731
7969
  var DEFAULT_PREFS = {
7732
7970
  theme: "system",
@@ -7821,11 +8059,11 @@ function applyPrefs(prefs, root = document.documentElement) {
7821
8059
  else root.removeAttribute("data-motion");
7822
8060
  }
7823
8061
  function useAppearancePrefs(store) {
7824
- const prefs = React46.useSyncExternalStore(store.subscribe, store.getSnapshot);
7825
- React46.useEffect(() => {
8062
+ const prefs = React47.useSyncExternalStore(store.subscribe, store.getSnapshot);
8063
+ React47.useEffect(() => {
7826
8064
  applyPrefs(prefs);
7827
8065
  }, [prefs]);
7828
- React46.useEffect(() => {
8066
+ React47.useEffect(() => {
7829
8067
  if (prefs.theme !== "system" || typeof window === "undefined" || typeof window.matchMedia !== "function") {
7830
8068
  return;
7831
8069
  }
@@ -7834,7 +8072,7 @@ function useAppearancePrefs(store) {
7834
8072
  mq.addEventListener("change", onChange);
7835
8073
  return () => mq.removeEventListener("change", onChange);
7836
8074
  }, [prefs]);
7837
- const update = React46.useCallback(
8075
+ const update = React47.useCallback(
7838
8076
  (patch) => {
7839
8077
  store.write({ ...store.getSnapshot(), ...patch });
7840
8078
  },
@@ -7844,7 +8082,7 @@ function useAppearancePrefs(store) {
7844
8082
  }
7845
8083
 
7846
8084
  // src/components/platform/AppearanceMenu.tsx
7847
- var import_jsx_runtime75 = require("react/jsx-runtime");
8085
+ var import_jsx_runtime76 = require("react/jsx-runtime");
7848
8086
  var THEME_OPTIONS = [
7849
8087
  { value: "light", label: "Light" },
7850
8088
  { value: "dark", label: "Dark" },
@@ -7857,16 +8095,16 @@ var TEXT_SCALE_OPTIONS = [
7857
8095
  { value: "xl", label: "XL" }
7858
8096
  ];
7859
8097
  function AppearanceMenu({ className = "", store: storeProp, storageKey, storage, defaults }) {
7860
- const store = React47.useMemo(
8098
+ const store = React48.useMemo(
7861
8099
  () => storeProp ?? createLocalStorageAppearanceStore({ storageKey, storage, defaults }),
7862
8100
  [storeProp, storageKey, storage, defaults]
7863
8101
  );
7864
8102
  const [prefs, update] = useAppearancePrefs(store);
7865
- const [open2, setOpen] = React47.useState(false);
7866
- const anchorRef = React47.useRef(null);
8103
+ const [open2, setOpen] = React48.useState(false);
8104
+ const anchorRef = React48.useRef(null);
7867
8105
  const patch = (p) => update(p);
7868
- return /* @__PURE__ */ (0, import_jsx_runtime75.jsxs)(React47.Fragment, { children: [
7869
- /* @__PURE__ */ (0, import_jsx_runtime75.jsx)("span", { ref: anchorRef, className: ["fd-appearance-anchor", className].filter(Boolean).join(" "), style: { display: "inline-flex" }, children: /* @__PURE__ */ (0, import_jsx_runtime75.jsx)(
8106
+ return /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)(React48.Fragment, { children: [
8107
+ /* @__PURE__ */ (0, import_jsx_runtime76.jsx)("span", { ref: anchorRef, className: ["fd-appearance-anchor", className].filter(Boolean).join(" "), style: { display: "inline-flex" }, children: /* @__PURE__ */ (0, import_jsx_runtime76.jsx)(
7870
8108
  IconButton,
7871
8109
  {
7872
8110
  icon: "circle-half",
@@ -7874,7 +8112,7 @@ function AppearanceMenu({ className = "", store: storeProp, storageKey, storage,
7874
8112
  onClick: () => setOpen((v) => !v)
7875
8113
  }
7876
8114
  ) }),
7877
- /* @__PURE__ */ (0, import_jsx_runtime75.jsx)(
8115
+ /* @__PURE__ */ (0, import_jsx_runtime76.jsx)(
7878
8116
  Popover,
7879
8117
  {
7880
8118
  open: open2,
@@ -7884,10 +8122,10 @@ function AppearanceMenu({ className = "", store: storeProp, storageKey, storage,
7884
8122
  padded: true,
7885
8123
  width: 260,
7886
8124
  label: "Appearance settings",
7887
- children: /* @__PURE__ */ (0, import_jsx_runtime75.jsxs)("div", { className: "fd-stack", style: { display: "flex", flexDirection: "column", gap: 16 }, children: [
7888
- /* @__PURE__ */ (0, import_jsx_runtime75.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: 6 }, children: [
7889
- /* @__PURE__ */ (0, import_jsx_runtime75.jsx)("span", { className: "fd-field-label", children: "Theme" }),
7890
- /* @__PURE__ */ (0, import_jsx_runtime75.jsx)(
8125
+ children: /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)("div", { className: "fd-stack", style: { display: "flex", flexDirection: "column", gap: 16 }, children: [
8126
+ /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: 6 }, children: [
8127
+ /* @__PURE__ */ (0, import_jsx_runtime76.jsx)("span", { className: "fd-field-label", children: "Theme" }),
8128
+ /* @__PURE__ */ (0, import_jsx_runtime76.jsx)(
7891
8129
  SegmentedControl,
7892
8130
  {
7893
8131
  options: THEME_OPTIONS,
@@ -7897,9 +8135,9 @@ function AppearanceMenu({ className = "", store: storeProp, storageKey, storage,
7897
8135
  }
7898
8136
  )
7899
8137
  ] }),
7900
- /* @__PURE__ */ (0, import_jsx_runtime75.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: 6 }, children: [
7901
- /* @__PURE__ */ (0, import_jsx_runtime75.jsx)("span", { className: "fd-field-label", children: "Text size" }),
7902
- /* @__PURE__ */ (0, import_jsx_runtime75.jsx)(
8138
+ /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: 6 }, children: [
8139
+ /* @__PURE__ */ (0, import_jsx_runtime76.jsx)("span", { className: "fd-field-label", children: "Text size" }),
8140
+ /* @__PURE__ */ (0, import_jsx_runtime76.jsx)(
7903
8141
  SegmentedControl,
7904
8142
  {
7905
8143
  options: TEXT_SCALE_OPTIONS,
@@ -7909,7 +8147,7 @@ function AppearanceMenu({ className = "", store: storeProp, storageKey, storage,
7909
8147
  }
7910
8148
  )
7911
8149
  ] }),
7912
- /* @__PURE__ */ (0, import_jsx_runtime75.jsx)(
8150
+ /* @__PURE__ */ (0, import_jsx_runtime76.jsx)(
7913
8151
  Switch,
7914
8152
  {
7915
8153
  label: "High contrast",
@@ -7918,7 +8156,7 @@ function AppearanceMenu({ className = "", store: storeProp, storageKey, storage,
7918
8156
  onChange: (e) => patch({ highContrast: e.target.checked })
7919
8157
  }
7920
8158
  ),
7921
- /* @__PURE__ */ (0, import_jsx_runtime75.jsx)(
8159
+ /* @__PURE__ */ (0, import_jsx_runtime76.jsx)(
7922
8160
  Switch,
7923
8161
  {
7924
8162
  label: "Reduce motion",
@@ -7934,14 +8172,14 @@ function AppearanceMenu({ className = "", store: storeProp, storageKey, storage,
7934
8172
  }
7935
8173
 
7936
8174
  // src/components/platform/ApiSpecBrowser.tsx
7937
- var React48 = __toESM(require("react"), 1);
7938
- var import_jsx_runtime76 = require("react/jsx-runtime");
8175
+ var React49 = __toESM(require("react"), 1);
8176
+ var import_jsx_runtime77 = require("react/jsx-runtime");
7939
8177
  var METHOD_TONE = { GET: "success", POST: "info", PATCH: "warning", PUT: "warning", DELETE: "danger" };
7940
8178
  function Json({ obj }) {
7941
- return /* @__PURE__ */ (0, import_jsx_runtime76.jsx)("pre", { className: "fd-json", children: JSON.stringify(obj, null, 2) });
8179
+ return /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("pre", { className: "fd-json", children: JSON.stringify(obj, null, 2) });
7942
8180
  }
7943
8181
  function Endpoint({ s, onRequest }) {
7944
- const [tried, setTried] = React48.useState(null);
8182
+ const [tried, setTried] = React49.useState(null);
7945
8183
  const run = async () => {
7946
8184
  setTried("busy");
7947
8185
  const t0 = (window.performance || Date).now();
@@ -7952,50 +8190,50 @@ function Endpoint({ s, onRequest }) {
7952
8190
  setTried({ ms: Math.round((window.performance || Date).now() - t0), error: String(e && e.message || e) });
7953
8191
  }
7954
8192
  };
7955
- return /* @__PURE__ */ (0, import_jsx_runtime76.jsx)(Card, { elevation: "flat", padded: false, children: /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)("div", { className: "fd-stack", style: { gap: 0 }, children: [
7956
- /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)("div", { className: "fd-row", style: { gap: 10, padding: "14px 18px", flexWrap: "wrap" }, children: [
7957
- /* @__PURE__ */ (0, import_jsx_runtime76.jsx)(Badge, { tone: METHOD_TONE[s.method] || "neutral", children: s.method }),
7958
- /* @__PURE__ */ (0, import_jsx_runtime76.jsx)("code", { className: "fd-mono", style: { fontSize: 12.5, fontWeight: 600, color: "var(--text)", wordBreak: "break-all" }, children: s.path }),
7959
- s.isList ? /* @__PURE__ */ (0, import_jsx_runtime76.jsx)(Badge, { tone: "neutral", icon: "rows", children: "Paged list" }) : null,
7960
- /* @__PURE__ */ (0, import_jsx_runtime76.jsx)("span", { style: { flex: 1 } }),
7961
- /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)("span", { className: "fd-body-sm fd-muted fd-mono", children: [
8193
+ return /* @__PURE__ */ (0, import_jsx_runtime77.jsx)(Card, { elevation: "flat", padded: false, children: /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)("div", { className: "fd-stack", style: { gap: 0 }, children: [
8194
+ /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)("div", { className: "fd-row", style: { gap: 10, padding: "14px 18px", flexWrap: "wrap" }, children: [
8195
+ /* @__PURE__ */ (0, import_jsx_runtime77.jsx)(Badge, { tone: METHOD_TONE[s.method] || "neutral", children: s.method }),
8196
+ /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("code", { className: "fd-mono", style: { fontSize: 12.5, fontWeight: 600, color: "var(--text)", wordBreak: "break-all" }, children: s.path }),
8197
+ s.isList ? /* @__PURE__ */ (0, import_jsx_runtime77.jsx)(Badge, { tone: "neutral", icon: "rows", children: "Paged list" }) : null,
8198
+ /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("span", { style: { flex: 1 } }),
8199
+ /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)("span", { className: "fd-body-sm fd-muted fd-mono", children: [
7962
8200
  s.latency[0],
7963
8201
  "\u2013",
7964
8202
  s.latency[1],
7965
8203
  "ms"
7966
8204
  ] }),
7967
- /* @__PURE__ */ (0, import_jsx_runtime76.jsx)(Button, { size: "sm", variant: "secondary", icon: "play", loading: tried === "busy", onClick: run, children: "Try it" })
8205
+ /* @__PURE__ */ (0, import_jsx_runtime77.jsx)(Button, { size: "sm", variant: "secondary", icon: "play", loading: tried === "busy", onClick: run, children: "Try it" })
7968
8206
  ] }),
7969
- /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)("div", { className: "fd-stack", style: { gap: 14, padding: "0 18px 16px" }, children: [
7970
- /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)("div", { className: "fd-stack", style: { gap: 6 }, children: [
7971
- /* @__PURE__ */ (0, import_jsx_runtime76.jsx)("span", { className: "fd-body-sm", style: { fontWeight: 700 }, children: s.title }),
7972
- /* @__PURE__ */ (0, import_jsx_runtime76.jsx)("p", { className: "fd-body-sm fd-secondary", style: { margin: 0, textWrap: "pretty" }, children: s.purpose }),
7973
- s.usedBy && s.usedBy.length ? /* @__PURE__ */ (0, import_jsx_runtime76.jsx)("span", { className: "fd-row", style: { gap: 6, flexWrap: "wrap" }, children: s.usedBy.map((u) => /* @__PURE__ */ (0, import_jsx_runtime76.jsx)(Tag, { children: u }, u)) }) : null
8207
+ /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)("div", { className: "fd-stack", style: { gap: 14, padding: "0 18px 16px" }, children: [
8208
+ /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)("div", { className: "fd-stack", style: { gap: 6 }, children: [
8209
+ /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("span", { className: "fd-body-sm", style: { fontWeight: 700 }, children: s.title }),
8210
+ /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("p", { className: "fd-body-sm fd-secondary", style: { margin: 0, textWrap: "pretty" }, children: s.purpose }),
8211
+ s.usedBy && s.usedBy.length ? /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("span", { className: "fd-row", style: { gap: 6, flexWrap: "wrap" }, children: s.usedBy.map((u) => /* @__PURE__ */ (0, import_jsx_runtime77.jsx)(Tag, { children: u }, u)) }) : null
7974
8212
  ] }),
7975
- /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)("div", { style: { display: "grid", gridTemplateColumns: "repeat(auto-fit,minmax(280px,1fr))", gap: 12, alignItems: "start" }, children: [
7976
- s.request ? /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)("div", { className: "fd-stack", style: { gap: 6 }, children: [
7977
- /* @__PURE__ */ (0, import_jsx_runtime76.jsx)("span", { className: "fd-overline fd-muted", children: "Request body" }),
7978
- /* @__PURE__ */ (0, import_jsx_runtime76.jsx)(Json, { obj: s.request })
8213
+ /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)("div", { style: { display: "grid", gridTemplateColumns: "repeat(auto-fit,minmax(280px,1fr))", gap: 12, alignItems: "start" }, children: [
8214
+ s.request ? /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)("div", { className: "fd-stack", style: { gap: 6 }, children: [
8215
+ /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("span", { className: "fd-overline fd-muted", children: "Request body" }),
8216
+ /* @__PURE__ */ (0, import_jsx_runtime77.jsx)(Json, { obj: s.request })
7979
8217
  ] }) : null,
7980
- s.query ? /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)("div", { className: "fd-stack", style: { gap: 6 }, children: [
7981
- /* @__PURE__ */ (0, import_jsx_runtime76.jsx)("span", { className: "fd-overline fd-muted", children: "Query" }),
7982
- /* @__PURE__ */ (0, import_jsx_runtime76.jsx)(Json, { obj: s.query })
8218
+ s.query ? /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)("div", { className: "fd-stack", style: { gap: 6 }, children: [
8219
+ /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("span", { className: "fd-overline fd-muted", children: "Query" }),
8220
+ /* @__PURE__ */ (0, import_jsx_runtime77.jsx)(Json, { obj: s.query })
7983
8221
  ] }) : null,
7984
- /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)("div", { className: "fd-stack", style: { gap: 6 }, children: [
7985
- /* @__PURE__ */ (0, import_jsx_runtime76.jsx)("span", { className: "fd-overline fd-muted", children: "Response 200" }),
7986
- /* @__PURE__ */ (0, import_jsx_runtime76.jsx)(Json, { obj: s.response })
8222
+ /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)("div", { className: "fd-stack", style: { gap: 6 }, children: [
8223
+ /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("span", { className: "fd-overline fd-muted", children: "Response 200" }),
8224
+ /* @__PURE__ */ (0, import_jsx_runtime77.jsx)(Json, { obj: s.response })
7987
8225
  ] })
7988
8226
  ] }),
7989
- s.notes ? /* @__PURE__ */ (0, import_jsx_runtime76.jsx)(Flag, { tone: "info", statement: "Implementation note", cost: s.notes, actions: null }) : null,
7990
- tried && tried !== "busy" ? /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)("div", { className: "fd-stack", style: { gap: 6 }, children: [
7991
- /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)("span", { className: "fd-row", style: { gap: 8 }, children: [
7992
- /* @__PURE__ */ (0, import_jsx_runtime76.jsx)("span", { className: "fd-overline fd-muted", children: "Simulated response" }),
7993
- /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)(Badge, { tone: tried.error ? "danger" : "success", icon: "timer", children: [
8227
+ s.notes ? /* @__PURE__ */ (0, import_jsx_runtime77.jsx)(Flag, { tone: "info", statement: "Implementation note", cost: s.notes, actions: null }) : null,
8228
+ tried && tried !== "busy" ? /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)("div", { className: "fd-stack", style: { gap: 6 }, children: [
8229
+ /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)("span", { className: "fd-row", style: { gap: 8 }, children: [
8230
+ /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("span", { className: "fd-overline fd-muted", children: "Simulated response" }),
8231
+ /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)(Badge, { tone: tried.error ? "danger" : "success", icon: "timer", children: [
7994
8232
  tried.ms,
7995
8233
  "ms"
7996
8234
  ] })
7997
8235
  ] }),
7998
- /* @__PURE__ */ (0, import_jsx_runtime76.jsx)(Json, { obj: tried.error ? { error: tried.error } : tried.data })
8236
+ /* @__PURE__ */ (0, import_jsx_runtime77.jsx)(Json, { obj: tried.error ? { error: tried.error } : tried.data })
7999
8237
  ] }) : null
8000
8238
  ] })
8001
8239
  ] }) });
@@ -8014,58 +8252,58 @@ function ApiSpecBrowser({
8014
8252
  className = "",
8015
8253
  ...rest
8016
8254
  }) {
8017
- const [q, setQ] = React48.useState("");
8018
- const [method, setMethod] = React48.useState(null);
8019
- const [mod, setMod] = React48.useState(null);
8020
- const [listOnly, setListOnly] = React48.useState(false);
8255
+ const [q, setQ] = React49.useState("");
8256
+ const [method, setMethod] = React49.useState(null);
8257
+ const [mod, setMod] = React49.useState(null);
8258
+ const [listOnly, setListOnly] = React49.useState(false);
8021
8259
  const activeModule = modules && modules.find((m) => m.id === mod);
8022
8260
  const hits = spec.filter((s) => (!method || s.method === method) && (!listOnly || s.isList) && (!activeModule || activeModule.endpoints.indexOf(s.id) >= 0) && (!q || (s.path + " " + s.title + " " + s.purpose + " " + (s.usedBy || []).join(" ")).toLowerCase().includes(q.toLowerCase())));
8023
8261
  const effGroups = groups && groups.length ? groups : [["All endpoints", spec.map((s) => s.id)]];
8024
8262
  const methods = [...new Set(spec.map((s) => s.method))];
8025
8263
  const listCount = spec.filter((s) => s.isList).length;
8026
- return /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 20, maxWidth: 1100 }, ...rest, children: [
8027
- /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)("div", { className: "fd-stack", style: { gap: 10 }, children: [
8028
- kicker ? /* @__PURE__ */ (0, import_jsx_runtime76.jsx)("span", { className: "fd-overline fd-muted", children: kicker }) : null,
8029
- /* @__PURE__ */ (0, import_jsx_runtime76.jsx)("h1", { className: "fd-h1", style: { margin: 0 }, children: title }),
8030
- lede ? /* @__PURE__ */ (0, import_jsx_runtime76.jsx)("p", { className: "fd-body fd-secondary fd-prose", style: { margin: 0 }, children: lede }) : null
8264
+ return /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 20, maxWidth: 1100 }, ...rest, children: [
8265
+ /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)("div", { className: "fd-stack", style: { gap: 10 }, children: [
8266
+ kicker ? /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("span", { className: "fd-overline fd-muted", children: kicker }) : null,
8267
+ /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("h1", { className: "fd-h1", style: { margin: 0 }, children: title }),
8268
+ lede ? /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("p", { className: "fd-body fd-secondary fd-prose", style: { margin: 0 }, children: lede }) : null
8031
8269
  ] }),
8032
- modules && modules.length ? /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)("div", { className: "fd-stack", style: { gap: 8 }, children: [
8033
- /* @__PURE__ */ (0, import_jsx_runtime76.jsx)("span", { className: "fd-overline fd-muted", children: "Filter by screen \u2014 every endpoint that screen depends on" }),
8034
- /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)("div", { className: "fd-row", style: { gap: 8, flexWrap: "wrap" }, children: [
8035
- /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)(Tag, { icon: "stack", selected: !mod, onClick: () => setMod(null), children: [
8270
+ modules && modules.length ? /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)("div", { className: "fd-stack", style: { gap: 8 }, children: [
8271
+ /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("span", { className: "fd-overline fd-muted", children: "Filter by screen \u2014 every endpoint that screen depends on" }),
8272
+ /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)("div", { className: "fd-row", style: { gap: 8, flexWrap: "wrap" }, children: [
8273
+ /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)(Tag, { icon: "stack", selected: !mod, onClick: () => setMod(null), children: [
8036
8274
  "All screens ",
8037
- /* @__PURE__ */ (0, import_jsx_runtime76.jsx)("span", { className: "fd-mono", children: spec.length })
8275
+ /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("span", { className: "fd-mono", children: spec.length })
8038
8276
  ] }),
8039
- modules.map((m) => /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)(Tag, { icon: m.icon, selected: mod === m.id, onClick: () => setMod(mod === m.id ? null : m.id), children: [
8277
+ modules.map((m) => /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)(Tag, { icon: m.icon, selected: mod === m.id, onClick: () => setMod(mod === m.id ? null : m.id), children: [
8040
8278
  m.label,
8041
8279
  " ",
8042
- /* @__PURE__ */ (0, import_jsx_runtime76.jsx)("span", { className: "fd-mono", children: m.endpoints.length })
8280
+ /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("span", { className: "fd-mono", children: m.endpoints.length })
8043
8281
  ] }, m.id))
8044
8282
  ] }),
8045
- activeModule ? /* @__PURE__ */ (0, import_jsx_runtime76.jsx)(
8283
+ activeModule ? /* @__PURE__ */ (0, import_jsx_runtime77.jsx)(
8046
8284
  Flag,
8047
8285
  {
8048
8286
  tone: "info",
8049
8287
  statement: activeModule.label + " calls " + activeModule.endpoints.length + " endpoints.",
8050
8288
  cost: "Integration checklist for this screen: " + activeModule.endpoints.join(", ") + ". Wire these and the screen is done.",
8051
- actions: /* @__PURE__ */ (0, import_jsx_runtime76.jsx)(Button, { size: "sm", variant: "ghost", icon: "x", onClick: () => setMod(null), children: "Show all screens" })
8289
+ actions: /* @__PURE__ */ (0, import_jsx_runtime77.jsx)(Button, { size: "sm", variant: "ghost", icon: "x", onClick: () => setMod(null), children: "Show all screens" })
8052
8290
  }
8053
8291
  ) : null
8054
8292
  ] }) : null,
8055
- sourceNote ? /* @__PURE__ */ (0, import_jsx_runtime76.jsx)(Flag, { tone: "info", statement: "Design-first: this page is the spec.", cost: sourceNote, actions: null }) : null,
8056
- /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)("div", { className: "fd-row", style: { gap: 10, flexWrap: "wrap" }, children: [
8057
- /* @__PURE__ */ (0, import_jsx_runtime76.jsx)(Input, { icon: "magnifying-glass", placeholder: "Find an endpoint, screen, or behavior", value: q, onChange: (e) => setQ(e.target.value), style: { width: 300 } }),
8058
- methods.map((m) => /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)(Tag, { selected: method === m, onClick: () => setMethod(method === m ? null : m), children: [
8293
+ sourceNote ? /* @__PURE__ */ (0, import_jsx_runtime77.jsx)(Flag, { tone: "info", statement: "Design-first: this page is the spec.", cost: sourceNote, actions: null }) : null,
8294
+ /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)("div", { className: "fd-row", style: { gap: 10, flexWrap: "wrap" }, children: [
8295
+ /* @__PURE__ */ (0, import_jsx_runtime77.jsx)(Input, { icon: "magnifying-glass", placeholder: "Find an endpoint, screen, or behavior", value: q, onChange: (e) => setQ(e.target.value), style: { width: 300 } }),
8296
+ methods.map((m) => /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)(Tag, { selected: method === m, onClick: () => setMethod(method === m ? null : m), children: [
8059
8297
  m,
8060
8298
  " ",
8061
- /* @__PURE__ */ (0, import_jsx_runtime76.jsx)("span", { className: "fd-mono", children: spec.filter((s) => s.method === m).length })
8299
+ /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("span", { className: "fd-mono", children: spec.filter((s) => s.method === m).length })
8062
8300
  ] }, m)),
8063
- listCount ? /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)(Tag, { icon: "rows", selected: listOnly, onClick: () => setListOnly(!listOnly), children: [
8301
+ listCount ? /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)(Tag, { icon: "rows", selected: listOnly, onClick: () => setListOnly(!listOnly), children: [
8064
8302
  "Paged lists ",
8065
- /* @__PURE__ */ (0, import_jsx_runtime76.jsx)("span", { className: "fd-mono", children: listCount })
8303
+ /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("span", { className: "fd-mono", children: listCount })
8066
8304
  ] }) : null,
8067
- /* @__PURE__ */ (0, import_jsx_runtime76.jsx)("span", { style: { flex: 1 } }),
8068
- /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)("span", { className: "fd-body-sm fd-muted", children: [
8305
+ /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("span", { style: { flex: 1 } }),
8306
+ /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)("span", { className: "fd-body-sm fd-muted", children: [
8069
8307
  hits.length,
8070
8308
  " of ",
8071
8309
  spec.length,
@@ -8073,31 +8311,31 @@ function ApiSpecBrowser({
8073
8311
  listCount ? " \xB7 " + listCount + " paged" : ""
8074
8312
  ] })
8075
8313
  ] }),
8076
- hits.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime76.jsx)(Card, { elevation: "flat", children: /* @__PURE__ */ (0, import_jsx_runtime76.jsx)("p", { className: "fd-body-sm fd-muted", style: { margin: 0 }, children: "No endpoint matches those filters." }) }) : effGroups.map(([g, ids]) => {
8314
+ hits.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime77.jsx)(Card, { elevation: "flat", children: /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("p", { className: "fd-body-sm fd-muted", style: { margin: 0 }, children: "No endpoint matches those filters." }) }) : effGroups.map(([g, ids]) => {
8077
8315
  const items = hits.filter((s) => ids.indexOf(s.id) >= 0);
8078
8316
  if (!items.length) return null;
8079
- return /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)("div", { className: "fd-stack", style: { gap: 12 }, children: [
8080
- /* @__PURE__ */ (0, import_jsx_runtime76.jsx)("span", { className: "fd-label-lg", children: g }),
8081
- items.map((s) => /* @__PURE__ */ (0, import_jsx_runtime76.jsx)(Endpoint, { s, onRequest }, s.id))
8317
+ return /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)("div", { className: "fd-stack", style: { gap: 12 }, children: [
8318
+ /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("span", { className: "fd-label-lg", children: g }),
8319
+ items.map((s) => /* @__PURE__ */ (0, import_jsx_runtime77.jsx)(Endpoint, { s, onRequest }, s.id))
8082
8320
  ] }, g);
8083
8321
  }),
8084
- conventions && conventions.length ? /* @__PURE__ */ (0, import_jsx_runtime76.jsx)(Card, { title: "Cross-cutting conventions", elevation: "flat", children: /* @__PURE__ */ (0, import_jsx_runtime76.jsx)("div", { className: "fd-stack", style: { gap: 10 }, children: conventions.map(([k, v]) => /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)("div", { className: "fd-row", style: { gap: 12, alignItems: "flex-start" }, children: [
8085
- /* @__PURE__ */ (0, import_jsx_runtime76.jsx)("span", { className: "fd-overline fd-muted", style: { width: 110, flex: "none", paddingTop: 2 }, children: k }),
8086
- /* @__PURE__ */ (0, import_jsx_runtime76.jsx)("span", { className: "fd-body-sm fd-secondary", style: { textWrap: "pretty" }, children: v })
8322
+ conventions && conventions.length ? /* @__PURE__ */ (0, import_jsx_runtime77.jsx)(Card, { title: "Cross-cutting conventions", elevation: "flat", children: /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("div", { className: "fd-stack", style: { gap: 10 }, children: conventions.map(([k, v]) => /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)("div", { className: "fd-row", style: { gap: 12, alignItems: "flex-start" }, children: [
8323
+ /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("span", { className: "fd-overline fd-muted", style: { width: 110, flex: "none", paddingTop: 2 }, children: k }),
8324
+ /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("span", { className: "fd-body-sm fd-secondary", style: { textWrap: "pretty" }, children: v })
8087
8325
  ] }, k)) }) }) : null,
8088
- openQuestions && openQuestions.length ? /* @__PURE__ */ (0, import_jsx_runtime76.jsx)(Collapsible, { icon: "list-checks", title: "Open questions before implementation", subtitle: openQuestions.length + " unresolved", children: /* @__PURE__ */ (0, import_jsx_runtime76.jsx)("div", { className: "fd-stack", style: { gap: 8 }, children: openQuestions.map(([id, question, why]) => /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)("div", { className: "fd-row", style: { gap: 10, alignItems: "flex-start", padding: "8px 0", borderTop: "1px solid var(--border)" }, children: [
8089
- /* @__PURE__ */ (0, import_jsx_runtime76.jsx)(Badge, { tone: "danger", children: id }),
8090
- /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)("span", { className: "fd-stack", style: { gap: 2, flex: 1 }, children: [
8091
- /* @__PURE__ */ (0, import_jsx_runtime76.jsx)("span", { className: "fd-body-sm", style: { fontWeight: 600 }, children: question }),
8092
- /* @__PURE__ */ (0, import_jsx_runtime76.jsx)("span", { className: "fd-body-sm fd-muted", children: why })
8326
+ openQuestions && openQuestions.length ? /* @__PURE__ */ (0, import_jsx_runtime77.jsx)(Collapsible, { icon: "list-checks", title: "Open questions before implementation", subtitle: openQuestions.length + " unresolved", children: /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("div", { className: "fd-stack", style: { gap: 8 }, children: openQuestions.map(([id, question, why]) => /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)("div", { className: "fd-row", style: { gap: 10, alignItems: "flex-start", padding: "8px 0", borderTop: "1px solid var(--border)" }, children: [
8327
+ /* @__PURE__ */ (0, import_jsx_runtime77.jsx)(Badge, { tone: "danger", children: id }),
8328
+ /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)("span", { className: "fd-stack", style: { gap: 2, flex: 1 }, children: [
8329
+ /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("span", { className: "fd-body-sm", style: { fontWeight: 600 }, children: question }),
8330
+ /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("span", { className: "fd-body-sm fd-muted", children: why })
8093
8331
  ] })
8094
8332
  ] }, id)) }) }) : null
8095
8333
  ] });
8096
8334
  }
8097
8335
 
8098
8336
  // src/components/platform/ProfilePage.tsx
8099
- var React49 = __toESM(require("react"), 1);
8100
- var import_jsx_runtime77 = require("react/jsx-runtime");
8337
+ var React50 = __toESM(require("react"), 1);
8338
+ var import_jsx_runtime78 = require("react/jsx-runtime");
8101
8339
  function fieldInitialValue(field, user) {
8102
8340
  if (field.value) return field.value(user);
8103
8341
  const raw = user[field.key];
@@ -8132,21 +8370,21 @@ function ProfilePage({
8132
8370
  }) {
8133
8371
  const { user: sessionUser, roles, permissions, saveProfile: saveProfile2 } = useSessionContext();
8134
8372
  const user = userProp || sessionUser;
8135
- const initialFieldValues = React49.useMemo(() => {
8373
+ const initialFieldValues = React50.useMemo(() => {
8136
8374
  const values2 = {};
8137
8375
  for (const field of fields) values2[field.key] = fieldInitialValue(field, user);
8138
8376
  return values2;
8139
8377
  }, [user.id, fields]);
8140
- const initialNotify = React49.useMemo(() => {
8378
+ const initialNotify = React50.useMemo(() => {
8141
8379
  const values2 = {};
8142
8380
  for (const n of notifications) values2[n.key] = !!user.notify?.[n.key];
8143
8381
  return values2;
8144
8382
  }, [user.id, notifications]);
8145
- const [values, setValues] = React49.useState(initialFieldValues);
8146
- const [notify, setNotify] = React49.useState(initialNotify);
8147
- const [saving, setSaving] = React49.useState(false);
8148
- const [saved, setSaved] = React49.useState(false);
8149
- const [prevUserId, setPrevUserId] = React49.useState(user.id);
8383
+ const [values, setValues] = React50.useState(initialFieldValues);
8384
+ const [notify, setNotify] = React50.useState(initialNotify);
8385
+ const [saving, setSaving] = React50.useState(false);
8386
+ const [saved, setSaved] = React50.useState(false);
8387
+ const [prevUserId, setPrevUserId] = React50.useState(user.id);
8150
8388
  if (user.id !== prevUserId) {
8151
8389
  setPrevUserId(user.id);
8152
8390
  setValues(initialFieldValues);
@@ -8183,37 +8421,37 @@ function ProfilePage({
8183
8421
  };
8184
8422
  const displayName = fields.some((f) => f.key === "name") ? values.name || user.name : user.name;
8185
8423
  const fieldGroups = groupFields(fields);
8186
- return /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 20, maxWidth: 860 }, children: [
8187
- /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)("div", { className: "fd-stack", style: { gap: 10 }, children: [
8188
- /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("span", { className: "fd-overline fd-muted", children: "Account" }),
8189
- /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("h1", { className: "fd-h1", style: { margin: 0 }, children: "Your profile" }),
8190
- /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("p", { className: "fd-body fd-secondary fd-prose", style: { margin: 0 }, children: "How you appear to colleagues and clients across every flytedesk app, and what we send you." })
8424
+ return /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 20, maxWidth: 860 }, children: [
8425
+ /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)("div", { className: "fd-stack", style: { gap: 10 }, children: [
8426
+ /* @__PURE__ */ (0, import_jsx_runtime78.jsx)("span", { className: "fd-overline fd-muted", children: "Account" }),
8427
+ /* @__PURE__ */ (0, import_jsx_runtime78.jsx)("h1", { className: "fd-h1", style: { margin: 0 }, children: "Your profile" }),
8428
+ /* @__PURE__ */ (0, import_jsx_runtime78.jsx)("p", { className: "fd-body fd-secondary fd-prose", style: { margin: 0 }, children: "How you appear to colleagues and clients across every flytedesk app, and what we send you." })
8191
8429
  ] }),
8192
- /* @__PURE__ */ (0, import_jsx_runtime77.jsx)(Card, { elevation: "flat", children: /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)("div", { className: "fd-row", style: { gap: 16, flexWrap: "wrap", alignItems: "flex-start" }, children: [
8193
- /* @__PURE__ */ (0, import_jsx_runtime77.jsx)(Avatar, { name: displayName, size: "lg" }),
8194
- /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)("div", { className: "fd-stack", style: { gap: 4, flex: 1, minWidth: 200 }, children: [
8195
- /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("span", { className: "fd-h3", style: { margin: 0 }, children: displayName }),
8196
- /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)("span", { className: "fd-row", style: { gap: 6, flexWrap: "wrap", paddingTop: 4 }, children: [
8197
- roles.map((r) => /* @__PURE__ */ (0, import_jsx_runtime77.jsx)(Badge, { tone: r.id === "owner" ? "success" : "neutral", children: r.name }, r.id)),
8198
- user.sso ? /* @__PURE__ */ (0, import_jsx_runtime77.jsx)(Badge, { tone: "info", icon: "shield-check", children: "SSO" }) : null
8430
+ /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(Card, { elevation: "flat", children: /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)("div", { className: "fd-row", style: { gap: 16, flexWrap: "wrap", alignItems: "flex-start" }, children: [
8431
+ /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(Avatar, { name: displayName, size: "lg" }),
8432
+ /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)("div", { className: "fd-stack", style: { gap: 4, flex: 1, minWidth: 200 }, children: [
8433
+ /* @__PURE__ */ (0, import_jsx_runtime78.jsx)("span", { className: "fd-h3", style: { margin: 0 }, children: displayName }),
8434
+ /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)("span", { className: "fd-row", style: { gap: 6, flexWrap: "wrap", paddingTop: 4 }, children: [
8435
+ roles.map((r) => /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(Badge, { tone: r.id === "owner" ? "success" : "neutral", children: r.name }, r.id)),
8436
+ user.sso ? /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(Badge, { tone: "info", icon: "shield-check", children: "SSO" }) : null
8199
8437
  ] })
8200
8438
  ] }),
8201
- onChangePhoto ? /* @__PURE__ */ (0, import_jsx_runtime77.jsx)(Button, { variant: "secondary", size: "sm", icon: "image", onClick: onChangePhoto, children: "Change photo" }) : null
8439
+ onChangePhoto ? /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(Button, { variant: "secondary", size: "sm", icon: "image", onClick: onChangePhoto, children: "Change photo" }) : null
8202
8440
  ] }) }),
8203
- fieldGroups.map(({ group, description, fields: groupFieldDefs }) => /* @__PURE__ */ (0, import_jsx_runtime77.jsx)(
8441
+ fieldGroups.map(({ group, description, fields: groupFieldDefs }) => /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(
8204
8442
  Card,
8205
8443
  {
8206
- title: description ? /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)("span", { className: "fd-stack", style: { gap: 2 }, children: [
8207
- /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("span", { children: group }),
8208
- /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("span", { className: "fd-body-sm fd-muted", style: { fontWeight: 400 }, children: description })
8444
+ title: description ? /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)("span", { className: "fd-stack", style: { gap: 2 }, children: [
8445
+ /* @__PURE__ */ (0, import_jsx_runtime78.jsx)("span", { children: group }),
8446
+ /* @__PURE__ */ (0, import_jsx_runtime78.jsx)("span", { className: "fd-body-sm fd-muted", style: { fontWeight: 400 }, children: description })
8209
8447
  ] }) : group,
8210
8448
  elevation: "flat",
8211
- children: /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)("div", { className: "fd-stack", style: { gap: 14 }, children: [
8212
- /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("div", { style: { display: "grid", gridTemplateColumns: "repeat(auto-fit,minmax(220px,1fr))", gap: 14 }, children: groupFieldDefs.filter((f) => f.type !== "textarea").map((field) => {
8449
+ children: /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)("div", { className: "fd-stack", style: { gap: 14 }, children: [
8450
+ /* @__PURE__ */ (0, import_jsx_runtime78.jsx)("div", { style: { display: "grid", gridTemplateColumns: "repeat(auto-fit,minmax(220px,1fr))", gap: 14 }, children: groupFieldDefs.filter((f) => f.type !== "textarea").map((field) => {
8213
8451
  const help = typeof field.help === "function" ? field.help(user) : field.help;
8214
8452
  const readOnly = field.readOnly || field.type === "readonly";
8215
8453
  if (field.type === "select") {
8216
- return /* @__PURE__ */ (0, import_jsx_runtime77.jsx)(
8454
+ return /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(
8217
8455
  Select,
8218
8456
  {
8219
8457
  label: field.label,
@@ -8227,7 +8465,7 @@ function ProfilePage({
8227
8465
  field.key
8228
8466
  );
8229
8467
  }
8230
- return /* @__PURE__ */ (0, import_jsx_runtime77.jsx)(
8468
+ return /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(
8231
8469
  Input,
8232
8470
  {
8233
8471
  label: field.label,
@@ -8243,7 +8481,7 @@ function ProfilePage({
8243
8481
  }) }),
8244
8482
  groupFieldDefs.filter((f) => f.type === "textarea").map((field) => {
8245
8483
  const help = typeof field.help === "function" ? field.help(user) : field.help;
8246
- return /* @__PURE__ */ (0, import_jsx_runtime77.jsx)(
8484
+ return /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(
8247
8485
  Textarea,
8248
8486
  {
8249
8487
  label: field.label,
@@ -8263,16 +8501,16 @@ function ProfilePage({
8263
8501
  group
8264
8502
  )),
8265
8503
  extra,
8266
- notifications.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime77.jsx)(Card, { title: "Notifications", elevation: "flat", children: /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("div", { className: "fd-stack", style: { gap: 14 }, children: notifications.map((n) => /* @__PURE__ */ (0, import_jsx_runtime77.jsx)(Switch, { checked: !!notify[n.key], onChange: () => toggleNotify(n.key), label: n.label, description: n.description }, n.key)) }) }) : null,
8267
- /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)(
8504
+ notifications.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(Card, { title: "Notifications", elevation: "flat", children: /* @__PURE__ */ (0, import_jsx_runtime78.jsx)("div", { className: "fd-stack", style: { gap: 14 }, children: notifications.map((n) => /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(Switch, { checked: !!notify[n.key], onChange: () => toggleNotify(n.key), label: n.label, description: n.description }, n.key)) }) }) : null,
8505
+ /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)(
8268
8506
  Card,
8269
8507
  {
8270
- title: /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)("span", { className: "fd-stack", style: { gap: 2 }, children: [
8271
- /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("span", { children: "Access" }),
8272
- /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("span", { className: "fd-body-sm fd-muted", style: { fontWeight: 400 }, children: "What your roles grant you" })
8508
+ title: /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)("span", { className: "fd-stack", style: { gap: 2 }, children: [
8509
+ /* @__PURE__ */ (0, import_jsx_runtime78.jsx)("span", { children: "Access" }),
8510
+ /* @__PURE__ */ (0, import_jsx_runtime78.jsx)("span", { className: "fd-body-sm fd-muted", style: { fontWeight: 400 }, children: "What your roles grant you" })
8273
8511
  ] }),
8274
8512
  elevation: "flat",
8275
- action: /* @__PURE__ */ (0, import_jsx_runtime77.jsx)(
8513
+ action: /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(
8276
8514
  Button,
8277
8515
  {
8278
8516
  size: "sm",
@@ -8283,39 +8521,39 @@ function ProfilePage({
8283
8521
  }
8284
8522
  ),
8285
8523
  children: [
8286
- /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)("div", { className: "fd-stack", style: { gap: 0 }, children: [
8287
- /* @__PURE__ */ (0, import_jsx_runtime77.jsx)(CardRow, { label: "Roles", children: roles.map((r) => r.name).join(", ") || "None" }),
8288
- /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)(CardRow, { label: "Permissions", children: [
8524
+ /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)("div", { className: "fd-stack", style: { gap: 0 }, children: [
8525
+ /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(CardRow, { label: "Roles", children: roles.map((r) => r.name).join(", ") || "None" }),
8526
+ /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)(CardRow, { label: "Permissions", children: [
8289
8527
  permissions.length,
8290
8528
  " granted"
8291
8529
  ] }),
8292
- /* @__PURE__ */ (0, import_jsx_runtime77.jsx)(CardRow, { label: "Member since", children: user.joined || "\u2014" })
8530
+ /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(CardRow, { label: "Member since", children: user.joined || "\u2014" })
8293
8531
  ] }),
8294
- /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("p", { className: "fd-body-sm fd-muted", style: { margin: "12px 0 0" }, children: "You cannot change your own roles \u2014 that is the point of them. An administrator manages roles from Admin \u2192 Users." })
8532
+ /* @__PURE__ */ (0, import_jsx_runtime78.jsx)("p", { className: "fd-body-sm fd-muted", style: { margin: "12px 0 0" }, children: "You cannot change your own roles \u2014 that is the point of them. An administrator manages roles from Admin \u2192 Users." })
8295
8533
  ]
8296
8534
  }
8297
8535
  ),
8298
- sessions ? /* @__PURE__ */ (0, import_jsx_runtime77.jsx)(
8536
+ sessions ? /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(
8299
8537
  Card,
8300
8538
  {
8301
8539
  title: "Signed-in devices",
8302
8540
  elevation: "flat",
8303
- action: /* @__PURE__ */ (0, import_jsx_runtime77.jsx)(Button, { size: "sm", variant: "ghost", icon: "sign-out", onClick: onSignOutEverywhere, children: "Sign out everywhere" }),
8304
- children: /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("div", { className: "fd-stack", style: { gap: 0 }, children: sessions.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("p", { className: "fd-body-sm fd-muted", style: { margin: 0 }, children: "No other signed-in devices." }) : sessions.map((s) => /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)("div", { className: "fd-row", style: { gap: 12, padding: "10px 0", borderTop: "1px solid var(--border)", flexWrap: "wrap" }, children: [
8305
- /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("i", { className: "ph ph-device-mobile", style: { fontSize: 16, color: "var(--text-muted)" }, "aria-hidden": "true" }),
8306
- /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)("span", { className: "fd-stack", style: { gap: 1, flex: 1, minWidth: 160 }, children: [
8307
- /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("span", { className: "fd-body-sm", style: { fontWeight: 600 }, children: s.device }),
8308
- /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)("span", { className: "fd-body-sm fd-muted", children: [
8541
+ action: /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(Button, { size: "sm", variant: "ghost", icon: "sign-out", onClick: onSignOutEverywhere, children: "Sign out everywhere" }),
8542
+ children: /* @__PURE__ */ (0, import_jsx_runtime78.jsx)("div", { className: "fd-stack", style: { gap: 0 }, children: sessions.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime78.jsx)("p", { className: "fd-body-sm fd-muted", style: { margin: 0 }, children: "No other signed-in devices." }) : sessions.map((s) => /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)("div", { className: "fd-row", style: { gap: 12, padding: "10px 0", borderTop: "1px solid var(--border)", flexWrap: "wrap" }, children: [
8543
+ /* @__PURE__ */ (0, import_jsx_runtime78.jsx)("i", { className: "ph ph-device-mobile", style: { fontSize: 16, color: "var(--text-muted)" }, "aria-hidden": "true" }),
8544
+ /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)("span", { className: "fd-stack", style: { gap: 1, flex: 1, minWidth: 160 }, children: [
8545
+ /* @__PURE__ */ (0, import_jsx_runtime78.jsx)("span", { className: "fd-body-sm", style: { fontWeight: 600 }, children: s.device }),
8546
+ /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)("span", { className: "fd-body-sm fd-muted", children: [
8309
8547
  s.where,
8310
8548
  " \xB7 ",
8311
8549
  s.when
8312
8550
  ] })
8313
8551
  ] }),
8314
- s.current ? /* @__PURE__ */ (0, import_jsx_runtime77.jsx)(Badge, { tone: "success", dot: true, children: "This device" }) : /* @__PURE__ */ (0, import_jsx_runtime77.jsx)(Button, { size: "sm", variant: "ghost", children: "Revoke" })
8552
+ s.current ? /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(Badge, { tone: "success", dot: true, children: "This device" }) : /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(Button, { size: "sm", variant: "ghost", children: "Revoke" })
8315
8553
  ] }, s.id)) })
8316
8554
  }
8317
8555
  ) : null,
8318
- /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)("div", { className: "fd-row", style: {
8556
+ /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)("div", { className: "fd-row", style: {
8319
8557
  gap: 10,
8320
8558
  flexWrap: "wrap",
8321
8559
  position: "sticky",
@@ -8326,19 +8564,19 @@ function ProfilePage({
8326
8564
  border: "1px solid var(--border)",
8327
8565
  boxShadow: "0 -4px 16px rgba(11,13,17,.06)"
8328
8566
  }, children: [
8329
- /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("span", { className: "fd-body-sm", style: { fontWeight: 600, flex: 1 }, children: saved ? "Saved." : dirty ? "Unsaved changes" : "No pending changes" }),
8330
- /* @__PURE__ */ (0, import_jsx_runtime77.jsx)(Button, { size: "sm", variant: "ghost", disabled: !dirty || saving, onClick: discard, children: "Discard" }),
8331
- /* @__PURE__ */ (0, import_jsx_runtime77.jsx)(Button, { size: "sm", icon: "check", disabled: !dirty || !canSave, loading: saving, onClick: save, children: "Save changes" })
8567
+ /* @__PURE__ */ (0, import_jsx_runtime78.jsx)("span", { className: "fd-body-sm", style: { fontWeight: 600, flex: 1 }, children: saved ? "Saved." : dirty ? "Unsaved changes" : "No pending changes" }),
8568
+ /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(Button, { size: "sm", variant: "ghost", disabled: !dirty || saving, onClick: discard, children: "Discard" }),
8569
+ /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(Button, { size: "sm", icon: "check", disabled: !dirty || !canSave, loading: saving, onClick: save, children: "Save changes" })
8332
8570
  ] })
8333
8571
  ] });
8334
8572
  }
8335
8573
 
8336
8574
  // src/components/platform/SignInPage.tsx
8337
- var React50 = __toESM(require("react"), 1);
8338
- var import_jsx_runtime78 = require("react/jsx-runtime");
8575
+ var React51 = __toESM(require("react"), 1);
8576
+ var import_jsx_runtime79 = require("react/jsx-runtime");
8339
8577
  function SignInPage({ productName, onSignIn, continueAs, error }) {
8340
- const [signingIn, setSigningIn] = React50.useState(false);
8341
- const [resuming, setResuming] = React50.useState(false);
8578
+ const [signingIn, setSigningIn] = React51.useState(false);
8579
+ const [resuming, setResuming] = React51.useState(false);
8342
8580
  function handleSignIn() {
8343
8581
  setSigningIn(true);
8344
8582
  onSignIn();
@@ -8347,7 +8585,7 @@ function SignInPage({ productName, onSignIn, continueAs, error }) {
8347
8585
  setResuming(true);
8348
8586
  continueAs.onContinue().finally(() => setResuming(false));
8349
8587
  }
8350
- return /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)(
8588
+ return /* @__PURE__ */ (0, import_jsx_runtime79.jsxs)(
8351
8589
  "div",
8352
8590
  {
8353
8591
  style: {
@@ -8361,7 +8599,7 @@ function SignInPage({ productName, onSignIn, continueAs, error }) {
8361
8599
  background: "radial-gradient(circle at 15% 15%, var(--blue-700) 0%, transparent 45%), radial-gradient(circle at 85% 85%, var(--blue-600) 0%, transparent 40%), linear-gradient(160deg, var(--navy) 0%, var(--blue-950) 55%, var(--blue-900) 100%)"
8362
8600
  },
8363
8601
  children: [
8364
- /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(
8602
+ /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(
8365
8603
  "div",
8366
8604
  {
8367
8605
  "aria-hidden": true,
@@ -8374,7 +8612,7 @@ function SignInPage({ productName, onSignIn, continueAs, error }) {
8374
8612
  }
8375
8613
  }
8376
8614
  ),
8377
- /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)(
8615
+ /* @__PURE__ */ (0, import_jsx_runtime79.jsxs)(
8378
8616
  "div",
8379
8617
  {
8380
8618
  style: {
@@ -8386,8 +8624,8 @@ function SignInPage({ productName, onSignIn, continueAs, error }) {
8386
8624
  alignItems: "center"
8387
8625
  },
8388
8626
  children: [
8389
- /* @__PURE__ */ (0, import_jsx_runtime78.jsx)("div", { style: { marginBottom: "var(--s-32)" }, "data-theme": "dark", children: /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(FlytedeskMark, { size: "lg" }) }),
8390
- /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)(
8627
+ /* @__PURE__ */ (0, import_jsx_runtime79.jsx)("div", { style: { marginBottom: "var(--s-32)" }, "data-theme": "dark", children: /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(FlytedeskMark, { size: "lg" }) }),
8628
+ /* @__PURE__ */ (0, import_jsx_runtime79.jsxs)(
8391
8629
  "div",
8392
8630
  {
8393
8631
  style: {
@@ -8397,7 +8635,7 @@ function SignInPage({ productName, onSignIn, continueAs, error }) {
8397
8635
  boxShadow: "0 24px 64px -12px rgba(2, 8, 20, 0.55), 0 2px 8px rgba(2, 8, 20, 0.3)"
8398
8636
  },
8399
8637
  children: [
8400
- /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(
8638
+ /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(
8401
8639
  "div",
8402
8640
  {
8403
8641
  style: {
@@ -8406,7 +8644,7 @@ function SignInPage({ productName, onSignIn, continueAs, error }) {
8406
8644
  }
8407
8645
  }
8408
8646
  ),
8409
- /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(Card, { children: /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)(
8647
+ /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(Card, { children: /* @__PURE__ */ (0, import_jsx_runtime79.jsxs)(
8410
8648
  "div",
8411
8649
  {
8412
8650
  style: {
@@ -8418,13 +8656,13 @@ function SignInPage({ productName, onSignIn, continueAs, error }) {
8418
8656
  padding: "var(--s-8) 0"
8419
8657
  },
8420
8658
  children: [
8421
- /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)("div", { children: [
8422
- /* @__PURE__ */ (0, import_jsx_runtime78.jsx)("h1", { className: "fd-h3", style: { color: "var(--navy)" }, children: productName }),
8423
- /* @__PURE__ */ (0, import_jsx_runtime78.jsx)("p", { className: "fd-body-sm fd-muted", style: { marginTop: "var(--s-4)" }, children: continueAs ? "Your session timed out, but you're likely still signed in" : "Sign in with your flytedesk workspace account" })
8659
+ /* @__PURE__ */ (0, import_jsx_runtime79.jsxs)("div", { children: [
8660
+ /* @__PURE__ */ (0, import_jsx_runtime79.jsx)("h1", { className: "fd-h3", style: { color: "var(--navy)" }, children: productName }),
8661
+ /* @__PURE__ */ (0, import_jsx_runtime79.jsx)("p", { className: "fd-body-sm fd-muted", style: { marginTop: "var(--s-4)" }, children: continueAs ? "Your session timed out, but you're likely still signed in" : "Sign in with your flytedesk workspace account" })
8424
8662
  ] }),
8425
- error ? /* @__PURE__ */ (0, import_jsx_runtime78.jsx)("div", { role: "alert", style: { width: "100%" }, children: /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(Banner, { tone: "danger", title: error }) }) : null,
8426
- continueAs ? /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)(import_jsx_runtime78.Fragment, { children: [
8427
- /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(
8663
+ error ? /* @__PURE__ */ (0, import_jsx_runtime79.jsx)("div", { role: "alert", style: { width: "100%" }, children: /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(Banner, { tone: "danger", title: error }) }) : null,
8664
+ continueAs ? /* @__PURE__ */ (0, import_jsx_runtime79.jsxs)(import_jsx_runtime79.Fragment, { children: [
8665
+ /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(
8428
8666
  Button,
8429
8667
  {
8430
8668
  variant: "primary",
@@ -8435,7 +8673,7 @@ function SignInPage({ productName, onSignIn, continueAs, error }) {
8435
8673
  children: resuming ? "Resuming\u2026" : `Continue as ${continueAs.name}`
8436
8674
  }
8437
8675
  ),
8438
- /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(
8676
+ /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(
8439
8677
  "button",
8440
8678
  {
8441
8679
  type: "button",
@@ -8452,7 +8690,7 @@ function SignInPage({ productName, onSignIn, continueAs, error }) {
8452
8690
  children: "Not you? Sign in with flytedesk ID"
8453
8691
  }
8454
8692
  )
8455
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(
8693
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(
8456
8694
  Button,
8457
8695
  {
8458
8696
  variant: "primary",
@@ -8460,7 +8698,7 @@ function SignInPage({ productName, onSignIn, continueAs, error }) {
8460
8698
  loading: signingIn,
8461
8699
  disabled: signingIn,
8462
8700
  onClick: handleSignIn,
8463
- children: /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)(
8701
+ children: /* @__PURE__ */ (0, import_jsx_runtime79.jsxs)(
8464
8702
  "span",
8465
8703
  {
8466
8704
  style: {
@@ -8472,14 +8710,14 @@ function SignInPage({ productName, onSignIn, continueAs, error }) {
8472
8710
  flexWrap: "nowrap"
8473
8711
  },
8474
8712
  children: [
8475
- /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(GoogleGlyph, {}),
8476
- /* @__PURE__ */ (0, import_jsx_runtime78.jsx)("span", { children: signingIn ? "Signing in\u2026" : "Sign in with flytedesk ID" })
8713
+ /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(GoogleGlyph, {}),
8714
+ /* @__PURE__ */ (0, import_jsx_runtime79.jsx)("span", { children: signingIn ? "Signing in\u2026" : "Sign in with flytedesk ID" })
8477
8715
  ]
8478
8716
  }
8479
8717
  )
8480
8718
  }
8481
8719
  ),
8482
- /* @__PURE__ */ (0, import_jsx_runtime78.jsx)("p", { className: "fd-body-sm fd-muted", style: { fontSize: "12px" }, children: "One account, every flytedesk app." })
8720
+ /* @__PURE__ */ (0, import_jsx_runtime79.jsx)("p", { className: "fd-body-sm fd-muted", style: { fontSize: "12px" }, children: "One account, every flytedesk app." })
8483
8721
  ]
8484
8722
  }
8485
8723
  ) })
@@ -8494,29 +8732,29 @@ function SignInPage({ productName, onSignIn, continueAs, error }) {
8494
8732
  );
8495
8733
  }
8496
8734
  function GoogleGlyph() {
8497
- return /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)("svg", { width: "18", height: "18", viewBox: "0 0 18 18", "aria-hidden": true, children: [
8498
- /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(
8735
+ return /* @__PURE__ */ (0, import_jsx_runtime79.jsxs)("svg", { width: "18", height: "18", viewBox: "0 0 18 18", "aria-hidden": true, children: [
8736
+ /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(
8499
8737
  "path",
8500
8738
  {
8501
8739
  fill: "#4285F4",
8502
8740
  d: "M17.64 9.2c0-.64-.06-1.25-.16-1.84H9v3.48h4.84a4.14 4.14 0 0 1-1.8 2.72v2.26h2.92c1.7-1.57 2.68-3.87 2.68-6.62Z"
8503
8741
  }
8504
8742
  ),
8505
- /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(
8743
+ /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(
8506
8744
  "path",
8507
8745
  {
8508
8746
  fill: "#34A853",
8509
8747
  d: "M9 18c2.43 0 4.47-.8 5.96-2.18l-2.92-2.26c-.81.54-1.84.87-3.04.87-2.34 0-4.32-1.58-5.03-3.7H.96v2.33A9 9 0 0 0 9 18Z"
8510
8748
  }
8511
8749
  ),
8512
- /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(
8750
+ /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(
8513
8751
  "path",
8514
8752
  {
8515
8753
  fill: "#FBBC05",
8516
8754
  d: "M3.97 10.73A5.4 5.4 0 0 1 3.68 9c0-.6.1-1.19.29-1.73V4.94H.96A9 9 0 0 0 0 9c0 1.45.35 2.83.96 4.06l3.01-2.33Z"
8517
8755
  }
8518
8756
  ),
8519
- /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(
8757
+ /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(
8520
8758
  "path",
8521
8759
  {
8522
8760
  fill: "#EA4335",
@@ -8527,10 +8765,10 @@ function GoogleGlyph() {
8527
8765
  }
8528
8766
 
8529
8767
  // src/components/platform/RoadmapTimeline.tsx
8530
- var React53 = __toESM(require("react"), 1);
8768
+ var React54 = __toESM(require("react"), 1);
8531
8769
 
8532
8770
  // src/kits/session.ts
8533
- var React51 = __toESM(require("react"), 1);
8771
+ var React52 = __toESM(require("react"), 1);
8534
8772
  var PERMISSION_CATALOG = [
8535
8773
  { group: "Plans", items: [
8536
8774
  { key: "plan.view", label: "View plans", detail: "Read any plan in the workspace." },
@@ -10097,8 +10335,8 @@ function roadmap(overrides) {
10097
10335
  };
10098
10336
  }
10099
10337
  function useSession() {
10100
- const [s, setS] = React51.useState(getSession);
10101
- React51.useEffect(() => subscribe(setS), []);
10338
+ const [s, setS] = React52.useState(getSession);
10339
+ React52.useEffect(() => subscribe(setS), []);
10102
10340
  return s;
10103
10341
  }
10104
10342
  var SessionKit = {
@@ -10131,7 +10369,7 @@ var SessionKit = {
10131
10369
  };
10132
10370
  function DemoSessionProvider({ children }) {
10133
10371
  const session = useSession();
10134
- const value = React51.useMemo(
10372
+ const value = React52.useMemo(
10135
10373
  () => ({
10136
10374
  user: session.user,
10137
10375
  roles: session.roles,
@@ -10147,11 +10385,11 @@ function DemoSessionProvider({ children }) {
10147
10385
  }),
10148
10386
  [session]
10149
10387
  );
10150
- return React51.createElement(SessionProvider, { value }, children);
10388
+ return React52.createElement(SessionProvider, { value }, children);
10151
10389
  }
10152
10390
 
10153
10391
  // src/kits/runtime.ts
10154
- var React52 = __toESM(require("react"), 1);
10392
+ var React53 = __toESM(require("react"), 1);
10155
10393
  var WIRED_ENDPOINTS = [
10156
10394
  // Nothing yet. Every id below would come from a real service:
10157
10395
  // "plan.get", "placements.list", …
@@ -10322,8 +10560,8 @@ var RuntimeKit = {
10322
10560
  };
10323
10561
  RuntimeKit.declare(FEATURE_NEEDS);
10324
10562
  function useRuntimeMode() {
10325
- const [m, setM] = React52.useState(RuntimeKit.getMode());
10326
- React52.useEffect(() => RuntimeKit.subscribe(setM), []);
10563
+ const [m, setM] = React53.useState(RuntimeKit.getMode());
10564
+ React53.useEffect(() => RuntimeKit.subscribe(setM), []);
10327
10565
  return m;
10328
10566
  }
10329
10567
  function useFeatureStatus(key) {
@@ -10342,7 +10580,7 @@ var UseRuntimeMode = useRuntimeMode;
10342
10580
  var UseFeatureStatus = useFeatureStatus;
10343
10581
 
10344
10582
  // src/components/platform/RoadmapTimeline.tsx
10345
- var import_jsx_runtime79 = require("react/jsx-runtime");
10583
+ var import_jsx_runtime80 = require("react/jsx-runtime");
10346
10584
  var STATUS = {
10347
10585
  shipped: { tone: "success", icon: "check-circle", label: "Wired" },
10348
10586
  next: { tone: "warning", icon: "traffic-cone", label: "Not wired" },
@@ -10357,45 +10595,45 @@ function RoadmapCard({ item, byKey, onOpenFlag }) {
10357
10595
  const s = STATUS[item.status] || STATUS.planned;
10358
10596
  const deps = (item.dependsOn || []).map((k) => byKey[k]).filter(Boolean);
10359
10597
  const blocking = deps.filter((d) => !d.implemented);
10360
- return /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(Card, { elevation: "flat", children: /* @__PURE__ */ (0, import_jsx_runtime79.jsxs)("div", { className: "fd-stack", style: { gap: 10 }, children: [
10361
- /* @__PURE__ */ (0, import_jsx_runtime79.jsxs)("div", { className: "fd-row", style: { gap: 8, flexWrap: "wrap" }, children: [
10362
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)("span", { className: "fd-body", style: { fontWeight: 700, flex: 1, minWidth: 140 }, children: item.label }),
10363
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(Badge, { tone: "neutral", icon: PROJECT_ICON[item.project] || "squares-four", children: item.project }),
10364
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(Badge, { tone: s.tone, icon: s.icon, children: s.label })
10598
+ return /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(Card, { elevation: "flat", children: /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("div", { className: "fd-stack", style: { gap: 10 }, children: [
10599
+ /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("div", { className: "fd-row", style: { gap: 8, flexWrap: "wrap" }, children: [
10600
+ /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("span", { className: "fd-body", style: { fontWeight: 700, flex: 1, minWidth: 140 }, children: item.label }),
10601
+ /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(Badge, { tone: "neutral", icon: PROJECT_ICON[item.project] || "squares-four", children: item.project }),
10602
+ /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(Badge, { tone: s.tone, icon: s.icon, children: s.label })
10365
10603
  ] }),
10366
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)("p", { className: "fd-body-sm fd-secondary", style: { margin: 0, textWrap: "pretty" }, children: item.description }),
10367
- item.backend ? /* @__PURE__ */ (0, import_jsx_runtime79.jsxs)("div", { className: "fd-row", style: { gap: 10, alignItems: "flex-start" }, children: [
10368
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)("span", { className: "fd-overline fd-muted", style: { width: 62, flex: "none", paddingTop: 2 }, children: "Backend" }),
10369
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)("span", { className: "fd-body-sm", style: { flex: 1, textWrap: "pretty" }, children: item.backend })
10604
+ /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("p", { className: "fd-body-sm fd-secondary", style: { margin: 0, textWrap: "pretty" }, children: item.description }),
10605
+ item.backend ? /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("div", { className: "fd-row", style: { gap: 10, alignItems: "flex-start" }, children: [
10606
+ /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("span", { className: "fd-overline fd-muted", style: { width: 62, flex: "none", paddingTop: 2 }, children: "Backend" }),
10607
+ /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("span", { className: "fd-body-sm", style: { flex: 1, textWrap: "pretty" }, children: item.backend })
10370
10608
  ] }) : null,
10371
- /* @__PURE__ */ (0, import_jsx_runtime79.jsxs)("div", { className: "fd-row", style: { gap: 12, flexWrap: "wrap" }, children: [
10372
- item.effort ? /* @__PURE__ */ (0, import_jsx_runtime79.jsxs)("span", { className: "fd-body-sm fd-muted", children: [
10373
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)("i", { className: "ph ph-hourglass-medium" }),
10609
+ /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("div", { className: "fd-row", style: { gap: 12, flexWrap: "wrap" }, children: [
10610
+ item.effort ? /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("span", { className: "fd-body-sm fd-muted", children: [
10611
+ /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("i", { className: "ph ph-hourglass-medium" }),
10374
10612
  " ",
10375
10613
  item.effort
10376
10614
  ] }) : null,
10377
- /* @__PURE__ */ (0, import_jsx_runtime79.jsxs)("span", { className: "fd-body-sm fd-muted", children: [
10378
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)("i", { className: "ph ph-user" }),
10615
+ /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("span", { className: "fd-body-sm fd-muted", children: [
10616
+ /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("i", { className: "ph ph-user" }),
10379
10617
  " ",
10380
10618
  item.owner
10381
10619
  ] }),
10382
- item.screen ? /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(Badge, { tone: "neutral", icon: "browser", children: "screen" }) : null,
10383
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)("span", { style: { flex: 1 } }),
10384
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(
10620
+ item.screen ? /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(Badge, { tone: "neutral", icon: "browser", children: "screen" }) : null,
10621
+ /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("span", { style: { flex: 1 } }),
10622
+ /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(
10385
10623
  "button",
10386
10624
  {
10387
10625
  type: "button",
10388
10626
  onClick: () => onOpenFlag && onOpenFlag(item.key),
10389
10627
  style: { all: "unset", cursor: "pointer", display: "inline-flex", alignItems: "center", gap: 5 },
10390
- children: /* @__PURE__ */ (0, import_jsx_runtime79.jsx)("code", { className: "fd-mono", style: { fontSize: 11, color: "var(--brand)" }, children: item.key })
10628
+ children: /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("code", { className: "fd-mono", style: { fontSize: 11, color: "var(--brand)" }, children: item.key })
10391
10629
  }
10392
10630
  )
10393
10631
  ] }),
10394
- deps.length ? /* @__PURE__ */ (0, import_jsx_runtime79.jsxs)("div", { className: "fd-row", style: { gap: 6, flexWrap: "wrap", paddingTop: 6, borderTop: "1px solid var(--border)" }, children: [
10395
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)("span", { className: "fd-overline fd-muted", style: { paddingTop: 3 }, children: "After" }),
10396
- deps.map((d) => /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(Tag, { icon: d.implemented ? "check" : "clock", children: d.label }, d.key))
10632
+ deps.length ? /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("div", { className: "fd-row", style: { gap: 6, flexWrap: "wrap", paddingTop: 6, borderTop: "1px solid var(--border)" }, children: [
10633
+ /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("span", { className: "fd-overline fd-muted", style: { paddingTop: 3 }, children: "After" }),
10634
+ deps.map((d) => /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(Tag, { icon: d.implemented ? "check" : "clock", children: d.label }, d.key))
10397
10635
  ] }) : null,
10398
- blocking.length && !item.implemented ? /* @__PURE__ */ (0, import_jsx_runtime79.jsxs)("span", { className: "fd-body-sm", style: { color: "var(--warn-text)" }, children: [
10636
+ blocking.length && !item.implemented ? /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("span", { className: "fd-body-sm", style: { color: "var(--warn-text)" }, children: [
10399
10637
  "Blocked until ",
10400
10638
  blocking.map((d) => d.label).join(" and "),
10401
10639
  " ",
@@ -10406,12 +10644,12 @@ function RoadmapCard({ item, byKey, onOpenFlag }) {
10406
10644
  }
10407
10645
  function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
10408
10646
  const session = SessionKit.useSession();
10409
- const [project, setProject] = React53.useState("");
10410
- const [q, setQ] = React53.useState("");
10411
- const scrollRef = React53.useRef(null);
10412
- const nowRef = React53.useRef(null);
10413
- const rm = React53.useMemo(() => SessionKit.roadmap({ isComplete: RuntimeKit.isComplete }), [session]);
10414
- const byKey = React53.useMemo(() => {
10647
+ const [project, setProject] = React54.useState("");
10648
+ const [q, setQ] = React54.useState("");
10649
+ const scrollRef = React54.useRef(null);
10650
+ const nowRef = React54.useRef(null);
10651
+ const rm = React54.useMemo(() => SessionKit.roadmap({ isComplete: RuntimeKit.isComplete }), [session]);
10652
+ const byKey = React54.useMemo(() => {
10415
10653
  const m = {};
10416
10654
  rm.items.forEach((i) => {
10417
10655
  m[i.key] = i;
@@ -10420,7 +10658,7 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
10420
10658
  }, [rm]);
10421
10659
  const items = rm.items.filter((i) => (!project || i.project === project) && (!q || (i.label + " " + i.description + " " + (i.backend || "") + " " + i.key).toLowerCase().includes(q.toLowerCase())));
10422
10660
  const projects = [...new Set(rm.items.map((i) => i.project))];
10423
- React53.useEffect(() => {
10661
+ React54.useEffect(() => {
10424
10662
  let raf1 = 0, raf2 = 0;
10425
10663
  const place = () => {
10426
10664
  const box = scrollRef.current, mark = nowRef.current;
@@ -10448,23 +10686,23 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
10448
10686
  }, 0);
10449
10687
  const nextPhase = items.find((i) => !i.implemented);
10450
10688
  let lastPhase = null;
10451
- return /* @__PURE__ */ (0, import_jsx_runtime79.jsxs)("div", { className: "fd-stack", style: { gap: 16, maxWidth: 1e3 }, children: [
10452
- /* @__PURE__ */ (0, import_jsx_runtime79.jsxs)("div", { className: "fd-stack", style: { gap: 10 }, children: [
10453
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)("span", { className: "fd-overline fd-muted", children: "Architecture" }),
10454
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)("h1", { className: "fd-h1", style: { margin: 0 }, children: title }),
10455
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)("p", { className: "fd-body fd-secondary fd-prose", style: { margin: 0 }, children: lede || "Every screen and feature in these tools is already designed and working against a simulated backend. This is the plan for connecting them to the real one \u2014 so the only work described here is server work." })
10689
+ return /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("div", { className: "fd-stack", style: { gap: 16, maxWidth: 1e3 }, children: [
10690
+ /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("div", { className: "fd-stack", style: { gap: 10 }, children: [
10691
+ /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("span", { className: "fd-overline fd-muted", children: "Architecture" }),
10692
+ /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("h1", { className: "fd-h1", style: { margin: 0 }, children: title }),
10693
+ /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("p", { className: "fd-body fd-secondary fd-prose", style: { margin: 0 }, children: lede || "Every screen and feature in these tools is already designed and working against a simulated backend. This is the plan for connecting them to the real one \u2014 so the only work described here is server work." })
10456
10694
  ] }),
10457
- /* @__PURE__ */ (0, import_jsx_runtime79.jsxs)("div", { className: "fd-grid-stats is-thin", children: [
10458
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(StatTile, { compact: true, label: "Wired", value: String(rm.shipped), sub: "of " + rm.items.length + " features" }),
10459
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(StatTile, { compact: true, label: "Remaining", value: String(rm.remaining), sub: "backend work" }),
10460
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(StatTile, { compact: true, label: "Est. effort", value: days ? days + " days" : "\u2014", sub: "sum of estimates, not calendar" }),
10461
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(StatTile, { compact: true, label: "Up next", value: nextPhase ? "Phase " + nextPhase.phase : "\u2014", sub: nextPhase ? nextPhase.phaseName : "all wired" })
10695
+ /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("div", { className: "fd-grid-stats is-thin", children: [
10696
+ /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(StatTile, { compact: true, label: "Wired", value: String(rm.shipped), sub: "of " + rm.items.length + " features" }),
10697
+ /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(StatTile, { compact: true, label: "Remaining", value: String(rm.remaining), sub: "backend work" }),
10698
+ /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(StatTile, { compact: true, label: "Est. effort", value: days ? days + " days" : "\u2014", sub: "sum of estimates, not calendar" }),
10699
+ /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(StatTile, { compact: true, label: "Up next", value: nextPhase ? "Phase " + nextPhase.phase : "\u2014", sub: nextPhase ? nextPhase.phaseName : "all wired" })
10462
10700
  ] }),
10463
- /* @__PURE__ */ (0, import_jsx_runtime79.jsxs)("div", { className: "fd-row", style: { gap: 10, flexWrap: "wrap" }, children: [
10464
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(Input, { icon: "magnifying-glass", placeholder: "Find a feature or a piece of backend work", value: q, onChange: (e) => setQ(e.target.value), style: { width: 300 } }),
10465
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(Select, { placeholder: "All projects", value: project, onChange: (e) => setProject(e.target.value), options: projects, style: { width: 190 } }),
10466
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)("span", { style: { flex: 1 } }),
10467
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(
10701
+ /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("div", { className: "fd-row", style: { gap: 10, flexWrap: "wrap" }, children: [
10702
+ /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(Input, { icon: "magnifying-glass", placeholder: "Find a feature or a piece of backend work", value: q, onChange: (e) => setQ(e.target.value), style: { width: 300 } }),
10703
+ /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(Select, { placeholder: "All projects", value: project, onChange: (e) => setProject(e.target.value), options: projects, style: { width: 190 } }),
10704
+ /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("span", { style: { flex: 1 } }),
10705
+ /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(
10468
10706
  Button,
10469
10707
  {
10470
10708
  size: "sm",
@@ -10478,7 +10716,7 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
10478
10716
  }
10479
10717
  )
10480
10718
  ] }),
10481
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(
10719
+ /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(
10482
10720
  Flag,
10483
10721
  {
10484
10722
  tone: "info",
@@ -10487,60 +10725,60 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
10487
10725
  actions: null
10488
10726
  }
10489
10727
  ),
10490
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)("div", { className: "fd-rm", children: /* @__PURE__ */ (0, import_jsx_runtime79.jsx)("div", { className: "fd-rm-scroll", ref: scrollRef, children: /* @__PURE__ */ (0, import_jsx_runtime79.jsxs)("div", { className: "fd-rm-track", children: [
10491
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)("span", { className: "fd-rm-spine", children: /* @__PURE__ */ (0, import_jsx_runtime79.jsx)("span", { className: "fd-rm-spine-done", style: { height: items.length ? 100 * shippedShown / items.length + "%" : "0%" } }) }),
10728
+ /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("div", { className: "fd-rm", children: /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("div", { className: "fd-rm-scroll", ref: scrollRef, children: /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("div", { className: "fd-rm-track", children: [
10729
+ /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("span", { className: "fd-rm-spine", children: /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("span", { className: "fd-rm-spine-done", style: { height: items.length ? 100 * shippedShown / items.length + "%" : "0%" } }) }),
10492
10730
  items.map((item, n) => {
10493
10731
  const showPhase = item.phase !== lastPhase;
10494
10732
  lastPhase = item.phase;
10495
10733
  const inPhase = items.filter((i) => i.phase === item.phase).length;
10496
10734
  const isBoundary = n === firstPending;
10497
- return /* @__PURE__ */ (0, import_jsx_runtime79.jsxs)(React53.Fragment, { children: [
10498
- showPhase ? /* @__PURE__ */ (0, import_jsx_runtime79.jsxs)("div", { className: "fd-rm-era", children: [
10499
- /* @__PURE__ */ (0, import_jsx_runtime79.jsxs)("span", { className: "fd-row", style: { gap: 8, flexWrap: "wrap", alignItems: "baseline" }, children: [
10500
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)("span", { style: { fontWeight: 700 }, children: item.phase === 0 ? "Shipped" : "Phase " + item.phase + " \u2014 " + item.phaseName }),
10501
- item.phase === 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime79.jsxs)("span", { className: "fd-mono", style: { opacity: 0.7, fontWeight: 400 }, children: [
10735
+ return /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)(React54.Fragment, { children: [
10736
+ showPhase ? /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("div", { className: "fd-rm-era", children: [
10737
+ /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("span", { className: "fd-row", style: { gap: 8, flexWrap: "wrap", alignItems: "baseline" }, children: [
10738
+ /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("span", { style: { fontWeight: 700 }, children: item.phase === 0 ? "Shipped" : "Phase " + item.phase + " \u2014 " + item.phaseName }),
10739
+ item.phase === 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("span", { className: "fd-mono", style: { opacity: 0.7, fontWeight: 400 }, children: [
10502
10740
  fmtDate(item.phaseStart),
10503
10741
  " \u2013 ",
10504
10742
  fmtDate(item.date)
10505
10743
  ] }),
10506
- /* @__PURE__ */ (0, import_jsx_runtime79.jsxs)("span", { style: { opacity: 0.7, fontWeight: 400 }, children: [
10744
+ /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("span", { style: { opacity: 0.7, fontWeight: 400 }, children: [
10507
10745
  "\xB7 ",
10508
10746
  inPhase,
10509
10747
  " feature",
10510
10748
  inPhase === 1 ? "" : "s"
10511
10749
  ] })
10512
10750
  ] }),
10513
- item.phaseWhy ? /* @__PURE__ */ (0, import_jsx_runtime79.jsx)("p", { className: "fd-rm-era-why", children: item.phaseWhy }) : null
10751
+ item.phaseWhy ? /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("p", { className: "fd-rm-era-why", children: item.phaseWhy }) : null
10514
10752
  ] }) : null,
10515
- isBoundary ? /* @__PURE__ */ (0, import_jsx_runtime79.jsx)("div", { className: "fd-rm-now", ref: nowRef, children: /* @__PURE__ */ (0, import_jsx_runtime79.jsxs)("span", { className: "fd-rm-now-pill", children: [
10516
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)("i", { className: "ph ph-map-pin" }),
10753
+ isBoundary ? /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("div", { className: "fd-rm-now", ref: nowRef, children: /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("span", { className: "fd-rm-now-pill", children: [
10754
+ /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("i", { className: "ph ph-map-pin" }),
10517
10755
  " You are here \u2014 everything above is wired"
10518
10756
  ] }) }) : null,
10519
- /* @__PURE__ */ (0, import_jsx_runtime79.jsxs)("div", { className: "fd-rm-row", children: [
10520
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)("span", { className: "fd-rm-dot " + (item.implemented ? "is-shipped" : item.status === "next" ? "is-next" : "") }),
10521
- /* @__PURE__ */ (0, import_jsx_runtime79.jsxs)("div", { className: "fd-rm-date", children: [
10757
+ /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("div", { className: "fd-rm-row", children: [
10758
+ /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("span", { className: "fd-rm-dot " + (item.implemented ? "is-shipped" : item.status === "next" ? "is-next" : "") }),
10759
+ /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("div", { className: "fd-rm-date", children: [
10522
10760
  fmtDate(item.date),
10523
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)("br", {}),
10524
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)("span", { style: { opacity: 0.75 }, children: item.implemented ? "shipped" : "phase " + item.phase })
10761
+ /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("br", {}),
10762
+ /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("span", { style: { opacity: 0.75 }, children: item.implemented ? "shipped" : "phase " + item.phase })
10525
10763
  ] }),
10526
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(RoadmapCard, { item, byKey, onOpenFlag })
10764
+ /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(RoadmapCard, { item, byKey, onOpenFlag })
10527
10765
  ] })
10528
10766
  ] }, item.key);
10529
10767
  }),
10530
- !items.length ? /* @__PURE__ */ (0, import_jsx_runtime79.jsx)("p", { className: "fd-body-sm fd-muted", children: "Nothing matches that filter." }) : null
10768
+ !items.length ? /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("p", { className: "fd-body-sm fd-muted", children: "Nothing matches that filter." }) : null
10531
10769
  ] }) }) }),
10532
- /* @__PURE__ */ (0, import_jsx_runtime79.jsxs)("p", { className: "fd-body-sm fd-muted", style: { margin: 0 }, children: [
10770
+ /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("p", { className: "fd-body-sm fd-muted", style: { margin: 0 }, children: [
10533
10771
  "Derived from the feature-flag registry \u2014 each entry's status is its flag's ",
10534
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)("code", { className: "fd-mono", children: "implemented" }),
10772
+ /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("code", { className: "fd-mono", children: "implemented" }),
10535
10773
  " field, so this page cannot drift from what the apps actually do."
10536
10774
  ] })
10537
10775
  ] });
10538
10776
  }
10539
10777
 
10540
10778
  // src/components/platform/ComingSoon.tsx
10541
- var React54 = __toESM(require("react"), 1);
10779
+ var React55 = __toESM(require("react"), 1);
10542
10780
  var import_react_dom6 = require("react-dom");
10543
- var import_jsx_runtime80 = require("react/jsx-runtime");
10781
+ var import_jsx_runtime81 = require("react/jsx-runtime");
10544
10782
  var BYPASS_STORE = "fd.soon.bypass.v1";
10545
10783
  function readBypassed() {
10546
10784
  try {
@@ -10556,8 +10794,8 @@ function writeBypassed(list) {
10556
10794
  }
10557
10795
  }
10558
10796
  function useBypass(key) {
10559
- const [on, setOn] = React54.useState(() => !!key && readBypassed().indexOf(key) >= 0);
10560
- React54.useEffect(() => {
10797
+ const [on, setOn] = React55.useState(() => !!key && readBypassed().indexOf(key) >= 0);
10798
+ React55.useEffect(() => {
10561
10799
  setOn(!!key && readBypassed().indexOf(key) >= 0);
10562
10800
  }, [key]);
10563
10801
  const set = (next) => {
@@ -10570,43 +10808,43 @@ function useBypass(key) {
10570
10808
  return [on, set];
10571
10809
  }
10572
10810
  function SoonCard({ label, detail, backend, eta, effort, onRoadmap, allowed, onBypass }) {
10573
- return /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)(import_jsx_runtime80.Fragment, { children: [
10574
- /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("span", { className: "fd-soon-badge", children: [
10575
- /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" }),
10811
+ return /* @__PURE__ */ (0, import_jsx_runtime81.jsxs)(import_jsx_runtime81.Fragment, { children: [
10812
+ /* @__PURE__ */ (0, import_jsx_runtime81.jsxs)("span", { className: "fd-soon-badge", children: [
10813
+ /* @__PURE__ */ (0, import_jsx_runtime81.jsx)("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" }),
10576
10814
  label
10577
10815
  ] }),
10578
- detail ? /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("span", { className: "fd-soon-detail", children: detail }) : null,
10579
- backend ? /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("span", { className: "fd-soon-backend", children: [
10580
- /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("span", { className: "fd-overline", children: "Needs" }),
10816
+ detail ? /* @__PURE__ */ (0, import_jsx_runtime81.jsx)("span", { className: "fd-soon-detail", children: detail }) : null,
10817
+ backend ? /* @__PURE__ */ (0, import_jsx_runtime81.jsxs)("span", { className: "fd-soon-backend", children: [
10818
+ /* @__PURE__ */ (0, import_jsx_runtime81.jsx)("span", { className: "fd-overline", children: "Needs" }),
10581
10819
  " ",
10582
10820
  backend
10583
10821
  ] }) : null,
10584
- eta || effort || onRoadmap ? /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("span", { className: "fd-soon-meta", children: [
10585
- eta ? /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("span", { children: [
10586
- /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("i", { className: "ph ph-calendar-blank", "aria-hidden": "true" }),
10822
+ eta || effort || onRoadmap ? /* @__PURE__ */ (0, import_jsx_runtime81.jsxs)("span", { className: "fd-soon-meta", children: [
10823
+ eta ? /* @__PURE__ */ (0, import_jsx_runtime81.jsxs)("span", { children: [
10824
+ /* @__PURE__ */ (0, import_jsx_runtime81.jsx)("i", { className: "ph ph-calendar-blank", "aria-hidden": "true" }),
10587
10825
  " ",
10588
10826
  eta
10589
10827
  ] }) : null,
10590
- effort ? /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("span", { children: [
10591
- /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("i", { className: "ph ph-hourglass-medium", "aria-hidden": "true" }),
10828
+ effort ? /* @__PURE__ */ (0, import_jsx_runtime81.jsxs)("span", { children: [
10829
+ /* @__PURE__ */ (0, import_jsx_runtime81.jsx)("i", { className: "ph ph-hourglass-medium", "aria-hidden": "true" }),
10592
10830
  " ",
10593
10831
  effort
10594
10832
  ] }) : null,
10595
- onRoadmap ? /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("button", { type: "button", className: "fd-soon-link", onClick: onRoadmap, children: [
10833
+ onRoadmap ? /* @__PURE__ */ (0, import_jsx_runtime81.jsxs)("button", { type: "button", className: "fd-soon-link", onClick: onRoadmap, children: [
10596
10834
  "See the roadmap ",
10597
- /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("i", { className: "ph ph-arrow-right", "aria-hidden": "true" })
10835
+ /* @__PURE__ */ (0, import_jsx_runtime81.jsx)("i", { className: "ph ph-arrow-right", "aria-hidden": "true" })
10598
10836
  ] }) : null
10599
10837
  ] }) : null,
10600
- allowed ? /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("button", { type: "button", className: "fd-soon-view", onClick: onBypass, children: [
10601
- /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("i", { className: "ph ph-eye", "aria-hidden": "true" }),
10838
+ allowed ? /* @__PURE__ */ (0, import_jsx_runtime81.jsxs)("button", { type: "button", className: "fd-soon-view", onClick: onBypass, children: [
10839
+ /* @__PURE__ */ (0, import_jsx_runtime81.jsx)("i", { className: "ph ph-eye", "aria-hidden": "true" }),
10602
10840
  " View and use it anyway"
10603
10841
  ] }) : null
10604
10842
  ] });
10605
10843
  }
10606
10844
  function useHoverCard(open2) {
10607
- const anchor = React54.useRef(null);
10608
- const [pos, setPos] = React54.useState(null);
10609
- React54.useLayoutEffect(() => {
10845
+ const anchor = React55.useRef(null);
10846
+ const [pos, setPos] = React55.useState(null);
10847
+ React55.useLayoutEffect(() => {
10610
10848
  if (!open2 || !anchor.current) {
10611
10849
  setPos(null);
10612
10850
  return;
@@ -10658,9 +10896,9 @@ function ComingSoon({
10658
10896
  const tip = [label, detail, backend ? "Needs " + backend : null, eta ? "ETA " + eta : null, effort].filter(Boolean).join(" \xB7 ");
10659
10897
  if (inline) {
10660
10898
  if (allowed && bypassed) {
10661
- return /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("span", { className: ["fd-soon-inline-on", className].filter(Boolean).join(" "), ...rest, children: [
10899
+ return /* @__PURE__ */ (0, import_jsx_runtime81.jsxs)("span", { className: ["fd-soon-inline-on", className].filter(Boolean).join(" "), ...rest, children: [
10662
10900
  children,
10663
- /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(
10901
+ /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(
10664
10902
  "button",
10665
10903
  {
10666
10904
  type: "button",
@@ -10668,12 +10906,12 @@ function ComingSoon({
10668
10906
  title: "Unwired \u2014 writes go to the simulated backend. " + tip + " Click to re-blur.",
10669
10907
  onClick: () => setBypassed(false),
10670
10908
  "aria-label": "Re-blur this unwired feature",
10671
- children: /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" })
10909
+ children: /* @__PURE__ */ (0, import_jsx_runtime81.jsx)("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" })
10672
10910
  }
10673
10911
  )
10674
10912
  ] });
10675
10913
  }
10676
- return /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(
10914
+ return /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(
10677
10915
  InlineSoon,
10678
10916
  {
10679
10917
  label,
@@ -10693,20 +10931,20 @@ function ComingSoon({
10693
10931
  );
10694
10932
  }
10695
10933
  if (allowed && bypassed) {
10696
- return /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 14 }, ...rest, children: [
10697
- /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("div", { className: "fd-soon-bar", role: "status", children: [
10698
- /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("span", { className: "fd-soon-badge", children: [
10699
- /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" }),
10934
+ return /* @__PURE__ */ (0, import_jsx_runtime81.jsxs)("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 14 }, ...rest, children: [
10935
+ /* @__PURE__ */ (0, import_jsx_runtime81.jsxs)("div", { className: "fd-soon-bar", role: "status", children: [
10936
+ /* @__PURE__ */ (0, import_jsx_runtime81.jsxs)("span", { className: "fd-soon-badge", children: [
10937
+ /* @__PURE__ */ (0, import_jsx_runtime81.jsx)("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" }),
10700
10938
  "Unwired feature \u2014 you are using it anyway"
10701
10939
  ] }),
10702
- /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("span", { className: "fd-soon-bar-detail", children: "Every action here writes to the simulated backend, so nothing you do persists beyond this session." }),
10703
- /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("span", { className: "fd-soon-bar-actions", children: [
10704
- onRoadmap ? /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("button", { type: "button", className: "fd-soon-link", onClick: onRoadmap, children: [
10940
+ /* @__PURE__ */ (0, import_jsx_runtime81.jsx)("span", { className: "fd-soon-bar-detail", children: "Every action here writes to the simulated backend, so nothing you do persists beyond this session." }),
10941
+ /* @__PURE__ */ (0, import_jsx_runtime81.jsxs)("span", { className: "fd-soon-bar-actions", children: [
10942
+ onRoadmap ? /* @__PURE__ */ (0, import_jsx_runtime81.jsxs)("button", { type: "button", className: "fd-soon-link", onClick: onRoadmap, children: [
10705
10943
  "Roadmap ",
10706
- /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("i", { className: "ph ph-arrow-right", "aria-hidden": "true" })
10944
+ /* @__PURE__ */ (0, import_jsx_runtime81.jsx)("i", { className: "ph ph-arrow-right", "aria-hidden": "true" })
10707
10945
  ] }) : null,
10708
- /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("button", { type: "button", className: "fd-soon-link", onClick: () => setBypassed(false), children: [
10709
- /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("i", { className: "ph ph-eye-slash", "aria-hidden": "true" }),
10946
+ /* @__PURE__ */ (0, import_jsx_runtime81.jsxs)("button", { type: "button", className: "fd-soon-link", onClick: () => setBypassed(false), children: [
10947
+ /* @__PURE__ */ (0, import_jsx_runtime81.jsx)("i", { className: "ph ph-eye-slash", "aria-hidden": "true" }),
10710
10948
  " Re-blur"
10711
10949
  ] })
10712
10950
  ] })
@@ -10714,10 +10952,10 @@ function ComingSoon({
10714
10952
  children
10715
10953
  ] });
10716
10954
  }
10717
- return /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("div", { className: ["fd-soon", className].filter(Boolean).join(" "), style: minHeight ? { minHeight } : void 0, ...rest, children: [
10718
- /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("div", { className: "fd-soon-under", style: { filter: "blur(" + blur + "px) saturate(.62)" }, ...{ inert: "" }, "aria-hidden": "true", children }),
10719
- /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("div", { className: "fd-soon-veil" }),
10720
- /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("div", { className: "fd-soon-note", role: "note", children: /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(
10955
+ return /* @__PURE__ */ (0, import_jsx_runtime81.jsxs)("div", { className: ["fd-soon", className].filter(Boolean).join(" "), style: minHeight ? { minHeight } : void 0, ...rest, children: [
10956
+ /* @__PURE__ */ (0, import_jsx_runtime81.jsx)("div", { className: "fd-soon-under", style: { filter: "blur(" + blur + "px) saturate(.62)" }, ...{ inert: "" }, "aria-hidden": "true", children }),
10957
+ /* @__PURE__ */ (0, import_jsx_runtime81.jsx)("div", { className: "fd-soon-veil" }),
10958
+ /* @__PURE__ */ (0, import_jsx_runtime81.jsx)("div", { className: "fd-soon-note", role: "note", children: /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(
10721
10959
  SoonCard,
10722
10960
  {
10723
10961
  label,
@@ -10733,10 +10971,10 @@ function ComingSoon({
10733
10971
  ] });
10734
10972
  }
10735
10973
  function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, onBypass, blur, tip, className, rest, children }) {
10736
- const [open2, setOpen] = React54.useState(false);
10974
+ const [open2, setOpen] = React55.useState(false);
10737
10975
  const [anchor, pos] = useHoverCard(open2);
10738
10976
  const zIndex = useOverlayLayer(open2);
10739
- const close2 = React54.useRef(null);
10977
+ const close2 = React55.useRef(null);
10740
10978
  const show = () => {
10741
10979
  if (close2.current) {
10742
10980
  clearTimeout(close2.current);
@@ -10752,10 +10990,10 @@ function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, o
10752
10990
  setOpen(false);
10753
10991
  }, 140);
10754
10992
  };
10755
- React54.useEffect(() => () => {
10993
+ React55.useEffect(() => () => {
10756
10994
  if (close2.current) clearTimeout(close2.current);
10757
10995
  }, []);
10758
- return /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)(
10996
+ return /* @__PURE__ */ (0, import_jsx_runtime81.jsxs)(
10759
10997
  "span",
10760
10998
  {
10761
10999
  ref: anchor,
@@ -10766,8 +11004,8 @@ function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, o
10766
11004
  onBlur: hide,
10767
11005
  ...rest,
10768
11006
  children: [
10769
- /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("span", { className: "fd-soon-under", style: { filter: "blur(" + Math.min(blur, 1.1) + "px) saturate(.66)" }, ...{ inert: "" }, "aria-hidden": "true", children }),
10770
- /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(
11007
+ /* @__PURE__ */ (0, import_jsx_runtime81.jsx)("span", { className: "fd-soon-under", style: { filter: "blur(" + Math.min(blur, 1.1) + "px) saturate(.66)" }, ...{ inert: "" }, "aria-hidden": "true", children }),
11008
+ /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(
10771
11009
  "button",
10772
11010
  {
10773
11011
  type: "button",
@@ -10778,11 +11016,11 @@ function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, o
10778
11016
  onFocus: show,
10779
11017
  onBlur: hide,
10780
11018
  onClick: () => open2 ? setOpen(false) : show(),
10781
- children: /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" })
11019
+ children: /* @__PURE__ */ (0, import_jsx_runtime81.jsx)("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" })
10782
11020
  }
10783
11021
  ),
10784
11022
  open2 && pos ? (0, import_react_dom6.createPortal)(
10785
- /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(LayerProvider, { zIndex, children: /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(
11023
+ /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(LayerProvider, { zIndex, children: /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(
10786
11024
  "div",
10787
11025
  {
10788
11026
  className: "fd-soon-note fd-soon-hovercard",
@@ -10790,7 +11028,7 @@ function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, o
10790
11028
  style: { position: "fixed", left: pos.left, top: pos.top, bottom: pos.bottom, width: pos.width, zIndex },
10791
11029
  onMouseEnter: show,
10792
11030
  onMouseLeave: hide,
10793
- children: /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(
11031
+ children: /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(
10794
11032
  SoonCard,
10795
11033
  {
10796
11034
  label,
@@ -10820,10 +11058,10 @@ function formatEta(iso2) {
10820
11058
  var FormatEta = formatEta;
10821
11059
 
10822
11060
  // src/components/platform/Gate.tsx
10823
- var import_jsx_runtime81 = require("react/jsx-runtime");
11061
+ var import_jsx_runtime82 = require("react/jsx-runtime");
10824
11062
  function PermissionDenied({ permission, title, detail, compact: compact3 = false, className = "", ...rest }) {
10825
11063
  const need = Array.isArray(permission) ? permission : [permission].filter(Boolean);
10826
- return /* @__PURE__ */ (0, import_jsx_runtime81.jsxs)(
11064
+ return /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)(
10827
11065
  "div",
10828
11066
  {
10829
11067
  className: ["fd-stack", className].filter(Boolean).join(" "),
@@ -10839,14 +11077,14 @@ function PermissionDenied({ permission, title, detail, compact: compact3 = false
10839
11077
  },
10840
11078
  ...rest,
10841
11079
  children: [
10842
- /* @__PURE__ */ (0, import_jsx_runtime81.jsxs)("span", { className: "fd-row", style: { gap: 8 }, children: [
10843
- /* @__PURE__ */ (0, import_jsx_runtime81.jsx)("i", { className: "ph ph-lock-simple", style: { fontSize: 16, color: "var(--text-muted)" }, "aria-hidden": "true" }),
10844
- /* @__PURE__ */ (0, import_jsx_runtime81.jsx)("span", { className: compact3 ? "fd-label-lg" : "fd-h3", children: title || "You do not have access to this" })
11080
+ /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)("span", { className: "fd-row", style: { gap: 8 }, children: [
11081
+ /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("i", { className: "ph ph-lock-simple", style: { fontSize: 16, color: "var(--text-muted)" }, "aria-hidden": "true" }),
11082
+ /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("span", { className: compact3 ? "fd-label-lg" : "fd-h3", children: title || "You do not have access to this" })
10845
11083
  ] }),
10846
- /* @__PURE__ */ (0, import_jsx_runtime81.jsx)("p", { className: "fd-body-sm fd-secondary", style: { margin: 0, textWrap: "pretty" }, children: detail || "Your roles do not grant this. An administrator can change that from Admin \u2192 Users." }),
10847
- need.length ? /* @__PURE__ */ (0, import_jsx_runtime81.jsxs)("span", { className: "fd-row", style: { gap: 6, flexWrap: "wrap" }, children: [
10848
- /* @__PURE__ */ (0, import_jsx_runtime81.jsx)("span", { className: "fd-overline fd-muted", children: "Requires" }),
10849
- need.map((p) => /* @__PURE__ */ (0, import_jsx_runtime81.jsx)("code", { className: "fd-mono", style: {
11084
+ /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("p", { className: "fd-body-sm fd-secondary", style: { margin: 0, textWrap: "pretty" }, children: detail || "Your roles do not grant this. An administrator can change that from Admin \u2192 Users." }),
11085
+ need.length ? /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)("span", { className: "fd-row", style: { gap: 6, flexWrap: "wrap" }, children: [
11086
+ /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("span", { className: "fd-overline fd-muted", children: "Requires" }),
11087
+ need.map((p) => /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("code", { className: "fd-mono", style: {
10850
11088
  fontSize: 11.5,
10851
11089
  padding: "2px 7px",
10852
11090
  borderRadius: 5,
@@ -10859,7 +11097,7 @@ function PermissionDenied({ permission, title, detail, compact: compact3 = false
10859
11097
  );
10860
11098
  }
10861
11099
  function GatePending({ compact: compact3 = false, className = "" }) {
10862
- return /* @__PURE__ */ (0, import_jsx_runtime81.jsxs)(
11100
+ return /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)(
10863
11101
  "div",
10864
11102
  {
10865
11103
  className: ["fd-stack", className].filter(Boolean).join(" "),
@@ -10875,11 +11113,11 @@ function GatePending({ compact: compact3 = false, className = "" }) {
10875
11113
  textAlign: "left"
10876
11114
  },
10877
11115
  children: [
10878
- /* @__PURE__ */ (0, import_jsx_runtime81.jsxs)("span", { className: "fd-row", style: { gap: 8 }, children: [
10879
- /* @__PURE__ */ (0, import_jsx_runtime81.jsx)("i", { className: "ph ph-arrows-clockwise", style: { fontSize: 16, color: "var(--text-muted)" }, "aria-hidden": "true" }),
10880
- /* @__PURE__ */ (0, import_jsx_runtime81.jsx)("span", { className: compact3 ? "fd-label-lg" : "fd-h3", children: "Reconnecting\u2026" })
11116
+ /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)("span", { className: "fd-row", style: { gap: 8 }, children: [
11117
+ /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("i", { className: "ph ph-arrows-clockwise", style: { fontSize: 16, color: "var(--text-muted)" }, "aria-hidden": "true" }),
11118
+ /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("span", { className: compact3 ? "fd-label-lg" : "fd-h3", children: "Reconnecting\u2026" })
10881
11119
  ] }),
10882
- /* @__PURE__ */ (0, import_jsx_runtime81.jsx)("p", { className: "fd-body-sm fd-secondary", style: { margin: 0, textWrap: "pretty" }, children: "Your access can't be verified right now. This will resolve on its own once the connection is back." })
11120
+ /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("p", { className: "fd-body-sm fd-secondary", style: { margin: 0, textWrap: "pretty" }, children: "Your access can't be verified right now. This will resolve on its own once the connection is back." })
10883
11121
  ]
10884
11122
  }
10885
11123
  );
@@ -10889,7 +11127,7 @@ function Gate({ perm, anyOf, role, silent = false, fallback, pendingFallback, co
10889
11127
  if (pending) {
10890
11128
  if (pendingFallback !== void 0) return pendingFallback;
10891
11129
  if (silent) return null;
10892
- return /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(GatePending, { compact: compact3 });
11130
+ return /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(GatePending, { compact: compact3 });
10893
11131
  }
10894
11132
  let ok = true;
10895
11133
  if (perm) ok = ok && can2(perm);
@@ -10898,7 +11136,7 @@ function Gate({ perm, anyOf, role, silent = false, fallback, pendingFallback, co
10898
11136
  if (ok) return children;
10899
11137
  if (fallback !== void 0) return fallback;
10900
11138
  if (silent) return null;
10901
- return /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(PermissionDenied, { permission: perm || anyOf, compact: compact3 });
11139
+ return /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(PermissionDenied, { permission: perm || anyOf, compact: compact3 });
10902
11140
  }
10903
11141
  function FeatureGate({
10904
11142
  flag,
@@ -10921,7 +11159,7 @@ function FeatureGate({
10921
11159
  const f = SessionKit.findFlag(flag) || {};
10922
11160
  const missing = rt.missing || [];
10923
11161
  const canBypass = pending ? false : bypassPerm === null ? false : !bypassPerm || can2(bypassPerm);
10924
- return /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(
11162
+ return /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(
10925
11163
  ComingSoon,
10926
11164
  {
10927
11165
  label: label || (variant === "inline" ? f.label || "Not wired yet" : "Designed \u2014 backend not wired yet"),
@@ -10942,22 +11180,22 @@ function FeatureGate({
10942
11180
  function PermissionHint({ perm, children }) {
10943
11181
  const { can: can2, pending } = useSessionContext();
10944
11182
  if (pending) {
10945
- return /* @__PURE__ */ (0, import_jsx_runtime81.jsx)("span", { title: "Access can't be verified right now", style: { display: "inline-flex", opacity: 0.45, cursor: "not-allowed" }, "aria-disabled": "true", children: /* @__PURE__ */ (0, import_jsx_runtime81.jsx)("span", { style: { pointerEvents: "none" }, children }) });
11183
+ return /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("span", { title: "Access can't be verified right now", style: { display: "inline-flex", opacity: 0.45, cursor: "not-allowed" }, "aria-disabled": "true", children: /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("span", { style: { pointerEvents: "none" }, children }) });
10946
11184
  }
10947
11185
  if (can2(perm)) return children;
10948
- return /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(
11186
+ return /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(
10949
11187
  "span",
10950
11188
  {
10951
11189
  title: "Requires " + (Array.isArray(perm) ? perm.join(", ") : perm),
10952
11190
  style: { display: "inline-flex", opacity: 0.45, cursor: "not-allowed" },
10953
11191
  "aria-disabled": "true",
10954
- children: /* @__PURE__ */ (0, import_jsx_runtime81.jsx)("span", { style: { pointerEvents: "none" }, children })
11192
+ children: /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("span", { style: { pointerEvents: "none" }, children })
10955
11193
  }
10956
11194
  );
10957
11195
  }
10958
11196
 
10959
11197
  // src/components/platform/ModeSwitch.tsx
10960
- var import_jsx_runtime82 = require("react/jsx-runtime");
11198
+ var import_jsx_runtime83 = require("react/jsx-runtime");
10961
11199
  function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog, onOpenSpec, summary }) {
10962
11200
  const mode2 = useRuntimeMode();
10963
11201
  const panel = useInlinePanel();
@@ -10969,8 +11207,8 @@ function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog
10969
11207
  RuntimeKit.setMode(next);
10970
11208
  setOpen(false);
10971
11209
  };
10972
- return /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)("span", { style: { position: "relative", display: "inline-flex" }, ref, children: [
10973
- /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)(
11210
+ return /* @__PURE__ */ (0, import_jsx_runtime83.jsxs)("span", { style: { position: "relative", display: "inline-flex" }, ref, children: [
11211
+ /* @__PURE__ */ (0, import_jsx_runtime83.jsxs)(
10974
11212
  "button",
10975
11213
  {
10976
11214
  type: "button",
@@ -10980,29 +11218,29 @@ function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog
10980
11218
  title: test ? "Test mode \u2014 every response is simulated. Click to inspect requests or return to live mode." : "Live mode \u2014 incomplete features are shown under construction. Click for test mode.",
10981
11219
  className: "fd-mode-btn" + (test ? " is-test" : "") + (open2 ? " is-open" : ""),
10982
11220
  children: [
10983
- /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("i", { className: "ph " + (test ? "ph-flask" : "ph-lightning"), style: { fontSize: 17 } }),
10984
- test && requestCount ? /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("span", { className: "fd-mono fd-mode-count", children: requestCount > 99 ? "99+" : requestCount }, requestCount) : null
11221
+ /* @__PURE__ */ (0, import_jsx_runtime83.jsx)("i", { className: "ph " + (test ? "ph-flask" : "ph-lightning"), style: { fontSize: 17 } }),
11222
+ test && requestCount ? /* @__PURE__ */ (0, import_jsx_runtime83.jsx)("span", { className: "fd-mono fd-mode-count", children: requestCount > 99 ? "99+" : requestCount }, requestCount) : null
10985
11223
  ]
10986
11224
  }
10987
11225
  ),
10988
- open2 ? /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(InlinePanelLayers, { panel, children: /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)("span", { className: "fd-view-enter fd-mode-pop", style: { zIndex }, children: [
10989
- /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)("span", { className: "fd-row", style: { gap: 10, padding: "12px 14px", borderBottom: "1px solid var(--border)" }, children: [
10990
- /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)("span", { className: "fd-badge " + (test ? "fd-badge-warning" : "fd-badge-neutral"), children: [
10991
- /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("i", { className: "ph " + (test ? "ph-flask" : "ph-lightning"), "aria-hidden": "true" }),
11226
+ open2 ? /* @__PURE__ */ (0, import_jsx_runtime83.jsx)(InlinePanelLayers, { panel, children: /* @__PURE__ */ (0, import_jsx_runtime83.jsxs)("span", { className: "fd-view-enter fd-mode-pop", style: { zIndex }, children: [
11227
+ /* @__PURE__ */ (0, import_jsx_runtime83.jsxs)("span", { className: "fd-row", style: { gap: 10, padding: "12px 14px", borderBottom: "1px solid var(--border)" }, children: [
11228
+ /* @__PURE__ */ (0, import_jsx_runtime83.jsxs)("span", { className: "fd-badge " + (test ? "fd-badge-warning" : "fd-badge-neutral"), children: [
11229
+ /* @__PURE__ */ (0, import_jsx_runtime83.jsx)("i", { className: "ph " + (test ? "ph-flask" : "ph-lightning"), "aria-hidden": "true" }),
10992
11230
  test ? "Test mode" : "Live mode"
10993
11231
  ] }),
10994
- test ? /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)("span", { className: "fd-body-sm fd-muted fd-mono", children: [
11232
+ test ? /* @__PURE__ */ (0, import_jsx_runtime83.jsxs)("span", { className: "fd-body-sm fd-muted fd-mono", children: [
10995
11233
  requestCount,
10996
11234
  " simulated request",
10997
11235
  requestCount === 1 ? "" : "s"
10998
11236
  ] }) : null,
10999
- /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("span", { style: { flex: 1 } }),
11000
- test && onClearLog ? /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("button", { type: "button", className: "fd-soon-link", onClick: onClearLog, children: "Clear" }) : null
11237
+ /* @__PURE__ */ (0, import_jsx_runtime83.jsx)("span", { style: { flex: 1 } }),
11238
+ test && onClearLog ? /* @__PURE__ */ (0, import_jsx_runtime83.jsx)("button", { type: "button", className: "fd-soon-link", onClick: onClearLog, children: "Clear" }) : null
11001
11239
  ] }),
11002
- /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)("span", { style: { display: "block", padding: "12px 14px", borderBottom: "1px solid var(--border)" }, children: [
11003
- /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("span", { className: "fd-body-sm fd-secondary", style: { display: "block", textWrap: "pretty" }, children: test ? "Every feature is usable and nothing is obstructed, but no response comes from a real service \u2014 nothing you do here persists. Use this to review and demo the design." : "This is what a user would see today. " + s.incomplete + " of " + s.total + " features depend on backend work that is not wired yet, so they render under construction." }),
11004
- /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)("span", { className: "fd-row", style: { gap: 8, marginTop: 10, flexWrap: "wrap" }, children: [
11005
- /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)("span", { className: "fd-body-sm fd-muted fd-mono", children: [
11240
+ /* @__PURE__ */ (0, import_jsx_runtime83.jsxs)("span", { style: { display: "block", padding: "12px 14px", borderBottom: "1px solid var(--border)" }, children: [
11241
+ /* @__PURE__ */ (0, import_jsx_runtime83.jsx)("span", { className: "fd-body-sm fd-secondary", style: { display: "block", textWrap: "pretty" }, children: test ? "Every feature is usable and nothing is obstructed, but no response comes from a real service \u2014 nothing you do here persists. Use this to review and demo the design." : "This is what a user would see today. " + s.incomplete + " of " + s.total + " features depend on backend work that is not wired yet, so they render under construction." }),
11242
+ /* @__PURE__ */ (0, import_jsx_runtime83.jsxs)("span", { className: "fd-row", style: { gap: 8, marginTop: 10, flexWrap: "wrap" }, children: [
11243
+ /* @__PURE__ */ (0, import_jsx_runtime83.jsxs)("span", { className: "fd-body-sm fd-muted fd-mono", children: [
11006
11244
  s.endpointsWired,
11007
11245
  " endpoint",
11008
11246
  s.endpointsWired === 1 ? "" : "s",
@@ -11012,58 +11250,58 @@ function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog
11012
11250
  s.total,
11013
11251
  " features complete"
11014
11252
  ] }),
11015
- onOpenSpec ? /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)(import_jsx_runtime82.Fragment, { children: [
11016
- /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("span", { style: { flex: 1 } }),
11017
- /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)("button", { type: "button", className: "fd-soon-link", onClick: () => {
11253
+ onOpenSpec ? /* @__PURE__ */ (0, import_jsx_runtime83.jsxs)(import_jsx_runtime83.Fragment, { children: [
11254
+ /* @__PURE__ */ (0, import_jsx_runtime83.jsx)("span", { style: { flex: 1 } }),
11255
+ /* @__PURE__ */ (0, import_jsx_runtime83.jsxs)("button", { type: "button", className: "fd-soon-link", onClick: () => {
11018
11256
  setOpen(false);
11019
11257
  onOpenSpec();
11020
11258
  }, children: [
11021
11259
  "API spec ",
11022
- /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("i", { className: "ph ph-arrow-right", "aria-hidden": "true" })
11260
+ /* @__PURE__ */ (0, import_jsx_runtime83.jsx)("i", { className: "ph ph-arrow-right", "aria-hidden": "true" })
11023
11261
  ] })
11024
11262
  ] }) : null
11025
11263
  ] })
11026
11264
  ] }),
11027
- /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)("span", { className: "fd-mode-choice", children: [
11028
- /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)("button", { type: "button", className: "fd-mode-opt" + (!test ? " is-on" : ""), onClick: () => go("live"), children: [
11029
- /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("i", { className: "ph ph-lightning", "aria-hidden": "true" }),
11030
- /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)("span", { className: "fd-mode-opt-text", children: [
11031
- /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("span", { className: "fd-mode-opt-title", children: "Live mode" }),
11032
- /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("span", { className: "fd-mode-opt-desc", children: "Incomplete features under construction" })
11265
+ /* @__PURE__ */ (0, import_jsx_runtime83.jsxs)("span", { className: "fd-mode-choice", children: [
11266
+ /* @__PURE__ */ (0, import_jsx_runtime83.jsxs)("button", { type: "button", className: "fd-mode-opt" + (!test ? " is-on" : ""), onClick: () => go("live"), children: [
11267
+ /* @__PURE__ */ (0, import_jsx_runtime83.jsx)("i", { className: "ph ph-lightning", "aria-hidden": "true" }),
11268
+ /* @__PURE__ */ (0, import_jsx_runtime83.jsxs)("span", { className: "fd-mode-opt-text", children: [
11269
+ /* @__PURE__ */ (0, import_jsx_runtime83.jsx)("span", { className: "fd-mode-opt-title", children: "Live mode" }),
11270
+ /* @__PURE__ */ (0, import_jsx_runtime83.jsx)("span", { className: "fd-mode-opt-desc", children: "Incomplete features under construction" })
11033
11271
  ] }),
11034
- !test ? /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("i", { className: "ph ph-check", "aria-hidden": "true" }) : null
11272
+ !test ? /* @__PURE__ */ (0, import_jsx_runtime83.jsx)("i", { className: "ph ph-check", "aria-hidden": "true" }) : null
11035
11273
  ] }),
11036
- /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)("button", { type: "button", className: "fd-mode-opt" + (test ? " is-on" : ""), onClick: () => go("test"), children: [
11037
- /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("i", { className: "ph ph-flask", "aria-hidden": "true" }),
11038
- /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)("span", { className: "fd-mode-opt-text", children: [
11039
- /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("span", { className: "fd-mode-opt-title", children: "Test mode" }),
11040
- /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("span", { className: "fd-mode-opt-desc", children: "Everything usable, all data simulated" })
11274
+ /* @__PURE__ */ (0, import_jsx_runtime83.jsxs)("button", { type: "button", className: "fd-mode-opt" + (test ? " is-on" : ""), onClick: () => go("test"), children: [
11275
+ /* @__PURE__ */ (0, import_jsx_runtime83.jsx)("i", { className: "ph ph-flask", "aria-hidden": "true" }),
11276
+ /* @__PURE__ */ (0, import_jsx_runtime83.jsxs)("span", { className: "fd-mode-opt-text", children: [
11277
+ /* @__PURE__ */ (0, import_jsx_runtime83.jsx)("span", { className: "fd-mode-opt-title", children: "Test mode" }),
11278
+ /* @__PURE__ */ (0, import_jsx_runtime83.jsx)("span", { className: "fd-mode-opt-desc", children: "Everything usable, all data simulated" })
11041
11279
  ] }),
11042
- test ? /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("i", { className: "ph ph-check", "aria-hidden": "true" }) : null
11280
+ test ? /* @__PURE__ */ (0, import_jsx_runtime83.jsx)("i", { className: "ph ph-check", "aria-hidden": "true" }) : null
11043
11281
  ] })
11044
11282
  ] }),
11045
- test && renderLog ? /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("span", { style: { display: "block", maxHeight: 340, overflowY: "auto", borderTop: "1px solid var(--border)" }, children: renderLog() }) : null
11283
+ test && renderLog ? /* @__PURE__ */ (0, import_jsx_runtime83.jsx)("span", { style: { display: "block", maxHeight: 340, overflowY: "auto", borderTop: "1px solid var(--border)" }, children: renderLog() }) : null
11046
11284
  ] }) }) : null
11047
11285
  ] });
11048
11286
  }
11049
11287
  function TestModeBar({ onExit }) {
11050
11288
  const mode2 = useRuntimeMode();
11051
11289
  if (mode2 !== "test") return null;
11052
- return /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)("div", { className: "fd-testbar", role: "status", children: [
11053
- /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)("span", { className: "fd-badge fd-badge-warning", children: [
11054
- /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("i", { className: "ph ph-flask", "aria-hidden": "true" }),
11290
+ return /* @__PURE__ */ (0, import_jsx_runtime83.jsxs)("div", { className: "fd-testbar", role: "status", children: [
11291
+ /* @__PURE__ */ (0, import_jsx_runtime83.jsxs)("span", { className: "fd-badge fd-badge-warning", children: [
11292
+ /* @__PURE__ */ (0, import_jsx_runtime83.jsx)("i", { className: "ph ph-flask", "aria-hidden": "true" }),
11055
11293
  "Test mode"
11056
11294
  ] }),
11057
- /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("span", { className: "fd-testbar-detail", children: "Every feature is unlocked and every response is simulated \u2014 nothing here persists." }),
11058
- /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)("button", { type: "button", className: "fd-soon-link", onClick: () => onExit ? onExit() : RuntimeKit.setMode("live"), children: [
11059
- /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("i", { className: "ph ph-lightning", "aria-hidden": "true" }),
11295
+ /* @__PURE__ */ (0, import_jsx_runtime83.jsx)("span", { className: "fd-testbar-detail", children: "Every feature is unlocked and every response is simulated \u2014 nothing here persists." }),
11296
+ /* @__PURE__ */ (0, import_jsx_runtime83.jsxs)("button", { type: "button", className: "fd-soon-link", onClick: () => onExit ? onExit() : RuntimeKit.setMode("live"), children: [
11297
+ /* @__PURE__ */ (0, import_jsx_runtime83.jsx)("i", { className: "ph ph-lightning", "aria-hidden": "true" }),
11060
11298
  " Back to live mode"
11061
11299
  ] })
11062
11300
  ] });
11063
11301
  }
11064
11302
 
11065
11303
  // src/components/planner/ChannelMeta.tsx
11066
- var import_jsx_runtime83 = require("react/jsx-runtime");
11304
+ var import_jsx_runtime84 = require("react/jsx-runtime");
11067
11305
  var CHANNEL_WEIGHTS = {
11068
11306
  "OOH": 50,
11069
11307
  "DOOH": 50,
@@ -11116,9 +11354,9 @@ function ChannelTag({ channel, size = "md", showLabel = true, dot = false, weigh
11116
11354
  const m = ChannelMeta(channel);
11117
11355
  const wt = channelWeightOf(channel || "");
11118
11356
  if (dot) {
11119
- return /* @__PURE__ */ (0, import_jsx_runtime83.jsx)("span", { className: ["fd-chan-dot", className].filter(Boolean).join(" "), title: m.name, style: { background: m.color }, ...rest });
11357
+ return /* @__PURE__ */ (0, import_jsx_runtime84.jsx)("span", { className: ["fd-chan-dot", className].filter(Boolean).join(" "), title: m.name, style: { background: m.color }, ...rest });
11120
11358
  }
11121
- return /* @__PURE__ */ (0, import_jsx_runtime83.jsxs)(
11359
+ return /* @__PURE__ */ (0, import_jsx_runtime84.jsxs)(
11122
11360
  "span",
11123
11361
  {
11124
11362
  className: ["fd-chan", size === "sm" ? "fd-chan-sm" : "", className].filter(Boolean).join(" "),
@@ -11126,16 +11364,16 @@ function ChannelTag({ channel, size = "md", showLabel = true, dot = false, weigh
11126
11364
  style: { "--chan": m.color },
11127
11365
  ...rest,
11128
11366
  children: [
11129
- /* @__PURE__ */ (0, import_jsx_runtime83.jsx)("i", { className: "ph ph-" + m.icon, "aria-hidden": "true" }),
11130
- showLabel ? /* @__PURE__ */ (0, import_jsx_runtime83.jsx)("span", { className: "fd-chan-label", children: m.label }) : null,
11131
- weight ? /* @__PURE__ */ (0, import_jsx_runtime83.jsx)("span", { className: "fd-chan-weight", children: wt || 0 }) : null
11367
+ /* @__PURE__ */ (0, import_jsx_runtime84.jsx)("i", { className: "ph ph-" + m.icon, "aria-hidden": "true" }),
11368
+ showLabel ? /* @__PURE__ */ (0, import_jsx_runtime84.jsx)("span", { className: "fd-chan-label", children: m.label }) : null,
11369
+ weight ? /* @__PURE__ */ (0, import_jsx_runtime84.jsx)("span", { className: "fd-chan-weight", children: wt || 0 }) : null
11132
11370
  ]
11133
11371
  }
11134
11372
  );
11135
11373
  }
11136
11374
 
11137
11375
  // src/components/planner/SaturationDistribution.tsx
11138
- var import_jsx_runtime84 = require("react/jsx-runtime");
11376
+ var import_jsx_runtime85 = require("react/jsx-runtime");
11139
11377
  var BANDS2 = [
11140
11378
  { key: "weak", label: "Weak", n: 1, range: "< 50" },
11141
11379
  { key: "adequate", label: "Adequate", n: 2, range: "50\u2013100" },
@@ -11146,24 +11384,24 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
11146
11384
  const grouped = BANDS2.map((b) => ({ ...b, items: campuses.filter((c) => c.band === b.key) }));
11147
11385
  const tallest = Math.max(1, ...grouped.map((g) => g.items.length));
11148
11386
  const floor = BANDS2.find((b) => b.key === floorBand) || BANDS2[0];
11149
- return /* @__PURE__ */ (0, import_jsx_runtime84.jsxs)("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 16 }, children: [
11150
- /* @__PURE__ */ (0, import_jsx_runtime84.jsx)("div", { style: { display: "grid", gridTemplateColumns: "repeat(4,minmax(0,1fr))", gap: 12, alignItems: "end" }, children: grouped.map((g) => {
11387
+ return /* @__PURE__ */ (0, import_jsx_runtime85.jsxs)("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 16 }, children: [
11388
+ /* @__PURE__ */ (0, import_jsx_runtime85.jsx)("div", { style: { display: "grid", gridTemplateColumns: "repeat(4,minmax(0,1fr))", gap: 12, alignItems: "end" }, children: grouped.map((g) => {
11151
11389
  const mark = "var(--csi-" + g.n + "-mark)";
11152
11390
  const active = selectedBand === g.key;
11153
- return /* @__PURE__ */ (0, import_jsx_runtime84.jsxs)(
11391
+ return /* @__PURE__ */ (0, import_jsx_runtime85.jsxs)(
11154
11392
  "button",
11155
11393
  {
11156
11394
  type: "button",
11157
11395
  onClick: onSelectBand ? () => onSelectBand(active ? null : g.key) : void 0,
11158
11396
  style: { display: "flex", flexDirection: "column", justifyContent: "flex-end", gap: 10, padding: 12, border: "1px solid " + (active ? "var(--border-strong)" : "var(--border)"), borderRadius: "var(--r-lg)", background: active ? "var(--surface-2)" : "var(--surface)", cursor: onSelectBand ? "pointer" : "default", textAlign: "left", minHeight: 190, minWidth: 0, transition: "background var(--dur-fast) var(--ease),border-color var(--dur-fast) var(--ease)" },
11159
11397
  children: [
11160
- /* @__PURE__ */ (0, import_jsx_runtime84.jsx)("span", { style: { display: "flex", flexDirection: "column-reverse", gap: 4, minHeight: tallest * 24, minWidth: 0 }, children: loading ? Array.from({ length: 3 }).map((_, i) => /* @__PURE__ */ (0, import_jsx_runtime84.jsx)("span", { className: "fd-skel", style: { height: 16, borderRadius: 4 } }, i)) : g.items.map((c) => (
11398
+ /* @__PURE__ */ (0, import_jsx_runtime85.jsx)("span", { style: { display: "flex", flexDirection: "column-reverse", gap: 4, minHeight: tallest * 24, minWidth: 0 }, children: loading ? Array.from({ length: 3 }).map((_, i) => /* @__PURE__ */ (0, import_jsx_runtime85.jsx)("span", { className: "fd-skel", style: { height: 16, borderRadius: 4 } }, i)) : g.items.map((c) => (
11161
11399
  // `overflow: hidden` + `white-space: nowrap` only clips once the span
11162
11400
  // actually HAS a bounded width to clip against (see the grid/flex
11163
11401
  // `minWidth: 0` chain above) — `textOverflow: ellipsis` then makes
11164
11402
  // that clip readable instead of a hard cut mid-letter; the full name
11165
11403
  // is still one hover away via `title`.
11166
- /* @__PURE__ */ (0, import_jsx_runtime84.jsx)(
11404
+ /* @__PURE__ */ (0, import_jsx_runtime85.jsx)(
11167
11405
  "span",
11168
11406
  {
11169
11407
  title: c.name + " \xB7 " + c.crp,
@@ -11173,13 +11411,13 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
11173
11411
  c.name
11174
11412
  )
11175
11413
  )) }),
11176
- /* @__PURE__ */ (0, import_jsx_runtime84.jsxs)("span", { className: "fd-row", style: { gap: 8, alignItems: "baseline" }, children: [
11177
- /* @__PURE__ */ (0, import_jsx_runtime84.jsx)("span", { className: "fd-num-hero", style: { fontSize: 30, color: g.items.length ? "var(--text)" : "var(--text-disabled)" }, children: loading ? "\u2013" : g.items.length }),
11178
- /* @__PURE__ */ (0, import_jsx_runtime84.jsx)("span", { className: "fd-meter", style: { gap: 2, color: mark }, "aria-hidden": "true", children: [1, 2, 3, 4].map((i) => /* @__PURE__ */ (0, import_jsx_runtime84.jsx)("span", { className: "fd-meter-seg" + (i <= g.n ? " is-on" : ""), style: { width: 4, height: 9 } }, i)) })
11414
+ /* @__PURE__ */ (0, import_jsx_runtime85.jsxs)("span", { className: "fd-row", style: { gap: 8, alignItems: "baseline" }, children: [
11415
+ /* @__PURE__ */ (0, import_jsx_runtime85.jsx)("span", { className: "fd-num-hero", style: { fontSize: 30, color: g.items.length ? "var(--text)" : "var(--text-disabled)" }, children: loading ? "\u2013" : g.items.length }),
11416
+ /* @__PURE__ */ (0, import_jsx_runtime85.jsx)("span", { className: "fd-meter", style: { gap: 2, color: mark }, "aria-hidden": "true", children: [1, 2, 3, 4].map((i) => /* @__PURE__ */ (0, import_jsx_runtime85.jsx)("span", { className: "fd-meter-seg" + (i <= g.n ? " is-on" : ""), style: { width: 4, height: 9 } }, i)) })
11179
11417
  ] }),
11180
- /* @__PURE__ */ (0, import_jsx_runtime84.jsxs)("span", { className: "fd-stack", style: { gap: 1 }, children: [
11181
- /* @__PURE__ */ (0, import_jsx_runtime84.jsx)("span", { className: "fd-label-lg", children: g.label }),
11182
- /* @__PURE__ */ (0, import_jsx_runtime84.jsxs)("span", { className: "fd-body-sm fd-muted", style: { fontSize: 11.5 }, children: [
11418
+ /* @__PURE__ */ (0, import_jsx_runtime85.jsxs)("span", { className: "fd-stack", style: { gap: 1 }, children: [
11419
+ /* @__PURE__ */ (0, import_jsx_runtime85.jsx)("span", { className: "fd-label-lg", children: g.label }),
11420
+ /* @__PURE__ */ (0, import_jsx_runtime85.jsxs)("span", { className: "fd-body-sm fd-muted", style: { fontSize: 11.5 }, children: [
11183
11421
  "CRP ",
11184
11422
  g.range
11185
11423
  ] })
@@ -11189,10 +11427,10 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
11189
11427
  g.key
11190
11428
  );
11191
11429
  }) }),
11192
- floorBand ? /* @__PURE__ */ (0, import_jsx_runtime84.jsxs)("div", { className: "fd-row", style: { gap: 10, padding: "12px 14px", borderRadius: "var(--r-md)", background: "var(--surface-2)", border: "1px solid var(--border)", flexWrap: "wrap" }, children: [
11193
- /* @__PURE__ */ (0, import_jsx_runtime84.jsx)("span", { className: "fd-meter", style: { gap: 2, color: "var(--csi-" + floor.n + "-mark)" }, "aria-hidden": "true", children: [1, 2, 3, 4].map((i) => /* @__PURE__ */ (0, import_jsx_runtime84.jsx)("span", { className: "fd-meter-seg" + (i <= floor.n ? " is-on" : ""), style: { width: 5, height: 12 } }, i)) }),
11194
- /* @__PURE__ */ (0, import_jsx_runtime84.jsxs)("span", { className: "fd-body-sm fd-secondary", style: { flex: 1, minWidth: 240 }, children: [
11195
- /* @__PURE__ */ (0, import_jsx_runtime84.jsxs)("strong", { style: { color: "var(--text)" }, children: [
11430
+ floorBand ? /* @__PURE__ */ (0, import_jsx_runtime85.jsxs)("div", { className: "fd-row", style: { gap: 10, padding: "12px 14px", borderRadius: "var(--r-md)", background: "var(--surface-2)", border: "1px solid var(--border)", flexWrap: "wrap" }, children: [
11431
+ /* @__PURE__ */ (0, import_jsx_runtime85.jsx)("span", { className: "fd-meter", style: { gap: 2, color: "var(--csi-" + floor.n + "-mark)" }, "aria-hidden": "true", children: [1, 2, 3, 4].map((i) => /* @__PURE__ */ (0, import_jsx_runtime85.jsx)("span", { className: "fd-meter-seg" + (i <= floor.n ? " is-on" : ""), style: { width: 5, height: 12 } }, i)) }),
11432
+ /* @__PURE__ */ (0, import_jsx_runtime85.jsxs)("span", { className: "fd-body-sm fd-secondary", style: { flex: 1, minWidth: 240 }, children: [
11433
+ /* @__PURE__ */ (0, import_jsx_runtime85.jsxs)("strong", { style: { color: "var(--text)" }, children: [
11196
11434
  "Plan floor ",
11197
11435
  floorScore
11198
11436
  ] }),
@@ -11203,8 +11441,8 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
11203
11441
  }
11204
11442
 
11205
11443
  // src/components/planner/MixGap.tsx
11206
- var React55 = __toESM(require("react"), 1);
11207
- var import_jsx_runtime85 = require("react/jsx-runtime");
11444
+ var React56 = __toESM(require("react"), 1);
11445
+ var import_jsx_runtime86 = require("react/jsx-runtime");
11208
11446
  var MIX_GAP_LAYOUT = {
11209
11447
  trackHeight: 30,
11210
11448
  barHeight: 20,
@@ -11218,19 +11456,19 @@ function mixGapOffset(value, max) {
11218
11456
  }
11219
11457
  function MixGap({ rows = [], loading = false, className = "" }) {
11220
11458
  const max = Math.max(1, ...rows.flatMap((r) => [r.target, r.realized]));
11221
- const [hover, setHover] = React55.useState(null);
11459
+ const [hover, setHover] = React56.useState(null);
11222
11460
  const toneOf = (gap) => gap >= -1 ? "ok" : gap >= -4 ? "warn" : "danger";
11223
11461
  const TONE = { ok: "var(--ok-solid)", warn: "var(--warn-solid)", danger: "var(--danger-solid)" };
11224
11462
  const { trackHeight, barHeight, targetWidth, labelGap } = MIX_GAP_LAYOUT;
11225
11463
  const barTop = (trackHeight - barHeight) / 2;
11226
- return /* @__PURE__ */ (0, import_jsx_runtime85.jsxs)("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 4 }, children: [
11227
- /* @__PURE__ */ (0, import_jsx_runtime85.jsxs)("div", { className: "fd-row", style: { gap: 16, justifyContent: "flex-end", paddingBottom: 6, flexWrap: "wrap" }, children: [
11228
- [["On target", TONE.ok], ["Close", TONE.warn], ["Short", TONE.danger]].map(([l, c]) => /* @__PURE__ */ (0, import_jsx_runtime85.jsxs)("span", { className: "fd-row fd-body-sm fd-muted", style: { gap: 6 }, children: [
11229
- /* @__PURE__ */ (0, import_jsx_runtime85.jsx)("span", { style: { width: 14, height: 9, borderRadius: 2, background: c } }),
11464
+ return /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 4 }, children: [
11465
+ /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("div", { className: "fd-row", style: { gap: 16, justifyContent: "flex-end", paddingBottom: 6, flexWrap: "wrap" }, children: [
11466
+ [["On target", TONE.ok], ["Close", TONE.warn], ["Short", TONE.danger]].map(([l, c]) => /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("span", { className: "fd-row fd-body-sm fd-muted", style: { gap: 6 }, children: [
11467
+ /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("span", { style: { width: 14, height: 9, borderRadius: 2, background: c } }),
11230
11468
  l
11231
11469
  ] }, l)),
11232
- /* @__PURE__ */ (0, import_jsx_runtime85.jsxs)("span", { className: "fd-row fd-body-sm fd-muted", style: { gap: 6 }, children: [
11233
- /* @__PURE__ */ (0, import_jsx_runtime85.jsx)("span", { "data-mixgap-legend-target": "", style: { width: targetWidth, height: 16, borderRadius: 1, background: MIX_GAP_TARGET_STRIPE } }),
11470
+ /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("span", { className: "fd-row fd-body-sm fd-muted", style: { gap: 6 }, children: [
11471
+ /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("span", { "data-mixgap-legend-target": "", style: { width: targetWidth, height: 16, borderRadius: 1, background: MIX_GAP_TARGET_STRIPE } }),
11234
11472
  "Target"
11235
11473
  ] })
11236
11474
  ] }),
@@ -11239,7 +11477,7 @@ function MixGap({ rows = [], loading = false, className = "" }) {
11239
11477
  const tone = toneOf(gap);
11240
11478
  const tip = "Realized " + r.realized + "% vs " + r.target + "% target" + (gap < -1 ? " \xB7 " + Math.abs(gap).toFixed(0) + " pts short" : gap > 1 ? " \xB7 " + gap.toFixed(0) + " pts over" : " \xB7 on target") + (r.note ? " \u2014 " + r.note : "");
11241
11479
  const labelLeft = r.realized > r.target ? `calc(${mixGapOffset(r.realized, max)} + ${labelGap}px)` : `calc(${mixGapOffset(r.target, max)} + ${targetWidth / 2 + labelGap}px)`;
11242
- return /* @__PURE__ */ (0, import_jsx_runtime85.jsxs)(
11480
+ return /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)(
11243
11481
  "div",
11244
11482
  {
11245
11483
  className: "fd-row",
@@ -11247,15 +11485,15 @@ function MixGap({ rows = [], loading = false, className = "" }) {
11247
11485
  onMouseEnter: () => setHover(r.channel),
11248
11486
  onMouseLeave: () => setHover(null),
11249
11487
  children: [
11250
- /* @__PURE__ */ (0, import_jsx_runtime85.jsx)("span", { style: { width: 128, flex: "none" }, children: /* @__PURE__ */ (0, import_jsx_runtime85.jsx)(ChannelTag, { channel: r.channel, size: "sm" }) }),
11251
- /* @__PURE__ */ (0, import_jsx_runtime85.jsx)("span", { style: { position: "relative", flex: 1, height: trackHeight, minWidth: 120 }, children: loading ? /* @__PURE__ */ (0, import_jsx_runtime85.jsx)("span", { className: "fd-skel", style: { position: "absolute", left: 0, right: 0, top: barTop, height: barHeight, borderRadius: 3 } }) : /* @__PURE__ */ (0, import_jsx_runtime85.jsxs)(import_jsx_runtime85.Fragment, { children: [
11252
- /* @__PURE__ */ (0, import_jsx_runtime85.jsx)("span", { "data-mixgap-bar": "", style: { position: "absolute", left: 0, top: barTop, height: barHeight, width: mixGapOffset(r.realized, max), background: TONE[tone], borderRadius: "2px 3px 3px 2px", transition: "width var(--dur-slow) var(--ease), background var(--dur-base) var(--ease)" } }),
11253
- /* @__PURE__ */ (0, import_jsx_runtime85.jsx)("span", { "data-mixgap-target": "", style: { position: "absolute", left: `calc(${mixGapOffset(r.target, max)} - ${targetWidth / 2}px)`, top: 0, width: targetWidth, height: trackHeight, background: MIX_GAP_TARGET_STRIPE, borderRadius: 1 } }),
11254
- /* @__PURE__ */ (0, import_jsx_runtime85.jsxs)("span", { "data-mixgap-label": "", className: "fd-num", style: { position: "absolute", left: labelLeft, top: "50%", transform: "translateY(-50%)", fontSize: 12, color: "var(--text-muted)", whiteSpace: "nowrap" }, children: [
11488
+ /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("span", { style: { width: 128, flex: "none" }, children: /* @__PURE__ */ (0, import_jsx_runtime86.jsx)(ChannelTag, { channel: r.channel, size: "sm" }) }),
11489
+ /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("span", { style: { position: "relative", flex: 1, height: trackHeight, minWidth: 120 }, children: loading ? /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("span", { className: "fd-skel", style: { position: "absolute", left: 0, right: 0, top: barTop, height: barHeight, borderRadius: 3 } }) : /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)(import_jsx_runtime86.Fragment, { children: [
11490
+ /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("span", { "data-mixgap-bar": "", style: { position: "absolute", left: 0, top: barTop, height: barHeight, width: mixGapOffset(r.realized, max), background: TONE[tone], borderRadius: "2px 3px 3px 2px", transition: "width var(--dur-slow) var(--ease), background var(--dur-base) var(--ease)" } }),
11491
+ /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("span", { "data-mixgap-target": "", style: { position: "absolute", left: `calc(${mixGapOffset(r.target, max)} - ${targetWidth / 2}px)`, top: 0, width: targetWidth, height: trackHeight, background: MIX_GAP_TARGET_STRIPE, borderRadius: 1 } }),
11492
+ /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("span", { "data-mixgap-label": "", className: "fd-num", style: { position: "absolute", left: labelLeft, top: "50%", transform: "translateY(-50%)", fontSize: 12, color: "var(--text-muted)", whiteSpace: "nowrap" }, children: [
11255
11493
  r.realized,
11256
11494
  "%"
11257
11495
  ] }),
11258
- hover === r.channel ? /* @__PURE__ */ (0, import_jsx_runtime85.jsx)("span", { className: "fd-tooltip", role: "tooltip", style: { position: "absolute", left: 0, right: "auto", bottom: trackHeight + 4, maxWidth: "min(340px, 100%)", whiteSpace: "normal", textAlign: "left", width: "max-content" }, children: tip }) : null
11496
+ hover === r.channel ? /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("span", { className: "fd-tooltip", role: "tooltip", style: { position: "absolute", left: 0, right: "auto", bottom: trackHeight + 4, maxWidth: "min(340px, 100%)", whiteSpace: "normal", textAlign: "left", width: "max-content" }, children: tip }) : null
11259
11497
  ] }) })
11260
11498
  ]
11261
11499
  },
@@ -11266,7 +11504,7 @@ function MixGap({ rows = [], loading = false, className = "" }) {
11266
11504
  }
11267
11505
 
11268
11506
  // src/components/planner/ChannelContribution.tsx
11269
- var import_jsx_runtime86 = require("react/jsx-runtime");
11507
+ var import_jsx_runtime87 = require("react/jsx-runtime");
11270
11508
  var money = (n) => "$" + Math.round(n).toLocaleString();
11271
11509
  function ChannelContribution({
11272
11510
  channels = [],
@@ -11282,9 +11520,9 @@ function ChannelContribution({
11282
11520
  const grand = total !== void 0 ? total : base + bonus;
11283
11521
  const pct = (v) => grand ? v / grand * 100 : 0;
11284
11522
  const spendTotal = channels.reduce((s, c) => s + Number(String(c.spend || 0).replace(/[^0-9.]/g, "")), 0);
11285
- return /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 16 }, children: [
11286
- loading ? /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("span", { className: "fd-skel", style: { height: 34, borderRadius: "var(--r-sm)" } }) : /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("div", { className: "fd-row", style: { height: 34, borderRadius: "var(--r-sm)", overflow: "hidden", gap: 2, background: "var(--surface-3)" }, children: [
11287
- channels.map((c) => /* @__PURE__ */ (0, import_jsx_runtime86.jsx)(
11523
+ return /* @__PURE__ */ (0, import_jsx_runtime87.jsxs)("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 16 }, children: [
11524
+ loading ? /* @__PURE__ */ (0, import_jsx_runtime87.jsx)("span", { className: "fd-skel", style: { height: 34, borderRadius: "var(--r-sm)" } }) : /* @__PURE__ */ (0, import_jsx_runtime87.jsxs)("div", { className: "fd-row", style: { height: 34, borderRadius: "var(--r-sm)", overflow: "hidden", gap: 2, background: "var(--surface-3)" }, children: [
11525
+ channels.map((c) => /* @__PURE__ */ (0, import_jsx_runtime87.jsx)(
11288
11526
  "span",
11289
11527
  {
11290
11528
  title: c.name + " \xB7 " + c.crp.toFixed(1) + " CRP",
@@ -11293,7 +11531,7 @@ function ChannelContribution({
11293
11531
  },
11294
11532
  c.name
11295
11533
  )),
11296
- bonus > 0 ? /* @__PURE__ */ (0, import_jsx_runtime86.jsx)(
11534
+ bonus > 0 ? /* @__PURE__ */ (0, import_jsx_runtime87.jsx)(
11297
11535
  "span",
11298
11536
  {
11299
11537
  title: "Surround-sound bonus +" + bonusPct + "%",
@@ -11302,18 +11540,18 @@ function ChannelContribution({
11302
11540
  }
11303
11541
  ) : null
11304
11542
  ] }),
11305
- showTable ? /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("table", { className: "fd-table", style: { fontSize: "var(--body-sm-size)" }, children: [
11306
- /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("tr", { children: [
11307
- /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("th", { style: { width: "34%" }, children: "Channel" }),
11308
- /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("th", { style: { width: "16%" }, children: "Weight" }),
11309
- /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("th", { className: "is-num", style: { width: "16%" }, children: "Spend" }),
11310
- /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("th", { className: "is-num", style: { width: "17%" }, children: "CRP" }),
11311
- /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("th", { className: "is-num", style: { width: "17%" }, children: "Share" })
11543
+ showTable ? /* @__PURE__ */ (0, import_jsx_runtime87.jsxs)("table", { className: "fd-table", style: { fontSize: "var(--body-sm-size)" }, children: [
11544
+ /* @__PURE__ */ (0, import_jsx_runtime87.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime87.jsxs)("tr", { children: [
11545
+ /* @__PURE__ */ (0, import_jsx_runtime87.jsx)("th", { style: { width: "34%" }, children: "Channel" }),
11546
+ /* @__PURE__ */ (0, import_jsx_runtime87.jsx)("th", { style: { width: "16%" }, children: "Weight" }),
11547
+ /* @__PURE__ */ (0, import_jsx_runtime87.jsx)("th", { className: "is-num", style: { width: "16%" }, children: "Spend" }),
11548
+ /* @__PURE__ */ (0, import_jsx_runtime87.jsx)("th", { className: "is-num", style: { width: "17%" }, children: "CRP" }),
11549
+ /* @__PURE__ */ (0, import_jsx_runtime87.jsx)("th", { className: "is-num", style: { width: "17%" }, children: "Share" })
11312
11550
  ] }) }),
11313
- /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("tbody", { children: [
11314
- channels.map((c) => /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("tr", { children: [
11315
- /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("td", { children: /* @__PURE__ */ (0, import_jsx_runtime86.jsx)(ChannelTag, { channel: c.name, size: "sm" }) }),
11316
- /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("td", { children: /* @__PURE__ */ (0, import_jsx_runtime86.jsx)(
11551
+ /* @__PURE__ */ (0, import_jsx_runtime87.jsxs)("tbody", { children: [
11552
+ channels.map((c) => /* @__PURE__ */ (0, import_jsx_runtime87.jsxs)("tr", { children: [
11553
+ /* @__PURE__ */ (0, import_jsx_runtime87.jsx)("td", { children: /* @__PURE__ */ (0, import_jsx_runtime87.jsx)(ChannelTag, { channel: c.name, size: "sm" }) }),
11554
+ /* @__PURE__ */ (0, import_jsx_runtime87.jsx)("td", { children: /* @__PURE__ */ (0, import_jsx_runtime87.jsx)(
11317
11555
  "span",
11318
11556
  {
11319
11557
  className: "fd-badge fd-badge-neutral",
@@ -11322,38 +11560,38 @@ function ChannelContribution({
11322
11560
  children: "weight " + (channelWeightOf(c.name) || 0)
11323
11561
  }
11324
11562
  ) }),
11325
- /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("td", { className: "is-num", children: c.spend }),
11326
- /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("td", { className: "is-num", children: c.crp.toFixed(1) }),
11327
- /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("td", { className: "is-num", children: [
11563
+ /* @__PURE__ */ (0, import_jsx_runtime87.jsx)("td", { className: "is-num", children: c.spend }),
11564
+ /* @__PURE__ */ (0, import_jsx_runtime87.jsx)("td", { className: "is-num", children: c.crp.toFixed(1) }),
11565
+ /* @__PURE__ */ (0, import_jsx_runtime87.jsxs)("td", { className: "is-num", children: [
11328
11566
  pct(c.crp).toFixed(0),
11329
11567
  "%"
11330
11568
  ] })
11331
11569
  ] }, c.name)),
11332
- bonus > 0 ? /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("tr", { children: [
11333
- /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("td", { children: /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("span", { className: "fd-row", style: { gap: 9, fontWeight: 600 }, children: [
11334
- /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("span", { style: { width: 9, height: 9, borderRadius: 2, background: "repeating-linear-gradient(135deg,var(--csi-3-mark) 0 3px,var(--csi-2-mark) 3px 6px)", flex: "none" } }),
11570
+ bonus > 0 ? /* @__PURE__ */ (0, import_jsx_runtime87.jsxs)("tr", { children: [
11571
+ /* @__PURE__ */ (0, import_jsx_runtime87.jsx)("td", { children: /* @__PURE__ */ (0, import_jsx_runtime87.jsxs)("span", { className: "fd-row", style: { gap: 9, fontWeight: 600 }, children: [
11572
+ /* @__PURE__ */ (0, import_jsx_runtime87.jsx)("span", { style: { width: 9, height: 9, borderRadius: 2, background: "repeating-linear-gradient(135deg,var(--csi-3-mark) 0 3px,var(--csi-2-mark) 3px 6px)", flex: "none" } }),
11335
11573
  "Surround-sound bonus"
11336
11574
  ] }) }),
11337
- /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("td", { children: /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("span", { className: "fd-badge fd-badge-success", style: { height: 20, fontSize: 11 }, children: [
11575
+ /* @__PURE__ */ (0, import_jsx_runtime87.jsx)("td", { children: /* @__PURE__ */ (0, import_jsx_runtime87.jsxs)("span", { className: "fd-badge fd-badge-success", style: { height: 20, fontSize: 11 }, children: [
11338
11576
  "+",
11339
11577
  bonusPct,
11340
11578
  "% of +",
11341
11579
  bonusMax,
11342
11580
  "%"
11343
11581
  ] }) }),
11344
- /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("td", { className: "is-num fd-muted", children: "\u2014" }),
11345
- /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("td", { className: "is-num", children: bonus.toFixed(1) }),
11346
- /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("td", { className: "is-num", children: [
11582
+ /* @__PURE__ */ (0, import_jsx_runtime87.jsx)("td", { className: "is-num fd-muted", children: "\u2014" }),
11583
+ /* @__PURE__ */ (0, import_jsx_runtime87.jsx)("td", { className: "is-num", children: bonus.toFixed(1) }),
11584
+ /* @__PURE__ */ (0, import_jsx_runtime87.jsxs)("td", { className: "is-num", children: [
11347
11585
  pct(bonus).toFixed(0),
11348
11586
  "%"
11349
11587
  ] })
11350
11588
  ] }) : null,
11351
- /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("tr", { style: { background: "var(--surface-2)" }, children: [
11352
- /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("td", { style: { fontWeight: 700 }, children: "Campus total" }),
11353
- /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("td", {}),
11354
- /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("td", { className: "is-num", style: { fontWeight: 700 }, children: money(spendTotal) }),
11355
- /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("td", { className: "is-num", style: { fontWeight: 700 }, children: grand.toFixed(1) }),
11356
- /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("td", { className: "is-num", style: { fontWeight: 700 }, children: "100%" })
11589
+ /* @__PURE__ */ (0, import_jsx_runtime87.jsxs)("tr", { style: { background: "var(--surface-2)" }, children: [
11590
+ /* @__PURE__ */ (0, import_jsx_runtime87.jsx)("td", { style: { fontWeight: 700 }, children: "Campus total" }),
11591
+ /* @__PURE__ */ (0, import_jsx_runtime87.jsx)("td", {}),
11592
+ /* @__PURE__ */ (0, import_jsx_runtime87.jsx)("td", { className: "is-num", style: { fontWeight: 700 }, children: money(spendTotal) }),
11593
+ /* @__PURE__ */ (0, import_jsx_runtime87.jsx)("td", { className: "is-num", style: { fontWeight: 700 }, children: grand.toFixed(1) }),
11594
+ /* @__PURE__ */ (0, import_jsx_runtime87.jsx)("td", { className: "is-num", style: { fontWeight: 700 }, children: "100%" })
11357
11595
  ] })
11358
11596
  ] })
11359
11597
  ] }) : null
@@ -11361,8 +11599,8 @@ function ChannelContribution({
11361
11599
  }
11362
11600
 
11363
11601
  // src/components/planner/BudgetReallocator.tsx
11364
- var React56 = __toESM(require("react"), 1);
11365
- var import_jsx_runtime87 = require("react/jsx-runtime");
11602
+ var React57 = __toESM(require("react"), 1);
11603
+ var import_jsx_runtime88 = require("react/jsx-runtime");
11366
11604
  var bandFor = (crp) => crp >= 200 ? "dominant" : crp >= 100 ? "strong" : crp >= 50 ? "adequate" : "weak";
11367
11605
  function BudgetReallocator({
11368
11606
  campus,
@@ -11377,8 +11615,8 @@ function BudgetReallocator({
11377
11615
  onCancel,
11378
11616
  className = ""
11379
11617
  }) {
11380
- const [draft, setDraft] = React56.useState(spend);
11381
- React56.useEffect(() => setDraft(spend), [spend]);
11618
+ const [draft, setDraft] = React57.useState(spend);
11619
+ React57.useEffect(() => setDraft(spend), [spend]);
11382
11620
  const dirty = draft !== spend;
11383
11621
  const nextCrp = scoreFor ? scoreFor(draft) : crp;
11384
11622
  const nextBand = bandFor(nextCrp);
@@ -11393,10 +11631,10 @@ function BudgetReallocator({
11393
11631
  setDraft(spend);
11394
11632
  if (onCancel) onCancel();
11395
11633
  };
11396
- const trackRef = React56.useRef(null);
11397
- const chipRef = React56.useRef(null);
11398
- const [chipLeft, setChipLeft] = React56.useState(null);
11399
- React56.useLayoutEffect(() => {
11634
+ const trackRef = React57.useRef(null);
11635
+ const chipRef = React57.useRef(null);
11636
+ const [chipLeft, setChipLeft] = React57.useState(null);
11637
+ React57.useLayoutEffect(() => {
11400
11638
  const track = trackRef.current;
11401
11639
  if (!dirty || !track) {
11402
11640
  setChipLeft(null);
@@ -11417,23 +11655,23 @@ function BudgetReallocator({
11417
11655
  ro.observe(track);
11418
11656
  return () => ro.disconnect();
11419
11657
  }, [dirty, pct]);
11420
- return /* @__PURE__ */ (0, import_jsx_runtime87.jsxs)(
11658
+ return /* @__PURE__ */ (0, import_jsx_runtime88.jsxs)(
11421
11659
  "div",
11422
11660
  {
11423
11661
  className: ["fd-stack", className].filter(Boolean).join(" "),
11424
11662
  style: { gap: 14, padding: 18, border: "1px solid " + (dirty ? "var(--border-brand)" : "var(--border)"), borderRadius: "var(--r-lg)", background: dirty ? "var(--surface-brand)" : "var(--surface)", color: "var(--text)", transition: "background var(--dur-base) var(--ease),border-color var(--dur-base) var(--ease)" },
11425
11663
  children: [
11426
- /* @__PURE__ */ (0, import_jsx_runtime87.jsxs)("div", { className: "fd-row", style: { gap: 12, flexWrap: "wrap" }, children: [
11427
- /* @__PURE__ */ (0, import_jsx_runtime87.jsx)("span", { className: "fd-h4", style: { flex: 1, minWidth: 140 }, children: campus }),
11428
- /* @__PURE__ */ (0, import_jsx_runtime87.jsx)(CsiBadge, { band: nowBand, crp, size: "medium" }),
11429
- dirty ? /* @__PURE__ */ (0, import_jsx_runtime87.jsxs)(import_jsx_runtime87.Fragment, { children: [
11430
- /* @__PURE__ */ (0, import_jsx_runtime87.jsx)("i", { className: "ph ph-arrow-right fd-muted", "aria-hidden": "true" }),
11431
- /* @__PURE__ */ (0, import_jsx_runtime87.jsx)(CsiBadge, { band: nextBand, crp: nextCrp, size: "medium", preview: true })
11664
+ /* @__PURE__ */ (0, import_jsx_runtime88.jsxs)("div", { className: "fd-row", style: { gap: 12, flexWrap: "wrap" }, children: [
11665
+ /* @__PURE__ */ (0, import_jsx_runtime88.jsx)("span", { className: "fd-h4", style: { flex: 1, minWidth: 140 }, children: campus }),
11666
+ /* @__PURE__ */ (0, import_jsx_runtime88.jsx)(CsiBadge, { band: nowBand, crp, size: "medium" }),
11667
+ dirty ? /* @__PURE__ */ (0, import_jsx_runtime88.jsxs)(import_jsx_runtime88.Fragment, { children: [
11668
+ /* @__PURE__ */ (0, import_jsx_runtime88.jsx)("i", { className: "ph ph-arrow-right fd-muted", "aria-hidden": "true" }),
11669
+ /* @__PURE__ */ (0, import_jsx_runtime88.jsx)(CsiBadge, { band: nextBand, crp: nextCrp, size: "medium", preview: true })
11432
11670
  ] }) : null
11433
11671
  ] }),
11434
- /* @__PURE__ */ (0, import_jsx_runtime87.jsxs)("div", { className: "fd-slider", ref: trackRef, children: [
11435
- /* @__PURE__ */ (0, import_jsx_runtime87.jsx)("span", { className: "fd-slider-fill", style: { width: pct + "%" } }),
11436
- dirty ? /* @__PURE__ */ (0, import_jsx_runtime87.jsx)(
11672
+ /* @__PURE__ */ (0, import_jsx_runtime88.jsxs)("div", { className: "fd-slider", ref: trackRef, children: [
11673
+ /* @__PURE__ */ (0, import_jsx_runtime88.jsx)("span", { className: "fd-slider-fill", style: { width: pct + "%" } }),
11674
+ dirty ? /* @__PURE__ */ (0, import_jsx_runtime88.jsx)(
11437
11675
  "span",
11438
11676
  {
11439
11677
  ref: chipRef,
@@ -11445,7 +11683,7 @@ function BudgetReallocator({
11445
11683
  children: (delta < 0 ? "\u2212$" : "+$") + Math.abs(delta).toLocaleString()
11446
11684
  }
11447
11685
  ) : null,
11448
- /* @__PURE__ */ (0, import_jsx_runtime87.jsx)(
11686
+ /* @__PURE__ */ (0, import_jsx_runtime88.jsx)(
11449
11687
  "input",
11450
11688
  {
11451
11689
  type: "range",
@@ -11461,13 +11699,13 @@ function BudgetReallocator({
11461
11699
  }
11462
11700
  )
11463
11701
  ] }),
11464
- /* @__PURE__ */ (0, import_jsx_runtime87.jsxs)("div", { className: "fd-row", style: { gap: 12, flexWrap: "wrap" }, children: [
11465
- /* @__PURE__ */ (0, import_jsx_runtime87.jsxs)("span", { className: "fd-stack", style: { gap: 2, flex: 1, minWidth: 150 }, children: [
11466
- /* @__PURE__ */ (0, import_jsx_runtime87.jsx)("span", { className: "fd-num", style: { fontSize: 19, fontWeight: 700 }, children: "$" + draft.toLocaleString() }),
11467
- /* @__PURE__ */ (0, import_jsx_runtime87.jsx)("span", { className: "fd-body-sm fd-muted", children: "Arrow keys step $100, shift+arrow $1,000. Escape reverts." })
11702
+ /* @__PURE__ */ (0, import_jsx_runtime88.jsxs)("div", { className: "fd-row", style: { gap: 12, flexWrap: "wrap" }, children: [
11703
+ /* @__PURE__ */ (0, import_jsx_runtime88.jsxs)("span", { className: "fd-stack", style: { gap: 2, flex: 1, minWidth: 150 }, children: [
11704
+ /* @__PURE__ */ (0, import_jsx_runtime88.jsx)("span", { className: "fd-num", style: { fontSize: 19, fontWeight: 700 }, children: "$" + draft.toLocaleString() }),
11705
+ /* @__PURE__ */ (0, import_jsx_runtime88.jsx)("span", { className: "fd-body-sm fd-muted", children: "Arrow keys step $100, shift+arrow $1,000. Escape reverts." })
11468
11706
  ] }),
11469
- /* @__PURE__ */ (0, import_jsx_runtime87.jsx)("button", { type: "button", className: "fd-btn fd-btn-ghost", disabled: !dirty, onClick: revert, children: "Cancel" }),
11470
- /* @__PURE__ */ (0, import_jsx_runtime87.jsx)(
11707
+ /* @__PURE__ */ (0, import_jsx_runtime88.jsx)("button", { type: "button", className: "fd-btn fd-btn-ghost", disabled: !dirty, onClick: revert, children: "Cancel" }),
11708
+ /* @__PURE__ */ (0, import_jsx_runtime88.jsx)(
11471
11709
  "button",
11472
11710
  {
11473
11711
  type: "button",
@@ -11486,7 +11724,7 @@ function BudgetReallocator({
11486
11724
  }
11487
11725
 
11488
11726
  // src/components/planner/SurroundSound.tsx
11489
- var import_jsx_runtime88 = require("react/jsx-runtime");
11727
+ var import_jsx_runtime89 = require("react/jsx-runtime");
11490
11728
  var CATEGORIES = [
11491
11729
  { key: "ooh", label: "OOH", icon: "flag-banner", color: "var(--ch-ooh)" },
11492
11730
  { key: "transit", label: "Transit", icon: "bus", color: "var(--ch-transit)" },
@@ -11498,26 +11736,26 @@ var CATEGORIES = [
11498
11736
  function SurroundSound({ present = [], bonusPct = 0, bonusMax = 40, missedCost, className = "" }) {
11499
11737
  const earned = Math.max(0, Math.min(1, bonusPct / bonusMax));
11500
11738
  const single = present.length <= 2;
11501
- return /* @__PURE__ */ (0, import_jsx_runtime88.jsxs)("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 14 }, children: [
11502
- /* @__PURE__ */ (0, import_jsx_runtime88.jsx)("div", { className: "fd-row", style: { gap: 8, flexWrap: "wrap" }, children: CATEGORIES.map((c) => {
11739
+ return /* @__PURE__ */ (0, import_jsx_runtime89.jsxs)("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 14 }, children: [
11740
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsx)("div", { className: "fd-row", style: { gap: 8, flexWrap: "wrap" }, children: CATEGORIES.map((c) => {
11503
11741
  const on = present.includes(c.key);
11504
- return /* @__PURE__ */ (0, import_jsx_runtime88.jsxs)(
11742
+ return /* @__PURE__ */ (0, import_jsx_runtime89.jsxs)(
11505
11743
  "span",
11506
11744
  {
11507
11745
  title: c.label + (on ? " \u2014 present" : " \u2014 not bought"),
11508
11746
  style: { display: "flex", flexDirection: "column", alignItems: "center", gap: 5, width: 62, padding: "10px 0", borderRadius: "var(--r-md)", border: "1px solid " + (on ? "var(--csi-2-edge)" : "var(--border)"), background: on ? "var(--csi-2-fill)" : "var(--surface-2)", color: on ? "var(--csi-2-text)" : "var(--text-disabled)" },
11509
11747
  children: [
11510
- /* @__PURE__ */ (0, import_jsx_runtime88.jsx)("i", { className: "ph ph-" + c.icon, style: { fontSize: 19, color: on ? c.color : "var(--text-muted)" }, "aria-hidden": "true" }),
11511
- /* @__PURE__ */ (0, import_jsx_runtime88.jsx)("span", { style: { fontSize: 10.5, fontWeight: 700 }, children: c.label })
11748
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsx)("i", { className: "ph ph-" + c.icon, style: { fontSize: 19, color: on ? c.color : "var(--text-muted)" }, "aria-hidden": "true" }),
11749
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsx)("span", { style: { fontSize: 10.5, fontWeight: 700 }, children: c.label })
11512
11750
  ]
11513
11751
  },
11514
11752
  c.key
11515
11753
  );
11516
11754
  }) }),
11517
- /* @__PURE__ */ (0, import_jsx_runtime88.jsxs)("div", { className: "fd-stack", style: { gap: 8 }, children: [
11518
- /* @__PURE__ */ (0, import_jsx_runtime88.jsxs)("div", { className: "fd-row", style: { justifyContent: "space-between", gap: 12 }, children: [
11519
- /* @__PURE__ */ (0, import_jsx_runtime88.jsx)("span", { className: "fd-label-lg", children: "Surround-sound bonus earned" }),
11520
- /* @__PURE__ */ (0, import_jsx_runtime88.jsxs)("span", { className: "fd-num", style: { color: single ? "var(--warn-text)" : "var(--csi-3-mark)", fontWeight: 700 }, children: [
11755
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsxs)("div", { className: "fd-stack", style: { gap: 8 }, children: [
11756
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsxs)("div", { className: "fd-row", style: { justifyContent: "space-between", gap: 12 }, children: [
11757
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsx)("span", { className: "fd-label-lg", children: "Surround-sound bonus earned" }),
11758
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsxs)("span", { className: "fd-num", style: { color: single ? "var(--warn-text)" : "var(--csi-3-mark)", fontWeight: 700 }, children: [
11521
11759
  "+",
11522
11760
  bonusPct,
11523
11761
  "% of +",
@@ -11525,8 +11763,8 @@ function SurroundSound({ present = [], bonusPct = 0, bonusMax = 40, missedCost,
11525
11763
  "%"
11526
11764
  ] })
11527
11765
  ] }),
11528
- /* @__PURE__ */ (0, import_jsx_runtime88.jsx)("div", { style: { height: 8, borderRadius: "var(--r-xs)", background: "var(--surface-3)", overflow: "hidden" }, children: /* @__PURE__ */ (0, import_jsx_runtime88.jsx)("div", { style: { height: "100%", width: earned * 100 + "%", background: "var(--csi-3-mark)", borderRadius: "inherit", transition: "width var(--dur-slow) var(--ease)" } }) }),
11529
- /* @__PURE__ */ (0, import_jsx_runtime88.jsxs)("span", { className: "fd-body-sm fd-secondary", style: { textWrap: "pretty" }, children: [
11766
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsx)("div", { style: { height: 8, borderRadius: "var(--r-xs)", background: "var(--surface-3)", overflow: "hidden" }, children: /* @__PURE__ */ (0, import_jsx_runtime89.jsx)("div", { style: { height: "100%", width: earned * 100 + "%", background: "var(--csi-3-mark)", borderRadius: "inherit", transition: "width var(--dur-slow) var(--ease)" } }) }),
11767
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsxs)("span", { className: "fd-body-sm fd-secondary", style: { textWrap: "pretty" }, children: [
11530
11768
  present.length,
11531
11769
  " of 6 channel categories present.",
11532
11770
  " ",
@@ -11538,7 +11776,7 @@ function SurroundSound({ present = [], bonusPct = 0, bonusMax = 40, missedCost,
11538
11776
  }
11539
11777
 
11540
11778
  // src/components/planner/Importance.tsx
11541
- var import_jsx_runtime89 = require("react/jsx-runtime");
11779
+ var import_jsx_runtime90 = require("react/jsx-runtime");
11542
11780
  var IMPORTANCE_LEVELS = [
11543
11781
  { id: "nudge", rank: 1, label: "Nudge", icon: "feather", description: "Breaks a tie, nothing more." },
11544
11782
  { id: "lean", rank: 2, label: "Lean", icon: "arrow-bend-up-right", description: "A mild preference between otherwise equal options." },
@@ -11568,7 +11806,7 @@ function importanceTokens(id) {
11568
11806
  function ImportanceTag({ level, showLabel = true, size = "sm", className = "", disabled = false }) {
11569
11807
  const lvl = importanceLevel(level);
11570
11808
  const t = importanceTokens(level);
11571
- return /* @__PURE__ */ (0, import_jsx_runtime89.jsxs)(
11809
+ return /* @__PURE__ */ (0, import_jsx_runtime90.jsxs)(
11572
11810
  "span",
11573
11811
  {
11574
11812
  className: ["fd-imp-tag", size === "md" ? "is-md" : "", disabled ? "is-disabled" : "", className].filter(Boolean).join(" "),
@@ -11576,16 +11814,16 @@ function ImportanceTag({ level, showLabel = true, size = "sm", className = "", d
11576
11814
  title: lvl.label + " \u2014 " + lvl.description,
11577
11815
  "aria-disabled": disabled ? "true" : void 0,
11578
11816
  children: [
11579
- /* @__PURE__ */ (0, import_jsx_runtime89.jsx)("i", { className: "ph ph-" + lvl.icon, "aria-hidden": "true" }),
11580
- showLabel ? lvl.label : /* @__PURE__ */ (0, import_jsx_runtime89.jsx)("span", { className: "fd-sr", children: lvl.label })
11817
+ /* @__PURE__ */ (0, import_jsx_runtime90.jsx)("i", { className: "ph ph-" + lvl.icon, "aria-hidden": "true" }),
11818
+ showLabel ? lvl.label : /* @__PURE__ */ (0, import_jsx_runtime90.jsx)("span", { className: "fd-sr", children: lvl.label })
11581
11819
  ]
11582
11820
  }
11583
11821
  );
11584
11822
  }
11585
11823
 
11586
11824
  // src/components/planner/PreferenceMeter.tsx
11587
- var React57 = __toESM(require("react"), 1);
11588
- var import_jsx_runtime90 = require("react/jsx-runtime");
11825
+ var React58 = __toESM(require("react"), 1);
11826
+ var import_jsx_runtime91 = require("react/jsx-runtime");
11589
11827
  function preferenceScore(criteria) {
11590
11828
  const earned = criteria.reduce((n, c) => n + (Number(c.earned) || 0), 0);
11591
11829
  const weight = criteria.reduce((n, c) => n + (Number(c.weight) || 0), 0);
@@ -11614,8 +11852,8 @@ function PreferenceMeter({
11614
11852
  className = ""
11615
11853
  }) {
11616
11854
  const value = score == null ? preferenceScore(criteria) : score;
11617
- const segments = React57.useMemo(() => preferenceSegments(criteria), [criteria]);
11618
- return /* @__PURE__ */ (0, import_jsx_runtime90.jsx)(
11855
+ const segments = React58.useMemo(() => preferenceSegments(criteria), [criteria]);
11856
+ return /* @__PURE__ */ (0, import_jsx_runtime91.jsx)(
11619
11857
  ScoreMeter,
11620
11858
  {
11621
11859
  score: value,
@@ -11627,22 +11865,22 @@ function PreferenceMeter({
11627
11865
  placement,
11628
11866
  className,
11629
11867
  breakdownLabel: breakdownTitle,
11630
- breakdown: /* @__PURE__ */ (0, import_jsx_runtime90.jsxs)("div", { className: "fd-prefbreak", children: [
11631
- /* @__PURE__ */ (0, import_jsx_runtime90.jsxs)("div", { className: "fd-prefbreak-head", children: [
11632
- /* @__PURE__ */ (0, import_jsx_runtime90.jsx)("span", { className: "fd-label-lg", children: breakdownTitle }),
11633
- /* @__PURE__ */ (0, import_jsx_runtime90.jsx)("span", { className: "fd-prefbreak-score fd-tabular", children: Math.round(value) })
11868
+ breakdown: /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)("div", { className: "fd-prefbreak", children: [
11869
+ /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)("div", { className: "fd-prefbreak-head", children: [
11870
+ /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("span", { className: "fd-label-lg", children: breakdownTitle }),
11871
+ /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("span", { className: "fd-prefbreak-score fd-tabular", children: Math.round(value) })
11634
11872
  ] }),
11635
- /* @__PURE__ */ (0, import_jsx_runtime90.jsx)("ul", { className: "fd-prefbreak-list", children: criteria.map((c) => {
11873
+ /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("ul", { className: "fd-prefbreak-list", children: criteria.map((c) => {
11636
11874
  const pct = c.weight > 0 ? Math.round((Number(c.earned) || 0) / c.weight * 100) : 0;
11637
- return /* @__PURE__ */ (0, import_jsx_runtime90.jsxs)("li", { className: pct === 0 ? "fd-prefbreak-item is-unmet" : "fd-prefbreak-item", children: [
11638
- /* @__PURE__ */ (0, import_jsx_runtime90.jsx)(ImportanceTag, { level: c.importance }),
11639
- /* @__PURE__ */ (0, import_jsx_runtime90.jsxs)("span", { className: "fd-prefbreak-text", children: [
11640
- /* @__PURE__ */ (0, import_jsx_runtime90.jsx)("span", { className: "fd-prefbreak-label", children: c.label }),
11641
- c.note ? /* @__PURE__ */ (0, import_jsx_runtime90.jsx)("span", { className: "fd-prefbreak-note", children: c.note }) : null
11875
+ return /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)("li", { className: pct === 0 ? "fd-prefbreak-item is-unmet" : "fd-prefbreak-item", children: [
11876
+ /* @__PURE__ */ (0, import_jsx_runtime91.jsx)(ImportanceTag, { level: c.importance }),
11877
+ /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)("span", { className: "fd-prefbreak-text", children: [
11878
+ /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("span", { className: "fd-prefbreak-label", children: c.label }),
11879
+ c.note ? /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("span", { className: "fd-prefbreak-note", children: c.note }) : null
11642
11880
  ] }),
11643
- /* @__PURE__ */ (0, import_jsx_runtime90.jsxs)("span", { className: "fd-prefbreak-val fd-tabular", children: [
11881
+ /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)("span", { className: "fd-prefbreak-val fd-tabular", children: [
11644
11882
  Math.round(Number(c.earned) || 0),
11645
- /* @__PURE__ */ (0, import_jsx_runtime90.jsx)("span", { className: "fd-prefbreak-sep", children: "/" }),
11883
+ /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("span", { className: "fd-prefbreak-sep", children: "/" }),
11646
11884
  Math.round(c.weight)
11647
11885
  ] })
11648
11886
  ] }, c.id);
@@ -11653,10 +11891,10 @@ function PreferenceMeter({
11653
11891
  }
11654
11892
 
11655
11893
  // src/components/chat/AgentChatPanel.tsx
11656
- var React63 = __toESM(require("react"), 1);
11894
+ var React64 = __toESM(require("react"), 1);
11657
11895
 
11658
11896
  // src/components/chat/chatEngine.ts
11659
- var React58 = __toESM(require("react"), 1);
11897
+ var React59 = __toESM(require("react"), 1);
11660
11898
  var CHAT_UNAVAILABLE = "chat_unavailable";
11661
11899
  var JOB_PENDING = ["queued", "running"];
11662
11900
  var JOB_SUCCESS = ["completed", "recovered"];
@@ -11710,22 +11948,22 @@ function useChatEngine(opts) {
11710
11948
  onClear,
11711
11949
  onFeedback
11712
11950
  } = opts || {};
11713
- const [status, setStatus] = React58.useState("idle");
11714
- const [threadId, setThreadId] = React58.useState(null);
11715
- const [messages, setMessages] = React58.useState([]);
11716
- const [queue, setQueue] = React58.useState([]);
11717
- const [fatal, setFatal] = React58.useState(null);
11718
- const [busy, setBusy] = React58.useState(false);
11719
- const [turnStartedAt, setTurnStartedAt] = React58.useState(null);
11720
- const listRef = React58.useRef([]);
11721
- const queueRef = React58.useRef([]);
11722
- const busyRef = React58.useRef(false);
11723
- const stoppedRef = React58.useRef(false);
11724
- const abortRef = React58.useRef(null);
11725
- const serverCount = React58.useRef(0);
11726
- const threadRef = React58.useRef(null);
11727
- const mounted = React58.useRef(true);
11728
- React58.useEffect(() => {
11951
+ const [status, setStatus] = React59.useState("idle");
11952
+ const [threadId, setThreadId] = React59.useState(null);
11953
+ const [messages, setMessages] = React59.useState([]);
11954
+ const [queue, setQueue] = React59.useState([]);
11955
+ const [fatal, setFatal] = React59.useState(null);
11956
+ const [busy, setBusy] = React59.useState(false);
11957
+ const [turnStartedAt, setTurnStartedAt] = React59.useState(null);
11958
+ const listRef = React59.useRef([]);
11959
+ const queueRef = React59.useRef([]);
11960
+ const busyRef = React59.useRef(false);
11961
+ const stoppedRef = React59.useRef(false);
11962
+ const abortRef = React59.useRef(null);
11963
+ const serverCount = React59.useRef(0);
11964
+ const threadRef = React59.useRef(null);
11965
+ const mounted = React59.useRef(true);
11966
+ React59.useEffect(() => {
11729
11967
  mounted.current = true;
11730
11968
  return () => {
11731
11969
  mounted.current = false;
@@ -11747,14 +11985,14 @@ function useChatEngine(opts) {
11747
11985
  }
11748
11986
  return false;
11749
11987
  };
11750
- const loadThread = React58.useCallback(async (id) => {
11988
+ const loadThread = React59.useCallback(async (id) => {
11751
11989
  const data = await apiAdapter.getThread(id);
11752
11990
  const list = [...data && data.messages || []];
11753
11991
  serverCount.current = list.length;
11754
11992
  commit(list);
11755
11993
  return list;
11756
11994
  }, [apiAdapter]);
11757
- React58.useEffect(() => {
11995
+ React59.useEffect(() => {
11758
11996
  if (!apiAdapter) {
11759
11997
  setStatus("idle");
11760
11998
  setFatal(null);
@@ -11967,7 +12205,7 @@ function useChatEngine(opts) {
11967
12205
  await dispatchTurn(turn);
11968
12206
  }
11969
12207
  }
11970
- const send = React58.useCallback((text, attachments) => {
12208
+ const send = React59.useCallback((text, attachments) => {
11971
12209
  const body = (text || "").trim();
11972
12210
  if (!body && !(attachments && attachments.length)) return;
11973
12211
  if (status === "disconnected") return;
@@ -11977,7 +12215,7 @@ function useChatEngine(opts) {
11977
12215
  stoppedRef.current = false;
11978
12216
  drain();
11979
12217
  }, [status]);
11980
- const stop = React58.useCallback(() => {
12218
+ const stop = React59.useCallback(() => {
11981
12219
  stoppedRef.current = true;
11982
12220
  const ac = abortRef.current;
11983
12221
  if (ac) {
@@ -11996,11 +12234,11 @@ function useChatEngine(opts) {
11996
12234
  store.del(STORAGE_PREFIX + threadRef.current);
11997
12235
  }
11998
12236
  }, [apiAdapter]);
11999
- const removeQueued = React58.useCallback((id) => {
12237
+ const removeQueued = React59.useCallback((id) => {
12000
12238
  queueRef.current = queueRef.current.filter((t) => t.id !== id);
12001
12239
  setQueue(queueRef.current.slice());
12002
12240
  }, []);
12003
- const retry = React58.useCallback(() => {
12241
+ const retry = React59.useCallback(() => {
12004
12242
  const list = listRef.current;
12005
12243
  let at = -1;
12006
12244
  for (let i = list.length - 1; i >= 0; i--) if (list[i].role === "user") {
@@ -12016,19 +12254,19 @@ function useChatEngine(opts) {
12016
12254
  setQueue(queueRef.current.slice());
12017
12255
  drain();
12018
12256
  }, []);
12019
- const clear = React58.useCallback(() => {
12257
+ const clear = React59.useCallback(() => {
12020
12258
  commit([]);
12021
12259
  serverCount.current = 0;
12022
12260
  queueRef.current = [];
12023
12261
  setQueue([]);
12024
12262
  onClear && onClear();
12025
12263
  }, [onClear]);
12026
- const setFeedback = React58.useCallback((id, value) => {
12264
+ const setFeedback = React59.useCallback((id, value) => {
12027
12265
  patch(id, (m) => ({ feedback: m.feedback === value ? null : value }));
12028
12266
  const msg = listRef.current.find((m) => m.id === id);
12029
12267
  onFeedback && onFeedback({ message: msg, feedback: msg ? msg.feedback : value });
12030
12268
  }, [onFeedback]);
12031
- const reload = React58.useCallback(async () => {
12269
+ const reload = React59.useCallback(async () => {
12032
12270
  if (!threadRef.current) return;
12033
12271
  setStatus("loading");
12034
12272
  try {
@@ -12066,11 +12304,11 @@ var ChatKit = {
12066
12304
  };
12067
12305
 
12068
12306
  // src/components/chat/ChatTranscript.tsx
12069
- var React60 = __toESM(require("react"), 1);
12307
+ var React61 = __toESM(require("react"), 1);
12070
12308
 
12071
12309
  // src/components/chat/ChatTurn.tsx
12072
- var React59 = __toESM(require("react"), 1);
12073
- var import_jsx_runtime91 = require("react/jsx-runtime");
12310
+ var React60 = __toESM(require("react"), 1);
12311
+ var import_jsx_runtime92 = require("react/jsx-runtime");
12074
12312
  function JsonView({ value }) {
12075
12313
  let text;
12076
12314
  try {
@@ -12078,67 +12316,67 @@ function JsonView({ value }) {
12078
12316
  } catch (e) {
12079
12317
  text = String(value);
12080
12318
  }
12081
- return /* @__PURE__ */ (0, import_jsx_runtime91.jsx)(CodeBlock, { code: text, language: "json", collapseAfter: 18 });
12319
+ return /* @__PURE__ */ (0, import_jsx_runtime92.jsx)(CodeBlock, { code: text, language: "json", collapseAfter: 18 });
12082
12320
  }
12083
12321
  function PacketCard({ packet, schema, render, onApply, applied }) {
12084
12322
  if (!packet) return null;
12085
12323
  const s = schema || {};
12086
12324
  const invalid = packet.valid === false;
12087
12325
  const title = s.heading || packet.type;
12088
- return /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)("section", { className: "fdc-packet" + (invalid ? " is-invalid" : ""), "aria-label": title, children: [
12089
- /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)("header", { className: "fdc-packet-head", children: [
12090
- /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("i", { className: "ph ph-" + (s.icon || "package"), "aria-hidden": "true" }),
12091
- /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("span", { className: "fdc-packet-title", title: truncationTitle(title), children: title }),
12092
- packet.repaired ? /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("span", { className: "fdc-packet-badge", children: "Repaired" }) : null,
12093
- invalid ? /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("span", { className: "fdc-packet-badge is-danger", children: "Invalid" }) : null
12326
+ return /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("section", { className: "fdc-packet" + (invalid ? " is-invalid" : ""), "aria-label": title, children: [
12327
+ /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("header", { className: "fdc-packet-head", children: [
12328
+ /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("i", { className: "ph ph-" + (s.icon || "package"), "aria-hidden": "true" }),
12329
+ /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("span", { className: "fdc-packet-title", title: truncationTitle(title), children: title }),
12330
+ packet.repaired ? /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("span", { className: "fdc-packet-badge", children: "Repaired" }) : null,
12331
+ invalid ? /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("span", { className: "fdc-packet-badge is-danger", children: "Invalid" }) : null
12094
12332
  ] }),
12095
- invalid ? /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)("div", { className: "fdc-packet-alert", role: "alert", children: [
12096
- /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
12097
- /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("span", { children: packet.error || "This result failed validation and can\u2019t be applied." })
12098
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("div", { className: "fdc-packet-body", children: render ? render(packet) : /* @__PURE__ */ (0, import_jsx_runtime91.jsx)(JsonView, { value: packet.payload }) }),
12099
- !invalid && onApply ? /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)("footer", { className: "fdc-packet-foot", children: [
12100
- packet.repaired ? /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("span", { className: "fdc-packet-note", children: "Corrected by the backend after a first attempt." }) : /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("span", {}),
12101
- /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)("button", { type: "button", className: "fd-btn fd-btn-primary fd-btn-sm", disabled: applied, onClick: () => onApply(packet), children: [
12102
- /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("i", { className: "ph ph-" + (applied ? "check" : "arrow-square-in"), "aria-hidden": "true" }),
12333
+ invalid ? /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("div", { className: "fdc-packet-alert", role: "alert", children: [
12334
+ /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
12335
+ /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("span", { children: packet.error || "This result failed validation and can\u2019t be applied." })
12336
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("div", { className: "fdc-packet-body", children: render ? render(packet) : /* @__PURE__ */ (0, import_jsx_runtime92.jsx)(JsonView, { value: packet.payload }) }),
12337
+ !invalid && onApply ? /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("footer", { className: "fdc-packet-foot", children: [
12338
+ packet.repaired ? /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("span", { className: "fdc-packet-note", children: "Corrected by the backend after a first attempt." }) : /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("span", {}),
12339
+ /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("button", { type: "button", className: "fd-btn fd-btn-primary fd-btn-sm", disabled: applied, onClick: () => onApply(packet), children: [
12340
+ /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("i", { className: "ph ph-" + (applied ? "check" : "arrow-square-in"), "aria-hidden": "true" }),
12103
12341
  applied ? "Applied" : s.applyLabel || "Apply"
12104
12342
  ] })
12105
12343
  ] }) : null
12106
12344
  ] });
12107
12345
  }
12108
12346
  function ThinkingBlock({ text, durationMs, streaming, defaultOpen = false }) {
12109
- const [open2, setOpen] = React59.useState(defaultOpen);
12347
+ const [open2, setOpen] = React60.useState(defaultOpen);
12110
12348
  if (!text) return null;
12111
- return /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)("div", { className: "fdc-think" + (open2 ? " is-open" : ""), children: [
12112
- /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)("button", { type: "button", className: "fdc-think-head", onClick: () => setOpen((v) => !v), "aria-expanded": open2, children: [
12113
- /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("i", { className: "ph ph-brain", "aria-hidden": "true" }),
12114
- /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("span", { children: streaming ? "Thinking" : durationMs ? "Thought for " + formatDuration(durationMs) : "Thought process" }),
12115
- streaming ? /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)("span", { className: "fdc-dots", "aria-hidden": "true", children: [
12116
- /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("span", {}),
12117
- /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("span", {}),
12118
- /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("span", {})
12349
+ return /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("div", { className: "fdc-think" + (open2 ? " is-open" : ""), children: [
12350
+ /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("button", { type: "button", className: "fdc-think-head", onClick: () => setOpen((v) => !v), "aria-expanded": open2, children: [
12351
+ /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("i", { className: "ph ph-brain", "aria-hidden": "true" }),
12352
+ /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("span", { children: streaming ? "Thinking" : durationMs ? "Thought for " + formatDuration(durationMs) : "Thought process" }),
12353
+ streaming ? /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("span", { className: "fdc-dots", "aria-hidden": "true", children: [
12354
+ /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("span", {}),
12355
+ /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("span", {}),
12356
+ /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("span", {})
12119
12357
  ] }) : null,
12120
- /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("i", { className: "ph ph-caret-" + (open2 ? "up" : "down"), "aria-hidden": "true" })
12358
+ /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("i", { className: "ph ph-caret-" + (open2 ? "up" : "down"), "aria-hidden": "true" })
12121
12359
  ] }),
12122
- open2 ? /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("div", { className: "fdc-think-body", children: text }) : null
12360
+ open2 ? /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("div", { className: "fdc-think-body", children: text }) : null
12123
12361
  ] });
12124
12362
  }
12125
12363
  function Citations({ items = [], onOpen }) {
12126
- const [open2, setOpen] = React59.useState(false);
12364
+ const [open2, setOpen] = React60.useState(false);
12127
12365
  if (!items.length) return null;
12128
- return /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)("div", { className: "fdc-cites", children: [
12129
- /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)("button", { type: "button", className: "fdc-cites-head", onClick: () => setOpen((v) => !v), "aria-expanded": open2, children: [
12130
- /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("i", { className: "ph ph-quotes", "aria-hidden": "true" }),
12131
- /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)("span", { children: [
12366
+ return /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("div", { className: "fdc-cites", children: [
12367
+ /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("button", { type: "button", className: "fdc-cites-head", onClick: () => setOpen((v) => !v), "aria-expanded": open2, children: [
12368
+ /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("i", { className: "ph ph-quotes", "aria-hidden": "true" }),
12369
+ /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("span", { children: [
12132
12370
  items.length,
12133
12371
  " source",
12134
12372
  items.length === 1 ? "" : "s"
12135
12373
  ] }),
12136
- /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("i", { className: "ph ph-caret-" + (open2 ? "up" : "down"), "aria-hidden": "true" })
12374
+ /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("i", { className: "ph ph-caret-" + (open2 ? "up" : "down"), "aria-hidden": "true" })
12137
12375
  ] }),
12138
- open2 ? /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("ol", { className: "fdc-cites-list", children: items.map((c, i) => /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)("li", { children: [
12139
- /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("span", { className: "fdc-cite-n fd-tabular", children: c.marker || i + 1 }),
12140
- c.url ? /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("a", { href: c.url, target: "_blank", rel: "noopener noreferrer", onClick: onOpen ? (e) => onOpen(c, e) : void 0, children: c.title || c.url }) : /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("span", { children: c.title || "Source" }),
12141
- c.detail ? /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("span", { className: "fdc-cite-detail", children: c.detail }) : null
12376
+ open2 ? /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("ol", { className: "fdc-cites-list", children: items.map((c, i) => /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("li", { children: [
12377
+ /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("span", { className: "fdc-cite-n fd-tabular", children: c.marker || i + 1 }),
12378
+ c.url ? /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("a", { href: c.url, target: "_blank", rel: "noopener noreferrer", onClick: onOpen ? (e) => onOpen(c, e) : void 0, children: c.title || c.url }) : /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("span", { children: c.title || "Source" }),
12379
+ c.detail ? /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("span", { className: "fdc-cite-detail", children: c.detail }) : null
12142
12380
  ] }, c.id || i)) }) : null
12143
12381
  ] });
12144
12382
  }
@@ -12149,29 +12387,29 @@ function clampText(text, max) {
12149
12387
  return (at > max * 0.6 ? cut.slice(0, at) : cut).trimEnd() + "\u2026";
12150
12388
  }
12151
12389
  function MessageBody({ message: m, ctx }) {
12152
- const [expanded, setExpanded] = React59.useState(false);
12390
+ const [expanded, setExpanded] = React60.useState(false);
12153
12391
  const isUser = m.role === "user";
12154
12392
  const raw = m.text || "";
12155
12393
  const clamped = !expanded && !m.streaming ? clampText(raw, ctx.maxVisibleChars) : null;
12156
12394
  const body = clamped != null ? clamped : raw;
12157
12395
  const showMd = ctx.markdown && !isUser;
12158
- return /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)("div", { className: "fdc-body", children: [
12159
- m.thinking && ctx.showThinking ? /* @__PURE__ */ (0, import_jsx_runtime91.jsx)(ThinkingBlock, { text: m.thinking, durationMs: m.thinkingMs, streaming: m.streaming && !m.text }) : null,
12160
- m.steps && m.steps.length && ctx.showSteps ? /* @__PURE__ */ (0, import_jsx_runtime91.jsx)(StepList, { steps: m.steps, defaultOpen: m.steps.some((s) => s.status === "running"), dense: true }) : null,
12161
- body ? /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)("div", { className: "fdc-text" + (isUser ? " is-user" : ""), children: [
12162
- showMd ? /* @__PURE__ */ (0, import_jsx_runtime91.jsx)(Markdown, { source: body, headingOffset: 2, codeProps: { collapseAfter: 22 }, renderCitation: ctx.renderCitation }) : /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("div", { className: "fdc-plain", children: body }),
12163
- m.streaming ? /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("span", { className: "fdc-caret", "aria-hidden": "true" }) : null
12396
+ return /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("div", { className: "fdc-body", children: [
12397
+ m.thinking && ctx.showThinking ? /* @__PURE__ */ (0, import_jsx_runtime92.jsx)(ThinkingBlock, { text: m.thinking, durationMs: m.thinkingMs, streaming: m.streaming && !m.text }) : null,
12398
+ m.steps && m.steps.length && ctx.showSteps ? /* @__PURE__ */ (0, import_jsx_runtime92.jsx)(StepList, { steps: m.steps, defaultOpen: m.steps.some((s) => s.status === "running"), dense: true }) : null,
12399
+ body ? /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("div", { className: "fdc-text" + (isUser ? " is-user" : ""), children: [
12400
+ showMd ? /* @__PURE__ */ (0, import_jsx_runtime92.jsx)(Markdown, { source: body, headingOffset: 2, codeProps: { collapseAfter: 22 }, renderCitation: ctx.renderCitation }) : /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("div", { className: "fdc-plain", children: body }),
12401
+ m.streaming ? /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("span", { className: "fdc-caret", "aria-hidden": "true" }) : null
12164
12402
  ] }) : null,
12165
- clamped != null ? /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)("button", { type: "button", className: "fdc-more", onClick: () => setExpanded(true), children: [
12166
- /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("i", { className: "ph ph-caret-down", "aria-hidden": "true" }),
12403
+ clamped != null ? /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("button", { type: "button", className: "fdc-more", onClick: () => setExpanded(true), children: [
12404
+ /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("i", { className: "ph ph-caret-down", "aria-hidden": "true" }),
12167
12405
  "Show more",
12168
- /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("span", { className: "fdc-more-len fd-tabular", children: raw.length < 2e3 ? raw.length.toLocaleString() + " characters" : Math.round(raw.length / 100) / 10 + "k characters" })
12169
- ] }) : expanded && ctx.maxVisibleChars && raw.length > ctx.maxVisibleChars ? /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)("button", { type: "button", className: "fdc-more", onClick: () => setExpanded(false), children: [
12170
- /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("i", { className: "ph ph-caret-up", "aria-hidden": "true" }),
12406
+ /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("span", { className: "fdc-more-len fd-tabular", children: raw.length < 2e3 ? raw.length.toLocaleString() + " characters" : Math.round(raw.length / 100) / 10 + "k characters" })
12407
+ ] }) : expanded && ctx.maxVisibleChars && raw.length > ctx.maxVisibleChars ? /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("button", { type: "button", className: "fdc-more", onClick: () => setExpanded(false), children: [
12408
+ /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("i", { className: "ph ph-caret-up", "aria-hidden": "true" }),
12171
12409
  "Show less"
12172
12410
  ] }) : null,
12173
- m.attachments && m.attachments.length ? /* @__PURE__ */ (0, import_jsx_runtime91.jsx)(FileGrid, { files: m.attachments, onOpen: ctx.onOpenAttachment, tiles: true, maxHeight: ctx.attachmentHeight || 220, compact: ctx.narrow }) : null,
12174
- m.packet ? /* @__PURE__ */ (0, import_jsx_runtime91.jsx)(
12411
+ m.attachments && m.attachments.length ? /* @__PURE__ */ (0, import_jsx_runtime92.jsx)(FileGrid, { files: m.attachments, onOpen: ctx.onOpenAttachment, tiles: true, maxHeight: ctx.attachmentHeight || 220, compact: ctx.narrow }) : null,
12412
+ m.packet ? /* @__PURE__ */ (0, import_jsx_runtime92.jsx)(
12175
12413
  PacketCard,
12176
12414
  {
12177
12415
  packet: m.packet,
@@ -12181,44 +12419,44 @@ function MessageBody({ message: m, ctx }) {
12181
12419
  applied: ctx.appliedPackets && ctx.appliedPackets[m.id]
12182
12420
  }
12183
12421
  ) : null,
12184
- m.citations && m.citations.length ? /* @__PURE__ */ (0, import_jsx_runtime91.jsx)(Citations, { items: m.citations, onOpen: ctx.onOpenCitation }) : null,
12185
- m.working ? /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)("div", { className: "fdc-working", role: "status", children: [
12186
- /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)("span", { className: "fdc-dots", "aria-hidden": "true", children: [
12187
- /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("span", {}),
12188
- /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("span", {}),
12189
- /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("span", {})
12422
+ m.citations && m.citations.length ? /* @__PURE__ */ (0, import_jsx_runtime92.jsx)(Citations, { items: m.citations, onOpen: ctx.onOpenCitation }) : null,
12423
+ m.working ? /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("div", { className: "fdc-working", role: "status", children: [
12424
+ /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("span", { className: "fdc-dots", "aria-hidden": "true", children: [
12425
+ /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("span", {}),
12426
+ /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("span", {}),
12427
+ /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("span", {})
12190
12428
  ] }),
12191
- /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)("span", { className: "fdc-working-label", children: [
12429
+ /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("span", { className: "fdc-working-label", children: [
12192
12430
  m.resumed ? "Resuming" : "Working",
12193
- m.job && m.job.status ? /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)("span", { className: "fdc-working-job", children: [
12431
+ m.job && m.job.status ? /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("span", { className: "fdc-working-job", children: [
12194
12432
  " \xB7 ",
12195
12433
  m.job.status
12196
12434
  ] }) : null,
12197
- m.job && m.job.detail ? /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)("span", { className: "fdc-working-job", children: [
12435
+ m.job && m.job.detail ? /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("span", { className: "fdc-working-job", children: [
12198
12436
  " \xB7 ",
12199
12437
  m.job.detail
12200
12438
  ] }) : null
12201
12439
  ] }),
12202
- m.jobId ? /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("span", { className: "fdc-working-id fd-mono", children: String(m.jobId).slice(0, 12) }) : null
12440
+ m.jobId ? /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("span", { className: "fdc-working-id fd-mono", children: String(m.jobId).slice(0, 12) }) : null
12203
12441
  ] }) : null,
12204
- m.stopped ? /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)("div", { className: "fdc-stopped", children: [
12205
- /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("i", { className: "ph ph-stop-circle", "aria-hidden": "true" }),
12442
+ m.stopped ? /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("div", { className: "fdc-stopped", children: [
12443
+ /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("i", { className: "ph ph-stop-circle", "aria-hidden": "true" }),
12206
12444
  "Stopped"
12207
12445
  ] }) : null,
12208
- m.error ? /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)("div", { className: "fdc-error", role: "alert", children: [
12209
- /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
12210
- /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("span", { className: "fdc-error-text", children: ctx.errorCopy ? ctx.errorCopy(m.error) : m.error }),
12211
- m.retryable && ctx.onRetry ? /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)("button", { type: "button", className: "fdc-error-retry", onClick: ctx.onRetry, children: [
12212
- /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("i", { className: "ph ph-arrow-clockwise", "aria-hidden": "true" }),
12446
+ m.error ? /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("div", { className: "fdc-error", role: "alert", children: [
12447
+ /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
12448
+ /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("span", { className: "fdc-error-text", children: ctx.errorCopy ? ctx.errorCopy(m.error) : m.error }),
12449
+ m.retryable && ctx.onRetry ? /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("button", { type: "button", className: "fdc-error-retry", onClick: ctx.onRetry, children: [
12450
+ /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("i", { className: "ph ph-arrow-clockwise", "aria-hidden": "true" }),
12213
12451
  "Retry"
12214
12452
  ] }) : null
12215
12453
  ] }) : null
12216
12454
  ] });
12217
12455
  }
12218
12456
  function useCopyRun() {
12219
- const [done, setDone] = React59.useState(false);
12220
- const t = React59.useRef(null);
12221
- React59.useEffect(() => () => {
12457
+ const [done, setDone] = React60.useState(false);
12458
+ const t = React60.useRef(null);
12459
+ React60.useEffect(() => () => {
12222
12460
  if (t.current) clearTimeout(t.current);
12223
12461
  }, []);
12224
12462
  return [done, (text) => {
@@ -12238,16 +12476,16 @@ function RunActions({ group, ctx }) {
12238
12476
  const isAssistant = group.role === "assistant";
12239
12477
  const fb = last.feedback;
12240
12478
  if (!ctx.messageActions) return null;
12241
- return /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)("div", { className: "fdc-actions", role: "group", "aria-label": "Message actions", children: [
12242
- /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)("button", { type: "button", className: "fdc-act" + (copied ? " is-done" : ""), onClick: () => copy(markdownToText(text)), "aria-label": "Copy message", children: [
12243
- /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("i", { className: "ph ph-" + (copied ? "check" : "copy"), "aria-hidden": "true" }),
12244
- /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("span", { className: "fdc-act-label", children: copied ? "Copied" : "Copy" })
12479
+ return /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("div", { className: "fdc-actions", role: "group", "aria-label": "Message actions", children: [
12480
+ /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("button", { type: "button", className: "fdc-act" + (copied ? " is-done" : ""), onClick: () => copy(markdownToText(text)), "aria-label": "Copy message", children: [
12481
+ /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("i", { className: "ph ph-" + (copied ? "check" : "copy"), "aria-hidden": "true" }),
12482
+ /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("span", { className: "fdc-act-label", children: copied ? "Copied" : "Copy" })
12245
12483
  ] }),
12246
- isAssistant && ctx.onRetry ? /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("button", { type: "button", className: "fdc-act", onClick: ctx.onRetry, "aria-label": "Retry this turn", children: /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("i", { className: "ph ph-arrow-clockwise", "aria-hidden": "true" }) }) : null,
12247
- group.role === "user" && ctx.onEdit ? /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("button", { type: "button", className: "fdc-act", onClick: () => ctx.onEdit(last), "aria-label": "Edit and resend", children: /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("i", { className: "ph ph-pencil-simple", "aria-hidden": "true" }) }) : null,
12248
- isAssistant && ctx.onFeedback ? /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)(React59.Fragment, { children: [
12249
- /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("button", { type: "button", className: "fdc-act" + (fb === "up" ? " is-on" : ""), onClick: () => ctx.onFeedback(last.id, "up"), "aria-pressed": fb === "up", "aria-label": "Good response", children: /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("i", { className: "ph ph-thumbs-up", "aria-hidden": "true" }) }),
12250
- /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("button", { type: "button", className: "fdc-act" + (fb === "down" ? " is-on" : ""), onClick: () => ctx.onFeedback(last.id, "down"), "aria-pressed": fb === "down", "aria-label": "Bad response", children: /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("i", { className: "ph ph-thumbs-down", "aria-hidden": "true" }) })
12484
+ isAssistant && ctx.onRetry ? /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("button", { type: "button", className: "fdc-act", onClick: ctx.onRetry, "aria-label": "Retry this turn", children: /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("i", { className: "ph ph-arrow-clockwise", "aria-hidden": "true" }) }) : null,
12485
+ group.role === "user" && ctx.onEdit ? /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("button", { type: "button", className: "fdc-act", onClick: () => ctx.onEdit(last), "aria-label": "Edit and resend", children: /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("i", { className: "ph ph-pencil-simple", "aria-hidden": "true" }) }) : null,
12486
+ isAssistant && ctx.onFeedback ? /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)(React60.Fragment, { children: [
12487
+ /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("button", { type: "button", className: "fdc-act" + (fb === "up" ? " is-on" : ""), onClick: () => ctx.onFeedback(last.id, "up"), "aria-pressed": fb === "up", "aria-label": "Good response", children: /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("i", { className: "ph ph-thumbs-up", "aria-hidden": "true" }) }),
12488
+ /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("button", { type: "button", className: "fdc-act" + (fb === "down" ? " is-on" : ""), onClick: () => ctx.onFeedback(last.id, "down"), "aria-pressed": fb === "down", "aria-label": "Bad response", children: /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("i", { className: "ph ph-thumbs-down", "aria-hidden": "true" }) })
12251
12489
  ] }) : null,
12252
12490
  ctx.extraActions ? ctx.extraActions(group) : null
12253
12491
  ] });
@@ -12257,22 +12495,22 @@ function ChatTurn({ group, ctx }) {
12257
12495
  const name = isUser ? ctx.userName : group.author || ctx.assistantName;
12258
12496
  const avatar = isUser ? ctx.userAvatar : ctx.assistantAvatar;
12259
12497
  const stamp = group.messages[0].timestamp;
12260
- return /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)("article", { className: "fdc-turn is-" + group.role, "aria-label": String(name) + (stamp ? " at " + formatClock(stamp) : ""), children: [
12261
- /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)("div", { className: "fdc-turn-head", children: [
12262
- ctx.showAvatars ? /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("span", { className: "fdc-avatar is-" + group.role, "aria-hidden": "true", children: avatar ? /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("img", { src: avatar, alt: "" }) : isUser ? /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("span", { className: "fdc-avatar-txt", children: (name || "You").slice(0, 1).toUpperCase() }) : /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("i", { className: "ph ph-" + (ctx.assistantIcon || "sparkle") }) }) : null,
12263
- /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("span", { className: "fdc-who", children: name }),
12264
- stamp ? /* @__PURE__ */ (0, import_jsx_runtime91.jsx)(RelativeTime, { className: "fdc-when", value: stamp }) : null,
12265
- group.messages.some((m) => m.model) ? /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("span", { className: "fdc-turn-model", children: group.messages.find((m) => m.model).model }) : null
12498
+ return /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("article", { className: "fdc-turn is-" + group.role, "aria-label": String(name) + (stamp ? " at " + formatClock(stamp) : ""), children: [
12499
+ /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("div", { className: "fdc-turn-head", children: [
12500
+ ctx.showAvatars ? /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("span", { className: "fdc-avatar is-" + group.role, "aria-hidden": "true", children: avatar ? /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("img", { src: avatar, alt: "" }) : isUser ? /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("span", { className: "fdc-avatar-txt", children: (name || "You").slice(0, 1).toUpperCase() }) : /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("i", { className: "ph ph-" + (ctx.assistantIcon || "sparkle") }) }) : null,
12501
+ /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("span", { className: "fdc-who", children: name }),
12502
+ stamp ? /* @__PURE__ */ (0, import_jsx_runtime92.jsx)(RelativeTime, { className: "fdc-when", value: stamp }) : null,
12503
+ group.messages.some((m) => m.model) ? /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("span", { className: "fdc-turn-model", children: group.messages.find((m) => m.model).model }) : null
12266
12504
  ] }),
12267
- /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)("div", { className: "fdc-turn-body", children: [
12268
- group.messages.map((m) => /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("div", { className: "fdc-msg" + (m.pending ? " is-pending" : ""), children: /* @__PURE__ */ (0, import_jsx_runtime91.jsx)(MessageBody, { message: m, ctx }) }, m.id)),
12269
- /* @__PURE__ */ (0, import_jsx_runtime91.jsx)(RunActions, { group, ctx })
12505
+ /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("div", { className: "fdc-turn-body", children: [
12506
+ group.messages.map((m) => /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("div", { className: "fdc-msg" + (m.pending ? " is-pending" : ""), children: /* @__PURE__ */ (0, import_jsx_runtime92.jsx)(MessageBody, { message: m, ctx }) }, m.id)),
12507
+ /* @__PURE__ */ (0, import_jsx_runtime92.jsx)(RunActions, { group, ctx })
12270
12508
  ] })
12271
12509
  ] });
12272
12510
  }
12273
12511
 
12274
12512
  // src/components/chat/ChatTranscript.tsx
12275
- var import_jsx_runtime92 = require("react/jsx-runtime");
12513
+ var import_jsx_runtime93 = require("react/jsx-runtime");
12276
12514
  var GROUP_WINDOW = 6e4;
12277
12515
  var STICK_PX = 100;
12278
12516
  function groupMessages(list) {
@@ -12305,25 +12543,25 @@ function dayLabel(key) {
12305
12543
  }
12306
12544
  function Suggestions({ items = [], onPick }) {
12307
12545
  if (!items.length) return null;
12308
- return /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("div", { className: "fdc-suggest", children: items.map((s, i) => {
12546
+ return /* @__PURE__ */ (0, import_jsx_runtime93.jsx)("div", { className: "fdc-suggest", children: items.map((s, i) => {
12309
12547
  const it = typeof s === "string" ? { label: s, text: s } : s;
12310
- return /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("button", { type: "button", className: "fdc-suggest-item", onClick: () => onPick && onPick(it.text || it.label), children: [
12311
- it.icon ? /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("i", { className: "ph ph-" + it.icon, "aria-hidden": "true" }) : null,
12312
- /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("span", { className: "fdc-suggest-text", children: [
12313
- /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("span", { className: "fdc-suggest-label", children: it.label }),
12314
- it.description ? /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("span", { className: "fdc-suggest-desc", children: it.description }) : null
12548
+ return /* @__PURE__ */ (0, import_jsx_runtime93.jsxs)("button", { type: "button", className: "fdc-suggest-item", onClick: () => onPick && onPick(it.text || it.label), children: [
12549
+ it.icon ? /* @__PURE__ */ (0, import_jsx_runtime93.jsx)("i", { className: "ph ph-" + it.icon, "aria-hidden": "true" }) : null,
12550
+ /* @__PURE__ */ (0, import_jsx_runtime93.jsxs)("span", { className: "fdc-suggest-text", children: [
12551
+ /* @__PURE__ */ (0, import_jsx_runtime93.jsx)("span", { className: "fdc-suggest-label", children: it.label }),
12552
+ it.description ? /* @__PURE__ */ (0, import_jsx_runtime93.jsx)("span", { className: "fdc-suggest-desc", children: it.description }) : null
12315
12553
  ] }),
12316
- /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("i", { className: "ph ph-arrow-up-right fdc-suggest-go", "aria-hidden": "true" })
12554
+ /* @__PURE__ */ (0, import_jsx_runtime93.jsx)("i", { className: "ph ph-arrow-up-right fdc-suggest-go", "aria-hidden": "true" })
12317
12555
  ] }, it.id || i);
12318
12556
  }) });
12319
12557
  }
12320
12558
  function LoadingTurns() {
12321
- return /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("div", { className: "fdc-skel", "aria-hidden": "true", children: [0, 1].map((i) => /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("div", { className: "fdc-skel-turn", children: [
12322
- /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("div", { className: "fd-skel fd-skel-circle", style: { width: 22, height: 22 } }),
12323
- /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("div", { className: "fdc-skel-lines", children: [
12324
- /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("div", { className: "fd-skel", style: { width: i ? "62%" : "44%", height: 11 } }),
12325
- /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("div", { className: "fd-skel", style: { width: i ? "94%" : "78%", height: 11 } }),
12326
- /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("div", { className: "fd-skel", style: { width: i ? "71%" : "56%", height: 11 } })
12559
+ return /* @__PURE__ */ (0, import_jsx_runtime93.jsx)("div", { className: "fdc-skel", "aria-hidden": "true", children: [0, 1].map((i) => /* @__PURE__ */ (0, import_jsx_runtime93.jsxs)("div", { className: "fdc-skel-turn", children: [
12560
+ /* @__PURE__ */ (0, import_jsx_runtime93.jsx)("div", { className: "fd-skel fd-skel-circle", style: { width: 22, height: 22 } }),
12561
+ /* @__PURE__ */ (0, import_jsx_runtime93.jsxs)("div", { className: "fdc-skel-lines", children: [
12562
+ /* @__PURE__ */ (0, import_jsx_runtime93.jsx)("div", { className: "fd-skel", style: { width: i ? "62%" : "44%", height: 11 } }),
12563
+ /* @__PURE__ */ (0, import_jsx_runtime93.jsx)("div", { className: "fd-skel", style: { width: i ? "94%" : "78%", height: 11 } }),
12564
+ /* @__PURE__ */ (0, import_jsx_runtime93.jsx)("div", { className: "fd-skel", style: { width: i ? "71%" : "56%", height: 11 } })
12327
12565
  ] })
12328
12566
  ] }, i)) });
12329
12567
  }
@@ -12340,10 +12578,10 @@ function ChatTranscript({
12340
12578
  renderEmpty,
12341
12579
  className = ""
12342
12580
  }) {
12343
- const scroller = React60.useRef(null);
12344
- const stick = React60.useRef(true);
12345
- const [pill, setPill] = React60.useState(0);
12346
- const seen = React60.useRef(0);
12581
+ const scroller = React61.useRef(null);
12582
+ const stick = React61.useRef(true);
12583
+ const [pill, setPill] = React61.useState(0);
12584
+ const seen = React61.useRef(0);
12347
12585
  const toBottom = (smooth) => {
12348
12586
  const el = scroller.current;
12349
12587
  if (!el) return;
@@ -12362,7 +12600,7 @@ function ChatTranscript({
12362
12600
  seen.current = messages.length;
12363
12601
  }
12364
12602
  };
12365
- React60.useLayoutEffect(() => {
12603
+ React61.useLayoutEffect(() => {
12366
12604
  const el = scroller.current;
12367
12605
  if (!el) return;
12368
12606
  if (stick.current) {
@@ -12370,7 +12608,7 @@ function ChatTranscript({
12370
12608
  seen.current = messages.length;
12371
12609
  } else setPill(Math.max(0, messages.length - seen.current));
12372
12610
  }, [messages]);
12373
- React60.useEffect(() => {
12611
+ React61.useEffect(() => {
12374
12612
  const el = scroller.current;
12375
12613
  const inner = el && el.firstChild;
12376
12614
  if (!el || !inner || typeof ResizeObserver === "undefined") return;
@@ -12380,38 +12618,38 @@ function ChatTranscript({
12380
12618
  ro.observe(inner);
12381
12619
  return () => ro.disconnect();
12382
12620
  }, []);
12383
- const groups = React60.useMemo(() => groupMessages(messages), [messages]);
12621
+ const groups = React61.useMemo(() => groupMessages(messages), [messages]);
12384
12622
  const empty = !messages.length && status === "ready";
12385
- return /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("div", { className: ["fdc-scroll", className].filter(Boolean).join(" "), ref: scroller, onScroll, children: [
12386
- /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("div", { className: "fdc-log", role: "log", "aria-label": "Conversation", children: [
12387
- status === "loading" || status === "resolving" ? /* @__PURE__ */ (0, import_jsx_runtime92.jsx)(LoadingTurns, {}) : null,
12388
- status === "disconnected" ? /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("div", { className: "fdc-dead", children: [
12389
- /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("span", { className: "fdc-dead-icon", children: /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("i", { className: "ph ph-plugs", "aria-hidden": "true" }) }),
12390
- /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("h3", { className: "fdc-dead-title", children: ctx.deadTitle || "The assistant isn\u2019t reachable" }),
12391
- /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("p", { className: "fdc-dead-body", children: fatal === "chat_unavailable" ? "The service reported chat_unavailable. Nothing you type will be lost \u2014 reopen the panel once it\u2019s back." : "The thread couldn\u2019t be resolved" + (fatal ? " (" + fatal + ")" : "") + ". The composer stays disabled until it resolves." }),
12392
- ctx.onReconnect ? /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("button", { type: "button", className: "fd-btn fd-btn-secondary fd-btn-sm", onClick: ctx.onReconnect, children: [
12393
- /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("i", { className: "ph ph-arrow-clockwise", "aria-hidden": "true" }),
12623
+ return /* @__PURE__ */ (0, import_jsx_runtime93.jsxs)("div", { className: ["fdc-scroll", className].filter(Boolean).join(" "), ref: scroller, onScroll, children: [
12624
+ /* @__PURE__ */ (0, import_jsx_runtime93.jsxs)("div", { className: "fdc-log", role: "log", "aria-label": "Conversation", children: [
12625
+ status === "loading" || status === "resolving" ? /* @__PURE__ */ (0, import_jsx_runtime93.jsx)(LoadingTurns, {}) : null,
12626
+ status === "disconnected" ? /* @__PURE__ */ (0, import_jsx_runtime93.jsxs)("div", { className: "fdc-dead", children: [
12627
+ /* @__PURE__ */ (0, import_jsx_runtime93.jsx)("span", { className: "fdc-dead-icon", children: /* @__PURE__ */ (0, import_jsx_runtime93.jsx)("i", { className: "ph ph-plugs", "aria-hidden": "true" }) }),
12628
+ /* @__PURE__ */ (0, import_jsx_runtime93.jsx)("h3", { className: "fdc-dead-title", children: ctx.deadTitle || "The assistant isn\u2019t reachable" }),
12629
+ /* @__PURE__ */ (0, import_jsx_runtime93.jsx)("p", { className: "fdc-dead-body", children: fatal === "chat_unavailable" ? "The service reported chat_unavailable. Nothing you type will be lost \u2014 reopen the panel once it\u2019s back." : "The thread couldn\u2019t be resolved" + (fatal ? " (" + fatal + ")" : "") + ". The composer stays disabled until it resolves." }),
12630
+ ctx.onReconnect ? /* @__PURE__ */ (0, import_jsx_runtime93.jsxs)("button", { type: "button", className: "fd-btn fd-btn-secondary fd-btn-sm", onClick: ctx.onReconnect, children: [
12631
+ /* @__PURE__ */ (0, import_jsx_runtime93.jsx)("i", { className: "ph ph-arrow-clockwise", "aria-hidden": "true" }),
12394
12632
  "Try again"
12395
12633
  ] }) : null
12396
12634
  ] }) : null,
12397
- empty ? renderEmpty ? renderEmpty() : /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("div", { className: "fdc-empty", children: [
12398
- /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("span", { className: "fdc-empty-icon", children: /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("i", { className: "ph ph-" + emptyIcon, "aria-hidden": "true" }) }),
12399
- /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("h3", { className: "fdc-empty-title", children: emptyTitle }),
12400
- emptyDescription ? /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("p", { className: "fdc-empty-body", children: emptyDescription }) : null,
12401
- /* @__PURE__ */ (0, import_jsx_runtime92.jsx)(Suggestions, { items: suggestions, onPick })
12635
+ empty ? renderEmpty ? renderEmpty() : /* @__PURE__ */ (0, import_jsx_runtime93.jsxs)("div", { className: "fdc-empty", children: [
12636
+ /* @__PURE__ */ (0, import_jsx_runtime93.jsx)("span", { className: "fdc-empty-icon", children: /* @__PURE__ */ (0, import_jsx_runtime93.jsx)("i", { className: "ph ph-" + emptyIcon, "aria-hidden": "true" }) }),
12637
+ /* @__PURE__ */ (0, import_jsx_runtime93.jsx)("h3", { className: "fdc-empty-title", children: emptyTitle }),
12638
+ emptyDescription ? /* @__PURE__ */ (0, import_jsx_runtime93.jsx)("p", { className: "fdc-empty-body", children: emptyDescription }) : null,
12639
+ /* @__PURE__ */ (0, import_jsx_runtime93.jsx)(Suggestions, { items: suggestions, onPick })
12402
12640
  ] }) : null,
12403
12641
  groups.map((g, i) => {
12404
12642
  const prev = groups[i - 1];
12405
12643
  const k = dayKey(g.messages[0].timestamp);
12406
12644
  const showDay = !!k && (!prev || dayKey(prev.messages[0].timestamp) !== k);
12407
- return /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)(React60.Fragment, { children: [
12408
- showDay ? /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("div", { className: "fdc-day", children: /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("span", { children: dayLabel(k) }) }) : null,
12409
- /* @__PURE__ */ (0, import_jsx_runtime92.jsx)(ChatTurn, { group: g, ctx })
12645
+ return /* @__PURE__ */ (0, import_jsx_runtime93.jsxs)(React61.Fragment, { children: [
12646
+ showDay ? /* @__PURE__ */ (0, import_jsx_runtime93.jsx)("div", { className: "fdc-day", children: /* @__PURE__ */ (0, import_jsx_runtime93.jsx)("span", { children: dayLabel(k) }) }) : null,
12647
+ /* @__PURE__ */ (0, import_jsx_runtime93.jsx)(ChatTurn, { group: g, ctx })
12410
12648
  ] }, g.key || i);
12411
12649
  })
12412
12650
  ] }),
12413
- pill ? /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("button", { type: "button", className: "fdc-pill", onClick: () => toBottom(true), children: [
12414
- /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("i", { className: "ph ph-arrow-down", "aria-hidden": "true" }),
12651
+ pill ? /* @__PURE__ */ (0, import_jsx_runtime93.jsxs)("button", { type: "button", className: "fdc-pill", onClick: () => toBottom(true), children: [
12652
+ /* @__PURE__ */ (0, import_jsx_runtime93.jsx)("i", { className: "ph ph-arrow-down", "aria-hidden": "true" }),
12415
12653
  pill,
12416
12654
  " new message",
12417
12655
  pill === 1 ? "" : "s"
@@ -12421,8 +12659,8 @@ function ChatTranscript({
12421
12659
  var TranscriptKit = { groupMessages };
12422
12660
 
12423
12661
  // src/components/chat/ChatComposer.tsx
12424
- var React61 = __toESM(require("react"), 1);
12425
- var import_jsx_runtime93 = require("react/jsx-runtime");
12662
+ var React62 = __toESM(require("react"), 1);
12663
+ var import_jsx_runtime94 = require("react/jsx-runtime");
12426
12664
  function ChatComposer({
12427
12665
  onSubmit,
12428
12666
  onStop,
@@ -12449,17 +12687,17 @@ function ChatComposer({
12449
12687
  onReject,
12450
12688
  onOpenAttachment
12451
12689
  }) {
12452
- const [text, setText] = React61.useState(draft || "");
12453
- const [trigger, setTrigger] = React61.useState(null);
12454
- const [mentionItems, setMentionItems] = React61.useState([]);
12455
- const [listening, setListening] = React61.useState(false);
12456
- const [notice, setNotice] = React61.useState(null);
12457
- const editor = React61.useRef(null);
12458
- const wrap = React61.useRef(null);
12459
- const stopVoice = React61.useRef(null);
12690
+ const [text, setText] = React62.useState(draft || "");
12691
+ const [trigger, setTrigger] = React62.useState(null);
12692
+ const [mentionItems, setMentionItems] = React62.useState([]);
12693
+ const [listening, setListening] = React62.useState(false);
12694
+ const [notice, setNotice] = React62.useState(null);
12695
+ const editor = React62.useRef(null);
12696
+ const wrap = React62.useRef(null);
12697
+ const stopVoice = React62.useRef(null);
12460
12698
  const staged = useStagedFiles(fileUploadHandler, { onError: () => {
12461
12699
  } });
12462
- React61.useEffect(() => {
12700
+ React62.useEffect(() => {
12463
12701
  if (draft != null && draft !== text) setText(draft);
12464
12702
  }, [draft]);
12465
12703
  const change = (v) => {
@@ -12495,7 +12733,7 @@ function ChatComposer({
12495
12733
  e.preventDefault();
12496
12734
  staged.add(found.files);
12497
12735
  };
12498
- React61.useEffect(() => {
12736
+ React62.useEffect(() => {
12499
12737
  if (!trigger || trigger.type !== "mention" || !mentionSources) {
12500
12738
  setMentionItems([]);
12501
12739
  return;
@@ -12513,7 +12751,7 @@ function ChatComposer({
12513
12751
  const q = (trigger.query || "").toLowerCase();
12514
12752
  setMentionItems(mentionSources.filter((m) => !q || (m.label + " " + (m.description || "")).toLowerCase().includes(q)));
12515
12753
  }, [trigger, mentionSources]);
12516
- const slashItems = React61.useMemo(() => {
12754
+ const slashItems = React62.useMemo(() => {
12517
12755
  if (!trigger || trigger.type !== "slash" || !slashCommands) return [];
12518
12756
  const q = (trigger.query || "").toLowerCase();
12519
12757
  return slashCommands.filter((c) => !q || (c.id + " " + c.label + " " + (c.description || "")).toLowerCase().includes(q));
@@ -12527,7 +12765,7 @@ function ChatComposer({
12527
12765
  description: it.description,
12528
12766
  icon: it.icon,
12529
12767
  meta: mention.meta,
12530
- shortcut: slash.shortcut ? /* @__PURE__ */ (0, import_jsx_runtime93.jsx)(KeyHint, { keys: slash.shortcut, size: "sm" }) : void 0,
12768
+ shortcut: slash.shortcut ? /* @__PURE__ */ (0, import_jsx_runtime94.jsx)(KeyHint, { keys: slash.shortcut, size: "sm" }) : void 0,
12531
12769
  onSelect: () => {
12532
12770
  const insert = trigger.type === "slash" ? slash.immediate ? "/" + slash.id : "/" + slash.id + " " : "@" + (mention.value || mention.label) + " ";
12533
12771
  editor.current && editor.current.replaceRange(trigger.from, trigger.to, insert);
@@ -12586,14 +12824,14 @@ function ChatComposer({
12586
12824
  stopVoice.current = typeof res === "function" ? res : () => {
12587
12825
  };
12588
12826
  };
12589
- return /* @__PURE__ */ (0, import_jsx_runtime93.jsxs)("div", { className: "fdc-composer" + (disabled ? " is-disabled" : "") + (narrow ? " is-narrow" : ""), children: [
12590
- queue.length ? /* @__PURE__ */ (0, import_jsx_runtime93.jsx)("div", { className: "fdc-queue", "aria-label": "Queued messages", children: queue.map((q) => /* @__PURE__ */ (0, import_jsx_runtime93.jsxs)("div", { className: "fdc-queue-row", children: [
12591
- /* @__PURE__ */ (0, import_jsx_runtime93.jsx)("i", { className: "ph ph-clock-countdown", "aria-hidden": "true" }),
12592
- /* @__PURE__ */ (0, import_jsx_runtime93.jsx)("span", { className: "fdc-queue-text", title: truncationTitle(q.text || (q.attachments ? q.attachments.length + " file(s)" : "")), children: q.text || (q.attachments ? q.attachments.length + " file(s)" : "") }),
12593
- onRemoveQueued ? /* @__PURE__ */ (0, import_jsx_runtime93.jsx)("button", { type: "button", className: "fdc-queue-x", onClick: () => onRemoveQueued(q.id), "aria-label": "Remove queued message", children: /* @__PURE__ */ (0, import_jsx_runtime93.jsx)("i", { className: "ph ph-x", "aria-hidden": "true" }) }) : null
12827
+ return /* @__PURE__ */ (0, import_jsx_runtime94.jsxs)("div", { className: "fdc-composer" + (disabled ? " is-disabled" : "") + (narrow ? " is-narrow" : ""), children: [
12828
+ queue.length ? /* @__PURE__ */ (0, import_jsx_runtime94.jsx)("div", { className: "fdc-queue", "aria-label": "Queued messages", children: queue.map((q) => /* @__PURE__ */ (0, import_jsx_runtime94.jsxs)("div", { className: "fdc-queue-row", children: [
12829
+ /* @__PURE__ */ (0, import_jsx_runtime94.jsx)("i", { className: "ph ph-clock-countdown", "aria-hidden": "true" }),
12830
+ /* @__PURE__ */ (0, import_jsx_runtime94.jsx)("span", { className: "fdc-queue-text", title: truncationTitle(q.text || (q.attachments ? q.attachments.length + " file(s)" : "")), children: q.text || (q.attachments ? q.attachments.length + " file(s)" : "") }),
12831
+ onRemoveQueued ? /* @__PURE__ */ (0, import_jsx_runtime94.jsx)("button", { type: "button", className: "fdc-queue-x", onClick: () => onRemoveQueued(q.id), "aria-label": "Remove queued message", children: /* @__PURE__ */ (0, import_jsx_runtime94.jsx)("i", { className: "ph ph-x", "aria-hidden": "true" }) }) : null
12594
12832
  ] }, q.id)) }) : null,
12595
12833
  sessionBar,
12596
- /* @__PURE__ */ (0, import_jsx_runtime93.jsx)(
12834
+ /* @__PURE__ */ (0, import_jsx_runtime94.jsx)(
12597
12835
  Dropzone,
12598
12836
  {
12599
12837
  className: "fdc-field",
@@ -12607,9 +12845,9 @@ function ChatComposer({
12607
12845
  disabled: !fileUploadHandler || disabled,
12608
12846
  label: "Drop to attach",
12609
12847
  hint: acceptFiles ? acceptFiles.replace(/,/g, " \xB7 ") : void 0,
12610
- children: /* @__PURE__ */ (0, import_jsx_runtime93.jsxs)("div", { ref: wrap, className: "fdc-field-inner", children: [
12611
- staged.items.length ? /* @__PURE__ */ (0, import_jsx_runtime93.jsx)("div", { className: "fdc-staged", children: /* @__PURE__ */ (0, import_jsx_runtime93.jsx)(FileStrip, { files: staged.items, size: narrow ? 60 : 68, onRemove: staged.remove, onRetry: staged.retry, onOpen: onOpenAttachment }) }) : null,
12612
- /* @__PURE__ */ (0, import_jsx_runtime93.jsx)(
12848
+ children: /* @__PURE__ */ (0, import_jsx_runtime94.jsxs)("div", { ref: wrap, className: "fdc-field-inner", children: [
12849
+ staged.items.length ? /* @__PURE__ */ (0, import_jsx_runtime94.jsx)("div", { className: "fdc-staged", children: /* @__PURE__ */ (0, import_jsx_runtime94.jsx)(FileStrip, { files: staged.items, size: narrow ? 60 : 68, onRemove: staged.remove, onRetry: staged.retry, onOpen: onOpenAttachment }) }) : null,
12850
+ /* @__PURE__ */ (0, import_jsx_runtime94.jsx)(
12613
12851
  MarkdownEditor,
12614
12852
  {
12615
12853
  ref: editor,
@@ -12628,33 +12866,33 @@ function ChatComposer({
12628
12866
  ariaLabel: "Message"
12629
12867
  }
12630
12868
  ),
12631
- /* @__PURE__ */ (0, import_jsx_runtime93.jsxs)("div", { className: "fdc-tools", children: [
12632
- fileUploadHandler ? /* @__PURE__ */ (0, import_jsx_runtime93.jsx)(FilePickButton, { onFiles: staged.add, onReject: (r) => flash(r[0].message), accept: acceptFiles, maxFileSize, label: "Attach files", icon: "plus" }) : null,
12633
- voiceHandler ? /* @__PURE__ */ (0, import_jsx_runtime93.jsx)("button", { type: "button", className: "fd-attachbtn" + (listening ? " is-live" : ""), onClick: voice, "aria-pressed": listening, "aria-label": listening ? "Stop dictation" : "Dictate", children: /* @__PURE__ */ (0, import_jsx_runtime93.jsx)("i", { className: "ph ph-" + (listening ? "waveform" : "microphone"), "aria-hidden": "true" }) }) : null,
12869
+ /* @__PURE__ */ (0, import_jsx_runtime94.jsxs)("div", { className: "fdc-tools", children: [
12870
+ fileUploadHandler ? /* @__PURE__ */ (0, import_jsx_runtime94.jsx)(FilePickButton, { onFiles: staged.add, onReject: (r) => flash(r[0].message), accept: acceptFiles, maxFileSize, label: "Attach files", icon: "plus" }) : null,
12871
+ voiceHandler ? /* @__PURE__ */ (0, import_jsx_runtime94.jsx)("button", { type: "button", className: "fd-attachbtn" + (listening ? " is-live" : ""), onClick: voice, "aria-pressed": listening, "aria-label": listening ? "Stop dictation" : "Dictate", children: /* @__PURE__ */ (0, import_jsx_runtime94.jsx)("i", { className: "ph ph-" + (listening ? "waveform" : "microphone"), "aria-hidden": "true" }) }) : null,
12634
12872
  toolbarExtras,
12635
- /* @__PURE__ */ (0, import_jsx_runtime93.jsx)("span", { className: "fdc-tools-gap" }),
12636
- maxLength && text.length > maxLength * 0.6 ? /* @__PURE__ */ (0, import_jsx_runtime93.jsxs)("span", { className: "fdc-count fd-tabular" + (text.length > maxLength * 0.95 ? " is-hot" : ""), children: [
12873
+ /* @__PURE__ */ (0, import_jsx_runtime94.jsx)("span", { className: "fdc-tools-gap" }),
12874
+ maxLength && text.length > maxLength * 0.6 ? /* @__PURE__ */ (0, import_jsx_runtime94.jsxs)("span", { className: "fdc-count fd-tabular" + (text.length > maxLength * 0.95 ? " is-hot" : ""), children: [
12637
12875
  text.length,
12638
12876
  "/",
12639
12877
  maxLength
12640
12878
  ] }) : null,
12641
- busy ? /* @__PURE__ */ (0, import_jsx_runtime93.jsxs)("button", { type: "button", className: "fdc-stop", onClick: onStop, "aria-label": "Stop generating", children: [
12642
- /* @__PURE__ */ (0, import_jsx_runtime93.jsx)("i", { className: "ph ph-stop-circle", "aria-hidden": "true" }),
12643
- /* @__PURE__ */ (0, import_jsx_runtime93.jsx)("span", { children: "Stop" })
12644
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime93.jsxs)("button", { type: "button", className: "fdc-send", onClick: submit, disabled: !canSend, "aria-label": "Send message", children: [
12645
- /* @__PURE__ */ (0, import_jsx_runtime93.jsx)("i", { className: "ph ph-paper-plane-right", "aria-hidden": "true" }),
12646
- /* @__PURE__ */ (0, import_jsx_runtime93.jsx)("span", { className: "fdc-send-label", children: "Send" })
12879
+ busy ? /* @__PURE__ */ (0, import_jsx_runtime94.jsxs)("button", { type: "button", className: "fdc-stop", onClick: onStop, "aria-label": "Stop generating", children: [
12880
+ /* @__PURE__ */ (0, import_jsx_runtime94.jsx)("i", { className: "ph ph-stop-circle", "aria-hidden": "true" }),
12881
+ /* @__PURE__ */ (0, import_jsx_runtime94.jsx)("span", { children: "Stop" })
12882
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime94.jsxs)("button", { type: "button", className: "fdc-send", onClick: submit, disabled: !canSend, "aria-label": "Send message", children: [
12883
+ /* @__PURE__ */ (0, import_jsx_runtime94.jsx)("i", { className: "ph ph-paper-plane-right", "aria-hidden": "true" }),
12884
+ /* @__PURE__ */ (0, import_jsx_runtime94.jsx)("span", { className: "fdc-send-label", children: "Send" })
12647
12885
  ] })
12648
12886
  ] })
12649
12887
  ] })
12650
12888
  }
12651
12889
  ),
12652
- notice ? /* @__PURE__ */ (0, import_jsx_runtime93.jsxs)("div", { className: "fdc-notice", role: "status", children: [
12653
- /* @__PURE__ */ (0, import_jsx_runtime93.jsx)("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
12890
+ notice ? /* @__PURE__ */ (0, import_jsx_runtime94.jsxs)("div", { className: "fdc-notice", role: "status", children: [
12891
+ /* @__PURE__ */ (0, import_jsx_runtime94.jsx)("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
12654
12892
  notice
12655
12893
  ] }) : null,
12656
- hint && !notice ? /* @__PURE__ */ (0, import_jsx_runtime93.jsx)("div", { className: "fdc-hint", children: hint }) : null,
12657
- /* @__PURE__ */ (0, import_jsx_runtime93.jsx)(
12894
+ hint && !notice ? /* @__PURE__ */ (0, import_jsx_runtime94.jsx)("div", { className: "fdc-hint", children: hint }) : null,
12895
+ /* @__PURE__ */ (0, import_jsx_runtime94.jsx)(
12658
12896
  Popover,
12659
12897
  {
12660
12898
  open: menuOpen,
@@ -12668,12 +12906,12 @@ function ChatComposer({
12668
12906
  returnFocus: false,
12669
12907
  closeOnOutside: true,
12670
12908
  label: trigger && trigger.type === "slash" ? "Commands" : "Mentions",
12671
- children: /* @__PURE__ */ (0, import_jsx_runtime93.jsx)(
12909
+ children: /* @__PURE__ */ (0, import_jsx_runtime94.jsx)(
12672
12910
  Menu,
12673
12911
  {
12674
12912
  items: menuItems,
12675
12913
  autoFocus: false,
12676
- header: /* @__PURE__ */ (0, import_jsx_runtime93.jsx)("div", { className: "fd-pop-group", children: trigger && trigger.type === "slash" ? "Commands" : "Attach context" }),
12914
+ header: /* @__PURE__ */ (0, import_jsx_runtime94.jsx)("div", { className: "fd-pop-group", children: trigger && trigger.type === "slash" ? "Commands" : "Attach context" }),
12677
12915
  onClose: () => setTrigger(null)
12678
12916
  }
12679
12917
  )
@@ -12683,12 +12921,12 @@ function ChatComposer({
12683
12921
  }
12684
12922
 
12685
12923
  // src/components/chat/ChatSessionBar.tsx
12686
- var React62 = __toESM(require("react"), 1);
12687
- var import_jsx_runtime94 = require("react/jsx-runtime");
12924
+ var React63 = __toESM(require("react"), 1);
12925
+ var import_jsx_runtime95 = require("react/jsx-runtime");
12688
12926
  var compact2 = meterFormats.compact;
12689
12927
  function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extras }) {
12690
- const [open2, setOpen] = React62.useState(false);
12691
- const anchor = React62.useRef(null);
12928
+ const [open2, setOpen] = React63.useState(false);
12929
+ const anchor = React63.useRef(null);
12692
12930
  const stats = sessionStats || null;
12693
12931
  const cu = contextUsage || null;
12694
12932
  const limits = usageLimits || null;
@@ -12703,9 +12941,9 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
12703
12941
  if (stats && stats.runningTasks) bits.push(stats.runningTasks + " running task" + (stats.runningTasks === 1 ? "" : "s"));
12704
12942
  if (cu) bits.push(pct + "% context");
12705
12943
  const expandable = !!(cu || limits);
12706
- return /* @__PURE__ */ (0, import_jsx_runtime94.jsxs)(React62.Fragment, { children: [
12707
- /* @__PURE__ */ (0, import_jsx_runtime94.jsxs)("div", { className: "fdc-bar", children: [
12708
- /* @__PURE__ */ (0, import_jsx_runtime94.jsxs)(
12944
+ return /* @__PURE__ */ (0, import_jsx_runtime95.jsxs)(React63.Fragment, { children: [
12945
+ /* @__PURE__ */ (0, import_jsx_runtime95.jsxs)("div", { className: "fdc-bar", children: [
12946
+ /* @__PURE__ */ (0, import_jsx_runtime95.jsxs)(
12709
12947
  "button",
12710
12948
  {
12711
12949
  type: "button",
@@ -12716,15 +12954,15 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
12716
12954
  "aria-expanded": expandable ? open2 : void 0,
12717
12955
  "aria-label": expandable ? "Usage details" : void 0,
12718
12956
  children: [
12719
- cu ? /* @__PURE__ */ (0, import_jsx_runtime94.jsx)("span", { className: "fdc-bar-mini", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime94.jsx)(SegmentedMeter, { total, segments: cu.segments, height: 4, showTotal: false }) }) : null,
12720
- /* @__PURE__ */ (0, import_jsx_runtime94.jsx)("span", { className: "fdc-bar-text", title: truncationTitle(bits.join(" \xB7 ")), children: bits.join(" \xB7 ") }),
12721
- expandable ? /* @__PURE__ */ (0, import_jsx_runtime94.jsx)("i", { className: "ph ph-caret-right fdc-bar-caret", "aria-hidden": "true" }) : null
12957
+ cu ? /* @__PURE__ */ (0, import_jsx_runtime95.jsx)("span", { className: "fdc-bar-mini", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime95.jsx)(SegmentedMeter, { total, segments: cu.segments, height: 4, showTotal: false }) }) : null,
12958
+ /* @__PURE__ */ (0, import_jsx_runtime95.jsx)("span", { className: "fdc-bar-text", title: truncationTitle(bits.join(" \xB7 ")), children: bits.join(" \xB7 ") }),
12959
+ expandable ? /* @__PURE__ */ (0, import_jsx_runtime95.jsx)("i", { className: "ph ph-caret-right fdc-bar-caret", "aria-hidden": "true" }) : null
12722
12960
  ]
12723
12961
  }
12724
12962
  ),
12725
12963
  extras
12726
12964
  ] }),
12727
- /* @__PURE__ */ (0, import_jsx_runtime94.jsx)(
12965
+ /* @__PURE__ */ (0, import_jsx_runtime95.jsx)(
12728
12966
  Popover,
12729
12967
  {
12730
12968
  open: open2,
@@ -12735,15 +12973,15 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
12735
12973
  maxHeight: 460,
12736
12974
  padded: true,
12737
12975
  label: "Usage",
12738
- footer: onClear ? /* @__PURE__ */ (0, import_jsx_runtime94.jsxs)("button", { type: "button", className: "fdc-usage-clear", onClick: () => {
12976
+ footer: onClear ? /* @__PURE__ */ (0, import_jsx_runtime95.jsxs)("button", { type: "button", className: "fdc-usage-clear", onClick: () => {
12739
12977
  setOpen(false);
12740
12978
  onClear();
12741
12979
  }, children: [
12742
- /* @__PURE__ */ (0, import_jsx_runtime94.jsx)("i", { className: "ph ph-trash", "aria-hidden": "true" }),
12980
+ /* @__PURE__ */ (0, import_jsx_runtime95.jsx)("i", { className: "ph ph-trash", "aria-hidden": "true" }),
12743
12981
  "Clear conversation"
12744
12982
  ] }) : void 0,
12745
- children: /* @__PURE__ */ (0, import_jsx_runtime94.jsxs)("div", { className: "fdc-usage", children: [
12746
- cu ? /* @__PURE__ */ (0, import_jsx_runtime94.jsx)("section", { className: "fdc-usage-sec", children: /* @__PURE__ */ (0, import_jsx_runtime94.jsx)(
12983
+ children: /* @__PURE__ */ (0, import_jsx_runtime95.jsxs)("div", { className: "fdc-usage", children: [
12984
+ cu ? /* @__PURE__ */ (0, import_jsx_runtime95.jsx)("section", { className: "fdc-usage-sec", children: /* @__PURE__ */ (0, import_jsx_runtime95.jsx)(
12747
12985
  SegmentedMeter,
12748
12986
  {
12749
12987
  total,
@@ -12755,9 +12993,9 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
12755
12993
  remainderLabel: "Free"
12756
12994
  }
12757
12995
  ) }) : null,
12758
- limits && limits.length ? /* @__PURE__ */ (0, import_jsx_runtime94.jsxs)("section", { className: "fdc-usage-sec", children: [
12759
- /* @__PURE__ */ (0, import_jsx_runtime94.jsx)("h4", { className: "fdc-usage-h", children: "Usage limits" }),
12760
- /* @__PURE__ */ (0, import_jsx_runtime94.jsx)("div", { className: "fdc-usage-rows", children: limits.map((l) => /* @__PURE__ */ (0, import_jsx_runtime94.jsx)(
12996
+ limits && limits.length ? /* @__PURE__ */ (0, import_jsx_runtime95.jsxs)("section", { className: "fdc-usage-sec", children: [
12997
+ /* @__PURE__ */ (0, import_jsx_runtime95.jsx)("h4", { className: "fdc-usage-h", children: "Usage limits" }),
12998
+ /* @__PURE__ */ (0, import_jsx_runtime95.jsx)("div", { className: "fdc-usage-rows", children: limits.map((l) => /* @__PURE__ */ (0, import_jsx_runtime95.jsx)(
12761
12999
  QuotaRow,
12762
13000
  {
12763
13001
  label: l.label,
@@ -12767,25 +13005,25 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
12767
13005
  l.id
12768
13006
  )) })
12769
13007
  ] }) : null,
12770
- stats ? /* @__PURE__ */ (0, import_jsx_runtime94.jsxs)("section", { className: "fdc-usage-sec fdc-usage-stats", children: [
12771
- stats.elapsedMs ? /* @__PURE__ */ (0, import_jsx_runtime94.jsxs)("div", { children: [
12772
- /* @__PURE__ */ (0, import_jsx_runtime94.jsx)("span", { children: "Session" }),
12773
- /* @__PURE__ */ (0, import_jsx_runtime94.jsx)("b", { className: "fd-tabular", children: formatDuration(stats.elapsedMs) })
13008
+ stats ? /* @__PURE__ */ (0, import_jsx_runtime95.jsxs)("section", { className: "fdc-usage-sec fdc-usage-stats", children: [
13009
+ stats.elapsedMs ? /* @__PURE__ */ (0, import_jsx_runtime95.jsxs)("div", { children: [
13010
+ /* @__PURE__ */ (0, import_jsx_runtime95.jsx)("span", { children: "Session" }),
13011
+ /* @__PURE__ */ (0, import_jsx_runtime95.jsx)("b", { className: "fd-tabular", children: formatDuration(stats.elapsedMs) })
12774
13012
  ] }) : null,
12775
- stats.tokens ? /* @__PURE__ */ (0, import_jsx_runtime94.jsxs)("div", { children: [
12776
- /* @__PURE__ */ (0, import_jsx_runtime94.jsx)("span", { children: "Tokens" }),
12777
- /* @__PURE__ */ (0, import_jsx_runtime94.jsx)("b", { className: "fd-tabular", children: stats.tokens.toLocaleString() })
13013
+ stats.tokens ? /* @__PURE__ */ (0, import_jsx_runtime95.jsxs)("div", { children: [
13014
+ /* @__PURE__ */ (0, import_jsx_runtime95.jsx)("span", { children: "Tokens" }),
13015
+ /* @__PURE__ */ (0, import_jsx_runtime95.jsx)("b", { className: "fd-tabular", children: stats.tokens.toLocaleString() })
12778
13016
  ] }) : null,
12779
- stats.costUsd != null ? /* @__PURE__ */ (0, import_jsx_runtime94.jsxs)("div", { children: [
12780
- /* @__PURE__ */ (0, import_jsx_runtime94.jsx)("span", { children: "Cost" }),
12781
- /* @__PURE__ */ (0, import_jsx_runtime94.jsxs)("b", { className: "fd-tabular", children: [
13017
+ stats.costUsd != null ? /* @__PURE__ */ (0, import_jsx_runtime95.jsxs)("div", { children: [
13018
+ /* @__PURE__ */ (0, import_jsx_runtime95.jsx)("span", { children: "Cost" }),
13019
+ /* @__PURE__ */ (0, import_jsx_runtime95.jsxs)("b", { className: "fd-tabular", children: [
12782
13020
  "$",
12783
13021
  Number(stats.costUsd).toFixed(3)
12784
13022
  ] })
12785
13023
  ] }) : null,
12786
- stats.turns ? /* @__PURE__ */ (0, import_jsx_runtime94.jsxs)("div", { children: [
12787
- /* @__PURE__ */ (0, import_jsx_runtime94.jsx)("span", { children: "Turns" }),
12788
- /* @__PURE__ */ (0, import_jsx_runtime94.jsx)("b", { className: "fd-tabular", children: stats.turns })
13024
+ stats.turns ? /* @__PURE__ */ (0, import_jsx_runtime95.jsxs)("div", { children: [
13025
+ /* @__PURE__ */ (0, import_jsx_runtime95.jsx)("span", { children: "Turns" }),
13026
+ /* @__PURE__ */ (0, import_jsx_runtime95.jsx)("b", { className: "fd-tabular", children: stats.turns })
12789
13027
  ] }) : null
12790
13028
  ] }) : null
12791
13029
  ] })
@@ -12824,7 +13062,7 @@ function ModelControls({
12824
13062
  disabled: m.disabled,
12825
13063
  checked: m.id === (current2 && current2.id),
12826
13064
  meta: m.meta,
12827
- shortcut: m.shortcut ? /* @__PURE__ */ (0, import_jsx_runtime94.jsx)(KeyHint, { keys: m.shortcut, size: "sm" }) : void 0,
13065
+ shortcut: m.shortcut ? /* @__PURE__ */ (0, import_jsx_runtime95.jsx)(KeyHint, { keys: m.shortcut, size: "sm" }) : void 0,
12828
13066
  onSelect: () => onModelChange && onModelChange(m.id)
12829
13067
  });
12830
13068
  const items = [{ kind: "section", label: "Models" }].concat(flat.map(item));
@@ -12837,15 +13075,15 @@ function ModelControls({
12837
13075
  items.push({ kind: "section", label: "Fast mode" });
12838
13076
  items.push({
12839
13077
  kind: "custom",
12840
- render: () => /* @__PURE__ */ (0, import_jsx_runtime94.jsxs)("label", { className: "fdc-switchrow", children: [
12841
- /* @__PURE__ */ (0, import_jsx_runtime94.jsx)("span", { children: fastModeLabel }),
12842
- /* @__PURE__ */ (0, import_jsx_runtime94.jsx)("input", { type: "checkbox", className: "fd-sr", checked: !!fastMode, onChange: (e) => onFastModeChange(e.target.checked) }),
12843
- /* @__PURE__ */ (0, import_jsx_runtime94.jsx)("span", { className: "fd-switch-track" + (fastMode ? " is-on" : ""), "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime94.jsx)("span", { className: "fd-switch-thumb" }) })
13078
+ render: () => /* @__PURE__ */ (0, import_jsx_runtime95.jsxs)("label", { className: "fdc-switchrow", children: [
13079
+ /* @__PURE__ */ (0, import_jsx_runtime95.jsx)("span", { children: fastModeLabel }),
13080
+ /* @__PURE__ */ (0, import_jsx_runtime95.jsx)("input", { type: "checkbox", className: "fd-sr", checked: !!fastMode, onChange: (e) => onFastModeChange(e.target.checked) }),
13081
+ /* @__PURE__ */ (0, import_jsx_runtime95.jsx)("span", { className: "fd-switch-track" + (fastMode ? " is-on" : ""), "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime95.jsx)("span", { className: "fd-switch-thumb" }) })
12844
13082
  ] })
12845
13083
  });
12846
13084
  }
12847
- return /* @__PURE__ */ (0, import_jsx_runtime94.jsxs)(React62.Fragment, { children: [
12848
- /* @__PURE__ */ (0, import_jsx_runtime94.jsx)(
13085
+ return /* @__PURE__ */ (0, import_jsx_runtime95.jsxs)(React63.Fragment, { children: [
13086
+ /* @__PURE__ */ (0, import_jsx_runtime95.jsx)(
12849
13087
  MenuButton,
12850
13088
  {
12851
13089
  items,
@@ -12856,7 +13094,7 @@ function ModelControls({
12856
13094
  title: "Choose a model"
12857
13095
  }
12858
13096
  ),
12859
- effortLevels && effortLevels.length ? /* @__PURE__ */ (0, import_jsx_runtime94.jsx)(
13097
+ effortLevels && effortLevels.length ? /* @__PURE__ */ (0, import_jsx_runtime95.jsx)(
12860
13098
  MenuButton,
12861
13099
  {
12862
13100
  placement: "top-end",
@@ -12877,7 +13115,7 @@ function ModelControls({
12877
13115
  }
12878
13116
 
12879
13117
  // src/components/chat/AgentChatPanel.tsx
12880
- var import_jsx_runtime95 = require("react/jsx-runtime");
13118
+ var import_jsx_runtime96 = require("react/jsx-runtime");
12881
13119
  var SURFACES = { sidebar: "is-sidebar", inline: "is-inline", page: "is-page", modal: "is-modal", sheet: "is-sheet" };
12882
13120
  function AgentChatPanel({
12883
13121
  /* required */
@@ -12961,11 +13199,11 @@ function AgentChatPanel({
12961
13199
  onFeedback,
12962
13200
  onEditMessage
12963
13201
  }) {
12964
- const [panelWidth, setPanelWidth] = React63.useState(width);
12965
- const [applied, setApplied] = React63.useState({});
12966
- const [draft, setDraft] = React63.useState("");
12967
- const dragging = React63.useRef(null);
12968
- React63.useEffect(() => setPanelWidth(width), [width]);
13202
+ const [panelWidth, setPanelWidth] = React64.useState(width);
13203
+ const [applied, setApplied] = React64.useState({});
13204
+ const [draft, setDraft] = React64.useState("");
13205
+ const dragging = React64.useRef(null);
13206
+ React64.useEffect(() => setPanelWidth(width), [width]);
12969
13207
  const engine = useChatEngine({
12970
13208
  contextType,
12971
13209
  contextId,
@@ -13031,7 +13269,7 @@ function AgentChatPanel({
13031
13269
  onReconnect: engine.reload,
13032
13270
  deadTitle: "The assistant isn\u2019t reachable"
13033
13271
  };
13034
- const sessionBar = /* @__PURE__ */ (0, import_jsx_runtime95.jsx)(
13272
+ const sessionBar = /* @__PURE__ */ (0, import_jsx_runtime96.jsx)(
13035
13273
  ChatSessionBar,
13036
13274
  {
13037
13275
  sessionStats,
@@ -13040,7 +13278,7 @@ function AgentChatPanel({
13040
13278
  onClear: engine.visible.length ? engine.clear : void 0
13041
13279
  }
13042
13280
  );
13043
- const modelControls = /* @__PURE__ */ (0, import_jsx_runtime95.jsx)(
13281
+ const modelControls = /* @__PURE__ */ (0, import_jsx_runtime96.jsx)(
13044
13282
  ModelControls,
13045
13283
  {
13046
13284
  models,
@@ -13055,7 +13293,7 @@ function AgentChatPanel({
13055
13293
  narrow
13056
13294
  }
13057
13295
  );
13058
- const threadMenu = threads && threads.length ? /* @__PURE__ */ (0, import_jsx_runtime95.jsx)(
13296
+ const threadMenu = threads && threads.length ? /* @__PURE__ */ (0, import_jsx_runtime96.jsx)(
13059
13297
  MenuButton,
13060
13298
  {
13061
13299
  variant: "ghost",
@@ -13082,7 +13320,7 @@ function AgentChatPanel({
13082
13320
  })))
13083
13321
  }
13084
13322
  ) : null;
13085
- return /* @__PURE__ */ (0, import_jsx_runtime95.jsxs)(
13323
+ return /* @__PURE__ */ (0, import_jsx_runtime96.jsxs)(
13086
13324
  "aside",
13087
13325
  {
13088
13326
  className: ["fdc-panel", SURFACES[surface] || SURFACES.sidebar, narrow ? "is-narrow" : "", className].filter(Boolean).join(" "),
@@ -13093,7 +13331,7 @@ function AgentChatPanel({
13093
13331
  },
13094
13332
  "aria-label": title,
13095
13333
  children: [
13096
- surface === "sidebar" && resizable ? /* @__PURE__ */ (0, import_jsx_runtime95.jsx)(
13334
+ surface === "sidebar" && resizable ? /* @__PURE__ */ (0, import_jsx_runtime96.jsx)(
13097
13335
  "div",
13098
13336
  {
13099
13337
  className: "fdc-grip",
@@ -13108,20 +13346,20 @@ function AgentChatPanel({
13108
13346
  }
13109
13347
  }
13110
13348
  ) : null,
13111
- showHeader ? /* @__PURE__ */ (0, import_jsx_runtime95.jsxs)("header", { className: "fdc-head", children: [
13112
- /* @__PURE__ */ (0, import_jsx_runtime95.jsx)("span", { className: "fdc-head-mark", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime95.jsx)("i", { className: "ph ph-" + assistantIcon }) }),
13113
- /* @__PURE__ */ (0, import_jsx_runtime95.jsxs)("span", { className: "fdc-head-titles", children: [
13114
- /* @__PURE__ */ (0, import_jsx_runtime95.jsx)("span", { className: "fdc-head-title", title: truncationTitle(title), children: title }),
13115
- subtitle ? /* @__PURE__ */ (0, import_jsx_runtime95.jsx)("span", { className: "fdc-head-sub", title: truncationTitle(subtitle), children: subtitle }) : null
13349
+ showHeader ? /* @__PURE__ */ (0, import_jsx_runtime96.jsxs)("header", { className: "fdc-head", children: [
13350
+ /* @__PURE__ */ (0, import_jsx_runtime96.jsx)("span", { className: "fdc-head-mark", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime96.jsx)("i", { className: "ph ph-" + assistantIcon }) }),
13351
+ /* @__PURE__ */ (0, import_jsx_runtime96.jsxs)("span", { className: "fdc-head-titles", children: [
13352
+ /* @__PURE__ */ (0, import_jsx_runtime96.jsx)("span", { className: "fdc-head-title", title: truncationTitle(title), children: title }),
13353
+ subtitle ? /* @__PURE__ */ (0, import_jsx_runtime96.jsx)("span", { className: "fdc-head-sub", title: truncationTitle(subtitle), children: subtitle }) : null
13116
13354
  ] }),
13117
- /* @__PURE__ */ (0, import_jsx_runtime95.jsxs)("span", { className: "fdc-head-acts", children: [
13355
+ /* @__PURE__ */ (0, import_jsx_runtime96.jsxs)("span", { className: "fdc-head-acts", children: [
13118
13356
  headerActions,
13119
13357
  threadMenu,
13120
- onNewThread ? /* @__PURE__ */ (0, import_jsx_runtime95.jsx)("button", { type: "button", className: "fdc-iconbtn", onClick: onNewThread, "aria-label": "New conversation", title: "New conversation", children: /* @__PURE__ */ (0, import_jsx_runtime95.jsx)("i", { className: "ph ph-plus", "aria-hidden": "true" }) }) : null,
13121
- onClose ? /* @__PURE__ */ (0, import_jsx_runtime95.jsx)("button", { type: "button", className: "fdc-iconbtn", onClick: onClose, "aria-label": "Close panel", title: "Close", children: /* @__PURE__ */ (0, import_jsx_runtime95.jsx)("i", { className: "ph ph-x", "aria-hidden": "true" }) }) : null
13358
+ onNewThread ? /* @__PURE__ */ (0, import_jsx_runtime96.jsx)("button", { type: "button", className: "fdc-iconbtn", onClick: onNewThread, "aria-label": "New conversation", title: "New conversation", children: /* @__PURE__ */ (0, import_jsx_runtime96.jsx)("i", { className: "ph ph-plus", "aria-hidden": "true" }) }) : null,
13359
+ onClose ? /* @__PURE__ */ (0, import_jsx_runtime96.jsx)("button", { type: "button", className: "fdc-iconbtn", onClick: onClose, "aria-label": "Close panel", title: "Close", children: /* @__PURE__ */ (0, import_jsx_runtime96.jsx)("i", { className: "ph ph-x", "aria-hidden": "true" }) }) : null
13122
13360
  ] })
13123
13361
  ] }) : null,
13124
- /* @__PURE__ */ (0, import_jsx_runtime95.jsx)(
13362
+ /* @__PURE__ */ (0, import_jsx_runtime96.jsx)(
13125
13363
  ChatTranscript,
13126
13364
  {
13127
13365
  messages: engine.visible,
@@ -13136,7 +13374,7 @@ function AgentChatPanel({
13136
13374
  renderEmpty
13137
13375
  }
13138
13376
  ),
13139
- /* @__PURE__ */ (0, import_jsx_runtime95.jsx)(
13377
+ /* @__PURE__ */ (0, import_jsx_runtime96.jsx)(
13140
13378
  ChatComposer,
13141
13379
  {
13142
13380
  onSubmit: (text, atts) => engine.send(text, atts),
@@ -13169,8 +13407,8 @@ function AgentChatPanel({
13169
13407
  }
13170
13408
 
13171
13409
  // src/components/files/FileViewer.tsx
13172
- var React64 = __toESM(require("react"), 1);
13173
- var import_jsx_runtime96 = require("react/jsx-runtime");
13410
+ var React65 = __toESM(require("react"), 1);
13411
+ var import_jsx_runtime97 = require("react/jsx-runtime");
13174
13412
  function previewKindOf(file) {
13175
13413
  const mime = (file.mime || "").toLowerCase();
13176
13414
  const ext = extensionOf(file.name || "");
@@ -13226,13 +13464,13 @@ function parseDelimited(text, delimiter) {
13226
13464
  return rows;
13227
13465
  }
13228
13466
  function usePreview(file, kind, resolveUrl) {
13229
- const [state, setState] = React64.useState({ status: "loading" });
13230
- const [attempt, setAttempt] = React64.useState(0);
13231
- const resolveRef = React64.useRef(resolveUrl);
13232
- React64.useEffect(() => {
13467
+ const [state, setState] = React65.useState({ status: "loading" });
13468
+ const [attempt, setAttempt] = React65.useState(0);
13469
+ const resolveRef = React65.useRef(resolveUrl);
13470
+ React65.useEffect(() => {
13233
13471
  resolveRef.current = resolveUrl;
13234
13472
  }, [resolveUrl]);
13235
- React64.useEffect(() => {
13473
+ React65.useEffect(() => {
13236
13474
  if (kind === "none") {
13237
13475
  setState({ status: "ready" });
13238
13476
  return;
@@ -13262,19 +13500,19 @@ function usePreview(file, kind, resolveUrl) {
13262
13500
  if (ac) ac.abort();
13263
13501
  };
13264
13502
  }, [file.id, kind, attempt]);
13265
- return { ...state, retry: React64.useCallback(() => setAttempt((a) => a + 1), []) };
13503
+ return { ...state, retry: React65.useCallback(() => setAttempt((a) => a + 1), []) };
13266
13504
  }
13267
13505
  function PreviewBody({ file, kind, state }) {
13268
- if (kind === "image") return /* @__PURE__ */ (0, import_jsx_runtime96.jsx)("img", { className: "fd-fv-image", src: state.url, alt: file.name || "Preview" });
13269
- if (kind === "pdf") return /* @__PURE__ */ (0, import_jsx_runtime96.jsx)("iframe", { className: "fd-fv-pdf", src: state.url, title: file.name || "PDF preview" });
13270
- if (kind === "markdown") return /* @__PURE__ */ (0, import_jsx_runtime96.jsx)(Markdown, { className: "fd-fv-markdown", source: state.text || "" });
13506
+ if (kind === "image") return /* @__PURE__ */ (0, import_jsx_runtime97.jsx)("img", { className: "fd-fv-image", src: state.url, alt: file.name || "Preview" });
13507
+ if (kind === "pdf") return /* @__PURE__ */ (0, import_jsx_runtime97.jsx)("iframe", { className: "fd-fv-pdf", src: state.url, title: file.name || "PDF preview" });
13508
+ if (kind === "markdown") return /* @__PURE__ */ (0, import_jsx_runtime97.jsx)(Markdown, { className: "fd-fv-markdown", source: state.text || "" });
13271
13509
  if (kind === "json") {
13272
13510
  let pretty = state.text || "";
13273
13511
  try {
13274
13512
  pretty = JSON.stringify(JSON.parse(pretty), null, 2);
13275
13513
  } catch {
13276
13514
  }
13277
- return /* @__PURE__ */ (0, import_jsx_runtime96.jsx)(CodeBlock, { code: pretty, language: "json" });
13515
+ return /* @__PURE__ */ (0, import_jsx_runtime97.jsx)(CodeBlock, { code: pretty, language: "json" });
13278
13516
  }
13279
13517
  if (kind === "csv") {
13280
13518
  const tsv = extensionOf(file.name || "") === "tsv" || (file.mime || "").toLowerCase().includes("tab-separated");
@@ -13282,12 +13520,12 @@ function PreviewBody({ file, kind, state }) {
13282
13520
  const head = rows[0] || [];
13283
13521
  const dataRows = rows.slice(1);
13284
13522
  const shown = dataRows.slice(0, FILE_VIEWER_CSV_ROW_LIMIT);
13285
- return /* @__PURE__ */ (0, import_jsx_runtime96.jsxs)("div", { className: "fd-fv-csv", children: [
13286
- /* @__PURE__ */ (0, import_jsx_runtime96.jsxs)("table", { className: "fd-fv-csv-table", children: [
13287
- /* @__PURE__ */ (0, import_jsx_runtime96.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime96.jsx)("tr", { children: head.map((c, i) => /* @__PURE__ */ (0, import_jsx_runtime96.jsx)("th", { children: c }, i)) }) }),
13288
- /* @__PURE__ */ (0, import_jsx_runtime96.jsx)("tbody", { children: shown.map((r, ri) => /* @__PURE__ */ (0, import_jsx_runtime96.jsx)("tr", { children: head.map((_, ci) => /* @__PURE__ */ (0, import_jsx_runtime96.jsx)("td", { children: r[ci] ?? "" }, ci)) }, ri)) })
13523
+ return /* @__PURE__ */ (0, import_jsx_runtime97.jsxs)("div", { className: "fd-fv-csv", children: [
13524
+ /* @__PURE__ */ (0, import_jsx_runtime97.jsxs)("table", { className: "fd-fv-csv-table", children: [
13525
+ /* @__PURE__ */ (0, import_jsx_runtime97.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime97.jsx)("tr", { children: head.map((c, i) => /* @__PURE__ */ (0, import_jsx_runtime97.jsx)("th", { children: c }, i)) }) }),
13526
+ /* @__PURE__ */ (0, import_jsx_runtime97.jsx)("tbody", { children: shown.map((r, ri) => /* @__PURE__ */ (0, import_jsx_runtime97.jsx)("tr", { children: head.map((_, ci) => /* @__PURE__ */ (0, import_jsx_runtime97.jsx)("td", { children: r[ci] ?? "" }, ci)) }, ri)) })
13289
13527
  ] }),
13290
- dataRows.length > FILE_VIEWER_CSV_ROW_LIMIT ? /* @__PURE__ */ (0, import_jsx_runtime96.jsxs)("p", { className: "fd-fv-csv-note fd-body-sm fd-muted", children: [
13528
+ dataRows.length > FILE_VIEWER_CSV_ROW_LIMIT ? /* @__PURE__ */ (0, import_jsx_runtime97.jsxs)("p", { className: "fd-fv-csv-note fd-body-sm fd-muted", children: [
13291
13529
  "Showing the first ",
13292
13530
  FILE_VIEWER_CSV_ROW_LIMIT.toLocaleString(),
13293
13531
  " of ",
@@ -13296,24 +13534,24 @@ function PreviewBody({ file, kind, state }) {
13296
13534
  ] }) : null
13297
13535
  ] });
13298
13536
  }
13299
- if (kind === "text") return /* @__PURE__ */ (0, import_jsx_runtime96.jsx)(CodeBlock, { code: state.text || "", language: extensionOf(file.name || "") || void 0 });
13300
- return /* @__PURE__ */ (0, import_jsx_runtime96.jsxs)("div", { className: "fd-fv-fallback", children: [
13301
- /* @__PURE__ */ (0, import_jsx_runtime96.jsx)("span", { className: "fd-fv-fallback-icon", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime96.jsx)("i", { className: "ph ph-" + iconForMime(file.mime, file.name) }) }),
13302
- /* @__PURE__ */ (0, import_jsx_runtime96.jsx)("span", { className: "fd-fv-fallback-title", children: "No preview available" }),
13303
- /* @__PURE__ */ (0, import_jsx_runtime96.jsxs)("span", { className: "fd-fv-fallback-meta", children: [
13537
+ if (kind === "text") return /* @__PURE__ */ (0, import_jsx_runtime97.jsx)(CodeBlock, { code: state.text || "", language: extensionOf(file.name || "") || void 0 });
13538
+ return /* @__PURE__ */ (0, import_jsx_runtime97.jsxs)("div", { className: "fd-fv-fallback", children: [
13539
+ /* @__PURE__ */ (0, import_jsx_runtime97.jsx)("span", { className: "fd-fv-fallback-icon", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime97.jsx)("i", { className: "ph ph-" + iconForMime(file.mime, file.name) }) }),
13540
+ /* @__PURE__ */ (0, import_jsx_runtime97.jsx)("span", { className: "fd-fv-fallback-title", children: "No preview available" }),
13541
+ /* @__PURE__ */ (0, import_jsx_runtime97.jsxs)("span", { className: "fd-fv-fallback-meta", children: [
13304
13542
  file.mime || "Unknown type",
13305
13543
  file.size ? " \xB7 " + formatBytes(file.size) : ""
13306
13544
  ] })
13307
13545
  ] });
13308
13546
  }
13309
13547
  function FileViewer({ file, resolveUrl, sidePanel, sidePanelLabel = "Details", onClose, actions, className = "" }) {
13310
- const kind = React64.useMemo(() => previewKindOf(file), [file]);
13548
+ const kind = React65.useMemo(() => previewKindOf(file), [file]);
13311
13549
  const preview = usePreview(file, kind, resolveUrl);
13312
- const [tab, setTab] = React64.useState("preview");
13313
- const [downloading, setDownloading] = React64.useState(false);
13314
- const [downloadError, setDownloadError] = React64.useState(null);
13550
+ const [tab, setTab] = React65.useState("preview");
13551
+ const [downloading, setDownloading] = React65.useState(false);
13552
+ const [downloadError, setDownloadError] = React65.useState(null);
13315
13553
  const hasSide = sidePanel != null;
13316
- React64.useEffect(() => {
13554
+ React65.useEffect(() => {
13317
13555
  setTab("preview");
13318
13556
  }, [file.id]);
13319
13557
  const download = () => {
@@ -13329,29 +13567,29 @@ function FileViewer({ file, resolveUrl, sidePanel, sidePanelLabel = "Details", o
13329
13567
  a.remove();
13330
13568
  }).catch((err) => setDownloadError(err && err.message || "Download failed.")).finally(() => setDownloading(false));
13331
13569
  };
13332
- return /* @__PURE__ */ (0, import_jsx_runtime96.jsxs)(
13570
+ return /* @__PURE__ */ (0, import_jsx_runtime97.jsxs)(
13333
13571
  "section",
13334
13572
  {
13335
13573
  className: ["fd-fv", hasSide && tab === "side" ? "is-tab-side" : "is-tab-preview", className].filter(Boolean).join(" "),
13336
13574
  "aria-label": file.name || "File",
13337
13575
  children: [
13338
- /* @__PURE__ */ (0, import_jsx_runtime96.jsxs)("header", { className: "fd-fv-head", children: [
13339
- /* @__PURE__ */ (0, import_jsx_runtime96.jsx)("span", { className: "fd-fv-head-icon", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime96.jsx)("i", { className: "ph ph-" + iconForMime(file.mime, file.name) }) }),
13340
- /* @__PURE__ */ (0, import_jsx_runtime96.jsxs)("span", { className: "fd-fv-head-titles", children: [
13341
- /* @__PURE__ */ (0, import_jsx_runtime96.jsx)("span", { className: "fd-fv-head-title", title: file.name, children: file.name }),
13342
- /* @__PURE__ */ (0, import_jsx_runtime96.jsxs)("span", { className: "fd-fv-head-meta", children: [
13576
+ /* @__PURE__ */ (0, import_jsx_runtime97.jsxs)("header", { className: "fd-fv-head", children: [
13577
+ /* @__PURE__ */ (0, import_jsx_runtime97.jsx)("span", { className: "fd-fv-head-icon", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime97.jsx)("i", { className: "ph ph-" + iconForMime(file.mime, file.name) }) }),
13578
+ /* @__PURE__ */ (0, import_jsx_runtime97.jsxs)("span", { className: "fd-fv-head-titles", children: [
13579
+ /* @__PURE__ */ (0, import_jsx_runtime97.jsx)("span", { className: "fd-fv-head-title", title: file.name, children: file.name }),
13580
+ /* @__PURE__ */ (0, import_jsx_runtime97.jsxs)("span", { className: "fd-fv-head-meta", children: [
13343
13581
  file.mime || "Unknown type",
13344
13582
  file.size ? " \xB7 " + formatBytes(file.size) : ""
13345
13583
  ] })
13346
13584
  ] }),
13347
- /* @__PURE__ */ (0, import_jsx_runtime96.jsxs)("span", { className: "fd-fv-head-actions", children: [
13585
+ /* @__PURE__ */ (0, import_jsx_runtime97.jsxs)("span", { className: "fd-fv-head-actions", children: [
13348
13586
  actions,
13349
- /* @__PURE__ */ (0, import_jsx_runtime96.jsx)(Button, { variant: "secondary", size: "sm", icon: "download-simple", loading: downloading, onClick: download, children: "Download" }),
13350
- onClose ? /* @__PURE__ */ (0, import_jsx_runtime96.jsx)(IconButton, { icon: "x", label: "Close", onClick: onClose }) : null
13587
+ /* @__PURE__ */ (0, import_jsx_runtime97.jsx)(Button, { variant: "secondary", size: "sm", icon: "download-simple", loading: downloading, onClick: download, children: "Download" }),
13588
+ onClose ? /* @__PURE__ */ (0, import_jsx_runtime97.jsx)(IconButton, { icon: "x", label: "Close", onClick: onClose }) : null
13351
13589
  ] })
13352
13590
  ] }),
13353
- downloadError ? /* @__PURE__ */ (0, import_jsx_runtime96.jsx)("div", { className: "fd-fv-download-error", role: "alert", children: downloadError }) : null,
13354
- hasSide ? /* @__PURE__ */ (0, import_jsx_runtime96.jsx)(
13591
+ downloadError ? /* @__PURE__ */ (0, import_jsx_runtime97.jsx)("div", { className: "fd-fv-download-error", role: "alert", children: downloadError }) : null,
13592
+ hasSide ? /* @__PURE__ */ (0, import_jsx_runtime97.jsx)(
13355
13593
  Tabs,
13356
13594
  {
13357
13595
  className: "fd-fv-tabs",
@@ -13360,19 +13598,19 @@ function FileViewer({ file, resolveUrl, sidePanel, sidePanelLabel = "Details", o
13360
13598
  onChange: (v) => setTab(v)
13361
13599
  }
13362
13600
  ) : null,
13363
- /* @__PURE__ */ (0, import_jsx_runtime96.jsxs)("div", { className: "fd-fv-body", children: [
13364
- /* @__PURE__ */ (0, import_jsx_runtime96.jsx)("div", { className: "fd-fv-preview", role: "region", "aria-label": "Preview of " + (file.name || "file"), children: /* @__PURE__ */ (0, import_jsx_runtime96.jsx)(
13601
+ /* @__PURE__ */ (0, import_jsx_runtime97.jsxs)("div", { className: "fd-fv-body", children: [
13602
+ /* @__PURE__ */ (0, import_jsx_runtime97.jsx)("div", { className: "fd-fv-preview", role: "region", "aria-label": "Preview of " + (file.name || "file"), children: /* @__PURE__ */ (0, import_jsx_runtime97.jsx)(
13365
13603
  LoadingRegion,
13366
13604
  {
13367
13605
  state: preview.status === "loading" ? "loading" : preview.status === "error" ? "error" : "ready",
13368
13606
  error: preview.error,
13369
13607
  label: "Loading preview of " + (file.name || "file"),
13370
13608
  onRetry: preview.status === "error" ? preview.retry : void 0,
13371
- skeleton: /* @__PURE__ */ (0, import_jsx_runtime96.jsx)(Skeleton, { shape: "card", h: 220 }),
13372
- children: /* @__PURE__ */ (0, import_jsx_runtime96.jsx)(PreviewBody, { file, kind, state: preview })
13609
+ skeleton: /* @__PURE__ */ (0, import_jsx_runtime97.jsx)(Skeleton, { shape: "card", h: 220 }),
13610
+ children: /* @__PURE__ */ (0, import_jsx_runtime97.jsx)(PreviewBody, { file, kind, state: preview })
13373
13611
  }
13374
13612
  ) }),
13375
- hasSide ? /* @__PURE__ */ (0, import_jsx_runtime96.jsx)("div", { className: "fd-fv-side", role: "region", "aria-label": sidePanelLabel, children: sidePanel }) : null
13613
+ hasSide ? /* @__PURE__ */ (0, import_jsx_runtime97.jsx)("div", { className: "fd-fv-side", role: "region", "aria-label": sidePanelLabel, children: sidePanel }) : null
13376
13614
  ] })
13377
13615
  ]
13378
13616
  }
@@ -13380,8 +13618,8 @@ function FileViewer({ file, resolveUrl, sidePanel, sidePanelLabel = "Details", o
13380
13618
  }
13381
13619
 
13382
13620
  // src/components/files/FileBrowser.tsx
13383
- var React65 = __toESM(require("react"), 1);
13384
- var import_jsx_runtime97 = require("react/jsx-runtime");
13621
+ var React66 = __toESM(require("react"), 1);
13622
+ var import_jsx_runtime98 = require("react/jsx-runtime");
13385
13623
  function childrenOf(folders, parentId) {
13386
13624
  return folders.filter((f) => f.parentId === parentId).sort((a, b) => a.name.localeCompare(b.name));
13387
13625
  }
@@ -13453,8 +13691,8 @@ function FolderPickerMenu({
13453
13691
  }) {
13454
13692
  const panel = useInlinePanel();
13455
13693
  const { open: open2, setOpen, ref, zIndex } = panel;
13456
- return /* @__PURE__ */ (0, import_jsx_runtime97.jsxs)("span", { className: "fd-fb-menu-anchor", ref, children: [
13457
- /* @__PURE__ */ (0, import_jsx_runtime97.jsx)(
13694
+ return /* @__PURE__ */ (0, import_jsx_runtime98.jsxs)("span", { className: "fd-fb-menu-anchor", ref, children: [
13695
+ /* @__PURE__ */ (0, import_jsx_runtime98.jsx)(
13458
13696
  IconButton,
13459
13697
  {
13460
13698
  icon: "arrows-out-cardinal",
@@ -13466,9 +13704,9 @@ function FolderPickerMenu({
13466
13704
  onClick: () => setOpen((v) => !v)
13467
13705
  }
13468
13706
  ),
13469
- open2 ? /* @__PURE__ */ (0, import_jsx_runtime97.jsx)(InlinePanelLayers, { panel, children: /* @__PURE__ */ (0, import_jsx_runtime97.jsxs)("div", { className: "fd-fb-menu", role: "menu", "aria-label": label, style: { zIndex }, children: [
13470
- /* @__PURE__ */ (0, import_jsx_runtime97.jsx)("span", { className: "fd-overline fd-muted fd-fb-menu-title", children: "Move to\u2026" }),
13471
- destinations.map((d) => /* @__PURE__ */ (0, import_jsx_runtime97.jsxs)(
13707
+ open2 ? /* @__PURE__ */ (0, import_jsx_runtime98.jsx)(InlinePanelLayers, { panel, children: /* @__PURE__ */ (0, import_jsx_runtime98.jsxs)("div", { className: "fd-fb-menu", role: "menu", "aria-label": label, style: { zIndex }, children: [
13708
+ /* @__PURE__ */ (0, import_jsx_runtime98.jsx)("span", { className: "fd-overline fd-muted fd-fb-menu-title", children: "Move to\u2026" }),
13709
+ destinations.map((d) => /* @__PURE__ */ (0, import_jsx_runtime98.jsxs)(
13472
13710
  "button",
13473
13711
  {
13474
13712
  type: "button",
@@ -13480,7 +13718,7 @@ function FolderPickerMenu({
13480
13718
  setOpen(false);
13481
13719
  },
13482
13720
  children: [
13483
- /* @__PURE__ */ (0, import_jsx_runtime97.jsx)("i", { className: "ph ph-" + (d.id == null ? "house-simple" : "folder-simple"), "aria-hidden": "true" }),
13721
+ /* @__PURE__ */ (0, import_jsx_runtime98.jsx)("i", { className: "ph ph-" + (d.id == null ? "house-simple" : "folder-simple"), "aria-hidden": "true" }),
13484
13722
  d.name
13485
13723
  ]
13486
13724
  },
@@ -13490,8 +13728,8 @@ function FolderPickerMenu({
13490
13728
  ] });
13491
13729
  }
13492
13730
  function RowShell({ icon, name, meta, onOpen, draggableId, isDropTarget, onDropPayload, actions, className = "" }) {
13493
- const [over, setOver] = React65.useState(false);
13494
- const dragCounter = React65.useRef(0);
13731
+ const [over, setOver] = React66.useState(false);
13732
+ const dragCounter = React66.useRef(0);
13495
13733
  const dropHandlers = isDropTarget ? {
13496
13734
  onDragEnter: (e) => {
13497
13735
  if (!hasInternalPayload(e)) return;
@@ -13516,8 +13754,8 @@ function RowShell({ icon, name, meta, onOpen, draggableId, isDropTarget, onDropP
13516
13754
  if (payload && onDropPayload) onDropPayload(payload);
13517
13755
  }
13518
13756
  } : {};
13519
- return /* @__PURE__ */ (0, import_jsx_runtime97.jsxs)("div", { className: ["fd-fb-row", over ? "is-drop-target" : "", className].filter(Boolean).join(" "), ...dropHandlers, children: [
13520
- /* @__PURE__ */ (0, import_jsx_runtime97.jsxs)(
13757
+ return /* @__PURE__ */ (0, import_jsx_runtime98.jsxs)("div", { className: ["fd-fb-row", over ? "is-drop-target" : "", className].filter(Boolean).join(" "), ...dropHandlers, children: [
13758
+ /* @__PURE__ */ (0, import_jsx_runtime98.jsxs)(
13521
13759
  "button",
13522
13760
  {
13523
13761
  type: "button",
@@ -13526,26 +13764,26 @@ function RowShell({ icon, name, meta, onOpen, draggableId, isDropTarget, onDropP
13526
13764
  draggable: !!draggableId,
13527
13765
  onDragStart: draggableId ? (e) => writeDragPayload(e, draggableId) : void 0,
13528
13766
  children: [
13529
- /* @__PURE__ */ (0, import_jsx_runtime97.jsx)("span", { className: "fd-fb-row-icon", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime97.jsx)("i", { className: "ph ph-" + icon }) }),
13530
- /* @__PURE__ */ (0, import_jsx_runtime97.jsxs)("span", { className: "fd-fb-row-text", children: [
13531
- /* @__PURE__ */ (0, import_jsx_runtime97.jsx)("span", { className: "fd-fb-row-name", title: name, children: name }),
13532
- meta ? /* @__PURE__ */ (0, import_jsx_runtime97.jsx)("span", { className: "fd-fb-row-meta", children: meta }) : null
13767
+ /* @__PURE__ */ (0, import_jsx_runtime98.jsx)("span", { className: "fd-fb-row-icon", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime98.jsx)("i", { className: "ph ph-" + icon }) }),
13768
+ /* @__PURE__ */ (0, import_jsx_runtime98.jsxs)("span", { className: "fd-fb-row-text", children: [
13769
+ /* @__PURE__ */ (0, import_jsx_runtime98.jsx)("span", { className: "fd-fb-row-name", title: name, children: name }),
13770
+ meta ? /* @__PURE__ */ (0, import_jsx_runtime98.jsx)("span", { className: "fd-fb-row-meta", children: meta }) : null
13533
13771
  ] })
13534
13772
  ]
13535
13773
  }
13536
13774
  ),
13537
- actions ? /* @__PURE__ */ (0, import_jsx_runtime97.jsx)("span", { className: "fd-fb-row-actions", children: actions }) : null
13775
+ actions ? /* @__PURE__ */ (0, import_jsx_runtime98.jsx)("span", { className: "fd-fb-row-actions", children: actions }) : null
13538
13776
  ] });
13539
13777
  }
13540
13778
  function TreeNode({ folder, depth, folders, currentFolderId, onNavigate, onMoveInto, canMove }) {
13541
13779
  const kids = childrenOf(folders, folder.id);
13542
- const [expanded, setExpanded] = React65.useState(() => currentFolderId != null && isSelfOrDescendant(folders, folder.id, currentFolderId));
13543
- React65.useEffect(() => {
13780
+ const [expanded, setExpanded] = React66.useState(() => currentFolderId != null && isSelfOrDescendant(folders, folder.id, currentFolderId));
13781
+ React66.useEffect(() => {
13544
13782
  if (currentFolderId != null && isSelfOrDescendant(folders, folder.id, currentFolderId)) setExpanded(true);
13545
13783
  }, [currentFolderId, folder.id, folders]);
13546
13784
  const isCurrent = folder.id === currentFolderId;
13547
- return /* @__PURE__ */ (0, import_jsx_runtime97.jsxs)("div", { className: "fd-fb-tree-node", children: [
13548
- /* @__PURE__ */ (0, import_jsx_runtime97.jsx)(
13785
+ return /* @__PURE__ */ (0, import_jsx_runtime98.jsxs)("div", { className: "fd-fb-tree-node", children: [
13786
+ /* @__PURE__ */ (0, import_jsx_runtime98.jsx)(
13549
13787
  RowShell,
13550
13788
  {
13551
13789
  icon: folder.id === currentFolderId ? "folder-open" : "folder-simple",
@@ -13555,7 +13793,7 @@ function TreeNode({ folder, depth, folders, currentFolderId, onNavigate, onMoveI
13555
13793
  isDropTarget: canMove,
13556
13794
  onDropPayload: (payload) => onMoveInto(payload, folder.id),
13557
13795
  className: ["fd-fb-tree-row", isCurrent ? "is-current" : ""].filter(Boolean).join(" "),
13558
- actions: kids.length ? /* @__PURE__ */ (0, import_jsx_runtime97.jsx)(
13796
+ actions: kids.length ? /* @__PURE__ */ (0, import_jsx_runtime98.jsx)(
13559
13797
  IconButton,
13560
13798
  {
13561
13799
  icon: expanded ? "caret-down" : "caret-right",
@@ -13567,7 +13805,7 @@ function TreeNode({ folder, depth, folders, currentFolderId, onNavigate, onMoveI
13567
13805
  ) : void 0
13568
13806
  }
13569
13807
  ),
13570
- expanded && kids.length ? /* @__PURE__ */ (0, import_jsx_runtime97.jsx)("div", { className: "fd-fb-tree-children", style: { paddingLeft: 14 }, children: kids.map((k) => /* @__PURE__ */ (0, import_jsx_runtime97.jsx)(
13808
+ expanded && kids.length ? /* @__PURE__ */ (0, import_jsx_runtime98.jsx)("div", { className: "fd-fb-tree-children", style: { paddingLeft: 14 }, children: kids.map((k) => /* @__PURE__ */ (0, import_jsx_runtime98.jsx)(
13571
13809
  TreeNode,
13572
13810
  {
13573
13811
  folder: k,
@@ -13606,15 +13844,15 @@ function FileBrowser({
13606
13844
  const canUpload = perm.canUpload !== false && !!onUpload;
13607
13845
  const canRemoveFile = perm.canRemoveFile !== false && !!onRemoveFile;
13608
13846
  const canDeleteFolder = perm.canDeleteFolder !== false && !!onDeleteFolder;
13609
- const [createOpen, setCreateOpen] = React65.useState(false);
13610
- const [createName, setCreateName] = React65.useState("");
13611
- const [renameTarget, setRenameTarget] = React65.useState(null);
13612
- const [renameValue, setRenameValue] = React65.useState("");
13613
- const [deleteTarget, setDeleteTarget] = React65.useState(null);
13614
- const uploadInputRef = React65.useRef(null);
13615
- const crumbFolders = React65.useMemo(() => ancestorsOf(folders, currentFolderId), [folders, currentFolderId]);
13616
- const subfolders = React65.useMemo(() => childrenOf(folders, currentFolderId), [folders, currentFolderId]);
13617
- const currentFiles = React65.useMemo(
13847
+ const [createOpen, setCreateOpen] = React66.useState(false);
13848
+ const [createName, setCreateName] = React66.useState("");
13849
+ const [renameTarget, setRenameTarget] = React66.useState(null);
13850
+ const [renameValue, setRenameValue] = React66.useState("");
13851
+ const [deleteTarget, setDeleteTarget] = React66.useState(null);
13852
+ const uploadInputRef = React66.useRef(null);
13853
+ const crumbFolders = React66.useMemo(() => ancestorsOf(folders, currentFolderId), [folders, currentFolderId]);
13854
+ const subfolders = React66.useMemo(() => childrenOf(folders, currentFolderId), [folders, currentFolderId]);
13855
+ const currentFiles = React66.useMemo(
13618
13856
  () => files.filter((f) => f.folderId === currentFolderId).sort((a, b) => a.name.localeCompare(b.name)),
13619
13857
  [files, currentFolderId]
13620
13858
  );
@@ -13653,10 +13891,10 @@ function FileBrowser({
13653
13891
  if (deleteTarget && onDeleteFolder) onDeleteFolder(deleteTarget);
13654
13892
  setDeleteTarget(null);
13655
13893
  };
13656
- const content = /* @__PURE__ */ (0, import_jsx_runtime97.jsxs)("div", { className: ["fd-fb", className].filter(Boolean).join(" "), children: [
13657
- /* @__PURE__ */ (0, import_jsx_runtime97.jsxs)("div", { className: "fd-fb-head", children: [
13658
- /* @__PURE__ */ (0, import_jsx_runtime97.jsxs)("nav", { className: "fd-fb-crumbs", "aria-label": "Folder path", children: [
13659
- /* @__PURE__ */ (0, import_jsx_runtime97.jsx)(
13894
+ const content = /* @__PURE__ */ (0, import_jsx_runtime98.jsxs)("div", { className: ["fd-fb", className].filter(Boolean).join(" "), children: [
13895
+ /* @__PURE__ */ (0, import_jsx_runtime98.jsxs)("div", { className: "fd-fb-head", children: [
13896
+ /* @__PURE__ */ (0, import_jsx_runtime98.jsxs)("nav", { className: "fd-fb-crumbs", "aria-label": "Folder path", children: [
13897
+ /* @__PURE__ */ (0, import_jsx_runtime98.jsx)(
13660
13898
  BreadcrumbCrumb,
13661
13899
  {
13662
13900
  label: "Home",
@@ -13666,7 +13904,7 @@ function FileBrowser({
13666
13904
  onDropPayload: (p) => moveIntoFolder(p, null)
13667
13905
  }
13668
13906
  ),
13669
- crumbFolders.map((f, i) => /* @__PURE__ */ (0, import_jsx_runtime97.jsx)(
13907
+ crumbFolders.map((f, i) => /* @__PURE__ */ (0, import_jsx_runtime98.jsx)(
13670
13908
  BreadcrumbCrumb,
13671
13909
  {
13672
13910
  label: f.name,
@@ -13678,11 +13916,11 @@ function FileBrowser({
13678
13916
  f.id
13679
13917
  ))
13680
13918
  ] }),
13681
- /* @__PURE__ */ (0, import_jsx_runtime97.jsxs)("span", { className: "fd-fb-actions", children: [
13682
- canCreateFolder ? /* @__PURE__ */ (0, import_jsx_runtime97.jsx)(Button, { variant: "secondary", size: "sm", icon: "folder-simple-plus", onClick: openCreate, children: "New folder" }) : null,
13683
- canUpload ? /* @__PURE__ */ (0, import_jsx_runtime97.jsxs)(import_jsx_runtime97.Fragment, { children: [
13684
- /* @__PURE__ */ (0, import_jsx_runtime97.jsx)(Button, { variant: "secondary", size: "sm", icon: "upload-simple", onClick: () => uploadInputRef.current && uploadInputRef.current.click(), children: "Upload" }),
13685
- /* @__PURE__ */ (0, import_jsx_runtime97.jsx)(
13919
+ /* @__PURE__ */ (0, import_jsx_runtime98.jsxs)("span", { className: "fd-fb-actions", children: [
13920
+ canCreateFolder ? /* @__PURE__ */ (0, import_jsx_runtime98.jsx)(Button, { variant: "secondary", size: "sm", icon: "folder-simple-plus", onClick: openCreate, children: "New folder" }) : null,
13921
+ canUpload ? /* @__PURE__ */ (0, import_jsx_runtime98.jsxs)(import_jsx_runtime98.Fragment, { children: [
13922
+ /* @__PURE__ */ (0, import_jsx_runtime98.jsx)(Button, { variant: "secondary", size: "sm", icon: "upload-simple", onClick: () => uploadInputRef.current && uploadInputRef.current.click(), children: "Upload" }),
13923
+ /* @__PURE__ */ (0, import_jsx_runtime98.jsx)(
13686
13924
  "input",
13687
13925
  {
13688
13926
  ref: uploadInputRef,
@@ -13700,9 +13938,9 @@ function FileBrowser({
13700
13938
  ] }) : null
13701
13939
  ] })
13702
13940
  ] }),
13703
- /* @__PURE__ */ (0, import_jsx_runtime97.jsxs)("div", { className: "fd-fb-body", children: [
13704
- /* @__PURE__ */ (0, import_jsx_runtime97.jsxs)("div", { className: "fd-fb-tree", role: "region", "aria-label": "Folder tree", children: [
13705
- /* @__PURE__ */ (0, import_jsx_runtime97.jsx)(
13941
+ /* @__PURE__ */ (0, import_jsx_runtime98.jsxs)("div", { className: "fd-fb-body", children: [
13942
+ /* @__PURE__ */ (0, import_jsx_runtime98.jsxs)("div", { className: "fd-fb-tree", role: "region", "aria-label": "Folder tree", children: [
13943
+ /* @__PURE__ */ (0, import_jsx_runtime98.jsx)(
13706
13944
  RowShell,
13707
13945
  {
13708
13946
  icon: "house-simple",
@@ -13713,7 +13951,7 @@ function FileBrowser({
13713
13951
  className: ["fd-fb-tree-row", currentFolderId == null ? "is-current" : ""].filter(Boolean).join(" ")
13714
13952
  }
13715
13953
  ),
13716
- childrenOf(folders, null).map((f) => /* @__PURE__ */ (0, import_jsx_runtime97.jsx)(
13954
+ childrenOf(folders, null).map((f) => /* @__PURE__ */ (0, import_jsx_runtime98.jsx)(
13717
13955
  TreeNode,
13718
13956
  {
13719
13957
  folder: f,
@@ -13727,18 +13965,18 @@ function FileBrowser({
13727
13965
  f.id
13728
13966
  ))
13729
13967
  ] }),
13730
- /* @__PURE__ */ (0, import_jsx_runtime97.jsx)("div", { className: "fd-fb-main", role: "region", "aria-label": "Folder contents", children: /* @__PURE__ */ (0, import_jsx_runtime97.jsx)(
13968
+ /* @__PURE__ */ (0, import_jsx_runtime98.jsx)("div", { className: "fd-fb-main", role: "region", "aria-label": "Folder contents", children: /* @__PURE__ */ (0, import_jsx_runtime98.jsx)(
13731
13969
  LoadingRegion,
13732
13970
  {
13733
13971
  state: loading ? "loading" : "ready",
13734
13972
  label: "Loading folder contents",
13735
- skeleton: /* @__PURE__ */ (0, import_jsx_runtime97.jsxs)("div", { className: "fd-stack", style: { gap: 8, padding: 12 }, children: [
13736
- /* @__PURE__ */ (0, import_jsx_runtime97.jsx)(Skeleton, { h: 44, radius: "10px" }),
13737
- /* @__PURE__ */ (0, import_jsx_runtime97.jsx)(Skeleton, { h: 44, radius: "10px" }),
13738
- /* @__PURE__ */ (0, import_jsx_runtime97.jsx)(Skeleton, { h: 44, radius: "10px" })
13973
+ skeleton: /* @__PURE__ */ (0, import_jsx_runtime98.jsxs)("div", { className: "fd-stack", style: { gap: 8, padding: 12 }, children: [
13974
+ /* @__PURE__ */ (0, import_jsx_runtime98.jsx)(Skeleton, { h: 44, radius: "10px" }),
13975
+ /* @__PURE__ */ (0, import_jsx_runtime98.jsx)(Skeleton, { h: 44, radius: "10px" }),
13976
+ /* @__PURE__ */ (0, import_jsx_runtime98.jsx)(Skeleton, { h: 44, radius: "10px" })
13739
13977
  ] }),
13740
- children: isEmpty ? /* @__PURE__ */ (0, import_jsx_runtime97.jsx)(EmptyState, { icon: "folder-open", title: "This folder is empty", children: canUpload ? "Drop files here, or use Upload above." : "Nothing has been filed here yet." }) : /* @__PURE__ */ (0, import_jsx_runtime97.jsxs)("div", { className: "fd-fb-list", children: [
13741
- subfolders.map((f) => /* @__PURE__ */ (0, import_jsx_runtime97.jsx)(
13978
+ children: isEmpty ? /* @__PURE__ */ (0, import_jsx_runtime98.jsx)(EmptyState, { icon: "folder-open", title: "This folder is empty", children: canUpload ? "Drop files here, or use Upload above." : "Nothing has been filed here yet." }) : /* @__PURE__ */ (0, import_jsx_runtime98.jsxs)("div", { className: "fd-fb-list", children: [
13979
+ subfolders.map((f) => /* @__PURE__ */ (0, import_jsx_runtime98.jsx)(
13742
13980
  RowShell,
13743
13981
  {
13744
13982
  icon: "folder-simple",
@@ -13747,9 +13985,9 @@ function FileBrowser({
13747
13985
  draggableId: canMove ? { kind: "folder", id: f.id } : void 0,
13748
13986
  isDropTarget: canMove,
13749
13987
  onDropPayload: (p) => moveIntoFolder(p, f.id),
13750
- actions: /* @__PURE__ */ (0, import_jsx_runtime97.jsxs)(import_jsx_runtime97.Fragment, { children: [
13751
- canRenameFolder ? /* @__PURE__ */ (0, import_jsx_runtime97.jsx)(IconButton, { icon: "pencil-simple", label: "Rename " + f.name, size: "sm", variant: "ghost", onClick: () => openRename(f) }) : null,
13752
- canMove ? /* @__PURE__ */ (0, import_jsx_runtime97.jsx)(
13988
+ actions: /* @__PURE__ */ (0, import_jsx_runtime98.jsxs)(import_jsx_runtime98.Fragment, { children: [
13989
+ canRenameFolder ? /* @__PURE__ */ (0, import_jsx_runtime98.jsx)(IconButton, { icon: "pencil-simple", label: "Rename " + f.name, size: "sm", variant: "ghost", onClick: () => openRename(f) }) : null,
13990
+ canMove ? /* @__PURE__ */ (0, import_jsx_runtime98.jsx)(
13753
13991
  FolderPickerMenu,
13754
13992
  {
13755
13993
  label: "Move " + f.name,
@@ -13757,12 +13995,12 @@ function FileBrowser({
13757
13995
  onPick: (target) => moveIntoFolder({ kind: "folder", id: f.id }, target)
13758
13996
  }
13759
13997
  ) : null,
13760
- canDeleteFolder ? /* @__PURE__ */ (0, import_jsx_runtime97.jsx)(IconButton, { icon: "trash-simple", label: "Delete " + f.name, size: "sm", variant: "ghost", onClick: () => openDelete(f) }) : null
13998
+ canDeleteFolder ? /* @__PURE__ */ (0, import_jsx_runtime98.jsx)(IconButton, { icon: "trash-simple", label: "Delete " + f.name, size: "sm", variant: "ghost", onClick: () => openDelete(f) }) : null
13761
13999
  ] })
13762
14000
  },
13763
14001
  f.id
13764
14002
  )),
13765
- currentFiles.map((file) => /* @__PURE__ */ (0, import_jsx_runtime97.jsx)(
14003
+ currentFiles.map((file) => /* @__PURE__ */ (0, import_jsx_runtime98.jsx)(
13766
14004
  RowShell,
13767
14005
  {
13768
14006
  icon: iconForMime(file.mime, file.name),
@@ -13770,8 +14008,8 @@ function FileBrowser({
13770
14008
  meta: file.size ? formatBytes(file.size) : void 0,
13771
14009
  onOpen: onOpenFile ? () => onOpenFile(file) : void 0,
13772
14010
  draggableId: canMove ? { kind: "file", id: file.id } : void 0,
13773
- actions: /* @__PURE__ */ (0, import_jsx_runtime97.jsxs)(import_jsx_runtime97.Fragment, { children: [
13774
- canMove ? /* @__PURE__ */ (0, import_jsx_runtime97.jsx)(
14011
+ actions: /* @__PURE__ */ (0, import_jsx_runtime98.jsxs)(import_jsx_runtime98.Fragment, { children: [
14012
+ canMove ? /* @__PURE__ */ (0, import_jsx_runtime98.jsx)(
13775
14013
  FolderPickerMenu,
13776
14014
  {
13777
14015
  label: "Move " + file.name,
@@ -13779,7 +14017,7 @@ function FileBrowser({
13779
14017
  onPick: (target) => onMoveFile && onMoveFile(file.id, target)
13780
14018
  }
13781
14019
  ) : null,
13782
- canRemoveFile ? /* @__PURE__ */ (0, import_jsx_runtime97.jsx)(IconButton, { icon: "trash-simple", label: "Remove " + file.name, size: "sm", variant: "ghost", onClick: () => onRemoveFile && onRemoveFile(file) }) : null
14020
+ canRemoveFile ? /* @__PURE__ */ (0, import_jsx_runtime98.jsx)(IconButton, { icon: "trash-simple", label: "Remove " + file.name, size: "sm", variant: "ghost", onClick: () => onRemoveFile && onRemoveFile(file) }) : null
13783
14021
  ] })
13784
14022
  },
13785
14023
  file.id
@@ -13788,10 +14026,10 @@ function FileBrowser({
13788
14026
  }
13789
14027
  ) })
13790
14028
  ] }),
13791
- /* @__PURE__ */ (0, import_jsx_runtime97.jsx)(Modal, { open: createOpen, title: "New folder", onClose: () => setCreateOpen(false), footer: /* @__PURE__ */ (0, import_jsx_runtime97.jsxs)(import_jsx_runtime97.Fragment, { children: [
13792
- /* @__PURE__ */ (0, import_jsx_runtime97.jsx)(Button, { variant: "secondary", onClick: () => setCreateOpen(false), children: "Cancel" }),
13793
- /* @__PURE__ */ (0, import_jsx_runtime97.jsx)(Button, { onClick: submitCreate, disabled: !createName.trim(), children: "Create" })
13794
- ] }), children: /* @__PURE__ */ (0, import_jsx_runtime97.jsx)(
14029
+ /* @__PURE__ */ (0, import_jsx_runtime98.jsx)(Modal, { open: createOpen, title: "New folder", onClose: () => setCreateOpen(false), footer: /* @__PURE__ */ (0, import_jsx_runtime98.jsxs)(import_jsx_runtime98.Fragment, { children: [
14030
+ /* @__PURE__ */ (0, import_jsx_runtime98.jsx)(Button, { variant: "secondary", onClick: () => setCreateOpen(false), children: "Cancel" }),
14031
+ /* @__PURE__ */ (0, import_jsx_runtime98.jsx)(Button, { onClick: submitCreate, disabled: !createName.trim(), children: "Create" })
14032
+ ] }), children: /* @__PURE__ */ (0, import_jsx_runtime98.jsx)(
13795
14033
  "input",
13796
14034
  {
13797
14035
  className: "fd-fb-input",
@@ -13805,10 +14043,10 @@ function FileBrowser({
13805
14043
  autoFocus: true
13806
14044
  }
13807
14045
  ) }),
13808
- /* @__PURE__ */ (0, import_jsx_runtime97.jsx)(Modal, { open: renameTarget != null, title: "Rename folder", onClose: () => setRenameTarget(null), footer: /* @__PURE__ */ (0, import_jsx_runtime97.jsxs)(import_jsx_runtime97.Fragment, { children: [
13809
- /* @__PURE__ */ (0, import_jsx_runtime97.jsx)(Button, { variant: "secondary", onClick: () => setRenameTarget(null), children: "Cancel" }),
13810
- /* @__PURE__ */ (0, import_jsx_runtime97.jsx)(Button, { onClick: submitRename, disabled: !renameValue.trim(), children: "Save" })
13811
- ] }), children: /* @__PURE__ */ (0, import_jsx_runtime97.jsx)(
14046
+ /* @__PURE__ */ (0, import_jsx_runtime98.jsx)(Modal, { open: renameTarget != null, title: "Rename folder", onClose: () => setRenameTarget(null), footer: /* @__PURE__ */ (0, import_jsx_runtime98.jsxs)(import_jsx_runtime98.Fragment, { children: [
14047
+ /* @__PURE__ */ (0, import_jsx_runtime98.jsx)(Button, { variant: "secondary", onClick: () => setRenameTarget(null), children: "Cancel" }),
14048
+ /* @__PURE__ */ (0, import_jsx_runtime98.jsx)(Button, { onClick: submitRename, disabled: !renameValue.trim(), children: "Save" })
14049
+ ] }), children: /* @__PURE__ */ (0, import_jsx_runtime98.jsx)(
13812
14050
  "input",
13813
14051
  {
13814
14052
  className: "fd-fb-input",
@@ -13822,22 +14060,22 @@ function FileBrowser({
13822
14060
  autoFocus: true
13823
14061
  }
13824
14062
  ) }),
13825
- /* @__PURE__ */ (0, import_jsx_runtime97.jsx)(
14063
+ /* @__PURE__ */ (0, import_jsx_runtime98.jsx)(
13826
14064
  Modal,
13827
14065
  {
13828
14066
  open: deleteTarget != null,
13829
14067
  title: deleteTarget ? "Delete \u201C" + deleteTarget.name + "\u201D?" : "Delete folder?",
13830
14068
  description: "This can't be undone. The folder must be empty.",
13831
14069
  onClose: () => setDeleteTarget(null),
13832
- footer: /* @__PURE__ */ (0, import_jsx_runtime97.jsxs)(import_jsx_runtime97.Fragment, { children: [
13833
- /* @__PURE__ */ (0, import_jsx_runtime97.jsx)(Button, { variant: "secondary", onClick: () => setDeleteTarget(null), children: "Cancel" }),
13834
- /* @__PURE__ */ (0, import_jsx_runtime97.jsx)(Button, { variant: "danger", onClick: confirmDelete, children: "Delete" })
14070
+ footer: /* @__PURE__ */ (0, import_jsx_runtime98.jsxs)(import_jsx_runtime98.Fragment, { children: [
14071
+ /* @__PURE__ */ (0, import_jsx_runtime98.jsx)(Button, { variant: "secondary", onClick: () => setDeleteTarget(null), children: "Cancel" }),
14072
+ /* @__PURE__ */ (0, import_jsx_runtime98.jsx)(Button, { variant: "danger", onClick: confirmDelete, children: "Delete" })
13835
14073
  ] })
13836
14074
  }
13837
14075
  )
13838
14076
  ] });
13839
14077
  if (!canUpload) return content;
13840
- return /* @__PURE__ */ (0, import_jsx_runtime97.jsx)(Dropzone, { className: "fd-fb-dropzone", onFiles: (picked) => onUpload && onUpload(picked, currentFolderId), label: "Drop files to upload", children: content });
14078
+ return /* @__PURE__ */ (0, import_jsx_runtime98.jsx)(Dropzone, { className: "fd-fb-dropzone", onFiles: (picked) => onUpload && onUpload(picked, currentFolderId), label: "Drop files to upload", children: content });
13841
14079
  }
13842
14080
  function BreadcrumbCrumb({
13843
14081
  label,
@@ -13846,8 +14084,8 @@ function BreadcrumbCrumb({
13846
14084
  isDropTarget,
13847
14085
  onDropPayload
13848
14086
  }) {
13849
- const [over, setOver] = React65.useState(false);
13850
- const dragCounter = React65.useRef(0);
14087
+ const [over, setOver] = React66.useState(false);
14088
+ const dragCounter = React66.useRef(0);
13851
14089
  const dropHandlers = isDropTarget ? {
13852
14090
  onDragEnter: (e) => {
13853
14091
  if (!hasInternalPayload(e)) return;
@@ -13872,11 +14110,11 @@ function BreadcrumbCrumb({
13872
14110
  if (payload && onDropPayload) onDropPayload(payload);
13873
14111
  }
13874
14112
  } : {};
13875
- return /* @__PURE__ */ (0, import_jsx_runtime97.jsx)("span", { className: ["fd-fb-crumb", over ? "is-drop-target" : ""].filter(Boolean).join(" "), ...dropHandlers, children: isCurrent ? /* @__PURE__ */ (0, import_jsx_runtime97.jsx)("span", { className: "fd-fb-crumb-current", "aria-current": "page", children: label }) : /* @__PURE__ */ (0, import_jsx_runtime97.jsx)("button", { type: "button", className: "fd-fb-crumb-link", onClick, children: label }) });
14113
+ return /* @__PURE__ */ (0, import_jsx_runtime98.jsx)("span", { className: ["fd-fb-crumb", over ? "is-drop-target" : ""].filter(Boolean).join(" "), ...dropHandlers, children: isCurrent ? /* @__PURE__ */ (0, import_jsx_runtime98.jsx)("span", { className: "fd-fb-crumb-current", "aria-current": "page", children: label }) : /* @__PURE__ */ (0, import_jsx_runtime98.jsx)("button", { type: "button", className: "fd-fb-crumb-link", onClick, children: label }) });
13876
14114
  }
13877
14115
 
13878
14116
  // src/kits/query.ts
13879
- var React66 = __toESM(require("react"), 1);
14117
+ var React67 = __toESM(require("react"), 1);
13880
14118
  var isMultiSelectShaped = (v) => !!v && typeof v === "object" && Array.isArray(v.values);
13881
14119
  var isRangeShaped = (v) => !!v && typeof v === "object" && ("min" in v || "max" in v);
13882
14120
  var isDateShaped = (v) => !!v && typeof v === "object" && "kind" in v;
@@ -13931,22 +14169,22 @@ function compare(a, b, dir) {
13931
14169
  var API = null;
13932
14170
  var PREFS = null;
13933
14171
  function useServerTable({ endpoint, params, defaults, deps, prefsKey }) {
13934
- const [query, setQuery] = React66.useState(() => {
14172
+ const [query, setQuery] = React67.useState(() => {
13935
14173
  const store = PREFS || window.PlannerPrefs;
13936
14174
  const saved = prefsKey && store ? store.getTable(prefsKey) : {};
13937
14175
  return { ...DEFAULTS, ...defaults || {}, ...saved.pageSize ? { pageSize: saved.pageSize } : {}, ...saved.sort ? { sort: saved.sort, dir: saved.dir || "desc" } : {} };
13938
14176
  });
13939
- const savePref = React66.useCallback((patch2) => {
14177
+ const savePref = React67.useCallback((patch2) => {
13940
14178
  const store = PREFS || window.PlannerPrefs;
13941
14179
  if (prefsKey && store) store.setTable(prefsKey, patch2);
13942
14180
  }, [prefsKey]);
13943
- const [res, setRes] = React66.useState(null);
13944
- const [loading, setLoading] = React66.useState(true);
13945
- const seq2 = React66.useRef(0);
14181
+ const [res, setRes] = React67.useState(null);
14182
+ const [loading, setLoading] = React67.useState(true);
14183
+ const seq2 = React67.useRef(0);
13946
14184
  const depKey = (deps || []).join("|");
13947
14185
  const paramKey = JSON.stringify(params || {});
13948
14186
  const queryKey = JSON.stringify(query);
13949
- React66.useEffect(() => {
14187
+ React67.useEffect(() => {
13950
14188
  const id = ++seq2.current;
13951
14189
  setLoading(true);
13952
14190
  const t = setTimeout(() => {
@@ -14265,12 +14503,12 @@ function createVersionStore(initialState, options) {
14265
14503
  }
14266
14504
 
14267
14505
  // src/kits/documentTitle.ts
14268
- var React67 = __toESM(require("react"), 1);
14506
+ var React68 = __toESM(require("react"), 1);
14269
14507
  function formatDocumentTitle(routeTitle, appName) {
14270
14508
  return [routeTitle, appName, "Flytedesk"].filter((part) => !!part && part.length > 0).join(" \xB7 ");
14271
14509
  }
14272
14510
  function useDocumentTitle(routeTitle, appName) {
14273
- React67.useEffect(() => {
14511
+ React68.useEffect(() => {
14274
14512
  if (typeof document === "undefined") return;
14275
14513
  document.title = formatDocumentTitle(routeTitle, appName);
14276
14514
  }, [routeTitle, appName]);
@@ -14313,6 +14551,7 @@ function useDocumentTitle(routeTitle, appName) {
14313
14551
  Clamp,
14314
14552
  ClockFace,
14315
14553
  CodeBlock,
14554
+ CodeEditor,
14316
14555
  Collapsible,
14317
14556
  ComingSoon,
14318
14557
  CsiBadge,