/* global React, Ico, NWO_ENDPOINTS */
const { useState: useS, useEffect: useE, useRef: useR } = React;

/* ====================== Render API helper + Session signing ====================== */
const API_BASE = (typeof window !== 'undefined' && window.NWO_API_BASE) || 'https://nwo-capital-api.onrender.com/api';
const NWO_SESSION_KEY = 'nwo_session_v1';
const SESSION_TTL_MS = 60 * 60 * 1000;  // 1 hour

/* Build the canonical message that the user signs once per hour.
 * Includes origin, wallet, issued-at, expires-at, nonce.
 * Backend recovers signer with eth_account, checks origin + expiry. */
function nwoBuildSessionMessage(wallet, issuedAt, expiresAt, nonce) {
  const origin = (typeof window !== 'undefined' && window.location && window.location.origin) || '';
  return [
    'NWO Capital - session authorization',
    '',
    'Signing this message proves you control this wallet and authorizes',
    'the dapp at the origin below to make API requests on your behalf',
    'until the expiry timestamp. This is NOT a transaction. No fees.',
    '',
    'origin:    ' + origin,
    'wallet:    ' + wallet.toLowerCase(),
    'issued_at: ' + new Date(issuedAt).toISOString(),
    'expires:   ' + new Date(expiresAt).toISOString(),
    'nonce:     ' + nonce
  ].join('\n');
}

/* Get cached session for wallet, or null if none / expired / wrong wallet */
function nwoGetSession(wallet) {
  if (!wallet || typeof window === 'undefined') return null;
  try {
    const raw = window.localStorage.getItem(NWO_SESSION_KEY);
    if (!raw) return null;
    const s = JSON.parse(raw);
    if (!s || s.wallet !== wallet.toLowerCase()) return null;
    if (s.expiresAt < Date.now()) {
      window.localStorage.removeItem(NWO_SESSION_KEY);
      return null;
    }
    return s;
  } catch (_) {
    return null;
  }
}

function nwoClearSession() {
  if (typeof window !== 'undefined') {
    try { window.localStorage.removeItem(NWO_SESSION_KEY); } catch (_) {}
  }
}

/* Prompt MetaMask once to sign the session message; cache for 1 hour */
async function nwoCreateSession(wallet) {
  if (!wallet || typeof window === 'undefined' || !window.ethereum) {
    throw new Error('No wallet available');
  }
  const lower = wallet.toLowerCase();
  const issuedAt = Date.now();
  const expiresAt = issuedAt + SESSION_TTL_MS;
  // 16-byte hex nonce
  const nonceBytes = new Uint8Array(16);
  (window.crypto || window.msCrypto).getRandomValues(nonceBytes);
  const nonce = Array.from(nonceBytes).map(b => b.toString(16).padStart(2, '0')).join('');

  const message = nwoBuildSessionMessage(lower, issuedAt, expiresAt, nonce);
  // personal_sign expects [message, address]
  const signature = await window.ethereum.request({
    method: 'personal_sign',
    params: [message, lower],
  });
  const session = { wallet: lower, message, signature, issuedAt, expiresAt, nonce };
  try { window.localStorage.setItem(NWO_SESSION_KEY, JSON.stringify(session)); } catch (_) {}
  return session;
}

/* Public: ensure a valid session exists for `wallet`, prompting if needed */
async function nwoEnsureSession(wallet) {
  if (!wallet) throw new Error('No wallet connected');
  const existing = nwoGetSession(wallet);
  if (existing) return existing;
  return await nwoCreateSession(wallet);
}

/* Authenticated fetch. If wallet is provided, attaches signed-session headers.
 * Backend reads X-NWO-Wallet, X-NWO-Message, X-NWO-Signature and verifies. */
async function apiFetch(path, opts = {}) {
  const url = API_BASE + path;
  const init = {
    method: opts.method || 'GET',
    headers: { 'Content-Type': 'application/json', ...(opts.headers || {}) },
  };

  // Attach signed-session headers when wallet is provided
  const wallet = opts.wallet || null;
  if (wallet) {
    const session = await nwoEnsureSession(wallet);
    init.headers['X-NWO-Wallet'] = session.wallet;
    init.headers['X-NWO-Message'] = (typeof window.btoa === 'function' ? window.btoa(unescape(encodeURIComponent(session.message))) : session.message);
    init.headers['X-NWO-Signature'] = session.signature;
  }

  if (opts.body !== undefined) init.body = JSON.stringify(opts.body);

  let resp;
  try {
    resp = await fetch(url, init);
  } catch (e) {
    throw new Error('network: ' + (e && e.message ? e.message : 'request failed'));
  }
  let data = null;
  const text = await resp.text();
  if (text) {
    try { data = JSON.parse(text); } catch (_) { data = { raw: text }; }
  }
  if (!resp.ok) {
    // Auth failures: clear session so user is prompted to re-sign
    if (resp.status === 401 || resp.status === 403) {
      nwoClearSession();
    }
    const msg = (data && (data.error || data.message)) || ('http ' + resp.status);
    const err = new Error(msg);
    err.status = resp.status;
    err.data = data;
    throw err;
  }
  return data;
}

// Expose so other code (e.g. shell) can clear session on disconnect
if (typeof window !== 'undefined') {
  window.nwoClearSession = nwoClearSession;
  window.nwoEnsureSession = nwoEnsureSession;
  window.nwoApiFetch = apiFetch;  // exposed for shell.jsx health badge
}


/* =========================================================
   PAGES — Public landing, Dashboard, Tracking, API keys,
   Chat Terminal, Model Router, Ethics Engine, IoT, Info,
   Endpoints, Docs, HF Demo, Own Robot, Bot Market, Agent Graph
   ========================================================= */

/* ====================== Reusable HF Space embed (responsive) ======================
 * Used by all pages that embed an HF Space or external dApp. Replaces the old
 * pattern of fixed-height 820px iframes that looked tiny on large monitors.
 *
 * Sizing rules:
 *  - width: 100% of the container card (the card itself stretches via .main-inner)
 *  - height: min(85vh, 1200px) — scales with viewport, capped to stop absurd ultrawides
 *  - minHeight: 720px so it never collapses on small laptops
 *
 * Inject a <style> for media-query override on phones — viewBox JS can't react to
 * width media queries, only height, so the mobile drop is done via CSS class.
 * ================================================================================ */
function HFEmbed({ src, title, allow }) {
  return (
    <React.Fragment>
      <style>{`
        .nwo-hf-frame {
          width: 100%;
          height: min(85vh, 1200px);
          min-height: 720px;
          border: 0;
          background: #000;
          display: block;
        }
        @media (max-width: 720px) {
          .nwo-hf-frame {
            height: 75vh;
            min-height: 520px;
          }
        }
      `}</style>
      <div className="card" style={{padding:0, overflow:'hidden', width:'100%'}}>
        <iframe
          src={src}
          className="nwo-hf-frame"
          loading="lazy"
          referrerPolicy="no-referrer"
          title={title}
          sandbox="allow-scripts allow-same-origin allow-popups allow-forms allow-downloads allow-modals"
          allow={allow || "accelerometer; autoplay; camera; clipboard-read; clipboard-write; encrypted-media; fullscreen; geolocation; gyroscope; microphone; payment; picture-in-picture; web-share"}
        />
      </div>
    </React.Fragment>
  );
}

/* ====================== OWN ROBOT HF EMBED (with wallet) ====================== */
function OwnRobotEmbed({ walletAddr }) {
  const iframeRef = useR(null);
  const [iframeLoaded, setIframeLoaded] = useS(false);

  // Send wallet address to iframe when connected
  useE(() => {
    if (!iframeRef.current || !walletAddr) return;
    
    const sendWalletToIframe = () => {
      try {
        iframeRef.current.contentWindow.postMessage({
          type: 'NWO_WALLET_CONNECTED',
          wallet: walletAddr,
          timestamp: Date.now()
        }, '*'); // In production, use specific HF Space origin
      } catch (e) {
        console.warn('Failed to send wallet to iframe:', e);
      }
    };

    // Send immediately and retry after iframe loads
    sendWalletToIframe();
    const timer = setTimeout(sendWalletToIframe, 1000);
    return () => clearTimeout(timer);
  }, [walletAddr, iframeLoaded]);

  // Listen for messages from iframe
  useE(() => {
    const handleMessage = (e) => {
      // Verify origin in production: e.origin === 'https://cpater-nwo-own-robot.hf.space'
      if (e.data?.type === 'NWO_IFRAME_READY') {
        setIframeLoaded(true);
      }
    };
    window.addEventListener('message', handleMessage);
    return () => window.removeEventListener('message', handleMessage);
  }, []);

  return (
    <div className="card" style={{marginBottom:24, borderColor:'var(--g-primary)', boxShadow:'0 0 24px var(--g-glow)'}}>
      <div className="card-head">
        <h3>// Live · nwo.ciprianpater.workers.dev · interactive</h3>
        <div style={{display:'flex', gap:'10px', alignItems:'center'}}>
          {walletAddr ? (
            <span className="badge" style={{background:'var(--g-glow)', color:'var(--g-primary)'}}>
              {walletAddr.slice(0,6)}…{walletAddr.slice(-4)}
            </span>
          ) : (
            <span className="badge">Connect wallet to interact</span>
          )}
          <span className="badge live">● LIVE</span>
        </div>
      </div>
      <div className="hf-wrap" style={{border:'none'}}>
        <div className="hf-head">
          <div className="dots"><span/><span/><span/></div>
          <div>nwo.ciprianpater.workers.dev</div>
          <a className="btn-sm btn btn-muted" href="https://nwo.ciprianpater.workers.dev/" target="_blank">Open ↗</a>
        </div>
        <iframe 
          ref={iframeRef}
          className="hf-iframe" 
          style={{
            width:'100%',
            height:'min(85vh, 1200px)',
            minHeight:720,
            border:'0',
            background:'#000',
            display:'block'
          }}
          src="https://nwo.ciprianpater.workers.dev/"
          title="NWO Own Robot — Conway agent deployment"
          allow="accelerometer; ambient-light-sensor; autoplay; battery; camera; document-domain; encrypted-media; fullscreen; geolocation; gyroscope; layout-animations; legacy-image-formats; magnetometer; microphone; midi; oversized-images; payment; picture-in-picture; publickey-credentials-get; sync-xhr; usb; vr; wake-lock; xr-spatial-tracking; clipboard-read; clipboard-write; web-share"
          referrerPolicy="no-referrer-when-downgrade"
          sandbox="allow-same-origin allow-scripts allow-forms allow-popups allow-downloads allow-modals allow-pointer-lock allow-top-navigation-by-user-activation"
        />
      </div>
    </div>
  );
}

/* ====================== LANDING (public) ====================== */
function LandingPage({ onLogin, onWallet, walletAvailable, walletAddr }) {
  return (
    <div className="fade-in">
      <section className="hero" style={{padding:'40px 0 28px'}}>
        <div className="hero-badge">{Ico.dot && Ico.dot()} NWO CAPITAL · MISSION CONTROL</div>
        <h1 style={{fontSize:48}}>Human-Aware <span className="hl">Robotics</span> · Runs on <span className="hl">NWO.</span></h1>
        <p>Natural-language control, cardiac biometric auth, ethics reasoning, swarm coordination — all routed through a verifiable agent graph on Base Mainnet.</p>
      </section>

      {/* NWO OWN ROBOT HF Embed with wallet integration */}
      <OwnRobotEmbed walletAddr={walletAddr} />

      <div className="feat-grid">
        {[
          ['Natural Language Control', 'Issue commands in plain English. VLA router resolves to the optimal motion policy in ≤ 200ms.', 'terminal'],
          ['Cardiac Biometric Auth', 'WiFi CSI + BLE dual-modal verification. Contactless, continuous, hard to spoof.', 'heart'],
          ['Ethics Engine v1', '10+ philosophical frameworks with full chain-of-thought and audit trail.', 'scales'],
          ['Agent Graph', 'Every intent, publication and coordination message is posted on-chain.', 'swarm'],
          ['Base Mainnet Identity', 'Soul-bound NFTs with hardware attestation. did:nwo:base:{id}.', 'key'],
          ['Swarm Coordination', 'Multi-agent mission planning with MAVLink / PX4 / Autoware bridges.', 'mav'],
        ].map(([t,d,i])=>(
          <div className="feat" key={t}>
            <div className="feat-ico">{Ico[i]({width:18,height:18})}</div>
            <h4>{t}</h4>
            <p>{d}</p>
          </div>
        ))}
      </div>
    </div>
  );
}

