/* data.jsx, Yoshi mobile · the whole dummy dataset + formatters.
   Numbers are plausible (net worth ≈ $397k). Tickers are real symbols,
   prices are illustrative. Everything here is static seed data; the app
   layers live state on top. Exported on `window`. */

const { useState, useEffect, useRef, useMemo, useCallback } = React;

/* ---------- formatters ----------------------------------------------------- */
// Split a number into grouped whole + decimal so the cents can grey out.
const money = (n, dp = 2) => {
  const neg = n < 0;
  const [w, d] = Math.abs(n).toFixed(dp).split(".");
  return { neg, whole: w.replace(/\B(?=(\d{3})+(?!\d))/g, ","), dec: d || "" };
};
// Full string e.g. "$1,234.56"
const usd = (n, dp = 2) => {
  const m = money(n, dp);
  return (m.neg ? "-$" : "$") + m.whole + (m.dec ? "." + m.dec : "");
};
const signed = (n, dp = 2) => { const m = money(n, dp); return (n >= 0 ? "+" : "−") + "$" + m.whole + (m.dec ? "." + m.dec : ""); };
const pct = (n) => (n >= 0 ? "+" : "−") + Math.abs(n).toFixed(2) + "%";
/* combined performance readout — the canonical app-wide format: +$XX.XX (X.X%) */
const perf = (abs, p, dp = 2) => signed(abs, dp) + " (" + Math.abs(p).toFixed(1) + "%)";

/* ---------- seeded series generator ---------------------------------------
   mulberry32 PRNG → a deterministic walk from start→end so a holding's
   chart always matches its quoted % move. */
const mulberry32 = (a) => () => {
  a |= 0; a = (a + 0x6D2B79F5) | 0;
  let t = Math.imul(a ^ (a >>> 15), 1 | a);
  t = (t + Math.imul(t ^ (t >>> 7), 61 | t)) ^ t;
  return ((t ^ (t >>> 14)) >>> 0) / 4294967296;
};
function series(seed, len, start, end, vol) {
  const rnd = mulberry32(seed);
  const pts = [];
  for (let i = 0; i < len; i++) {
    const t = i / (len - 1);
    const base = start + (end - start) * t;
    const noise = (rnd() - 0.5) * vol * (start || 1) * (1 - Math.abs(t - 0.5)); // taper at ends
    pts.push(i === len - 1 ? end : base + noise);
  }
  return pts;
}

