// U.Plane — product landing
const { useState, useEffect } = React;

const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "palette": "paper"
}/*EDITMODE-END*/;

const BRANDS = {
  uplane: {
    name: "U.Plane",
    glyph: "∥",
    eyebrow: "U.PLANE · v1.0 · LOCAL AI SUBSTRATE",
    h1: <>The same everything,<br/><em>everywhere</em></>,
    tagline: "Connect every AI platform to your machine. One memory, one context, one substrate.",
    lede: "Same memory. Same capabilities. Same access. Same context. Same skills — across every AI conversation, every platform, every place. Even agents with no native path to your machine. Sovereign by architecture: your machine, no APIs, no cloud.",
    title: "U.Plane — the same everything, everywhere"
  }
};

// ──────────────────────────────────────────────────────────────
// Install terminal (animated)
// ──────────────────────────────────────────────────────────────
function Terminal({ name }) {
  const lines = [
    { t: 'prompt', body: '> .\\start.bat' },
    { t: 'out', body: '' },
    { t: 'out', body: `${name} · onboarding` },
    { t: 'dim', body: '─────────────────────────────────' },
    { t: 'ok',  body: '✓ Node.js 20.11.0 detected' },
    { t: 'ok',  body: '✓ Backend config created · port 9001' },
    { t: 'ok',  body: '✓ Bridge dependencies installed' },
    { t: 'out', body: 'Set elevation phrases? (one per level, blank to skip)' },
    { t: 'cmd', body: '  operator  > "switch operator"' },
    { t: 'cmd', body: '  sovereign > "i authorize sovereign"' },
    { t: 'ok',  body: '✓ Phrases hashed with argon2id' },
    { t: 'ok',  body: '✓ Backend listening on 127.0.0.1:9001' },
    { t: 'ok',  body: '✓ /health 200 OK' },
    { t: 'dim', body: '─────────────────────────────────' },
    { t: 'prompt', body: 'READY' },
    { t: 'out', body: '  url      http://127.0.0.1:9001' },
    { t: 'out', body: '  level    workspace' },
    { t: 'out', body: '  clients  point any AI platform at this folder' },
    { t: 'cursor', body: '' }
  ];
  const [shown, setShown] = useState(0);
  useEffect(() => {
    if (shown >= lines.length) return;
    const id = setTimeout(() => setShown(s => s + 1), shown < 3 ? 260 : 160);
    return () => clearTimeout(id);
  }, [shown]);
  return (
    <div className="terminal">
      <div className="terminal-bar">
        <span className="light r"/><span className="light y"/><span className="light g"/>
        <span className="title">{name.toLowerCase()} · install</span>
      </div>
      <div className="terminal-body">
        {lines.slice(0, shown).map((l, i) => {
          if (l.t === 'cursor') return <span key={i} className="cursor"/>;
          const cls = l.t === 'prompt' ? 't-prompt' : l.t === 'cmd' ? 't-cmd' : l.t === 'ok' ? 't-ok' : l.t === 'warn' ? 't-warn' : l.t === 'dim' ? 't-dim' : 't-out';
          return <span key={i} className={`tline ${cls}`}>{l.body || '\u00A0'}</span>;
        })}
      </div>
    </div>
  );
}

