// ============================================================
// PROP ARENA — live data overrides
//   Replaces hardcoded mock components with versions wired into
//   PropArenaApi (profile, profile-edit, security/2FA, forgot-
//   password reset, notifications, affiliates, withdraw flow,
//   new-challenge success, mobile parity). Visual layout is
//   preserved – this file only changes data sources and wires
//   backend calls. Loaded last so window.* assignments win.
// ============================================================

(function () {
  if (typeof window === 'undefined') return;
  if (!window.React) return;

  const { useState, useEffect, useMemo } = React;

  // ─────────────────────────────────────────────────────────────
  // Local copies of layout helpers (so overrides don't depend on
  // module-level functions in arena-pages*.jsx that aren't on
  // window). Visual output matches the originals.
  // ─────────────────────────────────────────────────────────────
  function ArenaKvLocal({ label, value, mono, copy }) {
    return (
      <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', padding: '10px 0', borderBottom: '1px solid var(--line-2)' }}>
        <span style={{ fontSize: 11, color: 'var(--text-dim)', textTransform: 'uppercase', letterSpacing: '.08em', fontWeight: 600 }}>{label}</span>
        <span style={{ display: 'inline-flex', alignItems: 'center', gap: 8 }}>
          <span className={mono ? 'mono' : ''} style={{ fontSize: 13 }}>{value}</span>
          {copy && <button className="a-iconbtn" style={{ width: 26, height: 26 }} onClick={() => navigator.clipboard?.writeText(String(value || ''))}><I.copy size={11}/></button>}
        </span>
      </div>
    );
  }

  function ArenaInputFieldLocal({ label, v, onChange, type = 'text', mono, disabled }) {
    return (
      <div style={{ marginBottom: 12 }}>
        <label style={{ fontSize: 11, color: 'var(--text-dim)', textTransform: 'uppercase', letterSpacing: '.08em', fontWeight: 600, display: 'block', marginBottom: 6 }}>{label}</label>
        <input
          className="a-input"
          type={type}
          value={v ?? ''}
          onChange={e => onChange?.(e.target.value)}
          disabled={disabled}
          style={{ ...(mono ? { fontFamily: 'JetBrains Mono', fontSize: 13 } : {}), ...(disabled ? { opacity: 0.6, cursor: 'not-allowed' } : {}) }}
        />
      </div>
    );
  }

  function ArenaModalShellLocal({ children, onClose, title, subtitle, footer, width = 480 }) {
    return (
      <>
        <div onClick={onClose} style={{ position: 'fixed', inset: 0, background: 'rgba(0,0,0,0.62)', backdropFilter: 'blur(6px)', zIndex: 200 }}/>
        <div style={{
          position: 'fixed', top: '50%', left: '50%', transform: 'translate(-50%, -50%)',
          width, maxWidth: '92vw', maxHeight: '92vh', zIndex: 201,
          background: 'var(--surface)', border: '1px solid var(--line-3)',
          borderRadius: 18, display: 'flex', flexDirection: 'column',
          boxShadow: '0 30px 80px rgba(0,0,0,0.6)',
        }}>
          <div style={{ padding: '20px 24px', borderBottom: '1px solid var(--line)', display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start' }}>
            <div>
              <div style={{ fontFamily: 'Space Grotesk', fontSize: 18, fontWeight: 700, letterSpacing: '-0.02em' }}>{title}</div>
              {subtitle && <div style={{ fontSize: 12, color: 'var(--text-dim)', marginTop: 4 }}>{subtitle}</div>}
            </div>
            <button className="a-iconbtn" onClick={onClose}><I.x size={13}/></button>
          </div>
          <div style={{ padding: 24, overflowY: 'auto' }}>{children}</div>
          {footer && <div style={{ padding: '14px 24px', borderTop: '1px solid var(--line)', background: 'var(--surface-2)', display: 'flex', gap: 10, justifyContent: 'flex-end' }}>{footer}</div>}
        </div>
      </>
    );
  }

  function ArenaMobilePageHeadLocal({ title, sub, back }) {
    const { setPage } = useApp();
    return (
      <div className="am-page-head" style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 14 }}>
        <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
          {back && (
            <button className="a-iconbtn" onClick={() => setPage(back)} style={{ width: 34, height: 34 }}><I.chevronLeft size={14}/></button>
          )}
          <div>
            <h1 style={{ margin: 0, fontFamily: 'Space Grotesk', fontSize: 20, fontWeight: 700, letterSpacing: '-0.02em' }}>{title}</h1>
            {sub && <div style={{ fontSize: 12, color: 'var(--text-dim)', marginTop: 2 }}>{sub}</div>}
          </div>
        </div>
      </div>
    );
  }

  function ArenaTxSuccessLocal({ kind, amount, setPage }) {
    const ref = useMemo(() => 'PA-' + Math.random().toString(36).slice(2, 9).toUpperCase(), []);
    const labels = {
      withdraw:       { title: 'Withdrawal submitted', body: 'arriving within 24h', method: 'USDT TRC-20' },
      'deposit-crypto': { title: 'Payment confirmed', body: 'credited to your wallet', method: 'USDT TRC-20' },
      'deposit-card':   { title: 'Payment confirmed', body: 'credited to your wallet', method: 'Card' },
      'deposit-wire':   { title: 'Wire instructions sent', body: 'arrives 1–3 business days', method: 'Bank wire' },
    };
    const m = labels[kind] || labels.withdraw;
    return (
      <>
        <div className="a-pagehead">
          <div>
            <h1>All <em>set</em>.</h1>
            <div className="sub">{m.body}</div>
          </div>
        </div>
        <div className="a-section" style={{ maxWidth: 540, margin: '0 auto', textAlign: 'center', padding: '36px 28px' }}>
          <div style={{ width: 80, height: 80, borderRadius: 999, background: 'linear-gradient(135deg, var(--positive), oklch(62% 0.18 145))', color: '#06070D', display: 'flex', alignItems: 'center', justifyContent: 'center', margin: '0 auto', boxShadow: '0 0 60px -10px var(--positive)' }}>
            <I.check size={42}/>
          </div>
          <div style={{ fontFamily: 'Space Grotesk', fontSize: 28, fontWeight: 700, letterSpacing: '-0.025em', marginTop: 22 }}>{m.title}</div>
          <div style={{ marginTop: 6, fontSize: 14, color: 'var(--text-dim)' }}>
            {kind === 'withdraw' ? '−' : '+'}<b className="mono" style={{ color: 'var(--text)' }}>${Number(amount || 0).toFixed(2)}</b> {m.body}
          </div>

          <div style={{ marginTop: 24, padding: 16, background: 'var(--surface-2)', border: '1px solid var(--line)', borderRadius: 12, textAlign: 'left', fontSize: 13 }}>
            <ArenaKvLocal label="Reference" value={ref} mono copy/>
            <ArenaKvLocal label="Amount" value={'$' + Number(amount || 0).toFixed(2)} mono/>
            <ArenaKvLocal label="Method" value={m.method}/>
            <ArenaKvLocal label="Status" value={kind === 'deposit-wire' ? 'Pending' : 'Confirmed'}/>
          </div>

          <div style={{ display: 'flex', gap: 8, marginTop: 22 }}>
            <button className="a-btn ghost" style={{ flex: 1, justifyContent: 'center' }} onClick={() => setPage('wallet')}>View wallet</button>
            <button className="a-btn primary" style={{ flex: 1, justifyContent: 'center' }} onClick={() => setPage('dashboard')}>Done</button>
          </div>
        </div>
      </>
    );
  }

  // ─────────────────────────────────────────────────────────────
  // Live profile helpers
  // ─────────────────────────────────────────────────────────────
  function readField(source, keys, fallback) {
    if (!source) return fallback;
    for (const key of keys) {
      const value = String(key).split('.').reduce((acc, part) => (acc == null ? acc : acc[part]), source);
      if (value !== undefined && value !== null && value !== '') return value;
    }
    return fallback;
  }

  function boolStatus(value) {
    if (value === true || value === false) return value;
    if (typeof value !== 'string') return null;
    const v = value.trim().toLowerCase();
    if (['1', 'true', 'yes', 'enabled', 'active', 'verified', 'approved', 'complete', 'completed', 'passed'].includes(v)) return true;
    if (['0', 'false', 'no', 'disabled', 'off', 'inactive', 'unverified', 'rejected', 'declined', 'failed'].includes(v)) return false;
    return null;
  }

  function countryLabel(code, countries = []) {
    if (!code) return '';
    const list = Array.isArray(countries) ? countries : [];
    const match = list.find(c => {
      const value = c.code || c.iso || c.iso2 || c.countryCode || c.value || c.alpha2 || c.id;
      return String(value || '').toLowerCase() === String(code).toLowerCase();
    });
    return match?.printableName || match?.name || match?.label || match?.country || match?.title || String(code);
  }

  function profileFromUser(user, countries) {
    const raw = user || {};
    const name = window.PropArenaApi?.userName?.(raw) || readField(raw, ['name', 'fullName'], 'Trader');
    const firstName = readField(raw, ['firstName'], '');
    const lastName = readField(raw, ['lastName'], '');
    return {
      raw,
      name,
      firstName,
      lastName,
      initials: window.PropArenaApi?.userInitials?.(raw) || name.split(/\s+/).filter(Boolean).slice(0, 2).map(p => p[0]).join('').toUpperCase() || 'PA',
      email: readField(raw, ['email', 'emailAddress'], ''),
      telephone: readField(raw, ['telephone', 'phone', 'phoneNumber', 'mobile'], ''),
      telephonePrefix: readField(raw, ['telephonePrefix', 'phonePrefix', 'dialCode'], ''),
      countryIso: readField(raw, ['countryIso', 'countryCode', 'country', 'countryISO'], ''),
      countryName: countryLabel(readField(raw, ['countryIso', 'countryCode', 'country'], ''), countries),
      dateOfBirth: readField(raw, ['dateOfBirth', 'birthDate', 'dob'], ''),
      address: readField(raw, ['address', 'address.line1', 'street'], ''),
      city: readField(raw, ['city', 'address.city'], ''),
      zip: readField(raw, ['zip', 'postalCode', 'postcode', 'address.zip'], ''),
      state: readField(raw, ['state', 'region', 'address.state'], ''),
      currency: readField(raw, ['currency', 'baseCurrency'], 'USD'),
      languageIso: readField(raw, ['languageIso', 'language'], ''),
      tier: readField(raw, ['tier', 'level', 'clientTier'], ''),
      kycStatus: readField(raw, ['kycStatus', 'kyc.status', 'verificationStatus'], ''),
      fnsStatus: readField(raw, ['fnsStatus', 'fns.status', 'sumsubStatus', 'sumsubFnsStatus'], ''),
      fnsStatusDisplay: readField(raw, ['fnsStatusDisplay', 'fnsStatusLabel', 'sumsubStatusDisplay'], ''),
      isFnsUnassigned: raw?.isFnsUnassigned === true || raw?.isFnsUnassigned === 'true',
      isFnsRejected: raw?.isFnsRejected === true || raw?.isFnsRejected === 'true',
      twoFactorEnabled: readField(raw, ['twoFactorEnabled', 'twoFaEnabled', 'mfaEnabled', 'totpEnabled'], null),
      bankIban: readField(raw, ['bankAccountNumber', 'bankIban', 'iban'], ''),
      bankName: readField(raw, ['bankName'], ''),
      bankSwift: readField(raw, ['bankSwiftCode', 'bankSwift', 'swift', 'bic'], ''),
      memberSince: readField(raw, ['createdAt', 'registrationDate', 'memberSince'], ''),
    };
  }

  function kycInfo(p) {
    // Prefer Sumsub/FNS status (same source the wallet shows as verified) over
    // generic kycStatus. Falls back to kycStatus, then to a muted unknown.
    const fnsRaw = typeof p.fnsStatus === 'string' ? p.fnsStatus.trim() : '';
    const fnsNorm = fnsRaw.toLowerCase().replace(/[\s-]+/g, '_');
    const kycRaw = p.kycStatus;
    const kycNorm = typeof kycRaw === 'string' ? kycRaw.trim().toLowerCase() : '';
    const kycBool = boolStatus(kycRaw);
    const okWords = ['approved', 'verified', 'complete', 'completed', 'passed', 'accepted', 'assigned'];
    const pendingWords = ['pending', 'review', 'in_review', 'submitted', 'required', 'in_progress', 'processing'];
    const badWords = ['rejected', 'declined', 'failed', 'denied'];
    if (p.isFnsRejected) {
      return { state: 'bad', label: 'REJECTED', detail: 'Sumsub verification rejected' };
    }
    if (fnsNorm) {
      if (okWords.includes(fnsNorm)) return { state: 'ok', label: 'VERIFIED', detail: 'Sumsub verification active' };
      if (badWords.includes(fnsNorm)) return { state: 'bad', label: fnsNorm.toUpperCase(), detail: 'Sumsub verification status' };
      if (pendingWords.includes(fnsNorm)) return { state: 'warn', label: (p.fnsStatusDisplay || fnsRaw).toUpperCase().replace(/_/g, ' '), detail: 'Sumsub verification in progress' };
      // Any non-empty fns value that doesn't match these buckets — still
      // surface what the backend gave us instead of "STATUS UNAVAILABLE".
      return { state: 'warn', label: (p.fnsStatusDisplay || fnsRaw).toUpperCase().replace(/_/g, ' '), detail: 'Sumsub verification status' };
    }
    if (kycBool === true || okWords.includes(kycNorm)) {
      return { state: 'ok', label: 'VERIFIED', detail: 'Live profile status' };
    }
    if (kycBool === false || pendingWords.includes(kycNorm)) {
      return { state: 'warn', label: kycNorm ? kycNorm.replace(/_/g, ' ').toUpperCase() : 'PENDING', detail: 'Live profile status' };
    }
    if (badWords.includes(kycNorm)) {
      return { state: 'bad', label: kycNorm.toUpperCase(), detail: 'Live profile status' };
    }
    if (p.isFnsUnassigned === true) {
      return { state: 'warn', label: 'NOT STARTED', detail: 'Sumsub KYC has not been started yet' };
    }
    return { state: 'muted', label: 'STATUS UNAVAILABLE', detail: 'KYC status not yet exposed by profile' };
  }

  function formatDate(value) {
    if (!value) return '';
    const date = new Date(value);
    if (Number.isNaN(date.getTime())) return String(value);
    return date.toLocaleDateString('en-US', { year: 'numeric', month: 'short', day: 'numeric' });
  }

  function walletBalanceFromLive(wallet) {
    return Math.max(0, Number(wallet?.balance) || 0);
  }

  // ─────────────────────────────────────────────────────────────
  // PROFILE (desktop)
  // ─────────────────────────────────────────────────────────────
  function ArenaProfileLive() {
    const { user, setPage, liveData } = useApp();
    const wallet = useLiveWallet();
    const countries = liveData?.countries || [];
    const p = profileFromUser(user, countries);
    const kyc = kycInfo(p);

    // Match wallet/dashboard: lifetime payouts include both payout rows and
    // completed withdrawal rows (both are money paid out to the user).
    const lifetimePayouts = Number(wallet?.totalPaid) > 0
      ? Number(wallet.totalPaid)
      : [...(wallet?.payouts || []), ...(wallet?.withdrawals || [])]
          .filter(t => t.status === 'done')
          .reduce((s, t) => s + Math.abs(Number(t.amount) || 0), 0);
    const payoutCount = (wallet?.payouts || []).length + (wallet?.withdrawals || []).filter(t => t.status === 'done').length;

    return (
      <>
        <div className="a-pagehead">
          <div>
            <h1>My <em>profile</em>.</h1>
            <div className="sub">Personal · billing · bank · KYC · security</div>
          </div>
          <div style={{ display: 'flex', gap: 10 }}>
            <button className="a-btn secondary" onClick={() => setPage('security')}><I.shield size={13}/> Security</button>
            <button className="a-btn primary" onClick={() => setPage('profileEdit')}><I.edit size={13}/> Edit profile</button>
          </div>
        </div>

        <div className="a-section" style={{ marginBottom: 18, background: 'linear-gradient(135deg, rgba(255,92,245,0.06), rgba(92,217,255,0.04)), var(--surface)' }}>
          <div style={{ display: 'flex', gap: 22, alignItems: 'center' }}>
            <div style={{ width: 86, height: 86, borderRadius: 22, background: 'linear-gradient(135deg, var(--magenta), var(--cyan))', color: '#06070D', display: 'flex', alignItems: 'center', justifyContent: 'center', fontWeight: 800, fontSize: 32, fontFamily: 'Space Grotesk' }}>{p.initials}</div>
            <div style={{ flex: 1 }}>
              <div style={{ fontFamily: 'Space Grotesk', fontSize: 28, fontWeight: 700, letterSpacing: '-0.025em' }}>{p.name}</div>
              <div style={{ fontSize: 13, color: 'var(--text-dim)', marginTop: 4 }}>{p.email || '—'}{p.countryName ? ` · ${p.countryName}` : ''}{p.memberSince ? ` · trader since ${formatDate(p.memberSince)}` : ''}</div>
              <div style={{ display: 'flex', gap: 6, marginTop: 10, flexWrap: 'wrap' }}>
                <span className={'a-tag ' + (kyc.state === 'ok' ? 'success' : kyc.state === 'warn' ? 'pending' : kyc.state === 'bad' ? 'failed' : 'muted')}>KYC · {kyc.label}</span>
                {p.tier && <span className="a-tag" style={{ background: 'color-mix(in oklab, var(--cyan) 14%, transparent)', color: 'var(--cyan)' }}>{String(p.tier).toUpperCase()}</span>}
                {payoutCount > 0 && <span className="a-tag muted">{payoutCount} PAYOUT{payoutCount === 1 ? '' : 'S'}</span>}
              </div>
            </div>
            <div style={{ textAlign: 'right' }}>
              <div className="mono" style={{ fontSize: 32, fontWeight: 700, letterSpacing: '-0.03em' }}>${window.fmtMoney(lifetimePayouts || 0)}</div>
              <div style={{ fontSize: 11, color: 'var(--text-dim)', textTransform: 'uppercase', letterSpacing: '.1em' }}>Lifetime payouts</div>
            </div>
          </div>
        </div>

        <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 18, marginBottom: 18 }}>
          <div className="a-section">
            <h3 style={{ margin: '0 0 14px', fontFamily: 'Space Grotesk', fontSize: 16 }}>Personal</h3>
            <ArenaKvLocal label="Full name" value={p.name || '—'}/>
            <ArenaKvLocal label="Date of birth" value={p.dateOfBirth ? formatDate(p.dateOfBirth) : '—'}/>
            <ArenaKvLocal label="Country" value={p.countryName || '—'}/>
            <ArenaKvLocal label="Address" value={[p.address, p.city, p.zip].filter(Boolean).join(', ') || '—'} copy={Boolean(p.address)}/>
            <ArenaKvLocal label="Phone" value={p.telephone ? (p.telephonePrefix ? p.telephonePrefix + ' ' : '') + p.telephone : '—'}/>
            <ArenaKvLocal label="Email" value={p.email || '—'} copy={Boolean(p.email)}/>
          </div>
          <div className="a-section">
            <h3 style={{ margin: '0 0 14px', fontFamily: 'Space Grotesk', fontSize: 16 }}>Billing</h3>
            <ArenaKvLocal label="Default method" value="Wallet balance"/>
            <ArenaKvLocal label="Billing email" value={p.email || '—'} copy={Boolean(p.email)}/>
            <ArenaKvLocal label="Currency" value={p.currency || 'USD'}/>
            <ArenaKvLocal label="Wallet balance" value={'$' + window.fmtMoney(wallet?.balance || 0)} mono/>
            <ArenaKvLocal label="Lifetime payouts" value={'$' + window.fmtMoney(lifetimePayouts || 0)} mono/>
          </div>
        </div>

        <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 18 }}>
          <div className="a-section">
            <h3 style={{ margin: '0 0 14px', fontFamily: 'Space Grotesk', fontSize: 16 }}>Bank / Payout destinations</h3>
            {p.bankIban
              ? <ArenaKvLocal label="Wire · IBAN" value={p.bankIban} mono copy/>
              : <div style={{ fontSize: 12, color: 'var(--text-dim)', padding: '10px 0' }}>No bank IBAN on the live profile yet.</div>}
            {p.bankName && <ArenaKvLocal label="Bank" value={p.bankName}/>}
            {p.bankSwift && <ArenaKvLocal label="SWIFT" value={p.bankSwift} mono copy/>}
            <div style={{ marginTop: 12, fontSize: 12, color: 'var(--text-dim)' }}>
              <I.info size={12} style={{ marginRight: 6, verticalAlign: 'middle' }}/>
              Adding or editing destinations requires 2FA — visit <a onClick={() => setPage('security')} style={{ color: 'var(--cyan)', cursor: 'pointer' }}>Security</a>.
            </div>
          </div>
          <div className="a-section">
            <h3 style={{ margin: '0 0 14px', fontFamily: 'Space Grotesk', fontSize: 16 }}>KYC / Verification</h3>
            <div style={{ display: 'flex', alignItems: 'center', gap: 12, padding: '10px 0' }}>
              <div style={{
                width: 32, height: 32, borderRadius: 999,
                background: kyc.state === 'ok' ? 'color-mix(in oklab, var(--positive) 18%, transparent)' : kyc.state === 'warn' ? 'color-mix(in oklab, var(--gold) 18%, transparent)' : 'color-mix(in oklab, var(--text-dim) 18%, transparent)',
                color: kyc.state === 'ok' ? 'var(--positive)' : kyc.state === 'warn' ? 'var(--gold)' : 'var(--text-dim)',
                display: 'flex', alignItems: 'center', justifyContent: 'center',
              }}>{kyc.state === 'ok' ? <I.check size={14}/> : <I.warn size={14}/>}</div>
              <div style={{ flex: 1 }}>
                <div style={{ fontWeight: 500, fontSize: 14 }}>Identity verification</div>
                <div style={{ fontSize: 11, color: 'var(--text-dim)' }}>{kyc.detail}</div>
              </div>
              <span className={'a-tag ' + (kyc.state === 'ok' ? 'success' : kyc.state === 'warn' ? 'pending' : 'muted')}>{kyc.label}</span>
            </div>
            <div style={{ marginTop: 12, fontSize: 12, color: 'var(--text-dim)' }}>
              <I.info size={12} style={{ marginRight: 6, verticalAlign: 'middle' }}/>
              KYC capture flow lives behind the support portal; manage from Security when enabled upstream.
            </div>
          </div>
        </div>
      </>
    );
  }

  // ─────────────────────────────────────────────────────────────
  // PROFILE EDIT (desktop)
  // ─────────────────────────────────────────────────────────────
  function ArenaProfileEditLive() {
    const { user, setPage, liveData, refreshLiveData } = useApp();
    const countries = liveData?.countries || [];
    const initial = useMemo(() => profileFromUser(user, countries), [user, countries.length]);
    const [form, setForm] = useState({
      firstName: initial.firstName || (initial.name.split(/\s+/)[0] || ''),
      lastName: initial.lastName || initial.name.split(/\s+/).slice(1).join(' '),
      email: initial.email,
      telephonePrefix: initial.telephonePrefix || '+1',
      telephone: initial.telephone,
      countryIso: initial.countryIso,
      dateOfBirth: initial.dateOfBirth ? new Date(initial.dateOfBirth).toISOString().slice(0, 10) : '',
      address: initial.address,
      city: initial.city,
      zip: initial.zip,
      state: initial.state,
      bankIban: initial.bankIban,
      bankName: initial.bankName,
      bankSwift: initial.bankSwift,
    });
    const [saving, setSaving] = useState(false);
    const [error, setError] = useState('');
    const [success, setSuccess] = useState(false);
    const set = (key, value) => setForm(prev => ({ ...prev, [key]: value }));

    async function save() {
      setError('');
      setSuccess(false);
      setSaving(true);
      try {
        await window.PropArenaApi.updateProfile(form);
        setSuccess(true);
        try { await refreshLiveData?.(); } catch { /* not fatal */ }
        setTimeout(() => setPage('profile'), 600);
      } catch (err) {
        setError(err?.message || 'Saving your profile failed.');
      } finally {
        setSaving(false);
      }
    }

    return (
      <>
        <div className="a-pagehead">
          <div>
            <div style={{ fontSize: 12, color: 'var(--text-dim)', display: 'flex', alignItems: 'center', gap: 6 }}>
              <a onClick={() => setPage('profile')} style={{ cursor: 'pointer', color: 'var(--text-dim)' }}>Profile</a>
              <I.chevronRight size={10}/>
              <span style={{ color: 'var(--text)', fontWeight: 600 }}>Edit</span>
            </div>
            <h1 style={{ marginTop: 6 }}>Edit <em>profile</em>.</h1>
            <div className="sub">Saves go straight to Client_API · changes appear after refresh</div>
          </div>
          <div style={{ display: 'flex', gap: 10 }}>
            <button className="a-btn ghost" onClick={() => setPage('profile')}>Cancel</button>
            <button className="a-btn primary" onClick={save} disabled={saving}>
              {saving ? 'Saving…' : <><I.check size={13}/> Save profile</>}
            </button>
          </div>
        </div>

        {success && (
          <div className="a-section" style={{ marginBottom: 14, background: 'color-mix(in oklab, var(--positive) 12%, var(--surface))', borderColor: 'color-mix(in oklab, var(--positive) 35%, var(--line))', color: 'var(--positive)', fontWeight: 600 }}>
            <I.check size={13} style={{ marginRight: 6 }}/> Profile updated.
          </div>
        )}
        {error && (
          <div className="a-section" style={{ marginBottom: 14, background: 'color-mix(in oklab, var(--negative) 12%, var(--surface))', borderColor: 'color-mix(in oklab, var(--negative) 35%, var(--line))', color: 'var(--negative)', fontWeight: 600 }}>
            {error}
          </div>
        )}

        <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 18 }}>
          <div className="a-section">
            <h3 style={{ margin: '0 0 14px', fontFamily: 'Space Grotesk', fontSize: 16 }}>Personal</h3>
            <ArenaInputFieldLocal label="First name" v={form.firstName} onChange={v => set('firstName', v)}/>
            <ArenaInputFieldLocal label="Last name" v={form.lastName} onChange={v => set('lastName', v)}/>
            <ArenaInputFieldLocal label="Email (contact support to change)" v={form.email} onChange={() => {}} disabled/>
            <ArenaInputFieldLocal label="Date of birth" v={form.dateOfBirth} onChange={v => set('dateOfBirth', v)} type="date"/>
            <div style={{ marginBottom: 12 }}>
              <label style={{ fontSize: 11, color: 'var(--text-dim)', textTransform: 'uppercase', letterSpacing: '.08em', fontWeight: 600, display: 'block', marginBottom: 6 }}>Country</label>
              <select className="a-input" value={form.countryIso} onChange={e => set('countryIso', e.target.value)}>
                <option value="">Select…</option>
                {(countries || []).map(c => {
                  const code = c.code || c.iso || c.iso2 || c.countryCode || c.value || c.alpha2 || c.id;
                  const label = c.printableName || c.name || c.label || c.country || c.title;
                  if (!code || !label) return null;
                  return <option key={code} value={code}>{code} — {label}</option>;
                })}
              </select>
            </div>
            <div style={{ marginBottom: 12 }}>
              <label style={{ fontSize: 11, color: 'var(--text-dim)', textTransform: 'uppercase', letterSpacing: '.08em', fontWeight: 600, display: 'block', marginBottom: 6 }}>Phone</label>
              <div style={{ display: 'grid', gridTemplateColumns: '110px 1fr', gap: 8 }}>
                <input className="a-input" value={form.telephonePrefix || ''} onChange={e => set('telephonePrefix', e.target.value)}/>
                <input className="a-input" value={form.telephone || ''} onChange={e => set('telephone', e.target.value)}/>
              </div>
            </div>
          </div>

          <div className="a-section">
            <h3 style={{ margin: '0 0 14px', fontFamily: 'Space Grotesk', fontSize: 16 }}>Billing address</h3>
            <ArenaInputFieldLocal label="Street address" v={form.address} onChange={v => set('address', v)}/>
            <ArenaInputFieldLocal label="City" v={form.city} onChange={v => set('city', v)}/>
            <ArenaInputFieldLocal label="State / Region" v={form.state} onChange={v => set('state', v)}/>
            <ArenaInputFieldLocal label="ZIP / Postal" v={form.zip} onChange={v => set('zip', v)}/>

            <h3 style={{ margin: '22px 0 14px', fontFamily: 'Space Grotesk', fontSize: 16 }}>Bank · primary wire</h3>
            <ArenaInputFieldLocal label="IBAN / Account #" v={form.bankIban} onChange={v => set('bankIban', v)} mono/>
            <ArenaInputFieldLocal label="Bank name" v={form.bankName} onChange={v => set('bankName', v)}/>
            <ArenaInputFieldLocal label="SWIFT / BIC" v={form.bankSwift} onChange={v => set('bankSwift', v)} mono/>
            <div style={{ marginTop: 4, fontSize: 12, color: 'var(--text-dim)' }}>
              <I.info size={12} style={{ marginRight: 6, verticalAlign: 'middle' }}/>
              Changes to bank details require 2FA confirmation upstream.
            </div>
          </div>
        </div>
      </>
    );
  }

  // ─────────────────────────────────────────────────────────────
  // PASSWORD CHANGE MODAL (live)
  // ─────────────────────────────────────────────────────────────
  function PasswordChangeModal({ onClose, onSuccess }) {
    const [show, setShow] = useState(false);
    const [oldPw, setOldPw] = useState('');
    const [newPw, setNewPw] = useState('');
    const [confirmPw, setConfirmPw] = useState('');
    const [busy, setBusy] = useState(false);
    const [error, setError] = useState('');
    async function submit() {
      setError('');
      if (!oldPw || !newPw) { setError('Current and new passwords are required.'); return; }
      if (newPw.length < 8) { setError('New password must be at least 8 characters.'); return; }
      if (newPw !== confirmPw) { setError('New passwords do not match.'); return; }
      setBusy(true);
      try {
        await window.PropArenaApi.changePassword(oldPw, newPw);
        onSuccess?.();
        onClose();
      } catch (err) {
        setError(err?.message || 'Password change failed.');
      } finally {
        setBusy(false);
      }
    }
    return (
      <ArenaModalShellLocal
        onClose={onClose}
        title="Change password"
        subtitle="You'll be signed out of other sessions."
        footer={<>
          <button className="a-btn ghost" onClick={onClose}>Cancel</button>
          <button className="a-btn primary" onClick={submit} disabled={busy}>{busy ? 'Saving…' : <><I.check size={13}/> Save password</>}</button>
        </>}
      >
        {[['Current password', oldPw, setOldPw], ['New password', newPw, setNewPw], ['Confirm new password', confirmPw, setConfirmPw]].map(([label, value, setter], i) => (
          <div key={i} style={{ marginBottom: 12 }}>
            <label style={{ fontSize: 11, color: 'var(--text-dim)', textTransform: 'uppercase', letterSpacing: '.08em', fontWeight: 600, display: 'block', marginBottom: 6 }}>{label}</label>
            <div style={{ display: 'flex', gap: 6 }}>
              <input
                className="a-input"
                type={show ? 'text' : 'password'}
                placeholder="••••••••"
                value={value}
                onChange={e => setter(e.target.value)}
                style={{ flex: 1 }}
              />
              <button className="a-iconbtn" style={{ width: 40, height: 40 }} onClick={() => setShow(s => !s)} type="button">
                {show ? <I.eyeOff size={14}/> : <I.eye size={14}/>}
              </button>
            </div>
          </div>
        ))}
        {error && <div style={{ fontSize: 12, color: 'var(--negative)', marginTop: 6 }}>{error}</div>}
        <div style={{ marginTop: 8, fontSize: 12, color: 'var(--text-dim)' }}>Use 8+ characters with letters, numbers, and symbols.</div>
      </ArenaModalShellLocal>
    );
  }

  // ─────────────────────────────────────────────────────────────
  // 2FA modals (live)
  // ─────────────────────────────────────────────────────────────
  function TwoFASetupModal({ providerType, onClose, onDone }) {
    const [setupData, setSetupData] = useState(null);
    const [code, setCode] = useState('');
    const [error, setError] = useState('');
    const [busy, setBusy] = useState(false);

    useEffect(() => {
      let cancelled = false;
      window.PropArenaApi.otpSetup(providerType)
        .then(data => { if (!cancelled) setSetupData(data || {}); })
        .catch(err => { if (!cancelled) setError(err?.message || 'Could not start 2FA setup.'); });
      return () => { cancelled = true; };
    }, [providerType]);

    async function activate() {
      setError('');
      if (code.length !== 6) { setError('Enter the 6-digit code from your app.'); return; }
      setBusy(true);
      try {
        await window.PropArenaApi.otpActivate(providerType, code);
        onDone?.();
      } catch (err) {
        setError(err?.message || '2FA activation failed.');
      } finally {
        setBusy(false);
      }
    }

    const secret = setupData?.secret || setupData?.sharedSecret || setupData?.code || '';
    const qrUrl = setupData?.qrCodeUrl || setupData?.qrUrl || setupData?.url || '';

    return (
      <ArenaModalShellLocal
        onClose={onClose}
        title="Scan QR or copy secret"
        subtitle="Add this account to your authenticator app, then enter the 6-digit code."
        width={540}
        footer={<>
          <button className="a-btn ghost" onClick={onClose}>Cancel</button>
          <button className="a-btn primary" disabled={busy || code.length !== 6} onClick={activate}>
            {busy ? 'Activating…' : <><I.check size={13}/> Activate</>}
          </button>
        </>}
      >
        <div style={{ display: 'flex', gap: 18, alignItems: 'flex-start' }}>
          <div style={{ width: 160, height: 160, borderRadius: 12, background: '#fff', display: 'flex', alignItems: 'center', justifyContent: 'center', flex: 'none' }}>
            {qrUrl
              ? <img src={qrUrl} alt="2FA QR" style={{ width: 140, height: 140 }}/>
              : <span style={{ color: '#06070D', fontSize: 11, fontFamily: 'JetBrains Mono', padding: 6, textAlign: 'center' }}>QR pending</span>}
          </div>
          <div style={{ flex: 1 }}>
            <div style={{ fontSize: 11, color: 'var(--text-dim)', textTransform: 'uppercase', letterSpacing: '.08em', fontWeight: 600, marginBottom: 8 }}>Backup secret</div>
            <div style={{ display: 'flex', gap: 6 }}>
              <code style={{ flex: 1, padding: '10px 12px', background: 'var(--surface-2)', border: '1px solid var(--line)', borderRadius: 10, fontFamily: 'JetBrains Mono', fontSize: 13, letterSpacing: '0.04em', wordBreak: 'break-all' }}>{secret || '—'}</code>
              <button className="a-iconbtn" style={{ width: 40, height: 40 }} onClick={() => secret && navigator.clipboard?.writeText(secret)} type="button"><I.copy size={13}/></button>
            </div>
            <div style={{ marginTop: 12, fontSize: 11, color: 'var(--text-dim)' }}>Provider: <b style={{ color: 'var(--text)' }}>{providerType}</b></div>
            <div style={{ marginTop: 18 }}>
              <label style={{ fontSize: 11, color: 'var(--text-dim)', textTransform: 'uppercase', letterSpacing: '.08em', fontWeight: 600, display: 'block', marginBottom: 6 }}>6-digit code</label>
              <input
                className="a-input"
                value={code}
                onChange={e => setCode(e.target.value.replace(/\D/g, '').slice(0, 6))}
                placeholder="123 456"
                style={{ fontFamily: 'JetBrains Mono', fontSize: 22, textAlign: 'center', letterSpacing: '0.4em', padding: '14px 12px' }}
              />
            </div>
            {error && <div style={{ marginTop: 10, fontSize: 12, color: 'var(--negative)' }}>{error}</div>}
          </div>
        </div>
      </ArenaModalShellLocal>
    );
  }

  function TwoFADisableModal({ providerType, onClose, onConfirmed }) {
    const [busy, setBusy] = useState(false);
    const [error, setError] = useState('');
    async function submit() {
      setBusy(true);
      setError('');
      try {
        await window.PropArenaApi.otpDeactivate(providerType);
        onConfirmed?.();
      } catch (err) {
        setError(err?.message || 'Could not disable 2FA.');
      } finally {
        setBusy(false);
      }
    }
    return (
      <ArenaModalShellLocal
        onClose={onClose}
        title="Disable 2FA?"
        subtitle="Your account will be more vulnerable."
        footer={<>
          <button className="a-btn ghost" onClick={onClose}>Cancel</button>
          <button className="a-btn" onClick={submit} disabled={busy} style={{ background: 'color-mix(in oklab, var(--negative) 80%, transparent)', color: '#fff', opacity: busy ? 0.5 : 1 }}>
            {busy ? 'Working…' : 'Deactivate'}
          </button>
        </>}
      >
        <div style={{ padding: 14, background: 'color-mix(in oklab, var(--negative) 10%, transparent)', border: '1px solid color-mix(in oklab, var(--negative) 30%, transparent)', borderRadius: 12, fontSize: 13, marginBottom: 10 }}>
          <I.warn size={13} style={{ marginRight: 6, verticalAlign: 'middle', color: 'var(--negative)' }}/>
          We'll remove the <b>{providerType}</b> provider from your account.
        </div>
        {error && <div style={{ fontSize: 12, color: 'var(--negative)' }}>{error}</div>}
      </ArenaModalShellLocal>
    );
  }

  // ─────────────────────────────────────────────────────────────
  // SECURITY (desktop) — wired
  // ─────────────────────────────────────────────────────────────
  function ArenaSecurityLive() {
    const { setPage } = useApp();
    const [providers, setProviders] = useState([]);
    const [enabled, setEnabled] = useState([]);
    const [loading, setLoading] = useState(true);
    const [providerError, setProviderError] = useState('');
    const [pwModal, setPwModal] = useState(false);
    const [pwSuccess, setPwSuccess] = useState(false);
    const [setupModal, setSetupModal] = useState(null);
    const [disableModal, setDisableModal] = useState(null);
    const [doneMessage, setDoneMessage] = useState('');

    const reload = async () => {
      setLoading(true);
      try {
        const [prov, ena] = await Promise.allSettled([
          window.PropArenaApi.otpProviders(),
          window.PropArenaApi.otpEnabledProviders(),
        ]);
        if (prov.status === 'fulfilled') {
          const list = Array.isArray(prov.value) ? prov.value : Array.isArray(prov.value?.providers) ? prov.value.providers : [];
          setProviders(list);
          setProviderError('');
        } else {
          setProviderError(prov.reason?.message || 'Could not load 2FA providers.');
        }
        if (ena.status === 'fulfilled') setEnabled(Array.isArray(ena.value) ? ena.value : []);
      } finally {
        setLoading(false);
      }
    };

    useEffect(() => { reload(); }, []);

    const enabledTypes = enabled.map(p => (p?.type || p?.providerType || p?.name || '').toString().toLowerCase()).filter(Boolean);
    const knownProviders = providers.length ? providers : enabled.length ? enabled : [{ type: 'GoogleAuthenticator', name: 'Authenticator app' }];

    function isEnabled(provider) {
      const type = (provider?.type || provider?.providerType || provider?.name || '').toString().toLowerCase();
      return enabledTypes.includes(type);
    }

    return (
      <>
        <div className="a-pagehead">
          <div>
            <h1><em>Security</em>.</h1>
            <div className="sub">2FA · password · alerts · KYC</div>
          </div>
          <button className="a-btn secondary" onClick={() => setPage('profile')}><I.chevronLeft size={13}/> Profile</button>
        </div>

        {pwSuccess && (
          <div className="a-section" style={{ marginBottom: 14, color: 'var(--positive)', fontWeight: 600 }}>
            <I.check size={13} style={{ marginRight: 6 }}/> Password updated.
          </div>
        )}
        {doneMessage && (
          <div className="a-section" style={{ marginBottom: 14, color: 'var(--positive)', fontWeight: 600 }}>
            <I.check size={13} style={{ marginRight: 6 }}/> {doneMessage}
          </div>
        )}

        <div style={{ display: 'grid', gridTemplateColumns: '1.3fr 1fr', gap: 18 }}>
          <div style={{ display: 'flex', flexDirection: 'column', gap: 18 }}>
            <div className="a-section">
              <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 12 }}>
                <h3 style={{ margin: 0, fontFamily: 'Space Grotesk', fontSize: 16 }}>Two-factor authentication</h3>
                <button className="a-btn ghost sm" onClick={reload}><I.refresh size={11}/> Refresh</button>
              </div>
              {loading && <LiveLoadingState text="Loading 2FA providers…"/>}
              {!loading && providerError && (
                <div style={{ padding: 12, background: 'color-mix(in oklab, var(--negative) 10%, transparent)', border: '1px solid color-mix(in oklab, var(--negative) 30%, transparent)', borderRadius: 10, fontSize: 12, color: 'var(--negative)' }}>{providerError}</div>
              )}
              {!loading && knownProviders.map((provider, idx) => {
                const type = provider.type || provider.providerType || provider.name || `provider-${idx}`;
                const label = provider.name || provider.label || provider.title || type;
                const on = isEnabled(provider);
                return (
                  <div key={type} style={{ display: 'flex', alignItems: 'center', gap: 12, padding: '12px 0', borderTop: idx > 0 ? '1px solid var(--line-2)' : 'none' }}>
                    <I.shield size={18} style={{ color: on ? 'var(--positive)' : 'var(--text-dim)' }}/>
                    <div style={{ flex: 1 }}>
                      <div style={{ fontWeight: 600 }}>{label}</div>
                      <div style={{ fontSize: 11, color: 'var(--text-dim)' }}>{on ? 'Active · required on sensitive actions' : 'Not yet activated for this account'}</div>
                    </div>
                    {on
                      ? <span className="a-tag success">ENABLED</span>
                      : <span className="a-tag muted">OFF</span>}
                    {on
                      ? <button className="a-btn ghost sm" onClick={() => setDisableModal(type)}>Disable</button>
                      : <button className="a-btn primary sm" onClick={() => setSetupModal(type)}><I.shield size={11}/> Enable</button>}
                  </div>
                );
              })}
            </div>

            <div className="a-section">
              <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 12 }}>
                <h3 style={{ margin: 0, fontFamily: 'Space Grotesk', fontSize: 16 }}>Password</h3>
                <span className="a-tag muted"><I.shield size={9}/> CHANGE ANYTIME</span>
              </div>
              <div style={{ fontSize: 13, color: 'var(--text-dim)', marginBottom: 14 }}>Choose a unique password with at least 8 characters.</div>
              <button className="a-btn primary" onClick={() => { setPwModal(true); setPwSuccess(false); }}><I.lock size={13}/> Change password</button>
            </div>

            <div className="a-section">
              <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 12 }}>
                <h3 style={{ margin: 0, fontFamily: 'Space Grotesk', fontSize: 16 }}>Active sessions</h3>
              </div>
              <div style={{ fontSize: 13, color: 'var(--text-dim)' }}>The Client_API doesn't yet expose a sessions endpoint. Sign out from the top right to terminate this browser session.</div>
            </div>
          </div>

          <div style={{ display: 'flex', flexDirection: 'column', gap: 18 }}>
            <div className="a-section">
              <h3 style={{ margin: '0 0 14px', fontFamily: 'Space Grotesk', fontSize: 16 }}>Email &amp; security alerts</h3>
              <div style={{ fontSize: 13, color: 'var(--text-dim)' }}>
                Account alert preferences are managed centrally — toggle them from your Client_API account settings. Withdrawals always trigger a notification.
              </div>
            </div>

            <div className="a-section">
              <h3 style={{ margin: '0 0 14px', fontFamily: 'Space Grotesk', fontSize: 16 }}>Need to talk to support?</h3>
              <button className="a-btn secondary" onClick={() => setPage('help')}><I.speak size={13}/> Open help &amp; support</button>
            </div>
          </div>
        </div>

        {pwModal && <PasswordChangeModal onClose={() => setPwModal(false)} onSuccess={() => setPwSuccess(true)}/>}
        {setupModal && (
          <TwoFASetupModal
            providerType={setupModal}
            onClose={() => setSetupModal(null)}
            onDone={() => { setSetupModal(null); setDoneMessage('Two-factor authentication enabled.'); reload(); }}
          />
        )}
        {disableModal && (
          <TwoFADisableModal
            providerType={disableModal}
            onClose={() => setDisableModal(null)}
            onConfirmed={() => { setDisableModal(null); setDoneMessage('Two-factor authentication disabled.'); reload(); }}
          />
        )}
      </>
    );
  }

  // ─────────────────────────────────────────────────────────────
  // FORGOT PASSWORD (live reset call)
  // ─────────────────────────────────────────────────────────────
  function ArenaForgotPasswordLive() {
    const { setPage, forgotPassword } = useApp();
    const [mode, setMode] = useState('request'); // request | sent | reset | done
    const [email, setEmail] = useState('');
    const [token, setToken] = useState('');
    const [newPw, setNewPw] = useState('');
    const [show, setShow] = useState(false);
    const [error, setError] = useState('');
    const [busy, setBusy] = useState(false);

    async function requestReset() {
      setError('');
      setBusy(true);
      try {
        await forgotPassword(email.trim());
        setMode('sent');
      } catch (err) {
        setError(err?.message || 'Could not request a password reset.');
      } finally {
        setBusy(false);
      }
    }

    async function submitReset() {
      setError('');
      if (!token.trim()) { setError('Paste the reset code from your email.'); return; }
      if (!newPw || newPw.length < 8) { setError('New password must be at least 8 characters.'); return; }
      setBusy(true);
      try {
        await window.PropArenaApi.resetPassword(token.trim(), newPw);
        setMode('done');
      } catch (err) {
        setError(err?.message || 'Password reset failed.');
      } finally {
        setBusy(false);
      }
    }

    return (
      <div className="auth-bg auth-page">
        <div className="auth-card">
          <button className="auth-back" onClick={() => setPage('login')}><I.chevronLeft size={11}/> Back to login</button>
          <div style={{ marginBottom: 22 }}><PropArenaLockup size={28}/></div>

          {mode === 'request' && (
            <>
              <h1 className="auth-h">Forgot <em>password</em>.</h1>
              <p className="auth-sub">Enter your account email · we'll send a reset link.</p>
              <div className="field">
                <label>Email</label>
                <div className="ctrl">
                  <I.mail size={15} style={{ color: 'var(--text-faint)' }}/>
                  <input type="email" value={email} onChange={e => setEmail(e.target.value)}/>
                </div>
              </div>
              {error && <div className="helper" style={{ color: 'var(--negative)', marginBottom: 10 }}>{error}</div>}
              <button className="auth-submit" onClick={requestReset} disabled={busy}>{busy ? 'Sending…' : <>Send reset link <I.arrowRight size={14}/></>}</button>
              <div style={{ marginTop: 14, fontSize: 12, color: 'var(--text-dim)', textAlign: 'center' }}>
                Already have a token? <a onClick={() => setMode('reset')} style={{ color: 'var(--cyan)', cursor: 'pointer' }}>Enter reset code</a>
              </div>
            </>
          )}

          {mode === 'sent' && (
            <>
              <div style={{ width: 56, height: 56, borderRadius: 14, background: 'color-mix(in oklab, var(--positive) 20%, transparent)', color: 'var(--positive)', display: 'flex', alignItems: 'center', justifyContent: 'center', marginBottom: 18 }}><I.mail size={26}/></div>
              <h1 className="auth-h">Check your <em>email</em>.</h1>
              <p className="auth-sub">If <b style={{ color: 'var(--text)' }}>{email}</b> is registered, you'll receive a reset link within a minute.</p>
              <button className="auth-submit" onClick={() => setMode('reset')}>I have the code <I.arrowRight size={14}/></button>
              <div style={{ marginTop: 14, fontSize: 12, color: 'var(--text-dim)', textAlign: 'center' }}>
                <a onClick={() => setMode('request')} style={{ color: 'var(--cyan)', cursor: 'pointer' }}>Resend</a> · <a onClick={() => setPage('login')} style={{ color: 'var(--cyan)', cursor: 'pointer' }}>Back to login</a>
              </div>
            </>
          )}

          {mode === 'reset' && (
            <>
              <h1 className="auth-h">Reset <em>password</em>.</h1>
              <p className="auth-sub">Paste the reset code from your email, then pick a new password.</p>
              <div className="field">
                <label>Reset code</label>
                <div className="ctrl">
                  <I.lock size={15} style={{ color: 'var(--text-faint)' }}/>
                  <input type="text" placeholder="abc-xyz-123" value={token} onChange={e => setToken(e.target.value)}/>
                </div>
              </div>
              <div className="field">
                <label>New password</label>
                <div className="ctrl">
                  <I.lock size={15} style={{ color: 'var(--text-faint)' }}/>
                  <input type={show ? 'text' : 'password'} placeholder="At least 8 characters" value={newPw} onChange={e => setNewPw(e.target.value)}/>
                  <span onClick={() => setShow(s => !s)} style={{ cursor: 'pointer', display: 'inline-flex' }}>
                    {show ? <I.eyeOff size={15} style={{ color: 'var(--text-faint)' }}/> : <I.eye size={15} style={{ color: 'var(--text-faint)' }}/>}
                  </span>
                </div>
              </div>
              {error && <div className="helper" style={{ color: 'var(--negative)', marginBottom: 10 }}>{error}</div>}
              <button className="auth-submit" onClick={submitReset} disabled={busy}>{busy ? 'Resetting…' : <>Reset password <I.arrowRight size={14}/></>}</button>
            </>
          )}

          {mode === 'done' && (
            <>
              <div style={{ width: 56, height: 56, borderRadius: 14, background: 'color-mix(in oklab, var(--positive) 20%, transparent)', color: 'var(--positive)', display: 'flex', alignItems: 'center', justifyContent: 'center', marginBottom: 18 }}><I.check size={26}/></div>
              <h1 className="auth-h">Password <em>updated</em>.</h1>
              <p className="auth-sub">You can now sign in with your new password.</p>
              <button className="auth-submit" onClick={() => setPage('login')}>Continue to login <I.arrowRight size={14}/></button>
            </>
          )}
        </div>
      </div>
    );
  }

  // ─────────────────────────────────────────────────────────────
  // NOTIFICATIONS (use live messages)
  // ─────────────────────────────────────────────────────────────
  function ArenaNotificationsLive() {
    const { refreshLiveData } = useApp();
    const messages = useLiveMessages();
    const [busy, setBusy] = useState('');
    const [error, setError] = useState('');
    const unread = messages.filter(m => m.unread);

    async function markAll() {
      const ids = unread.map(m => m.id);
      if (!ids.length) return;
      setBusy('mark-all');
      setError('');
      try {
        await window.PropArenaApi.messageMarkRead(ids);
        await refreshLiveData?.();
      } catch (err) {
        setError(err?.message || 'Could not mark notifications as read.');
      } finally {
        setBusy('');
      }
    }

    return (
      <>
        <div className="a-pagehead">
          <div>
            <h1>Notifications.</h1>
            <div className="sub">{unread.length} unread · {messages.length} total</div>
          </div>
          <div style={{ display: 'flex', gap: 10 }}>
            <button className="a-btn secondary" disabled={!unread.length || !!busy} onClick={markAll}>
              <I.check size={13}/> {busy === 'mark-all' ? 'Saving…' : 'Mark all read'}
            </button>
            <button className="a-btn ghost" onClick={() => refreshLiveData?.()}><I.refresh size={13}/> Refresh</button>
          </div>
        </div>

        {error && <div className="a-section" style={{ marginBottom: 14, color: 'var(--negative)', fontSize: 13 }}>{error}</div>}

        <div className="a-section" style={{ padding: 0 }}>
          {!messages.length && <LiveEmptyState icon="bell" title="You're all caught up" sub="No notifications yet. We'll ping you here when there's a payout update, strike, or system message from PropArena."/>}
          {messages.map((m, i) => (
            <div key={m.id} style={{
              display: 'flex', alignItems: 'flex-start', gap: 14,
              padding: 16,
              borderBottom: i < messages.length - 1 ? '1px solid var(--line-2)' : 'none',
              background: m.unread ? 'linear-gradient(90deg, rgba(255,92,245,0.04), transparent)' : 'transparent',
            }}>
              <div style={{
                width: 40, height: 40, borderRadius: 12,
                background: m.unread ? 'linear-gradient(135deg, var(--magenta), var(--cyan))' : 'rgba(255,255,255,0.04)',
                color: m.unread ? '#06070D' : 'var(--text-dim)',
                display: 'flex', alignItems: 'center', justifyContent: 'center',
                flex: 'none',
              }}><I.mail size={18}/></div>
              <div style={{ flex: 1 }}>
                <div style={{ display: 'flex', justifyContent: 'space-between', marginBottom: 2 }}>
                  <span style={{ fontWeight: 600, fontSize: 14 }}>{m.subj}</span>
                  <span className="mono" style={{ fontSize: 11, color: 'var(--text-faint)' }}>{m.tm}</span>
                </div>
                <div style={{ fontSize: 13, color: 'var(--text-dim)' }}>{m.preview}</div>
              </div>
              {m.unread && <div style={{ width: 8, height: 8, borderRadius: 999, background: 'var(--magenta)', boxShadow: '0 0 6px var(--magenta)' }}/>}
            </div>
          ))}
        </div>
      </>
    );
  }

  // ─────────────────────────────────────────────────────────────
  // AFFILIATES (live referral link)
  // ─────────────────────────────────────────────────────────────
  function ArenaAffiliatesLive() {
    const { user } = useApp();
    const wallet = useLiveWallet();
    const name = window.PropArenaApi?.userName?.(user) || 'trader';
    const slug = String(name).toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-+|-+$/g, '') || 'trader';
    const link = `${window.location.origin}/r/${slug}`;
    const lifetimePayouts = Number(wallet?.totalPaid) > 0
      ? Number(wallet.totalPaid)
      : [...(wallet?.payouts || []), ...(wallet?.withdrawals || [])]
          .filter(t => t.status === 'done')
          .reduce((s, t) => s + Math.abs(Number(t.amount) || 0), 0);

    return (
      <>
        <div className="a-pagehead">
          <div>
            <h1>Affiliates &amp; <em>referrals</em>.</h1>
            <div className="sub">Share your link · earn on every challenge purchase</div>
          </div>
        </div>

        <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 14, marginBottom: 22 }}>
          <div className="a-tile glow">
            <div className="l"><I.coins size={11}/> LIFETIME PAYOUTS</div>
            <div className="v">${window.fmtMoneyCompact(lifetimePayouts || 0)}</div>
            <div className="d" style={{ color: 'var(--text-dim)' }}>{(wallet?.payouts || []).length} live rows</div>
          </div>
          <div className="a-tile cyan">
            <div className="l"><I.users size={11}/> COMMISSION</div>
            <div className="v">15%</div>
            <div className="d" style={{ color: 'var(--text-dim)' }}>Per referred challenge</div>
          </div>
          <div className="a-tile">
            <div className="l"><I.fire size={11}/> PAID IN</div>
            <div className="v">USDT</div>
            <div className="d" style={{ color: 'var(--text-dim)' }}>TRC-20 default</div>
          </div>
        </div>

        <div className="a-section" style={{ marginBottom: 18 }}>
          <h3 style={{ margin: '0 0 14px', fontFamily: 'Space Grotesk', fontSize: 16 }}>Your referral link</h3>
          <div style={{ display: 'flex', gap: 8, padding: '12px 16px', background: 'rgba(0,0,0,0.30)', border: '1px solid var(--line-3)', borderRadius: 12 }}>
            <span className="mono" style={{ flex: 1, fontSize: 14, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{link}</span>
            <button className="a-btn primary sm" onClick={() => navigator.clipboard?.writeText(link)}><I.copy size={11}/> Copy</button>
            <button className="a-btn secondary sm" onClick={() => window.open(link, '_blank')}><I.external size={11}/> Open</button>
          </div>
          <div style={{ display: 'grid', gridTemplateColumns: 'repeat(4, 1fr)', gap: 10, marginTop: 14 }}>
            {[
              { l: 'X / Twitter', i: 'speak', url: `https://twitter.com/intent/tweet?text=Trade%20with%20me%20on%20Prop%20Arena&url=${encodeURIComponent(link)}` },
              { l: 'WhatsApp',    i: 'speak', url: `https://wa.me/?text=${encodeURIComponent('Join me on Prop Arena ' + link)}` },
              { l: 'Telegram',    i: 'speak', url: `https://t.me/share/url?url=${encodeURIComponent(link)}&text=${encodeURIComponent('Join me on Prop Arena')}` },
              { l: 'Discord',     i: 'diamond', url: 'https://discord.com/channels/@me' },
            ].map(s => {
              const Ic = I[s.i];
              return (
                <a key={s.l} href={s.url} target="_blank" rel="noopener" className="a-btn secondary sm" style={{ justifyContent: 'center', textDecoration: 'none' }}>
                  <Ic size={12}/> Share to {s.l}
                </a>
              );
            })}
          </div>
        </div>

        <div className="a-section">
          <h3 style={{ margin: '0 0 14px', fontFamily: 'Space Grotesk', fontSize: 16 }}>Recent referrals</h3>
          <LiveEmptyState icon="users" title="No referral attribution yet" sub="Referrals will appear here once Client_API exposes them."/>
        </div>
      </>
    );
  }

  // ─────────────────────────────────────────────────────────────
  // WITHDRAW (desktop): use live wallet balance
  // ─────────────────────────────────────────────────────────────
  function ArenaWithdrawLive() {
    const { setPage } = useApp();
    const wallet = useLiveWallet();
    const available = walletBalanceFromLive(wallet);
    const [amount, setAmount] = useState((available > 0 ? Math.min(available, 600).toFixed(2) : '0.00'));
    const [method, setMethod] = useState(null);
    const amt = parseFloat(amount) || 0;
    function go() {
      try {
        sessionStorage.setItem('pa-desktop-withdraw-amount', amt.toFixed(2));
        sessionStorage.setItem('pa-desktop-withdraw-method', method || '');
      } catch (_) {}
      if (method === 'crypto') setPage('withdrawCrypto');
      if (method === 'wire') setPage('withdrawWire');
    }
    return (
      <>
        <div className="a-pagehead">
          <div>
            <div style={{ fontSize: 12, color: 'var(--text-dim)', display: 'flex', alignItems: 'center', gap: 6 }}>
              <a onClick={() => setPage('wallet')} style={{ cursor: 'pointer', color: 'var(--text-dim)' }}>Wallet</a>
              <I.chevronRight size={10}/>
              <span style={{ color: 'var(--text)', fontWeight: 600 }}>Withdraw</span>
            </div>
            <h1 style={{ marginTop: 6 }}>Withdraw <em>funds</em>.</h1>
            <div className="sub">Available <b className="mono" style={{ color: 'var(--text)' }}>${window.fmtMoney(available)}</b> · Staging withdrawal flow</div>
          </div>
        </div>

        <div style={{ display: 'grid', gridTemplateColumns: '1fr 380px', gap: 18 }}>
          <div className="a-section">
            <h3 style={{ margin: '0 0 14px', fontFamily: 'Space Grotesk', fontSize: 16 }}>Amount</h3>
            <div style={{ display: 'flex', gap: 8 }}>
              <input className="a-input" value={amount} onChange={e => setAmount(e.target.value)} style={{ flex: 1, fontFamily: 'JetBrains Mono', fontSize: 28, fontWeight: 600, letterSpacing: '-0.02em' }}/>
              <button className="a-btn secondary" onClick={() => setAmount(available.toFixed(2))}>Max</button>
            </div>

            <h3 style={{ margin: '24px 0 14px', fontFamily: 'Space Grotesk', fontSize: 16 }}>Method</h3>
            <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 10 }}>
              {[
                { id: 'crypto', l: 'Crypto', sub: 'USDT TRC-20 · 24h', i: 'btc' },
                { id: 'wire',   l: 'Bank wire', sub: '3–5 business days', i: 'bank' },
              ].map(m => (
                <button key={m.id} onClick={() => setMethod(m.id)} style={{
                  padding: 16, borderRadius: 14,
                  border: '1.5px solid ' + (method === m.id ? 'var(--magenta)' : 'var(--line)'),
                  background: method === m.id ? 'rgba(255,92,245,0.08)' : 'var(--surface-2)',
                  color: 'var(--text)', font: 'inherit', textAlign: 'left', cursor: 'pointer',
                  display: 'flex', flexDirection: 'column', gap: 6,
                }}>
                  <div style={{ width: 36, height: 36, borderRadius: 10, background: method === m.id ? 'linear-gradient(135deg, var(--magenta), var(--cyan))' : 'rgba(255,255,255,0.04)', color: method === m.id ? '#06070D' : 'var(--text-dim)', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>{I[m.i]({ size: 18 })}</div>
                  <div style={{ fontWeight: 700, fontSize: 14 }}>{m.l}</div>
                  <div style={{ fontSize: 11, color: 'var(--text-dim)' }}>{m.sub}</div>
                </button>
              ))}
            </div>
          </div>

          <div className="a-section" style={{ background: 'linear-gradient(135deg, rgba(255,92,245,0.10), rgba(92,217,255,0.06)), var(--surface)' }}>
            <div style={{ fontSize: 11, color: 'var(--text-dim)', textTransform: 'uppercase', letterSpacing: '.1em', fontWeight: 600 }}>Summary</div>
            <div className="mono" style={{ fontSize: 32, fontWeight: 700, letterSpacing: '-0.03em', marginTop: 6 }}>${amt.toFixed(2)}</div>
            <div style={{ marginTop: 10, fontSize: 12, color: 'var(--text-dim)' }}>Method: <b style={{ color: 'var(--text)' }}>{method ? method.toUpperCase() : 'select one'}</b></div>
            <div style={{ marginTop: 4, fontSize: 12, color: 'var(--text-dim)' }}>Network fee: <b style={{ color: 'var(--text)' }} className="mono">~$1.20</b></div>
            <div style={{ marginTop: 4, fontSize: 12, color: 'var(--text-dim)' }}>You receive: <b style={{ color: 'var(--text)' }} className="mono">${Math.max(0, amt - 1.2).toFixed(2)}</b></div>
            <button
              className="a-btn primary"
              style={{ width: '100%', marginTop: 16, justifyContent: 'center', height: 46, ...(!method || amt <= 0 || amt > available ? { opacity: 0.5, cursor: 'not-allowed' } : {}) }}
              disabled={!method || amt <= 0 || amt > available}
              onClick={go}
            >
              Continue <I.arrowRight size={13}/>
            </button>
          </div>
        </div>
      </>
    );
  }

  function ArenaWithdrawConfirmLive() {
    const { setPage } = useApp();
    const [code, setCode] = useState('');
    const [step, setStep] = useState('confirm');
    const amount = useMemo(() => {
      try { return parseFloat(sessionStorage.getItem('pa-desktop-withdraw-amount') || '0') || 0; }
      catch (_) { return 0; }
    }, []);
    const networkFee = 1.20;

    function submit() {
      if (code.length !== 6) return;
      setStep('processing');
      setTimeout(() => {
        window.arenaAddLocalWalletTx?.({
          kind: 'withdraw',
          label: `Wallet withdrawal (staging)`,
          method: 'Staging withdrawal',
          amount: -amount,
          status: 'done',
        });
        setStep('success');
      }, 1500);
    }

    if (step === 'success') return <ArenaTxSuccessLocal kind="withdraw" amount={amount} setPage={setPage}/>;

    return (
      <>
        <div className="a-pagehead">
          <div>
            <div style={{ fontSize: 12, color: 'var(--text-dim)', display: 'flex', alignItems: 'center', gap: 6 }}>
              <a onClick={() => setPage('withdraw')} style={{ cursor: 'pointer', color: 'var(--text-dim)' }}>Withdraw</a>
              <I.chevronRight size={10}/>
              <span style={{ color: 'var(--text)', fontWeight: 600 }}>Confirm</span>
            </div>
            <h1 style={{ marginTop: 6 }}>Review &amp; <em>confirm</em>.</h1>
            <div className="sub">Final review before we submit your withdrawal</div>
          </div>
          <button className="a-btn ghost" onClick={() => setPage('withdraw')}><I.chevronLeft size={13}/> Edit</button>
        </div>

        <div style={{ display: 'grid', gridTemplateColumns: '1fr 380px', gap: 18, maxWidth: 1080 }}>
          <div className="a-section" style={{ background: 'linear-gradient(135deg, rgba(255,92,245,0.10), rgba(92,217,255,0.06)), var(--surface)' }}>
            <div style={{ fontSize: 11, color: 'var(--text-dim)', textTransform: 'uppercase', letterSpacing: '.1em', fontWeight: 600 }}>You'll receive</div>
            <div className="mono" style={{ fontSize: 40, fontWeight: 700, letterSpacing: '-0.03em', marginTop: 4 }}>${Math.max(0, amount - networkFee).toFixed(2)}</div>
            <div style={{ marginTop: 4, fontSize: 13, color: 'var(--text-dim)' }}>USDT TRC-20 · arrival in ~24h</div>

            <div style={{ marginTop: 22, padding: 16, background: 'var(--surface-2)', border: '1px solid var(--line)', borderRadius: 12 }}>
              <ArenaKvLocal label="From" value="Wallet balance"/>
              <ArenaKvLocal label="Amount" value={'$' + amount.toFixed(2)} mono/>
              <ArenaKvLocal label="Method" value="USDT TRC-20"/>
              <ArenaKvLocal label="Network fee" value={'$' + networkFee.toFixed(2)} mono/>
            </div>
          </div>

          <div className="a-section" style={{ alignSelf: 'start' }}>
            <h3 style={{ margin: '0 0 12px', fontFamily: 'Space Grotesk', fontSize: 16 }}>2FA required</h3>
            {step === 'confirm' && (
              <>
                <div style={{ fontSize: 13, color: 'var(--text-dim)', marginBottom: 12 }}>Enter the 6-digit code from your authenticator app.</div>
                <input
                  className="a-input"
                  value={code}
                  onChange={e => setCode(e.target.value.replace(/\D/g, '').slice(0, 6))}
                  placeholder="123 456"
                  style={{ fontFamily: 'JetBrains Mono', fontSize: 24, textAlign: 'center', letterSpacing: '0.4em', padding: '18px 14px' }}
                />
                <button
                  className="a-btn primary"
                  onClick={submit}
                  disabled={code.length !== 6}
                  style={{ width: '100%', marginTop: 16, justifyContent: 'center', height: 46, ...(code.length !== 6 ? { opacity: 0.5, cursor: 'not-allowed' } : {}) }}
                >
                  <I.shield size={13}/> Confirm withdrawal
                </button>
                <div style={{ marginTop: 10, fontSize: 11, color: 'var(--text-dim)' }}>
                  <I.info size={11} style={{ marginRight: 4, verticalAlign: 'middle' }}/>
                  Staging confirmation only — no real funds move.
                </div>
              </>
            )}
            {step === 'processing' && (
              <div style={{ padding: '40px 0', textAlign: 'center' }}>
                <div style={{ width: 48, height: 48, border: '3px solid var(--line)', borderTopColor: 'var(--magenta)', borderRadius: '50%', animation: 'spin 0.8s linear infinite', margin: '0 auto' }}/>
                <div style={{ marginTop: 14, fontSize: 14, fontWeight: 600 }}>Submitting…</div>
                <style>{`@keyframes spin { to { transform: rotate(360deg); } }`}</style>
              </div>
            )}
          </div>
        </div>
      </>
    );
  }

  // ─────────────────────────────────────────────────────────────
  // MOBILE PROFILE EDIT (live save)
  // ─────────────────────────────────────────────────────────────
  function ArenaMobileProfileEditLive() {
    const { setPage, user, liveData, refreshLiveData } = useApp();
    const countries = liveData?.countries || [];
    const initial = useMemo(() => profileFromUser(user, countries), [user, countries.length]);
    const [form, setForm] = useState({
      firstName: initial.firstName || (initial.name.split(/\s+/)[0] || ''),
      lastName: initial.lastName || initial.name.split(/\s+/).slice(1).join(' '),
      telephonePrefix: initial.telephonePrefix || '+1',
      telephone: initial.telephone,
      countryIso: initial.countryIso,
      address: initial.address,
      city: initial.city,
      zip: initial.zip,
    });
    const [busy, setBusy] = useState(false);
    const [error, setError] = useState('');
    const [success, setSuccess] = useState(false);
    const set = (k, v) => setForm(prev => ({ ...prev, [k]: v }));

    async function save() {
      setError('');
      setBusy(true);
      try {
        await window.PropArenaApi.updateProfile(form);
        setSuccess(true);
        try { await refreshLiveData?.(); } catch { /* not fatal */ }
        setTimeout(() => setPage('profile'), 500);
      } catch (err) {
        setError(err?.message || 'Saving your profile failed.');
      } finally {
        setBusy(false);
      }
    }

    return (
      <div className="am-page">
        <ArenaMobilePageHeadLocal title="Edit profile" back="profile"/>
        {success && <div className="am-card" style={{ color: 'var(--positive)', fontWeight: 600 }}><I.check size={13} style={{ marginRight: 6 }}/> Profile updated.</div>}
        {error && <div className="am-card" style={{ color: 'var(--negative)', fontWeight: 600 }}>{error}</div>}
        <div className="am-card">
          {[
            ['First name', 'firstName'],
            ['Last name', 'lastName'],
            ['Phone prefix', 'telephonePrefix'],
            ['Phone', 'telephone'],
            ['Country (ISO)', 'countryIso'],
            ['Address', 'address'],
            ['City', 'city'],
            ['ZIP', 'zip'],
          ].map(([label, key]) => (
            <div key={key} style={{ marginBottom: 10 }}>
              <label style={{ fontSize: 10, color: 'var(--text-dim)', textTransform: 'uppercase', letterSpacing: '.08em', fontWeight: 600, display: 'block', marginBottom: 4 }}>{label}</label>
              <input className="a-input" value={form[key] || ''} onChange={e => set(key, e.target.value)}/>
            </div>
          ))}
          <button className="a-btn primary" style={{ width: '100%', justifyContent: 'center', marginTop: 8 }} onClick={save} disabled={busy}>
            {busy ? 'Saving…' : <><I.check size={13}/> Save</>}
          </button>
        </div>
      </div>
    );
  }

  // ─────────────────────────────────────────────────────────────
  // MOBILE SECURITY (live 2FA + password)
  // ─────────────────────────────────────────────────────────────
  function ArenaMobileSecurityLive() {
    const [enabled, setEnabled] = useState([]);
    const [providers, setProviders] = useState([]);
    const [loading, setLoading] = useState(true);
    const [pwModal, setPwModal] = useState(false);
    const [setupModal, setSetupModal] = useState(null);
    const [disableModal, setDisableModal] = useState(null);

    const reload = async () => {
      setLoading(true);
      const [prov, ena] = await Promise.allSettled([
        window.PropArenaApi.otpProviders(),
        window.PropArenaApi.otpEnabledProviders(),
      ]);
      if (prov.status === 'fulfilled') {
        const list = Array.isArray(prov.value) ? prov.value : Array.isArray(prov.value?.providers) ? prov.value.providers : [];
        setProviders(list);
      }
      if (ena.status === 'fulfilled') setEnabled(Array.isArray(ena.value) ? ena.value : []);
      setLoading(false);
    };

    useEffect(() => { reload(); }, []);
    const enabledTypes = enabled.map(p => (p?.type || p?.providerType || p?.name || '').toString().toLowerCase()).filter(Boolean);
    const list = providers.length ? providers : enabled.length ? enabled : [{ type: 'GoogleAuthenticator', name: 'Authenticator app' }];

    return (
      <div className="am-page">
        <ArenaMobilePageHeadLocal title="Security" back="profile"/>
        <div className="am-card" style={{ display: 'flex', alignItems: 'center', gap: 12 }}>
          <I.shield size={20} style={{ color: 'var(--cyan)' }}/>
          <div style={{ flex: 1 }}>
            <div style={{ fontWeight: 600 }}>Two-factor auth</div>
            <div style={{ fontSize: 11, color: 'var(--text-dim)' }}>
              {loading ? 'Loading 2FA providers…' : enabledTypes.length ? `${enabledTypes.length} provider${enabledTypes.length === 1 ? '' : 's'} active` : 'Not yet activated'}
            </div>
          </div>
          <button className="a-btn ghost sm" onClick={reload} disabled={loading}><I.refresh size={11}/></button>
        </div>
        {!loading && list.map((p, idx) => {
          const type = p.type || p.providerType || p.name || `provider-${idx}`;
          const label = p.name || p.label || type;
          const on = enabledTypes.includes(String(type).toLowerCase());
          return (
            <div key={type} className="am-card" style={{ display: 'flex', alignItems: 'center', gap: 12 }}>
              <I.shield size={18} style={{ color: on ? 'var(--positive)' : 'var(--text-dim)' }}/>
              <div style={{ flex: 1 }}>
                <div style={{ fontWeight: 600, fontSize: 13 }}>{label}</div>
                <div style={{ fontSize: 11, color: 'var(--text-dim)' }}>{on ? 'Enabled' : 'Not active'}</div>
              </div>
              {on
                ? <button className="a-btn ghost sm" onClick={() => setDisableModal(type)}>Disable</button>
                : <button className="a-btn primary sm" onClick={() => setSetupModal(type)}>Enable</button>}
            </div>
          );
        })}

        <div className="am-card" style={{ display: 'flex', alignItems: 'center', gap: 12 }}>
          <I.lock size={20} style={{ color: 'var(--text-dim)' }}/>
          <div style={{ flex: 1 }}>
            <div style={{ fontWeight: 600 }}>Password</div>
            <div style={{ fontSize: 11, color: 'var(--text-dim)' }}>Choose a unique password (8+ characters).</div>
          </div>
          <button className="a-btn secondary sm" onClick={() => setPwModal(true)}>Change</button>
        </div>

        <div className="am-card" style={{ display: 'flex', alignItems: 'center', gap: 12 }}>
          <I.info size={18} style={{ color: 'var(--text-dim)' }}/>
          <div style={{ flex: 1, fontSize: 12, color: 'var(--text-dim)' }}>
            Active sessions aren't yet exposed by the Client_API. Sign out from your profile menu to terminate this device.
          </div>
        </div>

        {pwModal && <PasswordChangeModal onClose={() => setPwModal(false)} onSuccess={() => {}}/>}
        {setupModal && (
          <TwoFASetupModal
            providerType={setupModal}
            onClose={() => setSetupModal(null)}
            onDone={() => { setSetupModal(null); reload(); }}
          />
        )}
        {disableModal && (
          <TwoFADisableModal
            providerType={disableModal}
            onClose={() => setDisableModal(null)}
            onConfirmed={() => { setDisableModal(null); reload(); }}
          />
        )}
      </div>
    );
  }

  // ─────────────────────────────────────────────────────────────
  // NEW CHALLENGE (fix undefined `login` bug + checkout flow)
  // ─────────────────────────────────────────────────────────────
  function ArenaNewChallengeLive() {
    const { setPage, refreshLiveData, user } = useApp();
    const wallet = useLiveWallet();
    const walletBalance = walletBalanceFromLive(wallet);
    // Backend resolves the authenticated user from the session cookie; we just
    // pass a sensible currency. Prefer the user's stored currency, fall back
    // to USD (matches reference `buyOffer(token, brokerId, 'USD')` posture).
    const checkoutCurrency = (user?.currency && String(user.currency).trim()) || 'USD';
    const purchaseEnabled = Boolean(window.PropArenaApi?.isPropPurchaseEnabled?.());

    // Demo fallback plans — used only while the live catalog is loading,
    // when /proptrade/all errors, or returns nothing. Never presented as
    // backend-derived.
    const fallbackPlanObj = {
      one: { name: 'Signature One', steps: 1, sizes: [5000, 10000, 25000, 50000, 100000, 200000], target: '8%', dd: '6%', daily: '4%', sub: '1-step · fastest path', tag: 'FAST' },
      sig: { name: 'Signature',     steps: 2, sizes: [25000, 50000, 100000, 200000],              target: '8% / 5%', dd: '8%', daily: '5%', sub: '2-step · most popular', tag: 'POPULAR' },
      pro: { name: 'Signature Pro', steps: 3, sizes: [50000, 100000, 200000],                     target: '10% / 5% / 5%', dd: '10%', daily: '5%', sub: '3-step · larger DD', tag: 'BIG DD' },
    };
    const fallbackPriceMap = { one: { 5000:59, 10000:89, 25000:199, 50000:299, 100000:539, 200000:999 }, sig: { 25000:159, 50000:269, 100000:499, 200000:899 }, pro: { 50000:219, 100000:419, 200000:749 } };

    const [catalogStatus, setCatalogStatus] = useState('idle'); // idle | loading | live | empty | error
    const [catalog, setCatalog] = useState(null); // { available, planObj, planKeys, byClass }
    const [livePlanKey, setLivePlanKey] = useState('');
    const [plan, setPlan] = useState('sig');
    const [size, setSize] = useState(50000);
    const [checkout, setCheckout] = useState(null);
    const [orderRef, setOrderRef] = useState('');

    useEffect(() => {
      if (!window.PropArenaApi?.propPackages || !window.PropArenaApi?.normalizePropPackages) {
        setCatalogStatus('error');
        return;
      }
      let cancelled = false;
      setCatalogStatus('loading');
      window.PropArenaApi.propPackages()
        .then((rows) => {
          if (cancelled) return;
          const normalized = window.PropArenaApi.normalizePropPackages(rows);
          if (!normalized.available) {
            setCatalog(normalized);
            setCatalogStatus('empty');
            return;
          }
          setCatalog(normalized);
          setCatalogStatus('live');
          // Prefer a "challenge"-class plan if present, else first available.
          const firstKey = (normalized.byClass.challenge[0]?.key)
            || (normalized.byClass.accelerated[0]?.key)
            || (normalized.byClass.funded[0]?.key)
            || normalized.planKeys[0];
          setLivePlanKey(firstKey);
        })
        .catch(() => {
          if (cancelled) return;
          setCatalogStatus('error');
        });
      return () => { cancelled = true; };
    }, []);

    const usingLive = catalogStatus === 'live' && catalog && catalog.planObj[livePlanKey];
    const cur = usingLive ? catalog.planObj[livePlanKey] : fallbackPlanObj[plan];
    const planObj = usingLive ? catalog.planObj : fallbackPlanObj;
    const planKeys = usingLive ? catalog.planKeys : Object.keys(fallbackPlanObj);

    if (cur && !cur.sizes.includes(size)) setSize(cur.sizes[0]);

    // Pricing source: Benjamin's 2026-05-25 contract — `selectedPackage.affiliateParam2`
    // is the package price in cents. `normalizePropPackages` captures it as
    // `variant.priceUsd`. When the live variant carries a price we use it; if
    // the field is missing we hold pricing at unavailable rather than fake a
    // number.
    const liveVariant = usingLive ? cur?.variantBySize?.[String(size)] : null;
    const livePrice = liveVariant?.priceUsd ?? null;
    const price = usingLive ? livePrice : (fallbackPriceMap[plan]?.[size] || 0);
    const orig = usingLive ? null : Math.round((price || 0) * 1.4);
    // Per Benjamin 2026-05-25 — no invented add-ons. Total = live package price
    // only. Real upgrade fields (affiliateParam16/affiliateParam19) still flow
    // through normalizePropPackages for future upgrade flows but are NOT added
    // to the checkout total here.
    const total = usingLive
      ? (livePrice !== null ? livePrice : 0)
      : price;
    const priceUnavailable = usingLive && livePrice === null;
    const selectPlan = (k) => { if (usingLive) setLivePlanKey(k); else setPlan(k); };
    const activePlanKey = usingLive ? livePlanKey : plan;

    if (checkout === 'success') {
      return (
        <NewChallengeSuccess
          plan={cur?.name || ''}
          size={size}
          total={total}
          orderRef={orderRef}
          onAccounts={() => setPage('accounts')}
        />
      );
    }

    const subCopy = usingLive
      ? `Live catalog · ${catalog.planKeys.length} package group${catalog.planKeys.length === 1 ? '' : 's'} from Prop backend · Wallet checkout`
      : catalogStatus === 'loading' ? 'Loading live catalog from Prop backend…'
      : catalogStatus === 'empty'   ? 'Live catalog returned no packages · showing demo plans'
      : catalogStatus === 'error'   ? 'Couldn’t load live catalog · showing demo plans'
      : 'Demo checkout · wallet payment preview';

    return (
      <>
        <div className="a-pagehead">
          <div>
            <h1>New <em>challenge</em>.</h1>
            <div className="sub">{subCopy}</div>
          </div>
        </div>

        <div style={{ display: 'grid', gridTemplateColumns: '1.5fr 1fr', gap: 22 }}>
          <div style={{ display: 'flex', flexDirection: 'column', gap: 18 }}>
            <div className="a-section">
              <div style={{ display: 'flex', alignItems: 'center', gap: 10, marginBottom: 14 }}>
                <div style={{ width: 26, height: 26, borderRadius: 8, background: 'linear-gradient(135deg, var(--magenta), var(--cyan))', color: '#06070D', display: 'flex', alignItems: 'center', justifyContent: 'center', fontWeight: 700, fontSize: 12 }}>1</div>
                <div style={{ fontFamily: 'Space Grotesk', fontWeight: 700, fontSize: 16 }}>Challenge type</div>
              </div>
              <div style={{ display: 'grid', gridTemplateColumns: planKeys.length <= 3 ? 'repeat(3, 1fr)' : 'repeat(auto-fit, minmax(220px, 1fr))', gap: 10 }}>
                {planKeys.map((k) => {
                  const p = planObj[k];
                  if (!p) return null;
                  const active = activePlanKey === k;
                  return (
                    <button key={k} onClick={() => selectPlan(k)} style={{
                      padding: 16, borderRadius: 14,
                      border: '1.5px solid ' + (active ? 'var(--magenta)' : 'var(--line)'),
                      background: active ? 'linear-gradient(135deg, rgba(255,92,245,0.10), rgba(92,217,255,0.04)), var(--surface-2)' : 'var(--surface-2)',
                      color: 'var(--text)', font: 'inherit', textAlign: 'left',
                      cursor: 'pointer',
                      display: 'flex', flexDirection: 'column', gap: 12,
                    }}>
                      <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start' }}>
                        <span style={{ fontSize: 10, fontWeight: 700, letterSpacing: '.06em', padding: '3px 8px', borderRadius: 999, border: '1px solid ' + (active ? 'var(--magenta)' : 'var(--line-3)'), color: active ? 'var(--magenta)' : 'var(--text-dim)' }}>{p.steps}-STEP</span>
                        {p.tag === 'POPULAR' && <span style={{ fontSize: 9, fontWeight: 700, padding: '3px 8px', borderRadius: 4, background: 'linear-gradient(135deg, var(--magenta), var(--cyan))', color: '#06070D', letterSpacing: '.06em' }}>POPULAR</span>}
                      </div>
                      <div>
                        <div style={{ fontFamily: 'Space Grotesk', fontSize: 18, fontWeight: 700, letterSpacing: '-0.02em' }}>{p.name}</div>
                        <div style={{ fontSize: 11, color: 'var(--text-dim)', marginTop: 2 }}>{p.sub}</div>
                      </div>
                      <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr 1fr', gap: 8, paddingTop: 10, borderTop: '1px solid var(--line-2)' }}>
                        {[['Target', p.target], ['Daily', p.daily], ['Max DD', p.dd]].map(([l, v]) => (
                          <div key={l}>
                            <div style={{ fontSize: 9, color: 'var(--text-faint)', letterSpacing: '.06em', textTransform: 'uppercase', fontWeight: 600 }}>{l}</div>
                            <div className="mono" style={{ fontSize: 12, fontWeight: 600, marginTop: 2 }}>{v}</div>
                          </div>
                        ))}
                      </div>
                    </button>
                  );
                })}
              </div>
            </div>

            <div className="a-section">
              <div style={{ display: 'flex', alignItems: 'center', gap: 10, marginBottom: 14 }}>
                <div style={{ width: 26, height: 26, borderRadius: 8, background: 'linear-gradient(135deg, var(--magenta), var(--cyan))', color: '#06070D', display: 'flex', alignItems: 'center', justifyContent: 'center', fontWeight: 700, fontSize: 12 }}>2</div>
                <div style={{ fontFamily: 'Space Grotesk', fontWeight: 700, fontSize: 16 }}>Account size</div>
              </div>
              <div style={{ display: 'flex', flexWrap: 'wrap', gap: 8 }}>
                {(cur?.sizes || []).map(s => {
                  const variantPrice = usingLive ? (cur?.variantBySize?.[String(s)]?.priceUsd ?? null) : null;
                  const tag = usingLive
                    ? (variantPrice !== null ? '$' + variantPrice.toFixed(2) : 'Price unavailable')
                    : ('$' + (fallbackPriceMap[plan]?.[s] || 0));
                  return (
                    <button key={s} onClick={() => setSize(s)} style={{
                      padding: '12px 18px', borderRadius: 10,
                      border: '1.5px solid ' + (size === s ? 'var(--magenta)' : 'var(--line)'),
                      background: size === s ? 'rgba(255,92,245,0.10)' : 'var(--surface-2)',
                      color: 'var(--text)', font: 'inherit', fontWeight: 700, fontSize: 14, cursor: 'pointer',
                      fontFamily: 'JetBrains Mono', letterSpacing: '-0.01em',
                      display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 2, minWidth: 90,
                    }}>
                      <span style={{ fontSize: 17 }}>${window.fmtMoneyCompact(s)}</span>
                      <span className="mono" style={{ fontSize: 10, color: size === s ? 'var(--magenta)' : 'var(--text-faint)', fontWeight: 500 }}>{tag}</span>
                    </button>
                  );
                })}
              </div>
            </div>

          </div>

          <div className="a-section" style={{ position: 'sticky', top: 100, alignSelf: 'start', background: 'linear-gradient(135deg, rgba(255,92,245,0.08), rgba(92,217,255,0.04)), var(--surface)' }}>
            <div style={{ fontSize: 11, color: 'var(--text-dim)', textTransform: 'uppercase', letterSpacing: '.1em', fontWeight: 600, marginBottom: 6 }}>Order summary</div>
            <div style={{ fontFamily: 'Space Grotesk', fontWeight: 700, fontSize: 24, letterSpacing: '-0.02em' }}>{cur?.name} ${window.fmtMoneyCompact(size)}</div>
            <div style={{ fontSize: 12, color: 'var(--text-dim)', marginTop: 4 }}>{cur?.steps}-step · target {cur?.target}</div>
            {usingLive && (
              <div style={{ display: 'grid', gridTemplateColumns: 'repeat(2, 1fr)', gap: 8, marginTop: 12, padding: 12, background: 'var(--surface-2)', borderRadius: 10, fontSize: 11 }}>
                {cur?.leverage && cur.leverage !== '—' && (
                  <div><span style={{ color: 'var(--text-faint)' }}>Leverage</span> <span className="mono" style={{ fontWeight: 600 }}>{cur.leverage}</span></div>
                )}
                {cur?.profitSplit && cur.profitSplit !== '—' && (
                  <div><span style={{ color: 'var(--text-faint)' }}>Profit split</span> <span className="mono" style={{ fontWeight: 600 }}>{cur.profitSplit}</span></div>
                )}
                {cur?.dd && cur.dd !== '—' && (
                  <div><span style={{ color: 'var(--text-faint)' }}>Max DD</span> <span className="mono" style={{ fontWeight: 600 }}>{cur.dd}</span></div>
                )}
                {cur?.daily && cur.daily !== '—' && (
                  <div><span style={{ color: 'var(--text-faint)' }}>Daily loss</span> <span className="mono" style={{ fontWeight: 600 }}>{cur.daily}</span></div>
                )}
                {cur?.server && (
                  <div style={{ gridColumn: '1 / -1' }}><span style={{ color: 'var(--text-faint)' }}>Server</span> <span className="mono" style={{ fontWeight: 600 }}>{cur.server}</span></div>
                )}
              </div>
            )}

            <div style={{ marginTop: 18, paddingTop: 16, borderTop: '1px solid var(--line-2)', display: 'flex', flexDirection: 'column', gap: 10 }}>
              <div style={{ display: 'flex', justifyContent: 'space-between', fontSize: 13 }}>
                <span style={{ color: 'var(--text-dim)' }}>Plan</span>
                {usingLive
                  ? (priceUnavailable
                      ? <span className="mono" style={{ color: 'var(--text-faint)' }}>Unavailable</span>
                      : <span className="mono">${livePrice.toFixed(2)}</span>)
                  : <span className="mono"><span style={{ color: 'var(--text-faint)', textDecoration: 'line-through', marginRight: 6 }}>${orig}</span>${price}</span>}
              </div>
            </div>
            <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'baseline', marginTop: 14, paddingTop: 14, borderTop: '1px solid var(--line)' }}>
              <span style={{ fontSize: 13, color: 'var(--text-dim)' }}>Total</span>
              <span className="mono" style={{ fontSize: 32, fontWeight: 700, letterSpacing: '-0.025em' }}>{priceUnavailable ? 'Unavailable' : `$${Number(total).toFixed(2)}`}</span>
            </div>
            <button className="a-btn primary" disabled={priceUnavailable} style={{ width: '100%', marginTop: 16, height: 48, justifyContent: 'center', opacity: priceUnavailable ? 0.55 : 1, cursor: priceUnavailable ? 'not-allowed' : 'pointer' }} onClick={() => !priceUnavailable && setCheckout('modal')}>
              <I.cards size={13}/> {priceUnavailable ? 'Price unavailable' : `Checkout · $${Number(total).toFixed(2)}`}
            </button>
            {priceUnavailable && (
              <div style={{ marginTop: 8, fontSize: 11, color: 'var(--text-faint)', textAlign: 'center' }}>
                affiliateParam2 missing on this package — refresh or ask support
              </div>
            )}
            <div style={{ display: 'flex', gap: 6, marginTop: 10, justifyContent: 'center', alignItems: 'center', flexWrap: 'wrap', fontSize: 11, color: 'var(--text-faint)' }}>
              <I.wallet size={12}/> Wallet checkout · powered by Prop backend
            </div>
          </div>
        </div>

        {checkout === 'modal' && (
          <NewChallengeCheckoutModal
            plan={cur?.name || ''}
            size={size}
            total={total}
            usingLive={Boolean(usingLive)}
            variant={usingLive ? cur?.variantBySize?.[String(size)] : null}
            walletBalance={walletBalance}
            currency={checkoutCurrency}
            purchaseEnabled={purchaseEnabled}
            onClose={() => setCheckout(null)}
            onSuccess={(ref) => {
              setOrderRef(ref);
              setCheckout('success');
              refreshLiveData?.().catch(() => {});
            }}
          />
        )}
      </>
    );
  }

  function NewChallengeCheckoutModal({ plan, size, total, usingLive, variant, walletBalance, currency, purchaseEnabled, onClose, onSuccess }) {
    // Live mode: only wallet checkout is wired (verified Prop /proptrade/buy-offer).
    // Card/crypto/wire have no verified backend contract in PropArena, so they
    // stay disabled with clear copy when usingLive. In fallback/demo mode the
    // existing local-only flow is preserved.
    const [method, setMethod] = useState(usingLive ? 'wallet' : 'card');
    const [step, setStep] = useState('form');
    const [card, setCard] = useState({ number: '', expiry: '', cvc: '', name: '' });
    const [submitError, setSubmitError] = useState('');
    const liveMode = Boolean(usingLive);
    const packageId = variant?.packageId ?? null;
    const livePrice = liveMode ? (variant?.priceUsd ?? null) : null;
    const livePriceAvailable = liveMode && livePrice !== null;
    const fee = (!liveMode && method === 'card') ? +(total * 0.025).toFixed(2) : 0;
    const finalTotal = livePriceAvailable ? livePrice : total + fee;
    const balance = Number(walletBalance) || 0;
    // When the live catalog exposes a real price (Benjamin's affiliateParam2
    // contract), require the wallet to actually cover it. Without a known
    // price we still let the backend reject, but the user is shown that the
    // price is unavailable.
    const balanceSufficient = liveMode
      ? (livePriceAvailable ? balance >= livePrice : balance > 0)
      : balance >= finalTotal;
    const liveDirectDisabled = liveMode;
    const walletDisabledReason = !liveMode ? '' : (!purchaseEnabled
      ? 'Wallet checkout pending payment activation. Contact support to enable.'
      : !packageId
        ? 'Package id missing from live catalog — refresh and retry.'
        : !livePriceAvailable
          ? 'Package price unavailable from live catalog — refresh and retry.'
          : !balanceSufficient
            ? `Wallet balance ($${balance.toFixed(2)}) is less than the package price ($${livePrice.toFixed(2)}). Top up before purchasing.`
            : '');
    const liveCtaDisabled = liveMode && (method !== 'wallet' || Boolean(walletDisabledReason));

    function submit() {
      setSubmitError('');
      // Live path: fire the verified Prop /proptrade/buy-offer mutation and
      // let the backend charge wallet + provision the account. Never write
      // a local fake tx for the live path — the live wallet refresh will
      // pick up the real transaction row.
      if (liveMode) {
        if (method !== 'wallet') {
          setSubmitError('Only wallet checkout is wired for live packages.');
          return;
        }
        if (!packageId) {
          setSubmitError('Package id missing — refresh and retry.');
          return;
        }
        if (!purchaseEnabled || typeof window.PropArenaApi?.propBuyOffer !== 'function') {
          setSubmitError('Wallet checkout is gated. Contact support to enable.');
          return;
        }
        setStep('processing');
        window.PropArenaApi.propBuyOffer(packageId, currency || 'USD')
          .then((result) => {
            const brokerUserId = result && (result.brokerUserId ?? result.brokerUserID ?? result.id);
            const ref = brokerUserId ? `PA-${brokerUserId}` : `PA-${Date.now().toString(36).toUpperCase()}`;
            onSuccess(ref);
          })
          .catch((err) => {
            setStep('form');
            const msg = err && err.message ? String(err.message) : 'Purchase failed. Please try again.';
            setSubmitError(msg);
          });
        return;
      }
      // Real-only checkout (Benjamin 2026-05-25): if the live gate is off
      // and we reach the fallback branch, surface a clear error instead of
      // writing a fake local wallet transaction. The Buy Package activity
      // table must only reflect real /proptrade/buy-offer mutations.
      setSubmitError('Checkout is unavailable — live purchase gate is off. Refresh and retry.');
    }

    return (
      <>
        <div onClick={onClose} style={{ position: 'fixed', inset: 0, background: 'rgba(0,0,0,0.62)', backdropFilter: 'blur(6px)', zIndex: 200 }}/>
        <div style={{
          position: 'fixed', top: '50%', left: '50%', transform: 'translate(-50%, -50%)',
          width: 640, maxWidth: '94vw', maxHeight: '90vh', zIndex: 201,
          background: 'var(--surface)', border: '1px solid var(--line-3)',
          borderRadius: 22,
          boxShadow: '0 30px 80px rgba(0,0,0,0.6)',
          display: 'flex', flexDirection: 'column', overflow: 'hidden',
        }}>
          <div style={{ padding: '18px 24px', borderBottom: '1px solid var(--line)', display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
            <div>
              <div style={{ fontFamily: 'Space Grotesk', fontSize: 18, fontWeight: 700, letterSpacing: '-0.02em' }}>Checkout</div>
              <div style={{ fontSize: 12, color: 'var(--text-dim)', marginTop: 2 }}>{plan} · ${window.fmtMoneyCompact(size)}</div>
            </div>
            <button className="a-iconbtn" onClick={onClose}><I.x size={13}/></button>
          </div>

          <div style={{ display: 'grid', gridTemplateColumns: '1fr 1.1fr', flex: 1, overflow: 'hidden' }}>
            <div style={{ padding: 24, background: 'var(--surface)', borderRight: '1px solid var(--line)', overflowY: 'auto' }}>
              <div style={{ fontSize: 12, color: 'var(--text-dim)' }}>You're buying</div>
              <div className="mono" style={{ fontSize: 32, fontWeight: 700, letterSpacing: '-0.025em', marginTop: 4 }}>{liveMode
                ? (livePriceAvailable ? `$${livePrice.toFixed(2)}` : 'Unavailable')
                : `$${finalTotal.toFixed(2)}`}</div>
              <div style={{ fontSize: 11, color: 'var(--text-faint)', marginTop: 2 }}>{(currency || 'USD')} · {plan} ${window.fmtMoneyCompact(size)}</div>

              <div style={{ marginTop: 22, display: 'flex', flexDirection: 'column', gap: 10, fontSize: 13 }}>
                <ArenaKvLocal label="Plan" value={plan}/>
                <ArenaKvLocal label="Size" value={'$' + window.fmtMoneyCompact(size)}/>
                {liveMode ? (
                  <>
                    {livePriceAvailable && <ArenaKvLocal label="Package price" value={'$' + livePrice.toFixed(2)} mono/>}
                    <ArenaKvLocal label="Wallet balance" value={'$' + window.fmtMoney(balance)} mono/>
                    {packageId !== null && <ArenaKvLocal label="Package id" value={String(packageId)} mono/>}
                  </>
                ) : (
                  <>
                    <ArenaKvLocal label="Subtotal" value={'$' + total.toFixed(2)} mono/>
                    {fee > 0 && <ArenaKvLocal label="Card fee (2.5%)" value={'$' + fee.toFixed(2)} mono/>}
                  </>
                )}
              </div>

              <div style={{ marginTop: 22, fontSize: 11, color: 'var(--text-faint)', display: 'flex', alignItems: 'center', gap: 6 }}>
                <I.shield size={12}/> {liveMode
                  ? 'Live Prop backend · /proptrade/buy-offer charges your wallet on confirm'
                  : 'Staging PSP · order recorded locally for QA'}
              </div>
            </div>

            <div style={{ padding: 24, background: 'var(--surface-2)', overflowY: 'auto' }}>
              {step === 'form' && (
                <>
                  <div style={{ fontSize: 11, color: 'var(--text-dim)', textTransform: 'uppercase', letterSpacing: '.08em', fontWeight: 600, marginBottom: 8 }}>Pay with</div>
                  <div style={{ display: 'grid', gridTemplateColumns: 'repeat(4, 1fr)', gap: 6, marginBottom: 18 }}>
                    {[
                      { id: 'card',   l: 'Card',   i: 'cards' },
                      { id: 'crypto', l: 'Crypto', i: 'btc' },
                      { id: 'wire',   l: 'Wire',   i: 'bank' },
                      { id: 'wallet', l: 'Wallet', i: 'wallet' },
                    ].map(m => {
                      const Ic = I[m.i];
                      const disabled = liveDirectDisabled && m.id !== 'wallet';
                      return (
                        <button key={m.id} disabled={disabled} onClick={() => !disabled && setMethod(m.id)} style={{
                          padding: '12px 8px', borderRadius: 10,
                          border: '1.5px solid ' + (method === m.id ? 'var(--magenta)' : 'var(--line)'),
                          background: method === m.id ? 'rgba(255,92,245,0.10)' : 'var(--surface)',
                          color: 'var(--text)', font: 'inherit',
                          cursor: disabled ? 'not-allowed' : 'pointer',
                          opacity: disabled ? 0.45 : 1,
                          display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 6,
                          fontSize: 11, fontWeight: 600,
                        }}>
                          <Ic size={16}/> {m.l}
                        </button>
                      );
                    })}
                  </div>

                  {liveDirectDisabled && method !== 'wallet' && (
                    <div style={{ padding: 14, background: 'var(--surface)', border: '1px solid var(--line)', borderRadius: 12, marginBottom: 14 }}>
                      <div style={{ fontWeight: 600, fontSize: 13, marginBottom: 4 }}>Direct payment coming soon</div>
                      <div style={{ fontSize: 12, color: 'var(--text-dim)' }}>
                        Card, crypto, and wire flows are not wired against the Prop backend yet. Use wallet balance to buy live packages.
                      </div>
                    </div>
                  )}

                  {!liveMode && method === 'card' && (
                    <>
                      <ArenaInputFieldLocal label="Card number" v={card.number} onChange={v => setCard({ ...card, number: v })} mono/>
                      <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 10 }}>
                        <ArenaInputFieldLocal label="Expiry" v={card.expiry} onChange={v => setCard({ ...card, expiry: v })} mono/>
                        <ArenaInputFieldLocal label="CVC" v={card.cvc} onChange={v => setCard({ ...card, cvc: v })} mono/>
                      </div>
                      <ArenaInputFieldLocal label="Cardholder" v={card.name} onChange={v => setCard({ ...card, name: v })}/>
                    </>
                  )}
                  {!liveMode && method === 'crypto' && (
                    <div style={{ padding: 14, background: 'var(--surface)', border: '1px solid var(--line)', borderRadius: 12, marginBottom: 14 }}>
                      <div style={{ fontWeight: 600, fontSize: 13, marginBottom: 4 }}>Pay with USDT</div>
                      <div style={{ fontSize: 12, color: 'var(--text-dim)' }}>Staging USDT flow. Order is recorded locally on confirmation.</div>
                    </div>
                  )}
                  {!liveMode && method === 'wire' && (
                    <div style={{ padding: 14, background: 'var(--surface)', border: '1px solid var(--line)', borderRadius: 12, marginBottom: 14 }}>
                      <div style={{ fontWeight: 600, fontSize: 13, marginBottom: 4 }}>Bank wire</div>
                      <div style={{ fontSize: 12, color: 'var(--text-dim)' }}>Staging wire flow. Account marked active for QA once submitted.</div>
                    </div>
                  )}
                  {method === 'wallet' && (
                    <div style={{ padding: 14, background: 'var(--surface)', border: '1px solid var(--line)', borderRadius: 12, marginBottom: 14 }}>
                      <div style={{ fontWeight: 600, fontSize: 13, marginBottom: 4 }}>Use wallet balance</div>
                      {liveMode ? (
                        <div style={{ fontSize: 12, color: 'var(--text-dim)' }}>
                          {walletDisabledReason
                            ? walletDisabledReason
                            : livePriceAvailable
                              ? `Available: $${window.fmtMoney(balance)} ${currency || 'USD'}. Confirms debit $${livePrice.toFixed(2)} from your wallet via /proptrade/buy-offer.`
                              : `Available: $${window.fmtMoney(balance)} ${currency || 'USD'}.`}
                        </div>
                      ) : (
                        <div style={{ fontSize: 12, color: 'var(--text-dim)' }}>Pays from your wallet. Recorded as a wallet payment.</div>
                      )}
                    </div>
                  )}

                  {submitError && (
                    <div style={{ padding: 12, background: 'rgba(255,82,82,0.08)', border: '1px solid rgba(255,82,82,0.35)', borderRadius: 10, marginBottom: 12, color: 'var(--text)', fontSize: 12 }}>
                      {submitError}
                    </div>
                  )}

                  <button className="a-btn primary" disabled={liveCtaDisabled} style={{ width: '100%', marginTop: 16, height: 48, justifyContent: 'center', opacity: liveCtaDisabled ? 0.55 : 1, cursor: liveCtaDisabled ? 'not-allowed' : 'pointer' }} onClick={() => !liveCtaDisabled && submit()}>
                    <I.check size={13}/> {liveMode
                      ? (livePriceAvailable ? `Pay $${livePrice.toFixed(2)} from wallet` : 'Confirm wallet purchase')
                      : `Pay $${finalTotal.toFixed(2)}`}
                  </button>
                </>
              )}
              {step === 'processing' && (
                <div style={{ padding: '60px 0', textAlign: 'center' }}>
                  <div style={{ width: 56, height: 56, border: '3px solid var(--line)', borderTopColor: 'var(--magenta)', borderRadius: '50%', animation: 'spin 0.8s linear infinite', margin: '0 auto' }}/>
                  <div style={{ marginTop: 18, fontSize: 15, fontWeight: 600 }}>{liveMode ? 'Submitting to Prop backend…' : 'Processing order…'}</div>
                  <style>{`@keyframes spin { to { transform: rotate(360deg); } }`}</style>
                </div>
              )}
            </div>
          </div>
        </div>
      </>
    );
  }

  function NewChallengeSuccess({ plan, size, total, orderRef, onAccounts }) {
    return (
      <>
        <div className="a-pagehead">
          <div>
            <h1>Welcome to the <em>arena</em>.</h1>
            <div className="sub">{plan} order recorded · accounts refresh on next sync</div>
          </div>
        </div>

        <div className="a-section" style={{ maxWidth: 640, margin: '0 auto', padding: 0, overflow: 'hidden' }}>
          <div style={{
            padding: 40, textAlign: 'center',
            background: 'linear-gradient(135deg, rgba(255,92,245,0.12), rgba(92,217,255,0.08))',
            borderBottom: '1px solid var(--line)',
          }}>
            <div style={{ width: 84, height: 84, borderRadius: 22, background: 'linear-gradient(135deg, var(--magenta), var(--cyan))', color: '#06070D', display: 'flex', alignItems: 'center', justifyContent: 'center', margin: '0 auto', boxShadow: '0 0 60px -10px var(--magenta)' }}>
              <I.rocket size={42}/>
            </div>
            <div style={{ fontFamily: 'Space Grotesk', fontSize: 30, fontWeight: 700, letterSpacing: '-0.025em', marginTop: 22 }}>{plan} ${window.fmtMoneyCompact(size)}</div>
            <div style={{ marginTop: 6, fontSize: 14, color: 'var(--text-dim)' }}>Order recorded · accounts refresh on next sync</div>
          </div>

          <div style={{ padding: 28 }}>
            <h3 style={{ margin: '0 0 14px', fontFamily: 'Space Grotesk', fontSize: 14, color: 'var(--text-dim)', letterSpacing: '.06em', textTransform: 'uppercase', fontWeight: 600 }}>What's next</h3>
            {[
              { i: 'mail', l: 'Order recorded', sub: 'Challenge provisioning starts after wallet payment confirms' },
              { i: 'candles', l: 'Connect & trade', sub: 'Open ArenaTrader (web) once your account provisions' },
              { i: 'target', l: 'Hit your target', sub: 'Reach the phase target while respecting daily & max DD' },
            ].map((s, i) => {
              const Ic = I[s.i];
              return (
                <div key={i} style={{ display: 'flex', alignItems: 'center', gap: 14, padding: '12px 0', borderTop: i > 0 ? '1px solid var(--line-2)' : 'none' }}>
                  <div style={{ width: 36, height: 36, borderRadius: 10, background: 'rgba(255,255,255,0.04)', color: 'var(--text-dim)', display: 'flex', alignItems: 'center', justifyContent: 'center' }}><Ic size={16}/></div>
                  <div style={{ flex: 1 }}>
                    <div style={{ fontWeight: 600, fontSize: 14 }}>{s.l}</div>
                    <div style={{ fontSize: 12, color: 'var(--text-dim)' }}>{s.sub}</div>
                  </div>
                </div>
              );
            })}

            <div style={{ marginTop: 22, padding: 16, background: 'var(--surface-2)', border: '1px solid var(--line)', borderRadius: 12 }}>
              <ArenaKvLocal label="Order ref" value={orderRef || 'PA-PENDING'} mono copy/>
              <ArenaKvLocal label="Charged" value={'$' + total.toFixed(2)} mono/>
              <ArenaKvLocal label="Status" value="Recorded"/>
            </div>

            <div style={{ display: 'flex', gap: 8, marginTop: 22 }}>
              <button className="a-btn ghost" style={{ flex: 1, justifyContent: 'center' }} onClick={onAccounts}>View accounts</button>
              <button className="a-btn primary" style={{ flex: 1, justifyContent: 'center' }} onClick={() => window.openArenaTrader && window.openArenaTrader()}>
                <I.candles size={13}/> Open ArenaTrader
              </button>
            </div>
          </div>
        </div>
      </>
    );
  }

  // ─────────────────────────────────────────────────────────────
  // DESKTOP DEPOSIT CARD (live cardholder)
  // ─────────────────────────────────────────────────────────────
  function ArenaDepositCardLive() {
    const { setPage, user } = useApp();
    const live = useLiveUser();
    const [step, setStep] = useState('form');
    const [card, setCard] = useState({ number: '', expiry: '', cvc: '', name: live?.name && live.name !== 'Trader' ? live.name : '' });
    const [save, setSave] = useState(true);
    const amount = 500;
    const fee = +(amount * 0.025).toFixed(2);
    const total = +(amount + fee).toFixed(2);
    useEffect(() => {
      if (!card.name && live?.name && live.name !== 'Trader') setCard(c => ({ ...c, name: live.name }));
    }, [live?.name]);
    function pay() { setStep('processing'); setTimeout(() => setStep('success'), 1500); }
    if (step === 'success') return <ArenaTxSuccessLocal kind="deposit-card" amount={amount} setPage={setPage}/>;
    return (
      <>
        <div className="a-pagehead">
          <div>
            <div style={{ fontSize: 12, color: 'var(--text-dim)', display: 'flex', alignItems: 'center', gap: 6 }}>
              <a onClick={() => setPage('deposit')} style={{ cursor: 'pointer', color: 'var(--text-dim)' }}>Deposit</a>
              <I.chevronRight size={10}/>
              <span style={{ color: 'var(--text)', fontWeight: 600 }}>Card</span>
            </div>
            <h1 style={{ marginTop: 6 }}>Card <em>deposit</em>.</h1>
            <div className="sub">Visa / Mastercard · 2.5% processing fee · 3-D Secure</div>
          </div>
          <button className="a-btn ghost" onClick={() => setPage('deposit')}><I.chevronLeft size={13}/> Back</button>
        </div>
        <div style={{ display: 'grid', gridTemplateColumns: '1fr 380px', gap: 18, maxWidth: 1080 }}>
          <div className="a-section">
            {step === 'form' && (
              <>
                <ArenaInputFieldLocal label="Card number" v={card.number} onChange={v => setCard({ ...card, number: v })} mono/>
                <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 12 }}>
                  <ArenaInputFieldLocal label="Expiry (MM/YY)" v={card.expiry} onChange={v => setCard({ ...card, expiry: v })} mono/>
                  <ArenaInputFieldLocal label="CVC" v={card.cvc} onChange={v => setCard({ ...card, cvc: v })} mono/>
                </div>
                <ArenaInputFieldLocal label="Cardholder name" v={card.name} onChange={v => setCard({ ...card, name: v })}/>
                <label style={{ display: 'flex', alignItems: 'center', gap: 8, fontSize: 12, color: 'var(--text-dim)', marginTop: 8 }}>
                  <input type="checkbox" checked={save} onChange={e => setSave(e.target.checked)}/>
                  Save this card for next time
                </label>
                <div style={{ marginTop: 14, padding: 12, background: 'rgba(0,0,0,0.2)', borderRadius: 10, fontSize: 12, color: 'var(--text-dim)', display: 'flex', alignItems: 'center', gap: 8 }}>
                  <I.shield size={13}/> Staging PSP · no production charge
                </div>
                <button className="a-btn primary" style={{ marginTop: 14, width: '100%', justifyContent: 'center', height: 46 }} onClick={pay}>
                  <I.lock size={13}/> Pay ${total.toFixed(2)}
                </button>
              </>
            )}
            {step === 'processing' && (
              <div style={{ padding: '60px 0', textAlign: 'center' }}>
                <div style={{ width: 56, height: 56, border: '3px solid var(--line)', borderTopColor: 'var(--magenta)', borderRadius: '50%', animation: 'spin 0.8s linear infinite', margin: '0 auto' }}/>
                <div style={{ marginTop: 14, fontSize: 14, fontWeight: 600 }}>Charging…</div>
                <style>{`@keyframes spin { to { transform: rotate(360deg); } }`}</style>
              </div>
            )}
          </div>
          <div className="a-section" style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', textAlign: 'center', background: 'linear-gradient(135deg, rgba(255,92,245,0.06), rgba(92,217,255,0.04)), var(--surface)' }}>
            <div style={{ fontSize: 11, color: 'var(--text-dim)', textTransform: 'uppercase', letterSpacing: '.1em', fontWeight: 600 }}>Total charged</div>
            <div className="mono" style={{ fontSize: 40, fontWeight: 700, letterSpacing: '-0.025em', marginTop: 6 }}>${total.toFixed(2)}</div>
            <div style={{ marginTop: 6, fontSize: 12, color: 'var(--text-dim)' }}>inc. ${fee.toFixed(2)} processing fee</div>
          </div>
        </div>
      </>
    );
  }

  // ─────────────────────────────────────────────────────────────
  // DESKTOP WITHDRAW WIRE (live beneficiary from Client_API profile)
  // ─────────────────────────────────────────────────────────────
  function ArenaWithdrawWireLive() {
    const { setPage, user } = useApp();
    const liveUser = useLiveUser();
    const raw = liveUser?.raw || user || {};
    const iban = raw?.bankAccountNumber || raw?.bankIban || raw?.iban || '';
    const swift = raw?.bankSwiftCode || raw?.bankSwift || raw?.swift || raw?.bic || '';
    const bankName = raw?.bankName || '';
    const accountName = raw?.bankAccountName || liveUser?.name || '';
    const beneficiaries = iban
      ? [{ id: 'b1', label: bankName || 'Primary bank', name: accountName || '—', iban, swift, bank: bankName || '—' }]
      : [];
    const [pick, setPick] = useState(beneficiaries[0]?.id || '');
    const [mode, setMode] = useState(beneficiaries.length ? 'saved' : 'new');
    return (
      <>
        <div className="a-pagehead">
          <div>
            <div style={{ fontSize: 12, color: 'var(--text-dim)', display: 'flex', alignItems: 'center', gap: 6 }}>
              <a onClick={() => setPage('withdraw')} style={{ cursor: 'pointer', color: 'var(--text-dim)' }}>Withdraw</a>
              <I.chevronRight size={10}/>
              <span style={{ color: 'var(--text)', fontWeight: 600 }}>Wire</span>
            </div>
            <h1 style={{ marginTop: 6 }}>Wire <em>destination</em>.</h1>
            <div className="sub">Send to your verified bank account · 3–5 business days</div>
          </div>
          <button className="a-btn ghost" onClick={() => setPage('withdraw')}><I.chevronLeft size={13}/> Back</button>
        </div>
        <div className="a-section" style={{ maxWidth: 720 }}>
          <div className="a-chips" style={{ marginBottom: 14 }}>
            <button className={mode === 'saved' ? 'active' : ''} onClick={() => setMode('saved')}>Saved <span className="c">{beneficiaries.length}</span></button>
            <button className={mode === 'new' ? 'active' : ''} onClick={() => setMode('new')}>+ New beneficiary</button>
          </div>
          {mode === 'saved' && beneficiaries.length === 0 && (
            <div style={{ padding: 24, textAlign: 'center', color: 'var(--text-dim)' }}>
              <I.bank size={28} style={{ color: 'var(--text-faint)' }}/>
              <div style={{ marginTop: 10, fontWeight: 600 }}>No saved beneficiaries</div>
              <div style={{ marginTop: 6, fontSize: 12 }}>Add your bank in <a onClick={() => setPage('profileEdit')} style={{ color: 'var(--cyan)', cursor: 'pointer' }}>Profile → Bank</a> to enable wire payouts.</div>
            </div>
          )}
          {mode === 'saved' && beneficiaries.map(b => (
            <button key={b.id} onClick={() => setPick(b.id)} style={{
              padding: '14px 16px', borderRadius: 12, width: '100%',
              border: '1.5px solid ' + (pick === b.id ? 'var(--magenta)' : 'var(--line)'),
              background: pick === b.id ? 'rgba(255,92,245,0.06)' : 'var(--surface-2)',
              color: 'var(--text)', font: 'inherit', cursor: 'pointer', textAlign: 'left',
              display: 'flex', alignItems: 'center', gap: 12, marginBottom: 8,
            }}>
              <div style={{ width: 38, height: 38, borderRadius: 10, background: 'rgba(255,255,255,0.04)', display: 'flex', alignItems: 'center', justifyContent: 'center', color: 'var(--text-dim)' }}><I.bank size={18}/></div>
              <div style={{ flex: 1 }}>
                <div style={{ fontWeight: 600, fontSize: 14 }}>{b.label}</div>
                <div className="mono" style={{ fontSize: 11, color: 'var(--text-dim)' }}>{b.iban.slice(0, 8)}…{b.iban.slice(-4)} {b.swift ? `· SWIFT ${b.swift}` : ''}</div>
                <div style={{ fontSize: 11, color: 'var(--text-faint)', marginTop: 2 }}>{b.name} · {b.bank}</div>
              </div>
              {pick === b.id && <I.check size={16} style={{ color: 'var(--magenta)' }}/>}
            </button>
          ))}
          {mode === 'new' && (
            <div style={{ padding: 24, textAlign: 'center', color: 'var(--text-dim)' }}>
              <div style={{ fontSize: 13 }}>Add a new beneficiary in <a onClick={() => setPage('profileEdit')} style={{ color: 'var(--cyan)', cursor: 'pointer' }}>Profile → Bank</a>. New-beneficiary onboarding will land when KYC and 2FA gates are wired.</div>
            </div>
          )}
          <div style={{ display: 'flex', gap: 8, marginTop: 14 }}>
            <button className="a-btn ghost" style={{ flex: 1, justifyContent: 'center' }} onClick={() => setPage('withdraw')}>Back</button>
            <button className="a-btn primary" style={{ flex: 1, justifyContent: 'center' }} disabled={!pick} onClick={() => setPage('withdrawConfirm')}>
              Continue <I.arrowRight size={13}/>
            </button>
          </div>
        </div>
      </>
    );
  }

    // Assign overrides — useApp/useLiveWallet/etc. are exposed by other scripts via
  // Object.assign(window, {...}). React route lookups happen at render time so
  // these wins.
  window.ArenaProfile = ArenaProfileLive;
  window.ArenaDepositCard = ArenaDepositCardLive;
  window.ArenaWithdrawWire = ArenaWithdrawWireLive;
  window.ArenaProfileEdit = ArenaProfileEditLive;
  window.ArenaSecurity = ArenaSecurityLive;
  window.ArenaForgotPassword = ArenaForgotPasswordLive;
  window.ArenaNotifications = ArenaNotificationsLive;
  window.ArenaAffiliates = ArenaAffiliatesLive;
  window.ArenaWithdraw = ArenaWithdrawLive;
  window.ArenaWithdrawConfirm = ArenaWithdrawConfirmLive;
  window.ArenaNewChallenge = ArenaNewChallengeLive;
  window.ArenaMobileProfileEdit = ArenaMobileProfileEditLive;
  window.ArenaMobileSecurity = ArenaMobileSecurityLive;
})();