/* ---------- the account model ---------------------------------------------- */
const HOLDINGS = [
  { id: "vti",  ticker: "VTI",  name: "Vanguard Total Market",  kind: "etf",    shares: 420,  avg: 235.10, last: 291.44, dch:  0.74, seed: 11,
    perf: { "1W": 1.2, "1M": 3.4, "1Y": 21.8 }, group: "investments",
    fund: [["Asset class","US Equity ETF"],["Expense ratio","0.03%"],["Yield","1.31%"],["52w range","224.10 – 296.80"]],
    news: [["Reuters","Broad market ETFs see record weekly inflows","2h"],["Bloomberg","Total-market funds outperform sector bets in Q1","Yest"]] },
  { id: "nvda", ticker: "NVDA", name: "NVIDIA Corp",            kind: "stock",  shares: 180,  avg: 88.40,  last: 142.17, dch:  2.31, seed: 22,
    perf: { "1W": 4.1, "1M": 9.7, "1Y": 64.2 }, group: "investments",
    fund: [["Market cap","$3.48T"],["P/E ratio","58.2"],["Day range","138.02 – 143.66"],["52w range","86.62 – 153.13"]],
    news: [["CNBC","NVIDIA extends rally on data-center demand","41m"],["WSJ","Chipmakers lead the tape into the close","3h"]] },
  { id: "aapl", ticker: "AAPL", name: "Apple Inc",              kind: "stock",  shares: 145,  avg: 171.20, last: 214.05, dch: -0.58, seed: 33,
    perf: { "1W": -0.9, "1M": 2.1, "1Y": 14.6 }, group: "investments",
    fund: [["Market cap","$3.27T"],["P/E ratio","33.4"],["Day range","212.88 – 216.40"],["52w range","164.08 – 237.49"]],
    news: [["The Verge","Apple's services revenue hits new high","1h"],["Bloomberg","Hardware guidance trimmed for the quarter","Yest"]] },
  { id: "voo",  ticker: "VOO",  name: "Vanguard S&P 500",       kind: "etf",    shares: 60,   avg: 402.30, last: 548.12, dch:  0.66, seed: 44,
    perf: { "1W": 1.0, "1M": 3.0, "1Y": 19.4 }, group: "investments",
    fund: [["Asset class","US Large-Cap ETF"],["Expense ratio","0.03%"],["Yield","1.27%"],["52w range","468.20 – 552.10"]],
    news: [["Morningstar","S&P 500 index funds extend gains","2h"]] },
  { id: "msft", ticker: "MSFT", name: "Microsoft Corp",         kind: "stock",  shares: 32,   avg: 332.50, last: 468.30, dch:  1.12, seed: 55,
    perf: { "1W": 2.2, "1M": 4.8, "1Y": 27.1 }, group: "investments",
    fund: [["Market cap","$3.48T"],["P/E ratio","36.9"],["Day range","462.10 – 470.55"],["52w range","362.90 – 471.00"]],
    news: [["Reuters","Microsoft cloud bookings beat estimates","4h"]] },

  { id: "btc",  ticker: "BTC",  name: "Bitcoin",                kind: "crypto", shares: 0.52, avg: 41200, last: 96180, dch:  3.42, seed: 66,
    perf: { "1W": 5.6, "1M": 12.4, "1Y": 118.0 }, group: "crypto",
    fund: [["Network","Bitcoin"],["Holdings","0.52000000 BTC"],["Cost basis","$41,200"],["24h range","92,400 – 97,010"]],
    news: [["CoinDesk","Bitcoin reclaims $96k as ETFs absorb supply","18m"],["Bloomberg","Spot BTC ETFs log eighth straight inflow day","2h"]] },
  { id: "eth",  ticker: "ETH",  name: "Ethereum",               kind: "crypto", shares: 4.2,  avg: 2210,  last: 3640, dch: -1.18, seed: 77,
    perf: { "1W": -2.1, "1M": 6.8, "1Y": 41.2 }, group: "crypto",
    fund: [["Network","Ethereum"],["Holdings","4.20000000 ETH"],["Cost basis","$2,210"],["24h range","3,580 – 3,712"]],
    news: [["The Block","Staking yields tick higher after upgrade","1h"]] },
  { id: "sol",  ticker: "SOL",  name: "Solana",                 kind: "crypto", shares: 120,  avg: 96.10, last: 188.40, dch:  4.77, seed: 88,
    perf: { "1W": 8.2, "1M": 19.3, "1Y": 96.5 }, group: "crypto",
    fund: [["Network","Solana"],["Holdings","120.000 SOL"],["Cost basis","$96.10"],["24h range","176.20 – 191.00"]],
    news: [["Decrypt","Solana network activity sets monthly record","3h"]] },
];

// Derived per-holding numbers.
HOLDINGS.forEach(h => {
  h.value   = h.shares * h.last;
  h.cost    = h.shares * h.avg;
  h.pl      = h.value - h.cost;
  h.plPct   = (h.pl / h.cost) * 100;
  h.dayAbs  = h.value * (h.dch / 100);
});

const CASH = [
  { id: "chk",  name: "Checking",  sub: "Yoshi · ••8841", apr: "",         value: 18420.55, color: "var(--ink-3)" },
  { id: "sav",  name: "Savings",   sub: "Yoshi · ••2207", apr: "4.80% APY", value: 64000.00, color: "var(--accent-2)" },
];

const GROUPS = {
  cash:        { label: "Cash",        items: CASH,                                       color: "var(--ink-2)" },
  investments: { label: "Investments", items: HOLDINGS.filter(h => h.group === "investments"), color: "var(--accent-4)" },
  crypto:      { label: "Crypto",      items: HOLDINGS.filter(h => h.group === "crypto"),      color: "var(--accent)" },
};

const sum = (arr) => arr.reduce((s, x) => s + x.value, 0);
const CASH_TOTAL   = sum(CASH);
const INVEST_TOTAL = sum(GROUPS.investments.items);
const CRYPTO_TOTAL = sum(GROUPS.crypto.items);
const NET_WORTH    = CASH_TOTAL + INVEST_TOTAL + CRYPTO_TOTAL;

/* Liabilities, read-only, linked from outside Yoshi via Plaid (like the
   external accounts in the Accounts tab). Net worth nets these against assets. */
