// Orbix Core site pages
// React hooks are exposed as globals from index.html.

// ============================================================
// Shared page header
// ============================================================
function PageHeader({ eyebrow, title, soft, body }) {
  return (
    <header className="page-header">
      <div className="section-eyebrow mono">
        <span className="eyebrow-dot" /> {eyebrow}
      </div>
      <h1 className="page-title">
        {title} {soft && <span className="section-title-soft">{soft}</span>}
      </h1>
      {body && <p className="page-body">{body}</p>}
    </header>
  );
}

// ============================================================
// VISION
// ============================================================
// Minimal line glyphs, one per principle.
const PrincipleIcon = ({ kind }) => {
  const stroke = 'currentColor';
  const sw = 1.4;
  const icons = {
    // 01 - Modular: three small connected squares
    modular: (
      <g fill="none" stroke={stroke} strokeWidth={sw} strokeLinecap="round" strokeLinejoin="round">
        <rect x="10" y="10" width="14" height="14" />
        <rect x="40" y="10" width="14" height="14" />
        <rect x="25" y="40" width="14" height="14" />
        <line x1="17" y1="24" x2="32" y2="40" />
        <line x1="47" y1="24" x2="32" y2="40" />
      </g>
    ),
    // 02 - Local: a small terminal prompt
    local: (
      <g fill="none" stroke={stroke} strokeWidth={sw} strokeLinecap="round" strokeLinejoin="round">
        <rect x="10" y="14" width="44" height="36" rx="2" />
        <polyline points="20,28 26,34 20,40" />
        <line x1="32" y1="40" x2="44" y2="40" />
      </g>
    ),
    // 03 - Green LLM: a single tiny sprout
    green: (
      <g fill="none" stroke={stroke} strokeWidth={sw} strokeLinecap="round" strokeLinejoin="round">
        <line x1="32" y1="52" x2="32" y2="30" />
        <path d="M32 36 C 22 36, 18 28, 18 22 C 26 22, 32 26, 32 36 Z" />
        <path d="M32 30 C 42 30, 46 22, 46 16 C 38 16, 32 20, 32 30 Z" />
        <path d="M22 52 L 42 52" />
      </g>
    ),
    // 04 - Autonomous: a circle with a dot (autonomous loop)
    autonomous: (
      <g fill="none" stroke={stroke} strokeWidth={sw} strokeLinecap="round" strokeLinejoin="round">
        <path d="M48 20 A 18 18 0 1 0 52 36" />
        <polyline points="48,12 48,20 56,20" />
        <circle cx="32" cy="32" r="3" fill={stroke} stroke="none" />
      </g>
    ),
    // 05 - Privacy: a small shield outline
    privacy: (
      <g fill="none" stroke={stroke} strokeWidth={sw} strokeLinecap="round" strokeLinejoin="round">
        <path d="M32 10 L 50 16 L 50 32 C 50 44, 42 50, 32 54 C 22 50, 14 44, 14 32 L 14 16 Z" />
        <circle cx="32" cy="30" r="3" />
        <line x1="32" y1="33" x2="32" y2="40" />
      </g>
    ),
    // 06 - No surveillance: an eye with a strike
    surveil: (
      <g fill="none" stroke={stroke} strokeWidth={sw} strokeLinecap="round" strokeLinejoin="round">
        <path d="M10 32 C 18 22, 26 20, 32 20 C 38 20, 46 22, 54 32 C 46 42, 38 44, 32 44 C 26 44, 18 42, 10 32 Z" />
        <circle cx="32" cy="32" r="4" />
        <line x1="14" y1="14" x2="50" y2="50" />
      </g>
    ),
  };
  return (
    <svg viewBox="0 0 64 64" className="principle-icon" aria-hidden="true">
      {icons[kind]}
    </svg>
  );
};

function GreenLLMScene_unused() {
  return (
    <div className="green-scene" aria-hidden="true">
      <svg viewBox="0 0 600 220" preserveAspectRatio="xMidYMax meet" className="green-scene-svg">
        <defs>
          {/* Light/shadow palette tied to the analog accent */}
          <linearGradient id="sky" x1="0" y1="0" x2="0" y2="1">
            <stop offset="0%" stopColor="oklch(0.94 0.04 60)" />
            <stop offset="100%" stopColor="oklch(0.92 0.05 50)" />
          </linearGradient>
        </defs>

        {/* Sky */}
        <rect x="0" y="0" width="600" height="220" fill="url(#sky)" />

        {/* Distant low-poly hill */}
        <polygon points="0,170 80,135 160,150 240,125 320,140 400,120 480,135 600,118 600,180 0,180" fill="oklch(0.78 0.10 70)" />
        <polygon points="0,180 80,135 160,150 80,180" fill="oklch(0.72 0.11 65)" />
        <polygon points="160,150 240,125 320,140 240,180" fill="oklch(0.72 0.11 65)" />
        <polygon points="320,140 400,120 480,135 400,180" fill="oklch(0.72 0.11 65)" />
        <polygon points="480,135 600,118 600,180 480,180" fill="oklch(0.72 0.11 65)" />

        {/* Foreground hill (warm sand) */}
        <polygon points="0,200 60,180 130,190 210,175 300,185 380,170 460,180 540,172 600,182 600,220 0,220" fill="oklch(0.86 0.06 70)" />
        <polygon points="0,220 60,180 130,190 130,220" fill="oklch(0.80 0.07 65)" />
        <polygon points="210,175 300,185 380,170 300,220 210,220" fill="oklch(0.80 0.07 65)" />
        <polygon points="460,180 540,172 600,182 600,220 460,220" fill="oklch(0.80 0.07 65)" />

        {/* Sun - coral analog accent */}
        <g transform="translate(490, 60)">
          <polygon points="0,-22 19,-11 19,11 0,22 -19,11 -19,-11" fill="oklch(0.66 0.18 35)" />
          <polygon points="0,-22 19,-11 0,0 -19,-11" fill="oklch(0.74 0.16 40)" />
          <polygon points="-19,-11 0,0 -19,11" fill="oklch(0.62 0.18 30)" />
        </g>

        {/* Tiny pine tree (left) */}
        <g transform="translate(70, 175)">
          <polygon points="0,0 -10,-22 10,-22" fill="oklch(0.55 0.12 145)" />
          <polygon points="0,0 -10,-22 0,-22" fill="oklch(0.48 0.13 145)" />
          <polygon points="0,-12 -8,-32 8,-32" fill="oklch(0.58 0.13 150)" />
          <polygon points="0,-12 -8,-32 0,-32" fill="oklch(0.50 0.14 145)" />
          <rect x="-2" y="0" width="4" height="6" fill="oklch(0.42 0.06 50)" />
        </g>

        {/* Sapling (centerish) */}
        <g transform="translate(180, 188)">
          <rect x="-1.5" y="0" width="3" height="8" fill="oklch(0.45 0.06 50)" />
          <polygon points="-7,-2 0,-12 7,-2 0,2" fill="oklch(0.62 0.14 145)" />
          <polygon points="-7,-2 0,-12 0,2" fill="oklch(0.55 0.15 145)" />
        </g>

        {/* Grass tufts (low-poly diamonds + spikes) */}
        {[
          [25, 198], [50, 200], [115, 196], [155, 199],
          [240, 195], [275, 198], [340, 194], [375, 197],
          [420, 195], [455, 198], [510, 196], [545, 199], [580, 195]
        ].map(([cx, cy], i) => (
          <g key={i} transform={`translate(${cx}, ${cy})`}>
            <polygon points="0,-6 -4,2 4,2" fill="oklch(0.62 0.14 145)" />
            <polygon points="0,-6 -4,2 0,2" fill="oklch(0.55 0.15 145)" />
            <polygon points="-3,-3 -7,3 1,3" fill="oklch(0.66 0.13 150)" />
          </g>
        ))}

        {/* Mushroom (warm accent) */}
        <g transform="translate(265, 196)">
          <rect x="-1.5" y="-2" width="3" height="6" fill="oklch(0.92 0.02 60)" />
          <polygon points="-7,-2 0,-9 7,-2" fill="oklch(0.66 0.18 35)" />
          <polygon points="-7,-2 0,-9 0,-2" fill="oklch(0.74 0.16 40)" />
          <circle cx="-3" cy="-4" r="1" fill="oklch(0.94 0.03 60)" />
          <circle cx="2" cy="-5" r="0.8" fill="oklch(0.94 0.03 60)" />
        </g>

        {/* Larger plant (right) */}
        <g transform="translate(400, 188)">
          <rect x="-1.5" y="0" width="3" height="10" fill="oklch(0.45 0.07 50)" />
          <polygon points="0,-2 -10,-8 -3,-12 0,-2" fill="oklch(0.60 0.15 145)" />
          <polygon points="0,-2 -10,-8 -3,-12" fill="oklch(0.52 0.16 145)" />
          <polygon points="0,-4 10,-10 4,-14 0,-4" fill="oklch(0.62 0.14 150)" />
          <polygon points="0,-4 10,-10 4,-14" fill="oklch(0.55 0.15 145)" />
          <polygon points="-3,-13 0,-22 3,-13" fill="oklch(0.66 0.13 145)" />
          <polygon points="-3,-13 0,-22 0,-13" fill="oklch(0.58 0.14 145)" />
        </g>

        {/* Pebbles */}
        <polygon points="100,212 108,208 114,213 108,216" fill="oklch(0.78 0.04 60)" />
        <polygon points="100,212 108,208 108,216" fill="oklch(0.72 0.05 55)" />
        <polygon points="320,210 326,206 332,211 326,213" fill="oklch(0.78 0.04 60)" />
        <polygon points="475,212 482,208 488,212 482,215" fill="oklch(0.78 0.04 60)" />
      </svg>
      <div className="green-scene-caption mono">
        <span className="status-dot" /> a small system, growing
      </div>
    </div>
  );
}

