/* flow3.jsx — Plaid link sheet · Funding · External accounts · Agent · Off to work. */

/* =============================================================
   Plaid link — the account-linking product experience, reused for
   the funding source (one depository) and read-only externals (many).
   ============================================================= */
const BANKS = [
  { id: "chase",    name: "Chase",            tint: "#1059a8", accts: [["Checking", "Checking", "••8841", 14231], ["Brokerage", "Brokerage", "••2207", 8400]] },
  { id: "bofa",     name: "Bank of America",  tint: "#c4112f", accts: [["Advantage Checking", "Checking", "••3392", 5210], ["Rewards Savings", "Savings", "••7715", 19800]] },
  { id: "wells",    name: "Wells Fargo",      tint: "#b81e26", accts: [["Everyday Checking", "Checking", "••4471", 3120]] },
  { id: "amex",     name: "American Express",  tint: "#1b6fb3", accts: [["Platinum Card", "Card", "••1008", -2104], ["High Yield Savings", "Savings", "••9920", 22500]] },
  { id: "capone",   name: "Capital One",      tint: "#13415f", accts: [["360 Checking", "Checking", "••5567", 2840]] },
  { id: "schwab",   name: "Charles Schwab",   tint: "#00a0df", accts: [["Brokerage", "Brokerage", "••2231", 88402]] },
  { id: "fidelity", name: "Fidelity",         tint: "#3a8c3f", accts: [["Individual", "Brokerage", "••6610", 31980]] },
  { id: "coinbase", name: "Coinbase",         tint: "#1652f0", accts: [["Portfolio", "Crypto", "••4417", 6712]] },
];

/* Plaid link. `requireFunding` (no funding source established yet) forces the
   user to include a checking/savings account in their selection — so every
   exit from Plaid leaves them with a usable funding source. Always
   multi-select: you link a bank and pull along any other accounts at once. */
const PlaidLink = ({ mode, requireFunding = false, onClose, onLinked, initialStep, initialBankId, initialSel }) => {
  // step: "list" | "connecting" | "select"
  const [step, setStep] = useState(initialStep || "list");
  const [bank, setBank] = useState(() => initialBankId ? BANKS.find((b) => b.id === initialBankId) || null : null);
  const [q, setQ] = useState("");
  const [sel, setSel] = useState(() => new Set(initialSel || []));

  // When establishing the funding source, only surface institutions that
  // actually have a depository account to link.
  const pool = requireFunding ? BANKS.filter((b) => b.accts.some((a) => a[1] === "Checking" || a[1] === "Savings")) : BANKS;
  const shown = pool.filter((b) => b.name.toLowerCase().includes(q.trim().toLowerCase()));

  const isDep = (a) => a[1] === "Checking" || a[1] === "Savings";

  const pick = (b) => {
    setBank(b); setStep("connecting");
    // pre-select every account at the institution — the user trims from there
    setSel(new Set(b.accts.map((_, i) => i)));
    setTimeout(() => setStep("select"), 1700);
  };
  const toggle = (i) => setSel((prev) => { const n = new Set(prev); n.has(i) ? n.delete(i) : n.add(i); return n; });

  // the funding source = first selected depository at this institution
  const fundingIdx = bank ? bank.accts.findIndex((a, i) => sel.has(i) && isDep(a)) : -1;
  const needsFunding = requireFunding && fundingIdx < 0;

  const finish = () => {
    const accts = [...sel].map((i) => ({ inst: bank.name, instId: bank.id, tint: bank.tint, name: bank.accts[i][0], type: bank.accts[i][1], mask: bank.accts[i][2], bal: bank.accts[i][3] }));
    onLinked(accts);
  };

  return (
    <div className="yo-enter" style={{ position: "absolute", inset: 0, zIndex: 410, background: "#f6f7f9", display: "flex", flexDirection: "column" }}>
      <div style={{ flex: "none", display: "flex", alignItems: "center", padding: "52px 18px 12px", gap: 10 }}>
        <span style={{ width: 22 }} />
        <div style={{ flex: 1, display: "flex", justifyContent: "center" }}><PlaidMark /></div>
        <span style={{ width: 22 }} />
      </div>

      {step === "list" && (
        <>
          <div style={{ flex: "none", padding: "6px 22px 14px" }}>
            <PHead>{mode === "funding" ? "Select your bank" : "Select an institution"}</PHead>
            <div style={{ display: "flex", alignItems: "center", gap: 10, padding: "13px 14px", background: "#fff", border: "1.5px solid #d8dadf", borderRadius: 12, marginTop: 16 }}>
              <Icon name="search" size={17} color="#9a9ea6" />
              <input value={q} onChange={(e) => setQ(e.target.value)} placeholder="Search 12,000+ institutions" autoFocus
                style={{ flex: 1, border: "none", outline: "none", background: "transparent", fontSize: 15, color: "#1a1c1f" }} />
            </div>
          </div>
          <div className="scroll" style={{ flex: 1, minHeight: 0, padding: "0 22px 16px" }}>
            {shown.map((b) => (
              <button key={b.id} className="press" onClick={() => pick(b)} style={{ width: "100%", display: "flex", alignItems: "center", gap: 13, padding: "14px 4px", background: "none", border: "none", borderBottom: "1px solid #eceef1", cursor: "pointer", textAlign: "left" }}>
                <span style={{ width: 38, height: 38, flex: "none", borderRadius: 9, background: b.tint, display: "grid", placeItems: "center", color: "#fff", fontFamily: "var(--f-display)", fontSize: 17, fontWeight: 700 }}>{b.name[0]}</span>
                <span style={{ flex: 1, fontFamily: "var(--f-display)", fontSize: 15.5, fontWeight: 600, color: "#1a1c1f" }}>{b.name}</span>
                <Icon name="arrow" size={17} color="#b6b9bf" />
              </button>
            ))}
          </div>
        </>
      )}

      {step === "connecting" && (
        <div style={{ flex: 1, display: "flex", flexDirection: "column", alignItems: "center", justifyContent: "center", padding: "0 30px", textAlign: "center" }}>
          <span style={{ width: 64, height: 64, borderRadius: 14, background: bank.tint, display: "grid", placeItems: "center", color: "#fff", fontFamily: "var(--f-display)", fontSize: 28, fontWeight: 700 }}>{bank.name[0]}</span>
          <div style={{ marginTop: 22, display: "flex", alignItems: "center", gap: 8, color: "#15171a" }}>
            <LiveDot size={6} color="#111" />
            <span style={{ fontFamily: "var(--f-display)", fontSize: 16, fontWeight: 600 }}>Connecting to {bank.name}…</span>
          </div>
          <div style={{ fontFamily: "var(--f-display)", fontSize: 13, color: "#6b6f76", marginTop: 10, lineHeight: 1.5, maxWidth: "28ch" }}>
            Plaid signs you in securely. Yoshi never sees your bank password.
          </div>
        </div>
      )}

      {step === "select" && (
        <>
          <div className="scroll" style={{ flex: 1, minHeight: 0, padding: "6px 22px 8px" }}>
            <PHead>Accounts at {bank.name}</PHead>
            <PNote>{requireFunding ? "Pick a checking or savings account to fund Yoshi. Add any others for Yoshi to read." : "Select which accounts Yoshi can see. Add a checking or savings to move money."}</PNote>
            <div style={{ marginTop: 18, display: "grid", gap: 10 }}>
              {bank.accts.map((a, i) => {
                const on = sel.has(i);
                const isFunding = i === fundingIdx;
                return (
                  <button key={i} className="press" onClick={() => toggle(i)} style={{ width: "100%", textAlign: "left", display: "flex", alignItems: "center", gap: 13, padding: "14px 15px", background: "#fff", border: `1.5px solid ${on ? "#111" : "#e1e3e8"}`, borderRadius: 12, cursor: "pointer" }}>
                    <span style={{ flex: 1, minWidth: 0 }}>
                      <span style={{ display: "flex", alignItems: "center", gap: 7 }}>
                        <span style={{ fontFamily: "var(--f-display)", fontSize: 15, fontWeight: 600, color: "#1a1c1f" }}>{a[0]}</span>
                      </span>
                      <span style={{ display: "block", fontFamily: "var(--f-display)", fontSize: 12.5, color: "#8a8e96", marginTop: 2 }}>{a[1]} · {a[2]}</span>
                    </span>
                    <span style={{ fontFamily: "var(--f-mono)", fontSize: 14, fontWeight: 600, color: a[3] < 0 ? "#b03a2e" : "#1a1c1f" }}>{a[3] < 0 ? "−$" : "$"}{Math.abs(a[3]).toLocaleString("en-US")}</span>
                    <span style={{ width: 22, height: 22, flex: "none", borderRadius: 6, border: `1.5px solid ${on ? "#111" : "#cdd0d5"}`, background: on ? "#111" : "transparent", display: "grid", placeItems: "center" }}>
                      {on && <Icon name="check" size={13} stroke={2.4} color="#fff" />}
                    </span>
                  </button>
                );
              })}
            </div>
            {needsFunding && (
              <div style={{ display: "flex", alignItems: "flex-start", gap: 8, marginTop: 14, padding: "11px 13px", background: "#fcf3e6", border: "1px solid #e7c98f", borderRadius: 10 }}>
                <span style={{ flex: "none", marginTop: 1, color: "#9a6a14" }}><Icon name="bank" size={15} color="#9a6a14" /></span>
                <span style={{ fontFamily: "var(--f-display)", fontSize: 12.5, color: "#7a5410", lineHeight: 1.45 }}>Select a checking or savings account to fund Yoshi.</span>
              </div>
            )}
          </div>
          <div style={{ flex: "none", padding: "12px 22px 26px" }}>
            <PBtn disabled={sel.size === 0} onClick={finish}>{`Link ${sel.size} account${sel.size === 1 ? "" : "s"}`}</PBtn>
            <div style={{ display: "flex", alignItems: "center", justifyContent: "center", gap: 6, marginTop: 14, color: "#9a9ea6" }}>
              <Icon name="shield" size={13} color="#9a9ea6" />
              <span style={{ fontFamily: "var(--f-display)", fontSize: 11, fontWeight: 600 }}>Secured by Plaid</span>
            </div>
          </div>
        </>
      )}
    </div>
  );
};