const LIABILITIES = [
  { id: "mortgage", name: "Home mortgage", sub: "Wells Fargo · ••7704", value: 238400.00, color: "var(--signal-neg)", min: "$2,140/mo · 27 yr left", apr: "5.88% APR",
    debt: { outstanding: "$238,400.00", original: "$310,000.00", term: "30 yr fixed", payoff: "Mar 2052", paid: "$146,200.00", nextMin: "$2,140.00 · Jun 1" } },
  { id: "sapphire", name: "Chase Sapphire", sub: "Credit card · ••6841", value: 3210.44, color: "var(--signal-neg)", min: "$35 min · due Jun 14", apr: "21.99% APR",
    debt: { outstanding: "$3,210.44", original: "$12,000.00 limit", term: "Revolving", payoff: "Revolving", paid: "$8,940.00", nextMin: "$35.00 · Jun 14" } },
  { id: "amex",     name: "Amex Gold",      sub: "Credit card · ••2008", value: 1180.62, color: "var(--signal-neg)", min: "$40 min · due Jun 9", apr: "24.24% APR",
    debt: { outstanding: "$1,180.62", original: "$10,000.00 limit", term: "Revolving", payoff: "Revolving", paid: "$5,210.00", nextMin: "$40.00 · Jun 9" } },
];
const LIAB_TOTAL   = sum(LIABILITIES);
const ASSET_TOTAL  = NET_WORTH;                 // alias, assets held at Yoshi
const NET_WORTH_TRUE = ASSET_TOTAL - LIAB_TOTAL; // assets minus liabilities
const DAY_ABS      = HOLDINGS.reduce((s, h) => s + h.dayAbs, 0) + 0; // cash doesn't move
const DAY_PCT      = (DAY_ABS / (NET_WORTH - DAY_ABS)) * 100;

/* Net-worth intraday series → ends at NET_WORTH, with two automation markers. */
const NW_SERIES = series(101, 34, NET_WORTH - DAY_ABS - 1800, NET_WORTH, 0.0016);
const NW_MARKERS = [
  { idx: 3,  time: "9:31",  name: "Weekly investing · VTI",  detail: "Bought $500 VTI", autoId: "a1" },
  { idx: 17, time: "11:08", name: "Sweep idle cash",   detail: "$12,000 · Checking to Savings", autoId: "a2" },
];

/* ---------- agent proposals (inbox) ---------------------------------------- */
const PROPOSALS = [
  { id: "p1", agent: "Yoshi agent", channel: "in-app", title: "Rebalance your investments",
    why: "Your stocks have grown to a bigger share than you planned. Sell some NVDA and BTC, buy VOO, to get back to your mix. You'd lock in a small gain.",
    net: 1153.66, settles: "tomorrow", kind: "trade",
    legs: [["SELL","NVDA","12 sh","≈ $1,706"],["SELL","BTC","0.018","≈ $1,731"],["BUY","VOO","6.1 sh","≈ $3,344"]] },
  { id: "p2", agent: "External agent", channel: "whatsapp", title: "Pay Chase Sapphire",
    why: "Your $2,340.18 statement is due in 6 days at 21.99% APR. Paying it in full from Cash now means you owe $0 interest and keep the card at a zero balance, and if you miss it the interest starts piling up on the whole balance.",
    net: -2340.18, settles: "tomorrow", settlesVerb: "closes", kind: "transfer",
    legs: [["PAY","Chase Sapphire","Statement","$2,340.18"],["FROM","Cash ••8841","Balance after","$80,080.37"]] },
  { id: "p3", agent: "Yoshi agent", channel: "email", title: "Earn more on idle cash",
    why: "$15,000 has sat in Savings for 9 days. Move it into short-term Treasuries earning about 5.1%, your money stays available every month.",
    net: 64.00, settles: "in 2 days", kind: "trade",
    legs: [["BUY","26-wk Treasuries","6 buys","$15,000"],["YIELD","Average","Per year","≈ 5.10%"]] },
];