function VisionPage() {
  const phases = [
    { n: '01', title: 'Build', body: 'Bob designs the workflow with you in plain English. Modular components: prompts, validators, secure relay, conditions. Built once, audited once.' },
    { n: '02', title: 'Scale', body: 'Reuse what already works. Components compose. The same secure-relay node that ships marketing copy redacts invoices tomorrow. No rewrites.' },
    { n: '03', title: 'Autonomous', body: 'Validated workflows run without supervision. Validators catch drift. Secure relay handles privacy. You design, the system runs.' },
  ];
  const principles = [
    { n: '01', title: 'Modular by design.', body: 'Reusable components, composable workflows. Build once, run forever, recombine for the next problem.' },
    { n: '02', title: 'Local by default.', body: 'Your own computer is the runtime. Inference, memory, and orchestration on-device. Cloud is a guest, never a host.' },
    { n: '03', title: 'Green LLM.', body: 'The cheapest token is the one not sent. Smart routing, prompt caching, deduplication. Day one: less waste. Year one: a fraction.' },
    { n: '04', title: 'Autonomous, validated.', body: 'A council of validators reviews every output. Sandboxed, diffed, approved. Reliability is the feature.' },
    { n: '05', title: 'Private by default.', body: 'Everything runs on your machine. When a step opts into the cloud, Secure Relay strips personal data first, so the cloud never sees who it belongs to.' },
    { n: '06', title: 'No surveillance economics.', body: 'No telemetry. No analytics SDKs. The app is free, and your keys, your spend, and your data stay yours.' },
  ];

  return (
    <article className="page">
      <PageHeader
        eyebrow="VISION"
        title="Build it once."
        soft="Scale it. Let it run."
        body="Orbix Core is not just local AI. It is a generic, modular way to build, scale, and run AI systems that stay efficient as they grow, and stay private the whole way."
      />

      <section className="phases">
        <div className="section-eyebrow mono"><span className="eyebrow-dot" /> THE LIFECYCLE</div>
        <h2 className="section-title">Three phases.<br /><span className="section-title-soft">One system that supports all of them.</span></h2>
        <div className="phases-grid">
          {phases.map((p, i) => (
            <article key={p.n} className="phase">
              <span className="phase-n mono">{p.n}</span>
              <h3 className="phase-title">{p.title}</h3>
              <p className="phase-body">{p.body}</p>
              {i < phases.length - 1 && <span className="phase-arrow mono">→</span>}
            </article>
          ))}
        </div>
      </section>

      <section className="green">
        <div className="green-grid">
          <div>
            <div className="section-eyebrow mono"><span className="eyebrow-dot" /> GREEN LLM</div>
            <h2 className="section-title">The cheapest token<br /><span className="section-title-soft">is the one not sent.</span></h2>
            <p className="section-body">
              Big cloud models burn energy and budget on routine work that a small local model handles just as well. Orbix runs small, efficient models on your own hardware and saves the heavy reasoning for the steps that truly need it. Prompt caching and workflow memory mean repeat runs get cheaper, not costlier.
            </p>
          </div>
          <div className="green-meter">
            <div className="green-meter-frame mono">
              <span>where work runs</span>
              <span>share</span>
            </div>
            <div className="green-rows">
              {[
                ['routine', 85, 'small local model'],
                ['reasoning', 12, 'larger local model'],
                ['cloud', 3, 'only if you allow, redacted first'],
              ].map(([k, pct, note]) => (
                <div key={k} className="green-row">
                  <span className="green-k mono">{k}</span>
                  <div className="green-bar"><span style={{ width: `${pct}%` }} /></div>
                  <span className="green-pct mono">{pct}%</span>
                  <span className="green-note">{note}</span>
                </div>
              ))}
            </div>
          </div>
        </div>
      </section>

      <section className="manifesto">
        <div className="manifesto-quote">
          <span className="quote-mark mono">"</span>
          <p>The next decade of AI will not be won by the largest models. It will be won by the systems that respect the people who use them, and the planet that runs them.</p>
          <span className="quote-attr mono">orbix core // founding principle</span>
        </div>
      </section>

      <section className="principles">
        <div className="section-eyebrow mono" style={{ marginBottom: 24 }}><span className="eyebrow-dot" /> SIX PRINCIPLES</div>
        <div className="principles-grid principles-grid-3">
          {principles.map((p, i) => {
            const kinds = ['modular', 'local', 'green', 'autonomous', 'privacy', 'surveil'];
            return (
              <article key={p.n} className="principle">
                <div className="principle-icon-wrap">
                  <PrincipleIcon kind={kinds[i]} />
                </div>
                <span className="principle-n mono">{p.n}</span>
                <h3 className="principle-title">{p.title}</h3>
                <p className="principle-body">{p.body}</p>
              </article>
            );
          })}
        </div>
      </section>

      <section className="vs">
        <div className="section-eyebrow mono"><span className="eyebrow-dot" /> THE CONTRAST</div>
        <h2 className="section-title">Two ways to ship AI.<br /><span className="section-title-soft">We picked the harder one.</span></h2>
        <div className="vs-table">
          <div className="vs-row vs-head mono">
            <span></span>
            <span>cloud-first</span>
            <span>orbix core</span>
          </div>
          {[
            ['data location', 'their servers', 'your machine'],
            ['inference', 'remote api', 'on-device'],
            ['cost model', 'per-token', 'free'],
            ['energy use', 'datacenter scale', 'laptop scale'],
            ['offline', 'no', 'yes'],
            ['audit trail', 'opaque', 'on-device log'],
            ['personal data to cloud', 'as sent', 'redacted first'],
            ['training on your data', 'often', 'never'],
          ].map(([k, a, b]) => (
            <div key={k} className="vs-row">
              <span className="vs-k mono">{k}</span>
              <span className="vs-a">{a}</span>
              <span className="vs-b">{b}</span>
            </div>
          ))}
        </div>
      </section>

      <CTA />
    </article>
  );
}

