@flytedan/flytebot-design-system 0.48.1 → 0.49.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -4641,7 +4641,7 @@ function CodeBlock({
4641
4641
  code = "",
4642
4642
  language,
4643
4643
  filename,
4644
- lineNumbers = false,
4644
+ lineNumbers: lineNumbers2 = false,
4645
4645
  wrap: wrapDefault = false,
4646
4646
  collapseAfter = 26,
4647
4647
  copyable = true,
@@ -4668,7 +4668,7 @@ function CodeBlock({
4668
4668
  ] }) : null
4669
4669
  ] }),
4670
4670
  /* @__PURE__ */ jsxs41("div", { className: "fd-code-body", children: [
4671
- lineNumbers ? /* @__PURE__ */ jsx49("pre", { className: "fd-code-gutter", "aria-hidden": "true", children: shown.split("\n").map((_, i) => i + 1 + "\n").join("") }) : null,
4671
+ lineNumbers2 ? /* @__PURE__ */ jsx49("pre", { className: "fd-code-gutter", "aria-hidden": "true", children: shown.split("\n").map((_, i) => i + 1 + "\n").join("") }) : null,
4672
4672
  /* @__PURE__ */ jsx49("pre", { className: "fd-code-pre", tabIndex: 0, children: /* @__PURE__ */ jsx49("code", { children: /* @__PURE__ */ jsx49(Highlighted, { code: shown, lang: language }) }) })
4673
4673
  ] }),
4674
4674
  foldable ? /* @__PURE__ */ jsxs41("button", { type: "button", className: "fd-code-fold", onClick: () => setOpen((v) => !v), "aria-expanded": open2, children: [
@@ -7251,17 +7251,254 @@ var MarkdownEditor = React42.forwardRef(function MarkdownEditor2({
7251
7251
  ] });
7252
7252
  });
7253
7253
 
7254
+ // src/components/forms/CodeEditor.tsx
7255
+ import * as React43 from "react";
7256
+ import { EditorView, keymap, lineNumbers, placeholder as cmPlaceholder, drawSelection, Decoration } from "@codemirror/view";
7257
+ import { EditorState, StateEffect, StateField, Compartment } from "@codemirror/state";
7258
+ import { defaultKeymap, history, historyKeymap, indentMore, indentLess } from "@codemirror/commands";
7259
+ import { sql as sqlLang } from "@codemirror/lang-sql";
7260
+ import { syntaxHighlighting, HighlightStyle, indentOnInput, bracketMatching } from "@codemirror/language";
7261
+ import { tags } from "@lezer/highlight";
7262
+ import { jsx as jsx72, jsxs as jsxs63 } from "react/jsx-runtime";
7263
+ function clampOffset(state, line, column) {
7264
+ const total = state.doc.lines;
7265
+ const ln = state.doc.line(Math.min(Math.max(1, line), total));
7266
+ const col = Math.max(0, (column || 1) - 1);
7267
+ return Math.min(ln.from + col, ln.to);
7268
+ }
7269
+ function toCmDiagnostics(state, diags) {
7270
+ return diags.map((d) => {
7271
+ const from = clampOffset(state, d.line, d.column ?? 1);
7272
+ const endLine = d.endLine ?? d.line;
7273
+ const endColumn = d.endColumn ?? state.doc.line(Math.min(Math.max(1, endLine), state.doc.lines)).length + 1;
7274
+ let to = clampOffset(state, endLine, endColumn);
7275
+ if (to <= from) to = Math.min(from + 1, state.doc.length);
7276
+ return { from, to, severity: d.severity || "error", message: d.message, source: void 0 };
7277
+ });
7278
+ }
7279
+ var setDiagnosticsEffect = StateEffect.define();
7280
+ var diagnosticsField = StateField.define({
7281
+ create: () => [],
7282
+ update(value, tr) {
7283
+ for (const e of tr.effects) if (e.is(setDiagnosticsEffect)) return e.value;
7284
+ if (!tr.docChanged) return value;
7285
+ return value.map((d) => ({ ...d, from: tr.changes.mapPos(d.from), to: tr.changes.mapPos(d.to) }));
7286
+ }
7287
+ });
7288
+ var tokenHighlight = HighlightStyle.define([
7289
+ { tag: tags.keyword, class: "tok-kw" },
7290
+ { tag: tags.string, class: "tok-str" },
7291
+ { tag: [tags.number, tags.bool], class: "tok-num" },
7292
+ { tag: tags.comment, class: "tok-com" },
7293
+ { tag: [tags.function(tags.variableName), tags.function(tags.propertyName)], class: "tok-fn" },
7294
+ { tag: tags.typeName, class: "tok-type" },
7295
+ { tag: tags.propertyName, class: "tok-prop" },
7296
+ { tag: tags.null, class: "tok-lit" },
7297
+ { tag: [tags.punctuation, tags.paren, tags.bracket], class: "tok-pun" },
7298
+ { tag: tags.operator, class: "tok-op" }
7299
+ ]);
7300
+ var editorTheme = EditorView.theme({
7301
+ "&": {
7302
+ fontFamily: "var(--font-mono)",
7303
+ fontSize: "12.5px",
7304
+ color: "var(--text)",
7305
+ backgroundColor: "transparent",
7306
+ height: "100%"
7307
+ },
7308
+ ".cm-content": { padding: "10px 12px", caretColor: "var(--text)" },
7309
+ ".cm-scroller": { fontFamily: "var(--font-mono)", lineHeight: "1.62" },
7310
+ ".cm-gutters": {
7311
+ backgroundColor: "transparent",
7312
+ color: "var(--text-disabled)",
7313
+ border: "0",
7314
+ borderRight: "1px solid var(--chat-code-border)"
7315
+ },
7316
+ ".cm-lineNumbers .cm-gutterElement": { padding: "0 8px 0 12px" },
7317
+ ".cm-activeLine": { backgroundColor: "var(--surface-2)" },
7318
+ ".cm-activeLineGutter": { backgroundColor: "var(--surface-2)", color: "var(--text-2)" },
7319
+ "&.cm-focused": { outline: "none" },
7320
+ ".cm-cursor": { borderLeftColor: "var(--text)" },
7321
+ ".cm-selectionBackground, &.cm-focused .cm-selectionBackground": { backgroundColor: "var(--blue-100) !important" },
7322
+ ".cm-placeholder": { color: "var(--text-disabled)" },
7323
+ ".fd-cm-diag-error": { textDecoration: "underline wavy var(--danger-solid)", textUnderlineOffset: "3px" },
7324
+ ".fd-cm-diag-warning": { textDecoration: "underline wavy var(--warn-solid)", textUnderlineOffset: "3px" },
7325
+ ".fd-cm-diag-info": { textDecoration: "underline wavy var(--info-solid)", textUnderlineOffset: "3px" }
7326
+ }, { dark: false });
7327
+ function severityClass(sev) {
7328
+ return sev === "warning" ? "fd-cm-diag-warning" : sev === "info" ? "fd-cm-diag-info" : "fd-cm-diag-error";
7329
+ }
7330
+ function decorationsFromDiagnostics() {
7331
+ return EditorView.decorations.compute([diagnosticsField], (state) => {
7332
+ const diags = state.field(diagnosticsField);
7333
+ if (!diags.length) return Decoration.none;
7334
+ const marks = diags.filter((d) => d.from < d.to).sort((a, b) => a.from - b.from).map((d) => Decoration.mark({ class: severityClass(d.severity) }).range(d.from, d.to));
7335
+ return Decoration.set(marks, true);
7336
+ });
7337
+ }
7338
+ function CodeEditor({
7339
+ value,
7340
+ onChange,
7341
+ label,
7342
+ help,
7343
+ error,
7344
+ required = false,
7345
+ disabled = false,
7346
+ readOnly = false,
7347
+ placeholder: placeholderText = "",
7348
+ diagnostics = [],
7349
+ showEscapeHint = true,
7350
+ minHeight = 160,
7351
+ id,
7352
+ className = "",
7353
+ style,
7354
+ autoFocus = false
7355
+ }) {
7356
+ const fieldId = useFieldId(id);
7357
+ const descId = fieldId + "-desc";
7358
+ const liveId = fieldId + "-live";
7359
+ const hostRef = React43.useRef(null);
7360
+ const viewRef = React43.useRef(null);
7361
+ const valueRef = React43.useRef(value);
7362
+ const onChangeRef = React43.useRef(onChange);
7363
+ onChangeRef.current = onChange;
7364
+ const editableCompartment = React43.useRef(new Compartment()).current;
7365
+ const attributesCompartment = React43.useRef(new Compartment()).current;
7366
+ const errorRef = React43.useRef(error);
7367
+ errorRef.current = error;
7368
+ const diagnosticsCountRef = React43.useRef(diagnostics.length);
7369
+ diagnosticsCountRef.current = diagnostics.length;
7370
+ function contentAttributes() {
7371
+ return {
7372
+ id: fieldId,
7373
+ "aria-describedby": descId + " " + liveId,
7374
+ "aria-invalid": errorRef.current || diagnosticsCountRef.current ? "true" : "false",
7375
+ ...label ? { "aria-label": label } : {}
7376
+ };
7377
+ }
7378
+ React43.useEffect(() => {
7379
+ const host = hostRef.current;
7380
+ if (!host) return;
7381
+ const updateListener = EditorView.updateListener.of((update) => {
7382
+ if (!update.docChanged) return;
7383
+ const next = update.state.doc.toString();
7384
+ valueRef.current = next;
7385
+ onChangeRef.current && onChangeRef.current(next);
7386
+ });
7387
+ const state = EditorState.create({
7388
+ doc: value,
7389
+ extensions: [
7390
+ lineNumbers(),
7391
+ history(),
7392
+ drawSelection(),
7393
+ indentOnInput(),
7394
+ bracketMatching(),
7395
+ sqlLang(),
7396
+ syntaxHighlighting(tokenHighlight),
7397
+ diagnosticsField,
7398
+ decorationsFromDiagnostics(),
7399
+ editorTheme,
7400
+ cmPlaceholder(placeholderText),
7401
+ keymap.of([
7402
+ { key: "Tab", run: indentMore, shift: indentLess },
7403
+ ...defaultKeymap,
7404
+ ...historyKeymap
7405
+ ]),
7406
+ editableCompartment.of(EditorView.editable.of(!disabled)),
7407
+ EditorState.readOnly.of(readOnly),
7408
+ updateListener,
7409
+ attributesCompartment.of(EditorView.contentAttributes.of(contentAttributes()))
7410
+ ]
7411
+ });
7412
+ const view = new EditorView({ state, parent: host });
7413
+ viewRef.current = view;
7414
+ if (autoFocus) view.focus();
7415
+ return () => {
7416
+ view.destroy();
7417
+ viewRef.current = null;
7418
+ };
7419
+ }, []);
7420
+ React43.useEffect(() => {
7421
+ const view = viewRef.current;
7422
+ if (!view) return;
7423
+ const current2 = view.state.doc.toString();
7424
+ if (current2 !== value) {
7425
+ view.dispatch({ changes: { from: 0, to: current2.length, insert: value } });
7426
+ }
7427
+ valueRef.current = value;
7428
+ }, [value]);
7429
+ React43.useEffect(() => {
7430
+ const view = viewRef.current;
7431
+ if (!view) return;
7432
+ view.dispatch({ effects: editableCompartment.reconfigure(EditorView.editable.of(!disabled)) });
7433
+ }, [disabled, editableCompartment]);
7434
+ React43.useEffect(() => {
7435
+ const view = viewRef.current;
7436
+ if (!view) return;
7437
+ view.dispatch({
7438
+ effects: [
7439
+ setDiagnosticsEffect.of(toCmDiagnostics(view.state, diagnostics)),
7440
+ attributesCompartment.reconfigure(EditorView.contentAttributes.of(contentAttributes()))
7441
+ ]
7442
+ });
7443
+ }, [diagnostics, error]);
7444
+ const box = ["fd-input", "fd-code-editor", error ? "fd-input-error" : "", disabled ? "fd-input-disabled" : ""].filter(Boolean).join(" ");
7445
+ 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("; ") : "";
7446
+ return /* @__PURE__ */ jsxs63("div", { className: ["fd-field", className].filter(Boolean).join(" "), style, children: [
7447
+ label ? /* @__PURE__ */ jsx72(FieldLabel, { htmlFor: fieldId, required, children: label }) : null,
7448
+ /* @__PURE__ */ jsx72(
7449
+ "div",
7450
+ {
7451
+ className: box,
7452
+ style: { minHeight },
7453
+ children: /* @__PURE__ */ jsx72(
7454
+ "div",
7455
+ {
7456
+ ref: hostRef,
7457
+ className: "fd-code-editor-host",
7458
+ style: { minHeight }
7459
+ }
7460
+ )
7461
+ }
7462
+ ),
7463
+ /* @__PURE__ */ jsxs63("span", { id: descId, className: "fd-sr", children: [
7464
+ help ? help + ". " : "",
7465
+ showEscapeHint ? "Tab indents. Press Escape, then Tab, to move focus out of the editor." : ""
7466
+ ] }),
7467
+ /* @__PURE__ */ jsx72("div", { id: liveId, className: "fd-sr", role: "status", "aria-live": "polite", children: announce }),
7468
+ diagnostics.length ? /* @__PURE__ */ jsx72("ul", { className: "fd-code-editor-diagnostics", children: diagnostics.map((d, i) => /* @__PURE__ */ jsxs63("li", { className: "fd-code-editor-diag is-" + (d.severity || "error"), children: [
7469
+ /* @__PURE__ */ jsx72(
7470
+ "i",
7471
+ {
7472
+ className: "ph ph-" + (d.severity === "warning" ? "warning" : d.severity === "info" ? "info" : "warning-circle"),
7473
+ "aria-hidden": "true"
7474
+ }
7475
+ ),
7476
+ /* @__PURE__ */ jsxs63("span", { className: "fd-code-editor-diag-loc", children: [
7477
+ "Line ",
7478
+ d.line,
7479
+ d.column ? ":" + d.column : ""
7480
+ ] }),
7481
+ /* @__PURE__ */ jsx72("span", { children: d.message })
7482
+ ] }, i)) }) : null,
7483
+ error ? /* @__PURE__ */ jsxs63("span", { className: "fd-field-error", children: [
7484
+ /* @__PURE__ */ jsx72("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
7485
+ error
7486
+ ] }) : !diagnostics.length && help ? /* @__PURE__ */ jsx72("span", { className: "fd-field-help", children: help }) : null,
7487
+ showEscapeHint ? /* @__PURE__ */ jsx72("span", { className: "fd-field-help fd-code-editor-hint", children: "Tab indents. Escape, then Tab, moves focus out." }) : null
7488
+ ] });
7489
+ }
7490
+
7254
7491
  // src/components/platform/AccountMenu.tsx
7255
- import * as React44 from "react";
7492
+ import * as React45 from "react";
7256
7493
 
7257
7494
  // src/kits/sessionContext.tsx
7258
- import * as React43 from "react";
7259
- var SessionContext = React43.createContext(null);
7495
+ import * as React44 from "react";
7496
+ var SessionContext = React44.createContext(null);
7260
7497
  function SessionProvider({ value, children }) {
7261
- return React43.createElement(SessionContext.Provider, { value }, children);
7498
+ return React44.createElement(SessionContext.Provider, { value }, children);
7262
7499
  }
7263
7500
  function useSessionContext() {
7264
- const ctx = React43.useContext(SessionContext);
7501
+ const ctx = React44.useContext(SessionContext);
7265
7502
  if (!ctx) {
7266
7503
  throw new Error(
7267
7504
  "useSessionContext() was called outside a <SessionProvider>. Wrap your app root in <SessionProvider value={...}> with your real session, or \u2014 in the docs site or a demo \u2014 in <DemoSessionProvider>, before rendering AccountMenu, Gate, ProfilePage or AppSwitcher."
@@ -7271,11 +7508,11 @@ function useSessionContext() {
7271
7508
  }
7272
7509
 
7273
7510
  // src/components/platform/AccountMenu.tsx
7274
- import { Fragment as Fragment16, jsx as jsx72, jsxs as jsxs63 } from "react/jsx-runtime";
7511
+ import { Fragment as Fragment16, jsx as jsx73, jsxs as jsxs64 } from "react/jsx-runtime";
7275
7512
  var DEFAULT_LINKS = [];
7276
7513
  var DEFAULT_GROUPS = [];
7277
7514
  function Item({ item, onPick }) {
7278
- return /* @__PURE__ */ jsxs63(
7515
+ return /* @__PURE__ */ jsxs64(
7279
7516
  "button",
7280
7517
  {
7281
7518
  type: "button",
@@ -7283,9 +7520,9 @@ function Item({ item, onPick }) {
7283
7520
  className: "fd-acct-item",
7284
7521
  onClick: () => onPick(item),
7285
7522
  children: [
7286
- item.icon ? /* @__PURE__ */ jsx72("i", { className: "ph ph-" + item.icon, "aria-hidden": "true" }) : null,
7287
- /* @__PURE__ */ jsx72("span", { style: { flex: 1 }, children: item.label }),
7288
- item.badge ? /* @__PURE__ */ jsx72(Badge, { tone: "neutral", children: item.badge }) : null
7523
+ item.icon ? /* @__PURE__ */ jsx73("i", { className: "ph ph-" + item.icon, "aria-hidden": "true" }) : null,
7524
+ /* @__PURE__ */ jsx73("span", { style: { flex: 1 }, children: item.label }),
7525
+ item.badge ? /* @__PURE__ */ jsx73(Badge, { tone: "neutral", children: item.badge }) : null
7289
7526
  ]
7290
7527
  }
7291
7528
  );
@@ -7301,11 +7538,11 @@ function AccountMenu({
7301
7538
  ...rest
7302
7539
  }) {
7303
7540
  const { user, roles, can: can2, signOut: ctxSignOut, demo, pending } = useSessionContext();
7304
- const [open2, setOpen] = React44.useState(false);
7305
- const [switching, setSwitching] = React44.useState(false);
7306
- const [signingOut, setSigningOut] = React44.useState(false);
7307
- const [signOutError, setSignOutError] = React44.useState(null);
7308
- const ref = React44.useRef(null);
7541
+ const [open2, setOpen] = React45.useState(false);
7542
+ const [switching, setSwitching] = React45.useState(false);
7543
+ const [signingOut, setSigningOut] = React45.useState(false);
7544
+ const [signOutError, setSignOutError] = React45.useState(null);
7545
+ const ref = React45.useRef(null);
7309
7546
  const visibleLinks = links.filter((l) => !l.perm || !pending && can2(l.perm));
7310
7547
  const visibleGroups = groups.map((g) => ({ label: g.label, links: g.links.filter((l) => !l.perm || !pending && can2(l.perm)) })).filter((g) => g.links.length);
7311
7548
  const closeMenu = () => {
@@ -7333,8 +7570,8 @@ function AccountMenu({
7333
7570
  }
7334
7571
  };
7335
7572
  const showSwitcher = allowUserSwitch && !!demo;
7336
- return /* @__PURE__ */ jsxs63(Fragment16, { children: [
7337
- /* @__PURE__ */ jsxs63(
7573
+ return /* @__PURE__ */ jsxs64(Fragment16, { children: [
7574
+ /* @__PURE__ */ jsxs64(
7338
7575
  "button",
7339
7576
  {
7340
7577
  type: "button",
@@ -7346,12 +7583,12 @@ function AccountMenu({
7346
7583
  onClick: () => open2 ? closeMenu() : setOpen(true),
7347
7584
  ...rest,
7348
7585
  children: [
7349
- /* @__PURE__ */ jsx72(Avatar, { name: user.name, size: "sm" }),
7350
- /* @__PURE__ */ jsx72("i", { className: "ph ph-caret-down", "aria-hidden": "true", style: { fontSize: 11, color: "var(--text-muted)" } })
7586
+ /* @__PURE__ */ jsx73(Avatar, { name: user.name, size: "sm" }),
7587
+ /* @__PURE__ */ jsx73("i", { className: "ph ph-caret-down", "aria-hidden": "true", style: { fontSize: 11, color: "var(--text-muted)" } })
7351
7588
  ]
7352
7589
  }
7353
7590
  ),
7354
- /* @__PURE__ */ jsx72(
7591
+ /* @__PURE__ */ jsx73(
7355
7592
  Popover,
7356
7593
  {
7357
7594
  open: open2,
@@ -7359,27 +7596,27 @@ function AccountMenu({
7359
7596
  onClose: closeMenu,
7360
7597
  placement: "bottom-end",
7361
7598
  width: 272,
7362
- children: /* @__PURE__ */ jsxs63("div", { role: "menu", className: "fd-stack", style: { gap: 0 }, children: [
7363
- /* @__PURE__ */ jsxs63("div", { className: "fd-row", style: { gap: 10, padding: "12px 14px", borderBottom: "1px solid var(--border)" }, children: [
7364
- /* @__PURE__ */ jsx72(Avatar, { name: user.name }),
7365
- /* @__PURE__ */ jsxs63("span", { className: "fd-stack", style: { gap: 1, minWidth: 0, flex: 1 }, children: [
7366
- /* @__PURE__ */ jsx72("span", { className: "fd-body-sm", style: { fontWeight: 700 }, children: user.name }),
7367
- /* @__PURE__ */ jsx72("span", { className: "fd-body-sm fd-muted fd-table-trunc", title: truncationTitle(user.email), children: user.email })
7599
+ children: /* @__PURE__ */ jsxs64("div", { role: "menu", className: "fd-stack", style: { gap: 0 }, children: [
7600
+ /* @__PURE__ */ jsxs64("div", { className: "fd-row", style: { gap: 10, padding: "12px 14px", borderBottom: "1px solid var(--border)" }, children: [
7601
+ /* @__PURE__ */ jsx73(Avatar, { name: user.name }),
7602
+ /* @__PURE__ */ jsxs64("span", { className: "fd-stack", style: { gap: 1, minWidth: 0, flex: 1 }, children: [
7603
+ /* @__PURE__ */ jsx73("span", { className: "fd-body-sm", style: { fontWeight: 700 }, children: user.name }),
7604
+ /* @__PURE__ */ jsx73("span", { className: "fd-body-sm fd-muted fd-table-trunc", title: truncationTitle(user.email), children: user.email })
7368
7605
  ] })
7369
7606
  ] }),
7370
- showRoles && roles.length ? /* @__PURE__ */ jsx72("div", { className: "fd-row", style: { gap: 6, padding: "10px 14px", flexWrap: "wrap", borderBottom: "1px solid var(--border)" }, children: roles.map((r) => /* @__PURE__ */ jsx72(Badge, { tone: r.id === "owner" ? "success" : "neutral", children: r.name }, r.id)) }) : null,
7371
- visibleLinks.length ? /* @__PURE__ */ jsx72("div", { className: "fd-acct-group", children: visibleLinks.map((l) => /* @__PURE__ */ jsx72(Item, { item: l, onPick: pick }, l.id)) }) : null,
7372
- visibleGroups.map((g) => /* @__PURE__ */ jsxs63("div", { className: "fd-acct-group", style: { borderTop: "1px solid var(--border)" }, children: [
7373
- /* @__PURE__ */ jsx72("span", { className: "fd-overline fd-muted", style: { padding: "8px 14px 4px", display: "block" }, children: g.label }),
7374
- g.links.map((l) => /* @__PURE__ */ jsx72(Item, { item: l, onPick: pick }, l.id))
7607
+ showRoles && roles.length ? /* @__PURE__ */ jsx73("div", { className: "fd-row", style: { gap: 6, padding: "10px 14px", flexWrap: "wrap", borderBottom: "1px solid var(--border)" }, children: roles.map((r) => /* @__PURE__ */ jsx73(Badge, { tone: r.id === "owner" ? "success" : "neutral", children: r.name }, r.id)) }) : null,
7608
+ visibleLinks.length ? /* @__PURE__ */ jsx73("div", { className: "fd-acct-group", children: visibleLinks.map((l) => /* @__PURE__ */ jsx73(Item, { item: l, onPick: pick }, l.id)) }) : null,
7609
+ visibleGroups.map((g) => /* @__PURE__ */ jsxs64("div", { className: "fd-acct-group", style: { borderTop: "1px solid var(--border)" }, children: [
7610
+ /* @__PURE__ */ jsx73("span", { className: "fd-overline fd-muted", style: { padding: "8px 14px 4px", display: "block" }, children: g.label }),
7611
+ g.links.map((l) => /* @__PURE__ */ jsx73(Item, { item: l, onPick: pick }, l.id))
7375
7612
  ] }, g.label)),
7376
- showSwitcher && demo ? /* @__PURE__ */ jsxs63("div", { className: "fd-acct-group", style: { borderTop: "1px solid var(--border)" }, children: [
7377
- /* @__PURE__ */ jsxs63("button", { type: "button", role: "menuitem", className: "fd-acct-item", onClick: () => setSwitching((s) => !s), children: [
7378
- /* @__PURE__ */ jsx72("i", { className: "ph ph-user-switch", "aria-hidden": "true" }),
7379
- /* @__PURE__ */ jsx72("span", { style: { flex: 1 }, children: "View as another member" }),
7380
- /* @__PURE__ */ jsx72("i", { className: "ph ph-caret-" + (switching ? "up" : "down"), "aria-hidden": "true", style: { fontSize: 11 } })
7613
+ showSwitcher && demo ? /* @__PURE__ */ jsxs64("div", { className: "fd-acct-group", style: { borderTop: "1px solid var(--border)" }, children: [
7614
+ /* @__PURE__ */ jsxs64("button", { type: "button", role: "menuitem", className: "fd-acct-item", onClick: () => setSwitching((s) => !s), children: [
7615
+ /* @__PURE__ */ jsx73("i", { className: "ph ph-user-switch", "aria-hidden": "true" }),
7616
+ /* @__PURE__ */ jsx73("span", { style: { flex: 1 }, children: "View as another member" }),
7617
+ /* @__PURE__ */ jsx73("i", { className: "ph ph-caret-" + (switching ? "up" : "down"), "aria-hidden": "true", style: { fontSize: 11 } })
7381
7618
  ] }),
7382
- switching ? /* @__PURE__ */ jsx72("div", { className: "fd-stack", style: { gap: 0 }, children: demo.allUsers.map((u) => /* @__PURE__ */ jsxs63(
7619
+ switching ? /* @__PURE__ */ jsx73("div", { className: "fd-stack", style: { gap: 0 }, children: demo.allUsers.map((u) => /* @__PURE__ */ jsxs64(
7383
7620
  "button",
7384
7621
  {
7385
7622
  type: "button",
@@ -7391,19 +7628,19 @@ function AccountMenu({
7391
7628
  setSwitching(false);
7392
7629
  },
7393
7630
  children: [
7394
- /* @__PURE__ */ jsx72(Avatar, { name: u.name, size: "sm" }),
7395
- /* @__PURE__ */ jsxs63("span", { className: "fd-stack", style: { gap: 0, flex: 1, minWidth: 0, alignItems: "flex-start" }, children: [
7396
- /* @__PURE__ */ jsx72("span", { style: { fontWeight: u.id === user.id ? 700 : 500 }, children: u.name }),
7397
- u.roles ? /* @__PURE__ */ jsx72("span", { className: "fd-muted", style: { fontSize: 11.5 }, children: u.roles.join(", ") }) : null
7631
+ /* @__PURE__ */ jsx73(Avatar, { name: u.name, size: "sm" }),
7632
+ /* @__PURE__ */ jsxs64("span", { className: "fd-stack", style: { gap: 0, flex: 1, minWidth: 0, alignItems: "flex-start" }, children: [
7633
+ /* @__PURE__ */ jsx73("span", { style: { fontWeight: u.id === user.id ? 700 : 500 }, children: u.name }),
7634
+ u.roles ? /* @__PURE__ */ jsx73("span", { className: "fd-muted", style: { fontSize: 11.5 }, children: u.roles.join(", ") }) : null
7398
7635
  ] }),
7399
- u.id === user.id ? /* @__PURE__ */ jsx72("i", { className: "ph ph-check", "aria-hidden": "true", style: { color: "var(--ok-text)" } }) : null
7636
+ u.id === user.id ? /* @__PURE__ */ jsx73("i", { className: "ph ph-check", "aria-hidden": "true", style: { color: "var(--ok-text)" } }) : null
7400
7637
  ]
7401
7638
  },
7402
7639
  u.id
7403
7640
  )) }) : null
7404
7641
  ] }) : null,
7405
- /* @__PURE__ */ jsxs63("div", { className: "fd-acct-group", style: { borderTop: "1px solid var(--border)" }, children: [
7406
- /* @__PURE__ */ jsxs63(
7642
+ /* @__PURE__ */ jsxs64("div", { className: "fd-acct-group", style: { borderTop: "1px solid var(--border)" }, children: [
7643
+ /* @__PURE__ */ jsxs64(
7407
7644
  "button",
7408
7645
  {
7409
7646
  type: "button",
@@ -7413,14 +7650,14 @@ function AccountMenu({
7413
7650
  disabled: signingOut,
7414
7651
  onClick: signOut,
7415
7652
  children: [
7416
- signingOut ? /* @__PURE__ */ jsx72(Spinner, { size: "sm" }) : /* @__PURE__ */ jsx72("i", { className: "ph ph-sign-out", "aria-hidden": "true" }),
7417
- /* @__PURE__ */ jsx72("span", { style: { flex: 1 }, children: signingOut ? "Signing out\u2026" : "Sign out" })
7653
+ signingOut ? /* @__PURE__ */ jsx73(Spinner, { size: "sm" }) : /* @__PURE__ */ jsx73("i", { className: "ph ph-sign-out", "aria-hidden": "true" }),
7654
+ /* @__PURE__ */ jsx73("span", { style: { flex: 1 }, children: signingOut ? "Signing out\u2026" : "Sign out" })
7418
7655
  ]
7419
7656
  }
7420
7657
  ),
7421
- signOutError ? /* @__PURE__ */ jsxs63("div", { role: "alert", className: "fd-body-sm", style: { padding: "0 14px 12px" }, children: [
7422
- /* @__PURE__ */ jsx72("span", { style: { display: "block", color: "var(--danger-text)", marginBottom: 6 }, children: signOutError }),
7423
- /* @__PURE__ */ jsx72("button", { type: "button", className: "fd-soon-link", disabled: signingOut, onClick: signOut, children: "Retry" })
7658
+ signOutError ? /* @__PURE__ */ jsxs64("div", { role: "alert", className: "fd-body-sm", style: { padding: "0 14px 12px" }, children: [
7659
+ /* @__PURE__ */ jsx73("span", { style: { display: "block", color: "var(--danger-text)", marginBottom: 6 }, children: signOutError }),
7660
+ /* @__PURE__ */ jsx73("button", { type: "button", className: "fd-soon-link", disabled: signingOut, onClick: signOut, children: "Retry" })
7424
7661
  ] }) : null
7425
7662
  ] })
7426
7663
  ] })
@@ -7430,13 +7667,13 @@ function AccountMenu({
7430
7667
  }
7431
7668
 
7432
7669
  // src/components/platform/AppSwitcher.tsx
7433
- import * as React45 from "react";
7434
- import { jsx as jsx73, jsxs as jsxs64 } from "react/jsx-runtime";
7670
+ import * as React46 from "react";
7671
+ import { jsx as jsx74, jsxs as jsxs65 } from "react/jsx-runtime";
7435
7672
  function AppSwitcher({ apps: appsProp, onNavigate, className = "" }) {
7436
7673
  const { apps: contextApps } = useSessionContext();
7437
7674
  const apps = appsProp ?? contextApps ?? [];
7438
- const [open2, setOpen] = React45.useState(false);
7439
- const anchorRef = React45.useRef(null);
7675
+ const [open2, setOpen] = React46.useState(false);
7676
+ const anchorRef = React46.useRef(null);
7440
7677
  if (!apps.length) return null;
7441
7678
  const items = apps.map((app) => ({
7442
7679
  id: app.key,
@@ -7450,8 +7687,8 @@ function AppSwitcher({ apps: appsProp, onNavigate, className = "" }) {
7450
7687
  window.location.href = app.url;
7451
7688
  }
7452
7689
  }));
7453
- return /* @__PURE__ */ jsxs64(React45.Fragment, { children: [
7454
- /* @__PURE__ */ jsx73("span", { ref: anchorRef, className: ["fd-appswitch-anchor", className].filter(Boolean).join(" "), style: { display: "inline-flex" }, children: /* @__PURE__ */ jsx73(
7690
+ return /* @__PURE__ */ jsxs65(React46.Fragment, { children: [
7691
+ /* @__PURE__ */ jsx74("span", { ref: anchorRef, className: ["fd-appswitch-anchor", className].filter(Boolean).join(" "), style: { display: "inline-flex" }, children: /* @__PURE__ */ jsx74(
7455
7692
  IconButton,
7456
7693
  {
7457
7694
  icon: "squares-four",
@@ -7461,7 +7698,7 @@ function AppSwitcher({ apps: appsProp, onNavigate, className = "" }) {
7461
7698
  onClick: () => setOpen((v) => !v)
7462
7699
  }
7463
7700
  ) }),
7464
- /* @__PURE__ */ jsx73(
7701
+ /* @__PURE__ */ jsx74(
7465
7702
  Popover,
7466
7703
  {
7467
7704
  open: open2,
@@ -7472,17 +7709,17 @@ function AppSwitcher({ apps: appsProp, onNavigate, className = "" }) {
7472
7709
  label: "All flytedesk apps",
7473
7710
  width: 240,
7474
7711
  maxHeight: 360,
7475
- children: /* @__PURE__ */ jsx73(Menu, { items, onClose: () => setOpen(false) })
7712
+ children: /* @__PURE__ */ jsx74(Menu, { items, onClose: () => setOpen(false) })
7476
7713
  }
7477
7714
  )
7478
7715
  ] });
7479
7716
  }
7480
7717
 
7481
7718
  // src/components/platform/AppearanceMenu.tsx
7482
- import * as React47 from "react";
7719
+ import * as React48 from "react";
7483
7720
 
7484
7721
  // src/kits/appearance.ts
7485
- import * as React46 from "react";
7722
+ import * as React47 from "react";
7486
7723
  var DEFAULT_STORAGE_KEY = "fd-appearance";
7487
7724
  var DEFAULT_PREFS = {
7488
7725
  theme: "system",
@@ -7577,11 +7814,11 @@ function applyPrefs(prefs, root = document.documentElement) {
7577
7814
  else root.removeAttribute("data-motion");
7578
7815
  }
7579
7816
  function useAppearancePrefs(store) {
7580
- const prefs = React46.useSyncExternalStore(store.subscribe, store.getSnapshot);
7581
- React46.useEffect(() => {
7817
+ const prefs = React47.useSyncExternalStore(store.subscribe, store.getSnapshot);
7818
+ React47.useEffect(() => {
7582
7819
  applyPrefs(prefs);
7583
7820
  }, [prefs]);
7584
- React46.useEffect(() => {
7821
+ React47.useEffect(() => {
7585
7822
  if (prefs.theme !== "system" || typeof window === "undefined" || typeof window.matchMedia !== "function") {
7586
7823
  return;
7587
7824
  }
@@ -7590,7 +7827,7 @@ function useAppearancePrefs(store) {
7590
7827
  mq.addEventListener("change", onChange);
7591
7828
  return () => mq.removeEventListener("change", onChange);
7592
7829
  }, [prefs]);
7593
- const update = React46.useCallback(
7830
+ const update = React47.useCallback(
7594
7831
  (patch) => {
7595
7832
  store.write({ ...store.getSnapshot(), ...patch });
7596
7833
  },
@@ -7600,7 +7837,7 @@ function useAppearancePrefs(store) {
7600
7837
  }
7601
7838
 
7602
7839
  // src/components/platform/AppearanceMenu.tsx
7603
- import { jsx as jsx74, jsxs as jsxs65 } from "react/jsx-runtime";
7840
+ import { jsx as jsx75, jsxs as jsxs66 } from "react/jsx-runtime";
7604
7841
  var THEME_OPTIONS = [
7605
7842
  { value: "light", label: "Light" },
7606
7843
  { value: "dark", label: "Dark" },
@@ -7613,16 +7850,16 @@ var TEXT_SCALE_OPTIONS = [
7613
7850
  { value: "xl", label: "XL" }
7614
7851
  ];
7615
7852
  function AppearanceMenu({ className = "", store: storeProp, storageKey, storage, defaults }) {
7616
- const store = React47.useMemo(
7853
+ const store = React48.useMemo(
7617
7854
  () => storeProp ?? createLocalStorageAppearanceStore({ storageKey, storage, defaults }),
7618
7855
  [storeProp, storageKey, storage, defaults]
7619
7856
  );
7620
7857
  const [prefs, update] = useAppearancePrefs(store);
7621
- const [open2, setOpen] = React47.useState(false);
7622
- const anchorRef = React47.useRef(null);
7858
+ const [open2, setOpen] = React48.useState(false);
7859
+ const anchorRef = React48.useRef(null);
7623
7860
  const patch = (p) => update(p);
7624
- return /* @__PURE__ */ jsxs65(React47.Fragment, { children: [
7625
- /* @__PURE__ */ jsx74("span", { ref: anchorRef, className: ["fd-appearance-anchor", className].filter(Boolean).join(" "), style: { display: "inline-flex" }, children: /* @__PURE__ */ jsx74(
7861
+ return /* @__PURE__ */ jsxs66(React48.Fragment, { children: [
7862
+ /* @__PURE__ */ jsx75("span", { ref: anchorRef, className: ["fd-appearance-anchor", className].filter(Boolean).join(" "), style: { display: "inline-flex" }, children: /* @__PURE__ */ jsx75(
7626
7863
  IconButton,
7627
7864
  {
7628
7865
  icon: "circle-half",
@@ -7630,7 +7867,7 @@ function AppearanceMenu({ className = "", store: storeProp, storageKey, storage,
7630
7867
  onClick: () => setOpen((v) => !v)
7631
7868
  }
7632
7869
  ) }),
7633
- /* @__PURE__ */ jsx74(
7870
+ /* @__PURE__ */ jsx75(
7634
7871
  Popover,
7635
7872
  {
7636
7873
  open: open2,
@@ -7640,10 +7877,10 @@ function AppearanceMenu({ className = "", store: storeProp, storageKey, storage,
7640
7877
  padded: true,
7641
7878
  width: 260,
7642
7879
  label: "Appearance settings",
7643
- children: /* @__PURE__ */ jsxs65("div", { className: "fd-stack", style: { display: "flex", flexDirection: "column", gap: 16 }, children: [
7644
- /* @__PURE__ */ jsxs65("div", { style: { display: "flex", flexDirection: "column", gap: 6 }, children: [
7645
- /* @__PURE__ */ jsx74("span", { className: "fd-field-label", children: "Theme" }),
7646
- /* @__PURE__ */ jsx74(
7880
+ children: /* @__PURE__ */ jsxs66("div", { className: "fd-stack", style: { display: "flex", flexDirection: "column", gap: 16 }, children: [
7881
+ /* @__PURE__ */ jsxs66("div", { style: { display: "flex", flexDirection: "column", gap: 6 }, children: [
7882
+ /* @__PURE__ */ jsx75("span", { className: "fd-field-label", children: "Theme" }),
7883
+ /* @__PURE__ */ jsx75(
7647
7884
  SegmentedControl,
7648
7885
  {
7649
7886
  options: THEME_OPTIONS,
@@ -7653,9 +7890,9 @@ function AppearanceMenu({ className = "", store: storeProp, storageKey, storage,
7653
7890
  }
7654
7891
  )
7655
7892
  ] }),
7656
- /* @__PURE__ */ jsxs65("div", { style: { display: "flex", flexDirection: "column", gap: 6 }, children: [
7657
- /* @__PURE__ */ jsx74("span", { className: "fd-field-label", children: "Text size" }),
7658
- /* @__PURE__ */ jsx74(
7893
+ /* @__PURE__ */ jsxs66("div", { style: { display: "flex", flexDirection: "column", gap: 6 }, children: [
7894
+ /* @__PURE__ */ jsx75("span", { className: "fd-field-label", children: "Text size" }),
7895
+ /* @__PURE__ */ jsx75(
7659
7896
  SegmentedControl,
7660
7897
  {
7661
7898
  options: TEXT_SCALE_OPTIONS,
@@ -7665,7 +7902,7 @@ function AppearanceMenu({ className = "", store: storeProp, storageKey, storage,
7665
7902
  }
7666
7903
  )
7667
7904
  ] }),
7668
- /* @__PURE__ */ jsx74(
7905
+ /* @__PURE__ */ jsx75(
7669
7906
  Switch,
7670
7907
  {
7671
7908
  label: "High contrast",
@@ -7674,7 +7911,7 @@ function AppearanceMenu({ className = "", store: storeProp, storageKey, storage,
7674
7911
  onChange: (e) => patch({ highContrast: e.target.checked })
7675
7912
  }
7676
7913
  ),
7677
- /* @__PURE__ */ jsx74(
7914
+ /* @__PURE__ */ jsx75(
7678
7915
  Switch,
7679
7916
  {
7680
7917
  label: "Reduce motion",
@@ -7690,14 +7927,14 @@ function AppearanceMenu({ className = "", store: storeProp, storageKey, storage,
7690
7927
  }
7691
7928
 
7692
7929
  // src/components/platform/ApiSpecBrowser.tsx
7693
- import * as React48 from "react";
7694
- import { jsx as jsx75, jsxs as jsxs66 } from "react/jsx-runtime";
7930
+ import * as React49 from "react";
7931
+ import { jsx as jsx76, jsxs as jsxs67 } from "react/jsx-runtime";
7695
7932
  var METHOD_TONE = { GET: "success", POST: "info", PATCH: "warning", PUT: "warning", DELETE: "danger" };
7696
7933
  function Json({ obj }) {
7697
- return /* @__PURE__ */ jsx75("pre", { className: "fd-json", children: JSON.stringify(obj, null, 2) });
7934
+ return /* @__PURE__ */ jsx76("pre", { className: "fd-json", children: JSON.stringify(obj, null, 2) });
7698
7935
  }
7699
7936
  function Endpoint({ s, onRequest }) {
7700
- const [tried, setTried] = React48.useState(null);
7937
+ const [tried, setTried] = React49.useState(null);
7701
7938
  const run = async () => {
7702
7939
  setTried("busy");
7703
7940
  const t0 = (window.performance || Date).now();
@@ -7708,50 +7945,50 @@ function Endpoint({ s, onRequest }) {
7708
7945
  setTried({ ms: Math.round((window.performance || Date).now() - t0), error: String(e && e.message || e) });
7709
7946
  }
7710
7947
  };
7711
- return /* @__PURE__ */ jsx75(Card, { elevation: "flat", padded: false, children: /* @__PURE__ */ jsxs66("div", { className: "fd-stack", style: { gap: 0 }, children: [
7712
- /* @__PURE__ */ jsxs66("div", { className: "fd-row", style: { gap: 10, padding: "14px 18px", flexWrap: "wrap" }, children: [
7713
- /* @__PURE__ */ jsx75(Badge, { tone: METHOD_TONE[s.method] || "neutral", children: s.method }),
7714
- /* @__PURE__ */ jsx75("code", { className: "fd-mono", style: { fontSize: 12.5, fontWeight: 600, color: "var(--text)", wordBreak: "break-all" }, children: s.path }),
7715
- s.isList ? /* @__PURE__ */ jsx75(Badge, { tone: "neutral", icon: "rows", children: "Paged list" }) : null,
7716
- /* @__PURE__ */ jsx75("span", { style: { flex: 1 } }),
7717
- /* @__PURE__ */ jsxs66("span", { className: "fd-body-sm fd-muted fd-mono", children: [
7948
+ return /* @__PURE__ */ jsx76(Card, { elevation: "flat", padded: false, children: /* @__PURE__ */ jsxs67("div", { className: "fd-stack", style: { gap: 0 }, children: [
7949
+ /* @__PURE__ */ jsxs67("div", { className: "fd-row", style: { gap: 10, padding: "14px 18px", flexWrap: "wrap" }, children: [
7950
+ /* @__PURE__ */ jsx76(Badge, { tone: METHOD_TONE[s.method] || "neutral", children: s.method }),
7951
+ /* @__PURE__ */ jsx76("code", { className: "fd-mono", style: { fontSize: 12.5, fontWeight: 600, color: "var(--text)", wordBreak: "break-all" }, children: s.path }),
7952
+ s.isList ? /* @__PURE__ */ jsx76(Badge, { tone: "neutral", icon: "rows", children: "Paged list" }) : null,
7953
+ /* @__PURE__ */ jsx76("span", { style: { flex: 1 } }),
7954
+ /* @__PURE__ */ jsxs67("span", { className: "fd-body-sm fd-muted fd-mono", children: [
7718
7955
  s.latency[0],
7719
7956
  "\u2013",
7720
7957
  s.latency[1],
7721
7958
  "ms"
7722
7959
  ] }),
7723
- /* @__PURE__ */ jsx75(Button, { size: "sm", variant: "secondary", icon: "play", loading: tried === "busy", onClick: run, children: "Try it" })
7960
+ /* @__PURE__ */ jsx76(Button, { size: "sm", variant: "secondary", icon: "play", loading: tried === "busy", onClick: run, children: "Try it" })
7724
7961
  ] }),
7725
- /* @__PURE__ */ jsxs66("div", { className: "fd-stack", style: { gap: 14, padding: "0 18px 16px" }, children: [
7726
- /* @__PURE__ */ jsxs66("div", { className: "fd-stack", style: { gap: 6 }, children: [
7727
- /* @__PURE__ */ jsx75("span", { className: "fd-body-sm", style: { fontWeight: 700 }, children: s.title }),
7728
- /* @__PURE__ */ jsx75("p", { className: "fd-body-sm fd-secondary", style: { margin: 0, textWrap: "pretty" }, children: s.purpose }),
7729
- s.usedBy && s.usedBy.length ? /* @__PURE__ */ jsx75("span", { className: "fd-row", style: { gap: 6, flexWrap: "wrap" }, children: s.usedBy.map((u) => /* @__PURE__ */ jsx75(Tag, { children: u }, u)) }) : null
7962
+ /* @__PURE__ */ jsxs67("div", { className: "fd-stack", style: { gap: 14, padding: "0 18px 16px" }, children: [
7963
+ /* @__PURE__ */ jsxs67("div", { className: "fd-stack", style: { gap: 6 }, children: [
7964
+ /* @__PURE__ */ jsx76("span", { className: "fd-body-sm", style: { fontWeight: 700 }, children: s.title }),
7965
+ /* @__PURE__ */ jsx76("p", { className: "fd-body-sm fd-secondary", style: { margin: 0, textWrap: "pretty" }, children: s.purpose }),
7966
+ s.usedBy && s.usedBy.length ? /* @__PURE__ */ jsx76("span", { className: "fd-row", style: { gap: 6, flexWrap: "wrap" }, children: s.usedBy.map((u) => /* @__PURE__ */ jsx76(Tag, { children: u }, u)) }) : null
7730
7967
  ] }),
7731
- /* @__PURE__ */ jsxs66("div", { style: { display: "grid", gridTemplateColumns: "repeat(auto-fit,minmax(280px,1fr))", gap: 12, alignItems: "start" }, children: [
7732
- s.request ? /* @__PURE__ */ jsxs66("div", { className: "fd-stack", style: { gap: 6 }, children: [
7733
- /* @__PURE__ */ jsx75("span", { className: "fd-overline fd-muted", children: "Request body" }),
7734
- /* @__PURE__ */ jsx75(Json, { obj: s.request })
7968
+ /* @__PURE__ */ jsxs67("div", { style: { display: "grid", gridTemplateColumns: "repeat(auto-fit,minmax(280px,1fr))", gap: 12, alignItems: "start" }, children: [
7969
+ s.request ? /* @__PURE__ */ jsxs67("div", { className: "fd-stack", style: { gap: 6 }, children: [
7970
+ /* @__PURE__ */ jsx76("span", { className: "fd-overline fd-muted", children: "Request body" }),
7971
+ /* @__PURE__ */ jsx76(Json, { obj: s.request })
7735
7972
  ] }) : null,
7736
- s.query ? /* @__PURE__ */ jsxs66("div", { className: "fd-stack", style: { gap: 6 }, children: [
7737
- /* @__PURE__ */ jsx75("span", { className: "fd-overline fd-muted", children: "Query" }),
7738
- /* @__PURE__ */ jsx75(Json, { obj: s.query })
7973
+ s.query ? /* @__PURE__ */ jsxs67("div", { className: "fd-stack", style: { gap: 6 }, children: [
7974
+ /* @__PURE__ */ jsx76("span", { className: "fd-overline fd-muted", children: "Query" }),
7975
+ /* @__PURE__ */ jsx76(Json, { obj: s.query })
7739
7976
  ] }) : null,
7740
- /* @__PURE__ */ jsxs66("div", { className: "fd-stack", style: { gap: 6 }, children: [
7741
- /* @__PURE__ */ jsx75("span", { className: "fd-overline fd-muted", children: "Response 200" }),
7742
- /* @__PURE__ */ jsx75(Json, { obj: s.response })
7977
+ /* @__PURE__ */ jsxs67("div", { className: "fd-stack", style: { gap: 6 }, children: [
7978
+ /* @__PURE__ */ jsx76("span", { className: "fd-overline fd-muted", children: "Response 200" }),
7979
+ /* @__PURE__ */ jsx76(Json, { obj: s.response })
7743
7980
  ] })
7744
7981
  ] }),
7745
- s.notes ? /* @__PURE__ */ jsx75(Flag, { tone: "info", statement: "Implementation note", cost: s.notes, actions: null }) : null,
7746
- tried && tried !== "busy" ? /* @__PURE__ */ jsxs66("div", { className: "fd-stack", style: { gap: 6 }, children: [
7747
- /* @__PURE__ */ jsxs66("span", { className: "fd-row", style: { gap: 8 }, children: [
7748
- /* @__PURE__ */ jsx75("span", { className: "fd-overline fd-muted", children: "Simulated response" }),
7749
- /* @__PURE__ */ jsxs66(Badge, { tone: tried.error ? "danger" : "success", icon: "timer", children: [
7982
+ s.notes ? /* @__PURE__ */ jsx76(Flag, { tone: "info", statement: "Implementation note", cost: s.notes, actions: null }) : null,
7983
+ tried && tried !== "busy" ? /* @__PURE__ */ jsxs67("div", { className: "fd-stack", style: { gap: 6 }, children: [
7984
+ /* @__PURE__ */ jsxs67("span", { className: "fd-row", style: { gap: 8 }, children: [
7985
+ /* @__PURE__ */ jsx76("span", { className: "fd-overline fd-muted", children: "Simulated response" }),
7986
+ /* @__PURE__ */ jsxs67(Badge, { tone: tried.error ? "danger" : "success", icon: "timer", children: [
7750
7987
  tried.ms,
7751
7988
  "ms"
7752
7989
  ] })
7753
7990
  ] }),
7754
- /* @__PURE__ */ jsx75(Json, { obj: tried.error ? { error: tried.error } : tried.data })
7991
+ /* @__PURE__ */ jsx76(Json, { obj: tried.error ? { error: tried.error } : tried.data })
7755
7992
  ] }) : null
7756
7993
  ] })
7757
7994
  ] }) });
@@ -7770,58 +8007,58 @@ function ApiSpecBrowser({
7770
8007
  className = "",
7771
8008
  ...rest
7772
8009
  }) {
7773
- const [q, setQ] = React48.useState("");
7774
- const [method, setMethod] = React48.useState(null);
7775
- const [mod, setMod] = React48.useState(null);
7776
- const [listOnly, setListOnly] = React48.useState(false);
8010
+ const [q, setQ] = React49.useState("");
8011
+ const [method, setMethod] = React49.useState(null);
8012
+ const [mod, setMod] = React49.useState(null);
8013
+ const [listOnly, setListOnly] = React49.useState(false);
7777
8014
  const activeModule = modules && modules.find((m) => m.id === mod);
7778
8015
  const hits = spec.filter((s) => (!method || s.method === method) && (!listOnly || s.isList) && (!activeModule || activeModule.endpoints.indexOf(s.id) >= 0) && (!q || (s.path + " " + s.title + " " + s.purpose + " " + (s.usedBy || []).join(" ")).toLowerCase().includes(q.toLowerCase())));
7779
8016
  const effGroups = groups && groups.length ? groups : [["All endpoints", spec.map((s) => s.id)]];
7780
8017
  const methods = [...new Set(spec.map((s) => s.method))];
7781
8018
  const listCount = spec.filter((s) => s.isList).length;
7782
- return /* @__PURE__ */ jsxs66("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 20, maxWidth: 1100 }, ...rest, children: [
7783
- /* @__PURE__ */ jsxs66("div", { className: "fd-stack", style: { gap: 10 }, children: [
7784
- kicker ? /* @__PURE__ */ jsx75("span", { className: "fd-overline fd-muted", children: kicker }) : null,
7785
- /* @__PURE__ */ jsx75("h1", { className: "fd-h1", style: { margin: 0 }, children: title }),
7786
- lede ? /* @__PURE__ */ jsx75("p", { className: "fd-body fd-secondary fd-prose", style: { margin: 0 }, children: lede }) : null
8019
+ return /* @__PURE__ */ jsxs67("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 20, maxWidth: 1100 }, ...rest, children: [
8020
+ /* @__PURE__ */ jsxs67("div", { className: "fd-stack", style: { gap: 10 }, children: [
8021
+ kicker ? /* @__PURE__ */ jsx76("span", { className: "fd-overline fd-muted", children: kicker }) : null,
8022
+ /* @__PURE__ */ jsx76("h1", { className: "fd-h1", style: { margin: 0 }, children: title }),
8023
+ lede ? /* @__PURE__ */ jsx76("p", { className: "fd-body fd-secondary fd-prose", style: { margin: 0 }, children: lede }) : null
7787
8024
  ] }),
7788
- modules && modules.length ? /* @__PURE__ */ jsxs66("div", { className: "fd-stack", style: { gap: 8 }, children: [
7789
- /* @__PURE__ */ jsx75("span", { className: "fd-overline fd-muted", children: "Filter by screen \u2014 every endpoint that screen depends on" }),
7790
- /* @__PURE__ */ jsxs66("div", { className: "fd-row", style: { gap: 8, flexWrap: "wrap" }, children: [
7791
- /* @__PURE__ */ jsxs66(Tag, { icon: "stack", selected: !mod, onClick: () => setMod(null), children: [
8025
+ modules && modules.length ? /* @__PURE__ */ jsxs67("div", { className: "fd-stack", style: { gap: 8 }, children: [
8026
+ /* @__PURE__ */ jsx76("span", { className: "fd-overline fd-muted", children: "Filter by screen \u2014 every endpoint that screen depends on" }),
8027
+ /* @__PURE__ */ jsxs67("div", { className: "fd-row", style: { gap: 8, flexWrap: "wrap" }, children: [
8028
+ /* @__PURE__ */ jsxs67(Tag, { icon: "stack", selected: !mod, onClick: () => setMod(null), children: [
7792
8029
  "All screens ",
7793
- /* @__PURE__ */ jsx75("span", { className: "fd-mono", children: spec.length })
8030
+ /* @__PURE__ */ jsx76("span", { className: "fd-mono", children: spec.length })
7794
8031
  ] }),
7795
- modules.map((m) => /* @__PURE__ */ jsxs66(Tag, { icon: m.icon, selected: mod === m.id, onClick: () => setMod(mod === m.id ? null : m.id), children: [
8032
+ modules.map((m) => /* @__PURE__ */ jsxs67(Tag, { icon: m.icon, selected: mod === m.id, onClick: () => setMod(mod === m.id ? null : m.id), children: [
7796
8033
  m.label,
7797
8034
  " ",
7798
- /* @__PURE__ */ jsx75("span", { className: "fd-mono", children: m.endpoints.length })
8035
+ /* @__PURE__ */ jsx76("span", { className: "fd-mono", children: m.endpoints.length })
7799
8036
  ] }, m.id))
7800
8037
  ] }),
7801
- activeModule ? /* @__PURE__ */ jsx75(
8038
+ activeModule ? /* @__PURE__ */ jsx76(
7802
8039
  Flag,
7803
8040
  {
7804
8041
  tone: "info",
7805
8042
  statement: activeModule.label + " calls " + activeModule.endpoints.length + " endpoints.",
7806
8043
  cost: "Integration checklist for this screen: " + activeModule.endpoints.join(", ") + ". Wire these and the screen is done.",
7807
- actions: /* @__PURE__ */ jsx75(Button, { size: "sm", variant: "ghost", icon: "x", onClick: () => setMod(null), children: "Show all screens" })
8044
+ actions: /* @__PURE__ */ jsx76(Button, { size: "sm", variant: "ghost", icon: "x", onClick: () => setMod(null), children: "Show all screens" })
7808
8045
  }
7809
8046
  ) : null
7810
8047
  ] }) : null,
7811
- sourceNote ? /* @__PURE__ */ jsx75(Flag, { tone: "info", statement: "Design-first: this page is the spec.", cost: sourceNote, actions: null }) : null,
7812
- /* @__PURE__ */ jsxs66("div", { className: "fd-row", style: { gap: 10, flexWrap: "wrap" }, children: [
7813
- /* @__PURE__ */ jsx75(Input, { icon: "magnifying-glass", placeholder: "Find an endpoint, screen, or behavior", value: q, onChange: (e) => setQ(e.target.value), style: { width: 300 } }),
7814
- methods.map((m) => /* @__PURE__ */ jsxs66(Tag, { selected: method === m, onClick: () => setMethod(method === m ? null : m), children: [
8048
+ sourceNote ? /* @__PURE__ */ jsx76(Flag, { tone: "info", statement: "Design-first: this page is the spec.", cost: sourceNote, actions: null }) : null,
8049
+ /* @__PURE__ */ jsxs67("div", { className: "fd-row", style: { gap: 10, flexWrap: "wrap" }, children: [
8050
+ /* @__PURE__ */ jsx76(Input, { icon: "magnifying-glass", placeholder: "Find an endpoint, screen, or behavior", value: q, onChange: (e) => setQ(e.target.value), style: { width: 300 } }),
8051
+ methods.map((m) => /* @__PURE__ */ jsxs67(Tag, { selected: method === m, onClick: () => setMethod(method === m ? null : m), children: [
7815
8052
  m,
7816
8053
  " ",
7817
- /* @__PURE__ */ jsx75("span", { className: "fd-mono", children: spec.filter((s) => s.method === m).length })
8054
+ /* @__PURE__ */ jsx76("span", { className: "fd-mono", children: spec.filter((s) => s.method === m).length })
7818
8055
  ] }, m)),
7819
- listCount ? /* @__PURE__ */ jsxs66(Tag, { icon: "rows", selected: listOnly, onClick: () => setListOnly(!listOnly), children: [
8056
+ listCount ? /* @__PURE__ */ jsxs67(Tag, { icon: "rows", selected: listOnly, onClick: () => setListOnly(!listOnly), children: [
7820
8057
  "Paged lists ",
7821
- /* @__PURE__ */ jsx75("span", { className: "fd-mono", children: listCount })
8058
+ /* @__PURE__ */ jsx76("span", { className: "fd-mono", children: listCount })
7822
8059
  ] }) : null,
7823
- /* @__PURE__ */ jsx75("span", { style: { flex: 1 } }),
7824
- /* @__PURE__ */ jsxs66("span", { className: "fd-body-sm fd-muted", children: [
8060
+ /* @__PURE__ */ jsx76("span", { style: { flex: 1 } }),
8061
+ /* @__PURE__ */ jsxs67("span", { className: "fd-body-sm fd-muted", children: [
7825
8062
  hits.length,
7826
8063
  " of ",
7827
8064
  spec.length,
@@ -7829,31 +8066,31 @@ function ApiSpecBrowser({
7829
8066
  listCount ? " \xB7 " + listCount + " paged" : ""
7830
8067
  ] })
7831
8068
  ] }),
7832
- hits.length === 0 ? /* @__PURE__ */ jsx75(Card, { elevation: "flat", children: /* @__PURE__ */ jsx75("p", { className: "fd-body-sm fd-muted", style: { margin: 0 }, children: "No endpoint matches those filters." }) }) : effGroups.map(([g, ids]) => {
8069
+ hits.length === 0 ? /* @__PURE__ */ jsx76(Card, { elevation: "flat", children: /* @__PURE__ */ jsx76("p", { className: "fd-body-sm fd-muted", style: { margin: 0 }, children: "No endpoint matches those filters." }) }) : effGroups.map(([g, ids]) => {
7833
8070
  const items = hits.filter((s) => ids.indexOf(s.id) >= 0);
7834
8071
  if (!items.length) return null;
7835
- return /* @__PURE__ */ jsxs66("div", { className: "fd-stack", style: { gap: 12 }, children: [
7836
- /* @__PURE__ */ jsx75("span", { className: "fd-label-lg", children: g }),
7837
- items.map((s) => /* @__PURE__ */ jsx75(Endpoint, { s, onRequest }, s.id))
8072
+ return /* @__PURE__ */ jsxs67("div", { className: "fd-stack", style: { gap: 12 }, children: [
8073
+ /* @__PURE__ */ jsx76("span", { className: "fd-label-lg", children: g }),
8074
+ items.map((s) => /* @__PURE__ */ jsx76(Endpoint, { s, onRequest }, s.id))
7838
8075
  ] }, g);
7839
8076
  }),
7840
- conventions && conventions.length ? /* @__PURE__ */ jsx75(Card, { title: "Cross-cutting conventions", elevation: "flat", children: /* @__PURE__ */ jsx75("div", { className: "fd-stack", style: { gap: 10 }, children: conventions.map(([k, v]) => /* @__PURE__ */ jsxs66("div", { className: "fd-row", style: { gap: 12, alignItems: "flex-start" }, children: [
7841
- /* @__PURE__ */ jsx75("span", { className: "fd-overline fd-muted", style: { width: 110, flex: "none", paddingTop: 2 }, children: k }),
7842
- /* @__PURE__ */ jsx75("span", { className: "fd-body-sm fd-secondary", style: { textWrap: "pretty" }, children: v })
8077
+ conventions && conventions.length ? /* @__PURE__ */ jsx76(Card, { title: "Cross-cutting conventions", elevation: "flat", children: /* @__PURE__ */ jsx76("div", { className: "fd-stack", style: { gap: 10 }, children: conventions.map(([k, v]) => /* @__PURE__ */ jsxs67("div", { className: "fd-row", style: { gap: 12, alignItems: "flex-start" }, children: [
8078
+ /* @__PURE__ */ jsx76("span", { className: "fd-overline fd-muted", style: { width: 110, flex: "none", paddingTop: 2 }, children: k }),
8079
+ /* @__PURE__ */ jsx76("span", { className: "fd-body-sm fd-secondary", style: { textWrap: "pretty" }, children: v })
7843
8080
  ] }, k)) }) }) : null,
7844
- openQuestions && openQuestions.length ? /* @__PURE__ */ jsx75(Collapsible, { icon: "list-checks", title: "Open questions before implementation", subtitle: openQuestions.length + " unresolved", children: /* @__PURE__ */ jsx75("div", { className: "fd-stack", style: { gap: 8 }, children: openQuestions.map(([id, question, why]) => /* @__PURE__ */ jsxs66("div", { className: "fd-row", style: { gap: 10, alignItems: "flex-start", padding: "8px 0", borderTop: "1px solid var(--border)" }, children: [
7845
- /* @__PURE__ */ jsx75(Badge, { tone: "danger", children: id }),
7846
- /* @__PURE__ */ jsxs66("span", { className: "fd-stack", style: { gap: 2, flex: 1 }, children: [
7847
- /* @__PURE__ */ jsx75("span", { className: "fd-body-sm", style: { fontWeight: 600 }, children: question }),
7848
- /* @__PURE__ */ jsx75("span", { className: "fd-body-sm fd-muted", children: why })
8081
+ openQuestions && openQuestions.length ? /* @__PURE__ */ jsx76(Collapsible, { icon: "list-checks", title: "Open questions before implementation", subtitle: openQuestions.length + " unresolved", children: /* @__PURE__ */ jsx76("div", { className: "fd-stack", style: { gap: 8 }, children: openQuestions.map(([id, question, why]) => /* @__PURE__ */ jsxs67("div", { className: "fd-row", style: { gap: 10, alignItems: "flex-start", padding: "8px 0", borderTop: "1px solid var(--border)" }, children: [
8082
+ /* @__PURE__ */ jsx76(Badge, { tone: "danger", children: id }),
8083
+ /* @__PURE__ */ jsxs67("span", { className: "fd-stack", style: { gap: 2, flex: 1 }, children: [
8084
+ /* @__PURE__ */ jsx76("span", { className: "fd-body-sm", style: { fontWeight: 600 }, children: question }),
8085
+ /* @__PURE__ */ jsx76("span", { className: "fd-body-sm fd-muted", children: why })
7849
8086
  ] })
7850
8087
  ] }, id)) }) }) : null
7851
8088
  ] });
7852
8089
  }
7853
8090
 
7854
8091
  // src/components/platform/ProfilePage.tsx
7855
- import * as React49 from "react";
7856
- import { jsx as jsx76, jsxs as jsxs67 } from "react/jsx-runtime";
8092
+ import * as React50 from "react";
8093
+ import { jsx as jsx77, jsxs as jsxs68 } from "react/jsx-runtime";
7857
8094
  function fieldInitialValue(field, user) {
7858
8095
  if (field.value) return field.value(user);
7859
8096
  const raw = user[field.key];
@@ -7888,21 +8125,21 @@ function ProfilePage({
7888
8125
  }) {
7889
8126
  const { user: sessionUser, roles, permissions, saveProfile: saveProfile2 } = useSessionContext();
7890
8127
  const user = userProp || sessionUser;
7891
- const initialFieldValues = React49.useMemo(() => {
8128
+ const initialFieldValues = React50.useMemo(() => {
7892
8129
  const values2 = {};
7893
8130
  for (const field of fields) values2[field.key] = fieldInitialValue(field, user);
7894
8131
  return values2;
7895
8132
  }, [user.id, fields]);
7896
- const initialNotify = React49.useMemo(() => {
8133
+ const initialNotify = React50.useMemo(() => {
7897
8134
  const values2 = {};
7898
8135
  for (const n of notifications) values2[n.key] = !!user.notify?.[n.key];
7899
8136
  return values2;
7900
8137
  }, [user.id, notifications]);
7901
- const [values, setValues] = React49.useState(initialFieldValues);
7902
- const [notify, setNotify] = React49.useState(initialNotify);
7903
- const [saving, setSaving] = React49.useState(false);
7904
- const [saved, setSaved] = React49.useState(false);
7905
- const [prevUserId, setPrevUserId] = React49.useState(user.id);
8138
+ const [values, setValues] = React50.useState(initialFieldValues);
8139
+ const [notify, setNotify] = React50.useState(initialNotify);
8140
+ const [saving, setSaving] = React50.useState(false);
8141
+ const [saved, setSaved] = React50.useState(false);
8142
+ const [prevUserId, setPrevUserId] = React50.useState(user.id);
7906
8143
  if (user.id !== prevUserId) {
7907
8144
  setPrevUserId(user.id);
7908
8145
  setValues(initialFieldValues);
@@ -7939,37 +8176,37 @@ function ProfilePage({
7939
8176
  };
7940
8177
  const displayName = fields.some((f) => f.key === "name") ? values.name || user.name : user.name;
7941
8178
  const fieldGroups = groupFields(fields);
7942
- return /* @__PURE__ */ jsxs67("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 20, maxWidth: 860 }, children: [
7943
- /* @__PURE__ */ jsxs67("div", { className: "fd-stack", style: { gap: 10 }, children: [
7944
- /* @__PURE__ */ jsx76("span", { className: "fd-overline fd-muted", children: "Account" }),
7945
- /* @__PURE__ */ jsx76("h1", { className: "fd-h1", style: { margin: 0 }, children: "Your profile" }),
7946
- /* @__PURE__ */ jsx76("p", { className: "fd-body fd-secondary fd-prose", style: { margin: 0 }, children: "How you appear to colleagues and clients across every flytedesk app, and what we send you." })
8179
+ return /* @__PURE__ */ jsxs68("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 20, maxWidth: 860 }, children: [
8180
+ /* @__PURE__ */ jsxs68("div", { className: "fd-stack", style: { gap: 10 }, children: [
8181
+ /* @__PURE__ */ jsx77("span", { className: "fd-overline fd-muted", children: "Account" }),
8182
+ /* @__PURE__ */ jsx77("h1", { className: "fd-h1", style: { margin: 0 }, children: "Your profile" }),
8183
+ /* @__PURE__ */ jsx77("p", { className: "fd-body fd-secondary fd-prose", style: { margin: 0 }, children: "How you appear to colleagues and clients across every flytedesk app, and what we send you." })
7947
8184
  ] }),
7948
- /* @__PURE__ */ jsx76(Card, { elevation: "flat", children: /* @__PURE__ */ jsxs67("div", { className: "fd-row", style: { gap: 16, flexWrap: "wrap", alignItems: "flex-start" }, children: [
7949
- /* @__PURE__ */ jsx76(Avatar, { name: displayName, size: "lg" }),
7950
- /* @__PURE__ */ jsxs67("div", { className: "fd-stack", style: { gap: 4, flex: 1, minWidth: 200 }, children: [
7951
- /* @__PURE__ */ jsx76("span", { className: "fd-h3", style: { margin: 0 }, children: displayName }),
7952
- /* @__PURE__ */ jsxs67("span", { className: "fd-row", style: { gap: 6, flexWrap: "wrap", paddingTop: 4 }, children: [
7953
- roles.map((r) => /* @__PURE__ */ jsx76(Badge, { tone: r.id === "owner" ? "success" : "neutral", children: r.name }, r.id)),
7954
- user.sso ? /* @__PURE__ */ jsx76(Badge, { tone: "info", icon: "shield-check", children: "SSO" }) : null
8185
+ /* @__PURE__ */ jsx77(Card, { elevation: "flat", children: /* @__PURE__ */ jsxs68("div", { className: "fd-row", style: { gap: 16, flexWrap: "wrap", alignItems: "flex-start" }, children: [
8186
+ /* @__PURE__ */ jsx77(Avatar, { name: displayName, size: "lg" }),
8187
+ /* @__PURE__ */ jsxs68("div", { className: "fd-stack", style: { gap: 4, flex: 1, minWidth: 200 }, children: [
8188
+ /* @__PURE__ */ jsx77("span", { className: "fd-h3", style: { margin: 0 }, children: displayName }),
8189
+ /* @__PURE__ */ jsxs68("span", { className: "fd-row", style: { gap: 6, flexWrap: "wrap", paddingTop: 4 }, children: [
8190
+ roles.map((r) => /* @__PURE__ */ jsx77(Badge, { tone: r.id === "owner" ? "success" : "neutral", children: r.name }, r.id)),
8191
+ user.sso ? /* @__PURE__ */ jsx77(Badge, { tone: "info", icon: "shield-check", children: "SSO" }) : null
7955
8192
  ] })
7956
8193
  ] }),
7957
- onChangePhoto ? /* @__PURE__ */ jsx76(Button, { variant: "secondary", size: "sm", icon: "image", onClick: onChangePhoto, children: "Change photo" }) : null
8194
+ onChangePhoto ? /* @__PURE__ */ jsx77(Button, { variant: "secondary", size: "sm", icon: "image", onClick: onChangePhoto, children: "Change photo" }) : null
7958
8195
  ] }) }),
7959
- fieldGroups.map(({ group, description, fields: groupFieldDefs }) => /* @__PURE__ */ jsx76(
8196
+ fieldGroups.map(({ group, description, fields: groupFieldDefs }) => /* @__PURE__ */ jsx77(
7960
8197
  Card,
7961
8198
  {
7962
- title: description ? /* @__PURE__ */ jsxs67("span", { className: "fd-stack", style: { gap: 2 }, children: [
7963
- /* @__PURE__ */ jsx76("span", { children: group }),
7964
- /* @__PURE__ */ jsx76("span", { className: "fd-body-sm fd-muted", style: { fontWeight: 400 }, children: description })
8199
+ title: description ? /* @__PURE__ */ jsxs68("span", { className: "fd-stack", style: { gap: 2 }, children: [
8200
+ /* @__PURE__ */ jsx77("span", { children: group }),
8201
+ /* @__PURE__ */ jsx77("span", { className: "fd-body-sm fd-muted", style: { fontWeight: 400 }, children: description })
7965
8202
  ] }) : group,
7966
8203
  elevation: "flat",
7967
- children: /* @__PURE__ */ jsxs67("div", { className: "fd-stack", style: { gap: 14 }, children: [
7968
- /* @__PURE__ */ jsx76("div", { style: { display: "grid", gridTemplateColumns: "repeat(auto-fit,minmax(220px,1fr))", gap: 14 }, children: groupFieldDefs.filter((f) => f.type !== "textarea").map((field) => {
8204
+ children: /* @__PURE__ */ jsxs68("div", { className: "fd-stack", style: { gap: 14 }, children: [
8205
+ /* @__PURE__ */ jsx77("div", { style: { display: "grid", gridTemplateColumns: "repeat(auto-fit,minmax(220px,1fr))", gap: 14 }, children: groupFieldDefs.filter((f) => f.type !== "textarea").map((field) => {
7969
8206
  const help = typeof field.help === "function" ? field.help(user) : field.help;
7970
8207
  const readOnly = field.readOnly || field.type === "readonly";
7971
8208
  if (field.type === "select") {
7972
- return /* @__PURE__ */ jsx76(
8209
+ return /* @__PURE__ */ jsx77(
7973
8210
  Select,
7974
8211
  {
7975
8212
  label: field.label,
@@ -7983,7 +8220,7 @@ function ProfilePage({
7983
8220
  field.key
7984
8221
  );
7985
8222
  }
7986
- return /* @__PURE__ */ jsx76(
8223
+ return /* @__PURE__ */ jsx77(
7987
8224
  Input,
7988
8225
  {
7989
8226
  label: field.label,
@@ -7999,7 +8236,7 @@ function ProfilePage({
7999
8236
  }) }),
8000
8237
  groupFieldDefs.filter((f) => f.type === "textarea").map((field) => {
8001
8238
  const help = typeof field.help === "function" ? field.help(user) : field.help;
8002
- return /* @__PURE__ */ jsx76(
8239
+ return /* @__PURE__ */ jsx77(
8003
8240
  Textarea,
8004
8241
  {
8005
8242
  label: field.label,
@@ -8019,16 +8256,16 @@ function ProfilePage({
8019
8256
  group
8020
8257
  )),
8021
8258
  extra,
8022
- notifications.length > 0 ? /* @__PURE__ */ jsx76(Card, { title: "Notifications", elevation: "flat", children: /* @__PURE__ */ jsx76("div", { className: "fd-stack", style: { gap: 14 }, children: notifications.map((n) => /* @__PURE__ */ jsx76(Switch, { checked: !!notify[n.key], onChange: () => toggleNotify(n.key), label: n.label, description: n.description }, n.key)) }) }) : null,
8023
- /* @__PURE__ */ jsxs67(
8259
+ notifications.length > 0 ? /* @__PURE__ */ jsx77(Card, { title: "Notifications", elevation: "flat", children: /* @__PURE__ */ jsx77("div", { className: "fd-stack", style: { gap: 14 }, children: notifications.map((n) => /* @__PURE__ */ jsx77(Switch, { checked: !!notify[n.key], onChange: () => toggleNotify(n.key), label: n.label, description: n.description }, n.key)) }) }) : null,
8260
+ /* @__PURE__ */ jsxs68(
8024
8261
  Card,
8025
8262
  {
8026
- title: /* @__PURE__ */ jsxs67("span", { className: "fd-stack", style: { gap: 2 }, children: [
8027
- /* @__PURE__ */ jsx76("span", { children: "Access" }),
8028
- /* @__PURE__ */ jsx76("span", { className: "fd-body-sm fd-muted", style: { fontWeight: 400 }, children: "What your roles grant you" })
8263
+ title: /* @__PURE__ */ jsxs68("span", { className: "fd-stack", style: { gap: 2 }, children: [
8264
+ /* @__PURE__ */ jsx77("span", { children: "Access" }),
8265
+ /* @__PURE__ */ jsx77("span", { className: "fd-body-sm fd-muted", style: { fontWeight: 400 }, children: "What your roles grant you" })
8029
8266
  ] }),
8030
8267
  elevation: "flat",
8031
- action: /* @__PURE__ */ jsx76(
8268
+ action: /* @__PURE__ */ jsx77(
8032
8269
  Button,
8033
8270
  {
8034
8271
  size: "sm",
@@ -8039,39 +8276,39 @@ function ProfilePage({
8039
8276
  }
8040
8277
  ),
8041
8278
  children: [
8042
- /* @__PURE__ */ jsxs67("div", { className: "fd-stack", style: { gap: 0 }, children: [
8043
- /* @__PURE__ */ jsx76(CardRow, { label: "Roles", children: roles.map((r) => r.name).join(", ") || "None" }),
8044
- /* @__PURE__ */ jsxs67(CardRow, { label: "Permissions", children: [
8279
+ /* @__PURE__ */ jsxs68("div", { className: "fd-stack", style: { gap: 0 }, children: [
8280
+ /* @__PURE__ */ jsx77(CardRow, { label: "Roles", children: roles.map((r) => r.name).join(", ") || "None" }),
8281
+ /* @__PURE__ */ jsxs68(CardRow, { label: "Permissions", children: [
8045
8282
  permissions.length,
8046
8283
  " granted"
8047
8284
  ] }),
8048
- /* @__PURE__ */ jsx76(CardRow, { label: "Member since", children: user.joined || "\u2014" })
8285
+ /* @__PURE__ */ jsx77(CardRow, { label: "Member since", children: user.joined || "\u2014" })
8049
8286
  ] }),
8050
- /* @__PURE__ */ jsx76("p", { className: "fd-body-sm fd-muted", style: { margin: "12px 0 0" }, children: "You cannot change your own roles \u2014 that is the point of them. An administrator manages roles from Admin \u2192 Users." })
8287
+ /* @__PURE__ */ jsx77("p", { className: "fd-body-sm fd-muted", style: { margin: "12px 0 0" }, children: "You cannot change your own roles \u2014 that is the point of them. An administrator manages roles from Admin \u2192 Users." })
8051
8288
  ]
8052
8289
  }
8053
8290
  ),
8054
- sessions ? /* @__PURE__ */ jsx76(
8291
+ sessions ? /* @__PURE__ */ jsx77(
8055
8292
  Card,
8056
8293
  {
8057
8294
  title: "Signed-in devices",
8058
8295
  elevation: "flat",
8059
- action: /* @__PURE__ */ jsx76(Button, { size: "sm", variant: "ghost", icon: "sign-out", onClick: onSignOutEverywhere, children: "Sign out everywhere" }),
8060
- children: /* @__PURE__ */ jsx76("div", { className: "fd-stack", style: { gap: 0 }, children: sessions.length === 0 ? /* @__PURE__ */ jsx76("p", { className: "fd-body-sm fd-muted", style: { margin: 0 }, children: "No other signed-in devices." }) : sessions.map((s) => /* @__PURE__ */ jsxs67("div", { className: "fd-row", style: { gap: 12, padding: "10px 0", borderTop: "1px solid var(--border)", flexWrap: "wrap" }, children: [
8061
- /* @__PURE__ */ jsx76("i", { className: "ph ph-device-mobile", style: { fontSize: 16, color: "var(--text-muted)" }, "aria-hidden": "true" }),
8062
- /* @__PURE__ */ jsxs67("span", { className: "fd-stack", style: { gap: 1, flex: 1, minWidth: 160 }, children: [
8063
- /* @__PURE__ */ jsx76("span", { className: "fd-body-sm", style: { fontWeight: 600 }, children: s.device }),
8064
- /* @__PURE__ */ jsxs67("span", { className: "fd-body-sm fd-muted", children: [
8296
+ action: /* @__PURE__ */ jsx77(Button, { size: "sm", variant: "ghost", icon: "sign-out", onClick: onSignOutEverywhere, children: "Sign out everywhere" }),
8297
+ children: /* @__PURE__ */ jsx77("div", { className: "fd-stack", style: { gap: 0 }, children: sessions.length === 0 ? /* @__PURE__ */ jsx77("p", { className: "fd-body-sm fd-muted", style: { margin: 0 }, children: "No other signed-in devices." }) : sessions.map((s) => /* @__PURE__ */ jsxs68("div", { className: "fd-row", style: { gap: 12, padding: "10px 0", borderTop: "1px solid var(--border)", flexWrap: "wrap" }, children: [
8298
+ /* @__PURE__ */ jsx77("i", { className: "ph ph-device-mobile", style: { fontSize: 16, color: "var(--text-muted)" }, "aria-hidden": "true" }),
8299
+ /* @__PURE__ */ jsxs68("span", { className: "fd-stack", style: { gap: 1, flex: 1, minWidth: 160 }, children: [
8300
+ /* @__PURE__ */ jsx77("span", { className: "fd-body-sm", style: { fontWeight: 600 }, children: s.device }),
8301
+ /* @__PURE__ */ jsxs68("span", { className: "fd-body-sm fd-muted", children: [
8065
8302
  s.where,
8066
8303
  " \xB7 ",
8067
8304
  s.when
8068
8305
  ] })
8069
8306
  ] }),
8070
- s.current ? /* @__PURE__ */ jsx76(Badge, { tone: "success", dot: true, children: "This device" }) : /* @__PURE__ */ jsx76(Button, { size: "sm", variant: "ghost", children: "Revoke" })
8307
+ s.current ? /* @__PURE__ */ jsx77(Badge, { tone: "success", dot: true, children: "This device" }) : /* @__PURE__ */ jsx77(Button, { size: "sm", variant: "ghost", children: "Revoke" })
8071
8308
  ] }, s.id)) })
8072
8309
  }
8073
8310
  ) : null,
8074
- /* @__PURE__ */ jsxs67("div", { className: "fd-row", style: {
8311
+ /* @__PURE__ */ jsxs68("div", { className: "fd-row", style: {
8075
8312
  gap: 10,
8076
8313
  flexWrap: "wrap",
8077
8314
  position: "sticky",
@@ -8082,19 +8319,19 @@ function ProfilePage({
8082
8319
  border: "1px solid var(--border)",
8083
8320
  boxShadow: "0 -4px 16px rgba(11,13,17,.06)"
8084
8321
  }, children: [
8085
- /* @__PURE__ */ jsx76("span", { className: "fd-body-sm", style: { fontWeight: 600, flex: 1 }, children: saved ? "Saved." : dirty ? "Unsaved changes" : "No pending changes" }),
8086
- /* @__PURE__ */ jsx76(Button, { size: "sm", variant: "ghost", disabled: !dirty || saving, onClick: discard, children: "Discard" }),
8087
- /* @__PURE__ */ jsx76(Button, { size: "sm", icon: "check", disabled: !dirty || !canSave, loading: saving, onClick: save, children: "Save changes" })
8322
+ /* @__PURE__ */ jsx77("span", { className: "fd-body-sm", style: { fontWeight: 600, flex: 1 }, children: saved ? "Saved." : dirty ? "Unsaved changes" : "No pending changes" }),
8323
+ /* @__PURE__ */ jsx77(Button, { size: "sm", variant: "ghost", disabled: !dirty || saving, onClick: discard, children: "Discard" }),
8324
+ /* @__PURE__ */ jsx77(Button, { size: "sm", icon: "check", disabled: !dirty || !canSave, loading: saving, onClick: save, children: "Save changes" })
8088
8325
  ] })
8089
8326
  ] });
8090
8327
  }
8091
8328
 
8092
8329
  // src/components/platform/SignInPage.tsx
8093
- import * as React50 from "react";
8094
- import { Fragment as Fragment19, jsx as jsx77, jsxs as jsxs68 } from "react/jsx-runtime";
8330
+ import * as React51 from "react";
8331
+ import { Fragment as Fragment19, jsx as jsx78, jsxs as jsxs69 } from "react/jsx-runtime";
8095
8332
  function SignInPage({ productName, onSignIn, continueAs, error }) {
8096
- const [signingIn, setSigningIn] = React50.useState(false);
8097
- const [resuming, setResuming] = React50.useState(false);
8333
+ const [signingIn, setSigningIn] = React51.useState(false);
8334
+ const [resuming, setResuming] = React51.useState(false);
8098
8335
  function handleSignIn() {
8099
8336
  setSigningIn(true);
8100
8337
  onSignIn();
@@ -8103,7 +8340,7 @@ function SignInPage({ productName, onSignIn, continueAs, error }) {
8103
8340
  setResuming(true);
8104
8341
  continueAs.onContinue().finally(() => setResuming(false));
8105
8342
  }
8106
- return /* @__PURE__ */ jsxs68(
8343
+ return /* @__PURE__ */ jsxs69(
8107
8344
  "div",
8108
8345
  {
8109
8346
  style: {
@@ -8117,7 +8354,7 @@ function SignInPage({ productName, onSignIn, continueAs, error }) {
8117
8354
  background: "radial-gradient(circle at 15% 15%, var(--blue-700) 0%, transparent 45%), radial-gradient(circle at 85% 85%, var(--blue-600) 0%, transparent 40%), linear-gradient(160deg, var(--navy) 0%, var(--blue-950) 55%, var(--blue-900) 100%)"
8118
8355
  },
8119
8356
  children: [
8120
- /* @__PURE__ */ jsx77(
8357
+ /* @__PURE__ */ jsx78(
8121
8358
  "div",
8122
8359
  {
8123
8360
  "aria-hidden": true,
@@ -8130,7 +8367,7 @@ function SignInPage({ productName, onSignIn, continueAs, error }) {
8130
8367
  }
8131
8368
  }
8132
8369
  ),
8133
- /* @__PURE__ */ jsxs68(
8370
+ /* @__PURE__ */ jsxs69(
8134
8371
  "div",
8135
8372
  {
8136
8373
  style: {
@@ -8142,8 +8379,8 @@ function SignInPage({ productName, onSignIn, continueAs, error }) {
8142
8379
  alignItems: "center"
8143
8380
  },
8144
8381
  children: [
8145
- /* @__PURE__ */ jsx77("div", { style: { marginBottom: "var(--s-32)" }, "data-theme": "dark", children: /* @__PURE__ */ jsx77(FlytedeskMark, { size: "lg" }) }),
8146
- /* @__PURE__ */ jsxs68(
8382
+ /* @__PURE__ */ jsx78("div", { style: { marginBottom: "var(--s-32)" }, "data-theme": "dark", children: /* @__PURE__ */ jsx78(FlytedeskMark, { size: "lg" }) }),
8383
+ /* @__PURE__ */ jsxs69(
8147
8384
  "div",
8148
8385
  {
8149
8386
  style: {
@@ -8153,7 +8390,7 @@ function SignInPage({ productName, onSignIn, continueAs, error }) {
8153
8390
  boxShadow: "0 24px 64px -12px rgba(2, 8, 20, 0.55), 0 2px 8px rgba(2, 8, 20, 0.3)"
8154
8391
  },
8155
8392
  children: [
8156
- /* @__PURE__ */ jsx77(
8393
+ /* @__PURE__ */ jsx78(
8157
8394
  "div",
8158
8395
  {
8159
8396
  style: {
@@ -8162,7 +8399,7 @@ function SignInPage({ productName, onSignIn, continueAs, error }) {
8162
8399
  }
8163
8400
  }
8164
8401
  ),
8165
- /* @__PURE__ */ jsx77(Card, { children: /* @__PURE__ */ jsxs68(
8402
+ /* @__PURE__ */ jsx78(Card, { children: /* @__PURE__ */ jsxs69(
8166
8403
  "div",
8167
8404
  {
8168
8405
  style: {
@@ -8174,13 +8411,13 @@ function SignInPage({ productName, onSignIn, continueAs, error }) {
8174
8411
  padding: "var(--s-8) 0"
8175
8412
  },
8176
8413
  children: [
8177
- /* @__PURE__ */ jsxs68("div", { children: [
8178
- /* @__PURE__ */ jsx77("h1", { className: "fd-h3", style: { color: "var(--navy)" }, children: productName }),
8179
- /* @__PURE__ */ jsx77("p", { className: "fd-body-sm fd-muted", style: { marginTop: "var(--s-4)" }, children: continueAs ? "Your session timed out, but you're likely still signed in" : "Sign in with your flytedesk workspace account" })
8414
+ /* @__PURE__ */ jsxs69("div", { children: [
8415
+ /* @__PURE__ */ jsx78("h1", { className: "fd-h3", style: { color: "var(--navy)" }, children: productName }),
8416
+ /* @__PURE__ */ jsx78("p", { className: "fd-body-sm fd-muted", style: { marginTop: "var(--s-4)" }, children: continueAs ? "Your session timed out, but you're likely still signed in" : "Sign in with your flytedesk workspace account" })
8180
8417
  ] }),
8181
- error ? /* @__PURE__ */ jsx77("div", { role: "alert", style: { width: "100%" }, children: /* @__PURE__ */ jsx77(Banner, { tone: "danger", title: error }) }) : null,
8182
- continueAs ? /* @__PURE__ */ jsxs68(Fragment19, { children: [
8183
- /* @__PURE__ */ jsx77(
8418
+ error ? /* @__PURE__ */ jsx78("div", { role: "alert", style: { width: "100%" }, children: /* @__PURE__ */ jsx78(Banner, { tone: "danger", title: error }) }) : null,
8419
+ continueAs ? /* @__PURE__ */ jsxs69(Fragment19, { children: [
8420
+ /* @__PURE__ */ jsx78(
8184
8421
  Button,
8185
8422
  {
8186
8423
  variant: "primary",
@@ -8191,7 +8428,7 @@ function SignInPage({ productName, onSignIn, continueAs, error }) {
8191
8428
  children: resuming ? "Resuming\u2026" : `Continue as ${continueAs.name}`
8192
8429
  }
8193
8430
  ),
8194
- /* @__PURE__ */ jsx77(
8431
+ /* @__PURE__ */ jsx78(
8195
8432
  "button",
8196
8433
  {
8197
8434
  type: "button",
@@ -8208,7 +8445,7 @@ function SignInPage({ productName, onSignIn, continueAs, error }) {
8208
8445
  children: "Not you? Sign in with flytedesk ID"
8209
8446
  }
8210
8447
  )
8211
- ] }) : /* @__PURE__ */ jsx77(
8448
+ ] }) : /* @__PURE__ */ jsx78(
8212
8449
  Button,
8213
8450
  {
8214
8451
  variant: "primary",
@@ -8216,7 +8453,7 @@ function SignInPage({ productName, onSignIn, continueAs, error }) {
8216
8453
  loading: signingIn,
8217
8454
  disabled: signingIn,
8218
8455
  onClick: handleSignIn,
8219
- children: /* @__PURE__ */ jsxs68(
8456
+ children: /* @__PURE__ */ jsxs69(
8220
8457
  "span",
8221
8458
  {
8222
8459
  style: {
@@ -8228,14 +8465,14 @@ function SignInPage({ productName, onSignIn, continueAs, error }) {
8228
8465
  flexWrap: "nowrap"
8229
8466
  },
8230
8467
  children: [
8231
- /* @__PURE__ */ jsx77(GoogleGlyph, {}),
8232
- /* @__PURE__ */ jsx77("span", { children: signingIn ? "Signing in\u2026" : "Sign in with flytedesk ID" })
8468
+ /* @__PURE__ */ jsx78(GoogleGlyph, {}),
8469
+ /* @__PURE__ */ jsx78("span", { children: signingIn ? "Signing in\u2026" : "Sign in with flytedesk ID" })
8233
8470
  ]
8234
8471
  }
8235
8472
  )
8236
8473
  }
8237
8474
  ),
8238
- /* @__PURE__ */ jsx77("p", { className: "fd-body-sm fd-muted", style: { fontSize: "12px" }, children: "One account, every flytedesk app." })
8475
+ /* @__PURE__ */ jsx78("p", { className: "fd-body-sm fd-muted", style: { fontSize: "12px" }, children: "One account, every flytedesk app." })
8239
8476
  ]
8240
8477
  }
8241
8478
  ) })
@@ -8250,29 +8487,29 @@ function SignInPage({ productName, onSignIn, continueAs, error }) {
8250
8487
  );
8251
8488
  }
8252
8489
  function GoogleGlyph() {
8253
- return /* @__PURE__ */ jsxs68("svg", { width: "18", height: "18", viewBox: "0 0 18 18", "aria-hidden": true, children: [
8254
- /* @__PURE__ */ jsx77(
8490
+ return /* @__PURE__ */ jsxs69("svg", { width: "18", height: "18", viewBox: "0 0 18 18", "aria-hidden": true, children: [
8491
+ /* @__PURE__ */ jsx78(
8255
8492
  "path",
8256
8493
  {
8257
8494
  fill: "#4285F4",
8258
8495
  d: "M17.64 9.2c0-.64-.06-1.25-.16-1.84H9v3.48h4.84a4.14 4.14 0 0 1-1.8 2.72v2.26h2.92c1.7-1.57 2.68-3.87 2.68-6.62Z"
8259
8496
  }
8260
8497
  ),
8261
- /* @__PURE__ */ jsx77(
8498
+ /* @__PURE__ */ jsx78(
8262
8499
  "path",
8263
8500
  {
8264
8501
  fill: "#34A853",
8265
8502
  d: "M9 18c2.43 0 4.47-.8 5.96-2.18l-2.92-2.26c-.81.54-1.84.87-3.04.87-2.34 0-4.32-1.58-5.03-3.7H.96v2.33A9 9 0 0 0 9 18Z"
8266
8503
  }
8267
8504
  ),
8268
- /* @__PURE__ */ jsx77(
8505
+ /* @__PURE__ */ jsx78(
8269
8506
  "path",
8270
8507
  {
8271
8508
  fill: "#FBBC05",
8272
8509
  d: "M3.97 10.73A5.4 5.4 0 0 1 3.68 9c0-.6.1-1.19.29-1.73V4.94H.96A9 9 0 0 0 0 9c0 1.45.35 2.83.96 4.06l3.01-2.33Z"
8273
8510
  }
8274
8511
  ),
8275
- /* @__PURE__ */ jsx77(
8512
+ /* @__PURE__ */ jsx78(
8276
8513
  "path",
8277
8514
  {
8278
8515
  fill: "#EA4335",
@@ -8283,10 +8520,10 @@ function GoogleGlyph() {
8283
8520
  }
8284
8521
 
8285
8522
  // src/components/platform/RoadmapTimeline.tsx
8286
- import * as React53 from "react";
8523
+ import * as React54 from "react";
8287
8524
 
8288
8525
  // src/kits/session.ts
8289
- import * as React51 from "react";
8526
+ import * as React52 from "react";
8290
8527
  var PERMISSION_CATALOG = [
8291
8528
  { group: "Plans", items: [
8292
8529
  { key: "plan.view", label: "View plans", detail: "Read any plan in the workspace." },
@@ -9853,8 +10090,8 @@ function roadmap(overrides) {
9853
10090
  };
9854
10091
  }
9855
10092
  function useSession() {
9856
- const [s, setS] = React51.useState(getSession);
9857
- React51.useEffect(() => subscribe(setS), []);
10093
+ const [s, setS] = React52.useState(getSession);
10094
+ React52.useEffect(() => subscribe(setS), []);
9858
10095
  return s;
9859
10096
  }
9860
10097
  var SessionKit = {
@@ -9887,7 +10124,7 @@ var SessionKit = {
9887
10124
  };
9888
10125
  function DemoSessionProvider({ children }) {
9889
10126
  const session = useSession();
9890
- const value = React51.useMemo(
10127
+ const value = React52.useMemo(
9891
10128
  () => ({
9892
10129
  user: session.user,
9893
10130
  roles: session.roles,
@@ -9903,11 +10140,11 @@ function DemoSessionProvider({ children }) {
9903
10140
  }),
9904
10141
  [session]
9905
10142
  );
9906
- return React51.createElement(SessionProvider, { value }, children);
10143
+ return React52.createElement(SessionProvider, { value }, children);
9907
10144
  }
9908
10145
 
9909
10146
  // src/kits/runtime.ts
9910
- import * as React52 from "react";
10147
+ import * as React53 from "react";
9911
10148
  var WIRED_ENDPOINTS = [
9912
10149
  // Nothing yet. Every id below would come from a real service:
9913
10150
  // "plan.get", "placements.list", …
@@ -10078,8 +10315,8 @@ var RuntimeKit = {
10078
10315
  };
10079
10316
  RuntimeKit.declare(FEATURE_NEEDS);
10080
10317
  function useRuntimeMode() {
10081
- const [m, setM] = React52.useState(RuntimeKit.getMode());
10082
- React52.useEffect(() => RuntimeKit.subscribe(setM), []);
10318
+ const [m, setM] = React53.useState(RuntimeKit.getMode());
10319
+ React53.useEffect(() => RuntimeKit.subscribe(setM), []);
10083
10320
  return m;
10084
10321
  }
10085
10322
  function useFeatureStatus(key) {
@@ -10098,7 +10335,7 @@ var UseRuntimeMode = useRuntimeMode;
10098
10335
  var UseFeatureStatus = useFeatureStatus;
10099
10336
 
10100
10337
  // src/components/platform/RoadmapTimeline.tsx
10101
- import { jsx as jsx78, jsxs as jsxs69 } from "react/jsx-runtime";
10338
+ import { jsx as jsx79, jsxs as jsxs70 } from "react/jsx-runtime";
10102
10339
  var STATUS = {
10103
10340
  shipped: { tone: "success", icon: "check-circle", label: "Wired" },
10104
10341
  next: { tone: "warning", icon: "traffic-cone", label: "Not wired" },
@@ -10113,45 +10350,45 @@ function RoadmapCard({ item, byKey, onOpenFlag }) {
10113
10350
  const s = STATUS[item.status] || STATUS.planned;
10114
10351
  const deps = (item.dependsOn || []).map((k) => byKey[k]).filter(Boolean);
10115
10352
  const blocking = deps.filter((d) => !d.implemented);
10116
- return /* @__PURE__ */ jsx78(Card, { elevation: "flat", children: /* @__PURE__ */ jsxs69("div", { className: "fd-stack", style: { gap: 10 }, children: [
10117
- /* @__PURE__ */ jsxs69("div", { className: "fd-row", style: { gap: 8, flexWrap: "wrap" }, children: [
10118
- /* @__PURE__ */ jsx78("span", { className: "fd-body", style: { fontWeight: 700, flex: 1, minWidth: 140 }, children: item.label }),
10119
- /* @__PURE__ */ jsx78(Badge, { tone: "neutral", icon: PROJECT_ICON[item.project] || "squares-four", children: item.project }),
10120
- /* @__PURE__ */ jsx78(Badge, { tone: s.tone, icon: s.icon, children: s.label })
10353
+ return /* @__PURE__ */ jsx79(Card, { elevation: "flat", children: /* @__PURE__ */ jsxs70("div", { className: "fd-stack", style: { gap: 10 }, children: [
10354
+ /* @__PURE__ */ jsxs70("div", { className: "fd-row", style: { gap: 8, flexWrap: "wrap" }, children: [
10355
+ /* @__PURE__ */ jsx79("span", { className: "fd-body", style: { fontWeight: 700, flex: 1, minWidth: 140 }, children: item.label }),
10356
+ /* @__PURE__ */ jsx79(Badge, { tone: "neutral", icon: PROJECT_ICON[item.project] || "squares-four", children: item.project }),
10357
+ /* @__PURE__ */ jsx79(Badge, { tone: s.tone, icon: s.icon, children: s.label })
10121
10358
  ] }),
10122
- /* @__PURE__ */ jsx78("p", { className: "fd-body-sm fd-secondary", style: { margin: 0, textWrap: "pretty" }, children: item.description }),
10123
- item.backend ? /* @__PURE__ */ jsxs69("div", { className: "fd-row", style: { gap: 10, alignItems: "flex-start" }, children: [
10124
- /* @__PURE__ */ jsx78("span", { className: "fd-overline fd-muted", style: { width: 62, flex: "none", paddingTop: 2 }, children: "Backend" }),
10125
- /* @__PURE__ */ jsx78("span", { className: "fd-body-sm", style: { flex: 1, textWrap: "pretty" }, children: item.backend })
10359
+ /* @__PURE__ */ jsx79("p", { className: "fd-body-sm fd-secondary", style: { margin: 0, textWrap: "pretty" }, children: item.description }),
10360
+ item.backend ? /* @__PURE__ */ jsxs70("div", { className: "fd-row", style: { gap: 10, alignItems: "flex-start" }, children: [
10361
+ /* @__PURE__ */ jsx79("span", { className: "fd-overline fd-muted", style: { width: 62, flex: "none", paddingTop: 2 }, children: "Backend" }),
10362
+ /* @__PURE__ */ jsx79("span", { className: "fd-body-sm", style: { flex: 1, textWrap: "pretty" }, children: item.backend })
10126
10363
  ] }) : null,
10127
- /* @__PURE__ */ jsxs69("div", { className: "fd-row", style: { gap: 12, flexWrap: "wrap" }, children: [
10128
- item.effort ? /* @__PURE__ */ jsxs69("span", { className: "fd-body-sm fd-muted", children: [
10129
- /* @__PURE__ */ jsx78("i", { className: "ph ph-hourglass-medium" }),
10364
+ /* @__PURE__ */ jsxs70("div", { className: "fd-row", style: { gap: 12, flexWrap: "wrap" }, children: [
10365
+ item.effort ? /* @__PURE__ */ jsxs70("span", { className: "fd-body-sm fd-muted", children: [
10366
+ /* @__PURE__ */ jsx79("i", { className: "ph ph-hourglass-medium" }),
10130
10367
  " ",
10131
10368
  item.effort
10132
10369
  ] }) : null,
10133
- /* @__PURE__ */ jsxs69("span", { className: "fd-body-sm fd-muted", children: [
10134
- /* @__PURE__ */ jsx78("i", { className: "ph ph-user" }),
10370
+ /* @__PURE__ */ jsxs70("span", { className: "fd-body-sm fd-muted", children: [
10371
+ /* @__PURE__ */ jsx79("i", { className: "ph ph-user" }),
10135
10372
  " ",
10136
10373
  item.owner
10137
10374
  ] }),
10138
- item.screen ? /* @__PURE__ */ jsx78(Badge, { tone: "neutral", icon: "browser", children: "screen" }) : null,
10139
- /* @__PURE__ */ jsx78("span", { style: { flex: 1 } }),
10140
- /* @__PURE__ */ jsx78(
10375
+ item.screen ? /* @__PURE__ */ jsx79(Badge, { tone: "neutral", icon: "browser", children: "screen" }) : null,
10376
+ /* @__PURE__ */ jsx79("span", { style: { flex: 1 } }),
10377
+ /* @__PURE__ */ jsx79(
10141
10378
  "button",
10142
10379
  {
10143
10380
  type: "button",
10144
10381
  onClick: () => onOpenFlag && onOpenFlag(item.key),
10145
10382
  style: { all: "unset", cursor: "pointer", display: "inline-flex", alignItems: "center", gap: 5 },
10146
- children: /* @__PURE__ */ jsx78("code", { className: "fd-mono", style: { fontSize: 11, color: "var(--brand)" }, children: item.key })
10383
+ children: /* @__PURE__ */ jsx79("code", { className: "fd-mono", style: { fontSize: 11, color: "var(--brand)" }, children: item.key })
10147
10384
  }
10148
10385
  )
10149
10386
  ] }),
10150
- deps.length ? /* @__PURE__ */ jsxs69("div", { className: "fd-row", style: { gap: 6, flexWrap: "wrap", paddingTop: 6, borderTop: "1px solid var(--border)" }, children: [
10151
- /* @__PURE__ */ jsx78("span", { className: "fd-overline fd-muted", style: { paddingTop: 3 }, children: "After" }),
10152
- deps.map((d) => /* @__PURE__ */ jsx78(Tag, { icon: d.implemented ? "check" : "clock", children: d.label }, d.key))
10387
+ deps.length ? /* @__PURE__ */ jsxs70("div", { className: "fd-row", style: { gap: 6, flexWrap: "wrap", paddingTop: 6, borderTop: "1px solid var(--border)" }, children: [
10388
+ /* @__PURE__ */ jsx79("span", { className: "fd-overline fd-muted", style: { paddingTop: 3 }, children: "After" }),
10389
+ deps.map((d) => /* @__PURE__ */ jsx79(Tag, { icon: d.implemented ? "check" : "clock", children: d.label }, d.key))
10153
10390
  ] }) : null,
10154
- blocking.length && !item.implemented ? /* @__PURE__ */ jsxs69("span", { className: "fd-body-sm", style: { color: "var(--warn-text)" }, children: [
10391
+ blocking.length && !item.implemented ? /* @__PURE__ */ jsxs70("span", { className: "fd-body-sm", style: { color: "var(--warn-text)" }, children: [
10155
10392
  "Blocked until ",
10156
10393
  blocking.map((d) => d.label).join(" and "),
10157
10394
  " ",
@@ -10162,12 +10399,12 @@ function RoadmapCard({ item, byKey, onOpenFlag }) {
10162
10399
  }
10163
10400
  function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
10164
10401
  const session = SessionKit.useSession();
10165
- const [project, setProject] = React53.useState("");
10166
- const [q, setQ] = React53.useState("");
10167
- const scrollRef = React53.useRef(null);
10168
- const nowRef = React53.useRef(null);
10169
- const rm = React53.useMemo(() => SessionKit.roadmap({ isComplete: RuntimeKit.isComplete }), [session]);
10170
- const byKey = React53.useMemo(() => {
10402
+ const [project, setProject] = React54.useState("");
10403
+ const [q, setQ] = React54.useState("");
10404
+ const scrollRef = React54.useRef(null);
10405
+ const nowRef = React54.useRef(null);
10406
+ const rm = React54.useMemo(() => SessionKit.roadmap({ isComplete: RuntimeKit.isComplete }), [session]);
10407
+ const byKey = React54.useMemo(() => {
10171
10408
  const m = {};
10172
10409
  rm.items.forEach((i) => {
10173
10410
  m[i.key] = i;
@@ -10176,7 +10413,7 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
10176
10413
  }, [rm]);
10177
10414
  const items = rm.items.filter((i) => (!project || i.project === project) && (!q || (i.label + " " + i.description + " " + (i.backend || "") + " " + i.key).toLowerCase().includes(q.toLowerCase())));
10178
10415
  const projects = [...new Set(rm.items.map((i) => i.project))];
10179
- React53.useEffect(() => {
10416
+ React54.useEffect(() => {
10180
10417
  let raf1 = 0, raf2 = 0;
10181
10418
  const place = () => {
10182
10419
  const box = scrollRef.current, mark = nowRef.current;
@@ -10204,23 +10441,23 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
10204
10441
  }, 0);
10205
10442
  const nextPhase = items.find((i) => !i.implemented);
10206
10443
  let lastPhase = null;
10207
- return /* @__PURE__ */ jsxs69("div", { className: "fd-stack", style: { gap: 16, maxWidth: 1e3 }, children: [
10208
- /* @__PURE__ */ jsxs69("div", { className: "fd-stack", style: { gap: 10 }, children: [
10209
- /* @__PURE__ */ jsx78("span", { className: "fd-overline fd-muted", children: "Architecture" }),
10210
- /* @__PURE__ */ jsx78("h1", { className: "fd-h1", style: { margin: 0 }, children: title }),
10211
- /* @__PURE__ */ jsx78("p", { className: "fd-body fd-secondary fd-prose", style: { margin: 0 }, children: lede || "Every screen and feature in these tools is already designed and working against a simulated backend. This is the plan for connecting them to the real one \u2014 so the only work described here is server work." })
10444
+ return /* @__PURE__ */ jsxs70("div", { className: "fd-stack", style: { gap: 16, maxWidth: 1e3 }, children: [
10445
+ /* @__PURE__ */ jsxs70("div", { className: "fd-stack", style: { gap: 10 }, children: [
10446
+ /* @__PURE__ */ jsx79("span", { className: "fd-overline fd-muted", children: "Architecture" }),
10447
+ /* @__PURE__ */ jsx79("h1", { className: "fd-h1", style: { margin: 0 }, children: title }),
10448
+ /* @__PURE__ */ jsx79("p", { className: "fd-body fd-secondary fd-prose", style: { margin: 0 }, children: lede || "Every screen and feature in these tools is already designed and working against a simulated backend. This is the plan for connecting them to the real one \u2014 so the only work described here is server work." })
10212
10449
  ] }),
10213
- /* @__PURE__ */ jsxs69("div", { className: "fd-grid-stats is-thin", children: [
10214
- /* @__PURE__ */ jsx78(StatTile, { compact: true, label: "Wired", value: String(rm.shipped), sub: "of " + rm.items.length + " features" }),
10215
- /* @__PURE__ */ jsx78(StatTile, { compact: true, label: "Remaining", value: String(rm.remaining), sub: "backend work" }),
10216
- /* @__PURE__ */ jsx78(StatTile, { compact: true, label: "Est. effort", value: days ? days + " days" : "\u2014", sub: "sum of estimates, not calendar" }),
10217
- /* @__PURE__ */ jsx78(StatTile, { compact: true, label: "Up next", value: nextPhase ? "Phase " + nextPhase.phase : "\u2014", sub: nextPhase ? nextPhase.phaseName : "all wired" })
10450
+ /* @__PURE__ */ jsxs70("div", { className: "fd-grid-stats is-thin", children: [
10451
+ /* @__PURE__ */ jsx79(StatTile, { compact: true, label: "Wired", value: String(rm.shipped), sub: "of " + rm.items.length + " features" }),
10452
+ /* @__PURE__ */ jsx79(StatTile, { compact: true, label: "Remaining", value: String(rm.remaining), sub: "backend work" }),
10453
+ /* @__PURE__ */ jsx79(StatTile, { compact: true, label: "Est. effort", value: days ? days + " days" : "\u2014", sub: "sum of estimates, not calendar" }),
10454
+ /* @__PURE__ */ jsx79(StatTile, { compact: true, label: "Up next", value: nextPhase ? "Phase " + nextPhase.phase : "\u2014", sub: nextPhase ? nextPhase.phaseName : "all wired" })
10218
10455
  ] }),
10219
- /* @__PURE__ */ jsxs69("div", { className: "fd-row", style: { gap: 10, flexWrap: "wrap" }, children: [
10220
- /* @__PURE__ */ jsx78(Input, { icon: "magnifying-glass", placeholder: "Find a feature or a piece of backend work", value: q, onChange: (e) => setQ(e.target.value), style: { width: 300 } }),
10221
- /* @__PURE__ */ jsx78(Select, { placeholder: "All projects", value: project, onChange: (e) => setProject(e.target.value), options: projects, style: { width: 190 } }),
10222
- /* @__PURE__ */ jsx78("span", { style: { flex: 1 } }),
10223
- /* @__PURE__ */ jsx78(
10456
+ /* @__PURE__ */ jsxs70("div", { className: "fd-row", style: { gap: 10, flexWrap: "wrap" }, children: [
10457
+ /* @__PURE__ */ jsx79(Input, { icon: "magnifying-glass", placeholder: "Find a feature or a piece of backend work", value: q, onChange: (e) => setQ(e.target.value), style: { width: 300 } }),
10458
+ /* @__PURE__ */ jsx79(Select, { placeholder: "All projects", value: project, onChange: (e) => setProject(e.target.value), options: projects, style: { width: 190 } }),
10459
+ /* @__PURE__ */ jsx79("span", { style: { flex: 1 } }),
10460
+ /* @__PURE__ */ jsx79(
10224
10461
  Button,
10225
10462
  {
10226
10463
  size: "sm",
@@ -10234,7 +10471,7 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
10234
10471
  }
10235
10472
  )
10236
10473
  ] }),
10237
- /* @__PURE__ */ jsx78(
10474
+ /* @__PURE__ */ jsx79(
10238
10475
  Flag,
10239
10476
  {
10240
10477
  tone: "info",
@@ -10243,60 +10480,60 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
10243
10480
  actions: null
10244
10481
  }
10245
10482
  ),
10246
- /* @__PURE__ */ jsx78("div", { className: "fd-rm", children: /* @__PURE__ */ jsx78("div", { className: "fd-rm-scroll", ref: scrollRef, children: /* @__PURE__ */ jsxs69("div", { className: "fd-rm-track", children: [
10247
- /* @__PURE__ */ jsx78("span", { className: "fd-rm-spine", children: /* @__PURE__ */ jsx78("span", { className: "fd-rm-spine-done", style: { height: items.length ? 100 * shippedShown / items.length + "%" : "0%" } }) }),
10483
+ /* @__PURE__ */ jsx79("div", { className: "fd-rm", children: /* @__PURE__ */ jsx79("div", { className: "fd-rm-scroll", ref: scrollRef, children: /* @__PURE__ */ jsxs70("div", { className: "fd-rm-track", children: [
10484
+ /* @__PURE__ */ jsx79("span", { className: "fd-rm-spine", children: /* @__PURE__ */ jsx79("span", { className: "fd-rm-spine-done", style: { height: items.length ? 100 * shippedShown / items.length + "%" : "0%" } }) }),
10248
10485
  items.map((item, n) => {
10249
10486
  const showPhase = item.phase !== lastPhase;
10250
10487
  lastPhase = item.phase;
10251
10488
  const inPhase = items.filter((i) => i.phase === item.phase).length;
10252
10489
  const isBoundary = n === firstPending;
10253
- return /* @__PURE__ */ jsxs69(React53.Fragment, { children: [
10254
- showPhase ? /* @__PURE__ */ jsxs69("div", { className: "fd-rm-era", children: [
10255
- /* @__PURE__ */ jsxs69("span", { className: "fd-row", style: { gap: 8, flexWrap: "wrap", alignItems: "baseline" }, children: [
10256
- /* @__PURE__ */ jsx78("span", { style: { fontWeight: 700 }, children: item.phase === 0 ? "Shipped" : "Phase " + item.phase + " \u2014 " + item.phaseName }),
10257
- item.phase === 0 ? null : /* @__PURE__ */ jsxs69("span", { className: "fd-mono", style: { opacity: 0.7, fontWeight: 400 }, children: [
10490
+ return /* @__PURE__ */ jsxs70(React54.Fragment, { children: [
10491
+ showPhase ? /* @__PURE__ */ jsxs70("div", { className: "fd-rm-era", children: [
10492
+ /* @__PURE__ */ jsxs70("span", { className: "fd-row", style: { gap: 8, flexWrap: "wrap", alignItems: "baseline" }, children: [
10493
+ /* @__PURE__ */ jsx79("span", { style: { fontWeight: 700 }, children: item.phase === 0 ? "Shipped" : "Phase " + item.phase + " \u2014 " + item.phaseName }),
10494
+ item.phase === 0 ? null : /* @__PURE__ */ jsxs70("span", { className: "fd-mono", style: { opacity: 0.7, fontWeight: 400 }, children: [
10258
10495
  fmtDate(item.phaseStart),
10259
10496
  " \u2013 ",
10260
10497
  fmtDate(item.date)
10261
10498
  ] }),
10262
- /* @__PURE__ */ jsxs69("span", { style: { opacity: 0.7, fontWeight: 400 }, children: [
10499
+ /* @__PURE__ */ jsxs70("span", { style: { opacity: 0.7, fontWeight: 400 }, children: [
10263
10500
  "\xB7 ",
10264
10501
  inPhase,
10265
10502
  " feature",
10266
10503
  inPhase === 1 ? "" : "s"
10267
10504
  ] })
10268
10505
  ] }),
10269
- item.phaseWhy ? /* @__PURE__ */ jsx78("p", { className: "fd-rm-era-why", children: item.phaseWhy }) : null
10506
+ item.phaseWhy ? /* @__PURE__ */ jsx79("p", { className: "fd-rm-era-why", children: item.phaseWhy }) : null
10270
10507
  ] }) : null,
10271
- isBoundary ? /* @__PURE__ */ jsx78("div", { className: "fd-rm-now", ref: nowRef, children: /* @__PURE__ */ jsxs69("span", { className: "fd-rm-now-pill", children: [
10272
- /* @__PURE__ */ jsx78("i", { className: "ph ph-map-pin" }),
10508
+ isBoundary ? /* @__PURE__ */ jsx79("div", { className: "fd-rm-now", ref: nowRef, children: /* @__PURE__ */ jsxs70("span", { className: "fd-rm-now-pill", children: [
10509
+ /* @__PURE__ */ jsx79("i", { className: "ph ph-map-pin" }),
10273
10510
  " You are here \u2014 everything above is wired"
10274
10511
  ] }) }) : null,
10275
- /* @__PURE__ */ jsxs69("div", { className: "fd-rm-row", children: [
10276
- /* @__PURE__ */ jsx78("span", { className: "fd-rm-dot " + (item.implemented ? "is-shipped" : item.status === "next" ? "is-next" : "") }),
10277
- /* @__PURE__ */ jsxs69("div", { className: "fd-rm-date", children: [
10512
+ /* @__PURE__ */ jsxs70("div", { className: "fd-rm-row", children: [
10513
+ /* @__PURE__ */ jsx79("span", { className: "fd-rm-dot " + (item.implemented ? "is-shipped" : item.status === "next" ? "is-next" : "") }),
10514
+ /* @__PURE__ */ jsxs70("div", { className: "fd-rm-date", children: [
10278
10515
  fmtDate(item.date),
10279
- /* @__PURE__ */ jsx78("br", {}),
10280
- /* @__PURE__ */ jsx78("span", { style: { opacity: 0.75 }, children: item.implemented ? "shipped" : "phase " + item.phase })
10516
+ /* @__PURE__ */ jsx79("br", {}),
10517
+ /* @__PURE__ */ jsx79("span", { style: { opacity: 0.75 }, children: item.implemented ? "shipped" : "phase " + item.phase })
10281
10518
  ] }),
10282
- /* @__PURE__ */ jsx78(RoadmapCard, { item, byKey, onOpenFlag })
10519
+ /* @__PURE__ */ jsx79(RoadmapCard, { item, byKey, onOpenFlag })
10283
10520
  ] })
10284
10521
  ] }, item.key);
10285
10522
  }),
10286
- !items.length ? /* @__PURE__ */ jsx78("p", { className: "fd-body-sm fd-muted", children: "Nothing matches that filter." }) : null
10523
+ !items.length ? /* @__PURE__ */ jsx79("p", { className: "fd-body-sm fd-muted", children: "Nothing matches that filter." }) : null
10287
10524
  ] }) }) }),
10288
- /* @__PURE__ */ jsxs69("p", { className: "fd-body-sm fd-muted", style: { margin: 0 }, children: [
10525
+ /* @__PURE__ */ jsxs70("p", { className: "fd-body-sm fd-muted", style: { margin: 0 }, children: [
10289
10526
  "Derived from the feature-flag registry \u2014 each entry's status is its flag's ",
10290
- /* @__PURE__ */ jsx78("code", { className: "fd-mono", children: "implemented" }),
10527
+ /* @__PURE__ */ jsx79("code", { className: "fd-mono", children: "implemented" }),
10291
10528
  " field, so this page cannot drift from what the apps actually do."
10292
10529
  ] })
10293
10530
  ] });
10294
10531
  }
10295
10532
 
10296
10533
  // src/components/platform/ComingSoon.tsx
10297
- import * as React54 from "react";
10534
+ import * as React55 from "react";
10298
10535
  import { createPortal as createPortal5 } from "react-dom";
10299
- import { Fragment as Fragment21, jsx as jsx79, jsxs as jsxs70 } from "react/jsx-runtime";
10536
+ import { Fragment as Fragment21, jsx as jsx80, jsxs as jsxs71 } from "react/jsx-runtime";
10300
10537
  var BYPASS_STORE = "fd.soon.bypass.v1";
10301
10538
  function readBypassed() {
10302
10539
  try {
@@ -10312,8 +10549,8 @@ function writeBypassed(list) {
10312
10549
  }
10313
10550
  }
10314
10551
  function useBypass(key) {
10315
- const [on, setOn] = React54.useState(() => !!key && readBypassed().indexOf(key) >= 0);
10316
- React54.useEffect(() => {
10552
+ const [on, setOn] = React55.useState(() => !!key && readBypassed().indexOf(key) >= 0);
10553
+ React55.useEffect(() => {
10317
10554
  setOn(!!key && readBypassed().indexOf(key) >= 0);
10318
10555
  }, [key]);
10319
10556
  const set = (next) => {
@@ -10326,43 +10563,43 @@ function useBypass(key) {
10326
10563
  return [on, set];
10327
10564
  }
10328
10565
  function SoonCard({ label, detail, backend, eta, effort, onRoadmap, allowed, onBypass }) {
10329
- return /* @__PURE__ */ jsxs70(Fragment21, { children: [
10330
- /* @__PURE__ */ jsxs70("span", { className: "fd-soon-badge", children: [
10331
- /* @__PURE__ */ jsx79("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" }),
10566
+ return /* @__PURE__ */ jsxs71(Fragment21, { children: [
10567
+ /* @__PURE__ */ jsxs71("span", { className: "fd-soon-badge", children: [
10568
+ /* @__PURE__ */ jsx80("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" }),
10332
10569
  label
10333
10570
  ] }),
10334
- detail ? /* @__PURE__ */ jsx79("span", { className: "fd-soon-detail", children: detail }) : null,
10335
- backend ? /* @__PURE__ */ jsxs70("span", { className: "fd-soon-backend", children: [
10336
- /* @__PURE__ */ jsx79("span", { className: "fd-overline", children: "Needs" }),
10571
+ detail ? /* @__PURE__ */ jsx80("span", { className: "fd-soon-detail", children: detail }) : null,
10572
+ backend ? /* @__PURE__ */ jsxs71("span", { className: "fd-soon-backend", children: [
10573
+ /* @__PURE__ */ jsx80("span", { className: "fd-overline", children: "Needs" }),
10337
10574
  " ",
10338
10575
  backend
10339
10576
  ] }) : null,
10340
- eta || effort || onRoadmap ? /* @__PURE__ */ jsxs70("span", { className: "fd-soon-meta", children: [
10341
- eta ? /* @__PURE__ */ jsxs70("span", { children: [
10342
- /* @__PURE__ */ jsx79("i", { className: "ph ph-calendar-blank", "aria-hidden": "true" }),
10577
+ eta || effort || onRoadmap ? /* @__PURE__ */ jsxs71("span", { className: "fd-soon-meta", children: [
10578
+ eta ? /* @__PURE__ */ jsxs71("span", { children: [
10579
+ /* @__PURE__ */ jsx80("i", { className: "ph ph-calendar-blank", "aria-hidden": "true" }),
10343
10580
  " ",
10344
10581
  eta
10345
10582
  ] }) : null,
10346
- effort ? /* @__PURE__ */ jsxs70("span", { children: [
10347
- /* @__PURE__ */ jsx79("i", { className: "ph ph-hourglass-medium", "aria-hidden": "true" }),
10583
+ effort ? /* @__PURE__ */ jsxs71("span", { children: [
10584
+ /* @__PURE__ */ jsx80("i", { className: "ph ph-hourglass-medium", "aria-hidden": "true" }),
10348
10585
  " ",
10349
10586
  effort
10350
10587
  ] }) : null,
10351
- onRoadmap ? /* @__PURE__ */ jsxs70("button", { type: "button", className: "fd-soon-link", onClick: onRoadmap, children: [
10588
+ onRoadmap ? /* @__PURE__ */ jsxs71("button", { type: "button", className: "fd-soon-link", onClick: onRoadmap, children: [
10352
10589
  "See the roadmap ",
10353
- /* @__PURE__ */ jsx79("i", { className: "ph ph-arrow-right", "aria-hidden": "true" })
10590
+ /* @__PURE__ */ jsx80("i", { className: "ph ph-arrow-right", "aria-hidden": "true" })
10354
10591
  ] }) : null
10355
10592
  ] }) : null,
10356
- allowed ? /* @__PURE__ */ jsxs70("button", { type: "button", className: "fd-soon-view", onClick: onBypass, children: [
10357
- /* @__PURE__ */ jsx79("i", { className: "ph ph-eye", "aria-hidden": "true" }),
10593
+ allowed ? /* @__PURE__ */ jsxs71("button", { type: "button", className: "fd-soon-view", onClick: onBypass, children: [
10594
+ /* @__PURE__ */ jsx80("i", { className: "ph ph-eye", "aria-hidden": "true" }),
10358
10595
  " View and use it anyway"
10359
10596
  ] }) : null
10360
10597
  ] });
10361
10598
  }
10362
10599
  function useHoverCard(open2) {
10363
- const anchor = React54.useRef(null);
10364
- const [pos, setPos] = React54.useState(null);
10365
- React54.useLayoutEffect(() => {
10600
+ const anchor = React55.useRef(null);
10601
+ const [pos, setPos] = React55.useState(null);
10602
+ React55.useLayoutEffect(() => {
10366
10603
  if (!open2 || !anchor.current) {
10367
10604
  setPos(null);
10368
10605
  return;
@@ -10414,9 +10651,9 @@ function ComingSoon({
10414
10651
  const tip = [label, detail, backend ? "Needs " + backend : null, eta ? "ETA " + eta : null, effort].filter(Boolean).join(" \xB7 ");
10415
10652
  if (inline) {
10416
10653
  if (allowed && bypassed) {
10417
- return /* @__PURE__ */ jsxs70("span", { className: ["fd-soon-inline-on", className].filter(Boolean).join(" "), ...rest, children: [
10654
+ return /* @__PURE__ */ jsxs71("span", { className: ["fd-soon-inline-on", className].filter(Boolean).join(" "), ...rest, children: [
10418
10655
  children,
10419
- /* @__PURE__ */ jsx79(
10656
+ /* @__PURE__ */ jsx80(
10420
10657
  "button",
10421
10658
  {
10422
10659
  type: "button",
@@ -10424,12 +10661,12 @@ function ComingSoon({
10424
10661
  title: "Unwired \u2014 writes go to the simulated backend. " + tip + " Click to re-blur.",
10425
10662
  onClick: () => setBypassed(false),
10426
10663
  "aria-label": "Re-blur this unwired feature",
10427
- children: /* @__PURE__ */ jsx79("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" })
10664
+ children: /* @__PURE__ */ jsx80("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" })
10428
10665
  }
10429
10666
  )
10430
10667
  ] });
10431
10668
  }
10432
- return /* @__PURE__ */ jsx79(
10669
+ return /* @__PURE__ */ jsx80(
10433
10670
  InlineSoon,
10434
10671
  {
10435
10672
  label,
@@ -10449,20 +10686,20 @@ function ComingSoon({
10449
10686
  );
10450
10687
  }
10451
10688
  if (allowed && bypassed) {
10452
- return /* @__PURE__ */ jsxs70("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 14 }, ...rest, children: [
10453
- /* @__PURE__ */ jsxs70("div", { className: "fd-soon-bar", role: "status", children: [
10454
- /* @__PURE__ */ jsxs70("span", { className: "fd-soon-badge", children: [
10455
- /* @__PURE__ */ jsx79("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" }),
10689
+ return /* @__PURE__ */ jsxs71("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 14 }, ...rest, children: [
10690
+ /* @__PURE__ */ jsxs71("div", { className: "fd-soon-bar", role: "status", children: [
10691
+ /* @__PURE__ */ jsxs71("span", { className: "fd-soon-badge", children: [
10692
+ /* @__PURE__ */ jsx80("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" }),
10456
10693
  "Unwired feature \u2014 you are using it anyway"
10457
10694
  ] }),
10458
- /* @__PURE__ */ jsx79("span", { className: "fd-soon-bar-detail", children: "Every action here writes to the simulated backend, so nothing you do persists beyond this session." }),
10459
- /* @__PURE__ */ jsxs70("span", { className: "fd-soon-bar-actions", children: [
10460
- onRoadmap ? /* @__PURE__ */ jsxs70("button", { type: "button", className: "fd-soon-link", onClick: onRoadmap, children: [
10695
+ /* @__PURE__ */ jsx80("span", { className: "fd-soon-bar-detail", children: "Every action here writes to the simulated backend, so nothing you do persists beyond this session." }),
10696
+ /* @__PURE__ */ jsxs71("span", { className: "fd-soon-bar-actions", children: [
10697
+ onRoadmap ? /* @__PURE__ */ jsxs71("button", { type: "button", className: "fd-soon-link", onClick: onRoadmap, children: [
10461
10698
  "Roadmap ",
10462
- /* @__PURE__ */ jsx79("i", { className: "ph ph-arrow-right", "aria-hidden": "true" })
10699
+ /* @__PURE__ */ jsx80("i", { className: "ph ph-arrow-right", "aria-hidden": "true" })
10463
10700
  ] }) : null,
10464
- /* @__PURE__ */ jsxs70("button", { type: "button", className: "fd-soon-link", onClick: () => setBypassed(false), children: [
10465
- /* @__PURE__ */ jsx79("i", { className: "ph ph-eye-slash", "aria-hidden": "true" }),
10701
+ /* @__PURE__ */ jsxs71("button", { type: "button", className: "fd-soon-link", onClick: () => setBypassed(false), children: [
10702
+ /* @__PURE__ */ jsx80("i", { className: "ph ph-eye-slash", "aria-hidden": "true" }),
10466
10703
  " Re-blur"
10467
10704
  ] })
10468
10705
  ] })
@@ -10470,10 +10707,10 @@ function ComingSoon({
10470
10707
  children
10471
10708
  ] });
10472
10709
  }
10473
- return /* @__PURE__ */ jsxs70("div", { className: ["fd-soon", className].filter(Boolean).join(" "), style: minHeight ? { minHeight } : void 0, ...rest, children: [
10474
- /* @__PURE__ */ jsx79("div", { className: "fd-soon-under", style: { filter: "blur(" + blur + "px) saturate(.62)" }, ...{ inert: "" }, "aria-hidden": "true", children }),
10475
- /* @__PURE__ */ jsx79("div", { className: "fd-soon-veil" }),
10476
- /* @__PURE__ */ jsx79("div", { className: "fd-soon-note", role: "note", children: /* @__PURE__ */ jsx79(
10710
+ return /* @__PURE__ */ jsxs71("div", { className: ["fd-soon", className].filter(Boolean).join(" "), style: minHeight ? { minHeight } : void 0, ...rest, children: [
10711
+ /* @__PURE__ */ jsx80("div", { className: "fd-soon-under", style: { filter: "blur(" + blur + "px) saturate(.62)" }, ...{ inert: "" }, "aria-hidden": "true", children }),
10712
+ /* @__PURE__ */ jsx80("div", { className: "fd-soon-veil" }),
10713
+ /* @__PURE__ */ jsx80("div", { className: "fd-soon-note", role: "note", children: /* @__PURE__ */ jsx80(
10477
10714
  SoonCard,
10478
10715
  {
10479
10716
  label,
@@ -10489,10 +10726,10 @@ function ComingSoon({
10489
10726
  ] });
10490
10727
  }
10491
10728
  function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, onBypass, blur, tip, className, rest, children }) {
10492
- const [open2, setOpen] = React54.useState(false);
10729
+ const [open2, setOpen] = React55.useState(false);
10493
10730
  const [anchor, pos] = useHoverCard(open2);
10494
10731
  const zIndex = useOverlayLayer(open2);
10495
- const close2 = React54.useRef(null);
10732
+ const close2 = React55.useRef(null);
10496
10733
  const show = () => {
10497
10734
  if (close2.current) {
10498
10735
  clearTimeout(close2.current);
@@ -10508,10 +10745,10 @@ function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, o
10508
10745
  setOpen(false);
10509
10746
  }, 140);
10510
10747
  };
10511
- React54.useEffect(() => () => {
10748
+ React55.useEffect(() => () => {
10512
10749
  if (close2.current) clearTimeout(close2.current);
10513
10750
  }, []);
10514
- return /* @__PURE__ */ jsxs70(
10751
+ return /* @__PURE__ */ jsxs71(
10515
10752
  "span",
10516
10753
  {
10517
10754
  ref: anchor,
@@ -10522,8 +10759,8 @@ function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, o
10522
10759
  onBlur: hide,
10523
10760
  ...rest,
10524
10761
  children: [
10525
- /* @__PURE__ */ jsx79("span", { className: "fd-soon-under", style: { filter: "blur(" + Math.min(blur, 1.1) + "px) saturate(.66)" }, ...{ inert: "" }, "aria-hidden": "true", children }),
10526
- /* @__PURE__ */ jsx79(
10762
+ /* @__PURE__ */ jsx80("span", { className: "fd-soon-under", style: { filter: "blur(" + Math.min(blur, 1.1) + "px) saturate(.66)" }, ...{ inert: "" }, "aria-hidden": "true", children }),
10763
+ /* @__PURE__ */ jsx80(
10527
10764
  "button",
10528
10765
  {
10529
10766
  type: "button",
@@ -10534,11 +10771,11 @@ function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, o
10534
10771
  onFocus: show,
10535
10772
  onBlur: hide,
10536
10773
  onClick: () => open2 ? setOpen(false) : show(),
10537
- children: /* @__PURE__ */ jsx79("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" })
10774
+ children: /* @__PURE__ */ jsx80("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" })
10538
10775
  }
10539
10776
  ),
10540
10777
  open2 && pos ? createPortal5(
10541
- /* @__PURE__ */ jsx79(LayerProvider, { zIndex, children: /* @__PURE__ */ jsx79(
10778
+ /* @__PURE__ */ jsx80(LayerProvider, { zIndex, children: /* @__PURE__ */ jsx80(
10542
10779
  "div",
10543
10780
  {
10544
10781
  className: "fd-soon-note fd-soon-hovercard",
@@ -10546,7 +10783,7 @@ function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, o
10546
10783
  style: { position: "fixed", left: pos.left, top: pos.top, bottom: pos.bottom, width: pos.width, zIndex },
10547
10784
  onMouseEnter: show,
10548
10785
  onMouseLeave: hide,
10549
- children: /* @__PURE__ */ jsx79(
10786
+ children: /* @__PURE__ */ jsx80(
10550
10787
  SoonCard,
10551
10788
  {
10552
10789
  label,
@@ -10576,10 +10813,10 @@ function formatEta(iso2) {
10576
10813
  var FormatEta = formatEta;
10577
10814
 
10578
10815
  // src/components/platform/Gate.tsx
10579
- import { jsx as jsx80, jsxs as jsxs71 } from "react/jsx-runtime";
10816
+ import { jsx as jsx81, jsxs as jsxs72 } from "react/jsx-runtime";
10580
10817
  function PermissionDenied({ permission, title, detail, compact: compact3 = false, className = "", ...rest }) {
10581
10818
  const need = Array.isArray(permission) ? permission : [permission].filter(Boolean);
10582
- return /* @__PURE__ */ jsxs71(
10819
+ return /* @__PURE__ */ jsxs72(
10583
10820
  "div",
10584
10821
  {
10585
10822
  className: ["fd-stack", className].filter(Boolean).join(" "),
@@ -10595,14 +10832,14 @@ function PermissionDenied({ permission, title, detail, compact: compact3 = false
10595
10832
  },
10596
10833
  ...rest,
10597
10834
  children: [
10598
- /* @__PURE__ */ jsxs71("span", { className: "fd-row", style: { gap: 8 }, children: [
10599
- /* @__PURE__ */ jsx80("i", { className: "ph ph-lock-simple", style: { fontSize: 16, color: "var(--text-muted)" }, "aria-hidden": "true" }),
10600
- /* @__PURE__ */ jsx80("span", { className: compact3 ? "fd-label-lg" : "fd-h3", children: title || "You do not have access to this" })
10835
+ /* @__PURE__ */ jsxs72("span", { className: "fd-row", style: { gap: 8 }, children: [
10836
+ /* @__PURE__ */ jsx81("i", { className: "ph ph-lock-simple", style: { fontSize: 16, color: "var(--text-muted)" }, "aria-hidden": "true" }),
10837
+ /* @__PURE__ */ jsx81("span", { className: compact3 ? "fd-label-lg" : "fd-h3", children: title || "You do not have access to this" })
10601
10838
  ] }),
10602
- /* @__PURE__ */ jsx80("p", { className: "fd-body-sm fd-secondary", style: { margin: 0, textWrap: "pretty" }, children: detail || "Your roles do not grant this. An administrator can change that from Admin \u2192 Users." }),
10603
- need.length ? /* @__PURE__ */ jsxs71("span", { className: "fd-row", style: { gap: 6, flexWrap: "wrap" }, children: [
10604
- /* @__PURE__ */ jsx80("span", { className: "fd-overline fd-muted", children: "Requires" }),
10605
- need.map((p) => /* @__PURE__ */ jsx80("code", { className: "fd-mono", style: {
10839
+ /* @__PURE__ */ jsx81("p", { className: "fd-body-sm fd-secondary", style: { margin: 0, textWrap: "pretty" }, children: detail || "Your roles do not grant this. An administrator can change that from Admin \u2192 Users." }),
10840
+ need.length ? /* @__PURE__ */ jsxs72("span", { className: "fd-row", style: { gap: 6, flexWrap: "wrap" }, children: [
10841
+ /* @__PURE__ */ jsx81("span", { className: "fd-overline fd-muted", children: "Requires" }),
10842
+ need.map((p) => /* @__PURE__ */ jsx81("code", { className: "fd-mono", style: {
10606
10843
  fontSize: 11.5,
10607
10844
  padding: "2px 7px",
10608
10845
  borderRadius: 5,
@@ -10615,7 +10852,7 @@ function PermissionDenied({ permission, title, detail, compact: compact3 = false
10615
10852
  );
10616
10853
  }
10617
10854
  function GatePending({ compact: compact3 = false, className = "" }) {
10618
- return /* @__PURE__ */ jsxs71(
10855
+ return /* @__PURE__ */ jsxs72(
10619
10856
  "div",
10620
10857
  {
10621
10858
  className: ["fd-stack", className].filter(Boolean).join(" "),
@@ -10631,11 +10868,11 @@ function GatePending({ compact: compact3 = false, className = "" }) {
10631
10868
  textAlign: "left"
10632
10869
  },
10633
10870
  children: [
10634
- /* @__PURE__ */ jsxs71("span", { className: "fd-row", style: { gap: 8 }, children: [
10635
- /* @__PURE__ */ jsx80("i", { className: "ph ph-arrows-clockwise", style: { fontSize: 16, color: "var(--text-muted)" }, "aria-hidden": "true" }),
10636
- /* @__PURE__ */ jsx80("span", { className: compact3 ? "fd-label-lg" : "fd-h3", children: "Reconnecting\u2026" })
10871
+ /* @__PURE__ */ jsxs72("span", { className: "fd-row", style: { gap: 8 }, children: [
10872
+ /* @__PURE__ */ jsx81("i", { className: "ph ph-arrows-clockwise", style: { fontSize: 16, color: "var(--text-muted)" }, "aria-hidden": "true" }),
10873
+ /* @__PURE__ */ jsx81("span", { className: compact3 ? "fd-label-lg" : "fd-h3", children: "Reconnecting\u2026" })
10637
10874
  ] }),
10638
- /* @__PURE__ */ jsx80("p", { className: "fd-body-sm fd-secondary", style: { margin: 0, textWrap: "pretty" }, children: "Your access can't be verified right now. This will resolve on its own once the connection is back." })
10875
+ /* @__PURE__ */ jsx81("p", { className: "fd-body-sm fd-secondary", style: { margin: 0, textWrap: "pretty" }, children: "Your access can't be verified right now. This will resolve on its own once the connection is back." })
10639
10876
  ]
10640
10877
  }
10641
10878
  );
@@ -10645,7 +10882,7 @@ function Gate({ perm, anyOf, role, silent = false, fallback, pendingFallback, co
10645
10882
  if (pending) {
10646
10883
  if (pendingFallback !== void 0) return pendingFallback;
10647
10884
  if (silent) return null;
10648
- return /* @__PURE__ */ jsx80(GatePending, { compact: compact3 });
10885
+ return /* @__PURE__ */ jsx81(GatePending, { compact: compact3 });
10649
10886
  }
10650
10887
  let ok = true;
10651
10888
  if (perm) ok = ok && can2(perm);
@@ -10654,7 +10891,7 @@ function Gate({ perm, anyOf, role, silent = false, fallback, pendingFallback, co
10654
10891
  if (ok) return children;
10655
10892
  if (fallback !== void 0) return fallback;
10656
10893
  if (silent) return null;
10657
- return /* @__PURE__ */ jsx80(PermissionDenied, { permission: perm || anyOf, compact: compact3 });
10894
+ return /* @__PURE__ */ jsx81(PermissionDenied, { permission: perm || anyOf, compact: compact3 });
10658
10895
  }
10659
10896
  function FeatureGate({
10660
10897
  flag,
@@ -10677,7 +10914,7 @@ function FeatureGate({
10677
10914
  const f = SessionKit.findFlag(flag) || {};
10678
10915
  const missing = rt.missing || [];
10679
10916
  const canBypass = pending ? false : bypassPerm === null ? false : !bypassPerm || can2(bypassPerm);
10680
- return /* @__PURE__ */ jsx80(
10917
+ return /* @__PURE__ */ jsx81(
10681
10918
  ComingSoon,
10682
10919
  {
10683
10920
  label: label || (variant === "inline" ? f.label || "Not wired yet" : "Designed \u2014 backend not wired yet"),
@@ -10698,22 +10935,22 @@ function FeatureGate({
10698
10935
  function PermissionHint({ perm, children }) {
10699
10936
  const { can: can2, pending } = useSessionContext();
10700
10937
  if (pending) {
10701
- return /* @__PURE__ */ jsx80("span", { title: "Access can't be verified right now", style: { display: "inline-flex", opacity: 0.45, cursor: "not-allowed" }, "aria-disabled": "true", children: /* @__PURE__ */ jsx80("span", { style: { pointerEvents: "none" }, children }) });
10938
+ return /* @__PURE__ */ jsx81("span", { title: "Access can't be verified right now", style: { display: "inline-flex", opacity: 0.45, cursor: "not-allowed" }, "aria-disabled": "true", children: /* @__PURE__ */ jsx81("span", { style: { pointerEvents: "none" }, children }) });
10702
10939
  }
10703
10940
  if (can2(perm)) return children;
10704
- return /* @__PURE__ */ jsx80(
10941
+ return /* @__PURE__ */ jsx81(
10705
10942
  "span",
10706
10943
  {
10707
10944
  title: "Requires " + (Array.isArray(perm) ? perm.join(", ") : perm),
10708
10945
  style: { display: "inline-flex", opacity: 0.45, cursor: "not-allowed" },
10709
10946
  "aria-disabled": "true",
10710
- children: /* @__PURE__ */ jsx80("span", { style: { pointerEvents: "none" }, children })
10947
+ children: /* @__PURE__ */ jsx81("span", { style: { pointerEvents: "none" }, children })
10711
10948
  }
10712
10949
  );
10713
10950
  }
10714
10951
 
10715
10952
  // src/components/platform/ModeSwitch.tsx
10716
- import { Fragment as Fragment22, jsx as jsx81, jsxs as jsxs72 } from "react/jsx-runtime";
10953
+ import { Fragment as Fragment22, jsx as jsx82, jsxs as jsxs73 } from "react/jsx-runtime";
10717
10954
  function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog, onOpenSpec, summary }) {
10718
10955
  const mode2 = useRuntimeMode();
10719
10956
  const panel = useInlinePanel();
@@ -10725,8 +10962,8 @@ function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog
10725
10962
  RuntimeKit.setMode(next);
10726
10963
  setOpen(false);
10727
10964
  };
10728
- return /* @__PURE__ */ jsxs72("span", { style: { position: "relative", display: "inline-flex" }, ref, children: [
10729
- /* @__PURE__ */ jsxs72(
10965
+ return /* @__PURE__ */ jsxs73("span", { style: { position: "relative", display: "inline-flex" }, ref, children: [
10966
+ /* @__PURE__ */ jsxs73(
10730
10967
  "button",
10731
10968
  {
10732
10969
  type: "button",
@@ -10736,29 +10973,29 @@ function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog
10736
10973
  title: test ? "Test mode \u2014 every response is simulated. Click to inspect requests or return to live mode." : "Live mode \u2014 incomplete features are shown under construction. Click for test mode.",
10737
10974
  className: "fd-mode-btn" + (test ? " is-test" : "") + (open2 ? " is-open" : ""),
10738
10975
  children: [
10739
- /* @__PURE__ */ jsx81("i", { className: "ph " + (test ? "ph-flask" : "ph-lightning"), style: { fontSize: 17 } }),
10740
- test && requestCount ? /* @__PURE__ */ jsx81("span", { className: "fd-mono fd-mode-count", children: requestCount > 99 ? "99+" : requestCount }, requestCount) : null
10976
+ /* @__PURE__ */ jsx82("i", { className: "ph " + (test ? "ph-flask" : "ph-lightning"), style: { fontSize: 17 } }),
10977
+ test && requestCount ? /* @__PURE__ */ jsx82("span", { className: "fd-mono fd-mode-count", children: requestCount > 99 ? "99+" : requestCount }, requestCount) : null
10741
10978
  ]
10742
10979
  }
10743
10980
  ),
10744
- open2 ? /* @__PURE__ */ jsx81(InlinePanelLayers, { panel, children: /* @__PURE__ */ jsxs72("span", { className: "fd-view-enter fd-mode-pop", style: { zIndex }, children: [
10745
- /* @__PURE__ */ jsxs72("span", { className: "fd-row", style: { gap: 10, padding: "12px 14px", borderBottom: "1px solid var(--border)" }, children: [
10746
- /* @__PURE__ */ jsxs72("span", { className: "fd-badge " + (test ? "fd-badge-warning" : "fd-badge-neutral"), children: [
10747
- /* @__PURE__ */ jsx81("i", { className: "ph " + (test ? "ph-flask" : "ph-lightning"), "aria-hidden": "true" }),
10981
+ open2 ? /* @__PURE__ */ jsx82(InlinePanelLayers, { panel, children: /* @__PURE__ */ jsxs73("span", { className: "fd-view-enter fd-mode-pop", style: { zIndex }, children: [
10982
+ /* @__PURE__ */ jsxs73("span", { className: "fd-row", style: { gap: 10, padding: "12px 14px", borderBottom: "1px solid var(--border)" }, children: [
10983
+ /* @__PURE__ */ jsxs73("span", { className: "fd-badge " + (test ? "fd-badge-warning" : "fd-badge-neutral"), children: [
10984
+ /* @__PURE__ */ jsx82("i", { className: "ph " + (test ? "ph-flask" : "ph-lightning"), "aria-hidden": "true" }),
10748
10985
  test ? "Test mode" : "Live mode"
10749
10986
  ] }),
10750
- test ? /* @__PURE__ */ jsxs72("span", { className: "fd-body-sm fd-muted fd-mono", children: [
10987
+ test ? /* @__PURE__ */ jsxs73("span", { className: "fd-body-sm fd-muted fd-mono", children: [
10751
10988
  requestCount,
10752
10989
  " simulated request",
10753
10990
  requestCount === 1 ? "" : "s"
10754
10991
  ] }) : null,
10755
- /* @__PURE__ */ jsx81("span", { style: { flex: 1 } }),
10756
- test && onClearLog ? /* @__PURE__ */ jsx81("button", { type: "button", className: "fd-soon-link", onClick: onClearLog, children: "Clear" }) : null
10992
+ /* @__PURE__ */ jsx82("span", { style: { flex: 1 } }),
10993
+ test && onClearLog ? /* @__PURE__ */ jsx82("button", { type: "button", className: "fd-soon-link", onClick: onClearLog, children: "Clear" }) : null
10757
10994
  ] }),
10758
- /* @__PURE__ */ jsxs72("span", { style: { display: "block", padding: "12px 14px", borderBottom: "1px solid var(--border)" }, children: [
10759
- /* @__PURE__ */ jsx81("span", { className: "fd-body-sm fd-secondary", style: { display: "block", textWrap: "pretty" }, children: test ? "Every feature is usable and nothing is obstructed, but no response comes from a real service \u2014 nothing you do here persists. Use this to review and demo the design." : "This is what a user would see today. " + s.incomplete + " of " + s.total + " features depend on backend work that is not wired yet, so they render under construction." }),
10760
- /* @__PURE__ */ jsxs72("span", { className: "fd-row", style: { gap: 8, marginTop: 10, flexWrap: "wrap" }, children: [
10761
- /* @__PURE__ */ jsxs72("span", { className: "fd-body-sm fd-muted fd-mono", children: [
10995
+ /* @__PURE__ */ jsxs73("span", { style: { display: "block", padding: "12px 14px", borderBottom: "1px solid var(--border)" }, children: [
10996
+ /* @__PURE__ */ jsx82("span", { className: "fd-body-sm fd-secondary", style: { display: "block", textWrap: "pretty" }, children: test ? "Every feature is usable and nothing is obstructed, but no response comes from a real service \u2014 nothing you do here persists. Use this to review and demo the design." : "This is what a user would see today. " + s.incomplete + " of " + s.total + " features depend on backend work that is not wired yet, so they render under construction." }),
10997
+ /* @__PURE__ */ jsxs73("span", { className: "fd-row", style: { gap: 8, marginTop: 10, flexWrap: "wrap" }, children: [
10998
+ /* @__PURE__ */ jsxs73("span", { className: "fd-body-sm fd-muted fd-mono", children: [
10762
10999
  s.endpointsWired,
10763
11000
  " endpoint",
10764
11001
  s.endpointsWired === 1 ? "" : "s",
@@ -10768,58 +11005,58 @@ function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog
10768
11005
  s.total,
10769
11006
  " features complete"
10770
11007
  ] }),
10771
- onOpenSpec ? /* @__PURE__ */ jsxs72(Fragment22, { children: [
10772
- /* @__PURE__ */ jsx81("span", { style: { flex: 1 } }),
10773
- /* @__PURE__ */ jsxs72("button", { type: "button", className: "fd-soon-link", onClick: () => {
11008
+ onOpenSpec ? /* @__PURE__ */ jsxs73(Fragment22, { children: [
11009
+ /* @__PURE__ */ jsx82("span", { style: { flex: 1 } }),
11010
+ /* @__PURE__ */ jsxs73("button", { type: "button", className: "fd-soon-link", onClick: () => {
10774
11011
  setOpen(false);
10775
11012
  onOpenSpec();
10776
11013
  }, children: [
10777
11014
  "API spec ",
10778
- /* @__PURE__ */ jsx81("i", { className: "ph ph-arrow-right", "aria-hidden": "true" })
11015
+ /* @__PURE__ */ jsx82("i", { className: "ph ph-arrow-right", "aria-hidden": "true" })
10779
11016
  ] })
10780
11017
  ] }) : null
10781
11018
  ] })
10782
11019
  ] }),
10783
- /* @__PURE__ */ jsxs72("span", { className: "fd-mode-choice", children: [
10784
- /* @__PURE__ */ jsxs72("button", { type: "button", className: "fd-mode-opt" + (!test ? " is-on" : ""), onClick: () => go("live"), children: [
10785
- /* @__PURE__ */ jsx81("i", { className: "ph ph-lightning", "aria-hidden": "true" }),
10786
- /* @__PURE__ */ jsxs72("span", { className: "fd-mode-opt-text", children: [
10787
- /* @__PURE__ */ jsx81("span", { className: "fd-mode-opt-title", children: "Live mode" }),
10788
- /* @__PURE__ */ jsx81("span", { className: "fd-mode-opt-desc", children: "Incomplete features under construction" })
11020
+ /* @__PURE__ */ jsxs73("span", { className: "fd-mode-choice", children: [
11021
+ /* @__PURE__ */ jsxs73("button", { type: "button", className: "fd-mode-opt" + (!test ? " is-on" : ""), onClick: () => go("live"), children: [
11022
+ /* @__PURE__ */ jsx82("i", { className: "ph ph-lightning", "aria-hidden": "true" }),
11023
+ /* @__PURE__ */ jsxs73("span", { className: "fd-mode-opt-text", children: [
11024
+ /* @__PURE__ */ jsx82("span", { className: "fd-mode-opt-title", children: "Live mode" }),
11025
+ /* @__PURE__ */ jsx82("span", { className: "fd-mode-opt-desc", children: "Incomplete features under construction" })
10789
11026
  ] }),
10790
- !test ? /* @__PURE__ */ jsx81("i", { className: "ph ph-check", "aria-hidden": "true" }) : null
11027
+ !test ? /* @__PURE__ */ jsx82("i", { className: "ph ph-check", "aria-hidden": "true" }) : null
10791
11028
  ] }),
10792
- /* @__PURE__ */ jsxs72("button", { type: "button", className: "fd-mode-opt" + (test ? " is-on" : ""), onClick: () => go("test"), children: [
10793
- /* @__PURE__ */ jsx81("i", { className: "ph ph-flask", "aria-hidden": "true" }),
10794
- /* @__PURE__ */ jsxs72("span", { className: "fd-mode-opt-text", children: [
10795
- /* @__PURE__ */ jsx81("span", { className: "fd-mode-opt-title", children: "Test mode" }),
10796
- /* @__PURE__ */ jsx81("span", { className: "fd-mode-opt-desc", children: "Everything usable, all data simulated" })
11029
+ /* @__PURE__ */ jsxs73("button", { type: "button", className: "fd-mode-opt" + (test ? " is-on" : ""), onClick: () => go("test"), children: [
11030
+ /* @__PURE__ */ jsx82("i", { className: "ph ph-flask", "aria-hidden": "true" }),
11031
+ /* @__PURE__ */ jsxs73("span", { className: "fd-mode-opt-text", children: [
11032
+ /* @__PURE__ */ jsx82("span", { className: "fd-mode-opt-title", children: "Test mode" }),
11033
+ /* @__PURE__ */ jsx82("span", { className: "fd-mode-opt-desc", children: "Everything usable, all data simulated" })
10797
11034
  ] }),
10798
- test ? /* @__PURE__ */ jsx81("i", { className: "ph ph-check", "aria-hidden": "true" }) : null
11035
+ test ? /* @__PURE__ */ jsx82("i", { className: "ph ph-check", "aria-hidden": "true" }) : null
10799
11036
  ] })
10800
11037
  ] }),
10801
- test && renderLog ? /* @__PURE__ */ jsx81("span", { style: { display: "block", maxHeight: 340, overflowY: "auto", borderTop: "1px solid var(--border)" }, children: renderLog() }) : null
11038
+ test && renderLog ? /* @__PURE__ */ jsx82("span", { style: { display: "block", maxHeight: 340, overflowY: "auto", borderTop: "1px solid var(--border)" }, children: renderLog() }) : null
10802
11039
  ] }) }) : null
10803
11040
  ] });
10804
11041
  }
10805
11042
  function TestModeBar({ onExit }) {
10806
11043
  const mode2 = useRuntimeMode();
10807
11044
  if (mode2 !== "test") return null;
10808
- return /* @__PURE__ */ jsxs72("div", { className: "fd-testbar", role: "status", children: [
10809
- /* @__PURE__ */ jsxs72("span", { className: "fd-badge fd-badge-warning", children: [
10810
- /* @__PURE__ */ jsx81("i", { className: "ph ph-flask", "aria-hidden": "true" }),
11045
+ return /* @__PURE__ */ jsxs73("div", { className: "fd-testbar", role: "status", children: [
11046
+ /* @__PURE__ */ jsxs73("span", { className: "fd-badge fd-badge-warning", children: [
11047
+ /* @__PURE__ */ jsx82("i", { className: "ph ph-flask", "aria-hidden": "true" }),
10811
11048
  "Test mode"
10812
11049
  ] }),
10813
- /* @__PURE__ */ jsx81("span", { className: "fd-testbar-detail", children: "Every feature is unlocked and every response is simulated \u2014 nothing here persists." }),
10814
- /* @__PURE__ */ jsxs72("button", { type: "button", className: "fd-soon-link", onClick: () => onExit ? onExit() : RuntimeKit.setMode("live"), children: [
10815
- /* @__PURE__ */ jsx81("i", { className: "ph ph-lightning", "aria-hidden": "true" }),
11050
+ /* @__PURE__ */ jsx82("span", { className: "fd-testbar-detail", children: "Every feature is unlocked and every response is simulated \u2014 nothing here persists." }),
11051
+ /* @__PURE__ */ jsxs73("button", { type: "button", className: "fd-soon-link", onClick: () => onExit ? onExit() : RuntimeKit.setMode("live"), children: [
11052
+ /* @__PURE__ */ jsx82("i", { className: "ph ph-lightning", "aria-hidden": "true" }),
10816
11053
  " Back to live mode"
10817
11054
  ] })
10818
11055
  ] });
10819
11056
  }
10820
11057
 
10821
11058
  // src/components/planner/ChannelMeta.tsx
10822
- import { jsx as jsx82, jsxs as jsxs73 } from "react/jsx-runtime";
11059
+ import { jsx as jsx83, jsxs as jsxs74 } from "react/jsx-runtime";
10823
11060
  var CHANNEL_WEIGHTS = {
10824
11061
  "OOH": 50,
10825
11062
  "DOOH": 50,
@@ -10872,9 +11109,9 @@ function ChannelTag({ channel, size = "md", showLabel = true, dot = false, weigh
10872
11109
  const m = ChannelMeta(channel);
10873
11110
  const wt = channelWeightOf(channel || "");
10874
11111
  if (dot) {
10875
- return /* @__PURE__ */ jsx82("span", { className: ["fd-chan-dot", className].filter(Boolean).join(" "), title: m.name, style: { background: m.color }, ...rest });
11112
+ return /* @__PURE__ */ jsx83("span", { className: ["fd-chan-dot", className].filter(Boolean).join(" "), title: m.name, style: { background: m.color }, ...rest });
10876
11113
  }
10877
- return /* @__PURE__ */ jsxs73(
11114
+ return /* @__PURE__ */ jsxs74(
10878
11115
  "span",
10879
11116
  {
10880
11117
  className: ["fd-chan", size === "sm" ? "fd-chan-sm" : "", className].filter(Boolean).join(" "),
@@ -10882,16 +11119,16 @@ function ChannelTag({ channel, size = "md", showLabel = true, dot = false, weigh
10882
11119
  style: { "--chan": m.color },
10883
11120
  ...rest,
10884
11121
  children: [
10885
- /* @__PURE__ */ jsx82("i", { className: "ph ph-" + m.icon, "aria-hidden": "true" }),
10886
- showLabel ? /* @__PURE__ */ jsx82("span", { className: "fd-chan-label", children: m.label }) : null,
10887
- weight ? /* @__PURE__ */ jsx82("span", { className: "fd-chan-weight", children: wt || 0 }) : null
11122
+ /* @__PURE__ */ jsx83("i", { className: "ph ph-" + m.icon, "aria-hidden": "true" }),
11123
+ showLabel ? /* @__PURE__ */ jsx83("span", { className: "fd-chan-label", children: m.label }) : null,
11124
+ weight ? /* @__PURE__ */ jsx83("span", { className: "fd-chan-weight", children: wt || 0 }) : null
10888
11125
  ]
10889
11126
  }
10890
11127
  );
10891
11128
  }
10892
11129
 
10893
11130
  // src/components/planner/SaturationDistribution.tsx
10894
- import { jsx as jsx83, jsxs as jsxs74 } from "react/jsx-runtime";
11131
+ import { jsx as jsx84, jsxs as jsxs75 } from "react/jsx-runtime";
10895
11132
  var BANDS2 = [
10896
11133
  { key: "weak", label: "Weak", n: 1, range: "< 50" },
10897
11134
  { key: "adequate", label: "Adequate", n: 2, range: "50\u2013100" },
@@ -10902,24 +11139,24 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
10902
11139
  const grouped = BANDS2.map((b) => ({ ...b, items: campuses.filter((c) => c.band === b.key) }));
10903
11140
  const tallest = Math.max(1, ...grouped.map((g) => g.items.length));
10904
11141
  const floor = BANDS2.find((b) => b.key === floorBand) || BANDS2[0];
10905
- return /* @__PURE__ */ jsxs74("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 16 }, children: [
10906
- /* @__PURE__ */ jsx83("div", { style: { display: "grid", gridTemplateColumns: "repeat(4,minmax(0,1fr))", gap: 12, alignItems: "end" }, children: grouped.map((g) => {
11142
+ return /* @__PURE__ */ jsxs75("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 16 }, children: [
11143
+ /* @__PURE__ */ jsx84("div", { style: { display: "grid", gridTemplateColumns: "repeat(4,minmax(0,1fr))", gap: 12, alignItems: "end" }, children: grouped.map((g) => {
10907
11144
  const mark = "var(--csi-" + g.n + "-mark)";
10908
11145
  const active = selectedBand === g.key;
10909
- return /* @__PURE__ */ jsxs74(
11146
+ return /* @__PURE__ */ jsxs75(
10910
11147
  "button",
10911
11148
  {
10912
11149
  type: "button",
10913
11150
  onClick: onSelectBand ? () => onSelectBand(active ? null : g.key) : void 0,
10914
11151
  style: { display: "flex", flexDirection: "column", justifyContent: "flex-end", gap: 10, padding: 12, border: "1px solid " + (active ? "var(--border-strong)" : "var(--border)"), borderRadius: "var(--r-lg)", background: active ? "var(--surface-2)" : "var(--surface)", cursor: onSelectBand ? "pointer" : "default", textAlign: "left", minHeight: 190, minWidth: 0, transition: "background var(--dur-fast) var(--ease),border-color var(--dur-fast) var(--ease)" },
10915
11152
  children: [
10916
- /* @__PURE__ */ jsx83("span", { style: { display: "flex", flexDirection: "column-reverse", gap: 4, minHeight: tallest * 24, minWidth: 0 }, children: loading ? Array.from({ length: 3 }).map((_, i) => /* @__PURE__ */ jsx83("span", { className: "fd-skel", style: { height: 16, borderRadius: 4 } }, i)) : g.items.map((c) => (
11153
+ /* @__PURE__ */ jsx84("span", { style: { display: "flex", flexDirection: "column-reverse", gap: 4, minHeight: tallest * 24, minWidth: 0 }, children: loading ? Array.from({ length: 3 }).map((_, i) => /* @__PURE__ */ jsx84("span", { className: "fd-skel", style: { height: 16, borderRadius: 4 } }, i)) : g.items.map((c) => (
10917
11154
  // `overflow: hidden` + `white-space: nowrap` only clips once the span
10918
11155
  // actually HAS a bounded width to clip against (see the grid/flex
10919
11156
  // `minWidth: 0` chain above) — `textOverflow: ellipsis` then makes
10920
11157
  // that clip readable instead of a hard cut mid-letter; the full name
10921
11158
  // is still one hover away via `title`.
10922
- /* @__PURE__ */ jsx83(
11159
+ /* @__PURE__ */ jsx84(
10923
11160
  "span",
10924
11161
  {
10925
11162
  title: c.name + " \xB7 " + c.crp,
@@ -10929,13 +11166,13 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
10929
11166
  c.name
10930
11167
  )
10931
11168
  )) }),
10932
- /* @__PURE__ */ jsxs74("span", { className: "fd-row", style: { gap: 8, alignItems: "baseline" }, children: [
10933
- /* @__PURE__ */ jsx83("span", { className: "fd-num-hero", style: { fontSize: 30, color: g.items.length ? "var(--text)" : "var(--text-disabled)" }, children: loading ? "\u2013" : g.items.length }),
10934
- /* @__PURE__ */ jsx83("span", { className: "fd-meter", style: { gap: 2, color: mark }, "aria-hidden": "true", children: [1, 2, 3, 4].map((i) => /* @__PURE__ */ jsx83("span", { className: "fd-meter-seg" + (i <= g.n ? " is-on" : ""), style: { width: 4, height: 9 } }, i)) })
11169
+ /* @__PURE__ */ jsxs75("span", { className: "fd-row", style: { gap: 8, alignItems: "baseline" }, children: [
11170
+ /* @__PURE__ */ jsx84("span", { className: "fd-num-hero", style: { fontSize: 30, color: g.items.length ? "var(--text)" : "var(--text-disabled)" }, children: loading ? "\u2013" : g.items.length }),
11171
+ /* @__PURE__ */ jsx84("span", { className: "fd-meter", style: { gap: 2, color: mark }, "aria-hidden": "true", children: [1, 2, 3, 4].map((i) => /* @__PURE__ */ jsx84("span", { className: "fd-meter-seg" + (i <= g.n ? " is-on" : ""), style: { width: 4, height: 9 } }, i)) })
10935
11172
  ] }),
10936
- /* @__PURE__ */ jsxs74("span", { className: "fd-stack", style: { gap: 1 }, children: [
10937
- /* @__PURE__ */ jsx83("span", { className: "fd-label-lg", children: g.label }),
10938
- /* @__PURE__ */ jsxs74("span", { className: "fd-body-sm fd-muted", style: { fontSize: 11.5 }, children: [
11173
+ /* @__PURE__ */ jsxs75("span", { className: "fd-stack", style: { gap: 1 }, children: [
11174
+ /* @__PURE__ */ jsx84("span", { className: "fd-label-lg", children: g.label }),
11175
+ /* @__PURE__ */ jsxs75("span", { className: "fd-body-sm fd-muted", style: { fontSize: 11.5 }, children: [
10939
11176
  "CRP ",
10940
11177
  g.range
10941
11178
  ] })
@@ -10945,10 +11182,10 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
10945
11182
  g.key
10946
11183
  );
10947
11184
  }) }),
10948
- floorBand ? /* @__PURE__ */ jsxs74("div", { className: "fd-row", style: { gap: 10, padding: "12px 14px", borderRadius: "var(--r-md)", background: "var(--surface-2)", border: "1px solid var(--border)", flexWrap: "wrap" }, children: [
10949
- /* @__PURE__ */ jsx83("span", { className: "fd-meter", style: { gap: 2, color: "var(--csi-" + floor.n + "-mark)" }, "aria-hidden": "true", children: [1, 2, 3, 4].map((i) => /* @__PURE__ */ jsx83("span", { className: "fd-meter-seg" + (i <= floor.n ? " is-on" : ""), style: { width: 5, height: 12 } }, i)) }),
10950
- /* @__PURE__ */ jsxs74("span", { className: "fd-body-sm fd-secondary", style: { flex: 1, minWidth: 240 }, children: [
10951
- /* @__PURE__ */ jsxs74("strong", { style: { color: "var(--text)" }, children: [
11185
+ floorBand ? /* @__PURE__ */ jsxs75("div", { className: "fd-row", style: { gap: 10, padding: "12px 14px", borderRadius: "var(--r-md)", background: "var(--surface-2)", border: "1px solid var(--border)", flexWrap: "wrap" }, children: [
11186
+ /* @__PURE__ */ jsx84("span", { className: "fd-meter", style: { gap: 2, color: "var(--csi-" + floor.n + "-mark)" }, "aria-hidden": "true", children: [1, 2, 3, 4].map((i) => /* @__PURE__ */ jsx84("span", { className: "fd-meter-seg" + (i <= floor.n ? " is-on" : ""), style: { width: 5, height: 12 } }, i)) }),
11187
+ /* @__PURE__ */ jsxs75("span", { className: "fd-body-sm fd-secondary", style: { flex: 1, minWidth: 240 }, children: [
11188
+ /* @__PURE__ */ jsxs75("strong", { style: { color: "var(--text)" }, children: [
10952
11189
  "Plan floor ",
10953
11190
  floorScore
10954
11191
  ] }),
@@ -10959,8 +11196,8 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
10959
11196
  }
10960
11197
 
10961
11198
  // src/components/planner/MixGap.tsx
10962
- import * as React55 from "react";
10963
- import { Fragment as Fragment23, jsx as jsx84, jsxs as jsxs75 } from "react/jsx-runtime";
11199
+ import * as React56 from "react";
11200
+ import { Fragment as Fragment23, jsx as jsx85, jsxs as jsxs76 } from "react/jsx-runtime";
10964
11201
  var MIX_GAP_LAYOUT = {
10965
11202
  trackHeight: 30,
10966
11203
  barHeight: 20,
@@ -10974,19 +11211,19 @@ function mixGapOffset(value, max) {
10974
11211
  }
10975
11212
  function MixGap({ rows = [], loading = false, className = "" }) {
10976
11213
  const max = Math.max(1, ...rows.flatMap((r) => [r.target, r.realized]));
10977
- const [hover, setHover] = React55.useState(null);
11214
+ const [hover, setHover] = React56.useState(null);
10978
11215
  const toneOf = (gap) => gap >= -1 ? "ok" : gap >= -4 ? "warn" : "danger";
10979
11216
  const TONE = { ok: "var(--ok-solid)", warn: "var(--warn-solid)", danger: "var(--danger-solid)" };
10980
11217
  const { trackHeight, barHeight, targetWidth, labelGap } = MIX_GAP_LAYOUT;
10981
11218
  const barTop = (trackHeight - barHeight) / 2;
10982
- return /* @__PURE__ */ jsxs75("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 4 }, children: [
10983
- /* @__PURE__ */ jsxs75("div", { className: "fd-row", style: { gap: 16, justifyContent: "flex-end", paddingBottom: 6, flexWrap: "wrap" }, children: [
10984
- [["On target", TONE.ok], ["Close", TONE.warn], ["Short", TONE.danger]].map(([l, c]) => /* @__PURE__ */ jsxs75("span", { className: "fd-row fd-body-sm fd-muted", style: { gap: 6 }, children: [
10985
- /* @__PURE__ */ jsx84("span", { style: { width: 14, height: 9, borderRadius: 2, background: c } }),
11219
+ return /* @__PURE__ */ jsxs76("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 4 }, children: [
11220
+ /* @__PURE__ */ jsxs76("div", { className: "fd-row", style: { gap: 16, justifyContent: "flex-end", paddingBottom: 6, flexWrap: "wrap" }, children: [
11221
+ [["On target", TONE.ok], ["Close", TONE.warn], ["Short", TONE.danger]].map(([l, c]) => /* @__PURE__ */ jsxs76("span", { className: "fd-row fd-body-sm fd-muted", style: { gap: 6 }, children: [
11222
+ /* @__PURE__ */ jsx85("span", { style: { width: 14, height: 9, borderRadius: 2, background: c } }),
10986
11223
  l
10987
11224
  ] }, l)),
10988
- /* @__PURE__ */ jsxs75("span", { className: "fd-row fd-body-sm fd-muted", style: { gap: 6 }, children: [
10989
- /* @__PURE__ */ jsx84("span", { "data-mixgap-legend-target": "", style: { width: targetWidth, height: 16, borderRadius: 1, background: MIX_GAP_TARGET_STRIPE } }),
11225
+ /* @__PURE__ */ jsxs76("span", { className: "fd-row fd-body-sm fd-muted", style: { gap: 6 }, children: [
11226
+ /* @__PURE__ */ jsx85("span", { "data-mixgap-legend-target": "", style: { width: targetWidth, height: 16, borderRadius: 1, background: MIX_GAP_TARGET_STRIPE } }),
10990
11227
  "Target"
10991
11228
  ] })
10992
11229
  ] }),
@@ -10995,7 +11232,7 @@ function MixGap({ rows = [], loading = false, className = "" }) {
10995
11232
  const tone = toneOf(gap);
10996
11233
  const tip = "Realized " + r.realized + "% vs " + r.target + "% target" + (gap < -1 ? " \xB7 " + Math.abs(gap).toFixed(0) + " pts short" : gap > 1 ? " \xB7 " + gap.toFixed(0) + " pts over" : " \xB7 on target") + (r.note ? " \u2014 " + r.note : "");
10997
11234
  const labelLeft = r.realized > r.target ? `calc(${mixGapOffset(r.realized, max)} + ${labelGap}px)` : `calc(${mixGapOffset(r.target, max)} + ${targetWidth / 2 + labelGap}px)`;
10998
- return /* @__PURE__ */ jsxs75(
11235
+ return /* @__PURE__ */ jsxs76(
10999
11236
  "div",
11000
11237
  {
11001
11238
  className: "fd-row",
@@ -11003,15 +11240,15 @@ function MixGap({ rows = [], loading = false, className = "" }) {
11003
11240
  onMouseEnter: () => setHover(r.channel),
11004
11241
  onMouseLeave: () => setHover(null),
11005
11242
  children: [
11006
- /* @__PURE__ */ jsx84("span", { style: { width: 128, flex: "none" }, children: /* @__PURE__ */ jsx84(ChannelTag, { channel: r.channel, size: "sm" }) }),
11007
- /* @__PURE__ */ jsx84("span", { style: { position: "relative", flex: 1, height: trackHeight, minWidth: 120 }, children: loading ? /* @__PURE__ */ jsx84("span", { className: "fd-skel", style: { position: "absolute", left: 0, right: 0, top: barTop, height: barHeight, borderRadius: 3 } }) : /* @__PURE__ */ jsxs75(Fragment23, { children: [
11008
- /* @__PURE__ */ jsx84("span", { "data-mixgap-bar": "", style: { position: "absolute", left: 0, top: barTop, height: barHeight, width: mixGapOffset(r.realized, max), background: TONE[tone], borderRadius: "2px 3px 3px 2px", transition: "width var(--dur-slow) var(--ease), background var(--dur-base) var(--ease)" } }),
11009
- /* @__PURE__ */ jsx84("span", { "data-mixgap-target": "", style: { position: "absolute", left: `calc(${mixGapOffset(r.target, max)} - ${targetWidth / 2}px)`, top: 0, width: targetWidth, height: trackHeight, background: MIX_GAP_TARGET_STRIPE, borderRadius: 1 } }),
11010
- /* @__PURE__ */ jsxs75("span", { "data-mixgap-label": "", className: "fd-num", style: { position: "absolute", left: labelLeft, top: "50%", transform: "translateY(-50%)", fontSize: 12, color: "var(--text-muted)", whiteSpace: "nowrap" }, children: [
11243
+ /* @__PURE__ */ jsx85("span", { style: { width: 128, flex: "none" }, children: /* @__PURE__ */ jsx85(ChannelTag, { channel: r.channel, size: "sm" }) }),
11244
+ /* @__PURE__ */ jsx85("span", { style: { position: "relative", flex: 1, height: trackHeight, minWidth: 120 }, children: loading ? /* @__PURE__ */ jsx85("span", { className: "fd-skel", style: { position: "absolute", left: 0, right: 0, top: barTop, height: barHeight, borderRadius: 3 } }) : /* @__PURE__ */ jsxs76(Fragment23, { children: [
11245
+ /* @__PURE__ */ jsx85("span", { "data-mixgap-bar": "", style: { position: "absolute", left: 0, top: barTop, height: barHeight, width: mixGapOffset(r.realized, max), background: TONE[tone], borderRadius: "2px 3px 3px 2px", transition: "width var(--dur-slow) var(--ease), background var(--dur-base) var(--ease)" } }),
11246
+ /* @__PURE__ */ jsx85("span", { "data-mixgap-target": "", style: { position: "absolute", left: `calc(${mixGapOffset(r.target, max)} - ${targetWidth / 2}px)`, top: 0, width: targetWidth, height: trackHeight, background: MIX_GAP_TARGET_STRIPE, borderRadius: 1 } }),
11247
+ /* @__PURE__ */ jsxs76("span", { "data-mixgap-label": "", className: "fd-num", style: { position: "absolute", left: labelLeft, top: "50%", transform: "translateY(-50%)", fontSize: 12, color: "var(--text-muted)", whiteSpace: "nowrap" }, children: [
11011
11248
  r.realized,
11012
11249
  "%"
11013
11250
  ] }),
11014
- hover === r.channel ? /* @__PURE__ */ jsx84("span", { className: "fd-tooltip", role: "tooltip", style: { position: "absolute", left: 0, right: "auto", bottom: trackHeight + 4, maxWidth: "min(340px, 100%)", whiteSpace: "normal", textAlign: "left", width: "max-content" }, children: tip }) : null
11251
+ hover === r.channel ? /* @__PURE__ */ jsx85("span", { className: "fd-tooltip", role: "tooltip", style: { position: "absolute", left: 0, right: "auto", bottom: trackHeight + 4, maxWidth: "min(340px, 100%)", whiteSpace: "normal", textAlign: "left", width: "max-content" }, children: tip }) : null
11015
11252
  ] }) })
11016
11253
  ]
11017
11254
  },
@@ -11022,7 +11259,7 @@ function MixGap({ rows = [], loading = false, className = "" }) {
11022
11259
  }
11023
11260
 
11024
11261
  // src/components/planner/ChannelContribution.tsx
11025
- import { jsx as jsx85, jsxs as jsxs76 } from "react/jsx-runtime";
11262
+ import { jsx as jsx86, jsxs as jsxs77 } from "react/jsx-runtime";
11026
11263
  var money = (n) => "$" + Math.round(n).toLocaleString();
11027
11264
  function ChannelContribution({
11028
11265
  channels = [],
@@ -11038,9 +11275,9 @@ function ChannelContribution({
11038
11275
  const grand = total !== void 0 ? total : base + bonus;
11039
11276
  const pct = (v) => grand ? v / grand * 100 : 0;
11040
11277
  const spendTotal = channels.reduce((s, c) => s + Number(String(c.spend || 0).replace(/[^0-9.]/g, "")), 0);
11041
- return /* @__PURE__ */ jsxs76("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 16 }, children: [
11042
- loading ? /* @__PURE__ */ jsx85("span", { className: "fd-skel", style: { height: 34, borderRadius: "var(--r-sm)" } }) : /* @__PURE__ */ jsxs76("div", { className: "fd-row", style: { height: 34, borderRadius: "var(--r-sm)", overflow: "hidden", gap: 2, background: "var(--surface-3)" }, children: [
11043
- channels.map((c) => /* @__PURE__ */ jsx85(
11278
+ return /* @__PURE__ */ jsxs77("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 16 }, children: [
11279
+ loading ? /* @__PURE__ */ jsx86("span", { className: "fd-skel", style: { height: 34, borderRadius: "var(--r-sm)" } }) : /* @__PURE__ */ jsxs77("div", { className: "fd-row", style: { height: 34, borderRadius: "var(--r-sm)", overflow: "hidden", gap: 2, background: "var(--surface-3)" }, children: [
11280
+ channels.map((c) => /* @__PURE__ */ jsx86(
11044
11281
  "span",
11045
11282
  {
11046
11283
  title: c.name + " \xB7 " + c.crp.toFixed(1) + " CRP",
@@ -11049,7 +11286,7 @@ function ChannelContribution({
11049
11286
  },
11050
11287
  c.name
11051
11288
  )),
11052
- bonus > 0 ? /* @__PURE__ */ jsx85(
11289
+ bonus > 0 ? /* @__PURE__ */ jsx86(
11053
11290
  "span",
11054
11291
  {
11055
11292
  title: "Surround-sound bonus +" + bonusPct + "%",
@@ -11058,18 +11295,18 @@ function ChannelContribution({
11058
11295
  }
11059
11296
  ) : null
11060
11297
  ] }),
11061
- showTable ? /* @__PURE__ */ jsxs76("table", { className: "fd-table", style: { fontSize: "var(--body-sm-size)" }, children: [
11062
- /* @__PURE__ */ jsx85("thead", { children: /* @__PURE__ */ jsxs76("tr", { children: [
11063
- /* @__PURE__ */ jsx85("th", { style: { width: "34%" }, children: "Channel" }),
11064
- /* @__PURE__ */ jsx85("th", { style: { width: "16%" }, children: "Weight" }),
11065
- /* @__PURE__ */ jsx85("th", { className: "is-num", style: { width: "16%" }, children: "Spend" }),
11066
- /* @__PURE__ */ jsx85("th", { className: "is-num", style: { width: "17%" }, children: "CRP" }),
11067
- /* @__PURE__ */ jsx85("th", { className: "is-num", style: { width: "17%" }, children: "Share" })
11298
+ showTable ? /* @__PURE__ */ jsxs77("table", { className: "fd-table", style: { fontSize: "var(--body-sm-size)" }, children: [
11299
+ /* @__PURE__ */ jsx86("thead", { children: /* @__PURE__ */ jsxs77("tr", { children: [
11300
+ /* @__PURE__ */ jsx86("th", { style: { width: "34%" }, children: "Channel" }),
11301
+ /* @__PURE__ */ jsx86("th", { style: { width: "16%" }, children: "Weight" }),
11302
+ /* @__PURE__ */ jsx86("th", { className: "is-num", style: { width: "16%" }, children: "Spend" }),
11303
+ /* @__PURE__ */ jsx86("th", { className: "is-num", style: { width: "17%" }, children: "CRP" }),
11304
+ /* @__PURE__ */ jsx86("th", { className: "is-num", style: { width: "17%" }, children: "Share" })
11068
11305
  ] }) }),
11069
- /* @__PURE__ */ jsxs76("tbody", { children: [
11070
- channels.map((c) => /* @__PURE__ */ jsxs76("tr", { children: [
11071
- /* @__PURE__ */ jsx85("td", { children: /* @__PURE__ */ jsx85(ChannelTag, { channel: c.name, size: "sm" }) }),
11072
- /* @__PURE__ */ jsx85("td", { children: /* @__PURE__ */ jsx85(
11306
+ /* @__PURE__ */ jsxs77("tbody", { children: [
11307
+ channels.map((c) => /* @__PURE__ */ jsxs77("tr", { children: [
11308
+ /* @__PURE__ */ jsx86("td", { children: /* @__PURE__ */ jsx86(ChannelTag, { channel: c.name, size: "sm" }) }),
11309
+ /* @__PURE__ */ jsx86("td", { children: /* @__PURE__ */ jsx86(
11073
11310
  "span",
11074
11311
  {
11075
11312
  className: "fd-badge fd-badge-neutral",
@@ -11078,38 +11315,38 @@ function ChannelContribution({
11078
11315
  children: "weight " + (channelWeightOf(c.name) || 0)
11079
11316
  }
11080
11317
  ) }),
11081
- /* @__PURE__ */ jsx85("td", { className: "is-num", children: c.spend }),
11082
- /* @__PURE__ */ jsx85("td", { className: "is-num", children: c.crp.toFixed(1) }),
11083
- /* @__PURE__ */ jsxs76("td", { className: "is-num", children: [
11318
+ /* @__PURE__ */ jsx86("td", { className: "is-num", children: c.spend }),
11319
+ /* @__PURE__ */ jsx86("td", { className: "is-num", children: c.crp.toFixed(1) }),
11320
+ /* @__PURE__ */ jsxs77("td", { className: "is-num", children: [
11084
11321
  pct(c.crp).toFixed(0),
11085
11322
  "%"
11086
11323
  ] })
11087
11324
  ] }, c.name)),
11088
- bonus > 0 ? /* @__PURE__ */ jsxs76("tr", { children: [
11089
- /* @__PURE__ */ jsx85("td", { children: /* @__PURE__ */ jsxs76("span", { className: "fd-row", style: { gap: 9, fontWeight: 600 }, children: [
11090
- /* @__PURE__ */ jsx85("span", { style: { width: 9, height: 9, borderRadius: 2, background: "repeating-linear-gradient(135deg,var(--csi-3-mark) 0 3px,var(--csi-2-mark) 3px 6px)", flex: "none" } }),
11325
+ bonus > 0 ? /* @__PURE__ */ jsxs77("tr", { children: [
11326
+ /* @__PURE__ */ jsx86("td", { children: /* @__PURE__ */ jsxs77("span", { className: "fd-row", style: { gap: 9, fontWeight: 600 }, children: [
11327
+ /* @__PURE__ */ jsx86("span", { style: { width: 9, height: 9, borderRadius: 2, background: "repeating-linear-gradient(135deg,var(--csi-3-mark) 0 3px,var(--csi-2-mark) 3px 6px)", flex: "none" } }),
11091
11328
  "Surround-sound bonus"
11092
11329
  ] }) }),
11093
- /* @__PURE__ */ jsx85("td", { children: /* @__PURE__ */ jsxs76("span", { className: "fd-badge fd-badge-success", style: { height: 20, fontSize: 11 }, children: [
11330
+ /* @__PURE__ */ jsx86("td", { children: /* @__PURE__ */ jsxs77("span", { className: "fd-badge fd-badge-success", style: { height: 20, fontSize: 11 }, children: [
11094
11331
  "+",
11095
11332
  bonusPct,
11096
11333
  "% of +",
11097
11334
  bonusMax,
11098
11335
  "%"
11099
11336
  ] }) }),
11100
- /* @__PURE__ */ jsx85("td", { className: "is-num fd-muted", children: "\u2014" }),
11101
- /* @__PURE__ */ jsx85("td", { className: "is-num", children: bonus.toFixed(1) }),
11102
- /* @__PURE__ */ jsxs76("td", { className: "is-num", children: [
11337
+ /* @__PURE__ */ jsx86("td", { className: "is-num fd-muted", children: "\u2014" }),
11338
+ /* @__PURE__ */ jsx86("td", { className: "is-num", children: bonus.toFixed(1) }),
11339
+ /* @__PURE__ */ jsxs77("td", { className: "is-num", children: [
11103
11340
  pct(bonus).toFixed(0),
11104
11341
  "%"
11105
11342
  ] })
11106
11343
  ] }) : null,
11107
- /* @__PURE__ */ jsxs76("tr", { style: { background: "var(--surface-2)" }, children: [
11108
- /* @__PURE__ */ jsx85("td", { style: { fontWeight: 700 }, children: "Campus total" }),
11109
- /* @__PURE__ */ jsx85("td", {}),
11110
- /* @__PURE__ */ jsx85("td", { className: "is-num", style: { fontWeight: 700 }, children: money(spendTotal) }),
11111
- /* @__PURE__ */ jsx85("td", { className: "is-num", style: { fontWeight: 700 }, children: grand.toFixed(1) }),
11112
- /* @__PURE__ */ jsx85("td", { className: "is-num", style: { fontWeight: 700 }, children: "100%" })
11344
+ /* @__PURE__ */ jsxs77("tr", { style: { background: "var(--surface-2)" }, children: [
11345
+ /* @__PURE__ */ jsx86("td", { style: { fontWeight: 700 }, children: "Campus total" }),
11346
+ /* @__PURE__ */ jsx86("td", {}),
11347
+ /* @__PURE__ */ jsx86("td", { className: "is-num", style: { fontWeight: 700 }, children: money(spendTotal) }),
11348
+ /* @__PURE__ */ jsx86("td", { className: "is-num", style: { fontWeight: 700 }, children: grand.toFixed(1) }),
11349
+ /* @__PURE__ */ jsx86("td", { className: "is-num", style: { fontWeight: 700 }, children: "100%" })
11113
11350
  ] })
11114
11351
  ] })
11115
11352
  ] }) : null
@@ -11117,8 +11354,8 @@ function ChannelContribution({
11117
11354
  }
11118
11355
 
11119
11356
  // src/components/planner/BudgetReallocator.tsx
11120
- import * as React56 from "react";
11121
- import { Fragment as Fragment24, jsx as jsx86, jsxs as jsxs77 } from "react/jsx-runtime";
11357
+ import * as React57 from "react";
11358
+ import { Fragment as Fragment24, jsx as jsx87, jsxs as jsxs78 } from "react/jsx-runtime";
11122
11359
  var bandFor = (crp) => crp >= 200 ? "dominant" : crp >= 100 ? "strong" : crp >= 50 ? "adequate" : "weak";
11123
11360
  function BudgetReallocator({
11124
11361
  campus,
@@ -11133,8 +11370,8 @@ function BudgetReallocator({
11133
11370
  onCancel,
11134
11371
  className = ""
11135
11372
  }) {
11136
- const [draft, setDraft] = React56.useState(spend);
11137
- React56.useEffect(() => setDraft(spend), [spend]);
11373
+ const [draft, setDraft] = React57.useState(spend);
11374
+ React57.useEffect(() => setDraft(spend), [spend]);
11138
11375
  const dirty = draft !== spend;
11139
11376
  const nextCrp = scoreFor ? scoreFor(draft) : crp;
11140
11377
  const nextBand = bandFor(nextCrp);
@@ -11149,10 +11386,10 @@ function BudgetReallocator({
11149
11386
  setDraft(spend);
11150
11387
  if (onCancel) onCancel();
11151
11388
  };
11152
- const trackRef = React56.useRef(null);
11153
- const chipRef = React56.useRef(null);
11154
- const [chipLeft, setChipLeft] = React56.useState(null);
11155
- React56.useLayoutEffect(() => {
11389
+ const trackRef = React57.useRef(null);
11390
+ const chipRef = React57.useRef(null);
11391
+ const [chipLeft, setChipLeft] = React57.useState(null);
11392
+ React57.useLayoutEffect(() => {
11156
11393
  const track = trackRef.current;
11157
11394
  if (!dirty || !track) {
11158
11395
  setChipLeft(null);
@@ -11173,23 +11410,23 @@ function BudgetReallocator({
11173
11410
  ro.observe(track);
11174
11411
  return () => ro.disconnect();
11175
11412
  }, [dirty, pct]);
11176
- return /* @__PURE__ */ jsxs77(
11413
+ return /* @__PURE__ */ jsxs78(
11177
11414
  "div",
11178
11415
  {
11179
11416
  className: ["fd-stack", className].filter(Boolean).join(" "),
11180
11417
  style: { gap: 14, padding: 18, border: "1px solid " + (dirty ? "var(--border-brand)" : "var(--border)"), borderRadius: "var(--r-lg)", background: dirty ? "var(--surface-brand)" : "var(--surface)", color: "var(--text)", transition: "background var(--dur-base) var(--ease),border-color var(--dur-base) var(--ease)" },
11181
11418
  children: [
11182
- /* @__PURE__ */ jsxs77("div", { className: "fd-row", style: { gap: 12, flexWrap: "wrap" }, children: [
11183
- /* @__PURE__ */ jsx86("span", { className: "fd-h4", style: { flex: 1, minWidth: 140 }, children: campus }),
11184
- /* @__PURE__ */ jsx86(CsiBadge, { band: nowBand, crp, size: "medium" }),
11185
- dirty ? /* @__PURE__ */ jsxs77(Fragment24, { children: [
11186
- /* @__PURE__ */ jsx86("i", { className: "ph ph-arrow-right fd-muted", "aria-hidden": "true" }),
11187
- /* @__PURE__ */ jsx86(CsiBadge, { band: nextBand, crp: nextCrp, size: "medium", preview: true })
11419
+ /* @__PURE__ */ jsxs78("div", { className: "fd-row", style: { gap: 12, flexWrap: "wrap" }, children: [
11420
+ /* @__PURE__ */ jsx87("span", { className: "fd-h4", style: { flex: 1, minWidth: 140 }, children: campus }),
11421
+ /* @__PURE__ */ jsx87(CsiBadge, { band: nowBand, crp, size: "medium" }),
11422
+ dirty ? /* @__PURE__ */ jsxs78(Fragment24, { children: [
11423
+ /* @__PURE__ */ jsx87("i", { className: "ph ph-arrow-right fd-muted", "aria-hidden": "true" }),
11424
+ /* @__PURE__ */ jsx87(CsiBadge, { band: nextBand, crp: nextCrp, size: "medium", preview: true })
11188
11425
  ] }) : null
11189
11426
  ] }),
11190
- /* @__PURE__ */ jsxs77("div", { className: "fd-slider", ref: trackRef, children: [
11191
- /* @__PURE__ */ jsx86("span", { className: "fd-slider-fill", style: { width: pct + "%" } }),
11192
- dirty ? /* @__PURE__ */ jsx86(
11427
+ /* @__PURE__ */ jsxs78("div", { className: "fd-slider", ref: trackRef, children: [
11428
+ /* @__PURE__ */ jsx87("span", { className: "fd-slider-fill", style: { width: pct + "%" } }),
11429
+ dirty ? /* @__PURE__ */ jsx87(
11193
11430
  "span",
11194
11431
  {
11195
11432
  ref: chipRef,
@@ -11201,7 +11438,7 @@ function BudgetReallocator({
11201
11438
  children: (delta < 0 ? "\u2212$" : "+$") + Math.abs(delta).toLocaleString()
11202
11439
  }
11203
11440
  ) : null,
11204
- /* @__PURE__ */ jsx86(
11441
+ /* @__PURE__ */ jsx87(
11205
11442
  "input",
11206
11443
  {
11207
11444
  type: "range",
@@ -11217,13 +11454,13 @@ function BudgetReallocator({
11217
11454
  }
11218
11455
  )
11219
11456
  ] }),
11220
- /* @__PURE__ */ jsxs77("div", { className: "fd-row", style: { gap: 12, flexWrap: "wrap" }, children: [
11221
- /* @__PURE__ */ jsxs77("span", { className: "fd-stack", style: { gap: 2, flex: 1, minWidth: 150 }, children: [
11222
- /* @__PURE__ */ jsx86("span", { className: "fd-num", style: { fontSize: 19, fontWeight: 700 }, children: "$" + draft.toLocaleString() }),
11223
- /* @__PURE__ */ jsx86("span", { className: "fd-body-sm fd-muted", children: "Arrow keys step $100, shift+arrow $1,000. Escape reverts." })
11457
+ /* @__PURE__ */ jsxs78("div", { className: "fd-row", style: { gap: 12, flexWrap: "wrap" }, children: [
11458
+ /* @__PURE__ */ jsxs78("span", { className: "fd-stack", style: { gap: 2, flex: 1, minWidth: 150 }, children: [
11459
+ /* @__PURE__ */ jsx87("span", { className: "fd-num", style: { fontSize: 19, fontWeight: 700 }, children: "$" + draft.toLocaleString() }),
11460
+ /* @__PURE__ */ jsx87("span", { className: "fd-body-sm fd-muted", children: "Arrow keys step $100, shift+arrow $1,000. Escape reverts." })
11224
11461
  ] }),
11225
- /* @__PURE__ */ jsx86("button", { type: "button", className: "fd-btn fd-btn-ghost", disabled: !dirty, onClick: revert, children: "Cancel" }),
11226
- /* @__PURE__ */ jsx86(
11462
+ /* @__PURE__ */ jsx87("button", { type: "button", className: "fd-btn fd-btn-ghost", disabled: !dirty, onClick: revert, children: "Cancel" }),
11463
+ /* @__PURE__ */ jsx87(
11227
11464
  "button",
11228
11465
  {
11229
11466
  type: "button",
@@ -11242,7 +11479,7 @@ function BudgetReallocator({
11242
11479
  }
11243
11480
 
11244
11481
  // src/components/planner/SurroundSound.tsx
11245
- import { jsx as jsx87, jsxs as jsxs78 } from "react/jsx-runtime";
11482
+ import { jsx as jsx88, jsxs as jsxs79 } from "react/jsx-runtime";
11246
11483
  var CATEGORIES = [
11247
11484
  { key: "ooh", label: "OOH", icon: "flag-banner", color: "var(--ch-ooh)" },
11248
11485
  { key: "transit", label: "Transit", icon: "bus", color: "var(--ch-transit)" },
@@ -11254,26 +11491,26 @@ var CATEGORIES = [
11254
11491
  function SurroundSound({ present = [], bonusPct = 0, bonusMax = 40, missedCost, className = "" }) {
11255
11492
  const earned = Math.max(0, Math.min(1, bonusPct / bonusMax));
11256
11493
  const single = present.length <= 2;
11257
- return /* @__PURE__ */ jsxs78("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 14 }, children: [
11258
- /* @__PURE__ */ jsx87("div", { className: "fd-row", style: { gap: 8, flexWrap: "wrap" }, children: CATEGORIES.map((c) => {
11494
+ return /* @__PURE__ */ jsxs79("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 14 }, children: [
11495
+ /* @__PURE__ */ jsx88("div", { className: "fd-row", style: { gap: 8, flexWrap: "wrap" }, children: CATEGORIES.map((c) => {
11259
11496
  const on = present.includes(c.key);
11260
- return /* @__PURE__ */ jsxs78(
11497
+ return /* @__PURE__ */ jsxs79(
11261
11498
  "span",
11262
11499
  {
11263
11500
  title: c.label + (on ? " \u2014 present" : " \u2014 not bought"),
11264
11501
  style: { display: "flex", flexDirection: "column", alignItems: "center", gap: 5, width: 62, padding: "10px 0", borderRadius: "var(--r-md)", border: "1px solid " + (on ? "var(--csi-2-edge)" : "var(--border)"), background: on ? "var(--csi-2-fill)" : "var(--surface-2)", color: on ? "var(--csi-2-text)" : "var(--text-disabled)" },
11265
11502
  children: [
11266
- /* @__PURE__ */ jsx87("i", { className: "ph ph-" + c.icon, style: { fontSize: 19, color: on ? c.color : "var(--text-muted)" }, "aria-hidden": "true" }),
11267
- /* @__PURE__ */ jsx87("span", { style: { fontSize: 10.5, fontWeight: 700 }, children: c.label })
11503
+ /* @__PURE__ */ jsx88("i", { className: "ph ph-" + c.icon, style: { fontSize: 19, color: on ? c.color : "var(--text-muted)" }, "aria-hidden": "true" }),
11504
+ /* @__PURE__ */ jsx88("span", { style: { fontSize: 10.5, fontWeight: 700 }, children: c.label })
11268
11505
  ]
11269
11506
  },
11270
11507
  c.key
11271
11508
  );
11272
11509
  }) }),
11273
- /* @__PURE__ */ jsxs78("div", { className: "fd-stack", style: { gap: 8 }, children: [
11274
- /* @__PURE__ */ jsxs78("div", { className: "fd-row", style: { justifyContent: "space-between", gap: 12 }, children: [
11275
- /* @__PURE__ */ jsx87("span", { className: "fd-label-lg", children: "Surround-sound bonus earned" }),
11276
- /* @__PURE__ */ jsxs78("span", { className: "fd-num", style: { color: single ? "var(--warn-text)" : "var(--csi-3-mark)", fontWeight: 700 }, children: [
11510
+ /* @__PURE__ */ jsxs79("div", { className: "fd-stack", style: { gap: 8 }, children: [
11511
+ /* @__PURE__ */ jsxs79("div", { className: "fd-row", style: { justifyContent: "space-between", gap: 12 }, children: [
11512
+ /* @__PURE__ */ jsx88("span", { className: "fd-label-lg", children: "Surround-sound bonus earned" }),
11513
+ /* @__PURE__ */ jsxs79("span", { className: "fd-num", style: { color: single ? "var(--warn-text)" : "var(--csi-3-mark)", fontWeight: 700 }, children: [
11277
11514
  "+",
11278
11515
  bonusPct,
11279
11516
  "% of +",
@@ -11281,8 +11518,8 @@ function SurroundSound({ present = [], bonusPct = 0, bonusMax = 40, missedCost,
11281
11518
  "%"
11282
11519
  ] })
11283
11520
  ] }),
11284
- /* @__PURE__ */ jsx87("div", { style: { height: 8, borderRadius: "var(--r-xs)", background: "var(--surface-3)", overflow: "hidden" }, children: /* @__PURE__ */ jsx87("div", { style: { height: "100%", width: earned * 100 + "%", background: "var(--csi-3-mark)", borderRadius: "inherit", transition: "width var(--dur-slow) var(--ease)" } }) }),
11285
- /* @__PURE__ */ jsxs78("span", { className: "fd-body-sm fd-secondary", style: { textWrap: "pretty" }, children: [
11521
+ /* @__PURE__ */ jsx88("div", { style: { height: 8, borderRadius: "var(--r-xs)", background: "var(--surface-3)", overflow: "hidden" }, children: /* @__PURE__ */ jsx88("div", { style: { height: "100%", width: earned * 100 + "%", background: "var(--csi-3-mark)", borderRadius: "inherit", transition: "width var(--dur-slow) var(--ease)" } }) }),
11522
+ /* @__PURE__ */ jsxs79("span", { className: "fd-body-sm fd-secondary", style: { textWrap: "pretty" }, children: [
11286
11523
  present.length,
11287
11524
  " of 6 channel categories present.",
11288
11525
  " ",
@@ -11294,7 +11531,7 @@ function SurroundSound({ present = [], bonusPct = 0, bonusMax = 40, missedCost,
11294
11531
  }
11295
11532
 
11296
11533
  // src/components/planner/Importance.tsx
11297
- import { jsx as jsx88, jsxs as jsxs79 } from "react/jsx-runtime";
11534
+ import { jsx as jsx89, jsxs as jsxs80 } from "react/jsx-runtime";
11298
11535
  var IMPORTANCE_LEVELS = [
11299
11536
  { id: "nudge", rank: 1, label: "Nudge", icon: "feather", description: "Breaks a tie, nothing more." },
11300
11537
  { id: "lean", rank: 2, label: "Lean", icon: "arrow-bend-up-right", description: "A mild preference between otherwise equal options." },
@@ -11324,7 +11561,7 @@ function importanceTokens(id) {
11324
11561
  function ImportanceTag({ level, showLabel = true, size = "sm", className = "", disabled = false }) {
11325
11562
  const lvl = importanceLevel(level);
11326
11563
  const t = importanceTokens(level);
11327
- return /* @__PURE__ */ jsxs79(
11564
+ return /* @__PURE__ */ jsxs80(
11328
11565
  "span",
11329
11566
  {
11330
11567
  className: ["fd-imp-tag", size === "md" ? "is-md" : "", disabled ? "is-disabled" : "", className].filter(Boolean).join(" "),
@@ -11332,16 +11569,16 @@ function ImportanceTag({ level, showLabel = true, size = "sm", className = "", d
11332
11569
  title: lvl.label + " \u2014 " + lvl.description,
11333
11570
  "aria-disabled": disabled ? "true" : void 0,
11334
11571
  children: [
11335
- /* @__PURE__ */ jsx88("i", { className: "ph ph-" + lvl.icon, "aria-hidden": "true" }),
11336
- showLabel ? lvl.label : /* @__PURE__ */ jsx88("span", { className: "fd-sr", children: lvl.label })
11572
+ /* @__PURE__ */ jsx89("i", { className: "ph ph-" + lvl.icon, "aria-hidden": "true" }),
11573
+ showLabel ? lvl.label : /* @__PURE__ */ jsx89("span", { className: "fd-sr", children: lvl.label })
11337
11574
  ]
11338
11575
  }
11339
11576
  );
11340
11577
  }
11341
11578
 
11342
11579
  // src/components/planner/PreferenceMeter.tsx
11343
- import * as React57 from "react";
11344
- import { jsx as jsx89, jsxs as jsxs80 } from "react/jsx-runtime";
11580
+ import * as React58 from "react";
11581
+ import { jsx as jsx90, jsxs as jsxs81 } from "react/jsx-runtime";
11345
11582
  function preferenceScore(criteria) {
11346
11583
  const earned = criteria.reduce((n, c) => n + (Number(c.earned) || 0), 0);
11347
11584
  const weight = criteria.reduce((n, c) => n + (Number(c.weight) || 0), 0);
@@ -11370,8 +11607,8 @@ function PreferenceMeter({
11370
11607
  className = ""
11371
11608
  }) {
11372
11609
  const value = score == null ? preferenceScore(criteria) : score;
11373
- const segments = React57.useMemo(() => preferenceSegments(criteria), [criteria]);
11374
- return /* @__PURE__ */ jsx89(
11610
+ const segments = React58.useMemo(() => preferenceSegments(criteria), [criteria]);
11611
+ return /* @__PURE__ */ jsx90(
11375
11612
  ScoreMeter,
11376
11613
  {
11377
11614
  score: value,
@@ -11383,22 +11620,22 @@ function PreferenceMeter({
11383
11620
  placement,
11384
11621
  className,
11385
11622
  breakdownLabel: breakdownTitle,
11386
- breakdown: /* @__PURE__ */ jsxs80("div", { className: "fd-prefbreak", children: [
11387
- /* @__PURE__ */ jsxs80("div", { className: "fd-prefbreak-head", children: [
11388
- /* @__PURE__ */ jsx89("span", { className: "fd-label-lg", children: breakdownTitle }),
11389
- /* @__PURE__ */ jsx89("span", { className: "fd-prefbreak-score fd-tabular", children: Math.round(value) })
11623
+ breakdown: /* @__PURE__ */ jsxs81("div", { className: "fd-prefbreak", children: [
11624
+ /* @__PURE__ */ jsxs81("div", { className: "fd-prefbreak-head", children: [
11625
+ /* @__PURE__ */ jsx90("span", { className: "fd-label-lg", children: breakdownTitle }),
11626
+ /* @__PURE__ */ jsx90("span", { className: "fd-prefbreak-score fd-tabular", children: Math.round(value) })
11390
11627
  ] }),
11391
- /* @__PURE__ */ jsx89("ul", { className: "fd-prefbreak-list", children: criteria.map((c) => {
11628
+ /* @__PURE__ */ jsx90("ul", { className: "fd-prefbreak-list", children: criteria.map((c) => {
11392
11629
  const pct = c.weight > 0 ? Math.round((Number(c.earned) || 0) / c.weight * 100) : 0;
11393
- return /* @__PURE__ */ jsxs80("li", { className: pct === 0 ? "fd-prefbreak-item is-unmet" : "fd-prefbreak-item", children: [
11394
- /* @__PURE__ */ jsx89(ImportanceTag, { level: c.importance }),
11395
- /* @__PURE__ */ jsxs80("span", { className: "fd-prefbreak-text", children: [
11396
- /* @__PURE__ */ jsx89("span", { className: "fd-prefbreak-label", children: c.label }),
11397
- c.note ? /* @__PURE__ */ jsx89("span", { className: "fd-prefbreak-note", children: c.note }) : null
11630
+ return /* @__PURE__ */ jsxs81("li", { className: pct === 0 ? "fd-prefbreak-item is-unmet" : "fd-prefbreak-item", children: [
11631
+ /* @__PURE__ */ jsx90(ImportanceTag, { level: c.importance }),
11632
+ /* @__PURE__ */ jsxs81("span", { className: "fd-prefbreak-text", children: [
11633
+ /* @__PURE__ */ jsx90("span", { className: "fd-prefbreak-label", children: c.label }),
11634
+ c.note ? /* @__PURE__ */ jsx90("span", { className: "fd-prefbreak-note", children: c.note }) : null
11398
11635
  ] }),
11399
- /* @__PURE__ */ jsxs80("span", { className: "fd-prefbreak-val fd-tabular", children: [
11636
+ /* @__PURE__ */ jsxs81("span", { className: "fd-prefbreak-val fd-tabular", children: [
11400
11637
  Math.round(Number(c.earned) || 0),
11401
- /* @__PURE__ */ jsx89("span", { className: "fd-prefbreak-sep", children: "/" }),
11638
+ /* @__PURE__ */ jsx90("span", { className: "fd-prefbreak-sep", children: "/" }),
11402
11639
  Math.round(c.weight)
11403
11640
  ] })
11404
11641
  ] }, c.id);
@@ -11409,10 +11646,10 @@ function PreferenceMeter({
11409
11646
  }
11410
11647
 
11411
11648
  // src/components/chat/AgentChatPanel.tsx
11412
- import * as React63 from "react";
11649
+ import * as React64 from "react";
11413
11650
 
11414
11651
  // src/components/chat/chatEngine.ts
11415
- import * as React58 from "react";
11652
+ import * as React59 from "react";
11416
11653
  var CHAT_UNAVAILABLE = "chat_unavailable";
11417
11654
  var JOB_PENDING = ["queued", "running"];
11418
11655
  var JOB_SUCCESS = ["completed", "recovered"];
@@ -11466,22 +11703,22 @@ function useChatEngine(opts) {
11466
11703
  onClear,
11467
11704
  onFeedback
11468
11705
  } = opts || {};
11469
- const [status, setStatus] = React58.useState("idle");
11470
- const [threadId, setThreadId] = React58.useState(null);
11471
- const [messages, setMessages] = React58.useState([]);
11472
- const [queue, setQueue] = React58.useState([]);
11473
- const [fatal, setFatal] = React58.useState(null);
11474
- const [busy, setBusy] = React58.useState(false);
11475
- const [turnStartedAt, setTurnStartedAt] = React58.useState(null);
11476
- const listRef = React58.useRef([]);
11477
- const queueRef = React58.useRef([]);
11478
- const busyRef = React58.useRef(false);
11479
- const stoppedRef = React58.useRef(false);
11480
- const abortRef = React58.useRef(null);
11481
- const serverCount = React58.useRef(0);
11482
- const threadRef = React58.useRef(null);
11483
- const mounted = React58.useRef(true);
11484
- React58.useEffect(() => {
11706
+ const [status, setStatus] = React59.useState("idle");
11707
+ const [threadId, setThreadId] = React59.useState(null);
11708
+ const [messages, setMessages] = React59.useState([]);
11709
+ const [queue, setQueue] = React59.useState([]);
11710
+ const [fatal, setFatal] = React59.useState(null);
11711
+ const [busy, setBusy] = React59.useState(false);
11712
+ const [turnStartedAt, setTurnStartedAt] = React59.useState(null);
11713
+ const listRef = React59.useRef([]);
11714
+ const queueRef = React59.useRef([]);
11715
+ const busyRef = React59.useRef(false);
11716
+ const stoppedRef = React59.useRef(false);
11717
+ const abortRef = React59.useRef(null);
11718
+ const serverCount = React59.useRef(0);
11719
+ const threadRef = React59.useRef(null);
11720
+ const mounted = React59.useRef(true);
11721
+ React59.useEffect(() => {
11485
11722
  mounted.current = true;
11486
11723
  return () => {
11487
11724
  mounted.current = false;
@@ -11503,14 +11740,14 @@ function useChatEngine(opts) {
11503
11740
  }
11504
11741
  return false;
11505
11742
  };
11506
- const loadThread = React58.useCallback(async (id) => {
11743
+ const loadThread = React59.useCallback(async (id) => {
11507
11744
  const data = await apiAdapter.getThread(id);
11508
11745
  const list = [...data && data.messages || []];
11509
11746
  serverCount.current = list.length;
11510
11747
  commit(list);
11511
11748
  return list;
11512
11749
  }, [apiAdapter]);
11513
- React58.useEffect(() => {
11750
+ React59.useEffect(() => {
11514
11751
  if (!apiAdapter) {
11515
11752
  setStatus("idle");
11516
11753
  setFatal(null);
@@ -11723,7 +11960,7 @@ function useChatEngine(opts) {
11723
11960
  await dispatchTurn(turn);
11724
11961
  }
11725
11962
  }
11726
- const send = React58.useCallback((text, attachments) => {
11963
+ const send = React59.useCallback((text, attachments) => {
11727
11964
  const body = (text || "").trim();
11728
11965
  if (!body && !(attachments && attachments.length)) return;
11729
11966
  if (status === "disconnected") return;
@@ -11733,7 +11970,7 @@ function useChatEngine(opts) {
11733
11970
  stoppedRef.current = false;
11734
11971
  drain();
11735
11972
  }, [status]);
11736
- const stop = React58.useCallback(() => {
11973
+ const stop = React59.useCallback(() => {
11737
11974
  stoppedRef.current = true;
11738
11975
  const ac = abortRef.current;
11739
11976
  if (ac) {
@@ -11752,11 +11989,11 @@ function useChatEngine(opts) {
11752
11989
  store.del(STORAGE_PREFIX + threadRef.current);
11753
11990
  }
11754
11991
  }, [apiAdapter]);
11755
- const removeQueued = React58.useCallback((id) => {
11992
+ const removeQueued = React59.useCallback((id) => {
11756
11993
  queueRef.current = queueRef.current.filter((t) => t.id !== id);
11757
11994
  setQueue(queueRef.current.slice());
11758
11995
  }, []);
11759
- const retry = React58.useCallback(() => {
11996
+ const retry = React59.useCallback(() => {
11760
11997
  const list = listRef.current;
11761
11998
  let at = -1;
11762
11999
  for (let i = list.length - 1; i >= 0; i--) if (list[i].role === "user") {
@@ -11772,19 +12009,19 @@ function useChatEngine(opts) {
11772
12009
  setQueue(queueRef.current.slice());
11773
12010
  drain();
11774
12011
  }, []);
11775
- const clear = React58.useCallback(() => {
12012
+ const clear = React59.useCallback(() => {
11776
12013
  commit([]);
11777
12014
  serverCount.current = 0;
11778
12015
  queueRef.current = [];
11779
12016
  setQueue([]);
11780
12017
  onClear && onClear();
11781
12018
  }, [onClear]);
11782
- const setFeedback = React58.useCallback((id, value) => {
12019
+ const setFeedback = React59.useCallback((id, value) => {
11783
12020
  patch(id, (m) => ({ feedback: m.feedback === value ? null : value }));
11784
12021
  const msg = listRef.current.find((m) => m.id === id);
11785
12022
  onFeedback && onFeedback({ message: msg, feedback: msg ? msg.feedback : value });
11786
12023
  }, [onFeedback]);
11787
- const reload = React58.useCallback(async () => {
12024
+ const reload = React59.useCallback(async () => {
11788
12025
  if (!threadRef.current) return;
11789
12026
  setStatus("loading");
11790
12027
  try {
@@ -11822,11 +12059,11 @@ var ChatKit = {
11822
12059
  };
11823
12060
 
11824
12061
  // src/components/chat/ChatTranscript.tsx
11825
- import * as React60 from "react";
12062
+ import * as React61 from "react";
11826
12063
 
11827
12064
  // src/components/chat/ChatTurn.tsx
11828
- import * as React59 from "react";
11829
- import { jsx as jsx90, jsxs as jsxs81 } from "react/jsx-runtime";
12065
+ import * as React60 from "react";
12066
+ import { jsx as jsx91, jsxs as jsxs82 } from "react/jsx-runtime";
11830
12067
  function JsonView({ value }) {
11831
12068
  let text;
11832
12069
  try {
@@ -11834,67 +12071,67 @@ function JsonView({ value }) {
11834
12071
  } catch (e) {
11835
12072
  text = String(value);
11836
12073
  }
11837
- return /* @__PURE__ */ jsx90(CodeBlock, { code: text, language: "json", collapseAfter: 18 });
12074
+ return /* @__PURE__ */ jsx91(CodeBlock, { code: text, language: "json", collapseAfter: 18 });
11838
12075
  }
11839
12076
  function PacketCard({ packet, schema, render, onApply, applied }) {
11840
12077
  if (!packet) return null;
11841
12078
  const s = schema || {};
11842
12079
  const invalid = packet.valid === false;
11843
12080
  const title = s.heading || packet.type;
11844
- return /* @__PURE__ */ jsxs81("section", { className: "fdc-packet" + (invalid ? " is-invalid" : ""), "aria-label": title, children: [
11845
- /* @__PURE__ */ jsxs81("header", { className: "fdc-packet-head", children: [
11846
- /* @__PURE__ */ jsx90("i", { className: "ph ph-" + (s.icon || "package"), "aria-hidden": "true" }),
11847
- /* @__PURE__ */ jsx90("span", { className: "fdc-packet-title", title: truncationTitle(title), children: title }),
11848
- packet.repaired ? /* @__PURE__ */ jsx90("span", { className: "fdc-packet-badge", children: "Repaired" }) : null,
11849
- invalid ? /* @__PURE__ */ jsx90("span", { className: "fdc-packet-badge is-danger", children: "Invalid" }) : null
12081
+ return /* @__PURE__ */ jsxs82("section", { className: "fdc-packet" + (invalid ? " is-invalid" : ""), "aria-label": title, children: [
12082
+ /* @__PURE__ */ jsxs82("header", { className: "fdc-packet-head", children: [
12083
+ /* @__PURE__ */ jsx91("i", { className: "ph ph-" + (s.icon || "package"), "aria-hidden": "true" }),
12084
+ /* @__PURE__ */ jsx91("span", { className: "fdc-packet-title", title: truncationTitle(title), children: title }),
12085
+ packet.repaired ? /* @__PURE__ */ jsx91("span", { className: "fdc-packet-badge", children: "Repaired" }) : null,
12086
+ invalid ? /* @__PURE__ */ jsx91("span", { className: "fdc-packet-badge is-danger", children: "Invalid" }) : null
11850
12087
  ] }),
11851
- invalid ? /* @__PURE__ */ jsxs81("div", { className: "fdc-packet-alert", role: "alert", children: [
11852
- /* @__PURE__ */ jsx90("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
11853
- /* @__PURE__ */ jsx90("span", { children: packet.error || "This result failed validation and can\u2019t be applied." })
11854
- ] }) : /* @__PURE__ */ jsx90("div", { className: "fdc-packet-body", children: render ? render(packet) : /* @__PURE__ */ jsx90(JsonView, { value: packet.payload }) }),
11855
- !invalid && onApply ? /* @__PURE__ */ jsxs81("footer", { className: "fdc-packet-foot", children: [
11856
- packet.repaired ? /* @__PURE__ */ jsx90("span", { className: "fdc-packet-note", children: "Corrected by the backend after a first attempt." }) : /* @__PURE__ */ jsx90("span", {}),
11857
- /* @__PURE__ */ jsxs81("button", { type: "button", className: "fd-btn fd-btn-primary fd-btn-sm", disabled: applied, onClick: () => onApply(packet), children: [
11858
- /* @__PURE__ */ jsx90("i", { className: "ph ph-" + (applied ? "check" : "arrow-square-in"), "aria-hidden": "true" }),
12088
+ invalid ? /* @__PURE__ */ jsxs82("div", { className: "fdc-packet-alert", role: "alert", children: [
12089
+ /* @__PURE__ */ jsx91("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
12090
+ /* @__PURE__ */ jsx91("span", { children: packet.error || "This result failed validation and can\u2019t be applied." })
12091
+ ] }) : /* @__PURE__ */ jsx91("div", { className: "fdc-packet-body", children: render ? render(packet) : /* @__PURE__ */ jsx91(JsonView, { value: packet.payload }) }),
12092
+ !invalid && onApply ? /* @__PURE__ */ jsxs82("footer", { className: "fdc-packet-foot", children: [
12093
+ packet.repaired ? /* @__PURE__ */ jsx91("span", { className: "fdc-packet-note", children: "Corrected by the backend after a first attempt." }) : /* @__PURE__ */ jsx91("span", {}),
12094
+ /* @__PURE__ */ jsxs82("button", { type: "button", className: "fd-btn fd-btn-primary fd-btn-sm", disabled: applied, onClick: () => onApply(packet), children: [
12095
+ /* @__PURE__ */ jsx91("i", { className: "ph ph-" + (applied ? "check" : "arrow-square-in"), "aria-hidden": "true" }),
11859
12096
  applied ? "Applied" : s.applyLabel || "Apply"
11860
12097
  ] })
11861
12098
  ] }) : null
11862
12099
  ] });
11863
12100
  }
11864
12101
  function ThinkingBlock({ text, durationMs, streaming, defaultOpen = false }) {
11865
- const [open2, setOpen] = React59.useState(defaultOpen);
12102
+ const [open2, setOpen] = React60.useState(defaultOpen);
11866
12103
  if (!text) return null;
11867
- return /* @__PURE__ */ jsxs81("div", { className: "fdc-think" + (open2 ? " is-open" : ""), children: [
11868
- /* @__PURE__ */ jsxs81("button", { type: "button", className: "fdc-think-head", onClick: () => setOpen((v) => !v), "aria-expanded": open2, children: [
11869
- /* @__PURE__ */ jsx90("i", { className: "ph ph-brain", "aria-hidden": "true" }),
11870
- /* @__PURE__ */ jsx90("span", { children: streaming ? "Thinking" : durationMs ? "Thought for " + formatDuration(durationMs) : "Thought process" }),
11871
- streaming ? /* @__PURE__ */ jsxs81("span", { className: "fdc-dots", "aria-hidden": "true", children: [
11872
- /* @__PURE__ */ jsx90("span", {}),
11873
- /* @__PURE__ */ jsx90("span", {}),
11874
- /* @__PURE__ */ jsx90("span", {})
12104
+ return /* @__PURE__ */ jsxs82("div", { className: "fdc-think" + (open2 ? " is-open" : ""), children: [
12105
+ /* @__PURE__ */ jsxs82("button", { type: "button", className: "fdc-think-head", onClick: () => setOpen((v) => !v), "aria-expanded": open2, children: [
12106
+ /* @__PURE__ */ jsx91("i", { className: "ph ph-brain", "aria-hidden": "true" }),
12107
+ /* @__PURE__ */ jsx91("span", { children: streaming ? "Thinking" : durationMs ? "Thought for " + formatDuration(durationMs) : "Thought process" }),
12108
+ streaming ? /* @__PURE__ */ jsxs82("span", { className: "fdc-dots", "aria-hidden": "true", children: [
12109
+ /* @__PURE__ */ jsx91("span", {}),
12110
+ /* @__PURE__ */ jsx91("span", {}),
12111
+ /* @__PURE__ */ jsx91("span", {})
11875
12112
  ] }) : null,
11876
- /* @__PURE__ */ jsx90("i", { className: "ph ph-caret-" + (open2 ? "up" : "down"), "aria-hidden": "true" })
12113
+ /* @__PURE__ */ jsx91("i", { className: "ph ph-caret-" + (open2 ? "up" : "down"), "aria-hidden": "true" })
11877
12114
  ] }),
11878
- open2 ? /* @__PURE__ */ jsx90("div", { className: "fdc-think-body", children: text }) : null
12115
+ open2 ? /* @__PURE__ */ jsx91("div", { className: "fdc-think-body", children: text }) : null
11879
12116
  ] });
11880
12117
  }
11881
12118
  function Citations({ items = [], onOpen }) {
11882
- const [open2, setOpen] = React59.useState(false);
12119
+ const [open2, setOpen] = React60.useState(false);
11883
12120
  if (!items.length) return null;
11884
- return /* @__PURE__ */ jsxs81("div", { className: "fdc-cites", children: [
11885
- /* @__PURE__ */ jsxs81("button", { type: "button", className: "fdc-cites-head", onClick: () => setOpen((v) => !v), "aria-expanded": open2, children: [
11886
- /* @__PURE__ */ jsx90("i", { className: "ph ph-quotes", "aria-hidden": "true" }),
11887
- /* @__PURE__ */ jsxs81("span", { children: [
12121
+ return /* @__PURE__ */ jsxs82("div", { className: "fdc-cites", children: [
12122
+ /* @__PURE__ */ jsxs82("button", { type: "button", className: "fdc-cites-head", onClick: () => setOpen((v) => !v), "aria-expanded": open2, children: [
12123
+ /* @__PURE__ */ jsx91("i", { className: "ph ph-quotes", "aria-hidden": "true" }),
12124
+ /* @__PURE__ */ jsxs82("span", { children: [
11888
12125
  items.length,
11889
12126
  " source",
11890
12127
  items.length === 1 ? "" : "s"
11891
12128
  ] }),
11892
- /* @__PURE__ */ jsx90("i", { className: "ph ph-caret-" + (open2 ? "up" : "down"), "aria-hidden": "true" })
12129
+ /* @__PURE__ */ jsx91("i", { className: "ph ph-caret-" + (open2 ? "up" : "down"), "aria-hidden": "true" })
11893
12130
  ] }),
11894
- open2 ? /* @__PURE__ */ jsx90("ol", { className: "fdc-cites-list", children: items.map((c, i) => /* @__PURE__ */ jsxs81("li", { children: [
11895
- /* @__PURE__ */ jsx90("span", { className: "fdc-cite-n fd-tabular", children: c.marker || i + 1 }),
11896
- c.url ? /* @__PURE__ */ jsx90("a", { href: c.url, target: "_blank", rel: "noopener noreferrer", onClick: onOpen ? (e) => onOpen(c, e) : void 0, children: c.title || c.url }) : /* @__PURE__ */ jsx90("span", { children: c.title || "Source" }),
11897
- c.detail ? /* @__PURE__ */ jsx90("span", { className: "fdc-cite-detail", children: c.detail }) : null
12131
+ open2 ? /* @__PURE__ */ jsx91("ol", { className: "fdc-cites-list", children: items.map((c, i) => /* @__PURE__ */ jsxs82("li", { children: [
12132
+ /* @__PURE__ */ jsx91("span", { className: "fdc-cite-n fd-tabular", children: c.marker || i + 1 }),
12133
+ c.url ? /* @__PURE__ */ jsx91("a", { href: c.url, target: "_blank", rel: "noopener noreferrer", onClick: onOpen ? (e) => onOpen(c, e) : void 0, children: c.title || c.url }) : /* @__PURE__ */ jsx91("span", { children: c.title || "Source" }),
12134
+ c.detail ? /* @__PURE__ */ jsx91("span", { className: "fdc-cite-detail", children: c.detail }) : null
11898
12135
  ] }, c.id || i)) }) : null
11899
12136
  ] });
11900
12137
  }
@@ -11905,29 +12142,29 @@ function clampText(text, max) {
11905
12142
  return (at > max * 0.6 ? cut.slice(0, at) : cut).trimEnd() + "\u2026";
11906
12143
  }
11907
12144
  function MessageBody({ message: m, ctx }) {
11908
- const [expanded, setExpanded] = React59.useState(false);
12145
+ const [expanded, setExpanded] = React60.useState(false);
11909
12146
  const isUser = m.role === "user";
11910
12147
  const raw = m.text || "";
11911
12148
  const clamped = !expanded && !m.streaming ? clampText(raw, ctx.maxVisibleChars) : null;
11912
12149
  const body = clamped != null ? clamped : raw;
11913
12150
  const showMd = ctx.markdown && !isUser;
11914
- return /* @__PURE__ */ jsxs81("div", { className: "fdc-body", children: [
11915
- m.thinking && ctx.showThinking ? /* @__PURE__ */ jsx90(ThinkingBlock, { text: m.thinking, durationMs: m.thinkingMs, streaming: m.streaming && !m.text }) : null,
11916
- m.steps && m.steps.length && ctx.showSteps ? /* @__PURE__ */ jsx90(StepList, { steps: m.steps, defaultOpen: m.steps.some((s) => s.status === "running"), dense: true }) : null,
11917
- body ? /* @__PURE__ */ jsxs81("div", { className: "fdc-text" + (isUser ? " is-user" : ""), children: [
11918
- showMd ? /* @__PURE__ */ jsx90(Markdown, { source: body, headingOffset: 2, codeProps: { collapseAfter: 22 }, renderCitation: ctx.renderCitation }) : /* @__PURE__ */ jsx90("div", { className: "fdc-plain", children: body }),
11919
- m.streaming ? /* @__PURE__ */ jsx90("span", { className: "fdc-caret", "aria-hidden": "true" }) : null
12151
+ return /* @__PURE__ */ jsxs82("div", { className: "fdc-body", children: [
12152
+ m.thinking && ctx.showThinking ? /* @__PURE__ */ jsx91(ThinkingBlock, { text: m.thinking, durationMs: m.thinkingMs, streaming: m.streaming && !m.text }) : null,
12153
+ m.steps && m.steps.length && ctx.showSteps ? /* @__PURE__ */ jsx91(StepList, { steps: m.steps, defaultOpen: m.steps.some((s) => s.status === "running"), dense: true }) : null,
12154
+ body ? /* @__PURE__ */ jsxs82("div", { className: "fdc-text" + (isUser ? " is-user" : ""), children: [
12155
+ showMd ? /* @__PURE__ */ jsx91(Markdown, { source: body, headingOffset: 2, codeProps: { collapseAfter: 22 }, renderCitation: ctx.renderCitation }) : /* @__PURE__ */ jsx91("div", { className: "fdc-plain", children: body }),
12156
+ m.streaming ? /* @__PURE__ */ jsx91("span", { className: "fdc-caret", "aria-hidden": "true" }) : null
11920
12157
  ] }) : null,
11921
- clamped != null ? /* @__PURE__ */ jsxs81("button", { type: "button", className: "fdc-more", onClick: () => setExpanded(true), children: [
11922
- /* @__PURE__ */ jsx90("i", { className: "ph ph-caret-down", "aria-hidden": "true" }),
12158
+ clamped != null ? /* @__PURE__ */ jsxs82("button", { type: "button", className: "fdc-more", onClick: () => setExpanded(true), children: [
12159
+ /* @__PURE__ */ jsx91("i", { className: "ph ph-caret-down", "aria-hidden": "true" }),
11923
12160
  "Show more",
11924
- /* @__PURE__ */ jsx90("span", { className: "fdc-more-len fd-tabular", children: raw.length < 2e3 ? raw.length.toLocaleString() + " characters" : Math.round(raw.length / 100) / 10 + "k characters" })
11925
- ] }) : expanded && ctx.maxVisibleChars && raw.length > ctx.maxVisibleChars ? /* @__PURE__ */ jsxs81("button", { type: "button", className: "fdc-more", onClick: () => setExpanded(false), children: [
11926
- /* @__PURE__ */ jsx90("i", { className: "ph ph-caret-up", "aria-hidden": "true" }),
12161
+ /* @__PURE__ */ jsx91("span", { className: "fdc-more-len fd-tabular", children: raw.length < 2e3 ? raw.length.toLocaleString() + " characters" : Math.round(raw.length / 100) / 10 + "k characters" })
12162
+ ] }) : expanded && ctx.maxVisibleChars && raw.length > ctx.maxVisibleChars ? /* @__PURE__ */ jsxs82("button", { type: "button", className: "fdc-more", onClick: () => setExpanded(false), children: [
12163
+ /* @__PURE__ */ jsx91("i", { className: "ph ph-caret-up", "aria-hidden": "true" }),
11927
12164
  "Show less"
11928
12165
  ] }) : null,
11929
- m.attachments && m.attachments.length ? /* @__PURE__ */ jsx90(FileGrid, { files: m.attachments, onOpen: ctx.onOpenAttachment, tiles: true, maxHeight: ctx.attachmentHeight || 220, compact: ctx.narrow }) : null,
11930
- m.packet ? /* @__PURE__ */ jsx90(
12166
+ m.attachments && m.attachments.length ? /* @__PURE__ */ jsx91(FileGrid, { files: m.attachments, onOpen: ctx.onOpenAttachment, tiles: true, maxHeight: ctx.attachmentHeight || 220, compact: ctx.narrow }) : null,
12167
+ m.packet ? /* @__PURE__ */ jsx91(
11931
12168
  PacketCard,
11932
12169
  {
11933
12170
  packet: m.packet,
@@ -11937,44 +12174,44 @@ function MessageBody({ message: m, ctx }) {
11937
12174
  applied: ctx.appliedPackets && ctx.appliedPackets[m.id]
11938
12175
  }
11939
12176
  ) : null,
11940
- m.citations && m.citations.length ? /* @__PURE__ */ jsx90(Citations, { items: m.citations, onOpen: ctx.onOpenCitation }) : null,
11941
- m.working ? /* @__PURE__ */ jsxs81("div", { className: "fdc-working", role: "status", children: [
11942
- /* @__PURE__ */ jsxs81("span", { className: "fdc-dots", "aria-hidden": "true", children: [
11943
- /* @__PURE__ */ jsx90("span", {}),
11944
- /* @__PURE__ */ jsx90("span", {}),
11945
- /* @__PURE__ */ jsx90("span", {})
12177
+ m.citations && m.citations.length ? /* @__PURE__ */ jsx91(Citations, { items: m.citations, onOpen: ctx.onOpenCitation }) : null,
12178
+ m.working ? /* @__PURE__ */ jsxs82("div", { className: "fdc-working", role: "status", children: [
12179
+ /* @__PURE__ */ jsxs82("span", { className: "fdc-dots", "aria-hidden": "true", children: [
12180
+ /* @__PURE__ */ jsx91("span", {}),
12181
+ /* @__PURE__ */ jsx91("span", {}),
12182
+ /* @__PURE__ */ jsx91("span", {})
11946
12183
  ] }),
11947
- /* @__PURE__ */ jsxs81("span", { className: "fdc-working-label", children: [
12184
+ /* @__PURE__ */ jsxs82("span", { className: "fdc-working-label", children: [
11948
12185
  m.resumed ? "Resuming" : "Working",
11949
- m.job && m.job.status ? /* @__PURE__ */ jsxs81("span", { className: "fdc-working-job", children: [
12186
+ m.job && m.job.status ? /* @__PURE__ */ jsxs82("span", { className: "fdc-working-job", children: [
11950
12187
  " \xB7 ",
11951
12188
  m.job.status
11952
12189
  ] }) : null,
11953
- m.job && m.job.detail ? /* @__PURE__ */ jsxs81("span", { className: "fdc-working-job", children: [
12190
+ m.job && m.job.detail ? /* @__PURE__ */ jsxs82("span", { className: "fdc-working-job", children: [
11954
12191
  " \xB7 ",
11955
12192
  m.job.detail
11956
12193
  ] }) : null
11957
12194
  ] }),
11958
- m.jobId ? /* @__PURE__ */ jsx90("span", { className: "fdc-working-id fd-mono", children: String(m.jobId).slice(0, 12) }) : null
12195
+ m.jobId ? /* @__PURE__ */ jsx91("span", { className: "fdc-working-id fd-mono", children: String(m.jobId).slice(0, 12) }) : null
11959
12196
  ] }) : null,
11960
- m.stopped ? /* @__PURE__ */ jsxs81("div", { className: "fdc-stopped", children: [
11961
- /* @__PURE__ */ jsx90("i", { className: "ph ph-stop-circle", "aria-hidden": "true" }),
12197
+ m.stopped ? /* @__PURE__ */ jsxs82("div", { className: "fdc-stopped", children: [
12198
+ /* @__PURE__ */ jsx91("i", { className: "ph ph-stop-circle", "aria-hidden": "true" }),
11962
12199
  "Stopped"
11963
12200
  ] }) : null,
11964
- m.error ? /* @__PURE__ */ jsxs81("div", { className: "fdc-error", role: "alert", children: [
11965
- /* @__PURE__ */ jsx90("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
11966
- /* @__PURE__ */ jsx90("span", { className: "fdc-error-text", children: ctx.errorCopy ? ctx.errorCopy(m.error) : m.error }),
11967
- m.retryable && ctx.onRetry ? /* @__PURE__ */ jsxs81("button", { type: "button", className: "fdc-error-retry", onClick: ctx.onRetry, children: [
11968
- /* @__PURE__ */ jsx90("i", { className: "ph ph-arrow-clockwise", "aria-hidden": "true" }),
12201
+ m.error ? /* @__PURE__ */ jsxs82("div", { className: "fdc-error", role: "alert", children: [
12202
+ /* @__PURE__ */ jsx91("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
12203
+ /* @__PURE__ */ jsx91("span", { className: "fdc-error-text", children: ctx.errorCopy ? ctx.errorCopy(m.error) : m.error }),
12204
+ m.retryable && ctx.onRetry ? /* @__PURE__ */ jsxs82("button", { type: "button", className: "fdc-error-retry", onClick: ctx.onRetry, children: [
12205
+ /* @__PURE__ */ jsx91("i", { className: "ph ph-arrow-clockwise", "aria-hidden": "true" }),
11969
12206
  "Retry"
11970
12207
  ] }) : null
11971
12208
  ] }) : null
11972
12209
  ] });
11973
12210
  }
11974
12211
  function useCopyRun() {
11975
- const [done, setDone] = React59.useState(false);
11976
- const t = React59.useRef(null);
11977
- React59.useEffect(() => () => {
12212
+ const [done, setDone] = React60.useState(false);
12213
+ const t = React60.useRef(null);
12214
+ React60.useEffect(() => () => {
11978
12215
  if (t.current) clearTimeout(t.current);
11979
12216
  }, []);
11980
12217
  return [done, (text) => {
@@ -11994,16 +12231,16 @@ function RunActions({ group, ctx }) {
11994
12231
  const isAssistant = group.role === "assistant";
11995
12232
  const fb = last.feedback;
11996
12233
  if (!ctx.messageActions) return null;
11997
- return /* @__PURE__ */ jsxs81("div", { className: "fdc-actions", role: "group", "aria-label": "Message actions", children: [
11998
- /* @__PURE__ */ jsxs81("button", { type: "button", className: "fdc-act" + (copied ? " is-done" : ""), onClick: () => copy(markdownToText(text)), "aria-label": "Copy message", children: [
11999
- /* @__PURE__ */ jsx90("i", { className: "ph ph-" + (copied ? "check" : "copy"), "aria-hidden": "true" }),
12000
- /* @__PURE__ */ jsx90("span", { className: "fdc-act-label", children: copied ? "Copied" : "Copy" })
12234
+ return /* @__PURE__ */ jsxs82("div", { className: "fdc-actions", role: "group", "aria-label": "Message actions", children: [
12235
+ /* @__PURE__ */ jsxs82("button", { type: "button", className: "fdc-act" + (copied ? " is-done" : ""), onClick: () => copy(markdownToText(text)), "aria-label": "Copy message", children: [
12236
+ /* @__PURE__ */ jsx91("i", { className: "ph ph-" + (copied ? "check" : "copy"), "aria-hidden": "true" }),
12237
+ /* @__PURE__ */ jsx91("span", { className: "fdc-act-label", children: copied ? "Copied" : "Copy" })
12001
12238
  ] }),
12002
- isAssistant && ctx.onRetry ? /* @__PURE__ */ jsx90("button", { type: "button", className: "fdc-act", onClick: ctx.onRetry, "aria-label": "Retry this turn", children: /* @__PURE__ */ jsx90("i", { className: "ph ph-arrow-clockwise", "aria-hidden": "true" }) }) : null,
12003
- group.role === "user" && ctx.onEdit ? /* @__PURE__ */ jsx90("button", { type: "button", className: "fdc-act", onClick: () => ctx.onEdit(last), "aria-label": "Edit and resend", children: /* @__PURE__ */ jsx90("i", { className: "ph ph-pencil-simple", "aria-hidden": "true" }) }) : null,
12004
- isAssistant && ctx.onFeedback ? /* @__PURE__ */ jsxs81(React59.Fragment, { children: [
12005
- /* @__PURE__ */ jsx90("button", { type: "button", className: "fdc-act" + (fb === "up" ? " is-on" : ""), onClick: () => ctx.onFeedback(last.id, "up"), "aria-pressed": fb === "up", "aria-label": "Good response", children: /* @__PURE__ */ jsx90("i", { className: "ph ph-thumbs-up", "aria-hidden": "true" }) }),
12006
- /* @__PURE__ */ jsx90("button", { type: "button", className: "fdc-act" + (fb === "down" ? " is-on" : ""), onClick: () => ctx.onFeedback(last.id, "down"), "aria-pressed": fb === "down", "aria-label": "Bad response", children: /* @__PURE__ */ jsx90("i", { className: "ph ph-thumbs-down", "aria-hidden": "true" }) })
12239
+ isAssistant && ctx.onRetry ? /* @__PURE__ */ jsx91("button", { type: "button", className: "fdc-act", onClick: ctx.onRetry, "aria-label": "Retry this turn", children: /* @__PURE__ */ jsx91("i", { className: "ph ph-arrow-clockwise", "aria-hidden": "true" }) }) : null,
12240
+ group.role === "user" && ctx.onEdit ? /* @__PURE__ */ jsx91("button", { type: "button", className: "fdc-act", onClick: () => ctx.onEdit(last), "aria-label": "Edit and resend", children: /* @__PURE__ */ jsx91("i", { className: "ph ph-pencil-simple", "aria-hidden": "true" }) }) : null,
12241
+ isAssistant && ctx.onFeedback ? /* @__PURE__ */ jsxs82(React60.Fragment, { children: [
12242
+ /* @__PURE__ */ jsx91("button", { type: "button", className: "fdc-act" + (fb === "up" ? " is-on" : ""), onClick: () => ctx.onFeedback(last.id, "up"), "aria-pressed": fb === "up", "aria-label": "Good response", children: /* @__PURE__ */ jsx91("i", { className: "ph ph-thumbs-up", "aria-hidden": "true" }) }),
12243
+ /* @__PURE__ */ jsx91("button", { type: "button", className: "fdc-act" + (fb === "down" ? " is-on" : ""), onClick: () => ctx.onFeedback(last.id, "down"), "aria-pressed": fb === "down", "aria-label": "Bad response", children: /* @__PURE__ */ jsx91("i", { className: "ph ph-thumbs-down", "aria-hidden": "true" }) })
12007
12244
  ] }) : null,
12008
12245
  ctx.extraActions ? ctx.extraActions(group) : null
12009
12246
  ] });
@@ -12013,22 +12250,22 @@ function ChatTurn({ group, ctx }) {
12013
12250
  const name = isUser ? ctx.userName : group.author || ctx.assistantName;
12014
12251
  const avatar = isUser ? ctx.userAvatar : ctx.assistantAvatar;
12015
12252
  const stamp = group.messages[0].timestamp;
12016
- return /* @__PURE__ */ jsxs81("article", { className: "fdc-turn is-" + group.role, "aria-label": String(name) + (stamp ? " at " + formatClock(stamp) : ""), children: [
12017
- /* @__PURE__ */ jsxs81("div", { className: "fdc-turn-head", children: [
12018
- ctx.showAvatars ? /* @__PURE__ */ jsx90("span", { className: "fdc-avatar is-" + group.role, "aria-hidden": "true", children: avatar ? /* @__PURE__ */ jsx90("img", { src: avatar, alt: "" }) : isUser ? /* @__PURE__ */ jsx90("span", { className: "fdc-avatar-txt", children: (name || "You").slice(0, 1).toUpperCase() }) : /* @__PURE__ */ jsx90("i", { className: "ph ph-" + (ctx.assistantIcon || "sparkle") }) }) : null,
12019
- /* @__PURE__ */ jsx90("span", { className: "fdc-who", children: name }),
12020
- stamp ? /* @__PURE__ */ jsx90(RelativeTime, { className: "fdc-when", value: stamp }) : null,
12021
- group.messages.some((m) => m.model) ? /* @__PURE__ */ jsx90("span", { className: "fdc-turn-model", children: group.messages.find((m) => m.model).model }) : null
12253
+ return /* @__PURE__ */ jsxs82("article", { className: "fdc-turn is-" + group.role, "aria-label": String(name) + (stamp ? " at " + formatClock(stamp) : ""), children: [
12254
+ /* @__PURE__ */ jsxs82("div", { className: "fdc-turn-head", children: [
12255
+ ctx.showAvatars ? /* @__PURE__ */ jsx91("span", { className: "fdc-avatar is-" + group.role, "aria-hidden": "true", children: avatar ? /* @__PURE__ */ jsx91("img", { src: avatar, alt: "" }) : isUser ? /* @__PURE__ */ jsx91("span", { className: "fdc-avatar-txt", children: (name || "You").slice(0, 1).toUpperCase() }) : /* @__PURE__ */ jsx91("i", { className: "ph ph-" + (ctx.assistantIcon || "sparkle") }) }) : null,
12256
+ /* @__PURE__ */ jsx91("span", { className: "fdc-who", children: name }),
12257
+ stamp ? /* @__PURE__ */ jsx91(RelativeTime, { className: "fdc-when", value: stamp }) : null,
12258
+ group.messages.some((m) => m.model) ? /* @__PURE__ */ jsx91("span", { className: "fdc-turn-model", children: group.messages.find((m) => m.model).model }) : null
12022
12259
  ] }),
12023
- /* @__PURE__ */ jsxs81("div", { className: "fdc-turn-body", children: [
12024
- group.messages.map((m) => /* @__PURE__ */ jsx90("div", { className: "fdc-msg" + (m.pending ? " is-pending" : ""), children: /* @__PURE__ */ jsx90(MessageBody, { message: m, ctx }) }, m.id)),
12025
- /* @__PURE__ */ jsx90(RunActions, { group, ctx })
12260
+ /* @__PURE__ */ jsxs82("div", { className: "fdc-turn-body", children: [
12261
+ group.messages.map((m) => /* @__PURE__ */ jsx91("div", { className: "fdc-msg" + (m.pending ? " is-pending" : ""), children: /* @__PURE__ */ jsx91(MessageBody, { message: m, ctx }) }, m.id)),
12262
+ /* @__PURE__ */ jsx91(RunActions, { group, ctx })
12026
12263
  ] })
12027
12264
  ] });
12028
12265
  }
12029
12266
 
12030
12267
  // src/components/chat/ChatTranscript.tsx
12031
- import { jsx as jsx91, jsxs as jsxs82 } from "react/jsx-runtime";
12268
+ import { jsx as jsx92, jsxs as jsxs83 } from "react/jsx-runtime";
12032
12269
  var GROUP_WINDOW = 6e4;
12033
12270
  var STICK_PX = 100;
12034
12271
  function groupMessages(list) {
@@ -12061,25 +12298,25 @@ function dayLabel(key) {
12061
12298
  }
12062
12299
  function Suggestions({ items = [], onPick }) {
12063
12300
  if (!items.length) return null;
12064
- return /* @__PURE__ */ jsx91("div", { className: "fdc-suggest", children: items.map((s, i) => {
12301
+ return /* @__PURE__ */ jsx92("div", { className: "fdc-suggest", children: items.map((s, i) => {
12065
12302
  const it = typeof s === "string" ? { label: s, text: s } : s;
12066
- return /* @__PURE__ */ jsxs82("button", { type: "button", className: "fdc-suggest-item", onClick: () => onPick && onPick(it.text || it.label), children: [
12067
- it.icon ? /* @__PURE__ */ jsx91("i", { className: "ph ph-" + it.icon, "aria-hidden": "true" }) : null,
12068
- /* @__PURE__ */ jsxs82("span", { className: "fdc-suggest-text", children: [
12069
- /* @__PURE__ */ jsx91("span", { className: "fdc-suggest-label", children: it.label }),
12070
- it.description ? /* @__PURE__ */ jsx91("span", { className: "fdc-suggest-desc", children: it.description }) : null
12303
+ return /* @__PURE__ */ jsxs83("button", { type: "button", className: "fdc-suggest-item", onClick: () => onPick && onPick(it.text || it.label), children: [
12304
+ it.icon ? /* @__PURE__ */ jsx92("i", { className: "ph ph-" + it.icon, "aria-hidden": "true" }) : null,
12305
+ /* @__PURE__ */ jsxs83("span", { className: "fdc-suggest-text", children: [
12306
+ /* @__PURE__ */ jsx92("span", { className: "fdc-suggest-label", children: it.label }),
12307
+ it.description ? /* @__PURE__ */ jsx92("span", { className: "fdc-suggest-desc", children: it.description }) : null
12071
12308
  ] }),
12072
- /* @__PURE__ */ jsx91("i", { className: "ph ph-arrow-up-right fdc-suggest-go", "aria-hidden": "true" })
12309
+ /* @__PURE__ */ jsx92("i", { className: "ph ph-arrow-up-right fdc-suggest-go", "aria-hidden": "true" })
12073
12310
  ] }, it.id || i);
12074
12311
  }) });
12075
12312
  }
12076
12313
  function LoadingTurns() {
12077
- return /* @__PURE__ */ jsx91("div", { className: "fdc-skel", "aria-hidden": "true", children: [0, 1].map((i) => /* @__PURE__ */ jsxs82("div", { className: "fdc-skel-turn", children: [
12078
- /* @__PURE__ */ jsx91("div", { className: "fd-skel fd-skel-circle", style: { width: 22, height: 22 } }),
12079
- /* @__PURE__ */ jsxs82("div", { className: "fdc-skel-lines", children: [
12080
- /* @__PURE__ */ jsx91("div", { className: "fd-skel", style: { width: i ? "62%" : "44%", height: 11 } }),
12081
- /* @__PURE__ */ jsx91("div", { className: "fd-skel", style: { width: i ? "94%" : "78%", height: 11 } }),
12082
- /* @__PURE__ */ jsx91("div", { className: "fd-skel", style: { width: i ? "71%" : "56%", height: 11 } })
12314
+ return /* @__PURE__ */ jsx92("div", { className: "fdc-skel", "aria-hidden": "true", children: [0, 1].map((i) => /* @__PURE__ */ jsxs83("div", { className: "fdc-skel-turn", children: [
12315
+ /* @__PURE__ */ jsx92("div", { className: "fd-skel fd-skel-circle", style: { width: 22, height: 22 } }),
12316
+ /* @__PURE__ */ jsxs83("div", { className: "fdc-skel-lines", children: [
12317
+ /* @__PURE__ */ jsx92("div", { className: "fd-skel", style: { width: i ? "62%" : "44%", height: 11 } }),
12318
+ /* @__PURE__ */ jsx92("div", { className: "fd-skel", style: { width: i ? "94%" : "78%", height: 11 } }),
12319
+ /* @__PURE__ */ jsx92("div", { className: "fd-skel", style: { width: i ? "71%" : "56%", height: 11 } })
12083
12320
  ] })
12084
12321
  ] }, i)) });
12085
12322
  }
@@ -12096,10 +12333,10 @@ function ChatTranscript({
12096
12333
  renderEmpty,
12097
12334
  className = ""
12098
12335
  }) {
12099
- const scroller = React60.useRef(null);
12100
- const stick = React60.useRef(true);
12101
- const [pill, setPill] = React60.useState(0);
12102
- const seen = React60.useRef(0);
12336
+ const scroller = React61.useRef(null);
12337
+ const stick = React61.useRef(true);
12338
+ const [pill, setPill] = React61.useState(0);
12339
+ const seen = React61.useRef(0);
12103
12340
  const toBottom = (smooth) => {
12104
12341
  const el = scroller.current;
12105
12342
  if (!el) return;
@@ -12118,7 +12355,7 @@ function ChatTranscript({
12118
12355
  seen.current = messages.length;
12119
12356
  }
12120
12357
  };
12121
- React60.useLayoutEffect(() => {
12358
+ React61.useLayoutEffect(() => {
12122
12359
  const el = scroller.current;
12123
12360
  if (!el) return;
12124
12361
  if (stick.current) {
@@ -12126,7 +12363,7 @@ function ChatTranscript({
12126
12363
  seen.current = messages.length;
12127
12364
  } else setPill(Math.max(0, messages.length - seen.current));
12128
12365
  }, [messages]);
12129
- React60.useEffect(() => {
12366
+ React61.useEffect(() => {
12130
12367
  const el = scroller.current;
12131
12368
  const inner = el && el.firstChild;
12132
12369
  if (!el || !inner || typeof ResizeObserver === "undefined") return;
@@ -12136,38 +12373,38 @@ function ChatTranscript({
12136
12373
  ro.observe(inner);
12137
12374
  return () => ro.disconnect();
12138
12375
  }, []);
12139
- const groups = React60.useMemo(() => groupMessages(messages), [messages]);
12376
+ const groups = React61.useMemo(() => groupMessages(messages), [messages]);
12140
12377
  const empty = !messages.length && status === "ready";
12141
- return /* @__PURE__ */ jsxs82("div", { className: ["fdc-scroll", className].filter(Boolean).join(" "), ref: scroller, onScroll, children: [
12142
- /* @__PURE__ */ jsxs82("div", { className: "fdc-log", role: "log", "aria-label": "Conversation", children: [
12143
- status === "loading" || status === "resolving" ? /* @__PURE__ */ jsx91(LoadingTurns, {}) : null,
12144
- status === "disconnected" ? /* @__PURE__ */ jsxs82("div", { className: "fdc-dead", children: [
12145
- /* @__PURE__ */ jsx91("span", { className: "fdc-dead-icon", children: /* @__PURE__ */ jsx91("i", { className: "ph ph-plugs", "aria-hidden": "true" }) }),
12146
- /* @__PURE__ */ jsx91("h3", { className: "fdc-dead-title", children: ctx.deadTitle || "The assistant isn\u2019t reachable" }),
12147
- /* @__PURE__ */ jsx91("p", { className: "fdc-dead-body", children: fatal === "chat_unavailable" ? "The service reported chat_unavailable. Nothing you type will be lost \u2014 reopen the panel once it\u2019s back." : "The thread couldn\u2019t be resolved" + (fatal ? " (" + fatal + ")" : "") + ". The composer stays disabled until it resolves." }),
12148
- ctx.onReconnect ? /* @__PURE__ */ jsxs82("button", { type: "button", className: "fd-btn fd-btn-secondary fd-btn-sm", onClick: ctx.onReconnect, children: [
12149
- /* @__PURE__ */ jsx91("i", { className: "ph ph-arrow-clockwise", "aria-hidden": "true" }),
12378
+ return /* @__PURE__ */ jsxs83("div", { className: ["fdc-scroll", className].filter(Boolean).join(" "), ref: scroller, onScroll, children: [
12379
+ /* @__PURE__ */ jsxs83("div", { className: "fdc-log", role: "log", "aria-label": "Conversation", children: [
12380
+ status === "loading" || status === "resolving" ? /* @__PURE__ */ jsx92(LoadingTurns, {}) : null,
12381
+ status === "disconnected" ? /* @__PURE__ */ jsxs83("div", { className: "fdc-dead", children: [
12382
+ /* @__PURE__ */ jsx92("span", { className: "fdc-dead-icon", children: /* @__PURE__ */ jsx92("i", { className: "ph ph-plugs", "aria-hidden": "true" }) }),
12383
+ /* @__PURE__ */ jsx92("h3", { className: "fdc-dead-title", children: ctx.deadTitle || "The assistant isn\u2019t reachable" }),
12384
+ /* @__PURE__ */ jsx92("p", { className: "fdc-dead-body", children: fatal === "chat_unavailable" ? "The service reported chat_unavailable. Nothing you type will be lost \u2014 reopen the panel once it\u2019s back." : "The thread couldn\u2019t be resolved" + (fatal ? " (" + fatal + ")" : "") + ". The composer stays disabled until it resolves." }),
12385
+ ctx.onReconnect ? /* @__PURE__ */ jsxs83("button", { type: "button", className: "fd-btn fd-btn-secondary fd-btn-sm", onClick: ctx.onReconnect, children: [
12386
+ /* @__PURE__ */ jsx92("i", { className: "ph ph-arrow-clockwise", "aria-hidden": "true" }),
12150
12387
  "Try again"
12151
12388
  ] }) : null
12152
12389
  ] }) : null,
12153
- empty ? renderEmpty ? renderEmpty() : /* @__PURE__ */ jsxs82("div", { className: "fdc-empty", children: [
12154
- /* @__PURE__ */ jsx91("span", { className: "fdc-empty-icon", children: /* @__PURE__ */ jsx91("i", { className: "ph ph-" + emptyIcon, "aria-hidden": "true" }) }),
12155
- /* @__PURE__ */ jsx91("h3", { className: "fdc-empty-title", children: emptyTitle }),
12156
- emptyDescription ? /* @__PURE__ */ jsx91("p", { className: "fdc-empty-body", children: emptyDescription }) : null,
12157
- /* @__PURE__ */ jsx91(Suggestions, { items: suggestions, onPick })
12390
+ empty ? renderEmpty ? renderEmpty() : /* @__PURE__ */ jsxs83("div", { className: "fdc-empty", children: [
12391
+ /* @__PURE__ */ jsx92("span", { className: "fdc-empty-icon", children: /* @__PURE__ */ jsx92("i", { className: "ph ph-" + emptyIcon, "aria-hidden": "true" }) }),
12392
+ /* @__PURE__ */ jsx92("h3", { className: "fdc-empty-title", children: emptyTitle }),
12393
+ emptyDescription ? /* @__PURE__ */ jsx92("p", { className: "fdc-empty-body", children: emptyDescription }) : null,
12394
+ /* @__PURE__ */ jsx92(Suggestions, { items: suggestions, onPick })
12158
12395
  ] }) : null,
12159
12396
  groups.map((g, i) => {
12160
12397
  const prev = groups[i - 1];
12161
12398
  const k = dayKey(g.messages[0].timestamp);
12162
12399
  const showDay = !!k && (!prev || dayKey(prev.messages[0].timestamp) !== k);
12163
- return /* @__PURE__ */ jsxs82(React60.Fragment, { children: [
12164
- showDay ? /* @__PURE__ */ jsx91("div", { className: "fdc-day", children: /* @__PURE__ */ jsx91("span", { children: dayLabel(k) }) }) : null,
12165
- /* @__PURE__ */ jsx91(ChatTurn, { group: g, ctx })
12400
+ return /* @__PURE__ */ jsxs83(React61.Fragment, { children: [
12401
+ showDay ? /* @__PURE__ */ jsx92("div", { className: "fdc-day", children: /* @__PURE__ */ jsx92("span", { children: dayLabel(k) }) }) : null,
12402
+ /* @__PURE__ */ jsx92(ChatTurn, { group: g, ctx })
12166
12403
  ] }, g.key || i);
12167
12404
  })
12168
12405
  ] }),
12169
- pill ? /* @__PURE__ */ jsxs82("button", { type: "button", className: "fdc-pill", onClick: () => toBottom(true), children: [
12170
- /* @__PURE__ */ jsx91("i", { className: "ph ph-arrow-down", "aria-hidden": "true" }),
12406
+ pill ? /* @__PURE__ */ jsxs83("button", { type: "button", className: "fdc-pill", onClick: () => toBottom(true), children: [
12407
+ /* @__PURE__ */ jsx92("i", { className: "ph ph-arrow-down", "aria-hidden": "true" }),
12171
12408
  pill,
12172
12409
  " new message",
12173
12410
  pill === 1 ? "" : "s"
@@ -12177,8 +12414,8 @@ function ChatTranscript({
12177
12414
  var TranscriptKit = { groupMessages };
12178
12415
 
12179
12416
  // src/components/chat/ChatComposer.tsx
12180
- import * as React61 from "react";
12181
- import { jsx as jsx92, jsxs as jsxs83 } from "react/jsx-runtime";
12417
+ import * as React62 from "react";
12418
+ import { jsx as jsx93, jsxs as jsxs84 } from "react/jsx-runtime";
12182
12419
  function ChatComposer({
12183
12420
  onSubmit,
12184
12421
  onStop,
@@ -12205,17 +12442,17 @@ function ChatComposer({
12205
12442
  onReject,
12206
12443
  onOpenAttachment
12207
12444
  }) {
12208
- const [text, setText] = React61.useState(draft || "");
12209
- const [trigger, setTrigger] = React61.useState(null);
12210
- const [mentionItems, setMentionItems] = React61.useState([]);
12211
- const [listening, setListening] = React61.useState(false);
12212
- const [notice, setNotice] = React61.useState(null);
12213
- const editor = React61.useRef(null);
12214
- const wrap = React61.useRef(null);
12215
- const stopVoice = React61.useRef(null);
12445
+ const [text, setText] = React62.useState(draft || "");
12446
+ const [trigger, setTrigger] = React62.useState(null);
12447
+ const [mentionItems, setMentionItems] = React62.useState([]);
12448
+ const [listening, setListening] = React62.useState(false);
12449
+ const [notice, setNotice] = React62.useState(null);
12450
+ const editor = React62.useRef(null);
12451
+ const wrap = React62.useRef(null);
12452
+ const stopVoice = React62.useRef(null);
12216
12453
  const staged = useStagedFiles(fileUploadHandler, { onError: () => {
12217
12454
  } });
12218
- React61.useEffect(() => {
12455
+ React62.useEffect(() => {
12219
12456
  if (draft != null && draft !== text) setText(draft);
12220
12457
  }, [draft]);
12221
12458
  const change = (v) => {
@@ -12251,7 +12488,7 @@ function ChatComposer({
12251
12488
  e.preventDefault();
12252
12489
  staged.add(found.files);
12253
12490
  };
12254
- React61.useEffect(() => {
12491
+ React62.useEffect(() => {
12255
12492
  if (!trigger || trigger.type !== "mention" || !mentionSources) {
12256
12493
  setMentionItems([]);
12257
12494
  return;
@@ -12269,7 +12506,7 @@ function ChatComposer({
12269
12506
  const q = (trigger.query || "").toLowerCase();
12270
12507
  setMentionItems(mentionSources.filter((m) => !q || (m.label + " " + (m.description || "")).toLowerCase().includes(q)));
12271
12508
  }, [trigger, mentionSources]);
12272
- const slashItems = React61.useMemo(() => {
12509
+ const slashItems = React62.useMemo(() => {
12273
12510
  if (!trigger || trigger.type !== "slash" || !slashCommands) return [];
12274
12511
  const q = (trigger.query || "").toLowerCase();
12275
12512
  return slashCommands.filter((c) => !q || (c.id + " " + c.label + " " + (c.description || "")).toLowerCase().includes(q));
@@ -12283,7 +12520,7 @@ function ChatComposer({
12283
12520
  description: it.description,
12284
12521
  icon: it.icon,
12285
12522
  meta: mention.meta,
12286
- shortcut: slash.shortcut ? /* @__PURE__ */ jsx92(KeyHint, { keys: slash.shortcut, size: "sm" }) : void 0,
12523
+ shortcut: slash.shortcut ? /* @__PURE__ */ jsx93(KeyHint, { keys: slash.shortcut, size: "sm" }) : void 0,
12287
12524
  onSelect: () => {
12288
12525
  const insert = trigger.type === "slash" ? slash.immediate ? "/" + slash.id : "/" + slash.id + " " : "@" + (mention.value || mention.label) + " ";
12289
12526
  editor.current && editor.current.replaceRange(trigger.from, trigger.to, insert);
@@ -12342,14 +12579,14 @@ function ChatComposer({
12342
12579
  stopVoice.current = typeof res === "function" ? res : () => {
12343
12580
  };
12344
12581
  };
12345
- return /* @__PURE__ */ jsxs83("div", { className: "fdc-composer" + (disabled ? " is-disabled" : "") + (narrow ? " is-narrow" : ""), children: [
12346
- queue.length ? /* @__PURE__ */ jsx92("div", { className: "fdc-queue", "aria-label": "Queued messages", children: queue.map((q) => /* @__PURE__ */ jsxs83("div", { className: "fdc-queue-row", children: [
12347
- /* @__PURE__ */ jsx92("i", { className: "ph ph-clock-countdown", "aria-hidden": "true" }),
12348
- /* @__PURE__ */ jsx92("span", { className: "fdc-queue-text", title: truncationTitle(q.text || (q.attachments ? q.attachments.length + " file(s)" : "")), children: q.text || (q.attachments ? q.attachments.length + " file(s)" : "") }),
12349
- onRemoveQueued ? /* @__PURE__ */ jsx92("button", { type: "button", className: "fdc-queue-x", onClick: () => onRemoveQueued(q.id), "aria-label": "Remove queued message", children: /* @__PURE__ */ jsx92("i", { className: "ph ph-x", "aria-hidden": "true" }) }) : null
12582
+ return /* @__PURE__ */ jsxs84("div", { className: "fdc-composer" + (disabled ? " is-disabled" : "") + (narrow ? " is-narrow" : ""), children: [
12583
+ queue.length ? /* @__PURE__ */ jsx93("div", { className: "fdc-queue", "aria-label": "Queued messages", children: queue.map((q) => /* @__PURE__ */ jsxs84("div", { className: "fdc-queue-row", children: [
12584
+ /* @__PURE__ */ jsx93("i", { className: "ph ph-clock-countdown", "aria-hidden": "true" }),
12585
+ /* @__PURE__ */ jsx93("span", { className: "fdc-queue-text", title: truncationTitle(q.text || (q.attachments ? q.attachments.length + " file(s)" : "")), children: q.text || (q.attachments ? q.attachments.length + " file(s)" : "") }),
12586
+ onRemoveQueued ? /* @__PURE__ */ jsx93("button", { type: "button", className: "fdc-queue-x", onClick: () => onRemoveQueued(q.id), "aria-label": "Remove queued message", children: /* @__PURE__ */ jsx93("i", { className: "ph ph-x", "aria-hidden": "true" }) }) : null
12350
12587
  ] }, q.id)) }) : null,
12351
12588
  sessionBar,
12352
- /* @__PURE__ */ jsx92(
12589
+ /* @__PURE__ */ jsx93(
12353
12590
  Dropzone,
12354
12591
  {
12355
12592
  className: "fdc-field",
@@ -12363,9 +12600,9 @@ function ChatComposer({
12363
12600
  disabled: !fileUploadHandler || disabled,
12364
12601
  label: "Drop to attach",
12365
12602
  hint: acceptFiles ? acceptFiles.replace(/,/g, " \xB7 ") : void 0,
12366
- children: /* @__PURE__ */ jsxs83("div", { ref: wrap, className: "fdc-field-inner", children: [
12367
- staged.items.length ? /* @__PURE__ */ jsx92("div", { className: "fdc-staged", children: /* @__PURE__ */ jsx92(FileStrip, { files: staged.items, size: narrow ? 60 : 68, onRemove: staged.remove, onRetry: staged.retry, onOpen: onOpenAttachment }) }) : null,
12368
- /* @__PURE__ */ jsx92(
12603
+ children: /* @__PURE__ */ jsxs84("div", { ref: wrap, className: "fdc-field-inner", children: [
12604
+ staged.items.length ? /* @__PURE__ */ jsx93("div", { className: "fdc-staged", children: /* @__PURE__ */ jsx93(FileStrip, { files: staged.items, size: narrow ? 60 : 68, onRemove: staged.remove, onRetry: staged.retry, onOpen: onOpenAttachment }) }) : null,
12605
+ /* @__PURE__ */ jsx93(
12369
12606
  MarkdownEditor,
12370
12607
  {
12371
12608
  ref: editor,
@@ -12384,33 +12621,33 @@ function ChatComposer({
12384
12621
  ariaLabel: "Message"
12385
12622
  }
12386
12623
  ),
12387
- /* @__PURE__ */ jsxs83("div", { className: "fdc-tools", children: [
12388
- fileUploadHandler ? /* @__PURE__ */ jsx92(FilePickButton, { onFiles: staged.add, onReject: (r) => flash(r[0].message), accept: acceptFiles, maxFileSize, label: "Attach files", icon: "plus" }) : null,
12389
- voiceHandler ? /* @__PURE__ */ jsx92("button", { type: "button", className: "fd-attachbtn" + (listening ? " is-live" : ""), onClick: voice, "aria-pressed": listening, "aria-label": listening ? "Stop dictation" : "Dictate", children: /* @__PURE__ */ jsx92("i", { className: "ph ph-" + (listening ? "waveform" : "microphone"), "aria-hidden": "true" }) }) : null,
12624
+ /* @__PURE__ */ jsxs84("div", { className: "fdc-tools", children: [
12625
+ fileUploadHandler ? /* @__PURE__ */ jsx93(FilePickButton, { onFiles: staged.add, onReject: (r) => flash(r[0].message), accept: acceptFiles, maxFileSize, label: "Attach files", icon: "plus" }) : null,
12626
+ voiceHandler ? /* @__PURE__ */ jsx93("button", { type: "button", className: "fd-attachbtn" + (listening ? " is-live" : ""), onClick: voice, "aria-pressed": listening, "aria-label": listening ? "Stop dictation" : "Dictate", children: /* @__PURE__ */ jsx93("i", { className: "ph ph-" + (listening ? "waveform" : "microphone"), "aria-hidden": "true" }) }) : null,
12390
12627
  toolbarExtras,
12391
- /* @__PURE__ */ jsx92("span", { className: "fdc-tools-gap" }),
12392
- maxLength && text.length > maxLength * 0.6 ? /* @__PURE__ */ jsxs83("span", { className: "fdc-count fd-tabular" + (text.length > maxLength * 0.95 ? " is-hot" : ""), children: [
12628
+ /* @__PURE__ */ jsx93("span", { className: "fdc-tools-gap" }),
12629
+ maxLength && text.length > maxLength * 0.6 ? /* @__PURE__ */ jsxs84("span", { className: "fdc-count fd-tabular" + (text.length > maxLength * 0.95 ? " is-hot" : ""), children: [
12393
12630
  text.length,
12394
12631
  "/",
12395
12632
  maxLength
12396
12633
  ] }) : null,
12397
- busy ? /* @__PURE__ */ jsxs83("button", { type: "button", className: "fdc-stop", onClick: onStop, "aria-label": "Stop generating", children: [
12398
- /* @__PURE__ */ jsx92("i", { className: "ph ph-stop-circle", "aria-hidden": "true" }),
12399
- /* @__PURE__ */ jsx92("span", { children: "Stop" })
12400
- ] }) : /* @__PURE__ */ jsxs83("button", { type: "button", className: "fdc-send", onClick: submit, disabled: !canSend, "aria-label": "Send message", children: [
12401
- /* @__PURE__ */ jsx92("i", { className: "ph ph-paper-plane-right", "aria-hidden": "true" }),
12402
- /* @__PURE__ */ jsx92("span", { className: "fdc-send-label", children: "Send" })
12634
+ busy ? /* @__PURE__ */ jsxs84("button", { type: "button", className: "fdc-stop", onClick: onStop, "aria-label": "Stop generating", children: [
12635
+ /* @__PURE__ */ jsx93("i", { className: "ph ph-stop-circle", "aria-hidden": "true" }),
12636
+ /* @__PURE__ */ jsx93("span", { children: "Stop" })
12637
+ ] }) : /* @__PURE__ */ jsxs84("button", { type: "button", className: "fdc-send", onClick: submit, disabled: !canSend, "aria-label": "Send message", children: [
12638
+ /* @__PURE__ */ jsx93("i", { className: "ph ph-paper-plane-right", "aria-hidden": "true" }),
12639
+ /* @__PURE__ */ jsx93("span", { className: "fdc-send-label", children: "Send" })
12403
12640
  ] })
12404
12641
  ] })
12405
12642
  ] })
12406
12643
  }
12407
12644
  ),
12408
- notice ? /* @__PURE__ */ jsxs83("div", { className: "fdc-notice", role: "status", children: [
12409
- /* @__PURE__ */ jsx92("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
12645
+ notice ? /* @__PURE__ */ jsxs84("div", { className: "fdc-notice", role: "status", children: [
12646
+ /* @__PURE__ */ jsx93("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
12410
12647
  notice
12411
12648
  ] }) : null,
12412
- hint && !notice ? /* @__PURE__ */ jsx92("div", { className: "fdc-hint", children: hint }) : null,
12413
- /* @__PURE__ */ jsx92(
12649
+ hint && !notice ? /* @__PURE__ */ jsx93("div", { className: "fdc-hint", children: hint }) : null,
12650
+ /* @__PURE__ */ jsx93(
12414
12651
  Popover,
12415
12652
  {
12416
12653
  open: menuOpen,
@@ -12424,12 +12661,12 @@ function ChatComposer({
12424
12661
  returnFocus: false,
12425
12662
  closeOnOutside: true,
12426
12663
  label: trigger && trigger.type === "slash" ? "Commands" : "Mentions",
12427
- children: /* @__PURE__ */ jsx92(
12664
+ children: /* @__PURE__ */ jsx93(
12428
12665
  Menu,
12429
12666
  {
12430
12667
  items: menuItems,
12431
12668
  autoFocus: false,
12432
- header: /* @__PURE__ */ jsx92("div", { className: "fd-pop-group", children: trigger && trigger.type === "slash" ? "Commands" : "Attach context" }),
12669
+ header: /* @__PURE__ */ jsx93("div", { className: "fd-pop-group", children: trigger && trigger.type === "slash" ? "Commands" : "Attach context" }),
12433
12670
  onClose: () => setTrigger(null)
12434
12671
  }
12435
12672
  )
@@ -12439,12 +12676,12 @@ function ChatComposer({
12439
12676
  }
12440
12677
 
12441
12678
  // src/components/chat/ChatSessionBar.tsx
12442
- import * as React62 from "react";
12443
- import { jsx as jsx93, jsxs as jsxs84 } from "react/jsx-runtime";
12679
+ import * as React63 from "react";
12680
+ import { jsx as jsx94, jsxs as jsxs85 } from "react/jsx-runtime";
12444
12681
  var compact2 = meterFormats.compact;
12445
12682
  function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extras }) {
12446
- const [open2, setOpen] = React62.useState(false);
12447
- const anchor = React62.useRef(null);
12683
+ const [open2, setOpen] = React63.useState(false);
12684
+ const anchor = React63.useRef(null);
12448
12685
  const stats = sessionStats || null;
12449
12686
  const cu = contextUsage || null;
12450
12687
  const limits = usageLimits || null;
@@ -12459,9 +12696,9 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
12459
12696
  if (stats && stats.runningTasks) bits.push(stats.runningTasks + " running task" + (stats.runningTasks === 1 ? "" : "s"));
12460
12697
  if (cu) bits.push(pct + "% context");
12461
12698
  const expandable = !!(cu || limits);
12462
- return /* @__PURE__ */ jsxs84(React62.Fragment, { children: [
12463
- /* @__PURE__ */ jsxs84("div", { className: "fdc-bar", children: [
12464
- /* @__PURE__ */ jsxs84(
12699
+ return /* @__PURE__ */ jsxs85(React63.Fragment, { children: [
12700
+ /* @__PURE__ */ jsxs85("div", { className: "fdc-bar", children: [
12701
+ /* @__PURE__ */ jsxs85(
12465
12702
  "button",
12466
12703
  {
12467
12704
  type: "button",
@@ -12472,15 +12709,15 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
12472
12709
  "aria-expanded": expandable ? open2 : void 0,
12473
12710
  "aria-label": expandable ? "Usage details" : void 0,
12474
12711
  children: [
12475
- cu ? /* @__PURE__ */ jsx93("span", { className: "fdc-bar-mini", "aria-hidden": "true", children: /* @__PURE__ */ jsx93(SegmentedMeter, { total, segments: cu.segments, height: 4, showTotal: false }) }) : null,
12476
- /* @__PURE__ */ jsx93("span", { className: "fdc-bar-text", title: truncationTitle(bits.join(" \xB7 ")), children: bits.join(" \xB7 ") }),
12477
- expandable ? /* @__PURE__ */ jsx93("i", { className: "ph ph-caret-right fdc-bar-caret", "aria-hidden": "true" }) : null
12712
+ cu ? /* @__PURE__ */ jsx94("span", { className: "fdc-bar-mini", "aria-hidden": "true", children: /* @__PURE__ */ jsx94(SegmentedMeter, { total, segments: cu.segments, height: 4, showTotal: false }) }) : null,
12713
+ /* @__PURE__ */ jsx94("span", { className: "fdc-bar-text", title: truncationTitle(bits.join(" \xB7 ")), children: bits.join(" \xB7 ") }),
12714
+ expandable ? /* @__PURE__ */ jsx94("i", { className: "ph ph-caret-right fdc-bar-caret", "aria-hidden": "true" }) : null
12478
12715
  ]
12479
12716
  }
12480
12717
  ),
12481
12718
  extras
12482
12719
  ] }),
12483
- /* @__PURE__ */ jsx93(
12720
+ /* @__PURE__ */ jsx94(
12484
12721
  Popover,
12485
12722
  {
12486
12723
  open: open2,
@@ -12491,15 +12728,15 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
12491
12728
  maxHeight: 460,
12492
12729
  padded: true,
12493
12730
  label: "Usage",
12494
- footer: onClear ? /* @__PURE__ */ jsxs84("button", { type: "button", className: "fdc-usage-clear", onClick: () => {
12731
+ footer: onClear ? /* @__PURE__ */ jsxs85("button", { type: "button", className: "fdc-usage-clear", onClick: () => {
12495
12732
  setOpen(false);
12496
12733
  onClear();
12497
12734
  }, children: [
12498
- /* @__PURE__ */ jsx93("i", { className: "ph ph-trash", "aria-hidden": "true" }),
12735
+ /* @__PURE__ */ jsx94("i", { className: "ph ph-trash", "aria-hidden": "true" }),
12499
12736
  "Clear conversation"
12500
12737
  ] }) : void 0,
12501
- children: /* @__PURE__ */ jsxs84("div", { className: "fdc-usage", children: [
12502
- cu ? /* @__PURE__ */ jsx93("section", { className: "fdc-usage-sec", children: /* @__PURE__ */ jsx93(
12738
+ children: /* @__PURE__ */ jsxs85("div", { className: "fdc-usage", children: [
12739
+ cu ? /* @__PURE__ */ jsx94("section", { className: "fdc-usage-sec", children: /* @__PURE__ */ jsx94(
12503
12740
  SegmentedMeter,
12504
12741
  {
12505
12742
  total,
@@ -12511,9 +12748,9 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
12511
12748
  remainderLabel: "Free"
12512
12749
  }
12513
12750
  ) }) : null,
12514
- limits && limits.length ? /* @__PURE__ */ jsxs84("section", { className: "fdc-usage-sec", children: [
12515
- /* @__PURE__ */ jsx93("h4", { className: "fdc-usage-h", children: "Usage limits" }),
12516
- /* @__PURE__ */ jsx93("div", { className: "fdc-usage-rows", children: limits.map((l) => /* @__PURE__ */ jsx93(
12751
+ limits && limits.length ? /* @__PURE__ */ jsxs85("section", { className: "fdc-usage-sec", children: [
12752
+ /* @__PURE__ */ jsx94("h4", { className: "fdc-usage-h", children: "Usage limits" }),
12753
+ /* @__PURE__ */ jsx94("div", { className: "fdc-usage-rows", children: limits.map((l) => /* @__PURE__ */ jsx94(
12517
12754
  QuotaRow,
12518
12755
  {
12519
12756
  label: l.label,
@@ -12523,25 +12760,25 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
12523
12760
  l.id
12524
12761
  )) })
12525
12762
  ] }) : null,
12526
- stats ? /* @__PURE__ */ jsxs84("section", { className: "fdc-usage-sec fdc-usage-stats", children: [
12527
- stats.elapsedMs ? /* @__PURE__ */ jsxs84("div", { children: [
12528
- /* @__PURE__ */ jsx93("span", { children: "Session" }),
12529
- /* @__PURE__ */ jsx93("b", { className: "fd-tabular", children: formatDuration(stats.elapsedMs) })
12763
+ stats ? /* @__PURE__ */ jsxs85("section", { className: "fdc-usage-sec fdc-usage-stats", children: [
12764
+ stats.elapsedMs ? /* @__PURE__ */ jsxs85("div", { children: [
12765
+ /* @__PURE__ */ jsx94("span", { children: "Session" }),
12766
+ /* @__PURE__ */ jsx94("b", { className: "fd-tabular", children: formatDuration(stats.elapsedMs) })
12530
12767
  ] }) : null,
12531
- stats.tokens ? /* @__PURE__ */ jsxs84("div", { children: [
12532
- /* @__PURE__ */ jsx93("span", { children: "Tokens" }),
12533
- /* @__PURE__ */ jsx93("b", { className: "fd-tabular", children: stats.tokens.toLocaleString() })
12768
+ stats.tokens ? /* @__PURE__ */ jsxs85("div", { children: [
12769
+ /* @__PURE__ */ jsx94("span", { children: "Tokens" }),
12770
+ /* @__PURE__ */ jsx94("b", { className: "fd-tabular", children: stats.tokens.toLocaleString() })
12534
12771
  ] }) : null,
12535
- stats.costUsd != null ? /* @__PURE__ */ jsxs84("div", { children: [
12536
- /* @__PURE__ */ jsx93("span", { children: "Cost" }),
12537
- /* @__PURE__ */ jsxs84("b", { className: "fd-tabular", children: [
12772
+ stats.costUsd != null ? /* @__PURE__ */ jsxs85("div", { children: [
12773
+ /* @__PURE__ */ jsx94("span", { children: "Cost" }),
12774
+ /* @__PURE__ */ jsxs85("b", { className: "fd-tabular", children: [
12538
12775
  "$",
12539
12776
  Number(stats.costUsd).toFixed(3)
12540
12777
  ] })
12541
12778
  ] }) : null,
12542
- stats.turns ? /* @__PURE__ */ jsxs84("div", { children: [
12543
- /* @__PURE__ */ jsx93("span", { children: "Turns" }),
12544
- /* @__PURE__ */ jsx93("b", { className: "fd-tabular", children: stats.turns })
12779
+ stats.turns ? /* @__PURE__ */ jsxs85("div", { children: [
12780
+ /* @__PURE__ */ jsx94("span", { children: "Turns" }),
12781
+ /* @__PURE__ */ jsx94("b", { className: "fd-tabular", children: stats.turns })
12545
12782
  ] }) : null
12546
12783
  ] }) : null
12547
12784
  ] })
@@ -12580,7 +12817,7 @@ function ModelControls({
12580
12817
  disabled: m.disabled,
12581
12818
  checked: m.id === (current2 && current2.id),
12582
12819
  meta: m.meta,
12583
- shortcut: m.shortcut ? /* @__PURE__ */ jsx93(KeyHint, { keys: m.shortcut, size: "sm" }) : void 0,
12820
+ shortcut: m.shortcut ? /* @__PURE__ */ jsx94(KeyHint, { keys: m.shortcut, size: "sm" }) : void 0,
12584
12821
  onSelect: () => onModelChange && onModelChange(m.id)
12585
12822
  });
12586
12823
  const items = [{ kind: "section", label: "Models" }].concat(flat.map(item));
@@ -12593,15 +12830,15 @@ function ModelControls({
12593
12830
  items.push({ kind: "section", label: "Fast mode" });
12594
12831
  items.push({
12595
12832
  kind: "custom",
12596
- render: () => /* @__PURE__ */ jsxs84("label", { className: "fdc-switchrow", children: [
12597
- /* @__PURE__ */ jsx93("span", { children: fastModeLabel }),
12598
- /* @__PURE__ */ jsx93("input", { type: "checkbox", className: "fd-sr", checked: !!fastMode, onChange: (e) => onFastModeChange(e.target.checked) }),
12599
- /* @__PURE__ */ jsx93("span", { className: "fd-switch-track" + (fastMode ? " is-on" : ""), "aria-hidden": "true", children: /* @__PURE__ */ jsx93("span", { className: "fd-switch-thumb" }) })
12833
+ render: () => /* @__PURE__ */ jsxs85("label", { className: "fdc-switchrow", children: [
12834
+ /* @__PURE__ */ jsx94("span", { children: fastModeLabel }),
12835
+ /* @__PURE__ */ jsx94("input", { type: "checkbox", className: "fd-sr", checked: !!fastMode, onChange: (e) => onFastModeChange(e.target.checked) }),
12836
+ /* @__PURE__ */ jsx94("span", { className: "fd-switch-track" + (fastMode ? " is-on" : ""), "aria-hidden": "true", children: /* @__PURE__ */ jsx94("span", { className: "fd-switch-thumb" }) })
12600
12837
  ] })
12601
12838
  });
12602
12839
  }
12603
- return /* @__PURE__ */ jsxs84(React62.Fragment, { children: [
12604
- /* @__PURE__ */ jsx93(
12840
+ return /* @__PURE__ */ jsxs85(React63.Fragment, { children: [
12841
+ /* @__PURE__ */ jsx94(
12605
12842
  MenuButton,
12606
12843
  {
12607
12844
  items,
@@ -12612,7 +12849,7 @@ function ModelControls({
12612
12849
  title: "Choose a model"
12613
12850
  }
12614
12851
  ),
12615
- effortLevels && effortLevels.length ? /* @__PURE__ */ jsx93(
12852
+ effortLevels && effortLevels.length ? /* @__PURE__ */ jsx94(
12616
12853
  MenuButton,
12617
12854
  {
12618
12855
  placement: "top-end",
@@ -12633,7 +12870,7 @@ function ModelControls({
12633
12870
  }
12634
12871
 
12635
12872
  // src/components/chat/AgentChatPanel.tsx
12636
- import { jsx as jsx94, jsxs as jsxs85 } from "react/jsx-runtime";
12873
+ import { jsx as jsx95, jsxs as jsxs86 } from "react/jsx-runtime";
12637
12874
  var SURFACES = { sidebar: "is-sidebar", inline: "is-inline", page: "is-page", modal: "is-modal", sheet: "is-sheet" };
12638
12875
  function AgentChatPanel({
12639
12876
  /* required */
@@ -12717,11 +12954,11 @@ function AgentChatPanel({
12717
12954
  onFeedback,
12718
12955
  onEditMessage
12719
12956
  }) {
12720
- const [panelWidth, setPanelWidth] = React63.useState(width);
12721
- const [applied, setApplied] = React63.useState({});
12722
- const [draft, setDraft] = React63.useState("");
12723
- const dragging = React63.useRef(null);
12724
- React63.useEffect(() => setPanelWidth(width), [width]);
12957
+ const [panelWidth, setPanelWidth] = React64.useState(width);
12958
+ const [applied, setApplied] = React64.useState({});
12959
+ const [draft, setDraft] = React64.useState("");
12960
+ const dragging = React64.useRef(null);
12961
+ React64.useEffect(() => setPanelWidth(width), [width]);
12725
12962
  const engine = useChatEngine({
12726
12963
  contextType,
12727
12964
  contextId,
@@ -12787,7 +13024,7 @@ function AgentChatPanel({
12787
13024
  onReconnect: engine.reload,
12788
13025
  deadTitle: "The assistant isn\u2019t reachable"
12789
13026
  };
12790
- const sessionBar = /* @__PURE__ */ jsx94(
13027
+ const sessionBar = /* @__PURE__ */ jsx95(
12791
13028
  ChatSessionBar,
12792
13029
  {
12793
13030
  sessionStats,
@@ -12796,7 +13033,7 @@ function AgentChatPanel({
12796
13033
  onClear: engine.visible.length ? engine.clear : void 0
12797
13034
  }
12798
13035
  );
12799
- const modelControls = /* @__PURE__ */ jsx94(
13036
+ const modelControls = /* @__PURE__ */ jsx95(
12800
13037
  ModelControls,
12801
13038
  {
12802
13039
  models,
@@ -12811,7 +13048,7 @@ function AgentChatPanel({
12811
13048
  narrow
12812
13049
  }
12813
13050
  );
12814
- const threadMenu = threads && threads.length ? /* @__PURE__ */ jsx94(
13051
+ const threadMenu = threads && threads.length ? /* @__PURE__ */ jsx95(
12815
13052
  MenuButton,
12816
13053
  {
12817
13054
  variant: "ghost",
@@ -12838,7 +13075,7 @@ function AgentChatPanel({
12838
13075
  })))
12839
13076
  }
12840
13077
  ) : null;
12841
- return /* @__PURE__ */ jsxs85(
13078
+ return /* @__PURE__ */ jsxs86(
12842
13079
  "aside",
12843
13080
  {
12844
13081
  className: ["fdc-panel", SURFACES[surface] || SURFACES.sidebar, narrow ? "is-narrow" : "", className].filter(Boolean).join(" "),
@@ -12849,7 +13086,7 @@ function AgentChatPanel({
12849
13086
  },
12850
13087
  "aria-label": title,
12851
13088
  children: [
12852
- surface === "sidebar" && resizable ? /* @__PURE__ */ jsx94(
13089
+ surface === "sidebar" && resizable ? /* @__PURE__ */ jsx95(
12853
13090
  "div",
12854
13091
  {
12855
13092
  className: "fdc-grip",
@@ -12864,20 +13101,20 @@ function AgentChatPanel({
12864
13101
  }
12865
13102
  }
12866
13103
  ) : null,
12867
- showHeader ? /* @__PURE__ */ jsxs85("header", { className: "fdc-head", children: [
12868
- /* @__PURE__ */ jsx94("span", { className: "fdc-head-mark", "aria-hidden": "true", children: /* @__PURE__ */ jsx94("i", { className: "ph ph-" + assistantIcon }) }),
12869
- /* @__PURE__ */ jsxs85("span", { className: "fdc-head-titles", children: [
12870
- /* @__PURE__ */ jsx94("span", { className: "fdc-head-title", title: truncationTitle(title), children: title }),
12871
- subtitle ? /* @__PURE__ */ jsx94("span", { className: "fdc-head-sub", title: truncationTitle(subtitle), children: subtitle }) : null
13104
+ showHeader ? /* @__PURE__ */ jsxs86("header", { className: "fdc-head", children: [
13105
+ /* @__PURE__ */ jsx95("span", { className: "fdc-head-mark", "aria-hidden": "true", children: /* @__PURE__ */ jsx95("i", { className: "ph ph-" + assistantIcon }) }),
13106
+ /* @__PURE__ */ jsxs86("span", { className: "fdc-head-titles", children: [
13107
+ /* @__PURE__ */ jsx95("span", { className: "fdc-head-title", title: truncationTitle(title), children: title }),
13108
+ subtitle ? /* @__PURE__ */ jsx95("span", { className: "fdc-head-sub", title: truncationTitle(subtitle), children: subtitle }) : null
12872
13109
  ] }),
12873
- /* @__PURE__ */ jsxs85("span", { className: "fdc-head-acts", children: [
13110
+ /* @__PURE__ */ jsxs86("span", { className: "fdc-head-acts", children: [
12874
13111
  headerActions,
12875
13112
  threadMenu,
12876
- onNewThread ? /* @__PURE__ */ jsx94("button", { type: "button", className: "fdc-iconbtn", onClick: onNewThread, "aria-label": "New conversation", title: "New conversation", children: /* @__PURE__ */ jsx94("i", { className: "ph ph-plus", "aria-hidden": "true" }) }) : null,
12877
- onClose ? /* @__PURE__ */ jsx94("button", { type: "button", className: "fdc-iconbtn", onClick: onClose, "aria-label": "Close panel", title: "Close", children: /* @__PURE__ */ jsx94("i", { className: "ph ph-x", "aria-hidden": "true" }) }) : null
13113
+ onNewThread ? /* @__PURE__ */ jsx95("button", { type: "button", className: "fdc-iconbtn", onClick: onNewThread, "aria-label": "New conversation", title: "New conversation", children: /* @__PURE__ */ jsx95("i", { className: "ph ph-plus", "aria-hidden": "true" }) }) : null,
13114
+ onClose ? /* @__PURE__ */ jsx95("button", { type: "button", className: "fdc-iconbtn", onClick: onClose, "aria-label": "Close panel", title: "Close", children: /* @__PURE__ */ jsx95("i", { className: "ph ph-x", "aria-hidden": "true" }) }) : null
12878
13115
  ] })
12879
13116
  ] }) : null,
12880
- /* @__PURE__ */ jsx94(
13117
+ /* @__PURE__ */ jsx95(
12881
13118
  ChatTranscript,
12882
13119
  {
12883
13120
  messages: engine.visible,
@@ -12892,7 +13129,7 @@ function AgentChatPanel({
12892
13129
  renderEmpty
12893
13130
  }
12894
13131
  ),
12895
- /* @__PURE__ */ jsx94(
13132
+ /* @__PURE__ */ jsx95(
12896
13133
  ChatComposer,
12897
13134
  {
12898
13135
  onSubmit: (text, atts) => engine.send(text, atts),
@@ -12925,8 +13162,8 @@ function AgentChatPanel({
12925
13162
  }
12926
13163
 
12927
13164
  // src/components/files/FileViewer.tsx
12928
- import * as React64 from "react";
12929
- import { jsx as jsx95, jsxs as jsxs86 } from "react/jsx-runtime";
13165
+ import * as React65 from "react";
13166
+ import { jsx as jsx96, jsxs as jsxs87 } from "react/jsx-runtime";
12930
13167
  function previewKindOf(file) {
12931
13168
  const mime = (file.mime || "").toLowerCase();
12932
13169
  const ext = extensionOf(file.name || "");
@@ -12982,13 +13219,13 @@ function parseDelimited(text, delimiter) {
12982
13219
  return rows;
12983
13220
  }
12984
13221
  function usePreview(file, kind, resolveUrl) {
12985
- const [state, setState] = React64.useState({ status: "loading" });
12986
- const [attempt, setAttempt] = React64.useState(0);
12987
- const resolveRef = React64.useRef(resolveUrl);
12988
- React64.useEffect(() => {
13222
+ const [state, setState] = React65.useState({ status: "loading" });
13223
+ const [attempt, setAttempt] = React65.useState(0);
13224
+ const resolveRef = React65.useRef(resolveUrl);
13225
+ React65.useEffect(() => {
12989
13226
  resolveRef.current = resolveUrl;
12990
13227
  }, [resolveUrl]);
12991
- React64.useEffect(() => {
13228
+ React65.useEffect(() => {
12992
13229
  if (kind === "none") {
12993
13230
  setState({ status: "ready" });
12994
13231
  return;
@@ -13018,19 +13255,19 @@ function usePreview(file, kind, resolveUrl) {
13018
13255
  if (ac) ac.abort();
13019
13256
  };
13020
13257
  }, [file.id, kind, attempt]);
13021
- return { ...state, retry: React64.useCallback(() => setAttempt((a) => a + 1), []) };
13258
+ return { ...state, retry: React65.useCallback(() => setAttempt((a) => a + 1), []) };
13022
13259
  }
13023
13260
  function PreviewBody({ file, kind, state }) {
13024
- if (kind === "image") return /* @__PURE__ */ jsx95("img", { className: "fd-fv-image", src: state.url, alt: file.name || "Preview" });
13025
- if (kind === "pdf") return /* @__PURE__ */ jsx95("iframe", { className: "fd-fv-pdf", src: state.url, title: file.name || "PDF preview" });
13026
- if (kind === "markdown") return /* @__PURE__ */ jsx95(Markdown, { className: "fd-fv-markdown", source: state.text || "" });
13261
+ if (kind === "image") return /* @__PURE__ */ jsx96("img", { className: "fd-fv-image", src: state.url, alt: file.name || "Preview" });
13262
+ if (kind === "pdf") return /* @__PURE__ */ jsx96("iframe", { className: "fd-fv-pdf", src: state.url, title: file.name || "PDF preview" });
13263
+ if (kind === "markdown") return /* @__PURE__ */ jsx96(Markdown, { className: "fd-fv-markdown", source: state.text || "" });
13027
13264
  if (kind === "json") {
13028
13265
  let pretty = state.text || "";
13029
13266
  try {
13030
13267
  pretty = JSON.stringify(JSON.parse(pretty), null, 2);
13031
13268
  } catch {
13032
13269
  }
13033
- return /* @__PURE__ */ jsx95(CodeBlock, { code: pretty, language: "json" });
13270
+ return /* @__PURE__ */ jsx96(CodeBlock, { code: pretty, language: "json" });
13034
13271
  }
13035
13272
  if (kind === "csv") {
13036
13273
  const tsv = extensionOf(file.name || "") === "tsv" || (file.mime || "").toLowerCase().includes("tab-separated");
@@ -13038,12 +13275,12 @@ function PreviewBody({ file, kind, state }) {
13038
13275
  const head = rows[0] || [];
13039
13276
  const dataRows = rows.slice(1);
13040
13277
  const shown = dataRows.slice(0, FILE_VIEWER_CSV_ROW_LIMIT);
13041
- return /* @__PURE__ */ jsxs86("div", { className: "fd-fv-csv", children: [
13042
- /* @__PURE__ */ jsxs86("table", { className: "fd-fv-csv-table", children: [
13043
- /* @__PURE__ */ jsx95("thead", { children: /* @__PURE__ */ jsx95("tr", { children: head.map((c, i) => /* @__PURE__ */ jsx95("th", { children: c }, i)) }) }),
13044
- /* @__PURE__ */ jsx95("tbody", { children: shown.map((r, ri) => /* @__PURE__ */ jsx95("tr", { children: head.map((_, ci) => /* @__PURE__ */ jsx95("td", { children: r[ci] ?? "" }, ci)) }, ri)) })
13278
+ return /* @__PURE__ */ jsxs87("div", { className: "fd-fv-csv", children: [
13279
+ /* @__PURE__ */ jsxs87("table", { className: "fd-fv-csv-table", children: [
13280
+ /* @__PURE__ */ jsx96("thead", { children: /* @__PURE__ */ jsx96("tr", { children: head.map((c, i) => /* @__PURE__ */ jsx96("th", { children: c }, i)) }) }),
13281
+ /* @__PURE__ */ jsx96("tbody", { children: shown.map((r, ri) => /* @__PURE__ */ jsx96("tr", { children: head.map((_, ci) => /* @__PURE__ */ jsx96("td", { children: r[ci] ?? "" }, ci)) }, ri)) })
13045
13282
  ] }),
13046
- dataRows.length > FILE_VIEWER_CSV_ROW_LIMIT ? /* @__PURE__ */ jsxs86("p", { className: "fd-fv-csv-note fd-body-sm fd-muted", children: [
13283
+ dataRows.length > FILE_VIEWER_CSV_ROW_LIMIT ? /* @__PURE__ */ jsxs87("p", { className: "fd-fv-csv-note fd-body-sm fd-muted", children: [
13047
13284
  "Showing the first ",
13048
13285
  FILE_VIEWER_CSV_ROW_LIMIT.toLocaleString(),
13049
13286
  " of ",
@@ -13052,24 +13289,24 @@ function PreviewBody({ file, kind, state }) {
13052
13289
  ] }) : null
13053
13290
  ] });
13054
13291
  }
13055
- if (kind === "text") return /* @__PURE__ */ jsx95(CodeBlock, { code: state.text || "", language: extensionOf(file.name || "") || void 0 });
13056
- return /* @__PURE__ */ jsxs86("div", { className: "fd-fv-fallback", children: [
13057
- /* @__PURE__ */ jsx95("span", { className: "fd-fv-fallback-icon", "aria-hidden": "true", children: /* @__PURE__ */ jsx95("i", { className: "ph ph-" + iconForMime(file.mime, file.name) }) }),
13058
- /* @__PURE__ */ jsx95("span", { className: "fd-fv-fallback-title", children: "No preview available" }),
13059
- /* @__PURE__ */ jsxs86("span", { className: "fd-fv-fallback-meta", children: [
13292
+ if (kind === "text") return /* @__PURE__ */ jsx96(CodeBlock, { code: state.text || "", language: extensionOf(file.name || "") || void 0 });
13293
+ return /* @__PURE__ */ jsxs87("div", { className: "fd-fv-fallback", children: [
13294
+ /* @__PURE__ */ jsx96("span", { className: "fd-fv-fallback-icon", "aria-hidden": "true", children: /* @__PURE__ */ jsx96("i", { className: "ph ph-" + iconForMime(file.mime, file.name) }) }),
13295
+ /* @__PURE__ */ jsx96("span", { className: "fd-fv-fallback-title", children: "No preview available" }),
13296
+ /* @__PURE__ */ jsxs87("span", { className: "fd-fv-fallback-meta", children: [
13060
13297
  file.mime || "Unknown type",
13061
13298
  file.size ? " \xB7 " + formatBytes(file.size) : ""
13062
13299
  ] })
13063
13300
  ] });
13064
13301
  }
13065
13302
  function FileViewer({ file, resolveUrl, sidePanel, sidePanelLabel = "Details", onClose, actions, className = "" }) {
13066
- const kind = React64.useMemo(() => previewKindOf(file), [file]);
13303
+ const kind = React65.useMemo(() => previewKindOf(file), [file]);
13067
13304
  const preview = usePreview(file, kind, resolveUrl);
13068
- const [tab, setTab] = React64.useState("preview");
13069
- const [downloading, setDownloading] = React64.useState(false);
13070
- const [downloadError, setDownloadError] = React64.useState(null);
13305
+ const [tab, setTab] = React65.useState("preview");
13306
+ const [downloading, setDownloading] = React65.useState(false);
13307
+ const [downloadError, setDownloadError] = React65.useState(null);
13071
13308
  const hasSide = sidePanel != null;
13072
- React64.useEffect(() => {
13309
+ React65.useEffect(() => {
13073
13310
  setTab("preview");
13074
13311
  }, [file.id]);
13075
13312
  const download = () => {
@@ -13085,29 +13322,29 @@ function FileViewer({ file, resolveUrl, sidePanel, sidePanelLabel = "Details", o
13085
13322
  a.remove();
13086
13323
  }).catch((err) => setDownloadError(err && err.message || "Download failed.")).finally(() => setDownloading(false));
13087
13324
  };
13088
- return /* @__PURE__ */ jsxs86(
13325
+ return /* @__PURE__ */ jsxs87(
13089
13326
  "section",
13090
13327
  {
13091
13328
  className: ["fd-fv", hasSide && tab === "side" ? "is-tab-side" : "is-tab-preview", className].filter(Boolean).join(" "),
13092
13329
  "aria-label": file.name || "File",
13093
13330
  children: [
13094
- /* @__PURE__ */ jsxs86("header", { className: "fd-fv-head", children: [
13095
- /* @__PURE__ */ jsx95("span", { className: "fd-fv-head-icon", "aria-hidden": "true", children: /* @__PURE__ */ jsx95("i", { className: "ph ph-" + iconForMime(file.mime, file.name) }) }),
13096
- /* @__PURE__ */ jsxs86("span", { className: "fd-fv-head-titles", children: [
13097
- /* @__PURE__ */ jsx95("span", { className: "fd-fv-head-title", title: file.name, children: file.name }),
13098
- /* @__PURE__ */ jsxs86("span", { className: "fd-fv-head-meta", children: [
13331
+ /* @__PURE__ */ jsxs87("header", { className: "fd-fv-head", children: [
13332
+ /* @__PURE__ */ jsx96("span", { className: "fd-fv-head-icon", "aria-hidden": "true", children: /* @__PURE__ */ jsx96("i", { className: "ph ph-" + iconForMime(file.mime, file.name) }) }),
13333
+ /* @__PURE__ */ jsxs87("span", { className: "fd-fv-head-titles", children: [
13334
+ /* @__PURE__ */ jsx96("span", { className: "fd-fv-head-title", title: file.name, children: file.name }),
13335
+ /* @__PURE__ */ jsxs87("span", { className: "fd-fv-head-meta", children: [
13099
13336
  file.mime || "Unknown type",
13100
13337
  file.size ? " \xB7 " + formatBytes(file.size) : ""
13101
13338
  ] })
13102
13339
  ] }),
13103
- /* @__PURE__ */ jsxs86("span", { className: "fd-fv-head-actions", children: [
13340
+ /* @__PURE__ */ jsxs87("span", { className: "fd-fv-head-actions", children: [
13104
13341
  actions,
13105
- /* @__PURE__ */ jsx95(Button, { variant: "secondary", size: "sm", icon: "download-simple", loading: downloading, onClick: download, children: "Download" }),
13106
- onClose ? /* @__PURE__ */ jsx95(IconButton, { icon: "x", label: "Close", onClick: onClose }) : null
13342
+ /* @__PURE__ */ jsx96(Button, { variant: "secondary", size: "sm", icon: "download-simple", loading: downloading, onClick: download, children: "Download" }),
13343
+ onClose ? /* @__PURE__ */ jsx96(IconButton, { icon: "x", label: "Close", onClick: onClose }) : null
13107
13344
  ] })
13108
13345
  ] }),
13109
- downloadError ? /* @__PURE__ */ jsx95("div", { className: "fd-fv-download-error", role: "alert", children: downloadError }) : null,
13110
- hasSide ? /* @__PURE__ */ jsx95(
13346
+ downloadError ? /* @__PURE__ */ jsx96("div", { className: "fd-fv-download-error", role: "alert", children: downloadError }) : null,
13347
+ hasSide ? /* @__PURE__ */ jsx96(
13111
13348
  Tabs,
13112
13349
  {
13113
13350
  className: "fd-fv-tabs",
@@ -13116,19 +13353,19 @@ function FileViewer({ file, resolveUrl, sidePanel, sidePanelLabel = "Details", o
13116
13353
  onChange: (v) => setTab(v)
13117
13354
  }
13118
13355
  ) : null,
13119
- /* @__PURE__ */ jsxs86("div", { className: "fd-fv-body", children: [
13120
- /* @__PURE__ */ jsx95("div", { className: "fd-fv-preview", role: "region", "aria-label": "Preview of " + (file.name || "file"), children: /* @__PURE__ */ jsx95(
13356
+ /* @__PURE__ */ jsxs87("div", { className: "fd-fv-body", children: [
13357
+ /* @__PURE__ */ jsx96("div", { className: "fd-fv-preview", role: "region", "aria-label": "Preview of " + (file.name || "file"), children: /* @__PURE__ */ jsx96(
13121
13358
  LoadingRegion,
13122
13359
  {
13123
13360
  state: preview.status === "loading" ? "loading" : preview.status === "error" ? "error" : "ready",
13124
13361
  error: preview.error,
13125
13362
  label: "Loading preview of " + (file.name || "file"),
13126
13363
  onRetry: preview.status === "error" ? preview.retry : void 0,
13127
- skeleton: /* @__PURE__ */ jsx95(Skeleton, { shape: "card", h: 220 }),
13128
- children: /* @__PURE__ */ jsx95(PreviewBody, { file, kind, state: preview })
13364
+ skeleton: /* @__PURE__ */ jsx96(Skeleton, { shape: "card", h: 220 }),
13365
+ children: /* @__PURE__ */ jsx96(PreviewBody, { file, kind, state: preview })
13129
13366
  }
13130
13367
  ) }),
13131
- hasSide ? /* @__PURE__ */ jsx95("div", { className: "fd-fv-side", role: "region", "aria-label": sidePanelLabel, children: sidePanel }) : null
13368
+ hasSide ? /* @__PURE__ */ jsx96("div", { className: "fd-fv-side", role: "region", "aria-label": sidePanelLabel, children: sidePanel }) : null
13132
13369
  ] })
13133
13370
  ]
13134
13371
  }
@@ -13136,8 +13373,8 @@ function FileViewer({ file, resolveUrl, sidePanel, sidePanelLabel = "Details", o
13136
13373
  }
13137
13374
 
13138
13375
  // src/components/files/FileBrowser.tsx
13139
- import * as React65 from "react";
13140
- import { Fragment as Fragment28, jsx as jsx96, jsxs as jsxs87 } from "react/jsx-runtime";
13376
+ import * as React66 from "react";
13377
+ import { Fragment as Fragment28, jsx as jsx97, jsxs as jsxs88 } from "react/jsx-runtime";
13141
13378
  function childrenOf(folders, parentId) {
13142
13379
  return folders.filter((f) => f.parentId === parentId).sort((a, b) => a.name.localeCompare(b.name));
13143
13380
  }
@@ -13209,8 +13446,8 @@ function FolderPickerMenu({
13209
13446
  }) {
13210
13447
  const panel = useInlinePanel();
13211
13448
  const { open: open2, setOpen, ref, zIndex } = panel;
13212
- return /* @__PURE__ */ jsxs87("span", { className: "fd-fb-menu-anchor", ref, children: [
13213
- /* @__PURE__ */ jsx96(
13449
+ return /* @__PURE__ */ jsxs88("span", { className: "fd-fb-menu-anchor", ref, children: [
13450
+ /* @__PURE__ */ jsx97(
13214
13451
  IconButton,
13215
13452
  {
13216
13453
  icon: "arrows-out-cardinal",
@@ -13222,9 +13459,9 @@ function FolderPickerMenu({
13222
13459
  onClick: () => setOpen((v) => !v)
13223
13460
  }
13224
13461
  ),
13225
- open2 ? /* @__PURE__ */ jsx96(InlinePanelLayers, { panel, children: /* @__PURE__ */ jsxs87("div", { className: "fd-fb-menu", role: "menu", "aria-label": label, style: { zIndex }, children: [
13226
- /* @__PURE__ */ jsx96("span", { className: "fd-overline fd-muted fd-fb-menu-title", children: "Move to\u2026" }),
13227
- destinations.map((d) => /* @__PURE__ */ jsxs87(
13462
+ open2 ? /* @__PURE__ */ jsx97(InlinePanelLayers, { panel, children: /* @__PURE__ */ jsxs88("div", { className: "fd-fb-menu", role: "menu", "aria-label": label, style: { zIndex }, children: [
13463
+ /* @__PURE__ */ jsx97("span", { className: "fd-overline fd-muted fd-fb-menu-title", children: "Move to\u2026" }),
13464
+ destinations.map((d) => /* @__PURE__ */ jsxs88(
13228
13465
  "button",
13229
13466
  {
13230
13467
  type: "button",
@@ -13236,7 +13473,7 @@ function FolderPickerMenu({
13236
13473
  setOpen(false);
13237
13474
  },
13238
13475
  children: [
13239
- /* @__PURE__ */ jsx96("i", { className: "ph ph-" + (d.id == null ? "house-simple" : "folder-simple"), "aria-hidden": "true" }),
13476
+ /* @__PURE__ */ jsx97("i", { className: "ph ph-" + (d.id == null ? "house-simple" : "folder-simple"), "aria-hidden": "true" }),
13240
13477
  d.name
13241
13478
  ]
13242
13479
  },
@@ -13246,8 +13483,8 @@ function FolderPickerMenu({
13246
13483
  ] });
13247
13484
  }
13248
13485
  function RowShell({ icon, name, meta, onOpen, draggableId, isDropTarget, onDropPayload, actions, className = "" }) {
13249
- const [over, setOver] = React65.useState(false);
13250
- const dragCounter = React65.useRef(0);
13486
+ const [over, setOver] = React66.useState(false);
13487
+ const dragCounter = React66.useRef(0);
13251
13488
  const dropHandlers = isDropTarget ? {
13252
13489
  onDragEnter: (e) => {
13253
13490
  if (!hasInternalPayload(e)) return;
@@ -13272,8 +13509,8 @@ function RowShell({ icon, name, meta, onOpen, draggableId, isDropTarget, onDropP
13272
13509
  if (payload && onDropPayload) onDropPayload(payload);
13273
13510
  }
13274
13511
  } : {};
13275
- return /* @__PURE__ */ jsxs87("div", { className: ["fd-fb-row", over ? "is-drop-target" : "", className].filter(Boolean).join(" "), ...dropHandlers, children: [
13276
- /* @__PURE__ */ jsxs87(
13512
+ return /* @__PURE__ */ jsxs88("div", { className: ["fd-fb-row", over ? "is-drop-target" : "", className].filter(Boolean).join(" "), ...dropHandlers, children: [
13513
+ /* @__PURE__ */ jsxs88(
13277
13514
  "button",
13278
13515
  {
13279
13516
  type: "button",
@@ -13282,26 +13519,26 @@ function RowShell({ icon, name, meta, onOpen, draggableId, isDropTarget, onDropP
13282
13519
  draggable: !!draggableId,
13283
13520
  onDragStart: draggableId ? (e) => writeDragPayload(e, draggableId) : void 0,
13284
13521
  children: [
13285
- /* @__PURE__ */ jsx96("span", { className: "fd-fb-row-icon", "aria-hidden": "true", children: /* @__PURE__ */ jsx96("i", { className: "ph ph-" + icon }) }),
13286
- /* @__PURE__ */ jsxs87("span", { className: "fd-fb-row-text", children: [
13287
- /* @__PURE__ */ jsx96("span", { className: "fd-fb-row-name", title: name, children: name }),
13288
- meta ? /* @__PURE__ */ jsx96("span", { className: "fd-fb-row-meta", children: meta }) : null
13522
+ /* @__PURE__ */ jsx97("span", { className: "fd-fb-row-icon", "aria-hidden": "true", children: /* @__PURE__ */ jsx97("i", { className: "ph ph-" + icon }) }),
13523
+ /* @__PURE__ */ jsxs88("span", { className: "fd-fb-row-text", children: [
13524
+ /* @__PURE__ */ jsx97("span", { className: "fd-fb-row-name", title: name, children: name }),
13525
+ meta ? /* @__PURE__ */ jsx97("span", { className: "fd-fb-row-meta", children: meta }) : null
13289
13526
  ] })
13290
13527
  ]
13291
13528
  }
13292
13529
  ),
13293
- actions ? /* @__PURE__ */ jsx96("span", { className: "fd-fb-row-actions", children: actions }) : null
13530
+ actions ? /* @__PURE__ */ jsx97("span", { className: "fd-fb-row-actions", children: actions }) : null
13294
13531
  ] });
13295
13532
  }
13296
13533
  function TreeNode({ folder, depth, folders, currentFolderId, onNavigate, onMoveInto, canMove }) {
13297
13534
  const kids = childrenOf(folders, folder.id);
13298
- const [expanded, setExpanded] = React65.useState(() => currentFolderId != null && isSelfOrDescendant(folders, folder.id, currentFolderId));
13299
- React65.useEffect(() => {
13535
+ const [expanded, setExpanded] = React66.useState(() => currentFolderId != null && isSelfOrDescendant(folders, folder.id, currentFolderId));
13536
+ React66.useEffect(() => {
13300
13537
  if (currentFolderId != null && isSelfOrDescendant(folders, folder.id, currentFolderId)) setExpanded(true);
13301
13538
  }, [currentFolderId, folder.id, folders]);
13302
13539
  const isCurrent = folder.id === currentFolderId;
13303
- return /* @__PURE__ */ jsxs87("div", { className: "fd-fb-tree-node", children: [
13304
- /* @__PURE__ */ jsx96(
13540
+ return /* @__PURE__ */ jsxs88("div", { className: "fd-fb-tree-node", children: [
13541
+ /* @__PURE__ */ jsx97(
13305
13542
  RowShell,
13306
13543
  {
13307
13544
  icon: folder.id === currentFolderId ? "folder-open" : "folder-simple",
@@ -13311,7 +13548,7 @@ function TreeNode({ folder, depth, folders, currentFolderId, onNavigate, onMoveI
13311
13548
  isDropTarget: canMove,
13312
13549
  onDropPayload: (payload) => onMoveInto(payload, folder.id),
13313
13550
  className: ["fd-fb-tree-row", isCurrent ? "is-current" : ""].filter(Boolean).join(" "),
13314
- actions: kids.length ? /* @__PURE__ */ jsx96(
13551
+ actions: kids.length ? /* @__PURE__ */ jsx97(
13315
13552
  IconButton,
13316
13553
  {
13317
13554
  icon: expanded ? "caret-down" : "caret-right",
@@ -13323,7 +13560,7 @@ function TreeNode({ folder, depth, folders, currentFolderId, onNavigate, onMoveI
13323
13560
  ) : void 0
13324
13561
  }
13325
13562
  ),
13326
- expanded && kids.length ? /* @__PURE__ */ jsx96("div", { className: "fd-fb-tree-children", style: { paddingLeft: 14 }, children: kids.map((k) => /* @__PURE__ */ jsx96(
13563
+ expanded && kids.length ? /* @__PURE__ */ jsx97("div", { className: "fd-fb-tree-children", style: { paddingLeft: 14 }, children: kids.map((k) => /* @__PURE__ */ jsx97(
13327
13564
  TreeNode,
13328
13565
  {
13329
13566
  folder: k,
@@ -13362,15 +13599,15 @@ function FileBrowser({
13362
13599
  const canUpload = perm.canUpload !== false && !!onUpload;
13363
13600
  const canRemoveFile = perm.canRemoveFile !== false && !!onRemoveFile;
13364
13601
  const canDeleteFolder = perm.canDeleteFolder !== false && !!onDeleteFolder;
13365
- const [createOpen, setCreateOpen] = React65.useState(false);
13366
- const [createName, setCreateName] = React65.useState("");
13367
- const [renameTarget, setRenameTarget] = React65.useState(null);
13368
- const [renameValue, setRenameValue] = React65.useState("");
13369
- const [deleteTarget, setDeleteTarget] = React65.useState(null);
13370
- const uploadInputRef = React65.useRef(null);
13371
- const crumbFolders = React65.useMemo(() => ancestorsOf(folders, currentFolderId), [folders, currentFolderId]);
13372
- const subfolders = React65.useMemo(() => childrenOf(folders, currentFolderId), [folders, currentFolderId]);
13373
- const currentFiles = React65.useMemo(
13602
+ const [createOpen, setCreateOpen] = React66.useState(false);
13603
+ const [createName, setCreateName] = React66.useState("");
13604
+ const [renameTarget, setRenameTarget] = React66.useState(null);
13605
+ const [renameValue, setRenameValue] = React66.useState("");
13606
+ const [deleteTarget, setDeleteTarget] = React66.useState(null);
13607
+ const uploadInputRef = React66.useRef(null);
13608
+ const crumbFolders = React66.useMemo(() => ancestorsOf(folders, currentFolderId), [folders, currentFolderId]);
13609
+ const subfolders = React66.useMemo(() => childrenOf(folders, currentFolderId), [folders, currentFolderId]);
13610
+ const currentFiles = React66.useMemo(
13374
13611
  () => files.filter((f) => f.folderId === currentFolderId).sort((a, b) => a.name.localeCompare(b.name)),
13375
13612
  [files, currentFolderId]
13376
13613
  );
@@ -13409,10 +13646,10 @@ function FileBrowser({
13409
13646
  if (deleteTarget && onDeleteFolder) onDeleteFolder(deleteTarget);
13410
13647
  setDeleteTarget(null);
13411
13648
  };
13412
- const content = /* @__PURE__ */ jsxs87("div", { className: ["fd-fb", className].filter(Boolean).join(" "), children: [
13413
- /* @__PURE__ */ jsxs87("div", { className: "fd-fb-head", children: [
13414
- /* @__PURE__ */ jsxs87("nav", { className: "fd-fb-crumbs", "aria-label": "Folder path", children: [
13415
- /* @__PURE__ */ jsx96(
13649
+ const content = /* @__PURE__ */ jsxs88("div", { className: ["fd-fb", className].filter(Boolean).join(" "), children: [
13650
+ /* @__PURE__ */ jsxs88("div", { className: "fd-fb-head", children: [
13651
+ /* @__PURE__ */ jsxs88("nav", { className: "fd-fb-crumbs", "aria-label": "Folder path", children: [
13652
+ /* @__PURE__ */ jsx97(
13416
13653
  BreadcrumbCrumb,
13417
13654
  {
13418
13655
  label: "Home",
@@ -13422,7 +13659,7 @@ function FileBrowser({
13422
13659
  onDropPayload: (p) => moveIntoFolder(p, null)
13423
13660
  }
13424
13661
  ),
13425
- crumbFolders.map((f, i) => /* @__PURE__ */ jsx96(
13662
+ crumbFolders.map((f, i) => /* @__PURE__ */ jsx97(
13426
13663
  BreadcrumbCrumb,
13427
13664
  {
13428
13665
  label: f.name,
@@ -13434,11 +13671,11 @@ function FileBrowser({
13434
13671
  f.id
13435
13672
  ))
13436
13673
  ] }),
13437
- /* @__PURE__ */ jsxs87("span", { className: "fd-fb-actions", children: [
13438
- canCreateFolder ? /* @__PURE__ */ jsx96(Button, { variant: "secondary", size: "sm", icon: "folder-simple-plus", onClick: openCreate, children: "New folder" }) : null,
13439
- canUpload ? /* @__PURE__ */ jsxs87(Fragment28, { children: [
13440
- /* @__PURE__ */ jsx96(Button, { variant: "secondary", size: "sm", icon: "upload-simple", onClick: () => uploadInputRef.current && uploadInputRef.current.click(), children: "Upload" }),
13441
- /* @__PURE__ */ jsx96(
13674
+ /* @__PURE__ */ jsxs88("span", { className: "fd-fb-actions", children: [
13675
+ canCreateFolder ? /* @__PURE__ */ jsx97(Button, { variant: "secondary", size: "sm", icon: "folder-simple-plus", onClick: openCreate, children: "New folder" }) : null,
13676
+ canUpload ? /* @__PURE__ */ jsxs88(Fragment28, { children: [
13677
+ /* @__PURE__ */ jsx97(Button, { variant: "secondary", size: "sm", icon: "upload-simple", onClick: () => uploadInputRef.current && uploadInputRef.current.click(), children: "Upload" }),
13678
+ /* @__PURE__ */ jsx97(
13442
13679
  "input",
13443
13680
  {
13444
13681
  ref: uploadInputRef,
@@ -13456,9 +13693,9 @@ function FileBrowser({
13456
13693
  ] }) : null
13457
13694
  ] })
13458
13695
  ] }),
13459
- /* @__PURE__ */ jsxs87("div", { className: "fd-fb-body", children: [
13460
- /* @__PURE__ */ jsxs87("div", { className: "fd-fb-tree", role: "region", "aria-label": "Folder tree", children: [
13461
- /* @__PURE__ */ jsx96(
13696
+ /* @__PURE__ */ jsxs88("div", { className: "fd-fb-body", children: [
13697
+ /* @__PURE__ */ jsxs88("div", { className: "fd-fb-tree", role: "region", "aria-label": "Folder tree", children: [
13698
+ /* @__PURE__ */ jsx97(
13462
13699
  RowShell,
13463
13700
  {
13464
13701
  icon: "house-simple",
@@ -13469,7 +13706,7 @@ function FileBrowser({
13469
13706
  className: ["fd-fb-tree-row", currentFolderId == null ? "is-current" : ""].filter(Boolean).join(" ")
13470
13707
  }
13471
13708
  ),
13472
- childrenOf(folders, null).map((f) => /* @__PURE__ */ jsx96(
13709
+ childrenOf(folders, null).map((f) => /* @__PURE__ */ jsx97(
13473
13710
  TreeNode,
13474
13711
  {
13475
13712
  folder: f,
@@ -13483,18 +13720,18 @@ function FileBrowser({
13483
13720
  f.id
13484
13721
  ))
13485
13722
  ] }),
13486
- /* @__PURE__ */ jsx96("div", { className: "fd-fb-main", role: "region", "aria-label": "Folder contents", children: /* @__PURE__ */ jsx96(
13723
+ /* @__PURE__ */ jsx97("div", { className: "fd-fb-main", role: "region", "aria-label": "Folder contents", children: /* @__PURE__ */ jsx97(
13487
13724
  LoadingRegion,
13488
13725
  {
13489
13726
  state: loading ? "loading" : "ready",
13490
13727
  label: "Loading folder contents",
13491
- skeleton: /* @__PURE__ */ jsxs87("div", { className: "fd-stack", style: { gap: 8, padding: 12 }, children: [
13492
- /* @__PURE__ */ jsx96(Skeleton, { h: 44, radius: "10px" }),
13493
- /* @__PURE__ */ jsx96(Skeleton, { h: 44, radius: "10px" }),
13494
- /* @__PURE__ */ jsx96(Skeleton, { h: 44, radius: "10px" })
13728
+ skeleton: /* @__PURE__ */ jsxs88("div", { className: "fd-stack", style: { gap: 8, padding: 12 }, children: [
13729
+ /* @__PURE__ */ jsx97(Skeleton, { h: 44, radius: "10px" }),
13730
+ /* @__PURE__ */ jsx97(Skeleton, { h: 44, radius: "10px" }),
13731
+ /* @__PURE__ */ jsx97(Skeleton, { h: 44, radius: "10px" })
13495
13732
  ] }),
13496
- children: isEmpty ? /* @__PURE__ */ jsx96(EmptyState, { icon: "folder-open", title: "This folder is empty", children: canUpload ? "Drop files here, or use Upload above." : "Nothing has been filed here yet." }) : /* @__PURE__ */ jsxs87("div", { className: "fd-fb-list", children: [
13497
- subfolders.map((f) => /* @__PURE__ */ jsx96(
13733
+ children: isEmpty ? /* @__PURE__ */ jsx97(EmptyState, { icon: "folder-open", title: "This folder is empty", children: canUpload ? "Drop files here, or use Upload above." : "Nothing has been filed here yet." }) : /* @__PURE__ */ jsxs88("div", { className: "fd-fb-list", children: [
13734
+ subfolders.map((f) => /* @__PURE__ */ jsx97(
13498
13735
  RowShell,
13499
13736
  {
13500
13737
  icon: "folder-simple",
@@ -13503,9 +13740,9 @@ function FileBrowser({
13503
13740
  draggableId: canMove ? { kind: "folder", id: f.id } : void 0,
13504
13741
  isDropTarget: canMove,
13505
13742
  onDropPayload: (p) => moveIntoFolder(p, f.id),
13506
- actions: /* @__PURE__ */ jsxs87(Fragment28, { children: [
13507
- canRenameFolder ? /* @__PURE__ */ jsx96(IconButton, { icon: "pencil-simple", label: "Rename " + f.name, size: "sm", variant: "ghost", onClick: () => openRename(f) }) : null,
13508
- canMove ? /* @__PURE__ */ jsx96(
13743
+ actions: /* @__PURE__ */ jsxs88(Fragment28, { children: [
13744
+ canRenameFolder ? /* @__PURE__ */ jsx97(IconButton, { icon: "pencil-simple", label: "Rename " + f.name, size: "sm", variant: "ghost", onClick: () => openRename(f) }) : null,
13745
+ canMove ? /* @__PURE__ */ jsx97(
13509
13746
  FolderPickerMenu,
13510
13747
  {
13511
13748
  label: "Move " + f.name,
@@ -13513,12 +13750,12 @@ function FileBrowser({
13513
13750
  onPick: (target) => moveIntoFolder({ kind: "folder", id: f.id }, target)
13514
13751
  }
13515
13752
  ) : null,
13516
- canDeleteFolder ? /* @__PURE__ */ jsx96(IconButton, { icon: "trash-simple", label: "Delete " + f.name, size: "sm", variant: "ghost", onClick: () => openDelete(f) }) : null
13753
+ canDeleteFolder ? /* @__PURE__ */ jsx97(IconButton, { icon: "trash-simple", label: "Delete " + f.name, size: "sm", variant: "ghost", onClick: () => openDelete(f) }) : null
13517
13754
  ] })
13518
13755
  },
13519
13756
  f.id
13520
13757
  )),
13521
- currentFiles.map((file) => /* @__PURE__ */ jsx96(
13758
+ currentFiles.map((file) => /* @__PURE__ */ jsx97(
13522
13759
  RowShell,
13523
13760
  {
13524
13761
  icon: iconForMime(file.mime, file.name),
@@ -13526,8 +13763,8 @@ function FileBrowser({
13526
13763
  meta: file.size ? formatBytes(file.size) : void 0,
13527
13764
  onOpen: onOpenFile ? () => onOpenFile(file) : void 0,
13528
13765
  draggableId: canMove ? { kind: "file", id: file.id } : void 0,
13529
- actions: /* @__PURE__ */ jsxs87(Fragment28, { children: [
13530
- canMove ? /* @__PURE__ */ jsx96(
13766
+ actions: /* @__PURE__ */ jsxs88(Fragment28, { children: [
13767
+ canMove ? /* @__PURE__ */ jsx97(
13531
13768
  FolderPickerMenu,
13532
13769
  {
13533
13770
  label: "Move " + file.name,
@@ -13535,7 +13772,7 @@ function FileBrowser({
13535
13772
  onPick: (target) => onMoveFile && onMoveFile(file.id, target)
13536
13773
  }
13537
13774
  ) : null,
13538
- canRemoveFile ? /* @__PURE__ */ jsx96(IconButton, { icon: "trash-simple", label: "Remove " + file.name, size: "sm", variant: "ghost", onClick: () => onRemoveFile && onRemoveFile(file) }) : null
13775
+ canRemoveFile ? /* @__PURE__ */ jsx97(IconButton, { icon: "trash-simple", label: "Remove " + file.name, size: "sm", variant: "ghost", onClick: () => onRemoveFile && onRemoveFile(file) }) : null
13539
13776
  ] })
13540
13777
  },
13541
13778
  file.id
@@ -13544,10 +13781,10 @@ function FileBrowser({
13544
13781
  }
13545
13782
  ) })
13546
13783
  ] }),
13547
- /* @__PURE__ */ jsx96(Modal, { open: createOpen, title: "New folder", onClose: () => setCreateOpen(false), footer: /* @__PURE__ */ jsxs87(Fragment28, { children: [
13548
- /* @__PURE__ */ jsx96(Button, { variant: "secondary", onClick: () => setCreateOpen(false), children: "Cancel" }),
13549
- /* @__PURE__ */ jsx96(Button, { onClick: submitCreate, disabled: !createName.trim(), children: "Create" })
13550
- ] }), children: /* @__PURE__ */ jsx96(
13784
+ /* @__PURE__ */ jsx97(Modal, { open: createOpen, title: "New folder", onClose: () => setCreateOpen(false), footer: /* @__PURE__ */ jsxs88(Fragment28, { children: [
13785
+ /* @__PURE__ */ jsx97(Button, { variant: "secondary", onClick: () => setCreateOpen(false), children: "Cancel" }),
13786
+ /* @__PURE__ */ jsx97(Button, { onClick: submitCreate, disabled: !createName.trim(), children: "Create" })
13787
+ ] }), children: /* @__PURE__ */ jsx97(
13551
13788
  "input",
13552
13789
  {
13553
13790
  className: "fd-fb-input",
@@ -13561,10 +13798,10 @@ function FileBrowser({
13561
13798
  autoFocus: true
13562
13799
  }
13563
13800
  ) }),
13564
- /* @__PURE__ */ jsx96(Modal, { open: renameTarget != null, title: "Rename folder", onClose: () => setRenameTarget(null), footer: /* @__PURE__ */ jsxs87(Fragment28, { children: [
13565
- /* @__PURE__ */ jsx96(Button, { variant: "secondary", onClick: () => setRenameTarget(null), children: "Cancel" }),
13566
- /* @__PURE__ */ jsx96(Button, { onClick: submitRename, disabled: !renameValue.trim(), children: "Save" })
13567
- ] }), children: /* @__PURE__ */ jsx96(
13801
+ /* @__PURE__ */ jsx97(Modal, { open: renameTarget != null, title: "Rename folder", onClose: () => setRenameTarget(null), footer: /* @__PURE__ */ jsxs88(Fragment28, { children: [
13802
+ /* @__PURE__ */ jsx97(Button, { variant: "secondary", onClick: () => setRenameTarget(null), children: "Cancel" }),
13803
+ /* @__PURE__ */ jsx97(Button, { onClick: submitRename, disabled: !renameValue.trim(), children: "Save" })
13804
+ ] }), children: /* @__PURE__ */ jsx97(
13568
13805
  "input",
13569
13806
  {
13570
13807
  className: "fd-fb-input",
@@ -13578,22 +13815,22 @@ function FileBrowser({
13578
13815
  autoFocus: true
13579
13816
  }
13580
13817
  ) }),
13581
- /* @__PURE__ */ jsx96(
13818
+ /* @__PURE__ */ jsx97(
13582
13819
  Modal,
13583
13820
  {
13584
13821
  open: deleteTarget != null,
13585
13822
  title: deleteTarget ? "Delete \u201C" + deleteTarget.name + "\u201D?" : "Delete folder?",
13586
13823
  description: "This can't be undone. The folder must be empty.",
13587
13824
  onClose: () => setDeleteTarget(null),
13588
- footer: /* @__PURE__ */ jsxs87(Fragment28, { children: [
13589
- /* @__PURE__ */ jsx96(Button, { variant: "secondary", onClick: () => setDeleteTarget(null), children: "Cancel" }),
13590
- /* @__PURE__ */ jsx96(Button, { variant: "danger", onClick: confirmDelete, children: "Delete" })
13825
+ footer: /* @__PURE__ */ jsxs88(Fragment28, { children: [
13826
+ /* @__PURE__ */ jsx97(Button, { variant: "secondary", onClick: () => setDeleteTarget(null), children: "Cancel" }),
13827
+ /* @__PURE__ */ jsx97(Button, { variant: "danger", onClick: confirmDelete, children: "Delete" })
13591
13828
  ] })
13592
13829
  }
13593
13830
  )
13594
13831
  ] });
13595
13832
  if (!canUpload) return content;
13596
- return /* @__PURE__ */ jsx96(Dropzone, { className: "fd-fb-dropzone", onFiles: (picked) => onUpload && onUpload(picked, currentFolderId), label: "Drop files to upload", children: content });
13833
+ return /* @__PURE__ */ jsx97(Dropzone, { className: "fd-fb-dropzone", onFiles: (picked) => onUpload && onUpload(picked, currentFolderId), label: "Drop files to upload", children: content });
13597
13834
  }
13598
13835
  function BreadcrumbCrumb({
13599
13836
  label,
@@ -13602,8 +13839,8 @@ function BreadcrumbCrumb({
13602
13839
  isDropTarget,
13603
13840
  onDropPayload
13604
13841
  }) {
13605
- const [over, setOver] = React65.useState(false);
13606
- const dragCounter = React65.useRef(0);
13842
+ const [over, setOver] = React66.useState(false);
13843
+ const dragCounter = React66.useRef(0);
13607
13844
  const dropHandlers = isDropTarget ? {
13608
13845
  onDragEnter: (e) => {
13609
13846
  if (!hasInternalPayload(e)) return;
@@ -13628,11 +13865,11 @@ function BreadcrumbCrumb({
13628
13865
  if (payload && onDropPayload) onDropPayload(payload);
13629
13866
  }
13630
13867
  } : {};
13631
- return /* @__PURE__ */ jsx96("span", { className: ["fd-fb-crumb", over ? "is-drop-target" : ""].filter(Boolean).join(" "), ...dropHandlers, children: isCurrent ? /* @__PURE__ */ jsx96("span", { className: "fd-fb-crumb-current", "aria-current": "page", children: label }) : /* @__PURE__ */ jsx96("button", { type: "button", className: "fd-fb-crumb-link", onClick, children: label }) });
13868
+ return /* @__PURE__ */ jsx97("span", { className: ["fd-fb-crumb", over ? "is-drop-target" : ""].filter(Boolean).join(" "), ...dropHandlers, children: isCurrent ? /* @__PURE__ */ jsx97("span", { className: "fd-fb-crumb-current", "aria-current": "page", children: label }) : /* @__PURE__ */ jsx97("button", { type: "button", className: "fd-fb-crumb-link", onClick, children: label }) });
13632
13869
  }
13633
13870
 
13634
13871
  // src/kits/query.ts
13635
- import * as React66 from "react";
13872
+ import * as React67 from "react";
13636
13873
  var isMultiSelectShaped = (v) => !!v && typeof v === "object" && Array.isArray(v.values);
13637
13874
  var isRangeShaped = (v) => !!v && typeof v === "object" && ("min" in v || "max" in v);
13638
13875
  var isDateShaped = (v) => !!v && typeof v === "object" && "kind" in v;
@@ -13687,22 +13924,22 @@ function compare(a, b, dir) {
13687
13924
  var API = null;
13688
13925
  var PREFS = null;
13689
13926
  function useServerTable({ endpoint, params, defaults, deps, prefsKey }) {
13690
- const [query, setQuery] = React66.useState(() => {
13927
+ const [query, setQuery] = React67.useState(() => {
13691
13928
  const store = PREFS || window.PlannerPrefs;
13692
13929
  const saved = prefsKey && store ? store.getTable(prefsKey) : {};
13693
13930
  return { ...DEFAULTS, ...defaults || {}, ...saved.pageSize ? { pageSize: saved.pageSize } : {}, ...saved.sort ? { sort: saved.sort, dir: saved.dir || "desc" } : {} };
13694
13931
  });
13695
- const savePref = React66.useCallback((patch2) => {
13932
+ const savePref = React67.useCallback((patch2) => {
13696
13933
  const store = PREFS || window.PlannerPrefs;
13697
13934
  if (prefsKey && store) store.setTable(prefsKey, patch2);
13698
13935
  }, [prefsKey]);
13699
- const [res, setRes] = React66.useState(null);
13700
- const [loading, setLoading] = React66.useState(true);
13701
- const seq2 = React66.useRef(0);
13936
+ const [res, setRes] = React67.useState(null);
13937
+ const [loading, setLoading] = React67.useState(true);
13938
+ const seq2 = React67.useRef(0);
13702
13939
  const depKey = (deps || []).join("|");
13703
13940
  const paramKey = JSON.stringify(params || {});
13704
13941
  const queryKey = JSON.stringify(query);
13705
- React66.useEffect(() => {
13942
+ React67.useEffect(() => {
13706
13943
  const id = ++seq2.current;
13707
13944
  setLoading(true);
13708
13945
  const t = setTimeout(() => {
@@ -14021,12 +14258,12 @@ function createVersionStore(initialState, options) {
14021
14258
  }
14022
14259
 
14023
14260
  // src/kits/documentTitle.ts
14024
- import * as React67 from "react";
14261
+ import * as React68 from "react";
14025
14262
  function formatDocumentTitle(routeTitle, appName) {
14026
14263
  return [routeTitle, appName, "Flytedesk"].filter((part) => !!part && part.length > 0).join(" \xB7 ");
14027
14264
  }
14028
14265
  function useDocumentTitle(routeTitle, appName) {
14029
- React67.useEffect(() => {
14266
+ React68.useEffect(() => {
14030
14267
  if (typeof document === "undefined") return;
14031
14268
  document.title = formatDocumentTitle(routeTitle, appName);
14032
14269
  }, [routeTitle, appName]);
@@ -14068,6 +14305,7 @@ export {
14068
14305
  Clamp,
14069
14306
  ClockFace,
14070
14307
  CodeBlock,
14308
+ CodeEditor,
14071
14309
  Collapsible,
14072
14310
  ComingSoon,
14073
14311
  CsiBadge,