// Account.jsx — member dashboard with internal nav: overview / orders / subscription / settings / logout
// SECURITY: identity is read from props (server-validated session in prod). No URL param parsing.
// All user-supplied fields rendered via React {} (no innerHTML, no reflection).

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

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

const Account = ({ user, onLogout, onShop, onUserUpdate }) => {
  const [view, setViewRaw] = React.useState(readAccountHash);
  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(readAccountHash());
    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',      glyph:'~' },
    { id:'orders',        label:'ORDERS',        glyph:'>' },
    { id:'subscriptions', label:'SUBSCRIPTIONS', glyph:'#' },
    ...(certsEnabled ? [{ id:'certs', label:'CERTS', glyph:'@' }] : []),
    { id:'settings',      label:'SETTINGS',      glyph:'$' },
  ];

  return (
    <section style={{ padding:'40px 24px 80px', maxWidth: 1280, margin:'0 auto' }}>
      <div style={{ display:'flex', alignItems:'baseline', gap: 14, marginBottom: 28, flexWrap:'wrap' }}>
        <h2 style={{ fontSize: 36, letterSpacing:'0.04em', textTransform:'uppercase', fontWeight: 800, color:'#FFF', margin: 0 }}>{'>'} /account</h2>
        <span style={{ fontSize: 15, color:'#BFBFBF', letterSpacing:'0.18em' }}>// authenticated as <span style={{ color:'#00FF41' }}>{user.handle}</span> · rank: <span style={{ color: tierInfo.accent }}>{tierInfo.glyph} {tierInfo.name}</span></span>
        <button onClick={onLogout} style={{ marginLeft:'auto', background:'transparent', border:'1px solid #FF3344', color:'#FF3344', padding:'8px 14px', fontFamily:'inherit', fontSize: 13, letterSpacing:'0.2em', cursor:'pointer', borderRadius: 2, fontWeight: 700 }}>
          [ EXIT ] ./logout
        </button>
      </div>

      <div style={{ display:'grid', gridTemplateColumns:'220px 1fr', gap: 28 }}>
        <aside style={{ position:'sticky', top: 120, alignSelf:'start' }}>
          <div style={{ fontSize: 13, letterSpacing:'0.22em', color:'#E0E0E0', fontWeight: 700, marginBottom: 10 }}>// SECTIONS</div>
          <div style={{ display:'flex', flexDirection:'column', gap: 4 }}>
            {navItems.map((n) => (
              <button key={n.id} onClick={() => setView(n.id)} style={{
                padding:'12px 14px', textAlign:'left', display:'flex', alignItems:'center', gap: 10,
                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: 14, fontWeight: 700, letterSpacing:'0.12em',
                cursor:'pointer', borderRadius: 2,
              }}>
                <span style={{ width: 14 }}>{view === n.id ? '>' : n.glyph}</span>
                <span>{n.label}</span>
              </button>
            ))}
          </div>

          {/* tier mini card — clickable to show all levels */}
          <div onClick={() => setShowTierLevels(true)} style={{ marginTop: 24, padding: 14, border: `1px solid ${tierInfo.accent}44`, background: `${tierInfo.accent}08`, cursor: 'pointer', transition: 'border-color 120ms, box-shadow 120ms' }}
            onMouseEnter={(e) => { e.currentTarget.style.borderColor = tierInfo.accent; e.currentTarget.style.boxShadow = `0 0 14px ${tierInfo.accent}33`; }}
            onMouseLeave={(e) => { e.currentTarget.style.borderColor = tierInfo.accent + '44'; e.currentTarget.style.boxShadow = 'none'; }}>
            <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
              <div style={{ fontSize: 12, color:'#BFBFBF', letterSpacing:'0.22em' }}>CLEARANCE</div>
              <span style={{ fontSize: 11, color: '#9A9A9A', letterSpacing: '0.12em' }}>[ VIEW ALL ]</span>
            </div>
            <div style={{ fontSize: 18, fontWeight: 800, color: tierInfo.accent, marginTop: 6, letterSpacing:'0.06em' }}>{tierInfo.glyph} {tierInfo.name}</div>
            <div style={{ marginTop: 8, height: 6, background:'rgba(255,255,255,0.14)', borderRadius: 1 }}>
              <div style={{ width: `${progress.percent}%`, height:'100%', background: tierInfo.accent, borderRadius: 1 }}></div>
            </div>
            <div style={{ fontSize: 12, color:'#9A9A9A', letterSpacing:'0.1em', marginTop: 6 }}>
              {Math.round(spend)} pts{progress.next ? ` · ${progress.remaining} pts to ${progress.next.name}` : ' · MAX RANK'}
            </div>
            {isSub && <div style={{ fontSize: 12, color:'#B266FF', letterSpacing:'0.12em', marginTop: 4 }}>+ SUBSCRIBER</div>}
          </div>
        </aside>

        <div>
          {view === 'overview'      && <Overview user={user} orders={orders} subs={subs} tierData={tierData} certsEnabled={certsEnabled} onView={setView} onShop={onShop} onShowTiers={() => setShowTierLevels(true)} />}
          {view === 'orders'        && <Orders orders={orders} />}
          {view === 'subscriptions' && <Subscriptions subs={subs} setSubs={setSubs} onShop={onShop} />}
          {view === 'certs'         && window.Certs && <window.Certs />}
          {view === 'settings'      && <Settings user={user} onUserUpdate={onUserUpdate} />}
        </div>
      </div>

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

// ===================== OVERVIEW =====================
const Overview = ({ 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 tierInfo = TH.getTier(spend);
  const progress = TH.getProgress(spend);
  const perks = TH.getPerks(spend, isSub);
  const nextPerks = TH.getNextPerks(spend);
  const disc = TH.getEffectiveDiscount(spend);

  const open = orders.filter((o) => o.status !== 'DELIVERED').length;
  const lastOrder = orders[0];
  const activeSubs = subs.filter((s) => s.status === 'ACTIVE');

  return (
    <div>
      <div style={{ padding:'18px 20px', background:'rgba(0,255,65,0.06)', border:'1px solid rgba(0,255,65,0.4)', color:'#00FF41', fontSize: 16, letterSpacing:'0.04em', lineHeight: 1.7, marginBottom: 28 }}>
        $ cat welcome.txt<br/>
        # welcome back, <span style={{ fontWeight: 800 }}>{user.handle}</span>.<br/>
        # rank: <span style={{ color: tierInfo.accent }}>{tierInfo.name}</span>.<span style={{ background:'#00FF41', color:'#000', marginLeft: 4, padding:'0 4px' }}>_</span>
      </div>

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

      <div style={{ display:'grid', gridTemplateColumns:'1fr 1fr', gap: 16 }}>
        {/* tier progress — clickable to see all levels */}
        <Block title="// CLEARANCE LEVEL" cta={progress.next ? './view-all-levels →' : '// MAX RANK'} onClick={onShowTiers}>
          <div style={{ display:'flex', alignItems:'baseline', justifyContent:'space-between' }}>
            <span style={{ fontSize: 20, fontWeight: 800, color: tierInfo.accent, letterSpacing:'0.04em' }}>{tierInfo.glyph} {tierInfo.name}</span>
            {progress.next && <span style={{ fontSize: 13, color:'#BFBFBF', letterSpacing:'0.12em' }}>{progress.percent}% · {progress.remaining} pts to go</span>}
          </div>
          <div style={{ marginTop: 12, height: 8, background:'rgba(255,255,255,0.14)', borderRadius: 1 }}>
            <div style={{ width: `${progress.percent}%`, height:'100%', background: tierInfo.accent, borderRadius: 1, transition:'width 400ms ease' }}></div>
          </div>
          {progress.next ? (
            <div style={{ marginTop: 10 }}>
              <div style={{ fontSize: 13, color:'#BFBFBF', letterSpacing:'0.06em' }}>// {progress.remaining} pts to <span style={{ color: progress.next.accent }}>{progress.next.glyph} {progress.next.name}</span></div>
              {nextPerks.length > 0 && (
                <div style={{ marginTop: 8, fontSize: 13, color:'#9A9A9A', lineHeight: 1.6 }}>
                  {nextPerks.map((pk, i) => <div key={i}>+ {pk}</div>)}
                </div>
              )}
            </div>
          ) : (
            <div style={{ marginTop: 10, fontSize: 13, color: tierInfo.accent, letterSpacing:'0.06em' }}>// you have reached the highest clearance level.</div>
          )}
        </Block>

        {/* active perks */}
        <Block title="// ACTIVE PERKS">
          {perks.length > 0 ? (
            <div style={{ fontSize: 14, color:'#E0E0E0', lineHeight: 1.8 }}>
              {perks.map((pk, i) => <div key={i} style={{ display:'flex', gap: 8 }}><span style={{ color:'#00FF41' }}>{'[✓]'}</span> {pk}</div>)}
            </div>
          ) : (
            <div style={{ fontSize: 14, color:'#9A9A9A', lineHeight: 1.7 }}>
              // no perks yet. start ordering to rank up.<br/>
              // next rank unlocks 24h early access to drops
            </div>
          )}
        </Block>

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

        {/* subscriptions summary */}
        <Block title="// SUBSCRIPTIONS" onClick={() => onView('subscriptions')} cta="./manage →">
          {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: 15}}>
                  <span style={{ color:'#B266FF', fontWeight: 700 }}>{(s.product_name || s.product_handle || '').toUpperCase()}</span>
                  <span style={{ color:'#BFBFBF', fontSize: 13}}>{s.cadence} · ×{s.quantity}</span>
                </div>
              ))}
              <div style={{ marginTop: 10, fontSize: 13, 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>
          )}
        </Block>
      </div>
    </div>
  );
};

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

