// MobileAccount.jsx — mobile account dashboard with vertical sections + scrollable nav pills
// SECURITY: identity from props (server-validated session). No URL param parsing.

const MOBILE_ACCOUNT_TABS = ['overview', 'orders', 'subscriptions', 'certs', 'settings'];

function readMobileAccountHash() {
  const h = location.hash.replace('#', '');
  return MOBILE_ACCOUNT_TABS.includes(h) ? h : 'overview';
}

const MobileAccount = ({ user, onLogout, onShop, onUserUpdate }) => {
  const [view, setViewRaw] = React.useState(readMobileAccountHash);
  const [orders, setOrders] = React.useState([]);
  const [subs, setSubs] = React.useState([]);
  const [tierData, setTierData] = React.useState(null);
  const [showTierLevels, setShowTierLevels] = React.useState(false);
  const [certsEnabled, setCertsEnabled] = React.useState(false);

  const setView = (id) => {
    setViewRaw(id);
    const hash = id === 'overview' ? '' : '#' + id;
    history.pushState({ accountTab: id }, '', location.pathname + hash);
  };

  React.useEffect(() => {
    const onPop = () => setViewRaw(readMobileAccountHash());
    window.addEventListener('popstate', onPop);
    if (!location.hash && view === 'overview') {
      history.replaceState({ accountTab: 'overview' }, '', location.pathname);
    }
    return () => window.removeEventListener('popstate', onPop);
  }, []);

  const TH = window.OBC_TIER_HELPERS;
  const spend = tierData ? tierData.lifetime_spend : (user.lifetime_spend || 0);
  const tierInfo = TH.getTier(spend);
  const progress = TH.getProgress(spend);
  const isSub = tierData ? tierData.is_subscriber : (user.is_subscriber || false);

  React.useEffect(() => {
    window.OBC_API.getOrders().then(setOrders).catch(() => {});
    window.OBC_API.getSubscriptions().then(setSubs).catch(() => {});
    window.OBC_API.getTierStatus().then((t) => { if (t) setTierData(t); }).catch(() => {});
    if (window.OBC_FLAGS && window.OBC_FLAGS.certs_enabled) {
      window.OBC_API.getCertProviders().then((r) => {
        const active = r && r.providers && r.providers.length > 0;
        setCertsEnabled(active);
        if (!active && view === 'certs') setViewRaw('overview');
      }).catch(() => {});
    } else if (view === 'certs') { setViewRaw('overview'); }
  }, []);

  const navItems = [
    { id: 'overview', label: 'OVERVIEW' },
    { id: 'orders', label: 'ORDERS' },
    { id: 'subscriptions', label: 'SUBS' },
    ...(certsEnabled ? [{ id: 'certs', label: 'CERTS' }] : []),
    { id: 'settings', label: 'SETTINGS' },
  ];

  return (
    <section style={{ padding: '20px 16px 60px', maxWidth: 480, margin: '0 auto' }}>
      {/* Welcome strip */}
      <div style={{ marginBottom: 12 }}>
        <div style={{ fontSize: 13, color: '#00FF41', letterSpacing: '0.22em', marginBottom: 4 }}>$ /account</div>
        <div style={{ display: 'flex', alignItems: 'baseline', gap: 8, flexWrap: 'wrap' }}>
          <span style={{ fontSize: 20, fontWeight: 800, color: '#FFF', letterSpacing: '0.04em' }}>{user.handle}</span>
          <span style={{ padding: '3px 8px', border: '1px solid ' + tierInfo.accent, color: tierInfo.accent, fontSize: 12, fontWeight: 700, letterSpacing: '0.18em' }}>{tierInfo.glyph} {tierInfo.name}</span>
        </div>
      </div>

      {/* Tier mini card — clickable */}
      <div onClick={() => setShowTierLevels(true)} style={{
        padding: 12, marginBottom: 16, border: '1px solid ' + tierInfo.accent + '44',
        background: tierInfo.accent + '08', cursor: 'pointer',
      }}>
        <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 6 }}>
          <span style={{ fontSize: 16, fontWeight: 800, color: tierInfo.accent, letterSpacing: '0.06em' }}>{tierInfo.glyph} {tierInfo.name}</span>
          <span style={{ fontSize: 11, color: '#9A9A9A', letterSpacing: '0.12em' }}>[ VIEW ALL ]</span>
        </div>
        <div style={{ height: 5, background: 'rgba(255,255,255,0.14)', borderRadius: 1, marginBottom: 6 }}>
          <div style={{ width: progress.percent + '%', height: '100%', background: tierInfo.accent, borderRadius: 1 }}></div>
        </div>
        <div style={{ fontSize: 12, color: '#9A9A9A', letterSpacing: '0.08em' }}>
          {Math.round(spend)} pts{progress.next ? ' · ' + progress.remaining + ' pts to ' + progress.next.name : ' · MAX RANK'}
          {isSub ? ' · ' : ''}{isSub && <span style={{ color: '#B266FF' }}>+SUB</span>}
        </div>
      </div>

      {/* Nav pills — 2x2 grid + full-width exit */}
      <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 6, marginBottom: 20 }}>
        {navItems.map((n) => (
          <button key={n.id} onClick={() => setView(n.id)} style={{
            padding: '10px 0',
            background: view === n.id ? '#00FF41' : 'transparent',
            color: view === n.id ? '#000' : '#E0E0E0',
            border: '1px solid ' + (view === n.id ? '#00FF41' : 'rgba(255,255,255,0.22)'),
            fontFamily: 'inherit', fontSize: 13, fontWeight: 700, letterSpacing: '0.12em',
            cursor: 'pointer', borderRadius: 2, minHeight: 44, textAlign: 'center',
          }}>{view === n.id ? '> ' : ''}{n.label}</button>
        ))}
        <button onClick={onLogout} style={{
          padding: '10px 0', gridColumn: 'span 2',
          background: 'transparent', border: '1px solid #FF3344', color: '#FF3344',
          fontFamily: 'inherit', fontSize: 13, fontWeight: 700, letterSpacing: '0.12em',
          cursor: 'pointer', borderRadius: 2, minHeight: 44, textAlign: 'center',
        }}>EXIT</button>
      </div>

      {/* Content */}
      {view === 'overview' && <MobileOverview user={user} orders={orders} subs={subs} tierData={tierData} certsEnabled={certsEnabled} onView={setView} onShop={onShop} onShowTiers={() => setShowTierLevels(true)} />}
      {view === 'orders' && <MobileOrders orders={orders} />}
      {view === 'subscriptions' && <MobileSubscriptions subs={subs} setSubs={setSubs} onShop={onShop} />}
      {view === 'certs' && window.Certs && <window.Certs />}
      {view === 'settings' && <MobileSettings user={user} onUserUpdate={onUserUpdate} />}

      {showTierLevels && ReactDOM.createPortal(
        <MobileTierLevels currentSpend={spend} isSub={isSub} onClose={() => setShowTierLevels(false)} />,
        document.getElementById('overlays')
      )}
    </section>
  );
};