const COMPLETED = [
  { id: "c1", title: "Sweep idle cash", detail: "$12,000 · Checking to Savings", when: "May 29", net: 0, by: "Cash agent" },
  { id: "c2", title: "Bought VOO", detail: "8.234 sh @ $548.12", when: "May 28", net: -4513.20, by: "Weekly investing · VTI" },
  { id: "c3", title: "Sold BTC", detail: "0.0421 @ $96,180", when: "May 25", net: 4049.18, by: "You" },
  { id: "c4", title: "Paid IRS · Q1 estimated", detail: "$8,432.00 · Checking", when: "Apr 22", net: -8432.00, by: "Tax agent" },
];

/* ---------- the stream · all activity, grouped by day -----------------------
   A mix of executions, deposits, a weekly summary digest, and a custom report
   the user asked Yoshi for. Newly-approved proposals get prepended to Today. */
const ACTIVITY = [
  { day: "Today", items: [
    { type: "report", kind: "Weekly summary", title: "Your week with Yoshi", detail: "Net worth +$3,212 · 4 automations ran · 1 proposal approved · $237 interest earned", when: "9:00" },
    { type: "exec", title: "Sweep idle cash", detail: "Checking to Savings", when: "11:08", net: 0, amount: 12000, by: "Cash agent" },
    { type: "exec", title: "Bought VTI", detail: "2.10 sh @ $291.44 · auto-invest", when: "9:31", net: -612.00, by: "Weekly investing · VTI" },
  ] },
  { day: "Yesterday", items: [
    { type: "exec", title: "Bought VOO", detail: "8.234 sh @ $548.12", when: "15:42", net: -4513.20, by: "Weekly investing · VTI" },
    { type: "report", kind: "Custom report", title: "Dining spend · last 90 days", detail: "$1,840 across 38 charges. Trending −12% vs prior 90d", when: "14:10" },
    { type: "deposit", title: "Pay day", detail: "Acme Corp · direct deposit", when: "08:02", net: 6240.00 },
  ] },
  { day: "Earlier this week", items: [
    { type: "exec", title: "Sold BTC", detail: "0.0421 @ $96,180", when: "Mon", net: 4049.18, by: "You" },
    { type: "exec", title: "Reserved tax", detail: "5% of deposit to Tax 2026", when: "Sun", net: -1747.20, by: "Tax agent" },
    { type: "exec", title: "Paid Chase card", detail: "Statement balance · Checking", when: "Sun", net: -2340.18, by: "Cash agent" },
  ] },
  { day: "Apr 22", items: [
    { type: "exec", title: "Paid IRS · Q1 estimated", detail: "$8,432.00 · Checking", when: "Apr 22", net: -8432.00, by: "Tax agent" },
  ] },
];

/* ---------- chat seed ------------------------------------------------------ */
const CHAT_SEED = [
  { from: "agent", t: "Morning. Your accounts are up $4,802 today, mostly NVDA and SOL. One thing needs you: your stocks have grown past the mix you wanted, so I'd like to even things out.", time: "9:24" },
  { from: "user",  t: "what would that do", time: "9:25" },
  { from: "agent", t: "Three trades: sell a little NVDA and Bitcoin, add VOO. You'd come out about $1,153 ahead, all done by tomorrow. Here it is, approve whenever you're ready.", time: "9:25", proposal: "p1" },
];

const QUICK_REPLIES = ["How's my cash doing?", "Pause my weekly investing", "What did you do today?", "Anything need my approval?"];

/* ---------- chat threads · past conversations with Yoshi -------------------
   The live thread is held in component state (seeded from CHAT_SEED above).
   These are read-only history, newest first. */