// ============================================================
// PRODUCTS
// ============================================================
function ProductsPage() {
  const [open, setOpen] = useState(() => new Set());
  const toggle = (id) => setOpen((prev) => {
    const next = new Set(prev);
    if (next.has(id)) next.delete(id); else next.add(id);
    return next;
  });

  const sections = [
    {
      pair: 'intro',
      span: true,
      cards: [
        {
          id: 'product',
          tag: '01',
          title: 'Product',
          body: 'Orbix Core runs AI locally on your own computer. It is model-agnostic: download from a built-in library or add any open model you like, and it runs on-device with GPU acceleration. Chat with Bob, build workflows visually, and manage agents, all without an internet connection.',
          expandLabel: "What's included",
          expand: (
            <ul className="prod-list">
              <li><strong>Local-First AI</strong> any open model runs on-device: download from the built-in library or add your own, vision models read images and PDFs.</li>
              <li><strong>Bob Orchestrator</strong> describe what you want, Bob designs workflows and creates agents.</li>
              <li><strong>Visual Builder</strong> drag-and-drop canvas with prompt, action, condition, loop, and relay nodes.</li>
              <li><strong>Secure Relay</strong> privacy bridge that strips personal data before sending to the cloud when needed.</li>
              <li><strong>Data Control</strong> confidential folders with per-agent permissions and access logging.</li>
              <li><strong>Pre-Flight Simulation</strong> agents evaluate changes in a sandbox before committing.</li>
              <li><strong>Window Intelligence</strong> Orbix reads any native, Electron, or browser app and operates it like a colleague.</li>
            </ul>
          ),
        },
        {
          id: 'philosophy',
          tag: '02',
          title: 'Work philosophy',
          body: 'The goal is not more tools. The goal is less friction. Orbix Core takes repetitive work off your plate so you can focus on decisions, creativity, and outcomes.',
          expandLabel: 'What this changes day to day',
          expand: (
            <p>
              Fewer manual checklists. Less switching between tabs. Less chasing updates. More time spent on the work that only you can do.
              Automation should support people, not obscure responsibility.
            </p>
          ),
        },
      ],
    },
    {
      pair: 'context',
      cards: [
        {
          id: 'window',
          tag: '03',
          title: 'Window Intelligence',
          body: 'Orbix reads the accessibility tree of any native, Electron, or browser application. It builds a living semantic twin that updates as the application state changes. Agents can read fields, write data, and trigger actions across any window, turning applications that were never integrated into a connected workflow.',
          expandLabel: 'How it works under the hood',
          expand: (
            <ul className="prod-list">
              <li><strong>Accessibility layer</strong> AX on macOS, UI Automation on Windows, plus DOM for browser and Electron windows.</li>
              <li><strong>Vision fallback</strong> when AX is unavailable, on-device vision reads the rendered UI directly.</li>
              <li><strong>Action layer</strong> click / type / read primitives at the OS level, no app-specific plugins.</li>
              <li><strong>Permissions</strong> per-app, revocable, every action logged.</li>
            </ul>
          ),
        },
        {
          id: 'governance',
          tag: '04',
          title: 'Built-in governance',
          body: 'Governance is not an afterthought. Orbix Core keeps access structured, execution reviewable, and outputs traceable. Because everything runs where you can see it, you stay in control.',
          expandLabel: 'How it stays observable',
          expand: (
            <ul className="prod-list">
              <li><strong>On-device by default</strong> data stays on your machine unless you choose to send it.</li>
              <li><strong>Secure Relay</strong> strips personal data before any cloud call.</li>
              <li><strong>Audit log</strong> an append-only record of what ran, kept locally.</li>
              <li><strong>Access control</strong> role-based folder access and per-agent permissions.</li>
            </ul>
          ),
        },
      ],
    },
    {
      pair: 'adopt',
      cards: [
        {
          id: 'incremental',
          tag: '05',
          title: 'Incremental adoption',
          body: 'Switching systems does not have to mean a six-month project. Import data by pasting a CSV. Connect a live sync when you are ready. Measure adoption as you go, and only cut over when the numbers say it is time.',
          expandLabel: 'How the transition works',
          expand: (
            <ol className="prod-list prod-list-ol">
              <li>Paste a CSV or connect a read-only sync, agents start working against your data immediately.</li>
              <li>Run shadow workflows in parallel with your existing tools, no production impact.</li>
              <li>Track time saved, error rates, and cost per task in the dashboard.</li>
              <li>Cut over module by module when you decide the numbers justify it.</li>
            </ol>
          ),
        },
        {
          id: 'takeover',
          tag: '06',
          title: 'Automation takeover',
          body: 'Already have workflows and automations running elsewhere? Orbix discovers them, analyzes complexity and cost, then migrates them with shadow-mode validation, your new automations run alongside the old ones until parity is confirmed.',
          expandLabel: 'Zero-downtime migration',
          expand: (
            <ul className="prod-list">
              <li><strong>Discover</strong> point Orbix at your Zapier / Make / n8n account, it inventories every flow.</li>
              <li><strong>Analyse</strong> complexity, monthly cost, failure rate, recommended Orbix equivalent.</li>
              <li><strong>Shadow run</strong> Orbix executes the new version in parallel, diffs the outputs.</li>
              <li><strong>Cut over</strong> only when the diffs are clean. Old workflow stays available as a rollback.</li>
            </ul>
          ),
        },
      ],
    },
    {
      pair: 'scale',
      span: true,
      cards: [
        {
          id: 'scale',
          tag: '07',
          title: 'What you thought was the future is now',
          body: 'Agents can run on one device with Orbix Core, then scale to multiple cores as your work grows. You can organize agents into a hierarchy, coordinate outputs through an agent council, and monitor activity across systems. Every output is reviewed by specialized validators before it ships, data integrity, business rules, and cost efficiency checked in parallel.',
          expandLabel: 'How teams scale this',
          expand: (
            <ul className="prod-list">
              <li><strong>One computer</strong> single-user, single-device, fully local, the default.</li>
              <li><strong>Team mesh</strong> multiple devices share a workflow library, each runs locally, audit logs aggregate.</li>
              <li><strong>Agent council</strong> validators review every output. Data integrity, business rules, cost: all checked in parallel.</li>
              <li><strong>Hierarchies</strong> coordinator agents delegate to specialists, every step is visible in the timeline.</li>
            </ul>
          ),
        },
      ],
    },
    {
      pair: 'platform',
      cards: [
        {
          id: 'modules',
          tag: '08',
          title: 'One platform, all modules',
          body: 'CRM, Finance, ERP, and Support are not separate products bolted together. They share the same data layer, the same user model, and the same governance rules. A contact in CRM is the same contact in Support. An invoice in Finance ties back to the deal in CRM.',
          expandLabel: 'Why this matters',
          expand: (
            <p>
              You stop reconciling. You stop importing CSVs between tools. A single record updates everywhere it appears, and every change carries the same audit trail. Reporting becomes one query, not five exports.
            </p>
          ),
        },
        {
          id: 'embedded',
          tag: '09',
          title: 'Embedded inside Orbix Core',
          body: 'Orbix Systems is no longer a separate web app. It opens as a panel directly inside Orbix Core. Your data, records, and agent activity, all accessible from one application without switching windows.',
          expandLabel: 'The integrated architecture',
          expand: (
            <ul className="prod-list">
              <li><strong>Single binary</strong> Core and Systems ship together, one install, one update channel.</li>
              <li><strong>Shared kernel</strong> the same orchestrator that drives agents drives the data panel.</li>
              <li><strong>Live records</strong> agent edits appear in the Systems panel in real time.</li>
              <li><strong>No browser tabs</strong> everything is a panel inside the desktop app.</li>
            </ul>
          ),
        },
      ],
    },
    {
      pair: 'tenancy',
      cards: [
        {
          id: 'tenant',
          tag: '10',
          title: 'Multi-tenant by default',
          body: 'Every organization gets its own isolated workspace with its own data, users, roles, and permissions. One deployment serves many teams without any cross-contamination.',
          expandLabel: 'Built for teams and enterprises',
          expand: (
            <ul className="prod-list">
              <li><strong>Workspace isolation</strong> data, agents, audit logs scoped per tenant.</li>
              <li><strong>RBAC</strong> roles and permissions managed per workspace, SSO friendly.</li>
              <li><strong>Sharing</strong> explicit, granular, revocable, never implicit.</li>
              <li><strong>Compliance</strong> per-workspace audit exports, regulator-ready.</li>
            </ul>
          ),
        },
        {
          id: 'data',
          tag: '11',
          title: 'Data Control',
          body: 'Register confidential folders. Control which agents can read or write to them. Every file access is logged with timestamps, agent names, and actions. Full audit trail for compliance.',
          expandLabel: 'How agent permissions work',
          expand: (
            <ul className="prod-list">
              <li><strong>Folder scope</strong> register any folder as confidential.</li>
              <li><strong>Per-agent</strong> read or read-write, default deny.</li>
              <li><strong>Append-only log</strong> every access immutable, exportable.</li>
              <li><strong>Revocable</strong> permissions can be cut at any time, in-flight work pauses cleanly.</li>
            </ul>
          ),
        },
      ],
    },
    {
      pair: 'control',
      span: true,
      cards: [
        {
          id: 'one-app',
          tag: '12',
          title: 'One app, complete control',
          body: 'Orbix Core and Orbix Systems are now one integrated platform. The desktop app gives you AI-powered automation, and the embedded data layer gives you structured records, audit trails, and confidential document management. No separate server, no browser tabs, no sync issues.',
          expandLabel: 'What this replaces',
          expand: (
            <ul className="prod-list prod-list-2col">
              <li>CRM tools for contact management</li>
              <li>Spreadsheets for ad-hoc reporting</li>
              <li>Cloud automation services</li>
              <li>Separate audit log databases</li>
              <li>Document management systems</li>
              <li>Workflow design tools</li>
              <li>Per-team chat-based AI subscriptions</li>
              <li>Custom integrations across SaaS apps</li>
            </ul>
          ),
        },
      ],
    },
  ];

  return (
    <article className="page">
      <PageHeader
        eyebrow="PRODUCTS"
        title="Built for people who want real automation"
        soft="without losing control."
        body="Simple enough to use daily, structured enough for enterprise governance."
      />

      <section className="prod-grid">
        {sections.map((row) => (
          <div key={row.pair} className={`prod-row ${row.span ? 'prod-row-span' : ''}`}>
            {row.cards.map((c) => {
              const isOpen = open.has(c.id);
              return (
                <article key={c.id} className={`prod-card ${isOpen ? 'is-open' : ''}`}>
                  <header className="prod-card-head">
                    <span className="prod-card-tag mono">{c.tag}</span>
                    <h3 className="prod-card-title">{c.title}</h3>
                  </header>
                  <p className="prod-card-body">{c.body}</p>
                  {c.expand && (
                    <>
                      <div className="prod-card-divider" />
                      <button
                        type="button"
                        className="prod-card-toggle"
                        onClick={() => toggle(c.id)}
                        aria-expanded={isOpen}
                      >
                        <span>{c.expandLabel}</span>
                        <span className={`prod-card-chev ${isOpen ? 'is-open' : ''}`} aria-hidden="true">⌃</span>
                      </button>
                      <div className={`prod-card-expand ${isOpen ? 'is-open' : ''}`}>
                        <div className="prod-card-expand-inner">{c.expand}</div>
                      </div>
                    </>
                  )}
                </article>
              );
            })}
          </div>
        ))}
      </section>

      <CTA />
    </article>
  );
}

// ============================================================
// PRICING
// ============================================================
function PricingPage({ user } = {}) {
  const features = [
    'Chat with Bob using local models',
    'Reads images and PDFs (vision)',
    'Unlimited agents and workflows',
    'Reusable workflows: trigger, AI step, output',
    'Connectors: SQLite, Dataverse, SQL Server, REST, email',
    'CLI + OpenAI-compatible endpoint (use it from any device)',
    'Window Intelligence: read and operate any app',
    'Secure Relay: local first, redacted before the cloud',
    'Scheduling, triggers, and event automations',
    'Knowledge base and memory',
    'Voice, text, and screen input',
    'Audit log kept on your machine',
    'Desktop app for macOS and Windows (Linux on the roadmap)',
    'Free forever, no subscriptions, no per-token fees',
    'Every future feature, included',
  ];

  return (
    <article className="page">
      <PageHeader
        eyebrow="PRICING"
        title="Pricing"
        soft="is zero."
        body="A hammer isn't rented by the swing. As AI becomes part of how we live and work, a tool this fundamental shouldn't carry a meter."
      />

      <section className="pricing-manifesto">
        <p>
          The industry loves selling you <strong>Starter</strong>, <strong>Pro</strong>, <strong>Business</strong>, and <strong>Enterprise</strong>, four ways to pay for the same product with features held hostage at every level. We think that's broken. So we don't charge for Orbix Core at all.
        </p>
      </section>

      <section className="one-plan">
        <div className="one-plan-glow" aria-hidden="true" />
        <div className="one-plan-card">
          <div className="one-plan-tag mono">ONE PLAN</div>
          <h2 className="one-plan-name">Orbix Core</h2>

          <div className="one-plan-price">
            <span className="one-plan-amount">Free</span>
            <span className="one-plan-period mono">forever</span>
          </div>
          <p className="one-plan-sub">No price. No seats. No metering. Every feature, for everyone.</p>

          <div className="one-plan-divider" />

          <h3 className="one-plan-heading">What do you get? Everything.</h3>

          <ul className="one-plan-features">
            {features.map((f) => (
              <li key={f}>
                <span className="op-check" aria-hidden="true">
                  <svg viewBox="0 0 16 16" width="14" height="14"><path d="M3.5 8.5 l3 3 l6 -7" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round" /></svg>
                </span>
                {f}
              </li>
            ))}
          </ul>

          <div className="one-plan-divider" />

          <div className="one-plan-cta">
            {user && user.license_key ? (
              <>
                <a href="/api/download" className="btn-primary btn-pill">
                  Download Orbix Core <span className="btn-arrow">→</span>
                </a>
                <p className="cta-fine mono">we log the download time and your account email. <a href="/data">data policy</a></p>
              </>
            ) : (
              <a
                href="/contact"
                className="btn-primary btn-pill"
                onClick={(e) => { e.preventDefault(); go('contact'); }}
              >
                Get Early Access <span className="btn-arrow">→</span>
              </a>
            )}
            <p className="one-plan-fine mono">Free forever. No subscriptions. No per-token fees.</p>
          </div>
        </div>
      </section>

      <section className="not-here">
        <p className="not-here-cap mono">You won't find these here.</p>
        <ul className="not-here-tiers">
          {[
            ['Starter', '$19/mo'],
            ['Pro', '$49/mo'],
            ['Business', '$99/mo'],
            ['Enterprise', '"Contact us"'],
          ].map(([n, p]) => (
            <li key={n} className="not-here-tier">
              <span className="strike">
                <span className="strike-name">{n}</span>
                <span className="strike-price">{p}</span>
              </span>
            </li>
          ))}
        </ul>
      </section>
    </article>
  );
}

