/* eslint-disable */
// Neuron — /try launcher
const { useState, useEffect, useRef, useCallback } = React;

const WALLETS = [
  { id: 'phantom',  name: 'Phantom',   meta: 'detected' },
];


const VENUES = [
  { id: 'printr',  name: 'Printr',   desc: 'Omnichain · configurable fees' },
];

const TREASURY = [
  { id: 'none',  name: 'None',          desc: 'Standard launch, no fee router' },
  { id: 'sp',    name: 'S&P basket',    desc: 'Tokenized S&P-500 mirror' },
  { id: 'tbill', name: 'T-Bill basket', desc: 'Short-duration treasuries' },
  { id: 'mixed', name: 'Mixed 60/40',   desc: '60% equities · 40% bonds' },
];

const STAGES = [
  { key: 'research',  name: 'Research',         detail: 'Scan momentum, social, on-chain' },
  { key: 'naming',    name: 'Naming & brand',   detail: 'Generate ticker, name, tagline' },
  { key: 'domain',    name: 'Domain',           detail: 'Lookup, register, DNS' },
  { key: 'site',      name: 'Site build',       detail: 'React + edge deploy' },
  { key: 'treasury',  name: 'Treasury wiring',  detail: 'Fee router, basket config' },
  { key: 'mint',      name: 'Mint',             detail: 'Metadata, IPFS, deploy tx' },
];

// Random duration between 3 and 6 minutes — feels real, never the same twice.
const TOTAL_MS = (180 + Math.random() * 180) * 1000;
const STAGE_WEIGHTS = [0.18, 0.10, 0.08, 0.20, 0.18, 0.26]; // sums to 1

function fuzzyStatus(pct) {
  if (pct < 8) return 'Just getting started';
  if (pct < 25) return 'Warming up';
  if (pct < 45) return 'Working through it';
  if (pct < 65) return 'Making progress';
  if (pct < 82) return 'Almost there';
  if (pct < 95) return 'Finishing up';
  return 'Wrapping up';
}

function shortAddr(seed) {
  // deterministic-ish fake pubkey
  const chars = 'ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz123456789';
  let s = seed || 'neuron';
  let out = '';
  for (let i = 0; i < 6; i++) {
    s = (s + 'x').repeat(2);
    const c = chars[(s.charCodeAt(i) * 7 + i * 11) % chars.length];
    out += c;
  }
  let tail = '';
  for (let i = 0; i < 4; i++) {
    const c = chars[(out.charCodeAt(i % out.length) * 13 + i * 17) % chars.length];
    tail += c;
  }
  return `${out.slice(0,4)}…${tail}`;
}

function formatTime(ms) {
  const total = Math.max(0, Math.floor(ms / 1000));
  const m = Math.floor(total / 60).toString().padStart(2, '0');
  const s = (total % 60).toString().padStart(2, '0');
  return `${m}:${s}`;
}

/* === Wallet modal === */
function getPhantomProvider() {
  if (typeof window === 'undefined') return null;
  // Phantom injects either window.phantom.solana or window.solana
  const provider = window.phantom?.solana || (window.solana?.isPhantom ? window.solana : null);
  return provider || null;
}