const THREADS = [
  { id: "th_tbill", title: "Earning more on idle cash", when: "May 26", preview: "Moved $15k of idle cash into short-term Treasuries at about 5.1%.",
    msgs: [
      { from: "user",  t: "what should i do with the idle cash in savings", time: "2:14 PM" },
      { from: "agent", t: "$15,000 has sat unused for 9 days. I'd move it into short-term Treasuries earning about 5.1%, your money stays available every month. Here's the proposal.", time: "2:14 PM" },
      { from: "user",  t: "looks good", time: "2:15 PM" },
      { from: "agent", t: "It's ready, approve whenever you like.", time: "2:15 PM" },
    ] },
  { id: "th_dca", title: "Pause investing for vacation", when: "May 18", preview: "Paused the weekly VTI buy. Kept the cash sweep running.",
    msgs: [
      { from: "user",  t: "pause my investing while i'm away next week", time: "7:40 AM" },
      { from: "agent", t: "Paused the weekly VTI buy. Nothing runs until you turn it back on. I'll keep sweeping idle cash to Savings unless you'd like that off too.", time: "7:41 AM" },
      { from: "user",  t: "keep the sweep on", time: "7:41 AM" },
      { from: "agent", t: "Will do. Enjoy the trip.", time: "7:41 AM" },
    ] },
  { id: "th_tax", title: "Tax reserve setup", when: "May 2", preview: "New rule: reserve 28% of every freelance deposit.",
    msgs: [
      { from: "user",  t: "i keep underpaying my quarterly taxes", time: "11:02 AM" },
      { from: "agent", t: "I can fix that at the source. New rule: reserve 28% of every freelance deposit into a Tax 2026 bucket, automatically. You'd never spend it by accident.", time: "11:02 AM" },
      { from: "user",  t: "do it", time: "11:03 AM" },
      { from: "agent", t: "Live. The first reserve runs on your next deposit. I'll log each one to your stream.", time: "11:03 AM" },
    ] },
  { id: "th_nvda", title: "Why NVDA dropped", when: "Apr 28", preview: "Sector pullback, not company-specific. Held on.",
    msgs: [
      { from: "user",  t: "why is nvda down today", time: "3:30 PM" },
      { from: "agent", t: "Sector-wide pullback after a downgrade across chipmakers, not company-specific. You're still up 64% on it, so this is just noise and nothing I'd act on.", time: "3:30 PM" },
      { from: "user",  t: "ok, leave it", time: "3:31 PM" },
    ] },
];

/* ---------- recent activity · a real transaction ledger -------------------
   More than agent moves: card spend, payroll, transfers, dividends, refunds. */
const TRANSACTIONS = [
  { id: "t1", icon: "receipt", title: "Whole Foods Market", detail: "Card ··4417", when: "Today", net: -142.38 },
  { id: "t2", icon: "down",    title: "Payroll · Northwind Labs", detail: "Direct deposit", when: "Today", net: 8200.00 },
  { id: "t3", icon: "bolt",    title: "Swept idle cash", detail: "Checking to Savings · Cash agent", when: "May 28", net: 0 },
  { id: "t4", icon: "swap",    title: "Sent to Maya Cohen", detail: "Zelle ··4471", when: "May 28", net: -250.00 },
  { id: "t5", icon: "trade",   title: "Dividend · VTI", detail: "Reinvested", when: "May 27", net: 84.20 },
  { id: "t6", icon: "receipt", title: "Uber", detail: "Card ··4417", when: "May 26", net: -23.90 },
  { id: "t7", icon: "down",    title: "Refund · Delta Air Lines", detail: "Card ··4417", when: "May 25", net: 312.40 },
  { id: "t8", icon: "receipt", title: "Netflix", detail: "Subscription · Card ··4417", when: "May 25", net: -15.49 },
  { id: "t9", icon: "trade",   title: "Sold BTC", detail: "0.0421 @ $96,180 · You", when: "May 24", net: 4049.18 },
  { id: "t10", icon: "receipt", title: "Con Edison", detail: "Autopay · Card ··4417", when: "May 23", net: -118.04 },
  { id: "t11", icon: "swap",   title: "Transfer to Brokerage", detail: "Chase to Yoshi ··3392", when: "May 22", net: -2000.00 },
];