// ===================== OVERVIEW =====================
const MobileOverview = ({ user, orders, subs, tierData, certsEnabled, onView, onShop, onShowTiers }) => {
  const TH = window.OBC_TIER_HELPERS;
  const spend = tierData ? tierData.lifetime_spend : (user.lifetime_spend || 0);
  const isSub = tierData ? tierData.is_subscriber : (user.is_subscriber || false);
  const certBoost = tierData ? (tierData.cert_boost || 0) : 0;
  const disc = TH.getEffectiveDiscount(spend);
  const activeSubs = subs.filter((s) => s.status === 'ACTIVE');
  const open = orders.filter((o) => o.status !== 'DELIVERED').length;
  const lastOrder = orders[0];

  return (
    <div>
      {/* stat grid */}
      <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 8, marginBottom: 16 }}>
        <MStat label="OPEN ORDERS" value={open} color="#00FF41" />
        <MStat label="TOTAL POINTS" value={Math.round(spend) + ' pts'} color="#00E5FF" />
        <MStat label="ACTIVE SUBS" value={activeSubs.length} color={activeSubs.length > 0 ? '#B266FF' : '#FF8C42'} />
        <MStat label="DISCOUNT" value={disc > 0 ? disc + '%' : '—'} color={disc > 0 ? '#FFD23F' : '#BFBFBF'} />
        {certsEnabled && <MStat label="CERT BOOST" value={certBoost > 0 ? '+' + certBoost + '%' : '—'} color={certBoost > 0 ? '#00E5FF' : '#BFBFBF'} />}
      </div>

      {/* Last order card */}
      <MobileCard title="// LAST ORDER" cta="./all-orders" onClick={() => onView('orders')}>
        {lastOrder ? (
          <>
            <div style={{ display: 'flex', alignItems: 'baseline', justifyContent: 'space-between' }}>
              <span style={{ fontSize: 16, fontWeight: 800, color: '#00FF41', letterSpacing: '0.04em' }}>{lastOrder.id}</span>
              <MobileStatusPill status={lastOrder.status} />
            </div>
            <div style={{ marginTop: 8, fontSize: 14, color: '#BFBFBF', letterSpacing: '0.06em' }}>{lastOrder.placed} · ${lastOrder.total}</div>
            <div style={{ marginTop: 8, fontSize: 14, color: '#FFFFFF', lineHeight: 1.6 }}>
              {lastOrder.items.map((i, k) => (<div key={k}>&gt; {i.name} x {i.qty}</div>))}
            </div>
          </>
        ) : <div style={{ color: '#BFBFBF', fontSize: 12 }}>// no orders yet.</div>}
      </MobileCard>

      {/* Subscriptions card */}
      <MobileCard title="// SUBSCRIPTIONS" cta="./manage" onClick={() => onView('subscriptions')}>
        {activeSubs.length > 0 ? (
          <div>
            {activeSubs.map((s, i) => (
              <div key={s.id || i} style={{ display: 'flex', justifyContent: 'space-between', padding: '6px 0', borderBottom: i < activeSubs.length - 1 ? '1px dashed rgba(255,255,255,0.18)' : 'none', fontSize: 12 }}>
                <span style={{ color: '#B266FF', fontWeight: 700 }}>{(s.product_name || s.product_handle || '').toUpperCase()}</span>
                <span style={{ color: '#BFBFBF', fontSize: 11 }}>{s.cadence} · x{s.quantity}</span>
              </div>
            ))}
            <div style={{ marginTop: 8, fontSize: 12, color: '#9A9A9A' }}>// +5% off subscription shipments</div>
          </div>
        ) : (
          <div style={{ fontSize: 14, color: '#9A9A9A', lineHeight: 1.7 }}>
            // no active subscriptions.<br/>
            <span style={{ color: '#B266FF', cursor: 'pointer' }} onClick={(e) => { e.stopPropagation(); onShop(); }}>./subscribe →</span> to any coffee for 5% off
          </div>
        )}
      </MobileCard>
    </div>
  );
};

// ===================== SUBSCRIPTIONS (multi-sub) =====================
const MobileSubscriptions = ({ subs, setSubs, onShop }) => {
  const [confirming, setConfirming] = React.useState(null);
  const cadenceLabels = {};
  (window.OBC_SUB_CADENCE_OPTIONS || []).forEach(function(c) { cadenceLabels[c.id] = c.label; });

  const doAction = async (subId, action) => {
    try {
      var res;
      if (action === 'pause') res = await window.OBC_API.pauseSubscription(subId);
      else if (action === 'resume') res = await window.OBC_API.resumeSubscription(subId);
      else if (action === 'cancel') res = await window.OBC_API.cancelSubscription(subId);
      if (res && res.ok !== false) {
        var updated = await window.OBC_API.getSubscriptions();
        setSubs(updated);
      }
    } catch (e) {}
    setConfirming(null);
  };

  const activeSubs = subs.filter((s) => s.status !== 'CANCELLED');

  const SubActionBtn = ({ children, color = '#00FF41', onClick }) => (
    <button onClick={onClick} style={{
      background: 'transparent', border: '1px solid ' + color, color,
      padding: '10px 14px', fontFamily: 'inherit', fontSize: 13, letterSpacing: '0.12em', fontWeight: 700,
      cursor: 'pointer', borderRadius: 2, minHeight: 44,
    }}>{children}</button>
  );

  return (
    <div>
      <div style={{ fontSize: 13, color: '#BFBFBF', letterSpacing: '0.18em', marginBottom: 14 }}>// subscribe to any coffee · 5% off</div>

      {activeSubs.length === 0 && (
        <div style={{ padding: 18, background: '#0A0A0A', border: '1px dashed rgba(178,102,255,0.4)', textAlign: 'center', marginBottom: 14 }}>
          <div style={{ fontSize: 14, color: '#BFBFBF', lineHeight: 1.7, marginBottom: 10 }}>
            // no active subscriptions.<br/>choose your coffee. choose your cadence.
          </div>
          <SubActionBtn color="#B266FF" onClick={onShop}>./browse-coffees</SubActionBtn>
        </div>
      )}

      {activeSubs.map((s) => {
        var isPaused = s.status === 'PAUSED';
        var name = (s.product_name || s.product_handle || '').toUpperCase().replace(/-/g, ' ');
        return (
          <div key={s.id} style={{ padding: 14, background: '#0A0A0A', border: '1px solid rgba(255,255,255,0.22)', marginBottom: 10 }}>
            <div style={{ display: 'flex', alignItems: 'baseline', justifyContent: 'space-between', marginBottom: 12 }}>
              <div style={{ fontSize: 18, fontWeight: 800, color: '#B266FF', letterSpacing: '0.04em' }}>{name}</div>
              <MobileStatusPill status={isPaused ? 'PAUSED' : 'ACTIVE'} />
            </div>

            <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 1, background: 'rgba(255,255,255,0.12)', marginBottom: 14 }}>
              {[
                ['NEXT SHIP', isPaused ? '— PAUSED —' : (s.next_ship_date || '—')],
                ['CADENCE', cadenceLabels[s.cadence] || s.cadence],
                ['QTY / GRIND', 'x' + s.quantity + ' · ' + s.grind],
                ['PRICE', '$' + (s.price || '—') + '/ea'],
              ].map(function(pair) { return (
                <div key={pair[0]} style={{ background: '#000', padding: '10px 12px' }}>
                  <div style={{ fontSize: 11, letterSpacing: '0.18em', color: '#A0A0A0', fontWeight: 700 }}>{pair[0]}</div>
                  <div style={{ marginTop: 4, fontSize: 14, color: '#FFF', fontWeight: 600 }}>{pair[1]}</div>
                </div>
              ); })}
            </div>

            <div style={{ display: 'flex', gap: 6, flexWrap: 'wrap' }}>
              <SubActionBtn color="#FFD23F" onClick={() => setConfirming({ id: s.id, action: isPaused ? 'resume' : 'pause' })}>./{isPaused ? 'resume' : 'pause'}</SubActionBtn>
              <SubActionBtn color="#FF3344" onClick={() => setConfirming({ id: s.id, action: 'cancel' })}>./cancel</SubActionBtn>
            </div>

            {confirming && confirming.id === s.id && (
              <div style={{ marginTop: 12, padding: 12, border: '1px solid ' + (confirming.action === 'cancel' ? '#FF3344' : '#FFD23F'), background: '#0A0A0A' }}>
                <div style={{ fontSize: 12, letterSpacing: '0.18em', fontWeight: 700, marginBottom: 8, color: confirming.action === 'cancel' ? '#FF3344' : '#FFD23F' }}>
                  // CONFIRM ./{confirming.action}
                </div>
                <div style={{ fontSize: 14, color: '#E0E0E0', lineHeight: 1.7, marginBottom: 12 }}>
                  {confirming.action === 'cancel' ? 'cancel ' + name + '? you can re-subscribe anytime.'
                    : confirming.action === 'resume' ? 'resume ' + name + '? next shipment will be scheduled.'
                    : 'pause ' + name + '? next shipment will be skipped.'}
                </div>
                <div style={{ display: 'flex', gap: 8 }}>
                  <SubActionBtn color={confirming.action === 'cancel' ? '#FF3344' : '#FFD23F'} onClick={() => doAction(s.id, confirming.action)}>./confirm</SubActionBtn>
                  <SubActionBtn color="#BFBFBF" onClick={() => setConfirming(null)}>./abort</SubActionBtn>
                </div>
              </div>
            )}

            {s.history && s.history.length > 0 && (
              <div style={{ marginTop: 14, paddingTop: 10, borderTop: '1px dashed rgba(255,255,255,0.18)' }}>
                <div style={{ fontSize: 11, color: '#9A9A9A', letterSpacing: '0.18em', marginBottom: 6 }}>// SHIPMENT LOG</div>
                {s.history.slice(0, 4).map((h, i) => (
                  <div key={i} style={{ display: 'flex', justifyContent: 'space-between', padding: '5px 0', fontSize: 13, color: '#BFBFBF' }}>
                    <span><span style={{ color: '#B266FF' }}>{'>'}</span> {h.date}{h.origin ? ' — ' + h.origin : ''}</span>
                    <span>${h.price}</span>
                  </div>
                ))}
              </div>
            )}
          </div>
        );
      })}

      <div style={{ padding: 12, border: '1px dashed rgba(178,102,255,0.28)', fontSize: 13, color: '#BFBFBF', lineHeight: 1.7 }}>
        <div style={{ color: '#B266FF', letterSpacing: '0.12em', fontWeight: 700, marginBottom: 6 }}>// SUBSCRIBER BENEFITS</div>
        {'>'} 5% off subscribed items (stacks with tier)<br/>
        {'>'} +12h early access<br/>
        {'>'} every shipment counts toward tier<br/>
        {'>'} subscribe to any coffee · choose your cadence
      </div>
    </div>
  );
};