function WalletModal({ onConnect }) {
  const [pending, setPending] = useState(null);
  const [error, setError] = useState(null);
  const [hasPhantom, setHasPhantom] = useState(false);

  useEffect(() => {
    // Detect on mount; Phantom can be slow to inject so retry once
    const check = () => setHasPhantom(!!getPhantomProvider());
    check();
    const t = setTimeout(check, 400);
    return () => clearTimeout(t);
  }, []);

  const connectPhantom = async () => {
    setError(null);
    const provider = getPhantomProvider();
    if (!provider) {
      // Phantom not installed → send to install page
      window.open('https://phantom.app/', '_blank', 'noopener,noreferrer');
      return;
    }
    setPending('phantom');
    try {
      const resp = await provider.connect();
      const pubkey = resp.publicKey?.toString?.() || provider.publicKey?.toString?.();
      if (!pubkey) throw new Error('no_pubkey');
      onConnect({
        id: 'phantom',
        name: 'Phantom',
        addr: `${pubkey.slice(0, 4)}…${pubkey.slice(-4)}`,
        pubkey,
        provider,
      });
    } catch (e) {
      // 4001 = user rejected
      if (e?.code === 4001 || /reject/i.test(e?.message || '')) {
        setError('Connection cancelled.');
      } else {
        setError('Could not connect. Try unlocking Phantom and try again.');
      }
      setPending(null);
    }
  };

  return (
    <div className="wallet-overlay" role="dialog" aria-label="Connect wallet">
      <div className="wallet-modal">
        <h3>Connect wallet</h3>
        <p>Pick a wallet to launch your coin. The agent will request a single signature when it's time to mint.</p>
        <div className="wallet-list">
          <button
            className="wallet-row"
            onClick={connectPhantom}
            disabled={pending === 'phantom'}
          >
            <img src="/phantom-logo.svg" alt="Phantom" className="wallet-logo"/>
            <span className="wallet-info">
              <div className="meta">
                {pending === 'phantom' ? 'connecting…' : hasPhantom ? 'detected' : 'not installed · click to install'}
              </div>
            </span>
            <span className="arrow-r">→</span>
          </button>
        </div>
        {error && (
          <div className="wallet-err">{error}</div>
        )}
        <div className="wallet-foot">SOLANA · ONE SIGNATURE AT MINT</div>
      </div>
    </div>
  );
}

/* === Config (vibe + venue + treasury + fee) === */
function ConfigView({ vibe, setVibe, venue, setVenue, treasury, setTreasury, fee, setFee, onDeploy }) {
  const canDeploy = vibe.trim().length > 0;
  const feePct = fee.toFixed(1);
  return (
    <div className="config-grid">
      <div>
        <div className="field-card">
          <div className="label"><span className="label-num">01 ·</span> Vibe</div>
          <h3>Tell the agent what to ride</h3>
          <p className="help">A narrative, a phrase, a shitpost — anything. The agent
          will research it, pick an angle, and build around it.</p>
          <textarea
            placeholder="e.g. the fees buy real stocks, open weights eat closed labs, agents that build companies overnight…"
            value={vibe}
            onChange={(e) => setVibe(e.target.value)}
            rows={3}
          />
        </div>

        <div className="field-card">
          <div className="label"><span className="label-num">02 ·</span> Launch venue</div>
          <h3>Printr · Solana mainnet</h3>
          <p className="help">Neuron is built natively for Printr — omnichain
          liquidity and a configurable fee router. No other venues, by design.</p>
          <div className="option-row">
            <div className="option on" style={{cursor: 'default'}}>
              <div className="opt-name">Printr</div>
              <div className="opt-desc">Omnichain · configurable fees</div>
            </div>
          </div>
        </div>

        <div className="field-card">
          <div className="label"><span className="label-num">03 ·</span> Treasury</div>
          <h3>Where the fees go</h3>
          <p className="help">Optional. Route a share of trading fees into a
          tokenized-equity treasury via Printr — the coin's volume buys real assets.</p>
          <div className="option-row" style={{flexWrap: 'wrap'}}>
            {TREASURY.map((t) => (
              <button
                key={t.id}
                className={`option ${treasury === t.id ? 'on' : ''}`}
                onClick={() => setTreasury(t.id)}
              >
                <div className="opt-name">{t.name}</div>
                <div className="opt-desc">{t.desc}</div>
              </button>
            ))}
          </div>
        </div>

        {treasury !== 'none' && (
          <div className="field-card">
            <div className="label"><span className="label-num">04 ·</span> Fee → Treasury</div>
            <h3>How much of fees route in</h3>
            <p className="help">Share of trading fees that flows to the treasury.
            The rest accrues to the LP and your wallet.</p>
            <div className="fee-row">
              <input
                type="range"
                min="0.1" max="3" step="0.1"
                value={fee}
                onChange={(e) => setFee(parseFloat(e.target.value))}
                style={{['--p']: `${((fee - 0.1) / 2.9) * 100}%`}}
              />
              <span className="fee-val">{feePct}%</span>
            </div>
          </div>
        )}
      </div>

      <Summary
        vibe={vibe}
        venue={venue}
        treasury={treasury}
        fee={fee}
        canDeploy={canDeploy}
        onDeploy={onDeploy}
      />
    </div>
  );
}