/* =============================================================
   08 · CONNECT YOUR BANK — link once through Plaid; it pulls every
   account at that institution. Pick the one that funds Yoshi (read/write);
   the rest ride along read-only. The more you connect, the more Yoshi sees.
   ============================================================= */
const FUND_PRESETS = [250, 1000, 5000, 10000];
const FUND_PRESET_RATIOS = [0, 1 / 3, 2 / 3, 1];

const fundingPresetStepFor = (cap) => {
  if (cap <= 500) return 1;
  if (cap <= 1000) return 10;
  if (cap <= 5000) return 50;
  return 100;
};

const fundingPresetsFor = (balance) => {
  const cap = Math.floor(Math.max(0, balance || 0));
  if (!cap) return FUND_PRESETS;
  if (cap >= 5000) return [250, 500, 1000, 5000];
  const maxPreset = Math.min(cap, 5000);
  const floor = Math.min(cap, cap <= 250 ? 100 : 250);
  const span = maxPreset - floor;
  const step = fundingPresetStepFor(maxPreset);
  return FUND_PRESET_RATIOS.map((ratio, i) => {
    if (i === 0) return floor;
    if (i === FUND_PRESET_RATIOS.length - 1) return maxPreset;
    const raw = floor + span * ratio;
    return Math.min(maxPreset, Math.max(floor, Math.round(raw / step) * step));
  });
};

const fundingPresetLabel = (amount) => {
  if (amount >= 1000) {
    const k = amount / 1000;
    return `$${k.toFixed(k >= 10 ? 1 : 1).replace(/\.0$/, "")}k`;
  }
  return `$${amount.toLocaleString("en-US")}`;
};

/* What Yoshi can do once it can SEE a given institution — the concrete
   payoff for connecting more, surfaced live as accounts come in. */
const INSIGHTS = {
  amex:     { tag: "Pay down your card", find: "Your Amex balance is accruing interest at 21.99% APR. Yoshi can clear it from cash before it's due.", value: "Stops interest", w: 95 },
  schwab:   { tag: "Put idle cash to work", find: "Uninvested cash is sitting in your Schwab brokerage. Yoshi can invest it on a schedule.", value: "+$1,240 / yr", w: 82 },
  fidelity: { tag: "Fix portfolio drift", find: "Your Fidelity mix has drifted from target after the run-up. Yoshi can propose a rebalance.", value: "Back on target", w: 78 },
  chase:    { tag: "Sweep idle cash", find: "Cash is sitting in Chase earning almost nothing. Yoshi can sweep it to 4.8% APY.", value: "+$402 / yr", w: 70 },
  bofa:     { tag: "Sweep idle cash", find: "Idle cash in Bank of America could earn 4.8% instead of sitting still.", value: "+$360 / yr", w: 68 },
  coinbase: { tag: "One net worth", find: "Your Coinbase crypto now rolls into a single balance Yoshi watches with everything else.", value: "Tracked", w: 45 },
  wells:    { tag: "Catch recurring fees", find: "With Wells Fargo visible, Yoshi can flag recurring fees and forgotten subscriptions.", value: "Watching", w: 35 },
  capone:   { tag: "Catch recurring fees", find: "Capital One spending is now visible. Yoshi spots fees and duplicate subscriptions.", value: "Watching", w: 34 },
};

const isDepository = (a) => a.type === "Checking" || a.type === "Savings";
const acctLabel = (a) => `${a.inst} ${a.type} · ${a.mask}`;
const sameAcct = (a, b) => !!(a && b && a.instId === b.instId && a.mask === b.mask);

/* ---- Connected account row ---- */
const ConnectedRow = ({ a, selected, onSelect, accent }) => (
  <div className="yo-enter" style={{ display: "flex", alignItems: "center", gap: 13, padding: "13px 14px", background: "var(--bg-card)", border: `1px solid ${accent ? "var(--accent)" : "var(--rule-2)"}`, borderRadius: 12 }}>
    <span style={{ width: 34, height: 34, flex: "none", borderRadius: 8, background: a.tint, display: "grid", placeItems: "center", color: "#fff", fontFamily: "var(--f-display)", fontSize: 15, fontWeight: 700 }}>{a.inst[0]}</span>
    <div style={{ flex: 1, minWidth: 0 }}>
      <div style={{ fontFamily: "var(--f-display)", fontSize: 14, fontWeight: 600 }}>{a.inst} {a.type}</div>
      <div style={{ fontFamily: "var(--f-mono)", fontSize: 10.5, color: "var(--ink-3)", letterSpacing: "0.04em", marginTop: 2 }}>{a.mask}</div>
    </div>
    {onSelect && (
      <button onClick={onSelect} style={{ background: "none", border: "none", padding: 4, cursor: "pointer", color: selected ? "var(--accent)" : "var(--ink-3)" }}>
        <Icon name="check" size={16} stroke={selected ? 2.4 : 1.5} color={selected ? "var(--accent)" : "var(--rule-2)"} />
      </button>
    )}
    {!onSelect && a.type !== "Checking" && a.type !== "Savings" && (
      <span style={{ display: "inline-flex", alignItems: "center", gap: 4 }}>
        <Icon name="eye" size={12} color="var(--ink-3)" />
      </span>
    )}
    {!onSelect && (a.type === "Checking" || a.type === "Savings") && (
      <span style={{ fontFamily: "var(--f-mono)", fontSize: 13, fontWeight: 600, color: "var(--ink-2)" }}>${Math.abs(a.bal).toLocaleString("en-US")}</span>
    )}
  </div>
);

