@flytedan/flytebot-design-system 0.67.4 → 0.70.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -974,6 +974,7 @@ __export(index_exports, {
974
974
  FILE_VIEWER_TEXT_LIMIT: () => FILE_VIEWER_TEXT_LIMIT,
975
975
  FactList: () => FactList,
976
976
  FeatureGate: () => FeatureGate,
977
+ Fieldset: () => Fieldset,
977
978
  FileBrowser: () => FileBrowser,
978
979
  FileChip: () => FileChip,
979
980
  FileGrid: () => FileGrid,
@@ -1027,6 +1028,7 @@ __export(index_exports, {
1027
1028
  QuotaRow: () => QuotaRow,
1028
1029
  ROOT_STEP: () => ROOT_STEP,
1029
1030
  Radio: () => Radio,
1031
+ RadioGroup: () => RadioGroup,
1030
1032
  RangeSlider: () => RangeSlider,
1031
1033
  RelativeTime: () => RelativeTime,
1032
1034
  RoadmapTimeline: () => RoadmapTimeline,
@@ -4193,6 +4195,24 @@ function CsiHero({ band = "weak", crp, label, className = "" }) {
4193
4195
  // src/components/data/DataTable.tsx
4194
4196
  var import_jsx_runtime44 = require("react/jsx-runtime");
4195
4197
  var STACK_MAX_WIDTH = 640;
4198
+ function RowActionButton({ action, size }) {
4199
+ return /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
4200
+ IconButton,
4201
+ {
4202
+ icon: action.icon,
4203
+ label: action.label,
4204
+ size,
4205
+ disabled: action.disabled,
4206
+ onClick: (e) => {
4207
+ e.stopPropagation();
4208
+ action.onClick();
4209
+ }
4210
+ }
4211
+ );
4212
+ }
4213
+ function RowActionCell({ action }) {
4214
+ return /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("td", { className: "fd-table-action", children: action ? /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(RowActionButton, { action, size: "sm" }) : null });
4215
+ }
4196
4216
  var cellOf = (c, row) => c.render ? c.render(row) : row[c.key];
4197
4217
  function rowInteraction(row, onRowClick) {
4198
4218
  if (!onRowClick) return {};
@@ -4220,6 +4240,7 @@ function DataTable({
4220
4240
  selectedIds,
4221
4241
  rowTitle,
4222
4242
  onRowClick,
4243
+ rowAction,
4223
4244
  rowKey = "id",
4224
4245
  loading = false,
4225
4246
  refreshing = false,
@@ -4256,27 +4277,37 @@ function DataTable({
4256
4277
  onSort,
4257
4278
  rowTitle,
4258
4279
  onRowClick,
4280
+ rowAction,
4259
4281
  isSelected
4260
4282
  }
4261
4283
  ) : /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("table", { className: ["fd-table", compact3 ? "fd-table-compact" : ""].filter(Boolean).join(" "), children: [
4262
- /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("tr", { children: columns.map((c) => /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
4263
- "th",
4264
- {
4265
- scope: "col",
4266
- style: { width: c.width },
4267
- className: [c.numeric ? "is-num" : "", sort && sort.key === c.key ? "is-sorted" : ""].filter(Boolean).join(" "),
4268
- "aria-sort": sort && sort.key === c.key ? sort.dir === "asc" ? "ascending" : "descending" : void 0,
4269
- children: c.sortable && onSort ? /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(SortButton, { column: c, sort, onSort }) : c.label
4270
- },
4271
- c.key
4272
- )) }) }),
4273
- /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("tbody", { className: stale ? "fd-stale" : void 0, children: loading ? Array.from({ length: skeletonRows }).map((_, i) => /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("tr", { children: columns.map((c) => /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("td", { className: c.numeric ? "is-num" : "", children: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("span", { className: "fd-skel fd-skel-text", style: { display: "inline-block", height: 13, width: c.numeric ? 52 : i % 3 === 0 ? "72%" : "88%" } }) }, c.key)) }, i)) : rows.map((r) => /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
4284
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("tr", { children: [
4285
+ columns.map((c) => /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
4286
+ "th",
4287
+ {
4288
+ scope: "col",
4289
+ style: { width: c.width },
4290
+ className: [c.numeric ? "is-num" : "", sort && sort.key === c.key ? "is-sorted" : ""].filter(Boolean).join(" "),
4291
+ "aria-sort": sort && sort.key === c.key ? sort.dir === "asc" ? "ascending" : "descending" : void 0,
4292
+ children: c.sortable && onSort ? /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(SortButton, { column: c, sort, onSort }) : c.label
4293
+ },
4294
+ c.key
4295
+ )),
4296
+ rowAction ? /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("th", { scope: "col", className: "fd-table-action-head", children: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("span", { className: "fd-sr-only", children: "Actions" }) }) : null
4297
+ ] }) }),
4298
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("tbody", { className: stale ? "fd-stale" : void 0, children: loading ? Array.from({ length: skeletonRows }).map((_, i) => /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("tr", { children: [
4299
+ columns.map((c) => /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("td", { className: c.numeric ? "is-num" : "", children: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("span", { className: "fd-skel fd-skel-text", style: { display: "inline-block", height: 13, width: c.numeric ? 52 : i % 3 === 0 ? "72%" : "88%" } }) }, c.key)),
4300
+ rowAction ? /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("td", { className: "fd-table-action" }) : null
4301
+ ] }, i)) : rows.map((r) => /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)(
4274
4302
  "tr",
4275
4303
  {
4276
4304
  "aria-selected": isSelected(r) ? "true" : void 0,
4277
4305
  title: rowTitle ? rowTitle(r) : void 0,
4278
4306
  ...rowInteraction(r, onRowClick),
4279
- children: columns.map((c) => /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("td", { className: c.numeric ? "is-num" : "", children: cellOf(c, r) }, c.key))
4307
+ children: [
4308
+ columns.map((c) => /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("td", { className: c.numeric ? "is-num" : "", children: cellOf(c, r) }, c.key)),
4309
+ rowAction ? /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(RowActionCell, { action: rowAction(r) }) : null
4310
+ ]
4280
4311
  },
4281
4312
  r[rowKey]
4282
4313
  )) })
@@ -4289,7 +4320,7 @@ function DataTable({
4289
4320
  ] }) }) : null
4290
4321
  ] });
4291
4322
  }
4292
- function StackedRows({ columns, rows, rowKey, loading, stale, skeletonRows, sort, onSort, rowTitle, onRowClick, isSelected }) {
4323
+ function StackedRows({ columns, rows, rowKey, loading, stale, skeletonRows, sort, onSort, rowTitle, onRowClick, rowAction, isSelected }) {
4293
4324
  const sortable = onSort ? columns.filter((c) => c.sortable) : [];
4294
4325
  const primary = columns.filter((c) => c.phone === "primary");
4295
4326
  const secondary = columns.filter((c) => c.phone === "secondary");
@@ -4308,31 +4339,34 @@ function StackedRows({ columns, rows, rowKey, loading, stale, skeletonRows, sort
4308
4339
  c.key
4309
4340
  );
4310
4341
  }) }) : null,
4311
- /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("div", { className: stale ? "fd-dt-cards fd-stale" : "fd-dt-cards", children: loading ? Array.from({ length: skeletonRows }).map((_, i) => /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("div", { className: "fd-dt-card", children: [
4342
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("div", { className: stale ? "fd-dt-cards fd-stale" : "fd-dt-cards", children: loading ? Array.from({ length: skeletonRows }).map((_, i) => /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("div", { className: "fd-dt-item", children: /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("div", { className: "fd-dt-card", children: [
4312
4343
  /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("span", { className: "fd-skel fd-skel-text", style: { display: "block", height: 14, width: i % 3 === 0 ? "55%" : "70%" } }),
4313
4344
  secondary.length ? /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("span", { className: "fd-skel fd-skel-text", style: { display: "block", height: 12, width: "40%" } }) : null
4314
- ] }, i)) : rows.map((r) => {
4345
+ ] }) }, i)) : rows.map((r) => {
4315
4346
  const selected = isSelected(r);
4347
+ const action = rowAction ? rowAction(r) : null;
4316
4348
  const semantics = onRowClick ? { role: "button", "aria-pressed": selected } : { "aria-current": selected ? "true" : void 0 };
4317
- return /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)(
4318
- "div",
4319
- {
4320
- className: "fd-dt-card",
4321
- title: rowTitle ? rowTitle(r) : void 0,
4322
- "data-selected": selected ? "true" : void 0,
4323
- ...semantics,
4324
- ...rowInteraction(r, onRowClick),
4325
- children: [
4326
- /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("div", { className: "fd-dt-card-title", children: primary.map((c) => /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("span", { className: c.numeric ? "is-num" : void 0, children: cellOf(c, r) }, c.key)) }),
4327
- secondary.length ? /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("div", { className: "fd-dt-card-meta", children: secondary.map((c) => /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("span", { className: c.numeric ? "is-num" : void 0, children: [
4328
- /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("span", { className: "fd-dt-card-label", children: c.label }),
4329
- " ",
4330
- cellOf(c, r)
4331
- ] }, c.key)) }) : null
4332
- ]
4333
- },
4334
- r[rowKey]
4335
- );
4349
+ return /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("div", { className: "fd-dt-item", children: [
4350
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)(
4351
+ "div",
4352
+ {
4353
+ className: "fd-dt-card",
4354
+ title: rowTitle ? rowTitle(r) : void 0,
4355
+ "data-selected": selected ? "true" : void 0,
4356
+ ...semantics,
4357
+ ...rowInteraction(r, onRowClick),
4358
+ children: [
4359
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("div", { className: "fd-dt-card-title", children: primary.map((c) => /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("span", { className: c.numeric ? "is-num" : void 0, children: cellOf(c, r) }, c.key)) }),
4360
+ secondary.length ? /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("div", { className: "fd-dt-card-meta", children: secondary.map((c) => /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("span", { className: c.numeric ? "is-num" : void 0, children: [
4361
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("span", { className: "fd-dt-card-label", children: c.label }),
4362
+ " ",
4363
+ cellOf(c, r)
4364
+ ] }, c.key)) }) : null
4365
+ ]
4366
+ }
4367
+ ),
4368
+ action ? /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("div", { className: "fd-dt-action", children: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(RowActionButton, { action, size: "md" }) }) : null
4369
+ ] }, r[rowKey]);
4336
4370
  }) })
4337
4371
  ] });
4338
4372
  }
@@ -6321,6 +6355,16 @@ function DiffBlock({ diff = "", filename, collapseAfter = 34, className = "" })
6321
6355
 
6322
6356
  // src/components/data/Markdown.tsx
6323
6357
  var React35 = __toESM(require("react"), 1);
6358
+
6359
+ // src/components/data/markdownEscape.ts
6360
+ var ESCAPABLE = /\\([!-/:-@[-`{-~])/g;
6361
+ var STAND_IN_BASE = 57344;
6362
+ var STAND_IN = /[-]/g;
6363
+ var hideEscapes = (s) => s.replace(STAND_IN, "\uFFFD").replace(ESCAPABLE, (_, c) => String.fromCharCode(STAND_IN_BASE + c.charCodeAt(0)));
6364
+ var showEscapes = (s) => s.replace(STAND_IN, (c) => String.fromCharCode(c.charCodeAt(0) - STAND_IN_BASE));
6365
+ var showEscapesRaw = (s) => s.replace(STAND_IN, (c) => "\\" + String.fromCharCode(c.charCodeAt(0) - STAND_IN_BASE));
6366
+
6367
+ // src/components/data/Markdown.tsx
6324
6368
  var import_jsx_runtime54 = require("react/jsx-runtime");
6325
6369
  var SAFE = /^(?:https?:|mailto:|tel:|#|\/|\.{1,2}\/)/i;
6326
6370
  var safeHref = (h) => SAFE.test(String(h || "").trim()) ? String(h).trim() : null;
@@ -6338,7 +6382,8 @@ var INLINE = [
6338
6382
  ];
6339
6383
  function inlineNodes(src, ctx, keyBase) {
6340
6384
  const out = [];
6341
- let rest = String(src == null ? "" : src), guard = 0;
6385
+ let rest = hideEscapes(String(src == null ? "" : src)), guard = 0;
6386
+ const d = showEscapes;
6342
6387
  const key = () => keyBase + "-" + out.length;
6343
6388
  while (rest && guard++ < 800) {
6344
6389
  let best = null;
@@ -6349,28 +6394,28 @@ function inlineNodes(src, ctx, keyBase) {
6349
6394
  }
6350
6395
  if (!best) break;
6351
6396
  const { kind, m } = best;
6352
- if (m.index > 0) out.push(rest.slice(0, m.index));
6397
+ if (m.index > 0) out.push(d(rest.slice(0, m.index)));
6353
6398
  const g = (i) => m[i];
6354
- if (kind === "code") out.push(/* @__PURE__ */ (0, import_jsx_runtime54.jsx)("code", { className: "fd-md-code", children: g(1) }, key()));
6399
+ if (kind === "code") out.push(/* @__PURE__ */ (0, import_jsx_runtime54.jsx)("code", { className: "fd-md-code", children: showEscapesRaw(g(1)) }, key()));
6355
6400
  else if (kind === "image") {
6356
- const src2 = safeHref(g(2));
6357
- out.push(ctx.allowImages && src2 ? /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("img", { className: "fd-md-img", src: src2, alt: g(1) || "", title: g(3) || void 0, loading: "lazy" }, key()) : /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("span", { className: "fd-md-imgalt", children: g(1) || "image" }, key()));
6401
+ const src2 = safeHref(d(g(2)));
6402
+ out.push(ctx.allowImages && src2 ? /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("img", { className: "fd-md-img", src: src2, alt: d(g(1) || ""), title: g(3) ? d(g(3)) : void 0, loading: "lazy" }, key()) : /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("span", { className: "fd-md-imgalt", children: d(g(1) || "image") }, key()));
6358
6403
  } else if (kind === "link") {
6359
- const href = safeHref(g(2));
6360
- out.push(href ? /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("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__ */ (0, import_jsx_runtime54.jsx)("span", { children: g(1) }, key()));
6404
+ const href = safeHref(d(g(2)));
6405
+ out.push(href ? /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("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__ */ (0, import_jsx_runtime54.jsx)("span", { children: d(g(1)) }, key()));
6361
6406
  } else if (kind === "cite") {
6362
- out.push(ctx.renderCitation ? /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(React35.Fragment, { children: ctx.renderCitation(g(1)) }, key()) : /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("sup", { className: "fd-md-cite", children: g(1) }, key()));
6407
+ out.push(ctx.renderCitation ? /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(React35.Fragment, { children: ctx.renderCitation(d(g(1))) }, key()) : /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("sup", { className: "fd-md-cite", children: d(g(1)) }, key()));
6363
6408
  } else if (kind === "strongem") out.push(/* @__PURE__ */ (0, import_jsx_runtime54.jsx)("strong", { children: /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("em", { children: inlineNodes(g(1), ctx, key()) }) }, key()));
6364
6409
  else if (kind === "strong") out.push(/* @__PURE__ */ (0, import_jsx_runtime54.jsx)("strong", { children: inlineNodes(g(1) || g(2), ctx, key()) }, key()));
6365
6410
  else if (kind === "em") out.push(/* @__PURE__ */ (0, import_jsx_runtime54.jsx)("em", { children: inlineNodes(g(1) || g(2), ctx, key()) }, key()));
6366
6411
  else if (kind === "del") out.push(/* @__PURE__ */ (0, import_jsx_runtime54.jsx)("del", { children: inlineNodes(g(1), ctx, key()) }, key()));
6367
6412
  else if (kind === "autolink" || kind === "bare") {
6368
- const href = safeHref(g(1));
6369
- out.push(href ? /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("a", { href, target: "_blank", rel: "noopener noreferrer", onClick: ctx.onLinkClick, children: g(1).replace(/^mailto:/, "") }, key()) : g(1));
6413
+ const href = safeHref(d(g(1)));
6414
+ out.push(href ? /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("a", { href, target: "_blank", rel: "noopener noreferrer", onClick: ctx.onLinkClick, children: d(g(1)).replace(/^mailto:/, "") }, key()) : d(g(1)));
6370
6415
  }
6371
6416
  rest = rest.slice(m.index + m[0].length);
6372
6417
  }
6373
- if (rest) out.push(rest);
6418
+ if (rest) out.push(d(rest));
6374
6419
  return out;
6375
6420
  }
6376
6421
  var RE = {
@@ -6382,7 +6427,26 @@ var RE = {
6382
6427
  task: /^\[([ xX])\]\s+(.*)$/,
6383
6428
  tableSep: /^\s*\|?[\s:|-]*-[\s:|-]*\|?\s*$/
6384
6429
  };
6385
- var splitRow = (line) => line.replace(/^\s*\|/, "").replace(/\|\s*$/, "").split("|").map((c) => c.trim());
6430
+ var splitRow = (line) => {
6431
+ const t = line.trim();
6432
+ const cells = [];
6433
+ let cur = "";
6434
+ for (let i = t.startsWith("|") ? 1 : 0; i < t.length; i++) {
6435
+ const c = t[i];
6436
+ if (c === "\\" && i + 1 < t.length) {
6437
+ cur += c + t[++i];
6438
+ continue;
6439
+ }
6440
+ if (c === "|") {
6441
+ cells.push(cur.trim());
6442
+ cur = "";
6443
+ continue;
6444
+ }
6445
+ cur += c;
6446
+ }
6447
+ if (cur.trim() || !t.endsWith("|")) cells.push(cur.trim());
6448
+ return cells;
6449
+ };
6386
6450
  function parseBlocks(src) {
6387
6451
  const lines = String(src == null ? "" : src).replace(/\r\n?/g, "\n").split("\n");
6388
6452
  const blocks = [];
@@ -6514,6 +6578,7 @@ function renderBlocks(blocks, ctx, path) {
6514
6578
  }
6515
6579
  });
6516
6580
  }
6581
+ var mdClass = (base, size, tone, className) => [base, size && `${base}--${size}`, tone === "muted" && `${base}--muted`, className].filter(Boolean).join(" ");
6517
6582
  function Markdown({
6518
6583
  source = "",
6519
6584
  className = "",
@@ -6521,14 +6586,16 @@ function Markdown({
6521
6586
  allowImages = true,
6522
6587
  headingOffset = 0,
6523
6588
  renderCitation,
6524
- onLinkClick
6589
+ onLinkClick,
6590
+ size = "body",
6591
+ tone = "default"
6525
6592
  }) {
6526
6593
  const ctx = { allowImages, headingOffset, renderCitation, onLinkClick, codeProps };
6527
6594
  const blocks = React35.useMemo(() => parseBlocks(source), [source]);
6528
- return /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("div", { className: ["fd-md", className].filter(Boolean).join(" "), children: renderBlocks(blocks, ctx, "b") });
6595
+ return /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("div", { className: mdClass("fd-md", size, tone, className), children: renderBlocks(blocks, ctx, "b") });
6529
6596
  }
6530
- function MarkdownInline({ source = "", className = "", onLinkClick }) {
6531
- return /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("span", { className: ["fd-md-inline", className].filter(Boolean).join(" "), children: inlineNodes(source, { allowImages: false, onLinkClick }, "i") });
6597
+ function MarkdownInline({ source = "", className = "", onLinkClick, size, tone }) {
6598
+ return /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("span", { className: mdClass("fd-md-inline", size, tone, className), children: inlineNodes(source, { allowImages: false, onLinkClick }, "i") });
6532
6599
  }
6533
6600
  function markdownToText(src) {
6534
6601
  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();
@@ -7797,14 +7864,17 @@ function Checkbox({ label, description, card = false, indeterminate = false, cla
7797
7864
 
7798
7865
  // src/components/forms/Radio.tsx
7799
7866
  var import_jsx_runtime70 = require("react/jsx-runtime");
7800
- function Radio({ label, description, card = false, className = "", ...rest }) {
7867
+ function Radio({ label, description, badge, card = false, className = "", ...rest }) {
7801
7868
  return /* @__PURE__ */ (0, import_jsx_runtime70.jsxs)("label", { className: ["fd-choice", card ? "fd-choice-card" : "", className].filter(Boolean).join(" "), children: [
7802
7869
  /* @__PURE__ */ (0, import_jsx_runtime70.jsxs)("span", { className: "fd-choice-input", children: [
7803
7870
  /* @__PURE__ */ (0, import_jsx_runtime70.jsx)("input", { type: "radio", ...rest }),
7804
7871
  /* @__PURE__ */ (0, import_jsx_runtime70.jsx)("span", { className: "fd-choice-box fd-choice-box-round", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime70.jsx)("span", { className: "fd-choice-dot" }) })
7805
7872
  ] }),
7806
7873
  /* @__PURE__ */ (0, import_jsx_runtime70.jsxs)("span", { className: "fd-choice-text", children: [
7807
- /* @__PURE__ */ (0, import_jsx_runtime70.jsx)("span", { className: "fd-choice-title", children: label }),
7874
+ /* @__PURE__ */ (0, import_jsx_runtime70.jsxs)("span", { className: "fd-choice-title", children: [
7875
+ label,
7876
+ badge ? /* @__PURE__ */ (0, import_jsx_runtime70.jsx)("span", { className: "fd-choice-badge", children: badge }) : null
7877
+ ] }),
7808
7878
  description ? /* @__PURE__ */ (0, import_jsx_runtime70.jsx)("span", { className: "fd-choice-desc", children: description }) : null
7809
7879
  ] })
7810
7880
  ] });
@@ -9396,17 +9466,49 @@ function CodeEditor({
9396
9466
  ] });
9397
9467
  }
9398
9468
 
9469
+ // src/components/forms/RadioGroup.tsx
9470
+ var React53 = __toESM(require("react"), 1);
9471
+ var import_jsx_runtime80 = require("react/jsx-runtime");
9472
+ function RadioGroup({ label, options, value, onChange, card = false, disabled = false, name, className = "" }) {
9473
+ const autoName = React53.useId();
9474
+ const labelId = React53.useId();
9475
+ return /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("div", { role: "radiogroup", "aria-labelledby": labelId, "aria-disabled": disabled || void 0, className: ["fd-radiogroup", className].filter(Boolean).join(" "), children: [
9476
+ /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("span", { id: labelId, className: "fd-radiogroup-label", children: label }),
9477
+ options.map((o) => /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(
9478
+ Radio,
9479
+ {
9480
+ card,
9481
+ name: name ?? autoName,
9482
+ value: o.value,
9483
+ label: o.label,
9484
+ description: o.description,
9485
+ badge: o.badge,
9486
+ checked: o.value === value,
9487
+ disabled: disabled || o.disabled,
9488
+ onChange: () => onChange(o.value)
9489
+ },
9490
+ o.value
9491
+ ))
9492
+ ] });
9493
+ }
9494
+
9495
+ // src/components/forms/Fieldset.tsx
9496
+ var import_jsx_runtime81 = require("react/jsx-runtime");
9497
+ function Fieldset({ busy = false, className = "", ...rest }) {
9498
+ return /* @__PURE__ */ (0, import_jsx_runtime81.jsx)("fieldset", { disabled: busy, "aria-busy": busy || void 0, className: ["fd-fieldset", className].filter(Boolean).join(" "), ...rest });
9499
+ }
9500
+
9399
9501
  // src/components/platform/AccountMenu.tsx
9400
- var React54 = __toESM(require("react"), 1);
9502
+ var React55 = __toESM(require("react"), 1);
9401
9503
 
9402
9504
  // src/kits/sessionContext.tsx
9403
- var React53 = __toESM(require("react"), 1);
9404
- var SessionContext = React53.createContext(null);
9505
+ var React54 = __toESM(require("react"), 1);
9506
+ var SessionContext = React54.createContext(null);
9405
9507
  function SessionProvider({ value, children }) {
9406
- return React53.createElement(SessionContext.Provider, { value }, children);
9508
+ return React54.createElement(SessionContext.Provider, { value }, children);
9407
9509
  }
9408
9510
  function useSessionContext() {
9409
- const ctx = React53.useContext(SessionContext);
9511
+ const ctx = React54.useContext(SessionContext);
9410
9512
  if (!ctx) {
9411
9513
  throw new Error(
9412
9514
  "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."
@@ -9416,11 +9518,11 @@ function useSessionContext() {
9416
9518
  }
9417
9519
 
9418
9520
  // src/components/platform/AccountMenu.tsx
9419
- var import_jsx_runtime80 = require("react/jsx-runtime");
9521
+ var import_jsx_runtime82 = require("react/jsx-runtime");
9420
9522
  var DEFAULT_LINKS = [];
9421
9523
  var DEFAULT_GROUPS = [];
9422
9524
  function Item({ item, onPick }) {
9423
- return /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)(
9525
+ return /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)(
9424
9526
  "button",
9425
9527
  {
9426
9528
  type: "button",
@@ -9428,9 +9530,9 @@ function Item({ item, onPick }) {
9428
9530
  className: "fd-acct-item",
9429
9531
  onClick: () => onPick(item),
9430
9532
  children: [
9431
- item.icon ? /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("i", { className: "ph ph-" + item.icon, "aria-hidden": "true" }) : null,
9432
- /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("span", { style: { flex: 1 }, children: item.label }),
9433
- item.badge ? /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(Badge, { tone: "neutral", children: item.badge }) : null
9533
+ item.icon ? /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("i", { className: "ph ph-" + item.icon, "aria-hidden": "true" }) : null,
9534
+ /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("span", { style: { flex: 1 }, children: item.label }),
9535
+ item.badge ? /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(Badge, { tone: "neutral", children: item.badge }) : null
9434
9536
  ]
9435
9537
  }
9436
9538
  );
@@ -9446,11 +9548,11 @@ function AccountMenu({
9446
9548
  ...rest
9447
9549
  }) {
9448
9550
  const { user, roles, can: can2, signOut: ctxSignOut, demo, pending } = useSessionContext();
9449
- const [open2, setOpen] = React54.useState(false);
9450
- const [switching, setSwitching] = React54.useState(false);
9451
- const [signingOut, setSigningOut] = React54.useState(false);
9452
- const [signOutError, setSignOutError] = React54.useState(null);
9453
- const ref = React54.useRef(null);
9551
+ const [open2, setOpen] = React55.useState(false);
9552
+ const [switching, setSwitching] = React55.useState(false);
9553
+ const [signingOut, setSigningOut] = React55.useState(false);
9554
+ const [signOutError, setSignOutError] = React55.useState(null);
9555
+ const ref = React55.useRef(null);
9454
9556
  const visibleLinks = links.filter((l) => !l.perm || !pending && can2(l.perm));
9455
9557
  const visibleGroups = groups.map((g) => ({ label: g.label, links: g.links.filter((l) => !l.perm || !pending && can2(l.perm)) })).filter((g) => g.links.length);
9456
9558
  const closeMenu = () => {
@@ -9478,8 +9580,8 @@ function AccountMenu({
9478
9580
  }
9479
9581
  };
9480
9582
  const showSwitcher = allowUserSwitch && !!demo;
9481
- return /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)(import_jsx_runtime80.Fragment, { children: [
9482
- /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)(
9583
+ return /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)(import_jsx_runtime82.Fragment, { children: [
9584
+ /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)(
9483
9585
  "button",
9484
9586
  {
9485
9587
  type: "button",
@@ -9491,12 +9593,12 @@ function AccountMenu({
9491
9593
  onClick: () => open2 ? closeMenu() : setOpen(true),
9492
9594
  ...rest,
9493
9595
  children: [
9494
- /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(Avatar, { name: user.name, size: "sm" }),
9495
- /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("i", { className: "ph ph-caret-down", "aria-hidden": "true", style: { fontSize: 11, color: "var(--text-muted)" } })
9596
+ /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(Avatar, { name: user.name, size: "sm" }),
9597
+ /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("i", { className: "ph ph-caret-down", "aria-hidden": "true", style: { fontSize: 11, color: "var(--text-muted)" } })
9496
9598
  ]
9497
9599
  }
9498
9600
  ),
9499
- /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(
9601
+ /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(
9500
9602
  Popover,
9501
9603
  {
9502
9604
  open: open2,
@@ -9504,27 +9606,27 @@ function AccountMenu({
9504
9606
  onClose: closeMenu,
9505
9607
  placement: "bottom-end",
9506
9608
  width: 272,
9507
- children: /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("div", { role: "menu", className: "fd-stack", style: { gap: 0 }, children: [
9508
- /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("div", { className: "fd-row", style: { gap: 10, padding: "12px 14px", borderBottom: "1px solid var(--border)" }, children: [
9509
- /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(Avatar, { name: user.name }),
9510
- /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("span", { className: "fd-stack", style: { gap: 1, minWidth: 0, flex: 1 }, children: [
9511
- /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("span", { className: "fd-body-sm", style: { fontWeight: 700 }, children: user.name }),
9512
- /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("span", { className: "fd-body-sm fd-muted fd-table-trunc", title: truncationTitle(user.email), children: user.email })
9609
+ children: /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)("div", { role: "menu", className: "fd-stack", style: { gap: 0 }, children: [
9610
+ /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)("div", { className: "fd-row", style: { gap: 10, padding: "12px 14px", borderBottom: "1px solid var(--border)" }, children: [
9611
+ /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(Avatar, { name: user.name }),
9612
+ /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)("span", { className: "fd-stack", style: { gap: 1, minWidth: 0, flex: 1 }, children: [
9613
+ /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("span", { className: "fd-body-sm", style: { fontWeight: 700 }, children: user.name }),
9614
+ /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("span", { className: "fd-body-sm fd-muted fd-table-trunc", title: truncationTitle(user.email), children: user.email })
9513
9615
  ] })
9514
9616
  ] }),
9515
- showRoles && roles.length ? /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("div", { className: "fd-row", style: { gap: 6, padding: "10px 14px", flexWrap: "wrap", borderBottom: "1px solid var(--border)" }, children: roles.map((r) => /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(Badge, { tone: r.id === "owner" ? "success" : "neutral", children: r.name }, r.id)) }) : null,
9516
- visibleLinks.length ? /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("div", { className: "fd-acct-group", children: visibleLinks.map((l) => /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(Item, { item: l, onPick: pick }, l.id)) }) : null,
9517
- visibleGroups.map((g) => /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("div", { className: "fd-acct-group", style: { borderTop: "1px solid var(--border)" }, children: [
9518
- /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("span", { className: "fd-overline fd-muted", style: { padding: "8px 14px 4px", display: "block" }, children: g.label }),
9519
- g.links.map((l) => /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(Item, { item: l, onPick: pick }, l.id))
9617
+ showRoles && roles.length ? /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("div", { className: "fd-row", style: { gap: 6, padding: "10px 14px", flexWrap: "wrap", borderBottom: "1px solid var(--border)" }, children: roles.map((r) => /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(Badge, { tone: r.id === "owner" ? "success" : "neutral", children: r.name }, r.id)) }) : null,
9618
+ visibleLinks.length ? /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("div", { className: "fd-acct-group", children: visibleLinks.map((l) => /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(Item, { item: l, onPick: pick }, l.id)) }) : null,
9619
+ visibleGroups.map((g) => /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)("div", { className: "fd-acct-group", style: { borderTop: "1px solid var(--border)" }, children: [
9620
+ /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("span", { className: "fd-overline fd-muted", style: { padding: "8px 14px 4px", display: "block" }, children: g.label }),
9621
+ g.links.map((l) => /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(Item, { item: l, onPick: pick }, l.id))
9520
9622
  ] }, g.label)),
9521
- showSwitcher && demo ? /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("div", { className: "fd-acct-group", style: { borderTop: "1px solid var(--border)" }, children: [
9522
- /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("button", { type: "button", role: "menuitem", className: "fd-acct-item", onClick: () => setSwitching((s) => !s), children: [
9523
- /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("i", { className: "ph ph-user-switch", "aria-hidden": "true" }),
9524
- /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("span", { style: { flex: 1 }, children: "View as another member" }),
9525
- /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("i", { className: "ph ph-caret-" + (switching ? "up" : "down"), "aria-hidden": "true", style: { fontSize: 11 } })
9623
+ showSwitcher && demo ? /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)("div", { className: "fd-acct-group", style: { borderTop: "1px solid var(--border)" }, children: [
9624
+ /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)("button", { type: "button", role: "menuitem", className: "fd-acct-item", onClick: () => setSwitching((s) => !s), children: [
9625
+ /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("i", { className: "ph ph-user-switch", "aria-hidden": "true" }),
9626
+ /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("span", { style: { flex: 1 }, children: "View as another member" }),
9627
+ /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("i", { className: "ph ph-caret-" + (switching ? "up" : "down"), "aria-hidden": "true", style: { fontSize: 11 } })
9526
9628
  ] }),
9527
- switching ? /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("div", { className: "fd-stack", style: { gap: 0 }, children: demo.allUsers.map((u) => /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)(
9629
+ switching ? /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("div", { className: "fd-stack", style: { gap: 0 }, children: demo.allUsers.map((u) => /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)(
9528
9630
  "button",
9529
9631
  {
9530
9632
  type: "button",
@@ -9536,19 +9638,19 @@ function AccountMenu({
9536
9638
  setSwitching(false);
9537
9639
  },
9538
9640
  children: [
9539
- /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(Avatar, { name: u.name, size: "sm" }),
9540
- /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("span", { className: "fd-stack", style: { gap: 0, flex: 1, minWidth: 0, alignItems: "flex-start" }, children: [
9541
- /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("span", { style: { fontWeight: u.id === user.id ? 700 : 500 }, children: u.name }),
9542
- u.roles ? /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("span", { className: "fd-muted", style: { fontSize: 11.5 }, children: u.roles.join(", ") }) : null
9641
+ /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(Avatar, { name: u.name, size: "sm" }),
9642
+ /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)("span", { className: "fd-stack", style: { gap: 0, flex: 1, minWidth: 0, alignItems: "flex-start" }, children: [
9643
+ /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("span", { style: { fontWeight: u.id === user.id ? 700 : 500 }, children: u.name }),
9644
+ u.roles ? /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("span", { className: "fd-muted", style: { fontSize: 11.5 }, children: u.roles.join(", ") }) : null
9543
9645
  ] }),
9544
- u.id === user.id ? /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("i", { className: "ph ph-check", "aria-hidden": "true", style: { color: "var(--ok-text)" } }) : null
9646
+ u.id === user.id ? /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("i", { className: "ph ph-check", "aria-hidden": "true", style: { color: "var(--ok-text)" } }) : null
9545
9647
  ]
9546
9648
  },
9547
9649
  u.id
9548
9650
  )) }) : null
9549
9651
  ] }) : null,
9550
- /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("div", { className: "fd-acct-group", style: { borderTop: "1px solid var(--border)" }, children: [
9551
- /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)(
9652
+ /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)("div", { className: "fd-acct-group", style: { borderTop: "1px solid var(--border)" }, children: [
9653
+ /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)(
9552
9654
  "button",
9553
9655
  {
9554
9656
  type: "button",
@@ -9558,14 +9660,14 @@ function AccountMenu({
9558
9660
  disabled: signingOut,
9559
9661
  onClick: signOut,
9560
9662
  children: [
9561
- signingOut ? /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(Spinner, { size: "sm" }) : /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("i", { className: "ph ph-sign-out", "aria-hidden": "true" }),
9562
- /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("span", { style: { flex: 1 }, children: signingOut ? "Signing out\u2026" : "Sign out" })
9663
+ signingOut ? /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(Spinner, { size: "sm" }) : /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("i", { className: "ph ph-sign-out", "aria-hidden": "true" }),
9664
+ /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("span", { style: { flex: 1 }, children: signingOut ? "Signing out\u2026" : "Sign out" })
9563
9665
  ]
9564
9666
  }
9565
9667
  ),
9566
- signOutError ? /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("div", { role: "alert", className: "fd-body-sm", style: { padding: "0 14px 12px" }, children: [
9567
- /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("span", { style: { display: "block", color: "var(--danger-text)", marginBottom: 6 }, children: signOutError }),
9568
- /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("button", { type: "button", className: "fd-soon-link", disabled: signingOut, onClick: signOut, children: "Retry" })
9668
+ signOutError ? /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)("div", { role: "alert", className: "fd-body-sm", style: { padding: "0 14px 12px" }, children: [
9669
+ /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("span", { style: { display: "block", color: "var(--danger-text)", marginBottom: 6 }, children: signOutError }),
9670
+ /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("button", { type: "button", className: "fd-soon-link", disabled: signingOut, onClick: signOut, children: "Retry" })
9569
9671
  ] }) : null
9570
9672
  ] })
9571
9673
  ] })
@@ -9575,13 +9677,13 @@ function AccountMenu({
9575
9677
  }
9576
9678
 
9577
9679
  // src/components/platform/AppSwitcher.tsx
9578
- var React55 = __toESM(require("react"), 1);
9579
- var import_jsx_runtime81 = require("react/jsx-runtime");
9680
+ var React56 = __toESM(require("react"), 1);
9681
+ var import_jsx_runtime83 = require("react/jsx-runtime");
9580
9682
  function AppSwitcher({ apps: appsProp, onNavigate, className = "" }) {
9581
9683
  const { apps: contextApps } = useSessionContext();
9582
9684
  const apps = appsProp ?? contextApps ?? [];
9583
- const [open2, setOpen] = React55.useState(false);
9584
- const anchorRef = React55.useRef(null);
9685
+ const [open2, setOpen] = React56.useState(false);
9686
+ const anchorRef = React56.useRef(null);
9585
9687
  if (!apps.length) return null;
9586
9688
  const items = apps.map((app) => ({
9587
9689
  id: app.key,
@@ -9595,8 +9697,8 @@ function AppSwitcher({ apps: appsProp, onNavigate, className = "" }) {
9595
9697
  window.location.href = app.url;
9596
9698
  }
9597
9699
  }));
9598
- return /* @__PURE__ */ (0, import_jsx_runtime81.jsxs)(React55.Fragment, { children: [
9599
- /* @__PURE__ */ (0, import_jsx_runtime81.jsx)("span", { ref: anchorRef, className: ["fd-appswitch-anchor", className].filter(Boolean).join(" "), style: { display: "inline-flex" }, children: /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(
9700
+ return /* @__PURE__ */ (0, import_jsx_runtime83.jsxs)(React56.Fragment, { children: [
9701
+ /* @__PURE__ */ (0, import_jsx_runtime83.jsx)("span", { ref: anchorRef, className: ["fd-appswitch-anchor", className].filter(Boolean).join(" "), style: { display: "inline-flex" }, children: /* @__PURE__ */ (0, import_jsx_runtime83.jsx)(
9600
9702
  IconButton,
9601
9703
  {
9602
9704
  icon: "squares-four",
@@ -9606,7 +9708,7 @@ function AppSwitcher({ apps: appsProp, onNavigate, className = "" }) {
9606
9708
  onClick: () => setOpen((v) => !v)
9607
9709
  }
9608
9710
  ) }),
9609
- /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(
9711
+ /* @__PURE__ */ (0, import_jsx_runtime83.jsx)(
9610
9712
  Popover,
9611
9713
  {
9612
9714
  open: open2,
@@ -9617,17 +9719,17 @@ function AppSwitcher({ apps: appsProp, onNavigate, className = "" }) {
9617
9719
  label: "All flytedesk apps",
9618
9720
  width: 240,
9619
9721
  maxHeight: 360,
9620
- children: /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(Menu, { items, onClose: () => setOpen(false) })
9722
+ children: /* @__PURE__ */ (0, import_jsx_runtime83.jsx)(Menu, { items, onClose: () => setOpen(false) })
9621
9723
  }
9622
9724
  )
9623
9725
  ] });
9624
9726
  }
9625
9727
 
9626
9728
  // src/components/platform/AppearanceMenu.tsx
9627
- var React58 = __toESM(require("react"), 1);
9729
+ var React59 = __toESM(require("react"), 1);
9628
9730
 
9629
9731
  // src/kits/appearance.ts
9630
- var React56 = __toESM(require("react"), 1);
9732
+ var React57 = __toESM(require("react"), 1);
9631
9733
  var DEFAULT_STORAGE_KEY = "fd-appearance";
9632
9734
  var DEFAULT_PREFS = {
9633
9735
  theme: "system",
@@ -9739,8 +9841,8 @@ function watchAppearance(store, root = document.documentElement) {
9739
9841
  };
9740
9842
  }
9741
9843
  function useAppearancePrefs(store) {
9742
- const prefs = React56.useSyncExternalStore(store.subscribe, store.getSnapshot);
9743
- const update = React56.useCallback(
9844
+ const prefs = React57.useSyncExternalStore(store.subscribe, store.getSnapshot);
9845
+ const update = React57.useCallback(
9744
9846
  (patch) => {
9745
9847
  store.write({ ...store.getSnapshot(), ...patch });
9746
9848
  },
@@ -9750,21 +9852,21 @@ function useAppearancePrefs(store) {
9750
9852
  }
9751
9853
 
9752
9854
  // src/components/platform/AppearanceProvider.tsx
9753
- var React57 = __toESM(require("react"), 1);
9754
- var import_jsx_runtime82 = require("react/jsx-runtime");
9755
- var AppearanceStoreContext = React57.createContext(null);
9855
+ var React58 = __toESM(require("react"), 1);
9856
+ var import_jsx_runtime84 = require("react/jsx-runtime");
9857
+ var AppearanceStoreContext = React58.createContext(null);
9756
9858
  function AppearanceProvider({ store, children }) {
9757
- React57.useLayoutEffect(() => watchAppearance(store), [store]);
9758
- return /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(AppearanceStoreContext.Provider, { value: store, children });
9859
+ React58.useLayoutEffect(() => watchAppearance(store), [store]);
9860
+ return /* @__PURE__ */ (0, import_jsx_runtime84.jsx)(AppearanceStoreContext.Provider, { value: store, children });
9759
9861
  }
9760
9862
  function useAppearanceStore() {
9761
- const store = React57.useContext(AppearanceStoreContext);
9863
+ const store = React58.useContext(AppearanceStoreContext);
9762
9864
  if (!store) throw new Error("AppearanceMenu and useAppearanceStore must be rendered inside an <AppearanceProvider>.");
9763
9865
  return store;
9764
9866
  }
9765
9867
 
9766
9868
  // src/components/platform/AppearanceMenu.tsx
9767
- var import_jsx_runtime83 = require("react/jsx-runtime");
9869
+ var import_jsx_runtime85 = require("react/jsx-runtime");
9768
9870
  var THEME_OPTIONS = [
9769
9871
  { value: "light", label: "Light" },
9770
9872
  { value: "dark", label: "Dark" },
@@ -9778,11 +9880,11 @@ var TEXT_SCALE_OPTIONS = [
9778
9880
  ];
9779
9881
  function AppearanceMenu({ className = "" }) {
9780
9882
  const [prefs, update] = useAppearancePrefs(useAppearanceStore());
9781
- const [open2, setOpen] = React58.useState(false);
9782
- const anchorRef = React58.useRef(null);
9883
+ const [open2, setOpen] = React59.useState(false);
9884
+ const anchorRef = React59.useRef(null);
9783
9885
  const patch = (p) => update(p);
9784
- return /* @__PURE__ */ (0, import_jsx_runtime83.jsxs)(React58.Fragment, { children: [
9785
- /* @__PURE__ */ (0, import_jsx_runtime83.jsx)("span", { ref: anchorRef, className: ["fd-appearance-anchor", className].filter(Boolean).join(" "), style: { display: "inline-flex" }, children: /* @__PURE__ */ (0, import_jsx_runtime83.jsx)(
9886
+ return /* @__PURE__ */ (0, import_jsx_runtime85.jsxs)(React59.Fragment, { children: [
9887
+ /* @__PURE__ */ (0, import_jsx_runtime85.jsx)("span", { ref: anchorRef, className: ["fd-appearance-anchor", className].filter(Boolean).join(" "), style: { display: "inline-flex" }, children: /* @__PURE__ */ (0, import_jsx_runtime85.jsx)(
9786
9888
  IconButton,
9787
9889
  {
9788
9890
  icon: "circle-half",
@@ -9790,7 +9892,7 @@ function AppearanceMenu({ className = "" }) {
9790
9892
  onClick: () => setOpen((v) => !v)
9791
9893
  }
9792
9894
  ) }),
9793
- /* @__PURE__ */ (0, import_jsx_runtime83.jsx)(
9895
+ /* @__PURE__ */ (0, import_jsx_runtime85.jsx)(
9794
9896
  Popover,
9795
9897
  {
9796
9898
  open: open2,
@@ -9800,10 +9902,10 @@ function AppearanceMenu({ className = "" }) {
9800
9902
  padded: true,
9801
9903
  width: 260,
9802
9904
  label: "Appearance settings",
9803
- children: /* @__PURE__ */ (0, import_jsx_runtime83.jsxs)("div", { className: "fd-stack", style: { display: "flex", flexDirection: "column", gap: 16 }, children: [
9804
- /* @__PURE__ */ (0, import_jsx_runtime83.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: 6 }, children: [
9805
- /* @__PURE__ */ (0, import_jsx_runtime83.jsx)("span", { className: "fd-field-label", children: "Theme" }),
9806
- /* @__PURE__ */ (0, import_jsx_runtime83.jsx)(
9905
+ children: /* @__PURE__ */ (0, import_jsx_runtime85.jsxs)("div", { className: "fd-stack", style: { display: "flex", flexDirection: "column", gap: 16 }, children: [
9906
+ /* @__PURE__ */ (0, import_jsx_runtime85.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: 6 }, children: [
9907
+ /* @__PURE__ */ (0, import_jsx_runtime85.jsx)("span", { className: "fd-field-label", children: "Theme" }),
9908
+ /* @__PURE__ */ (0, import_jsx_runtime85.jsx)(
9807
9909
  SegmentedControl,
9808
9910
  {
9809
9911
  options: THEME_OPTIONS,
@@ -9813,9 +9915,9 @@ function AppearanceMenu({ className = "" }) {
9813
9915
  }
9814
9916
  )
9815
9917
  ] }),
9816
- /* @__PURE__ */ (0, import_jsx_runtime83.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: 6 }, children: [
9817
- /* @__PURE__ */ (0, import_jsx_runtime83.jsx)("span", { className: "fd-field-label", children: "Text size" }),
9818
- /* @__PURE__ */ (0, import_jsx_runtime83.jsx)(
9918
+ /* @__PURE__ */ (0, import_jsx_runtime85.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: 6 }, children: [
9919
+ /* @__PURE__ */ (0, import_jsx_runtime85.jsx)("span", { className: "fd-field-label", children: "Text size" }),
9920
+ /* @__PURE__ */ (0, import_jsx_runtime85.jsx)(
9819
9921
  SegmentedControl,
9820
9922
  {
9821
9923
  options: TEXT_SCALE_OPTIONS,
@@ -9825,7 +9927,7 @@ function AppearanceMenu({ className = "" }) {
9825
9927
  }
9826
9928
  )
9827
9929
  ] }),
9828
- /* @__PURE__ */ (0, import_jsx_runtime83.jsx)(
9930
+ /* @__PURE__ */ (0, import_jsx_runtime85.jsx)(
9829
9931
  Switch,
9830
9932
  {
9831
9933
  label: "High contrast",
@@ -9834,7 +9936,7 @@ function AppearanceMenu({ className = "" }) {
9834
9936
  onChange: (e) => patch({ highContrast: e.target.checked })
9835
9937
  }
9836
9938
  ),
9837
- /* @__PURE__ */ (0, import_jsx_runtime83.jsx)(
9939
+ /* @__PURE__ */ (0, import_jsx_runtime85.jsx)(
9838
9940
  Switch,
9839
9941
  {
9840
9942
  label: "Reduce motion",
@@ -9850,14 +9952,14 @@ function AppearanceMenu({ className = "" }) {
9850
9952
  }
9851
9953
 
9852
9954
  // src/components/platform/ApiSpecBrowser.tsx
9853
- var React59 = __toESM(require("react"), 1);
9854
- var import_jsx_runtime84 = require("react/jsx-runtime");
9955
+ var React60 = __toESM(require("react"), 1);
9956
+ var import_jsx_runtime86 = require("react/jsx-runtime");
9855
9957
  var METHOD_TONE = { GET: "success", POST: "info", PATCH: "warning", PUT: "warning", DELETE: "danger" };
9856
9958
  function Json({ obj }) {
9857
- return /* @__PURE__ */ (0, import_jsx_runtime84.jsx)("pre", { className: "fd-json", children: JSON.stringify(obj, null, 2) });
9959
+ return /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("pre", { className: "fd-json", children: JSON.stringify(obj, null, 2) });
9858
9960
  }
9859
9961
  function Endpoint({ s, onRequest }) {
9860
- const [tried, setTried] = React59.useState(null);
9962
+ const [tried, setTried] = React60.useState(null);
9861
9963
  const run = async () => {
9862
9964
  setTried("busy");
9863
9965
  const t0 = (window.performance || Date).now();
@@ -9868,50 +9970,50 @@ function Endpoint({ s, onRequest }) {
9868
9970
  setTried({ ms: Math.round((window.performance || Date).now() - t0), error: String(e && e.message || e) });
9869
9971
  }
9870
9972
  };
9871
- return /* @__PURE__ */ (0, import_jsx_runtime84.jsx)(Card, { elevation: "flat", padded: false, children: /* @__PURE__ */ (0, import_jsx_runtime84.jsxs)("div", { className: "fd-stack", style: { gap: 0 }, children: [
9872
- /* @__PURE__ */ (0, import_jsx_runtime84.jsxs)("div", { className: "fd-row", style: { gap: 10, padding: "14px 18px", flexWrap: "wrap" }, children: [
9873
- /* @__PURE__ */ (0, import_jsx_runtime84.jsx)(Badge, { tone: METHOD_TONE[s.method] || "neutral", children: s.method }),
9874
- /* @__PURE__ */ (0, import_jsx_runtime84.jsx)("code", { className: "fd-mono", style: { fontSize: 12.5, fontWeight: 600, color: "var(--text)", wordBreak: "break-all" }, children: s.path }),
9875
- s.isList ? /* @__PURE__ */ (0, import_jsx_runtime84.jsx)(Badge, { tone: "neutral", icon: "rows", children: "Paged list" }) : null,
9876
- /* @__PURE__ */ (0, import_jsx_runtime84.jsx)("span", { style: { flex: 1 } }),
9877
- /* @__PURE__ */ (0, import_jsx_runtime84.jsxs)("span", { className: "fd-body-sm fd-muted fd-mono", children: [
9973
+ return /* @__PURE__ */ (0, import_jsx_runtime86.jsx)(Card, { elevation: "flat", padded: false, children: /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("div", { className: "fd-stack", style: { gap: 0 }, children: [
9974
+ /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("div", { className: "fd-row", style: { gap: 10, padding: "14px 18px", flexWrap: "wrap" }, children: [
9975
+ /* @__PURE__ */ (0, import_jsx_runtime86.jsx)(Badge, { tone: METHOD_TONE[s.method] || "neutral", children: s.method }),
9976
+ /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("code", { className: "fd-mono", style: { fontSize: 12.5, fontWeight: 600, color: "var(--text)", wordBreak: "break-all" }, children: s.path }),
9977
+ s.isList ? /* @__PURE__ */ (0, import_jsx_runtime86.jsx)(Badge, { tone: "neutral", icon: "rows", children: "Paged list" }) : null,
9978
+ /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("span", { style: { flex: 1 } }),
9979
+ /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("span", { className: "fd-body-sm fd-muted fd-mono", children: [
9878
9980
  s.latency[0],
9879
9981
  "\u2013",
9880
9982
  s.latency[1],
9881
9983
  "ms"
9882
9984
  ] }),
9883
- /* @__PURE__ */ (0, import_jsx_runtime84.jsx)(Button, { size: "sm", variant: "secondary", icon: "play", loading: tried === "busy", onClick: run, children: "Try it" })
9985
+ /* @__PURE__ */ (0, import_jsx_runtime86.jsx)(Button, { size: "sm", variant: "secondary", icon: "play", loading: tried === "busy", onClick: run, children: "Try it" })
9884
9986
  ] }),
9885
- /* @__PURE__ */ (0, import_jsx_runtime84.jsxs)("div", { className: "fd-stack", style: { gap: 14, padding: "0 18px 16px" }, children: [
9886
- /* @__PURE__ */ (0, import_jsx_runtime84.jsxs)("div", { className: "fd-stack", style: { gap: 6 }, children: [
9887
- /* @__PURE__ */ (0, import_jsx_runtime84.jsx)("span", { className: "fd-body-sm", style: { fontWeight: 700 }, children: s.title }),
9888
- /* @__PURE__ */ (0, import_jsx_runtime84.jsx)("p", { className: "fd-body-sm fd-secondary", style: { margin: 0, textWrap: "pretty" }, children: s.purpose }),
9889
- s.usedBy && s.usedBy.length ? /* @__PURE__ */ (0, import_jsx_runtime84.jsx)("span", { className: "fd-row", style: { gap: 6, flexWrap: "wrap" }, children: s.usedBy.map((u) => /* @__PURE__ */ (0, import_jsx_runtime84.jsx)(Tag, { children: u }, u)) }) : null
9987
+ /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("div", { className: "fd-stack", style: { gap: 14, padding: "0 18px 16px" }, children: [
9988
+ /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("div", { className: "fd-stack", style: { gap: 6 }, children: [
9989
+ /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("span", { className: "fd-body-sm", style: { fontWeight: 700 }, children: s.title }),
9990
+ /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("p", { className: "fd-body-sm fd-secondary", style: { margin: 0, textWrap: "pretty" }, children: s.purpose }),
9991
+ s.usedBy && s.usedBy.length ? /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("span", { className: "fd-row", style: { gap: 6, flexWrap: "wrap" }, children: s.usedBy.map((u) => /* @__PURE__ */ (0, import_jsx_runtime86.jsx)(Tag, { children: u }, u)) }) : null
9890
9992
  ] }),
9891
- /* @__PURE__ */ (0, import_jsx_runtime84.jsxs)("div", { style: { display: "grid", gridTemplateColumns: "repeat(auto-fit,minmax(280px,1fr))", gap: 12, alignItems: "start" }, children: [
9892
- s.request ? /* @__PURE__ */ (0, import_jsx_runtime84.jsxs)("div", { className: "fd-stack", style: { gap: 6 }, children: [
9893
- /* @__PURE__ */ (0, import_jsx_runtime84.jsx)("span", { className: "fd-overline fd-muted", children: "Request body" }),
9894
- /* @__PURE__ */ (0, import_jsx_runtime84.jsx)(Json, { obj: s.request })
9993
+ /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("div", { style: { display: "grid", gridTemplateColumns: "repeat(auto-fit,minmax(280px,1fr))", gap: 12, alignItems: "start" }, children: [
9994
+ s.request ? /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("div", { className: "fd-stack", style: { gap: 6 }, children: [
9995
+ /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("span", { className: "fd-overline fd-muted", children: "Request body" }),
9996
+ /* @__PURE__ */ (0, import_jsx_runtime86.jsx)(Json, { obj: s.request })
9895
9997
  ] }) : null,
9896
- s.query ? /* @__PURE__ */ (0, import_jsx_runtime84.jsxs)("div", { className: "fd-stack", style: { gap: 6 }, children: [
9897
- /* @__PURE__ */ (0, import_jsx_runtime84.jsx)("span", { className: "fd-overline fd-muted", children: "Query" }),
9898
- /* @__PURE__ */ (0, import_jsx_runtime84.jsx)(Json, { obj: s.query })
9998
+ s.query ? /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("div", { className: "fd-stack", style: { gap: 6 }, children: [
9999
+ /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("span", { className: "fd-overline fd-muted", children: "Query" }),
10000
+ /* @__PURE__ */ (0, import_jsx_runtime86.jsx)(Json, { obj: s.query })
9899
10001
  ] }) : null,
9900
- /* @__PURE__ */ (0, import_jsx_runtime84.jsxs)("div", { className: "fd-stack", style: { gap: 6 }, children: [
9901
- /* @__PURE__ */ (0, import_jsx_runtime84.jsx)("span", { className: "fd-overline fd-muted", children: "Response 200" }),
9902
- /* @__PURE__ */ (0, import_jsx_runtime84.jsx)(Json, { obj: s.response })
10002
+ /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("div", { className: "fd-stack", style: { gap: 6 }, children: [
10003
+ /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("span", { className: "fd-overline fd-muted", children: "Response 200" }),
10004
+ /* @__PURE__ */ (0, import_jsx_runtime86.jsx)(Json, { obj: s.response })
9903
10005
  ] })
9904
10006
  ] }),
9905
- s.notes ? /* @__PURE__ */ (0, import_jsx_runtime84.jsx)(Flag, { tone: "info", statement: "Implementation note", cost: s.notes, actions: null }) : null,
9906
- tried && tried !== "busy" ? /* @__PURE__ */ (0, import_jsx_runtime84.jsxs)("div", { className: "fd-stack", style: { gap: 6 }, children: [
9907
- /* @__PURE__ */ (0, import_jsx_runtime84.jsxs)("span", { className: "fd-row", style: { gap: 8 }, children: [
9908
- /* @__PURE__ */ (0, import_jsx_runtime84.jsx)("span", { className: "fd-overline fd-muted", children: "Simulated response" }),
9909
- /* @__PURE__ */ (0, import_jsx_runtime84.jsxs)(Badge, { tone: tried.error ? "danger" : "success", icon: "timer", children: [
10007
+ s.notes ? /* @__PURE__ */ (0, import_jsx_runtime86.jsx)(Flag, { tone: "info", statement: "Implementation note", cost: s.notes, actions: null }) : null,
10008
+ tried && tried !== "busy" ? /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("div", { className: "fd-stack", style: { gap: 6 }, children: [
10009
+ /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("span", { className: "fd-row", style: { gap: 8 }, children: [
10010
+ /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("span", { className: "fd-overline fd-muted", children: "Simulated response" }),
10011
+ /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)(Badge, { tone: tried.error ? "danger" : "success", icon: "timer", children: [
9910
10012
  tried.ms,
9911
10013
  "ms"
9912
10014
  ] })
9913
10015
  ] }),
9914
- /* @__PURE__ */ (0, import_jsx_runtime84.jsx)(Json, { obj: tried.error ? { error: tried.error } : tried.data })
10016
+ /* @__PURE__ */ (0, import_jsx_runtime86.jsx)(Json, { obj: tried.error ? { error: tried.error } : tried.data })
9915
10017
  ] }) : null
9916
10018
  ] })
9917
10019
  ] }) });
@@ -9930,58 +10032,58 @@ function ApiSpecBrowser({
9930
10032
  className = "",
9931
10033
  ...rest
9932
10034
  }) {
9933
- const [q, setQ] = React59.useState("");
9934
- const [method, setMethod] = React59.useState(null);
9935
- const [mod, setMod] = React59.useState(null);
9936
- const [listOnly, setListOnly] = React59.useState(false);
10035
+ const [q, setQ] = React60.useState("");
10036
+ const [method, setMethod] = React60.useState(null);
10037
+ const [mod, setMod] = React60.useState(null);
10038
+ const [listOnly, setListOnly] = React60.useState(false);
9937
10039
  const activeModule = modules && modules.find((m) => m.id === mod);
9938
10040
  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())));
9939
10041
  const effGroups = groups && groups.length ? groups : [["All endpoints", spec.map((s) => s.id)]];
9940
10042
  const methods = [...new Set(spec.map((s) => s.method))];
9941
10043
  const listCount = spec.filter((s) => s.isList).length;
9942
- return /* @__PURE__ */ (0, import_jsx_runtime84.jsxs)("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 20, maxWidth: 1100 }, ...rest, children: [
9943
- /* @__PURE__ */ (0, import_jsx_runtime84.jsxs)("div", { className: "fd-stack", style: { gap: 10 }, children: [
9944
- kicker ? /* @__PURE__ */ (0, import_jsx_runtime84.jsx)("span", { className: "fd-overline fd-muted", children: kicker }) : null,
9945
- /* @__PURE__ */ (0, import_jsx_runtime84.jsx)("h1", { className: "fd-h1", style: { margin: 0 }, children: title }),
9946
- lede ? /* @__PURE__ */ (0, import_jsx_runtime84.jsx)("p", { className: "fd-body fd-secondary fd-prose", style: { margin: 0 }, children: lede }) : null
10044
+ return /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 20, maxWidth: 1100 }, ...rest, children: [
10045
+ /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("div", { className: "fd-stack", style: { gap: 10 }, children: [
10046
+ kicker ? /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("span", { className: "fd-overline fd-muted", children: kicker }) : null,
10047
+ /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("h1", { className: "fd-h1", style: { margin: 0 }, children: title }),
10048
+ lede ? /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("p", { className: "fd-body fd-secondary fd-prose", style: { margin: 0 }, children: lede }) : null
9947
10049
  ] }),
9948
- modules && modules.length ? /* @__PURE__ */ (0, import_jsx_runtime84.jsxs)("div", { className: "fd-stack", style: { gap: 8 }, children: [
9949
- /* @__PURE__ */ (0, import_jsx_runtime84.jsx)("span", { className: "fd-overline fd-muted", children: "Filter by screen \u2014 every endpoint that screen depends on" }),
9950
- /* @__PURE__ */ (0, import_jsx_runtime84.jsxs)("div", { className: "fd-row", style: { gap: 8, flexWrap: "wrap" }, children: [
9951
- /* @__PURE__ */ (0, import_jsx_runtime84.jsxs)(Tag, { icon: "stack", selected: !mod, onClick: () => setMod(null), children: [
10050
+ modules && modules.length ? /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("div", { className: "fd-stack", style: { gap: 8 }, children: [
10051
+ /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("span", { className: "fd-overline fd-muted", children: "Filter by screen \u2014 every endpoint that screen depends on" }),
10052
+ /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("div", { className: "fd-row", style: { gap: 8, flexWrap: "wrap" }, children: [
10053
+ /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)(Tag, { icon: "stack", selected: !mod, onClick: () => setMod(null), children: [
9952
10054
  "All screens ",
9953
- /* @__PURE__ */ (0, import_jsx_runtime84.jsx)("span", { className: "fd-mono", children: spec.length })
10055
+ /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("span", { className: "fd-mono", children: spec.length })
9954
10056
  ] }),
9955
- modules.map((m) => /* @__PURE__ */ (0, import_jsx_runtime84.jsxs)(Tag, { icon: m.icon, selected: mod === m.id, onClick: () => setMod(mod === m.id ? null : m.id), children: [
10057
+ modules.map((m) => /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)(Tag, { icon: m.icon, selected: mod === m.id, onClick: () => setMod(mod === m.id ? null : m.id), children: [
9956
10058
  m.label,
9957
10059
  " ",
9958
- /* @__PURE__ */ (0, import_jsx_runtime84.jsx)("span", { className: "fd-mono", children: m.endpoints.length })
10060
+ /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("span", { className: "fd-mono", children: m.endpoints.length })
9959
10061
  ] }, m.id))
9960
10062
  ] }),
9961
- activeModule ? /* @__PURE__ */ (0, import_jsx_runtime84.jsx)(
10063
+ activeModule ? /* @__PURE__ */ (0, import_jsx_runtime86.jsx)(
9962
10064
  Flag,
9963
10065
  {
9964
10066
  tone: "info",
9965
10067
  statement: activeModule.label + " calls " + activeModule.endpoints.length + " endpoints.",
9966
10068
  cost: "Integration checklist for this screen: " + activeModule.endpoints.join(", ") + ". Wire these and the screen is done.",
9967
- actions: /* @__PURE__ */ (0, import_jsx_runtime84.jsx)(Button, { size: "sm", variant: "ghost", icon: "x", onClick: () => setMod(null), children: "Show all screens" })
10069
+ actions: /* @__PURE__ */ (0, import_jsx_runtime86.jsx)(Button, { size: "sm", variant: "ghost", icon: "x", onClick: () => setMod(null), children: "Show all screens" })
9968
10070
  }
9969
10071
  ) : null
9970
10072
  ] }) : null,
9971
- sourceNote ? /* @__PURE__ */ (0, import_jsx_runtime84.jsx)(Flag, { tone: "info", statement: "Design-first: this page is the spec.", cost: sourceNote, actions: null }) : null,
9972
- /* @__PURE__ */ (0, import_jsx_runtime84.jsxs)("div", { className: "fd-row", style: { gap: 10, flexWrap: "wrap" }, children: [
9973
- /* @__PURE__ */ (0, import_jsx_runtime84.jsx)(Input, { icon: "magnifying-glass", placeholder: "Find an endpoint, screen, or behavior", value: q, onChange: (e) => setQ(e.target.value), style: { width: 300 } }),
9974
- methods.map((m) => /* @__PURE__ */ (0, import_jsx_runtime84.jsxs)(Tag, { selected: method === m, onClick: () => setMethod(method === m ? null : m), children: [
10073
+ sourceNote ? /* @__PURE__ */ (0, import_jsx_runtime86.jsx)(Flag, { tone: "info", statement: "Design-first: this page is the spec.", cost: sourceNote, actions: null }) : null,
10074
+ /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("div", { className: "fd-row", style: { gap: 10, flexWrap: "wrap" }, children: [
10075
+ /* @__PURE__ */ (0, import_jsx_runtime86.jsx)(Input, { icon: "magnifying-glass", placeholder: "Find an endpoint, screen, or behavior", value: q, onChange: (e) => setQ(e.target.value), style: { width: 300 } }),
10076
+ methods.map((m) => /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)(Tag, { selected: method === m, onClick: () => setMethod(method === m ? null : m), children: [
9975
10077
  m,
9976
10078
  " ",
9977
- /* @__PURE__ */ (0, import_jsx_runtime84.jsx)("span", { className: "fd-mono", children: spec.filter((s) => s.method === m).length })
10079
+ /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("span", { className: "fd-mono", children: spec.filter((s) => s.method === m).length })
9978
10080
  ] }, m)),
9979
- listCount ? /* @__PURE__ */ (0, import_jsx_runtime84.jsxs)(Tag, { icon: "rows", selected: listOnly, onClick: () => setListOnly(!listOnly), children: [
10081
+ listCount ? /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)(Tag, { icon: "rows", selected: listOnly, onClick: () => setListOnly(!listOnly), children: [
9980
10082
  "Paged lists ",
9981
- /* @__PURE__ */ (0, import_jsx_runtime84.jsx)("span", { className: "fd-mono", children: listCount })
10083
+ /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("span", { className: "fd-mono", children: listCount })
9982
10084
  ] }) : null,
9983
- /* @__PURE__ */ (0, import_jsx_runtime84.jsx)("span", { style: { flex: 1 } }),
9984
- /* @__PURE__ */ (0, import_jsx_runtime84.jsxs)("span", { className: "fd-body-sm fd-muted", children: [
10085
+ /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("span", { style: { flex: 1 } }),
10086
+ /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("span", { className: "fd-body-sm fd-muted", children: [
9985
10087
  hits.length,
9986
10088
  " of ",
9987
10089
  spec.length,
@@ -9989,31 +10091,31 @@ function ApiSpecBrowser({
9989
10091
  listCount ? " \xB7 " + listCount + " paged" : ""
9990
10092
  ] })
9991
10093
  ] }),
9992
- hits.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime84.jsx)(Card, { elevation: "flat", children: /* @__PURE__ */ (0, import_jsx_runtime84.jsx)("p", { className: "fd-body-sm fd-muted", style: { margin: 0 }, children: "No endpoint matches those filters." }) }) : effGroups.map(([g, ids]) => {
10094
+ hits.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime86.jsx)(Card, { elevation: "flat", children: /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("p", { className: "fd-body-sm fd-muted", style: { margin: 0 }, children: "No endpoint matches those filters." }) }) : effGroups.map(([g, ids]) => {
9993
10095
  const items = hits.filter((s) => ids.indexOf(s.id) >= 0);
9994
10096
  if (!items.length) return null;
9995
- return /* @__PURE__ */ (0, import_jsx_runtime84.jsxs)("div", { className: "fd-stack", style: { gap: 12 }, children: [
9996
- /* @__PURE__ */ (0, import_jsx_runtime84.jsx)("span", { className: "fd-label-lg", children: g }),
9997
- items.map((s) => /* @__PURE__ */ (0, import_jsx_runtime84.jsx)(Endpoint, { s, onRequest }, s.id))
10097
+ return /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("div", { className: "fd-stack", style: { gap: 12 }, children: [
10098
+ /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("span", { className: "fd-label-lg", children: g }),
10099
+ items.map((s) => /* @__PURE__ */ (0, import_jsx_runtime86.jsx)(Endpoint, { s, onRequest }, s.id))
9998
10100
  ] }, g);
9999
10101
  }),
10000
- conventions && conventions.length ? /* @__PURE__ */ (0, import_jsx_runtime84.jsx)(Card, { title: "Cross-cutting conventions", elevation: "flat", children: /* @__PURE__ */ (0, import_jsx_runtime84.jsx)("div", { className: "fd-stack", style: { gap: 10 }, children: conventions.map(([k, v]) => /* @__PURE__ */ (0, import_jsx_runtime84.jsxs)("div", { className: "fd-row", style: { gap: 12, alignItems: "flex-start" }, children: [
10001
- /* @__PURE__ */ (0, import_jsx_runtime84.jsx)("span", { className: "fd-overline fd-muted", style: { width: 110, flex: "none", paddingTop: 2 }, children: k }),
10002
- /* @__PURE__ */ (0, import_jsx_runtime84.jsx)("span", { className: "fd-body-sm fd-secondary", style: { textWrap: "pretty" }, children: v })
10102
+ conventions && conventions.length ? /* @__PURE__ */ (0, import_jsx_runtime86.jsx)(Card, { title: "Cross-cutting conventions", elevation: "flat", children: /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("div", { className: "fd-stack", style: { gap: 10 }, children: conventions.map(([k, v]) => /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("div", { className: "fd-row", style: { gap: 12, alignItems: "flex-start" }, children: [
10103
+ /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("span", { className: "fd-overline fd-muted", style: { width: 110, flex: "none", paddingTop: 2 }, children: k }),
10104
+ /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("span", { className: "fd-body-sm fd-secondary", style: { textWrap: "pretty" }, children: v })
10003
10105
  ] }, k)) }) }) : null,
10004
- openQuestions && openQuestions.length ? /* @__PURE__ */ (0, import_jsx_runtime84.jsx)(Collapsible, { icon: "list-checks", title: "Open questions before implementation", subtitle: openQuestions.length + " unresolved", children: /* @__PURE__ */ (0, import_jsx_runtime84.jsx)("div", { className: "fd-stack", style: { gap: 8 }, children: openQuestions.map(([id, question, why]) => /* @__PURE__ */ (0, import_jsx_runtime84.jsxs)("div", { className: "fd-row", style: { gap: 10, alignItems: "flex-start", padding: "8px 0", borderTop: "1px solid var(--border)" }, children: [
10005
- /* @__PURE__ */ (0, import_jsx_runtime84.jsx)(Badge, { tone: "danger", children: id }),
10006
- /* @__PURE__ */ (0, import_jsx_runtime84.jsxs)("span", { className: "fd-stack", style: { gap: 2, flex: 1 }, children: [
10007
- /* @__PURE__ */ (0, import_jsx_runtime84.jsx)("span", { className: "fd-body-sm", style: { fontWeight: 600 }, children: question }),
10008
- /* @__PURE__ */ (0, import_jsx_runtime84.jsx)("span", { className: "fd-body-sm fd-muted", children: why })
10106
+ openQuestions && openQuestions.length ? /* @__PURE__ */ (0, import_jsx_runtime86.jsx)(Collapsible, { icon: "list-checks", title: "Open questions before implementation", subtitle: openQuestions.length + " unresolved", children: /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("div", { className: "fd-stack", style: { gap: 8 }, children: openQuestions.map(([id, question, why]) => /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("div", { className: "fd-row", style: { gap: 10, alignItems: "flex-start", padding: "8px 0", borderTop: "1px solid var(--border)" }, children: [
10107
+ /* @__PURE__ */ (0, import_jsx_runtime86.jsx)(Badge, { tone: "danger", children: id }),
10108
+ /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("span", { className: "fd-stack", style: { gap: 2, flex: 1 }, children: [
10109
+ /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("span", { className: "fd-body-sm", style: { fontWeight: 600 }, children: question }),
10110
+ /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("span", { className: "fd-body-sm fd-muted", children: why })
10009
10111
  ] })
10010
10112
  ] }, id)) }) }) : null
10011
10113
  ] });
10012
10114
  }
10013
10115
 
10014
10116
  // src/components/platform/ProfilePage.tsx
10015
- var React60 = __toESM(require("react"), 1);
10016
- var import_jsx_runtime85 = require("react/jsx-runtime");
10117
+ var React61 = __toESM(require("react"), 1);
10118
+ var import_jsx_runtime87 = require("react/jsx-runtime");
10017
10119
  function fieldInitialValue(field, user) {
10018
10120
  if (field.value) return field.value(user);
10019
10121
  const raw = user[field.key];
@@ -10048,21 +10150,21 @@ function ProfilePage({
10048
10150
  }) {
10049
10151
  const { user: sessionUser, roles, permissions, saveProfile: saveProfile2 } = useSessionContext();
10050
10152
  const user = userProp || sessionUser;
10051
- const initialFieldValues = React60.useMemo(() => {
10153
+ const initialFieldValues = React61.useMemo(() => {
10052
10154
  const values2 = {};
10053
10155
  for (const field of fields) values2[field.key] = fieldInitialValue(field, user);
10054
10156
  return values2;
10055
10157
  }, [user.id, fields]);
10056
- const initialNotify = React60.useMemo(() => {
10158
+ const initialNotify = React61.useMemo(() => {
10057
10159
  const values2 = {};
10058
10160
  for (const n of notifications) values2[n.key] = !!user.notify?.[n.key];
10059
10161
  return values2;
10060
10162
  }, [user.id, notifications]);
10061
- const [values, setValues] = React60.useState(initialFieldValues);
10062
- const [notify, setNotify] = React60.useState(initialNotify);
10063
- const [saving, setSaving] = React60.useState(false);
10064
- const [saved, setSaved] = React60.useState(false);
10065
- const [prevUserId, setPrevUserId] = React60.useState(user.id);
10163
+ const [values, setValues] = React61.useState(initialFieldValues);
10164
+ const [notify, setNotify] = React61.useState(initialNotify);
10165
+ const [saving, setSaving] = React61.useState(false);
10166
+ const [saved, setSaved] = React61.useState(false);
10167
+ const [prevUserId, setPrevUserId] = React61.useState(user.id);
10066
10168
  if (user.id !== prevUserId) {
10067
10169
  setPrevUserId(user.id);
10068
10170
  setValues(initialFieldValues);
@@ -10099,37 +10201,37 @@ function ProfilePage({
10099
10201
  };
10100
10202
  const displayName = fields.some((f) => f.key === "name") ? values.name || user.name : user.name;
10101
10203
  const fieldGroups = groupFields(fields);
10102
- return /* @__PURE__ */ (0, import_jsx_runtime85.jsxs)("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 20, maxWidth: 860 }, children: [
10103
- /* @__PURE__ */ (0, import_jsx_runtime85.jsxs)("div", { className: "fd-stack", style: { gap: 10 }, children: [
10104
- /* @__PURE__ */ (0, import_jsx_runtime85.jsx)("span", { className: "fd-overline fd-muted", children: "Account" }),
10105
- /* @__PURE__ */ (0, import_jsx_runtime85.jsx)("h1", { className: "fd-h1", style: { margin: 0 }, children: "Your profile" }),
10106
- /* @__PURE__ */ (0, import_jsx_runtime85.jsx)("p", { className: "fd-body fd-secondary fd-prose", style: { margin: 0 }, children: "How you appear to colleagues and clients across every flytedesk app, and what we send you." })
10204
+ return /* @__PURE__ */ (0, import_jsx_runtime87.jsxs)("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 20, maxWidth: 860 }, children: [
10205
+ /* @__PURE__ */ (0, import_jsx_runtime87.jsxs)("div", { className: "fd-stack", style: { gap: 10 }, children: [
10206
+ /* @__PURE__ */ (0, import_jsx_runtime87.jsx)("span", { className: "fd-overline fd-muted", children: "Account" }),
10207
+ /* @__PURE__ */ (0, import_jsx_runtime87.jsx)("h1", { className: "fd-h1", style: { margin: 0 }, children: "Your profile" }),
10208
+ /* @__PURE__ */ (0, import_jsx_runtime87.jsx)("p", { className: "fd-body fd-secondary fd-prose", style: { margin: 0 }, children: "How you appear to colleagues and clients across every flytedesk app, and what we send you." })
10107
10209
  ] }),
10108
- /* @__PURE__ */ (0, import_jsx_runtime85.jsx)(Card, { elevation: "flat", children: /* @__PURE__ */ (0, import_jsx_runtime85.jsxs)("div", { className: "fd-row", style: { gap: 16, flexWrap: "wrap", alignItems: "flex-start" }, children: [
10109
- /* @__PURE__ */ (0, import_jsx_runtime85.jsx)(Avatar, { name: displayName, size: "lg" }),
10110
- /* @__PURE__ */ (0, import_jsx_runtime85.jsxs)("div", { className: "fd-stack", style: { gap: 4, flex: 1, minWidth: 200 }, children: [
10111
- /* @__PURE__ */ (0, import_jsx_runtime85.jsx)("span", { className: "fd-h3", style: { margin: 0 }, children: displayName }),
10112
- /* @__PURE__ */ (0, import_jsx_runtime85.jsxs)("span", { className: "fd-row", style: { gap: 6, flexWrap: "wrap", paddingTop: 4 }, children: [
10113
- roles.map((r) => /* @__PURE__ */ (0, import_jsx_runtime85.jsx)(Badge, { tone: r.id === "owner" ? "success" : "neutral", children: r.name }, r.id)),
10114
- user.sso ? /* @__PURE__ */ (0, import_jsx_runtime85.jsx)(Badge, { tone: "info", icon: "shield-check", children: "SSO" }) : null
10210
+ /* @__PURE__ */ (0, import_jsx_runtime87.jsx)(Card, { elevation: "flat", children: /* @__PURE__ */ (0, import_jsx_runtime87.jsxs)("div", { className: "fd-row", style: { gap: 16, flexWrap: "wrap", alignItems: "flex-start" }, children: [
10211
+ /* @__PURE__ */ (0, import_jsx_runtime87.jsx)(Avatar, { name: displayName, size: "lg" }),
10212
+ /* @__PURE__ */ (0, import_jsx_runtime87.jsxs)("div", { className: "fd-stack", style: { gap: 4, flex: 1, minWidth: 200 }, children: [
10213
+ /* @__PURE__ */ (0, import_jsx_runtime87.jsx)("span", { className: "fd-h3", style: { margin: 0 }, children: displayName }),
10214
+ /* @__PURE__ */ (0, import_jsx_runtime87.jsxs)("span", { className: "fd-row", style: { gap: 6, flexWrap: "wrap", paddingTop: 4 }, children: [
10215
+ roles.map((r) => /* @__PURE__ */ (0, import_jsx_runtime87.jsx)(Badge, { tone: r.id === "owner" ? "success" : "neutral", children: r.name }, r.id)),
10216
+ user.sso ? /* @__PURE__ */ (0, import_jsx_runtime87.jsx)(Badge, { tone: "info", icon: "shield-check", children: "SSO" }) : null
10115
10217
  ] })
10116
10218
  ] }),
10117
- onChangePhoto ? /* @__PURE__ */ (0, import_jsx_runtime85.jsx)(Button, { variant: "secondary", size: "sm", icon: "image", onClick: onChangePhoto, children: "Change photo" }) : null
10219
+ onChangePhoto ? /* @__PURE__ */ (0, import_jsx_runtime87.jsx)(Button, { variant: "secondary", size: "sm", icon: "image", onClick: onChangePhoto, children: "Change photo" }) : null
10118
10220
  ] }) }),
10119
- fieldGroups.map(({ group, description, fields: groupFieldDefs }) => /* @__PURE__ */ (0, import_jsx_runtime85.jsx)(
10221
+ fieldGroups.map(({ group, description, fields: groupFieldDefs }) => /* @__PURE__ */ (0, import_jsx_runtime87.jsx)(
10120
10222
  Card,
10121
10223
  {
10122
- title: description ? /* @__PURE__ */ (0, import_jsx_runtime85.jsxs)("span", { className: "fd-stack", style: { gap: 2 }, children: [
10123
- /* @__PURE__ */ (0, import_jsx_runtime85.jsx)("span", { children: group }),
10124
- /* @__PURE__ */ (0, import_jsx_runtime85.jsx)("span", { className: "fd-body-sm fd-muted", style: { fontWeight: 400 }, children: description })
10224
+ title: description ? /* @__PURE__ */ (0, import_jsx_runtime87.jsxs)("span", { className: "fd-stack", style: { gap: 2 }, children: [
10225
+ /* @__PURE__ */ (0, import_jsx_runtime87.jsx)("span", { children: group }),
10226
+ /* @__PURE__ */ (0, import_jsx_runtime87.jsx)("span", { className: "fd-body-sm fd-muted", style: { fontWeight: 400 }, children: description })
10125
10227
  ] }) : group,
10126
10228
  elevation: "flat",
10127
- children: /* @__PURE__ */ (0, import_jsx_runtime85.jsxs)("div", { className: "fd-stack", style: { gap: 14 }, children: [
10128
- /* @__PURE__ */ (0, import_jsx_runtime85.jsx)("div", { style: { display: "grid", gridTemplateColumns: "repeat(auto-fit,minmax(220px,1fr))", gap: 14 }, children: groupFieldDefs.filter((f) => f.type !== "textarea").map((field) => {
10229
+ children: /* @__PURE__ */ (0, import_jsx_runtime87.jsxs)("div", { className: "fd-stack", style: { gap: 14 }, children: [
10230
+ /* @__PURE__ */ (0, import_jsx_runtime87.jsx)("div", { style: { display: "grid", gridTemplateColumns: "repeat(auto-fit,minmax(220px,1fr))", gap: 14 }, children: groupFieldDefs.filter((f) => f.type !== "textarea").map((field) => {
10129
10231
  const help = typeof field.help === "function" ? field.help(user) : field.help;
10130
10232
  const readOnly = field.readOnly || field.type === "readonly";
10131
10233
  if (field.type === "select") {
10132
- return /* @__PURE__ */ (0, import_jsx_runtime85.jsx)(
10234
+ return /* @__PURE__ */ (0, import_jsx_runtime87.jsx)(
10133
10235
  Select,
10134
10236
  {
10135
10237
  label: field.label,
@@ -10143,7 +10245,7 @@ function ProfilePage({
10143
10245
  field.key
10144
10246
  );
10145
10247
  }
10146
- return /* @__PURE__ */ (0, import_jsx_runtime85.jsx)(
10248
+ return /* @__PURE__ */ (0, import_jsx_runtime87.jsx)(
10147
10249
  Input,
10148
10250
  {
10149
10251
  label: field.label,
@@ -10159,7 +10261,7 @@ function ProfilePage({
10159
10261
  }) }),
10160
10262
  groupFieldDefs.filter((f) => f.type === "textarea").map((field) => {
10161
10263
  const help = typeof field.help === "function" ? field.help(user) : field.help;
10162
- return /* @__PURE__ */ (0, import_jsx_runtime85.jsx)(
10264
+ return /* @__PURE__ */ (0, import_jsx_runtime87.jsx)(
10163
10265
  Textarea,
10164
10266
  {
10165
10267
  label: field.label,
@@ -10179,16 +10281,16 @@ function ProfilePage({
10179
10281
  group
10180
10282
  )),
10181
10283
  extra,
10182
- notifications.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime85.jsx)(Card, { title: "Notifications", elevation: "flat", children: /* @__PURE__ */ (0, import_jsx_runtime85.jsx)("div", { className: "fd-stack", style: { gap: 14 }, children: notifications.map((n) => /* @__PURE__ */ (0, import_jsx_runtime85.jsx)(Switch, { checked: !!notify[n.key], onChange: () => toggleNotify(n.key), label: n.label, description: n.description }, n.key)) }) }) : null,
10183
- /* @__PURE__ */ (0, import_jsx_runtime85.jsxs)(
10284
+ notifications.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime87.jsx)(Card, { title: "Notifications", elevation: "flat", children: /* @__PURE__ */ (0, import_jsx_runtime87.jsx)("div", { className: "fd-stack", style: { gap: 14 }, children: notifications.map((n) => /* @__PURE__ */ (0, import_jsx_runtime87.jsx)(Switch, { checked: !!notify[n.key], onChange: () => toggleNotify(n.key), label: n.label, description: n.description }, n.key)) }) }) : null,
10285
+ /* @__PURE__ */ (0, import_jsx_runtime87.jsxs)(
10184
10286
  Card,
10185
10287
  {
10186
- title: /* @__PURE__ */ (0, import_jsx_runtime85.jsxs)("span", { className: "fd-stack", style: { gap: 2 }, children: [
10187
- /* @__PURE__ */ (0, import_jsx_runtime85.jsx)("span", { children: "Access" }),
10188
- /* @__PURE__ */ (0, import_jsx_runtime85.jsx)("span", { className: "fd-body-sm fd-muted", style: { fontWeight: 400 }, children: "What your roles grant you" })
10288
+ title: /* @__PURE__ */ (0, import_jsx_runtime87.jsxs)("span", { className: "fd-stack", style: { gap: 2 }, children: [
10289
+ /* @__PURE__ */ (0, import_jsx_runtime87.jsx)("span", { children: "Access" }),
10290
+ /* @__PURE__ */ (0, import_jsx_runtime87.jsx)("span", { className: "fd-body-sm fd-muted", style: { fontWeight: 400 }, children: "What your roles grant you" })
10189
10291
  ] }),
10190
10292
  elevation: "flat",
10191
- action: /* @__PURE__ */ (0, import_jsx_runtime85.jsx)(
10293
+ action: /* @__PURE__ */ (0, import_jsx_runtime87.jsx)(
10192
10294
  Button,
10193
10295
  {
10194
10296
  size: "sm",
@@ -10199,39 +10301,39 @@ function ProfilePage({
10199
10301
  }
10200
10302
  ),
10201
10303
  children: [
10202
- /* @__PURE__ */ (0, import_jsx_runtime85.jsxs)("div", { className: "fd-stack", style: { gap: 0 }, children: [
10203
- /* @__PURE__ */ (0, import_jsx_runtime85.jsx)(CardRow, { label: "Roles", children: roles.map((r) => r.name).join(", ") || "None" }),
10204
- /* @__PURE__ */ (0, import_jsx_runtime85.jsxs)(CardRow, { label: "Permissions", children: [
10304
+ /* @__PURE__ */ (0, import_jsx_runtime87.jsxs)("div", { className: "fd-stack", style: { gap: 0 }, children: [
10305
+ /* @__PURE__ */ (0, import_jsx_runtime87.jsx)(CardRow, { label: "Roles", children: roles.map((r) => r.name).join(", ") || "None" }),
10306
+ /* @__PURE__ */ (0, import_jsx_runtime87.jsxs)(CardRow, { label: "Permissions", children: [
10205
10307
  permissions.length,
10206
10308
  " granted"
10207
10309
  ] }),
10208
- /* @__PURE__ */ (0, import_jsx_runtime85.jsx)(CardRow, { label: "Member since", children: user.joined || "\u2014" })
10310
+ /* @__PURE__ */ (0, import_jsx_runtime87.jsx)(CardRow, { label: "Member since", children: user.joined || "\u2014" })
10209
10311
  ] }),
10210
- /* @__PURE__ */ (0, import_jsx_runtime85.jsx)("p", { className: "fd-body-sm fd-muted", style: { margin: "12px 0 0" }, children: "You cannot change your own roles \u2014 that is the point of them. An administrator manages roles from Admin \u2192 Users." })
10312
+ /* @__PURE__ */ (0, import_jsx_runtime87.jsx)("p", { className: "fd-body-sm fd-muted", style: { margin: "12px 0 0" }, children: "You cannot change your own roles \u2014 that is the point of them. An administrator manages roles from Admin \u2192 Users." })
10211
10313
  ]
10212
10314
  }
10213
10315
  ),
10214
- sessions ? /* @__PURE__ */ (0, import_jsx_runtime85.jsx)(
10316
+ sessions ? /* @__PURE__ */ (0, import_jsx_runtime87.jsx)(
10215
10317
  Card,
10216
10318
  {
10217
10319
  title: "Signed-in devices",
10218
10320
  elevation: "flat",
10219
- action: /* @__PURE__ */ (0, import_jsx_runtime85.jsx)(Button, { size: "sm", variant: "ghost", icon: "sign-out", onClick: onSignOutEverywhere, children: "Sign out everywhere" }),
10220
- children: /* @__PURE__ */ (0, import_jsx_runtime85.jsx)("div", { className: "fd-stack", style: { gap: 0 }, children: sessions.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime85.jsx)("p", { className: "fd-body-sm fd-muted", style: { margin: 0 }, children: "No other signed-in devices." }) : sessions.map((s) => /* @__PURE__ */ (0, import_jsx_runtime85.jsxs)("div", { className: "fd-row", style: { gap: 12, padding: "10px 0", borderTop: "1px solid var(--border)", flexWrap: "wrap" }, children: [
10221
- /* @__PURE__ */ (0, import_jsx_runtime85.jsx)("i", { className: "ph ph-device-mobile", style: { fontSize: 16, color: "var(--text-muted)" }, "aria-hidden": "true" }),
10222
- /* @__PURE__ */ (0, import_jsx_runtime85.jsxs)("span", { className: "fd-stack", style: { gap: 1, flex: 1, minWidth: 160 }, children: [
10223
- /* @__PURE__ */ (0, import_jsx_runtime85.jsx)("span", { className: "fd-body-sm", style: { fontWeight: 600 }, children: s.device }),
10224
- /* @__PURE__ */ (0, import_jsx_runtime85.jsxs)("span", { className: "fd-body-sm fd-muted", children: [
10321
+ action: /* @__PURE__ */ (0, import_jsx_runtime87.jsx)(Button, { size: "sm", variant: "ghost", icon: "sign-out", onClick: onSignOutEverywhere, children: "Sign out everywhere" }),
10322
+ children: /* @__PURE__ */ (0, import_jsx_runtime87.jsx)("div", { className: "fd-stack", style: { gap: 0 }, children: sessions.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime87.jsx)("p", { className: "fd-body-sm fd-muted", style: { margin: 0 }, children: "No other signed-in devices." }) : sessions.map((s) => /* @__PURE__ */ (0, import_jsx_runtime87.jsxs)("div", { className: "fd-row", style: { gap: 12, padding: "10px 0", borderTop: "1px solid var(--border)", flexWrap: "wrap" }, children: [
10323
+ /* @__PURE__ */ (0, import_jsx_runtime87.jsx)("i", { className: "ph ph-device-mobile", style: { fontSize: 16, color: "var(--text-muted)" }, "aria-hidden": "true" }),
10324
+ /* @__PURE__ */ (0, import_jsx_runtime87.jsxs)("span", { className: "fd-stack", style: { gap: 1, flex: 1, minWidth: 160 }, children: [
10325
+ /* @__PURE__ */ (0, import_jsx_runtime87.jsx)("span", { className: "fd-body-sm", style: { fontWeight: 600 }, children: s.device }),
10326
+ /* @__PURE__ */ (0, import_jsx_runtime87.jsxs)("span", { className: "fd-body-sm fd-muted", children: [
10225
10327
  s.where,
10226
10328
  " \xB7 ",
10227
10329
  s.when
10228
10330
  ] })
10229
10331
  ] }),
10230
- s.current ? /* @__PURE__ */ (0, import_jsx_runtime85.jsx)(Badge, { tone: "success", dot: true, children: "This device" }) : /* @__PURE__ */ (0, import_jsx_runtime85.jsx)(Button, { size: "sm", variant: "ghost", children: "Revoke" })
10332
+ s.current ? /* @__PURE__ */ (0, import_jsx_runtime87.jsx)(Badge, { tone: "success", dot: true, children: "This device" }) : /* @__PURE__ */ (0, import_jsx_runtime87.jsx)(Button, { size: "sm", variant: "ghost", children: "Revoke" })
10231
10333
  ] }, s.id)) })
10232
10334
  }
10233
10335
  ) : null,
10234
- /* @__PURE__ */ (0, import_jsx_runtime85.jsxs)("div", { className: "fd-row", style: {
10336
+ /* @__PURE__ */ (0, import_jsx_runtime87.jsxs)("div", { className: "fd-row", style: {
10235
10337
  gap: 10,
10236
10338
  flexWrap: "wrap",
10237
10339
  position: "sticky",
@@ -10242,16 +10344,16 @@ function ProfilePage({
10242
10344
  border: "1px solid var(--border)",
10243
10345
  boxShadow: "0 -4px 16px rgba(11,13,17,.06)"
10244
10346
  }, children: [
10245
- /* @__PURE__ */ (0, import_jsx_runtime85.jsx)("span", { className: "fd-body-sm", style: { fontWeight: 600, flex: 1 }, children: saved ? "Saved." : dirty ? "Unsaved changes" : "No pending changes" }),
10246
- /* @__PURE__ */ (0, import_jsx_runtime85.jsx)(Button, { size: "sm", variant: "ghost", disabled: !dirty || saving, onClick: discard, children: "Discard" }),
10247
- /* @__PURE__ */ (0, import_jsx_runtime85.jsx)(Button, { size: "sm", icon: "check", disabled: !dirty || !canSave, loading: saving, onClick: save, children: "Save changes" })
10347
+ /* @__PURE__ */ (0, import_jsx_runtime87.jsx)("span", { className: "fd-body-sm", style: { fontWeight: 600, flex: 1 }, children: saved ? "Saved." : dirty ? "Unsaved changes" : "No pending changes" }),
10348
+ /* @__PURE__ */ (0, import_jsx_runtime87.jsx)(Button, { size: "sm", variant: "ghost", disabled: !dirty || saving, onClick: discard, children: "Discard" }),
10349
+ /* @__PURE__ */ (0, import_jsx_runtime87.jsx)(Button, { size: "sm", icon: "check", disabled: !dirty || !canSave, loading: saving, onClick: save, children: "Save changes" })
10248
10350
  ] })
10249
10351
  ] });
10250
10352
  }
10251
10353
 
10252
10354
  // src/components/platform/SessionScreen.tsx
10253
- var React61 = __toESM(require("react"), 1);
10254
- var import_jsx_runtime86 = require("react/jsx-runtime");
10355
+ var React62 = __toESM(require("react"), 1);
10356
+ var import_jsx_runtime88 = require("react/jsx-runtime");
10255
10357
  var COPY = {
10256
10358
  "signing-in": { busy: "Signing you in\u2026" },
10257
10359
  "session-expired": { busy: "Your session expired \u2014 signing you back in\u2026" },
@@ -10264,28 +10366,28 @@ function SessionScreen({ kind, error, onRetry, productName }) {
10264
10366
  const copy = COPY[kind];
10265
10367
  const busyMessage = "busy" in copy ? copy.busy : null;
10266
10368
  const failureTitle = "failure" in copy ? copy.failure : null;
10267
- const [announced, setAnnounced] = React61.useState("");
10268
- React61.useEffect(() => {
10369
+ const [announced, setAnnounced] = React62.useState("");
10370
+ React62.useEffect(() => {
10269
10371
  setAnnounced(busyMessage ?? "");
10270
10372
  }, [busyMessage]);
10271
- const titleRef = React61.useRef(null);
10373
+ const titleRef = React62.useRef(null);
10272
10374
  const failed = failureTitle !== null;
10273
- React61.useEffect(() => {
10375
+ React62.useEffect(() => {
10274
10376
  titleRef.current?.focus({ preventScroll: true });
10275
10377
  }, [failed]);
10276
- return /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("main", { className: "fd-session-screen", children: /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("div", { className: "fd-session-screen-inner", children: [
10277
- /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("div", { className: "fd-session-screen-mark", "data-theme": "dark", children: /* @__PURE__ */ (0, import_jsx_runtime86.jsx)(FlytedeskMark, { size: "lg" }) }),
10278
- /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("div", { className: "fd-session-screen-frame", children: [
10279
- /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("div", { className: "fd-session-screen-stripe" }),
10280
- /* @__PURE__ */ (0, import_jsx_runtime86.jsx)(Card, { children: /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("div", { className: "fd-session-screen-body", children: [
10281
- /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("h1", { ref: titleRef, tabIndex: -1, className: "fd-h3 fd-session-screen-title", children: productName }),
10282
- /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("div", { role: "status", "aria-live": "polite", className: "fd-session-screen-status", children: busyMessage !== null ? /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)(import_jsx_runtime86.Fragment, { children: [
10283
- /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("span", { className: "fd-spinner fd-spinner-lg fd-session-screen-spinner", "aria-hidden": "true" }),
10284
- /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("p", { className: "fd-body fd-session-screen-message", children: announced })
10378
+ return /* @__PURE__ */ (0, import_jsx_runtime88.jsx)("main", { className: "fd-session-screen", children: /* @__PURE__ */ (0, import_jsx_runtime88.jsxs)("div", { className: "fd-session-screen-inner", children: [
10379
+ /* @__PURE__ */ (0, import_jsx_runtime88.jsx)("div", { className: "fd-session-screen-mark", "data-theme": "dark", children: /* @__PURE__ */ (0, import_jsx_runtime88.jsx)(FlytedeskMark, { size: "lg" }) }),
10380
+ /* @__PURE__ */ (0, import_jsx_runtime88.jsxs)("div", { className: "fd-session-screen-frame", children: [
10381
+ /* @__PURE__ */ (0, import_jsx_runtime88.jsx)("div", { className: "fd-session-screen-stripe" }),
10382
+ /* @__PURE__ */ (0, import_jsx_runtime88.jsx)(Card, { children: /* @__PURE__ */ (0, import_jsx_runtime88.jsxs)("div", { className: "fd-session-screen-body", children: [
10383
+ /* @__PURE__ */ (0, import_jsx_runtime88.jsx)("h1", { ref: titleRef, tabIndex: -1, className: "fd-h3 fd-session-screen-title", children: productName }),
10384
+ /* @__PURE__ */ (0, import_jsx_runtime88.jsx)("div", { role: "status", "aria-live": "polite", className: "fd-session-screen-status", children: busyMessage !== null ? /* @__PURE__ */ (0, import_jsx_runtime88.jsxs)(import_jsx_runtime88.Fragment, { children: [
10385
+ /* @__PURE__ */ (0, import_jsx_runtime88.jsx)("span", { className: "fd-spinner fd-spinner-lg fd-session-screen-spinner", "aria-hidden": "true" }),
10386
+ /* @__PURE__ */ (0, import_jsx_runtime88.jsx)("p", { className: "fd-body fd-session-screen-message", children: announced })
10285
10387
  ] }) : null }),
10286
- failureTitle !== null ? /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("div", { className: "fd-session-screen-failure", children: [
10287
- /* @__PURE__ */ (0, import_jsx_runtime86.jsx)(Banner, { tone: "danger", title: failureTitle, detail: error ?? void 0 }),
10288
- onRetry !== null ? /* @__PURE__ */ (0, import_jsx_runtime86.jsx)(Button, { variant: "primary", block: true, onClick: onRetry, children: "Try again" }) : null
10388
+ failureTitle !== null ? /* @__PURE__ */ (0, import_jsx_runtime88.jsxs)("div", { className: "fd-session-screen-failure", children: [
10389
+ /* @__PURE__ */ (0, import_jsx_runtime88.jsx)(Banner, { tone: "danger", title: failureTitle, detail: error ?? void 0 }),
10390
+ onRetry !== null ? /* @__PURE__ */ (0, import_jsx_runtime88.jsx)(Button, { variant: "primary", block: true, onClick: onRetry, children: "Try again" }) : null
10289
10391
  ] }) : null
10290
10392
  ] }) })
10291
10393
  ] })
@@ -10293,10 +10395,10 @@ function SessionScreen({ kind, error, onRetry, productName }) {
10293
10395
  }
10294
10396
 
10295
10397
  // src/components/platform/RoadmapTimeline.tsx
10296
- var React64 = __toESM(require("react"), 1);
10398
+ var React65 = __toESM(require("react"), 1);
10297
10399
 
10298
10400
  // src/kits/session.ts
10299
- var React62 = __toESM(require("react"), 1);
10401
+ var React63 = __toESM(require("react"), 1);
10300
10402
  var PERMISSION_CATALOG = [
10301
10403
  { group: "Plans", items: [
10302
10404
  { key: "plan.view", label: "View plans", detail: "Read any plan in the workspace." },
@@ -11863,8 +11965,8 @@ function roadmap(overrides) {
11863
11965
  };
11864
11966
  }
11865
11967
  function useSession() {
11866
- const [s, setS] = React62.useState(getSession);
11867
- React62.useEffect(() => subscribe(setS), []);
11968
+ const [s, setS] = React63.useState(getSession);
11969
+ React63.useEffect(() => subscribe(setS), []);
11868
11970
  return s;
11869
11971
  }
11870
11972
  var SessionKit = {
@@ -11897,7 +11999,7 @@ var SessionKit = {
11897
11999
  };
11898
12000
  function DemoSessionProvider({ children }) {
11899
12001
  const session = useSession();
11900
- const value = React62.useMemo(
12002
+ const value = React63.useMemo(
11901
12003
  () => ({
11902
12004
  user: session.user,
11903
12005
  roles: session.roles,
@@ -11913,11 +12015,11 @@ function DemoSessionProvider({ children }) {
11913
12015
  }),
11914
12016
  [session]
11915
12017
  );
11916
- return React62.createElement(SessionProvider, { value }, children);
12018
+ return React63.createElement(SessionProvider, { value }, children);
11917
12019
  }
11918
12020
 
11919
12021
  // src/kits/runtime.ts
11920
- var React63 = __toESM(require("react"), 1);
12022
+ var React64 = __toESM(require("react"), 1);
11921
12023
  var WIRED_ENDPOINTS = [
11922
12024
  // Nothing yet. Every id below would come from a real service:
11923
12025
  // "plan.get", "placements.list", …
@@ -12088,8 +12190,8 @@ var RuntimeKit = {
12088
12190
  };
12089
12191
  RuntimeKit.declare(FEATURE_NEEDS);
12090
12192
  function useRuntimeMode() {
12091
- const [m, setM] = React63.useState(RuntimeKit.getMode());
12092
- React63.useEffect(() => RuntimeKit.subscribe(setM), []);
12193
+ const [m, setM] = React64.useState(RuntimeKit.getMode());
12194
+ React64.useEffect(() => RuntimeKit.subscribe(setM), []);
12093
12195
  return m;
12094
12196
  }
12095
12197
  function useFeatureStatus(key) {
@@ -12108,7 +12210,7 @@ var UseRuntimeMode = useRuntimeMode;
12108
12210
  var UseFeatureStatus = useFeatureStatus;
12109
12211
 
12110
12212
  // src/components/platform/RoadmapTimeline.tsx
12111
- var import_jsx_runtime87 = require("react/jsx-runtime");
12213
+ var import_jsx_runtime89 = require("react/jsx-runtime");
12112
12214
  var STATUS = {
12113
12215
  shipped: { tone: "success", icon: "check-circle", label: "Wired" },
12114
12216
  next: { tone: "warning", icon: "traffic-cone", label: "Not wired" },
@@ -12123,45 +12225,45 @@ function RoadmapCard({ item, byKey, onOpenFlag }) {
12123
12225
  const s = STATUS[item.status] || STATUS.planned;
12124
12226
  const deps = (item.dependsOn || []).map((k) => byKey[k]).filter(Boolean);
12125
12227
  const blocking = deps.filter((d) => !d.implemented);
12126
- return /* @__PURE__ */ (0, import_jsx_runtime87.jsx)(Card, { elevation: "flat", children: /* @__PURE__ */ (0, import_jsx_runtime87.jsxs)("div", { className: "fd-stack", style: { gap: 10 }, children: [
12127
- /* @__PURE__ */ (0, import_jsx_runtime87.jsxs)("div", { className: "fd-row", style: { gap: 8, flexWrap: "wrap" }, children: [
12128
- /* @__PURE__ */ (0, import_jsx_runtime87.jsx)("span", { className: "fd-body", style: { fontWeight: 700, flex: 1, minWidth: 140 }, children: item.label }),
12129
- /* @__PURE__ */ (0, import_jsx_runtime87.jsx)(Badge, { tone: "neutral", icon: PROJECT_ICON[item.project] || "squares-four", children: item.project }),
12130
- /* @__PURE__ */ (0, import_jsx_runtime87.jsx)(Badge, { tone: s.tone, icon: s.icon, children: s.label })
12228
+ return /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(Card, { elevation: "flat", children: /* @__PURE__ */ (0, import_jsx_runtime89.jsxs)("div", { className: "fd-stack", style: { gap: 10 }, children: [
12229
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsxs)("div", { className: "fd-row", style: { gap: 8, flexWrap: "wrap" }, children: [
12230
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsx)("span", { className: "fd-body", style: { fontWeight: 700, flex: 1, minWidth: 140 }, children: item.label }),
12231
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(Badge, { tone: "neutral", icon: PROJECT_ICON[item.project] || "squares-four", children: item.project }),
12232
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(Badge, { tone: s.tone, icon: s.icon, children: s.label })
12131
12233
  ] }),
12132
- /* @__PURE__ */ (0, import_jsx_runtime87.jsx)("p", { className: "fd-body-sm fd-secondary", style: { margin: 0, textWrap: "pretty" }, children: item.description }),
12133
- item.backend ? /* @__PURE__ */ (0, import_jsx_runtime87.jsxs)("div", { className: "fd-row", style: { gap: 10, alignItems: "flex-start" }, children: [
12134
- /* @__PURE__ */ (0, import_jsx_runtime87.jsx)("span", { className: "fd-overline fd-muted", style: { width: 62, flex: "none", paddingTop: 2 }, children: "Backend" }),
12135
- /* @__PURE__ */ (0, import_jsx_runtime87.jsx)("span", { className: "fd-body-sm", style: { flex: 1, textWrap: "pretty" }, children: item.backend })
12234
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsx)("p", { className: "fd-body-sm fd-secondary", style: { margin: 0, textWrap: "pretty" }, children: item.description }),
12235
+ item.backend ? /* @__PURE__ */ (0, import_jsx_runtime89.jsxs)("div", { className: "fd-row", style: { gap: 10, alignItems: "flex-start" }, children: [
12236
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsx)("span", { className: "fd-overline fd-muted", style: { width: 62, flex: "none", paddingTop: 2 }, children: "Backend" }),
12237
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsx)("span", { className: "fd-body-sm", style: { flex: 1, textWrap: "pretty" }, children: item.backend })
12136
12238
  ] }) : null,
12137
- /* @__PURE__ */ (0, import_jsx_runtime87.jsxs)("div", { className: "fd-row", style: { gap: 12, flexWrap: "wrap" }, children: [
12138
- item.effort ? /* @__PURE__ */ (0, import_jsx_runtime87.jsxs)("span", { className: "fd-body-sm fd-muted", children: [
12139
- /* @__PURE__ */ (0, import_jsx_runtime87.jsx)("i", { className: "ph ph-hourglass-medium" }),
12239
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsxs)("div", { className: "fd-row", style: { gap: 12, flexWrap: "wrap" }, children: [
12240
+ item.effort ? /* @__PURE__ */ (0, import_jsx_runtime89.jsxs)("span", { className: "fd-body-sm fd-muted", children: [
12241
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsx)("i", { className: "ph ph-hourglass-medium" }),
12140
12242
  " ",
12141
12243
  item.effort
12142
12244
  ] }) : null,
12143
- /* @__PURE__ */ (0, import_jsx_runtime87.jsxs)("span", { className: "fd-body-sm fd-muted", children: [
12144
- /* @__PURE__ */ (0, import_jsx_runtime87.jsx)("i", { className: "ph ph-user" }),
12245
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsxs)("span", { className: "fd-body-sm fd-muted", children: [
12246
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsx)("i", { className: "ph ph-user" }),
12145
12247
  " ",
12146
12248
  item.owner
12147
12249
  ] }),
12148
- item.screen ? /* @__PURE__ */ (0, import_jsx_runtime87.jsx)(Badge, { tone: "neutral", icon: "browser", children: "screen" }) : null,
12149
- /* @__PURE__ */ (0, import_jsx_runtime87.jsx)("span", { style: { flex: 1 } }),
12150
- /* @__PURE__ */ (0, import_jsx_runtime87.jsx)(
12250
+ item.screen ? /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(Badge, { tone: "neutral", icon: "browser", children: "screen" }) : null,
12251
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsx)("span", { style: { flex: 1 } }),
12252
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(
12151
12253
  "button",
12152
12254
  {
12153
12255
  type: "button",
12154
12256
  onClick: () => onOpenFlag && onOpenFlag(item.key),
12155
12257
  style: { all: "unset", cursor: "pointer", display: "inline-flex", alignItems: "center", gap: 5 },
12156
- children: /* @__PURE__ */ (0, import_jsx_runtime87.jsx)("code", { className: "fd-mono", style: { fontSize: 11, color: "var(--brand)" }, children: item.key })
12258
+ children: /* @__PURE__ */ (0, import_jsx_runtime89.jsx)("code", { className: "fd-mono", style: { fontSize: 11, color: "var(--brand)" }, children: item.key })
12157
12259
  }
12158
12260
  )
12159
12261
  ] }),
12160
- deps.length ? /* @__PURE__ */ (0, import_jsx_runtime87.jsxs)("div", { className: "fd-row", style: { gap: 6, flexWrap: "wrap", paddingTop: 6, borderTop: "1px solid var(--border)" }, children: [
12161
- /* @__PURE__ */ (0, import_jsx_runtime87.jsx)("span", { className: "fd-overline fd-muted", style: { paddingTop: 3 }, children: "After" }),
12162
- deps.map((d) => /* @__PURE__ */ (0, import_jsx_runtime87.jsx)(Tag, { icon: d.implemented ? "check" : "clock", children: d.label }, d.key))
12262
+ deps.length ? /* @__PURE__ */ (0, import_jsx_runtime89.jsxs)("div", { className: "fd-row", style: { gap: 6, flexWrap: "wrap", paddingTop: 6, borderTop: "1px solid var(--border)" }, children: [
12263
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsx)("span", { className: "fd-overline fd-muted", style: { paddingTop: 3 }, children: "After" }),
12264
+ deps.map((d) => /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(Tag, { icon: d.implemented ? "check" : "clock", children: d.label }, d.key))
12163
12265
  ] }) : null,
12164
- blocking.length && !item.implemented ? /* @__PURE__ */ (0, import_jsx_runtime87.jsxs)("span", { className: "fd-body-sm", style: { color: "var(--warn-text)" }, children: [
12266
+ blocking.length && !item.implemented ? /* @__PURE__ */ (0, import_jsx_runtime89.jsxs)("span", { className: "fd-body-sm", style: { color: "var(--warn-text)" }, children: [
12165
12267
  "Blocked until ",
12166
12268
  blocking.map((d) => d.label).join(" and "),
12167
12269
  " ",
@@ -12172,12 +12274,12 @@ function RoadmapCard({ item, byKey, onOpenFlag }) {
12172
12274
  }
12173
12275
  function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
12174
12276
  const session = SessionKit.useSession();
12175
- const [project, setProject] = React64.useState("");
12176
- const [q, setQ] = React64.useState("");
12177
- const scrollRef = React64.useRef(null);
12178
- const nowRef = React64.useRef(null);
12179
- const rm = React64.useMemo(() => SessionKit.roadmap({ isComplete: RuntimeKit.isComplete }), [session]);
12180
- const byKey = React64.useMemo(() => {
12277
+ const [project, setProject] = React65.useState("");
12278
+ const [q, setQ] = React65.useState("");
12279
+ const scrollRef = React65.useRef(null);
12280
+ const nowRef = React65.useRef(null);
12281
+ const rm = React65.useMemo(() => SessionKit.roadmap({ isComplete: RuntimeKit.isComplete }), [session]);
12282
+ const byKey = React65.useMemo(() => {
12181
12283
  const m = {};
12182
12284
  rm.items.forEach((i) => {
12183
12285
  m[i.key] = i;
@@ -12186,7 +12288,7 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
12186
12288
  }, [rm]);
12187
12289
  const items = rm.items.filter((i) => (!project || i.project === project) && (!q || (i.label + " " + i.description + " " + (i.backend || "") + " " + i.key).toLowerCase().includes(q.toLowerCase())));
12188
12290
  const projects = [...new Set(rm.items.map((i) => i.project))];
12189
- React64.useEffect(() => {
12291
+ React65.useEffect(() => {
12190
12292
  let raf1 = 0, raf2 = 0;
12191
12293
  const place = () => {
12192
12294
  const box = scrollRef.current, mark = nowRef.current;
@@ -12214,23 +12316,23 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
12214
12316
  }, 0);
12215
12317
  const nextPhase = items.find((i) => !i.implemented);
12216
12318
  let lastPhase = null;
12217
- return /* @__PURE__ */ (0, import_jsx_runtime87.jsxs)("div", { className: "fd-stack", style: { gap: 16, maxWidth: 1e3 }, children: [
12218
- /* @__PURE__ */ (0, import_jsx_runtime87.jsxs)("div", { className: "fd-stack", style: { gap: 10 }, children: [
12219
- /* @__PURE__ */ (0, import_jsx_runtime87.jsx)("span", { className: "fd-overline fd-muted", children: "Architecture" }),
12220
- /* @__PURE__ */ (0, import_jsx_runtime87.jsx)("h1", { className: "fd-h1", style: { margin: 0 }, children: title }),
12221
- /* @__PURE__ */ (0, import_jsx_runtime87.jsx)("p", { className: "fd-body fd-secondary fd-prose", style: { margin: 0 }, children: lede || "Every screen and feature in these tools is already designed and working against a simulated backend. This is the plan for connecting them to the real one \u2014 so the only work described here is server work." })
12319
+ return /* @__PURE__ */ (0, import_jsx_runtime89.jsxs)("div", { className: "fd-stack", style: { gap: 16, maxWidth: 1e3 }, children: [
12320
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsxs)("div", { className: "fd-stack", style: { gap: 10 }, children: [
12321
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsx)("span", { className: "fd-overline fd-muted", children: "Architecture" }),
12322
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsx)("h1", { className: "fd-h1", style: { margin: 0 }, children: title }),
12323
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsx)("p", { className: "fd-body fd-secondary fd-prose", style: { margin: 0 }, children: lede || "Every screen and feature in these tools is already designed and working against a simulated backend. This is the plan for connecting them to the real one \u2014 so the only work described here is server work." })
12222
12324
  ] }),
12223
- /* @__PURE__ */ (0, import_jsx_runtime87.jsxs)("div", { className: "fd-grid-stats is-thin", children: [
12224
- /* @__PURE__ */ (0, import_jsx_runtime87.jsx)(StatTile, { compact: true, label: "Wired", value: String(rm.shipped), sub: "of " + rm.items.length + " features" }),
12225
- /* @__PURE__ */ (0, import_jsx_runtime87.jsx)(StatTile, { compact: true, label: "Remaining", value: String(rm.remaining), sub: "backend work" }),
12226
- /* @__PURE__ */ (0, import_jsx_runtime87.jsx)(StatTile, { compact: true, label: "Est. effort", value: days ? days + " days" : "\u2014", sub: "sum of estimates, not calendar" }),
12227
- /* @__PURE__ */ (0, import_jsx_runtime87.jsx)(StatTile, { compact: true, label: "Up next", value: nextPhase ? "Phase " + nextPhase.phase : "\u2014", sub: nextPhase ? nextPhase.phaseName : "all wired" })
12325
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsxs)("div", { className: "fd-grid-stats is-thin", children: [
12326
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(StatTile, { compact: true, label: "Wired", value: String(rm.shipped), sub: "of " + rm.items.length + " features" }),
12327
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(StatTile, { compact: true, label: "Remaining", value: String(rm.remaining), sub: "backend work" }),
12328
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(StatTile, { compact: true, label: "Est. effort", value: days ? days + " days" : "\u2014", sub: "sum of estimates, not calendar" }),
12329
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(StatTile, { compact: true, label: "Up next", value: nextPhase ? "Phase " + nextPhase.phase : "\u2014", sub: nextPhase ? nextPhase.phaseName : "all wired" })
12228
12330
  ] }),
12229
- /* @__PURE__ */ (0, import_jsx_runtime87.jsxs)("div", { className: "fd-row", style: { gap: 10, flexWrap: "wrap" }, children: [
12230
- /* @__PURE__ */ (0, import_jsx_runtime87.jsx)(Input, { icon: "magnifying-glass", placeholder: "Find a feature or a piece of backend work", value: q, onChange: (e) => setQ(e.target.value), style: { width: 300 } }),
12231
- /* @__PURE__ */ (0, import_jsx_runtime87.jsx)(Select, { placeholder: "All projects", value: project, onChange: (e) => setProject(e.target.value), options: projects, style: { width: 190 } }),
12232
- /* @__PURE__ */ (0, import_jsx_runtime87.jsx)("span", { style: { flex: 1 } }),
12233
- /* @__PURE__ */ (0, import_jsx_runtime87.jsx)(
12331
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsxs)("div", { className: "fd-row", style: { gap: 10, flexWrap: "wrap" }, children: [
12332
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(Input, { icon: "magnifying-glass", placeholder: "Find a feature or a piece of backend work", value: q, onChange: (e) => setQ(e.target.value), style: { width: 300 } }),
12333
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(Select, { placeholder: "All projects", value: project, onChange: (e) => setProject(e.target.value), options: projects, style: { width: 190 } }),
12334
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsx)("span", { style: { flex: 1 } }),
12335
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(
12234
12336
  Button,
12235
12337
  {
12236
12338
  size: "sm",
@@ -12244,7 +12346,7 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
12244
12346
  }
12245
12347
  )
12246
12348
  ] }),
12247
- /* @__PURE__ */ (0, import_jsx_runtime87.jsx)(
12349
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(
12248
12350
  Flag,
12249
12351
  {
12250
12352
  tone: "info",
@@ -12253,60 +12355,60 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
12253
12355
  actions: null
12254
12356
  }
12255
12357
  ),
12256
- /* @__PURE__ */ (0, import_jsx_runtime87.jsx)("div", { className: "fd-rm", children: /* @__PURE__ */ (0, import_jsx_runtime87.jsx)("div", { className: "fd-rm-scroll", ref: scrollRef, children: /* @__PURE__ */ (0, import_jsx_runtime87.jsxs)("div", { className: "fd-rm-track", children: [
12257
- /* @__PURE__ */ (0, import_jsx_runtime87.jsx)("span", { className: "fd-rm-spine", children: /* @__PURE__ */ (0, import_jsx_runtime87.jsx)("span", { className: "fd-rm-spine-done", style: { height: items.length ? 100 * shippedShown / items.length + "%" : "0%" } }) }),
12358
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsx)("div", { className: "fd-rm", children: /* @__PURE__ */ (0, import_jsx_runtime89.jsx)("div", { className: "fd-rm-scroll", ref: scrollRef, children: /* @__PURE__ */ (0, import_jsx_runtime89.jsxs)("div", { className: "fd-rm-track", children: [
12359
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsx)("span", { className: "fd-rm-spine", children: /* @__PURE__ */ (0, import_jsx_runtime89.jsx)("span", { className: "fd-rm-spine-done", style: { height: items.length ? 100 * shippedShown / items.length + "%" : "0%" } }) }),
12258
12360
  items.map((item, n) => {
12259
12361
  const showPhase = item.phase !== lastPhase;
12260
12362
  lastPhase = item.phase;
12261
12363
  const inPhase = items.filter((i) => i.phase === item.phase).length;
12262
12364
  const isBoundary = n === firstPending;
12263
- return /* @__PURE__ */ (0, import_jsx_runtime87.jsxs)(React64.Fragment, { children: [
12264
- showPhase ? /* @__PURE__ */ (0, import_jsx_runtime87.jsxs)("div", { className: "fd-rm-era", children: [
12265
- /* @__PURE__ */ (0, import_jsx_runtime87.jsxs)("span", { className: "fd-row", style: { gap: 8, flexWrap: "wrap", alignItems: "baseline" }, children: [
12266
- /* @__PURE__ */ (0, import_jsx_runtime87.jsx)("span", { style: { fontWeight: 700 }, children: item.phase === 0 ? "Shipped" : "Phase " + item.phase + " \u2014 " + item.phaseName }),
12267
- item.phase === 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime87.jsxs)("span", { className: "fd-mono", style: { opacity: 0.7, fontWeight: 400 }, children: [
12365
+ return /* @__PURE__ */ (0, import_jsx_runtime89.jsxs)(React65.Fragment, { children: [
12366
+ showPhase ? /* @__PURE__ */ (0, import_jsx_runtime89.jsxs)("div", { className: "fd-rm-era", children: [
12367
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsxs)("span", { className: "fd-row", style: { gap: 8, flexWrap: "wrap", alignItems: "baseline" }, children: [
12368
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsx)("span", { style: { fontWeight: 700 }, children: item.phase === 0 ? "Shipped" : "Phase " + item.phase + " \u2014 " + item.phaseName }),
12369
+ item.phase === 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime89.jsxs)("span", { className: "fd-mono", style: { opacity: 0.7, fontWeight: 400 }, children: [
12268
12370
  fmtDate(item.phaseStart),
12269
12371
  " \u2013 ",
12270
12372
  fmtDate(item.date)
12271
12373
  ] }),
12272
- /* @__PURE__ */ (0, import_jsx_runtime87.jsxs)("span", { style: { opacity: 0.7, fontWeight: 400 }, children: [
12374
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsxs)("span", { style: { opacity: 0.7, fontWeight: 400 }, children: [
12273
12375
  "\xB7 ",
12274
12376
  inPhase,
12275
12377
  " feature",
12276
12378
  inPhase === 1 ? "" : "s"
12277
12379
  ] })
12278
12380
  ] }),
12279
- item.phaseWhy ? /* @__PURE__ */ (0, import_jsx_runtime87.jsx)("p", { className: "fd-rm-era-why", children: item.phaseWhy }) : null
12381
+ item.phaseWhy ? /* @__PURE__ */ (0, import_jsx_runtime89.jsx)("p", { className: "fd-rm-era-why", children: item.phaseWhy }) : null
12280
12382
  ] }) : null,
12281
- isBoundary ? /* @__PURE__ */ (0, import_jsx_runtime87.jsx)("div", { className: "fd-rm-now", ref: nowRef, children: /* @__PURE__ */ (0, import_jsx_runtime87.jsxs)("span", { className: "fd-rm-now-pill", children: [
12282
- /* @__PURE__ */ (0, import_jsx_runtime87.jsx)("i", { className: "ph ph-map-pin" }),
12383
+ isBoundary ? /* @__PURE__ */ (0, import_jsx_runtime89.jsx)("div", { className: "fd-rm-now", ref: nowRef, children: /* @__PURE__ */ (0, import_jsx_runtime89.jsxs)("span", { className: "fd-rm-now-pill", children: [
12384
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsx)("i", { className: "ph ph-map-pin" }),
12283
12385
  " You are here \u2014 everything above is wired"
12284
12386
  ] }) }) : null,
12285
- /* @__PURE__ */ (0, import_jsx_runtime87.jsxs)("div", { className: "fd-rm-row", children: [
12286
- /* @__PURE__ */ (0, import_jsx_runtime87.jsx)("span", { className: "fd-rm-dot " + (item.implemented ? "is-shipped" : item.status === "next" ? "is-next" : "") }),
12287
- /* @__PURE__ */ (0, import_jsx_runtime87.jsxs)("div", { className: "fd-rm-date", children: [
12387
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsxs)("div", { className: "fd-rm-row", children: [
12388
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsx)("span", { className: "fd-rm-dot " + (item.implemented ? "is-shipped" : item.status === "next" ? "is-next" : "") }),
12389
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsxs)("div", { className: "fd-rm-date", children: [
12288
12390
  fmtDate(item.date),
12289
- /* @__PURE__ */ (0, import_jsx_runtime87.jsx)("br", {}),
12290
- /* @__PURE__ */ (0, import_jsx_runtime87.jsx)("span", { style: { opacity: 0.75 }, children: item.implemented ? "shipped" : "phase " + item.phase })
12391
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsx)("br", {}),
12392
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsx)("span", { style: { opacity: 0.75 }, children: item.implemented ? "shipped" : "phase " + item.phase })
12291
12393
  ] }),
12292
- /* @__PURE__ */ (0, import_jsx_runtime87.jsx)(RoadmapCard, { item, byKey, onOpenFlag })
12394
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(RoadmapCard, { item, byKey, onOpenFlag })
12293
12395
  ] })
12294
12396
  ] }, item.key);
12295
12397
  }),
12296
- !items.length ? /* @__PURE__ */ (0, import_jsx_runtime87.jsx)("p", { className: "fd-body-sm fd-muted", children: "Nothing matches that filter." }) : null
12398
+ !items.length ? /* @__PURE__ */ (0, import_jsx_runtime89.jsx)("p", { className: "fd-body-sm fd-muted", children: "Nothing matches that filter." }) : null
12297
12399
  ] }) }) }),
12298
- /* @__PURE__ */ (0, import_jsx_runtime87.jsxs)("p", { className: "fd-body-sm fd-muted", style: { margin: 0 }, children: [
12400
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsxs)("p", { className: "fd-body-sm fd-muted", style: { margin: 0 }, children: [
12299
12401
  "Derived from the feature-flag registry \u2014 each entry's status is its flag's ",
12300
- /* @__PURE__ */ (0, import_jsx_runtime87.jsx)("code", { className: "fd-mono", children: "implemented" }),
12402
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsx)("code", { className: "fd-mono", children: "implemented" }),
12301
12403
  " field, so this page cannot drift from what the apps actually do."
12302
12404
  ] })
12303
12405
  ] });
12304
12406
  }
12305
12407
 
12306
12408
  // src/components/platform/ComingSoon.tsx
12307
- var React65 = __toESM(require("react"), 1);
12409
+ var React66 = __toESM(require("react"), 1);
12308
12410
  var import_react_dom7 = require("react-dom");
12309
- var import_jsx_runtime88 = require("react/jsx-runtime");
12411
+ var import_jsx_runtime90 = require("react/jsx-runtime");
12310
12412
  var BYPASS_STORE = "fd.soon.bypass.v1";
12311
12413
  function readBypassed() {
12312
12414
  try {
@@ -12322,8 +12424,8 @@ function writeBypassed(list) {
12322
12424
  }
12323
12425
  }
12324
12426
  function useBypass(key) {
12325
- const [on, setOn] = React65.useState(() => !!key && readBypassed().indexOf(key) >= 0);
12326
- React65.useEffect(() => {
12427
+ const [on, setOn] = React66.useState(() => !!key && readBypassed().indexOf(key) >= 0);
12428
+ React66.useEffect(() => {
12327
12429
  setOn(!!key && readBypassed().indexOf(key) >= 0);
12328
12430
  }, [key]);
12329
12431
  const set = (next) => {
@@ -12336,43 +12438,43 @@ function useBypass(key) {
12336
12438
  return [on, set];
12337
12439
  }
12338
12440
  function SoonCard({ label, detail, backend, eta, effort, onRoadmap, allowed, onBypass }) {
12339
- return /* @__PURE__ */ (0, import_jsx_runtime88.jsxs)(import_jsx_runtime88.Fragment, { children: [
12340
- /* @__PURE__ */ (0, import_jsx_runtime88.jsxs)("span", { className: "fd-soon-badge", children: [
12341
- /* @__PURE__ */ (0, import_jsx_runtime88.jsx)("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" }),
12441
+ return /* @__PURE__ */ (0, import_jsx_runtime90.jsxs)(import_jsx_runtime90.Fragment, { children: [
12442
+ /* @__PURE__ */ (0, import_jsx_runtime90.jsxs)("span", { className: "fd-soon-badge", children: [
12443
+ /* @__PURE__ */ (0, import_jsx_runtime90.jsx)("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" }),
12342
12444
  label
12343
12445
  ] }),
12344
- detail ? /* @__PURE__ */ (0, import_jsx_runtime88.jsx)("span", { className: "fd-soon-detail", children: detail }) : null,
12345
- backend ? /* @__PURE__ */ (0, import_jsx_runtime88.jsxs)("span", { className: "fd-soon-backend", children: [
12346
- /* @__PURE__ */ (0, import_jsx_runtime88.jsx)("span", { className: "fd-overline", children: "Needs" }),
12446
+ detail ? /* @__PURE__ */ (0, import_jsx_runtime90.jsx)("span", { className: "fd-soon-detail", children: detail }) : null,
12447
+ backend ? /* @__PURE__ */ (0, import_jsx_runtime90.jsxs)("span", { className: "fd-soon-backend", children: [
12448
+ /* @__PURE__ */ (0, import_jsx_runtime90.jsx)("span", { className: "fd-overline", children: "Needs" }),
12347
12449
  " ",
12348
12450
  backend
12349
12451
  ] }) : null,
12350
- eta || effort || onRoadmap ? /* @__PURE__ */ (0, import_jsx_runtime88.jsxs)("span", { className: "fd-soon-meta", children: [
12351
- eta ? /* @__PURE__ */ (0, import_jsx_runtime88.jsxs)("span", { children: [
12352
- /* @__PURE__ */ (0, import_jsx_runtime88.jsx)("i", { className: "ph ph-calendar-blank", "aria-hidden": "true" }),
12452
+ eta || effort || onRoadmap ? /* @__PURE__ */ (0, import_jsx_runtime90.jsxs)("span", { className: "fd-soon-meta", children: [
12453
+ eta ? /* @__PURE__ */ (0, import_jsx_runtime90.jsxs)("span", { children: [
12454
+ /* @__PURE__ */ (0, import_jsx_runtime90.jsx)("i", { className: "ph ph-calendar-blank", "aria-hidden": "true" }),
12353
12455
  " ",
12354
12456
  eta
12355
12457
  ] }) : null,
12356
- effort ? /* @__PURE__ */ (0, import_jsx_runtime88.jsxs)("span", { children: [
12357
- /* @__PURE__ */ (0, import_jsx_runtime88.jsx)("i", { className: "ph ph-hourglass-medium", "aria-hidden": "true" }),
12458
+ effort ? /* @__PURE__ */ (0, import_jsx_runtime90.jsxs)("span", { children: [
12459
+ /* @__PURE__ */ (0, import_jsx_runtime90.jsx)("i", { className: "ph ph-hourglass-medium", "aria-hidden": "true" }),
12358
12460
  " ",
12359
12461
  effort
12360
12462
  ] }) : null,
12361
- onRoadmap ? /* @__PURE__ */ (0, import_jsx_runtime88.jsxs)("button", { type: "button", className: "fd-soon-link", onClick: onRoadmap, children: [
12463
+ onRoadmap ? /* @__PURE__ */ (0, import_jsx_runtime90.jsxs)("button", { type: "button", className: "fd-soon-link", onClick: onRoadmap, children: [
12362
12464
  "See the roadmap ",
12363
- /* @__PURE__ */ (0, import_jsx_runtime88.jsx)("i", { className: "ph ph-arrow-right", "aria-hidden": "true" })
12465
+ /* @__PURE__ */ (0, import_jsx_runtime90.jsx)("i", { className: "ph ph-arrow-right", "aria-hidden": "true" })
12364
12466
  ] }) : null
12365
12467
  ] }) : null,
12366
- allowed ? /* @__PURE__ */ (0, import_jsx_runtime88.jsxs)("button", { type: "button", className: "fd-soon-view", onClick: onBypass, children: [
12367
- /* @__PURE__ */ (0, import_jsx_runtime88.jsx)("i", { className: "ph ph-eye", "aria-hidden": "true" }),
12468
+ allowed ? /* @__PURE__ */ (0, import_jsx_runtime90.jsxs)("button", { type: "button", className: "fd-soon-view", onClick: onBypass, children: [
12469
+ /* @__PURE__ */ (0, import_jsx_runtime90.jsx)("i", { className: "ph ph-eye", "aria-hidden": "true" }),
12368
12470
  " View and use it anyway"
12369
12471
  ] }) : null
12370
12472
  ] });
12371
12473
  }
12372
12474
  function useHoverCard(open2) {
12373
- const anchor = React65.useRef(null);
12374
- const [pos, setPos] = React65.useState(null);
12375
- React65.useLayoutEffect(() => {
12475
+ const anchor = React66.useRef(null);
12476
+ const [pos, setPos] = React66.useState(null);
12477
+ React66.useLayoutEffect(() => {
12376
12478
  if (!open2 || !anchor.current) {
12377
12479
  setPos(null);
12378
12480
  return;
@@ -12424,9 +12526,9 @@ function ComingSoon({
12424
12526
  const tip = [label, detail, backend ? "Needs " + backend : null, eta ? "ETA " + eta : null, effort].filter(Boolean).join(" \xB7 ");
12425
12527
  if (inline) {
12426
12528
  if (allowed && bypassed) {
12427
- return /* @__PURE__ */ (0, import_jsx_runtime88.jsxs)("span", { className: ["fd-soon-inline-on", className].filter(Boolean).join(" "), ...rest, children: [
12529
+ return /* @__PURE__ */ (0, import_jsx_runtime90.jsxs)("span", { className: ["fd-soon-inline-on", className].filter(Boolean).join(" "), ...rest, children: [
12428
12530
  children,
12429
- /* @__PURE__ */ (0, import_jsx_runtime88.jsx)(
12531
+ /* @__PURE__ */ (0, import_jsx_runtime90.jsx)(
12430
12532
  "button",
12431
12533
  {
12432
12534
  type: "button",
@@ -12434,12 +12536,12 @@ function ComingSoon({
12434
12536
  title: "Unwired \u2014 writes go to the simulated backend. " + tip + " Click to re-blur.",
12435
12537
  onClick: () => setBypassed(false),
12436
12538
  "aria-label": "Re-blur this unwired feature",
12437
- children: /* @__PURE__ */ (0, import_jsx_runtime88.jsx)("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" })
12539
+ children: /* @__PURE__ */ (0, import_jsx_runtime90.jsx)("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" })
12438
12540
  }
12439
12541
  )
12440
12542
  ] });
12441
12543
  }
12442
- return /* @__PURE__ */ (0, import_jsx_runtime88.jsx)(
12544
+ return /* @__PURE__ */ (0, import_jsx_runtime90.jsx)(
12443
12545
  InlineSoon,
12444
12546
  {
12445
12547
  label,
@@ -12459,20 +12561,20 @@ function ComingSoon({
12459
12561
  );
12460
12562
  }
12461
12563
  if (allowed && bypassed) {
12462
- return /* @__PURE__ */ (0, import_jsx_runtime88.jsxs)("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 14 }, ...rest, children: [
12463
- /* @__PURE__ */ (0, import_jsx_runtime88.jsxs)("div", { className: "fd-soon-bar", role: "status", children: [
12464
- /* @__PURE__ */ (0, import_jsx_runtime88.jsxs)("span", { className: "fd-soon-badge", children: [
12465
- /* @__PURE__ */ (0, import_jsx_runtime88.jsx)("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" }),
12564
+ return /* @__PURE__ */ (0, import_jsx_runtime90.jsxs)("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 14 }, ...rest, children: [
12565
+ /* @__PURE__ */ (0, import_jsx_runtime90.jsxs)("div", { className: "fd-soon-bar", role: "status", children: [
12566
+ /* @__PURE__ */ (0, import_jsx_runtime90.jsxs)("span", { className: "fd-soon-badge", children: [
12567
+ /* @__PURE__ */ (0, import_jsx_runtime90.jsx)("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" }),
12466
12568
  "Unwired feature \u2014 you are using it anyway"
12467
12569
  ] }),
12468
- /* @__PURE__ */ (0, import_jsx_runtime88.jsx)("span", { className: "fd-soon-bar-detail", children: "Every action here writes to the simulated backend, so nothing you do persists beyond this session." }),
12469
- /* @__PURE__ */ (0, import_jsx_runtime88.jsxs)("span", { className: "fd-soon-bar-actions", children: [
12470
- onRoadmap ? /* @__PURE__ */ (0, import_jsx_runtime88.jsxs)("button", { type: "button", className: "fd-soon-link", onClick: onRoadmap, children: [
12570
+ /* @__PURE__ */ (0, import_jsx_runtime90.jsx)("span", { className: "fd-soon-bar-detail", children: "Every action here writes to the simulated backend, so nothing you do persists beyond this session." }),
12571
+ /* @__PURE__ */ (0, import_jsx_runtime90.jsxs)("span", { className: "fd-soon-bar-actions", children: [
12572
+ onRoadmap ? /* @__PURE__ */ (0, import_jsx_runtime90.jsxs)("button", { type: "button", className: "fd-soon-link", onClick: onRoadmap, children: [
12471
12573
  "Roadmap ",
12472
- /* @__PURE__ */ (0, import_jsx_runtime88.jsx)("i", { className: "ph ph-arrow-right", "aria-hidden": "true" })
12574
+ /* @__PURE__ */ (0, import_jsx_runtime90.jsx)("i", { className: "ph ph-arrow-right", "aria-hidden": "true" })
12473
12575
  ] }) : null,
12474
- /* @__PURE__ */ (0, import_jsx_runtime88.jsxs)("button", { type: "button", className: "fd-soon-link", onClick: () => setBypassed(false), children: [
12475
- /* @__PURE__ */ (0, import_jsx_runtime88.jsx)("i", { className: "ph ph-eye-slash", "aria-hidden": "true" }),
12576
+ /* @__PURE__ */ (0, import_jsx_runtime90.jsxs)("button", { type: "button", className: "fd-soon-link", onClick: () => setBypassed(false), children: [
12577
+ /* @__PURE__ */ (0, import_jsx_runtime90.jsx)("i", { className: "ph ph-eye-slash", "aria-hidden": "true" }),
12476
12578
  " Re-blur"
12477
12579
  ] })
12478
12580
  ] })
@@ -12480,10 +12582,10 @@ function ComingSoon({
12480
12582
  children
12481
12583
  ] });
12482
12584
  }
12483
- return /* @__PURE__ */ (0, import_jsx_runtime88.jsxs)("div", { className: ["fd-soon", className].filter(Boolean).join(" "), style: minHeight ? { minHeight } : void 0, ...rest, children: [
12484
- /* @__PURE__ */ (0, import_jsx_runtime88.jsx)("div", { className: "fd-soon-under", style: { filter: "blur(" + blur + "px) saturate(.62)" }, ...{ inert: "" }, "aria-hidden": "true", children }),
12485
- /* @__PURE__ */ (0, import_jsx_runtime88.jsx)("div", { className: "fd-soon-veil" }),
12486
- /* @__PURE__ */ (0, import_jsx_runtime88.jsx)("div", { className: "fd-soon-note", role: "note", children: /* @__PURE__ */ (0, import_jsx_runtime88.jsx)(
12585
+ return /* @__PURE__ */ (0, import_jsx_runtime90.jsxs)("div", { className: ["fd-soon", className].filter(Boolean).join(" "), style: minHeight ? { minHeight } : void 0, ...rest, children: [
12586
+ /* @__PURE__ */ (0, import_jsx_runtime90.jsx)("div", { className: "fd-soon-under", style: { filter: "blur(" + blur + "px) saturate(.62)" }, ...{ inert: "" }, "aria-hidden": "true", children }),
12587
+ /* @__PURE__ */ (0, import_jsx_runtime90.jsx)("div", { className: "fd-soon-veil" }),
12588
+ /* @__PURE__ */ (0, import_jsx_runtime90.jsx)("div", { className: "fd-soon-note", role: "note", children: /* @__PURE__ */ (0, import_jsx_runtime90.jsx)(
12487
12589
  SoonCard,
12488
12590
  {
12489
12591
  label,
@@ -12499,12 +12601,12 @@ function ComingSoon({
12499
12601
  ] });
12500
12602
  }
12501
12603
  function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, onBypass, blur, tip, className, rest, children }) {
12502
- const [open2, setOpen] = React65.useState(false);
12604
+ const [open2, setOpen] = React66.useState(false);
12503
12605
  const [anchor, pos] = useHoverCard(open2);
12504
- const hoverCardRef = React65.useRef(null);
12606
+ const hoverCardRef = React66.useRef(null);
12505
12607
  const hoverLayer = useStackedLayer({ active: open2, containerRef: hoverCardRef, returnFocus: false });
12506
12608
  const zIndex = useLayerZIndex(hoverLayer);
12507
- const close2 = React65.useRef(null);
12609
+ const close2 = React66.useRef(null);
12508
12610
  const show = () => {
12509
12611
  if (close2.current) {
12510
12612
  clearTimeout(close2.current);
@@ -12520,10 +12622,10 @@ function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, o
12520
12622
  setOpen(false);
12521
12623
  }, 140);
12522
12624
  };
12523
- React65.useEffect(() => () => {
12625
+ React66.useEffect(() => () => {
12524
12626
  if (close2.current) clearTimeout(close2.current);
12525
12627
  }, []);
12526
- return /* @__PURE__ */ (0, import_jsx_runtime88.jsxs)(
12628
+ return /* @__PURE__ */ (0, import_jsx_runtime90.jsxs)(
12527
12629
  "span",
12528
12630
  {
12529
12631
  ref: anchor,
@@ -12534,8 +12636,8 @@ function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, o
12534
12636
  onBlur: hide,
12535
12637
  ...rest,
12536
12638
  children: [
12537
- /* @__PURE__ */ (0, import_jsx_runtime88.jsx)("span", { className: "fd-soon-under", style: { filter: "blur(" + Math.min(blur, 1.1) + "px) saturate(.66)" }, ...{ inert: "" }, "aria-hidden": "true", children }),
12538
- /* @__PURE__ */ (0, import_jsx_runtime88.jsx)(
12639
+ /* @__PURE__ */ (0, import_jsx_runtime90.jsx)("span", { className: "fd-soon-under", style: { filter: "blur(" + Math.min(blur, 1.1) + "px) saturate(.66)" }, ...{ inert: "" }, "aria-hidden": "true", children }),
12640
+ /* @__PURE__ */ (0, import_jsx_runtime90.jsx)(
12539
12641
  "button",
12540
12642
  {
12541
12643
  type: "button",
@@ -12546,11 +12648,11 @@ function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, o
12546
12648
  onFocus: show,
12547
12649
  onBlur: hide,
12548
12650
  onClick: () => open2 ? setOpen(false) : show(),
12549
- children: /* @__PURE__ */ (0, import_jsx_runtime88.jsx)("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" })
12651
+ children: /* @__PURE__ */ (0, import_jsx_runtime90.jsx)("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" })
12550
12652
  }
12551
12653
  ),
12552
12654
  open2 && pos ? (0, import_react_dom7.createPortal)(
12553
- /* @__PURE__ */ (0, import_jsx_runtime88.jsx)(
12655
+ /* @__PURE__ */ (0, import_jsx_runtime90.jsx)(
12554
12656
  "div",
12555
12657
  {
12556
12658
  ref: hoverCardRef,
@@ -12559,7 +12661,7 @@ function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, o
12559
12661
  style: { position: "fixed", left: pos.left, top: pos.top, bottom: pos.bottom, width: pos.width, zIndex },
12560
12662
  onMouseEnter: show,
12561
12663
  onMouseLeave: hide,
12562
- children: /* @__PURE__ */ (0, import_jsx_runtime88.jsx)(
12664
+ children: /* @__PURE__ */ (0, import_jsx_runtime90.jsx)(
12563
12665
  SoonCard,
12564
12666
  {
12565
12667
  label,
@@ -12589,10 +12691,10 @@ function formatEta(iso2) {
12589
12691
  var FormatEta = formatEta;
12590
12692
 
12591
12693
  // src/components/platform/Gate.tsx
12592
- var import_jsx_runtime89 = require("react/jsx-runtime");
12694
+ var import_jsx_runtime91 = require("react/jsx-runtime");
12593
12695
  function PermissionDenied({ permission, title, detail, compact: compact3 = false, className = "", ...rest }) {
12594
12696
  const need = Array.isArray(permission) ? permission : [permission].filter(Boolean);
12595
- return /* @__PURE__ */ (0, import_jsx_runtime89.jsxs)(
12697
+ return /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)(
12596
12698
  "div",
12597
12699
  {
12598
12700
  className: ["fd-stack", className].filter(Boolean).join(" "),
@@ -12608,14 +12710,14 @@ function PermissionDenied({ permission, title, detail, compact: compact3 = false
12608
12710
  },
12609
12711
  ...rest,
12610
12712
  children: [
12611
- /* @__PURE__ */ (0, import_jsx_runtime89.jsxs)("span", { className: "fd-row", style: { gap: 8 }, children: [
12612
- /* @__PURE__ */ (0, import_jsx_runtime89.jsx)("i", { className: "ph ph-lock-simple", style: { fontSize: 16, color: "var(--text-muted)" }, "aria-hidden": "true" }),
12613
- /* @__PURE__ */ (0, import_jsx_runtime89.jsx)("span", { className: compact3 ? "fd-label-lg" : "fd-h3", children: title || "You do not have access to this" })
12713
+ /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)("span", { className: "fd-row", style: { gap: 8 }, children: [
12714
+ /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("i", { className: "ph ph-lock-simple", style: { fontSize: 16, color: "var(--text-muted)" }, "aria-hidden": "true" }),
12715
+ /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("span", { className: compact3 ? "fd-label-lg" : "fd-h3", children: title || "You do not have access to this" })
12614
12716
  ] }),
12615
- /* @__PURE__ */ (0, import_jsx_runtime89.jsx)("p", { className: "fd-body-sm fd-secondary", style: { margin: 0, textWrap: "pretty" }, children: detail || "Your roles do not grant this. An administrator can change that from Admin \u2192 Users." }),
12616
- need.length ? /* @__PURE__ */ (0, import_jsx_runtime89.jsxs)("span", { className: "fd-row", style: { gap: 6, flexWrap: "wrap" }, children: [
12617
- /* @__PURE__ */ (0, import_jsx_runtime89.jsx)("span", { className: "fd-overline fd-muted", children: "Requires" }),
12618
- need.map((p) => /* @__PURE__ */ (0, import_jsx_runtime89.jsx)("code", { className: "fd-mono", style: {
12717
+ /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("p", { className: "fd-body-sm fd-secondary", style: { margin: 0, textWrap: "pretty" }, children: detail || "Your roles do not grant this. An administrator can change that from Admin \u2192 Users." }),
12718
+ need.length ? /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)("span", { className: "fd-row", style: { gap: 6, flexWrap: "wrap" }, children: [
12719
+ /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("span", { className: "fd-overline fd-muted", children: "Requires" }),
12720
+ need.map((p) => /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("code", { className: "fd-mono", style: {
12619
12721
  fontSize: 11.5,
12620
12722
  padding: "2px 7px",
12621
12723
  borderRadius: 5,
@@ -12628,7 +12730,7 @@ function PermissionDenied({ permission, title, detail, compact: compact3 = false
12628
12730
  );
12629
12731
  }
12630
12732
  function GatePending({ compact: compact3 = false, className = "" }) {
12631
- return /* @__PURE__ */ (0, import_jsx_runtime89.jsxs)(
12733
+ return /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)(
12632
12734
  "div",
12633
12735
  {
12634
12736
  className: ["fd-stack", className].filter(Boolean).join(" "),
@@ -12644,11 +12746,11 @@ function GatePending({ compact: compact3 = false, className = "" }) {
12644
12746
  textAlign: "left"
12645
12747
  },
12646
12748
  children: [
12647
- /* @__PURE__ */ (0, import_jsx_runtime89.jsxs)("span", { className: "fd-row", style: { gap: 8 }, children: [
12648
- /* @__PURE__ */ (0, import_jsx_runtime89.jsx)("i", { className: "ph ph-arrows-clockwise", style: { fontSize: 16, color: "var(--text-muted)" }, "aria-hidden": "true" }),
12649
- /* @__PURE__ */ (0, import_jsx_runtime89.jsx)("span", { className: compact3 ? "fd-label-lg" : "fd-h3", children: "Reconnecting\u2026" })
12749
+ /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)("span", { className: "fd-row", style: { gap: 8 }, children: [
12750
+ /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("i", { className: "ph ph-arrows-clockwise", style: { fontSize: 16, color: "var(--text-muted)" }, "aria-hidden": "true" }),
12751
+ /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("span", { className: compact3 ? "fd-label-lg" : "fd-h3", children: "Reconnecting\u2026" })
12650
12752
  ] }),
12651
- /* @__PURE__ */ (0, import_jsx_runtime89.jsx)("p", { className: "fd-body-sm fd-secondary", style: { margin: 0, textWrap: "pretty" }, children: "Your access can't be verified right now. This will resolve on its own once the connection is back." })
12753
+ /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("p", { className: "fd-body-sm fd-secondary", style: { margin: 0, textWrap: "pretty" }, children: "Your access can't be verified right now. This will resolve on its own once the connection is back." })
12652
12754
  ]
12653
12755
  }
12654
12756
  );
@@ -12658,7 +12760,7 @@ function Gate({ perm, anyOf, role, silent = false, fallback, pendingFallback, co
12658
12760
  if (pending) {
12659
12761
  if (pendingFallback !== void 0) return pendingFallback;
12660
12762
  if (silent) return null;
12661
- return /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(GatePending, { compact: compact3 });
12763
+ return /* @__PURE__ */ (0, import_jsx_runtime91.jsx)(GatePending, { compact: compact3 });
12662
12764
  }
12663
12765
  let ok = true;
12664
12766
  if (perm) ok = ok && can2(perm);
@@ -12667,7 +12769,7 @@ function Gate({ perm, anyOf, role, silent = false, fallback, pendingFallback, co
12667
12769
  if (ok) return children;
12668
12770
  if (fallback !== void 0) return fallback;
12669
12771
  if (silent) return null;
12670
- return /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(PermissionDenied, { permission: perm || anyOf, compact: compact3 });
12772
+ return /* @__PURE__ */ (0, import_jsx_runtime91.jsx)(PermissionDenied, { permission: perm || anyOf, compact: compact3 });
12671
12773
  }
12672
12774
  function FeatureGate({
12673
12775
  flag,
@@ -12690,7 +12792,7 @@ function FeatureGate({
12690
12792
  const f = SessionKit.findFlag(flag) || {};
12691
12793
  const missing = rt.missing || [];
12692
12794
  const canBypass = pending ? false : bypassPerm === null ? false : !bypassPerm || can2(bypassPerm);
12693
- return /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(
12795
+ return /* @__PURE__ */ (0, import_jsx_runtime91.jsx)(
12694
12796
  ComingSoon,
12695
12797
  {
12696
12798
  label: label || (variant === "inline" ? f.label || "Not wired yet" : "Designed \u2014 backend not wired yet"),
@@ -12711,22 +12813,22 @@ function FeatureGate({
12711
12813
  function PermissionHint({ perm, children }) {
12712
12814
  const { can: can2, pending } = useSessionContext();
12713
12815
  if (pending) {
12714
- return /* @__PURE__ */ (0, import_jsx_runtime89.jsx)("span", { title: "Access can't be verified right now", style: { display: "inline-flex", opacity: 0.45, cursor: "not-allowed" }, "aria-disabled": "true", children: /* @__PURE__ */ (0, import_jsx_runtime89.jsx)("span", { style: { pointerEvents: "none" }, children }) });
12816
+ return /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("span", { title: "Access can't be verified right now", style: { display: "inline-flex", opacity: 0.45, cursor: "not-allowed" }, "aria-disabled": "true", children: /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("span", { style: { pointerEvents: "none" }, children }) });
12715
12817
  }
12716
12818
  if (can2(perm)) return children;
12717
- return /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(
12819
+ return /* @__PURE__ */ (0, import_jsx_runtime91.jsx)(
12718
12820
  "span",
12719
12821
  {
12720
12822
  title: "Requires " + (Array.isArray(perm) ? perm.join(", ") : perm),
12721
12823
  style: { display: "inline-flex", opacity: 0.45, cursor: "not-allowed" },
12722
12824
  "aria-disabled": "true",
12723
- children: /* @__PURE__ */ (0, import_jsx_runtime89.jsx)("span", { style: { pointerEvents: "none" }, children })
12825
+ children: /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("span", { style: { pointerEvents: "none" }, children })
12724
12826
  }
12725
12827
  );
12726
12828
  }
12727
12829
 
12728
12830
  // src/components/platform/ModeSwitch.tsx
12729
- var import_jsx_runtime90 = require("react/jsx-runtime");
12831
+ var import_jsx_runtime92 = require("react/jsx-runtime");
12730
12832
  function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog, onOpenSpec, summary }) {
12731
12833
  const mode2 = useRuntimeMode();
12732
12834
  const panel = useInlinePanel();
@@ -12738,8 +12840,8 @@ function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog
12738
12840
  RuntimeKit.setMode(next);
12739
12841
  setOpen(false);
12740
12842
  };
12741
- return /* @__PURE__ */ (0, import_jsx_runtime90.jsxs)("span", { style: { display: "inline-flex" }, ref, children: [
12742
- /* @__PURE__ */ (0, import_jsx_runtime90.jsxs)(
12843
+ return /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("span", { style: { display: "inline-flex" }, ref, children: [
12844
+ /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)(
12743
12845
  "button",
12744
12846
  {
12745
12847
  type: "button",
@@ -12749,29 +12851,29 @@ function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog
12749
12851
  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.",
12750
12852
  className: "fd-mode-btn" + (test ? " is-test" : "") + (open2 ? " is-open" : ""),
12751
12853
  children: [
12752
- /* @__PURE__ */ (0, import_jsx_runtime90.jsx)("i", { className: "ph " + (test ? "ph-flask" : "ph-lightning"), style: { fontSize: 17 } }),
12753
- test && requestCount ? /* @__PURE__ */ (0, import_jsx_runtime90.jsx)("span", { className: "fd-mono fd-mode-count", children: requestCount > 99 ? "99+" : requestCount }, requestCount) : null
12854
+ /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("i", { className: "ph " + (test ? "ph-flask" : "ph-lightning"), style: { fontSize: 17 } }),
12855
+ test && requestCount ? /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("span", { className: "fd-mono fd-mode-count", children: requestCount > 99 ? "99+" : requestCount }, requestCount) : null
12754
12856
  ]
12755
12857
  }
12756
12858
  ),
12757
- /* @__PURE__ */ (0, import_jsx_runtime90.jsxs)(InlinePanelSurface, { panel, align: "right", offset: 8, width: 400, className: "fd-mode-pop", label: test ? "Test mode" : "Live mode", children: [
12758
- /* @__PURE__ */ (0, import_jsx_runtime90.jsxs)("span", { className: "fd-row", style: { gap: 10, padding: "12px 14px", borderBottom: "1px solid var(--border)" }, children: [
12759
- /* @__PURE__ */ (0, import_jsx_runtime90.jsxs)("span", { className: "fd-badge " + (test ? "fd-badge-warning" : "fd-badge-neutral"), children: [
12760
- /* @__PURE__ */ (0, import_jsx_runtime90.jsx)("i", { className: "ph " + (test ? "ph-flask" : "ph-lightning"), "aria-hidden": "true" }),
12859
+ /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)(InlinePanelSurface, { panel, align: "right", offset: 8, width: 400, className: "fd-mode-pop", label: test ? "Test mode" : "Live mode", children: [
12860
+ /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("span", { className: "fd-row", style: { gap: 10, padding: "12px 14px", borderBottom: "1px solid var(--border)" }, children: [
12861
+ /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("span", { className: "fd-badge " + (test ? "fd-badge-warning" : "fd-badge-neutral"), children: [
12862
+ /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("i", { className: "ph " + (test ? "ph-flask" : "ph-lightning"), "aria-hidden": "true" }),
12761
12863
  test ? "Test mode" : "Live mode"
12762
12864
  ] }),
12763
- test ? /* @__PURE__ */ (0, import_jsx_runtime90.jsxs)("span", { className: "fd-body-sm fd-muted fd-mono", children: [
12865
+ test ? /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("span", { className: "fd-body-sm fd-muted fd-mono", children: [
12764
12866
  requestCount,
12765
12867
  " simulated request",
12766
12868
  requestCount === 1 ? "" : "s"
12767
12869
  ] }) : null,
12768
- /* @__PURE__ */ (0, import_jsx_runtime90.jsx)("span", { style: { flex: 1 } }),
12769
- test && onClearLog ? /* @__PURE__ */ (0, import_jsx_runtime90.jsx)("button", { type: "button", className: "fd-soon-link", onClick: onClearLog, children: "Clear" }) : null
12870
+ /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("span", { style: { flex: 1 } }),
12871
+ test && onClearLog ? /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("button", { type: "button", className: "fd-soon-link", onClick: onClearLog, children: "Clear" }) : null
12770
12872
  ] }),
12771
- /* @__PURE__ */ (0, import_jsx_runtime90.jsxs)("span", { style: { display: "block", padding: "12px 14px", borderBottom: "1px solid var(--border)" }, children: [
12772
- /* @__PURE__ */ (0, import_jsx_runtime90.jsx)("span", { className: "fd-body-sm fd-secondary", style: { display: "block", textWrap: "pretty" }, children: test ? "Every feature is usable and nothing is obstructed, but no response comes from a real service \u2014 nothing you do here persists. Use this to review and demo the design." : "This is what a user would see today. " + s.incomplete + " of " + s.total + " features depend on backend work that is not wired yet, so they render under construction." }),
12773
- /* @__PURE__ */ (0, import_jsx_runtime90.jsxs)("span", { className: "fd-row", style: { gap: 8, marginTop: 10, flexWrap: "wrap" }, children: [
12774
- /* @__PURE__ */ (0, import_jsx_runtime90.jsxs)("span", { className: "fd-body-sm fd-muted fd-mono", children: [
12873
+ /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("span", { style: { display: "block", padding: "12px 14px", borderBottom: "1px solid var(--border)" }, children: [
12874
+ /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("span", { className: "fd-body-sm fd-secondary", style: { display: "block", textWrap: "pretty" }, children: test ? "Every feature is usable and nothing is obstructed, but no response comes from a real service \u2014 nothing you do here persists. Use this to review and demo the design." : "This is what a user would see today. " + s.incomplete + " of " + s.total + " features depend on backend work that is not wired yet, so they render under construction." }),
12875
+ /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("span", { className: "fd-row", style: { gap: 8, marginTop: 10, flexWrap: "wrap" }, children: [
12876
+ /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("span", { className: "fd-body-sm fd-muted fd-mono", children: [
12775
12877
  s.endpointsWired,
12776
12878
  " endpoint",
12777
12879
  s.endpointsWired === 1 ? "" : "s",
@@ -12781,58 +12883,58 @@ function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog
12781
12883
  s.total,
12782
12884
  " features complete"
12783
12885
  ] }),
12784
- onOpenSpec ? /* @__PURE__ */ (0, import_jsx_runtime90.jsxs)(import_jsx_runtime90.Fragment, { children: [
12785
- /* @__PURE__ */ (0, import_jsx_runtime90.jsx)("span", { style: { flex: 1 } }),
12786
- /* @__PURE__ */ (0, import_jsx_runtime90.jsxs)("button", { type: "button", className: "fd-soon-link", onClick: () => {
12886
+ onOpenSpec ? /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)(import_jsx_runtime92.Fragment, { children: [
12887
+ /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("span", { style: { flex: 1 } }),
12888
+ /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("button", { type: "button", className: "fd-soon-link", onClick: () => {
12787
12889
  setOpen(false);
12788
12890
  onOpenSpec();
12789
12891
  }, children: [
12790
12892
  "API spec ",
12791
- /* @__PURE__ */ (0, import_jsx_runtime90.jsx)("i", { className: "ph ph-arrow-right", "aria-hidden": "true" })
12893
+ /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("i", { className: "ph ph-arrow-right", "aria-hidden": "true" })
12792
12894
  ] })
12793
12895
  ] }) : null
12794
12896
  ] })
12795
12897
  ] }),
12796
- /* @__PURE__ */ (0, import_jsx_runtime90.jsxs)("span", { className: "fd-mode-choice", children: [
12797
- /* @__PURE__ */ (0, import_jsx_runtime90.jsxs)("button", { type: "button", className: "fd-mode-opt" + (!test ? " is-on" : ""), onClick: () => go("live"), children: [
12798
- /* @__PURE__ */ (0, import_jsx_runtime90.jsx)("i", { className: "ph ph-lightning", "aria-hidden": "true" }),
12799
- /* @__PURE__ */ (0, import_jsx_runtime90.jsxs)("span", { className: "fd-mode-opt-text", children: [
12800
- /* @__PURE__ */ (0, import_jsx_runtime90.jsx)("span", { className: "fd-mode-opt-title", children: "Live mode" }),
12801
- /* @__PURE__ */ (0, import_jsx_runtime90.jsx)("span", { className: "fd-mode-opt-desc", children: "Incomplete features under construction" })
12898
+ /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("span", { className: "fd-mode-choice", children: [
12899
+ /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("button", { type: "button", className: "fd-mode-opt" + (!test ? " is-on" : ""), onClick: () => go("live"), children: [
12900
+ /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("i", { className: "ph ph-lightning", "aria-hidden": "true" }),
12901
+ /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("span", { className: "fd-mode-opt-text", children: [
12902
+ /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("span", { className: "fd-mode-opt-title", children: "Live mode" }),
12903
+ /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("span", { className: "fd-mode-opt-desc", children: "Incomplete features under construction" })
12802
12904
  ] }),
12803
- !test ? /* @__PURE__ */ (0, import_jsx_runtime90.jsx)("i", { className: "ph ph-check", "aria-hidden": "true" }) : null
12905
+ !test ? /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("i", { className: "ph ph-check", "aria-hidden": "true" }) : null
12804
12906
  ] }),
12805
- /* @__PURE__ */ (0, import_jsx_runtime90.jsxs)("button", { type: "button", className: "fd-mode-opt" + (test ? " is-on" : ""), onClick: () => go("test"), children: [
12806
- /* @__PURE__ */ (0, import_jsx_runtime90.jsx)("i", { className: "ph ph-flask", "aria-hidden": "true" }),
12807
- /* @__PURE__ */ (0, import_jsx_runtime90.jsxs)("span", { className: "fd-mode-opt-text", children: [
12808
- /* @__PURE__ */ (0, import_jsx_runtime90.jsx)("span", { className: "fd-mode-opt-title", children: "Test mode" }),
12809
- /* @__PURE__ */ (0, import_jsx_runtime90.jsx)("span", { className: "fd-mode-opt-desc", children: "Everything usable, all data simulated" })
12907
+ /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("button", { type: "button", className: "fd-mode-opt" + (test ? " is-on" : ""), onClick: () => go("test"), children: [
12908
+ /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("i", { className: "ph ph-flask", "aria-hidden": "true" }),
12909
+ /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("span", { className: "fd-mode-opt-text", children: [
12910
+ /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("span", { className: "fd-mode-opt-title", children: "Test mode" }),
12911
+ /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("span", { className: "fd-mode-opt-desc", children: "Everything usable, all data simulated" })
12810
12912
  ] }),
12811
- test ? /* @__PURE__ */ (0, import_jsx_runtime90.jsx)("i", { className: "ph ph-check", "aria-hidden": "true" }) : null
12913
+ test ? /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("i", { className: "ph ph-check", "aria-hidden": "true" }) : null
12812
12914
  ] })
12813
12915
  ] }),
12814
- test && renderLog ? /* @__PURE__ */ (0, import_jsx_runtime90.jsx)("span", { style: { display: "block", maxHeight: 340, overflowY: "auto", borderTop: "1px solid var(--border)" }, children: renderLog() }) : null
12916
+ test && renderLog ? /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("span", { style: { display: "block", maxHeight: 340, overflowY: "auto", borderTop: "1px solid var(--border)" }, children: renderLog() }) : null
12815
12917
  ] })
12816
12918
  ] });
12817
12919
  }
12818
12920
  function TestModeBar({ onExit }) {
12819
12921
  const mode2 = useRuntimeMode();
12820
12922
  if (mode2 !== "test") return null;
12821
- return /* @__PURE__ */ (0, import_jsx_runtime90.jsxs)("div", { className: "fd-testbar", role: "status", children: [
12822
- /* @__PURE__ */ (0, import_jsx_runtime90.jsxs)("span", { className: "fd-badge fd-badge-warning", children: [
12823
- /* @__PURE__ */ (0, import_jsx_runtime90.jsx)("i", { className: "ph ph-flask", "aria-hidden": "true" }),
12923
+ return /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("div", { className: "fd-testbar", role: "status", children: [
12924
+ /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("span", { className: "fd-badge fd-badge-warning", children: [
12925
+ /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("i", { className: "ph ph-flask", "aria-hidden": "true" }),
12824
12926
  "Test mode"
12825
12927
  ] }),
12826
- /* @__PURE__ */ (0, import_jsx_runtime90.jsx)("span", { className: "fd-testbar-detail", children: "Every feature is unlocked and every response is simulated \u2014 nothing here persists." }),
12827
- /* @__PURE__ */ (0, import_jsx_runtime90.jsxs)("button", { type: "button", className: "fd-soon-link", onClick: () => onExit ? onExit() : RuntimeKit.setMode("live"), children: [
12828
- /* @__PURE__ */ (0, import_jsx_runtime90.jsx)("i", { className: "ph ph-lightning", "aria-hidden": "true" }),
12928
+ /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("span", { className: "fd-testbar-detail", children: "Every feature is unlocked and every response is simulated \u2014 nothing here persists." }),
12929
+ /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("button", { type: "button", className: "fd-soon-link", onClick: () => onExit ? onExit() : RuntimeKit.setMode("live"), children: [
12930
+ /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("i", { className: "ph ph-lightning", "aria-hidden": "true" }),
12829
12931
  " Back to live mode"
12830
12932
  ] })
12831
12933
  ] });
12832
12934
  }
12833
12935
 
12834
12936
  // src/components/planner/ChannelMeta.tsx
12835
- var import_jsx_runtime91 = require("react/jsx-runtime");
12937
+ var import_jsx_runtime93 = require("react/jsx-runtime");
12836
12938
  var CHANNEL_WEIGHTS = {
12837
12939
  "OOH": 50,
12838
12940
  "DOOH": 50,
@@ -12885,9 +12987,9 @@ function ChannelTag({ channel, size = "md", showLabel = true, dot = false, weigh
12885
12987
  const m = ChannelMeta(channel);
12886
12988
  const wt = channelWeightOf(channel || "");
12887
12989
  if (dot) {
12888
- return /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("span", { className: ["fd-chan-dot", className].filter(Boolean).join(" "), title: m.name, style: { background: m.color }, ...rest });
12990
+ return /* @__PURE__ */ (0, import_jsx_runtime93.jsx)("span", { className: ["fd-chan-dot", className].filter(Boolean).join(" "), title: m.name, style: { background: m.color }, ...rest });
12889
12991
  }
12890
- return /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)(
12992
+ return /* @__PURE__ */ (0, import_jsx_runtime93.jsxs)(
12891
12993
  "span",
12892
12994
  {
12893
12995
  className: ["fd-chan", size === "sm" ? "fd-chan-sm" : "", className].filter(Boolean).join(" "),
@@ -12895,16 +12997,16 @@ function ChannelTag({ channel, size = "md", showLabel = true, dot = false, weigh
12895
12997
  style: { "--chan": m.color },
12896
12998
  ...rest,
12897
12999
  children: [
12898
- /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("i", { className: "ph ph-" + m.icon, "aria-hidden": "true" }),
12899
- showLabel ? /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("span", { className: "fd-chan-label", children: m.label }) : null,
12900
- weight ? /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("span", { className: "fd-chan-weight", children: wt || 0 }) : null
13000
+ /* @__PURE__ */ (0, import_jsx_runtime93.jsx)("i", { className: "ph ph-" + m.icon, "aria-hidden": "true" }),
13001
+ showLabel ? /* @__PURE__ */ (0, import_jsx_runtime93.jsx)("span", { className: "fd-chan-label", children: m.label }) : null,
13002
+ weight ? /* @__PURE__ */ (0, import_jsx_runtime93.jsx)("span", { className: "fd-chan-weight", children: wt || 0 }) : null
12901
13003
  ]
12902
13004
  }
12903
13005
  );
12904
13006
  }
12905
13007
 
12906
13008
  // src/components/planner/SaturationDistribution.tsx
12907
- var import_jsx_runtime92 = require("react/jsx-runtime");
13009
+ var import_jsx_runtime94 = require("react/jsx-runtime");
12908
13010
  var BANDS2 = [
12909
13011
  { key: "weak", label: "Weak", n: 1, range: "< 50" },
12910
13012
  { key: "adequate", label: "Adequate", n: 2, range: "50\u2013100" },
@@ -12915,24 +13017,24 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
12915
13017
  const grouped = BANDS2.map((b) => ({ ...b, items: campuses.filter((c) => c.band === b.key) }));
12916
13018
  const tallest = Math.max(1, ...grouped.map((g) => g.items.length));
12917
13019
  const floor = BANDS2.find((b) => b.key === floorBand) || BANDS2[0];
12918
- return /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 16 }, children: [
12919
- /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("div", { style: { display: "grid", gridTemplateColumns: "repeat(4,minmax(0,1fr))", gap: 12, alignItems: "end" }, children: grouped.map((g) => {
13020
+ return /* @__PURE__ */ (0, import_jsx_runtime94.jsxs)("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 16 }, children: [
13021
+ /* @__PURE__ */ (0, import_jsx_runtime94.jsx)("div", { style: { display: "grid", gridTemplateColumns: "repeat(4,minmax(0,1fr))", gap: 12, alignItems: "end" }, children: grouped.map((g) => {
12920
13022
  const mark = "var(--csi-" + g.n + "-mark)";
12921
13023
  const active = selectedBand === g.key;
12922
- return /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)(
13024
+ return /* @__PURE__ */ (0, import_jsx_runtime94.jsxs)(
12923
13025
  "button",
12924
13026
  {
12925
13027
  type: "button",
12926
13028
  onClick: onSelectBand ? () => onSelectBand(active ? null : g.key) : void 0,
12927
13029
  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)" },
12928
13030
  children: [
12929
- /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("span", { style: { display: "flex", flexDirection: "column-reverse", gap: 4, minHeight: tallest * 24, minWidth: 0 }, children: loading ? Array.from({ length: 3 }).map((_, i) => /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("span", { className: "fd-skel", style: { height: 16, borderRadius: 4 } }, i)) : g.items.map((c) => (
13031
+ /* @__PURE__ */ (0, import_jsx_runtime94.jsx)("span", { style: { display: "flex", flexDirection: "column-reverse", gap: 4, minHeight: tallest * 24, minWidth: 0 }, children: loading ? Array.from({ length: 3 }).map((_, i) => /* @__PURE__ */ (0, import_jsx_runtime94.jsx)("span", { className: "fd-skel", style: { height: 16, borderRadius: 4 } }, i)) : g.items.map((c) => (
12930
13032
  // `overflow: hidden` + `white-space: nowrap` only clips once the span
12931
13033
  // actually HAS a bounded width to clip against (see the grid/flex
12932
13034
  // `minWidth: 0` chain above) — `textOverflow: ellipsis` then makes
12933
13035
  // that clip readable instead of a hard cut mid-letter; the full name
12934
13036
  // is still one hover away via `title`.
12935
- /* @__PURE__ */ (0, import_jsx_runtime92.jsx)(
13037
+ /* @__PURE__ */ (0, import_jsx_runtime94.jsx)(
12936
13038
  "span",
12937
13039
  {
12938
13040
  title: c.name + " \xB7 " + c.crp,
@@ -12942,13 +13044,13 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
12942
13044
  c.name
12943
13045
  )
12944
13046
  )) }),
12945
- /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("span", { className: "fd-row", style: { gap: 8, alignItems: "baseline" }, children: [
12946
- /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("span", { className: "fd-num-hero", style: { fontSize: 30, color: g.items.length ? "var(--text)" : "var(--text-disabled)" }, children: loading ? "\u2013" : g.items.length }),
12947
- /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("span", { className: "fd-meter", style: { gap: 2, color: mark }, "aria-hidden": "true", children: [1, 2, 3, 4].map((i) => /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("span", { className: "fd-meter-seg" + (i <= g.n ? " is-on" : ""), style: { width: 4, height: 9 } }, i)) })
13047
+ /* @__PURE__ */ (0, import_jsx_runtime94.jsxs)("span", { className: "fd-row", style: { gap: 8, alignItems: "baseline" }, children: [
13048
+ /* @__PURE__ */ (0, import_jsx_runtime94.jsx)("span", { className: "fd-num-hero", style: { fontSize: 30, color: g.items.length ? "var(--text)" : "var(--text-disabled)" }, children: loading ? "\u2013" : g.items.length }),
13049
+ /* @__PURE__ */ (0, import_jsx_runtime94.jsx)("span", { className: "fd-meter", style: { gap: 2, color: mark }, "aria-hidden": "true", children: [1, 2, 3, 4].map((i) => /* @__PURE__ */ (0, import_jsx_runtime94.jsx)("span", { className: "fd-meter-seg" + (i <= g.n ? " is-on" : ""), style: { width: 4, height: 9 } }, i)) })
12948
13050
  ] }),
12949
- /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("span", { className: "fd-stack", style: { gap: 1 }, children: [
12950
- /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("span", { className: "fd-label-lg", children: g.label }),
12951
- /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("span", { className: "fd-body-sm fd-muted", style: { fontSize: 11.5 }, children: [
13051
+ /* @__PURE__ */ (0, import_jsx_runtime94.jsxs)("span", { className: "fd-stack", style: { gap: 1 }, children: [
13052
+ /* @__PURE__ */ (0, import_jsx_runtime94.jsx)("span", { className: "fd-label-lg", children: g.label }),
13053
+ /* @__PURE__ */ (0, import_jsx_runtime94.jsxs)("span", { className: "fd-body-sm fd-muted", style: { fontSize: 11.5 }, children: [
12952
13054
  "CRP ",
12953
13055
  g.range
12954
13056
  ] })
@@ -12958,10 +13060,10 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
12958
13060
  g.key
12959
13061
  );
12960
13062
  }) }),
12961
- floorBand ? /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("div", { className: "fd-row", style: { gap: 10, padding: "12px 14px", borderRadius: "var(--r-md)", background: "var(--surface-2)", border: "1px solid var(--border)", flexWrap: "wrap" }, children: [
12962
- /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("span", { className: "fd-meter", style: { gap: 2, color: "var(--csi-" + floor.n + "-mark)" }, "aria-hidden": "true", children: [1, 2, 3, 4].map((i) => /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("span", { className: "fd-meter-seg" + (i <= floor.n ? " is-on" : ""), style: { width: 5, height: 12 } }, i)) }),
12963
- /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("span", { className: "fd-body-sm fd-secondary", style: { flex: 1, minWidth: 240 }, children: [
12964
- /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("strong", { style: { color: "var(--text)" }, children: [
13063
+ floorBand ? /* @__PURE__ */ (0, import_jsx_runtime94.jsxs)("div", { className: "fd-row", style: { gap: 10, padding: "12px 14px", borderRadius: "var(--r-md)", background: "var(--surface-2)", border: "1px solid var(--border)", flexWrap: "wrap" }, children: [
13064
+ /* @__PURE__ */ (0, import_jsx_runtime94.jsx)("span", { className: "fd-meter", style: { gap: 2, color: "var(--csi-" + floor.n + "-mark)" }, "aria-hidden": "true", children: [1, 2, 3, 4].map((i) => /* @__PURE__ */ (0, import_jsx_runtime94.jsx)("span", { className: "fd-meter-seg" + (i <= floor.n ? " is-on" : ""), style: { width: 5, height: 12 } }, i)) }),
13065
+ /* @__PURE__ */ (0, import_jsx_runtime94.jsxs)("span", { className: "fd-body-sm fd-secondary", style: { flex: 1, minWidth: 240 }, children: [
13066
+ /* @__PURE__ */ (0, import_jsx_runtime94.jsxs)("strong", { style: { color: "var(--text)" }, children: [
12965
13067
  "Plan floor ",
12966
13068
  floorScore
12967
13069
  ] }),
@@ -12972,8 +13074,8 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
12972
13074
  }
12973
13075
 
12974
13076
  // src/components/planner/MixGap.tsx
12975
- var React66 = __toESM(require("react"), 1);
12976
- var import_jsx_runtime93 = require("react/jsx-runtime");
13077
+ var React67 = __toESM(require("react"), 1);
13078
+ var import_jsx_runtime95 = require("react/jsx-runtime");
12977
13079
  var MIX_GAP_LAYOUT = {
12978
13080
  trackHeight: 30,
12979
13081
  barHeight: 20,
@@ -12987,19 +13089,19 @@ function mixGapOffset(value, max) {
12987
13089
  }
12988
13090
  function MixGap({ rows = [], loading = false, className = "" }) {
12989
13091
  const max = Math.max(1, ...rows.flatMap((r) => [r.target, r.realized]));
12990
- const [hover, setHover] = React66.useState(null);
13092
+ const [hover, setHover] = React67.useState(null);
12991
13093
  const toneOf = (gap) => gap >= -1 ? "ok" : gap >= -4 ? "warn" : "danger";
12992
13094
  const TONE = { ok: "var(--ok-solid)", warn: "var(--warn-solid)", danger: "var(--danger-solid)" };
12993
13095
  const { trackHeight, barHeight, targetWidth, labelGap } = MIX_GAP_LAYOUT;
12994
13096
  const barTop = (trackHeight - barHeight) / 2;
12995
- return /* @__PURE__ */ (0, import_jsx_runtime93.jsxs)("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 4 }, children: [
12996
- /* @__PURE__ */ (0, import_jsx_runtime93.jsxs)("div", { className: "fd-row", style: { gap: 16, justifyContent: "flex-end", paddingBottom: 6, flexWrap: "wrap" }, children: [
12997
- [["On target", TONE.ok], ["Close", TONE.warn], ["Short", TONE.danger]].map(([l, c]) => /* @__PURE__ */ (0, import_jsx_runtime93.jsxs)("span", { className: "fd-row fd-body-sm fd-muted", style: { gap: 6 }, children: [
12998
- /* @__PURE__ */ (0, import_jsx_runtime93.jsx)("span", { style: { width: 14, height: 9, borderRadius: 2, background: c } }),
13097
+ return /* @__PURE__ */ (0, import_jsx_runtime95.jsxs)("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 4 }, children: [
13098
+ /* @__PURE__ */ (0, import_jsx_runtime95.jsxs)("div", { className: "fd-row", style: { gap: 16, justifyContent: "flex-end", paddingBottom: 6, flexWrap: "wrap" }, children: [
13099
+ [["On target", TONE.ok], ["Close", TONE.warn], ["Short", TONE.danger]].map(([l, c]) => /* @__PURE__ */ (0, import_jsx_runtime95.jsxs)("span", { className: "fd-row fd-body-sm fd-muted", style: { gap: 6 }, children: [
13100
+ /* @__PURE__ */ (0, import_jsx_runtime95.jsx)("span", { style: { width: 14, height: 9, borderRadius: 2, background: c } }),
12999
13101
  l
13000
13102
  ] }, l)),
13001
- /* @__PURE__ */ (0, import_jsx_runtime93.jsxs)("span", { className: "fd-row fd-body-sm fd-muted", style: { gap: 6 }, children: [
13002
- /* @__PURE__ */ (0, import_jsx_runtime93.jsx)("span", { "data-mixgap-legend-target": "", style: { width: targetWidth, height: 16, borderRadius: 1, background: MIX_GAP_TARGET_STRIPE } }),
13103
+ /* @__PURE__ */ (0, import_jsx_runtime95.jsxs)("span", { className: "fd-row fd-body-sm fd-muted", style: { gap: 6 }, children: [
13104
+ /* @__PURE__ */ (0, import_jsx_runtime95.jsx)("span", { "data-mixgap-legend-target": "", style: { width: targetWidth, height: 16, borderRadius: 1, background: MIX_GAP_TARGET_STRIPE } }),
13003
13105
  "Target"
13004
13106
  ] })
13005
13107
  ] }),
@@ -13008,7 +13110,7 @@ function MixGap({ rows = [], loading = false, className = "" }) {
13008
13110
  const tone = toneOf(gap);
13009
13111
  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 : "");
13010
13112
  const labelLeft = r.realized > r.target ? `calc(${mixGapOffset(r.realized, max)} + ${labelGap}px)` : `calc(${mixGapOffset(r.target, max)} + ${targetWidth / 2 + labelGap}px)`;
13011
- return /* @__PURE__ */ (0, import_jsx_runtime93.jsxs)(
13113
+ return /* @__PURE__ */ (0, import_jsx_runtime95.jsxs)(
13012
13114
  "div",
13013
13115
  {
13014
13116
  className: "fd-row",
@@ -13016,15 +13118,15 @@ function MixGap({ rows = [], loading = false, className = "" }) {
13016
13118
  onMouseEnter: () => setHover(r.channel),
13017
13119
  onMouseLeave: () => setHover(null),
13018
13120
  children: [
13019
- /* @__PURE__ */ (0, import_jsx_runtime93.jsx)("span", { style: { width: 128, flex: "none" }, children: /* @__PURE__ */ (0, import_jsx_runtime93.jsx)(ChannelTag, { channel: r.channel, size: "sm" }) }),
13020
- /* @__PURE__ */ (0, import_jsx_runtime93.jsx)("span", { style: { position: "relative", flex: 1, height: trackHeight, minWidth: 120 }, children: loading ? /* @__PURE__ */ (0, import_jsx_runtime93.jsx)("span", { className: "fd-skel", style: { position: "absolute", left: 0, right: 0, top: barTop, height: barHeight, borderRadius: 3 } }) : /* @__PURE__ */ (0, import_jsx_runtime93.jsxs)(import_jsx_runtime93.Fragment, { children: [
13021
- /* @__PURE__ */ (0, import_jsx_runtime93.jsx)("span", { "data-mixgap-bar": "", style: { position: "absolute", left: 0, top: barTop, height: barHeight, width: mixGapOffset(r.realized, max), background: TONE[tone], borderRadius: "2px 3px 3px 2px", transition: "width var(--dur-slow) var(--ease), background var(--dur-base) var(--ease)" } }),
13022
- /* @__PURE__ */ (0, import_jsx_runtime93.jsx)("span", { "data-mixgap-target": "", style: { position: "absolute", left: `calc(${mixGapOffset(r.target, max)} - ${targetWidth / 2}px)`, top: 0, width: targetWidth, height: trackHeight, background: MIX_GAP_TARGET_STRIPE, borderRadius: 1 } }),
13023
- /* @__PURE__ */ (0, import_jsx_runtime93.jsxs)("span", { "data-mixgap-label": "", className: "fd-num", style: { position: "absolute", left: labelLeft, top: "50%", transform: "translateY(-50%)", fontSize: 12, color: "var(--text-muted)", whiteSpace: "nowrap" }, children: [
13121
+ /* @__PURE__ */ (0, import_jsx_runtime95.jsx)("span", { style: { width: 128, flex: "none" }, children: /* @__PURE__ */ (0, import_jsx_runtime95.jsx)(ChannelTag, { channel: r.channel, size: "sm" }) }),
13122
+ /* @__PURE__ */ (0, import_jsx_runtime95.jsx)("span", { style: { position: "relative", flex: 1, height: trackHeight, minWidth: 120 }, children: loading ? /* @__PURE__ */ (0, import_jsx_runtime95.jsx)("span", { className: "fd-skel", style: { position: "absolute", left: 0, right: 0, top: barTop, height: barHeight, borderRadius: 3 } }) : /* @__PURE__ */ (0, import_jsx_runtime95.jsxs)(import_jsx_runtime95.Fragment, { children: [
13123
+ /* @__PURE__ */ (0, import_jsx_runtime95.jsx)("span", { "data-mixgap-bar": "", style: { position: "absolute", left: 0, top: barTop, height: barHeight, width: mixGapOffset(r.realized, max), background: TONE[tone], borderRadius: "2px 3px 3px 2px", transition: "width var(--dur-slow) var(--ease), background var(--dur-base) var(--ease)" } }),
13124
+ /* @__PURE__ */ (0, import_jsx_runtime95.jsx)("span", { "data-mixgap-target": "", style: { position: "absolute", left: `calc(${mixGapOffset(r.target, max)} - ${targetWidth / 2}px)`, top: 0, width: targetWidth, height: trackHeight, background: MIX_GAP_TARGET_STRIPE, borderRadius: 1 } }),
13125
+ /* @__PURE__ */ (0, import_jsx_runtime95.jsxs)("span", { "data-mixgap-label": "", className: "fd-num", style: { position: "absolute", left: labelLeft, top: "50%", transform: "translateY(-50%)", fontSize: 12, color: "var(--text-muted)", whiteSpace: "nowrap" }, children: [
13024
13126
  r.realized,
13025
13127
  "%"
13026
13128
  ] }),
13027
- hover === r.channel ? /* @__PURE__ */ (0, import_jsx_runtime93.jsx)("span", { className: "fd-tooltip", role: "tooltip", style: { position: "absolute", left: 0, right: "auto", bottom: trackHeight + 4, maxWidth: "min(340px, 100%)", whiteSpace: "normal", textAlign: "left", width: "max-content" }, children: tip }) : null
13129
+ hover === r.channel ? /* @__PURE__ */ (0, import_jsx_runtime95.jsx)("span", { className: "fd-tooltip", role: "tooltip", style: { position: "absolute", left: 0, right: "auto", bottom: trackHeight + 4, maxWidth: "min(340px, 100%)", whiteSpace: "normal", textAlign: "left", width: "max-content" }, children: tip }) : null
13028
13130
  ] }) })
13029
13131
  ]
13030
13132
  },
@@ -13035,7 +13137,7 @@ function MixGap({ rows = [], loading = false, className = "" }) {
13035
13137
  }
13036
13138
 
13037
13139
  // src/components/planner/ChannelContribution.tsx
13038
- var import_jsx_runtime94 = require("react/jsx-runtime");
13140
+ var import_jsx_runtime96 = require("react/jsx-runtime");
13039
13141
  var money = (n) => "$" + Math.round(n).toLocaleString();
13040
13142
  function ChannelContribution({
13041
13143
  channels = [],
@@ -13051,9 +13153,9 @@ function ChannelContribution({
13051
13153
  const grand = total !== void 0 ? total : base + bonus;
13052
13154
  const pct = (v) => grand ? v / grand * 100 : 0;
13053
13155
  const spendTotal = channels.reduce((s, c) => s + Number(String(c.spend || 0).replace(/[^0-9.]/g, "")), 0);
13054
- return /* @__PURE__ */ (0, import_jsx_runtime94.jsxs)("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 16 }, children: [
13055
- loading ? /* @__PURE__ */ (0, import_jsx_runtime94.jsx)("span", { className: "fd-skel", style: { height: 34, borderRadius: "var(--r-sm)" } }) : /* @__PURE__ */ (0, import_jsx_runtime94.jsxs)("div", { className: "fd-row", style: { height: 34, borderRadius: "var(--r-sm)", overflow: "hidden", gap: 2, background: "var(--surface-3)" }, children: [
13056
- channels.map((c) => /* @__PURE__ */ (0, import_jsx_runtime94.jsx)(
13156
+ return /* @__PURE__ */ (0, import_jsx_runtime96.jsxs)("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 16 }, children: [
13157
+ loading ? /* @__PURE__ */ (0, import_jsx_runtime96.jsx)("span", { className: "fd-skel", style: { height: 34, borderRadius: "var(--r-sm)" } }) : /* @__PURE__ */ (0, import_jsx_runtime96.jsxs)("div", { className: "fd-row", style: { height: 34, borderRadius: "var(--r-sm)", overflow: "hidden", gap: 2, background: "var(--surface-3)" }, children: [
13158
+ channels.map((c) => /* @__PURE__ */ (0, import_jsx_runtime96.jsx)(
13057
13159
  "span",
13058
13160
  {
13059
13161
  title: c.name + " \xB7 " + c.crp.toFixed(1) + " CRP",
@@ -13062,7 +13164,7 @@ function ChannelContribution({
13062
13164
  },
13063
13165
  c.name
13064
13166
  )),
13065
- bonus > 0 ? /* @__PURE__ */ (0, import_jsx_runtime94.jsx)(
13167
+ bonus > 0 ? /* @__PURE__ */ (0, import_jsx_runtime96.jsx)(
13066
13168
  "span",
13067
13169
  {
13068
13170
  title: "Surround-sound bonus +" + bonusPct + "%",
@@ -13071,18 +13173,18 @@ function ChannelContribution({
13071
13173
  }
13072
13174
  ) : null
13073
13175
  ] }),
13074
- showTable ? /* @__PURE__ */ (0, import_jsx_runtime94.jsxs)("table", { className: "fd-table", style: { fontSize: "var(--body-sm-size)" }, children: [
13075
- /* @__PURE__ */ (0, import_jsx_runtime94.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime94.jsxs)("tr", { children: [
13076
- /* @__PURE__ */ (0, import_jsx_runtime94.jsx)("th", { style: { width: "34%" }, children: "Channel" }),
13077
- /* @__PURE__ */ (0, import_jsx_runtime94.jsx)("th", { style: { width: "16%" }, children: "Weight" }),
13078
- /* @__PURE__ */ (0, import_jsx_runtime94.jsx)("th", { className: "is-num", style: { width: "16%" }, children: "Spend" }),
13079
- /* @__PURE__ */ (0, import_jsx_runtime94.jsx)("th", { className: "is-num", style: { width: "17%" }, children: "CRP" }),
13080
- /* @__PURE__ */ (0, import_jsx_runtime94.jsx)("th", { className: "is-num", style: { width: "17%" }, children: "Share" })
13176
+ showTable ? /* @__PURE__ */ (0, import_jsx_runtime96.jsxs)("table", { className: "fd-table", style: { fontSize: "var(--body-sm-size)" }, children: [
13177
+ /* @__PURE__ */ (0, import_jsx_runtime96.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime96.jsxs)("tr", { children: [
13178
+ /* @__PURE__ */ (0, import_jsx_runtime96.jsx)("th", { style: { width: "34%" }, children: "Channel" }),
13179
+ /* @__PURE__ */ (0, import_jsx_runtime96.jsx)("th", { style: { width: "16%" }, children: "Weight" }),
13180
+ /* @__PURE__ */ (0, import_jsx_runtime96.jsx)("th", { className: "is-num", style: { width: "16%" }, children: "Spend" }),
13181
+ /* @__PURE__ */ (0, import_jsx_runtime96.jsx)("th", { className: "is-num", style: { width: "17%" }, children: "CRP" }),
13182
+ /* @__PURE__ */ (0, import_jsx_runtime96.jsx)("th", { className: "is-num", style: { width: "17%" }, children: "Share" })
13081
13183
  ] }) }),
13082
- /* @__PURE__ */ (0, import_jsx_runtime94.jsxs)("tbody", { children: [
13083
- channels.map((c) => /* @__PURE__ */ (0, import_jsx_runtime94.jsxs)("tr", { children: [
13084
- /* @__PURE__ */ (0, import_jsx_runtime94.jsx)("td", { children: /* @__PURE__ */ (0, import_jsx_runtime94.jsx)(ChannelTag, { channel: c.name, size: "sm" }) }),
13085
- /* @__PURE__ */ (0, import_jsx_runtime94.jsx)("td", { children: /* @__PURE__ */ (0, import_jsx_runtime94.jsx)(
13184
+ /* @__PURE__ */ (0, import_jsx_runtime96.jsxs)("tbody", { children: [
13185
+ channels.map((c) => /* @__PURE__ */ (0, import_jsx_runtime96.jsxs)("tr", { children: [
13186
+ /* @__PURE__ */ (0, import_jsx_runtime96.jsx)("td", { children: /* @__PURE__ */ (0, import_jsx_runtime96.jsx)(ChannelTag, { channel: c.name, size: "sm" }) }),
13187
+ /* @__PURE__ */ (0, import_jsx_runtime96.jsx)("td", { children: /* @__PURE__ */ (0, import_jsx_runtime96.jsx)(
13086
13188
  "span",
13087
13189
  {
13088
13190
  className: "fd-badge fd-badge-neutral",
@@ -13091,38 +13193,38 @@ function ChannelContribution({
13091
13193
  children: "weight " + (channelWeightOf(c.name) || 0)
13092
13194
  }
13093
13195
  ) }),
13094
- /* @__PURE__ */ (0, import_jsx_runtime94.jsx)("td", { className: "is-num", children: c.spend }),
13095
- /* @__PURE__ */ (0, import_jsx_runtime94.jsx)("td", { className: "is-num", children: c.crp.toFixed(1) }),
13096
- /* @__PURE__ */ (0, import_jsx_runtime94.jsxs)("td", { className: "is-num", children: [
13196
+ /* @__PURE__ */ (0, import_jsx_runtime96.jsx)("td", { className: "is-num", children: c.spend }),
13197
+ /* @__PURE__ */ (0, import_jsx_runtime96.jsx)("td", { className: "is-num", children: c.crp.toFixed(1) }),
13198
+ /* @__PURE__ */ (0, import_jsx_runtime96.jsxs)("td", { className: "is-num", children: [
13097
13199
  pct(c.crp).toFixed(0),
13098
13200
  "%"
13099
13201
  ] })
13100
13202
  ] }, c.name)),
13101
- bonus > 0 ? /* @__PURE__ */ (0, import_jsx_runtime94.jsxs)("tr", { children: [
13102
- /* @__PURE__ */ (0, import_jsx_runtime94.jsx)("td", { children: /* @__PURE__ */ (0, import_jsx_runtime94.jsxs)("span", { className: "fd-row", style: { gap: 9, fontWeight: 600 }, children: [
13103
- /* @__PURE__ */ (0, import_jsx_runtime94.jsx)("span", { style: { width: 9, height: 9, borderRadius: 2, background: "repeating-linear-gradient(135deg,var(--csi-3-mark) 0 3px,var(--csi-2-mark) 3px 6px)", flex: "none" } }),
13203
+ bonus > 0 ? /* @__PURE__ */ (0, import_jsx_runtime96.jsxs)("tr", { children: [
13204
+ /* @__PURE__ */ (0, import_jsx_runtime96.jsx)("td", { children: /* @__PURE__ */ (0, import_jsx_runtime96.jsxs)("span", { className: "fd-row", style: { gap: 9, fontWeight: 600 }, children: [
13205
+ /* @__PURE__ */ (0, import_jsx_runtime96.jsx)("span", { style: { width: 9, height: 9, borderRadius: 2, background: "repeating-linear-gradient(135deg,var(--csi-3-mark) 0 3px,var(--csi-2-mark) 3px 6px)", flex: "none" } }),
13104
13206
  "Surround-sound bonus"
13105
13207
  ] }) }),
13106
- /* @__PURE__ */ (0, import_jsx_runtime94.jsx)("td", { children: /* @__PURE__ */ (0, import_jsx_runtime94.jsxs)("span", { className: "fd-badge fd-badge-success", style: { height: 20, fontSize: 11 }, children: [
13208
+ /* @__PURE__ */ (0, import_jsx_runtime96.jsx)("td", { children: /* @__PURE__ */ (0, import_jsx_runtime96.jsxs)("span", { className: "fd-badge fd-badge-success", style: { height: 20, fontSize: 11 }, children: [
13107
13209
  "+",
13108
13210
  bonusPct,
13109
13211
  "% of +",
13110
13212
  bonusMax,
13111
13213
  "%"
13112
13214
  ] }) }),
13113
- /* @__PURE__ */ (0, import_jsx_runtime94.jsx)("td", { className: "is-num fd-muted", children: "\u2014" }),
13114
- /* @__PURE__ */ (0, import_jsx_runtime94.jsx)("td", { className: "is-num", children: bonus.toFixed(1) }),
13115
- /* @__PURE__ */ (0, import_jsx_runtime94.jsxs)("td", { className: "is-num", children: [
13215
+ /* @__PURE__ */ (0, import_jsx_runtime96.jsx)("td", { className: "is-num fd-muted", children: "\u2014" }),
13216
+ /* @__PURE__ */ (0, import_jsx_runtime96.jsx)("td", { className: "is-num", children: bonus.toFixed(1) }),
13217
+ /* @__PURE__ */ (0, import_jsx_runtime96.jsxs)("td", { className: "is-num", children: [
13116
13218
  pct(bonus).toFixed(0),
13117
13219
  "%"
13118
13220
  ] })
13119
13221
  ] }) : null,
13120
- /* @__PURE__ */ (0, import_jsx_runtime94.jsxs)("tr", { style: { background: "var(--surface-2)" }, children: [
13121
- /* @__PURE__ */ (0, import_jsx_runtime94.jsx)("td", { style: { fontWeight: 700 }, children: "Campus total" }),
13122
- /* @__PURE__ */ (0, import_jsx_runtime94.jsx)("td", {}),
13123
- /* @__PURE__ */ (0, import_jsx_runtime94.jsx)("td", { className: "is-num", style: { fontWeight: 700 }, children: money(spendTotal) }),
13124
- /* @__PURE__ */ (0, import_jsx_runtime94.jsx)("td", { className: "is-num", style: { fontWeight: 700 }, children: grand.toFixed(1) }),
13125
- /* @__PURE__ */ (0, import_jsx_runtime94.jsx)("td", { className: "is-num", style: { fontWeight: 700 }, children: "100%" })
13222
+ /* @__PURE__ */ (0, import_jsx_runtime96.jsxs)("tr", { style: { background: "var(--surface-2)" }, children: [
13223
+ /* @__PURE__ */ (0, import_jsx_runtime96.jsx)("td", { style: { fontWeight: 700 }, children: "Campus total" }),
13224
+ /* @__PURE__ */ (0, import_jsx_runtime96.jsx)("td", {}),
13225
+ /* @__PURE__ */ (0, import_jsx_runtime96.jsx)("td", { className: "is-num", style: { fontWeight: 700 }, children: money(spendTotal) }),
13226
+ /* @__PURE__ */ (0, import_jsx_runtime96.jsx)("td", { className: "is-num", style: { fontWeight: 700 }, children: grand.toFixed(1) }),
13227
+ /* @__PURE__ */ (0, import_jsx_runtime96.jsx)("td", { className: "is-num", style: { fontWeight: 700 }, children: "100%" })
13126
13228
  ] })
13127
13229
  ] })
13128
13230
  ] }) : null
@@ -13130,8 +13232,8 @@ function ChannelContribution({
13130
13232
  }
13131
13233
 
13132
13234
  // src/components/planner/BudgetReallocator.tsx
13133
- var React67 = __toESM(require("react"), 1);
13134
- var import_jsx_runtime95 = require("react/jsx-runtime");
13235
+ var React68 = __toESM(require("react"), 1);
13236
+ var import_jsx_runtime97 = require("react/jsx-runtime");
13135
13237
  var bandFor = (crp) => crp >= 200 ? "dominant" : crp >= 100 ? "strong" : crp >= 50 ? "adequate" : "weak";
13136
13238
  function BudgetReallocator({
13137
13239
  campus,
@@ -13146,8 +13248,8 @@ function BudgetReallocator({
13146
13248
  onCancel,
13147
13249
  className = ""
13148
13250
  }) {
13149
- const [draft, setDraft] = React67.useState(spend);
13150
- React67.useEffect(() => setDraft(spend), [spend]);
13251
+ const [draft, setDraft] = React68.useState(spend);
13252
+ React68.useEffect(() => setDraft(spend), [spend]);
13151
13253
  const dirty = draft !== spend;
13152
13254
  const nextCrp = scoreFor ? scoreFor(draft) : crp;
13153
13255
  const nextBand = bandFor(nextCrp);
@@ -13162,10 +13264,10 @@ function BudgetReallocator({
13162
13264
  setDraft(spend);
13163
13265
  if (onCancel) onCancel();
13164
13266
  };
13165
- const trackRef = React67.useRef(null);
13166
- const chipRef = React67.useRef(null);
13167
- const [chipLeft, setChipLeft] = React67.useState(null);
13168
- React67.useLayoutEffect(() => {
13267
+ const trackRef = React68.useRef(null);
13268
+ const chipRef = React68.useRef(null);
13269
+ const [chipLeft, setChipLeft] = React68.useState(null);
13270
+ React68.useLayoutEffect(() => {
13169
13271
  const track = trackRef.current;
13170
13272
  if (!dirty || !track) {
13171
13273
  setChipLeft(null);
@@ -13186,23 +13288,23 @@ function BudgetReallocator({
13186
13288
  ro.observe(track);
13187
13289
  return () => ro.disconnect();
13188
13290
  }, [dirty, pct]);
13189
- return /* @__PURE__ */ (0, import_jsx_runtime95.jsxs)(
13291
+ return /* @__PURE__ */ (0, import_jsx_runtime97.jsxs)(
13190
13292
  "div",
13191
13293
  {
13192
13294
  className: ["fd-stack", className].filter(Boolean).join(" "),
13193
13295
  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)" },
13194
13296
  children: [
13195
- /* @__PURE__ */ (0, import_jsx_runtime95.jsxs)("div", { className: "fd-row", style: { gap: 12, flexWrap: "wrap" }, children: [
13196
- /* @__PURE__ */ (0, import_jsx_runtime95.jsx)("span", { className: "fd-h4", style: { flex: 1, minWidth: 140 }, children: campus }),
13197
- /* @__PURE__ */ (0, import_jsx_runtime95.jsx)(CsiBadge, { band: nowBand, crp, size: "medium" }),
13198
- dirty ? /* @__PURE__ */ (0, import_jsx_runtime95.jsxs)(import_jsx_runtime95.Fragment, { children: [
13199
- /* @__PURE__ */ (0, import_jsx_runtime95.jsx)("i", { className: "ph ph-arrow-right fd-muted", "aria-hidden": "true" }),
13200
- /* @__PURE__ */ (0, import_jsx_runtime95.jsx)(CsiBadge, { band: nextBand, crp: nextCrp, size: "medium", preview: true })
13297
+ /* @__PURE__ */ (0, import_jsx_runtime97.jsxs)("div", { className: "fd-row", style: { gap: 12, flexWrap: "wrap" }, children: [
13298
+ /* @__PURE__ */ (0, import_jsx_runtime97.jsx)("span", { className: "fd-h4", style: { flex: 1, minWidth: 140 }, children: campus }),
13299
+ /* @__PURE__ */ (0, import_jsx_runtime97.jsx)(CsiBadge, { band: nowBand, crp, size: "medium" }),
13300
+ dirty ? /* @__PURE__ */ (0, import_jsx_runtime97.jsxs)(import_jsx_runtime97.Fragment, { children: [
13301
+ /* @__PURE__ */ (0, import_jsx_runtime97.jsx)("i", { className: "ph ph-arrow-right fd-muted", "aria-hidden": "true" }),
13302
+ /* @__PURE__ */ (0, import_jsx_runtime97.jsx)(CsiBadge, { band: nextBand, crp: nextCrp, size: "medium", preview: true })
13201
13303
  ] }) : null
13202
13304
  ] }),
13203
- /* @__PURE__ */ (0, import_jsx_runtime95.jsxs)("div", { className: "fd-slider", ref: trackRef, children: [
13204
- /* @__PURE__ */ (0, import_jsx_runtime95.jsx)("span", { className: "fd-slider-fill", style: { width: pct + "%" } }),
13205
- dirty ? /* @__PURE__ */ (0, import_jsx_runtime95.jsx)(
13305
+ /* @__PURE__ */ (0, import_jsx_runtime97.jsxs)("div", { className: "fd-slider", ref: trackRef, children: [
13306
+ /* @__PURE__ */ (0, import_jsx_runtime97.jsx)("span", { className: "fd-slider-fill", style: { width: pct + "%" } }),
13307
+ dirty ? /* @__PURE__ */ (0, import_jsx_runtime97.jsx)(
13206
13308
  "span",
13207
13309
  {
13208
13310
  ref: chipRef,
@@ -13214,7 +13316,7 @@ function BudgetReallocator({
13214
13316
  children: (delta < 0 ? "\u2212$" : "+$") + Math.abs(delta).toLocaleString()
13215
13317
  }
13216
13318
  ) : null,
13217
- /* @__PURE__ */ (0, import_jsx_runtime95.jsx)(
13319
+ /* @__PURE__ */ (0, import_jsx_runtime97.jsx)(
13218
13320
  "input",
13219
13321
  {
13220
13322
  type: "range",
@@ -13230,13 +13332,13 @@ function BudgetReallocator({
13230
13332
  }
13231
13333
  )
13232
13334
  ] }),
13233
- /* @__PURE__ */ (0, import_jsx_runtime95.jsxs)("div", { className: "fd-row", style: { gap: 12, flexWrap: "wrap" }, children: [
13234
- /* @__PURE__ */ (0, import_jsx_runtime95.jsxs)("span", { className: "fd-stack", style: { gap: 2, flex: 1, minWidth: 150 }, children: [
13235
- /* @__PURE__ */ (0, import_jsx_runtime95.jsx)("span", { className: "fd-num", style: { fontSize: 19, fontWeight: 700 }, children: "$" + draft.toLocaleString() }),
13236
- /* @__PURE__ */ (0, import_jsx_runtime95.jsx)("span", { className: "fd-body-sm fd-muted", children: "Arrow keys step $100, shift+arrow $1,000. Escape reverts." })
13335
+ /* @__PURE__ */ (0, import_jsx_runtime97.jsxs)("div", { className: "fd-row", style: { gap: 12, flexWrap: "wrap" }, children: [
13336
+ /* @__PURE__ */ (0, import_jsx_runtime97.jsxs)("span", { className: "fd-stack", style: { gap: 2, flex: 1, minWidth: 150 }, children: [
13337
+ /* @__PURE__ */ (0, import_jsx_runtime97.jsx)("span", { className: "fd-num", style: { fontSize: 19, fontWeight: 700 }, children: "$" + draft.toLocaleString() }),
13338
+ /* @__PURE__ */ (0, import_jsx_runtime97.jsx)("span", { className: "fd-body-sm fd-muted", children: "Arrow keys step $100, shift+arrow $1,000. Escape reverts." })
13237
13339
  ] }),
13238
- /* @__PURE__ */ (0, import_jsx_runtime95.jsx)("button", { type: "button", className: "fd-btn fd-btn-ghost", disabled: !dirty, onClick: revert, children: "Cancel" }),
13239
- /* @__PURE__ */ (0, import_jsx_runtime95.jsx)(
13340
+ /* @__PURE__ */ (0, import_jsx_runtime97.jsx)("button", { type: "button", className: "fd-btn fd-btn-ghost", disabled: !dirty, onClick: revert, children: "Cancel" }),
13341
+ /* @__PURE__ */ (0, import_jsx_runtime97.jsx)(
13240
13342
  "button",
13241
13343
  {
13242
13344
  type: "button",
@@ -13255,7 +13357,7 @@ function BudgetReallocator({
13255
13357
  }
13256
13358
 
13257
13359
  // src/components/planner/SurroundSound.tsx
13258
- var import_jsx_runtime96 = require("react/jsx-runtime");
13360
+ var import_jsx_runtime98 = require("react/jsx-runtime");
13259
13361
  var CATEGORIES = [
13260
13362
  { key: "ooh", label: "OOH", icon: "flag-banner", color: "var(--ch-ooh)" },
13261
13363
  { key: "transit", label: "Transit", icon: "bus", color: "var(--ch-transit)" },
@@ -13267,26 +13369,26 @@ var CATEGORIES = [
13267
13369
  function SurroundSound({ present = [], bonusPct = 0, bonusMax = 40, missedCost, className = "" }) {
13268
13370
  const earned = Math.max(0, Math.min(1, bonusPct / bonusMax));
13269
13371
  const single = present.length <= 2;
13270
- return /* @__PURE__ */ (0, import_jsx_runtime96.jsxs)("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 14 }, children: [
13271
- /* @__PURE__ */ (0, import_jsx_runtime96.jsx)("div", { className: "fd-row", style: { gap: 8, flexWrap: "wrap" }, children: CATEGORIES.map((c) => {
13372
+ return /* @__PURE__ */ (0, import_jsx_runtime98.jsxs)("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 14 }, children: [
13373
+ /* @__PURE__ */ (0, import_jsx_runtime98.jsx)("div", { className: "fd-row", style: { gap: 8, flexWrap: "wrap" }, children: CATEGORIES.map((c) => {
13272
13374
  const on = present.includes(c.key);
13273
- return /* @__PURE__ */ (0, import_jsx_runtime96.jsxs)(
13375
+ return /* @__PURE__ */ (0, import_jsx_runtime98.jsxs)(
13274
13376
  "span",
13275
13377
  {
13276
13378
  title: c.label + (on ? " \u2014 present" : " \u2014 not bought"),
13277
13379
  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)" },
13278
13380
  children: [
13279
- /* @__PURE__ */ (0, import_jsx_runtime96.jsx)("i", { className: "ph ph-" + c.icon, style: { fontSize: 19, color: on ? c.color : "var(--text-muted)" }, "aria-hidden": "true" }),
13280
- /* @__PURE__ */ (0, import_jsx_runtime96.jsx)("span", { style: { fontSize: 10.5, fontWeight: 700 }, children: c.label })
13381
+ /* @__PURE__ */ (0, import_jsx_runtime98.jsx)("i", { className: "ph ph-" + c.icon, style: { fontSize: 19, color: on ? c.color : "var(--text-muted)" }, "aria-hidden": "true" }),
13382
+ /* @__PURE__ */ (0, import_jsx_runtime98.jsx)("span", { style: { fontSize: 10.5, fontWeight: 700 }, children: c.label })
13281
13383
  ]
13282
13384
  },
13283
13385
  c.key
13284
13386
  );
13285
13387
  }) }),
13286
- /* @__PURE__ */ (0, import_jsx_runtime96.jsxs)("div", { className: "fd-stack", style: { gap: 8 }, children: [
13287
- /* @__PURE__ */ (0, import_jsx_runtime96.jsxs)("div", { className: "fd-row", style: { justifyContent: "space-between", gap: 12 }, children: [
13288
- /* @__PURE__ */ (0, import_jsx_runtime96.jsx)("span", { className: "fd-label-lg", children: "Surround-sound bonus earned" }),
13289
- /* @__PURE__ */ (0, import_jsx_runtime96.jsxs)("span", { className: "fd-num", style: { color: single ? "var(--warn-text)" : "var(--csi-3-mark)", fontWeight: 700 }, children: [
13388
+ /* @__PURE__ */ (0, import_jsx_runtime98.jsxs)("div", { className: "fd-stack", style: { gap: 8 }, children: [
13389
+ /* @__PURE__ */ (0, import_jsx_runtime98.jsxs)("div", { className: "fd-row", style: { justifyContent: "space-between", gap: 12 }, children: [
13390
+ /* @__PURE__ */ (0, import_jsx_runtime98.jsx)("span", { className: "fd-label-lg", children: "Surround-sound bonus earned" }),
13391
+ /* @__PURE__ */ (0, import_jsx_runtime98.jsxs)("span", { className: "fd-num", style: { color: single ? "var(--warn-text)" : "var(--csi-3-mark)", fontWeight: 700 }, children: [
13290
13392
  "+",
13291
13393
  bonusPct,
13292
13394
  "% of +",
@@ -13294,8 +13396,8 @@ function SurroundSound({ present = [], bonusPct = 0, bonusMax = 40, missedCost,
13294
13396
  "%"
13295
13397
  ] })
13296
13398
  ] }),
13297
- /* @__PURE__ */ (0, import_jsx_runtime96.jsx)("div", { style: { height: 8, borderRadius: "var(--r-xs)", background: "var(--surface-3)", overflow: "hidden" }, children: /* @__PURE__ */ (0, import_jsx_runtime96.jsx)("div", { style: { height: "100%", width: earned * 100 + "%", background: "var(--csi-3-mark)", borderRadius: "inherit", transition: "width var(--dur-slow) var(--ease)" } }) }),
13298
- /* @__PURE__ */ (0, import_jsx_runtime96.jsxs)("span", { className: "fd-body-sm fd-secondary", style: { textWrap: "pretty" }, children: [
13399
+ /* @__PURE__ */ (0, import_jsx_runtime98.jsx)("div", { style: { height: 8, borderRadius: "var(--r-xs)", background: "var(--surface-3)", overflow: "hidden" }, children: /* @__PURE__ */ (0, import_jsx_runtime98.jsx)("div", { style: { height: "100%", width: earned * 100 + "%", background: "var(--csi-3-mark)", borderRadius: "inherit", transition: "width var(--dur-slow) var(--ease)" } }) }),
13400
+ /* @__PURE__ */ (0, import_jsx_runtime98.jsxs)("span", { className: "fd-body-sm fd-secondary", style: { textWrap: "pretty" }, children: [
13299
13401
  present.length,
13300
13402
  " of 6 channel categories present.",
13301
13403
  " ",
@@ -13307,7 +13409,7 @@ function SurroundSound({ present = [], bonusPct = 0, bonusMax = 40, missedCost,
13307
13409
  }
13308
13410
 
13309
13411
  // src/components/planner/Importance.tsx
13310
- var import_jsx_runtime97 = require("react/jsx-runtime");
13412
+ var import_jsx_runtime99 = require("react/jsx-runtime");
13311
13413
  var IMPORTANCE_LEVELS = [
13312
13414
  { id: "nudge", rank: 1, label: "Nudge", icon: "feather", description: "Breaks a tie, nothing more." },
13313
13415
  { id: "lean", rank: 2, label: "Lean", icon: "arrow-bend-up-right", description: "A mild preference between otherwise equal options." },
@@ -13337,7 +13439,7 @@ function importanceTokens(id) {
13337
13439
  function ImportanceTag({ level, showLabel = true, size = "sm", className = "", disabled = false }) {
13338
13440
  const lvl = importanceLevel(level);
13339
13441
  const t = importanceTokens(level);
13340
- return /* @__PURE__ */ (0, import_jsx_runtime97.jsxs)(
13442
+ return /* @__PURE__ */ (0, import_jsx_runtime99.jsxs)(
13341
13443
  "span",
13342
13444
  {
13343
13445
  className: ["fd-imp-tag", size === "md" ? "is-md" : "", disabled ? "is-disabled" : "", className].filter(Boolean).join(" "),
@@ -13345,16 +13447,16 @@ function ImportanceTag({ level, showLabel = true, size = "sm", className = "", d
13345
13447
  title: lvl.label + " \u2014 " + lvl.description,
13346
13448
  "aria-disabled": disabled ? "true" : void 0,
13347
13449
  children: [
13348
- /* @__PURE__ */ (0, import_jsx_runtime97.jsx)("i", { className: "ph ph-" + lvl.icon, "aria-hidden": "true" }),
13349
- showLabel ? lvl.label : /* @__PURE__ */ (0, import_jsx_runtime97.jsx)("span", { className: "fd-sr", children: lvl.label })
13450
+ /* @__PURE__ */ (0, import_jsx_runtime99.jsx)("i", { className: "ph ph-" + lvl.icon, "aria-hidden": "true" }),
13451
+ showLabel ? lvl.label : /* @__PURE__ */ (0, import_jsx_runtime99.jsx)("span", { className: "fd-sr", children: lvl.label })
13350
13452
  ]
13351
13453
  }
13352
13454
  );
13353
13455
  }
13354
13456
 
13355
13457
  // src/components/planner/PreferenceMeter.tsx
13356
- var React68 = __toESM(require("react"), 1);
13357
- var import_jsx_runtime98 = require("react/jsx-runtime");
13458
+ var React69 = __toESM(require("react"), 1);
13459
+ var import_jsx_runtime100 = require("react/jsx-runtime");
13358
13460
  function preferenceScore(criteria) {
13359
13461
  const earned = criteria.reduce((n, c) => n + (Number(c.earned) || 0), 0);
13360
13462
  const weight = criteria.reduce((n, c) => n + (Number(c.weight) || 0), 0);
@@ -13383,8 +13485,8 @@ function PreferenceMeter({
13383
13485
  className = ""
13384
13486
  }) {
13385
13487
  const value = score == null ? preferenceScore(criteria) : score;
13386
- const segments = React68.useMemo(() => preferenceSegments(criteria), [criteria]);
13387
- return /* @__PURE__ */ (0, import_jsx_runtime98.jsx)(
13488
+ const segments = React69.useMemo(() => preferenceSegments(criteria), [criteria]);
13489
+ return /* @__PURE__ */ (0, import_jsx_runtime100.jsx)(
13388
13490
  ScoreMeter,
13389
13491
  {
13390
13492
  score: value,
@@ -13396,22 +13498,22 @@ function PreferenceMeter({
13396
13498
  placement,
13397
13499
  className,
13398
13500
  breakdownLabel: breakdownTitle,
13399
- breakdown: /* @__PURE__ */ (0, import_jsx_runtime98.jsxs)("div", { className: "fd-prefbreak", children: [
13400
- /* @__PURE__ */ (0, import_jsx_runtime98.jsxs)("div", { className: "fd-prefbreak-head", children: [
13401
- /* @__PURE__ */ (0, import_jsx_runtime98.jsx)("span", { className: "fd-label-lg", children: breakdownTitle }),
13402
- /* @__PURE__ */ (0, import_jsx_runtime98.jsx)("span", { className: "fd-prefbreak-score fd-tabular", children: Math.round(value) })
13501
+ breakdown: /* @__PURE__ */ (0, import_jsx_runtime100.jsxs)("div", { className: "fd-prefbreak", children: [
13502
+ /* @__PURE__ */ (0, import_jsx_runtime100.jsxs)("div", { className: "fd-prefbreak-head", children: [
13503
+ /* @__PURE__ */ (0, import_jsx_runtime100.jsx)("span", { className: "fd-label-lg", children: breakdownTitle }),
13504
+ /* @__PURE__ */ (0, import_jsx_runtime100.jsx)("span", { className: "fd-prefbreak-score fd-tabular", children: Math.round(value) })
13403
13505
  ] }),
13404
- /* @__PURE__ */ (0, import_jsx_runtime98.jsx)("ul", { className: "fd-prefbreak-list", children: criteria.map((c) => {
13506
+ /* @__PURE__ */ (0, import_jsx_runtime100.jsx)("ul", { className: "fd-prefbreak-list", children: criteria.map((c) => {
13405
13507
  const pct = c.weight > 0 ? Math.round((Number(c.earned) || 0) / c.weight * 100) : 0;
13406
- return /* @__PURE__ */ (0, import_jsx_runtime98.jsxs)("li", { className: pct === 0 ? "fd-prefbreak-item is-unmet" : "fd-prefbreak-item", children: [
13407
- /* @__PURE__ */ (0, import_jsx_runtime98.jsx)(ImportanceTag, { level: c.importance }),
13408
- /* @__PURE__ */ (0, import_jsx_runtime98.jsxs)("span", { className: "fd-prefbreak-text", children: [
13409
- /* @__PURE__ */ (0, import_jsx_runtime98.jsx)("span", { className: "fd-prefbreak-label", children: c.label }),
13410
- c.note ? /* @__PURE__ */ (0, import_jsx_runtime98.jsx)("span", { className: "fd-prefbreak-note", children: c.note }) : null
13508
+ return /* @__PURE__ */ (0, import_jsx_runtime100.jsxs)("li", { className: pct === 0 ? "fd-prefbreak-item is-unmet" : "fd-prefbreak-item", children: [
13509
+ /* @__PURE__ */ (0, import_jsx_runtime100.jsx)(ImportanceTag, { level: c.importance }),
13510
+ /* @__PURE__ */ (0, import_jsx_runtime100.jsxs)("span", { className: "fd-prefbreak-text", children: [
13511
+ /* @__PURE__ */ (0, import_jsx_runtime100.jsx)("span", { className: "fd-prefbreak-label", children: c.label }),
13512
+ c.note ? /* @__PURE__ */ (0, import_jsx_runtime100.jsx)("span", { className: "fd-prefbreak-note", children: c.note }) : null
13411
13513
  ] }),
13412
- /* @__PURE__ */ (0, import_jsx_runtime98.jsxs)("span", { className: "fd-prefbreak-val fd-tabular", children: [
13514
+ /* @__PURE__ */ (0, import_jsx_runtime100.jsxs)("span", { className: "fd-prefbreak-val fd-tabular", children: [
13413
13515
  Math.round(Number(c.earned) || 0),
13414
- /* @__PURE__ */ (0, import_jsx_runtime98.jsx)("span", { className: "fd-prefbreak-sep", children: "/" }),
13516
+ /* @__PURE__ */ (0, import_jsx_runtime100.jsx)("span", { className: "fd-prefbreak-sep", children: "/" }),
13415
13517
  Math.round(c.weight)
13416
13518
  ] })
13417
13519
  ] }, c.id);
@@ -13422,10 +13524,10 @@ function PreferenceMeter({
13422
13524
  }
13423
13525
 
13424
13526
  // src/components/chat/AgentChatPanel.tsx
13425
- var React74 = __toESM(require("react"), 1);
13527
+ var React75 = __toESM(require("react"), 1);
13426
13528
 
13427
13529
  // src/components/chat/chatEngine.ts
13428
- var React69 = __toESM(require("react"), 1);
13530
+ var React70 = __toESM(require("react"), 1);
13429
13531
  var CHAT_UNAVAILABLE = "chat_unavailable";
13430
13532
  var JOB_PENDING = ["queued", "running"];
13431
13533
  var JOB_SUCCESS = ["completed", "recovered"];
@@ -13470,7 +13572,7 @@ function useChatEngine(opts) {
13470
13572
  initialMessage,
13471
13573
  threadId: threadIdProp,
13472
13574
  pollIntervalMs = 1500,
13473
- pollMaxAttempts = 120,
13575
+ pendingTimeoutMs = 18e4,
13474
13576
  store = safeStore,
13475
13577
  onPacket,
13476
13578
  onThreadReady,
@@ -13479,22 +13581,22 @@ function useChatEngine(opts) {
13479
13581
  onClear,
13480
13582
  onFeedback
13481
13583
  } = opts || {};
13482
- const [status, setStatus] = React69.useState("idle");
13483
- const [threadId, setThreadId] = React69.useState(null);
13484
- const [messages, setMessages] = React69.useState([]);
13485
- const [queue, setQueue] = React69.useState([]);
13486
- const [fatal, setFatal] = React69.useState(null);
13487
- const [busy, setBusy] = React69.useState(false);
13488
- const [turnStartedAt, setTurnStartedAt] = React69.useState(null);
13489
- const listRef = React69.useRef([]);
13490
- const queueRef = React69.useRef([]);
13491
- const busyRef = React69.useRef(false);
13492
- const stoppedRef = React69.useRef(false);
13493
- const abortRef = React69.useRef(null);
13494
- const serverCount = React69.useRef(0);
13495
- const threadRef = React69.useRef(null);
13496
- const mounted = React69.useRef(true);
13497
- React69.useEffect(() => {
13584
+ const [status, setStatus] = React70.useState("idle");
13585
+ const [threadId, setThreadId] = React70.useState(null);
13586
+ const [messages, setMessages] = React70.useState([]);
13587
+ const [queue, setQueue] = React70.useState([]);
13588
+ const [fatal, setFatal] = React70.useState(null);
13589
+ const [busy, setBusy] = React70.useState(false);
13590
+ const [turnStartedAt, setTurnStartedAt] = React70.useState(null);
13591
+ const listRef = React70.useRef([]);
13592
+ const queueRef = React70.useRef([]);
13593
+ const busyRef = React70.useRef(false);
13594
+ const stoppedRef = React70.useRef(false);
13595
+ const abortRef = React70.useRef(null);
13596
+ const serverCount = React70.useRef(0);
13597
+ const threadRef = React70.useRef(null);
13598
+ const mounted = React70.useRef(true);
13599
+ React70.useEffect(() => {
13498
13600
  mounted.current = true;
13499
13601
  return () => {
13500
13602
  mounted.current = false;
@@ -13516,14 +13618,21 @@ function useChatEngine(opts) {
13516
13618
  }
13517
13619
  return false;
13518
13620
  };
13519
- const loadThread = React69.useCallback(async (id) => {
13621
+ const loadThread = React70.useCallback(async (id) => {
13520
13622
  const data = await apiAdapter.getThread(id);
13521
13623
  const list = [...data && data.messages || []];
13522
13624
  serverCount.current = list.length;
13523
13625
  commit(list);
13524
13626
  return list;
13525
13627
  }, [apiAdapter]);
13526
- React69.useEffect(() => {
13628
+ async function mergeThread() {
13629
+ const data = await apiAdapter.getThread(threadRef.current);
13630
+ const server = data && data.messages || [];
13631
+ const ids = new Set(server.map((m) => m.id));
13632
+ serverCount.current = server.length;
13633
+ commit([...server, ...listRef.current.filter((m) => !ids.has(m.id))]);
13634
+ }
13635
+ React70.useEffect(() => {
13527
13636
  if (!apiAdapter) {
13528
13637
  setStatus("idle");
13529
13638
  setFatal(null);
@@ -13569,7 +13678,9 @@ function useChatEngine(opts) {
13569
13678
  setStatus("ready");
13570
13679
  onThreadReady && onThreadReady(id);
13571
13680
  const stored = store.get(STORAGE_PREFIX + id);
13681
+ const last = [...visibleMessages(listRef.current)].reverse().find((m) => m.role === "assistant");
13572
13682
  if (stored) resumeJob(stored);
13683
+ else if (last && last.working && last.jobId) resumeJob(last.jobId, last.id);
13573
13684
  else if (initialMessage) send(initialMessage);
13574
13685
  } catch (err) {
13575
13686
  if (dead) return;
@@ -13585,8 +13696,8 @@ function useChatEngine(opts) {
13585
13696
  }, [apiAdapter, contextType, contextId, threadIdProp]);
13586
13697
  async function pollJob(jobId, placeholderId) {
13587
13698
  store.set(STORAGE_PREFIX + threadRef.current, jobId);
13588
- let attempts = 0;
13589
- while (attempts++ < pollMaxAttempts) {
13699
+ const deadline = Date.now() + pendingTimeoutMs;
13700
+ while (true) {
13590
13701
  if (stoppedRef.current) break;
13591
13702
  await sleep(pollIntervalMs);
13592
13703
  if (!mounted.current) return;
@@ -13604,7 +13715,15 @@ function useChatEngine(opts) {
13604
13715
  }
13605
13716
  patch(placeholderId, { job });
13606
13717
  const bucket2 = jobBucket(job && job.status);
13607
- if (bucket2 === "pending") continue;
13718
+ if (bucket2 === "pending") {
13719
+ try {
13720
+ await mergeThread();
13721
+ } catch (err) {
13722
+ fail(err);
13723
+ }
13724
+ if (Date.now() >= deadline) break;
13725
+ continue;
13726
+ }
13608
13727
  if (bucket2 === "success") {
13609
13728
  finishJob(jobId, job);
13610
13729
  return;
@@ -13641,9 +13760,10 @@ function useChatEngine(opts) {
13641
13760
  patch(placeholderId, { working: false, streaming: false, error: code, retryable: !!retryable, job: job || void 0 });
13642
13761
  onError && onError(new Error(code));
13643
13762
  }
13644
- function resumeJob(jobId) {
13645
- const id = uid("a");
13646
- push({ id, role: "assistant", working: true, jobId, resumed: true });
13763
+ function resumeJob(jobId, existingId) {
13764
+ const id = existingId || uid("a");
13765
+ if (existingId) patch(id, { working: true, resumed: true });
13766
+ else push({ id, role: "assistant", working: true, jobId, resumed: true });
13647
13767
  setBusy(true);
13648
13768
  busyRef.current = true;
13649
13769
  setTurnStartedAt(Date.now());
@@ -13736,7 +13856,7 @@ function useChatEngine(opts) {
13736
13856
  await dispatchTurn(turn);
13737
13857
  }
13738
13858
  }
13739
- const send = React69.useCallback((text, attachments) => {
13859
+ const send = React70.useCallback((text, attachments) => {
13740
13860
  const body = (text || "").trim();
13741
13861
  if (!body && !(attachments && attachments.length)) return;
13742
13862
  if (status === "disconnected") return;
@@ -13746,7 +13866,7 @@ function useChatEngine(opts) {
13746
13866
  stoppedRef.current = false;
13747
13867
  drain();
13748
13868
  }, [status]);
13749
- const stop = React69.useCallback(() => {
13869
+ const stop = React70.useCallback(() => {
13750
13870
  stoppedRef.current = true;
13751
13871
  const ac = abortRef.current;
13752
13872
  if (ac) {
@@ -13765,11 +13885,11 @@ function useChatEngine(opts) {
13765
13885
  store.del(STORAGE_PREFIX + threadRef.current);
13766
13886
  }
13767
13887
  }, [apiAdapter]);
13768
- const removeQueued = React69.useCallback((id) => {
13888
+ const removeQueued = React70.useCallback((id) => {
13769
13889
  queueRef.current = queueRef.current.filter((t) => t.id !== id);
13770
13890
  setQueue(queueRef.current.slice());
13771
13891
  }, []);
13772
- const retry = React69.useCallback(() => {
13892
+ const retry = React70.useCallback(() => {
13773
13893
  const list = listRef.current;
13774
13894
  let at = -1;
13775
13895
  for (let i = list.length - 1; i >= 0; i--) if (list[i].role === "user") {
@@ -13785,19 +13905,19 @@ function useChatEngine(opts) {
13785
13905
  setQueue(queueRef.current.slice());
13786
13906
  drain();
13787
13907
  }, []);
13788
- const clear = React69.useCallback(() => {
13908
+ const clear = React70.useCallback(() => {
13789
13909
  commit([]);
13790
13910
  serverCount.current = 0;
13791
13911
  queueRef.current = [];
13792
13912
  setQueue([]);
13793
13913
  onClear && onClear();
13794
13914
  }, [onClear]);
13795
- const setFeedback = React69.useCallback((id, value) => {
13915
+ const setFeedback = React70.useCallback((id, value) => {
13796
13916
  patch(id, (m) => ({ feedback: m.feedback === value ? null : value }));
13797
13917
  const msg = listRef.current.find((m) => m.id === id);
13798
13918
  onFeedback && onFeedback({ message: msg, feedback: msg ? msg.feedback : value });
13799
13919
  }, [onFeedback]);
13800
- const reload = React69.useCallback(async () => {
13920
+ const reload = React70.useCallback(async () => {
13801
13921
  if (!threadRef.current) return;
13802
13922
  setStatus("loading");
13803
13923
  try {
@@ -13835,11 +13955,11 @@ var ChatKit = {
13835
13955
  };
13836
13956
 
13837
13957
  // src/components/chat/ChatTranscript.tsx
13838
- var React71 = __toESM(require("react"), 1);
13958
+ var React72 = __toESM(require("react"), 1);
13839
13959
 
13840
13960
  // src/components/chat/ChatTurn.tsx
13841
- var React70 = __toESM(require("react"), 1);
13842
- var import_jsx_runtime99 = require("react/jsx-runtime");
13961
+ var React71 = __toESM(require("react"), 1);
13962
+ var import_jsx_runtime101 = require("react/jsx-runtime");
13843
13963
  function JsonView({ value }) {
13844
13964
  let text;
13845
13965
  try {
@@ -13847,67 +13967,67 @@ function JsonView({ value }) {
13847
13967
  } catch (e) {
13848
13968
  text = String(value);
13849
13969
  }
13850
- return /* @__PURE__ */ (0, import_jsx_runtime99.jsx)(CodeBlock, { code: text, language: "json", collapseAfter: 18 });
13970
+ return /* @__PURE__ */ (0, import_jsx_runtime101.jsx)(CodeBlock, { code: text, language: "json", collapseAfter: 18 });
13851
13971
  }
13852
13972
  function PacketCard({ packet, schema, render, onApply, applied }) {
13853
13973
  if (!packet) return null;
13854
13974
  const s = schema || {};
13855
13975
  const invalid = packet.valid === false;
13856
13976
  const title = s.heading || packet.type;
13857
- return /* @__PURE__ */ (0, import_jsx_runtime99.jsxs)("section", { className: "fdc-packet" + (invalid ? " is-invalid" : ""), "aria-label": title, children: [
13858
- /* @__PURE__ */ (0, import_jsx_runtime99.jsxs)("header", { className: "fdc-packet-head", children: [
13859
- /* @__PURE__ */ (0, import_jsx_runtime99.jsx)("i", { className: "ph ph-" + (s.icon || "package"), "aria-hidden": "true" }),
13860
- /* @__PURE__ */ (0, import_jsx_runtime99.jsx)("span", { className: "fdc-packet-title", title: truncationTitle(title), children: title }),
13861
- packet.repaired ? /* @__PURE__ */ (0, import_jsx_runtime99.jsx)("span", { className: "fdc-packet-badge", children: "Repaired" }) : null,
13862
- invalid ? /* @__PURE__ */ (0, import_jsx_runtime99.jsx)("span", { className: "fdc-packet-badge is-danger", children: "Invalid" }) : null
13977
+ return /* @__PURE__ */ (0, import_jsx_runtime101.jsxs)("section", { className: "fdc-packet" + (invalid ? " is-invalid" : ""), "aria-label": title, children: [
13978
+ /* @__PURE__ */ (0, import_jsx_runtime101.jsxs)("header", { className: "fdc-packet-head", children: [
13979
+ /* @__PURE__ */ (0, import_jsx_runtime101.jsx)("i", { className: "ph ph-" + (s.icon || "package"), "aria-hidden": "true" }),
13980
+ /* @__PURE__ */ (0, import_jsx_runtime101.jsx)("span", { className: "fdc-packet-title", title: truncationTitle(title), children: title }),
13981
+ packet.repaired ? /* @__PURE__ */ (0, import_jsx_runtime101.jsx)("span", { className: "fdc-packet-badge", children: "Repaired" }) : null,
13982
+ invalid ? /* @__PURE__ */ (0, import_jsx_runtime101.jsx)("span", { className: "fdc-packet-badge is-danger", children: "Invalid" }) : null
13863
13983
  ] }),
13864
- invalid ? /* @__PURE__ */ (0, import_jsx_runtime99.jsxs)("div", { className: "fdc-packet-alert", role: "alert", children: [
13865
- /* @__PURE__ */ (0, import_jsx_runtime99.jsx)("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
13866
- /* @__PURE__ */ (0, import_jsx_runtime99.jsx)("span", { children: packet.error || "This result failed validation and can\u2019t be applied." })
13867
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime99.jsx)("div", { className: "fdc-packet-body", children: render ? render(packet) : /* @__PURE__ */ (0, import_jsx_runtime99.jsx)(JsonView, { value: packet.payload }) }),
13868
- !invalid && onApply ? /* @__PURE__ */ (0, import_jsx_runtime99.jsxs)("footer", { className: "fdc-packet-foot", children: [
13869
- packet.repaired ? /* @__PURE__ */ (0, import_jsx_runtime99.jsx)("span", { className: "fdc-packet-note", children: "Corrected by the backend after a first attempt." }) : /* @__PURE__ */ (0, import_jsx_runtime99.jsx)("span", {}),
13870
- /* @__PURE__ */ (0, import_jsx_runtime99.jsxs)("button", { type: "button", className: "fd-btn fd-btn-primary fd-btn-sm", disabled: applied, onClick: () => onApply(packet), children: [
13871
- /* @__PURE__ */ (0, import_jsx_runtime99.jsx)("i", { className: "ph ph-" + (applied ? "check" : "arrow-square-in"), "aria-hidden": "true" }),
13984
+ invalid ? /* @__PURE__ */ (0, import_jsx_runtime101.jsxs)("div", { className: "fdc-packet-alert", role: "alert", children: [
13985
+ /* @__PURE__ */ (0, import_jsx_runtime101.jsx)("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
13986
+ /* @__PURE__ */ (0, import_jsx_runtime101.jsx)("span", { children: packet.error || "This result failed validation and can\u2019t be applied." })
13987
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime101.jsx)("div", { className: "fdc-packet-body", children: render ? render(packet) : /* @__PURE__ */ (0, import_jsx_runtime101.jsx)(JsonView, { value: packet.payload }) }),
13988
+ !invalid && onApply && s.apply !== false ? /* @__PURE__ */ (0, import_jsx_runtime101.jsxs)("footer", { className: "fdc-packet-foot", children: [
13989
+ packet.repaired ? /* @__PURE__ */ (0, import_jsx_runtime101.jsx)("span", { className: "fdc-packet-note", children: "Corrected by the backend after a first attempt." }) : /* @__PURE__ */ (0, import_jsx_runtime101.jsx)("span", {}),
13990
+ /* @__PURE__ */ (0, import_jsx_runtime101.jsxs)("button", { type: "button", className: "fd-btn fd-btn-primary fd-btn-sm", disabled: applied, onClick: () => onApply(packet), children: [
13991
+ /* @__PURE__ */ (0, import_jsx_runtime101.jsx)("i", { className: "ph ph-" + (applied ? "check" : "arrow-square-in"), "aria-hidden": "true" }),
13872
13992
  applied ? "Applied" : s.applyLabel || "Apply"
13873
13993
  ] })
13874
13994
  ] }) : null
13875
13995
  ] });
13876
13996
  }
13877
13997
  function ThinkingBlock({ text, durationMs, streaming, defaultOpen = false }) {
13878
- const [open2, setOpen] = React70.useState(defaultOpen);
13998
+ const [open2, setOpen] = React71.useState(defaultOpen);
13879
13999
  if (!text) return null;
13880
- return /* @__PURE__ */ (0, import_jsx_runtime99.jsxs)("div", { className: "fdc-think" + (open2 ? " is-open" : ""), children: [
13881
- /* @__PURE__ */ (0, import_jsx_runtime99.jsxs)("button", { type: "button", className: "fdc-think-head", onClick: () => setOpen((v) => !v), "aria-expanded": open2, children: [
13882
- /* @__PURE__ */ (0, import_jsx_runtime99.jsx)("i", { className: "ph ph-brain", "aria-hidden": "true" }),
13883
- /* @__PURE__ */ (0, import_jsx_runtime99.jsx)("span", { children: streaming ? "Thinking" : durationMs ? "Thought for " + formatDuration(durationMs) : "Thought process" }),
13884
- streaming ? /* @__PURE__ */ (0, import_jsx_runtime99.jsxs)("span", { className: "fdc-dots", "aria-hidden": "true", children: [
13885
- /* @__PURE__ */ (0, import_jsx_runtime99.jsx)("span", {}),
13886
- /* @__PURE__ */ (0, import_jsx_runtime99.jsx)("span", {}),
13887
- /* @__PURE__ */ (0, import_jsx_runtime99.jsx)("span", {})
14000
+ return /* @__PURE__ */ (0, import_jsx_runtime101.jsxs)("div", { className: "fdc-think" + (open2 ? " is-open" : ""), children: [
14001
+ /* @__PURE__ */ (0, import_jsx_runtime101.jsxs)("button", { type: "button", className: "fdc-think-head", onClick: () => setOpen((v) => !v), "aria-expanded": open2, children: [
14002
+ /* @__PURE__ */ (0, import_jsx_runtime101.jsx)("i", { className: "ph ph-brain", "aria-hidden": "true" }),
14003
+ /* @__PURE__ */ (0, import_jsx_runtime101.jsx)("span", { children: streaming ? "Thinking" : durationMs ? "Thought for " + formatDuration(durationMs) : "Thought process" }),
14004
+ streaming ? /* @__PURE__ */ (0, import_jsx_runtime101.jsxs)("span", { className: "fdc-dots", "aria-hidden": "true", children: [
14005
+ /* @__PURE__ */ (0, import_jsx_runtime101.jsx)("span", {}),
14006
+ /* @__PURE__ */ (0, import_jsx_runtime101.jsx)("span", {}),
14007
+ /* @__PURE__ */ (0, import_jsx_runtime101.jsx)("span", {})
13888
14008
  ] }) : null,
13889
- /* @__PURE__ */ (0, import_jsx_runtime99.jsx)("i", { className: "ph ph-caret-" + (open2 ? "up" : "down"), "aria-hidden": "true" })
14009
+ /* @__PURE__ */ (0, import_jsx_runtime101.jsx)("i", { className: "ph ph-caret-" + (open2 ? "up" : "down"), "aria-hidden": "true" })
13890
14010
  ] }),
13891
- open2 ? /* @__PURE__ */ (0, import_jsx_runtime99.jsx)("div", { className: "fdc-think-body", children: text }) : null
14011
+ open2 ? /* @__PURE__ */ (0, import_jsx_runtime101.jsx)("div", { className: "fdc-think-body", children: text }) : null
13892
14012
  ] });
13893
14013
  }
13894
14014
  function Citations({ items = [], onOpen }) {
13895
- const [open2, setOpen] = React70.useState(false);
14015
+ const [open2, setOpen] = React71.useState(false);
13896
14016
  if (!items.length) return null;
13897
- return /* @__PURE__ */ (0, import_jsx_runtime99.jsxs)("div", { className: "fdc-cites", children: [
13898
- /* @__PURE__ */ (0, import_jsx_runtime99.jsxs)("button", { type: "button", className: "fdc-cites-head", onClick: () => setOpen((v) => !v), "aria-expanded": open2, children: [
13899
- /* @__PURE__ */ (0, import_jsx_runtime99.jsx)("i", { className: "ph ph-quotes", "aria-hidden": "true" }),
13900
- /* @__PURE__ */ (0, import_jsx_runtime99.jsxs)("span", { children: [
14017
+ return /* @__PURE__ */ (0, import_jsx_runtime101.jsxs)("div", { className: "fdc-cites", children: [
14018
+ /* @__PURE__ */ (0, import_jsx_runtime101.jsxs)("button", { type: "button", className: "fdc-cites-head", onClick: () => setOpen((v) => !v), "aria-expanded": open2, children: [
14019
+ /* @__PURE__ */ (0, import_jsx_runtime101.jsx)("i", { className: "ph ph-quotes", "aria-hidden": "true" }),
14020
+ /* @__PURE__ */ (0, import_jsx_runtime101.jsxs)("span", { children: [
13901
14021
  items.length,
13902
14022
  " source",
13903
14023
  items.length === 1 ? "" : "s"
13904
14024
  ] }),
13905
- /* @__PURE__ */ (0, import_jsx_runtime99.jsx)("i", { className: "ph ph-caret-" + (open2 ? "up" : "down"), "aria-hidden": "true" })
14025
+ /* @__PURE__ */ (0, import_jsx_runtime101.jsx)("i", { className: "ph ph-caret-" + (open2 ? "up" : "down"), "aria-hidden": "true" })
13906
14026
  ] }),
13907
- open2 ? /* @__PURE__ */ (0, import_jsx_runtime99.jsx)("ol", { className: "fdc-cites-list", children: items.map((c, i) => /* @__PURE__ */ (0, import_jsx_runtime99.jsxs)("li", { children: [
13908
- /* @__PURE__ */ (0, import_jsx_runtime99.jsx)("span", { className: "fdc-cite-n fd-tabular", children: c.marker || i + 1 }),
13909
- c.url ? /* @__PURE__ */ (0, import_jsx_runtime99.jsx)("a", { href: c.url, target: "_blank", rel: "noopener noreferrer", onClick: onOpen ? (e) => onOpen(c, e) : void 0, children: c.title || c.url }) : /* @__PURE__ */ (0, import_jsx_runtime99.jsx)("span", { children: c.title || "Source" }),
13910
- c.detail ? /* @__PURE__ */ (0, import_jsx_runtime99.jsx)("span", { className: "fdc-cite-detail", children: c.detail }) : null
14027
+ open2 ? /* @__PURE__ */ (0, import_jsx_runtime101.jsx)("ol", { className: "fdc-cites-list", children: items.map((c, i) => /* @__PURE__ */ (0, import_jsx_runtime101.jsxs)("li", { children: [
14028
+ /* @__PURE__ */ (0, import_jsx_runtime101.jsx)("span", { className: "fdc-cite-n fd-tabular", children: c.marker || i + 1 }),
14029
+ c.url ? /* @__PURE__ */ (0, import_jsx_runtime101.jsx)("a", { href: c.url, target: "_blank", rel: "noopener noreferrer", onClick: onOpen ? (e) => onOpen(c, e) : void 0, children: c.title || c.url }) : /* @__PURE__ */ (0, import_jsx_runtime101.jsx)("span", { children: c.title || "Source" }),
14030
+ c.detail ? /* @__PURE__ */ (0, import_jsx_runtime101.jsx)("span", { className: "fdc-cite-detail", children: c.detail }) : null
13911
14031
  ] }, c.id || i)) }) : null
13912
14032
  ] });
13913
14033
  }
@@ -13918,29 +14038,29 @@ function clampText(text, max) {
13918
14038
  return (at > max * 0.6 ? cut.slice(0, at) : cut).trimEnd() + "\u2026";
13919
14039
  }
13920
14040
  function MessageBody({ message: m, ctx }) {
13921
- const [expanded, setExpanded] = React70.useState(false);
14041
+ const [expanded, setExpanded] = React71.useState(false);
13922
14042
  const isUser = m.role === "user";
13923
14043
  const raw = m.text || "";
13924
14044
  const clamped = !expanded && !m.streaming ? clampText(raw, ctx.maxVisibleChars) : null;
13925
14045
  const body = clamped != null ? clamped : raw;
13926
14046
  const showMd = ctx.markdown && !isUser;
13927
- return /* @__PURE__ */ (0, import_jsx_runtime99.jsxs)("div", { className: "fdc-body", children: [
13928
- m.thinking && ctx.showThinking ? /* @__PURE__ */ (0, import_jsx_runtime99.jsx)(ThinkingBlock, { text: m.thinking, durationMs: m.thinkingMs, streaming: m.streaming && !m.text }) : null,
13929
- m.steps && m.steps.length && ctx.showSteps ? /* @__PURE__ */ (0, import_jsx_runtime99.jsx)(StepList, { steps: m.steps, defaultOpen: m.steps.some((s) => s.status === "running"), dense: true }) : null,
13930
- body ? /* @__PURE__ */ (0, import_jsx_runtime99.jsxs)("div", { className: "fdc-text" + (isUser ? " is-user" : ""), children: [
13931
- showMd ? /* @__PURE__ */ (0, import_jsx_runtime99.jsx)(Markdown, { source: body, headingOffset: 2, codeProps: { collapseAfter: 22 }, renderCitation: ctx.renderCitation }) : /* @__PURE__ */ (0, import_jsx_runtime99.jsx)("div", { className: "fdc-plain", children: body }),
13932
- m.streaming ? /* @__PURE__ */ (0, import_jsx_runtime99.jsx)("span", { className: "fdc-caret", "aria-hidden": "true" }) : null
14047
+ return /* @__PURE__ */ (0, import_jsx_runtime101.jsxs)("div", { className: "fdc-body", children: [
14048
+ m.thinking && ctx.showThinking ? /* @__PURE__ */ (0, import_jsx_runtime101.jsx)(ThinkingBlock, { text: m.thinking, durationMs: m.thinkingMs, streaming: m.streaming && !m.text }) : null,
14049
+ m.steps && m.steps.length && ctx.showSteps ? /* @__PURE__ */ (0, import_jsx_runtime101.jsx)(StepList, { steps: m.steps, defaultOpen: m.steps.some((s) => s.status === "running"), dense: true }) : null,
14050
+ body ? /* @__PURE__ */ (0, import_jsx_runtime101.jsxs)("div", { className: "fdc-text" + (isUser ? " is-user" : ""), children: [
14051
+ showMd ? /* @__PURE__ */ (0, import_jsx_runtime101.jsx)(Markdown, { source: body, headingOffset: 2, codeProps: { collapseAfter: 22 }, renderCitation: ctx.renderCitation }) : /* @__PURE__ */ (0, import_jsx_runtime101.jsx)("div", { className: "fdc-plain", children: body }),
14052
+ m.streaming ? /* @__PURE__ */ (0, import_jsx_runtime101.jsx)("span", { className: "fdc-caret", "aria-hidden": "true" }) : null
13933
14053
  ] }) : null,
13934
- clamped != null ? /* @__PURE__ */ (0, import_jsx_runtime99.jsxs)("button", { type: "button", className: "fdc-more", onClick: () => setExpanded(true), children: [
13935
- /* @__PURE__ */ (0, import_jsx_runtime99.jsx)("i", { className: "ph ph-caret-down", "aria-hidden": "true" }),
14054
+ clamped != null ? /* @__PURE__ */ (0, import_jsx_runtime101.jsxs)("button", { type: "button", className: "fdc-more", onClick: () => setExpanded(true), children: [
14055
+ /* @__PURE__ */ (0, import_jsx_runtime101.jsx)("i", { className: "ph ph-caret-down", "aria-hidden": "true" }),
13936
14056
  "Show more",
13937
- /* @__PURE__ */ (0, import_jsx_runtime99.jsx)("span", { className: "fdc-more-len fd-tabular", children: raw.length < 2e3 ? raw.length.toLocaleString() + " characters" : Math.round(raw.length / 100) / 10 + "k characters" })
13938
- ] }) : expanded && ctx.maxVisibleChars && raw.length > ctx.maxVisibleChars ? /* @__PURE__ */ (0, import_jsx_runtime99.jsxs)("button", { type: "button", className: "fdc-more", onClick: () => setExpanded(false), children: [
13939
- /* @__PURE__ */ (0, import_jsx_runtime99.jsx)("i", { className: "ph ph-caret-up", "aria-hidden": "true" }),
14057
+ /* @__PURE__ */ (0, import_jsx_runtime101.jsx)("span", { className: "fdc-more-len fd-tabular", children: raw.length < 2e3 ? raw.length.toLocaleString() + " characters" : Math.round(raw.length / 100) / 10 + "k characters" })
14058
+ ] }) : expanded && ctx.maxVisibleChars && raw.length > ctx.maxVisibleChars ? /* @__PURE__ */ (0, import_jsx_runtime101.jsxs)("button", { type: "button", className: "fdc-more", onClick: () => setExpanded(false), children: [
14059
+ /* @__PURE__ */ (0, import_jsx_runtime101.jsx)("i", { className: "ph ph-caret-up", "aria-hidden": "true" }),
13940
14060
  "Show less"
13941
14061
  ] }) : null,
13942
- m.attachments && m.attachments.length ? /* @__PURE__ */ (0, import_jsx_runtime99.jsx)(FileGrid, { files: m.attachments, onOpen: ctx.onOpenAttachment, tiles: true, maxHeight: ctx.attachmentHeight || 220, compact: ctx.narrow }) : null,
13943
- m.packet ? /* @__PURE__ */ (0, import_jsx_runtime99.jsx)(
14062
+ m.attachments && m.attachments.length ? /* @__PURE__ */ (0, import_jsx_runtime101.jsx)(FileGrid, { files: m.attachments, onOpen: ctx.onOpenAttachment, tiles: true, maxHeight: ctx.attachmentHeight || 220, compact: ctx.narrow }) : null,
14063
+ m.packet ? /* @__PURE__ */ (0, import_jsx_runtime101.jsx)(
13944
14064
  PacketCard,
13945
14065
  {
13946
14066
  packet: m.packet,
@@ -13950,35 +14070,35 @@ function MessageBody({ message: m, ctx }) {
13950
14070
  applied: ctx.appliedPackets && ctx.appliedPackets[m.id]
13951
14071
  }
13952
14072
  ) : null,
13953
- m.citations && m.citations.length ? /* @__PURE__ */ (0, import_jsx_runtime99.jsx)(Citations, { items: m.citations, onOpen: ctx.onOpenCitation }) : null,
13954
- m.working ? /* @__PURE__ */ (0, import_jsx_runtime99.jsxs)("div", { className: "fdc-working", role: "status", children: [
13955
- /* @__PURE__ */ (0, import_jsx_runtime99.jsxs)("span", { className: "fdc-dots", "aria-hidden": "true", children: [
13956
- /* @__PURE__ */ (0, import_jsx_runtime99.jsx)("span", {}),
13957
- /* @__PURE__ */ (0, import_jsx_runtime99.jsx)("span", {}),
13958
- /* @__PURE__ */ (0, import_jsx_runtime99.jsx)("span", {})
14073
+ m.citations && m.citations.length ? /* @__PURE__ */ (0, import_jsx_runtime101.jsx)(Citations, { items: m.citations, onOpen: ctx.onOpenCitation }) : null,
14074
+ m.working ? /* @__PURE__ */ (0, import_jsx_runtime101.jsxs)("div", { className: "fdc-working", role: "status", children: [
14075
+ /* @__PURE__ */ (0, import_jsx_runtime101.jsxs)("span", { className: "fdc-dots", "aria-hidden": "true", children: [
14076
+ /* @__PURE__ */ (0, import_jsx_runtime101.jsx)("span", {}),
14077
+ /* @__PURE__ */ (0, import_jsx_runtime101.jsx)("span", {}),
14078
+ /* @__PURE__ */ (0, import_jsx_runtime101.jsx)("span", {})
13959
14079
  ] }),
13960
- /* @__PURE__ */ (0, import_jsx_runtime99.jsxs)("span", { className: "fdc-working-label", children: [
14080
+ /* @__PURE__ */ (0, import_jsx_runtime101.jsxs)("span", { className: "fdc-working-label", children: [
13961
14081
  m.resumed ? "Resuming" : "Working",
13962
- m.job && m.job.status ? /* @__PURE__ */ (0, import_jsx_runtime99.jsxs)("span", { className: "fdc-working-job", children: [
14082
+ m.job && m.job.status ? /* @__PURE__ */ (0, import_jsx_runtime101.jsxs)("span", { className: "fdc-working-job", children: [
13963
14083
  " \xB7 ",
13964
14084
  m.job.status
13965
14085
  ] }) : null,
13966
- m.job && m.job.detail ? /* @__PURE__ */ (0, import_jsx_runtime99.jsxs)("span", { className: "fdc-working-job", children: [
14086
+ m.job && m.job.detail ? /* @__PURE__ */ (0, import_jsx_runtime101.jsxs)("span", { className: "fdc-working-job", children: [
13967
14087
  " \xB7 ",
13968
14088
  m.job.detail
13969
14089
  ] }) : null
13970
14090
  ] }),
13971
- m.jobId ? /* @__PURE__ */ (0, import_jsx_runtime99.jsx)("span", { className: "fdc-working-id fd-mono", children: String(m.jobId).slice(0, 12) }) : null
14091
+ m.jobId ? /* @__PURE__ */ (0, import_jsx_runtime101.jsx)("span", { className: "fdc-working-id fd-mono", children: String(m.jobId).slice(0, 12) }) : null
13972
14092
  ] }) : null,
13973
- m.stopped ? /* @__PURE__ */ (0, import_jsx_runtime99.jsxs)("div", { className: "fdc-stopped", children: [
13974
- /* @__PURE__ */ (0, import_jsx_runtime99.jsx)("i", { className: "ph ph-stop-circle", "aria-hidden": "true" }),
14093
+ m.stopped ? /* @__PURE__ */ (0, import_jsx_runtime101.jsxs)("div", { className: "fdc-stopped", children: [
14094
+ /* @__PURE__ */ (0, import_jsx_runtime101.jsx)("i", { className: "ph ph-stop-circle", "aria-hidden": "true" }),
13975
14095
  "Stopped"
13976
14096
  ] }) : null,
13977
- m.error ? /* @__PURE__ */ (0, import_jsx_runtime99.jsxs)("div", { className: "fdc-error", role: "alert", children: [
13978
- /* @__PURE__ */ (0, import_jsx_runtime99.jsx)("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
13979
- /* @__PURE__ */ (0, import_jsx_runtime99.jsx)("span", { className: "fdc-error-text", children: ctx.errorCopy ? ctx.errorCopy(m.error) : m.error }),
13980
- m.retryable && ctx.onRetry ? /* @__PURE__ */ (0, import_jsx_runtime99.jsxs)("button", { type: "button", className: "fdc-error-retry", onClick: ctx.onRetry, children: [
13981
- /* @__PURE__ */ (0, import_jsx_runtime99.jsx)("i", { className: "ph ph-arrow-clockwise", "aria-hidden": "true" }),
14097
+ m.error ? /* @__PURE__ */ (0, import_jsx_runtime101.jsxs)("div", { className: "fdc-error", role: "alert", children: [
14098
+ /* @__PURE__ */ (0, import_jsx_runtime101.jsx)("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
14099
+ /* @__PURE__ */ (0, import_jsx_runtime101.jsx)("span", { className: "fdc-error-text", children: ctx.errorCopy ? ctx.errorCopy(m.error) : m.error }),
14100
+ m.retryable && ctx.onRetry ? /* @__PURE__ */ (0, import_jsx_runtime101.jsxs)("button", { type: "button", className: "fdc-error-retry", onClick: ctx.onRetry, children: [
14101
+ /* @__PURE__ */ (0, import_jsx_runtime101.jsx)("i", { className: "ph ph-arrow-clockwise", "aria-hidden": "true" }),
13982
14102
  "Retry"
13983
14103
  ] }) : null
13984
14104
  ] }) : null
@@ -13991,16 +14111,16 @@ function RunActions({ group, ctx }) {
13991
14111
  const isAssistant = group.role === "assistant";
13992
14112
  const fb = last.feedback;
13993
14113
  if (!ctx.messageActions) return null;
13994
- return /* @__PURE__ */ (0, import_jsx_runtime99.jsxs)("div", { className: "fdc-actions", role: "group", "aria-label": "Message actions", children: [
13995
- /* @__PURE__ */ (0, import_jsx_runtime99.jsxs)("button", { type: "button", className: "fdc-act" + (copied ? " is-done" : ""), onClick: () => copy(markdownToText(text)), "aria-label": "Copy message", children: [
13996
- /* @__PURE__ */ (0, import_jsx_runtime99.jsx)("i", { className: "ph ph-" + (copied ? "check" : "copy"), "aria-hidden": "true" }),
13997
- /* @__PURE__ */ (0, import_jsx_runtime99.jsx)("span", { className: "fdc-act-label", children: copied ? "Copied" : "Copy" })
14114
+ return /* @__PURE__ */ (0, import_jsx_runtime101.jsxs)("div", { className: "fdc-actions", role: "group", "aria-label": "Message actions", children: [
14115
+ /* @__PURE__ */ (0, import_jsx_runtime101.jsxs)("button", { type: "button", className: "fdc-act" + (copied ? " is-done" : ""), onClick: () => copy(markdownToText(text)), "aria-label": "Copy message", children: [
14116
+ /* @__PURE__ */ (0, import_jsx_runtime101.jsx)("i", { className: "ph ph-" + (copied ? "check" : "copy"), "aria-hidden": "true" }),
14117
+ /* @__PURE__ */ (0, import_jsx_runtime101.jsx)("span", { className: "fdc-act-label", children: copied ? "Copied" : "Copy" })
13998
14118
  ] }),
13999
- isAssistant && ctx.onRetry ? /* @__PURE__ */ (0, import_jsx_runtime99.jsx)("button", { type: "button", className: "fdc-act", onClick: ctx.onRetry, "aria-label": "Retry this turn", children: /* @__PURE__ */ (0, import_jsx_runtime99.jsx)("i", { className: "ph ph-arrow-clockwise", "aria-hidden": "true" }) }) : null,
14000
- group.role === "user" && ctx.onEdit ? /* @__PURE__ */ (0, import_jsx_runtime99.jsx)("button", { type: "button", className: "fdc-act", onClick: () => ctx.onEdit(last), "aria-label": "Edit and resend", children: /* @__PURE__ */ (0, import_jsx_runtime99.jsx)("i", { className: "ph ph-pencil-simple", "aria-hidden": "true" }) }) : null,
14001
- isAssistant && ctx.onFeedback ? /* @__PURE__ */ (0, import_jsx_runtime99.jsxs)(React70.Fragment, { children: [
14002
- /* @__PURE__ */ (0, import_jsx_runtime99.jsx)("button", { type: "button", className: "fdc-act" + (fb === "up" ? " is-on" : ""), onClick: () => ctx.onFeedback(last.id, "up"), "aria-pressed": fb === "up", "aria-label": "Good response", children: /* @__PURE__ */ (0, import_jsx_runtime99.jsx)("i", { className: "ph ph-thumbs-up", "aria-hidden": "true" }) }),
14003
- /* @__PURE__ */ (0, import_jsx_runtime99.jsx)("button", { type: "button", className: "fdc-act" + (fb === "down" ? " is-on" : ""), onClick: () => ctx.onFeedback(last.id, "down"), "aria-pressed": fb === "down", "aria-label": "Bad response", children: /* @__PURE__ */ (0, import_jsx_runtime99.jsx)("i", { className: "ph ph-thumbs-down", "aria-hidden": "true" }) })
14119
+ isAssistant && ctx.onRetry ? /* @__PURE__ */ (0, import_jsx_runtime101.jsx)("button", { type: "button", className: "fdc-act", onClick: ctx.onRetry, "aria-label": "Retry this turn", children: /* @__PURE__ */ (0, import_jsx_runtime101.jsx)("i", { className: "ph ph-arrow-clockwise", "aria-hidden": "true" }) }) : null,
14120
+ group.role === "user" && ctx.onEdit ? /* @__PURE__ */ (0, import_jsx_runtime101.jsx)("button", { type: "button", className: "fdc-act", onClick: () => ctx.onEdit(last), "aria-label": "Edit and resend", children: /* @__PURE__ */ (0, import_jsx_runtime101.jsx)("i", { className: "ph ph-pencil-simple", "aria-hidden": "true" }) }) : null,
14121
+ isAssistant && ctx.onFeedback ? /* @__PURE__ */ (0, import_jsx_runtime101.jsxs)(React71.Fragment, { children: [
14122
+ /* @__PURE__ */ (0, import_jsx_runtime101.jsx)("button", { type: "button", className: "fdc-act" + (fb === "up" ? " is-on" : ""), onClick: () => ctx.onFeedback(last.id, "up"), "aria-pressed": fb === "up", "aria-label": "Good response", children: /* @__PURE__ */ (0, import_jsx_runtime101.jsx)("i", { className: "ph ph-thumbs-up", "aria-hidden": "true" }) }),
14123
+ /* @__PURE__ */ (0, import_jsx_runtime101.jsx)("button", { type: "button", className: "fdc-act" + (fb === "down" ? " is-on" : ""), onClick: () => ctx.onFeedback(last.id, "down"), "aria-pressed": fb === "down", "aria-label": "Bad response", children: /* @__PURE__ */ (0, import_jsx_runtime101.jsx)("i", { className: "ph ph-thumbs-down", "aria-hidden": "true" }) })
14004
14124
  ] }) : null,
14005
14125
  ctx.extraActions ? ctx.extraActions(group) : null
14006
14126
  ] });
@@ -14010,22 +14130,22 @@ function ChatTurn({ group, ctx }) {
14010
14130
  const name = isUser ? ctx.userName : group.author || ctx.assistantName;
14011
14131
  const avatar = isUser ? ctx.userAvatar : ctx.assistantAvatar;
14012
14132
  const stamp = group.messages[0].timestamp;
14013
- return /* @__PURE__ */ (0, import_jsx_runtime99.jsxs)("article", { className: "fdc-turn is-" + group.role, "aria-label": String(name) + (stamp ? " at " + formatClock(stamp) : ""), children: [
14014
- /* @__PURE__ */ (0, import_jsx_runtime99.jsxs)("div", { className: "fdc-turn-head", children: [
14015
- ctx.showAvatars ? /* @__PURE__ */ (0, import_jsx_runtime99.jsx)("span", { className: "fdc-avatar is-" + group.role, "aria-hidden": "true", children: avatar ? /* @__PURE__ */ (0, import_jsx_runtime99.jsx)("img", { src: avatar, alt: "" }) : isUser ? /* @__PURE__ */ (0, import_jsx_runtime99.jsx)("span", { className: "fdc-avatar-txt", children: (name || "You").slice(0, 1).toUpperCase() }) : /* @__PURE__ */ (0, import_jsx_runtime99.jsx)("i", { className: "ph ph-" + (ctx.assistantIcon || "sparkle") }) }) : null,
14016
- /* @__PURE__ */ (0, import_jsx_runtime99.jsx)("span", { className: "fdc-who", children: name }),
14017
- stamp ? /* @__PURE__ */ (0, import_jsx_runtime99.jsx)(RelativeTime, { className: "fdc-when", value: stamp }) : null,
14018
- group.messages.some((m) => m.model) ? /* @__PURE__ */ (0, import_jsx_runtime99.jsx)("span", { className: "fdc-turn-model", children: group.messages.find((m) => m.model).model }) : null
14133
+ return /* @__PURE__ */ (0, import_jsx_runtime101.jsxs)("article", { className: "fdc-turn is-" + group.role, "aria-label": String(name) + (stamp ? " at " + formatClock(stamp) : ""), children: [
14134
+ /* @__PURE__ */ (0, import_jsx_runtime101.jsxs)("div", { className: "fdc-turn-head", children: [
14135
+ ctx.showAvatars ? /* @__PURE__ */ (0, import_jsx_runtime101.jsx)("span", { className: "fdc-avatar is-" + group.role, "aria-hidden": "true", children: avatar ? /* @__PURE__ */ (0, import_jsx_runtime101.jsx)("img", { src: avatar, alt: "" }) : isUser ? /* @__PURE__ */ (0, import_jsx_runtime101.jsx)("span", { className: "fdc-avatar-txt", children: (name || "You").slice(0, 1).toUpperCase() }) : /* @__PURE__ */ (0, import_jsx_runtime101.jsx)("i", { className: "ph ph-" + (ctx.assistantIcon || "sparkle") }) }) : null,
14136
+ /* @__PURE__ */ (0, import_jsx_runtime101.jsx)("span", { className: "fdc-who", children: name }),
14137
+ stamp ? /* @__PURE__ */ (0, import_jsx_runtime101.jsx)(RelativeTime, { className: "fdc-when", value: stamp }) : null,
14138
+ group.messages.some((m) => m.model) ? /* @__PURE__ */ (0, import_jsx_runtime101.jsx)("span", { className: "fdc-turn-model", children: group.messages.find((m) => m.model).model }) : null
14019
14139
  ] }),
14020
- /* @__PURE__ */ (0, import_jsx_runtime99.jsxs)("div", { className: "fdc-turn-body", children: [
14021
- group.messages.map((m) => /* @__PURE__ */ (0, import_jsx_runtime99.jsx)("div", { className: "fdc-msg" + (m.pending ? " is-pending" : ""), children: /* @__PURE__ */ (0, import_jsx_runtime99.jsx)(MessageBody, { message: m, ctx }) }, m.id)),
14022
- /* @__PURE__ */ (0, import_jsx_runtime99.jsx)(RunActions, { group, ctx })
14140
+ /* @__PURE__ */ (0, import_jsx_runtime101.jsxs)("div", { className: "fdc-turn-body", children: [
14141
+ group.messages.map((m) => /* @__PURE__ */ (0, import_jsx_runtime101.jsx)("div", { className: "fdc-msg" + (m.pending ? " is-pending" : ""), children: /* @__PURE__ */ (0, import_jsx_runtime101.jsx)(MessageBody, { message: m, ctx }) }, m.id)),
14142
+ /* @__PURE__ */ (0, import_jsx_runtime101.jsx)(RunActions, { group, ctx })
14023
14143
  ] })
14024
14144
  ] });
14025
14145
  }
14026
14146
 
14027
14147
  // src/components/chat/ChatTranscript.tsx
14028
- var import_jsx_runtime100 = require("react/jsx-runtime");
14148
+ var import_jsx_runtime102 = require("react/jsx-runtime");
14029
14149
  var GROUP_WINDOW = 6e4;
14030
14150
  var STICK_PX = 100;
14031
14151
  function groupMessages(list) {
@@ -14058,25 +14178,25 @@ function dayLabel(key) {
14058
14178
  }
14059
14179
  function Suggestions({ items = [], onPick }) {
14060
14180
  if (!items.length) return null;
14061
- return /* @__PURE__ */ (0, import_jsx_runtime100.jsx)("div", { className: "fdc-suggest", children: items.map((s, i) => {
14181
+ return /* @__PURE__ */ (0, import_jsx_runtime102.jsx)("div", { className: "fdc-suggest", children: items.map((s, i) => {
14062
14182
  const it = typeof s === "string" ? { label: s, text: s } : s;
14063
- return /* @__PURE__ */ (0, import_jsx_runtime100.jsxs)("button", { type: "button", className: "fdc-suggest-item", onClick: () => onPick && onPick(it.text || it.label), children: [
14064
- it.icon ? /* @__PURE__ */ (0, import_jsx_runtime100.jsx)("i", { className: "ph ph-" + it.icon, "aria-hidden": "true" }) : null,
14065
- /* @__PURE__ */ (0, import_jsx_runtime100.jsxs)("span", { className: "fdc-suggest-text", children: [
14066
- /* @__PURE__ */ (0, import_jsx_runtime100.jsx)("span", { className: "fdc-suggest-label", children: it.label }),
14067
- it.description ? /* @__PURE__ */ (0, import_jsx_runtime100.jsx)("span", { className: "fdc-suggest-desc", children: it.description }) : null
14183
+ return /* @__PURE__ */ (0, import_jsx_runtime102.jsxs)("button", { type: "button", className: "fdc-suggest-item", onClick: () => onPick && onPick(it.text || it.label), children: [
14184
+ it.icon ? /* @__PURE__ */ (0, import_jsx_runtime102.jsx)("i", { className: "ph ph-" + it.icon, "aria-hidden": "true" }) : null,
14185
+ /* @__PURE__ */ (0, import_jsx_runtime102.jsxs)("span", { className: "fdc-suggest-text", children: [
14186
+ /* @__PURE__ */ (0, import_jsx_runtime102.jsx)("span", { className: "fdc-suggest-label", children: it.label }),
14187
+ it.description ? /* @__PURE__ */ (0, import_jsx_runtime102.jsx)("span", { className: "fdc-suggest-desc", children: it.description }) : null
14068
14188
  ] }),
14069
- /* @__PURE__ */ (0, import_jsx_runtime100.jsx)("i", { className: "ph ph-arrow-up-right fdc-suggest-go", "aria-hidden": "true" })
14189
+ /* @__PURE__ */ (0, import_jsx_runtime102.jsx)("i", { className: "ph ph-arrow-up-right fdc-suggest-go", "aria-hidden": "true" })
14070
14190
  ] }, it.id || i);
14071
14191
  }) });
14072
14192
  }
14073
14193
  function LoadingTurns() {
14074
- return /* @__PURE__ */ (0, import_jsx_runtime100.jsx)("div", { className: "fdc-skel", "aria-hidden": "true", children: [0, 1].map((i) => /* @__PURE__ */ (0, import_jsx_runtime100.jsxs)("div", { className: "fdc-skel-turn", children: [
14075
- /* @__PURE__ */ (0, import_jsx_runtime100.jsx)("div", { className: "fd-skel fd-skel-circle", style: { width: 22, height: 22 } }),
14076
- /* @__PURE__ */ (0, import_jsx_runtime100.jsxs)("div", { className: "fdc-skel-lines", children: [
14077
- /* @__PURE__ */ (0, import_jsx_runtime100.jsx)("div", { className: "fd-skel", style: { width: i ? "62%" : "44%", height: 11 } }),
14078
- /* @__PURE__ */ (0, import_jsx_runtime100.jsx)("div", { className: "fd-skel", style: { width: i ? "94%" : "78%", height: 11 } }),
14079
- /* @__PURE__ */ (0, import_jsx_runtime100.jsx)("div", { className: "fd-skel", style: { width: i ? "71%" : "56%", height: 11 } })
14194
+ return /* @__PURE__ */ (0, import_jsx_runtime102.jsx)("div", { className: "fdc-skel", "aria-hidden": "true", children: [0, 1].map((i) => /* @__PURE__ */ (0, import_jsx_runtime102.jsxs)("div", { className: "fdc-skel-turn", children: [
14195
+ /* @__PURE__ */ (0, import_jsx_runtime102.jsx)("div", { className: "fd-skel fd-skel-circle", style: { width: 22, height: 22 } }),
14196
+ /* @__PURE__ */ (0, import_jsx_runtime102.jsxs)("div", { className: "fdc-skel-lines", children: [
14197
+ /* @__PURE__ */ (0, import_jsx_runtime102.jsx)("div", { className: "fd-skel", style: { width: i ? "62%" : "44%", height: 11 } }),
14198
+ /* @__PURE__ */ (0, import_jsx_runtime102.jsx)("div", { className: "fd-skel", style: { width: i ? "94%" : "78%", height: 11 } }),
14199
+ /* @__PURE__ */ (0, import_jsx_runtime102.jsx)("div", { className: "fd-skel", style: { width: i ? "71%" : "56%", height: 11 } })
14080
14200
  ] })
14081
14201
  ] }, i)) });
14082
14202
  }
@@ -14093,10 +14213,10 @@ function ChatTranscript({
14093
14213
  renderEmpty,
14094
14214
  className = ""
14095
14215
  }) {
14096
- const scroller = React71.useRef(null);
14097
- const stick = React71.useRef(true);
14098
- const [pill, setPill] = React71.useState(0);
14099
- const seen = React71.useRef(0);
14216
+ const scroller = React72.useRef(null);
14217
+ const stick = React72.useRef(true);
14218
+ const [pill, setPill] = React72.useState(0);
14219
+ const seen = React72.useRef(0);
14100
14220
  const toBottom = (smooth) => {
14101
14221
  const el = scroller.current;
14102
14222
  if (!el) return;
@@ -14115,7 +14235,7 @@ function ChatTranscript({
14115
14235
  seen.current = messages.length;
14116
14236
  }
14117
14237
  };
14118
- React71.useLayoutEffect(() => {
14238
+ React72.useLayoutEffect(() => {
14119
14239
  const el = scroller.current;
14120
14240
  if (!el) return;
14121
14241
  if (stick.current) {
@@ -14123,7 +14243,7 @@ function ChatTranscript({
14123
14243
  seen.current = messages.length;
14124
14244
  } else setPill(Math.max(0, messages.length - seen.current));
14125
14245
  }, [messages]);
14126
- React71.useEffect(() => {
14246
+ React72.useEffect(() => {
14127
14247
  const el = scroller.current;
14128
14248
  const inner = el && el.firstChild;
14129
14249
  if (!el || !inner || typeof ResizeObserver === "undefined") return;
@@ -14133,38 +14253,38 @@ function ChatTranscript({
14133
14253
  ro.observe(inner);
14134
14254
  return () => ro.disconnect();
14135
14255
  }, []);
14136
- const groups = React71.useMemo(() => groupMessages(messages), [messages]);
14256
+ const groups = React72.useMemo(() => groupMessages(messages), [messages]);
14137
14257
  const empty = !messages.length && status === "ready";
14138
- return /* @__PURE__ */ (0, import_jsx_runtime100.jsxs)("div", { className: ["fdc-scroll", className].filter(Boolean).join(" "), ref: scroller, onScroll, children: [
14139
- /* @__PURE__ */ (0, import_jsx_runtime100.jsxs)("div", { className: "fdc-log", role: "log", "aria-label": "Conversation", children: [
14140
- status === "loading" || status === "resolving" ? /* @__PURE__ */ (0, import_jsx_runtime100.jsx)(LoadingTurns, {}) : null,
14141
- status === "disconnected" ? /* @__PURE__ */ (0, import_jsx_runtime100.jsxs)("div", { className: "fdc-dead", children: [
14142
- /* @__PURE__ */ (0, import_jsx_runtime100.jsx)("span", { className: "fdc-dead-icon", children: /* @__PURE__ */ (0, import_jsx_runtime100.jsx)("i", { className: "ph ph-plugs", "aria-hidden": "true" }) }),
14143
- /* @__PURE__ */ (0, import_jsx_runtime100.jsx)("h3", { className: "fdc-dead-title", children: ctx.deadTitle || "The assistant isn\u2019t reachable" }),
14144
- /* @__PURE__ */ (0, import_jsx_runtime100.jsx)("p", { className: "fdc-dead-body", children: fatal === "chat_unavailable" ? "The service reported chat_unavailable. Nothing you type will be lost \u2014 reopen the panel once it\u2019s back." : "The thread couldn\u2019t be resolved" + (fatal ? " (" + fatal + ")" : "") + ". The composer stays disabled until it resolves." }),
14145
- ctx.onReconnect ? /* @__PURE__ */ (0, import_jsx_runtime100.jsxs)("button", { type: "button", className: "fd-btn fd-btn-secondary fd-btn-sm", onClick: ctx.onReconnect, children: [
14146
- /* @__PURE__ */ (0, import_jsx_runtime100.jsx)("i", { className: "ph ph-arrow-clockwise", "aria-hidden": "true" }),
14258
+ return /* @__PURE__ */ (0, import_jsx_runtime102.jsxs)("div", { className: ["fdc-scroll", className].filter(Boolean).join(" "), ref: scroller, onScroll, children: [
14259
+ /* @__PURE__ */ (0, import_jsx_runtime102.jsxs)("div", { className: "fdc-log", role: "log", "aria-label": "Conversation", children: [
14260
+ status === "loading" || status === "resolving" ? /* @__PURE__ */ (0, import_jsx_runtime102.jsx)(LoadingTurns, {}) : null,
14261
+ status === "disconnected" ? /* @__PURE__ */ (0, import_jsx_runtime102.jsxs)("div", { className: "fdc-dead", children: [
14262
+ /* @__PURE__ */ (0, import_jsx_runtime102.jsx)("span", { className: "fdc-dead-icon", children: /* @__PURE__ */ (0, import_jsx_runtime102.jsx)("i", { className: "ph ph-plugs", "aria-hidden": "true" }) }),
14263
+ /* @__PURE__ */ (0, import_jsx_runtime102.jsx)("h3", { className: "fdc-dead-title", children: ctx.deadTitle || "The assistant isn\u2019t reachable" }),
14264
+ /* @__PURE__ */ (0, import_jsx_runtime102.jsx)("p", { className: "fdc-dead-body", children: fatal === "chat_unavailable" ? "The service reported chat_unavailable. Nothing you type will be lost \u2014 reopen the panel once it\u2019s back." : "The thread couldn\u2019t be resolved" + (fatal ? " (" + fatal + ")" : "") + ". The composer stays disabled until it resolves." }),
14265
+ ctx.onReconnect ? /* @__PURE__ */ (0, import_jsx_runtime102.jsxs)("button", { type: "button", className: "fd-btn fd-btn-secondary fd-btn-sm", onClick: ctx.onReconnect, children: [
14266
+ /* @__PURE__ */ (0, import_jsx_runtime102.jsx)("i", { className: "ph ph-arrow-clockwise", "aria-hidden": "true" }),
14147
14267
  "Try again"
14148
14268
  ] }) : null
14149
14269
  ] }) : null,
14150
- empty ? renderEmpty ? renderEmpty() : /* @__PURE__ */ (0, import_jsx_runtime100.jsxs)("div", { className: "fdc-empty", children: [
14151
- /* @__PURE__ */ (0, import_jsx_runtime100.jsx)("span", { className: "fdc-empty-icon", children: /* @__PURE__ */ (0, import_jsx_runtime100.jsx)("i", { className: "ph ph-" + emptyIcon, "aria-hidden": "true" }) }),
14152
- /* @__PURE__ */ (0, import_jsx_runtime100.jsx)("h3", { className: "fdc-empty-title", children: emptyTitle }),
14153
- emptyDescription ? /* @__PURE__ */ (0, import_jsx_runtime100.jsx)("p", { className: "fdc-empty-body", children: emptyDescription }) : null,
14154
- /* @__PURE__ */ (0, import_jsx_runtime100.jsx)(Suggestions, { items: suggestions, onPick })
14270
+ empty ? renderEmpty ? renderEmpty() : /* @__PURE__ */ (0, import_jsx_runtime102.jsxs)("div", { className: "fdc-empty", children: [
14271
+ /* @__PURE__ */ (0, import_jsx_runtime102.jsx)("span", { className: "fdc-empty-icon", children: /* @__PURE__ */ (0, import_jsx_runtime102.jsx)("i", { className: "ph ph-" + emptyIcon, "aria-hidden": "true" }) }),
14272
+ /* @__PURE__ */ (0, import_jsx_runtime102.jsx)("h3", { className: "fdc-empty-title", children: emptyTitle }),
14273
+ emptyDescription ? /* @__PURE__ */ (0, import_jsx_runtime102.jsx)("p", { className: "fdc-empty-body", children: emptyDescription }) : null,
14274
+ /* @__PURE__ */ (0, import_jsx_runtime102.jsx)(Suggestions, { items: suggestions, onPick })
14155
14275
  ] }) : null,
14156
14276
  groups.map((g, i) => {
14157
14277
  const prev = groups[i - 1];
14158
14278
  const k = dayKey(g.messages[0].timestamp);
14159
14279
  const showDay = !!k && (!prev || dayKey(prev.messages[0].timestamp) !== k);
14160
- return /* @__PURE__ */ (0, import_jsx_runtime100.jsxs)(React71.Fragment, { children: [
14161
- showDay ? /* @__PURE__ */ (0, import_jsx_runtime100.jsx)("div", { className: "fdc-day", children: /* @__PURE__ */ (0, import_jsx_runtime100.jsx)("span", { children: dayLabel(k) }) }) : null,
14162
- /* @__PURE__ */ (0, import_jsx_runtime100.jsx)(ChatTurn, { group: g, ctx })
14280
+ return /* @__PURE__ */ (0, import_jsx_runtime102.jsxs)(React72.Fragment, { children: [
14281
+ showDay ? /* @__PURE__ */ (0, import_jsx_runtime102.jsx)("div", { className: "fdc-day", children: /* @__PURE__ */ (0, import_jsx_runtime102.jsx)("span", { children: dayLabel(k) }) }) : null,
14282
+ /* @__PURE__ */ (0, import_jsx_runtime102.jsx)(ChatTurn, { group: g, ctx })
14163
14283
  ] }, g.key || i);
14164
14284
  })
14165
14285
  ] }),
14166
- pill ? /* @__PURE__ */ (0, import_jsx_runtime100.jsxs)("button", { type: "button", className: "fdc-pill", onClick: () => toBottom(true), children: [
14167
- /* @__PURE__ */ (0, import_jsx_runtime100.jsx)("i", { className: "ph ph-arrow-down", "aria-hidden": "true" }),
14286
+ pill ? /* @__PURE__ */ (0, import_jsx_runtime102.jsxs)("button", { type: "button", className: "fdc-pill", onClick: () => toBottom(true), children: [
14287
+ /* @__PURE__ */ (0, import_jsx_runtime102.jsx)("i", { className: "ph ph-arrow-down", "aria-hidden": "true" }),
14168
14288
  pill,
14169
14289
  " new message",
14170
14290
  pill === 1 ? "" : "s"
@@ -14174,8 +14294,8 @@ function ChatTranscript({
14174
14294
  var TranscriptKit = { groupMessages };
14175
14295
 
14176
14296
  // src/components/chat/ChatComposer.tsx
14177
- var React72 = __toESM(require("react"), 1);
14178
- var import_jsx_runtime101 = require("react/jsx-runtime");
14297
+ var React73 = __toESM(require("react"), 1);
14298
+ var import_jsx_runtime103 = require("react/jsx-runtime");
14179
14299
  function ChatComposer({
14180
14300
  onSubmit,
14181
14301
  onStop,
@@ -14202,17 +14322,17 @@ function ChatComposer({
14202
14322
  onReject,
14203
14323
  onOpenAttachment
14204
14324
  }) {
14205
- const [text, setText] = React72.useState(draft || "");
14206
- const [trigger, setTrigger] = React72.useState(null);
14207
- const [mentionItems, setMentionItems] = React72.useState([]);
14208
- const [listening, setListening] = React72.useState(false);
14209
- const [notice, setNotice] = React72.useState(null);
14210
- const editor = React72.useRef(null);
14211
- const wrap = React72.useRef(null);
14212
- const stopVoice = React72.useRef(null);
14325
+ const [text, setText] = React73.useState(draft || "");
14326
+ const [trigger, setTrigger] = React73.useState(null);
14327
+ const [mentionItems, setMentionItems] = React73.useState([]);
14328
+ const [listening, setListening] = React73.useState(false);
14329
+ const [notice, setNotice] = React73.useState(null);
14330
+ const editor = React73.useRef(null);
14331
+ const wrap = React73.useRef(null);
14332
+ const stopVoice = React73.useRef(null);
14213
14333
  const staged = useStagedFiles(fileUploadHandler, { onError: () => {
14214
14334
  } });
14215
- React72.useEffect(() => {
14335
+ React73.useEffect(() => {
14216
14336
  if (draft != null && draft !== text) setText(draft);
14217
14337
  }, [draft]);
14218
14338
  const change = (v) => {
@@ -14248,7 +14368,7 @@ function ChatComposer({
14248
14368
  e.preventDefault();
14249
14369
  staged.add(found.files);
14250
14370
  };
14251
- React72.useEffect(() => {
14371
+ React73.useEffect(() => {
14252
14372
  if (!trigger || trigger.type !== "mention" || !mentionSources) {
14253
14373
  setMentionItems([]);
14254
14374
  return;
@@ -14266,7 +14386,7 @@ function ChatComposer({
14266
14386
  const q = (trigger.query || "").toLowerCase();
14267
14387
  setMentionItems(mentionSources.filter((m) => !q || (m.label + " " + (m.description || "")).toLowerCase().includes(q)));
14268
14388
  }, [trigger, mentionSources]);
14269
- const slashItems = React72.useMemo(() => {
14389
+ const slashItems = React73.useMemo(() => {
14270
14390
  if (!trigger || trigger.type !== "slash" || !slashCommands) return [];
14271
14391
  const q = (trigger.query || "").toLowerCase();
14272
14392
  return slashCommands.filter((c) => !q || (c.id + " " + c.label + " " + (c.description || "")).toLowerCase().includes(q));
@@ -14280,7 +14400,7 @@ function ChatComposer({
14280
14400
  description: it.description,
14281
14401
  icon: it.icon,
14282
14402
  meta: mention.meta,
14283
- shortcut: slash.shortcut ? /* @__PURE__ */ (0, import_jsx_runtime101.jsx)(KeyHint, { keys: slash.shortcut, size: "sm" }) : void 0,
14403
+ shortcut: slash.shortcut ? /* @__PURE__ */ (0, import_jsx_runtime103.jsx)(KeyHint, { keys: slash.shortcut, size: "sm" }) : void 0,
14284
14404
  onSelect: () => {
14285
14405
  const insert = trigger.type === "slash" ? slash.immediate ? "/" + slash.id : "/" + slash.id + " " : "@" + (mention.value || mention.label) + " ";
14286
14406
  editor.current && editor.current.replaceRange(trigger.from, trigger.to, insert);
@@ -14339,14 +14459,14 @@ function ChatComposer({
14339
14459
  stopVoice.current = typeof res === "function" ? res : () => {
14340
14460
  };
14341
14461
  };
14342
- return /* @__PURE__ */ (0, import_jsx_runtime101.jsxs)("div", { className: "fdc-composer" + (disabled ? " is-disabled" : "") + (narrow ? " is-narrow" : ""), children: [
14343
- queue.length ? /* @__PURE__ */ (0, import_jsx_runtime101.jsx)("div", { className: "fdc-queue", "aria-label": "Queued messages", children: queue.map((q) => /* @__PURE__ */ (0, import_jsx_runtime101.jsxs)("div", { className: "fdc-queue-row", children: [
14344
- /* @__PURE__ */ (0, import_jsx_runtime101.jsx)("i", { className: "ph ph-clock-countdown", "aria-hidden": "true" }),
14345
- /* @__PURE__ */ (0, import_jsx_runtime101.jsx)("span", { className: "fdc-queue-text", title: truncationTitle(q.text || (q.attachments ? q.attachments.length + " file(s)" : "")), children: q.text || (q.attachments ? q.attachments.length + " file(s)" : "") }),
14346
- onRemoveQueued ? /* @__PURE__ */ (0, import_jsx_runtime101.jsx)("button", { type: "button", className: "fdc-queue-x", onClick: () => onRemoveQueued(q.id), "aria-label": "Remove queued message", children: /* @__PURE__ */ (0, import_jsx_runtime101.jsx)("i", { className: "ph ph-x", "aria-hidden": "true" }) }) : null
14462
+ return /* @__PURE__ */ (0, import_jsx_runtime103.jsxs)("div", { className: "fdc-composer" + (disabled ? " is-disabled" : "") + (narrow ? " is-narrow" : ""), children: [
14463
+ queue.length ? /* @__PURE__ */ (0, import_jsx_runtime103.jsx)("div", { className: "fdc-queue", "aria-label": "Queued messages", children: queue.map((q) => /* @__PURE__ */ (0, import_jsx_runtime103.jsxs)("div", { className: "fdc-queue-row", children: [
14464
+ /* @__PURE__ */ (0, import_jsx_runtime103.jsx)("i", { className: "ph ph-clock-countdown", "aria-hidden": "true" }),
14465
+ /* @__PURE__ */ (0, import_jsx_runtime103.jsx)("span", { className: "fdc-queue-text", title: truncationTitle(q.text || (q.attachments ? q.attachments.length + " file(s)" : "")), children: q.text || (q.attachments ? q.attachments.length + " file(s)" : "") }),
14466
+ onRemoveQueued ? /* @__PURE__ */ (0, import_jsx_runtime103.jsx)("button", { type: "button", className: "fdc-queue-x", onClick: () => onRemoveQueued(q.id), "aria-label": "Remove queued message", children: /* @__PURE__ */ (0, import_jsx_runtime103.jsx)("i", { className: "ph ph-x", "aria-hidden": "true" }) }) : null
14347
14467
  ] }, q.id)) }) : null,
14348
14468
  sessionBar,
14349
- /* @__PURE__ */ (0, import_jsx_runtime101.jsx)(
14469
+ /* @__PURE__ */ (0, import_jsx_runtime103.jsx)(
14350
14470
  Dropzone,
14351
14471
  {
14352
14472
  className: "fdc-field",
@@ -14360,9 +14480,9 @@ function ChatComposer({
14360
14480
  disabled: !fileUploadHandler || disabled,
14361
14481
  label: "Drop to attach",
14362
14482
  hint: acceptFiles ? acceptFiles.replace(/,/g, " \xB7 ") : void 0,
14363
- children: /* @__PURE__ */ (0, import_jsx_runtime101.jsxs)("div", { ref: wrap, className: "fdc-field-inner", children: [
14364
- staged.items.length ? /* @__PURE__ */ (0, import_jsx_runtime101.jsx)("div", { className: "fdc-staged", children: /* @__PURE__ */ (0, import_jsx_runtime101.jsx)(FileStrip, { files: staged.items, size: narrow ? 60 : 68, onRemove: staged.remove, onRetry: staged.retry, onOpen: onOpenAttachment }) }) : null,
14365
- /* @__PURE__ */ (0, import_jsx_runtime101.jsx)(
14483
+ children: /* @__PURE__ */ (0, import_jsx_runtime103.jsxs)("div", { ref: wrap, className: "fdc-field-inner", children: [
14484
+ staged.items.length ? /* @__PURE__ */ (0, import_jsx_runtime103.jsx)("div", { className: "fdc-staged", children: /* @__PURE__ */ (0, import_jsx_runtime103.jsx)(FileStrip, { files: staged.items, size: narrow ? 60 : 68, onRemove: staged.remove, onRetry: staged.retry, onOpen: onOpenAttachment }) }) : null,
14485
+ /* @__PURE__ */ (0, import_jsx_runtime103.jsx)(
14366
14486
  MarkdownEditor,
14367
14487
  {
14368
14488
  ref: editor,
@@ -14381,33 +14501,33 @@ function ChatComposer({
14381
14501
  ariaLabel: "Message"
14382
14502
  }
14383
14503
  ),
14384
- /* @__PURE__ */ (0, import_jsx_runtime101.jsxs)("div", { className: "fdc-tools", children: [
14385
- fileUploadHandler ? /* @__PURE__ */ (0, import_jsx_runtime101.jsx)(FilePickButton, { onFiles: staged.add, onReject: (r) => flash(r[0].message), accept: acceptFiles, maxFileSize, label: "Attach files", icon: "plus" }) : null,
14386
- voiceHandler ? /* @__PURE__ */ (0, import_jsx_runtime101.jsx)("button", { type: "button", className: "fd-attachbtn" + (listening ? " is-live" : ""), onClick: voice, "aria-pressed": listening, "aria-label": listening ? "Stop dictation" : "Dictate", children: /* @__PURE__ */ (0, import_jsx_runtime101.jsx)("i", { className: "ph ph-" + (listening ? "waveform" : "microphone"), "aria-hidden": "true" }) }) : null,
14504
+ /* @__PURE__ */ (0, import_jsx_runtime103.jsxs)("div", { className: "fdc-tools", children: [
14505
+ fileUploadHandler ? /* @__PURE__ */ (0, import_jsx_runtime103.jsx)(FilePickButton, { onFiles: staged.add, onReject: (r) => flash(r[0].message), accept: acceptFiles, maxFileSize, label: "Attach files", icon: "plus" }) : null,
14506
+ voiceHandler ? /* @__PURE__ */ (0, import_jsx_runtime103.jsx)("button", { type: "button", className: "fd-attachbtn" + (listening ? " is-live" : ""), onClick: voice, "aria-pressed": listening, "aria-label": listening ? "Stop dictation" : "Dictate", children: /* @__PURE__ */ (0, import_jsx_runtime103.jsx)("i", { className: "ph ph-" + (listening ? "waveform" : "microphone"), "aria-hidden": "true" }) }) : null,
14387
14507
  toolbarExtras,
14388
- /* @__PURE__ */ (0, import_jsx_runtime101.jsx)("span", { className: "fdc-tools-gap" }),
14389
- maxLength && text.length > maxLength * 0.6 ? /* @__PURE__ */ (0, import_jsx_runtime101.jsxs)("span", { className: "fdc-count fd-tabular" + (text.length > maxLength * 0.95 ? " is-hot" : ""), children: [
14508
+ /* @__PURE__ */ (0, import_jsx_runtime103.jsx)("span", { className: "fdc-tools-gap" }),
14509
+ maxLength && text.length > maxLength * 0.6 ? /* @__PURE__ */ (0, import_jsx_runtime103.jsxs)("span", { className: "fdc-count fd-tabular" + (text.length > maxLength * 0.95 ? " is-hot" : ""), children: [
14390
14510
  text.length,
14391
14511
  "/",
14392
14512
  maxLength
14393
14513
  ] }) : null,
14394
- busy ? /* @__PURE__ */ (0, import_jsx_runtime101.jsxs)("button", { type: "button", className: "fdc-stop", onClick: onStop, "aria-label": "Stop generating", children: [
14395
- /* @__PURE__ */ (0, import_jsx_runtime101.jsx)("i", { className: "ph ph-stop-circle", "aria-hidden": "true" }),
14396
- /* @__PURE__ */ (0, import_jsx_runtime101.jsx)("span", { children: "Stop" })
14397
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime101.jsxs)("button", { type: "button", className: "fdc-send", onClick: submit, disabled: !canSend, "aria-label": "Send message", children: [
14398
- /* @__PURE__ */ (0, import_jsx_runtime101.jsx)("i", { className: "ph ph-paper-plane-right", "aria-hidden": "true" }),
14399
- /* @__PURE__ */ (0, import_jsx_runtime101.jsx)("span", { className: "fdc-send-label", children: "Send" })
14514
+ busy ? /* @__PURE__ */ (0, import_jsx_runtime103.jsxs)("button", { type: "button", className: "fdc-stop", onClick: onStop, "aria-label": "Stop generating", children: [
14515
+ /* @__PURE__ */ (0, import_jsx_runtime103.jsx)("i", { className: "ph ph-stop-circle", "aria-hidden": "true" }),
14516
+ /* @__PURE__ */ (0, import_jsx_runtime103.jsx)("span", { children: "Stop" })
14517
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime103.jsxs)("button", { type: "button", className: "fdc-send", onClick: submit, disabled: !canSend, "aria-label": "Send message", children: [
14518
+ /* @__PURE__ */ (0, import_jsx_runtime103.jsx)("i", { className: "ph ph-paper-plane-right", "aria-hidden": "true" }),
14519
+ /* @__PURE__ */ (0, import_jsx_runtime103.jsx)("span", { className: "fdc-send-label", children: "Send" })
14400
14520
  ] })
14401
14521
  ] })
14402
14522
  ] })
14403
14523
  }
14404
14524
  ),
14405
- notice ? /* @__PURE__ */ (0, import_jsx_runtime101.jsxs)("div", { className: "fdc-notice", role: "status", children: [
14406
- /* @__PURE__ */ (0, import_jsx_runtime101.jsx)("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
14525
+ notice ? /* @__PURE__ */ (0, import_jsx_runtime103.jsxs)("div", { className: "fdc-notice", role: "status", children: [
14526
+ /* @__PURE__ */ (0, import_jsx_runtime103.jsx)("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
14407
14527
  notice
14408
14528
  ] }) : null,
14409
- hint && !notice ? /* @__PURE__ */ (0, import_jsx_runtime101.jsx)("div", { className: "fdc-hint", children: hint }) : null,
14410
- /* @__PURE__ */ (0, import_jsx_runtime101.jsx)(
14529
+ hint && !notice ? /* @__PURE__ */ (0, import_jsx_runtime103.jsx)("div", { className: "fdc-hint", children: hint }) : null,
14530
+ /* @__PURE__ */ (0, import_jsx_runtime103.jsx)(
14411
14531
  Popover,
14412
14532
  {
14413
14533
  open: menuOpen,
@@ -14421,12 +14541,12 @@ function ChatComposer({
14421
14541
  returnFocus: false,
14422
14542
  closeOnOutside: true,
14423
14543
  label: trigger && trigger.type === "slash" ? "Commands" : "Mentions",
14424
- children: /* @__PURE__ */ (0, import_jsx_runtime101.jsx)(
14544
+ children: /* @__PURE__ */ (0, import_jsx_runtime103.jsx)(
14425
14545
  Menu,
14426
14546
  {
14427
14547
  items: menuItems,
14428
14548
  autoFocus: false,
14429
- header: /* @__PURE__ */ (0, import_jsx_runtime101.jsx)("div", { className: "fd-pop-group", children: trigger && trigger.type === "slash" ? "Commands" : "Attach context" }),
14549
+ header: /* @__PURE__ */ (0, import_jsx_runtime103.jsx)("div", { className: "fd-pop-group", children: trigger && trigger.type === "slash" ? "Commands" : "Attach context" }),
14430
14550
  onClose: () => setTrigger(null)
14431
14551
  }
14432
14552
  )
@@ -14436,12 +14556,12 @@ function ChatComposer({
14436
14556
  }
14437
14557
 
14438
14558
  // src/components/chat/ChatSessionBar.tsx
14439
- var React73 = __toESM(require("react"), 1);
14440
- var import_jsx_runtime102 = require("react/jsx-runtime");
14559
+ var React74 = __toESM(require("react"), 1);
14560
+ var import_jsx_runtime104 = require("react/jsx-runtime");
14441
14561
  var compact2 = meterFormats.compact;
14442
14562
  function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extras }) {
14443
- const [open2, setOpen] = React73.useState(false);
14444
- const anchor = React73.useRef(null);
14563
+ const [open2, setOpen] = React74.useState(false);
14564
+ const anchor = React74.useRef(null);
14445
14565
  const stats = sessionStats || null;
14446
14566
  const cu = contextUsage || null;
14447
14567
  const limits = usageLimits || null;
@@ -14456,9 +14576,9 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
14456
14576
  if (stats && stats.runningTasks) bits.push(stats.runningTasks + " running task" + (stats.runningTasks === 1 ? "" : "s"));
14457
14577
  if (cu) bits.push(pct + "% context");
14458
14578
  const expandable = !!(cu || limits);
14459
- return /* @__PURE__ */ (0, import_jsx_runtime102.jsxs)(React73.Fragment, { children: [
14460
- /* @__PURE__ */ (0, import_jsx_runtime102.jsxs)("div", { className: "fdc-bar", children: [
14461
- /* @__PURE__ */ (0, import_jsx_runtime102.jsxs)(
14579
+ return /* @__PURE__ */ (0, import_jsx_runtime104.jsxs)(React74.Fragment, { children: [
14580
+ /* @__PURE__ */ (0, import_jsx_runtime104.jsxs)("div", { className: "fdc-bar", children: [
14581
+ /* @__PURE__ */ (0, import_jsx_runtime104.jsxs)(
14462
14582
  "button",
14463
14583
  {
14464
14584
  type: "button",
@@ -14469,15 +14589,15 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
14469
14589
  "aria-expanded": expandable ? open2 : void 0,
14470
14590
  "aria-label": expandable ? "Usage details" : void 0,
14471
14591
  children: [
14472
- cu ? /* @__PURE__ */ (0, import_jsx_runtime102.jsx)("span", { className: "fdc-bar-mini", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime102.jsx)(SegmentedMeter, { total, segments: cu.segments, height: 4, showTotal: false }) }) : null,
14473
- /* @__PURE__ */ (0, import_jsx_runtime102.jsx)("span", { className: "fdc-bar-text", title: truncationTitle(bits.join(" \xB7 ")), children: bits.join(" \xB7 ") }),
14474
- expandable ? /* @__PURE__ */ (0, import_jsx_runtime102.jsx)("i", { className: "ph ph-caret-right fdc-bar-caret", "aria-hidden": "true" }) : null
14592
+ cu ? /* @__PURE__ */ (0, import_jsx_runtime104.jsx)("span", { className: "fdc-bar-mini", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime104.jsx)(SegmentedMeter, { total, segments: cu.segments, height: 4, showTotal: false }) }) : null,
14593
+ /* @__PURE__ */ (0, import_jsx_runtime104.jsx)("span", { className: "fdc-bar-text", title: truncationTitle(bits.join(" \xB7 ")), children: bits.join(" \xB7 ") }),
14594
+ expandable ? /* @__PURE__ */ (0, import_jsx_runtime104.jsx)("i", { className: "ph ph-caret-right fdc-bar-caret", "aria-hidden": "true" }) : null
14475
14595
  ]
14476
14596
  }
14477
14597
  ),
14478
14598
  extras
14479
14599
  ] }),
14480
- /* @__PURE__ */ (0, import_jsx_runtime102.jsx)(
14600
+ /* @__PURE__ */ (0, import_jsx_runtime104.jsx)(
14481
14601
  Popover,
14482
14602
  {
14483
14603
  open: open2,
@@ -14488,15 +14608,15 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
14488
14608
  maxHeight: 460,
14489
14609
  padded: true,
14490
14610
  label: "Usage",
14491
- footer: onClear ? /* @__PURE__ */ (0, import_jsx_runtime102.jsxs)("button", { type: "button", className: "fdc-usage-clear", onClick: () => {
14611
+ footer: onClear ? /* @__PURE__ */ (0, import_jsx_runtime104.jsxs)("button", { type: "button", className: "fdc-usage-clear", onClick: () => {
14492
14612
  setOpen(false);
14493
14613
  onClear();
14494
14614
  }, children: [
14495
- /* @__PURE__ */ (0, import_jsx_runtime102.jsx)("i", { className: "ph ph-trash", "aria-hidden": "true" }),
14615
+ /* @__PURE__ */ (0, import_jsx_runtime104.jsx)("i", { className: "ph ph-trash", "aria-hidden": "true" }),
14496
14616
  "Clear conversation"
14497
14617
  ] }) : void 0,
14498
- children: /* @__PURE__ */ (0, import_jsx_runtime102.jsxs)("div", { className: "fdc-usage", children: [
14499
- cu ? /* @__PURE__ */ (0, import_jsx_runtime102.jsx)("section", { className: "fdc-usage-sec", children: /* @__PURE__ */ (0, import_jsx_runtime102.jsx)(
14618
+ children: /* @__PURE__ */ (0, import_jsx_runtime104.jsxs)("div", { className: "fdc-usage", children: [
14619
+ cu ? /* @__PURE__ */ (0, import_jsx_runtime104.jsx)("section", { className: "fdc-usage-sec", children: /* @__PURE__ */ (0, import_jsx_runtime104.jsx)(
14500
14620
  SegmentedMeter,
14501
14621
  {
14502
14622
  total,
@@ -14508,9 +14628,9 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
14508
14628
  remainderLabel: "Free"
14509
14629
  }
14510
14630
  ) }) : null,
14511
- limits && limits.length ? /* @__PURE__ */ (0, import_jsx_runtime102.jsxs)("section", { className: "fdc-usage-sec", children: [
14512
- /* @__PURE__ */ (0, import_jsx_runtime102.jsx)("h4", { className: "fdc-usage-h", children: "Usage limits" }),
14513
- /* @__PURE__ */ (0, import_jsx_runtime102.jsx)("div", { className: "fdc-usage-rows", children: limits.map((l) => /* @__PURE__ */ (0, import_jsx_runtime102.jsx)(
14631
+ limits && limits.length ? /* @__PURE__ */ (0, import_jsx_runtime104.jsxs)("section", { className: "fdc-usage-sec", children: [
14632
+ /* @__PURE__ */ (0, import_jsx_runtime104.jsx)("h4", { className: "fdc-usage-h", children: "Usage limits" }),
14633
+ /* @__PURE__ */ (0, import_jsx_runtime104.jsx)("div", { className: "fdc-usage-rows", children: limits.map((l) => /* @__PURE__ */ (0, import_jsx_runtime104.jsx)(
14514
14634
  QuotaRow,
14515
14635
  {
14516
14636
  label: l.label,
@@ -14520,25 +14640,25 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
14520
14640
  l.id
14521
14641
  )) })
14522
14642
  ] }) : null,
14523
- stats ? /* @__PURE__ */ (0, import_jsx_runtime102.jsxs)("section", { className: "fdc-usage-sec fdc-usage-stats", children: [
14524
- stats.elapsedMs ? /* @__PURE__ */ (0, import_jsx_runtime102.jsxs)("div", { children: [
14525
- /* @__PURE__ */ (0, import_jsx_runtime102.jsx)("span", { children: "Session" }),
14526
- /* @__PURE__ */ (0, import_jsx_runtime102.jsx)("b", { className: "fd-tabular", children: formatDuration(stats.elapsedMs) })
14643
+ stats ? /* @__PURE__ */ (0, import_jsx_runtime104.jsxs)("section", { className: "fdc-usage-sec fdc-usage-stats", children: [
14644
+ stats.elapsedMs ? /* @__PURE__ */ (0, import_jsx_runtime104.jsxs)("div", { children: [
14645
+ /* @__PURE__ */ (0, import_jsx_runtime104.jsx)("span", { children: "Session" }),
14646
+ /* @__PURE__ */ (0, import_jsx_runtime104.jsx)("b", { className: "fd-tabular", children: formatDuration(stats.elapsedMs) })
14527
14647
  ] }) : null,
14528
- stats.tokens ? /* @__PURE__ */ (0, import_jsx_runtime102.jsxs)("div", { children: [
14529
- /* @__PURE__ */ (0, import_jsx_runtime102.jsx)("span", { children: "Tokens" }),
14530
- /* @__PURE__ */ (0, import_jsx_runtime102.jsx)("b", { className: "fd-tabular", children: stats.tokens.toLocaleString() })
14648
+ stats.tokens ? /* @__PURE__ */ (0, import_jsx_runtime104.jsxs)("div", { children: [
14649
+ /* @__PURE__ */ (0, import_jsx_runtime104.jsx)("span", { children: "Tokens" }),
14650
+ /* @__PURE__ */ (0, import_jsx_runtime104.jsx)("b", { className: "fd-tabular", children: stats.tokens.toLocaleString() })
14531
14651
  ] }) : null,
14532
- stats.costUsd != null ? /* @__PURE__ */ (0, import_jsx_runtime102.jsxs)("div", { children: [
14533
- /* @__PURE__ */ (0, import_jsx_runtime102.jsx)("span", { children: "Cost" }),
14534
- /* @__PURE__ */ (0, import_jsx_runtime102.jsxs)("b", { className: "fd-tabular", children: [
14652
+ stats.costUsd != null ? /* @__PURE__ */ (0, import_jsx_runtime104.jsxs)("div", { children: [
14653
+ /* @__PURE__ */ (0, import_jsx_runtime104.jsx)("span", { children: "Cost" }),
14654
+ /* @__PURE__ */ (0, import_jsx_runtime104.jsxs)("b", { className: "fd-tabular", children: [
14535
14655
  "$",
14536
14656
  Number(stats.costUsd).toFixed(3)
14537
14657
  ] })
14538
14658
  ] }) : null,
14539
- stats.turns ? /* @__PURE__ */ (0, import_jsx_runtime102.jsxs)("div", { children: [
14540
- /* @__PURE__ */ (0, import_jsx_runtime102.jsx)("span", { children: "Turns" }),
14541
- /* @__PURE__ */ (0, import_jsx_runtime102.jsx)("b", { className: "fd-tabular", children: stats.turns })
14659
+ stats.turns ? /* @__PURE__ */ (0, import_jsx_runtime104.jsxs)("div", { children: [
14660
+ /* @__PURE__ */ (0, import_jsx_runtime104.jsx)("span", { children: "Turns" }),
14661
+ /* @__PURE__ */ (0, import_jsx_runtime104.jsx)("b", { className: "fd-tabular", children: stats.turns })
14542
14662
  ] }) : null
14543
14663
  ] }) : null
14544
14664
  ] })
@@ -14577,7 +14697,7 @@ function ModelControls({
14577
14697
  disabled: m.disabled,
14578
14698
  checked: m.id === (current2 && current2.id),
14579
14699
  meta: m.meta,
14580
- shortcut: m.shortcut ? /* @__PURE__ */ (0, import_jsx_runtime102.jsx)(KeyHint, { keys: m.shortcut, size: "sm" }) : void 0,
14700
+ shortcut: m.shortcut ? /* @__PURE__ */ (0, import_jsx_runtime104.jsx)(KeyHint, { keys: m.shortcut, size: "sm" }) : void 0,
14581
14701
  onSelect: () => onModelChange && onModelChange(m.id)
14582
14702
  });
14583
14703
  const items = [{ kind: "section", label: "Models" }].concat(flat.map(item));
@@ -14590,15 +14710,15 @@ function ModelControls({
14590
14710
  items.push({ kind: "section", label: "Fast mode" });
14591
14711
  items.push({
14592
14712
  kind: "custom",
14593
- render: () => /* @__PURE__ */ (0, import_jsx_runtime102.jsxs)("label", { className: "fdc-switchrow", children: [
14594
- /* @__PURE__ */ (0, import_jsx_runtime102.jsx)("span", { children: fastModeLabel }),
14595
- /* @__PURE__ */ (0, import_jsx_runtime102.jsx)("input", { type: "checkbox", className: "fd-sr", checked: !!fastMode, onChange: (e) => onFastModeChange(e.target.checked) }),
14596
- /* @__PURE__ */ (0, import_jsx_runtime102.jsx)("span", { className: "fd-switch-track" + (fastMode ? " is-on" : ""), "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime102.jsx)("span", { className: "fd-switch-thumb" }) })
14713
+ render: () => /* @__PURE__ */ (0, import_jsx_runtime104.jsxs)("label", { className: "fdc-switchrow", children: [
14714
+ /* @__PURE__ */ (0, import_jsx_runtime104.jsx)("span", { children: fastModeLabel }),
14715
+ /* @__PURE__ */ (0, import_jsx_runtime104.jsx)("input", { type: "checkbox", className: "fd-sr", checked: !!fastMode, onChange: (e) => onFastModeChange(e.target.checked) }),
14716
+ /* @__PURE__ */ (0, import_jsx_runtime104.jsx)("span", { className: "fd-switch-track" + (fastMode ? " is-on" : ""), "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime104.jsx)("span", { className: "fd-switch-thumb" }) })
14597
14717
  ] })
14598
14718
  });
14599
14719
  }
14600
- return /* @__PURE__ */ (0, import_jsx_runtime102.jsxs)(React73.Fragment, { children: [
14601
- /* @__PURE__ */ (0, import_jsx_runtime102.jsx)(
14720
+ return /* @__PURE__ */ (0, import_jsx_runtime104.jsxs)(React74.Fragment, { children: [
14721
+ /* @__PURE__ */ (0, import_jsx_runtime104.jsx)(
14602
14722
  MenuButton,
14603
14723
  {
14604
14724
  items,
@@ -14609,7 +14729,7 @@ function ModelControls({
14609
14729
  title: "Choose a model"
14610
14730
  }
14611
14731
  ),
14612
- effortLevels && effortLevels.length ? /* @__PURE__ */ (0, import_jsx_runtime102.jsx)(
14732
+ effortLevels && effortLevels.length ? /* @__PURE__ */ (0, import_jsx_runtime104.jsx)(
14613
14733
  MenuButton,
14614
14734
  {
14615
14735
  placement: "top-end",
@@ -14630,7 +14750,7 @@ function ModelControls({
14630
14750
  }
14631
14751
 
14632
14752
  // src/components/chat/AgentChatPanel.tsx
14633
- var import_jsx_runtime103 = require("react/jsx-runtime");
14753
+ var import_jsx_runtime105 = require("react/jsx-runtime");
14634
14754
  var SURFACES = { sidebar: "is-sidebar", inline: "is-inline", page: "is-page", modal: "is-modal", sheet: "is-sheet" };
14635
14755
  function AgentChatPanel({
14636
14756
  /* required */
@@ -14664,6 +14784,7 @@ function AgentChatPanel({
14664
14784
  packetSchemas,
14665
14785
  packetRenderers,
14666
14786
  onApplyPacket,
14787
+ pendingTimeoutMs,
14667
14788
  onOpenAttachment,
14668
14789
  errorCopy,
14669
14790
  /* composer */
@@ -14714,17 +14835,18 @@ function AgentChatPanel({
14714
14835
  onFeedback,
14715
14836
  onEditMessage
14716
14837
  }) {
14717
- const [panelWidth, setPanelWidth] = React74.useState(width);
14718
- const [applied, setApplied] = React74.useState({});
14719
- const [draft, setDraft] = React74.useState("");
14720
- const dragging = React74.useRef(null);
14721
- React74.useEffect(() => setPanelWidth(width), [width]);
14838
+ const [panelWidth, setPanelWidth] = React75.useState(width);
14839
+ const [applied, setApplied] = React75.useState({});
14840
+ const [draft, setDraft] = React75.useState("");
14841
+ const dragging = React75.useRef(null);
14842
+ React75.useEffect(() => setPanelWidth(width), [width]);
14722
14843
  const engine = useChatEngine({
14723
14844
  contextType,
14724
14845
  contextId,
14725
14846
  apiAdapter,
14726
14847
  initialMessage,
14727
14848
  threadId,
14849
+ pendingTimeoutMs,
14728
14850
  onPacket,
14729
14851
  onThreadReady,
14730
14852
  onError,
@@ -14784,7 +14906,7 @@ function AgentChatPanel({
14784
14906
  onReconnect: engine.reload,
14785
14907
  deadTitle: "The assistant isn\u2019t reachable"
14786
14908
  };
14787
- const sessionBar = /* @__PURE__ */ (0, import_jsx_runtime103.jsx)(
14909
+ const sessionBar = /* @__PURE__ */ (0, import_jsx_runtime105.jsx)(
14788
14910
  ChatSessionBar,
14789
14911
  {
14790
14912
  sessionStats,
@@ -14793,7 +14915,7 @@ function AgentChatPanel({
14793
14915
  onClear: engine.visible.length ? engine.clear : void 0
14794
14916
  }
14795
14917
  );
14796
- const modelControls = /* @__PURE__ */ (0, import_jsx_runtime103.jsx)(
14918
+ const modelControls = /* @__PURE__ */ (0, import_jsx_runtime105.jsx)(
14797
14919
  ModelControls,
14798
14920
  {
14799
14921
  models,
@@ -14808,7 +14930,7 @@ function AgentChatPanel({
14808
14930
  narrow
14809
14931
  }
14810
14932
  );
14811
- const threadMenu = threads && threads.length ? /* @__PURE__ */ (0, import_jsx_runtime103.jsx)(
14933
+ const threadMenu = threads && threads.length ? /* @__PURE__ */ (0, import_jsx_runtime105.jsx)(
14812
14934
  MenuButton,
14813
14935
  {
14814
14936
  variant: "ghost",
@@ -14835,7 +14957,7 @@ function AgentChatPanel({
14835
14957
  })))
14836
14958
  }
14837
14959
  ) : null;
14838
- return /* @__PURE__ */ (0, import_jsx_runtime103.jsxs)(
14960
+ return /* @__PURE__ */ (0, import_jsx_runtime105.jsxs)(
14839
14961
  "aside",
14840
14962
  {
14841
14963
  className: ["fdc-panel", SURFACES[surface] || SURFACES.sidebar, narrow ? "is-narrow" : "", className].filter(Boolean).join(" "),
@@ -14846,7 +14968,7 @@ function AgentChatPanel({
14846
14968
  },
14847
14969
  "aria-label": title,
14848
14970
  children: [
14849
- surface === "sidebar" && resizable ? /* @__PURE__ */ (0, import_jsx_runtime103.jsx)(
14971
+ surface === "sidebar" && resizable ? /* @__PURE__ */ (0, import_jsx_runtime105.jsx)(
14850
14972
  "div",
14851
14973
  {
14852
14974
  className: "fdc-grip",
@@ -14861,20 +14983,20 @@ function AgentChatPanel({
14861
14983
  }
14862
14984
  }
14863
14985
  ) : null,
14864
- showHeader ? /* @__PURE__ */ (0, import_jsx_runtime103.jsxs)("header", { className: "fdc-head", children: [
14865
- /* @__PURE__ */ (0, import_jsx_runtime103.jsx)("span", { className: "fdc-head-mark", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime103.jsx)("i", { className: "ph ph-" + assistantIcon }) }),
14866
- /* @__PURE__ */ (0, import_jsx_runtime103.jsxs)("span", { className: "fdc-head-titles", children: [
14867
- /* @__PURE__ */ (0, import_jsx_runtime103.jsx)("span", { className: "fdc-head-title", title: truncationTitle(title), children: title }),
14868
- subtitle ? /* @__PURE__ */ (0, import_jsx_runtime103.jsx)("span", { className: "fdc-head-sub", title: truncationTitle(subtitle), children: subtitle }) : null
14986
+ showHeader ? /* @__PURE__ */ (0, import_jsx_runtime105.jsxs)("header", { className: "fdc-head", children: [
14987
+ /* @__PURE__ */ (0, import_jsx_runtime105.jsx)("span", { className: "fdc-head-mark", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime105.jsx)("i", { className: "ph ph-" + assistantIcon }) }),
14988
+ /* @__PURE__ */ (0, import_jsx_runtime105.jsxs)("span", { className: "fdc-head-titles", children: [
14989
+ /* @__PURE__ */ (0, import_jsx_runtime105.jsx)("span", { className: "fdc-head-title", title: truncationTitle(title), children: title }),
14990
+ subtitle ? /* @__PURE__ */ (0, import_jsx_runtime105.jsx)("span", { className: "fdc-head-sub", title: truncationTitle(subtitle), children: subtitle }) : null
14869
14991
  ] }),
14870
- /* @__PURE__ */ (0, import_jsx_runtime103.jsxs)("span", { className: "fdc-head-acts", children: [
14992
+ /* @__PURE__ */ (0, import_jsx_runtime105.jsxs)("span", { className: "fdc-head-acts", children: [
14871
14993
  headerActions,
14872
14994
  threadMenu,
14873
- onNewThread ? /* @__PURE__ */ (0, import_jsx_runtime103.jsx)("button", { type: "button", className: "fdc-iconbtn", onClick: onNewThread, "aria-label": "New conversation", title: "New conversation", children: /* @__PURE__ */ (0, import_jsx_runtime103.jsx)("i", { className: "ph ph-plus", "aria-hidden": "true" }) }) : null,
14874
- onClose ? /* @__PURE__ */ (0, import_jsx_runtime103.jsx)("button", { type: "button", className: "fdc-iconbtn", onClick: onClose, "aria-label": "Close panel", title: "Close", children: /* @__PURE__ */ (0, import_jsx_runtime103.jsx)("i", { className: "ph ph-x", "aria-hidden": "true" }) }) : null
14995
+ onNewThread ? /* @__PURE__ */ (0, import_jsx_runtime105.jsx)("button", { type: "button", className: "fdc-iconbtn", onClick: onNewThread, "aria-label": "New conversation", title: "New conversation", children: /* @__PURE__ */ (0, import_jsx_runtime105.jsx)("i", { className: "ph ph-plus", "aria-hidden": "true" }) }) : null,
14996
+ onClose ? /* @__PURE__ */ (0, import_jsx_runtime105.jsx)("button", { type: "button", className: "fdc-iconbtn", onClick: onClose, "aria-label": "Close panel", title: "Close", children: /* @__PURE__ */ (0, import_jsx_runtime105.jsx)("i", { className: "ph ph-x", "aria-hidden": "true" }) }) : null
14875
14997
  ] })
14876
14998
  ] }) : null,
14877
- /* @__PURE__ */ (0, import_jsx_runtime103.jsx)(
14999
+ /* @__PURE__ */ (0, import_jsx_runtime105.jsx)(
14878
15000
  ChatTranscript,
14879
15001
  {
14880
15002
  messages: engine.visible,
@@ -14889,7 +15011,7 @@ function AgentChatPanel({
14889
15011
  renderEmpty
14890
15012
  }
14891
15013
  ),
14892
- /* @__PURE__ */ (0, import_jsx_runtime103.jsx)(
15014
+ /* @__PURE__ */ (0, import_jsx_runtime105.jsx)(
14893
15015
  ChatComposer,
14894
15016
  {
14895
15017
  onSubmit: (text, atts) => engine.send(text, atts),
@@ -14922,8 +15044,8 @@ function AgentChatPanel({
14922
15044
  }
14923
15045
 
14924
15046
  // src/components/files/FileViewer.tsx
14925
- var React75 = __toESM(require("react"), 1);
14926
- var import_jsx_runtime104 = require("react/jsx-runtime");
15047
+ var React76 = __toESM(require("react"), 1);
15048
+ var import_jsx_runtime106 = require("react/jsx-runtime");
14927
15049
  function previewKindOf(file) {
14928
15050
  const mime = (file.mime || "").toLowerCase();
14929
15051
  const ext = extensionOf(file.name || "");
@@ -14979,13 +15101,13 @@ function parseDelimited(text, delimiter) {
14979
15101
  return rows;
14980
15102
  }
14981
15103
  function usePreview(file, kind, resolveUrl) {
14982
- const [state, setState] = React75.useState({ status: "loading" });
14983
- const [attempt, setAttempt] = React75.useState(0);
14984
- const resolveRef = React75.useRef(resolveUrl);
14985
- React75.useEffect(() => {
15104
+ const [state, setState] = React76.useState({ status: "loading" });
15105
+ const [attempt, setAttempt] = React76.useState(0);
15106
+ const resolveRef = React76.useRef(resolveUrl);
15107
+ React76.useEffect(() => {
14986
15108
  resolveRef.current = resolveUrl;
14987
15109
  }, [resolveUrl]);
14988
- React75.useEffect(() => {
15110
+ React76.useEffect(() => {
14989
15111
  if (kind === "none") {
14990
15112
  setState({ status: "ready" });
14991
15113
  return;
@@ -15015,19 +15137,19 @@ function usePreview(file, kind, resolveUrl) {
15015
15137
  if (ac) ac.abort();
15016
15138
  };
15017
15139
  }, [file.id, kind, attempt]);
15018
- return { ...state, retry: React75.useCallback(() => setAttempt((a) => a + 1), []) };
15140
+ return { ...state, retry: React76.useCallback(() => setAttempt((a) => a + 1), []) };
15019
15141
  }
15020
15142
  function PreviewBody({ file, kind, state }) {
15021
- if (kind === "image") return /* @__PURE__ */ (0, import_jsx_runtime104.jsx)("img", { className: "fd-fv-image", src: state.url, alt: file.name || "Preview" });
15022
- if (kind === "pdf") return /* @__PURE__ */ (0, import_jsx_runtime104.jsx)("iframe", { className: "fd-fv-pdf", src: state.url, title: file.name || "PDF preview" });
15023
- if (kind === "markdown") return /* @__PURE__ */ (0, import_jsx_runtime104.jsx)(Markdown, { className: "fd-fv-markdown", source: state.text || "" });
15143
+ if (kind === "image") return /* @__PURE__ */ (0, import_jsx_runtime106.jsx)("img", { className: "fd-fv-image", src: state.url, alt: file.name || "Preview" });
15144
+ if (kind === "pdf") return /* @__PURE__ */ (0, import_jsx_runtime106.jsx)("iframe", { className: "fd-fv-pdf", src: state.url, title: file.name || "PDF preview" });
15145
+ if (kind === "markdown") return /* @__PURE__ */ (0, import_jsx_runtime106.jsx)(Markdown, { className: "fd-fv-markdown", source: state.text || "" });
15024
15146
  if (kind === "json") {
15025
15147
  let pretty = state.text || "";
15026
15148
  try {
15027
15149
  pretty = JSON.stringify(JSON.parse(pretty), null, 2);
15028
15150
  } catch {
15029
15151
  }
15030
- return /* @__PURE__ */ (0, import_jsx_runtime104.jsx)(CodeBlock, { code: pretty, language: "json" });
15152
+ return /* @__PURE__ */ (0, import_jsx_runtime106.jsx)(CodeBlock, { code: pretty, language: "json" });
15031
15153
  }
15032
15154
  if (kind === "csv") {
15033
15155
  const tsv = extensionOf(file.name || "") === "tsv" || (file.mime || "").toLowerCase().includes("tab-separated");
@@ -15035,12 +15157,12 @@ function PreviewBody({ file, kind, state }) {
15035
15157
  const head = rows[0] || [];
15036
15158
  const dataRows = rows.slice(1);
15037
15159
  const shown = dataRows.slice(0, FILE_VIEWER_CSV_ROW_LIMIT);
15038
- return /* @__PURE__ */ (0, import_jsx_runtime104.jsxs)("div", { className: "fd-fv-csv", children: [
15039
- /* @__PURE__ */ (0, import_jsx_runtime104.jsxs)("table", { className: "fd-fv-csv-table", children: [
15040
- /* @__PURE__ */ (0, import_jsx_runtime104.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime104.jsx)("tr", { children: head.map((c, i) => /* @__PURE__ */ (0, import_jsx_runtime104.jsx)("th", { children: c }, i)) }) }),
15041
- /* @__PURE__ */ (0, import_jsx_runtime104.jsx)("tbody", { children: shown.map((r, ri) => /* @__PURE__ */ (0, import_jsx_runtime104.jsx)("tr", { children: head.map((_, ci) => /* @__PURE__ */ (0, import_jsx_runtime104.jsx)("td", { children: r[ci] ?? "" }, ci)) }, ri)) })
15160
+ return /* @__PURE__ */ (0, import_jsx_runtime106.jsxs)("div", { className: "fd-fv-csv", children: [
15161
+ /* @__PURE__ */ (0, import_jsx_runtime106.jsxs)("table", { className: "fd-fv-csv-table", children: [
15162
+ /* @__PURE__ */ (0, import_jsx_runtime106.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime106.jsx)("tr", { children: head.map((c, i) => /* @__PURE__ */ (0, import_jsx_runtime106.jsx)("th", { children: c }, i)) }) }),
15163
+ /* @__PURE__ */ (0, import_jsx_runtime106.jsx)("tbody", { children: shown.map((r, ri) => /* @__PURE__ */ (0, import_jsx_runtime106.jsx)("tr", { children: head.map((_, ci) => /* @__PURE__ */ (0, import_jsx_runtime106.jsx)("td", { children: r[ci] ?? "" }, ci)) }, ri)) })
15042
15164
  ] }),
15043
- dataRows.length > FILE_VIEWER_CSV_ROW_LIMIT ? /* @__PURE__ */ (0, import_jsx_runtime104.jsxs)("p", { className: "fd-fv-csv-note fd-body-sm fd-muted", children: [
15165
+ dataRows.length > FILE_VIEWER_CSV_ROW_LIMIT ? /* @__PURE__ */ (0, import_jsx_runtime106.jsxs)("p", { className: "fd-fv-csv-note fd-body-sm fd-muted", children: [
15044
15166
  "Showing the first ",
15045
15167
  FILE_VIEWER_CSV_ROW_LIMIT.toLocaleString(),
15046
15168
  " of ",
@@ -15049,24 +15171,24 @@ function PreviewBody({ file, kind, state }) {
15049
15171
  ] }) : null
15050
15172
  ] });
15051
15173
  }
15052
- if (kind === "text") return /* @__PURE__ */ (0, import_jsx_runtime104.jsx)(CodeBlock, { code: state.text || "", language: extensionOf(file.name || "") || void 0 });
15053
- return /* @__PURE__ */ (0, import_jsx_runtime104.jsxs)("div", { className: "fd-fv-fallback", children: [
15054
- /* @__PURE__ */ (0, import_jsx_runtime104.jsx)("span", { className: "fd-fv-fallback-icon", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime104.jsx)("i", { className: "ph ph-" + iconForMime(file.mime, file.name) }) }),
15055
- /* @__PURE__ */ (0, import_jsx_runtime104.jsx)("span", { className: "fd-fv-fallback-title", children: "No preview available" }),
15056
- /* @__PURE__ */ (0, import_jsx_runtime104.jsxs)("span", { className: "fd-fv-fallback-meta", children: [
15174
+ if (kind === "text") return /* @__PURE__ */ (0, import_jsx_runtime106.jsx)(CodeBlock, { code: state.text || "", language: extensionOf(file.name || "") || void 0 });
15175
+ return /* @__PURE__ */ (0, import_jsx_runtime106.jsxs)("div", { className: "fd-fv-fallback", children: [
15176
+ /* @__PURE__ */ (0, import_jsx_runtime106.jsx)("span", { className: "fd-fv-fallback-icon", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime106.jsx)("i", { className: "ph ph-" + iconForMime(file.mime, file.name) }) }),
15177
+ /* @__PURE__ */ (0, import_jsx_runtime106.jsx)("span", { className: "fd-fv-fallback-title", children: "No preview available" }),
15178
+ /* @__PURE__ */ (0, import_jsx_runtime106.jsxs)("span", { className: "fd-fv-fallback-meta", children: [
15057
15179
  file.mime || "Unknown type",
15058
15180
  file.size ? " \xB7 " + formatBytes(file.size) : ""
15059
15181
  ] })
15060
15182
  ] });
15061
15183
  }
15062
15184
  function FileViewer({ file, resolveUrl, sidePanel, sidePanelLabel = "Details", onClose, actions, className = "" }) {
15063
- const kind = React75.useMemo(() => previewKindOf(file), [file]);
15185
+ const kind = React76.useMemo(() => previewKindOf(file), [file]);
15064
15186
  const preview = usePreview(file, kind, resolveUrl);
15065
- const [tab, setTab] = React75.useState("preview");
15066
- const [downloading, setDownloading] = React75.useState(false);
15067
- const [downloadError, setDownloadError] = React75.useState(null);
15187
+ const [tab, setTab] = React76.useState("preview");
15188
+ const [downloading, setDownloading] = React76.useState(false);
15189
+ const [downloadError, setDownloadError] = React76.useState(null);
15068
15190
  const hasSide = sidePanel != null;
15069
- React75.useEffect(() => {
15191
+ React76.useEffect(() => {
15070
15192
  setTab("preview");
15071
15193
  }, [file.id]);
15072
15194
  const download = () => {
@@ -15082,29 +15204,29 @@ function FileViewer({ file, resolveUrl, sidePanel, sidePanelLabel = "Details", o
15082
15204
  a.remove();
15083
15205
  }).catch((err) => setDownloadError(err && err.message || "Download failed.")).finally(() => setDownloading(false));
15084
15206
  };
15085
- return /* @__PURE__ */ (0, import_jsx_runtime104.jsxs)(
15207
+ return /* @__PURE__ */ (0, import_jsx_runtime106.jsxs)(
15086
15208
  "section",
15087
15209
  {
15088
15210
  className: ["fd-fv", hasSide && tab === "side" ? "is-tab-side" : "is-tab-preview", className].filter(Boolean).join(" "),
15089
15211
  "aria-label": file.name || "File",
15090
15212
  children: [
15091
- /* @__PURE__ */ (0, import_jsx_runtime104.jsxs)("header", { className: "fd-fv-head", children: [
15092
- /* @__PURE__ */ (0, import_jsx_runtime104.jsx)("span", { className: "fd-fv-head-icon", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime104.jsx)("i", { className: "ph ph-" + iconForMime(file.mime, file.name) }) }),
15093
- /* @__PURE__ */ (0, import_jsx_runtime104.jsxs)("span", { className: "fd-fv-head-titles", children: [
15094
- /* @__PURE__ */ (0, import_jsx_runtime104.jsx)("span", { className: "fd-fv-head-title", title: file.name, children: file.name }),
15095
- /* @__PURE__ */ (0, import_jsx_runtime104.jsxs)("span", { className: "fd-fv-head-meta", children: [
15213
+ /* @__PURE__ */ (0, import_jsx_runtime106.jsxs)("header", { className: "fd-fv-head", children: [
15214
+ /* @__PURE__ */ (0, import_jsx_runtime106.jsx)("span", { className: "fd-fv-head-icon", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime106.jsx)("i", { className: "ph ph-" + iconForMime(file.mime, file.name) }) }),
15215
+ /* @__PURE__ */ (0, import_jsx_runtime106.jsxs)("span", { className: "fd-fv-head-titles", children: [
15216
+ /* @__PURE__ */ (0, import_jsx_runtime106.jsx)("span", { className: "fd-fv-head-title", title: file.name, children: file.name }),
15217
+ /* @__PURE__ */ (0, import_jsx_runtime106.jsxs)("span", { className: "fd-fv-head-meta", children: [
15096
15218
  file.mime || "Unknown type",
15097
15219
  file.size ? " \xB7 " + formatBytes(file.size) : ""
15098
15220
  ] })
15099
15221
  ] }),
15100
- /* @__PURE__ */ (0, import_jsx_runtime104.jsxs)("span", { className: "fd-fv-head-actions", children: [
15222
+ /* @__PURE__ */ (0, import_jsx_runtime106.jsxs)("span", { className: "fd-fv-head-actions", children: [
15101
15223
  actions,
15102
- /* @__PURE__ */ (0, import_jsx_runtime104.jsx)(Button, { variant: "secondary", size: "sm", icon: "download-simple", loading: downloading, onClick: download, children: "Download" }),
15103
- onClose ? /* @__PURE__ */ (0, import_jsx_runtime104.jsx)(IconButton, { icon: "x", label: "Close", onClick: onClose }) : null
15224
+ /* @__PURE__ */ (0, import_jsx_runtime106.jsx)(Button, { variant: "secondary", size: "sm", icon: "download-simple", loading: downloading, onClick: download, children: "Download" }),
15225
+ onClose ? /* @__PURE__ */ (0, import_jsx_runtime106.jsx)(IconButton, { icon: "x", label: "Close", onClick: onClose }) : null
15104
15226
  ] })
15105
15227
  ] }),
15106
- downloadError ? /* @__PURE__ */ (0, import_jsx_runtime104.jsx)("div", { className: "fd-fv-download-error", role: "alert", children: downloadError }) : null,
15107
- hasSide ? /* @__PURE__ */ (0, import_jsx_runtime104.jsx)(
15228
+ downloadError ? /* @__PURE__ */ (0, import_jsx_runtime106.jsx)("div", { className: "fd-fv-download-error", role: "alert", children: downloadError }) : null,
15229
+ hasSide ? /* @__PURE__ */ (0, import_jsx_runtime106.jsx)(
15108
15230
  Tabs,
15109
15231
  {
15110
15232
  className: "fd-fv-tabs",
@@ -15113,19 +15235,19 @@ function FileViewer({ file, resolveUrl, sidePanel, sidePanelLabel = "Details", o
15113
15235
  onChange: (v) => setTab(v)
15114
15236
  }
15115
15237
  ) : null,
15116
- /* @__PURE__ */ (0, import_jsx_runtime104.jsxs)("div", { className: "fd-fv-body", children: [
15117
- /* @__PURE__ */ (0, import_jsx_runtime104.jsx)("div", { className: "fd-fv-preview", role: "region", "aria-label": "Preview of " + (file.name || "file"), children: /* @__PURE__ */ (0, import_jsx_runtime104.jsx)(
15238
+ /* @__PURE__ */ (0, import_jsx_runtime106.jsxs)("div", { className: "fd-fv-body", children: [
15239
+ /* @__PURE__ */ (0, import_jsx_runtime106.jsx)("div", { className: "fd-fv-preview", role: "region", "aria-label": "Preview of " + (file.name || "file"), children: /* @__PURE__ */ (0, import_jsx_runtime106.jsx)(
15118
15240
  LoadingRegion,
15119
15241
  {
15120
15242
  state: preview.status === "loading" ? "loading" : preview.status === "error" ? "error" : "ready",
15121
15243
  error: preview.error,
15122
15244
  label: "Loading preview of " + (file.name || "file"),
15123
15245
  onRetry: preview.status === "error" ? preview.retry : void 0,
15124
- skeleton: /* @__PURE__ */ (0, import_jsx_runtime104.jsx)(Skeleton, { shape: "card", h: 220 }),
15125
- children: /* @__PURE__ */ (0, import_jsx_runtime104.jsx)(PreviewBody, { file, kind, state: preview })
15246
+ skeleton: /* @__PURE__ */ (0, import_jsx_runtime106.jsx)(Skeleton, { shape: "card", h: 220 }),
15247
+ children: /* @__PURE__ */ (0, import_jsx_runtime106.jsx)(PreviewBody, { file, kind, state: preview })
15126
15248
  }
15127
15249
  ) }),
15128
- hasSide ? /* @__PURE__ */ (0, import_jsx_runtime104.jsx)("div", { className: "fd-fv-side", role: "region", "aria-label": sidePanelLabel, children: sidePanel }) : null
15250
+ hasSide ? /* @__PURE__ */ (0, import_jsx_runtime106.jsx)("div", { className: "fd-fv-side", role: "region", "aria-label": sidePanelLabel, children: sidePanel }) : null
15129
15251
  ] })
15130
15252
  ]
15131
15253
  }
@@ -15133,8 +15255,8 @@ function FileViewer({ file, resolveUrl, sidePanel, sidePanelLabel = "Details", o
15133
15255
  }
15134
15256
 
15135
15257
  // src/components/files/FileBrowser.tsx
15136
- var React76 = __toESM(require("react"), 1);
15137
- var import_jsx_runtime105 = require("react/jsx-runtime");
15258
+ var React77 = __toESM(require("react"), 1);
15259
+ var import_jsx_runtime107 = require("react/jsx-runtime");
15138
15260
  function childrenOf(folders, parentId) {
15139
15261
  return folders.filter((f) => f.parentId === parentId).sort((a, b) => a.name.localeCompare(b.name));
15140
15262
  }
@@ -15206,8 +15328,8 @@ function FolderPickerMenu({
15206
15328
  }) {
15207
15329
  const panel = useInlinePanel();
15208
15330
  const { open: open2, setOpen, ref } = panel;
15209
- return /* @__PURE__ */ (0, import_jsx_runtime105.jsxs)("span", { className: "fd-fb-menu-anchor", ref, children: [
15210
- /* @__PURE__ */ (0, import_jsx_runtime105.jsx)(
15331
+ return /* @__PURE__ */ (0, import_jsx_runtime107.jsxs)("span", { className: "fd-fb-menu-anchor", ref, children: [
15332
+ /* @__PURE__ */ (0, import_jsx_runtime107.jsx)(
15211
15333
  IconButton,
15212
15334
  {
15213
15335
  icon: "arrows-out-cardinal",
@@ -15219,9 +15341,9 @@ function FolderPickerMenu({
15219
15341
  onClick: () => setOpen((v) => !v)
15220
15342
  }
15221
15343
  ),
15222
- /* @__PURE__ */ (0, import_jsx_runtime105.jsx)(InlinePanelSurface, { panel, align: "right", offset: 4, width: 220, maxHeight: 280, role: "menu", label, children: /* @__PURE__ */ (0, import_jsx_runtime105.jsxs)("div", { className: "fd-fb-menu", children: [
15223
- /* @__PURE__ */ (0, import_jsx_runtime105.jsx)("span", { className: "fd-overline fd-muted fd-fb-menu-title", children: "Move to\u2026" }),
15224
- destinations.map((d) => /* @__PURE__ */ (0, import_jsx_runtime105.jsxs)(
15344
+ /* @__PURE__ */ (0, import_jsx_runtime107.jsx)(InlinePanelSurface, { panel, align: "right", offset: 4, width: 220, maxHeight: 280, role: "menu", label, children: /* @__PURE__ */ (0, import_jsx_runtime107.jsxs)("div", { className: "fd-fb-menu", children: [
15345
+ /* @__PURE__ */ (0, import_jsx_runtime107.jsx)("span", { className: "fd-overline fd-muted fd-fb-menu-title", children: "Move to\u2026" }),
15346
+ destinations.map((d) => /* @__PURE__ */ (0, import_jsx_runtime107.jsxs)(
15225
15347
  "button",
15226
15348
  {
15227
15349
  type: "button",
@@ -15233,7 +15355,7 @@ function FolderPickerMenu({
15233
15355
  setOpen(false);
15234
15356
  },
15235
15357
  children: [
15236
- /* @__PURE__ */ (0, import_jsx_runtime105.jsx)("i", { className: "ph ph-" + (d.id == null ? "house-simple" : "folder-simple"), "aria-hidden": "true" }),
15358
+ /* @__PURE__ */ (0, import_jsx_runtime107.jsx)("i", { className: "ph ph-" + (d.id == null ? "house-simple" : "folder-simple"), "aria-hidden": "true" }),
15237
15359
  d.name
15238
15360
  ]
15239
15361
  },
@@ -15243,8 +15365,8 @@ function FolderPickerMenu({
15243
15365
  ] });
15244
15366
  }
15245
15367
  function RowShell({ icon, name, meta, onOpen, draggableId, isDropTarget, onDropPayload, actions, className = "" }) {
15246
- const [over, setOver] = React76.useState(false);
15247
- const dragCounter = React76.useRef(0);
15368
+ const [over, setOver] = React77.useState(false);
15369
+ const dragCounter = React77.useRef(0);
15248
15370
  const dropHandlers = isDropTarget ? {
15249
15371
  onDragEnter: (e) => {
15250
15372
  if (!hasInternalPayload(e)) return;
@@ -15269,8 +15391,8 @@ function RowShell({ icon, name, meta, onOpen, draggableId, isDropTarget, onDropP
15269
15391
  if (payload && onDropPayload) onDropPayload(payload);
15270
15392
  }
15271
15393
  } : {};
15272
- return /* @__PURE__ */ (0, import_jsx_runtime105.jsxs)("div", { className: ["fd-fb-row", over ? "is-drop-target" : "", className].filter(Boolean).join(" "), ...dropHandlers, children: [
15273
- /* @__PURE__ */ (0, import_jsx_runtime105.jsxs)(
15394
+ return /* @__PURE__ */ (0, import_jsx_runtime107.jsxs)("div", { className: ["fd-fb-row", over ? "is-drop-target" : "", className].filter(Boolean).join(" "), ...dropHandlers, children: [
15395
+ /* @__PURE__ */ (0, import_jsx_runtime107.jsxs)(
15274
15396
  "button",
15275
15397
  {
15276
15398
  type: "button",
@@ -15279,26 +15401,26 @@ function RowShell({ icon, name, meta, onOpen, draggableId, isDropTarget, onDropP
15279
15401
  draggable: !!draggableId,
15280
15402
  onDragStart: draggableId ? (e) => writeDragPayload(e, draggableId) : void 0,
15281
15403
  children: [
15282
- /* @__PURE__ */ (0, import_jsx_runtime105.jsx)("span", { className: "fd-fb-row-icon", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime105.jsx)("i", { className: "ph ph-" + icon }) }),
15283
- /* @__PURE__ */ (0, import_jsx_runtime105.jsxs)("span", { className: "fd-fb-row-text", children: [
15284
- /* @__PURE__ */ (0, import_jsx_runtime105.jsx)("span", { className: "fd-fb-row-name", title: name, children: name }),
15285
- meta ? /* @__PURE__ */ (0, import_jsx_runtime105.jsx)("span", { className: "fd-fb-row-meta", children: meta }) : null
15404
+ /* @__PURE__ */ (0, import_jsx_runtime107.jsx)("span", { className: "fd-fb-row-icon", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime107.jsx)("i", { className: "ph ph-" + icon }) }),
15405
+ /* @__PURE__ */ (0, import_jsx_runtime107.jsxs)("span", { className: "fd-fb-row-text", children: [
15406
+ /* @__PURE__ */ (0, import_jsx_runtime107.jsx)("span", { className: "fd-fb-row-name", title: name, children: name }),
15407
+ meta ? /* @__PURE__ */ (0, import_jsx_runtime107.jsx)("span", { className: "fd-fb-row-meta", children: meta }) : null
15286
15408
  ] })
15287
15409
  ]
15288
15410
  }
15289
15411
  ),
15290
- actions ? /* @__PURE__ */ (0, import_jsx_runtime105.jsx)("span", { className: "fd-fb-row-actions", children: actions }) : null
15412
+ actions ? /* @__PURE__ */ (0, import_jsx_runtime107.jsx)("span", { className: "fd-fb-row-actions", children: actions }) : null
15291
15413
  ] });
15292
15414
  }
15293
15415
  function TreeNode({ folder, depth, folders, currentFolderId, onNavigate, onMoveInto, canMove }) {
15294
15416
  const kids = childrenOf(folders, folder.id);
15295
- const [expanded, setExpanded] = React76.useState(() => currentFolderId != null && isSelfOrDescendant(folders, folder.id, currentFolderId));
15296
- React76.useEffect(() => {
15417
+ const [expanded, setExpanded] = React77.useState(() => currentFolderId != null && isSelfOrDescendant(folders, folder.id, currentFolderId));
15418
+ React77.useEffect(() => {
15297
15419
  if (currentFolderId != null && isSelfOrDescendant(folders, folder.id, currentFolderId)) setExpanded(true);
15298
15420
  }, [currentFolderId, folder.id, folders]);
15299
15421
  const isCurrent = folder.id === currentFolderId;
15300
- return /* @__PURE__ */ (0, import_jsx_runtime105.jsxs)("div", { className: "fd-fb-tree-node", children: [
15301
- /* @__PURE__ */ (0, import_jsx_runtime105.jsx)(
15422
+ return /* @__PURE__ */ (0, import_jsx_runtime107.jsxs)("div", { className: "fd-fb-tree-node", children: [
15423
+ /* @__PURE__ */ (0, import_jsx_runtime107.jsx)(
15302
15424
  RowShell,
15303
15425
  {
15304
15426
  icon: folder.id === currentFolderId ? "folder-open" : "folder-simple",
@@ -15308,7 +15430,7 @@ function TreeNode({ folder, depth, folders, currentFolderId, onNavigate, onMoveI
15308
15430
  isDropTarget: canMove,
15309
15431
  onDropPayload: (payload) => onMoveInto(payload, folder.id),
15310
15432
  className: ["fd-fb-tree-row", isCurrent ? "is-current" : ""].filter(Boolean).join(" "),
15311
- actions: kids.length ? /* @__PURE__ */ (0, import_jsx_runtime105.jsx)(
15433
+ actions: kids.length ? /* @__PURE__ */ (0, import_jsx_runtime107.jsx)(
15312
15434
  IconButton,
15313
15435
  {
15314
15436
  icon: expanded ? "caret-down" : "caret-right",
@@ -15320,7 +15442,7 @@ function TreeNode({ folder, depth, folders, currentFolderId, onNavigate, onMoveI
15320
15442
  ) : void 0
15321
15443
  }
15322
15444
  ),
15323
- expanded && kids.length ? /* @__PURE__ */ (0, import_jsx_runtime105.jsx)("div", { className: "fd-fb-tree-children", style: { paddingLeft: 14 }, children: kids.map((k) => /* @__PURE__ */ (0, import_jsx_runtime105.jsx)(
15445
+ expanded && kids.length ? /* @__PURE__ */ (0, import_jsx_runtime107.jsx)("div", { className: "fd-fb-tree-children", style: { paddingLeft: 14 }, children: kids.map((k) => /* @__PURE__ */ (0, import_jsx_runtime107.jsx)(
15324
15446
  TreeNode,
15325
15447
  {
15326
15448
  folder: k,
@@ -15359,15 +15481,15 @@ function FileBrowser({
15359
15481
  const canUpload = perm.canUpload !== false && !!onUpload;
15360
15482
  const canRemoveFile = perm.canRemoveFile !== false && !!onRemoveFile;
15361
15483
  const canDeleteFolder = perm.canDeleteFolder !== false && !!onDeleteFolder;
15362
- const [createOpen, setCreateOpen] = React76.useState(false);
15363
- const [createName, setCreateName] = React76.useState("");
15364
- const [renameTarget, setRenameTarget] = React76.useState(null);
15365
- const [renameValue, setRenameValue] = React76.useState("");
15366
- const [deleteTarget, setDeleteTarget] = React76.useState(null);
15367
- const uploadInputRef = React76.useRef(null);
15368
- const crumbFolders = React76.useMemo(() => ancestorsOf(folders, currentFolderId), [folders, currentFolderId]);
15369
- const subfolders = React76.useMemo(() => childrenOf(folders, currentFolderId), [folders, currentFolderId]);
15370
- const currentFiles = React76.useMemo(
15484
+ const [createOpen, setCreateOpen] = React77.useState(false);
15485
+ const [createName, setCreateName] = React77.useState("");
15486
+ const [renameTarget, setRenameTarget] = React77.useState(null);
15487
+ const [renameValue, setRenameValue] = React77.useState("");
15488
+ const [deleteTarget, setDeleteTarget] = React77.useState(null);
15489
+ const uploadInputRef = React77.useRef(null);
15490
+ const crumbFolders = React77.useMemo(() => ancestorsOf(folders, currentFolderId), [folders, currentFolderId]);
15491
+ const subfolders = React77.useMemo(() => childrenOf(folders, currentFolderId), [folders, currentFolderId]);
15492
+ const currentFiles = React77.useMemo(
15371
15493
  () => files.filter((f) => f.folderId === currentFolderId).sort((a, b) => a.name.localeCompare(b.name)),
15372
15494
  [files, currentFolderId]
15373
15495
  );
@@ -15406,10 +15528,10 @@ function FileBrowser({
15406
15528
  if (deleteTarget && onDeleteFolder) onDeleteFolder(deleteTarget);
15407
15529
  setDeleteTarget(null);
15408
15530
  };
15409
- const content = /* @__PURE__ */ (0, import_jsx_runtime105.jsxs)("div", { className: ["fd-fb", className].filter(Boolean).join(" "), children: [
15410
- /* @__PURE__ */ (0, import_jsx_runtime105.jsxs)("div", { className: "fd-fb-head", children: [
15411
- /* @__PURE__ */ (0, import_jsx_runtime105.jsxs)("nav", { className: "fd-fb-crumbs", "aria-label": "Folder path", children: [
15412
- /* @__PURE__ */ (0, import_jsx_runtime105.jsx)(
15531
+ const content = /* @__PURE__ */ (0, import_jsx_runtime107.jsxs)("div", { className: ["fd-fb", className].filter(Boolean).join(" "), children: [
15532
+ /* @__PURE__ */ (0, import_jsx_runtime107.jsxs)("div", { className: "fd-fb-head", children: [
15533
+ /* @__PURE__ */ (0, import_jsx_runtime107.jsxs)("nav", { className: "fd-fb-crumbs", "aria-label": "Folder path", children: [
15534
+ /* @__PURE__ */ (0, import_jsx_runtime107.jsx)(
15413
15535
  BreadcrumbCrumb,
15414
15536
  {
15415
15537
  label: "Home",
@@ -15419,7 +15541,7 @@ function FileBrowser({
15419
15541
  onDropPayload: (p) => moveIntoFolder(p, null)
15420
15542
  }
15421
15543
  ),
15422
- crumbFolders.map((f, i) => /* @__PURE__ */ (0, import_jsx_runtime105.jsx)(
15544
+ crumbFolders.map((f, i) => /* @__PURE__ */ (0, import_jsx_runtime107.jsx)(
15423
15545
  BreadcrumbCrumb,
15424
15546
  {
15425
15547
  label: f.name,
@@ -15431,11 +15553,11 @@ function FileBrowser({
15431
15553
  f.id
15432
15554
  ))
15433
15555
  ] }),
15434
- /* @__PURE__ */ (0, import_jsx_runtime105.jsxs)("span", { className: "fd-fb-actions", children: [
15435
- canCreateFolder ? /* @__PURE__ */ (0, import_jsx_runtime105.jsx)(Button, { variant: "secondary", size: "sm", icon: "folder-simple-plus", onClick: openCreate, children: "New folder" }) : null,
15436
- canUpload ? /* @__PURE__ */ (0, import_jsx_runtime105.jsxs)(import_jsx_runtime105.Fragment, { children: [
15437
- /* @__PURE__ */ (0, import_jsx_runtime105.jsx)(Button, { variant: "secondary", size: "sm", icon: "upload-simple", onClick: () => uploadInputRef.current && uploadInputRef.current.click(), children: "Upload" }),
15438
- /* @__PURE__ */ (0, import_jsx_runtime105.jsx)(
15556
+ /* @__PURE__ */ (0, import_jsx_runtime107.jsxs)("span", { className: "fd-fb-actions", children: [
15557
+ canCreateFolder ? /* @__PURE__ */ (0, import_jsx_runtime107.jsx)(Button, { variant: "secondary", size: "sm", icon: "folder-simple-plus", onClick: openCreate, children: "New folder" }) : null,
15558
+ canUpload ? /* @__PURE__ */ (0, import_jsx_runtime107.jsxs)(import_jsx_runtime107.Fragment, { children: [
15559
+ /* @__PURE__ */ (0, import_jsx_runtime107.jsx)(Button, { variant: "secondary", size: "sm", icon: "upload-simple", onClick: () => uploadInputRef.current && uploadInputRef.current.click(), children: "Upload" }),
15560
+ /* @__PURE__ */ (0, import_jsx_runtime107.jsx)(
15439
15561
  "input",
15440
15562
  {
15441
15563
  ref: uploadInputRef,
@@ -15453,9 +15575,9 @@ function FileBrowser({
15453
15575
  ] }) : null
15454
15576
  ] })
15455
15577
  ] }),
15456
- /* @__PURE__ */ (0, import_jsx_runtime105.jsxs)("div", { className: "fd-fb-body", children: [
15457
- /* @__PURE__ */ (0, import_jsx_runtime105.jsxs)("div", { className: "fd-fb-tree", role: "region", "aria-label": "Folder tree", children: [
15458
- /* @__PURE__ */ (0, import_jsx_runtime105.jsx)(
15578
+ /* @__PURE__ */ (0, import_jsx_runtime107.jsxs)("div", { className: "fd-fb-body", children: [
15579
+ /* @__PURE__ */ (0, import_jsx_runtime107.jsxs)("div", { className: "fd-fb-tree", role: "region", "aria-label": "Folder tree", children: [
15580
+ /* @__PURE__ */ (0, import_jsx_runtime107.jsx)(
15459
15581
  RowShell,
15460
15582
  {
15461
15583
  icon: "house-simple",
@@ -15466,7 +15588,7 @@ function FileBrowser({
15466
15588
  className: ["fd-fb-tree-row", currentFolderId == null ? "is-current" : ""].filter(Boolean).join(" ")
15467
15589
  }
15468
15590
  ),
15469
- childrenOf(folders, null).map((f) => /* @__PURE__ */ (0, import_jsx_runtime105.jsx)(
15591
+ childrenOf(folders, null).map((f) => /* @__PURE__ */ (0, import_jsx_runtime107.jsx)(
15470
15592
  TreeNode,
15471
15593
  {
15472
15594
  folder: f,
@@ -15480,18 +15602,18 @@ function FileBrowser({
15480
15602
  f.id
15481
15603
  ))
15482
15604
  ] }),
15483
- /* @__PURE__ */ (0, import_jsx_runtime105.jsx)("div", { className: "fd-fb-main", role: "region", "aria-label": "Folder contents", children: /* @__PURE__ */ (0, import_jsx_runtime105.jsx)(
15605
+ /* @__PURE__ */ (0, import_jsx_runtime107.jsx)("div", { className: "fd-fb-main", role: "region", "aria-label": "Folder contents", children: /* @__PURE__ */ (0, import_jsx_runtime107.jsx)(
15484
15606
  LoadingRegion,
15485
15607
  {
15486
15608
  state: loading ? "loading" : "ready",
15487
15609
  label: "Loading folder contents",
15488
- skeleton: /* @__PURE__ */ (0, import_jsx_runtime105.jsxs)("div", { className: "fd-stack", style: { gap: 8, padding: 12 }, children: [
15489
- /* @__PURE__ */ (0, import_jsx_runtime105.jsx)(Skeleton, { h: 44, radius: "10px" }),
15490
- /* @__PURE__ */ (0, import_jsx_runtime105.jsx)(Skeleton, { h: 44, radius: "10px" }),
15491
- /* @__PURE__ */ (0, import_jsx_runtime105.jsx)(Skeleton, { h: 44, radius: "10px" })
15610
+ skeleton: /* @__PURE__ */ (0, import_jsx_runtime107.jsxs)("div", { className: "fd-stack", style: { gap: 8, padding: 12 }, children: [
15611
+ /* @__PURE__ */ (0, import_jsx_runtime107.jsx)(Skeleton, { h: 44, radius: "10px" }),
15612
+ /* @__PURE__ */ (0, import_jsx_runtime107.jsx)(Skeleton, { h: 44, radius: "10px" }),
15613
+ /* @__PURE__ */ (0, import_jsx_runtime107.jsx)(Skeleton, { h: 44, radius: "10px" })
15492
15614
  ] }),
15493
- children: isEmpty ? /* @__PURE__ */ (0, import_jsx_runtime105.jsx)(EmptyState, { icon: "folder-open", title: "This folder is empty", children: canUpload ? "Drop files here, or use Upload above." : "Nothing has been filed here yet." }) : /* @__PURE__ */ (0, import_jsx_runtime105.jsxs)("div", { className: "fd-fb-list", children: [
15494
- subfolders.map((f) => /* @__PURE__ */ (0, import_jsx_runtime105.jsx)(
15615
+ children: isEmpty ? /* @__PURE__ */ (0, import_jsx_runtime107.jsx)(EmptyState, { icon: "folder-open", title: "This folder is empty", children: canUpload ? "Drop files here, or use Upload above." : "Nothing has been filed here yet." }) : /* @__PURE__ */ (0, import_jsx_runtime107.jsxs)("div", { className: "fd-fb-list", children: [
15616
+ subfolders.map((f) => /* @__PURE__ */ (0, import_jsx_runtime107.jsx)(
15495
15617
  RowShell,
15496
15618
  {
15497
15619
  icon: "folder-simple",
@@ -15500,9 +15622,9 @@ function FileBrowser({
15500
15622
  draggableId: canMove ? { kind: "folder", id: f.id } : void 0,
15501
15623
  isDropTarget: canMove,
15502
15624
  onDropPayload: (p) => moveIntoFolder(p, f.id),
15503
- actions: /* @__PURE__ */ (0, import_jsx_runtime105.jsxs)(import_jsx_runtime105.Fragment, { children: [
15504
- canRenameFolder ? /* @__PURE__ */ (0, import_jsx_runtime105.jsx)(IconButton, { icon: "pencil-simple", label: "Rename " + f.name, size: "sm", variant: "ghost", onClick: () => openRename(f) }) : null,
15505
- canMove ? /* @__PURE__ */ (0, import_jsx_runtime105.jsx)(
15625
+ actions: /* @__PURE__ */ (0, import_jsx_runtime107.jsxs)(import_jsx_runtime107.Fragment, { children: [
15626
+ canRenameFolder ? /* @__PURE__ */ (0, import_jsx_runtime107.jsx)(IconButton, { icon: "pencil-simple", label: "Rename " + f.name, size: "sm", variant: "ghost", onClick: () => openRename(f) }) : null,
15627
+ canMove ? /* @__PURE__ */ (0, import_jsx_runtime107.jsx)(
15506
15628
  FolderPickerMenu,
15507
15629
  {
15508
15630
  label: "Move " + f.name,
@@ -15510,12 +15632,12 @@ function FileBrowser({
15510
15632
  onPick: (target) => moveIntoFolder({ kind: "folder", id: f.id }, target)
15511
15633
  }
15512
15634
  ) : null,
15513
- canDeleteFolder ? /* @__PURE__ */ (0, import_jsx_runtime105.jsx)(IconButton, { icon: "trash-simple", label: "Delete " + f.name, size: "sm", variant: "ghost", onClick: () => openDelete(f) }) : null
15635
+ canDeleteFolder ? /* @__PURE__ */ (0, import_jsx_runtime107.jsx)(IconButton, { icon: "trash-simple", label: "Delete " + f.name, size: "sm", variant: "ghost", onClick: () => openDelete(f) }) : null
15514
15636
  ] })
15515
15637
  },
15516
15638
  f.id
15517
15639
  )),
15518
- currentFiles.map((file) => /* @__PURE__ */ (0, import_jsx_runtime105.jsx)(
15640
+ currentFiles.map((file) => /* @__PURE__ */ (0, import_jsx_runtime107.jsx)(
15519
15641
  RowShell,
15520
15642
  {
15521
15643
  icon: iconForMime(file.mime, file.name),
@@ -15523,8 +15645,8 @@ function FileBrowser({
15523
15645
  meta: file.size ? formatBytes(file.size) : void 0,
15524
15646
  onOpen: onOpenFile ? () => onOpenFile(file) : void 0,
15525
15647
  draggableId: canMove ? { kind: "file", id: file.id } : void 0,
15526
- actions: /* @__PURE__ */ (0, import_jsx_runtime105.jsxs)(import_jsx_runtime105.Fragment, { children: [
15527
- canMove ? /* @__PURE__ */ (0, import_jsx_runtime105.jsx)(
15648
+ actions: /* @__PURE__ */ (0, import_jsx_runtime107.jsxs)(import_jsx_runtime107.Fragment, { children: [
15649
+ canMove ? /* @__PURE__ */ (0, import_jsx_runtime107.jsx)(
15528
15650
  FolderPickerMenu,
15529
15651
  {
15530
15652
  label: "Move " + file.name,
@@ -15532,7 +15654,7 @@ function FileBrowser({
15532
15654
  onPick: (target) => onMoveFile && onMoveFile(file.id, target)
15533
15655
  }
15534
15656
  ) : null,
15535
- canRemoveFile ? /* @__PURE__ */ (0, import_jsx_runtime105.jsx)(IconButton, { icon: "trash-simple", label: "Remove " + file.name, size: "sm", variant: "ghost", onClick: () => onRemoveFile && onRemoveFile(file) }) : null
15657
+ canRemoveFile ? /* @__PURE__ */ (0, import_jsx_runtime107.jsx)(IconButton, { icon: "trash-simple", label: "Remove " + file.name, size: "sm", variant: "ghost", onClick: () => onRemoveFile && onRemoveFile(file) }) : null
15536
15658
  ] })
15537
15659
  },
15538
15660
  file.id
@@ -15541,10 +15663,10 @@ function FileBrowser({
15541
15663
  }
15542
15664
  ) })
15543
15665
  ] }),
15544
- /* @__PURE__ */ (0, import_jsx_runtime105.jsx)(Modal, { open: createOpen, title: "New folder", onClose: () => setCreateOpen(false), footer: /* @__PURE__ */ (0, import_jsx_runtime105.jsxs)(import_jsx_runtime105.Fragment, { children: [
15545
- /* @__PURE__ */ (0, import_jsx_runtime105.jsx)(Button, { variant: "secondary", onClick: () => setCreateOpen(false), children: "Cancel" }),
15546
- /* @__PURE__ */ (0, import_jsx_runtime105.jsx)(Button, { onClick: submitCreate, disabled: !createName.trim(), children: "Create" })
15547
- ] }), children: /* @__PURE__ */ (0, import_jsx_runtime105.jsx)(
15666
+ /* @__PURE__ */ (0, import_jsx_runtime107.jsx)(Modal, { open: createOpen, title: "New folder", onClose: () => setCreateOpen(false), footer: /* @__PURE__ */ (0, import_jsx_runtime107.jsxs)(import_jsx_runtime107.Fragment, { children: [
15667
+ /* @__PURE__ */ (0, import_jsx_runtime107.jsx)(Button, { variant: "secondary", onClick: () => setCreateOpen(false), children: "Cancel" }),
15668
+ /* @__PURE__ */ (0, import_jsx_runtime107.jsx)(Button, { onClick: submitCreate, disabled: !createName.trim(), children: "Create" })
15669
+ ] }), children: /* @__PURE__ */ (0, import_jsx_runtime107.jsx)(
15548
15670
  "input",
15549
15671
  {
15550
15672
  className: "fd-fb-input",
@@ -15558,10 +15680,10 @@ function FileBrowser({
15558
15680
  autoFocus: true
15559
15681
  }
15560
15682
  ) }),
15561
- /* @__PURE__ */ (0, import_jsx_runtime105.jsx)(Modal, { open: renameTarget != null, title: "Rename folder", onClose: () => setRenameTarget(null), footer: /* @__PURE__ */ (0, import_jsx_runtime105.jsxs)(import_jsx_runtime105.Fragment, { children: [
15562
- /* @__PURE__ */ (0, import_jsx_runtime105.jsx)(Button, { variant: "secondary", onClick: () => setRenameTarget(null), children: "Cancel" }),
15563
- /* @__PURE__ */ (0, import_jsx_runtime105.jsx)(Button, { onClick: submitRename, disabled: !renameValue.trim(), children: "Save" })
15564
- ] }), children: /* @__PURE__ */ (0, import_jsx_runtime105.jsx)(
15683
+ /* @__PURE__ */ (0, import_jsx_runtime107.jsx)(Modal, { open: renameTarget != null, title: "Rename folder", onClose: () => setRenameTarget(null), footer: /* @__PURE__ */ (0, import_jsx_runtime107.jsxs)(import_jsx_runtime107.Fragment, { children: [
15684
+ /* @__PURE__ */ (0, import_jsx_runtime107.jsx)(Button, { variant: "secondary", onClick: () => setRenameTarget(null), children: "Cancel" }),
15685
+ /* @__PURE__ */ (0, import_jsx_runtime107.jsx)(Button, { onClick: submitRename, disabled: !renameValue.trim(), children: "Save" })
15686
+ ] }), children: /* @__PURE__ */ (0, import_jsx_runtime107.jsx)(
15565
15687
  "input",
15566
15688
  {
15567
15689
  className: "fd-fb-input",
@@ -15575,22 +15697,22 @@ function FileBrowser({
15575
15697
  autoFocus: true
15576
15698
  }
15577
15699
  ) }),
15578
- /* @__PURE__ */ (0, import_jsx_runtime105.jsx)(
15700
+ /* @__PURE__ */ (0, import_jsx_runtime107.jsx)(
15579
15701
  Modal,
15580
15702
  {
15581
15703
  open: deleteTarget != null,
15582
15704
  title: deleteTarget ? "Delete \u201C" + deleteTarget.name + "\u201D?" : "Delete folder?",
15583
15705
  description: "This can't be undone. The folder must be empty.",
15584
15706
  onClose: () => setDeleteTarget(null),
15585
- footer: /* @__PURE__ */ (0, import_jsx_runtime105.jsxs)(import_jsx_runtime105.Fragment, { children: [
15586
- /* @__PURE__ */ (0, import_jsx_runtime105.jsx)(Button, { variant: "secondary", onClick: () => setDeleteTarget(null), children: "Cancel" }),
15587
- /* @__PURE__ */ (0, import_jsx_runtime105.jsx)(Button, { variant: "danger", onClick: confirmDelete, children: "Delete" })
15707
+ footer: /* @__PURE__ */ (0, import_jsx_runtime107.jsxs)(import_jsx_runtime107.Fragment, { children: [
15708
+ /* @__PURE__ */ (0, import_jsx_runtime107.jsx)(Button, { variant: "secondary", onClick: () => setDeleteTarget(null), children: "Cancel" }),
15709
+ /* @__PURE__ */ (0, import_jsx_runtime107.jsx)(Button, { variant: "danger", onClick: confirmDelete, children: "Delete" })
15588
15710
  ] })
15589
15711
  }
15590
15712
  )
15591
15713
  ] });
15592
15714
  if (!canUpload) return content;
15593
- return /* @__PURE__ */ (0, import_jsx_runtime105.jsx)(Dropzone, { className: "fd-fb-dropzone", onFiles: (picked) => onUpload && onUpload(picked, currentFolderId), label: "Drop files to upload", children: content });
15715
+ return /* @__PURE__ */ (0, import_jsx_runtime107.jsx)(Dropzone, { className: "fd-fb-dropzone", onFiles: (picked) => onUpload && onUpload(picked, currentFolderId), label: "Drop files to upload", children: content });
15594
15716
  }
15595
15717
  function BreadcrumbCrumb({
15596
15718
  label,
@@ -15599,8 +15721,8 @@ function BreadcrumbCrumb({
15599
15721
  isDropTarget,
15600
15722
  onDropPayload
15601
15723
  }) {
15602
- const [over, setOver] = React76.useState(false);
15603
- const dragCounter = React76.useRef(0);
15724
+ const [over, setOver] = React77.useState(false);
15725
+ const dragCounter = React77.useRef(0);
15604
15726
  const dropHandlers = isDropTarget ? {
15605
15727
  onDragEnter: (e) => {
15606
15728
  if (!hasInternalPayload(e)) return;
@@ -15625,11 +15747,11 @@ function BreadcrumbCrumb({
15625
15747
  if (payload && onDropPayload) onDropPayload(payload);
15626
15748
  }
15627
15749
  } : {};
15628
- return /* @__PURE__ */ (0, import_jsx_runtime105.jsx)("span", { className: ["fd-fb-crumb", over ? "is-drop-target" : ""].filter(Boolean).join(" "), ...dropHandlers, children: isCurrent ? /* @__PURE__ */ (0, import_jsx_runtime105.jsx)("span", { className: "fd-fb-crumb-current", "aria-current": "page", children: label }) : /* @__PURE__ */ (0, import_jsx_runtime105.jsx)("button", { type: "button", className: "fd-fb-crumb-link", onClick, children: label }) });
15750
+ return /* @__PURE__ */ (0, import_jsx_runtime107.jsx)("span", { className: ["fd-fb-crumb", over ? "is-drop-target" : ""].filter(Boolean).join(" "), ...dropHandlers, children: isCurrent ? /* @__PURE__ */ (0, import_jsx_runtime107.jsx)("span", { className: "fd-fb-crumb-current", "aria-current": "page", children: label }) : /* @__PURE__ */ (0, import_jsx_runtime107.jsx)("button", { type: "button", className: "fd-fb-crumb-link", onClick, children: label }) });
15629
15751
  }
15630
15752
 
15631
15753
  // src/kits/query.ts
15632
- var React77 = __toESM(require("react"), 1);
15754
+ var React78 = __toESM(require("react"), 1);
15633
15755
 
15634
15756
  // src/kits/queryUrl.ts
15635
15757
  var historyUrlAdapter = {
@@ -15767,38 +15889,38 @@ function requestFor(params, query, paging, after) {
15767
15889
  }
15768
15890
  var toError = (e) => e instanceof Error ? e : new Error(String(e));
15769
15891
  function useServerTable({ endpoint, params, defaults, deps, prefsKey, paging = "page", url }) {
15770
- const [base] = React77.useState(() => {
15892
+ const [base] = React78.useState(() => {
15771
15893
  const store = PREFS || window.PlannerPrefs;
15772
15894
  const saved = prefsKey && store ? store.getTable(prefsKey) : {};
15773
15895
  return { ...DEFAULTS, ...defaults || {}, ...saved.pageSize ? { pageSize: saved.pageSize } : {}, ...saved.sort ? { sort: saved.sort, dir: saved.dir || "desc" } : {} };
15774
15896
  });
15775
- const [mountParams] = React77.useState(() => url ? (url.adapter ?? historyUrlAdapter).read() : null);
15776
- const address = React77.useRef(mountParams);
15777
- const [query, setQuery] = React77.useState(() => url && mountParams ? readQueryFromUrl(mountParams, url.scope, base, paging) : base);
15778
- const savePref = React77.useCallback((patch2) => {
15897
+ const [mountParams] = React78.useState(() => url ? (url.adapter ?? historyUrlAdapter).read() : null);
15898
+ const address = React78.useRef(mountParams);
15899
+ const [query, setQuery] = React78.useState(() => url && mountParams ? readQueryFromUrl(mountParams, url.scope, base, paging) : base);
15900
+ const savePref = React78.useCallback((patch2) => {
15779
15901
  const store = PREFS || window.PlannerPrefs;
15780
15902
  if (prefsKey && store) store.setTable(prefsKey, patch2);
15781
15903
  }, [prefsKey]);
15782
- const [res, setRes] = React77.useState(null);
15783
- const [loading, setLoading] = React77.useState(true);
15784
- const [loadingMore, setLoadingMore] = React77.useState(false);
15785
- const [failure, setFailure] = React77.useState(null);
15786
- const [reloadToken, setReloadToken] = React77.useState(0);
15787
- const moreController = React77.useRef(null);
15904
+ const [res, setRes] = React78.useState(null);
15905
+ const [loading, setLoading] = React78.useState(true);
15906
+ const [loadingMore, setLoadingMore] = React78.useState(false);
15907
+ const [failure, setFailure] = React78.useState(null);
15908
+ const [reloadToken, setReloadToken] = React78.useState(0);
15909
+ const moreController = React78.useRef(null);
15788
15910
  const depKey = (deps || []).join("|");
15789
15911
  const paramKey = JSON.stringify(params || {});
15790
15912
  const queryKey = JSON.stringify(query);
15791
- const lifetime = React77.useRef(null);
15792
- React77.useEffect(() => {
15913
+ const lifetime = React78.useRef(null);
15914
+ React78.useEffect(() => {
15793
15915
  const controller = new AbortController();
15794
15916
  lifetime.current = controller;
15795
15917
  return () => controller.abort();
15796
15918
  }, []);
15797
- const latest = React77.useRef({ res, loading, query, params, endpoint, url, base });
15798
- React77.useEffect(() => {
15919
+ const latest = React78.useRef({ res, loading, query, params, endpoint, url, base });
15920
+ React78.useLayoutEffect(() => {
15799
15921
  latest.current = { res, loading, query, params, endpoint, url, base };
15800
15922
  });
15801
- React77.useEffect(() => {
15923
+ React78.useEffect(() => {
15802
15924
  const controller = new AbortController();
15803
15925
  const { signal } = controller;
15804
15926
  setLoading(true);
@@ -15834,7 +15956,7 @@ function useServerTable({ endpoint, params, defaults, deps, prefsKey, paging = "
15834
15956
  };
15835
15957
  }, [endpoint, queryKey, paramKey, depKey, paging, reloadToken]);
15836
15958
  const adapter = url ? url.adapter ?? historyUrlAdapter : null;
15837
- React77.useEffect(() => {
15959
+ React78.useEffect(() => {
15838
15960
  if (!adapter) return;
15839
15961
  return adapter.subscribe((params2) => {
15840
15962
  const { url: u, base: b } = latest.current;
@@ -16184,12 +16306,12 @@ function createVersionStore(initialState, options) {
16184
16306
  }
16185
16307
 
16186
16308
  // src/kits/documentTitle.ts
16187
- var React78 = __toESM(require("react"), 1);
16309
+ var React79 = __toESM(require("react"), 1);
16188
16310
  function formatDocumentTitle(routeTitle, appName) {
16189
16311
  return [routeTitle, appName, "Flytedesk"].filter((part) => !!part && part.length > 0).join(" \xB7 ");
16190
16312
  }
16191
16313
  function useDocumentTitle(routeTitle, appName) {
16192
- React78.useEffect(() => {
16314
+ React79.useEffect(() => {
16193
16315
  if (typeof document === "undefined") return;
16194
16316
  document.title = formatDocumentTitle(routeTitle, appName);
16195
16317
  }, [routeTitle, appName]);
@@ -16261,6 +16383,7 @@ function useDocumentTitle(routeTitle, appName) {
16261
16383
  FILE_VIEWER_TEXT_LIMIT,
16262
16384
  FactList,
16263
16385
  FeatureGate,
16386
+ Fieldset,
16264
16387
  FileBrowser,
16265
16388
  FileChip,
16266
16389
  FileGrid,
@@ -16314,6 +16437,7 @@ function useDocumentTitle(routeTitle, appName) {
16314
16437
  QuotaRow,
16315
16438
  ROOT_STEP,
16316
16439
  Radio,
16440
+ RadioGroup,
16317
16441
  RangeSlider,
16318
16442
  RelativeTime,
16319
16443
  RoadmapTimeline,