/* ---------- automations · standing rules the agents run -------------------- */
const AUTOMATIONS = [
  { id: "a1", name: "Weekly investing · VTI", status: "active", cadence: "Every Friday · 11 weeks", measure: "+$184", sub: "this month",
    summary: "Buys $500 of VTI every Friday at the open, funded from Checking.", next: "Next run · Fri May 30",
    perf: [["Invested", "$5,500"], ["Current value", "$5,684"], ["Total return", "+$184 (3.3%)"], ["Runs", "11"]] },
  { id: "a2", name: "Sweep idle cash", status: "active", cadence: "Standing rule · 4.8% APY", measure: "+$237", sub: "interest, 90d",
    summary: "Moves idle Checking cash above $15,000 into Savings to earn 4.8% APY.", next: "Triggers when idle > $15,000",
    perf: [["Swept, 90d", "$48,000"], ["Interest", "+$237"], ["Threshold", "> $15,000"], ["Last run", "May 28"]] },
  { id: "a3", name: "Lower taxes on gains", status: "watching", cadence: "Watching · 2 holdings", measure: "+$420", sub: "saved ytd",
    summary: "Watches for investments that have dropped, so selling one can reduce the taxes you owe on your gains.", next: "No action needed today",
    perf: [["Saved YTD", "+$420"], ["Watching", "2"], ["Est. tax saved", "$96"], ["Safeguards", "On"]] },
  { id: "a4", name: "Round-ups into BTC", status: "active", cadence: "Per card swipe", measure: "+$62", sub: "invested, 30d",
    summary: "Rounds each card purchase to the nearest dollar and buys BTC weekly.", next: "Next buy · Sun Jun 1",
    perf: [["Rounded, 30d", "$62"], ["Into", "BTC"], ["Avg / swipe", "$0.41"], ["Swipes", "151"]] },
  { id: "a5", name: "Pay card in full", status: "active", cadence: "On statement close", measure: "$0", sub: "interest paid",
    summary: "Pays the full statement balance from Checking the day before it's due.", next: "Next · Chase Sapphire, Jun 2",
    perf: [["Paid YTD", "$14,200"], ["Interest", "$0"], ["On-time", "100%"], ["Source", "Checking"]] },
];

/* ---------- market universe + explore (trade search) ---------------------- */
const MARKET = [
  ...HOLDINGS.map(h => ({ id: h.id, ticker: h.ticker, name: h.name, last: h.last, dch: h.dch, kind: h.kind, held: true })),
  { id: "tsla",  ticker: "TSLA",  name: "Tesla Inc",            last: 342.18, dch: -1.84, kind: "stock" },
  { id: "googl", ticker: "GOOGL", name: "Alphabet Inc",         last: 178.22, dch: 0.91,  kind: "stock" },
  { id: "amzn",  ticker: "AMZN",  name: "Amazon.com Inc",       last: 201.40, dch: 1.22,  kind: "stock" },
  { id: "spy",   ticker: "SPY",   name: "SPDR S&P 500 ETF",     last: 597.10, dch: 0.64,  kind: "etf" },
  { id: "coin",  ticker: "COIN",  name: "Coinbase Global",      last: 248.77, dch: 3.10,  kind: "stock" },
  { id: "qqq",   ticker: "QQQ",   name: "Invesco QQQ Trust",    last: 512.33, dch: 0.88,  kind: "etf" },
  { id: "meta",  ticker: "META",  name: "Meta Platforms",       last: 612.05, dch: 1.45,  kind: "stock" },
  { id: "amd",   ticker: "AMD",   name: "Advanced Micro Dev",   last: 168.90, dch: 2.07,  kind: "stock" },
  { id: "doge",  ticker: "DOGE",  name: "Dogecoin",             last: 0.42,   dch: 5.60,  kind: "crypto" },
];
const TRENDING = ["nvda", "btc", "tsla", "sol", "coin", "amd"];
const EXPLORE_NEWS = [
  ["Bloomberg", "Chipmakers lead the tape as AI demand holds", "41m"],
  ["Reuters",   "Fed minutes point to one more cut this year",  "2h"],
  ["CoinDesk",  "Spot BTC ETFs log eighth straight inflow day", "3h"],
  ["WSJ",       "Big tech earnings beat, guidance mixed",        "5h"],
];

/* AI news brief · whole-market synthesis with cited, click-out sources */
const MARKET_NEWS = {
  when: "9:41 AM",
  brief: [
    { t: "Equities opened higher with semiconductors leading the tape as AI demand stays firm", s: 0 },
    { t: "Rate worries eased after Fed minutes pointed to one more cut this year", s: 1 },
    { t: "Crypto held steady — spot Bitcoin ETFs logged an eighth straight day of inflows", s: 2 },
    { t: "Big-tech earnings beat on revenue, though forward guidance came in mixed", s: 3 },
  ],
  sources: [
    { pub: "Bloomberg", head: "Chipmakers lead the tape as AI demand holds", when: "41m", url: "https://www.bloomberg.com/markets" },
    { pub: "Reuters",   head: "Fed minutes point to one more cut this year",  when: "2h",  url: "https://www.reuters.com/markets/us/" },
    { pub: "CoinDesk",  head: "Spot BTC ETFs log eighth straight inflow day", when: "3h",  url: "https://www.coindesk.com/markets" },
    { pub: "WSJ",       head: "Big tech earnings beat, guidance mixed",        when: "5h",  url: "https://www.wsj.com/finance/stocks" },
  ],
};