const Funding = ({ funding, setFunding, externals, setExternals, onNext, onLinkedNext, onSkipToAgent }) => {
  const [plaid, setPlaid]           = useState(false);
  const [attempts, setAttempts]     = useState(0);   // how many times Plaid was opened
  const [plaidFailed, setPlaidFailed] = useState(false); // last attempt failed/exited

  const depAccts  = externals.filter(isDepository);
  const hasBank   = depAccts.length > 0;
  const hasInvest = externals.some((a) => a.type === "Brokerage" || a.type === "Crypto");
  const hasAny    = externals.length > 0;

  // state 1: bank linked → Next goes to funding page
  // state 2: invest-only → Next goes to funding page (will prompt bank link there)
  // state 3: failed/exited → Next skips to agent (no retry gating)
  const canProceed = hasAny || plaidFailed;
  const skipToAgent = !hasAny && plaidFailed;

  const onLinked = (accts) => {
    const next = [...externals];
    accts.forEach((a) => { if (!next.some((x) => sameAcct(x, a))) next.push(a); });
    setExternals(next);
    if (!funding) { const dep = next.find(isDepository); if (dep) setFunding(dep); }
    setPlaid(false);
    setPlaidFailed(false);
    onLinkedNext && onLinkedNext();
  };

  const onPlaidClose = () => {
    setPlaid(false);
    setPlaidFailed(true);
  };

  const openPlaid = () => {
    setAttempts((n) => n + 1);
    setPlaid(true);
  };

  // idle state: nothing linked yet, no failure
  const showIdle = !hasAny && !plaidFailed;
  // failure state: exited/errored, haven't succeeded
  const showRetry = !hasAny && plaidFailed;

  return (
    <Screen>
      <Body>
        <H>Connect your<Brk /><Accent>accounts.</Accent></H>
        <Sub>Link securely through Plaid to power Yoshi. The more accounts you connect, the more Yoshi can see and do.</Sub>

        {/* ---- IDLE: nothing linked yet ---- */}
        {showIdle && (
          <>
            <button className="press" onClick={openPlaid} style={{ width: "100%", display: "flex", alignItems: "center", gap: 13, marginTop: 18, padding: "16px 15px", background: "var(--bg-card)", border: "1px dashed var(--rule-2)", borderRadius: 12, cursor: "pointer", textAlign: "left" }}>
              <span style={{ flex: "none", color: "var(--accent)" }}><Icon name="bank" size={24} color="var(--accent)" /></span>
              <span style={{ flex: 1 }}>
                <span style={{ display: "block", fontFamily: "var(--f-display)", fontSize: 15, fontWeight: 600 }}>Link accounts</span>
              </span>
              <Icon name="arrow" size={18} color="var(--ink-3)" />
            </button>
            <Disclosure>Connections run through Plaid. Yoshi never sees your password, and every move still needs your approval.</Disclosure>
          </>
        )}

        {/* ---- RETRY: Plaid failed or exited ---- */}
        {showRetry && (
          <>
            <div style={{ marginTop: 18, padding: "13px 14px", background: "color-mix(in srgb, var(--accent) 14%, var(--bg-card))", border: "1px solid var(--accent)", borderRadius: 12 }}>
              <div style={{ display: "flex", alignItems: "flex-start", gap: 9 }}>
                <span style={{ flex: "none", marginTop: 1, color: "var(--accent)" }}><Icon name="bank" size={16} color="var(--accent)" /></span>
                <div style={{ flex: 1, fontFamily: "var(--f-display)", fontSize: 13.5, fontWeight: 600, color: "var(--ink)", lineHeight: 1.45 }}>Connection didn't complete. That's okay, try again below.</div>
              </div>
            </div>
            <button className="press" onClick={openPlaid} style={{ width: "100%", display: "flex", alignItems: "center", gap: 13, marginTop: 10, padding: "16px 15px", background: "var(--bg-card)", border: "1px dashed var(--rule-2)", borderRadius: 12, cursor: "pointer", textAlign: "left" }}>
              <span style={{ flex: "none", color: "var(--accent)" }}><Icon name="bank" size={24} color="var(--accent)" /></span>
              <span style={{ flex: 1 }}>
                <span style={{ display: "block", fontFamily: "var(--f-display)", fontSize: 15, fontWeight: 600 }}>Link accounts</span>
              </span>
              <Icon name="arrow" size={18} color="var(--ink-3)" />
            </button>
            <Disclosure>You can always connect accounts later from the Accounts tab.</Disclosure>
          </>
        )}

        {/* ---- STATE 1 + 2: Accounts linked ---- */}
        {hasAny && (
          <>
            {/* All linked accounts — bank, brokerage, crypto, side by side */}
            <SubHead>Connected accounts</SubHead>
            <div style={{ display: "grid", gap: 9 }}>
              {externals.map((a, i) => (
                <ConnectedRow key={i} a={a} accent={isDepository(a) && sameAcct(a, funding)} selected={sameAcct(a, funding)} />
              ))}
            </div>

            {/* No bank — callout */}
            {!hasBank && (
              <div style={{ marginTop: 18, padding: "13px 14px", background: "color-mix(in srgb, var(--accent) 14%, var(--bg-card))", border: "1px solid var(--accent)", borderRadius: 12 }}>
                <div style={{ display: "flex", alignItems: "flex-start", gap: 9 }}>
                  <span style={{ flex: "none", marginTop: 1, color: "var(--accent)" }}><Icon name="bank" size={16} color="var(--accent)" /></span>
                  <div style={{ flex: 1, fontFamily: "var(--f-display)", fontSize: 13.5, fontWeight: 600, color: "var(--ink)" }}>You'll need to add a checking or savings account to fund Yoshi.</div>
                </div>
              </div>
            )}
          </>
        )}
      </Body>
      <Dock>
        {hasAny ? (
          <Btn full onClick={onNext}>Continue <Icon name="arrow" size={15} color="var(--accent-ink)" /></Btn>
        ) : plaidFailed ? (
          <SkipLink onClick={onSkipToAgent}>Skip for now</SkipLink>
        ) : null}
      </Dock>
      {plaid && <PlaidLink mode="readonly" requireFunding={!funding} onClose={onPlaidClose} onLinked={onLinked} />}
    </Screen>
  );
};

/* =============================================================
   09 · PUT YOSHI TO WORK — fund the account so Yoshi has something
   to work with. Optional; skip and fund later.
   ============================================================= */
