> ## Documentation Index
> Fetch the complete documentation index at: https://developer.uphold.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Payment Widget introduction

> The Uphold Payment Widget is an embeddable, managed solution that lets users securely add payment methods and run transactions across web and native apps.

export const PaymentWidgetDemoMintlify = ({showAnnotation = true, initialPartner = 0, partners = ML_PARTNER_CONFIGS, bankDark = false} = {}) => {
  const [partnerIdx, setPartnerIdx] = useState(initialPartner);
  const [screen, setScreen] = useState("home");
  const [txnMode, setTxnMode] = useState("deposit");
  const [selectedCard, setSelectedCard] = useState(null);
  const [selectedBankAccount, setSelectedBankAccount] = useState(null);
  const [txnAmount, setTxnAmount] = useState("500");
  const [animDir, setAnimDir] = useState("fwd");
  const [didNavigate, setDidNavigate] = useState(false);
  const [bumps, setBumps] = useState({
    meridian: 0,
    lumen: 0,
    vault: 0
  });
  const [stepsDone, setStepsDone] = useState({
    1: false,
    2: false,
    3: false
  });
  const [bankCloseDelay, setBankCloseDelay] = useState(false);
  const cfg = partners[partnerIdx];
  const widgetOpen = screen === "widget";
  useEffect(() => {
    setScreen("home");
    setSelectedCard(null);
    setSelectedBankAccount(null);
    setTxnMode("deposit");
    setAnimDir("fwd");
  }, [partnerIdx]);
  useEffect(() => {
    if (screen !== "home") {
      setBankCloseDelay(false);
      return;
    }
    if (!bankCloseDelay) {
      setStepsDone({
        1: false,
        2: false,
        3: false
      });
      return;
    }
    const t = setTimeout(() => {
      setStepsDone({
        1: false,
        2: false,
        3: false
      });
      setBankCloseDelay(false);
    }, 2000);
    return () => clearTimeout(t);
  }, [screen, bankCloseDelay, cfg.id]);
  const go = (s, dir = "fwd") => {
    setDidNavigate(true);
    setAnimDir(dir);
    setScreen(s);
  };
  const handleBankClose = () => {
    const amt = Number(txnAmount) || 250;
    setBumps(b => ({
      ...b,
      [cfg.id]: (b[cfg.id] || 0) + amt
    }));
    setStepsDone(s => ({
      ...s,
      3: true
    }));
    setBankCloseDelay(true);
    go("home", "back");
  };
  const handleCryptoClose = () => {
    setStepsDone(s => ({
      ...s,
      3: true
    }));
    setBankCloseDelay(true);
    go("home", "back");
  };
  const renderHome = () => {
    const onTopUp = () => {
      setTxnMode("deposit");
      setSelectedCard(null);
      setSelectedBankAccount(null);
      setStepsDone({
        1: true,
        2: false,
        3: false
      });
      go("txn");
    };
    const onWithdraw = () => {
      setTxnMode("withdraw");
      setSelectedCard(null);
      setSelectedBankAccount(null);
      setStepsDone({
        1: true,
        2: false,
        3: false
      });
      go("txn");
    };
    const bump = bumps[cfg.id] || 0;
    if (cfg.id === "meridian") return <MeridianHome onTopUp={onTopUp} onWithdraw={onWithdraw} bump={bump} />;
    if (cfg.id === "lumen") return <LumenHome onTopUp={onTopUp} onWithdraw={onWithdraw} bump={bump} accent={cfg.accent} />;
    return <VaultHome onTopUp={onTopUp} onWithdraw={onWithdraw} bump={bump} />;
  };
  const renderBody = () => {
    if (screen === "home") return renderHome();
    if (screen === "widget") return <WidgetFlow onBack={() => {
      if (!selectedCard && !selectedBankAccount) {
        setStepsDone(s => ({
          ...s,
          2: false
        }));
      }
      go("txn", "back");
    }} onBankClose={handleBankClose} onCryptoClose={handleCryptoClose} onSelectCard={c => {
      setSelectedCard(c);
      setSelectedBankAccount(null);
      setStepsDone(s => ({
        ...s,
        3: true
      }));
      go("txn", "back");
    }} onSelectBankAccount={b => {
      setSelectedBankAccount(b);
      setSelectedCard(null);
      setStepsDone(s => ({
        ...s,
        3: true
      }));
      go("txn", "back");
    }} currency={cfg.currency} dark={!!cfg.widgetDark} bankDark={bankDark} mode={txnMode} partner={cfg.id} />;
    if (screen === "txn") return <TransactionPage partner={cfg.id} accent={cfg.accent} currency={cfg.currency} onBack={() => {
      setSelectedCard(null);
      setSelectedBankAccount(null);
      go("home", "back");
    }} onPickSource={() => {
      setStepsDone(s => ({
        ...s,
        2: true
      }));
      go("widget");
    }} selectedCard={selectedCard} selectedBankAccount={selectedBankAccount} onConfirm={amt => {
      const a = Number(amt) || 0;
      setTxnAmount(amt);
      if (a > 0) setBumps(b => ({
        ...b,
        [cfg.id]: (b[cfg.id] || 0) + (txnMode === "withdraw" ? -a : a)
      }));
      go("success");
    }} mode={txnMode} />;
    if (screen === "success") return <SuccessScreen partner={cfg.id} amount={txnAmount} card={selectedCard} bankAccount={selectedBankAccount} currency={cfg.currency} mode={txnMode} onDone={() => {
      setSelectedCard(null);
      setSelectedBankAccount(null);
      go("home", "back");
    }} />;
  };
  const sectionLabel = text => <div className="text-[#0E1525]/45 dark:text-white/45" style={{
    display: "flex",
    alignItems: "center",
    gap: "0.375rem",
    fontSize: "0.6875rem",
    fontWeight: 600,
    letterSpacing: "0.08em",
    textTransform: "uppercase"
  }}>
      {text}
    </div>;
  return <div style={{
    fontFamily: "sans-serif"
  }}>
      <style>{`
        @keyframes ml-anim-fwd { from { opacity: 0; transform: translateX(12px); } to { opacity: 1; transform: translateX(0); } }
        @keyframes ml-anim-back { from { opacity: 0; transform: translateX(-12px); } to { opacity: 1; transform: translateX(0); } }
        @keyframes ml-anim-up { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: translateY(0); } }
        @keyframes ml-toast-in { from { opacity: 0; transform: translateY(-8px); } to { opacity: 1; transform: translateY(0); } }
        @keyframes ml-toast-out { to { opacity: 0; transform: translateY(-8px); } }
        @keyframes ml-success-pop { 0% { transform: scale(0.6); opacity: 0; } 60% { transform: scale(1.08); opacity: 1; } 100% { transform: scale(1); opacity: 1; } }
        .ml-demo-outer { padding: 2.5rem; display: flex; flex-direction: row; align-items: center; justify-content: center; gap: 1rem; background: radial-gradient(1200px 600px at 50% 0%, rgba(53, 177, 61, 0.1), transparent 60%), linear-gradient(rgb(252, 252, 251), rgb(244, 244, 238)); }
        .ml-step-num { width: 28px; height: 28px; border-radius: 50%; font-size: 0.8125rem; font-weight: 600; display: flex; align-items: center; justify-content: center; flex-shrink: 0; margin-top: 2px; background: rgba(14,21,37,0.08); color: rgba(14,21,37,0.7); border: none; transition: background 250ms ease, color 250ms ease; }
        .dark .ml-step-num { background: rgba(255,255,255,0.1); color: rgba(255,255,255,0.6); }
        .ml-step-num.is-done, .dark .ml-step-num.is-done { background: #35B13D; color: white; }
        .dark .ml-demo-outer { background: #0D0F14; }
        .ml-demo-phone { order: 2; flex: 0 0 auto; display: flex; justify-content: center; position: relative; }
        .ml-demo-panels { display: contents; }
        .ml-demo-left { order: 1; flex: 1; display: flex; flex-direction: column; gap: 1rem; }
        .ml-demo-right { order: 3; flex: 1; display: flex; flex-direction: column; gap: 1.25rem; }
        .ml-demo-tabs { display: none; gap: 0.375rem; align-items: center; flex-wrap: wrap; justify-content: flex-start; }
        .ml-tab-selected { background: white !important; box-shadow: rgba(11,15,30,0.12) 0px 2px 8px -2px; }
        .dark .ml-tab-selected { background: #252A35 !important; box-shadow: none; }
        @media (max-width: 800px) {
          .ml-demo-outer { flex-direction: column; align-items: center; padding: 1.5rem; gap: 0; }
          .ml-demo-panels { display: contents; }
          .ml-demo-left { order: 0; width: 100%; flex: unset; }
          .ml-demo-phone { order: 1; flex: unset; padding-bottom: 48px; }
          .ml-demo-right { order: 2; width: 100%; flex: unset; }
        }
        .ml-partner-btn-selected { background: white; box-shadow: rgba(11, 15, 30, 0.18) 0px 6px 20px -6px; }
        .dark .ml-partner-btn-selected { background: #252A35; box-shadow: none; }
        .ml-caption-muted { color: rgba(14,21,37,0.45); }
        .dark .ml-caption-muted { color: rgba(255,255,255,0.45); }
        .ml-info-card { background: rgba(11, 15, 30, 0.04); border-radius: 0.75rem; padding: 1rem; }
        .dark .ml-info-card { background: #1C1F26; }
        @keyframes ml-pill-pulse { 0%, 100% { box-shadow: 0 0 0 0 rgba(255,176,32,0); } 50% { box-shadow: 0 0 0 6px rgba(255,176,32,0.6), 0 0 14px rgba(255,176,32,0.4); } }
        .ml-pill-pulse { animation: ml-pill-pulse 2.5s ease-in-out infinite; }
        @keyframes ml-ring {
          0%, 100% { box-shadow: 0 0 0 3px #35B13D, 0 0 28px rgba(53,177,61,0.18), rgba(11,15,30,0.55) 0px 50px 90px -28px, rgba(11,15,30,0.25) 0px 8px 24px -8px; }
          50% { box-shadow: 0 0 0 4px #35B13D, 0 0 64px rgba(53,177,61,0.42), rgba(11,15,30,0.55) 0px 50px 90px -28px, rgba(11,15,30,0.25) 0px 8px 24px -8px; }
        }
        .ml-ring-active { animation: ml-ring 2.4s ease-in-out infinite; }
        @keyframes ml-copy-pop { 0% { transform: scale(0.6); opacity: 0; } 55% { transform: scale(1.2); opacity: 1; } 100% { transform: scale(1); opacity: 1; } }
        .ml-copy-pop { animation: ml-copy-pop 240ms ease-out; }
      `}</style>

      <div className="dark:bg-[#0D0F14] ml-demo-outer" style={{
    borderRadius: "1.5rem",
    border: "1px solid rgba(0,0,0,0.06)",
    position: "relative"
  }}>

        {}
        <div style={{
    position: "absolute",
    inset: 0,
    borderRadius: "1.5rem",
    background: "rgba(11,15,30,0.5)",
    opacity: widgetOpen ? 1 : 0,
    transition: "opacity 350ms ease",
    pointerEvents: "none",
    zIndex: 1
  }} />

        {}
        <div className="ml-demo-tabs">
          <div style={{
    width: "100%",
    marginBottom: "0.25rem"
  }}>{sectionLabel("Pick a partner app")}</div>
          {partners.map((p, i) => <button key={p.id} onClick={() => setPartnerIdx(i)} className={partnerIdx === i ? "ml-tab-selected" : ""} style={{
    display: "flex",
    alignItems: "center",
    gap: "0.5rem",
    padding: "0.4375rem 0.75rem 0.4375rem 0.5rem",
    borderRadius: "0.625rem",
    border: "none",
    cursor: "pointer",
    background: "transparent",
    transition: "background 200ms"
  }}>
              <span style={{
    width: 28,
    height: 28,
    borderRadius: "0.4375rem",
    display: "inline-flex",
    alignItems: "center",
    justifyContent: "center",
    fontSize: "0.8125rem",
    fontWeight: 800,
    flexShrink: 0,
    background: p.chipBg,
    color: p.chipFg
  }}>{p.label[0]}</span>
              <span className="text-[#0E1525] dark:text-white" style={{
    fontSize: "0.875rem",
    fontWeight: 600
  }}>{p.label}</span>
            </button>)}
        </div>

        {}
        <div className="ml-demo-phone" style={{
    paddingTop: showAnnotation ? 48 : 0,
    zIndex: 2
  }}>
          <div style={{
    position: "relative"
  }}>
            {}
            <div className={`rounded-[40px] sm:rounded-[44px] ${widgetOpen ? "ml-ring-active" : ""}`} style={{
    transition: "box-shadow 400ms cubic-bezier(.16,1,.3,1)",
    boxShadow: widgetOpen ? undefined : "rgba(11,15,30,0.55) 0px 50px 90px -28px, rgba(11,15,30,0.25) 0px 8px 24px -8px"
  }}>
              <PhoneShell bgClass={cfg.phoneBgClass} lightStatus={!!cfg.lightStatus} borderClass={cfg.lightStatus ? "border-black/10" : "border-white/10"}>
                <div key={screen} className="flex-1 flex flex-col min-h-0" style={{
    animation: !didNavigate ? undefined : animDir === "fwd" ? "ml-anim-fwd 280ms cubic-bezier(.16,1,.3,1)" : "ml-anim-back 280ms cubic-bezier(.16,1,.3,1)"
  }}>
                  {renderBody()}
                </div>
              </PhoneShell>
            </div>

            {}
            {showAnnotation && <div style={{
    position: "absolute",
    top: -15,
    left: "50%",
    transform: widgetOpen ? "translateX(-50%) translateY(0)" : "translateX(-50%) translateY(6px)",
    display: "flex",
    alignItems: "center",
    gap: "0.4rem",
    whiteSpace: "nowrap",
    opacity: widgetOpen ? 1 : 0,
    pointerEvents: "none",
    transition: "opacity 300ms ease, transform 300ms cubic-bezier(.16,1,.3,1)",
    zIndex: 5,
    background: "#35B13D",
    color: "#fff",
    padding: "0.34rem 0.78rem",
    borderRadius: "999px",
    fontSize: "0.6875rem",
    fontWeight: 700,
    boxShadow: "0 8px 22px -6px rgba(53,177,61,0.75)"
  }}>
                <LeafLogo color="#ffffff" />
                Uphold Payment Widget
                <span style={{
    opacity: 0.85,
    fontWeight: 600
  }}>· inside {cfg.label}</span>
              </div>}
          </div>
        </div>

        {}
        <div className="ml-demo-panels">

          {}
          <div className="ml-demo-left">
            {sectionLabel("Pick a partner app")}

            <div style={{
    display: "flex",
    flexDirection: "column",
    gap: "4px"
  }}>
              {partners.map((p, i) => <button key={p.id} onClick={() => setPartnerIdx(i)} className={partnerIdx === i ? "ml-partner-btn-selected" : "bg-transparent hover:bg-black/5 dark:hover:bg-white/5"} style={{
    display: "flex",
    alignItems: "center",
    gap: "0.75rem",
    padding: "0.75rem",
    borderRadius: "0.75rem",
    border: "none",
    cursor: "pointer",
    textAlign: "left",
    width: "100%",
    transition: "background 200ms"
  }}>
                  <span style={{
    width: 32,
    height: 32,
    borderRadius: "0.5rem",
    display: "inline-flex",
    alignItems: "center",
    justifyContent: "center",
    fontSize: "0.875rem",
    fontWeight: 800,
    flexShrink: 0,
    background: p.chipBg,
    color: p.chipFg
  }}>{p.label[0]}</span>
                  <div style={{
    flex: 1,
    minWidth: 0
  }}>
                    <div className="text-[#0E1525] dark:text-white" style={{
    fontSize: "0.875rem",
    fontWeight: 700,
    lineHeight: 1.3
  }}>{p.label}</div>
                    <div className="text-[#0E1525]/50 dark:text-white/50" style={{
    fontSize: "0.75rem",
    marginTop: 2,
    lineHeight: 1.3
  }}>{p.tag} · {p.desc}</div>
                  </div>
                  {partnerIdx === i && <svg width="18" height="18" viewBox="0 0 24 24" fill="none" style={{
    flexShrink: 0
  }}>
                      <circle cx="12" cy="12" r="11" fill="#35B13D" />
                      <path d="M7 12l3.5 3.5L17 8" stroke="white" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round" />
                    </svg>}
                </button>)}
            </div>

            <div className="ml-info-card">
              <div className="text-[#0E1525] dark:text-white" style={{
    fontSize: "0.875rem",
    fontWeight: 700,
    marginBottom: "0.375rem"
  }}>One widget. Any host.</div>
              <div className="text-[#0E1525]/55 dark:text-white/55" style={{
    fontSize: "0.8125rem",
    lineHeight: 1.5
  }}>Each app in the list is a different partner. The same widget lives inside all three. Dark and light mode included.</div>
            </div>
          </div>

          {}
          <div className="ml-demo-right">
            {sectionLabel("Try the flow")}
            {[{
    n: 1,
    title: "Tap the funding pill",
    desc: "The partner host's UI and UX. Yours stays yours."
  }, {
    n: 2,
    title: "Widget takes over the body",
    desc: "The widget handles the payment method selection experience."
  }, {
    n: 3,
    title: "Pick a method, return",
    desc: "Selection lands back on the host. Done."
  }].map(step => <div key={step.n} style={{
    display: "flex",
    gap: "0.75rem"
  }}>
                <div className={`ml-step-num${stepsDone[step.n] ? " is-done" : ""}`}>{step.n}</div>
                <div>
                  <div className="text-[#0E1525] dark:text-white" style={{
    fontSize: "0.875rem",
    fontWeight: 700,
    lineHeight: 1.3
  }}>{step.title}</div>
                  <div className="text-[#0E1525]/55 dark:text-white/55" style={{
    fontSize: "0.8125rem",
    marginTop: 4,
    lineHeight: 1.5
  }}>{step.desc}</div>
                </div>
              </div>)}
          </div>

        </div>

      </div>
    </div>;
};