/* AI news brief · synthesis of stories that touch the user's holdings */
const HOLDINGS_NEWS = {
  when: "9:41 AM",
  brief: [
    { tkr: "NVDA", t: "extended its rally on steady AI demand, lifting your largest position", s: 0 },
    { tkr: "VTI",  t: "rode a record day of broad-market ETF inflows, a tailwind for your core holding", s: 1 },
    { tkr: "BTC",  t: "held a key level, steadying your crypto sleeve, with nothing that needs action", s: 2 },
  ],
  sources: [
    { pub: "Bloomberg",   head: "Nvidia extends rally as AI orders stay strong", when: "1h", url: "https://www.bloomberg.com/quote/NVDA:US" },
    { pub: "Morningstar", head: "Broad-market ETF inflows hit a record",         when: "3h", url: "https://www.morningstar.com/etfs/arcx/vti/quote" },
    { pub: "CoinDesk",    head: "Bitcoin holds support as ETF demand steadies",  when: "4h", url: "https://www.coindesk.com/price/bitcoin" },
  ],
};

/* Day-one read · MARKET — shown before any accounts are linked. General market,
   no personal positions, no citations needed beyond public sources. */
const DAYONE_MARKET_NEWS = {
  when: "9:41 AM",
  brief: [
    { tkr: "Stocks", t: "opened higher as broad indexes pushed toward record territory on steady economic data", s: 0 },
    { tkr: "Yields", t: "eased after a soft inflation print, a supportive backdrop for both stocks and bonds", s: 1 },
    { tkr: "BTC",    t: "held a key level on firm ETF demand, with no major headlines behind the move", s: 2 },
  ],
  sources: [
    { pub: "Bloomberg",   head: "Stocks climb toward records on steady data",   when: "1h", url: "https://www.bloomberg.com/markets" },
    { pub: "Reuters",     head: "Treasury yields ease after soft inflation",    when: "2h", url: "https://www.reuters.com/markets/" },
    { pub: "CoinDesk",    head: "Bitcoin holds support as ETF demand steadies", when: "4h", url: "https://www.coindesk.com/price/bitcoin" },
  ],
};

/* Day-one read · FINANCE — shown once the user links accounts. A quick read on
   their own money rather than the market. No external citations. */
const DAYONE_FINANCE_NEWS = {
  when: "9:41 AM",
  brief: [
    { tkr: "Cash",     t: "Most of your linked balance is sitting in checking, earning close to nothing" },
    { tkr: "Savings",  t: "Moving idle cash into a high-yield account could add a few hundred dollars a year" },
    { tkr: "Spending", t: "Your recurring charges look steady this week, with nothing unusual to flag" },
  ],
  sources: [],
};

/* ---------- profile -------------------------------------------------------- */
const PROFILE = {
  name: "Rivka Lipson", handle: "@rivka", member: "Member since 2025",
  channels: [
    ["Push notifications", "On this device", true],
    ["WhatsApp", "+1 ••• ••• 4471", true],
    ["iMessage", "rivka@hey.com", true],
    ["Email", "rivka@hey.com", false],
  ],
  limits: [
    ["Per-approval cap", "$25,000"],
    ["Daily autonomous cap", "$5,000"],
    ["Trades without approval", "Off"],
  ],
};

/* ---------- "For you" · the notification hub, split into folders ----------- */
/* folder: "alerts" (recaps, price alerts, opportunities, nudges) or
   "automations" (confirmations a standing rule ran). "Needs you" pulls from
   PROPOSALS and "Insights" from BRIEF_INSIGHTS — both handled in the UI. */