// ============================================================
// ABOUT - "What Made Orbix Core" tabbed system
// ============================================================
// Three views: Human (the values that built the company), Business
// (the modules that run on top), Atom (everything converging into one nucleus).

const HUMAN_BODIES = [
  // {x, y} are percentages of the canvas. {color} is the planet hue.
  { id: 'philosophy', label: 'Philosophy', x: 50,  y: 56, size: 28, color: 'oklch(0.65 0.18 295)', primary: true },
  { id: 'curiosity',  label: 'Curiosity',  x: 22,  y: 50, size: 18, color: 'oklch(0.78 0.16 80)' },
  { id: 'code',       label: 'Code',       x: 38,  y: 44, size: 14, color: 'oklch(0.70 0.16 155)' },
  { id: 'ethics',     label: 'Ethics',     x: 40,  y: 24, size: 12, color: 'oklch(0.75 0.03 240)' },
  { id: 'creativity', label: 'Creativity', x: 65,  y: 32, size: 14, color: 'oklch(0.70 0.18 10)'  },
  { id: 'math',       label: 'Math',       x: 64,  y: 54, size: 12, color: 'oklch(0.65 0.16 240)' },
  { id: 'morale',     label: 'Morale',     x: 82,  y: 78, size: 14, color: 'oklch(0.65 0.18 310)' },
];

const BUSINESS_BODIES = [
  { id: 'core',         label: 'Core',                x: 50, y: 52, size: 30, color: 'oklch(0.65 0.18 295)', primary: true },
  { id: 'agents',       label: 'Agents',              x: 56, y: 40, size: 14, color: 'oklch(0.70 0.18 295)' },
  { id: 'workflows',    label: 'Workflows',           x: 60, y: 68, size: 14, color: 'oklch(0.65 0.16 240)' },
  { id: 'window_intel', label: 'Window Intelligence', x: 30, y: 44, size: 14, color: 'oklch(0.70 0.18 10)'  },
  { id: 'connectors',   label: 'Connectors',          x: 32, y: 54, size: 12, color: 'oklch(0.70 0.16 155)' },
  { id: 'data_lake',    label: 'Data Lake',           x: 25, y: 62, size: 14, color: 'oklch(0.78 0.16 80)'  },
  { id: 'core_api',     label: 'Core API',            x: 14, y: 68, size: 12, color: 'oklch(0.70 0.10 295)' },
  { id: 'green_llm',    label: 'Green LLM',           x: 22, y: 80, size: 14, color: 'oklch(0.70 0.16 155)' },
];

// Detail copy for click-to-read (lifted from the previous about page).
const VALUE_DETAILS = {
  // Human values
  philosophy: { title: 'Philosophy', value: 'Product clarity & intentional design',
    body: "Every design decision in Orbix starts with a question about purpose. We don't build features because we can, we build them because they reduce noise, protect attention, and respect the people who use them. This discipline keeps the product focused, reduces complexity for users, and builds the kind of trust that turns early adopters into long-term advocates." },
  math: { title: 'Math', value: 'Cost efficiency & performance optimization',
    body: 'Token economics, cost models, routing efficiency, the engine behind Green LLM is mathematics. Orbix optimises every inference call with hard numbers: input tokens, cache hit rates, model selection curves. This translates directly to lower operating costs, predictable billing, and the ability to offer competitive pricing without sacrificing capability.' },
  code: { title: 'Code', value: 'Speed, safety & auditability',
    body: 'Rust, TypeScript, structured actions. The codebase is the product. Every agent, every workflow, every automation pipeline is built to be fast, safe, and auditable. Clean architecture means fewer bugs, faster iteration, and a foundation that scales from a single user to an enterprise deployment without rewrites.' },
  creativity: { title: 'Creativity', value: 'Differentiation & user experience',
    body: "Orbix exists because someone looked at how AI tools work and thought: this could be calmer, cheaper, and more human. Creativity drives the interface, the agent design, the way workflows feel when you use them. It's the difference between software that works and software people genuinely enjoy, and that difference is what creates loyalty in a crowded market." },
  curiosity: { title: 'Curiosity', value: 'Innovation & feature discovery',
    body: 'Window Intelligence exists because we asked: what if an agent could see any application? The Workflow Engine exists because we asked: what if automation could learn? Every feature in Orbix started as a curious question that refused to go away. Curiosity is the engine that keeps the product ahead of what users expect.' },
  ethics: { title: 'Ethics', value: 'Trust, compliance & enterprise readiness',
    body: "EU Boundary Mode, the Rationale Log, human-in-the-loop escalation, these aren't compliance checkboxes. They exist because we believe AI should be transparent, auditable, and controllable. For the business, this means enterprises can adopt Orbix without legal friction, and users can trust that the system respects their boundaries." },
  morale: { title: 'Morale', value: 'Resilience & product soul',
    body: "Building something meaningful requires belief. Morale is what keeps the work going when the problem is hard and the scope is wide. It's embedded in how we treat users, how we design calm interfaces, and why Bob still has a job. A product built with conviction feels different from one built by obligation, and users can tell." },
  // Business architecture
  core: { title: 'Core', value: 'The orchestrator the rest orbits',
    body: 'Orbix Core is the desktop runtime - Bob, the workflow engine, the agent council, Window Intelligence, Secure Relay. Everything else attaches to it. When values guide architecture, the core stays small enough to reason about and powerful enough to host the entire system on a single computer.' },
  agents: { title: 'Agents', value: 'Autonomous task execution',
    body: 'Orbix agents operate across any application on your computer. They read screens via Window Intelligence, execute structured actions, and adapt in real-time. Each agent runs within a cost boundary, logs its rationale, and escalates when uncertain. The result: reliable automation that works like a thoughtful colleague, not a brittle script.' },
  workflows: { title: 'Workflows', value: 'Saved intelligence that compounds',
    body: 'A workflow in Orbix is a saved sequence of agent actions, not a rigid pipeline. Workflows adapt to context, branch on conditions, and improve as you refine them. They flow between agents, connectors, and systems, turning one-off tasks into repeatable, auditable processes that save hours every week.' },
  connectors: { title: 'Connectors', value: 'Integration with your existing stack',
    body: 'Gmail, Calendar, Notion, Slack, Linear, Orbix connects to the tools you already use via secure OAuth flows. Connectors turn external services into structured actions that agents and workflows can invoke. No manual copy-paste, no tab-switching, no context loss.' },
  window_intel: { title: 'Window Intelligence', value: 'See and act on any application',
    body: "Window Intelligence uses the operating system's accessibility layer (AX on macOS, UI Automation on Windows) to read what's on screen, any app, any window. It extracts structured data from interfaces that have no API, turning visual information into actionable context. This is what makes Orbix agents truly general-purpose." },
  data_lake: { title: 'Data Lake', value: 'Enterprise memory at scale',
    body: 'The OrbixSystems Data Lake stores enterprise knowledge, documents, transcripts, CRM records, analytics, in a structured, searchable format. Agents query the lake for context before acting, ensuring decisions are grounded in real data rather than hallucinated assumptions.' },
  green_llm: { title: 'Green LLM', value: 'Cost-efficient AI inference',
    body: 'Green LLM routes every inference call through a cost-optimization layer: prompt caching, model selection based on task complexity, token budget enforcement, and EU boundary compliance. The result is AI that performs at Claude-level quality while keeping costs predictable and as low as possible.' },
  core_api: { title: 'Core API', value: 'The central nervous system',
    body: "Every agent, workflow, and connector communicates through the Core API, a Rust-powered backbone that handles authentication, rate limiting, rationale logging, and real-time streaming. It's the layer that ensures everything works together reliably, securely, and at speed." },
  // Atom - fusion concepts
  scalability:  { title: 'Scalability',  value: 'Architecture that multiplies, not just grows',
    body: "When values guide architecture, scaling isn't a rewrite, it's a continuation. Every module in Orbix, agents, workflows, connectors, was built to multiply. Add a thousand users or a hundred new integrations; the core doesn't flinch. This is what happens when you design for the future from day one." },
  autonomy:     { title: 'Autonomy',     value: 'Independent agents, human-guided boundaries',
    body: "Human values set the boundaries. Business architecture executes within them. The result: agents that act independently but never unsupervised. Real autonomy isn't about removing humans from the loop, it's about making the loop effortless. Click less, trust more." },
  convergence:  { title: 'Convergence',  value: 'Where philosophy meets engineering',
    body: 'Philosophy meets Rust. Ethics meets API design. Creativity meets workflow automation. Orbix Core exists at the intersection, where the things that matter to people are expressed through the things machines do best. That intersection is the product.' },
  evolution:    { title: 'Evolution',    value: 'Transforming how work gets done, starting now',
    body: 'Over the next 1-2 years, Orbix will transform how you work: agents that learn from your patterns, workflows that refine themselves, a system that grows with you rather than against you. The foundation is already here. What comes next will feel like a different era.' },
  intelligence: { title: 'Intelligence', value: 'Woven through every layer, not bolted on',
    body: 'Not artificial intelligence added as a feature, but intelligence woven through every layer. Window Intelligence sees your screen. Green LLM optimizes every call. The Data Lake remembers everything. Together they form something genuinely new, a system that thinks before it acts.' },
  simplicity:   { title: 'Simplicity',   value: 'Complexity under the hood, calm on the surface',
    body: "The most powerful system is the one you don't have to think about. Orbix takes complex architectural and philosophical pillars and distills them into a calm, quiet interface. Fourteen dimensions of depth, one clean surface. That's the design principle behind everything you touch." },
  resilience:   { title: 'Resilience',   value: 'Built to last, not just to launch',
    body: "Built on Rust, guided by ethics, funded by efficiency. Orbix doesn't depend on a single model, a single cloud, or a single point of failure. The fusion of strong values and clean architecture creates a system designed to outlast trends and survive the unexpected." },
  transparency: { title: 'Transparency', value: 'Trust as a structural guarantee',
    body: "Every agent logs its reasoning. Every workflow is auditable. Every cost is visible. When values and architecture align on openness, trust isn't a marketing word, it's a structural guarantee. You see exactly what happened, why it happened, and what it cost." },
  adaptability: { title: 'Adaptability', value: 'Change absorbed, not feared',
    body: "The atom doesn't break when you add new electrons. Neither does Orbix. New connectors, new models, new regulations, the architecture absorbs change because the values anticipated it. Adaptability isn't a feature. It's a consequence of getting the foundation right." },
};