const MStat = ({ label, value, color }) => (
  <div style={{ padding: '14px 12px', background: '#0A0A0A', border: '1px solid rgba(255,255,255,0.22)' }}>
    <div style={{ fontSize: 11, color: '#BFBFBF', letterSpacing: '0.22em', fontWeight: 700 }}>{label}</div>
    <div style={{ marginTop: 6, fontSize: 20, fontWeight: 800, color, letterSpacing: '0.04em' }}>{value}</div>
  </div>
);

const MobileCard = ({ title, children, cta, onClick }) => (
  <div onClick={onClick} style={{
    padding: 14, background: '#0A0A0A', border: '1px solid rgba(255,255,255,0.22)',
    cursor: onClick ? 'pointer' : 'default', marginBottom: 10,
  }}>
    <div style={{ display: 'flex', alignItems: 'baseline', justifyContent: 'space-between', marginBottom: 10 }}>
      <span style={{ fontSize: 12, color: '#BFBFBF', letterSpacing: '0.22em', fontWeight: 700 }}>{title}</span>
      {cta && <span style={{ fontSize: 12, color: '#00FF41', letterSpacing: '0.15em' }}>{cta}</span>}
    </div>
    {children}
  </div>
);

const MobileStatusPill = ({ status }) => {
  const colors = { SHIPPED: '#FFD23F', DELIVERED: '#00FF41', PROCESSING: '#00E5FF', CANCELED: '#FF3344', CANCELLED: '#FF3344', ACTIVE: '#00FF41', PAUSED: '#FF8C42' };
  const c = colors[status] || '#BFBFBF';
  return <span style={{ padding: '2px 8px', border: '1px solid ' + c, color: c, fontSize: 11, fontWeight: 700, letterSpacing: '0.15em' }}>[{status}]</span>;
};

// ===================== ORDERS =====================
const MobileOrders = ({ orders }) => {
  const [open, setOpen] = React.useState(null);

  return (
    <div>
      <div style={{ fontSize: 13, color: '#BFBFBF', letterSpacing: '0.18em', marginBottom: 14 }}>// {orders.length} orders</div>

      {orders.map((o) => (
        <div key={o.id} style={{ marginBottom: 8 }}>
          <div onClick={() => setOpen(open === o.id ? null : o.id)} style={{
            padding: '14px', background: open === o.id ? 'rgba(0,255,65,0.04)' : '#0A0A0A',
            border: '1px solid rgba(255,255,255,0.22)', cursor: 'pointer',
          }}>
            <div style={{ display: 'flex', alignItems: 'baseline', justifyContent: 'space-between', marginBottom: 6 }}>
              <span style={{ color: '#00FF41', fontWeight: 700, fontSize: 15, letterSpacing: '0.04em' }}>{o.id}</span>
              <span style={{ color: '#BFBFBF', fontSize: 11 }}>{open === o.id ? '[-]' : '[+]'}</span>
            </div>
            <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', fontSize: 12 }}>
              <span style={{ color: '#E0E0E0' }}>{o.placed}</span>
              <MobileStatusPill status={o.status} />
              <span style={{ color: '#FFF', fontWeight: 700 }}>${o.total}</span>
            </div>
          </div>

          {open === o.id && (
            <div style={{ padding: '14px', background: '#0A0A0A', borderTop: 'none', border: '1px solid rgba(255,255,255,0.22)', borderTopWidth: 0 }}>
              <div style={{ fontSize: 12, letterSpacing: '0.22em', color: '#BFBFBF', marginBottom: 8 }}>// ITEMS</div>
              {o.items.map((i, k) => (
                <div key={k} style={{ display: 'flex', justifyContent: 'space-between', padding: '6px 0', borderBottom: '1px dashed rgba(255,255,255,0.18)', fontSize: 12 }}>
                  <span><span style={{ color: '#00FF41' }}>{'>'}</span> {i.name} x {i.qty}</span>
                  <span style={{ color: '#FFF' }}>${i.price * i.qty}</span>
                </div>
              ))}
              {o.track && (
                <div style={{ marginTop: 10, fontSize: 13, color: '#E0E0E0' }}>
                  tracking: <span style={{ color: '#00FF41' }}>{o.track}</span>
                </div>
              )}
              <div style={{ marginTop: 10, display: 'flex', gap: 6, flexWrap: 'wrap' }}>
                <MSmallBtn>./track</MSmallBtn>
                <MSmallBtn>./reorder</MSmallBtn>
                <MSmallBtn>./help</MSmallBtn>
              </div>
            </div>
          )}
        </div>
      ))}
    </div>
  );
};