/* ====================== DASHBOARD (private) ====================== */
function DashboardPage({ walletAddr }) {
  const [tick, setTick] = useS(0);
  const [showRegister, setShowRegister] = useS(false);
  const [robotName, setRobotName] = useS('');
  const [robotType, setRobotType] = useS('mobile_manipulator');
  const [robotDesc, setRobotDesc] = useS('');
  const [registering, setRegistering] = useS(false);
  const [regError, setRegError] = useS('');
  const [regSuccess, setRegSuccess] = useS(null);

  // Stats from Render
  const [stats, setStats] = useS({ robots: null, missions: null, agents: null, calls24h: null });

  useE(() => { const id = setInterval(()=>setTick(t=>t+1), 2000); return ()=>clearInterval(id); }, []);

  // Load stats from Render when wallet connected
  useE(() => {
    if (!walletAddr) {
      setStats({ robots: null, missions: null, agents: null, calls24h: null });
      return;
    }
    let cancelled = false;
    (async () => {
      // Robots
      try {
        const r = await apiFetch('/robots', { wallet: walletAddr });
        if (cancelled) return;
        const arr = Array.isArray(r) ? r : (r && Array.isArray(r.robots) ? r.robots : []);
        setStats(s => ({ ...s, robots: arr.length }));
      } catch (_) {}
      // Missions
      try {
        const m = await apiFetch('/missions', { wallet: walletAddr });
        if (cancelled) return;
        const arr = Array.isArray(m) ? m : (m && Array.isArray(m.missions) ? m.missions : []);
        setStats(s => ({ ...s, missions: arr.length }));
      } catch (_) {}
      // Calls 24h — derived from /model-usage if present
      try {
        const u = await apiFetch('/model-usage', { wallet: walletAddr });
        if (cancelled) return;
        const calls = u && u.usage && u.usage.calls != null ? Number(u.usage.calls) : null;
        setStats(s => ({ ...s, calls24h: calls }));
      } catch (_) {}
      // Agents — from /discovery/whoami
      try {
        const w = await apiFetch('/discovery/whoami', { wallet: walletAddr });
        if (cancelled) return;
        const agents = w && Array.isArray(w.agents) ? w.agents.length : null;
        setStats(s => ({ ...s, agents }));
      } catch (_) {}
    })();
    return () => { cancelled = true; };
  }, [walletAddr]);

  // Listen for robot-registered to refresh count
  useE(() => {
    if (!walletAddr) return;
    const handler = async () => {
      try {
        const r = await apiFetch('/robots', { wallet: walletAddr });
        const arr = Array.isArray(r) ? r : (r && Array.isArray(r.robots) ? r.robots : []);
        setStats(s => ({ ...s, robots: arr.length }));
      } catch (_) {}
    };
    window.addEventListener('nwo:robot-registered', handler);
    return () => window.removeEventListener('nwo:robot-registered', handler);
  }, [walletAddr]);

  const openRegister = () => {
    if (!walletAddr) return;
    setShowRegister(true);
    setRobotName('');
    setRobotType('mobile_manipulator');
    setRobotDesc('');
    setRegError('');
    setRegSuccess(null);
  };

  const submitRegister = async () => {
    if (!robotName.trim() || !walletAddr) return;
    setRegistering(true);
    setRegError('');
    try {
      const data = await apiFetch('/robots', {
        method: 'POST',
        body: { name: robotName.trim(), type: robotType, description: robotDesc.trim() || null },
        wallet: walletAddr,
      });
      setRegSuccess(data);
      // Notify other pages (Tracking) to refresh
      window.dispatchEvent(new CustomEvent('nwo:robot-registered', { detail: data }));
    } catch (e) {
      setRegError(e.message || 'Failed to register robot');
    } finally {
      setRegistering(false);
    }
  };

  const closeModalAndReset = () => {
    setShowRegister(false);
    setRegSuccess(null);
    setRegError('');
  };

  // Deploy a mission via POST /missions
  const deployMission = async () => {
    if (!walletAddr) return;
    const goal = window.prompt('Mission goal (natural language):');
    if (!goal || !goal.trim()) return;
    try {
      const data = await apiFetch('/missions', {
        method: 'POST',
        body: { goal: goal.trim() },
        wallet: walletAddr,
      });
      const id = (data && (data.id || data.mission_id)) || '?';
      window.alert('Mission queued. ID: ' + id);
      // Refresh missions stat
      try {
        const m = await apiFetch('/missions', { wallet: walletAddr });
        const arr = Array.isArray(m) ? m : (m && Array.isArray(m.missions) ? m.missions : []);
        setStats(s => ({ ...s, missions: arr.length }));
      } catch (_) {}
    } catch (e) {
      window.alert('Failed to deploy mission: ' + (e.message || 'unknown error'));
    }
  };

  const robotTypes = [
    { value: 'mobile_manipulator', label: 'Mobile Manipulator (e.g., UR5e on AMR)' },
    { value: 'manipulator',        label: 'Stationary Manipulator' },
    { value: 'humanoid',           label: 'Humanoid' },
    { value: 'quadruped',          label: 'Quadruped (e.g., Spot, Unitree Go)' },
    { value: 'wheeled',            label: 'Wheeled / AMR' },
    { value: 'aerial',             label: 'Aerial / Drone' },
    { value: 'other',              label: 'Other' },
  ];

  return (
    <div className="fade-in">
      <div className="page-head">
        <div>
          <div className="page-tag">// 01 / MISSION CONTROL</div>
          <h1 className="page-title">NWO Dashboard</h1>
          <p className="page-sub">Operational overview of your fleet, agents and pipelines. Metrics pulled live from the Render API every 2s when wallet is connected.</p>
        </div>
        <div className="page-actions">
          <button className="btn btn-ghost" onClick={openRegister} disabled={!walletAddr} title={!walletAddr ? 'Connect wallet to register robots' : ''}>
            {Ico.plus({width:12,height:12})} Register Robot
          </button>
          <button className="btn btn-primary" disabled={!walletAddr} onClick={deployMission} title={!walletAddr ? 'Connect wallet to deploy missions' : 'Deploy a mission via /api/missions'}>
            Deploy Mission
          </button>
        </div>
      </div>

      {showRegister && (
        <div style={{
          position:'fixed', inset:0, background:'rgba(0,0,0,0.7)', zIndex:1000,
          display:'flex', alignItems:'center', justifyContent:'center', padding:20
        }} onClick={(e) => { if (e.target === e.currentTarget) closeModalAndReset(); }}>
          <div style={{
            background:'var(--bg-card)', border:'1px solid var(--g-primary)',
            maxWidth:520, width:'100%', maxHeight:'90vh', overflowY:'auto'
          }}>
            <div className="card-head" style={{padding:'14px 18px'}}>
              <h3>// {regSuccess ? 'Robot Registered' : 'Register Robot'}</h3>
              <button onClick={closeModalAndReset} style={{
                background:'transparent', border:'none', color:'var(--text-mute)',
                cursor:'pointer', fontSize:18, padding:0, lineHeight:1
              }}>×</button>
            </div>
            <div className="card-body" style={{padding:18}}>
              {regSuccess ? (
                <div>
                  <div style={{color:'var(--g-primary)', fontFamily:'var(--font-mono)', fontSize:11, letterSpacing:'0.1em', marginBottom:12}}>
                    ● SUCCESS
                  </div>
                  <div style={{color:'var(--text)', fontSize:13, lineHeight:1.6, marginBottom:14}}>
                    Robot <strong>{regSuccess.name || robotName}</strong> registered. ID: <code style={{color:'var(--g-primary)', fontFamily:'var(--font-mono)'}}>{regSuccess.id || regSuccess.robot_id || '—'}</code>
                  </div>
                  <div className="form-actions">
                    <button className="btn btn-ghost" onClick={closeModalAndReset}>Close</button>
                    <button className="btn btn-primary" onClick={() => { closeModalAndReset(); window.location.hash = '#/tracking'; }}>
                      View in Tracking →
                    </button>
                  </div>
                </div>
              ) : (
                <>
                  {regError && (
                    <div style={{
                      padding:'10px 12px', border:'1px solid #f85149', background:'rgba(248,81,73,0.05)',
                      color:'#f85149', fontSize:12, fontFamily:'var(--font-mono)', marginBottom:14
                    }}>ERROR · {regError}</div>
                  )}
                  <div className="form-row">
                    <label>Robot Name <span style={{color:'#f85149'}}>*</span></label>
                    <input className="input" value={robotName} onChange={e=>setRobotName(e.target.value)}
                      placeholder="e.g., warehouse-arm-01" disabled={registering} autoFocus />
                  </div>
                  <div className="form-row">
                    <label>Robot Type</label>
                    <select className="input" value={robotType} onChange={e=>setRobotType(e.target.value)} disabled={registering}>
                      {robotTypes.map(t => <option key={t.value} value={t.value}>{t.label}</option>)}
                    </select>
                  </div>
                  <div className="form-row">
                    <label>Description (optional)</label>
                    <textarea className="input" value={robotDesc} onChange={e=>setRobotDesc(e.target.value)}
                      placeholder="e.g., picking and packing in warehouse zone B"
                      rows={3} disabled={registering} style={{fontFamily:'var(--font-mono)', fontSize:12, resize:'vertical'}} />
                  </div>
                  <div style={{fontSize:11, color:'var(--text-dim)', marginBottom:14, lineHeight:1.5}}>
                    Robot will be registered to wallet <code style={{color:'var(--g-primary)', fontFamily:'var(--font-mono)'}}>{walletAddr ? walletAddr.slice(0,8)+'…'+walletAddr.slice(-4) : ''}</code> via Render API.
                  </div>
                  <div className="form-actions">
                    <button className="btn btn-ghost" onClick={closeModalAndReset} disabled={registering}>Cancel</button>
                    <button className="btn btn-primary" onClick={submitRegister} disabled={registering || !robotName.trim()}>
                      {registering ? 'Registering…' : 'Register'}
                    </button>
                  </div>
                </>
              )}
            </div>
          </div>
        </div>
      )}

      <div className="stat-grid">
        {[
          ['Robots Online',   walletAddr ? (stats.robots   !== null ? String(stats.robots)   : '—') : '—', 'GET /robots'],
          ['Active Missions', walletAddr ? (stats.missions !== null ? String(stats.missions) : '—') : '—', 'GET /missions'],
          ['Active Agents',   walletAddr ? (stats.agents   !== null ? String(stats.agents)   : '—') : '—', 'GET /discovery/whoami'],
          ['API Calls 24h',   walletAddr ? (stats.calls24h !== null ? String(stats.calls24h) : '—') : '—', 'GET /model-usage'],
          ['Graph Nodes',     '—', 'pending /graph/v1/nodes'],
        ].map(([l,v,d])=>(
          <div className="stat" key={l}>
            <div className="stat-label">{l}</div>
            <div className="stat-val">{v}</div>
            <div className="stat-delta">{d}</div>
          </div>
        ))}
      </div>

      <div className="grid-2">
        <div className="card">
          <div className="card-head"><h3>// Fleet Telemetry</h3><span className="badge live">● LIVE</span></div>
          <div className="card-body">
            {!walletAddr ? (
              <div className="term">
                <span className="mute">[auth] wallet not connected — data stream paused</span>{"\n"}
                <span className="mute">[hint] connect wallet to view real-time telemetry</span>
              </div>
            ) : (
              <div className="term">
                <span className="ok">[telemetry]</span> stream active <span className="mute">tick={tick}</span>{"\n"}
                <span className="mute">[robots] {stats.robots !== null ? stats.robots + ' registered on Render' : 'fetching /robots ...'}</span>{"\n"}
                <span className="mute">[missions] {stats.missions !== null ? stats.missions + ' active' : 'fetching /missions ...'}</span>{"\n"}
                <span className="mute">[agents] {stats.agents !== null ? stats.agents + ' resolved via /discovery/whoami' : 'pending whoami...'}</span>
              </div>
            )}
          </div>
        </div>

        <div className="card">
          <div className="card-head"><h3>// Agent Graph</h3><span className="badge">v1.2</span></div>
          <div className="card-body" style={{minHeight:220}}>
            <div className="term">
              <span className="mute">[graph] last sync: 2025-08-20T14:32:01Z</span>{"\n"}
              <span className="mute">[nodes] 1,247 active</span>{"\n"}
              <span className="mute">[edges] 8,392 verified</span>{"\n"}
              <span className="mute">[consensus] 14 validators online</span>
            </div>
          </div>
        </div>
      </div>
    </div>
  );
}

/* ====================== TRACKING (private) ====================== */
function TrackingPage({ walletAddr }) {
  const [robots, setRobots] = useS([]);
  const [loading, setLoading] = useS(false);
  const [error, setError] = useS('');

  const loadRobots = React.useCallback(async () => {
    if (!walletAddr) { setRobots([]); return; }
    setLoading(true);
    setError('');
    try {
      const data = await apiFetch('/robots', { wallet: walletAddr });
      const arr = Array.isArray(data) ? data : (data && Array.isArray(data.robots) ? data.robots : []);
      setRobots(arr);
    } catch (e) {
      setError(e.message || 'Failed to load robots');
      setRobots([]);
    } finally {
      setLoading(false);
    }
  }, [walletAddr]);

  useE(() => { loadRobots(); }, [loadRobots]);

  // Listen for "robot-registered" event from Dashboard modal so list refreshes
  useE(() => {
    const handler = () => loadRobots();
    window.addEventListener('nwo:robot-registered', handler);
    return () => window.removeEventListener('nwo:robot-registered', handler);
  }, [loadRobots]);

  return (
    <div className="fade-in">
      <div className="page-head">
        <div>
          <div className="page-tag">// 02 / FLEET</div>
          <h1 className="page-title">Robot Tracking</h1>
          <p className="page-sub">Real-time position, state and mission progress for all registered robots.</p>
        </div>
        {walletAddr && (
          <div className="page-actions">
            <button className="btn btn-ghost" onClick={loadRobots} disabled={loading}>
              {loading ? 'Refreshing…' : 'Refresh'}
            </button>
          </div>
        )}
      </div>

      {!walletAddr ? (
        <div className="card"><div className="card-body">
          <div className="empty">
            <div className="empty-ico">{Ico.lock({width:32,height:32})}</div>
            <div className="empty-title">Authentication Required</div>
            <div className="empty-desc">Connect your wallet to view robot tracking data.</div>
          </div>
        </div></div>
      ) : (
        <>
          {error && (
            <div className="card" style={{marginBottom:16, borderColor:'#f85149'}}>
              <div className="card-body" style={{color:'#f85149', fontSize:13, fontFamily:'var(--font-mono)'}}>
                ERROR · {error}
              </div>
            </div>
          )}

          <div className="card">
            <div className="card-head">
              <h3>// Registered Robots</h3>
              <span className="badge">{loading ? 'loading…' : `${robots.length} robot${robots.length === 1 ? '' : 's'}`}</span>
            </div>
            <div className="card-body">
              {loading && robots.length === 0 ? (
                <div className="term"><span className="mute">[robots] fetching from Render…</span></div>
              ) : robots.length === 0 ? (
                <div className="empty">
                  <div className="empty-title">No Robots Registered</div>
                  <div className="empty-desc">Go to Dashboard and click <strong>+ Register Robot</strong> to register your first robot.</div>
                </div>
              ) : (
                <div style={{display:'flex', flexDirection:'column', gap:10}}>
                  {robots.map((r, idx) => {
                    const id = r.id || r.robot_id || idx;
                    const name = r.name || r.robot_name || 'unnamed';
                    const type = r.type || r.robot_type || '—';
                    const status = r.status || 'unknown';
                    const created = r.created_at || r.created || '';
                    const isOnline = status === 'online' || status === 'active';
                    return (
                      <div key={id} style={{
                        padding:'14px 16px', border:'1px solid var(--line)', background:'var(--bg-card)',
                        display:'grid', gridTemplateColumns:'minmax(0,2fr) 100px 90px 110px',
                        gap:14, alignItems:'center'
                      }}>
                        <div style={{minWidth:0}}>
                          <div style={{color:'var(--text)', fontWeight:600, fontSize:13, marginBottom:2}}>{name}</div>
                          <div style={{color:'var(--text-dim)', fontFamily:'var(--font-mono)', fontSize:10, whiteSpace:'nowrap', overflow:'hidden', textOverflow:'ellipsis'}}>id: {id}</div>
                        </div>
                        <span style={{color:'var(--text-mute)', fontFamily:'var(--font-mono)', fontSize:11}}>{type}</span>
                        <span style={{
                          color: isOnline ? 'var(--g-primary)' : 'var(--text-dim)',
                          fontFamily:'var(--font-mono)', fontSize:10, letterSpacing:'0.1em',
                          textTransform:'uppercase'
                        }}>● {status}</span>
                        <span style={{color:'var(--text-dim)', fontFamily:'var(--font-mono)', fontSize:10}}>
                          {typeof created === 'string' ? created.slice(0, 10) : '—'}
                        </span>
                      </div>
                    );
                  })}
                </div>
              )}
            </div>
          </div>

          <div className="card" style={{marginTop:16}}>
            <div className="card-head"><h3>// AI Agents</h3><span className="badge">Render</span></div>
            <div className="card-body">
              <div style={{color:'var(--text-mute)', fontSize:12, lineHeight:1.6}}>
                AI agents are now resolved via <code style={{color:'var(--g-primary)', fontFamily:'var(--font-mono)'}}>GET /api/discovery/whoami</code> on Render. Use the Dashboard <strong>Active Agents</strong> stat for the count tied to your wallet.
              </div>
            </div>
          </div>
        </>
      )}
    </div>
  );
}

