/* 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 to review the investment case and risks before you decide?"] },
  { 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,
});