const BRIEFS = [
  { id: "b1", folder: "alerts", type: "recap", title: "Market recap",
    body: "Markets closed higher. Your portfolio is up " + perf(DAY_ABS, DAY_PCT) + " today, led by NVDA and BTC.",
    value: DAY_ABS, tone: "in", when: "4:05 PM",
    ask: ["Give me today's market recap.", "Markets closed higher. Your portfolio finished " + perf(DAY_ABS, DAY_PCT) + ", led by NVDA (+3.2%) and BTC (+2.4%). Cash and bonds were flat. Nothing needs your attention right now, so just say the word if you want a deeper read on any holding."] },
  { id: "b2", folder: "alerts", type: "report", title: "Debt payoff report",
    body: "Your scheduled report: card balances are down $1,160 this month, and at this pace the Amex Gold clears in about 4 months.",
    value: 1160, tone: "in", when: "Mon",
    ask: ["Show my debt payoff progress.", "Here's where your payoff plan stands. Total card debt is down to $4,391 from $5,551, the Amex Gold (24.24% APR) clears in about 4 months at $300 a month, and the Chase Sapphire follows after that. Want me to put more toward the higher-rate card so it finishes sooner?"] },
  { id: "b3", folder: "alerts", type: "opportunity", title: "Idle cash is sitting still",
    body: "$15,000 has sat in Checking for 9 days. Moved to short-term Treasuries it could earn about 5.1% and stay liquid.",
    when: "11:02 AM",
    ask: ["Should I move my idle cash?", "$15,000 has been idle in Checking for 9 days, earning nothing. In 26-week Treasuries near 5.1% that's about $760 a year, and it stays available. Want me to draft the move for your approval?"] },
  { id: "b4", folder: "alerts", type: "nudge", title: "NVDA is 18% of your book",
    body: "After the run, a single name is a large share of your portfolio. Worth trimming to rebalance?",
    when: "Fri",
    ask: ["Is my NVDA position too big?", "NVDA is about 18% of your investments after the run, which is a lot riding on one name. If you trim a slice into a broad fund you lower the single-stock risk without changing your direction, so want me to size a rebalance?"] },
  { id: "b5", folder: "alerts", type: "alert", title: "Price alert · COIN",
    body: "COIN slipped below $240, down 2.1% this week. Not held.",
    value: 240, when: "Thu",
    ask: ["Should I buy COIN on the dip?", "COIN is down 2.1% this week, trading just under $240. You don't hold it today. It's volatile and moves with crypto flows, so if you want exposure I'd keep it small. Want me to put together a paper trade first?"] },
  { id: "r1", folder: "automations", type: "automation", title: "Sweep idle cash ran", autoId: "a2",
    body: "Moved $4,000 from Checking to Savings to keep earning 4.80% APY.",
    value: 4000, when: "9:30 AM" },
  { id: "r2", folder: "automations", type: "automation", title: "Weekly investing ran", autoId: "a1",
    body: "Bought $500 of VTI at the open. 11-week streak, +$184 so far.",
    value: 500, when: "Fri" },
  { id: "r3", folder: "automations", type: "automation", title: "Paid Chase Sapphire in full", autoId: "a5",
    body: "Paid the $2,340 statement from Checking the day before it was due. No interest owed.",
    value: 2340, when: "Jun 2" },
];

/* insights folder — what Yoshi sees across the accounts */
const BRIEF_INSIGHTS = [
  { label: "Spending", stat: "−12%", tone: "pos", read: "You spent 12% less this month than last, because dining and travel both dropped.",
    ask: ["Break down my spending.", "You're down 12% month over month, mostly less dining and travel. Top categories are groceries, utilities, and subscriptions. Want a full breakdown or a budget?"] },
  { label: "Fees paid", stat: "$0", tone: "pos", read: "No account, trading, or transfer fees so far this year.",
    ask: ["What fees am I paying?", "You've paid nothing so far this year, because there are no account, commission, or standard transfer fees. Only expedited wires cost anything, so want the fee schedule?"] },
];

Object.assign(window, {
  useState, useEffect, useRef, useMemo, useCallback,
  money, usd, signed, pct, perf, series, mulberry32,
  HOLDINGS, CASH, GROUPS, CASH_TOTAL, INVEST_TOTAL, CRYPTO_TOTAL, NET_WORTH, DAY_ABS, DAY_PCT,
  LIABILITIES, LIAB_TOTAL, ASSET_TOTAL, NET_WORTH_TRUE,
  NW_SERIES, NW_MARKERS, PROPOSALS, COMPLETED, ACTIVITY, CHAT_SEED, QUICK_REPLIES, THREADS, PROFILE,
  TRANSACTIONS, AUTOMATIONS, MARKET, TRENDING, EXPLORE_NEWS, MARKET_NEWS, HOLDINGS_NEWS, DAYONE_MARKET_NEWS, DAYONE_FINANCE_NEWS, BRIEFS, BRIEF_INSIGHTS,
});
