@flytedan/flytebot-design-system 0.48.0 → 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,
@@ -1095,28 +1096,28 @@ function Card({
1095
1096
  interactive ? "fd-card-interactive" : "",
1096
1097
  className
1097
1098
  ].filter(Boolean).join(" ");
1098
- const head = title ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "fd-card-head", children: [
1099
+ const titleOnlyHead = title ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "fd-card-head", children: [
1099
1100
  /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "fd-card-head-title", title: truncationTitle(title), children: title }),
1100
- action
1101
+ !interactive && action
1101
1102
  ] }) : null;
1102
1103
  const body = padded ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "fd-card-body", children }) : children;
1103
1104
  const foot = footer ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "fd-card-foot", children: footer }) : null;
1104
- if (href != null) {
1105
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("a", { href, onClick, className: cls, role, tabIndex, ...rest, children: [
1106
- head,
1107
- body,
1108
- foot
1105
+ if (interactive) {
1106
+ const inner = href != null ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("a", { href, onClick, className: cls, role, tabIndex, ...rest, children: [
1107
+ titleOnlyHead,
1108
+ body
1109
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("button", { type: "button", onClick, className: cls, role, tabIndex, ...rest, children: [
1110
+ titleOnlyHead,
1111
+ body
1109
1112
  ] });
1110
- }
1111
- if (onClick != null) {
1112
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("button", { type: "button", onClick, className: cls, role, tabIndex, ...rest, children: [
1113
- head,
1114
- body,
1113
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "fd-card-shell", children: [
1114
+ inner,
1115
+ action ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "fd-card-shell-action", children: action }) : null,
1115
1116
  foot
1116
1117
  ] });
1117
1118
  }
1118
1119
  return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: cls, role, tabIndex, ...rest, children: [
1119
- head,
1120
+ titleOnlyHead,
1120
1121
  body,
1121
1122
  foot
1122
1123
  ] });
@@ -1290,8 +1291,21 @@ function ScreenHead({ kicker, title, lede, actions }) {
1290
1291
  // src/components/layout/CardGrid.tsx
1291
1292
  var React8 = __toESM(require("react"), 1);
1292
1293
  var import_jsx_runtime12 = require("react/jsx-runtime");
1294
+ function flattenFragments(children) {
1295
+ const out = [];
1296
+ React8.Children.forEach(children, (child) => {
1297
+ if (child === null || child === void 0 || typeof child === "boolean") return;
1298
+ if (React8.isValidElement(child) && child.type === React8.Fragment) {
1299
+ const fragmentChildren = child.props.children;
1300
+ out.push(...flattenFragments(fragmentChildren));
1301
+ return;
1302
+ }
1303
+ out.push(child);
1304
+ });
1305
+ return out;
1306
+ }
1293
1307
  function CardGrid({ children, minCardWidth = 280, gap = "lg", className = "", style }) {
1294
- const items = React8.Children.toArray(children);
1308
+ const items = flattenFragments(children);
1295
1309
  return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
1296
1310
  "div",
1297
1311
  {
@@ -1299,10 +1313,12 @@ function CardGrid({ children, minCardWidth = 280, gap = "lg", className = "", st
1299
1313
  className: ["fd-card-grid", "fd-gap-" + gap, className].filter(Boolean).join(" "),
1300
1314
  style: { ["--card-grid-min"]: minCardWidth + "px", ...style },
1301
1315
  children: items.map((child, i) => {
1302
- if (!React8.isValidElement(child)) return child;
1303
- const existingProps = child.props;
1304
- if (existingProps.role) return child;
1305
- return React8.cloneElement(child, { role: "listitem", key: child.key ?? i });
1316
+ if (React8.isValidElement(child)) {
1317
+ const existingRole = child.props.role;
1318
+ if (existingRole) return child;
1319
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { role: "listitem", children: child }, child.key ?? i);
1320
+ }
1321
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { role: "listitem", children: child }, i);
1306
1322
  })
1307
1323
  }
1308
1324
  );
@@ -4870,7 +4886,7 @@ function CodeBlock({
4870
4886
  code = "",
4871
4887
  language,
4872
4888
  filename,
4873
- lineNumbers = false,
4889
+ lineNumbers: lineNumbers2 = false,
4874
4890
  wrap: wrapDefault = false,
4875
4891
  collapseAfter = 26,
4876
4892
  copyable = true,
@@ -4897,7 +4913,7 @@ function CodeBlock({
4897
4913
  ] }) : null
4898
4914
  ] }),
4899
4915
  /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("div", { className: "fd-code-body", children: [
4900
- 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,
4901
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 }) }) })
4902
4918
  ] }),
