@burdenoff/microfe-brainyrich 2026.720.1 → 2026.730.1

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.
@@ -1,17 +1,17 @@
1
- import { useAcknowledgeInsight as e, useCreateRebalanceProposal as t, useDismissInsight as n, usePagedInsights as r, usePortfolios as i, useRebalanceProposals as a, useResolveInsight as o, useTransitionRebalanceProposal as s } from "../hooks/useBrainyRichApi.js";
2
- import { LoadMore as c } from "../components/LoadMore.js";
3
- import { ConfirmDialog as ee } from "../components/ConfirmDialog.js";
1
+ import { useAcknowledgeInsight as e, useCreateRebalanceProposal as t, useDismissInsight as n, useGenerateRiskInsights as r, usePagedInsights as i, usePortfolioRiskSignals as a, usePortfolioRiskSummary as o, usePortfolios as s, useRebalanceProposals as c, useResolveInsight as ee, useTransitionRebalanceProposal as te } from "../hooks/useBrainyRichApi.js";
2
+ import { LoadMore as ne } from "../components/LoadMore.js";
3
+ import { ConfirmDialog as re } from "../components/ConfirmDialog.js";
4
4
  import { ActorName as l } from "../components/ActorName.js";
5
- import { DonutChart as te, FadeIn as u, GlassCard as ne, LifecycleStepper as d, StatTile as f } from "../components/viz.js";
5
+ import { DonutChart as ie, FadeIn as u, GlassCard as ae, LifecycleStepper as d, StatTile as f } from "../components/viz.js";
6
6
  import "../components/index.js";
7
- import { EmptyState as p, ErrorState as re, LoadingState as ie, SectionShell as ae, formatDate as m, formatMoney as oe, formatPct as h, statusBadgeVariant as g } from "./_shared.js";
8
- import { CommentThread as se } from "../components/reuse/CommentThread.js";
7
+ import { EmptyState as p, ErrorState as oe, LoadingState as se, SectionShell as ce, formatDate as m, formatMoney as le, formatPct as h, statusBadgeVariant as g } from "./_shared.js";
8
+ import { CommentThread as ue } from "../components/reuse/CommentThread.js";
9
9
  import { useMemo as _, useState as v } from "react";
10
- import { Activity as ce, AlertTriangle as le, ArrowRight as ue, Check as y, Eye as de, Gauge as fe, Layers as pe, MoreHorizontal as me, Plus as he, Scale as b, ShieldAlert as x, ShieldCheck as S, TrendingUp as ge, X as C } from "lucide-react";
11
- import { Fragment as _e, jsx as w, jsxs as T } from "react/jsx-runtime";
12
- import { Badge as E, Button as D, Card as ve, CardContent as ye, CardDescription as be, CardHeader as xe, CardTitle as Se, Dialog as Ce, DialogClose as we, DialogContent as O, DialogDescription as k, DialogFooter as Te, DialogHeader as Ee, DialogTitle as De, DropdownMenu as Oe, DropdownMenuContent as ke, DropdownMenuItem as A, DropdownMenuLabel as Ae, DropdownMenuSeparator as je, DropdownMenuTrigger as Me, Input as Ne, Label as j, Select as Pe, SelectContent as Fe, SelectItem as Ie, SelectTrigger as Le, SelectValue as Re, Table as ze, TableBody as M, TableCell as N, TableHead as P, TableHeader as Be, TableRow as F, Textarea as Ve } from "@burdenoff/fe-libs/ui";
10
+ import { Activity as de, AlertTriangle as fe, ArrowRight as pe, Check as me, Eye as he, Gauge as y, Layers as ge, MoreHorizontal as _e, Plus as ve, RefreshCw as ye, Scale as b, ShieldAlert as x, ShieldCheck as S, Sparkles as be, TrendingUp as xe, X as C } from "lucide-react";
11
+ import { Fragment as Se, jsx as w, jsxs as T } from "react/jsx-runtime";
12
+ import { Badge as E, Button as D, Card as Ce, CardContent as we, CardDescription as Te, CardHeader as O, CardTitle as k, Dialog as Ee, DialogClose as De, DialogContent as Oe, DialogDescription as ke, DialogFooter as Ae, DialogHeader as je, DialogTitle as Me, DropdownMenu as Ne, DropdownMenuContent as Pe, DropdownMenuItem as A, DropdownMenuLabel as Fe, DropdownMenuSeparator as Ie, DropdownMenuTrigger as Le, Input as Re, Label as j, Select as ze, SelectContent as Be, SelectItem as Ve, SelectTrigger as He, SelectValue as Ue, Table as We, TableBody as Ge, TableCell as M, TableHead as N, TableHeader as Ke, TableRow as P, Textarea as qe } from "@burdenoff/fe-libs/ui";
13
13
  //#region src/brainyrich/pages/RiskPage.tsx
