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