const ATOM_VALUES = [
  { id: 'scalability',   label: 'Scalability',   color: 'oklch(0.65 0.18 295)' },
  { id: 'autonomy',      label: 'Autonomy',      color: 'oklch(0.65 0.16 270)' },
  { id: 'convergence',   label: 'Convergence',   color: 'oklch(0.65 0.16 240)' },
  { id: 'evolution',     label: 'Evolution',     color: 'oklch(0.70 0.18 10)'  },
  { id: 'intelligence',  label: 'Intelligence',  color: 'oklch(0.78 0.16 80)'  },
  { id: 'simplicity',    label: 'Simplicity',    color: 'oklch(0.70 0.16 155)' },
  { id: 'resilience',    label: 'Resilience',    color: 'oklch(0.75 0.03 240)' },
  { id: 'transparency',  label: 'Transparency',  color: 'oklch(0.65 0.18 320)' },
  { id: 'adaptability',  label: 'Adaptability',  color: 'oklch(0.65 0.18 295)' },
];

// Slow, meditative orbital tracks (radius % of canvas, duration in s, dir)
const PF_TRACKS = [
  { r: 14, dur: 48,  dir: 'normal'  },
  { r: 22, dur: 64,  dir: 'reverse' },
  { r: 30, dur: 80,  dir: 'normal'  },
  { r: 38, dur: 100, dir: 'reverse' },
  { r: 46, dur: 120, dir: 'normal'  },
  { r: 54, dur: 145, dir: 'reverse' },
  { r: 62, dur: 172, dir: 'normal'  },
];

function PlanetField({ bodies, activeId, onSelect }) {
  const primary = bodies.find((b) => b.primary);
  const satellites = bodies.filter((b) => !b.primary);
  const usedTracks = satellites.map((_, i) => PF_TRACKS[i % PF_TRACKS.length]);
  const ringRadii = Array.from(new Set(usedTracks.map((t) => t.r)));
  return (
    <div className="pf-canvas">
      <div className="pf-stars" aria-hidden="true" />
      {/* One guide ring per used orbit radius */}
      <div className="pf-rings" aria-hidden="true">
        {ringRadii.map((r) => (
          <span key={r} className="pf-ring" style={{ width: `${r * 2}%`, height: `${r * 2}%` }} />
        ))}
      </div>
      {/* Primary planet anchored at the centre */}
      {primary && (
        <button
          type="button"
          className={`pf-primary-btn ${activeId === primary.id ? 'is-active' : ''}`}
          style={{ '--pf-color': primary.color, '--pf-size': `${primary.size}px` }}
          onClick={() => onSelect && onSelect(primary.id)}
          aria-label={primary.label}
        >
          <span className="pf-planet" />
          <span className="pf-label pf-label-primary">{primary.label}</span>
        </button>
      )}
      {/* Satellites ride circular orbits */}
      {satellites.map((b, i) => {
        const t = PF_TRACKS[i % PF_TRACKS.length];
        const startAngle = ((i * 137) % 360); // golden-angle distribution
        const delay = `-${(t.dur * (startAngle / 360)).toFixed(2)}s`;
        return (
          <div
            key={b.id}
            className="pf-track"
            style={{
              width: `${t.r * 2}%`,
              height: `${t.r * 2}%`,
              animationDuration: `${t.dur}s`,
              animationDirection: t.dir,
              animationDelay: delay,
            }}
          >
            <div
              className="pf-orbiter"
              style={{
                '--pf-size': `${b.size}px`,
                '--pf-color': b.color,
                animationDuration: `${t.dur}s`,
                animationDirection: t.dir,
                animationDelay: delay,
              }}
            >
              <button
                type="button"
                className={`pf-planet-btn ${activeId === b.id ? 'is-active' : ''}`}
                onClick={() => onSelect && onSelect(b.id)}
                aria-label={b.label}
              >
                <span className="pf-planet" />
              </button>
              <span className="pf-label">{b.label}</span>
            </div>
          </div>
        );
      })}
    </div>
  );
}

function AtomViz({ activeId, onSelect }) {
  // Three rings, each carrying three electrons; each ring rotates the
  // whole carrier so the orbit line tilts, and inside it three e-trks
  // ride an elliptical path with offset delays.
  const rings = [
    { rot: 0,   dur: 28, dir: 'normal',  values: ATOM_VALUES.slice(0, 3) },
    { rot: 60,  dur: 34, dir: 'reverse', values: ATOM_VALUES.slice(3, 6) },
    { rot: -60, dur: 31, dir: 'normal',  values: ATOM_VALUES.slice(6, 9) },
  ];
  return (
    <div className="atom-canvas">
      <div className="atom-glow" aria-hidden="true" />
      <div className="atom-origin">
        <div className="atom-nucleus-new" />
        {rings.map((ring, i) => (
          <div
            key={i}
            className={`atom-ring atom-ring-${i + 1}`}
            style={{ transform: `rotate(${ring.rot}deg)` }}
          >
            <div className="atom-orbit-ellipse" />
            {ring.values.map((v, j) => (
              <div
                key={v.id}
                className="e-trk"
                style={{
                  animationDuration: `${ring.dur}s`,
                  animationDirection: ring.dir,
                  animationDelay: `-${((ring.dur * j) / 3).toFixed(2)}s`,
                }}
              >
                <button
                  type="button"
                  className={`atom-electron-new ${activeId === v.id ? 'is-active' : ''}`}
                  style={{ '--e-color': v.color }}
                  aria-label={v.label}
                  onClick={() => onSelect && onSelect(v.id)}
                />
              </div>
            ))}
          </div>
        ))}
      </div>
    </div>
  );
}

function WhatMadeOrbix() {
  const [tab, setTab] = useState('human');
  const [selected, setSelected] = useState(null);
  const descRef = useRef(null);
  const tabs = [
    { id: 'human',    label: 'Human' },
    { id: 'business', label: 'Business' },
    { id: 'atom',     label: 'The Atom. The Core' },
  ];

  // Reset selection when tab changes so a stale id doesn't carry over.
  const onTab = (id) => { setTab(id); setSelected(null); };

  // When a planet/electron is clicked, ease the description card
  // into view so the click feels like it produced something.
  useEffect(() => {
    if (!selected || !descRef.current) return;
    const el = descRef.current;
    const id = window.requestAnimationFrame(() => {
      el.scrollIntoView({ behavior: 'smooth', block: 'center' });
    });
    return () => window.cancelAnimationFrame(id);
  }, [selected]);

  const detail = selected ? VALUE_DETAILS[selected] : null;
  const detailColor = (() => {
    if (!selected) return null;
    const all = [...HUMAN_BODIES, ...BUSINESS_BODIES, ...ATOM_VALUES];
    const match = all.find((b) => b.id === selected);
    return match ? match.color : null;
  })();

  return (
    <div className="wmo">
      <div className="wmo-eyebrow mono">WHAT MADE ORBIX CORE</div>
      <div className="wmo-tabs" role="tablist">
        {tabs.map((t) => (
          <button
            key={t.id}
            role="tab"
            aria-selected={tab === t.id}
            className={`wmo-tab ${tab === t.id ? 'is-active' : ''}`}
            onClick={() => onTab(t.id)}
          >
            {t.label}
          </button>
        ))}
      </div>

      {tab === 'human' && (
        <div className="wmo-stage" key="human">
          <PlanetField bodies={HUMAN_BODIES} activeId={selected} onSelect={setSelected} />
        </div>
      )}

      {tab === 'business' && (
        <div className="wmo-stage" key="business">
          <PlanetField bodies={BUSINESS_BODIES} activeId={selected} onSelect={setSelected} />
        </div>
      )}

      {tab === 'atom' && (
        <div className="wmo-stage wmo-stage-atom" key="atom">
          <p className="wmo-atom-caption">Two systems, one nucleus. This is what happens when values meet architecture.</p>
          <div className="wmo-atom-grid">
            <AtomViz activeId={selected} onSelect={setSelected} />
            <ul className="atom-list">
              {ATOM_VALUES.map((v) => (
                <li key={v.id}>
                  <button
                    type="button"
                    className={`atom-list-item ${selected === v.id ? 'is-active' : ''}`}
                    onClick={() => setSelected(v.id)}
                  >
                    <span className="atom-list-dot" style={{ background: v.color }} />
                    <span>{v.label}</span>
                  </button>
                </li>
              ))}
            </ul>
          </div>
        </div>
      )}

      {detail && (
        <div
          ref={descRef}
          className="wmo-desc"
          role="dialog"
          aria-label="Description"
          style={detailColor ? { '--wmo-desc-accent': detailColor } : undefined}
        >
          <div className="wmo-desc-bar mono">
            <span className="wmo-desc-dot" aria-hidden="true" />
            <span className="wmo-desc-cat">
              {tab === 'human' ? 'human · value' : tab === 'business' ? 'business · module' : 'fusion · concept'}
            </span>
            <span className="wmo-desc-spacer" />
            <span className="wmo-desc-id">{selected}</span>
            <button
              type="button"
              className="wmo-desc-close"
              onClick={() => setSelected(null)}
              aria-label="Close description"
            >×</button>
          </div>
          <div className="wmo-desc-body">
            <h3 className="wmo-desc-title">{detail.title}</h3>
            {detail.value && <p className="wmo-desc-value mono">{detail.value}</p>}
            <p className="wmo-desc-text">{detail.body}</p>
          </div>
        </div>
      )}
    </div>
  );
}