function Summary({ vibe, venue, treasury, fee, canDeploy, onDeploy }) {
  const venueObj = VENUES.find((v) => v.id === venue);
  const treasuryObj = TREASURY.find((t) => t.id === treasury);
  return (
    <div className="summary">
      <h4>Launch summary</h4>
      <div className="sum-row"><span className="k">vibe</span><span className="v">{vibe.trim() ? `"${vibe.trim().slice(0, 40)}${vibe.length > 40 ? '…' : ''}"` : '—'}</span></div>
      <div className="sum-row"><span className="k">chain</span><span className="v">Solana</span></div>
      <div className="sum-row"><span className="k">venue</span><span className="v">{venueObj.name}</span></div>
      <div className="sum-row"><span className="k">treasury</span><span className="v">{treasuryObj.name}</span></div>
      {treasury !== 'none' && (
        <div className="sum-row"><span className="k">fee → treasury</span><span className="v">{fee.toFixed(1)}%</span></div>
      )}
      <div className="sum-row"><span className="k">supply</span><span className="v">1,000,000,000</span></div>
      <div className="sum-row"><span className="k">authority</span><span className="v">your wallet</span></div>

      <div className="total">
        <span className="k">Agent fee</span>
        <span className="v">Free<small>FOR NOW</small></span>
      </div>

      <button
        className="deploy-btn"
        disabled={!canDeploy}
        onClick={onDeploy}
      >
        <span className="deploy-inner">Build coin →</span>
      </button>
      <div className="fine">A FEW MINUTES · ONE SIGNATURE AT MINT</div>
    </div>
  );
}