// ──────────────────────────────────────────────────────────────
// Sections
// ──────────────────────────────────────────────────────────────
function Hero({ brand }) {
  const b = BRANDS[brand] || BRANDS.uplane;
  return (
    <section className="hero" data-screen-label="01 Hero">
      <div className="app">
        <div className="hero-grid">
          <div>
            <div className="eyebrow"><span className="dot"/>{b.eyebrow}</div>
            <h1 className="brand-h1">{b.h1}</h1>
            <p className="tagline">{b.tagline}</p>
            <p className="mono dim" style={{marginBottom: '20px', maxWidth: '52ch'}}>MCP is the protocol your AI tools use to talk to local programs. U.Plane is the one they all share.</p>
            <p className="lede">{b.lede}</p>
            <div className="hero-cta">
              <a className="btn primary" href="#pricing"><span>Subscribe — first month free</span><span className="arrow">↓</span></a>
              <a className="btn ghost" href="#install">How the install runs <span className="arrow">↓</span></a>
            </div>
            <p className="hero-meta-line"><b>The AI does the install.</b> Hand the kit to any MCP-capable AI — Claude Code, Cursor, Codex, Gemini CLI, Antigravity, Cowork. It asks four short questions, runs the install end-to-end, prints <span className="mono" style={{color:'var(--ok)'}}>READY</span>.</p>
            <div className="hero-meta">
              <span><b>Commercial license</b> · per developer</span>
              <span><b>Windows x64</b> · Node 18+ · Python optional</span>
              <span><b>Mac / Linux</b> on the roadmap</span>
            </div>
          </div>
          <Terminal name={b.name} />
        </div>
      </div>
    </section>
  );
}

function FounderBand() {
  return (
    <section data-screen-label="00 Founder">
      <div className="app">
        <div className="reach-band">
          <div className="reach-mark">▲</div>
          <div className="reach-body">
            <span className="reach-eyebrow">BUILT BY ONE PERSON</span>
            <h3>4000+ hours · 9+ months · <em>solo, unfunded.</em></h3>
            <p>No board, no roadmap that isn't yours. v1.0 ships today. If you back the founder now, the founder remembers.</p>
          </div>
        </div>
      </div>
    </section>
  );
}

function Problem() {
  return (
    <section data-screen-label="02 Problem">
      <div className="app">
        <div className="section-head">
          <span className="num">§ 01 · Continuity</span>
          <h2>Every chat picks up where the <em>last one</em> ended.</h2>
          <p className="head-cap">Your project's to-do list, work log, decisions, and conventions — maintained by the plane between sessions, read by every model on arrival. Plan a refactor in Cursor at 10am; implement it in Claude Code at 3pm with the plan already loaded. Sketch a feature in your browser at lunch; pick it up on your phone on the train home. Every new chat opens to a project already in progress.</p>
        </div>
        <div className="reach-band">
          <div className="reach-mark">◎</div>
          <div className="reach-body">
            <span className="reach-eyebrow">REACH</span>
            <h3>Filesystem and memory — <em>even in the browser. Even on the phone.</em></h3>
            <p>The plane gives capabilities to platforms that never had them. Web clients and mobile chats hit the same local substrate as your desktop tools. One brain. Every surface. Every device.</p>
          </div>
        </div>
      </div>
    </section>
  );
}

function Architecture() {
  return (
    <section data-screen-label="03 Architecture">
      <div className="app">
        <div className="section-head">
          <span className="num">§ 02 · How it sits</span>
          <h2>One backend. One bridge. <em>One spine.</em></h2>
          <p className="head-cap">Every platform points at the same address. Every conversation reads the same memory. Every elevation runs through the same gate.</p>
        </div>
        <div className="arch-diagram">
          <div className="arch-row orchestrator">
            <span className="arch-pill paperclip">Paperclip · multi-agent orchestrator <span className="opt">optional</span></span>
          </div>
          <div className="arch-cap subtle">↓ routes work to the clients below</div>
          <div className="arch-row clients">
            <span className="arch-pill client">claude code</span>
            <span className="arch-pill client">cursor</span>
            <span className="arch-pill client">vs code</span>
            <span className="arch-pill client">codex</span>
            <span className="arch-pill client">gemini cli</span>
            <span className="arch-pill client">antigravity</span>
            <span className="arch-pill client">cowork</span>
            <span className="arch-pill client">openclaw</span>
          </div>
          <div className="arch-cap">8 AI surfaces</div>
          <div className="arch-row"><span className="arch-arrow">↓</span></div>
          <div className="arch-row"><span className="arch-pill bridge">MCP bridge</span></div>
          <div className="arch-row"><span className="arch-arrow">↓</span></div>
          <div className="arch-row"><span className="arch-pill core">local backend · 127.0.0.1:9001</span></div>
          <div className="arch-row"><span className="arch-arrow">↓</span></div>
          <div className="arch-row layers">
            <span className="arch-pill layer">session</span>
            <span className="arch-pill layer">memory</span>
            <span className="arch-pill layer">verify</span>
            <span className="arch-pill layer">runtime</span>
            <span className="arch-pill layer">body</span>
            <span className="arch-pill layer">project</span>
            <span className="arch-pill layer">person</span>
            <span className="arch-pill layer">claims</span>
            <span className="arch-pill layer">coordination</span>
          </div>
          <div className="arch-cap">9 tool groups · 32 tools · one normalized contract</div>
        </div>
      </div>
    </section>
  );
}

