@flytedan/flytebot-design-system 0.19.0 → 0.21.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
@@ -6376,11 +6376,204 @@ function ProfilePage({
6376
6376
  ] });
6377
6377
  }
6378
6378
 
6379
+ // src/components/platform/SignInPage.tsx
6380
+ import * as React42 from "react";
6381
+ import { Fragment as Fragment18, jsx as jsx67, jsxs as jsxs61 } from "react/jsx-runtime";
6382
+ function SignInPage({ productName, onSignIn, continueAs, error }) {
6383
+ const [signingIn, setSigningIn] = React42.useState(false);
6384
+ const [resuming, setResuming] = React42.useState(false);
6385
+ function handleSignIn() {
6386
+ setSigningIn(true);
6387
+ onSignIn();
6388
+ }
6389
+ function handleContinue() {
6390
+ setResuming(true);
6391
+ continueAs.onContinue().finally(() => setResuming(false));
6392
+ }
6393
+ return /* @__PURE__ */ jsxs61(
6394
+ "div",
6395
+ {
6396
+ style: {
6397
+ position: "relative",
6398
+ display: "grid",
6399
+ placeItems: "center",
6400
+ minHeight: "100vh",
6401
+ padding: "24px 16px",
6402
+ boxSizing: "border-box",
6403
+ overflow: "hidden",
6404
+ background: "radial-gradient(circle at 15% 15%, var(--blue-700) 0%, transparent 45%), radial-gradient(circle at 85% 85%, var(--blue-600) 0%, transparent 40%), linear-gradient(160deg, var(--navy) 0%, var(--blue-950) 55%, var(--blue-900) 100%)"
6405
+ },
6406
+ children: [
6407
+ /* @__PURE__ */ jsx67(
6408
+ "div",
6409
+ {
6410
+ "aria-hidden": true,
6411
+ style: {
6412
+ position: "absolute",
6413
+ inset: 0,
6414
+ backgroundImage: "linear-gradient(rgba(255,255,255,0.05) 1px, transparent 1px), linear-gradient(90deg, rgba(255,255,255,0.05) 1px, transparent 1px)",
6415
+ backgroundSize: "48px 48px",
6416
+ maskImage: "radial-gradient(circle at 50% 40%, black, transparent 70%)"
6417
+ }
6418
+ }
6419
+ ),
6420
+ /* @__PURE__ */ jsxs61(
6421
+ "div",
6422
+ {
6423
+ style: {
6424
+ position: "relative",
6425
+ width: "100%",
6426
+ maxWidth: 408,
6427
+ display: "flex",
6428
+ flexDirection: "column",
6429
+ alignItems: "center"
6430
+ },
6431
+ children: [
6432
+ /* @__PURE__ */ jsx67("div", { style: { marginBottom: "var(--s-32)" }, "data-theme": "dark", children: /* @__PURE__ */ jsx67(FlytedeskMark, { size: "lg" }) }),
6433
+ /* @__PURE__ */ jsxs61(
6434
+ "div",
6435
+ {
6436
+ style: {
6437
+ width: "100%",
6438
+ borderRadius: "var(--r-2xl)",
6439
+ overflow: "hidden",
6440
+ boxShadow: "0 24px 64px -12px rgba(2, 8, 20, 0.55), 0 2px 8px rgba(2, 8, 20, 0.3)"
6441
+ },
6442
+ children: [
6443
+ /* @__PURE__ */ jsx67(
6444
+ "div",
6445
+ {
6446
+ style: {
6447
+ height: 4,
6448
+ background: "linear-gradient(90deg, var(--blue-400), var(--blue-600), var(--navy))"
6449
+ }
6450
+ }
6451
+ ),
6452
+ /* @__PURE__ */ jsx67(Card, { children: /* @__PURE__ */ jsxs61(
6453
+ "div",
6454
+ {
6455
+ style: {
6456
+ display: "flex",
6457
+ flexDirection: "column",
6458
+ gap: "var(--s-20)",
6459
+ alignItems: "center",
6460
+ textAlign: "center",
6461
+ padding: "var(--s-8) 0"
6462
+ },
6463
+ children: [
6464
+ /* @__PURE__ */ jsxs61("div", { children: [
6465
+ /* @__PURE__ */ jsx67("h1", { className: "fd-h3", style: { color: "var(--navy)" }, children: productName }),
6466
+ /* @__PURE__ */ jsx67("p", { className: "fd-body-sm fd-muted", style: { marginTop: "var(--s-4)" }, children: continueAs ? "Your session timed out, but you're likely still signed in" : "Sign in with your flytedesk workspace account" })
6467
+ ] }),
6468
+ error ? /* @__PURE__ */ jsx67("div", { role: "alert", style: { width: "100%" }, children: /* @__PURE__ */ jsx67(Banner, { tone: "danger", title: error }) }) : null,
6469
+ continueAs ? /* @__PURE__ */ jsxs61(Fragment18, { children: [
6470
+ /* @__PURE__ */ jsx67(
6471
+ Button,
6472
+ {
6473
+ variant: "primary",
6474
+ style: { width: "100%" },
6475
+ loading: resuming,
6476
+ disabled: resuming,
6477
+ onClick: handleContinue,
6478
+ children: resuming ? "Resuming\u2026" : `Continue as ${continueAs.name}`
6479
+ }
6480
+ ),
6481
+ /* @__PURE__ */ jsx67(
6482
+ "button",
6483
+ {
6484
+ type: "button",
6485
+ className: "fd-body-sm fd-muted",
6486
+ style: {
6487
+ background: "none",
6488
+ border: "none",
6489
+ cursor: "pointer",
6490
+ textDecoration: "underline",
6491
+ padding: 0
6492
+ },
6493
+ disabled: resuming,
6494
+ onClick: continueAs.onDecline,
6495
+ children: "Not you? Sign in with flytedesk ID"
6496
+ }
6497
+ )
6498
+ ] }) : /* @__PURE__ */ jsx67(
6499
+ Button,
6500
+ {
6501
+ variant: "primary",
6502
+ style: { width: "100%" },
6503
+ loading: signingIn,
6504
+ disabled: signingIn,
6505
+ onClick: handleSignIn,
6506
+ children: /* @__PURE__ */ jsxs61(
6507
+ "span",
6508
+ {
6509
+ style: {
6510
+ display: "flex",
6511
+ flexDirection: "row",
6512
+ alignItems: "center",
6513
+ justifyContent: "center",
6514
+ gap: "var(--s-8)",
6515
+ flexWrap: "nowrap"
6516
+ },
6517
+ children: [
6518
+ /* @__PURE__ */ jsx67(GoogleGlyph, {}),
6519
+ /* @__PURE__ */ jsx67("span", { children: signingIn ? "Signing in\u2026" : "Sign in with flytedesk ID" })
6520
+ ]
6521
+ }
6522
+ )
6523
+ }
6524
+ ),
6525
+ /* @__PURE__ */ jsx67("p", { className: "fd-body-sm fd-muted", style: { fontSize: "12px" }, children: "One account, every flytedesk app." })
6526
+ ]
6527
+ }
6528
+ ) })
6529
+ ]
6530
+ }
6531
+ )
6532
+ ]
6533
+ }
6534
+ )
6535
+ ]
6536
+ }
6537
+ );
6538
+ }
6539
+ function GoogleGlyph() {
6540
+ return /* @__PURE__ */ jsxs61("svg", { width: "18", height: "18", viewBox: "0 0 18 18", "aria-hidden": true, children: [
6541
+ /* @__PURE__ */ jsx67(
6542
+ "path",
6543
+ {
6544
+ fill: "#4285F4",
6545
+ d: "M17.64 9.2c0-.64-.06-1.25-.16-1.84H9v3.48h4.84a4.14 4.14 0 0 1-1.8 2.72v2.26h2.92c1.7-1.57 2.68-3.87 2.68-6.62Z"
6546
+ }
6547
+ ),
6548
+ /* @__PURE__ */ jsx67(
6549
+ "path",
6550
+ {
6551
+ fill: "#34A853",
6552
+ d: "M9 18c2.43 0 4.47-.8 5.96-2.18l-2.92-2.26c-.81.54-1.84.87-3.04.87-2.34 0-4.32-1.58-5.03-3.7H.96v2.33A9 9 0 0 0 9 18Z"
6553
+ }
6554
+ ),
6555
+ /* @__PURE__ */ jsx67(
6556
+ "path",
6557
+ {
6558
+ fill: "#FBBC05",
6559
+ d: "M3.97 10.73A5.4 5.4 0 0 1 3.68 9c0-.6.1-1.19.29-1.73V4.94H.96A9 9 0 0 0 0 9c0 1.45.35 2.83.96 4.06l3.01-2.33Z"
6560
+ }
6561
+ ),
6562
+ /* @__PURE__ */ jsx67(
6563
+ "path",
6564
+ {
6565
+ fill: "#EA4335",
6566
+ d: "M9 3.58c1.32 0 2.51.45 3.44 1.35l2.59-2.59C13.46.89 11.43 0 9 0A9 9 0 0 0 .96 4.94l3.01 2.33C4.68 5.16 6.66 3.58 9 3.58Z"
6567
+ }
6568
+ )
6569
+ ] });
6570
+ }
6571
+
6379
6572
  // src/components/platform/RoadmapTimeline.tsx
6380
- import * as React44 from "react";
6573
+ import * as React45 from "react";
6381
6574
 
6382
6575
  // src/kits/session.ts