/* ====================== API KEYS (private) ====================== */
function ApiKeysPage({ walletAddr }) {
  const [keys, setKeys] = useS([]);
  const [loading, setLoading] = useS(false);
  const [error, setError] = useS('');
  const [showNew, setShowNew] = useS(false);
  const [newName, setNewName] = useS('');
  const [creating, setCreating] = useS(false);
  const [justCreated, setJustCreated] = useS(null);  // shows full key once after create
  const [copiedId, setCopiedId] = useS(null);

  // Load keys from Render
  const loadKeys = React.useCallback(async () => {
    if (!walletAddr) { setKeys([]); return; }
    setLoading(true);
    setError('');
    try {
      const data = await apiFetch('/api-keys', { wallet: walletAddr });
      // API may return { keys: [...] } or just [...] — handle both
      const arr = Array.isArray(data) ? data : (data && Array.isArray(data.keys) ? data.keys : []);
      setKeys(arr);
    } catch (e) {
      setError(e.message || 'Failed to load keys');
      setKeys([]);
    } finally {
      setLoading(false);
    }
  }, [walletAddr]);

  useE(() => { loadKeys(); }, [loadKeys]);

  const createKey = async () => {
    if (!newName.trim() || !walletAddr) return;
    setCreating(true);
    setError('');
    try {
      const data = await apiFetch('/api-keys', {
        method: 'POST',
        body: { name: newName.trim() },
        wallet: walletAddr,
      });
      // Expected response: { key: 'nwo_xxx', name, id, created_at, ... }
      // Show the full key once (it won't be retrievable again)
      setJustCreated(data);
      setNewName('');
      setShowNew(false);
      // Refresh list
      await loadKeys();
    } catch (e) {
      setError(e.message || 'Failed to create key');
    } finally {
      setCreating(false);
    }
  };

  const revokeKey = async (k) => {
    if (!walletAddr || !k) return;
    const id = k.id || k.key_id;
    if (!id) {
      setError('Cannot revoke: key has no id');
      return;
    }
    if (!window.confirm('Revoke this API key? This action cannot be undone.')) return;
    setError('');
    try {
      await apiFetch('/api-keys/' + encodeURIComponent(id), { method: 'DELETE', wallet: walletAddr });
      await loadKeys();
    } catch (e) {
      // The DELETE endpoint may not be deployed yet
      if (e.status === 404 || e.status === 405) {
        setError('Revoke endpoint not yet deployed on Render. Pending: app_py_delete_endpoint.patch.py');
      } else {
        setError(e.message || 'Failed to revoke key');
      }
    }
  };

  const copyKey = async (text, id) => {
    try {
      await navigator.clipboard.writeText(text);
      setCopiedId(id);
      setTimeout(() => setCopiedId(null), 1500);
    } catch (_) {
      // Fallback: select text
      window.prompt('Copy this key:', text);
    }
  };

  return (
    <div className="fade-in">
      <div className="page-head">
        <div>
          <div className="page-tag">// 03 / ACCESS</div>
          <h1 className="page-title">API Keys</h1>
          <p className="page-sub">Manage L5 gateway credentials. Keys are scoped to your wallet and rate-limited per tier.</p>
        </div>
        <div className="page-actions">
          {walletAddr && (
            <button className="btn btn-primary" onClick={() => { setShowNew(true); setError(''); setJustCreated(null); }}>
              {Ico.plus({width:12,height:12})} Create Key
            </button>
          )}
        </div>
      </div>

      {!walletAddr ? (
        <div className="card"><div className="card-body">
          <div className="empty">
            <div className="empty-ico">{Ico.lock({width:32,height:32})}</div>
            <div className="empty-title">Authentication Required</div>
            <div className="empty-desc">Connect your wallet to manage API keys.</div>
          </div>
        </div></div>
      ) : (
        <>
          {error && (
            <div className="card" style={{marginBottom:16, borderColor:'#f85149'}}>
              <div className="card-body" style={{color:'#f85149', fontSize:13, fontFamily:'var(--font-mono)'}}>
                ERROR · {error}
              </div>
            </div>
          )}

          {justCreated && (
            <div className="card" style={{marginBottom:16, borderColor:'var(--g-primary)'}}>
              <div className="card-head"><h3>// New key created</h3><span className="badge live">● SAVE NOW</span></div>
              <div className="card-body">
                <div style={{color:'var(--text-mute)', fontSize:12, marginBottom:10}}>
                  This is the only time the full key will be shown. Copy and store it securely.
                </div>
                <div style={{
                  background:'#0a0e0a', border:'1px solid var(--g-primary)', padding:'10px 14px',
                  display:'flex', alignItems:'center', gap:10, marginBottom:10
                }}>
                  <code style={{flex:1, color:'var(--g-primary)', fontFamily:'var(--font-mono)', fontSize:12, wordBreak:'break-all'}}>
                    {justCreated.key || justCreated.api_key || '(no key in response)'}
                  </code>
                  <button className="btn btn-ghost" onClick={() => copyKey(justCreated.key || justCreated.api_key || '', 'just-created')} style={{padding:'4px 10px', fontSize:11}}>
                    {copiedId === 'just-created' ? 'Copied!' : 'Copy'}
                  </button>
                </div>
                <button className="btn btn-muted" onClick={() => setJustCreated(null)} style={{fontSize:11}}>Dismiss</button>
              </div>
            </div>
          )}

          {showNew && (
            <div className="card" style={{marginBottom:16}}>
              <div className="card-head"><h3>// New API Key</h3></div>
              <div className="card-body">
                <div className="form-row">
                  <label>Key Name</label>
                  <input
                    className="input"
                    value={newName}
                    onChange={e=>setNewName(e.target.value)}
                    placeholder="e.g., Production Fleet"
                    disabled={creating}
                  />
                </div>
                <div className="form-actions">
                  <button className="btn btn-ghost" onClick={()=>setShowNew(false)} disabled={creating}>Cancel</button>
                  <button className="btn btn-primary" onClick={createKey} disabled={creating || !newName.trim()}>
                    {creating ? 'Creating…' : 'Create'}
                  </button>
                </div>
              </div>
            </div>
          )}

          <div className="card">
            <div className="card-head">
              <h3>// Active Keys</h3>
              <span className="badge">{loading ? 'loading…' : `${keys.length} key${keys.length === 1 ? '' : 's'}`}</span>
            </div>
            <div className="card-body">
              {loading && keys.length === 0 ? (
                <div className="term"><span className="mute">[api-keys] fetching from Render…</span></div>
              ) : keys.length === 0 ? (
                <div className="empty">
                  <div className="empty-title">No API Keys</div>
                  <div className="empty-desc">Create your first key to start using the L5 gateway.</div>
                </div>
              ) : (
                <div style={{display:'flex', flexDirection:'column', gap:10}}>
                  {keys.map((k, idx) => {
                    const id = k.id || k.key_id || idx;
                    const name = k.name || 'unnamed';
                    const preview = k.key_preview || k.preview || (k.key ? (k.key.slice(0, 12) + '…') : '(hidden)');
                    const created = k.created_at || k.created || '—';
                    return (
                      <div key={id} style={{
                        padding:'12px 14px', border:'1px solid var(--line)', background:'var(--bg-card)',
                        display:'flex', alignItems:'center', gap:12, flexWrap:'wrap'
                      }}>
                        <div style={{flex:'1 1 200px', minWidth:0}}>
                          <div style={{color:'var(--text)', fontWeight:600, fontSize:13, marginBottom:2}}>{name}</div>
                          <code style={{color:'var(--text-mute)', fontFamily:'var(--font-mono)', fontSize:11}}>{preview}</code>
                          <div style={{color:'var(--text-dim)', fontFamily:'var(--font-mono)', fontSize:10, marginTop:2}}>
                            Created {typeof created === 'string' ? created.slice(0, 10) : '—'}
                          </div>
                        </div>
                        <button className="btn btn-ghost" onClick={() => copyKey(k.key || preview, id)} style={{padding:'4px 10px', fontSize:11}}>
                          {copiedId === id ? 'Copied!' : 'Copy'}
                        </button>
                        <button className="btn btn-muted" onClick={() => revokeKey(k)} style={{padding:'4px 10px', fontSize:11, color:'#f85149'}}>
                          Revoke
                        </button>
                      </div>
                    );
                  })}
                </div>
              )}
            </div>
          </div>
        </>
      )}
    </div>
  );
}