function Layers() {
  const layers = [
    { n: '01', name: 'Session', desc: 'Loads prior state on connect, appends per-action worklog, seals on close.' },
    { n: '02', name: 'Memory', desc: 'Full-text local store with browse + read + delete. No vector DB. No external deps.' },
    { n: '03', name: 'Verification', desc: 'Structural lint on drafts and final text. Stops broken output shipping.' },
    { n: '04', name: 'Runtime', desc: 'Substrate health, restart, and phrase-gated access-tier elevation.' },
    { n: '05', name: 'Body', desc: 'OS actuation — files, shell, screen, keyboard, mouse, windows.' },
    { n: '06', name: 'Project', desc: 'A living knowledge document every model reads on arrival.' },
    { n: '07', name: 'Person', desc: 'Named identity + operational work-style preferences. Shared across every AI on this machine.' },
    { n: '08', name: 'Claims', desc: 'Persistent record of what the system asserted. Verified after the fact.' },
    { n: '09', name: 'Coordination', desc: 'Async channels for AI sessions on the same machine to leave each other messages.' }
  ];
  return (
    <section data-screen-label="04 Layers">
      <div className="app">
        <div className="section-head">
          <span className="num">§ 03 · Tool surface</span>
          <h2>Nine tool groups. <em>One contract.</em></h2>
          <p className="head-cap">No platform invents its own surface. Every client calls the same groups against the same backend. The bridge advertises only the tools the resolved tier permits — lower tiers see fewer tools (absent from the surface, not denied).</p>
        </div>
        <ul className="layers-list">
          {layers.map(l => (
            <li key={l.n} className="layer-row">
              <span className="layer-row-n">{l.n}</span>
              <span className="layer-row-name">{l.name}</span>
              <span className="layer-row-desc">{l.desc}</span>
            </li>
          ))}
        </ul>
      </div>
    </section>
  );
}

function Access() {
  const levels = [
    { lvl: 'observe', desc: 'Read-only inspection. No writes, no shell, no motor. Safe for evaluation and oversight.', pips: 1, perms: ['read'] },
    { lvl: 'workspace', desc: 'Default. File read/write and shell, jailed to allowed paths. Safe for everyday coding and refactoring.', pips: 2, perms: ['read', 'write'] },
    { lvl: 'operator', desc: 'Workspace + screenshot, mouse, keyboard, window read/write. For automation and serious co-work.', pips: 3, perms: ['read', 'write', 'shell', 'control'] },
    { lvl: 'sovereign', desc: 'Full local authority including substrate restart. For when you want the system to act as if it were you.', pips: 4, perms: ['read', 'write', 'shell', 'control', 'system'] }
  ];
  return (
    <section data-screen-label="05 Access">
      <div className="app">
        <div className="section-head">
          <span className="num">§ 04 · Authority</span>
          <h2>Four tiers. <em>The AI cannot raise its own level.</em></h2>
          <p className="head-cap">Default install is <span className="mono" style={{color:'var(--accent)'}}>workspace</span>. Elevation requires a phrase shipped predetermined inside the kit — hashed argon2id on first backend boot (the AI can verify a match but never sees or produces the phrase). The AI sees only <span className="mono" style={{color:'var(--accent)'}}>phrase_count</span>, never the phrase itself. You can customize or clear phrases via <span className="mono">scripts/setup-elevation.ps1</span>; an empty list keeps a level unreachable from chat.</p>
        </div>
        <ul className="access-list">
          {levels.map((l, i) => (
            <li key={l.lvl} className={`access-row tier-${l.lvl}`}>
              <span className="lvl"><span className="lvl-n">{String(i+1).padStart(2,'0')}</span><span className="lvl-name">{l.lvl}</span></span>
              <span className="desc">{l.desc}</span>
              <span className="perms">
                {l.perms.map(p => <span key={p} className={`perm perm-${p}`}>{p}</span>)}
              </span>
            </li>
          ))}
        </ul>
      </div>
    </section>
  );
}