function AboutPage() {
  return (
    <article className="page">
      <PageHeader
        eyebrow="ABOUT"
        title="About Us"
        body="Two people, one vision. Build something calm, powerful, and worth using every day."
      />

      <section className="people">
        <div className="people-grid">
          <article className="person-card">
            <div className="person-card-top">
              <div className="person-portrait-sq">
                <img src="/images/andreas.jpg" alt="Andreas S Wilborg Zeberg N." />
              </div>
              <div className="person-card-head">
                <p className="person-role-line mono">Founder & CEO</p>
                <h3 className="person-name">Andreas S Wilborg Zeberg N.</h3>
                <p className="person-tagline">Creative minded. Dad. Master of Orbix agents.</p>
                <div className="person-socials">
                  <a className="social-pill" href="#" onClick={(e) => e.preventDefault()}>
                    <svg viewBox="0 0 24 24" width="13" height="13" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
                      <rect x="3" y="3" width="18" height="18" rx="5" />
                      <circle cx="12" cy="12" r="4" />
                      <circle cx="17.5" cy="6.5" r="0.8" fill="currentColor" stroke="none" />
                    </svg>
                    Instagram
                  </a>
                  <a className="social-pill" href="#" onClick={(e) => e.preventDefault()}>
                    <svg viewBox="0 0 24 24" width="13" height="13" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
                      <rect x="3" y="3" width="18" height="18" rx="3" />
                      <path d="M7 10v7M7 7v0.01M11 17v-4a3 3 0 0 1 6 0v4" />
                    </svg>
                    LinkedIn
                  </a>
                </div>
                <p className="person-mini">Follow for baby spam, cozy getaways, and belemnites.</p>
              </div>
            </div>
            <div className="person-card-section">
              <h4 className="person-section-h">Rabbit holes and breakthroughs</h4>
              <ul className="person-bullets">
                <li>Loves diving deep into problems until they crack open.</li>
                <li>Obsessed with calm interfaces and automation you can trust.</li>
                <li>Happiest three layers into a rabbit hole, chasing the thing nobody else noticed.</li>
              </ul>
            </div>
          </article>

          <article className="person-card">
            <div className="person-card-top">
              <div className="person-portrait-sq person-portrait-orb">
                <img src="/images/orbix-logo.png?v=2026-07-19a" alt="Bob" />
              </div>
              <div className="person-card-head">
                <p className="person-role-line mono">Moral Support</p>
                <h3 className="person-name">Bob</h3>
                <p className="person-tagline">Ping pong partner for every CEO idea. Someone has to be productive.</p>
                <div className="person-socials person-socials-disabled" aria-hidden="true">
                  <span className="social-pill is-disabled">
                    <svg viewBox="0 0 24 24" width="13" height="13" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round">
                      <rect x="3" y="3" width="18" height="18" rx="5" />
                      <circle cx="12" cy="12" r="4" />
                      <circle cx="17.5" cy="6.5" r="0.8" fill="currentColor" stroke="none" />
                    </svg>
                    Instagram
                  </span>
                  <span className="social-pill is-disabled">
                    <svg viewBox="0 0 24 24" width="13" height="13" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round">
                      <rect x="3" y="3" width="18" height="18" rx="3" />
                      <path d="M7 10v7M7 7v0.01M11 17v-4a3 3 0 0 1 6 0v4" />
                    </svg>
                    LinkedIn
                  </span>
                </div>
                <p className="person-mini person-mini-italic">"Bob is not allowed on social media."</p>
              </div>
            </div>
            <div className="person-card-section">
              <h4 className="person-section-h">Role in the company</h4>
              <ul className="person-bullets">
                <li>Provides unwavering emotional stability during feature creep.</li>
                <li>Approves ideas via silence or ping pong victory.</li>
                <li>Has never once asked for a roadmap. Thrives in chaos.</li>
              </ul>
            </div>
          </article>
        </div>
      </section>

      <section className="about-philosophy">
        <WhatMadeOrbix />
      </section>

      <section className="about-grid">
        <div className="about-col">
          <h3 className="about-h">Where we are</h3>
          <p>A small, focused team distributed across Europe. Engineering in Berlin and Tallinn. Design in Lisbon. Operations everywhere a laptop fits.</p>
        </div>
        <div className="about-col">
          <h3 className="about-h">What we believe</h3>
          <p>Privacy is not a feature. Reliability is not a feature. They are the substrate. Everything we build sits on top of those two assumptions, and we will not compromise on either to ship faster.</p>
        </div>
        <div className="about-col">
          <h3 className="about-h">How we work</h3>
          <p>Long cycles. Clear releases. No dark-pattern growth. We charge for software so we never have to charge for your data. The math is that simple.</p>
        </div>
      </section>

      <section className="timeline">
        <div className="section-eyebrow mono"><span className="eyebrow-dot" /> SHORT HISTORY</div>
        <ol className="timeline-list">
          {[
            ['2024 · Q2', 'First prototype', 'A weekend project: an open model running locally, orchestrating a five-step workflow without an internet connection. We knew immediately.'],
            ['2024 · Q4', 'Secure Relay', 'The hardest module. Detect, redact, swap, and reverse without breaking the response. Took six months. Worth every week.'],
            ['2025 · Q2', 'Bob', 'Shipped the orchestrator. The first version that felt like talking to a careful colleague instead of a clever toy.'],
            ['2025 · Q4', 'Window Intelligence', 'Agents that read any app on your computer. Native, no plugins, no APIs. The integration problem dissolved.'],
            ['2026 · Now', 'Public beta', 'Early access opens on macOS and Windows. Every feature included, free for everyone. Linux is on the roadmap.'],
          ].map(([when, what, body]) => (
            <li key={when} className="tl-item">
              <span className="tl-when mono">{when}</span>
              <div className="tl-body">
                <h4>{what}</h4>
                <p>{body}</p>
              </div>
            </li>
          ))}
        </ol>
      </section>

      <CTA />
    </article>
  );
}

// ============================================================
// CONTACT
// ============================================================
function ContactPage() {
  const [form, setForm] = useState({ name: '', email: '', org: '', size: 'solo', use: '' });
  const [sent, setSent] = useState(false);
  const [submitting, setSubmitting] = useState(false);
  const [errorMsg, setErrorMsg] = useState('');
  const update = (k, v) => setForm((f) => ({ ...f, [k]: v }));
  const submit = async (e) => {
    e.preventDefault();
    if (submitting) return;
    setSubmitting(true);
    setErrorMsg('');
    try {
      const res = await fetch('https://formspree.io/f/xlgpaavn', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json', 'Accept': 'application/json' },
        body: JSON.stringify({
          name: form.name,
          email: form.email,
          organisation: form.org,
          team_size: form.size,
          use_case: form.use,
          _subject: 'Orbix early access request',
        }),
      });
      if (res.ok) {
        setSent(true);
      } else {
        const data = await res.json().catch(() => ({}));
        setErrorMsg((data && data.errors && data.errors[0] && data.errors[0].message) || 'Could not submit. Please try again or email orbie@orbixcore.ai.');
      }
    } catch (err) {
      setErrorMsg('Connection failed. Please try again or email orbie@orbixcore.ai.');
    } finally {
      setSubmitting(false);
    }
  };

  return (
    <article className="page">
      <PageHeader eyebrow="GET EARLY ACCESS" title="Tell us how you'd" soft="put Orbix to work." body="Early access is rolling out by use case. Share a few details and we'll prioritise activations that match what we're focused on this month." />

      <section className="contact-shell">
        <div className="contact-form-wrap">
          <div className="bob-card">
            <div className="bob-card-bar mono">
              <span className="status-dot" /> request · early access
              <span className="bob-card-spacer" />
              <span>encrypted in transit</span>
            </div>
            <div className="bob-card-body contact-body">
              {sent ? (
                <div className="contact-success">
                  <div className="success-mark"><span /><span /><span /></div>
                  <h3>Request received.</h3>
                  <p>We'll be in touch within two business days. In the meantime, browse the modules or read the vision.</p>
                  <div className="contact-success-actions">
                    <a href="/products" className="btn-ghost mono" onClick={(e) => { e.preventDefault(); go('products'); }}>Products →</a>
                    <a href="/vision" className="btn-ghost mono" onClick={(e) => { e.preventDefault(); go('vision'); }}>Vision →</a>
                  </div>
                </div>
              ) : (
                <form className="contact-form" onSubmit={submit}>
                  <div className="field">
                    <label className="mono">name</label>
                    <input type="text" required value={form.name} onChange={(e) => update('name', e.target.value)} placeholder="" />
                  </div>
                  <div className="field-row">
                    <div className="field">
                      <label className="mono">email</label>
                      <input type="email" required value={form.email} onChange={(e) => update('email', e.target.value)} placeholder="" />
                    </div>
                    <div className="field">
                      <label className="mono">organisation</label>
                      <input type="text" value={form.org} onChange={(e) => update('org', e.target.value)} placeholder="" />
                    </div>
                  </div>
                  <div className="field">
                    <label className="mono">team size</label>
                    <div className="seg">
                      {['solo', '2-10', '11-50', '50+'].map((s) => (
                        <button key={s} type="button" className={`seg-btn mono ${form.size === s ? 'is-active' : ''}`} onClick={() => update('size', s)}>{s}</button>
                      ))}
                    </div>
                  </div>
                  <div className="field">
                    <label className="mono">how would you use orbix?</label>
                    <textarea rows="4" value={form.use} onChange={(e) => update('use', e.target.value)} placeholder="" />
                  </div>
                  {errorMsg && <div className="auth-error mono" role="alert">{errorMsg}</div>}
                  <div className="contact-submit">
                    <button type="submit" className="btn-primary btn-lg" disabled={submitting}>{submitting ? 'Sending' : 'Request access'} <span className="btn-arrow">→</span></button>
                    <span className="mono contact-meta">no marketing list · no analytics · no tracking</span>
                  </div>
                </form>
              )}
            </div>
          </div>
        </div>

        <aside className="contact-side">
          <div className="contact-side-block">
            <div className="section-eyebrow mono"><span className="eyebrow-dot" /> ANDREAS</div>
            <h3>Founder & CEO.</h3>
            <p>For partnerships, press, procurement, and anything strategic. Write directly.</p>
            <a className="contact-link mono" href="mailto:asw@orbixcore.ai">asw@orbixcore.ai</a>
          </div>
          <div className="contact-side-block">
            <div className="section-eyebrow mono"><span className="eyebrow-dot" /> ORBIE</div>
            <h3>Everything else.</h3>
            <p>Support, license questions, activation issues, and curious questions about Orbix Core.</p>
            <a className="contact-link mono" href="mailto:orbie@orbixcore.ai">orbie@orbixcore.ai</a>
          </div>
        </aside>
      </section>
    </article>
  );
}