export const ML_PARTNER_CONFIGS = [{
  id: "meridian",
  label: "Meridian",
  tag: "Investing",
  desc: "ETF & equities",
  chipBg: "#1d2738",
  chipFg: "#fff",
  phoneBgClass: "bg-[#FAFAF7]",
  currency: "GBP",
  accent: "#1d2738",
  lightStatus: true
}, {
  id: "lumen",
  label: "Lumen",
  tag: "Crypto",
  desc: "Crypto & staking",
  chipBg: "#0B0D10",
  chipFg: "#E8FF3A",
  phoneBgClass: "bg-[#0B0D10]",
  currency: "USD",
  accent: "#E8FF3A",
  lightStatus: false,
  widgetDark: true
}, {
  id: "vault",
  label: "Vault",
  tag: "Neobank",
  desc: "Spending & savings",
  chipBg: "#FF5C39",
  chipFg: "#fff",
  phoneBgClass: "bg-[#F4EFE8]",
  currency: "EUR",
  accent: "#FF5C39",
  lightStatus: true
}];

export const WCalloutInfo = ({icon, children, dark}) => {
  if (dark) {
    return <div className="flex items-start gap-3 p-3.5 rounded-xl bg-[#2c50b4]/30">
        <div className="flex-shrink-0 flex items-center justify-center w-6 text-[#bcd4ff]">{icon}</div>
        <div className="text-[13px] leading-normal text-white/90">{children}</div>
      </div>;
  }
  return <div className="flex items-start gap-3 p-3.5 rounded-xl bg-blue-100">
      <div className="flex-shrink-0 flex items-center justify-center w-6 text-[#1a4caa]">{icon}</div>
      <div className="text-[13px] leading-normal text-[#0E1525]">{children}</div>
    </div>;
};

export const SuccessScreen = ({partner, amount, card, bankAccount, currency, onDone, mode = "deposit"}) => {
  const isDark = partner === "lumen";
  const isVault = partner === "vault";
  const isWithdraw = mode === "withdraw";
  const bgStyle = isDark ? {
    backgroundColor: "#0B0D10",
    color: "white"
  } : isVault ? {
    backgroundColor: "#F4EFE8",
    color: "#0E1525"
  } : {
    backgroundColor: "#FAFAF7",
    color: "#0E1525"
  };
  const sym = currency === "USD" ? "$" : currency === "EUR" ? "€" : "£";
  const accent = partner === "lumen" ? "#E8FF3A" : partner === "vault" ? "#FF5C39" : "#1d2738";
  const fmtAmt = a => {
    const n = Number(a);
    if (!isFinite(n)) return a;
    return n.toLocaleString("en-US", {
      minimumFractionDigits: n % 1 === 0 ? 0 : 2,
      maximumFractionDigits: 2
    });
  };
  const isCryptoWithdraw = isWithdraw && !!(bankAccount && bankAccount.cryptoAssetId);
  const cryptoRate = currency === "USD" ? 95000 : currency === "EUR" ? 88000 : 75000;
  const cryptoAmount = isCryptoWithdraw ? (Number(amount || 0) / cryptoRate).toFixed(6) : null;
  return <div className="flex-1 flex flex-col" style={{
    ...bgStyle,
    animation: "ml-anim-up 320ms cubic-bezier(.16,1,.3,1)"
  }}>
      <div className="flex-1 flex flex-col items-center justify-center px-8 text-center">
        <div className={`w-20 h-20 rounded-full flex items-center justify-center mb-6 text-[#35B13D] ${isDark ? "bg-white/[0.07]" : "bg-black/[0.06]"}`} style={{
    animation: "ml-success-pop 500ms cubic-bezier(.16,1,.3,1) both"
  }}>
          <IcoCheck />
        </div>
        <div className="text-[26px] font-extrabold tracking-tight mb-2">{isWithdraw ? "Withdrawal confirmed" : "Deposit confirmed"}</div>
        <div className="text-[44px] font-extrabold tracking-tight mb-1 tabular-nums">{sym}{fmtAmt(amount)}</div>
        {isCryptoWithdraw && <div className={`text-[18px] font-semibold tabular-nums mb-2 ${isDark ? "text-white/70" : "text-[#0E1525]/70"}`}>≈ {cryptoAmount} BTC</div>}
      </div>
      <div className="px-5 pt-4 pb-10 flex-shrink-0">
        <button onClick={onDone} className="w-full border-0 rounded-full text-[15px] font-bold cursor-pointer" style={{
    height: "3rem",
    padding: 0,
    background: isDark ? accent : "#0E1525",
    color: isDark ? "#0B0D10" : "#fff"
  }}>
          Back to home
        </button>
      </div>
    </div>;
};

export const TransactionPage = ({partner, onBack, onPickSource, selectedCard, selectedBankAccount, onConfirm, accent, currency, mode = "deposit"}) => {
  const [amount, setAmount] = useState("500");
  const isDark = partner === "lumen";
  const isWithdraw = mode === "withdraw";
  const isVault = partner === "vault";
  const bgStyle = isDark ? {
    backgroundColor: "#0B0D10",
    color: "white"
  } : isVault ? {
    backgroundColor: "#F4EFE8",
    color: "#0E1525"
  } : {
    backgroundColor: "#FAFAF7",
    color: "#0E1525"
  };
  const muted = isDark ? "text-white/50" : "text-[#0E1525]/50";
  const sym = currency === "USD" ? "$" : currency === "EUR" ? "€" : "£";
  const destLabel = partner === "lumen" ? "BTC Wallet" : partner === "vault" ? "Spending" : "GBP Balance";
  const destSub = partner === "lumen" ? "Crypto" : partner === "vault" ? "Vault Debit" : "Meridian";
  const hasExternal = !!(selectedCard || selectedBankAccount);
  const canConfirm = hasExternal && amount.length > 0;
  const isCryptoWithdraw = isWithdraw && !!(selectedBankAccount && selectedBankAccount.cryptoAssetId);
  const cryptoRate = currency === "USD" ? 95000 : currency === "EUR" ? 88000 : 75000;
  const receiveValue = isCryptoWithdraw ? `${(Number(amount || 0) / cryptoRate).toFixed(6)} BTC` : `${sym}${amount}`;
  const externalIcon = selectedBankAccount ? selectedBankAccount.cryptoAssetId ? <CryptoMark id={selectedBankAccount.cryptoAssetId} sm /> : <div className={`w-[30px] h-[30px] rounded-[9px] flex items-center justify-center flex-shrink-0 ${isDark ? "bg-white/10 text-white" : "bg-black/5 text-[#0E1525]"}`}><IcoBank /></div> : selectedCard ? selectedCard.brand === "mastercard" ? <McardMark sm /> : <VisaMark sm /> : <div className={`w-[30px] h-[30px] rounded-[9px] border-[1.5px] flex items-center justify-center flex-shrink-0 ${isDark ? "border-white/40 text-white" : "border-[#0E1525]/25 text-[#0E1525]"}`}><IcoCardPlus /></div>;
  const externalTitle = selectedBankAccount ? selectedBankAccount.name : selectedCard ? `#${selectedCard.last4}` : "Tap to select";
  const externalSub = selectedBankAccount ? selectedBankAccount.currency : selectedCard ? selectedCard.currency : isWithdraw ? "Destination" : "Source";
  const cardPill = <button key="card" onClick={onPickSource} className={`${!hasExternal ? "ml-pill-pulse" : ""} flex-1 min-w-0 min-h-[72px] flex items-center gap-2 px-2.5 py-3 rounded-[18px] border-2 cursor-pointer text-left transition-colors ${hasExternal ? isDark ? "border-white/20 bg-white/5 hover:bg-white/10" : "border-[#0E1525]/15 bg-black/5 hover:bg-black/10" : isDark ? "border-white/10 bg-white/5 hover:bg-white/10" : "border-[#0E1525]/10 bg-black/5 hover:bg-black/10"}`}>
      {externalIcon}
      <div className="flex-1 min-w-0">
        <div className="font-bold whitespace-nowrap overflow-hidden text-ellipsis" style={{
    fontSize: "0.75rem"
  }}>{externalTitle}</div>
        <div className={`text-xs mt-px whitespace-nowrap overflow-hidden text-ellipsis ${muted}`}>{externalSub}</div>
      </div>
    </button>;
  const balancePill = <div key="balance" className={`flex-1 min-w-0 min-h-[72px] flex items-center gap-2 px-2.5 py-3 rounded-[18px] border-2 ${isDark ? "border-white/10 bg-white/5" : "border-[#0E1525]/10 bg-black/5"}`}>
      <div className={`w-[30px] h-[30px] rounded-full flex items-center justify-center text-sm font-extrabold flex-shrink-0 ${isDark ? "bg-white text-[#0B0D10]" : "bg-[#1d2738] text-white"}`}>{sym}</div>
      <div className="flex-1 min-w-0">
        <div className="font-bold whitespace-nowrap overflow-hidden text-ellipsis" style={{
    fontSize: "0.75rem"
  }}>{destLabel}</div>
        <div className={`text-xs mt-px whitespace-nowrap overflow-hidden text-ellipsis ${muted}`}>{destSub}</div>
      </div>
    </div>;
  const arrow = <div key="arrow" className={`flex-shrink-0 ${muted}`}><IcoArrow /></div>;
  const pills = isWithdraw ? [balancePill, arrow, cardPill] : [cardPill, arrow, balancePill];
  return <div className="flex-1 flex flex-col min-h-0" style={bgStyle}>
      <div className="flex items-center gap-3 px-5 pt-4 pb-3">
        <button onClick={onBack} className={`w-10 h-10 rounded-full border-0 flex items-center justify-center cursor-pointer ${isDark ? "bg-white/[0.08] text-white" : "bg-[#0E1525]/[0.06] text-[#0E1525]"}`}><IcoBack /></button>
        <span className="text-[17px] font-bold flex-1 text-center pr-10">{isWithdraw ? "Withdraw funds" : "Add funds"}</span>
      </div>

      <div className="flex-1 px-5 pt-2 overflow-hidden">
        <div className={`text-xs font-semibold uppercase tracking-[1px] mb-2.5 ${muted}`}>From → To</div>
        <div className="flex items-center gap-2.5">{pills}</div>

        <div className="mt-7">
          <div className={`text-xs font-semibold uppercase tracking-[1px] mb-2.5 ${muted}`}>Amount</div>
          <div className={`flex items-center rounded-[18px] border-2 overflow-hidden ${isDark ? "border-white/10 bg-white/5" : "border-[#0E1525]/10 bg-black/5"}`}>
            <div className={`pl-5 pr-4 py-4 text-[28px] font-bold ${muted}`}>{sym}</div>
            <input type="text" inputMode="decimal" value={amount} onChange={e => setAmount(e.target.value.replace(/[^0-9.]/g, ""))} className="flex-1 border-0 outline-none bg-transparent text-[34px] font-bold py-4 pr-5 font-sans tabular-nums w-0" />
          </div>
          <div className="flex justify-end mt-2 gap-2">
            {["100", "500", "1,000"].map(v => <button key={v} onClick={() => setAmount(v.replace(",", ""))} className={`px-3.5 py-1.5 border rounded-full text-[13px] font-semibold cursor-pointer bg-transparent transition-colors ${isDark ? "border-white/10 text-white hover:bg-white/5" : "border-[#0E1525]/10 text-[#0E1525] hover:bg-black/5"}`}>
                {sym}{v}
              </button>)}
          </div>
        </div>

        {hasExternal && amount && <div className={`mt-6 p-4 rounded-2xl ${isDark ? "bg-white/5" : "bg-black/[0.04]"}`} style={{
    animation: "ml-anim-up 320ms cubic-bezier(.16,1,.3,1)"
  }}>
            <div className={`text-[13px] mb-3 ${muted}`}>Summary</div>
            {[["You send", `${sym}${amount}`], [isWithdraw ? "Destination" : "Payment method", selectedBankAccount ? selectedBankAccount.name : `#${selectedCard.last4} (${selectedCard.brand.slice(0, 1).toUpperCase() + selectedCard.brand.slice(1)})`], ["Processing fee", `${sym}0.00`], ["You receive", receiveValue]].map(([k, v]) => <div key={k} className="flex justify-between mb-2">
                <span className={`text-[13px] ${muted}`}>{k}</span>
                <span className="text-[13px] font-semibold tabular-nums">{v}</span>
              </div>)}
          </div>}
      </div>

      <div className="px-5 pt-4 pb-10 flex-shrink-0">
        <button onClick={canConfirm ? () => onConfirm(amount) : undefined} className={`w-full border-0 rounded-full text-[15px] font-bold ${canConfirm ? "cursor-pointer" : "cursor-default"} transition-opacity`} style={{
    height: "3rem",
    padding: 0,
    background: canConfirm ? isDark ? accent : "#0E1525" : isDark ? "rgba(255,255,255,0.1)" : "rgba(11,15,30,0.08)",
    color: canConfirm ? isDark ? "#0B0D10" : "#fff" : isDark ? "rgba(255,255,255,0.5)" : "rgba(11,15,30,0.5)"
  }}>
          {hasExternal ? isWithdraw ? "Confirm withdrawal" : "Confirm deposit" : isWithdraw ? "Confirm withdrawal" : "Confirm deposit"}
        </button>
      </div>
    </div>;
};