const MSmallBtn = ({ children }) => (
  <button style={{
    background: 'transparent', border: '1px solid rgba(255,255,255,0.28)', color: '#E0E0E0',
    padding: '8px 12px', fontFamily: 'inherit', fontSize: 13, letterSpacing: '0.12em',
    cursor: 'pointer', borderRadius: 2, minHeight: 36,
  }}>{'>'} {children}</button>
);

// ===================== SETTINGS =====================
const MobileSettings = ({ user, onUserUpdate }) => {
  const [form, setForm] = React.useState({
    name: user.name,
    email: user.email,
    handle: user.handle,
    marketing: user.marketing || false,
    notify_orders: user.notify_orders !== false,
    notify_drops: user.notify_drops !== false,
    notify_subs: user.notify_subs !== false,
    line1: '', line2: '', city: '', state: '', zip: '',
    ...user.shipping,
  });
  const [saved, setSaved] = React.useState(false);
  const [saving, setSaving] = React.useState(false);
  const [err, setErr] = React.useState(null);
  const set = (k, v) => { setForm((f) => ({ ...f, [k]: v })); setSaved(false); };

  const submit = async (e) => {
    e.preventDefault();
    setErr(null); setSaving(true);
    try {
      await Promise.all([
        window.OBC_API.updateProfile({ name: form.name, handle: form.handle, marketing: form.marketing, notify_orders: form.notify_orders, notify_drops: form.notify_drops, notify_subs: form.notify_subs }),
        window.OBC_API.updateAddress({ line1: form.line1, line2: form.line2, city: form.city, state: form.state, zip: form.zip }),
      ]);
      if (onUserUpdate) {
        const fresh = await window.OBC_API.getCurrentUser();
        onUserUpdate(fresh || { ...user, name: form.name, handle: form.handle, marketing: form.marketing });
      }
      setSaved(true);
      setTimeout(() => setSaved(false), 2400);
    } catch (e) { setErr('// failed to save: ' + (e.message || 'unknown error')); }
    setSaving(false);
  };

  return (
    <form onSubmit={submit}>
      <MSettingsGroup title="// IDENTITY">
        <MSField label="HANDLE" value={form.handle} onChange={(v) => set('handle', v)} />
        <MSField label="DISPLAY NAME" value={form.name} onChange={(v) => set('name', v)} />
        <MSField label="EMAIL" value={form.email} type="email" />
      </MSettingsGroup>

      <MSettingsGroup title="// SHIPPING ADDRESS">
        <MSField label="STREET" value={form.line1} onChange={(v) => set('line1', v)} />
        <MSField label="UNIT / APT" value={form.line2} onChange={(v) => set('line2', v)} />
        <MSField label="CITY" value={form.city} onChange={(v) => set('city', v)} />
        <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 8 }}>
          <MSField label="STATE" value={form.state} onChange={(v) => set('state', v)} />
          <MSField label="ZIP" value={form.zip} onChange={(v) => set('zip', v)} />
        </div>
      </MSettingsGroup>

      <MobileMfaSettings mfaEnabled={user.mfa_enabled || false} />

      <MSettingsGroup title="// NOTIFICATIONS">
        <MobileToggle label="ORDER UPDATES" checked={form.notify_orders} onChange={(v) => set('notify_orders', v)} />
        <MobileToggle label="NEW DROP ALERTS" checked={form.notify_drops} onChange={(v) => set('notify_drops', v)} />
        <MobileToggle label="SUBSCRIPTION REMINDERS" checked={form.notify_subs} onChange={(v) => set('notify_subs', v)} />
        <MobileToggle label="MARKETING" checked={form.marketing} onChange={(v) => set('marketing', v)} />
      </MSettingsGroup>

      <button type="submit" disabled={saving} style={{
        width: '100%', marginTop: 20, background: '#00FF41', color: '#000',
        border: '1px solid #00FF41', padding: '16px', fontFamily: 'inherit',
        fontWeight: 800, fontSize: 16, letterSpacing: '0.22em',
        cursor: saving ? 'default' : 'pointer',
        borderRadius: 2, minHeight: 52, opacity: saving ? 0.5 : 1,
      }}>{saving ? '// saving...' : '> ./save-changes'}</button>
      {saved && (
        <div style={{ marginTop: 10, textAlign: 'center', color: '#00FF41', fontSize: 14, letterSpacing: '0.18em' }}>
          [ OK ] saved.
        </div>
      )}
      {err && (
        <div style={{ marginTop: 10, textAlign: 'center', color: '#FF4444', fontSize: 14, letterSpacing: '0.18em' }}>
          {err}
        </div>
      )}
    </form>
  );
};