// ============================================================
// AUTH MODAL (sign in / create account) - wired to /api/auth/*
// ============================================================
function AuthModal({ mode, onClose, onSwitch, onSuccess, apiBase = '' }) {
  const isSignup = mode === 'signup';
  const [form, setForm] = useState({ name: '', email: '', password: '', license: '', marketing: true });
  const [showPw, setShowPw] = useState(false);
  const [loading, setLoading] = useState(false);
  const [errorMsg, setErrorMsg] = useState('');
  const update = (k, v) => setForm((f) => ({ ...f, [k]: v }));

  const pw = form.password;
  const checks = {
    len: pw.length >= 8,
    upper: /[A-Z]/.test(pw),
    lower: /[a-z]/.test(pw),
    num: /[0-9]/.test(pw),
  };
  const allOk = isSignup ? Object.values(checks).every(Boolean) && form.email && form.name : form.email && pw;

  const submit = async (e) => {
    e.preventDefault();
    if (!allOk || loading) return;
    setLoading(true);
    setErrorMsg('');
    const endpoint = isSignup ? '/api/auth/register' : '/api/auth/login';
    const body = isSignup
      ? { email: form.email.trim(), password: pw, name: form.name.trim(), marketing_opt_in: form.marketing }
      : { email: form.email.trim(), password: pw };
    try {
      const res = await fetch(apiBase + endpoint, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(body),
      });
      const data = await res.json().catch(() => ({}));
      if (data && data.token && data.user) {
        try { localStorage.setItem('orbix-token', data.token); } catch (e) {}
        if (isSignup && form.license.trim()) {
          try {
            await fetch(apiBase + '/api/activate', {
              method: 'POST',
              headers: { 'Content-Type': 'application/json' },
              body: JSON.stringify({ key: form.license.trim(), email: data.user.email }),
            });
            const me = await fetch(apiBase + '/api/auth/me', {
              headers: { 'Authorization': 'Bearer ' + data.token },
            }).then((r) => r.ok ? r.json() : null);
            if (me && me.email) { onSuccess(me); return; }
          } catch (e) {}
        }
        onSuccess(data.user);
      } else {
        setErrorMsg((data && data.error) || 'Something went wrong.');
      }
    } catch (err) {
      setErrorMsg('Connection failed. Please try again.');
    } finally {
      setLoading(false);
    }
  };

  useEffect(() => {
    const onKey = (e) => { if (e.key === 'Escape') onClose(); };
    window.addEventListener('keydown', onKey);
    document.body.style.overflow = 'hidden';
    return () => {
      window.removeEventListener('keydown', onKey);
      document.body.style.overflow = '';
    };
  }, [onClose]);

  return (
    <div className="auth-overlay" onClick={onClose}>
      <div className="auth-modal" onClick={(e) => e.stopPropagation()}>
        <button className="auth-close" onClick={onClose} aria-label="Close">×</button>
        <div className="auth-bar mono">
          <span className="status-dot" />
          {isSignup ? 'create account · orbix core' : 'sign in · orbix core'}
          <span className="bob-card-spacer" />
          <span>encrypted</span>
        </div>
        <div className="auth-body">
          <div className="auth-head">
            <div className="section-eyebrow mono"><span className="eyebrow-dot" /> {isSignup ? 'NEW ACCOUNT' : 'WELCOME BACK'}</div>
            <h2 className="auth-title">{isSignup ? 'Create your account.' : 'Sign in to Orbix.'}</h2>
            <p className="auth-sub">{isSignup ? 'One account for downloads, license activation, and EU boundary settings.' : 'Pick up where you left off.'}</p>
          </div>

          <form className="auth-form" onSubmit={submit}>
            {isSignup && (
              <div className="field">
                <label className="mono">name</label>
                <input type="text" required value={form.name} onChange={(e) => update('name', e.target.value)} placeholder="Andreas Schmidt" />
              </div>
            )}
            <div className="field">
              <label className="mono">email</label>
              <input type="email" required value={form.email} onChange={(e) => update('email', e.target.value)} placeholder="you@company.com" />
            </div>
            <div className="field">
              <label className="mono">password</label>
              <div className="pw-wrap">
                <input
                  type={showPw ? 'text' : 'password'}
                  required
                  value={form.password}
                  onChange={(e) => update('password', e.target.value)}
                  placeholder={isSignup ? '8+ characters' : 'your password'}
                />
                <button type="button" className="pw-toggle mono" onClick={() => setShowPw((v) => !v)}>
                  {showPw ? 'hide' : 'show'}
                </button>
              </div>
              {isSignup && (
                <div className="pw-checks mono">
                  <span className={checks.len ? 'ok' : ''}>{checks.len ? '✓' : '·'} 8+ chars</span>
                  <span className={checks.upper ? 'ok' : ''}>{checks.upper ? '✓' : '·'} uppercase</span>
                  <span className={checks.lower ? 'ok' : ''}>{checks.lower ? '✓' : '·'} lowercase</span>
                  <span className={checks.num ? 'ok' : ''}>{checks.num ? '✓' : '·'} number</span>
                </div>
              )}
            </div>
            {isSignup && (
              <div className="field">
                <label className="mono">license key <span className="field-opt">optional</span></label>
                <input type="text" value={form.license} onChange={(e) => update('license', e.target.value)} placeholder="ORBX-XXXX-XXXX-XXXX" />
              </div>
            )}

            <button type="submit" className="btn-primary btn-lg auth-submit" disabled={!allOk || loading}>
              {loading ? <span className="auth-spinner" /> : null}
              {loading ? 'working' : isSignup ? 'Create account' : 'Sign in'}
              {!loading && <span className="btn-arrow">→</span>}
            </button>

            {errorMsg && <p className="auth-error mono">{errorMsg}</p>}

            {!isSignup && (
              <a href="#" className="auth-forgot mono" onClick={(e) => e.preventDefault()}>forgot password?</a>
            )}

            <p className="auth-switch mono">
              {isSignup ? 'already have an account?' : "don't have an account yet?"}
              {' '}
              <button type="button" className="link-btn" onClick={onSwitch}>
                {isSignup ? 'sign in' : 'create one'}
              </button>
            </p>

            {isSignup && (
              <>
                <label className="auth-consent mono">
                  <input
                    type="checkbox"
                    checked={form.marketing}
                    onChange={(e) => update('marketing', e.target.checked)}
                  />
                  <span>email me about Orbix Core releases and product updates. you can opt out any time.</span>
                </label>
                <p className="auth-fine mono">
                  By creating an account you accept our <a href="/data">data policy</a>. We store your name, email, and license activations on Vercel KV (EU). We don't run analytics or share with anyone.
                </p>
              </>
            )}
          </form>
        </div>
      </div>
    </div>
  );
}