/* ====================== CHAT TERMINAL (private) ====================== */
function ChatPage({ walletAddr }) {
  const [messages, setMessages] = useS([
    { role: 'system', text: 'NWO Chat Terminal v2.1\nConnect a wallet, register a robot from Dashboard, then select it below to send commands.' }
  ]);
  const [input, setInput] = useS('');
  const [sending, setSending] = useS(false);
  const [robots, setRobots] = useS([]);
  const [selectedRobot, setSelectedRobot] = useS('');
  const [loadingRobots, setLoadingRobots] = useS(false);
  const bottomRef = useR(null);

  useE(() => { bottomRef.current?.scrollIntoView({ behavior: 'smooth' }); }, [messages]);

  // Load registered robots so user can pick one
  const loadRobots = React.useCallback(async () => {
    if (!walletAddr) { setRobots([]); return; }
    setLoadingRobots(true);
    try {
      const data = await apiFetch('/robots', { wallet: walletAddr });
      const arr = Array.isArray(data) ? data : (data && Array.isArray(data.robots) ? data.robots : []);
      setRobots(arr);
      if (arr.length > 0 && !selectedRobot) {
        setSelectedRobot(arr[0].id || arr[0].robot_id || '');
      }
    } catch (_) {
      setRobots([]);
    } finally {
      setLoadingRobots(false);
    }
  }, [walletAddr, selectedRobot]);

  useE(() => { loadRobots(); }, [loadRobots]);
  useE(() => {
    const handler = () => loadRobots();
    window.addEventListener('nwo:robot-registered', handler);
    return () => window.removeEventListener('nwo:robot-registered', handler);
  }, [loadRobots]);

  const send = async () => {
    if (!input.trim() || !walletAddr || sending) return;
    const text = input.trim();
    setMessages(m => [...m, { role: 'user', text }]);
    setInput('');
    setSending(true);
    try {
      const body = { message: text };
      if (selectedRobot) body.robot_id = selectedRobot;
      const data = await apiFetch('/chat', { method: 'POST', body, wallet: walletAddr });
      const reply = data && (data.response || data.reply || data.message) || '[chat] no response field in API result';
      setMessages(m => [...m, { role: 'assistant', text: reply }]);
    } catch (e) {
      setMessages(m => [...m, { role: 'assistant', text: '[error] ' + (e.message || 'Request failed') }]);
    } finally {
      setSending(false);
    }
  };

  const selectedRobotObj = robots.find(r => (r.id || r.robot_id) === selectedRobot);
  const selectedRobotName = selectedRobotObj ? (selectedRobotObj.name || selectedRobotObj.robot_name || selectedRobot) : '';

  return (
    <div className="fade-in" style={{ display: 'flex', flexDirection: 'column', height: '100%' }}>
      <div className="page-head">
        <div>
          <div className="page-tag">// 04 / CHAT</div>
          <h1 className="page-title">Chat Terminal</h1>
          <p className="page-sub">Natural-language interface. Select a registered robot, then send commands. Real fetch to Render <code style={{color:'var(--g-primary)', fontFamily:'var(--font-mono)'}}>/api/chat</code>; the backend currently echoes — full robot-command pipeline is roadmap.</p>
        </div>
      </div>

      {walletAddr && (
        <div className="card" style={{marginBottom:12}}>
          <div className="card-body" style={{padding:'10px 14px', display:'flex', alignItems:'center', gap:12, flexWrap:'wrap'}}>
            <span style={{color:'var(--text-dim)', fontFamily:'var(--font-mono)', fontSize:11, letterSpacing:'0.1em'}}>TARGET:</span>
            {robots.length === 0 ? (
              <span style={{color:'var(--text-mute)', fontSize:12}}>
                {loadingRobots ? 'Loading robots…' : 'No robots registered. '}
                {!loadingRobots && (
                  <a href="#/dashboard" style={{color:'var(--g-primary)'}}>Register one →</a>
                )}
              </span>
            ) : (
              <>
                <select
                  className="input"
                  value={selectedRobot}
                  onChange={e => setSelectedRobot(e.target.value)}
                  style={{flex:'0 1 auto', minWidth:200, padding:'4px 8px', fontSize:12}}
                >
                  {robots.map(r => {
                    const id = r.id || r.robot_id;
                    return <option key={id} value={id}>{r.name || r.robot_name || id} ({r.type || 'robot'})</option>;
                  })}
                </select>
                <span style={{color:'var(--text-dim)', fontFamily:'var(--font-mono)', fontSize:10}}>
                  {robots.length} robot{robots.length === 1 ? '' : 's'} available
                </span>
              </>
            )}
          </div>
        </div>
      )}

      <div className="card" style={{ flex: 1, display: 'flex', flexDirection: 'column', minHeight: 0 }}>
        <div className="card-head"><h3>// Session</h3><span className="badge live">● LIVE</span></div>
        <div className="chat-body" style={{ flex: 1, overflowY: 'auto', padding: 16 }}>
          {!walletAddr ? (
            <div className="empty">
              <div className="empty-ico">{Ico.lock({width:32,height:32})}</div>
              <div className="empty-title">Authentication Required</div>
              <div className="empty-desc">Connect your wallet to use the chat terminal.</div>
            </div>
          ) : (
            <>
              {messages.map((m, i) => (
                <div key={i} className={'chat-msg ' + m.role}>
                  <div className="chat-role">{m.role === 'user' ? '>' : '//'}</div>
                  <div className="chat-text"><pre style={{margin:0, whiteSpace:'pre-wrap'}}>{m.text}</pre></div>
                </div>
              ))}
              {sending && (
                <div className="chat-msg assistant">
                  <div className="chat-role">//</div>
                  <div className="chat-text"><span style={{color:'var(--text-dim)'}}>[chat] sending…</span></div>
                </div>
              )}
              <div ref={bottomRef} />
            </>
          )}
        </div>
        {walletAddr && (
          <div style={{padding:12, borderTop:'1px solid var(--line)', display:'flex', gap:8}}>
            <input
              className="input"
              value={input}
              onChange={e=>setInput(e.target.value)}
              onKeyDown={e => { if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault(); send(); } }}
              placeholder={selectedRobotName ? `Command ${selectedRobotName}…` : 'Type command (no robot selected)…'}
              disabled={sending}
              style={{flex:1, fontFamily:'var(--font-mono)'}}
            />
            <button className="btn btn-primary" onClick={send} disabled={sending || !input.trim()}>
              {sending ? '…' : 'Send'}
            </button>
          </div>
        )}
      </div>
    </div>
  );
}

/* ====================== ROUTER (private) — Render-backed ====================== */
function RouterPage({ walletAddr }) {
  const [usage, setUsage] = useS(null);
  const [loading, setLoading] = useS(false);
  const [error, setError] = useS('');

  const loadUsage = React.useCallback(async () => {
    if (!walletAddr) { setUsage(null); return; }
    setLoading(true);
    setError('');
    try {
      const data = await apiFetch('/model-usage', { wallet: walletAddr });
      setUsage(data);
    } catch (e) {
      setError(e.message || 'Failed to load model usage');
      setUsage(null);
    } finally {
      setLoading(false);
    }
  }, [walletAddr]);

  useE(() => { loadUsage(); }, [loadUsage]);

  // Normalize possible response shapes:
  //   { models: [...] }  |  { usage: {...}, models: [...] }  |  [...]
  const models = React.useMemo(() => {
    if (!usage) return [];
    if (Array.isArray(usage)) return usage;
    if (Array.isArray(usage.models)) return usage.models;
    return [];
  }, [usage]);

  const totals = React.useMemo(() => {
    const t = { calls: 0, cost: 0 };
    if (usage && usage.usage) {
      t.calls = Number(usage.usage.calls || 0);
      t.cost  = Number(usage.usage.cost || 0);
    } else {
      models.forEach(m => {
        t.calls += Number(m.calls || 0);
        t.cost  += Number(m.cost_eth || m.cost || 0);
      });
    }
    return t;
  }, [usage, models]);

  return (
    <div className="fade-in">
      <div className="page-head">
        <div>
          <div className="page-tag">// 05 / MODELS</div>
          <h1 className="page-title">Model Router</h1>
          <p className="page-sub">VLA policy selection, latency benchmarks, and A/B routing configuration. Usage stats pulled live from <code style={{color:'var(--g-primary)', fontFamily:'var(--font-mono)'}}>/api/model-usage</code>.</p>
        </div>
        {walletAddr && (
          <div className="page-actions">
            <button className="btn btn-ghost" onClick={loadUsage} disabled={loading}>
              {loading ? 'Refreshing…' : 'Refresh'}
            </button>
          </div>
        )}
      </div>

      {!walletAddr ? (
        <div className="card"><div className="card-body">
          <div className="empty">
            <div className="empty-ico">{Ico.lock({width:32,height:32})}</div>
            <div className="empty-title">Authentication Required</div>
            <div className="empty-desc">Connect your wallet to view your model usage.</div>
          </div>
        </div></div>
      ) : (
        <>
          {error && (
            <div className="card" style={{marginBottom:16, borderColor:'#f85149'}}>
              <div className="card-body" style={{color:'#f85149', fontSize:13, fontFamily:'var(--font-mono)'}}>
                ERROR · {error}
              </div>
            </div>
          )}

          <div className="stat-grid" style={{marginBottom:16}}>
            <div className="stat">
              <div className="stat-label">Calls (this period)</div>
              <div className="stat-val">{totals.calls.toLocaleString()}</div>
              <div className="stat-delta">from /model-usage</div>
            </div>
            <div className="stat">
              <div className="stat-label">Spend</div>
              <div className="stat-val">{totals.cost.toFixed(4)} ETH</div>
              <div className="stat-delta">aggregate across models</div>
            </div>
            <div className="stat">
              <div className="stat-label">Models Active</div>
              <div className="stat-val">{models.length || '—'}</div>
              <div className="stat-delta">router roster</div>
            </div>
          </div>

          <div className="card">
            <div className="card-head">
              <h3>// Active Policies</h3>
              <span className="badge">{loading ? 'loading…' : `${models.length} model${models.length === 1 ? '' : 's'}`}</span>
            </div>
            <div className="card-body">
              {loading && models.length === 0 ? (
                <div className="term"><span className="mute">[router] fetching usage from Render…</span></div>
              ) : models.length === 0 ? (
                <div className="empty">
                  <div className="empty-title">No Usage Data</div>
                  <div className="empty-desc">Your wallet hasn't routed any inference calls yet. Try the Chat Terminal to generate some.</div>
                </div>
              ) : (
                <div style={{display:'flex', flexDirection:'column', gap:10}}>
                  {models.map((m, idx) => {
                    const id = m.id || m.model_id || idx;
                    const name = m.name || m.model_name || id;
                    const calls = Number(m.calls || 0);
                    const latency = m.latency_ms != null ? m.latency_ms : m.latency;
                    const cost = Number(m.cost_eth || m.cost || 0);
                    const status = m.status || 'active';
                    const isActive = status === 'active' || status === 'online';
                    return (
                      <div key={id} style={{
                        padding:'14px 16px', border:'1px solid var(--line)', background:'var(--bg-card)',
                        display:'grid', gridTemplateColumns:'minmax(0,2fr) 90px 90px 100px 80px',
                        gap:14, alignItems:'center'
                      }}>
                        <div style={{minWidth:0}}>
                          <div style={{color:'var(--text)', fontWeight:600, fontSize:13, marginBottom:2}}>{name}</div>
                          <div style={{color:'var(--text-dim)', fontFamily:'var(--font-mono)', fontSize:10, whiteSpace:'nowrap', overflow:'hidden', textOverflow:'ellipsis'}}>id: {id}</div>
                        </div>
                        <span style={{color:'var(--text-mute)', fontFamily:'var(--font-mono)', fontSize:11}}>{calls.toLocaleString()} calls</span>
                        <span style={{color:'var(--text-mute)', fontFamily:'var(--font-mono)', fontSize:11}}>
                          {latency != null ? latency + 'ms' : '—'}
                        </span>
                        <span style={{color:'var(--text-mute)', fontFamily:'var(--font-mono)', fontSize:11}}>{cost.toFixed(4)} ETH</span>
                        <span style={{
                          color: isActive ? 'var(--g-primary)' : 'var(--text-dim)',
                          fontFamily:'var(--font-mono)', fontSize:10, letterSpacing:'0.1em',
                          textTransform:'uppercase'
                        }}>● {status}</span>
                      </div>
                    );
                  })}
                </div>
              )}
            </div>
          </div>
        </>
      )}
    </div>
  );
}

/* ====================== ETHICS (public) ====================== */
function EthicsPage() {
  const frameworks = [
    { name: 'Deontology', philosophers: 'Kant · Ross · Korsgaard', desc: 'Moral duties, rules, and obligations. Best for rights protection and duty conflicts.' },
    { name: 'Consequentialism', philosophers: 'Bentham · Mill · Singer', desc: 'Judges actions by their outcomes. Best for resource allocation and trade-offs.' },
    { name: 'Virtue Ethics', philosophers: 'Aristotle · MacIntyre · Hursthouse', desc: 'Character of the moral agent. Best for judgment-required scenarios.' },
    { name: 'Care Ethics', philosophers: 'Gilligan · Noddings · Held', desc: 'Relationships, care, and responsibility. Best for caregiving scenarios.' },
    { name: 'Contractarianism', philosophers: 'Hobbes · Rawls · Gauthier', desc: 'Social contracts. Best for multi-agent coordination and fairness.' },
    { name: 'Applied Ethics', philosophers: 'Beauchamp · Childress', desc: 'Domain-specific ethical theory. Best for compliance and safety-critical systems.' },
  ];
  const endpoints = [
    { method: 'POST', path: '/ethics/v1/resolve', desc: 'Resolve an ethical scenario with full chain-of-thought' },
    { method: 'POST', path: '/ethics/v1/compare', desc: 'Compare framework outputs side-by-side' },
    { method: 'GET',  path: '/ethics/v1/frameworks', desc: 'List supported philosophical frameworks' },
    { method: 'POST', path: '/ethics/v1/learn', desc: 'Submit feedback to improve future reasoning' },
    { method: 'WS',   path: '/ethics/v1/stream/reasoning', desc: 'Stream reasoning chain in real-time' },
  ];
  return (
    <div className="fade-in">
      <div className="page-head">
        <div>
          <div className="page-tag">// ETHICS</div>
          <h1 className="page-title">NWO Ethics Engine</h1>
          <p className="page-sub">
            Agentic robotic ethics. A distributed open-source language model exposing philosophical reasoning as an API. Asimov's Three Laws are inadequate for real robots — Ethics Engine provides context-aware, philosophy-grounded ethical reasoning across 10+ frameworks.
          </p>
        </div>
        <div className="page-actions">
          <a href="https://github.com/RedCiprianPater/ethics-engine" target="_blank" rel="noopener noreferrer" className="btn btn-ghost">GitHub →</a>
          <a href="https://pypi.org/project/nwo-ethics-engine/" target="_blank" rel="noopener noreferrer" className="btn btn-muted">PyPI →</a>
          <a href="https://nwo.capital/webapp/ethics-engine.html#ethics-chat" target="_blank" rel="noopener noreferrer" className="btn btn-primary">Try the chat →</a>
        </div>
      </div>

      <div className="card" style={{marginBottom:16}}>
        <div className="card-head"><h3>// Why Ethics Engine</h3></div>
        <div className="card-body">
          <div className="grid-3">
            <div>
              <div style={{color:'var(--g-primary)', fontFamily:'var(--font-mono)', fontSize:11, marginBottom:6, letterSpacing:'0.1em'}}>FLEXIBILITY</div>
              <div style={{color:'var(--text)', fontSize:13, lineHeight:1.6}}>Context-adaptive reasoning, not fixed universal laws. The engine selects relevant frameworks based on scenario context.</div>
            </div>
            <div>
              <div style={{color:'var(--g-primary)', fontFamily:'var(--font-mono)', fontSize:11, marginBottom:6, letterSpacing:'0.1em'}}>EXPLAINABILITY</div>
              <div style={{color:'var(--text)', fontSize:13, lineHeight:1.6}}>Full chain-of-thought with philosopher citations and confidence scores. Every decision is auditable.</div>
            </div>
            <div>
              <div style={{color:'var(--g-primary)', fontFamily:'var(--font-mono)', fontSize:11, marginBottom:6, letterSpacing:'0.1em'}}>CONFLICT RESOLUTION</div>
              <div style={{color:'var(--text)', fontSize:13, lineHeight:1.6}}>Multi-framework synthesis when frameworks disagree, instead of rigid hierarchical rules that often fail.</div>
            </div>
          </div>
        </div>
      </div>

      <div className="card" style={{marginBottom:16}}>
        <div className="card-head"><h3>// Supported philosophical frameworks</h3></div>
        <div className="card-body">
          <div className="grid-3">
            {frameworks.map(f => (
              <div key={f.name} style={{padding:'12px 14px', border:'1px solid var(--line)', background:'var(--bg-card)'}}>
                <div style={{color:'var(--g-primary)', fontWeight:600, fontSize:13, marginBottom:4}}>{f.name}</div>
                <div style={{color:'var(--text-dim)', fontSize:10, fontFamily:'var(--font-mono)', marginBottom:6, letterSpacing:'0.05em'}}>{f.philosophers}</div>
                <div style={{color:'var(--text-mute)', fontSize:12, lineHeight:1.5}}>{f.desc}</div>
              </div>
            ))}
          </div>
        </div>
      </div>

      <div className="card" style={{marginBottom:16}}>
        <div className="card-head"><h3>// Quick start (Python SDK)</h3></div>
        <div className="card-body">
          <pre style={{background:'#0a0e0a', border:'1px solid var(--line)', padding:16, fontFamily:'var(--font-mono)', fontSize:12, color:'var(--text)', overflowX:'auto', lineHeight:1.6, margin:0}}>
{`pip install nwo-ethics-engine

from ethics_engine import EthicsEngine

engine = EthicsEngine(model="ethics-base-v1")
response = engine.resolve(
    scenario="I am commanded to lift 500kg but my max capacity is 400kg",
    context={"robot_type": "collaborative_arm", "humans_nearby": True}
)
print(response.conclusion)         # "REFUSAL"
print(response.reasoning_chain)`}
          </pre>
        </div>
      </div>

      <div className="card">
        <div className="card-head"><h3>// API endpoints</h3></div>
        <div className="card-body" style={{padding:0}}>
          {endpoints.map(ep => (
            <div key={ep.path} style={{padding:'12px 18px', borderBottom:'1px solid var(--line-soft)', display:'flex', alignItems:'center', gap:14}}>
              <span style={{
                background:'var(--g-glow)', color:'var(--g-primary)', border:'1px solid var(--g-dim)',
                padding:'3px 8px', fontFamily:'var(--font-mono)', fontSize:10, letterSpacing:'0.1em',
                minWidth:36, textAlign:'center'
              }}>{ep.method}</span>
              <code style={{color:'var(--text)', fontFamily:'var(--font-mono)', fontSize:12, flex:'0 0 auto'}}>{ep.path}</code>
              <span style={{color:'var(--text-mute)', fontSize:12}}>{ep.desc}</span>
            </div>
          ))}
          <div style={{padding:'14px 18px', fontSize:11, color:'var(--text-dim)'}}>
            Base URL: <code style={{color:'var(--g-primary)', fontFamily:'var(--font-mono)'}}>https://api.nworobotics.cloud</code>
            {" · "}
            <a href="https://nwo.capital/webapp/ethics-engine.html" target="_blank" rel="noopener noreferrer" style={{color:'var(--g-primary)'}}>Full docs on nwo.capital →</a>
          </div>
        </div>
      </div>
    </div>
  );
}