// ===================== MOBILE MFA SETTINGS =====================
const MobileMfaSettings = ({ mfaEnabled: initialEnabled }) => {
  const [phase, setPhase] = React.useState('idle');
  const [status, setStatus] = React.useState({ totp_enabled: initialEnabled, passkeys: [], recovery_codes_remaining: 0 });
  const [enrollData, setEnrollData] = React.useState(null);
  const [code, setCode] = React.useState('');
  const [err, setErr] = React.useState(null);
  const [busy, setBusy] = React.useState(false);
  const [showRecovery, setShowRecovery] = React.useState(false);
  const [justEnabled, setJustEnabled] = React.useState(null);
  const [passkeyName, setPasskeyName] = React.useState('');
  const [qrSvg, setQrSvg] = React.useState('');
  const webauthnSupported = typeof window !== 'undefined' && window.OBC_WebAuthn?.isSupported();

  const refreshStatus = async () => {
    try {
      const s = await window.OBC_API.mfaStatus();
      if (s.ok) setStatus(s);
    } catch (e) { /* silent */ }
  };
  React.useEffect(() => { refreshStatus(); }, []);

  const hasAny = status.totp_enabled || status.passkeys.length > 0;

  React.useEffect(() => {
    if (enrollData?.otpauth_uri && phase === 'enrolling-totp' && typeof qrcode !== 'undefined') {
      try {
        const qr = qrcode(0, 'M');
        qr.addData(enrollData.otpauth_uri);
        qr.make();
        setQrSvg(qr.createSvgTag({ cellSize: 3, margin: 3 }).replace(/fill="#000000"/g, 'fill="#00FF41"'));
      } catch (e) { /* qr library not loaded */ }
    }
  }, [enrollData, phase]);

  const startTotpEnroll = async () => {
    setErr(null); setBusy(true);
    try {
      const data = await window.OBC_API.enrollMfa();
      setEnrollData(data);
      setPhase('enrolling-totp');
    } catch (e) { setErr('// failed to start enrollment.'); }
    setBusy(false);
  };

  const confirmTotpEnroll = async () => {
    setErr(null);
    if (!code || code.length !== 6 || !/^\d{6}$/.test(code)) { setErr('// enter the 6-digit code.'); return; }
    setBusy(true);
    try {
      const result = await window.OBC_API.confirmMfaEnroll(code);
      if (result.ok) {
        setJustEnabled('totp');
        setPhase('idle'); setCode('');
        await refreshStatus();
      } else { setErr('// invalid code.'); }
    } catch (e) { setErr('// verification failed.'); }
    setBusy(false);
  };

  const startPasskeyEnroll = async () => {
    setErr(null); setBusy(true);
    try {
      if (!window.OBC_WebAuthn?.isSupported()) { setErr('// your browser does not support passkeys.'); setBusy(false); return; }
      const { options } = await window.OBC_API.enrollPasskey();
      setErr('// waiting for browser prompt...');
      const attestation = await window.OBC_WebAuthn.registerPasskey(options);
      setErr(null);
      setPhase('naming-passkey');
      setEnrollData({ attestation });
    } catch (e) {
      if (e.name === 'NotAllowedError') { setErr('// passkey registration was cancelled.'); }
      else { setErr('// failed to register passkey.'); }
    }
    setBusy(false);
  };

  const confirmPasskeyEnroll = async () => {
    setErr(null); setBusy(true);
    try {
      const result = await window.OBC_API.confirmPasskey(enrollData.attestation, passkeyName || 'Passkey');
      if (result.ok) {
        if (result.recovery_codes) {
          setEnrollData({ ...enrollData, recovery_codes: result.recovery_codes });
          setJustEnabled('passkey-with-codes');
        } else {
          setJustEnabled('passkey');
        }
        setPhase('idle'); setPasskeyName('');
        await refreshStatus();
      } else { setErr('// passkey verification failed.'); }
    } catch (e) { setErr('// failed to save passkey.'); }
    setBusy(false);
  };

  const disableTotp = async () => {
    setErr(null);
    if (!code || code.length !== 6 || !/^\d{6}$/.test(code)) { setErr('// enter your current 6-digit TOTP code.'); return; }
    setBusy(true);
    try {
      const result = await window.OBC_API.disableMfa(code, 'totp');
      if (result.ok !== false) { setPhase('idle'); setCode(''); setJustEnabled(null); await refreshStatus(); }
      else { setErr('// invalid code.'); }
    } catch (e) { setErr('// failed to disable TOTP.'); }
    setBusy(false);
  };

  const removePasskey = async (credId) => {
    setErr(null);
    if (!code || code.length !== 6 || !/^\d{6}$/.test(code)) { setErr('// enter TOTP code to confirm.'); return; }
    setBusy(true);
    try {
      await window.OBC_API.disableMfa(code, 'passkey', credId);
      setCode(''); await refreshStatus();
    } catch (e) { setErr('// failed to remove passkey.'); }
    setBusy(false);
  };

  const regenerateCodes = async () => {
    setErr(null);
    if (!code || code.length !== 6 || !/^\d{6}$/.test(code)) { setErr('// enter TOTP code to regenerate.'); return; }
    setBusy(true);
    try {
      const result = await window.OBC_API.regenerateRecoveryCodes(code);
      if (result.ok) {
        setEnrollData({ recovery_codes: result.recovery_codes });
        setShowRecovery(true); setCode('');
        await refreshStatus();
      } else { setErr('// invalid code.'); }
    } catch (e) { setErr('// failed to regenerate.'); }
    setBusy(false);
  };

  const downloadCodes = (codes) => {
    const text = '# Operator Brewing — Recovery Codes\n# Each code works once. Store safely.\n\n' + codes.join('\n');
    const blob = new Blob([text], { type: 'text/plain' });
    const a = document.createElement('a');
    a.href = URL.createObjectURL(blob);
    a.download = 'obc-recovery-codes.txt';
    a.click();
    URL.revokeObjectURL(a.href);
  };

  const cancelFlow = () => { setPhase('idle'); setCode(''); setErr(null); setEnrollData(null); setPasskeyName(''); };

  const MfaActionBtn = ({ children, color = '#00FF41', onClick }) => (
    <button onClick={onClick} style={{
      background: 'transparent', border: '1px solid ' + color, color,
      padding: '10px 14px', fontFamily: 'inherit', fontSize: 13, letterSpacing: '0.15em', fontWeight: 700,
      cursor: 'pointer', borderRadius: 2, minHeight: 44,
    }}>{children}</button>
  );

  return (
    <MSettingsGroup title="// SECURITY — MFA">
      {/* Success banners */}
      {justEnabled === 'totp' && (
        <div style={{ padding: 12, border: '1px solid #00FF41', background: 'rgba(0,255,65,0.06)', marginBottom: 12, fontSize: 14, color: '#00FF41', letterSpacing: '0.06em' }}>
          // TOTP 2FA enabled.
        </div>
      )}
      {justEnabled === 'passkey' && (
        <div style={{ padding: 12, border: '1px solid #00FF41', background: 'rgba(0,255,65,0.06)', marginBottom: 12, fontSize: 14, color: '#00FF41', letterSpacing: '0.06em' }}>
          // passkey registered.
        </div>
      )}
      {justEnabled === 'passkey-with-codes' && enrollData?.recovery_codes && (
        <div style={{ padding: 12, border: '1px solid #FFD23F', background: 'rgba(255,210,63,0.06)', marginBottom: 12 }}>
          <div style={{ fontSize: 14, color: '#FFD23F', letterSpacing: '0.06em', marginBottom: 8 }}>
            // passkey registered. SAVE RECOVERY CODES:
          </div>
          <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 3, fontSize: 14, color: '#FFD23F', letterSpacing: '0.1em', marginBottom: 8 }}>
            {enrollData.recovery_codes.map((c, i) => <div key={i} style={{ padding: '3px 6px', background: 'rgba(255,210,63,0.06)' }}>{c}</div>)}
          </div>
          <MfaActionBtn color="#FFD23F" onClick={() => downloadCodes(enrollData.recovery_codes)}>./download</MfaActionBtn>
        </div>
      )}

      {/* IDLE — status overview */}
      {phase === 'idle' && (
        <div>
          <div style={{ fontSize: 14, color: '#E0E0E0', letterSpacing: '0.06em', marginBottom: 10 }}>
            TOTP: <span style={{ color: status.totp_enabled ? '#00FF41' : '#FF3344', fontWeight: 700 }}>[{status.totp_enabled ? 'ENABLED' : 'DISABLED'}]</span>
          </div>

          {status.passkeys.length > 0 && (
            <div style={{ marginBottom: 10 }}>
              <div style={{ fontSize: 12, color: '#BFBFBF', letterSpacing: '0.18em', marginBottom: 6 }}>// PASSKEYS</div>
              {status.passkeys.map(pk => (
                <div key={pk.credential_id} style={{ display: 'flex', alignItems: 'center', gap: 8, padding: '8px 10px', background: '#0A0A0A', border: '1px solid rgba(255,255,255,0.18)', marginBottom: 3, fontSize: 12 }}>
                  <span style={{ color: '#00E5FF' }}>&#x1F511;</span>
                  <span style={{ color: '#E0E0E0', flex: 1 }}>{pk.device_name || 'Passkey'}</span>
                  <span style={{ fontSize: 12, color: pk.backed_up ? '#00FF41' : '#BFBFBF' }}>{pk.backed_up ? '[synced]' : '[device]'}</span>
                </div>
              ))}
            </div>
          )}

          {hasAny && (
            <div style={{ fontSize: 13, color: '#BFBFBF', marginBottom: 10 }}>
              recovery codes: <span style={{ color: status.recovery_codes_remaining > 3 ? '#FFD23F' : '#FF3344', fontWeight: 700 }}>{status.recovery_codes_remaining}</span>
            </div>
          )}

          <div style={{ display: 'flex', gap: 6, flexWrap: 'wrap' }}>
            {!status.totp_enabled && (
              <MfaActionBtn color="#00FF41" onClick={startTotpEnroll}>{busy ? '//...' : './add-totp'}</MfaActionBtn>
            )}
            {webauthnSupported && (
              <MfaActionBtn color="#00E5FF" onClick={startPasskeyEnroll}>{busy ? '//...' : './add-passkey'}</MfaActionBtn>
            )}
            {status.totp_enabled && (
              <MfaActionBtn color="#FF3344" onClick={() => { setPhase('disabling'); setCode(''); setErr(null); }}>./disable-totp</MfaActionBtn>
            )}
            {hasAny && (
              <MfaActionBtn color="#FFD23F" onClick={() => { setPhase('regenerating'); setCode(''); setErr(null); }}>./regen-codes</MfaActionBtn>
            )}
            {status.passkeys.length > 0 && (
              <MfaActionBtn color="#FF3344" onClick={() => { setPhase('removing-passkey'); setCode(''); setErr(null); }}>./rm-passkey</MfaActionBtn>
            )}
          </div>

          {!hasAny && (
            <div style={{ fontSize: 13, color: '#BFBFBF', lineHeight: 1.7, marginTop: 10 }}>
              // protect your account with TOTP or a passkey.
            </div>
          )}
        </div>
      )}

      {/* ENROLLING TOTP */}
      {phase === 'enrolling-totp' && enrollData && (
        <div>
          <div style={{ fontSize: 13, color: '#FFD23F', letterSpacing: '0.22em', marginBottom: 12 }}>$ ./mfa --enroll-totp</div>

          {/* QR code */}
          <div style={{ fontSize: 12, color: '#BFBFBF', letterSpacing: '0.18em', marginBottom: 8 }}>// STEP 1: SCAN QR CODE</div>
          {/* qrSvg sourced from qrcode-generator lib, not user input */}
          {qrSvg ? (
            <div dangerouslySetInnerHTML={{ __html: qrSvg }} style={{ background: '#0A0A0A', border: '1px solid rgba(255,255,255,0.22)', padding: 14, textAlign: 'center', minHeight: 160, display: 'flex', alignItems: 'center', justifyContent: 'center', marginBottom: 10 }} />
          ) : (
            <div style={{ background: '#0A0A0A', border: '1px solid rgba(255,255,255,0.22)', padding: 14, textAlign: 'center', minHeight: 160, display: 'flex', alignItems: 'center', justifyContent: 'center', marginBottom: 10 }}>
              <span style={{ color: '#9A9A9A', fontSize: 11 }}>loading qr...</span>
            </div>
          )}
          <div style={{ fontSize: 12, color: '#9A9A9A', marginBottom: 6 }}>// manual entry:</div>
          <div style={{ padding: '8px 10px', background: '#0A0A0A', border: '1px solid rgba(255,255,255,0.22)', fontSize: 14, color: '#00FF41', letterSpacing: '0.08em', wordBreak: 'break-all', userSelect: 'all', marginBottom: 14 }}>
            {enrollData.secret}
          </div>

          {/* Code input */}
          <div style={{ fontSize: 12, color: '#BFBFBF', letterSpacing: '0.18em', marginBottom: 8 }}>// STEP 2: ENTER CODE</div>
          <input value={code} onChange={(e) => { setCode(e.target.value.replace(/\D/g, '').slice(0, 6)); setErr(null); }}
            maxLength={6} pattern="[0-9]*" inputMode="numeric" autoComplete="one-time-code" autoFocus placeholder="000000"
            style={{ width: '100%', background: '#000', border: '1px solid rgba(255,255,255,0.28)', color: '#FFF', fontFamily: 'inherit', fontSize: 22, padding: '14px', borderRadius: 2, letterSpacing: '0.3em', textAlign: 'center', minHeight: 52, marginBottom: 10 }}
            onFocus={(e) => { e.target.style.borderColor = '#00FF41'; e.target.style.boxShadow = '0 0 0 1px #00FF41'; }}
            onBlur={(e) => { e.target.style.borderColor = 'rgba(255,255,255,0.28)'; e.target.style.boxShadow = 'none'; }}
          />
          {err && <div style={{ marginBottom: 10, padding: '10px 12px', border: '1px solid #FF3344', color: '#FF3344', fontSize: 12 }}>{err}</div>}
          <div style={{ display: 'flex', gap: 8 }}>
            <MfaActionBtn color="#00FF41" onClick={confirmTotpEnroll}>{busy ? '//...' : './confirm'}</MfaActionBtn>
            <MfaActionBtn color="#BFBFBF" onClick={cancelFlow}>./cancel</MfaActionBtn>
          </div>

          {/* Recovery codes toggle */}
          <div style={{ marginTop: 14 }}>
            <div onClick={() => setShowRecovery(!showRecovery)} style={{ fontSize: 13, color: '#FFD23F', letterSpacing: '0.12em', cursor: 'pointer' }}>
              {showRecovery ? '[-]' : '[+]'} recovery codes ({enrollData.recovery_codes?.length || 0})
            </div>
            {showRecovery && enrollData.recovery_codes && (
              <div style={{ marginTop: 8, padding: 10, background: '#0A0A0A', border: '1px solid rgba(255,210,63,0.4)' }}>
                <div style={{ fontSize: 12, color: '#FF3344', letterSpacing: '0.12em', marginBottom: 6 }}>// SAVE THESE NOW.</div>
                <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 3, fontSize: 14, color: '#FFD23F', letterSpacing: '0.1em' }}>
                  {enrollData.recovery_codes.map((c, i) => <div key={i} style={{ padding: '3px 6px', background: 'rgba(255,210,63,0.06)' }}>{c}</div>)}
                </div>
                <div style={{ marginTop: 8 }}>
                  <MfaActionBtn color="#FFD23F" onClick={() => downloadCodes(enrollData.recovery_codes)}>./download</MfaActionBtn>
                </div>
              </div>
            )}
          </div>
        </div>
      )}

      {/* NAMING PASSKEY */}
      {phase === 'naming-passkey' && (
        <div>
          <div style={{ fontSize: 13, color: '#00E5FF', letterSpacing: '0.22em', marginBottom: 12 }}>$ ./mfa --register-passkey</div>
          <div style={{ fontSize: 14, color: '#E0E0E0', lineHeight: 1.7, marginBottom: 12 }}>
            // passkey captured. name it:
          </div>
          <input value={passkeyName} onChange={(e) => setPasskeyName(e.target.value.slice(0, 64))}
            autoFocus placeholder="e.g. iPhone, YubiKey"
            style={{ width: '100%', background: '#000', border: '1px solid rgba(255,255,255,0.28)', color: '#FFF', fontFamily: 'inherit', fontSize: 16, padding: '12px', borderRadius: 2, minHeight: 48, marginBottom: 10 }}
            onFocus={(e) => { e.target.style.borderColor = '#00E5FF'; }}
            onBlur={(e) => { e.target.style.borderColor = 'rgba(255,255,255,0.28)'; }}
          />
          {err && <div style={{ marginBottom: 10, padding: '10px 12px', border: '1px solid #FF3344', color: '#FF3344', fontSize: 12 }}>{err}</div>}
          <div style={{ display: 'flex', gap: 8 }}>
            <MfaActionBtn color="#00E5FF" onClick={confirmPasskeyEnroll}>{busy ? '//...' : './save-passkey'}</MfaActionBtn>
            <MfaActionBtn color="#BFBFBF" onClick={cancelFlow}>./cancel</MfaActionBtn>
          </div>
        </div>
      )}

      {/* DISABLING TOTP */}
      {phase === 'disabling' && (
        <div>
          <div style={{ fontSize: 13, color: '#FF3344', letterSpacing: '0.22em', marginBottom: 12 }}>$ ./mfa --disable-totp</div>
          <div style={{ fontSize: 14, color: '#E0E0E0', lineHeight: 1.7, marginBottom: 12 }}>
            // enter your current TOTP code to disable.
          </div>
          <input value={code} onChange={(e) => { setCode(e.target.value.replace(/\D/g, '').slice(0, 6)); setErr(null); }}
            maxLength={6} pattern="[0-9]*" inputMode="numeric" autoComplete="one-time-code" autoFocus placeholder="000000"
            style={{ width: '100%', background: '#000', border: '1px solid rgba(255,255,255,0.28)', color: '#FFF', fontFamily: 'inherit', fontSize: 22, padding: '14px', borderRadius: 2, letterSpacing: '0.3em', textAlign: 'center', minHeight: 52, marginBottom: 10 }}
            onFocus={(e) => { e.target.style.borderColor = '#FF3344'; }}
            onBlur={(e) => { e.target.style.borderColor = 'rgba(255,255,255,0.28)'; }}
          />
          {err && <div style={{ marginBottom: 10, padding: '10px 12px', border: '1px solid #FF3344', color: '#FF3344', fontSize: 12 }}>{err}</div>}
          <div style={{ display: 'flex', gap: 8 }}>
            <MfaActionBtn color="#FF3344" onClick={disableTotp}>{busy ? '//...' : './confirm-disable'}</MfaActionBtn>
            <MfaActionBtn color="#BFBFBF" onClick={cancelFlow}>./cancel</MfaActionBtn>
          </div>
        </div>
      )}

      {/* REMOVING PASSKEY */}
      {phase === 'removing-passkey' && (
        <div>
          <div style={{ fontSize: 13, color: '#FF3344', letterSpacing: '0.22em', marginBottom: 12 }}>$ ./mfa --remove-passkey</div>
          {status.passkeys.map(pk => (
            <div key={pk.credential_id} style={{ display: 'flex', alignItems: 'center', gap: 8, padding: '10px', background: '#0A0A0A', border: '1px solid rgba(255,255,255,0.18)', marginBottom: 4, cursor: 'pointer', minHeight: 44 }}
              onClick={() => { if (code.length === 6) removePasskey(pk.credential_id); }}>
              <span style={{ color: '#FF3344', fontSize: 11 }}>[x]</span>
              <span style={{ fontSize: 14, color: '#E0E0E0', flex: 1 }}>{pk.device_name || 'Passkey'}</span>
            </div>
          ))}
          <input value={code} onChange={(e) => { setCode(e.target.value.replace(/\D/g, '').slice(0, 6)); setErr(null); }}
            maxLength={6} inputMode="numeric" autoFocus placeholder="TOTP code"
            style={{ width: '100%', marginTop: 10, background: '#000', border: '1px solid rgba(255,255,255,0.28)', color: '#FFF', fontFamily: 'inherit', fontSize: 22, padding: '14px', borderRadius: 2, letterSpacing: '0.3em', textAlign: 'center', minHeight: 52, marginBottom: 10 }}
            onFocus={(e) => { e.target.style.borderColor = '#FF3344'; }}
            onBlur={(e) => { e.target.style.borderColor = 'rgba(255,255,255,0.28)'; }}
          />
          {err && <div style={{ marginBottom: 10, padding: '10px 12px', border: '1px solid #FF3344', color: '#FF3344', fontSize: 12 }}>{err}</div>}
          <MfaActionBtn color="#BFBFBF" onClick={cancelFlow}>./cancel</MfaActionBtn>
        </div>
      )}

      {/* REGENERATING CODES */}
      {phase === 'regenerating' && (
        <div>
          <div style={{ fontSize: 13, color: '#FFD23F', letterSpacing: '0.22em', marginBottom: 12 }}>$ ./mfa --regenerate-codes</div>
          <div style={{ fontSize: 14, color: '#E0E0E0', lineHeight: 1.7, marginBottom: 12 }}>
            // invalidates existing codes. enter TOTP to confirm.
          </div>
          <input value={code} onChange={(e) => { setCode(e.target.value.replace(/\D/g, '').slice(0, 6)); setErr(null); }}
            maxLength={6} inputMode="numeric" autoFocus placeholder="000000"
            style={{ width: '100%', background: '#000', border: '1px solid rgba(255,255,255,0.28)', color: '#FFF', fontFamily: 'inherit', fontSize: 22, padding: '14px', borderRadius: 2, letterSpacing: '0.3em', textAlign: 'center', minHeight: 52, marginBottom: 10 }}
            onFocus={(e) => { e.target.style.borderColor = '#FFD23F'; }}
            onBlur={(e) => { e.target.style.borderColor = 'rgba(255,255,255,0.28)'; }}
          />
          {err && <div style={{ marginBottom: 10, padding: '10px 12px', border: '1px solid #FF3344', color: '#FF3344', fontSize: 12 }}>{err}</div>}
          {showRecovery && enrollData?.recovery_codes && (
            <div style={{ marginBottom: 10, padding: 10, background: '#0A0A0A', border: '1px solid rgba(255,210,63,0.4)' }}>
              <div style={{ fontSize: 12, color: '#FF3344', letterSpacing: '0.12em', marginBottom: 6 }}>// NEW CODES:</div>
              <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 3, fontSize: 14, color: '#FFD23F', letterSpacing: '0.1em' }}>
                {enrollData.recovery_codes.map((c, i) => <div key={i} style={{ padding: '3px 6px', background: 'rgba(255,210,63,0.06)' }}>{c}</div>)}
              </div>
              <div style={{ marginTop: 8 }}><MfaActionBtn color="#FFD23F" onClick={() => downloadCodes(enrollData.recovery_codes)}>./download</MfaActionBtn></div>
            </div>
          )}
          <div style={{ display: 'flex', gap: 8 }}>
            <MfaActionBtn color="#FFD23F" onClick={regenerateCodes}>{busy ? '//...' : './regenerate'}</MfaActionBtn>
            <MfaActionBtn color="#BFBFBF" onClick={cancelFlow}>./cancel</MfaActionBtn>
          </div>
        </div>
      )}
    </MSettingsGroup>
  );
};