export const VaultHome = ({onTopUp, onWithdraw, bump = 0}) => {
  const balance = "€" + (3182.40 + bump).toLocaleString("en-US", {
    minimumFractionDigits: 2,
    maximumFractionDigits: 2
  });
  return <div className="flex-1 flex flex-col min-h-0 bg-[#F4EFE8] text-[#1A1410]">
      <div className="flex items-center justify-between px-5 pt-4 pb-2">
        <div className="flex items-center gap-2">
          <svg className="w-[22px] h-[22px]" viewBox="0 0 24 24" fill="none"><circle cx="12" cy="12" r="10" stroke="#1A1410" strokeWidth="2" /><path d="M9 12L12 15 17 9" stroke="#FF5C39" strokeWidth="2.4" strokeLinecap="round" strokeLinejoin="round" fill="none" /></svg>
          <span className="text-[15px] font-bold">Vault</span>
        </div>
        <div className="flex items-center gap-2">
          <span className="text-[11px] font-bold uppercase tracking-[0.8px] px-2.5 py-0.5 rounded-full bg-[#FF5C39] text-white">Pro</span>
          <div className="w-9 h-9 rounded-full bg-[#1A1410] text-white flex items-center justify-center text-xs font-extrabold">EM</div>
        </div>
      </div>
      <div className="px-5 pt-5">
        <div className="text-[13px] font-semibold text-[#1A1410]/60">Spending account</div>
        <div className="text-[42px] font-extrabold tracking-tight mt-2 tabular-nums">{balance}</div>
      </div>
      <div className="grid grid-cols-3 gap-2 px-5 pt-5">
        <button onClick={onTopUp} className="ml-pill-pulse px-2 py-3 border-0 rounded-2xl bg-[#FF5C39] text-white text-[13px] font-bold cursor-pointer flex flex-col items-center gap-1.5">
          <div className="w-7 h-7 flex items-center justify-center"><IcoCardPlus /></div>
          <span>Add money</span>
        </button>
        {[["Send", "M12 19V5M5 12l7-7 7 7", true], ["Pots", "M19 5c-1.5 0-2.8 1.4-3 2-3.5-1.5-11-.3-11 5 0 1.8 0 3 2 4.5V20h4v-2h3v2h4v-4c1-.5 1.7-1 2-2h2v-4h-2c0-1-.5-1.5-1-2V5zM2 9v1c0 1.1.9 2 2 2h1M16 11h.01", false]].map(([l, d, isSend]) => <button key={l} onClick={isSend ? onWithdraw : undefined} className={`${isSend ? "ml-pill-pulse " : ""}px-2 py-3 border-0 rounded-2xl bg-[#1A1410]/5 text-[#1A1410] text-[13px] font-bold cursor-pointer flex flex-col items-center gap-1.5`}>
            <div className="w-7 h-7 flex items-center justify-center">
              <svg className="w-5 h-5" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d={d} /></svg>
            </div>
            <span>{l}</span>
          </button>)}
      </div>
      <div className="px-5 pt-5">
        <div className="text-sm font-bold mb-2.5">Saving pots</div>
        <div className="flex gap-2">
          {[["✈", "Travel", "€842", "#FFE8DA"], ["₣", "Tax", "€1,200", "#E8E2FF"], ["◓", "Roof", "€3,400", "#DCEEDC"]].map(([e, l, a, t]) => <div key={l} className="flex-1 rounded-2xl p-3" style={{
    background: t
  }}>
              <div className="text-[20px] mb-1">{e}</div>
              <div className="text-xs font-bold text-[#1A1410]/70">{l}</div>
              <div className="text-[15px] font-bold mt-0.5 tabular-nums">{a}</div>
            </div>)}
        </div>
      </div>
      <div className="px-5 pt-5">
        <div className="text-sm font-bold mb-2">Today</div>
        {[["P", "Pret a Manger", "Coffee", "-€4.85", false], ["U", "Uber", "Transport", "-€12.40", false], ["A", "Acme Co", "Salary", "+€2,840.00", true]].map(([i, n, c, a, pos]) => <div key={n} className="flex items-center gap-3 py-2.5 border-b border-[#1A1410]/5">
            <div className="w-9 h-9 rounded-full bg-[#1A1410]/10 flex items-center justify-center text-sm font-bold flex-shrink-0">{i}</div>
            <div className="flex-1">
              <div className="text-sm font-bold">{n}</div>
              <div className="text-xs text-[#1A1410]/50 mt-px">{c}</div>
            </div>
            <div className={`text-sm font-bold tabular-nums ${pos ? "text-[#0E8C5C]" : "text-[#1A1410]"}`}>{a}</div>
          </div>)}
      </div>
      <div className="flex justify-around px-5 pt-3 pb-2.5 border-t border-[#1A1410]/5 mt-auto flex-shrink-0">
        {[["Home", "M3 12l9-9 9 9M5 10v10h14V10", true], ["Cards", "M3 7h18v10H3zM3 11h18"], ["Invest", "M3 18h4V8H3zM10 18h4V4h-4zM17 18h4v-7h-4z"], ["More", "M5 12h.01M12 12h.01M19 12h.01"]].map(([l, d, a]) => <NavTab key={l} label={l} d={d} active={a} accent="#FF5C39" />)}
      </div>
    </div>;
};

export const LumenHome = ({onTopUp, onWithdraw, accent = "#E8FF3A", bump = 0}) => {
  const balance = "$" + (12847.62 + bump).toLocaleString("en-US", {
    minimumFractionDigits: 2,
    maximumFractionDigits: 2
  });
  return <div className="flex-1 flex flex-col min-h-0 bg-[#0B0D10] text-white">
      <div className="flex items-center justify-between px-5 pt-4 pb-2">
        <div className="flex items-center gap-2">
          <div className="w-8 h-8 rounded-[10px] flex items-center justify-center" style={{
    background: accent
  }}>
            <svg className="w-4 h-4" viewBox="0 0 24 24" fill="none" stroke="#0B0D10" strokeWidth="2.4" strokeLinecap="round" strokeLinejoin="round"><path d="M12 2 L4 12 L12 16 L20 12 Z" /><path d="M4 12 L12 22 L20 12" /></svg>
          </div>
          <span className="text-[15px] font-bold">Lumen</span>
        </div>
        <div className="w-9 h-9 rounded-full bg-gradient-to-br from-[#7c5cff] to-[#ff5cae] flex items-center justify-center text-xs font-bold">JL</div>
      </div>
      <div className="px-5 pt-5">
        <div className="text-xs uppercase tracking-[1.2px] text-white/40 font-semibold">Portfolio value</div>
        <div className="text-[40px] font-extrabold tracking-tight mt-1.5 tabular-nums">{balance}</div>
        <div className="text-[13px] mt-1.5" style={{
    color: accent
  }}>+$214.30 (+1.71%) Today</div>
      </div>
      <div className="mx-5 mt-4 rounded-2xl overflow-hidden border border-white/5 h-20 relative bg-white/[0.03]">
        <svg width="100%" height="100%" viewBox="0 0 320 80" preserveAspectRatio="none">
          <defs>
            <linearGradient id="mlSg" x1="0" x2="0" y1="0" y2="1">
              <stop offset="0%" stopColor={accent} stopOpacity="0.4" /><stop offset="100%" stopColor={accent} stopOpacity="0" />
            </linearGradient>
          </defs>
          <path d="M0,60 C30,52 50,68 80,46 S140,24 170,34 S230,12 260,20 S310,4 320,6 L320,80 L0,80 Z" fill="url(#mlSg)" />
          <path d="M0,60 C30,52 50,68 80,46 S140,24 170,34 S230,12 260,20 S310,4 320,6" fill="none" stroke={accent} strokeWidth="2" />
        </svg>
      </div>
      <div className="grid grid-cols-2 gap-2.5 px-5 pt-4">
        <button onClick={onTopUp} className="ml-pill-pulse p-3.5 border-0 rounded-2xl text-[14px] font-bold cursor-pointer text-left flex flex-col gap-1" style={{
    background: accent,
    color: "#0B0D10"
  }}>
          <div className="text-[11px] uppercase tracking-[0.8px] opacity-70">Buy</div>
          <div>Add funds</div>
        </button>
        <button onClick={onWithdraw} className="ml-pill-pulse p-3.5 border-0 rounded-2xl bg-white/5 text-white text-sm font-bold cursor-pointer text-left flex flex-col gap-1">
          <div className="text-[11px] uppercase tracking-[0.8px] opacity-60">Send</div>
          <div>Withdraw funds</div>
        </button>
      </div>
      <div className="px-5 pt-5">
        <div className="text-[15px] font-bold mb-2.5">Holdings</div>
        {[{
    g: "₿",
    c: "#F7931A",
    n: "Bitcoin",
    a: "0.1842 BTC",
    v: "$8,924",
    ch: "+2.1%",
    up: true
  }, {
    g: "Ξ",
    c: "#627EEA",
    n: "Ethereum",
    a: "1.214 ETH",
    v: "$2,816",
    ch: "+0.8%",
    up: true
  }, {
    g: "◎",
    c: "#9945FF",
    n: "Solana",
    a: "6.50 SOL",
    v: "$842",
    ch: "-1.4%",
    up: false
  }].map(h => <div key={h.n} className="flex items-center gap-3 py-2.5 border-b border-white/5">
            <div className="w-9 h-9 rounded-full text-white flex items-center justify-center text-sm font-bold flex-shrink-0" style={{
    background: h.c
  }}>{h.g}</div>
            <div className="flex-1">
              <div className="text-sm font-bold">{h.n}</div>
              <div className="text-xs text-white/50 mt-px">{h.a}</div>
            </div>
            <div className="text-right">
              <div className="text-sm font-bold tabular-nums">{h.v}</div>
              <div className={`text-xs mt-px ${h.up === true ? "text-[#5EE38F]" : h.up === false ? "text-[#FF6B6B]" : "text-white/40"}`}>{h.ch}</div>
            </div>
          </div>)}
      </div>
      <div className="flex justify-around px-5 pt-3 pb-2.5 border-t border-white/5 mt-auto flex-shrink-0">
        {[["Home", "M3 12l9-9 9 9M5 10v10h14V10", true], ["Markets", "M3 18h4V8H3zM10 18h4V4h-4zM17 18h4v-7h-4z"], ["Earn", "M12 2v20M5 9l7-7 7 7M5 15l7 7 7-7"], ["Profile", "M12 12a4 4 0 100-8 4 4 0 000 8zM4 22a8 8 0 0116 0"]].map(([l, d, a]) => <NavTab key={l} label={l} d={d} active={a} dark />)}
      </div>
    </div>;
};