const Block = ({ title, children, cta, onClick }) => (
  <div onClick={onClick} style={{ padding: 18, background:'#0A0A0A', border:'1px solid rgba(255,255,255,0.22)', cursor: onClick ? 'pointer' : 'default', transition:'border-color 120ms, box-shadow 120ms' }}
    onMouseEnter={(e) => { if (onClick) { e.currentTarget.style.borderColor = '#00FF41'; e.currentTarget.style.boxShadow = '0 0 18px rgba(0,255,65,0.18)'; } }}
    onMouseLeave={(e) => { e.currentTarget.style.borderColor = 'rgba(255,255,255,0.22)'; e.currentTarget.style.boxShadow = 'none'; }}>
    <div style={{ display:'flex', alignItems:'baseline', justifyContent:'space-between', marginBottom: 12 }}>
      <span style={{ fontSize: 13, color:'#BFBFBF', letterSpacing:'0.22em', fontWeight: 700 }}>{title}</span>
      {cta && <span style={{ fontSize: 13, color:'#00FF41', letterSpacing:'0.18em' }}>{cta}</span>}
    </div>
    {children}
  </div>
);

const StatusPill = ({ 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:'3px 10px', border:`1px solid ${c}`, color: c, fontSize: 12, fontWeight: 700, letterSpacing:'0.18em' }}>[{status}]</span>;
};