function Install() {
  return (
    <section id="install" data-screen-label="06 Install">
      <div className="app">
        <div className="section-head">
          <span className="num">§ 05 · Install</span>
          <h2>Drop the folder. Point any AI at it. <em>READY</em> in under a minute.</h2>
          <p className="head-cap">One launcher does the bootstrap. The AI reads its installer file and wires itself. You authorize the elevation phrases and read the verdict.</p>
        </div>
        <div className="platform-strip">
          <span className="pp">Claude Code</span>
          <span className="pp">Cursor</span>
          <span className="pp">VS Code</span>
          <span className="pp">Codex</span>
          <span className="pp">Gemini CLI</span>
          <span className="pp">Antigravity</span>
          <span className="pp">Cowork</span>
          <span className="pp">OpenClaw</span>
          <span className="pp dim">+ anything MCP-capable</span>
        </div>
        <div className="install-grid">
          <ol className="install-steps">
            <li>
              <h4>Subscribe — get your personalized kit</h4>
              <p>PayPal redirects you to <span className="mono">uplane.host/download?sub=&lt;id&gt;</span>; the Worker injects your signed license token into <span className="mono">U.Plane-backend/license.token</span> and streams you the zip. ~34 MB. Compiled <span className="mono">server.exe</span>, bundled bridge, readable motor source, all docs.</p>
            </li>
            <li>
              <h4>Hand the kit to your AI</h4>
              <p>Open the extracted folder in any MCP-capable AI — Claude Code, Cursor, Codex, VS Code, Gemini CLI, Antigravity, Cowork. It reads its installer file (<span className="mono">CLAUDE.md</span>, <span className="mono">GEMINI.md</span>, <span className="mono">AGENTS.md</span>, <span className="mono">COWORK.md</span>), follows <span className="mono">INSTALLER_SPEC.md</span>, becomes the lifelong operator.</p>
            </li>
            <li>
              <h4>Answer four short questions</h4>
              <p>Your name. The install folder. Starting access tier (<span className="mono">observe</span> / <span className="mono">workspace</span> / <span className="mono">operator</span> / <span className="mono">sovereign</span>). Which AI clients to wire. Elevation phrases ship predetermined — you don't invent them at install.</p>
            </li>
            <li>
              <h4>The AI prints <span className="mono" style={{color:'var(--ok)'}}>READY</span> — or <span className="mono" style={{color:'var(--warn)'}}>BLOCKED</span> with the specific reason</h4>
              <p>One unambiguous verdict per run. If you'd rather drive setup yourself, <span className="mono">scripts/onboard.ps1</span> does the same thing. To wire more platforms later, <span className="mono">start.bat wire</span>.</p>
            </li>
          </ol>
          <div className="terminal" style={{marginTop: 8}}>
            <div className="terminal-bar">
              <span className="light r"/><span className="light y"/><span className="light g"/>
              <span className="title">PowerShell · daily use</span>
            </div>
            <div className="terminal-body">
              <span className="tline t-dim"># First run — Windows</span>
              <span className="tline t-prompt">&gt; .\start.bat</span>
              <span className="tline t-out">&nbsp;</span>
              <span className="tline t-dim"># Wire more platforms later</span>
              <span className="tline t-prompt">&gt; .\start.bat wire</span>
              <span className="tline t-out">&nbsp;</span>
              <span className="tline t-dim"># Non-interactive automation</span>
              <span className="tline t-prompt">&gt; powershell -File .\scripts\onboard.ps1 `</span>
              <span className="tline t-cmd">    -Clients "all" -AccessLevel workspace</span>
              <span className="tline t-out">&nbsp;</span>
              <span className="tline t-dim"># Verify backend health</span>
              <span className="tline t-prompt">&gt; .\scripts\health-check.ps1</span>
              <span className="tline t-ok">✓ /health 200 OK · 127.0.0.1:9001</span>
            </div>
          </div>
        </div>
      </div>
    </section>
  );
}

function Pricing() {
  const tiers = [
    {
      tier: 'Monthly',
      price: '€25',
      priceSub: '/ dev / month',
      sub: '1st month free · 2nd month €12.50 · cancel anytime',
      desc: 'Commercial use, billed monthly. Cancel from your PayPal account.',
      features: [
        'Commercial-use license',
        'All releases of the current major version',
        'All releases during your subscription',
        'Email support for install issues',
        'First month free, second month half off'
      ],
      paypalHost: 'paypal-monthly',
      highlight: false
    },
    {
      tier: 'Quarterly',
      price: '€65',
      priceSub: '/ dev / quarter',
      sub: '€21.67 / mo blended · €10 cheaper than 3 × monthly',
      desc: 'Commercial use, billed every three months. PayPal cancellation.',
      features: [
        'Commercial-use license',
        'All releases of the current major version',
        'All releases during your subscription',
        '30-day refund window',
        '€10 / quarter saved vs monthly'
      ],
      paypalHost: 'paypal-quarterly',
      highlight: false
    },
    {
      tier: 'Annual',
      price: '€235',
      priceSub: '/ dev / year',
      sub: '≈ €19.58 / mo · 12-month price lock',
      desc: 'Commercial use, billed yearly. About €65 cheaper than 12 × monthly.',
      features: [
        'Commercial-use license',
        'All releases of the current major version',
        'All releases during your subscription',
        '30-day refund window',
        '12-month price lock'
      ],
      paypalHost: 'paypal-annual',
      highlight: false
    },
    {
      tier: 'Founders',
      price: '€250+',
      priceSub: 'one-time · lifetime',
      sub: '10 of 10 spots remaining · ever · first-come, first-served',
      desc: 'One payment, forever. €15 more than Annual buys lifetime instead of one year. Closes permanently once the 10th seat is claimed.',
      features: [
        'Lifetime commercial-use license — every future release, every major version',
        'Lifetime price lock at €0 / year after this one payment',
        '€500+ unlocks 2 lifetime seats from one order (one to keep, one to gift)',
        'Founder credit in the kit footer',
        'Direct line to the maintainer (contact@uplane.host)',
        'Non-refundable: this is a founding donation, not a subscription trial'
      ],
      paypalHost: 'paypal-founders',
      highlight: true,
      badge: '10 of 10 remaining'
    }
  ];
  return (
    <section data-screen-label="07 Pricing">
      <div className="app">
        <div className="section-head">
          <span className="num">§ 06 · Commercial</span>
          <h2>Three subscriptions. <em>One founding tier.</em></h2>
          <p className="head-cap">Per developer. Pay monthly, quarterly, or yearly — or once, forever. <strong style={{color:'var(--accent)'}}>Founders' Tier closes at 10 seats and never re-opens.</strong> €15 more than Annual buys lifetime instead of one year.</p>
        </div>
        <div className="pricing-grid">
          {tiers.map(t => (
            <div key={t.tier} className={`price-card${t.highlight ? ' highlight' : ''}`}>
              {t.badge && <span className="price-badge">{t.badge}</span>}
              <div className="price-tier">{t.tier}</div>
              <div className="price-amount">
                <span className="price-val">{t.price}</span>
                {t.priceSub && <span className="price-unit">{t.priceSub}</span>}
              </div>
              <div className="price-sub">{t.sub}</div>
              <p className="price-desc">{t.desc}</p>
              <ul className="price-feats">
                {t.features.map(f => <li key={f}>{f}</li>)}
              </ul>
              <div id={t.paypalHost} className="paypal-host"></div>
            </div>
          ))}
        </div>
      </div>
    </section>
  );
}

function Faq() {
  const items = [
    ['Why pay €250 for the Founders\' Tier instead of €235 for Annual?', '€15 more than Annual buys lifetime instead of one year. You pay once, ever; every future release of every future major version is yours; no renewals to remember, no rate changes to dodge. 10 lifetime spots will ever exist — once claimed, the tier closes permanently and never re-opens. Founders also get credit in the kit footer and a direct line to the maintainer. €500+ unlocks 2 lifetime seats from one order (one to keep, one to gift).'],
    ['How does U.Plane compare to Mem0, Letta, Cursor\'s built-in memory, or OpenAI\'s memory?', 'Those are per-platform memory systems. They each work inside ONE AI client and stop at its boundary. U.Plane is the layer below — one local backend that EVERY platform talks to. Write a memory in Claude Code, find it in Cursor. Set an access tier once, every wired AI inherits it. U.Plane also bundles a substrate-tier of features the others don\'t carry: a shared project-knowledge document, an automatic action ledger with backup-before-mutate, a named-Person identity layer, inter-session coordination channels, and a phrase-gated access wall. If you only use one AI client, the per-platform memory is fine. The moment you use two, U.Plane pays for itself.'],
    ['Is my model provider key included?', 'No. The substrate is the local stack — memory, continuity, verification, optional motor. You bring your own model. The bridge talks to clients; the clients talk to providers.'],
    ['What actually runs on my machine?', 'A local HTTP backend on 127.0.0.1:9001 and a stdio MCP bridge that clients invoke on demand. No outbound calls from the substrate itself. The HTTP listener has no authentication — it trusts the OS account boundary and 127.0.0.1 binding. If you enable remote access via Tailscale, bearer-token auth is mandatory.'],
    ['Can the AI elevate its own access level?', 'No. The kit ships with predetermined elevation phrases that are hashed argon2id on first backend boot — the AI can verify a match but never sees or produces the phrase itself. The AI sees only the count and the prompt to ask you. If you leave a level\'s phrase list empty (via scripts/setup-elevation.ps1), that level is unreachable from chat — period.'],
    ['Why is the access-control layer open source but the substrate isn\'t?', 'The motor/ layer — body_gate.py, access_policy.py, body_motor.py — is the surface that decides what an AI can touch on your machine. Shipping it as readable source lets anyone audit tier enforcement and tool exposure without trusting an opaque binary. The substrate logic, memory engine, and continuity routing are the IP — they ship compiled in server.exe. Each shipped file\'s SHA-256 is published so you can verify your download.'],
    ['Refunds?', 'Monthly: first month is free, no charge. Quarterly and Annual: 30-day refund window from the most recent charge, handled by email. Founders\' Tier is non-refundable — it\'s a founding donation, not a subscription trial, and the seat-count drives the cap.'],
    ['Mac and Linux?', 'On the roadmap. Today the substrate ships as a Windows x64 binary. For pre-launch non-Windows installs, email contact@uplane.host.'],
    ['How is memory stored?', 'A local JSONL append-only store with full-text search via SQLite FTS5. No external database, no embedding model required. Bounded scan limit per request (default 200,000 lines) so latency stays predictable. Five memory operations: write, search, browse (no-keyword scroll), read (one row by id), delete (rollback an import batch).'],
    ['What if I overwrite something by accident?', 'Every body_file write/edit/append/move/delete and copy-overwrite auto-snapshots the prior bytes to runtime/_uplane_backups/ BEFORE the change, at every tier including sovereign. There is also a control-center folder the AI cannot write to via its file tool — that is your zone, managed directly by you. Recovery is the most recent .bak; the substrate keeps an audit ledger in _backups.log.'],
    ['Does the AI really do the install?', 'Yes. Open the kit folder in any MCP-capable agent. It reads its installer file (CLAUDE.md, GEMINI.md, AGENTS.md, COWORK.md), follows INSTALLER_SPEC.md, runs end-to-end, verifies, prints READY. You answer four short questions (name, folder, starting tier, which clients to wire). Elevation phrases ship predetermined — you don\'t invent them at install. If you\'d rather drive setup yourself, scripts/onboard.ps1 does the same thing.']
  ];
  return (
    <section data-screen-label="08 FAQ">
      <div className="app">
        <div className="section-head">
          <span className="num">§ 07 · FAQ</span>
          <h2>Questions that come up.</h2>
        </div>
        <div className="faq-list">
          {items.map(([q, a], i) => (
            <details key={i} className="faq-item">
              <summary className="faq-q">{q}<span className="plus">+</span></summary>
              <div className="faq-a">{a}</div>
            </details>
          ))}
        </div>
      </div>
    </section>
  );
}

function Cta({ brand }) {
  const b = BRANDS[brand] || BRANDS.uplane;
  return (
    <section data-screen-label="09 CTA">
      <div className="app">
        <div className="cta-band">
          <div>
            <h2>Run it locally. Keep the spine.</h2>
            <p>U.Plane v1.0 — Windows x64. Nine tool layers. Four phrase-gated authority tiers. Eight AI surfaces pre-wireable. The bridge advertises only the tools the current tier permits; the AI cannot raise its own authority; the files that define its authority cannot be rewritten by its own tools at any tier. Your memory, your identity, your project knowledge stay on your disk.</p>
            <div className="actions">
              <a className="btn primary" href="#pricing">Subscribe <span className="arrow">↓</span></a>
              <a className="btn ghost" href="#install">Install flow</a>
              <a className="btn ghost" href="mailto:contact@uplane.host">Commercial license</a>
            </div>
          </div>
          <div className="support-col">
            <div className="support-head">Built by one person</div>
            <p>U.Plane is built and maintained independently by Gonçalo Mattos Parreira — 4000+ hours, 9+ months, solo, unfunded. No board, no roadmap that isn't yours. If you back the founder now, the founder remembers.</p>
            <div className="support-links">
              <a href="https://ko-fi.com/goncalo001" target="_blank" rel="noreferrer">Ko-fi ↗</a>
            </div>
            <div className="lic">
              Commercial use: <a href="mailto:contact@uplane.host">contact@uplane.host</a><br/>
              <span style={{color:'var(--dim)'}}>© 2026 Gonçalo Mattos Parreira</span>
            </div>
          </div>
        </div>
      </div>
    </section>
  );
}

function Foot({ brand }) {
  const b = BRANDS[brand] || BRANDS.uplane;
  return (
    <footer className="foot">
      <div className="app">
        <div className="foot-inner">
          <div className="foot-mark">
            <span className="glyph">{b.glyph}</span>
            <span>{b.name}</span>
            <span className="dim mono">v1.0 · Windows x64</span>
          </div>
          <div className="foot-links">
            <a href="#install">Install</a>
            <a href="mailto:contact@uplane.host">Contact</a>
          </div>
        </div>
      </div>
    </footer>
  );
}

window.UPlane = { Hero, FounderBand, Problem, Architecture, Layers, Access, Install, Pricing, Faq, Cta, Foot, BRANDS };