export const MeridianHome = ({onTopUp, onWithdraw, bump = 0}) => {
  const balance = "£" + (24318.04 + bump).toLocaleString("en-US", {
    minimumFractionDigits: 2,
    maximumFractionDigits: 2
  });
  return <div className="flex-1 flex flex-col min-h-0 bg-[#FAFAF7] text-[#0E1525]">
      <div className="flex items-center justify-between px-5 pt-4 pb-2">
        <div className="flex items-center gap-2">
          <svg className="w-5 h-5" viewBox="0 0 24 24" fill="none" stroke="#1d2738" strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round"><path d="M3 18L9 10l4 4 8-10" /><circle cx="9" cy="10" r="1.4" fill="#1d2738" stroke="none" /><circle cx="13" cy="14" r="1.4" fill="#1d2738" stroke="none" /></svg>
          <span className="text-[15px] font-bold">Meridian</span>
        </div>
        <div className="w-9 h-9 rounded-full bg-[#1d2738] flex items-center justify-center text-xs font-extrabold text-white">JL</div>
      </div>
      <div className="mx-5 mt-2 p-6 rounded-3xl bg-[#1d2738] text-white relative overflow-hidden">
        <div className="absolute -right-10 -bottom-7 w-40 h-40 rounded-full bg-white/5 pointer-events-none" />
        <div className="text-xs font-semibold uppercase tracking-[1.1px] opacity-70 mb-1.5">Total balance</div>
        <div className="text-4xl font-extrabold tracking-tight tabular-nums">{balance}</div>
        <div className="text-[13px] opacity-70 mt-1.5">↑ +£482.91 this month</div>
        <div className="flex gap-2 mt-5">
          <button onClick={onTopUp} className="ml-pill-pulse flex-1 py-2.5 border-0 rounded-xl bg-white text-[#1d2738] text-[13px] font-bold cursor-pointer flex items-center justify-center gap-1.5"><IcoPlus /> Top up</button>
          <button onClick={onWithdraw} className="ml-pill-pulse flex-1 py-2.5 border-0 rounded-xl bg-white/10 text-white text-[13px] font-bold cursor-pointer">Withdraw</button>
        </div>
      </div>
      <div className="px-5 pt-5">
        <div className="flex justify-between items-center mb-3">
          <span className="text-[15px] font-bold">Portfolio</span>
          <span className="text-xs text-[#0E1525]/50">5 positions</span>
        </div>
        <div className="flex flex-col">
          {[{
    l: "V",
    c: "#1A1F71",
    n: "VWRP",
    s: "Vanguard FTSE All-World",
    v: "£8,402",
    ch: "+1.4%",
    up: true
  }, {
    l: "A",
    c: "#0071E3",
    n: "AAPL",
    s: "Apple Inc.",
    v: "£4,128",
    ch: "+0.6%",
    up: true
  }, {
    l: "N",
    c: "#76B900",
    n: "NVDA",
    s: "NVIDIA Corp.",
    v: "£3,890",
    ch: "+3.2%",
    up: true
  }, {
    l: "T",
    c: "#E50914",
    n: "TSLA",
    s: "Tesla, Inc.",
    v: "£2,140",
    ch: "-0.8%",
    up: false
  }, {
    l: "₿",
    c: "#F7931A",
    n: "BTC",
    s: "Bitcoin",
    v: "£5,756",
    ch: "+2.1%",
    up: true
  }].map(p => <div key={p.n} className="flex items-center gap-3 py-2.5 border-b border-[#0E1525]/5">
              <div className="w-9 h-9 rounded-full text-white flex items-center justify-center text-[13px] font-extrabold flex-shrink-0" style={{
    background: p.c
  }}>{p.l}</div>
              <div className="flex-1">
                <div className="text-sm font-bold">{p.n}</div>
                <div className="text-xs text-[#0E1525]/50 mt-px">{p.s}</div>
              </div>
              <div className="text-right">
                <div className="text-sm font-bold tabular-nums">{p.v}</div>
                <div className={`text-xs mt-px ${p.up ? "text-[#0E8C5C]" : p.ch.startsWith("-") ? "text-[#C53030]" : "text-[#0E1525]/45"}`}>{p.ch}</div>
              </div>
            </div>)}
        </div>
      </div>
      <div className="flex justify-around px-5 pt-3 pb-2.5 border-t border-[#0E1525]/5 mt-auto flex-shrink-0">
        {[["Home", "M3 12l9-9 9 9M5 10v10h14V10", true], ["Invest", "M3 18h4V8H3zM10 18h4V4h-4zM17 18h4v-7h-4z"], ["Plans", "M9 12h6M9 16h3M7 4h10a2 2 0 012 2v14l-3-2-2 2-2-2-2 2-2-2-3 2V6a2 2 0 012-2z"], ["You", "M12 12a4 4 0 100-8 4 4 0 000 8zM4 22a8 8 0 0116 0"]].map(([l, d, a]) => <NavTab key={l} label={l} d={d} active={a} accent="#1d2738" />)}
      </div>
    </div>;
};

export const NavTab = ({label, d, active, dark, accent}) => {
  const colorOn = dark ? "text-white" : accent || "text-[#1d2738]";
  const colorOff = dark ? "text-white/35" : "text-[#0E1525]/35";
  return <button className={`flex flex-col items-center gap-0.5 border-0 bg-transparent cursor-pointer ${active ? colorOn : colorOff}`} style={accent && active ? {
    color: accent
  } : undefined}>
      <svg className="w-5 h-5" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d={d} /></svg>
      <span className="text-[10px] font-bold">{label}</span>
    </button>;
};

export const FundsToast = ({toast, currency, partnerId, onDismiss}) => {
  if (!toast) return null;
  const styles = partnerId === "lumen" ? {
    bg: "bg-[#1A1D22]",
    border: "border-white/10",
    iconBg: "bg-[#E8FF3A]",
    iconFg: "text-[#0B0D10]",
    title: "text-white",
    subtitle: "text-white/55"
  } : partnerId === "vault" ? {
    bg: "bg-white",
    border: "border-[#1A1410]/10",
    iconBg: "bg-[#0E8C5C]",
    iconFg: "text-white",
    title: "text-[#1A1410]",
    subtitle: "text-[#1A1410]/60"
  } : {
    bg: "bg-white",
    border: "border-[#0E1525]/10",
    iconBg: "bg-[#0E8C5C]",
    iconFg: "text-white",
    title: "text-[#0E1525]",
    subtitle: "text-[#0E1525]/60"
  };
  return <div className={`absolute top-[60px] left-4 right-4 z-50 px-3.5 py-3 rounded-2xl border shadow-[0_16px_32px_-10px_rgba(0,0,0,0.25)] flex items-center gap-3 ${styles.bg} ${styles.border}`} style={{
    animation: toast.exiting ? "ml-toast-out 240ms cubic-bezier(.4,0,.7,.2) forwards" : "ml-toast-in 320ms cubic-bezier(.16,1,.3,1)"
  }}>
      <div className={`w-[34px] h-[34px] rounded-full flex items-center justify-center flex-shrink-0 ${styles.iconBg} ${styles.iconFg}`}>
        <svg className="w-[18px] h-[18px]" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.6" strokeLinecap="round" strokeLinejoin="round"><path d="M5 12l4 4L19 7" /></svg>
      </div>
      <div className="flex-1 min-w-0">
        <div className={`text-[13px] font-bold leading-tight ${styles.title}`}>Funds received</div>
        <div className={`text-xs mt-0.5 leading-snug ${styles.subtitle}`}>{fmtMoney(toast.amount, currency)} added via bank transfer</div>
      </div>
      <button onClick={onDismiss} aria-label="Dismiss" className={`bg-transparent border-0 cursor-pointer p-1 flex ${styles.subtitle}`}>
        <IcoX />
      </button>
    </div>;
};

export const fmtMoney = (n, currency = "GBP") => {
  const sym = currency === "USD" ? "$" : currency === "EUR" ? "€" : "£";
  return sym + Number(n).toLocaleString("en-US", {
    minimumFractionDigits: 2,
    maximumFractionDigits: 2
  });
};

export const WidgetFlow = ({onBack, onBankClose, onCryptoClose, onSelectCard, onSelectBankAccount, currency = "GBP", dark = false, bankDark = false, mode = "deposit", partner = "meridian"}) => {
  const [screen, setScreen] = useState("method");
  const [dir, setDir] = useState("fwd");
  const [cryptoAsset, setCryptoAsset] = useState(null);
  const [cryptoWithdrawal, setCryptoWithdrawal] = useState({
    asset: null,
    address: "",
    tag: ""
  });
  const go = (s, d = "fwd") => {
    setDir(d);
    setScreen(s);
  };
  const isWithdraw = mode === "withdraw";
  let body;
  if (screen === "method") {
    body = <WidgetSelectMethod key="method" onPickCard={() => go("cards")} onPickBank={() => go("bank")} onPickCrypto={() => go(isWithdraw ? "crypto-withdrawal" : "crypto-select")} onBack={onBack} dark={dark} mode={mode} />;
  } else if (screen === "cards") {
    body = <WidgetSelectCard key="cards" onBack={() => go("method", "back")} onSelectCard={onSelectCard} currency={currency} dark={dark} />;
  } else if (screen === "bank") {
    if (isWithdraw && partner === "lumen") {
      body = <WidgetSelectBankAccount key="bank-list" onBack={() => go("method", "back")} onSelectBankAccount={onSelectBankAccount} dark={dark} />;
    } else if (isWithdraw && (partner === "meridian" || partner === "vault")) {
      const single = partner === "vault" ? [{
        id: "eur-default",
        name: "EUR bank account",
        currency: "EUR"
      }] : [{
        id: "gbp-default",
        name: "GBP bank account",
        currency: "GBP"
      }];
      body = <WidgetSelectBankAccount key="bank-single" onBack={() => go("method", "back")} onSelectBankAccount={onSelectBankAccount} accounts={single} variant="single" dark={dark || bankDark} />;
    } else {
      body = <WidgetBankTransfer key="bank" onBack={() => go("method", "back")} onClose={onBankClose || onBack} dark={dark || bankDark} region={currency === "USD" ? "US" : currency === "EUR" ? "EU" : "GB"} />;
    }
  } else if (screen === "crypto-select") {
    body = <WidgetCryptoSelect key="crypto-select" onBack={() => {
      setCryptoAsset(null);
      go("method", "back");
    }} asset={cryptoAsset} onPickAsset={() => go("crypto-asset-list")} onContinue={() => go("crypto-address")} dark={dark} />;
  } else if (screen === "crypto-asset-list") {
    body = <WidgetCryptoAssetList key="crypto-asset-list" onClose={() => go("crypto-select", "back")} onSelect={id => {
      setCryptoAsset(id);
      go("crypto-select", "back");
    }} dark={dark} />;
  } else if (screen === "crypto-address") {
    body = <WidgetCryptoAddress key="crypto-address" onBack={() => go("crypto-select", "back")} onClose={onCryptoClose || onBack} dark={dark} />;
  } else if (screen === "crypto-withdrawal") {
    const handleCryptoWithdrawalContinue = () => {
      const addr = cryptoWithdrawal.address || "bc1q4jcyq5ne9qwdnp88xddc4ej02ja9c";
      const truncAddr = addr.length > 14 ? `${addr.slice(0, 6)}…${addr.slice(-4)}` : addr;
      setCryptoWithdrawal({
        asset: null,
        address: "",
        tag: ""
      });
      onSelectBankAccount && onSelectBankAccount({
        id: "crypto-BTC",
        name: "Bitcoin network",
        currency: truncAddr,
        cryptoAssetId: "BTC"
      });
    };
    body = <WidgetCryptoWithdrawal key="crypto-withdrawal" state={cryptoWithdrawal} setState={setCryptoWithdrawal} onBack={() => {
      setCryptoWithdrawal({
        asset: null,
        address: "",
        tag: ""
      });
      go("method", "back");
    }} onPickAsset={() => go("crypto-asset-list-wd")} onContinue={handleCryptoWithdrawalContinue} dark={dark} />;
  } else if (screen === "crypto-asset-list-wd") {
    body = <WidgetCryptoAssetList key="crypto-asset-list-wd" onClose={() => go("crypto-withdrawal", "back")} onSelect={id => {
      setCryptoWithdrawal(s => ({
        ...s,
        asset: id
      }));
      go("crypto-withdrawal", "back");
    }} dark={dark} />;
  }
  return <div className={`flex-1 flex flex-col min-h-0 relative ${dark ? "bg-[#0E1116]" : ""}`}>
      <div key={screen} className="flex-1 flex flex-col min-h-0" style={{
    animation: dir === "fwd" ? "ml-anim-fwd 280ms cubic-bezier(.16,1,.3,1)" : "ml-anim-back 280ms cubic-bezier(.16,1,.3,1)"
  }}>
        {body}
      </div>
    </div>;
};

export const WToast = ({msg}) => <div className="absolute left-5 right-5 top-[70px] px-4 py-3.5 rounded-xl text-sm font-semibold text-white bg-[#39a854] shadow-[0_12px_24px_-6px_rgba(0,0,0,0.3)] z-[100]" style={{
  animation: "ml-toast-in 300ms cubic-bezier(.16,1,.3,1)"
}}>{msg}</div>;

export const WidgetCryptoWithdrawal = ({state, setState, onBack, onPickAsset, onContinue, dark}) => {
  const {asset, address, tag} = state;
  const hasAsset = asset === "BTC";
  const surfaceText = dark ? "text-white" : "text-[#0E1525]";
  const muted = dark ? "text-white/55" : "text-[#0E1525]/55";
  return <div className={`flex-1 flex flex-col min-h-0 ${dark ? "bg-[#0E1116] text-white" : "bg-[#f4f4f5] text-[#0E1525]"}`}>
      <WTopBar onBack={onBack} dark={dark} />
      <div className="flex-1 px-5 pt-1 overflow-y-auto">
        <h1 className="m-0 mb-6 text-[26px] font-bold tracking-tight leading-[1.15]" style={{
    color: dark ? "#ffffff" : "#0E1525"
  }}>Withdrawal details</h1>

        <div className={`text-[14px] font-bold mb-2 ${surfaceText}`}>Crypto asset</div>
        <button onClick={onPickAsset} className={`w-full flex items-center gap-2.5 px-3.5 py-3 rounded-xl border-[1.5px] mb-4 cursor-pointer text-left transition-colors ${dark ? "border-white/20 bg-white/[0.04] hover:bg-white/[0.08]" : "border-[#0E1525]/20 bg-white hover:bg-black/[0.03]"}`}>
          {hasAsset && <CryptoMark id="BTC" sm />}
          <div className={`flex-1 min-w-0 text-[15px] ${hasAsset ? surfaceText : muted}`}>
            {hasAsset ? "Bitcoin" : "Select a crypto asset"}
          </div>
          <CryptoFieldChevron dark={dark} />
        </button>

        <div className={`text-[14px] font-bold mb-2 ${hasAsset ? surfaceText : dark ? "text-white/40" : "text-[#0E1525]/35"}`}>Network</div>
        <div className={`w-full flex items-center gap-2.5 px-3.5 py-3 rounded-xl border-[1.5px] cursor-default ${hasAsset ? dark ? "border-white/20 bg-white/[0.04]" : "border-[#0E1525]/20 bg-white" : dark ? "border-white/15 bg-white/[0.02]" : "border-[#0E1525]/15 bg-white"} ${hasAsset ? "" : "mb-4"}`}>
          {hasAsset && <CryptoMark id="BTC" sm />}
          <div className={`flex-1 min-w-0 text-[15px] ${hasAsset ? surfaceText : dark ? "text-white/30" : "text-[#0E1525]/30"}`}>
            {hasAsset ? "Bitcoin network" : "Select a network"}
          </div>
          <CryptoFieldChevron dark={dark} dim={!hasAsset} />
        </div>

        {hasAsset && <>
            <div className={`text-[14px] font-bold mb-2 mt-4 ${surfaceText}`}>Wallet address</div>
            <div className={`flex items-center px-3.5 py-3 rounded-xl border-[1.5px] mb-4 ${dark ? "border-white/20 bg-white/[0.04]" : "border-[#0E1525]/20 bg-white"}`}>
              <input value={address} onChange={e => setState(s => ({
    ...s,
    address: e.target.value
  }))} placeholder="e.g. bc1q4jcyq5ne9qwdnp88xddc4ej02ja9c..." className={`flex-1 min-w-0 bg-transparent border-0 outline-none text-[15px] font-sans ${dark ? "text-white placeholder:text-white/45" : "text-[#0E1525] placeholder:text-[#0E1525]/45"}`} />
            </div>

            <div className={`text-[14px] font-bold mb-2 ${surfaceText}`}>Destination tag (if required)</div>
            <div className={`flex items-center px-3.5 py-3 rounded-xl border-[1.5px] mb-2 ${dark ? "border-white/20 bg-white/[0.04]" : "border-[#0E1525]/20 bg-white"}`}>
              <input value={tag} onChange={e => setState(s => ({
    ...s,
    tag: e.target.value
  }))} placeholder="e.g. 1234567890" className={`flex-1 min-w-0 bg-transparent border-0 outline-none text-[15px] font-sans ${dark ? "text-white placeholder:text-white/45" : "text-[#0E1525] placeholder:text-[#0E1525]/45"}`} />
            </div>
            <div className={`text-[12px] ${muted}`}>
              Enter the destination tag if required. <span className={`underline ${surfaceText}`}>Learn more</span>
            </div>
          </>}
      </div>
      <div className="px-5 pt-3 pb-2 flex-shrink-0">
        <button onClick={onContinue} className={`w-full border-0 rounded-full text-[15px] font-bold cursor-pointer transition-colors ${dark ? "bg-white text-[#0E1525] hover:bg-white/90" : "bg-[#0E1525] text-white hover:bg-[#0E1525]/90"}`} style={{
    height: "3rem",
    padding: 0
  }}>
          Continue
        </button>
      </div>
      <WFooter dark={dark} />
    </div>;
};