// ===================== ORDERS =====================
const Orders = ({ orders }) => {
  const [open, setOpen] = React.useState(null);
  return (
    <div>
      <h3 style={{ fontSize: 22, fontWeight: 800, color:'#FFF', letterSpacing:'0.04em', textTransform:'uppercase', margin: '0 0 6px' }}>./orders --all</h3>
      <div style={{ fontSize: 14, color:'#BFBFBF', letterSpacing:'0.18em', marginBottom: 22 }}>// {orders.length} records · sorted desc by date</div>

      {/* table header */}
      <div style={{ display:'grid', gridTemplateColumns:'1.2fr 1fr 1fr 1fr 0.6fr', gap: 12, padding:'10px 14px', background:'#0A0A0A', borderTop:'1px solid rgba(255,255,255,0.22)', borderBottom:'1px solid rgba(255,255,255,0.22)', fontSize: 12, letterSpacing:'0.22em', color:'#BFBFBF', fontWeight: 700 }}>
        <span>ORDER ID</span>
        <span>PLACED</span>
        <span>STATUS</span>
        <span style={{ textAlign:'right' }}>TOTAL</span>
        <span></span>
      </div>

      {orders.map((o) => (
        <div key={o.id}>
          <div onClick={() => setOpen(open === o.id ? null : o.id)} style={{
            display:'grid', gridTemplateColumns:'1.2fr 1fr 1fr 1fr 0.6fr', gap: 12,
            padding:'14px', borderBottom:'1px solid rgba(255,255,255,0.12)',
            cursor:'pointer', alignItems:'center', fontSize: 15, color:'#FFFFFF',
            background: open === o.id ? 'rgba(0,255,65,0.04)' : 'transparent',
          }}
            onMouseEnter={(e) => e.currentTarget.style.background = open === o.id ? 'rgba(0,255,65,0.06)' : 'rgba(255,255,255,0.03)'}
            onMouseLeave={(e) => e.currentTarget.style.background = open === o.id ? 'rgba(0,255,65,0.04)' : 'transparent'}>
            <span style={{ color:'#00FF41', fontWeight: 700, letterSpacing:'0.04em' }}>{o.id}</span>
            <span style={{ color:'#E0E0E0' }}>{o.placed}</span>
            <StatusPill status={o.status} />
            <span style={{ textAlign:'right', fontWeight: 700 }}>${o.total}</span>
            <span style={{ textAlign:'right', color:'#BFBFBF', fontSize: 13, letterSpacing:'0.15em' }}>{open === o.id ? '[ - ]' : '[ + ]'}</span>
          </div>
          {open === o.id && (
            <div style={{ padding:'18px 22px', background:'#0A0A0A', borderBottom:'1px solid rgba(255,255,255,0.22)' }}>
              <div style={{ display:'grid', gridTemplateColumns:'1.4fr 1fr', gap: 22 }}>
                {/* items */}
                <div>
                  <div style={{ fontSize: 12, letterSpacing:'0.22em', color:'#BFBFBF', marginBottom: 10 }}>// ITEMS</div>
                  {o.items.map((i, k) => (
                    <div key={k} style={{ display:'flex', justifyContent:'space-between', padding:'8px 0', borderBottom:'1px dashed rgba(255,255,255,0.18)', fontSize: 15}}>
                      <span><span style={{ color:'#00FF41' }}>{'>'}</span> {i.name} × {i.qty} <span style={{ color:'#BFBFBF', fontSize: 13, letterSpacing:'0.1em' }}>· {i.grind}{i.note ? ` ${i.note}` : ''}</span></span>
                      <span style={{ color:'#FFF' }}>${i.price * i.qty}</span>
                    </div>
                  ))}
                </div>
                {/* tracking + actions */}
                <div>
                  <div style={{ fontSize: 12, letterSpacing:'0.22em', color:'#BFBFBF', marginBottom: 10 }}>// SHIPMENT</div>
                  <div style={{ fontSize: 14, color:'#E0E0E0', lineHeight: 1.7 }}>tracking: <span style={{ color:'#00FF41' }}>{o.track}</span></div>
                  <div style={{ marginTop: 14, display:'flex', flexDirection:'column', gap: 6 }}>
                    <SmallBtn>./track-shipment</SmallBtn>
                    <SmallBtn>./reorder</SmallBtn>
                    <SmallBtn>./request-help</SmallBtn>
                  </div>
                </div>
              </div>
            </div>
          )}
        </div>
      ))}
    </div>
  );
};

const SmallBtn = ({ 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.18em',
    cursor:'pointer', borderRadius: 2, textAlign:'left',
  }}>{'>'} {children}</button>
);