// User menu (when signed in) - real license activation + download link
function UserMenu({ user, onSignOut }) {
  const [open, setOpen] = useState(false);
  const [activating, setActivating] = useState(false);
  const [keyVal, setKeyVal] = useState('');
  const [keyMsg, setKeyMsg] = useState('');
  const [licenseKey, setLicenseKey] = useState(user.license_key || null);
  const [marketingOptIn, setMarketingOptIn] = useState(user.marketing_opt_in !== false);
  const ref = useRef(null);

  useEffect(() => { setLicenseKey(user.license_key || null); }, [user.license_key]);
  useEffect(() => { setMarketingOptIn(user.marketing_opt_in !== false); }, [user.marketing_opt_in]);

  const toggleMarketing = async () => {
    const next = !marketingOptIn;
    setMarketingOptIn(next);
    try {
      const token = (typeof localStorage !== 'undefined' && localStorage.getItem('orbix-token')) || '';
      await fetch('/api/auth/marketing', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json', 'Authorization': 'Bearer ' + token },
        body: JSON.stringify({ opt_in: next }),
      });
    } catch (e) {
      // Roll back on failure so the toggle reflects truth.
      setMarketingOptIn(!next);
    }
  };

  useEffect(() => {
    const onClick = (e) => { if (ref.current && !ref.current.contains(e.target)) setOpen(false); };
    window.addEventListener('mousedown', onClick);
    return () => window.removeEventListener('mousedown', onClick);
  }, []);
  const initials = (user.name || user.email).split(/[\s@.]/).filter(Boolean).slice(0, 2).map((s) => s[0].toUpperCase()).join('');

  const activate = async (e) => {
    e.preventDefault();
    if (!keyVal.trim() || activating) return;
    setActivating(true);
    setKeyMsg('');
    try {
      const res = await fetch('/api/activate', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ key: keyVal.trim().toUpperCase(), email: user.email }),
      });
      const data = await res.json().catch(() => ({}));
      if (data && data.valid) {
        setLicenseKey(data.key || keyVal.trim().toUpperCase());
        setKeyMsg('Activated.');
        setKeyVal('');
      } else {
        setKeyMsg((data && data.error) || 'Invalid key.');
      }
    } catch (err) {
      setKeyMsg('Connection failed.');
    } finally {
      setActivating(false);
    }
  };

  return (
    <div className="user-menu" ref={ref}>
      <button className="user-pill" onClick={() => setOpen((v) => !v)}>
        <span className="user-avatar mono">{initials}</span>
        <span className="user-name">{user.name || user.email}</span>
        <span className="user-caret">▾</span>
      </button>
      {open && (
        <div className="user-dropdown">
          <div className="user-dd-head">
            <div className="user-dd-name">{user.name || user.email.split('@')[0]}</div>
            <div className="user-dd-email mono">{user.email}</div>
          </div>

          {licenseKey ? (
            <>
              <div className="user-dd-license mono">{licenseKey}</div>
              <a className="user-dd-link" href="/api/download">Download orbixcore.dmg</a>
            </>
          ) : (
            <form className="user-dd-key" onSubmit={activate}>
              <label className="user-dd-key-label mono">Activate license</label>
              <div className="user-dd-key-row">
                <input
                  type="text"
                  className="user-dd-key-input mono"
                  placeholder="ORBX-PRO-XXXX-XXXX"
                  value={keyVal}
                  onChange={(e) => setKeyVal(e.target.value)}
                />
                <button type="submit" className="user-dd-key-btn mono" disabled={activating || !keyVal.trim()}>
                  {activating ? '…' : '→'}
                </button>
              </div>
              {keyMsg && <span className="user-dd-key-msg mono">{keyMsg}</span>}
            </form>
          )}

          <label className="user-dd-toggle mono">
            <input type="checkbox" checked={marketingOptIn} onChange={toggleMarketing} />
            <span>email me about updates</span>
          </label>

          <a className="user-dd-link user-dd-fine" href="/data">Data policy</a>
          <button className="user-dd-link user-dd-out" onClick={onSignOut}>Sign out</button>
        </div>
      )}
    </div>
  );
}

// ============================================================
// COOKIES PAGE (legal stub)
// ============================================================
function CookiesPage() {
  return (
    <article className="page">
      <PageHeader
        eyebrow="LEGAL"
        title="Cookies"
        soft="and other crumbs."
        body="Orbix Core does not use tracking cookies, analytics SDKs, or third-party fingerprinting. The site stores a session token and theme preference in your browser's local storage. Nothing else."
      />
      <section className="legal-grid">
        <div className="legal-col">
          <h3 className="about-h">What we store</h3>
          <p><strong>orbix-token</strong> - a JSON Web Token issued after sign-in. Used to authenticate API calls. Cleared on sign-out.</p>
          <p><strong>orbix-theme</strong> - your preference for light or dark mode.</p>
        </div>
        <div className="legal-col">
          <h3 className="about-h">What we don't</h3>
          <p>No Google Analytics. No Mixpanel. No Segment. No advertising pixels. No session replay. No marketing cookies. No third-party CDNs that profile you.</p>
        </div>
        <div className="legal-col">
          <h3 className="about-h">How to clear</h3>
          <p>Sign out from the user menu, or clear site data in your browser. Both actions revoke the token client-side. Server-side, tokens expire after 30 days.</p>
        </div>
      </section>
      <CTA />
    </article>
  );
}

function DataPolicyPage() {
  return (
    <article className="page">
      <PageHeader
        eyebrow="LEGAL"
        title="Data policy"
        soft="what we keep, where, and why."
        body="Plain English. No 4,000-word EULA. This is the whole policy."
      />
      <section className="legal-grid">
        <div className="legal-col">
          <h3 className="about-h">What we collect</h3>
          <p>When you create an account: <strong>email</strong>, <strong>name</strong>, and a <strong>password hash</strong> (bcrypt, never the plain password).</p>
          <p>When you activate a license: the <strong>license key</strong>, the <strong>email</strong> you tied it to, and a <strong>machine ID</strong> for license enforcement.</p>
          <p>When you download orbixcore.dmg: a <strong>timestamp</strong>, your <strong>email if signed in</strong> (otherwise anonymous), the <strong>user-agent</strong> string, and the <strong>IP that hit our edge</strong>.</p>
        </div>
        <div className="legal-col">
          <h3 className="about-h">Where it lives</h3>
          <p>Everything sits in a single Vercel KV (Upstash Redis) database, in the EU region. The only people with access are the founders.</p>
          <p>We do not run analytics, advertising, session replay, or third-party SDKs that profile you. The Cookies page details what your browser stores locally.</p>
        </div>
        <div className="legal-col">
          <h3 className="about-h">How we use it</h3>
          <p>To run the service: authenticate sign-ins, enforce license tiers, ship updates.</p>
          <p>To talk to you: when there's something we genuinely think you'd want to know about Orbix Core. New release, breaking change, early-access invite. <strong>Not</strong> drip campaigns or third-party offers.</p>
          <p>You're opted in by default when you create an account. You can opt out anytime from your account menu, or by emailing <a href="mailto:orbie@orbixcore.ai">orbie@orbixcore.ai</a>.</p>
        </div>
        <div className="legal-col">
          <h3 className="about-h">Your rights</h3>
          <p><strong>Access:</strong> ask us for everything we have on you and we'll mail it back as JSON.</p>
          <p><strong>Correction:</strong> change your name and email from your account settings.</p>
          <p><strong>Deletion:</strong> the Delete account button in your menu wipes your record, your license activations, and your download history. Mail us if you want a confirmation.</p>
          <p><strong>Portability:</strong> the export above is also your portable copy.</p>
        </div>
        <div className="legal-col">
          <h3 className="about-h">Sharing with anyone else</h3>
          <p>No. We don't sell, rent, or share your data with third parties. The only sub-processor is Vercel itself, who hosts the database.</p>
        </div>
        <div className="legal-col">
          <h3 className="about-h">Changes</h3>
          <p>If we change this policy, accounts created under the old version stay under the old version until you accept the new one in-app. The current version is dated <strong>2026-04-27</strong>.</p>
        </div>
      </section>
      <CTA />
    </article>
  );
}

// ============================================================
// ROADMAP  -  what's coming next, replaces the old GitHub footer link
// ============================================================
function RoadmapPage() {
  const items = [
    {
      id: 'windows',
      tag: 'CLIENT · WINDOWS',
      status: 'IN DEVELOPMENT',
      title: 'Same Bob, on Windows.',
      lede: 'A native Windows build with the same on-device runtime, the same Secure Relay, and free like the rest of Orbix Core. No second tier, no missing features.',
      bullets: [
        'Native installer · signed and auto-updating',
        'Window Intelligence parity · Bob reads the apps you already use',
        'Local inference on supported GPUs · no cloud required',
        'The same command-line tool and local endpoint as the Mac build',
      ],
      footnote: 'Internal alpha runs today. Public preview when it is ready.',
    },
    {
      id: 'linux',
      tag: 'CLIENT · LINUX',
      status: 'PLANNED',
      title: 'Orbix Core on Linux.',
      lede: 'A native Linux desktop build, so the same free, local-first Orbix Core runs on the machines many developers and teams already prefer.',
      bullets: [
        'Same runtime, same Bob, same reusable workflows',
        'Local inference on your own GPU',
        'The command-line tool and local endpoint, native to Linux',
      ],
      footnote: 'On the roadmap. It ships when it is genuinely ready, not before.',
    },
  ];

  return (
    <article className="page">
      <PageHeader
        eyebrow="ROADMAP"
        title="What's"
        soft="next."
        body="What we're building right now. Each one earns its place. None of them ship before they're ready."
      />

      <section className="roadmap">
        {items.map((it) => (
          <article key={it.id} className="roadmap-card">
            <header className="roadmap-card-head">
              <div className="roadmap-tag mono">{it.tag}</div>
              <div className="roadmap-status mono">
                <span className="status-dot" /> {it.status}
              </div>
            </header>
            <h2 className="roadmap-title">{it.title}</h2>
            <p className="roadmap-lede">{it.lede}</p>
            <ul className="roadmap-bullets">
              {it.bullets.map((b) => (
                <li key={b}>{b}</li>
              ))}
            </ul>
            <div className="roadmap-foot mono">{it.footnote}</div>
          </article>
        ))}
      </section>

      <section className="roadmap-honest">
        <div className="section-eyebrow mono">
          <span className="eyebrow-dot" /> WHAT'S NOT ON THIS PAGE
        </div>
        <h2 className="section-title">
          We don't list things <span className="section-title-soft">we haven't started.</span>
        </h2>
        <p className="roadmap-honest-body">
          No vapour, no speculative line items, no quarter-roman-numeral charts. When something else is far enough along to be honest about, it shows up here. Until then, it doesn't.
        </p>
      </section>
    </article>
  );
}

// Expose to window so components.jsx can render them
Object.assign(window, {
  VisionPage, ProductsPage, PricingPage, AboutPage, ContactPage, CookiesPage, DataPolicyPage,
  RoadmapPage,
  AuthModal, UserMenu,
});