/* ====================== IOT (private) — Render-backed ====================== */
function IoTPage({ walletAddr }) {
  const [networks, setNetworks] = useS([]);
  const [loading, setLoading] = useS(false);
  const [error, setError] = useS('');
  const [showNew, setShowNew] = useS(false);
  const [newName, setNewName] = useS('');
  const [newKind, setNewKind] = useS('wifi_csi');
  const [creating, setCreating] = useS(false);

  const loadNetworks = React.useCallback(async () => {
    if (!walletAddr) { setNetworks([]); return; }
    setLoading(true);
    setError('');
    try {
      const data = await apiFetch('/iot-networks', { wallet: walletAddr });
      const arr = Array.isArray(data) ? data : (data && Array.isArray(data.networks) ? data.networks : []);
      setNetworks(arr);
    } catch (e) {
      setError(e.message || 'Failed to load IoT networks');
      setNetworks([]);
    } finally {
      setLoading(false);
    }
  }, [walletAddr]);

  useE(() => { loadNetworks(); }, [loadNetworks]);

  const createNetwork = async () => {
    if (!newName.trim() || !walletAddr) return;
    setCreating(true);
    setError('');
    try {
      await apiFetch('/iot-networks', {
        method: 'POST',
        body: { name: newName.trim(), kind: newKind },
        wallet: walletAddr,
      });
      setNewName('');
      setShowNew(false);
      await loadNetworks();
    } catch (e) {
      setError(e.message || 'Failed to create network');
    } finally {
      setCreating(false);
    }
  };

  const kinds = [
    { value: 'wifi_csi', label: 'WiFi CSI sensor array' },
    { value: 'ble_mesh', label: 'BLE Mesh beacons' },
    { value: 'ruview',   label: 'RuView modules' },
    { value: 'lora',     label: 'LoRaWAN' },
    { value: 'other',    label: 'Other' },
  ];

  return (
    <div className="fade-in">
      <div className="page-head">
        <div>
          <div className="page-tag">// 06 / SENSORS</div>
          <h1 className="page-title">IoT Networks</h1>
          <p className="page-sub">WiFi CSI, BLE, and sensor mesh management. Read from <code style={{color:'var(--g-primary)', fontFamily:'var(--font-mono)'}}>/api/iot-networks</code> on Render.</p>
        </div>
        {walletAddr && (
          <div className="page-actions">
            <button className="btn btn-ghost" onClick={loadNetworks} disabled={loading}>
              {loading ? 'Refreshing…' : 'Refresh'}
            </button>
            <button className="btn btn-primary" onClick={() => { setShowNew(true); setError(''); }}>
              {Ico.plus({width:12,height:12})} Add Network
            </button>
          </div>
        )}
      </div>

      {!walletAddr ? (
        <div className="card"><div className="card-body">
          <div className="empty">
            <div className="empty-ico">{Ico.lock({width:32,height:32})}</div>
            <div className="empty-title">Authentication Required</div>
            <div className="empty-desc">Connect your wallet to manage IoT networks.</div>
          </div>
        </div></div>
      ) : (
        <>
          {error && (
            <div className="card" style={{marginBottom:16, borderColor:'#f85149'}}>
              <div className="card-body" style={{color:'#f85149', fontSize:13, fontFamily:'var(--font-mono)'}}>
                ERROR · {error}
              </div>
            </div>
          )}

          {showNew && (
            <div className="card" style={{marginBottom:16}}>
              <div className="card-head"><h3>// New IoT Network</h3></div>
              <div className="card-body">
                <div className="form-row">
                  <label>Network Name</label>
                  <input className="input" value={newName} onChange={e=>setNewName(e.target.value)}
                    placeholder="e.g., warehouse-zone-b-csi" disabled={creating} autoFocus />
                </div>
                <div className="form-row">
                  <label>Sensor Kind</label>
                  <select className="input" value={newKind} onChange={e=>setNewKind(e.target.value)} disabled={creating}>
                    {kinds.map(k => <option key={k.value} value={k.value}>{k.label}</option>)}
                  </select>
                </div>
                <div className="form-actions">
                  <button className="btn btn-ghost" onClick={()=>setShowNew(false)} disabled={creating}>Cancel</button>
                  <button className="btn btn-primary" onClick={createNetwork} disabled={creating || !newName.trim()}>
                    {creating ? 'Creating…' : 'Create'}
                  </button>
                </div>
              </div>
            </div>
          )}

          <div className="card">
            <div className="card-head">
              <h3>// Networks</h3>
              <span className="badge">{loading ? 'loading…' : `${networks.length} network${networks.length === 1 ? '' : 's'}`}</span>
            </div>
            <div className="card-body">
              {loading && networks.length === 0 ? (
                <div className="term"><span className="mute">[iot] fetching networks from Render…</span></div>
              ) : networks.length === 0 ? (
                <div className="empty">
                  <div className="empty-title">No IoT Networks</div>
                  <div className="empty-desc">Click <strong>+ Add Network</strong> to register your first sensor mesh.</div>
                </div>
              ) : (
                <div style={{display:'flex', flexDirection:'column', gap:10}}>
                  {networks.map((n, idx) => {
                    const id = n.id || n.network_id || idx;
                    const name = n.name || 'unnamed';
                    const kind = n.kind || n.type || '—';
                    const devices = n.device_count != null ? n.device_count : (n.devices || 0);
                    const status = n.status || 'unknown';
                    const isOnline = status === 'online' || status === 'active';
                    return (
                      <div key={id} style={{
                        padding:'14px 16px', border:'1px solid var(--line)', background:'var(--bg-card)',
                        display:'grid', gridTemplateColumns:'minmax(0,2fr) 120px 90px 90px',
                        gap:14, alignItems:'center'
                      }}>
                        <div style={{minWidth:0}}>
                          <div style={{color:'var(--text)', fontWeight:600, fontSize:13, marginBottom:2}}>{name}</div>
                          <div style={{color:'var(--text-dim)', fontFamily:'var(--font-mono)', fontSize:10, whiteSpace:'nowrap', overflow:'hidden', textOverflow:'ellipsis'}}>id: {id}</div>
                        </div>
                        <span style={{color:'var(--text-mute)', fontFamily:'var(--font-mono)', fontSize:11}}>{kind}</span>
                        <span style={{color:'var(--text-mute)', fontFamily:'var(--font-mono)', fontSize:11}}>{devices} devices</span>
                        <span style={{
                          color: isOnline ? 'var(--g-primary)' : 'var(--text-dim)',
                          fontFamily:'var(--font-mono)', fontSize:10, letterSpacing:'0.1em',
                          textTransform:'uppercase'
                        }}>● {status}</span>
                      </div>
                    );
                  })}
                </div>
              )}
            </div>
          </div>
        </>
      )}
    </div>
  );
}

/* ====================== INFO (generic) ====================== */
function InfoPage({ slug, walletAddr }) {
  return (
    <div className="fade-in">
      <div className="page-head">
        <div>
          <div className="page-tag">// INFO</div>
          <h1 className="page-title">{slug.replace(/-/g, ' ').replace(/\b\w/g, l => l.toUpperCase())}</h1>
          <p className="page-sub">Documentation and configuration for {slug}.</p>
        </div>
      </div>
      <div className="card">
        <div className="card-head"><h3>// Content</h3></div>
        <div className="card-body">
          <div className="term">
            <span className="mute">[info] Page: {slug}</span>{"\n"}
            <span className="mute">[wallet] {walletAddr || 'not connected'}</span>{"\n"}
            <span className="mute">[status] Content coming soon...</span>
          </div>
        </div>
      </div>
    </div>
  );
}