const FundDeposit = ({ funding, setFunding, externals = [], setExternals, deposit, setDeposit, onNext, onSkip }) => {
  const [amt, setAmt] = useState(deposit || 0);
  const [other, setOther] = useState(false);
  const [customStr, setCustomStr] = useState("");
  const [confirming, setConfirming] = useState(false);
  const [confirmed, setConfirmed] = useState(false);
  const [pickerOpen, setPickerOpen] = useState(false);
  const [plaid, setPlaid] = useState(false);
  const [fundingMethod, setFundingMethod] = useState(funding ? "bank" : "");
  const web = usePlatform() === "web";

  const banks = externals.filter(isDepository);
  const hasMultipleBanks = banks.length > 1;
  const availableBalance = Math.max(0, funding?.bal || 0);
  const presetAmounts = fundingPresetsFor(fundingMethod === "bank" && funding ? availableBalance : 5000);
  const overAvailable = fundingMethod === "bank" && funding && amt > availableBalance;
  const fundingMethodCta = amt <= 0
    ? "Choose an amount"
    : !fundingMethod ? "Choose a funding method"
    : fundingMethod === "applePay" ? `Pay ${usd(amt)} with Apple Pay`
    : !funding ? "Link bank account"
    : confirmed ? "Confirmed"
    : "Confirm with passkey";

  useEffect(() => {
    if (fundingMethod === "bank" && funding && amt > availableBalance) {
      setAmt(0);
      setOther(false);
      setCustomStr("");
    }
  }, [fundingMethod, funding, availableBalance]);

  const onLinked = (accts) => {
    const next = [...externals];
    accts.forEach((a) => { if (!next.some((x) => sameAcct(x, a))) next.push(a); });
    setExternals(next);
    if (!funding) { const dep = next.find(isDepository); if (dep) setFunding(dep); }
    setPlaid(false);
  };

  const handleNext = () => {
    if (amt <= 0 || overAvailable || !fundingMethod) return;
    if (fundingMethod === "applePay") { setDeposit(amt); onNext(); return; }
    if (!funding) { setPlaid(true); return; }
    if (!confirmed) { setConfirming(true); return; }
    setDeposit(amt); onNext();
  };

  const onPasskeyConfirm = () => {
    setConfirming(false);
    setConfirmed(true);
    setTimeout(() => { setDeposit(amt); onNext(); }, 400);
  };
  return (
    <Screen>
      <Body>
        <H>Put Yoshi<Brk />to <Accent>work.</Accent></H>
        <Sub>Move money into your Yoshi account so it has something to work with. You can skip and fund anytime later.</Sub>

        <SubHead>Amount <span style={{ fontWeight: 500, letterSpacing: 0, textTransform: "none", color: "var(--ink-3)" }}>· optional</span></SubHead>
        <div style={{ display: "grid", gridTemplateColumns: "repeat(5, 1fr)", gap: 7 }}>
          {presetAmounts.map((p, i) => {
            const on = !other && amt === p;
            return (
              <button key={`${i}-${p}`} className="press" onClick={() => { setOther(false); setAmt(on ? 0 : p); }} style={{ padding: "13px 2px", cursor: "pointer", borderRadius: 10, background: on ? "color-mix(in srgb, var(--accent) 12%, var(--bg-card))" : "var(--bg-2)", border: `1px solid ${on ? "var(--accent)" : "var(--rule)"}`, fontFamily: "var(--f-display)", fontSize: 12.5, fontWeight: 700, color: "var(--ink)" }}>
                {fundingPresetLabel(p)}
              </button>
            );
          })}
          <button className="press" onClick={() => { setOther(true); setAmt(customStr ? parseInt(customStr, 10) : 0); }} style={{ padding: "13px 2px", cursor: "pointer", borderRadius: 10, background: other ? "color-mix(in srgb, var(--accent) 12%, var(--bg-card))" : "var(--bg-2)", border: `1px solid ${other ? "var(--accent)" : "var(--rule)"}`, fontFamily: "var(--f-display)", fontSize: 12.5, fontWeight: 700, color: "var(--ink)" }}>
            Other
          </button>
        </div>
        {other && (
          <div className="yo-enter" style={{ marginTop: 9 }}>
            <Field prefix="$" inputMode="numeric" autoFocus placeholder="Enter an amount"
              value={customStr ? parseInt(customStr, 10).toLocaleString("en-US") : ""}
              onChange={(v) => { const d = v.replace(/[^0-9]/g, ""); setCustomStr(d); setAmt(d ? parseInt(d, 10) : 0); }} />
            {overAvailable && (
              <div style={{ marginTop: 7, fontFamily: "var(--f-display)", fontSize: 11.5, color: "var(--signal-neg)" }}>
                Amount can't be more than {usd(availableBalance)}.
              </div>
            )}
          </div>
        )}

        <SubHead>Funding method</SubHead>
        <div style={{ display: "grid", gap: 9 }}>
          {funding ? (
            <div>
              <button
                type="button"
                className="press"
                onClick={() => {
                  setFundingMethod("bank");
                  if (hasMultipleBanks) setPickerOpen((o) => fundingMethod === "bank" ? !o : true);
                }}
                style={{
                  width: "100%", display: "flex", alignItems: "center", gap: 12,
                  padding: "13px 14px", background: fundingMethod === "bank" ? "color-mix(in srgb, var(--accent) 10%, var(--bg-card))" : "var(--bg-card)",
                  border: `1px solid ${fundingMethod === "bank" ? "var(--accent)" : "var(--rule-2)"}`,
                  borderRadius: pickerOpen && fundingMethod === "bank" ? "12px 12px 0 0" : 12,
                  borderBottomColor: pickerOpen && fundingMethod === "bank" ? "transparent" : (fundingMethod === "bank" ? "var(--accent)" : "var(--rule-2)"),
                  cursor: "pointer",
                  textAlign: "left",
                }}>
                <span style={{ width: 34, height: 34, flex: "none", borderRadius: 8, background: funding.tint, display: "grid", placeItems: "center", color: "#fff", fontFamily: "var(--f-display)", fontSize: 15, fontWeight: 700 }}>{funding.inst[0]}</span>
                <div style={{ flex: 1, minWidth: 0 }}>
                  <div style={{ fontFamily: "var(--f-display)", fontSize: 14, fontWeight: 700 }}>{funding.inst} {funding.type} <span style={{ fontFamily: "var(--f-mono)", fontSize: 11, color: "var(--ink-3)", fontWeight: 400 }}>{funding.mask}</span></div>
                  <div style={{ fontFamily: "var(--f-display)", fontSize: 12.2, color: "var(--ink-3)", marginTop: 2 }}>Available balance {usd(funding.bal)}</div>
                </div>
                <div style={{ flex: "none", display: "grid", justifyItems: "end", gap: 5 }}>
                  <span style={{ display: "inline-flex", alignItems: "center", gap: 3, fontFamily: "var(--f-mono)", fontSize: 9.5, fontWeight: 600, letterSpacing: "0.08em", textTransform: "uppercase", color: "var(--accent)", padding: "3px 8px 3px 6px", borderRadius: 999, background: "color-mix(in srgb, var(--accent) 12%, var(--bg-card))", border: "1px solid color-mix(in srgb, var(--accent) 40%, transparent)" }}><Icon name="bolt" size={11} stroke={1.8} color="var(--accent)" />Instant</span>
                  {hasMultipleBanks && <Icon name={pickerOpen && fundingMethod === "bank" ? "up" : "down"} size={15} color="var(--ink-3)" />}
                  {!hasMultipleBanks && fundingMethod === "bank" && <Icon name="check" size={16} stroke={2.4} color="var(--accent)" />}
                </div>
              </button>

              {pickerOpen && fundingMethod === "bank" && hasMultipleBanks && (
                <div style={{ border: "1px solid var(--accent)", borderTop: "none", borderRadius: "0 0 12px 12px", background: "var(--bg-card)", overflow: "hidden" }}>
                  {banks.filter((b) => !sameAcct(b, funding)).map((a, i) => (
                    <button key={i} type="button" onClick={() => { setFunding(a); setFundingMethod("bank"); setPickerOpen(false); }}
                      style={{ width: "100%", display: "flex", alignItems: "center", gap: 12, padding: "12px 14px", background: "transparent", border: "none", borderTop: "1px solid var(--rule)", cursor: "pointer", textAlign: "left" }}>
                      <span style={{ width: 30, height: 30, flex: "none", borderRadius: 8, background: a.tint, display: "grid", placeItems: "center", color: "#fff", fontFamily: "var(--f-display)", fontSize: 13, fontWeight: 700 }}>{a.inst[0]}</span>
                      <div style={{ flex: 1, minWidth: 0 }}>
                        <div style={{ fontFamily: "var(--f-display)", fontSize: 13.5, fontWeight: 600 }}>{a.inst} {a.type} <span style={{ fontFamily: "var(--f-mono)", fontSize: 10.5, color: "var(--ink-3)", fontWeight: 400 }}>{a.mask}</span></div>
                        <div style={{ fontFamily: "var(--f-display)", fontSize: 11.5, color: "var(--ink-3)", marginTop: 2 }}>Available balance {usd(a.bal)}</div>
                      </div>
                    </button>
                  ))}
                </div>
              )}
            </div>
          ) : (
            <button
              type="button"
              className="press"
              onClick={() => { setFundingMethod("bank"); setPlaid(true); }}
              style={{
                width: "100%", display: "flex", alignItems: "center", gap: 13,
                padding: "14px 15px", background: fundingMethod === "bank" ? "color-mix(in srgb, var(--accent) 10%, var(--bg-card))" : "var(--bg-card)",
                border: `1px dashed ${fundingMethod === "bank" ? "var(--accent)" : "var(--rule-2)"}`,
                borderRadius: 12, cursor: "pointer", textAlign: "left",
              }}>
              <span style={{ flex: "none", color: "var(--accent)" }}><Icon name="bank" size={22} color="var(--accent)" /></span>
              <span style={{ flex: 1, minWidth: 0 }}>
                <span style={{ display: "block", fontFamily: "var(--f-display)", fontSize: 14.5, fontWeight: 700 }}>Link bank account</span>
                <span style={{ display: "block", fontFamily: "var(--f-display)", fontSize: 12.2, color: "var(--ink-3)", marginTop: 2 }}>Use checking or savings instead</span>
              </span>
              <Icon name="arrow" size={18} color="var(--ink-3)" />
            </button>
          )}

          <button
            type="button"
            className="press"
            onClick={() => { setFundingMethod("applePay"); setPickerOpen(false); }}
            style={{
              width: "100%", display: "flex", alignItems: "center", gap: 12,
              padding: "14px 15px", background: fundingMethod === "applePay" ? "color-mix(in srgb, var(--accent) 10%, var(--bg-card))" : "var(--bg-card)",
              border: `1px solid ${fundingMethod === "applePay" ? "var(--accent)" : "var(--rule-2)"}`,
              borderRadius: 12, cursor: "pointer", textAlign: "left",
            }}>
            <span style={{ width: 34, height: 34, flex: "none", borderRadius: 9, background: "var(--bg-2)", border: "1px solid var(--rule-2)", display: "grid", placeItems: "center", color: "var(--accent)" }}>
              <Icon name="card" size={18} color="var(--accent)" />
            </span>
            <span style={{ flex: 1, minWidth: 0 }}>
              <span style={{ display: "block", fontFamily: "var(--f-display)", fontSize: 14.5, fontWeight: 700, color: "var(--ink)" }}>Apple Pay</span>
              <span style={{ display: "block", fontFamily: "var(--f-display)", fontSize: 12.2, lineHeight: 1.35, color: "var(--ink-3)", marginTop: 2 }}>Fund with a card in your wallet</span>
            </span>
            {fundingMethod === "applePay" && <Icon name="check" size={16} stroke={2.4} color="var(--accent)" />}
          </button>
        </div>

        <Disclosure>
          <span style={{ display: "grid", gap: 2 }}>
            <span>Deposits in your Yoshi account are FDIC-insured through Column N.A., Member FDIC.</span>
            <a href="/cash-account-disclosures/" target="_blank" rel="noopener noreferrer" style={{ color: "inherit", textDecoration: "underline", textUnderlineOffset: 2, justifySelf: "start" }}>Authorization terms and conditions</a>
          </span>
        </Disclosure>

      </Body>
      <Dock>
        <Btn full disabled={amt <= 0 || overAvailable || !fundingMethod} onClick={handleNext}>
          {confirmed ? <><Icon name="check" size={18} color="var(--accent-ink)" /> Confirmed</> : <>{fundingMethodCta}{fundingMethod === "bank" && funding && <Icon name="shield" size={18} color={(amt <= 0 || overAvailable) ? "var(--ink-3)" : "var(--accent-ink)"} />}</>}
        </Btn>
        <SkipLink onClick={onSkip}>Skip for now</SkipLink>
      </Dock>

      {/* Passkey confirm — centered modal on web, bottom sheet on mobile */}
      {confirming && (
        <>
          <div onClick={() => setConfirming(false)} style={{ position: "absolute", inset: 0, zIndex: 50, background: "rgba(0,0,0,0.44)", backdropFilter: "blur(4px)", WebkitBackdropFilter: "blur(4px)" }} />
          {web ? (
            <div style={{ position: "absolute", inset: 0, zIndex: 51, display: "flex", alignItems: "center", justifyContent: "center", padding: 28 }}>
              <div className="yo-enter" style={{ width: "100%", maxWidth: 360, background: "var(--bg-card)", border: "1px solid var(--rule-2)", borderRadius: 16, padding: "30px 28px 26px", boxShadow: "0 16px 40px -16px rgba(0,0,0,0.34)" }}>
                <div style={{ display: "flex", flexDirection: "column", alignItems: "center", gap: 10, marginBottom: 24 }}>
                  <span style={{ width: 52, height: 52, borderRadius: 14, background: "var(--bg-2)", border: "1px solid var(--rule-2)", display: "grid", placeItems: "center" }}>
                    <Icon name="shield" size={26} color="var(--accent)" />
                  </span>
                  <div style={{ textAlign: "center" }}>
                    <div style={{ fontFamily: "var(--f-display)", fontSize: 17, fontWeight: 700, letterSpacing: "-0.02em" }}>Confirm with passkey</div>
                    <div style={{ fontFamily: "var(--f-display)", fontSize: 13, color: "var(--ink-3)", marginTop: 5, lineHeight: 1.45 }}>
                      Authorise a transfer of <strong>${amt.toLocaleString("en-US")}</strong> from your {funding ? `${funding.inst} ${funding.type}` : "funding source"}.
                    </div>
                  </div>
                </div>
                <div style={{ display: "grid", gap: 9 }}>
                  <Btn full onClick={onPasskeyConfirm}>
                    <Icon name="shield" size={16} color="var(--accent-ink)" /> Use passkey
                  </Btn>
                  <button onClick={() => setConfirming(false)} style={{ background: "none", border: "none", fontFamily: "var(--f-display)", fontSize: 14, color: "var(--ink-3)", cursor: "pointer", padding: "8px 0" }}>Cancel</button>
                </div>
              </div>
            </div>
          ) : (
            <div style={{ position: "absolute", bottom: 0, left: 0, right: 0, zIndex: 51, background: "var(--bg-card)", borderRadius: "20px 20px 0 0", padding: "20px 24px 40px", boxShadow: "0 -8px 32px rgba(0,0,0,0.18)" }}>
              <div style={{ width: 36, height: 4, borderRadius: 999, background: "var(--rule-2)", margin: "0 auto 22px" }} />
              <div style={{ display: "flex", flexDirection: "column", alignItems: "center", gap: 10, marginBottom: 24 }}>
                <span style={{ width: 52, height: 52, borderRadius: 14, background: "var(--bg-2)", border: "1px solid var(--rule-2)", display: "grid", placeItems: "center" }}>
                  <Icon name="shield" size={26} color="var(--accent)" />
                </span>
                <div style={{ textAlign: "center" }}>
                  <div style={{ fontFamily: "var(--f-display)", fontSize: 17, fontWeight: 700, letterSpacing: "-0.02em" }}>Confirm with passkey</div>
                  <div style={{ fontFamily: "var(--f-display)", fontSize: 13, color: "var(--ink-3)", marginTop: 5, lineHeight: 1.45 }}>
                    Authorise a transfer of <strong>${amt.toLocaleString("en-US")}</strong> from your {funding ? `${funding.inst} ${funding.type}` : "funding source"}.
                  </div>
                </div>
              </div>
              <div style={{ display: "grid", gap: 9 }}>
                <Btn full onClick={onPasskeyConfirm}>
                  <Icon name="shield" size={16} color="var(--accent-ink)" /> Use passkey
                </Btn>
                <button onClick={() => setConfirming(false)} style={{ background: "none", border: "none", fontFamily: "var(--f-display)", fontSize: 14, color: "var(--ink-3)", cursor: "pointer", padding: "8px 0" }}>Cancel</button>
              </div>
            </div>
          )}
        </>
      )}
      {plaid && <PlaidLink mode="readonly" requireFunding onClose={() => setPlaid(false)} onLinked={onLinked} />}
    </Screen>
  );
};