4903
4919
  foldable ? /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("button", { type: "button", className: "fd-code-fold", onClick: () => setOpen((v) => !v), "aria-expanded": open2, children: [
@@ -7480,17 +7496,254 @@ var MarkdownEditor = React42.forwardRef(function MarkdownEditor2({
7480
7496
  ] });
7481
7497
  });
7482
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
+
7483
7736
  // src/components/platform/AccountMenu.tsx
7484
- var React44 = __toESM(require("react"), 1);
7737
+ var React45 = __toESM(require("react"), 1);
7485
7738
 
7486
7739
  // src/kits/sessionContext.tsx
7487
- var React43 = __toESM(require("react"), 1);
7488
- var SessionContext = React43.createContext(null);
7740
+ var React44 = __toESM(require("react"), 1);
7741
+ var SessionContext = React44.createContext(null);
7489
7742
  function SessionProvider({ value, children }) {
7490
- return React43.createElement(SessionContext.Provider, { value }, children);
7743
+ return React44.createElement(SessionContext.Provider, { value }, children);
7491
7744
  }
7492
7745
  function useSessionContext() {
7493
- const ctx = React43.useContext(SessionContext);
7746
+ const ctx = React44.useContext(SessionContext);
7494
7747
  if (!ctx) {
7495
7748
  throw new Error(
7496
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."
@@ -7500,11 +7753,11 @@ function useSessionContext() {
7500
7753
  }
7501
7754
 
7502
7755
  // src/components/platform/AccountMenu.tsx
7503
- var import_jsx_runtime73 = require("react/jsx-runtime");
7756
+ var import_jsx_runtime74 = require("react/jsx-runtime");
7504
7757
  var DEFAULT_LINKS = [];
7505
7758
  var DEFAULT_GROUPS = [];
7506
7759
  function Item({ item, onPick }) {
7507
- return /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)(
7760
+ return /* @__PURE__ */ (0, import_jsx_runtime74.jsxs)(
7508
7761
  "button",
7509
7762
  {
7510
7763
  type: "button",
@@ -7512,9 +7765,9 @@ function Item({ item, onPick }) {
7512
7765
  className: "fd-acct-item",
7513
7766
  onClick: () => onPick(item),
7514
7767
  children: [
7515
- item.icon ? /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("i", { className: "ph ph-" + item.icon, "aria-hidden": "true" }) : null,
7516
- /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("span", { style: { flex: 1 }, children: item.label }),
7517
- 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
7518
7771
  ]
7519
7772
  }
7520
7773
  );
@@ -7530,11 +7783,11 @@ function AccountMenu({
7530
7783
  ...rest
7531
7784
  }) {
7532
7785
  const { user, roles, can: can2, signOut: ctxSignOut, demo, pending } = useSessionContext();
7533
- const [open2, setOpen] = React44.useState(false);
7534
- const [switching, setSwitching] = React44.useState(false);
7535
- const [signingOut, setSigningOut] = React44.useState(false);
7536
- const [signOutError, setSignOutError] = React44.useState(null);
7537
- 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);
7538
7791
  const visibleLinks = links.filter((l) => !l.perm || !pending && can2(l.perm));
7539
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);
7540
7793
  const closeMenu = () => {
@@ -7562,8 +7815,8 @@ function AccountMenu({
7562
7815
  }
7563
7816
  };
7564
7817
  const showSwitcher = allowUserSwitch && !!demo;
7565
- return /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)(import_jsx_runtime73.Fragment, { children: [
7566
- /* @__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)(
7567
7820
  "button",
7568
7821
  {
7569
7822
  type: "button",
@@ -7575,12 +7828,12 @@ function AccountMenu({
7575
7828
  onClick: () => open2 ? closeMenu() : setOpen(true),
7576
7829
  ...rest,
7577
7830
  children: [
7578
- /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(Avatar, { name: user.name, size: "sm" }),
7579
- /* @__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)" } })
7580
7833
  ]
7581
7834
  }
7582
7835
  ),
7583
- /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(
7836
+ /* @__PURE__ */ (0, import_jsx_runtime74.jsx)(
7584
7837
  Popover,
7585
7838
  {
7586
7839
  open: open2,
@@ -7588,27 +7841,27 @@ function AccountMenu({
7588
7841
  onClose: closeMenu,
7589
7842
  placement: "bottom-end",
7590
7843
  width: 272,
7591
- children: /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("div", { role: "menu", className: "fd-stack", style: { gap: 0 }, children: [
7592
- /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("div", { className: "fd-row", style: { gap: 10, padding: "12px 14px", borderBottom: "1px solid var(--border)" }, children: [
7593
- /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(Avatar, { name: user.name }),
7594
- /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("span", { className: "fd-stack", style: { gap: 1, minWidth: 0, flex: 1 }, children: [
7595
- /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("span", { className: "fd-body-sm", style: { fontWeight: 700 }, children: user.name }),
7596
- /* @__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 })
7597
7850
  ] })
7598
7851
  ] }),
7599
- 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,
7600
- 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,
7601
- visibleGroups.map((g) => /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("div", { className: "fd-acct-group", style: { borderTop: "1px solid var(--border)" }, children: [
7602
- /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("span", { className: "fd-overline fd-muted", style: { padding: "8px 14px 4px", display: "block" }, children: g.label }),
7603
- 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))
7604
7857
  ] }, g.label)),
7605
- showSwitcher && demo ? /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("div", { className: "fd-acct-group", style: { borderTop: "1px solid var(--border)" }, children: [
7606
- /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("button", { type: "button", role: "menuitem", className: "fd-acct-item", onClick: () => setSwitching((s) => !s), children: [
7607
- /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("i", { className: "ph ph-user-switch", "aria-hidden": "true" }),
7608
- /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("span", { style: { flex: 1 }, children: "View as another member" }),
7609
- /* @__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 } })
7610
7863
  ] }),
7611
- 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)(
7612
7865
  "button",
7613
7866
  {
7614
7867
  type: "button",
@@ -7620,19 +7873,19 @@ function AccountMenu({
7620
7873
  setSwitching(false);
7621
7874
  },
7622
7875
  children: [
7623
- /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(Avatar, { name: u.name, size: "sm" }),
7624
- /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("span", { className: "fd-stack", style: { gap: 0, flex: 1, minWidth: 0, alignItems: "flex-start" }, children: [
7625
- /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("span", { style: { fontWeight: u.id === user.id ? 700 : 500 }, children: u.name }),
7626
- 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
7627
7880
  ] }),
7628
- 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
7629
7882
  ]
7630
7883
  },
7631
7884
  u.id
7632
7885
  )) }) : null
7633
7886
  ] }) : null,
7634
- /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("div", { className: "fd-acct-group", style: { borderTop: "1px solid var(--border)" }, children: [
7635
- /* @__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)(
7636
7889
  "button",
7637
7890
  {
7638
7891
  type: "button",
@@ -7642,14 +7895,14 @@ function AccountMenu({
7642
7895
  disabled: signingOut,
7643
7896
  onClick: signOut,
7644
7897
  children: [
7645
- 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" }),
7646
- /* @__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" })
7647
7900
  ]
7648
7901
  }
7649
7902
  ),
7650
- signOutError ? /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("div", { role: "alert", className: "fd-body-sm", style: { padding: "0 14px 12px" }, children: [
7651
- /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("span", { style: { display: "block", color: "var(--danger-text)", marginBottom: 6 }, children: signOutError }),
7652
- /* @__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" })
7653
7906
  ] }) : null
7654
7907
  ] })
7655
7908
  ] })
@@ -7659,13 +7912,13 @@ function AccountMenu({
7659
7912
  }
7660
7913
 
7661
7914
  // src/components/platform/AppSwitcher.tsx
7662
- var React45 = __toESM(require("react"), 1);
7663
- var import_jsx_runtime74 = require("react/jsx-runtime");
7915
+ var React46 = __toESM(require("react"), 1);
7916
+ var import_jsx_runtime75 = require("react/jsx-runtime");
7664
7917
  function AppSwitcher({ apps: appsProp, onNavigate, className = "" }) {
7665
7918
  const { apps: contextApps } = useSessionContext();
7666
7919
  const apps = appsProp ?? contextApps ?? [];
7667
- const [open2, setOpen] = React45.useState(false);
7668
- const anchorRef = React45.useRef(null);
7920
+ const [open2, setOpen] = React46.useState(false);
7921
+ const anchorRef = React46.useRef(null);
7669
7922
  if (!apps.length) return null;
7670
7923
  const items = apps.map((app) => ({
7671
7924
  id: app.key,
@@ -7679,8 +7932,8 @@ function AppSwitcher({ apps: appsProp, onNavigate, className = "" }) {
7679
7932
  window.location.href = app.url;
7680
7933
  }
7681
7934
  }));
7682
- return /* @__PURE__ */ (0, import_jsx_runtime74.jsxs)(React45.Fragment, { children: [
7683
- /* @__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)(
7684
7937
  IconButton,
7685
7938
  {
7686
7939
  icon: "squares-four",
@@ -7690,7 +7943,7 @@ function AppSwitcher({ apps: appsProp, onNavigate, className = "" }) {
7690
7943
  onClick: () => setOpen((v) => !v)
7691
7944
  }
7692
7945
  ) }),
7693
- /* @__PURE__ */ (0, import_jsx_runtime74.jsx)(
7946
+ /* @__PURE__ */ (0, import_jsx_runtime75.jsx)(
7694
7947
  Popover,
7695
7948
  {
7696
7949
  open: open2,
@@ -7701,17 +7954,17 @@ function AppSwitcher({ apps: appsProp, onNavigate, className = "" }) {
7701
7954
  label: "All flytedesk apps",
7702
7955
  width: 240,
7703
7956
  maxHeight: 360,
7704
- 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) })
7705
7958
  }
7706
7959
  )
7707
7960
  ] });
7708
7961
  }
7709
7962
 
7710
7963
  // src/components/platform/AppearanceMenu.tsx
7711
- var React47 = __toESM(require("react"), 1);
7964
+ var React48 = __toESM(require("react"), 1);
7712
7965
 
7713
7966
  // src/kits/appearance.ts
7714
- var React46 = __toESM(require("react"), 1);
7967
+ var React47 = __toESM(require("react"), 1);
7715
7968
  var DEFAULT_STORAGE_KEY = "fd-appearance";
7716
7969
  var DEFAULT_PREFS = {
7717
7970
  theme: "system",
@@ -7806,11 +8059,11 @@ function applyPrefs(prefs, root = document.documentElement) {
7806
8059
  else root.removeAttribute("data-motion");
7807
8060
  }
7808
8061
  function useAppearancePrefs(store) {
7809
- const prefs = React46.useSyncExternalStore(store.subscribe, store.getSnapshot);
7810
- React46.useEffect(() => {
8062
+ const prefs = React47.useSyncExternalStore(store.subscribe, store.getSnapshot);
8063
+ React47.useEffect(() => {
7811
8064
  applyPrefs(prefs);
7812
8065
  }, [prefs]);
7813
- React46.useEffect(() => {
8066
+ React47.useEffect(() => {
7814
8067
  if (prefs.theme !== "system" || typeof window === "undefined" || typeof window.matchMedia !== "function") {
7815
8068
  return;
7816
8069
  }
@@ -7819,7 +8072,7 @@ function useAppearancePrefs(store) {
7819
8072
  mq.addEventListener("change", onChange);
7820
8073
  return () => mq.removeEventListener("change", onChange);
7821
8074
  }, [prefs]);
7822
- const update = React46.useCallback(
8075
+ const update = React47.useCallback(
7823
8076
  (patch) => {
7824
8077
  store.write({ ...store.getSnapshot(), ...patch });
7825
8078
  },
@@ -7829,7 +8082,7 @@ function useAppearancePrefs(store) {
7829
8082
  }
7830
8083
 
7831
8084
  // src/components/platform/AppearanceMenu.tsx
7832
- var import_jsx_runtime75 = require("react/jsx-runtime");
8085
+ var import_jsx_runtime76 = require("react/jsx-runtime");
7833
8086
  var THEME_OPTIONS = [
7834
8087
  { value: "light", label: "Light" },
7835
8088
  { value: "dark", label: "Dark" },
@@ -7842,16 +8095,16 @@ var TEXT_SCALE_OPTIONS = [
7842
8095
  { value: "xl", label: "XL" }
7843
8096
  ];
7844
8097
  function AppearanceMenu({ className = "", store: storeProp, storageKey, storage, defaults }) {
7845
- const store = React47.useMemo(
8098
+ const store = React48.useMemo(
7846
8099
  () => storeProp ?? createLocalStorageAppearanceStore({ storageKey, storage, defaults }),
7847
8100
  [storeProp, storageKey, storage, defaults]
7848
8101
  );
7849
8102
  const [prefs, update] = useAppearancePrefs(store);
7850
- const [open2, setOpen] = React47.useState(false);
7851
- const anchorRef = React47.useRef(null);
8103
+ const [open2, setOpen] = React48.useState(false);
8104
+ const anchorRef = React48.useRef(null);
7852
8105
  const patch = (p) => update(p);
7853
- return /* @__PURE__ */ (0, import_jsx_runtime75.jsxs)(React47.Fragment, { children: [
7854
- /* @__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)(
7855
8108
  IconButton,
7856
8109
  {
7857
8110
  icon: "circle-half",
@@ -7859,7 +8112,7 @@ function AppearanceMenu({ className = "", store: storeProp, storageKey, storage,
7859
8112
  onClick: () => setOpen((v) => !v)
7860
8113
  }
7861
8114
  ) }),
7862
- /* @__PURE__ */ (0, import_jsx_runtime75.jsx)(
8115
+ /* @__PURE__ */ (0, import_jsx_runtime76.jsx)(
7863
8116
  Popover,
7864
8117
  {
7865
8118
  open: open2,
@@ -7869,10 +8122,10 @@ function AppearanceMenu({ className = "", store: storeProp, storageKey, storage,
7869
8122
  padded: true,
7870
8123
  width: 260,
7871
8124
  label: "Appearance settings",
7872
- children: /* @__PURE__ */ (0, import_jsx_runtime75.jsxs)("div", { className: "fd-stack", style: { display: "flex", flexDirection: "column", gap: 16 }, children: [
7873
- /* @__PURE__ */ (0, import_jsx_runtime75.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: 6 }, children: [
7874
- /* @__PURE__ */ (0, import_jsx_runtime75.jsx)("span", { className: "fd-field-label", children: "Theme" }),
7875
- /* @__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)(
7876
8129
  SegmentedControl,
7877
8130
  {
7878
8131
  options: THEME_OPTIONS,
@@ -7882,9 +8135,9 @@ function AppearanceMenu({ className = "", store: storeProp, storageKey, storage,
7882
8135
  }
7883
8136
  )
7884
8137
  ] }),
7885
- /* @__PURE__ */ (0, import_jsx_runtime75.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: 6 }, children: [
7886
- /* @__PURE__ */ (0, import_jsx_runtime75.jsx)("span", { className: "fd-field-label", children: "Text size" }),
7887
- /* @__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)(
7888
8141
  SegmentedControl,
7889
8142
  {
7890
8143
  options: TEXT_SCALE_OPTIONS,
@@ -7894,7 +8147,7 @@ function AppearanceMenu({ className = "", store: storeProp, storageKey, storage,
7894
8147
  }
7895
8148
  )
7896
8149
  ] }),
7897
- /* @__PURE__ */ (0, import_jsx_runtime75.jsx)(
8150
+ /* @__PURE__ */ (0, import_jsx_runtime76.jsx)(
7898
8151
  Switch,
7899
8152
  {
7900
8153
  label: "High contrast",
@@ -7903,7 +8156,7 @@ function AppearanceMenu({ className = "", store: storeProp, storageKey, storage,
7903
8156
  onChange: (e) => patch({ highContrast: e.target.checked })
7904
8157
  }
7905
8158
  ),
7906
- /* @__PURE__ */ (0, import_jsx_runtime75.jsx)(
8159
+ /* @__PURE__ */ (0, import_jsx_runtime76.jsx)(
7907
8160
  Switch,
7908
8161
  {
7909
8162
  label: "Reduce motion",
@@ -7919,14 +8172,14 @@ function AppearanceMenu({ className = "", store: storeProp, storageKey, storage,
7919
8172
  }
7920
8173
 
7921
8174
  // src/components/platform/ApiSpecBrowser.tsx
7922
- var React48 = __toESM(require("react"), 1);
7923
- var import_jsx_runtime76 = require("react/jsx-runtime");
8175
+ var React49 = __toESM(require("react"), 1);
8176
+ var import_jsx_runtime77 = require("react/jsx-runtime");
7924
8177
  var METHOD_TONE = { GET: "success", POST: "info", PATCH: "warning", PUT: "warning", DELETE: "danger" };
7925
8178
  function Json({ obj }) {
7926
- 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) });
7927
8180
  }
7928
8181
  function Endpoint({ s, onRequest }) {
7929
- const [tried, setTried] = React48.useState(null);
8182
+ const [tried, setTried] = React49.useState(null);
7930
8183
  const run = async () => {
7931
8184
  setTried("busy");
7932
8185
  const t0 = (window.performance || Date).now();
@@ -7937,50 +8190,50 @@ function Endpoint({ s, onRequest }) {
7937
8190
  setTried({ ms: Math.round((window.performance || Date).now() - t0), error: String(e && e.message || e) });
7938
8191
  }
7939
8192
  };
7940
- 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: [
7941
- /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)("div", { className: "fd-row", style: { gap: 10, padding: "14px 18px", flexWrap: "wrap" }, children: [
7942
- /* @__PURE__ */ (0, import_jsx_runtime76.jsx)(Badge, { tone: METHOD_TONE[s.method] || "neutral", children: s.method }),
7943
- /* @__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 }),
7944
- s.isList ? /* @__PURE__ */ (0, import_jsx_runtime76.jsx)(Badge, { tone: "neutral", icon: "rows", children: "Paged list" }) : null,
7945
- /* @__PURE__ */ (0, import_jsx_runtime76.jsx)("span", { style: { flex: 1 } }),
7946
- /* @__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: [
7947
8200
  s.latency[0],
7948
8201
  "\u2013",
7949
8202
  s.latency[1],
7950
8203
  "ms"
7951
8204
  ] }),
7952
- /* @__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" })
7953
8206
  ] }),
7954
- /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)("div", { className: "fd-stack", style: { gap: 14, padding: "0 18px 16px" }, children: [
7955
- /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)("div", { className: "fd-stack", style: { gap: 6 }, children: [
7956
- /* @__PURE__ */ (0, import_jsx_runtime76.jsx)("span", { className: "fd-body-sm", style: { fontWeight: 700 }, children: s.title }),
7957
- /* @__PURE__ */ (0, import_jsx_runtime76.jsx)("p", { className: "fd-body-sm fd-secondary", style: { margin: 0, textWrap: "pretty" }, children: s.purpose }),
7958
- 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
7959
8212
  ] }),
7960
- /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)("div", { style: { display: "grid", gridTemplateColumns: "repeat(auto-fit,minmax(280px,1fr))", gap: 12, alignItems: "start" }, children: [
7961
- s.request ? /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)("div", { className: "fd-stack", style: { gap: 6 }, children: [
7962
- /* @__PURE__ */ (0, import_jsx_runtime76.jsx)("span", { className: "fd-overline fd-muted", children: "Request body" }),
7963
- /* @__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 })
7964
8217
  ] }) : null,
7965
- s.query ? /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)("div", { className: "fd-stack", style: { gap: 6 }, children: [
7966
- /* @__PURE__ */ (0, import_jsx_runtime76.jsx)("span", { className: "fd-overline fd-muted", children: "Query" }),
7967
- /* @__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 })
7968
8221
  ] }) : null,
7969
- /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)("div", { className: "fd-stack", style: { gap: 6 }, children: [
7970
- /* @__PURE__ */ (0, import_jsx_runtime76.jsx)("span", { className: "fd-overline fd-muted", children: "Response 200" }),
7971
- /* @__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 })
7972
8225
  ] })
7973
8226
  ] }),
7974
- s.notes ? /* @__PURE__ */ (0, import_jsx_runtime76.jsx)(Flag, { tone: "info", statement: "Implementation note", cost: s.notes, actions: null }) : null,
7975
- tried && tried !== "busy" ? /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)("div", { className: "fd-stack", style: { gap: 6 }, children: [
7976
- /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)("span", { className: "fd-row", style: { gap: 8 }, children: [
7977
- /* @__PURE__ */ (0, import_jsx_runtime76.jsx)("span", { className: "fd-overline fd-muted", children: "Simulated response" }),
7978
- /* @__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: [
7979
8232
  tried.ms,
7980
8233
  "ms"
7981
8234
  ] })
7982
8235
  ] }),
7983
- /* @__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 })
7984
8237
  ] }) : null
7985
8238
  ] })
7986
8239
  ] }) });
@@ -7999,58 +8252,58 @@ function ApiSpecBrowser({
7999
8252
  className = "",
8000
8253
  ...rest
8001
8254
  }) {
8002
- const [q, setQ] = React48.useState("");
8003
- const [method, setMethod] = React48.useState(null);
8004
- const [mod, setMod] = React48.useState(null);
8005
- 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);
8006
8259
  const activeModule = modules && modules.find((m) => m.id === mod);
8007
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())));
8008
8261
  const effGroups = groups && groups.length ? groups : [["All endpoints", spec.map((s) => s.id)]];
8009
8262
  const methods = [...new Set(spec.map((s) => s.method))];
8010
8263
  const listCount = spec.filter((s) => s.isList).length;
8011
- return /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 20, maxWidth: 1100 }, ...rest, children: [
8012
- /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)("div", { className: "fd-stack", style: { gap: 10 }, children: [
8013
- kicker ? /* @__PURE__ */ (0, import_jsx_runtime76.jsx)("span", { className: "fd-overline fd-muted", children: kicker }) : null,
8014
- /* @__PURE__ */ (0, import_jsx_runtime76.jsx)("h1", { className: "fd-h1", style: { margin: 0 }, children: title }),
8015
- 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
8016
8269
  ] }),
8017
- modules && modules.length ? /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)("div", { className: "fd-stack", style: { gap: 8 }, children: [
8018
- /* @__PURE__ */ (0, import_jsx_runtime76.jsx)("span", { className: "fd-overline fd-muted", children: "Filter by screen \u2014 every endpoint that screen depends on" }),
8019
- /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)("div", { className: "fd-row", style: { gap: 8, flexWrap: "wrap" }, children: [
8020
- /* @__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: [
8021
8274
  "All screens ",
8022
- /* @__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 })
8023
8276
  ] }),
8024
- 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: [
8025
8278
  m.label,
8026
8279
  " ",
8027
- /* @__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 })
8028
8281
  ] }, m.id))
8029
8282
  ] }),
8030
- activeModule ? /* @__PURE__ */ (0, import_jsx_runtime76.jsx)(
8283
+ activeModule ? /* @__PURE__ */ (0, import_jsx_runtime77.jsx)(
8031
8284
  Flag,
8032
8285
  {
8033
8286
  tone: "info",
8034
8287
  statement: activeModule.label + " calls " + activeModule.endpoints.length + " endpoints.",
8035
8288
  cost: "Integration checklist for this screen: " + activeModule.endpoints.join(", ") + ". Wire these and the screen is done.",
8036
- 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" })
8037
8290
  }
8038
8291
  ) : null
8039
8292
  ] }) : null,
8040
- sourceNote ? /* @__PURE__ */ (0, import_jsx_runtime76.jsx)(Flag, { tone: "info", statement: "Design-first: this page is the spec.", cost: sourceNote, actions: null }) : null,
8041
- /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)("div", { className: "fd-row", style: { gap: 10, flexWrap: "wrap" }, children: [
8042
- /* @__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 } }),
8043
- 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: [
8044
8297
  m,
8045
8298
  " ",
8046
- /* @__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 })
8047
8300
  ] }, m)),
8048
- 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: [
8049
8302
  "Paged lists ",
8050
- /* @__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 })
8051
8304
  ] }) : null,
8052
- /* @__PURE__ */ (0, import_jsx_runtime76.jsx)("span", { style: { flex: 1 } }),
8053
- /* @__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: [
8054
8307
  hits.length,
8055
8308
  " of ",
8056
8309
  spec.length,
@@ -8058,31 +8311,31 @@ function ApiSpecBrowser({
8058
8311
  listCount ? " \xB7 " + listCount + " paged" : ""
8059
8312
  ] })
8060
8313
  ] }),
8061
- 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]) => {
8062
8315
  const items = hits.filter((s) => ids.indexOf(s.id) >= 0);
8063
8316
  if (!items.length) return null;
8064
- return /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)("div", { className: "fd-stack", style: { gap: 12 }, children: [
8065
- /* @__PURE__ */ (0, import_jsx_runtime76.jsx)("span", { className: "fd-label-lg", children: g }),
8066
- 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))
8067
8320
  ] }, g);
8068
8321
  }),
8069
- 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: [
8070
- /* @__PURE__ */ (0, import_jsx_runtime76.jsx)("span", { className: "fd-overline fd-muted", style: { width: 110, flex: "none", paddingTop: 2 }, children: k }),
8071
- /* @__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 })
8072
8325
  ] }, k)) }) }) : null,
8073
- 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: [
8074
- /* @__PURE__ */ (0, import_jsx_runtime76.jsx)(Badge, { tone: "danger", children: id }),
8075
- /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)("span", { className: "fd-stack", style: { gap: 2, flex: 1 }, children: [
8076
- /* @__PURE__ */ (0, import_jsx_runtime76.jsx)("span", { className: "fd-body-sm", style: { fontWeight: 600 }, children: question }),
8077
- /* @__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 })
8078
8331
  ] })
8079
8332
  ] }, id)) }) }) : null
8080
8333
  ] });
8081
8334
  }
8082
8335
 
8083
8336
  // src/components/platform/ProfilePage.tsx
8084
- var React49 = __toESM(require("react"), 1);
8085
- var import_jsx_runtime77 = require("react/jsx-runtime");
8337
+ var React50 = __toESM(require("react"), 1);
8338
+ var import_jsx_runtime78 = require("react/jsx-runtime");
8086
8339
  function fieldInitialValue(field, user) {
8087
8340
  if (field.value) return field.value(user);
8088
8341
  const raw = user[field.key];
@@ -8117,21 +8370,21 @@ function ProfilePage({
8117
8370
  }) {
8118
8371
  const { user: sessionUser, roles, permissions, saveProfile: saveProfile2 } = useSessionContext();
8119
8372
  const user = userProp || sessionUser;
8120
- const initialFieldValues = React49.useMemo(() => {
8373
+ const initialFieldValues = React50.useMemo(() => {
8121
8374
  const values2 = {};
8122
8375
  for (const field of fields) values2[field.key] = fieldInitialValue(field, user);
8123
8376
  return values2;
8124
8377
  }, [user.id, fields]);
8125
- const initialNotify = React49.useMemo(() => {
8378
+ const initialNotify = React50.useMemo(() => {
8126
8379
  const values2 = {};
8127
8380
  for (const n of notifications) values2[n.key] = !!user.notify?.[n.key];
8128
8381
  return values2;
8129
8382
  }, [user.id, notifications]);
8130
- const [values, setValues] = React49.useState(initialFieldValues);
8131
- const [notify, setNotify] = React49.useState(initialNotify);
8132
- const [saving, setSaving] = React49.useState(false);
8133
- const [saved, setSaved] = React49.useState(false);
8134
- 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);
8135
8388
  if (user.id !== prevUserId) {
8136
8389
  setPrevUserId(user.id);
8137
8390
  setValues(initialFieldValues);
@@ -8168,37 +8421,37 @@ function ProfilePage({
8168
8421
  };
8169
8422
  const displayName = fields.some((f) => f.key === "name") ? values.name || user.name : user.name;
8170
8423
  const fieldGroups = groupFields(fields);
8171
- return /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 20, maxWidth: 860 }, children: [
8172
- /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)("div", { className: "fd-stack", style: { gap: 10 }, children: [
8173
- /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("span", { className: "fd-overline fd-muted", children: "Account" }),
8174
- /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("h1", { className: "fd-h1", style: { margin: 0 }, children: "Your profile" }),
8175
- /* @__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." })
8176
8429
  ] }),
8177
- /* @__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: [
8178
- /* @__PURE__ */ (0, import_jsx_runtime77.jsx)(Avatar, { name: displayName, size: "lg" }),
8179
- /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)("div", { className: "fd-stack", style: { gap: 4, flex: 1, minWidth: 200 }, children: [
8180
- /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("span", { className: "fd-h3", style: { margin: 0 }, children: displayName }),
8181
- /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)("span", { className: "fd-row", style: { gap: 6, flexWrap: "wrap", paddingTop: 4 }, children: [
8182
- roles.map((r) => /* @__PURE__ */ (0, import_jsx_runtime77.jsx)(Badge, { tone: r.id === "owner" ? "success" : "neutral", children: r.name }, r.id)),
8183
- 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
8184
8437
  ] })
8185
8438
  ] }),
8186
- 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
8187
8440
  ] }) }),
8188
- 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)(
8189
8442
  Card,
8190
8443
  {
8191
- title: description ? /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)("span", { className: "fd-stack", style: { gap: 2 }, children: [
8192
- /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("span", { children: group }),
8193
- /* @__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 })
8194
8447
  ] }) : group,
8195
8448
  elevation: "flat",
8196
- children: /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)("div", { className: "fd-stack", style: { gap: 14 }, children: [
8197
- /* @__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) => {
8198
8451
  const help = typeof field.help === "function" ? field.help(user) : field.help;
8199
8452
  const readOnly = field.readOnly || field.type === "readonly";
8200
8453
  if (field.type === "select") {
8201
- return /* @__PURE__ */ (0, import_jsx_runtime77.jsx)(
8454
+ return /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(
8202
8455
  Select,
8203
8456
  {
8204
8457
  label: field.label,
@@ -8212,7 +8465,7 @@ function ProfilePage({
8212
8465
  field.key
8213
8466
  );
8214
8467
  }
8215
- return /* @__PURE__ */ (0, import_jsx_runtime77.jsx)(
8468
+ return /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(
8216
8469
  Input,
8217
8470
  {
8218
8471
  label: field.label,
@@ -8228,7 +8481,7 @@ function ProfilePage({
8228
8481
  }) }),
8229
8482
  groupFieldDefs.filter((f) => f.type === "textarea").map((field) => {
8230
8483
  const help = typeof field.help === "function" ? field.help(user) : field.help;
8231
- return /* @__PURE__ */ (0, import_jsx_runtime77.jsx)(
8484
+ return /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(
8232
8485
  Textarea,
8233
8486
  {
8234
8487
  label: field.label,
@@ -8248,16 +8501,16 @@ function ProfilePage({
8248
8501
  group
8249
8502
  )),
8250
8503
  extra,
8251
- 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,
8252
- /* @__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)(
8253
8506
  Card,
8254
8507
  {
8255
- title: /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)("span", { className: "fd-stack", style: { gap: 2 }, children: [
8256
- /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("span", { children: "Access" }),
8257
- /* @__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" })
8258
8511
  ] }),
8259
8512
  elevation: "flat",
8260
- action: /* @__PURE__ */ (0, import_jsx_runtime77.jsx)(
8513
+ action: /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(
8261
8514
  Button,
8262
8515
  {
8263
8516
  size: "sm",
@@ -8268,39 +8521,39 @@ function ProfilePage({
8268
8521
  }
8269
8522
  ),
8270
8523
  children: [
8271
- /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)("div", { className: "fd-stack", style: { gap: 0 }, children: [
8272
- /* @__PURE__ */ (0, import_jsx_runtime77.jsx)(CardRow, { label: "Roles", children: roles.map((r) => r.name).join(", ") || "None" }),
8273
- /* @__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: [
8274
8527
  permissions.length,
8275
8528
  " granted"
8276
8529
  ] }),
8277
- /* @__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" })
8278
8531
  ] }),
8279
- /* @__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." })
8280
8533
  ]
8281
8534
  }
8282
8535
  ),
8283
- sessions ? /* @__PURE__ */ (0, import_jsx_runtime77.jsx)(
8536
+ sessions ? /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(
8284
8537
  Card,
8285
8538
  {
8286
8539
  title: "Signed-in devices",
8287
8540
  elevation: "flat",
8288
- action: /* @__PURE__ */ (0, import_jsx_runtime77.jsx)(Button, { size: "sm", variant: "ghost", icon: "sign-out", onClick: onSignOutEverywhere, children: "Sign out everywhere" }),
8289
- 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: [
8290
- /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("i", { className: "ph ph-device-mobile", style: { fontSize: 16, color: "var(--text-muted)" }, "aria-hidden": "true" }),
8291
- /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)("span", { className: "fd-stack", style: { gap: 1, flex: 1, minWidth: 160 }, children: [
8292
- /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("span", { className: "fd-body-sm", style: { fontWeight: 600 }, children: s.device }),
8293
- /* @__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: [
8294
8547
  s.where,
8295
8548
  " \xB7 ",
8296
8549
  s.when
8297
8550
  ] })
8298
8551
  ] }),
8299
- 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" })
8300
8553
  ] }, s.id)) })
8301
8554
  }
8302
8555
  ) : null,
8303
- /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)("div", { className: "fd-row", style: {
8556
+ /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)("div", { className: "fd-row", style: {
8304
8557
  gap: 10,
8305
8558
  flexWrap: "wrap",
8306
8559
  position: "sticky",
@@ -8311,19 +8564,19 @@ function ProfilePage({
8311
8564
  border: "1px solid var(--border)",
8312
8565
  boxShadow: "0 -4px 16px rgba(11,13,17,.06)"
8313
8566
  }, children: [
8314
- /* @__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" }),
8315
- /* @__PURE__ */ (0, import_jsx_runtime77.jsx)(Button, { size: "sm", variant: "ghost", disabled: !dirty || saving, onClick: discard, children: "Discard" }),
8316
- /* @__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" })
8317
8570
  ] })
8318
8571
  ] });
8319
8572
  }
8320
8573
 
8321
8574
  // src/components/platform/SignInPage.tsx
8322
- var React50 = __toESM(require("react"), 1);
8323
- var import_jsx_runtime78 = require("react/jsx-runtime");
8575
+ var React51 = __toESM(require("react"), 1);
8576
+ var import_jsx_runtime79 = require("react/jsx-runtime");
8324
8577
  function SignInPage({ productName, onSignIn, continueAs, error }) {
8325
- const [signingIn, setSigningIn] = React50.useState(false);
8326
- const [resuming, setResuming] = React50.useState(false);
8578
+ const [signingIn, setSigningIn] = React51.useState(false);
8579
+ const [resuming, setResuming] = React51.useState(false);
8327
8580
  function handleSignIn() {
8328
8581
  setSigningIn(true);
8329
8582
  onSignIn();
@@ -8332,7 +8585,7 @@ function SignInPage({ productName, onSignIn, continueAs, error }) {
8332
8585
  setResuming(true);
8333
8586
  continueAs.onContinue().finally(() => setResuming(false));
8334
8587
  }
8335
- return /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)(
8588
+ return /* @__PURE__ */ (0, import_jsx_runtime79.jsxs)(
8336
8589
  "div",
8337
8590
  {
8338
8591
  style: {
@@ -8346,7 +8599,7 @@ function SignInPage({ productName, onSignIn, continueAs, error }) {
8346
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%)"
8347
8600
  },
8348
8601
  children: [
8349
- /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(
8602
+ /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(
8350
8603
  "div",
8351
8604
  {
8352
8605
  "aria-hidden": true,
@@ -8359,7 +8612,7 @@ function SignInPage({ productName, onSignIn, continueAs, error }) {
8359
8612
  }
8360
8613
  }
8361
8614
  ),
8362
- /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)(
8615
+ /* @__PURE__ */ (0, import_jsx_runtime79.jsxs)(
8363
8616
  "div",
8364
8617
  {
8365
8618
  style: {
@@ -8371,8 +8624,8 @@ function SignInPage({ productName, onSignIn, continueAs, error }) {
8371
8624
  alignItems: "center"
8372
8625
  },
8373
8626
  children: [
8374
- /* @__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" }) }),
8375
- /* @__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)(
8376
8629
  "div",
8377
8630
  {
8378
8631
  style: {
@@ -8382,7 +8635,7 @@ function SignInPage({ productName, onSignIn, continueAs, error }) {
8382
8635
  boxShadow: "0 24px 64px -12px rgba(2, 8, 20, 0.55), 0 2px 8px rgba(2, 8, 20, 0.3)"
8383
8636
  },
8384
8637
  children: [
8385
- /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(
8638
+ /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(
8386
8639
  "div",
8387
8640
  {
8388
8641
  style: {
@@ -8391,7 +8644,7 @@ function SignInPage({ productName, onSignIn, continueAs, error }) {
8391
8644
  }
8392
8645
  }
8393
8646
  ),
8394
- /* @__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)(
8395
8648
  "div",
8396
8649
  {
8397
8650
  style: {
@@ -8403,13 +8656,13 @@ function SignInPage({ productName, onSignIn, continueAs, error }) {
8403
8656
  padding: "var(--s-8) 0"
8404
8657
  },
8405
8658
  children: [
8406
- /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)("div", { children: [
8407
- /* @__PURE__ */ (0, import_jsx_runtime78.jsx)("h1", { className: "fd-h3", style: { color: "var(--navy)" }, children: productName }),
8408
- /* @__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" })
8409
8662
  ] }),
8410
- 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,
8411
- continueAs ? /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)(import_jsx_runtime78.Fragment, { children: [
8412
- /* @__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)(
8413
8666
  Button,
8414
8667
  {
8415
8668
  variant: "primary",
@@ -8420,7 +8673,7 @@ function SignInPage({ productName, onSignIn, continueAs, error }) {
8420
8673
  children: resuming ? "Resuming\u2026" : `Continue as ${continueAs.name}`
8421
8674
  }
8422
8675
  ),
8423
- /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(
8676
+ /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(
8424
8677
  "button",
8425
8678
  {
8426
8679
  type: "button",
@@ -8437,7 +8690,7 @@ function SignInPage({ productName, onSignIn, continueAs, error }) {
8437
8690
  children: "Not you? Sign in with flytedesk ID"
8438
8691
  }
8439
8692
  )
8440
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(
8693
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(
8441
8694
  Button,
8442
8695
  {
8443
8696
  variant: "primary",
@@ -8445,7 +8698,7 @@ function SignInPage({ productName, onSignIn, continueAs, error }) {
8445
8698
  loading: signingIn,
8446
8699
  disabled: signingIn,
8447
8700
  onClick: handleSignIn,
8448
- children: /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)(
8701
+ children: /* @__PURE__ */ (0, import_jsx_runtime79.jsxs)(
8449
8702
  "span",
8450
8703
  {
8451
8704
  style: {
@@ -8457,14 +8710,14 @@ function SignInPage({ productName, onSignIn, continueAs, error }) {
8457
8710
  flexWrap: "nowrap"
8458
8711
  },
8459
8712
  children: [
8460
- /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(GoogleGlyph, {}),
8461
- /* @__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" })
8462
8715
  ]
8463
8716
  }
8464
8717
  )
8465
8718
  }
8466
8719
  ),
8467
- /* @__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." })
8468
8721
  ]
8469
8722
  }
8470
8723
  ) })
@@ -8479,29 +8732,29 @@ function SignInPage({ productName, onSignIn, continueAs, error }) {
8479
8732
  );
8480
8733
  }
8481
8734
  function GoogleGlyph() {
8482
- return /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)("svg", { width: "18", height: "18", viewBox: "0 0 18 18", "aria-hidden": true, children: [
8483
- /* @__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)(
8484
8737
  "path",
8485
8738
  {
8486
8739
  fill: "#4285F4",
8487
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"
8488
8741
  }
8489
8742
  ),
8490
- /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(
8743
+ /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(
8491
8744
  "path",
8492
8745
  {
8493
8746
  fill: "#34A853",
8494
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"
8495
8748
  }
8496
8749
  ),
8497
- /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(
8750
+ /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(
8498
8751
  "path",
8499
8752
  {
8500
8753
  fill: "#FBBC05",
8501
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"
8502
8755
  }
8503
8756
  ),
8504
- /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(
8757
+ /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(
8505
8758
  "path",
8506
8759
  {
8507
8760
  fill: "#EA4335",
@@ -8512,10 +8765,10 @@ function GoogleGlyph() {
8512
8765
  }
8513
8766
 
8514
8767
  // src/components/platform/RoadmapTimeline.tsx
8515
- var React53 = __toESM(require("react"), 1);
8768
+ var React54 = __toESM(require("react"), 1);
8516
8769
 
8517
8770
  // src/kits/session.ts
8518
- var React51 = __toESM(require("react"), 1);
8771
+ var React52 = __toESM(require("react"), 1);
8519
8772
  var PERMISSION_CATALOG = [
8520
8773
  { group: "Plans", items: [
8521
8774
  { key: "plan.view", label: "View plans", detail: "Read any plan in the workspace." },
@@ -10082,8 +10335,8 @@ function roadmap(overrides) {
10082
10335
  };
10083
10336
  }
10084
10337
  function useSession() {
10085
- const [s, setS] = React51.useState(getSession);
10086
- React51.useEffect(() => subscribe(setS), []);
10338
+ const [s, setS] = React52.useState(getSession);
10339
+ React52.useEffect(() => subscribe(setS), []);
10087
10340
  return s;
10088
10341
  }
10089
10342
  var SessionKit = {
@@ -10116,7 +10369,7 @@ var SessionKit = {
10116
10369
  };
10117
10370
  function DemoSessionProvider({ children }) {
10118
10371
  const session = useSession();
10119
- const value = React51.useMemo(
10372
+ const value = React52.useMemo(
10120
10373
  () => ({
10121
10374
  user: session.user,
10122
10375
  roles: session.roles,
@@ -10132,11 +10385,11 @@ function DemoSessionProvider({ children }) {
10132
10385
  }),
10133
10386
  [session]
10134
10387
  );
10135
- return React51.createElement(SessionProvider, { value }, children);
10388
+ return React52.createElement(SessionProvider, { value }, children);
10136
10389
  }
10137
10390
 
10138
10391
  // src/kits/runtime.ts
10139
- var React52 = __toESM(require("react"), 1);
10392
+ var React53 = __toESM(require("react"), 1);
10140
10393
  var WIRED_ENDPOINTS = [
10141
10394
  // Nothing yet. Every id below would come from a real service:
10142
10395
  // "plan.get", "placements.list", …
@@ -10307,8 +10560,8 @@ var RuntimeKit = {
10307
10560
  };
10308
10561
  RuntimeKit.declare(FEATURE_NEEDS);
10309
10562
  function useRuntimeMode() {
10310
- const [m, setM] = React52.useState(RuntimeKit.getMode());
10311
- React52.useEffect(() => RuntimeKit.subscribe(setM), []);
10563
+ const [m, setM] = React53.useState(RuntimeKit.getMode());
10564
+ React53.useEffect(() => RuntimeKit.subscribe(setM), []);
10312
10565
  return m;
10313
10566
  }
10314
10567
  function useFeatureStatus(key) {
@@ -10327,7 +10580,7 @@ var UseRuntimeMode = useRuntimeMode;
10327
10580
  var UseFeatureStatus = useFeatureStatus;
10328
10581
 
10329
10582
  // src/components/platform/RoadmapTimeline.tsx
10330
- var import_jsx_runtime79 = require("react/jsx-runtime");
10583
+ var import_jsx_runtime80 = require("react/jsx-runtime");
10331
10584
  var STATUS = {
10332
10585
  shipped: { tone: "success", icon: "check-circle", label: "Wired" },
10333
10586
  next: { tone: "warning", icon: "traffic-cone", label: "Not wired" },
@@ -10342,45 +10595,45 @@ function RoadmapCard({ item, byKey, onOpenFlag }) {
10342
10595
  const s = STATUS[item.status] || STATUS.planned;
10343
10596
  const deps = (item.dependsOn || []).map((k) => byKey[k]).filter(Boolean);
10344
10597
  const blocking = deps.filter((d) => !d.implemented);
10345
- 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: [
10346
- /* @__PURE__ */ (0, import_jsx_runtime79.jsxs)("div", { className: "fd-row", style: { gap: 8, flexWrap: "wrap" }, children: [
10347
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)("span", { className: "fd-body", style: { fontWeight: 700, flex: 1, minWidth: 140 }, children: item.label }),
10348
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(Badge, { tone: "neutral", icon: PROJECT_ICON[item.project] || "squares-four", children: item.project }),
10349
- /* @__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 })
10350
10603
  ] }),
10351
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)("p", { className: "fd-body-sm fd-secondary", style: { margin: 0, textWrap: "pretty" }, children: item.description }),
10352
- item.backend ? /* @__PURE__ */ (0, import_jsx_runtime79.jsxs)("div", { className: "fd-row", style: { gap: 10, alignItems: "flex-start" }, children: [
10353
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)("span", { className: "fd-overline fd-muted", style: { width: 62, flex: "none", paddingTop: 2 }, children: "Backend" }),
10354
- /* @__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 })
10355
10608
  ] }) : null,
10356
- /* @__PURE__ */ (0, import_jsx_runtime79.jsxs)("div", { className: "fd-row", style: { gap: 12, flexWrap: "wrap" }, children: [
10357
- item.effort ? /* @__PURE__ */ (0, import_jsx_runtime79.jsxs)("span", { className: "fd-body-sm fd-muted", children: [
10358
- /* @__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" }),
10359
10612
  " ",
10360
10613
  item.effort
10361
10614
  ] }) : null,
10362
- /* @__PURE__ */ (0, import_jsx_runtime79.jsxs)("span", { className: "fd-body-sm fd-muted", children: [
10363
- /* @__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" }),
10364
10617
  " ",
10365
10618
  item.owner
10366
10619
  ] }),
10367
- item.screen ? /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(Badge, { tone: "neutral", icon: "browser", children: "screen" }) : null,
10368
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)("span", { style: { flex: 1 } }),
10369
- /* @__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)(
10370
10623
  "button",
10371
10624
  {
10372
10625
  type: "button",
10373
10626
  onClick: () => onOpenFlag && onOpenFlag(item.key),
10374
10627
  style: { all: "unset", cursor: "pointer", display: "inline-flex", alignItems: "center", gap: 5 },
10375
- 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 })
10376
10629
  }
10377
10630
  )
10378
10631
  ] }),
10379
- 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: [
10380
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)("span", { className: "fd-overline fd-muted", style: { paddingTop: 3 }, children: "After" }),
10381
- 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))
10382
10635
  ] }) : null,
10383
- 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: [
10384
10637
  "Blocked until ",
10385
10638
  blocking.map((d) => d.label).join(" and "),
10386
10639
  " ",
@@ -10391,12 +10644,12 @@ function RoadmapCard({ item, byKey, onOpenFlag }) {
10391
10644
  }
10392
10645
  function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
10393
10646
  const session = SessionKit.useSession();
10394
- const [project, setProject] = React53.useState("");
10395
- const [q, setQ] = React53.useState("");
10396
- const scrollRef = React53.useRef(null);
10397
- const nowRef = React53.useRef(null);
10398
- const rm = React53.useMemo(() => SessionKit.roadmap({ isComplete: RuntimeKit.isComplete }), [session]);
10399
- 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(() => {
10400
10653
  const m = {};
10401
10654
  rm.items.forEach((i) => {
10402
10655
  m[i.key] = i;
@@ -10405,7 +10658,7 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
10405
10658
  }, [rm]);
10406
10659
  const items = rm.items.filter((i) => (!project || i.project === project) && (!q || (i.label + " " + i.description + " " + (i.backend || "") + " " + i.key).toLowerCase().includes(q.toLowerCase())));
10407
10660
  const projects = [...new Set(rm.items.map((i) => i.project))];
10408
- React53.useEffect(() => {
10661
+ React54.useEffect(() => {
10409
10662
  let raf1 = 0, raf2 = 0;
10410
10663
  const place = () => {
10411
10664
  const box = scrollRef.current, mark = nowRef.current;
@@ -10433,23 +10686,23 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
10433
10686
  }, 0);
10434
10687
  const nextPhase = items.find((i) => !i.implemented);
10435
10688
  let lastPhase = null;
10436
- return /* @__PURE__ */ (0, import_jsx_runtime79.jsxs)("div", { className: "fd-stack", style: { gap: 16, maxWidth: 1e3 }, children: [
10437
- /* @__PURE__ */ (0, import_jsx_runtime79.jsxs)("div", { className: "fd-stack", style: { gap: 10 }, children: [
10438
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)("span", { className: "fd-overline fd-muted", children: "Architecture" }),
10439
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)("h1", { className: "fd-h1", style: { margin: 0 }, children: title }),
10440
- /* @__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." })
10441
10694
  ] }),
10442
- /* @__PURE__ */ (0, import_jsx_runtime79.jsxs)("div", { className: "fd-grid-stats is-thin", children: [
10443
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(StatTile, { compact: true, label: "Wired", value: String(rm.shipped), sub: "of " + rm.items.length + " features" }),
10444
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(StatTile, { compact: true, label: "Remaining", value: String(rm.remaining), sub: "backend work" }),
10445
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(StatTile, { compact: true, label: "Est. effort", value: days ? days + " days" : "\u2014", sub: "sum of estimates, not calendar" }),
10446
- /* @__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" })
10447
10700
  ] }),
10448
- /* @__PURE__ */ (0, import_jsx_runtime79.jsxs)("div", { className: "fd-row", style: { gap: 10, flexWrap: "wrap" }, children: [
10449
- /* @__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 } }),
10450
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(Select, { placeholder: "All projects", value: project, onChange: (e) => setProject(e.target.value), options: projects, style: { width: 190 } }),
10451
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)("span", { style: { flex: 1 } }),
10452
- /* @__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)(
10453
10706
  Button,
10454
10707
  {
10455
10708
  size: "sm",
@@ -10463,7 +10716,7 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
10463
10716
  }
10464
10717
  )
10465
10718
  ] }),
10466
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(
10719
+ /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(
10467
10720
  Flag,
10468
10721
  {
10469
10722
  tone: "info",
@@ -10472,60 +10725,60 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
10472
10725
  actions: null
10473
10726
  }
10474
10727
  ),
10475
- /* @__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: [
10476
- /* @__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%" } }) }),
10477
10730
  items.map((item, n) => {
10478
10731
  const showPhase = item.phase !== lastPhase;
10479
10732
  lastPhase = item.phase;
10480
10733
  const inPhase = items.filter((i) => i.phase === item.phase).length;
10481
10734
  const isBoundary = n === firstPending;
10482
- return /* @__PURE__ */ (0, import_jsx_runtime79.jsxs)(React53.Fragment, { children: [
10483
- showPhase ? /* @__PURE__ */ (0, import_jsx_runtime79.jsxs)("div", { className: "fd-rm-era", children: [
10484
- /* @__PURE__ */ (0, import_jsx_runtime79.jsxs)("span", { className: "fd-row", style: { gap: 8, flexWrap: "wrap", alignItems: "baseline" }, children: [
10485
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)("span", { style: { fontWeight: 700 }, children: item.phase === 0 ? "Shipped" : "Phase " + item.phase + " \u2014 " + item.phaseName }),
10486
- 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: [
10487
10740
  fmtDate(item.phaseStart),
10488
10741
  " \u2013 ",
10489
10742
  fmtDate(item.date)
10490
10743
  ] }),
10491
- /* @__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: [
10492
10745
  "\xB7 ",
10493
10746
  inPhase,
10494
10747
  " feature",
10495
10748
  inPhase === 1 ? "" : "s"
10496
10749
  ] })
10497
10750
  ] }),
10498
- 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
10499
10752
  ] }) : null,
10500
- 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: [
10501
- /* @__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" }),
10502
10755
  " You are here \u2014 everything above is wired"
10503
10756
  ] }) }) : null,
10504
- /* @__PURE__ */ (0, import_jsx_runtime79.jsxs)("div", { className: "fd-rm-row", children: [
10505
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)("span", { className: "fd-rm-dot " + (item.implemented ? "is-shipped" : item.status === "next" ? "is-next" : "") }),
10506
- /* @__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: [
10507
10760
  fmtDate(item.date),
10508
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)("br", {}),
10509
- /* @__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 })
10510
10763
  ] }),
10511
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(RoadmapCard, { item, byKey, onOpenFlag })
10764
+ /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(RoadmapCard, { item, byKey, onOpenFlag })
10512
10765
  ] })
10513
10766
  ] }, item.key);
10514
10767
  }),
10515
- !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
10516
10769
  ] }) }) }),
10517
- /* @__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: [
10518
10771
  "Derived from the feature-flag registry \u2014 each entry's status is its flag's ",
10519
- /* @__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" }),
10520
10773
  " field, so this page cannot drift from what the apps actually do."
10521
10774
  ] })
10522
10775
  ] });
10523
10776
  }
10524
10777
 
10525
10778
  // src/components/platform/ComingSoon.tsx
10526
- var React54 = __toESM(require("react"), 1);
10779
+ var React55 = __toESM(require("react"), 1);
10527
10780
  var import_react_dom6 = require("react-dom");
10528
- var import_jsx_runtime80 = require("react/jsx-runtime");
10781
+ var import_jsx_runtime81 = require("react/jsx-runtime");
10529
10782
  var BYPASS_STORE = "fd.soon.bypass.v1";
10530
10783
  function readBypassed() {
10531
10784
  try {
@@ -10541,8 +10794,8 @@ function writeBypassed(list) {
10541
10794
  }
10542
10795
  }
10543
10796
  function useBypass(key) {
10544
- const [on, setOn] = React54.useState(() => !!key && readBypassed().indexOf(key) >= 0);
10545
- React54.useEffect(() => {
10797
+ const [on, setOn] = React55.useState(() => !!key && readBypassed().indexOf(key) >= 0);
10798
+ React55.useEffect(() => {
10546
10799
  setOn(!!key && readBypassed().indexOf(key) >= 0);
10547
10800
  }, [key]);
10548
10801
  const set = (next) => {
@@ -10555,43 +10808,43 @@ function useBypass(key) {
10555
10808
  return [on, set];
10556
10809
  }
10557
10810
  function SoonCard({ label, detail, backend, eta, effort, onRoadmap, allowed, onBypass }) {
10558
- return /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)(import_jsx_runtime80.Fragment, { children: [
10559
- /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("span", { className: "fd-soon-badge", children: [
10560
- /* @__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" }),
10561
10814
  label
10562
10815
  ] }),
10563
- detail ? /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("span", { className: "fd-soon-detail", children: detail }) : null,
10564
- backend ? /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("span", { className: "fd-soon-backend", children: [
10565
- /* @__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" }),
10566
10819
  " ",
10567
10820
  backend
10568
10821
  ] }) : null,
10569
- eta || effort || onRoadmap ? /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("span", { className: "fd-soon-meta", children: [
10570
- eta ? /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("span", { children: [
10571
- /* @__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" }),
10572
10825
  " ",
10573
10826
  eta
10574
10827
  ] }) : null,
10575
- effort ? /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("span", { children: [
10576
- /* @__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" }),
10577
10830
  " ",
10578
10831
  effort
10579
10832
  ] }) : null,
10580
- 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: [
10581
10834
  "See the roadmap ",
10582
- /* @__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" })
10583
10836
  ] }) : null
10584
10837
  ] }) : null,
10585
- allowed ? /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("button", { type: "button", className: "fd-soon-view", onClick: onBypass, children: [
10586
- /* @__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" }),
10587
10840
  " View and use it anyway"
10588
10841
  ] }) : null
10589
10842
  ] });
10590
10843
  }
10591
10844
  function useHoverCard(open2) {
10592
- const anchor = React54.useRef(null);
10593
- const [pos, setPos] = React54.useState(null);
10594
- React54.useLayoutEffect(() => {
10845
+ const anchor = React55.useRef(null);
10846
+ const [pos, setPos] = React55.useState(null);
10847
+ React55.useLayoutEffect(() => {
10595
10848
  if (!open2 || !anchor.current) {
10596
10849
  setPos(null);
10597
10850
  return;
@@ -10643,9 +10896,9 @@ function ComingSoon({
10643
10896
  const tip = [label, detail, backend ? "Needs " + backend : null, eta ? "ETA " + eta : null, effort].filter(Boolean).join(" \xB7 ");
10644
10897
  if (inline) {
10645
10898
  if (allowed && bypassed) {
10646
- 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: [
10647
10900
  children,
10648
- /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(
10901
+ /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(
10649
10902
  "button",
10650
10903
  {
10651
10904
  type: "button",
@@ -10653,12 +10906,12 @@ function ComingSoon({
10653
10906
  title: "Unwired \u2014 writes go to the simulated backend. " + tip + " Click to re-blur.",
10654
10907
  onClick: () => setBypassed(false),
10655
10908
  "aria-label": "Re-blur this unwired feature",
10656
- 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" })
10657
10910
  }
10658
10911
  )
10659
10912
  ] });
10660
10913
  }
10661
- return /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(
10914
+ return /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(
10662
10915
  InlineSoon,
10663
10916
  {
10664
10917
  label,
@@ -10678,20 +10931,20 @@ function ComingSoon({
10678
10931
  );
10679
10932
  }
10680
10933
  if (allowed && bypassed) {
10681
- return /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 14 }, ...rest, children: [
10682
- /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("div", { className: "fd-soon-bar", role: "status", children: [
10683
- /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("span", { className: "fd-soon-badge", children: [
10684
- /* @__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" }),
10685
10938
  "Unwired feature \u2014 you are using it anyway"
10686
10939
  ] }),
10687
- /* @__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." }),
10688
- /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("span", { className: "fd-soon-bar-actions", children: [
10689
- 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: [
10690
10943
  "Roadmap ",
10691
- /* @__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" })
10692
10945
  ] }) : null,
10693
- /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("button", { type: "button", className: "fd-soon-link", onClick: () => setBypassed(false), children: [
10694
- /* @__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" }),
10695
10948
  " Re-blur"
10696
10949
  ] })
10697
10950
  ] })
@@ -10699,10 +10952,10 @@ function ComingSoon({
10699
10952
  children
10700
10953
  ] });
10701
10954
  }
10702
- return /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("div", { className: ["fd-soon", className].filter(Boolean).join(" "), style: minHeight ? { minHeight } : void 0, ...rest, children: [
10703
- /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("div", { className: "fd-soon-under", style: { filter: "blur(" + blur + "px) saturate(.62)" }, ...{ inert: "" }, "aria-hidden": "true", children }),
10704
- /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("div", { className: "fd-soon-veil" }),
10705
- /* @__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)(
10706
10959
  SoonCard,
10707
10960
  {
10708
10961
  label,
@@ -10718,10 +10971,10 @@ function ComingSoon({
10718
10971
  ] });
10719
10972
  }
10720
10973
  function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, onBypass, blur, tip, className, rest, children }) {
10721
- const [open2, setOpen] = React54.useState(false);
10974
+ const [open2, setOpen] = React55.useState(false);
10722
10975
  const [anchor, pos] = useHoverCard(open2);
10723
10976
  const zIndex = useOverlayLayer(open2);
10724
- const close2 = React54.useRef(null);
10977
+ const close2 = React55.useRef(null);
10725
10978
  const show = () => {
10726
10979
  if (close2.current) {
10727
10980
  clearTimeout(close2.current);
@@ -10737,10 +10990,10 @@ function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, o
10737
10990
  setOpen(false);
10738
10991
  }, 140);
10739
10992
  };
10740
- React54.useEffect(() => () => {
10993
+ React55.useEffect(() => () => {
10741
10994
  if (close2.current) clearTimeout(close2.current);
10742
10995
  }, []);
10743
- return /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)(
10996
+ return /* @__PURE__ */ (0, import_jsx_runtime81.jsxs)(
10744
10997
  "span",
10745
10998
  {
10746
10999
  ref: anchor,
@@ -10751,8 +11004,8 @@ function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, o
10751
11004
  onBlur: hide,
10752
11005
  ...rest,
10753
11006
  children: [
10754
- /* @__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 }),
10755
- /* @__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)(
10756
11009
  "button",
10757
11010
  {
10758
11011
  type: "button",
@@ -10763,11 +11016,11 @@ function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, o
10763
11016
  onFocus: show,
10764
11017
  onBlur: hide,
10765
11018
  onClick: () => open2 ? setOpen(false) : show(),
10766
- 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" })
10767
11020
  }
10768
11021
  ),
10769
11022
  open2 && pos ? (0, import_react_dom6.createPortal)(
10770
- /* @__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)(
10771
11024
  "div",
10772
11025
  {
10773
11026
  className: "fd-soon-note fd-soon-hovercard",
@@ -10775,7 +11028,7 @@ function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, o
10775
11028
  style: { position: "fixed", left: pos.left, top: pos.top, bottom: pos.bottom, width: pos.width, zIndex },
10776
11029
  onMouseEnter: show,
10777
11030
  onMouseLeave: hide,
10778
- children: /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(
11031
+ children: /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(
10779
11032
  SoonCard,
10780
11033
  {
10781
11034
  label,
@@ -10805,10 +11058,10 @@ function formatEta(iso2) {
10805
11058
  var FormatEta = formatEta;
10806
11059
 
10807
11060
  // src/components/platform/Gate.tsx
10808
- var import_jsx_runtime81 = require("react/jsx-runtime");
11061
+ var import_jsx_runtime82 = require("react/jsx-runtime");
10809
11062
  function PermissionDenied({ permission, title, detail, compact: compact3 = false, className = "", ...rest }) {
10810
11063
  const need = Array.isArray(permission) ? permission : [permission].filter(Boolean);
10811
- return /* @__PURE__ */ (0, import_jsx_runtime81.jsxs)(
11064
+ return /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)(
10812
11065
  "div",
10813
11066
  {
10814
11067
  className: ["fd-stack", className].filter(Boolean).join(" "),
@@ -10824,14 +11077,14 @@ function PermissionDenied({ permission, title, detail, compact: compact3 = false
10824
11077
  },
10825
11078
  ...rest,
10826
11079
  children: [
10827
- /* @__PURE__ */ (0, import_jsx_runtime81.jsxs)("span", { className: "fd-row", style: { gap: 8 }, children: [
10828
- /* @__PURE__ */ (0, import_jsx_runtime81.jsx)("i", { className: "ph ph-lock-simple", style: { fontSize: 16, color: "var(--text-muted)" }, "aria-hidden": "true" }),
10829
- /* @__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" })
10830
11083
  ] }),
10831
- /* @__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." }),
10832
- need.length ? /* @__PURE__ */ (0, import_jsx_runtime81.jsxs)("span", { className: "fd-row", style: { gap: 6, flexWrap: "wrap" }, children: [
10833
- /* @__PURE__ */ (0, import_jsx_runtime81.jsx)("span", { className: "fd-overline fd-muted", children: "Requires" }),
10834
- 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: {
10835
11088
  fontSize: 11.5,
10836
11089
  padding: "2px 7px",
10837
11090
  borderRadius: 5,
@@ -10844,7 +11097,7 @@ function PermissionDenied({ permission, title, detail, compact: compact3 = false
10844
11097
  );
10845
11098
  }
10846
11099
  function GatePending({ compact: compact3 = false, className = "" }) {
10847
- return /* @__PURE__ */ (0, import_jsx_runtime81.jsxs)(
11100
+ return /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)(
10848
11101
  "div",
10849
11102
  {
10850
11103
  className: ["fd-stack", className].filter(Boolean).join(" "),
@@ -10860,11 +11113,11 @@ function GatePending({ compact: compact3 = false, className = "" }) {
10860
11113
  textAlign: "left"
10861
11114
  },
10862
11115
  children: [
10863
- /* @__PURE__ */ (0, import_jsx_runtime81.jsxs)("span", { className: "fd-row", style: { gap: 8 }, children: [
10864
- /* @__PURE__ */ (0, import_jsx_runtime81.jsx)("i", { className: "ph ph-arrows-clockwise", style: { fontSize: 16, color: "var(--text-muted)" }, "aria-hidden": "true" }),
10865
- /* @__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" })
10866
11119
  ] }),
10867
- /* @__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." })
10868
11121
  ]
10869
11122
  }
10870
11123
  );
@@ -10874,7 +11127,7 @@ function Gate({ perm, anyOf, role, silent = false, fallback, pendingFallback, co
10874
11127
  if (pending) {
10875
11128
  if (pendingFallback !== void 0) return pendingFallback;
10876
11129
  if (silent) return null;
10877
- return /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(GatePending, { compact: compact3 });
11130
+ return /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(GatePending, { compact: compact3 });
10878
11131
  }
10879
11132
  let ok = true;
10880
11133
  if (perm) ok = ok && can2(perm);
@@ -10883,7 +11136,7 @@ function Gate({ perm, anyOf, role, silent = false, fallback, pendingFallback, co
10883
11136
  if (ok) return children;
10884
11137
  if (fallback !== void 0) return fallback;
10885
11138
  if (silent) return null;
10886
- 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 });
10887
11140
  }
10888
11141
  function FeatureGate({
10889
11142
  flag,
@@ -10906,7 +11159,7 @@ function FeatureGate({
10906
11159
  const f = SessionKit.findFlag(flag) || {};
10907
11160
  const missing = rt.missing || [];
10908
11161
  const canBypass = pending ? false : bypassPerm === null ? false : !bypassPerm || can2(bypassPerm);
10909
- return /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(
11162
+ return /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(
10910
11163
  ComingSoon,
10911
11164
  {
10912
11165
  label: label || (variant === "inline" ? f.label || "Not wired yet" : "Designed \u2014 backend not wired yet"),
@@ -10927,22 +11180,22 @@ function FeatureGate({
10927
11180
  function PermissionHint({ perm, children }) {
10928
11181
  const { can: can2, pending } = useSessionContext();
10929
11182
  if (pending) {
10930
- 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 }) });
10931
11184
  }
10932
11185
  if (can2(perm)) return children;
10933
- return /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(
11186
+ return /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(
10934
11187
  "span",
10935
11188
  {
10936
11189
  title: "Requires " + (Array.isArray(perm) ? perm.join(", ") : perm),
10937
11190
  style: { display: "inline-flex", opacity: 0.45, cursor: "not-allowed" },
10938
11191
  "aria-disabled": "true",
10939
- 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 })
10940
11193
  }
10941
11194
  );
10942
11195
  }
10943
11196
 
10944
11197
  // src/components/platform/ModeSwitch.tsx
10945
- var import_jsx_runtime82 = require("react/jsx-runtime");
11198
+ var import_jsx_runtime83 = require("react/jsx-runtime");
10946
11199
  function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog, onOpenSpec, summary }) {
10947
11200
  const mode2 = useRuntimeMode();
10948
11201
  const panel = useInlinePanel();
@@ -10954,8 +11207,8 @@ function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog
10954
11207
  RuntimeKit.setMode(next);
10955
11208
  setOpen(false);
10956
11209
  };
10957
- return /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)("span", { style: { position: "relative", display: "inline-flex" }, ref, children: [
10958
- /* @__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)(
10959
11212
  "button",
10960
11213
  {
10961
11214
  type: "button",
@@ -10965,29 +11218,29 @@ function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog
10965
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.",
10966
11219
  className: "fd-mode-btn" + (test ? " is-test" : "") + (open2 ? " is-open" : ""),
10967
11220
  children: [
10968
- /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("i", { className: "ph " + (test ? "ph-flask" : "ph-lightning"), style: { fontSize: 17 } }),
10969
- 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
10970
11223
  ]
10971
11224
  }
10972
11225
  ),
10973
- 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: [
10974
- /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)("span", { className: "fd-row", style: { gap: 10, padding: "12px 14px", borderBottom: "1px solid var(--border)" }, children: [
10975
- /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)("span", { className: "fd-badge " + (test ? "fd-badge-warning" : "fd-badge-neutral"), children: [
10976
- /* @__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" }),
10977
11230
  test ? "Test mode" : "Live mode"
10978
11231
  ] }),
10979
- 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: [
10980
11233
  requestCount,
10981
11234
  " simulated request",
10982
11235
  requestCount === 1 ? "" : "s"
10983
11236
  ] }) : null,
10984
- /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("span", { style: { flex: 1 } }),
10985
- 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
10986
11239
  ] }),
10987
- /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)("span", { style: { display: "block", padding: "12px 14px", borderBottom: "1px solid var(--border)" }, children: [
10988
- /* @__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." }),
10989
- /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)("span", { className: "fd-row", style: { gap: 8, marginTop: 10, flexWrap: "wrap" }, children: [
10990
- /* @__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: [
10991
11244
  s.endpointsWired,
10992
11245
  " endpoint",
10993
11246
  s.endpointsWired === 1 ? "" : "s",
@@ -10997,58 +11250,58 @@ function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog
10997
11250
  s.total,
10998
11251
  " features complete"
10999
11252
  ] }),
11000
- onOpenSpec ? /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)(import_jsx_runtime82.Fragment, { children: [
11001
- /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("span", { style: { flex: 1 } }),
11002
- /* @__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: () => {
11003
11256
  setOpen(false);
11004
11257
  onOpenSpec();
11005
11258
  }, children: [
11006
11259
  "API spec ",
11007
- /* @__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" })
11008
11261
  ] })
11009
11262
  ] }) : null
11010
11263
  ] })
11011
11264
  ] }),
11012
- /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)("span", { className: "fd-mode-choice", children: [
11013
- /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)("button", { type: "button", className: "fd-mode-opt" + (!test ? " is-on" : ""), onClick: () => go("live"), children: [
11014
- /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("i", { className: "ph ph-lightning", "aria-hidden": "true" }),
11015
- /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)("span", { className: "fd-mode-opt-text", children: [
11016
- /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("span", { className: "fd-mode-opt-title", children: "Live mode" }),
11017
- /* @__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" })
11018
11271
  ] }),
11019
- !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
11020
11273
  ] }),
11021
- /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)("button", { type: "button", className: "fd-mode-opt" + (test ? " is-on" : ""), onClick: () => go("test"), children: [
11022
- /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("i", { className: "ph ph-flask", "aria-hidden": "true" }),
11023
- /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)("span", { className: "fd-mode-opt-text", children: [
11024
- /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("span", { className: "fd-mode-opt-title", children: "Test mode" }),
11025
- /* @__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" })
11026
11279
  ] }),
11027
- 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
11028
11281
  ] })
11029
11282
  ] }),
11030
- 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
11031
11284
  ] }) }) : null
11032
11285
  ] });
11033
11286
  }
11034
11287
  function TestModeBar({ onExit }) {
11035
11288
  const mode2 = useRuntimeMode();
11036
11289
  if (mode2 !== "test") return null;
11037
- return /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)("div", { className: "fd-testbar", role: "status", children: [
11038
- /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)("span", { className: "fd-badge fd-badge-warning", children: [
11039
- /* @__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" }),
11040
11293
  "Test mode"
11041
11294
  ] }),
11042
- /* @__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." }),
11043
- /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)("button", { type: "button", className: "fd-soon-link", onClick: () => onExit ? onExit() : RuntimeKit.setMode("live"), children: [
11044
- /* @__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" }),
11045
11298
  " Back to live mode"
11046
11299
  ] })
11047
11300
  ] });
11048
11301
  }
11049
11302
 
11050
11303
  // src/components/planner/ChannelMeta.tsx
11051
- var import_jsx_runtime83 = require("react/jsx-runtime");
11304
+ var import_jsx_runtime84 = require("react/jsx-runtime");
11052
11305
  var CHANNEL_WEIGHTS = {
11053
11306
  "OOH": 50,
11054
11307
  "DOOH": 50,
@@ -11101,9 +11354,9 @@ function ChannelTag({ channel, size = "md", showLabel = true, dot = false, weigh
11101
11354
  const m = ChannelMeta(channel);
11102
11355
  const wt = channelWeightOf(channel || "");
11103
11356
  if (dot) {
11104
- 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 });
11105
11358
  }
11106
- return /* @__PURE__ */ (0, import_jsx_runtime83.jsxs)(
11359
+ return /* @__PURE__ */ (0, import_jsx_runtime84.jsxs)(
11107
11360
  "span",
11108
11361
  {
11109
11362
  className: ["fd-chan", size === "sm" ? "fd-chan-sm" : "", className].filter(Boolean).join(" "),
@@ -11111,16 +11364,16 @@ function ChannelTag({ channel, size = "md", showLabel = true, dot = false, weigh
11111
11364
  style: { "--chan": m.color },
11112
11365
  ...rest,
11113
11366
  children: [
11114
- /* @__PURE__ */ (0, import_jsx_runtime83.jsx)("i", { className: "ph ph-" + m.icon, "aria-hidden": "true" }),
11115
- showLabel ? /* @__PURE__ */ (0, import_jsx_runtime83.jsx)("span", { className: "fd-chan-label", children: m.label }) : null,
11116
- 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
11117
11370
  ]
11118
11371
  }
11119
11372
  );
11120
11373
  }
11121
11374
 
11122
11375
  // src/components/planner/SaturationDistribution.tsx
11123
- var import_jsx_runtime84 = require("react/jsx-runtime");
11376
+ var import_jsx_runtime85 = require("react/jsx-runtime");
11124
11377
  var BANDS2 = [
11125
11378
  { key: "weak", label: "Weak", n: 1, range: "< 50" },
11126
11379
  { key: "adequate", label: "Adequate", n: 2, range: "50\u2013100" },
@@ -11131,24 +11384,24 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
11131
11384
  const grouped = BANDS2.map((b) => ({ ...b, items: campuses.filter((c) => c.band === b.key) }));
11132
11385
  const tallest = Math.max(1, ...grouped.map((g) => g.items.length));
11133
11386
  const floor = BANDS2.find((b) => b.key === floorBand) || BANDS2[0];
11134
- return /* @__PURE__ */ (0, import_jsx_runtime84.jsxs)("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 16 }, children: [
11135
- /* @__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) => {
11136
11389
  const mark = "var(--csi-" + g.n + "-mark)";
11137
11390
  const active = selectedBand === g.key;
11138
- return /* @__PURE__ */ (0, import_jsx_runtime84.jsxs)(
11391
+ return /* @__PURE__ */ (0, import_jsx_runtime85.jsxs)(
11139
11392
  "button",
11140
11393
  {
11141
11394
  type: "button",
11142
11395
  onClick: onSelectBand ? () => onSelectBand(active ? null : g.key) : void 0,
11143
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)" },
11144
11397
  children: [
11145
- /* @__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) => (
11146
11399
  // `overflow: hidden` + `white-space: nowrap` only clips once the span
11147
11400
  // actually HAS a bounded width to clip against (see the grid/flex
11148
11401
  // `minWidth: 0` chain above) — `textOverflow: ellipsis` then makes
11149
11402
  // that clip readable instead of a hard cut mid-letter; the full name
11150
11403
  // is still one hover away via `title`.
11151
- /* @__PURE__ */ (0, import_jsx_runtime84.jsx)(
11404
+ /* @__PURE__ */ (0, import_jsx_runtime85.jsx)(
11152
11405
  "span",
11153
11406
  {
11154
11407
  title: c.name + " \xB7 " + c.crp,
@@ -11158,13 +11411,13 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
11158
11411
  c.name
11159
11412
  )
11160
11413
  )) }),
11161
- /* @__PURE__ */ (0, import_jsx_runtime84.jsxs)("span", { className: "fd-row", style: { gap: 8, alignItems: "baseline" }, children: [
11162
- /* @__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 }),
11163
- /* @__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)) })
11164
11417
  ] }),
11165
- /* @__PURE__ */ (0, import_jsx_runtime84.jsxs)("span", { className: "fd-stack", style: { gap: 1 }, children: [
11166
- /* @__PURE__ */ (0, import_jsx_runtime84.jsx)("span", { className: "fd-label-lg", children: g.label }),
11167
- /* @__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: [
11168
11421
  "CRP ",
11169
11422
  g.range
11170
11423
  ] })
@@ -11174,10 +11427,10 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
11174
11427
  g.key
11175
11428
  );
11176
11429
  }) }),
11177
- 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: [
11178
- /* @__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)) }),
11179
- /* @__PURE__ */ (0, import_jsx_runtime84.jsxs)("span", { className: "fd-body-sm fd-secondary", style: { flex: 1, minWidth: 240 }, children: [
11180
- /* @__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: [
11181
11434
  "Plan floor ",
11182
11435
  floorScore
11183
11436
  ] }),
@@ -11188,8 +11441,8 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
11188
11441
  }
11189
11442
 
11190
11443
  // src/components/planner/MixGap.tsx
11191
- var React55 = __toESM(require("react"), 1);
11192
- var import_jsx_runtime85 = require("react/jsx-runtime");
11444
+ var React56 = __toESM(require("react"), 1);
11445
+ var import_jsx_runtime86 = require("react/jsx-runtime");
11193
11446
  var MIX_GAP_LAYOUT = {
11194
11447
  trackHeight: 30,
11195
11448
  barHeight: 20,
@@ -11203,19 +11456,19 @@ function mixGapOffset(value, max) {
11203
11456
  }
11204
11457
  function MixGap({ rows = [], loading = false, className = "" }) {
11205
11458
  const max = Math.max(1, ...rows.flatMap((r) => [r.target, r.realized]));
11206
- const [hover, setHover] = React55.useState(null);
11459
+ const [hover, setHover] = React56.useState(null);
11207
11460
  const toneOf = (gap) => gap >= -1 ? "ok" : gap >= -4 ? "warn" : "danger";
11208
11461
  const TONE = { ok: "var(--ok-solid)", warn: "var(--warn-solid)", danger: "var(--danger-solid)" };
11209
11462
  const { trackHeight, barHeight, targetWidth, labelGap } = MIX_GAP_LAYOUT;
11210
11463
  const barTop = (trackHeight - barHeight) / 2;
11211
- return /* @__PURE__ */ (0, import_jsx_runtime85.jsxs)("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 4 }, children: [
11212
- /* @__PURE__ */ (0, import_jsx_runtime85.jsxs)("div", { className: "fd-row", style: { gap: 16, justifyContent: "flex-end", paddingBottom: 6, flexWrap: "wrap" }, children: [
11213
- [["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: [
11214
- /* @__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 } }),
11215
11468
  l
11216
11469
  ] }, l)),
11217
- /* @__PURE__ */ (0, import_jsx_runtime85.jsxs)("span", { className: "fd-row fd-body-sm fd-muted", style: { gap: 6 }, children: [
11218
- /* @__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 } }),
11219
11472
  "Target"
11220
11473
  ] })
11221
11474
  ] }),
@@ -11224,7 +11477,7 @@ function MixGap({ rows = [], loading = false, className = "" }) {
11224
11477
  const tone = toneOf(gap);
11225
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 : "");
11226
11479
  const labelLeft = r.realized > r.target ? `calc(${mixGapOffset(r.realized, max)} + ${labelGap}px)` : `calc(${mixGapOffset(r.target, max)} + ${targetWidth / 2 + labelGap}px)`;
11227
- return /* @__PURE__ */ (0, import_jsx_runtime85.jsxs)(
11480
+ return /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)(
11228
11481
  "div",
11229
11482
  {
11230
11483
  className: "fd-row",
@@ -11232,15 +11485,15 @@ function MixGap({ rows = [], loading = false, className = "" }) {
11232
11485
  onMouseEnter: () => setHover(r.channel),
11233
11486
  onMouseLeave: () => setHover(null),
11234
11487
  children: [
11235
- /* @__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" }) }),
11236
- /* @__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: [
11237
- /* @__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)" } }),
11238
- /* @__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 } }),
11239
- /* @__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: [
11240
11493
  r.realized,
11241
11494
  "%"
11242
11495
  ] }),
11243
- 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
11244
11497
  ] }) })
11245
11498
  ]
11246
11499
  },
@@ -11251,7 +11504,7 @@ function MixGap({ rows = [], loading = false, className = "" }) {
11251
11504
  }
11252
11505
 
11253
11506
  // src/components/planner/ChannelContribution.tsx
11254
- var import_jsx_runtime86 = require("react/jsx-runtime");
11507
+ var import_jsx_runtime87 = require("react/jsx-runtime");
11255
11508
  var money = (n) => "$" + Math.round(n).toLocaleString();
11256
11509
  function ChannelContribution({
11257
11510
  channels = [],
@@ -11267,9 +11520,9 @@ function ChannelContribution({
11267
11520
  const grand = total !== void 0 ? total : base + bonus;
11268
11521
  const pct = (v) => grand ? v / grand * 100 : 0;
11269
11522
  const spendTotal = channels.reduce((s, c) => s + Number(String(c.spend || 0).replace(/[^0-9.]/g, "")), 0);
11270
- return /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 16 }, children: [
11271
- 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: [
11272
- 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)(
11273
11526
  "span",
11274
11527
  {
11275
11528
  title: c.name + " \xB7 " + c.crp.toFixed(1) + " CRP",
@@ -11278,7 +11531,7 @@ function ChannelContribution({
11278
11531
  },
11279
11532
  c.name
11280
11533
  )),
11281
- bonus > 0 ? /* @__PURE__ */ (0, import_jsx_runtime86.jsx)(
11534
+ bonus > 0 ? /* @__PURE__ */ (0, import_jsx_runtime87.jsx)(
11282
11535
  "span",
11283
11536
  {
11284
11537
  title: "Surround-sound bonus +" + bonusPct + "%",
@@ -11287,18 +11540,18 @@ function ChannelContribution({
11287
11540
  }
11288
11541
  ) : null
11289
11542
  ] }),
11290
- showTable ? /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("table", { className: "fd-table", style: { fontSize: "var(--body-sm-size)" }, children: [
11291
- /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("tr", { children: [
11292
- /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("th", { style: { width: "34%" }, children: "Channel" }),
11293
- /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("th", { style: { width: "16%" }, children: "Weight" }),
11294
- /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("th", { className: "is-num", style: { width: "16%" }, children: "Spend" }),
11295
- /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("th", { className: "is-num", style: { width: "17%" }, children: "CRP" }),
11296
- /* @__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" })
11297
11550
  ] }) }),
11298
- /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("tbody", { children: [
11299
- channels.map((c) => /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("tr", { children: [
11300
- /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("td", { children: /* @__PURE__ */ (0, import_jsx_runtime86.jsx)(ChannelTag, { channel: c.name, size: "sm" }) }),
11301
- /* @__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)(
11302
11555
  "span",
11303
11556
  {
11304
11557
  className: "fd-badge fd-badge-neutral",
@@ -11307,38 +11560,38 @@ function ChannelContribution({
11307
11560
  children: "weight " + (channelWeightOf(c.name) || 0)
11308
11561
  }
11309
11562
  ) }),
11310
- /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("td", { className: "is-num", children: c.spend }),
11311
- /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("td", { className: "is-num", children: c.crp.toFixed(1) }),
11312
- /* @__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: [
11313
11566
  pct(c.crp).toFixed(0),
11314
11567
  "%"
11315
11568
  ] })
11316
11569
  ] }, c.name)),
11317
- bonus > 0 ? /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("tr", { children: [
11318
- /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("td", { children: /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("span", { className: "fd-row", style: { gap: 9, fontWeight: 600 }, children: [
11319
- /* @__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" } }),
11320
11573
  "Surround-sound bonus"
11321
11574
  ] }) }),
11322
- /* @__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: [
11323
11576
  "+",
11324
11577
  bonusPct,
11325
11578
  "% of +",
11326
11579
  bonusMax,
11327
11580
  "%"
11328
11581
  ] }) }),
11329
- /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("td", { className: "is-num fd-muted", children: "\u2014" }),
11330
- /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("td", { className: "is-num", children: bonus.toFixed(1) }),
11331
- /* @__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: [
11332
11585
  pct(bonus).toFixed(0),
11333
11586
  "%"
11334
11587
  ] })
11335
11588
  ] }) : null,
11336
- /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("tr", { style: { background: "var(--surface-2)" }, children: [
11337
- /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("td", { style: { fontWeight: 700 }, children: "Campus total" }),
11338
- /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("td", {}),
11339
- /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("td", { className: "is-num", style: { fontWeight: 700 }, children: money(spendTotal) }),
11340
- /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("td", { className: "is-num", style: { fontWeight: 700 }, children: grand.toFixed(1) }),
11341
- /* @__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%" })
11342
11595
  ] })
11343
11596
  ] })
11344
11597
  ] }) : null
@@ -11346,8 +11599,8 @@ function ChannelContribution({
11346
11599
  }
11347
11600
 
11348
11601
  // src/components/planner/BudgetReallocator.tsx
11349
- var React56 = __toESM(require("react"), 1);
11350
- var import_jsx_runtime87 = require("react/jsx-runtime");
11602
+ var React57 = __toESM(require("react"), 1);
11603
+ var import_jsx_runtime88 = require("react/jsx-runtime");
11351
11604
  var bandFor = (crp) => crp >= 200 ? "dominant" : crp >= 100 ? "strong" : crp >= 50 ? "adequate" : "weak";
11352
11605
  function BudgetReallocator({
11353
11606
  campus,
@@ -11362,8 +11615,8 @@ function BudgetReallocator({
11362
11615
  onCancel,
11363
11616
  className = ""
11364
11617
  }) {
11365
- const [draft, setDraft] = React56.useState(spend);
11366
- React56.useEffect(() => setDraft(spend), [spend]);
11618
+ const [draft, setDraft] = React57.useState(spend);
11619
+ React57.useEffect(() => setDraft(spend), [spend]);
11367
11620
  const dirty = draft !== spend;
11368
11621
  const nextCrp = scoreFor ? scoreFor(draft) : crp;
11369
11622
  const nextBand = bandFor(nextCrp);
@@ -11378,10 +11631,10 @@ function BudgetReallocator({
11378
11631
  setDraft(spend);
11379
11632
  if (onCancel) onCancel();
11380
11633
  };
11381
- const trackRef = React56.useRef(null);
11382
- const chipRef = React56.useRef(null);
11383
- const [chipLeft, setChipLeft] = React56.useState(null);
11384
- React56.useLayoutEffect(() => {
11634
+ const trackRef = React57.useRef(null);
11635
+ const chipRef = React57.useRef(null);
11636
+ const [chipLeft, setChipLeft] = React57.useState(null);
11637
+ React57.useLayoutEffect(() => {
11385
11638
  const track = trackRef.current;
11386
11639
  if (!dirty || !track) {
11387
11640
  setChipLeft(null);
@@ -11402,23 +11655,23 @@ function BudgetReallocator({
11402
11655
  ro.observe(track);
11403
11656
  return () => ro.disconnect();
11404
11657
  }, [dirty, pct]);
11405
- return /* @__PURE__ */ (0, import_jsx_runtime87.jsxs)(
11658
+ return /* @__PURE__ */ (0, import_jsx_runtime88.jsxs)(
11406
11659
  "div",
11407
11660
  {
11408
11661
  className: ["fd-stack", className].filter(Boolean).join(" "),
11409
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)" },
11410
11663
  children: [
11411
- /* @__PURE__ */ (0, import_jsx_runtime87.jsxs)("div", { className: "fd-row", style: { gap: 12, flexWrap: "wrap" }, children: [
11412
- /* @__PURE__ */ (0, import_jsx_runtime87.jsx)("span", { className: "fd-h4", style: { flex: 1, minWidth: 140 }, children: campus }),
11413
- /* @__PURE__ */ (0, import_jsx_runtime87.jsx)(CsiBadge, { band: nowBand, crp, size: "medium" }),
11414
- dirty ? /* @__PURE__ */ (0, import_jsx_runtime87.jsxs)(import_jsx_runtime87.Fragment, { children: [
11415
- /* @__PURE__ */ (0, import_jsx_runtime87.jsx)("i", { className: "ph ph-arrow-right fd-muted", "aria-hidden": "true" }),
11416
- /* @__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 })
11417
11670
  ] }) : null
11418
11671
  ] }),
11419
- /* @__PURE__ */ (0, import_jsx_runtime87.jsxs)("div", { className: "fd-slider", ref: trackRef, children: [
11420
- /* @__PURE__ */ (0, import_jsx_runtime87.jsx)("span", { className: "fd-slider-fill", style: { width: pct + "%" } }),
11421
- 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)(
11422
11675
  "span",
11423
11676
  {
11424
11677
  ref: chipRef,
@@ -11430,7 +11683,7 @@ function BudgetReallocator({
11430
11683
  children: (delta < 0 ? "\u2212$" : "+$") + Math.abs(delta).toLocaleString()
11431
11684
  }
11432
11685
  ) : null,
11433
- /* @__PURE__ */ (0, import_jsx_runtime87.jsx)(
11686
+ /* @__PURE__ */ (0, import_jsx_runtime88.jsx)(
11434
11687
  "input",
11435
11688
  {
11436
11689
  type: "range",
@@ -11446,13 +11699,13 @@ function BudgetReallocator({
11446
11699
  }
11447
11700
  )
11448
11701
  ] }),
11449
- /* @__PURE__ */ (0, import_jsx_runtime87.jsxs)("div", { className: "fd-row", style: { gap: 12, flexWrap: "wrap" }, children: [
11450
- /* @__PURE__ */ (0, import_jsx_runtime87.jsxs)("span", { className: "fd-stack", style: { gap: 2, flex: 1, minWidth: 150 }, children: [
11451
- /* @__PURE__ */ (0, import_jsx_runtime87.jsx)("span", { className: "fd-num", style: { fontSize: 19, fontWeight: 700 }, children: "$" + draft.toLocaleString() }),
11452
- /* @__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." })
11453
11706
  ] }),
11454
- /* @__PURE__ */ (0, import_jsx_runtime87.jsx)("button", { type: "button", className: "fd-btn fd-btn-ghost", disabled: !dirty, onClick: revert, children: "Cancel" }),
11455
- /* @__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)(
11456
11709
  "button",
11457
11710
  {
11458
11711
  type: "button",
@@ -11471,7 +11724,7 @@ function BudgetReallocator({
11471
11724
  }
11472
11725
 
11473
11726
  // src/components/planner/SurroundSound.tsx
11474
- var import_jsx_runtime88 = require("react/jsx-runtime");
11727
+ var import_jsx_runtime89 = require("react/jsx-runtime");
11475
11728
  var CATEGORIES = [
11476
11729
  { key: "ooh", label: "OOH", icon: "flag-banner", color: "var(--ch-ooh)" },
11477
11730
  { key: "transit", label: "Transit", icon: "bus", color: "var(--ch-transit)" },
@@ -11483,26 +11736,26 @@ var CATEGORIES = [
11483
11736
  function SurroundSound({ present = [], bonusPct = 0, bonusMax = 40, missedCost, className = "" }) {
11484
11737
  const earned = Math.max(0, Math.min(1, bonusPct / bonusMax));
11485
11738
  const single = present.length <= 2;
11486
- return /* @__PURE__ */ (0, import_jsx_runtime88.jsxs)("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 14 }, children: [
11487
- /* @__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) => {
11488
11741
  const on = present.includes(c.key);
11489
- return /* @__PURE__ */ (0, import_jsx_runtime88.jsxs)(
11742
+ return /* @__PURE__ */ (0, import_jsx_runtime89.jsxs)(
11490
11743
  "span",
11491
11744
  {
11492
11745
  title: c.label + (on ? " \u2014 present" : " \u2014 not bought"),
11493
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)" },
11494
11747
  children: [
11495
- /* @__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" }),
11496
- /* @__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 })
11497
11750
  ]
11498
11751
  },
11499
11752
  c.key
11500
11753
  );
11501
11754
  }) }),
11502
- /* @__PURE__ */ (0, import_jsx_runtime88.jsxs)("div", { className: "fd-stack", style: { gap: 8 }, children: [
11503
- /* @__PURE__ */ (0, import_jsx_runtime88.jsxs)("div", { className: "fd-row", style: { justifyContent: "space-between", gap: 12 }, children: [
11504
- /* @__PURE__ */ (0, import_jsx_runtime88.jsx)("span", { className: "fd-label-lg", children: "Surround-sound bonus earned" }),
11505
- /* @__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: [
11506
11759
  "+",
11507
11760
  bonusPct,
11508
11761
  "% of +",
@@ -11510,8 +11763,8 @@ function SurroundSound({ present = [], bonusPct = 0, bonusMax = 40, missedCost,
11510
11763
  "%"
11511
11764
  ] })
11512
11765
  ] }),
11513
- /* @__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)" } }) }),
11514
- /* @__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: [
11515
11768
  present.length,
11516
11769
  " of 6 channel categories present.",
11517
11770
  " ",
@@ -11523,7 +11776,7 @@ function SurroundSound({ present = [], bonusPct = 0, bonusMax = 40, missedCost,
11523
11776
  }
11524
11777
 
11525
11778
  // src/components/planner/Importance.tsx
11526
- var import_jsx_runtime89 = require("react/jsx-runtime");
11779
+ var import_jsx_runtime90 = require("react/jsx-runtime");
11527
11780
  var IMPORTANCE_LEVELS = [
11528
11781
  { id: "nudge", rank: 1, label: "Nudge", icon: "feather", description: "Breaks a tie, nothing more." },
11529
11782
  { id: "lean", rank: 2, label: "Lean", icon: "arrow-bend-up-right", description: "A mild preference between otherwise equal options." },
@@ -11553,7 +11806,7 @@ function importanceTokens(id) {
11553
11806
  function ImportanceTag({ level, showLabel = true, size = "sm", className = "", disabled = false }) {
11554
11807
  const lvl = importanceLevel(level);
11555
11808
  const t = importanceTokens(level);
11556
- return /* @__PURE__ */ (0, import_jsx_runtime89.jsxs)(
11809
+ return /* @__PURE__ */ (0, import_jsx_runtime90.jsxs)(
11557
11810
  "span",
11558
11811
  {
11559
11812
  className: ["fd-imp-tag", size === "md" ? "is-md" : "", disabled ? "is-disabled" : "", className].filter(Boolean).join(" "),
@@ -11561,16 +11814,16 @@ function ImportanceTag({ level, showLabel = true, size = "sm", className = "", d
11561
11814
  title: lvl.label + " \u2014 " + lvl.description,
11562
11815
  "aria-disabled": disabled ? "true" : void 0,
11563
11816
  children: [
11564
- /* @__PURE__ */ (0, import_jsx_runtime89.jsx)("i", { className: "ph ph-" + lvl.icon, "aria-hidden": "true" }),
11565
- 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 })
11566
11819
  ]
11567
11820
  }
11568
11821
  );
11569
11822
  }
11570
11823
 
11571
11824
  // src/components/planner/PreferenceMeter.tsx
11572
- var React57 = __toESM(require("react"), 1);
11573
- var import_jsx_runtime90 = require("react/jsx-runtime");
11825
+ var React58 = __toESM(require("react"), 1);
11826
+ var import_jsx_runtime91 = require("react/jsx-runtime");
11574
11827
  function preferenceScore(criteria) {
11575
11828
  const earned = criteria.reduce((n, c) => n + (Number(c.earned) || 0), 0);
11576
11829
  const weight = criteria.reduce((n, c) => n + (Number(c.weight) || 0), 0);
@@ -11599,8 +11852,8 @@ function PreferenceMeter({
11599
11852
  className = ""
11600
11853
  }) {
11601
11854
  const value = score == null ? preferenceScore(criteria) : score;
11602
- const segments = React57.useMemo(() => preferenceSegments(criteria), [criteria]);
11603
- return /* @__PURE__ */ (0, import_jsx_runtime90.jsx)(
11855
+ const segments = React58.useMemo(() => preferenceSegments(criteria), [criteria]);
11856
+ return /* @__PURE__ */ (0, import_jsx_runtime91.jsx)(
11604
11857
  ScoreMeter,
11605
11858
  {
11606
11859
  score: value,
@@ -11612,22 +11865,22 @@ function PreferenceMeter({
11612
11865
  placement,
11613
11866
  className,
11614
11867
  breakdownLabel: breakdownTitle,
11615
- breakdown: /* @__PURE__ */ (0, import_jsx_runtime90.jsxs)("div", { className: "fd-prefbreak", children: [
11616
- /* @__PURE__ */ (0, import_jsx_runtime90.jsxs)("div", { className: "fd-prefbreak-head", children: [
11617
- /* @__PURE__ */ (0, import_jsx_runtime90.jsx)("span", { className: "fd-label-lg", children: breakdownTitle }),
11618
- /* @__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) })
11619
11872
  ] }),
11620
- /* @__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) => {
11621
11874
  const pct = c.weight > 0 ? Math.round((Number(c.earned) || 0) / c.weight * 100) : 0;
11622
- return /* @__PURE__ */ (0, import_jsx_runtime90.jsxs)("li", { className: pct === 0 ? "fd-prefbreak-item is-unmet" : "fd-prefbreak-item", children: [
11623
- /* @__PURE__ */ (0, import_jsx_runtime90.jsx)(ImportanceTag, { level: c.importance }),
11624
- /* @__PURE__ */ (0, import_jsx_runtime90.jsxs)("span", { className: "fd-prefbreak-text", children: [
11625
- /* @__PURE__ */ (0, import_jsx_runtime90.jsx)("span", { className: "fd-prefbreak-label", children: c.label }),
11626
- 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
11627
11880
  ] }),
11628
- /* @__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: [
11629
11882
  Math.round(Number(c.earned) || 0),
11630
- /* @__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: "/" }),
11631
11884
  Math.round(c.weight)
11632
11885
  ] })
11633
11886
  ] }, c.id);
@@ -11638,10 +11891,10 @@ function PreferenceMeter({
11638
11891
  }
11639
11892
 
11640
11893
  // src/components/chat/AgentChatPanel.tsx
11641
- var React63 = __toESM(require("react"), 1);
11894
+ var React64 = __toESM(require("react"), 1);
11642
11895
 
11643
11896
  // src/components/chat/chatEngine.ts
11644
- var React58 = __toESM(require("react"), 1);
11897
+ var React59 = __toESM(require("react"), 1);
11645
11898
  var CHAT_UNAVAILABLE = "chat_unavailable";
11646
11899
  var JOB_PENDING = ["queued", "running"];
11647
11900
  var JOB_SUCCESS = ["completed", "recovered"];
@@ -11695,22 +11948,22 @@ function useChatEngine(opts) {
11695
11948
  onClear,
11696
11949
  onFeedback
11697
11950
  } = opts || {};
11698
- const [status, setStatus] = React58.useState("idle");
11699
- const [threadId, setThreadId] = React58.useState(null);
11700
- const [messages, setMessages] = React58.useState([]);
11701
- const [queue, setQueue] = React58.useState([]);
11702
- const [fatal, setFatal] = React58.useState(null);
11703
- const [busy, setBusy] = React58.useState(false);
11704
- const [turnStartedAt, setTurnStartedAt] = React58.useState(null);
11705
- const listRef = React58.useRef([]);
11706
- const queueRef = React58.useRef([]);
11707
- const busyRef = React58.useRef(false);
11708
- const stoppedRef = React58.useRef(false);
11709
- const abortRef = React58.useRef(null);
11710
- const serverCount = React58.useRef(0);
11711
- const threadRef = React58.useRef(null);
11712
- const mounted = React58.useRef(true);
11713
- 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(() => {
11714
11967
  mounted.current = true;
11715
11968
  return () => {
11716
11969
  mounted.current = false;
@@ -11732,14 +11985,14 @@ function useChatEngine(opts) {
11732
11985
  }
11733
11986
  return false;
11734
11987
  };
11735
- const loadThread = React58.useCallback(async (id) => {
11988
+ const loadThread = React59.useCallback(async (id) => {
11736
11989
  const data = await apiAdapter.getThread(id);
11737
11990
  const list = [...data && data.messages || []];
11738
11991
  serverCount.current = list.length;
11739
11992
  commit(list);
11740
11993
  return list;
11741
11994
  }, [apiAdapter]);
11742
- React58.useEffect(() => {
11995
+ React59.useEffect(() => {
11743
11996
  if (!apiAdapter) {
11744
11997
  setStatus("idle");
11745
11998
  setFatal(null);
@@ -11952,7 +12205,7 @@ function useChatEngine(opts) {
11952
12205
  await dispatchTurn(turn);
11953
12206
  }
11954
12207
  }
11955
- const send = React58.useCallback((text, attachments) => {
12208
+ const send = React59.useCallback((text, attachments) => {
11956
12209
  const body = (text || "").trim();
11957
12210
  if (!body && !(attachments && attachments.length)) return;
11958
12211
  if (status === "disconnected") return;
@@ -11962,7 +12215,7 @@ function useChatEngine(opts) {
11962
12215
  stoppedRef.current = false;
11963
12216
  drain();
11964
12217
  }, [status]);
11965
- const stop = React58.useCallback(() => {
12218
+ const stop = React59.useCallback(() => {
11966
12219
  stoppedRef.current = true;
11967
12220
  const ac = abortRef.current;
11968
12221
  if (ac) {
@@ -11981,11 +12234,11 @@ function useChatEngine(opts) {
11981
12234
  store.del(STORAGE_PREFIX + threadRef.current);
11982
12235
  }
11983
12236
  }, [apiAdapter]);
11984
- const removeQueued = React58.useCallback((id) => {
12237
+ const removeQueued = React59.useCallback((id) => {
11985
12238
  queueRef.current = queueRef.current.filter((t) => t.id !== id);
11986
12239
  setQueue(queueRef.current.slice());
11987
12240
  }, []);
11988
- const retry = React58.useCallback(() => {
12241
+ const retry = React59.useCallback(() => {
11989
12242
  const list = listRef.current;
11990
12243
  let at = -1;
11991
12244
  for (let i = list.length - 1; i >= 0; i--) if (list[i].role === "user") {
@@ -12001,19 +12254,19 @@ function useChatEngine(opts) {
12001
12254
  setQueue(queueRef.current.slice());
12002
12255
  drain();
12003
12256
  }, []);
12004
- const clear = React58.useCallback(() => {
12257
+ const clear = React59.useCallback(() => {
12005
12258
  commit([]);
12006
12259
  serverCount.current = 0;
12007
12260
  queueRef.current = [];
12008
12261
  setQueue([]);
12009
12262
  onClear && onClear();
12010
12263
  }, [onClear]);
12011
- const setFeedback = React58.useCallback((id, value) => {
12264
+ const setFeedback = React59.useCallback((id, value) => {
12012
12265
  patch(id, (m) => ({ feedback: m.feedback === value ? null : value }));
12013
12266
  const msg = listRef.current.find((m) => m.id === id);
12014
12267
  onFeedback && onFeedback({ message: msg, feedback: msg ? msg.feedback : value });
12015
12268
  }, [onFeedback]);
12016
- const reload = React58.useCallback(async () => {
12269
+ const reload = React59.useCallback(async () => {
12017
12270
  if (!threadRef.current) return;
12018
12271
  setStatus("loading");
12019
12272
  try {
@@ -12051,11 +12304,11 @@ var ChatKit = {
12051
12304
  };
12052
12305
 
12053
12306
  // src/components/chat/ChatTranscript.tsx
12054
- var React60 = __toESM(require("react"), 1);
12307
+ var React61 = __toESM(require("react"), 1);
12055
12308
 
12056
12309
  // src/components/chat/ChatTurn.tsx
12057
- var React59 = __toESM(require("react"), 1);
12058
- var import_jsx_runtime91 = require("react/jsx-runtime");
12310
+ var React60 = __toESM(require("react"), 1);
12311
+ var import_jsx_runtime92 = require("react/jsx-runtime");
12059
12312
  function JsonView({ value }) {
12060
12313
  let text;
12061
12314
  try {
@@ -12063,67 +12316,67 @@ function JsonView({ value }) {
12063
12316
  } catch (e) {
12064
12317
  text = String(value);
12065
12318
  }
12066
- 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 });
12067
12320
  }
12068
12321
  function PacketCard({ packet, schema, render, onApply, applied }) {
12069
12322
  if (!packet) return null;
12070
12323
  const s = schema || {};
12071
12324
  const invalid = packet.valid === false;
12072
12325
  const title = s.heading || packet.type;
12073
- return /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)("section", { className: "fdc-packet" + (invalid ? " is-invalid" : ""), "aria-label": title, children: [
12074
- /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)("header", { className: "fdc-packet-head", children: [
12075
- /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("i", { className: "ph ph-" + (s.icon || "package"), "aria-hidden": "true" }),
12076
- /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("span", { className: "fdc-packet-title", title: truncationTitle(title), children: title }),
12077
- packet.repaired ? /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("span", { className: "fdc-packet-badge", children: "Repaired" }) : null,
12078
- 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
12079
12332
  ] }),
12080
- invalid ? /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)("div", { className: "fdc-packet-alert", role: "alert", children: [
12081
- /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
12082
- /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("span", { children: packet.error || "This result failed validation and can\u2019t be applied." })
12083
- ] }) : /* @__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 }) }),
12084
- !invalid && onApply ? /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)("footer", { className: "fdc-packet-foot", children: [
12085
- 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", {}),
12086
- /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)("button", { type: "button", className: "fd-btn fd-btn-primary fd-btn-sm", disabled: applied, onClick: () => onApply(packet), children: [
12087
- /* @__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" }),
12088
12341
  applied ? "Applied" : s.applyLabel || "Apply"
12089
12342
  ] })
12090
12343
  ] }) : null
12091
12344
  ] });
12092
12345
  }
12093
12346
  function ThinkingBlock({ text, durationMs, streaming, defaultOpen = false }) {
12094
- const [open2, setOpen] = React59.useState(defaultOpen);
12347
+ const [open2, setOpen] = React60.useState(defaultOpen);
12095
12348
  if (!text) return null;
12096
- return /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)("div", { className: "fdc-think" + (open2 ? " is-open" : ""), children: [
12097
- /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)("button", { type: "button", className: "fdc-think-head", onClick: () => setOpen((v) => !v), "aria-expanded": open2, children: [
12098
- /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("i", { className: "ph ph-brain", "aria-hidden": "true" }),
12099
- /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("span", { children: streaming ? "Thinking" : durationMs ? "Thought for " + formatDuration(durationMs) : "Thought process" }),
12100
- streaming ? /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)("span", { className: "fdc-dots", "aria-hidden": "true", children: [
12101
- /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("span", {}),
12102
- /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("span", {}),
12103
- /* @__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", {})
12104
12357
  ] }) : null,
12105
- /* @__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" })
12106
12359
  ] }),
12107
- 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
12108
12361
  ] });
12109
12362
  }
12110
12363
  function Citations({ items = [], onOpen }) {
12111
- const [open2, setOpen] = React59.useState(false);
12364
+ const [open2, setOpen] = React60.useState(false);
12112
12365
  if (!items.length) return null;
12113
- return /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)("div", { className: "fdc-cites", children: [
12114
- /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)("button", { type: "button", className: "fdc-cites-head", onClick: () => setOpen((v) => !v), "aria-expanded": open2, children: [
12115
- /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("i", { className: "ph ph-quotes", "aria-hidden": "true" }),
12116
- /* @__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: [
12117
12370
  items.length,
12118
12371
  " source",
12119
12372
  items.length === 1 ? "" : "s"
12120
12373
  ] }),
12121
- /* @__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" })
12122
12375
  ] }),
12123
- 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: [
12124
- /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("span", { className: "fdc-cite-n fd-tabular", children: c.marker || i + 1 }),
12125
- 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" }),
12126
- 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
12127
12380
  ] }, c.id || i)) }) : null
12128
12381
  ] });
12129
12382
  }
@@ -12134,29 +12387,29 @@ function clampText(text, max) {
12134
12387
  return (at > max * 0.6 ? cut.slice(0, at) : cut).trimEnd() + "\u2026";
12135
12388
  }
12136
12389
  function MessageBody({ message: m, ctx }) {
12137
- const [expanded, setExpanded] = React59.useState(false);
12390
+ const [expanded, setExpanded] = React60.useState(false);
12138
12391
  const isUser = m.role === "user";
12139
12392
  const raw = m.text || "";
12140
12393
  const clamped = !expanded && !m.streaming ? clampText(raw, ctx.maxVisibleChars) : null;
12141
12394
  const body = clamped != null ? clamped : raw;
12142
12395
  const showMd = ctx.markdown && !isUser;
12143
- return /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)("div", { className: "fdc-body", children: [
12144
- m.thinking && ctx.showThinking ? /* @__PURE__ */ (0, import_jsx_runtime91.jsx)(ThinkingBlock, { text: m.thinking, durationMs: m.thinkingMs, streaming: m.streaming && !m.text }) : null,
12145
- 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,
12146
- body ? /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)("div", { className: "fdc-text" + (isUser ? " is-user" : ""), children: [
12147
- 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 }),
12148
- 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
12149
12402
  ] }) : null,
12150
- clamped != null ? /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)("button", { type: "button", className: "fdc-more", onClick: () => setExpanded(true), children: [
12151
- /* @__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" }),
12152
12405
  "Show more",
12153
- /* @__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" })
12154
- ] }) : expanded && ctx.maxVisibleChars && raw.length > ctx.maxVisibleChars ? /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)("button", { type: "button", className: "fdc-more", onClick: () => setExpanded(false), children: [
12155
- /* @__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" }),
12156
12409
  "Show less"
12157
12410
  ] }) : null,
12158
- 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,
12159
- 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)(
12160
12413
  PacketCard,
12161
12414
  {
12162
12415
  packet: m.packet,
@@ -12166,44 +12419,44 @@ function MessageBody({ message: m, ctx }) {
12166
12419
  applied: ctx.appliedPackets && ctx.appliedPackets[m.id]
12167
12420
  }
12168
12421
  ) : null,
12169
- m.citations && m.citations.length ? /* @__PURE__ */ (0, import_jsx_runtime91.jsx)(Citations, { items: m.citations, onOpen: ctx.onOpenCitation }) : null,
12170
- m.working ? /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)("div", { className: "fdc-working", role: "status", children: [
12171
- /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)("span", { className: "fdc-dots", "aria-hidden": "true", children: [
12172
- /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("span", {}),
12173
- /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("span", {}),
12174
- /* @__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", {})
12175
12428
  ] }),
12176
- /* @__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: [
12177
12430
  m.resumed ? "Resuming" : "Working",
12178
- 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: [
12179
12432
  " \xB7 ",
12180
12433
  m.job.status
12181
12434
  ] }) : null,
12182
- 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: [
12183
12436
  " \xB7 ",
12184
12437
  m.job.detail
12185
12438
  ] }) : null
12186
12439
  ] }),
12187
- 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
12188
12441
  ] }) : null,
12189
- m.stopped ? /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)("div", { className: "fdc-stopped", children: [
12190
- /* @__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" }),
12191
12444
  "Stopped"
12192
12445
  ] }) : null,
12193
- m.error ? /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)("div", { className: "fdc-error", role: "alert", children: [
12194
- /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
12195
- /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("span", { className: "fdc-error-text", children: ctx.errorCopy ? ctx.errorCopy(m.error) : m.error }),
12196
- m.retryable && ctx.onRetry ? /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)("button", { type: "button", className: "fdc-error-retry", onClick: ctx.onRetry, children: [
12197
- /* @__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" }),
12198
12451
  "Retry"
12199
12452
  ] }) : null
12200
12453
  ] }) : null
12201
12454
  ] });
12202
12455
  }
12203
12456
  function useCopyRun() {
12204
- const [done, setDone] = React59.useState(false);
12205
- const t = React59.useRef(null);
12206
- React59.useEffect(() => () => {
12457
+ const [done, setDone] = React60.useState(false);
12458
+ const t = React60.useRef(null);
12459
+ React60.useEffect(() => () => {
12207
12460
  if (t.current) clearTimeout(t.current);
12208
12461
  }, []);
12209
12462
  return [done, (text) => {
@@ -12223,16 +12476,16 @@ function RunActions({ group, ctx }) {
12223
12476
  const isAssistant = group.role === "assistant";
12224
12477
  const fb = last.feedback;
12225
12478
  if (!ctx.messageActions) return null;
12226
- return /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)("div", { className: "fdc-actions", role: "group", "aria-label": "Message actions", children: [
12227
- /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)("button", { type: "button", className: "fdc-act" + (copied ? " is-done" : ""), onClick: () => copy(markdownToText(text)), "aria-label": "Copy message", children: [
12228
- /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("i", { className: "ph ph-" + (copied ? "check" : "copy"), "aria-hidden": "true" }),
12229
- /* @__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" })
12230
12483
  ] }),
12231
- 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,
12232
- 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,
12233
- isAssistant && ctx.onFeedback ? /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)(React59.Fragment, { children: [
12234
- /* @__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" }) }),
12235
- /* @__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" }) })
12236
12489
  ] }) : null,
12237
12490
  ctx.extraActions ? ctx.extraActions(group) : null
12238
12491
  ] });
@@ -12242,22 +12495,22 @@ function ChatTurn({ group, ctx }) {
12242
12495
  const name = isUser ? ctx.userName : group.author || ctx.assistantName;
12243
12496
  const avatar = isUser ? ctx.userAvatar : ctx.assistantAvatar;
12244
12497
  const stamp = group.messages[0].timestamp;
12245
- return /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)("article", { className: "fdc-turn is-" + group.role, "aria-label": String(name) + (stamp ? " at " + formatClock(stamp) : ""), children: [
12246
- /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)("div", { className: "fdc-turn-head", children: [
12247
- 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,
12248
- /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("span", { className: "fdc-who", children: name }),
12249
- stamp ? /* @__PURE__ */ (0, import_jsx_runtime91.jsx)(RelativeTime, { className: "fdc-when", value: stamp }) : null,
12250
- 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
12251
12504
  ] }),
12252
- /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)("div", { className: "fdc-turn-body", children: [
12253
- 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)),
12254
- /* @__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 })
12255
12508
  ] })
12256
12509
  ] });
12257
12510
  }
12258
12511
 
12259
12512
  // src/components/chat/ChatTranscript.tsx
12260
- var import_jsx_runtime92 = require("react/jsx-runtime");
12513
+ var import_jsx_runtime93 = require("react/jsx-runtime");
12261
12514
  var GROUP_WINDOW = 6e4;
12262
12515
  var STICK_PX = 100;
12263
12516
  function groupMessages(list) {
@@ -12290,25 +12543,25 @@ function dayLabel(key) {
12290
12543
  }
12291
12544
  function Suggestions({ items = [], onPick }) {
12292
12545
  if (!items.length) return null;
12293
- 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) => {
12294
12547
  const it = typeof s === "string" ? { label: s, text: s } : s;
12295
- return /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("button", { type: "button", className: "fdc-suggest-item", onClick: () => onPick && onPick(it.text || it.label), children: [
12296
- it.icon ? /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("i", { className: "ph ph-" + it.icon, "aria-hidden": "true" }) : null,
12297
- /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("span", { className: "fdc-suggest-text", children: [
12298
- /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("span", { className: "fdc-suggest-label", children: it.label }),
12299
- 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
12300
12553
  ] }),
12301
- /* @__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" })
12302
12555
  ] }, it.id || i);
12303
12556
  }) });
12304
12557
  }
12305
12558
  function LoadingTurns() {
12306
- 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: [
12307
- /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("div", { className: "fd-skel fd-skel-circle", style: { width: 22, height: 22 } }),
12308
- /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("div", { className: "fdc-skel-lines", children: [
12309
- /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("div", { className: "fd-skel", style: { width: i ? "62%" : "44%", height: 11 } }),
12310
- /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("div", { className: "fd-skel", style: { width: i ? "94%" : "78%", height: 11 } }),
12311
- /* @__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 } })
12312
12565
  ] })
12313
12566
  ] }, i)) });
12314
12567
  }
@@ -12325,10 +12578,10 @@ function ChatTranscript({
12325
12578
  renderEmpty,
12326
12579
  className = ""
12327
12580
  }) {
12328
- const scroller = React60.useRef(null);
12329
- const stick = React60.useRef(true);
12330
- const [pill, setPill] = React60.useState(0);
12331
- 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);
12332
12585
  const toBottom = (smooth) => {
12333
12586
  const el = scroller.current;
12334
12587
  if (!el) return;
@@ -12347,7 +12600,7 @@ function ChatTranscript({
12347
12600
  seen.current = messages.length;
12348
12601
  }
12349
12602
  };
12350
- React60.useLayoutEffect(() => {
12603
+ React61.useLayoutEffect(() => {
12351
12604
  const el = scroller.current;
12352
12605
  if (!el) return;
12353
12606
  if (stick.current) {
@@ -12355,7 +12608,7 @@ function ChatTranscript({
12355
12608
  seen.current = messages.length;
12356
12609
  } else setPill(Math.max(0, messages.length - seen.current));
12357
12610
  }, [messages]);
12358
- React60.useEffect(() => {
12611
+ React61.useEffect(() => {
12359
12612
  const el = scroller.current;
12360
12613
  const inner = el && el.firstChild;
12361
12614
  if (!el || !inner || typeof ResizeObserver === "undefined") return;
@@ -12365,38 +12618,38 @@ function ChatTranscript({
12365
12618
  ro.observe(inner);
12366
12619
  return () => ro.disconnect();
12367
12620
  }, []);
12368
- const groups = React60.useMemo(() => groupMessages(messages), [messages]);
12621
+ const groups = React61.useMemo(() => groupMessages(messages), [messages]);
12369
12622
  const empty = !messages.length && status === "ready";
12370
- return /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("div", { className: ["fdc-scroll", className].filter(Boolean).join(" "), ref: scroller, onScroll, children: [
12371
- /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("div", { className: "fdc-log", role: "log", "aria-label": "Conversation", children: [
12372
- status === "loading" || status === "resolving" ? /* @__PURE__ */ (0, import_jsx_runtime92.jsx)(LoadingTurns, {}) : null,
12373
- status === "disconnected" ? /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("div", { className: "fdc-dead", children: [
12374
- /* @__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" }) }),
12375
- /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("h3", { className: "fdc-dead-title", children: ctx.deadTitle || "The assistant isn\u2019t reachable" }),
12376
- /* @__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." }),
12377
- ctx.onReconnect ? /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("button", { type: "button", className: "fd-btn fd-btn-secondary fd-btn-sm", onClick: ctx.onReconnect, children: [
12378
- /* @__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" }),
12379
12632
  "Try again"
12380
12633
  ] }) : null
12381
12634
  ] }) : null,
12382
- empty ? renderEmpty ? renderEmpty() : /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("div", { className: "fdc-empty", children: [
12383
- /* @__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" }) }),
12384
- /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("h3", { className: "fdc-empty-title", children: emptyTitle }),
12385
- emptyDescription ? /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("p", { className: "fdc-empty-body", children: emptyDescription }) : null,
12386
- /* @__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 })
12387
12640
  ] }) : null,
12388
12641
  groups.map((g, i) => {
12389
12642
  const prev = groups[i - 1];
12390
12643
  const k = dayKey(g.messages[0].timestamp);
12391
12644
  const showDay = !!k && (!prev || dayKey(prev.messages[0].timestamp) !== k);
12392
- return /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)(React60.Fragment, { children: [
12393
- showDay ? /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("div", { className: "fdc-day", children: /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("span", { children: dayLabel(k) }) }) : null,
12394
- /* @__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 })
12395
12648
  ] }, g.key || i);
12396
12649
  })
12397
12650
  ] }),
12398
- pill ? /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("button", { type: "button", className: "fdc-pill", onClick: () => toBottom(true), children: [
12399
- /* @__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" }),
12400
12653
  pill,
12401
12654
  " new message",
12402
12655
  pill === 1 ? "" : "s"
@@ -12406,8 +12659,8 @@ function ChatTranscript({
12406
12659
  var TranscriptKit = { groupMessages };
12407
12660
 
12408
12661
  // src/components/chat/ChatComposer.tsx
12409
- var React61 = __toESM(require("react"), 1);
12410
- var import_jsx_runtime93 = require("react/jsx-runtime");
12662
+ var React62 = __toESM(require("react"), 1);
12663
+ var import_jsx_runtime94 = require("react/jsx-runtime");
12411
12664
  function ChatComposer({
12412
12665
  onSubmit,
12413
12666
  onStop,
@@ -12434,17 +12687,17 @@ function ChatComposer({
12434
12687
  onReject,
12435
12688
  onOpenAttachment
12436
12689
  }) {
12437
- const [text, setText] = React61.useState(draft || "");
12438
- const [trigger, setTrigger] = React61.useState(null);
12439
- const [mentionItems, setMentionItems] = React61.useState([]);
12440
- const [listening, setListening] = React61.useState(false);
12441
- const [notice, setNotice] = React61.useState(null);
12442
- const editor = React61.useRef(null);
12443
- const wrap = React61.useRef(null);
12444
- 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);
12445
12698
  const staged = useStagedFiles(fileUploadHandler, { onError: () => {
12446
12699
  } });
12447
- React61.useEffect(() => {
12700
+ React62.useEffect(() => {
12448
12701
  if (draft != null && draft !== text) setText(draft);
12449
12702
  }, [draft]);
12450
12703
  const change = (v) => {
@@ -12480,7 +12733,7 @@ function ChatComposer({
12480
12733
  e.preventDefault();
12481
12734
  staged.add(found.files);
12482
12735
  };
12483
- React61.useEffect(() => {
12736
+ React62.useEffect(() => {
12484
12737
  if (!trigger || trigger.type !== "mention" || !mentionSources) {
12485
12738
  setMentionItems([]);
12486
12739
  return;
@@ -12498,7 +12751,7 @@ function ChatComposer({
12498
12751
  const q = (trigger.query || "").toLowerCase();
12499
12752
  setMentionItems(mentionSources.filter((m) => !q || (m.label + " " + (m.description || "")).toLowerCase().includes(q)));
12500
12753
  }, [trigger, mentionSources]);
12501
- const slashItems = React61.useMemo(() => {
12754
+ const slashItems = React62.useMemo(() => {
12502
12755
  if (!trigger || trigger.type !== "slash" || !slashCommands) return [];
12503
12756
  const q = (trigger.query || "").toLowerCase();
12504
12757
  return slashCommands.filter((c) => !q || (c.id + " " + c.label + " " + (c.description || "")).toLowerCase().includes(q));
@@ -12512,7 +12765,7 @@ function ChatComposer({
12512
12765
  description: it.description,
12513
12766
  icon: it.icon,
12514
12767
  meta: mention.meta,
12515
- 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,
12516
12769
  onSelect: () => {
12517
12770
  const insert = trigger.type === "slash" ? slash.immediate ? "/" + slash.id : "/" + slash.id + " " : "@" + (mention.value || mention.label) + " ";
12518
12771
  editor.current && editor.current.replaceRange(trigger.from, trigger.to, insert);
@@ -12571,14 +12824,14 @@ function ChatComposer({
12571
12824
  stopVoice.current = typeof res === "function" ? res : () => {
12572
12825
  };
12573
12826
  };
12574
- return /* @__PURE__ */ (0, import_jsx_runtime93.jsxs)("div", { className: "fdc-composer" + (disabled ? " is-disabled" : "") + (narrow ? " is-narrow" : ""), children: [
12575
- 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: [
12576
- /* @__PURE__ */ (0, import_jsx_runtime93.jsx)("i", { className: "ph ph-clock-countdown", "aria-hidden": "true" }),
12577
- /* @__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)" : "") }),
12578
- 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
12579
12832
  ] }, q.id)) }) : null,
12580
12833
  sessionBar,
12581
- /* @__PURE__ */ (0, import_jsx_runtime93.jsx)(
12834
+ /* @__PURE__ */ (0, import_jsx_runtime94.jsx)(
12582
12835
  Dropzone,
12583
12836
  {
12584
12837
  className: "fdc-field",
@@ -12592,9 +12845,9 @@ function ChatComposer({
12592
12845
  disabled: !fileUploadHandler || disabled,
12593
12846
  label: "Drop to attach",
12594
12847
  hint: acceptFiles ? acceptFiles.replace(/,/g, " \xB7 ") : void 0,
12595
- children: /* @__PURE__ */ (0, import_jsx_runtime93.jsxs)("div", { ref: wrap, className: "fdc-field-inner", children: [
12596
- 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,
12597
- /* @__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)(
12598
12851
  MarkdownEditor,
12599
12852
  {
12600
12853
  ref: editor,
@@ -12613,33 +12866,33 @@ function ChatComposer({
12613
12866
  ariaLabel: "Message"
12614
12867
  }
12615
12868
  ),
12616
- /* @__PURE__ */ (0, import_jsx_runtime93.jsxs)("div", { className: "fdc-tools", children: [
12617
- 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,
12618
- 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,
12619
12872
  toolbarExtras,
12620
- /* @__PURE__ */ (0, import_jsx_runtime93.jsx)("span", { className: "fdc-tools-gap" }),
12621
- 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: [
12622
12875
  text.length,
12623
12876
  "/",
12624
12877
  maxLength
12625
12878
  ] }) : null,
12626
- busy ? /* @__PURE__ */ (0, import_jsx_runtime93.jsxs)("button", { type: "button", className: "fdc-stop", onClick: onStop, "aria-label": "Stop generating", children: [
12627
- /* @__PURE__ */ (0, import_jsx_runtime93.jsx)("i", { className: "ph ph-stop-circle", "aria-hidden": "true" }),
12628
- /* @__PURE__ */ (0, import_jsx_runtime93.jsx)("span", { children: "Stop" })
12629
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime93.jsxs)("button", { type: "button", className: "fdc-send", onClick: submit, disabled: !canSend, "aria-label": "Send message", children: [
12630
- /* @__PURE__ */ (0, import_jsx_runtime93.jsx)("i", { className: "ph ph-paper-plane-right", "aria-hidden": "true" }),
12631
- /* @__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" })
12632
12885
  ] })
12633
12886
  ] })
12634
12887
  ] })
12635
12888
  }
12636
12889
  ),
12637
- notice ? /* @__PURE__ */ (0, import_jsx_runtime93.jsxs)("div", { className: "fdc-notice", role: "status", children: [
12638
- /* @__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" }),
12639
12892
  notice
12640
12893
  ] }) : null,
12641
- hint && !notice ? /* @__PURE__ */ (0, import_jsx_runtime93.jsx)("div", { className: "fdc-hint", children: hint }) : null,
12642
- /* @__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)(
12643
12896
  Popover,
12644
12897
  {
12645
12898
  open: menuOpen,
@@ -12653,12 +12906,12 @@ function ChatComposer({
12653
12906
  returnFocus: false,
12654
12907
  closeOnOutside: true,
12655
12908
  label: trigger && trigger.type === "slash" ? "Commands" : "Mentions",
12656
- children: /* @__PURE__ */ (0, import_jsx_runtime93.jsx)(
12909
+ children: /* @__PURE__ */ (0, import_jsx_runtime94.jsx)(
12657
12910
  Menu,
12658
12911
  {
12659
12912
  items: menuItems,
12660
12913
  autoFocus: false,
12661
- 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" }),
12662
12915
  onClose: () => setTrigger(null)
12663
12916
  }
12664
12917
  )
@@ -12668,12 +12921,12 @@ function ChatComposer({
12668
12921
  }
12669
12922
 
12670
12923
  // src/components/chat/ChatSessionBar.tsx
12671
- var React62 = __toESM(require("react"), 1);
12672
- var import_jsx_runtime94 = require("react/jsx-runtime");
12924
+ var React63 = __toESM(require("react"), 1);
12925
+ var import_jsx_runtime95 = require("react/jsx-runtime");
12673
12926
  var compact2 = meterFormats.compact;
12674
12927
  function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extras }) {
12675
- const [open2, setOpen] = React62.useState(false);
12676
- const anchor = React62.useRef(null);
12928
+ const [open2, setOpen] = React63.useState(false);
12929
+ const anchor = React63.useRef(null);
12677
12930
  const stats = sessionStats || null;
12678
12931
  const cu = contextUsage || null;
12679
12932
  const limits = usageLimits || null;
@@ -12688,9 +12941,9 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
12688
12941
  if (stats && stats.runningTasks) bits.push(stats.runningTasks + " running task" + (stats.runningTasks === 1 ? "" : "s"));
12689
12942
  if (cu) bits.push(pct + "% context");
12690
12943
  const expandable = !!(cu || limits);
12691
- return /* @__PURE__ */ (0, import_jsx_runtime94.jsxs)(React62.Fragment, { children: [
12692
- /* @__PURE__ */ (0, import_jsx_runtime94.jsxs)("div", { className: "fdc-bar", children: [
12693
- /* @__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)(
12694
12947
  "button",
12695
12948
  {
12696
12949
  type: "button",
@@ -12701,15 +12954,15 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
12701
12954
  "aria-expanded": expandable ? open2 : void 0,
12702
12955
  "aria-label": expandable ? "Usage details" : void 0,
12703
12956
  children: [
12704
- 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,
12705
- /* @__PURE__ */ (0, import_jsx_runtime94.jsx)("span", { className: "fdc-bar-text", title: truncationTitle(bits.join(" \xB7 ")), children: bits.join(" \xB7 ") }),
12706
- 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
12707
12960
  ]
12708
12961
  }
12709
12962
  ),
12710
12963
  extras
12711
12964
  ] }),
12712
- /* @__PURE__ */ (0, import_jsx_runtime94.jsx)(
12965
+ /* @__PURE__ */ (0, import_jsx_runtime95.jsx)(
12713
12966
  Popover,
12714
12967
  {
12715
12968
  open: open2,
@@ -12720,15 +12973,15 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
12720
12973
  maxHeight: 460,
12721
12974
  padded: true,
12722
12975
  label: "Usage",
12723
- 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: () => {
12724
12977
  setOpen(false);
12725
12978
  onClear();
12726
12979
  }, children: [
12727
- /* @__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" }),
12728
12981
  "Clear conversation"
12729
12982
  ] }) : void 0,
12730
- children: /* @__PURE__ */ (0, import_jsx_runtime94.jsxs)("div", { className: "fdc-usage", children: [
12731
- 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)(
12732
12985
  SegmentedMeter,
12733
12986
  {
12734
12987
  total,
@@ -12740,9 +12993,9 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
12740
12993
  remainderLabel: "Free"
12741
12994
  }
12742
12995
  ) }) : null,
12743
- limits && limits.length ? /* @__PURE__ */ (0, import_jsx_runtime94.jsxs)("section", { className: "fdc-usage-sec", children: [
12744
- /* @__PURE__ */ (0, import_jsx_runtime94.jsx)("h4", { className: "fdc-usage-h", children: "Usage limits" }),
12745
- /* @__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)(
12746
12999
  QuotaRow,
12747
13000
  {
12748
13001
  label: l.label,
@@ -12752,25 +13005,25 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
12752
13005
  l.id
12753
13006
  )) })
12754
13007
  ] }) : null,
12755
- stats ? /* @__PURE__ */ (0, import_jsx_runtime94.jsxs)("section", { className: "fdc-usage-sec fdc-usage-stats", children: [
12756
- stats.elapsedMs ? /* @__PURE__ */ (0, import_jsx_runtime94.jsxs)("div", { children: [
12757
- /* @__PURE__ */ (0, import_jsx_runtime94.jsx)("span", { children: "Session" }),
12758
- /* @__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) })
12759
13012
  ] }) : null,
12760
- stats.tokens ? /* @__PURE__ */ (0, import_jsx_runtime94.jsxs)("div", { children: [
12761
- /* @__PURE__ */ (0, import_jsx_runtime94.jsx)("span", { children: "Tokens" }),
12762
- /* @__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() })
12763
13016
  ] }) : null,
12764
- stats.costUsd != null ? /* @__PURE__ */ (0, import_jsx_runtime94.jsxs)("div", { children: [
12765
- /* @__PURE__ */ (0, import_jsx_runtime94.jsx)("span", { children: "Cost" }),
12766
- /* @__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: [
12767
13020
  "$",
12768
13021
  Number(stats.costUsd).toFixed(3)
12769
13022
  ] })
12770
13023
  ] }) : null,
12771
- stats.turns ? /* @__PURE__ */ (0, import_jsx_runtime94.jsxs)("div", { children: [
12772
- /* @__PURE__ */ (0, import_jsx_runtime94.jsx)("span", { children: "Turns" }),
12773
- /* @__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 })
12774
13027
  ] }) : null
12775
13028
  ] }) : null
12776
13029
  ] })
@@ -12809,7 +13062,7 @@ function ModelControls({
12809
13062
  disabled: m.disabled,
12810
13063
  checked: m.id === (current2 && current2.id),
12811
13064
  meta: m.meta,
12812
- 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,
12813
13066
  onSelect: () => onModelChange && onModelChange(m.id)
12814
13067
  });
12815
13068
  const items = [{ kind: "section", label: "Models" }].concat(flat.map(item));
@@ -12822,15 +13075,15 @@ function ModelControls({
12822
13075
  items.push({ kind: "section", label: "Fast mode" });
12823
13076
  items.push({
12824
13077
  kind: "custom",
12825
- render: () => /* @__PURE__ */ (0, import_jsx_runtime94.jsxs)("label", { className: "fdc-switchrow", children: [
12826
- /* @__PURE__ */ (0, import_jsx_runtime94.jsx)("span", { children: fastModeLabel }),
12827
- /* @__PURE__ */ (0, import_jsx_runtime94.jsx)("input", { type: "checkbox", className: "fd-sr", checked: !!fastMode, onChange: (e) => onFastModeChange(e.target.checked) }),
12828
- /* @__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" }) })
12829
13082
  ] })
12830
13083
  });
12831
13084
  }
12832
- return /* @__PURE__ */ (0, import_jsx_runtime94.jsxs)(React62.Fragment, { children: [
12833
- /* @__PURE__ */ (0, import_jsx_runtime94.jsx)(
13085
+ return /* @__PURE__ */ (0, import_jsx_runtime95.jsxs)(React63.Fragment, { children: [
13086
+ /* @__PURE__ */ (0, import_jsx_runtime95.jsx)(
12834
13087
  MenuButton,
12835
13088
  {
12836
13089
  items,
@@ -12841,7 +13094,7 @@ function ModelControls({
12841
13094
  title: "Choose a model"
12842
13095
  }
12843
13096
  ),
12844
- effortLevels && effortLevels.length ? /* @__PURE__ */ (0, import_jsx_runtime94.jsx)(
13097
+ effortLevels && effortLevels.length ? /* @__PURE__ */ (0, import_jsx_runtime95.jsx)(
12845
13098
  MenuButton,
12846
13099
  {
12847
13100
  placement: "top-end",
@@ -12862,7 +13115,7 @@ function ModelControls({
12862
13115
  }
12863
13116
 
12864
13117
  // src/components/chat/AgentChatPanel.tsx
12865
- var import_jsx_runtime95 = require("react/jsx-runtime");
13118
+ var import_jsx_runtime96 = require("react/jsx-runtime");
12866
13119
  var SURFACES = { sidebar: "is-sidebar", inline: "is-inline", page: "is-page", modal: "is-modal", sheet: "is-sheet" };
12867
13120
  function AgentChatPanel({
12868
13121
  /* required */
@@ -12946,11 +13199,11 @@ function AgentChatPanel({
12946
13199
  onFeedback,
12947
13200
  onEditMessage
12948
13201
  }) {
12949
- const [panelWidth, setPanelWidth] = React63.useState(width);
12950
- const [applied, setApplied] = React63.useState({});
12951
- const [draft, setDraft] = React63.useState("");
12952
- const dragging = React63.useRef(null);
12953
- 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]);
12954
13207
  const engine = useChatEngine({
12955
13208
  contextType,
12956
13209
  contextId,
@@ -13016,7 +13269,7 @@ function AgentChatPanel({
13016
13269
  onReconnect: engine.reload,
13017
13270
  deadTitle: "The assistant isn\u2019t reachable"
13018
13271
  };
13019
- const sessionBar = /* @__PURE__ */ (0, import_jsx_runtime95.jsx)(
13272
+ const sessionBar = /* @__PURE__ */ (0, import_jsx_runtime96.jsx)(
13020
13273
  ChatSessionBar,
13021
13274
  {
13022
13275
  sessionStats,
@@ -13025,7 +13278,7 @@ function AgentChatPanel({
13025
13278
  onClear: engine.visible.length ? engine.clear : void 0
13026
13279
  }
13027
13280
  );
13028
- const modelControls = /* @__PURE__ */ (0, import_jsx_runtime95.jsx)(
13281
+ const modelControls = /* @__PURE__ */ (0, import_jsx_runtime96.jsx)(
13029
13282
  ModelControls,
13030
13283
  {
13031
13284
  models,
@@ -13040,7 +13293,7 @@ function AgentChatPanel({
13040
13293
  narrow
13041
13294
  }
13042
13295
  );
13043
- const threadMenu = threads && threads.length ? /* @__PURE__ */ (0, import_jsx_runtime95.jsx)(
13296
+ const threadMenu = threads && threads.length ? /* @__PURE__ */ (0, import_jsx_runtime96.jsx)(
13044
13297
  MenuButton,
13045
13298
  {
13046
13299
  variant: "ghost",
@@ -13067,7 +13320,7 @@ function AgentChatPanel({
13067
13320
  })))
13068
13321
  }
13069
13322
  ) : null;
13070
- return /* @__PURE__ */ (0, import_jsx_runtime95.jsxs)(
13323
+ return /* @__PURE__ */ (0, import_jsx_runtime96.jsxs)(
13071
13324
  "aside",
13072
13325
  {
13073
13326
  className: ["fdc-panel", SURFACES[surface] || SURFACES.sidebar, narrow ? "is-narrow" : "", className].filter(Boolean).join(" "),
@@ -13078,7 +13331,7 @@ function AgentChatPanel({
13078
13331
  },
13079
13332
  "aria-label": title,
13080
13333
  children: [
13081
- surface === "sidebar" && resizable ? /* @__PURE__ */ (0, import_jsx_runtime95.jsx)(
13334
+ surface === "sidebar" && resizable ? /* @__PURE__ */ (0, import_jsx_runtime96.jsx)(
13082
13335
  "div",
13083
13336
  {
13084
13337
  className: "fdc-grip",
@@ -13093,20 +13346,20 @@ function AgentChatPanel({
13093
13346
  }
13094
13347
  }
13095
13348
  ) : null,
13096
- showHeader ? /* @__PURE__ */ (0, import_jsx_runtime95.jsxs)("header", { className: "fdc-head", children: [
13097
- /* @__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 }) }),
13098
- /* @__PURE__ */ (0, import_jsx_runtime95.jsxs)("span", { className: "fdc-head-titles", children: [
13099
- /* @__PURE__ */ (0, import_jsx_runtime95.jsx)("span", { className: "fdc-head-title", title: truncationTitle(title), children: title }),
13100
- 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
13101
13354
  ] }),
13102
- /* @__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: [
13103
13356
  headerActions,
13104
13357
  threadMenu,
13105
- 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,
13106
- 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
13107
13360
  ] })
13108
13361
  ] }) : null,
13109
- /* @__PURE__ */ (0, import_jsx_runtime95.jsx)(
13362
+ /* @__PURE__ */ (0, import_jsx_runtime96.jsx)(
13110
13363
  ChatTranscript,
13111
13364
  {
13112
13365
  messages: engine.visible,
@@ -13121,7 +13374,7 @@ function AgentChatPanel({
13121
13374
  renderEmpty
13122
13375
  }
13123
13376
  ),
13124
- /* @__PURE__ */ (0, import_jsx_runtime95.jsx)(
13377
+ /* @__PURE__ */ (0, import_jsx_runtime96.jsx)(
13125
13378
  ChatComposer,
13126
13379
  {
13127
13380
  onSubmit: (text, atts) => engine.send(text, atts),
@@ -13154,8 +13407,8 @@ function AgentChatPanel({
13154
13407
  }
13155
13408
 
13156
13409
  // src/components/files/FileViewer.tsx
13157
- var React64 = __toESM(require("react"), 1);
13158
- var import_jsx_runtime96 = require("react/jsx-runtime");
13410
+ var React65 = __toESM(require("react"), 1);
13411
+ var import_jsx_runtime97 = require("react/jsx-runtime");
13159
13412
  function previewKindOf(file) {
13160
13413
  const mime = (file.mime || "").toLowerCase();
13161
13414
  const ext = extensionOf(file.name || "");
@@ -13211,13 +13464,13 @@ function parseDelimited(text, delimiter) {
13211
13464
  return rows;
13212
13465
  }
13213
13466
  function usePreview(file, kind, resolveUrl) {
13214
- const [state, setState] = React64.useState({ status: "loading" });
13215
- const [attempt, setAttempt] = React64.useState(0);
13216
- const resolveRef = React64.useRef(resolveUrl);
13217
- 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(() => {
13218
13471
  resolveRef.current = resolveUrl;
13219
13472
  }, [resolveUrl]);
13220
- React64.useEffect(() => {
13473
+ React65.useEffect(() => {
13221
13474
  if (kind === "none") {
13222
13475
  setState({ status: "ready" });
13223
13476
  return;
@@ -13247,19 +13500,19 @@ function usePreview(file, kind, resolveUrl) {
13247
13500
  if (ac) ac.abort();
13248
13501
  };
13249
13502
  }, [file.id, kind, attempt]);
13250
- return { ...state, retry: React64.useCallback(() => setAttempt((a) => a + 1), []) };
13503
+ return { ...state, retry: React65.useCallback(() => setAttempt((a) => a + 1), []) };
13251
13504
  }
13252
13505
  function PreviewBody({ file, kind, state }) {
13253
- if (kind === "image") return /* @__PURE__ */ (0, import_jsx_runtime96.jsx)("img", { className: "fd-fv-image", src: state.url, alt: file.name || "Preview" });
13254
- if (kind === "pdf") return /* @__PURE__ */ (0, import_jsx_runtime96.jsx)("iframe", { className: "fd-fv-pdf", src: state.url, title: file.name || "PDF preview" });
13255
- 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 || "" });
13256
13509
  if (kind === "json") {
13257
13510
  let pretty = state.text || "";
13258
13511
  try {
13259
13512
  pretty = JSON.stringify(JSON.parse(pretty), null, 2);
13260
13513
  } catch {
13261
13514
  }
13262
- 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" });
13263
13516
  }
13264
13517
  if (kind === "csv") {
13265
13518
  const tsv = extensionOf(file.name || "") === "tsv" || (file.mime || "").toLowerCase().includes("tab-separated");
@@ -13267,12 +13520,12 @@ function PreviewBody({ file, kind, state }) {
13267
13520
  const head = rows[0] || [];
13268
13521
  const dataRows = rows.slice(1);
13269
13522
  const shown = dataRows.slice(0, FILE_VIEWER_CSV_ROW_LIMIT);
13270
- return /* @__PURE__ */ (0, import_jsx_runtime96.jsxs)("div", { className: "fd-fv-csv", children: [
13271
- /* @__PURE__ */ (0, import_jsx_runtime96.jsxs)("table", { className: "fd-fv-csv-table", children: [
13272
- /* @__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)) }) }),
13273
- /* @__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)) })
13274
13527
  ] }),
13275
- 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: [
13276
13529
  "Showing the first ",
13277
13530
  FILE_VIEWER_CSV_ROW_LIMIT.toLocaleString(),
13278
13531
  " of ",
@@ -13281,24 +13534,24 @@ function PreviewBody({ file, kind, state }) {
13281
13534
  ] }) : null
13282
13535
  ] });
13283
13536
  }
13284
- if (kind === "text") return /* @__PURE__ */ (0, import_jsx_runtime96.jsx)(CodeBlock, { code: state.text || "", language: extensionOf(file.name || "") || void 0 });
13285
- return /* @__PURE__ */ (0, import_jsx_runtime96.jsxs)("div", { className: "fd-fv-fallback", children: [
13286
- /* @__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) }) }),
13287
- /* @__PURE__ */ (0, import_jsx_runtime96.jsx)("span", { className: "fd-fv-fallback-title", children: "No preview available" }),
13288
- /* @__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: [
13289
13542
  file.mime || "Unknown type",
13290
13543
  file.size ? " \xB7 " + formatBytes(file.size) : ""
13291
13544
  ] })
13292
13545
  ] });
13293
13546
  }
13294
13547
  function FileViewer({ file, resolveUrl, sidePanel, sidePanelLabel = "Details", onClose, actions, className = "" }) {
13295
- const kind = React64.useMemo(() => previewKindOf(file), [file]);
13548
+ const kind = React65.useMemo(() => previewKindOf(file), [file]);
13296
13549
  const preview = usePreview(file, kind, resolveUrl);
13297
- const [tab, setTab] = React64.useState("preview");
13298
- const [downloading, setDownloading] = React64.useState(false);
13299
- 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);
13300
13553
  const hasSide = sidePanel != null;
13301
- React64.useEffect(() => {
13554
+ React65.useEffect(() => {
13302
13555
  setTab("preview");
13303
13556
  }, [file.id]);
13304
13557
  const download = () => {
@@ -13314,29 +13567,29 @@ function FileViewer({ file, resolveUrl, sidePanel, sidePanelLabel = "Details", o
13314
13567
  a.remove();
13315
13568
  }).catch((err) => setDownloadError(err && err.message || "Download failed.")).finally(() => setDownloading(false));
13316
13569
  };
13317
- return /* @__PURE__ */ (0, import_jsx_runtime96.jsxs)(
13570
+ return /* @__PURE__ */ (0, import_jsx_runtime97.jsxs)(
13318
13571
  "section",
13319
13572
  {
13320
13573
  className: ["fd-fv", hasSide && tab === "side" ? "is-tab-side" : "is-tab-preview", className].filter(Boolean).join(" "),
13321
13574
  "aria-label": file.name || "File",
13322
13575
  children: [
13323
- /* @__PURE__ */ (0, import_jsx_runtime96.jsxs)("header", { className: "fd-fv-head", children: [
13324
- /* @__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) }) }),
13325
- /* @__PURE__ */ (0, import_jsx_runtime96.jsxs)("span", { className: "fd-fv-head-titles", children: [
13326
- /* @__PURE__ */ (0, import_jsx_runtime96.jsx)("span", { className: "fd-fv-head-title", title: file.name, children: file.name }),
13327
- /* @__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: [
13328
13581
  file.mime || "Unknown type",
13329
13582
  file.size ? " \xB7 " + formatBytes(file.size) : ""
13330
13583
  ] })
13331
13584
  ] }),
13332
- /* @__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: [
13333
13586
  actions,
13334
- /* @__PURE__ */ (0, import_jsx_runtime96.jsx)(Button, { variant: "secondary", size: "sm", icon: "download-simple", loading: downloading, onClick: download, children: "Download" }),
13335
- 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
13336
13589
  ] })
13337
13590
  ] }),
13338
- downloadError ? /* @__PURE__ */ (0, import_jsx_runtime96.jsx)("div", { className: "fd-fv-download-error", role: "alert", children: downloadError }) : null,
13339
- 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)(
13340
13593
  Tabs,
13341
13594
  {
13342
13595
  className: "fd-fv-tabs",
@@ -13345,19 +13598,19 @@ function FileViewer({ file, resolveUrl, sidePanel, sidePanelLabel = "Details", o
13345
13598
  onChange: (v) => setTab(v)
13346
13599
  }
13347
13600
  ) : null,
13348
- /* @__PURE__ */ (0, import_jsx_runtime96.jsxs)("div", { className: "fd-fv-body", children: [
13349
- /* @__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)(
13350
13603
  LoadingRegion,
13351
13604
  {
13352
13605
  state: preview.status === "loading" ? "loading" : preview.status === "error" ? "error" : "ready",
13353
13606
  error: preview.error,
13354
13607
  label: "Loading preview of " + (file.name || "file"),
13355
13608
  onRetry: preview.status === "error" ? preview.retry : void 0,
13356
- skeleton: /* @__PURE__ */ (0, import_jsx_runtime96.jsx)(Skeleton, { shape: "card", h: 220 }),
13357
- 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 })
13358
13611
  }
13359
13612
  ) }),
13360
- 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
13361
13614
  ] })
13362
13615
  ]
13363
13616
  }
@@ -13365,8 +13618,8 @@ function FileViewer({ file, resolveUrl, sidePanel, sidePanelLabel = "Details", o
13365
13618
  }
13366
13619
 
13367
13620
  // src/components/files/FileBrowser.tsx
13368
- var React65 = __toESM(require("react"), 1);
13369
- var import_jsx_runtime97 = require("react/jsx-runtime");
13621
+ var React66 = __toESM(require("react"), 1);
13622
+ var import_jsx_runtime98 = require("react/jsx-runtime");
13370
13623
  function childrenOf(folders, parentId) {
13371
13624
  return folders.filter((f) => f.parentId === parentId).sort((a, b) => a.name.localeCompare(b.name));
13372
13625
  }
@@ -13438,8 +13691,8 @@ function FolderPickerMenu({
13438
13691
  }) {
13439
13692
  const panel = useInlinePanel();
13440
13693
  const { open: open2, setOpen, ref, zIndex } = panel;
13441
- return /* @__PURE__ */ (0, import_jsx_runtime97.jsxs)("span", { className: "fd-fb-menu-anchor", ref, children: [
13442
- /* @__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)(
13443
13696
  IconButton,
13444
13697
  {
13445
13698
  icon: "arrows-out-cardinal",
@@ -13451,9 +13704,9 @@ function FolderPickerMenu({
13451
13704
  onClick: () => setOpen((v) => !v)
13452
13705
  }
13453
13706
  ),
13454
- 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: [
13455
- /* @__PURE__ */ (0, import_jsx_runtime97.jsx)("span", { className: "fd-overline fd-muted fd-fb-menu-title", children: "Move to\u2026" }),
13456
- 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)(
13457
13710
  "button",
13458
13711
  {
13459
13712
  type: "button",
@@ -13465,7 +13718,7 @@ function FolderPickerMenu({
13465
13718
  setOpen(false);
13466
13719
  },
13467
13720
  children: [
13468
- /* @__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" }),
13469
13722
  d.name
13470
13723
  ]
13471
13724
  },
@@ -13475,8 +13728,8 @@ function FolderPickerMenu({
13475
13728
  ] });
13476
13729
  }
13477
13730
  function RowShell({ icon, name, meta, onOpen, draggableId, isDropTarget, onDropPayload, actions, className = "" }) {
13478
- const [over, setOver] = React65.useState(false);
13479
- const dragCounter = React65.useRef(0);
13731
+ const [over, setOver] = React66.useState(false);
13732
+ const dragCounter = React66.useRef(0);
13480
13733
  const dropHandlers = isDropTarget ? {
13481
13734
  onDragEnter: (e) => {
13482
13735
  if (!hasInternalPayload(e)) return;
@@ -13501,8 +13754,8 @@ function RowShell({ icon, name, meta, onOpen, draggableId, isDropTarget, onDropP
13501
13754
  if (payload && onDropPayload) onDropPayload(payload);
13502
13755
  }
13503
13756
  } : {};
13504
- return /* @__PURE__ */ (0, import_jsx_runtime97.jsxs)("div", { className: ["fd-fb-row", over ? "is-drop-target" : "", className].filter(Boolean).join(" "), ...dropHandlers, children: [
13505
- /* @__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)(
13506
13759
  "button",
13507
13760
  {
13508
13761
  type: "button",
@@ -13511,26 +13764,26 @@ function RowShell({ icon, name, meta, onOpen, draggableId, isDropTarget, onDropP
13511
13764
  draggable: !!draggableId,
13512
13765
  onDragStart: draggableId ? (e) => writeDragPayload(e, draggableId) : void 0,
13513
13766
  children: [
13514
- /* @__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 }) }),
13515
- /* @__PURE__ */ (0, import_jsx_runtime97.jsxs)("span", { className: "fd-fb-row-text", children: [
13516
- /* @__PURE__ */ (0, import_jsx_runtime97.jsx)("span", { className: "fd-fb-row-name", title: name, children: name }),
13517
- 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
13518
13771
  ] })
13519
13772
  ]
13520
13773
  }
13521
13774
  ),
13522
- 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
13523
13776
  ] });
13524
13777
  }
13525
13778
  function TreeNode({ folder, depth, folders, currentFolderId, onNavigate, onMoveInto, canMove }) {
13526
13779
  const kids = childrenOf(folders, folder.id);
13527
- const [expanded, setExpanded] = React65.useState(() => currentFolderId != null && isSelfOrDescendant(folders, folder.id, currentFolderId));
13528
- React65.useEffect(() => {
13780
+ const [expanded, setExpanded] = React66.useState(() => currentFolderId != null && isSelfOrDescendant(folders, folder.id, currentFolderId));
13781
+ React66.useEffect(() => {
13529
13782
  if (currentFolderId != null && isSelfOrDescendant(folders, folder.id, currentFolderId)) setExpanded(true);
13530
13783
  }, [currentFolderId, folder.id, folders]);
13531
13784
  const isCurrent = folder.id === currentFolderId;
13532
- return /* @__PURE__ */ (0, import_jsx_runtime97.jsxs)("div", { className: "fd-fb-tree-node", children: [
13533
- /* @__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)(
13534
13787
  RowShell,
13535
13788
  {
13536
13789
  icon: folder.id === currentFolderId ? "folder-open" : "folder-simple",
@@ -13540,7 +13793,7 @@ function TreeNode({ folder, depth, folders, currentFolderId, onNavigate, onMoveI
13540
13793
  isDropTarget: canMove,
13541
13794
  onDropPayload: (payload) => onMoveInto(payload, folder.id),
13542
13795
  className: ["fd-fb-tree-row", isCurrent ? "is-current" : ""].filter(Boolean).join(" "),
13543
- actions: kids.length ? /* @__PURE__ */ (0, import_jsx_runtime97.jsx)(
13796
+ actions: kids.length ? /* @__PURE__ */ (0, import_jsx_runtime98.jsx)(
13544
13797
  IconButton,
13545
13798
  {
13546
13799
  icon: expanded ? "caret-down" : "caret-right",
@@ -13552,7 +13805,7 @@ function TreeNode({ folder, depth, folders, currentFolderId, onNavigate, onMoveI
13552
13805
  ) : void 0
13553
13806
  }
13554
13807
  ),
13555
- 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)(
13556
13809
  TreeNode,
13557
13810
  {
13558
13811
  folder: k,
@@ -13591,15 +13844,15 @@ function FileBrowser({
13591
13844
  const canUpload = perm.canUpload !== false && !!onUpload;
13592
13845
  const canRemoveFile = perm.canRemoveFile !== false && !!onRemoveFile;
13593
13846
  const canDeleteFolder = perm.canDeleteFolder !== false && !!onDeleteFolder;
13594
- const [createOpen, setCreateOpen] = React65.useState(false);
13595
- const [createName, setCreateName] = React65.useState("");
13596
- const [renameTarget, setRenameTarget] = React65.useState(null);
13597
- const [renameValue, setRenameValue] = React65.useState("");
13598
- const [deleteTarget, setDeleteTarget] = React65.useState(null);
13599
- const uploadInputRef = React65.useRef(null);
13600
- const crumbFolders = React65.useMemo(() => ancestorsOf(folders, currentFolderId), [folders, currentFolderId]);
13601
- const subfolders = React65.useMemo(() => childrenOf(folders, currentFolderId), [folders, currentFolderId]);
13602
- 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(
13603
13856
  () => files.filter((f) => f.folderId === currentFolderId).sort((a, b) => a.name.localeCompare(b.name)),
13604
13857
  [files, currentFolderId]
13605
13858
  );
@@ -13638,10 +13891,10 @@ function FileBrowser({
13638
13891
  if (deleteTarget && onDeleteFolder) onDeleteFolder(deleteTarget);
13639
13892
  setDeleteTarget(null);
13640
13893
  };
13641
- const content = /* @__PURE__ */ (0, import_jsx_runtime97.jsxs)("div", { className: ["fd-fb", className].filter(Boolean).join(" "), children: [
13642
- /* @__PURE__ */ (0, import_jsx_runtime97.jsxs)("div", { className: "fd-fb-head", children: [
13643
- /* @__PURE__ */ (0, import_jsx_runtime97.jsxs)("nav", { className: "fd-fb-crumbs", "aria-label": "Folder path", children: [
13644
- /* @__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)(
13645
13898
  BreadcrumbCrumb,
13646
13899
  {
13647
13900
  label: "Home",
@@ -13651,7 +13904,7 @@ function FileBrowser({
13651
13904
  onDropPayload: (p) => moveIntoFolder(p, null)
13652
13905
  }
13653
13906
  ),
13654
- crumbFolders.map((f, i) => /* @__PURE__ */ (0, import_jsx_runtime97.jsx)(
13907
+ crumbFolders.map((f, i) => /* @__PURE__ */ (0, import_jsx_runtime98.jsx)(
13655
13908
  BreadcrumbCrumb,
13656
13909
  {
13657
13910
  label: f.name,
@@ -13663,11 +13916,11 @@ function FileBrowser({
13663
13916
  f.id
13664
13917
  ))
13665
13918
  ] }),
13666
- /* @__PURE__ */ (0, import_jsx_runtime97.jsxs)("span", { className: "fd-fb-actions", children: [
13667
- canCreateFolder ? /* @__PURE__ */ (0, import_jsx_runtime97.jsx)(Button, { variant: "secondary", size: "sm", icon: "folder-simple-plus", onClick: openCreate, children: "New folder" }) : null,
13668
- canUpload ? /* @__PURE__ */ (0, import_jsx_runtime97.jsxs)(import_jsx_runtime97.Fragment, { children: [
13669
- /* @__PURE__ */ (0, import_jsx_runtime97.jsx)(Button, { variant: "secondary", size: "sm", icon: "upload-simple", onClick: () => uploadInputRef.current && uploadInputRef.current.click(), children: "Upload" }),
13670
- /* @__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)(
13671
13924
  "input",
13672
13925
  {
13673
13926
  ref: uploadInputRef,
@@ -13685,9 +13938,9 @@ function FileBrowser({
13685
13938
  ] }) : null
13686
13939
  ] })
13687
13940
  ] }),
13688
- /* @__PURE__ */ (0, import_jsx_runtime97.jsxs)("div", { className: "fd-fb-body", children: [
13689
- /* @__PURE__ */ (0, import_jsx_runtime97.jsxs)("div", { className: "fd-fb-tree", role: "region", "aria-label": "Folder tree", children: [
13690
- /* @__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)(
13691
13944
  RowShell,
13692
13945
  {
13693
13946
  icon: "house-simple",
@@ -13698,7 +13951,7 @@ function FileBrowser({
13698
13951
  className: ["fd-fb-tree-row", currentFolderId == null ? "is-current" : ""].filter(Boolean).join(" ")
13699
13952
  }
13700
13953
  ),
13701
- childrenOf(folders, null).map((f) => /* @__PURE__ */ (0, import_jsx_runtime97.jsx)(
13954
+ childrenOf(folders, null).map((f) => /* @__PURE__ */ (0, import_jsx_runtime98.jsx)(
13702
13955
  TreeNode,
13703
13956
  {
13704
13957
  folder: f,
@@ -13712,18 +13965,18 @@ function FileBrowser({
13712
13965
  f.id
13713
13966
  ))
13714
13967
  ] }),
13715
- /* @__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)(
13716
13969
  LoadingRegion,
13717
13970
  {
13718
13971
  state: loading ? "loading" : "ready",
13719
13972
  label: "Loading folder contents",
13720
- skeleton: /* @__PURE__ */ (0, import_jsx_runtime97.jsxs)("div", { className: "fd-stack", style: { gap: 8, padding: 12 }, children: [
13721
- /* @__PURE__ */ (0, import_jsx_runtime97.jsx)(Skeleton, { h: 44, radius: "10px" }),
13722
- /* @__PURE__ */ (0, import_jsx_runtime97.jsx)(Skeleton, { h: 44, radius: "10px" }),
13723
- /* @__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" })
13724
13977
  ] }),
13725
- 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: [
13726
- 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)(
13727
13980
  RowShell,
13728
13981
  {
13729
13982
  icon: "folder-simple",
@@ -13732,9 +13985,9 @@ function FileBrowser({
13732
13985
  draggableId: canMove ? { kind: "folder", id: f.id } : void 0,
13733
13986
  isDropTarget: canMove,
13734
13987
  onDropPayload: (p) => moveIntoFolder(p, f.id),
13735
- actions: /* @__PURE__ */ (0, import_jsx_runtime97.jsxs)(import_jsx_runtime97.Fragment, { children: [
13736
- canRenameFolder ? /* @__PURE__ */ (0, import_jsx_runtime97.jsx)(IconButton, { icon: "pencil-simple", label: "Rename " + f.name, size: "sm", variant: "ghost", onClick: () => openRename(f) }) : null,
13737
- 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)(
13738
13991
  FolderPickerMenu,
13739
13992
  {
13740
13993
  label: "Move " + f.name,
@@ -13742,12 +13995,12 @@ function FileBrowser({
13742
13995
  onPick: (target) => moveIntoFolder({ kind: "folder", id: f.id }, target)
13743
13996
  }
13744
13997
  ) : null,
13745
- 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
13746
13999
  ] })
13747
14000
  },
13748
14001
  f.id
13749
14002
  )),
13750
- currentFiles.map((file) => /* @__PURE__ */ (0, import_jsx_runtime97.jsx)(
14003
+ currentFiles.map((file) => /* @__PURE__ */ (0, import_jsx_runtime98.jsx)(
13751
14004
  RowShell,
13752
14005
  {
13753
14006
  icon: iconForMime(file.mime, file.name),
@@ -13755,8 +14008,8 @@ function FileBrowser({
13755
14008
  meta: file.size ? formatBytes(file.size) : void 0,
13756
14009
  onOpen: onOpenFile ? () => onOpenFile(file) : void 0,
13757
14010
  draggableId: canMove ? { kind: "file", id: file.id } : void 0,
13758
- actions: /* @__PURE__ */ (0, import_jsx_runtime97.jsxs)(import_jsx_runtime97.Fragment, { children: [
13759
- 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)(
13760
14013
  FolderPickerMenu,
13761
14014
  {
13762
14015
  label: "Move " + file.name,
@@ -13764,7 +14017,7 @@ function FileBrowser({
13764
14017
  onPick: (target) => onMoveFile && onMoveFile(file.id, target)
13765
14018
  }
13766
14019
  ) : null,
13767
- 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
13768
14021
  ] })
13769
14022
  },
13770
14023
  file.id
@@ -13773,10 +14026,10 @@ function FileBrowser({
13773
14026
  }
13774
14027
  ) })
13775
14028
  ] }),
13776
- /* @__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: [
13777
- /* @__PURE__ */ (0, import_jsx_runtime97.jsx)(Button, { variant: "secondary", onClick: () => setCreateOpen(false), children: "Cancel" }),
13778
- /* @__PURE__ */ (0, import_jsx_runtime97.jsx)(Button, { onClick: submitCreate, disabled: !createName.trim(), children: "Create" })
13779
- ] }), 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)(
13780
14033
  "input",
13781
14034
  {
13782
14035
  className: "fd-fb-input",
@@ -13790,10 +14043,10 @@ function FileBrowser({
13790
14043
  autoFocus: true
13791
14044
  }
13792
14045
  ) }),
13793
- /* @__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: [
13794
- /* @__PURE__ */ (0, import_jsx_runtime97.jsx)(Button, { variant: "secondary", onClick: () => setRenameTarget(null), children: "Cancel" }),
13795
- /* @__PURE__ */ (0, import_jsx_runtime97.jsx)(Button, { onClick: submitRename, disabled: !renameValue.trim(), children: "Save" })
13796
- ] }), 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)(
13797
14050
  "input",
13798
14051
  {
13799
14052
  className: "fd-fb-input",
@@ -13807,22 +14060,22 @@ function FileBrowser({
13807
14060
  autoFocus: true
13808
14061
  }
13809
14062
  ) }),
13810
- /* @__PURE__ */ (0, import_jsx_runtime97.jsx)(
14063
+ /* @__PURE__ */ (0, import_jsx_runtime98.jsx)(
13811
14064
  Modal,
13812
14065
  {
13813
14066
  open: deleteTarget != null,
13814
14067
  title: deleteTarget ? "Delete \u201C" + deleteTarget.name + "\u201D?" : "Delete folder?",
13815
14068
  description: "This can't be undone. The folder must be empty.",
13816
14069
  onClose: () => setDeleteTarget(null),
13817
- footer: /* @__PURE__ */ (0, import_jsx_runtime97.jsxs)(import_jsx_runtime97.Fragment, { children: [
13818
- /* @__PURE__ */ (0, import_jsx_runtime97.jsx)(Button, { variant: "secondary", onClick: () => setDeleteTarget(null), children: "Cancel" }),
13819
- /* @__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" })
13820
14073
  ] })
13821
14074
  }
13822
14075
  )
13823
14076
  ] });
13824
14077
  if (!canUpload) return content;
13825
- 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 });
13826
14079
  }
13827
14080
  function BreadcrumbCrumb({
13828
14081
  label,
@@ -13831,8 +14084,8 @@ function BreadcrumbCrumb({
13831
14084
  isDropTarget,
13832
14085
  onDropPayload
13833
14086
  }) {
13834
- const [over, setOver] = React65.useState(false);
13835
- const dragCounter = React65.useRef(0);
14087
+ const [over, setOver] = React66.useState(false);
14088
+ const dragCounter = React66.useRef(0);
13836
14089
  const dropHandlers = isDropTarget ? {
13837
14090
  onDragEnter: (e) => {
13838
14091
  if (!hasInternalPayload(e)) return;
@@ -13857,11 +14110,11 @@ function BreadcrumbCrumb({
13857
14110
  if (payload && onDropPayload) onDropPayload(payload);
13858
14111
  }
13859
14112
  } : {};
13860
- 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 }) });
13861
14114
  }
13862
14115
 
13863
14116
  // src/kits/query.ts
13864
- var React66 = __toESM(require("react"), 1);
14117
+ var React67 = __toESM(require("react"), 1);
13865
14118
  var isMultiSelectShaped = (v) => !!v && typeof v === "object" && Array.isArray(v.values);
13866
14119
  var isRangeShaped = (v) => !!v && typeof v === "object" && ("min" in v || "max" in v);
13867
14120
  var isDateShaped = (v) => !!v && typeof v === "object" && "kind" in v;
@@ -13916,22 +14169,22 @@ function compare(a, b, dir) {
13916
14169
  var API = null;
13917
14170
  var PREFS = null;
13918
14171
  function useServerTable({ endpoint, params, defaults, deps, prefsKey }) {
13919
- const [query, setQuery] = React66.useState(() => {
14172
+ const [query, setQuery] = React67.useState(() => {
13920
14173
  const store = PREFS || window.PlannerPrefs;
13921
14174
  const saved = prefsKey && store ? store.getTable(prefsKey) : {};
13922
14175
  return { ...DEFAULTS, ...defaults || {}, ...saved.pageSize ? { pageSize: saved.pageSize } : {}, ...saved.sort ? { sort: saved.sort, dir: saved.dir || "desc" } : {} };
13923
14176
  });
13924
- const savePref = React66.useCallback((patch2) => {
14177
+ const savePref = React67.useCallback((patch2) => {
13925
14178
  const store = PREFS || window.PlannerPrefs;
13926
14179
  if (prefsKey && store) store.setTable(prefsKey, patch2);
13927
14180
  }, [prefsKey]);
13928
- const [res, setRes] = React66.useState(null);
13929
- const [loading, setLoading] = React66.useState(true);
13930
- 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);
13931
14184
  const depKey = (deps || []).join("|");
13932
14185
  const paramKey = JSON.stringify(params || {});
13933
14186
  const queryKey = JSON.stringify(query);
13934
- React66.useEffect(() => {
14187
+ React67.useEffect(() => {
13935
14188
  const id = ++seq2.current;
13936
14189
  setLoading(true);
13937
14190
  const t = setTimeout(() => {
@@ -14250,12 +14503,12 @@ function createVersionStore(initialState, options) {
14250
14503
  }
14251
14504
 
14252
14505
  // src/kits/documentTitle.ts
14253
- var React67 = __toESM(require("react"), 1);
14506
+ var React68 = __toESM(require("react"), 1);
14254
14507
  function formatDocumentTitle(routeTitle, appName) {
14255
14508
  return [routeTitle, appName, "Flytedesk"].filter((part) => !!part && part.length > 0).join(" \xB7 ");
14256
14509
  }
14257
14510
  function useDocumentTitle(routeTitle, appName) {
14258
- React67.useEffect(() => {
14511
+ React68.useEffect(() => {
14259
14512
  if (typeof document === "undefined") return;
14260
14513
  document.title = formatDocumentTitle(routeTitle, appName);
14261
14514
  }, [routeTitle, appName]);
@@ -14298,6 +14551,7 @@ function useDocumentTitle(routeTitle, appName) {
14298
14551
  Clamp,
14299
14552
  ClockFace,
14300
14553
  CodeBlock,
14554
+ CodeEditor,
14301
14555
  Collapsible,
14302
14556
  ComingSoon,
14303
14557
  CsiBadge,