const MSettingsGroup = ({ title, children }) => (
  <div style={{ marginBottom: 16, padding: 14, background: '#0A0A0A', border: '1px solid rgba(255,255,255,0.22)' }}>
    <div style={{ fontSize: 12, color: '#BFBFBF', letterSpacing: '0.22em', fontWeight: 700, marginBottom: 12 }}>{title}</div>
    <div style={{ display: 'flex', flexDirection: 'column', gap: 10 }}>{children}</div>
  </div>
);

const MSField = ({ label, value, onChange, type = 'text', placeholder }) => (
  <div>
    <div style={{ fontSize: 12, color: '#E0E0E0', letterSpacing: '0.22em', fontWeight: 700, marginBottom: 4 }}>{'>'} {label}</div>
    <input
      type={type} value={value || ''} placeholder={placeholder} maxLength={500}
      onChange={onChange ? (e) => onChange(e.target.value) : undefined}
      readOnly={!onChange}
      style={{
        width: '100%', background: '#000', border: '1px solid rgba(255,255,255,0.28)',
        color: '#FFF', fontFamily: 'inherit', fontSize: 16, padding: '12px', borderRadius: 2,
        minHeight: 48,
      }}
      onFocus={(e) => { e.target.style.borderColor = '#00FF41'; e.target.style.boxShadow = '0 0 0 1px #00FF41'; }}
      onBlur={(e) => { e.target.style.borderColor = 'rgba(255,255,255,0.28)'; e.target.style.boxShadow = 'none'; }}
    />
  </div>
);