6383
- import * as React42 from "react";
6576
+ import * as React43 from "react";
6384
6577
  var PERMISSION_CATALOG = [
6385
6578
  { group: "Plans", items: [
6386
6579
  { key: "plan.view", label: "View plans", detail: "Read any plan in the workspace." },
@@ -7947,8 +8140,8 @@ function roadmap(overrides) {
7947
8140
  };
7948
8141
  }
7949
8142
  function useSession() {
7950
- const [s, setS] = React42.useState(getSession);
7951
- React42.useEffect(() => subscribe(setS), []);
8143
+ const [s, setS] = React43.useState(getSession);
8144
+ React43.useEffect(() => subscribe(setS), []);
7952
8145
  return s;
7953
8146
  }
7954
8147
  var SessionKit = {
@@ -7981,7 +8174,7 @@ var SessionKit = {
7981
8174
  };
7982
8175
  function DemoSessionProvider({ children }) {
7983
8176
  const session = useSession();
7984
- const value = React42.useMemo(
8177
+ const value = React43.useMemo(
7985
8178
  () => ({
7986
8179
  user: session.user,
7987
8180
  roles: session.roles,
@@ -7997,11 +8190,11 @@ function DemoSessionProvider({ children }) {
7997
8190
  }),
7998
8191
  [session]
7999
8192
  );
8000
- return React42.createElement(SessionProvider, { value }, children);
8193
+ return React43.createElement(SessionProvider, { value }, children);
8001
8194
  }
8002
8195
 
8003
8196
  // src/kits/runtime.ts
8004
- import * as React43 from "react";
8197
+ import * as React44 from "react";
8005
8198
  var WIRED_ENDPOINTS = [
8006
8199
  // Nothing yet. Every id below would come from a real service:
8007
8200
  // "plan.get", "placements.list", …
@@ -8172,8 +8365,8 @@ var RuntimeKit = {
8172
8365
  };
8173
8366
  RuntimeKit.declare(FEATURE_NEEDS);
8174
8367
  function useRuntimeMode() {
8175
- const [m, setM] = React43.useState(RuntimeKit.getMode());
8176
- React43.useEffect(() => RuntimeKit.subscribe(setM), []);
8368
+ const [m, setM] = React44.useState(RuntimeKit.getMode());
8369
+ React44.useEffect(() => RuntimeKit.subscribe(setM), []);
8177
8370
  return m;
8178
8371
  }
8179
8372
  function useFeatureStatus(key) {
@@ -8192,7 +8385,7 @@ var UseRuntimeMode = useRuntimeMode;
8192
8385
  var UseFeatureStatus = useFeatureStatus;
8193
8386
 
8194
8387
  // src/components/platform/RoadmapTimeline.tsx
8195
- import { jsx as jsx67, jsxs as jsxs61 } from "react/jsx-runtime";
8388
+ import { jsx as jsx68, jsxs as jsxs62 } from "react/jsx-runtime";
8196
8389
  var STATUS = {
8197
8390
  shipped: { tone: "success", icon: "check-circle", label: "Wired" },
8198
8391
  next: { tone: "warning", icon: "traffic-cone", label: "Not wired" },
@@ -8207,45 +8400,45 @@ function RoadmapCard({ item, byKey, onOpenFlag }) {
8207
8400
  const s = STATUS[item.status] || STATUS.planned;
8208
8401
  const deps = (item.dependsOn || []).map((k) => byKey[k]).filter(Boolean);
8209
8402
  const blocking = deps.filter((d) => !d.implemented);
8210
- return /* @__PURE__ */ jsx67(Card, { elevation: "flat", children: /* @__PURE__ */ jsxs61("div", { className: "fd-stack", style: { gap: 10 }, children: [
8211
- /* @__PURE__ */ jsxs61("div", { className: "fd-row", style: { gap: 8, flexWrap: "wrap" }, children: [
8212
- /* @__PURE__ */ jsx67("span", { className: "fd-body", style: { fontWeight: 700, flex: 1, minWidth: 140 }, children: item.label }),
8213
- /* @__PURE__ */ jsx67(Badge, { tone: "neutral", icon: PROJECT_ICON[item.project] || "squares-four", children: item.project }),
8214
- /* @__PURE__ */ jsx67(Badge, { tone: s.tone, icon: s.icon, children: s.label })
8403
+ return /* @__PURE__ */ jsx68(Card, { elevation: "flat", children: /* @__PURE__ */ jsxs62("div", { className: "fd-stack", style: { gap: 10 }, children: [
8404
+ /* @__PURE__ */ jsxs62("div", { className: "fd-row", style: { gap: 8, flexWrap: "wrap" }, children: [
8405
+ /* @__PURE__ */ jsx68("span", { className: "fd-body", style: { fontWeight: 700, flex: 1, minWidth: 140 }, children: item.label }),
8406
+ /* @__PURE__ */ jsx68(Badge, { tone: "neutral", icon: PROJECT_ICON[item.project] || "squares-four", children: item.project }),
8407
+ /* @__PURE__ */ jsx68(Badge, { tone: s.tone, icon: s.icon, children: s.label })
8215
8408
  ] }),
8216
- /* @__PURE__ */ jsx67("p", { className: "fd-body-sm fd-secondary", style: { margin: 0, textWrap: "pretty" }, children: item.description }),
8217
- item.backend ? /* @__PURE__ */ jsxs61("div", { className: "fd-row", style: { gap: 10, alignItems: "flex-start" }, children: [
8218
- /* @__PURE__ */ jsx67("span", { className: "fd-overline fd-muted", style: { width: 62, flex: "none", paddingTop: 2 }, children: "Backend" }),
8219
- /* @__PURE__ */ jsx67("span", { className: "fd-body-sm", style: { flex: 1, textWrap: "pretty" }, children: item.backend })
8409
+ /* @__PURE__ */ jsx68("p", { className: "fd-body-sm fd-secondary", style: { margin: 0, textWrap: "pretty" }, children: item.description }),
8410
+ item.backend ? /* @__PURE__ */ jsxs62("div", { className: "fd-row", style: { gap: 10, alignItems: "flex-start" }, children: [
8411
+ /* @__PURE__ */ jsx68("span", { className: "fd-overline fd-muted", style: { width: 62, flex: "none", paddingTop: 2 }, children: "Backend" }),
8412
+ /* @__PURE__ */ jsx68("span", { className: "fd-body-sm", style: { flex: 1, textWrap: "pretty" }, children: item.backend })
8220
8413
  ] }) : null,
8221
- /* @__PURE__ */ jsxs61("div", { className: "fd-row", style: { gap: 12, flexWrap: "wrap" }, children: [
8222
- item.effort ? /* @__PURE__ */ jsxs61("span", { className: "fd-body-sm fd-muted", children: [
8223
- /* @__PURE__ */ jsx67("i", { className: "ph ph-hourglass-medium" }),
8414
+ /* @__PURE__ */ jsxs62("div", { className: "fd-row", style: { gap: 12, flexWrap: "wrap" }, children: [
8415
+ item.effort ? /* @__PURE__ */ jsxs62("span", { className: "fd-body-sm fd-muted", children: [
8416
+ /* @__PURE__ */ jsx68("i", { className: "ph ph-hourglass-medium" }),
8224
8417
  " ",
8225
8418
  item.effort
8226
8419
  ] }) : null,
8227
- /* @__PURE__ */ jsxs61("span", { className: "fd-body-sm fd-muted", children: [
8228
- /* @__PURE__ */ jsx67("i", { className: "ph ph-user" }),
8420
+ /* @__PURE__ */ jsxs62("span", { className: "fd-body-sm fd-muted", children: [
8421
+ /* @__PURE__ */ jsx68("i", { className: "ph ph-user" }),
8229
8422
  " ",
8230
8423
  item.owner
8231
8424
  ] }),
8232
- item.screen ? /* @__PURE__ */ jsx67(Badge, { tone: "neutral", icon: "browser", children: "screen" }) : null,
8233
- /* @__PURE__ */ jsx67("span", { style: { flex: 1 } }),
8234
- /* @__PURE__ */ jsx67(
8425
+ item.screen ? /* @__PURE__ */ jsx68(Badge, { tone: "neutral", icon: "browser", children: "screen" }) : null,
8426
+ /* @__PURE__ */ jsx68("span", { style: { flex: 1 } }),
8427
+ /* @__PURE__ */ jsx68(
8235
8428
  "button",
8236
8429
  {
8237
8430
  type: "button",
8238
8431
  onClick: () => onOpenFlag && onOpenFlag(item.key),
8239
8432
  style: { all: "unset", cursor: "pointer", display: "inline-flex", alignItems: "center", gap: 5 },
8240
- children: /* @__PURE__ */ jsx67("code", { className: "fd-mono", style: { fontSize: 11, color: "var(--brand)" }, children: item.key })
8433
+ children: /* @__PURE__ */ jsx68("code", { className: "fd-mono", style: { fontSize: 11, color: "var(--brand)" }, children: item.key })
8241
8434
  }
8242
8435
  )
8243
8436
  ] }),
8244
- deps.length ? /* @__PURE__ */ jsxs61("div", { className: "fd-row", style: { gap: 6, flexWrap: "wrap", paddingTop: 6, borderTop: "1px solid var(--border)" }, children: [
8245
- /* @__PURE__ */ jsx67("span", { className: "fd-overline fd-muted", style: { paddingTop: 3 }, children: "After" }),
8246
- deps.map((d) => /* @__PURE__ */ jsx67(Tag, { icon: d.implemented ? "check" : "clock", children: d.label }, d.key))
8437
+ deps.length ? /* @__PURE__ */ jsxs62("div", { className: "fd-row", style: { gap: 6, flexWrap: "wrap", paddingTop: 6, borderTop: "1px solid var(--border)" }, children: [
8438
+ /* @__PURE__ */ jsx68("span", { className: "fd-overline fd-muted", style: { paddingTop: 3 }, children: "After" }),
8439
+ deps.map((d) => /* @__PURE__ */ jsx68(Tag, { icon: d.implemented ? "check" : "clock", children: d.label }, d.key))
8247
8440
  ] }) : null,
8248
- blocking.length && !item.implemented ? /* @__PURE__ */ jsxs61("span", { className: "fd-body-sm", style: { color: "var(--warn-text)" }, children: [
8441
+ blocking.length && !item.implemented ? /* @__PURE__ */ jsxs62("span", { className: "fd-body-sm", style: { color: "var(--warn-text)" }, children: [
8249
8442
  "Blocked until ",
8250
8443
  blocking.map((d) => d.label).join(" and "),
8251
8444
  " ",
@@ -8256,12 +8449,12 @@ function RoadmapCard({ item, byKey, onOpenFlag }) {
8256
8449
  }
8257
8450
  function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
8258
8451
  const session = SessionKit.useSession();
8259
- const [project, setProject] = React44.useState("");
8260
- const [q, setQ] = React44.useState("");
8261
- const scrollRef = React44.useRef(null);
8262
- const nowRef = React44.useRef(null);
8263
- const rm = React44.useMemo(() => SessionKit.roadmap({ isComplete: RuntimeKit.isComplete }), [session]);
8264
- const byKey = React44.useMemo(() => {
8452
+ const [project, setProject] = React45.useState("");
8453
+ const [q, setQ] = React45.useState("");
8454
+ const scrollRef = React45.useRef(null);
8455
+ const nowRef = React45.useRef(null);
8456
+ const rm = React45.useMemo(() => SessionKit.roadmap({ isComplete: RuntimeKit.isComplete }), [session]);
8457
+ const byKey = React45.useMemo(() => {
8265
8458
  const m = {};
8266
8459
  rm.items.forEach((i) => {
8267
8460
  m[i.key] = i;
@@ -8270,7 +8463,7 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
8270
8463
  }, [rm]);
8271
8464
  const items = rm.items.filter((i) => (!project || i.project === project) && (!q || (i.label + " " + i.description + " " + (i.backend || "") + " " + i.key).toLowerCase().includes(q.toLowerCase())));
8272
8465
  const projects = [...new Set(rm.items.map((i) => i.project))];
8273
- React44.useEffect(() => {
8466
+ React45.useEffect(() => {
8274
8467
  let raf1 = 0, raf2 = 0;
8275
8468
  const place = () => {
8276
8469
  const box = scrollRef.current, mark = nowRef.current;
@@ -8298,23 +8491,23 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
8298
8491
  }, 0);
8299
8492
  const nextPhase = items.find((i) => !i.implemented);
8300
8493
  let lastPhase = null;
8301
- return /* @__PURE__ */ jsxs61("div", { className: "fd-stack", style: { gap: 16, maxWidth: 1e3 }, children: [
8302
- /* @__PURE__ */ jsxs61("div", { className: "fd-stack", style: { gap: 10 }, children: [
8303
- /* @__PURE__ */ jsx67("span", { className: "fd-overline fd-muted", children: "Architecture" }),
8304
- /* @__PURE__ */ jsx67("h1", { className: "fd-h1", style: { margin: 0 }, children: title }),
8305
- /* @__PURE__ */ jsx67("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." })
8494
+ return /* @__PURE__ */ jsxs62("div", { className: "fd-stack", style: { gap: 16, maxWidth: 1e3 }, children: [
8495
+ /* @__PURE__ */ jsxs62("div", { className: "fd-stack", style: { gap: 10 }, children: [
8496
+ /* @__PURE__ */ jsx68("span", { className: "fd-overline fd-muted", children: "Architecture" }),
8497
+ /* @__PURE__ */ jsx68("h1", { className: "fd-h1", style: { margin: 0 }, children: title }),
8498
+ /* @__PURE__ */ jsx68("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." })
8306
8499
  ] }),
8307
- /* @__PURE__ */ jsxs61("div", { className: "fd-grid-stats is-thin", children: [
8308
- /* @__PURE__ */ jsx67(StatTile, { compact: true, label: "Wired", value: String(rm.shipped), sub: "of " + rm.items.length + " features" }),
8309
- /* @__PURE__ */ jsx67(StatTile, { compact: true, label: "Remaining", value: String(rm.remaining), sub: "backend work" }),
8310
- /* @__PURE__ */ jsx67(StatTile, { compact: true, label: "Est. effort", value: days ? days + " days" : "\u2014", sub: "sum of estimates, not calendar" }),
8311
- /* @__PURE__ */ jsx67(StatTile, { compact: true, label: "Up next", value: nextPhase ? "Phase " + nextPhase.phase : "\u2014", sub: nextPhase ? nextPhase.phaseName : "all wired" })
8500
+ /* @__PURE__ */ jsxs62("div", { className: "fd-grid-stats is-thin", children: [
8501
+ /* @__PURE__ */ jsx68(StatTile, { compact: true, label: "Wired", value: String(rm.shipped), sub: "of " + rm.items.length + " features" }),
8502
+ /* @__PURE__ */ jsx68(StatTile, { compact: true, label: "Remaining", value: String(rm.remaining), sub: "backend work" }),
8503
+ /* @__PURE__ */ jsx68(StatTile, { compact: true, label: "Est. effort", value: days ? days + " days" : "\u2014", sub: "sum of estimates, not calendar" }),
8504
+ /* @__PURE__ */ jsx68(StatTile, { compact: true, label: "Up next", value: nextPhase ? "Phase " + nextPhase.phase : "\u2014", sub: nextPhase ? nextPhase.phaseName : "all wired" })
8312
8505
  ] }),
8313
- /* @__PURE__ */ jsxs61("div", { className: "fd-row", style: { gap: 10, flexWrap: "wrap" }, children: [
8314
- /* @__PURE__ */ jsx67(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 } }),
8315
- /* @__PURE__ */ jsx67(Select, { placeholder: "All projects", value: project, onChange: (e) => setProject(e.target.value), options: projects, style: { width: 190 } }),
8316
- /* @__PURE__ */ jsx67("span", { style: { flex: 1 } }),
8317
- /* @__PURE__ */ jsx67(
8506
+ /* @__PURE__ */ jsxs62("div", { className: "fd-row", style: { gap: 10, flexWrap: "wrap" }, children: [
8507
+ /* @__PURE__ */ jsx68(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 } }),
8508
+ /* @__PURE__ */ jsx68(Select, { placeholder: "All projects", value: project, onChange: (e) => setProject(e.target.value), options: projects, style: { width: 190 } }),
8509
+ /* @__PURE__ */ jsx68("span", { style: { flex: 1 } }),
8510
+ /* @__PURE__ */ jsx68(
8318
8511
  Button,
8319
8512
  {
8320
8513
  size: "sm",
@@ -8328,7 +8521,7 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
8328
8521
  }
8329
8522
  )
8330
8523
  ] }),
8331
- /* @__PURE__ */ jsx67(
8524
+ /* @__PURE__ */ jsx68(
8332
8525
  Flag,
8333
8526
  {
8334
8527
  tone: "info",
@@ -8337,60 +8530,60 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
8337
8530
  actions: null
8338
8531
  }
8339
8532
  ),
8340
- /* @__PURE__ */ jsx67("div", { className: "fd-rm", children: /* @__PURE__ */ jsx67("div", { className: "fd-rm-scroll", ref: scrollRef, children: /* @__PURE__ */ jsxs61("div", { className: "fd-rm-track", children: [
8341
- /* @__PURE__ */ jsx67("span", { className: "fd-rm-spine", children: /* @__PURE__ */ jsx67("span", { className: "fd-rm-spine-done", style: { height: items.length ? 100 * shippedShown / items.length + "%" : "0%" } }) }),
8533
+ /* @__PURE__ */ jsx68("div", { className: "fd-rm", children: /* @__PURE__ */ jsx68("div", { className: "fd-rm-scroll", ref: scrollRef, children: /* @__PURE__ */ jsxs62("div", { className: "fd-rm-track", children: [
8534
+ /* @__PURE__ */ jsx68("span", { className: "fd-rm-spine", children: /* @__PURE__ */ jsx68("span", { className: "fd-rm-spine-done", style: { height: items.length ? 100 * shippedShown / items.length + "%" : "0%" } }) }),
8342
8535
  items.map((item, n) => {
8343
8536
  const showPhase = item.phase !== lastPhase;
8344
8537
  lastPhase = item.phase;
8345
8538
  const inPhase = items.filter((i) => i.phase === item.phase).length;
8346
8539
  const isBoundary = n === firstPending;
8347
- return /* @__PURE__ */ jsxs61(React44.Fragment, { children: [
8348
- showPhase ? /* @__PURE__ */ jsxs61("div", { className: "fd-rm-era", children: [
8349
- /* @__PURE__ */ jsxs61("span", { className: "fd-row", style: { gap: 8, flexWrap: "wrap", alignItems: "baseline" }, children: [
8350
- /* @__PURE__ */ jsx67("span", { style: { fontWeight: 700 }, children: item.phase === 0 ? "Shipped" : "Phase " + item.phase + " \u2014 " + item.phaseName }),
8351
- item.phase === 0 ? null : /* @__PURE__ */ jsxs61("span", { className: "fd-mono", style: { opacity: 0.7, fontWeight: 400 }, children: [
8540
+ return /* @__PURE__ */ jsxs62(React45.Fragment, { children: [
8541
+ showPhase ? /* @__PURE__ */ jsxs62("div", { className: "fd-rm-era", children: [
8542
+ /* @__PURE__ */ jsxs62("span", { className: "fd-row", style: { gap: 8, flexWrap: "wrap", alignItems: "baseline" }, children: [
8543
+ /* @__PURE__ */ jsx68("span", { style: { fontWeight: 700 }, children: item.phase === 0 ? "Shipped" : "Phase " + item.phase + " \u2014 " + item.phaseName }),
8544
+ item.phase === 0 ? null : /* @__PURE__ */ jsxs62("span", { className: "fd-mono", style: { opacity: 0.7, fontWeight: 400 }, children: [
8352
8545
  fmtDate(item.phaseStart),
8353
8546
  " \u2013 ",
8354
8547
  fmtDate(item.date)
8355
8548
  ] }),
8356
- /* @__PURE__ */ jsxs61("span", { style: { opacity: 0.7, fontWeight: 400 }, children: [
8549
+ /* @__PURE__ */ jsxs62("span", { style: { opacity: 0.7, fontWeight: 400 }, children: [
8357
8550
  "\xB7 ",
8358
8551
  inPhase,
8359
8552
  " feature",
8360
8553
  inPhase === 1 ? "" : "s"
8361
8554
  ] })
8362
8555
  ] }),
8363
- item.phaseWhy ? /* @__PURE__ */ jsx67("p", { className: "fd-rm-era-why", children: item.phaseWhy }) : null
8556
+ item.phaseWhy ? /* @__PURE__ */ jsx68("p", { className: "fd-rm-era-why", children: item.phaseWhy }) : null
8364
8557
  ] }) : null,
8365
- isBoundary ? /* @__PURE__ */ jsx67("div", { className: "fd-rm-now", ref: nowRef, children: /* @__PURE__ */ jsxs61("span", { className: "fd-rm-now-pill", children: [
8366
- /* @__PURE__ */ jsx67("i", { className: "ph ph-map-pin" }),
8558
+ isBoundary ? /* @__PURE__ */ jsx68("div", { className: "fd-rm-now", ref: nowRef, children: /* @__PURE__ */ jsxs62("span", { className: "fd-rm-now-pill", children: [
8559
+ /* @__PURE__ */ jsx68("i", { className: "ph ph-map-pin" }),
8367
8560
  " You are here \u2014 everything above is wired"
8368
8561
  ] }) }) : null,
8369
- /* @__PURE__ */ jsxs61("div", { className: "fd-rm-row", children: [
8370
- /* @__PURE__ */ jsx67("span", { className: "fd-rm-dot " + (item.implemented ? "is-shipped" : item.status === "next" ? "is-next" : "") }),
8371
- /* @__PURE__ */ jsxs61("div", { className: "fd-rm-date", children: [
8562
+ /* @__PURE__ */ jsxs62("div", { className: "fd-rm-row", children: [
8563
+ /* @__PURE__ */ jsx68("span", { className: "fd-rm-dot " + (item.implemented ? "is-shipped" : item.status === "next" ? "is-next" : "") }),
8564
+ /* @__PURE__ */ jsxs62("div", { className: "fd-rm-date", children: [
8372
8565
  fmtDate(item.date),
8373
- /* @__PURE__ */ jsx67("br", {}),
8374
- /* @__PURE__ */ jsx67("span", { style: { opacity: 0.75 }, children: item.implemented ? "shipped" : "phase " + item.phase })
8566
+ /* @__PURE__ */ jsx68("br", {}),
8567
+ /* @__PURE__ */ jsx68("span", { style: { opacity: 0.75 }, children: item.implemented ? "shipped" : "phase " + item.phase })
8375
8568
  ] }),
8376
- /* @__PURE__ */ jsx67(RoadmapCard, { item, byKey, onOpenFlag })
8569
+ /* @__PURE__ */ jsx68(RoadmapCard, { item, byKey, onOpenFlag })
8377
8570
  ] })
8378
8571
  ] }, item.key);
8379
8572
  }),
8380
- !items.length ? /* @__PURE__ */ jsx67("p", { className: "fd-body-sm fd-muted", children: "Nothing matches that filter." }) : null
8573
+ !items.length ? /* @__PURE__ */ jsx68("p", { className: "fd-body-sm fd-muted", children: "Nothing matches that filter." }) : null
8381
8574
  ] }) }) }),
8382
- /* @__PURE__ */ jsxs61("p", { className: "fd-body-sm fd-muted", style: { margin: 0 }, children: [
8575
+ /* @__PURE__ */ jsxs62("p", { className: "fd-body-sm fd-muted", style: { margin: 0 }, children: [
8383
8576
  "Derived from the feature-flag registry \u2014 each entry's status is its flag's ",
8384
- /* @__PURE__ */ jsx67("code", { className: "fd-mono", children: "implemented" }),
8577
+ /* @__PURE__ */ jsx68("code", { className: "fd-mono", children: "implemented" }),
8385
8578
  " field, so this page cannot drift from what the apps actually do."
8386
8579
  ] })
8387
8580
  ] });
8388
8581
  }
8389
8582
 
8390
8583
  // src/components/platform/ComingSoon.tsx
8391
- import * as React45 from "react";
8584
+ import * as React46 from "react";
8392
8585
  import { createPortal as createPortal5 } from "react-dom";
8393
- import { Fragment as Fragment19, jsx as jsx68, jsxs as jsxs62 } from "react/jsx-runtime";
8586
+ import { Fragment as Fragment20, jsx as jsx69, jsxs as jsxs63 } from "react/jsx-runtime";
8394
8587
  var BYPASS_STORE = "fd.soon.bypass.v1";
8395
8588
  function readBypassed() {
8396
8589
  try {
@@ -8406,8 +8599,8 @@ function writeBypassed(list) {
8406
8599
  }
8407
8600
  }
8408
8601
  function useBypass(key) {
8409
- const [on, setOn] = React45.useState(() => !!key && readBypassed().indexOf(key) >= 0);
8410
- React45.useEffect(() => {
8602
+ const [on, setOn] = React46.useState(() => !!key && readBypassed().indexOf(key) >= 0);
8603
+ React46.useEffect(() => {
8411
8604
  setOn(!!key && readBypassed().indexOf(key) >= 0);
8412
8605
  }, [key]);
8413
8606
  const set = (next) => {
@@ -8420,43 +8613,43 @@ function useBypass(key) {
8420
8613
  return [on, set];
8421
8614
  }
8422
8615
  function SoonCard({ label, detail, backend, eta, effort, onRoadmap, allowed, onBypass }) {
8423
- return /* @__PURE__ */ jsxs62(Fragment19, { children: [
8424
- /* @__PURE__ */ jsxs62("span", { className: "fd-soon-badge", children: [
8425
- /* @__PURE__ */ jsx68("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" }),
8616
+ return /* @__PURE__ */ jsxs63(Fragment20, { children: [
8617
+ /* @__PURE__ */ jsxs63("span", { className: "fd-soon-badge", children: [
8618
+ /* @__PURE__ */ jsx69("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" }),
8426
8619
  label
8427
8620
  ] }),
8428
- detail ? /* @__PURE__ */ jsx68("span", { className: "fd-soon-detail", children: detail }) : null,
8429
- backend ? /* @__PURE__ */ jsxs62("span", { className: "fd-soon-backend", children: [
8430
- /* @__PURE__ */ jsx68("span", { className: "fd-overline", children: "Needs" }),
8621
+ detail ? /* @__PURE__ */ jsx69("span", { className: "fd-soon-detail", children: detail }) : null,
8622
+ backend ? /* @__PURE__ */ jsxs63("span", { className: "fd-soon-backend", children: [
8623
+ /* @__PURE__ */ jsx69("span", { className: "fd-overline", children: "Needs" }),
8431
8624
  " ",
8432
8625
  backend
8433
8626
  ] }) : null,
8434
- eta || effort || onRoadmap ? /* @__PURE__ */ jsxs62("span", { className: "fd-soon-meta", children: [
8435
- eta ? /* @__PURE__ */ jsxs62("span", { children: [
8436
- /* @__PURE__ */ jsx68("i", { className: "ph ph-calendar-blank", "aria-hidden": "true" }),
8627
+ eta || effort || onRoadmap ? /* @__PURE__ */ jsxs63("span", { className: "fd-soon-meta", children: [
8628
+ eta ? /* @__PURE__ */ jsxs63("span", { children: [
8629
+ /* @__PURE__ */ jsx69("i", { className: "ph ph-calendar-blank", "aria-hidden": "true" }),
8437
8630
  " ",
8438
8631
  eta
8439
8632
  ] }) : null,
8440
- effort ? /* @__PURE__ */ jsxs62("span", { children: [
8441
- /* @__PURE__ */ jsx68("i", { className: "ph ph-hourglass-medium", "aria-hidden": "true" }),
8633
+ effort ? /* @__PURE__ */ jsxs63("span", { children: [
8634
+ /* @__PURE__ */ jsx69("i", { className: "ph ph-hourglass-medium", "aria-hidden": "true" }),
8442
8635
  " ",
8443
8636
  effort
8444
8637
  ] }) : null,
8445
- onRoadmap ? /* @__PURE__ */ jsxs62("button", { type: "button", className: "fd-soon-link", onClick: onRoadmap, children: [
8638
+ onRoadmap ? /* @__PURE__ */ jsxs63("button", { type: "button", className: "fd-soon-link", onClick: onRoadmap, children: [
8446
8639
  "See the roadmap ",
8447
- /* @__PURE__ */ jsx68("i", { className: "ph ph-arrow-right", "aria-hidden": "true" })
8640
+ /* @__PURE__ */ jsx69("i", { className: "ph ph-arrow-right", "aria-hidden": "true" })
8448
8641
  ] }) : null
8449
8642
  ] }) : null,
8450
- allowed ? /* @__PURE__ */ jsxs62("button", { type: "button", className: "fd-soon-view", onClick: onBypass, children: [
8451
- /* @__PURE__ */ jsx68("i", { className: "ph ph-eye", "aria-hidden": "true" }),
8643
+ allowed ? /* @__PURE__ */ jsxs63("button", { type: "button", className: "fd-soon-view", onClick: onBypass, children: [
8644
+ /* @__PURE__ */ jsx69("i", { className: "ph ph-eye", "aria-hidden": "true" }),
8452
8645
  " View and use it anyway"
8453
8646
  ] }) : null
8454
8647
  ] });
8455
8648
  }
8456
8649
  function useHoverCard(open) {
8457
- const anchor = React45.useRef(null);
8458
- const [pos, setPos] = React45.useState(null);
8459
- React45.useLayoutEffect(() => {
8650
+ const anchor = React46.useRef(null);
8651
+ const [pos, setPos] = React46.useState(null);
8652
+ React46.useLayoutEffect(() => {
8460
8653
  if (!open || !anchor.current) {
8461
8654
  setPos(null);
8462
8655
  return;
@@ -8508,9 +8701,9 @@ function ComingSoon({
8508
8701
  const tip = [label, detail, backend ? "Needs " + backend : null, eta ? "ETA " + eta : null, effort].filter(Boolean).join(" \xB7 ");
8509
8702
  if (inline) {
8510
8703
  if (allowed && bypassed) {
8511
- return /* @__PURE__ */ jsxs62("span", { className: ["fd-soon-inline-on", className].filter(Boolean).join(" "), ...rest, children: [
8704
+ return /* @__PURE__ */ jsxs63("span", { className: ["fd-soon-inline-on", className].filter(Boolean).join(" "), ...rest, children: [
8512
8705
  children,
8513
- /* @__PURE__ */ jsx68(
8706
+ /* @__PURE__ */ jsx69(
8514
8707
  "button",
8515
8708
  {
8516
8709
  type: "button",
@@ -8518,12 +8711,12 @@ function ComingSoon({
8518
8711
  title: "Unwired \u2014 writes go to the simulated backend. " + tip + " Click to re-blur.",
8519
8712
  onClick: () => setBypassed(false),
8520
8713
  "aria-label": "Re-blur this unwired feature",
8521
- children: /* @__PURE__ */ jsx68("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" })
8714
+ children: /* @__PURE__ */ jsx69("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" })
8522
8715
  }
8523
8716
  )
8524
8717
  ] });
8525
8718
  }
8526
- return /* @__PURE__ */ jsx68(
8719
+ return /* @__PURE__ */ jsx69(
8527
8720
  InlineSoon,
8528
8721
  {
8529
8722
  label,
@@ -8543,20 +8736,20 @@ function ComingSoon({
8543
8736
  );
8544
8737
  }
8545
8738
  if (allowed && bypassed) {
8546
- return /* @__PURE__ */ jsxs62("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 14 }, ...rest, children: [
8547
- /* @__PURE__ */ jsxs62("div", { className: "fd-soon-bar", role: "status", children: [
8548
- /* @__PURE__ */ jsxs62("span", { className: "fd-soon-badge", children: [
8549
- /* @__PURE__ */ jsx68("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" }),
8739
+ return /* @__PURE__ */ jsxs63("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 14 }, ...rest, children: [
8740
+ /* @__PURE__ */ jsxs63("div", { className: "fd-soon-bar", role: "status", children: [
8741
+ /* @__PURE__ */ jsxs63("span", { className: "fd-soon-badge", children: [
8742
+ /* @__PURE__ */ jsx69("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" }),
8550
8743
  "Unwired feature \u2014 you are using it anyway"
8551
8744
  ] }),
8552
- /* @__PURE__ */ jsx68("span", { className: "fd-soon-bar-detail", children: "Every action here writes to the simulated backend, so nothing you do persists beyond this session." }),
8553
- /* @__PURE__ */ jsxs62("span", { className: "fd-soon-bar-actions", children: [
8554
- onRoadmap ? /* @__PURE__ */ jsxs62("button", { type: "button", className: "fd-soon-link", onClick: onRoadmap, children: [
8745
+ /* @__PURE__ */ jsx69("span", { className: "fd-soon-bar-detail", children: "Every action here writes to the simulated backend, so nothing you do persists beyond this session." }),
8746
+ /* @__PURE__ */ jsxs63("span", { className: "fd-soon-bar-actions", children: [
8747
+ onRoadmap ? /* @__PURE__ */ jsxs63("button", { type: "button", className: "fd-soon-link", onClick: onRoadmap, children: [
8555
8748
  "Roadmap ",
8556
- /* @__PURE__ */ jsx68("i", { className: "ph ph-arrow-right", "aria-hidden": "true" })
8749
+ /* @__PURE__ */ jsx69("i", { className: "ph ph-arrow-right", "aria-hidden": "true" })
8557
8750
  ] }) : null,
8558
- /* @__PURE__ */ jsxs62("button", { type: "button", className: "fd-soon-link", onClick: () => setBypassed(false), children: [
8559
- /* @__PURE__ */ jsx68("i", { className: "ph ph-eye-slash", "aria-hidden": "true" }),
8751
+ /* @__PURE__ */ jsxs63("button", { type: "button", className: "fd-soon-link", onClick: () => setBypassed(false), children: [
8752
+ /* @__PURE__ */ jsx69("i", { className: "ph ph-eye-slash", "aria-hidden": "true" }),
8560
8753
  " Re-blur"
8561
8754
  ] })
8562
8755
  ] })
@@ -8564,10 +8757,10 @@ function ComingSoon({
8564
8757
  children
8565
8758
  ] });
8566
8759
  }
8567
- return /* @__PURE__ */ jsxs62("div", { className: ["fd-soon", className].filter(Boolean).join(" "), style: minHeight ? { minHeight } : void 0, ...rest, children: [
8568
- /* @__PURE__ */ jsx68("div", { className: "fd-soon-under", style: { filter: "blur(" + blur + "px) saturate(.62)" }, ...{ inert: "" }, "aria-hidden": "true", children }),
8569
- /* @__PURE__ */ jsx68("div", { className: "fd-soon-veil" }),
8570
- /* @__PURE__ */ jsx68("div", { className: "fd-soon-note", role: "note", children: /* @__PURE__ */ jsx68(
8760
+ return /* @__PURE__ */ jsxs63("div", { className: ["fd-soon", className].filter(Boolean).join(" "), style: minHeight ? { minHeight } : void 0, ...rest, children: [
8761
+ /* @__PURE__ */ jsx69("div", { className: "fd-soon-under", style: { filter: "blur(" + blur + "px) saturate(.62)" }, ...{ inert: "" }, "aria-hidden": "true", children }),
8762
+ /* @__PURE__ */ jsx69("div", { className: "fd-soon-veil" }),
8763
+ /* @__PURE__ */ jsx69("div", { className: "fd-soon-note", role: "note", children: /* @__PURE__ */ jsx69(
8571
8764
  SoonCard,
8572
8765
  {
8573
8766
  label,
@@ -8583,10 +8776,10 @@ function ComingSoon({
8583
8776
  ] });
8584
8777
  }
8585
8778
  function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, onBypass, blur, tip, className, rest, children }) {
8586
- const [open, setOpen] = React45.useState(false);
8779
+ const [open, setOpen] = React46.useState(false);
8587
8780
  const [anchor, pos] = useHoverCard(open);
8588
8781
  const zIndex = useOverlayLayer(open);
8589
- const close = React45.useRef(null);
8782
+ const close = React46.useRef(null);
8590
8783
  const show = () => {
8591
8784
  if (close.current) {
8592
8785
  clearTimeout(close.current);
@@ -8602,10 +8795,10 @@ function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, o
8602
8795
  setOpen(false);
8603
8796
  }, 140);
8604
8797
  };
8605
- React45.useEffect(() => () => {
8798
+ React46.useEffect(() => () => {
8606
8799
  if (close.current) clearTimeout(close.current);
8607
8800
  }, []);
8608
- return /* @__PURE__ */ jsxs62(
8801
+ return /* @__PURE__ */ jsxs63(
8609
8802
  "span",
8610
8803
  {
8611
8804
  ref: anchor,
@@ -8616,8 +8809,8 @@ function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, o
8616
8809
  onBlur: hide,
8617
8810
  ...rest,
8618
8811
  children: [
8619
- /* @__PURE__ */ jsx68("span", { className: "fd-soon-under", style: { filter: "blur(" + Math.min(blur, 1.1) + "px) saturate(.66)" }, ...{ inert: "" }, "aria-hidden": "true", children }),
8620
- /* @__PURE__ */ jsx68(
8812
+ /* @__PURE__ */ jsx69("span", { className: "fd-soon-under", style: { filter: "blur(" + Math.min(blur, 1.1) + "px) saturate(.66)" }, ...{ inert: "" }, "aria-hidden": "true", children }),
8813
+ /* @__PURE__ */ jsx69(
8621
8814
  "button",
8622
8815
  {
8623
8816
  type: "button",
@@ -8628,11 +8821,11 @@ function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, o
8628
8821
  onFocus: show,
8629
8822
  onBlur: hide,
8630
8823
  onClick: () => open ? setOpen(false) : show(),
8631
- children: /* @__PURE__ */ jsx68("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" })
8824
+ children: /* @__PURE__ */ jsx69("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" })
8632
8825
  }
8633
8826
  ),
8634
8827
  open && pos ? createPortal5(
8635
- /* @__PURE__ */ jsx68(LayerProvider, { zIndex, children: /* @__PURE__ */ jsx68(
8828
+ /* @__PURE__ */ jsx69(LayerProvider, { zIndex, children: /* @__PURE__ */ jsx69(
8636
8829
  "div",
8637
8830
  {
8638
8831
  className: "fd-soon-note fd-soon-hovercard",
@@ -8640,7 +8833,7 @@ function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, o
8640
8833
  style: { position: "fixed", left: pos.left, top: pos.top, bottom: pos.bottom, width: pos.width, zIndex },
8641
8834
  onMouseEnter: show,
8642
8835
  onMouseLeave: hide,
8643
- children: /* @__PURE__ */ jsx68(
8836
+ children: /* @__PURE__ */ jsx69(
8644
8837
  SoonCard,
8645
8838
  {
8646
8839
  label,
@@ -8670,10 +8863,10 @@ function formatEta(iso2) {
8670
8863
  var FormatEta = formatEta;
8671
8864
 
8672
8865
  // src/components/platform/Gate.tsx
8673
- import { jsx as jsx69, jsxs as jsxs63 } from "react/jsx-runtime";
8866
+ import { jsx as jsx70, jsxs as jsxs64 } from "react/jsx-runtime";
8674
8867
  function PermissionDenied({ permission, title, detail, compact: compact3 = false, className = "", ...rest }) {
8675
8868
  const need = Array.isArray(permission) ? permission : [permission].filter(Boolean);
8676
- return /* @__PURE__ */ jsxs63(
8869
+ return /* @__PURE__ */ jsxs64(
8677
8870
  "div",
8678
8871
  {
8679
8872
  className: ["fd-stack", className].filter(Boolean).join(" "),
@@ -8689,14 +8882,14 @@ function PermissionDenied({ permission, title, detail, compact: compact3 = false
8689
8882
  },
8690
8883
  ...rest,
8691
8884
  children: [
8692
- /* @__PURE__ */ jsxs63("span", { className: "fd-row", style: { gap: 8 }, children: [
8693
- /* @__PURE__ */ jsx69("i", { className: "ph ph-lock-simple", style: { fontSize: 16, color: "var(--text-muted)" }, "aria-hidden": "true" }),
8694
- /* @__PURE__ */ jsx69("span", { className: compact3 ? "fd-label-lg" : "fd-h3", children: title || "You do not have access to this" })
8885
+ /* @__PURE__ */ jsxs64("span", { className: "fd-row", style: { gap: 8 }, children: [
8886
+ /* @__PURE__ */ jsx70("i", { className: "ph ph-lock-simple", style: { fontSize: 16, color: "var(--text-muted)" }, "aria-hidden": "true" }),
8887
+ /* @__PURE__ */ jsx70("span", { className: compact3 ? "fd-label-lg" : "fd-h3", children: title || "You do not have access to this" })
8695
8888
  ] }),
8696
- /* @__PURE__ */ jsx69("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." }),
8697
- need.length ? /* @__PURE__ */ jsxs63("span", { className: "fd-row", style: { gap: 6, flexWrap: "wrap" }, children: [
8698
- /* @__PURE__ */ jsx69("span", { className: "fd-overline fd-muted", children: "Requires" }),
8699
- need.map((p) => /* @__PURE__ */ jsx69("code", { className: "fd-mono", style: {
8889
+ /* @__PURE__ */ jsx70("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." }),
8890
+ need.length ? /* @__PURE__ */ jsxs64("span", { className: "fd-row", style: { gap: 6, flexWrap: "wrap" }, children: [
8891
+ /* @__PURE__ */ jsx70("span", { className: "fd-overline fd-muted", children: "Requires" }),
8892
+ need.map((p) => /* @__PURE__ */ jsx70("code", { className: "fd-mono", style: {
8700
8893
  fontSize: 11.5,
8701
8894
  padding: "2px 7px",
8702
8895
  borderRadius: 5,
@@ -8717,7 +8910,7 @@ function Gate({ perm, anyOf, role, silent = false, fallback, compact: compact3 =
8717
8910
  if (ok) return children;
8718
8911
  if (fallback !== void 0) return fallback;
8719
8912
  if (silent) return null;
8720
- return /* @__PURE__ */ jsx69(PermissionDenied, { permission: perm || anyOf, compact: compact3 });
8913
+ return /* @__PURE__ */ jsx70(PermissionDenied, { permission: perm || anyOf, compact: compact3 });
8721
8914
  }
8722
8915
  function FeatureGate({
8723
8916
  flag,
@@ -8740,7 +8933,7 @@ function FeatureGate({
8740
8933
  const f = SessionKit.findFlag(flag) || {};
8741
8934
  const missing = rt.missing || [];
8742
8935
  const canBypass = bypassPerm === null ? false : !bypassPerm || can2(bypassPerm);
8743
- return /* @__PURE__ */ jsx69(
8936
+ return /* @__PURE__ */ jsx70(
8744
8937
  ComingSoon,
8745
8938
  {
8746
8939
  label: label || (variant === "inline" ? f.label || "Not wired yet" : "Designed \u2014 backend not wired yet"),
@@ -8761,26 +8954,26 @@ function FeatureGate({
8761
8954
  function PermissionHint({ perm, children }) {
8762
8955
  const { can: can2 } = useSessionContext();
8763
8956
  if (can2(perm)) return children;
8764
- return /* @__PURE__ */ jsx69(
8957
+ return /* @__PURE__ */ jsx70(
8765
8958
  "span",
8766
8959
  {
8767
8960
  title: "Requires " + (Array.isArray(perm) ? perm.join(", ") : perm),
8768
8961
  style: { display: "inline-flex", opacity: 0.45, cursor: "not-allowed" },
8769
8962
  "aria-disabled": "true",
8770
- children: /* @__PURE__ */ jsx69("span", { style: { pointerEvents: "none" }, children })
8963
+ children: /* @__PURE__ */ jsx70("span", { style: { pointerEvents: "none" }, children })
8771
8964
  }
8772
8965
  );
8773
8966
  }
8774
8967
 
8775
8968
  // src/components/platform/ModeSwitch.tsx
8776
- import * as React46 from "react";
8777
- import { Fragment as Fragment20, jsx as jsx70, jsxs as jsxs64 } from "react/jsx-runtime";
8969
+ import * as React47 from "react";
8970
+ import { Fragment as Fragment21, jsx as jsx71, jsxs as jsxs65 } from "react/jsx-runtime";
8778
8971
  function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog, onOpenSpec, summary }) {
8779
8972
  const mode2 = useRuntimeMode();
8780
- const [open, setOpen] = React46.useState(false);
8973
+ const [open, setOpen] = React47.useState(false);
8781
8974
  const zIndex = useOverlayLayer(open);
8782
- const ref = React46.useRef(null);
8783
- React46.useEffect(() => {
8975
+ const ref = React47.useRef(null);
8976
+ React47.useEffect(() => {
8784
8977
  if (!open) return;
8785
8978
  const away = (e) => {
8786
8979
  if (ref.current && !ref.current.contains(e.target)) setOpen(false);
@@ -8802,8 +8995,8 @@ function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog
8802
8995
  RuntimeKit.setMode(next);
8803
8996
  setOpen(false);
8804
8997
  };
8805
- return /* @__PURE__ */ jsxs64("span", { style: { position: "relative", display: "inline-flex" }, ref, children: [
8806
- /* @__PURE__ */ jsxs64(
8998
+ return /* @__PURE__ */ jsxs65("span", { style: { position: "relative", display: "inline-flex" }, ref, children: [
8999
+ /* @__PURE__ */ jsxs65(
8807
9000
  "button",
8808
9001
  {
8809
9002
  type: "button",
@@ -8813,29 +9006,29 @@ function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog
8813
9006
  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.",
8814
9007
  className: "fd-mode-btn" + (test ? " is-test" : "") + (open ? " is-open" : ""),
8815
9008
  children: [
8816
- /* @__PURE__ */ jsx70("i", { className: "ph " + (test ? "ph-flask" : "ph-lightning"), style: { fontSize: 17 } }),
8817
- test && requestCount ? /* @__PURE__ */ jsx70("span", { className: "fd-mono fd-mode-count", children: requestCount > 99 ? "99+" : requestCount }, requestCount) : null
9009
+ /* @__PURE__ */ jsx71("i", { className: "ph " + (test ? "ph-flask" : "ph-lightning"), style: { fontSize: 17 } }),
9010
+ test && requestCount ? /* @__PURE__ */ jsx71("span", { className: "fd-mono fd-mode-count", children: requestCount > 99 ? "99+" : requestCount }, requestCount) : null
8818
9011
  ]
8819
9012
  }
8820
9013
  ),
8821
- open ? /* @__PURE__ */ jsx70(LayerProvider, { zIndex, children: /* @__PURE__ */ jsxs64("span", { className: "fd-view-enter fd-mode-pop", style: { zIndex }, children: [
8822
- /* @__PURE__ */ jsxs64("span", { className: "fd-row", style: { gap: 10, padding: "12px 14px", borderBottom: "1px solid var(--border)" }, children: [
8823
- /* @__PURE__ */ jsxs64("span", { className: "fd-badge " + (test ? "fd-badge-warning" : "fd-badge-neutral"), children: [
8824
- /* @__PURE__ */ jsx70("i", { className: "ph " + (test ? "ph-flask" : "ph-lightning"), "aria-hidden": "true" }),
9014
+ open ? /* @__PURE__ */ jsx71(LayerProvider, { zIndex, children: /* @__PURE__ */ jsxs65("span", { className: "fd-view-enter fd-mode-pop", style: { zIndex }, children: [
9015
+ /* @__PURE__ */ jsxs65("span", { className: "fd-row", style: { gap: 10, padding: "12px 14px", borderBottom: "1px solid var(--border)" }, children: [
9016
+ /* @__PURE__ */ jsxs65("span", { className: "fd-badge " + (test ? "fd-badge-warning" : "fd-badge-neutral"), children: [
9017
+ /* @__PURE__ */ jsx71("i", { className: "ph " + (test ? "ph-flask" : "ph-lightning"), "aria-hidden": "true" }),
8825
9018
  test ? "Test mode" : "Live mode"
8826
9019
  ] }),
8827
- test ? /* @__PURE__ */ jsxs64("span", { className: "fd-body-sm fd-muted fd-mono", children: [
9020
+ test ? /* @__PURE__ */ jsxs65("span", { className: "fd-body-sm fd-muted fd-mono", children: [
8828
9021
  requestCount,
8829
9022
  " simulated request",
8830
9023
  requestCount === 1 ? "" : "s"
8831
9024
  ] }) : null,
8832
- /* @__PURE__ */ jsx70("span", { style: { flex: 1 } }),
8833
- test && onClearLog ? /* @__PURE__ */ jsx70("button", { type: "button", className: "fd-soon-link", onClick: onClearLog, children: "Clear" }) : null
9025
+ /* @__PURE__ */ jsx71("span", { style: { flex: 1 } }),
9026
+ test && onClearLog ? /* @__PURE__ */ jsx71("button", { type: "button", className: "fd-soon-link", onClick: onClearLog, children: "Clear" }) : null
8834
9027
  ] }),
8835
- /* @__PURE__ */ jsxs64("span", { style: { display: "block", padding: "12px 14px", borderBottom: "1px solid var(--border)" }, children: [
8836
- /* @__PURE__ */ jsx70("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." }),
8837
- /* @__PURE__ */ jsxs64("span", { className: "fd-row", style: { gap: 8, marginTop: 10, flexWrap: "wrap" }, children: [
8838
- /* @__PURE__ */ jsxs64("span", { className: "fd-body-sm fd-muted fd-mono", children: [
9028
+ /* @__PURE__ */ jsxs65("span", { style: { display: "block", padding: "12px 14px", borderBottom: "1px solid var(--border)" }, children: [
9029
+ /* @__PURE__ */ jsx71("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." }),
9030
+ /* @__PURE__ */ jsxs65("span", { className: "fd-row", style: { gap: 8, marginTop: 10, flexWrap: "wrap" }, children: [
9031
+ /* @__PURE__ */ jsxs65("span", { className: "fd-body-sm fd-muted fd-mono", children: [
8839
9032
  s.endpointsWired,
8840
9033
  " endpoint",
8841
9034
  s.endpointsWired === 1 ? "" : "s",
@@ -8845,58 +9038,58 @@ function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog
8845
9038
  s.total,
8846
9039
  " features complete"
8847
9040
  ] }),
8848
- onOpenSpec ? /* @__PURE__ */ jsxs64(Fragment20, { children: [
8849
- /* @__PURE__ */ jsx70("span", { style: { flex: 1 } }),
8850
- /* @__PURE__ */ jsxs64("button", { type: "button", className: "fd-soon-link", onClick: () => {
9041
+ onOpenSpec ? /* @__PURE__ */ jsxs65(Fragment21, { children: [
9042
+ /* @__PURE__ */ jsx71("span", { style: { flex: 1 } }),
9043
+ /* @__PURE__ */ jsxs65("button", { type: "button", className: "fd-soon-link", onClick: () => {
8851
9044
  setOpen(false);
8852
9045
  onOpenSpec();
8853
9046
  }, children: [
8854
9047
  "API spec ",
8855
- /* @__PURE__ */ jsx70("i", { className: "ph ph-arrow-right", "aria-hidden": "true" })
9048
+ /* @__PURE__ */ jsx71("i", { className: "ph ph-arrow-right", "aria-hidden": "true" })
8856
9049
  ] })
8857
9050
  ] }) : null
8858
9051
  ] })
8859
9052
  ] }),
8860
- /* @__PURE__ */ jsxs64("span", { className: "fd-mode-choice", children: [
8861
- /* @__PURE__ */ jsxs64("button", { type: "button", className: "fd-mode-opt" + (!test ? " is-on" : ""), onClick: () => go("live"), children: [
8862
- /* @__PURE__ */ jsx70("i", { className: "ph ph-lightning", "aria-hidden": "true" }),
8863
- /* @__PURE__ */ jsxs64("span", { className: "fd-mode-opt-text", children: [
8864
- /* @__PURE__ */ jsx70("span", { className: "fd-mode-opt-title", children: "Live mode" }),
8865
- /* @__PURE__ */ jsx70("span", { className: "fd-mode-opt-desc", children: "Incomplete features under construction" })
9053
+ /* @__PURE__ */ jsxs65("span", { className: "fd-mode-choice", children: [
9054
+ /* @__PURE__ */ jsxs65("button", { type: "button", className: "fd-mode-opt" + (!test ? " is-on" : ""), onClick: () => go("live"), children: [
9055
+ /* @__PURE__ */ jsx71("i", { className: "ph ph-lightning", "aria-hidden": "true" }),
9056
+ /* @__PURE__ */ jsxs65("span", { className: "fd-mode-opt-text", children: [
9057
+ /* @__PURE__ */ jsx71("span", { className: "fd-mode-opt-title", children: "Live mode" }),
9058
+ /* @__PURE__ */ jsx71("span", { className: "fd-mode-opt-desc", children: "Incomplete features under construction" })
8866
9059
  ] }),
8867
- !test ? /* @__PURE__ */ jsx70("i", { className: "ph ph-check", "aria-hidden": "true" }) : null
9060
+ !test ? /* @__PURE__ */ jsx71("i", { className: "ph ph-check", "aria-hidden": "true" }) : null
8868
9061
  ] }),
8869
- /* @__PURE__ */ jsxs64("button", { type: "button", className: "fd-mode-opt" + (test ? " is-on" : ""), onClick: () => go("test"), children: [
8870
- /* @__PURE__ */ jsx70("i", { className: "ph ph-flask", "aria-hidden": "true" }),
8871
- /* @__PURE__ */ jsxs64("span", { className: "fd-mode-opt-text", children: [
8872
- /* @__PURE__ */ jsx70("span", { className: "fd-mode-opt-title", children: "Test mode" }),
8873
- /* @__PURE__ */ jsx70("span", { className: "fd-mode-opt-desc", children: "Everything usable, all data simulated" })
9062
+ /* @__PURE__ */ jsxs65("button", { type: "button", className: "fd-mode-opt" + (test ? " is-on" : ""), onClick: () => go("test"), children: [
9063
+ /* @__PURE__ */ jsx71("i", { className: "ph ph-flask", "aria-hidden": "true" }),
9064
+ /* @__PURE__ */ jsxs65("span", { className: "fd-mode-opt-text", children: [
9065
+ /* @__PURE__ */ jsx71("span", { className: "fd-mode-opt-title", children: "Test mode" }),
9066
+ /* @__PURE__ */ jsx71("span", { className: "fd-mode-opt-desc", children: "Everything usable, all data simulated" })
8874
9067
  ] }),
8875
- test ? /* @__PURE__ */ jsx70("i", { className: "ph ph-check", "aria-hidden": "true" }) : null
9068
+ test ? /* @__PURE__ */ jsx71("i", { className: "ph ph-check", "aria-hidden": "true" }) : null
8876
9069
  ] })
8877
9070
  ] }),
8878
- test && renderLog ? /* @__PURE__ */ jsx70("span", { style: { display: "block", maxHeight: 340, overflowY: "auto", borderTop: "1px solid var(--border)" }, children: renderLog() }) : null
9071
+ test && renderLog ? /* @__PURE__ */ jsx71("span", { style: { display: "block", maxHeight: 340, overflowY: "auto", borderTop: "1px solid var(--border)" }, children: renderLog() }) : null
8879
9072
  ] }) }) : null
8880
9073
  ] });
8881
9074
  }
8882
9075
  function TestModeBar({ onExit }) {
8883
9076
  const mode2 = useRuntimeMode();
8884
9077
  if (mode2 !== "test") return null;
8885
- return /* @__PURE__ */ jsxs64("div", { className: "fd-testbar", role: "status", children: [
8886
- /* @__PURE__ */ jsxs64("span", { className: "fd-badge fd-badge-warning", children: [
8887
- /* @__PURE__ */ jsx70("i", { className: "ph ph-flask", "aria-hidden": "true" }),
9078
+ return /* @__PURE__ */ jsxs65("div", { className: "fd-testbar", role: "status", children: [
9079
+ /* @__PURE__ */ jsxs65("span", { className: "fd-badge fd-badge-warning", children: [
9080
+ /* @__PURE__ */ jsx71("i", { className: "ph ph-flask", "aria-hidden": "true" }),
8888
9081
  "Test mode"
8889
9082
  ] }),
8890
- /* @__PURE__ */ jsx70("span", { className: "fd-testbar-detail", children: "Every feature is unlocked and every response is simulated \u2014 nothing here persists." }),
8891
- /* @__PURE__ */ jsxs64("button", { type: "button", className: "fd-soon-link", onClick: () => onExit ? onExit() : RuntimeKit.setMode("live"), children: [
8892
- /* @__PURE__ */ jsx70("i", { className: "ph ph-lightning", "aria-hidden": "true" }),
9083
+ /* @__PURE__ */ jsx71("span", { className: "fd-testbar-detail", children: "Every feature is unlocked and every response is simulated \u2014 nothing here persists." }),
9084
+ /* @__PURE__ */ jsxs65("button", { type: "button", className: "fd-soon-link", onClick: () => onExit ? onExit() : RuntimeKit.setMode("live"), children: [
9085
+ /* @__PURE__ */ jsx71("i", { className: "ph ph-lightning", "aria-hidden": "true" }),
8893
9086
  " Back to live mode"
8894
9087
  ] })
8895
9088
  ] });
8896
9089
  }
8897
9090
 
8898
9091
  // src/components/planner/ChannelMeta.tsx
8899
- import { jsx as jsx71, jsxs as jsxs65 } from "react/jsx-runtime";
9092
+ import { jsx as jsx72, jsxs as jsxs66 } from "react/jsx-runtime";
8900
9093
  var CHANNEL_WEIGHTS = {
8901
9094
  "OOH": 50,
8902
9095
  "DOOH": 50,
@@ -8949,9 +9142,9 @@ function ChannelTag({ channel, size = "md", showLabel = true, dot = false, weigh
8949
9142
  const m = ChannelMeta(channel);
8950
9143
  const wt = channelWeightOf(channel || "");
8951
9144
  if (dot) {
8952
- return /* @__PURE__ */ jsx71("span", { className: ["fd-chan-dot", className].filter(Boolean).join(" "), title: m.name, style: { background: m.color }, ...rest });
9145
+ return /* @__PURE__ */ jsx72("span", { className: ["fd-chan-dot", className].filter(Boolean).join(" "), title: m.name, style: { background: m.color }, ...rest });
8953
9146
  }
8954
- return /* @__PURE__ */ jsxs65(
9147
+ return /* @__PURE__ */ jsxs66(
8955
9148
  "span",
8956
9149
  {
8957
9150
  className: ["fd-chan", size === "sm" ? "fd-chan-sm" : "", className].filter(Boolean).join(" "),
@@ -8959,16 +9152,16 @@ function ChannelTag({ channel, size = "md", showLabel = true, dot = false, weigh
8959
9152
  style: { "--chan": m.color },
8960
9153
  ...rest,
8961
9154
  children: [
8962
- /* @__PURE__ */ jsx71("i", { className: "ph ph-" + m.icon, "aria-hidden": "true" }),
8963
- showLabel ? /* @__PURE__ */ jsx71("span", { className: "fd-chan-label", children: m.label }) : null,
8964
- weight ? /* @__PURE__ */ jsx71("span", { className: "fd-chan-weight", children: wt || 0 }) : null
9155
+ /* @__PURE__ */ jsx72("i", { className: "ph ph-" + m.icon, "aria-hidden": "true" }),
9156
+ showLabel ? /* @__PURE__ */ jsx72("span", { className: "fd-chan-label", children: m.label }) : null,
9157
+ weight ? /* @__PURE__ */ jsx72("span", { className: "fd-chan-weight", children: wt || 0 }) : null
8965
9158
  ]
8966
9159
  }
8967
9160
  );
8968
9161
  }
8969
9162
 
8970
9163
  // src/components/planner/SaturationDistribution.tsx
8971
- import { jsx as jsx72, jsxs as jsxs66 } from "react/jsx-runtime";
9164
+ import { jsx as jsx73, jsxs as jsxs67 } from "react/jsx-runtime";
8972
9165
  var BANDS2 = [
8973
9166
  { key: "weak", label: "Weak", n: 1, range: "< 50" },
8974
9167
  { key: "adequate", label: "Adequate", n: 2, range: "50\u2013100" },
@@ -8979,24 +9172,24 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
8979
9172
  const grouped = BANDS2.map((b) => ({ ...b, items: campuses.filter((c) => c.band === b.key) }));
8980
9173
  const tallest = Math.max(1, ...grouped.map((g) => g.items.length));
8981
9174
  const floor = BANDS2.find((b) => b.key === floorBand) || BANDS2[0];
8982
- return /* @__PURE__ */ jsxs66("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 16 }, children: [
8983
- /* @__PURE__ */ jsx72("div", { style: { display: "grid", gridTemplateColumns: "repeat(4,minmax(0,1fr))", gap: 12, alignItems: "end" }, children: grouped.map((g) => {
9175
+ return /* @__PURE__ */ jsxs67("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 16 }, children: [
9176
+ /* @__PURE__ */ jsx73("div", { style: { display: "grid", gridTemplateColumns: "repeat(4,minmax(0,1fr))", gap: 12, alignItems: "end" }, children: grouped.map((g) => {
8984
9177
  const mark = "var(--csi-" + g.n + "-mark)";
8985
9178
  const active = selectedBand === g.key;
8986
- return /* @__PURE__ */ jsxs66(
9179
+ return /* @__PURE__ */ jsxs67(
8987
9180
  "button",
8988
9181
  {
8989
9182
  type: "button",
8990
9183
  onClick: onSelectBand ? () => onSelectBand(active ? null : g.key) : void 0,
8991
9184
  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)" },
8992
9185
  children: [
8993
- /* @__PURE__ */ jsx72("span", { style: { display: "flex", flexDirection: "column-reverse", gap: 4, minHeight: tallest * 24, minWidth: 0 }, children: loading ? Array.from({ length: 3 }).map((_, i) => /* @__PURE__ */ jsx72("span", { className: "fd-skel", style: { height: 16, borderRadius: 4 } }, i)) : g.items.map((c) => (
9186
+ /* @__PURE__ */ jsx73("span", { style: { display: "flex", flexDirection: "column-reverse", gap: 4, minHeight: tallest * 24, minWidth: 0 }, children: loading ? Array.from({ length: 3 }).map((_, i) => /* @__PURE__ */ jsx73("span", { className: "fd-skel", style: { height: 16, borderRadius: 4 } }, i)) : g.items.map((c) => (
8994
9187
  // `overflow: hidden` + `white-space: nowrap` only clips once the span
8995
9188
  // actually HAS a bounded width to clip against (see the grid/flex
8996
9189
  // `minWidth: 0` chain above) — `textOverflow: ellipsis` then makes
8997
9190
  // that clip readable instead of a hard cut mid-letter; the full name
8998
9191
  // is still one hover away via `title`.
8999
- /* @__PURE__ */ jsx72(
9192
+ /* @__PURE__ */ jsx73(
9000
9193
  "span",
9001
9194
  {
9002
9195
  title: c.name + " \xB7 " + c.crp,
@@ -9006,13 +9199,13 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
9006
9199
  c.name
9007
9200
  )
9008
9201
  )) }),
9009
- /* @__PURE__ */ jsxs66("span", { className: "fd-row", style: { gap: 8, alignItems: "baseline" }, children: [
9010
- /* @__PURE__ */ jsx72("span", { className: "fd-num-hero", style: { fontSize: 30, color: g.items.length ? "var(--text)" : "var(--text-disabled)" }, children: loading ? "\u2013" : g.items.length }),
9011
- /* @__PURE__ */ jsx72("span", { className: "fd-meter", style: { gap: 2, color: mark }, "aria-hidden": "true", children: [1, 2, 3, 4].map((i) => /* @__PURE__ */ jsx72("span", { className: "fd-meter-seg" + (i <= g.n ? " is-on" : ""), style: { width: 4, height: 9 } }, i)) })
9202
+ /* @__PURE__ */ jsxs67("span", { className: "fd-row", style: { gap: 8, alignItems: "baseline" }, children: [
9203
+ /* @__PURE__ */ jsx73("span", { className: "fd-num-hero", style: { fontSize: 30, color: g.items.length ? "var(--text)" : "var(--text-disabled)" }, children: loading ? "\u2013" : g.items.length }),
9204
+ /* @__PURE__ */ jsx73("span", { className: "fd-meter", style: { gap: 2, color: mark }, "aria-hidden": "true", children: [1, 2, 3, 4].map((i) => /* @__PURE__ */ jsx73("span", { className: "fd-meter-seg" + (i <= g.n ? " is-on" : ""), style: { width: 4, height: 9 } }, i)) })
9012
9205
  ] }),
9013
- /* @__PURE__ */ jsxs66("span", { className: "fd-stack", style: { gap: 1 }, children: [
9014
- /* @__PURE__ */ jsx72("span", { className: "fd-label-lg", children: g.label }),
9015
- /* @__PURE__ */ jsxs66("span", { className: "fd-body-sm fd-muted", style: { fontSize: 11.5 }, children: [
9206
+ /* @__PURE__ */ jsxs67("span", { className: "fd-stack", style: { gap: 1 }, children: [
9207
+ /* @__PURE__ */ jsx73("span", { className: "fd-label-lg", children: g.label }),
9208
+ /* @__PURE__ */ jsxs67("span", { className: "fd-body-sm fd-muted", style: { fontSize: 11.5 }, children: [
9016
9209
  "CRP ",
9017
9210
  g.range
9018
9211
  ] })
@@ -9022,10 +9215,10 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
9022
9215
  g.key
9023
9216
  );
9024
9217
  }) }),
9025
- floorBand ? /* @__PURE__ */ jsxs66("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: [
9026
- /* @__PURE__ */ jsx72("span", { className: "fd-meter", style: { gap: 2, color: "var(--csi-" + floor.n + "-mark)" }, "aria-hidden": "true", children: [1, 2, 3, 4].map((i) => /* @__PURE__ */ jsx72("span", { className: "fd-meter-seg" + (i <= floor.n ? " is-on" : ""), style: { width: 5, height: 12 } }, i)) }),
9027
- /* @__PURE__ */ jsxs66("span", { className: "fd-body-sm fd-secondary", style: { flex: 1, minWidth: 240 }, children: [
9028
- /* @__PURE__ */ jsxs66("strong", { style: { color: "var(--text)" }, children: [
9218
+ floorBand ? /* @__PURE__ */ jsxs67("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: [
9219
+ /* @__PURE__ */ jsx73("span", { className: "fd-meter", style: { gap: 2, color: "var(--csi-" + floor.n + "-mark)" }, "aria-hidden": "true", children: [1, 2, 3, 4].map((i) => /* @__PURE__ */ jsx73("span", { className: "fd-meter-seg" + (i <= floor.n ? " is-on" : ""), style: { width: 5, height: 12 } }, i)) }),
9220
+ /* @__PURE__ */ jsxs67("span", { className: "fd-body-sm fd-secondary", style: { flex: 1, minWidth: 240 }, children: [
9221
+ /* @__PURE__ */ jsxs67("strong", { style: { color: "var(--text)" }, children: [
9029
9222
  "Plan floor ",
9030
9223
  floorScore
9031
9224
  ] }),
@@ -9036,8 +9229,8 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
9036
9229
  }
9037
9230
 
9038
9231
  // src/components/planner/MixGap.tsx
9039
- import * as React47 from "react";
9040
- import { Fragment as Fragment21, jsx as jsx73, jsxs as jsxs67 } from "react/jsx-runtime";
9232
+ import * as React48 from "react";
9233
+ import { Fragment as Fragment22, jsx as jsx74, jsxs as jsxs68 } from "react/jsx-runtime";
9041
9234
  var MIX_GAP_LAYOUT = {
9042
9235
  trackHeight: 30,
9043
9236
  barHeight: 20,
@@ -9051,19 +9244,19 @@ function mixGapOffset(value, max) {
9051
9244
  }
9052
9245
  function MixGap({ rows = [], loading = false, className = "" }) {
9053
9246
  const max = Math.max(1, ...rows.flatMap((r) => [r.target, r.realized]));
9054
- const [hover, setHover] = React47.useState(null);
9247
+ const [hover, setHover] = React48.useState(null);
9055
9248
  const toneOf = (gap) => gap >= -1 ? "ok" : gap >= -4 ? "warn" : "danger";
9056
9249
  const TONE = { ok: "var(--ok-solid)", warn: "var(--warn-solid)", danger: "var(--danger-solid)" };
9057
9250
  const { trackHeight, barHeight, targetWidth, labelGap } = MIX_GAP_LAYOUT;
9058
9251
  const barTop = (trackHeight - barHeight) / 2;
9059
- return /* @__PURE__ */ jsxs67("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 4 }, children: [
9060
- /* @__PURE__ */ jsxs67("div", { className: "fd-row", style: { gap: 16, justifyContent: "flex-end", paddingBottom: 6, flexWrap: "wrap" }, children: [
9061
- [["On target", TONE.ok], ["Close", TONE.warn], ["Short", TONE.danger]].map(([l, c]) => /* @__PURE__ */ jsxs67("span", { className: "fd-row fd-body-sm fd-muted", style: { gap: 6 }, children: [
9062
- /* @__PURE__ */ jsx73("span", { style: { width: 14, height: 9, borderRadius: 2, background: c } }),
9252
+ return /* @__PURE__ */ jsxs68("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 4 }, children: [
9253
+ /* @__PURE__ */ jsxs68("div", { className: "fd-row", style: { gap: 16, justifyContent: "flex-end", paddingBottom: 6, flexWrap: "wrap" }, children: [
9254
+ [["On target", TONE.ok], ["Close", TONE.warn], ["Short", TONE.danger]].map(([l, c]) => /* @__PURE__ */ jsxs68("span", { className: "fd-row fd-body-sm fd-muted", style: { gap: 6 }, children: [
9255
+ /* @__PURE__ */ jsx74("span", { style: { width: 14, height: 9, borderRadius: 2, background: c } }),
9063
9256
  l
9064
9257
  ] }, l)),
9065
- /* @__PURE__ */ jsxs67("span", { className: "fd-row fd-body-sm fd-muted", style: { gap: 6 }, children: [
9066
- /* @__PURE__ */ jsx73("span", { "data-mixgap-legend-target": "", style: { width: targetWidth, height: 16, borderRadius: 1, background: MIX_GAP_TARGET_STRIPE } }),
9258
+ /* @__PURE__ */ jsxs68("span", { className: "fd-row fd-body-sm fd-muted", style: { gap: 6 }, children: [
9259
+ /* @__PURE__ */ jsx74("span", { "data-mixgap-legend-target": "", style: { width: targetWidth, height: 16, borderRadius: 1, background: MIX_GAP_TARGET_STRIPE } }),
9067
9260
  "Target"
9068
9261
  ] })
9069
9262
  ] }),
@@ -9072,7 +9265,7 @@ function MixGap({ rows = [], loading = false, className = "" }) {
9072
9265
  const tone = toneOf(gap);
9073
9266
  const tip = "Realized " + r.realized + "% vs " + r.target + "% target" + (gap < -1 ? " \xB7 " + Math.abs(gap).toFixed(0) + " pts short" : gap > 1 ? " \xB7 " + gap.toFixed(0) + " pts over" : " \xB7 on target") + (r.note ? " \u2014 " + r.note : "");
9074
9267
  const labelLeft = r.realized > r.target ? `calc(${mixGapOffset(r.realized, max)} + ${labelGap}px)` : `calc(${mixGapOffset(r.target, max)} + ${targetWidth / 2 + labelGap}px)`;
9075
- return /* @__PURE__ */ jsxs67(
9268
+ return /* @__PURE__ */ jsxs68(
9076
9269
  "div",
9077
9270
  {
9078
9271
  className: "fd-row",
@@ -9080,15 +9273,15 @@ function MixGap({ rows = [], loading = false, className = "" }) {
9080
9273
  onMouseEnter: () => setHover(r.channel),
9081
9274
  onMouseLeave: () => setHover(null),
9082
9275
  children: [
9083
- /* @__PURE__ */ jsx73("span", { style: { width: 128, flex: "none" }, children: /* @__PURE__ */ jsx73(ChannelTag, { channel: r.channel, size: "sm" }) }),
9084
- /* @__PURE__ */ jsx73("span", { style: { position: "relative", flex: 1, height: trackHeight, minWidth: 120 }, children: loading ? /* @__PURE__ */ jsx73("span", { className: "fd-skel", style: { position: "absolute", left: 0, right: 0, top: barTop, height: barHeight, borderRadius: 3 } }) : /* @__PURE__ */ jsxs67(Fragment21, { children: [
9085
- /* @__PURE__ */ jsx73("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)" } }),
9086
- /* @__PURE__ */ jsx73("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 } }),
9087
- /* @__PURE__ */ jsxs67("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: [
9276
+ /* @__PURE__ */ jsx74("span", { style: { width: 128, flex: "none" }, children: /* @__PURE__ */ jsx74(ChannelTag, { channel: r.channel, size: "sm" }) }),
9277
+ /* @__PURE__ */ jsx74("span", { style: { position: "relative", flex: 1, height: trackHeight, minWidth: 120 }, children: loading ? /* @__PURE__ */ jsx74("span", { className: "fd-skel", style: { position: "absolute", left: 0, right: 0, top: barTop, height: barHeight, borderRadius: 3 } }) : /* @__PURE__ */ jsxs68(Fragment22, { children: [
9278
+ /* @__PURE__ */ jsx74("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)" } }),
9279
+ /* @__PURE__ */ jsx74("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 } }),
9280
+ /* @__PURE__ */ jsxs68("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: [
9088
9281
  r.realized,
9089
9282
  "%"
9090
9283
  ] }),
9091
- hover === r.channel ? /* @__PURE__ */ jsx73("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
9284
+ hover === r.channel ? /* @__PURE__ */ jsx74("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
9092
9285
  ] }) })
9093
9286
  ]
9094
9287
  },
@@ -9099,7 +9292,7 @@ function MixGap({ rows = [], loading = false, className = "" }) {
9099
9292
  }
9100
9293
 
9101
9294
  // src/components/planner/ChannelContribution.tsx
9102
- import { jsx as jsx74, jsxs as jsxs68 } from "react/jsx-runtime";
9295
+ import { jsx as jsx75, jsxs as jsxs69 } from "react/jsx-runtime";
9103
9296
  var money = (n) => "$" + Math.round(n).toLocaleString();
9104
9297
  function ChannelContribution({
9105
9298
  channels = [],
@@ -9115,9 +9308,9 @@ function ChannelContribution({
9115
9308
  const grand = total !== void 0 ? total : base + bonus;
9116
9309
  const pct = (v) => grand ? v / grand * 100 : 0;
9117
9310
  const spendTotal = channels.reduce((s, c) => s + Number(String(c.spend || 0).replace(/[^0-9.]/g, "")), 0);
9118
- return /* @__PURE__ */ jsxs68("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 16 }, children: [
9119
- loading ? /* @__PURE__ */ jsx74("span", { className: "fd-skel", style: { height: 34, borderRadius: "var(--r-sm)" } }) : /* @__PURE__ */ jsxs68("div", { className: "fd-row", style: { height: 34, borderRadius: "var(--r-sm)", overflow: "hidden", gap: 2, background: "var(--surface-3)" }, children: [
9120
- channels.map((c) => /* @__PURE__ */ jsx74(
9311
+ return /* @__PURE__ */ jsxs69("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 16 }, children: [
9312
+ loading ? /* @__PURE__ */ jsx75("span", { className: "fd-skel", style: { height: 34, borderRadius: "var(--r-sm)" } }) : /* @__PURE__ */ jsxs69("div", { className: "fd-row", style: { height: 34, borderRadius: "var(--r-sm)", overflow: "hidden", gap: 2, background: "var(--surface-3)" }, children: [
9313
+ channels.map((c) => /* @__PURE__ */ jsx75(
9121
9314
  "span",
9122
9315
  {
9123
9316
  title: c.name + " \xB7 " + c.crp.toFixed(1) + " CRP",
@@ -9126,7 +9319,7 @@ function ChannelContribution({
9126
9319
  },
9127
9320
  c.name
9128
9321
  )),
9129
- bonus > 0 ? /* @__PURE__ */ jsx74(
9322
+ bonus > 0 ? /* @__PURE__ */ jsx75(
9130
9323
  "span",
9131
9324
  {
9132
9325
  title: "Surround-sound bonus +" + bonusPct + "%",
@@ -9135,18 +9328,18 @@ function ChannelContribution({
9135
9328
  }
9136
9329
  ) : null
9137
9330
  ] }),
9138
- showTable ? /* @__PURE__ */ jsxs68("table", { className: "fd-table", style: { fontSize: "var(--body-sm-size)" }, children: [
9139
- /* @__PURE__ */ jsx74("thead", { children: /* @__PURE__ */ jsxs68("tr", { children: [
9140
- /* @__PURE__ */ jsx74("th", { style: { width: "34%" }, children: "Channel" }),
9141
- /* @__PURE__ */ jsx74("th", { style: { width: "16%" }, children: "Weight" }),
9142
- /* @__PURE__ */ jsx74("th", { className: "is-num", style: { width: "16%" }, children: "Spend" }),
9143
- /* @__PURE__ */ jsx74("th", { className: "is-num", style: { width: "17%" }, children: "CRP" }),
9144
- /* @__PURE__ */ jsx74("th", { className: "is-num", style: { width: "17%" }, children: "Share" })
9331
+ showTable ? /* @__PURE__ */ jsxs69("table", { className: "fd-table", style: { fontSize: "var(--body-sm-size)" }, children: [
9332
+ /* @__PURE__ */ jsx75("thead", { children: /* @__PURE__ */ jsxs69("tr", { children: [
9333
+ /* @__PURE__ */ jsx75("th", { style: { width: "34%" }, children: "Channel" }),
9334
+ /* @__PURE__ */ jsx75("th", { style: { width: "16%" }, children: "Weight" }),
9335
+ /* @__PURE__ */ jsx75("th", { className: "is-num", style: { width: "16%" }, children: "Spend" }),
9336
+ /* @__PURE__ */ jsx75("th", { className: "is-num", style: { width: "17%" }, children: "CRP" }),
9337
+ /* @__PURE__ */ jsx75("th", { className: "is-num", style: { width: "17%" }, children: "Share" })
9145
9338
  ] }) }),
9146
- /* @__PURE__ */ jsxs68("tbody", { children: [
9147
- channels.map((c) => /* @__PURE__ */ jsxs68("tr", { children: [
9148
- /* @__PURE__ */ jsx74("td", { children: /* @__PURE__ */ jsx74(ChannelTag, { channel: c.name, size: "sm" }) }),
9149
- /* @__PURE__ */ jsx74("td", { children: /* @__PURE__ */ jsx74(
9339
+ /* @__PURE__ */ jsxs69("tbody", { children: [
9340
+ channels.map((c) => /* @__PURE__ */ jsxs69("tr", { children: [
9341
+ /* @__PURE__ */ jsx75("td", { children: /* @__PURE__ */ jsx75(ChannelTag, { channel: c.name, size: "sm" }) }),
9342
+ /* @__PURE__ */ jsx75("td", { children: /* @__PURE__ */ jsx75(
9150
9343
  "span",
9151
9344
  {
9152
9345
  className: "fd-badge fd-badge-neutral",
@@ -9155,38 +9348,38 @@ function ChannelContribution({
9155
9348
  children: "weight " + (channelWeightOf(c.name) || 0)
9156
9349
  }
9157
9350
  ) }),
9158
- /* @__PURE__ */ jsx74("td", { className: "is-num", children: c.spend }),
9159
- /* @__PURE__ */ jsx74("td", { className: "is-num", children: c.crp.toFixed(1) }),
9160
- /* @__PURE__ */ jsxs68("td", { className: "is-num", children: [
9351
+ /* @__PURE__ */ jsx75("td", { className: "is-num", children: c.spend }),
9352
+ /* @__PURE__ */ jsx75("td", { className: "is-num", children: c.crp.toFixed(1) }),
9353
+ /* @__PURE__ */ jsxs69("td", { className: "is-num", children: [
9161
9354
  pct(c.crp).toFixed(0),
9162
9355
  "%"
9163
9356
  ] })
9164
9357
  ] }, c.name)),
9165
- bonus > 0 ? /* @__PURE__ */ jsxs68("tr", { children: [
9166
- /* @__PURE__ */ jsx74("td", { children: /* @__PURE__ */ jsxs68("span", { className: "fd-row", style: { gap: 9, fontWeight: 600 }, children: [
9167
- /* @__PURE__ */ jsx74("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" } }),
9358
+ bonus > 0 ? /* @__PURE__ */ jsxs69("tr", { children: [
9359
+ /* @__PURE__ */ jsx75("td", { children: /* @__PURE__ */ jsxs69("span", { className: "fd-row", style: { gap: 9, fontWeight: 600 }, children: [
9360
+ /* @__PURE__ */ jsx75("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" } }),
9168
9361
  "Surround-sound bonus"
9169
9362
  ] }) }),
9170
- /* @__PURE__ */ jsx74("td", { children: /* @__PURE__ */ jsxs68("span", { className: "fd-badge fd-badge-success", style: { height: 20, fontSize: 11 }, children: [
9363
+ /* @__PURE__ */ jsx75("td", { children: /* @__PURE__ */ jsxs69("span", { className: "fd-badge fd-badge-success", style: { height: 20, fontSize: 11 }, children: [
9171
9364
  "+",
9172
9365
  bonusPct,
9173
9366
  "% of +",
9174
9367
  bonusMax,
9175
9368
  "%"
9176
9369
  ] }) }),
9177
- /* @__PURE__ */ jsx74("td", { className: "is-num fd-muted", children: "\u2014" }),
9178
- /* @__PURE__ */ jsx74("td", { className: "is-num", children: bonus.toFixed(1) }),
9179
- /* @__PURE__ */ jsxs68("td", { className: "is-num", children: [
9370
+ /* @__PURE__ */ jsx75("td", { className: "is-num fd-muted", children: "\u2014" }),
9371
+ /* @__PURE__ */ jsx75("td", { className: "is-num", children: bonus.toFixed(1) }),
9372
+ /* @__PURE__ */ jsxs69("td", { className: "is-num", children: [
9180
9373
  pct(bonus).toFixed(0),
9181
9374
  "%"
9182
9375
  ] })
9183
9376
  ] }) : null,
9184
- /* @__PURE__ */ jsxs68("tr", { style: { background: "var(--surface-2)" }, children: [
9185
- /* @__PURE__ */ jsx74("td", { style: { fontWeight: 700 }, children: "Campus total" }),
9186
- /* @__PURE__ */ jsx74("td", {}),
9187
- /* @__PURE__ */ jsx74("td", { className: "is-num", style: { fontWeight: 700 }, children: money(spendTotal) }),
9188
- /* @__PURE__ */ jsx74("td", { className: "is-num", style: { fontWeight: 700 }, children: grand.toFixed(1) }),
9189
- /* @__PURE__ */ jsx74("td", { className: "is-num", style: { fontWeight: 700 }, children: "100%" })
9377
+ /* @__PURE__ */ jsxs69("tr", { style: { background: "var(--surface-2)" }, children: [
9378
+ /* @__PURE__ */ jsx75("td", { style: { fontWeight: 700 }, children: "Campus total" }),
9379
+ /* @__PURE__ */ jsx75("td", {}),
9380
+ /* @__PURE__ */ jsx75("td", { className: "is-num", style: { fontWeight: 700 }, children: money(spendTotal) }),
9381
+ /* @__PURE__ */ jsx75("td", { className: "is-num", style: { fontWeight: 700 }, children: grand.toFixed(1) }),
9382
+ /* @__PURE__ */ jsx75("td", { className: "is-num", style: { fontWeight: 700 }, children: "100%" })
9190
9383
  ] })
9191
9384
  ] })
9192
9385
  ] }) : null
@@ -9194,8 +9387,8 @@ function ChannelContribution({
9194
9387
  }
9195
9388
 
9196
9389
  // src/components/planner/BudgetReallocator.tsx
9197
- import * as React48 from "react";
9198
- import { Fragment as Fragment22, jsx as jsx75, jsxs as jsxs69 } from "react/jsx-runtime";
9390
+ import * as React49 from "react";
9391
+ import { Fragment as Fragment23, jsx as jsx76, jsxs as jsxs70 } from "react/jsx-runtime";
9199
9392
  var bandFor = (crp) => crp >= 200 ? "dominant" : crp >= 100 ? "strong" : crp >= 50 ? "adequate" : "weak";
9200
9393
  function BudgetReallocator({
9201
9394
  campus,
@@ -9210,8 +9403,8 @@ function BudgetReallocator({
9210
9403
  onCancel,
9211
9404
  className = ""
9212
9405
  }) {
9213
- const [draft, setDraft] = React48.useState(spend);
9214
- React48.useEffect(() => setDraft(spend), [spend]);
9406
+ const [draft, setDraft] = React49.useState(spend);
9407
+ React49.useEffect(() => setDraft(spend), [spend]);
9215
9408
  const dirty = draft !== spend;
9216
9409
  const nextCrp = scoreFor ? scoreFor(draft) : crp;
9217
9410
  const nextBand = bandFor(nextCrp);
@@ -9226,10 +9419,10 @@ function BudgetReallocator({
9226
9419
  setDraft(spend);
9227
9420
  if (onCancel) onCancel();
9228
9421
  };
9229
- const trackRef = React48.useRef(null);
9230
- const chipRef = React48.useRef(null);
9231
- const [chipLeft, setChipLeft] = React48.useState(null);
9232
- React48.useLayoutEffect(() => {
9422
+ const trackRef = React49.useRef(null);
9423
+ const chipRef = React49.useRef(null);
9424
+ const [chipLeft, setChipLeft] = React49.useState(null);
9425
+ React49.useLayoutEffect(() => {
9233
9426
  const track = trackRef.current;
9234
9427
  if (!dirty || !track) {
9235
9428
  setChipLeft(null);
@@ -9250,23 +9443,23 @@ function BudgetReallocator({
9250
9443
  ro.observe(track);
9251
9444
  return () => ro.disconnect();
9252
9445
  }, [dirty, pct]);
9253
- return /* @__PURE__ */ jsxs69(
9446
+ return /* @__PURE__ */ jsxs70(
9254
9447
  "div",
9255
9448
  {
9256
9449
  className: ["fd-stack", className].filter(Boolean).join(" "),
9257
9450
  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)" },
9258
9451
  children: [
9259
- /* @__PURE__ */ jsxs69("div", { className: "fd-row", style: { gap: 12, flexWrap: "wrap" }, children: [
9260
- /* @__PURE__ */ jsx75("span", { className: "fd-h4", style: { flex: 1, minWidth: 140 }, children: campus }),
9261
- /* @__PURE__ */ jsx75(CsiBadge, { band: nowBand, crp, size: "medium" }),
9262
- dirty ? /* @__PURE__ */ jsxs69(Fragment22, { children: [
9263
- /* @__PURE__ */ jsx75("i", { className: "ph ph-arrow-right fd-muted", "aria-hidden": "true" }),
9264
- /* @__PURE__ */ jsx75(CsiBadge, { band: nextBand, crp: nextCrp, size: "medium", preview: true })
9452
+ /* @__PURE__ */ jsxs70("div", { className: "fd-row", style: { gap: 12, flexWrap: "wrap" }, children: [
9453
+ /* @__PURE__ */ jsx76("span", { className: "fd-h4", style: { flex: 1, minWidth: 140 }, children: campus }),
9454
+ /* @__PURE__ */ jsx76(CsiBadge, { band: nowBand, crp, size: "medium" }),
9455
+ dirty ? /* @__PURE__ */ jsxs70(Fragment23, { children: [
9456
+ /* @__PURE__ */ jsx76("i", { className: "ph ph-arrow-right fd-muted", "aria-hidden": "true" }),
9457
+ /* @__PURE__ */ jsx76(CsiBadge, { band: nextBand, crp: nextCrp, size: "medium", preview: true })
9265
9458
  ] }) : null
9266
9459
  ] }),
9267
- /* @__PURE__ */ jsxs69("div", { className: "fd-slider", ref: trackRef, children: [
9268
- /* @__PURE__ */ jsx75("span", { className: "fd-slider-fill", style: { width: pct + "%" } }),
9269
- dirty ? /* @__PURE__ */ jsx75(
9460
+ /* @__PURE__ */ jsxs70("div", { className: "fd-slider", ref: trackRef, children: [
9461
+ /* @__PURE__ */ jsx76("span", { className: "fd-slider-fill", style: { width: pct + "%" } }),
9462
+ dirty ? /* @__PURE__ */ jsx76(
9270
9463
  "span",
9271
9464
  {
9272
9465
  ref: chipRef,
@@ -9278,7 +9471,7 @@ function BudgetReallocator({
9278
9471
  children: (delta < 0 ? "\u2212$" : "+$") + Math.abs(delta).toLocaleString()
9279
9472
  }
9280
9473
  ) : null,
9281
- /* @__PURE__ */ jsx75(
9474
+ /* @__PURE__ */ jsx76(
9282
9475
  "input",
9283
9476
  {
9284
9477
  type: "range",
@@ -9294,13 +9487,13 @@ function BudgetReallocator({
9294
9487
  }
9295
9488
  )
9296
9489
  ] }),
9297
- /* @__PURE__ */ jsxs69("div", { className: "fd-row", style: { gap: 12, flexWrap: "wrap" }, children: [
9298
- /* @__PURE__ */ jsxs69("span", { className: "fd-stack", style: { gap: 2, flex: 1, minWidth: 150 }, children: [
9299
- /* @__PURE__ */ jsx75("span", { className: "fd-num", style: { fontSize: 19, fontWeight: 700 }, children: "$" + draft.toLocaleString() }),
9300
- /* @__PURE__ */ jsx75("span", { className: "fd-body-sm fd-muted", children: "Arrow keys step $100, shift+arrow $1,000. Escape reverts." })
9490
+ /* @__PURE__ */ jsxs70("div", { className: "fd-row", style: { gap: 12, flexWrap: "wrap" }, children: [
9491
+ /* @__PURE__ */ jsxs70("span", { className: "fd-stack", style: { gap: 2, flex: 1, minWidth: 150 }, children: [
9492
+ /* @__PURE__ */ jsx76("span", { className: "fd-num", style: { fontSize: 19, fontWeight: 700 }, children: "$" + draft.toLocaleString() }),
9493
+ /* @__PURE__ */ jsx76("span", { className: "fd-body-sm fd-muted", children: "Arrow keys step $100, shift+arrow $1,000. Escape reverts." })
9301
9494
  ] }),
9302
- /* @__PURE__ */ jsx75("button", { type: "button", className: "fd-btn fd-btn-ghost", disabled: !dirty, onClick: revert, children: "Cancel" }),
9303
- /* @__PURE__ */ jsx75(
9495
+ /* @__PURE__ */ jsx76("button", { type: "button", className: "fd-btn fd-btn-ghost", disabled: !dirty, onClick: revert, children: "Cancel" }),
9496
+ /* @__PURE__ */ jsx76(
9304
9497
  "button",
9305
9498
  {
9306
9499
  type: "button",
@@ -9319,7 +9512,7 @@ function BudgetReallocator({
9319
9512
  }
9320
9513
 
9321
9514
  // src/components/planner/SurroundSound.tsx
9322
- import { jsx as jsx76, jsxs as jsxs70 } from "react/jsx-runtime";
9515
+ import { jsx as jsx77, jsxs as jsxs71 } from "react/jsx-runtime";
9323
9516
  var CATEGORIES = [
9324
9517
  { key: "ooh", label: "OOH", icon: "flag-banner", color: "var(--ch-ooh)" },
9325
9518
  { key: "transit", label: "Transit", icon: "bus", color: "var(--ch-transit)" },
@@ -9331,26 +9524,26 @@ var CATEGORIES = [
9331
9524
  function SurroundSound({ present = [], bonusPct = 0, bonusMax = 40, missedCost, className = "" }) {
9332
9525
  const earned = Math.max(0, Math.min(1, bonusPct / bonusMax));
9333
9526
  const single = present.length <= 2;
9334
- return /* @__PURE__ */ jsxs70("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 14 }, children: [
9335
- /* @__PURE__ */ jsx76("div", { className: "fd-row", style: { gap: 8, flexWrap: "wrap" }, children: CATEGORIES.map((c) => {
9527
+ return /* @__PURE__ */ jsxs71("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 14 }, children: [
9528
+ /* @__PURE__ */ jsx77("div", { className: "fd-row", style: { gap: 8, flexWrap: "wrap" }, children: CATEGORIES.map((c) => {
9336
9529
  const on = present.includes(c.key);
9337
- return /* @__PURE__ */ jsxs70(
9530
+ return /* @__PURE__ */ jsxs71(
9338
9531
  "span",
9339
9532
  {
9340
9533
  title: c.label + (on ? " \u2014 present" : " \u2014 not bought"),
9341
9534
  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)" },
9342
9535
  children: [
9343
- /* @__PURE__ */ jsx76("i", { className: "ph ph-" + c.icon, style: { fontSize: 19, color: on ? c.color : "var(--text-muted)" }, "aria-hidden": "true" }),
9344
- /* @__PURE__ */ jsx76("span", { style: { fontSize: 10.5, fontWeight: 700 }, children: c.label })
9536
+ /* @__PURE__ */ jsx77("i", { className: "ph ph-" + c.icon, style: { fontSize: 19, color: on ? c.color : "var(--text-muted)" }, "aria-hidden": "true" }),
9537
+ /* @__PURE__ */ jsx77("span", { style: { fontSize: 10.5, fontWeight: 700 }, children: c.label })
9345
9538
  ]
9346
9539
  },
9347
9540
  c.key
9348
9541
  );
9349
9542
  }) }),
9350
- /* @__PURE__ */ jsxs70("div", { className: "fd-stack", style: { gap: 8 }, children: [
9351
- /* @__PURE__ */ jsxs70("div", { className: "fd-row", style: { justifyContent: "space-between", gap: 12 }, children: [
9352
- /* @__PURE__ */ jsx76("span", { className: "fd-label-lg", children: "Surround-sound bonus earned" }),
9353
- /* @__PURE__ */ jsxs70("span", { className: "fd-num", style: { color: single ? "var(--warn-text)" : "var(--csi-3-mark)", fontWeight: 700 }, children: [
9543
+ /* @__PURE__ */ jsxs71("div", { className: "fd-stack", style: { gap: 8 }, children: [
9544
+ /* @__PURE__ */ jsxs71("div", { className: "fd-row", style: { justifyContent: "space-between", gap: 12 }, children: [
9545
+ /* @__PURE__ */ jsx77("span", { className: "fd-label-lg", children: "Surround-sound bonus earned" }),
9546
+ /* @__PURE__ */ jsxs71("span", { className: "fd-num", style: { color: single ? "var(--warn-text)" : "var(--csi-3-mark)", fontWeight: 700 }, children: [
9354
9547
  "+",
9355
9548
  bonusPct,
9356
9549
  "% of +",
@@ -9358,8 +9551,8 @@ function SurroundSound({ present = [], bonusPct = 0, bonusMax = 40, missedCost,
9358
9551
  "%"
9359
9552
  ] })
9360
9553
  ] }),
9361
- /* @__PURE__ */ jsx76("div", { style: { height: 8, borderRadius: "var(--r-xs)", background: "var(--surface-3)", overflow: "hidden" }, children: /* @__PURE__ */ jsx76("div", { style: { height: "100%", width: earned * 100 + "%", background: "var(--csi-3-mark)", borderRadius: "inherit", transition: "width var(--dur-slow) var(--ease)" } }) }),
9362
- /* @__PURE__ */ jsxs70("span", { className: "fd-body-sm fd-secondary", style: { textWrap: "pretty" }, children: [
9554
+ /* @__PURE__ */ jsx77("div", { style: { height: 8, borderRadius: "var(--r-xs)", background: "var(--surface-3)", overflow: "hidden" }, children: /* @__PURE__ */ jsx77("div", { style: { height: "100%", width: earned * 100 + "%", background: "var(--csi-3-mark)", borderRadius: "inherit", transition: "width var(--dur-slow) var(--ease)" } }) }),
9555
+ /* @__PURE__ */ jsxs71("span", { className: "fd-body-sm fd-secondary", style: { textWrap: "pretty" }, children: [
9363
9556
  present.length,
9364
9557
  " of 6 channel categories present.",
9365
9558
  " ",
@@ -9371,7 +9564,7 @@ function SurroundSound({ present = [], bonusPct = 0, bonusMax = 40, missedCost,
9371
9564
  }
9372
9565
 
9373
9566
  // src/components/planner/Importance.tsx
9374
- import { jsx as jsx77, jsxs as jsxs71 } from "react/jsx-runtime";
9567
+ import { jsx as jsx78, jsxs as jsxs72 } from "react/jsx-runtime";
9375
9568
  var IMPORTANCE_LEVELS = [
9376
9569
  { id: "nudge", rank: 1, label: "Nudge", icon: "feather", description: "Breaks a tie, nothing more." },
9377
9570
  { id: "lean", rank: 2, label: "Lean", icon: "arrow-bend-up-right", description: "A mild preference between otherwise equal options." },
@@ -9401,23 +9594,23 @@ function importanceTokens(id) {
9401
9594
  function ImportanceTag({ level, showLabel = true, size = "sm", className = "" }) {
9402
9595
  const lvl = importanceLevel(level);
9403
9596
  const t = importanceTokens(level);
9404
- return /* @__PURE__ */ jsxs71(
9597
+ return /* @__PURE__ */ jsxs72(
9405
9598
  "span",
9406
9599
  {
9407
9600
  className: ["fd-imp-tag", size === "md" ? "is-md" : "", className].filter(Boolean).join(" "),
9408
9601
  style: { background: t.fill, borderColor: t.edge, color: t.text },
9409
9602
  title: lvl.label + " \u2014 " + lvl.description,
9410
9603
  children: [
9411
- /* @__PURE__ */ jsx77("i", { className: "ph ph-" + lvl.icon, "aria-hidden": "true" }),
9412
- showLabel ? lvl.label : /* @__PURE__ */ jsx77("span", { className: "fd-sr", children: lvl.label })
9604
+ /* @__PURE__ */ jsx78("i", { className: "ph ph-" + lvl.icon, "aria-hidden": "true" }),
9605
+ showLabel ? lvl.label : /* @__PURE__ */ jsx78("span", { className: "fd-sr", children: lvl.label })
9413
9606
  ]
9414
9607
  }
9415
9608
  );
9416
9609
  }
9417
9610
 
9418
9611
  // src/components/planner/PreferenceMeter.tsx
9419
- import * as React49 from "react";
9420
- import { jsx as jsx78, jsxs as jsxs72 } from "react/jsx-runtime";
9612
+ import * as React50 from "react";
9613
+ import { jsx as jsx79, jsxs as jsxs73 } from "react/jsx-runtime";
9421
9614
  function preferenceScore(criteria) {
9422
9615
  const earned = criteria.reduce((n, c) => n + (Number(c.earned) || 0), 0);
9423
9616
  const weight = criteria.reduce((n, c) => n + (Number(c.weight) || 0), 0);
@@ -9446,8 +9639,8 @@ function PreferenceMeter({
9446
9639
  className = ""
9447
9640
  }) {
9448
9641
  const value = score == null ? preferenceScore(criteria) : score;
9449
- const segments = React49.useMemo(() => preferenceSegments(criteria), [criteria]);
9450
- return /* @__PURE__ */ jsx78(
9642
+ const segments = React50.useMemo(() => preferenceSegments(criteria), [criteria]);
9643
+ return /* @__PURE__ */ jsx79(
9451
9644
  ScoreMeter,
9452
9645
  {
9453
9646
  score: value,
@@ -9459,22 +9652,22 @@ function PreferenceMeter({
9459
9652
  placement,
9460
9653
  className,
9461
9654
  breakdownLabel: breakdownTitle,
9462
- breakdown: /* @__PURE__ */ jsxs72("div", { className: "fd-prefbreak", children: [
9463
- /* @__PURE__ */ jsxs72("div", { className: "fd-prefbreak-head", children: [
9464
- /* @__PURE__ */ jsx78("span", { className: "fd-label-lg", children: breakdownTitle }),
9465
- /* @__PURE__ */ jsx78("span", { className: "fd-prefbreak-score fd-tabular", children: Math.round(value) })
9655
+ breakdown: /* @__PURE__ */ jsxs73("div", { className: "fd-prefbreak", children: [
9656
+ /* @__PURE__ */ jsxs73("div", { className: "fd-prefbreak-head", children: [
9657
+ /* @__PURE__ */ jsx79("span", { className: "fd-label-lg", children: breakdownTitle }),
9658
+ /* @__PURE__ */ jsx79("span", { className: "fd-prefbreak-score fd-tabular", children: Math.round(value) })
9466
9659
  ] }),
9467
- /* @__PURE__ */ jsx78("ul", { className: "fd-prefbreak-list", children: criteria.map((c) => {
9660
+ /* @__PURE__ */ jsx79("ul", { className: "fd-prefbreak-list", children: criteria.map((c) => {
9468
9661
  const pct = c.weight > 0 ? Math.round((Number(c.earned) || 0) / c.weight * 100) : 0;
9469
- return /* @__PURE__ */ jsxs72("li", { className: pct === 0 ? "fd-prefbreak-item is-unmet" : "fd-prefbreak-item", children: [
9470
- /* @__PURE__ */ jsx78(ImportanceTag, { level: c.importance }),
9471
- /* @__PURE__ */ jsxs72("span", { className: "fd-prefbreak-text", children: [
9472
- /* @__PURE__ */ jsx78("span", { className: "fd-prefbreak-label", children: c.label }),
9473
- c.note ? /* @__PURE__ */ jsx78("span", { className: "fd-prefbreak-note", children: c.note }) : null
9662
+ return /* @__PURE__ */ jsxs73("li", { className: pct === 0 ? "fd-prefbreak-item is-unmet" : "fd-prefbreak-item", children: [
9663
+ /* @__PURE__ */ jsx79(ImportanceTag, { level: c.importance }),
9664
+ /* @__PURE__ */ jsxs73("span", { className: "fd-prefbreak-text", children: [
9665
+ /* @__PURE__ */ jsx79("span", { className: "fd-prefbreak-label", children: c.label }),
9666
+ c.note ? /* @__PURE__ */ jsx79("span", { className: "fd-prefbreak-note", children: c.note }) : null
9474
9667
  ] }),
9475
- /* @__PURE__ */ jsxs72("span", { className: "fd-prefbreak-val fd-tabular", children: [
9668
+ /* @__PURE__ */ jsxs73("span", { className: "fd-prefbreak-val fd-tabular", children: [
9476
9669
  Math.round(Number(c.earned) || 0),
9477
- /* @__PURE__ */ jsx78("span", { className: "fd-prefbreak-sep", children: "/" }),
9670
+ /* @__PURE__ */ jsx79("span", { className: "fd-prefbreak-sep", children: "/" }),
9478
9671
  Math.round(c.weight)
9479
9672
  ] })
9480
9673
  ] }, c.id);
@@ -9485,10 +9678,10 @@ function PreferenceMeter({
9485
9678
  }
9486
9679
 
9487
9680
  // src/components/chat/AgentChatPanel.tsx
9488
- import * as React55 from "react";
9681
+ import * as React56 from "react";
9489
9682
 
9490
9683
  // src/components/chat/chatEngine.ts
9491
- import * as React50 from "react";
9684
+ import * as React51 from "react";
9492
9685
  var CHAT_UNAVAILABLE = "chat_unavailable";
9493
9686
  var JOB_PENDING = ["queued", "running"];
9494
9687
  var JOB_SUCCESS = ["completed", "recovered"];
@@ -9542,22 +9735,22 @@ function useChatEngine(opts) {
9542
9735
  onClear,
9543
9736
  onFeedback
9544
9737
  } = opts || {};
9545
- const [status, setStatus] = React50.useState("idle");
9546
- const [threadId, setThreadId] = React50.useState(null);
9547
- const [messages, setMessages] = React50.useState([]);
9548
- const [queue, setQueue] = React50.useState([]);
9549
- const [fatal, setFatal] = React50.useState(null);
9550
- const [busy, setBusy] = React50.useState(false);
9551
- const [turnStartedAt, setTurnStartedAt] = React50.useState(null);
9552
- const listRef = React50.useRef([]);
9553
- const queueRef = React50.useRef([]);
9554
- const busyRef = React50.useRef(false);
9555
- const stoppedRef = React50.useRef(false);
9556
- const abortRef = React50.useRef(null);
9557
- const serverCount = React50.useRef(0);
9558
- const threadRef = React50.useRef(null);
9559
- const mounted = React50.useRef(true);
9560
- React50.useEffect(() => {
9738
+ const [status, setStatus] = React51.useState("idle");
9739
+ const [threadId, setThreadId] = React51.useState(null);
9740
+ const [messages, setMessages] = React51.useState([]);
9741
+ const [queue, setQueue] = React51.useState([]);
9742
+ const [fatal, setFatal] = React51.useState(null);
9743
+ const [busy, setBusy] = React51.useState(false);
9744
+ const [turnStartedAt, setTurnStartedAt] = React51.useState(null);
9745
+ const listRef = React51.useRef([]);
9746
+ const queueRef = React51.useRef([]);
9747
+ const busyRef = React51.useRef(false);
9748
+ const stoppedRef = React51.useRef(false);
9749
+ const abortRef = React51.useRef(null);
9750
+ const serverCount = React51.useRef(0);
9751
+ const threadRef = React51.useRef(null);
9752
+ const mounted = React51.useRef(true);
9753
+ React51.useEffect(() => {
9561
9754
  mounted.current = true;
9562
9755
  return () => {
9563
9756
  mounted.current = false;
@@ -9579,14 +9772,14 @@ function useChatEngine(opts) {
9579
9772
  }
9580
9773
  return false;
9581
9774
  };
9582
- const loadThread = React50.useCallback(async (id) => {
9775
+ const loadThread = React51.useCallback(async (id) => {
9583
9776
  const data = await apiAdapter.getThread(id);
9584
9777
  const list = [...data && data.messages || []];
9585
9778
  serverCount.current = list.length;
9586
9779
  commit(list);
9587
9780
  return list;
9588
9781
  }, [apiAdapter]);
9589
- React50.useEffect(() => {
9782
+ React51.useEffect(() => {
9590
9783
  if (!apiAdapter) {
9591
9784
  setStatus("idle");
9592
9785
  setFatal(null);
@@ -9799,7 +9992,7 @@ function useChatEngine(opts) {
9799
9992
  await dispatchTurn(turn);
9800
9993
  }
9801
9994
  }
9802
- const send = React50.useCallback((text, attachments) => {
9995
+ const send = React51.useCallback((text, attachments) => {
9803
9996
  const body = (text || "").trim();
9804
9997
  if (!body && !(attachments && attachments.length)) return;
9805
9998
  if (status === "disconnected") return;
@@ -9809,7 +10002,7 @@ function useChatEngine(opts) {
9809
10002
  stoppedRef.current = false;
9810
10003
  drain();
9811
10004
  }, [status]);
9812
- const stop = React50.useCallback(() => {
10005
+ const stop = React51.useCallback(() => {
9813
10006
  stoppedRef.current = true;
9814
10007
  const ac = abortRef.current;
9815
10008
  if (ac) {
@@ -9828,11 +10021,11 @@ function useChatEngine(opts) {
9828
10021
  store.del(STORAGE_PREFIX + threadRef.current);
9829
10022
  }
9830
10023
  }, [apiAdapter]);
9831
- const removeQueued = React50.useCallback((id) => {
10024
+ const removeQueued = React51.useCallback((id) => {
9832
10025
  queueRef.current = queueRef.current.filter((t) => t.id !== id);
9833
10026
  setQueue(queueRef.current.slice());
9834
10027
  }, []);
9835
- const retry = React50.useCallback(() => {
10028
+ const retry = React51.useCallback(() => {
9836
10029
  const list = listRef.current;
9837
10030
  let at = -1;
9838
10031
  for (let i = list.length - 1; i >= 0; i--) if (list[i].role === "user") {
@@ -9848,19 +10041,19 @@ function useChatEngine(opts) {
9848
10041
  setQueue(queueRef.current.slice());
9849
10042
  drain();
9850
10043
  }, []);
9851
- const clear = React50.useCallback(() => {
10044
+ const clear = React51.useCallback(() => {
9852
10045
  commit([]);
9853
10046
  serverCount.current = 0;
9854
10047
  queueRef.current = [];
9855
10048
  setQueue([]);
9856
10049
  onClear && onClear();
9857
10050
  }, [onClear]);
9858
- const setFeedback = React50.useCallback((id, value) => {
10051
+ const setFeedback = React51.useCallback((id, value) => {
9859
10052
  patch(id, (m) => ({ feedback: m.feedback === value ? null : value }));
9860
10053
  const msg = listRef.current.find((m) => m.id === id);
9861
10054
  onFeedback && onFeedback({ message: msg, feedback: msg ? msg.feedback : value });
9862
10055
  }, [onFeedback]);
9863
- const reload = React50.useCallback(async () => {
10056
+ const reload = React51.useCallback(async () => {
9864
10057
  if (!threadRef.current) return;
9865
10058
  setStatus("loading");
9866
10059
  try {
@@ -9898,11 +10091,11 @@ var ChatKit = {
9898
10091
  };
9899
10092
 
9900
10093
  // src/components/chat/ChatTranscript.tsx
9901
- import * as React52 from "react";
10094
+ import * as React53 from "react";
9902
10095
 
9903
10096
  // src/components/chat/ChatTurn.tsx
9904
- import * as React51 from "react";
9905
- import { jsx as jsx79, jsxs as jsxs73 } from "react/jsx-runtime";
10097
+ import * as React52 from "react";
10098
+ import { jsx as jsx80, jsxs as jsxs74 } from "react/jsx-runtime";
9906
10099
  function JsonView({ value }) {
9907
10100
  let text;
9908
10101
  try {
@@ -9910,67 +10103,67 @@ function JsonView({ value }) {
9910
10103
  } catch (e) {
9911
10104
  text = String(value);
9912
10105
  }
9913
- return /* @__PURE__ */ jsx79(CodeBlock, { code: text, language: "json", collapseAfter: 18 });
10106
+ return /* @__PURE__ */ jsx80(CodeBlock, { code: text, language: "json", collapseAfter: 18 });
9914
10107
  }
9915
10108
  function PacketCard({ packet, schema, render, onApply, applied }) {
9916
10109
  if (!packet) return null;
9917
10110
  const s = schema || {};
9918
10111
  const invalid = packet.valid === false;
9919
10112
  const title = s.heading || packet.type;
9920
- return /* @__PURE__ */ jsxs73("section", { className: "fdc-packet" + (invalid ? " is-invalid" : ""), "aria-label": title, children: [
9921
- /* @__PURE__ */ jsxs73("header", { className: "fdc-packet-head", children: [
9922
- /* @__PURE__ */ jsx79("i", { className: "ph ph-" + (s.icon || "package"), "aria-hidden": "true" }),
9923
- /* @__PURE__ */ jsx79("span", { className: "fdc-packet-title", title: truncationTitle(title), children: title }),
9924
- packet.repaired ? /* @__PURE__ */ jsx79("span", { className: "fdc-packet-badge", children: "Repaired" }) : null,
9925
- invalid ? /* @__PURE__ */ jsx79("span", { className: "fdc-packet-badge is-danger", children: "Invalid" }) : null
10113
+ return /* @__PURE__ */ jsxs74("section", { className: "fdc-packet" + (invalid ? " is-invalid" : ""), "aria-label": title, children: [
10114
+ /* @__PURE__ */ jsxs74("header", { className: "fdc-packet-head", children: [
10115
+ /* @__PURE__ */ jsx80("i", { className: "ph ph-" + (s.icon || "package"), "aria-hidden": "true" }),
10116
+ /* @__PURE__ */ jsx80("span", { className: "fdc-packet-title", title: truncationTitle(title), children: title }),
10117
+ packet.repaired ? /* @__PURE__ */ jsx80("span", { className: "fdc-packet-badge", children: "Repaired" }) : null,
10118
+ invalid ? /* @__PURE__ */ jsx80("span", { className: "fdc-packet-badge is-danger", children: "Invalid" }) : null
9926
10119
  ] }),
9927
- invalid ? /* @__PURE__ */ jsxs73("div", { className: "fdc-packet-alert", role: "alert", children: [
9928
- /* @__PURE__ */ jsx79("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
9929
- /* @__PURE__ */ jsx79("span", { children: packet.error || "This result failed validation and can\u2019t be applied." })
9930
- ] }) : /* @__PURE__ */ jsx79("div", { className: "fdc-packet-body", children: render ? render(packet) : /* @__PURE__ */ jsx79(JsonView, { value: packet.payload }) }),
9931
- !invalid && onApply ? /* @__PURE__ */ jsxs73("footer", { className: "fdc-packet-foot", children: [
9932
- packet.repaired ? /* @__PURE__ */ jsx79("span", { className: "fdc-packet-note", children: "Corrected by the backend after a first attempt." }) : /* @__PURE__ */ jsx79("span", {}),
9933
- /* @__PURE__ */ jsxs73("button", { type: "button", className: "fd-btn fd-btn-primary fd-btn-sm", disabled: applied, onClick: () => onApply(packet), children: [
9934
- /* @__PURE__ */ jsx79("i", { className: "ph ph-" + (applied ? "check" : "arrow-square-in"), "aria-hidden": "true" }),
10120
+ invalid ? /* @__PURE__ */ jsxs74("div", { className: "fdc-packet-alert", role: "alert", children: [
10121
+ /* @__PURE__ */ jsx80("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
10122
+ /* @__PURE__ */ jsx80("span", { children: packet.error || "This result failed validation and can\u2019t be applied." })
10123
+ ] }) : /* @__PURE__ */ jsx80("div", { className: "fdc-packet-body", children: render ? render(packet) : /* @__PURE__ */ jsx80(JsonView, { value: packet.payload }) }),
10124
+ !invalid && onApply ? /* @__PURE__ */ jsxs74("footer", { className: "fdc-packet-foot", children: [
10125
+ packet.repaired ? /* @__PURE__ */ jsx80("span", { className: "fdc-packet-note", children: "Corrected by the backend after a first attempt." }) : /* @__PURE__ */ jsx80("span", {}),
10126
+ /* @__PURE__ */ jsxs74("button", { type: "button", className: "fd-btn fd-btn-primary fd-btn-sm", disabled: applied, onClick: () => onApply(packet), children: [
10127
+ /* @__PURE__ */ jsx80("i", { className: "ph ph-" + (applied ? "check" : "arrow-square-in"), "aria-hidden": "true" }),
9935
10128
  applied ? "Applied" : s.applyLabel || "Apply"
9936
10129
  ] })
9937
10130
  ] }) : null
9938
10131
  ] });
9939
10132
  }
9940
10133
  function ThinkingBlock({ text, durationMs, streaming, defaultOpen = false }) {
9941
- const [open, setOpen] = React51.useState(defaultOpen);
10134
+ const [open, setOpen] = React52.useState(defaultOpen);
9942
10135
  if (!text) return null;
9943
- return /* @__PURE__ */ jsxs73("div", { className: "fdc-think" + (open ? " is-open" : ""), children: [
9944
- /* @__PURE__ */ jsxs73("button", { type: "button", className: "fdc-think-head", onClick: () => setOpen((v) => !v), "aria-expanded": open, children: [
9945
- /* @__PURE__ */ jsx79("i", { className: "ph ph-brain", "aria-hidden": "true" }),
9946
- /* @__PURE__ */ jsx79("span", { children: streaming ? "Thinking" : durationMs ? "Thought for " + formatDuration(durationMs) : "Thought process" }),
9947
- streaming ? /* @__PURE__ */ jsxs73("span", { className: "fdc-dots", "aria-hidden": "true", children: [
9948
- /* @__PURE__ */ jsx79("span", {}),
9949
- /* @__PURE__ */ jsx79("span", {}),
9950
- /* @__PURE__ */ jsx79("span", {})
10136
+ return /* @__PURE__ */ jsxs74("div", { className: "fdc-think" + (open ? " is-open" : ""), children: [
10137
+ /* @__PURE__ */ jsxs74("button", { type: "button", className: "fdc-think-head", onClick: () => setOpen((v) => !v), "aria-expanded": open, children: [
10138
+ /* @__PURE__ */ jsx80("i", { className: "ph ph-brain", "aria-hidden": "true" }),
10139
+ /* @__PURE__ */ jsx80("span", { children: streaming ? "Thinking" : durationMs ? "Thought for " + formatDuration(durationMs) : "Thought process" }),
10140
+ streaming ? /* @__PURE__ */ jsxs74("span", { className: "fdc-dots", "aria-hidden": "true", children: [
10141
+ /* @__PURE__ */ jsx80("span", {}),
10142
+ /* @__PURE__ */ jsx80("span", {}),
10143
+ /* @__PURE__ */ jsx80("span", {})
9951
10144
  ] }) : null,
9952
- /* @__PURE__ */ jsx79("i", { className: "ph ph-caret-" + (open ? "up" : "down"), "aria-hidden": "true" })
10145
+ /* @__PURE__ */ jsx80("i", { className: "ph ph-caret-" + (open ? "up" : "down"), "aria-hidden": "true" })
9953
10146
  ] }),
9954
- open ? /* @__PURE__ */ jsx79("div", { className: "fdc-think-body", children: text }) : null
10147
+ open ? /* @__PURE__ */ jsx80("div", { className: "fdc-think-body", children: text }) : null
9955
10148
  ] });
9956
10149
  }
9957
10150
  function Citations({ items = [], onOpen }) {
9958
- const [open, setOpen] = React51.useState(false);
10151
+ const [open, setOpen] = React52.useState(false);
9959
10152
  if (!items.length) return null;
9960
- return /* @__PURE__ */ jsxs73("div", { className: "fdc-cites", children: [
9961
- /* @__PURE__ */ jsxs73("button", { type: "button", className: "fdc-cites-head", onClick: () => setOpen((v) => !v), "aria-expanded": open, children: [
9962
- /* @__PURE__ */ jsx79("i", { className: "ph ph-quotes", "aria-hidden": "true" }),
9963
- /* @__PURE__ */ jsxs73("span", { children: [
10153
+ return /* @__PURE__ */ jsxs74("div", { className: "fdc-cites", children: [
10154
+ /* @__PURE__ */ jsxs74("button", { type: "button", className: "fdc-cites-head", onClick: () => setOpen((v) => !v), "aria-expanded": open, children: [
10155
+ /* @__PURE__ */ jsx80("i", { className: "ph ph-quotes", "aria-hidden": "true" }),
10156
+ /* @__PURE__ */ jsxs74("span", { children: [
9964
10157
  items.length,
9965
10158
  " source",
9966
10159
  items.length === 1 ? "" : "s"
9967
10160
  ] }),
9968
- /* @__PURE__ */ jsx79("i", { className: "ph ph-caret-" + (open ? "up" : "down"), "aria-hidden": "true" })
10161
+ /* @__PURE__ */ jsx80("i", { className: "ph ph-caret-" + (open ? "up" : "down"), "aria-hidden": "true" })
9969
10162
  ] }),
9970
- open ? /* @__PURE__ */ jsx79("ol", { className: "fdc-cites-list", children: items.map((c, i) => /* @__PURE__ */ jsxs73("li", { children: [
9971
- /* @__PURE__ */ jsx79("span", { className: "fdc-cite-n fd-tabular", children: c.marker || i + 1 }),
9972
- c.url ? /* @__PURE__ */ jsx79("a", { href: c.url, target: "_blank", rel: "noopener noreferrer", onClick: onOpen ? (e) => onOpen(c, e) : void 0, children: c.title || c.url }) : /* @__PURE__ */ jsx79("span", { children: c.title || "Source" }),
9973
- c.detail ? /* @__PURE__ */ jsx79("span", { className: "fdc-cite-detail", children: c.detail }) : null
10163
+ open ? /* @__PURE__ */ jsx80("ol", { className: "fdc-cites-list", children: items.map((c, i) => /* @__PURE__ */ jsxs74("li", { children: [
10164
+ /* @__PURE__ */ jsx80("span", { className: "fdc-cite-n fd-tabular", children: c.marker || i + 1 }),
10165
+ c.url ? /* @__PURE__ */ jsx80("a", { href: c.url, target: "_blank", rel: "noopener noreferrer", onClick: onOpen ? (e) => onOpen(c, e) : void 0, children: c.title || c.url }) : /* @__PURE__ */ jsx80("span", { children: c.title || "Source" }),
10166
+ c.detail ? /* @__PURE__ */ jsx80("span", { className: "fdc-cite-detail", children: c.detail }) : null
9974
10167
  ] }, c.id || i)) }) : null
9975
10168
  ] });
9976
10169
  }
@@ -9981,29 +10174,29 @@ function clampText(text, max) {
9981
10174
  return (at > max * 0.6 ? cut.slice(0, at) : cut).trimEnd() + "\u2026";
9982
10175
  }
9983
10176
  function MessageBody({ message: m, ctx }) {
9984
- const [expanded, setExpanded] = React51.useState(false);
10177
+ const [expanded, setExpanded] = React52.useState(false);
9985
10178
  const isUser = m.role === "user";
9986
10179
  const raw = m.text || "";
9987
10180
  const clamped = !expanded && !m.streaming ? clampText(raw, ctx.maxVisibleChars) : null;
9988
10181
  const body = clamped != null ? clamped : raw;
9989
10182
  const showMd = ctx.markdown && !isUser;
9990
- return /* @__PURE__ */ jsxs73("div", { className: "fdc-body", children: [
9991
- m.thinking && ctx.showThinking ? /* @__PURE__ */ jsx79(ThinkingBlock, { text: m.thinking, durationMs: m.thinkingMs, streaming: m.streaming && !m.text }) : null,
9992
- m.steps && m.steps.length && ctx.showSteps ? /* @__PURE__ */ jsx79(StepList, { steps: m.steps, defaultOpen: m.steps.some((s) => s.status === "running"), dense: true }) : null,
9993
- body ? /* @__PURE__ */ jsxs73("div", { className: "fdc-text" + (isUser ? " is-user" : ""), children: [
9994
- showMd ? /* @__PURE__ */ jsx79(Markdown, { source: body, headingOffset: 2, codeProps: { collapseAfter: 22 }, renderCitation: ctx.renderCitation }) : /* @__PURE__ */ jsx79("div", { className: "fdc-plain", children: body }),
9995
- m.streaming ? /* @__PURE__ */ jsx79("span", { className: "fdc-caret", "aria-hidden": "true" }) : null
10183
+ return /* @__PURE__ */ jsxs74("div", { className: "fdc-body", children: [
10184
+ m.thinking && ctx.showThinking ? /* @__PURE__ */ jsx80(ThinkingBlock, { text: m.thinking, durationMs: m.thinkingMs, streaming: m.streaming && !m.text }) : null,
10185
+ m.steps && m.steps.length && ctx.showSteps ? /* @__PURE__ */ jsx80(StepList, { steps: m.steps, defaultOpen: m.steps.some((s) => s.status === "running"), dense: true }) : null,
10186
+ body ? /* @__PURE__ */ jsxs74("div", { className: "fdc-text" + (isUser ? " is-user" : ""), children: [
10187
+ showMd ? /* @__PURE__ */ jsx80(Markdown, { source: body, headingOffset: 2, codeProps: { collapseAfter: 22 }, renderCitation: ctx.renderCitation }) : /* @__PURE__ */ jsx80("div", { className: "fdc-plain", children: body }),
10188
+ m.streaming ? /* @__PURE__ */ jsx80("span", { className: "fdc-caret", "aria-hidden": "true" }) : null
9996
10189
  ] }) : null,
9997
- clamped != null ? /* @__PURE__ */ jsxs73("button", { type: "button", className: "fdc-more", onClick: () => setExpanded(true), children: [
9998
- /* @__PURE__ */ jsx79("i", { className: "ph ph-caret-down", "aria-hidden": "true" }),
10190
+ clamped != null ? /* @__PURE__ */ jsxs74("button", { type: "button", className: "fdc-more", onClick: () => setExpanded(true), children: [
10191
+ /* @__PURE__ */ jsx80("i", { className: "ph ph-caret-down", "aria-hidden": "true" }),
9999
10192
  "Show more",
10000
- /* @__PURE__ */ jsx79("span", { className: "fdc-more-len fd-tabular", children: raw.length < 2e3 ? raw.length.toLocaleString() + " characters" : Math.round(raw.length / 100) / 10 + "k characters" })
10001
- ] }) : expanded && ctx.maxVisibleChars && raw.length > ctx.maxVisibleChars ? /* @__PURE__ */ jsxs73("button", { type: "button", className: "fdc-more", onClick: () => setExpanded(false), children: [
10002
- /* @__PURE__ */ jsx79("i", { className: "ph ph-caret-up", "aria-hidden": "true" }),
10193
+ /* @__PURE__ */ jsx80("span", { className: "fdc-more-len fd-tabular", children: raw.length < 2e3 ? raw.length.toLocaleString() + " characters" : Math.round(raw.length / 100) / 10 + "k characters" })
10194
+ ] }) : expanded && ctx.maxVisibleChars && raw.length > ctx.maxVisibleChars ? /* @__PURE__ */ jsxs74("button", { type: "button", className: "fdc-more", onClick: () => setExpanded(false), children: [
10195
+ /* @__PURE__ */ jsx80("i", { className: "ph ph-caret-up", "aria-hidden": "true" }),
10003
10196
  "Show less"
10004
10197
  ] }) : null,
10005
- m.attachments && m.attachments.length ? /* @__PURE__ */ jsx79(FileGrid, { files: m.attachments, onOpen: ctx.onOpenAttachment, tiles: true, maxHeight: ctx.attachmentHeight || 220, compact: ctx.narrow }) : null,
10006
- m.packet ? /* @__PURE__ */ jsx79(
10198
+ m.attachments && m.attachments.length ? /* @__PURE__ */ jsx80(FileGrid, { files: m.attachments, onOpen: ctx.onOpenAttachment, tiles: true, maxHeight: ctx.attachmentHeight || 220, compact: ctx.narrow }) : null,
10199
+ m.packet ? /* @__PURE__ */ jsx80(
10007
10200
  PacketCard,
10008
10201
  {
10009
10202
  packet: m.packet,
@@ -10013,44 +10206,44 @@ function MessageBody({ message: m, ctx }) {
10013
10206
  applied: ctx.appliedPackets && ctx.appliedPackets[m.id]
10014
10207
  }
10015
10208
  ) : null,
10016
- m.citations && m.citations.length ? /* @__PURE__ */ jsx79(Citations, { items: m.citations, onOpen: ctx.onOpenCitation }) : null,
10017
- m.working ? /* @__PURE__ */ jsxs73("div", { className: "fdc-working", role: "status", children: [
10018
- /* @__PURE__ */ jsxs73("span", { className: "fdc-dots", "aria-hidden": "true", children: [
10019
- /* @__PURE__ */ jsx79("span", {}),
10020
- /* @__PURE__ */ jsx79("span", {}),
10021
- /* @__PURE__ */ jsx79("span", {})
10209
+ m.citations && m.citations.length ? /* @__PURE__ */ jsx80(Citations, { items: m.citations, onOpen: ctx.onOpenCitation }) : null,
10210
+ m.working ? /* @__PURE__ */ jsxs74("div", { className: "fdc-working", role: "status", children: [
10211
+ /* @__PURE__ */ jsxs74("span", { className: "fdc-dots", "aria-hidden": "true", children: [
10212
+ /* @__PURE__ */ jsx80("span", {}),
10213
+ /* @__PURE__ */ jsx80("span", {}),
10214
+ /* @__PURE__ */ jsx80("span", {})
10022
10215
  ] }),
10023
- /* @__PURE__ */ jsxs73("span", { className: "fdc-working-label", children: [
10216
+ /* @__PURE__ */ jsxs74("span", { className: "fdc-working-label", children: [
10024
10217
  m.resumed ? "Resuming" : "Working",
10025
- m.job && m.job.status ? /* @__PURE__ */ jsxs73("span", { className: "fdc-working-job", children: [
10218
+ m.job && m.job.status ? /* @__PURE__ */ jsxs74("span", { className: "fdc-working-job", children: [
10026
10219
  " \xB7 ",
10027
10220
  m.job.status
10028
10221
  ] }) : null,
10029
- m.job && m.job.detail ? /* @__PURE__ */ jsxs73("span", { className: "fdc-working-job", children: [
10222
+ m.job && m.job.detail ? /* @__PURE__ */ jsxs74("span", { className: "fdc-working-job", children: [
10030
10223
  " \xB7 ",
10031
10224
  m.job.detail
10032
10225
  ] }) : null
10033
10226
  ] }),
10034
- m.jobId ? /* @__PURE__ */ jsx79("span", { className: "fdc-working-id fd-mono", children: String(m.jobId).slice(0, 12) }) : null
10227
+ m.jobId ? /* @__PURE__ */ jsx80("span", { className: "fdc-working-id fd-mono", children: String(m.jobId).slice(0, 12) }) : null
10035
10228
  ] }) : null,
10036
- m.stopped ? /* @__PURE__ */ jsxs73("div", { className: "fdc-stopped", children: [
10037
- /* @__PURE__ */ jsx79("i", { className: "ph ph-stop-circle", "aria-hidden": "true" }),
10229
+ m.stopped ? /* @__PURE__ */ jsxs74("div", { className: "fdc-stopped", children: [
10230
+ /* @__PURE__ */ jsx80("i", { className: "ph ph-stop-circle", "aria-hidden": "true" }),
10038
10231
  "Stopped"
10039
10232
  ] }) : null,
10040
- m.error ? /* @__PURE__ */ jsxs73("div", { className: "fdc-error", role: "alert", children: [
10041
- /* @__PURE__ */ jsx79("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
10042
- /* @__PURE__ */ jsx79("span", { className: "fdc-error-text", children: ctx.errorCopy ? ctx.errorCopy(m.error) : m.error }),
10043
- m.retryable && ctx.onRetry ? /* @__PURE__ */ jsxs73("button", { type: "button", className: "fdc-error-retry", onClick: ctx.onRetry, children: [
10044
- /* @__PURE__ */ jsx79("i", { className: "ph ph-arrow-clockwise", "aria-hidden": "true" }),
10233
+ m.error ? /* @__PURE__ */ jsxs74("div", { className: "fdc-error", role: "alert", children: [
10234
+ /* @__PURE__ */ jsx80("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
10235
+ /* @__PURE__ */ jsx80("span", { className: "fdc-error-text", children: ctx.errorCopy ? ctx.errorCopy(m.error) : m.error }),
10236
+ m.retryable && ctx.onRetry ? /* @__PURE__ */ jsxs74("button", { type: "button", className: "fdc-error-retry", onClick: ctx.onRetry, children: [
10237
+ /* @__PURE__ */ jsx80("i", { className: "ph ph-arrow-clockwise", "aria-hidden": "true" }),
10045
10238
  "Retry"
10046
10239
  ] }) : null
10047
10240
  ] }) : null
10048
10241
  ] });
10049
10242
  }
10050
10243
  function useCopyRun() {
10051
- const [done, setDone] = React51.useState(false);
10052
- const t = React51.useRef(null);
10053
- React51.useEffect(() => () => {
10244
+ const [done, setDone] = React52.useState(false);
10245
+ const t = React52.useRef(null);
10246
+ React52.useEffect(() => () => {
10054
10247
  if (t.current) clearTimeout(t.current);
10055
10248
  }, []);
10056
10249
  return [done, (text) => {
@@ -10070,16 +10263,16 @@ function RunActions({ group, ctx }) {
10070
10263
  const isAssistant = group.role === "assistant";
10071
10264
  const fb = last.feedback;
10072
10265
  if (!ctx.messageActions) return null;
10073
- return /* @__PURE__ */ jsxs73("div", { className: "fdc-actions", role: "group", "aria-label": "Message actions", children: [
10074
- /* @__PURE__ */ jsxs73("button", { type: "button", className: "fdc-act" + (copied ? " is-done" : ""), onClick: () => copy(markdownToText(text)), "aria-label": "Copy message", children: [
10075
- /* @__PURE__ */ jsx79("i", { className: "ph ph-" + (copied ? "check" : "copy"), "aria-hidden": "true" }),
10076
- /* @__PURE__ */ jsx79("span", { className: "fdc-act-label", children: copied ? "Copied" : "Copy" })
10266
+ return /* @__PURE__ */ jsxs74("div", { className: "fdc-actions", role: "group", "aria-label": "Message actions", children: [
10267
+ /* @__PURE__ */ jsxs74("button", { type: "button", className: "fdc-act" + (copied ? " is-done" : ""), onClick: () => copy(markdownToText(text)), "aria-label": "Copy message", children: [
10268
+ /* @__PURE__ */ jsx80("i", { className: "ph ph-" + (copied ? "check" : "copy"), "aria-hidden": "true" }),
10269
+ /* @__PURE__ */ jsx80("span", { className: "fdc-act-label", children: copied ? "Copied" : "Copy" })
10077
10270
  ] }),
10078
- isAssistant && ctx.onRetry ? /* @__PURE__ */ jsx79("button", { type: "button", className: "fdc-act", onClick: ctx.onRetry, "aria-label": "Retry this turn", children: /* @__PURE__ */ jsx79("i", { className: "ph ph-arrow-clockwise", "aria-hidden": "true" }) }) : null,
10079
- group.role === "user" && ctx.onEdit ? /* @__PURE__ */ jsx79("button", { type: "button", className: "fdc-act", onClick: () => ctx.onEdit(last), "aria-label": "Edit and resend", children: /* @__PURE__ */ jsx79("i", { className: "ph ph-pencil-simple", "aria-hidden": "true" }) }) : null,
10080
- isAssistant && ctx.onFeedback ? /* @__PURE__ */ jsxs73(React51.Fragment, { children: [
10081
- /* @__PURE__ */ jsx79("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__ */ jsx79("i", { className: "ph ph-thumbs-up", "aria-hidden": "true" }) }),
10082
- /* @__PURE__ */ jsx79("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__ */ jsx79("i", { className: "ph ph-thumbs-down", "aria-hidden": "true" }) })
10271
+ isAssistant && ctx.onRetry ? /* @__PURE__ */ jsx80("button", { type: "button", className: "fdc-act", onClick: ctx.onRetry, "aria-label": "Retry this turn", children: /* @__PURE__ */ jsx80("i", { className: "ph ph-arrow-clockwise", "aria-hidden": "true" }) }) : null,
10272
+ group.role === "user" && ctx.onEdit ? /* @__PURE__ */ jsx80("button", { type: "button", className: "fdc-act", onClick: () => ctx.onEdit(last), "aria-label": "Edit and resend", children: /* @__PURE__ */ jsx80("i", { className: "ph ph-pencil-simple", "aria-hidden": "true" }) }) : null,
10273
+ isAssistant && ctx.onFeedback ? /* @__PURE__ */ jsxs74(React52.Fragment, { children: [
10274
+ /* @__PURE__ */ jsx80("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__ */ jsx80("i", { className: "ph ph-thumbs-up", "aria-hidden": "true" }) }),
10275
+ /* @__PURE__ */ jsx80("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__ */ jsx80("i", { className: "ph ph-thumbs-down", "aria-hidden": "true" }) })
10083
10276
  ] }) : null,
10084
10277
  ctx.extraActions ? ctx.extraActions(group) : null
10085
10278
  ] });
@@ -10089,22 +10282,22 @@ function ChatTurn({ group, ctx }) {
10089
10282
  const name = isUser ? ctx.userName : group.author || ctx.assistantName;
10090
10283
  const avatar = isUser ? ctx.userAvatar : ctx.assistantAvatar;
10091
10284
  const stamp = group.messages[0].timestamp;
10092
- return /* @__PURE__ */ jsxs73("article", { className: "fdc-turn is-" + group.role, "aria-label": String(name) + (stamp ? " at " + formatClock(stamp) : ""), children: [
10093
- /* @__PURE__ */ jsxs73("div", { className: "fdc-turn-head", children: [
10094
- ctx.showAvatars ? /* @__PURE__ */ jsx79("span", { className: "fdc-avatar is-" + group.role, "aria-hidden": "true", children: avatar ? /* @__PURE__ */ jsx79("img", { src: avatar, alt: "" }) : isUser ? /* @__PURE__ */ jsx79("span", { className: "fdc-avatar-txt", children: (name || "You").slice(0, 1).toUpperCase() }) : /* @__PURE__ */ jsx79("i", { className: "ph ph-" + (ctx.assistantIcon || "sparkle") }) }) : null,
10095
- /* @__PURE__ */ jsx79("span", { className: "fdc-who", children: name }),
10096
- stamp ? /* @__PURE__ */ jsx79(RelativeTime, { className: "fdc-when", value: stamp }) : null,
10097
- group.messages.some((m) => m.model) ? /* @__PURE__ */ jsx79("span", { className: "fdc-turn-model", children: group.messages.find((m) => m.model).model }) : null
10285
+ return /* @__PURE__ */ jsxs74("article", { className: "fdc-turn is-" + group.role, "aria-label": String(name) + (stamp ? " at " + formatClock(stamp) : ""), children: [
10286
+ /* @__PURE__ */ jsxs74("div", { className: "fdc-turn-head", children: [
10287
+ ctx.showAvatars ? /* @__PURE__ */ jsx80("span", { className: "fdc-avatar is-" + group.role, "aria-hidden": "true", children: avatar ? /* @__PURE__ */ jsx80("img", { src: avatar, alt: "" }) : isUser ? /* @__PURE__ */ jsx80("span", { className: "fdc-avatar-txt", children: (name || "You").slice(0, 1).toUpperCase() }) : /* @__PURE__ */ jsx80("i", { className: "ph ph-" + (ctx.assistantIcon || "sparkle") }) }) : null,
10288
+ /* @__PURE__ */ jsx80("span", { className: "fdc-who", children: name }),
10289
+ stamp ? /* @__PURE__ */ jsx80(RelativeTime, { className: "fdc-when", value: stamp }) : null,
10290
+ group.messages.some((m) => m.model) ? /* @__PURE__ */ jsx80("span", { className: "fdc-turn-model", children: group.messages.find((m) => m.model).model }) : null
10098
10291
  ] }),
10099
- /* @__PURE__ */ jsxs73("div", { className: "fdc-turn-body", children: [
10100
- group.messages.map((m) => /* @__PURE__ */ jsx79("div", { className: "fdc-msg" + (m.pending ? " is-pending" : ""), children: /* @__PURE__ */ jsx79(MessageBody, { message: m, ctx }) }, m.id)),
10101
- /* @__PURE__ */ jsx79(RunActions, { group, ctx })
10292
+ /* @__PURE__ */ jsxs74("div", { className: "fdc-turn-body", children: [
10293
+ group.messages.map((m) => /* @__PURE__ */ jsx80("div", { className: "fdc-msg" + (m.pending ? " is-pending" : ""), children: /* @__PURE__ */ jsx80(MessageBody, { message: m, ctx }) }, m.id)),
10294
+ /* @__PURE__ */ jsx80(RunActions, { group, ctx })
10102
10295
  ] })
10103
10296
  ] });
10104
10297
  }
10105
10298
 
10106
10299
  // src/components/chat/ChatTranscript.tsx
10107
- import { jsx as jsx80, jsxs as jsxs74 } from "react/jsx-runtime";
10300
+ import { jsx as jsx81, jsxs as jsxs75 } from "react/jsx-runtime";
10108
10301
  var GROUP_WINDOW = 6e4;
10109
10302
  var STICK_PX = 100;
10110
10303
  function groupMessages(list) {
@@ -10137,25 +10330,25 @@ function dayLabel(key) {
10137
10330
  }
10138
10331
  function Suggestions({ items = [], onPick }) {
10139
10332
  if (!items.length) return null;
10140
- return /* @__PURE__ */ jsx80("div", { className: "fdc-suggest", children: items.map((s, i) => {
10333
+ return /* @__PURE__ */ jsx81("div", { className: "fdc-suggest", children: items.map((s, i) => {
10141
10334
  const it = typeof s === "string" ? { label: s, text: s } : s;
10142
- return /* @__PURE__ */ jsxs74("button", { type: "button", className: "fdc-suggest-item", onClick: () => onPick && onPick(it.text || it.label), children: [
10143
- it.icon ? /* @__PURE__ */ jsx80("i", { className: "ph ph-" + it.icon, "aria-hidden": "true" }) : null,
10144
- /* @__PURE__ */ jsxs74("span", { className: "fdc-suggest-text", children: [
10145
- /* @__PURE__ */ jsx80("span", { className: "fdc-suggest-label", children: it.label }),
10146
- it.description ? /* @__PURE__ */ jsx80("span", { className: "fdc-suggest-desc", children: it.description }) : null
10335
+ return /* @__PURE__ */ jsxs75("button", { type: "button", className: "fdc-suggest-item", onClick: () => onPick && onPick(it.text || it.label), children: [
10336
+ it.icon ? /* @__PURE__ */ jsx81("i", { className: "ph ph-" + it.icon, "aria-hidden": "true" }) : null,
10337
+ /* @__PURE__ */ jsxs75("span", { className: "fdc-suggest-text", children: [
10338
+ /* @__PURE__ */ jsx81("span", { className: "fdc-suggest-label", children: it.label }),
10339
+ it.description ? /* @__PURE__ */ jsx81("span", { className: "fdc-suggest-desc", children: it.description }) : null
10147
10340
  ] }),
10148
- /* @__PURE__ */ jsx80("i", { className: "ph ph-arrow-up-right fdc-suggest-go", "aria-hidden": "true" })
10341
+ /* @__PURE__ */ jsx81("i", { className: "ph ph-arrow-up-right fdc-suggest-go", "aria-hidden": "true" })
10149
10342
  ] }, it.id || i);
10150
10343
  }) });
10151
10344
  }
10152
10345
  function LoadingTurns() {
10153
- return /* @__PURE__ */ jsx80("div", { className: "fdc-skel", "aria-hidden": "true", children: [0, 1].map((i) => /* @__PURE__ */ jsxs74("div", { className: "fdc-skel-turn", children: [
10154
- /* @__PURE__ */ jsx80("div", { className: "fd-skel fd-skel-circle", style: { width: 22, height: 22 } }),
10155
- /* @__PURE__ */ jsxs74("div", { className: "fdc-skel-lines", children: [
10156
- /* @__PURE__ */ jsx80("div", { className: "fd-skel", style: { width: i ? "62%" : "44%", height: 11 } }),
10157
- /* @__PURE__ */ jsx80("div", { className: "fd-skel", style: { width: i ? "94%" : "78%", height: 11 } }),
10158
- /* @__PURE__ */ jsx80("div", { className: "fd-skel", style: { width: i ? "71%" : "56%", height: 11 } })
10346
+ return /* @__PURE__ */ jsx81("div", { className: "fdc-skel", "aria-hidden": "true", children: [0, 1].map((i) => /* @__PURE__ */ jsxs75("div", { className: "fdc-skel-turn", children: [
10347
+ /* @__PURE__ */ jsx81("div", { className: "fd-skel fd-skel-circle", style: { width: 22, height: 22 } }),
10348
+ /* @__PURE__ */ jsxs75("div", { className: "fdc-skel-lines", children: [
10349
+ /* @__PURE__ */ jsx81("div", { className: "fd-skel", style: { width: i ? "62%" : "44%", height: 11 } }),
10350
+ /* @__PURE__ */ jsx81("div", { className: "fd-skel", style: { width: i ? "94%" : "78%", height: 11 } }),
10351
+ /* @__PURE__ */ jsx81("div", { className: "fd-skel", style: { width: i ? "71%" : "56%", height: 11 } })
10159
10352
  ] })
10160
10353
  ] }, i)) });
10161
10354
  }
@@ -10172,10 +10365,10 @@ function ChatTranscript({
10172
10365
  renderEmpty,
10173
10366
  className = ""
10174
10367
  }) {
10175
- const scroller = React52.useRef(null);
10176
- const stick = React52.useRef(true);
10177
- const [pill, setPill] = React52.useState(0);
10178
- const seen = React52.useRef(0);
10368
+ const scroller = React53.useRef(null);
10369
+ const stick = React53.useRef(true);
10370
+ const [pill, setPill] = React53.useState(0);
10371
+ const seen = React53.useRef(0);
10179
10372
  const toBottom = (smooth) => {
10180
10373
  const el = scroller.current;
10181
10374
  if (!el) return;
@@ -10194,7 +10387,7 @@ function ChatTranscript({
10194
10387
  seen.current = messages.length;
10195
10388
  }
10196
10389
  };
10197
- React52.useLayoutEffect(() => {
10390
+ React53.useLayoutEffect(() => {
10198
10391
  const el = scroller.current;
10199
10392
  if (!el) return;
10200
10393
  if (stick.current) {
@@ -10202,7 +10395,7 @@ function ChatTranscript({
10202
10395
  seen.current = messages.length;
10203
10396
  } else setPill(Math.max(0, messages.length - seen.current));
10204
10397
  }, [messages]);
10205
- React52.useEffect(() => {
10398
+ React53.useEffect(() => {
10206
10399
  const el = scroller.current;
10207
10400
  const inner = el && el.firstChild;
10208
10401
  if (!el || !inner || typeof ResizeObserver === "undefined") return;
@@ -10212,38 +10405,38 @@ function ChatTranscript({
10212
10405
  ro.observe(inner);
10213
10406
  return () => ro.disconnect();
10214
10407
  }, []);
10215
- const groups = React52.useMemo(() => groupMessages(messages), [messages]);
10408
+ const groups = React53.useMemo(() => groupMessages(messages), [messages]);
10216
10409
  const empty = !messages.length && status === "ready";
10217
- return /* @__PURE__ */ jsxs74("div", { className: ["fdc-scroll", className].filter(Boolean).join(" "), ref: scroller, onScroll, children: [
10218
- /* @__PURE__ */ jsxs74("div", { className: "fdc-log", role: "log", "aria-label": "Conversation", children: [
10219
- status === "loading" || status === "resolving" ? /* @__PURE__ */ jsx80(LoadingTurns, {}) : null,
10220
- status === "disconnected" ? /* @__PURE__ */ jsxs74("div", { className: "fdc-dead", children: [
10221
- /* @__PURE__ */ jsx80("span", { className: "fdc-dead-icon", children: /* @__PURE__ */ jsx80("i", { className: "ph ph-plugs", "aria-hidden": "true" }) }),
10222
- /* @__PURE__ */ jsx80("h3", { className: "fdc-dead-title", children: ctx.deadTitle || "The assistant isn\u2019t reachable" }),
10223
- /* @__PURE__ */ jsx80("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." }),
10224
- ctx.onReconnect ? /* @__PURE__ */ jsxs74("button", { type: "button", className: "fd-btn fd-btn-secondary fd-btn-sm", onClick: ctx.onReconnect, children: [
10225
- /* @__PURE__ */ jsx80("i", { className: "ph ph-arrow-clockwise", "aria-hidden": "true" }),
10410
+ return /* @__PURE__ */ jsxs75("div", { className: ["fdc-scroll", className].filter(Boolean).join(" "), ref: scroller, onScroll, children: [
10411
+ /* @__PURE__ */ jsxs75("div", { className: "fdc-log", role: "log", "aria-label": "Conversation", children: [
10412
+ status === "loading" || status === "resolving" ? /* @__PURE__ */ jsx81(LoadingTurns, {}) : null,
10413
+ status === "disconnected" ? /* @__PURE__ */ jsxs75("div", { className: "fdc-dead", children: [
10414
+ /* @__PURE__ */ jsx81("span", { className: "fdc-dead-icon", children: /* @__PURE__ */ jsx81("i", { className: "ph ph-plugs", "aria-hidden": "true" }) }),
10415
+ /* @__PURE__ */ jsx81("h3", { className: "fdc-dead-title", children: ctx.deadTitle || "The assistant isn\u2019t reachable" }),
10416
+ /* @__PURE__ */ jsx81("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." }),
10417
+ ctx.onReconnect ? /* @__PURE__ */ jsxs75("button", { type: "button", className: "fd-btn fd-btn-secondary fd-btn-sm", onClick: ctx.onReconnect, children: [
10418
+ /* @__PURE__ */ jsx81("i", { className: "ph ph-arrow-clockwise", "aria-hidden": "true" }),
10226
10419
  "Try again"
10227
10420
  ] }) : null
10228
10421
  ] }) : null,
10229
- empty ? renderEmpty ? renderEmpty() : /* @__PURE__ */ jsxs74("div", { className: "fdc-empty", children: [
10230
- /* @__PURE__ */ jsx80("span", { className: "fdc-empty-icon", children: /* @__PURE__ */ jsx80("i", { className: "ph ph-" + emptyIcon, "aria-hidden": "true" }) }),
10231
- /* @__PURE__ */ jsx80("h3", { className: "fdc-empty-title", children: emptyTitle }),
10232
- emptyDescription ? /* @__PURE__ */ jsx80("p", { className: "fdc-empty-body", children: emptyDescription }) : null,
10233
- /* @__PURE__ */ jsx80(Suggestions, { items: suggestions, onPick })
10422
+ empty ? renderEmpty ? renderEmpty() : /* @__PURE__ */ jsxs75("div", { className: "fdc-empty", children: [
10423
+ /* @__PURE__ */ jsx81("span", { className: "fdc-empty-icon", children: /* @__PURE__ */ jsx81("i", { className: "ph ph-" + emptyIcon, "aria-hidden": "true" }) }),
10424
+ /* @__PURE__ */ jsx81("h3", { className: "fdc-empty-title", children: emptyTitle }),
10425
+ emptyDescription ? /* @__PURE__ */ jsx81("p", { className: "fdc-empty-body", children: emptyDescription }) : null,
10426
+ /* @__PURE__ */ jsx81(Suggestions, { items: suggestions, onPick })
10234
10427
  ] }) : null,
10235
10428
  groups.map((g, i) => {
10236
10429
  const prev = groups[i - 1];
10237
10430
  const k = dayKey(g.messages[0].timestamp);
10238
10431
  const showDay = !!k && (!prev || dayKey(prev.messages[0].timestamp) !== k);
10239
- return /* @__PURE__ */ jsxs74(React52.Fragment, { children: [
10240
- showDay ? /* @__PURE__ */ jsx80("div", { className: "fdc-day", children: /* @__PURE__ */ jsx80("span", { children: dayLabel(k) }) }) : null,
10241
- /* @__PURE__ */ jsx80(ChatTurn, { group: g, ctx })
10432
+ return /* @__PURE__ */ jsxs75(React53.Fragment, { children: [
10433
+ showDay ? /* @__PURE__ */ jsx81("div", { className: "fdc-day", children: /* @__PURE__ */ jsx81("span", { children: dayLabel(k) }) }) : null,
10434
+ /* @__PURE__ */ jsx81(ChatTurn, { group: g, ctx })
10242
10435
  ] }, g.key || i);
10243
10436
  })
10244
10437
  ] }),
10245
- pill ? /* @__PURE__ */ jsxs74("button", { type: "button", className: "fdc-pill", onClick: () => toBottom(true), children: [
10246
- /* @__PURE__ */ jsx80("i", { className: "ph ph-arrow-down", "aria-hidden": "true" }),
10438
+ pill ? /* @__PURE__ */ jsxs75("button", { type: "button", className: "fdc-pill", onClick: () => toBottom(true), children: [
10439
+ /* @__PURE__ */ jsx81("i", { className: "ph ph-arrow-down", "aria-hidden": "true" }),
10247
10440
  pill,
10248
10441
  " new message",
10249
10442
  pill === 1 ? "" : "s"
@@ -10253,8 +10446,8 @@ function ChatTranscript({
10253
10446
  var TranscriptKit = { groupMessages };
10254
10447
 
10255
10448
  // src/components/chat/ChatComposer.tsx
10256
- import * as React53 from "react";
10257
- import { jsx as jsx81, jsxs as jsxs75 } from "react/jsx-runtime";
10449
+ import * as React54 from "react";
10450
+ import { jsx as jsx82, jsxs as jsxs76 } from "react/jsx-runtime";
10258
10451
  function ChatComposer({
10259
10452
  onSubmit,
10260
10453
  onStop,
@@ -10281,17 +10474,17 @@ function ChatComposer({
10281
10474
  onReject,
10282
10475
  onOpenAttachment
10283
10476
  }) {
10284
- const [text, setText] = React53.useState(draft || "");
10285
- const [trigger, setTrigger] = React53.useState(null);
10286
- const [mentionItems, setMentionItems] = React53.useState([]);
10287
- const [listening, setListening] = React53.useState(false);
10288
- const [notice, setNotice] = React53.useState(null);
10289
- const editor = React53.useRef(null);
10290
- const wrap = React53.useRef(null);
10291
- const stopVoice = React53.useRef(null);
10477
+ const [text, setText] = React54.useState(draft || "");
10478
+ const [trigger, setTrigger] = React54.useState(null);
10479
+ const [mentionItems, setMentionItems] = React54.useState([]);
10480
+ const [listening, setListening] = React54.useState(false);
10481
+ const [notice, setNotice] = React54.useState(null);
10482
+ const editor = React54.useRef(null);
10483
+ const wrap = React54.useRef(null);
10484
+ const stopVoice = React54.useRef(null);
10292
10485
  const staged = useStagedFiles(fileUploadHandler, { onError: () => {
10293
10486
  } });
10294
- React53.useEffect(() => {
10487
+ React54.useEffect(() => {
10295
10488
  if (draft != null && draft !== text) setText(draft);
10296
10489
  }, [draft]);
10297
10490
  const change = (v) => {
@@ -10327,7 +10520,7 @@ function ChatComposer({
10327
10520
  e.preventDefault();
10328
10521
  staged.add(found.files);
10329
10522
  };
10330
- React53.useEffect(() => {
10523
+ React54.useEffect(() => {
10331
10524
  if (!trigger || trigger.type !== "mention" || !mentionSources) {
10332
10525
  setMentionItems([]);
10333
10526
  return;
@@ -10345,7 +10538,7 @@ function ChatComposer({
10345
10538
  const q = (trigger.query || "").toLowerCase();
10346
10539
  setMentionItems(mentionSources.filter((m) => !q || (m.label + " " + (m.description || "")).toLowerCase().includes(q)));
10347
10540
  }, [trigger, mentionSources]);
10348
- const slashItems = React53.useMemo(() => {
10541
+ const slashItems = React54.useMemo(() => {
10349
10542
  if (!trigger || trigger.type !== "slash" || !slashCommands) return [];
10350
10543
  const q = (trigger.query || "").toLowerCase();
10351
10544
  return slashCommands.filter((c) => !q || (c.id + " " + c.label + " " + (c.description || "")).toLowerCase().includes(q));
@@ -10359,7 +10552,7 @@ function ChatComposer({
10359
10552
  description: it.description,
10360
10553
  icon: it.icon,
10361
10554
  meta: mention.meta,
10362
- shortcut: slash.shortcut ? /* @__PURE__ */ jsx81(KeyHint, { keys: slash.shortcut, size: "sm" }) : void 0,
10555
+ shortcut: slash.shortcut ? /* @__PURE__ */ jsx82(KeyHint, { keys: slash.shortcut, size: "sm" }) : void 0,
10363
10556
  onSelect: () => {
10364
10557
  const insert = trigger.type === "slash" ? slash.immediate ? "/" + slash.id : "/" + slash.id + " " : "@" + (mention.value || mention.label) + " ";
10365
10558
  editor.current && editor.current.replaceRange(trigger.from, trigger.to, insert);
@@ -10422,14 +10615,14 @@ function ChatComposer({
10422
10615
  stopVoice.current = typeof res === "function" ? res : () => {
10423
10616
  };
10424
10617
  };
10425
- return /* @__PURE__ */ jsxs75("div", { className: "fdc-composer" + (disabled ? " is-disabled" : "") + (narrow ? " is-narrow" : ""), children: [
10426
- queue.length ? /* @__PURE__ */ jsx81("div", { className: "fdc-queue", "aria-label": "Queued messages", children: queue.map((q) => /* @__PURE__ */ jsxs75("div", { className: "fdc-queue-row", children: [
10427
- /* @__PURE__ */ jsx81("i", { className: "ph ph-clock-countdown", "aria-hidden": "true" }),
10428
- /* @__PURE__ */ jsx81("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)" : "") }),
10429
- onRemoveQueued ? /* @__PURE__ */ jsx81("button", { type: "button", className: "fdc-queue-x", onClick: () => onRemoveQueued(q.id), "aria-label": "Remove queued message", children: /* @__PURE__ */ jsx81("i", { className: "ph ph-x", "aria-hidden": "true" }) }) : null
10618
+ return /* @__PURE__ */ jsxs76("div", { className: "fdc-composer" + (disabled ? " is-disabled" : "") + (narrow ? " is-narrow" : ""), children: [
10619
+ queue.length ? /* @__PURE__ */ jsx82("div", { className: "fdc-queue", "aria-label": "Queued messages", children: queue.map((q) => /* @__PURE__ */ jsxs76("div", { className: "fdc-queue-row", children: [
10620
+ /* @__PURE__ */ jsx82("i", { className: "ph ph-clock-countdown", "aria-hidden": "true" }),
10621
+ /* @__PURE__ */ jsx82("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)" : "") }),
10622
+ onRemoveQueued ? /* @__PURE__ */ jsx82("button", { type: "button", className: "fdc-queue-x", onClick: () => onRemoveQueued(q.id), "aria-label": "Remove queued message", children: /* @__PURE__ */ jsx82("i", { className: "ph ph-x", "aria-hidden": "true" }) }) : null
10430
10623
  ] }, q.id)) }) : null,
10431
10624
  sessionBar,
10432
- /* @__PURE__ */ jsx81(
10625
+ /* @__PURE__ */ jsx82(
10433
10626
  Dropzone,
10434
10627
  {
10435
10628
  className: "fdc-field",
@@ -10443,9 +10636,9 @@ function ChatComposer({
10443
10636
  disabled: !fileUploadHandler || disabled,
10444
10637
  label: "Drop to attach",
10445
10638
  hint: acceptFiles ? acceptFiles.replace(/,/g, " \xB7 ") : void 0,
10446
- children: /* @__PURE__ */ jsxs75("div", { ref: wrap, className: "fdc-field-inner", children: [
10447
- staged.items.length ? /* @__PURE__ */ jsx81("div", { className: "fdc-staged", children: /* @__PURE__ */ jsx81(FileStrip, { files: staged.items, size: narrow ? 60 : 68, onRemove: staged.remove, onRetry: staged.retry, onOpen: onOpenAttachment }) }) : null,
10448
- /* @__PURE__ */ jsx81(
10639
+ children: /* @__PURE__ */ jsxs76("div", { ref: wrap, className: "fdc-field-inner", children: [
10640
+ staged.items.length ? /* @__PURE__ */ jsx82("div", { className: "fdc-staged", children: /* @__PURE__ */ jsx82(FileStrip, { files: staged.items, size: narrow ? 60 : 68, onRemove: staged.remove, onRetry: staged.retry, onOpen: onOpenAttachment }) }) : null,
10641
+ /* @__PURE__ */ jsx82(
10449
10642
  MarkdownEditor,
10450
10643
  {
10451
10644
  ref: editor,
@@ -10464,33 +10657,33 @@ function ChatComposer({
10464
10657
  ariaLabel: "Message"
10465
10658
  }
10466
10659
  ),
10467
- /* @__PURE__ */ jsxs75("div", { className: "fdc-tools", children: [
10468
- fileUploadHandler ? /* @__PURE__ */ jsx81(FilePickButton, { onFiles: staged.add, onReject: (r) => flash(r[0].message), accept: acceptFiles, maxFileSize, label: "Attach files", icon: "plus" }) : null,
10469
- voiceHandler ? /* @__PURE__ */ jsx81("button", { type: "button", className: "fd-attachbtn" + (listening ? " is-live" : ""), onClick: voice, "aria-pressed": listening, "aria-label": listening ? "Stop dictation" : "Dictate", children: /* @__PURE__ */ jsx81("i", { className: "ph ph-" + (listening ? "waveform" : "microphone"), "aria-hidden": "true" }) }) : null,
10660
+ /* @__PURE__ */ jsxs76("div", { className: "fdc-tools", children: [
10661
+ fileUploadHandler ? /* @__PURE__ */ jsx82(FilePickButton, { onFiles: staged.add, onReject: (r) => flash(r[0].message), accept: acceptFiles, maxFileSize, label: "Attach files", icon: "plus" }) : null,
10662
+ voiceHandler ? /* @__PURE__ */ jsx82("button", { type: "button", className: "fd-attachbtn" + (listening ? " is-live" : ""), onClick: voice, "aria-pressed": listening, "aria-label": listening ? "Stop dictation" : "Dictate", children: /* @__PURE__ */ jsx82("i", { className: "ph ph-" + (listening ? "waveform" : "microphone"), "aria-hidden": "true" }) }) : null,
10470
10663
  toolbarExtras,
10471
- /* @__PURE__ */ jsx81("span", { className: "fdc-tools-gap" }),
10472
- maxLength && text.length > maxLength * 0.6 ? /* @__PURE__ */ jsxs75("span", { className: "fdc-count fd-tabular" + (text.length > maxLength * 0.95 ? " is-hot" : ""), children: [
10664
+ /* @__PURE__ */ jsx82("span", { className: "fdc-tools-gap" }),
10665
+ maxLength && text.length > maxLength * 0.6 ? /* @__PURE__ */ jsxs76("span", { className: "fdc-count fd-tabular" + (text.length > maxLength * 0.95 ? " is-hot" : ""), children: [
10473
10666
  text.length,
10474
10667
  "/",
10475
10668
  maxLength
10476
10669
  ] }) : null,
10477
- busy ? /* @__PURE__ */ jsxs75("button", { type: "button", className: "fdc-stop", onClick: onStop, "aria-label": "Stop generating", children: [
10478
- /* @__PURE__ */ jsx81("i", { className: "ph ph-stop-circle", "aria-hidden": "true" }),
10479
- /* @__PURE__ */ jsx81("span", { children: "Stop" })
10480
- ] }) : /* @__PURE__ */ jsxs75("button", { type: "button", className: "fdc-send", onClick: submit, disabled: !canSend, "aria-label": "Send message", children: [
10481
- /* @__PURE__ */ jsx81("i", { className: "ph ph-paper-plane-right", "aria-hidden": "true" }),
10482
- /* @__PURE__ */ jsx81("span", { className: "fdc-send-label", children: "Send" })
10670
+ busy ? /* @__PURE__ */ jsxs76("button", { type: "button", className: "fdc-stop", onClick: onStop, "aria-label": "Stop generating", children: [
10671
+ /* @__PURE__ */ jsx82("i", { className: "ph ph-stop-circle", "aria-hidden": "true" }),
10672
+ /* @__PURE__ */ jsx82("span", { children: "Stop" })
10673
+ ] }) : /* @__PURE__ */ jsxs76("button", { type: "button", className: "fdc-send", onClick: submit, disabled: !canSend, "aria-label": "Send message", children: [
10674
+ /* @__PURE__ */ jsx82("i", { className: "ph ph-paper-plane-right", "aria-hidden": "true" }),
10675
+ /* @__PURE__ */ jsx82("span", { className: "fdc-send-label", children: "Send" })
10483
10676
  ] })
10484
10677
  ] })
10485
10678
  ] })
10486
10679
  }
10487
10680
  ),
10488
- notice ? /* @__PURE__ */ jsxs75("div", { className: "fdc-notice", role: "status", children: [
10489
- /* @__PURE__ */ jsx81("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
10681
+ notice ? /* @__PURE__ */ jsxs76("div", { className: "fdc-notice", role: "status", children: [
10682
+ /* @__PURE__ */ jsx82("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
10490
10683
  notice
10491
10684
  ] }) : null,
10492
- hint && !notice ? /* @__PURE__ */ jsx81("div", { className: "fdc-hint", children: hint }) : null,
10493
- /* @__PURE__ */ jsx81(
10685
+ hint && !notice ? /* @__PURE__ */ jsx82("div", { className: "fdc-hint", children: hint }) : null,
10686
+ /* @__PURE__ */ jsx82(
10494
10687
  Popover,
10495
10688
  {
10496
10689
  open: menuOpen,
@@ -10504,12 +10697,12 @@ function ChatComposer({
10504
10697
  returnFocus: false,
10505
10698
  closeOnOutside: true,
10506
10699
  label: trigger && trigger.type === "slash" ? "Commands" : "Mentions",
10507
- children: /* @__PURE__ */ jsx81(
10700
+ children: /* @__PURE__ */ jsx82(
10508
10701
  Menu,
10509
10702
  {
10510
10703
  items: menuItems,
10511
10704
  autoFocus: false,
10512
- header: /* @__PURE__ */ jsx81("div", { className: "fd-pop-group", children: trigger && trigger.type === "slash" ? "Commands" : "Attach context" }),
10705
+ header: /* @__PURE__ */ jsx82("div", { className: "fd-pop-group", children: trigger && trigger.type === "slash" ? "Commands" : "Attach context" }),
10513
10706
  onClose: () => setTrigger(null)
10514
10707
  }
10515
10708
  )
@@ -10519,12 +10712,12 @@ function ChatComposer({
10519
10712
  }
10520
10713
 
10521
10714
  // src/components/chat/ChatSessionBar.tsx
10522
- import * as React54 from "react";
10523
- import { jsx as jsx82, jsxs as jsxs76 } from "react/jsx-runtime";
10715
+ import * as React55 from "react";
10716
+ import { jsx as jsx83, jsxs as jsxs77 } from "react/jsx-runtime";
10524
10717
  var compact2 = meterFormats.compact;
10525
10718
  function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extras }) {
10526
- const [open, setOpen] = React54.useState(false);
10527
- const anchor = React54.useRef(null);
10719
+ const [open, setOpen] = React55.useState(false);
10720
+ const anchor = React55.useRef(null);
10528
10721
  const stats = sessionStats || null;
10529
10722
  const cu = contextUsage || null;
10530
10723
  const limits = usageLimits || null;
@@ -10539,9 +10732,9 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
10539
10732
  if (stats && stats.runningTasks) bits.push(stats.runningTasks + " running task" + (stats.runningTasks === 1 ? "" : "s"));
10540
10733
  if (cu) bits.push(pct + "% context");
10541
10734
  const expandable = !!(cu || limits);
10542
- return /* @__PURE__ */ jsxs76(React54.Fragment, { children: [
10543
- /* @__PURE__ */ jsxs76("div", { className: "fdc-bar", children: [
10544
- /* @__PURE__ */ jsxs76(
10735
+ return /* @__PURE__ */ jsxs77(React55.Fragment, { children: [
10736
+ /* @__PURE__ */ jsxs77("div", { className: "fdc-bar", children: [
10737
+ /* @__PURE__ */ jsxs77(
10545
10738
  "button",
10546
10739
  {
10547
10740
  type: "button",
@@ -10552,15 +10745,15 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
10552
10745
  "aria-expanded": expandable ? open : void 0,
10553
10746
  "aria-label": expandable ? "Usage details" : void 0,
10554
10747
  children: [
10555
- cu ? /* @__PURE__ */ jsx82("span", { className: "fdc-bar-mini", "aria-hidden": "true", children: /* @__PURE__ */ jsx82(SegmentedMeter, { total, segments: cu.segments, height: 4, showTotal: false }) }) : null,
10556
- /* @__PURE__ */ jsx82("span", { className: "fdc-bar-text", title: truncationTitle(bits.join(" \xB7 ")), children: bits.join(" \xB7 ") }),
10557
- expandable ? /* @__PURE__ */ jsx82("i", { className: "ph ph-caret-right fdc-bar-caret", "aria-hidden": "true" }) : null
10748
+ cu ? /* @__PURE__ */ jsx83("span", { className: "fdc-bar-mini", "aria-hidden": "true", children: /* @__PURE__ */ jsx83(SegmentedMeter, { total, segments: cu.segments, height: 4, showTotal: false }) }) : null,
10749
+ /* @__PURE__ */ jsx83("span", { className: "fdc-bar-text", title: truncationTitle(bits.join(" \xB7 ")), children: bits.join(" \xB7 ") }),
10750
+ expandable ? /* @__PURE__ */ jsx83("i", { className: "ph ph-caret-right fdc-bar-caret", "aria-hidden": "true" }) : null
10558
10751
  ]
10559
10752
  }
10560
10753
  ),
10561
10754
  extras
10562
10755
  ] }),
10563
- /* @__PURE__ */ jsx82(
10756
+ /* @__PURE__ */ jsx83(
10564
10757
  Popover,
10565
10758
  {
10566
10759
  open,
@@ -10571,15 +10764,15 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
10571
10764
  maxHeight: 460,
10572
10765
  padded: true,
10573
10766
  label: "Usage",
10574
- footer: onClear ? /* @__PURE__ */ jsxs76("button", { type: "button", className: "fdc-usage-clear", onClick: () => {
10767
+ footer: onClear ? /* @__PURE__ */ jsxs77("button", { type: "button", className: "fdc-usage-clear", onClick: () => {
10575
10768
  setOpen(false);
10576
10769
  onClear();
10577
10770
  }, children: [
10578
- /* @__PURE__ */ jsx82("i", { className: "ph ph-trash", "aria-hidden": "true" }),
10771
+ /* @__PURE__ */ jsx83("i", { className: "ph ph-trash", "aria-hidden": "true" }),
10579
10772
  "Clear conversation"
10580
10773
  ] }) : void 0,
10581
- children: /* @__PURE__ */ jsxs76("div", { className: "fdc-usage", children: [
10582
- cu ? /* @__PURE__ */ jsx82("section", { className: "fdc-usage-sec", children: /* @__PURE__ */ jsx82(
10774
+ children: /* @__PURE__ */ jsxs77("div", { className: "fdc-usage", children: [
10775
+ cu ? /* @__PURE__ */ jsx83("section", { className: "fdc-usage-sec", children: /* @__PURE__ */ jsx83(
10583
10776
  SegmentedMeter,
10584
10777
  {
10585
10778
  total,
@@ -10591,9 +10784,9 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
10591
10784
  remainderLabel: "Free"
10592
10785
  }
10593
10786
  ) }) : null,
10594
- limits && limits.length ? /* @__PURE__ */ jsxs76("section", { className: "fdc-usage-sec", children: [
10595
- /* @__PURE__ */ jsx82("h4", { className: "fdc-usage-h", children: "Usage limits" }),
10596
- /* @__PURE__ */ jsx82("div", { className: "fdc-usage-rows", children: limits.map((l) => /* @__PURE__ */ jsx82(
10787
+ limits && limits.length ? /* @__PURE__ */ jsxs77("section", { className: "fdc-usage-sec", children: [
10788
+ /* @__PURE__ */ jsx83("h4", { className: "fdc-usage-h", children: "Usage limits" }),
10789
+ /* @__PURE__ */ jsx83("div", { className: "fdc-usage-rows", children: limits.map((l) => /* @__PURE__ */ jsx83(
10597
10790
  QuotaRow,
10598
10791
  {
10599
10792
  label: l.label,
@@ -10603,25 +10796,25 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
10603
10796
  l.id
10604
10797
  )) })
10605
10798
  ] }) : null,
10606
- stats ? /* @__PURE__ */ jsxs76("section", { className: "fdc-usage-sec fdc-usage-stats", children: [
10607
- stats.elapsedMs ? /* @__PURE__ */ jsxs76("div", { children: [
10608
- /* @__PURE__ */ jsx82("span", { children: "Session" }),
10609
- /* @__PURE__ */ jsx82("b", { className: "fd-tabular", children: formatDuration(stats.elapsedMs) })
10799
+ stats ? /* @__PURE__ */ jsxs77("section", { className: "fdc-usage-sec fdc-usage-stats", children: [
10800
+ stats.elapsedMs ? /* @__PURE__ */ jsxs77("div", { children: [
10801
+ /* @__PURE__ */ jsx83("span", { children: "Session" }),
10802
+ /* @__PURE__ */ jsx83("b", { className: "fd-tabular", children: formatDuration(stats.elapsedMs) })
10610
10803
  ] }) : null,
10611
- stats.tokens ? /* @__PURE__ */ jsxs76("div", { children: [
10612
- /* @__PURE__ */ jsx82("span", { children: "Tokens" }),
10613
- /* @__PURE__ */ jsx82("b", { className: "fd-tabular", children: stats.tokens.toLocaleString() })
10804
+ stats.tokens ? /* @__PURE__ */ jsxs77("div", { children: [
10805
+ /* @__PURE__ */ jsx83("span", { children: "Tokens" }),
10806
+ /* @__PURE__ */ jsx83("b", { className: "fd-tabular", children: stats.tokens.toLocaleString() })
10614
10807
  ] }) : null,
10615
- stats.costUsd != null ? /* @__PURE__ */ jsxs76("div", { children: [
10616
- /* @__PURE__ */ jsx82("span", { children: "Cost" }),
10617
- /* @__PURE__ */ jsxs76("b", { className: "fd-tabular", children: [
10808
+ stats.costUsd != null ? /* @__PURE__ */ jsxs77("div", { children: [
10809
+ /* @__PURE__ */ jsx83("span", { children: "Cost" }),
10810
+ /* @__PURE__ */ jsxs77("b", { className: "fd-tabular", children: [
10618
10811
  "$",
10619
10812
  Number(stats.costUsd).toFixed(3)
10620
10813
  ] })
10621
10814
  ] }) : null,
10622
- stats.turns ? /* @__PURE__ */ jsxs76("div", { children: [
10623
- /* @__PURE__ */ jsx82("span", { children: "Turns" }),
10624
- /* @__PURE__ */ jsx82("b", { className: "fd-tabular", children: stats.turns })
10815
+ stats.turns ? /* @__PURE__ */ jsxs77("div", { children: [
10816
+ /* @__PURE__ */ jsx83("span", { children: "Turns" }),
10817
+ /* @__PURE__ */ jsx83("b", { className: "fd-tabular", children: stats.turns })
10625
10818
  ] }) : null
10626
10819
  ] }) : null
10627
10820
  ] })
@@ -10660,7 +10853,7 @@ function ModelControls({
10660
10853
  disabled: m.disabled,
10661
10854
  checked: m.id === (current2 && current2.id),
10662
10855
  meta: m.meta,
10663
- shortcut: m.shortcut ? /* @__PURE__ */ jsx82(KeyHint, { keys: m.shortcut, size: "sm" }) : void 0,
10856
+ shortcut: m.shortcut ? /* @__PURE__ */ jsx83(KeyHint, { keys: m.shortcut, size: "sm" }) : void 0,
10664
10857
  onSelect: () => onModelChange && onModelChange(m.id)
10665
10858
  });
10666
10859
  const items = [{ kind: "section", label: "Models" }].concat(flat.map(item));
@@ -10673,15 +10866,15 @@ function ModelControls({
10673
10866
  items.push({ kind: "section", label: "Fast mode" });
10674
10867
  items.push({
10675
10868
  kind: "custom",
10676
- render: () => /* @__PURE__ */ jsxs76("label", { className: "fdc-switchrow", children: [
10677
- /* @__PURE__ */ jsx82("span", { children: fastModeLabel }),
10678
- /* @__PURE__ */ jsx82("input", { type: "checkbox", className: "fd-sr", checked: !!fastMode, onChange: (e) => onFastModeChange(e.target.checked) }),
10679
- /* @__PURE__ */ jsx82("span", { className: "fd-switch-track" + (fastMode ? " is-on" : ""), "aria-hidden": "true", children: /* @__PURE__ */ jsx82("span", { className: "fd-switch-thumb" }) })
10869
+ render: () => /* @__PURE__ */ jsxs77("label", { className: "fdc-switchrow", children: [
10870
+ /* @__PURE__ */ jsx83("span", { children: fastModeLabel }),
10871
+ /* @__PURE__ */ jsx83("input", { type: "checkbox", className: "fd-sr", checked: !!fastMode, onChange: (e) => onFastModeChange(e.target.checked) }),
10872
+ /* @__PURE__ */ jsx83("span", { className: "fd-switch-track" + (fastMode ? " is-on" : ""), "aria-hidden": "true", children: /* @__PURE__ */ jsx83("span", { className: "fd-switch-thumb" }) })
10680
10873
  ] })
10681
10874
  });
10682
10875
  }
10683
- return /* @__PURE__ */ jsxs76(React54.Fragment, { children: [
10684
- /* @__PURE__ */ jsx82(
10876
+ return /* @__PURE__ */ jsxs77(React55.Fragment, { children: [
10877
+ /* @__PURE__ */ jsx83(
10685
10878
  MenuButton,
10686
10879
  {
10687
10880
  items,
@@ -10692,7 +10885,7 @@ function ModelControls({
10692
10885
  title: "Choose a model"
10693
10886
  }
10694
10887
  ),
10695
- effortLevels && effortLevels.length ? /* @__PURE__ */ jsx82(
10888
+ effortLevels && effortLevels.length ? /* @__PURE__ */ jsx83(
10696
10889
  MenuButton,
10697
10890
  {
10698
10891
  placement: "top-end",
@@ -10713,7 +10906,7 @@ function ModelControls({
10713
10906
  }
10714
10907
 
10715
10908
  // src/components/chat/AgentChatPanel.tsx
10716
- import { jsx as jsx83, jsxs as jsxs77 } from "react/jsx-runtime";
10909
+ import { jsx as jsx84, jsxs as jsxs78 } from "react/jsx-runtime";
10717
10910
  var SURFACES = { sidebar: "is-sidebar", inline: "is-inline", page: "is-page", modal: "is-modal", sheet: "is-sheet" };
10718
10911
  function AgentChatPanel({
10719
10912
  /* required */
@@ -10797,11 +10990,11 @@ function AgentChatPanel({
10797
10990
  onFeedback,
10798
10991
  onEditMessage
10799
10992
  }) {
10800
- const [panelWidth, setPanelWidth] = React55.useState(width);
10801
- const [applied, setApplied] = React55.useState({});
10802
- const [draft, setDraft] = React55.useState("");
10803
- const dragging = React55.useRef(null);
10804
- React55.useEffect(() => setPanelWidth(width), [width]);
10993
+ const [panelWidth, setPanelWidth] = React56.useState(width);
10994
+ const [applied, setApplied] = React56.useState({});
10995
+ const [draft, setDraft] = React56.useState("");
10996
+ const dragging = React56.useRef(null);
10997
+ React56.useEffect(() => setPanelWidth(width), [width]);
10805
10998
  const engine = useChatEngine({
10806
10999
  contextType,
10807
11000
  contextId,
@@ -10867,7 +11060,7 @@ function AgentChatPanel({
10867
11060
  onReconnect: engine.reload,
10868
11061
  deadTitle: "The assistant isn\u2019t reachable"
10869
11062
  };
10870
- const sessionBar = /* @__PURE__ */ jsx83(
11063
+ const sessionBar = /* @__PURE__ */ jsx84(
10871
11064
  ChatSessionBar,
10872
11065
  {
10873
11066
  sessionStats,
@@ -10876,7 +11069,7 @@ function AgentChatPanel({
10876
11069
  onClear: engine.visible.length ? engine.clear : void 0
10877
11070
  }
10878
11071
  );
10879
- const modelControls = /* @__PURE__ */ jsx83(
11072
+ const modelControls = /* @__PURE__ */ jsx84(
10880
11073
  ModelControls,
10881
11074
  {
10882
11075
  models,
@@ -10891,7 +11084,7 @@ function AgentChatPanel({
10891
11084
  narrow
10892
11085
  }
10893
11086
  );
10894
- const threadMenu = threads && threads.length ? /* @__PURE__ */ jsx83(
11087
+ const threadMenu = threads && threads.length ? /* @__PURE__ */ jsx84(
10895
11088
  MenuButton,
10896
11089
  {
10897
11090
  variant: "ghost",
@@ -10918,7 +11111,7 @@ function AgentChatPanel({
10918
11111
  })))
10919
11112
  }
10920
11113
  ) : null;
10921
- return /* @__PURE__ */ jsxs77(
11114
+ return /* @__PURE__ */ jsxs78(
10922
11115
  "aside",
10923
11116
  {
10924
11117
  className: ["fdc-panel", SURFACES[surface] || SURFACES.sidebar, narrow ? "is-narrow" : "", className].filter(Boolean).join(" "),
@@ -10929,7 +11122,7 @@ function AgentChatPanel({
10929
11122
  },
10930
11123
  "aria-label": title,
10931
11124
  children: [
10932
- surface === "sidebar" && resizable ? /* @__PURE__ */ jsx83(
11125
+ surface === "sidebar" && resizable ? /* @__PURE__ */ jsx84(
10933
11126
  "div",
10934
11127
  {
10935
11128
  className: "fdc-grip",
@@ -10944,20 +11137,20 @@ function AgentChatPanel({
10944
11137
  }
10945
11138
  }
10946
11139
  ) : null,
10947
- showHeader ? /* @__PURE__ */ jsxs77("header", { className: "fdc-head", children: [
10948
- /* @__PURE__ */ jsx83("span", { className: "fdc-head-mark", "aria-hidden": "true", children: /* @__PURE__ */ jsx83("i", { className: "ph ph-" + assistantIcon }) }),
10949
- /* @__PURE__ */ jsxs77("span", { className: "fdc-head-titles", children: [
10950
- /* @__PURE__ */ jsx83("span", { className: "fdc-head-title", title: truncationTitle(title), children: title }),
10951
- subtitle ? /* @__PURE__ */ jsx83("span", { className: "fdc-head-sub", title: truncationTitle(subtitle), children: subtitle }) : null
11140
+ showHeader ? /* @__PURE__ */ jsxs78("header", { className: "fdc-head", children: [
11141
+ /* @__PURE__ */ jsx84("span", { className: "fdc-head-mark", "aria-hidden": "true", children: /* @__PURE__ */ jsx84("i", { className: "ph ph-" + assistantIcon }) }),
11142
+ /* @__PURE__ */ jsxs78("span", { className: "fdc-head-titles", children: [
11143
+ /* @__PURE__ */ jsx84("span", { className: "fdc-head-title", title: truncationTitle(title), children: title }),
11144
+ subtitle ? /* @__PURE__ */ jsx84("span", { className: "fdc-head-sub", title: truncationTitle(subtitle), children: subtitle }) : null
10952
11145
  ] }),
10953
- /* @__PURE__ */ jsxs77("span", { className: "fdc-head-acts", children: [
11146
+ /* @__PURE__ */ jsxs78("span", { className: "fdc-head-acts", children: [
10954
11147
  headerActions,
10955
11148
  threadMenu,
10956
- onNewThread ? /* @__PURE__ */ jsx83("button", { type: "button", className: "fdc-iconbtn", onClick: onNewThread, "aria-label": "New conversation", title: "New conversation", children: /* @__PURE__ */ jsx83("i", { className: "ph ph-plus", "aria-hidden": "true" }) }) : null,
10957
- onClose ? /* @__PURE__ */ jsx83("button", { type: "button", className: "fdc-iconbtn", onClick: onClose, "aria-label": "Close panel", title: "Close", children: /* @__PURE__ */ jsx83("i", { className: "ph ph-x", "aria-hidden": "true" }) }) : null
11149
+ onNewThread ? /* @__PURE__ */ jsx84("button", { type: "button", className: "fdc-iconbtn", onClick: onNewThread, "aria-label": "New conversation", title: "New conversation", children: /* @__PURE__ */ jsx84("i", { className: "ph ph-plus", "aria-hidden": "true" }) }) : null,
11150
+ onClose ? /* @__PURE__ */ jsx84("button", { type: "button", className: "fdc-iconbtn", onClick: onClose, "aria-label": "Close panel", title: "Close", children: /* @__PURE__ */ jsx84("i", { className: "ph ph-x", "aria-hidden": "true" }) }) : null
10958
11151
  ] })
10959
11152
  ] }) : null,
10960
- /* @__PURE__ */ jsx83(
11153
+ /* @__PURE__ */ jsx84(
10961
11154
  ChatTranscript,
10962
11155
  {
10963
11156
  messages: engine.visible,
@@ -10972,7 +11165,7 @@ function AgentChatPanel({
10972
11165
  renderEmpty
10973
11166
  }
10974
11167
  ),
10975
- /* @__PURE__ */ jsx83(
11168
+ /* @__PURE__ */ jsx84(
10976
11169
  ChatComposer,
10977
11170
  {
10978
11171
  onSubmit: (text, atts) => engine.send(text, atts),
@@ -11005,8 +11198,8 @@ function AgentChatPanel({
11005
11198
  }
11006
11199
 
11007
11200
  // src/components/files/FileViewer.tsx
11008
- import * as React56 from "react";
11009
- import { jsx as jsx84, jsxs as jsxs78 } from "react/jsx-runtime";
11201
+ import * as React57 from "react";
11202
+ import { jsx as jsx85, jsxs as jsxs79 } from "react/jsx-runtime";
11010
11203
  function previewKindOf(file) {
11011
11204
  const mime = (file.mime || "").toLowerCase();
11012
11205
  const ext = extensionOf(file.name || "");
@@ -11062,13 +11255,13 @@ function parseDelimited(text, delimiter) {
11062
11255
  return rows;
11063
11256
  }
11064
11257
  function usePreview(file, kind, resolveUrl) {
11065
- const [state, setState] = React56.useState({ status: "loading" });
11066
- const [attempt, setAttempt] = React56.useState(0);
11067
- const resolveRef = React56.useRef(resolveUrl);
11068
- React56.useEffect(() => {
11258
+ const [state, setState] = React57.useState({ status: "loading" });
11259
+ const [attempt, setAttempt] = React57.useState(0);
11260
+ const resolveRef = React57.useRef(resolveUrl);
11261
+ React57.useEffect(() => {
11069
11262
  resolveRef.current = resolveUrl;
11070
11263
  }, [resolveUrl]);
11071
- React56.useEffect(() => {
11264
+ React57.useEffect(() => {
11072
11265
  if (kind === "none") {
11073
11266
  setState({ status: "ready" });
11074
11267
  return;
@@ -11098,19 +11291,19 @@ function usePreview(file, kind, resolveUrl) {
11098
11291
  if (ac) ac.abort();
11099
11292
  };
11100
11293
  }, [file.id, kind, attempt]);
11101
- return { ...state, retry: React56.useCallback(() => setAttempt((a) => a + 1), []) };
11294
+ return { ...state, retry: React57.useCallback(() => setAttempt((a) => a + 1), []) };
11102
11295
  }
11103
11296
  function PreviewBody({ file, kind, state }) {
11104
- if (kind === "image") return /* @__PURE__ */ jsx84("img", { className: "fd-fv-image", src: state.url, alt: file.name || "Preview" });
11105
- if (kind === "pdf") return /* @__PURE__ */ jsx84("iframe", { className: "fd-fv-pdf", src: state.url, title: file.name || "PDF preview" });
11106
- if (kind === "markdown") return /* @__PURE__ */ jsx84(Markdown, { className: "fd-fv-markdown", source: state.text || "" });
11297
+ if (kind === "image") return /* @__PURE__ */ jsx85("img", { className: "fd-fv-image", src: state.url, alt: file.name || "Preview" });
11298
+ if (kind === "pdf") return /* @__PURE__ */ jsx85("iframe", { className: "fd-fv-pdf", src: state.url, title: file.name || "PDF preview" });
11299
+ if (kind === "markdown") return /* @__PURE__ */ jsx85(Markdown, { className: "fd-fv-markdown", source: state.text || "" });
11107
11300
  if (kind === "json") {
11108
11301
  let pretty = state.text || "";
11109
11302
  try {
11110
11303
  pretty = JSON.stringify(JSON.parse(pretty), null, 2);
11111
11304
  } catch {
11112
11305
  }
11113
- return /* @__PURE__ */ jsx84(CodeBlock, { code: pretty, language: "json" });
11306
+ return /* @__PURE__ */ jsx85(CodeBlock, { code: pretty, language: "json" });
11114
11307
  }
11115
11308
  if (kind === "csv") {
11116
11309
  const tsv = extensionOf(file.name || "") === "tsv" || (file.mime || "").toLowerCase().includes("tab-separated");
@@ -11118,12 +11311,12 @@ function PreviewBody({ file, kind, state }) {
11118
11311
  const head = rows[0] || [];
11119
11312
  const dataRows = rows.slice(1);
11120
11313
  const shown = dataRows.slice(0, FILE_VIEWER_CSV_ROW_LIMIT);
11121
- return /* @__PURE__ */ jsxs78("div", { className: "fd-fv-csv", children: [
11122
- /* @__PURE__ */ jsxs78("table", { className: "fd-fv-csv-table", children: [
11123
- /* @__PURE__ */ jsx84("thead", { children: /* @__PURE__ */ jsx84("tr", { children: head.map((c, i) => /* @__PURE__ */ jsx84("th", { children: c }, i)) }) }),
11124
- /* @__PURE__ */ jsx84("tbody", { children: shown.map((r, ri) => /* @__PURE__ */ jsx84("tr", { children: head.map((_, ci) => /* @__PURE__ */ jsx84("td", { children: r[ci] ?? "" }, ci)) }, ri)) })
11314
+ return /* @__PURE__ */ jsxs79("div", { className: "fd-fv-csv", children: [
11315
+ /* @__PURE__ */ jsxs79("table", { className: "fd-fv-csv-table", children: [
11316
+ /* @__PURE__ */ jsx85("thead", { children: /* @__PURE__ */ jsx85("tr", { children: head.map((c, i) => /* @__PURE__ */ jsx85("th", { children: c }, i)) }) }),
11317
+ /* @__PURE__ */ jsx85("tbody", { children: shown.map((r, ri) => /* @__PURE__ */ jsx85("tr", { children: head.map((_, ci) => /* @__PURE__ */ jsx85("td", { children: r[ci] ?? "" }, ci)) }, ri)) })
11125
11318
  ] }),
11126
- dataRows.length > FILE_VIEWER_CSV_ROW_LIMIT ? /* @__PURE__ */ jsxs78("p", { className: "fd-fv-csv-note fd-body-sm fd-muted", children: [
11319
+ dataRows.length > FILE_VIEWER_CSV_ROW_LIMIT ? /* @__PURE__ */ jsxs79("p", { className: "fd-fv-csv-note fd-body-sm fd-muted", children: [
11127
11320
  "Showing the first ",
11128
11321
  FILE_VIEWER_CSV_ROW_LIMIT.toLocaleString(),
11129
11322
  " of ",
@@ -11132,24 +11325,24 @@ function PreviewBody({ file, kind, state }) {
11132
11325
  ] }) : null
11133
11326
  ] });
11134
11327
  }
11135
- if (kind === "text") return /* @__PURE__ */ jsx84(CodeBlock, { code: state.text || "", language: extensionOf(file.name || "") || void 0 });
11136
- return /* @__PURE__ */ jsxs78("div", { className: "fd-fv-fallback", children: [
11137
- /* @__PURE__ */ jsx84("span", { className: "fd-fv-fallback-icon", "aria-hidden": "true", children: /* @__PURE__ */ jsx84("i", { className: "ph ph-" + iconForMime(file.mime, file.name) }) }),
11138
- /* @__PURE__ */ jsx84("span", { className: "fd-fv-fallback-title", children: "No preview available" }),
11139
- /* @__PURE__ */ jsxs78("span", { className: "fd-fv-fallback-meta", children: [
11328
+ if (kind === "text") return /* @__PURE__ */ jsx85(CodeBlock, { code: state.text || "", language: extensionOf(file.name || "") || void 0 });
11329
+ return /* @__PURE__ */ jsxs79("div", { className: "fd-fv-fallback", children: [
11330
+ /* @__PURE__ */ jsx85("span", { className: "fd-fv-fallback-icon", "aria-hidden": "true", children: /* @__PURE__ */ jsx85("i", { className: "ph ph-" + iconForMime(file.mime, file.name) }) }),
11331
+ /* @__PURE__ */ jsx85("span", { className: "fd-fv-fallback-title", children: "No preview available" }),
11332
+ /* @__PURE__ */ jsxs79("span", { className: "fd-fv-fallback-meta", children: [
11140
11333
  file.mime || "Unknown type",
11141
11334
  file.size ? " \xB7 " + formatBytes(file.size) : ""
11142
11335
  ] })
11143
11336
  ] });
11144
11337
  }
11145
11338
  function FileViewer({ file, resolveUrl, sidePanel, sidePanelLabel = "Details", onClose, actions, className = "" }) {
11146
- const kind = React56.useMemo(() => previewKindOf(file), [file]);
11339
+ const kind = React57.useMemo(() => previewKindOf(file), [file]);
11147
11340
  const preview = usePreview(file, kind, resolveUrl);
11148
- const [tab, setTab] = React56.useState("preview");
11149
- const [downloading, setDownloading] = React56.useState(false);
11150
- const [downloadError, setDownloadError] = React56.useState(null);
11341
+ const [tab, setTab] = React57.useState("preview");
11342
+ const [downloading, setDownloading] = React57.useState(false);
11343
+ const [downloadError, setDownloadError] = React57.useState(null);
11151
11344
  const hasSide = sidePanel != null;
11152
- React56.useEffect(() => {
11345
+ React57.useEffect(() => {
11153
11346
  setTab("preview");
11154
11347
  }, [file.id]);
11155
11348
  const download = () => {
@@ -11165,29 +11358,29 @@ function FileViewer({ file, resolveUrl, sidePanel, sidePanelLabel = "Details", o
11165
11358
  a.remove();
11166
11359
  }).catch((err) => setDownloadError(err && err.message || "Download failed.")).finally(() => setDownloading(false));
11167
11360
  };
11168
- return /* @__PURE__ */ jsxs78(
11361
+ return /* @__PURE__ */ jsxs79(
11169
11362
  "section",
11170
11363
  {
11171
11364
  className: ["fd-fv", hasSide && tab === "side" ? "is-tab-side" : "is-tab-preview", className].filter(Boolean).join(" "),
11172
11365
  "aria-label": file.name || "File",
11173
11366
  children: [
11174
- /* @__PURE__ */ jsxs78("header", { className: "fd-fv-head", children: [
11175
- /* @__PURE__ */ jsx84("span", { className: "fd-fv-head-icon", "aria-hidden": "true", children: /* @__PURE__ */ jsx84("i", { className: "ph ph-" + iconForMime(file.mime, file.name) }) }),
11176
- /* @__PURE__ */ jsxs78("span", { className: "fd-fv-head-titles", children: [
11177
- /* @__PURE__ */ jsx84("span", { className: "fd-fv-head-title", title: file.name, children: file.name }),
11178
- /* @__PURE__ */ jsxs78("span", { className: "fd-fv-head-meta", children: [
11367
+ /* @__PURE__ */ jsxs79("header", { className: "fd-fv-head", children: [
11368
+ /* @__PURE__ */ jsx85("span", { className: "fd-fv-head-icon", "aria-hidden": "true", children: /* @__PURE__ */ jsx85("i", { className: "ph ph-" + iconForMime(file.mime, file.name) }) }),
11369
+ /* @__PURE__ */ jsxs79("span", { className: "fd-fv-head-titles", children: [
11370
+ /* @__PURE__ */ jsx85("span", { className: "fd-fv-head-title", title: file.name, children: file.name }),
11371
+ /* @__PURE__ */ jsxs79("span", { className: "fd-fv-head-meta", children: [
11179
11372
  file.mime || "Unknown type",
11180
11373
  file.size ? " \xB7 " + formatBytes(file.size) : ""
11181
11374
  ] })
11182
11375
  ] }),
11183
- /* @__PURE__ */ jsxs78("span", { className: "fd-fv-head-actions", children: [
11376
+ /* @__PURE__ */ jsxs79("span", { className: "fd-fv-head-actions", children: [
11184
11377
  actions,
11185
- /* @__PURE__ */ jsx84(Button, { variant: "secondary", size: "sm", icon: "download-simple", loading: downloading, onClick: download, children: "Download" }),
11186
- onClose ? /* @__PURE__ */ jsx84(IconButton, { icon: "x", label: "Close", onClick: onClose }) : null
11378
+ /* @__PURE__ */ jsx85(Button, { variant: "secondary", size: "sm", icon: "download-simple", loading: downloading, onClick: download, children: "Download" }),
11379
+ onClose ? /* @__PURE__ */ jsx85(IconButton, { icon: "x", label: "Close", onClick: onClose }) : null
11187
11380
  ] })
11188
11381
  ] }),
11189
- downloadError ? /* @__PURE__ */ jsx84("div", { className: "fd-fv-download-error", role: "alert", children: downloadError }) : null,
11190
- hasSide ? /* @__PURE__ */ jsx84(
11382
+ downloadError ? /* @__PURE__ */ jsx85("div", { className: "fd-fv-download-error", role: "alert", children: downloadError }) : null,
11383
+ hasSide ? /* @__PURE__ */ jsx85(
11191
11384
  Tabs,
11192
11385
  {
11193
11386
  className: "fd-fv-tabs",
@@ -11196,19 +11389,19 @@ function FileViewer({ file, resolveUrl, sidePanel, sidePanelLabel = "Details", o
11196
11389
  onChange: (v) => setTab(v)
11197
11390
  }
11198
11391
  ) : null,
11199
- /* @__PURE__ */ jsxs78("div", { className: "fd-fv-body", children: [
11200
- /* @__PURE__ */ jsx84("div", { className: "fd-fv-preview", role: "region", "aria-label": "Preview of " + (file.name || "file"), children: /* @__PURE__ */ jsx84(
11392
+ /* @__PURE__ */ jsxs79("div", { className: "fd-fv-body", children: [
11393
+ /* @__PURE__ */ jsx85("div", { className: "fd-fv-preview", role: "region", "aria-label": "Preview of " + (file.name || "file"), children: /* @__PURE__ */ jsx85(
11201
11394
  LoadingRegion,
11202
11395
  {
11203
11396
  state: preview.status === "loading" ? "loading" : preview.status === "error" ? "error" : "ready",
11204
11397
  error: preview.error,
11205
11398
  label: "Loading preview of " + (file.name || "file"),
11206
11399
  onRetry: preview.status === "error" ? preview.retry : void 0,
11207
- skeleton: /* @__PURE__ */ jsx84(Skeleton, { shape: "card", h: 220 }),
11208
- children: /* @__PURE__ */ jsx84(PreviewBody, { file, kind, state: preview })
11400
+ skeleton: /* @__PURE__ */ jsx85(Skeleton, { shape: "card", h: 220 }),
11401
+ children: /* @__PURE__ */ jsx85(PreviewBody, { file, kind, state: preview })
11209
11402
  }
11210
11403
  ) }),
11211
- hasSide ? /* @__PURE__ */ jsx84("div", { className: "fd-fv-side", role: "region", "aria-label": sidePanelLabel, children: sidePanel }) : null
11404
+ hasSide ? /* @__PURE__ */ jsx85("div", { className: "fd-fv-side", role: "region", "aria-label": sidePanelLabel, children: sidePanel }) : null
11212
11405
  ] })
11213
11406
  ]
11214
11407
  }
@@ -11216,8 +11409,8 @@ function FileViewer({ file, resolveUrl, sidePanel, sidePanelLabel = "Details", o
11216
11409
  }
11217
11410
 
11218
11411
  // src/components/files/FileBrowser.tsx
11219
- import * as React57 from "react";
11220
- import { Fragment as Fragment26, jsx as jsx85, jsxs as jsxs79 } from "react/jsx-runtime";
11412
+ import * as React58 from "react";
11413
+ import { Fragment as Fragment27, jsx as jsx86, jsxs as jsxs80 } from "react/jsx-runtime";
11221
11414
  function childrenOf(folders, parentId) {
11222
11415
  return folders.filter((f) => f.parentId === parentId).sort((a, b) => a.name.localeCompare(b.name));
11223
11416
  }
@@ -11287,10 +11480,10 @@ function FolderPickerMenu({
11287
11480
  destinations,
11288
11481
  onPick
11289
11482
  }) {
11290
- const [open, setOpen] = React57.useState(false);
11483
+ const [open, setOpen] = React58.useState(false);
11291
11484
  const zIndex = useOverlayLayer(open);
11292
- const ref = React57.useRef(null);
11293
- React57.useEffect(() => {
11485
+ const ref = React58.useRef(null);
11486
+ React58.useEffect(() => {
11294
11487
  if (!open) return;
11295
11488
  const away = (e) => {
11296
11489
  if (ref.current && !ref.current.contains(e.target)) setOpen(false);
@@ -11305,8 +11498,8 @@ function FolderPickerMenu({
11305
11498
  document.removeEventListener("keydown", esc);
11306
11499
  };
11307
11500
  }, [open]);
11308
- return /* @__PURE__ */ jsxs79("span", { className: "fd-fb-menu-anchor", ref, children: [
11309
- /* @__PURE__ */ jsx85(
11501
+ return /* @__PURE__ */ jsxs80("span", { className: "fd-fb-menu-anchor", ref, children: [
11502
+ /* @__PURE__ */ jsx86(
11310
11503
  IconButton,
11311
11504
  {
11312
11505
  icon: "arrows-out-cardinal",
@@ -11318,9 +11511,9 @@ function FolderPickerMenu({
11318
11511
  onClick: () => setOpen((v) => !v)
11319
11512
  }
11320
11513
  ),
11321
- open ? /* @__PURE__ */ jsx85(LayerProvider, { zIndex, children: /* @__PURE__ */ jsxs79("div", { className: "fd-fb-menu", role: "menu", "aria-label": label, style: { zIndex }, children: [
11322
- /* @__PURE__ */ jsx85("span", { className: "fd-overline fd-muted fd-fb-menu-title", children: "Move to\u2026" }),
11323
- destinations.map((d) => /* @__PURE__ */ jsxs79(
11514
+ open ? /* @__PURE__ */ jsx86(LayerProvider, { zIndex, children: /* @__PURE__ */ jsxs80("div", { className: "fd-fb-menu", role: "menu", "aria-label": label, style: { zIndex }, children: [
11515
+ /* @__PURE__ */ jsx86("span", { className: "fd-overline fd-muted fd-fb-menu-title", children: "Move to\u2026" }),
11516
+ destinations.map((d) => /* @__PURE__ */ jsxs80(
11324
11517
  "button",
11325
11518
  {
11326
11519
  type: "button",
@@ -11332,7 +11525,7 @@ function FolderPickerMenu({
11332
11525
  setOpen(false);
11333
11526
  },
11334
11527
  children: [
11335
- /* @__PURE__ */ jsx85("i", { className: "ph ph-" + (d.id == null ? "house-simple" : "folder-simple"), "aria-hidden": "true" }),
11528
+ /* @__PURE__ */ jsx86("i", { className: "ph ph-" + (d.id == null ? "house-simple" : "folder-simple"), "aria-hidden": "true" }),
11336
11529
  d.name
11337
11530
  ]
11338
11531
  },
@@ -11342,8 +11535,8 @@ function FolderPickerMenu({
11342
11535
  ] });
11343
11536
  }
11344
11537
  function RowShell({ icon, name, meta, onOpen, draggableId, isDropTarget, onDropPayload, actions, className = "" }) {
11345
- const [over, setOver] = React57.useState(false);
11346
- const dragCounter = React57.useRef(0);
11538
+ const [over, setOver] = React58.useState(false);
11539
+ const dragCounter = React58.useRef(0);
11347
11540
  const dropHandlers = isDropTarget ? {
11348
11541
  onDragEnter: (e) => {
11349
11542
  if (!hasInternalPayload(e)) return;
@@ -11368,8 +11561,8 @@ function RowShell({ icon, name, meta, onOpen, draggableId, isDropTarget, onDropP
11368
11561
  if (payload && onDropPayload) onDropPayload(payload);
11369
11562
  }
11370
11563
  } : {};
11371
- return /* @__PURE__ */ jsxs79("div", { className: ["fd-fb-row", over ? "is-drop-target" : "", className].filter(Boolean).join(" "), ...dropHandlers, children: [
11372
- /* @__PURE__ */ jsxs79(
11564
+ return /* @__PURE__ */ jsxs80("div", { className: ["fd-fb-row", over ? "is-drop-target" : "", className].filter(Boolean).join(" "), ...dropHandlers, children: [
11565
+ /* @__PURE__ */ jsxs80(
11373
11566
  "button",
11374
11567
  {
11375
11568
  type: "button",
@@ -11378,26 +11571,26 @@ function RowShell({ icon, name, meta, onOpen, draggableId, isDropTarget, onDropP
11378
11571
  draggable: !!draggableId,
11379
11572
  onDragStart: draggableId ? (e) => writeDragPayload(e, draggableId) : void 0,
11380
11573
  children: [
11381
- /* @__PURE__ */ jsx85("span", { className: "fd-fb-row-icon", "aria-hidden": "true", children: /* @__PURE__ */ jsx85("i", { className: "ph ph-" + icon }) }),
11382
- /* @__PURE__ */ jsxs79("span", { className: "fd-fb-row-text", children: [
11383
- /* @__PURE__ */ jsx85("span", { className: "fd-fb-row-name", title: name, children: name }),
11384
- meta ? /* @__PURE__ */ jsx85("span", { className: "fd-fb-row-meta", children: meta }) : null
11574
+ /* @__PURE__ */ jsx86("span", { className: "fd-fb-row-icon", "aria-hidden": "true", children: /* @__PURE__ */ jsx86("i", { className: "ph ph-" + icon }) }),
11575
+ /* @__PURE__ */ jsxs80("span", { className: "fd-fb-row-text", children: [
11576
+ /* @__PURE__ */ jsx86("span", { className: "fd-fb-row-name", title: name, children: name }),
11577
+ meta ? /* @__PURE__ */ jsx86("span", { className: "fd-fb-row-meta", children: meta }) : null
11385
11578
  ] })
11386
11579
  ]
11387
11580
  }
11388
11581
  ),
11389
- actions ? /* @__PURE__ */ jsx85("span", { className: "fd-fb-row-actions", children: actions }) : null
11582
+ actions ? /* @__PURE__ */ jsx86("span", { className: "fd-fb-row-actions", children: actions }) : null
11390
11583
  ] });
11391
11584
  }
11392
11585
  function TreeNode({ folder, depth, folders, currentFolderId, onNavigate, onMoveInto, canMove }) {
11393
11586
  const kids = childrenOf(folders, folder.id);
11394
- const [expanded, setExpanded] = React57.useState(() => currentFolderId != null && isSelfOrDescendant(folders, folder.id, currentFolderId));
11395
- React57.useEffect(() => {
11587
+ const [expanded, setExpanded] = React58.useState(() => currentFolderId != null && isSelfOrDescendant(folders, folder.id, currentFolderId));
11588
+ React58.useEffect(() => {
11396
11589
  if (currentFolderId != null && isSelfOrDescendant(folders, folder.id, currentFolderId)) setExpanded(true);
11397
11590
  }, [currentFolderId, folder.id, folders]);
11398
11591
  const isCurrent = folder.id === currentFolderId;
11399
- return /* @__PURE__ */ jsxs79("div", { className: "fd-fb-tree-node", children: [
11400
- /* @__PURE__ */ jsx85(
11592
+ return /* @__PURE__ */ jsxs80("div", { className: "fd-fb-tree-node", children: [
11593
+ /* @__PURE__ */ jsx86(
11401
11594
  RowShell,
11402
11595
  {
11403
11596
  icon: folder.id === currentFolderId ? "folder-open" : "folder-simple",
@@ -11407,7 +11600,7 @@ function TreeNode({ folder, depth, folders, currentFolderId, onNavigate, onMoveI
11407
11600
  isDropTarget: canMove,
11408
11601
  onDropPayload: (payload) => onMoveInto(payload, folder.id),
11409
11602
  className: ["fd-fb-tree-row", isCurrent ? "is-current" : ""].filter(Boolean).join(" "),
11410
- actions: kids.length ? /* @__PURE__ */ jsx85(
11603
+ actions: kids.length ? /* @__PURE__ */ jsx86(
11411
11604
  IconButton,
11412
11605
  {
11413
11606
  icon: expanded ? "caret-down" : "caret-right",
@@ -11419,7 +11612,7 @@ function TreeNode({ folder, depth, folders, currentFolderId, onNavigate, onMoveI
11419
11612
  ) : void 0
11420
11613
  }
11421
11614
  ),
11422
- expanded && kids.length ? /* @__PURE__ */ jsx85("div", { className: "fd-fb-tree-children", style: { paddingLeft: 14 }, children: kids.map((k) => /* @__PURE__ */ jsx85(
11615
+ expanded && kids.length ? /* @__PURE__ */ jsx86("div", { className: "fd-fb-tree-children", style: { paddingLeft: 14 }, children: kids.map((k) => /* @__PURE__ */ jsx86(
11423
11616
  TreeNode,
11424
11617
  {
11425
11618
  folder: k,
@@ -11458,15 +11651,15 @@ function FileBrowser({
11458
11651
  const canUpload = perm.canUpload !== false && !!onUpload;
11459
11652
  const canRemoveFile = perm.canRemoveFile !== false && !!onRemoveFile;
11460
11653
  const canDeleteFolder = perm.canDeleteFolder !== false && !!onDeleteFolder;
11461
- const [createOpen, setCreateOpen] = React57.useState(false);
11462
- const [createName, setCreateName] = React57.useState("");
11463
- const [renameTarget, setRenameTarget] = React57.useState(null);
11464
- const [renameValue, setRenameValue] = React57.useState("");
11465
- const [deleteTarget, setDeleteTarget] = React57.useState(null);
11466
- const uploadInputRef = React57.useRef(null);
11467
- const crumbFolders = React57.useMemo(() => ancestorsOf(folders, currentFolderId), [folders, currentFolderId]);
11468
- const subfolders = React57.useMemo(() => childrenOf(folders, currentFolderId), [folders, currentFolderId]);
11469
- const currentFiles = React57.useMemo(
11654
+ const [createOpen, setCreateOpen] = React58.useState(false);
11655
+ const [createName, setCreateName] = React58.useState("");
11656
+ const [renameTarget, setRenameTarget] = React58.useState(null);
11657
+ const [renameValue, setRenameValue] = React58.useState("");
11658
+ const [deleteTarget, setDeleteTarget] = React58.useState(null);
11659
+ const uploadInputRef = React58.useRef(null);
11660
+ const crumbFolders = React58.useMemo(() => ancestorsOf(folders, currentFolderId), [folders, currentFolderId]);
11661
+ const subfolders = React58.useMemo(() => childrenOf(folders, currentFolderId), [folders, currentFolderId]);
11662
+ const currentFiles = React58.useMemo(
11470
11663
  () => files.filter((f) => f.folderId === currentFolderId).sort((a, b) => a.name.localeCompare(b.name)),
11471
11664
  [files, currentFolderId]
11472
11665
  );
@@ -11505,10 +11698,10 @@ function FileBrowser({
11505
11698
  if (deleteTarget && onDeleteFolder) onDeleteFolder(deleteTarget);
11506
11699
  setDeleteTarget(null);
11507
11700
  };
11508
- const content = /* @__PURE__ */ jsxs79("div", { className: ["fd-fb", className].filter(Boolean).join(" "), children: [
11509
- /* @__PURE__ */ jsxs79("div", { className: "fd-fb-head", children: [
11510
- /* @__PURE__ */ jsxs79("nav", { className: "fd-fb-crumbs", "aria-label": "Folder path", children: [
11511
- /* @__PURE__ */ jsx85(
11701
+ const content = /* @__PURE__ */ jsxs80("div", { className: ["fd-fb", className].filter(Boolean).join(" "), children: [
11702
+ /* @__PURE__ */ jsxs80("div", { className: "fd-fb-head", children: [
11703
+ /* @__PURE__ */ jsxs80("nav", { className: "fd-fb-crumbs", "aria-label": "Folder path", children: [
11704
+ /* @__PURE__ */ jsx86(
11512
11705
  BreadcrumbCrumb,
11513
11706
  {
11514
11707
  label: "Home",
@@ -11518,7 +11711,7 @@ function FileBrowser({
11518
11711
  onDropPayload: (p) => moveIntoFolder(p, null)
11519
11712
  }
11520
11713
  ),
11521
- crumbFolders.map((f, i) => /* @__PURE__ */ jsx85(
11714
+ crumbFolders.map((f, i) => /* @__PURE__ */ jsx86(
11522
11715
  BreadcrumbCrumb,
11523
11716
  {
11524
11717
  label: f.name,
@@ -11530,11 +11723,11 @@ function FileBrowser({
11530
11723
  f.id
11531
11724
  ))
11532
11725
  ] }),
11533
- /* @__PURE__ */ jsxs79("span", { className: "fd-fb-actions", children: [
11534
- canCreateFolder ? /* @__PURE__ */ jsx85(Button, { variant: "secondary", size: "sm", icon: "folder-simple-plus", onClick: openCreate, children: "New folder" }) : null,
11535
- canUpload ? /* @__PURE__ */ jsxs79(Fragment26, { children: [
11536
- /* @__PURE__ */ jsx85(Button, { variant: "secondary", size: "sm", icon: "upload-simple", onClick: () => uploadInputRef.current && uploadInputRef.current.click(), children: "Upload" }),
11537
- /* @__PURE__ */ jsx85(
11726
+ /* @__PURE__ */ jsxs80("span", { className: "fd-fb-actions", children: [
11727
+ canCreateFolder ? /* @__PURE__ */ jsx86(Button, { variant: "secondary", size: "sm", icon: "folder-simple-plus", onClick: openCreate, children: "New folder" }) : null,
11728
+ canUpload ? /* @__PURE__ */ jsxs80(Fragment27, { children: [
11729
+ /* @__PURE__ */ jsx86(Button, { variant: "secondary", size: "sm", icon: "upload-simple", onClick: () => uploadInputRef.current && uploadInputRef.current.click(), children: "Upload" }),
11730
+ /* @__PURE__ */ jsx86(
11538
11731
  "input",
11539
11732
  {
11540
11733
  ref: uploadInputRef,
@@ -11552,9 +11745,9 @@ function FileBrowser({
11552
11745
  ] }) : null
11553
11746
  ] })
11554
11747
  ] }),
11555
- /* @__PURE__ */ jsxs79("div", { className: "fd-fb-body", children: [
11556
- /* @__PURE__ */ jsxs79("div", { className: "fd-fb-tree", role: "region", "aria-label": "Folder tree", children: [
11557
- /* @__PURE__ */ jsx85(
11748
+ /* @__PURE__ */ jsxs80("div", { className: "fd-fb-body", children: [
11749
+ /* @__PURE__ */ jsxs80("div", { className: "fd-fb-tree", role: "region", "aria-label": "Folder tree", children: [
11750
+ /* @__PURE__ */ jsx86(
11558
11751
  RowShell,
11559
11752
  {
11560
11753
  icon: "house-simple",
@@ -11565,7 +11758,7 @@ function FileBrowser({
11565
11758
  className: ["fd-fb-tree-row", currentFolderId == null ? "is-current" : ""].filter(Boolean).join(" ")
11566
11759
  }
11567
11760
  ),
11568
- childrenOf(folders, null).map((f) => /* @__PURE__ */ jsx85(
11761
+ childrenOf(folders, null).map((f) => /* @__PURE__ */ jsx86(
11569
11762
  TreeNode,
11570
11763
  {
11571
11764
  folder: f,
@@ -11579,18 +11772,18 @@ function FileBrowser({
11579
11772
  f.id
11580
11773
  ))
11581
11774
  ] }),
11582
- /* @__PURE__ */ jsx85("div", { className: "fd-fb-main", role: "region", "aria-label": "Folder contents", children: /* @__PURE__ */ jsx85(
11775
+ /* @__PURE__ */ jsx86("div", { className: "fd-fb-main", role: "region", "aria-label": "Folder contents", children: /* @__PURE__ */ jsx86(
11583
11776
  LoadingRegion,
11584
11777
  {
11585
11778
  state: loading ? "loading" : "ready",
11586
11779
  label: "Loading folder contents",
11587
- skeleton: /* @__PURE__ */ jsxs79("div", { className: "fd-stack", style: { gap: 8, padding: 12 }, children: [
11588
- /* @__PURE__ */ jsx85(Skeleton, { h: 44, radius: "10px" }),
11589
- /* @__PURE__ */ jsx85(Skeleton, { h: 44, radius: "10px" }),
11590
- /* @__PURE__ */ jsx85(Skeleton, { h: 44, radius: "10px" })
11780
+ skeleton: /* @__PURE__ */ jsxs80("div", { className: "fd-stack", style: { gap: 8, padding: 12 }, children: [
11781
+ /* @__PURE__ */ jsx86(Skeleton, { h: 44, radius: "10px" }),
11782
+ /* @__PURE__ */ jsx86(Skeleton, { h: 44, radius: "10px" }),
11783
+ /* @__PURE__ */ jsx86(Skeleton, { h: 44, radius: "10px" })
11591
11784
  ] }),
11592
- children: isEmpty ? /* @__PURE__ */ jsx85(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__ */ jsxs79("div", { className: "fd-fb-list", children: [
11593
- subfolders.map((f) => /* @__PURE__ */ jsx85(
11785
+ children: isEmpty ? /* @__PURE__ */ jsx86(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__ */ jsxs80("div", { className: "fd-fb-list", children: [
11786
+ subfolders.map((f) => /* @__PURE__ */ jsx86(
11594
11787
  RowShell,
11595
11788
  {
11596
11789
  icon: "folder-simple",
@@ -11599,9 +11792,9 @@ function FileBrowser({
11599
11792
  draggableId: canMove ? { kind: "folder", id: f.id } : void 0,
11600
11793
  isDropTarget: canMove,
11601
11794
  onDropPayload: (p) => moveIntoFolder(p, f.id),
11602
- actions: /* @__PURE__ */ jsxs79(Fragment26, { children: [
11603
- canRenameFolder ? /* @__PURE__ */ jsx85(IconButton, { icon: "pencil-simple", label: "Rename " + f.name, size: "sm", variant: "ghost", onClick: () => openRename(f) }) : null,
11604
- canMove ? /* @__PURE__ */ jsx85(
11795
+ actions: /* @__PURE__ */ jsxs80(Fragment27, { children: [
11796
+ canRenameFolder ? /* @__PURE__ */ jsx86(IconButton, { icon: "pencil-simple", label: "Rename " + f.name, size: "sm", variant: "ghost", onClick: () => openRename(f) }) : null,
11797
+ canMove ? /* @__PURE__ */ jsx86(
11605
11798
  FolderPickerMenu,
11606
11799
  {
11607
11800
  label: "Move " + f.name,
@@ -11609,12 +11802,12 @@ function FileBrowser({
11609
11802
  onPick: (target) => moveIntoFolder({ kind: "folder", id: f.id }, target)
11610
11803
  }
11611
11804
  ) : null,
11612
- canDeleteFolder ? /* @__PURE__ */ jsx85(IconButton, { icon: "trash-simple", label: "Delete " + f.name, size: "sm", variant: "ghost", onClick: () => openDelete(f) }) : null
11805
+ canDeleteFolder ? /* @__PURE__ */ jsx86(IconButton, { icon: "trash-simple", label: "Delete " + f.name, size: "sm", variant: "ghost", onClick: () => openDelete(f) }) : null
11613
11806
  ] })
11614
11807
  },
11615
11808
  f.id
11616
11809
  )),
11617
- currentFiles.map((file) => /* @__PURE__ */ jsx85(
11810
+ currentFiles.map((file) => /* @__PURE__ */ jsx86(
11618
11811
  RowShell,
11619
11812
  {
11620
11813
  icon: iconForMime(file.mime, file.name),
@@ -11622,8 +11815,8 @@ function FileBrowser({
11622
11815
  meta: file.size ? formatBytes(file.size) : void 0,
11623
11816
  onOpen: onOpenFile ? () => onOpenFile(file) : void 0,
11624
11817
  draggableId: canMove ? { kind: "file", id: file.id } : void 0,
11625
- actions: /* @__PURE__ */ jsxs79(Fragment26, { children: [
11626
- canMove ? /* @__PURE__ */ jsx85(
11818
+ actions: /* @__PURE__ */ jsxs80(Fragment27, { children: [
11819
+ canMove ? /* @__PURE__ */ jsx86(
11627
11820
  FolderPickerMenu,
11628
11821
  {
11629
11822
  label: "Move " + file.name,
@@ -11631,7 +11824,7 @@ function FileBrowser({
11631
11824
  onPick: (target) => onMoveFile && onMoveFile(file.id, target)
11632
11825
  }
11633
11826
  ) : null,
11634
- canRemoveFile ? /* @__PURE__ */ jsx85(IconButton, { icon: "trash-simple", label: "Remove " + file.name, size: "sm", variant: "ghost", onClick: () => onRemoveFile && onRemoveFile(file) }) : null
11827
+ canRemoveFile ? /* @__PURE__ */ jsx86(IconButton, { icon: "trash-simple", label: "Remove " + file.name, size: "sm", variant: "ghost", onClick: () => onRemoveFile && onRemoveFile(file) }) : null
11635
11828
  ] })
11636
11829
  },
11637
11830
  file.id
@@ -11640,10 +11833,10 @@ function FileBrowser({
11640
11833
  }
11641
11834
  ) })
11642
11835
  ] }),
11643
- /* @__PURE__ */ jsx85(Modal, { open: createOpen, title: "New folder", onClose: () => setCreateOpen(false), footer: /* @__PURE__ */ jsxs79(Fragment26, { children: [
11644
- /* @__PURE__ */ jsx85(Button, { variant: "secondary", onClick: () => setCreateOpen(false), children: "Cancel" }),
11645
- /* @__PURE__ */ jsx85(Button, { onClick: submitCreate, disabled: !createName.trim(), children: "Create" })
11646
- ] }), children: /* @__PURE__ */ jsx85(
11836
+ /* @__PURE__ */ jsx86(Modal, { open: createOpen, title: "New folder", onClose: () => setCreateOpen(false), footer: /* @__PURE__ */ jsxs80(Fragment27, { children: [
11837
+ /* @__PURE__ */ jsx86(Button, { variant: "secondary", onClick: () => setCreateOpen(false), children: "Cancel" }),
11838
+ /* @__PURE__ */ jsx86(Button, { onClick: submitCreate, disabled: !createName.trim(), children: "Create" })
11839
+ ] }), children: /* @__PURE__ */ jsx86(
11647
11840
  "input",
11648
11841
  {
11649
11842
  className: "fd-fb-input",
@@ -11657,10 +11850,10 @@ function FileBrowser({
11657
11850
  autoFocus: true
11658
11851
  }
11659
11852
  ) }),
11660
- /* @__PURE__ */ jsx85(Modal, { open: renameTarget != null, title: "Rename folder", onClose: () => setRenameTarget(null), footer: /* @__PURE__ */ jsxs79(Fragment26, { children: [
11661
- /* @__PURE__ */ jsx85(Button, { variant: "secondary", onClick: () => setRenameTarget(null), children: "Cancel" }),
11662
- /* @__PURE__ */ jsx85(Button, { onClick: submitRename, disabled: !renameValue.trim(), children: "Save" })
11663
- ] }), children: /* @__PURE__ */ jsx85(
11853
+ /* @__PURE__ */ jsx86(Modal, { open: renameTarget != null, title: "Rename folder", onClose: () => setRenameTarget(null), footer: /* @__PURE__ */ jsxs80(Fragment27, { children: [
11854
+ /* @__PURE__ */ jsx86(Button, { variant: "secondary", onClick: () => setRenameTarget(null), children: "Cancel" }),
11855
+ /* @__PURE__ */ jsx86(Button, { onClick: submitRename, disabled: !renameValue.trim(), children: "Save" })
11856
+ ] }), children: /* @__PURE__ */ jsx86(
11664
11857
  "input",
11665
11858
  {
11666
11859
  className: "fd-fb-input",
@@ -11674,22 +11867,22 @@ function FileBrowser({
11674
11867
  autoFocus: true
11675
11868
  }
11676
11869
  ) }),
11677
- /* @__PURE__ */ jsx85(
11870
+ /* @__PURE__ */ jsx86(
11678
11871
  Modal,
11679
11872
  {
11680
11873
  open: deleteTarget != null,
11681
11874
  title: deleteTarget ? "Delete \u201C" + deleteTarget.name + "\u201D?" : "Delete folder?",
11682
11875
  description: "This can't be undone. The folder must be empty.",
11683
11876
  onClose: () => setDeleteTarget(null),
11684
- footer: /* @__PURE__ */ jsxs79(Fragment26, { children: [
11685
- /* @__PURE__ */ jsx85(Button, { variant: "secondary", onClick: () => setDeleteTarget(null), children: "Cancel" }),
11686
- /* @__PURE__ */ jsx85(Button, { variant: "danger", onClick: confirmDelete, children: "Delete" })
11877
+ footer: /* @__PURE__ */ jsxs80(Fragment27, { children: [
11878
+ /* @__PURE__ */ jsx86(Button, { variant: "secondary", onClick: () => setDeleteTarget(null), children: "Cancel" }),
11879
+ /* @__PURE__ */ jsx86(Button, { variant: "danger", onClick: confirmDelete, children: "Delete" })
11687
11880
  ] })
11688
11881
  }
11689
11882
  )
11690
11883
  ] });
11691
11884
  if (!canUpload) return content;
11692
- return /* @__PURE__ */ jsx85(Dropzone, { className: "fd-fb-dropzone", onFiles: (picked) => onUpload && onUpload(picked, currentFolderId), label: "Drop files to upload", children: content });
11885
+ return /* @__PURE__ */ jsx86(Dropzone, { className: "fd-fb-dropzone", onFiles: (picked) => onUpload && onUpload(picked, currentFolderId), label: "Drop files to upload", children: content });
11693
11886
  }
11694
11887
  function BreadcrumbCrumb({
11695
11888
  label,
@@ -11698,8 +11891,8 @@ function BreadcrumbCrumb({
11698
11891
  isDropTarget,
11699
11892
  onDropPayload
11700
11893
  }) {
11701
- const [over, setOver] = React57.useState(false);
11702
- const dragCounter = React57.useRef(0);
11894
+ const [over, setOver] = React58.useState(false);
11895
+ const dragCounter = React58.useRef(0);
11703
11896
  const dropHandlers = isDropTarget ? {
11704
11897
  onDragEnter: (e) => {
11705
11898
  if (!hasInternalPayload(e)) return;
@@ -11724,11 +11917,11 @@ function BreadcrumbCrumb({
11724
11917
  if (payload && onDropPayload) onDropPayload(payload);
11725
11918
  }
11726
11919
  } : {};
11727
- return /* @__PURE__ */ jsx85("span", { className: ["fd-fb-crumb", over ? "is-drop-target" : ""].filter(Boolean).join(" "), ...dropHandlers, children: isCurrent ? /* @__PURE__ */ jsx85("span", { className: "fd-fb-crumb-current", "aria-current": "page", children: label }) : /* @__PURE__ */ jsx85("button", { type: "button", className: "fd-fb-crumb-link", onClick, children: label }) });
11920
+ return /* @__PURE__ */ jsx86("span", { className: ["fd-fb-crumb", over ? "is-drop-target" : ""].filter(Boolean).join(" "), ...dropHandlers, children: isCurrent ? /* @__PURE__ */ jsx86("span", { className: "fd-fb-crumb-current", "aria-current": "page", children: label }) : /* @__PURE__ */ jsx86("button", { type: "button", className: "fd-fb-crumb-link", onClick, children: label }) });
11728
11921
  }
11729
11922
 
11730
11923
  // src/kits/query.ts
11731
- import * as React58 from "react";
11924
+ import * as React59 from "react";
11732
11925
  function eqFilter(get2) {
11733
11926
  return (row, value) => Array.isArray(value) ? value.includes(get2(row)) : get2(row) === value;
11734
11927
  }
@@ -11760,22 +11953,22 @@ function compare(a, b, dir) {
11760
11953
  var API = null;
11761
11954
  var PREFS = null;
11762
11955
  function useServerTable({ endpoint, params, defaults, deps, prefsKey }) {
11763
- const [query, setQuery] = React58.useState(() => {
11956
+ const [query, setQuery] = React59.useState(() => {
11764
11957
  const store = PREFS || window.PlannerPrefs;
11765
11958
  const saved = prefsKey && store ? store.getTable(prefsKey) : {};
11766
11959
  return { ...DEFAULTS, ...defaults || {}, ...saved.pageSize ? { pageSize: saved.pageSize } : {}, ...saved.sort ? { sort: saved.sort, dir: saved.dir || "desc" } : {} };
11767
11960
  });
11768
- const savePref = React58.useCallback((patch2) => {
11961
+ const savePref = React59.useCallback((patch2) => {
11769
11962
  const store = PREFS || window.PlannerPrefs;
11770
11963
  if (prefsKey && store) store.setTable(prefsKey, patch2);
11771
11964
  }, [prefsKey]);
11772
- const [res, setRes] = React58.useState(null);
11773
- const [loading, setLoading] = React58.useState(true);
11774
- const seq2 = React58.useRef(0);
11965
+ const [res, setRes] = React59.useState(null);
11966
+ const [loading, setLoading] = React59.useState(true);
11967
+ const seq2 = React59.useRef(0);
11775
11968
  const depKey = (deps || []).join("|");
11776
11969
  const paramKey = JSON.stringify(params || {});
11777
11970
  const queryKey = JSON.stringify(query);
11778
- React58.useEffect(() => {
11971
+ React59.useEffect(() => {
11779
11972
  const id = ++seq2.current;
11780
11973
  setLoading(true);
11781
11974
  const t = setTimeout(() => {
@@ -12074,12 +12267,12 @@ function createVersionStore(initialState, options) {
12074
12267
  }
12075
12268
 
12076
12269
  // src/kits/documentTitle.ts
12077
- import * as React59 from "react";
12270
+ import * as React60 from "react";
12078
12271
  function formatDocumentTitle(routeTitle, appName) {
12079
12272
  return [routeTitle, appName, "Flytedesk"].filter((part) => !!part && part.length > 0).join(" \xB7 ");
12080
12273
  }
12081
12274
  function useDocumentTitle(routeTitle, appName) {
12082
- React59.useEffect(() => {
12275
+ React60.useEffect(() => {
12083
12276
  if (typeof document === "undefined") return;
12084
12277
  document.title = formatDocumentTitle(routeTitle, appName);
12085
12278
  }, [routeTitle, appName]);
@@ -12201,6 +12394,7 @@ export {
12201
12394
  SessionKit,
12202
12395
  SessionProvider,
12203
12396
  SidebarNav,
12397
+ SignInPage,
12204
12398
  Skeleton,
12205
12399
  SkeletonText,
12206
12400
  Slider,