@flytedan/flytebot-design-system 0.58.0 → 0.59.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -8059,7 +8059,7 @@ function AppSwitcher({ apps: appsProp, onNavigate, className = "" }) {
8059
8059
  }
8060
8060
 
8061
8061
  // src/components/platform/AppearanceMenu.tsx
8062
- import * as React52 from "react";
8062
+ import * as React53 from "react";
8063
8063
 
8064
8064
  // src/kits/appearance.ts
8065
8065
  import * as React51 from "react";
@@ -8156,20 +8156,25 @@ function applyPrefs(prefs, root = document.documentElement) {
8156
8156
  if (prefs.reduceMotion) root.setAttribute("data-motion", "reduce");
8157
8157
  else root.removeAttribute("data-motion");
8158
8158
  }
8159
+ function applyAppearance(store, root = document.documentElement) {
8160
+ applyPrefs(store.getSnapshot(), root);
8161
+ }
8162
+ function watchAppearance(store, root = document.documentElement) {
8163
+ const apply = () => applyAppearance(store, root);
8164
+ apply();
8165
+ const unsubscribe = store.subscribe(apply);
8166
+ const mq = typeof window !== "undefined" && typeof window.matchMedia === "function" ? window.matchMedia("(prefers-color-scheme: dark)") : null;
8167
+ const onSchemeChange = () => {
8168
+ if (store.getSnapshot().theme === "system") apply();
8169
+ };
8170
+ mq?.addEventListener("change", onSchemeChange);
8171
+ return () => {
8172
+ unsubscribe();
8173
+ mq?.removeEventListener("change", onSchemeChange);
8174
+ };
8175
+ }
8159
8176
  function useAppearancePrefs(store) {
8160
8177
  const prefs = React51.useSyncExternalStore(store.subscribe, store.getSnapshot);
8161
- React51.useEffect(() => {
8162
- applyPrefs(prefs);
8163
- }, [prefs]);
8164
- React51.useEffect(() => {
8165
- if (prefs.theme !== "system" || typeof window === "undefined" || typeof window.matchMedia !== "function") {
8166
- return;
8167
- }
8168
- const mq = window.matchMedia("(prefers-color-scheme: dark)");
8169
- const onChange = () => applyPrefs(prefs);
8170
- mq.addEventListener("change", onChange);
8171
- return () => mq.removeEventListener("change", onChange);
8172
- }, [prefs]);
8173
8178
  const update = React51.useCallback(
8174
8179
  (patch) => {
8175
8180
  store.write({ ...store.getSnapshot(), ...patch });
@@ -8179,8 +8184,22 @@ function useAppearancePrefs(store) {
8179
8184
  return [prefs, update];
8180
8185
  }
8181
8186
 
8187
+ // src/components/platform/AppearanceProvider.tsx
8188
+ import * as React52 from "react";
8189
+ import { jsx as jsx77 } from "react/jsx-runtime";
8190
+ var AppearanceStoreContext = React52.createContext(null);
8191
+ function AppearanceProvider({ store, children }) {
8192
+ React52.useLayoutEffect(() => watchAppearance(store), [store]);
8193
+ return /* @__PURE__ */ jsx77(AppearanceStoreContext.Provider, { value: store, children });
8194
+ }
8195
+ function useAppearanceStore() {
8196
+ const store = React52.useContext(AppearanceStoreContext);
8197
+ if (!store) throw new Error("AppearanceMenu and useAppearanceStore must be rendered inside an <AppearanceProvider>.");
8198
+ return store;
8199
+ }
8200
+
8182
8201
  // src/components/platform/AppearanceMenu.tsx
8183
- import { jsx as jsx77, jsxs as jsxs68 } from "react/jsx-runtime";
8202
+ import { jsx as jsx78, jsxs as jsxs68 } from "react/jsx-runtime";
8184
8203
  var THEME_OPTIONS = [
8185
8204
  { value: "light", label: "Light" },
8186
8205
  { value: "dark", label: "Dark" },
@@ -8192,17 +8211,13 @@ var TEXT_SCALE_OPTIONS = [
8192
8211
  { value: "lg", label: "L" },
8193
8212
  { value: "xl", label: "XL" }
8194
8213
  ];
8195
- function AppearanceMenu({ className = "", store: storeProp, storageKey, storage, defaults }) {
8196
- const store = React52.useMemo(
8197
- () => storeProp ?? createLocalStorageAppearanceStore({ storageKey, storage, defaults }),
8198
- [storeProp, storageKey, storage, defaults]
8199
- );
8200
- const [prefs, update] = useAppearancePrefs(store);
8201
- const [open2, setOpen] = React52.useState(false);
8202
- const anchorRef = React52.useRef(null);
8214
+ function AppearanceMenu({ className = "" }) {
8215
+ const [prefs, update] = useAppearancePrefs(useAppearanceStore());
8216
+ const [open2, setOpen] = React53.useState(false);
8217
+ const anchorRef = React53.useRef(null);
8203
8218
  const patch = (p) => update(p);
8204
- return /* @__PURE__ */ jsxs68(React52.Fragment, { children: [
8205
- /* @__PURE__ */ jsx77("span", { ref: anchorRef, className: ["fd-appearance-anchor", className].filter(Boolean).join(" "), style: { display: "inline-flex" }, children: /* @__PURE__ */ jsx77(
8219
+ return /* @__PURE__ */ jsxs68(React53.Fragment, { children: [
8220
+ /* @__PURE__ */ jsx78("span", { ref: anchorRef, className: ["fd-appearance-anchor", className].filter(Boolean).join(" "), style: { display: "inline-flex" }, children: /* @__PURE__ */ jsx78(
8206
8221
  IconButton,
8207
8222
  {
8208
8223
  icon: "circle-half",
@@ -8210,7 +8225,7 @@ function AppearanceMenu({ className = "", store: storeProp, storageKey, storage,
8210
8225
  onClick: () => setOpen((v) => !v)
8211
8226
  }
8212
8227
  ) }),
8213
- /* @__PURE__ */ jsx77(
8228
+ /* @__PURE__ */ jsx78(
8214
8229
  Popover,
8215
8230
  {
8216
8231
  open: open2,
@@ -8222,8 +8237,8 @@ function AppearanceMenu({ className = "", store: storeProp, storageKey, storage,
8222
8237
  label: "Appearance settings",
8223
8238
  children: /* @__PURE__ */ jsxs68("div", { className: "fd-stack", style: { display: "flex", flexDirection: "column", gap: 16 }, children: [
8224
8239
  /* @__PURE__ */ jsxs68("div", { style: { display: "flex", flexDirection: "column", gap: 6 }, children: [
8225
- /* @__PURE__ */ jsx77("span", { className: "fd-field-label", children: "Theme" }),
8226
- /* @__PURE__ */ jsx77(
8240
+ /* @__PURE__ */ jsx78("span", { className: "fd-field-label", children: "Theme" }),
8241
+ /* @__PURE__ */ jsx78(
8227
8242
  SegmentedControl,
8228
8243
  {
8229
8244
  options: THEME_OPTIONS,
@@ -8234,8 +8249,8 @@ function AppearanceMenu({ className = "", store: storeProp, storageKey, storage,
8234
8249
  )
8235
8250
  ] }),
8236
8251
  /* @__PURE__ */ jsxs68("div", { style: { display: "flex", flexDirection: "column", gap: 6 }, children: [
8237
- /* @__PURE__ */ jsx77("span", { className: "fd-field-label", children: "Text size" }),
8238
- /* @__PURE__ */ jsx77(
8252
+ /* @__PURE__ */ jsx78("span", { className: "fd-field-label", children: "Text size" }),
8253
+ /* @__PURE__ */ jsx78(
8239
8254
  SegmentedControl,
8240
8255
  {
8241
8256
  options: TEXT_SCALE_OPTIONS,
@@ -8245,7 +8260,7 @@ function AppearanceMenu({ className = "", store: storeProp, storageKey, storage,
8245
8260
  }
8246
8261
  )
8247
8262
  ] }),
8248
- /* @__PURE__ */ jsx77(
8263
+ /* @__PURE__ */ jsx78(
8249
8264
  Switch,
8250
8265
  {
8251
8266
  label: "High contrast",
@@ -8254,7 +8269,7 @@ function AppearanceMenu({ className = "", store: storeProp, storageKey, storage,
8254
8269
  onChange: (e) => patch({ highContrast: e.target.checked })
8255
8270
  }
8256
8271
  ),
8257
- /* @__PURE__ */ jsx77(
8272
+ /* @__PURE__ */ jsx78(
8258
8273
  Switch,
8259
8274
  {
8260
8275
  label: "Reduce motion",
@@ -8270,14 +8285,14 @@ function AppearanceMenu({ className = "", store: storeProp, storageKey, storage,
8270
8285
  }
8271
8286
 
8272
8287
  // src/components/platform/ApiSpecBrowser.tsx
8273
- import * as React53 from "react";
8274
- import { jsx as jsx78, jsxs as jsxs69 } from "react/jsx-runtime";
8288
+ import * as React54 from "react";
8289
+ import { jsx as jsx79, jsxs as jsxs69 } from "react/jsx-runtime";
8275
8290
  var METHOD_TONE = { GET: "success", POST: "info", PATCH: "warning", PUT: "warning", DELETE: "danger" };
8276
8291
  function Json({ obj }) {
8277
- return /* @__PURE__ */ jsx78("pre", { className: "fd-json", children: JSON.stringify(obj, null, 2) });
8292
+ return /* @__PURE__ */ jsx79("pre", { className: "fd-json", children: JSON.stringify(obj, null, 2) });
8278
8293
  }
8279
8294
  function Endpoint({ s, onRequest }) {
8280
- const [tried, setTried] = React53.useState(null);
8295
+ const [tried, setTried] = React54.useState(null);
8281
8296
  const run = async () => {
8282
8297
  setTried("busy");
8283
8298
  const t0 = (window.performance || Date).now();
@@ -8288,50 +8303,50 @@ function Endpoint({ s, onRequest }) {
8288
8303
  setTried({ ms: Math.round((window.performance || Date).now() - t0), error: String(e && e.message || e) });
8289
8304
  }
8290
8305
  };
8291
- return /* @__PURE__ */ jsx78(Card, { elevation: "flat", padded: false, children: /* @__PURE__ */ jsxs69("div", { className: "fd-stack", style: { gap: 0 }, children: [
8306
+ return /* @__PURE__ */ jsx79(Card, { elevation: "flat", padded: false, children: /* @__PURE__ */ jsxs69("div", { className: "fd-stack", style: { gap: 0 }, children: [
8292
8307
  /* @__PURE__ */ jsxs69("div", { className: "fd-row", style: { gap: 10, padding: "14px 18px", flexWrap: "wrap" }, children: [
8293
- /* @__PURE__ */ jsx78(Badge, { tone: METHOD_TONE[s.method] || "neutral", children: s.method }),
8294
- /* @__PURE__ */ jsx78("code", { className: "fd-mono", style: { fontSize: 12.5, fontWeight: 600, color: "var(--text)", wordBreak: "break-all" }, children: s.path }),
8295
- s.isList ? /* @__PURE__ */ jsx78(Badge, { tone: "neutral", icon: "rows", children: "Paged list" }) : null,
8296
- /* @__PURE__ */ jsx78("span", { style: { flex: 1 } }),
8308
+ /* @__PURE__ */ jsx79(Badge, { tone: METHOD_TONE[s.method] || "neutral", children: s.method }),
8309
+ /* @__PURE__ */ jsx79("code", { className: "fd-mono", style: { fontSize: 12.5, fontWeight: 600, color: "var(--text)", wordBreak: "break-all" }, children: s.path }),
8310
+ s.isList ? /* @__PURE__ */ jsx79(Badge, { tone: "neutral", icon: "rows", children: "Paged list" }) : null,
8311
+ /* @__PURE__ */ jsx79("span", { style: { flex: 1 } }),
8297
8312
  /* @__PURE__ */ jsxs69("span", { className: "fd-body-sm fd-muted fd-mono", children: [
8298
8313
  s.latency[0],
8299
8314
  "\u2013",
8300
8315
  s.latency[1],
8301
8316
  "ms"
8302
8317
  ] }),
8303
- /* @__PURE__ */ jsx78(Button, { size: "sm", variant: "secondary", icon: "play", loading: tried === "busy", onClick: run, children: "Try it" })
8318
+ /* @__PURE__ */ jsx79(Button, { size: "sm", variant: "secondary", icon: "play", loading: tried === "busy", onClick: run, children: "Try it" })
8304
8319
  ] }),
8305
8320
  /* @__PURE__ */ jsxs69("div", { className: "fd-stack", style: { gap: 14, padding: "0 18px 16px" }, children: [
8306
8321
  /* @__PURE__ */ jsxs69("div", { className: "fd-stack", style: { gap: 6 }, children: [
8307
- /* @__PURE__ */ jsx78("span", { className: "fd-body-sm", style: { fontWeight: 700 }, children: s.title }),
8308
- /* @__PURE__ */ jsx78("p", { className: "fd-body-sm fd-secondary", style: { margin: 0, textWrap: "pretty" }, children: s.purpose }),
8309
- s.usedBy && s.usedBy.length ? /* @__PURE__ */ jsx78("span", { className: "fd-row", style: { gap: 6, flexWrap: "wrap" }, children: s.usedBy.map((u) => /* @__PURE__ */ jsx78(Tag, { children: u }, u)) }) : null
8322
+ /* @__PURE__ */ jsx79("span", { className: "fd-body-sm", style: { fontWeight: 700 }, children: s.title }),
8323
+ /* @__PURE__ */ jsx79("p", { className: "fd-body-sm fd-secondary", style: { margin: 0, textWrap: "pretty" }, children: s.purpose }),
8324
+ s.usedBy && s.usedBy.length ? /* @__PURE__ */ jsx79("span", { className: "fd-row", style: { gap: 6, flexWrap: "wrap" }, children: s.usedBy.map((u) => /* @__PURE__ */ jsx79(Tag, { children: u }, u)) }) : null
8310
8325
  ] }),
8311
8326
  /* @__PURE__ */ jsxs69("div", { style: { display: "grid", gridTemplateColumns: "repeat(auto-fit,minmax(280px,1fr))", gap: 12, alignItems: "start" }, children: [
8312
8327
  s.request ? /* @__PURE__ */ jsxs69("div", { className: "fd-stack", style: { gap: 6 }, children: [
8313
- /* @__PURE__ */ jsx78("span", { className: "fd-overline fd-muted", children: "Request body" }),
8314
- /* @__PURE__ */ jsx78(Json, { obj: s.request })
8328
+ /* @__PURE__ */ jsx79("span", { className: "fd-overline fd-muted", children: "Request body" }),
8329
+ /* @__PURE__ */ jsx79(Json, { obj: s.request })
8315
8330
  ] }) : null,
8316
8331
  s.query ? /* @__PURE__ */ jsxs69("div", { className: "fd-stack", style: { gap: 6 }, children: [
8317
- /* @__PURE__ */ jsx78("span", { className: "fd-overline fd-muted", children: "Query" }),
8318
- /* @__PURE__ */ jsx78(Json, { obj: s.query })
8332
+ /* @__PURE__ */ jsx79("span", { className: "fd-overline fd-muted", children: "Query" }),
8333
+ /* @__PURE__ */ jsx79(Json, { obj: s.query })
8319
8334
  ] }) : null,
8320
8335
  /* @__PURE__ */ jsxs69("div", { className: "fd-stack", style: { gap: 6 }, children: [
8321
- /* @__PURE__ */ jsx78("span", { className: "fd-overline fd-muted", children: "Response 200" }),
8322
- /* @__PURE__ */ jsx78(Json, { obj: s.response })
8336
+ /* @__PURE__ */ jsx79("span", { className: "fd-overline fd-muted", children: "Response 200" }),
8337
+ /* @__PURE__ */ jsx79(Json, { obj: s.response })
8323
8338
  ] })
8324
8339
  ] }),
8325
- s.notes ? /* @__PURE__ */ jsx78(Flag, { tone: "info", statement: "Implementation note", cost: s.notes, actions: null }) : null,
8340
+ s.notes ? /* @__PURE__ */ jsx79(Flag, { tone: "info", statement: "Implementation note", cost: s.notes, actions: null }) : null,
8326
8341
  tried && tried !== "busy" ? /* @__PURE__ */ jsxs69("div", { className: "fd-stack", style: { gap: 6 }, children: [
8327
8342
  /* @__PURE__ */ jsxs69("span", { className: "fd-row", style: { gap: 8 }, children: [
8328
- /* @__PURE__ */ jsx78("span", { className: "fd-overline fd-muted", children: "Simulated response" }),
8343
+ /* @__PURE__ */ jsx79("span", { className: "fd-overline fd-muted", children: "Simulated response" }),
8329
8344
  /* @__PURE__ */ jsxs69(Badge, { tone: tried.error ? "danger" : "success", icon: "timer", children: [
8330
8345
  tried.ms,
8331
8346
  "ms"
8332
8347
  ] })
8333
8348
  ] }),
8334
- /* @__PURE__ */ jsx78(Json, { obj: tried.error ? { error: tried.error } : tried.data })
8349
+ /* @__PURE__ */ jsx79(Json, { obj: tried.error ? { error: tried.error } : tried.data })
8335
8350
  ] }) : null
8336
8351
  ] })
8337
8352
  ] }) });
@@ -8350,10 +8365,10 @@ function ApiSpecBrowser({
8350
8365
  className = "",
8351
8366
  ...rest
8352
8367
  }) {
8353
- const [q, setQ] = React53.useState("");
8354
- const [method, setMethod] = React53.useState(null);
8355
- const [mod, setMod] = React53.useState(null);
8356
- const [listOnly, setListOnly] = React53.useState(false);
8368
+ const [q, setQ] = React54.useState("");
8369
+ const [method, setMethod] = React54.useState(null);
8370
+ const [mod, setMod] = React54.useState(null);
8371
+ const [listOnly, setListOnly] = React54.useState(false);
8357
8372
  const activeModule = modules && modules.find((m) => m.id === mod);
8358
8373
  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())));
8359
8374
  const effGroups = groups && groups.length ? groups : [["All endpoints", spec.map((s) => s.id)]];
@@ -8361,46 +8376,46 @@ function ApiSpecBrowser({
8361
8376
  const listCount = spec.filter((s) => s.isList).length;
8362
8377
  return /* @__PURE__ */ jsxs69("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 20, maxWidth: 1100 }, ...rest, children: [
8363
8378
  /* @__PURE__ */ jsxs69("div", { className: "fd-stack", style: { gap: 10 }, children: [
8364
- kicker ? /* @__PURE__ */ jsx78("span", { className: "fd-overline fd-muted", children: kicker }) : null,
8365
- /* @__PURE__ */ jsx78("h1", { className: "fd-h1", style: { margin: 0 }, children: title }),
8366
- lede ? /* @__PURE__ */ jsx78("p", { className: "fd-body fd-secondary fd-prose", style: { margin: 0 }, children: lede }) : null
8379
+ kicker ? /* @__PURE__ */ jsx79("span", { className: "fd-overline fd-muted", children: kicker }) : null,
8380
+ /* @__PURE__ */ jsx79("h1", { className: "fd-h1", style: { margin: 0 }, children: title }),
8381
+ lede ? /* @__PURE__ */ jsx79("p", { className: "fd-body fd-secondary fd-prose", style: { margin: 0 }, children: lede }) : null
8367
8382
  ] }),
8368
8383
  modules && modules.length ? /* @__PURE__ */ jsxs69("div", { className: "fd-stack", style: { gap: 8 }, children: [
8369
- /* @__PURE__ */ jsx78("span", { className: "fd-overline fd-muted", children: "Filter by screen \u2014 every endpoint that screen depends on" }),
8384
+ /* @__PURE__ */ jsx79("span", { className: "fd-overline fd-muted", children: "Filter by screen \u2014 every endpoint that screen depends on" }),
8370
8385
  /* @__PURE__ */ jsxs69("div", { className: "fd-row", style: { gap: 8, flexWrap: "wrap" }, children: [
8371
8386
  /* @__PURE__ */ jsxs69(Tag, { icon: "stack", selected: !mod, onClick: () => setMod(null), children: [
8372
8387
  "All screens ",
8373
- /* @__PURE__ */ jsx78("span", { className: "fd-mono", children: spec.length })
8388
+ /* @__PURE__ */ jsx79("span", { className: "fd-mono", children: spec.length })
8374
8389
  ] }),
8375
8390
  modules.map((m) => /* @__PURE__ */ jsxs69(Tag, { icon: m.icon, selected: mod === m.id, onClick: () => setMod(mod === m.id ? null : m.id), children: [
8376
8391
  m.label,
8377
8392
  " ",
8378
- /* @__PURE__ */ jsx78("span", { className: "fd-mono", children: m.endpoints.length })
8393
+ /* @__PURE__ */ jsx79("span", { className: "fd-mono", children: m.endpoints.length })
8379
8394
  ] }, m.id))
8380
8395
  ] }),
8381
- activeModule ? /* @__PURE__ */ jsx78(
8396
+ activeModule ? /* @__PURE__ */ jsx79(
8382
8397
  Flag,
8383
8398
  {
8384
8399
  tone: "info",
8385
8400
  statement: activeModule.label + " calls " + activeModule.endpoints.length + " endpoints.",
8386
8401
  cost: "Integration checklist for this screen: " + activeModule.endpoints.join(", ") + ". Wire these and the screen is done.",
8387
- actions: /* @__PURE__ */ jsx78(Button, { size: "sm", variant: "ghost", icon: "x", onClick: () => setMod(null), children: "Show all screens" })
8402
+ actions: /* @__PURE__ */ jsx79(Button, { size: "sm", variant: "ghost", icon: "x", onClick: () => setMod(null), children: "Show all screens" })
8388
8403
  }
8389
8404
  ) : null
8390
8405
  ] }) : null,
8391
- sourceNote ? /* @__PURE__ */ jsx78(Flag, { tone: "info", statement: "Design-first: this page is the spec.", cost: sourceNote, actions: null }) : null,
8406
+ sourceNote ? /* @__PURE__ */ jsx79(Flag, { tone: "info", statement: "Design-first: this page is the spec.", cost: sourceNote, actions: null }) : null,
8392
8407
  /* @__PURE__ */ jsxs69("div", { className: "fd-row", style: { gap: 10, flexWrap: "wrap" }, children: [
8393
- /* @__PURE__ */ jsx78(Input, { icon: "magnifying-glass", placeholder: "Find an endpoint, screen, or behavior", value: q, onChange: (e) => setQ(e.target.value), style: { width: 300 } }),
8408
+ /* @__PURE__ */ jsx79(Input, { icon: "magnifying-glass", placeholder: "Find an endpoint, screen, or behavior", value: q, onChange: (e) => setQ(e.target.value), style: { width: 300 } }),
8394
8409
  methods.map((m) => /* @__PURE__ */ jsxs69(Tag, { selected: method === m, onClick: () => setMethod(method === m ? null : m), children: [
8395
8410
  m,
8396
8411
  " ",
8397
- /* @__PURE__ */ jsx78("span", { className: "fd-mono", children: spec.filter((s) => s.method === m).length })
8412
+ /* @__PURE__ */ jsx79("span", { className: "fd-mono", children: spec.filter((s) => s.method === m).length })
8398
8413
  ] }, m)),
8399
8414
  listCount ? /* @__PURE__ */ jsxs69(Tag, { icon: "rows", selected: listOnly, onClick: () => setListOnly(!listOnly), children: [
8400
8415
  "Paged lists ",
8401
- /* @__PURE__ */ jsx78("span", { className: "fd-mono", children: listCount })
8416
+ /* @__PURE__ */ jsx79("span", { className: "fd-mono", children: listCount })
8402
8417
  ] }) : null,
8403
- /* @__PURE__ */ jsx78("span", { style: { flex: 1 } }),
8418
+ /* @__PURE__ */ jsx79("span", { style: { flex: 1 } }),
8404
8419
  /* @__PURE__ */ jsxs69("span", { className: "fd-body-sm fd-muted", children: [
8405
8420
  hits.length,
8406
8421
  " of ",
@@ -8409,31 +8424,31 @@ function ApiSpecBrowser({
8409
8424
  listCount ? " \xB7 " + listCount + " paged" : ""
8410
8425
  ] })
8411
8426
  ] }),
8412
- hits.length === 0 ? /* @__PURE__ */ jsx78(Card, { elevation: "flat", children: /* @__PURE__ */ jsx78("p", { className: "fd-body-sm fd-muted", style: { margin: 0 }, children: "No endpoint matches those filters." }) }) : effGroups.map(([g, ids]) => {
8427
+ hits.length === 0 ? /* @__PURE__ */ jsx79(Card, { elevation: "flat", children: /* @__PURE__ */ jsx79("p", { className: "fd-body-sm fd-muted", style: { margin: 0 }, children: "No endpoint matches those filters." }) }) : effGroups.map(([g, ids]) => {
8413
8428
  const items = hits.filter((s) => ids.indexOf(s.id) >= 0);
8414
8429
  if (!items.length) return null;
8415
8430
  return /* @__PURE__ */ jsxs69("div", { className: "fd-stack", style: { gap: 12 }, children: [
8416
- /* @__PURE__ */ jsx78("span", { className: "fd-label-lg", children: g }),
8417
- items.map((s) => /* @__PURE__ */ jsx78(Endpoint, { s, onRequest }, s.id))
8431
+ /* @__PURE__ */ jsx79("span", { className: "fd-label-lg", children: g }),
8432
+ items.map((s) => /* @__PURE__ */ jsx79(Endpoint, { s, onRequest }, s.id))
8418
8433
  ] }, g);
8419
8434
  }),
8420
- conventions && conventions.length ? /* @__PURE__ */ jsx78(Card, { title: "Cross-cutting conventions", elevation: "flat", children: /* @__PURE__ */ jsx78("div", { className: "fd-stack", style: { gap: 10 }, children: conventions.map(([k, v]) => /* @__PURE__ */ jsxs69("div", { className: "fd-row", style: { gap: 12, alignItems: "flex-start" }, children: [
8421
- /* @__PURE__ */ jsx78("span", { className: "fd-overline fd-muted", style: { width: 110, flex: "none", paddingTop: 2 }, children: k }),
8422
- /* @__PURE__ */ jsx78("span", { className: "fd-body-sm fd-secondary", style: { textWrap: "pretty" }, children: v })
8435
+ conventions && conventions.length ? /* @__PURE__ */ jsx79(Card, { title: "Cross-cutting conventions", elevation: "flat", children: /* @__PURE__ */ jsx79("div", { className: "fd-stack", style: { gap: 10 }, children: conventions.map(([k, v]) => /* @__PURE__ */ jsxs69("div", { className: "fd-row", style: { gap: 12, alignItems: "flex-start" }, children: [
8436
+ /* @__PURE__ */ jsx79("span", { className: "fd-overline fd-muted", style: { width: 110, flex: "none", paddingTop: 2 }, children: k }),
8437
+ /* @__PURE__ */ jsx79("span", { className: "fd-body-sm fd-secondary", style: { textWrap: "pretty" }, children: v })
8423
8438
  ] }, k)) }) }) : null,
8424
- openQuestions && openQuestions.length ? /* @__PURE__ */ jsx78(Collapsible, { icon: "list-checks", title: "Open questions before implementation", subtitle: openQuestions.length + " unresolved", children: /* @__PURE__ */ jsx78("div", { className: "fd-stack", style: { gap: 8 }, children: openQuestions.map(([id, question, why]) => /* @__PURE__ */ jsxs69("div", { className: "fd-row", style: { gap: 10, alignItems: "flex-start", padding: "8px 0", borderTop: "1px solid var(--border)" }, children: [
8425
- /* @__PURE__ */ jsx78(Badge, { tone: "danger", children: id }),
8439
+ openQuestions && openQuestions.length ? /* @__PURE__ */ jsx79(Collapsible, { icon: "list-checks", title: "Open questions before implementation", subtitle: openQuestions.length + " unresolved", children: /* @__PURE__ */ jsx79("div", { className: "fd-stack", style: { gap: 8 }, children: openQuestions.map(([id, question, why]) => /* @__PURE__ */ jsxs69("div", { className: "fd-row", style: { gap: 10, alignItems: "flex-start", padding: "8px 0", borderTop: "1px solid var(--border)" }, children: [
8440
+ /* @__PURE__ */ jsx79(Badge, { tone: "danger", children: id }),
8426
8441
  /* @__PURE__ */ jsxs69("span", { className: "fd-stack", style: { gap: 2, flex: 1 }, children: [
8427
- /* @__PURE__ */ jsx78("span", { className: "fd-body-sm", style: { fontWeight: 600 }, children: question }),
8428
- /* @__PURE__ */ jsx78("span", { className: "fd-body-sm fd-muted", children: why })
8442
+ /* @__PURE__ */ jsx79("span", { className: "fd-body-sm", style: { fontWeight: 600 }, children: question }),
8443
+ /* @__PURE__ */ jsx79("span", { className: "fd-body-sm fd-muted", children: why })
8429
8444
  ] })
8430
8445
  ] }, id)) }) }) : null
8431
8446
  ] });
8432
8447
  }
8433
8448
 
8434
8449
  // src/components/platform/ProfilePage.tsx
8435
- import * as React54 from "react";
8436
- import { jsx as jsx79, jsxs as jsxs70 } from "react/jsx-runtime";
8450
+ import * as React55 from "react";
8451
+ import { jsx as jsx80, jsxs as jsxs70 } from "react/jsx-runtime";
8437
8452
  function fieldInitialValue(field, user) {
8438
8453
  if (field.value) return field.value(user);
8439
8454
  const raw = user[field.key];
@@ -8468,21 +8483,21 @@ function ProfilePage({
8468
8483
  }) {
8469
8484
  const { user: sessionUser, roles, permissions, saveProfile: saveProfile2 } = useSessionContext();
8470
8485
  const user = userProp || sessionUser;
8471
- const initialFieldValues = React54.useMemo(() => {
8486
+ const initialFieldValues = React55.useMemo(() => {
8472
8487
  const values2 = {};
8473
8488
  for (const field of fields) values2[field.key] = fieldInitialValue(field, user);
8474
8489
  return values2;
8475
8490
  }, [user.id, fields]);
8476
- const initialNotify = React54.useMemo(() => {
8491
+ const initialNotify = React55.useMemo(() => {
8477
8492
  const values2 = {};
8478
8493
  for (const n of notifications) values2[n.key] = !!user.notify?.[n.key];
8479
8494
  return values2;
8480
8495
  }, [user.id, notifications]);
8481
- const [values, setValues] = React54.useState(initialFieldValues);
8482
- const [notify, setNotify] = React54.useState(initialNotify);
8483
- const [saving, setSaving] = React54.useState(false);
8484
- const [saved, setSaved] = React54.useState(false);
8485
- const [prevUserId, setPrevUserId] = React54.useState(user.id);
8496
+ const [values, setValues] = React55.useState(initialFieldValues);
8497
+ const [notify, setNotify] = React55.useState(initialNotify);
8498
+ const [saving, setSaving] = React55.useState(false);
8499
+ const [saved, setSaved] = React55.useState(false);
8500
+ const [prevUserId, setPrevUserId] = React55.useState(user.id);
8486
8501
  if (user.id !== prevUserId) {
8487
8502
  setPrevUserId(user.id);
8488
8503
  setValues(initialFieldValues);
@@ -8521,35 +8536,35 @@ function ProfilePage({
8521
8536
  const fieldGroups = groupFields(fields);
8522
8537
  return /* @__PURE__ */ jsxs70("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 20, maxWidth: 860 }, children: [
8523
8538
  /* @__PURE__ */ jsxs70("div", { className: "fd-stack", style: { gap: 10 }, children: [
8524
- /* @__PURE__ */ jsx79("span", { className: "fd-overline fd-muted", children: "Account" }),
8525
- /* @__PURE__ */ jsx79("h1", { className: "fd-h1", style: { margin: 0 }, children: "Your profile" }),
8526
- /* @__PURE__ */ jsx79("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." })
8539
+ /* @__PURE__ */ jsx80("span", { className: "fd-overline fd-muted", children: "Account" }),
8540
+ /* @__PURE__ */ jsx80("h1", { className: "fd-h1", style: { margin: 0 }, children: "Your profile" }),
8541
+ /* @__PURE__ */ jsx80("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." })
8527
8542
  ] }),
8528
- /* @__PURE__ */ jsx79(Card, { elevation: "flat", children: /* @__PURE__ */ jsxs70("div", { className: "fd-row", style: { gap: 16, flexWrap: "wrap", alignItems: "flex-start" }, children: [
8529
- /* @__PURE__ */ jsx79(Avatar, { name: displayName, size: "lg" }),
8543
+ /* @__PURE__ */ jsx80(Card, { elevation: "flat", children: /* @__PURE__ */ jsxs70("div", { className: "fd-row", style: { gap: 16, flexWrap: "wrap", alignItems: "flex-start" }, children: [
8544
+ /* @__PURE__ */ jsx80(Avatar, { name: displayName, size: "lg" }),
8530
8545
  /* @__PURE__ */ jsxs70("div", { className: "fd-stack", style: { gap: 4, flex: 1, minWidth: 200 }, children: [
8531
- /* @__PURE__ */ jsx79("span", { className: "fd-h3", style: { margin: 0 }, children: displayName }),
8546
+ /* @__PURE__ */ jsx80("span", { className: "fd-h3", style: { margin: 0 }, children: displayName }),
8532
8547
  /* @__PURE__ */ jsxs70("span", { className: "fd-row", style: { gap: 6, flexWrap: "wrap", paddingTop: 4 }, children: [
8533
- roles.map((r) => /* @__PURE__ */ jsx79(Badge, { tone: r.id === "owner" ? "success" : "neutral", children: r.name }, r.id)),
8534
- user.sso ? /* @__PURE__ */ jsx79(Badge, { tone: "info", icon: "shield-check", children: "SSO" }) : null
8548
+ roles.map((r) => /* @__PURE__ */ jsx80(Badge, { tone: r.id === "owner" ? "success" : "neutral", children: r.name }, r.id)),
8549
+ user.sso ? /* @__PURE__ */ jsx80(Badge, { tone: "info", icon: "shield-check", children: "SSO" }) : null
8535
8550
  ] })
8536
8551
  ] }),
8537
- onChangePhoto ? /* @__PURE__ */ jsx79(Button, { variant: "secondary", size: "sm", icon: "image", onClick: onChangePhoto, children: "Change photo" }) : null
8552
+ onChangePhoto ? /* @__PURE__ */ jsx80(Button, { variant: "secondary", size: "sm", icon: "image", onClick: onChangePhoto, children: "Change photo" }) : null
8538
8553
  ] }) }),
8539
- fieldGroups.map(({ group, description, fields: groupFieldDefs }) => /* @__PURE__ */ jsx79(
8554
+ fieldGroups.map(({ group, description, fields: groupFieldDefs }) => /* @__PURE__ */ jsx80(
8540
8555
  Card,
8541
8556
  {
8542
8557
  title: description ? /* @__PURE__ */ jsxs70("span", { className: "fd-stack", style: { gap: 2 }, children: [
8543
- /* @__PURE__ */ jsx79("span", { children: group }),
8544
- /* @__PURE__ */ jsx79("span", { className: "fd-body-sm fd-muted", style: { fontWeight: 400 }, children: description })
8558
+ /* @__PURE__ */ jsx80("span", { children: group }),
8559
+ /* @__PURE__ */ jsx80("span", { className: "fd-body-sm fd-muted", style: { fontWeight: 400 }, children: description })
8545
8560
  ] }) : group,
8546
8561
  elevation: "flat",
8547
8562
  children: /* @__PURE__ */ jsxs70("div", { className: "fd-stack", style: { gap: 14 }, children: [
8548
- /* @__PURE__ */ jsx79("div", { style: { display: "grid", gridTemplateColumns: "repeat(auto-fit,minmax(220px,1fr))", gap: 14 }, children: groupFieldDefs.filter((f) => f.type !== "textarea").map((field) => {
8563
+ /* @__PURE__ */ jsx80("div", { style: { display: "grid", gridTemplateColumns: "repeat(auto-fit,minmax(220px,1fr))", gap: 14 }, children: groupFieldDefs.filter((f) => f.type !== "textarea").map((field) => {
8549
8564
  const help = typeof field.help === "function" ? field.help(user) : field.help;
8550
8565
  const readOnly = field.readOnly || field.type === "readonly";
8551
8566
  if (field.type === "select") {
8552
- return /* @__PURE__ */ jsx79(
8567
+ return /* @__PURE__ */ jsx80(
8553
8568
  Select,
8554
8569
  {
8555
8570
  label: field.label,
@@ -8563,7 +8578,7 @@ function ProfilePage({
8563
8578
  field.key
8564
8579
  );
8565
8580
  }
8566
- return /* @__PURE__ */ jsx79(
8581
+ return /* @__PURE__ */ jsx80(
8567
8582
  Input,
8568
8583
  {
8569
8584
  label: field.label,
@@ -8579,7 +8594,7 @@ function ProfilePage({
8579
8594
  }) }),
8580
8595
  groupFieldDefs.filter((f) => f.type === "textarea").map((field) => {
8581
8596
  const help = typeof field.help === "function" ? field.help(user) : field.help;
8582
- return /* @__PURE__ */ jsx79(
8597
+ return /* @__PURE__ */ jsx80(
8583
8598
  Textarea,
8584
8599
  {
8585
8600
  label: field.label,
@@ -8599,16 +8614,16 @@ function ProfilePage({
8599
8614
  group
8600
8615
  )),
8601
8616
  extra,
8602
- notifications.length > 0 ? /* @__PURE__ */ jsx79(Card, { title: "Notifications", elevation: "flat", children: /* @__PURE__ */ jsx79("div", { className: "fd-stack", style: { gap: 14 }, children: notifications.map((n) => /* @__PURE__ */ jsx79(Switch, { checked: !!notify[n.key], onChange: () => toggleNotify(n.key), label: n.label, description: n.description }, n.key)) }) }) : null,
8617
+ notifications.length > 0 ? /* @__PURE__ */ jsx80(Card, { title: "Notifications", elevation: "flat", children: /* @__PURE__ */ jsx80("div", { className: "fd-stack", style: { gap: 14 }, children: notifications.map((n) => /* @__PURE__ */ jsx80(Switch, { checked: !!notify[n.key], onChange: () => toggleNotify(n.key), label: n.label, description: n.description }, n.key)) }) }) : null,
8603
8618
  /* @__PURE__ */ jsxs70(
8604
8619
  Card,
8605
8620
  {
8606
8621
  title: /* @__PURE__ */ jsxs70("span", { className: "fd-stack", style: { gap: 2 }, children: [
8607
- /* @__PURE__ */ jsx79("span", { children: "Access" }),
8608
- /* @__PURE__ */ jsx79("span", { className: "fd-body-sm fd-muted", style: { fontWeight: 400 }, children: "What your roles grant you" })
8622
+ /* @__PURE__ */ jsx80("span", { children: "Access" }),
8623
+ /* @__PURE__ */ jsx80("span", { className: "fd-body-sm fd-muted", style: { fontWeight: 400 }, children: "What your roles grant you" })
8609
8624
  ] }),
8610
8625
  elevation: "flat",
8611
- action: /* @__PURE__ */ jsx79(
8626
+ action: /* @__PURE__ */ jsx80(
8612
8627
  Button,
8613
8628
  {
8614
8629
  size: "sm",
@@ -8620,34 +8635,34 @@ function ProfilePage({
8620
8635
  ),
8621
8636
  children: [
8622
8637
  /* @__PURE__ */ jsxs70("div", { className: "fd-stack", style: { gap: 0 }, children: [
8623
- /* @__PURE__ */ jsx79(CardRow, { label: "Roles", children: roles.map((r) => r.name).join(", ") || "None" }),
8638
+ /* @__PURE__ */ jsx80(CardRow, { label: "Roles", children: roles.map((r) => r.name).join(", ") || "None" }),
8624
8639
  /* @__PURE__ */ jsxs70(CardRow, { label: "Permissions", children: [
8625
8640
  permissions.length,
8626
8641
  " granted"
8627
8642
  ] }),
8628
- /* @__PURE__ */ jsx79(CardRow, { label: "Member since", children: user.joined || "\u2014" })
8643
+ /* @__PURE__ */ jsx80(CardRow, { label: "Member since", children: user.joined || "\u2014" })
8629
8644
  ] }),
8630
- /* @__PURE__ */ jsx79("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." })
8645
+ /* @__PURE__ */ jsx80("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." })
8631
8646
  ]
8632
8647
  }
8633
8648
  ),
8634
- sessions ? /* @__PURE__ */ jsx79(
8649
+ sessions ? /* @__PURE__ */ jsx80(
8635
8650
  Card,
8636
8651
  {
8637
8652
  title: "Signed-in devices",
8638
8653
  elevation: "flat",
8639
- action: /* @__PURE__ */ jsx79(Button, { size: "sm", variant: "ghost", icon: "sign-out", onClick: onSignOutEverywhere, children: "Sign out everywhere" }),
8640
- children: /* @__PURE__ */ jsx79("div", { className: "fd-stack", style: { gap: 0 }, children: sessions.length === 0 ? /* @__PURE__ */ jsx79("p", { className: "fd-body-sm fd-muted", style: { margin: 0 }, children: "No other signed-in devices." }) : sessions.map((s) => /* @__PURE__ */ jsxs70("div", { className: "fd-row", style: { gap: 12, padding: "10px 0", borderTop: "1px solid var(--border)", flexWrap: "wrap" }, children: [
8641
- /* @__PURE__ */ jsx79("i", { className: "ph ph-device-mobile", style: { fontSize: 16, color: "var(--text-muted)" }, "aria-hidden": "true" }),
8654
+ action: /* @__PURE__ */ jsx80(Button, { size: "sm", variant: "ghost", icon: "sign-out", onClick: onSignOutEverywhere, children: "Sign out everywhere" }),
8655
+ children: /* @__PURE__ */ jsx80("div", { className: "fd-stack", style: { gap: 0 }, children: sessions.length === 0 ? /* @__PURE__ */ jsx80("p", { className: "fd-body-sm fd-muted", style: { margin: 0 }, children: "No other signed-in devices." }) : sessions.map((s) => /* @__PURE__ */ jsxs70("div", { className: "fd-row", style: { gap: 12, padding: "10px 0", borderTop: "1px solid var(--border)", flexWrap: "wrap" }, children: [
8656
+ /* @__PURE__ */ jsx80("i", { className: "ph ph-device-mobile", style: { fontSize: 16, color: "var(--text-muted)" }, "aria-hidden": "true" }),
8642
8657
  /* @__PURE__ */ jsxs70("span", { className: "fd-stack", style: { gap: 1, flex: 1, minWidth: 160 }, children: [
8643
- /* @__PURE__ */ jsx79("span", { className: "fd-body-sm", style: { fontWeight: 600 }, children: s.device }),
8658
+ /* @__PURE__ */ jsx80("span", { className: "fd-body-sm", style: { fontWeight: 600 }, children: s.device }),
8644
8659
  /* @__PURE__ */ jsxs70("span", { className: "fd-body-sm fd-muted", children: [
8645
8660
  s.where,
8646
8661
  " \xB7 ",
8647
8662
  s.when
8648
8663
  ] })
8649
8664
  ] }),
8650
- s.current ? /* @__PURE__ */ jsx79(Badge, { tone: "success", dot: true, children: "This device" }) : /* @__PURE__ */ jsx79(Button, { size: "sm", variant: "ghost", children: "Revoke" })
8665
+ s.current ? /* @__PURE__ */ jsx80(Badge, { tone: "success", dot: true, children: "This device" }) : /* @__PURE__ */ jsx80(Button, { size: "sm", variant: "ghost", children: "Revoke" })
8651
8666
  ] }, s.id)) })
8652
8667
  }
8653
8668
  ) : null,
@@ -8662,16 +8677,16 @@ function ProfilePage({
8662
8677
  border: "1px solid var(--border)",
8663
8678
  boxShadow: "0 -4px 16px rgba(11,13,17,.06)"
8664
8679
  }, children: [
8665
- /* @__PURE__ */ jsx79("span", { className: "fd-body-sm", style: { fontWeight: 600, flex: 1 }, children: saved ? "Saved." : dirty ? "Unsaved changes" : "No pending changes" }),
8666
- /* @__PURE__ */ jsx79(Button, { size: "sm", variant: "ghost", disabled: !dirty || saving, onClick: discard, children: "Discard" }),
8667
- /* @__PURE__ */ jsx79(Button, { size: "sm", icon: "check", disabled: !dirty || !canSave, loading: saving, onClick: save, children: "Save changes" })
8680
+ /* @__PURE__ */ jsx80("span", { className: "fd-body-sm", style: { fontWeight: 600, flex: 1 }, children: saved ? "Saved." : dirty ? "Unsaved changes" : "No pending changes" }),
8681
+ /* @__PURE__ */ jsx80(Button, { size: "sm", variant: "ghost", disabled: !dirty || saving, onClick: discard, children: "Discard" }),
8682
+ /* @__PURE__ */ jsx80(Button, { size: "sm", icon: "check", disabled: !dirty || !canSave, loading: saving, onClick: save, children: "Save changes" })
8668
8683
  ] })
8669
8684
  ] });
8670
8685
  }
8671
8686
 
8672
8687
  // src/components/platform/SessionScreen.tsx
8673
- import * as React55 from "react";
8674
- import { Fragment as Fragment20, jsx as jsx80, jsxs as jsxs71 } from "react/jsx-runtime";
8688
+ import * as React56 from "react";
8689
+ import { Fragment as Fragment20, jsx as jsx81, jsxs as jsxs71 } from "react/jsx-runtime";
8675
8690
  var COPY = {
8676
8691
  "signing-in": { busy: "Signing you in\u2026" },
8677
8692
  "session-expired": { busy: "Your session expired \u2014 signing you back in\u2026" },
@@ -8684,28 +8699,28 @@ function SessionScreen({ kind, error, onRetry, productName }) {
8684
8699
  const copy = COPY[kind];
8685
8700
  const busyMessage = "busy" in copy ? copy.busy : null;
8686
8701
  const failureTitle = "failure" in copy ? copy.failure : null;
8687
- const [announced, setAnnounced] = React55.useState("");
8688
- React55.useEffect(() => {
8702
+ const [announced, setAnnounced] = React56.useState("");
8703
+ React56.useEffect(() => {
8689
8704
  setAnnounced(busyMessage ?? "");
8690
8705
  }, [busyMessage]);
8691
- const titleRef = React55.useRef(null);
8706
+ const titleRef = React56.useRef(null);
8692
8707
  const failed = failureTitle !== null;
8693
- React55.useEffect(() => {
8708
+ React56.useEffect(() => {
8694
8709
  titleRef.current?.focus({ preventScroll: true });
8695
8710
  }, [failed]);
8696
- return /* @__PURE__ */ jsx80("main", { className: "fd-session-screen", children: /* @__PURE__ */ jsxs71("div", { className: "fd-session-screen-inner", children: [
8697
- /* @__PURE__ */ jsx80("div", { className: "fd-session-screen-mark", "data-theme": "dark", children: /* @__PURE__ */ jsx80(FlytedeskMark, { size: "lg" }) }),
8711
+ return /* @__PURE__ */ jsx81("main", { className: "fd-session-screen", children: /* @__PURE__ */ jsxs71("div", { className: "fd-session-screen-inner", children: [
8712
+ /* @__PURE__ */ jsx81("div", { className: "fd-session-screen-mark", "data-theme": "dark", children: /* @__PURE__ */ jsx81(FlytedeskMark, { size: "lg" }) }),
8698
8713
  /* @__PURE__ */ jsxs71("div", { className: "fd-session-screen-frame", children: [
8699
- /* @__PURE__ */ jsx80("div", { className: "fd-session-screen-stripe" }),
8700
- /* @__PURE__ */ jsx80(Card, { children: /* @__PURE__ */ jsxs71("div", { className: "fd-session-screen-body", children: [
8701
- /* @__PURE__ */ jsx80("h1", { ref: titleRef, tabIndex: -1, className: "fd-h3 fd-session-screen-title", children: productName }),
8702
- /* @__PURE__ */ jsx80("div", { role: "status", "aria-live": "polite", className: "fd-session-screen-status", children: busyMessage !== null ? /* @__PURE__ */ jsxs71(Fragment20, { children: [
8703
- /* @__PURE__ */ jsx80("span", { className: "fd-spinner fd-spinner-lg fd-session-screen-spinner", "aria-hidden": "true" }),
8704
- /* @__PURE__ */ jsx80("p", { className: "fd-body fd-session-screen-message", children: announced })
8714
+ /* @__PURE__ */ jsx81("div", { className: "fd-session-screen-stripe" }),
8715
+ /* @__PURE__ */ jsx81(Card, { children: /* @__PURE__ */ jsxs71("div", { className: "fd-session-screen-body", children: [
8716
+ /* @__PURE__ */ jsx81("h1", { ref: titleRef, tabIndex: -1, className: "fd-h3 fd-session-screen-title", children: productName }),
8717
+ /* @__PURE__ */ jsx81("div", { role: "status", "aria-live": "polite", className: "fd-session-screen-status", children: busyMessage !== null ? /* @__PURE__ */ jsxs71(Fragment20, { children: [
8718
+ /* @__PURE__ */ jsx81("span", { className: "fd-spinner fd-spinner-lg fd-session-screen-spinner", "aria-hidden": "true" }),
8719
+ /* @__PURE__ */ jsx81("p", { className: "fd-body fd-session-screen-message", children: announced })
8705
8720
  ] }) : null }),
8706
8721
  failureTitle !== null ? /* @__PURE__ */ jsxs71("div", { className: "fd-session-screen-failure", children: [
8707
- /* @__PURE__ */ jsx80(Banner, { tone: "danger", title: failureTitle, detail: error ?? void 0 }),
8708
- onRetry !== null ? /* @__PURE__ */ jsx80(Button, { variant: "primary", block: true, onClick: onRetry, children: "Try again" }) : null
8722
+ /* @__PURE__ */ jsx81(Banner, { tone: "danger", title: failureTitle, detail: error ?? void 0 }),
8723
+ onRetry !== null ? /* @__PURE__ */ jsx81(Button, { variant: "primary", block: true, onClick: onRetry, children: "Try again" }) : null
8709
8724
  ] }) : null
8710
8725
  ] }) })
8711
8726
  ] })
@@ -8713,10 +8728,10 @@ function SessionScreen({ kind, error, onRetry, productName }) {
8713
8728
  }
8714
8729
 
8715
8730
  // src/components/platform/RoadmapTimeline.tsx
8716
- import * as React58 from "react";
8731
+ import * as React59 from "react";
8717
8732
 
8718
8733
  // src/kits/session.ts
8719
- import * as React56 from "react";
8734
+ import * as React57 from "react";
8720
8735
  var PERMISSION_CATALOG = [
8721
8736
  { group: "Plans", items: [
8722
8737
  { key: "plan.view", label: "View plans", detail: "Read any plan in the workspace." },
@@ -10283,8 +10298,8 @@ function roadmap(overrides) {
10283
10298
  };
10284
10299
  }
10285
10300
  function useSession() {
10286
- const [s, setS] = React56.useState(getSession);
10287
- React56.useEffect(() => subscribe(setS), []);
10301
+ const [s, setS] = React57.useState(getSession);
10302
+ React57.useEffect(() => subscribe(setS), []);
10288
10303
  return s;
10289
10304
  }
10290
10305
  var SessionKit = {
@@ -10317,7 +10332,7 @@ var SessionKit = {
10317
10332
  };
10318
10333
  function DemoSessionProvider({ children }) {
10319
10334
  const session = useSession();
10320
- const value = React56.useMemo(
10335
+ const value = React57.useMemo(
10321
10336
  () => ({
10322
10337
  user: session.user,
10323
10338
  roles: session.roles,
@@ -10333,11 +10348,11 @@ function DemoSessionProvider({ children }) {
10333
10348
  }),
10334
10349
  [session]
10335
10350
  );
10336
- return React56.createElement(SessionProvider, { value }, children);
10351
+ return React57.createElement(SessionProvider, { value }, children);
10337
10352
  }
10338
10353
 
10339
10354
  // src/kits/runtime.ts
10340
- import * as React57 from "react";
10355
+ import * as React58 from "react";
10341
10356
  var WIRED_ENDPOINTS = [
10342
10357
  // Nothing yet. Every id below would come from a real service:
10343
10358
  // "plan.get", "placements.list", …
@@ -10508,8 +10523,8 @@ var RuntimeKit = {
10508
10523
  };
10509
10524
  RuntimeKit.declare(FEATURE_NEEDS);
10510
10525
  function useRuntimeMode() {
10511
- const [m, setM] = React57.useState(RuntimeKit.getMode());
10512
- React57.useEffect(() => RuntimeKit.subscribe(setM), []);
10526
+ const [m, setM] = React58.useState(RuntimeKit.getMode());
10527
+ React58.useEffect(() => RuntimeKit.subscribe(setM), []);
10513
10528
  return m;
10514
10529
  }
10515
10530
  function useFeatureStatus(key) {
@@ -10528,7 +10543,7 @@ var UseRuntimeMode = useRuntimeMode;
10528
10543
  var UseFeatureStatus = useFeatureStatus;
10529
10544
 
10530
10545
  // src/components/platform/RoadmapTimeline.tsx
10531
- import { jsx as jsx81, jsxs as jsxs72 } from "react/jsx-runtime";
10546
+ import { jsx as jsx82, jsxs as jsxs72 } from "react/jsx-runtime";
10532
10547
  var STATUS = {
10533
10548
  shipped: { tone: "success", icon: "check-circle", label: "Wired" },
10534
10549
  next: { tone: "warning", icon: "traffic-cone", label: "Not wired" },
@@ -10543,43 +10558,43 @@ function RoadmapCard({ item, byKey, onOpenFlag }) {
10543
10558
  const s = STATUS[item.status] || STATUS.planned;
10544
10559
  const deps = (item.dependsOn || []).map((k) => byKey[k]).filter(Boolean);
10545
10560
  const blocking = deps.filter((d) => !d.implemented);
10546
- return /* @__PURE__ */ jsx81(Card, { elevation: "flat", children: /* @__PURE__ */ jsxs72("div", { className: "fd-stack", style: { gap: 10 }, children: [
10561
+ return /* @__PURE__ */ jsx82(Card, { elevation: "flat", children: /* @__PURE__ */ jsxs72("div", { className: "fd-stack", style: { gap: 10 }, children: [
10547
10562
  /* @__PURE__ */ jsxs72("div", { className: "fd-row", style: { gap: 8, flexWrap: "wrap" }, children: [
10548
- /* @__PURE__ */ jsx81("span", { className: "fd-body", style: { fontWeight: 700, flex: 1, minWidth: 140 }, children: item.label }),
10549
- /* @__PURE__ */ jsx81(Badge, { tone: "neutral", icon: PROJECT_ICON[item.project] || "squares-four", children: item.project }),
10550
- /* @__PURE__ */ jsx81(Badge, { tone: s.tone, icon: s.icon, children: s.label })
10563
+ /* @__PURE__ */ jsx82("span", { className: "fd-body", style: { fontWeight: 700, flex: 1, minWidth: 140 }, children: item.label }),
10564
+ /* @__PURE__ */ jsx82(Badge, { tone: "neutral", icon: PROJECT_ICON[item.project] || "squares-four", children: item.project }),
10565
+ /* @__PURE__ */ jsx82(Badge, { tone: s.tone, icon: s.icon, children: s.label })
10551
10566
  ] }),
10552
- /* @__PURE__ */ jsx81("p", { className: "fd-body-sm fd-secondary", style: { margin: 0, textWrap: "pretty" }, children: item.description }),
10567
+ /* @__PURE__ */ jsx82("p", { className: "fd-body-sm fd-secondary", style: { margin: 0, textWrap: "pretty" }, children: item.description }),
10553
10568
  item.backend ? /* @__PURE__ */ jsxs72("div", { className: "fd-row", style: { gap: 10, alignItems: "flex-start" }, children: [
10554
- /* @__PURE__ */ jsx81("span", { className: "fd-overline fd-muted", style: { width: 62, flex: "none", paddingTop: 2 }, children: "Backend" }),
10555
- /* @__PURE__ */ jsx81("span", { className: "fd-body-sm", style: { flex: 1, textWrap: "pretty" }, children: item.backend })
10569
+ /* @__PURE__ */ jsx82("span", { className: "fd-overline fd-muted", style: { width: 62, flex: "none", paddingTop: 2 }, children: "Backend" }),
10570
+ /* @__PURE__ */ jsx82("span", { className: "fd-body-sm", style: { flex: 1, textWrap: "pretty" }, children: item.backend })
10556
10571
  ] }) : null,
10557
10572
  /* @__PURE__ */ jsxs72("div", { className: "fd-row", style: { gap: 12, flexWrap: "wrap" }, children: [
10558
10573
  item.effort ? /* @__PURE__ */ jsxs72("span", { className: "fd-body-sm fd-muted", children: [
10559
- /* @__PURE__ */ jsx81("i", { className: "ph ph-hourglass-medium" }),
10574
+ /* @__PURE__ */ jsx82("i", { className: "ph ph-hourglass-medium" }),
10560
10575
  " ",
10561
10576
  item.effort
10562
10577
  ] }) : null,
10563
10578
  /* @__PURE__ */ jsxs72("span", { className: "fd-body-sm fd-muted", children: [
10564
- /* @__PURE__ */ jsx81("i", { className: "ph ph-user" }),
10579
+ /* @__PURE__ */ jsx82("i", { className: "ph ph-user" }),
10565
10580
  " ",
10566
10581
  item.owner
10567
10582
  ] }),
10568
- item.screen ? /* @__PURE__ */ jsx81(Badge, { tone: "neutral", icon: "browser", children: "screen" }) : null,
10569
- /* @__PURE__ */ jsx81("span", { style: { flex: 1 } }),
10570
- /* @__PURE__ */ jsx81(
10583
+ item.screen ? /* @__PURE__ */ jsx82(Badge, { tone: "neutral", icon: "browser", children: "screen" }) : null,
10584
+ /* @__PURE__ */ jsx82("span", { style: { flex: 1 } }),
10585
+ /* @__PURE__ */ jsx82(
10571
10586
  "button",
10572
10587
  {
10573
10588
  type: "button",
10574
10589
  onClick: () => onOpenFlag && onOpenFlag(item.key),
10575
10590
  style: { all: "unset", cursor: "pointer", display: "inline-flex", alignItems: "center", gap: 5 },
10576
- children: /* @__PURE__ */ jsx81("code", { className: "fd-mono", style: { fontSize: 11, color: "var(--brand)" }, children: item.key })
10591
+ children: /* @__PURE__ */ jsx82("code", { className: "fd-mono", style: { fontSize: 11, color: "var(--brand)" }, children: item.key })
10577
10592
  }
10578
10593
  )
10579
10594
  ] }),
10580
10595
  deps.length ? /* @__PURE__ */ jsxs72("div", { className: "fd-row", style: { gap: 6, flexWrap: "wrap", paddingTop: 6, borderTop: "1px solid var(--border)" }, children: [
10581
- /* @__PURE__ */ jsx81("span", { className: "fd-overline fd-muted", style: { paddingTop: 3 }, children: "After" }),
10582
- deps.map((d) => /* @__PURE__ */ jsx81(Tag, { icon: d.implemented ? "check" : "clock", children: d.label }, d.key))
10596
+ /* @__PURE__ */ jsx82("span", { className: "fd-overline fd-muted", style: { paddingTop: 3 }, children: "After" }),
10597
+ deps.map((d) => /* @__PURE__ */ jsx82(Tag, { icon: d.implemented ? "check" : "clock", children: d.label }, d.key))
10583
10598
  ] }) : null,
10584
10599
  blocking.length && !item.implemented ? /* @__PURE__ */ jsxs72("span", { className: "fd-body-sm", style: { color: "var(--warn-text)" }, children: [
10585
10600
  "Blocked until ",
@@ -10592,12 +10607,12 @@ function RoadmapCard({ item, byKey, onOpenFlag }) {
10592
10607
  }
10593
10608
  function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
10594
10609
  const session = SessionKit.useSession();
10595
- const [project, setProject] = React58.useState("");
10596
- const [q, setQ] = React58.useState("");
10597
- const scrollRef = React58.useRef(null);
10598
- const nowRef = React58.useRef(null);
10599
- const rm = React58.useMemo(() => SessionKit.roadmap({ isComplete: RuntimeKit.isComplete }), [session]);
10600
- const byKey = React58.useMemo(() => {
10610
+ const [project, setProject] = React59.useState("");
10611
+ const [q, setQ] = React59.useState("");
10612
+ const scrollRef = React59.useRef(null);
10613
+ const nowRef = React59.useRef(null);
10614
+ const rm = React59.useMemo(() => SessionKit.roadmap({ isComplete: RuntimeKit.isComplete }), [session]);
10615
+ const byKey = React59.useMemo(() => {
10601
10616
  const m = {};
10602
10617
  rm.items.forEach((i) => {
10603
10618
  m[i.key] = i;
@@ -10606,7 +10621,7 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
10606
10621
  }, [rm]);
10607
10622
  const items = rm.items.filter((i) => (!project || i.project === project) && (!q || (i.label + " " + i.description + " " + (i.backend || "") + " " + i.key).toLowerCase().includes(q.toLowerCase())));
10608
10623
  const projects = [...new Set(rm.items.map((i) => i.project))];
10609
- React58.useEffect(() => {
10624
+ React59.useEffect(() => {
10610
10625
  let raf1 = 0, raf2 = 0;
10611
10626
  const place = () => {
10612
10627
  const box = scrollRef.current, mark = nowRef.current;
@@ -10636,21 +10651,21 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
10636
10651
  let lastPhase = null;
10637
10652
  return /* @__PURE__ */ jsxs72("div", { className: "fd-stack", style: { gap: 16, maxWidth: 1e3 }, children: [
10638
10653
  /* @__PURE__ */ jsxs72("div", { className: "fd-stack", style: { gap: 10 }, children: [
10639
- /* @__PURE__ */ jsx81("span", { className: "fd-overline fd-muted", children: "Architecture" }),
10640
- /* @__PURE__ */ jsx81("h1", { className: "fd-h1", style: { margin: 0 }, children: title }),
10641
- /* @__PURE__ */ jsx81("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." })
10654
+ /* @__PURE__ */ jsx82("span", { className: "fd-overline fd-muted", children: "Architecture" }),
10655
+ /* @__PURE__ */ jsx82("h1", { className: "fd-h1", style: { margin: 0 }, children: title }),
10656
+ /* @__PURE__ */ jsx82("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." })
10642
10657
  ] }),
10643
10658
  /* @__PURE__ */ jsxs72("div", { className: "fd-grid-stats is-thin", children: [
10644
- /* @__PURE__ */ jsx81(StatTile, { compact: true, label: "Wired", value: String(rm.shipped), sub: "of " + rm.items.length + " features" }),
10645
- /* @__PURE__ */ jsx81(StatTile, { compact: true, label: "Remaining", value: String(rm.remaining), sub: "backend work" }),
10646
- /* @__PURE__ */ jsx81(StatTile, { compact: true, label: "Est. effort", value: days ? days + " days" : "\u2014", sub: "sum of estimates, not calendar" }),
10647
- /* @__PURE__ */ jsx81(StatTile, { compact: true, label: "Up next", value: nextPhase ? "Phase " + nextPhase.phase : "\u2014", sub: nextPhase ? nextPhase.phaseName : "all wired" })
10659
+ /* @__PURE__ */ jsx82(StatTile, { compact: true, label: "Wired", value: String(rm.shipped), sub: "of " + rm.items.length + " features" }),
10660
+ /* @__PURE__ */ jsx82(StatTile, { compact: true, label: "Remaining", value: String(rm.remaining), sub: "backend work" }),
10661
+ /* @__PURE__ */ jsx82(StatTile, { compact: true, label: "Est. effort", value: days ? days + " days" : "\u2014", sub: "sum of estimates, not calendar" }),
10662
+ /* @__PURE__ */ jsx82(StatTile, { compact: true, label: "Up next", value: nextPhase ? "Phase " + nextPhase.phase : "\u2014", sub: nextPhase ? nextPhase.phaseName : "all wired" })
10648
10663
  ] }),
10649
10664
  /* @__PURE__ */ jsxs72("div", { className: "fd-row", style: { gap: 10, flexWrap: "wrap" }, children: [
10650
- /* @__PURE__ */ jsx81(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 } }),
10651
- /* @__PURE__ */ jsx81(Select, { placeholder: "All projects", value: project, onChange: (e) => setProject(e.target.value), options: projects, style: { width: 190 } }),
10652
- /* @__PURE__ */ jsx81("span", { style: { flex: 1 } }),
10653
- /* @__PURE__ */ jsx81(
10665
+ /* @__PURE__ */ jsx82(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 } }),
10666
+ /* @__PURE__ */ jsx82(Select, { placeholder: "All projects", value: project, onChange: (e) => setProject(e.target.value), options: projects, style: { width: 190 } }),
10667
+ /* @__PURE__ */ jsx82("span", { style: { flex: 1 } }),
10668
+ /* @__PURE__ */ jsx82(
10654
10669
  Button,
10655
10670
  {
10656
10671
  size: "sm",
@@ -10664,7 +10679,7 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
10664
10679
  }
10665
10680
  )
10666
10681
  ] }),
10667
- /* @__PURE__ */ jsx81(
10682
+ /* @__PURE__ */ jsx82(
10668
10683
  Flag,
10669
10684
  {
10670
10685
  tone: "info",
@@ -10673,17 +10688,17 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
10673
10688
  actions: null
10674
10689
  }
10675
10690
  ),
10676
- /* @__PURE__ */ jsx81("div", { className: "fd-rm", children: /* @__PURE__ */ jsx81("div", { className: "fd-rm-scroll", ref: scrollRef, children: /* @__PURE__ */ jsxs72("div", { className: "fd-rm-track", children: [
10677
- /* @__PURE__ */ jsx81("span", { className: "fd-rm-spine", children: /* @__PURE__ */ jsx81("span", { className: "fd-rm-spine-done", style: { height: items.length ? 100 * shippedShown / items.length + "%" : "0%" } }) }),
10691
+ /* @__PURE__ */ jsx82("div", { className: "fd-rm", children: /* @__PURE__ */ jsx82("div", { className: "fd-rm-scroll", ref: scrollRef, children: /* @__PURE__ */ jsxs72("div", { className: "fd-rm-track", children: [
10692
+ /* @__PURE__ */ jsx82("span", { className: "fd-rm-spine", children: /* @__PURE__ */ jsx82("span", { className: "fd-rm-spine-done", style: { height: items.length ? 100 * shippedShown / items.length + "%" : "0%" } }) }),
10678
10693
  items.map((item, n) => {
10679
10694
  const showPhase = item.phase !== lastPhase;
10680
10695
  lastPhase = item.phase;
10681
10696
  const inPhase = items.filter((i) => i.phase === item.phase).length;
10682
10697
  const isBoundary = n === firstPending;
10683
- return /* @__PURE__ */ jsxs72(React58.Fragment, { children: [
10698
+ return /* @__PURE__ */ jsxs72(React59.Fragment, { children: [
10684
10699
  showPhase ? /* @__PURE__ */ jsxs72("div", { className: "fd-rm-era", children: [
10685
10700
  /* @__PURE__ */ jsxs72("span", { className: "fd-row", style: { gap: 8, flexWrap: "wrap", alignItems: "baseline" }, children: [
10686
- /* @__PURE__ */ jsx81("span", { style: { fontWeight: 700 }, children: item.phase === 0 ? "Shipped" : "Phase " + item.phase + " \u2014 " + item.phaseName }),
10701
+ /* @__PURE__ */ jsx82("span", { style: { fontWeight: 700 }, children: item.phase === 0 ? "Shipped" : "Phase " + item.phase + " \u2014 " + item.phaseName }),
10687
10702
  item.phase === 0 ? null : /* @__PURE__ */ jsxs72("span", { className: "fd-mono", style: { opacity: 0.7, fontWeight: 400 }, children: [
10688
10703
  fmtDate(item.phaseStart),
10689
10704
  " \u2013 ",
@@ -10696,37 +10711,37 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
10696
10711
  inPhase === 1 ? "" : "s"
10697
10712
  ] })
10698
10713
  ] }),
10699
- item.phaseWhy ? /* @__PURE__ */ jsx81("p", { className: "fd-rm-era-why", children: item.phaseWhy }) : null
10714
+ item.phaseWhy ? /* @__PURE__ */ jsx82("p", { className: "fd-rm-era-why", children: item.phaseWhy }) : null
10700
10715
  ] }) : null,
10701
- isBoundary ? /* @__PURE__ */ jsx81("div", { className: "fd-rm-now", ref: nowRef, children: /* @__PURE__ */ jsxs72("span", { className: "fd-rm-now-pill", children: [
10702
- /* @__PURE__ */ jsx81("i", { className: "ph ph-map-pin" }),
10716
+ isBoundary ? /* @__PURE__ */ jsx82("div", { className: "fd-rm-now", ref: nowRef, children: /* @__PURE__ */ jsxs72("span", { className: "fd-rm-now-pill", children: [
10717
+ /* @__PURE__ */ jsx82("i", { className: "ph ph-map-pin" }),
10703
10718
  " You are here \u2014 everything above is wired"
10704
10719
  ] }) }) : null,
10705
10720
  /* @__PURE__ */ jsxs72("div", { className: "fd-rm-row", children: [
10706
- /* @__PURE__ */ jsx81("span", { className: "fd-rm-dot " + (item.implemented ? "is-shipped" : item.status === "next" ? "is-next" : "") }),
10721
+ /* @__PURE__ */ jsx82("span", { className: "fd-rm-dot " + (item.implemented ? "is-shipped" : item.status === "next" ? "is-next" : "") }),
10707
10722
  /* @__PURE__ */ jsxs72("div", { className: "fd-rm-date", children: [
10708
10723
  fmtDate(item.date),
10709
- /* @__PURE__ */ jsx81("br", {}),
10710
- /* @__PURE__ */ jsx81("span", { style: { opacity: 0.75 }, children: item.implemented ? "shipped" : "phase " + item.phase })
10724
+ /* @__PURE__ */ jsx82("br", {}),
10725
+ /* @__PURE__ */ jsx82("span", { style: { opacity: 0.75 }, children: item.implemented ? "shipped" : "phase " + item.phase })
10711
10726
  ] }),
10712
- /* @__PURE__ */ jsx81(RoadmapCard, { item, byKey, onOpenFlag })
10727
+ /* @__PURE__ */ jsx82(RoadmapCard, { item, byKey, onOpenFlag })
10713
10728
  ] })
10714
10729
  ] }, item.key);
10715
10730
  }),
10716
- !items.length ? /* @__PURE__ */ jsx81("p", { className: "fd-body-sm fd-muted", children: "Nothing matches that filter." }) : null
10731
+ !items.length ? /* @__PURE__ */ jsx82("p", { className: "fd-body-sm fd-muted", children: "Nothing matches that filter." }) : null
10717
10732
  ] }) }) }),
10718
10733
  /* @__PURE__ */ jsxs72("p", { className: "fd-body-sm fd-muted", style: { margin: 0 }, children: [
10719
10734
  "Derived from the feature-flag registry \u2014 each entry's status is its flag's ",
10720
- /* @__PURE__ */ jsx81("code", { className: "fd-mono", children: "implemented" }),
10735
+ /* @__PURE__ */ jsx82("code", { className: "fd-mono", children: "implemented" }),
10721
10736
  " field, so this page cannot drift from what the apps actually do."
10722
10737
  ] })
10723
10738
  ] });
10724
10739
  }
10725
10740
 
10726
10741
  // src/components/platform/ComingSoon.tsx
10727
- import * as React59 from "react";
10742
+ import * as React60 from "react";
10728
10743
  import { createPortal as createPortal6 } from "react-dom";
10729
- import { Fragment as Fragment22, jsx as jsx82, jsxs as jsxs73 } from "react/jsx-runtime";
10744
+ import { Fragment as Fragment22, jsx as jsx83, jsxs as jsxs73 } from "react/jsx-runtime";
10730
10745
  var BYPASS_STORE = "fd.soon.bypass.v1";
10731
10746
  function readBypassed() {
10732
10747
  try {
@@ -10742,8 +10757,8 @@ function writeBypassed(list) {
10742
10757
  }
10743
10758
  }
10744
10759
  function useBypass(key) {
10745
- const [on, setOn] = React59.useState(() => !!key && readBypassed().indexOf(key) >= 0);
10746
- React59.useEffect(() => {
10760
+ const [on, setOn] = React60.useState(() => !!key && readBypassed().indexOf(key) >= 0);
10761
+ React60.useEffect(() => {
10747
10762
  setOn(!!key && readBypassed().indexOf(key) >= 0);
10748
10763
  }, [key]);
10749
10764
  const set = (next) => {
@@ -10758,41 +10773,41 @@ function useBypass(key) {
10758
10773
  function SoonCard({ label, detail, backend, eta, effort, onRoadmap, allowed, onBypass }) {
10759
10774
  return /* @__PURE__ */ jsxs73(Fragment22, { children: [
10760
10775
  /* @__PURE__ */ jsxs73("span", { className: "fd-soon-badge", children: [
10761
- /* @__PURE__ */ jsx82("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" }),
10776
+ /* @__PURE__ */ jsx83("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" }),
10762
10777
  label
10763
10778
  ] }),
10764
- detail ? /* @__PURE__ */ jsx82("span", { className: "fd-soon-detail", children: detail }) : null,
10779
+ detail ? /* @__PURE__ */ jsx83("span", { className: "fd-soon-detail", children: detail }) : null,
10765
10780
  backend ? /* @__PURE__ */ jsxs73("span", { className: "fd-soon-backend", children: [
10766
- /* @__PURE__ */ jsx82("span", { className: "fd-overline", children: "Needs" }),
10781
+ /* @__PURE__ */ jsx83("span", { className: "fd-overline", children: "Needs" }),
10767
10782
  " ",
10768
10783
  backend
10769
10784
  ] }) : null,
10770
10785
  eta || effort || onRoadmap ? /* @__PURE__ */ jsxs73("span", { className: "fd-soon-meta", children: [
10771
10786
  eta ? /* @__PURE__ */ jsxs73("span", { children: [
10772
- /* @__PURE__ */ jsx82("i", { className: "ph ph-calendar-blank", "aria-hidden": "true" }),
10787
+ /* @__PURE__ */ jsx83("i", { className: "ph ph-calendar-blank", "aria-hidden": "true" }),
10773
10788
  " ",
10774
10789
  eta
10775
10790
  ] }) : null,
10776
10791
  effort ? /* @__PURE__ */ jsxs73("span", { children: [
10777
- /* @__PURE__ */ jsx82("i", { className: "ph ph-hourglass-medium", "aria-hidden": "true" }),
10792
+ /* @__PURE__ */ jsx83("i", { className: "ph ph-hourglass-medium", "aria-hidden": "true" }),
10778
10793
  " ",
10779
10794
  effort
10780
10795
  ] }) : null,
10781
10796
  onRoadmap ? /* @__PURE__ */ jsxs73("button", { type: "button", className: "fd-soon-link", onClick: onRoadmap, children: [
10782
10797
  "See the roadmap ",
10783
- /* @__PURE__ */ jsx82("i", { className: "ph ph-arrow-right", "aria-hidden": "true" })
10798
+ /* @__PURE__ */ jsx83("i", { className: "ph ph-arrow-right", "aria-hidden": "true" })
10784
10799
  ] }) : null
10785
10800
  ] }) : null,
10786
10801
  allowed ? /* @__PURE__ */ jsxs73("button", { type: "button", className: "fd-soon-view", onClick: onBypass, children: [
10787
- /* @__PURE__ */ jsx82("i", { className: "ph ph-eye", "aria-hidden": "true" }),
10802
+ /* @__PURE__ */ jsx83("i", { className: "ph ph-eye", "aria-hidden": "true" }),
10788
10803
  " View and use it anyway"
10789
10804
  ] }) : null
10790
10805
  ] });
10791
10806
  }
10792
10807
  function useHoverCard(open2) {
10793
- const anchor = React59.useRef(null);
10794
- const [pos, setPos] = React59.useState(null);
10795
- React59.useLayoutEffect(() => {
10808
+ const anchor = React60.useRef(null);
10809
+ const [pos, setPos] = React60.useState(null);
10810
+ React60.useLayoutEffect(() => {
10796
10811
  if (!open2 || !anchor.current) {
10797
10812
  setPos(null);
10798
10813
  return;
@@ -10846,7 +10861,7 @@ function ComingSoon({
10846
10861
  if (allowed && bypassed) {
10847
10862
  return /* @__PURE__ */ jsxs73("span", { className: ["fd-soon-inline-on", className].filter(Boolean).join(" "), ...rest, children: [
10848
10863
  children,
10849
- /* @__PURE__ */ jsx82(
10864
+ /* @__PURE__ */ jsx83(
10850
10865
  "button",
10851
10866
  {
10852
10867
  type: "button",
@@ -10854,12 +10869,12 @@ function ComingSoon({
10854
10869
  title: "Unwired \u2014 writes go to the simulated backend. " + tip + " Click to re-blur.",
10855
10870
  onClick: () => setBypassed(false),
10856
10871
  "aria-label": "Re-blur this unwired feature",
10857
- children: /* @__PURE__ */ jsx82("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" })
10872
+ children: /* @__PURE__ */ jsx83("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" })
10858
10873
  }
10859
10874
  )
10860
10875
  ] });
10861
10876
  }
10862
- return /* @__PURE__ */ jsx82(
10877
+ return /* @__PURE__ */ jsx83(
10863
10878
  InlineSoon,
10864
10879
  {
10865
10880
  label,
@@ -10882,17 +10897,17 @@ function ComingSoon({
10882
10897
  return /* @__PURE__ */ jsxs73("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 14 }, ...rest, children: [
10883
10898
  /* @__PURE__ */ jsxs73("div", { className: "fd-soon-bar", role: "status", children: [
10884
10899
  /* @__PURE__ */ jsxs73("span", { className: "fd-soon-badge", children: [
10885
- /* @__PURE__ */ jsx82("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" }),
10900
+ /* @__PURE__ */ jsx83("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" }),
10886
10901
  "Unwired feature \u2014 you are using it anyway"
10887
10902
  ] }),
10888
- /* @__PURE__ */ jsx82("span", { className: "fd-soon-bar-detail", children: "Every action here writes to the simulated backend, so nothing you do persists beyond this session." }),
10903
+ /* @__PURE__ */ jsx83("span", { className: "fd-soon-bar-detail", children: "Every action here writes to the simulated backend, so nothing you do persists beyond this session." }),
10889
10904
  /* @__PURE__ */ jsxs73("span", { className: "fd-soon-bar-actions", children: [
10890
10905
  onRoadmap ? /* @__PURE__ */ jsxs73("button", { type: "button", className: "fd-soon-link", onClick: onRoadmap, children: [
10891
10906
  "Roadmap ",
10892
- /* @__PURE__ */ jsx82("i", { className: "ph ph-arrow-right", "aria-hidden": "true" })
10907
+ /* @__PURE__ */ jsx83("i", { className: "ph ph-arrow-right", "aria-hidden": "true" })
10893
10908
  ] }) : null,
10894
10909
  /* @__PURE__ */ jsxs73("button", { type: "button", className: "fd-soon-link", onClick: () => setBypassed(false), children: [
10895
- /* @__PURE__ */ jsx82("i", { className: "ph ph-eye-slash", "aria-hidden": "true" }),
10910
+ /* @__PURE__ */ jsx83("i", { className: "ph ph-eye-slash", "aria-hidden": "true" }),
10896
10911
  " Re-blur"
10897
10912
  ] })
10898
10913
  ] })
@@ -10901,9 +10916,9 @@ function ComingSoon({
10901
10916
  ] });
10902
10917
  }
10903
10918
  return /* @__PURE__ */ jsxs73("div", { className: ["fd-soon", className].filter(Boolean).join(" "), style: minHeight ? { minHeight } : void 0, ...rest, children: [
10904
- /* @__PURE__ */ jsx82("div", { className: "fd-soon-under", style: { filter: "blur(" + blur + "px) saturate(.62)" }, ...{ inert: "" }, "aria-hidden": "true", children }),
10905
- /* @__PURE__ */ jsx82("div", { className: "fd-soon-veil" }),
10906
- /* @__PURE__ */ jsx82("div", { className: "fd-soon-note", role: "note", children: /* @__PURE__ */ jsx82(
10919
+ /* @__PURE__ */ jsx83("div", { className: "fd-soon-under", style: { filter: "blur(" + blur + "px) saturate(.62)" }, ...{ inert: "" }, "aria-hidden": "true", children }),
10920
+ /* @__PURE__ */ jsx83("div", { className: "fd-soon-veil" }),
10921
+ /* @__PURE__ */ jsx83("div", { className: "fd-soon-note", role: "note", children: /* @__PURE__ */ jsx83(
10907
10922
  SoonCard,
10908
10923
  {
10909
10924
  label,
@@ -10919,12 +10934,12 @@ function ComingSoon({
10919
10934
  ] });
10920
10935
  }
10921
10936
  function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, onBypass, blur, tip, className, rest, children }) {
10922
- const [open2, setOpen] = React59.useState(false);
10937
+ const [open2, setOpen] = React60.useState(false);
10923
10938
  const [anchor, pos] = useHoverCard(open2);
10924
- const hoverCardRef = React59.useRef(null);
10939
+ const hoverCardRef = React60.useRef(null);
10925
10940
  const hoverLayer = useStackedLayer({ active: open2, containerRef: hoverCardRef, returnFocus: false });
10926
10941
  const zIndex = useLayerZIndex(hoverLayer);
10927
- const close2 = React59.useRef(null);
10942
+ const close2 = React60.useRef(null);
10928
10943
  const show = () => {
10929
10944
  if (close2.current) {
10930
10945
  clearTimeout(close2.current);
@@ -10940,7 +10955,7 @@ function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, o
10940
10955
  setOpen(false);
10941
10956
  }, 140);
10942
10957
  };
10943
- React59.useEffect(() => () => {
10958
+ React60.useEffect(() => () => {
10944
10959
  if (close2.current) clearTimeout(close2.current);
10945
10960
  }, []);
10946
10961
  return /* @__PURE__ */ jsxs73(
@@ -10954,8 +10969,8 @@ function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, o
10954
10969
  onBlur: hide,
10955
10970
  ...rest,
10956
10971
  children: [
10957
- /* @__PURE__ */ jsx82("span", { className: "fd-soon-under", style: { filter: "blur(" + Math.min(blur, 1.1) + "px) saturate(.66)" }, ...{ inert: "" }, "aria-hidden": "true", children }),
10958
- /* @__PURE__ */ jsx82(
10972
+ /* @__PURE__ */ jsx83("span", { className: "fd-soon-under", style: { filter: "blur(" + Math.min(blur, 1.1) + "px) saturate(.66)" }, ...{ inert: "" }, "aria-hidden": "true", children }),
10973
+ /* @__PURE__ */ jsx83(
10959
10974
  "button",
10960
10975
  {
10961
10976
  type: "button",
@@ -10966,11 +10981,11 @@ function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, o
10966
10981
  onFocus: show,
10967
10982
  onBlur: hide,
10968
10983
  onClick: () => open2 ? setOpen(false) : show(),
10969
- children: /* @__PURE__ */ jsx82("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" })
10984
+ children: /* @__PURE__ */ jsx83("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" })
10970
10985
  }
10971
10986
  ),
10972
10987
  open2 && pos ? createPortal6(
10973
- /* @__PURE__ */ jsx82(
10988
+ /* @__PURE__ */ jsx83(
10974
10989
  "div",
10975
10990
  {
10976
10991
  ref: hoverCardRef,
@@ -10979,7 +10994,7 @@ function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, o
10979
10994
  style: { position: "fixed", left: pos.left, top: pos.top, bottom: pos.bottom, width: pos.width, zIndex },
10980
10995
  onMouseEnter: show,
10981
10996
  onMouseLeave: hide,
10982
- children: /* @__PURE__ */ jsx82(
10997
+ children: /* @__PURE__ */ jsx83(
10983
10998
  SoonCard,
10984
10999
  {
10985
11000
  label,
@@ -11009,7 +11024,7 @@ function formatEta(iso2) {
11009
11024
  var FormatEta = formatEta;
11010
11025
 
11011
11026
  // src/components/platform/Gate.tsx
11012
- import { jsx as jsx83, jsxs as jsxs74 } from "react/jsx-runtime";
11027
+ import { jsx as jsx84, jsxs as jsxs74 } from "react/jsx-runtime";
11013
11028
  function PermissionDenied({ permission, title, detail, compact: compact3 = false, className = "", ...rest }) {
11014
11029
  const need = Array.isArray(permission) ? permission : [permission].filter(Boolean);
11015
11030
  return /* @__PURE__ */ jsxs74(
@@ -11029,13 +11044,13 @@ function PermissionDenied({ permission, title, detail, compact: compact3 = false
11029
11044
  ...rest,
11030
11045
  children: [
11031
11046
  /* @__PURE__ */ jsxs74("span", { className: "fd-row", style: { gap: 8 }, children: [
11032
- /* @__PURE__ */ jsx83("i", { className: "ph ph-lock-simple", style: { fontSize: 16, color: "var(--text-muted)" }, "aria-hidden": "true" }),
11033
- /* @__PURE__ */ jsx83("span", { className: compact3 ? "fd-label-lg" : "fd-h3", children: title || "You do not have access to this" })
11047
+ /* @__PURE__ */ jsx84("i", { className: "ph ph-lock-simple", style: { fontSize: 16, color: "var(--text-muted)" }, "aria-hidden": "true" }),
11048
+ /* @__PURE__ */ jsx84("span", { className: compact3 ? "fd-label-lg" : "fd-h3", children: title || "You do not have access to this" })
11034
11049
  ] }),
11035
- /* @__PURE__ */ jsx83("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." }),
11050
+ /* @__PURE__ */ jsx84("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." }),
11036
11051
  need.length ? /* @__PURE__ */ jsxs74("span", { className: "fd-row", style: { gap: 6, flexWrap: "wrap" }, children: [
11037
- /* @__PURE__ */ jsx83("span", { className: "fd-overline fd-muted", children: "Requires" }),
11038
- need.map((p) => /* @__PURE__ */ jsx83("code", { className: "fd-mono", style: {
11052
+ /* @__PURE__ */ jsx84("span", { className: "fd-overline fd-muted", children: "Requires" }),
11053
+ need.map((p) => /* @__PURE__ */ jsx84("code", { className: "fd-mono", style: {
11039
11054
  fontSize: 11.5,
11040
11055
  padding: "2px 7px",
11041
11056
  borderRadius: 5,
@@ -11065,10 +11080,10 @@ function GatePending({ compact: compact3 = false, className = "" }) {
11065
11080
  },
11066
11081
  children: [
11067
11082
  /* @__PURE__ */ jsxs74("span", { className: "fd-row", style: { gap: 8 }, children: [
11068
- /* @__PURE__ */ jsx83("i", { className: "ph ph-arrows-clockwise", style: { fontSize: 16, color: "var(--text-muted)" }, "aria-hidden": "true" }),
11069
- /* @__PURE__ */ jsx83("span", { className: compact3 ? "fd-label-lg" : "fd-h3", children: "Reconnecting\u2026" })
11083
+ /* @__PURE__ */ jsx84("i", { className: "ph ph-arrows-clockwise", style: { fontSize: 16, color: "var(--text-muted)" }, "aria-hidden": "true" }),
11084
+ /* @__PURE__ */ jsx84("span", { className: compact3 ? "fd-label-lg" : "fd-h3", children: "Reconnecting\u2026" })
11070
11085
  ] }),
11071
- /* @__PURE__ */ jsx83("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." })
11086
+ /* @__PURE__ */ jsx84("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." })
11072
11087
  ]
11073
11088
  }
11074
11089
  );
@@ -11078,7 +11093,7 @@ function Gate({ perm, anyOf, role, silent = false, fallback, pendingFallback, co
11078
11093
  if (pending) {
11079
11094
  if (pendingFallback !== void 0) return pendingFallback;
11080
11095
  if (silent) return null;
11081
- return /* @__PURE__ */ jsx83(GatePending, { compact: compact3 });
11096
+ return /* @__PURE__ */ jsx84(GatePending, { compact: compact3 });
11082
11097
  }
11083
11098
  let ok = true;
11084
11099
  if (perm) ok = ok && can2(perm);
@@ -11087,7 +11102,7 @@ function Gate({ perm, anyOf, role, silent = false, fallback, pendingFallback, co
11087
11102
  if (ok) return children;
11088
11103
  if (fallback !== void 0) return fallback;
11089
11104
  if (silent) return null;
11090
- return /* @__PURE__ */ jsx83(PermissionDenied, { permission: perm || anyOf, compact: compact3 });
11105
+ return /* @__PURE__ */ jsx84(PermissionDenied, { permission: perm || anyOf, compact: compact3 });
11091
11106
  }
11092
11107
  function FeatureGate({
11093
11108
  flag,
@@ -11110,7 +11125,7 @@ function FeatureGate({
11110
11125
  const f = SessionKit.findFlag(flag) || {};
11111
11126
  const missing = rt.missing || [];
11112
11127
  const canBypass = pending ? false : bypassPerm === null ? false : !bypassPerm || can2(bypassPerm);
11113
- return /* @__PURE__ */ jsx83(
11128
+ return /* @__PURE__ */ jsx84(
11114
11129
  ComingSoon,
11115
11130
  {
11116
11131
  label: label || (variant === "inline" ? f.label || "Not wired yet" : "Designed \u2014 backend not wired yet"),
@@ -11131,22 +11146,22 @@ function FeatureGate({
11131
11146
  function PermissionHint({ perm, children }) {
11132
11147
  const { can: can2, pending } = useSessionContext();
11133
11148
  if (pending) {
11134
- return /* @__PURE__ */ jsx83("span", { title: "Access can't be verified right now", style: { display: "inline-flex", opacity: 0.45, cursor: "not-allowed" }, "aria-disabled": "true", children: /* @__PURE__ */ jsx83("span", { style: { pointerEvents: "none" }, children }) });
11149
+ return /* @__PURE__ */ jsx84("span", { title: "Access can't be verified right now", style: { display: "inline-flex", opacity: 0.45, cursor: "not-allowed" }, "aria-disabled": "true", children: /* @__PURE__ */ jsx84("span", { style: { pointerEvents: "none" }, children }) });
11135
11150
  }
11136
11151
  if (can2(perm)) return children;
11137
- return /* @__PURE__ */ jsx83(
11152
+ return /* @__PURE__ */ jsx84(
11138
11153
  "span",
11139
11154
  {
11140
11155
  title: "Requires " + (Array.isArray(perm) ? perm.join(", ") : perm),
11141
11156
  style: { display: "inline-flex", opacity: 0.45, cursor: "not-allowed" },
11142
11157
  "aria-disabled": "true",
11143
- children: /* @__PURE__ */ jsx83("span", { style: { pointerEvents: "none" }, children })
11158
+ children: /* @__PURE__ */ jsx84("span", { style: { pointerEvents: "none" }, children })
11144
11159
  }
11145
11160
  );
11146
11161
  }
11147
11162
 
11148
11163
  // src/components/platform/ModeSwitch.tsx
11149
- import { Fragment as Fragment23, jsx as jsx84, jsxs as jsxs75 } from "react/jsx-runtime";
11164
+ import { Fragment as Fragment23, jsx as jsx85, jsxs as jsxs75 } from "react/jsx-runtime";
11150
11165
  function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog, onOpenSpec, summary }) {
11151
11166
  const mode2 = useRuntimeMode();
11152
11167
  const panel = useInlinePanel();
@@ -11169,15 +11184,15 @@ function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog
11169
11184
  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.",
11170
11185
  className: "fd-mode-btn" + (test ? " is-test" : "") + (open2 ? " is-open" : ""),
11171
11186
  children: [
11172
- /* @__PURE__ */ jsx84("i", { className: "ph " + (test ? "ph-flask" : "ph-lightning"), style: { fontSize: 17 } }),
11173
- test && requestCount ? /* @__PURE__ */ jsx84("span", { className: "fd-mono fd-mode-count", children: requestCount > 99 ? "99+" : requestCount }, requestCount) : null
11187
+ /* @__PURE__ */ jsx85("i", { className: "ph " + (test ? "ph-flask" : "ph-lightning"), style: { fontSize: 17 } }),
11188
+ test && requestCount ? /* @__PURE__ */ jsx85("span", { className: "fd-mono fd-mode-count", children: requestCount > 99 ? "99+" : requestCount }, requestCount) : null
11174
11189
  ]
11175
11190
  }
11176
11191
  ),
11177
11192
  /* @__PURE__ */ jsxs75(InlinePanelSurface, { panel, align: "right", offset: 8, width: 400, className: "fd-mode-pop", label: test ? "Test mode" : "Live mode", children: [
11178
11193
  /* @__PURE__ */ jsxs75("span", { className: "fd-row", style: { gap: 10, padding: "12px 14px", borderBottom: "1px solid var(--border)" }, children: [
11179
11194
  /* @__PURE__ */ jsxs75("span", { className: "fd-badge " + (test ? "fd-badge-warning" : "fd-badge-neutral"), children: [
11180
- /* @__PURE__ */ jsx84("i", { className: "ph " + (test ? "ph-flask" : "ph-lightning"), "aria-hidden": "true" }),
11195
+ /* @__PURE__ */ jsx85("i", { className: "ph " + (test ? "ph-flask" : "ph-lightning"), "aria-hidden": "true" }),
11181
11196
  test ? "Test mode" : "Live mode"
11182
11197
  ] }),
11183
11198
  test ? /* @__PURE__ */ jsxs75("span", { className: "fd-body-sm fd-muted fd-mono", children: [
@@ -11185,11 +11200,11 @@ function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog
11185
11200
  " simulated request",
11186
11201
  requestCount === 1 ? "" : "s"
11187
11202
  ] }) : null,
11188
- /* @__PURE__ */ jsx84("span", { style: { flex: 1 } }),
11189
- test && onClearLog ? /* @__PURE__ */ jsx84("button", { type: "button", className: "fd-soon-link", onClick: onClearLog, children: "Clear" }) : null
11203
+ /* @__PURE__ */ jsx85("span", { style: { flex: 1 } }),
11204
+ test && onClearLog ? /* @__PURE__ */ jsx85("button", { type: "button", className: "fd-soon-link", onClick: onClearLog, children: "Clear" }) : null
11190
11205
  ] }),
11191
11206
  /* @__PURE__ */ jsxs75("span", { style: { display: "block", padding: "12px 14px", borderBottom: "1px solid var(--border)" }, children: [
11192
- /* @__PURE__ */ jsx84("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." }),
11207
+ /* @__PURE__ */ jsx85("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." }),
11193
11208
  /* @__PURE__ */ jsxs75("span", { className: "fd-row", style: { gap: 8, marginTop: 10, flexWrap: "wrap" }, children: [
11194
11209
  /* @__PURE__ */ jsxs75("span", { className: "fd-body-sm fd-muted fd-mono", children: [
11195
11210
  s.endpointsWired,
@@ -11202,36 +11217,36 @@ function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog
11202
11217
  " features complete"
11203
11218
  ] }),
11204
11219
  onOpenSpec ? /* @__PURE__ */ jsxs75(Fragment23, { children: [
11205
- /* @__PURE__ */ jsx84("span", { style: { flex: 1 } }),
11220
+ /* @__PURE__ */ jsx85("span", { style: { flex: 1 } }),
11206
11221
  /* @__PURE__ */ jsxs75("button", { type: "button", className: "fd-soon-link", onClick: () => {
11207
11222
  setOpen(false);
11208
11223
  onOpenSpec();
11209
11224
  }, children: [
11210
11225
  "API spec ",
11211
- /* @__PURE__ */ jsx84("i", { className: "ph ph-arrow-right", "aria-hidden": "true" })
11226
+ /* @__PURE__ */ jsx85("i", { className: "ph ph-arrow-right", "aria-hidden": "true" })
11212
11227
  ] })
11213
11228
  ] }) : null
11214
11229
  ] })
11215
11230
  ] }),
11216
11231
  /* @__PURE__ */ jsxs75("span", { className: "fd-mode-choice", children: [
11217
11232
  /* @__PURE__ */ jsxs75("button", { type: "button", className: "fd-mode-opt" + (!test ? " is-on" : ""), onClick: () => go("live"), children: [
11218
- /* @__PURE__ */ jsx84("i", { className: "ph ph-lightning", "aria-hidden": "true" }),
11233
+ /* @__PURE__ */ jsx85("i", { className: "ph ph-lightning", "aria-hidden": "true" }),
11219
11234
  /* @__PURE__ */ jsxs75("span", { className: "fd-mode-opt-text", children: [
11220
- /* @__PURE__ */ jsx84("span", { className: "fd-mode-opt-title", children: "Live mode" }),
11221
- /* @__PURE__ */ jsx84("span", { className: "fd-mode-opt-desc", children: "Incomplete features under construction" })
11235
+ /* @__PURE__ */ jsx85("span", { className: "fd-mode-opt-title", children: "Live mode" }),
11236
+ /* @__PURE__ */ jsx85("span", { className: "fd-mode-opt-desc", children: "Incomplete features under construction" })
11222
11237
  ] }),
11223
- !test ? /* @__PURE__ */ jsx84("i", { className: "ph ph-check", "aria-hidden": "true" }) : null
11238
+ !test ? /* @__PURE__ */ jsx85("i", { className: "ph ph-check", "aria-hidden": "true" }) : null
11224
11239
  ] }),
11225
11240
  /* @__PURE__ */ jsxs75("button", { type: "button", className: "fd-mode-opt" + (test ? " is-on" : ""), onClick: () => go("test"), children: [
11226
- /* @__PURE__ */ jsx84("i", { className: "ph ph-flask", "aria-hidden": "true" }),
11241
+ /* @__PURE__ */ jsx85("i", { className: "ph ph-flask", "aria-hidden": "true" }),
11227
11242
  /* @__PURE__ */ jsxs75("span", { className: "fd-mode-opt-text", children: [
11228
- /* @__PURE__ */ jsx84("span", { className: "fd-mode-opt-title", children: "Test mode" }),
11229
- /* @__PURE__ */ jsx84("span", { className: "fd-mode-opt-desc", children: "Everything usable, all data simulated" })
11243
+ /* @__PURE__ */ jsx85("span", { className: "fd-mode-opt-title", children: "Test mode" }),
11244
+ /* @__PURE__ */ jsx85("span", { className: "fd-mode-opt-desc", children: "Everything usable, all data simulated" })
11230
11245
  ] }),
11231
- test ? /* @__PURE__ */ jsx84("i", { className: "ph ph-check", "aria-hidden": "true" }) : null
11246
+ test ? /* @__PURE__ */ jsx85("i", { className: "ph ph-check", "aria-hidden": "true" }) : null
11232
11247
  ] })
11233
11248
  ] }),
11234
- test && renderLog ? /* @__PURE__ */ jsx84("span", { style: { display: "block", maxHeight: 340, overflowY: "auto", borderTop: "1px solid var(--border)" }, children: renderLog() }) : null
11249
+ test && renderLog ? /* @__PURE__ */ jsx85("span", { style: { display: "block", maxHeight: 340, overflowY: "auto", borderTop: "1px solid var(--border)" }, children: renderLog() }) : null
11235
11250
  ] })
11236
11251
  ] });
11237
11252
  }
@@ -11240,19 +11255,19 @@ function TestModeBar({ onExit }) {
11240
11255
  if (mode2 !== "test") return null;
11241
11256
  return /* @__PURE__ */ jsxs75("div", { className: "fd-testbar", role: "status", children: [
11242
11257
  /* @__PURE__ */ jsxs75("span", { className: "fd-badge fd-badge-warning", children: [
11243
- /* @__PURE__ */ jsx84("i", { className: "ph ph-flask", "aria-hidden": "true" }),
11258
+ /* @__PURE__ */ jsx85("i", { className: "ph ph-flask", "aria-hidden": "true" }),
11244
11259
  "Test mode"
11245
11260
  ] }),
11246
- /* @__PURE__ */ jsx84("span", { className: "fd-testbar-detail", children: "Every feature is unlocked and every response is simulated \u2014 nothing here persists." }),
11261
+ /* @__PURE__ */ jsx85("span", { className: "fd-testbar-detail", children: "Every feature is unlocked and every response is simulated \u2014 nothing here persists." }),
11247
11262
  /* @__PURE__ */ jsxs75("button", { type: "button", className: "fd-soon-link", onClick: () => onExit ? onExit() : RuntimeKit.setMode("live"), children: [
11248
- /* @__PURE__ */ jsx84("i", { className: "ph ph-lightning", "aria-hidden": "true" }),
11263
+ /* @__PURE__ */ jsx85("i", { className: "ph ph-lightning", "aria-hidden": "true" }),
11249
11264
  " Back to live mode"
11250
11265
  ] })
11251
11266
  ] });
11252
11267
  }
11253
11268
 
11254
11269
  // src/components/planner/ChannelMeta.tsx
11255
- import { jsx as jsx85, jsxs as jsxs76 } from "react/jsx-runtime";
11270
+ import { jsx as jsx86, jsxs as jsxs76 } from "react/jsx-runtime";
11256
11271
  var CHANNEL_WEIGHTS = {
11257
11272
  "OOH": 50,
11258
11273
  "DOOH": 50,
@@ -11305,7 +11320,7 @@ function ChannelTag({ channel, size = "md", showLabel = true, dot = false, weigh
11305
11320
  const m = ChannelMeta(channel);
11306
11321
  const wt = channelWeightOf(channel || "");
11307
11322
  if (dot) {
11308
- return /* @__PURE__ */ jsx85("span", { className: ["fd-chan-dot", className].filter(Boolean).join(" "), title: m.name, style: { background: m.color }, ...rest });
11323
+ return /* @__PURE__ */ jsx86("span", { className: ["fd-chan-dot", className].filter(Boolean).join(" "), title: m.name, style: { background: m.color }, ...rest });
11309
11324
  }
11310
11325
  return /* @__PURE__ */ jsxs76(
11311
11326
  "span",
@@ -11315,16 +11330,16 @@ function ChannelTag({ channel, size = "md", showLabel = true, dot = false, weigh
11315
11330
  style: { "--chan": m.color },
11316
11331
  ...rest,
11317
11332
  children: [
11318
- /* @__PURE__ */ jsx85("i", { className: "ph ph-" + m.icon, "aria-hidden": "true" }),
11319
- showLabel ? /* @__PURE__ */ jsx85("span", { className: "fd-chan-label", children: m.label }) : null,
11320
- weight ? /* @__PURE__ */ jsx85("span", { className: "fd-chan-weight", children: wt || 0 }) : null
11333
+ /* @__PURE__ */ jsx86("i", { className: "ph ph-" + m.icon, "aria-hidden": "true" }),
11334
+ showLabel ? /* @__PURE__ */ jsx86("span", { className: "fd-chan-label", children: m.label }) : null,
11335
+ weight ? /* @__PURE__ */ jsx86("span", { className: "fd-chan-weight", children: wt || 0 }) : null
11321
11336
  ]
11322
11337
  }
11323
11338
  );
11324
11339
  }
11325
11340
 
11326
11341
  // src/components/planner/SaturationDistribution.tsx
11327
- import { jsx as jsx86, jsxs as jsxs77 } from "react/jsx-runtime";
11342
+ import { jsx as jsx87, jsxs as jsxs77 } from "react/jsx-runtime";
11328
11343
  var BANDS2 = [
11329
11344
  { key: "weak", label: "Weak", n: 1, range: "< 50" },
11330
11345
  { key: "adequate", label: "Adequate", n: 2, range: "50\u2013100" },
@@ -11336,7 +11351,7 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
11336
11351
  const tallest = Math.max(1, ...grouped.map((g) => g.items.length));
11337
11352
  const floor = BANDS2.find((b) => b.key === floorBand) || BANDS2[0];
11338
11353
  return /* @__PURE__ */ jsxs77("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 16 }, children: [
11339
- /* @__PURE__ */ jsx86("div", { style: { display: "grid", gridTemplateColumns: "repeat(4,minmax(0,1fr))", gap: 12, alignItems: "end" }, children: grouped.map((g) => {
11354
+ /* @__PURE__ */ jsx87("div", { style: { display: "grid", gridTemplateColumns: "repeat(4,minmax(0,1fr))", gap: 12, alignItems: "end" }, children: grouped.map((g) => {
11340
11355
  const mark = "var(--csi-" + g.n + "-mark)";
11341
11356
  const active = selectedBand === g.key;
11342
11357
  return /* @__PURE__ */ jsxs77(
@@ -11346,13 +11361,13 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
11346
11361
  onClick: onSelectBand ? () => onSelectBand(active ? null : g.key) : void 0,
11347
11362
  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)" },
11348
11363
  children: [
11349
- /* @__PURE__ */ jsx86("span", { style: { display: "flex", flexDirection: "column-reverse", gap: 4, minHeight: tallest * 24, minWidth: 0 }, children: loading ? Array.from({ length: 3 }).map((_, i) => /* @__PURE__ */ jsx86("span", { className: "fd-skel", style: { height: 16, borderRadius: 4 } }, i)) : g.items.map((c) => (
11364
+ /* @__PURE__ */ jsx87("span", { style: { display: "flex", flexDirection: "column-reverse", gap: 4, minHeight: tallest * 24, minWidth: 0 }, children: loading ? Array.from({ length: 3 }).map((_, i) => /* @__PURE__ */ jsx87("span", { className: "fd-skel", style: { height: 16, borderRadius: 4 } }, i)) : g.items.map((c) => (
11350
11365
  // `overflow: hidden` + `white-space: nowrap` only clips once the span
11351
11366
  // actually HAS a bounded width to clip against (see the grid/flex
11352
11367
  // `minWidth: 0` chain above) — `textOverflow: ellipsis` then makes
11353
11368
  // that clip readable instead of a hard cut mid-letter; the full name
11354
11369
  // is still one hover away via `title`.
11355
- /* @__PURE__ */ jsx86(
11370
+ /* @__PURE__ */ jsx87(
11356
11371
  "span",
11357
11372
  {
11358
11373
  title: c.name + " \xB7 " + c.crp,
@@ -11363,11 +11378,11 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
11363
11378
  )
11364
11379
  )) }),
11365
11380
  /* @__PURE__ */ jsxs77("span", { className: "fd-row", style: { gap: 8, alignItems: "baseline" }, children: [
11366
- /* @__PURE__ */ jsx86("span", { className: "fd-num-hero", style: { fontSize: 30, color: g.items.length ? "var(--text)" : "var(--text-disabled)" }, children: loading ? "\u2013" : g.items.length }),
11367
- /* @__PURE__ */ jsx86("span", { className: "fd-meter", style: { gap: 2, color: mark }, "aria-hidden": "true", children: [1, 2, 3, 4].map((i) => /* @__PURE__ */ jsx86("span", { className: "fd-meter-seg" + (i <= g.n ? " is-on" : ""), style: { width: 4, height: 9 } }, i)) })
11381
+ /* @__PURE__ */ jsx87("span", { className: "fd-num-hero", style: { fontSize: 30, color: g.items.length ? "var(--text)" : "var(--text-disabled)" }, children: loading ? "\u2013" : g.items.length }),
11382
+ /* @__PURE__ */ jsx87("span", { className: "fd-meter", style: { gap: 2, color: mark }, "aria-hidden": "true", children: [1, 2, 3, 4].map((i) => /* @__PURE__ */ jsx87("span", { className: "fd-meter-seg" + (i <= g.n ? " is-on" : ""), style: { width: 4, height: 9 } }, i)) })
11368
11383
  ] }),
11369
11384
  /* @__PURE__ */ jsxs77("span", { className: "fd-stack", style: { gap: 1 }, children: [
11370
- /* @__PURE__ */ jsx86("span", { className: "fd-label-lg", children: g.label }),
11385
+ /* @__PURE__ */ jsx87("span", { className: "fd-label-lg", children: g.label }),
11371
11386
  /* @__PURE__ */ jsxs77("span", { className: "fd-body-sm fd-muted", style: { fontSize: 11.5 }, children: [
11372
11387
  "CRP ",
11373
11388
  g.range
@@ -11379,7 +11394,7 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
11379
11394
  );
11380
11395
  }) }),
11381
11396
  floorBand ? /* @__PURE__ */ jsxs77("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: [
11382
- /* @__PURE__ */ jsx86("span", { className: "fd-meter", style: { gap: 2, color: "var(--csi-" + floor.n + "-mark)" }, "aria-hidden": "true", children: [1, 2, 3, 4].map((i) => /* @__PURE__ */ jsx86("span", { className: "fd-meter-seg" + (i <= floor.n ? " is-on" : ""), style: { width: 5, height: 12 } }, i)) }),
11397
+ /* @__PURE__ */ jsx87("span", { className: "fd-meter", style: { gap: 2, color: "var(--csi-" + floor.n + "-mark)" }, "aria-hidden": "true", children: [1, 2, 3, 4].map((i) => /* @__PURE__ */ jsx87("span", { className: "fd-meter-seg" + (i <= floor.n ? " is-on" : ""), style: { width: 5, height: 12 } }, i)) }),
11383
11398
  /* @__PURE__ */ jsxs77("span", { className: "fd-body-sm fd-secondary", style: { flex: 1, minWidth: 240 }, children: [
11384
11399
  /* @__PURE__ */ jsxs77("strong", { style: { color: "var(--text)" }, children: [
11385
11400
  "Plan floor ",
@@ -11392,8 +11407,8 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
11392
11407
  }
11393
11408
 
11394
11409
  // src/components/planner/MixGap.tsx
11395
- import * as React60 from "react";
11396
- import { Fragment as Fragment24, jsx as jsx87, jsxs as jsxs78 } from "react/jsx-runtime";
11410
+ import * as React61 from "react";
11411
+ import { Fragment as Fragment24, jsx as jsx88, jsxs as jsxs78 } from "react/jsx-runtime";
11397
11412
  var MIX_GAP_LAYOUT = {
11398
11413
  trackHeight: 30,
11399
11414
  barHeight: 20,
@@ -11407,7 +11422,7 @@ function mixGapOffset(value, max) {
11407
11422
  }
11408
11423
  function MixGap({ rows = [], loading = false, className = "" }) {
11409
11424
  const max = Math.max(1, ...rows.flatMap((r) => [r.target, r.realized]));
11410
- const [hover, setHover] = React60.useState(null);
11425
+ const [hover, setHover] = React61.useState(null);
11411
11426
  const toneOf = (gap) => gap >= -1 ? "ok" : gap >= -4 ? "warn" : "danger";
11412
11427
  const TONE = { ok: "var(--ok-solid)", warn: "var(--warn-solid)", danger: "var(--danger-solid)" };
11413
11428
  const { trackHeight, barHeight, targetWidth, labelGap } = MIX_GAP_LAYOUT;
@@ -11415,11 +11430,11 @@ function MixGap({ rows = [], loading = false, className = "" }) {
11415
11430
  return /* @__PURE__ */ jsxs78("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 4 }, children: [
11416
11431
  /* @__PURE__ */ jsxs78("div", { className: "fd-row", style: { gap: 16, justifyContent: "flex-end", paddingBottom: 6, flexWrap: "wrap" }, children: [
11417
11432
  [["On target", TONE.ok], ["Close", TONE.warn], ["Short", TONE.danger]].map(([l, c]) => /* @__PURE__ */ jsxs78("span", { className: "fd-row fd-body-sm fd-muted", style: { gap: 6 }, children: [
11418
- /* @__PURE__ */ jsx87("span", { style: { width: 14, height: 9, borderRadius: 2, background: c } }),
11433
+ /* @__PURE__ */ jsx88("span", { style: { width: 14, height: 9, borderRadius: 2, background: c } }),
11419
11434
  l
11420
11435
  ] }, l)),
11421
11436
  /* @__PURE__ */ jsxs78("span", { className: "fd-row fd-body-sm fd-muted", style: { gap: 6 }, children: [
11422
- /* @__PURE__ */ jsx87("span", { "data-mixgap-legend-target": "", style: { width: targetWidth, height: 16, borderRadius: 1, background: MIX_GAP_TARGET_STRIPE } }),
11437
+ /* @__PURE__ */ jsx88("span", { "data-mixgap-legend-target": "", style: { width: targetWidth, height: 16, borderRadius: 1, background: MIX_GAP_TARGET_STRIPE } }),
11423
11438
  "Target"
11424
11439
  ] })
11425
11440
  ] }),
@@ -11436,15 +11451,15 @@ function MixGap({ rows = [], loading = false, className = "" }) {
11436
11451
  onMouseEnter: () => setHover(r.channel),
11437
11452
  onMouseLeave: () => setHover(null),
11438
11453
  children: [
11439
- /* @__PURE__ */ jsx87("span", { style: { width: 128, flex: "none" }, children: /* @__PURE__ */ jsx87(ChannelTag, { channel: r.channel, size: "sm" }) }),
11440
- /* @__PURE__ */ jsx87("span", { style: { position: "relative", flex: 1, height: trackHeight, minWidth: 120 }, children: loading ? /* @__PURE__ */ jsx87("span", { className: "fd-skel", style: { position: "absolute", left: 0, right: 0, top: barTop, height: barHeight, borderRadius: 3 } }) : /* @__PURE__ */ jsxs78(Fragment24, { children: [
11441
- /* @__PURE__ */ jsx87("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)" } }),
11442
- /* @__PURE__ */ jsx87("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 } }),
11454
+ /* @__PURE__ */ jsx88("span", { style: { width: 128, flex: "none" }, children: /* @__PURE__ */ jsx88(ChannelTag, { channel: r.channel, size: "sm" }) }),
11455
+ /* @__PURE__ */ jsx88("span", { style: { position: "relative", flex: 1, height: trackHeight, minWidth: 120 }, children: loading ? /* @__PURE__ */ jsx88("span", { className: "fd-skel", style: { position: "absolute", left: 0, right: 0, top: barTop, height: barHeight, borderRadius: 3 } }) : /* @__PURE__ */ jsxs78(Fragment24, { children: [
11456
+ /* @__PURE__ */ jsx88("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)" } }),
11457
+ /* @__PURE__ */ jsx88("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 } }),
11443
11458
  /* @__PURE__ */ jsxs78("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: [
11444
11459
  r.realized,
11445
11460
  "%"
11446
11461
  ] }),
11447
- hover === r.channel ? /* @__PURE__ */ jsx87("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
11462
+ hover === r.channel ? /* @__PURE__ */ jsx88("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
11448
11463
  ] }) })
11449
11464
  ]
11450
11465
  },
@@ -11455,7 +11470,7 @@ function MixGap({ rows = [], loading = false, className = "" }) {
11455
11470
  }
11456
11471
 
11457
11472
  // src/components/planner/ChannelContribution.tsx
11458
- import { jsx as jsx88, jsxs as jsxs79 } from "react/jsx-runtime";
11473
+ import { jsx as jsx89, jsxs as jsxs79 } from "react/jsx-runtime";
11459
11474
  var money = (n) => "$" + Math.round(n).toLocaleString();
11460
11475
  function ChannelContribution({
11461
11476
  channels = [],
@@ -11472,8 +11487,8 @@ function ChannelContribution({
11472
11487
  const pct = (v) => grand ? v / grand * 100 : 0;
11473
11488
  const spendTotal = channels.reduce((s, c) => s + Number(String(c.spend || 0).replace(/[^0-9.]/g, "")), 0);
11474
11489
  return /* @__PURE__ */ jsxs79("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 16 }, children: [
11475
- loading ? /* @__PURE__ */ jsx88("span", { className: "fd-skel", style: { height: 34, borderRadius: "var(--r-sm)" } }) : /* @__PURE__ */ jsxs79("div", { className: "fd-row", style: { height: 34, borderRadius: "var(--r-sm)", overflow: "hidden", gap: 2, background: "var(--surface-3)" }, children: [
11476
- channels.map((c) => /* @__PURE__ */ jsx88(
11490
+ loading ? /* @__PURE__ */ jsx89("span", { className: "fd-skel", style: { height: 34, borderRadius: "var(--r-sm)" } }) : /* @__PURE__ */ jsxs79("div", { className: "fd-row", style: { height: 34, borderRadius: "var(--r-sm)", overflow: "hidden", gap: 2, background: "var(--surface-3)" }, children: [
11491
+ channels.map((c) => /* @__PURE__ */ jsx89(
11477
11492
  "span",
11478
11493
  {
11479
11494
  title: c.name + " \xB7 " + c.crp.toFixed(1) + " CRP",
@@ -11482,7 +11497,7 @@ function ChannelContribution({
11482
11497
  },
11483
11498
  c.name
11484
11499
  )),
11485
- bonus > 0 ? /* @__PURE__ */ jsx88(
11500
+ bonus > 0 ? /* @__PURE__ */ jsx89(
11486
11501
  "span",
11487
11502
  {
11488
11503
  title: "Surround-sound bonus +" + bonusPct + "%",
@@ -11492,17 +11507,17 @@ function ChannelContribution({
11492
11507
  ) : null
11493
11508
  ] }),
11494
11509
  showTable ? /* @__PURE__ */ jsxs79("table", { className: "fd-table", style: { fontSize: "var(--body-sm-size)" }, children: [
11495
- /* @__PURE__ */ jsx88("thead", { children: /* @__PURE__ */ jsxs79("tr", { children: [
11496
- /* @__PURE__ */ jsx88("th", { style: { width: "34%" }, children: "Channel" }),
11497
- /* @__PURE__ */ jsx88("th", { style: { width: "16%" }, children: "Weight" }),
11498
- /* @__PURE__ */ jsx88("th", { className: "is-num", style: { width: "16%" }, children: "Spend" }),
11499
- /* @__PURE__ */ jsx88("th", { className: "is-num", style: { width: "17%" }, children: "CRP" }),
11500
- /* @__PURE__ */ jsx88("th", { className: "is-num", style: { width: "17%" }, children: "Share" })
11510
+ /* @__PURE__ */ jsx89("thead", { children: /* @__PURE__ */ jsxs79("tr", { children: [
11511
+ /* @__PURE__ */ jsx89("th", { style: { width: "34%" }, children: "Channel" }),
11512
+ /* @__PURE__ */ jsx89("th", { style: { width: "16%" }, children: "Weight" }),
11513
+ /* @__PURE__ */ jsx89("th", { className: "is-num", style: { width: "16%" }, children: "Spend" }),
11514
+ /* @__PURE__ */ jsx89("th", { className: "is-num", style: { width: "17%" }, children: "CRP" }),
11515
+ /* @__PURE__ */ jsx89("th", { className: "is-num", style: { width: "17%" }, children: "Share" })
11501
11516
  ] }) }),
11502
11517
  /* @__PURE__ */ jsxs79("tbody", { children: [
11503
11518
  channels.map((c) => /* @__PURE__ */ jsxs79("tr", { children: [
11504
- /* @__PURE__ */ jsx88("td", { children: /* @__PURE__ */ jsx88(ChannelTag, { channel: c.name, size: "sm" }) }),
11505
- /* @__PURE__ */ jsx88("td", { children: /* @__PURE__ */ jsx88(
11519
+ /* @__PURE__ */ jsx89("td", { children: /* @__PURE__ */ jsx89(ChannelTag, { channel: c.name, size: "sm" }) }),
11520
+ /* @__PURE__ */ jsx89("td", { children: /* @__PURE__ */ jsx89(
11506
11521
  "span",
11507
11522
  {
11508
11523
  className: "fd-badge fd-badge-neutral",
@@ -11511,38 +11526,38 @@ function ChannelContribution({
11511
11526
  children: "weight " + (channelWeightOf(c.name) || 0)
11512
11527
  }
11513
11528
  ) }),
11514
- /* @__PURE__ */ jsx88("td", { className: "is-num", children: c.spend }),
11515
- /* @__PURE__ */ jsx88("td", { className: "is-num", children: c.crp.toFixed(1) }),
11529
+ /* @__PURE__ */ jsx89("td", { className: "is-num", children: c.spend }),
11530
+ /* @__PURE__ */ jsx89("td", { className: "is-num", children: c.crp.toFixed(1) }),
11516
11531
  /* @__PURE__ */ jsxs79("td", { className: "is-num", children: [
11517
11532
  pct(c.crp).toFixed(0),
11518
11533
  "%"
11519
11534
  ] })
11520
11535
  ] }, c.name)),
11521
11536
  bonus > 0 ? /* @__PURE__ */ jsxs79("tr", { children: [
11522
- /* @__PURE__ */ jsx88("td", { children: /* @__PURE__ */ jsxs79("span", { className: "fd-row", style: { gap: 9, fontWeight: 600 }, children: [
11523
- /* @__PURE__ */ jsx88("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" } }),
11537
+ /* @__PURE__ */ jsx89("td", { children: /* @__PURE__ */ jsxs79("span", { className: "fd-row", style: { gap: 9, fontWeight: 600 }, children: [
11538
+ /* @__PURE__ */ jsx89("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" } }),
11524
11539
  "Surround-sound bonus"
11525
11540
  ] }) }),
11526
- /* @__PURE__ */ jsx88("td", { children: /* @__PURE__ */ jsxs79("span", { className: "fd-badge fd-badge-success", style: { height: 20, fontSize: 11 }, children: [
11541
+ /* @__PURE__ */ jsx89("td", { children: /* @__PURE__ */ jsxs79("span", { className: "fd-badge fd-badge-success", style: { height: 20, fontSize: 11 }, children: [
11527
11542
  "+",
11528
11543
  bonusPct,
11529
11544
  "% of +",
11530
11545
  bonusMax,
11531
11546
  "%"
11532
11547
  ] }) }),
11533
- /* @__PURE__ */ jsx88("td", { className: "is-num fd-muted", children: "\u2014" }),
11534
- /* @__PURE__ */ jsx88("td", { className: "is-num", children: bonus.toFixed(1) }),
11548
+ /* @__PURE__ */ jsx89("td", { className: "is-num fd-muted", children: "\u2014" }),
11549
+ /* @__PURE__ */ jsx89("td", { className: "is-num", children: bonus.toFixed(1) }),
11535
11550
  /* @__PURE__ */ jsxs79("td", { className: "is-num", children: [
11536
11551
  pct(bonus).toFixed(0),
11537
11552
  "%"
11538
11553
  ] })
11539
11554
  ] }) : null,
11540
11555
  /* @__PURE__ */ jsxs79("tr", { style: { background: "var(--surface-2)" }, children: [
11541
- /* @__PURE__ */ jsx88("td", { style: { fontWeight: 700 }, children: "Campus total" }),
11542
- /* @__PURE__ */ jsx88("td", {}),
11543
- /* @__PURE__ */ jsx88("td", { className: "is-num", style: { fontWeight: 700 }, children: money(spendTotal) }),
11544
- /* @__PURE__ */ jsx88("td", { className: "is-num", style: { fontWeight: 700 }, children: grand.toFixed(1) }),
11545
- /* @__PURE__ */ jsx88("td", { className: "is-num", style: { fontWeight: 700 }, children: "100%" })
11556
+ /* @__PURE__ */ jsx89("td", { style: { fontWeight: 700 }, children: "Campus total" }),
11557
+ /* @__PURE__ */ jsx89("td", {}),
11558
+ /* @__PURE__ */ jsx89("td", { className: "is-num", style: { fontWeight: 700 }, children: money(spendTotal) }),
11559
+ /* @__PURE__ */ jsx89("td", { className: "is-num", style: { fontWeight: 700 }, children: grand.toFixed(1) }),
11560
+ /* @__PURE__ */ jsx89("td", { className: "is-num", style: { fontWeight: 700 }, children: "100%" })
11546
11561
  ] })
11547
11562
  ] })
11548
11563
  ] }) : null
@@ -11550,8 +11565,8 @@ function ChannelContribution({
11550
11565
  }
11551
11566
 
11552
11567
  // src/components/planner/BudgetReallocator.tsx
11553
- import * as React61 from "react";
11554
- import { Fragment as Fragment25, jsx as jsx89, jsxs as jsxs80 } from "react/jsx-runtime";
11568
+ import * as React62 from "react";
11569
+ import { Fragment as Fragment25, jsx as jsx90, jsxs as jsxs80 } from "react/jsx-runtime";
11555
11570
  var bandFor = (crp) => crp >= 200 ? "dominant" : crp >= 100 ? "strong" : crp >= 50 ? "adequate" : "weak";
11556
11571
  function BudgetReallocator({
11557
11572
  campus,
@@ -11566,8 +11581,8 @@ function BudgetReallocator({
11566
11581
  onCancel,
11567
11582
  className = ""
11568
11583
  }) {
11569
- const [draft, setDraft] = React61.useState(spend);
11570
- React61.useEffect(() => setDraft(spend), [spend]);
11584
+ const [draft, setDraft] = React62.useState(spend);
11585
+ React62.useEffect(() => setDraft(spend), [spend]);
11571
11586
  const dirty = draft !== spend;
11572
11587
  const nextCrp = scoreFor ? scoreFor(draft) : crp;
11573
11588
  const nextBand = bandFor(nextCrp);
@@ -11582,10 +11597,10 @@ function BudgetReallocator({
11582
11597
  setDraft(spend);
11583
11598
  if (onCancel) onCancel();
11584
11599
  };
11585
- const trackRef = React61.useRef(null);
11586
- const chipRef = React61.useRef(null);
11587
- const [chipLeft, setChipLeft] = React61.useState(null);
11588
- React61.useLayoutEffect(() => {
11600
+ const trackRef = React62.useRef(null);
11601
+ const chipRef = React62.useRef(null);
11602
+ const [chipLeft, setChipLeft] = React62.useState(null);
11603
+ React62.useLayoutEffect(() => {
11589
11604
  const track = trackRef.current;
11590
11605
  if (!dirty || !track) {
11591
11606
  setChipLeft(null);
@@ -11613,16 +11628,16 @@ function BudgetReallocator({
11613
11628
  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)" },
11614
11629
  children: [
11615
11630
  /* @__PURE__ */ jsxs80("div", { className: "fd-row", style: { gap: 12, flexWrap: "wrap" }, children: [
11616
- /* @__PURE__ */ jsx89("span", { className: "fd-h4", style: { flex: 1, minWidth: 140 }, children: campus }),
11617
- /* @__PURE__ */ jsx89(CsiBadge, { band: nowBand, crp, size: "medium" }),
11631
+ /* @__PURE__ */ jsx90("span", { className: "fd-h4", style: { flex: 1, minWidth: 140 }, children: campus }),
11632
+ /* @__PURE__ */ jsx90(CsiBadge, { band: nowBand, crp, size: "medium" }),
11618
11633
  dirty ? /* @__PURE__ */ jsxs80(Fragment25, { children: [
11619
- /* @__PURE__ */ jsx89("i", { className: "ph ph-arrow-right fd-muted", "aria-hidden": "true" }),
11620
- /* @__PURE__ */ jsx89(CsiBadge, { band: nextBand, crp: nextCrp, size: "medium", preview: true })
11634
+ /* @__PURE__ */ jsx90("i", { className: "ph ph-arrow-right fd-muted", "aria-hidden": "true" }),
11635
+ /* @__PURE__ */ jsx90(CsiBadge, { band: nextBand, crp: nextCrp, size: "medium", preview: true })
11621
11636
  ] }) : null
11622
11637
  ] }),
11623
11638
  /* @__PURE__ */ jsxs80("div", { className: "fd-slider", ref: trackRef, children: [
11624
- /* @__PURE__ */ jsx89("span", { className: "fd-slider-fill", style: { width: pct + "%" } }),
11625
- dirty ? /* @__PURE__ */ jsx89(
11639
+ /* @__PURE__ */ jsx90("span", { className: "fd-slider-fill", style: { width: pct + "%" } }),
11640
+ dirty ? /* @__PURE__ */ jsx90(
11626
11641
  "span",
11627
11642
  {
11628
11643
  ref: chipRef,
@@ -11634,7 +11649,7 @@ function BudgetReallocator({
11634
11649
  children: (delta < 0 ? "\u2212$" : "+$") + Math.abs(delta).toLocaleString()
11635
11650
  }
11636
11651
  ) : null,
11637
- /* @__PURE__ */ jsx89(
11652
+ /* @__PURE__ */ jsx90(
11638
11653
  "input",
11639
11654
  {
11640
11655
  type: "range",
@@ -11652,11 +11667,11 @@ function BudgetReallocator({
11652
11667
  ] }),
11653
11668
  /* @__PURE__ */ jsxs80("div", { className: "fd-row", style: { gap: 12, flexWrap: "wrap" }, children: [
11654
11669
  /* @__PURE__ */ jsxs80("span", { className: "fd-stack", style: { gap: 2, flex: 1, minWidth: 150 }, children: [
11655
- /* @__PURE__ */ jsx89("span", { className: "fd-num", style: { fontSize: 19, fontWeight: 700 }, children: "$" + draft.toLocaleString() }),
11656
- /* @__PURE__ */ jsx89("span", { className: "fd-body-sm fd-muted", children: "Arrow keys step $100, shift+arrow $1,000. Escape reverts." })
11670
+ /* @__PURE__ */ jsx90("span", { className: "fd-num", style: { fontSize: 19, fontWeight: 700 }, children: "$" + draft.toLocaleString() }),
11671
+ /* @__PURE__ */ jsx90("span", { className: "fd-body-sm fd-muted", children: "Arrow keys step $100, shift+arrow $1,000. Escape reverts." })
11657
11672
  ] }),
11658
- /* @__PURE__ */ jsx89("button", { type: "button", className: "fd-btn fd-btn-ghost", disabled: !dirty, onClick: revert, children: "Cancel" }),
11659
- /* @__PURE__ */ jsx89(
11673
+ /* @__PURE__ */ jsx90("button", { type: "button", className: "fd-btn fd-btn-ghost", disabled: !dirty, onClick: revert, children: "Cancel" }),
11674
+ /* @__PURE__ */ jsx90(
11660
11675
  "button",
11661
11676
  {
11662
11677
  type: "button",
@@ -11675,7 +11690,7 @@ function BudgetReallocator({
11675
11690
  }
11676
11691
 
11677
11692
  // src/components/planner/SurroundSound.tsx
11678
- import { jsx as jsx90, jsxs as jsxs81 } from "react/jsx-runtime";
11693
+ import { jsx as jsx91, jsxs as jsxs81 } from "react/jsx-runtime";
11679
11694
  var CATEGORIES = [
11680
11695
  { key: "ooh", label: "OOH", icon: "flag-banner", color: "var(--ch-ooh)" },
11681
11696
  { key: "transit", label: "Transit", icon: "bus", color: "var(--ch-transit)" },
@@ -11688,7 +11703,7 @@ function SurroundSound({ present = [], bonusPct = 0, bonusMax = 40, missedCost,
11688
11703
  const earned = Math.max(0, Math.min(1, bonusPct / bonusMax));
11689
11704
  const single = present.length <= 2;
11690
11705
  return /* @__PURE__ */ jsxs81("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 14 }, children: [
11691
- /* @__PURE__ */ jsx90("div", { className: "fd-row", style: { gap: 8, flexWrap: "wrap" }, children: CATEGORIES.map((c) => {
11706
+ /* @__PURE__ */ jsx91("div", { className: "fd-row", style: { gap: 8, flexWrap: "wrap" }, children: CATEGORIES.map((c) => {
11692
11707
  const on = present.includes(c.key);
11693
11708
  return /* @__PURE__ */ jsxs81(
11694
11709
  "span",
@@ -11696,8 +11711,8 @@ function SurroundSound({ present = [], bonusPct = 0, bonusMax = 40, missedCost,
11696
11711
  title: c.label + (on ? " \u2014 present" : " \u2014 not bought"),
11697
11712
  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)" },
11698
11713
  children: [
11699
- /* @__PURE__ */ jsx90("i", { className: "ph ph-" + c.icon, style: { fontSize: 19, color: on ? c.color : "var(--text-muted)" }, "aria-hidden": "true" }),
11700
- /* @__PURE__ */ jsx90("span", { style: { fontSize: 10.5, fontWeight: 700 }, children: c.label })
11714
+ /* @__PURE__ */ jsx91("i", { className: "ph ph-" + c.icon, style: { fontSize: 19, color: on ? c.color : "var(--text-muted)" }, "aria-hidden": "true" }),
11715
+ /* @__PURE__ */ jsx91("span", { style: { fontSize: 10.5, fontWeight: 700 }, children: c.label })
11701
11716
  ]
11702
11717
  },
11703
11718
  c.key
@@ -11705,7 +11720,7 @@ function SurroundSound({ present = [], bonusPct = 0, bonusMax = 40, missedCost,
11705
11720
  }) }),
11706
11721
  /* @__PURE__ */ jsxs81("div", { className: "fd-stack", style: { gap: 8 }, children: [
11707
11722
  /* @__PURE__ */ jsxs81("div", { className: "fd-row", style: { justifyContent: "space-between", gap: 12 }, children: [
11708
- /* @__PURE__ */ jsx90("span", { className: "fd-label-lg", children: "Surround-sound bonus earned" }),
11723
+ /* @__PURE__ */ jsx91("span", { className: "fd-label-lg", children: "Surround-sound bonus earned" }),
11709
11724
  /* @__PURE__ */ jsxs81("span", { className: "fd-num", style: { color: single ? "var(--warn-text)" : "var(--csi-3-mark)", fontWeight: 700 }, children: [
11710
11725
  "+",
11711
11726
  bonusPct,
@@ -11714,7 +11729,7 @@ function SurroundSound({ present = [], bonusPct = 0, bonusMax = 40, missedCost,
11714
11729
  "%"
11715
11730
  ] })
11716
11731
  ] }),
11717
- /* @__PURE__ */ jsx90("div", { style: { height: 8, borderRadius: "var(--r-xs)", background: "var(--surface-3)", overflow: "hidden" }, children: /* @__PURE__ */ jsx90("div", { style: { height: "100%", width: earned * 100 + "%", background: "var(--csi-3-mark)", borderRadius: "inherit", transition: "width var(--dur-slow) var(--ease)" } }) }),
11732
+ /* @__PURE__ */ jsx91("div", { style: { height: 8, borderRadius: "var(--r-xs)", background: "var(--surface-3)", overflow: "hidden" }, children: /* @__PURE__ */ jsx91("div", { style: { height: "100%", width: earned * 100 + "%", background: "var(--csi-3-mark)", borderRadius: "inherit", transition: "width var(--dur-slow) var(--ease)" } }) }),
11718
11733
  /* @__PURE__ */ jsxs81("span", { className: "fd-body-sm fd-secondary", style: { textWrap: "pretty" }, children: [
11719
11734
  present.length,
11720
11735
  " of 6 channel categories present.",
@@ -11727,7 +11742,7 @@ function SurroundSound({ present = [], bonusPct = 0, bonusMax = 40, missedCost,
11727
11742
  }
11728
11743
 
11729
11744
  // src/components/planner/Importance.tsx
11730
- import { jsx as jsx91, jsxs as jsxs82 } from "react/jsx-runtime";
11745
+ import { jsx as jsx92, jsxs as jsxs82 } from "react/jsx-runtime";
11731
11746
  var IMPORTANCE_LEVELS = [
11732
11747
  { id: "nudge", rank: 1, label: "Nudge", icon: "feather", description: "Breaks a tie, nothing more." },
11733
11748
  { id: "lean", rank: 2, label: "Lean", icon: "arrow-bend-up-right", description: "A mild preference between otherwise equal options." },
@@ -11765,16 +11780,16 @@ function ImportanceTag({ level, showLabel = true, size = "sm", className = "", d
11765
11780
  title: lvl.label + " \u2014 " + lvl.description,
11766
11781
  "aria-disabled": disabled ? "true" : void 0,
11767
11782
  children: [
11768
- /* @__PURE__ */ jsx91("i", { className: "ph ph-" + lvl.icon, "aria-hidden": "true" }),
11769
- showLabel ? lvl.label : /* @__PURE__ */ jsx91("span", { className: "fd-sr", children: lvl.label })
11783
+ /* @__PURE__ */ jsx92("i", { className: "ph ph-" + lvl.icon, "aria-hidden": "true" }),
11784
+ showLabel ? lvl.label : /* @__PURE__ */ jsx92("span", { className: "fd-sr", children: lvl.label })
11770
11785
  ]
11771
11786
  }
11772
11787
  );
11773
11788
  }
11774
11789
 
11775
11790
  // src/components/planner/PreferenceMeter.tsx
11776
- import * as React62 from "react";
11777
- import { jsx as jsx92, jsxs as jsxs83 } from "react/jsx-runtime";
11791
+ import * as React63 from "react";
11792
+ import { jsx as jsx93, jsxs as jsxs83 } from "react/jsx-runtime";
11778
11793
  function preferenceScore(criteria) {
11779
11794
  const earned = criteria.reduce((n, c) => n + (Number(c.earned) || 0), 0);
11780
11795
  const weight = criteria.reduce((n, c) => n + (Number(c.weight) || 0), 0);
@@ -11803,8 +11818,8 @@ function PreferenceMeter({
11803
11818
  className = ""
11804
11819
  }) {
11805
11820
  const value = score == null ? preferenceScore(criteria) : score;
11806
- const segments = React62.useMemo(() => preferenceSegments(criteria), [criteria]);
11807
- return /* @__PURE__ */ jsx92(
11821
+ const segments = React63.useMemo(() => preferenceSegments(criteria), [criteria]);
11822
+ return /* @__PURE__ */ jsx93(
11808
11823
  ScoreMeter,
11809
11824
  {
11810
11825
  score: value,
@@ -11818,20 +11833,20 @@ function PreferenceMeter({
11818
11833
  breakdownLabel: breakdownTitle,
11819
11834
  breakdown: /* @__PURE__ */ jsxs83("div", { className: "fd-prefbreak", children: [
11820
11835
  /* @__PURE__ */ jsxs83("div", { className: "fd-prefbreak-head", children: [
11821
- /* @__PURE__ */ jsx92("span", { className: "fd-label-lg", children: breakdownTitle }),
11822
- /* @__PURE__ */ jsx92("span", { className: "fd-prefbreak-score fd-tabular", children: Math.round(value) })
11836
+ /* @__PURE__ */ jsx93("span", { className: "fd-label-lg", children: breakdownTitle }),
11837
+ /* @__PURE__ */ jsx93("span", { className: "fd-prefbreak-score fd-tabular", children: Math.round(value) })
11823
11838
  ] }),
11824
- /* @__PURE__ */ jsx92("ul", { className: "fd-prefbreak-list", children: criteria.map((c) => {
11839
+ /* @__PURE__ */ jsx93("ul", { className: "fd-prefbreak-list", children: criteria.map((c) => {
11825
11840
  const pct = c.weight > 0 ? Math.round((Number(c.earned) || 0) / c.weight * 100) : 0;
11826
11841
  return /* @__PURE__ */ jsxs83("li", { className: pct === 0 ? "fd-prefbreak-item is-unmet" : "fd-prefbreak-item", children: [
11827
- /* @__PURE__ */ jsx92(ImportanceTag, { level: c.importance }),
11842
+ /* @__PURE__ */ jsx93(ImportanceTag, { level: c.importance }),
11828
11843
  /* @__PURE__ */ jsxs83("span", { className: "fd-prefbreak-text", children: [
11829
- /* @__PURE__ */ jsx92("span", { className: "fd-prefbreak-label", children: c.label }),
11830
- c.note ? /* @__PURE__ */ jsx92("span", { className: "fd-prefbreak-note", children: c.note }) : null
11844
+ /* @__PURE__ */ jsx93("span", { className: "fd-prefbreak-label", children: c.label }),
11845
+ c.note ? /* @__PURE__ */ jsx93("span", { className: "fd-prefbreak-note", children: c.note }) : null
11831
11846
  ] }),
11832
11847
  /* @__PURE__ */ jsxs83("span", { className: "fd-prefbreak-val fd-tabular", children: [
11833
11848
  Math.round(Number(c.earned) || 0),
11834
- /* @__PURE__ */ jsx92("span", { className: "fd-prefbreak-sep", children: "/" }),
11849
+ /* @__PURE__ */ jsx93("span", { className: "fd-prefbreak-sep", children: "/" }),
11835
11850
  Math.round(c.weight)
11836
11851
  ] })
11837
11852
  ] }, c.id);
@@ -11842,10 +11857,10 @@ function PreferenceMeter({
11842
11857
  }
11843
11858
 
11844
11859
  // src/components/chat/AgentChatPanel.tsx
11845
- import * as React68 from "react";
11860
+ import * as React69 from "react";
11846
11861
 
11847
11862
  // src/components/chat/chatEngine.ts
11848
- import * as React63 from "react";
11863
+ import * as React64 from "react";
11849
11864
  var CHAT_UNAVAILABLE = "chat_unavailable";
11850
11865
  var JOB_PENDING = ["queued", "running"];
11851
11866
  var JOB_SUCCESS = ["completed", "recovered"];
@@ -11899,22 +11914,22 @@ function useChatEngine(opts) {
11899
11914
  onClear,
11900
11915
  onFeedback
11901
11916
  } = opts || {};
11902
- const [status, setStatus] = React63.useState("idle");
11903
- const [threadId, setThreadId] = React63.useState(null);
11904
- const [messages, setMessages] = React63.useState([]);
11905
- const [queue, setQueue] = React63.useState([]);
11906
- const [fatal, setFatal] = React63.useState(null);
11907
- const [busy, setBusy] = React63.useState(false);
11908
- const [turnStartedAt, setTurnStartedAt] = React63.useState(null);
11909
- const listRef = React63.useRef([]);
11910
- const queueRef = React63.useRef([]);
11911
- const busyRef = React63.useRef(false);
11912
- const stoppedRef = React63.useRef(false);
11913
- const abortRef = React63.useRef(null);
11914
- const serverCount = React63.useRef(0);
11915
- const threadRef = React63.useRef(null);
11916
- const mounted = React63.useRef(true);
11917
- React63.useEffect(() => {
11917
+ const [status, setStatus] = React64.useState("idle");
11918
+ const [threadId, setThreadId] = React64.useState(null);
11919
+ const [messages, setMessages] = React64.useState([]);
11920
+ const [queue, setQueue] = React64.useState([]);
11921
+ const [fatal, setFatal] = React64.useState(null);
11922
+ const [busy, setBusy] = React64.useState(false);
11923
+ const [turnStartedAt, setTurnStartedAt] = React64.useState(null);
11924
+ const listRef = React64.useRef([]);
11925
+ const queueRef = React64.useRef([]);
11926
+ const busyRef = React64.useRef(false);
11927
+ const stoppedRef = React64.useRef(false);
11928
+ const abortRef = React64.useRef(null);
11929
+ const serverCount = React64.useRef(0);
11930
+ const threadRef = React64.useRef(null);
11931
+ const mounted = React64.useRef(true);
11932
+ React64.useEffect(() => {
11918
11933
  mounted.current = true;
11919
11934
  return () => {
11920
11935
  mounted.current = false;
@@ -11936,14 +11951,14 @@ function useChatEngine(opts) {
11936
11951
  }
11937
11952
  return false;
11938
11953
  };
11939
- const loadThread = React63.useCallback(async (id) => {
11954
+ const loadThread = React64.useCallback(async (id) => {
11940
11955
  const data = await apiAdapter.getThread(id);
11941
11956
  const list = [...data && data.messages || []];
11942
11957
  serverCount.current = list.length;
11943
11958
  commit(list);
11944
11959
  return list;
11945
11960
  }, [apiAdapter]);
11946
- React63.useEffect(() => {
11961
+ React64.useEffect(() => {
11947
11962
  if (!apiAdapter) {
11948
11963
  setStatus("idle");
11949
11964
  setFatal(null);
@@ -12156,7 +12171,7 @@ function useChatEngine(opts) {
12156
12171
  await dispatchTurn(turn);
12157
12172
  }
12158
12173
  }
12159
- const send = React63.useCallback((text, attachments) => {
12174
+ const send = React64.useCallback((text, attachments) => {
12160
12175
  const body = (text || "").trim();
12161
12176
  if (!body && !(attachments && attachments.length)) return;
12162
12177
  if (status === "disconnected") return;
@@ -12166,7 +12181,7 @@ function useChatEngine(opts) {
12166
12181
  stoppedRef.current = false;
12167
12182
  drain();
12168
12183
  }, [status]);
12169
- const stop = React63.useCallback(() => {
12184
+ const stop = React64.useCallback(() => {
12170
12185
  stoppedRef.current = true;
12171
12186
  const ac = abortRef.current;
12172
12187
  if (ac) {
@@ -12185,11 +12200,11 @@ function useChatEngine(opts) {
12185
12200
  store.del(STORAGE_PREFIX + threadRef.current);
12186
12201
  }
12187
12202
  }, [apiAdapter]);
12188
- const removeQueued = React63.useCallback((id) => {
12203
+ const removeQueued = React64.useCallback((id) => {
12189
12204
  queueRef.current = queueRef.current.filter((t) => t.id !== id);
12190
12205
  setQueue(queueRef.current.slice());
12191
12206
  }, []);
12192
- const retry = React63.useCallback(() => {
12207
+ const retry = React64.useCallback(() => {
12193
12208
  const list = listRef.current;
12194
12209
  let at = -1;
12195
12210
  for (let i = list.length - 1; i >= 0; i--) if (list[i].role === "user") {
@@ -12205,19 +12220,19 @@ function useChatEngine(opts) {
12205
12220
  setQueue(queueRef.current.slice());
12206
12221
  drain();
12207
12222
  }, []);
12208
- const clear = React63.useCallback(() => {
12223
+ const clear = React64.useCallback(() => {
12209
12224
  commit([]);
12210
12225
  serverCount.current = 0;
12211
12226
  queueRef.current = [];
12212
12227
  setQueue([]);
12213
12228
  onClear && onClear();
12214
12229
  }, [onClear]);
12215
- const setFeedback = React63.useCallback((id, value) => {
12230
+ const setFeedback = React64.useCallback((id, value) => {
12216
12231
  patch(id, (m) => ({ feedback: m.feedback === value ? null : value }));
12217
12232
  const msg = listRef.current.find((m) => m.id === id);
12218
12233
  onFeedback && onFeedback({ message: msg, feedback: msg ? msg.feedback : value });
12219
12234
  }, [onFeedback]);
12220
- const reload = React63.useCallback(async () => {
12235
+ const reload = React64.useCallback(async () => {
12221
12236
  if (!threadRef.current) return;
12222
12237
  setStatus("loading");
12223
12238
  try {
@@ -12255,11 +12270,11 @@ var ChatKit = {
12255
12270
  };
12256
12271
 
12257
12272
  // src/components/chat/ChatTranscript.tsx
12258
- import * as React65 from "react";
12273
+ import * as React66 from "react";
12259
12274
 
12260
12275
  // src/components/chat/ChatTurn.tsx
12261
- import * as React64 from "react";
12262
- import { jsx as jsx93, jsxs as jsxs84 } from "react/jsx-runtime";
12276
+ import * as React65 from "react";
12277
+ import { jsx as jsx94, jsxs as jsxs84 } from "react/jsx-runtime";
12263
12278
  function JsonView({ value }) {
12264
12279
  let text;
12265
12280
  try {
@@ -12267,7 +12282,7 @@ function JsonView({ value }) {
12267
12282
  } catch (e) {
12268
12283
  text = String(value);
12269
12284
  }
12270
- return /* @__PURE__ */ jsx93(CodeBlock, { code: text, language: "json", collapseAfter: 18 });
12285
+ return /* @__PURE__ */ jsx94(CodeBlock, { code: text, language: "json", collapseAfter: 18 });
12271
12286
  }
12272
12287
  function PacketCard({ packet, schema, render, onApply, applied }) {
12273
12288
  if (!packet) return null;
@@ -12276,58 +12291,58 @@ function PacketCard({ packet, schema, render, onApply, applied }) {
12276
12291
  const title = s.heading || packet.type;
12277
12292
  return /* @__PURE__ */ jsxs84("section", { className: "fdc-packet" + (invalid ? " is-invalid" : ""), "aria-label": title, children: [
12278
12293
  /* @__PURE__ */ jsxs84("header", { className: "fdc-packet-head", children: [
12279
- /* @__PURE__ */ jsx93("i", { className: "ph ph-" + (s.icon || "package"), "aria-hidden": "true" }),
12280
- /* @__PURE__ */ jsx93("span", { className: "fdc-packet-title", title: truncationTitle(title), children: title }),
12281
- packet.repaired ? /* @__PURE__ */ jsx93("span", { className: "fdc-packet-badge", children: "Repaired" }) : null,
12282
- invalid ? /* @__PURE__ */ jsx93("span", { className: "fdc-packet-badge is-danger", children: "Invalid" }) : null
12294
+ /* @__PURE__ */ jsx94("i", { className: "ph ph-" + (s.icon || "package"), "aria-hidden": "true" }),
12295
+ /* @__PURE__ */ jsx94("span", { className: "fdc-packet-title", title: truncationTitle(title), children: title }),
12296
+ packet.repaired ? /* @__PURE__ */ jsx94("span", { className: "fdc-packet-badge", children: "Repaired" }) : null,
12297
+ invalid ? /* @__PURE__ */ jsx94("span", { className: "fdc-packet-badge is-danger", children: "Invalid" }) : null
12283
12298
  ] }),
12284
12299
  invalid ? /* @__PURE__ */ jsxs84("div", { className: "fdc-packet-alert", role: "alert", children: [
12285
- /* @__PURE__ */ jsx93("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
12286
- /* @__PURE__ */ jsx93("span", { children: packet.error || "This result failed validation and can\u2019t be applied." })
12287
- ] }) : /* @__PURE__ */ jsx93("div", { className: "fdc-packet-body", children: render ? render(packet) : /* @__PURE__ */ jsx93(JsonView, { value: packet.payload }) }),
12300
+ /* @__PURE__ */ jsx94("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
12301
+ /* @__PURE__ */ jsx94("span", { children: packet.error || "This result failed validation and can\u2019t be applied." })
12302
+ ] }) : /* @__PURE__ */ jsx94("div", { className: "fdc-packet-body", children: render ? render(packet) : /* @__PURE__ */ jsx94(JsonView, { value: packet.payload }) }),
12288
12303
  !invalid && onApply ? /* @__PURE__ */ jsxs84("footer", { className: "fdc-packet-foot", children: [
12289
- packet.repaired ? /* @__PURE__ */ jsx93("span", { className: "fdc-packet-note", children: "Corrected by the backend after a first attempt." }) : /* @__PURE__ */ jsx93("span", {}),
12304
+ packet.repaired ? /* @__PURE__ */ jsx94("span", { className: "fdc-packet-note", children: "Corrected by the backend after a first attempt." }) : /* @__PURE__ */ jsx94("span", {}),
12290
12305
  /* @__PURE__ */ jsxs84("button", { type: "button", className: "fd-btn fd-btn-primary fd-btn-sm", disabled: applied, onClick: () => onApply(packet), children: [
12291
- /* @__PURE__ */ jsx93("i", { className: "ph ph-" + (applied ? "check" : "arrow-square-in"), "aria-hidden": "true" }),
12306
+ /* @__PURE__ */ jsx94("i", { className: "ph ph-" + (applied ? "check" : "arrow-square-in"), "aria-hidden": "true" }),
12292
12307
  applied ? "Applied" : s.applyLabel || "Apply"
12293
12308
  ] })
12294
12309
  ] }) : null
12295
12310
  ] });
12296
12311
  }
12297
12312
  function ThinkingBlock({ text, durationMs, streaming, defaultOpen = false }) {
12298
- const [open2, setOpen] = React64.useState(defaultOpen);
12313
+ const [open2, setOpen] = React65.useState(defaultOpen);
12299
12314
  if (!text) return null;
12300
12315
  return /* @__PURE__ */ jsxs84("div", { className: "fdc-think" + (open2 ? " is-open" : ""), children: [
12301
12316
  /* @__PURE__ */ jsxs84("button", { type: "button", className: "fdc-think-head", onClick: () => setOpen((v) => !v), "aria-expanded": open2, children: [
12302
- /* @__PURE__ */ jsx93("i", { className: "ph ph-brain", "aria-hidden": "true" }),
12303
- /* @__PURE__ */ jsx93("span", { children: streaming ? "Thinking" : durationMs ? "Thought for " + formatDuration(durationMs) : "Thought process" }),
12317
+ /* @__PURE__ */ jsx94("i", { className: "ph ph-brain", "aria-hidden": "true" }),
12318
+ /* @__PURE__ */ jsx94("span", { children: streaming ? "Thinking" : durationMs ? "Thought for " + formatDuration(durationMs) : "Thought process" }),
12304
12319
  streaming ? /* @__PURE__ */ jsxs84("span", { className: "fdc-dots", "aria-hidden": "true", children: [
12305
- /* @__PURE__ */ jsx93("span", {}),
12306
- /* @__PURE__ */ jsx93("span", {}),
12307
- /* @__PURE__ */ jsx93("span", {})
12320
+ /* @__PURE__ */ jsx94("span", {}),
12321
+ /* @__PURE__ */ jsx94("span", {}),
12322
+ /* @__PURE__ */ jsx94("span", {})
12308
12323
  ] }) : null,
12309
- /* @__PURE__ */ jsx93("i", { className: "ph ph-caret-" + (open2 ? "up" : "down"), "aria-hidden": "true" })
12324
+ /* @__PURE__ */ jsx94("i", { className: "ph ph-caret-" + (open2 ? "up" : "down"), "aria-hidden": "true" })
12310
12325
  ] }),
12311
- open2 ? /* @__PURE__ */ jsx93("div", { className: "fdc-think-body", children: text }) : null
12326
+ open2 ? /* @__PURE__ */ jsx94("div", { className: "fdc-think-body", children: text }) : null
12312
12327
  ] });
12313
12328
  }
12314
12329
  function Citations({ items = [], onOpen }) {
12315
- const [open2, setOpen] = React64.useState(false);
12330
+ const [open2, setOpen] = React65.useState(false);
12316
12331
  if (!items.length) return null;
12317
12332
  return /* @__PURE__ */ jsxs84("div", { className: "fdc-cites", children: [
12318
12333
  /* @__PURE__ */ jsxs84("button", { type: "button", className: "fdc-cites-head", onClick: () => setOpen((v) => !v), "aria-expanded": open2, children: [
12319
- /* @__PURE__ */ jsx93("i", { className: "ph ph-quotes", "aria-hidden": "true" }),
12334
+ /* @__PURE__ */ jsx94("i", { className: "ph ph-quotes", "aria-hidden": "true" }),
12320
12335
  /* @__PURE__ */ jsxs84("span", { children: [
12321
12336
  items.length,
12322
12337
  " source",
12323
12338
  items.length === 1 ? "" : "s"
12324
12339
  ] }),
12325
- /* @__PURE__ */ jsx93("i", { className: "ph ph-caret-" + (open2 ? "up" : "down"), "aria-hidden": "true" })
12340
+ /* @__PURE__ */ jsx94("i", { className: "ph ph-caret-" + (open2 ? "up" : "down"), "aria-hidden": "true" })
12326
12341
  ] }),
12327
- open2 ? /* @__PURE__ */ jsx93("ol", { className: "fdc-cites-list", children: items.map((c, i) => /* @__PURE__ */ jsxs84("li", { children: [
12328
- /* @__PURE__ */ jsx93("span", { className: "fdc-cite-n fd-tabular", children: c.marker || i + 1 }),
12329
- c.url ? /* @__PURE__ */ jsx93("a", { href: c.url, target: "_blank", rel: "noopener noreferrer", onClick: onOpen ? (e) => onOpen(c, e) : void 0, children: c.title || c.url }) : /* @__PURE__ */ jsx93("span", { children: c.title || "Source" }),
12330
- c.detail ? /* @__PURE__ */ jsx93("span", { className: "fdc-cite-detail", children: c.detail }) : null
12342
+ open2 ? /* @__PURE__ */ jsx94("ol", { className: "fdc-cites-list", children: items.map((c, i) => /* @__PURE__ */ jsxs84("li", { children: [
12343
+ /* @__PURE__ */ jsx94("span", { className: "fdc-cite-n fd-tabular", children: c.marker || i + 1 }),
12344
+ c.url ? /* @__PURE__ */ jsx94("a", { href: c.url, target: "_blank", rel: "noopener noreferrer", onClick: onOpen ? (e) => onOpen(c, e) : void 0, children: c.title || c.url }) : /* @__PURE__ */ jsx94("span", { children: c.title || "Source" }),
12345
+ c.detail ? /* @__PURE__ */ jsx94("span", { className: "fdc-cite-detail", children: c.detail }) : null
12331
12346
  ] }, c.id || i)) }) : null
12332
12347
  ] });
12333
12348
  }
@@ -12338,29 +12353,29 @@ function clampText(text, max) {
12338
12353
  return (at > max * 0.6 ? cut.slice(0, at) : cut).trimEnd() + "\u2026";
12339
12354
  }
12340
12355
  function MessageBody({ message: m, ctx }) {
12341
- const [expanded, setExpanded] = React64.useState(false);
12356
+ const [expanded, setExpanded] = React65.useState(false);
12342
12357
  const isUser = m.role === "user";
12343
12358
  const raw = m.text || "";
12344
12359
  const clamped = !expanded && !m.streaming ? clampText(raw, ctx.maxVisibleChars) : null;
12345
12360
  const body = clamped != null ? clamped : raw;
12346
12361
  const showMd = ctx.markdown && !isUser;
12347
12362
  return /* @__PURE__ */ jsxs84("div", { className: "fdc-body", children: [
12348
- m.thinking && ctx.showThinking ? /* @__PURE__ */ jsx93(ThinkingBlock, { text: m.thinking, durationMs: m.thinkingMs, streaming: m.streaming && !m.text }) : null,
12349
- m.steps && m.steps.length && ctx.showSteps ? /* @__PURE__ */ jsx93(StepList, { steps: m.steps, defaultOpen: m.steps.some((s) => s.status === "running"), dense: true }) : null,
12363
+ m.thinking && ctx.showThinking ? /* @__PURE__ */ jsx94(ThinkingBlock, { text: m.thinking, durationMs: m.thinkingMs, streaming: m.streaming && !m.text }) : null,
12364
+ m.steps && m.steps.length && ctx.showSteps ? /* @__PURE__ */ jsx94(StepList, { steps: m.steps, defaultOpen: m.steps.some((s) => s.status === "running"), dense: true }) : null,
12350
12365
  body ? /* @__PURE__ */ jsxs84("div", { className: "fdc-text" + (isUser ? " is-user" : ""), children: [
12351
- showMd ? /* @__PURE__ */ jsx93(Markdown, { source: body, headingOffset: 2, codeProps: { collapseAfter: 22 }, renderCitation: ctx.renderCitation }) : /* @__PURE__ */ jsx93("div", { className: "fdc-plain", children: body }),
12352
- m.streaming ? /* @__PURE__ */ jsx93("span", { className: "fdc-caret", "aria-hidden": "true" }) : null
12366
+ showMd ? /* @__PURE__ */ jsx94(Markdown, { source: body, headingOffset: 2, codeProps: { collapseAfter: 22 }, renderCitation: ctx.renderCitation }) : /* @__PURE__ */ jsx94("div", { className: "fdc-plain", children: body }),
12367
+ m.streaming ? /* @__PURE__ */ jsx94("span", { className: "fdc-caret", "aria-hidden": "true" }) : null
12353
12368
  ] }) : null,
12354
12369
  clamped != null ? /* @__PURE__ */ jsxs84("button", { type: "button", className: "fdc-more", onClick: () => setExpanded(true), children: [
12355
- /* @__PURE__ */ jsx93("i", { className: "ph ph-caret-down", "aria-hidden": "true" }),
12370
+ /* @__PURE__ */ jsx94("i", { className: "ph ph-caret-down", "aria-hidden": "true" }),
12356
12371
  "Show more",
12357
- /* @__PURE__ */ jsx93("span", { className: "fdc-more-len fd-tabular", children: raw.length < 2e3 ? raw.length.toLocaleString() + " characters" : Math.round(raw.length / 100) / 10 + "k characters" })
12372
+ /* @__PURE__ */ jsx94("span", { className: "fdc-more-len fd-tabular", children: raw.length < 2e3 ? raw.length.toLocaleString() + " characters" : Math.round(raw.length / 100) / 10 + "k characters" })
12358
12373
  ] }) : expanded && ctx.maxVisibleChars && raw.length > ctx.maxVisibleChars ? /* @__PURE__ */ jsxs84("button", { type: "button", className: "fdc-more", onClick: () => setExpanded(false), children: [
12359
- /* @__PURE__ */ jsx93("i", { className: "ph ph-caret-up", "aria-hidden": "true" }),
12374
+ /* @__PURE__ */ jsx94("i", { className: "ph ph-caret-up", "aria-hidden": "true" }),
12360
12375
  "Show less"
12361
12376
  ] }) : null,
12362
- m.attachments && m.attachments.length ? /* @__PURE__ */ jsx93(FileGrid, { files: m.attachments, onOpen: ctx.onOpenAttachment, tiles: true, maxHeight: ctx.attachmentHeight || 220, compact: ctx.narrow }) : null,
12363
- m.packet ? /* @__PURE__ */ jsx93(
12377
+ m.attachments && m.attachments.length ? /* @__PURE__ */ jsx94(FileGrid, { files: m.attachments, onOpen: ctx.onOpenAttachment, tiles: true, maxHeight: ctx.attachmentHeight || 220, compact: ctx.narrow }) : null,
12378
+ m.packet ? /* @__PURE__ */ jsx94(
12364
12379
  PacketCard,
12365
12380
  {
12366
12381
  packet: m.packet,
@@ -12370,12 +12385,12 @@ function MessageBody({ message: m, ctx }) {
12370
12385
  applied: ctx.appliedPackets && ctx.appliedPackets[m.id]
12371
12386
  }
12372
12387
  ) : null,
12373
- m.citations && m.citations.length ? /* @__PURE__ */ jsx93(Citations, { items: m.citations, onOpen: ctx.onOpenCitation }) : null,
12388
+ m.citations && m.citations.length ? /* @__PURE__ */ jsx94(Citations, { items: m.citations, onOpen: ctx.onOpenCitation }) : null,
12374
12389
  m.working ? /* @__PURE__ */ jsxs84("div", { className: "fdc-working", role: "status", children: [
12375
12390
  /* @__PURE__ */ jsxs84("span", { className: "fdc-dots", "aria-hidden": "true", children: [
12376
- /* @__PURE__ */ jsx93("span", {}),
12377
- /* @__PURE__ */ jsx93("span", {}),
12378
- /* @__PURE__ */ jsx93("span", {})
12391
+ /* @__PURE__ */ jsx94("span", {}),
12392
+ /* @__PURE__ */ jsx94("span", {}),
12393
+ /* @__PURE__ */ jsx94("span", {})
12379
12394
  ] }),
12380
12395
  /* @__PURE__ */ jsxs84("span", { className: "fdc-working-label", children: [
12381
12396
  m.resumed ? "Resuming" : "Working",
@@ -12388,17 +12403,17 @@ function MessageBody({ message: m, ctx }) {
12388
12403
  m.job.detail
12389
12404
  ] }) : null
12390
12405
  ] }),
12391
- m.jobId ? /* @__PURE__ */ jsx93("span", { className: "fdc-working-id fd-mono", children: String(m.jobId).slice(0, 12) }) : null
12406
+ m.jobId ? /* @__PURE__ */ jsx94("span", { className: "fdc-working-id fd-mono", children: String(m.jobId).slice(0, 12) }) : null
12392
12407
  ] }) : null,
12393
12408
  m.stopped ? /* @__PURE__ */ jsxs84("div", { className: "fdc-stopped", children: [
12394
- /* @__PURE__ */ jsx93("i", { className: "ph ph-stop-circle", "aria-hidden": "true" }),
12409
+ /* @__PURE__ */ jsx94("i", { className: "ph ph-stop-circle", "aria-hidden": "true" }),
12395
12410
  "Stopped"
12396
12411
  ] }) : null,
12397
12412
  m.error ? /* @__PURE__ */ jsxs84("div", { className: "fdc-error", role: "alert", children: [
12398
- /* @__PURE__ */ jsx93("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
12399
- /* @__PURE__ */ jsx93("span", { className: "fdc-error-text", children: ctx.errorCopy ? ctx.errorCopy(m.error) : m.error }),
12413
+ /* @__PURE__ */ jsx94("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
12414
+ /* @__PURE__ */ jsx94("span", { className: "fdc-error-text", children: ctx.errorCopy ? ctx.errorCopy(m.error) : m.error }),
12400
12415
  m.retryable && ctx.onRetry ? /* @__PURE__ */ jsxs84("button", { type: "button", className: "fdc-error-retry", onClick: ctx.onRetry, children: [
12401
- /* @__PURE__ */ jsx93("i", { className: "ph ph-arrow-clockwise", "aria-hidden": "true" }),
12416
+ /* @__PURE__ */ jsx94("i", { className: "ph ph-arrow-clockwise", "aria-hidden": "true" }),
12402
12417
  "Retry"
12403
12418
  ] }) : null
12404
12419
  ] }) : null
@@ -12413,14 +12428,14 @@ function RunActions({ group, ctx }) {
12413
12428
  if (!ctx.messageActions) return null;
12414
12429
  return /* @__PURE__ */ jsxs84("div", { className: "fdc-actions", role: "group", "aria-label": "Message actions", children: [
12415
12430
  /* @__PURE__ */ jsxs84("button", { type: "button", className: "fdc-act" + (copied ? " is-done" : ""), onClick: () => copy(markdownToText(text)), "aria-label": "Copy message", children: [
12416
- /* @__PURE__ */ jsx93("i", { className: "ph ph-" + (copied ? "check" : "copy"), "aria-hidden": "true" }),
12417
- /* @__PURE__ */ jsx93("span", { className: "fdc-act-label", children: copied ? "Copied" : "Copy" })
12431
+ /* @__PURE__ */ jsx94("i", { className: "ph ph-" + (copied ? "check" : "copy"), "aria-hidden": "true" }),
12432
+ /* @__PURE__ */ jsx94("span", { className: "fdc-act-label", children: copied ? "Copied" : "Copy" })
12418
12433
  ] }),
12419
- isAssistant && ctx.onRetry ? /* @__PURE__ */ jsx93("button", { type: "button", className: "fdc-act", onClick: ctx.onRetry, "aria-label": "Retry this turn", children: /* @__PURE__ */ jsx93("i", { className: "ph ph-arrow-clockwise", "aria-hidden": "true" }) }) : null,
12420
- group.role === "user" && ctx.onEdit ? /* @__PURE__ */ jsx93("button", { type: "button", className: "fdc-act", onClick: () => ctx.onEdit(last), "aria-label": "Edit and resend", children: /* @__PURE__ */ jsx93("i", { className: "ph ph-pencil-simple", "aria-hidden": "true" }) }) : null,
12421
- isAssistant && ctx.onFeedback ? /* @__PURE__ */ jsxs84(React64.Fragment, { children: [
12422
- /* @__PURE__ */ jsx93("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__ */ jsx93("i", { className: "ph ph-thumbs-up", "aria-hidden": "true" }) }),
12423
- /* @__PURE__ */ jsx93("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__ */ jsx93("i", { className: "ph ph-thumbs-down", "aria-hidden": "true" }) })
12434
+ isAssistant && ctx.onRetry ? /* @__PURE__ */ jsx94("button", { type: "button", className: "fdc-act", onClick: ctx.onRetry, "aria-label": "Retry this turn", children: /* @__PURE__ */ jsx94("i", { className: "ph ph-arrow-clockwise", "aria-hidden": "true" }) }) : null,
12435
+ group.role === "user" && ctx.onEdit ? /* @__PURE__ */ jsx94("button", { type: "button", className: "fdc-act", onClick: () => ctx.onEdit(last), "aria-label": "Edit and resend", children: /* @__PURE__ */ jsx94("i", { className: "ph ph-pencil-simple", "aria-hidden": "true" }) }) : null,
12436
+ isAssistant && ctx.onFeedback ? /* @__PURE__ */ jsxs84(React65.Fragment, { children: [
12437
+ /* @__PURE__ */ jsx94("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__ */ jsx94("i", { className: "ph ph-thumbs-up", "aria-hidden": "true" }) }),
12438
+ /* @__PURE__ */ jsx94("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__ */ jsx94("i", { className: "ph ph-thumbs-down", "aria-hidden": "true" }) })
12424
12439
  ] }) : null,
12425
12440
  ctx.extraActions ? ctx.extraActions(group) : null
12426
12441
  ] });
@@ -12432,20 +12447,20 @@ function ChatTurn({ group, ctx }) {
12432
12447
  const stamp = group.messages[0].timestamp;
12433
12448
  return /* @__PURE__ */ jsxs84("article", { className: "fdc-turn is-" + group.role, "aria-label": String(name) + (stamp ? " at " + formatClock(stamp) : ""), children: [
12434
12449
  /* @__PURE__ */ jsxs84("div", { className: "fdc-turn-head", children: [
12435
- ctx.showAvatars ? /* @__PURE__ */ jsx93("span", { className: "fdc-avatar is-" + group.role, "aria-hidden": "true", children: avatar ? /* @__PURE__ */ jsx93("img", { src: avatar, alt: "" }) : isUser ? /* @__PURE__ */ jsx93("span", { className: "fdc-avatar-txt", children: (name || "You").slice(0, 1).toUpperCase() }) : /* @__PURE__ */ jsx93("i", { className: "ph ph-" + (ctx.assistantIcon || "sparkle") }) }) : null,
12436
- /* @__PURE__ */ jsx93("span", { className: "fdc-who", children: name }),
12437
- stamp ? /* @__PURE__ */ jsx93(RelativeTime, { className: "fdc-when", value: stamp }) : null,
12438
- group.messages.some((m) => m.model) ? /* @__PURE__ */ jsx93("span", { className: "fdc-turn-model", children: group.messages.find((m) => m.model).model }) : null
12450
+ ctx.showAvatars ? /* @__PURE__ */ jsx94("span", { className: "fdc-avatar is-" + group.role, "aria-hidden": "true", children: avatar ? /* @__PURE__ */ jsx94("img", { src: avatar, alt: "" }) : isUser ? /* @__PURE__ */ jsx94("span", { className: "fdc-avatar-txt", children: (name || "You").slice(0, 1).toUpperCase() }) : /* @__PURE__ */ jsx94("i", { className: "ph ph-" + (ctx.assistantIcon || "sparkle") }) }) : null,
12451
+ /* @__PURE__ */ jsx94("span", { className: "fdc-who", children: name }),
12452
+ stamp ? /* @__PURE__ */ jsx94(RelativeTime, { className: "fdc-when", value: stamp }) : null,
12453
+ group.messages.some((m) => m.model) ? /* @__PURE__ */ jsx94("span", { className: "fdc-turn-model", children: group.messages.find((m) => m.model).model }) : null
12439
12454
  ] }),
12440
12455
  /* @__PURE__ */ jsxs84("div", { className: "fdc-turn-body", children: [
12441
- group.messages.map((m) => /* @__PURE__ */ jsx93("div", { className: "fdc-msg" + (m.pending ? " is-pending" : ""), children: /* @__PURE__ */ jsx93(MessageBody, { message: m, ctx }) }, m.id)),
12442
- /* @__PURE__ */ jsx93(RunActions, { group, ctx })
12456
+ group.messages.map((m) => /* @__PURE__ */ jsx94("div", { className: "fdc-msg" + (m.pending ? " is-pending" : ""), children: /* @__PURE__ */ jsx94(MessageBody, { message: m, ctx }) }, m.id)),
12457
+ /* @__PURE__ */ jsx94(RunActions, { group, ctx })
12443
12458
  ] })
12444
12459
  ] });
12445
12460
  }
12446
12461
 
12447
12462
  // src/components/chat/ChatTranscript.tsx
12448
- import { jsx as jsx94, jsxs as jsxs85 } from "react/jsx-runtime";
12463
+ import { jsx as jsx95, jsxs as jsxs85 } from "react/jsx-runtime";
12449
12464
  var GROUP_WINDOW = 6e4;
12450
12465
  var STICK_PX = 100;
12451
12466
  function groupMessages(list) {
@@ -12478,25 +12493,25 @@ function dayLabel(key) {
12478
12493
  }
12479
12494
  function Suggestions({ items = [], onPick }) {
12480
12495
  if (!items.length) return null;
12481
- return /* @__PURE__ */ jsx94("div", { className: "fdc-suggest", children: items.map((s, i) => {
12496
+ return /* @__PURE__ */ jsx95("div", { className: "fdc-suggest", children: items.map((s, i) => {
12482
12497
  const it = typeof s === "string" ? { label: s, text: s } : s;
12483
12498
  return /* @__PURE__ */ jsxs85("button", { type: "button", className: "fdc-suggest-item", onClick: () => onPick && onPick(it.text || it.label), children: [
12484
- it.icon ? /* @__PURE__ */ jsx94("i", { className: "ph ph-" + it.icon, "aria-hidden": "true" }) : null,
12499
+ it.icon ? /* @__PURE__ */ jsx95("i", { className: "ph ph-" + it.icon, "aria-hidden": "true" }) : null,
12485
12500
  /* @__PURE__ */ jsxs85("span", { className: "fdc-suggest-text", children: [
12486
- /* @__PURE__ */ jsx94("span", { className: "fdc-suggest-label", children: it.label }),
12487
- it.description ? /* @__PURE__ */ jsx94("span", { className: "fdc-suggest-desc", children: it.description }) : null
12501
+ /* @__PURE__ */ jsx95("span", { className: "fdc-suggest-label", children: it.label }),
12502
+ it.description ? /* @__PURE__ */ jsx95("span", { className: "fdc-suggest-desc", children: it.description }) : null
12488
12503
  ] }),
12489
- /* @__PURE__ */ jsx94("i", { className: "ph ph-arrow-up-right fdc-suggest-go", "aria-hidden": "true" })
12504
+ /* @__PURE__ */ jsx95("i", { className: "ph ph-arrow-up-right fdc-suggest-go", "aria-hidden": "true" })
12490
12505
  ] }, it.id || i);
12491
12506
  }) });
12492
12507
  }
12493
12508
  function LoadingTurns() {
12494
- return /* @__PURE__ */ jsx94("div", { className: "fdc-skel", "aria-hidden": "true", children: [0, 1].map((i) => /* @__PURE__ */ jsxs85("div", { className: "fdc-skel-turn", children: [
12495
- /* @__PURE__ */ jsx94("div", { className: "fd-skel fd-skel-circle", style: { width: 22, height: 22 } }),
12509
+ return /* @__PURE__ */ jsx95("div", { className: "fdc-skel", "aria-hidden": "true", children: [0, 1].map((i) => /* @__PURE__ */ jsxs85("div", { className: "fdc-skel-turn", children: [
12510
+ /* @__PURE__ */ jsx95("div", { className: "fd-skel fd-skel-circle", style: { width: 22, height: 22 } }),
12496
12511
  /* @__PURE__ */ jsxs85("div", { className: "fdc-skel-lines", children: [
12497
- /* @__PURE__ */ jsx94("div", { className: "fd-skel", style: { width: i ? "62%" : "44%", height: 11 } }),
12498
- /* @__PURE__ */ jsx94("div", { className: "fd-skel", style: { width: i ? "94%" : "78%", height: 11 } }),
12499
- /* @__PURE__ */ jsx94("div", { className: "fd-skel", style: { width: i ? "71%" : "56%", height: 11 } })
12512
+ /* @__PURE__ */ jsx95("div", { className: "fd-skel", style: { width: i ? "62%" : "44%", height: 11 } }),
12513
+ /* @__PURE__ */ jsx95("div", { className: "fd-skel", style: { width: i ? "94%" : "78%", height: 11 } }),
12514
+ /* @__PURE__ */ jsx95("div", { className: "fd-skel", style: { width: i ? "71%" : "56%", height: 11 } })
12500
12515
  ] })
12501
12516
  ] }, i)) });
12502
12517
  }
@@ -12513,10 +12528,10 @@ function ChatTranscript({
12513
12528
  renderEmpty,
12514
12529
  className = ""
12515
12530
  }) {
12516
- const scroller = React65.useRef(null);
12517
- const stick = React65.useRef(true);
12518
- const [pill, setPill] = React65.useState(0);
12519
- const seen = React65.useRef(0);
12531
+ const scroller = React66.useRef(null);
12532
+ const stick = React66.useRef(true);
12533
+ const [pill, setPill] = React66.useState(0);
12534
+ const seen = React66.useRef(0);
12520
12535
  const toBottom = (smooth) => {
12521
12536
  const el = scroller.current;
12522
12537
  if (!el) return;
@@ -12535,7 +12550,7 @@ function ChatTranscript({
12535
12550
  seen.current = messages.length;
12536
12551
  }
12537
12552
  };
12538
- React65.useLayoutEffect(() => {
12553
+ React66.useLayoutEffect(() => {
12539
12554
  const el = scroller.current;
12540
12555
  if (!el) return;
12541
12556
  if (stick.current) {
@@ -12543,7 +12558,7 @@ function ChatTranscript({
12543
12558
  seen.current = messages.length;
12544
12559
  } else setPill(Math.max(0, messages.length - seen.current));
12545
12560
  }, [messages]);
12546
- React65.useEffect(() => {
12561
+ React66.useEffect(() => {
12547
12562
  const el = scroller.current;
12548
12563
  const inner = el && el.firstChild;
12549
12564
  if (!el || !inner || typeof ResizeObserver === "undefined") return;
@@ -12553,38 +12568,38 @@ function ChatTranscript({
12553
12568
  ro.observe(inner);
12554
12569
  return () => ro.disconnect();
12555
12570
  }, []);
12556
- const groups = React65.useMemo(() => groupMessages(messages), [messages]);
12571
+ const groups = React66.useMemo(() => groupMessages(messages), [messages]);
12557
12572
  const empty = !messages.length && status === "ready";
12558
12573
  return /* @__PURE__ */ jsxs85("div", { className: ["fdc-scroll", className].filter(Boolean).join(" "), ref: scroller, onScroll, children: [
12559
12574
  /* @__PURE__ */ jsxs85("div", { className: "fdc-log", role: "log", "aria-label": "Conversation", children: [
12560
- status === "loading" || status === "resolving" ? /* @__PURE__ */ jsx94(LoadingTurns, {}) : null,
12575
+ status === "loading" || status === "resolving" ? /* @__PURE__ */ jsx95(LoadingTurns, {}) : null,
12561
12576
  status === "disconnected" ? /* @__PURE__ */ jsxs85("div", { className: "fdc-dead", children: [
12562
- /* @__PURE__ */ jsx94("span", { className: "fdc-dead-icon", children: /* @__PURE__ */ jsx94("i", { className: "ph ph-plugs", "aria-hidden": "true" }) }),
12563
- /* @__PURE__ */ jsx94("h3", { className: "fdc-dead-title", children: ctx.deadTitle || "The assistant isn\u2019t reachable" }),
12564
- /* @__PURE__ */ jsx94("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." }),
12577
+ /* @__PURE__ */ jsx95("span", { className: "fdc-dead-icon", children: /* @__PURE__ */ jsx95("i", { className: "ph ph-plugs", "aria-hidden": "true" }) }),
12578
+ /* @__PURE__ */ jsx95("h3", { className: "fdc-dead-title", children: ctx.deadTitle || "The assistant isn\u2019t reachable" }),
12579
+ /* @__PURE__ */ jsx95("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." }),
12565
12580
  ctx.onReconnect ? /* @__PURE__ */ jsxs85("button", { type: "button", className: "fd-btn fd-btn-secondary fd-btn-sm", onClick: ctx.onReconnect, children: [
12566
- /* @__PURE__ */ jsx94("i", { className: "ph ph-arrow-clockwise", "aria-hidden": "true" }),
12581
+ /* @__PURE__ */ jsx95("i", { className: "ph ph-arrow-clockwise", "aria-hidden": "true" }),
12567
12582
  "Try again"
12568
12583
  ] }) : null
12569
12584
  ] }) : null,
12570
12585
  empty ? renderEmpty ? renderEmpty() : /* @__PURE__ */ jsxs85("div", { className: "fdc-empty", children: [
12571
- /* @__PURE__ */ jsx94("span", { className: "fdc-empty-icon", children: /* @__PURE__ */ jsx94("i", { className: "ph ph-" + emptyIcon, "aria-hidden": "true" }) }),
12572
- /* @__PURE__ */ jsx94("h3", { className: "fdc-empty-title", children: emptyTitle }),
12573
- emptyDescription ? /* @__PURE__ */ jsx94("p", { className: "fdc-empty-body", children: emptyDescription }) : null,
12574
- /* @__PURE__ */ jsx94(Suggestions, { items: suggestions, onPick })
12586
+ /* @__PURE__ */ jsx95("span", { className: "fdc-empty-icon", children: /* @__PURE__ */ jsx95("i", { className: "ph ph-" + emptyIcon, "aria-hidden": "true" }) }),
12587
+ /* @__PURE__ */ jsx95("h3", { className: "fdc-empty-title", children: emptyTitle }),
12588
+ emptyDescription ? /* @__PURE__ */ jsx95("p", { className: "fdc-empty-body", children: emptyDescription }) : null,
12589
+ /* @__PURE__ */ jsx95(Suggestions, { items: suggestions, onPick })
12575
12590
  ] }) : null,
12576
12591
  groups.map((g, i) => {
12577
12592
  const prev = groups[i - 1];
12578
12593
  const k = dayKey(g.messages[0].timestamp);
12579
12594
  const showDay = !!k && (!prev || dayKey(prev.messages[0].timestamp) !== k);
12580
- return /* @__PURE__ */ jsxs85(React65.Fragment, { children: [
12581
- showDay ? /* @__PURE__ */ jsx94("div", { className: "fdc-day", children: /* @__PURE__ */ jsx94("span", { children: dayLabel(k) }) }) : null,
12582
- /* @__PURE__ */ jsx94(ChatTurn, { group: g, ctx })
12595
+ return /* @__PURE__ */ jsxs85(React66.Fragment, { children: [
12596
+ showDay ? /* @__PURE__ */ jsx95("div", { className: "fdc-day", children: /* @__PURE__ */ jsx95("span", { children: dayLabel(k) }) }) : null,
12597
+ /* @__PURE__ */ jsx95(ChatTurn, { group: g, ctx })
12583
12598
  ] }, g.key || i);
12584
12599
  })
12585
12600
  ] }),
12586
12601
  pill ? /* @__PURE__ */ jsxs85("button", { type: "button", className: "fdc-pill", onClick: () => toBottom(true), children: [
12587
- /* @__PURE__ */ jsx94("i", { className: "ph ph-arrow-down", "aria-hidden": "true" }),
12602
+ /* @__PURE__ */ jsx95("i", { className: "ph ph-arrow-down", "aria-hidden": "true" }),
12588
12603
  pill,
12589
12604
  " new message",
12590
12605
  pill === 1 ? "" : "s"
@@ -12594,8 +12609,8 @@ function ChatTranscript({
12594
12609
  var TranscriptKit = { groupMessages };
12595
12610
 
12596
12611
  // src/components/chat/ChatComposer.tsx
12597
- import * as React66 from "react";
12598
- import { jsx as jsx95, jsxs as jsxs86 } from "react/jsx-runtime";
12612
+ import * as React67 from "react";
12613
+ import { jsx as jsx96, jsxs as jsxs86 } from "react/jsx-runtime";
12599
12614
  function ChatComposer({
12600
12615
  onSubmit,
12601
12616
  onStop,
@@ -12622,17 +12637,17 @@ function ChatComposer({
12622
12637
  onReject,
12623
12638
  onOpenAttachment
12624
12639
  }) {
12625
- const [text, setText] = React66.useState(draft || "");
12626
- const [trigger, setTrigger] = React66.useState(null);
12627
- const [mentionItems, setMentionItems] = React66.useState([]);
12628
- const [listening, setListening] = React66.useState(false);
12629
- const [notice, setNotice] = React66.useState(null);
12630
- const editor = React66.useRef(null);
12631
- const wrap = React66.useRef(null);
12632
- const stopVoice = React66.useRef(null);
12640
+ const [text, setText] = React67.useState(draft || "");
12641
+ const [trigger, setTrigger] = React67.useState(null);
12642
+ const [mentionItems, setMentionItems] = React67.useState([]);
12643
+ const [listening, setListening] = React67.useState(false);
12644
+ const [notice, setNotice] = React67.useState(null);
12645
+ const editor = React67.useRef(null);
12646
+ const wrap = React67.useRef(null);
12647
+ const stopVoice = React67.useRef(null);
12633
12648
  const staged = useStagedFiles(fileUploadHandler, { onError: () => {
12634
12649
  } });
12635
- React66.useEffect(() => {
12650
+ React67.useEffect(() => {
12636
12651
  if (draft != null && draft !== text) setText(draft);
12637
12652
  }, [draft]);
12638
12653
  const change = (v) => {
@@ -12668,7 +12683,7 @@ function ChatComposer({
12668
12683
  e.preventDefault();
12669
12684
  staged.add(found.files);
12670
12685
  };
12671
- React66.useEffect(() => {
12686
+ React67.useEffect(() => {
12672
12687
  if (!trigger || trigger.type !== "mention" || !mentionSources) {
12673
12688
  setMentionItems([]);
12674
12689
  return;
@@ -12686,7 +12701,7 @@ function ChatComposer({
12686
12701
  const q = (trigger.query || "").toLowerCase();
12687
12702
  setMentionItems(mentionSources.filter((m) => !q || (m.label + " " + (m.description || "")).toLowerCase().includes(q)));
12688
12703
  }, [trigger, mentionSources]);
12689
- const slashItems = React66.useMemo(() => {
12704
+ const slashItems = React67.useMemo(() => {
12690
12705
  if (!trigger || trigger.type !== "slash" || !slashCommands) return [];
12691
12706
  const q = (trigger.query || "").toLowerCase();
12692
12707
  return slashCommands.filter((c) => !q || (c.id + " " + c.label + " " + (c.description || "")).toLowerCase().includes(q));
@@ -12700,7 +12715,7 @@ function ChatComposer({
12700
12715
  description: it.description,
12701
12716
  icon: it.icon,
12702
12717
  meta: mention.meta,
12703
- shortcut: slash.shortcut ? /* @__PURE__ */ jsx95(KeyHint, { keys: slash.shortcut, size: "sm" }) : void 0,
12718
+ shortcut: slash.shortcut ? /* @__PURE__ */ jsx96(KeyHint, { keys: slash.shortcut, size: "sm" }) : void 0,
12704
12719
  onSelect: () => {
12705
12720
  const insert = trigger.type === "slash" ? slash.immediate ? "/" + slash.id : "/" + slash.id + " " : "@" + (mention.value || mention.label) + " ";
12706
12721
  editor.current && editor.current.replaceRange(trigger.from, trigger.to, insert);
@@ -12760,13 +12775,13 @@ function ChatComposer({
12760
12775
  };
12761
12776
  };
12762
12777
  return /* @__PURE__ */ jsxs86("div", { className: "fdc-composer" + (disabled ? " is-disabled" : "") + (narrow ? " is-narrow" : ""), children: [
12763
- queue.length ? /* @__PURE__ */ jsx95("div", { className: "fdc-queue", "aria-label": "Queued messages", children: queue.map((q) => /* @__PURE__ */ jsxs86("div", { className: "fdc-queue-row", children: [
12764
- /* @__PURE__ */ jsx95("i", { className: "ph ph-clock-countdown", "aria-hidden": "true" }),
12765
- /* @__PURE__ */ jsx95("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)" : "") }),
12766
- onRemoveQueued ? /* @__PURE__ */ jsx95("button", { type: "button", className: "fdc-queue-x", onClick: () => onRemoveQueued(q.id), "aria-label": "Remove queued message", children: /* @__PURE__ */ jsx95("i", { className: "ph ph-x", "aria-hidden": "true" }) }) : null
12778
+ queue.length ? /* @__PURE__ */ jsx96("div", { className: "fdc-queue", "aria-label": "Queued messages", children: queue.map((q) => /* @__PURE__ */ jsxs86("div", { className: "fdc-queue-row", children: [
12779
+ /* @__PURE__ */ jsx96("i", { className: "ph ph-clock-countdown", "aria-hidden": "true" }),
12780
+ /* @__PURE__ */ jsx96("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)" : "") }),
12781
+ onRemoveQueued ? /* @__PURE__ */ jsx96("button", { type: "button", className: "fdc-queue-x", onClick: () => onRemoveQueued(q.id), "aria-label": "Remove queued message", children: /* @__PURE__ */ jsx96("i", { className: "ph ph-x", "aria-hidden": "true" }) }) : null
12767
12782
  ] }, q.id)) }) : null,
12768
12783
  sessionBar,
12769
- /* @__PURE__ */ jsx95(
12784
+ /* @__PURE__ */ jsx96(
12770
12785
  Dropzone,
12771
12786
  {
12772
12787
  className: "fdc-field",
@@ -12781,8 +12796,8 @@ function ChatComposer({
12781
12796
  label: "Drop to attach",
12782
12797
  hint: acceptFiles ? acceptFiles.replace(/,/g, " \xB7 ") : void 0,
12783
12798
  children: /* @__PURE__ */ jsxs86("div", { ref: wrap, className: "fdc-field-inner", children: [
12784
- staged.items.length ? /* @__PURE__ */ jsx95("div", { className: "fdc-staged", children: /* @__PURE__ */ jsx95(FileStrip, { files: staged.items, size: narrow ? 60 : 68, onRemove: staged.remove, onRetry: staged.retry, onOpen: onOpenAttachment }) }) : null,
12785
- /* @__PURE__ */ jsx95(
12799
+ staged.items.length ? /* @__PURE__ */ jsx96("div", { className: "fdc-staged", children: /* @__PURE__ */ jsx96(FileStrip, { files: staged.items, size: narrow ? 60 : 68, onRemove: staged.remove, onRetry: staged.retry, onOpen: onOpenAttachment }) }) : null,
12800
+ /* @__PURE__ */ jsx96(
12786
12801
  MarkdownEditor,
12787
12802
  {
12788
12803
  ref: editor,
@@ -12802,32 +12817,32 @@ function ChatComposer({
12802
12817
  }
12803
12818
  ),
12804
12819
  /* @__PURE__ */ jsxs86("div", { className: "fdc-tools", children: [
12805
- fileUploadHandler ? /* @__PURE__ */ jsx95(FilePickButton, { onFiles: staged.add, onReject: (r) => flash(r[0].message), accept: acceptFiles, maxFileSize, label: "Attach files", icon: "plus" }) : null,
12806
- voiceHandler ? /* @__PURE__ */ jsx95("button", { type: "button", className: "fd-attachbtn" + (listening ? " is-live" : ""), onClick: voice, "aria-pressed": listening, "aria-label": listening ? "Stop dictation" : "Dictate", children: /* @__PURE__ */ jsx95("i", { className: "ph ph-" + (listening ? "waveform" : "microphone"), "aria-hidden": "true" }) }) : null,
12820
+ fileUploadHandler ? /* @__PURE__ */ jsx96(FilePickButton, { onFiles: staged.add, onReject: (r) => flash(r[0].message), accept: acceptFiles, maxFileSize, label: "Attach files", icon: "plus" }) : null,
12821
+ voiceHandler ? /* @__PURE__ */ jsx96("button", { type: "button", className: "fd-attachbtn" + (listening ? " is-live" : ""), onClick: voice, "aria-pressed": listening, "aria-label": listening ? "Stop dictation" : "Dictate", children: /* @__PURE__ */ jsx96("i", { className: "ph ph-" + (listening ? "waveform" : "microphone"), "aria-hidden": "true" }) }) : null,
12807
12822
  toolbarExtras,
12808
- /* @__PURE__ */ jsx95("span", { className: "fdc-tools-gap" }),
12823
+ /* @__PURE__ */ jsx96("span", { className: "fdc-tools-gap" }),
12809
12824
  maxLength && text.length > maxLength * 0.6 ? /* @__PURE__ */ jsxs86("span", { className: "fdc-count fd-tabular" + (text.length > maxLength * 0.95 ? " is-hot" : ""), children: [
12810
12825
  text.length,
12811
12826
  "/",
12812
12827
  maxLength
12813
12828
  ] }) : null,
12814
12829
  busy ? /* @__PURE__ */ jsxs86("button", { type: "button", className: "fdc-stop", onClick: onStop, "aria-label": "Stop generating", children: [
12815
- /* @__PURE__ */ jsx95("i", { className: "ph ph-stop-circle", "aria-hidden": "true" }),
12816
- /* @__PURE__ */ jsx95("span", { children: "Stop" })
12830
+ /* @__PURE__ */ jsx96("i", { className: "ph ph-stop-circle", "aria-hidden": "true" }),
12831
+ /* @__PURE__ */ jsx96("span", { children: "Stop" })
12817
12832
  ] }) : /* @__PURE__ */ jsxs86("button", { type: "button", className: "fdc-send", onClick: submit, disabled: !canSend, "aria-label": "Send message", children: [
12818
- /* @__PURE__ */ jsx95("i", { className: "ph ph-paper-plane-right", "aria-hidden": "true" }),
12819
- /* @__PURE__ */ jsx95("span", { className: "fdc-send-label", children: "Send" })
12833
+ /* @__PURE__ */ jsx96("i", { className: "ph ph-paper-plane-right", "aria-hidden": "true" }),
12834
+ /* @__PURE__ */ jsx96("span", { className: "fdc-send-label", children: "Send" })
12820
12835
  ] })
12821
12836
  ] })
12822
12837
  ] })
12823
12838
  }
12824
12839
  ),
12825
12840
  notice ? /* @__PURE__ */ jsxs86("div", { className: "fdc-notice", role: "status", children: [
12826
- /* @__PURE__ */ jsx95("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
12841
+ /* @__PURE__ */ jsx96("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
12827
12842
  notice
12828
12843
  ] }) : null,
12829
- hint && !notice ? /* @__PURE__ */ jsx95("div", { className: "fdc-hint", children: hint }) : null,
12830
- /* @__PURE__ */ jsx95(
12844
+ hint && !notice ? /* @__PURE__ */ jsx96("div", { className: "fdc-hint", children: hint }) : null,
12845
+ /* @__PURE__ */ jsx96(
12831
12846
  Popover,
12832
12847
  {
12833
12848
  open: menuOpen,
@@ -12841,12 +12856,12 @@ function ChatComposer({
12841
12856
  returnFocus: false,
12842
12857
  closeOnOutside: true,
12843
12858
  label: trigger && trigger.type === "slash" ? "Commands" : "Mentions",
12844
- children: /* @__PURE__ */ jsx95(
12859
+ children: /* @__PURE__ */ jsx96(
12845
12860
  Menu,
12846
12861
  {
12847
12862
  items: menuItems,
12848
12863
  autoFocus: false,
12849
- header: /* @__PURE__ */ jsx95("div", { className: "fd-pop-group", children: trigger && trigger.type === "slash" ? "Commands" : "Attach context" }),
12864
+ header: /* @__PURE__ */ jsx96("div", { className: "fd-pop-group", children: trigger && trigger.type === "slash" ? "Commands" : "Attach context" }),
12850
12865
  onClose: () => setTrigger(null)
12851
12866
  }
12852
12867
  )
@@ -12856,12 +12871,12 @@ function ChatComposer({
12856
12871
  }
12857
12872
 
12858
12873
  // src/components/chat/ChatSessionBar.tsx
12859
- import * as React67 from "react";
12860
- import { jsx as jsx96, jsxs as jsxs87 } from "react/jsx-runtime";
12874
+ import * as React68 from "react";
12875
+ import { jsx as jsx97, jsxs as jsxs87 } from "react/jsx-runtime";
12861
12876
  var compact2 = meterFormats.compact;
12862
12877
  function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extras }) {
12863
- const [open2, setOpen] = React67.useState(false);
12864
- const anchor = React67.useRef(null);
12878
+ const [open2, setOpen] = React68.useState(false);
12879
+ const anchor = React68.useRef(null);
12865
12880
  const stats = sessionStats || null;
12866
12881
  const cu = contextUsage || null;
12867
12882
  const limits = usageLimits || null;
@@ -12876,7 +12891,7 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
12876
12891
  if (stats && stats.runningTasks) bits.push(stats.runningTasks + " running task" + (stats.runningTasks === 1 ? "" : "s"));
12877
12892
  if (cu) bits.push(pct + "% context");
12878
12893
  const expandable = !!(cu || limits);
12879
- return /* @__PURE__ */ jsxs87(React67.Fragment, { children: [
12894
+ return /* @__PURE__ */ jsxs87(React68.Fragment, { children: [
12880
12895
  /* @__PURE__ */ jsxs87("div", { className: "fdc-bar", children: [
12881
12896
  /* @__PURE__ */ jsxs87(
12882
12897
  "button",
@@ -12889,15 +12904,15 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
12889
12904
  "aria-expanded": expandable ? open2 : void 0,
12890
12905
  "aria-label": expandable ? "Usage details" : void 0,
12891
12906
  children: [
12892
- cu ? /* @__PURE__ */ jsx96("span", { className: "fdc-bar-mini", "aria-hidden": "true", children: /* @__PURE__ */ jsx96(SegmentedMeter, { total, segments: cu.segments, height: 4, showTotal: false }) }) : null,
12893
- /* @__PURE__ */ jsx96("span", { className: "fdc-bar-text", title: truncationTitle(bits.join(" \xB7 ")), children: bits.join(" \xB7 ") }),
12894
- expandable ? /* @__PURE__ */ jsx96("i", { className: "ph ph-caret-right fdc-bar-caret", "aria-hidden": "true" }) : null
12907
+ cu ? /* @__PURE__ */ jsx97("span", { className: "fdc-bar-mini", "aria-hidden": "true", children: /* @__PURE__ */ jsx97(SegmentedMeter, { total, segments: cu.segments, height: 4, showTotal: false }) }) : null,
12908
+ /* @__PURE__ */ jsx97("span", { className: "fdc-bar-text", title: truncationTitle(bits.join(" \xB7 ")), children: bits.join(" \xB7 ") }),
12909
+ expandable ? /* @__PURE__ */ jsx97("i", { className: "ph ph-caret-right fdc-bar-caret", "aria-hidden": "true" }) : null
12895
12910
  ]
12896
12911
  }
12897
12912
  ),
12898
12913
  extras
12899
12914
  ] }),
12900
- /* @__PURE__ */ jsx96(
12915
+ /* @__PURE__ */ jsx97(
12901
12916
  Popover,
12902
12917
  {
12903
12918
  open: open2,
@@ -12912,11 +12927,11 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
12912
12927
  setOpen(false);
12913
12928
  onClear();
12914
12929
  }, children: [
12915
- /* @__PURE__ */ jsx96("i", { className: "ph ph-trash", "aria-hidden": "true" }),
12930
+ /* @__PURE__ */ jsx97("i", { className: "ph ph-trash", "aria-hidden": "true" }),
12916
12931
  "Clear conversation"
12917
12932
  ] }) : void 0,
12918
12933
  children: /* @__PURE__ */ jsxs87("div", { className: "fdc-usage", children: [
12919
- cu ? /* @__PURE__ */ jsx96("section", { className: "fdc-usage-sec", children: /* @__PURE__ */ jsx96(
12934
+ cu ? /* @__PURE__ */ jsx97("section", { className: "fdc-usage-sec", children: /* @__PURE__ */ jsx97(
12920
12935
  SegmentedMeter,
12921
12936
  {
12922
12937
  total,
@@ -12929,8 +12944,8 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
12929
12944
  }
12930
12945
  ) }) : null,
12931
12946
  limits && limits.length ? /* @__PURE__ */ jsxs87("section", { className: "fdc-usage-sec", children: [
12932
- /* @__PURE__ */ jsx96("h4", { className: "fdc-usage-h", children: "Usage limits" }),
12933
- /* @__PURE__ */ jsx96("div", { className: "fdc-usage-rows", children: limits.map((l) => /* @__PURE__ */ jsx96(
12947
+ /* @__PURE__ */ jsx97("h4", { className: "fdc-usage-h", children: "Usage limits" }),
12948
+ /* @__PURE__ */ jsx97("div", { className: "fdc-usage-rows", children: limits.map((l) => /* @__PURE__ */ jsx97(
12934
12949
  QuotaRow,
12935
12950
  {
12936
12951
  label: l.label,
@@ -12942,23 +12957,23 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
12942
12957
  ] }) : null,
12943
12958
  stats ? /* @__PURE__ */ jsxs87("section", { className: "fdc-usage-sec fdc-usage-stats", children: [
12944
12959
  stats.elapsedMs ? /* @__PURE__ */ jsxs87("div", { children: [
12945
- /* @__PURE__ */ jsx96("span", { children: "Session" }),
12946
- /* @__PURE__ */ jsx96("b", { className: "fd-tabular", children: formatDuration(stats.elapsedMs) })
12960
+ /* @__PURE__ */ jsx97("span", { children: "Session" }),
12961
+ /* @__PURE__ */ jsx97("b", { className: "fd-tabular", children: formatDuration(stats.elapsedMs) })
12947
12962
  ] }) : null,
12948
12963
  stats.tokens ? /* @__PURE__ */ jsxs87("div", { children: [
12949
- /* @__PURE__ */ jsx96("span", { children: "Tokens" }),
12950
- /* @__PURE__ */ jsx96("b", { className: "fd-tabular", children: stats.tokens.toLocaleString() })
12964
+ /* @__PURE__ */ jsx97("span", { children: "Tokens" }),
12965
+ /* @__PURE__ */ jsx97("b", { className: "fd-tabular", children: stats.tokens.toLocaleString() })
12951
12966
  ] }) : null,
12952
12967
  stats.costUsd != null ? /* @__PURE__ */ jsxs87("div", { children: [
12953
- /* @__PURE__ */ jsx96("span", { children: "Cost" }),
12968
+ /* @__PURE__ */ jsx97("span", { children: "Cost" }),
12954
12969
  /* @__PURE__ */ jsxs87("b", { className: "fd-tabular", children: [
12955
12970
  "$",
12956
12971
  Number(stats.costUsd).toFixed(3)
12957
12972
  ] })
12958
12973
  ] }) : null,
12959
12974
  stats.turns ? /* @__PURE__ */ jsxs87("div", { children: [
12960
- /* @__PURE__ */ jsx96("span", { children: "Turns" }),
12961
- /* @__PURE__ */ jsx96("b", { className: "fd-tabular", children: stats.turns })
12975
+ /* @__PURE__ */ jsx97("span", { children: "Turns" }),
12976
+ /* @__PURE__ */ jsx97("b", { className: "fd-tabular", children: stats.turns })
12962
12977
  ] }) : null
12963
12978
  ] }) : null
12964
12979
  ] })
@@ -12997,7 +13012,7 @@ function ModelControls({
12997
13012
  disabled: m.disabled,
12998
13013
  checked: m.id === (current2 && current2.id),
12999
13014
  meta: m.meta,
13000
- shortcut: m.shortcut ? /* @__PURE__ */ jsx96(KeyHint, { keys: m.shortcut, size: "sm" }) : void 0,
13015
+ shortcut: m.shortcut ? /* @__PURE__ */ jsx97(KeyHint, { keys: m.shortcut, size: "sm" }) : void 0,
13001
13016
  onSelect: () => onModelChange && onModelChange(m.id)
13002
13017
  });
13003
13018
  const items = [{ kind: "section", label: "Models" }].concat(flat.map(item));
@@ -13011,14 +13026,14 @@ function ModelControls({
13011
13026
  items.push({
13012
13027
  kind: "custom",
13013
13028
  render: () => /* @__PURE__ */ jsxs87("label", { className: "fdc-switchrow", children: [
13014
- /* @__PURE__ */ jsx96("span", { children: fastModeLabel }),
13015
- /* @__PURE__ */ jsx96("input", { type: "checkbox", className: "fd-sr", checked: !!fastMode, onChange: (e) => onFastModeChange(e.target.checked) }),
13016
- /* @__PURE__ */ jsx96("span", { className: "fd-switch-track" + (fastMode ? " is-on" : ""), "aria-hidden": "true", children: /* @__PURE__ */ jsx96("span", { className: "fd-switch-thumb" }) })
13029
+ /* @__PURE__ */ jsx97("span", { children: fastModeLabel }),
13030
+ /* @__PURE__ */ jsx97("input", { type: "checkbox", className: "fd-sr", checked: !!fastMode, onChange: (e) => onFastModeChange(e.target.checked) }),
13031
+ /* @__PURE__ */ jsx97("span", { className: "fd-switch-track" + (fastMode ? " is-on" : ""), "aria-hidden": "true", children: /* @__PURE__ */ jsx97("span", { className: "fd-switch-thumb" }) })
13017
13032
  ] })
13018
13033
  });
13019
13034
  }
13020
- return /* @__PURE__ */ jsxs87(React67.Fragment, { children: [
13021
- /* @__PURE__ */ jsx96(
13035
+ return /* @__PURE__ */ jsxs87(React68.Fragment, { children: [
13036
+ /* @__PURE__ */ jsx97(
13022
13037
  MenuButton,
13023
13038
  {
13024
13039
  items,
@@ -13029,7 +13044,7 @@ function ModelControls({
13029
13044
  title: "Choose a model"
13030
13045
  }
13031
13046
  ),
13032
- effortLevels && effortLevels.length ? /* @__PURE__ */ jsx96(
13047
+ effortLevels && effortLevels.length ? /* @__PURE__ */ jsx97(
13033
13048
  MenuButton,
13034
13049
  {
13035
13050
  placement: "top-end",
@@ -13050,7 +13065,7 @@ function ModelControls({
13050
13065
  }
13051
13066
 
13052
13067
  // src/components/chat/AgentChatPanel.tsx
13053
- import { jsx as jsx97, jsxs as jsxs88 } from "react/jsx-runtime";
13068
+ import { jsx as jsx98, jsxs as jsxs88 } from "react/jsx-runtime";
13054
13069
  var SURFACES = { sidebar: "is-sidebar", inline: "is-inline", page: "is-page", modal: "is-modal", sheet: "is-sheet" };
13055
13070
  function AgentChatPanel({
13056
13071
  /* required */
@@ -13134,11 +13149,11 @@ function AgentChatPanel({
13134
13149
  onFeedback,
13135
13150
  onEditMessage
13136
13151
  }) {
13137
- const [panelWidth, setPanelWidth] = React68.useState(width);
13138
- const [applied, setApplied] = React68.useState({});
13139
- const [draft, setDraft] = React68.useState("");
13140
- const dragging = React68.useRef(null);
13141
- React68.useEffect(() => setPanelWidth(width), [width]);
13152
+ const [panelWidth, setPanelWidth] = React69.useState(width);
13153
+ const [applied, setApplied] = React69.useState({});
13154
+ const [draft, setDraft] = React69.useState("");
13155
+ const dragging = React69.useRef(null);
13156
+ React69.useEffect(() => setPanelWidth(width), [width]);
13142
13157
  const engine = useChatEngine({
13143
13158
  contextType,
13144
13159
  contextId,
@@ -13204,7 +13219,7 @@ function AgentChatPanel({
13204
13219
  onReconnect: engine.reload,
13205
13220
  deadTitle: "The assistant isn\u2019t reachable"
13206
13221
  };
13207
- const sessionBar = /* @__PURE__ */ jsx97(
13222
+ const sessionBar = /* @__PURE__ */ jsx98(
13208
13223
  ChatSessionBar,
13209
13224
  {
13210
13225
  sessionStats,
@@ -13213,7 +13228,7 @@ function AgentChatPanel({
13213
13228
  onClear: engine.visible.length ? engine.clear : void 0
13214
13229
  }
13215
13230
  );
13216
- const modelControls = /* @__PURE__ */ jsx97(
13231
+ const modelControls = /* @__PURE__ */ jsx98(
13217
13232
  ModelControls,
13218
13233
  {
13219
13234
  models,
@@ -13228,7 +13243,7 @@ function AgentChatPanel({
13228
13243
  narrow
13229
13244
  }
13230
13245
  );
13231
- const threadMenu = threads && threads.length ? /* @__PURE__ */ jsx97(
13246
+ const threadMenu = threads && threads.length ? /* @__PURE__ */ jsx98(
13232
13247
  MenuButton,
13233
13248
  {
13234
13249
  variant: "ghost",
@@ -13266,7 +13281,7 @@ function AgentChatPanel({
13266
13281
  },
13267
13282
  "aria-label": title,
13268
13283
  children: [
13269
- surface === "sidebar" && resizable ? /* @__PURE__ */ jsx97(
13284
+ surface === "sidebar" && resizable ? /* @__PURE__ */ jsx98(
13270
13285
  "div",
13271
13286
  {
13272
13287
  className: "fdc-grip",
@@ -13282,19 +13297,19 @@ function AgentChatPanel({
13282
13297
  }
13283
13298
  ) : null,
13284
13299
  showHeader ? /* @__PURE__ */ jsxs88("header", { className: "fdc-head", children: [
13285
- /* @__PURE__ */ jsx97("span", { className: "fdc-head-mark", "aria-hidden": "true", children: /* @__PURE__ */ jsx97("i", { className: "ph ph-" + assistantIcon }) }),
13300
+ /* @__PURE__ */ jsx98("span", { className: "fdc-head-mark", "aria-hidden": "true", children: /* @__PURE__ */ jsx98("i", { className: "ph ph-" + assistantIcon }) }),
13286
13301
  /* @__PURE__ */ jsxs88("span", { className: "fdc-head-titles", children: [
13287
- /* @__PURE__ */ jsx97("span", { className: "fdc-head-title", title: truncationTitle(title), children: title }),
13288
- subtitle ? /* @__PURE__ */ jsx97("span", { className: "fdc-head-sub", title: truncationTitle(subtitle), children: subtitle }) : null
13302
+ /* @__PURE__ */ jsx98("span", { className: "fdc-head-title", title: truncationTitle(title), children: title }),
13303
+ subtitle ? /* @__PURE__ */ jsx98("span", { className: "fdc-head-sub", title: truncationTitle(subtitle), children: subtitle }) : null
13289
13304
  ] }),
13290
13305
  /* @__PURE__ */ jsxs88("span", { className: "fdc-head-acts", children: [
13291
13306
  headerActions,
13292
13307
  threadMenu,
13293
- onNewThread ? /* @__PURE__ */ jsx97("button", { type: "button", className: "fdc-iconbtn", onClick: onNewThread, "aria-label": "New conversation", title: "New conversation", children: /* @__PURE__ */ jsx97("i", { className: "ph ph-plus", "aria-hidden": "true" }) }) : null,
13294
- onClose ? /* @__PURE__ */ jsx97("button", { type: "button", className: "fdc-iconbtn", onClick: onClose, "aria-label": "Close panel", title: "Close", children: /* @__PURE__ */ jsx97("i", { className: "ph ph-x", "aria-hidden": "true" }) }) : null
13308
+ onNewThread ? /* @__PURE__ */ jsx98("button", { type: "button", className: "fdc-iconbtn", onClick: onNewThread, "aria-label": "New conversation", title: "New conversation", children: /* @__PURE__ */ jsx98("i", { className: "ph ph-plus", "aria-hidden": "true" }) }) : null,
13309
+ onClose ? /* @__PURE__ */ jsx98("button", { type: "button", className: "fdc-iconbtn", onClick: onClose, "aria-label": "Close panel", title: "Close", children: /* @__PURE__ */ jsx98("i", { className: "ph ph-x", "aria-hidden": "true" }) }) : null
13295
13310
  ] })
13296
13311
  ] }) : null,
13297
- /* @__PURE__ */ jsx97(
13312
+ /* @__PURE__ */ jsx98(
13298
13313
  ChatTranscript,
13299
13314
  {
13300
13315
  messages: engine.visible,
@@ -13309,7 +13324,7 @@ function AgentChatPanel({
13309
13324
  renderEmpty
13310
13325
  }
13311
13326
  ),
13312
- /* @__PURE__ */ jsx97(
13327
+ /* @__PURE__ */ jsx98(
13313
13328
  ChatComposer,
13314
13329
  {
13315
13330
  onSubmit: (text, atts) => engine.send(text, atts),
@@ -13342,8 +13357,8 @@ function AgentChatPanel({
13342
13357
  }
13343
13358
 
13344
13359
  // src/components/files/FileViewer.tsx
13345
- import * as React69 from "react";
13346
- import { jsx as jsx98, jsxs as jsxs89 } from "react/jsx-runtime";
13360
+ import * as React70 from "react";
13361
+ import { jsx as jsx99, jsxs as jsxs89 } from "react/jsx-runtime";
13347
13362
  function previewKindOf(file) {
13348
13363
  const mime = (file.mime || "").toLowerCase();
13349
13364
  const ext = extensionOf(file.name || "");
@@ -13399,13 +13414,13 @@ function parseDelimited(text, delimiter) {
13399
13414
  return rows;
13400
13415
  }
13401
13416
  function usePreview(file, kind, resolveUrl) {
13402
- const [state, setState] = React69.useState({ status: "loading" });
13403
- const [attempt, setAttempt] = React69.useState(0);
13404
- const resolveRef = React69.useRef(resolveUrl);
13405
- React69.useEffect(() => {
13417
+ const [state, setState] = React70.useState({ status: "loading" });
13418
+ const [attempt, setAttempt] = React70.useState(0);
13419
+ const resolveRef = React70.useRef(resolveUrl);
13420
+ React70.useEffect(() => {
13406
13421
  resolveRef.current = resolveUrl;
13407
13422
  }, [resolveUrl]);
13408
- React69.useEffect(() => {
13423
+ React70.useEffect(() => {
13409
13424
  if (kind === "none") {
13410
13425
  setState({ status: "ready" });
13411
13426
  return;
@@ -13435,19 +13450,19 @@ function usePreview(file, kind, resolveUrl) {
13435
13450
  if (ac) ac.abort();
13436
13451
  };
13437
13452
  }, [file.id, kind, attempt]);
13438
- return { ...state, retry: React69.useCallback(() => setAttempt((a) => a + 1), []) };
13453
+ return { ...state, retry: React70.useCallback(() => setAttempt((a) => a + 1), []) };
13439
13454
  }
13440
13455
  function PreviewBody({ file, kind, state }) {
13441
- if (kind === "image") return /* @__PURE__ */ jsx98("img", { className: "fd-fv-image", src: state.url, alt: file.name || "Preview" });
13442
- if (kind === "pdf") return /* @__PURE__ */ jsx98("iframe", { className: "fd-fv-pdf", src: state.url, title: file.name || "PDF preview" });
13443
- if (kind === "markdown") return /* @__PURE__ */ jsx98(Markdown, { className: "fd-fv-markdown", source: state.text || "" });
13456
+ if (kind === "image") return /* @__PURE__ */ jsx99("img", { className: "fd-fv-image", src: state.url, alt: file.name || "Preview" });
13457
+ if (kind === "pdf") return /* @__PURE__ */ jsx99("iframe", { className: "fd-fv-pdf", src: state.url, title: file.name || "PDF preview" });
13458
+ if (kind === "markdown") return /* @__PURE__ */ jsx99(Markdown, { className: "fd-fv-markdown", source: state.text || "" });
13444
13459
  if (kind === "json") {
13445
13460
  let pretty = state.text || "";
13446
13461
  try {
13447
13462
  pretty = JSON.stringify(JSON.parse(pretty), null, 2);
13448
13463
  } catch {
13449
13464
  }
13450
- return /* @__PURE__ */ jsx98(CodeBlock, { code: pretty, language: "json" });
13465
+ return /* @__PURE__ */ jsx99(CodeBlock, { code: pretty, language: "json" });
13451
13466
  }
13452
13467
  if (kind === "csv") {
13453
13468
  const tsv = extensionOf(file.name || "") === "tsv" || (file.mime || "").toLowerCase().includes("tab-separated");
@@ -13457,8 +13472,8 @@ function PreviewBody({ file, kind, state }) {
13457
13472
  const shown = dataRows.slice(0, FILE_VIEWER_CSV_ROW_LIMIT);
13458
13473
  return /* @__PURE__ */ jsxs89("div", { className: "fd-fv-csv", children: [
13459
13474
  /* @__PURE__ */ jsxs89("table", { className: "fd-fv-csv-table", children: [
13460
- /* @__PURE__ */ jsx98("thead", { children: /* @__PURE__ */ jsx98("tr", { children: head.map((c, i) => /* @__PURE__ */ jsx98("th", { children: c }, i)) }) }),
13461
- /* @__PURE__ */ jsx98("tbody", { children: shown.map((r, ri) => /* @__PURE__ */ jsx98("tr", { children: head.map((_, ci) => /* @__PURE__ */ jsx98("td", { children: r[ci] ?? "" }, ci)) }, ri)) })
13475
+ /* @__PURE__ */ jsx99("thead", { children: /* @__PURE__ */ jsx99("tr", { children: head.map((c, i) => /* @__PURE__ */ jsx99("th", { children: c }, i)) }) }),
13476
+ /* @__PURE__ */ jsx99("tbody", { children: shown.map((r, ri) => /* @__PURE__ */ jsx99("tr", { children: head.map((_, ci) => /* @__PURE__ */ jsx99("td", { children: r[ci] ?? "" }, ci)) }, ri)) })
13462
13477
  ] }),
13463
13478
  dataRows.length > FILE_VIEWER_CSV_ROW_LIMIT ? /* @__PURE__ */ jsxs89("p", { className: "fd-fv-csv-note fd-body-sm fd-muted", children: [
13464
13479
  "Showing the first ",
@@ -13469,10 +13484,10 @@ function PreviewBody({ file, kind, state }) {
13469
13484
  ] }) : null
13470
13485
  ] });
13471
13486
  }
13472
- if (kind === "text") return /* @__PURE__ */ jsx98(CodeBlock, { code: state.text || "", language: extensionOf(file.name || "") || void 0 });
13487
+ if (kind === "text") return /* @__PURE__ */ jsx99(CodeBlock, { code: state.text || "", language: extensionOf(file.name || "") || void 0 });
13473
13488
  return /* @__PURE__ */ jsxs89("div", { className: "fd-fv-fallback", children: [
13474
- /* @__PURE__ */ jsx98("span", { className: "fd-fv-fallback-icon", "aria-hidden": "true", children: /* @__PURE__ */ jsx98("i", { className: "ph ph-" + iconForMime(file.mime, file.name) }) }),
13475
- /* @__PURE__ */ jsx98("span", { className: "fd-fv-fallback-title", children: "No preview available" }),
13489
+ /* @__PURE__ */ jsx99("span", { className: "fd-fv-fallback-icon", "aria-hidden": "true", children: /* @__PURE__ */ jsx99("i", { className: "ph ph-" + iconForMime(file.mime, file.name) }) }),
13490
+ /* @__PURE__ */ jsx99("span", { className: "fd-fv-fallback-title", children: "No preview available" }),
13476
13491
  /* @__PURE__ */ jsxs89("span", { className: "fd-fv-fallback-meta", children: [
13477
13492
  file.mime || "Unknown type",
13478
13493
  file.size ? " \xB7 " + formatBytes(file.size) : ""
@@ -13480,13 +13495,13 @@ function PreviewBody({ file, kind, state }) {
13480
13495
  ] });
13481
13496
  }
13482
13497
  function FileViewer({ file, resolveUrl, sidePanel, sidePanelLabel = "Details", onClose, actions, className = "" }) {
13483
- const kind = React69.useMemo(() => previewKindOf(file), [file]);
13498
+ const kind = React70.useMemo(() => previewKindOf(file), [file]);
13484
13499
  const preview = usePreview(file, kind, resolveUrl);
13485
- const [tab, setTab] = React69.useState("preview");
13486
- const [downloading, setDownloading] = React69.useState(false);
13487
- const [downloadError, setDownloadError] = React69.useState(null);
13500
+ const [tab, setTab] = React70.useState("preview");
13501
+ const [downloading, setDownloading] = React70.useState(false);
13502
+ const [downloadError, setDownloadError] = React70.useState(null);
13488
13503
  const hasSide = sidePanel != null;
13489
- React69.useEffect(() => {
13504
+ React70.useEffect(() => {
13490
13505
  setTab("preview");
13491
13506
  }, [file.id]);
13492
13507
  const download = () => {
@@ -13509,9 +13524,9 @@ function FileViewer({ file, resolveUrl, sidePanel, sidePanelLabel = "Details", o
13509
13524
  "aria-label": file.name || "File",
13510
13525
  children: [
13511
13526
  /* @__PURE__ */ jsxs89("header", { className: "fd-fv-head", children: [
13512
- /* @__PURE__ */ jsx98("span", { className: "fd-fv-head-icon", "aria-hidden": "true", children: /* @__PURE__ */ jsx98("i", { className: "ph ph-" + iconForMime(file.mime, file.name) }) }),
13527
+ /* @__PURE__ */ jsx99("span", { className: "fd-fv-head-icon", "aria-hidden": "true", children: /* @__PURE__ */ jsx99("i", { className: "ph ph-" + iconForMime(file.mime, file.name) }) }),
13513
13528
  /* @__PURE__ */ jsxs89("span", { className: "fd-fv-head-titles", children: [
13514
- /* @__PURE__ */ jsx98("span", { className: "fd-fv-head-title", title: file.name, children: file.name }),
13529
+ /* @__PURE__ */ jsx99("span", { className: "fd-fv-head-title", title: file.name, children: file.name }),
13515
13530
  /* @__PURE__ */ jsxs89("span", { className: "fd-fv-head-meta", children: [
13516
13531
  file.mime || "Unknown type",
13517
13532
  file.size ? " \xB7 " + formatBytes(file.size) : ""
@@ -13519,12 +13534,12 @@ function FileViewer({ file, resolveUrl, sidePanel, sidePanelLabel = "Details", o
13519
13534
  ] }),
13520
13535
  /* @__PURE__ */ jsxs89("span", { className: "fd-fv-head-actions", children: [
13521
13536
  actions,
13522
- /* @__PURE__ */ jsx98(Button, { variant: "secondary", size: "sm", icon: "download-simple", loading: downloading, onClick: download, children: "Download" }),
13523
- onClose ? /* @__PURE__ */ jsx98(IconButton, { icon: "x", label: "Close", onClick: onClose }) : null
13537
+ /* @__PURE__ */ jsx99(Button, { variant: "secondary", size: "sm", icon: "download-simple", loading: downloading, onClick: download, children: "Download" }),
13538
+ onClose ? /* @__PURE__ */ jsx99(IconButton, { icon: "x", label: "Close", onClick: onClose }) : null
13524
13539
  ] })
13525
13540
  ] }),
13526
- downloadError ? /* @__PURE__ */ jsx98("div", { className: "fd-fv-download-error", role: "alert", children: downloadError }) : null,
13527
- hasSide ? /* @__PURE__ */ jsx98(
13541
+ downloadError ? /* @__PURE__ */ jsx99("div", { className: "fd-fv-download-error", role: "alert", children: downloadError }) : null,
13542
+ hasSide ? /* @__PURE__ */ jsx99(
13528
13543
  Tabs,
13529
13544
  {
13530
13545
  className: "fd-fv-tabs",
@@ -13534,18 +13549,18 @@ function FileViewer({ file, resolveUrl, sidePanel, sidePanelLabel = "Details", o
13534
13549
  }
13535
13550
  ) : null,
13536
13551
  /* @__PURE__ */ jsxs89("div", { className: "fd-fv-body", children: [
13537
- /* @__PURE__ */ jsx98("div", { className: "fd-fv-preview", role: "region", "aria-label": "Preview of " + (file.name || "file"), children: /* @__PURE__ */ jsx98(
13552
+ /* @__PURE__ */ jsx99("div", { className: "fd-fv-preview", role: "region", "aria-label": "Preview of " + (file.name || "file"), children: /* @__PURE__ */ jsx99(
13538
13553
  LoadingRegion,
13539
13554
  {
13540
13555
  state: preview.status === "loading" ? "loading" : preview.status === "error" ? "error" : "ready",
13541
13556
  error: preview.error,
13542
13557
  label: "Loading preview of " + (file.name || "file"),
13543
13558
  onRetry: preview.status === "error" ? preview.retry : void 0,
13544
- skeleton: /* @__PURE__ */ jsx98(Skeleton, { shape: "card", h: 220 }),
13545
- children: /* @__PURE__ */ jsx98(PreviewBody, { file, kind, state: preview })
13559
+ skeleton: /* @__PURE__ */ jsx99(Skeleton, { shape: "card", h: 220 }),
13560
+ children: /* @__PURE__ */ jsx99(PreviewBody, { file, kind, state: preview })
13546
13561
  }
13547
13562
  ) }),
13548
- hasSide ? /* @__PURE__ */ jsx98("div", { className: "fd-fv-side", role: "region", "aria-label": sidePanelLabel, children: sidePanel }) : null
13563
+ hasSide ? /* @__PURE__ */ jsx99("div", { className: "fd-fv-side", role: "region", "aria-label": sidePanelLabel, children: sidePanel }) : null
13549
13564
  ] })
13550
13565
  ]
13551
13566
  }
@@ -13553,8 +13568,8 @@ function FileViewer({ file, resolveUrl, sidePanel, sidePanelLabel = "Details", o
13553
13568
  }
13554
13569
 
13555
13570
  // src/components/files/FileBrowser.tsx
13556
- import * as React70 from "react";
13557
- import { Fragment as Fragment29, jsx as jsx99, jsxs as jsxs90 } from "react/jsx-runtime";
13571
+ import * as React71 from "react";
13572
+ import { Fragment as Fragment29, jsx as jsx100, jsxs as jsxs90 } from "react/jsx-runtime";
13558
13573
  function childrenOf(folders, parentId) {
13559
13574
  return folders.filter((f) => f.parentId === parentId).sort((a, b) => a.name.localeCompare(b.name));
13560
13575
  }
@@ -13627,7 +13642,7 @@ function FolderPickerMenu({
13627
13642
  const panel = useInlinePanel();
13628
13643
  const { open: open2, setOpen, ref } = panel;
13629
13644
  return /* @__PURE__ */ jsxs90("span", { className: "fd-fb-menu-anchor", ref, children: [
13630
- /* @__PURE__ */ jsx99(
13645
+ /* @__PURE__ */ jsx100(
13631
13646
  IconButton,
13632
13647
  {
13633
13648
  icon: "arrows-out-cardinal",
@@ -13639,8 +13654,8 @@ function FolderPickerMenu({
13639
13654
  onClick: () => setOpen((v) => !v)
13640
13655
  }
13641
13656
  ),
13642
- /* @__PURE__ */ jsx99(InlinePanelSurface, { panel, align: "right", offset: 4, width: 220, maxHeight: 280, role: "menu", label, children: /* @__PURE__ */ jsxs90("div", { className: "fd-fb-menu", children: [
13643
- /* @__PURE__ */ jsx99("span", { className: "fd-overline fd-muted fd-fb-menu-title", children: "Move to\u2026" }),
13657
+ /* @__PURE__ */ jsx100(InlinePanelSurface, { panel, align: "right", offset: 4, width: 220, maxHeight: 280, role: "menu", label, children: /* @__PURE__ */ jsxs90("div", { className: "fd-fb-menu", children: [
13658
+ /* @__PURE__ */ jsx100("span", { className: "fd-overline fd-muted fd-fb-menu-title", children: "Move to\u2026" }),
13644
13659
  destinations.map((d) => /* @__PURE__ */ jsxs90(
13645
13660
  "button",
13646
13661
  {
@@ -13653,7 +13668,7 @@ function FolderPickerMenu({
13653
13668
  setOpen(false);
13654
13669
  },
13655
13670
  children: [
13656
- /* @__PURE__ */ jsx99("i", { className: "ph ph-" + (d.id == null ? "house-simple" : "folder-simple"), "aria-hidden": "true" }),
13671
+ /* @__PURE__ */ jsx100("i", { className: "ph ph-" + (d.id == null ? "house-simple" : "folder-simple"), "aria-hidden": "true" }),
13657
13672
  d.name
13658
13673
  ]
13659
13674
  },
@@ -13663,8 +13678,8 @@ function FolderPickerMenu({
13663
13678
  ] });
13664
13679
  }
13665
13680
  function RowShell({ icon, name, meta, onOpen, draggableId, isDropTarget, onDropPayload, actions, className = "" }) {
13666
- const [over, setOver] = React70.useState(false);
13667
- const dragCounter = React70.useRef(0);
13681
+ const [over, setOver] = React71.useState(false);
13682
+ const dragCounter = React71.useRef(0);
13668
13683
  const dropHandlers = isDropTarget ? {
13669
13684
  onDragEnter: (e) => {
13670
13685
  if (!hasInternalPayload(e)) return;
@@ -13699,26 +13714,26 @@ function RowShell({ icon, name, meta, onOpen, draggableId, isDropTarget, onDropP
13699
13714
  draggable: !!draggableId,
13700
13715
  onDragStart: draggableId ? (e) => writeDragPayload(e, draggableId) : void 0,
13701
13716
  children: [
13702
- /* @__PURE__ */ jsx99("span", { className: "fd-fb-row-icon", "aria-hidden": "true", children: /* @__PURE__ */ jsx99("i", { className: "ph ph-" + icon }) }),
13717
+ /* @__PURE__ */ jsx100("span", { className: "fd-fb-row-icon", "aria-hidden": "true", children: /* @__PURE__ */ jsx100("i", { className: "ph ph-" + icon }) }),
13703
13718
  /* @__PURE__ */ jsxs90("span", { className: "fd-fb-row-text", children: [
13704
- /* @__PURE__ */ jsx99("span", { className: "fd-fb-row-name", title: name, children: name }),
13705
- meta ? /* @__PURE__ */ jsx99("span", { className: "fd-fb-row-meta", children: meta }) : null
13719
+ /* @__PURE__ */ jsx100("span", { className: "fd-fb-row-name", title: name, children: name }),
13720
+ meta ? /* @__PURE__ */ jsx100("span", { className: "fd-fb-row-meta", children: meta }) : null
13706
13721
  ] })
13707
13722
  ]
13708
13723
  }
13709
13724
  ),
13710
- actions ? /* @__PURE__ */ jsx99("span", { className: "fd-fb-row-actions", children: actions }) : null
13725
+ actions ? /* @__PURE__ */ jsx100("span", { className: "fd-fb-row-actions", children: actions }) : null
13711
13726
  ] });
13712
13727
  }
13713
13728
  function TreeNode({ folder, depth, folders, currentFolderId, onNavigate, onMoveInto, canMove }) {
13714
13729
  const kids = childrenOf(folders, folder.id);
13715
- const [expanded, setExpanded] = React70.useState(() => currentFolderId != null && isSelfOrDescendant(folders, folder.id, currentFolderId));
13716
- React70.useEffect(() => {
13730
+ const [expanded, setExpanded] = React71.useState(() => currentFolderId != null && isSelfOrDescendant(folders, folder.id, currentFolderId));
13731
+ React71.useEffect(() => {
13717
13732
  if (currentFolderId != null && isSelfOrDescendant(folders, folder.id, currentFolderId)) setExpanded(true);
13718
13733
  }, [currentFolderId, folder.id, folders]);
13719
13734
  const isCurrent = folder.id === currentFolderId;
13720
13735
  return /* @__PURE__ */ jsxs90("div", { className: "fd-fb-tree-node", children: [
13721
- /* @__PURE__ */ jsx99(
13736
+ /* @__PURE__ */ jsx100(
13722
13737
  RowShell,
13723
13738
  {
13724
13739
  icon: folder.id === currentFolderId ? "folder-open" : "folder-simple",
@@ -13728,7 +13743,7 @@ function TreeNode({ folder, depth, folders, currentFolderId, onNavigate, onMoveI
13728
13743
  isDropTarget: canMove,
13729
13744
  onDropPayload: (payload) => onMoveInto(payload, folder.id),
13730
13745
  className: ["fd-fb-tree-row", isCurrent ? "is-current" : ""].filter(Boolean).join(" "),
13731
- actions: kids.length ? /* @__PURE__ */ jsx99(
13746
+ actions: kids.length ? /* @__PURE__ */ jsx100(
13732
13747
  IconButton,
13733
13748
  {
13734
13749
  icon: expanded ? "caret-down" : "caret-right",
@@ -13740,7 +13755,7 @@ function TreeNode({ folder, depth, folders, currentFolderId, onNavigate, onMoveI
13740
13755
  ) : void 0
13741
13756
  }
13742
13757
  ),
13743
- expanded && kids.length ? /* @__PURE__ */ jsx99("div", { className: "fd-fb-tree-children", style: { paddingLeft: 14 }, children: kids.map((k) => /* @__PURE__ */ jsx99(
13758
+ expanded && kids.length ? /* @__PURE__ */ jsx100("div", { className: "fd-fb-tree-children", style: { paddingLeft: 14 }, children: kids.map((k) => /* @__PURE__ */ jsx100(
13744
13759
  TreeNode,
13745
13760
  {
13746
13761
  folder: k,
@@ -13779,15 +13794,15 @@ function FileBrowser({
13779
13794
  const canUpload = perm.canUpload !== false && !!onUpload;
13780
13795
  const canRemoveFile = perm.canRemoveFile !== false && !!onRemoveFile;
13781
13796
  const canDeleteFolder = perm.canDeleteFolder !== false && !!onDeleteFolder;
13782
- const [createOpen, setCreateOpen] = React70.useState(false);
13783
- const [createName, setCreateName] = React70.useState("");
13784
- const [renameTarget, setRenameTarget] = React70.useState(null);
13785
- const [renameValue, setRenameValue] = React70.useState("");
13786
- const [deleteTarget, setDeleteTarget] = React70.useState(null);
13787
- const uploadInputRef = React70.useRef(null);
13788
- const crumbFolders = React70.useMemo(() => ancestorsOf(folders, currentFolderId), [folders, currentFolderId]);
13789
- const subfolders = React70.useMemo(() => childrenOf(folders, currentFolderId), [folders, currentFolderId]);
13790
- const currentFiles = React70.useMemo(
13797
+ const [createOpen, setCreateOpen] = React71.useState(false);
13798
+ const [createName, setCreateName] = React71.useState("");
13799
+ const [renameTarget, setRenameTarget] = React71.useState(null);
13800
+ const [renameValue, setRenameValue] = React71.useState("");
13801
+ const [deleteTarget, setDeleteTarget] = React71.useState(null);
13802
+ const uploadInputRef = React71.useRef(null);
13803
+ const crumbFolders = React71.useMemo(() => ancestorsOf(folders, currentFolderId), [folders, currentFolderId]);
13804
+ const subfolders = React71.useMemo(() => childrenOf(folders, currentFolderId), [folders, currentFolderId]);
13805
+ const currentFiles = React71.useMemo(
13791
13806
  () => files.filter((f) => f.folderId === currentFolderId).sort((a, b) => a.name.localeCompare(b.name)),
13792
13807
  [files, currentFolderId]
13793
13808
  );
@@ -13829,7 +13844,7 @@ function FileBrowser({
13829
13844
  const content = /* @__PURE__ */ jsxs90("div", { className: ["fd-fb", className].filter(Boolean).join(" "), children: [
13830
13845
  /* @__PURE__ */ jsxs90("div", { className: "fd-fb-head", children: [
13831
13846
  /* @__PURE__ */ jsxs90("nav", { className: "fd-fb-crumbs", "aria-label": "Folder path", children: [
13832
- /* @__PURE__ */ jsx99(
13847
+ /* @__PURE__ */ jsx100(
13833
13848
  BreadcrumbCrumb,
13834
13849
  {
13835
13850
  label: "Home",
@@ -13839,7 +13854,7 @@ function FileBrowser({
13839
13854
  onDropPayload: (p) => moveIntoFolder(p, null)
13840
13855
  }
13841
13856
  ),
13842
- crumbFolders.map((f, i) => /* @__PURE__ */ jsx99(
13857
+ crumbFolders.map((f, i) => /* @__PURE__ */ jsx100(
13843
13858
  BreadcrumbCrumb,
13844
13859
  {
13845
13860
  label: f.name,
@@ -13852,10 +13867,10 @@ function FileBrowser({
13852
13867
  ))
13853
13868
  ] }),
13854
13869
  /* @__PURE__ */ jsxs90("span", { className: "fd-fb-actions", children: [
13855
- canCreateFolder ? /* @__PURE__ */ jsx99(Button, { variant: "secondary", size: "sm", icon: "folder-simple-plus", onClick: openCreate, children: "New folder" }) : null,
13870
+ canCreateFolder ? /* @__PURE__ */ jsx100(Button, { variant: "secondary", size: "sm", icon: "folder-simple-plus", onClick: openCreate, children: "New folder" }) : null,
13856
13871
  canUpload ? /* @__PURE__ */ jsxs90(Fragment29, { children: [
13857
- /* @__PURE__ */ jsx99(Button, { variant: "secondary", size: "sm", icon: "upload-simple", onClick: () => uploadInputRef.current && uploadInputRef.current.click(), children: "Upload" }),
13858
- /* @__PURE__ */ jsx99(
13872
+ /* @__PURE__ */ jsx100(Button, { variant: "secondary", size: "sm", icon: "upload-simple", onClick: () => uploadInputRef.current && uploadInputRef.current.click(), children: "Upload" }),
13873
+ /* @__PURE__ */ jsx100(
13859
13874
  "input",
13860
13875
  {
13861
13876
  ref: uploadInputRef,
@@ -13875,7 +13890,7 @@ function FileBrowser({
13875
13890
  ] }),
13876
13891
  /* @__PURE__ */ jsxs90("div", { className: "fd-fb-body", children: [
13877
13892
  /* @__PURE__ */ jsxs90("div", { className: "fd-fb-tree", role: "region", "aria-label": "Folder tree", children: [
13878
- /* @__PURE__ */ jsx99(
13893
+ /* @__PURE__ */ jsx100(
13879
13894
  RowShell,
13880
13895
  {
13881
13896
  icon: "house-simple",
@@ -13886,7 +13901,7 @@ function FileBrowser({
13886
13901
  className: ["fd-fb-tree-row", currentFolderId == null ? "is-current" : ""].filter(Boolean).join(" ")
13887
13902
  }
13888
13903
  ),
13889
- childrenOf(folders, null).map((f) => /* @__PURE__ */ jsx99(
13904
+ childrenOf(folders, null).map((f) => /* @__PURE__ */ jsx100(
13890
13905
  TreeNode,
13891
13906
  {
13892
13907
  folder: f,
@@ -13900,18 +13915,18 @@ function FileBrowser({
13900
13915
  f.id
13901
13916
  ))
13902
13917
  ] }),
13903
- /* @__PURE__ */ jsx99("div", { className: "fd-fb-main", role: "region", "aria-label": "Folder contents", children: /* @__PURE__ */ jsx99(
13918
+ /* @__PURE__ */ jsx100("div", { className: "fd-fb-main", role: "region", "aria-label": "Folder contents", children: /* @__PURE__ */ jsx100(
13904
13919
  LoadingRegion,
13905
13920
  {
13906
13921
  state: loading ? "loading" : "ready",
13907
13922
  label: "Loading folder contents",
13908
13923
  skeleton: /* @__PURE__ */ jsxs90("div", { className: "fd-stack", style: { gap: 8, padding: 12 }, children: [
13909
- /* @__PURE__ */ jsx99(Skeleton, { h: 44, radius: "10px" }),
13910
- /* @__PURE__ */ jsx99(Skeleton, { h: 44, radius: "10px" }),
13911
- /* @__PURE__ */ jsx99(Skeleton, { h: 44, radius: "10px" })
13924
+ /* @__PURE__ */ jsx100(Skeleton, { h: 44, radius: "10px" }),
13925
+ /* @__PURE__ */ jsx100(Skeleton, { h: 44, radius: "10px" }),
13926
+ /* @__PURE__ */ jsx100(Skeleton, { h: 44, radius: "10px" })
13912
13927
  ] }),
13913
- children: isEmpty ? /* @__PURE__ */ jsx99(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__ */ jsxs90("div", { className: "fd-fb-list", children: [
13914
- subfolders.map((f) => /* @__PURE__ */ jsx99(
13928
+ children: isEmpty ? /* @__PURE__ */ jsx100(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__ */ jsxs90("div", { className: "fd-fb-list", children: [
13929
+ subfolders.map((f) => /* @__PURE__ */ jsx100(
13915
13930
  RowShell,
13916
13931
  {
13917
13932
  icon: "folder-simple",
@@ -13921,8 +13936,8 @@ function FileBrowser({
13921
13936
  isDropTarget: canMove,
13922
13937
  onDropPayload: (p) => moveIntoFolder(p, f.id),
13923
13938
  actions: /* @__PURE__ */ jsxs90(Fragment29, { children: [
13924
- canRenameFolder ? /* @__PURE__ */ jsx99(IconButton, { icon: "pencil-simple", label: "Rename " + f.name, size: "sm", variant: "ghost", onClick: () => openRename(f) }) : null,
13925
- canMove ? /* @__PURE__ */ jsx99(
13939
+ canRenameFolder ? /* @__PURE__ */ jsx100(IconButton, { icon: "pencil-simple", label: "Rename " + f.name, size: "sm", variant: "ghost", onClick: () => openRename(f) }) : null,
13940
+ canMove ? /* @__PURE__ */ jsx100(
13926
13941
  FolderPickerMenu,
13927
13942
  {
13928
13943
  label: "Move " + f.name,
@@ -13930,12 +13945,12 @@ function FileBrowser({
13930
13945
  onPick: (target) => moveIntoFolder({ kind: "folder", id: f.id }, target)
13931
13946
  }
13932
13947
  ) : null,
13933
- canDeleteFolder ? /* @__PURE__ */ jsx99(IconButton, { icon: "trash-simple", label: "Delete " + f.name, size: "sm", variant: "ghost", onClick: () => openDelete(f) }) : null
13948
+ canDeleteFolder ? /* @__PURE__ */ jsx100(IconButton, { icon: "trash-simple", label: "Delete " + f.name, size: "sm", variant: "ghost", onClick: () => openDelete(f) }) : null
13934
13949
  ] })
13935
13950
  },
13936
13951
  f.id
13937
13952
  )),
13938
- currentFiles.map((file) => /* @__PURE__ */ jsx99(
13953
+ currentFiles.map((file) => /* @__PURE__ */ jsx100(
13939
13954
  RowShell,
13940
13955
  {
13941
13956
  icon: iconForMime(file.mime, file.name),
@@ -13944,7 +13959,7 @@ function FileBrowser({
13944
13959
  onOpen: onOpenFile ? () => onOpenFile(file) : void 0,
13945
13960
  draggableId: canMove ? { kind: "file", id: file.id } : void 0,
13946
13961
  actions: /* @__PURE__ */ jsxs90(Fragment29, { children: [
13947
- canMove ? /* @__PURE__ */ jsx99(
13962
+ canMove ? /* @__PURE__ */ jsx100(
13948
13963
  FolderPickerMenu,
13949
13964
  {
13950
13965
  label: "Move " + file.name,
@@ -13952,7 +13967,7 @@ function FileBrowser({
13952
13967
  onPick: (target) => onMoveFile && onMoveFile(file.id, target)
13953
13968
  }
13954
13969
  ) : null,
13955
- canRemoveFile ? /* @__PURE__ */ jsx99(IconButton, { icon: "trash-simple", label: "Remove " + file.name, size: "sm", variant: "ghost", onClick: () => onRemoveFile && onRemoveFile(file) }) : null
13970
+ canRemoveFile ? /* @__PURE__ */ jsx100(IconButton, { icon: "trash-simple", label: "Remove " + file.name, size: "sm", variant: "ghost", onClick: () => onRemoveFile && onRemoveFile(file) }) : null
13956
13971
  ] })
13957
13972
  },
13958
13973
  file.id
@@ -13961,10 +13976,10 @@ function FileBrowser({
13961
13976
  }
13962
13977
  ) })
13963
13978
  ] }),
13964
- /* @__PURE__ */ jsx99(Modal, { open: createOpen, title: "New folder", onClose: () => setCreateOpen(false), footer: /* @__PURE__ */ jsxs90(Fragment29, { children: [
13965
- /* @__PURE__ */ jsx99(Button, { variant: "secondary", onClick: () => setCreateOpen(false), children: "Cancel" }),
13966
- /* @__PURE__ */ jsx99(Button, { onClick: submitCreate, disabled: !createName.trim(), children: "Create" })
13967
- ] }), children: /* @__PURE__ */ jsx99(
13979
+ /* @__PURE__ */ jsx100(Modal, { open: createOpen, title: "New folder", onClose: () => setCreateOpen(false), footer: /* @__PURE__ */ jsxs90(Fragment29, { children: [
13980
+ /* @__PURE__ */ jsx100(Button, { variant: "secondary", onClick: () => setCreateOpen(false), children: "Cancel" }),
13981
+ /* @__PURE__ */ jsx100(Button, { onClick: submitCreate, disabled: !createName.trim(), children: "Create" })
13982
+ ] }), children: /* @__PURE__ */ jsx100(
13968
13983
  "input",
13969
13984
  {
13970
13985
  className: "fd-fb-input",
@@ -13978,10 +13993,10 @@ function FileBrowser({
13978
13993
  autoFocus: true
13979
13994
  }
13980
13995
  ) }),
13981
- /* @__PURE__ */ jsx99(Modal, { open: renameTarget != null, title: "Rename folder", onClose: () => setRenameTarget(null), footer: /* @__PURE__ */ jsxs90(Fragment29, { children: [
13982
- /* @__PURE__ */ jsx99(Button, { variant: "secondary", onClick: () => setRenameTarget(null), children: "Cancel" }),
13983
- /* @__PURE__ */ jsx99(Button, { onClick: submitRename, disabled: !renameValue.trim(), children: "Save" })
13984
- ] }), children: /* @__PURE__ */ jsx99(
13996
+ /* @__PURE__ */ jsx100(Modal, { open: renameTarget != null, title: "Rename folder", onClose: () => setRenameTarget(null), footer: /* @__PURE__ */ jsxs90(Fragment29, { children: [
13997
+ /* @__PURE__ */ jsx100(Button, { variant: "secondary", onClick: () => setRenameTarget(null), children: "Cancel" }),
13998
+ /* @__PURE__ */ jsx100(Button, { onClick: submitRename, disabled: !renameValue.trim(), children: "Save" })
13999
+ ] }), children: /* @__PURE__ */ jsx100(
13985
14000
  "input",
13986
14001
  {
13987
14002
  className: "fd-fb-input",
@@ -13995,7 +14010,7 @@ function FileBrowser({
13995
14010
  autoFocus: true
13996
14011
  }
13997
14012
  ) }),
13998
- /* @__PURE__ */ jsx99(
14013
+ /* @__PURE__ */ jsx100(
13999
14014
  Modal,
14000
14015
  {
14001
14016
  open: deleteTarget != null,
@@ -14003,14 +14018,14 @@ function FileBrowser({
14003
14018
  description: "This can't be undone. The folder must be empty.",
14004
14019
  onClose: () => setDeleteTarget(null),
14005
14020
  footer: /* @__PURE__ */ jsxs90(Fragment29, { children: [
14006
- /* @__PURE__ */ jsx99(Button, { variant: "secondary", onClick: () => setDeleteTarget(null), children: "Cancel" }),
14007
- /* @__PURE__ */ jsx99(Button, { variant: "danger", onClick: confirmDelete, children: "Delete" })
14021
+ /* @__PURE__ */ jsx100(Button, { variant: "secondary", onClick: () => setDeleteTarget(null), children: "Cancel" }),
14022
+ /* @__PURE__ */ jsx100(Button, { variant: "danger", onClick: confirmDelete, children: "Delete" })
14008
14023
  ] })
14009
14024
  }
14010
14025
  )
14011
14026
  ] });
14012
14027
  if (!canUpload) return content;
14013
- return /* @__PURE__ */ jsx99(Dropzone, { className: "fd-fb-dropzone", onFiles: (picked) => onUpload && onUpload(picked, currentFolderId), label: "Drop files to upload", children: content });
14028
+ return /* @__PURE__ */ jsx100(Dropzone, { className: "fd-fb-dropzone", onFiles: (picked) => onUpload && onUpload(picked, currentFolderId), label: "Drop files to upload", children: content });
14014
14029
  }
14015
14030
  function BreadcrumbCrumb({
14016
14031
  label,
@@ -14019,8 +14034,8 @@ function BreadcrumbCrumb({
14019
14034
  isDropTarget,
14020
14035
  onDropPayload
14021
14036
  }) {
14022
- const [over, setOver] = React70.useState(false);
14023
- const dragCounter = React70.useRef(0);
14037
+ const [over, setOver] = React71.useState(false);
14038
+ const dragCounter = React71.useRef(0);
14024
14039
  const dropHandlers = isDropTarget ? {
14025
14040
  onDragEnter: (e) => {
14026
14041
  if (!hasInternalPayload(e)) return;
@@ -14045,11 +14060,11 @@ function BreadcrumbCrumb({
14045
14060
  if (payload && onDropPayload) onDropPayload(payload);
14046
14061
  }
14047
14062
  } : {};
14048
- return /* @__PURE__ */ jsx99("span", { className: ["fd-fb-crumb", over ? "is-drop-target" : ""].filter(Boolean).join(" "), ...dropHandlers, children: isCurrent ? /* @__PURE__ */ jsx99("span", { className: "fd-fb-crumb-current", "aria-current": "page", children: label }) : /* @__PURE__ */ jsx99("button", { type: "button", className: "fd-fb-crumb-link", onClick, children: label }) });
14063
+ return /* @__PURE__ */ jsx100("span", { className: ["fd-fb-crumb", over ? "is-drop-target" : ""].filter(Boolean).join(" "), ...dropHandlers, children: isCurrent ? /* @__PURE__ */ jsx100("span", { className: "fd-fb-crumb-current", "aria-current": "page", children: label }) : /* @__PURE__ */ jsx100("button", { type: "button", className: "fd-fb-crumb-link", onClick, children: label }) });
14049
14064
  }
14050
14065
 
14051
14066
  // src/kits/query.ts
14052
- import * as React71 from "react";
14067
+ import * as React72 from "react";
14053
14068
  var isMultiSelectShaped = (v) => !!v && typeof v === "object" && Array.isArray(v.values);
14054
14069
  var isRangeShaped = (v) => !!v && typeof v === "object" && ("min" in v || "max" in v);
14055
14070
  var isDateShaped = (v) => !!v && typeof v === "object" && "kind" in v;
@@ -14104,22 +14119,22 @@ function compare(a, b, dir) {
14104
14119
  var API = null;
14105
14120
  var PREFS = null;
14106
14121
  function useServerTable({ endpoint, params, defaults, deps, prefsKey }) {
14107
- const [query, setQuery] = React71.useState(() => {
14122
+ const [query, setQuery] = React72.useState(() => {
14108
14123
  const store = PREFS || window.PlannerPrefs;
14109
14124
  const saved = prefsKey && store ? store.getTable(prefsKey) : {};
14110
14125
  return { ...DEFAULTS, ...defaults || {}, ...saved.pageSize ? { pageSize: saved.pageSize } : {}, ...saved.sort ? { sort: saved.sort, dir: saved.dir || "desc" } : {} };
14111
14126
  });
14112
- const savePref = React71.useCallback((patch2) => {
14127
+ const savePref = React72.useCallback((patch2) => {
14113
14128
  const store = PREFS || window.PlannerPrefs;
14114
14129
  if (prefsKey && store) store.setTable(prefsKey, patch2);
14115
14130
  }, [prefsKey]);
14116
- const [res, setRes] = React71.useState(null);
14117
- const [loading, setLoading] = React71.useState(true);
14118
- const seq2 = React71.useRef(0);
14131
+ const [res, setRes] = React72.useState(null);
14132
+ const [loading, setLoading] = React72.useState(true);
14133
+ const seq2 = React72.useRef(0);
14119
14134
  const depKey = (deps || []).join("|");
14120
14135
  const paramKey = JSON.stringify(params || {});
14121
14136
  const queryKey = JSON.stringify(query);
14122
- React71.useEffect(() => {
14137
+ React72.useEffect(() => {
14123
14138
  const id = ++seq2.current;
14124
14139
  setLoading(true);
14125
14140
  const t = setTimeout(() => {
@@ -14438,12 +14453,12 @@ function createVersionStore(initialState, options) {
14438
14453
  }
14439
14454
 
14440
14455
  // src/kits/documentTitle.ts
14441
- import * as React72 from "react";
14456
+ import * as React73 from "react";
14442
14457
  function formatDocumentTitle(routeTitle, appName) {
14443
14458
  return [routeTitle, appName, "Flytedesk"].filter((part) => !!part && part.length > 0).join(" \xB7 ");
14444
14459
  }
14445
14460
  function useDocumentTitle(routeTitle, appName) {
14446
- React72.useEffect(() => {
14461
+ React73.useEffect(() => {
14447
14462
  if (typeof document === "undefined") return;
14448
14463
  document.title = formatDocumentTitle(routeTitle, appName);
14449
14464
  }, [routeTitle, appName]);
@@ -14457,6 +14472,7 @@ export {
14457
14472
  AppShell,
14458
14473
  AppSwitcher,
14459
14474
  AppearanceMenu,
14475
+ AppearanceProvider,
14460
14476
  Avatar,
14461
14477
  AvatarStack,
14462
14478
  Badge,
@@ -14612,6 +14628,7 @@ export {
14612
14628
  __resetLayerStackForTests,
14613
14629
  acceptMatches,
14614
14630
  anyOfFilter,
14631
+ applyAppearance,
14615
14632
  applyPrefs,
14616
14633
  channelWeightOf,
14617
14634
  computeNeedMore,
@@ -14657,6 +14674,7 @@ export {
14657
14674
  toAttachment,
14658
14675
  tokenize,
14659
14676
  useAppearancePrefs,
14677
+ useAppearanceStore,
14660
14678
  useChatEngine,
14661
14679
  useCopyToClipboard,
14662
14680
  useCornerStackSlot,
@@ -14672,6 +14690,7 @@ export {
14672
14690
  useStagedFiles,
14673
14691
  useToast,
14674
14692
  validateFilterValue,
14675
- visibleMessages
14693
+ visibleMessages,
14694
+ watchAppearance
14676
14695
  };
14677
14696
  //# sourceMappingURL=index.js.map