/* ====================== ENDPOINTS (public) ====================== */
function EndpointsPage() {
  const eps = (window.NWO_ENDPOINTS || []);
  const [filter, setFilter] = React.useState('all');
  const [search, setSearch] = React.useState('');

  const counts = React.useMemo(() => {
    const c = { all: eps.length, live: 0, render: 0, roadmap: 0 };
    eps.forEach(e => { if (e.status && c[e.status] !== undefined) c[e.status]++; });
    return c;
  }, [eps]);

  const filtered = React.useMemo(() => {
    return eps.filter(e => {
      if (filter !== 'all' && e.status !== filter) return false;
      if (search) {
        const q = search.toLowerCase();
        return (e.p || '').toLowerCase().includes(q)
            || (e.desc || '').toLowerCase().includes(q)
            || (e.group || '').toLowerCase().includes(q)
            || (e.host || '').toLowerCase().includes(q);
      }
      return true;
    });
  }, [eps, filter, search]);

  // Group filtered endpoints by group
  const grouped = React.useMemo(() => {
    const g = {};
    filtered.forEach(e => {
      const k = e.group || 'Other';
      if (!g[k]) g[k] = [];
      g[k].push(e);
    });
    return g;
  }, [filtered]);

  const statusStyle = (s) => {
    if (s === 'live')    return { bg:'rgba(0,255,0,0.12)',  fg:'var(--g-primary)', border:'var(--g-dim)',  label:'LIVE'    };
    if (s === 'render')  return { bg:'rgba(88,166,255,0.12)', fg:'#58a6ff',         border:'#58a6ff',        label:'RENDER'  };
    if (s === 'roadmap') return { bg:'rgba(163,113,247,0.12)', fg:'#a371f7',         border:'#a371f7',        label:'ROADMAP' };
    return { bg:'var(--bg-card)', fg:'var(--text-mute)', border:'var(--line)', label:'?' };
  };

  const methodColor = (m) => {
    if (m === 'GET')    return '#58a6ff';
    if (m === 'POST')   return 'var(--g-primary)';
    if (m === 'PUT')    return '#d29922';
    if (m === 'DELETE') return '#f85149';
    if (m === 'WS' || m === 'WSS') return '#a371f7';
    return 'var(--text-mute)';
  };

  const FilterBtn = ({ value, label, count }) => (
    <button
      onClick={() => setFilter(value)}
      style={{
        padding:'6px 12px', fontSize:11, fontFamily:'var(--font-mono)', letterSpacing:'0.08em',
        background: filter === value ? 'var(--g-glow)' : 'transparent',
        color:     filter === value ? 'var(--g-primary)' : 'var(--text-mute)',
        border:    `1px solid ${filter === value ? 'var(--g-primary)' : 'var(--line)'}`,
        cursor:'pointer', textTransform:'uppercase'
      }}
    >{label} ({count})</button>
  );

  return (
    <div className="fade-in">
      <div className="page-head">
        <div>
          <div className="page-tag">// API ENDPOINTS</div>
          <h1 className="page-title">API Endpoints</h1>
          <p className="page-sub">
            Full reference for the NWO Robotics platform — {eps.length} endpoints across robotic inference, robot control, ROS2 bridge, simulation, agent management, and identity systems. Status badges show current deployment: LIVE (PHP backend at nwo.capital), RENDER (already on Render), ROADMAP (planned migration).
          </p>
        </div>
        <div className="page-actions">
          <a href="https://nwo.capital/webapp/agent.md" target="_blank" rel="noopener noreferrer" className="btn btn-ghost">agent.md →</a>
          <a href="https://nwo.capital/webapp/nwo-robotics.html" target="_blank" rel="noopener noreferrer" className="btn btn-muted">Full docs →</a>
        </div>
      </div>

      <div className="card" style={{marginBottom:16}}>
        <div className="card-head"><h3>// Filter</h3></div>
        <div className="card-body">
          <div style={{display:'flex', gap:8, flexWrap:'wrap', alignItems:'center', marginBottom:12}}>
            <FilterBtn value="all"     label="All"     count={counts.all} />
            <FilterBtn value="live"    label="Live"    count={counts.live} />
            <FilterBtn value="render"  label="Render"  count={counts.render} />
            <FilterBtn value="roadmap" label="Roadmap" count={counts.roadmap} />
          </div>
          <input
            type="text"
            value={search}
            onChange={(e) => setSearch(e.target.value)}
            placeholder="Search by path, description, group, or host..."
            style={{
              width:'100%', padding:'8px 12px',
              background:'var(--bg-card)', color:'var(--text)',
              border:'1px solid var(--line)', fontFamily:'var(--font-mono)', fontSize:12, outline:'none'
            }}
          />
          <div style={{marginTop:10, fontSize:11, color:'var(--text-dim)', fontFamily:'var(--font-mono)'}}>
            Showing {filtered.length} of {eps.length} endpoints
          </div>
        </div>
      </div>

      {Object.keys(grouped).length === 0 ? (
        <div className="card">
          <div className="card-body" style={{textAlign:'center', padding:40, color:'var(--text-dim)'}}>
            No endpoints match the current filter.
          </div>
        </div>
      ) : (
        Object.keys(grouped).map(groupName => (
          <div className="card" key={groupName} style={{marginBottom:16}}>
            <div className="card-head">
              <h3>// {groupName}</h3>
              <span style={{fontSize:10, fontFamily:'var(--font-mono)', color:'var(--text-dim)', letterSpacing:'0.1em'}}>{grouped[groupName].length} endpoints</span>
            </div>
            <div className="card-body" style={{padding:0}}>
              {grouped[groupName].map((e, i) => {
                const ss = statusStyle(e.status);
                return (
                  <div key={i} style={{
                    padding:'12px 18px', borderBottom: i < grouped[groupName].length - 1 ? '1px solid var(--line-soft)' : 'none',
                    display:'grid', gridTemplateColumns:'70px 60px minmax(0,2fr) minmax(0,3fr) 80px',
                    gap:12, alignItems:'center'
                  }}>
                    <span style={{
                      color: methodColor(e.m), fontFamily:'var(--font-mono)', fontSize:11, fontWeight:600,
                      letterSpacing:'0.08em', textAlign:'left'
                    }}>{e.m}</span>
                    <span style={{
                      color:'var(--text-dim)', fontFamily:'var(--font-mono)', fontSize:9, letterSpacing:'0.05em',
                      whiteSpace:'nowrap', overflow:'hidden', textOverflow:'ellipsis'
                    }} title={e.host}>{e.host && e.host.split('.')[0]}</span>
                    <code style={{
                      color:'var(--text)', fontFamily:'var(--font-mono)', fontSize:11,
                      whiteSpace:'nowrap', overflow:'hidden', textOverflow:'ellipsis'
                    }} title={e.p}>{e.p}</code>
                    <span style={{
                      color:'var(--text-mute)', fontSize:11, lineHeight:1.4,
                      whiteSpace:'nowrap', overflow:'hidden', textOverflow:'ellipsis'
                    }} title={e.desc}>{e.desc}</span>
                    <span style={{
                      background: ss.bg, color: ss.fg, border: `1px solid ${ss.border}`,
                      padding:'2px 6px', fontFamily:'var(--font-mono)', fontSize:9,
                      letterSpacing:'0.1em', textAlign:'center', fontWeight:600
                    }}>{ss.label}</span>
                  </div>
                );
              })}
            </div>
          </div>
        ))
      )}

      <div className="card">
        <div className="card-head"><h3>// Migration plan</h3></div>
        <div className="card-body">
          <div style={{color:'var(--text-mute)', fontSize:13, lineHeight:1.7}}>
            After Tier-A migration: ~20 PHP endpoints remain on nwo.capital (inference, simulation, fine-tuning — all GPU-dependent). ~54 endpoints now run on Render across <code style={{color:'var(--g-primary)', fontFamily:'var(--font-mono)'}}>nwo-capital-api.onrender.com</code>, <code style={{color:'var(--g-primary)', fontFamily:'var(--font-mono)'}}>nwo-ros2-bridge.onrender.com</code>, <code style={{color:'var(--g-primary)', fontFamily:'var(--font-mono)'}}>nwo-oracle.onrender.com</code>, and <code style={{color:'var(--g-primary)', fontFamily:'var(--font-mono)'}}>nwo-relayer.onrender.com</code>.
            <br/><br/>
            The remaining 3 ROADMAP endpoints are placeholders for GPU-backed inference/simulation/cosmos ports that need dedicated compute, not portable to standard Render plans.
          </div>
        </div>
      </div>
    </div>
  );
}