const MobileToggle = ({ label, defaultChecked, checked, onChange }) => {
  const [on, setOn] = React.useState(checked !== undefined ? !!checked : !!defaultChecked);
  const toggle = () => { const next = !on; setOn(next); if (onChange) onChange(next); };
  return (
    <label style={{ display: 'flex', alignItems: 'center', gap: 10, fontSize: 14, color: '#E0E0E0', cursor: 'pointer', minHeight: 44 }}>
      <span onClick={toggle} style={{
        width: 40, height: 22, background: on ? '#00FF41' : 'transparent',
        border: '1px solid ' + (on ? '#00FF41' : 'rgba(255,255,255,0.28)'),
        position: 'relative', borderRadius: 2, flexShrink: 0,
      }}>
        <span style={{
          position: 'absolute', top: 2, left: on ? 20 : 2,
          width: 16, height: 16, background: on ? '#000' : '#888',
          transition: 'left 80ms ease-out',
        }}></span>
      </span>
      <span style={{ letterSpacing: '0.1em' }}>{label}</span>
    </label>
  );
};

// ===================== MOBILE TIER LEVELS OVERLAY =====================
const MobileTierLevels = ({ currentSpend, isSub, onClose }) => {
  const TH = window.OBC_TIER_HELPERS;
  const TIERS = window.OBC_TIERS;
  const currentIdx = TH.getTierIndex(currentSpend);

  React.useEffect(() => {
    document.body.style.overflow = 'hidden';
    return () => { document.body.style.overflow = ''; };
  }, []);

  const tierPerks = [
    [],
    ['24h early access', 'free ship over $100'],
    ['48h early access', 'free ship over $85', 'quarterly sample'],
    ['5% discount', '5% merch', '3-day early access', 'free ship over $75', 'quarterly sample', 'birthday bag'],
    ['8% discount', '8% merch', '7-day early access', 'free ship over $60', 'quarterly sample', 'birthday bag', 'vote on roasts'],
    ['10% discount', '10% merch', '14-day early access', 'free ship over $50', 'monthly sample', '2 birthday bags', 'vote on roasts', 'name on site'],
  ];

  return (
    <div style={{
      position: 'fixed', inset: 0, background: '#0A0A0A', zIndex: 200,
      display: 'flex', flexDirection: 'column',
      fontFamily: "'JetBrains Mono', monospace",
      animation: 'mobileDetailSlideUp 200ms ease-out',
    }}>
      {/* Close bar */}
      <div style={{
        padding: '10px 16px', display: 'flex', alignItems: 'center',
        borderBottom: '1px solid rgba(255,255,255,0.08)',
        background: '#000', flexShrink: 0,
      }}>
        <span style={{ fontSize: 12, color: '#A0A0A0', letterSpacing: '0.15em' }}>// CLEARANCE LEVELS</span>
        <button onClick={onClose} style={{
          marginLeft: 'auto', background: 'transparent',
          border: '1px solid rgba(255,255,255,0.2)', color: '#B8B8B8',
          padding: '6px 12px', fontFamily: 'inherit', fontSize: 13,
          letterSpacing: '0.12em', cursor: 'pointer', minHeight: 36,
        }}>[x]</button>
      </div>

      <div style={{ flex: 1, overflow: 'auto', padding: '14px 16px' }}>
        <div style={{ fontSize: 13, color: '#9A9A9A', letterSpacing: '0.06em', marginBottom: 14 }}>
          // ranks earned through loyalty. keep ordering.
        </div>

        {isSub && (
          <div style={{ padding: '8px 12px', border: '1px solid rgba(178,102,255,0.4)', background: 'rgba(178,102,255,0.06)', marginBottom: 14, fontSize: 12, color: '#B266FF', letterSpacing: '0.06em', lineHeight: 1.6 }}>
            + SUBSCRIBER: 5% off sub items · 1.25x pts on sub items · +12h early access
          </div>
        )}

        {TIERS.map(function(t, i) {
          var isCurrent = i === currentIdx;
          var isReached = i <= currentIdx;
          var perks = tierPerks[i] || [];
          return (
            <div key={t.name} style={{
              padding: 12, marginBottom: 6,
              border: '1px solid ' + (isCurrent ? t.accent : 'rgba(255,255,255,0.12)'),
              background: isCurrent ? t.accent + '0A' : 'transparent',
            }}>
              <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 6 }}>
                <div style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
                  <span style={{ fontSize: 20, fontWeight: 800, color: t.accent }}>{t.glyph}</span>
                  <span style={{ fontSize: 16, fontWeight: 800, color: t.accent, letterSpacing: '0.04em' }}>{t.name}</span>
                </div>
                <span style={{ fontSize: 12, color: '#9A9A9A', letterSpacing: '0.08em' }}>
                  {t.threshold === 0 ? 'start' : 'lvl ' + i + '/' + (TIERS.length - 1)}
                </span>
              </div>

              {isCurrent && (
                <div style={{ marginBottom: 8, padding: '2px 8px', display: 'inline-block', border: '1px solid ' + t.accent, fontSize: 11, color: t.accent, letterSpacing: '0.15em', fontWeight: 700 }}>
                  YOU ARE HERE
                </div>
              )}

              {perks.length > 0 ? (
                <div style={{ display: 'flex', flexWrap: 'wrap', gap: 5 }}>
                  {perks.map(function(pk, j) { return (
                    <span key={j} style={{
                      padding: '5px 10px', fontSize: 14, fontWeight: 600, letterSpacing: '0.03em',
                      border: '1px solid ' + (isReached ? t.accent + '66' : 'rgba(255,255,255,0.15)'),
                      color: isReached ? '#FFF' : '#888',
                      background: isReached ? t.accent + '18' : 'transparent',
                    }}>{pk}</span>
                  ); })}
                </div>
              ) : (
                <div style={{ fontSize: 14, color: '#888' }}>// base rank</div>
              )}

              {t.discount > 0 && (
                <div style={{ marginTop: 6, fontSize: 12, color: isReached ? '#E0E0E0' : '#555', letterSpacing: '0.06em' }}>
                  {'tier discount: ' + t.discount + '% on all orders'}{isSub ? ' · +5% on subscriptions' : ''}
                </div>
              )}
            </div>
          );
        })}

        <div style={{ marginTop: 10, paddingTop: 10, borderTop: '1px dashed rgba(255,255,255,0.18)', fontSize: 12, color: '#9A9A9A', letterSpacing: '0.08em' }}>
          // your points: <span style={{ color: '#FFF', fontWeight: 700 }}>{Math.round(currentSpend)} pts</span> · 1 dollar spent = 1 point
        </div>
        <div style={{ marginTop: 6, fontSize: 11, color: '#00FF41', letterSpacing: '0.06em' }}>
          // all ranks are permanent — status never expires.
        </div>
      </div>
    </div>
  );
};

window.MobileAccount = MobileAccount;
