@flytedan/flytebot-design-system 0.68.0 → 0.70.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
@@ -1,3 +1,8 @@
1
+ import {
2
+ hideEscapes,
3
+ showEscapes,
4
+ showEscapesRaw
5
+ } from "./chunk-OVTWSE43.js";
1
6
  import {
2
7
  US_STATES,
3
8
  US_STATE_CODES,
@@ -5224,7 +5229,8 @@ var INLINE = [
5224
5229
  ];
5225
5230
  function inlineNodes(src, ctx, keyBase) {
5226
5231
  const out = [];
5227
- let rest = String(src == null ? "" : src), guard = 0;
5232
+ let rest = hideEscapes(String(src == null ? "" : src)), guard = 0;
5233
+ const d = showEscapes;
5228
5234
  const key = () => keyBase + "-" + out.length;
5229
5235
  while (rest && guard++ < 800) {
5230
5236
  let best = null;
@@ -5235,28 +5241,28 @@ function inlineNodes(src, ctx, keyBase) {
5235
5241
  }
5236
5242
  if (!best) break;
5237
5243
  const { kind, m } = best;
5238
- if (m.index > 0) out.push(rest.slice(0, m.index));
5244
+ if (m.index > 0) out.push(d(rest.slice(0, m.index)));
5239
5245
  const g = (i) => m[i];
5240
- if (kind === "code") out.push(/* @__PURE__ */ jsx54("code", { className: "fd-md-code", children: g(1) }, key()));
5246
+ if (kind === "code") out.push(/* @__PURE__ */ jsx54("code", { className: "fd-md-code", children: showEscapesRaw(g(1)) }, key()));
5241
5247
  else if (kind === "image") {
5242
- const src2 = safeHref(g(2));
5243
- out.push(ctx.allowImages && src2 ? /* @__PURE__ */ jsx54("img", { className: "fd-md-img", src: src2, alt: g(1) || "", title: g(3) || void 0, loading: "lazy" }, key()) : /* @__PURE__ */ jsx54("span", { className: "fd-md-imgalt", children: g(1) || "image" }, key()));
5248
+ const src2 = safeHref(d(g(2)));
5249
+ out.push(ctx.allowImages && src2 ? /* @__PURE__ */ jsx54("img", { className: "fd-md-img", src: src2, alt: d(g(1) || ""), title: g(3) ? d(g(3)) : void 0, loading: "lazy" }, key()) : /* @__PURE__ */ jsx54("span", { className: "fd-md-imgalt", children: d(g(1) || "image") }, key()));
5244
5250
  } else if (kind === "link") {
5245
- const href = safeHref(g(2));
5246
- out.push(href ? /* @__PURE__ */ jsx54("a", { href, title: g(3) || void 0, target: /^https?:/i.test(href) ? "_blank" : void 0, rel: "noopener noreferrer", onClick: ctx.onLinkClick, children: inlineNodes(g(1), ctx, key()) }, key()) : /* @__PURE__ */ jsx54("span", { children: g(1) }, key()));
5251
+ const href = safeHref(d(g(2)));
5252
+ out.push(href ? /* @__PURE__ */ jsx54("a", { href, title: g(3) ? d(g(3)) : void 0, target: /^https?:/i.test(href) ? "_blank" : void 0, rel: "noopener noreferrer", onClick: ctx.onLinkClick, children: inlineNodes(g(1), ctx, key()) }, key()) : /* @__PURE__ */ jsx54("span", { children: d(g(1)) }, key()));
5247
5253
  } else if (kind === "cite") {
5248
- out.push(ctx.renderCitation ? /* @__PURE__ */ jsx54(React35.Fragment, { children: ctx.renderCitation(g(1)) }, key()) : /* @__PURE__ */ jsx54("sup", { className: "fd-md-cite", children: g(1) }, key()));
5254
+ out.push(ctx.renderCitation ? /* @__PURE__ */ jsx54(React35.Fragment, { children: ctx.renderCitation(d(g(1))) }, key()) : /* @__PURE__ */ jsx54("sup", { className: "fd-md-cite", children: d(g(1)) }, key()));
5249
5255
  } else if (kind === "strongem") out.push(/* @__PURE__ */ jsx54("strong", { children: /* @__PURE__ */ jsx54("em", { children: inlineNodes(g(1), ctx, key()) }) }, key()));
5250
5256
  else if (kind === "strong") out.push(/* @__PURE__ */ jsx54("strong", { children: inlineNodes(g(1) || g(2), ctx, key()) }, key()));
5251
5257
  else if (kind === "em") out.push(/* @__PURE__ */ jsx54("em", { children: inlineNodes(g(1) || g(2), ctx, key()) }, key()));
5252
5258
  else if (kind === "del") out.push(/* @__PURE__ */ jsx54("del", { children: inlineNodes(g(1), ctx, key()) }, key()));
5253
5259
  else if (kind === "autolink" || kind === "bare") {
5254
- const href = safeHref(g(1));
5255
- out.push(href ? /* @__PURE__ */ jsx54("a", { href, target: "_blank", rel: "noopener noreferrer", onClick: ctx.onLinkClick, children: g(1).replace(/^mailto:/, "") }, key()) : g(1));
5260
+ const href = safeHref(d(g(1)));
5261
+ out.push(href ? /* @__PURE__ */ jsx54("a", { href, target: "_blank", rel: "noopener noreferrer", onClick: ctx.onLinkClick, children: d(g(1)).replace(/^mailto:/, "") }, key()) : d(g(1)));
5256
5262
  }
5257
5263
  rest = rest.slice(m.index + m[0].length);
5258
5264
  }
5259
- if (rest) out.push(rest);
5265
+ if (rest) out.push(d(rest));
5260
5266
  return out;
5261
5267
  }
5262
5268
  var RE = {
@@ -5268,7 +5274,26 @@ var RE = {
5268
5274
  task: /^\[([ xX])\]\s+(.*)$/,
5269
5275
  tableSep: /^\s*\|?[\s:|-]*-[\s:|-]*\|?\s*$/
5270
5276
  };
5271
- var splitRow = (line) => line.replace(/^\s*\|/, "").replace(/\|\s*$/, "").split("|").map((c) => c.trim());
5277
+ var splitRow = (line) => {
5278
+ const t = line.trim();
5279
+ const cells = [];
5280
+ let cur = "";
5281
+ for (let i = t.startsWith("|") ? 1 : 0; i < t.length; i++) {
5282
+ const c = t[i];
5283
+ if (c === "\\" && i + 1 < t.length) {
5284
+ cur += c + t[++i];
5285
+ continue;
5286
+ }
5287
+ if (c === "|") {
5288
+ cells.push(cur.trim());
5289
+ cur = "";
5290
+ continue;
5291
+ }
5292
+ cur += c;
5293
+ }
5294
+ if (cur.trim() || !t.endsWith("|")) cells.push(cur.trim());
5295
+ return cells;
5296
+ };
5272
5297
  function parseBlocks(src) {
5273
5298
  const lines = String(src == null ? "" : src).replace(/\r\n?/g, "\n").split("\n");
5274
5299
  const blocks = [];
@@ -5400,6 +5425,7 @@ function renderBlocks(blocks, ctx, path) {
5400
5425
  }
5401
5426
  });
5402
5427
  }
5428
+ var mdClass = (base, size, tone, className) => [base, size && `${base}--${size}`, tone === "muted" && `${base}--muted`, className].filter(Boolean).join(" ");
5403
5429
  function Markdown({
5404
5430
  source = "",
5405
5431
  className = "",
@@ -5407,14 +5433,16 @@ function Markdown({
5407
5433
  allowImages = true,
5408
5434
  headingOffset = 0,
5409
5435
  renderCitation,
5410
- onLinkClick
5436
+ onLinkClick,
5437
+ size = "body",
5438
+ tone = "default"
5411
5439
  }) {
5412
5440
  const ctx = { allowImages, headingOffset, renderCitation, onLinkClick, codeProps };
5413
5441
  const blocks = React35.useMemo(() => parseBlocks(source), [source]);
5414
- return /* @__PURE__ */ jsx54("div", { className: ["fd-md", className].filter(Boolean).join(" "), children: renderBlocks(blocks, ctx, "b") });
5442
+ return /* @__PURE__ */ jsx54("div", { className: mdClass("fd-md", size, tone, className), children: renderBlocks(blocks, ctx, "b") });
5415
5443
  }
5416
- function MarkdownInline({ source = "", className = "", onLinkClick }) {
5417
- return /* @__PURE__ */ jsx54("span", { className: ["fd-md-inline", className].filter(Boolean).join(" "), children: inlineNodes(source, { allowImages: false, onLinkClick }, "i") });
5444
+ function MarkdownInline({ source = "", className = "", onLinkClick, size, tone }) {
5445
+ return /* @__PURE__ */ jsx54("span", { className: mdClass("fd-md-inline", size, tone, className), children: inlineNodes(source, { allowImages: false, onLinkClick }, "i") });
5418
5446
  }
5419
5447
  function markdownToText(src) {
5420
5448
  return String(src == null ? "" : src).replace(/```[\w+#-]*\n?([\s\S]*?)```/g, "$1").replace(/`([^`]+)`/g, "$1").replace(/!\[([^\]]*)\]\([^)]*\)/g, "$1").replace(/\[([^\]]+)\]\([^)]*\)/g, "$1").replace(/^\s{0,3}#{1,6}\s+/gm, "").replace(/\*\*\*([^*]+)\*\*\*|\*\*([^*]+)\*\*|__([^_]+)__/g, "$1$2$3").replace(/(^|\W)[*_]([^*_\n]+)[*_](\W|$)/g, "$1$2$3").replace(/~~([^~]+)~~/g, "$1").replace(/^\s*>\s?/gm, "").trim();
@@ -6678,14 +6706,17 @@ function Checkbox({ label, description, card = false, indeterminate = false, cla
6678
6706
 
6679
6707
  // src/components/forms/Radio.tsx
6680
6708
  import { jsx as jsx69, jsxs as jsxs58 } from "react/jsx-runtime";
6681
- function Radio({ label, description, card = false, className = "", ...rest }) {
6709
+ function Radio({ label, description, badge, card = false, className = "", ...rest }) {
6682
6710
  return /* @__PURE__ */ jsxs58("label", { className: ["fd-choice", card ? "fd-choice-card" : "", className].filter(Boolean).join(" "), children: [
6683
6711
  /* @__PURE__ */ jsxs58("span", { className: "fd-choice-input", children: [
6684
6712
  /* @__PURE__ */ jsx69("input", { type: "radio", ...rest }),
6685
6713
  /* @__PURE__ */ jsx69("span", { className: "fd-choice-box fd-choice-box-round", "aria-hidden": "true", children: /* @__PURE__ */ jsx69("span", { className: "fd-choice-dot" }) })
6686
6714
  ] }),
6687
6715
  /* @__PURE__ */ jsxs58("span", { className: "fd-choice-text", children: [
6688
- /* @__PURE__ */ jsx69("span", { className: "fd-choice-title", children: label }),
6716
+ /* @__PURE__ */ jsxs58("span", { className: "fd-choice-title", children: [
6717
+ label,
6718
+ badge ? /* @__PURE__ */ jsx69("span", { className: "fd-choice-badge", children: badge }) : null
6719
+ ] }),
6689
6720
  description ? /* @__PURE__ */ jsx69("span", { className: "fd-choice-desc", children: description }) : null
6690
6721
  ] })
6691
6722
  ] });
@@ -8277,17 +8308,49 @@ function CodeEditor({
8277
8308
  ] });
8278
8309
  }
8279
8310
 
8311
+ // src/components/forms/RadioGroup.tsx
8312
+ import * as React53 from "react";
8313
+ import { jsx as jsx79, jsxs as jsxs68 } from "react/jsx-runtime";
8314
+ function RadioGroup({ label, options, value, onChange, card = false, disabled = false, name, className = "" }) {
8315
+ const autoName = React53.useId();
8316
+ const labelId = React53.useId();
8317
+ return /* @__PURE__ */ jsxs68("div", { role: "radiogroup", "aria-labelledby": labelId, "aria-disabled": disabled || void 0, className: ["fd-radiogroup", className].filter(Boolean).join(" "), children: [
8318
+ /* @__PURE__ */ jsx79("span", { id: labelId, className: "fd-radiogroup-label", children: label }),
8319
+ options.map((o) => /* @__PURE__ */ jsx79(
8320
+ Radio,
8321
+ {
8322
+ card,
8323
+ name: name ?? autoName,
8324
+ value: o.value,
8325
+ label: o.label,
8326
+ description: o.description,
8327
+ badge: o.badge,
8328
+ checked: o.value === value,
8329
+ disabled: disabled || o.disabled,
8330
+ onChange: () => onChange(o.value)
8331
+ },
8332
+ o.value
8333
+ ))
8334
+ ] });
8335
+ }
8336
+
8337
+ // src/components/forms/Fieldset.tsx
8338
+ import { jsx as jsx80 } from "react/jsx-runtime";
8339
+ function Fieldset({ busy = false, className = "", ...rest }) {
8340
+ return /* @__PURE__ */ jsx80("fieldset", { disabled: busy, "aria-busy": busy || void 0, className: ["fd-fieldset", className].filter(Boolean).join(" "), ...rest });
8341
+ }
8342
+
8280
8343
  // src/components/platform/AccountMenu.tsx
8281
- import * as React54 from "react";
8344
+ import * as React55 from "react";
8282
8345
 
8283
8346
  // src/kits/sessionContext.tsx
8284
- import * as React53 from "react";
8285
- var SessionContext = React53.createContext(null);
8347
+ import * as React54 from "react";
8348
+ var SessionContext = React54.createContext(null);
8286
8349
  function SessionProvider({ value, children }) {
8287
- return React53.createElement(SessionContext.Provider, { value }, children);
8350
+ return React54.createElement(SessionContext.Provider, { value }, children);
8288
8351
  }
8289
8352
  function useSessionContext() {
8290
- const ctx = React53.useContext(SessionContext);
8353
+ const ctx = React54.useContext(SessionContext);
8291
8354
  if (!ctx) {
8292
8355
  throw new Error(
8293
8356
  "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."
@@ -8297,11 +8360,11 @@ function useSessionContext() {
8297
8360
  }
8298
8361
 
8299
8362
  // src/components/platform/AccountMenu.tsx
8300
- import { Fragment as Fragment19, jsx as jsx79, jsxs as jsxs68 } from "react/jsx-runtime";
8363
+ import { Fragment as Fragment19, jsx as jsx81, jsxs as jsxs69 } from "react/jsx-runtime";
8301
8364
  var DEFAULT_LINKS = [];
8302
8365
  var DEFAULT_GROUPS = [];
8303
8366
  function Item({ item, onPick }) {
8304
- return /* @__PURE__ */ jsxs68(
8367
+ return /* @__PURE__ */ jsxs69(
8305
8368
  "button",
8306
8369
  {
8307
8370
  type: "button",
@@ -8309,9 +8372,9 @@ function Item({ item, onPick }) {
8309
8372
  className: "fd-acct-item",
8310
8373
  onClick: () => onPick(item),
8311
8374
  children: [
8312
- item.icon ? /* @__PURE__ */ jsx79("i", { className: "ph ph-" + item.icon, "aria-hidden": "true" }) : null,
8313
- /* @__PURE__ */ jsx79("span", { style: { flex: 1 }, children: item.label }),
8314
- item.badge ? /* @__PURE__ */ jsx79(Badge, { tone: "neutral", children: item.badge }) : null
8375
+ item.icon ? /* @__PURE__ */ jsx81("i", { className: "ph ph-" + item.icon, "aria-hidden": "true" }) : null,
8376
+ /* @__PURE__ */ jsx81("span", { style: { flex: 1 }, children: item.label }),
8377
+ item.badge ? /* @__PURE__ */ jsx81(Badge, { tone: "neutral", children: item.badge }) : null
8315
8378
  ]
8316
8379
  }
8317
8380
  );
@@ -8327,11 +8390,11 @@ function AccountMenu({
8327
8390
  ...rest
8328
8391
  }) {
8329
8392
  const { user, roles, can: can2, signOut: ctxSignOut, demo, pending } = useSessionContext();
8330
- const [open2, setOpen] = React54.useState(false);
8331
- const [switching, setSwitching] = React54.useState(false);
8332
- const [signingOut, setSigningOut] = React54.useState(false);
8333
- const [signOutError, setSignOutError] = React54.useState(null);
8334
- const ref = React54.useRef(null);
8393
+ const [open2, setOpen] = React55.useState(false);
8394
+ const [switching, setSwitching] = React55.useState(false);
8395
+ const [signingOut, setSigningOut] = React55.useState(false);
8396
+ const [signOutError, setSignOutError] = React55.useState(null);
8397
+ const ref = React55.useRef(null);
8335
8398
  const visibleLinks = links.filter((l) => !l.perm || !pending && can2(l.perm));
8336
8399
  const visibleGroups = groups.map((g) => ({ label: g.label, links: g.links.filter((l) => !l.perm || !pending && can2(l.perm)) })).filter((g) => g.links.length);
8337
8400
  const closeMenu = () => {
@@ -8359,8 +8422,8 @@ function AccountMenu({
8359
8422
  }
8360
8423
  };
8361
8424
  const showSwitcher = allowUserSwitch && !!demo;
8362
- return /* @__PURE__ */ jsxs68(Fragment19, { children: [
8363
- /* @__PURE__ */ jsxs68(
8425
+ return /* @__PURE__ */ jsxs69(Fragment19, { children: [
8426
+ /* @__PURE__ */ jsxs69(
8364
8427
  "button",
8365
8428
  {
8366
8429
  type: "button",
@@ -8372,12 +8435,12 @@ function AccountMenu({
8372
8435
  onClick: () => open2 ? closeMenu() : setOpen(true),
8373
8436
  ...rest,
8374
8437
  children: [
8375
- /* @__PURE__ */ jsx79(Avatar, { name: user.name, size: "sm" }),
8376
- /* @__PURE__ */ jsx79("i", { className: "ph ph-caret-down", "aria-hidden": "true", style: { fontSize: 11, color: "var(--text-muted)" } })
8438
+ /* @__PURE__ */ jsx81(Avatar, { name: user.name, size: "sm" }),
8439
+ /* @__PURE__ */ jsx81("i", { className: "ph ph-caret-down", "aria-hidden": "true", style: { fontSize: 11, color: "var(--text-muted)" } })
8377
8440
  ]
8378
8441
  }
8379
8442
  ),
8380
- /* @__PURE__ */ jsx79(
8443
+ /* @__PURE__ */ jsx81(
8381
8444
  Popover,
8382
8445
  {
8383
8446
  open: open2,
@@ -8385,27 +8448,27 @@ function AccountMenu({
8385
8448
  onClose: closeMenu,
8386
8449
  placement: "bottom-end",
8387
8450
  width: 272,
8388
- children: /* @__PURE__ */ jsxs68("div", { role: "menu", className: "fd-stack", style: { gap: 0 }, children: [
8389
- /* @__PURE__ */ jsxs68("div", { className: "fd-row", style: { gap: 10, padding: "12px 14px", borderBottom: "1px solid var(--border)" }, children: [
8390
- /* @__PURE__ */ jsx79(Avatar, { name: user.name }),
8391
- /* @__PURE__ */ jsxs68("span", { className: "fd-stack", style: { gap: 1, minWidth: 0, flex: 1 }, children: [
8392
- /* @__PURE__ */ jsx79("span", { className: "fd-body-sm", style: { fontWeight: 700 }, children: user.name }),
8393
- /* @__PURE__ */ jsx79("span", { className: "fd-body-sm fd-muted fd-table-trunc", title: truncationTitle(user.email), children: user.email })
8451
+ children: /* @__PURE__ */ jsxs69("div", { role: "menu", className: "fd-stack", style: { gap: 0 }, children: [
8452
+ /* @__PURE__ */ jsxs69("div", { className: "fd-row", style: { gap: 10, padding: "12px 14px", borderBottom: "1px solid var(--border)" }, children: [
8453
+ /* @__PURE__ */ jsx81(Avatar, { name: user.name }),
8454
+ /* @__PURE__ */ jsxs69("span", { className: "fd-stack", style: { gap: 1, minWidth: 0, flex: 1 }, children: [
8455
+ /* @__PURE__ */ jsx81("span", { className: "fd-body-sm", style: { fontWeight: 700 }, children: user.name }),
8456
+ /* @__PURE__ */ jsx81("span", { className: "fd-body-sm fd-muted fd-table-trunc", title: truncationTitle(user.email), children: user.email })
8394
8457
  ] })
8395
8458
  ] }),
8396
- showRoles && roles.length ? /* @__PURE__ */ jsx79("div", { className: "fd-row", style: { gap: 6, padding: "10px 14px", flexWrap: "wrap", borderBottom: "1px solid var(--border)" }, children: roles.map((r) => /* @__PURE__ */ jsx79(Badge, { tone: r.id === "owner" ? "success" : "neutral", children: r.name }, r.id)) }) : null,
8397
- visibleLinks.length ? /* @__PURE__ */ jsx79("div", { className: "fd-acct-group", children: visibleLinks.map((l) => /* @__PURE__ */ jsx79(Item, { item: l, onPick: pick }, l.id)) }) : null,
8398
- visibleGroups.map((g) => /* @__PURE__ */ jsxs68("div", { className: "fd-acct-group", style: { borderTop: "1px solid var(--border)" }, children: [
8399
- /* @__PURE__ */ jsx79("span", { className: "fd-overline fd-muted", style: { padding: "8px 14px 4px", display: "block" }, children: g.label }),
8400
- g.links.map((l) => /* @__PURE__ */ jsx79(Item, { item: l, onPick: pick }, l.id))
8459
+ showRoles && roles.length ? /* @__PURE__ */ jsx81("div", { className: "fd-row", style: { gap: 6, padding: "10px 14px", flexWrap: "wrap", borderBottom: "1px solid var(--border)" }, children: roles.map((r) => /* @__PURE__ */ jsx81(Badge, { tone: r.id === "owner" ? "success" : "neutral", children: r.name }, r.id)) }) : null,
8460
+ visibleLinks.length ? /* @__PURE__ */ jsx81("div", { className: "fd-acct-group", children: visibleLinks.map((l) => /* @__PURE__ */ jsx81(Item, { item: l, onPick: pick }, l.id)) }) : null,
8461
+ visibleGroups.map((g) => /* @__PURE__ */ jsxs69("div", { className: "fd-acct-group", style: { borderTop: "1px solid var(--border)" }, children: [
8462
+ /* @__PURE__ */ jsx81("span", { className: "fd-overline fd-muted", style: { padding: "8px 14px 4px", display: "block" }, children: g.label }),
8463
+ g.links.map((l) => /* @__PURE__ */ jsx81(Item, { item: l, onPick: pick }, l.id))
8401
8464
  ] }, g.label)),
8402
- showSwitcher && demo ? /* @__PURE__ */ jsxs68("div", { className: "fd-acct-group", style: { borderTop: "1px solid var(--border)" }, children: [
8403
- /* @__PURE__ */ jsxs68("button", { type: "button", role: "menuitem", className: "fd-acct-item", onClick: () => setSwitching((s) => !s), children: [
8404
- /* @__PURE__ */ jsx79("i", { className: "ph ph-user-switch", "aria-hidden": "true" }),
8405
- /* @__PURE__ */ jsx79("span", { style: { flex: 1 }, children: "View as another member" }),
8406
- /* @__PURE__ */ jsx79("i", { className: "ph ph-caret-" + (switching ? "up" : "down"), "aria-hidden": "true", style: { fontSize: 11 } })
8465
+ showSwitcher && demo ? /* @__PURE__ */ jsxs69("div", { className: "fd-acct-group", style: { borderTop: "1px solid var(--border)" }, children: [
8466
+ /* @__PURE__ */ jsxs69("button", { type: "button", role: "menuitem", className: "fd-acct-item", onClick: () => setSwitching((s) => !s), children: [
8467
+ /* @__PURE__ */ jsx81("i", { className: "ph ph-user-switch", "aria-hidden": "true" }),
8468
+ /* @__PURE__ */ jsx81("span", { style: { flex: 1 }, children: "View as another member" }),
8469
+ /* @__PURE__ */ jsx81("i", { className: "ph ph-caret-" + (switching ? "up" : "down"), "aria-hidden": "true", style: { fontSize: 11 } })
8407
8470
  ] }),
8408
- switching ? /* @__PURE__ */ jsx79("div", { className: "fd-stack", style: { gap: 0 }, children: demo.allUsers.map((u) => /* @__PURE__ */ jsxs68(
8471
+ switching ? /* @__PURE__ */ jsx81("div", { className: "fd-stack", style: { gap: 0 }, children: demo.allUsers.map((u) => /* @__PURE__ */ jsxs69(
8409
8472
  "button",
8410
8473
  {
8411
8474
  type: "button",
@@ -8417,19 +8480,19 @@ function AccountMenu({
8417
8480
  setSwitching(false);
8418
8481
  },
8419
8482
  children: [
8420
- /* @__PURE__ */ jsx79(Avatar, { name: u.name, size: "sm" }),
8421
- /* @__PURE__ */ jsxs68("span", { className: "fd-stack", style: { gap: 0, flex: 1, minWidth: 0, alignItems: "flex-start" }, children: [
8422
- /* @__PURE__ */ jsx79("span", { style: { fontWeight: u.id === user.id ? 700 : 500 }, children: u.name }),
8423
- u.roles ? /* @__PURE__ */ jsx79("span", { className: "fd-muted", style: { fontSize: 11.5 }, children: u.roles.join(", ") }) : null
8483
+ /* @__PURE__ */ jsx81(Avatar, { name: u.name, size: "sm" }),
8484
+ /* @__PURE__ */ jsxs69("span", { className: "fd-stack", style: { gap: 0, flex: 1, minWidth: 0, alignItems: "flex-start" }, children: [
8485
+ /* @__PURE__ */ jsx81("span", { style: { fontWeight: u.id === user.id ? 700 : 500 }, children: u.name }),
8486
+ u.roles ? /* @__PURE__ */ jsx81("span", { className: "fd-muted", style: { fontSize: 11.5 }, children: u.roles.join(", ") }) : null
8424
8487
  ] }),
8425
- u.id === user.id ? /* @__PURE__ */ jsx79("i", { className: "ph ph-check", "aria-hidden": "true", style: { color: "var(--ok-text)" } }) : null
8488
+ u.id === user.id ? /* @__PURE__ */ jsx81("i", { className: "ph ph-check", "aria-hidden": "true", style: { color: "var(--ok-text)" } }) : null
8426
8489
  ]
8427
8490
  },
8428
8491
  u.id
8429
8492
  )) }) : null
8430
8493
  ] }) : null,
8431
- /* @__PURE__ */ jsxs68("div", { className: "fd-acct-group", style: { borderTop: "1px solid var(--border)" }, children: [
8432
- /* @__PURE__ */ jsxs68(
8494
+ /* @__PURE__ */ jsxs69("div", { className: "fd-acct-group", style: { borderTop: "1px solid var(--border)" }, children: [
8495
+ /* @__PURE__ */ jsxs69(
8433
8496
  "button",
8434
8497
  {
8435
8498
  type: "button",
@@ -8439,14 +8502,14 @@ function AccountMenu({
8439
8502
  disabled: signingOut,
8440
8503
  onClick: signOut,
8441
8504
  children: [
8442
- signingOut ? /* @__PURE__ */ jsx79(Spinner, { size: "sm" }) : /* @__PURE__ */ jsx79("i", { className: "ph ph-sign-out", "aria-hidden": "true" }),
8443
- /* @__PURE__ */ jsx79("span", { style: { flex: 1 }, children: signingOut ? "Signing out\u2026" : "Sign out" })
8505
+ signingOut ? /* @__PURE__ */ jsx81(Spinner, { size: "sm" }) : /* @__PURE__ */ jsx81("i", { className: "ph ph-sign-out", "aria-hidden": "true" }),
8506
+ /* @__PURE__ */ jsx81("span", { style: { flex: 1 }, children: signingOut ? "Signing out\u2026" : "Sign out" })
8444
8507
  ]
8445
8508
  }
8446
8509
  ),
8447
- signOutError ? /* @__PURE__ */ jsxs68("div", { role: "alert", className: "fd-body-sm", style: { padding: "0 14px 12px" }, children: [
8448
- /* @__PURE__ */ jsx79("span", { style: { display: "block", color: "var(--danger-text)", marginBottom: 6 }, children: signOutError }),
8449
- /* @__PURE__ */ jsx79("button", { type: "button", className: "fd-soon-link", disabled: signingOut, onClick: signOut, children: "Retry" })
8510
+ signOutError ? /* @__PURE__ */ jsxs69("div", { role: "alert", className: "fd-body-sm", style: { padding: "0 14px 12px" }, children: [
8511
+ /* @__PURE__ */ jsx81("span", { style: { display: "block", color: "var(--danger-text)", marginBottom: 6 }, children: signOutError }),
8512
+ /* @__PURE__ */ jsx81("button", { type: "button", className: "fd-soon-link", disabled: signingOut, onClick: signOut, children: "Retry" })
8450
8513
  ] }) : null
8451
8514
  ] })
8452
8515
  ] })
@@ -8456,13 +8519,13 @@ function AccountMenu({
8456
8519
  }
8457
8520
 
8458
8521
  // src/components/platform/AppSwitcher.tsx
8459
- import * as React55 from "react";
8460
- import { jsx as jsx80, jsxs as jsxs69 } from "react/jsx-runtime";
8522
+ import * as React56 from "react";
8523
+ import { jsx as jsx82, jsxs as jsxs70 } from "react/jsx-runtime";
8461
8524
  function AppSwitcher({ apps: appsProp, onNavigate, className = "" }) {
8462
8525
  const { apps: contextApps } = useSessionContext();
8463
8526
  const apps = appsProp ?? contextApps ?? [];
8464
- const [open2, setOpen] = React55.useState(false);
8465
- const anchorRef = React55.useRef(null);
8527
+ const [open2, setOpen] = React56.useState(false);
8528
+ const anchorRef = React56.useRef(null);
8466
8529
  if (!apps.length) return null;
8467
8530
  const items = apps.map((app) => ({
8468
8531
  id: app.key,
@@ -8476,8 +8539,8 @@ function AppSwitcher({ apps: appsProp, onNavigate, className = "" }) {
8476
8539
  window.location.href = app.url;
8477
8540
  }
8478
8541
  }));
8479
- return /* @__PURE__ */ jsxs69(React55.Fragment, { children: [
8480
- /* @__PURE__ */ jsx80("span", { ref: anchorRef, className: ["fd-appswitch-anchor", className].filter(Boolean).join(" "), style: { display: "inline-flex" }, children: /* @__PURE__ */ jsx80(
8542
+ return /* @__PURE__ */ jsxs70(React56.Fragment, { children: [
8543
+ /* @__PURE__ */ jsx82("span", { ref: anchorRef, className: ["fd-appswitch-anchor", className].filter(Boolean).join(" "), style: { display: "inline-flex" }, children: /* @__PURE__ */ jsx82(
8481
8544
  IconButton,
8482
8545
  {
8483
8546
  icon: "squares-four",
@@ -8487,7 +8550,7 @@ function AppSwitcher({ apps: appsProp, onNavigate, className = "" }) {
8487
8550
  onClick: () => setOpen((v) => !v)
8488
8551
  }
8489
8552
  ) }),
8490
- /* @__PURE__ */ jsx80(
8553
+ /* @__PURE__ */ jsx82(
8491
8554
  Popover,
8492
8555
  {
8493
8556
  open: open2,
@@ -8498,17 +8561,17 @@ function AppSwitcher({ apps: appsProp, onNavigate, className = "" }) {
8498
8561
  label: "All flytedesk apps",
8499
8562
  width: 240,
8500
8563
  maxHeight: 360,
8501
- children: /* @__PURE__ */ jsx80(Menu, { items, onClose: () => setOpen(false) })
8564
+ children: /* @__PURE__ */ jsx82(Menu, { items, onClose: () => setOpen(false) })
8502
8565
  }
8503
8566
  )
8504
8567
  ] });
8505
8568
  }
8506
8569
 
8507
8570
  // src/components/platform/AppearanceMenu.tsx
8508
- import * as React58 from "react";
8571
+ import * as React59 from "react";
8509
8572
 
8510
8573
  // src/kits/appearance.ts
8511
- import * as React56 from "react";
8574
+ import * as React57 from "react";
8512
8575
  var DEFAULT_STORAGE_KEY = "fd-appearance";
8513
8576
  var DEFAULT_PREFS = {
8514
8577
  theme: "system",
@@ -8620,8 +8683,8 @@ function watchAppearance(store, root = document.documentElement) {
8620
8683
  };
8621
8684
  }
8622
8685
  function useAppearancePrefs(store) {
8623
- const prefs = React56.useSyncExternalStore(store.subscribe, store.getSnapshot);
8624
- const update = React56.useCallback(
8686
+ const prefs = React57.useSyncExternalStore(store.subscribe, store.getSnapshot);
8687
+ const update = React57.useCallback(
8625
8688
  (patch) => {
8626
8689
  store.write({ ...store.getSnapshot(), ...patch });
8627
8690
  },
@@ -8631,21 +8694,21 @@ function useAppearancePrefs(store) {
8631
8694
  }
8632
8695
 
8633
8696
  // src/components/platform/AppearanceProvider.tsx
8634
- import * as React57 from "react";
8635
- import { jsx as jsx81 } from "react/jsx-runtime";
8636
- var AppearanceStoreContext = React57.createContext(null);
8697
+ import * as React58 from "react";
8698
+ import { jsx as jsx83 } from "react/jsx-runtime";
8699
+ var AppearanceStoreContext = React58.createContext(null);
8637
8700
  function AppearanceProvider({ store, children }) {
8638
- React57.useLayoutEffect(() => watchAppearance(store), [store]);
8639
- return /* @__PURE__ */ jsx81(AppearanceStoreContext.Provider, { value: store, children });
8701
+ React58.useLayoutEffect(() => watchAppearance(store), [store]);
8702
+ return /* @__PURE__ */ jsx83(AppearanceStoreContext.Provider, { value: store, children });
8640
8703
  }
8641
8704
  function useAppearanceStore() {
8642
- const store = React57.useContext(AppearanceStoreContext);
8705
+ const store = React58.useContext(AppearanceStoreContext);
8643
8706
  if (!store) throw new Error("AppearanceMenu and useAppearanceStore must be rendered inside an <AppearanceProvider>.");
8644
8707
  return store;
8645
8708
  }
8646
8709
 
8647
8710
  // src/components/platform/AppearanceMenu.tsx
8648
- import { jsx as jsx82, jsxs as jsxs70 } from "react/jsx-runtime";
8711
+ import { jsx as jsx84, jsxs as jsxs71 } from "react/jsx-runtime";
8649
8712
  var THEME_OPTIONS = [
8650
8713
  { value: "light", label: "Light" },
8651
8714
  { value: "dark", label: "Dark" },
@@ -8659,11 +8722,11 @@ var TEXT_SCALE_OPTIONS = [
8659
8722
  ];
8660
8723
  function AppearanceMenu({ className = "" }) {
8661
8724
  const [prefs, update] = useAppearancePrefs(useAppearanceStore());
8662
- const [open2, setOpen] = React58.useState(false);
8663
- const anchorRef = React58.useRef(null);
8725
+ const [open2, setOpen] = React59.useState(false);
8726
+ const anchorRef = React59.useRef(null);
8664
8727
  const patch = (p) => update(p);
8665
- return /* @__PURE__ */ jsxs70(React58.Fragment, { children: [
8666
- /* @__PURE__ */ jsx82("span", { ref: anchorRef, className: ["fd-appearance-anchor", className].filter(Boolean).join(" "), style: { display: "inline-flex" }, children: /* @__PURE__ */ jsx82(
8728
+ return /* @__PURE__ */ jsxs71(React59.Fragment, { children: [
8729
+ /* @__PURE__ */ jsx84("span", { ref: anchorRef, className: ["fd-appearance-anchor", className].filter(Boolean).join(" "), style: { display: "inline-flex" }, children: /* @__PURE__ */ jsx84(
8667
8730
  IconButton,
8668
8731
  {
8669
8732
  icon: "circle-half",
@@ -8671,7 +8734,7 @@ function AppearanceMenu({ className = "" }) {
8671
8734
  onClick: () => setOpen((v) => !v)
8672
8735
  }
8673
8736
  ) }),
8674
- /* @__PURE__ */ jsx82(
8737
+ /* @__PURE__ */ jsx84(
8675
8738
  Popover,
8676
8739
  {
8677
8740
  open: open2,
@@ -8681,10 +8744,10 @@ function AppearanceMenu({ className = "" }) {
8681
8744
  padded: true,
8682
8745
  width: 260,
8683
8746
  label: "Appearance settings",
8684
- children: /* @__PURE__ */ jsxs70("div", { className: "fd-stack", style: { display: "flex", flexDirection: "column", gap: 16 }, children: [
8685
- /* @__PURE__ */ jsxs70("div", { style: { display: "flex", flexDirection: "column", gap: 6 }, children: [
8686
- /* @__PURE__ */ jsx82("span", { className: "fd-field-label", children: "Theme" }),
8687
- /* @__PURE__ */ jsx82(
8747
+ children: /* @__PURE__ */ jsxs71("div", { className: "fd-stack", style: { display: "flex", flexDirection: "column", gap: 16 }, children: [
8748
+ /* @__PURE__ */ jsxs71("div", { style: { display: "flex", flexDirection: "column", gap: 6 }, children: [
8749
+ /* @__PURE__ */ jsx84("span", { className: "fd-field-label", children: "Theme" }),
8750
+ /* @__PURE__ */ jsx84(
8688
8751
  SegmentedControl,
8689
8752
  {
8690
8753
  options: THEME_OPTIONS,
@@ -8694,9 +8757,9 @@ function AppearanceMenu({ className = "" }) {
8694
8757
  }
8695
8758
  )
8696
8759
  ] }),
8697
- /* @__PURE__ */ jsxs70("div", { style: { display: "flex", flexDirection: "column", gap: 6 }, children: [
8698
- /* @__PURE__ */ jsx82("span", { className: "fd-field-label", children: "Text size" }),
8699
- /* @__PURE__ */ jsx82(
8760
+ /* @__PURE__ */ jsxs71("div", { style: { display: "flex", flexDirection: "column", gap: 6 }, children: [
8761
+ /* @__PURE__ */ jsx84("span", { className: "fd-field-label", children: "Text size" }),
8762
+ /* @__PURE__ */ jsx84(
8700
8763
  SegmentedControl,
8701
8764
  {
8702
8765
  options: TEXT_SCALE_OPTIONS,
@@ -8706,7 +8769,7 @@ function AppearanceMenu({ className = "" }) {
8706
8769
  }
8707
8770
  )
8708
8771
  ] }),
8709
- /* @__PURE__ */ jsx82(
8772
+ /* @__PURE__ */ jsx84(
8710
8773
  Switch,
8711
8774
  {
8712
8775
  label: "High contrast",
@@ -8715,7 +8778,7 @@ function AppearanceMenu({ className = "" }) {
8715
8778
  onChange: (e) => patch({ highContrast: e.target.checked })
8716
8779
  }
8717
8780
  ),
8718
- /* @__PURE__ */ jsx82(
8781
+ /* @__PURE__ */ jsx84(
8719
8782
  Switch,
8720
8783
  {
8721
8784
  label: "Reduce motion",
@@ -8731,14 +8794,14 @@ function AppearanceMenu({ className = "" }) {
8731
8794
  }
8732
8795
 
8733
8796
  // src/components/platform/ApiSpecBrowser.tsx
8734
- import * as React59 from "react";
8735
- import { jsx as jsx83, jsxs as jsxs71 } from "react/jsx-runtime";
8797
+ import * as React60 from "react";
8798
+ import { jsx as jsx85, jsxs as jsxs72 } from "react/jsx-runtime";
8736
8799
  var METHOD_TONE = { GET: "success", POST: "info", PATCH: "warning", PUT: "warning", DELETE: "danger" };
8737
8800
  function Json({ obj }) {
8738
- return /* @__PURE__ */ jsx83("pre", { className: "fd-json", children: JSON.stringify(obj, null, 2) });
8801
+ return /* @__PURE__ */ jsx85("pre", { className: "fd-json", children: JSON.stringify(obj, null, 2) });
8739
8802
  }
8740
8803
  function Endpoint({ s, onRequest }) {
8741
- const [tried, setTried] = React59.useState(null);
8804
+ const [tried, setTried] = React60.useState(null);
8742
8805
  const run = async () => {
8743
8806
  setTried("busy");
8744
8807
  const t0 = (window.performance || Date).now();
@@ -8749,50 +8812,50 @@ function Endpoint({ s, onRequest }) {
8749
8812
  setTried({ ms: Math.round((window.performance || Date).now() - t0), error: String(e && e.message || e) });
8750
8813
  }
8751
8814
  };
8752
- return /* @__PURE__ */ jsx83(Card, { elevation: "flat", padded: false, children: /* @__PURE__ */ jsxs71("div", { className: "fd-stack", style: { gap: 0 }, children: [
8753
- /* @__PURE__ */ jsxs71("div", { className: "fd-row", style: { gap: 10, padding: "14px 18px", flexWrap: "wrap" }, children: [
8754
- /* @__PURE__ */ jsx83(Badge, { tone: METHOD_TONE[s.method] || "neutral", children: s.method }),
8755
- /* @__PURE__ */ jsx83("code", { className: "fd-mono", style: { fontSize: 12.5, fontWeight: 600, color: "var(--text)", wordBreak: "break-all" }, children: s.path }),
8756
- s.isList ? /* @__PURE__ */ jsx83(Badge, { tone: "neutral", icon: "rows", children: "Paged list" }) : null,
8757
- /* @__PURE__ */ jsx83("span", { style: { flex: 1 } }),
8758
- /* @__PURE__ */ jsxs71("span", { className: "fd-body-sm fd-muted fd-mono", children: [
8815
+ return /* @__PURE__ */ jsx85(Card, { elevation: "flat", padded: false, children: /* @__PURE__ */ jsxs72("div", { className: "fd-stack", style: { gap: 0 }, children: [
8816
+ /* @__PURE__ */ jsxs72("div", { className: "fd-row", style: { gap: 10, padding: "14px 18px", flexWrap: "wrap" }, children: [
8817
+ /* @__PURE__ */ jsx85(Badge, { tone: METHOD_TONE[s.method] || "neutral", children: s.method }),
8818
+ /* @__PURE__ */ jsx85("code", { className: "fd-mono", style: { fontSize: 12.5, fontWeight: 600, color: "var(--text)", wordBreak: "break-all" }, children: s.path }),
8819
+ s.isList ? /* @__PURE__ */ jsx85(Badge, { tone: "neutral", icon: "rows", children: "Paged list" }) : null,
8820
+ /* @__PURE__ */ jsx85("span", { style: { flex: 1 } }),
8821
+ /* @__PURE__ */ jsxs72("span", { className: "fd-body-sm fd-muted fd-mono", children: [
8759
8822
  s.latency[0],
8760
8823
  "\u2013",
8761
8824
  s.latency[1],
8762
8825
  "ms"
8763
8826
  ] }),
8764
- /* @__PURE__ */ jsx83(Button, { size: "sm", variant: "secondary", icon: "play", loading: tried === "busy", onClick: run, children: "Try it" })
8827
+ /* @__PURE__ */ jsx85(Button, { size: "sm", variant: "secondary", icon: "play", loading: tried === "busy", onClick: run, children: "Try it" })
8765
8828
  ] }),
8766
- /* @__PURE__ */ jsxs71("div", { className: "fd-stack", style: { gap: 14, padding: "0 18px 16px" }, children: [
8767
- /* @__PURE__ */ jsxs71("div", { className: "fd-stack", style: { gap: 6 }, children: [
8768
- /* @__PURE__ */ jsx83("span", { className: "fd-body-sm", style: { fontWeight: 700 }, children: s.title }),
8769
- /* @__PURE__ */ jsx83("p", { className: "fd-body-sm fd-secondary", style: { margin: 0, textWrap: "pretty" }, children: s.purpose }),
8770
- s.usedBy && s.usedBy.length ? /* @__PURE__ */ jsx83("span", { className: "fd-row", style: { gap: 6, flexWrap: "wrap" }, children: s.usedBy.map((u) => /* @__PURE__ */ jsx83(Tag, { children: u }, u)) }) : null
8829
+ /* @__PURE__ */ jsxs72("div", { className: "fd-stack", style: { gap: 14, padding: "0 18px 16px" }, children: [
8830
+ /* @__PURE__ */ jsxs72("div", { className: "fd-stack", style: { gap: 6 }, children: [
8831
+ /* @__PURE__ */ jsx85("span", { className: "fd-body-sm", style: { fontWeight: 700 }, children: s.title }),
8832
+ /* @__PURE__ */ jsx85("p", { className: "fd-body-sm fd-secondary", style: { margin: 0, textWrap: "pretty" }, children: s.purpose }),
8833
+ s.usedBy && s.usedBy.length ? /* @__PURE__ */ jsx85("span", { className: "fd-row", style: { gap: 6, flexWrap: "wrap" }, children: s.usedBy.map((u) => /* @__PURE__ */ jsx85(Tag, { children: u }, u)) }) : null
8771
8834
  ] }),
8772
- /* @__PURE__ */ jsxs71("div", { style: { display: "grid", gridTemplateColumns: "repeat(auto-fit,minmax(280px,1fr))", gap: 12, alignItems: "start" }, children: [
8773
- s.request ? /* @__PURE__ */ jsxs71("div", { className: "fd-stack", style: { gap: 6 }, children: [
8774
- /* @__PURE__ */ jsx83("span", { className: "fd-overline fd-muted", children: "Request body" }),
8775
- /* @__PURE__ */ jsx83(Json, { obj: s.request })
8835
+ /* @__PURE__ */ jsxs72("div", { style: { display: "grid", gridTemplateColumns: "repeat(auto-fit,minmax(280px,1fr))", gap: 12, alignItems: "start" }, children: [
8836
+ s.request ? /* @__PURE__ */ jsxs72("div", { className: "fd-stack", style: { gap: 6 }, children: [
8837
+ /* @__PURE__ */ jsx85("span", { className: "fd-overline fd-muted", children: "Request body" }),
8838
+ /* @__PURE__ */ jsx85(Json, { obj: s.request })
8776
8839
  ] }) : null,
8777
- s.query ? /* @__PURE__ */ jsxs71("div", { className: "fd-stack", style: { gap: 6 }, children: [
8778
- /* @__PURE__ */ jsx83("span", { className: "fd-overline fd-muted", children: "Query" }),
8779
- /* @__PURE__ */ jsx83(Json, { obj: s.query })
8840
+ s.query ? /* @__PURE__ */ jsxs72("div", { className: "fd-stack", style: { gap: 6 }, children: [
8841
+ /* @__PURE__ */ jsx85("span", { className: "fd-overline fd-muted", children: "Query" }),
8842
+ /* @__PURE__ */ jsx85(Json, { obj: s.query })
8780
8843
  ] }) : null,
8781
- /* @__PURE__ */ jsxs71("div", { className: "fd-stack", style: { gap: 6 }, children: [
8782
- /* @__PURE__ */ jsx83("span", { className: "fd-overline fd-muted", children: "Response 200" }),
8783
- /* @__PURE__ */ jsx83(Json, { obj: s.response })
8844
+ /* @__PURE__ */ jsxs72("div", { className: "fd-stack", style: { gap: 6 }, children: [
8845
+ /* @__PURE__ */ jsx85("span", { className: "fd-overline fd-muted", children: "Response 200" }),
8846
+ /* @__PURE__ */ jsx85(Json, { obj: s.response })
8784
8847
  ] })
8785
8848
  ] }),
8786
- s.notes ? /* @__PURE__ */ jsx83(Flag, { tone: "info", statement: "Implementation note", cost: s.notes, actions: null }) : null,
8787
- tried && tried !== "busy" ? /* @__PURE__ */ jsxs71("div", { className: "fd-stack", style: { gap: 6 }, children: [
8788
- /* @__PURE__ */ jsxs71("span", { className: "fd-row", style: { gap: 8 }, children: [
8789
- /* @__PURE__ */ jsx83("span", { className: "fd-overline fd-muted", children: "Simulated response" }),
8790
- /* @__PURE__ */ jsxs71(Badge, { tone: tried.error ? "danger" : "success", icon: "timer", children: [
8849
+ s.notes ? /* @__PURE__ */ jsx85(Flag, { tone: "info", statement: "Implementation note", cost: s.notes, actions: null }) : null,
8850
+ tried && tried !== "busy" ? /* @__PURE__ */ jsxs72("div", { className: "fd-stack", style: { gap: 6 }, children: [
8851
+ /* @__PURE__ */ jsxs72("span", { className: "fd-row", style: { gap: 8 }, children: [
8852
+ /* @__PURE__ */ jsx85("span", { className: "fd-overline fd-muted", children: "Simulated response" }),
8853
+ /* @__PURE__ */ jsxs72(Badge, { tone: tried.error ? "danger" : "success", icon: "timer", children: [
8791
8854
  tried.ms,
8792
8855
  "ms"
8793
8856
  ] })
8794
8857
  ] }),
8795
- /* @__PURE__ */ jsx83(Json, { obj: tried.error ? { error: tried.error } : tried.data })
8858
+ /* @__PURE__ */ jsx85(Json, { obj: tried.error ? { error: tried.error } : tried.data })
8796
8859
  ] }) : null
8797
8860
  ] })
8798
8861
  ] }) });
@@ -8811,58 +8874,58 @@ function ApiSpecBrowser({
8811
8874
  className = "",
8812
8875
  ...rest
8813
8876
  }) {
8814
- const [q, setQ] = React59.useState("");
8815
- const [method, setMethod] = React59.useState(null);
8816
- const [mod, setMod] = React59.useState(null);
8817
- const [listOnly, setListOnly] = React59.useState(false);
8877
+ const [q, setQ] = React60.useState("");
8878
+ const [method, setMethod] = React60.useState(null);
8879
+ const [mod, setMod] = React60.useState(null);
8880
+ const [listOnly, setListOnly] = React60.useState(false);
8818
8881
  const activeModule = modules && modules.find((m) => m.id === mod);
8819
8882
  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())));
8820
8883
  const effGroups = groups && groups.length ? groups : [["All endpoints", spec.map((s) => s.id)]];
8821
8884
  const methods = [...new Set(spec.map((s) => s.method))];
8822
8885
  const listCount = spec.filter((s) => s.isList).length;
8823
- return /* @__PURE__ */ jsxs71("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 20, maxWidth: 1100 }, ...rest, children: [
8824
- /* @__PURE__ */ jsxs71("div", { className: "fd-stack", style: { gap: 10 }, children: [
8825
- kicker ? /* @__PURE__ */ jsx83("span", { className: "fd-overline fd-muted", children: kicker }) : null,
8826
- /* @__PURE__ */ jsx83("h1", { className: "fd-h1", style: { margin: 0 }, children: title }),
8827
- lede ? /* @__PURE__ */ jsx83("p", { className: "fd-body fd-secondary fd-prose", style: { margin: 0 }, children: lede }) : null
8886
+ return /* @__PURE__ */ jsxs72("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 20, maxWidth: 1100 }, ...rest, children: [
8887
+ /* @__PURE__ */ jsxs72("div", { className: "fd-stack", style: { gap: 10 }, children: [
8888
+ kicker ? /* @__PURE__ */ jsx85("span", { className: "fd-overline fd-muted", children: kicker }) : null,
8889
+ /* @__PURE__ */ jsx85("h1", { className: "fd-h1", style: { margin: 0 }, children: title }),
8890
+ lede ? /* @__PURE__ */ jsx85("p", { className: "fd-body fd-secondary fd-prose", style: { margin: 0 }, children: lede }) : null
8828
8891
  ] }),
8829
- modules && modules.length ? /* @__PURE__ */ jsxs71("div", { className: "fd-stack", style: { gap: 8 }, children: [
8830
- /* @__PURE__ */ jsx83("span", { className: "fd-overline fd-muted", children: "Filter by screen \u2014 every endpoint that screen depends on" }),
8831
- /* @__PURE__ */ jsxs71("div", { className: "fd-row", style: { gap: 8, flexWrap: "wrap" }, children: [
8832
- /* @__PURE__ */ jsxs71(Tag, { icon: "stack", selected: !mod, onClick: () => setMod(null), children: [
8892
+ modules && modules.length ? /* @__PURE__ */ jsxs72("div", { className: "fd-stack", style: { gap: 8 }, children: [
8893
+ /* @__PURE__ */ jsx85("span", { className: "fd-overline fd-muted", children: "Filter by screen \u2014 every endpoint that screen depends on" }),
8894
+ /* @__PURE__ */ jsxs72("div", { className: "fd-row", style: { gap: 8, flexWrap: "wrap" }, children: [
8895
+ /* @__PURE__ */ jsxs72(Tag, { icon: "stack", selected: !mod, onClick: () => setMod(null), children: [
8833
8896
  "All screens ",
8834
- /* @__PURE__ */ jsx83("span", { className: "fd-mono", children: spec.length })
8897
+ /* @__PURE__ */ jsx85("span", { className: "fd-mono", children: spec.length })
8835
8898
  ] }),
8836
- modules.map((m) => /* @__PURE__ */ jsxs71(Tag, { icon: m.icon, selected: mod === m.id, onClick: () => setMod(mod === m.id ? null : m.id), children: [
8899
+ modules.map((m) => /* @__PURE__ */ jsxs72(Tag, { icon: m.icon, selected: mod === m.id, onClick: () => setMod(mod === m.id ? null : m.id), children: [
8837
8900
  m.label,
8838
8901
  " ",
8839
- /* @__PURE__ */ jsx83("span", { className: "fd-mono", children: m.endpoints.length })
8902
+ /* @__PURE__ */ jsx85("span", { className: "fd-mono", children: m.endpoints.length })
8840
8903
  ] }, m.id))
8841
8904
  ] }),
8842
- activeModule ? /* @__PURE__ */ jsx83(
8905
+ activeModule ? /* @__PURE__ */ jsx85(
8843
8906
  Flag,
8844
8907
  {
8845
8908
  tone: "info",
8846
8909
  statement: activeModule.label + " calls " + activeModule.endpoints.length + " endpoints.",
8847
8910
  cost: "Integration checklist for this screen: " + activeModule.endpoints.join(", ") + ". Wire these and the screen is done.",
8848
- actions: /* @__PURE__ */ jsx83(Button, { size: "sm", variant: "ghost", icon: "x", onClick: () => setMod(null), children: "Show all screens" })
8911
+ actions: /* @__PURE__ */ jsx85(Button, { size: "sm", variant: "ghost", icon: "x", onClick: () => setMod(null), children: "Show all screens" })
8849
8912
  }
8850
8913
  ) : null
8851
8914
  ] }) : null,
8852
- sourceNote ? /* @__PURE__ */ jsx83(Flag, { tone: "info", statement: "Design-first: this page is the spec.", cost: sourceNote, actions: null }) : null,
8853
- /* @__PURE__ */ jsxs71("div", { className: "fd-row", style: { gap: 10, flexWrap: "wrap" }, children: [
8854
- /* @__PURE__ */ jsx83(Input, { icon: "magnifying-glass", placeholder: "Find an endpoint, screen, or behavior", value: q, onChange: (e) => setQ(e.target.value), style: { width: 300 } }),
8855
- methods.map((m) => /* @__PURE__ */ jsxs71(Tag, { selected: method === m, onClick: () => setMethod(method === m ? null : m), children: [
8915
+ sourceNote ? /* @__PURE__ */ jsx85(Flag, { tone: "info", statement: "Design-first: this page is the spec.", cost: sourceNote, actions: null }) : null,
8916
+ /* @__PURE__ */ jsxs72("div", { className: "fd-row", style: { gap: 10, flexWrap: "wrap" }, children: [
8917
+ /* @__PURE__ */ jsx85(Input, { icon: "magnifying-glass", placeholder: "Find an endpoint, screen, or behavior", value: q, onChange: (e) => setQ(e.target.value), style: { width: 300 } }),
8918
+ methods.map((m) => /* @__PURE__ */ jsxs72(Tag, { selected: method === m, onClick: () => setMethod(method === m ? null : m), children: [
8856
8919
  m,
8857
8920
  " ",
8858
- /* @__PURE__ */ jsx83("span", { className: "fd-mono", children: spec.filter((s) => s.method === m).length })
8921
+ /* @__PURE__ */ jsx85("span", { className: "fd-mono", children: spec.filter((s) => s.method === m).length })
8859
8922
  ] }, m)),
8860
- listCount ? /* @__PURE__ */ jsxs71(Tag, { icon: "rows", selected: listOnly, onClick: () => setListOnly(!listOnly), children: [
8923
+ listCount ? /* @__PURE__ */ jsxs72(Tag, { icon: "rows", selected: listOnly, onClick: () => setListOnly(!listOnly), children: [
8861
8924
  "Paged lists ",
8862
- /* @__PURE__ */ jsx83("span", { className: "fd-mono", children: listCount })
8925
+ /* @__PURE__ */ jsx85("span", { className: "fd-mono", children: listCount })
8863
8926
  ] }) : null,
8864
- /* @__PURE__ */ jsx83("span", { style: { flex: 1 } }),
8865
- /* @__PURE__ */ jsxs71("span", { className: "fd-body-sm fd-muted", children: [
8927
+ /* @__PURE__ */ jsx85("span", { style: { flex: 1 } }),
8928
+ /* @__PURE__ */ jsxs72("span", { className: "fd-body-sm fd-muted", children: [
8866
8929
  hits.length,
8867
8930
  " of ",
8868
8931
  spec.length,
@@ -8870,31 +8933,31 @@ function ApiSpecBrowser({
8870
8933
  listCount ? " \xB7 " + listCount + " paged" : ""
8871
8934
  ] })
8872
8935
  ] }),
8873
- hits.length === 0 ? /* @__PURE__ */ jsx83(Card, { elevation: "flat", children: /* @__PURE__ */ jsx83("p", { className: "fd-body-sm fd-muted", style: { margin: 0 }, children: "No endpoint matches those filters." }) }) : effGroups.map(([g, ids]) => {
8936
+ hits.length === 0 ? /* @__PURE__ */ jsx85(Card, { elevation: "flat", children: /* @__PURE__ */ jsx85("p", { className: "fd-body-sm fd-muted", style: { margin: 0 }, children: "No endpoint matches those filters." }) }) : effGroups.map(([g, ids]) => {
8874
8937
  const items = hits.filter((s) => ids.indexOf(s.id) >= 0);
8875
8938
  if (!items.length) return null;
8876
- return /* @__PURE__ */ jsxs71("div", { className: "fd-stack", style: { gap: 12 }, children: [
8877
- /* @__PURE__ */ jsx83("span", { className: "fd-label-lg", children: g }),
8878
- items.map((s) => /* @__PURE__ */ jsx83(Endpoint, { s, onRequest }, s.id))
8939
+ return /* @__PURE__ */ jsxs72("div", { className: "fd-stack", style: { gap: 12 }, children: [
8940
+ /* @__PURE__ */ jsx85("span", { className: "fd-label-lg", children: g }),
8941
+ items.map((s) => /* @__PURE__ */ jsx85(Endpoint, { s, onRequest }, s.id))
8879
8942
  ] }, g);
8880
8943
  }),
8881
- conventions && conventions.length ? /* @__PURE__ */ jsx83(Card, { title: "Cross-cutting conventions", elevation: "flat", children: /* @__PURE__ */ jsx83("div", { className: "fd-stack", style: { gap: 10 }, children: conventions.map(([k, v]) => /* @__PURE__ */ jsxs71("div", { className: "fd-row", style: { gap: 12, alignItems: "flex-start" }, children: [
8882
- /* @__PURE__ */ jsx83("span", { className: "fd-overline fd-muted", style: { width: 110, flex: "none", paddingTop: 2 }, children: k }),
8883
- /* @__PURE__ */ jsx83("span", { className: "fd-body-sm fd-secondary", style: { textWrap: "pretty" }, children: v })
8944
+ conventions && conventions.length ? /* @__PURE__ */ jsx85(Card, { title: "Cross-cutting conventions", elevation: "flat", children: /* @__PURE__ */ jsx85("div", { className: "fd-stack", style: { gap: 10 }, children: conventions.map(([k, v]) => /* @__PURE__ */ jsxs72("div", { className: "fd-row", style: { gap: 12, alignItems: "flex-start" }, children: [
8945
+ /* @__PURE__ */ jsx85("span", { className: "fd-overline fd-muted", style: { width: 110, flex: "none", paddingTop: 2 }, children: k }),
8946
+ /* @__PURE__ */ jsx85("span", { className: "fd-body-sm fd-secondary", style: { textWrap: "pretty" }, children: v })
8884
8947
  ] }, k)) }) }) : null,
8885
- openQuestions && openQuestions.length ? /* @__PURE__ */ jsx83(Collapsible, { icon: "list-checks", title: "Open questions before implementation", subtitle: openQuestions.length + " unresolved", children: /* @__PURE__ */ jsx83("div", { className: "fd-stack", style: { gap: 8 }, children: openQuestions.map(([id, question, why]) => /* @__PURE__ */ jsxs71("div", { className: "fd-row", style: { gap: 10, alignItems: "flex-start", padding: "8px 0", borderTop: "1px solid var(--border)" }, children: [
8886
- /* @__PURE__ */ jsx83(Badge, { tone: "danger", children: id }),
8887
- /* @__PURE__ */ jsxs71("span", { className: "fd-stack", style: { gap: 2, flex: 1 }, children: [
8888
- /* @__PURE__ */ jsx83("span", { className: "fd-body-sm", style: { fontWeight: 600 }, children: question }),
8889
- /* @__PURE__ */ jsx83("span", { className: "fd-body-sm fd-muted", children: why })
8948
+ openQuestions && openQuestions.length ? /* @__PURE__ */ jsx85(Collapsible, { icon: "list-checks", title: "Open questions before implementation", subtitle: openQuestions.length + " unresolved", children: /* @__PURE__ */ jsx85("div", { className: "fd-stack", style: { gap: 8 }, children: openQuestions.map(([id, question, why]) => /* @__PURE__ */ jsxs72("div", { className: "fd-row", style: { gap: 10, alignItems: "flex-start", padding: "8px 0", borderTop: "1px solid var(--border)" }, children: [
8949
+ /* @__PURE__ */ jsx85(Badge, { tone: "danger", children: id }),
8950
+ /* @__PURE__ */ jsxs72("span", { className: "fd-stack", style: { gap: 2, flex: 1 }, children: [
8951
+ /* @__PURE__ */ jsx85("span", { className: "fd-body-sm", style: { fontWeight: 600 }, children: question }),
8952
+ /* @__PURE__ */ jsx85("span", { className: "fd-body-sm fd-muted", children: why })
8890
8953
  ] })
8891
8954
  ] }, id)) }) }) : null
8892
8955
  ] });
8893
8956
  }
8894
8957
 
8895
8958
  // src/components/platform/ProfilePage.tsx
8896
- import * as React60 from "react";
8897
- import { jsx as jsx84, jsxs as jsxs72 } from "react/jsx-runtime";
8959
+ import * as React61 from "react";
8960
+ import { jsx as jsx86, jsxs as jsxs73 } from "react/jsx-runtime";
8898
8961
  function fieldInitialValue(field, user) {
8899
8962
  if (field.value) return field.value(user);
8900
8963
  const raw = user[field.key];
@@ -8929,21 +8992,21 @@ function ProfilePage({
8929
8992
  }) {
8930
8993
  const { user: sessionUser, roles, permissions, saveProfile: saveProfile2 } = useSessionContext();
8931
8994
  const user = userProp || sessionUser;
8932
- const initialFieldValues = React60.useMemo(() => {
8995
+ const initialFieldValues = React61.useMemo(() => {
8933
8996
  const values2 = {};
8934
8997
  for (const field of fields) values2[field.key] = fieldInitialValue(field, user);
8935
8998
  return values2;
8936
8999
  }, [user.id, fields]);
8937
- const initialNotify = React60.useMemo(() => {
9000
+ const initialNotify = React61.useMemo(() => {
8938
9001
  const values2 = {};
8939
9002
  for (const n of notifications) values2[n.key] = !!user.notify?.[n.key];
8940
9003
  return values2;
8941
9004
  }, [user.id, notifications]);
8942
- const [values, setValues] = React60.useState(initialFieldValues);
8943
- const [notify, setNotify] = React60.useState(initialNotify);
8944
- const [saving, setSaving] = React60.useState(false);
8945
- const [saved, setSaved] = React60.useState(false);
8946
- const [prevUserId, setPrevUserId] = React60.useState(user.id);
9005
+ const [values, setValues] = React61.useState(initialFieldValues);
9006
+ const [notify, setNotify] = React61.useState(initialNotify);
9007
+ const [saving, setSaving] = React61.useState(false);
9008
+ const [saved, setSaved] = React61.useState(false);
9009
+ const [prevUserId, setPrevUserId] = React61.useState(user.id);
8947
9010
  if (user.id !== prevUserId) {
8948
9011
  setPrevUserId(user.id);
8949
9012
  setValues(initialFieldValues);
@@ -8980,37 +9043,37 @@ function ProfilePage({
8980
9043
  };
8981
9044
  const displayName = fields.some((f) => f.key === "name") ? values.name || user.name : user.name;
8982
9045
  const fieldGroups = groupFields(fields);
8983
- return /* @__PURE__ */ jsxs72("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 20, maxWidth: 860 }, children: [
8984
- /* @__PURE__ */ jsxs72("div", { className: "fd-stack", style: { gap: 10 }, children: [
8985
- /* @__PURE__ */ jsx84("span", { className: "fd-overline fd-muted", children: "Account" }),
8986
- /* @__PURE__ */ jsx84("h1", { className: "fd-h1", style: { margin: 0 }, children: "Your profile" }),
8987
- /* @__PURE__ */ jsx84("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." })
9046
+ return /* @__PURE__ */ jsxs73("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 20, maxWidth: 860 }, children: [
9047
+ /* @__PURE__ */ jsxs73("div", { className: "fd-stack", style: { gap: 10 }, children: [
9048
+ /* @__PURE__ */ jsx86("span", { className: "fd-overline fd-muted", children: "Account" }),
9049
+ /* @__PURE__ */ jsx86("h1", { className: "fd-h1", style: { margin: 0 }, children: "Your profile" }),
9050
+ /* @__PURE__ */ jsx86("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." })
8988
9051
  ] }),
8989
- /* @__PURE__ */ jsx84(Card, { elevation: "flat", children: /* @__PURE__ */ jsxs72("div", { className: "fd-row", style: { gap: 16, flexWrap: "wrap", alignItems: "flex-start" }, children: [
8990
- /* @__PURE__ */ jsx84(Avatar, { name: displayName, size: "lg" }),
8991
- /* @__PURE__ */ jsxs72("div", { className: "fd-stack", style: { gap: 4, flex: 1, minWidth: 200 }, children: [
8992
- /* @__PURE__ */ jsx84("span", { className: "fd-h3", style: { margin: 0 }, children: displayName }),
8993
- /* @__PURE__ */ jsxs72("span", { className: "fd-row", style: { gap: 6, flexWrap: "wrap", paddingTop: 4 }, children: [
8994
- roles.map((r) => /* @__PURE__ */ jsx84(Badge, { tone: r.id === "owner" ? "success" : "neutral", children: r.name }, r.id)),
8995
- user.sso ? /* @__PURE__ */ jsx84(Badge, { tone: "info", icon: "shield-check", children: "SSO" }) : null
9052
+ /* @__PURE__ */ jsx86(Card, { elevation: "flat", children: /* @__PURE__ */ jsxs73("div", { className: "fd-row", style: { gap: 16, flexWrap: "wrap", alignItems: "flex-start" }, children: [
9053
+ /* @__PURE__ */ jsx86(Avatar, { name: displayName, size: "lg" }),
9054
+ /* @__PURE__ */ jsxs73("div", { className: "fd-stack", style: { gap: 4, flex: 1, minWidth: 200 }, children: [
9055
+ /* @__PURE__ */ jsx86("span", { className: "fd-h3", style: { margin: 0 }, children: displayName }),
9056
+ /* @__PURE__ */ jsxs73("span", { className: "fd-row", style: { gap: 6, flexWrap: "wrap", paddingTop: 4 }, children: [
9057
+ roles.map((r) => /* @__PURE__ */ jsx86(Badge, { tone: r.id === "owner" ? "success" : "neutral", children: r.name }, r.id)),
9058
+ user.sso ? /* @__PURE__ */ jsx86(Badge, { tone: "info", icon: "shield-check", children: "SSO" }) : null
8996
9059
  ] })
8997
9060
  ] }),
8998
- onChangePhoto ? /* @__PURE__ */ jsx84(Button, { variant: "secondary", size: "sm", icon: "image", onClick: onChangePhoto, children: "Change photo" }) : null
9061
+ onChangePhoto ? /* @__PURE__ */ jsx86(Button, { variant: "secondary", size: "sm", icon: "image", onClick: onChangePhoto, children: "Change photo" }) : null
8999
9062
  ] }) }),
9000
- fieldGroups.map(({ group, description, fields: groupFieldDefs }) => /* @__PURE__ */ jsx84(
9063
+ fieldGroups.map(({ group, description, fields: groupFieldDefs }) => /* @__PURE__ */ jsx86(
9001
9064
  Card,
9002
9065
  {
9003
- title: description ? /* @__PURE__ */ jsxs72("span", { className: "fd-stack", style: { gap: 2 }, children: [
9004
- /* @__PURE__ */ jsx84("span", { children: group }),
9005
- /* @__PURE__ */ jsx84("span", { className: "fd-body-sm fd-muted", style: { fontWeight: 400 }, children: description })
9066
+ title: description ? /* @__PURE__ */ jsxs73("span", { className: "fd-stack", style: { gap: 2 }, children: [
9067
+ /* @__PURE__ */ jsx86("span", { children: group }),
9068
+ /* @__PURE__ */ jsx86("span", { className: "fd-body-sm fd-muted", style: { fontWeight: 400 }, children: description })
9006
9069
  ] }) : group,
9007
9070
  elevation: "flat",
9008
- children: /* @__PURE__ */ jsxs72("div", { className: "fd-stack", style: { gap: 14 }, children: [
9009
- /* @__PURE__ */ jsx84("div", { style: { display: "grid", gridTemplateColumns: "repeat(auto-fit,minmax(220px,1fr))", gap: 14 }, children: groupFieldDefs.filter((f) => f.type !== "textarea").map((field) => {
9071
+ children: /* @__PURE__ */ jsxs73("div", { className: "fd-stack", style: { gap: 14 }, children: [
9072
+ /* @__PURE__ */ jsx86("div", { style: { display: "grid", gridTemplateColumns: "repeat(auto-fit,minmax(220px,1fr))", gap: 14 }, children: groupFieldDefs.filter((f) => f.type !== "textarea").map((field) => {
9010
9073
  const help = typeof field.help === "function" ? field.help(user) : field.help;
9011
9074
  const readOnly = field.readOnly || field.type === "readonly";
9012
9075
  if (field.type === "select") {
9013
- return /* @__PURE__ */ jsx84(
9076
+ return /* @__PURE__ */ jsx86(
9014
9077
  Select,
9015
9078
  {
9016
9079
  label: field.label,
@@ -9024,7 +9087,7 @@ function ProfilePage({
9024
9087
  field.key
9025
9088
  );
9026
9089
  }
9027
- return /* @__PURE__ */ jsx84(
9090
+ return /* @__PURE__ */ jsx86(
9028
9091
  Input,
9029
9092
  {
9030
9093
  label: field.label,
@@ -9040,7 +9103,7 @@ function ProfilePage({
9040
9103
  }) }),
9041
9104
  groupFieldDefs.filter((f) => f.type === "textarea").map((field) => {
9042
9105
  const help = typeof field.help === "function" ? field.help(user) : field.help;
9043
- return /* @__PURE__ */ jsx84(
9106
+ return /* @__PURE__ */ jsx86(
9044
9107
  Textarea,
9045
9108
  {
9046
9109
  label: field.label,
@@ -9060,16 +9123,16 @@ function ProfilePage({
9060
9123
  group
9061
9124
  )),
9062
9125
  extra,
9063
- notifications.length > 0 ? /* @__PURE__ */ jsx84(Card, { title: "Notifications", elevation: "flat", children: /* @__PURE__ */ jsx84("div", { className: "fd-stack", style: { gap: 14 }, children: notifications.map((n) => /* @__PURE__ */ jsx84(Switch, { checked: !!notify[n.key], onChange: () => toggleNotify(n.key), label: n.label, description: n.description }, n.key)) }) }) : null,
9064
- /* @__PURE__ */ jsxs72(
9126
+ notifications.length > 0 ? /* @__PURE__ */ jsx86(Card, { title: "Notifications", elevation: "flat", children: /* @__PURE__ */ jsx86("div", { className: "fd-stack", style: { gap: 14 }, children: notifications.map((n) => /* @__PURE__ */ jsx86(Switch, { checked: !!notify[n.key], onChange: () => toggleNotify(n.key), label: n.label, description: n.description }, n.key)) }) }) : null,
9127
+ /* @__PURE__ */ jsxs73(
9065
9128
  Card,
9066
9129
  {
9067
- title: /* @__PURE__ */ jsxs72("span", { className: "fd-stack", style: { gap: 2 }, children: [
9068
- /* @__PURE__ */ jsx84("span", { children: "Access" }),
9069
- /* @__PURE__ */ jsx84("span", { className: "fd-body-sm fd-muted", style: { fontWeight: 400 }, children: "What your roles grant you" })
9130
+ title: /* @__PURE__ */ jsxs73("span", { className: "fd-stack", style: { gap: 2 }, children: [
9131
+ /* @__PURE__ */ jsx86("span", { children: "Access" }),
9132
+ /* @__PURE__ */ jsx86("span", { className: "fd-body-sm fd-muted", style: { fontWeight: 400 }, children: "What your roles grant you" })
9070
9133
  ] }),
9071
9134
  elevation: "flat",
9072
- action: /* @__PURE__ */ jsx84(
9135
+ action: /* @__PURE__ */ jsx86(
9073
9136
  Button,
9074
9137
  {
9075
9138
  size: "sm",
@@ -9080,39 +9143,39 @@ function ProfilePage({
9080
9143
  }
9081
9144
  ),
9082
9145
  children: [
9083
- /* @__PURE__ */ jsxs72("div", { className: "fd-stack", style: { gap: 0 }, children: [
9084
- /* @__PURE__ */ jsx84(CardRow, { label: "Roles", children: roles.map((r) => r.name).join(", ") || "None" }),
9085
- /* @__PURE__ */ jsxs72(CardRow, { label: "Permissions", children: [
9146
+ /* @__PURE__ */ jsxs73("div", { className: "fd-stack", style: { gap: 0 }, children: [
9147
+ /* @__PURE__ */ jsx86(CardRow, { label: "Roles", children: roles.map((r) => r.name).join(", ") || "None" }),
9148
+ /* @__PURE__ */ jsxs73(CardRow, { label: "Permissions", children: [
9086
9149
  permissions.length,
9087
9150
  " granted"
9088
9151
  ] }),
9089
- /* @__PURE__ */ jsx84(CardRow, { label: "Member since", children: user.joined || "\u2014" })
9152
+ /* @__PURE__ */ jsx86(CardRow, { label: "Member since", children: user.joined || "\u2014" })
9090
9153
  ] }),
9091
- /* @__PURE__ */ jsx84("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." })
9154
+ /* @__PURE__ */ jsx86("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." })
9092
9155
  ]
9093
9156
  }
9094
9157
  ),
9095
- sessions ? /* @__PURE__ */ jsx84(
9158
+ sessions ? /* @__PURE__ */ jsx86(
9096
9159
  Card,
9097
9160
  {
9098
9161
  title: "Signed-in devices",
9099
9162
  elevation: "flat",
9100
- action: /* @__PURE__ */ jsx84(Button, { size: "sm", variant: "ghost", icon: "sign-out", onClick: onSignOutEverywhere, children: "Sign out everywhere" }),
9101
- children: /* @__PURE__ */ jsx84("div", { className: "fd-stack", style: { gap: 0 }, children: sessions.length === 0 ? /* @__PURE__ */ jsx84("p", { className: "fd-body-sm fd-muted", style: { margin: 0 }, children: "No other signed-in devices." }) : sessions.map((s) => /* @__PURE__ */ jsxs72("div", { className: "fd-row", style: { gap: 12, padding: "10px 0", borderTop: "1px solid var(--border)", flexWrap: "wrap" }, children: [
9102
- /* @__PURE__ */ jsx84("i", { className: "ph ph-device-mobile", style: { fontSize: 16, color: "var(--text-muted)" }, "aria-hidden": "true" }),
9103
- /* @__PURE__ */ jsxs72("span", { className: "fd-stack", style: { gap: 1, flex: 1, minWidth: 160 }, children: [
9104
- /* @__PURE__ */ jsx84("span", { className: "fd-body-sm", style: { fontWeight: 600 }, children: s.device }),
9105
- /* @__PURE__ */ jsxs72("span", { className: "fd-body-sm fd-muted", children: [
9163
+ action: /* @__PURE__ */ jsx86(Button, { size: "sm", variant: "ghost", icon: "sign-out", onClick: onSignOutEverywhere, children: "Sign out everywhere" }),
9164
+ children: /* @__PURE__ */ jsx86("div", { className: "fd-stack", style: { gap: 0 }, children: sessions.length === 0 ? /* @__PURE__ */ jsx86("p", { className: "fd-body-sm fd-muted", style: { margin: 0 }, children: "No other signed-in devices." }) : sessions.map((s) => /* @__PURE__ */ jsxs73("div", { className: "fd-row", style: { gap: 12, padding: "10px 0", borderTop: "1px solid var(--border)", flexWrap: "wrap" }, children: [
9165
+ /* @__PURE__ */ jsx86("i", { className: "ph ph-device-mobile", style: { fontSize: 16, color: "var(--text-muted)" }, "aria-hidden": "true" }),
9166
+ /* @__PURE__ */ jsxs73("span", { className: "fd-stack", style: { gap: 1, flex: 1, minWidth: 160 }, children: [
9167
+ /* @__PURE__ */ jsx86("span", { className: "fd-body-sm", style: { fontWeight: 600 }, children: s.device }),
9168
+ /* @__PURE__ */ jsxs73("span", { className: "fd-body-sm fd-muted", children: [
9106
9169
  s.where,
9107
9170
  " \xB7 ",
9108
9171
  s.when
9109
9172
  ] })
9110
9173
  ] }),
9111
- s.current ? /* @__PURE__ */ jsx84(Badge, { tone: "success", dot: true, children: "This device" }) : /* @__PURE__ */ jsx84(Button, { size: "sm", variant: "ghost", children: "Revoke" })
9174
+ s.current ? /* @__PURE__ */ jsx86(Badge, { tone: "success", dot: true, children: "This device" }) : /* @__PURE__ */ jsx86(Button, { size: "sm", variant: "ghost", children: "Revoke" })
9112
9175
  ] }, s.id)) })
9113
9176
  }
9114
9177
  ) : null,
9115
- /* @__PURE__ */ jsxs72("div", { className: "fd-row", style: {
9178
+ /* @__PURE__ */ jsxs73("div", { className: "fd-row", style: {
9116
9179
  gap: 10,
9117
9180
  flexWrap: "wrap",
9118
9181
  position: "sticky",
@@ -9123,16 +9186,16 @@ function ProfilePage({
9123
9186
  border: "1px solid var(--border)",
9124
9187
  boxShadow: "0 -4px 16px rgba(11,13,17,.06)"
9125
9188
  }, children: [
9126
- /* @__PURE__ */ jsx84("span", { className: "fd-body-sm", style: { fontWeight: 600, flex: 1 }, children: saved ? "Saved." : dirty ? "Unsaved changes" : "No pending changes" }),
9127
- /* @__PURE__ */ jsx84(Button, { size: "sm", variant: "ghost", disabled: !dirty || saving, onClick: discard, children: "Discard" }),
9128
- /* @__PURE__ */ jsx84(Button, { size: "sm", icon: "check", disabled: !dirty || !canSave, loading: saving, onClick: save, children: "Save changes" })
9189
+ /* @__PURE__ */ jsx86("span", { className: "fd-body-sm", style: { fontWeight: 600, flex: 1 }, children: saved ? "Saved." : dirty ? "Unsaved changes" : "No pending changes" }),
9190
+ /* @__PURE__ */ jsx86(Button, { size: "sm", variant: "ghost", disabled: !dirty || saving, onClick: discard, children: "Discard" }),
9191
+ /* @__PURE__ */ jsx86(Button, { size: "sm", icon: "check", disabled: !dirty || !canSave, loading: saving, onClick: save, children: "Save changes" })
9129
9192
  ] })
9130
9193
  ] });
9131
9194
  }
9132
9195
 
9133
9196
  // src/components/platform/SessionScreen.tsx
9134
- import * as React61 from "react";
9135
- import { Fragment as Fragment22, jsx as jsx85, jsxs as jsxs73 } from "react/jsx-runtime";
9197
+ import * as React62 from "react";
9198
+ import { Fragment as Fragment22, jsx as jsx87, jsxs as jsxs74 } from "react/jsx-runtime";
9136
9199
  var COPY = {
9137
9200
  "signing-in": { busy: "Signing you in\u2026" },
9138
9201
  "session-expired": { busy: "Your session expired \u2014 signing you back in\u2026" },
@@ -9145,28 +9208,28 @@ function SessionScreen({ kind, error, onRetry, productName }) {
9145
9208
  const copy = COPY[kind];
9146
9209
  const busyMessage = "busy" in copy ? copy.busy : null;
9147
9210
  const failureTitle = "failure" in copy ? copy.failure : null;
9148
- const [announced, setAnnounced] = React61.useState("");
9149
- React61.useEffect(() => {
9211
+ const [announced, setAnnounced] = React62.useState("");
9212
+ React62.useEffect(() => {
9150
9213
  setAnnounced(busyMessage ?? "");
9151
9214
  }, [busyMessage]);
9152
- const titleRef = React61.useRef(null);
9215
+ const titleRef = React62.useRef(null);
9153
9216
  const failed = failureTitle !== null;
9154
- React61.useEffect(() => {
9217
+ React62.useEffect(() => {
9155
9218
  titleRef.current?.focus({ preventScroll: true });
9156
9219
  }, [failed]);
9157
- return /* @__PURE__ */ jsx85("main", { className: "fd-session-screen", children: /* @__PURE__ */ jsxs73("div", { className: "fd-session-screen-inner", children: [
9158
- /* @__PURE__ */ jsx85("div", { className: "fd-session-screen-mark", "data-theme": "dark", children: /* @__PURE__ */ jsx85(FlytedeskMark, { size: "lg" }) }),
9159
- /* @__PURE__ */ jsxs73("div", { className: "fd-session-screen-frame", children: [
9160
- /* @__PURE__ */ jsx85("div", { className: "fd-session-screen-stripe" }),
9161
- /* @__PURE__ */ jsx85(Card, { children: /* @__PURE__ */ jsxs73("div", { className: "fd-session-screen-body", children: [
9162
- /* @__PURE__ */ jsx85("h1", { ref: titleRef, tabIndex: -1, className: "fd-h3 fd-session-screen-title", children: productName }),
9163
- /* @__PURE__ */ jsx85("div", { role: "status", "aria-live": "polite", className: "fd-session-screen-status", children: busyMessage !== null ? /* @__PURE__ */ jsxs73(Fragment22, { children: [
9164
- /* @__PURE__ */ jsx85("span", { className: "fd-spinner fd-spinner-lg fd-session-screen-spinner", "aria-hidden": "true" }),
9165
- /* @__PURE__ */ jsx85("p", { className: "fd-body fd-session-screen-message", children: announced })
9220
+ return /* @__PURE__ */ jsx87("main", { className: "fd-session-screen", children: /* @__PURE__ */ jsxs74("div", { className: "fd-session-screen-inner", children: [
9221
+ /* @__PURE__ */ jsx87("div", { className: "fd-session-screen-mark", "data-theme": "dark", children: /* @__PURE__ */ jsx87(FlytedeskMark, { size: "lg" }) }),
9222
+ /* @__PURE__ */ jsxs74("div", { className: "fd-session-screen-frame", children: [
9223
+ /* @__PURE__ */ jsx87("div", { className: "fd-session-screen-stripe" }),
9224
+ /* @__PURE__ */ jsx87(Card, { children: /* @__PURE__ */ jsxs74("div", { className: "fd-session-screen-body", children: [
9225
+ /* @__PURE__ */ jsx87("h1", { ref: titleRef, tabIndex: -1, className: "fd-h3 fd-session-screen-title", children: productName }),
9226
+ /* @__PURE__ */ jsx87("div", { role: "status", "aria-live": "polite", className: "fd-session-screen-status", children: busyMessage !== null ? /* @__PURE__ */ jsxs74(Fragment22, { children: [
9227
+ /* @__PURE__ */ jsx87("span", { className: "fd-spinner fd-spinner-lg fd-session-screen-spinner", "aria-hidden": "true" }),
9228
+ /* @__PURE__ */ jsx87("p", { className: "fd-body fd-session-screen-message", children: announced })
9166
9229
  ] }) : null }),
9167
- failureTitle !== null ? /* @__PURE__ */ jsxs73("div", { className: "fd-session-screen-failure", children: [
9168
- /* @__PURE__ */ jsx85(Banner, { tone: "danger", title: failureTitle, detail: error ?? void 0 }),
9169
- onRetry !== null ? /* @__PURE__ */ jsx85(Button, { variant: "primary", block: true, onClick: onRetry, children: "Try again" }) : null
9230
+ failureTitle !== null ? /* @__PURE__ */ jsxs74("div", { className: "fd-session-screen-failure", children: [
9231
+ /* @__PURE__ */ jsx87(Banner, { tone: "danger", title: failureTitle, detail: error ?? void 0 }),
9232
+ onRetry !== null ? /* @__PURE__ */ jsx87(Button, { variant: "primary", block: true, onClick: onRetry, children: "Try again" }) : null
9170
9233
  ] }) : null
9171
9234
  ] }) })
9172
9235
  ] })
@@ -9174,10 +9237,10 @@ function SessionScreen({ kind, error, onRetry, productName }) {
9174
9237
  }
9175
9238
 
9176
9239
  // src/components/platform/RoadmapTimeline.tsx
9177
- import * as React64 from "react";
9240
+ import * as React65 from "react";
9178
9241
 
9179
9242
  // src/kits/session.ts
9180
- import * as React62 from "react";
9243
+ import * as React63 from "react";
9181
9244
  var PERMISSION_CATALOG = [
9182
9245
  { group: "Plans", items: [
9183
9246
  { key: "plan.view", label: "View plans", detail: "Read any plan in the workspace." },
@@ -10744,8 +10807,8 @@ function roadmap(overrides) {
10744
10807
  };
10745
10808
  }
10746
10809
  function useSession() {
10747
- const [s, setS] = React62.useState(getSession);
10748
- React62.useEffect(() => subscribe(setS), []);
10810
+ const [s, setS] = React63.useState(getSession);
10811
+ React63.useEffect(() => subscribe(setS), []);
10749
10812
  return s;
10750
10813
  }
10751
10814
  var SessionKit = {
@@ -10778,7 +10841,7 @@ var SessionKit = {
10778
10841
  };
10779
10842
  function DemoSessionProvider({ children }) {
10780
10843
  const session = useSession();
10781
- const value = React62.useMemo(
10844
+ const value = React63.useMemo(
10782
10845
  () => ({
10783
10846
  user: session.user,
10784
10847
  roles: session.roles,
@@ -10794,11 +10857,11 @@ function DemoSessionProvider({ children }) {
10794
10857
  }),
10795
10858
  [session]
10796
10859
  );
10797
- return React62.createElement(SessionProvider, { value }, children);
10860
+ return React63.createElement(SessionProvider, { value }, children);
10798
10861
  }
10799
10862
 
10800
10863
  // src/kits/runtime.ts
10801
- import * as React63 from "react";
10864
+ import * as React64 from "react";
10802
10865
  var WIRED_ENDPOINTS = [
10803
10866
  // Nothing yet. Every id below would come from a real service:
10804
10867
  // "plan.get", "placements.list", …
@@ -10969,8 +11032,8 @@ var RuntimeKit = {
10969
11032
  };
10970
11033
  RuntimeKit.declare(FEATURE_NEEDS);
10971
11034
  function useRuntimeMode() {
10972
- const [m, setM] = React63.useState(RuntimeKit.getMode());
10973
- React63.useEffect(() => RuntimeKit.subscribe(setM), []);
11035
+ const [m, setM] = React64.useState(RuntimeKit.getMode());
11036
+ React64.useEffect(() => RuntimeKit.subscribe(setM), []);
10974
11037
  return m;
10975
11038
  }
10976
11039
  function useFeatureStatus(key) {
@@ -10989,7 +11052,7 @@ var UseRuntimeMode = useRuntimeMode;
10989
11052
  var UseFeatureStatus = useFeatureStatus;
10990
11053
 
10991
11054
  // src/components/platform/RoadmapTimeline.tsx
10992
- import { jsx as jsx86, jsxs as jsxs74 } from "react/jsx-runtime";
11055
+ import { jsx as jsx88, jsxs as jsxs75 } from "react/jsx-runtime";
10993
11056
  var STATUS = {
10994
11057
  shipped: { tone: "success", icon: "check-circle", label: "Wired" },
10995
11058
  next: { tone: "warning", icon: "traffic-cone", label: "Not wired" },
@@ -11004,45 +11067,45 @@ function RoadmapCard({ item, byKey, onOpenFlag }) {
11004
11067
  const s = STATUS[item.status] || STATUS.planned;
11005
11068
  const deps = (item.dependsOn || []).map((k) => byKey[k]).filter(Boolean);
11006
11069
  const blocking = deps.filter((d) => !d.implemented);
11007
- return /* @__PURE__ */ jsx86(Card, { elevation: "flat", children: /* @__PURE__ */ jsxs74("div", { className: "fd-stack", style: { gap: 10 }, children: [
11008
- /* @__PURE__ */ jsxs74("div", { className: "fd-row", style: { gap: 8, flexWrap: "wrap" }, children: [
11009
- /* @__PURE__ */ jsx86("span", { className: "fd-body", style: { fontWeight: 700, flex: 1, minWidth: 140 }, children: item.label }),
11010
- /* @__PURE__ */ jsx86(Badge, { tone: "neutral", icon: PROJECT_ICON[item.project] || "squares-four", children: item.project }),
11011
- /* @__PURE__ */ jsx86(Badge, { tone: s.tone, icon: s.icon, children: s.label })
11070
+ return /* @__PURE__ */ jsx88(Card, { elevation: "flat", children: /* @__PURE__ */ jsxs75("div", { className: "fd-stack", style: { gap: 10 }, children: [
11071
+ /* @__PURE__ */ jsxs75("div", { className: "fd-row", style: { gap: 8, flexWrap: "wrap" }, children: [
11072
+ /* @__PURE__ */ jsx88("span", { className: "fd-body", style: { fontWeight: 700, flex: 1, minWidth: 140 }, children: item.label }),
11073
+ /* @__PURE__ */ jsx88(Badge, { tone: "neutral", icon: PROJECT_ICON[item.project] || "squares-four", children: item.project }),
11074
+ /* @__PURE__ */ jsx88(Badge, { tone: s.tone, icon: s.icon, children: s.label })
11012
11075
  ] }),
11013
- /* @__PURE__ */ jsx86("p", { className: "fd-body-sm fd-secondary", style: { margin: 0, textWrap: "pretty" }, children: item.description }),
11014
- item.backend ? /* @__PURE__ */ jsxs74("div", { className: "fd-row", style: { gap: 10, alignItems: "flex-start" }, children: [
11015
- /* @__PURE__ */ jsx86("span", { className: "fd-overline fd-muted", style: { width: 62, flex: "none", paddingTop: 2 }, children: "Backend" }),
11016
- /* @__PURE__ */ jsx86("span", { className: "fd-body-sm", style: { flex: 1, textWrap: "pretty" }, children: item.backend })
11076
+ /* @__PURE__ */ jsx88("p", { className: "fd-body-sm fd-secondary", style: { margin: 0, textWrap: "pretty" }, children: item.description }),
11077
+ item.backend ? /* @__PURE__ */ jsxs75("div", { className: "fd-row", style: { gap: 10, alignItems: "flex-start" }, children: [
11078
+ /* @__PURE__ */ jsx88("span", { className: "fd-overline fd-muted", style: { width: 62, flex: "none", paddingTop: 2 }, children: "Backend" }),
11079
+ /* @__PURE__ */ jsx88("span", { className: "fd-body-sm", style: { flex: 1, textWrap: "pretty" }, children: item.backend })
11017
11080
  ] }) : null,
11018
- /* @__PURE__ */ jsxs74("div", { className: "fd-row", style: { gap: 12, flexWrap: "wrap" }, children: [
11019
- item.effort ? /* @__PURE__ */ jsxs74("span", { className: "fd-body-sm fd-muted", children: [
11020
- /* @__PURE__ */ jsx86("i", { className: "ph ph-hourglass-medium" }),
11081
+ /* @__PURE__ */ jsxs75("div", { className: "fd-row", style: { gap: 12, flexWrap: "wrap" }, children: [
11082
+ item.effort ? /* @__PURE__ */ jsxs75("span", { className: "fd-body-sm fd-muted", children: [
11083
+ /* @__PURE__ */ jsx88("i", { className: "ph ph-hourglass-medium" }),
11021
11084
  " ",
11022
11085
  item.effort
11023
11086
  ] }) : null,
11024
- /* @__PURE__ */ jsxs74("span", { className: "fd-body-sm fd-muted", children: [
11025
- /* @__PURE__ */ jsx86("i", { className: "ph ph-user" }),
11087
+ /* @__PURE__ */ jsxs75("span", { className: "fd-body-sm fd-muted", children: [
11088
+ /* @__PURE__ */ jsx88("i", { className: "ph ph-user" }),
11026
11089
  " ",
11027
11090
  item.owner
11028
11091
  ] }),
11029
- item.screen ? /* @__PURE__ */ jsx86(Badge, { tone: "neutral", icon: "browser", children: "screen" }) : null,
11030
- /* @__PURE__ */ jsx86("span", { style: { flex: 1 } }),
11031
- /* @__PURE__ */ jsx86(
11092
+ item.screen ? /* @__PURE__ */ jsx88(Badge, { tone: "neutral", icon: "browser", children: "screen" }) : null,
11093
+ /* @__PURE__ */ jsx88("span", { style: { flex: 1 } }),
11094
+ /* @__PURE__ */ jsx88(
11032
11095
  "button",
11033
11096
  {
11034
11097
  type: "button",
11035
11098
  onClick: () => onOpenFlag && onOpenFlag(item.key),
11036
11099
  style: { all: "unset", cursor: "pointer", display: "inline-flex", alignItems: "center", gap: 5 },
11037
- children: /* @__PURE__ */ jsx86("code", { className: "fd-mono", style: { fontSize: 11, color: "var(--brand)" }, children: item.key })
11100
+ children: /* @__PURE__ */ jsx88("code", { className: "fd-mono", style: { fontSize: 11, color: "var(--brand)" }, children: item.key })
11038
11101
  }
11039
11102
  )
11040
11103
  ] }),
11041
- deps.length ? /* @__PURE__ */ jsxs74("div", { className: "fd-row", style: { gap: 6, flexWrap: "wrap", paddingTop: 6, borderTop: "1px solid var(--border)" }, children: [
11042
- /* @__PURE__ */ jsx86("span", { className: "fd-overline fd-muted", style: { paddingTop: 3 }, children: "After" }),
11043
- deps.map((d) => /* @__PURE__ */ jsx86(Tag, { icon: d.implemented ? "check" : "clock", children: d.label }, d.key))
11104
+ deps.length ? /* @__PURE__ */ jsxs75("div", { className: "fd-row", style: { gap: 6, flexWrap: "wrap", paddingTop: 6, borderTop: "1px solid var(--border)" }, children: [
11105
+ /* @__PURE__ */ jsx88("span", { className: "fd-overline fd-muted", style: { paddingTop: 3 }, children: "After" }),
11106
+ deps.map((d) => /* @__PURE__ */ jsx88(Tag, { icon: d.implemented ? "check" : "clock", children: d.label }, d.key))
11044
11107
  ] }) : null,
11045
- blocking.length && !item.implemented ? /* @__PURE__ */ jsxs74("span", { className: "fd-body-sm", style: { color: "var(--warn-text)" }, children: [
11108
+ blocking.length && !item.implemented ? /* @__PURE__ */ jsxs75("span", { className: "fd-body-sm", style: { color: "var(--warn-text)" }, children: [
11046
11109
  "Blocked until ",
11047
11110
  blocking.map((d) => d.label).join(" and "),
11048
11111
  " ",
@@ -11053,12 +11116,12 @@ function RoadmapCard({ item, byKey, onOpenFlag }) {
11053
11116
  }
11054
11117
  function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
11055
11118
  const session = SessionKit.useSession();
11056
- const [project, setProject] = React64.useState("");
11057
- const [q, setQ] = React64.useState("");
11058
- const scrollRef = React64.useRef(null);
11059
- const nowRef = React64.useRef(null);
11060
- const rm = React64.useMemo(() => SessionKit.roadmap({ isComplete: RuntimeKit.isComplete }), [session]);
11061
- const byKey = React64.useMemo(() => {
11119
+ const [project, setProject] = React65.useState("");
11120
+ const [q, setQ] = React65.useState("");
11121
+ const scrollRef = React65.useRef(null);
11122
+ const nowRef = React65.useRef(null);
11123
+ const rm = React65.useMemo(() => SessionKit.roadmap({ isComplete: RuntimeKit.isComplete }), [session]);
11124
+ const byKey = React65.useMemo(() => {
11062
11125
  const m = {};
11063
11126
  rm.items.forEach((i) => {
11064
11127
  m[i.key] = i;
@@ -11067,7 +11130,7 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
11067
11130
  }, [rm]);
11068
11131
  const items = rm.items.filter((i) => (!project || i.project === project) && (!q || (i.label + " " + i.description + " " + (i.backend || "") + " " + i.key).toLowerCase().includes(q.toLowerCase())));
11069
11132
  const projects = [...new Set(rm.items.map((i) => i.project))];
11070
- React64.useEffect(() => {
11133
+ React65.useEffect(() => {
11071
11134
  let raf1 = 0, raf2 = 0;
11072
11135
  const place = () => {
11073
11136
  const box = scrollRef.current, mark = nowRef.current;
@@ -11095,23 +11158,23 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
11095
11158
  }, 0);
11096
11159
  const nextPhase = items.find((i) => !i.implemented);
11097
11160
  let lastPhase = null;
11098
- return /* @__PURE__ */ jsxs74("div", { className: "fd-stack", style: { gap: 16, maxWidth: 1e3 }, children: [
11099
- /* @__PURE__ */ jsxs74("div", { className: "fd-stack", style: { gap: 10 }, children: [
11100
- /* @__PURE__ */ jsx86("span", { className: "fd-overline fd-muted", children: "Architecture" }),
11101
- /* @__PURE__ */ jsx86("h1", { className: "fd-h1", style: { margin: 0 }, children: title }),
11102
- /* @__PURE__ */ jsx86("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." })
11161
+ return /* @__PURE__ */ jsxs75("div", { className: "fd-stack", style: { gap: 16, maxWidth: 1e3 }, children: [
11162
+ /* @__PURE__ */ jsxs75("div", { className: "fd-stack", style: { gap: 10 }, children: [
11163
+ /* @__PURE__ */ jsx88("span", { className: "fd-overline fd-muted", children: "Architecture" }),
11164
+ /* @__PURE__ */ jsx88("h1", { className: "fd-h1", style: { margin: 0 }, children: title }),
11165
+ /* @__PURE__ */ jsx88("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." })
11103
11166
  ] }),
11104
- /* @__PURE__ */ jsxs74("div", { className: "fd-grid-stats is-thin", children: [
11105
- /* @__PURE__ */ jsx86(StatTile, { compact: true, label: "Wired", value: String(rm.shipped), sub: "of " + rm.items.length + " features" }),
11106
- /* @__PURE__ */ jsx86(StatTile, { compact: true, label: "Remaining", value: String(rm.remaining), sub: "backend work" }),
11107
- /* @__PURE__ */ jsx86(StatTile, { compact: true, label: "Est. effort", value: days ? days + " days" : "\u2014", sub: "sum of estimates, not calendar" }),
11108
- /* @__PURE__ */ jsx86(StatTile, { compact: true, label: "Up next", value: nextPhase ? "Phase " + nextPhase.phase : "\u2014", sub: nextPhase ? nextPhase.phaseName : "all wired" })
11167
+ /* @__PURE__ */ jsxs75("div", { className: "fd-grid-stats is-thin", children: [
11168
+ /* @__PURE__ */ jsx88(StatTile, { compact: true, label: "Wired", value: String(rm.shipped), sub: "of " + rm.items.length + " features" }),
11169
+ /* @__PURE__ */ jsx88(StatTile, { compact: true, label: "Remaining", value: String(rm.remaining), sub: "backend work" }),
11170
+ /* @__PURE__ */ jsx88(StatTile, { compact: true, label: "Est. effort", value: days ? days + " days" : "\u2014", sub: "sum of estimates, not calendar" }),
11171
+ /* @__PURE__ */ jsx88(StatTile, { compact: true, label: "Up next", value: nextPhase ? "Phase " + nextPhase.phase : "\u2014", sub: nextPhase ? nextPhase.phaseName : "all wired" })
11109
11172
  ] }),
11110
- /* @__PURE__ */ jsxs74("div", { className: "fd-row", style: { gap: 10, flexWrap: "wrap" }, children: [
11111
- /* @__PURE__ */ jsx86(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 } }),
11112
- /* @__PURE__ */ jsx86(Select, { placeholder: "All projects", value: project, onChange: (e) => setProject(e.target.value), options: projects, style: { width: 190 } }),
11113
- /* @__PURE__ */ jsx86("span", { style: { flex: 1 } }),
11114
- /* @__PURE__ */ jsx86(
11173
+ /* @__PURE__ */ jsxs75("div", { className: "fd-row", style: { gap: 10, flexWrap: "wrap" }, children: [
11174
+ /* @__PURE__ */ jsx88(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 } }),
11175
+ /* @__PURE__ */ jsx88(Select, { placeholder: "All projects", value: project, onChange: (e) => setProject(e.target.value), options: projects, style: { width: 190 } }),
11176
+ /* @__PURE__ */ jsx88("span", { style: { flex: 1 } }),
11177
+ /* @__PURE__ */ jsx88(
11115
11178
  Button,
11116
11179
  {
11117
11180
  size: "sm",
@@ -11125,7 +11188,7 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
11125
11188
  }
11126
11189
  )
11127
11190
  ] }),
11128
- /* @__PURE__ */ jsx86(
11191
+ /* @__PURE__ */ jsx88(
11129
11192
  Flag,
11130
11193
  {
11131
11194
  tone: "info",
@@ -11134,60 +11197,60 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
11134
11197
  actions: null
11135
11198
  }
11136
11199
  ),
11137
- /* @__PURE__ */ jsx86("div", { className: "fd-rm", children: /* @__PURE__ */ jsx86("div", { className: "fd-rm-scroll", ref: scrollRef, children: /* @__PURE__ */ jsxs74("div", { className: "fd-rm-track", children: [
11138
- /* @__PURE__ */ jsx86("span", { className: "fd-rm-spine", children: /* @__PURE__ */ jsx86("span", { className: "fd-rm-spine-done", style: { height: items.length ? 100 * shippedShown / items.length + "%" : "0%" } }) }),
11200
+ /* @__PURE__ */ jsx88("div", { className: "fd-rm", children: /* @__PURE__ */ jsx88("div", { className: "fd-rm-scroll", ref: scrollRef, children: /* @__PURE__ */ jsxs75("div", { className: "fd-rm-track", children: [
11201
+ /* @__PURE__ */ jsx88("span", { className: "fd-rm-spine", children: /* @__PURE__ */ jsx88("span", { className: "fd-rm-spine-done", style: { height: items.length ? 100 * shippedShown / items.length + "%" : "0%" } }) }),
11139
11202
  items.map((item, n) => {
11140
11203
  const showPhase = item.phase !== lastPhase;
11141
11204
  lastPhase = item.phase;
11142
11205
  const inPhase = items.filter((i) => i.phase === item.phase).length;
11143
11206
  const isBoundary = n === firstPending;
11144
- return /* @__PURE__ */ jsxs74(React64.Fragment, { children: [
11145
- showPhase ? /* @__PURE__ */ jsxs74("div", { className: "fd-rm-era", children: [
11146
- /* @__PURE__ */ jsxs74("span", { className: "fd-row", style: { gap: 8, flexWrap: "wrap", alignItems: "baseline" }, children: [
11147
- /* @__PURE__ */ jsx86("span", { style: { fontWeight: 700 }, children: item.phase === 0 ? "Shipped" : "Phase " + item.phase + " \u2014 " + item.phaseName }),
11148
- item.phase === 0 ? null : /* @__PURE__ */ jsxs74("span", { className: "fd-mono", style: { opacity: 0.7, fontWeight: 400 }, children: [
11207
+ return /* @__PURE__ */ jsxs75(React65.Fragment, { children: [
11208
+ showPhase ? /* @__PURE__ */ jsxs75("div", { className: "fd-rm-era", children: [
11209
+ /* @__PURE__ */ jsxs75("span", { className: "fd-row", style: { gap: 8, flexWrap: "wrap", alignItems: "baseline" }, children: [
11210
+ /* @__PURE__ */ jsx88("span", { style: { fontWeight: 700 }, children: item.phase === 0 ? "Shipped" : "Phase " + item.phase + " \u2014 " + item.phaseName }),
11211
+ item.phase === 0 ? null : /* @__PURE__ */ jsxs75("span", { className: "fd-mono", style: { opacity: 0.7, fontWeight: 400 }, children: [
11149
11212
  fmtDate(item.phaseStart),
11150
11213
  " \u2013 ",
11151
11214
  fmtDate(item.date)
11152
11215
  ] }),
11153
- /* @__PURE__ */ jsxs74("span", { style: { opacity: 0.7, fontWeight: 400 }, children: [
11216
+ /* @__PURE__ */ jsxs75("span", { style: { opacity: 0.7, fontWeight: 400 }, children: [
11154
11217
  "\xB7 ",
11155
11218
  inPhase,
11156
11219
  " feature",
11157
11220
  inPhase === 1 ? "" : "s"
11158
11221
  ] })
11159
11222
  ] }),
11160
- item.phaseWhy ? /* @__PURE__ */ jsx86("p", { className: "fd-rm-era-why", children: item.phaseWhy }) : null
11223
+ item.phaseWhy ? /* @__PURE__ */ jsx88("p", { className: "fd-rm-era-why", children: item.phaseWhy }) : null
11161
11224
  ] }) : null,
11162
- isBoundary ? /* @__PURE__ */ jsx86("div", { className: "fd-rm-now", ref: nowRef, children: /* @__PURE__ */ jsxs74("span", { className: "fd-rm-now-pill", children: [
11163
- /* @__PURE__ */ jsx86("i", { className: "ph ph-map-pin" }),
11225
+ isBoundary ? /* @__PURE__ */ jsx88("div", { className: "fd-rm-now", ref: nowRef, children: /* @__PURE__ */ jsxs75("span", { className: "fd-rm-now-pill", children: [
11226
+ /* @__PURE__ */ jsx88("i", { className: "ph ph-map-pin" }),
11164
11227
  " You are here \u2014 everything above is wired"
11165
11228
  ] }) }) : null,
11166
- /* @__PURE__ */ jsxs74("div", { className: "fd-rm-row", children: [
11167
- /* @__PURE__ */ jsx86("span", { className: "fd-rm-dot " + (item.implemented ? "is-shipped" : item.status === "next" ? "is-next" : "") }),
11168
- /* @__PURE__ */ jsxs74("div", { className: "fd-rm-date", children: [
11229
+ /* @__PURE__ */ jsxs75("div", { className: "fd-rm-row", children: [
11230
+ /* @__PURE__ */ jsx88("span", { className: "fd-rm-dot " + (item.implemented ? "is-shipped" : item.status === "next" ? "is-next" : "") }),
11231
+ /* @__PURE__ */ jsxs75("div", { className: "fd-rm-date", children: [
11169
11232
  fmtDate(item.date),
11170
- /* @__PURE__ */ jsx86("br", {}),
11171
- /* @__PURE__ */ jsx86("span", { style: { opacity: 0.75 }, children: item.implemented ? "shipped" : "phase " + item.phase })
11233
+ /* @__PURE__ */ jsx88("br", {}),
11234
+ /* @__PURE__ */ jsx88("span", { style: { opacity: 0.75 }, children: item.implemented ? "shipped" : "phase " + item.phase })
11172
11235
  ] }),
11173
- /* @__PURE__ */ jsx86(RoadmapCard, { item, byKey, onOpenFlag })
11236
+ /* @__PURE__ */ jsx88(RoadmapCard, { item, byKey, onOpenFlag })
11174
11237
  ] })
11175
11238
  ] }, item.key);
11176
11239
  }),
11177
- !items.length ? /* @__PURE__ */ jsx86("p", { className: "fd-body-sm fd-muted", children: "Nothing matches that filter." }) : null
11240
+ !items.length ? /* @__PURE__ */ jsx88("p", { className: "fd-body-sm fd-muted", children: "Nothing matches that filter." }) : null
11178
11241
  ] }) }) }),
11179
- /* @__PURE__ */ jsxs74("p", { className: "fd-body-sm fd-muted", style: { margin: 0 }, children: [
11242
+ /* @__PURE__ */ jsxs75("p", { className: "fd-body-sm fd-muted", style: { margin: 0 }, children: [
11180
11243
  "Derived from the feature-flag registry \u2014 each entry's status is its flag's ",
11181
- /* @__PURE__ */ jsx86("code", { className: "fd-mono", children: "implemented" }),
11244
+ /* @__PURE__ */ jsx88("code", { className: "fd-mono", children: "implemented" }),
11182
11245
  " field, so this page cannot drift from what the apps actually do."
11183
11246
  ] })
11184
11247
  ] });
11185
11248
  }
11186
11249
 
11187
11250
  // src/components/platform/ComingSoon.tsx
11188
- import * as React65 from "react";
11251
+ import * as React66 from "react";
11189
11252
  import { createPortal as createPortal6 } from "react-dom";
11190
- import { Fragment as Fragment24, jsx as jsx87, jsxs as jsxs75 } from "react/jsx-runtime";
11253
+ import { Fragment as Fragment24, jsx as jsx89, jsxs as jsxs76 } from "react/jsx-runtime";
11191
11254
  var BYPASS_STORE = "fd.soon.bypass.v1";
11192
11255
  function readBypassed() {
11193
11256
  try {
@@ -11203,8 +11266,8 @@ function writeBypassed(list) {
11203
11266
  }
11204
11267
  }
11205
11268
  function useBypass(key) {
11206
- const [on, setOn] = React65.useState(() => !!key && readBypassed().indexOf(key) >= 0);
11207
- React65.useEffect(() => {
11269
+ const [on, setOn] = React66.useState(() => !!key && readBypassed().indexOf(key) >= 0);
11270
+ React66.useEffect(() => {
11208
11271
  setOn(!!key && readBypassed().indexOf(key) >= 0);
11209
11272
  }, [key]);
11210
11273
  const set = (next) => {
@@ -11217,43 +11280,43 @@ function useBypass(key) {
11217
11280
  return [on, set];
11218
11281
  }
11219
11282
  function SoonCard({ label, detail, backend, eta, effort, onRoadmap, allowed, onBypass }) {
11220
- return /* @__PURE__ */ jsxs75(Fragment24, { children: [
11221
- /* @__PURE__ */ jsxs75("span", { className: "fd-soon-badge", children: [
11222
- /* @__PURE__ */ jsx87("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" }),
11283
+ return /* @__PURE__ */ jsxs76(Fragment24, { children: [
11284
+ /* @__PURE__ */ jsxs76("span", { className: "fd-soon-badge", children: [
11285
+ /* @__PURE__ */ jsx89("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" }),
11223
11286
  label
11224
11287
  ] }),
11225
- detail ? /* @__PURE__ */ jsx87("span", { className: "fd-soon-detail", children: detail }) : null,
11226
- backend ? /* @__PURE__ */ jsxs75("span", { className: "fd-soon-backend", children: [
11227
- /* @__PURE__ */ jsx87("span", { className: "fd-overline", children: "Needs" }),
11288
+ detail ? /* @__PURE__ */ jsx89("span", { className: "fd-soon-detail", children: detail }) : null,
11289
+ backend ? /* @__PURE__ */ jsxs76("span", { className: "fd-soon-backend", children: [
11290
+ /* @__PURE__ */ jsx89("span", { className: "fd-overline", children: "Needs" }),
11228
11291
  " ",
11229
11292
  backend
11230
11293
  ] }) : null,
11231
- eta || effort || onRoadmap ? /* @__PURE__ */ jsxs75("span", { className: "fd-soon-meta", children: [
11232
- eta ? /* @__PURE__ */ jsxs75("span", { children: [
11233
- /* @__PURE__ */ jsx87("i", { className: "ph ph-calendar-blank", "aria-hidden": "true" }),
11294
+ eta || effort || onRoadmap ? /* @__PURE__ */ jsxs76("span", { className: "fd-soon-meta", children: [
11295
+ eta ? /* @__PURE__ */ jsxs76("span", { children: [
11296
+ /* @__PURE__ */ jsx89("i", { className: "ph ph-calendar-blank", "aria-hidden": "true" }),
11234
11297
  " ",
11235
11298
  eta
11236
11299
  ] }) : null,
11237
- effort ? /* @__PURE__ */ jsxs75("span", { children: [
11238
- /* @__PURE__ */ jsx87("i", { className: "ph ph-hourglass-medium", "aria-hidden": "true" }),
11300
+ effort ? /* @__PURE__ */ jsxs76("span", { children: [
11301
+ /* @__PURE__ */ jsx89("i", { className: "ph ph-hourglass-medium", "aria-hidden": "true" }),
11239
11302
  " ",
11240
11303
  effort
11241
11304
  ] }) : null,
11242
- onRoadmap ? /* @__PURE__ */ jsxs75("button", { type: "button", className: "fd-soon-link", onClick: onRoadmap, children: [
11305
+ onRoadmap ? /* @__PURE__ */ jsxs76("button", { type: "button", className: "fd-soon-link", onClick: onRoadmap, children: [
11243
11306
  "See the roadmap ",
11244
- /* @__PURE__ */ jsx87("i", { className: "ph ph-arrow-right", "aria-hidden": "true" })
11307
+ /* @__PURE__ */ jsx89("i", { className: "ph ph-arrow-right", "aria-hidden": "true" })
11245
11308
  ] }) : null
11246
11309
  ] }) : null,
11247
- allowed ? /* @__PURE__ */ jsxs75("button", { type: "button", className: "fd-soon-view", onClick: onBypass, children: [
11248
- /* @__PURE__ */ jsx87("i", { className: "ph ph-eye", "aria-hidden": "true" }),
11310
+ allowed ? /* @__PURE__ */ jsxs76("button", { type: "button", className: "fd-soon-view", onClick: onBypass, children: [
11311
+ /* @__PURE__ */ jsx89("i", { className: "ph ph-eye", "aria-hidden": "true" }),
11249
11312
  " View and use it anyway"
11250
11313
  ] }) : null
11251
11314
  ] });
11252
11315
  }
11253
11316
  function useHoverCard(open2) {
11254
- const anchor = React65.useRef(null);
11255
- const [pos, setPos] = React65.useState(null);
11256
- React65.useLayoutEffect(() => {
11317
+ const anchor = React66.useRef(null);
11318
+ const [pos, setPos] = React66.useState(null);
11319
+ React66.useLayoutEffect(() => {
11257
11320
  if (!open2 || !anchor.current) {
11258
11321
  setPos(null);
11259
11322
  return;
@@ -11305,9 +11368,9 @@ function ComingSoon({
11305
11368
  const tip = [label, detail, backend ? "Needs " + backend : null, eta ? "ETA " + eta : null, effort].filter(Boolean).join(" \xB7 ");
11306
11369
  if (inline) {
11307
11370
  if (allowed && bypassed) {
11308
- return /* @__PURE__ */ jsxs75("span", { className: ["fd-soon-inline-on", className].filter(Boolean).join(" "), ...rest, children: [
11371
+ return /* @__PURE__ */ jsxs76("span", { className: ["fd-soon-inline-on", className].filter(Boolean).join(" "), ...rest, children: [
11309
11372
  children,
11310
- /* @__PURE__ */ jsx87(
11373
+ /* @__PURE__ */ jsx89(
11311
11374
  "button",
11312
11375
  {
11313
11376
  type: "button",
@@ -11315,12 +11378,12 @@ function ComingSoon({
11315
11378
  title: "Unwired \u2014 writes go to the simulated backend. " + tip + " Click to re-blur.",
11316
11379
  onClick: () => setBypassed(false),
11317
11380
  "aria-label": "Re-blur this unwired feature",
11318
- children: /* @__PURE__ */ jsx87("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" })
11381
+ children: /* @__PURE__ */ jsx89("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" })
11319
11382
  }
11320
11383
  )
11321
11384
  ] });
11322
11385
  }
11323
- return /* @__PURE__ */ jsx87(
11386
+ return /* @__PURE__ */ jsx89(
11324
11387
  InlineSoon,
11325
11388
  {
11326
11389
  label,
@@ -11340,20 +11403,20 @@ function ComingSoon({
11340
11403
  );
11341
11404
  }
11342
11405
  if (allowed && bypassed) {
11343
- return /* @__PURE__ */ jsxs75("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 14 }, ...rest, children: [
11344
- /* @__PURE__ */ jsxs75("div", { className: "fd-soon-bar", role: "status", children: [
11345
- /* @__PURE__ */ jsxs75("span", { className: "fd-soon-badge", children: [
11346
- /* @__PURE__ */ jsx87("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" }),
11406
+ return /* @__PURE__ */ jsxs76("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 14 }, ...rest, children: [
11407
+ /* @__PURE__ */ jsxs76("div", { className: "fd-soon-bar", role: "status", children: [
11408
+ /* @__PURE__ */ jsxs76("span", { className: "fd-soon-badge", children: [
11409
+ /* @__PURE__ */ jsx89("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" }),
11347
11410
  "Unwired feature \u2014 you are using it anyway"
11348
11411
  ] }),
11349
- /* @__PURE__ */ jsx87("span", { className: "fd-soon-bar-detail", children: "Every action here writes to the simulated backend, so nothing you do persists beyond this session." }),
11350
- /* @__PURE__ */ jsxs75("span", { className: "fd-soon-bar-actions", children: [
11351
- onRoadmap ? /* @__PURE__ */ jsxs75("button", { type: "button", className: "fd-soon-link", onClick: onRoadmap, children: [
11412
+ /* @__PURE__ */ jsx89("span", { className: "fd-soon-bar-detail", children: "Every action here writes to the simulated backend, so nothing you do persists beyond this session." }),
11413
+ /* @__PURE__ */ jsxs76("span", { className: "fd-soon-bar-actions", children: [
11414
+ onRoadmap ? /* @__PURE__ */ jsxs76("button", { type: "button", className: "fd-soon-link", onClick: onRoadmap, children: [
11352
11415
  "Roadmap ",
11353
- /* @__PURE__ */ jsx87("i", { className: "ph ph-arrow-right", "aria-hidden": "true" })
11416
+ /* @__PURE__ */ jsx89("i", { className: "ph ph-arrow-right", "aria-hidden": "true" })
11354
11417
  ] }) : null,
11355
- /* @__PURE__ */ jsxs75("button", { type: "button", className: "fd-soon-link", onClick: () => setBypassed(false), children: [
11356
- /* @__PURE__ */ jsx87("i", { className: "ph ph-eye-slash", "aria-hidden": "true" }),
11418
+ /* @__PURE__ */ jsxs76("button", { type: "button", className: "fd-soon-link", onClick: () => setBypassed(false), children: [
11419
+ /* @__PURE__ */ jsx89("i", { className: "ph ph-eye-slash", "aria-hidden": "true" }),
11357
11420
  " Re-blur"
11358
11421
  ] })
11359
11422
  ] })
@@ -11361,10 +11424,10 @@ function ComingSoon({
11361
11424
  children
11362
11425
  ] });
11363
11426
  }
11364
- return /* @__PURE__ */ jsxs75("div", { className: ["fd-soon", className].filter(Boolean).join(" "), style: minHeight ? { minHeight } : void 0, ...rest, children: [
11365
- /* @__PURE__ */ jsx87("div", { className: "fd-soon-under", style: { filter: "blur(" + blur + "px) saturate(.62)" }, ...{ inert: "" }, "aria-hidden": "true", children }),
11366
- /* @__PURE__ */ jsx87("div", { className: "fd-soon-veil" }),
11367
- /* @__PURE__ */ jsx87("div", { className: "fd-soon-note", role: "note", children: /* @__PURE__ */ jsx87(
11427
+ return /* @__PURE__ */ jsxs76("div", { className: ["fd-soon", className].filter(Boolean).join(" "), style: minHeight ? { minHeight } : void 0, ...rest, children: [
11428
+ /* @__PURE__ */ jsx89("div", { className: "fd-soon-under", style: { filter: "blur(" + blur + "px) saturate(.62)" }, ...{ inert: "" }, "aria-hidden": "true", children }),
11429
+ /* @__PURE__ */ jsx89("div", { className: "fd-soon-veil" }),
11430
+ /* @__PURE__ */ jsx89("div", { className: "fd-soon-note", role: "note", children: /* @__PURE__ */ jsx89(
11368
11431
  SoonCard,
11369
11432
  {
11370
11433
  label,
@@ -11380,12 +11443,12 @@ function ComingSoon({
11380
11443
  ] });
11381
11444
  }
11382
11445
  function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, onBypass, blur, tip, className, rest, children }) {
11383
- const [open2, setOpen] = React65.useState(false);
11446
+ const [open2, setOpen] = React66.useState(false);
11384
11447
  const [anchor, pos] = useHoverCard(open2);
11385
- const hoverCardRef = React65.useRef(null);
11448
+ const hoverCardRef = React66.useRef(null);
11386
11449
  const hoverLayer = useStackedLayer({ active: open2, containerRef: hoverCardRef, returnFocus: false });
11387
11450
  const zIndex = useLayerZIndex(hoverLayer);
11388
- const close2 = React65.useRef(null);
11451
+ const close2 = React66.useRef(null);
11389
11452
  const show = () => {
11390
11453
  if (close2.current) {
11391
11454
  clearTimeout(close2.current);
@@ -11401,10 +11464,10 @@ function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, o
11401
11464
  setOpen(false);
11402
11465
  }, 140);
11403
11466
  };
11404
- React65.useEffect(() => () => {
11467
+ React66.useEffect(() => () => {
11405
11468
  if (close2.current) clearTimeout(close2.current);
11406
11469
  }, []);
11407
- return /* @__PURE__ */ jsxs75(
11470
+ return /* @__PURE__ */ jsxs76(
11408
11471
  "span",
11409
11472
  {
11410
11473
  ref: anchor,
@@ -11415,8 +11478,8 @@ function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, o
11415
11478
  onBlur: hide,
11416
11479
  ...rest,
11417
11480
  children: [
11418
- /* @__PURE__ */ jsx87("span", { className: "fd-soon-under", style: { filter: "blur(" + Math.min(blur, 1.1) + "px) saturate(.66)" }, ...{ inert: "" }, "aria-hidden": "true", children }),
11419
- /* @__PURE__ */ jsx87(
11481
+ /* @__PURE__ */ jsx89("span", { className: "fd-soon-under", style: { filter: "blur(" + Math.min(blur, 1.1) + "px) saturate(.66)" }, ...{ inert: "" }, "aria-hidden": "true", children }),
11482
+ /* @__PURE__ */ jsx89(
11420
11483
  "button",
11421
11484
  {
11422
11485
  type: "button",
@@ -11427,11 +11490,11 @@ function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, o
11427
11490
  onFocus: show,
11428
11491
  onBlur: hide,
11429
11492
  onClick: () => open2 ? setOpen(false) : show(),
11430
- children: /* @__PURE__ */ jsx87("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" })
11493
+ children: /* @__PURE__ */ jsx89("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" })
11431
11494
  }
11432
11495
  ),
11433
11496
  open2 && pos ? createPortal6(
11434
- /* @__PURE__ */ jsx87(
11497
+ /* @__PURE__ */ jsx89(
11435
11498
  "div",
11436
11499
  {
11437
11500
  ref: hoverCardRef,
@@ -11440,7 +11503,7 @@ function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, o
11440
11503
  style: { position: "fixed", left: pos.left, top: pos.top, bottom: pos.bottom, width: pos.width, zIndex },
11441
11504
  onMouseEnter: show,
11442
11505
  onMouseLeave: hide,
11443
- children: /* @__PURE__ */ jsx87(
11506
+ children: /* @__PURE__ */ jsx89(
11444
11507
  SoonCard,
11445
11508
  {
11446
11509
  label,
@@ -11470,10 +11533,10 @@ function formatEta(iso2) {
11470
11533
  var FormatEta = formatEta;
11471
11534
 
11472
11535
  // src/components/platform/Gate.tsx
11473
- import { jsx as jsx88, jsxs as jsxs76 } from "react/jsx-runtime";
11536
+ import { jsx as jsx90, jsxs as jsxs77 } from "react/jsx-runtime";
11474
11537
  function PermissionDenied({ permission, title, detail, compact: compact3 = false, className = "", ...rest }) {
11475
11538
  const need = Array.isArray(permission) ? permission : [permission].filter(Boolean);
11476
- return /* @__PURE__ */ jsxs76(
11539
+ return /* @__PURE__ */ jsxs77(
11477
11540
  "div",
11478
11541
  {
11479
11542
  className: ["fd-stack", className].filter(Boolean).join(" "),
@@ -11489,14 +11552,14 @@ function PermissionDenied({ permission, title, detail, compact: compact3 = false
11489
11552
  },
11490
11553
  ...rest,
11491
11554
  children: [
11492
- /* @__PURE__ */ jsxs76("span", { className: "fd-row", style: { gap: 8 }, children: [
11493
- /* @__PURE__ */ jsx88("i", { className: "ph ph-lock-simple", style: { fontSize: 16, color: "var(--text-muted)" }, "aria-hidden": "true" }),
11494
- /* @__PURE__ */ jsx88("span", { className: compact3 ? "fd-label-lg" : "fd-h3", children: title || "You do not have access to this" })
11555
+ /* @__PURE__ */ jsxs77("span", { className: "fd-row", style: { gap: 8 }, children: [
11556
+ /* @__PURE__ */ jsx90("i", { className: "ph ph-lock-simple", style: { fontSize: 16, color: "var(--text-muted)" }, "aria-hidden": "true" }),
11557
+ /* @__PURE__ */ jsx90("span", { className: compact3 ? "fd-label-lg" : "fd-h3", children: title || "You do not have access to this" })
11495
11558
  ] }),
11496
- /* @__PURE__ */ jsx88("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." }),
11497
- need.length ? /* @__PURE__ */ jsxs76("span", { className: "fd-row", style: { gap: 6, flexWrap: "wrap" }, children: [
11498
- /* @__PURE__ */ jsx88("span", { className: "fd-overline fd-muted", children: "Requires" }),
11499
- need.map((p) => /* @__PURE__ */ jsx88("code", { className: "fd-mono", style: {
11559
+ /* @__PURE__ */ jsx90("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." }),
11560
+ need.length ? /* @__PURE__ */ jsxs77("span", { className: "fd-row", style: { gap: 6, flexWrap: "wrap" }, children: [
11561
+ /* @__PURE__ */ jsx90("span", { className: "fd-overline fd-muted", children: "Requires" }),
11562
+ need.map((p) => /* @__PURE__ */ jsx90("code", { className: "fd-mono", style: {
11500
11563
  fontSize: 11.5,
11501
11564
  padding: "2px 7px",
11502
11565
  borderRadius: 5,
@@ -11509,7 +11572,7 @@ function PermissionDenied({ permission, title, detail, compact: compact3 = false
11509
11572
  );
11510
11573
  }
11511
11574
  function GatePending({ compact: compact3 = false, className = "" }) {
11512
- return /* @__PURE__ */ jsxs76(
11575
+ return /* @__PURE__ */ jsxs77(
11513
11576
  "div",
11514
11577
  {
11515
11578
  className: ["fd-stack", className].filter(Boolean).join(" "),
@@ -11525,11 +11588,11 @@ function GatePending({ compact: compact3 = false, className = "" }) {
11525
11588
  textAlign: "left"
11526
11589
  },
11527
11590
  children: [
11528
- /* @__PURE__ */ jsxs76("span", { className: "fd-row", style: { gap: 8 }, children: [
11529
- /* @__PURE__ */ jsx88("i", { className: "ph ph-arrows-clockwise", style: { fontSize: 16, color: "var(--text-muted)" }, "aria-hidden": "true" }),
11530
- /* @__PURE__ */ jsx88("span", { className: compact3 ? "fd-label-lg" : "fd-h3", children: "Reconnecting\u2026" })
11591
+ /* @__PURE__ */ jsxs77("span", { className: "fd-row", style: { gap: 8 }, children: [
11592
+ /* @__PURE__ */ jsx90("i", { className: "ph ph-arrows-clockwise", style: { fontSize: 16, color: "var(--text-muted)" }, "aria-hidden": "true" }),
11593
+ /* @__PURE__ */ jsx90("span", { className: compact3 ? "fd-label-lg" : "fd-h3", children: "Reconnecting\u2026" })
11531
11594
  ] }),
11532
- /* @__PURE__ */ jsx88("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." })
11595
+ /* @__PURE__ */ jsx90("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." })
11533
11596
  ]
11534
11597
  }
11535
11598
  );
@@ -11539,7 +11602,7 @@ function Gate({ perm, anyOf, role, silent = false, fallback, pendingFallback, co
11539
11602
  if (pending) {
11540
11603
  if (pendingFallback !== void 0) return pendingFallback;
11541
11604
  if (silent) return null;
11542
- return /* @__PURE__ */ jsx88(GatePending, { compact: compact3 });
11605
+ return /* @__PURE__ */ jsx90(GatePending, { compact: compact3 });
11543
11606
  }
11544
11607
  let ok = true;
11545
11608
  if (perm) ok = ok && can2(perm);
@@ -11548,7 +11611,7 @@ function Gate({ perm, anyOf, role, silent = false, fallback, pendingFallback, co
11548
11611
  if (ok) return children;
11549
11612
  if (fallback !== void 0) return fallback;
11550
11613
  if (silent) return null;
11551
- return /* @__PURE__ */ jsx88(PermissionDenied, { permission: perm || anyOf, compact: compact3 });
11614
+ return /* @__PURE__ */ jsx90(PermissionDenied, { permission: perm || anyOf, compact: compact3 });
11552
11615
  }
11553
11616
  function FeatureGate({
11554
11617
  flag,
@@ -11571,7 +11634,7 @@ function FeatureGate({
11571
11634
  const f = SessionKit.findFlag(flag) || {};
11572
11635
  const missing = rt.missing || [];
11573
11636
  const canBypass = pending ? false : bypassPerm === null ? false : !bypassPerm || can2(bypassPerm);
11574
- return /* @__PURE__ */ jsx88(
11637
+ return /* @__PURE__ */ jsx90(
11575
11638
  ComingSoon,
11576
11639
  {
11577
11640
  label: label || (variant === "inline" ? f.label || "Not wired yet" : "Designed \u2014 backend not wired yet"),
@@ -11592,22 +11655,22 @@ function FeatureGate({
11592
11655
  function PermissionHint({ perm, children }) {
11593
11656
  const { can: can2, pending } = useSessionContext();
11594
11657
  if (pending) {
11595
- return /* @__PURE__ */ jsx88("span", { title: "Access can't be verified right now", style: { display: "inline-flex", opacity: 0.45, cursor: "not-allowed" }, "aria-disabled": "true", children: /* @__PURE__ */ jsx88("span", { style: { pointerEvents: "none" }, children }) });
11658
+ return /* @__PURE__ */ jsx90("span", { title: "Access can't be verified right now", style: { display: "inline-flex", opacity: 0.45, cursor: "not-allowed" }, "aria-disabled": "true", children: /* @__PURE__ */ jsx90("span", { style: { pointerEvents: "none" }, children }) });
11596
11659
  }
11597
11660
  if (can2(perm)) return children;
11598
- return /* @__PURE__ */ jsx88(
11661
+ return /* @__PURE__ */ jsx90(
11599
11662
  "span",
11600
11663
  {
11601
11664
  title: "Requires " + (Array.isArray(perm) ? perm.join(", ") : perm),
11602
11665
  style: { display: "inline-flex", opacity: 0.45, cursor: "not-allowed" },
11603
11666
  "aria-disabled": "true",
11604
- children: /* @__PURE__ */ jsx88("span", { style: { pointerEvents: "none" }, children })
11667
+ children: /* @__PURE__ */ jsx90("span", { style: { pointerEvents: "none" }, children })
11605
11668
  }
11606
11669
  );
11607
11670
  }
11608
11671
 
11609
11672
  // src/components/platform/ModeSwitch.tsx
11610
- import { Fragment as Fragment25, jsx as jsx89, jsxs as jsxs77 } from "react/jsx-runtime";
11673
+ import { Fragment as Fragment25, jsx as jsx91, jsxs as jsxs78 } from "react/jsx-runtime";
11611
11674
  function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog, onOpenSpec, summary }) {
11612
11675
  const mode2 = useRuntimeMode();
11613
11676
  const panel = useInlinePanel();
@@ -11619,8 +11682,8 @@ function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog
11619
11682
  RuntimeKit.setMode(next);
11620
11683
  setOpen(false);
11621
11684
  };
11622
- return /* @__PURE__ */ jsxs77("span", { style: { display: "inline-flex" }, ref, children: [
11623
- /* @__PURE__ */ jsxs77(
11685
+ return /* @__PURE__ */ jsxs78("span", { style: { display: "inline-flex" }, ref, children: [
11686
+ /* @__PURE__ */ jsxs78(
11624
11687
  "button",
11625
11688
  {
11626
11689
  type: "button",
@@ -11630,29 +11693,29 @@ function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog
11630
11693
  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.",
11631
11694
  className: "fd-mode-btn" + (test ? " is-test" : "") + (open2 ? " is-open" : ""),
11632
11695
  children: [
11633
- /* @__PURE__ */ jsx89("i", { className: "ph " + (test ? "ph-flask" : "ph-lightning"), style: { fontSize: 17 } }),
11634
- test && requestCount ? /* @__PURE__ */ jsx89("span", { className: "fd-mono fd-mode-count", children: requestCount > 99 ? "99+" : requestCount }, requestCount) : null
11696
+ /* @__PURE__ */ jsx91("i", { className: "ph " + (test ? "ph-flask" : "ph-lightning"), style: { fontSize: 17 } }),
11697
+ test && requestCount ? /* @__PURE__ */ jsx91("span", { className: "fd-mono fd-mode-count", children: requestCount > 99 ? "99+" : requestCount }, requestCount) : null
11635
11698
  ]
11636
11699
  }
11637
11700
  ),
11638
- /* @__PURE__ */ jsxs77(InlinePanelSurface, { panel, align: "right", offset: 8, width: 400, className: "fd-mode-pop", label: test ? "Test mode" : "Live mode", children: [
11639
- /* @__PURE__ */ jsxs77("span", { className: "fd-row", style: { gap: 10, padding: "12px 14px", borderBottom: "1px solid var(--border)" }, children: [
11640
- /* @__PURE__ */ jsxs77("span", { className: "fd-badge " + (test ? "fd-badge-warning" : "fd-badge-neutral"), children: [
11641
- /* @__PURE__ */ jsx89("i", { className: "ph " + (test ? "ph-flask" : "ph-lightning"), "aria-hidden": "true" }),
11701
+ /* @__PURE__ */ jsxs78(InlinePanelSurface, { panel, align: "right", offset: 8, width: 400, className: "fd-mode-pop", label: test ? "Test mode" : "Live mode", children: [
11702
+ /* @__PURE__ */ jsxs78("span", { className: "fd-row", style: { gap: 10, padding: "12px 14px", borderBottom: "1px solid var(--border)" }, children: [
11703
+ /* @__PURE__ */ jsxs78("span", { className: "fd-badge " + (test ? "fd-badge-warning" : "fd-badge-neutral"), children: [
11704
+ /* @__PURE__ */ jsx91("i", { className: "ph " + (test ? "ph-flask" : "ph-lightning"), "aria-hidden": "true" }),
11642
11705
  test ? "Test mode" : "Live mode"
11643
11706
  ] }),
11644
- test ? /* @__PURE__ */ jsxs77("span", { className: "fd-body-sm fd-muted fd-mono", children: [
11707
+ test ? /* @__PURE__ */ jsxs78("span", { className: "fd-body-sm fd-muted fd-mono", children: [
11645
11708
  requestCount,
11646
11709
  " simulated request",
11647
11710
  requestCount === 1 ? "" : "s"
11648
11711
  ] }) : null,
11649
- /* @__PURE__ */ jsx89("span", { style: { flex: 1 } }),
11650
- test && onClearLog ? /* @__PURE__ */ jsx89("button", { type: "button", className: "fd-soon-link", onClick: onClearLog, children: "Clear" }) : null
11712
+ /* @__PURE__ */ jsx91("span", { style: { flex: 1 } }),
11713
+ test && onClearLog ? /* @__PURE__ */ jsx91("button", { type: "button", className: "fd-soon-link", onClick: onClearLog, children: "Clear" }) : null
11651
11714
  ] }),
11652
- /* @__PURE__ */ jsxs77("span", { style: { display: "block", padding: "12px 14px", borderBottom: "1px solid var(--border)" }, children: [
11653
- /* @__PURE__ */ jsx89("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." }),
11654
- /* @__PURE__ */ jsxs77("span", { className: "fd-row", style: { gap: 8, marginTop: 10, flexWrap: "wrap" }, children: [
11655
- /* @__PURE__ */ jsxs77("span", { className: "fd-body-sm fd-muted fd-mono", children: [
11715
+ /* @__PURE__ */ jsxs78("span", { style: { display: "block", padding: "12px 14px", borderBottom: "1px solid var(--border)" }, children: [
11716
+ /* @__PURE__ */ jsx91("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." }),
11717
+ /* @__PURE__ */ jsxs78("span", { className: "fd-row", style: { gap: 8, marginTop: 10, flexWrap: "wrap" }, children: [
11718
+ /* @__PURE__ */ jsxs78("span", { className: "fd-body-sm fd-muted fd-mono", children: [
11656
11719
  s.endpointsWired,
11657
11720
  " endpoint",
11658
11721
  s.endpointsWired === 1 ? "" : "s",
@@ -11662,58 +11725,58 @@ function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog
11662
11725
  s.total,
11663
11726
  " features complete"
11664
11727
  ] }),
11665
- onOpenSpec ? /* @__PURE__ */ jsxs77(Fragment25, { children: [
11666
- /* @__PURE__ */ jsx89("span", { style: { flex: 1 } }),
11667
- /* @__PURE__ */ jsxs77("button", { type: "button", className: "fd-soon-link", onClick: () => {
11728
+ onOpenSpec ? /* @__PURE__ */ jsxs78(Fragment25, { children: [
11729
+ /* @__PURE__ */ jsx91("span", { style: { flex: 1 } }),
11730
+ /* @__PURE__ */ jsxs78("button", { type: "button", className: "fd-soon-link", onClick: () => {
11668
11731
  setOpen(false);
11669
11732
  onOpenSpec();
11670
11733
  }, children: [
11671
11734
  "API spec ",
11672
- /* @__PURE__ */ jsx89("i", { className: "ph ph-arrow-right", "aria-hidden": "true" })
11735
+ /* @__PURE__ */ jsx91("i", { className: "ph ph-arrow-right", "aria-hidden": "true" })
11673
11736
  ] })
11674
11737
  ] }) : null
11675
11738
  ] })
11676
11739
  ] }),
11677
- /* @__PURE__ */ jsxs77("span", { className: "fd-mode-choice", children: [
11678
- /* @__PURE__ */ jsxs77("button", { type: "button", className: "fd-mode-opt" + (!test ? " is-on" : ""), onClick: () => go("live"), children: [
11679
- /* @__PURE__ */ jsx89("i", { className: "ph ph-lightning", "aria-hidden": "true" }),
11680
- /* @__PURE__ */ jsxs77("span", { className: "fd-mode-opt-text", children: [
11681
- /* @__PURE__ */ jsx89("span", { className: "fd-mode-opt-title", children: "Live mode" }),
11682
- /* @__PURE__ */ jsx89("span", { className: "fd-mode-opt-desc", children: "Incomplete features under construction" })
11740
+ /* @__PURE__ */ jsxs78("span", { className: "fd-mode-choice", children: [
11741
+ /* @__PURE__ */ jsxs78("button", { type: "button", className: "fd-mode-opt" + (!test ? " is-on" : ""), onClick: () => go("live"), children: [
11742
+ /* @__PURE__ */ jsx91("i", { className: "ph ph-lightning", "aria-hidden": "true" }),
11743
+ /* @__PURE__ */ jsxs78("span", { className: "fd-mode-opt-text", children: [
11744
+ /* @__PURE__ */ jsx91("span", { className: "fd-mode-opt-title", children: "Live mode" }),
11745
+ /* @__PURE__ */ jsx91("span", { className: "fd-mode-opt-desc", children: "Incomplete features under construction" })
11683
11746
  ] }),
11684
- !test ? /* @__PURE__ */ jsx89("i", { className: "ph ph-check", "aria-hidden": "true" }) : null
11747
+ !test ? /* @__PURE__ */ jsx91("i", { className: "ph ph-check", "aria-hidden": "true" }) : null
11685
11748
  ] }),
11686
- /* @__PURE__ */ jsxs77("button", { type: "button", className: "fd-mode-opt" + (test ? " is-on" : ""), onClick: () => go("test"), children: [
11687
- /* @__PURE__ */ jsx89("i", { className: "ph ph-flask", "aria-hidden": "true" }),
11688
- /* @__PURE__ */ jsxs77("span", { className: "fd-mode-opt-text", children: [
11689
- /* @__PURE__ */ jsx89("span", { className: "fd-mode-opt-title", children: "Test mode" }),
11690
- /* @__PURE__ */ jsx89("span", { className: "fd-mode-opt-desc", children: "Everything usable, all data simulated" })
11749
+ /* @__PURE__ */ jsxs78("button", { type: "button", className: "fd-mode-opt" + (test ? " is-on" : ""), onClick: () => go("test"), children: [
11750
+ /* @__PURE__ */ jsx91("i", { className: "ph ph-flask", "aria-hidden": "true" }),
11751
+ /* @__PURE__ */ jsxs78("span", { className: "fd-mode-opt-text", children: [
11752
+ /* @__PURE__ */ jsx91("span", { className: "fd-mode-opt-title", children: "Test mode" }),
11753
+ /* @__PURE__ */ jsx91("span", { className: "fd-mode-opt-desc", children: "Everything usable, all data simulated" })
11691
11754
  ] }),
11692
- test ? /* @__PURE__ */ jsx89("i", { className: "ph ph-check", "aria-hidden": "true" }) : null
11755
+ test ? /* @__PURE__ */ jsx91("i", { className: "ph ph-check", "aria-hidden": "true" }) : null
11693
11756
  ] })
11694
11757
  ] }),
11695
- test && renderLog ? /* @__PURE__ */ jsx89("span", { style: { display: "block", maxHeight: 340, overflowY: "auto", borderTop: "1px solid var(--border)" }, children: renderLog() }) : null
11758
+ test && renderLog ? /* @__PURE__ */ jsx91("span", { style: { display: "block", maxHeight: 340, overflowY: "auto", borderTop: "1px solid var(--border)" }, children: renderLog() }) : null
11696
11759
  ] })
11697
11760
  ] });
11698
11761
  }
11699
11762
  function TestModeBar({ onExit }) {
11700
11763
  const mode2 = useRuntimeMode();
11701
11764
  if (mode2 !== "test") return null;
11702
- return /* @__PURE__ */ jsxs77("div", { className: "fd-testbar", role: "status", children: [
11703
- /* @__PURE__ */ jsxs77("span", { className: "fd-badge fd-badge-warning", children: [
11704
- /* @__PURE__ */ jsx89("i", { className: "ph ph-flask", "aria-hidden": "true" }),
11765
+ return /* @__PURE__ */ jsxs78("div", { className: "fd-testbar", role: "status", children: [
11766
+ /* @__PURE__ */ jsxs78("span", { className: "fd-badge fd-badge-warning", children: [
11767
+ /* @__PURE__ */ jsx91("i", { className: "ph ph-flask", "aria-hidden": "true" }),
11705
11768
  "Test mode"
11706
11769
  ] }),
11707
- /* @__PURE__ */ jsx89("span", { className: "fd-testbar-detail", children: "Every feature is unlocked and every response is simulated \u2014 nothing here persists." }),
11708
- /* @__PURE__ */ jsxs77("button", { type: "button", className: "fd-soon-link", onClick: () => onExit ? onExit() : RuntimeKit.setMode("live"), children: [
11709
- /* @__PURE__ */ jsx89("i", { className: "ph ph-lightning", "aria-hidden": "true" }),
11770
+ /* @__PURE__ */ jsx91("span", { className: "fd-testbar-detail", children: "Every feature is unlocked and every response is simulated \u2014 nothing here persists." }),
11771
+ /* @__PURE__ */ jsxs78("button", { type: "button", className: "fd-soon-link", onClick: () => onExit ? onExit() : RuntimeKit.setMode("live"), children: [
11772
+ /* @__PURE__ */ jsx91("i", { className: "ph ph-lightning", "aria-hidden": "true" }),
11710
11773
  " Back to live mode"
11711
11774
  ] })
11712
11775
  ] });
11713
11776
  }
11714
11777
 
11715
11778
  // src/components/planner/ChannelMeta.tsx
11716
- import { jsx as jsx90, jsxs as jsxs78 } from "react/jsx-runtime";
11779
+ import { jsx as jsx92, jsxs as jsxs79 } from "react/jsx-runtime";
11717
11780
  var CHANNEL_WEIGHTS = {
11718
11781
  "OOH": 50,
11719
11782
  "DOOH": 50,
@@ -11766,9 +11829,9 @@ function ChannelTag({ channel, size = "md", showLabel = true, dot = false, weigh
11766
11829
  const m = ChannelMeta(channel);
11767
11830
  const wt = channelWeightOf(channel || "");
11768
11831
  if (dot) {
11769
- return /* @__PURE__ */ jsx90("span", { className: ["fd-chan-dot", className].filter(Boolean).join(" "), title: m.name, style: { background: m.color }, ...rest });
11832
+ return /* @__PURE__ */ jsx92("span", { className: ["fd-chan-dot", className].filter(Boolean).join(" "), title: m.name, style: { background: m.color }, ...rest });
11770
11833
  }
11771
- return /* @__PURE__ */ jsxs78(
11834
+ return /* @__PURE__ */ jsxs79(
11772
11835
  "span",
11773
11836
  {
11774
11837
  className: ["fd-chan", size === "sm" ? "fd-chan-sm" : "", className].filter(Boolean).join(" "),
@@ -11776,16 +11839,16 @@ function ChannelTag({ channel, size = "md", showLabel = true, dot = false, weigh
11776
11839
  style: { "--chan": m.color },
11777
11840
  ...rest,
11778
11841
  children: [
11779
- /* @__PURE__ */ jsx90("i", { className: "ph ph-" + m.icon, "aria-hidden": "true" }),
11780
- showLabel ? /* @__PURE__ */ jsx90("span", { className: "fd-chan-label", children: m.label }) : null,
11781
- weight ? /* @__PURE__ */ jsx90("span", { className: "fd-chan-weight", children: wt || 0 }) : null
11842
+ /* @__PURE__ */ jsx92("i", { className: "ph ph-" + m.icon, "aria-hidden": "true" }),
11843
+ showLabel ? /* @__PURE__ */ jsx92("span", { className: "fd-chan-label", children: m.label }) : null,
11844
+ weight ? /* @__PURE__ */ jsx92("span", { className: "fd-chan-weight", children: wt || 0 }) : null
11782
11845
  ]
11783
11846
  }
11784
11847
  );
11785
11848
  }
11786
11849
 
11787
11850
  // src/components/planner/SaturationDistribution.tsx
11788
- import { jsx as jsx91, jsxs as jsxs79 } from "react/jsx-runtime";
11851
+ import { jsx as jsx93, jsxs as jsxs80 } from "react/jsx-runtime";
11789
11852
  var BANDS2 = [
11790
11853
  { key: "weak", label: "Weak", n: 1, range: "< 50" },
11791
11854
  { key: "adequate", label: "Adequate", n: 2, range: "50\u2013100" },
@@ -11796,24 +11859,24 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
11796
11859
  const grouped = BANDS2.map((b) => ({ ...b, items: campuses.filter((c) => c.band === b.key) }));
11797
11860
  const tallest = Math.max(1, ...grouped.map((g) => g.items.length));
11798
11861
  const floor = BANDS2.find((b) => b.key === floorBand) || BANDS2[0];
11799
- return /* @__PURE__ */ jsxs79("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 16 }, children: [
11800
- /* @__PURE__ */ jsx91("div", { style: { display: "grid", gridTemplateColumns: "repeat(4,minmax(0,1fr))", gap: 12, alignItems: "end" }, children: grouped.map((g) => {
11862
+ return /* @__PURE__ */ jsxs80("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 16 }, children: [
11863
+ /* @__PURE__ */ jsx93("div", { style: { display: "grid", gridTemplateColumns: "repeat(4,minmax(0,1fr))", gap: 12, alignItems: "end" }, children: grouped.map((g) => {
11801
11864
  const mark = "var(--csi-" + g.n + "-mark)";
11802
11865
  const active = selectedBand === g.key;
11803
- return /* @__PURE__ */ jsxs79(
11866
+ return /* @__PURE__ */ jsxs80(
11804
11867
  "button",
11805
11868
  {
11806
11869
  type: "button",
11807
11870
  onClick: onSelectBand ? () => onSelectBand(active ? null : g.key) : void 0,
11808
11871
  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)" },
11809
11872
  children: [
11810
- /* @__PURE__ */ jsx91("span", { style: { display: "flex", flexDirection: "column-reverse", gap: 4, minHeight: tallest * 24, minWidth: 0 }, children: loading ? Array.from({ length: 3 }).map((_, i) => /* @__PURE__ */ jsx91("span", { className: "fd-skel", style: { height: 16, borderRadius: 4 } }, i)) : g.items.map((c) => (
11873
+ /* @__PURE__ */ jsx93("span", { style: { display: "flex", flexDirection: "column-reverse", gap: 4, minHeight: tallest * 24, minWidth: 0 }, children: loading ? Array.from({ length: 3 }).map((_, i) => /* @__PURE__ */ jsx93("span", { className: "fd-skel", style: { height: 16, borderRadius: 4 } }, i)) : g.items.map((c) => (
11811
11874
  // `overflow: hidden` + `white-space: nowrap` only clips once the span
11812
11875
  // actually HAS a bounded width to clip against (see the grid/flex
11813
11876
  // `minWidth: 0` chain above) — `textOverflow: ellipsis` then makes
11814
11877
  // that clip readable instead of a hard cut mid-letter; the full name
11815
11878
  // is still one hover away via `title`.
11816
- /* @__PURE__ */ jsx91(
11879
+ /* @__PURE__ */ jsx93(
11817
11880
  "span",
11818
11881
  {
11819
11882
  title: c.name + " \xB7 " + c.crp,
@@ -11823,13 +11886,13 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
11823
11886
  c.name
11824
11887
  )
11825
11888
  )) }),
11826
- /* @__PURE__ */ jsxs79("span", { className: "fd-row", style: { gap: 8, alignItems: "baseline" }, children: [
11827
- /* @__PURE__ */ jsx91("span", { className: "fd-num-hero", style: { fontSize: 30, color: g.items.length ? "var(--text)" : "var(--text-disabled)" }, children: loading ? "\u2013" : g.items.length }),
11828
- /* @__PURE__ */ jsx91("span", { className: "fd-meter", style: { gap: 2, color: mark }, "aria-hidden": "true", children: [1, 2, 3, 4].map((i) => /* @__PURE__ */ jsx91("span", { className: "fd-meter-seg" + (i <= g.n ? " is-on" : ""), style: { width: 4, height: 9 } }, i)) })
11889
+ /* @__PURE__ */ jsxs80("span", { className: "fd-row", style: { gap: 8, alignItems: "baseline" }, children: [
11890
+ /* @__PURE__ */ jsx93("span", { className: "fd-num-hero", style: { fontSize: 30, color: g.items.length ? "var(--text)" : "var(--text-disabled)" }, children: loading ? "\u2013" : g.items.length }),
11891
+ /* @__PURE__ */ jsx93("span", { className: "fd-meter", style: { gap: 2, color: mark }, "aria-hidden": "true", children: [1, 2, 3, 4].map((i) => /* @__PURE__ */ jsx93("span", { className: "fd-meter-seg" + (i <= g.n ? " is-on" : ""), style: { width: 4, height: 9 } }, i)) })
11829
11892
  ] }),
11830
- /* @__PURE__ */ jsxs79("span", { className: "fd-stack", style: { gap: 1 }, children: [
11831
- /* @__PURE__ */ jsx91("span", { className: "fd-label-lg", children: g.label }),
11832
- /* @__PURE__ */ jsxs79("span", { className: "fd-body-sm fd-muted", style: { fontSize: 11.5 }, children: [
11893
+ /* @__PURE__ */ jsxs80("span", { className: "fd-stack", style: { gap: 1 }, children: [
11894
+ /* @__PURE__ */ jsx93("span", { className: "fd-label-lg", children: g.label }),
11895
+ /* @__PURE__ */ jsxs80("span", { className: "fd-body-sm fd-muted", style: { fontSize: 11.5 }, children: [
11833
11896
  "CRP ",
11834
11897
  g.range
11835
11898
  ] })
@@ -11839,10 +11902,10 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
11839
11902
  g.key
11840
11903
  );
11841
11904
  }) }),
11842
- floorBand ? /* @__PURE__ */ jsxs79("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: [
11843
- /* @__PURE__ */ jsx91("span", { className: "fd-meter", style: { gap: 2, color: "var(--csi-" + floor.n + "-mark)" }, "aria-hidden": "true", children: [1, 2, 3, 4].map((i) => /* @__PURE__ */ jsx91("span", { className: "fd-meter-seg" + (i <= floor.n ? " is-on" : ""), style: { width: 5, height: 12 } }, i)) }),
11844
- /* @__PURE__ */ jsxs79("span", { className: "fd-body-sm fd-secondary", style: { flex: 1, minWidth: 240 }, children: [
11845
- /* @__PURE__ */ jsxs79("strong", { style: { color: "var(--text)" }, children: [
11905
+ floorBand ? /* @__PURE__ */ jsxs80("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: [
11906
+ /* @__PURE__ */ jsx93("span", { className: "fd-meter", style: { gap: 2, color: "var(--csi-" + floor.n + "-mark)" }, "aria-hidden": "true", children: [1, 2, 3, 4].map((i) => /* @__PURE__ */ jsx93("span", { className: "fd-meter-seg" + (i <= floor.n ? " is-on" : ""), style: { width: 5, height: 12 } }, i)) }),
11907
+ /* @__PURE__ */ jsxs80("span", { className: "fd-body-sm fd-secondary", style: { flex: 1, minWidth: 240 }, children: [
11908
+ /* @__PURE__ */ jsxs80("strong", { style: { color: "var(--text)" }, children: [
11846
11909
  "Plan floor ",
11847
11910
  floorScore
11848
11911
  ] }),
@@ -11853,8 +11916,8 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
11853
11916
  }
11854
11917
 
11855
11918
  // src/components/planner/MixGap.tsx
11856
- import * as React66 from "react";
11857
- import { Fragment as Fragment26, jsx as jsx92, jsxs as jsxs80 } from "react/jsx-runtime";
11919
+ import * as React67 from "react";
11920
+ import { Fragment as Fragment26, jsx as jsx94, jsxs as jsxs81 } from "react/jsx-runtime";
11858
11921
  var MIX_GAP_LAYOUT = {
11859
11922
  trackHeight: 30,
11860
11923
  barHeight: 20,
@@ -11868,19 +11931,19 @@ function mixGapOffset(value, max) {
11868
11931
  }
11869
11932
  function MixGap({ rows = [], loading = false, className = "" }) {
11870
11933
  const max = Math.max(1, ...rows.flatMap((r) => [r.target, r.realized]));
11871
- const [hover, setHover] = React66.useState(null);
11934
+ const [hover, setHover] = React67.useState(null);
11872
11935
  const toneOf = (gap) => gap >= -1 ? "ok" : gap >= -4 ? "warn" : "danger";
11873
11936
  const TONE = { ok: "var(--ok-solid)", warn: "var(--warn-solid)", danger: "var(--danger-solid)" };
11874
11937
  const { trackHeight, barHeight, targetWidth, labelGap } = MIX_GAP_LAYOUT;
11875
11938
  const barTop = (trackHeight - barHeight) / 2;
11876
- return /* @__PURE__ */ jsxs80("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 4 }, children: [
11877
- /* @__PURE__ */ jsxs80("div", { className: "fd-row", style: { gap: 16, justifyContent: "flex-end", paddingBottom: 6, flexWrap: "wrap" }, children: [
11878
- [["On target", TONE.ok], ["Close", TONE.warn], ["Short", TONE.danger]].map(([l, c]) => /* @__PURE__ */ jsxs80("span", { className: "fd-row fd-body-sm fd-muted", style: { gap: 6 }, children: [
11879
- /* @__PURE__ */ jsx92("span", { style: { width: 14, height: 9, borderRadius: 2, background: c } }),
11939
+ return /* @__PURE__ */ jsxs81("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 4 }, children: [
11940
+ /* @__PURE__ */ jsxs81("div", { className: "fd-row", style: { gap: 16, justifyContent: "flex-end", paddingBottom: 6, flexWrap: "wrap" }, children: [
11941
+ [["On target", TONE.ok], ["Close", TONE.warn], ["Short", TONE.danger]].map(([l, c]) => /* @__PURE__ */ jsxs81("span", { className: "fd-row fd-body-sm fd-muted", style: { gap: 6 }, children: [
11942
+ /* @__PURE__ */ jsx94("span", { style: { width: 14, height: 9, borderRadius: 2, background: c } }),
11880
11943
  l
11881
11944
  ] }, l)),
11882
- /* @__PURE__ */ jsxs80("span", { className: "fd-row fd-body-sm fd-muted", style: { gap: 6 }, children: [
11883
- /* @__PURE__ */ jsx92("span", { "data-mixgap-legend-target": "", style: { width: targetWidth, height: 16, borderRadius: 1, background: MIX_GAP_TARGET_STRIPE } }),
11945
+ /* @__PURE__ */ jsxs81("span", { className: "fd-row fd-body-sm fd-muted", style: { gap: 6 }, children: [
11946
+ /* @__PURE__ */ jsx94("span", { "data-mixgap-legend-target": "", style: { width: targetWidth, height: 16, borderRadius: 1, background: MIX_GAP_TARGET_STRIPE } }),
11884
11947
  "Target"
11885
11948
  ] })
11886
11949
  ] }),
@@ -11889,7 +11952,7 @@ function MixGap({ rows = [], loading = false, className = "" }) {
11889
11952
  const tone = toneOf(gap);
11890
11953
  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 : "");
11891
11954
  const labelLeft = r.realized > r.target ? `calc(${mixGapOffset(r.realized, max)} + ${labelGap}px)` : `calc(${mixGapOffset(r.target, max)} + ${targetWidth / 2 + labelGap}px)`;
11892
- return /* @__PURE__ */ jsxs80(
11955
+ return /* @__PURE__ */ jsxs81(
11893
11956
  "div",
11894
11957
  {
11895
11958
  className: "fd-row",
@@ -11897,15 +11960,15 @@ function MixGap({ rows = [], loading = false, className = "" }) {
11897
11960
  onMouseEnter: () => setHover(r.channel),
11898
11961
  onMouseLeave: () => setHover(null),
11899
11962
  children: [
11900
- /* @__PURE__ */ jsx92("span", { style: { width: 128, flex: "none" }, children: /* @__PURE__ */ jsx92(ChannelTag, { channel: r.channel, size: "sm" }) }),
11901
- /* @__PURE__ */ jsx92("span", { style: { position: "relative", flex: 1, height: trackHeight, minWidth: 120 }, children: loading ? /* @__PURE__ */ jsx92("span", { className: "fd-skel", style: { position: "absolute", left: 0, right: 0, top: barTop, height: barHeight, borderRadius: 3 } }) : /* @__PURE__ */ jsxs80(Fragment26, { children: [
11902
- /* @__PURE__ */ jsx92("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)" } }),
11903
- /* @__PURE__ */ jsx92("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 } }),
11904
- /* @__PURE__ */ jsxs80("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: [
11963
+ /* @__PURE__ */ jsx94("span", { style: { width: 128, flex: "none" }, children: /* @__PURE__ */ jsx94(ChannelTag, { channel: r.channel, size: "sm" }) }),
11964
+ /* @__PURE__ */ jsx94("span", { style: { position: "relative", flex: 1, height: trackHeight, minWidth: 120 }, children: loading ? /* @__PURE__ */ jsx94("span", { className: "fd-skel", style: { position: "absolute", left: 0, right: 0, top: barTop, height: barHeight, borderRadius: 3 } }) : /* @__PURE__ */ jsxs81(Fragment26, { children: [
11965
+ /* @__PURE__ */ jsx94("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)" } }),
11966
+ /* @__PURE__ */ jsx94("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 } }),
11967
+ /* @__PURE__ */ jsxs81("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: [
11905
11968
  r.realized,
11906
11969
  "%"
11907
11970
  ] }),
11908
- hover === r.channel ? /* @__PURE__ */ jsx92("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
11971
+ hover === r.channel ? /* @__PURE__ */ jsx94("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
11909
11972
  ] }) })
11910
11973
  ]
11911
11974
  },
@@ -11916,7 +11979,7 @@ function MixGap({ rows = [], loading = false, className = "" }) {
11916
11979
  }
11917
11980
 
11918
11981
  // src/components/planner/ChannelContribution.tsx
11919
- import { jsx as jsx93, jsxs as jsxs81 } from "react/jsx-runtime";
11982
+ import { jsx as jsx95, jsxs as jsxs82 } from "react/jsx-runtime";
11920
11983
  var money = (n) => "$" + Math.round(n).toLocaleString();
11921
11984
  function ChannelContribution({
11922
11985
  channels = [],
@@ -11932,9 +11995,9 @@ function ChannelContribution({
11932
11995
  const grand = total !== void 0 ? total : base + bonus;
11933
11996
  const pct = (v) => grand ? v / grand * 100 : 0;
11934
11997
  const spendTotal = channels.reduce((s, c) => s + Number(String(c.spend || 0).replace(/[^0-9.]/g, "")), 0);
11935
- return /* @__PURE__ */ jsxs81("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 16 }, children: [
11936
- loading ? /* @__PURE__ */ jsx93("span", { className: "fd-skel", style: { height: 34, borderRadius: "var(--r-sm)" } }) : /* @__PURE__ */ jsxs81("div", { className: "fd-row", style: { height: 34, borderRadius: "var(--r-sm)", overflow: "hidden", gap: 2, background: "var(--surface-3)" }, children: [
11937
- channels.map((c) => /* @__PURE__ */ jsx93(
11998
+ return /* @__PURE__ */ jsxs82("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 16 }, children: [
11999
+ loading ? /* @__PURE__ */ jsx95("span", { className: "fd-skel", style: { height: 34, borderRadius: "var(--r-sm)" } }) : /* @__PURE__ */ jsxs82("div", { className: "fd-row", style: { height: 34, borderRadius: "var(--r-sm)", overflow: "hidden", gap: 2, background: "var(--surface-3)" }, children: [
12000
+ channels.map((c) => /* @__PURE__ */ jsx95(
11938
12001
  "span",
11939
12002
  {
11940
12003
  title: c.name + " \xB7 " + c.crp.toFixed(1) + " CRP",
@@ -11943,7 +12006,7 @@ function ChannelContribution({
11943
12006
  },
11944
12007
  c.name
11945
12008
  )),
11946
- bonus > 0 ? /* @__PURE__ */ jsx93(
12009
+ bonus > 0 ? /* @__PURE__ */ jsx95(
11947
12010
  "span",
11948
12011
  {
11949
12012
  title: "Surround-sound bonus +" + bonusPct + "%",
@@ -11952,18 +12015,18 @@ function ChannelContribution({
11952
12015
  }
11953
12016
  ) : null
11954
12017
  ] }),
11955
- showTable ? /* @__PURE__ */ jsxs81("table", { className: "fd-table", style: { fontSize: "var(--body-sm-size)" }, children: [
11956
- /* @__PURE__ */ jsx93("thead", { children: /* @__PURE__ */ jsxs81("tr", { children: [
11957
- /* @__PURE__ */ jsx93("th", { style: { width: "34%" }, children: "Channel" }),
11958
- /* @__PURE__ */ jsx93("th", { style: { width: "16%" }, children: "Weight" }),
11959
- /* @__PURE__ */ jsx93("th", { className: "is-num", style: { width: "16%" }, children: "Spend" }),
11960
- /* @__PURE__ */ jsx93("th", { className: "is-num", style: { width: "17%" }, children: "CRP" }),
11961
- /* @__PURE__ */ jsx93("th", { className: "is-num", style: { width: "17%" }, children: "Share" })
12018
+ showTable ? /* @__PURE__ */ jsxs82("table", { className: "fd-table", style: { fontSize: "var(--body-sm-size)" }, children: [
12019
+ /* @__PURE__ */ jsx95("thead", { children: /* @__PURE__ */ jsxs82("tr", { children: [
12020
+ /* @__PURE__ */ jsx95("th", { style: { width: "34%" }, children: "Channel" }),
12021
+ /* @__PURE__ */ jsx95("th", { style: { width: "16%" }, children: "Weight" }),
12022
+ /* @__PURE__ */ jsx95("th", { className: "is-num", style: { width: "16%" }, children: "Spend" }),
12023
+ /* @__PURE__ */ jsx95("th", { className: "is-num", style: { width: "17%" }, children: "CRP" }),
12024
+ /* @__PURE__ */ jsx95("th", { className: "is-num", style: { width: "17%" }, children: "Share" })
11962
12025
  ] }) }),
11963
- /* @__PURE__ */ jsxs81("tbody", { children: [
11964
- channels.map((c) => /* @__PURE__ */ jsxs81("tr", { children: [
11965
- /* @__PURE__ */ jsx93("td", { children: /* @__PURE__ */ jsx93(ChannelTag, { channel: c.name, size: "sm" }) }),
11966
- /* @__PURE__ */ jsx93("td", { children: /* @__PURE__ */ jsx93(
12026
+ /* @__PURE__ */ jsxs82("tbody", { children: [
12027
+ channels.map((c) => /* @__PURE__ */ jsxs82("tr", { children: [
12028
+ /* @__PURE__ */ jsx95("td", { children: /* @__PURE__ */ jsx95(ChannelTag, { channel: c.name, size: "sm" }) }),
12029
+ /* @__PURE__ */ jsx95("td", { children: /* @__PURE__ */ jsx95(
11967
12030
  "span",
11968
12031
  {
11969
12032
  className: "fd-badge fd-badge-neutral",
@@ -11972,38 +12035,38 @@ function ChannelContribution({
11972
12035
  children: "weight " + (channelWeightOf(c.name) || 0)
11973
12036
  }
11974
12037
  ) }),
11975
- /* @__PURE__ */ jsx93("td", { className: "is-num", children: c.spend }),
11976
- /* @__PURE__ */ jsx93("td", { className: "is-num", children: c.crp.toFixed(1) }),
11977
- /* @__PURE__ */ jsxs81("td", { className: "is-num", children: [
12038
+ /* @__PURE__ */ jsx95("td", { className: "is-num", children: c.spend }),
12039
+ /* @__PURE__ */ jsx95("td", { className: "is-num", children: c.crp.toFixed(1) }),
12040
+ /* @__PURE__ */ jsxs82("td", { className: "is-num", children: [
11978
12041
  pct(c.crp).toFixed(0),
11979
12042
  "%"
11980
12043
  ] })
11981
12044
  ] }, c.name)),
11982
- bonus > 0 ? /* @__PURE__ */ jsxs81("tr", { children: [
11983
- /* @__PURE__ */ jsx93("td", { children: /* @__PURE__ */ jsxs81("span", { className: "fd-row", style: { gap: 9, fontWeight: 600 }, children: [
11984
- /* @__PURE__ */ jsx93("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" } }),
12045
+ bonus > 0 ? /* @__PURE__ */ jsxs82("tr", { children: [
12046
+ /* @__PURE__ */ jsx95("td", { children: /* @__PURE__ */ jsxs82("span", { className: "fd-row", style: { gap: 9, fontWeight: 600 }, children: [
12047
+ /* @__PURE__ */ jsx95("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" } }),
11985
12048
  "Surround-sound bonus"
11986
12049
  ] }) }),
11987
- /* @__PURE__ */ jsx93("td", { children: /* @__PURE__ */ jsxs81("span", { className: "fd-badge fd-badge-success", style: { height: 20, fontSize: 11 }, children: [
12050
+ /* @__PURE__ */ jsx95("td", { children: /* @__PURE__ */ jsxs82("span", { className: "fd-badge fd-badge-success", style: { height: 20, fontSize: 11 }, children: [
11988
12051
  "+",
11989
12052
  bonusPct,
11990
12053
  "% of +",
11991
12054
  bonusMax,
11992
12055
  "%"
11993
12056
  ] }) }),
11994
- /* @__PURE__ */ jsx93("td", { className: "is-num fd-muted", children: "\u2014" }),
11995
- /* @__PURE__ */ jsx93("td", { className: "is-num", children: bonus.toFixed(1) }),
11996
- /* @__PURE__ */ jsxs81("td", { className: "is-num", children: [
12057
+ /* @__PURE__ */ jsx95("td", { className: "is-num fd-muted", children: "\u2014" }),
12058
+ /* @__PURE__ */ jsx95("td", { className: "is-num", children: bonus.toFixed(1) }),
12059
+ /* @__PURE__ */ jsxs82("td", { className: "is-num", children: [
11997
12060
  pct(bonus).toFixed(0),
11998
12061
  "%"
11999
12062
  ] })
12000
12063
  ] }) : null,
12001
- /* @__PURE__ */ jsxs81("tr", { style: { background: "var(--surface-2)" }, children: [
12002
- /* @__PURE__ */ jsx93("td", { style: { fontWeight: 700 }, children: "Campus total" }),
12003
- /* @__PURE__ */ jsx93("td", {}),
12004
- /* @__PURE__ */ jsx93("td", { className: "is-num", style: { fontWeight: 700 }, children: money(spendTotal) }),
12005
- /* @__PURE__ */ jsx93("td", { className: "is-num", style: { fontWeight: 700 }, children: grand.toFixed(1) }),
12006
- /* @__PURE__ */ jsx93("td", { className: "is-num", style: { fontWeight: 700 }, children: "100%" })
12064
+ /* @__PURE__ */ jsxs82("tr", { style: { background: "var(--surface-2)" }, children: [
12065
+ /* @__PURE__ */ jsx95("td", { style: { fontWeight: 700 }, children: "Campus total" }),
12066
+ /* @__PURE__ */ jsx95("td", {}),
12067
+ /* @__PURE__ */ jsx95("td", { className: "is-num", style: { fontWeight: 700 }, children: money(spendTotal) }),
12068
+ /* @__PURE__ */ jsx95("td", { className: "is-num", style: { fontWeight: 700 }, children: grand.toFixed(1) }),
12069
+ /* @__PURE__ */ jsx95("td", { className: "is-num", style: { fontWeight: 700 }, children: "100%" })
12007
12070
  ] })
12008
12071
  ] })
12009
12072
  ] }) : null
@@ -12011,8 +12074,8 @@ function ChannelContribution({
12011
12074
  }
12012
12075
 
12013
12076
  // src/components/planner/BudgetReallocator.tsx
12014
- import * as React67 from "react";
12015
- import { Fragment as Fragment27, jsx as jsx94, jsxs as jsxs82 } from "react/jsx-runtime";
12077
+ import * as React68 from "react";
12078
+ import { Fragment as Fragment27, jsx as jsx96, jsxs as jsxs83 } from "react/jsx-runtime";
12016
12079
  var bandFor = (crp) => crp >= 200 ? "dominant" : crp >= 100 ? "strong" : crp >= 50 ? "adequate" : "weak";
12017
12080
  function BudgetReallocator({
12018
12081
  campus,
@@ -12027,8 +12090,8 @@ function BudgetReallocator({
12027
12090
  onCancel,
12028
12091
  className = ""
12029
12092
  }) {
12030
- const [draft, setDraft] = React67.useState(spend);
12031
- React67.useEffect(() => setDraft(spend), [spend]);
12093
+ const [draft, setDraft] = React68.useState(spend);
12094
+ React68.useEffect(() => setDraft(spend), [spend]);
12032
12095
  const dirty = draft !== spend;
12033
12096
  const nextCrp = scoreFor ? scoreFor(draft) : crp;
12034
12097
  const nextBand = bandFor(nextCrp);
@@ -12043,10 +12106,10 @@ function BudgetReallocator({
12043
12106
  setDraft(spend);
12044
12107
  if (onCancel) onCancel();
12045
12108
  };
12046
- const trackRef = React67.useRef(null);
12047
- const chipRef = React67.useRef(null);
12048
- const [chipLeft, setChipLeft] = React67.useState(null);
12049
- React67.useLayoutEffect(() => {
12109
+ const trackRef = React68.useRef(null);
12110
+ const chipRef = React68.useRef(null);
12111
+ const [chipLeft, setChipLeft] = React68.useState(null);
12112
+ React68.useLayoutEffect(() => {
12050
12113
  const track = trackRef.current;
12051
12114
  if (!dirty || !track) {
12052
12115
  setChipLeft(null);
@@ -12067,23 +12130,23 @@ function BudgetReallocator({
12067
12130
  ro.observe(track);
12068
12131
  return () => ro.disconnect();
12069
12132
  }, [dirty, pct]);
12070
- return /* @__PURE__ */ jsxs82(
12133
+ return /* @__PURE__ */ jsxs83(
12071
12134
  "div",
12072
12135
  {
12073
12136
  className: ["fd-stack", className].filter(Boolean).join(" "),
12074
12137
  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)" },
12075
12138
  children: [
12076
- /* @__PURE__ */ jsxs82("div", { className: "fd-row", style: { gap: 12, flexWrap: "wrap" }, children: [
12077
- /* @__PURE__ */ jsx94("span", { className: "fd-h4", style: { flex: 1, minWidth: 140 }, children: campus }),
12078
- /* @__PURE__ */ jsx94(CsiBadge, { band: nowBand, crp, size: "medium" }),
12079
- dirty ? /* @__PURE__ */ jsxs82(Fragment27, { children: [
12080
- /* @__PURE__ */ jsx94("i", { className: "ph ph-arrow-right fd-muted", "aria-hidden": "true" }),
12081
- /* @__PURE__ */ jsx94(CsiBadge, { band: nextBand, crp: nextCrp, size: "medium", preview: true })
12139
+ /* @__PURE__ */ jsxs83("div", { className: "fd-row", style: { gap: 12, flexWrap: "wrap" }, children: [
12140
+ /* @__PURE__ */ jsx96("span", { className: "fd-h4", style: { flex: 1, minWidth: 140 }, children: campus }),
12141
+ /* @__PURE__ */ jsx96(CsiBadge, { band: nowBand, crp, size: "medium" }),
12142
+ dirty ? /* @__PURE__ */ jsxs83(Fragment27, { children: [
12143
+ /* @__PURE__ */ jsx96("i", { className: "ph ph-arrow-right fd-muted", "aria-hidden": "true" }),
12144
+ /* @__PURE__ */ jsx96(CsiBadge, { band: nextBand, crp: nextCrp, size: "medium", preview: true })
12082
12145
  ] }) : null
12083
12146
  ] }),
12084
- /* @__PURE__ */ jsxs82("div", { className: "fd-slider", ref: trackRef, children: [
12085
- /* @__PURE__ */ jsx94("span", { className: "fd-slider-fill", style: { width: pct + "%" } }),
12086
- dirty ? /* @__PURE__ */ jsx94(
12147
+ /* @__PURE__ */ jsxs83("div", { className: "fd-slider", ref: trackRef, children: [
12148
+ /* @__PURE__ */ jsx96("span", { className: "fd-slider-fill", style: { width: pct + "%" } }),
12149
+ dirty ? /* @__PURE__ */ jsx96(
12087
12150
  "span",
12088
12151
  {
12089
12152
  ref: chipRef,
@@ -12095,7 +12158,7 @@ function BudgetReallocator({
12095
12158
  children: (delta < 0 ? "\u2212$" : "+$") + Math.abs(delta).toLocaleString()
12096
12159
  }
12097
12160
  ) : null,
12098
- /* @__PURE__ */ jsx94(
12161
+ /* @__PURE__ */ jsx96(
12099
12162
  "input",
12100
12163
  {
12101
12164
  type: "range",
@@ -12111,13 +12174,13 @@ function BudgetReallocator({
12111
12174
  }
12112
12175
  )
12113
12176
  ] }),
12114
- /* @__PURE__ */ jsxs82("div", { className: "fd-row", style: { gap: 12, flexWrap: "wrap" }, children: [
12115
- /* @__PURE__ */ jsxs82("span", { className: "fd-stack", style: { gap: 2, flex: 1, minWidth: 150 }, children: [
12116
- /* @__PURE__ */ jsx94("span", { className: "fd-num", style: { fontSize: 19, fontWeight: 700 }, children: "$" + draft.toLocaleString() }),
12117
- /* @__PURE__ */ jsx94("span", { className: "fd-body-sm fd-muted", children: "Arrow keys step $100, shift+arrow $1,000. Escape reverts." })
12177
+ /* @__PURE__ */ jsxs83("div", { className: "fd-row", style: { gap: 12, flexWrap: "wrap" }, children: [
12178
+ /* @__PURE__ */ jsxs83("span", { className: "fd-stack", style: { gap: 2, flex: 1, minWidth: 150 }, children: [
12179
+ /* @__PURE__ */ jsx96("span", { className: "fd-num", style: { fontSize: 19, fontWeight: 700 }, children: "$" + draft.toLocaleString() }),
12180
+ /* @__PURE__ */ jsx96("span", { className: "fd-body-sm fd-muted", children: "Arrow keys step $100, shift+arrow $1,000. Escape reverts." })
12118
12181
  ] }),
12119
- /* @__PURE__ */ jsx94("button", { type: "button", className: "fd-btn fd-btn-ghost", disabled: !dirty, onClick: revert, children: "Cancel" }),
12120
- /* @__PURE__ */ jsx94(
12182
+ /* @__PURE__ */ jsx96("button", { type: "button", className: "fd-btn fd-btn-ghost", disabled: !dirty, onClick: revert, children: "Cancel" }),
12183
+ /* @__PURE__ */ jsx96(
12121
12184
  "button",
12122
12185
  {
12123
12186
  type: "button",
@@ -12136,7 +12199,7 @@ function BudgetReallocator({
12136
12199
  }
12137
12200
 
12138
12201
  // src/components/planner/SurroundSound.tsx
12139
- import { jsx as jsx95, jsxs as jsxs83 } from "react/jsx-runtime";
12202
+ import { jsx as jsx97, jsxs as jsxs84 } from "react/jsx-runtime";
12140
12203
  var CATEGORIES = [
12141
12204
  { key: "ooh", label: "OOH", icon: "flag-banner", color: "var(--ch-ooh)" },
12142
12205
  { key: "transit", label: "Transit", icon: "bus", color: "var(--ch-transit)" },
@@ -12148,26 +12211,26 @@ var CATEGORIES = [
12148
12211
  function SurroundSound({ present = [], bonusPct = 0, bonusMax = 40, missedCost, className = "" }) {
12149
12212
  const earned = Math.max(0, Math.min(1, bonusPct / bonusMax));
12150
12213
  const single = present.length <= 2;
12151
- return /* @__PURE__ */ jsxs83("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 14 }, children: [
12152
- /* @__PURE__ */ jsx95("div", { className: "fd-row", style: { gap: 8, flexWrap: "wrap" }, children: CATEGORIES.map((c) => {
12214
+ return /* @__PURE__ */ jsxs84("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 14 }, children: [
12215
+ /* @__PURE__ */ jsx97("div", { className: "fd-row", style: { gap: 8, flexWrap: "wrap" }, children: CATEGORIES.map((c) => {
12153
12216
  const on = present.includes(c.key);
12154
- return /* @__PURE__ */ jsxs83(
12217
+ return /* @__PURE__ */ jsxs84(
12155
12218
  "span",
12156
12219
  {
12157
12220
  title: c.label + (on ? " \u2014 present" : " \u2014 not bought"),
12158
12221
  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)" },
12159
12222
  children: [
12160
- /* @__PURE__ */ jsx95("i", { className: "ph ph-" + c.icon, style: { fontSize: 19, color: on ? c.color : "var(--text-muted)" }, "aria-hidden": "true" }),
12161
- /* @__PURE__ */ jsx95("span", { style: { fontSize: 10.5, fontWeight: 700 }, children: c.label })
12223
+ /* @__PURE__ */ jsx97("i", { className: "ph ph-" + c.icon, style: { fontSize: 19, color: on ? c.color : "var(--text-muted)" }, "aria-hidden": "true" }),
12224
+ /* @__PURE__ */ jsx97("span", { style: { fontSize: 10.5, fontWeight: 700 }, children: c.label })
12162
12225
  ]
12163
12226
  },
12164
12227
  c.key
12165
12228
  );
12166
12229
  }) }),
12167
- /* @__PURE__ */ jsxs83("div", { className: "fd-stack", style: { gap: 8 }, children: [
12168
- /* @__PURE__ */ jsxs83("div", { className: "fd-row", style: { justifyContent: "space-between", gap: 12 }, children: [
12169
- /* @__PURE__ */ jsx95("span", { className: "fd-label-lg", children: "Surround-sound bonus earned" }),
12170
- /* @__PURE__ */ jsxs83("span", { className: "fd-num", style: { color: single ? "var(--warn-text)" : "var(--csi-3-mark)", fontWeight: 700 }, children: [
12230
+ /* @__PURE__ */ jsxs84("div", { className: "fd-stack", style: { gap: 8 }, children: [
12231
+ /* @__PURE__ */ jsxs84("div", { className: "fd-row", style: { justifyContent: "space-between", gap: 12 }, children: [
12232
+ /* @__PURE__ */ jsx97("span", { className: "fd-label-lg", children: "Surround-sound bonus earned" }),
12233
+ /* @__PURE__ */ jsxs84("span", { className: "fd-num", style: { color: single ? "var(--warn-text)" : "var(--csi-3-mark)", fontWeight: 700 }, children: [
12171
12234
  "+",
12172
12235
  bonusPct,
12173
12236
  "% of +",
@@ -12175,8 +12238,8 @@ function SurroundSound({ present = [], bonusPct = 0, bonusMax = 40, missedCost,
12175
12238
  "%"
12176
12239
  ] })
12177
12240
  ] }),
12178
- /* @__PURE__ */ jsx95("div", { style: { height: 8, borderRadius: "var(--r-xs)", background: "var(--surface-3)", overflow: "hidden" }, children: /* @__PURE__ */ jsx95("div", { style: { height: "100%", width: earned * 100 + "%", background: "var(--csi-3-mark)", borderRadius: "inherit", transition: "width var(--dur-slow) var(--ease)" } }) }),
12179
- /* @__PURE__ */ jsxs83("span", { className: "fd-body-sm fd-secondary", style: { textWrap: "pretty" }, children: [
12241
+ /* @__PURE__ */ jsx97("div", { style: { height: 8, borderRadius: "var(--r-xs)", background: "var(--surface-3)", overflow: "hidden" }, children: /* @__PURE__ */ jsx97("div", { style: { height: "100%", width: earned * 100 + "%", background: "var(--csi-3-mark)", borderRadius: "inherit", transition: "width var(--dur-slow) var(--ease)" } }) }),
12242
+ /* @__PURE__ */ jsxs84("span", { className: "fd-body-sm fd-secondary", style: { textWrap: "pretty" }, children: [
12180
12243
  present.length,
12181
12244
  " of 6 channel categories present.",
12182
12245
  " ",
@@ -12188,7 +12251,7 @@ function SurroundSound({ present = [], bonusPct = 0, bonusMax = 40, missedCost,
12188
12251
  }
12189
12252
 
12190
12253
  // src/components/planner/Importance.tsx
12191
- import { jsx as jsx96, jsxs as jsxs84 } from "react/jsx-runtime";
12254
+ import { jsx as jsx98, jsxs as jsxs85 } from "react/jsx-runtime";
12192
12255
  var IMPORTANCE_LEVELS = [
12193
12256
  { id: "nudge", rank: 1, label: "Nudge", icon: "feather", description: "Breaks a tie, nothing more." },
12194
12257
  { id: "lean", rank: 2, label: "Lean", icon: "arrow-bend-up-right", description: "A mild preference between otherwise equal options." },
@@ -12218,7 +12281,7 @@ function importanceTokens(id) {
12218
12281
  function ImportanceTag({ level, showLabel = true, size = "sm", className = "", disabled = false }) {
12219
12282
  const lvl = importanceLevel(level);
12220
12283
  const t = importanceTokens(level);
12221
- return /* @__PURE__ */ jsxs84(
12284
+ return /* @__PURE__ */ jsxs85(
12222
12285
  "span",
12223
12286
  {
12224
12287
  className: ["fd-imp-tag", size === "md" ? "is-md" : "", disabled ? "is-disabled" : "", className].filter(Boolean).join(" "),
@@ -12226,16 +12289,16 @@ function ImportanceTag({ level, showLabel = true, size = "sm", className = "", d
12226
12289
  title: lvl.label + " \u2014 " + lvl.description,
12227
12290
  "aria-disabled": disabled ? "true" : void 0,
12228
12291
  children: [
12229
- /* @__PURE__ */ jsx96("i", { className: "ph ph-" + lvl.icon, "aria-hidden": "true" }),
12230
- showLabel ? lvl.label : /* @__PURE__ */ jsx96("span", { className: "fd-sr", children: lvl.label })
12292
+ /* @__PURE__ */ jsx98("i", { className: "ph ph-" + lvl.icon, "aria-hidden": "true" }),
12293
+ showLabel ? lvl.label : /* @__PURE__ */ jsx98("span", { className: "fd-sr", children: lvl.label })
12231
12294
  ]
12232
12295
  }
12233
12296
  );
12234
12297
  }
12235
12298
 
12236
12299
  // src/components/planner/PreferenceMeter.tsx
12237
- import * as React68 from "react";
12238
- import { jsx as jsx97, jsxs as jsxs85 } from "react/jsx-runtime";
12300
+ import * as React69 from "react";
12301
+ import { jsx as jsx99, jsxs as jsxs86 } from "react/jsx-runtime";
12239
12302
  function preferenceScore(criteria) {
12240
12303
  const earned = criteria.reduce((n, c) => n + (Number(c.earned) || 0), 0);
12241
12304
  const weight = criteria.reduce((n, c) => n + (Number(c.weight) || 0), 0);
@@ -12264,8 +12327,8 @@ function PreferenceMeter({
12264
12327
  className = ""
12265
12328
  }) {
12266
12329
  const value = score == null ? preferenceScore(criteria) : score;
12267
- const segments = React68.useMemo(() => preferenceSegments(criteria), [criteria]);
12268
- return /* @__PURE__ */ jsx97(
12330
+ const segments = React69.useMemo(() => preferenceSegments(criteria), [criteria]);
12331
+ return /* @__PURE__ */ jsx99(
12269
12332
  ScoreMeter,
12270
12333
  {
12271
12334
  score: value,
@@ -12277,22 +12340,22 @@ function PreferenceMeter({
12277
12340
  placement,
12278
12341
  className,
12279
12342
  breakdownLabel: breakdownTitle,
12280
- breakdown: /* @__PURE__ */ jsxs85("div", { className: "fd-prefbreak", children: [
12281
- /* @__PURE__ */ jsxs85("div", { className: "fd-prefbreak-head", children: [
12282
- /* @__PURE__ */ jsx97("span", { className: "fd-label-lg", children: breakdownTitle }),
12283
- /* @__PURE__ */ jsx97("span", { className: "fd-prefbreak-score fd-tabular", children: Math.round(value) })
12343
+ breakdown: /* @__PURE__ */ jsxs86("div", { className: "fd-prefbreak", children: [
12344
+ /* @__PURE__ */ jsxs86("div", { className: "fd-prefbreak-head", children: [
12345
+ /* @__PURE__ */ jsx99("span", { className: "fd-label-lg", children: breakdownTitle }),
12346
+ /* @__PURE__ */ jsx99("span", { className: "fd-prefbreak-score fd-tabular", children: Math.round(value) })
12284
12347
  ] }),
12285
- /* @__PURE__ */ jsx97("ul", { className: "fd-prefbreak-list", children: criteria.map((c) => {
12348
+ /* @__PURE__ */ jsx99("ul", { className: "fd-prefbreak-list", children: criteria.map((c) => {
12286
12349
  const pct = c.weight > 0 ? Math.round((Number(c.earned) || 0) / c.weight * 100) : 0;
12287
- return /* @__PURE__ */ jsxs85("li", { className: pct === 0 ? "fd-prefbreak-item is-unmet" : "fd-prefbreak-item", children: [
12288
- /* @__PURE__ */ jsx97(ImportanceTag, { level: c.importance }),
12289
- /* @__PURE__ */ jsxs85("span", { className: "fd-prefbreak-text", children: [
12290
- /* @__PURE__ */ jsx97("span", { className: "fd-prefbreak-label", children: c.label }),
12291
- c.note ? /* @__PURE__ */ jsx97("span", { className: "fd-prefbreak-note", children: c.note }) : null
12350
+ return /* @__PURE__ */ jsxs86("li", { className: pct === 0 ? "fd-prefbreak-item is-unmet" : "fd-prefbreak-item", children: [
12351
+ /* @__PURE__ */ jsx99(ImportanceTag, { level: c.importance }),
12352
+ /* @__PURE__ */ jsxs86("span", { className: "fd-prefbreak-text", children: [
12353
+ /* @__PURE__ */ jsx99("span", { className: "fd-prefbreak-label", children: c.label }),
12354
+ c.note ? /* @__PURE__ */ jsx99("span", { className: "fd-prefbreak-note", children: c.note }) : null
12292
12355
  ] }),
12293
- /* @__PURE__ */ jsxs85("span", { className: "fd-prefbreak-val fd-tabular", children: [
12356
+ /* @__PURE__ */ jsxs86("span", { className: "fd-prefbreak-val fd-tabular", children: [
12294
12357
  Math.round(Number(c.earned) || 0),
12295
- /* @__PURE__ */ jsx97("span", { className: "fd-prefbreak-sep", children: "/" }),
12358
+ /* @__PURE__ */ jsx99("span", { className: "fd-prefbreak-sep", children: "/" }),
12296
12359
  Math.round(c.weight)
12297
12360
  ] })
12298
12361
  ] }, c.id);
@@ -12303,10 +12366,10 @@ function PreferenceMeter({
12303
12366
  }
12304
12367
 
12305
12368
  // src/components/chat/AgentChatPanel.tsx
12306
- import * as React74 from "react";
12369
+ import * as React75 from "react";
12307
12370
 
12308
12371
  // src/components/chat/chatEngine.ts
12309
- import * as React69 from "react";
12372
+ import * as React70 from "react";
12310
12373
  var CHAT_UNAVAILABLE = "chat_unavailable";
12311
12374
  var JOB_PENDING = ["queued", "running"];
12312
12375
  var JOB_SUCCESS = ["completed", "recovered"];
@@ -12351,7 +12414,7 @@ function useChatEngine(opts) {
12351
12414
  initialMessage,
12352
12415
  threadId: threadIdProp,
12353
12416
  pollIntervalMs = 1500,
12354
- pollMaxAttempts = 120,
12417
+ pendingTimeoutMs = 18e4,
12355
12418
  store = safeStore,
12356
12419
  onPacket,
12357
12420
  onThreadReady,
@@ -12360,22 +12423,22 @@ function useChatEngine(opts) {
12360
12423
  onClear,
12361
12424
  onFeedback
12362
12425
  } = opts || {};
12363
- const [status, setStatus] = React69.useState("idle");
12364
- const [threadId, setThreadId] = React69.useState(null);
12365
- const [messages, setMessages] = React69.useState([]);
12366
- const [queue, setQueue] = React69.useState([]);
12367
- const [fatal, setFatal] = React69.useState(null);
12368
- const [busy, setBusy] = React69.useState(false);
12369
- const [turnStartedAt, setTurnStartedAt] = React69.useState(null);
12370
- const listRef = React69.useRef([]);
12371
- const queueRef = React69.useRef([]);
12372
- const busyRef = React69.useRef(false);
12373
- const stoppedRef = React69.useRef(false);
12374
- const abortRef = React69.useRef(null);
12375
- const serverCount = React69.useRef(0);
12376
- const threadRef = React69.useRef(null);
12377
- const mounted = React69.useRef(true);
12378
- React69.useEffect(() => {
12426
+ const [status, setStatus] = React70.useState("idle");
12427
+ const [threadId, setThreadId] = React70.useState(null);
12428
+ const [messages, setMessages] = React70.useState([]);
12429
+ const [queue, setQueue] = React70.useState([]);
12430
+ const [fatal, setFatal] = React70.useState(null);
12431
+ const [busy, setBusy] = React70.useState(false);
12432
+ const [turnStartedAt, setTurnStartedAt] = React70.useState(null);
12433
+ const listRef = React70.useRef([]);
12434
+ const queueRef = React70.useRef([]);
12435
+ const busyRef = React70.useRef(false);
12436
+ const stoppedRef = React70.useRef(false);
12437
+ const abortRef = React70.useRef(null);
12438
+ const serverCount = React70.useRef(0);
12439
+ const threadRef = React70.useRef(null);
12440
+ const mounted = React70.useRef(true);
12441
+ React70.useEffect(() => {
12379
12442
  mounted.current = true;
12380
12443
  return () => {
12381
12444
  mounted.current = false;
@@ -12397,14 +12460,21 @@ function useChatEngine(opts) {
12397
12460
  }
12398
12461
  return false;
12399
12462
  };
12400
- const loadThread = React69.useCallback(async (id) => {
12463
+ const loadThread = React70.useCallback(async (id) => {
12401
12464
  const data = await apiAdapter.getThread(id);
12402
12465
  const list = [...data && data.messages || []];
12403
12466
  serverCount.current = list.length;
12404
12467
  commit(list);
12405
12468
  return list;
12406
12469
  }, [apiAdapter]);
12407
- React69.useEffect(() => {
12470
+ async function mergeThread() {
12471
+ const data = await apiAdapter.getThread(threadRef.current);
12472
+ const server = data && data.messages || [];
12473
+ const ids = new Set(server.map((m) => m.id));
12474
+ serverCount.current = server.length;
12475
+ commit([...server, ...listRef.current.filter((m) => !ids.has(m.id))]);
12476
+ }
12477
+ React70.useEffect(() => {
12408
12478
  if (!apiAdapter) {
12409
12479
  setStatus("idle");
12410
12480
  setFatal(null);
@@ -12450,7 +12520,9 @@ function useChatEngine(opts) {
12450
12520
  setStatus("ready");
12451
12521
  onThreadReady && onThreadReady(id);
12452
12522
  const stored = store.get(STORAGE_PREFIX + id);
12523
+ const last = [...visibleMessages(listRef.current)].reverse().find((m) => m.role === "assistant");
12453
12524
  if (stored) resumeJob(stored);
12525
+ else if (last && last.working && last.jobId) resumeJob(last.jobId, last.id);
12454
12526
  else if (initialMessage) send(initialMessage);
12455
12527
  } catch (err) {
12456
12528
  if (dead) return;
@@ -12466,8 +12538,8 @@ function useChatEngine(opts) {
12466
12538
  }, [apiAdapter, contextType, contextId, threadIdProp]);
12467
12539
  async function pollJob(jobId, placeholderId) {
12468
12540
  store.set(STORAGE_PREFIX + threadRef.current, jobId);
12469
- let attempts = 0;
12470
- while (attempts++ < pollMaxAttempts) {
12541
+ const deadline = Date.now() + pendingTimeoutMs;
12542
+ while (true) {
12471
12543
  if (stoppedRef.current) break;
12472
12544
  await sleep(pollIntervalMs);
12473
12545
  if (!mounted.current) return;
@@ -12485,7 +12557,15 @@ function useChatEngine(opts) {
12485
12557
  }
12486
12558
  patch(placeholderId, { job });
12487
12559
  const bucket2 = jobBucket(job && job.status);
12488
- if (bucket2 === "pending") continue;
12560
+ if (bucket2 === "pending") {
12561
+ try {
12562
+ await mergeThread();
12563
+ } catch (err) {
12564
+ fail(err);
12565
+ }
12566
+ if (Date.now() >= deadline) break;
12567
+ continue;
12568
+ }
12489
12569
  if (bucket2 === "success") {
12490
12570
  finishJob(jobId, job);
12491
12571
  return;
@@ -12522,9 +12602,10 @@ function useChatEngine(opts) {
12522
12602
  patch(placeholderId, { working: false, streaming: false, error: code, retryable: !!retryable, job: job || void 0 });
12523
12603
  onError && onError(new Error(code));
12524
12604
  }
12525
- function resumeJob(jobId) {
12526
- const id = uid("a");
12527
- push({ id, role: "assistant", working: true, jobId, resumed: true });
12605
+ function resumeJob(jobId, existingId) {
12606
+ const id = existingId || uid("a");
12607
+ if (existingId) patch(id, { working: true, resumed: true });
12608
+ else push({ id, role: "assistant", working: true, jobId, resumed: true });
12528
12609
  setBusy(true);
12529
12610
  busyRef.current = true;
12530
12611
  setTurnStartedAt(Date.now());
@@ -12617,7 +12698,7 @@ function useChatEngine(opts) {
12617
12698
  await dispatchTurn(turn);
12618
12699
  }
12619
12700
  }
12620
- const send = React69.useCallback((text, attachments) => {
12701
+ const send = React70.useCallback((text, attachments) => {
12621
12702
  const body = (text || "").trim();
12622
12703
  if (!body && !(attachments && attachments.length)) return;
12623
12704
  if (status === "disconnected") return;
@@ -12627,7 +12708,7 @@ function useChatEngine(opts) {
12627
12708
  stoppedRef.current = false;
12628
12709
  drain();
12629
12710
  }, [status]);
12630
- const stop = React69.useCallback(() => {
12711
+ const stop = React70.useCallback(() => {
12631
12712
  stoppedRef.current = true;
12632
12713
  const ac = abortRef.current;
12633
12714
  if (ac) {
@@ -12646,11 +12727,11 @@ function useChatEngine(opts) {
12646
12727
  store.del(STORAGE_PREFIX + threadRef.current);
12647
12728
  }
12648
12729
  }, [apiAdapter]);
12649
- const removeQueued = React69.useCallback((id) => {
12730
+ const removeQueued = React70.useCallback((id) => {
12650
12731
  queueRef.current = queueRef.current.filter((t) => t.id !== id);
12651
12732
  setQueue(queueRef.current.slice());
12652
12733
  }, []);
12653
- const retry = React69.useCallback(() => {
12734
+ const retry = React70.useCallback(() => {
12654
12735
  const list = listRef.current;
12655
12736
  let at = -1;
12656
12737
  for (let i = list.length - 1; i >= 0; i--) if (list[i].role === "user") {
@@ -12666,19 +12747,19 @@ function useChatEngine(opts) {
12666
12747
  setQueue(queueRef.current.slice());
12667
12748
  drain();
12668
12749
  }, []);
12669
- const clear = React69.useCallback(() => {
12750
+ const clear = React70.useCallback(() => {
12670
12751
  commit([]);
12671
12752
  serverCount.current = 0;
12672
12753
  queueRef.current = [];
12673
12754
  setQueue([]);
12674
12755
  onClear && onClear();
12675
12756
  }, [onClear]);
12676
- const setFeedback = React69.useCallback((id, value) => {
12757
+ const setFeedback = React70.useCallback((id, value) => {
12677
12758
  patch(id, (m) => ({ feedback: m.feedback === value ? null : value }));
12678
12759
  const msg = listRef.current.find((m) => m.id === id);
12679
12760
  onFeedback && onFeedback({ message: msg, feedback: msg ? msg.feedback : value });
12680
12761
  }, [onFeedback]);
12681
- const reload = React69.useCallback(async () => {
12762
+ const reload = React70.useCallback(async () => {
12682
12763
  if (!threadRef.current) return;
12683
12764
  setStatus("loading");
12684
12765
  try {
@@ -12716,11 +12797,11 @@ var ChatKit = {
12716
12797
  };
12717
12798
 
12718
12799
  // src/components/chat/ChatTranscript.tsx
12719
- import * as React71 from "react";
12800
+ import * as React72 from "react";
12720
12801
 
12721
12802
  // src/components/chat/ChatTurn.tsx
12722
- import * as React70 from "react";
12723
- import { jsx as jsx98, jsxs as jsxs86 } from "react/jsx-runtime";
12803
+ import * as React71 from "react";
12804
+ import { jsx as jsx100, jsxs as jsxs87 } from "react/jsx-runtime";
12724
12805
  function JsonView({ value }) {
12725
12806
  let text;
12726
12807
  try {
@@ -12728,67 +12809,67 @@ function JsonView({ value }) {
12728
12809
  } catch (e) {
12729
12810
  text = String(value);
12730
12811
  }
12731
- return /* @__PURE__ */ jsx98(CodeBlock, { code: text, language: "json", collapseAfter: 18 });
12812
+ return /* @__PURE__ */ jsx100(CodeBlock, { code: text, language: "json", collapseAfter: 18 });
12732
12813
  }
12733
12814
  function PacketCard({ packet, schema, render, onApply, applied }) {
12734
12815
  if (!packet) return null;
12735
12816
  const s = schema || {};
12736
12817
  const invalid = packet.valid === false;
12737
12818
  const title = s.heading || packet.type;
12738
- return /* @__PURE__ */ jsxs86("section", { className: "fdc-packet" + (invalid ? " is-invalid" : ""), "aria-label": title, children: [
12739
- /* @__PURE__ */ jsxs86("header", { className: "fdc-packet-head", children: [
12740
- /* @__PURE__ */ jsx98("i", { className: "ph ph-" + (s.icon || "package"), "aria-hidden": "true" }),
12741
- /* @__PURE__ */ jsx98("span", { className: "fdc-packet-title", title: truncationTitle(title), children: title }),
12742
- packet.repaired ? /* @__PURE__ */ jsx98("span", { className: "fdc-packet-badge", children: "Repaired" }) : null,
12743
- invalid ? /* @__PURE__ */ jsx98("span", { className: "fdc-packet-badge is-danger", children: "Invalid" }) : null
12819
+ return /* @__PURE__ */ jsxs87("section", { className: "fdc-packet" + (invalid ? " is-invalid" : ""), "aria-label": title, children: [
12820
+ /* @__PURE__ */ jsxs87("header", { className: "fdc-packet-head", children: [
12821
+ /* @__PURE__ */ jsx100("i", { className: "ph ph-" + (s.icon || "package"), "aria-hidden": "true" }),
12822
+ /* @__PURE__ */ jsx100("span", { className: "fdc-packet-title", title: truncationTitle(title), children: title }),
12823
+ packet.repaired ? /* @__PURE__ */ jsx100("span", { className: "fdc-packet-badge", children: "Repaired" }) : null,
12824
+ invalid ? /* @__PURE__ */ jsx100("span", { className: "fdc-packet-badge is-danger", children: "Invalid" }) : null
12744
12825
  ] }),
12745
- invalid ? /* @__PURE__ */ jsxs86("div", { className: "fdc-packet-alert", role: "alert", children: [
12746
- /* @__PURE__ */ jsx98("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
12747
- /* @__PURE__ */ jsx98("span", { children: packet.error || "This result failed validation and can\u2019t be applied." })
12748
- ] }) : /* @__PURE__ */ jsx98("div", { className: "fdc-packet-body", children: render ? render(packet) : /* @__PURE__ */ jsx98(JsonView, { value: packet.payload }) }),
12749
- !invalid && onApply ? /* @__PURE__ */ jsxs86("footer", { className: "fdc-packet-foot", children: [
12750
- packet.repaired ? /* @__PURE__ */ jsx98("span", { className: "fdc-packet-note", children: "Corrected by the backend after a first attempt." }) : /* @__PURE__ */ jsx98("span", {}),
12751
- /* @__PURE__ */ jsxs86("button", { type: "button", className: "fd-btn fd-btn-primary fd-btn-sm", disabled: applied, onClick: () => onApply(packet), children: [
12752
- /* @__PURE__ */ jsx98("i", { className: "ph ph-" + (applied ? "check" : "arrow-square-in"), "aria-hidden": "true" }),
12826
+ invalid ? /* @__PURE__ */ jsxs87("div", { className: "fdc-packet-alert", role: "alert", children: [
12827
+ /* @__PURE__ */ jsx100("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
12828
+ /* @__PURE__ */ jsx100("span", { children: packet.error || "This result failed validation and can\u2019t be applied." })
12829
+ ] }) : /* @__PURE__ */ jsx100("div", { className: "fdc-packet-body", children: render ? render(packet) : /* @__PURE__ */ jsx100(JsonView, { value: packet.payload }) }),
12830
+ !invalid && onApply && s.apply !== false ? /* @__PURE__ */ jsxs87("footer", { className: "fdc-packet-foot", children: [
12831
+ packet.repaired ? /* @__PURE__ */ jsx100("span", { className: "fdc-packet-note", children: "Corrected by the backend after a first attempt." }) : /* @__PURE__ */ jsx100("span", {}),
12832
+ /* @__PURE__ */ jsxs87("button", { type: "button", className: "fd-btn fd-btn-primary fd-btn-sm", disabled: applied, onClick: () => onApply(packet), children: [
12833
+ /* @__PURE__ */ jsx100("i", { className: "ph ph-" + (applied ? "check" : "arrow-square-in"), "aria-hidden": "true" }),
12753
12834
  applied ? "Applied" : s.applyLabel || "Apply"
12754
12835
  ] })
12755
12836
  ] }) : null
12756
12837
  ] });
12757
12838
  }
12758
12839
  function ThinkingBlock({ text, durationMs, streaming, defaultOpen = false }) {
12759
- const [open2, setOpen] = React70.useState(defaultOpen);
12840
+ const [open2, setOpen] = React71.useState(defaultOpen);
12760
12841
  if (!text) return null;
12761
- return /* @__PURE__ */ jsxs86("div", { className: "fdc-think" + (open2 ? " is-open" : ""), children: [
12762
- /* @__PURE__ */ jsxs86("button", { type: "button", className: "fdc-think-head", onClick: () => setOpen((v) => !v), "aria-expanded": open2, children: [
12763
- /* @__PURE__ */ jsx98("i", { className: "ph ph-brain", "aria-hidden": "true" }),
12764
- /* @__PURE__ */ jsx98("span", { children: streaming ? "Thinking" : durationMs ? "Thought for " + formatDuration(durationMs) : "Thought process" }),
12765
- streaming ? /* @__PURE__ */ jsxs86("span", { className: "fdc-dots", "aria-hidden": "true", children: [
12766
- /* @__PURE__ */ jsx98("span", {}),
12767
- /* @__PURE__ */ jsx98("span", {}),
12768
- /* @__PURE__ */ jsx98("span", {})
12842
+ return /* @__PURE__ */ jsxs87("div", { className: "fdc-think" + (open2 ? " is-open" : ""), children: [
12843
+ /* @__PURE__ */ jsxs87("button", { type: "button", className: "fdc-think-head", onClick: () => setOpen((v) => !v), "aria-expanded": open2, children: [
12844
+ /* @__PURE__ */ jsx100("i", { className: "ph ph-brain", "aria-hidden": "true" }),
12845
+ /* @__PURE__ */ jsx100("span", { children: streaming ? "Thinking" : durationMs ? "Thought for " + formatDuration(durationMs) : "Thought process" }),
12846
+ streaming ? /* @__PURE__ */ jsxs87("span", { className: "fdc-dots", "aria-hidden": "true", children: [
12847
+ /* @__PURE__ */ jsx100("span", {}),
12848
+ /* @__PURE__ */ jsx100("span", {}),
12849
+ /* @__PURE__ */ jsx100("span", {})
12769
12850
  ] }) : null,
12770
- /* @__PURE__ */ jsx98("i", { className: "ph ph-caret-" + (open2 ? "up" : "down"), "aria-hidden": "true" })
12851
+ /* @__PURE__ */ jsx100("i", { className: "ph ph-caret-" + (open2 ? "up" : "down"), "aria-hidden": "true" })
12771
12852
  ] }),
12772
- open2 ? /* @__PURE__ */ jsx98("div", { className: "fdc-think-body", children: text }) : null
12853
+ open2 ? /* @__PURE__ */ jsx100("div", { className: "fdc-think-body", children: text }) : null
12773
12854
  ] });
12774
12855
  }
12775
12856
  function Citations({ items = [], onOpen }) {
12776
- const [open2, setOpen] = React70.useState(false);
12857
+ const [open2, setOpen] = React71.useState(false);
12777
12858
  if (!items.length) return null;
12778
- return /* @__PURE__ */ jsxs86("div", { className: "fdc-cites", children: [
12779
- /* @__PURE__ */ jsxs86("button", { type: "button", className: "fdc-cites-head", onClick: () => setOpen((v) => !v), "aria-expanded": open2, children: [
12780
- /* @__PURE__ */ jsx98("i", { className: "ph ph-quotes", "aria-hidden": "true" }),
12781
- /* @__PURE__ */ jsxs86("span", { children: [
12859
+ return /* @__PURE__ */ jsxs87("div", { className: "fdc-cites", children: [
12860
+ /* @__PURE__ */ jsxs87("button", { type: "button", className: "fdc-cites-head", onClick: () => setOpen((v) => !v), "aria-expanded": open2, children: [
12861
+ /* @__PURE__ */ jsx100("i", { className: "ph ph-quotes", "aria-hidden": "true" }),
12862
+ /* @__PURE__ */ jsxs87("span", { children: [
12782
12863
  items.length,
12783
12864
  " source",
12784
12865
  items.length === 1 ? "" : "s"
12785
12866
  ] }),
12786
- /* @__PURE__ */ jsx98("i", { className: "ph ph-caret-" + (open2 ? "up" : "down"), "aria-hidden": "true" })
12867
+ /* @__PURE__ */ jsx100("i", { className: "ph ph-caret-" + (open2 ? "up" : "down"), "aria-hidden": "true" })
12787
12868
  ] }),
12788
- open2 ? /* @__PURE__ */ jsx98("ol", { className: "fdc-cites-list", children: items.map((c, i) => /* @__PURE__ */ jsxs86("li", { children: [
12789
- /* @__PURE__ */ jsx98("span", { className: "fdc-cite-n fd-tabular", children: c.marker || i + 1 }),
12790
- c.url ? /* @__PURE__ */ jsx98("a", { href: c.url, target: "_blank", rel: "noopener noreferrer", onClick: onOpen ? (e) => onOpen(c, e) : void 0, children: c.title || c.url }) : /* @__PURE__ */ jsx98("span", { children: c.title || "Source" }),
12791
- c.detail ? /* @__PURE__ */ jsx98("span", { className: "fdc-cite-detail", children: c.detail }) : null
12869
+ open2 ? /* @__PURE__ */ jsx100("ol", { className: "fdc-cites-list", children: items.map((c, i) => /* @__PURE__ */ jsxs87("li", { children: [
12870
+ /* @__PURE__ */ jsx100("span", { className: "fdc-cite-n fd-tabular", children: c.marker || i + 1 }),
12871
+ c.url ? /* @__PURE__ */ jsx100("a", { href: c.url, target: "_blank", rel: "noopener noreferrer", onClick: onOpen ? (e) => onOpen(c, e) : void 0, children: c.title || c.url }) : /* @__PURE__ */ jsx100("span", { children: c.title || "Source" }),
12872
+ c.detail ? /* @__PURE__ */ jsx100("span", { className: "fdc-cite-detail", children: c.detail }) : null
12792
12873
  ] }, c.id || i)) }) : null
12793
12874
  ] });
12794
12875
  }
@@ -12799,29 +12880,29 @@ function clampText(text, max) {
12799
12880
  return (at > max * 0.6 ? cut.slice(0, at) : cut).trimEnd() + "\u2026";
12800
12881
  }
12801
12882
  function MessageBody({ message: m, ctx }) {
12802
- const [expanded, setExpanded] = React70.useState(false);
12883
+ const [expanded, setExpanded] = React71.useState(false);
12803
12884
  const isUser = m.role === "user";
12804
12885
  const raw = m.text || "";
12805
12886
  const clamped = !expanded && !m.streaming ? clampText(raw, ctx.maxVisibleChars) : null;
12806
12887
  const body = clamped != null ? clamped : raw;
12807
12888
  const showMd = ctx.markdown && !isUser;
12808
- return /* @__PURE__ */ jsxs86("div", { className: "fdc-body", children: [
12809
- m.thinking && ctx.showThinking ? /* @__PURE__ */ jsx98(ThinkingBlock, { text: m.thinking, durationMs: m.thinkingMs, streaming: m.streaming && !m.text }) : null,
12810
- m.steps && m.steps.length && ctx.showSteps ? /* @__PURE__ */ jsx98(StepList, { steps: m.steps, defaultOpen: m.steps.some((s) => s.status === "running"), dense: true }) : null,
12811
- body ? /* @__PURE__ */ jsxs86("div", { className: "fdc-text" + (isUser ? " is-user" : ""), children: [
12812
- showMd ? /* @__PURE__ */ jsx98(Markdown, { source: body, headingOffset: 2, codeProps: { collapseAfter: 22 }, renderCitation: ctx.renderCitation }) : /* @__PURE__ */ jsx98("div", { className: "fdc-plain", children: body }),
12813
- m.streaming ? /* @__PURE__ */ jsx98("span", { className: "fdc-caret", "aria-hidden": "true" }) : null
12889
+ return /* @__PURE__ */ jsxs87("div", { className: "fdc-body", children: [
12890
+ m.thinking && ctx.showThinking ? /* @__PURE__ */ jsx100(ThinkingBlock, { text: m.thinking, durationMs: m.thinkingMs, streaming: m.streaming && !m.text }) : null,
12891
+ m.steps && m.steps.length && ctx.showSteps ? /* @__PURE__ */ jsx100(StepList, { steps: m.steps, defaultOpen: m.steps.some((s) => s.status === "running"), dense: true }) : null,
12892
+ body ? /* @__PURE__ */ jsxs87("div", { className: "fdc-text" + (isUser ? " is-user" : ""), children: [
12893
+ showMd ? /* @__PURE__ */ jsx100(Markdown, { source: body, headingOffset: 2, codeProps: { collapseAfter: 22 }, renderCitation: ctx.renderCitation }) : /* @__PURE__ */ jsx100("div", { className: "fdc-plain", children: body }),
12894
+ m.streaming ? /* @__PURE__ */ jsx100("span", { className: "fdc-caret", "aria-hidden": "true" }) : null
12814
12895
  ] }) : null,
12815
- clamped != null ? /* @__PURE__ */ jsxs86("button", { type: "button", className: "fdc-more", onClick: () => setExpanded(true), children: [
12816
- /* @__PURE__ */ jsx98("i", { className: "ph ph-caret-down", "aria-hidden": "true" }),
12896
+ clamped != null ? /* @__PURE__ */ jsxs87("button", { type: "button", className: "fdc-more", onClick: () => setExpanded(true), children: [
12897
+ /* @__PURE__ */ jsx100("i", { className: "ph ph-caret-down", "aria-hidden": "true" }),
12817
12898
  "Show more",
12818
- /* @__PURE__ */ jsx98("span", { className: "fdc-more-len fd-tabular", children: raw.length < 2e3 ? raw.length.toLocaleString() + " characters" : Math.round(raw.length / 100) / 10 + "k characters" })
12819
- ] }) : expanded && ctx.maxVisibleChars && raw.length > ctx.maxVisibleChars ? /* @__PURE__ */ jsxs86("button", { type: "button", className: "fdc-more", onClick: () => setExpanded(false), children: [
12820
- /* @__PURE__ */ jsx98("i", { className: "ph ph-caret-up", "aria-hidden": "true" }),
12899
+ /* @__PURE__ */ jsx100("span", { className: "fdc-more-len fd-tabular", children: raw.length < 2e3 ? raw.length.toLocaleString() + " characters" : Math.round(raw.length / 100) / 10 + "k characters" })
12900
+ ] }) : expanded && ctx.maxVisibleChars && raw.length > ctx.maxVisibleChars ? /* @__PURE__ */ jsxs87("button", { type: "button", className: "fdc-more", onClick: () => setExpanded(false), children: [
12901
+ /* @__PURE__ */ jsx100("i", { className: "ph ph-caret-up", "aria-hidden": "true" }),
12821
12902
  "Show less"
12822
12903
  ] }) : null,
12823
- m.attachments && m.attachments.length ? /* @__PURE__ */ jsx98(FileGrid, { files: m.attachments, onOpen: ctx.onOpenAttachment, tiles: true, maxHeight: ctx.attachmentHeight || 220, compact: ctx.narrow }) : null,
12824
- m.packet ? /* @__PURE__ */ jsx98(
12904
+ m.attachments && m.attachments.length ? /* @__PURE__ */ jsx100(FileGrid, { files: m.attachments, onOpen: ctx.onOpenAttachment, tiles: true, maxHeight: ctx.attachmentHeight || 220, compact: ctx.narrow }) : null,
12905
+ m.packet ? /* @__PURE__ */ jsx100(
12825
12906
  PacketCard,
12826
12907
  {
12827
12908
  packet: m.packet,
@@ -12831,35 +12912,35 @@ function MessageBody({ message: m, ctx }) {
12831
12912
  applied: ctx.appliedPackets && ctx.appliedPackets[m.id]
12832
12913
  }
12833
12914
  ) : null,
12834
- m.citations && m.citations.length ? /* @__PURE__ */ jsx98(Citations, { items: m.citations, onOpen: ctx.onOpenCitation }) : null,
12835
- m.working ? /* @__PURE__ */ jsxs86("div", { className: "fdc-working", role: "status", children: [
12836
- /* @__PURE__ */ jsxs86("span", { className: "fdc-dots", "aria-hidden": "true", children: [
12837
- /* @__PURE__ */ jsx98("span", {}),
12838
- /* @__PURE__ */ jsx98("span", {}),
12839
- /* @__PURE__ */ jsx98("span", {})
12915
+ m.citations && m.citations.length ? /* @__PURE__ */ jsx100(Citations, { items: m.citations, onOpen: ctx.onOpenCitation }) : null,
12916
+ m.working ? /* @__PURE__ */ jsxs87("div", { className: "fdc-working", role: "status", children: [
12917
+ /* @__PURE__ */ jsxs87("span", { className: "fdc-dots", "aria-hidden": "true", children: [
12918
+ /* @__PURE__ */ jsx100("span", {}),
12919
+ /* @__PURE__ */ jsx100("span", {}),
12920
+ /* @__PURE__ */ jsx100("span", {})
12840
12921
  ] }),
12841
- /* @__PURE__ */ jsxs86("span", { className: "fdc-working-label", children: [
12922
+ /* @__PURE__ */ jsxs87("span", { className: "fdc-working-label", children: [
12842
12923
  m.resumed ? "Resuming" : "Working",
12843
- m.job && m.job.status ? /* @__PURE__ */ jsxs86("span", { className: "fdc-working-job", children: [
12924
+ m.job && m.job.status ? /* @__PURE__ */ jsxs87("span", { className: "fdc-working-job", children: [
12844
12925
  " \xB7 ",
12845
12926
  m.job.status
12846
12927
  ] }) : null,
12847
- m.job && m.job.detail ? /* @__PURE__ */ jsxs86("span", { className: "fdc-working-job", children: [
12928
+ m.job && m.job.detail ? /* @__PURE__ */ jsxs87("span", { className: "fdc-working-job", children: [
12848
12929
  " \xB7 ",
12849
12930
  m.job.detail
12850
12931
  ] }) : null
12851
12932
  ] }),
12852
- m.jobId ? /* @__PURE__ */ jsx98("span", { className: "fdc-working-id fd-mono", children: String(m.jobId).slice(0, 12) }) : null
12933
+ m.jobId ? /* @__PURE__ */ jsx100("span", { className: "fdc-working-id fd-mono", children: String(m.jobId).slice(0, 12) }) : null
12853
12934
  ] }) : null,
12854
- m.stopped ? /* @__PURE__ */ jsxs86("div", { className: "fdc-stopped", children: [
12855
- /* @__PURE__ */ jsx98("i", { className: "ph ph-stop-circle", "aria-hidden": "true" }),
12935
+ m.stopped ? /* @__PURE__ */ jsxs87("div", { className: "fdc-stopped", children: [
12936
+ /* @__PURE__ */ jsx100("i", { className: "ph ph-stop-circle", "aria-hidden": "true" }),
12856
12937
  "Stopped"
12857
12938
  ] }) : null,
12858
- m.error ? /* @__PURE__ */ jsxs86("div", { className: "fdc-error", role: "alert", children: [
12859
- /* @__PURE__ */ jsx98("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
12860
- /* @__PURE__ */ jsx98("span", { className: "fdc-error-text", children: ctx.errorCopy ? ctx.errorCopy(m.error) : m.error }),
12861
- m.retryable && ctx.onRetry ? /* @__PURE__ */ jsxs86("button", { type: "button", className: "fdc-error-retry", onClick: ctx.onRetry, children: [
12862
- /* @__PURE__ */ jsx98("i", { className: "ph ph-arrow-clockwise", "aria-hidden": "true" }),
12939
+ m.error ? /* @__PURE__ */ jsxs87("div", { className: "fdc-error", role: "alert", children: [
12940
+ /* @__PURE__ */ jsx100("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
12941
+ /* @__PURE__ */ jsx100("span", { className: "fdc-error-text", children: ctx.errorCopy ? ctx.errorCopy(m.error) : m.error }),
12942
+ m.retryable && ctx.onRetry ? /* @__PURE__ */ jsxs87("button", { type: "button", className: "fdc-error-retry", onClick: ctx.onRetry, children: [
12943
+ /* @__PURE__ */ jsx100("i", { className: "ph ph-arrow-clockwise", "aria-hidden": "true" }),
12863
12944
  "Retry"
12864
12945
  ] }) : null
12865
12946
  ] }) : null
@@ -12872,16 +12953,16 @@ function RunActions({ group, ctx }) {
12872
12953
  const isAssistant = group.role === "assistant";
12873
12954
  const fb = last.feedback;
12874
12955
  if (!ctx.messageActions) return null;
12875
- return /* @__PURE__ */ jsxs86("div", { className: "fdc-actions", role: "group", "aria-label": "Message actions", children: [
12876
- /* @__PURE__ */ jsxs86("button", { type: "button", className: "fdc-act" + (copied ? " is-done" : ""), onClick: () => copy(markdownToText(text)), "aria-label": "Copy message", children: [
12877
- /* @__PURE__ */ jsx98("i", { className: "ph ph-" + (copied ? "check" : "copy"), "aria-hidden": "true" }),
12878
- /* @__PURE__ */ jsx98("span", { className: "fdc-act-label", children: copied ? "Copied" : "Copy" })
12956
+ return /* @__PURE__ */ jsxs87("div", { className: "fdc-actions", role: "group", "aria-label": "Message actions", children: [
12957
+ /* @__PURE__ */ jsxs87("button", { type: "button", className: "fdc-act" + (copied ? " is-done" : ""), onClick: () => copy(markdownToText(text)), "aria-label": "Copy message", children: [
12958
+ /* @__PURE__ */ jsx100("i", { className: "ph ph-" + (copied ? "check" : "copy"), "aria-hidden": "true" }),
12959
+ /* @__PURE__ */ jsx100("span", { className: "fdc-act-label", children: copied ? "Copied" : "Copy" })
12879
12960
  ] }),
12880
- isAssistant && ctx.onRetry ? /* @__PURE__ */ jsx98("button", { type: "button", className: "fdc-act", onClick: ctx.onRetry, "aria-label": "Retry this turn", children: /* @__PURE__ */ jsx98("i", { className: "ph ph-arrow-clockwise", "aria-hidden": "true" }) }) : null,
12881
- group.role === "user" && ctx.onEdit ? /* @__PURE__ */ jsx98("button", { type: "button", className: "fdc-act", onClick: () => ctx.onEdit(last), "aria-label": "Edit and resend", children: /* @__PURE__ */ jsx98("i", { className: "ph ph-pencil-simple", "aria-hidden": "true" }) }) : null,
12882
- isAssistant && ctx.onFeedback ? /* @__PURE__ */ jsxs86(React70.Fragment, { children: [
12883
- /* @__PURE__ */ jsx98("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__ */ jsx98("i", { className: "ph ph-thumbs-up", "aria-hidden": "true" }) }),
12884
- /* @__PURE__ */ jsx98("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__ */ jsx98("i", { className: "ph ph-thumbs-down", "aria-hidden": "true" }) })
12961
+ isAssistant && ctx.onRetry ? /* @__PURE__ */ jsx100("button", { type: "button", className: "fdc-act", onClick: ctx.onRetry, "aria-label": "Retry this turn", children: /* @__PURE__ */ jsx100("i", { className: "ph ph-arrow-clockwise", "aria-hidden": "true" }) }) : null,
12962
+ group.role === "user" && ctx.onEdit ? /* @__PURE__ */ jsx100("button", { type: "button", className: "fdc-act", onClick: () => ctx.onEdit(last), "aria-label": "Edit and resend", children: /* @__PURE__ */ jsx100("i", { className: "ph ph-pencil-simple", "aria-hidden": "true" }) }) : null,
12963
+ isAssistant && ctx.onFeedback ? /* @__PURE__ */ jsxs87(React71.Fragment, { children: [
12964
+ /* @__PURE__ */ jsx100("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__ */ jsx100("i", { className: "ph ph-thumbs-up", "aria-hidden": "true" }) }),
12965
+ /* @__PURE__ */ jsx100("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__ */ jsx100("i", { className: "ph ph-thumbs-down", "aria-hidden": "true" }) })
12885
12966
  ] }) : null,
12886
12967
  ctx.extraActions ? ctx.extraActions(group) : null
12887
12968
  ] });
@@ -12891,22 +12972,22 @@ function ChatTurn({ group, ctx }) {
12891
12972
  const name = isUser ? ctx.userName : group.author || ctx.assistantName;
12892
12973
  const avatar = isUser ? ctx.userAvatar : ctx.assistantAvatar;
12893
12974
  const stamp = group.messages[0].timestamp;
12894
- return /* @__PURE__ */ jsxs86("article", { className: "fdc-turn is-" + group.role, "aria-label": String(name) + (stamp ? " at " + formatClock(stamp) : ""), children: [
12895
- /* @__PURE__ */ jsxs86("div", { className: "fdc-turn-head", children: [
12896
- ctx.showAvatars ? /* @__PURE__ */ jsx98("span", { className: "fdc-avatar is-" + group.role, "aria-hidden": "true", children: avatar ? /* @__PURE__ */ jsx98("img", { src: avatar, alt: "" }) : isUser ? /* @__PURE__ */ jsx98("span", { className: "fdc-avatar-txt", children: (name || "You").slice(0, 1).toUpperCase() }) : /* @__PURE__ */ jsx98("i", { className: "ph ph-" + (ctx.assistantIcon || "sparkle") }) }) : null,
12897
- /* @__PURE__ */ jsx98("span", { className: "fdc-who", children: name }),
12898
- stamp ? /* @__PURE__ */ jsx98(RelativeTime, { className: "fdc-when", value: stamp }) : null,
12899
- group.messages.some((m) => m.model) ? /* @__PURE__ */ jsx98("span", { className: "fdc-turn-model", children: group.messages.find((m) => m.model).model }) : null
12975
+ return /* @__PURE__ */ jsxs87("article", { className: "fdc-turn is-" + group.role, "aria-label": String(name) + (stamp ? " at " + formatClock(stamp) : ""), children: [
12976
+ /* @__PURE__ */ jsxs87("div", { className: "fdc-turn-head", children: [
12977
+ ctx.showAvatars ? /* @__PURE__ */ jsx100("span", { className: "fdc-avatar is-" + group.role, "aria-hidden": "true", children: avatar ? /* @__PURE__ */ jsx100("img", { src: avatar, alt: "" }) : isUser ? /* @__PURE__ */ jsx100("span", { className: "fdc-avatar-txt", children: (name || "You").slice(0, 1).toUpperCase() }) : /* @__PURE__ */ jsx100("i", { className: "ph ph-" + (ctx.assistantIcon || "sparkle") }) }) : null,
12978
+ /* @__PURE__ */ jsx100("span", { className: "fdc-who", children: name }),
12979
+ stamp ? /* @__PURE__ */ jsx100(RelativeTime, { className: "fdc-when", value: stamp }) : null,
12980
+ group.messages.some((m) => m.model) ? /* @__PURE__ */ jsx100("span", { className: "fdc-turn-model", children: group.messages.find((m) => m.model).model }) : null
12900
12981
  ] }),
12901
- /* @__PURE__ */ jsxs86("div", { className: "fdc-turn-body", children: [
12902
- group.messages.map((m) => /* @__PURE__ */ jsx98("div", { className: "fdc-msg" + (m.pending ? " is-pending" : ""), children: /* @__PURE__ */ jsx98(MessageBody, { message: m, ctx }) }, m.id)),
12903
- /* @__PURE__ */ jsx98(RunActions, { group, ctx })
12982
+ /* @__PURE__ */ jsxs87("div", { className: "fdc-turn-body", children: [
12983
+ group.messages.map((m) => /* @__PURE__ */ jsx100("div", { className: "fdc-msg" + (m.pending ? " is-pending" : ""), children: /* @__PURE__ */ jsx100(MessageBody, { message: m, ctx }) }, m.id)),
12984
+ /* @__PURE__ */ jsx100(RunActions, { group, ctx })
12904
12985
  ] })
12905
12986
  ] });
12906
12987
  }
12907
12988
 
12908
12989
  // src/components/chat/ChatTranscript.tsx
12909
- import { jsx as jsx99, jsxs as jsxs87 } from "react/jsx-runtime";
12990
+ import { jsx as jsx101, jsxs as jsxs88 } from "react/jsx-runtime";
12910
12991
  var GROUP_WINDOW = 6e4;
12911
12992
  var STICK_PX = 100;
12912
12993
  function groupMessages(list) {
@@ -12939,25 +13020,25 @@ function dayLabel(key) {
12939
13020
  }
12940
13021
  function Suggestions({ items = [], onPick }) {
12941
13022
  if (!items.length) return null;
12942
- return /* @__PURE__ */ jsx99("div", { className: "fdc-suggest", children: items.map((s, i) => {
13023
+ return /* @__PURE__ */ jsx101("div", { className: "fdc-suggest", children: items.map((s, i) => {
12943
13024
  const it = typeof s === "string" ? { label: s, text: s } : s;
12944
- return /* @__PURE__ */ jsxs87("button", { type: "button", className: "fdc-suggest-item", onClick: () => onPick && onPick(it.text || it.label), children: [
12945
- it.icon ? /* @__PURE__ */ jsx99("i", { className: "ph ph-" + it.icon, "aria-hidden": "true" }) : null,
12946
- /* @__PURE__ */ jsxs87("span", { className: "fdc-suggest-text", children: [
12947
- /* @__PURE__ */ jsx99("span", { className: "fdc-suggest-label", children: it.label }),
12948
- it.description ? /* @__PURE__ */ jsx99("span", { className: "fdc-suggest-desc", children: it.description }) : null
13025
+ return /* @__PURE__ */ jsxs88("button", { type: "button", className: "fdc-suggest-item", onClick: () => onPick && onPick(it.text || it.label), children: [
13026
+ it.icon ? /* @__PURE__ */ jsx101("i", { className: "ph ph-" + it.icon, "aria-hidden": "true" }) : null,
13027
+ /* @__PURE__ */ jsxs88("span", { className: "fdc-suggest-text", children: [
13028
+ /* @__PURE__ */ jsx101("span", { className: "fdc-suggest-label", children: it.label }),
13029
+ it.description ? /* @__PURE__ */ jsx101("span", { className: "fdc-suggest-desc", children: it.description }) : null
12949
13030
  ] }),
12950
- /* @__PURE__ */ jsx99("i", { className: "ph ph-arrow-up-right fdc-suggest-go", "aria-hidden": "true" })
13031
+ /* @__PURE__ */ jsx101("i", { className: "ph ph-arrow-up-right fdc-suggest-go", "aria-hidden": "true" })
12951
13032
  ] }, it.id || i);
12952
13033
  }) });
12953
13034
  }
12954
13035
  function LoadingTurns() {
12955
- return /* @__PURE__ */ jsx99("div", { className: "fdc-skel", "aria-hidden": "true", children: [0, 1].map((i) => /* @__PURE__ */ jsxs87("div", { className: "fdc-skel-turn", children: [
12956
- /* @__PURE__ */ jsx99("div", { className: "fd-skel fd-skel-circle", style: { width: 22, height: 22 } }),
12957
- /* @__PURE__ */ jsxs87("div", { className: "fdc-skel-lines", children: [
12958
- /* @__PURE__ */ jsx99("div", { className: "fd-skel", style: { width: i ? "62%" : "44%", height: 11 } }),
12959
- /* @__PURE__ */ jsx99("div", { className: "fd-skel", style: { width: i ? "94%" : "78%", height: 11 } }),
12960
- /* @__PURE__ */ jsx99("div", { className: "fd-skel", style: { width: i ? "71%" : "56%", height: 11 } })
13036
+ return /* @__PURE__ */ jsx101("div", { className: "fdc-skel", "aria-hidden": "true", children: [0, 1].map((i) => /* @__PURE__ */ jsxs88("div", { className: "fdc-skel-turn", children: [
13037
+ /* @__PURE__ */ jsx101("div", { className: "fd-skel fd-skel-circle", style: { width: 22, height: 22 } }),
13038
+ /* @__PURE__ */ jsxs88("div", { className: "fdc-skel-lines", children: [
13039
+ /* @__PURE__ */ jsx101("div", { className: "fd-skel", style: { width: i ? "62%" : "44%", height: 11 } }),
13040
+ /* @__PURE__ */ jsx101("div", { className: "fd-skel", style: { width: i ? "94%" : "78%", height: 11 } }),
13041
+ /* @__PURE__ */ jsx101("div", { className: "fd-skel", style: { width: i ? "71%" : "56%", height: 11 } })
12961
13042
  ] })
12962
13043
  ] }, i)) });
12963
13044
  }
@@ -12974,10 +13055,10 @@ function ChatTranscript({
12974
13055
  renderEmpty,
12975
13056
  className = ""
12976
13057
  }) {
12977
- const scroller = React71.useRef(null);
12978
- const stick = React71.useRef(true);
12979
- const [pill, setPill] = React71.useState(0);
12980
- const seen = React71.useRef(0);
13058
+ const scroller = React72.useRef(null);
13059
+ const stick = React72.useRef(true);
13060
+ const [pill, setPill] = React72.useState(0);
13061
+ const seen = React72.useRef(0);
12981
13062
  const toBottom = (smooth) => {
12982
13063
  const el = scroller.current;
12983
13064
  if (!el) return;
@@ -12996,7 +13077,7 @@ function ChatTranscript({
12996
13077
  seen.current = messages.length;
12997
13078
  }
12998
13079
  };
12999
- React71.useLayoutEffect(() => {
13080
+ React72.useLayoutEffect(() => {
13000
13081
  const el = scroller.current;
13001
13082
  if (!el) return;
13002
13083
  if (stick.current) {
@@ -13004,7 +13085,7 @@ function ChatTranscript({
13004
13085
  seen.current = messages.length;
13005
13086
  } else setPill(Math.max(0, messages.length - seen.current));
13006
13087
  }, [messages]);
13007
- React71.useEffect(() => {
13088
+ React72.useEffect(() => {
13008
13089
  const el = scroller.current;
13009
13090
  const inner = el && el.firstChild;
13010
13091
  if (!el || !inner || typeof ResizeObserver === "undefined") return;
@@ -13014,38 +13095,38 @@ function ChatTranscript({
13014
13095
  ro.observe(inner);
13015
13096
  return () => ro.disconnect();
13016
13097
  }, []);
13017
- const groups = React71.useMemo(() => groupMessages(messages), [messages]);
13098
+ const groups = React72.useMemo(() => groupMessages(messages), [messages]);
13018
13099
  const empty = !messages.length && status === "ready";
13019
- return /* @__PURE__ */ jsxs87("div", { className: ["fdc-scroll", className].filter(Boolean).join(" "), ref: scroller, onScroll, children: [
13020
- /* @__PURE__ */ jsxs87("div", { className: "fdc-log", role: "log", "aria-label": "Conversation", children: [
13021
- status === "loading" || status === "resolving" ? /* @__PURE__ */ jsx99(LoadingTurns, {}) : null,
13022
- status === "disconnected" ? /* @__PURE__ */ jsxs87("div", { className: "fdc-dead", children: [
13023
- /* @__PURE__ */ jsx99("span", { className: "fdc-dead-icon", children: /* @__PURE__ */ jsx99("i", { className: "ph ph-plugs", "aria-hidden": "true" }) }),
13024
- /* @__PURE__ */ jsx99("h3", { className: "fdc-dead-title", children: ctx.deadTitle || "The assistant isn\u2019t reachable" }),
13025
- /* @__PURE__ */ jsx99("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." }),
13026
- ctx.onReconnect ? /* @__PURE__ */ jsxs87("button", { type: "button", className: "fd-btn fd-btn-secondary fd-btn-sm", onClick: ctx.onReconnect, children: [
13027
- /* @__PURE__ */ jsx99("i", { className: "ph ph-arrow-clockwise", "aria-hidden": "true" }),
13100
+ return /* @__PURE__ */ jsxs88("div", { className: ["fdc-scroll", className].filter(Boolean).join(" "), ref: scroller, onScroll, children: [
13101
+ /* @__PURE__ */ jsxs88("div", { className: "fdc-log", role: "log", "aria-label": "Conversation", children: [
13102
+ status === "loading" || status === "resolving" ? /* @__PURE__ */ jsx101(LoadingTurns, {}) : null,
13103
+ status === "disconnected" ? /* @__PURE__ */ jsxs88("div", { className: "fdc-dead", children: [
13104
+ /* @__PURE__ */ jsx101("span", { className: "fdc-dead-icon", children: /* @__PURE__ */ jsx101("i", { className: "ph ph-plugs", "aria-hidden": "true" }) }),
13105
+ /* @__PURE__ */ jsx101("h3", { className: "fdc-dead-title", children: ctx.deadTitle || "The assistant isn\u2019t reachable" }),
13106
+ /* @__PURE__ */ jsx101("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." }),
13107
+ ctx.onReconnect ? /* @__PURE__ */ jsxs88("button", { type: "button", className: "fd-btn fd-btn-secondary fd-btn-sm", onClick: ctx.onReconnect, children: [
13108
+ /* @__PURE__ */ jsx101("i", { className: "ph ph-arrow-clockwise", "aria-hidden": "true" }),
13028
13109
  "Try again"
13029
13110
  ] }) : null
13030
13111
  ] }) : null,
13031
- empty ? renderEmpty ? renderEmpty() : /* @__PURE__ */ jsxs87("div", { className: "fdc-empty", children: [
13032
- /* @__PURE__ */ jsx99("span", { className: "fdc-empty-icon", children: /* @__PURE__ */ jsx99("i", { className: "ph ph-" + emptyIcon, "aria-hidden": "true" }) }),
13033
- /* @__PURE__ */ jsx99("h3", { className: "fdc-empty-title", children: emptyTitle }),
13034
- emptyDescription ? /* @__PURE__ */ jsx99("p", { className: "fdc-empty-body", children: emptyDescription }) : null,
13035
- /* @__PURE__ */ jsx99(Suggestions, { items: suggestions, onPick })
13112
+ empty ? renderEmpty ? renderEmpty() : /* @__PURE__ */ jsxs88("div", { className: "fdc-empty", children: [
13113
+ /* @__PURE__ */ jsx101("span", { className: "fdc-empty-icon", children: /* @__PURE__ */ jsx101("i", { className: "ph ph-" + emptyIcon, "aria-hidden": "true" }) }),
13114
+ /* @__PURE__ */ jsx101("h3", { className: "fdc-empty-title", children: emptyTitle }),
13115
+ emptyDescription ? /* @__PURE__ */ jsx101("p", { className: "fdc-empty-body", children: emptyDescription }) : null,
13116
+ /* @__PURE__ */ jsx101(Suggestions, { items: suggestions, onPick })
13036
13117
  ] }) : null,
13037
13118
  groups.map((g, i) => {
13038
13119
  const prev = groups[i - 1];
13039
13120
  const k = dayKey(g.messages[0].timestamp);
13040
13121
  const showDay = !!k && (!prev || dayKey(prev.messages[0].timestamp) !== k);
13041
- return /* @__PURE__ */ jsxs87(React71.Fragment, { children: [
13042
- showDay ? /* @__PURE__ */ jsx99("div", { className: "fdc-day", children: /* @__PURE__ */ jsx99("span", { children: dayLabel(k) }) }) : null,
13043
- /* @__PURE__ */ jsx99(ChatTurn, { group: g, ctx })
13122
+ return /* @__PURE__ */ jsxs88(React72.Fragment, { children: [
13123
+ showDay ? /* @__PURE__ */ jsx101("div", { className: "fdc-day", children: /* @__PURE__ */ jsx101("span", { children: dayLabel(k) }) }) : null,
13124
+ /* @__PURE__ */ jsx101(ChatTurn, { group: g, ctx })
13044
13125
  ] }, g.key || i);
13045
13126
  })
13046
13127
  ] }),
13047
- pill ? /* @__PURE__ */ jsxs87("button", { type: "button", className: "fdc-pill", onClick: () => toBottom(true), children: [
13048
- /* @__PURE__ */ jsx99("i", { className: "ph ph-arrow-down", "aria-hidden": "true" }),
13128
+ pill ? /* @__PURE__ */ jsxs88("button", { type: "button", className: "fdc-pill", onClick: () => toBottom(true), children: [
13129
+ /* @__PURE__ */ jsx101("i", { className: "ph ph-arrow-down", "aria-hidden": "true" }),
13049
13130
  pill,
13050
13131
  " new message",
13051
13132
  pill === 1 ? "" : "s"
@@ -13055,8 +13136,8 @@ function ChatTranscript({
13055
13136
  var TranscriptKit = { groupMessages };
13056
13137
 
13057
13138
  // src/components/chat/ChatComposer.tsx
13058
- import * as React72 from "react";
13059
- import { jsx as jsx100, jsxs as jsxs88 } from "react/jsx-runtime";
13139
+ import * as React73 from "react";
13140
+ import { jsx as jsx102, jsxs as jsxs89 } from "react/jsx-runtime";
13060
13141
  function ChatComposer({
13061
13142
  onSubmit,
13062
13143
  onStop,
@@ -13083,17 +13164,17 @@ function ChatComposer({
13083
13164
  onReject,
13084
13165
  onOpenAttachment
13085
13166
  }) {
13086
- const [text, setText] = React72.useState(draft || "");
13087
- const [trigger, setTrigger] = React72.useState(null);
13088
- const [mentionItems, setMentionItems] = React72.useState([]);
13089
- const [listening, setListening] = React72.useState(false);
13090
- const [notice, setNotice] = React72.useState(null);
13091
- const editor = React72.useRef(null);
13092
- const wrap = React72.useRef(null);
13093
- const stopVoice = React72.useRef(null);
13167
+ const [text, setText] = React73.useState(draft || "");
13168
+ const [trigger, setTrigger] = React73.useState(null);
13169
+ const [mentionItems, setMentionItems] = React73.useState([]);
13170
+ const [listening, setListening] = React73.useState(false);
13171
+ const [notice, setNotice] = React73.useState(null);
13172
+ const editor = React73.useRef(null);
13173
+ const wrap = React73.useRef(null);
13174
+ const stopVoice = React73.useRef(null);
13094
13175
  const staged = useStagedFiles(fileUploadHandler, { onError: () => {
13095
13176
  } });
13096
- React72.useEffect(() => {
13177
+ React73.useEffect(() => {
13097
13178
  if (draft != null && draft !== text) setText(draft);
13098
13179
  }, [draft]);
13099
13180
  const change = (v) => {
@@ -13129,7 +13210,7 @@ function ChatComposer({
13129
13210
  e.preventDefault();
13130
13211
  staged.add(found.files);
13131
13212
  };
13132
- React72.useEffect(() => {
13213
+ React73.useEffect(() => {
13133
13214
  if (!trigger || trigger.type !== "mention" || !mentionSources) {
13134
13215
  setMentionItems([]);
13135
13216
  return;
@@ -13147,7 +13228,7 @@ function ChatComposer({
13147
13228
  const q = (trigger.query || "").toLowerCase();
13148
13229
  setMentionItems(mentionSources.filter((m) => !q || (m.label + " " + (m.description || "")).toLowerCase().includes(q)));
13149
13230
  }, [trigger, mentionSources]);
13150
- const slashItems = React72.useMemo(() => {
13231
+ const slashItems = React73.useMemo(() => {
13151
13232
  if (!trigger || trigger.type !== "slash" || !slashCommands) return [];
13152
13233
  const q = (trigger.query || "").toLowerCase();
13153
13234
  return slashCommands.filter((c) => !q || (c.id + " " + c.label + " " + (c.description || "")).toLowerCase().includes(q));
@@ -13161,7 +13242,7 @@ function ChatComposer({
13161
13242
  description: it.description,
13162
13243
  icon: it.icon,
13163
13244
  meta: mention.meta,
13164
- shortcut: slash.shortcut ? /* @__PURE__ */ jsx100(KeyHint, { keys: slash.shortcut, size: "sm" }) : void 0,
13245
+ shortcut: slash.shortcut ? /* @__PURE__ */ jsx102(KeyHint, { keys: slash.shortcut, size: "sm" }) : void 0,
13165
13246
  onSelect: () => {
13166
13247
  const insert = trigger.type === "slash" ? slash.immediate ? "/" + slash.id : "/" + slash.id + " " : "@" + (mention.value || mention.label) + " ";
13167
13248
  editor.current && editor.current.replaceRange(trigger.from, trigger.to, insert);
@@ -13220,14 +13301,14 @@ function ChatComposer({
13220
13301
  stopVoice.current = typeof res === "function" ? res : () => {
13221
13302
  };
13222
13303
  };
13223
- return /* @__PURE__ */ jsxs88("div", { className: "fdc-composer" + (disabled ? " is-disabled" : "") + (narrow ? " is-narrow" : ""), children: [
13224
- queue.length ? /* @__PURE__ */ jsx100("div", { className: "fdc-queue", "aria-label": "Queued messages", children: queue.map((q) => /* @__PURE__ */ jsxs88("div", { className: "fdc-queue-row", children: [
13225
- /* @__PURE__ */ jsx100("i", { className: "ph ph-clock-countdown", "aria-hidden": "true" }),
13226
- /* @__PURE__ */ jsx100("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)" : "") }),
13227
- onRemoveQueued ? /* @__PURE__ */ jsx100("button", { type: "button", className: "fdc-queue-x", onClick: () => onRemoveQueued(q.id), "aria-label": "Remove queued message", children: /* @__PURE__ */ jsx100("i", { className: "ph ph-x", "aria-hidden": "true" }) }) : null
13304
+ return /* @__PURE__ */ jsxs89("div", { className: "fdc-composer" + (disabled ? " is-disabled" : "") + (narrow ? " is-narrow" : ""), children: [
13305
+ queue.length ? /* @__PURE__ */ jsx102("div", { className: "fdc-queue", "aria-label": "Queued messages", children: queue.map((q) => /* @__PURE__ */ jsxs89("div", { className: "fdc-queue-row", children: [
13306
+ /* @__PURE__ */ jsx102("i", { className: "ph ph-clock-countdown", "aria-hidden": "true" }),
13307
+ /* @__PURE__ */ jsx102("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)" : "") }),
13308
+ onRemoveQueued ? /* @__PURE__ */ jsx102("button", { type: "button", className: "fdc-queue-x", onClick: () => onRemoveQueued(q.id), "aria-label": "Remove queued message", children: /* @__PURE__ */ jsx102("i", { className: "ph ph-x", "aria-hidden": "true" }) }) : null
13228
13309
  ] }, q.id)) }) : null,
13229
13310
  sessionBar,
13230
- /* @__PURE__ */ jsx100(
13311
+ /* @__PURE__ */ jsx102(
13231
13312
  Dropzone,
13232
13313
  {
13233
13314
  className: "fdc-field",
@@ -13241,9 +13322,9 @@ function ChatComposer({
13241
13322
  disabled: !fileUploadHandler || disabled,
13242
13323
  label: "Drop to attach",
13243
13324
  hint: acceptFiles ? acceptFiles.replace(/,/g, " \xB7 ") : void 0,
13244
- children: /* @__PURE__ */ jsxs88("div", { ref: wrap, className: "fdc-field-inner", children: [
13245
- staged.items.length ? /* @__PURE__ */ jsx100("div", { className: "fdc-staged", children: /* @__PURE__ */ jsx100(FileStrip, { files: staged.items, size: narrow ? 60 : 68, onRemove: staged.remove, onRetry: staged.retry, onOpen: onOpenAttachment }) }) : null,
13246
- /* @__PURE__ */ jsx100(
13325
+ children: /* @__PURE__ */ jsxs89("div", { ref: wrap, className: "fdc-field-inner", children: [
13326
+ staged.items.length ? /* @__PURE__ */ jsx102("div", { className: "fdc-staged", children: /* @__PURE__ */ jsx102(FileStrip, { files: staged.items, size: narrow ? 60 : 68, onRemove: staged.remove, onRetry: staged.retry, onOpen: onOpenAttachment }) }) : null,
13327
+ /* @__PURE__ */ jsx102(
13247
13328
  MarkdownEditor,
13248
13329
  {
13249
13330
  ref: editor,
@@ -13262,33 +13343,33 @@ function ChatComposer({
13262
13343
  ariaLabel: "Message"
13263
13344
  }
13264
13345
  ),
13265
- /* @__PURE__ */ jsxs88("div", { className: "fdc-tools", children: [
13266
- fileUploadHandler ? /* @__PURE__ */ jsx100(FilePickButton, { onFiles: staged.add, onReject: (r) => flash(r[0].message), accept: acceptFiles, maxFileSize, label: "Attach files", icon: "plus" }) : null,
13267
- voiceHandler ? /* @__PURE__ */ jsx100("button", { type: "button", className: "fd-attachbtn" + (listening ? " is-live" : ""), onClick: voice, "aria-pressed": listening, "aria-label": listening ? "Stop dictation" : "Dictate", children: /* @__PURE__ */ jsx100("i", { className: "ph ph-" + (listening ? "waveform" : "microphone"), "aria-hidden": "true" }) }) : null,
13346
+ /* @__PURE__ */ jsxs89("div", { className: "fdc-tools", children: [
13347
+ fileUploadHandler ? /* @__PURE__ */ jsx102(FilePickButton, { onFiles: staged.add, onReject: (r) => flash(r[0].message), accept: acceptFiles, maxFileSize, label: "Attach files", icon: "plus" }) : null,
13348
+ voiceHandler ? /* @__PURE__ */ jsx102("button", { type: "button", className: "fd-attachbtn" + (listening ? " is-live" : ""), onClick: voice, "aria-pressed": listening, "aria-label": listening ? "Stop dictation" : "Dictate", children: /* @__PURE__ */ jsx102("i", { className: "ph ph-" + (listening ? "waveform" : "microphone"), "aria-hidden": "true" }) }) : null,
13268
13349
  toolbarExtras,
13269
- /* @__PURE__ */ jsx100("span", { className: "fdc-tools-gap" }),
13270
- maxLength && text.length > maxLength * 0.6 ? /* @__PURE__ */ jsxs88("span", { className: "fdc-count fd-tabular" + (text.length > maxLength * 0.95 ? " is-hot" : ""), children: [
13350
+ /* @__PURE__ */ jsx102("span", { className: "fdc-tools-gap" }),
13351
+ maxLength && text.length > maxLength * 0.6 ? /* @__PURE__ */ jsxs89("span", { className: "fdc-count fd-tabular" + (text.length > maxLength * 0.95 ? " is-hot" : ""), children: [
13271
13352
  text.length,
13272
13353
  "/",
13273
13354
  maxLength
13274
13355
  ] }) : null,
13275
- busy ? /* @__PURE__ */ jsxs88("button", { type: "button", className: "fdc-stop", onClick: onStop, "aria-label": "Stop generating", children: [
13276
- /* @__PURE__ */ jsx100("i", { className: "ph ph-stop-circle", "aria-hidden": "true" }),
13277
- /* @__PURE__ */ jsx100("span", { children: "Stop" })
13278
- ] }) : /* @__PURE__ */ jsxs88("button", { type: "button", className: "fdc-send", onClick: submit, disabled: !canSend, "aria-label": "Send message", children: [
13279
- /* @__PURE__ */ jsx100("i", { className: "ph ph-paper-plane-right", "aria-hidden": "true" }),
13280
- /* @__PURE__ */ jsx100("span", { className: "fdc-send-label", children: "Send" })
13356
+ busy ? /* @__PURE__ */ jsxs89("button", { type: "button", className: "fdc-stop", onClick: onStop, "aria-label": "Stop generating", children: [
13357
+ /* @__PURE__ */ jsx102("i", { className: "ph ph-stop-circle", "aria-hidden": "true" }),
13358
+ /* @__PURE__ */ jsx102("span", { children: "Stop" })
13359
+ ] }) : /* @__PURE__ */ jsxs89("button", { type: "button", className: "fdc-send", onClick: submit, disabled: !canSend, "aria-label": "Send message", children: [
13360
+ /* @__PURE__ */ jsx102("i", { className: "ph ph-paper-plane-right", "aria-hidden": "true" }),
13361
+ /* @__PURE__ */ jsx102("span", { className: "fdc-send-label", children: "Send" })
13281
13362
  ] })
13282
13363
  ] })
13283
13364
  ] })
13284
13365
  }
13285
13366
  ),
13286
- notice ? /* @__PURE__ */ jsxs88("div", { className: "fdc-notice", role: "status", children: [
13287
- /* @__PURE__ */ jsx100("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
13367
+ notice ? /* @__PURE__ */ jsxs89("div", { className: "fdc-notice", role: "status", children: [
13368
+ /* @__PURE__ */ jsx102("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
13288
13369
  notice
13289
13370
  ] }) : null,
13290
- hint && !notice ? /* @__PURE__ */ jsx100("div", { className: "fdc-hint", children: hint }) : null,
13291
- /* @__PURE__ */ jsx100(
13371
+ hint && !notice ? /* @__PURE__ */ jsx102("div", { className: "fdc-hint", children: hint }) : null,
13372
+ /* @__PURE__ */ jsx102(
13292
13373
  Popover,
13293
13374
  {
13294
13375
  open: menuOpen,
@@ -13302,12 +13383,12 @@ function ChatComposer({
13302
13383
  returnFocus: false,
13303
13384
  closeOnOutside: true,
13304
13385
  label: trigger && trigger.type === "slash" ? "Commands" : "Mentions",
13305
- children: /* @__PURE__ */ jsx100(
13386
+ children: /* @__PURE__ */ jsx102(
13306
13387
  Menu,
13307
13388
  {
13308
13389
  items: menuItems,
13309
13390
  autoFocus: false,
13310
- header: /* @__PURE__ */ jsx100("div", { className: "fd-pop-group", children: trigger && trigger.type === "slash" ? "Commands" : "Attach context" }),
13391
+ header: /* @__PURE__ */ jsx102("div", { className: "fd-pop-group", children: trigger && trigger.type === "slash" ? "Commands" : "Attach context" }),
13311
13392
  onClose: () => setTrigger(null)
13312
13393
  }
13313
13394
  )
@@ -13317,12 +13398,12 @@ function ChatComposer({
13317
13398
  }
13318
13399
 
13319
13400
  // src/components/chat/ChatSessionBar.tsx
13320
- import * as React73 from "react";
13321
- import { jsx as jsx101, jsxs as jsxs89 } from "react/jsx-runtime";
13401
+ import * as React74 from "react";
13402
+ import { jsx as jsx103, jsxs as jsxs90 } from "react/jsx-runtime";
13322
13403
  var compact2 = meterFormats.compact;
13323
13404
  function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extras }) {
13324
- const [open2, setOpen] = React73.useState(false);
13325
- const anchor = React73.useRef(null);
13405
+ const [open2, setOpen] = React74.useState(false);
13406
+ const anchor = React74.useRef(null);
13326
13407
  const stats = sessionStats || null;
13327
13408
  const cu = contextUsage || null;
13328
13409
  const limits = usageLimits || null;
@@ -13337,9 +13418,9 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
13337
13418
  if (stats && stats.runningTasks) bits.push(stats.runningTasks + " running task" + (stats.runningTasks === 1 ? "" : "s"));
13338
13419
  if (cu) bits.push(pct + "% context");
13339
13420
  const expandable = !!(cu || limits);
13340
- return /* @__PURE__ */ jsxs89(React73.Fragment, { children: [
13341
- /* @__PURE__ */ jsxs89("div", { className: "fdc-bar", children: [
13342
- /* @__PURE__ */ jsxs89(
13421
+ return /* @__PURE__ */ jsxs90(React74.Fragment, { children: [
13422
+ /* @__PURE__ */ jsxs90("div", { className: "fdc-bar", children: [
13423
+ /* @__PURE__ */ jsxs90(
13343
13424
  "button",
13344
13425
  {
13345
13426
  type: "button",
@@ -13350,15 +13431,15 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
13350
13431
  "aria-expanded": expandable ? open2 : void 0,
13351
13432
  "aria-label": expandable ? "Usage details" : void 0,
13352
13433
  children: [
13353
- cu ? /* @__PURE__ */ jsx101("span", { className: "fdc-bar-mini", "aria-hidden": "true", children: /* @__PURE__ */ jsx101(SegmentedMeter, { total, segments: cu.segments, height: 4, showTotal: false }) }) : null,
13354
- /* @__PURE__ */ jsx101("span", { className: "fdc-bar-text", title: truncationTitle(bits.join(" \xB7 ")), children: bits.join(" \xB7 ") }),
13355
- expandable ? /* @__PURE__ */ jsx101("i", { className: "ph ph-caret-right fdc-bar-caret", "aria-hidden": "true" }) : null
13434
+ cu ? /* @__PURE__ */ jsx103("span", { className: "fdc-bar-mini", "aria-hidden": "true", children: /* @__PURE__ */ jsx103(SegmentedMeter, { total, segments: cu.segments, height: 4, showTotal: false }) }) : null,
13435
+ /* @__PURE__ */ jsx103("span", { className: "fdc-bar-text", title: truncationTitle(bits.join(" \xB7 ")), children: bits.join(" \xB7 ") }),
13436
+ expandable ? /* @__PURE__ */ jsx103("i", { className: "ph ph-caret-right fdc-bar-caret", "aria-hidden": "true" }) : null
13356
13437
  ]
13357
13438
  }
13358
13439
  ),
13359
13440
  extras
13360
13441
  ] }),
13361
- /* @__PURE__ */ jsx101(
13442
+ /* @__PURE__ */ jsx103(
13362
13443
  Popover,
13363
13444
  {
13364
13445
  open: open2,
@@ -13369,15 +13450,15 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
13369
13450
  maxHeight: 460,
13370
13451
  padded: true,
13371
13452
  label: "Usage",
13372
- footer: onClear ? /* @__PURE__ */ jsxs89("button", { type: "button", className: "fdc-usage-clear", onClick: () => {
13453
+ footer: onClear ? /* @__PURE__ */ jsxs90("button", { type: "button", className: "fdc-usage-clear", onClick: () => {
13373
13454
  setOpen(false);
13374
13455
  onClear();
13375
13456
  }, children: [
13376
- /* @__PURE__ */ jsx101("i", { className: "ph ph-trash", "aria-hidden": "true" }),
13457
+ /* @__PURE__ */ jsx103("i", { className: "ph ph-trash", "aria-hidden": "true" }),
13377
13458
  "Clear conversation"
13378
13459
  ] }) : void 0,
13379
- children: /* @__PURE__ */ jsxs89("div", { className: "fdc-usage", children: [
13380
- cu ? /* @__PURE__ */ jsx101("section", { className: "fdc-usage-sec", children: /* @__PURE__ */ jsx101(
13460
+ children: /* @__PURE__ */ jsxs90("div", { className: "fdc-usage", children: [
13461
+ cu ? /* @__PURE__ */ jsx103("section", { className: "fdc-usage-sec", children: /* @__PURE__ */ jsx103(
13381
13462
  SegmentedMeter,
13382
13463
  {
13383
13464
  total,
@@ -13389,9 +13470,9 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
13389
13470
  remainderLabel: "Free"
13390
13471
  }
13391
13472
  ) }) : null,
13392
- limits && limits.length ? /* @__PURE__ */ jsxs89("section", { className: "fdc-usage-sec", children: [
13393
- /* @__PURE__ */ jsx101("h4", { className: "fdc-usage-h", children: "Usage limits" }),
13394
- /* @__PURE__ */ jsx101("div", { className: "fdc-usage-rows", children: limits.map((l) => /* @__PURE__ */ jsx101(
13473
+ limits && limits.length ? /* @__PURE__ */ jsxs90("section", { className: "fdc-usage-sec", children: [
13474
+ /* @__PURE__ */ jsx103("h4", { className: "fdc-usage-h", children: "Usage limits" }),
13475
+ /* @__PURE__ */ jsx103("div", { className: "fdc-usage-rows", children: limits.map((l) => /* @__PURE__ */ jsx103(
13395
13476
  QuotaRow,
13396
13477
  {
13397
13478
  label: l.label,
@@ -13401,25 +13482,25 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
13401
13482
  l.id
13402
13483
  )) })
13403
13484
  ] }) : null,
13404
- stats ? /* @__PURE__ */ jsxs89("section", { className: "fdc-usage-sec fdc-usage-stats", children: [
13405
- stats.elapsedMs ? /* @__PURE__ */ jsxs89("div", { children: [
13406
- /* @__PURE__ */ jsx101("span", { children: "Session" }),
13407
- /* @__PURE__ */ jsx101("b", { className: "fd-tabular", children: formatDuration(stats.elapsedMs) })
13485
+ stats ? /* @__PURE__ */ jsxs90("section", { className: "fdc-usage-sec fdc-usage-stats", children: [
13486
+ stats.elapsedMs ? /* @__PURE__ */ jsxs90("div", { children: [
13487
+ /* @__PURE__ */ jsx103("span", { children: "Session" }),
13488
+ /* @__PURE__ */ jsx103("b", { className: "fd-tabular", children: formatDuration(stats.elapsedMs) })
13408
13489
  ] }) : null,
13409
- stats.tokens ? /* @__PURE__ */ jsxs89("div", { children: [
13410
- /* @__PURE__ */ jsx101("span", { children: "Tokens" }),
13411
- /* @__PURE__ */ jsx101("b", { className: "fd-tabular", children: stats.tokens.toLocaleString() })
13490
+ stats.tokens ? /* @__PURE__ */ jsxs90("div", { children: [
13491
+ /* @__PURE__ */ jsx103("span", { children: "Tokens" }),
13492
+ /* @__PURE__ */ jsx103("b", { className: "fd-tabular", children: stats.tokens.toLocaleString() })
13412
13493
  ] }) : null,
13413
- stats.costUsd != null ? /* @__PURE__ */ jsxs89("div", { children: [
13414
- /* @__PURE__ */ jsx101("span", { children: "Cost" }),
13415
- /* @__PURE__ */ jsxs89("b", { className: "fd-tabular", children: [
13494
+ stats.costUsd != null ? /* @__PURE__ */ jsxs90("div", { children: [
13495
+ /* @__PURE__ */ jsx103("span", { children: "Cost" }),
13496
+ /* @__PURE__ */ jsxs90("b", { className: "fd-tabular", children: [
13416
13497
  "$",
13417
13498
  Number(stats.costUsd).toFixed(3)
13418
13499
  ] })
13419
13500
  ] }) : null,
13420
- stats.turns ? /* @__PURE__ */ jsxs89("div", { children: [
13421
- /* @__PURE__ */ jsx101("span", { children: "Turns" }),
13422
- /* @__PURE__ */ jsx101("b", { className: "fd-tabular", children: stats.turns })
13501
+ stats.turns ? /* @__PURE__ */ jsxs90("div", { children: [
13502
+ /* @__PURE__ */ jsx103("span", { children: "Turns" }),
13503
+ /* @__PURE__ */ jsx103("b", { className: "fd-tabular", children: stats.turns })
13423
13504
  ] }) : null
13424
13505
  ] }) : null
13425
13506
  ] })
@@ -13458,7 +13539,7 @@ function ModelControls({
13458
13539
  disabled: m.disabled,
13459
13540
  checked: m.id === (current2 && current2.id),
13460
13541
  meta: m.meta,
13461
- shortcut: m.shortcut ? /* @__PURE__ */ jsx101(KeyHint, { keys: m.shortcut, size: "sm" }) : void 0,
13542
+ shortcut: m.shortcut ? /* @__PURE__ */ jsx103(KeyHint, { keys: m.shortcut, size: "sm" }) : void 0,
13462
13543
  onSelect: () => onModelChange && onModelChange(m.id)
13463
13544
  });
13464
13545
  const items = [{ kind: "section", label: "Models" }].concat(flat.map(item));
@@ -13471,15 +13552,15 @@ function ModelControls({
13471
13552
  items.push({ kind: "section", label: "Fast mode" });
13472
13553
  items.push({
13473
13554
  kind: "custom",
13474
- render: () => /* @__PURE__ */ jsxs89("label", { className: "fdc-switchrow", children: [
13475
- /* @__PURE__ */ jsx101("span", { children: fastModeLabel }),
13476
- /* @__PURE__ */ jsx101("input", { type: "checkbox", className: "fd-sr", checked: !!fastMode, onChange: (e) => onFastModeChange(e.target.checked) }),
13477
- /* @__PURE__ */ jsx101("span", { className: "fd-switch-track" + (fastMode ? " is-on" : ""), "aria-hidden": "true", children: /* @__PURE__ */ jsx101("span", { className: "fd-switch-thumb" }) })
13555
+ render: () => /* @__PURE__ */ jsxs90("label", { className: "fdc-switchrow", children: [
13556
+ /* @__PURE__ */ jsx103("span", { children: fastModeLabel }),
13557
+ /* @__PURE__ */ jsx103("input", { type: "checkbox", className: "fd-sr", checked: !!fastMode, onChange: (e) => onFastModeChange(e.target.checked) }),
13558
+ /* @__PURE__ */ jsx103("span", { className: "fd-switch-track" + (fastMode ? " is-on" : ""), "aria-hidden": "true", children: /* @__PURE__ */ jsx103("span", { className: "fd-switch-thumb" }) })
13478
13559
  ] })
13479
13560
  });
13480
13561
  }
13481
- return /* @__PURE__ */ jsxs89(React73.Fragment, { children: [
13482
- /* @__PURE__ */ jsx101(
13562
+ return /* @__PURE__ */ jsxs90(React74.Fragment, { children: [
13563
+ /* @__PURE__ */ jsx103(
13483
13564
  MenuButton,
13484
13565
  {
13485
13566
  items,
@@ -13490,7 +13571,7 @@ function ModelControls({
13490
13571
  title: "Choose a model"
13491
13572
  }
13492
13573
  ),
13493
- effortLevels && effortLevels.length ? /* @__PURE__ */ jsx101(
13574
+ effortLevels && effortLevels.length ? /* @__PURE__ */ jsx103(
13494
13575
  MenuButton,
13495
13576
  {
13496
13577
  placement: "top-end",
@@ -13511,7 +13592,7 @@ function ModelControls({
13511
13592
  }
13512
13593
 
13513
13594
  // src/components/chat/AgentChatPanel.tsx
13514
- import { jsx as jsx102, jsxs as jsxs90 } from "react/jsx-runtime";
13595
+ import { jsx as jsx104, jsxs as jsxs91 } from "react/jsx-runtime";
13515
13596
  var SURFACES = { sidebar: "is-sidebar", inline: "is-inline", page: "is-page", modal: "is-modal", sheet: "is-sheet" };
13516
13597
  function AgentChatPanel({
13517
13598
  /* required */
@@ -13545,6 +13626,7 @@ function AgentChatPanel({
13545
13626
  packetSchemas,
13546
13627
  packetRenderers,
13547
13628
  onApplyPacket,
13629
+ pendingTimeoutMs,
13548
13630
  onOpenAttachment,
13549
13631
  errorCopy,
13550
13632
  /* composer */
@@ -13595,17 +13677,18 @@ function AgentChatPanel({
13595
13677
  onFeedback,
13596
13678
  onEditMessage
13597
13679
  }) {
13598
- const [panelWidth, setPanelWidth] = React74.useState(width);
13599
- const [applied, setApplied] = React74.useState({});
13600
- const [draft, setDraft] = React74.useState("");
13601
- const dragging = React74.useRef(null);
13602
- React74.useEffect(() => setPanelWidth(width), [width]);
13680
+ const [panelWidth, setPanelWidth] = React75.useState(width);
13681
+ const [applied, setApplied] = React75.useState({});
13682
+ const [draft, setDraft] = React75.useState("");
13683
+ const dragging = React75.useRef(null);
13684
+ React75.useEffect(() => setPanelWidth(width), [width]);
13603
13685
  const engine = useChatEngine({
13604
13686
  contextType,
13605
13687
  contextId,
13606
13688
  apiAdapter,
13607
13689
  initialMessage,
13608
13690
  threadId,
13691
+ pendingTimeoutMs,
13609
13692
  onPacket,
13610
13693
  onThreadReady,
13611
13694
  onError,
@@ -13665,7 +13748,7 @@ function AgentChatPanel({
13665
13748
  onReconnect: engine.reload,
13666
13749
  deadTitle: "The assistant isn\u2019t reachable"
13667
13750
  };
13668
- const sessionBar = /* @__PURE__ */ jsx102(
13751
+ const sessionBar = /* @__PURE__ */ jsx104(
13669
13752
  ChatSessionBar,
13670
13753
  {
13671
13754
  sessionStats,
@@ -13674,7 +13757,7 @@ function AgentChatPanel({
13674
13757
  onClear: engine.visible.length ? engine.clear : void 0
13675
13758
  }
13676
13759
  );
13677
- const modelControls = /* @__PURE__ */ jsx102(
13760
+ const modelControls = /* @__PURE__ */ jsx104(
13678
13761
  ModelControls,
13679
13762
  {
13680
13763
  models,
@@ -13689,7 +13772,7 @@ function AgentChatPanel({
13689
13772
  narrow
13690
13773
  }
13691
13774
  );
13692
- const threadMenu = threads && threads.length ? /* @__PURE__ */ jsx102(
13775
+ const threadMenu = threads && threads.length ? /* @__PURE__ */ jsx104(
13693
13776
  MenuButton,
13694
13777
  {
13695
13778
  variant: "ghost",
@@ -13716,7 +13799,7 @@ function AgentChatPanel({
13716
13799
  })))
13717
13800
  }
13718
13801
  ) : null;
13719
- return /* @__PURE__ */ jsxs90(
13802
+ return /* @__PURE__ */ jsxs91(
13720
13803
  "aside",
13721
13804
  {
13722
13805
  className: ["fdc-panel", SURFACES[surface] || SURFACES.sidebar, narrow ? "is-narrow" : "", className].filter(Boolean).join(" "),
@@ -13727,7 +13810,7 @@ function AgentChatPanel({
13727
13810
  },
13728
13811
  "aria-label": title,
13729
13812
  children: [
13730
- surface === "sidebar" && resizable ? /* @__PURE__ */ jsx102(
13813
+ surface === "sidebar" && resizable ? /* @__PURE__ */ jsx104(
13731
13814
  "div",
13732
13815
  {
13733
13816
  className: "fdc-grip",
@@ -13742,20 +13825,20 @@ function AgentChatPanel({
13742
13825
  }
13743
13826
  }
13744
13827
  ) : null,
13745
- showHeader ? /* @__PURE__ */ jsxs90("header", { className: "fdc-head", children: [
13746
- /* @__PURE__ */ jsx102("span", { className: "fdc-head-mark", "aria-hidden": "true", children: /* @__PURE__ */ jsx102("i", { className: "ph ph-" + assistantIcon }) }),
13747
- /* @__PURE__ */ jsxs90("span", { className: "fdc-head-titles", children: [
13748
- /* @__PURE__ */ jsx102("span", { className: "fdc-head-title", title: truncationTitle(title), children: title }),
13749
- subtitle ? /* @__PURE__ */ jsx102("span", { className: "fdc-head-sub", title: truncationTitle(subtitle), children: subtitle }) : null
13828
+ showHeader ? /* @__PURE__ */ jsxs91("header", { className: "fdc-head", children: [
13829
+ /* @__PURE__ */ jsx104("span", { className: "fdc-head-mark", "aria-hidden": "true", children: /* @__PURE__ */ jsx104("i", { className: "ph ph-" + assistantIcon }) }),
13830
+ /* @__PURE__ */ jsxs91("span", { className: "fdc-head-titles", children: [
13831
+ /* @__PURE__ */ jsx104("span", { className: "fdc-head-title", title: truncationTitle(title), children: title }),
13832
+ subtitle ? /* @__PURE__ */ jsx104("span", { className: "fdc-head-sub", title: truncationTitle(subtitle), children: subtitle }) : null
13750
13833
  ] }),
13751
- /* @__PURE__ */ jsxs90("span", { className: "fdc-head-acts", children: [
13834
+ /* @__PURE__ */ jsxs91("span", { className: "fdc-head-acts", children: [
13752
13835
  headerActions,
13753
13836
  threadMenu,
13754
- onNewThread ? /* @__PURE__ */ jsx102("button", { type: "button", className: "fdc-iconbtn", onClick: onNewThread, "aria-label": "New conversation", title: "New conversation", children: /* @__PURE__ */ jsx102("i", { className: "ph ph-plus", "aria-hidden": "true" }) }) : null,
13755
- onClose ? /* @__PURE__ */ jsx102("button", { type: "button", className: "fdc-iconbtn", onClick: onClose, "aria-label": "Close panel", title: "Close", children: /* @__PURE__ */ jsx102("i", { className: "ph ph-x", "aria-hidden": "true" }) }) : null
13837
+ onNewThread ? /* @__PURE__ */ jsx104("button", { type: "button", className: "fdc-iconbtn", onClick: onNewThread, "aria-label": "New conversation", title: "New conversation", children: /* @__PURE__ */ jsx104("i", { className: "ph ph-plus", "aria-hidden": "true" }) }) : null,
13838
+ onClose ? /* @__PURE__ */ jsx104("button", { type: "button", className: "fdc-iconbtn", onClick: onClose, "aria-label": "Close panel", title: "Close", children: /* @__PURE__ */ jsx104("i", { className: "ph ph-x", "aria-hidden": "true" }) }) : null
13756
13839
  ] })
13757
13840
  ] }) : null,
13758
- /* @__PURE__ */ jsx102(
13841
+ /* @__PURE__ */ jsx104(
13759
13842
  ChatTranscript,
13760
13843
  {
13761
13844
  messages: engine.visible,
@@ -13770,7 +13853,7 @@ function AgentChatPanel({
13770
13853
  renderEmpty
13771
13854
  }
13772
13855
  ),
13773
- /* @__PURE__ */ jsx102(
13856
+ /* @__PURE__ */ jsx104(
13774
13857
  ChatComposer,
13775
13858
  {
13776
13859
  onSubmit: (text, atts) => engine.send(text, atts),
@@ -13803,8 +13886,8 @@ function AgentChatPanel({
13803
13886
  }
13804
13887
 
13805
13888
  // src/components/files/FileViewer.tsx
13806
- import * as React75 from "react";
13807
- import { jsx as jsx103, jsxs as jsxs91 } from "react/jsx-runtime";
13889
+ import * as React76 from "react";
13890
+ import { jsx as jsx105, jsxs as jsxs92 } from "react/jsx-runtime";
13808
13891
  function previewKindOf(file) {
13809
13892
  const mime = (file.mime || "").toLowerCase();
13810
13893
  const ext = extensionOf(file.name || "");
@@ -13860,13 +13943,13 @@ function parseDelimited(text, delimiter) {
13860
13943
  return rows;
13861
13944
  }
13862
13945
  function usePreview(file, kind, resolveUrl) {
13863
- const [state, setState] = React75.useState({ status: "loading" });
13864
- const [attempt, setAttempt] = React75.useState(0);
13865
- const resolveRef = React75.useRef(resolveUrl);
13866
- React75.useEffect(() => {
13946
+ const [state, setState] = React76.useState({ status: "loading" });
13947
+ const [attempt, setAttempt] = React76.useState(0);
13948
+ const resolveRef = React76.useRef(resolveUrl);
13949
+ React76.useEffect(() => {
13867
13950
  resolveRef.current = resolveUrl;
13868
13951
  }, [resolveUrl]);
13869
- React75.useEffect(() => {
13952
+ React76.useEffect(() => {
13870
13953
  if (kind === "none") {
13871
13954
  setState({ status: "ready" });
13872
13955
  return;
@@ -13896,19 +13979,19 @@ function usePreview(file, kind, resolveUrl) {
13896
13979
  if (ac) ac.abort();
13897
13980
  };
13898
13981
  }, [file.id, kind, attempt]);
13899
- return { ...state, retry: React75.useCallback(() => setAttempt((a) => a + 1), []) };
13982
+ return { ...state, retry: React76.useCallback(() => setAttempt((a) => a + 1), []) };
13900
13983
  }
13901
13984
  function PreviewBody({ file, kind, state }) {
13902
- if (kind === "image") return /* @__PURE__ */ jsx103("img", { className: "fd-fv-image", src: state.url, alt: file.name || "Preview" });
13903
- if (kind === "pdf") return /* @__PURE__ */ jsx103("iframe", { className: "fd-fv-pdf", src: state.url, title: file.name || "PDF preview" });
13904
- if (kind === "markdown") return /* @__PURE__ */ jsx103(Markdown, { className: "fd-fv-markdown", source: state.text || "" });
13985
+ if (kind === "image") return /* @__PURE__ */ jsx105("img", { className: "fd-fv-image", src: state.url, alt: file.name || "Preview" });
13986
+ if (kind === "pdf") return /* @__PURE__ */ jsx105("iframe", { className: "fd-fv-pdf", src: state.url, title: file.name || "PDF preview" });
13987
+ if (kind === "markdown") return /* @__PURE__ */ jsx105(Markdown, { className: "fd-fv-markdown", source: state.text || "" });
13905
13988
  if (kind === "json") {
13906
13989
  let pretty = state.text || "";
13907
13990
  try {
13908
13991
  pretty = JSON.stringify(JSON.parse(pretty), null, 2);
13909
13992
  } catch {
13910
13993
  }
13911
- return /* @__PURE__ */ jsx103(CodeBlock, { code: pretty, language: "json" });
13994
+ return /* @__PURE__ */ jsx105(CodeBlock, { code: pretty, language: "json" });
13912
13995
  }
13913
13996
  if (kind === "csv") {
13914
13997
  const tsv = extensionOf(file.name || "") === "tsv" || (file.mime || "").toLowerCase().includes("tab-separated");
@@ -13916,12 +13999,12 @@ function PreviewBody({ file, kind, state }) {
13916
13999
  const head = rows[0] || [];
13917
14000
  const dataRows = rows.slice(1);
13918
14001
  const shown = dataRows.slice(0, FILE_VIEWER_CSV_ROW_LIMIT);
13919
- return /* @__PURE__ */ jsxs91("div", { className: "fd-fv-csv", children: [
13920
- /* @__PURE__ */ jsxs91("table", { className: "fd-fv-csv-table", children: [
13921
- /* @__PURE__ */ jsx103("thead", { children: /* @__PURE__ */ jsx103("tr", { children: head.map((c, i) => /* @__PURE__ */ jsx103("th", { children: c }, i)) }) }),
13922
- /* @__PURE__ */ jsx103("tbody", { children: shown.map((r, ri) => /* @__PURE__ */ jsx103("tr", { children: head.map((_, ci) => /* @__PURE__ */ jsx103("td", { children: r[ci] ?? "" }, ci)) }, ri)) })
14002
+ return /* @__PURE__ */ jsxs92("div", { className: "fd-fv-csv", children: [
14003
+ /* @__PURE__ */ jsxs92("table", { className: "fd-fv-csv-table", children: [
14004
+ /* @__PURE__ */ jsx105("thead", { children: /* @__PURE__ */ jsx105("tr", { children: head.map((c, i) => /* @__PURE__ */ jsx105("th", { children: c }, i)) }) }),
14005
+ /* @__PURE__ */ jsx105("tbody", { children: shown.map((r, ri) => /* @__PURE__ */ jsx105("tr", { children: head.map((_, ci) => /* @__PURE__ */ jsx105("td", { children: r[ci] ?? "" }, ci)) }, ri)) })
13923
14006
  ] }),
13924
- dataRows.length > FILE_VIEWER_CSV_ROW_LIMIT ? /* @__PURE__ */ jsxs91("p", { className: "fd-fv-csv-note fd-body-sm fd-muted", children: [
14007
+ dataRows.length > FILE_VIEWER_CSV_ROW_LIMIT ? /* @__PURE__ */ jsxs92("p", { className: "fd-fv-csv-note fd-body-sm fd-muted", children: [
13925
14008
  "Showing the first ",
13926
14009
  FILE_VIEWER_CSV_ROW_LIMIT.toLocaleString(),
13927
14010
  " of ",
@@ -13930,24 +14013,24 @@ function PreviewBody({ file, kind, state }) {
13930
14013
  ] }) : null
13931
14014
  ] });
13932
14015
  }
13933
- if (kind === "text") return /* @__PURE__ */ jsx103(CodeBlock, { code: state.text || "", language: extensionOf(file.name || "") || void 0 });
13934
- return /* @__PURE__ */ jsxs91("div", { className: "fd-fv-fallback", children: [
13935
- /* @__PURE__ */ jsx103("span", { className: "fd-fv-fallback-icon", "aria-hidden": "true", children: /* @__PURE__ */ jsx103("i", { className: "ph ph-" + iconForMime(file.mime, file.name) }) }),
13936
- /* @__PURE__ */ jsx103("span", { className: "fd-fv-fallback-title", children: "No preview available" }),
13937
- /* @__PURE__ */ jsxs91("span", { className: "fd-fv-fallback-meta", children: [
14016
+ if (kind === "text") return /* @__PURE__ */ jsx105(CodeBlock, { code: state.text || "", language: extensionOf(file.name || "") || void 0 });
14017
+ return /* @__PURE__ */ jsxs92("div", { className: "fd-fv-fallback", children: [
14018
+ /* @__PURE__ */ jsx105("span", { className: "fd-fv-fallback-icon", "aria-hidden": "true", children: /* @__PURE__ */ jsx105("i", { className: "ph ph-" + iconForMime(file.mime, file.name) }) }),
14019
+ /* @__PURE__ */ jsx105("span", { className: "fd-fv-fallback-title", children: "No preview available" }),
14020
+ /* @__PURE__ */ jsxs92("span", { className: "fd-fv-fallback-meta", children: [
13938
14021
  file.mime || "Unknown type",
13939
14022
  file.size ? " \xB7 " + formatBytes(file.size) : ""
13940
14023
  ] })
13941
14024
  ] });
13942
14025
  }
13943
14026
  function FileViewer({ file, resolveUrl, sidePanel, sidePanelLabel = "Details", onClose, actions, className = "" }) {
13944
- const kind = React75.useMemo(() => previewKindOf(file), [file]);
14027
+ const kind = React76.useMemo(() => previewKindOf(file), [file]);
13945
14028
  const preview = usePreview(file, kind, resolveUrl);
13946
- const [tab, setTab] = React75.useState("preview");
13947
- const [downloading, setDownloading] = React75.useState(false);
13948
- const [downloadError, setDownloadError] = React75.useState(null);
14029
+ const [tab, setTab] = React76.useState("preview");
14030
+ const [downloading, setDownloading] = React76.useState(false);
14031
+ const [downloadError, setDownloadError] = React76.useState(null);
13949
14032
  const hasSide = sidePanel != null;
13950
- React75.useEffect(() => {
14033
+ React76.useEffect(() => {
13951
14034
  setTab("preview");
13952
14035
  }, [file.id]);
13953
14036
  const download = () => {
@@ -13963,29 +14046,29 @@ function FileViewer({ file, resolveUrl, sidePanel, sidePanelLabel = "Details", o
13963
14046
  a.remove();
13964
14047
  }).catch((err) => setDownloadError(err && err.message || "Download failed.")).finally(() => setDownloading(false));
13965
14048
  };
13966
- return /* @__PURE__ */ jsxs91(
14049
+ return /* @__PURE__ */ jsxs92(
13967
14050
  "section",
13968
14051
  {
13969
14052
  className: ["fd-fv", hasSide && tab === "side" ? "is-tab-side" : "is-tab-preview", className].filter(Boolean).join(" "),
13970
14053
  "aria-label": file.name || "File",
13971
14054
  children: [
13972
- /* @__PURE__ */ jsxs91("header", { className: "fd-fv-head", children: [
13973
- /* @__PURE__ */ jsx103("span", { className: "fd-fv-head-icon", "aria-hidden": "true", children: /* @__PURE__ */ jsx103("i", { className: "ph ph-" + iconForMime(file.mime, file.name) }) }),
13974
- /* @__PURE__ */ jsxs91("span", { className: "fd-fv-head-titles", children: [
13975
- /* @__PURE__ */ jsx103("span", { className: "fd-fv-head-title", title: file.name, children: file.name }),
13976
- /* @__PURE__ */ jsxs91("span", { className: "fd-fv-head-meta", children: [
14055
+ /* @__PURE__ */ jsxs92("header", { className: "fd-fv-head", children: [
14056
+ /* @__PURE__ */ jsx105("span", { className: "fd-fv-head-icon", "aria-hidden": "true", children: /* @__PURE__ */ jsx105("i", { className: "ph ph-" + iconForMime(file.mime, file.name) }) }),
14057
+ /* @__PURE__ */ jsxs92("span", { className: "fd-fv-head-titles", children: [
14058
+ /* @__PURE__ */ jsx105("span", { className: "fd-fv-head-title", title: file.name, children: file.name }),
14059
+ /* @__PURE__ */ jsxs92("span", { className: "fd-fv-head-meta", children: [
13977
14060
  file.mime || "Unknown type",
13978
14061
  file.size ? " \xB7 " + formatBytes(file.size) : ""
13979
14062
  ] })
13980
14063
  ] }),
13981
- /* @__PURE__ */ jsxs91("span", { className: "fd-fv-head-actions", children: [
14064
+ /* @__PURE__ */ jsxs92("span", { className: "fd-fv-head-actions", children: [
13982
14065
  actions,
13983
- /* @__PURE__ */ jsx103(Button, { variant: "secondary", size: "sm", icon: "download-simple", loading: downloading, onClick: download, children: "Download" }),
13984
- onClose ? /* @__PURE__ */ jsx103(IconButton, { icon: "x", label: "Close", onClick: onClose }) : null
14066
+ /* @__PURE__ */ jsx105(Button, { variant: "secondary", size: "sm", icon: "download-simple", loading: downloading, onClick: download, children: "Download" }),
14067
+ onClose ? /* @__PURE__ */ jsx105(IconButton, { icon: "x", label: "Close", onClick: onClose }) : null
13985
14068
  ] })
13986
14069
  ] }),
13987
- downloadError ? /* @__PURE__ */ jsx103("div", { className: "fd-fv-download-error", role: "alert", children: downloadError }) : null,
13988
- hasSide ? /* @__PURE__ */ jsx103(
14070
+ downloadError ? /* @__PURE__ */ jsx105("div", { className: "fd-fv-download-error", role: "alert", children: downloadError }) : null,
14071
+ hasSide ? /* @__PURE__ */ jsx105(
13989
14072
  Tabs,
13990
14073
  {
13991
14074
  className: "fd-fv-tabs",
@@ -13994,19 +14077,19 @@ function FileViewer({ file, resolveUrl, sidePanel, sidePanelLabel = "Details", o
13994
14077
  onChange: (v) => setTab(v)
13995
14078
  }
13996
14079
  ) : null,
13997
- /* @__PURE__ */ jsxs91("div", { className: "fd-fv-body", children: [
13998
- /* @__PURE__ */ jsx103("div", { className: "fd-fv-preview", role: "region", "aria-label": "Preview of " + (file.name || "file"), children: /* @__PURE__ */ jsx103(
14080
+ /* @__PURE__ */ jsxs92("div", { className: "fd-fv-body", children: [
14081
+ /* @__PURE__ */ jsx105("div", { className: "fd-fv-preview", role: "region", "aria-label": "Preview of " + (file.name || "file"), children: /* @__PURE__ */ jsx105(
13999
14082
  LoadingRegion,
14000
14083
  {
14001
14084
  state: preview.status === "loading" ? "loading" : preview.status === "error" ? "error" : "ready",
14002
14085
  error: preview.error,
14003
14086
  label: "Loading preview of " + (file.name || "file"),
14004
14087
  onRetry: preview.status === "error" ? preview.retry : void 0,
14005
- skeleton: /* @__PURE__ */ jsx103(Skeleton, { shape: "card", h: 220 }),
14006
- children: /* @__PURE__ */ jsx103(PreviewBody, { file, kind, state: preview })
14088
+ skeleton: /* @__PURE__ */ jsx105(Skeleton, { shape: "card", h: 220 }),
14089
+ children: /* @__PURE__ */ jsx105(PreviewBody, { file, kind, state: preview })
14007
14090
  }
14008
14091
  ) }),
14009
- hasSide ? /* @__PURE__ */ jsx103("div", { className: "fd-fv-side", role: "region", "aria-label": sidePanelLabel, children: sidePanel }) : null
14092
+ hasSide ? /* @__PURE__ */ jsx105("div", { className: "fd-fv-side", role: "region", "aria-label": sidePanelLabel, children: sidePanel }) : null
14010
14093
  ] })
14011
14094
  ]
14012
14095
  }
@@ -14014,8 +14097,8 @@ function FileViewer({ file, resolveUrl, sidePanel, sidePanelLabel = "Details", o
14014
14097
  }
14015
14098
 
14016
14099
  // src/components/files/FileBrowser.tsx
14017
- import * as React76 from "react";
14018
- import { Fragment as Fragment31, jsx as jsx104, jsxs as jsxs92 } from "react/jsx-runtime";
14100
+ import * as React77 from "react";
14101
+ import { Fragment as Fragment31, jsx as jsx106, jsxs as jsxs93 } from "react/jsx-runtime";
14019
14102
  function childrenOf(folders, parentId) {
14020
14103
  return folders.filter((f) => f.parentId === parentId).sort((a, b) => a.name.localeCompare(b.name));
14021
14104
  }
@@ -14087,8 +14170,8 @@ function FolderPickerMenu({
14087
14170
  }) {
14088
14171
  const panel = useInlinePanel();
14089
14172
  const { open: open2, setOpen, ref } = panel;
14090
- return /* @__PURE__ */ jsxs92("span", { className: "fd-fb-menu-anchor", ref, children: [
14091
- /* @__PURE__ */ jsx104(
14173
+ return /* @__PURE__ */ jsxs93("span", { className: "fd-fb-menu-anchor", ref, children: [
14174
+ /* @__PURE__ */ jsx106(
14092
14175
  IconButton,
14093
14176
  {
14094
14177
  icon: "arrows-out-cardinal",
@@ -14100,9 +14183,9 @@ function FolderPickerMenu({
14100
14183
  onClick: () => setOpen((v) => !v)
14101
14184
  }
14102
14185
  ),
14103
- /* @__PURE__ */ jsx104(InlinePanelSurface, { panel, align: "right", offset: 4, width: 220, maxHeight: 280, role: "menu", label, children: /* @__PURE__ */ jsxs92("div", { className: "fd-fb-menu", children: [
14104
- /* @__PURE__ */ jsx104("span", { className: "fd-overline fd-muted fd-fb-menu-title", children: "Move to\u2026" }),
14105
- destinations.map((d) => /* @__PURE__ */ jsxs92(
14186
+ /* @__PURE__ */ jsx106(InlinePanelSurface, { panel, align: "right", offset: 4, width: 220, maxHeight: 280, role: "menu", label, children: /* @__PURE__ */ jsxs93("div", { className: "fd-fb-menu", children: [
14187
+ /* @__PURE__ */ jsx106("span", { className: "fd-overline fd-muted fd-fb-menu-title", children: "Move to\u2026" }),
14188
+ destinations.map((d) => /* @__PURE__ */ jsxs93(
14106
14189
  "button",
14107
14190
  {
14108
14191
  type: "button",
@@ -14114,7 +14197,7 @@ function FolderPickerMenu({
14114
14197
  setOpen(false);
14115
14198
  },
14116
14199
  children: [
14117
- /* @__PURE__ */ jsx104("i", { className: "ph ph-" + (d.id == null ? "house-simple" : "folder-simple"), "aria-hidden": "true" }),
14200
+ /* @__PURE__ */ jsx106("i", { className: "ph ph-" + (d.id == null ? "house-simple" : "folder-simple"), "aria-hidden": "true" }),
14118
14201
  d.name
14119
14202
  ]
14120
14203
  },
@@ -14124,8 +14207,8 @@ function FolderPickerMenu({
14124
14207
  ] });
14125
14208
  }
14126
14209
  function RowShell({ icon, name, meta, onOpen, draggableId, isDropTarget, onDropPayload, actions, className = "" }) {
14127
- const [over, setOver] = React76.useState(false);
14128
- const dragCounter = React76.useRef(0);
14210
+ const [over, setOver] = React77.useState(false);
14211
+ const dragCounter = React77.useRef(0);
14129
14212
  const dropHandlers = isDropTarget ? {
14130
14213
  onDragEnter: (e) => {
14131
14214
  if (!hasInternalPayload(e)) return;
@@ -14150,8 +14233,8 @@ function RowShell({ icon, name, meta, onOpen, draggableId, isDropTarget, onDropP
14150
14233
  if (payload && onDropPayload) onDropPayload(payload);
14151
14234
  }
14152
14235
  } : {};
14153
- return /* @__PURE__ */ jsxs92("div", { className: ["fd-fb-row", over ? "is-drop-target" : "", className].filter(Boolean).join(" "), ...dropHandlers, children: [
14154
- /* @__PURE__ */ jsxs92(
14236
+ return /* @__PURE__ */ jsxs93("div", { className: ["fd-fb-row", over ? "is-drop-target" : "", className].filter(Boolean).join(" "), ...dropHandlers, children: [
14237
+ /* @__PURE__ */ jsxs93(
14155
14238
  "button",
14156
14239
  {
14157
14240
  type: "button",
@@ -14160,26 +14243,26 @@ function RowShell({ icon, name, meta, onOpen, draggableId, isDropTarget, onDropP
14160
14243
  draggable: !!draggableId,
14161
14244
  onDragStart: draggableId ? (e) => writeDragPayload(e, draggableId) : void 0,
14162
14245
  children: [
14163
- /* @__PURE__ */ jsx104("span", { className: "fd-fb-row-icon", "aria-hidden": "true", children: /* @__PURE__ */ jsx104("i", { className: "ph ph-" + icon }) }),
14164
- /* @__PURE__ */ jsxs92("span", { className: "fd-fb-row-text", children: [
14165
- /* @__PURE__ */ jsx104("span", { className: "fd-fb-row-name", title: name, children: name }),
14166
- meta ? /* @__PURE__ */ jsx104("span", { className: "fd-fb-row-meta", children: meta }) : null
14246
+ /* @__PURE__ */ jsx106("span", { className: "fd-fb-row-icon", "aria-hidden": "true", children: /* @__PURE__ */ jsx106("i", { className: "ph ph-" + icon }) }),
14247
+ /* @__PURE__ */ jsxs93("span", { className: "fd-fb-row-text", children: [
14248
+ /* @__PURE__ */ jsx106("span", { className: "fd-fb-row-name", title: name, children: name }),
14249
+ meta ? /* @__PURE__ */ jsx106("span", { className: "fd-fb-row-meta", children: meta }) : null
14167
14250
  ] })
14168
14251
  ]
14169
14252
  }
14170
14253
  ),
14171
- actions ? /* @__PURE__ */ jsx104("span", { className: "fd-fb-row-actions", children: actions }) : null
14254
+ actions ? /* @__PURE__ */ jsx106("span", { className: "fd-fb-row-actions", children: actions }) : null
14172
14255
  ] });
14173
14256
  }
14174
14257
  function TreeNode({ folder, depth, folders, currentFolderId, onNavigate, onMoveInto, canMove }) {
14175
14258
  const kids = childrenOf(folders, folder.id);
14176
- const [expanded, setExpanded] = React76.useState(() => currentFolderId != null && isSelfOrDescendant(folders, folder.id, currentFolderId));
14177
- React76.useEffect(() => {
14259
+ const [expanded, setExpanded] = React77.useState(() => currentFolderId != null && isSelfOrDescendant(folders, folder.id, currentFolderId));
14260
+ React77.useEffect(() => {
14178
14261
  if (currentFolderId != null && isSelfOrDescendant(folders, folder.id, currentFolderId)) setExpanded(true);
14179
14262
  }, [currentFolderId, folder.id, folders]);
14180
14263
  const isCurrent = folder.id === currentFolderId;
14181
- return /* @__PURE__ */ jsxs92("div", { className: "fd-fb-tree-node", children: [
14182
- /* @__PURE__ */ jsx104(
14264
+ return /* @__PURE__ */ jsxs93("div", { className: "fd-fb-tree-node", children: [
14265
+ /* @__PURE__ */ jsx106(
14183
14266
  RowShell,
14184
14267
  {
14185
14268
  icon: folder.id === currentFolderId ? "folder-open" : "folder-simple",
@@ -14189,7 +14272,7 @@ function TreeNode({ folder, depth, folders, currentFolderId, onNavigate, onMoveI
14189
14272
  isDropTarget: canMove,
14190
14273
  onDropPayload: (payload) => onMoveInto(payload, folder.id),
14191
14274
  className: ["fd-fb-tree-row", isCurrent ? "is-current" : ""].filter(Boolean).join(" "),
14192
- actions: kids.length ? /* @__PURE__ */ jsx104(
14275
+ actions: kids.length ? /* @__PURE__ */ jsx106(
14193
14276
  IconButton,
14194
14277
  {
14195
14278
  icon: expanded ? "caret-down" : "caret-right",
@@ -14201,7 +14284,7 @@ function TreeNode({ folder, depth, folders, currentFolderId, onNavigate, onMoveI
14201
14284
  ) : void 0
14202
14285
  }
14203
14286
  ),
14204
- expanded && kids.length ? /* @__PURE__ */ jsx104("div", { className: "fd-fb-tree-children", style: { paddingLeft: 14 }, children: kids.map((k) => /* @__PURE__ */ jsx104(
14287
+ expanded && kids.length ? /* @__PURE__ */ jsx106("div", { className: "fd-fb-tree-children", style: { paddingLeft: 14 }, children: kids.map((k) => /* @__PURE__ */ jsx106(
14205
14288
  TreeNode,
14206
14289
  {
14207
14290
  folder: k,
@@ -14240,15 +14323,15 @@ function FileBrowser({
14240
14323
  const canUpload = perm.canUpload !== false && !!onUpload;
14241
14324
  const canRemoveFile = perm.canRemoveFile !== false && !!onRemoveFile;
14242
14325
  const canDeleteFolder = perm.canDeleteFolder !== false && !!onDeleteFolder;
14243
- const [createOpen, setCreateOpen] = React76.useState(false);
14244
- const [createName, setCreateName] = React76.useState("");
14245
- const [renameTarget, setRenameTarget] = React76.useState(null);
14246
- const [renameValue, setRenameValue] = React76.useState("");
14247
- const [deleteTarget, setDeleteTarget] = React76.useState(null);
14248
- const uploadInputRef = React76.useRef(null);
14249
- const crumbFolders = React76.useMemo(() => ancestorsOf(folders, currentFolderId), [folders, currentFolderId]);
14250
- const subfolders = React76.useMemo(() => childrenOf(folders, currentFolderId), [folders, currentFolderId]);
14251
- const currentFiles = React76.useMemo(
14326
+ const [createOpen, setCreateOpen] = React77.useState(false);
14327
+ const [createName, setCreateName] = React77.useState("");
14328
+ const [renameTarget, setRenameTarget] = React77.useState(null);
14329
+ const [renameValue, setRenameValue] = React77.useState("");
14330
+ const [deleteTarget, setDeleteTarget] = React77.useState(null);
14331
+ const uploadInputRef = React77.useRef(null);
14332
+ const crumbFolders = React77.useMemo(() => ancestorsOf(folders, currentFolderId), [folders, currentFolderId]);
14333
+ const subfolders = React77.useMemo(() => childrenOf(folders, currentFolderId), [folders, currentFolderId]);
14334
+ const currentFiles = React77.useMemo(
14252
14335
  () => files.filter((f) => f.folderId === currentFolderId).sort((a, b) => a.name.localeCompare(b.name)),
14253
14336
  [files, currentFolderId]
14254
14337
  );
@@ -14287,10 +14370,10 @@ function FileBrowser({
14287
14370
  if (deleteTarget && onDeleteFolder) onDeleteFolder(deleteTarget);
14288
14371
  setDeleteTarget(null);
14289
14372
  };
14290
- const content = /* @__PURE__ */ jsxs92("div", { className: ["fd-fb", className].filter(Boolean).join(" "), children: [
14291
- /* @__PURE__ */ jsxs92("div", { className: "fd-fb-head", children: [
14292
- /* @__PURE__ */ jsxs92("nav", { className: "fd-fb-crumbs", "aria-label": "Folder path", children: [
14293
- /* @__PURE__ */ jsx104(
14373
+ const content = /* @__PURE__ */ jsxs93("div", { className: ["fd-fb", className].filter(Boolean).join(" "), children: [
14374
+ /* @__PURE__ */ jsxs93("div", { className: "fd-fb-head", children: [
14375
+ /* @__PURE__ */ jsxs93("nav", { className: "fd-fb-crumbs", "aria-label": "Folder path", children: [
14376
+ /* @__PURE__ */ jsx106(
14294
14377
  BreadcrumbCrumb,
14295
14378
  {
14296
14379
  label: "Home",
@@ -14300,7 +14383,7 @@ function FileBrowser({
14300
14383
  onDropPayload: (p) => moveIntoFolder(p, null)
14301
14384
  }
14302
14385
  ),
14303
- crumbFolders.map((f, i) => /* @__PURE__ */ jsx104(
14386
+ crumbFolders.map((f, i) => /* @__PURE__ */ jsx106(
14304
14387
  BreadcrumbCrumb,
14305
14388
  {
14306
14389
  label: f.name,
@@ -14312,11 +14395,11 @@ function FileBrowser({
14312
14395
  f.id
14313
14396
  ))
14314
14397
  ] }),
14315
- /* @__PURE__ */ jsxs92("span", { className: "fd-fb-actions", children: [
14316
- canCreateFolder ? /* @__PURE__ */ jsx104(Button, { variant: "secondary", size: "sm", icon: "folder-simple-plus", onClick: openCreate, children: "New folder" }) : null,
14317
- canUpload ? /* @__PURE__ */ jsxs92(Fragment31, { children: [
14318
- /* @__PURE__ */ jsx104(Button, { variant: "secondary", size: "sm", icon: "upload-simple", onClick: () => uploadInputRef.current && uploadInputRef.current.click(), children: "Upload" }),
14319
- /* @__PURE__ */ jsx104(
14398
+ /* @__PURE__ */ jsxs93("span", { className: "fd-fb-actions", children: [
14399
+ canCreateFolder ? /* @__PURE__ */ jsx106(Button, { variant: "secondary", size: "sm", icon: "folder-simple-plus", onClick: openCreate, children: "New folder" }) : null,
14400
+ canUpload ? /* @__PURE__ */ jsxs93(Fragment31, { children: [
14401
+ /* @__PURE__ */ jsx106(Button, { variant: "secondary", size: "sm", icon: "upload-simple", onClick: () => uploadInputRef.current && uploadInputRef.current.click(), children: "Upload" }),
14402
+ /* @__PURE__ */ jsx106(
14320
14403
  "input",
14321
14404
  {
14322
14405
  ref: uploadInputRef,
@@ -14334,9 +14417,9 @@ function FileBrowser({
14334
14417
  ] }) : null
14335
14418
  ] })
14336
14419
  ] }),
14337
- /* @__PURE__ */ jsxs92("div", { className: "fd-fb-body", children: [
14338
- /* @__PURE__ */ jsxs92("div", { className: "fd-fb-tree", role: "region", "aria-label": "Folder tree", children: [
14339
- /* @__PURE__ */ jsx104(
14420
+ /* @__PURE__ */ jsxs93("div", { className: "fd-fb-body", children: [
14421
+ /* @__PURE__ */ jsxs93("div", { className: "fd-fb-tree", role: "region", "aria-label": "Folder tree", children: [
14422
+ /* @__PURE__ */ jsx106(
14340
14423
  RowShell,
14341
14424
  {
14342
14425
  icon: "house-simple",
@@ -14347,7 +14430,7 @@ function FileBrowser({
14347
14430
  className: ["fd-fb-tree-row", currentFolderId == null ? "is-current" : ""].filter(Boolean).join(" ")
14348
14431
  }
14349
14432
  ),
14350
- childrenOf(folders, null).map((f) => /* @__PURE__ */ jsx104(
14433
+ childrenOf(folders, null).map((f) => /* @__PURE__ */ jsx106(
14351
14434
  TreeNode,
14352
14435
  {
14353
14436
  folder: f,
@@ -14361,18 +14444,18 @@ function FileBrowser({
14361
14444
  f.id
14362
14445
  ))
14363
14446
  ] }),
14364
- /* @__PURE__ */ jsx104("div", { className: "fd-fb-main", role: "region", "aria-label": "Folder contents", children: /* @__PURE__ */ jsx104(
14447
+ /* @__PURE__ */ jsx106("div", { className: "fd-fb-main", role: "region", "aria-label": "Folder contents", children: /* @__PURE__ */ jsx106(
14365
14448
  LoadingRegion,
14366
14449
  {
14367
14450
  state: loading ? "loading" : "ready",
14368
14451
  label: "Loading folder contents",
14369
- skeleton: /* @__PURE__ */ jsxs92("div", { className: "fd-stack", style: { gap: 8, padding: 12 }, children: [
14370
- /* @__PURE__ */ jsx104(Skeleton, { h: 44, radius: "10px" }),
14371
- /* @__PURE__ */ jsx104(Skeleton, { h: 44, radius: "10px" }),
14372
- /* @__PURE__ */ jsx104(Skeleton, { h: 44, radius: "10px" })
14452
+ skeleton: /* @__PURE__ */ jsxs93("div", { className: "fd-stack", style: { gap: 8, padding: 12 }, children: [
14453
+ /* @__PURE__ */ jsx106(Skeleton, { h: 44, radius: "10px" }),
14454
+ /* @__PURE__ */ jsx106(Skeleton, { h: 44, radius: "10px" }),
14455
+ /* @__PURE__ */ jsx106(Skeleton, { h: 44, radius: "10px" })
14373
14456
  ] }),
14374
- children: isEmpty ? /* @__PURE__ */ jsx104(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__ */ jsxs92("div", { className: "fd-fb-list", children: [
14375
- subfolders.map((f) => /* @__PURE__ */ jsx104(
14457
+ children: isEmpty ? /* @__PURE__ */ jsx106(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__ */ jsxs93("div", { className: "fd-fb-list", children: [
14458
+ subfolders.map((f) => /* @__PURE__ */ jsx106(
14376
14459
  RowShell,
14377
14460
  {
14378
14461
  icon: "folder-simple",
@@ -14381,9 +14464,9 @@ function FileBrowser({
14381
14464
  draggableId: canMove ? { kind: "folder", id: f.id } : void 0,
14382
14465
  isDropTarget: canMove,
14383
14466
  onDropPayload: (p) => moveIntoFolder(p, f.id),
14384
- actions: /* @__PURE__ */ jsxs92(Fragment31, { children: [
14385
- canRenameFolder ? /* @__PURE__ */ jsx104(IconButton, { icon: "pencil-simple", label: "Rename " + f.name, size: "sm", variant: "ghost", onClick: () => openRename(f) }) : null,
14386
- canMove ? /* @__PURE__ */ jsx104(
14467
+ actions: /* @__PURE__ */ jsxs93(Fragment31, { children: [
14468
+ canRenameFolder ? /* @__PURE__ */ jsx106(IconButton, { icon: "pencil-simple", label: "Rename " + f.name, size: "sm", variant: "ghost", onClick: () => openRename(f) }) : null,
14469
+ canMove ? /* @__PURE__ */ jsx106(
14387
14470
  FolderPickerMenu,
14388
14471
  {
14389
14472
  label: "Move " + f.name,
@@ -14391,12 +14474,12 @@ function FileBrowser({
14391
14474
  onPick: (target) => moveIntoFolder({ kind: "folder", id: f.id }, target)
14392
14475
  }
14393
14476
  ) : null,
14394
- canDeleteFolder ? /* @__PURE__ */ jsx104(IconButton, { icon: "trash-simple", label: "Delete " + f.name, size: "sm", variant: "ghost", onClick: () => openDelete(f) }) : null
14477
+ canDeleteFolder ? /* @__PURE__ */ jsx106(IconButton, { icon: "trash-simple", label: "Delete " + f.name, size: "sm", variant: "ghost", onClick: () => openDelete(f) }) : null
14395
14478
  ] })
14396
14479
  },
14397
14480
  f.id
14398
14481
  )),
14399
- currentFiles.map((file) => /* @__PURE__ */ jsx104(
14482
+ currentFiles.map((file) => /* @__PURE__ */ jsx106(
14400
14483
  RowShell,
14401
14484
  {
14402
14485
  icon: iconForMime(file.mime, file.name),
@@ -14404,8 +14487,8 @@ function FileBrowser({
14404
14487
  meta: file.size ? formatBytes(file.size) : void 0,
14405
14488
  onOpen: onOpenFile ? () => onOpenFile(file) : void 0,
14406
14489
  draggableId: canMove ? { kind: "file", id: file.id } : void 0,
14407
- actions: /* @__PURE__ */ jsxs92(Fragment31, { children: [
14408
- canMove ? /* @__PURE__ */ jsx104(
14490
+ actions: /* @__PURE__ */ jsxs93(Fragment31, { children: [
14491
+ canMove ? /* @__PURE__ */ jsx106(
14409
14492
  FolderPickerMenu,
14410
14493
  {
14411
14494
  label: "Move " + file.name,
@@ -14413,7 +14496,7 @@ function FileBrowser({
14413
14496
  onPick: (target) => onMoveFile && onMoveFile(file.id, target)
14414
14497
  }
14415
14498
  ) : null,
14416
- canRemoveFile ? /* @__PURE__ */ jsx104(IconButton, { icon: "trash-simple", label: "Remove " + file.name, size: "sm", variant: "ghost", onClick: () => onRemoveFile && onRemoveFile(file) }) : null
14499
+ canRemoveFile ? /* @__PURE__ */ jsx106(IconButton, { icon: "trash-simple", label: "Remove " + file.name, size: "sm", variant: "ghost", onClick: () => onRemoveFile && onRemoveFile(file) }) : null
14417
14500
  ] })
14418
14501
  },
14419
14502
  file.id
@@ -14422,10 +14505,10 @@ function FileBrowser({
14422
14505
  }
14423
14506
  ) })
14424
14507
  ] }),
14425
- /* @__PURE__ */ jsx104(Modal, { open: createOpen, title: "New folder", onClose: () => setCreateOpen(false), footer: /* @__PURE__ */ jsxs92(Fragment31, { children: [
14426
- /* @__PURE__ */ jsx104(Button, { variant: "secondary", onClick: () => setCreateOpen(false), children: "Cancel" }),
14427
- /* @__PURE__ */ jsx104(Button, { onClick: submitCreate, disabled: !createName.trim(), children: "Create" })
14428
- ] }), children: /* @__PURE__ */ jsx104(
14508
+ /* @__PURE__ */ jsx106(Modal, { open: createOpen, title: "New folder", onClose: () => setCreateOpen(false), footer: /* @__PURE__ */ jsxs93(Fragment31, { children: [
14509
+ /* @__PURE__ */ jsx106(Button, { variant: "secondary", onClick: () => setCreateOpen(false), children: "Cancel" }),
14510
+ /* @__PURE__ */ jsx106(Button, { onClick: submitCreate, disabled: !createName.trim(), children: "Create" })
14511
+ ] }), children: /* @__PURE__ */ jsx106(
14429
14512
  "input",
14430
14513
  {
14431
14514
  className: "fd-fb-input",
@@ -14439,10 +14522,10 @@ function FileBrowser({
14439
14522
  autoFocus: true
14440
14523
  }
14441
14524
  ) }),
14442
- /* @__PURE__ */ jsx104(Modal, { open: renameTarget != null, title: "Rename folder", onClose: () => setRenameTarget(null), footer: /* @__PURE__ */ jsxs92(Fragment31, { children: [
14443
- /* @__PURE__ */ jsx104(Button, { variant: "secondary", onClick: () => setRenameTarget(null), children: "Cancel" }),
14444
- /* @__PURE__ */ jsx104(Button, { onClick: submitRename, disabled: !renameValue.trim(), children: "Save" })
14445
- ] }), children: /* @__PURE__ */ jsx104(
14525
+ /* @__PURE__ */ jsx106(Modal, { open: renameTarget != null, title: "Rename folder", onClose: () => setRenameTarget(null), footer: /* @__PURE__ */ jsxs93(Fragment31, { children: [
14526
+ /* @__PURE__ */ jsx106(Button, { variant: "secondary", onClick: () => setRenameTarget(null), children: "Cancel" }),
14527
+ /* @__PURE__ */ jsx106(Button, { onClick: submitRename, disabled: !renameValue.trim(), children: "Save" })
14528
+ ] }), children: /* @__PURE__ */ jsx106(
14446
14529
  "input",
14447
14530
  {
14448
14531
  className: "fd-fb-input",
@@ -14456,22 +14539,22 @@ function FileBrowser({
14456
14539
  autoFocus: true
14457
14540
  }
14458
14541
  ) }),
14459
- /* @__PURE__ */ jsx104(
14542
+ /* @__PURE__ */ jsx106(
14460
14543
  Modal,
14461
14544
  {
14462
14545
  open: deleteTarget != null,
14463
14546
  title: deleteTarget ? "Delete \u201C" + deleteTarget.name + "\u201D?" : "Delete folder?",
14464
14547
  description: "This can't be undone. The folder must be empty.",
14465
14548
  onClose: () => setDeleteTarget(null),
14466
- footer: /* @__PURE__ */ jsxs92(Fragment31, { children: [
14467
- /* @__PURE__ */ jsx104(Button, { variant: "secondary", onClick: () => setDeleteTarget(null), children: "Cancel" }),
14468
- /* @__PURE__ */ jsx104(Button, { variant: "danger", onClick: confirmDelete, children: "Delete" })
14549
+ footer: /* @__PURE__ */ jsxs93(Fragment31, { children: [
14550
+ /* @__PURE__ */ jsx106(Button, { variant: "secondary", onClick: () => setDeleteTarget(null), children: "Cancel" }),
14551
+ /* @__PURE__ */ jsx106(Button, { variant: "danger", onClick: confirmDelete, children: "Delete" })
14469
14552
  ] })
14470
14553
  }
14471
14554
  )
14472
14555
  ] });
14473
14556
  if (!canUpload) return content;
14474
- return /* @__PURE__ */ jsx104(Dropzone, { className: "fd-fb-dropzone", onFiles: (picked) => onUpload && onUpload(picked, currentFolderId), label: "Drop files to upload", children: content });
14557
+ return /* @__PURE__ */ jsx106(Dropzone, { className: "fd-fb-dropzone", onFiles: (picked) => onUpload && onUpload(picked, currentFolderId), label: "Drop files to upload", children: content });
14475
14558
  }
14476
14559
  function BreadcrumbCrumb({
14477
14560
  label,
@@ -14480,8 +14563,8 @@ function BreadcrumbCrumb({
14480
14563
  isDropTarget,
14481
14564
  onDropPayload
14482
14565
  }) {
14483
- const [over, setOver] = React76.useState(false);
14484
- const dragCounter = React76.useRef(0);
14566
+ const [over, setOver] = React77.useState(false);
14567
+ const dragCounter = React77.useRef(0);
14485
14568
  const dropHandlers = isDropTarget ? {
14486
14569
  onDragEnter: (e) => {
14487
14570
  if (!hasInternalPayload(e)) return;
@@ -14506,11 +14589,11 @@ function BreadcrumbCrumb({
14506
14589
  if (payload && onDropPayload) onDropPayload(payload);
14507
14590
  }
14508
14591
  } : {};
14509
- return /* @__PURE__ */ jsx104("span", { className: ["fd-fb-crumb", over ? "is-drop-target" : ""].filter(Boolean).join(" "), ...dropHandlers, children: isCurrent ? /* @__PURE__ */ jsx104("span", { className: "fd-fb-crumb-current", "aria-current": "page", children: label }) : /* @__PURE__ */ jsx104("button", { type: "button", className: "fd-fb-crumb-link", onClick, children: label }) });
14592
+ return /* @__PURE__ */ jsx106("span", { className: ["fd-fb-crumb", over ? "is-drop-target" : ""].filter(Boolean).join(" "), ...dropHandlers, children: isCurrent ? /* @__PURE__ */ jsx106("span", { className: "fd-fb-crumb-current", "aria-current": "page", children: label }) : /* @__PURE__ */ jsx106("button", { type: "button", className: "fd-fb-crumb-link", onClick, children: label }) });
14510
14593
  }
14511
14594
 
14512
14595
  // src/kits/query.ts
14513
- import * as React77 from "react";
14596
+ import * as React78 from "react";
14514
14597
 
14515
14598
  // src/kits/queryUrl.ts
14516
14599
  var historyUrlAdapter = {
@@ -14648,38 +14731,38 @@ function requestFor(params, query, paging, after) {
14648
14731
  }
14649
14732
  var toError = (e) => e instanceof Error ? e : new Error(String(e));
14650
14733
  function useServerTable({ endpoint, params, defaults, deps, prefsKey, paging = "page", url }) {
14651
- const [base] = React77.useState(() => {
14734
+ const [base] = React78.useState(() => {
14652
14735
  const store = PREFS || window.PlannerPrefs;
14653
14736
  const saved = prefsKey && store ? store.getTable(prefsKey) : {};
14654
14737
  return { ...DEFAULTS, ...defaults || {}, ...saved.pageSize ? { pageSize: saved.pageSize } : {}, ...saved.sort ? { sort: saved.sort, dir: saved.dir || "desc" } : {} };
14655
14738
  });
14656
- const [mountParams] = React77.useState(() => url ? (url.adapter ?? historyUrlAdapter).read() : null);
14657
- const address = React77.useRef(mountParams);
14658
- const [query, setQuery] = React77.useState(() => url && mountParams ? readQueryFromUrl(mountParams, url.scope, base, paging) : base);
14659
- const savePref = React77.useCallback((patch2) => {
14739
+ const [mountParams] = React78.useState(() => url ? (url.adapter ?? historyUrlAdapter).read() : null);
14740
+ const address = React78.useRef(mountParams);
14741
+ const [query, setQuery] = React78.useState(() => url && mountParams ? readQueryFromUrl(mountParams, url.scope, base, paging) : base);
14742
+ const savePref = React78.useCallback((patch2) => {
14660
14743
  const store = PREFS || window.PlannerPrefs;
14661
14744
  if (prefsKey && store) store.setTable(prefsKey, patch2);
14662
14745
  }, [prefsKey]);
14663
- const [res, setRes] = React77.useState(null);
14664
- const [loading, setLoading] = React77.useState(true);
14665
- const [loadingMore, setLoadingMore] = React77.useState(false);
14666
- const [failure, setFailure] = React77.useState(null);
14667
- const [reloadToken, setReloadToken] = React77.useState(0);
14668
- const moreController = React77.useRef(null);
14746
+ const [res, setRes] = React78.useState(null);
14747
+ const [loading, setLoading] = React78.useState(true);
14748
+ const [loadingMore, setLoadingMore] = React78.useState(false);
14749
+ const [failure, setFailure] = React78.useState(null);
14750
+ const [reloadToken, setReloadToken] = React78.useState(0);
14751
+ const moreController = React78.useRef(null);
14669
14752
  const depKey = (deps || []).join("|");
14670
14753
  const paramKey = JSON.stringify(params || {});
14671
14754
  const queryKey = JSON.stringify(query);
14672
- const lifetime = React77.useRef(null);
14673
- React77.useEffect(() => {
14755
+ const lifetime = React78.useRef(null);
14756
+ React78.useEffect(() => {
14674
14757
  const controller = new AbortController();
14675
14758
  lifetime.current = controller;
14676
14759
  return () => controller.abort();
14677
14760
  }, []);
14678
- const latest = React77.useRef({ res, loading, query, params, endpoint, url, base });
14679
- React77.useEffect(() => {
14761
+ const latest = React78.useRef({ res, loading, query, params, endpoint, url, base });
14762
+ React78.useLayoutEffect(() => {
14680
14763
  latest.current = { res, loading, query, params, endpoint, url, base };
14681
14764
  });
14682
- React77.useEffect(() => {
14765
+ React78.useEffect(() => {
14683
14766
  const controller = new AbortController();
14684
14767
  const { signal } = controller;
14685
14768
  setLoading(true);
@@ -14715,7 +14798,7 @@ function useServerTable({ endpoint, params, defaults, deps, prefsKey, paging = "
14715
14798
  };
14716
14799
  }, [endpoint, queryKey, paramKey, depKey, paging, reloadToken]);
14717
14800
  const adapter = url ? url.adapter ?? historyUrlAdapter : null;
14718
- React77.useEffect(() => {
14801
+ React78.useEffect(() => {
14719
14802
  if (!adapter) return;
14720
14803
  return adapter.subscribe((params2) => {
14721
14804
  const { url: u, base: b } = latest.current;
@@ -15065,12 +15148,12 @@ function createVersionStore(initialState, options) {
15065
15148
  }
15066
15149
 
15067
15150
  // src/kits/documentTitle.ts
15068
- import * as React78 from "react";
15151
+ import * as React79 from "react";
15069
15152
  function formatDocumentTitle(routeTitle, appName) {
15070
15153
  return [routeTitle, appName, "Flytedesk"].filter((part) => !!part && part.length > 0).join(" \xB7 ");
15071
15154
  }
15072
15155
  function useDocumentTitle(routeTitle, appName) {
15073
- React78.useEffect(() => {
15156
+ React79.useEffect(() => {
15074
15157
  if (typeof document === "undefined") return;
15075
15158
  document.title = formatDocumentTitle(routeTitle, appName);
15076
15159
  }, [routeTitle, appName]);
@@ -15141,6 +15224,7 @@ export {
15141
15224
  FILE_VIEWER_TEXT_LIMIT,
15142
15225
  FactList,
15143
15226
  FeatureGate,
15227
+ Fieldset,
15144
15228
  FileBrowser,
15145
15229
  FileChip,
15146
15230
  FileGrid,
@@ -15194,6 +15278,7 @@ export {
15194
15278
  QuotaRow,
15195
15279
  ROOT_STEP,
15196
15280
  Radio,
15281
+ RadioGroup,
15197
15282
  RangeSlider,
15198
15283
  RelativeTime,
15199
15284
  RoadmapTimeline,