14
- var He = {
14
+ var Je = {
15
15
  DRAFT: ["PROPOSED", "CANCELLED"],
16
16
  PROPOSED: [
17
17
  "APPROVED",
@@ -22,49 +22,49 @@ var He = {
22
22
  REJECTED: [],
23
23
  EXECUTED: [],
24
24
  CANCELLED: []
25
- }, Ue = new Set([
25
+ }, Ye = new Set([
26
26
  "DRIFT",
27
27
  "CONCENTRATION_RISK",
28
28
  "REBALANCE_DUE",
29
29
  "CASH_DRAG",
30
30
  "FEE_ANOMALY"
31
31
  ]);
32
- function I(e) {
32
+ function F(e) {
33
33
  return e.toLowerCase().split("_").map((e) => e.charAt(0).toUpperCase() + e.slice(1)).join(" ");
34
34
  }
35
- var L = [
35
+ var I = [
36
36
  "Draft",
37
37
  "Proposed",
38
38
  "Approved",
39
39
  "Executed"
40
- ], We = {
40
+ ], Xe = {
41
41
  DRAFT: "neutral",
42
42
  PROPOSED: "warning",
43
43
  APPROVED: "blue",
44
44
  EXECUTED: "success",
45
45
  REJECTED: "error",
46
46
  CANCELLED: "neutral"
47
- }, Ge = [
47
+ }, Ze = [
48
48
  "PROPOSED",
49
49
  "DRAFT",
50
50
  "APPROVED",
51
51
  "EXECUTED",
52
52
  "REJECTED",
53
53
  "CANCELLED"
54
- ], Ke = {
54
+ ], Qe = {
55
55
  CRITICAL: "error",
56
56
  HIGH: "warning",
57
57
  MEDIUM: "info",
58
58
  LOW: "teal",
59
59
  INFO: "neutral"
60
- }, qe = [
60
+ }, $e = [
61
61
  "CRITICAL",
62
62
  "HIGH",
63
63
  "MEDIUM",
64
64
  "LOW",
65
65
  "INFO"
66
66
  ];
67
- function Je(e) {
67
+ function et(e) {
68
68
  if (!Array.isArray(e) || e.length === 0) return null;
69
69
  let t = [];
70
70
  for (let n of e) {
@@ -101,11 +101,14 @@ function Je(e) {
101
101
  }
102
102
  return t;
103
103
  }
104
- function Ye(e) {
104
+ function tt(e) {
105
+ return e == null ? "—" : typeof e == "number" ? Number.isInteger(e) ? e.toLocaleString() : e.toLocaleString(void 0, { maximumFractionDigits: 2 }) : typeof e == "boolean" ? e ? "Yes" : "No" : typeof e == "string" ? e : JSON.stringify(e);
106
+ }
107
+ function L(e) {
105
108
  let t = (e ?? "").toUpperCase();
106
109
  return t.includes("BUY") || t.includes("ADD") ? "text-status-success-text" : t.includes("SELL") || t.includes("TRIM") || t.includes("REDUCE") ? "text-status-error-text" : "text-text-secondary";
107
110
  }
108
- function Xe(e) {
111
+ function nt(e) {
109
112
  if (e == null) return "—";
110
113
  if (Array.isArray(e)) return `${e.length} trade${e.length === 1 ? "" : "s"}`;
111
114
  if (typeof e == "object") {
@@ -114,86 +117,86 @@ function Xe(e) {
114
117
  }
115
118
  return String(e);
116
119
  }
117
- var Ze = {
120
+ var rt = {
118
121
  portfolioId: "",
119
122
  driftPct: "",
120
123
  rationale: "",
121
124
  trades: ""
122
125
  };
123
- function Qe(e) {
126
+ function it(e) {
124
127
  if (e.trim() === "") return;
125
128
  let t = Number(e);
126
129
  return Number.isFinite(t) ? t : void 0;
127
130
  }
128
- function $e() {
129
- let { data: l, isLoading: d, isError: oe, refetch: se } = a(), { data: y } = i(), { items: L, hasMore: Je, loadMore: Ye, isLoading: $e, isFetchingNextPage: nt, isError: rt, refetch: it } = r(), R = t(), z = s(), at = e(), ot = n(), st = o(), [ct, B] = v(!1), [V, H] = v(Ze), [lt, U] = v(null), [W, G] = v(null), [K, q] = v(null), J = _(() => {
131
+ function R() {
132
+ let { data: l, isLoading: d, isError: ue, refetch: me } = c(), { data: I } = s(), [et, tt] = v(void 0), L = et ?? I[0]?.id ?? "", { data: R, isLoading: ct, isError: lt, refetch: ut } = a(L || void 0), z = r(), { data: B, isFetching: V, refetch: dt } = o(L || void 0), { items: H, hasMore: ft, loadMore: pt, isLoading: mt, isFetchingNextPage: ht, isError: gt, refetch: _t } = i(), U = t(), W = te(), vt = e(), yt = n(), bt = ee(), [xt, G] = v(!1), [K, q] = v(rt), [St, J] = v(null), [Y, Ct] = v(null), [X, Z] = v(null), Q = _(() => {
130
133
  let e = /* @__PURE__ */ new Map();
131
- for (let t of y) e.set(t.id, t);
134
+ for (let t of I) e.set(t.id, t);
132
135
  return e;
133
- }, [y]), Y = _(() => L.filter((e) => Ue.has(e.type)), [L]), ut = l.filter((e) => e.status === "DRAFT" || e.status === "PROPOSED" || e.status === "APPROVED"), X = Y.filter((e) => e.status === "OPEN"), dt = l.length > 0 ? l.reduce((e, t) => e + (t.driftPct ?? 0), 0) / l.length : null, ft = _(() => l.filter((e) => {
134
- let t = J.get(e.portfolioId)?.driftThresholdPct;
136
+ }, [I]), wt = _(() => H.filter((e) => Ye.has(e.type)), [H]), Tt = l.filter((e) => e.status === "DRAFT" || e.status === "PROPOSED" || e.status === "APPROVED"), $ = wt.filter((e) => e.status === "OPEN"), Et = l.length > 0 ? l.reduce((e, t) => e + (t.driftPct ?? 0), 0) / l.length : null, Dt = _(() => l.filter((e) => {
137
+ let t = Q.get(e.portfolioId)?.driftThresholdPct;
135
138
  return t != null && Number.isFinite(t) && e.driftPct >= t;
136
- }).length, [l, J]), pt = _(() => [...l].sort((e, t) => new Date(e.createdAt).getTime() - new Date(t.createdAt).getTime()).map((e) => e.driftPct).filter((e) => Number.isFinite(e)), [l]), mt = _(() => {
139
+ }).length, [l, Q]), Ot = _(() => [...l].sort((e, t) => new Date(e.createdAt).getTime() - new Date(t.createdAt).getTime()).map((e) => e.driftPct).filter((e) => Number.isFinite(e)), [l]), kt = _(() => {
137
140
  let e = /* @__PURE__ */ new Map();
138
141
  for (let t of l) e.set(t.status, (e.get(t.status) ?? 0) + 1);
139
- return Ge.filter((t) => (e.get(t) ?? 0) > 0).map((t) => ({
140
- label: I(t),
142
+ return Ze.filter((t) => (e.get(t) ?? 0) > 0).map((t) => ({
143
+ label: F(t),
141
144
  value: e.get(t) ?? 0,
142
- tone: We[t]
145
+ tone: Xe[t]
143
146
  }));
144
- }, [l]), Z = _(() => {
147
+ }, [l]), At = _(() => {
145
148
  let e = /* @__PURE__ */ new Map();
146
- for (let t of X) e.set(t.severity, (e.get(t.severity) ?? 0) + 1);
147
- return qe.filter((t) => (e.get(t) ?? 0) > 0).map((t) => ({
148
- label: I(t),
149
+ for (let t of $) e.set(t.severity, (e.get(t.severity) ?? 0) + 1);
150
+ return $e.filter((t) => (e.get(t) ?? 0) > 0).map((t) => ({
151
+ label: F(t),
149
152
  value: e.get(t) ?? 0,
150
- tone: Ke[t]
153
+ tone: Qe[t]
151
154
  }));
152
- }, [X]), Q = y.length > 0;
153
- function ht() {
154
- H(Ze), U(null), B(!0);
155
+ }, [$]), jt = I.length > 0;
156
+ function Mt() {
157
+ q(rt), J(null), G(!0);
155
158
  }
156
- function gt() {
157
- if (!V.portfolioId) return;
159
+ function Nt() {
160
+ if (!K.portfolioId) return;
158
161
  let e;
159
- if (V.trades.trim() !== "") try {
160
- e = JSON.parse(V.trades);
162
+ if (K.trades.trim() !== "") try {
163
+ e = JSON.parse(K.trades);
161
164
  } catch {
162
- U("Trades must be valid JSON.");
165
+ J("Trades must be valid JSON.");
163
166
  return;
164
167
  }
165
- let t = J.get(V.portfolioId);
166
- R.mutate({
167
- portfolioId: V.portfolioId,
168
+ let t = Q.get(K.portfolioId);
169
+ U.mutate({
170
+ portfolioId: K.portfolioId,
168
171
  householdId: t?.householdId ?? null,
169
- driftPct: Qe(V.driftPct),
170
- rationale: V.rationale.trim() || null,
172
+ driftPct: it(K.driftPct),
173
+ rationale: K.rationale.trim() || null,
171
174
  ...e === void 0 ? {} : { trades: e }
172
- }, { onSuccess: () => B(!1) });
175
+ }, { onSuccess: () => G(!1) });
173
176
  }
174
- function $(e, t) {
177
+ function Pt(e, t) {
175
178
  if (t === "REJECTED" || t === "CANCELLED") {
176
- q({
179
+ Z({
177
180
  proposal: e,
178
181
  status: t
179
182
  });
180
183
  return;
181
184
  }
182
- z.mutate({
185
+ W.mutate({
183
186
  id: e.id,
184
187
  status: t
185
188
  });
186
189
  }
187
- function _t(e) {
188
- let t = J.get(e.portfolioId)?.driftThresholdPct;
190
+ function Ft(e) {
191
+ let t = Q.get(e.portfolioId)?.driftThresholdPct;
189
192
  return t != null && Number.isFinite(t) && e.driftPct >= t;
190
193
  }
191
- return /* @__PURE__ */ T(ae, {
194
+ return /* @__PURE__ */ T(ce, {
192
195
  title: "Risk & Rebalancing",
193
196
  description: "Review drift-driven rebalance proposals and act on portfolio risk insights.",
194
- badges: [`${ut.length} active`, `${X.length} open insight${X.length === 1 ? "" : "s"}`],
197
+ badges: [`${Tt.length} active`, `${$.length} open insight${$.length === 1 ? "" : "s"}`],
195
198
  actionLabel: "New proposal",
196
- onAction: ht,
199
+ onAction: Mt,
197
200
  children: [
198
201
  /* @__PURE__ */ T("div", {
199
202
  className: "grid gap-4 sm:grid-cols-2 xl:grid-cols-4",
@@ -202,11 +205,11 @@ function $e() {
202
205
  index: 0,
203
206
  children: /* @__PURE__ */ w(f, {
204
207
  label: "Average drift",
205
- value: dt === null ? "—" : h(dt),
206
- spark: pt.length > 1 ? pt : void 0,
207
- sparkTone: ft > 0 ? "error" : "brand",
208
+ value: Et === null ? "—" : h(Et),
209
+ spark: Ot.length > 1 ? Ot : void 0,
210
+ sparkTone: Dt > 0 ? "error" : "brand",
208
211
  glow: !0,
209
- icon: /* @__PURE__ */ w(fe, {
212
+ icon: /* @__PURE__ */ w(y, {
210
213
  className: "size-4",
211
214
  "aria-hidden": "true"
212
215
  })
@@ -216,8 +219,8 @@ function $e() {
216
219
  index: 1,
217
220
  children: /* @__PURE__ */ w(f, {
218
221
  label: "Active proposals",
219
- value: String(ut.length),
220
- icon: /* @__PURE__ */ w(ce, {
222
+ value: String(Tt.length),
223
+ icon: /* @__PURE__ */ w(de, {
221
224
  className: "size-4",
222
225
  "aria-hidden": "true"
223
226
  })
@@ -228,7 +231,7 @@ function $e() {
228
231
  children: /* @__PURE__ */ w(f, {
229
232
  label: "Total proposals",
230
233
  value: String(l.length),
231
- icon: /* @__PURE__ */ w(pe, {
234
+ icon: /* @__PURE__ */ w(ge, {
232
235
  className: "size-4",
233
236
  "aria-hidden": "true"
234
237
  })
@@ -238,8 +241,8 @@ function $e() {
238
241
  index: 3,
239
242
  children: /* @__PURE__ */ w(f, {
240
243
  label: "Open risk insights",
241
- value: String(X.length),
242
- deltaTone: X.length > 0 ? "negative" : "neutral",
244
+ value: String($.length),
245
+ deltaTone: $.length > 0 ? "negative" : "neutral",
243
246
  icon: /* @__PURE__ */ w(x, {
244
247
  className: "size-4",
245
248
  "aria-hidden": "true"
@@ -248,24 +251,24 @@ function $e() {
248
251
  })
249
252
  ]
250
253
  }),
251
- (mt.length > 0 || Z.length > 0) && !d ? /* @__PURE__ */ T("div", {
254
+ (kt.length > 0 || At.length > 0) && !d ? /* @__PURE__ */ T("div", {
252
255
  className: "grid gap-4 lg:grid-cols-2",
253
256
  children: [/* @__PURE__ */ w(u, {
254
257
  index: 0,
255
- children: /* @__PURE__ */ T(ne, {
258
+ children: /* @__PURE__ */ T(ae, {
256
259
  glow: !0,
257
260
  className: "h-full",
258
261
  children: [/* @__PURE__ */ T("div", {
259
262
  className: "mb-3 flex items-center gap-2",
260
- children: [/* @__PURE__ */ w(ge, {
263
+ children: [/* @__PURE__ */ w(xe, {
261
264
  className: "size-4 text-text-secondary",
262
265
  "aria-hidden": "true"
263
266
  }), /* @__PURE__ */ w("h2", {
264
267
  className: "text-sm font-semibold text-text-primary",
265
268
  children: "Proposal pipeline"
266
269
  })]
267
- }), /* @__PURE__ */ w(te, {
268
- data: mt,
270
+ }), /* @__PURE__ */ w(ie, {
271
+ data: kt,
269
272
  centerValue: String(l.length),
270
273
  centerLabel: "proposals",
271
274
  height: 200
@@ -273,7 +276,7 @@ function $e() {
273
276
  })
274
277
  }), /* @__PURE__ */ w(u, {
275
278
  index: 1,
276
- children: /* @__PURE__ */ T(ne, {
279
+ children: /* @__PURE__ */ T(ae, {
277
280
  className: "h-full",
278
281
  children: [/* @__PURE__ */ T("div", {
279
282
  className: "mb-3 flex items-center gap-2",
@@ -284,9 +287,9 @@ function $e() {
284
287
  className: "text-sm font-semibold text-text-primary",
285
288
  children: "Open risk signals"
286
289
  })]
287
- }), Z.length > 0 ? /* @__PURE__ */ w(te, {
288
- data: Z,
289
- centerValue: String(X.length),
290
+ }), At.length > 0 ? /* @__PURE__ */ w(ie, {
291
+ data: At,
292
+ centerValue: String($.length),
290
293
  centerLabel: "open",
291
294
  height: 200
292
295
  }) : /* @__PURE__ */ T("div", {
@@ -302,61 +305,236 @@ function $e() {
302
305
  })
303
306
  })]
304
307
  }) : null,
305
- /* @__PURE__ */ T(ve, { children: [/* @__PURE__ */ T(xe, { children: [/* @__PURE__ */ T(Se, {
308
+ /* @__PURE__ */ T(Ce, { children: [/* @__PURE__ */ T(O, { children: [/* @__PURE__ */ T(k, {
309
+ className: "flex items-center gap-2",
310
+ children: [/* @__PURE__ */ w(y, {
311
+ className: "h-5 w-5",
312
+ "aria-hidden": "true"
313
+ }), "Portfolio risk signals"]
314
+ }), /* @__PURE__ */ w(Te, { children: "Real, explainable signals computed live from this portfolio's own holdings and target allocation — every signal below shows the real inputs and formula/threshold behind it. Informational only, never a buy/sell recommendation." })] }), /* @__PURE__ */ T(we, {
315
+ className: "space-y-4",
316
+ children: [/* @__PURE__ */ T("div", {
317
+ className: "flex flex-wrap items-center gap-3",
318
+ children: [
319
+ /* @__PURE__ */ T("div", {
320
+ className: "min-w-[220px] space-y-1.5",
321
+ children: [/* @__PURE__ */ w(j, {
322
+ htmlFor: "risk-portfolio",
323
+ children: "Portfolio"
324
+ }), /* @__PURE__ */ T(ze, {
325
+ value: L,
326
+ onValueChange: tt,
327
+ children: [/* @__PURE__ */ w(He, {
328
+ id: "risk-portfolio",
329
+ children: /* @__PURE__ */ w(Ue, { placeholder: "Select a portfolio" })
330
+ }), /* @__PURE__ */ w(Be, { children: I.map((e) => /* @__PURE__ */ w(Ve, {
331
+ value: e.id,
332
+ children: e.name
333
+ }, e.id)) })]
334
+ })]
335
+ }),
336
+ /* @__PURE__ */ T(D, {
337
+ variant: "outline",
338
+ size: "sm",
339
+ className: "mt-auto",
340
+ disabled: !L || ct,
341
+ onClick: () => ut(),
342
+ children: [/* @__PURE__ */ w(ye, {
343
+ className: "size-4",
344
+ "aria-hidden": "true"
345
+ }), "Recompute"]
346
+ }),
347
+ /* @__PURE__ */ T(D, {
348
+ variant: "outline",
349
+ size: "sm",
350
+ className: "mt-auto",
351
+ disabled: !L || (R?.signals.length ?? 0) === 0 || z.isPending,
352
+ onClick: () => z.mutate(L),
353
+ children: [/* @__PURE__ */ w(x, {
354
+ className: "size-4",
355
+ "aria-hidden": "true"
356
+ }), z.isPending ? "Saving…" : "Save as insights"]
357
+ })
358
+ ]
359
+ }), I.length === 0 ? /* @__PURE__ */ w(p, {
360
+ icon: /* @__PURE__ */ w(y, {
361
+ className: "size-6",
362
+ "aria-hidden": "true"
363
+ }),
364
+ title: "No portfolios yet",
365
+ description: "Create a portfolio to compute real risk signals from its holdings."
366
+ }) : ct ? /* @__PURE__ */ w(se, {}) : lt ? /* @__PURE__ */ w(oe, { onRetry: () => ut() }) : R ? /* @__PURE__ */ T("div", {
367
+ className: "space-y-4",
368
+ children: [
369
+ /* @__PURE__ */ T("div", {
370
+ className: "grid gap-3 sm:grid-cols-3",
371
+ children: [
372
+ /* @__PURE__ */ w(f, {
373
+ label: "Portfolio value",
374
+ value: le(R.totalValue),
375
+ icon: /* @__PURE__ */ w(ge, {
376
+ className: "size-4",
377
+ "aria-hidden": "true"
378
+ })
379
+ }),
380
+ /* @__PURE__ */ w(f, {
381
+ label: "Holdings considered",
382
+ value: String(R.holdingsConsidered),
383
+ icon: /* @__PURE__ */ w(de, {
384
+ className: "size-4",
385
+ "aria-hidden": "true"
386
+ })
387
+ }),
388
+ /* @__PURE__ */ w(f, {
389
+ label: "Signals breached",
390
+ value: String(R.signals.length),
391
+ deltaTone: R.signals.length > 0 ? "negative" : "neutral",
392
+ icon: /* @__PURE__ */ w(x, {
393
+ className: "size-4",
394
+ "aria-hidden": "true"
395
+ })
396
+ })
397
+ ]
398
+ }),
399
+ R.signals.length === 0 ? /* @__PURE__ */ w(p, {
400
+ icon: /* @__PURE__ */ w(S, {
401
+ className: "size-6",
402
+ "aria-hidden": "true"
403
+ }),
404
+ title: "No configured threshold was breached",
405
+ description: "This portfolio's concentration, cash, drift and unrealized-loss metrics are all within their configured thresholds."
406
+ }) : /* @__PURE__ */ w("ul", {
407
+ className: "space-y-3",
408
+ children: R.signals.map((e, t) => /* @__PURE__ */ w(ot, { signal: e }, `${e.kind}-${t}`))
409
+ }),
410
+ /* @__PURE__ */ T("div", {
411
+ className: "rounded-xl border border-border-subtle bg-bg-surface p-4",
412
+ children: [/* @__PURE__ */ T("div", {
413
+ className: "flex flex-wrap items-center justify-between gap-2",
414
+ children: [/* @__PURE__ */ T("div", {
415
+ className: "flex items-center gap-2",
416
+ children: [
417
+ /* @__PURE__ */ w(be, {
418
+ className: "size-4 text-text-secondary",
419
+ "aria-hidden": "true"
420
+ }),
421
+ /* @__PURE__ */ w("h3", {
422
+ className: "text-sm font-semibold text-text-primary",
423
+ children: "AI summary"
424
+ }),
425
+ /* @__PURE__ */ w("span", {
426
+ className: "text-xs text-text-muted",
427
+ children: "(optional — plain-language restatement of the signals above; never a source of numbers)"
428
+ })
429
+ ]
430
+ }), /* @__PURE__ */ T(D, {
431
+ variant: "outline",
432
+ size: "sm",
433
+ disabled: !L || V,
434
+ onClick: () => dt(),
435
+ children: [/* @__PURE__ */ w(be, {
436
+ className: "size-4",
437
+ "aria-hidden": "true"
438
+ }), V ? "Generating…" : "Generate AI summary"]
439
+ })]
440
+ }), V ? /* @__PURE__ */ w("p", {
441
+ className: "mt-2 text-sm text-text-secondary",
442
+ children: "Asking the AI provider…"
443
+ }) : B?.generated ? /* @__PURE__ */ T("div", {
444
+ className: "mt-2 space-y-1",
445
+ children: [/* @__PURE__ */ w("p", {
446
+ className: "text-sm text-text-primary",
447
+ children: B.summary
448
+ }), /* @__PURE__ */ T("p", {
449
+ className: "text-xs text-text-muted",
450
+ children: [
451
+ "AI-generated commentary",
452
+ B.provider ? ` · ${B.provider}` : "",
453
+ " · based on",
454
+ " ",
455
+ B.signalsConsidered,
456
+ " computed signal",
457
+ B.signalsConsidered === 1 ? "" : "s",
458
+ " above"
459
+ ]
460
+ })]
461
+ }) : B && !B.generated ? /* @__PURE__ */ T("p", {
462
+ className: "mt-2 text-sm text-text-secondary",
463
+ children: [
464
+ "AI summary unavailable — ",
465
+ B.reason ?? "no provider configured",
466
+ ". The deterministic signals above are unaffected."
467
+ ]
468
+ }) : /* @__PURE__ */ w("p", {
469
+ className: "mt-2 text-sm text-text-muted",
470
+ children: "Not generated yet. The deterministic signals above always work without this."
471
+ })]
472
+ })
473
+ ]
474
+ }) : /* @__PURE__ */ w(p, {
475
+ icon: /* @__PURE__ */ w(y, {
476
+ className: "size-6",
477
+ "aria-hidden": "true"
478
+ }),
479
+ title: "Select a portfolio",
480
+ description: "Choose a portfolio above to compute its real risk signals."
481
+ })]
482
+ })] }),
483
+ /* @__PURE__ */ T(Ce, { children: [/* @__PURE__ */ T(O, { children: [/* @__PURE__ */ T(k, {
306
484
  className: "flex items-center gap-2",
307
485
  children: [/* @__PURE__ */ w(b, {
308
486
  className: "h-5 w-5",
309
487
  "aria-hidden": "true"
310
488
  }), "Rebalance proposals"]
311
- }), /* @__PURE__ */ w(be, { children: "Drift against target allocation, with lifecycle actions per proposal." })] }), /* @__PURE__ */ w(ye, { children: d ? /* @__PURE__ */ w(ie, {}) : oe ? /* @__PURE__ */ w(re, { onRetry: () => se() }) : l.length === 0 ? /* @__PURE__ */ w(p, {
489
+ }), /* @__PURE__ */ w(Te, { children: "Drift against target allocation, with lifecycle actions per proposal." })] }), /* @__PURE__ */ w(we, { children: d ? /* @__PURE__ */ w(se, {}) : ue ? /* @__PURE__ */ w(oe, { onRetry: () => me() }) : l.length === 0 ? /* @__PURE__ */ w(p, {
312
490
  icon: /* @__PURE__ */ w(b, {
313
491
  className: "size-6",
314
492
  "aria-hidden": "true"
315
493
  }),
316
494
  title: "No rebalance proposals",
317
- description: Q ? "Create a proposal when a portfolio drifts from its target allocation." : "Create a portfolio first, then propose a rebalance when it drifts.",
318
- action: Q ? /* @__PURE__ */ T(D, {
495
+ description: jt ? "Create a proposal when a portfolio drifts from its target allocation." : "Create a portfolio first, then propose a rebalance when it drifts.",
496
+ action: jt ? /* @__PURE__ */ T(D, {
319
497
  size: "sm",
320
- onClick: ht,
321
- children: [/* @__PURE__ */ w(he, {
498
+ onClick: Mt,
499
+ children: [/* @__PURE__ */ w(ve, {
322
500
  className: "size-4",
323
501
  "aria-hidden": "true"
324
502
  }), "New proposal"]
325
503
  }) : void 0
326
504
  }) : /* @__PURE__ */ w("div", {
327
505
  className: "overflow-x-auto",
328
- children: /* @__PURE__ */ T(ze, { children: [/* @__PURE__ */ w(Be, { children: /* @__PURE__ */ T(F, { children: [
329
- /* @__PURE__ */ w(P, { children: "Portfolio" }),
330
- /* @__PURE__ */ w(P, {
506
+ children: /* @__PURE__ */ T(We, { children: [/* @__PURE__ */ w(Ke, { children: /* @__PURE__ */ T(P, { children: [
507
+ /* @__PURE__ */ w(N, { children: "Portfolio" }),
508
+ /* @__PURE__ */ w(N, {
331
509
  className: "text-right",
332
510
  children: "Drift"
333
511
  }),
334
- /* @__PURE__ */ w(P, { children: "Status" }),
335
- /* @__PURE__ */ w(P, { children: "Rationale" }),
336
- /* @__PURE__ */ w(P, { children: "Trades" }),
337
- /* @__PURE__ */ w(P, { children: "Created" }),
338
- /* @__PURE__ */ w(P, {
512
+ /* @__PURE__ */ w(N, { children: "Status" }),
513
+ /* @__PURE__ */ w(N, { children: "Rationale" }),
514
+ /* @__PURE__ */ w(N, { children: "Trades" }),
515
+ /* @__PURE__ */ w(N, { children: "Created" }),
516
+ /* @__PURE__ */ w(N, {
339
517
  className: "w-12 text-right",
340
518
  children: "Actions"
341
519
  })
342
- ] }) }), /* @__PURE__ */ w(M, { children: l.map((e) => {
343
- let t = J.get(e.portfolioId), n = _t(e), r = He[e.status], i = t?.driftThresholdPct, a = i != null && i > 0 ? Math.min(100, e.driftPct / i * 100) : null;
344
- return /* @__PURE__ */ T(F, {
345
- onClick: () => G(e),
520
+ ] }) }), /* @__PURE__ */ w(Ge, { children: l.map((e) => {
521
+ let t = Q.get(e.portfolioId), n = Ft(e), r = Je[e.status], i = t?.driftThresholdPct, a = i != null && i > 0 ? Math.min(100, e.driftPct / i * 100) : null;
522
+ return /* @__PURE__ */ T(P, {
523
+ onClick: () => Ct(e),
346
524
  className: "cursor-pointer transition-colors motion-safe:hover:bg-bg-elevated",
347
525
  children: [
348
- /* @__PURE__ */ T(N, { children: [/* @__PURE__ */ w("p", {
526
+ /* @__PURE__ */ T(M, { children: [/* @__PURE__ */ w("p", {
349
527
  className: "font-medium text-text-primary",
350
528
  children: t?.name ?? "Unknown portfolio"
351
529
  }), /* @__PURE__ */ T("p", {
352
530
  className: "text-xs text-text-secondary",
353
531
  children: [t?.baseCurrency ?? "—", i == null ? "" : ` · threshold ${h(i)}`]
354
532
  })] }),
355
- /* @__PURE__ */ T(N, {
533
+ /* @__PURE__ */ T(M, {
356
534
  className: "text-right",
357
535
  children: [/* @__PURE__ */ T("span", {
358
536
  className: `inline-flex items-center justify-end gap-1 font-semibold tabular-nums ${n ? "text-status-error-text" : "text-text-primary"}`,
359
- children: [n ? /* @__PURE__ */ w(le, {
537
+ children: [n ? /* @__PURE__ */ w(fe, {
360
538
  className: "size-4",
361
539
  "aria-hidden": "true"
362
540
  }) : null, h(e.driftPct)]
@@ -379,60 +557,60 @@ function $e() {
379
557
  })
380
558
  })]
381
559
  }),
382
- /* @__PURE__ */ w(N, { children: /* @__PURE__ */ w(E, {
560
+ /* @__PURE__ */ w(M, { children: /* @__PURE__ */ w(E, {
383
561
  variant: g(e.status),
384
- children: I(e.status)
562
+ children: F(e.status)
385
563
  }) }),
386
- /* @__PURE__ */ w(N, {
564
+ /* @__PURE__ */ w(M, {
387
565
  className: "max-w-xs",
388
566
  children: /* @__PURE__ */ w("p", {
389
567
  className: "truncate text-sm text-text-secondary",
390
568
  children: e.rationale ?? "—"
391
569
  })
392
570
  }),
393
- /* @__PURE__ */ w(N, {
571
+ /* @__PURE__ */ w(M, {
394
572
  className: "text-sm text-text-secondary",
395
- children: Xe(e.trades)
573
+ children: nt(e.trades)
396
574
  }),
397
- /* @__PURE__ */ w(N, {
575
+ /* @__PURE__ */ w(M, {
398
576
  className: "text-sm text-text-secondary",
399
577
  children: m(e.createdAt)
400
578
  }),
401
- /* @__PURE__ */ w(N, {
579
+ /* @__PURE__ */ w(M, {
402
580
  className: "text-right",
403
581
  onClick: (e) => e.stopPropagation(),
404
- children: /* @__PURE__ */ T(Oe, { children: [/* @__PURE__ */ w(Me, {
582
+ children: /* @__PURE__ */ T(Ne, { children: [/* @__PURE__ */ w(Le, {
405
583
  asChild: !0,
406
584
  children: /* @__PURE__ */ w(D, {
407
585
  variant: "ghost",
408
586
  size: "sm",
409
587
  "aria-label": `Actions for ${t?.name ?? "proposal"}`,
410
- children: /* @__PURE__ */ w(me, {
588
+ children: /* @__PURE__ */ w(_e, {
411
589
  className: "size-4",
412
590
  "aria-hidden": "true"
413
591
  })
414
592
  })
415
- }), /* @__PURE__ */ T(ke, {
593
+ }), /* @__PURE__ */ T(Pe, {
416
594
  align: "end",
417
595
  children: [/* @__PURE__ */ T(A, {
418
- onClick: () => G(e),
419
- children: [/* @__PURE__ */ w(de, {
596
+ onClick: () => Ct(e),
597
+ children: [/* @__PURE__ */ w(he, {
420
598
  className: "size-4",
421
599
  "aria-hidden": "true"
422
600
  }), "View details"]
423
- }), r.length > 0 ? /* @__PURE__ */ T(_e, { children: [
424
- /* @__PURE__ */ w(je, {}),
425
- /* @__PURE__ */ w(Ae, { children: "Advance to" }),
601
+ }), r.length > 0 ? /* @__PURE__ */ T(Se, { children: [
602
+ /* @__PURE__ */ w(Ie, {}),
603
+ /* @__PURE__ */ w(Fe, { children: "Advance to" }),
426
604
  r.map((t) => {
427
605
  let n = t === "REJECTED" || t === "CANCELLED";
428
606
  return /* @__PURE__ */ T(A, {
429
- disabled: z.isPending,
607
+ disabled: W.isPending,
430
608
  className: n ? "text-status-error-text" : void 0,
431
- onClick: () => $(e, t),
432
- children: [w(n ? C : ue, {
609
+ onClick: () => Pt(e, t),
610
+ children: [w(n ? C : pe, {
433
611
  className: "size-4",
434
612
  "aria-hidden": "true"
435
- }), I(t)]
613
+ }), F(t)]
436
614
  }, t);
437
615
  })
438
616
  ] }) : null]
@@ -442,13 +620,13 @@ function $e() {
442
620
  }, e.id);
443
621
  }) })] })
444
622
  }) })] }),
445
- /* @__PURE__ */ T(ve, { children: [/* @__PURE__ */ T(xe, { children: [/* @__PURE__ */ T(Se, {
623
+ /* @__PURE__ */ T(Ce, { children: [/* @__PURE__ */ T(O, { children: [/* @__PURE__ */ T(k, {
446
624
  className: "flex items-center gap-2",
447
625
  children: [/* @__PURE__ */ w(x, {
448
626
  className: "h-5 w-5",
449
627
  "aria-hidden": "true"
450
628
  }), "Risk insights"]
451
- }), /* @__PURE__ */ w(be, { children: "Drift, concentration, cash-drag and fee-anomaly signals detected across your portfolios." })] }), /* @__PURE__ */ w(ye, { children: $e ? /* @__PURE__ */ w(ie, {}) : rt ? /* @__PURE__ */ w(re, { onRetry: () => it() }) : Y.length === 0 ? /* @__PURE__ */ w(p, {
629
+ }), /* @__PURE__ */ w(Te, { children: "Drift, concentration, cash-drag and fee-anomaly signals detected across your portfolios." })] }), /* @__PURE__ */ w(we, { children: mt ? /* @__PURE__ */ w(se, {}) : gt ? /* @__PURE__ */ w(oe, { onRetry: () => _t() }) : wt.length === 0 ? /* @__PURE__ */ w(p, {
452
630
  icon: /* @__PURE__ */ w(S, {
453
631
  className: "size-6",
454
632
  "aria-hidden": "true"
@@ -457,28 +635,28 @@ function $e() {
457
635
  description: "No drift, concentration, cash-drag or fee-anomaly signals are open right now."
458
636
  }) : /* @__PURE__ */ T("div", {
459
637
  className: "space-y-3",
460
- children: [Y.map((e, t) => /* @__PURE__ */ w(u, {
638
+ children: [wt.map((e, t) => /* @__PURE__ */ w(u, {
461
639
  index: t,
462
- children: /* @__PURE__ */ w(tt, {
640
+ children: /* @__PURE__ */ w(st, {
463
641
  insight: e,
464
- onAcknowledge: () => at.mutate(e.id),
465
- onResolve: () => st.mutate(e.id),
466
- onDismiss: () => ot.mutate(e.id),
467
- actionPending: at.isPending || st.isPending || ot.isPending
642
+ onAcknowledge: () => vt.mutate(e.id),
643
+ onResolve: () => bt.mutate(e.id),
644
+ onDismiss: () => yt.mutate(e.id),
645
+ actionPending: vt.isPending || bt.isPending || yt.isPending
468
646
  })
469
- }, e.id)), /* @__PURE__ */ w(c, {
470
- hasMore: Je,
471
- onClick: Ye,
472
- loading: nt,
647
+ }, e.id)), /* @__PURE__ */ w(ne, {
648
+ hasMore: ft,
649
+ onClick: pt,
650
+ loading: ht,
473
651
  label: "Load more insights"
474
652
  })]
475
653
  }) })] }),
476
- /* @__PURE__ */ w(Ce, {
477
- open: ct,
478
- onOpenChange: B,
479
- children: /* @__PURE__ */ T(O, { children: [
480
- /* @__PURE__ */ T(Ee, { children: [/* @__PURE__ */ w(De, { children: "New rebalance proposal" }), /* @__PURE__ */ w(k, { children: "Propose a rebalance for a portfolio that has drifted from its target allocation." })] }),
481
- Q ? /* @__PURE__ */ T("div", {
654
+ /* @__PURE__ */ w(Ee, {
655
+ open: xt,
656
+ onOpenChange: G,
657
+ children: /* @__PURE__ */ T(Oe, { children: [
658
+ /* @__PURE__ */ T(je, { children: [/* @__PURE__ */ w(Me, { children: "New rebalance proposal" }), /* @__PURE__ */ w(ke, { children: "Propose a rebalance for a portfolio that has drifted from its target allocation." })] }),
659
+ jt ? /* @__PURE__ */ T("div", {
482
660
  className: "grid gap-4",
483
661
  children: [
484
662
  /* @__PURE__ */ T("div", {
@@ -491,16 +669,16 @@ function $e() {
491
669
  className: "text-status-error-text",
492
670
  children: "*"
493
671
  })]
494
- }), /* @__PURE__ */ T(Pe, {
495
- value: V.portfolioId,
496
- onValueChange: (e) => H((t) => ({
672
+ }), /* @__PURE__ */ T(ze, {
673
+ value: K.portfolioId,
674
+ onValueChange: (e) => q((t) => ({
497
675
  ...t,
498
676
  portfolioId: e
499
677
  })),
500
- children: [/* @__PURE__ */ w(Le, {
678
+ children: [/* @__PURE__ */ w(He, {
501
679
  id: "prop-portfolio",
502
- children: /* @__PURE__ */ w(Re, { placeholder: "Select a portfolio" })
503
- }), /* @__PURE__ */ w(Fe, { children: y.map((e) => /* @__PURE__ */ w(Ie, {
680
+ children: /* @__PURE__ */ w(Ue, { placeholder: "Select a portfolio" })
681
+ }), /* @__PURE__ */ w(Be, { children: I.map((e) => /* @__PURE__ */ w(Ve, {
504
682
  value: e.id,
505
683
  children: e.name
506
684
  }, e.id)) })]
@@ -510,11 +688,11 @@ function $e() {
510
688
  children: [/* @__PURE__ */ w(j, {
511
689
  htmlFor: "prop-drift",
512
690
  children: "Drift %"
513
- }), /* @__PURE__ */ w(Ne, {
691
+ }), /* @__PURE__ */ w(Re, {
514
692
  id: "prop-drift",
515
693
  type: "number",
516
- value: V.driftPct,
517
- onChange: (e) => H((t) => ({
694
+ value: K.driftPct,
695
+ onChange: (e) => q((t) => ({
518
696
  ...t,
519
697
  driftPct: e.target.value
520
698
  })),
@@ -527,10 +705,10 @@ function $e() {
527
705
  children: [/* @__PURE__ */ w(j, {
528
706
  htmlFor: "prop-rationale",
529
707
  children: "Rationale"
530
- }), /* @__PURE__ */ w(Ve, {
708
+ }), /* @__PURE__ */ w(qe, {
531
709
  id: "prop-rationale",
532
- value: V.rationale,
533
- onChange: (e) => H((t) => ({
710
+ value: K.rationale,
711
+ onChange: (e) => q((t) => ({
534
712
  ...t,
535
713
  rationale: e.target.value
536
714
  })),
@@ -544,21 +722,21 @@ function $e() {
544
722
  htmlFor: "prop-trades",
545
723
  children: "Trades (JSON, optional)"
546
724
  }),
547
- /* @__PURE__ */ w(Ve, {
725
+ /* @__PURE__ */ w(qe, {
548
726
  id: "prop-trades",
549
727
  className: "font-mono text-xs",
550
- value: V.trades,
728
+ value: K.trades,
551
729
  onChange: (e) => {
552
- U(null), H((t) => ({
730
+ J(null), q((t) => ({
553
731
  ...t,
554
732
  trades: e.target.value
555
733
  }));
556
734
  },
557
735
  placeholder: "e.g. [{\"symbol\":\"VOO\",\"action\":\"SELL\",\"quantity\":10}]"
558
736
  }),
559
- lt ? /* @__PURE__ */ w("p", {
737
+ St ? /* @__PURE__ */ w("p", {
560
738
  className: "text-xs text-status-error-text",
561
- children: lt
739
+ children: St
562
740
  }) : null
563
741
  ]
564
742
  })
@@ -571,70 +749,70 @@ function $e() {
571
749
  title: "Create a portfolio first",
572
750
  description: "A rebalance proposal targets a portfolio. Add a portfolio on the Portfolios page, then return here to propose a rebalance."
573
751
  }),
574
- /* @__PURE__ */ T(Te, { children: [/* @__PURE__ */ w(we, {
752
+ /* @__PURE__ */ T(Ae, { children: [/* @__PURE__ */ w(De, {
575
753
  asChild: !0,
576
754
  children: /* @__PURE__ */ w(D, {
577
755
  variant: "outline",
578
756
  children: "Cancel"
579
757
  })
580
758
  }), /* @__PURE__ */ w(D, {
581
- onClick: gt,
582
- disabled: !V.portfolioId || R.isPending,
583
- children: R.isPending ? "Creating…" : "Create proposal"
759
+ onClick: Nt,
760
+ disabled: !K.portfolioId || U.isPending,
761
+ children: U.isPending ? "Creating…" : "Create proposal"
584
762
  })] })
585
763
  ] })
586
764
  }),
587
765
  (() => {
588
- let e = W ? l.find((e) => e.id === W.id) ?? W : null, t = e ? L.filter((t) => t.subjectId === e.portfolioId) : [];
589
- return /* @__PURE__ */ w(et, {
766
+ let e = Y ? l.find((e) => e.id === Y.id) ?? Y : null, t = e ? H.filter((t) => t.subjectId === e.portfolioId) : [];
767
+ return /* @__PURE__ */ w(at, {
590
768
  proposal: e,
591
- portfolio: e ? J.get(e.portfolioId) ?? null : null,
769
+ portfolio: e ? Q.get(e.portfolioId) ?? null : null,
592
770
  relatedInsights: t,
593
- nextStatuses: e ? He[e.status] : [],
594
- transitionPending: z.isPending,
771
+ nextStatuses: e ? Je[e.status] : [],
772
+ transitionPending: W.isPending,
595
773
  onTransition: (t) => {
596
- e && $(e, t);
774
+ e && Pt(e, t);
597
775
  },
598
776
  onOpenChange: (e) => {
599
- e || G(null);
777
+ e || Ct(null);
600
778
  }
601
779
  });
602
780
  })(),
603
- /* @__PURE__ */ w(ee, {
604
- open: K !== null,
781
+ /* @__PURE__ */ w(re, {
782
+ open: X !== null,
605
783
  onOpenChange: (e) => {
606
- e || q(null);
784
+ e || Z(null);
607
785
  },
608
- title: K?.status === "REJECTED" ? "Reject this proposal?" : "Cancel this proposal?",
609
- description: K ? `This moves the rebalance proposal for ${J.get(K.proposal.portfolioId)?.name ?? "this portfolio"} to ${I(K.status)}. This cannot be undone.` : void 0,
610
- confirmLabel: K?.status === "REJECTED" ? "Reject" : "Cancel proposal",
786
+ title: X?.status === "REJECTED" ? "Reject this proposal?" : "Cancel this proposal?",
787
+ description: X ? `This moves the rebalance proposal for ${Q.get(X.proposal.portfolioId)?.name ?? "this portfolio"} to ${F(X.status)}. This cannot be undone.` : void 0,
788
+ confirmLabel: X?.status === "REJECTED" ? "Reject" : "Cancel proposal",
611
789
  cancelLabel: "Keep",
612
790
  destructive: !0,
613
- pending: z.isPending,
791
+ pending: W.isPending,
614
792
  onConfirm: () => {
615
- K && z.mutate({
616
- id: K.proposal.id,
617
- status: K.status
618
- }, { onSuccess: () => q(null) });
793
+ X && W.mutate({
794
+ id: X.proposal.id,
795
+ status: X.status
796
+ }, { onSuccess: () => Z(null) });
619
797
  }
620
798
  })
621
799
  ]
622
800
  });
623
801
  }
624
- function et({ proposal: e, portfolio: t, relatedInsights: n, nextStatuses: r, transitionPending: i, onTransition: a, onOpenChange: o }) {
625
- let s = e ? Je(e.trades) : null, c = e != null && t?.driftThresholdPct != null && Number.isFinite(t.driftThresholdPct) && e.driftPct >= t.driftThresholdPct;
626
- return /* @__PURE__ */ w(Ce, {
802
+ function at({ proposal: e, portfolio: t, relatedInsights: n, nextStatuses: r, transitionPending: i, onTransition: a, onOpenChange: o }) {
803
+ let s = e ? et(e.trades) : null, c = e != null && t?.driftThresholdPct != null && Number.isFinite(t.driftThresholdPct) && e.driftPct >= t.driftThresholdPct;
804
+ return /* @__PURE__ */ w(Ee, {
627
805
  open: e !== null,
628
806
  onOpenChange: o,
629
- children: /* @__PURE__ */ w(O, {
807
+ children: /* @__PURE__ */ w(Oe, {
630
808
  className: "max-h-[88vh] max-w-3xl overflow-y-auto",
631
- children: e ? /* @__PURE__ */ T(_e, { children: [
632
- /* @__PURE__ */ T(Ee, { children: [
809
+ children: e ? /* @__PURE__ */ T(Se, { children: [
810
+ /* @__PURE__ */ T(je, { children: [
633
811
  /* @__PURE__ */ w("p", {
634
812
  className: "text-xs font-medium uppercase tracking-wide text-text-secondary",
635
813
  children: "Detail"
636
814
  }),
637
- /* @__PURE__ */ T(De, {
815
+ /* @__PURE__ */ T(Me, {
638
816
  className: "flex flex-wrap items-center gap-2 text-xl",
639
817
  children: [
640
818
  t?.name ?? "Rebalance proposal",
@@ -644,11 +822,11 @@ function et({ proposal: e, portfolio: t, relatedInsights: n, nextStatuses: r, tr
644
822
  }),
645
823
  /* @__PURE__ */ w(E, {
646
824
  variant: g(e.status),
647
- children: I(e.status)
825
+ children: F(e.status)
648
826
  })
649
827
  ]
650
828
  }),
651
- /* @__PURE__ */ T(k, { children: [
829
+ /* @__PURE__ */ T(ke, { children: [
652
830
  "Created ",
653
831
  m(e.createdAt),
654
832
  e.executedAt ? ` · executed ${m(e.executedAt)}` : ""
@@ -657,8 +835,8 @@ function et({ proposal: e, portfolio: t, relatedInsights: n, nextStatuses: r, tr
657
835
  /* @__PURE__ */ w("div", {
658
836
  className: "rounded-xl border border-border-subtle bg-bg-surface p-4",
659
837
  children: /* @__PURE__ */ w(d, {
660
- steps: L,
661
- current: I(e.status)
838
+ steps: I,
839
+ current: F(e.status)
662
840
  })
663
841
  }),
664
842
  /* @__PURE__ */ T("div", {
@@ -669,7 +847,7 @@ function et({ proposal: e, portfolio: t, relatedInsights: n, nextStatuses: r, tr
669
847
  value: h(e.driftPct),
670
848
  deltaTone: c ? "negative" : "neutral",
671
849
  glow: c,
672
- icon: /* @__PURE__ */ w(fe, {
850
+ icon: /* @__PURE__ */ w(y, {
673
851
  className: "size-4",
674
852
  "aria-hidden": "true"
675
853
  })
@@ -707,38 +885,38 @@ function et({ proposal: e, portfolio: t, relatedInsights: n, nextStatuses: r, tr
707
885
  children: "Proposed trades"
708
886
  }), s && s.length > 0 ? /* @__PURE__ */ w("div", {
709
887
  className: "overflow-x-auto rounded-lg border border-border-subtle",
710
- children: /* @__PURE__ */ T(ze, { children: [/* @__PURE__ */ w(Be, { children: /* @__PURE__ */ T(F, { children: [
711
- /* @__PURE__ */ w(P, { children: "Action" }),
712
- /* @__PURE__ */ w(P, { children: "Symbol" }),
713
- /* @__PURE__ */ w(P, {
888
+ children: /* @__PURE__ */ T(We, { children: [/* @__PURE__ */ w(Ke, { children: /* @__PURE__ */ T(P, { children: [
889
+ /* @__PURE__ */ w(N, { children: "Action" }),
890
+ /* @__PURE__ */ w(N, { children: "Symbol" }),
891
+ /* @__PURE__ */ w(N, {
714
892
  className: "text-right",
715
893
  children: "Quantity"
716
894
  }),
717
- /* @__PURE__ */ w(P, {
895
+ /* @__PURE__ */ w(N, {
718
896
  className: "text-right",
719
897
  children: "Est. value"
720
898
  })
721
- ] }) }), /* @__PURE__ */ w(M, { children: s.map((e, n) => /* @__PURE__ */ T(F, { children: [
722
- /* @__PURE__ */ w(N, {
723
- className: `font-semibold ${Ye(e.action)}`,
899
+ ] }) }), /* @__PURE__ */ w(Ge, { children: s.map((e, n) => /* @__PURE__ */ T(P, { children: [
900
+ /* @__PURE__ */ w(M, {
901
+ className: `font-semibold ${L(e.action)}`,
724
902
  children: e.action ? e.action.toUpperCase() : "—"
725
903
  }),
726
- /* @__PURE__ */ w(N, {
904
+ /* @__PURE__ */ w(M, {
727
905
  className: "font-medium text-text-primary",
728
906
  children: e.symbol ?? "—"
729
907
  }),
730
- /* @__PURE__ */ w(N, {
908
+ /* @__PURE__ */ w(M, {
731
909
  className: "text-right tabular-nums text-text-secondary",
732
910
  children: e.quantity == null ? "—" : e.quantity.toLocaleString()
733
911
  }),
734
- /* @__PURE__ */ w(N, {
912
+ /* @__PURE__ */ w(M, {
735
913
  className: "text-right tabular-nums text-text-secondary",
736
- children: e.value == null ? "—" : oe(e.value, t?.baseCurrency ?? "USD")
914
+ children: e.value == null ? "—" : le(e.value, t?.baseCurrency ?? "USD")
737
915
  })
738
916
  ] }, n)) })] })
739
917
  }) : /* @__PURE__ */ T("p", {
740
918
  className: "text-sm text-text-secondary",
741
- children: [Xe(e.trades), " — no structured trade breakdown available."]
919
+ children: [nt(e.trades), " — no structured trade breakdown available."]
742
920
  })]
743
921
  }),
744
922
  /* @__PURE__ */ T("div", {
@@ -761,10 +939,10 @@ function et({ proposal: e, portfolio: t, relatedInsights: n, nextStatuses: r, tr
761
939
  disabled: i,
762
940
  className: t ? "text-status-error-text" : void 0,
763
941
  onClick: () => a(e),
764
- children: [w(t ? C : ue, {
942
+ children: [w(t ? C : pe, {
765
943
  className: "size-4",
766
944
  "aria-hidden": "true"
767
- }), I(e)]
945
+ }), F(e)]
768
946
  }, e);
769
947
  })
770
948
  }) : null,
@@ -789,15 +967,15 @@ function et({ proposal: e, portfolio: t, relatedInsights: n, nextStatuses: r, tr
789
967
  }),
790
968
  /* @__PURE__ */ w(E, {
791
969
  variant: g(e.severity),
792
- children: I(e.severity)
970
+ children: F(e.severity)
793
971
  }),
794
972
  /* @__PURE__ */ w(E, {
795
973
  variant: "outline",
796
- children: I(e.type)
974
+ children: F(e.type)
797
975
  }),
798
976
  /* @__PURE__ */ w(E, {
799
977
  variant: g(e.status),
800
- children: I(e.status)
978
+ children: F(e.status)
801
979
  })
802
980
  ]
803
981
  }), e.detail ? /* @__PURE__ */ w("p", {
@@ -809,7 +987,7 @@ function et({ proposal: e, portfolio: t, relatedInsights: n, nextStatuses: r, tr
809
987
  }) : null,
810
988
  /* @__PURE__ */ w("div", {
811
989
  className: "border-t border-border-subtle pt-4",
812
- children: /* @__PURE__ */ w(se, {
990
+ children: /* @__PURE__ */ w(ue, {
813
991
  entityType: "brainyrich-rebalance",
814
992
  entityId: e.id,
815
993
  heading: "Discussion"
@@ -819,7 +997,49 @@ function et({ proposal: e, portfolio: t, relatedInsights: n, nextStatuses: r, tr
819
997
  })
820
998
  });
821
999
  }
822
- function tt({ insight: e, onAcknowledge: t, onResolve: n, onDismiss: r, actionPending: i }) {
1000
+ function ot({ signal: e }) {
1001
+ let t = Object.entries(e.metrics ?? {});
1002
+ return /* @__PURE__ */ T("li", {
1003
+ className: "rounded-lg border border-border-subtle bg-bg-surface p-4",
1004
+ children: [
1005
+ /* @__PURE__ */ T("div", {
1006
+ className: "flex flex-wrap items-center gap-2",
1007
+ children: [
1008
+ /* @__PURE__ */ w("p", {
1009
+ className: "font-medium text-text-primary",
1010
+ children: e.title
1011
+ }),
1012
+ /* @__PURE__ */ w(E, {
1013
+ variant: g(e.severity),
1014
+ children: F(e.severity)
1015
+ }),
1016
+ /* @__PURE__ */ w(E, {
1017
+ variant: "outline",
1018
+ children: F(e.kind)
1019
+ })
1020
+ ]
1021
+ }),
1022
+ e.detail ? /* @__PURE__ */ w("p", {
1023
+ className: "mt-1 text-sm text-text-secondary",
1024
+ children: e.detail
1025
+ }) : null,
1026
+ t.length > 0 ? /* @__PURE__ */ w("dl", {
1027
+ className: "mt-3 grid grid-cols-2 gap-x-4 gap-y-1 sm:grid-cols-3 lg:grid-cols-4",
1028
+ children: t.map(([e, t]) => /* @__PURE__ */ T("div", {
1029
+ className: "min-w-0",
1030
+ children: [/* @__PURE__ */ w("dt", {
1031
+ className: "truncate text-[11px] uppercase tracking-wide text-text-muted",
1032
+ children: F(e)
1033
+ }), /* @__PURE__ */ w("dd", {
1034
+ className: "truncate text-sm font-medium tabular-nums text-text-primary",
1035
+ children: tt(t)
1036
+ })]
1037
+ }, e))
1038
+ }) : null
1039
+ ]
1040
+ });
1041
+ }
1042
+ function st({ insight: e, onAcknowledge: t, onResolve: n, onDismiss: r, actionPending: i }) {
823
1043
  let a = e.status === "RESOLVED" || e.status === "DISMISSED";
824
1044
  return /* @__PURE__ */ T("div", {
825
1045
  className: "flex items-start justify-between gap-4 rounded-lg border border-border-subtle bg-bg-surface p-4 transition-shadow motion-safe:hover:shadow-[var(--shadow-pop-hover,var(--shadow-elevation-2))]",
@@ -835,15 +1055,15 @@ function tt({ insight: e, onAcknowledge: t, onResolve: n, onDismiss: r, actionPe
835
1055
  }),
836
1056
  /* @__PURE__ */ w(E, {
837
1057
  variant: g(e.severity),
838
- children: I(e.severity)
1058
+ children: F(e.severity)
839
1059
  }),
840
1060
  /* @__PURE__ */ w(E, {
841
1061
  variant: "outline",
842
- children: I(e.type)
1062
+ children: F(e.type)
843
1063
  }),
844
1064
  /* @__PURE__ */ w(E, {
845
1065
  variant: g(e.status),
846
- children: I(e.status)
1066
+ children: F(e.status)
847
1067
  })
848
1068
  ]
849
1069
  }),
@@ -859,24 +1079,24 @@ function tt({ insight: e, onAcknowledge: t, onResolve: n, onDismiss: r, actionPe
859
1079
  }), a ? /* @__PURE__ */ w("span", {
860
1080
  className: "mt-1 text-xs text-text-muted",
861
1081
  children: "Closed"
862
- }) : /* @__PURE__ */ T(Oe, { children: [/* @__PURE__ */ w(Me, {
1082
+ }) : /* @__PURE__ */ T(Ne, { children: [/* @__PURE__ */ w(Le, {
863
1083
  asChild: !0,
864
1084
  children: /* @__PURE__ */ w(D, {
865
1085
  variant: "ghost",
866
1086
  size: "sm",
867
1087
  "aria-label": `Actions for ${e.title}`,
868
1088
  disabled: i,
869
- children: /* @__PURE__ */ w(me, {
1089
+ children: /* @__PURE__ */ w(_e, {
870
1090
  className: "size-4",
871
1091
  "aria-hidden": "true"
872
1092
  })
873
1093
  })
874
- }), /* @__PURE__ */ T(ke, {
1094
+ }), /* @__PURE__ */ T(Pe, {
875
1095
  align: "end",
876
1096
  children: [
877
1097
  e.status === "OPEN" ? /* @__PURE__ */ T(A, {
878
1098
  onClick: t,
879
- children: [/* @__PURE__ */ w(y, {
1099
+ children: [/* @__PURE__ */ w(me, {
880
1100
  className: "size-4",
881
1101
  "aria-hidden": "true"
882
1102
  }), "Acknowledge"]
@@ -901,6 +1121,6 @@ function tt({ insight: e, onAcknowledge: t, onResolve: n, onDismiss: r, actionPe
901
1121
  });
902
1122
  }
903
1123
  //#endregion
904
- export { $e as RiskPage };
1124
+ export { R as RiskPage };
905
1125
 
906
1126
  //# sourceMappingURL=RiskPage.js.map