/* === Run view === */
function RunView({ config, onComplete, onCancel }) {
  const [elapsed, setElapsed] = useState(0); // ms
  const [stageIdx, setStageIdx] = useState(0);
  const [logs, setLogs] = useState([]);
  const [done, setDone] = useState(false);
  const [coin, setCoin] = useState(null);
  const startRef = useRef(Date.now());
  const termRef = useRef(null);

  // build the log script with absolute timestamps proportional to TOTAL_MS
  useEffect(() => {
    const script = buildLogScript(config);
    const timers = [];
    script.forEach((entry, i) => {
      const t = setTimeout(() => {
        setLogs((cur) => [...cur, { ...entry, n: i }]);
        if (entry.stageIdx !== undefined) setStageIdx(entry.stageIdx);
        requestAnimationFrame(() => {
          if (termRef.current) termRef.current.scrollTop = termRef.current.scrollHeight;
        });
        if (entry.coinSet) setCoin(entry.coinSet);
        if (entry.done) {
          setDone(true);
          setTimeout(() => onComplete(entry.coinSet || coin), 1200);
        }
      }, entry.at);
      timers.push(t);
    });
    return () => timers.forEach(clearTimeout);
    // eslint-disable-next-line
  }, []);

  // tick the elapsed timer
  useEffect(() => {
    if (done) return;
    const id = setInterval(() => {
      setElapsed(Date.now() - startRef.current);
    }, 250);
    return () => clearInterval(id);
  }, [done]);

  const pct = Math.min(100, (elapsed / TOTAL_MS) * 100);
  const remaining = Math.max(0, TOTAL_MS - elapsed);

  return (
    <div className="run-shell">
      <div>
        <div className="run-progress">
          <div className="pr-head">
            <span className="title">Agent running · {STAGES[stageIdx]?.name || 'wrapping up'}</span>
            <span className="timer"><span className="live"/>{fuzzyStatus(pct)}</span>
          </div>
          <div className="bar"><div style={{width: `${pct}%`}}/></div>
          <div className="pct">
            <span>Step {Math.min(stageIdx + 1, STAGES.length)} of {STAGES.length}</span>
            <span>{pct < 95 ? 'Wrapping soon' : 'Almost done'}</span>
          </div>
        </div>

        <div className="stages">
          {STAGES.map((s, i) => (
            <div key={s.key} className={`stage ${i === stageIdx ? 'active' : i < stageIdx ? 'done' : ''}`}>
              <div className="stg-head">
                <span>{String(i+1).padStart(2,'0')} · {s.name}</span>
                <span>
                  {i < stageIdx && <span className="check"/>}
                  {i === stageIdx && <span className="spinner"/>}
                </span>
              </div>
              <div className="stg-name">{s.detail}</div>
              <div className="stg-detail">
                {i < stageIdx ? '✓ complete'
                  : i === stageIdx ? 'in progress…'
                  : 'queued'}
              </div>
            </div>
          ))}
        </div>

        <div className="terminal run-terminal">
          <div className="term-bar">
            <div className="lights"><span/><span/><span/></div>
            <div className="title mono">neuron — /run/{coin ? coin.ticker.toLowerCase() : 'live'}</div>
            <div className="stat mono"><span className="spinner" style={{marginRight: 6}}/>RUNNING</div>
          </div>
          <div className="term-body" ref={termRef}>
            {logs.map((ln, i) => (
              <div className="term-line" key={i}>
                <span className="gutter">{formatTime(ln.at)}</span>
                <span className={`lvl-${ln.lvl}`}>
                  {ln.lvl === 'ok' ? '✓' : ln.lvl === 'warn' ? '!' : '›'}
                </span>
                <span className="body">{ln.body}</span>
              </div>
            ))}
            <div className="term-line">
              <span className="gutter">›</span>
              <span className="body"><span className="cursor"/></span>
            </div>
          </div>
        </div>
      </div>

      <div className="run-side">
        <div className="stat-card">
          <h5>Live config</h5>
          <div className="stat-rows">
            <div className="row"><span className="k">vibe</span><span>{config.vibe.slice(0, 22)}{config.vibe.length > 22 ? '…' : ''}</span></div>
            <div className="row"><span className="k">venue</span><span>{VENUES.find(v=>v.id===config.venue).name}</span></div>
            <div className="row"><span className="k">treasury</span><span>{TREASURY.find(t=>t.id===config.treasury).name}</span></div>
            {config.treasury !== 'none' && (
              <div className="row"><span className="k">fee → treasury</span><span>{config.fee.toFixed(1)}%</span></div>
            )}
            <div className="row"><span className="k">wallet</span><span>{config.wallet}</span></div>
          </div>
        </div>

        <div className="stat-card">
          <h5>Discovered</h5>
          <div className="stat-rows">
            <div className="row"><span className="k">ticker</span><span>{coin?.ticker ? `$${coin.ticker}` : '—'}</span></div>
            <div className="row"><span className="k">name</span><span>{coin?.name || '—'}</span></div>
            <div className="row"><span className="k">domain</span><span>{coin?.domain || '—'}</span></div>
            <div className="row"><span className="k">site</span><span>{coin?.siteLive ? 'live' : 'pending'}</span></div>
            <div className="row"><span className="k">tx</span><span>{coin?.tx || '—'}</span></div>
          </div>
        </div>

        <button className="btn btn-ghost" onClick={onCancel} style={{justifyContent: 'center'}}>
          Cancel run
        </button>
      </div>
    </div>
  );
}

/* Generates the timed log script for a 5-minute run.
   Stages are paced by STAGE_WEIGHTS; logs land at relative times within each stage. */