// ===================== SUBSCRIPTIONS (multi-sub) =====================
const Subscriptions = ({ 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 {
      let 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) {
        const updated = await window.OBC_API.getSubscriptions();
        setSubs(updated);
      }
    } catch (e) {}
    setConfirming(null);
  };

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

  return (
    <div>
      <h3 style={{ fontSize: 22, fontWeight: 800, color:'#FFF', letterSpacing:'0.04em', textTransform:'uppercase', margin: '0 0 6px' }}>./subscriptions</h3>
      <div style={{ fontSize: 14, color:'#BFBFBF', letterSpacing:'0.18em', marginBottom: 22 }}>// recurring caffeine delivery · subscribe to any coffee for 5% off</div>

      {activeSubs.length === 0 && (
        <div style={{ padding: 28, background:'#0A0A0A', border:'1px dashed rgba(178,102,255,0.4)', textAlign:'center', marginBottom: 18 }}>
          <div style={{ fontSize: 16, color:'#BFBFBF', lineHeight: 1.7 }}>
            // no active subscriptions.<br/>
            subscribe to any coffee. choose your cadence. get 5% off every order.
          </div>
          <ActionBtn color="#B266FF" onClick={onShop}>./browse-coffees →</ActionBtn>
        </div>
      )}

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

            <div style={{ marginTop: 18, display:'grid', gridTemplateColumns:'repeat(4, 1fr)', gap: 1, background:'rgba(255,255,255,0.22)', border:'1px solid rgba(255,255,255,0.22)' }}>
              {[
                ['NEXT SHIP', isPaused ? '— PAUSED —' : (s.next_ship_date || '—')],
                ['CADENCE', cadenceLabels[s.cadence] || s.cadence],
                ['QTY / GRIND', `×${s.quantity} · ${s.grind}`],
                ['PRICE', `$${s.price || '—'}/ea`],
              ].map(([k, v]) => (
                <div key={k} style={{ background:'#000', padding:'12px 14px' }}>
                  <div style={{ fontSize: 12, letterSpacing:'0.22em', color:'#BFBFBF', fontWeight: 700 }}>{k}</div>
                  <div style={{ marginTop: 5, fontSize: 16, color:'#FFF', fontWeight: 600, letterSpacing:'0.06em' }}>{v}</div>
                </div>
              ))}
            </div>

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

            {confirming && confirming.id === s.id && (
              <div style={{ marginTop: 14, padding: 14, border: `1px solid ${confirming.action === 'cancel' ? '#FF3344' : '#FFD23F'}`, background:'#0A0A0A', fontSize: 15, lineHeight: 1.7, color:'#FFF' }}>
                <div style={{ color: confirming.action === 'cancel' ? '#FF3344' : '#FFD23F', letterSpacing:'0.18em', fontSize: 13, fontWeight: 700 }}>// CONFIRM ./{confirming.action}</div>
                <div style={{ marginTop: 8 }}>
                  {confirming.action === 'cancel' ? `cancel ${name} subscription? 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={{ marginTop: 14, display:'flex', gap: 8 }}>
                  <ActionBtn color={confirming.action === 'cancel' ? '#FF3344' : '#FFD23F'} onClick={() => doAction(s.id, confirming.action)}>./confirm</ActionBtn>
                  <ActionBtn color="#BFBFBF" onClick={() => setConfirming(null)}>./abort</ActionBtn>
                </div>
              </div>
            )}

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

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

const ActionBtn = ({ children, color = '#00FF41', onClick }) => (
  <button onClick={onClick} style={{
    background:'transparent', border:`1px solid ${color}`, color,
    padding:'10px 16px', fontFamily:'inherit', fontSize: 14, letterSpacing:'0.18em', fontWeight: 700,
    cursor:'pointer', borderRadius: 2,
  }}>{children}</button>
);

// ===================== SETTINGS =====================
const Settings = ({ 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}>
      <h3 style={{ fontSize: 22, fontWeight: 800, color:'#FFF', letterSpacing:'0.04em', textTransform:'uppercase', margin: '0 0 6px' }}>./settings</h3>
      <div style={{ fontSize: 14, color:'#BFBFBF', letterSpacing:'0.18em', marginBottom: 22 }}>// identity · shipping · security</div>

      <SettingsGroup title="// IDENTITY">
        <SField label="HANDLE" value={form.handle} onChange={(v) => set('handle', v)} hint="// public. shown in your receipts." />
        <SField label="DISPLAY NAME" value={form.name} onChange={(v) => set('name', v)} />
        <SField label="EMAIL" value={form.email} type="email" hint="// managed by Shopify." />
      </SettingsGroup>

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

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

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

      <div style={{ marginTop: 32, display:'flex', alignItems:'center', gap: 12, flexWrap:'wrap' }}>
        <button type="submit" disabled={saving} style={{
          background:'#00FF41', color:'#000', border:'1px solid #00FF41',
          padding:'14px 22px', fontFamily:'inherit', fontWeight: 800, fontSize: 15,
          letterSpacing:'0.22em', cursor: saving ? 'default' : 'pointer', borderRadius: 2,
          opacity: saving ? 0.5 : 1,
        }}>{saving ? '// saving...' : '> ./save-changes'}</button>
        {saved && <div style={{ color:'#00FF41', fontSize: 14, letterSpacing:'0.18em' }}>[ OK ] saved.</div>}
        {err && <div style={{ color:'#FF4444', fontSize: 14, letterSpacing:'0.18em' }}>{err}</div>}
        <span style={{ marginLeft:'auto', fontSize: 12, color:'#7A7A7A', letterSpacing:'0.18em' }}>// changes audit-logged.</span>
      </div>
    </form>
  );
};

// ===================== MFA SETTINGS =====================
const MfaSettings = ({ 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: 4, margin: 4 }).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 from your authenticator.'); 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: ' + e.message); }
    }
    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 your TOTP code to confirm removal.'); 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 your 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(''); };

  return (
    <SettingsGroup title="// SECURITY — MULTI-FACTOR AUTH">
      {/* Success banners */}
      {justEnabled === 'totp' && (
        <div style={{ padding: 14, border:'1px solid #00FF41', background:'rgba(0,255,65,0.06)', marginBottom: 14, fontSize: 14, color:'#00FF41', letterSpacing:'0.06em', lineHeight: 1.7 }}>
          // TOTP 2FA enabled. save your recovery codes somewhere safe.
        </div>
      )}
      {justEnabled === 'passkey' && (
        <div style={{ padding: 14, border:'1px solid #00FF41', background:'rgba(0,255,65,0.06)', marginBottom: 14, fontSize: 14, color:'#00FF41', letterSpacing:'0.06em', lineHeight: 1.7 }}>
          // passkey registered successfully.
        </div>
      )}
      {justEnabled === 'passkey-with-codes' && enrollData?.recovery_codes && (
        <div style={{ padding: 14, border:'1px solid #FFD23F', background:'rgba(255,210,63,0.06)', marginBottom: 14 }}>
          <div style={{ fontSize: 14, color:'#FFD23F', letterSpacing:'0.06em', lineHeight: 1.7, marginBottom: 10 }}>
            // passkey registered. SAVE YOUR RECOVERY CODES — they are your backup if you lose access.
          </div>
          <div style={{ display:'grid', gridTemplateColumns:'1fr 1fr', gap: 4, fontFamily:'inherit', fontSize: 15, color:'#FFD23F', letterSpacing:'0.1em', marginBottom: 10 }}>
            {enrollData.recovery_codes.map((c, i) => <div key={i} style={{ padding:'4px 8px', background:'rgba(255,210,63,0.06)' }}>{c}</div>)}
          </div>
          <ActionBtn color="#FFD23F" onClick={() => downloadCodes(enrollData.recovery_codes)}>./download-codes</ActionBtn>
        </div>
      )}

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

          {/* Passkeys list */}
          {status.passkeys.length > 0 && (
            <div style={{ marginBottom: 14 }}>
              <div style={{ fontSize: 13, color:'#BFBFBF', letterSpacing:'0.18em', marginBottom: 8 }}>// PASSKEYS</div>
              {status.passkeys.map(pk => (
                <div key={pk.credential_id} style={{ display:'flex', alignItems:'center', gap: 10, padding:'8px 12px', background:'#0A0A0A', border:'1px solid rgba(255,255,255,0.18)', marginBottom: 4 }}>
                  <span style={{ color:'#00E5FF', fontSize: 16}}>🔑</span>
                  <span style={{ fontSize: 15, color:'#E0E0E0', flex: 1 }}>{pk.device_name || 'Passkey'}</span>
                  {pk.last_used_at && <span style={{ fontSize: 12, color:'#9A9A9A' }}>last used: {pk.last_used_at?.slice(0,10)}</span>}
                  <span style={{ fontSize: 13, color: pk.backed_up ? '#00FF41' : '#BFBFBF' }}>{pk.backed_up ? '[synced]' : '[device]'}</span>
                </div>
              ))}
            </div>
          )}

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

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

          {!hasAny && (
            <div style={{ fontSize: 14, color:'#BFBFBF', lineHeight: 1.7, marginTop: 14 }}>
              // protect your account with TOTP or a passkey.<br/>
              // TOTP works with any authenticator app. passkeys use your device's biometrics or security key.
            </div>
          )}
        </div>
      )}

      {/* ENROLLING TOTP */}
      {phase === 'enrolling-totp' && enrollData && (
        <div>
          <div style={{ fontSize: 13, color:'#FFD23F', letterSpacing:'0.22em', marginBottom: 14 }}>$ ./mfa --enroll-totp</div>
          <div style={{ display:'grid', gridTemplateColumns:'1fr 1fr', gap: 18 }}>
            <div>
              <div style={{ fontSize: 13, color:'#BFBFBF', letterSpacing:'0.18em', marginBottom: 10 }}>// STEP 1: SCAN QR CODE</div>
              {/* SECURITY: qrSvg is from qrcode-generator library (not user input) — safe for dangerouslySetInnerHTML */}
              {qrSvg ? (
                <div dangerouslySetInnerHTML={{ __html: qrSvg }} style={{ background:'#0A0A0A', border:'1px solid rgba(255,255,255,0.22)', padding: 16, textAlign:'center', minHeight: 200, display:'flex', alignItems:'center', justifyContent:'center' }} />
              ) : (
                <div style={{ background:'#0A0A0A', border:'1px solid rgba(255,255,255,0.22)', padding: 16, textAlign:'center', minHeight: 200, display:'flex', alignItems:'center', justifyContent:'center' }}>
                  <span style={{ color:'#9A9A9A', fontSize: 13}}>loading qr...</span>
                </div>
              )}
              <div style={{ marginTop: 10, fontSize: 12, color:'#9A9A9A', letterSpacing:'0.06em' }}>// can't scan? enter manually:</div>
              <div style={{ marginTop: 6, padding:'10px 12px', background:'#0A0A0A', border:'1px solid rgba(255,255,255,0.22)', fontSize: 16, color:'#00FF41', letterSpacing:'0.12em', wordBreak:'break-all', userSelect:'all' }}>
                {enrollData.secret}
              </div>
            </div>
            <div>
              <div style={{ fontSize: 13, color:'#BFBFBF', letterSpacing:'0.18em', marginBottom: 10 }}>// STEP 2: ENTER CODE</div>
              <div style={{ fontSize: 14, color:'#E0E0E0', lineHeight: 1.7, marginBottom: 14 }}>
                scan the QR code with your authenticator app, then enter the 6-digit code.
              </div>
              <div style={{ marginBottom: 14 }}>
                <div style={{ fontSize: 13, letterSpacing:'0.22em', color:'#E0E0E0', fontWeight: 700, marginBottom: 6 }}>{'>'} TOTP 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:'12px 14px', borderRadius: 2, letterSpacing:'0.3em', textAlign:'center' }}
                  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>
              {err && <div style={{ marginBottom: 14, padding:'10px 14px', border:'1px solid #FF3344', color:'#FF3344', fontSize: 14}}>{err}</div>}
              <div style={{ display:'flex', gap: 10 }}>
                <ActionBtn color="#00FF41" onClick={confirmTotpEnroll}>{busy ? '// verifying...' : './confirm'}</ActionBtn>
                <ActionBtn color="#BFBFBF" onClick={cancelFlow}>./cancel</ActionBtn>
              </div>
              <div style={{ marginTop: 18 }}>
                <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: 12, background:'#0A0A0A', border:'1px solid rgba(255,210,63,0.4)' }}>
                    <div style={{ fontSize: 12, color:'#FF3344', letterSpacing:'0.12em', marginBottom: 8, lineHeight: 1.6 }}>
                      // SAVE THESE NOW. each code works once.
                    </div>
                    <div style={{ display:'grid', gridTemplateColumns:'1fr 1fr', gap: 4, fontSize: 15, color:'#FFD23F', letterSpacing:'0.1em' }}>
                      {enrollData.recovery_codes.map((c, i) => <div key={i} style={{ padding:'4px 8px', background:'rgba(255,210,63,0.06)' }}>{c}</div>)}
                    </div>
                    <div style={{ marginTop: 10 }}>
                      <ActionBtn color="#FFD23F" onClick={() => downloadCodes(enrollData.recovery_codes)}>./download</ActionBtn>
                    </div>
                  </div>
                )}
              </div>
            </div>
          </div>
        </div>
      )}

      {/* NAMING PASSKEY */}
      {phase === 'naming-passkey' && (
        <div>
          <div style={{ fontSize: 13, color:'#00E5FF', letterSpacing:'0.22em', marginBottom: 14 }}>$ ./mfa --register-passkey</div>
          <div style={{ fontSize: 14, color:'#E0E0E0', lineHeight: 1.7, marginBottom: 14 }}>
            // passkey captured. give it a name so you can identify it later.
          </div>
          <div style={{ marginBottom: 14 }}>
            <div style={{ fontSize: 13, letterSpacing:'0.22em', color:'#E0E0E0', fontWeight: 700, marginBottom: 6 }}>{'>'} DEVICE NAME</div>
            <input value={passkeyName} onChange={(e) => setPasskeyName(e.target.value.slice(0, 64))}
              autoFocus placeholder="e.g. MacBook Pro, YubiKey 5C"
              style={{ width:'100%', background:'#000', border:'1px solid rgba(255,255,255,0.28)', color:'#FFF', fontFamily:'inherit', fontSize: 16, padding:'10px 12px', borderRadius: 2 }}
              onFocus={(e) => { e.target.style.borderColor = '#00E5FF'; e.target.style.boxShadow = '0 0 0 1px #00E5FF'; }}
              onBlur={(e) => { e.target.style.borderColor = 'rgba(255,255,255,0.28)'; e.target.style.boxShadow = 'none'; }}
            />
          </div>
          {err && <div style={{ marginBottom: 14, padding:'10px 14px', border:'1px solid #FF3344', color:'#FF3344', fontSize: 14}}>{err}</div>}
          <div style={{ display:'flex', gap: 10 }}>
            <ActionBtn color="#00E5FF" onClick={confirmPasskeyEnroll}>{busy ? '// saving...' : './save-passkey'}</ActionBtn>
            <ActionBtn color="#BFBFBF" onClick={cancelFlow}>./cancel</ActionBtn>
          </div>
        </div>
      )}

      {/* DISABLING TOTP */}
      {phase === 'disabling' && (
        <div>
          <div style={{ fontSize: 13, color:'#FF3344', letterSpacing:'0.22em', marginBottom: 14 }}>$ ./mfa --disable-totp</div>
          <div style={{ fontSize: 14, color:'#E0E0E0', lineHeight: 1.7, marginBottom: 14 }}>
            // enter your current TOTP code to disable authenticator app 2FA.
          </div>
          <div style={{ marginBottom: 14 }}>
            <div style={{ fontSize: 13, letterSpacing:'0.22em', color:'#E0E0E0', fontWeight: 700, marginBottom: 6 }}>{'>'} TOTP 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: 220, background:'#000', border:'1px solid rgba(255,255,255,0.28)', color:'#FFF', fontFamily:'inherit', fontSize: 22, padding:'12px 14px', borderRadius: 2, letterSpacing:'0.3em', textAlign:'center' }}
              onFocus={(e) => { e.target.style.borderColor = '#FF3344'; e.target.style.boxShadow = '0 0 0 1px #FF3344'; }}
              onBlur={(e) => { e.target.style.borderColor = 'rgba(255,255,255,0.28)'; e.target.style.boxShadow = 'none'; }}
            />
          </div>
          {err && <div style={{ marginBottom: 14, padding:'10px 14px', border:'1px solid #FF3344', color:'#FF3344', fontSize: 14}}>{err}</div>}
          <div style={{ display:'flex', gap: 10 }}>
            <ActionBtn color="#FF3344" onClick={disableTotp}>{busy ? '// verifying...' : './confirm-disable'}</ActionBtn>
            <ActionBtn color="#BFBFBF" onClick={cancelFlow}>./cancel</ActionBtn>
          </div>
        </div>
      )}

      {/* REMOVING PASSKEY */}
      {phase === 'removing-passkey' && (
        <div>
          <div style={{ fontSize: 13, color:'#FF3344', letterSpacing:'0.22em', marginBottom: 14 }}>$ ./mfa --remove-passkey</div>
          <div style={{ fontSize: 14, color:'#E0E0E0', lineHeight: 1.7, marginBottom: 14 }}>
            // select a passkey to remove and enter your TOTP code to confirm.
          </div>
          {status.passkeys.map(pk => (
            <div key={pk.credential_id} style={{ display:'flex', alignItems:'center', gap: 10, padding:'8px 12px', background:'#0A0A0A', border:'1px solid rgba(255,255,255,0.18)', marginBottom: 4, cursor:'pointer' }}
              onClick={() => { if (code.length === 6) removePasskey(pk.credential_id); }}>
              <span style={{ color:'#FF3344', fontSize: 13}}>[×]</span>
              <span style={{ fontSize: 15, color:'#E0E0E0', flex: 1 }}>{pk.device_name || 'Passkey'}</span>
              <span style={{ fontSize: 12, color:'#9A9A9A' }}>{pk.credential_id?.slice(0,12)}...</span>
            </div>
          ))}
          <div style={{ marginTop: 14, marginBottom: 14 }}>
            <div style={{ fontSize: 13, letterSpacing:'0.22em', color:'#E0E0E0', fontWeight: 700, marginBottom: 6 }}>{'>'} TOTP CODE</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: 220, background:'#000', border:'1px solid rgba(255,255,255,0.28)', color:'#FFF', fontFamily:'inherit', fontSize: 22, padding:'12px 14px', borderRadius: 2, letterSpacing:'0.3em', textAlign:'center' }}
              onFocus={(e) => { e.target.style.borderColor = '#FF3344'; }}
              onBlur={(e) => { e.target.style.borderColor = 'rgba(255,255,255,0.28)'; }}
            />
          </div>
          {err && <div style={{ marginBottom: 14, padding:'10px 14px', border:'1px solid #FF3344', color:'#FF3344', fontSize: 14}}>{err}</div>}
          <ActionBtn color="#BFBFBF" onClick={cancelFlow}>./cancel</ActionBtn>
        </div>
      )}

      {/* REGENERATING CODES */}
      {phase === 'regenerating' && (
        <div>
          <div style={{ fontSize: 13, color:'#FFD23F', letterSpacing:'0.22em', marginBottom: 14 }}>$ ./mfa --regenerate-codes</div>
          <div style={{ fontSize: 14, color:'#E0E0E0', lineHeight: 1.7, marginBottom: 14 }}>
            // this will invalidate all existing recovery codes and generate new ones.<br/>
            // enter your TOTP code to confirm.
          </div>
          <div style={{ marginBottom: 14 }}>
            <div style={{ fontSize: 13, letterSpacing:'0.22em', color:'#E0E0E0', fontWeight: 700, marginBottom: 6 }}>{'>'} TOTP CODE</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: 220, background:'#000', border:'1px solid rgba(255,255,255,0.28)', color:'#FFF', fontFamily:'inherit', fontSize: 22, padding:'12px 14px', borderRadius: 2, letterSpacing:'0.3em', textAlign:'center' }}
              onFocus={(e) => { e.target.style.borderColor = '#FFD23F'; }}
              onBlur={(e) => { e.target.style.borderColor = 'rgba(255,255,255,0.28)'; }}
            />
          </div>
          {err && <div style={{ marginBottom: 14, padding:'10px 14px', border:'1px solid #FF3344', color:'#FF3344', fontSize: 14}}>{err}</div>}
          {showRecovery && enrollData?.recovery_codes && (
            <div style={{ marginBottom: 14, padding: 12, background:'#0A0A0A', border:'1px solid rgba(255,210,63,0.4)' }}>
              <div style={{ fontSize: 12, color:'#FF3344', letterSpacing:'0.12em', marginBottom: 8 }}>// NEW CODES — save these now.</div>
              <div style={{ display:'grid', gridTemplateColumns:'1fr 1fr', gap: 4, fontSize: 15, color:'#FFD23F', letterSpacing:'0.1em' }}>
                {enrollData.recovery_codes.map((c, i) => <div key={i} style={{ padding:'4px 8px', background:'rgba(255,210,63,0.06)' }}>{c}</div>)}
              </div>
              <div style={{ marginTop: 10 }}><ActionBtn color="#FFD23F" onClick={() => downloadCodes(enrollData.recovery_codes)}>./download</ActionBtn></div>
            </div>
          )}
          <div style={{ display:'flex', gap: 10 }}>
            <ActionBtn color="#FFD23F" onClick={regenerateCodes}>{busy ? '// generating...' : './regenerate'}</ActionBtn>
            <ActionBtn color="#BFBFBF" onClick={cancelFlow}>./cancel</ActionBtn>
          </div>
        </div>
      )}
    </SettingsGroup>
  );
};

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

const SField = ({ label, value, onChange, type = 'text', placeholder, hint }) => (
  <div>
    <div style={{ fontSize: 13, color:'#E0E0E0', letterSpacing:'0.22em', fontWeight: 700, marginBottom: 5 }}>{'>'} {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: 15, padding:'10px 12px', borderRadius: 2,
      }}
      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'; }}
    />
    {hint && <div style={{ marginTop: 4, fontSize: 12, color:'#9A9A9A', letterSpacing:'0.05em' }}>{hint}</div>}
  </div>
);

const Toggle = ({ 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: 15, color:'#E0E0E0', cursor:'pointer' }}>
      <span onClick={toggle} style={{
        width: 36, height: 18, background: on ? '#00FF41' : 'transparent',
        border:'1px solid '+(on ? '#00FF41' : 'rgba(255,255,255,0.28)'),
        position:'relative', borderRadius: 2,
      }}>
        <span style={{
          position:'absolute', top: 1, left: on ? 19 : 1,
          width: 14, height: 14, background: on ? '#000' : '#888',
          transition:'left 80ms ease-out',
        }}></span>
      </span>
      <span style={{ letterSpacing:'0.1em' }}>{label}</span>
    </label>
  );
};

// ===================== TIER LEVELS OVERLAY =====================
const TierLevels = ({ 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';
    const onKey = (e) => { if (e.key === 'Escape') onClose(); };
    window.addEventListener('keydown', onKey);
    return () => { document.body.style.overflow = ''; window.removeEventListener('keydown', onKey); };
  }, []);

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

  return (
    <div onClick={onClose} style={{
      position: 'fixed', inset: 0, background: 'rgba(0,0,0,0.92)', zIndex: 200,
      display: 'flex', alignItems: 'center', justifyContent: 'center',
      padding: 24, overflow: 'auto',
    }}>
      <div onClick={(e) => e.stopPropagation()} style={{
        maxWidth: 900, width: '100%', background: '#0A0A0A',
        border: '1px solid rgba(255,255,255,0.22)', padding: 28,
        maxHeight: '90vh', overflow: 'auto', position: 'relative',
        fontFamily: "'JetBrains Mono', monospace",
      }}>
        <button onClick={onClose} style={{
          position: 'absolute', top: 14, right: 14, background: 'transparent',
          border: '1px solid rgba(255,255,255,0.2)', color: '#B8B8B8',
          padding: '4px 10px', cursor: 'pointer', fontFamily: 'inherit',
          fontSize: 13, letterSpacing: '0.18em',
        }}>[ ESC ] CLOSE</button>

        <div style={{ fontSize: 13, letterSpacing: '0.25em', color: '#BFBFBF', fontWeight: 600 }}>// SYSTEM</div>
        <h2 style={{ fontSize: 28, fontWeight: 800, color: '#FFF', letterSpacing: '0.04em', margin: '8px 0 4px', textTransform: 'uppercase' }}>Clearance Levels</h2>
        <div style={{ fontSize: 14, color: '#9A9A9A', letterSpacing: '0.08em', marginBottom: 24 }}>
          // ranks earned through loyalty. keep ordering — the system tracks everything.
        </div>

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

        <div style={{ display: 'flex', flexDirection: 'column', gap: 2 }}>
          {TIERS.map((t, i) => {
            const isCurrent = i === currentIdx;
            const isReached = i <= currentIdx;
            const perks = tierPerks[i] || [];
            return (
              <div key={t.name} style={{
                display: 'grid', gridTemplateColumns: '200px 1fr',
                border: `1px solid ${isCurrent ? t.accent : 'rgba(255,255,255,0.12)'}`,
                background: isCurrent ? t.accent + '0A' : 'transparent',
                transition: 'border-color 120ms',
              }}>
                {/* Left: rank info */}
                <div style={{
                  padding: '16px 18px', borderRight: `1px solid ${isCurrent ? t.accent + '44' : 'rgba(255,255,255,0.08)'}`,
                  display: 'flex', flexDirection: 'column', justifyContent: 'center',
                }}>
                  <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
                    <span style={{ fontSize: 24, fontWeight: 800, color: t.accent, lineHeight: 1 }}>{t.glyph}</span>
                    <span style={{ fontSize: 15, fontWeight: 800, color: t.accent, letterSpacing: '0.06em' }}>{t.name}</span>
                  </div>
                  <div style={{ marginTop: 6, fontSize: 13, color: '#9A9A9A', letterSpacing: '0.12em' }}>
                    {t.threshold === 0 ? '// starting rank' : `// clearance ${i} of ${TIERS.length - 1}`}
                  </div>
                  {isCurrent && (
                    <div style={{ marginTop: 6, padding: '2px 8px', display: 'inline-block', width: 'fit-content', border: `1px solid ${t.accent}`, fontSize: 11, color: t.accent, letterSpacing: '0.18em', fontWeight: 700 }}>
                      YOU ARE HERE
                    </div>
                  )}
                </div>

                {/* Right: perks */}
                <div style={{ padding: '14px 18px', display: 'flex', flexDirection: 'column', justifyContent: 'center' }}>
                  {perks.length > 0 ? (
                    <div style={{ display: 'flex', flexWrap: 'wrap', gap: 8 }}>
                      {perks.map((pk, j) => (
                        <span key={j} style={{
                          padding: '6px 12px', fontSize: 15, fontWeight: 600, letterSpacing: '0.04em',
                          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: 15, color: '#888', letterSpacing: '0.04em', padding: '4px 0' }}>
                      // base rank — start ordering to unlock perks
                    </div>
                  )}
                  {t.discount > 0 && (
                    <div style={{ marginTop: 8, fontSize: 13, color: isReached ? '#E0E0E0' : '#555', letterSpacing: '0.06em' }}>
                      {`tier discount: ${t.discount}% on all orders`}{isSub ? ` · +5% on subscriptions` : ''}
                    </div>
                  )}
                </div>
              </div>
            );
          })}
        </div>

        <div style={{ marginTop: 20, paddingTop: 14, borderTop: '1px dashed rgba(255,255,255,0.18)', display: 'flex', justifyContent: 'space-between', alignItems: 'baseline' }}>
          <span style={{ fontSize: 13, color: '#9A9A9A', letterSpacing: '0.1em' }}>// your points: <span style={{ color: '#FFF', fontWeight: 700 }}>{Math.round(currentSpend)} pts</span></span>
          <span style={{ fontSize: 12, color: '#6E6E6E', letterSpacing: '0.12em' }}>1 dollar spent = 1 point · bonus events coming</span>
        </div>
        <div style={{ marginTop: 8, fontSize: 12, color: '#00FF41', letterSpacing: '0.08em' }}>
          // all ranks are permanent — your status never expires.
        </div>
      </div>
    </div>
  );
};

window.Account = Account;