/* =============================================================
   10 · AGENT — connect an assistant (kept as-is)
   ============================================================= */
const AGENTS = [
  /* apps you authorize over OAuth */
  { id: "chatgpt",    name: "ChatGPT",           icon: "message",  kind: "oauth" },
  { id: "claude",     name: "Claude",            icon: "robot",    kind: "oauth" },
  { id: "openclaw",   name: "OpenClaw",          icon: "bolt",     kind: "copy" },
  /* Yoshi's own integration methods */
  { id: "mcp",        name: "Yoshi MCP",         icon: "connect",  kind: "copy" },
  { id: "build",      name: "Build with Yoshi",  icon: "easel",    kind: "copy" },
  { id: "sdks",       name: "Yoshi SDKs",        icon: "terminal", kind: "sdk" },
];

const AGENT_SETUP = {
  mcp:      "yoshi mcp add --key ys_demo_8f3ac2d1",
  build:    "npm i @yoshi/sdk && yoshi init",
  openclaw: "openclaw connect yoshi --key ys_demo_8f3ac2d1",
};

/* one marketplace card — icon, name, and a state-driven footer action */
const AgentCard = ({ a, state, open, onClick }) => {
  const web = usePlatform() === "web";
  const active = state === "activated" || state === "live" || state === "connected";
  const statusLabel = state === "live" ? "Live" : state === "connected" ? "Connected" : "Activated";
  const btnLabel = state === "copy" ? "Copy setup" : "Authorize";
  return (
    <button key={a.id} className="press" onClick={onClick} style={{ position: "relative", textAlign: "left", cursor: "pointer", padding: web ? "12px 13px 11px" : "16px 15px 14px", borderRadius: 12, background: "var(--bg-card)", border: `1px solid ${active || open ? "var(--accent)" : "var(--rule)"}`, color: "var(--ink)", display: "flex", flexDirection: "column", gap: web ? 8 : 11, minHeight: web ? 116 : 152, overflow: "hidden" }}>
      {active && <span style={{ position: "absolute", top: 0, left: 0, right: 0, height: 2, background: "var(--accent)" }} />}
      <span style={{ width: web ? 32 : 38, height: web ? 32 : 38, flex: "none", border: `1px solid ${active ? "var(--accent)" : "var(--rule-2)"}`, borderRadius: 9, display: "grid", placeItems: "center", color: active ? "var(--accent)" : "var(--ink-2)" }}>
        <Icon name={a.icon} size={web ? 17 : 19} stroke={1.6} color={active ? "var(--accent)" : "var(--ink-2)"} />
      </span>
      <div style={{ fontFamily: "var(--f-display)", fontSize: web ? 14.5 : 15.5, fontWeight: 700, letterSpacing: "-0.015em", textWrap: "pretty", lineHeight: 1.2 }}>{a.name}</div>
      <div style={{ marginTop: "auto", width: "100%" }}>
        {active ? (
          <span style={{ display: "inline-flex", alignItems: "center", gap: 7, fontFamily: "var(--f-display)", fontSize: 12.5, fontWeight: 600, color: "var(--accent)" }}>
            <span style={{ width: 6, height: 6, borderRadius: 999, background: "var(--accent)" }} /> {statusLabel}
          </span>
        ) : state === "sdk" ? (
          <span style={{ display: "flex", alignItems: "center", justifyContent: "space-between", fontFamily: "var(--f-display)", fontSize: 13, fontWeight: 600, color: "var(--accent)" }}>
            View SDKs <Icon name="back" size={14} color="var(--accent)" style={{ transform: "scaleX(-1)" }} />
          </span>
        ) : (
          <span style={{ display: "block", textAlign: "center", padding: "9px 0", borderRadius: 8, background: "var(--bg-2)", border: "1px solid var(--rule-2)", fontFamily: "var(--f-display)", fontSize: 13, fontWeight: 600, color: "var(--ink)" }}>{btnLabel}</span>
        )}
      </div>
    </button>
  );
};