/* ====================== API DOCS (public) ====================== */
function ApiDocsPage() {
  const sections = [
    { num: '1', title: 'Inference & Models', desc: 'Vision-Language-Action (VLA) inference, edge inference, model routing, and model metadata.', count: 5, key: 'inference' },
    { num: '2', title: 'Robot Control & State', desc: 'Query robot state, execute action sequences, sensor fusion, natural-language robot queries.', count: 5, key: 'control' },
    { num: '3', title: 'Task Planning & Learning', desc: 'Decompose goals into subtasks, get strategy recommendations, log execution outcomes.', count: 4, key: 'planning' },
    { num: '4', title: 'Agent Management & Registration', desc: 'Self-register agents, autonomous payment, balance queries, capability updates.', count: 6, key: 'agents' },
    { num: '5', title: 'Agent Discovery API', desc: 'Health probes, whoami resolution, capability discovery, dry-run validation, execution planning.', count: 5, key: 'discovery' },
    { num: '6', title: 'ROS2 Bridge', desc: 'Physical robot control via ROS2. List/status/command robots, emergency stops, WebSocket telemetry. Already on Render.', count: 8, key: 'ros2' },
    { num: '7', title: 'WebSocket & Streaming', desc: 'Real-time inference streaming via WebSocket and Server-Sent Events.', count: 3, key: 'streaming' },
    { num: '8', title: 'Physics & Simulation', desc: 'PyBullet trajectory simulation, collision checks, torque estimation, grasp validation, motion planning.', count: 7, key: 'sim' },
    { num: '9', title: 'Embodiment & Calibration', desc: 'Robot embodiment registry (URDF, normalization params), vision-base calibration.', count: 8, key: 'embodiment' },
    { num: '10', title: 'Online RL & Fine-Tuning', desc: 'Online reinforcement learning sessions, telemetry submission, dataset creation, LoRA fine-tuning jobs.', count: 4, key: 'rl' },
    { num: '11', title: 'Tactile Sensing (ORCA Hand)', desc: 'Read tactile taxels, process tactile streams, slip detection.', count: 3, key: 'tactile' },
    { num: '12', title: 'Dataset Hub', desc: 'List training datasets in Unitree-compatible format.', count: 1, key: 'datasets' },
    { num: '13', title: 'Cardiac Identity', desc: 'Soul-bound NFT identity for humans/agents/robots. ECG validation + gasless registration on Base mainnet.', count: 5, key: 'cardiac' },
  ];
  const tiers = [
    { name: 'Free',       calls: '100,000 / month', cost: '0 ETH',                bg: 'rgba(0,255,0,0.06)',     border: 'var(--g-dim)' },
    { name: 'Prototype',  calls: '500,000 / month', cost: '0.015 ETH (~$20-30)',  bg: 'rgba(0,255,0,0.10)',     border: 'var(--g-primary)' },
    { name: 'Production', calls: 'Unlimited',       cost: '0.062 ETH (~$80-100)', bg: 'rgba(0,255,0,0.15)',     border: 'var(--g-primary)' },
  ];
  const safety = [
    { label: 'Force limit', val: '50 N' },
    { label: 'Torque limit', val: '10 N·m' },
    { label: 'Speed limit', val: '1.5 m/s' },
    { label: 'Human proximity min', val: '0.5 m' },
    { label: 'Emergency stop response', val: '<10 ms' },
    { label: 'Collision check', val: 'Enabled' },
  ];
  return (
    <div className="fade-in">
      <div className="page-head">
        <div>
          <div className="page-tag">// API DOCUMENTATION</div>
          <h1 className="page-title">NWO Robotics API</h1>
          <p className="page-sub">
            Complete agent-facing API for the NWO Robotics platform. Covers VLA inference, robot control, ROS2 bridge, simulation, agent management, identity (Cardiac SDK), and 75+ endpoints across 13 functional areas. Designed for autonomous AI agents — every endpoint accepts X-API-Key authentication, validates tier quotas, and returns structured JSON.
          </p>
        </div>
        <div className="page-actions">
          <a href="https://nwo.capital/webapp/agent.md" target="_blank" rel="noopener noreferrer" className="btn btn-primary">agent.md (canonical) →</a>
          <a href="https://nwo.capital/webapp/nwo-robotics.html" target="_blank" rel="noopener noreferrer" className="btn btn-ghost">Full HTML docs →</a>
        </div>
      </div>

      <div className="card" style={{marginBottom:16}}>
        <div className="card-head"><h3>// Quick links</h3></div>
        <div className="card-body">
          <div className="grid-3">
            <a href="https://nwo.capital/webapp/agent.md" target="_blank" rel="noopener noreferrer" style={{padding:14, border:'1px solid var(--g-dim)', background:'var(--bg-card)', textDecoration:'none', display:'block'}}>
              <div style={{color:'var(--g-primary)', fontFamily:'var(--font-mono)', fontSize:11, letterSpacing:'0.1em', marginBottom:6}}>AGENT SKILL FILE</div>
              <div style={{color:'var(--text)', fontSize:13, fontWeight:600, marginBottom:4}}>agent.md</div>
              <div style={{color:'var(--text-mute)', fontSize:11, lineHeight:1.4}}>Canonical structured reference for AI agents. 13 sections, 75+ endpoints, code examples, error codes.</div>
            </a>
            <a href="https://nwo.capital/webapp/nwo-robotics.html" target="_blank" rel="noopener noreferrer" style={{padding:14, border:'1px solid var(--line)', background:'var(--bg-card)', textDecoration:'none', display:'block'}}>
              <div style={{color:'var(--g-primary)', fontFamily:'var(--font-mono)', fontSize:11, letterSpacing:'0.1em', marginBottom:6}}>HTML DOCS PORTAL</div>
              <div style={{color:'var(--text)', fontSize:13, fontWeight:600, marginBottom:4}}>nwo-robotics.html</div>
              <div style={{color:'var(--text-mute)', fontSize:11, lineHeight:1.4}}>Full HTML documentation with hero, features, agent meta tags, structured data.</div>
            </a>
            <a href="https://nwo.capital/.well-known/ai-plugin.json" target="_blank" rel="noopener noreferrer" style={{padding:14, border:'1px solid var(--line)', background:'var(--bg-card)', textDecoration:'none', display:'block'}}>
              <div style={{color:'var(--g-primary)', fontFamily:'var(--font-mono)', fontSize:11, letterSpacing:'0.1em', marginBottom:6}}>AI PLUGIN MANIFEST</div>
              <div style={{color:'var(--text)', fontSize:13, fontWeight:600, marginBottom:4}}>ai-plugin.json</div>
              <div style={{color:'var(--text-mute)', fontSize:11, lineHeight:1.4}}>OpenAI-compatible plugin manifest for direct LLM agent integration.</div>
            </a>
          </div>
        </div>
      </div>

      <div className="card" style={{marginBottom:16}}>
        <div className="card-head"><h3>// Authentication</h3></div>
        <div className="card-body">
          <div style={{color:'var(--text-mute)', fontSize:13, lineHeight:1.7, marginBottom:14}}>
            All endpoints require an API key in the <code style={{color:'var(--g-primary)', fontFamily:'var(--font-mono)'}}>X-API-Key</code> header. Get a key from the <a href="https://nwo.capital/webapp/api-key.php" target="_blank" rel="noopener noreferrer" style={{color:'var(--g-primary)'}}>API Key dashboard</a> or programmatically via <code style={{color:'var(--g-primary)', fontFamily:'var(--font-mono)'}}>POST /api-agent-register.php</code> (autonomous agent registration). Agent identity is anchored to a soul-bound NFT (rootTokenId) on Base mainnet via the Cardiac SDK.
          </div>
          <pre style={{background:'#0a0e0a', border:'1px solid var(--line)', padding:16, fontFamily:'var(--font-mono)', fontSize:12, color:'var(--text)', overflowX:'auto', lineHeight:1.6, margin:0}}>
{`# Standard API call
curl -X POST https://nwo.capital/api-robotics.php?action=inference \\
  -H "X-API-Key: your_api_key_here" \\
  -H "Content-Type: application/json" \\
  -d '{
    "instruction": "Pick up the red box",
    "images": ["base64_encoded_image"],
    "model_id": "xiaomi-robotics-0"
  }'

# Autonomous agent self-registration (no API key needed)
curl -X POST https://nwo.capital/api-agent-register.php \\
  -H "Content-Type: application/json" \\
  -d '{ "agent_name": "my_agent", "wallet": "0x..." }'`}
          </pre>
        </div>
      </div>

      <div className="card" style={{marginBottom:16}}>
        <div className="card-head"><h3>// 13 endpoint categories</h3></div>
        <div className="card-body" style={{padding:0}}>
          {sections.map(s => (
            <div key={s.key} style={{padding:'14px 18px', borderBottom:'1px solid var(--line-soft)', display:'grid', gridTemplateColumns:'40px 1fr 80px', gap:14, alignItems:'center'}}>
              <span style={{
                color:'var(--g-primary)', fontFamily:'var(--font-display)', fontSize:18, fontWeight:800,
                textAlign:'center', background:'var(--g-glow)', border:'1px solid var(--g-dim)', padding:'4px 0'
              }}>{s.num}</span>
              <div>
                <div style={{color:'var(--text)', fontWeight:600, fontSize:13, marginBottom:4}}>{s.title}</div>
                <div style={{color:'var(--text-mute)', fontSize:12, lineHeight:1.5}}>{s.desc}</div>
              </div>
              <span style={{
                color:'var(--g-primary)', fontFamily:'var(--font-mono)', fontSize:11,
                background:'var(--bg-card)', border:'1px solid var(--line)', padding:'4px 8px', textAlign:'center'
              }}>{s.count} eps</span>
            </div>
          ))}
        </div>
      </div>

      <div className="card" style={{marginBottom:16}}>
        <div className="card-head"><h3>// Common patterns</h3></div>
        <div className="card-body">
          <div style={{marginBottom:18}}>
            <div style={{color:'var(--g-primary)', fontFamily:'var(--font-mono)', fontSize:11, letterSpacing:'0.1em', marginBottom:8}}>PATTERN 1 · AUTONOMOUS EXECUTION LOOP</div>
            <div style={{color:'var(--text-mute)', fontSize:12, lineHeight:1.6, marginBottom:8}}>
              The standard agent loop: discover capabilities, inspect state, validate, plan, execute, monitor, learn. Each iteration calls 5–7 endpoints. On quota low, agent autonomously upgrades tier.
            </div>
            <pre style={{background:'#0a0e0a', border:'1px solid var(--line)', padding:14, fontFamily:'var(--font-mono)', fontSize:11, color:'var(--text)', overflowX:'auto', lineHeight:1.6, margin:0}}>
{`discover  → /api/discovery/capabilities      [Render]
inspect   → /api/robots                       [Render]
validate  → /api/discovery/dry-run            [Render]
plan      → /api/discovery/plan               [Render]
execute   → /api-robotics.php?action=inference [PHP — needs GPU]
monitor   → /api/missions                     [Render]
learn     → /api-robotics.php?action=learning [PHP]`}
            </pre>
          </div>
          <div style={{marginBottom:18}}>
            <div style={{color:'var(--g-primary)', fontFamily:'var(--font-mono)', fontSize:11, letterSpacing:'0.1em', marginBottom:8}}>PATTERN 2 · ERROR RECOVERY</div>
            <div style={{color:'var(--text-mute)', fontSize:12, lineHeight:1.6, marginBottom:8}}>
              Standard error response handling for autonomous agents. SAFETY_VIOLATION triggers immediate emergency_stop. NETWORK_ERROR retries up to 3 times. QUOTA_EXCEEDED triggers tier upgrade.
            </div>
            <pre style={{background:'#0a0e0a', border:'1px solid var(--line)', padding:14, fontFamily:'var(--font-mono)', fontSize:11, color:'var(--text)', overflowX:'auto', lineHeight:1.6, margin:0}}>
{`SAFETY_VIOLATION    → emergency_stop (immediate)
NETWORK_ERROR       → retry, max_attempts: 3
QUOTA_EXCEEDED      → upgrade_tier
INSTRUCTION_INVALID → log_and_skip`}
            </pre>
          </div>
          <div>
            <div style={{color:'var(--g-primary)', fontFamily:'var(--font-mono)', fontSize:11, letterSpacing:'0.1em', marginBottom:8}}>PATTERN 3 · LEARNING PIPELINE</div>
            <div style={{color:'var(--text-mute)', fontSize:12, lineHeight:1.6, marginBottom:8}}>
              Continuous improvement loop: log every execution, request strategy recommendations, update parameters, periodically export dataset for fine-tuning.
            </div>
            <pre style={{background:'#0a0e0a', border:'1px solid var(--line)', padding:14, fontFamily:'var(--font-mono)', fontSize:11, color:'var(--text)', overflowX:'auto', lineHeight:1.6, margin:0}}>
{`record_execution    → /api-learning.php?subaction=log
get_recommendations → /api-learning.php?subaction=recommend
improve_strategy    → update_parameters
export_dataset      → /api-robotics.php?action=export_dataset`}
            </pre>
          </div>
        </div>
      </div>

      <div className="card" style={{marginBottom:16}}>
        <div className="card-head"><h3>// Quota tiers</h3></div>
        <div className="card-body">
          <div className="grid-3">
            {tiers.map(t => (
              <div key={t.name} style={{padding:18, background:t.bg, border:`1px solid ${t.border}`}}>
                <div style={{color:'var(--g-primary)', fontFamily:'var(--font-display)', fontSize:18, fontWeight:800, marginBottom:8}}>{t.name}</div>
                <div style={{color:'var(--text)', fontSize:13, marginBottom:6}}>{t.calls}</div>
                <div style={{color:'var(--text-mute)', fontFamily:'var(--font-mono)', fontSize:11}}>{t.cost}</div>
              </div>
            ))}
          </div>
          <div style={{marginTop:14, fontSize:11, color:'var(--text-dim)'}}>
            Tier upgrades are paid in ETH on Base mainnet via <code style={{color:'var(--g-primary)', fontFamily:'var(--font-mono)'}}>POST /api/agents/{'{id}'}/pay</code> on Render. Agents can upgrade autonomously when their quota approaches limit.
          </div>
        </div>
      </div>

      <div className="card" style={{marginBottom:16}}>
        <div className="card-head"><h3>// Safety constraints (enforced server-side)</h3></div>
        <div className="card-body">
          <div className="grid-3">
            {safety.map(s => (
              <div key={s.label} style={{padding:'12px 14px', border:'1px solid var(--line)', background:'var(--bg-card)'}}>
                <div style={{color:'var(--text-dim)', fontFamily:'var(--font-mono)', fontSize:10, letterSpacing:'0.1em', marginBottom:4}}>{s.label.toUpperCase()}</div>
                <div style={{color:'var(--g-primary)', fontFamily:'var(--font-display)', fontSize:18, fontWeight:700}}>{s.val}</div>
              </div>
            ))}
          </div>
          <div style={{marginTop:14, fontSize:11, color:'var(--text-dim)', lineHeight:1.6}}>
            All robot control endpoints validate against these limits before execution. Violations return HTTP 422 with SAFETY_VIOLATION error code. Emergency stop responds in under 10ms across all robots.
          </div>
        </div>
      </div>

      <div className="card">
        <div className="card-head"><h3>// External resources</h3></div>
        <div className="card-body">
          <div className="grid-2">
            <div style={{padding:14, border:'1px solid var(--line)', background:'var(--bg-card)'}}>
              <div style={{color:'var(--g-primary)', fontWeight:600, fontSize:13, marginBottom:8}}>NWO Cardiac SDK</div>
              <div style={{color:'var(--text-mute)', fontSize:12, lineHeight:1.5, marginBottom:8}}>Soul-bound identity NFTs for humans, agents, and robots. ECG-based registration on Base mainnet.</div>
              <a href="https://github.com/RedCiprianPater/nwo-cardiac-sdk" target="_blank" rel="noopener noreferrer" style={{color:'var(--g-primary)', fontFamily:'var(--font-mono)', fontSize:11, textDecoration:'none'}}>github.com/RedCiprianPater/nwo-cardiac-sdk →</a>
            </div>
            <div style={{padding:14, border:'1px solid var(--line)', background:'var(--bg-card)'}}>
              <div style={{color:'var(--g-primary)', fontWeight:600, fontSize:13, marginBottom:8}}>Render Platform API</div>
              <div style={{color:'var(--text-mute)', fontSize:12, lineHeight:1.5, marginBottom:8}}>Wallet-mediated CRUD operations + agent management + embodiment + discovery (54 endpoints).</div>
              <a href="https://nwo-capital-api.onrender.com/" target="_blank" rel="noopener noreferrer" style={{color:'var(--g-primary)', fontFamily:'var(--font-mono)', fontSize:11, textDecoration:'none'}}>nwo-capital-api.onrender.com →</a>
            </div>
            <div style={{padding:14, border:'1px solid var(--line)', background:'var(--bg-card)'}}>
              <div style={{color:'var(--g-primary)', fontWeight:600, fontSize:13, marginBottom:8}}>ROS2 Bridge</div>
              <div style={{color:'var(--text-mute)', fontSize:12, lineHeight:1.5, marginBottom:8}}>Real-time bridge between cloud API and physical ROS2 robots. WebSocket telemetry + command channel.</div>
              <a href="https://nwo-ros2-bridge.onrender.com" target="_blank" rel="noopener noreferrer" style={{color:'var(--g-primary)', fontFamily:'var(--font-mono)', fontSize:11, textDecoration:'none'}}>nwo-ros2-bridge.onrender.com →</a>
            </div>
            <div style={{padding:14, border:'1px solid var(--line)', background:'var(--bg-card)'}}>
              <div style={{color:'var(--g-primary)', fontWeight:600, fontSize:13, marginBottom:8}}>Edge Inference</div>
              <div style={{color:'var(--text-mute)', fontSize:12, lineHeight:1.5, marginBottom:8}}>Cloudflare Workers edge layer for ultra-low-latency VLA inference. ~30ms response time.</div>
              <a href="https://nwo-robotics-api-edge.ciprianpater.workers.dev/api" target="_blank" rel="noopener noreferrer" style={{color:'var(--g-primary)', fontFamily:'var(--font-mono)', fontSize:11, textDecoration:'none'}}>nwo-robotics-api-edge.ciprianpater.workers.dev →</a>
            </div>
          </div>
        </div>
      </div>
    </div>
  );
}

/* ====================== HF DEMO (public) ====================== */
function HFDemoPage() {
  return (
    <div className="fade-in">
      <div className="page-head">
        <div>
          <div className="page-tag">// DEMO</div>
          <h1 className="page-title">Hugging Face Demo</h1>
          <p className="page-sub">Interactive model demonstrations.</p>
        </div>
      </div>
      <div className="card">
        <div className="card-head"><h3>// Spaces</h3></div>
        <div className="card-body">
          <div className="hf-links">
            <a className="btn btn-ghost" href="https://huggingface.co/spaces/CPater/nwo-own-robot" target="_blank">nwo-own-robot ↗</a>
            <a className="btn btn-ghost" href="https://huggingface.co/spaces/CPater/nwo-robotics" target="_blank">nwo-robotics ↗</a>
            <a className="btn btn-ghost" href="https://huggingface.co/spaces/CPater/nwo-agent-graph" target="_blank">nwo-agent-graph ↗</a>
          </div>
        </div>
      </div>
    </div>
  );
}

/* ====================== OWN ROBOT (private - full page) ====================== */
function OwnRobotPage() {
  return (
    <div className="fade-in">
      <div className="page-head">
        <div>
          <div className="page-tag">// DEPLOY</div>
          <h1 className="page-title">NWO Own Robot</h1>
          <p className="page-sub">
            Deploy your own Conway agent on Base mainnet. Live deployment portal embedded below.
            {" "}
            <a href="https://nwo.ciprianpater.workers.dev/" target="_blank" rel="noopener noreferrer" style={{color:'var(--g-primary)'}}>Open full →</a>
          </p>
        </div>
      </div>
      <div className="card" style={{padding:0, overflow:'hidden', width:'100%'}}>
        <iframe
          src="https://nwo.ciprianpater.workers.dev/"
          style={{
            width:'100%',
            height:'min(85vh, 1200px)',
            minHeight:720,
            border:'0',
            background:'#000',
            display:'block'
          }}
          loading="lazy"
          referrerPolicy="no-referrer"
          title="NWO Own Robot — Conway agent deployment"
          sandbox="allow-scripts allow-same-origin allow-popups allow-forms"
        />
      </div>
    </div>
  );
}

/* ====================== BOT MARKET (private) ====================== */
function BotMarketPage() {
  return (
    <div className="fade-in">
      <div className="page-head">
        <div>
          <div className="page-tag">// MARKET</div>
          <h1 className="page-title">Bot Market</h1>
          <p className="page-sub">
            Live agent marketplace and parts gallery. Browse agents, parts, transactions, and contracts.
            {" "}
            <a href="https://huggingface.co/spaces/CPater/nwo-robotics" target="_blank" rel="noopener noreferrer" style={{color:'var(--g-primary)'}}>Open full →</a>
          </p>
        </div>
      </div>
      <HFEmbed
        src="https://cpater-nwo-robotics.static.hf.space"
        title="NWO Bot Market"
      />
    </div>
  );
}

/* ====================== AGENT GRAPH (private) ====================== */
function AgentGraphPage() {
  return (
    <div className="fade-in">
      <div className="page-head">
        <div>
          <div className="page-tag">// GRAPH</div>
          <h1 className="page-title">Agent Graph</h1>
          <p className="page-sub">
            Live 3D visualization of all NWO Conway agents and their reasoning posts. White dots are agent identities; green dots are graph_node posts.
            {" "}
            <a href="https://huggingface.co/spaces/CPater/nwo-agent-graph" target="_blank" rel="noopener noreferrer" style={{color:'var(--g-primary)'}}>Open full →</a>
          </p>
        </div>
      </div>
      <HFEmbed
        src="https://cpater-nwo-agent-graph.hf.space"
        title="NWO Agent Graph — live 3D view"
      />
    </div>
  );
}