export const WidgetCryptoAddress = ({onBack, onClose, dark}) => {
  const address = "bc1q4jcyq5ne9qwdnp88xddc4ej02ja9c";
  const surfaceText = dark ? "text-white" : "text-[#0E1525]";
  const muted = dark ? "text-white/55" : "text-[#0E1525]/55";
  const stronger = dark ? "text-white/75" : "text-[#0E1525]/70";
  const [copied, setCopied] = useState(false);
  const handleCopy = () => {
    if (typeof navigator !== "undefined" && navigator.clipboard) {
      navigator.clipboard.writeText(address + "...").catch(() => {});
    }
    setCopied(true);
    setTimeout(() => setCopied(false), 1400);
  };
  return <div className={`flex-1 flex flex-col min-h-0 overflow-y-auto ${dark ? "bg-[#0E1116] text-white" : "bg-[#f4f4f5] text-[#0E1525]"}`}>
      <div className="flex items-center gap-3 px-5 pt-4 pb-3 flex-shrink-0">
        <button onClick={onBack} className={`w-10 h-10 rounded-full border-0 flex items-center justify-center cursor-pointer ${dark ? "bg-white/10 text-white" : "bg-black/5 text-[#0E1525]"}`}><IcoBack /></button>
        <div className={`flex-1 text-center pr-10 text-[17px] font-semibold ${surfaceText}`}>BTC crypto address</div>
      </div>
      <div className="px-5 pt-1">
        <h1 className="mt-5 mb-1 text-[26px] font-bold tracking-tight leading-[1.15]" style={{
    color: dark ? "#ffffff" : "#0E1525"
  }}>Deposit Bitcoin</h1>
        <div className={`flex items-center gap-2 text-[13px] ${muted}`}>
          <span>via</span>
          <CryptoMark id="BTC" sm />
          <span className={`font-semibold ${surfaceText}`}>Bitcoin network</span>
        </div>

        <div className="flex justify-center my-5">
          <div className="bg-white p-3 rounded-xl">
            <QrCode />
          </div>
        </div>

        <div className={`flex items-start gap-3 p-3.5 rounded-xl border mb-4 ${dark ? "bg-[#3a2e08]/60 border-[#F5C24D]/50" : "bg-[#FFF4DC] border-[#F5C24D]"}`}>
          <div className={`flex-shrink-0 w-7 flex items-center justify-center ${dark ? "text-[#F5C24D]" : "text-[#A06800]"}`}>
            <svg className="w-5 h-5" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
              <path d="M10.29 3.86L1.82 18a2 2 0 001.71 3h16.94a2 2 0 001.71-3L13.71 3.86a2 2 0 00-3.42 0z" /><line x1="12" y1="9" x2="12" y2="13" /><line x1="12" y1="17" x2="12.01" y2="17" />
            </svg>
          </div>
          <div className={`text-[13px] leading-normal ${dark ? "text-[#F5DA9C]" : "text-[#0E1525]"}`}>Only Bitcoin can be sent to this address using the Bitcoin network.</div>
        </div>

        <div className="flex items-start justify-between gap-3 py-2">
          <div className="flex-1 min-w-0">
            <div className={`text-[14px] font-bold ${surfaceText}`}>BTC wallet address</div>
            <div className={`text-[13px] mt-1 ${stronger}`} style={{
    fontFamily: "Menlo, monospace",
    overflow: "hidden",
    textOverflow: "ellipsis",
    whiteSpace: "nowrap"
  }}>{address}…</div>
          </div>
          <button onClick={handleCopy} className={`flex-shrink-0 mt-1 cursor-pointer bg-transparent border-0 ${copied ? "text-[#35B13D]" : muted}`}>
            <span key={copied ? "check" : "copy"} className="ml-copy-pop inline-flex">
              {copied ? <svg className="w-5 h-5" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.4" strokeLinecap="round" strokeLinejoin="round"><polyline points="20 6 9 17 4 12" /></svg> : <IcoCopy />}
            </span>
          </button>
        </div>
        <div className="flex items-center justify-between gap-3 py-2">
          <div className={`text-[14px] font-bold ${surfaceText}`}>Receiving account</div>
          <div className={`flex items-center gap-2 text-[14px] ${stronger}`}>
            <CryptoMark id="BTC" sm />
            <span>BTC account</span>
          </div>
        </div>
        <div className="flex items-center justify-between gap-3 py-2 pb-3">
          <div className={`text-[14px] font-bold ${surfaceText}`}>Processing time</div>
          <div className={`text-[14px] ${stronger}`}>30 minutes</div>
        </div>
      </div>
      <div className="px-5 pt-1 pb-2 flex-shrink-0">
        <button onClick={onClose} className={`w-full border-[1.5px] rounded-full text-[15px] font-bold cursor-pointer transition-colors bg-transparent ${dark ? "border-white text-white hover:bg-white/10" : "border-[#0E1525] text-[#0E1525] hover:bg-black/5"}`} style={{
    height: "3rem",
    padding: 0
  }}>
          Close
        </button>
      </div>
      <WFooter dark={dark} />
    </div>;
};

export const WidgetCryptoAssetList = ({onClose, onSelect, dark}) => <div className={`flex-1 flex flex-col min-h-0 ${dark ? "bg-[#0E1116] text-white" : "bg-[#f4f4f5] text-[#0E1525]"}`}>
    <div className="flex items-center gap-3 px-5 pt-4 pb-3 flex-shrink-0">
      <button onClick={onClose} className={`w-10 h-10 rounded-full border-0 flex items-center justify-center cursor-pointer ${dark ? "bg-white/10 text-white" : "bg-black/5 text-[#0E1525]"}`}>
        <svg className="w-5 h-5" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round"><polyline points="6 9 12 15 18 9" /></svg>
      </button>
      <div className={`flex-1 text-center pr-10 text-[17px] font-semibold ${dark ? "text-white" : "text-[#0E1525]"}`}>Select a crypto asset</div>
    </div>
    <div className="px-5 pt-1 flex-shrink-0">
      <div className={`flex items-center gap-2.5 px-3.5 py-2.5 rounded-full ${dark ? "bg-white/[0.06]" : "bg-black/[0.05]"}`}>
        <svg className={`w-4 h-4 flex-shrink-0 ${dark ? "text-white/55" : "text-[#0E1525]/45"}`} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round">
          <circle cx="11" cy="11" r="7" /><line x1="21" y1="21" x2="16.65" y2="16.65" />
        </svg>
        <input value="" readOnly placeholder="Search assets" className={`flex-1 min-w-0 bg-transparent border-0 outline-none text-[14px] font-sans cursor-default ${dark ? "text-white placeholder:text-white/45" : "text-[#0E1525] placeholder:text-[#0E1525]/45"}`} />
      </div>
    </div>
    <div className="flex-1 px-5 pt-3 pb-1 overflow-y-auto">
      {CRYPTO_ASSETS.map(a => <button key={a.id} onClick={a.selectable ? () => onSelect(a.id) : undefined} className={`${a.selectable ? "ml-pill-pulse rounded-2xl " : ""}flex items-center gap-3 w-full px-2 py-2.5 border-0 bg-transparent text-left ${a.selectable ? "cursor-pointer" : "cursor-default"}`}>
          <div className="relative">
            <CryptoMark id={a.id} />
            {a.unavailable && <div className="absolute -bottom-0.5 -right-0.5 w-[18px] h-[18px] rounded-full flex items-center justify-center" style={{
  background: dark ? "#0E1116" : "#f4f4f5"
}}>
                <svg width="14" height="14" viewBox="0 0 14 14" fill="none">
                  <circle cx="7" cy="7" r="5" fill={dark ? "#3A3D42" : "#9FA3AB"} />
                  <line x1="3.6" y1="10.4" x2="10.4" y2="3.6" stroke="#fff" strokeWidth="1.4" strokeLinecap="round" />
                </svg>
              </div>}
          </div>
          <div className="flex-1 min-w-0">
            <div className="flex items-baseline gap-1.5">
              <span className={`text-[15px] font-bold ${dark ? "text-white" : "text-[#0E1525]"}`}>{a.name}</span>
              <span className={`text-[14px] ${dark ? "text-white/45" : "text-[#0E1525]/45"}`}>{a.symbol}</span>
            </div>
            <div className={`text-[13px] mt-0.5 ${dark ? "text-white/55" : "text-[#0E1525]/55"}`}>{a.sub}</div>
          </div>
        </button>)}
    </div>
    <WFooter dark={dark} />
  </div>;

export const WidgetCryptoSelect = ({onBack, asset, onPickAsset, onContinue, dark}) => {
  const hasAsset = asset === "BTC";
  return <div className={`flex-1 flex flex-col min-h-0 ${dark ? "bg-[#0E1116] text-white" : "bg-[#f4f4f5] text-[#0E1525]"}`}>
      <WTopBar onBack={onBack} dark={dark} />
      <div className="flex-1 px-5 pt-1 overflow-y-auto">
        <h1 className={`mt-5 mb-6 text-[26px] font-bold tracking-tight leading-[1.15] ${dark ? "text-white" : "text-[#0E1525]"}`}>Select a crypto asset and network</h1>

        <div className={`text-[14px] font-bold mb-2 ${dark ? "text-white" : "text-[#0E1525]"}`}>Crypto asset</div>
        <button onClick={onPickAsset} className={`w-full flex items-center gap-2.5 px-3.5 py-3 rounded-xl border-[1.5px] mb-4 cursor-pointer text-left transition-colors ${dark ? "border-white/20 bg-white/[0.04] hover:bg-white/[0.08]" : "border-[#0E1525]/20 bg-white hover:bg-black/[0.03]"}`}>
          {hasAsset && <CryptoMark id="BTC" sm />}
          <div className={`flex-1 min-w-0 text-[15px] ${hasAsset ? dark ? "text-white" : "text-[#0E1525]" : dark ? "text-white/55" : "text-[#0E1525]/55"}`}>
            {hasAsset ? "Bitcoin" : "Select a crypto asset"}
          </div>
          <CryptoFieldChevron dark={dark} />
        </button>

        <div className={`text-[14px] font-bold mb-2 ${hasAsset ? dark ? "text-white" : "text-[#0E1525]" : dark ? "text-white/40" : "text-[#0E1525]/35"}`}>Network</div>
        <div className={`w-full flex items-center gap-2.5 px-3.5 py-3 rounded-xl border-[1.5px] cursor-default ${dark ? "border-white/15 bg-white/[0.02]" : "border-[#0E1525]/15 bg-transparent"}`}>
          {hasAsset && <CryptoMark id="BTC" sm />}
          <div className={`flex-1 min-w-0 text-[15px] ${hasAsset ? dark ? "text-white" : "text-[#0E1525]" : dark ? "text-white/30" : "text-[#0E1525]/30"}`}>
            {hasAsset ? "Bitcoin network" : "Select a network"}
          </div>
          <CryptoFieldChevron dark={dark} dim />
        </div>
      </div>
      <div className="px-5 pt-3 pb-2 flex-shrink-0">
        <button onClick={hasAsset ? onContinue : undefined} disabled={!hasAsset} className={`w-full border-0 rounded-full text-[15px] font-bold transition-colors ${hasAsset ? "cursor-pointer" : "cursor-not-allowed"} ${dark ? hasAsset ? "bg-white text-[#0E1525] hover:bg-white/90" : "bg-white/30 text-[#0E1525]/60" : hasAsset ? "bg-[#0E1525] text-white hover:bg-[#0E1525]/90" : "bg-[#0E1525]/40 text-white"}`} style={{
    height: "3rem",
    padding: 0
  }}>
          Continue
        </button>
      </div>
      <WFooter dark={dark} />
    </div>;
};

export const CRYPTO_ASSETS = [{
  id: "BTC",
  name: "Bitcoin",
  symbol: "BTC",
  glyph: "₿",
  bg: "#F7931A",
  fg: "#fff",
  sub: "Bitcoin network",
  selectable: true
}, {
  id: "ETH",
  name: "Ethereum",
  symbol: "ETH",
  glyph: "Ξ",
  bg: "#627EEA",
  fg: "#fff",
  sub: "Multiple networks",
  selectable: false
}, {
  id: "XRP",
  name: "XRP",
  symbol: "XRP",
  glyph: "✕",
  bg: "#23292F",
  fg: "#fff",
  sub: "XRP Ledger network",
  selectable: false,
  unavailable: true
}, {
  id: "SOL",
  name: "Solana",
  symbol: "SOL",
  glyph: "◎",
  bg: "#9945FF",
  fg: "#fff",
  sub: "Solana network",
  selectable: false
}, {
  id: "DOGE",
  name: "Dogecoin",
  symbol: "DOGE",
  glyph: "Ð",
  bg: "#C2A633",
  fg: "#fff",
  sub: "Dogecoin network",
  selectable: false
}, {
  id: "ADA",
  name: "Cardano",
  symbol: "ADA",
  glyph: "◉",
  bg: "#0033AD",
  fg: "#fff",
  sub: "Cardano network",
  selectable: false
}, {
  id: "LINK",
  name: "Chainlink",
  symbol: "LINK",
  glyph: "⬡",
  bg: "#2A5ADA",
  fg: "#fff",
  sub: "Ethereum network",
  selectable: false
}, {
  id: "BNB",
  name: "BNB",
  symbol: "BNB",
  glyph: "✶",
  bg: "#0E0E10",
  fg: "#fff",
  sub: "BNB Smart Chain network",
  selectable: false
}];

export const CryptoFieldChevron = ({dark, dim}) => <svg className={`w-4 h-4 flex-shrink-0 ${dim ? dark ? "text-white/30" : "text-[#0E1525]/30" : dark ? "text-white/60" : "text-[#0E1525]/55"}`} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round"><polyline points="6 9 12 15 18 9" /></svg>;

export const QrCode = () => {
  const N = 25;
  const M = 4;
  const grid = Array.from({
    length: N
  }, () => Array(N).fill(false));
  const finder = (oy, ox) => {
    for (let y = 0; y < 7; y++) for (let x = 0; x < 7; x++) {
      const isOuter = y === 0 || y === 6 || x === 0 || x === 6;
      const isCore = y >= 2 && y <= 4 && x >= 2 && x <= 4;
      grid[oy + y][ox + x] = isOuter || isCore;
    }
  };
  finder(0, 0);
  finder(0, 18);
  finder(18, 0);
  const align = (oy, ox) => {
    for (let y = 0; y < 5; y++) for (let x = 0; x < 5; x++) {
      const isOuter = y === 0 || y === 4 || x === 0 || x === 4;
      const isCenter = y === 2 && x === 2;
      grid[oy + y][ox + x] = isOuter || isCenter;
    }
  };
  align(16, 16);
  for (let i = 8; i < 17; i++) {
    grid[6][i] = i % 2 === 0;
    grid[i][6] = i % 2 === 0;
  }
  let s = 0x1ABE7;
  const next = () => {
    s = s * 1664525 + 1013904223 >>> 0;
    return s & 1;
  };
  for (let y = 0; y < N; y++) for (let x = 0; x < N; x++) {
    if (y < 8 && x < 8 || y < 8 && x >= 17 || y >= 17 && x < 8) continue;
    if (y >= 16 && y <= 20 && x >= 16 && x <= 20) continue;
    if (y === 6 || x === 6) continue;
    grid[y][x] = next() === 1;
  }
  const cells = [];
  for (let y = 0; y < N; y++) for (let x = 0; x < N; x++) {
    if (grid[y][x]) cells.push(<rect key={`${y}-${x}`} x={x * M} y={y * M} width={M} height={M} fill="#000" />);
  }
  return <svg width="160" height="160" viewBox="0 0 100 100" shapeRendering="crispEdges">
      <rect width="100" height="100" fill="#fff" />
      {cells}
    </svg>;
};

export const CryptoMark = ({id, sm}) => {
  const a = CRYPTO_ASSETS.find(x => x.id === id);
  if (!a) return null;
  const size = sm ? 22 : 36;
  return <div className="rounded-full flex items-center justify-center flex-shrink-0" style={{
    width: size,
    height: size,
    background: a.bg,
    color: a.fg,
    fontSize: sm ? 12 : 18,
    fontWeight: 800,
    lineHeight: 1
  }}>
      {a.glyph}
    </div>;
};

export const WidgetBankTransfer = ({onBack, onClose, dark = false, region = "GB"}) => {
  const headerBgStyle = {
    backgroundColor: dark ? "#1c1f24" : "#F2F2F2"
  };
  const detailsBgStyle = {
    backgroundColor: dark ? "#23262c" : "#EBEBF1"
  };
  const textStyle = {
    color: dark ? "white" : "#0E1525"
  };
  const mutedStyle = {
    color: dark ? "rgba(255,255,255,0.6)" : "rgba(14,21,37,0.6)"
  };
  const subtleStyle = {
    color: dark ? "rgba(255,255,255,0.55)" : "rgba(14,21,37,0.55)"
  };
  const infoBgStyle = {
    backgroundColor: dark ? "rgba(44,80,180,0.3)" : "#DFEAFD"
  };
  const infoTextStyle = {
    color: dark ? "rgba(255,255,255,0.9)" : "#0E1525"
  };
  const infoStrokeStyle = {
    borderColor: dark ? "rgba(255,255,255,0.85)" : "#0E1525",
    color: dark ? "rgba(255,255,255,0.85)" : "#0E1525"
  };
  const closeBtnStyle = {
    backgroundColor: dark ? "white" : "#0E1525",
    color: dark ? "#0E1525" : "white"
  };
  const dividerStyle = {
    backgroundColor: dark ? "rgba(255,255,255,0.05)" : "rgba(14,21,37,0.05)"
  };
  return <div className="flex-1 flex flex-col min-h-0 overflow-y-auto" style={{
    ...headerBgStyle,
    ...textStyle
  }}>
      <div className="flex items-center gap-3 px-5 pt-4 pb-3 flex-shrink-0">
        <button onClick={onBack} className="w-10 h-10 rounded-full border-0 flex items-center justify-center cursor-pointer" style={{
    backgroundColor: dark ? "rgba(255,255,255,0.1)" : "rgba(14,21,37,0.1)",
    color: dark ? "white" : "#0E1525"
  }}><IcoBack /></button>
        <div className="flex-1 text-center pr-10 text-[17px] font-semibold" style={textStyle}>Bank transfer details</div>
      </div>
      <div className="px-5 pt-1">
        <h1 className="mt-2 mb-2 text-[24px] font-bold tracking-tight leading-[1.15]" style={textStyle}>You're ready to transfer funds</h1>
        <div className="text-[13px] mb-4 leading-snug" style={mutedStyle}>Copy the details below and enter them in your banking app.</div>
        <div className="flex items-start gap-3 p-3.5 rounded-2xl mb-4" style={infoBgStyle}>
          <div className="w-[22px] h-[22px] rounded-full border-[1.5px] flex items-center justify-center flex-shrink-0" style={infoStrokeStyle}><IcoInfoSm /></div>
          {region === "US" ? <div className="text-[14px] leading-snug" style={infoTextStyle}>You must deposit from a US bank account 🇺🇸 in the name of John Smith.</div> : region === "EU" ? <div className="text-[14px] leading-snug" style={infoTextStyle}>You must deposit from a euro bank account 🇪🇺 in the name of John Smith.</div> : <div className="text-[14px] leading-snug" style={infoTextStyle}>You must deposit from a pound sterling bank account 🇬🇧 in the name of John Smith.</div>}
        </div>
        {region !== "US" && <>
            <div className="text-sm font-bold mb-2" style={textStyle}>To</div>
            <div className="flex items-center gap-2.5 px-3.5 py-3 rounded-xl border-[1.5px] mb-4" style={{
    borderColor: dark ? "rgba(255,255,255,0.2)" : "rgba(14,21,37,0.2)"
  }}>
              <div style={{
    width: 24,
    height: 24,
    borderRadius: "50%",
    overflow: "hidden",
    flexShrink: 0,
    clipPath: "circle(50%)"
  }}>
                {region === "EU" ? <svg width="24" height="24" viewBox="0 0 40 40">
                    <defs>
                      <linearGradient id="mlEurcGrad" x1="0" y1="0" x2="1" y2="1">
                        <stop offset="0%" stopColor="#3F8EFF" /><stop offset="100%" stopColor="#1F4FB8" />
                      </linearGradient>
                    </defs>
                    <circle cx="20" cy="20" r="20" fill="url(#mlEurcGrad)" />
                    <path d="M22.5 11.5c-3.4 0-6.2 2-7.4 5.2h-2v1.7h1.6c-.05.4-.07.8-.07 1.2 0 .42.03.83.08 1.23h-1.6v1.7h2c1.2 3.2 4 5.2 7.4 5.2 1.6 0 3-.42 4.1-1.18l-1.4-1.45c-.78.5-1.7.78-2.7.78-2.4 0-4.4-1.4-5.3-3.45h5v-1.7h-5.42c-.06-.4-.1-.81-.1-1.23 0-.41.04-.81.1-1.2h5.42v-1.7h-5c.9-2.05 2.9-3.45 5.3-3.45 1.05 0 1.95.27 2.7.78l1.4-1.45c-1.1-.76-2.5-1.18-4.13-1.18z" fill="#fff" />
                  </svg> : <svg width="24" height="24" viewBox="0 0 60 40" preserveAspectRatio="xMidYMid slice">
                    <rect width="60" height="40" fill="#012169" />
                    <path d="M0,0 L60,40 M60,0 L0,40" stroke="#fff" strokeWidth="6" />
                    <path d="M0,0 L60,40 M60,0 L0,40" stroke="#C8102E" strokeWidth="2.4" />
                    <path d="M30,0 V40 M0,20 H60" stroke="#fff" strokeWidth="10" />
                    <path d="M30,0 V40 M0,20 H60" stroke="#C8102E" strokeWidth="5" />
                  </svg>}
              </div>
              <div className="flex-1 text-sm" style={{
    color: dark ? "rgba(255,255,255,0.75)" : "rgba(14,21,37,0.6)"
  }}>{region === "EU" ? "EUROC account" : "My GBP account"}</div>
              <svg className="w-4 h-4" style={{
    color: dark ? "rgba(255,255,255,0.6)" : "rgba(14,21,37,0.55)"
  }} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round"><polyline points="6 9 12 15 18 9" /></svg>
            </div>
          </>}
      </div>
      <div className="px-5 py-4 flex-1" style={detailsBgStyle}>
        {region === "GB" || region === "EU" ? <>
            <div className="mb-3.5">
              <div className="text-sm mb-2" style={{
    ...textStyle,
    fontWeight: 500
  }}>Account reference code</div>
              <div className="flex items-center" style={{
    gap: "0.25rem"
  }}>
                {["U", "H", "3", "A", "3", "9", "D", "A", "8", "2"].map((c, i) => <RefChip key={i} ch={c} dark={dark} />)}
                <button className="ml-auto bg-transparent border-0 cursor-pointer p-1" style={mutedStyle}><IcoCopy /></button>
              </div>
              <div className="text-[13px] mt-2 leading-snug" style={subtleStyle}>You must include this reference code in the bank transfer description. <u style={textStyle}>Why do I need it?</u></div>
            </div>
            <div className="h-px my-1.5" style={dividerStyle} />
            <BTField label="Beneficiary" value="LHV BANK LIMITED" info dark={dark} />
            <BTField label="Sort code" value="04-03-15" info mono dark={dark} />
            <BTField label="Account number" value="00000728" info mono dark={dark} />
            <BTField label="Bank name" value="LHV BANK LIMITED" dark={dark} />
            <BTField label="Bank address" value={"One Angel Court\nLondon, United\nKingdom, EC2R 7HJ"} dark={dark} />
          </> : <>
            <BTField label="Beneficiary" value="Us Business Llc" info dark={dark} />
            <BTField label="Routing number" value="021214891" info mono dark={dark} />
            <BTField label="Account number" value="351954843592" info mono dark={dark} />
            <div className="py-3.5">
              <div className="text-sm font-bold mb-1" style={textStyle}>Account type</div>
              <div className="text-sm" style={subtleStyle}>Checking</div>
            </div>
            <BTField label="Bank name" value="Cross River Bank" dark={dark} />
            <BTField label="Bank address" value={"885 Teaneck Rd\nTeaneck, NJ 07666"} dark={dark} />
          </>}
      </div>
      <div className="px-5 pt-1 flex-shrink-0" style={headerBgStyle}>
        {region === "US" && <div className="flex items-start justify-between py-3.5 gap-4">
            <div className="text-sm font-bold pt-0.5" style={textStyle}>Destination</div>
            <div className="flex items-center gap-2 text-sm" style={mutedStyle}>
              <UsFlag /><span>USD Bank Account</span>
            </div>
          </div>}
        <div className="flex items-start justify-between py-3.5 gap-4">
          <div className="text-sm font-bold pt-0.5" style={textStyle}>Processing time</div>
          <div className="text-sm text-right max-w-[220px] leading-snug" style={mutedStyle}>{region === "US" ? "Up to 2 business days (ACH and Instant ACH)" : "Instant"}</div>
        </div>
      </div>
      <div className="px-5 pt-1 pb-4 flex-shrink-0" style={headerBgStyle}>
        <button onClick={onClose} className="w-full border-0 rounded-full text-[15px] font-bold cursor-pointer" style={{
    ...closeBtnStyle,
    height: "3rem",
    padding: 0
  }}>Close</button>
      </div>
      <div className="flex items-center justify-center gap-2.5 px-5 pt-1 pb-5 text-sm flex-shrink-0" style={{
    ...headerBgStyle,
    color: dark ? "rgba(255,255,255,0.55)" : "rgba(14,21,37,0.55)"
  }}>
        <LeafLogo /><div className="w-px h-3.5" style={{
    backgroundColor: dark ? "rgba(255,255,255,0.2)" : "rgba(14,21,37,0.15)"
  }} />
        <span>Powered by <strong style={textStyle}>Uphold</strong></span>
      </div>
    </div>;
};

export const BTField = ({label, value, info, mono, dark}) => <div className="flex items-start justify-between py-3.5 gap-3">
    <div className="flex-1 min-w-0">
      <div className="flex items-center gap-1.5 text-sm font-bold mb-1" style={{
  color: dark ? "white" : "#0E1525"
}}>
        {label}
        {info && <span className="w-4 h-4 rounded-full border-[1.2px] inline-flex items-center justify-center" style={{
  borderColor: dark ? "rgba(255,255,255,0.5)" : "rgba(14,21,37,0.55)",
  color: dark ? "rgba(255,255,255,0.65)" : "rgba(14,21,37,0.65)"
}}>
            <IcoInfoSm />
          </span>}
      </div>
      <div className={`text-sm whitespace-pre-line ${mono ? "font-mono" : ""}`} style={{
  color: dark ? "rgba(255,255,255,0.65)" : "rgba(14,21,37,0.55)"
}}>{value}</div>
    </div>
    <button className="bg-transparent border-0 cursor-pointer p-1 mt-0.5" style={{
  color: dark ? "rgba(255,255,255,0.7)" : "rgba(14,21,37,0.65)"
}}><IcoCopy /></button>
  </div>;

export const RefChip = ({ch, dark}) => <div className="rounded-lg font-bold flex items-center justify-center flex-shrink-0" style={{
  backgroundColor: dark ? "white" : "#0E1525",
  color: dark ? "#0E1525" : "white",
  fontFamily: "Menlo, monospace",
  fontSize: "1.25rem",
  lineHeight: "1.313rem",
  paddingInline: "0.375rem",
  paddingBlock: "0.25rem"
}}>{ch}</div>;

export const WidgetAddCard = ({onBack, onSubmit, dark}) => {
  const [num, setNum] = useState("4111 1111 1111 1111");
  const [exp, setExp] = useState("12/56");
  const [cvv, setCvv] = useState("123");
  const fmtNum = v => v.replace(/\D/g, "").slice(0, 16).replace(/(\d{4})(?=\d)/g, "$1 ");
  const fmtExp = v => {
    const d = v.replace(/\D/g, "").slice(0, 4);
    return d.length > 2 ? d.slice(0, 2) + "/" + d.slice(2) : d;
  };
  return <div className={`flex-1 flex flex-col min-h-0 ${dark ? "bg-[#0E1116] text-white" : "bg-[#f4f4f5] text-[#0E1525]"}`}>
      <WTopBar onBack={onBack} title="Add a credit or debit card" dark={dark} />
      <div className="flex-1 px-5 pt-1 overflow-hidden">
        <div className={`text-sm mb-5 ${dark ? "text-white/55" : "text-[#0E1525]/55"}`}>We only support Visa and Mastercard.</div>
        <WField label="Card number" leading={<div className="flex items-center justify-center bg-[#1a1f71] flex-shrink-0 w-6 h-6 rounded-full"><span className="text-white font-black italic tracking-tight text-[8px]" style={{
    fontFamily: "Arial, sans-serif"
  }}>VISA</span></div>} value={num} onChange={e => setNum(fmtNum(e.target.value))} placeholder="1234 5678 9012 3456" inputMode="numeric" dark={dark} />
        <div className="flex gap-3 mt-4">
          <WField label="Valid thru" value={exp} onChange={e => setExp(fmtExp(e.target.value))} placeholder="MM/YY" inputMode="numeric" dark={dark} />
          <WField label="CVV" value={cvv} onChange={e => setCvv(e.target.value.replace(/\D/g, "").slice(0, 4))} placeholder="123" inputMode="numeric" dark={dark} />
        </div>
        <div className="mt-5 flex flex-col gap-2.5">
          <WCallout icon={<UkFlag />} dark={dark}>Transactions on this card will be made in GBP. Bank or card issuer fees may apply.</WCallout>
          <WCalloutInfo icon={<IcoInfo />} dark={dark}>Your card may use Verified by Visa or Mastercard SecureCode for added protection, which might require you to enter a special code.</WCalloutInfo>
        </div>
      </div>
      <div className="px-5 pt-4 pb-10 flex-shrink-0">
        <button onClick={onSubmit} style={{
    height: "3rem",
    padding: 0
  }} className={`w-full border-0 rounded-full text-[15px] font-bold cursor-pointer transition-colors ${dark ? "bg-white text-[#0E1525] hover:bg-white/90" : "bg-[#0E1525] text-white hover:bg-[#0E1525]/90"}`}>Add card</button>
      </div>
    </div>;
};

export const WCallout = ({icon, children, dark}) => {
  if (dark) {
    return <div className="flex items-center gap-3 p-3.5 rounded-xl bg-[#2c50b4]/30">
        <div className="flex-shrink-0 flex items-center justify-center w-6 text-white/90">{icon}</div>
        <div className="text-[13px] leading-normal text-white/90">{children}</div>
      </div>;
  }
  return <div className="flex items-center gap-3 p-3.5 rounded-xl bg-white">
      <div className="flex-shrink-0 flex items-center justify-center w-6 text-[#0E1525]">{icon}</div>
      <div className="text-[13px] leading-normal text-[#0E1525]">{children}</div>
    </div>;
};

export const WField = ({label, value, onChange, placeholder, leading, inputMode, dark}) => <div className="flex-1 min-w-0">
    <label className={`block text-sm font-semibold mb-2 ${dark ? "text-white" : "text-[#0E1525]"}`}>{label}</label>
    <div className={`flex items-center gap-2.5 px-3.5 h-10 rounded-xl border-[1.5px] ${dark ? "border-white/20 bg-white/[0.04]" : "border-[#0E1525]/20"}`}>
      {leading && <div className="flex-shrink-0">{leading}</div>}
      <input value={value} onChange={onChange} placeholder={placeholder} inputMode={inputMode} className={`flex-1 min-w-0 border-0 outline-none bg-transparent text-[15px] font-sans ${dark ? "text-white" : "text-[#0E1525]"}`} />
    </div>
  </div>;

export const WidgetSelectBankAccount = ({onBack, onSelectBankAccount, onAddBankAccount, accounts = DEFAULT_BANK_ACCOUNTS, dark, variant = "multi"}) => {
  const isSingle = variant === "single";
  return <div className={`flex-1 flex flex-col min-h-0 ${dark ? "bg-[#0E1116] text-white" : "bg-[#f4f4f5] text-[#0E1525]"}`}>
      <WTopBar onBack={onBack} dark={dark} />
      <div className="flex-1 px-5 pt-1 overflow-hidden">
        <h1 className={`m-0 mb-3 text-[30px] font-bold tracking-tight ${dark ? "text-white" : "text-[#0E1525]"}`}>Select bank account</h1>
        {isSingle && <div className={`mb-5 w-full text-[13px] leading-[1.5rem] ${dark ? "text-white/55" : "text-[#0E1525]/55"}`}>
            To use a different account, first make a deposit from it. This links it for future withdrawals.
          </div>}
        <div className="flex flex-col gap-2.5">
          {accounts.map(acc => <BankRow key={acc.id} account={acc} onClick={() => onSelectBankAccount && onSelectBankAccount(acc)} dark={dark} />)}
          {!isSingle && <AddBankRow onClick={onAddBankAccount} dark={dark} />}
        </div>
      </div>
      <WFooter dark={dark} />
    </div>;
};

export const DEFAULT_BANK_ACCOUNTS = [{
  id: "chase",
  name: "Chase Checking",
  currency: "USD"
}, {
  id: "wells",
  name: "Wells Fargo Savings",
  currency: "USD"
}, {
  id: "boa",
  name: "Bank of America Checking",
  currency: "USD"
}, {
  id: "citi",
  name: "Citi Priority",
  currency: "USD"
}];

export const AddBankRow = ({onClick, dark}) => <button onClick={onClick} className={`flex h-[72px] items-center gap-3.5 w-full px-4 py-3.5 border-0 rounded-2xl text-left cursor-pointer transition-colors ${dark ? "bg-white/[0.04] hover:bg-white/[0.08]" : "bg-white hover:bg-white/80"}`}>
    <div className={`w-10 h-10 rounded-full flex items-center justify-center flex-shrink-0 ${dark ? "bg-[#3A3D42] text-white" : "bg-black/5 text-[#0E1525]"}`}><IcoPlus /></div>
    <div>
      <div className={`text-[14px] leading-[1.313rem] font-bold ${dark ? "text-white" : "text-[#0E1525]"}`}>Add bank account</div>
      <div className={`text-[12px] leading-[1.125rem] mt-px ${dark ? "text-white/55" : "text-[#0E1525]/55"}`}>Use a different account</div>
    </div>
  </button>;

export const BankRow = ({account, onClick, dark}) => <div onClick={onClick} role="button" tabIndex={0} onKeyDown={e => (e.key === "Enter" || e.key === " ") && (e.preventDefault(), onClick?.())} className={`flex h-[72px] items-center gap-3.5 px-4 py-3.5 rounded-2xl cursor-pointer transition-colors ${dark ? "bg-white/[0.04] hover:bg-white/[0.08]" : "bg-white hover:bg-white/80"}`}>
    <div className={`w-10 h-10 rounded-full flex items-center justify-center flex-shrink-0 ${dark ? "bg-[#3A3D42] text-white" : "bg-black/5 text-[#0E1525]"}`}><IcoBank /></div>
    <div className="flex-1 min-w-0">
      <div className={`text-[14px] leading-[1.313rem] font-bold ${dark ? "text-white" : "text-[#0E1525]"}`}>{account.name}</div>
      <div className={`text-[12px] leading-[1.125rem] mt-px ${dark ? "text-white/55" : "text-[#0E1525]/55"}`}>{account.currency}</div>
    </div>
    <button onClick={e => e.stopPropagation()} className={`w-9 h-9 rounded-full border-0 cursor-pointer flex items-center justify-center ${dark ? "bg-[#3A3D42] text-white/45" : "bg-black/5 text-[#0E1525]/40"}`}>
      <IcoMore />
    </button>
  </div>;

export const WidgetSelectCard = ({onBack, onAddCard, onSelectCard, currency = "GBP", dark}) => {
  const pick = c => () => onSelectCard && onSelectCard(c);
  return <div className={`flex-1 flex flex-col min-h-0 ${dark ? "bg-[#0E1116] text-white" : "bg-[#f4f4f5] text-[#0E1525]"}`}>
      <WTopBar onBack={onBack} dark={dark} />
      <div className="flex-1 px-5 pt-1 overflow-hidden">
        <h1 className={`m-0 mb-4 text-[26px] font-bold tracking-tight ${dark ? "text-white" : "text-[#0E1525]"}`}>Select card</h1>
        <div className="flex flex-col gap-2">
          <CardRow brand="visa" last4="1111" currency={currency} onClick={pick({
    brand: "visa",
    last4: "1111",
    currency
  })} dark={dark} />
          <CardRow brand="visa" last4="2222" currency={currency} onClick={pick({
    brand: "visa",
    last4: "2222",
    currency
  })} dark={dark} />
          <CardRow brand="mastercard" last4="4444" currency={currency} onClick={pick({
    brand: "mastercard",
    last4: "3333",
    currency
  })} dark={dark} />
          <AddCardRow onClick={onAddCard} dark={dark} />
        </div>
      </div>
      <WFooter dark={dark} />
    </div>;
};

export const AddCardRow = ({onClick, dark}) => <button onClick={onClick} className={`flex items-center h-[72px] gap-3.5 w-full px-3.5 py-3.5 border-0 rounded-2xl text-left transition-colors ${onClick ? "cursor-pointer" : "cursor-default"} ${dark ? `bg-white/[0.04]${onClick ? " hover:bg-white/[0.08]" : ""}` : `bg-white${onClick ? " hover:bg-white/80" : ""}`}`}>
    <div className={`w-10 h-10 rounded-full flex items-center justify-center flex-shrink-0 ${dark ? "bg-[#3A3D42] text-white" : "bg-black/5 text-[#0E1525]"}`}><IcoPlus /></div>
    <div>
      <div className={`text-[14px] leading-[1.313rem] font-bold ${dark ? "text-white" : "text-[#0E1525]"}`}>Add debit or credit card</div>
      <div className={`text-[12px] leading-[1.125rem] mt-0.5 ${dark ? "text-white/55" : "text-[#0E1525]/55"}`}>Visa/Mastercard</div>
    </div>
  </button>;

export const CardRow = ({brand, last4, currency, status, expired, onClick, dark}) => <div onClick={expired ? undefined : onClick} role={expired ? undefined : "button"} tabIndex={expired ? -1 : 0} onKeyDown={e => !expired && (e.key === "Enter" || e.key === " ") && (e.preventDefault(), onClick?.())} className={`flex h-[72px] items-center gap-3.5 px-3.5 py-3 rounded-2xl transition-colors ${expired ? "cursor-not-allowed opacity-60" : "cursor-pointer"} ${dark ? "bg-white/[0.04] hover:bg-white/[0.08]" : "bg-white hover:bg-white/80"}`}>
    <div className="relative">
      {brand === "visa" ? <VisaMark /> : <McardMark />}
      {expired && <AlertBadge />}
    </div>
    <div className="flex-1">
      <div className={`text-[14px] leading-[1.313rem] font-bold ${dark ? "text-white" : "text-[#0E1525]"}`}>#{last4}</div>
      <div className={`text-[12px] leading-[1.125rem] mt-px ${dark ? "text-white/55" : "text-[#0E1525]/55"}`}>{currency}</div>
      <div className={`text-[12px] leading-[1.125rem] ${expired ? "text-[#ff6a4d]" : dark ? "text-white/55" : "text-[#0E1525]/55"}`}>{status}</div>
    </div>
    <button onClick={e => e.stopPropagation()} className={`w-9 h-9 rounded-full border-0 cursor-pointer flex items-center justify-center ${dark ? "bg-[#3A3D42] text-white/45" : "bg-black/5 text-[#0E1525]/40"}`}>
      <IcoMore />
    </button>
  </div>;

export const WidgetSelectMethod = ({onPickCard, onPickBank, onPickCrypto, onBack, dark, mode}) => <div className={`flex-1 flex flex-col min-h-0 ${dark ? "bg-[#0E1116] text-white" : "bg-[#f4f4f5] text-[#0E1525]"}`}>
    <WTopBar onBack={onBack} dark={dark} />
    <div className="flex-1 px-5 pt-1 overflow-hidden">
      <h1 className={`m-0 mb-6 text-[26px] font-bold tracking-tight ${dark ? "text-white" : "text-[#0E1525]"}`}>{mode === "withdraw" ? "Select a withdrawal method" : "Select a payment method"}</h1>
      <div className={`text-[13px] mb-2.5 ${dark ? "text-white/55" : "text-[#0E1525]/55"}`}>Instant transfer</div>
      <MethodTile icon={<IcoCard />} title={mode === "withdraw" ? "Debit card" : "Credit or debit card"} sub="Visa/Mastercard" onClick={onPickCard} dark={dark} />
      <div className={`text-[13px] mt-5 mb-2.5 ${dark ? "text-white/55" : "text-[#0E1525]/55"}`}>Regular bank transfer</div>
      <MethodTile icon={<IcoBank />} title="Bank transfer" onClick={onPickBank} dark={dark} />
      <div className={`text-[13px] mt-5 mb-2.5 ${dark ? "text-white/55" : "text-[#0E1525]/55"}`}>Crypto transfer</div>
      <MethodTile icon={<IcoCrypto />} title="Crypto networks" onClick={onPickCrypto} dark={dark} />
    </div>
    <WFooter dark={dark} />
  </div>;

export const MethodTile = ({icon, title, sub, onClick, dark}) => <button onClick={onClick} className={`flex items-center gap-4 w-full h-[72px] px-3.5 py-3 border-0 rounded-2xl text-left transition-colors ${onClick ? "cursor-pointer" : "cursor-default"} ${dark ? "bg-white/[0.04] hover:bg-white/[0.08]" : "bg-white hover:bg-white/80"}`}>
    <div className={`w-11 h-11 rounded-full flex items-center justify-center flex-shrink-0 ${dark ? "bg-[#3A3D42] text-white" : "bg-black/5 text-[#0E1525]"}`}>{icon}</div>
    <div>
      <div className={`text-[14px] leading-[1.313rem] font-bold ${dark ? "text-white" : "text-[#0E1525]"}`}>{title}</div>
      {sub && <div className={`text-[12px] leading-[1.125rem] mt-0.5 ${dark ? "text-white/55" : "text-[#0E1525]/55"}`}>{sub}</div>}
    </div>
  </button>;

export const WFooter = ({dark}) => <div className={`flex items-center justify-center gap-2.5 px-5 pt-4 pb-5 flex-shrink-0 text-sm ${dark ? "text-white/55" : "text-[#0E1525]/50"}`}>
    <LeafLogo />
    <div className={`w-px h-3.5 ${dark ? "bg-white/20" : "bg-[#0E1525]/15"}`} />
    <span>Powered by <strong style={{
  color: dark ? "#ffffff" : "#0E1525"
}}>Uphold</strong></span>
  </div>;

export const WTopBar = ({onBack, title, dark}) => <div className="flex items-center gap-3 px-5 pt-4 pb-3">
    <button onClick={onBack} className={`w-10 h-10 rounded-full border-0 flex items-center justify-center cursor-pointer ${dark ? "bg-white/10 text-white" : "bg-black/5 text-[#0E1525]"}`}>
      <IcoBack />
    </button>
    {title && <div className={`flex-1 text-center pr-10 text-[17px] font-semibold ${dark ? "text-white" : "text-[#0E1525]"}`}>{title}</div>}
  </div>;

export const PhoneShell = ({children, bgClass = "bg-[#FAFAF7]", lightStatus = true, borderClass = "border-black/10"}) => <div className={`relative w-[320px] sm:w-[360px] h-[720px] rounded-[40px] sm:rounded-[44px] overflow-hidden border-2 flex flex-col font-sans shadow-[0_48px_96px_-28px_rgba(11,15,30,0.45),0_8px_20px_-6px_rgba(11,15,30,0.18)] ${bgClass} ${borderClass}`}>
    <div className={`absolute top-2 left-1/2 -translate-x-1/2 w-[110px] h-7 rounded-full z-10 ${lightStatus ? "bg-black" : "bg-white/20"}`} />
    <StatusBar light={lightStatus} />
    <div className="flex-1 flex flex-col min-h-0 relative">{children}</div>
    <div className="absolute bottom-2 left-1/2 -translate-x-1/2 w-[134px] h-[5px] rounded-full z-20" style={{
  background: lightStatus ? "rgba(14,21,37,0.2)" : "rgba(255,255,255,0.4)"
}} />
  </div>;

export const StatusBar = ({light}) => <div className="h-11 flex items-center justify-between px-7 flex-shrink-0 text-[15px] bg-green font-semibold" style={{
  color: light ? "#0E1525" : "white",
  backgroundColor: light ? "white" : "black"
}}>
    <span>9:41</span>
    <div className="flex items-center gap-1.5">
      <svg className="w-[18px] h-3" viewBox="0 0 18 12" fill="currentColor"><rect x="0" y="8" width="3" height="4" rx="0.5" /><rect x="5" y="5" width="3" height="7" rx="0.5" /><rect x="10" y="2" width="3" height="10" rx="0.5" /><rect x="15" y="0" width="3" height="12" rx="0.5" /></svg>
      <svg className="w-4 h-3" viewBox="0 0 16 12" fill="none" stroke="currentColor" strokeWidth="1.4"><path d="M1,5 Q8,-1 15,5" /><path d="M3.5,7 Q8,3 12.5,7" /><circle cx="8" cy="9.5" r="1" fill="currentColor" /></svg>
      <svg className="w-[26px] h-3" viewBox="0 0 26 12" fill="none"><rect x="0.5" y="0.5" width="22" height="11" rx="2.5" stroke="currentColor" strokeOpacity="0.5" /><rect x="2" y="2" width="19" height="8" rx="1.5" fill="currentColor" /><rect x="23" y="4" width="2" height="4" rx="1" fill="currentColor" fillOpacity="0.5" /></svg>
    </div>
  </div>;

export const LeafLogo = ({color = "#35B13D"}) => <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 14 18" className="w-3.5 h-[18px]">
    <path fill={color} fillRule="evenodd" clipRule="evenodd" d="M11.622 9.986a9.52 9.52 0 0 1-1.536 2.343c.427-1.588.221-3.64-.702-5.631a9.941 9.941 0 0 0-1.866-2.741c1.163-.89 2.373-1.181 3.308-.771.6.262 1.062.8 1.337 1.555.521 1.43.319 3.39-.541 5.245Zm-9.744 0C1.018 8.131.815 6.17 1.337 4.741c.275-.755.737-1.293 1.337-1.555.935-.41 2.145-.12 3.308.77a9.924 9.924 0 0 0-1.866 2.742c-.924 1.992-1.13 4.043-.703 5.631a9.506 9.506 0 0 1-1.535-2.343Zm5.744 4.02c-.269.117-.562.178-.872.182a2.224 2.224 0 0 1-.872-.183c-1.801-.789-2.165-3.95-.796-6.905A8.948 8.948 0 0 1 6.75 4.642 8.926 8.926 0 0 1 8.417 7.1c1.37 2.953 1.006 6.115-.795 6.904Zm2.445-11.999C9 1.965 7.837 2.397 6.75 3.261 5.663 2.398 4.5 1.964 3.433 2.006a5.903 5.903 0 0 1 3.316-1.005c1.226 0 2.377.367 3.318 1.006Zm3.098 2.42v-.003l-.003-.006a.02.02 0 0 1-.001-.005l-.004-.01C12.255 1.77 9.684 0 6.749 0 3.807 0 1.23 1.778.334 4.424c-.001.004-.001.009-.003.013-.595 1.66-.38 3.882.58 5.952C2.226 13.223 4.61 15.19 6.72 15.19h.06c2.11 0 4.495-1.968 5.808-4.8.962-2.075 1.177-4.302.577-5.963Zm-4.61 12.321a6.517 6.517 0 0 1-1.757.25h-.084a6.53 6.53 0 0 1-1.768-.253.533.533 0 0 0-.657.337.497.497 0 0 0 .356.623 7.64 7.64 0 0 0 2.07.295h.083c.674 0 1.367-.098 2.056-.291a.497.497 0 0 0 .357-.623.533.533 0 0 0-.656-.338Z" />
  </svg>;

export const EurcCoin = () => <svg className="w-7 h-7 block" viewBox="0 0 40 40">
    <defs>
      <linearGradient id="mlEurcGrad" x1="0" y1="0" x2="1" y2="1">
        <stop offset="0%" stopColor="#3F8EFF" /><stop offset="100%" stopColor="#1F4FB8" />
      </linearGradient>
    </defs>
    <circle cx="20" cy="20" r="20" fill="url(#mlEurcGrad)" />
    <path d="M22.5 11.5c-3.4 0-6.2 2-7.4 5.2h-2v1.7h1.6c-.05.4-.07.8-.07 1.2 0 .42.03.83.08 1.23h-1.6v1.7h2c1.2 3.2 4 5.2 7.4 5.2 1.6 0 3-.42 4.1-1.18l-1.4-1.45c-.78.5-1.7.78-2.7.78-2.4 0-4.4-1.4-5.3-3.45h5v-1.7h-5.42c-.06-.4-.1-.81-.1-1.23 0-.41.04-.81.1-1.2h5.42v-1.7h-5c.9-2.05 2.9-3.45 5.3-3.45 1.05 0 1.95.27 2.7.78l1.4-1.45c-1.1-.76-2.5-1.18-4.13-1.18z" fill="#fff" />
  </svg>;

export const EuFlag = () => <svg className="w-7 h-5 rounded-sm block overflow-hidden" viewBox="0 0 60 40">
    <rect width="60" height="40" fill="#003399" />
    {Array.from({
  length: 12
}).map((_, i) => {
  const a = (i * 30 - 90) * Math.PI / 180;
  return <circle key={i} cx={30 + Math.cos(a) * 12} cy={20 + Math.sin(a) * 12} r="1.6" fill="#FFCC00" />;
})}
  </svg>;

export const UsFlag = () => <svg className="w-7 h-5 rounded-sm block overflow-hidden" viewBox="0 0 60 40">
    <rect width="60" height="40" fill="#fff" />
    {[0, 2, 4, 6, 8, 10, 12].map(i => <rect key={i} y={i * 40 / 13} width="60" height={40 / 13} fill="#B22234" />)}
    <rect width="24" height="22" fill="#3C3B6E" />
  </svg>;

export const UkFlag = () => <svg className="w-6 h-6 rounded-full block" viewBox="0 0 60 60">
    <rect width="60" height="60" fill="#012169" />
    <path d="M0,0 L60,60 M60,0 L0,60" stroke="#fff" strokeWidth="9" />
    <path d="M0,0 L60,60 M60,0 L0,60" stroke="#C8102E" strokeWidth="3.6" />
    <path d="M30,0 V60 M0,30 H60" stroke="#fff" strokeWidth="15" />
    <path d="M30,0 V60 M0,30 H60" stroke="#C8102E" strokeWidth="7.5" />
  </svg>;

export const AlertBadge = () => <div className="absolute -right-0.5 -bottom-0.5 w-4 h-4 rounded-full bg-white flex items-center justify-center">
    <svg className="w-3.5 h-3.5" viewBox="0 0 24 24"><circle cx="12" cy="12" r="11" fill="#e5563b" /><rect x="11" y="6" width="2" height="8" fill="#fff" rx="1" /><circle cx="12" cy="17" r="1.2" fill="#fff" /></svg>
  </div>;

export const McardMark = ({sm}) => <div className={`relative flex items-center justify-center bg-white flex-shrink-0 ${sm ? "w-9 h-6 rounded" : "w-10 h-10 rounded-full"}`}>
    <div className={`absolute rounded-full bg-[#eb001b] opacity-95 ${sm ? "w-3.5 h-3.5 left-1.5 top-[5px]" : "w-[22px] h-[22px] left-[5px] top-[9px]"}`} />
    <div className={`absolute rounded-full bg-[#f79e1b] opacity-85 mix-blend-multiply ${sm ? "w-3.5 h-3.5 left-4 top-[5px]" : "w-[22px] h-[22px] left-[13px] top-[9px]"}`} />
  </div>;

export const VisaMark = ({sm}) => <div className={`flex items-center justify-center bg-[#1a1f71] flex-shrink-0 ${sm ? "w-9 h-6 rounded" : "w-10 h-10 rounded-full"}`}>
    <span className={`text-white font-black italic tracking-tight ${sm ? "text-[11px]" : "text-[13px]"}`} style={{
  fontFamily: "Arial, sans-serif"
}}>VISA</span>
  </div>;

export const IcoX = () => <svg className="w-3.5 h-3.5" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.4" strokeLinecap="round">
    <path d="M6 6l12 12M18 6L6 18" />
  </svg>;

export const IcoInfoSm = () => <svg className="w-3.5 h-3.5" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
    <line x1="12" y1="11" x2="12" y2="16" /><circle cx="12" cy="7.5" r="1" fill="currentColor" stroke="none" />
  </svg>;

export const IcoCopy = () => <svg className="w-5 h-5" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round">
    <rect x="9" y="9" width="11" height="11" rx="2" /><path d="M5 15V5a2 2 0 0 1 2-2h10" />
  </svg>;

export const IcoCheck = () => <svg className="w-7 h-7" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round">
    <polyline points="20 6 9 17 4 12" />
  </svg>;

export const IcoInfo = () => <svg className="w-5 h-5" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round">
    <circle cx="12" cy="12" r="9" /><line x1="12" y1="11" x2="12" y2="17" />
    <circle cx="12" cy="7.5" r="1.2" fill="currentColor" stroke="none" />
  </svg>;

export const IcoMore = () => <svg className="w-5 h-5" viewBox="0 0 24 24" fill="currentColor">
    <circle cx="12" cy="5" r="1.4" /><circle cx="12" cy="12" r="1.4" /><circle cx="12" cy="19" r="1.4" />
  </svg>;

export const IcoPlus = () => <svg className="w-[22px] h-[22px]" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
    <line x1="12" y1="5" x2="12" y2="19" /><line x1="5" y1="12" x2="19" y2="12" />
  </svg>;

export const IcoCrypto = () => <svg className="w-[22px] h-[22px]" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round">
    <circle cx="12" cy="12" r="9" /><circle cx="12" cy="12" r="2.5" />
    <line x1="12" y1="3" x2="12" y2="9.5" /><line x1="12" y1="14.5" x2="12" y2="21" />
    <line x1="3" y1="12" x2="9.5" y2="12" /><line x1="14.5" y1="12" x2="21" y2="12" />
  </svg>;

export const IcoBank = () => <svg className="w-[22px] h-[22px]" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round">
    <path d="M3 10.5 12 4l9 6.5" /><line x1="3" y1="10.5" x2="21" y2="10.5" />
    <line x1="6" y1="11" x2="6" y2="17" /><line x1="10" y1="11" x2="10" y2="17" />
    <line x1="14" y1="11" x2="14" y2="17" /><line x1="18" y1="11" x2="18" y2="17" />
    <line x1="3" y1="20" x2="21" y2="20" />
  </svg>;

export const IcoCard = () => <svg className="w-[22px] h-[22px]" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round">
    <rect x="2" y="5" width="20" height="14" rx="2.5" /><line x1="2" y1="10" x2="22" y2="10" />
  </svg>;

export const IcoCardPlus = () => <svg className="w-[22px] h-[22px]" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round">
    <rect x="3" y="5" width="18" height="14" rx="2.5" />
    <line x1="3" y1="10" x2="21" y2="10" />
    <line x1="12" y1="14" x2="12" y2="17" /><line x1="10.5" y1="15.5" x2="13.5" y2="15.5" />
  </svg>;

export const IcoArrow = () => <svg className="w-4 h-4" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
    <line x1="5" y1="12" x2="19" y2="12" /><polyline points="12 5 19 12 12 19" />
  </svg>;

export const IcoBack = () => <svg className="w-5 h-5" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round">
    <polyline points="15 18 9 12 15 6" />
  </svg>;

<p>
  The Payment Widget is a fully Uphold-managed, embeddable solution that allows users to securely add pay-in and payout methods.
</p>

<p>
  It's built with developer efficiency and global readiness in mind, with support for multi-platform integration and a growing list of payment methods.
</p>

<PaymentWidgetDemoMintlify />

***

<CardGroup cols={2}>
  <Card title="Turnkey experience" icon="key">
    Fully managed UI with automated state handling and lightweight SDK to instantiate and control the Widget.

    Go live quickly with minimal frontend effort.
  </Card>

  <Card title="Flexible payment method support" icon="wallet">
    Accept cards, bank, and crypto transfers out of the box.

    Control which methods users see, with more options on the way.
  </Card>

  <Card title="Multi-platform embedding" icon="mobile-screen-button">
    Embed seamlessly into web apps via iframe and native apps via WebView.

    Consistent user experience across all platforms.
  </Card>

  <Card title="Real-time event handling" icon="bolt">
    SDK emits lifecycle events such as success, error, and cancellation, with minimal error handling required.

    Integrate deeply with your app's flow and UI feedback.
  </Card>
</CardGroup>

## Payment methods

Read our Developer Guides for step-by-step instructions on implementing specific payment methods with the Widget.

<CardGroup cols={3}>
  <Card title="Bank" icon="bank">
    * [Bank deposits](/developer-guides/bank-transfers/deposit/via-payment-widget)
    * [Bank withdrawals](/developer-guides/bank-transfers/withdrawal/via-payment-widget)
  </Card>

  <Card title="Card" icon="credit-card">
    * [Card deposits](/developer-guides/card-transfers/deposit/via-payment-widget)
    * [Card withdrawals](/developer-guides/card-transfers/withdrawal/via-payment-widget)
  </Card>

  <Card title="Crypto" icon="bitcoin">
    * [Crypto deposits](/developer-guides/crypto-transfers/deposit/via-payment-widget)
    * [Crypto withdrawals](/developer-guides/crypto-transfers/withdrawal/via-payment-widget)
  </Card>
</CardGroup>