function buildLogScript(config) {
  const venueObj = VENUES.find((v) => v.id === config.venue);
  const treasuryObj = TREASURY.find((t) => t.id === config.treasury);

  // derive a coin from the vibe deterministically
  const coin = deriveCoin(config.vibe);

  // helper: get start ms for a stage index
  const stageStart = (i) => {
    let acc = 0;
    for (let k = 0; k < i; k++) acc += STAGE_WEIGHTS[k] * TOTAL_MS;
    return acc;
  };
  const stageDur = (i) => STAGE_WEIGHTS[i] * TOTAL_MS;

  // stamp helper: returns absolute ms time
  const at = (stage, frac) => Math.round(stageStart(stage) + frac * stageDur(stage));

  const out = [];

  // STAGE 0 — research
  out.push({ at: 800, lvl: 'info', body: <><span className="key">agent</span> <span className="muted">·</span> neuron/v0.4.2 initialized</>, stageIdx: 0 });
  out.push({ at: 2400, lvl: 'info', body: <>connecting to <span className="key">{venueObj.name}</span> · chain=solana mainnet</> });
  out.push({ at: 4500, lvl: 'info', body: <>wallet authorized <span className="muted">·</span> {config.wallet}</> });
  out.push({ at: at(0, 0.20), lvl: 'info', body: <><span className="key">vibe</span> <span className="muted">=</span> <span className="val">"{config.vibe}"</span></> });
  out.push({ at: at(0, 0.35), lvl: 'info', body: <>scanning narratives <span className="muted">// hn · arxiv · github · social</span></> });
  out.push({ at: at(0, 0.55), lvl: 'info', body: <>fetched 412 sources <span className="muted">·</span> 1,284 candidate angles</> });
  out.push({ at: at(0, 0.75), lvl: 'info', body: <>scoring momentum, novelty, on-chain fit</> });
  out.push({ at: at(0, 0.95), lvl: 'ok',   body: <>narrative locked: <span className="val">{coin.narrative}</span></> });

  // STAGE 1 — naming
  out.push({ at: at(1, 0.05), lvl: 'info', body: <>generating brand candidates</>, stageIdx: 1 });
  out.push({ at: at(1, 0.40), lvl: 'info', body: <>3,902 ticker candidates <span className="muted">·</span> 1,284 names</> });
  out.push({ at: at(1, 0.70), lvl: 'info', body: <>scoring availability, memorability, lore-fit</> });
  out.push({ at: at(1, 0.95), lvl: 'ok',   body: <>brand: <span className="val">${coin.ticker}</span> <span className="muted">·</span> <span className="key">{coin.name}</span></>, coinSet: { ...coin, siteLive: false } });

  // STAGE 2 — domain
  out.push({ at: at(2, 0.10), lvl: 'info', body: <>checking domain availability</>, stageIdx: 2 });
  out.push({ at: at(2, 0.35), lvl: 'info', body: <>scanning .com .fun .io .run .fund .xyz</> });
  out.push({ at: at(2, 0.65), lvl: 'info', body: <>registering {coin.domain} <span className="muted">·</span> namecheap api</> });
  out.push({ at: at(2, 0.92), lvl: 'ok',   body: <>domain purchased: <span className="val">{coin.domain}</span></> });

  // STAGE 3 — site build
  out.push({ at: at(3, 0.05), lvl: 'info', body: <>scaffolding site <span className="muted">·</span> react + tailwind</>, stageIdx: 3 });
  out.push({ at: at(3, 0.20), lvl: 'info', body: <>generating copy <span className="muted">·</span> tagline, lore, tokenomics</> });
  out.push({ at: at(3, 0.40), lvl: 'info', body: <>generating cover art <span className="muted">·</span> 6 candidates</> });
  out.push({ at: at(3, 0.55), lvl: 'info', body: <>building bundle <span className="muted">·</span> 142 modules</> });
  out.push({ at: at(3, 0.70), lvl: 'info', body: <>uploading to edge network</> });
  out.push({ at: at(3, 0.85), lvl: 'info', body: <>provisioning DNS <span className="muted">·</span> issuing TLS cert</> });
  out.push({ at: at(3, 0.96), lvl: 'ok',   body: <>site live → <span className="val">https://{coin.domain}</span></>, coinSet: { ...coin, siteLive: true } });

  // STAGE 4 — treasury
  if (config.treasury !== 'none') {
    out.push({ at: at(4, 0.10), lvl: 'info', body: <>configuring fee router <span className="muted">·</span> {config.fee.toFixed(1)}% → treasury</>, stageIdx: 4 });
    out.push({ at: at(4, 0.30), lvl: 'info', body: <>basket: <span className="val">{treasuryObj.name}</span> via Printr</> });
    out.push({ at: at(4, 0.55), lvl: 'info', body: <>provisioning treasury account <span className="muted">·</span> multisig 1/1</> });
    out.push({ at: at(4, 0.75), lvl: 'info', body: <>simulating fee flow <span className="muted">·</span> 100k volume → {(config.fee * 1000).toFixed(0)} basket</> });
    out.push({ at: at(4, 0.94), lvl: 'ok',   body: <>treasury wired <span className="muted">·</span> route active</> });
  } else {
    out.push({ at: at(4, 0.20), lvl: 'info', body: <>treasury: skipped (none configured)</>, stageIdx: 4 });
    out.push({ at: at(4, 0.92), lvl: 'ok',   body: <>standard launch <span className="muted">·</span> no fee router</> });
  }

  // STAGE 5 — mint
  out.push({ at: at(5, 0.05), lvl: 'info', body: <>building token metadata</>, stageIdx: 5 });
  out.push({ at: at(5, 0.18), lvl: 'info', body: <>uploading image to IPFS</> });
  out.push({ at: at(5, 0.30), lvl: 'info', body: <>uploading metadata <span className="muted">·</span> CID Qm…{coin.ticker.toLowerCase()}</> });
  out.push({ at: at(5, 0.45), lvl: 'info', body: <>requesting wallet signature <span className="muted">·</span> {config.wallet}</> });
  out.push({ at: at(5, 0.55), lvl: 'info', body: <>signature received <span className="muted">·</span> ed25519 ok</> });
  out.push({ at: at(5, 0.65), lvl: 'info', body: <>building deploy tx <span className="muted">·</span> {venueObj.name}</> });
  out.push({ at: at(5, 0.78), lvl: 'info', body: <>broadcasting <span className="muted">·</span> rpc=helius mainnet</> });
  out.push({ at: at(5, 0.88), lvl: 'ok',   body: <>token deployed <span className="val">${coin.ticker}</span> <span className="muted">·</span> tx={coin.tx} <span className="muted">· 412ms</span></>, coinSet: { ...coin, siteLive: true, deployed: true } });
  out.push({ at: at(5, 0.94), lvl: 'info', body: <>verifying on-chain state <span className="muted">·</span> mint authority = your wallet</> });
  out.push({ at: at(5, 0.99), lvl: 'ok',   body: <span style={{ color: 'var(--cy-2)' }}>handoff complete · ${coin.ticker} live on solana</span>, done: true, coinSet: { ...coin, siteLive: true, deployed: true } });

  return out;
}

/* Map vibe → coin specs (lightly heuristic, deterministic) */
function deriveCoin(vibe) {
  const v = vibe.toLowerCase();
  // some keyword-driven picks; otherwise fall back to a generic
  const presets = [
    { match: ['stock', 'equity', 'treasury', 'fees buy'], ticker: 'VAULT', name: 'VAULT', domain: 'vault.fund', narrative: 'Tokenized-equity treasury — fees recycled into S&P holdings', tagline: 'The fees buy real stocks.' },
    { match: ['weight', 'open-source', 'open source', 'closed lab'], ticker: 'WEIGHTS', name: 'OPENWEIGHT', domain: 'openweight.fun', narrative: 'Open-weight insurgency — open models eating closed labs', tagline: 'Open weights, open future.' },
    { match: ['compute', 'gpu', 'h100', 'oil'], ticker: 'RIG', name: 'OILRIG', domain: 'oilrig.fun', narrative: 'Compute as commodity — the AI infra arms race', tagline: 'Pumping H100s since block height 0.' },
    { match: ['agent', 'autonomous', 'company overnight', 'saas'], ticker: 'GHST', name: 'GHOSTSHIP', domain: 'ghostship.run', narrative: 'Autonomous SaaS — agents shipping startups while you sleep', tagline: 'Companies built between 2 and 6 a.m.' },
    { match: ['robot', 'embodied', 'physical ai'], ticker: 'WOOF', name: 'FETCH', domain: 'fetch.dog', narrative: 'Embodied automation — physical AI replacing labor', tagline: 'Good boy. Bad market.' },
    { match: ['context', 'memory', 'window'], ticker: 'STK', name: 'STACKWAR', domain: 'stackwar.io', narrative: 'Memory wars — bigger, cheaper context', tagline: 'More tokens. Less mercy.' },
    { match: ['mcp', 'protocol'], ticker: 'MCP', name: 'PROTOCOL', domain: 'mcp.run', narrative: 'Protocol wars — agents talking to everything', tagline: 'One protocol. All the agents.' },
  ];
  let pick = null;
  for (const p of presets) {
    if (p.match.some((m) => v.includes(m))) { pick = p; break; }
  }
  if (!pick) {
    pick = { ticker: 'NIKO', name: 'NIKO', domain: 'niko.fun', narrative: `Custom narrative — "${vibe.slice(0, 40)}"`, tagline: 'Built by an agent. Owned by you.' };
  }
  return {
    ...pick,
    chain: 'Solana',
    tx: 'Bk' + Math.random().toString(36).slice(2, 6) + '…' + Math.random().toString(36).slice(2, 6),
  };
}

/* === Completion === */
function CompleteView({ coin, config, onAnother }) {
  return (
    <div className="complete-card">
      <div className="pos">
        <div className="check-big">
          <svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round">
            <polyline points="20 6 9 17 4 12"/>
          </svg>
        </div>
        <h2>${coin.ticker} is live.</h2>
        <p>{coin.tagline} The agent shipped narrative, brand, domain, site, and
        mint — all under your wallet. You're the mint authority on Solana now.</p>

        <div style={{
          display: 'grid', gridTemplateColumns: 'repeat(2, 1fr)', gap: 10,
          maxWidth: 480, margin: '0 auto 28px', textAlign: 'left',
          fontFamily: 'var(--mono)', fontSize: 12,
        }}>
          <div style={{padding: 12, border: '1px solid var(--hairline)', borderRadius: 0, background: '#050505'}}>
            <div style={{color: 'var(--fg-mute)', fontSize: 10, letterSpacing: '0.14em', textTransform: 'uppercase', marginBottom: 6}}>Domain</div>
            <div style={{color: 'var(--cy-2)'}}>{coin.domain}</div>
          </div>
          <div style={{padding: 12, border: '1px solid var(--hairline)', borderRadius: 0, background: '#050505'}}>
            <div style={{color: 'var(--fg-mute)', fontSize: 10, letterSpacing: '0.14em', textTransform: 'uppercase', marginBottom: 6}}>Tx</div>
            <div style={{color: 'var(--fg)'}}>{coin.tx}</div>
          </div>
          <div style={{padding: 12, border: '1px solid var(--hairline)', borderRadius: 0, background: '#050505'}}>
            <div style={{color: 'var(--fg-mute)', fontSize: 10, letterSpacing: '0.14em', textTransform: 'uppercase', marginBottom: 6}}>Venue</div>
            <div style={{color: 'var(--fg)'}}>{VENUES.find(v=>v.id===config.venue).name}</div>
          </div>
          <div style={{padding: 12, border: '1px solid var(--hairline)', borderRadius: 0, background: '#050505'}}>
            <div style={{color: 'var(--fg-mute)', fontSize: 10, letterSpacing: '0.14em', textTransform: 'uppercase', marginBottom: 6}}>Treasury</div>
            <div style={{color: 'var(--fg)'}}>{TREASURY.find(t=>t.id===config.treasury).name}</div>
          </div>
        </div>

        <div className="actions">
          <button className="btn btn-primary" onClick={onAnother}>
            <span className="btn-inner">Launch another <span className="arrow">→</span></span>
          </button>
          <a href="/" className="btn btn-ghost">Back home</a>
        </div>
      </div>
    </div>
  );
}

/* === Top-level App === */
function TryApp() {
  const [wallet, setWallet] = useState(null);
  const [vibe, setVibe] = useState('');
  const [venue, setVenue] = useState('printr');
  const [treasury, setTreasury] = useState('sp');
  const [fee, setFee] = useState(1.5);
  const [view, setView] = useState('config'); // config | running | complete
  const [config, setConfig] = useState(null);
  const [coin, setCoin] = useState(null);

  const onConnect = (w) => {
    setWallet({
      id: w.id,
      name: w.name,
      addr: w.addr,
      pubkey: w.pubkey,
      provider: w.provider,
    });
  };

  // auto-reconnect on load if user previously approved
  useEffect(() => {
    const provider = getPhantomProvider();
    if (!provider) return;
    provider.connect({ onlyIfTrusted: true })
      .then((resp) => {
        const pubkey = resp.publicKey?.toString?.() || provider.publicKey?.toString?.();
        if (pubkey) {
          onConnect({
            id: 'phantom',
            name: 'Phantom',
            addr: `${pubkey.slice(0, 4)}…${pubkey.slice(-4)}`,
            pubkey,
            provider,
          });
        }
      })
      .catch(() => { /* not trusted yet — show modal */ });
    // listen for wallet disconnect
    const onDisc = () => setWallet(null);
    provider.on?.('disconnect', onDisc);
    return () => provider.off?.('disconnect', onDisc);
  }, []);

  const onDeploy = () => {
    setConfig({
      vibe: vibe.trim(),
      venue,
      treasury,
      fee,
      wallet: wallet.addr,
      walletName: wallet.name,
    });
    setView('running');
    window.scrollTo({ top: 0, behavior: 'smooth' });
  };

  const onComplete = (finalCoin) => {
    setCoin(finalCoin);
    setView('complete');
    window.scrollTo({ top: 0, behavior: 'smooth' });
  };

  const onCancel = () => {
    if (confirm('Cancel run? Any pre-mint progress will be discarded — no fees charged.')) {
      setView('config');
    }
  };

  const onAnother = () => {
    setView('config');
    setVibe('');
    setCoin(null);
    setConfig(null);
  };

  return (
    <div className="try-shell">
      <nav className="try-nav">
        <div className="inner">
          <a href="/" className="brand" style={{textDecoration: 'none'}}>
            <span className="mark"/>
            <span>Neuron</span>
            <span className="v">v0.4</span>
          </a>
          <div style={{display: 'flex', alignItems: 'center', gap: 12}}>
            <span className="pill">Mainnet</span>
            {wallet && (
              <button
                className="wallet-chip wallet-chip-btn"
                onClick={async () => {
                  try { await wallet.provider?.disconnect?.(); } catch {}
                  setWallet(null);
                  setView('config');
                }}
                title="Disconnect"
              >
                <span className="dot"/>
                {wallet.name} · {wallet.addr}
                <span className="disconnect-x">×</span>
              </button>
            )}
          </div>
        </div>
      </nav>

      {!wallet && <WalletModal onConnect={onConnect} />}

      <div className="try-page">
        {view === 'config' && wallet && (
          <>
            <div className="try-head">
              <h1>Configure your launch.<br/><em>Hand off to the agent.</em></h1>
              <p>Tell Neuron what to build. The agent runs research, names the coin,
              ships the site, and mints — usually a few minutes end-to-end.</p>
            </div>
            <ConfigView
              vibe={vibe} setVibe={setVibe}
              venue={venue} setVenue={setVenue}
              treasury={treasury} setTreasury={setTreasury}
              fee={fee} setFee={setFee}
              onDeploy={onDeploy}
            />
          </>
        )}

        {view === 'running' && (
          <>
            <div className="try-head">
              <h1>Agent is cooking.<br/><em>Take a coffee.</em></h1>
              <p>The pipeline runs through research, naming, domain, site, treasury,
              and mint. You can cancel any time before the deploy tx fires.</p>
            </div>
            <RunView config={config} onComplete={onComplete} onCancel={onCancel} />
          </>
        )}

        {view === 'complete' && coin && (
          <>
            <div className="try-head">
              <h1>Handoff complete.<br/><em>Your coin is live.</em></h1>
              <p>The agent shipped everything end to end. You're the mint authority
              on Solana, the domain is registered to you, and the site repo is under
              your account.</p>
            </div>
            <CompleteView coin={coin} config={config} onAnother={onAnother} />
          </>
        )}
      </div>
    </div>
  );
}

ReactDOM.createRoot(document.getElementById('root')).render(<TryApp/>);
