@flytedan/flytebot-design-system 0.57.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
@@ -1128,9 +1128,11 @@ import * as React10 from "react";
1128
1128
  // src/kits/cornerStack.tsx
1129
1129
  import * as React9 from "react";
1130
1130
  import { createPortal as createPortal4 } from "react-dom";
1131
+ var CORNER_STACK_INSET_PROPERTY = "--fd-corner-stack-inset";
1131
1132
  var SLOTS = ["jobs", "toasts"];
1132
1133
  var references = /* @__PURE__ */ new Map();
1133
1134
  var host = null;
1135
+ var hostObserver = null;
1134
1136
  var slotElements = /* @__PURE__ */ new Map();
1135
1137
  function createHost() {
1136
1138
  const stack = document.createElement("div");
@@ -1144,8 +1146,18 @@ function createHost() {
1144
1146
  slotElements.set(slot, element);
1145
1147
  }
1146
1148
  document.body.appendChild(stack);
1149
+ publishInset(stack);
1150
+ if (typeof ResizeObserver === "function") {
1151
+ hostObserver = new ResizeObserver(() => publishInset(stack));
1152
+ hostObserver.observe(stack);
1153
+ }
1147
1154
  return stack;
1148
1155
  }
1156
+ function publishInset(stack) {
1157
+ const height = stack.offsetHeight;
1158
+ const inset = height > 0 ? height + parseFloat(getComputedStyle(stack).bottom) : 0;
1159
+ document.documentElement.style.setProperty(CORNER_STACK_INSET_PROPERTY, `${inset}px`);
1160
+ }
1149
1161
  function acquire(slot) {
1150
1162
  host ??= createHost();
1151
1163
  references.set(slot, (references.get(slot) ?? 0) + 1);
@@ -1156,6 +1168,9 @@ function release(slot) {
1156
1168
  if (remaining > 0) references.set(slot, remaining);
1157
1169
  else references.delete(slot);
1158
1170
  if (references.size === 0 && host) {
1171
+ hostObserver?.disconnect();
1172
+ hostObserver = null;
1173
+ document.documentElement.style.removeProperty(CORNER_STACK_INSET_PROPERTY);
1159
1174
  host.remove();
1160
1175
  host = null;
1161
1176
  slotElements.clear();
@@ -1594,7 +1609,7 @@ function AppShell({
1594
1609
  /* @__PURE__ */ jsx21(
1595
1610
  "div",
1596
1611
  {
1597
- className: contentClassName,
1612
+ className: ["fd-app-shell-content", contentClassName].filter(Boolean).join(" "),
1598
1613
  style: {
1599
1614
  flex: 1,
1600
1615
  minWidth: 0,
@@ -1602,7 +1617,6 @@ function AppShell({
1602
1617
  // table) is contained and clipped by this scroller, never stretching the document.
1603
1618
  position: "relative",
1604
1619
  overflowY: "auto",
1605
- padding: 24,
1606
1620
  maxWidth: contentMaxWidth,
1607
1621
  margin: "0 auto",
1608
1622
  width: "100%",
@@ -8045,7 +8059,7 @@ function AppSwitcher({ apps: appsProp, onNavigate, className = "" }) {
8045
8059
  }
8046
8060
 
8047
8061
  // src/components/platform/AppearanceMenu.tsx
8048
- import * as React52 from "react";
8062
+ import * as React53 from "react";
8049
8063
 
8050
8064
  // src/kits/appearance.ts
8051
8065
  import * as React51 from "react";
@@ -8142,20 +8156,25 @@ function applyPrefs(prefs, root = document.documentElement) {
8142
8156
  if (prefs.reduceMotion) root.setAttribute("data-motion", "reduce");
8143
8157
  else root.removeAttribute("data-motion");
8144
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
+ }
8145
8176
  function useAppearancePrefs(store) {
8146
8177
  const prefs = React51.useSyncExternalStore(store.subscribe, store.getSnapshot);
8147
- React51.useEffect(() => {
8148
- applyPrefs(prefs);
8149
- }, [prefs]);
8150
- React51.useEffect(() => {
8151
- if (prefs.theme !== "system" || typeof window === "undefined" || typeof window.matchMedia !== "function") {
8152
- return;
8153
- }
8154
- const mq = window.matchMedia("(prefers-color-scheme: dark)");
8155
- const onChange = () => applyPrefs(prefs);
8156
- mq.addEventListener("change", onChange);
8157
- return () => mq.removeEventListener("change", onChange);
8158
- }, [prefs]);
8159
8178
  const update = React51.useCallback(
8160
8179
  (patch) => {
8161
8180
  store.write({ ...store.getSnapshot(), ...patch });
@@ -8165,8 +8184,22 @@ function useAppearancePrefs(store) {
8165
8184
  return [prefs, update];
8166
8185
  }
8167
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
+
8168
8201
  // src/components/platform/AppearanceMenu.tsx
8169
- import { jsx as jsx77, jsxs as jsxs68 } from "react/jsx-runtime";
8202
+ import { jsx as jsx78, jsxs as jsxs68 } from "react/jsx-runtime";
8170
8203
  var THEME_OPTIONS = [
8171
8204
  { value: "light", label: "Light" },
8172
8205
  { value: "dark", label: "Dark" },
@@ -8178,17 +8211,13 @@ var TEXT_SCALE_OPTIONS = [
8178
8211
  { value: "lg", label: "L" },
8179
8212
  { value: "xl", label: "XL" }
8180
8213
  ];
8181
- function AppearanceMenu({ className = "", store: storeProp, storageKey, storage, defaults }) {
8182
- const store = React52.useMemo(
8183
- () => storeProp ?? createLocalStorageAppearanceStore({ storageKey, storage, defaults }),
8184
- [storeProp, storageKey, storage, defaults]
8185
- );
8186
- const [prefs, update] = useAppearancePrefs(store);
8187
- const [open2, setOpen] = React52.useState(false);
8188
- 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);
8189
8218
  const patch = (p) => update(p);
8190
- return /* @__PURE__ */ jsxs68(React52.Fragment, { children: [
8191
- /* @__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(
8192
8221
  IconButton,
8193
8222
  {
8194
8223
  icon: "circle-half",
@@ -8196,7 +8225,7 @@ function AppearanceMenu({ className = "", store: storeProp, storageKey, storage,
8196
8225
  onClick: () => setOpen((v) => !v)
8197
8226
  }
8198
8227
  ) }),
8199
- /* @__PURE__ */ jsx77(
8228
+ /* @__PURE__ */ jsx78(
8200
8229
  Popover,
8201
8230
  {
8202
8231
  open: open2,
@@ -8208,8 +8237,8 @@ function AppearanceMenu({ className = "", store: storeProp, storageKey, storage,
8208
8237
  label: "Appearance settings",
8209
8238
  children: /* @__PURE__ */ jsxs68("div", { className: "fd-stack", style: { display: "flex", flexDirection: "column", gap: 16 }, children: [
8210
8239
  /* @__PURE__ */ jsxs68("div", { style: { display: "flex", flexDirection: "column", gap: 6 }, children: [
8211
- /* @__PURE__ */ jsx77("span", { className: "fd-field-label", children: "Theme" }),
8212
- /* @__PURE__ */ jsx77(
8240
+ /* @__PURE__ */ jsx78("span", { className: "fd-field-label", children: "Theme" }),
8241
+ /* @__PURE__ */ jsx78(
8213
8242
  SegmentedControl,
8214
8243
  {
8215
8244
  options: THEME_OPTIONS,
@@ -8220,8 +8249,8 @@ function AppearanceMenu({ className = "", store: storeProp, storageKey, storage,
8220
8249
  )
8221
8250
  ] }),
8222
8251
  /* @__PURE__ */ jsxs68("div", { style: { display: "flex", flexDirection: "column", gap: 6 }, children: [
8223
- /* @__PURE__ */ jsx77("span", { className: "fd-field-label", children: "Text size" }),
8224
- /* @__PURE__ */ jsx77(
8252
+ /* @__PURE__ */ jsx78("span", { className: "fd-field-label", children: "Text size" }),
8253
+ /* @__PURE__ */ jsx78(
8225
8254
  SegmentedControl,
8226
8255
  {
8227
8256
  options: TEXT_SCALE_OPTIONS,
@@ -8231,7 +8260,7 @@ function AppearanceMenu({ className = "", store: storeProp, storageKey, storage,
8231
8260
  }
8232
8261
  )
8233
8262
  ] }),
8234
- /* @__PURE__ */ jsx77(
8263
+ /* @__PURE__ */ jsx78(
8235
8264
  Switch,
8236
8265
  {
8237
8266
  label: "High contrast",
@@ -8240,7 +8269,7 @@ function AppearanceMenu({ className = "", store: storeProp, storageKey, storage,
8240
8269
  onChange: (e) => patch({ highContrast: e.target.checked })
8241
8270
  }
8242
8271
  ),
8243
- /* @__PURE__ */ jsx77(
8272
+ /* @__PURE__ */ jsx78(
8244
8273
  Switch,
8245
8274
  {
8246
8275
  label: "Reduce motion",
@@ -8256,14 +8285,14 @@ function AppearanceMenu({ className = "", store: storeProp, storageKey, storage,
8256
8285
  }
8257
8286
 
8258
8287
  // src/components/platform/ApiSpecBrowser.tsx
8259
- import * as React53 from "react";
8260
- 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";
8261
8290
  var METHOD_TONE = { GET: "success", POST: "info", PATCH: "warning", PUT: "warning", DELETE: "danger" };
8262
8291
  function Json({ obj }) {
8263
- 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) });
8264
8293
  }
8265
8294
  function Endpoint({ s, onRequest }) {
8266
- const [tried, setTried] = React53.useState(null);
8295
+ const [tried, setTried] = React54.useState(null);
8267
8296
  const run = async () => {
8268
8297
  setTried("busy");
8269
8298
  const t0 = (window.performance || Date).now();
@@ -8274,50 +8303,50 @@ function Endpoint({ s, onRequest }) {
8274
8303
  setTried({ ms: Math.round((window.performance || Date).now() - t0), error: String(e && e.message || e) });
8275
8304
  }
8276
8305
  };
8277
- 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: [
8278
8307
  /* @__PURE__ */ jsxs69("div", { className: "fd-row", style: { gap: 10, padding: "14px 18px", flexWrap: "wrap" }, children: [
8279
- /* @__PURE__ */ jsx78(Badge, { tone: METHOD_TONE[s.method] || "neutral", children: s.method }),
8280
- /* @__PURE__ */ jsx78("code", { className: "fd-mono", style: { fontSize: 12.5, fontWeight: 600, color: "var(--text)", wordBreak: "break-all" }, children: s.path }),
8281
- s.isList ? /* @__PURE__ */ jsx78(Badge, { tone: "neutral", icon: "rows", children: "Paged list" }) : null,
8282
- /* @__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 } }),
8283
8312
  /* @__PURE__ */ jsxs69("span", { className: "fd-body-sm fd-muted fd-mono", children: [
8284
8313
  s.latency[0],
8285
8314
  "\u2013",
8286
8315
  s.latency[1],
8287
8316
  "ms"
8288
8317
  ] }),
8289
- /* @__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" })
8290
8319
  ] }),
8291
8320
  /* @__PURE__ */ jsxs69("div", { className: "fd-stack", style: { gap: 14, padding: "0 18px 16px" }, children: [
8292
8321
  /* @__PURE__ */ jsxs69("div", { className: "fd-stack", style: { gap: 6 }, children: [
8293
- /* @__PURE__ */ jsx78("span", { className: "fd-body-sm", style: { fontWeight: 700 }, children: s.title }),
8294
- /* @__PURE__ */ jsx78("p", { className: "fd-body-sm fd-secondary", style: { margin: 0, textWrap: "pretty" }, children: s.purpose }),
8295
- 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
8296
8325
  ] }),
8297
8326
  /* @__PURE__ */ jsxs69("div", { style: { display: "grid", gridTemplateColumns: "repeat(auto-fit,minmax(280px,1fr))", gap: 12, alignItems: "start" }, children: [
8298
8327
  s.request ? /* @__PURE__ */ jsxs69("div", { className: "fd-stack", style: { gap: 6 }, children: [
8299
- /* @__PURE__ */ jsx78("span", { className: "fd-overline fd-muted", children: "Request body" }),
8300
- /* @__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 })
8301
8330
  ] }) : null,
8302
8331
  s.query ? /* @__PURE__ */ jsxs69("div", { className: "fd-stack", style: { gap: 6 }, children: [
8303
- /* @__PURE__ */ jsx78("span", { className: "fd-overline fd-muted", children: "Query" }),
8304
- /* @__PURE__ */ jsx78(Json, { obj: s.query })
8332
+ /* @__PURE__ */ jsx79("span", { className: "fd-overline fd-muted", children: "Query" }),
8333
+ /* @__PURE__ */ jsx79(Json, { obj: s.query })
8305
8334
  ] }) : null,
8306
8335
  /* @__PURE__ */ jsxs69("div", { className: "fd-stack", style: { gap: 6 }, children: [
8307
- /* @__PURE__ */ jsx78("span", { className: "fd-overline fd-muted", children: "Response 200" }),
8308
- /* @__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 })
8309
8338
  ] })
8310
8339
  ] }),
8311
- 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,
8312
8341
  tried && tried !== "busy" ? /* @__PURE__ */ jsxs69("div", { className: "fd-stack", style: { gap: 6 }, children: [
8313
8342
  /* @__PURE__ */ jsxs69("span", { className: "fd-row", style: { gap: 8 }, children: [
8314
- /* @__PURE__ */ jsx78("span", { className: "fd-overline fd-muted", children: "Simulated response" }),
8343
+ /* @__PURE__ */ jsx79("span", { className: "fd-overline fd-muted", children: "Simulated response" }),
8315
8344
  /* @__PURE__ */ jsxs69(Badge, { tone: tried.error ? "danger" : "success", icon: "timer", children: [
8316
8345
  tried.ms,
8317
8346
  "ms"
8318
8347
  ] })
8319
8348
  ] }),
8320
- /* @__PURE__ */ jsx78(Json, { obj: tried.error ? { error: tried.error } : tried.data })
8349
+ /* @__PURE__ */ jsx79(Json, { obj: tried.error ? { error: tried.error } : tried.data })
8321
8350
  ] }) : null
8322
8351
  ] })
8323
8352
  ] }) });
@@ -8336,10 +8365,10 @@ function ApiSpecBrowser({
8336
8365
  className = "",
8337
8366
  ...rest
8338
8367
  }) {
8339
- const [q, setQ] = React53.useState("");
8340
- const [method, setMethod] = React53.useState(null);
8341
- const [mod, setMod] = React53.useState(null);
8342
- 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);
8343
8372
  const activeModule = modules && modules.find((m) => m.id === mod);
8344
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())));
8345
8374
  const effGroups = groups && groups.length ? groups : [["All endpoints", spec.map((s) => s.id)]];
@@ -8347,46 +8376,46 @@ function ApiSpecBrowser({
8347
8376
  const listCount = spec.filter((s) => s.isList).length;
8348
8377
  return /* @__PURE__ */ jsxs69("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 20, maxWidth: 1100 }, ...rest, children: [
8349
8378
  /* @__PURE__ */ jsxs69("div", { className: "fd-stack", style: { gap: 10 }, children: [
8350
- kicker ? /* @__PURE__ */ jsx78("span", { className: "fd-overline fd-muted", children: kicker }) : null,
8351
- /* @__PURE__ */ jsx78("h1", { className: "fd-h1", style: { margin: 0 }, children: title }),
8352
- 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
8353
8382
  ] }),
8354
8383
  modules && modules.length ? /* @__PURE__ */ jsxs69("div", { className: "fd-stack", style: { gap: 8 }, children: [
8355
- /* @__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" }),
8356
8385
  /* @__PURE__ */ jsxs69("div", { className: "fd-row", style: { gap: 8, flexWrap: "wrap" }, children: [
8357
8386
  /* @__PURE__ */ jsxs69(Tag, { icon: "stack", selected: !mod, onClick: () => setMod(null), children: [
8358
8387
  "All screens ",
8359
- /* @__PURE__ */ jsx78("span", { className: "fd-mono", children: spec.length })
8388
+ /* @__PURE__ */ jsx79("span", { className: "fd-mono", children: spec.length })
8360
8389
  ] }),
8361
8390
  modules.map((m) => /* @__PURE__ */ jsxs69(Tag, { icon: m.icon, selected: mod === m.id, onClick: () => setMod(mod === m.id ? null : m.id), children: [
8362
8391
  m.label,
8363
8392
  " ",
8364
- /* @__PURE__ */ jsx78("span", { className: "fd-mono", children: m.endpoints.length })
8393
+ /* @__PURE__ */ jsx79("span", { className: "fd-mono", children: m.endpoints.length })
8365
8394
  ] }, m.id))
8366
8395
  ] }),
8367
- activeModule ? /* @__PURE__ */ jsx78(
8396
+ activeModule ? /* @__PURE__ */ jsx79(
8368
8397
  Flag,
8369
8398
  {
8370
8399
  tone: "info",
8371
8400
  statement: activeModule.label + " calls " + activeModule.endpoints.length + " endpoints.",
8372
8401
  cost: "Integration checklist for this screen: " + activeModule.endpoints.join(", ") + ". Wire these and the screen is done.",
8373
- 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" })
8374
8403
  }
8375
8404
  ) : null
8376
8405
  ] }) : null,
8377
- 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,
8378
8407
  /* @__PURE__ */ jsxs69("div", { className: "fd-row", style: { gap: 10, flexWrap: "wrap" }, children: [
8379
- /* @__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 } }),
8380
8409
  methods.map((m) => /* @__PURE__ */ jsxs69(Tag, { selected: method === m, onClick: () => setMethod(method === m ? null : m), children: [
8381
8410
  m,
8382
8411
  " ",
8383
- /* @__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 })
8384
8413
  ] }, m)),
8385
8414
  listCount ? /* @__PURE__ */ jsxs69(Tag, { icon: "rows", selected: listOnly, onClick: () => setListOnly(!listOnly), children: [
8386
8415
  "Paged lists ",
8387
- /* @__PURE__ */ jsx78("span", { className: "fd-mono", children: listCount })
8416
+ /* @__PURE__ */ jsx79("span", { className: "fd-mono", children: listCount })
8388
8417
  ] }) : null,
8389
- /* @__PURE__ */ jsx78("span", { style: { flex: 1 } }),
8418
+ /* @__PURE__ */ jsx79("span", { style: { flex: 1 } }),
8390
8419
  /* @__PURE__ */ jsxs69("span", { className: "fd-body-sm fd-muted", children: [
8391
8420
  hits.length,
8392
8421
  " of ",
@@ -8395,31 +8424,31 @@ function ApiSpecBrowser({
8395
8424
  listCount ? " \xB7 " + listCount + " paged" : ""
8396
8425
  ] })
8397
8426
  ] }),
8398
- 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]) => {
8399
8428
  const items = hits.filter((s) => ids.indexOf(s.id) >= 0);
8400
8429
  if (!items.length) return null;
8401
8430
  return /* @__PURE__ */ jsxs69("div", { className: "fd-stack", style: { gap: 12 }, children: [
8402
- /* @__PURE__ */ jsx78("span", { className: "fd-label-lg", children: g }),
8403
- 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))
8404
8433
  ] }, g);
8405
8434
  }),
8406
- 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: [
8407
- /* @__PURE__ */ jsx78("span", { className: "fd-overline fd-muted", style: { width: 110, flex: "none", paddingTop: 2 }, children: k }),
8408
- /* @__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 })
8409
8438
  ] }, k)) }) }) : null,
8410
- 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: [
8411
- /* @__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 }),
8412
8441
  /* @__PURE__ */ jsxs69("span", { className: "fd-stack", style: { gap: 2, flex: 1 }, children: [
8413
- /* @__PURE__ */ jsx78("span", { className: "fd-body-sm", style: { fontWeight: 600 }, children: question }),
8414
- /* @__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 })
8415
8444
  ] })
8416
8445
  ] }, id)) }) }) : null
8417
8446
  ] });
8418
8447
  }
8419
8448
 
8420
8449
  // src/components/platform/ProfilePage.tsx
8421
- import * as React54 from "react";
8422
- 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";
8423
8452
  function fieldInitialValue(field, user) {
8424
8453
  if (field.value) return field.value(user);
8425
8454
  const raw = user[field.key];
@@ -8454,21 +8483,21 @@ function ProfilePage({
8454
8483
  }) {
8455
8484
  const { user: sessionUser, roles, permissions, saveProfile: saveProfile2 } = useSessionContext();
8456
8485
  const user = userProp || sessionUser;
8457
- const initialFieldValues = React54.useMemo(() => {
8486
+ const initialFieldValues = React55.useMemo(() => {
8458
8487
  const values2 = {};
8459
8488
  for (const field of fields) values2[field.key] = fieldInitialValue(field, user);
8460
8489
  return values2;
8461
8490
  }, [user.id, fields]);
8462
- const initialNotify = React54.useMemo(() => {
8491
+ const initialNotify = React55.useMemo(() => {
8463
8492
  const values2 = {};
8464
8493
  for (const n of notifications) values2[n.key] = !!user.notify?.[n.key];
8465
8494
  return values2;
8466
8495
  }, [user.id, notifications]);
8467
- const [values, setValues] = React54.useState(initialFieldValues);
8468
- const [notify, setNotify] = React54.useState(initialNotify);
8469
- const [saving, setSaving] = React54.useState(false);
8470
- const [saved, setSaved] = React54.useState(false);
8471
- 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);
8472
8501
  if (user.id !== prevUserId) {
8473
8502
  setPrevUserId(user.id);
8474
8503
  setValues(initialFieldValues);
@@ -8507,35 +8536,35 @@ function ProfilePage({
8507
8536
  const fieldGroups = groupFields(fields);
8508
8537
  return /* @__PURE__ */ jsxs70("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 20, maxWidth: 860 }, children: [
8509
8538
  /* @__PURE__ */ jsxs70("div", { className: "fd-stack", style: { gap: 10 }, children: [
8510
- /* @__PURE__ */ jsx79("span", { className: "fd-overline fd-muted", children: "Account" }),
8511
- /* @__PURE__ */ jsx79("h1", { className: "fd-h1", style: { margin: 0 }, children: "Your profile" }),
8512
- /* @__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." })
8513
8542
  ] }),
8514
- /* @__PURE__ */ jsx79(Card, { elevation: "flat", children: /* @__PURE__ */ jsxs70("div", { className: "fd-row", style: { gap: 16, flexWrap: "wrap", alignItems: "flex-start" }, children: [
8515
- /* @__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" }),
8516
8545
  /* @__PURE__ */ jsxs70("div", { className: "fd-stack", style: { gap: 4, flex: 1, minWidth: 200 }, children: [
8517
- /* @__PURE__ */ jsx79("span", { className: "fd-h3", style: { margin: 0 }, children: displayName }),
8546
+ /* @__PURE__ */ jsx80("span", { className: "fd-h3", style: { margin: 0 }, children: displayName }),
8518
8547
  /* @__PURE__ */ jsxs70("span", { className: "fd-row", style: { gap: 6, flexWrap: "wrap", paddingTop: 4 }, children: [
8519
- roles.map((r) => /* @__PURE__ */ jsx79(Badge, { tone: r.id === "owner" ? "success" : "neutral", children: r.name }, r.id)),
8520
- 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
8521
8550
  ] })
8522
8551
  ] }),
8523
- 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
8524
8553
  ] }) }),
8525
- fieldGroups.map(({ group, description, fields: groupFieldDefs }) => /* @__PURE__ */ jsx79(
8554
+ fieldGroups.map(({ group, description, fields: groupFieldDefs }) => /* @__PURE__ */ jsx80(
8526
8555
  Card,
8527
8556
  {
8528
8557
  title: description ? /* @__PURE__ */ jsxs70("span", { className: "fd-stack", style: { gap: 2 }, children: [
8529
- /* @__PURE__ */ jsx79("span", { children: group }),
8530
- /* @__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 })
8531
8560
  ] }) : group,
8532
8561
  elevation: "flat",
8533
8562
  children: /* @__PURE__ */ jsxs70("div", { className: "fd-stack", style: { gap: 14 }, children: [
8534
- /* @__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) => {
8535
8564
  const help = typeof field.help === "function" ? field.help(user) : field.help;
8536
8565
  const readOnly = field.readOnly || field.type === "readonly";
8537
8566
  if (field.type === "select") {
8538
- return /* @__PURE__ */ jsx79(
8567
+ return /* @__PURE__ */ jsx80(
8539
8568
  Select,
8540
8569
  {
8541
8570
  label: field.label,
@@ -8549,7 +8578,7 @@ function ProfilePage({
8549
8578
  field.key
8550
8579
  );
8551
8580
  }
8552
- return /* @__PURE__ */ jsx79(
8581
+ return /* @__PURE__ */ jsx80(
8553
8582
  Input,
8554
8583
  {
8555
8584
  label: field.label,
@@ -8565,7 +8594,7 @@ function ProfilePage({
8565
8594
  }) }),
8566
8595
  groupFieldDefs.filter((f) => f.type === "textarea").map((field) => {
8567
8596
  const help = typeof field.help === "function" ? field.help(user) : field.help;
8568
- return /* @__PURE__ */ jsx79(
8597
+ return /* @__PURE__ */ jsx80(
8569
8598
  Textarea,
8570
8599
  {
8571
8600
  label: field.label,
@@ -8585,16 +8614,16 @@ function ProfilePage({
8585
8614
  group
8586
8615
  )),
8587
8616
  extra,
8588
- 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,
8589
8618
  /* @__PURE__ */ jsxs70(
8590
8619
  Card,
8591
8620
  {
8592
8621
  title: /* @__PURE__ */ jsxs70("span", { className: "fd-stack", style: { gap: 2 }, children: [
8593
- /* @__PURE__ */ jsx79("span", { children: "Access" }),
8594
- /* @__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" })
8595
8624
  ] }),
8596
8625
  elevation: "flat",
8597
- action: /* @__PURE__ */ jsx79(
8626
+ action: /* @__PURE__ */ jsx80(
8598
8627
  Button,
8599
8628
  {
8600
8629
  size: "sm",
@@ -8606,34 +8635,34 @@ function ProfilePage({
8606
8635
  ),
8607
8636
  children: [
8608
8637
  /* @__PURE__ */ jsxs70("div", { className: "fd-stack", style: { gap: 0 }, children: [
8609
- /* @__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" }),
8610
8639
  /* @__PURE__ */ jsxs70(CardRow, { label: "Permissions", children: [
8611
8640
  permissions.length,
8612
8641
  " granted"
8613
8642
  ] }),
8614
- /* @__PURE__ */ jsx79(CardRow, { label: "Member since", children: user.joined || "\u2014" })
8643
+ /* @__PURE__ */ jsx80(CardRow, { label: "Member since", children: user.joined || "\u2014" })
8615
8644
  ] }),
8616
- /* @__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." })
8617
8646
  ]
8618
8647
  }
8619
8648
  ),
8620
- sessions ? /* @__PURE__ */ jsx79(
8649
+ sessions ? /* @__PURE__ */ jsx80(
8621
8650
  Card,
8622
8651
  {
8623
8652
  title: "Signed-in devices",
8624
8653
  elevation: "flat",
8625
- action: /* @__PURE__ */ jsx79(Button, { size: "sm", variant: "ghost", icon: "sign-out", onClick: onSignOutEverywhere, children: "Sign out everywhere" }),
8626
- 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: [
8627
- /* @__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" }),
8628
8657
  /* @__PURE__ */ jsxs70("span", { className: "fd-stack", style: { gap: 1, flex: 1, minWidth: 160 }, children: [
8629
- /* @__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 }),
8630
8659
  /* @__PURE__ */ jsxs70("span", { className: "fd-body-sm fd-muted", children: [
8631
8660
  s.where,
8632
8661
  " \xB7 ",
8633
8662
  s.when
8634
8663
  ] })
8635
8664
  ] }),
8636
- 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" })
8637
8666
  ] }, s.id)) })
8638
8667
  }
8639
8668
  ) : null,
@@ -8648,16 +8677,16 @@ function ProfilePage({
8648
8677
  border: "1px solid var(--border)",
8649
8678
  boxShadow: "0 -4px 16px rgba(11,13,17,.06)"
8650
8679
  }, children: [
8651
- /* @__PURE__ */ jsx79("span", { className: "fd-body-sm", style: { fontWeight: 600, flex: 1 }, children: saved ? "Saved." : dirty ? "Unsaved changes" : "No pending changes" }),
8652
- /* @__PURE__ */ jsx79(Button, { size: "sm", variant: "ghost", disabled: !dirty || saving, onClick: discard, children: "Discard" }),
8653
- /* @__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" })
8654
8683
  ] })
8655
8684
  ] });
8656
8685
  }
8657
8686
 
8658
8687
  // src/components/platform/SessionScreen.tsx
8659
- import * as React55 from "react";
8660
- 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";
8661
8690
  var COPY = {
8662
8691
  "signing-in": { busy: "Signing you in\u2026" },
8663
8692
  "session-expired": { busy: "Your session expired \u2014 signing you back in\u2026" },
@@ -8670,28 +8699,28 @@ function SessionScreen({ kind, error, onRetry, productName }) {
8670
8699
  const copy = COPY[kind];
8671
8700
  const busyMessage = "busy" in copy ? copy.busy : null;
8672
8701
  const failureTitle = "failure" in copy ? copy.failure : null;
8673
- const [announced, setAnnounced] = React55.useState("");
8674
- React55.useEffect(() => {
8702
+ const [announced, setAnnounced] = React56.useState("");
8703
+ React56.useEffect(() => {
8675
8704
  setAnnounced(busyMessage ?? "");
8676
8705
  }, [busyMessage]);
8677
- const titleRef = React55.useRef(null);
8706
+ const titleRef = React56.useRef(null);
8678
8707
  const failed = failureTitle !== null;
8679
- React55.useEffect(() => {
8708
+ React56.useEffect(() => {
8680
8709
  titleRef.current?.focus({ preventScroll: true });
8681
8710
  }, [failed]);
8682
- return /* @__PURE__ */ jsx80("main", { className: "fd-session-screen", children: /* @__PURE__ */ jsxs71("div", { className: "fd-session-screen-inner", children: [
8683
- /* @__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" }) }),
8684
8713
  /* @__PURE__ */ jsxs71("div", { className: "fd-session-screen-frame", children: [
8685
- /* @__PURE__ */ jsx80("div", { className: "fd-session-screen-stripe" }),
8686
- /* @__PURE__ */ jsx80(Card, { children: /* @__PURE__ */ jsxs71("div", { className: "fd-session-screen-body", children: [
8687
- /* @__PURE__ */ jsx80("h1", { ref: titleRef, tabIndex: -1, className: "fd-h3 fd-session-screen-title", children: productName }),
8688
- /* @__PURE__ */ jsx80("div", { role: "status", "aria-live": "polite", className: "fd-session-screen-status", children: busyMessage !== null ? /* @__PURE__ */ jsxs71(Fragment20, { children: [
8689
- /* @__PURE__ */ jsx80("span", { className: "fd-spinner fd-spinner-lg fd-session-screen-spinner", "aria-hidden": "true" }),
8690
- /* @__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 })
8691
8720
  ] }) : null }),
8692
8721
  failureTitle !== null ? /* @__PURE__ */ jsxs71("div", { className: "fd-session-screen-failure", children: [
8693
- /* @__PURE__ */ jsx80(Banner, { tone: "danger", title: failureTitle, detail: error ?? void 0 }),
8694
- 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
8695
8724
  ] }) : null
8696
8725
  ] }) })
8697
8726
  ] })
@@ -8699,10 +8728,10 @@ function SessionScreen({ kind, error, onRetry, productName }) {
8699
8728
  }
8700
8729
 
8701
8730
  // src/components/platform/RoadmapTimeline.tsx
8702
- import * as React58 from "react";
8731
+ import * as React59 from "react";
8703
8732
 
8704
8733
  // src/kits/session.ts
8705
- import * as React56 from "react";
8734
+ import * as React57 from "react";
8706
8735
  var PERMISSION_CATALOG = [
8707
8736
  { group: "Plans", items: [
8708
8737
  { key: "plan.view", label: "View plans", detail: "Read any plan in the workspace." },
@@ -10269,8 +10298,8 @@ function roadmap(overrides) {
10269
10298
  };
10270
10299
  }
10271
10300
  function useSession() {
10272
- const [s, setS] = React56.useState(getSession);
10273
- React56.useEffect(() => subscribe(setS), []);
10301
+ const [s, setS] = React57.useState(getSession);
10302
+ React57.useEffect(() => subscribe(setS), []);
10274
10303
  return s;
10275
10304
  }
10276
10305
  var SessionKit = {
@@ -10303,7 +10332,7 @@ var SessionKit = {
10303
10332
  };
10304
10333
  function DemoSessionProvider({ children }) {
10305
10334
  const session = useSession();
10306
- const value = React56.useMemo(
10335
+ const value = React57.useMemo(
10307
10336
  () => ({
10308
10337
  user: session.user,
10309
10338
  roles: session.roles,
@@ -10319,11 +10348,11 @@ function DemoSessionProvider({ children }) {
10319
10348
  }),
10320
10349
  [session]
10321
10350
  );
10322
- return React56.createElement(SessionProvider, { value }, children);
10351
+ return React57.createElement(SessionProvider, { value }, children);
10323
10352
  }
10324
10353
 
10325
10354
  // src/kits/runtime.ts
10326
- import * as React57 from "react";
10355
+ import * as React58 from "react";
10327
10356
  var WIRED_ENDPOINTS = [
10328
10357
  // Nothing yet. Every id below would come from a real service:
10329
10358
  // "plan.get", "placements.list", …
@@ -10494,8 +10523,8 @@ var RuntimeKit = {
10494
10523
  };
10495
10524
  RuntimeKit.declare(FEATURE_NEEDS);
10496
10525
  function useRuntimeMode() {
10497
- const [m, setM] = React57.useState(RuntimeKit.getMode());
10498
- React57.useEffect(() => RuntimeKit.subscribe(setM), []);
10526
+ const [m, setM] = React58.useState(RuntimeKit.getMode());
10527
+ React58.useEffect(() => RuntimeKit.subscribe(setM), []);
10499
10528
  return m;
10500
10529
  }
10501
10530
  function useFeatureStatus(key) {
@@ -10514,7 +10543,7 @@ var UseRuntimeMode = useRuntimeMode;
10514
10543
  var UseFeatureStatus = useFeatureStatus;
10515
10544
 
10516
10545
  // src/components/platform/RoadmapTimeline.tsx
10517
- import { jsx as jsx81, jsxs as jsxs72 } from "react/jsx-runtime";
10546
+ import { jsx as jsx82, jsxs as jsxs72 } from "react/jsx-runtime";
10518
10547
  var STATUS = {
10519
10548
  shipped: { tone: "success", icon: "check-circle", label: "Wired" },
10520
10549
  next: { tone: "warning", icon: "traffic-cone", label: "Not wired" },
@@ -10529,43 +10558,43 @@ function RoadmapCard({ item, byKey, onOpenFlag }) {
10529
10558
  const s = STATUS[item.status] || STATUS.planned;
10530
10559
  const deps = (item.dependsOn || []).map((k) => byKey[k]).filter(Boolean);
10531
10560
  const blocking = deps.filter((d) => !d.implemented);
10532
- 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: [
10533
10562
  /* @__PURE__ */ jsxs72("div", { className: "fd-row", style: { gap: 8, flexWrap: "wrap" }, children: [
10534
- /* @__PURE__ */ jsx81("span", { className: "fd-body", style: { fontWeight: 700, flex: 1, minWidth: 140 }, children: item.label }),
10535
- /* @__PURE__ */ jsx81(Badge, { tone: "neutral", icon: PROJECT_ICON[item.project] || "squares-four", children: item.project }),
10536
- /* @__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 })
10537
10566
  ] }),
10538
- /* @__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 }),
10539
10568
  item.backend ? /* @__PURE__ */ jsxs72("div", { className: "fd-row", style: { gap: 10, alignItems: "flex-start" }, children: [
10540
- /* @__PURE__ */ jsx81("span", { className: "fd-overline fd-muted", style: { width: 62, flex: "none", paddingTop: 2 }, children: "Backend" }),
10541
- /* @__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 })
10542
10571
  ] }) : null,
10543
10572
  /* @__PURE__ */ jsxs72("div", { className: "fd-row", style: { gap: 12, flexWrap: "wrap" }, children: [
10544
10573
  item.effort ? /* @__PURE__ */ jsxs72("span", { className: "fd-body-sm fd-muted", children: [
10545
- /* @__PURE__ */ jsx81("i", { className: "ph ph-hourglass-medium" }),
10574
+ /* @__PURE__ */ jsx82("i", { className: "ph ph-hourglass-medium" }),
10546
10575
  " ",
10547
10576
  item.effort
10548
10577
  ] }) : null,
10549
10578
  /* @__PURE__ */ jsxs72("span", { className: "fd-body-sm fd-muted", children: [
10550
- /* @__PURE__ */ jsx81("i", { className: "ph ph-user" }),
10579
+ /* @__PURE__ */ jsx82("i", { className: "ph ph-user" }),
10551
10580
  " ",
10552
10581
  item.owner
10553
10582
  ] }),
10554
- item.screen ? /* @__PURE__ */ jsx81(Badge, { tone: "neutral", icon: "browser", children: "screen" }) : null,
10555
- /* @__PURE__ */ jsx81("span", { style: { flex: 1 } }),
10556
- /* @__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(
10557
10586
  "button",
10558
10587
  {
10559
10588
  type: "button",
10560
10589
  onClick: () => onOpenFlag && onOpenFlag(item.key),
10561
10590
  style: { all: "unset", cursor: "pointer", display: "inline-flex", alignItems: "center", gap: 5 },
10562
- 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 })
10563
10592
  }
10564
10593
  )
10565
10594
  ] }),
10566
10595
  deps.length ? /* @__PURE__ */ jsxs72("div", { className: "fd-row", style: { gap: 6, flexWrap: "wrap", paddingTop: 6, borderTop: "1px solid var(--border)" }, children: [
10567
- /* @__PURE__ */ jsx81("span", { className: "fd-overline fd-muted", style: { paddingTop: 3 }, children: "After" }),
10568
- 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))
10569
10598
  ] }) : null,
10570
10599
  blocking.length && !item.implemented ? /* @__PURE__ */ jsxs72("span", { className: "fd-body-sm", style: { color: "var(--warn-text)" }, children: [
10571
10600
  "Blocked until ",
@@ -10578,12 +10607,12 @@ function RoadmapCard({ item, byKey, onOpenFlag }) {
10578
10607
  }
10579
10608
  function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
10580
10609
  const session = SessionKit.useSession();
10581
- const [project, setProject] = React58.useState("");
10582
- const [q, setQ] = React58.useState("");
10583
- const scrollRef = React58.useRef(null);
10584
- const nowRef = React58.useRef(null);
10585
- const rm = React58.useMemo(() => SessionKit.roadmap({ isComplete: RuntimeKit.isComplete }), [session]);
10586
- 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(() => {
10587
10616
  const m = {};
10588
10617
  rm.items.forEach((i) => {
10589
10618
  m[i.key] = i;
@@ -10592,7 +10621,7 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
10592
10621
  }, [rm]);
10593
10622
  const items = rm.items.filter((i) => (!project || i.project === project) && (!q || (i.label + " " + i.description + " " + (i.backend || "") + " " + i.key).toLowerCase().includes(q.toLowerCase())));
10594
10623
  const projects = [...new Set(rm.items.map((i) => i.project))];
10595
- React58.useEffect(() => {
10624
+ React59.useEffect(() => {
10596
10625
  let raf1 = 0, raf2 = 0;
10597
10626
  const place = () => {
10598
10627
  const box = scrollRef.current, mark = nowRef.current;
@@ -10622,21 +10651,21 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
10622
10651
  let lastPhase = null;
10623
10652
  return /* @__PURE__ */ jsxs72("div", { className: "fd-stack", style: { gap: 16, maxWidth: 1e3 }, children: [
10624
10653
  /* @__PURE__ */ jsxs72("div", { className: "fd-stack", style: { gap: 10 }, children: [
10625
- /* @__PURE__ */ jsx81("span", { className: "fd-overline fd-muted", children: "Architecture" }),
10626
- /* @__PURE__ */ jsx81("h1", { className: "fd-h1", style: { margin: 0 }, children: title }),
10627
- /* @__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." })
10628
10657
  ] }),
10629
10658
  /* @__PURE__ */ jsxs72("div", { className: "fd-grid-stats is-thin", children: [
10630
- /* @__PURE__ */ jsx81(StatTile, { compact: true, label: "Wired", value: String(rm.shipped), sub: "of " + rm.items.length + " features" }),
10631
- /* @__PURE__ */ jsx81(StatTile, { compact: true, label: "Remaining", value: String(rm.remaining), sub: "backend work" }),
10632
- /* @__PURE__ */ jsx81(StatTile, { compact: true, label: "Est. effort", value: days ? days + " days" : "\u2014", sub: "sum of estimates, not calendar" }),
10633
- /* @__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" })
10634
10663
  ] }),
10635
10664
  /* @__PURE__ */ jsxs72("div", { className: "fd-row", style: { gap: 10, flexWrap: "wrap" }, children: [
10636
- /* @__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 } }),
10637
- /* @__PURE__ */ jsx81(Select, { placeholder: "All projects", value: project, onChange: (e) => setProject(e.target.value), options: projects, style: { width: 190 } }),
10638
- /* @__PURE__ */ jsx81("span", { style: { flex: 1 } }),
10639
- /* @__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(
10640
10669
  Button,
10641
10670
  {
10642
10671
  size: "sm",
@@ -10650,7 +10679,7 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
10650
10679
  }
10651
10680
  )
10652
10681
  ] }),
10653
- /* @__PURE__ */ jsx81(
10682
+ /* @__PURE__ */ jsx82(
10654
10683
  Flag,
10655
10684
  {
10656
10685
  tone: "info",
@@ -10659,17 +10688,17 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
10659
10688
  actions: null
10660
10689
  }
10661
10690
  ),
10662
- /* @__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: [
10663
- /* @__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%" } }) }),
10664
10693
  items.map((item, n) => {
10665
10694
  const showPhase = item.phase !== lastPhase;
10666
10695
  lastPhase = item.phase;
10667
10696
  const inPhase = items.filter((i) => i.phase === item.phase).length;
10668
10697
  const isBoundary = n === firstPending;
10669
- return /* @__PURE__ */ jsxs72(React58.Fragment, { children: [
10698
+ return /* @__PURE__ */ jsxs72(React59.Fragment, { children: [
10670
10699
  showPhase ? /* @__PURE__ */ jsxs72("div", { className: "fd-rm-era", children: [
10671
10700
  /* @__PURE__ */ jsxs72("span", { className: "fd-row", style: { gap: 8, flexWrap: "wrap", alignItems: "baseline" }, children: [
10672
- /* @__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 }),
10673
10702
  item.phase === 0 ? null : /* @__PURE__ */ jsxs72("span", { className: "fd-mono", style: { opacity: 0.7, fontWeight: 400 }, children: [
10674
10703
  fmtDate(item.phaseStart),
10675
10704
  " \u2013 ",
@@ -10682,37 +10711,37 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
10682
10711
  inPhase === 1 ? "" : "s"
10683
10712
  ] })
10684
10713
  ] }),
10685
- 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
10686
10715
  ] }) : null,
10687
- isBoundary ? /* @__PURE__ */ jsx81("div", { className: "fd-rm-now", ref: nowRef, children: /* @__PURE__ */ jsxs72("span", { className: "fd-rm-now-pill", children: [
10688
- /* @__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" }),
10689
10718
  " You are here \u2014 everything above is wired"
10690
10719
  ] }) }) : null,
10691
10720
  /* @__PURE__ */ jsxs72("div", { className: "fd-rm-row", children: [
10692
- /* @__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" : "") }),
10693
10722
  /* @__PURE__ */ jsxs72("div", { className: "fd-rm-date", children: [
10694
10723
  fmtDate(item.date),
10695
- /* @__PURE__ */ jsx81("br", {}),
10696
- /* @__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 })
10697
10726
  ] }),
10698
- /* @__PURE__ */ jsx81(RoadmapCard, { item, byKey, onOpenFlag })
10727
+ /* @__PURE__ */ jsx82(RoadmapCard, { item, byKey, onOpenFlag })
10699
10728
  ] })
10700
10729
  ] }, item.key);
10701
10730
  }),
10702
- !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
10703
10732
  ] }) }) }),
10704
10733
  /* @__PURE__ */ jsxs72("p", { className: "fd-body-sm fd-muted", style: { margin: 0 }, children: [
10705
10734
  "Derived from the feature-flag registry \u2014 each entry's status is its flag's ",
10706
- /* @__PURE__ */ jsx81("code", { className: "fd-mono", children: "implemented" }),
10735
+ /* @__PURE__ */ jsx82("code", { className: "fd-mono", children: "implemented" }),
10707
10736
  " field, so this page cannot drift from what the apps actually do."
10708
10737
  ] })
10709
10738
  ] });
10710
10739
  }
10711
10740
 
10712
10741
  // src/components/platform/ComingSoon.tsx
10713
- import * as React59 from "react";
10742
+ import * as React60 from "react";
10714
10743
  import { createPortal as createPortal6 } from "react-dom";
10715
- 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";
10716
10745
  var BYPASS_STORE = "fd.soon.bypass.v1";
10717
10746
  function readBypassed() {
10718
10747
  try {
@@ -10728,8 +10757,8 @@ function writeBypassed(list) {
10728
10757
  }
10729
10758
  }
10730
10759
  function useBypass(key) {
10731
- const [on, setOn] = React59.useState(() => !!key && readBypassed().indexOf(key) >= 0);
10732
- React59.useEffect(() => {
10760
+ const [on, setOn] = React60.useState(() => !!key && readBypassed().indexOf(key) >= 0);
10761
+ React60.useEffect(() => {
10733
10762
  setOn(!!key && readBypassed().indexOf(key) >= 0);
10734
10763
  }, [key]);
10735
10764
  const set = (next) => {
@@ -10744,41 +10773,41 @@ function useBypass(key) {
10744
10773
  function SoonCard({ label, detail, backend, eta, effort, onRoadmap, allowed, onBypass }) {
10745
10774
  return /* @__PURE__ */ jsxs73(Fragment22, { children: [
10746
10775
  /* @__PURE__ */ jsxs73("span", { className: "fd-soon-badge", children: [
10747
- /* @__PURE__ */ jsx82("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" }),
10776
+ /* @__PURE__ */ jsx83("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" }),
10748
10777
  label
10749
10778
  ] }),
10750
- detail ? /* @__PURE__ */ jsx82("span", { className: "fd-soon-detail", children: detail }) : null,
10779
+ detail ? /* @__PURE__ */ jsx83("span", { className: "fd-soon-detail", children: detail }) : null,
10751
10780
  backend ? /* @__PURE__ */ jsxs73("span", { className: "fd-soon-backend", children: [
10752
- /* @__PURE__ */ jsx82("span", { className: "fd-overline", children: "Needs" }),
10781
+ /* @__PURE__ */ jsx83("span", { className: "fd-overline", children: "Needs" }),
10753
10782
  " ",
10754
10783
  backend
10755
10784
  ] }) : null,
10756
10785
  eta || effort || onRoadmap ? /* @__PURE__ */ jsxs73("span", { className: "fd-soon-meta", children: [
10757
10786
  eta ? /* @__PURE__ */ jsxs73("span", { children: [
10758
- /* @__PURE__ */ jsx82("i", { className: "ph ph-calendar-blank", "aria-hidden": "true" }),
10787
+ /* @__PURE__ */ jsx83("i", { className: "ph ph-calendar-blank", "aria-hidden": "true" }),
10759
10788
  " ",
10760
10789
  eta
10761
10790
  ] }) : null,
10762
10791
  effort ? /* @__PURE__ */ jsxs73("span", { children: [
10763
- /* @__PURE__ */ jsx82("i", { className: "ph ph-hourglass-medium", "aria-hidden": "true" }),
10792
+ /* @__PURE__ */ jsx83("i", { className: "ph ph-hourglass-medium", "aria-hidden": "true" }),
10764
10793
  " ",
10765
10794
  effort
10766
10795
  ] }) : null,
10767
10796
  onRoadmap ? /* @__PURE__ */ jsxs73("button", { type: "button", className: "fd-soon-link", onClick: onRoadmap, children: [
10768
10797
  "See the roadmap ",
10769
- /* @__PURE__ */ jsx82("i", { className: "ph ph-arrow-right", "aria-hidden": "true" })
10798
+ /* @__PURE__ */ jsx83("i", { className: "ph ph-arrow-right", "aria-hidden": "true" })
10770
10799
  ] }) : null
10771
10800
  ] }) : null,
10772
10801
  allowed ? /* @__PURE__ */ jsxs73("button", { type: "button", className: "fd-soon-view", onClick: onBypass, children: [
10773
- /* @__PURE__ */ jsx82("i", { className: "ph ph-eye", "aria-hidden": "true" }),
10802
+ /* @__PURE__ */ jsx83("i", { className: "ph ph-eye", "aria-hidden": "true" }),
10774
10803
  " View and use it anyway"
10775
10804
  ] }) : null
10776
10805
  ] });
10777
10806
  }
10778
10807
  function useHoverCard(open2) {
10779
- const anchor = React59.useRef(null);
10780
- const [pos, setPos] = React59.useState(null);
10781
- React59.useLayoutEffect(() => {
10808
+ const anchor = React60.useRef(null);
10809
+ const [pos, setPos] = React60.useState(null);
10810
+ React60.useLayoutEffect(() => {
10782
10811
  if (!open2 || !anchor.current) {
10783
10812
  setPos(null);
10784
10813
  return;
@@ -10832,7 +10861,7 @@ function ComingSoon({
10832
10861
  if (allowed && bypassed) {
10833
10862
  return /* @__PURE__ */ jsxs73("span", { className: ["fd-soon-inline-on", className].filter(Boolean).join(" "), ...rest, children: [
10834
10863
  children,
10835
- /* @__PURE__ */ jsx82(
10864
+ /* @__PURE__ */ jsx83(
10836
10865
  "button",
10837
10866
  {
10838
10867
  type: "button",
@@ -10840,12 +10869,12 @@ function ComingSoon({
10840
10869
  title: "Unwired \u2014 writes go to the simulated backend. " + tip + " Click to re-blur.",
10841
10870
  onClick: () => setBypassed(false),
10842
10871
  "aria-label": "Re-blur this unwired feature",
10843
- 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" })
10844
10873
  }
10845
10874
  )
10846
10875
  ] });
10847
10876
  }
10848
- return /* @__PURE__ */ jsx82(
10877
+ return /* @__PURE__ */ jsx83(
10849
10878
  InlineSoon,
10850
10879
  {
10851
10880
  label,
@@ -10868,17 +10897,17 @@ function ComingSoon({
10868
10897
  return /* @__PURE__ */ jsxs73("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 14 }, ...rest, children: [
10869
10898
  /* @__PURE__ */ jsxs73("div", { className: "fd-soon-bar", role: "status", children: [
10870
10899
  /* @__PURE__ */ jsxs73("span", { className: "fd-soon-badge", children: [
10871
- /* @__PURE__ */ jsx82("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" }),
10900
+ /* @__PURE__ */ jsx83("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" }),
10872
10901
  "Unwired feature \u2014 you are using it anyway"
10873
10902
  ] }),
10874
- /* @__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." }),
10875
10904
  /* @__PURE__ */ jsxs73("span", { className: "fd-soon-bar-actions", children: [
10876
10905
  onRoadmap ? /* @__PURE__ */ jsxs73("button", { type: "button", className: "fd-soon-link", onClick: onRoadmap, children: [
10877
10906
  "Roadmap ",
10878
- /* @__PURE__ */ jsx82("i", { className: "ph ph-arrow-right", "aria-hidden": "true" })
10907
+ /* @__PURE__ */ jsx83("i", { className: "ph ph-arrow-right", "aria-hidden": "true" })
10879
10908
  ] }) : null,
10880
10909
  /* @__PURE__ */ jsxs73("button", { type: "button", className: "fd-soon-link", onClick: () => setBypassed(false), children: [
10881
- /* @__PURE__ */ jsx82("i", { className: "ph ph-eye-slash", "aria-hidden": "true" }),
10910
+ /* @__PURE__ */ jsx83("i", { className: "ph ph-eye-slash", "aria-hidden": "true" }),
10882
10911
  " Re-blur"
10883
10912
  ] })
10884
10913
  ] })
@@ -10887,9 +10916,9 @@ function ComingSoon({
10887
10916
  ] });
10888
10917
  }
10889
10918
  return /* @__PURE__ */ jsxs73("div", { className: ["fd-soon", className].filter(Boolean).join(" "), style: minHeight ? { minHeight } : void 0, ...rest, children: [
10890
- /* @__PURE__ */ jsx82("div", { className: "fd-soon-under", style: { filter: "blur(" + blur + "px) saturate(.62)" }, ...{ inert: "" }, "aria-hidden": "true", children }),
10891
- /* @__PURE__ */ jsx82("div", { className: "fd-soon-veil" }),
10892
- /* @__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(
10893
10922
  SoonCard,
10894
10923
  {
10895
10924
  label,
@@ -10905,12 +10934,12 @@ function ComingSoon({
10905
10934
  ] });
10906
10935
  }
10907
10936
  function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, onBypass, blur, tip, className, rest, children }) {
10908
- const [open2, setOpen] = React59.useState(false);
10937
+ const [open2, setOpen] = React60.useState(false);
10909
10938
  const [anchor, pos] = useHoverCard(open2);
10910
- const hoverCardRef = React59.useRef(null);
10939
+ const hoverCardRef = React60.useRef(null);
10911
10940
  const hoverLayer = useStackedLayer({ active: open2, containerRef: hoverCardRef, returnFocus: false });
10912
10941
  const zIndex = useLayerZIndex(hoverLayer);
10913
- const close2 = React59.useRef(null);
10942
+ const close2 = React60.useRef(null);
10914
10943
  const show = () => {
10915
10944
  if (close2.current) {
10916
10945
  clearTimeout(close2.current);
@@ -10926,7 +10955,7 @@ function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, o
10926
10955
  setOpen(false);
10927
10956
  }, 140);
10928
10957
  };
10929
- React59.useEffect(() => () => {
10958
+ React60.useEffect(() => () => {
10930
10959
  if (close2.current) clearTimeout(close2.current);
10931
10960
  }, []);
10932
10961
  return /* @__PURE__ */ jsxs73(
@@ -10940,8 +10969,8 @@ function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, o
10940
10969
  onBlur: hide,
10941
10970
  ...rest,
10942
10971
  children: [
10943
- /* @__PURE__ */ jsx82("span", { className: "fd-soon-under", style: { filter: "blur(" + Math.min(blur, 1.1) + "px) saturate(.66)" }, ...{ inert: "" }, "aria-hidden": "true", children }),
10944
- /* @__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(
10945
10974
  "button",
10946
10975
  {
10947
10976
  type: "button",
@@ -10952,11 +10981,11 @@ function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, o
10952
10981
  onFocus: show,
10953
10982
  onBlur: hide,
10954
10983
  onClick: () => open2 ? setOpen(false) : show(),
10955
- 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" })
10956
10985
  }
10957
10986
  ),
10958
10987
  open2 && pos ? createPortal6(
10959
- /* @__PURE__ */ jsx82(
10988
+ /* @__PURE__ */ jsx83(
10960
10989
  "div",
10961
10990
  {
10962
10991
  ref: hoverCardRef,
@@ -10965,7 +10994,7 @@ function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, o
10965
10994
  style: { position: "fixed", left: pos.left, top: pos.top, bottom: pos.bottom, width: pos.width, zIndex },
10966
10995
  onMouseEnter: show,
10967
10996
  onMouseLeave: hide,
10968
- children: /* @__PURE__ */ jsx82(
10997
+ children: /* @__PURE__ */ jsx83(
10969
10998
  SoonCard,
10970
10999
  {
10971
11000
  label,
@@ -10995,7 +11024,7 @@ function formatEta(iso2) {
10995
11024
  var FormatEta = formatEta;
10996
11025
 
10997
11026
  // src/components/platform/Gate.tsx
10998
- import { jsx as jsx83, jsxs as jsxs74 } from "react/jsx-runtime";
11027
+ import { jsx as jsx84, jsxs as jsxs74 } from "react/jsx-runtime";
10999
11028
  function PermissionDenied({ permission, title, detail, compact: compact3 = false, className = "", ...rest }) {
11000
11029
  const need = Array.isArray(permission) ? permission : [permission].filter(Boolean);
11001
11030
  return /* @__PURE__ */ jsxs74(
@@ -11015,13 +11044,13 @@ function PermissionDenied({ permission, title, detail, compact: compact3 = false
11015
11044
  ...rest,
11016
11045
  children: [
11017
11046
  /* @__PURE__ */ jsxs74("span", { className: "fd-row", style: { gap: 8 }, children: [
11018
- /* @__PURE__ */ jsx83("i", { className: "ph ph-lock-simple", style: { fontSize: 16, color: "var(--text-muted)" }, "aria-hidden": "true" }),
11019
- /* @__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" })
11020
11049
  ] }),
11021
- /* @__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." }),
11022
11051
  need.length ? /* @__PURE__ */ jsxs74("span", { className: "fd-row", style: { gap: 6, flexWrap: "wrap" }, children: [
11023
- /* @__PURE__ */ jsx83("span", { className: "fd-overline fd-muted", children: "Requires" }),
11024
- 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: {
11025
11054
  fontSize: 11.5,
11026
11055
  padding: "2px 7px",
11027
11056
  borderRadius: 5,
@@ -11051,10 +11080,10 @@ function GatePending({ compact: compact3 = false, className = "" }) {
11051
11080
  },
11052
11081
  children: [
11053
11082
  /* @__PURE__ */ jsxs74("span", { className: "fd-row", style: { gap: 8 }, children: [
11054
- /* @__PURE__ */ jsx83("i", { className: "ph ph-arrows-clockwise", style: { fontSize: 16, color: "var(--text-muted)" }, "aria-hidden": "true" }),
11055
- /* @__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" })
11056
11085
  ] }),
11057
- /* @__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." })
11058
11087
  ]
11059
11088
  }
11060
11089
  );
@@ -11064,7 +11093,7 @@ function Gate({ perm, anyOf, role, silent = false, fallback, pendingFallback, co
11064
11093
  if (pending) {
11065
11094
  if (pendingFallback !== void 0) return pendingFallback;
11066
11095
  if (silent) return null;
11067
- return /* @__PURE__ */ jsx83(GatePending, { compact: compact3 });
11096
+ return /* @__PURE__ */ jsx84(GatePending, { compact: compact3 });
11068
11097
  }
11069
11098
  let ok = true;
11070
11099
  if (perm) ok = ok && can2(perm);
@@ -11073,7 +11102,7 @@ function Gate({ perm, anyOf, role, silent = false, fallback, pendingFallback, co
11073
11102
  if (ok) return children;
11074
11103
  if (fallback !== void 0) return fallback;
11075
11104
  if (silent) return null;
11076
- return /* @__PURE__ */ jsx83(PermissionDenied, { permission: perm || anyOf, compact: compact3 });
11105
+ return /* @__PURE__ */ jsx84(PermissionDenied, { permission: perm || anyOf, compact: compact3 });
11077
11106
  }
11078
11107
  function FeatureGate({
11079
11108
  flag,
@@ -11096,7 +11125,7 @@ function FeatureGate({
11096
11125
  const f = SessionKit.findFlag(flag) || {};
11097
11126
  const missing = rt.missing || [];
11098
11127
  const canBypass = pending ? false : bypassPerm === null ? false : !bypassPerm || can2(bypassPerm);
11099
- return /* @__PURE__ */ jsx83(
11128
+ return /* @__PURE__ */ jsx84(
11100
11129
  ComingSoon,
11101
11130
  {
11102
11131
  label: label || (variant === "inline" ? f.label || "Not wired yet" : "Designed \u2014 backend not wired yet"),
@@ -11117,22 +11146,22 @@ function FeatureGate({
11117
11146
  function PermissionHint({ perm, children }) {
11118
11147
  const { can: can2, pending } = useSessionContext();
11119
11148
  if (pending) {
11120
- 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 }) });
11121
11150
  }
11122
11151
  if (can2(perm)) return children;
11123
- return /* @__PURE__ */ jsx83(
11152
+ return /* @__PURE__ */ jsx84(
11124
11153
  "span",
11125
11154
  {
11126
11155
  title: "Requires " + (Array.isArray(perm) ? perm.join(", ") : perm),
11127
11156
  style: { display: "inline-flex", opacity: 0.45, cursor: "not-allowed" },
11128
11157
  "aria-disabled": "true",
11129
- children: /* @__PURE__ */ jsx83("span", { style: { pointerEvents: "none" }, children })
11158
+ children: /* @__PURE__ */ jsx84("span", { style: { pointerEvents: "none" }, children })
11130
11159
  }
11131
11160
  );
11132
11161
  }
11133
11162
 
11134
11163
  // src/components/platform/ModeSwitch.tsx
11135
- 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";
11136
11165
  function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog, onOpenSpec, summary }) {
11137
11166
  const mode2 = useRuntimeMode();
11138
11167
  const panel = useInlinePanel();
@@ -11155,15 +11184,15 @@ function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog
11155
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.",
11156
11185
  className: "fd-mode-btn" + (test ? " is-test" : "") + (open2 ? " is-open" : ""),
11157
11186
  children: [
11158
- /* @__PURE__ */ jsx84("i", { className: "ph " + (test ? "ph-flask" : "ph-lightning"), style: { fontSize: 17 } }),
11159
- 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
11160
11189
  ]
11161
11190
  }
11162
11191
  ),
11163
11192
  /* @__PURE__ */ jsxs75(InlinePanelSurface, { panel, align: "right", offset: 8, width: 400, className: "fd-mode-pop", label: test ? "Test mode" : "Live mode", children: [
11164
11193
  /* @__PURE__ */ jsxs75("span", { className: "fd-row", style: { gap: 10, padding: "12px 14px", borderBottom: "1px solid var(--border)" }, children: [
11165
11194
  /* @__PURE__ */ jsxs75("span", { className: "fd-badge " + (test ? "fd-badge-warning" : "fd-badge-neutral"), children: [
11166
- /* @__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" }),
11167
11196
  test ? "Test mode" : "Live mode"
11168
11197
  ] }),
11169
11198
  test ? /* @__PURE__ */ jsxs75("span", { className: "fd-body-sm fd-muted fd-mono", children: [
@@ -11171,11 +11200,11 @@ function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog
11171
11200
  " simulated request",
11172
11201
  requestCount === 1 ? "" : "s"
11173
11202
  ] }) : null,
11174
- /* @__PURE__ */ jsx84("span", { style: { flex: 1 } }),
11175
- 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
11176
11205
  ] }),
11177
11206
  /* @__PURE__ */ jsxs75("span", { style: { display: "block", padding: "12px 14px", borderBottom: "1px solid var(--border)" }, children: [
11178
- /* @__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." }),
11179
11208
  /* @__PURE__ */ jsxs75("span", { className: "fd-row", style: { gap: 8, marginTop: 10, flexWrap: "wrap" }, children: [
11180
11209
  /* @__PURE__ */ jsxs75("span", { className: "fd-body-sm fd-muted fd-mono", children: [
11181
11210
  s.endpointsWired,
@@ -11188,36 +11217,36 @@ function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog
11188
11217
  " features complete"
11189
11218
  ] }),
11190
11219
  onOpenSpec ? /* @__PURE__ */ jsxs75(Fragment23, { children: [
11191
- /* @__PURE__ */ jsx84("span", { style: { flex: 1 } }),
11220
+ /* @__PURE__ */ jsx85("span", { style: { flex: 1 } }),
11192
11221
  /* @__PURE__ */ jsxs75("button", { type: "button", className: "fd-soon-link", onClick: () => {
11193
11222
  setOpen(false);
11194
11223
  onOpenSpec();
11195
11224
  }, children: [
11196
11225
  "API spec ",
11197
- /* @__PURE__ */ jsx84("i", { className: "ph ph-arrow-right", "aria-hidden": "true" })
11226
+ /* @__PURE__ */ jsx85("i", { className: "ph ph-arrow-right", "aria-hidden": "true" })
11198
11227
  ] })
11199
11228
  ] }) : null
11200
11229
  ] })
11201
11230
  ] }),
11202
11231
  /* @__PURE__ */ jsxs75("span", { className: "fd-mode-choice", children: [
11203
11232
  /* @__PURE__ */ jsxs75("button", { type: "button", className: "fd-mode-opt" + (!test ? " is-on" : ""), onClick: () => go("live"), children: [
11204
- /* @__PURE__ */ jsx84("i", { className: "ph ph-lightning", "aria-hidden": "true" }),
11233
+ /* @__PURE__ */ jsx85("i", { className: "ph ph-lightning", "aria-hidden": "true" }),
11205
11234
  /* @__PURE__ */ jsxs75("span", { className: "fd-mode-opt-text", children: [
11206
- /* @__PURE__ */ jsx84("span", { className: "fd-mode-opt-title", children: "Live mode" }),
11207
- /* @__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" })
11208
11237
  ] }),
11209
- !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
11210
11239
  ] }),
11211
11240
  /* @__PURE__ */ jsxs75("button", { type: "button", className: "fd-mode-opt" + (test ? " is-on" : ""), onClick: () => go("test"), children: [
11212
- /* @__PURE__ */ jsx84("i", { className: "ph ph-flask", "aria-hidden": "true" }),
11241
+ /* @__PURE__ */ jsx85("i", { className: "ph ph-flask", "aria-hidden": "true" }),
11213
11242
  /* @__PURE__ */ jsxs75("span", { className: "fd-mode-opt-text", children: [
11214
- /* @__PURE__ */ jsx84("span", { className: "fd-mode-opt-title", children: "Test mode" }),
11215
- /* @__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" })
11216
11245
  ] }),
11217
- 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
11218
11247
  ] })
11219
11248
  ] }),
11220
- 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
11221
11250
  ] })
11222
11251
  ] });
11223
11252
  }
@@ -11226,19 +11255,19 @@ function TestModeBar({ onExit }) {
11226
11255
  if (mode2 !== "test") return null;
11227
11256
  return /* @__PURE__ */ jsxs75("div", { className: "fd-testbar", role: "status", children: [
11228
11257
  /* @__PURE__ */ jsxs75("span", { className: "fd-badge fd-badge-warning", children: [
11229
- /* @__PURE__ */ jsx84("i", { className: "ph ph-flask", "aria-hidden": "true" }),
11258
+ /* @__PURE__ */ jsx85("i", { className: "ph ph-flask", "aria-hidden": "true" }),
11230
11259
  "Test mode"
11231
11260
  ] }),
11232
- /* @__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." }),
11233
11262
  /* @__PURE__ */ jsxs75("button", { type: "button", className: "fd-soon-link", onClick: () => onExit ? onExit() : RuntimeKit.setMode("live"), children: [
11234
- /* @__PURE__ */ jsx84("i", { className: "ph ph-lightning", "aria-hidden": "true" }),
11263
+ /* @__PURE__ */ jsx85("i", { className: "ph ph-lightning", "aria-hidden": "true" }),
11235
11264
  " Back to live mode"
11236
11265
  ] })
11237
11266
  ] });
11238
11267
  }
11239
11268
 
11240
11269
  // src/components/planner/ChannelMeta.tsx
11241
- import { jsx as jsx85, jsxs as jsxs76 } from "react/jsx-runtime";
11270
+ import { jsx as jsx86, jsxs as jsxs76 } from "react/jsx-runtime";
11242
11271
  var CHANNEL_WEIGHTS = {
11243
11272
  "OOH": 50,
11244
11273
  "DOOH": 50,
@@ -11291,7 +11320,7 @@ function ChannelTag({ channel, size = "md", showLabel = true, dot = false, weigh
11291
11320
  const m = ChannelMeta(channel);
11292
11321
  const wt = channelWeightOf(channel || "");
11293
11322
  if (dot) {
11294
- 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 });
11295
11324
  }
11296
11325
  return /* @__PURE__ */ jsxs76(
11297
11326
  "span",
@@ -11301,16 +11330,16 @@ function ChannelTag({ channel, size = "md", showLabel = true, dot = false, weigh
11301
11330
  style: { "--chan": m.color },
11302
11331
  ...rest,
11303
11332
  children: [
11304
- /* @__PURE__ */ jsx85("i", { className: "ph ph-" + m.icon, "aria-hidden": "true" }),
11305
- showLabel ? /* @__PURE__ */ jsx85("span", { className: "fd-chan-label", children: m.label }) : null,
11306
- 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
11307
11336
  ]
11308
11337
  }
11309
11338
  );
11310
11339
  }
11311
11340
 
11312
11341
  // src/components/planner/SaturationDistribution.tsx
11313
- import { jsx as jsx86, jsxs as jsxs77 } from "react/jsx-runtime";
11342
+ import { jsx as jsx87, jsxs as jsxs77 } from "react/jsx-runtime";
11314
11343
  var BANDS2 = [
11315
11344
  { key: "weak", label: "Weak", n: 1, range: "< 50" },
11316
11345
  { key: "adequate", label: "Adequate", n: 2, range: "50\u2013100" },
@@ -11322,7 +11351,7 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
11322
11351
  const tallest = Math.max(1, ...grouped.map((g) => g.items.length));
11323
11352
  const floor = BANDS2.find((b) => b.key === floorBand) || BANDS2[0];
11324
11353
  return /* @__PURE__ */ jsxs77("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 16 }, children: [
11325
- /* @__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) => {
11326
11355
  const mark = "var(--csi-" + g.n + "-mark)";
11327
11356
  const active = selectedBand === g.key;
11328
11357
  return /* @__PURE__ */ jsxs77(
@@ -11332,13 +11361,13 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
11332
11361
  onClick: onSelectBand ? () => onSelectBand(active ? null : g.key) : void 0,
11333
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)" },
11334
11363
  children: [
11335
- /* @__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) => (
11336
11365
  // `overflow: hidden` + `white-space: nowrap` only clips once the span
11337
11366
  // actually HAS a bounded width to clip against (see the grid/flex
11338
11367
  // `minWidth: 0` chain above) — `textOverflow: ellipsis` then makes
11339
11368
  // that clip readable instead of a hard cut mid-letter; the full name
11340
11369
  // is still one hover away via `title`.
11341
- /* @__PURE__ */ jsx86(
11370
+ /* @__PURE__ */ jsx87(
11342
11371
  "span",
11343
11372
  {
11344
11373
  title: c.name + " \xB7 " + c.crp,
@@ -11349,11 +11378,11 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
11349
11378
  )
11350
11379
  )) }),
11351
11380
  /* @__PURE__ */ jsxs77("span", { className: "fd-row", style: { gap: 8, alignItems: "baseline" }, children: [
11352
- /* @__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 }),
11353
- /* @__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)) })
11354
11383
  ] }),
11355
11384
  /* @__PURE__ */ jsxs77("span", { className: "fd-stack", style: { gap: 1 }, children: [
11356
- /* @__PURE__ */ jsx86("span", { className: "fd-label-lg", children: g.label }),
11385
+ /* @__PURE__ */ jsx87("span", { className: "fd-label-lg", children: g.label }),
11357
11386
  /* @__PURE__ */ jsxs77("span", { className: "fd-body-sm fd-muted", style: { fontSize: 11.5 }, children: [
11358
11387
  "CRP ",
11359
11388
  g.range
@@ -11365,7 +11394,7 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
11365
11394
  );
11366
11395
  }) }),
11367
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: [
11368
- /* @__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)) }),
11369
11398
  /* @__PURE__ */ jsxs77("span", { className: "fd-body-sm fd-secondary", style: { flex: 1, minWidth: 240 }, children: [
11370
11399
  /* @__PURE__ */ jsxs77("strong", { style: { color: "var(--text)" }, children: [
11371
11400
  "Plan floor ",
@@ -11378,8 +11407,8 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
11378
11407
  }
11379
11408
 
11380
11409
  // src/components/planner/MixGap.tsx
11381
- import * as React60 from "react";
11382
- 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";
11383
11412
  var MIX_GAP_LAYOUT = {
11384
11413
  trackHeight: 30,
11385
11414
  barHeight: 20,
@@ -11393,7 +11422,7 @@ function mixGapOffset(value, max) {
11393
11422
  }
11394
11423
  function MixGap({ rows = [], loading = false, className = "" }) {
11395
11424
  const max = Math.max(1, ...rows.flatMap((r) => [r.target, r.realized]));
11396
- const [hover, setHover] = React60.useState(null);
11425
+ const [hover, setHover] = React61.useState(null);
11397
11426
  const toneOf = (gap) => gap >= -1 ? "ok" : gap >= -4 ? "warn" : "danger";
11398
11427
  const TONE = { ok: "var(--ok-solid)", warn: "var(--warn-solid)", danger: "var(--danger-solid)" };
11399
11428
  const { trackHeight, barHeight, targetWidth, labelGap } = MIX_GAP_LAYOUT;
@@ -11401,11 +11430,11 @@ function MixGap({ rows = [], loading = false, className = "" }) {
11401
11430
  return /* @__PURE__ */ jsxs78("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 4 }, children: [
11402
11431
  /* @__PURE__ */ jsxs78("div", { className: "fd-row", style: { gap: 16, justifyContent: "flex-end", paddingBottom: 6, flexWrap: "wrap" }, children: [
11403
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: [
11404
- /* @__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 } }),
11405
11434
  l
11406
11435
  ] }, l)),
11407
11436
  /* @__PURE__ */ jsxs78("span", { className: "fd-row fd-body-sm fd-muted", style: { gap: 6 }, children: [
11408
- /* @__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 } }),
11409
11438
  "Target"
11410
11439
  ] })
11411
11440
  ] }),
@@ -11422,15 +11451,15 @@ function MixGap({ rows = [], loading = false, className = "" }) {
11422
11451
  onMouseEnter: () => setHover(r.channel),
11423
11452
  onMouseLeave: () => setHover(null),
11424
11453
  children: [
11425
- /* @__PURE__ */ jsx87("span", { style: { width: 128, flex: "none" }, children: /* @__PURE__ */ jsx87(ChannelTag, { channel: r.channel, size: "sm" }) }),
11426
- /* @__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: [
11427
- /* @__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)" } }),
11428
- /* @__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 } }),
11429
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: [
11430
11459
  r.realized,
11431
11460
  "%"
11432
11461
  ] }),
11433
- 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
11434
11463
  ] }) })
11435
11464
  ]
11436
11465
  },
@@ -11441,7 +11470,7 @@ function MixGap({ rows = [], loading = false, className = "" }) {
11441
11470
  }
11442
11471
 
11443
11472
  // src/components/planner/ChannelContribution.tsx
11444
- import { jsx as jsx88, jsxs as jsxs79 } from "react/jsx-runtime";
11473
+ import { jsx as jsx89, jsxs as jsxs79 } from "react/jsx-runtime";
11445
11474
  var money = (n) => "$" + Math.round(n).toLocaleString();
11446
11475
  function ChannelContribution({
11447
11476
  channels = [],
@@ -11458,8 +11487,8 @@ function ChannelContribution({
11458
11487
  const pct = (v) => grand ? v / grand * 100 : 0;
11459
11488
  const spendTotal = channels.reduce((s, c) => s + Number(String(c.spend || 0).replace(/[^0-9.]/g, "")), 0);
11460
11489
  return /* @__PURE__ */ jsxs79("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 16 }, children: [
11461
- 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: [
11462
- 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(
11463
11492
  "span",
11464
11493
  {
11465
11494
  title: c.name + " \xB7 " + c.crp.toFixed(1) + " CRP",
@@ -11468,7 +11497,7 @@ function ChannelContribution({
11468
11497
  },
11469
11498
  c.name
11470
11499
  )),
11471
- bonus > 0 ? /* @__PURE__ */ jsx88(
11500
+ bonus > 0 ? /* @__PURE__ */ jsx89(
11472
11501
  "span",
11473
11502
  {
11474
11503
  title: "Surround-sound bonus +" + bonusPct + "%",
@@ -11478,17 +11507,17 @@ function ChannelContribution({
11478
11507
  ) : null
11479
11508
  ] }),
11480
11509
  showTable ? /* @__PURE__ */ jsxs79("table", { className: "fd-table", style: { fontSize: "var(--body-sm-size)" }, children: [
11481
- /* @__PURE__ */ jsx88("thead", { children: /* @__PURE__ */ jsxs79("tr", { children: [
11482
- /* @__PURE__ */ jsx88("th", { style: { width: "34%" }, children: "Channel" }),
11483
- /* @__PURE__ */ jsx88("th", { style: { width: "16%" }, children: "Weight" }),
11484
- /* @__PURE__ */ jsx88("th", { className: "is-num", style: { width: "16%" }, children: "Spend" }),
11485
- /* @__PURE__ */ jsx88("th", { className: "is-num", style: { width: "17%" }, children: "CRP" }),
11486
- /* @__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" })
11487
11516
  ] }) }),
11488
11517
  /* @__PURE__ */ jsxs79("tbody", { children: [
11489
11518
  channels.map((c) => /* @__PURE__ */ jsxs79("tr", { children: [
11490
- /* @__PURE__ */ jsx88("td", { children: /* @__PURE__ */ jsx88(ChannelTag, { channel: c.name, size: "sm" }) }),
11491
- /* @__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(
11492
11521
  "span",
11493
11522
  {
11494
11523
  className: "fd-badge fd-badge-neutral",
@@ -11497,38 +11526,38 @@ function ChannelContribution({
11497
11526
  children: "weight " + (channelWeightOf(c.name) || 0)
11498
11527
  }
11499
11528
  ) }),
11500
- /* @__PURE__ */ jsx88("td", { className: "is-num", children: c.spend }),
11501
- /* @__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) }),
11502
11531
  /* @__PURE__ */ jsxs79("td", { className: "is-num", children: [
11503
11532
  pct(c.crp).toFixed(0),
11504
11533
  "%"
11505
11534
  ] })
11506
11535
  ] }, c.name)),
11507
11536
  bonus > 0 ? /* @__PURE__ */ jsxs79("tr", { children: [
11508
- /* @__PURE__ */ jsx88("td", { children: /* @__PURE__ */ jsxs79("span", { className: "fd-row", style: { gap: 9, fontWeight: 600 }, children: [
11509
- /* @__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" } }),
11510
11539
  "Surround-sound bonus"
11511
11540
  ] }) }),
11512
- /* @__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: [
11513
11542
  "+",
11514
11543
  bonusPct,
11515
11544
  "% of +",
11516
11545
  bonusMax,
11517
11546
  "%"
11518
11547
  ] }) }),
11519
- /* @__PURE__ */ jsx88("td", { className: "is-num fd-muted", children: "\u2014" }),
11520
- /* @__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) }),
11521
11550
  /* @__PURE__ */ jsxs79("td", { className: "is-num", children: [
11522
11551
  pct(bonus).toFixed(0),
11523
11552
  "%"
11524
11553
  ] })
11525
11554
  ] }) : null,
11526
11555
  /* @__PURE__ */ jsxs79("tr", { style: { background: "var(--surface-2)" }, children: [
11527
- /* @__PURE__ */ jsx88("td", { style: { fontWeight: 700 }, children: "Campus total" }),
11528
- /* @__PURE__ */ jsx88("td", {}),
11529
- /* @__PURE__ */ jsx88("td", { className: "is-num", style: { fontWeight: 700 }, children: money(spendTotal) }),
11530
- /* @__PURE__ */ jsx88("td", { className: "is-num", style: { fontWeight: 700 }, children: grand.toFixed(1) }),
11531
- /* @__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%" })
11532
11561
  ] })
11533
11562
  ] })
11534
11563
  ] }) : null
@@ -11536,8 +11565,8 @@ function ChannelContribution({
11536
11565
  }
11537
11566
 
11538
11567
  // src/components/planner/BudgetReallocator.tsx
11539
- import * as React61 from "react";
11540
- 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";
11541
11570
  var bandFor = (crp) => crp >= 200 ? "dominant" : crp >= 100 ? "strong" : crp >= 50 ? "adequate" : "weak";
11542
11571
  function BudgetReallocator({
11543
11572
  campus,
@@ -11552,8 +11581,8 @@ function BudgetReallocator({
11552
11581
  onCancel,
11553
11582
  className = ""
11554
11583
  }) {
11555
- const [draft, setDraft] = React61.useState(spend);
11556
- React61.useEffect(() => setDraft(spend), [spend]);
11584
+ const [draft, setDraft] = React62.useState(spend);
11585
+ React62.useEffect(() => setDraft(spend), [spend]);
11557
11586
  const dirty = draft !== spend;
11558
11587
  const nextCrp = scoreFor ? scoreFor(draft) : crp;
11559
11588
  const nextBand = bandFor(nextCrp);
@@ -11568,10 +11597,10 @@ function BudgetReallocator({
11568
11597
  setDraft(spend);
11569
11598
  if (onCancel) onCancel();
11570
11599
  };
11571
- const trackRef = React61.useRef(null);
11572
- const chipRef = React61.useRef(null);
11573
- const [chipLeft, setChipLeft] = React61.useState(null);
11574
- React61.useLayoutEffect(() => {
11600
+ const trackRef = React62.useRef(null);
11601
+ const chipRef = React62.useRef(null);
11602
+ const [chipLeft, setChipLeft] = React62.useState(null);
11603
+ React62.useLayoutEffect(() => {
11575
11604
  const track = trackRef.current;
11576
11605
  if (!dirty || !track) {
11577
11606
  setChipLeft(null);
@@ -11599,16 +11628,16 @@ function BudgetReallocator({
11599
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)" },
11600
11629
  children: [
11601
11630
  /* @__PURE__ */ jsxs80("div", { className: "fd-row", style: { gap: 12, flexWrap: "wrap" }, children: [
11602
- /* @__PURE__ */ jsx89("span", { className: "fd-h4", style: { flex: 1, minWidth: 140 }, children: campus }),
11603
- /* @__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" }),
11604
11633
  dirty ? /* @__PURE__ */ jsxs80(Fragment25, { children: [
11605
- /* @__PURE__ */ jsx89("i", { className: "ph ph-arrow-right fd-muted", "aria-hidden": "true" }),
11606
- /* @__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 })
11607
11636
  ] }) : null
11608
11637
  ] }),
11609
11638
  /* @__PURE__ */ jsxs80("div", { className: "fd-slider", ref: trackRef, children: [
11610
- /* @__PURE__ */ jsx89("span", { className: "fd-slider-fill", style: { width: pct + "%" } }),
11611
- dirty ? /* @__PURE__ */ jsx89(
11639
+ /* @__PURE__ */ jsx90("span", { className: "fd-slider-fill", style: { width: pct + "%" } }),
11640
+ dirty ? /* @__PURE__ */ jsx90(
11612
11641
  "span",
11613
11642
  {
11614
11643
  ref: chipRef,
@@ -11620,7 +11649,7 @@ function BudgetReallocator({
11620
11649
  children: (delta < 0 ? "\u2212$" : "+$") + Math.abs(delta).toLocaleString()
11621
11650
  }
11622
11651
  ) : null,
11623
- /* @__PURE__ */ jsx89(
11652
+ /* @__PURE__ */ jsx90(
11624
11653
  "input",
11625
11654
  {
11626
11655
  type: "range",
@@ -11638,11 +11667,11 @@ function BudgetReallocator({
11638
11667
  ] }),
11639
11668
  /* @__PURE__ */ jsxs80("div", { className: "fd-row", style: { gap: 12, flexWrap: "wrap" }, children: [
11640
11669
  /* @__PURE__ */ jsxs80("span", { className: "fd-stack", style: { gap: 2, flex: 1, minWidth: 150 }, children: [
11641
- /* @__PURE__ */ jsx89("span", { className: "fd-num", style: { fontSize: 19, fontWeight: 700 }, children: "$" + draft.toLocaleString() }),
11642
- /* @__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." })
11643
11672
  ] }),
11644
- /* @__PURE__ */ jsx89("button", { type: "button", className: "fd-btn fd-btn-ghost", disabled: !dirty, onClick: revert, children: "Cancel" }),
11645
- /* @__PURE__ */ jsx89(
11673
+ /* @__PURE__ */ jsx90("button", { type: "button", className: "fd-btn fd-btn-ghost", disabled: !dirty, onClick: revert, children: "Cancel" }),
11674
+ /* @__PURE__ */ jsx90(
11646
11675
  "button",
11647
11676
  {
11648
11677
  type: "button",
@@ -11661,7 +11690,7 @@ function BudgetReallocator({
11661
11690
  }
11662
11691
 
11663
11692
  // src/components/planner/SurroundSound.tsx
11664
- import { jsx as jsx90, jsxs as jsxs81 } from "react/jsx-runtime";
11693
+ import { jsx as jsx91, jsxs as jsxs81 } from "react/jsx-runtime";
11665
11694
  var CATEGORIES = [
11666
11695
  { key: "ooh", label: "OOH", icon: "flag-banner", color: "var(--ch-ooh)" },
11667
11696
  { key: "transit", label: "Transit", icon: "bus", color: "var(--ch-transit)" },
@@ -11674,7 +11703,7 @@ function SurroundSound({ present = [], bonusPct = 0, bonusMax = 40, missedCost,
11674
11703
  const earned = Math.max(0, Math.min(1, bonusPct / bonusMax));
11675
11704
  const single = present.length <= 2;
11676
11705
  return /* @__PURE__ */ jsxs81("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 14 }, children: [
11677
- /* @__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) => {
11678
11707
  const on = present.includes(c.key);
11679
11708
  return /* @__PURE__ */ jsxs81(
11680
11709
  "span",
@@ -11682,8 +11711,8 @@ function SurroundSound({ present = [], bonusPct = 0, bonusMax = 40, missedCost,
11682
11711
  title: c.label + (on ? " \u2014 present" : " \u2014 not bought"),
11683
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)" },
11684
11713
  children: [
11685
- /* @__PURE__ */ jsx90("i", { className: "ph ph-" + c.icon, style: { fontSize: 19, color: on ? c.color : "var(--text-muted)" }, "aria-hidden": "true" }),
11686
- /* @__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 })
11687
11716
  ]
11688
11717
  },
11689
11718
  c.key
@@ -11691,7 +11720,7 @@ function SurroundSound({ present = [], bonusPct = 0, bonusMax = 40, missedCost,
11691
11720
  }) }),
11692
11721
  /* @__PURE__ */ jsxs81("div", { className: "fd-stack", style: { gap: 8 }, children: [
11693
11722
  /* @__PURE__ */ jsxs81("div", { className: "fd-row", style: { justifyContent: "space-between", gap: 12 }, children: [
11694
- /* @__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" }),
11695
11724
  /* @__PURE__ */ jsxs81("span", { className: "fd-num", style: { color: single ? "var(--warn-text)" : "var(--csi-3-mark)", fontWeight: 700 }, children: [
11696
11725
  "+",
11697
11726
  bonusPct,
@@ -11700,7 +11729,7 @@ function SurroundSound({ present = [], bonusPct = 0, bonusMax = 40, missedCost,
11700
11729
  "%"
11701
11730
  ] })
11702
11731
  ] }),
11703
- /* @__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)" } }) }),
11704
11733
  /* @__PURE__ */ jsxs81("span", { className: "fd-body-sm fd-secondary", style: { textWrap: "pretty" }, children: [
11705
11734
  present.length,
11706
11735
  " of 6 channel categories present.",
@@ -11713,7 +11742,7 @@ function SurroundSound({ present = [], bonusPct = 0, bonusMax = 40, missedCost,
11713
11742
  }
11714
11743
 
11715
11744
  // src/components/planner/Importance.tsx
11716
- import { jsx as jsx91, jsxs as jsxs82 } from "react/jsx-runtime";
11745
+ import { jsx as jsx92, jsxs as jsxs82 } from "react/jsx-runtime";
11717
11746
  var IMPORTANCE_LEVELS = [
11718
11747
  { id: "nudge", rank: 1, label: "Nudge", icon: "feather", description: "Breaks a tie, nothing more." },
11719
11748
  { id: "lean", rank: 2, label: "Lean", icon: "arrow-bend-up-right", description: "A mild preference between otherwise equal options." },
@@ -11751,16 +11780,16 @@ function ImportanceTag({ level, showLabel = true, size = "sm", className = "", d
11751
11780
  title: lvl.label + " \u2014 " + lvl.description,
11752
11781
  "aria-disabled": disabled ? "true" : void 0,
11753
11782
  children: [
11754
- /* @__PURE__ */ jsx91("i", { className: "ph ph-" + lvl.icon, "aria-hidden": "true" }),
11755
- 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 })
11756
11785
  ]
11757
11786
  }
11758
11787
  );
11759
11788
  }
11760
11789
 
11761
11790
  // src/components/planner/PreferenceMeter.tsx
11762
- import * as React62 from "react";
11763
- 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";
11764
11793
  function preferenceScore(criteria) {
11765
11794
  const earned = criteria.reduce((n, c) => n + (Number(c.earned) || 0), 0);
11766
11795
  const weight = criteria.reduce((n, c) => n + (Number(c.weight) || 0), 0);
@@ -11789,8 +11818,8 @@ function PreferenceMeter({
11789
11818
  className = ""
11790
11819
  }) {
11791
11820
  const value = score == null ? preferenceScore(criteria) : score;
11792
- const segments = React62.useMemo(() => preferenceSegments(criteria), [criteria]);
11793
- return /* @__PURE__ */ jsx92(
11821
+ const segments = React63.useMemo(() => preferenceSegments(criteria), [criteria]);
11822
+ return /* @__PURE__ */ jsx93(
11794
11823
  ScoreMeter,
11795
11824
  {
11796
11825
  score: value,
@@ -11804,20 +11833,20 @@ function PreferenceMeter({
11804
11833
  breakdownLabel: breakdownTitle,
11805
11834
  breakdown: /* @__PURE__ */ jsxs83("div", { className: "fd-prefbreak", children: [
11806
11835
  /* @__PURE__ */ jsxs83("div", { className: "fd-prefbreak-head", children: [
11807
- /* @__PURE__ */ jsx92("span", { className: "fd-label-lg", children: breakdownTitle }),
11808
- /* @__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) })
11809
11838
  ] }),
11810
- /* @__PURE__ */ jsx92("ul", { className: "fd-prefbreak-list", children: criteria.map((c) => {
11839
+ /* @__PURE__ */ jsx93("ul", { className: "fd-prefbreak-list", children: criteria.map((c) => {
11811
11840
  const pct = c.weight > 0 ? Math.round((Number(c.earned) || 0) / c.weight * 100) : 0;
11812
11841
  return /* @__PURE__ */ jsxs83("li", { className: pct === 0 ? "fd-prefbreak-item is-unmet" : "fd-prefbreak-item", children: [
11813
- /* @__PURE__ */ jsx92(ImportanceTag, { level: c.importance }),
11842
+ /* @__PURE__ */ jsx93(ImportanceTag, { level: c.importance }),
11814
11843
  /* @__PURE__ */ jsxs83("span", { className: "fd-prefbreak-text", children: [
11815
- /* @__PURE__ */ jsx92("span", { className: "fd-prefbreak-label", children: c.label }),
11816
- 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
11817
11846
  ] }),
11818
11847
  /* @__PURE__ */ jsxs83("span", { className: "fd-prefbreak-val fd-tabular", children: [
11819
11848
  Math.round(Number(c.earned) || 0),
11820
- /* @__PURE__ */ jsx92("span", { className: "fd-prefbreak-sep", children: "/" }),
11849
+ /* @__PURE__ */ jsx93("span", { className: "fd-prefbreak-sep", children: "/" }),
11821
11850
  Math.round(c.weight)
11822
11851
  ] })
11823
11852
  ] }, c.id);
@@ -11828,10 +11857,10 @@ function PreferenceMeter({
11828
11857
  }
11829
11858
 
11830
11859
  // src/components/chat/AgentChatPanel.tsx
11831
- import * as React68 from "react";
11860
+ import * as React69 from "react";
11832
11861
 
11833
11862
  // src/components/chat/chatEngine.ts
11834
- import * as React63 from "react";
11863
+ import * as React64 from "react";
11835
11864
  var CHAT_UNAVAILABLE = "chat_unavailable";
11836
11865
  var JOB_PENDING = ["queued", "running"];
11837
11866
  var JOB_SUCCESS = ["completed", "recovered"];
@@ -11885,22 +11914,22 @@ function useChatEngine(opts) {
11885
11914
  onClear,
11886
11915
  onFeedback
11887
11916
  } = opts || {};
11888
- const [status, setStatus] = React63.useState("idle");
11889
- const [threadId, setThreadId] = React63.useState(null);
11890
- const [messages, setMessages] = React63.useState([]);
11891
- const [queue, setQueue] = React63.useState([]);
11892
- const [fatal, setFatal] = React63.useState(null);
11893
- const [busy, setBusy] = React63.useState(false);
11894
- const [turnStartedAt, setTurnStartedAt] = React63.useState(null);
11895
- const listRef = React63.useRef([]);
11896
- const queueRef = React63.useRef([]);
11897
- const busyRef = React63.useRef(false);
11898
- const stoppedRef = React63.useRef(false);
11899
- const abortRef = React63.useRef(null);
11900
- const serverCount = React63.useRef(0);
11901
- const threadRef = React63.useRef(null);
11902
- const mounted = React63.useRef(true);
11903
- 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(() => {
11904
11933
  mounted.current = true;
11905
11934
  return () => {
11906
11935
  mounted.current = false;
@@ -11922,14 +11951,14 @@ function useChatEngine(opts) {
11922
11951
  }
11923
11952
  return false;
11924
11953
  };
11925
- const loadThread = React63.useCallback(async (id) => {
11954
+ const loadThread = React64.useCallback(async (id) => {
11926
11955
  const data = await apiAdapter.getThread(id);
11927
11956
  const list = [...data && data.messages || []];
11928
11957
  serverCount.current = list.length;
11929
11958
  commit(list);
11930
11959
  return list;
11931
11960
  }, [apiAdapter]);
11932
- React63.useEffect(() => {
11961
+ React64.useEffect(() => {
11933
11962
  if (!apiAdapter) {
11934
11963
  setStatus("idle");
11935
11964
  setFatal(null);
@@ -12142,7 +12171,7 @@ function useChatEngine(opts) {
12142
12171
  await dispatchTurn(turn);
12143
12172
  }
12144
12173
  }
12145
- const send = React63.useCallback((text, attachments) => {
12174
+ const send = React64.useCallback((text, attachments) => {
12146
12175
  const body = (text || "").trim();
12147
12176
  if (!body && !(attachments && attachments.length)) return;
12148
12177
  if (status === "disconnected") return;
@@ -12152,7 +12181,7 @@ function useChatEngine(opts) {
12152
12181
  stoppedRef.current = false;
12153
12182
  drain();
12154
12183
  }, [status]);
12155
- const stop = React63.useCallback(() => {
12184
+ const stop = React64.useCallback(() => {
12156
12185
  stoppedRef.current = true;
12157
12186
  const ac = abortRef.current;
12158
12187
  if (ac) {
@@ -12171,11 +12200,11 @@ function useChatEngine(opts) {
12171
12200
  store.del(STORAGE_PREFIX + threadRef.current);
12172
12201
  }
12173
12202
  }, [apiAdapter]);
12174
- const removeQueued = React63.useCallback((id) => {
12203
+ const removeQueued = React64.useCallback((id) => {
12175
12204
  queueRef.current = queueRef.current.filter((t) => t.id !== id);
12176
12205
  setQueue(queueRef.current.slice());
12177
12206
  }, []);
12178
- const retry = React63.useCallback(() => {
12207
+ const retry = React64.useCallback(() => {
12179
12208
  const list = listRef.current;
12180
12209
  let at = -1;
12181
12210
  for (let i = list.length - 1; i >= 0; i--) if (list[i].role === "user") {
@@ -12191,19 +12220,19 @@ function useChatEngine(opts) {
12191
12220
  setQueue(queueRef.current.slice());
12192
12221
  drain();
12193
12222
  }, []);
12194
- const clear = React63.useCallback(() => {
12223
+ const clear = React64.useCallback(() => {
12195
12224
  commit([]);
12196
12225
  serverCount.current = 0;
12197
12226
  queueRef.current = [];
12198
12227
  setQueue([]);
12199
12228
  onClear && onClear();
12200
12229
  }, [onClear]);
12201
- const setFeedback = React63.useCallback((id, value) => {
12230
+ const setFeedback = React64.useCallback((id, value) => {
12202
12231
  patch(id, (m) => ({ feedback: m.feedback === value ? null : value }));
12203
12232
  const msg = listRef.current.find((m) => m.id === id);
12204
12233
  onFeedback && onFeedback({ message: msg, feedback: msg ? msg.feedback : value });
12205
12234
  }, [onFeedback]);
12206
- const reload = React63.useCallback(async () => {
12235
+ const reload = React64.useCallback(async () => {
12207
12236
  if (!threadRef.current) return;
12208
12237
  setStatus("loading");
12209
12238
  try {
@@ -12241,11 +12270,11 @@ var ChatKit = {
12241
12270
  };
12242
12271
 
12243
12272
  // src/components/chat/ChatTranscript.tsx
12244
- import * as React65 from "react";
12273
+ import * as React66 from "react";
12245
12274
 
12246
12275
  // src/components/chat/ChatTurn.tsx
12247
- import * as React64 from "react";
12248
- 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";
12249
12278
  function JsonView({ value }) {
12250
12279
  let text;
12251
12280
  try {
@@ -12253,7 +12282,7 @@ function JsonView({ value }) {
12253
12282
  } catch (e) {
12254
12283
  text = String(value);
12255
12284
  }
12256
- return /* @__PURE__ */ jsx93(CodeBlock, { code: text, language: "json", collapseAfter: 18 });
12285
+ return /* @__PURE__ */ jsx94(CodeBlock, { code: text, language: "json", collapseAfter: 18 });
12257
12286
  }
12258
12287
  function PacketCard({ packet, schema, render, onApply, applied }) {
12259
12288
  if (!packet) return null;
@@ -12262,58 +12291,58 @@ function PacketCard({ packet, schema, render, onApply, applied }) {
12262
12291
  const title = s.heading || packet.type;
12263
12292
  return /* @__PURE__ */ jsxs84("section", { className: "fdc-packet" + (invalid ? " is-invalid" : ""), "aria-label": title, children: [
12264
12293
  /* @__PURE__ */ jsxs84("header", { className: "fdc-packet-head", children: [
12265
- /* @__PURE__ */ jsx93("i", { className: "ph ph-" + (s.icon || "package"), "aria-hidden": "true" }),
12266
- /* @__PURE__ */ jsx93("span", { className: "fdc-packet-title", title: truncationTitle(title), children: title }),
12267
- packet.repaired ? /* @__PURE__ */ jsx93("span", { className: "fdc-packet-badge", children: "Repaired" }) : null,
12268
- 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
12269
12298
  ] }),
12270
12299
  invalid ? /* @__PURE__ */ jsxs84("div", { className: "fdc-packet-alert", role: "alert", children: [
12271
- /* @__PURE__ */ jsx93("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
12272
- /* @__PURE__ */ jsx93("span", { children: packet.error || "This result failed validation and can\u2019t be applied." })
12273
- ] }) : /* @__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 }) }),
12274
12303
  !invalid && onApply ? /* @__PURE__ */ jsxs84("footer", { className: "fdc-packet-foot", children: [
12275
- 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", {}),
12276
12305
  /* @__PURE__ */ jsxs84("button", { type: "button", className: "fd-btn fd-btn-primary fd-btn-sm", disabled: applied, onClick: () => onApply(packet), children: [
12277
- /* @__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" }),
12278
12307
  applied ? "Applied" : s.applyLabel || "Apply"
12279
12308
  ] })
12280
12309
  ] }) : null
12281
12310
  ] });
12282
12311
  }
12283
12312
  function ThinkingBlock({ text, durationMs, streaming, defaultOpen = false }) {
12284
- const [open2, setOpen] = React64.useState(defaultOpen);
12313
+ const [open2, setOpen] = React65.useState(defaultOpen);
12285
12314
  if (!text) return null;
12286
12315
  return /* @__PURE__ */ jsxs84("div", { className: "fdc-think" + (open2 ? " is-open" : ""), children: [
12287
12316
  /* @__PURE__ */ jsxs84("button", { type: "button", className: "fdc-think-head", onClick: () => setOpen((v) => !v), "aria-expanded": open2, children: [
12288
- /* @__PURE__ */ jsx93("i", { className: "ph ph-brain", "aria-hidden": "true" }),
12289
- /* @__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" }),
12290
12319
  streaming ? /* @__PURE__ */ jsxs84("span", { className: "fdc-dots", "aria-hidden": "true", children: [
12291
- /* @__PURE__ */ jsx93("span", {}),
12292
- /* @__PURE__ */ jsx93("span", {}),
12293
- /* @__PURE__ */ jsx93("span", {})
12320
+ /* @__PURE__ */ jsx94("span", {}),
12321
+ /* @__PURE__ */ jsx94("span", {}),
12322
+ /* @__PURE__ */ jsx94("span", {})
12294
12323
  ] }) : null,
12295
- /* @__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" })
12296
12325
  ] }),
12297
- open2 ? /* @__PURE__ */ jsx93("div", { className: "fdc-think-body", children: text }) : null
12326
+ open2 ? /* @__PURE__ */ jsx94("div", { className: "fdc-think-body", children: text }) : null
12298
12327
  ] });
12299
12328
  }
12300
12329
  function Citations({ items = [], onOpen }) {
12301
- const [open2, setOpen] = React64.useState(false);
12330
+ const [open2, setOpen] = React65.useState(false);
12302
12331
  if (!items.length) return null;
12303
12332
  return /* @__PURE__ */ jsxs84("div", { className: "fdc-cites", children: [
12304
12333
  /* @__PURE__ */ jsxs84("button", { type: "button", className: "fdc-cites-head", onClick: () => setOpen((v) => !v), "aria-expanded": open2, children: [
12305
- /* @__PURE__ */ jsx93("i", { className: "ph ph-quotes", "aria-hidden": "true" }),
12334
+ /* @__PURE__ */ jsx94("i", { className: "ph ph-quotes", "aria-hidden": "true" }),
12306
12335
  /* @__PURE__ */ jsxs84("span", { children: [
12307
12336
  items.length,
12308
12337
  " source",
12309
12338
  items.length === 1 ? "" : "s"
12310
12339
  ] }),
12311
- /* @__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" })
12312
12341
  ] }),
12313
- open2 ? /* @__PURE__ */ jsx93("ol", { className: "fdc-cites-list", children: items.map((c, i) => /* @__PURE__ */ jsxs84("li", { children: [
12314
- /* @__PURE__ */ jsx93("span", { className: "fdc-cite-n fd-tabular", children: c.marker || i + 1 }),
12315
- 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" }),
12316
- 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
12317
12346
  ] }, c.id || i)) }) : null
12318
12347
  ] });
12319
12348
  }
@@ -12324,29 +12353,29 @@ function clampText(text, max) {
12324
12353
  return (at > max * 0.6 ? cut.slice(0, at) : cut).trimEnd() + "\u2026";
12325
12354
  }
12326
12355
  function MessageBody({ message: m, ctx }) {
12327
- const [expanded, setExpanded] = React64.useState(false);
12356
+ const [expanded, setExpanded] = React65.useState(false);
12328
12357
  const isUser = m.role === "user";
12329
12358
  const raw = m.text || "";
12330
12359
  const clamped = !expanded && !m.streaming ? clampText(raw, ctx.maxVisibleChars) : null;
12331
12360
  const body = clamped != null ? clamped : raw;
12332
12361
  const showMd = ctx.markdown && !isUser;
12333
12362
  return /* @__PURE__ */ jsxs84("div", { className: "fdc-body", children: [
12334
- m.thinking && ctx.showThinking ? /* @__PURE__ */ jsx93(ThinkingBlock, { text: m.thinking, durationMs: m.thinkingMs, streaming: m.streaming && !m.text }) : null,
12335
- 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,
12336
12365
  body ? /* @__PURE__ */ jsxs84("div", { className: "fdc-text" + (isUser ? " is-user" : ""), children: [
12337
- showMd ? /* @__PURE__ */ jsx93(Markdown, { source: body, headingOffset: 2, codeProps: { collapseAfter: 22 }, renderCitation: ctx.renderCitation }) : /* @__PURE__ */ jsx93("div", { className: "fdc-plain", children: body }),
12338
- 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
12339
12368
  ] }) : null,
12340
12369
  clamped != null ? /* @__PURE__ */ jsxs84("button", { type: "button", className: "fdc-more", onClick: () => setExpanded(true), children: [
12341
- /* @__PURE__ */ jsx93("i", { className: "ph ph-caret-down", "aria-hidden": "true" }),
12370
+ /* @__PURE__ */ jsx94("i", { className: "ph ph-caret-down", "aria-hidden": "true" }),
12342
12371
  "Show more",
12343
- /* @__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" })
12344
12373
  ] }) : expanded && ctx.maxVisibleChars && raw.length > ctx.maxVisibleChars ? /* @__PURE__ */ jsxs84("button", { type: "button", className: "fdc-more", onClick: () => setExpanded(false), children: [
12345
- /* @__PURE__ */ jsx93("i", { className: "ph ph-caret-up", "aria-hidden": "true" }),
12374
+ /* @__PURE__ */ jsx94("i", { className: "ph ph-caret-up", "aria-hidden": "true" }),
12346
12375
  "Show less"
12347
12376
  ] }) : null,
12348
- m.attachments && m.attachments.length ? /* @__PURE__ */ jsx93(FileGrid, { files: m.attachments, onOpen: ctx.onOpenAttachment, tiles: true, maxHeight: ctx.attachmentHeight || 220, compact: ctx.narrow }) : null,
12349
- 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(
12350
12379
  PacketCard,
12351
12380
  {
12352
12381
  packet: m.packet,
@@ -12356,12 +12385,12 @@ function MessageBody({ message: m, ctx }) {
12356
12385
  applied: ctx.appliedPackets && ctx.appliedPackets[m.id]
12357
12386
  }
12358
12387
  ) : null,
12359
- 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,
12360
12389
  m.working ? /* @__PURE__ */ jsxs84("div", { className: "fdc-working", role: "status", children: [
12361
12390
  /* @__PURE__ */ jsxs84("span", { className: "fdc-dots", "aria-hidden": "true", children: [
12362
- /* @__PURE__ */ jsx93("span", {}),
12363
- /* @__PURE__ */ jsx93("span", {}),
12364
- /* @__PURE__ */ jsx93("span", {})
12391
+ /* @__PURE__ */ jsx94("span", {}),
12392
+ /* @__PURE__ */ jsx94("span", {}),
12393
+ /* @__PURE__ */ jsx94("span", {})
12365
12394
  ] }),
12366
12395
  /* @__PURE__ */ jsxs84("span", { className: "fdc-working-label", children: [
12367
12396
  m.resumed ? "Resuming" : "Working",
@@ -12374,17 +12403,17 @@ function MessageBody({ message: m, ctx }) {
12374
12403
  m.job.detail
12375
12404
  ] }) : null
12376
12405
  ] }),
12377
- 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
12378
12407
  ] }) : null,
12379
12408
  m.stopped ? /* @__PURE__ */ jsxs84("div", { className: "fdc-stopped", children: [
12380
- /* @__PURE__ */ jsx93("i", { className: "ph ph-stop-circle", "aria-hidden": "true" }),
12409
+ /* @__PURE__ */ jsx94("i", { className: "ph ph-stop-circle", "aria-hidden": "true" }),
12381
12410
  "Stopped"
12382
12411
  ] }) : null,
12383
12412
  m.error ? /* @__PURE__ */ jsxs84("div", { className: "fdc-error", role: "alert", children: [
12384
- /* @__PURE__ */ jsx93("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
12385
- /* @__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 }),
12386
12415
  m.retryable && ctx.onRetry ? /* @__PURE__ */ jsxs84("button", { type: "button", className: "fdc-error-retry", onClick: ctx.onRetry, children: [
12387
- /* @__PURE__ */ jsx93("i", { className: "ph ph-arrow-clockwise", "aria-hidden": "true" }),
12416
+ /* @__PURE__ */ jsx94("i", { className: "ph ph-arrow-clockwise", "aria-hidden": "true" }),
12388
12417
  "Retry"
12389
12418
  ] }) : null
12390
12419
  ] }) : null
@@ -12399,14 +12428,14 @@ function RunActions({ group, ctx }) {
12399
12428
  if (!ctx.messageActions) return null;
12400
12429
  return /* @__PURE__ */ jsxs84("div", { className: "fdc-actions", role: "group", "aria-label": "Message actions", children: [
12401
12430
  /* @__PURE__ */ jsxs84("button", { type: "button", className: "fdc-act" + (copied ? " is-done" : ""), onClick: () => copy(markdownToText(text)), "aria-label": "Copy message", children: [
12402
- /* @__PURE__ */ jsx93("i", { className: "ph ph-" + (copied ? "check" : "copy"), "aria-hidden": "true" }),
12403
- /* @__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" })
12404
12433
  ] }),
12405
- 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,
12406
- 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,
12407
- isAssistant && ctx.onFeedback ? /* @__PURE__ */ jsxs84(React64.Fragment, { children: [
12408
- /* @__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" }) }),
12409
- /* @__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" }) })
12410
12439
  ] }) : null,
12411
12440
  ctx.extraActions ? ctx.extraActions(group) : null
12412
12441
  ] });
@@ -12418,20 +12447,20 @@ function ChatTurn({ group, ctx }) {
12418
12447
  const stamp = group.messages[0].timestamp;
12419
12448
  return /* @__PURE__ */ jsxs84("article", { className: "fdc-turn is-" + group.role, "aria-label": String(name) + (stamp ? " at " + formatClock(stamp) : ""), children: [
12420
12449
  /* @__PURE__ */ jsxs84("div", { className: "fdc-turn-head", children: [
12421
- 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,
12422
- /* @__PURE__ */ jsx93("span", { className: "fdc-who", children: name }),
12423
- stamp ? /* @__PURE__ */ jsx93(RelativeTime, { className: "fdc-when", value: stamp }) : null,
12424
- 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
12425
12454
  ] }),
12426
12455
  /* @__PURE__ */ jsxs84("div", { className: "fdc-turn-body", children: [
12427
- group.messages.map((m) => /* @__PURE__ */ jsx93("div", { className: "fdc-msg" + (m.pending ? " is-pending" : ""), children: /* @__PURE__ */ jsx93(MessageBody, { message: m, ctx }) }, m.id)),
12428
- /* @__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 })
12429
12458
  ] })
12430
12459
  ] });
12431
12460
  }
12432
12461
 
12433
12462
  // src/components/chat/ChatTranscript.tsx
12434
- import { jsx as jsx94, jsxs as jsxs85 } from "react/jsx-runtime";
12463
+ import { jsx as jsx95, jsxs as jsxs85 } from "react/jsx-runtime";
12435
12464
  var GROUP_WINDOW = 6e4;
12436
12465
  var STICK_PX = 100;
12437
12466
  function groupMessages(list) {
@@ -12464,25 +12493,25 @@ function dayLabel(key) {
12464
12493
  }
12465
12494
  function Suggestions({ items = [], onPick }) {
12466
12495
  if (!items.length) return null;
12467
- 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) => {
12468
12497
  const it = typeof s === "string" ? { label: s, text: s } : s;
12469
12498
  return /* @__PURE__ */ jsxs85("button", { type: "button", className: "fdc-suggest-item", onClick: () => onPick && onPick(it.text || it.label), children: [
12470
- 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,
12471
12500
  /* @__PURE__ */ jsxs85("span", { className: "fdc-suggest-text", children: [
12472
- /* @__PURE__ */ jsx94("span", { className: "fdc-suggest-label", children: it.label }),
12473
- 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
12474
12503
  ] }),
12475
- /* @__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" })
12476
12505
  ] }, it.id || i);
12477
12506
  }) });
12478
12507
  }
12479
12508
  function LoadingTurns() {
12480
- return /* @__PURE__ */ jsx94("div", { className: "fdc-skel", "aria-hidden": "true", children: [0, 1].map((i) => /* @__PURE__ */ jsxs85("div", { className: "fdc-skel-turn", children: [
12481
- /* @__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 } }),
12482
12511
  /* @__PURE__ */ jsxs85("div", { className: "fdc-skel-lines", children: [
12483
- /* @__PURE__ */ jsx94("div", { className: "fd-skel", style: { width: i ? "62%" : "44%", height: 11 } }),
12484
- /* @__PURE__ */ jsx94("div", { className: "fd-skel", style: { width: i ? "94%" : "78%", height: 11 } }),
12485
- /* @__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 } })
12486
12515
  ] })
12487
12516
  ] }, i)) });
12488
12517
  }
@@ -12499,10 +12528,10 @@ function ChatTranscript({
12499
12528
  renderEmpty,
12500
12529
  className = ""
12501
12530
  }) {
12502
- const scroller = React65.useRef(null);
12503
- const stick = React65.useRef(true);
12504
- const [pill, setPill] = React65.useState(0);
12505
- 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);
12506
12535
  const toBottom = (smooth) => {
12507
12536
  const el = scroller.current;
12508
12537
  if (!el) return;
@@ -12521,7 +12550,7 @@ function ChatTranscript({
12521
12550
  seen.current = messages.length;
12522
12551
  }
12523
12552
  };
12524
- React65.useLayoutEffect(() => {
12553
+ React66.useLayoutEffect(() => {
12525
12554
  const el = scroller.current;
12526
12555
  if (!el) return;
12527
12556
  if (stick.current) {
@@ -12529,7 +12558,7 @@ function ChatTranscript({
12529
12558
  seen.current = messages.length;
12530
12559
  } else setPill(Math.max(0, messages.length - seen.current));
12531
12560
  }, [messages]);
12532
- React65.useEffect(() => {
12561
+ React66.useEffect(() => {
12533
12562
  const el = scroller.current;
12534
12563
  const inner = el && el.firstChild;
12535
12564
  if (!el || !inner || typeof ResizeObserver === "undefined") return;
@@ -12539,38 +12568,38 @@ function ChatTranscript({
12539
12568
  ro.observe(inner);
12540
12569
  return () => ro.disconnect();
12541
12570
  }, []);
12542
- const groups = React65.useMemo(() => groupMessages(messages), [messages]);
12571
+ const groups = React66.useMemo(() => groupMessages(messages), [messages]);
12543
12572
  const empty = !messages.length && status === "ready";
12544
12573
  return /* @__PURE__ */ jsxs85("div", { className: ["fdc-scroll", className].filter(Boolean).join(" "), ref: scroller, onScroll, children: [
12545
12574
  /* @__PURE__ */ jsxs85("div", { className: "fdc-log", role: "log", "aria-label": "Conversation", children: [
12546
- status === "loading" || status === "resolving" ? /* @__PURE__ */ jsx94(LoadingTurns, {}) : null,
12575
+ status === "loading" || status === "resolving" ? /* @__PURE__ */ jsx95(LoadingTurns, {}) : null,
12547
12576
  status === "disconnected" ? /* @__PURE__ */ jsxs85("div", { className: "fdc-dead", children: [
12548
- /* @__PURE__ */ jsx94("span", { className: "fdc-dead-icon", children: /* @__PURE__ */ jsx94("i", { className: "ph ph-plugs", "aria-hidden": "true" }) }),
12549
- /* @__PURE__ */ jsx94("h3", { className: "fdc-dead-title", children: ctx.deadTitle || "The assistant isn\u2019t reachable" }),
12550
- /* @__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." }),
12551
12580
  ctx.onReconnect ? /* @__PURE__ */ jsxs85("button", { type: "button", className: "fd-btn fd-btn-secondary fd-btn-sm", onClick: ctx.onReconnect, children: [
12552
- /* @__PURE__ */ jsx94("i", { className: "ph ph-arrow-clockwise", "aria-hidden": "true" }),
12581
+ /* @__PURE__ */ jsx95("i", { className: "ph ph-arrow-clockwise", "aria-hidden": "true" }),
12553
12582
  "Try again"
12554
12583
  ] }) : null
12555
12584
  ] }) : null,
12556
12585
  empty ? renderEmpty ? renderEmpty() : /* @__PURE__ */ jsxs85("div", { className: "fdc-empty", children: [
12557
- /* @__PURE__ */ jsx94("span", { className: "fdc-empty-icon", children: /* @__PURE__ */ jsx94("i", { className: "ph ph-" + emptyIcon, "aria-hidden": "true" }) }),
12558
- /* @__PURE__ */ jsx94("h3", { className: "fdc-empty-title", children: emptyTitle }),
12559
- emptyDescription ? /* @__PURE__ */ jsx94("p", { className: "fdc-empty-body", children: emptyDescription }) : null,
12560
- /* @__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 })
12561
12590
  ] }) : null,
12562
12591
  groups.map((g, i) => {
12563
12592
  const prev = groups[i - 1];
12564
12593
  const k = dayKey(g.messages[0].timestamp);
12565
12594
  const showDay = !!k && (!prev || dayKey(prev.messages[0].timestamp) !== k);
12566
- return /* @__PURE__ */ jsxs85(React65.Fragment, { children: [
12567
- showDay ? /* @__PURE__ */ jsx94("div", { className: "fdc-day", children: /* @__PURE__ */ jsx94("span", { children: dayLabel(k) }) }) : null,
12568
- /* @__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 })
12569
12598
  ] }, g.key || i);
12570
12599
  })
12571
12600
  ] }),
12572
12601
  pill ? /* @__PURE__ */ jsxs85("button", { type: "button", className: "fdc-pill", onClick: () => toBottom(true), children: [
12573
- /* @__PURE__ */ jsx94("i", { className: "ph ph-arrow-down", "aria-hidden": "true" }),
12602
+ /* @__PURE__ */ jsx95("i", { className: "ph ph-arrow-down", "aria-hidden": "true" }),
12574
12603
  pill,
12575
12604
  " new message",
12576
12605
  pill === 1 ? "" : "s"
@@ -12580,8 +12609,8 @@ function ChatTranscript({
12580
12609
  var TranscriptKit = { groupMessages };
12581
12610
 
12582
12611
  // src/components/chat/ChatComposer.tsx
12583
- import * as React66 from "react";
12584
- 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";
12585
12614
  function ChatComposer({
12586
12615
  onSubmit,
12587
12616
  onStop,
@@ -12608,17 +12637,17 @@ function ChatComposer({
12608
12637
  onReject,
12609
12638
  onOpenAttachment
12610
12639
  }) {
12611
- const [text, setText] = React66.useState(draft || "");
12612
- const [trigger, setTrigger] = React66.useState(null);
12613
- const [mentionItems, setMentionItems] = React66.useState([]);
12614
- const [listening, setListening] = React66.useState(false);
12615
- const [notice, setNotice] = React66.useState(null);
12616
- const editor = React66.useRef(null);
12617
- const wrap = React66.useRef(null);
12618
- 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);
12619
12648
  const staged = useStagedFiles(fileUploadHandler, { onError: () => {
12620
12649
  } });
12621
- React66.useEffect(() => {
12650
+ React67.useEffect(() => {
12622
12651
  if (draft != null && draft !== text) setText(draft);
12623
12652
  }, [draft]);
12624
12653
  const change = (v) => {
@@ -12654,7 +12683,7 @@ function ChatComposer({
12654
12683
  e.preventDefault();
12655
12684
  staged.add(found.files);
12656
12685
  };
12657
- React66.useEffect(() => {
12686
+ React67.useEffect(() => {
12658
12687
  if (!trigger || trigger.type !== "mention" || !mentionSources) {
12659
12688
  setMentionItems([]);
12660
12689
  return;
@@ -12672,7 +12701,7 @@ function ChatComposer({
12672
12701
  const q = (trigger.query || "").toLowerCase();
12673
12702
  setMentionItems(mentionSources.filter((m) => !q || (m.label + " " + (m.description || "")).toLowerCase().includes(q)));
12674
12703
  }, [trigger, mentionSources]);
12675
- const slashItems = React66.useMemo(() => {
12704
+ const slashItems = React67.useMemo(() => {
12676
12705
  if (!trigger || trigger.type !== "slash" || !slashCommands) return [];
12677
12706
  const q = (trigger.query || "").toLowerCase();
12678
12707
  return slashCommands.filter((c) => !q || (c.id + " " + c.label + " " + (c.description || "")).toLowerCase().includes(q));
@@ -12686,7 +12715,7 @@ function ChatComposer({
12686
12715
  description: it.description,
12687
12716
  icon: it.icon,
12688
12717
  meta: mention.meta,
12689
- 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,
12690
12719
  onSelect: () => {
12691
12720
  const insert = trigger.type === "slash" ? slash.immediate ? "/" + slash.id : "/" + slash.id + " " : "@" + (mention.value || mention.label) + " ";
12692
12721
  editor.current && editor.current.replaceRange(trigger.from, trigger.to, insert);
@@ -12746,13 +12775,13 @@ function ChatComposer({
12746
12775
  };
12747
12776
  };
12748
12777
  return /* @__PURE__ */ jsxs86("div", { className: "fdc-composer" + (disabled ? " is-disabled" : "") + (narrow ? " is-narrow" : ""), children: [
12749
- queue.length ? /* @__PURE__ */ jsx95("div", { className: "fdc-queue", "aria-label": "Queued messages", children: queue.map((q) => /* @__PURE__ */ jsxs86("div", { className: "fdc-queue-row", children: [
12750
- /* @__PURE__ */ jsx95("i", { className: "ph ph-clock-countdown", "aria-hidden": "true" }),
12751
- /* @__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)" : "") }),
12752
- 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
12753
12782
  ] }, q.id)) }) : null,
12754
12783
  sessionBar,
12755
- /* @__PURE__ */ jsx95(
12784
+ /* @__PURE__ */ jsx96(
12756
12785
  Dropzone,
12757
12786
  {
12758
12787
  className: "fdc-field",
@@ -12767,8 +12796,8 @@ function ChatComposer({
12767
12796
  label: "Drop to attach",
12768
12797
  hint: acceptFiles ? acceptFiles.replace(/,/g, " \xB7 ") : void 0,
12769
12798
  children: /* @__PURE__ */ jsxs86("div", { ref: wrap, className: "fdc-field-inner", children: [
12770
- 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,
12771
- /* @__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(
12772
12801
  MarkdownEditor,
12773
12802
  {
12774
12803
  ref: editor,
@@ -12788,32 +12817,32 @@ function ChatComposer({
12788
12817
  }
12789
12818
  ),
12790
12819
  /* @__PURE__ */ jsxs86("div", { className: "fdc-tools", children: [
12791
- fileUploadHandler ? /* @__PURE__ */ jsx95(FilePickButton, { onFiles: staged.add, onReject: (r) => flash(r[0].message), accept: acceptFiles, maxFileSize, label: "Attach files", icon: "plus" }) : null,
12792
- 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,
12793
12822
  toolbarExtras,
12794
- /* @__PURE__ */ jsx95("span", { className: "fdc-tools-gap" }),
12823
+ /* @__PURE__ */ jsx96("span", { className: "fdc-tools-gap" }),
12795
12824
  maxLength && text.length > maxLength * 0.6 ? /* @__PURE__ */ jsxs86("span", { className: "fdc-count fd-tabular" + (text.length > maxLength * 0.95 ? " is-hot" : ""), children: [
12796
12825
  text.length,
12797
12826
  "/",
12798
12827
  maxLength
12799
12828
  ] }) : null,
12800
12829
  busy ? /* @__PURE__ */ jsxs86("button", { type: "button", className: "fdc-stop", onClick: onStop, "aria-label": "Stop generating", children: [
12801
- /* @__PURE__ */ jsx95("i", { className: "ph ph-stop-circle", "aria-hidden": "true" }),
12802
- /* @__PURE__ */ jsx95("span", { children: "Stop" })
12830
+ /* @__PURE__ */ jsx96("i", { className: "ph ph-stop-circle", "aria-hidden": "true" }),
12831
+ /* @__PURE__ */ jsx96("span", { children: "Stop" })
12803
12832
  ] }) : /* @__PURE__ */ jsxs86("button", { type: "button", className: "fdc-send", onClick: submit, disabled: !canSend, "aria-label": "Send message", children: [
12804
- /* @__PURE__ */ jsx95("i", { className: "ph ph-paper-plane-right", "aria-hidden": "true" }),
12805
- /* @__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" })
12806
12835
  ] })
12807
12836
  ] })
12808
12837
  ] })
12809
12838
  }
12810
12839
  ),
12811
12840
  notice ? /* @__PURE__ */ jsxs86("div", { className: "fdc-notice", role: "status", children: [
12812
- /* @__PURE__ */ jsx95("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
12841
+ /* @__PURE__ */ jsx96("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
12813
12842
  notice
12814
12843
  ] }) : null,
12815
- hint && !notice ? /* @__PURE__ */ jsx95("div", { className: "fdc-hint", children: hint }) : null,
12816
- /* @__PURE__ */ jsx95(
12844
+ hint && !notice ? /* @__PURE__ */ jsx96("div", { className: "fdc-hint", children: hint }) : null,
12845
+ /* @__PURE__ */ jsx96(
12817
12846
  Popover,
12818
12847
  {
12819
12848
  open: menuOpen,
@@ -12827,12 +12856,12 @@ function ChatComposer({
12827
12856
  returnFocus: false,
12828
12857
  closeOnOutside: true,
12829
12858
  label: trigger && trigger.type === "slash" ? "Commands" : "Mentions",
12830
- children: /* @__PURE__ */ jsx95(
12859
+ children: /* @__PURE__ */ jsx96(
12831
12860
  Menu,
12832
12861
  {
12833
12862
  items: menuItems,
12834
12863
  autoFocus: false,
12835
- 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" }),
12836
12865
  onClose: () => setTrigger(null)
12837
12866
  }
12838
12867
  )
@@ -12842,12 +12871,12 @@ function ChatComposer({
12842
12871
  }
12843
12872
 
12844
12873
  // src/components/chat/ChatSessionBar.tsx
12845
- import * as React67 from "react";
12846
- 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";
12847
12876
  var compact2 = meterFormats.compact;
12848
12877
  function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extras }) {
12849
- const [open2, setOpen] = React67.useState(false);
12850
- const anchor = React67.useRef(null);
12878
+ const [open2, setOpen] = React68.useState(false);
12879
+ const anchor = React68.useRef(null);
12851
12880
  const stats = sessionStats || null;
12852
12881
  const cu = contextUsage || null;
12853
12882
  const limits = usageLimits || null;
@@ -12862,7 +12891,7 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
12862
12891
  if (stats && stats.runningTasks) bits.push(stats.runningTasks + " running task" + (stats.runningTasks === 1 ? "" : "s"));
12863
12892
  if (cu) bits.push(pct + "% context");
12864
12893
  const expandable = !!(cu || limits);
12865
- return /* @__PURE__ */ jsxs87(React67.Fragment, { children: [
12894
+ return /* @__PURE__ */ jsxs87(React68.Fragment, { children: [
12866
12895
  /* @__PURE__ */ jsxs87("div", { className: "fdc-bar", children: [
12867
12896
  /* @__PURE__ */ jsxs87(
12868
12897
  "button",
@@ -12875,15 +12904,15 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
12875
12904
  "aria-expanded": expandable ? open2 : void 0,
12876
12905
  "aria-label": expandable ? "Usage details" : void 0,
12877
12906
  children: [
12878
- cu ? /* @__PURE__ */ jsx96("span", { className: "fdc-bar-mini", "aria-hidden": "true", children: /* @__PURE__ */ jsx96(SegmentedMeter, { total, segments: cu.segments, height: 4, showTotal: false }) }) : null,
12879
- /* @__PURE__ */ jsx96("span", { className: "fdc-bar-text", title: truncationTitle(bits.join(" \xB7 ")), children: bits.join(" \xB7 ") }),
12880
- 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
12881
12910
  ]
12882
12911
  }
12883
12912
  ),
12884
12913
  extras
12885
12914
  ] }),
12886
- /* @__PURE__ */ jsx96(
12915
+ /* @__PURE__ */ jsx97(
12887
12916
  Popover,
12888
12917
  {
12889
12918
  open: open2,
@@ -12898,11 +12927,11 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
12898
12927
  setOpen(false);
12899
12928
  onClear();
12900
12929
  }, children: [
12901
- /* @__PURE__ */ jsx96("i", { className: "ph ph-trash", "aria-hidden": "true" }),
12930
+ /* @__PURE__ */ jsx97("i", { className: "ph ph-trash", "aria-hidden": "true" }),
12902
12931
  "Clear conversation"
12903
12932
  ] }) : void 0,
12904
12933
  children: /* @__PURE__ */ jsxs87("div", { className: "fdc-usage", children: [
12905
- cu ? /* @__PURE__ */ jsx96("section", { className: "fdc-usage-sec", children: /* @__PURE__ */ jsx96(
12934
+ cu ? /* @__PURE__ */ jsx97("section", { className: "fdc-usage-sec", children: /* @__PURE__ */ jsx97(
12906
12935
  SegmentedMeter,
12907
12936
  {
12908
12937
  total,
@@ -12915,8 +12944,8 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
12915
12944
  }
12916
12945
  ) }) : null,
12917
12946
  limits && limits.length ? /* @__PURE__ */ jsxs87("section", { className: "fdc-usage-sec", children: [
12918
- /* @__PURE__ */ jsx96("h4", { className: "fdc-usage-h", children: "Usage limits" }),
12919
- /* @__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(
12920
12949
  QuotaRow,
12921
12950
  {
12922
12951
  label: l.label,
@@ -12928,23 +12957,23 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
12928
12957
  ] }) : null,
12929
12958
  stats ? /* @__PURE__ */ jsxs87("section", { className: "fdc-usage-sec fdc-usage-stats", children: [
12930
12959
  stats.elapsedMs ? /* @__PURE__ */ jsxs87("div", { children: [
12931
- /* @__PURE__ */ jsx96("span", { children: "Session" }),
12932
- /* @__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) })
12933
12962
  ] }) : null,
12934
12963
  stats.tokens ? /* @__PURE__ */ jsxs87("div", { children: [
12935
- /* @__PURE__ */ jsx96("span", { children: "Tokens" }),
12936
- /* @__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() })
12937
12966
  ] }) : null,
12938
12967
  stats.costUsd != null ? /* @__PURE__ */ jsxs87("div", { children: [
12939
- /* @__PURE__ */ jsx96("span", { children: "Cost" }),
12968
+ /* @__PURE__ */ jsx97("span", { children: "Cost" }),
12940
12969
  /* @__PURE__ */ jsxs87("b", { className: "fd-tabular", children: [
12941
12970
  "$",
12942
12971
  Number(stats.costUsd).toFixed(3)
12943
12972
  ] })
12944
12973
  ] }) : null,
12945
12974
  stats.turns ? /* @__PURE__ */ jsxs87("div", { children: [
12946
- /* @__PURE__ */ jsx96("span", { children: "Turns" }),
12947
- /* @__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 })
12948
12977
  ] }) : null
12949
12978
  ] }) : null
12950
12979
  ] })
@@ -12983,7 +13012,7 @@ function ModelControls({
12983
13012
  disabled: m.disabled,
12984
13013
  checked: m.id === (current2 && current2.id),
12985
13014
  meta: m.meta,
12986
- 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,
12987
13016
  onSelect: () => onModelChange && onModelChange(m.id)
12988
13017
  });
12989
13018
  const items = [{ kind: "section", label: "Models" }].concat(flat.map(item));
@@ -12997,14 +13026,14 @@ function ModelControls({
12997
13026
  items.push({
12998
13027
  kind: "custom",
12999
13028
  render: () => /* @__PURE__ */ jsxs87("label", { className: "fdc-switchrow", children: [
13000
- /* @__PURE__ */ jsx96("span", { children: fastModeLabel }),
13001
- /* @__PURE__ */ jsx96("input", { type: "checkbox", className: "fd-sr", checked: !!fastMode, onChange: (e) => onFastModeChange(e.target.checked) }),
13002
- /* @__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" }) })
13003
13032
  ] })
13004
13033
  });
13005
13034
  }
13006
- return /* @__PURE__ */ jsxs87(React67.Fragment, { children: [
13007
- /* @__PURE__ */ jsx96(
13035
+ return /* @__PURE__ */ jsxs87(React68.Fragment, { children: [
13036
+ /* @__PURE__ */ jsx97(
13008
13037
  MenuButton,
13009
13038
  {
13010
13039
  items,
@@ -13015,7 +13044,7 @@ function ModelControls({
13015
13044
  title: "Choose a model"
13016
13045
  }
13017
13046
  ),
13018
- effortLevels && effortLevels.length ? /* @__PURE__ */ jsx96(
13047
+ effortLevels && effortLevels.length ? /* @__PURE__ */ jsx97(
13019
13048
  MenuButton,
13020
13049
  {
13021
13050
  placement: "top-end",
@@ -13036,7 +13065,7 @@ function ModelControls({
13036
13065
  }
13037
13066
 
13038
13067
  // src/components/chat/AgentChatPanel.tsx
13039
- import { jsx as jsx97, jsxs as jsxs88 } from "react/jsx-runtime";
13068
+ import { jsx as jsx98, jsxs as jsxs88 } from "react/jsx-runtime";
13040
13069
  var SURFACES = { sidebar: "is-sidebar", inline: "is-inline", page: "is-page", modal: "is-modal", sheet: "is-sheet" };
13041
13070
  function AgentChatPanel({
13042
13071
  /* required */
@@ -13120,11 +13149,11 @@ function AgentChatPanel({
13120
13149
  onFeedback,
13121
13150
  onEditMessage
13122
13151
  }) {
13123
- const [panelWidth, setPanelWidth] = React68.useState(width);
13124
- const [applied, setApplied] = React68.useState({});
13125
- const [draft, setDraft] = React68.useState("");
13126
- const dragging = React68.useRef(null);
13127
- 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]);
13128
13157
  const engine = useChatEngine({
13129
13158
  contextType,
13130
13159
  contextId,
@@ -13190,7 +13219,7 @@ function AgentChatPanel({
13190
13219
  onReconnect: engine.reload,
13191
13220
  deadTitle: "The assistant isn\u2019t reachable"
13192
13221
  };
13193
- const sessionBar = /* @__PURE__ */ jsx97(
13222
+ const sessionBar = /* @__PURE__ */ jsx98(
13194
13223
  ChatSessionBar,
13195
13224
  {
13196
13225
  sessionStats,
@@ -13199,7 +13228,7 @@ function AgentChatPanel({
13199
13228
  onClear: engine.visible.length ? engine.clear : void 0
13200
13229
  }
13201
13230
  );
13202
- const modelControls = /* @__PURE__ */ jsx97(
13231
+ const modelControls = /* @__PURE__ */ jsx98(
13203
13232
  ModelControls,
13204
13233
  {
13205
13234
  models,
@@ -13214,7 +13243,7 @@ function AgentChatPanel({
13214
13243
  narrow
13215
13244
  }
13216
13245
  );
13217
- const threadMenu = threads && threads.length ? /* @__PURE__ */ jsx97(
13246
+ const threadMenu = threads && threads.length ? /* @__PURE__ */ jsx98(
13218
13247
  MenuButton,
13219
13248
  {
13220
13249
  variant: "ghost",
@@ -13252,7 +13281,7 @@ function AgentChatPanel({
13252
13281
  },
13253
13282
  "aria-label": title,
13254
13283
  children: [
13255
- surface === "sidebar" && resizable ? /* @__PURE__ */ jsx97(
13284
+ surface === "sidebar" && resizable ? /* @__PURE__ */ jsx98(
13256
13285
  "div",
13257
13286
  {
13258
13287
  className: "fdc-grip",
@@ -13268,19 +13297,19 @@ function AgentChatPanel({
13268
13297
  }
13269
13298
  ) : null,
13270
13299
  showHeader ? /* @__PURE__ */ jsxs88("header", { className: "fdc-head", children: [
13271
- /* @__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 }) }),
13272
13301
  /* @__PURE__ */ jsxs88("span", { className: "fdc-head-titles", children: [
13273
- /* @__PURE__ */ jsx97("span", { className: "fdc-head-title", title: truncationTitle(title), children: title }),
13274
- 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
13275
13304
  ] }),
13276
13305
  /* @__PURE__ */ jsxs88("span", { className: "fdc-head-acts", children: [
13277
13306
  headerActions,
13278
13307
  threadMenu,
13279
- 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,
13280
- 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
13281
13310
  ] })
13282
13311
  ] }) : null,
13283
- /* @__PURE__ */ jsx97(
13312
+ /* @__PURE__ */ jsx98(
13284
13313
  ChatTranscript,
13285
13314
  {
13286
13315
  messages: engine.visible,
@@ -13295,7 +13324,7 @@ function AgentChatPanel({
13295
13324
  renderEmpty
13296
13325
  }
13297
13326
  ),
13298
- /* @__PURE__ */ jsx97(
13327
+ /* @__PURE__ */ jsx98(
13299
13328
  ChatComposer,
13300
13329
  {
13301
13330
  onSubmit: (text, atts) => engine.send(text, atts),
@@ -13328,8 +13357,8 @@ function AgentChatPanel({
13328
13357
  }
13329
13358
 
13330
13359
  // src/components/files/FileViewer.tsx
13331
- import * as React69 from "react";
13332
- 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";
13333
13362
  function previewKindOf(file) {
13334
13363
  const mime = (file.mime || "").toLowerCase();
13335
13364
  const ext = extensionOf(file.name || "");
@@ -13385,13 +13414,13 @@ function parseDelimited(text, delimiter) {
13385
13414
  return rows;
13386
13415
  }
13387
13416
  function usePreview(file, kind, resolveUrl) {
13388
- const [state, setState] = React69.useState({ status: "loading" });
13389
- const [attempt, setAttempt] = React69.useState(0);
13390
- const resolveRef = React69.useRef(resolveUrl);
13391
- 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(() => {
13392
13421
  resolveRef.current = resolveUrl;
13393
13422
  }, [resolveUrl]);
13394
- React69.useEffect(() => {
13423
+ React70.useEffect(() => {
13395
13424
  if (kind === "none") {
13396
13425
  setState({ status: "ready" });
13397
13426
  return;
@@ -13421,19 +13450,19 @@ function usePreview(file, kind, resolveUrl) {
13421
13450
  if (ac) ac.abort();
13422
13451
  };
13423
13452
  }, [file.id, kind, attempt]);
13424
- return { ...state, retry: React69.useCallback(() => setAttempt((a) => a + 1), []) };
13453
+ return { ...state, retry: React70.useCallback(() => setAttempt((a) => a + 1), []) };
13425
13454
  }
13426
13455
  function PreviewBody({ file, kind, state }) {
13427
- if (kind === "image") return /* @__PURE__ */ jsx98("img", { className: "fd-fv-image", src: state.url, alt: file.name || "Preview" });
13428
- if (kind === "pdf") return /* @__PURE__ */ jsx98("iframe", { className: "fd-fv-pdf", src: state.url, title: file.name || "PDF preview" });
13429
- 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 || "" });
13430
13459
  if (kind === "json") {
13431
13460
  let pretty = state.text || "";
13432
13461
  try {
13433
13462
  pretty = JSON.stringify(JSON.parse(pretty), null, 2);
13434
13463
  } catch {
13435
13464
  }
13436
- return /* @__PURE__ */ jsx98(CodeBlock, { code: pretty, language: "json" });
13465
+ return /* @__PURE__ */ jsx99(CodeBlock, { code: pretty, language: "json" });
13437
13466
  }
13438
13467
  if (kind === "csv") {
13439
13468
  const tsv = extensionOf(file.name || "") === "tsv" || (file.mime || "").toLowerCase().includes("tab-separated");
@@ -13443,8 +13472,8 @@ function PreviewBody({ file, kind, state }) {
13443
13472
  const shown = dataRows.slice(0, FILE_VIEWER_CSV_ROW_LIMIT);
13444
13473
  return /* @__PURE__ */ jsxs89("div", { className: "fd-fv-csv", children: [
13445
13474
  /* @__PURE__ */ jsxs89("table", { className: "fd-fv-csv-table", children: [
13446
- /* @__PURE__ */ jsx98("thead", { children: /* @__PURE__ */ jsx98("tr", { children: head.map((c, i) => /* @__PURE__ */ jsx98("th", { children: c }, i)) }) }),
13447
- /* @__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)) })
13448
13477
  ] }),
13449
13478
  dataRows.length > FILE_VIEWER_CSV_ROW_LIMIT ? /* @__PURE__ */ jsxs89("p", { className: "fd-fv-csv-note fd-body-sm fd-muted", children: [
13450
13479
  "Showing the first ",
@@ -13455,10 +13484,10 @@ function PreviewBody({ file, kind, state }) {
13455
13484
  ] }) : null
13456
13485
  ] });
13457
13486
  }
13458
- 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 });
13459
13488
  return /* @__PURE__ */ jsxs89("div", { className: "fd-fv-fallback", children: [
13460
- /* @__PURE__ */ jsx98("span", { className: "fd-fv-fallback-icon", "aria-hidden": "true", children: /* @__PURE__ */ jsx98("i", { className: "ph ph-" + iconForMime(file.mime, file.name) }) }),
13461
- /* @__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" }),
13462
13491
  /* @__PURE__ */ jsxs89("span", { className: "fd-fv-fallback-meta", children: [
13463
13492
  file.mime || "Unknown type",
13464
13493
  file.size ? " \xB7 " + formatBytes(file.size) : ""
@@ -13466,13 +13495,13 @@ function PreviewBody({ file, kind, state }) {
13466
13495
  ] });
13467
13496
  }
13468
13497
  function FileViewer({ file, resolveUrl, sidePanel, sidePanelLabel = "Details", onClose, actions, className = "" }) {
13469
- const kind = React69.useMemo(() => previewKindOf(file), [file]);
13498
+ const kind = React70.useMemo(() => previewKindOf(file), [file]);
13470
13499
  const preview = usePreview(file, kind, resolveUrl);
13471
- const [tab, setTab] = React69.useState("preview");
13472
- const [downloading, setDownloading] = React69.useState(false);
13473
- 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);
13474
13503
  const hasSide = sidePanel != null;
13475
- React69.useEffect(() => {
13504
+ React70.useEffect(() => {
13476
13505
  setTab("preview");
13477
13506
  }, [file.id]);
13478
13507
  const download = () => {
@@ -13495,9 +13524,9 @@ function FileViewer({ file, resolveUrl, sidePanel, sidePanelLabel = "Details", o
13495
13524
  "aria-label": file.name || "File",
13496
13525
  children: [
13497
13526
  /* @__PURE__ */ jsxs89("header", { className: "fd-fv-head", children: [
13498
- /* @__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) }) }),
13499
13528
  /* @__PURE__ */ jsxs89("span", { className: "fd-fv-head-titles", children: [
13500
- /* @__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 }),
13501
13530
  /* @__PURE__ */ jsxs89("span", { className: "fd-fv-head-meta", children: [
13502
13531
  file.mime || "Unknown type",
13503
13532
  file.size ? " \xB7 " + formatBytes(file.size) : ""
@@ -13505,12 +13534,12 @@ function FileViewer({ file, resolveUrl, sidePanel, sidePanelLabel = "Details", o
13505
13534
  ] }),
13506
13535
  /* @__PURE__ */ jsxs89("span", { className: "fd-fv-head-actions", children: [
13507
13536
  actions,
13508
- /* @__PURE__ */ jsx98(Button, { variant: "secondary", size: "sm", icon: "download-simple", loading: downloading, onClick: download, children: "Download" }),
13509
- 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
13510
13539
  ] })
13511
13540
  ] }),
13512
- downloadError ? /* @__PURE__ */ jsx98("div", { className: "fd-fv-download-error", role: "alert", children: downloadError }) : null,
13513
- hasSide ? /* @__PURE__ */ jsx98(
13541
+ downloadError ? /* @__PURE__ */ jsx99("div", { className: "fd-fv-download-error", role: "alert", children: downloadError }) : null,
13542
+ hasSide ? /* @__PURE__ */ jsx99(
13514
13543
  Tabs,
13515
13544
  {
13516
13545
  className: "fd-fv-tabs",
@@ -13520,18 +13549,18 @@ function FileViewer({ file, resolveUrl, sidePanel, sidePanelLabel = "Details", o
13520
13549
  }
13521
13550
  ) : null,
13522
13551
  /* @__PURE__ */ jsxs89("div", { className: "fd-fv-body", children: [
13523
- /* @__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(
13524
13553
  LoadingRegion,
13525
13554
  {
13526
13555
  state: preview.status === "loading" ? "loading" : preview.status === "error" ? "error" : "ready",
13527
13556
  error: preview.error,
13528
13557
  label: "Loading preview of " + (file.name || "file"),
13529
13558
  onRetry: preview.status === "error" ? preview.retry : void 0,
13530
- skeleton: /* @__PURE__ */ jsx98(Skeleton, { shape: "card", h: 220 }),
13531
- 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 })
13532
13561
  }
13533
13562
  ) }),
13534
- 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
13535
13564
  ] })
13536
13565
  ]
13537
13566
  }
@@ -13539,8 +13568,8 @@ function FileViewer({ file, resolveUrl, sidePanel, sidePanelLabel = "Details", o
13539
13568
  }
13540
13569
 
13541
13570
  // src/components/files/FileBrowser.tsx
13542
- import * as React70 from "react";
13543
- 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";
13544
13573
  function childrenOf(folders, parentId) {
13545
13574
  return folders.filter((f) => f.parentId === parentId).sort((a, b) => a.name.localeCompare(b.name));
13546
13575
  }
@@ -13613,7 +13642,7 @@ function FolderPickerMenu({
13613
13642
  const panel = useInlinePanel();
13614
13643
  const { open: open2, setOpen, ref } = panel;
13615
13644
  return /* @__PURE__ */ jsxs90("span", { className: "fd-fb-menu-anchor", ref, children: [
13616
- /* @__PURE__ */ jsx99(
13645
+ /* @__PURE__ */ jsx100(
13617
13646
  IconButton,
13618
13647
  {
13619
13648
  icon: "arrows-out-cardinal",
@@ -13625,8 +13654,8 @@ function FolderPickerMenu({
13625
13654
  onClick: () => setOpen((v) => !v)
13626
13655
  }
13627
13656
  ),
13628
- /* @__PURE__ */ jsx99(InlinePanelSurface, { panel, align: "right", offset: 4, width: 220, maxHeight: 280, role: "menu", label, children: /* @__PURE__ */ jsxs90("div", { className: "fd-fb-menu", children: [
13629
- /* @__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" }),
13630
13659
  destinations.map((d) => /* @__PURE__ */ jsxs90(
13631
13660
  "button",
13632
13661
  {
@@ -13639,7 +13668,7 @@ function FolderPickerMenu({
13639
13668
  setOpen(false);
13640
13669
  },
13641
13670
  children: [
13642
- /* @__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" }),
13643
13672
  d.name
13644
13673
  ]
13645
13674
  },
@@ -13649,8 +13678,8 @@ function FolderPickerMenu({
13649
13678
  ] });
13650
13679
  }
13651
13680
  function RowShell({ icon, name, meta, onOpen, draggableId, isDropTarget, onDropPayload, actions, className = "" }) {
13652
- const [over, setOver] = React70.useState(false);
13653
- const dragCounter = React70.useRef(0);
13681
+ const [over, setOver] = React71.useState(false);
13682
+ const dragCounter = React71.useRef(0);
13654
13683
  const dropHandlers = isDropTarget ? {
13655
13684
  onDragEnter: (e) => {
13656
13685
  if (!hasInternalPayload(e)) return;
@@ -13685,26 +13714,26 @@ function RowShell({ icon, name, meta, onOpen, draggableId, isDropTarget, onDropP
13685
13714
  draggable: !!draggableId,
13686
13715
  onDragStart: draggableId ? (e) => writeDragPayload(e, draggableId) : void 0,
13687
13716
  children: [
13688
- /* @__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 }) }),
13689
13718
  /* @__PURE__ */ jsxs90("span", { className: "fd-fb-row-text", children: [
13690
- /* @__PURE__ */ jsx99("span", { className: "fd-fb-row-name", title: name, children: name }),
13691
- 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
13692
13721
  ] })
13693
13722
  ]
13694
13723
  }
13695
13724
  ),
13696
- 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
13697
13726
  ] });
13698
13727
  }
13699
13728
  function TreeNode({ folder, depth, folders, currentFolderId, onNavigate, onMoveInto, canMove }) {
13700
13729
  const kids = childrenOf(folders, folder.id);
13701
- const [expanded, setExpanded] = React70.useState(() => currentFolderId != null && isSelfOrDescendant(folders, folder.id, currentFolderId));
13702
- React70.useEffect(() => {
13730
+ const [expanded, setExpanded] = React71.useState(() => currentFolderId != null && isSelfOrDescendant(folders, folder.id, currentFolderId));
13731
+ React71.useEffect(() => {
13703
13732
  if (currentFolderId != null && isSelfOrDescendant(folders, folder.id, currentFolderId)) setExpanded(true);
13704
13733
  }, [currentFolderId, folder.id, folders]);
13705
13734
  const isCurrent = folder.id === currentFolderId;
13706
13735
  return /* @__PURE__ */ jsxs90("div", { className: "fd-fb-tree-node", children: [
13707
- /* @__PURE__ */ jsx99(
13736
+ /* @__PURE__ */ jsx100(
13708
13737
  RowShell,
13709
13738
  {
13710
13739
  icon: folder.id === currentFolderId ? "folder-open" : "folder-simple",
@@ -13714,7 +13743,7 @@ function TreeNode({ folder, depth, folders, currentFolderId, onNavigate, onMoveI
13714
13743
  isDropTarget: canMove,
13715
13744
  onDropPayload: (payload) => onMoveInto(payload, folder.id),
13716
13745
  className: ["fd-fb-tree-row", isCurrent ? "is-current" : ""].filter(Boolean).join(" "),
13717
- actions: kids.length ? /* @__PURE__ */ jsx99(
13746
+ actions: kids.length ? /* @__PURE__ */ jsx100(
13718
13747
  IconButton,
13719
13748
  {
13720
13749
  icon: expanded ? "caret-down" : "caret-right",
@@ -13726,7 +13755,7 @@ function TreeNode({ folder, depth, folders, currentFolderId, onNavigate, onMoveI
13726
13755
  ) : void 0
13727
13756
  }
13728
13757
  ),
13729
- 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(
13730
13759
  TreeNode,
13731
13760
  {
13732
13761
  folder: k,
@@ -13765,15 +13794,15 @@ function FileBrowser({
13765
13794
  const canUpload = perm.canUpload !== false && !!onUpload;
13766
13795
  const canRemoveFile = perm.canRemoveFile !== false && !!onRemoveFile;
13767
13796
  const canDeleteFolder = perm.canDeleteFolder !== false && !!onDeleteFolder;
13768
- const [createOpen, setCreateOpen] = React70.useState(false);
13769
- const [createName, setCreateName] = React70.useState("");
13770
- const [renameTarget, setRenameTarget] = React70.useState(null);
13771
- const [renameValue, setRenameValue] = React70.useState("");
13772
- const [deleteTarget, setDeleteTarget] = React70.useState(null);
13773
- const uploadInputRef = React70.useRef(null);
13774
- const crumbFolders = React70.useMemo(() => ancestorsOf(folders, currentFolderId), [folders, currentFolderId]);
13775
- const subfolders = React70.useMemo(() => childrenOf(folders, currentFolderId), [folders, currentFolderId]);
13776
- 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(
13777
13806
  () => files.filter((f) => f.folderId === currentFolderId).sort((a, b) => a.name.localeCompare(b.name)),
13778
13807
  [files, currentFolderId]
13779
13808
  );
@@ -13815,7 +13844,7 @@ function FileBrowser({
13815
13844
  const content = /* @__PURE__ */ jsxs90("div", { className: ["fd-fb", className].filter(Boolean).join(" "), children: [
13816
13845
  /* @__PURE__ */ jsxs90("div", { className: "fd-fb-head", children: [
13817
13846
  /* @__PURE__ */ jsxs90("nav", { className: "fd-fb-crumbs", "aria-label": "Folder path", children: [
13818
- /* @__PURE__ */ jsx99(
13847
+ /* @__PURE__ */ jsx100(
13819
13848
  BreadcrumbCrumb,
13820
13849
  {
13821
13850
  label: "Home",
@@ -13825,7 +13854,7 @@ function FileBrowser({
13825
13854
  onDropPayload: (p) => moveIntoFolder(p, null)
13826
13855
  }
13827
13856
  ),
13828
- crumbFolders.map((f, i) => /* @__PURE__ */ jsx99(
13857
+ crumbFolders.map((f, i) => /* @__PURE__ */ jsx100(
13829
13858
  BreadcrumbCrumb,
13830
13859
  {
13831
13860
  label: f.name,
@@ -13838,10 +13867,10 @@ function FileBrowser({
13838
13867
  ))
13839
13868
  ] }),
13840
13869
  /* @__PURE__ */ jsxs90("span", { className: "fd-fb-actions", children: [
13841
- 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,
13842
13871
  canUpload ? /* @__PURE__ */ jsxs90(Fragment29, { children: [
13843
- /* @__PURE__ */ jsx99(Button, { variant: "secondary", size: "sm", icon: "upload-simple", onClick: () => uploadInputRef.current && uploadInputRef.current.click(), children: "Upload" }),
13844
- /* @__PURE__ */ jsx99(
13872
+ /* @__PURE__ */ jsx100(Button, { variant: "secondary", size: "sm", icon: "upload-simple", onClick: () => uploadInputRef.current && uploadInputRef.current.click(), children: "Upload" }),
13873
+ /* @__PURE__ */ jsx100(
13845
13874
  "input",
13846
13875
  {
13847
13876
  ref: uploadInputRef,
@@ -13861,7 +13890,7 @@ function FileBrowser({
13861
13890
  ] }),
13862
13891
  /* @__PURE__ */ jsxs90("div", { className: "fd-fb-body", children: [
13863
13892
  /* @__PURE__ */ jsxs90("div", { className: "fd-fb-tree", role: "region", "aria-label": "Folder tree", children: [
13864
- /* @__PURE__ */ jsx99(
13893
+ /* @__PURE__ */ jsx100(
13865
13894
  RowShell,
13866
13895
  {
13867
13896
  icon: "house-simple",
@@ -13872,7 +13901,7 @@ function FileBrowser({
13872
13901
  className: ["fd-fb-tree-row", currentFolderId == null ? "is-current" : ""].filter(Boolean).join(" ")
13873
13902
  }
13874
13903
  ),
13875
- childrenOf(folders, null).map((f) => /* @__PURE__ */ jsx99(
13904
+ childrenOf(folders, null).map((f) => /* @__PURE__ */ jsx100(
13876
13905
  TreeNode,
13877
13906
  {
13878
13907
  folder: f,
@@ -13886,18 +13915,18 @@ function FileBrowser({
13886
13915
  f.id
13887
13916
  ))
13888
13917
  ] }),
13889
- /* @__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(
13890
13919
  LoadingRegion,
13891
13920
  {
13892
13921
  state: loading ? "loading" : "ready",
13893
13922
  label: "Loading folder contents",
13894
13923
  skeleton: /* @__PURE__ */ jsxs90("div", { className: "fd-stack", style: { gap: 8, padding: 12 }, children: [
13895
- /* @__PURE__ */ jsx99(Skeleton, { h: 44, radius: "10px" }),
13896
- /* @__PURE__ */ jsx99(Skeleton, { h: 44, radius: "10px" }),
13897
- /* @__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" })
13898
13927
  ] }),
13899
- 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: [
13900
- 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(
13901
13930
  RowShell,
13902
13931
  {
13903
13932
  icon: "folder-simple",
@@ -13907,8 +13936,8 @@ function FileBrowser({
13907
13936
  isDropTarget: canMove,
13908
13937
  onDropPayload: (p) => moveIntoFolder(p, f.id),
13909
13938
  actions: /* @__PURE__ */ jsxs90(Fragment29, { children: [
13910
- canRenameFolder ? /* @__PURE__ */ jsx99(IconButton, { icon: "pencil-simple", label: "Rename " + f.name, size: "sm", variant: "ghost", onClick: () => openRename(f) }) : null,
13911
- 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(
13912
13941
  FolderPickerMenu,
13913
13942
  {
13914
13943
  label: "Move " + f.name,
@@ -13916,12 +13945,12 @@ function FileBrowser({
13916
13945
  onPick: (target) => moveIntoFolder({ kind: "folder", id: f.id }, target)
13917
13946
  }
13918
13947
  ) : null,
13919
- 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
13920
13949
  ] })
13921
13950
  },
13922
13951
  f.id
13923
13952
  )),
13924
- currentFiles.map((file) => /* @__PURE__ */ jsx99(
13953
+ currentFiles.map((file) => /* @__PURE__ */ jsx100(
13925
13954
  RowShell,
13926
13955
  {
13927
13956
  icon: iconForMime(file.mime, file.name),
@@ -13930,7 +13959,7 @@ function FileBrowser({
13930
13959
  onOpen: onOpenFile ? () => onOpenFile(file) : void 0,
13931
13960
  draggableId: canMove ? { kind: "file", id: file.id } : void 0,
13932
13961
  actions: /* @__PURE__ */ jsxs90(Fragment29, { children: [
13933
- canMove ? /* @__PURE__ */ jsx99(
13962
+ canMove ? /* @__PURE__ */ jsx100(
13934
13963
  FolderPickerMenu,
13935
13964
  {
13936
13965
  label: "Move " + file.name,
@@ -13938,7 +13967,7 @@ function FileBrowser({
13938
13967
  onPick: (target) => onMoveFile && onMoveFile(file.id, target)
13939
13968
  }
13940
13969
  ) : null,
13941
- 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
13942
13971
  ] })
13943
13972
  },
13944
13973
  file.id
@@ -13947,10 +13976,10 @@ function FileBrowser({
13947
13976
  }
13948
13977
  ) })
13949
13978
  ] }),
13950
- /* @__PURE__ */ jsx99(Modal, { open: createOpen, title: "New folder", onClose: () => setCreateOpen(false), footer: /* @__PURE__ */ jsxs90(Fragment29, { children: [
13951
- /* @__PURE__ */ jsx99(Button, { variant: "secondary", onClick: () => setCreateOpen(false), children: "Cancel" }),
13952
- /* @__PURE__ */ jsx99(Button, { onClick: submitCreate, disabled: !createName.trim(), children: "Create" })
13953
- ] }), 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(
13954
13983
  "input",
13955
13984
  {
13956
13985
  className: "fd-fb-input",
@@ -13964,10 +13993,10 @@ function FileBrowser({
13964
13993
  autoFocus: true
13965
13994
  }
13966
13995
  ) }),
13967
- /* @__PURE__ */ jsx99(Modal, { open: renameTarget != null, title: "Rename folder", onClose: () => setRenameTarget(null), footer: /* @__PURE__ */ jsxs90(Fragment29, { children: [
13968
- /* @__PURE__ */ jsx99(Button, { variant: "secondary", onClick: () => setRenameTarget(null), children: "Cancel" }),
13969
- /* @__PURE__ */ jsx99(Button, { onClick: submitRename, disabled: !renameValue.trim(), children: "Save" })
13970
- ] }), 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(
13971
14000
  "input",
13972
14001
  {
13973
14002
  className: "fd-fb-input",
@@ -13981,7 +14010,7 @@ function FileBrowser({
13981
14010
  autoFocus: true
13982
14011
  }
13983
14012
  ) }),
13984
- /* @__PURE__ */ jsx99(
14013
+ /* @__PURE__ */ jsx100(
13985
14014
  Modal,
13986
14015
  {
13987
14016
  open: deleteTarget != null,
@@ -13989,14 +14018,14 @@ function FileBrowser({
13989
14018
  description: "This can't be undone. The folder must be empty.",
13990
14019
  onClose: () => setDeleteTarget(null),
13991
14020
  footer: /* @__PURE__ */ jsxs90(Fragment29, { children: [
13992
- /* @__PURE__ */ jsx99(Button, { variant: "secondary", onClick: () => setDeleteTarget(null), children: "Cancel" }),
13993
- /* @__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" })
13994
14023
  ] })
13995
14024
  }
13996
14025
  )
13997
14026
  ] });
13998
14027
  if (!canUpload) return content;
13999
- 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 });
14000
14029
  }
14001
14030
  function BreadcrumbCrumb({
14002
14031
  label,
@@ -14005,8 +14034,8 @@ function BreadcrumbCrumb({
14005
14034
  isDropTarget,
14006
14035
  onDropPayload
14007
14036
  }) {
14008
- const [over, setOver] = React70.useState(false);
14009
- const dragCounter = React70.useRef(0);
14037
+ const [over, setOver] = React71.useState(false);
14038
+ const dragCounter = React71.useRef(0);
14010
14039
  const dropHandlers = isDropTarget ? {
14011
14040
  onDragEnter: (e) => {
14012
14041
  if (!hasInternalPayload(e)) return;
@@ -14031,11 +14060,11 @@ function BreadcrumbCrumb({
14031
14060
  if (payload && onDropPayload) onDropPayload(payload);
14032
14061
  }
14033
14062
  } : {};
14034
- 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 }) });
14035
14064
  }
14036
14065
 
14037
14066
  // src/kits/query.ts
14038
- import * as React71 from "react";
14067
+ import * as React72 from "react";
14039
14068
  var isMultiSelectShaped = (v) => !!v && typeof v === "object" && Array.isArray(v.values);
14040
14069
  var isRangeShaped = (v) => !!v && typeof v === "object" && ("min" in v || "max" in v);
14041
14070
  var isDateShaped = (v) => !!v && typeof v === "object" && "kind" in v;
@@ -14090,22 +14119,22 @@ function compare(a, b, dir) {
14090
14119
  var API = null;
14091
14120
  var PREFS = null;
14092
14121
  function useServerTable({ endpoint, params, defaults, deps, prefsKey }) {
14093
- const [query, setQuery] = React71.useState(() => {
14122
+ const [query, setQuery] = React72.useState(() => {
14094
14123
  const store = PREFS || window.PlannerPrefs;
14095
14124
  const saved = prefsKey && store ? store.getTable(prefsKey) : {};
14096
14125
  return { ...DEFAULTS, ...defaults || {}, ...saved.pageSize ? { pageSize: saved.pageSize } : {}, ...saved.sort ? { sort: saved.sort, dir: saved.dir || "desc" } : {} };
14097
14126
  });
14098
- const savePref = React71.useCallback((patch2) => {
14127
+ const savePref = React72.useCallback((patch2) => {
14099
14128
  const store = PREFS || window.PlannerPrefs;
14100
14129
  if (prefsKey && store) store.setTable(prefsKey, patch2);
14101
14130
  }, [prefsKey]);
14102
- const [res, setRes] = React71.useState(null);
14103
- const [loading, setLoading] = React71.useState(true);
14104
- 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);
14105
14134
  const depKey = (deps || []).join("|");
14106
14135
  const paramKey = JSON.stringify(params || {});
14107
14136
  const queryKey = JSON.stringify(query);
14108
- React71.useEffect(() => {
14137
+ React72.useEffect(() => {
14109
14138
  const id = ++seq2.current;
14110
14139
  setLoading(true);
14111
14140
  const t = setTimeout(() => {
@@ -14424,12 +14453,12 @@ function createVersionStore(initialState, options) {
14424
14453
  }
14425
14454
 
14426
14455
  // src/kits/documentTitle.ts
14427
- import * as React72 from "react";
14456
+ import * as React73 from "react";
14428
14457
  function formatDocumentTitle(routeTitle, appName) {
14429
14458
  return [routeTitle, appName, "Flytedesk"].filter((part) => !!part && part.length > 0).join(" \xB7 ");
14430
14459
  }
14431
14460
  function useDocumentTitle(routeTitle, appName) {
14432
- React72.useEffect(() => {
14461
+ React73.useEffect(() => {
14433
14462
  if (typeof document === "undefined") return;
14434
14463
  document.title = formatDocumentTitle(routeTitle, appName);
14435
14464
  }, [routeTitle, appName]);
@@ -14443,6 +14472,7 @@ export {
14443
14472
  AppShell,
14444
14473
  AppSwitcher,
14445
14474
  AppearanceMenu,
14475
+ AppearanceProvider,
14446
14476
  Avatar,
14447
14477
  AvatarStack,
14448
14478
  Badge,
@@ -14454,6 +14484,7 @@ export {
14454
14484
  CHANNEL_WEIGHTS,
14455
14485
  CHAT_UNAVAILABLE,
14456
14486
  COPIED_FEEDBACK_MS,
14487
+ CORNER_STACK_INSET_PROPERTY,
14457
14488
  Calendar,
14458
14489
  Card,
14459
14490
  CardGrid,
@@ -14597,6 +14628,7 @@ export {
14597
14628
  __resetLayerStackForTests,
14598
14629
  acceptMatches,
14599
14630
  anyOfFilter,
14631
+ applyAppearance,
14600
14632
  applyPrefs,
14601
14633
  channelWeightOf,
14602
14634
  computeNeedMore,
@@ -14642,6 +14674,7 @@ export {
14642
14674
  toAttachment,
14643
14675
  tokenize,
14644
14676
  useAppearancePrefs,
14677
+ useAppearanceStore,
14645
14678
  useChatEngine,
14646
14679
  useCopyToClipboard,
14647
14680
  useCornerStackSlot,
@@ -14657,6 +14690,7 @@ export {
14657
14690
  useStagedFiles,
14658
14691
  useToast,
14659
14692
  validateFilterValue,
14660
- visibleMessages
14693
+ visibleMessages,
14694
+ watchAppearance
14661
14695
  };
14662
14696
  //# sourceMappingURL=index.js.map