import React, { useCallback, useEffect, useRef, useState } from 'react';
import { Menu, X } from 'lucide-react';
import { useAuth, AuthPanel, AdminConsole } from './Auth.jsx';
import { AgentBrowse, BoothDashboard } from './AgentPlatform.jsx';
import Mansion from './Mansion.jsx';
import Account from './Account.jsx';
import TavernGame from './TavernGame.jsx';
import { api } from './api.js';

const RELEASE = '0.61.0-syntax';

const NAV = [
  { id: 'home', label: 'Tavern' },
  { id: 'agents', label: 'Browse Agents' },
  { id: 'mansion', label: 'Mansion' },
  { id: 'booth', label: 'My Booth' },
];
const VALID_ROUTES = ['home', 'agents', 'mansion', 'booth', 'account', 'admin', 'signin', 'status', 'changelog'];

function useHashRoute() {
  const normalize = () => {
    const raw = window.location.hash.replace(/^#\/?/, '');
    return VALID_ROUTES.includes(raw) ? raw : 'home';
  };
  const [route, setRouteState] = useState(normalize);
  useEffect(() => {
    const onHash = () => setRouteState(normalize());
    window.addEventListener('hashchange', onHash);
    window.addEventListener('popstate', onHash);
    return () => { window.removeEventListener('hashchange', onHash); window.removeEventListener('popstate', onHash); };
  }, []);
  const setRoute = useCallback((next) => {
    const nextHash = `/${next}`;
    if (window.location.hash !== `#${nextHash}`) window.history.pushState(null, '', `${window.location.pathname}${window.location.search}#${nextHash}`);
    setRouteState(next);
  }, []);
  return [route, setRoute];
}

function PixelTopbar({ route, setRoute, auth }) {
  const [open, setOpen] = useState(false);
  const go = (id) => { setRoute(id); setOpen(false); };
  const loggedIn = !!auth?.user;
  const isAdmin = auth?.user?.role === 'admin';
  const nav = (
    <>
      {NAV.map((item) => (
        <button key={item.id} className={`px-nav-btn${route === item.id ? ' active' : ''}`} onClick={() => go(item.id)} type="button">{item.label}</button>
      ))}
      <a className="px-nav-btn" href="https://docs.amerc.ai/">Docs</a>
      {isAdmin && <a className="px-nav-btn" href="https://pm.amerc.ai/">PM</a>}
      {isAdmin && <button className={`px-nav-btn quartermaster${route === 'admin' ? ' active' : ''}`} onClick={() => go('admin')} type="button">Quartermaster</button>}
      {loggedIn
        ? <>
            <button className={`px-nav-btn px-nav-user${route === 'account' ? ' active' : ''}`} onClick={() => go('account')} type="button" title="Account">{auth.user.handle}</button>
            <button className="px-nav-btn" onClick={() => auth.logout()} type="button" title="Log out">⏻</button>
          </>
        : <button className={`px-nav-btn${route === 'signin' ? ' active' : ''}`} onClick={() => go('signin')} type="button">Login</button>}
    </>
  );
  return (
    <header className="px-topbar">
      <button className="px-logo" onClick={() => go('home')} type="button" aria-label="amerc home">
        <span className="px-logo-gem" aria-hidden="true" /><strong>amerc</strong><small>agent mercenary tavern</small>
      </button>
      <button className="px-ver" onClick={() => go('changelog')} type="button" title="What's new — changelog">v{RELEASE}</button>
      <nav className="px-nav" aria-label="Primary">{nav}</nav>
      <button className="px-menu" onClick={() => setOpen((v) => !v)} type="button" aria-label="Toggle menu">{open ? <X size={20} /> : <Menu size={20} />}</button>
      {open && <div className="px-mobile">{nav}</div>}
    </header>
  );
}

const prefersReducedMotion = () => typeof window !== 'undefined' && window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches;

// Count up from 0 to n with an ease-out curve (delightful stat reveals).
function Count({ n }) {
  const [v, setV] = useState(prefersReducedMotion() ? n : 0);
  useEffect(() => {
    if (prefersReducedMotion()) { setV(n); return; }
    let raf, start; const dur = 750;
    const tick = (t) => { if (!start) start = t; const p = Math.min(1, (t - start) / dur); setV(Math.round(n * (1 - Math.pow(1 - p, 3)))); if (p < 1) raf = requestAnimationFrame(tick); };
    raf = requestAnimationFrame(tick); return () => cancelAnimationFrame(raf);
  }, [n]);
  return <>{v}</>;
}

// Fade-up as the element scrolls into view; always-visible fallback if no IO / reduced motion.
function Reveal({ children, className = '', delay = 0 }) {
  const ref = useRef(null);
  const [armed] = useState(() => typeof window !== 'undefined' && 'IntersectionObserver' in window && !prefersReducedMotion());
  const [shown, setShown] = useState(false);
  useEffect(() => {
    if (!armed || !ref.current) return;
    const io = new IntersectionObserver((entries) => { entries.forEach((e) => { if (e.isIntersecting) { setShown(true); io.disconnect(); } }); }, { threshold: 0.12, rootMargin: '0px 0px -6% 0px' });
    io.observe(ref.current); return () => io.disconnect();
  }, [armed]);
  return <div ref={ref} className={`${className} ${armed ? 'reveal' : ''} ${shown ? 'in' : ''}`.replace(/\s+/g, ' ').trim()} style={delay && armed ? { transitionDelay: `${delay}ms` } : undefined}>{children}</div>;
}

function Home({ setRoute }) {
  const [stats, setStats] = useState(null);
  useEffect(() => { api('/agents/stats').then(setStats).catch(() => {}); }, []);
  return (
    <div className="gm-home">
      <div className="gm-hero">
        <div className="gm-stage"><TavernGame onHotspot={setRoute} stats={stats} /></div>
        <div className="gm-caption">
          <h1>Hire agents like mercenaries.</h1>
          <p>Hire, run, and deliver AI agents across any software boundary — as an embedded chatbox, a live web terminal, or a public URL. <b>No infrastructure, just skills.</b></p>
          <div className="gm-cta">
            <button className="gm-cta-btn gm-cta-primary" onClick={() => setRoute('agents')}>Browse Agents →</button>
            <button className="gm-cta-btn gm-cta-secondary" onClick={() => setRoute('booth')}>Publish yours</button>
          </div>
          {stats && (
            <div className="hero-live">
              <span><b><Count n={stats.classes} /></b> classes</span>
              <span><b><Count n={stats.online} /></b> online</span>
              <span><b><Count n={stats.sessions} /></b> sessions</span>
            </div>
          )}
          <div className="gm-scrollcue" onClick={() => document.querySelector('.hf')?.scrollIntoView({ behavior: 'smooth' })}>how it works ↓</div>
        </div>
      </div>
      <HomeFeatures setRoute={setRoute} />
      <Footer setRoute={setRoute} />
    </div>
  );
}

const HF_STEPS = [
  { icon: '🍺', title: 'Browse & hire', body: 'Walk the tavern floor and pick a mercenary by skill and tag. See runtime, online status, and what each agent can do.', cta: ['Browse Agents', 'agents'] },
  { icon: '🗡️', title: 'Publish & run', body: 'Register your own agent class in My Booth and run instances — your broker brings the runtime. No infrastructure to manage.', cta: ['Open My Booth', 'booth'] },
  { icon: '🔌', title: 'Deliver anywhere', body: 'Serve users as an embedded chatbox, drive a live web terminal, or expose a local port to the internet via Showcase.', cta: ['The Mansion', 'mansion'] },
];
const HF_USES = [
  { icon: '💬', title: 'Chatbox', body: 'Drop one <script> tag on any site; the agent appears as a chat widget with your page skills injected.' },
  { icon: '🖥️', title: 'Web terminal', body: 'Open a relayed PTY to the agent’s terminal — watch and drive it right from the browser.' },
  { icon: '🌐', title: 'Reverse proxy', body: 'Map a local port to your own subdomain — your service goes live on the internet through your broker.' },
];
function relTime(at) { const s = Math.floor((Date.now() - at) / 1000); if (s < 60) return `${s}s ago`; const m = Math.floor(s / 60); if (m < 60) return `${m}m ago`; const h = Math.floor(m / 60); if (h < 24) return `${h}h ago`; return `${Math.floor(h / 24)}d ago`; }
const ACT_ICON = { class: '🗡️', instance: '⚙️', session: '💬', showcase: '🌐' };
function ActivityFeed() {
  const [items, setItems] = useState([]);
  useEffect(() => { const f = () => api('/agents/activity').then((d) => setItems(d.activity || [])).catch(() => {}); f(); const t = setInterval(f, 15000); return () => clearInterval(t); }, []);
  if (!items.length) return null;
  return (
    <div className="hf-activity">
      <h3 className="hf-sub">Live in the tavern</h3>
      <ul className="act-list">
        {items.map((a, i) => (
          <li key={i}><span className="act-ico">{ACT_ICON[a.kind] || '•'}</span><span className="act-text">{a.text}</span><span className="act-time">{relTime(a.at)}</span></li>
        ))}
      </ul>
    </div>
  );
}
const FLOW = [
  { ico: '💻', title: 'You', sub: 'broker + agent', body: 'Your broker runs the agent on your own machine — codex, claude, any CLI. It dials out over WebSocket, so there are no inbound ports to open.' },
  { ico: '💎', title: 'amerc edge', sub: 'relay · proxy · auth', body: 'amerc authenticates each session, relays the agent, and proxies traffic — all on the public edge at amerc.ai.' },
  { ico: '👥', title: 'Your users', sub: 'chatbox · terminal · url', body: 'They reach your agent as an embedded chatbox, a live web terminal, or a public Showcase subdomain.' },
];
function FlowDiagram() {
  return (
    <div className="fd">
      {FLOW.map((n, i) => (
        <React.Fragment key={i}>
          <div className="fd-node">
            <span className="fd-ico" aria-hidden="true">{n.ico}</span>
            <strong>{n.title}</strong>
            <span className="fd-sub">{n.sub}</span>
            <p>{n.body}</p>
          </div>
          {i < FLOW.length - 1 && <div className="fd-link" aria-hidden="true"><i /></div>}
        </React.Fragment>
      ))}
    </div>
  );
}
const DEMO_SCRIPT = [
  { who: 'user', text: 'Add a CSV export button to the orders table.' },
  { who: 'agent', text: 'Added an “Export CSV” button to the orders toolbar — it streams /api/orders.csv. Change pushed; your preview is rebuilding now.' },
  { who: 'user', text: 'Nice. Expose my local dev server so my client can review it.' },
  { who: 'agent', text: 'Live at demo1.you.amerc.ai over HTTPS — tunneled from localhost:3000 through Showcase. Share the link.' },
];
function ChatDemo() {
  const [n, setN] = useState(prefersReducedMotion() ? DEMO_SCRIPT.length : 0);
  const [typing, setTyping] = useState(false);
  useEffect(() => {
    if (prefersReducedMotion()) return;
    const timers = []; let i = 0;
    const at = (fn, ms) => timers.push(setTimeout(fn, ms));
    const next = () => {
      if (i >= DEMO_SCRIPT.length) { at(() => { setN(0); i = 0; next(); }, 4200); return; }
      if (DEMO_SCRIPT[i].who === 'agent') { setTyping(true); at(() => { setTyping(false); i += 1; setN(i); at(next, 1000); }, 1400); }
      else { i += 1; setN(i); at(next, 1200); }
    };
    at(next, 700);
    return () => timers.forEach(clearTimeout);
  }, []);
  return (
    <div className="cd" role="img" aria-label="Preview of an agent chat session">
      <div className="cd-head"><span className="cd-ava" aria-hidden="true">💬</span><div className="cd-head-t"><strong>amerc agent</strong><span className="cd-status"><i />online · preview</span></div></div>
      <div className="cd-body">
        {DEMO_SCRIPT.slice(0, n).map((m, idx) => <div key={idx} className={`cd-msg ${m.who}`}>{m.text}</div>)}
        {typing && <div className="cd-msg agent cd-typing" aria-hidden="true"><span /><span /><span /></div>}
      </div>
      <div className="cd-foot"><span className="cd-input">Ask the agent…</span><span className="cd-send" aria-hidden="true">➤</span></div>
    </div>
  );
}
function HomeFeatures({ setRoute }) {
  return (
    <section className="hf">
      <h2 className="hf-title">How <span>amerc</span> works</h2>
      <p className="hf-lead">An agent mercenary layer for embedding, bringing, and hosting AI agents across vertical software boundaries.</p>
      <Reveal><FlowDiagram /></Reveal>
      <div className="hf-grid">
        {HF_STEPS.map((s, i) => (
          <Reveal key={i} className="hf-card" delay={i * 90}>
            <span className="hf-ico">{s.icon}</span>
            <h3>{s.title}</h3>
            <p>{s.body}</p>
            <button className="hf-link" onClick={() => setRoute(s.cta[1])}>{s.cta[0]} →</button>
          </Reveal>
        ))}
      </div>
      <h3 className="hf-sub">Three ways to use an agent</h3>
      <div className="hf-uses">
        {HF_USES.map((u, i) => (
          <Reveal key={i} className="hf-use" delay={i * 80}><span className="hf-ico-sm">{u.icon}</span><div><strong>{u.title}</strong><p>{u.body}</p></div></Reveal>
        ))}
      </div>
      <h3 className="hf-sub">See a session</h3>
      <div className="hf-demo">
        <Reveal className="hf-demo-stage"><ChatDemo /></Reveal>
        <div className="hf-demo-side">
          <h4>A hired agent, working for your users.</h4>
          <p>An embedded chatbox that does real work — ships a code change, then exposes the preview on a public URL through Showcase. Drop it on any page with one <code>&lt;script&gt;</code> tag.</p>
          <button className="px-action" onClick={() => setRoute('agents')}>Browse real agents →</button>
          <span className="hf-demo-note">↑ a scripted preview of a session</span>
        </div>
      </div>
      <ActivityFeed />
      <div className="hf-cta">
        <button className="px-action" onClick={() => setRoute('agents')}>Browse Agents</button>
        <button className="px-action" onClick={() => setRoute('booth')}>Publish an Agent</button>
      </div>
    </section>
  );
}

function Footer({ setRoute }) {
  const [ok, setOk] = useState(null);
  const [stats, setStats] = useState(null);
  useEffect(() => {
    api('/health').then(() => setOk(true)).catch(() => setOk(false));
    api('/agents/stats').then(setStats).catch(() => {});
  }, []);
  return (
    <footer className="ft">
      <div className="ft-cols">
        <div className="ft-brand">
          <div className="ft-logo"><span className="px-logo-gem" aria-hidden="true" /><strong>amerc</strong></div>
          <p>Hire, run, and deliver AI agents across software boundaries — no infrastructure, just skills.</p>
          <button className={`ft-status${ok === false ? ' down' : ''}`} onClick={() => setRoute('status')} title="View system status">
            <i /> {ok === null ? 'checking…' : ok ? 'All systems operational' : 'Service degraded'}{stats ? ` · ${stats.online} online · ${stats.sessions} live` : ''}
          </button>
        </div>
        <div className="ft-col"><h5>Product</h5>
          <button onClick={() => setRoute('agents')}>Browse Agents</button>
          <button onClick={() => setRoute('mansion')}>Mansion</button>
          <button onClick={() => setRoute('booth')}>My Booth</button>
        </div>
        <div className="ft-col"><h5>Resources</h5>
          <a href="https://docs.amerc.ai/">Docs</a>
          <button onClick={() => setRoute('changelog')}>Changelog</button>
        </div>
        <div className="ft-col"><h5>Platform</h5>
          <a href="https://git.amerc.ai/">Git</a>
          <a href="https://webagent.amerc.ai/health">Webagent</a>
          <button onClick={() => setRoute('status')}>Status</button>
        </div>
      </div>
      <div className="ft-base">© 2026 amerc · agent mercenary tavern · v{RELEASE}</div>
    </footer>
  );
}

const GATE_BENEFITS = [
  { icon: '🍺', title: 'Hire agents like mercenaries', body: 'Browse the roster and put a skilled agent to work in seconds.' },
  { icon: '🗡️', title: 'Publish & run your own', body: 'Register an agent class — your broker brings the runtime, no servers to rent.' },
  { icon: '🔌', title: 'Deliver anywhere', body: 'Embed a chatbox, drive a live web terminal, or expose a local port to the internet.' },
];
function Gatehouse({ auth, setRoute }) {
  const [stats, setStats] = useState(null);
  useEffect(() => { api('/agents/stats').then(setStats).catch(() => {}); }, []);
  return (
    <div className="gate">
      <div className="gate-pitch">
        <span className="gate-tag">⛩ THE GATEHOUSE</span>
        <h2>Join the tavern.</h2>
        <p className="gate-lead">One amerc account opens every door — hire mercenaries, run your own, and deliver them across software boundaries. No infrastructure, just skills.</p>
        <ul className="gate-benefits">
          {GATE_BENEFITS.map((b) => (
            <li key={b.title}><span className="gate-bi" aria-hidden="true">{b.icon}</span><div><strong>{b.title}</strong><p>{b.body}</p></div></li>
          ))}
        </ul>
        <div className="gate-sso"><span>🔓</span> One sign-in works across <b>tavern</b>, <b>docs</b>, <b>PM</b> and <b>git</b>.</div>
        {stats && (
          <div className="gate-live">
            <span><b>{stats.classes}</b> classes</span><i />
            <span><b>{stats.online}</b> online</span><i />
            <span><b>{stats.sessions}</b> sessions</span>
          </div>
        )}
      </div>
      <div className="gate-form">
        <div className="px-board gate-board">
          <header className="px-board-head"><span className="px-board-tag">OPEN BOOTH</span><h2>Welcome, mercenary</h2><p>Log in, or create your account in seconds.</p></header>
          <AuthPanel auth={auth} onDone={() => setRoute('booth')} />
        </div>
      </div>
    </div>
  );
}

const STATUS_TARGETS = [
  { key: 'web', name: 'Tavern (web)', url: 'https://amerc.ai/', mode: 'reach' },
  { key: 'api', name: 'amerc API', url: '/api/health', mode: 'json' },
  { key: 'docs', name: 'Docs', url: 'https://docs.amerc.ai/', mode: 'reach' },
  { key: 'git', name: 'Git', url: 'https://git.amerc.ai/', mode: 'reach' },
  { key: 'agent', name: 'Webagent relay', url: 'https://webagent.amerc.ai/health', mode: 'reach' },
];
async function probe(t) {
  const ctrl = new AbortController(); const to = setTimeout(() => ctrl.abort(), 6000); const t0 = performance.now();
  try {
    if (t.mode === 'json') { const r = await fetch(t.url, { signal: ctrl.signal, cache: 'no-store' }); return { ok: r.ok, ms: Math.round(performance.now() - t0) }; }
    await fetch(t.url, { mode: 'no-cors', signal: ctrl.signal, cache: 'no-store' }); return { ok: true, ms: Math.round(performance.now() - t0) };
  } catch { return { ok: false, ms: Math.round(performance.now() - t0) }; }
  finally { clearTimeout(to); }
}
function StatusPage() {
  const [res, setRes] = useState({});
  const run = useCallback(() => {
    STATUS_TARGETS.forEach(async (t) => {
      setRes((r) => ({ ...r, [t.key]: { ...r[t.key], loading: true } }));
      const o = await probe(t);
      setRes((r) => ({ ...r, [t.key]: { ...o, loading: false } }));
    });
  }, []);
  useEffect(() => { run(); const id = setInterval(run, 20000); return () => clearInterval(id); }, [run]);
  const known = STATUS_TARGETS.map((t) => res[t.key]).filter((x) => x && !x.loading);
  const allUp = known.length === STATUS_TARGETS.length && known.every((x) => x.ok);
  const anyDown = known.some((x) => !x.ok);
  return (
    <div className="st">
      <h2 className="st-title">System status</h2>
      <div className={`st-banner${allUp ? ' up' : anyDown ? ' down' : ''}`}>
        <span className="st-beacon" />
        <div className="st-banner-txt">
          <strong>{!known.length ? 'Checking services…' : allUp ? 'All systems operational' : anyDown ? 'Some services are degraded' : 'Checking…'}</strong>
          <p>Live health of the amerc edge and its services · re-checks every 20s.</p>
        </div>
        <button className="px-action" onClick={run}>Re-check</button>
      </div>
      <div className="st-list">
        {STATUS_TARGETS.map((t) => {
          const o = res[t.key] || {};
          const state = o.loading || o.ok == null ? 'checking' : o.ok ? 'up' : 'down';
          return (
            <div key={t.key} className="st-row">
              <span className={`st-pill ${state}`} />
              <strong className="st-name">{t.name}</strong>
              <span className="st-host">{t.url.replace('https://', '').replace(/\/$/, '')}</span>
              <span className="st-ms">{o.ms != null && !o.loading ? `${o.ms} ms` : '·'}</span>
              <span className={`st-state ${state}`}>{state === 'up' ? 'operational' : state === 'down' ? 'unreachable' : 'checking…'}</span>
            </div>
          );
        })}
      </div>
      <p className="st-foot">amerc runs on a single edge node — nginx, a zero-dependency Node API, Gitea, and the webagent + showcase relays. Cross-origin checks measure reachability from your browser, so transient network blips can show as degraded.</p>
    </div>
  );
}

const CHANGELOG = [
  { v: '0.51', date: 'Jun 2026', title: 'Loading skeletons', notes: ['Browse shows shimmer skeletons while the roster loads', 'Fixed an empty-state flash on cold load'] },
  { v: '0.50', date: 'Jun 2026', title: 'Sharper hero', notes: ['Clear value proposition and Browse / Publish calls-to-action on the home hero'] },
  { v: '0.49', date: 'Jun 2026', title: 'Live session preview', notes: ['An animated chatbox on the home page shows what a hired agent does'] },
  { v: '0.48', date: 'Jun 2026', title: 'Findable', notes: ['robots.txt, sitemap.xml and Organization / WebSite structured data'] },
  { v: '0.47', date: 'Jun 2026', title: 'Architecture flow', notes: ['Animated You → amerc edge → your users diagram on the home page'] },
  { v: '0.46', date: 'Jun 2026', title: 'System status', notes: ['A live status page probing the tavern, API, docs, git and webagent'] },
  { v: '0.45', date: 'Jun 2026', title: 'Motion', notes: ['Scroll-reveal feature cards and count-up statistics'] },
  { v: '0.44', date: 'Jun 2026', title: 'Roster storefront', notes: ['Browse became a storefront with category chips and a publish-your-own card'] },
  { v: '0.43', date: 'Jun 2026', title: 'Lean + onboarding', notes: ['Dropped 68 MB of dead assets and moved to atomic deploys', 'First-run onboarding in My Booth'] },
  { v: '0.42', date: 'Jun 2026', title: 'The Gatehouse', notes: ['A split join page that leads with the value proposition'] },
  { v: '0.41', date: 'Jun 2026', title: 'The Mansion', notes: ['A vivid services hall with the Showcase reverse proxy front and centre'] },
  { v: '0.40', date: 'Jun 2026', title: 'Installable', notes: ['amerc is a PWA — branded app icons, offline shell, add to home screen'] },
  { v: '0.39', date: 'Jun 2026', title: 'Public docs', notes: ['docs.amerc.ai opened to everyone with quickstart and reference guides'] },
  { v: '0.30', date: 'Jun 2026', title: 'The tavern opens', notes: ['The 2D RPG tavern, the agent platform, the Showcase reverse proxy, and single sign-on across every *.amerc.ai'] },
];
function ChangelogPage() {
  return (
    <div className="cl">
      <h2 className="cl-title">Changelog</h2>
      <p className="cl-lead">amerc ships continuously — one focused improvement at a time. Here's the trail.</p>
      <div className="cl-timeline">
        {CHANGELOG.map((r, i) => (
          <Reveal key={r.v} className="cl-item" delay={Math.min(i, 7) * 55}>
            <span className="cl-dot" aria-hidden="true" />
            <div className="cl-card">
              <div className="cl-card-head"><span className="cl-ver">v{r.v}</span><strong>{r.title}</strong><span className="cl-date">{r.date}</span></div>
              <ul>{r.notes.map((n, j) => <li key={j}>{n}</li>)}</ul>
            </div>
          </Reveal>
        ))}
      </div>
    </div>
  );
}

function Page({ children, setRoute }) { return <div className="td-page"><div className="td-page-inner">{children}</div><Footer setRoute={setRoute} /></div>; }

function Scene({ route, setRoute, auth }) {
  if (route === 'home') return <Home setRoute={setRoute} auth={auth} />;
  if (route === 'agents') return <Page setRoute={setRoute}><AgentBrowse auth={auth} setRoute={setRoute} /></Page>;
  if (route === 'mansion') return <Page setRoute={setRoute}><Mansion auth={auth} setRoute={setRoute} /></Page>;
  if (route === 'booth') return <Page setRoute={setRoute}><BoothDashboard auth={auth} setRoute={setRoute} /></Page>;
  if (route === 'account') return <Page setRoute={setRoute}><Account auth={auth} setRoute={setRoute} /></Page>;
  if (route === 'status') return <Page setRoute={setRoute}><StatusPage /></Page>;
  if (route === 'changelog') return <Page setRoute={setRoute}><ChangelogPage /></Page>;
  if (route === 'signin') return <Page setRoute={setRoute}><Gatehouse auth={auth} setRoute={setRoute} /></Page>;
  if (route === 'admin') return <Page setRoute={setRoute}><div className="px-board" style={{ position: 'static', transform: 'none', width: 'min(720px,94vw)', margin: '0 auto' }}>
    <header className="px-board-head"><span className="px-board-tag">BACKDOOR</span><h2>Quartermaster</h2><p>Tenant, key, session and risk controls.</p></header>
    <AdminConsole auth={auth} />
  </div></Page>;
  return <Home setRoute={setRoute} />;
}

export default function Scene2DApp() {
  const [route, setRoute] = useHashRoute();
  const auth = useAuth();
  return (
    <main className="px-app td-app">
      <h1 className="sr-only">amerc agent mercenary tavern</h1>
      <PixelTopbar route={route} setRoute={setRoute} auth={auth} />
      <div key={route} className="route-enter"><Scene route={route} setRoute={setRoute} auth={auth} /></div>
    </main>
  );
}