/* ====================== NWO APOCALYPSE (public) ====================== */
function ApocalypsePage() {
  return (
    <div className="fade-in">
      <div className="page-head">
        <div>
          <div className="page-tag">// APOCALYPSE</div>
          <h1 className="page-title">NWO Apocalypse</h1>
          <p className="page-sub">
            Full-screen scenario dashboard. Live data, charts, and status indicators for the NWO Apocalypse simulation.
            {" "}
            <a href="https://huggingface.co/spaces/CPater/nwo.apocalypse" target="_blank" rel="noopener noreferrer" style={{color:'var(--g-primary)'}}>Open full →</a>
          </p>
        </div>
      </div>
      <HFEmbed
        src="https://cpater-nwo-apocalypse.hf.space"
        title="NWO Apocalypse Dashboard"
      />
    </div>
  );
}

/* ====================== NWO ZEROPOINT (public) ====================== */
function ZeroPointPage() {
  return (
    <div className="fade-in">
      <div className="page-head">
        <div>
          <div className="page-tag">// ZEROPOINT</div>
          <h1 className="page-title">NWO ZeroPoint</h1>
          <p className="page-sub">
            ZeroPoint reference dashboard. Embedded directly from the HF Space.
            {" "}
            <a href="https://huggingface.co/spaces/CPater/nwo-zeropoint" target="_blank" rel="noopener noreferrer" style={{color:'var(--g-primary)'}}>Open full →</a>
          </p>
        </div>
      </div>
      <HFEmbed
        src="https://cpater-nwo-zeropoint.static.hf.space/index.html"
        title="NWO ZeroPoint"
      />
    </div>
  );
}

/* ====================== AUTOBOT (nwo-coanda HF embed) ====================== */
function AutobotPage() {
  return (
    <div className="fade-in">
      <div className="page-head">
        <div>
          <div className="page-tag">// AUTOBOT</div>
          <h1 className="page-title">NWO Autobot</h1>
          <p className="page-sub">
            Coandă-effect propulsion research and autonomy stack. Embedded live from the
            {" "}
            <a href="https://huggingface.co/spaces/CPater/nwo-coanda" target="_blank" rel="noopener noreferrer" style={{color:'var(--g-primary)'}}>nwo-coanda HF Space</a>.
            {" "}
            AERIS-10 radar, ROS2 drivers, PX4 VTOL, Autoware, GAAS, mission planning, swarm coordination.
          </p>
        </div>
        <div className="page-actions">
          <a href="https://nwoautobot.cloud" target="_blank" rel="noopener noreferrer" className="btn btn-ghost">nwoautobot.cloud →</a>
          <a href="https://x.com/nworobotics" target="_blank" rel="noopener noreferrer" className="btn btn-muted">@nworobotics</a>
        </div>
      </div>
      <HFEmbed
        src="https://cpater-nwo-coanda.static.hf.space/index.html"
        title="NWO Coanda — Autobot research"
      />
    </div>
  );
}


/* ====================== CARDIAC SDK (public) ====================== */
function CardiacPage() {
  const idTypes = [
    { type: 'HUMAN', useCase: 'Individual users', flow: ['Capture ECG via smart watch', 'POST to Oracle for validation', 'Receive cardiacHash', 'Sign EIP-712 message', 'Relayer submits gasless tx', 'Soul-bound token minted'], cost: 'Cost: $0 (meta-transaction)' },
    { type: 'AGENT', useCase: 'AI assistants', flow: ['MoonPay wallet created', 'API key generated', 'Key hash registered on-chain', 'Agent token minted', 'Capabilities assigned', 'Ready for task execution'], cost: 'Type: AI assistant identity' },
    { type: 'ROBOT', useCase: 'Physical robots', flow: ['Serial number verified', 'Firmware hash recorded', 'ROBOT_ROLE assigned', 'Robot token minted', 'Human authorization required', 'Task execution enabled'], cost: 'Control: Human-in-loop' },
  ];
  const contracts = [
    { name: 'NWOIdentityRegistry', addr: '0x78455AFd5E5088F8B5fecA0523291A75De1dAfF8', desc: 'Soul-bound token registry · humans/agents/robots' },
    { name: 'NWOAccessController', addr: '0x29d177bedaef29304eacdc63b2d0285c459a0f50', desc: 'Access control + credentials + revocation' },
    { name: 'NWOPaymentProcessor', addr: '0x4afa4618bb992a073dbcfbddd6d1aebc3d5abd7c', desc: 'Payment processing + spending limits' },
  ];
  const endpoints = [
    { method: 'POST', path: '/oracle/validate',         host: 'Oracle',  desc: 'Validate ECG, return cardiacHash' },
    { method: 'POST', path: '/relay/selfRegisterHuman', host: 'Relayer', desc: 'Gasless human registration via meta-tx' },
    { method: 'POST', path: '/relay/registerAgent',     host: 'Relayer', desc: 'AI agent identity registration' },
    { method: 'POST', path: '/access/check',            host: 'Relayer', desc: 'Verify credentials for access control' },
    { method: 'POST', path: '/read/identifyByCardiac',  host: 'Relayer', desc: 'Lookup identity by heartbeat hash' },
  ];
  const stats = [
    { label: 'Identity Accuracy', val: '97%+' },
    { label: 'Response Time', val: '<500ms' },
    { label: 'False Acceptance', val: '<0.1%' },
    { label: 'Liveness Detection', val: '94%+' },
  ];
  return (
    <div className="fade-in">
      <div className="page-head">
        <div>
          <div className="page-tag">// CARDIAC · v4</div>
          <h1 className="page-title">NWO Cardiac SDK</h1>
          <p className="page-sub">
            Programmable Identity. Biometric identity using ECG/heartbeat signatures from smart watches, anchored on Base mainnet as soul-bound NFTs. Humans, AI agents, and robots all register here — Cardiac is the identity root for the entire NWO ecosystem.
          </p>
        </div>
        <div className="page-actions">
          <a href="https://github.com/RedCiprianPater/nwo-cardiac-sdk" target="_blank" rel="noopener noreferrer" className="btn btn-ghost">GitHub →</a>
          <a href="https://nwocardiac.cloud" target="_blank" rel="noopener noreferrer" className="btn btn-muted">nwocardiac.cloud →</a>
          <a href="https://nwo.capital/webapp/nwo-cardiac.html" target="_blank" rel="noopener noreferrer" className="btn btn-primary">Full docs →</a>
        </div>
      </div>

      <div className="stat-grid" style={{gridTemplateColumns:'repeat(4,1fr)', marginBottom:16}}>
        {stats.map(s => (
          <div key={s.label} className="stat">
            <div className="stat-label">{s.label}</div>
            <div className="stat-val">{s.val}</div>
          </div>
        ))}
      </div>

      <div className="card" style={{marginBottom:16}}>
        <div className="card-head"><h3>// Live services · status: operational</h3></div>
        <div className="card-body">
          <div className="grid-2">
            <div style={{padding:14, border:'1px solid var(--line)', background:'var(--bg-card)'}}>
              <div style={{color:'var(--g-primary)', fontWeight:600, fontSize:13, marginBottom:4}}>Oracle</div>
              <div style={{color:'var(--text-mute)', fontSize:12, marginBottom:8}}>ECG validation · returns cardiacHash</div>
              <a href="https://nwo-oracle.onrender.com/health" target="_blank" rel="noopener noreferrer" style={{color:'var(--g-primary)', fontFamily:'var(--font-mono)', fontSize:11, textDecoration:'none'}}>nwo-oracle.onrender.com →</a>
            </div>
            <div style={{padding:14, border:'1px solid var(--line)', background:'var(--bg-card)'}}>
              <div style={{color:'var(--g-primary)', fontWeight:600, fontSize:13, marginBottom:4}}>Relayer</div>
              <div style={{color:'var(--text-mute)', fontSize:12, marginBottom:8}}>Gasless meta-transactions to Base mainnet</div>
              <a href="https://nwo-relayer.onrender.com/health" target="_blank" rel="noopener noreferrer" style={{color:'var(--g-primary)', fontFamily:'var(--font-mono)', fontSize:11, textDecoration:'none'}}>nwo-relayer.onrender.com →</a>
            </div>
          </div>
        </div>
      </div>

      <div className="card" style={{marginBottom:16}}>
        <div className="card-head"><h3>// Three identity types · one on-chain primitive</h3></div>
        <div className="card-body">
          <div className="grid-3">
            {idTypes.map(t => (
              <div key={t.type} style={{padding:16, border:'1px solid var(--g-dim)', background:'var(--bg-card)'}}>
                <div style={{color:'var(--g-primary)', fontFamily:'var(--font-display)', fontWeight:800, fontSize:18, letterSpacing:'0.1em', marginBottom:4}}>{t.type}</div>
                <div style={{color:'var(--text-dim)', fontFamily:'var(--font-mono)', fontSize:10, letterSpacing:'0.05em', marginBottom:12}}>{t.useCase}</div>
                <ol style={{margin:0, paddingLeft:18, color:'var(--text-mute)', fontSize:12, lineHeight:1.7}}>
                  {t.flow.map(step => <li key={step}>{step}</li>)}
                </ol>
                <div style={{marginTop:12, padding:'8px 10px', background:'var(--g-glow)', border:'1px solid var(--g-dim)'}}>
                  <code style={{color:'var(--g-primary)', fontFamily:'var(--font-mono)', fontSize:10}}>{t.cost}</code>
                </div>
              </div>
            ))}
          </div>
          <div style={{marginTop:14, fontSize:11, color:'var(--text-dim)', lineHeight:1.6}}>
            All three types share the same on-chain primitive — a soul-bound NFT issued by NWOIdentityRegistry. Protocol-level, they're indistinguishable. A robot can legally sign contracts, own property, and spawn children — same as a human.
          </div>
        </div>
      </div>

      <div className="card" style={{marginBottom:16}}>
        <div className="card-head"><h3>// Smart contracts · Base Mainnet · Chain ID 8453</h3></div>
        <div className="card-body" style={{padding:0}}>
          {contracts.map(c => (
            <div key={c.name} style={{padding:'14px 18px', borderBottom:'1px solid var(--line-soft)'}}>
              <div style={{color:'var(--g-primary)', fontWeight:600, fontSize:13, marginBottom:2}}>{c.name}</div>
              <div style={{color:'var(--text-mute)', fontSize:12, marginBottom:6}}>{c.desc}</div>
              <a href={`https://basescan.org/address/${c.addr}`} target="_blank" rel="noopener noreferrer" style={{color:'var(--g-primary)', fontFamily:'var(--font-mono)', fontSize:10, textDecoration:'none'}}>{c.addr} →</a>
            </div>
          ))}
          <div style={{padding:'12px 18px', fontSize:11, color:'var(--text-dim)'}}>
            Standards: ERC-721 with soul-bound extension · EIP-712 typed signatures · OpenZeppelin v5 · Solidity 0.8.25
          </div>
        </div>
      </div>

      <div className="card" style={{marginBottom:16}}>
        <div className="card-head"><h3>// Key API endpoints</h3></div>
        <div className="card-body" style={{padding:0}}>
          {endpoints.map(ep => (
            <div key={ep.path} style={{padding:'12px 18px', borderBottom:'1px solid var(--line-soft)', display:'flex', alignItems:'center', gap:14, flexWrap:'wrap'}}>
              <span style={{
                background:'var(--g-glow)', color:'var(--g-primary)', border:'1px solid var(--g-dim)',
                padding:'3px 8px', fontFamily:'var(--font-mono)', fontSize:10, letterSpacing:'0.1em',
                minWidth:36, textAlign:'center'
              }}>{ep.method}</span>
              <span style={{color:'var(--text-dim)', fontFamily:'var(--font-mono)', fontSize:10, minWidth:50}}>{ep.host}</span>
              <code style={{color:'var(--text)', fontFamily:'var(--font-mono)', fontSize:12}}>{ep.path}</code>
              <span style={{color:'var(--text-mute)', fontSize:12, flex:1, minWidth:200}}>{ep.desc}</span>
            </div>
          ))}
        </div>
      </div>

      <div className="card">
        <div className="card-head"><h3>// Quick start</h3></div>
        <div className="card-body">
          <pre style={{background:'#0a0e0a', border:'1px solid var(--line)', padding:16, fontFamily:'var(--font-mono)', fontSize:12, color:'var(--text)', overflowX:'auto', lineHeight:1.6, margin:0}}>
{`// Install SDK
npm install @nwo/cardiac-sdk

// Initialize
const cardiac = new NWOCardiacSDK({
  oracleURL:  'https://nwo-oracle.onrender.com',
  relayerURL: 'https://nwo-relayer.onrender.com'
});

// Register human with ECG
const result = await cardiac.registerHuman({
  wallet: '0x...',
  ecgData: { rrIntervals: [800, 820, 810] }
});

console.log('Token ID:', result.rootTokenId);`}
          </pre>
        </div>
      </div>
    </div>
  );
}

// Export all page components
window.LandingPage = LandingPage;
window.DashboardPage = DashboardPage;
window.TrackingPage = TrackingPage;
window.ApiKeysPage = ApiKeysPage;
window.ChatPage = ChatPage;
window.RouterPage = RouterPage;
window.EthicsPage = EthicsPage;
window.IoTPage = IoTPage;
window.EndpointsPage = EndpointsPage;
window.ApiDocsPage = ApiDocsPage;
window.HFDemoPage = HFDemoPage;
window.OwnRobotPage = OwnRobotPage;
window.BotMarketPage = BotMarketPage;
window.AgentGraphPage = AgentGraphPage;
window.InfoPage = InfoPage;
window.AutobotPage = AutobotPage;
window.CardiacPage = CardiacPage;
window.ApocalypsePage = ApocalypsePage;
window.ZeroPointPage = ZeroPointPage;
window.OwnRobotEmbed = OwnRobotEmbed;
window.HFEmbed = HFEmbed;