const Agent = ({ agents = [], setAgents, onNext, onSkip }) => {
  const [redirecting, setRedirecting] = useState(null); // OAuth agent id mid-authorize
  const [setupId, setSetupId] = useState(null);         // copy-agent id whose command is shown
  const [copied, setCopied] = useState(false);
  const web = usePlatform() === "web";
  const isConnected = (id) => agents.includes(id);
  const markConnected = (id) => setAgents((prev) => (prev.includes(id) ? prev : [...prev, id]));
  const cardState = (a) => {
    if (a.kind === "sdk") return "sdk";
    if (a.kind === "copy") return isConnected(a.id) ? "connected" : "copy";
    return isConnected(a.id) ? "activated" : "authorize";
  };

  const connect = (a) => {
    if (a.kind === "sdk") return;
    if (isConnected(a.id)) {                              // tap connected → disconnect
      setAgents(agents.filter((x) => x !== a.id));
      if (setupId === a.id) setSetupId(null);
      return;
    }
    if (a.kind === "copy") {                              // MCP / CLI → reveal command to run
      setCopied(false);
      setSetupId((cur) => (cur === a.id ? null : a.id));
      return;
    }
    setRedirecting(a.id);                                 // OAuth agent → leave & return
    setTimeout(() => { markConnected(a.id); setRedirecting(null); }, 1700);
  };

  const doCopy = () => {
    try { navigator.clipboard && navigator.clipboard.writeText(AGENT_SETUP[setupId] || ""); } catch (e) {}
    setCopied(true);
    markConnected(setupId);
  };

  const redirectAgent = AGENTS.find((a) => a.id === redirecting);
  const setupAgent = AGENTS.find((a) => a.id === setupId);
  const count = agents.length;

  return (
  <Screen style={{ position: "relative" }}>
    <Body>
      <H>Bring your AI<Brk />into the <Accent>loop.</Accent></H>
      <Sub>Connect the assistants you already use and they can draft moves right in your chats. You still approve every one.</Sub>

      <div style={{ display: "grid", gridTemplateColumns: web ? "repeat(3, 1fr)" : "repeat(2, 1fr)", gap: 11, marginTop: 20 }}>
        {AGENTS.map((a) => {
          const st = cardState(a);
          const open = setupId === a.id && st === "copy";
          return <AgentCard key={a.id} a={a} state={st} open={open} onClick={() => connect(a)} />;
        })}
      </div>

      {/* CLI agents — copy the command, run it in your own agent framework to connect */}
      {setupAgent && !isConnected(setupAgent.id) && (
        <div className="yo-enter" style={{ marginTop: 12 }}>
          <div style={{ display: "flex", gap: 10, alignItems: "center", padding: "12px 13px", background: "var(--terminal-fill)", borderRadius: 12 }}>
            <span style={{ flex: "none", color: "var(--terminal-ink)", display: "flex" }}><Icon name="terminal" size={16} color="var(--terminal-ink)" /></span>
            <code style={{ flex: 1, minWidth: 0, fontFamily: "var(--f-mono, ui-monospace, monospace)", fontSize: 11.5, color: "var(--terminal-ink)", whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis" }}>{AGENT_SETUP[setupAgent.id]}</code>
            <button className="press" onClick={doCopy} style={{ flex: "none", display: "inline-flex", alignItems: "center", gap: 5, background: "var(--accent)", color: "var(--accent-ink)", border: "none", borderRadius: 8, padding: "7px 11px", fontFamily: "var(--f-display)", fontSize: 12, fontWeight: 700, cursor: "pointer" }}>
              {copied ? <><Icon name="check" size={13} stroke={2.2} color="var(--accent-ink)" /> Copied</> : "Copy"}
            </button>
          </div>
        </div>
      )}

      <div style={{ display: "flex", gap: 9, alignItems: "flex-start", padding: "13px 14px", background: "color-mix(in srgb, var(--accent) 14%, var(--bg-card))", border: "1px solid var(--accent)", borderRadius: 12, marginTop: 18 }}>
        <span style={{ flex: "none", marginTop: 1, color: "var(--accent)" }}><Icon name="shield" size={16} color="var(--accent)" /></span>
        <span style={{ flex: 1, fontFamily: "var(--f-display)", fontSize: 13.5, fontWeight: 600, color: "var(--ink)", lineHeight: 1.45 }}>
          Propose-only access. An agent never holds or moves your money on its own. Revoke any connection anytime.
        </span>
      </div>
    </Body>
    <Dock>
      {count > 0 ? (
        <Btn full onClick={onNext}>Enter Yoshi!</Btn>
      ) : (
        <Btn full onClick={onSkip}>Skip to enter Yoshi</Btn>
      )}
    </Dock>

    {/* OAuth redirect — leave to the agent's app to authorize, then return */}
    {redirectAgent && (
      <>
        <div style={{ position: "absolute", inset: 0, zIndex: 60, background: "color-mix(in srgb, var(--bg) 70%, transparent)", backdropFilter: "blur(8px)", WebkitBackdropFilter: "blur(8px)" }} />
        <div style={{ position: "absolute", inset: 0, zIndex: 61, display: "flex", alignItems: "center", justifyContent: "center", padding: 28 }}>
          <div className="yo-enter" style={{ width: "100%", maxWidth: 280, background: "var(--bg-card)", border: "1px solid var(--rule-2)", borderRadius: 16, padding: "26px 22px", textAlign: "center", boxShadow: "0 16px 40px -16px rgba(0,0,0,0.34)" }}>
            <div style={{ display: "flex", alignItems: "center", justifyContent: "center", gap: 12, marginBottom: 17 }}>
              <span style={{ width: 38, height: 38, flex: "none", border: "1px solid var(--rule-2)", display: "grid", placeItems: "center", fontFamily: "var(--f-display)", fontSize: 17, fontWeight: 700, color: "var(--ink)" }}>Y</span>
              <LiveDot size={7} color="var(--accent)" />
              <span style={{ width: 38, height: 38, flex: "none", border: "1px solid var(--accent)", display: "grid", placeItems: "center", fontFamily: "var(--f-display)", fontSize: 17, fontWeight: 700, color: "var(--accent)" }}>{redirectAgent.name[0]}</span>
            </div>
            <div style={{ fontFamily: "var(--f-display)", fontSize: 16, fontWeight: 700, letterSpacing: "-0.02em" }}>Opening {redirectAgent.name}…</div>
            <div style={{ fontFamily: "var(--f-display)", fontSize: 13, color: "var(--ink-3)", marginTop: 6, lineHeight: 1.45 }}>Authorize Yoshi in {redirectAgent.name}, then you'll come right back here.</div>
          </div>
        </div>
      </>
    )}
  </Screen>
  );
};

/* =============================================================
   11 · DISCLOSURES — the last gate before Yoshi gets to work.
   Institutional register: concede the fine print, lay it out plainly.
   Tapping continue is the acknowledgment; the seam draws as you sign.
   ============================================================= */
const AckRow = ({ label, href, children, last }) => (
  <div style={{ padding: "15px 0", borderBottom: last ? "none" : "1px dashed var(--rule)" }}>
    <div style={{ display: "flex", alignItems: "center", gap: 8 }}>
      <Eyebrow color="var(--accent)" style={{ fontSize: 9.5 }}>{label}</Eyebrow>
      {href && (
        <a href={href} target="_blank" rel="noopener noreferrer" className="press" aria-label={label + " document"} style={{ marginLeft: "auto", flex: "none", display: "inline-flex", color: "var(--ink-3)" }}>
          <Icon name="external" size={14} color="var(--ink-3)" />
        </a>
      )}
    </div>
    <span style={{ display: "block", fontFamily: "var(--f-display)", fontSize: 13.5, color: "var(--ink)", lineHeight: 1.48, marginTop: 5, textWrap: "pretty" }}>{children}</span>
  </div>
);

const CheckMark = ({ checked }) => (
  <span style={{
    width: 19, height: 19, flex: "none", borderRadius: 5, display: "grid", placeItems: "center",
    border: `1px solid ${checked ? "var(--accent)" : "var(--rule-2)"}`,
    background: checked ? "var(--accent)" : "transparent",
    color: "var(--accent-ink)",
    transition: "background 160ms ease, border-color 160ms ease"
  }}>
    {checked && <Icon name="check" size={13} color="var(--accent-ink)" />}
  </span>
);

const AgreementCheckRow = ({ checked, onToggle, label, sub, href, onOpen, first, last }) => {
  const openProps = href
    ? { as: "a", href, target: "_blank", rel: "noopener noreferrer" }
    : {};
  const openControl = onOpen
    ? (
      <button type="button" className="press" onClick={(event) => { event.stopPropagation(); onOpen(); }} aria-label={`${label} agreements`} style={{ border: "none", background: "none", padding: 4, margin: -4, display: "inline-flex", color: "var(--ink-3)", cursor: "pointer" }}>
        <Icon name="external" size={14} color="var(--ink-3)" />
      </button>
    )
    : (
      <a {...openProps} className="press" onClick={(event) => event.stopPropagation()} aria-label={`${label} agreements`} style={{ display: "inline-flex", color: "var(--ink-3)" }}>
        <Icon name="external" size={14} color="var(--ink-3)" />
      </a>
    );
  return (
    <button type="button" className="press" role="checkbox" aria-checked={checked} onClick={onToggle} style={{
      width: "100%", display: "grid", gridTemplateColumns: "auto 1fr auto", gap: 12, alignItems: "center",
      padding: "14px 0", background: "none", border: "none", borderTop: first ? "none" : "1px dashed var(--rule)",
      borderBottom: last ? "none" : undefined, color: "var(--ink)", cursor: "pointer", textAlign: "left"
    }}>
      <CheckMark checked={checked} />
      <span style={{ minWidth: 0 }}>
        <span style={{ display: "block", fontFamily: "var(--f-display)", fontSize: 14.5, fontWeight: 700, letterSpacing: "-0.015em" }}>{label}</span>
        <span style={{ display: "block", fontFamily: "var(--f-display)", fontSize: 11.5, color: "var(--ink-3)", lineHeight: 1.35, marginTop: 3, textWrap: "pretty" }}>{sub}</span>
      </span>
      {openControl}
    </button>
  );
};

const PartnerRow = ({ name, role, member, href, onClick, first }) => {
  const common = {
    textDecoration: "none", width: "100%", display: "grid", gridTemplateColumns: "1fr auto", gap: 12, alignItems: "center",
    padding: "13px 0", background: "none", border: "none", borderTop: `1px ${first ? "solid" : "dashed"} var(--rule)`,
    color: "var(--ink)", cursor: "pointer", textAlign: "left" };
  const body = (
    <>
      <span style={{ minWidth: 0 }}>
        <span style={{ display: "block", fontFamily: "var(--f-display)", fontSize: 14.5, fontWeight: 700, letterSpacing: "-0.015em" }}>{name}</span>
        <span style={{ display: "block", fontFamily: "var(--f-mono)", fontSize: 9, letterSpacing: "0.05em", textTransform: "uppercase", color: "var(--ink-3)", marginTop: 3, whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis" }}>{role} · {member}</span>
      </span>
      <span style={{ display: "inline-flex", alignItems: "center", gap: 5, flex: "none", fontFamily: "var(--f-display)", fontSize: 11.5, fontWeight: 600, color: "var(--ink-2)" }}>
        Agreements <Icon name="external" size={14} color="var(--ink-3)" />
      </span>
    </>
  );
  return onClick
    ? <button type="button" className="press" onClick={onClick} style={common}>{body}</button>
    : <a href={href} target="_blank" rel="noopener noreferrer" className="press" style={common}>{body}</a>;
};

/* The Apex agreements + disclosures, as an in-app push screen reached from the
   brokerage row. Each document opens its PDF; the disclosures live at the foot. */
const APEX_DOCS = [
  ["Customer Account Agreement", "https://storage.googleapis.com/apexclearing-account-agreements-prd-00/SCAA-OBD-20260318-EN.pdf"],
  ["Customer Information Brochure", "https://library.apexfintechsolutions.com/wp-content/uploads/2024/12/Apex-Direct-Customer-Infromation-Brochure.pdf"],
  ["Privacy Policy", "https://library.apexfintechsolutions.com/wp-content/uploads/2025/04/AFBS-Privacy-Policy.pdf"],
  ["Terms of Service", "https://library.apexfintechsolutions.com/wp-content/uploads/2025/04/AFBS-Terms-of-Service-Template.pdf"],
  ["CIP Notice", "https://library.apexfintechsolutions.com/wp-content/uploads/2025/04/FINRA-CIP-Notice.pdf"],
  ["Business Continuity Plan", "https://library.apexfintechsolutions.com/wp-content/uploads/2024/12/Business-Continuity-Plan-Policy-11-08-2024.pdf"],
  ["Fee Sheet", "https://library.apexfintechsolutions.com/wp-content/uploads/2024/12/Apex-Direct-Misc-Services-Fee-Sheet-11.2024.pdf"],
];

const ApexAgreements = ({ onClose }) => {
  const link = { color: "var(--ink-2)", textDecoration: "underline", textUnderlineOffset: 2 };
  const disc = { fontFamily: "var(--f-display)", fontSize: 11.5, color: "var(--ink-3)", lineHeight: 1.58, marginTop: 12, marginBottom: 0, textWrap: "pretty", letterSpacing: "0.003em" };
  return (
    <div style={{ position: "absolute", inset: 0, zIndex: 80, background: "var(--bg)", display: "flex", flexDirection: "column", animation: "sheet-in 320ms cubic-bezier(0.16,1,0.30,1) both" }} data-screen-label="Apex agreements">
      <NavBar title="Apex Clearing Corporation" sub="Brokerage agreements" right={
        <button className="press" onClick={onClose} aria-label="Close" style={{ background: "none", border: "none", padding: 6, margin: "0 -6px", display: "flex", color: "var(--ink)", cursor: "pointer", flex: "none" }}>
          <Icon name="close" size={20} />
        </button>
      } />
      <div className="scroll" style={{ flex: 1, minHeight: 0, padding: "12px 24px 28px" }}>
        <Eyebrow color="var(--ink-2)">Documents</Eyebrow>
        <div style={{ display: "grid", marginTop: 4 }}>
          {APEX_DOCS.map(([name, url], i) => (
            <a key={name} href={url} target="_blank" rel="noopener noreferrer" className="press" style={{
              textDecoration: "none", display: "grid", gridTemplateColumns: "1fr auto", gap: 12, alignItems: "center",
              padding: "14px 0", borderTop: `1px ${i === 0 ? "solid" : "dashed"} var(--rule)`, color: "var(--ink)" }}>
              <span style={{ fontFamily: "var(--f-display)", fontSize: 14, fontWeight: 600, letterSpacing: "-0.01em" }}>{name}</span>
              <Icon name="external" size={15} color="var(--ink-3)" />
            </a>
          ))}
        </div>

        <div style={{ marginTop: 26, paddingTop: 18, borderTop: "1px solid var(--rule-2)" }}>
          <p style={{ ...disc, marginTop: 0 }}>
            Brokerage services are provided by Apex Clearing Corporation, an SEC-registered broker-dealer and member FINRA/SIPC. Learn more about Apex at{" "}
            <a href="https://brokercheck.finra.org/" target="_blank" rel="noopener noreferrer" style={link}>FINRA BrokerCheck</a>.
          </p>
          <p style={disc}>
            Investing in securities involves risks, including the potential loss of principal. Securities investments are not FDIC insured, are not bank guaranteed, and may lose value. Before investing, please carefully review your investment objectives, risk tolerance, charges, and expenses. Yoshi is not owned or operated by Apex Clearing Corporation.
          </p>
          <p style={{ ...disc, display: "flex", alignItems: "center", gap: 7 }}>
            <span>For additional information about SIPC coverage, visit{" "}
              <a href="https://www.sipc.org" target="_blank" rel="noopener noreferrer" style={link}>sipc.org</a>.</span>
          </p>
        </div>
      </div>
    </div>
  );
};

const Disclosures = ({ onNext }) => {
  const [signing, setSigning] = useState(false);
  const [showApex, setShowApex] = useState(false);
  const [checks, setChecks] = useState({ esign: false, column: false, apex: false });
  const toggleCheck = (key) => setChecks((current) => ({ ...current, [key]: !current[key] }));
  const sign = () => { if (signing) return; setSigning(true); setTimeout(() => onNext(), 760); };
  const selectAllAndContinue = () => {
    if (signing) return;
    setChecks({ esign: true, column: true, apex: true });
    sign();
  };
  const link = { color: "var(--ink-2)", textDecoration: "underline", textUnderlineOffset: 2 };

  return (
    <Screen style={{ position: "relative" }}>
      <Body>
        <H>A bit of<Brk />fine <Accent>print.</Accent></H>
        <Sub style={{ maxWidth: "none" }}>Check the boxes below to confirm you've read and accept the agreements.</Sub>

        {/* required acknowledgments — flagged with the 2px seam top-bar */}
        <div style={{ position: "relative", marginTop: 20, background: "var(--bg-card)", border: "1px solid var(--rule-2)", borderRadius: 14, padding: "4px 16px 6px", overflow: "hidden" }}>
          <span style={{ position: "absolute", top: 0, left: 0, right: 0, height: 2, background: "var(--accent)" }} />
          <AgreementCheckRow first checked={checks.esign} onToggle={() => toggleCheck("esign")} label="E-sign" sub="Electronic delivery and signature of your account documents." href="/esign-consent/" />
          <AgreementCheckRow checked={checks.column} onToggle={() => toggleCheck("column")} label="Column N.A." sub="Banking · Member FDIC" href="https://column.com/legal" />
          <AgreementCheckRow last checked={checks.apex} onToggle={() => toggleCheck("apex")} label="Apex Clearing Corporation" sub="Brokerage · Member FINRA/SIPC" onOpen={() => setShowApex(true)} />
        </div>

        {/* the required fine print, in full */}
        <p style={{ fontFamily: "var(--f-display)", fontSize: 10.5, color: "var(--ink-3)", lineHeight: 1.55, marginTop: 22, marginBottom: 4, textWrap: "pretty", letterSpacing: "0.004em" }}>
          Yoshi is a fintech company, not a bank. Cash Account and banking services provided by Column N.A., Member FDIC. FDIC insurance covers the failure of an insured depository institution. Brokerage services are provided by Apex Clearing Corporation, an SEC-registered broker-dealer and member FINRA/SIPC. Learn more about Apex at{" "}
          <a href="https://brokercheck.finra.org/" target="_blank" rel="noopener noreferrer" style={link}>FINRA BrokerCheck</a>.
        </p>
      </Body>
      <Dock>
        {/* the seam draws across at the moment of signing — the brand's approval signature */}
        <div style={{ height: 1, background: "var(--accent)", opacity: 0.6, transformOrigin: "left center", transform: `scaleX(${signing ? 1 : 0})`, transition: "transform 700ms linear" }} />
        <Btn full onClick={selectAllAndContinue} disabled={signing}>
          {signing
            ? <><LiveDot size={6} color="var(--accent-ink)" /> Signing…</>
            : <>Select all &amp; continue <Icon name="arrow" size={15} color="var(--accent-ink)" /></>}
        </Btn>
      </Dock>

      {showApex && <ApexAgreements onClose={() => setShowApex(false)} />}
    </Screen>
  );
};

/* =============================================================
   12 · OFF TO WORK — account creation before external linking.
   ============================================================= */
const OffToWork = ({ accent = "#6c9a5c", onDone }) => {
  const [status, setStatus] = useState("creating");
  useEffect(() => {
    const live = setTimeout(() => setStatus("live"), 2400);
    const done = setTimeout(() => { onDone && onDone(); }, 3800);
    return () => { clearTimeout(live); clearTimeout(done); };
  }, [onDone]);
  const ink = "#f3f1ea", m55 = "rgba(243,241,234,0.58)", m18 = "rgba(243,241,234,0.18)";
  const mark = `url(${(typeof window !== "undefined" && window.__resources && window.__resources.logoBlack) || "assets/logo-mark-black.png"})`;
  const live = status === "live";

  return (
    <Screen style={{ background: "#141310", color: ink }}>
      <div className="scroll" style={{ flex: 1, minHeight: 0, padding: "12px 24px 28px", display: "flex", flexDirection: "column", justifyContent: "center" }}>
        <div style={{ display: "flex", flexDirection: "column", alignItems: "center", textAlign: "center" }}>
          <div className="yo-grow" style={{ width: 60, height: 68, background: accent,
            WebkitMaskImage: mark, maskImage: mark, WebkitMaskSize: "contain", maskSize: "contain",
            WebkitMaskRepeat: "no-repeat", maskRepeat: "no-repeat", WebkitMaskPosition: "center", maskPosition: "center" }} />
          <div className="yo-enter" data-delay="1" style={{ display: "flex", alignItems: "center", justifyContent: "center", gap: 9, minHeight: 18, marginTop: 24 }}>
            {live ? <Icon name="check" size={15} stroke={2.6} color={accent} /> : <LiveDot size={8} color={accent} />}
            <span style={{ fontFamily: "var(--f-display)", fontSize: 10.5, fontWeight: 700, letterSpacing: "0.16em", textTransform: "uppercase", color: accent }}>{live ? "Your accounts are live!" : "Creating your accounts."}</span>
          </div>
          <div className="yo-enter" data-delay="2" style={{ fontFamily: "var(--f-display)", fontSize: 40, fontWeight: 700, letterSpacing: "-0.035em", lineHeight: 1.0, marginTop: 14, color: ink }}>
            Yoshi is off<br />to <span style={{ color: accent }}>work.</span>
          </div>
        </div>

        <div className="yo-enter" data-delay="3" style={{ marginTop: 34, width: "100%", maxWidth: 320, marginLeft: "auto", marginRight: "auto", borderTop: `1px solid ${m18}`, borderBottom: `1px solid ${m18}` }}>
          {[
            ["bank", "Next, add money or fund later"],
            ["card", "Use Apple Pay or link a bank on the funding screen"],
          ].map(([ic, tx]) => (
            <div key={tx} style={{ display: "flex", alignItems: "flex-start", justifyContent: "center", gap: 12, padding: "13px 0", borderBottom: tx.includes("external") ? `1px dashed ${m18}` : "none" }}>
              <span style={{ color: accent, flex: "none", marginTop: 1 }}><Icon name={ic} size={17} color={accent} /></span>
              <span style={{ flex: 1, fontFamily: "var(--f-display)", fontSize: 13.5, fontWeight: 500, lineHeight: 1.42, color: tx.includes("Use") ? m55 : ink, textAlign: "left" }}>{tx}</span>
            </div>
          ))}
        </div>
      </div>
    </Screen>
  );
};

Object.assign(window, { PlaidLink, BANKS, Funding, FundDeposit, Agent, AGENTS, Disclosures, OffToWork });
