// site.jsx — Noah marketing site (Aurora-unified)

const { useState, useEffect, useRef } = React;

// ── Attribution helpers ──────────────────────────────────────────────────
//
// Read the FB click identifiers from the current page state. fbclid lives
// on the URL; _fbp is a cookie the Meta Pixel sets on first PageView.
function readAttribution() {
  try {
    const fbclid = new URLSearchParams(window.location.search).get("fbclid") || undefined;
    const fbp = (document.cookie.match(/(?:^|; )_fbp=([^;]+)/) || [])[1] || undefined;
    return { fbclid, fbp };
  } catch {
    return {};
  }
}

// Fire-and-forget POST to noah-consumer. keepalive=true lets the request
// continue after the user navigates away (which is exactly what happens
// on a Download click — the <a> takes them to GitHub immediately).
function postBeacon(path, body) {
  try {
    const base = window.NOAH_CONSUMER_BASE;
    if (!base) return;
    fetch(base + path, {
      method: "POST",
      headers: { "content-type": "application/json" },
      body: JSON.stringify(body),
      keepalive: true,
    }).catch(() => {});
  } catch { /* swallow */ }
}

// Called when the user clicks a Download button. Server-side CAPI Lead
// fires with whatever attribution we have (fbc/fbp/IP/UA). Lets Meta's
// auction model see intent at click time, not hours later when the user
// opens the app.
// PLATFORM ids ("mac" | "windows") → noah-consumer's platform keys
// ("mac" | "win" | "linux"). Keep this mapping in one place — getting
// it wrong silently emails Windows users a Mac link.
function backendPlatformKey(platformId) {
  if (platformId === "windows") return "win";
  if (platformId === "linux") return "linux";
  return "mac";
}

function fireDownloadEvent(platformId) {
  const attr = readAttribution();
  postBeacon("/attribution/download", {
    fbclid: attr.fbclid,
    fbp: attr.fbp,
    platform: backendPlatformKey(platformId),
  });
  if (window.fbq) {
    try { window.fbq("track", "Lead"); } catch { /* swallow */ }
  }
}

// ── Platform detection ───────────────────────────────────────────────────
//
// Three sources, in priority order:
//   1. window.NOAH_PLATFORM   — set by /windows/index.html before site.jsx
//                               loads. Forces the page to a specific platform.
//   2. URL query ?p=win|mac   — for ad-campaign deep links that need a
//                               guaranteed platform regardless of UA.
//   3. navigator.userAgent    — UA sniff. Mac is the canonical default
//                               for anything ambiguous (matches
//                               /download/index.js behavior).
function detectPlatform() {
  if (typeof window === "undefined") return "mac";
  if (window.NOAH_PLATFORM === "windows" || window.NOAH_PLATFORM === "mac") {
    return window.NOAH_PLATFORM;
  }
  try {
    const p = new URLSearchParams(window.location.search).get("p");
    if (p === "win" || p === "windows") return "windows";
    if (p === "mac" || p === "macos") return "mac";
  } catch (_) { /* swallow */ }
  const ua = navigator.userAgent || "";
  if (/Windows/i.test(ua)) return "windows";
  return "mac";
}

const PLATFORM = {
  mac: {
    id: "mac",
    label: "macOS",
    short: "Mac",
    deviceShort: "Mac",         // colloquial device noun for hero copy: "Your Mac, …"
    downloadHref: "/download/mac",
    pillText: "For macOS",
    footerLine: "For macOS",
    osName: "macOS",
    osDescriptor: "your Mac",
    // Minimum supported OS version — surfaces in the hero meta line so
    // visitors don't download then discover incompatibility.
    osRequirement: "macOS 12+ · Apple Silicon & Intel",
    Glyph: () => <AppleGlyph />,
  },
  windows: {
    id: "windows",
    label: "Windows",
    short: "Windows",
    deviceShort: "PC",          // "Your PC, …" — never "Your Windows, …"
    downloadHref: "/download/win",
    pillText: "For Windows",
    footerLine: "For Windows",
    osName: "Windows",
    osDescriptor: "your PC",
    osRequirement: "Windows 10+ · x64 & ARM64",
    Glyph: () => <WindowsGlyph />,
  },
};

// usePlatform — returns the resolved PLATFORM[…] config. Listens for the
// `?p=` query change so an in-page link to ?p=win flips the CTAs without
// a full reload.
function usePlatform() {
  const [id, setId] = useState(detectPlatform);
  useEffect(() => {
    const onPop = () => setId(detectPlatform());
    window.addEventListener("popstate", onPop);
    return () => window.removeEventListener("popstate", onPop);
  }, []);
  return PLATFORM[id] || PLATFORM.mac;
}

// ── "Email me the install link" modal ────────────────────────────────────
//
// The compromise between gated and gateless email capture. The big
// Download button stays loud (zero-friction path for impatient users).
// This secondary path serves users who'd rather get the link in their
// inbox — wrong machine, considered buyers, anyone deferring install.
//
// What we get in exchange for the friction:
//   • Email = Meta's strongest CAPI match key (9-10/10 quality)
//   • A real recovery channel — today, downloaders who don't open the
//     app are gone forever. With email we can nudge them.
//   • A self-selecting cohort with higher trial→paid intent.
//
// Implementation: posts to noah-consumer /install-link, which emails
// the install URL via Resend and fires CAPI Lead with the email.
function EmailMeModal({ platform, onClose }) {
  const [email, setEmail] = useState("");
  const [submitting, setSubmitting] = useState(false);
  const [error, setError] = useState("");
  const [sentTo, setSentTo] = useState("");
  const inputRef = useRef(null);

  useEffect(() => {
    // Focus the input on open. Tiny delay so the modal mount animation
    // doesn't steal focus back.
    const t = setTimeout(() => inputRef.current?.focus(), 30);
    const onKey = (e) => { if (e.key === "Escape") onClose(); };
    window.addEventListener("keydown", onKey);
    return () => { clearTimeout(t); window.removeEventListener("keydown", onKey); };
  }, [onClose]);

  const submit = async () => {
    const trimmed = email.trim().toLowerCase();
    if (!/^[^@\s]+@[^@\s]+\.[^@\s]+$/.test(trimmed)) {
      setError("That doesn't look like an email — give it another try.");
      return;
    }
    setSubmitting(true);
    setError("");
    try {
      const attr = readAttribution();
      const platformKey = backendPlatformKey(platform.id);
      const base = window.NOAH_CONSUMER_BASE;
      const resp = await fetch(base + "/install-link", {
        method: "POST",
        headers: { "content-type": "application/json" },
        body: JSON.stringify({
          email: trimmed,
          platform: platformKey,
          fbclid: attr.fbclid,
          fbp: attr.fbp,
        }),
      });
      if (!resp.ok) throw new Error("send failed");
      setSentTo(trimmed);
    } catch (e) {
      setError("Something went sideways on our end. Try again in a moment?");
    } finally {
      setSubmitting(false);
    }
  };

  return (
    <div
      onClick={onClose}
      style={{
        position: "fixed", inset: 0, zIndex: 100,
        background: "rgba(20, 18, 14, 0.45)",
        backdropFilter: "blur(6px)",
        display: "flex", alignItems: "center", justifyContent: "center",
        padding: 20,
      }}
    >
      <div
        onClick={(e) => e.stopPropagation()}
        style={{
          background: "var(--page-2)",
          border: "1px solid var(--line-2)",
          borderRadius: 18,
          maxWidth: 460, width: "100%",
          padding: "28px 26px 22px",
          boxShadow: "0 24px 60px -20px rgba(0,0,0,0.35)",
          position: "relative",
        }}
      >
        <button
          onClick={onClose}
          aria-label="Close"
          style={{
            position: "absolute", top: 14, right: 14,
            background: "transparent", border: "none",
            color: "var(--mute)", cursor: "pointer",
            fontSize: 20, lineHeight: 1, padding: 4,
          }}
        >×</button>

        {sentTo ? (
          <div>
            <h3 style={{ fontSize: 20, fontWeight: 700, color: "var(--ink)", margin: "0 0 8px", letterSpacing: "-0.01em" }}>
              Link's on its way.
            </h3>
            <p style={{ fontSize: 14.5, color: "var(--ink-2)", lineHeight: 1.55, margin: "0 0 8px" }}>
              Check <strong style={{ color: "var(--ink)" }}>{sentTo}</strong> — it should arrive in a moment. The link works on any {platform.label} and opens the same download as our website.
            </p>
            <p style={{ fontSize: 13, color: "var(--mute)", lineHeight: 1.55, margin: 0 }}>
              Not seeing it? Peek in spam, or close this and try again.
            </p>
          </div>
        ) : (
          <div>
            <h3 style={{ fontSize: 20, fontWeight: 700, color: "var(--ink)", margin: "0 0 6px", letterSpacing: "-0.01em" }}>
              We'll email you the install link.
            </h3>
            <p style={{ fontSize: 14, color: "var(--ink-2)", lineHeight: 1.55, margin: "0 0 16px" }}>
              For when you'd rather install on a different {platform.label}, or just save it for later. Same download as the button — nothing to verify.
            </p>
            <input
              ref={inputRef}
              type="email"
              value={email}
              onChange={(e) => { setEmail(e.target.value); setError(""); }}
              onKeyDown={(e) => { if (e.key === "Enter") submit(); }}
              placeholder="you@example.com"
              disabled={submitting}
              style={{
                width: "100%",
                padding: "12px 14px",
                borderRadius: 12,
                border: "1px solid var(--line-2)",
                background: "var(--bg-input, #fff)",
                color: "var(--ink)",
                fontSize: 15,
                fontFamily: "inherit",
                outline: "none",
                marginBottom: 10,
                boxSizing: "border-box",
              }}
            />
            {error && (
              <p style={{ fontSize: 12.5, color: "#b91c1c", margin: "0 0 10px" }}>{error}</p>
            )}
            <button
              onClick={submit}
              disabled={submitting || !email.trim()}
              className="btn-aurora"
              style={{ width: "100%", justifyContent: "center", padding: "12px 18px", fontSize: 14 }}
            >
              {submitting ? "Sending…" : "Send the link"}
            </button>
            <p style={{ fontSize: 11.5, color: "var(--mute)", lineHeight: 1.55, margin: "12px 0 0", textAlign: "center" }}>
              We'll only email about your install. No marketing list, no sharing.
            </p>
          </div>
        )}
      </div>
    </div>
  );
}

// Small text-button that opens the modal. Sits next to the loud
// aurora Download CTA — intentionally quieter so it doesn't compete.
function EmailMeButton({ platform }) {
  const [open, setOpen] = useState(false);
  return (
    <React.Fragment>
      <button onClick={() => setOpen(true)} className="btn-quiet">
        Email me the link
      </button>
      {open && <EmailMeModal platform={platform} onClose={() => setOpen(false)} />}
    </React.Fragment>
  );
}

// ── Headlines ────────────────────────────────────────────────────────────

// Headlines are written for one specific person: a knowledge worker whose
// {device} is their primary income tool. Trigger is acute (something is
// breaking RIGHT NOW), not aspirational ("optimize your computer").
//
//   • meeting       → default. Names the trigger moment directly.
//   • stop-googling → category-defining alt; positions Noah against the
//                     "google the symptom, read 4 forum posts, guess" loop.
//   • describe-it   → calm fallback variant for paid-search where the
//                     headline has to be more literal than aspirational.
//
// `lead`, `em`, and `sub` all support {device} (e.g. "your Mac") and
// {deviceShort} ("Mac") tokens — the Hero component substitutes both.
const HEADLINES = {
  "meeting": {
    lead: "Your {deviceShort},",
    em:   "fixed before your next meeting.",
    sub:  "Tell Noah what's wrong. It finds the cause and fixes it on your approval. $5/month.",
  },
  "stop-googling": {
    lead: "Stop googling",
    em:   "“why is my {deviceShort} slow.”",
    sub:  "Skip the forum guesses. Noah inspects, names the culprit, fixes it. $5/month.",
  },
  "describe-it": {
    lead: "Describe the problem.",
    em:   "Noah finds it. You approve the fix.",
    sub:  "Plain-English diagnosis. One-tap fix. Every change logged and undoable. $5/month.",
  },
};

// ── Nav ──────────────────────────────────────────────────────────────────

function Nav({ platform }) {
  const Glyph = platform.Glyph;
  return (
    <div className="sticky top-0 z-40" style={{
      backdropFilter: "saturate(160%) blur(12px)",
      WebkitBackdropFilter: "saturate(160%) blur(12px)",
      background: "color-mix(in srgb, var(--page) 78%, transparent)",
      borderBottom: "1px solid var(--line)",
    }}>
      <nav className="max-w-[1180px] mx-auto px-6 h-15 flex items-center justify-between py-3">
        <a href="#" className="flex items-center gap-2.5 ink">
          <NoahLogo size={30} radius={9} />
          <span style={{ fontWeight: 700, letterSpacing: "-0.015em", fontSize: 16 }}>Noah</span>
        </a>
        <div className="hidden md:flex items-center gap-7 text-[13.5px]" style={{ color: "var(--ink-2)" }}>
          <a href="#what" className="hover:text-[var(--ink)]">What I fix</a>
          <a href="#how"  className="hover:text-[var(--ink)]">How it works</a>
          <a href="#talk" className="hover:text-[var(--ink)]">A conversation</a>
          <a href="#price" className="hover:text-[var(--ink)]">Pricing</a>
          <a href="#faq"   className="hover:text-[var(--ink)]">FAQ</a>
        </div>
        <a
          href={platform.downloadHref}
          className="btn-aurora"
          data-platform={platform.id}
          style={{ padding: "8px 14px", fontSize: 13 }}
          onClick={() => fireDownloadEvent(platform.id)}
        >
          <Glyph /> Download
        </a>
      </nav>
    </div>
  );
}

function AppleGlyph() {
  return (
    <svg width="12" height="12" viewBox="0 0 24 24" fill="currentColor">
      <path d="M16.37 1c.18 1.34-.36 2.69-1.15 3.66-.86 1.02-2.27 1.81-3.66 1.7-.21-1.33.45-2.7 1.21-3.59C13.7 1.79 15.14 1.04 16.37 1zm4.36 16.36c-.6 1.32-.89 1.91-1.66 3.07-1.07 1.62-2.58 3.64-4.45 3.66-1.66.02-2.09-1.08-4.35-1.07-2.26.02-2.73 1.09-4.39 1.07-1.87-.02-3.3-1.83-4.37-3.46-2.98-4.56-3.3-9.9-1.46-12.74 1.31-2.02 3.38-3.2 5.32-3.2 1.98 0 3.22 1.08 4.86 1.08 1.59 0 2.56-1.09 4.85-1.09 1.73 0 3.56.94 4.86 2.57-4.27 2.34-3.58 8.44.79 10.11z" />
    </svg>
  );
}

// Windows logo — four-pane "fluent" style mark. Sized to match AppleGlyph
// optically so they swap one-for-one inside the same button.
function WindowsGlyph() {
  return (
    <svg width="12" height="12" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true">
      <path d="M3 5.4L10.5 4.4v7.1H3V5.4zM11.5 4.3L21 3v8.5h-9.5V4.3zM3 12.5h7.5v7.1L3 18.6v-6.1zM11.5 12.5H21V21l-9.5-1.3v-7.2z" />
    </svg>
  );
}

// ── Hero ─────────────────────────────────────────────────────────────────

function Hero({ tweaks, platform }) {
  const h = HEADLINES[tweaks.headline] || HEADLINES["meeting"];
  const Glyph = platform.Glyph;
  // Substitute {device} ("your Mac"/"your PC") and {deviceShort} ("Mac"/"PC")
  // in lead/em/sub so platform-aware headlines work in any slot.
  const fill = (s) => s
    .replace(/\{deviceShort\}/g, platform.deviceShort)
    .replace(/\{device\}/g, platform.osDescriptor);
  const lead = fill(h.lead);
  const em   = fill(h.em);
  const sub  = fill(h.sub);
  return (
    <section className="relative overflow-hidden">
      {/* ambient aurora glow */}
      <div className="pointer-events-none absolute -top-32 left-1/2 -translate-x-1/2 w-[1100px] h-[640px] rounded-full"
        style={{ background: "var(--aurora)", filter: "blur(100px)", opacity: 0.18 }} />

      <div className="max-w-[1180px] mx-auto px-6 pt-14 md:pt-20 pb-16 md:pb-24 relative">
        <div className="flex items-center gap-2 mb-7 flex-wrap">
          <span className="pill-aurora">
            <Icon.Sparkle size={12} style={{ color: "var(--accent-indigo)" }} />
            7-day trial · no card
          </span>
          <span className="pill">{platform.pillText}</span>
        </div>

        <h1 className="h-display text-[56px] md:text-[92px] max-w-[1000px]">
          {lead}
          <br />
          <span className="aurora-text">{em}</span>
        </h1>

        <p className="mt-6 max-w-[620px] text-[17px] md:text-[19px] ink-2 leading-relaxed" style={{ textWrap: "pretty" }}>
          {sub}
        </p>

        <div className="mt-9 flex flex-wrap items-center gap-3">
          <a
            href={platform.downloadHref}
            className="btn-aurora"
            data-platform={platform.id}
            onClick={() => fireDownloadEvent(platform.id)}
          >
            <Glyph /> Download for {platform.label}
          </a>
          <EmailMeButton platform={platform} />
          <a href="#how" className="btn-quiet">See it in action</a>
        </div>
        <div className="mt-4 flex flex-wrap items-center gap-x-3 gap-y-1 text-[12px] mute">
          <span>7-day trial · no card · cancel any time</span>
          <span className="opacity-50">·</span>
          <span>{platform.osRequirement}</span>
        </div>

        <div className="mt-14 md:mt-20">
          {tweaks.hero === "chat"     && <HeroChat />}
          {tweaks.hero === "picker"   && <HeroPicker platform={platform} />}
          {(!tweaks.hero || tweaks.hero === "minimal") && <HeroMinimal />}
        </div>
      </div>
    </section>
  );
}

function HeroPicker({ platform }) {
  return (
    <div className="relative max-w-[920px] mx-auto">
      <IssuePicker activeKey="slow" device={platform?.deviceShort || "Mac"} />
    </div>
  );
}

function HeroChat() {
  return (
    <div className="relative max-w-[1080px] mx-auto">
      <ConversationPreview />
    </div>
  );
}

function HeroMinimal() {
  // Editorial hero — Approval Flow alongside a real conversation snippet.
  // The canonical example across the whole site is the Slack Helper memory
  // leak (universal to Mac + Windows, a googleable real problem). Don't
  // swap to a different example here without updating it everywhere.
  return (
    <div className="relative max-w-[1080px] mx-auto">
      <div className="grid md:grid-cols-12 gap-6 items-stretch">
        <div className="md:col-span-7">
          <MiniConversation />
        </div>
        <div className="md:col-span-5 card-cream p-7 flex flex-col">
          <div className="eyebrow">Every conversation</div>
          <h3 className="mt-3 h-title text-[28px]" style={{ textWrap: "balance" }}>
            Show, <span className="font-serif-it">then act.</span>
          </h3>
          <p className="mt-3 text-[14px] ink-2 leading-relaxed" style={{ textWrap: "pretty" }}>
            Noah always presents a plan before executing. The proposed action is the one thing on screen with full color — so you always know exactly what you're saying yes to.
          </p>
          <div className="mt-6 space-y-3.5 flex-1">
            {[
              { k: "Explain",  v: "Plain English. \u201cSlack Helper has leaked 11 GB of memory.\u201d",        color: "var(--accent-blue)" },
              { k: "Propose",  v: "The fix in one sentence. \u201cRestart Slack. The leak goes away.\u201d",     color: "var(--accent-indigo)" },
              { k: "Ask",      v: "One tap to approve. Nothing happens without it.",                            color: "var(--accent-violet)" },
              { k: "Report",   v: "Before and after. \u201cMemory: 11.2 GB \u2192 2.1 GB.\u201d Logged and undoable.", color: "var(--commit-bright)" },
            ].map((s) => (
              <div key={s.k} className="flex gap-3 items-start">
                <span style={{
                  width: 10, height: 10, borderRadius: 999, marginTop: 6,
                  background: s.color, flexShrink: 0,
                  boxShadow: `0 0 12px ${s.color}`,
                }} />
                <div>
                  <p className="text-[13.5px]" style={{ color: "var(--ink)", fontWeight: 600 }}>{s.k}</p>
                  <p className="text-[13px] ink-2 leading-snug" style={{ textWrap: "pretty" }}>{s.v}</p>
                </div>
              </div>
            ))}
          </div>
        </div>
      </div>
    </div>
  );
}

// ── What I fix — 8 tiles, on-cream, matching app picker rhythm ──────────

function WhatIFix({ platform }) {
  // The header's "my Mac" / "my PC" needs to flip per platform — the
  // colloquial phrasing only feels natural when it matches what the
  // visitor calls their own machine.
  const colloquial = platform && platform.id === "windows"
    ? "“my PC is being weird.”"
    : "“my Mac is being weird.”";
  return (
    <section id="what" className="py-20 md:py-28">
      <div className="max-w-[1180px] mx-auto px-6">
        <div className="max-w-[720px] mb-12">
          <div className="eyebrow mb-4">The eight problems Noah is built for</div>
          <h2 className="h-title text-[40px] md:text-[56px]">
            The greatest hits of <span className="font-serif-it">{colloquial}</span>
          </h2>
          <p className="mt-5 text-[16px] ink-2 leading-relaxed" style={{ textWrap: "pretty" }}>
            These eight come up over and over. Noah names the actual cause — the runaway process, the stuck queue, the broken DNS — and fixes it after you tap approve.
          </p>
        </div>

        <div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-3.5">
          {ISSUES.map((tile, i) => {
            const Ic = tile.Icon;
            const title = tile.title.replace("{device}", platform.deviceShort);
            return (
              <div key={i} className="card-cream p-5" style={{ transition: "transform .15s ease" }}>
                <div style={{
                  width: 38, height: 38, borderRadius: 10,
                  background: "var(--bg-tertiary)",
                  color: "var(--accent-indigo)",
                  display: "flex", alignItems: "center", justifyContent: "center",
                }}>
                  <Ic size={18} />
                </div>
                <p className="mt-4 text-[15px] ink" style={{ fontWeight: 600, letterSpacing: "-0.005em" }}>{title}</p>
                <p className="mt-1 text-[13px] mute leading-snug" style={{ textWrap: "pretty" }}>{tile.sub}</p>
              </div>
            );
          })}
        </div>

        <p className="mt-8 text-[13px] mute max-w-[640px]" style={{ textWrap: "pretty" }}>
          That's the list. If your problem isn't here — a dead SSD, a recovery situation, an OS reinstall — Noah will tell you it's out of scope and point you to who can help. No bluffing.
        </p>
      </div>
    </section>
  );
}

// ── How it works — Approval Flow (BRAND_GUIDE §6) ───────────────────────

function HowItWorks() {
  const steps = [
    {
      n: "01",
      kicker: "Explain",
      t: "Noah names the cause.",
      d: "Plain English. \u201cSlack Helper has leaked 11 GB of memory \u2014 that's the slowness.\u201d",
      color: "var(--accent-blue)",
    },
    {
      n: "02",
      kicker: "Propose",
      t: "Proposes the fix — in one sentence.",
      d: "\u201cRestart Slack. State reloads, the leak goes away.\u201d That's the bright button.",
      color: "var(--accent-indigo)",
    },
    {
      n: "03",
      kicker: "Ask",
      t: "One tap. Nothing without it.",
      d: "Destructive operations need a second confirmation. Noah never runs anything you haven't seen.",
      color: "var(--accent-violet)",
    },
    {
      n: "04",
      kicker: "Report",
      t: "Before and after, in numbers.",
      d: "\u201cDone. Memory: 11.2 GB \u2192 2.1 GB.\u201d Logged and undoable from the Action Log.",
      color: "var(--commit-bright)",
    },
  ];
  return (
    <section id="how" className="py-20 md:py-28" style={{ borderTop: "1px solid var(--line)" }}>
      <div className="max-w-[1180px] mx-auto px-6">
        <div className="flex items-end justify-between flex-wrap gap-6 mb-12">
          <div className="max-w-[640px]">
            <div className="eyebrow mb-4">How it works</div>
            <h2 className="h-title text-[40px] md:text-[52px]">
              Show, <span className="font-serif-it">then act.</span>
            </h2>
          </div>
          <p className="text-[14px] mute max-w-[320px]">
            Noah always presents a plan before executing. The user is in control.
          </p>
        </div>

        <div className="grid md:grid-cols-2 lg:grid-cols-4 gap-4">
          {steps.map((s) => (
            <div key={s.n} className="card-cream p-6 flex flex-col">
              <div className="flex items-baseline justify-between">
                <span className="font-mono text-[11px] mute">{s.n}</span>
                <span style={{
                  display: "inline-flex", alignItems: "center", gap: 6,
                  fontSize: 10.5, fontWeight: 600,
                  letterSpacing: "0.12em", textTransform: "uppercase",
                  color: s.color,
                }}>
                  <span style={{ width: 14, height: 2, borderRadius: 1, background: s.color }} />
                  {s.kicker}
                </span>
              </div>
              <h3 className="mt-6 text-[20px] h-title" style={{ textWrap: "balance" }}>{s.t}</h3>
              <p className="mt-3 text-[13.5px] ink-2 leading-relaxed" style={{ textWrap: "pretty" }}>{s.d}</p>
            </div>
          ))}
        </div>
      </div>
    </section>
  );
}

// ── Conversation block ───────────────────────────────────────────────────

function ConversationBlock() {
  return (
    <section id="talk" className="py-20 md:py-28 relative overflow-hidden" style={{ borderTop: "1px solid var(--line)" }}>
      <div className="absolute pointer-events-none -top-20 right-[5%] w-[600px] h-[600px] rounded-full"
        style={{ background: "var(--aurora)", filter: "blur(100px)", opacity: 0.12 }} />

      <div className="max-w-[1180px] mx-auto px-6 grid md:grid-cols-12 gap-10 relative">
        <div className="md:col-span-4 md:sticky md:top-24 md:self-start">
          <div className="eyebrow mb-4">A real conversation</div>
          <h2 className="h-title text-[36px] md:text-[48px]">
            Conversational. <span className="font-serif-it">Specific. Honest.</span>
          </h2>
          <p className="mt-5 text-[15.5px] ink-2 leading-relaxed" style={{ textWrap: "pretty" }}>
            No prompts. No command palette. Describe the problem in your words. Noah names the specific thing it found (“Slack Helper, 11 GB,” not “some processes”) and walks through the fix with you.
          </p>
          <div className="mt-6 flex flex-col gap-2.5">
            {[
              "Names specific things — not “some processes”",
              "Shows the tool it ran, every step",
              "Reversible — \u201cundo that\u201d works",
            ].map((s) => (
              <div key={s} className="flex items-start gap-2.5 text-[13.5px] ink-2">
                <Icon.Check size={14} style={{ color: "var(--commit-bright)" }} />
                <span>{s}</span>
              </div>
            ))}
          </div>
        </div>
        <div className="md:col-span-8">
          <ConversationPreview />
        </div>
      </div>
    </section>
  );
}

// ── Why Noah / Trust ─────────────────────────────────────────────────────

function WhyNoah() {
  const items = [
    {
      kicker: "Approval",
      title: "You approve every change. Every change is undoable.",
      body: "Noah shows the exact plan before it runs. Every change is logged. Say \u201cundo that\u201d and it reverses. This is the line between Noah and \u201chere\u2019s a command, paste it in your terminal.\u201d",
    },
    {
      kicker: "Plain language",
      title: "Findings written for you, not for an admin.",
      body: "Findings in your words. When something technical comes up, Noah explains it in the same breath. No jargon. No \u201cjust restart it.\u201d",
    },
    {
      kicker: "Bounded",
      title: "A fixed set of audited tools. Nothing else.",
      body: "A fixed set of audited tools \u2014 processes, system info, disk, network, app cache, print queues, crash logs. Noah cannot execute arbitrary shell. The blast radius is small on purpose.",
    },
  ];
  return (
    <section className="py-20 md:py-28" style={{ borderTop: "1px solid var(--line)" }}>
      <div className="max-w-[1180px] mx-auto px-6">
        <div className="max-w-[680px] mb-12">
          <div className="eyebrow mb-4">Why Noah</div>
          <h2 className="h-title text-[36px] md:text-[48px]">
            You see every plan. <span className="font-serif-it">You press every button.</span>
          </h2>
        </div>
        <div className="grid md:grid-cols-3 gap-4">
          {items.map((x) => (
            <div key={x.kicker} className="card-cream p-6">
              <div className="eyebrow mb-4">{x.kicker}</div>
              <h3 className="text-[20px] h-title">{x.title}</h3>
              <p className="mt-3 text-[14px] ink-2 leading-relaxed" style={{ textWrap: "pretty" }}>{x.body}</p>
            </div>
          ))}
        </div>
      </div>
    </section>
  );
}

// ── Pricing — Subscribe-B (Handoff §6) — segmented annual/monthly ───────

function Pricing({ platform }) {
  const [plan, setPlan] = useState("annual"); // matches Subscribe-B default
  return (
    <section id="price" className="py-20 md:py-28" style={{ borderTop: "1px solid var(--line)" }}>
      <div className="max-w-[1180px] mx-auto px-6">
        <div className="max-w-[640px] mx-auto text-center mb-12">
          <div className="eyebrow mb-4" style={{ justifyContent: "center" }}>Pricing</div>
          <h2 className="h-title text-[40px] md:text-[52px]">
            $50 a year. About <span className="font-serif-it aurora-text">one billed hour.</span>
          </h2>
          <p className="mt-5 text-[16px] ink-2 leading-relaxed" style={{ textWrap: "pretty" }}>
            Seven days free, no card. One prevented hour pays for the year.
          </p>
        </div>

        <div className="card-cream p-8 max-w-[520px] mx-auto" style={{ position: "relative" }}>
          {/* Trust pill — matches Subscribe-B header */}
          <div className="flex justify-center mb-5">
            <span className="pill-aurora">
              <Icon.Sparkle size={11} style={{ color: "var(--accent-indigo)" }} />
              7-day trial · no card
            </span>
          </div>

          {/* Segmented control — annual / monthly */}
          <div style={{
            display: "flex", padding: 4, borderRadius: 14,
            background: "var(--bg-secondary)", border: "1px solid var(--card-border)",
            boxShadow: "var(--card-shadow)",
            margin: "0 auto", maxWidth: 380,
          }}>
            {[
              { id: "annual",  label: "Annual",  price: "$50",   unit: "/ yr", note: "~$4.17/mo", badge: "SAVE 17%" },
              { id: "monthly", label: "Monthly", price: "$4.99", unit: "/ mo", note: "billed monthly" },
            ].map((p) => {
              const on = plan === p.id;
              return (
                <button key={p.id} onClick={() => setPlan(p.id)}
                  style={{
                    position: "relative", flex: 1, padding: "12px 16px",
                    borderRadius: 11, border: "none", textAlign: "left",
                    background: on ? "var(--aurora)" : "transparent",
                    color: on ? "#fff" : "var(--text-secondary)",
                    boxShadow: on ? "0 6px 16px -4px rgba(99,102,241,0.5)" : "none",
                    cursor: "pointer", fontFamily: "inherit",
                    transition: "all 200ms ease",
                  }}>
                  <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between" }}>
                    <span style={{ fontSize: 11.5, fontWeight: 600, letterSpacing: "0.04em", opacity: on ? 0.9 : 1 }}>{p.label}</span>
                    {p.badge && (
                      <span style={{
                        fontSize: 9.5, fontWeight: 700, letterSpacing: "0.08em",
                        padding: "2px 6px", borderRadius: 999,
                        background: on ? "rgba(255,255,255,0.20)" : "var(--commit-soft)",
                        color: on ? "#fff" : "var(--commit)",
                        whiteSpace: "nowrap",
                      }}>{p.badge}</span>
                    )}
                  </div>
                  <div style={{ marginTop: 4, display: "flex", alignItems: "baseline", gap: 4 }}>
                    <span style={{ fontSize: 22, fontWeight: 700, letterSpacing: "-0.02em", fontVariantNumeric: "tabular-nums" }}>{p.price}</span>
                    <span style={{ fontSize: 11.5, opacity: 0.7 }}>{p.unit}</span>
                  </div>
                  <div style={{ fontSize: 10.5, opacity: 0.7, marginTop: 2 }}>{p.note}</div>
                </button>
              );
            })}
          </div>

          {/* What's included */}
          <ul className="space-y-2.5 text-[13.5px] ink-2 my-7 max-w-[380px] mx-auto">
            {[
              "Diagnoses and fixes across the eight categories",
              "Every change logged and undoable",
              "Plain-English plans, approved before they run",
              "Cancel any time — trial includes today's fix",
            ].map((f) => (
              <li key={f} className="flex gap-2.5">
                <Icon.Check size={14} style={{ marginTop: 4, color: "var(--accent-indigo)", flexShrink: 0 }} />
                <span>{f}</span>
              </li>
            ))}
          </ul>

          <div className="flex gap-3 max-w-[380px] mx-auto">
            <a href={platform.downloadHref} className="btn-quiet flex-1 justify-center" data-platform={platform.id} onClick={() => fireDownloadEvent(platform.id)}>Continue trial</a>
            <a href={platform.downloadHref} className="btn-aurora flex-1 justify-center" data-platform={platform.id} onClick={() => fireDownloadEvent(platform.id)}>
              <Icon.Sparkle size={12} />
              Subscribe
            </a>
          </div>
          <p className="text-[11px] mute text-center mt-4">
            7-day trial · no card now · cancel any time
          </p>
        </div>
      </div>
    </section>
  );
}

// ── FAQ ──────────────────────────────────────────────────────────────────

function FAQ({ platform }) {
  // Per-platform copy. Mac and Windows both get a "What does Noah read"
  // question that names the right OS, and the "other platform" closer is
  // adjusted so a Windows visitor sees the Mac availability and vice versa.
  const isWin = platform.id === "windows";
  const device = platform.osDescriptor;            // "your Mac" / "your PC"
  const os     = platform.osName;                  // "macOS" / "Windows"
  const otherDevice = isWin ? "your Mac" : "your PC";
  const otherOs     = isWin ? "macOS"    : "Windows";
  const otherHref   = isWin ? "/"        : "/windows";

  const qa = [
    { q: "What does Noah actually do?",
      a: `A desktop app for ${device}. You describe the problem. Noah runs a small set of audited tools (processes, resources, network, the system log), names the cause, proposes a one-sentence fix, and runs it only when you tap approve.` },
    { q: `What does Noah read on ${device}?`,
      a: `Only what ${os} exposes to any app: processes (the same list ${isWin ? "Task Manager" : "Activity Monitor"} shows), CPU & memory, free disk, network, the system log. No files. No browser history. No passwords. No screen capture. Ever.` },
    { q: `Is Noah just ChatGPT with a ${platform.short} wrapper?`,
      a: "No. The conversation uses a language model. Every action is a hand-built tool with a fixed scope. Noah can't execute arbitrary shell or PowerShell." },
    { q: "What if Noah breaks something?",
      a: "Every change is logged and undoable \u2014 \u201cundo that\u201d works. Destructive operations need a second confirmation." },
    { q: `Will Noah fix a hardware problem \u2014 broken battery, dying SSD, busted Wi-Fi card?`,
      a: `No. Noah diagnoses the symptom and tells you when it's hardware, so you know whether to book an ${isWin ? "service" : "Apple Store"} appointment. Repairing physical components isn't its job.` },
    { q: "How much does it cost?",
      a: "$50/year (~$4.17/mo) or $4.99/month. Seven days free, no card. Cancel any time." },
    { q: `Does Noah work on ${otherOs}?`,
      a: `Yes \u2014 dedicated build at <a href="${otherHref}" style="color:var(--accent-indigo);text-decoration:underline">onnoah.app${otherHref === "/" ? "" : otherHref}</a>. Same conversation model and Action Log; diagnostic tools differ to match what each OS exposes.` },
  ];
  const [open, setOpen] = useState(0);
  return (
    <section id="faq" className="py-20 md:py-28" style={{ borderTop: "1px solid var(--line)" }}>
      <div className="max-w-[860px] mx-auto px-6">
        <div className="eyebrow mb-4">Questions</div>
        <h2 className="h-title text-[36px] md:text-[44px] mb-10">
          Things people <span className="font-serif-it">ask first.</span>
        </h2>
        <div style={{ borderTop: "1px solid var(--line)", borderBottom: "1px solid var(--line)" }}>
          {qa.map((x, i) => (
            <div key={i} style={{ borderBottom: i < qa.length - 1 ? "1px solid var(--line)" : "none" }}>
              <button onClick={() => setOpen(open === i ? -1 : i)}
                className="w-full text-left flex items-center justify-between gap-4 py-5">
                <span className="text-[16px] ink" style={{ fontWeight: 600, textWrap: "balance", letterSpacing: "-0.005em" }}>{x.q}</span>
                <span className="font-mono text-[18px] mute flex-shrink-0"
                  style={{ transform: open === i ? "rotate(45deg)" : "none", transition: "transform .15s ease" }}>+</span>
              </button>
              {open === i && (
                <p className="pb-5 pr-8 text-[14.5px] ink-2 leading-relaxed"
                  style={{ textWrap: "pretty" }}
                  dangerouslySetInnerHTML={{ __html: x.a }} />
              )}
            </div>
          ))}
        </div>
      </div>
    </section>
  );
}

// ── Download CTA ─────────────────────────────────────────────────────────

function DownloadCTA({ platform }) {
  const Glyph = platform.Glyph;
  // Platform-specific copy on the closer — Mac users uninstall by dragging
  // to Trash; Windows users uninstall from Settings → Apps. Get this right
  // because users notice mismatched-OS metaphors immediately.
  const closer = platform.id === "windows"
    ? "Download. Tell Noah what's wrong. See the plan. Press the bright button. Seven days free. Uninstall any time from Settings."
    : "Download. Tell Noah what's wrong. See the plan. Press the bright button. Seven days free. Drag to Trash any time.";
  return (
    <section id="download" className="py-20 md:py-32 relative overflow-hidden">
      <div className="pointer-events-none absolute inset-0"
        style={{ background: "radial-gradient(60% 80% at 50% 40%, rgba(99,102,241,0.20), transparent 70%)" }} />
      <div className="max-w-[860px] mx-auto px-6 text-center relative">
        <div style={{ display: "inline-flex", justifyContent: "center" }}>
          <NoahLogo size={64} radius={16} />
        </div>
        <h2 className="mt-7 h-display text-[44px] md:text-[64px]">
          You describe it. <span className="font-serif-it aurora-text">You approve it. Done.</span>
        </h2>
        <p className="mt-5 text-[16px] ink-2 max-w-[520px] mx-auto leading-relaxed" style={{ textWrap: "pretty" }}>
          {closer}
        </p>
        <div className="mt-9 flex items-center justify-center gap-3 flex-wrap">
          <a
            href={platform.downloadHref}
            className="btn-aurora text-[14.5px]"
            data-platform={platform.id}
            style={{ padding: "13px 22px" }}
            onClick={() => fireDownloadEvent(platform.id)}
          >
            <Glyph /> Download for {platform.label}
          </a>
          <EmailMeButton platform={platform} />
          <a href="/docs/changelog" className="btn-quiet">Read the changelog</a>
        </div>
        <p className="mt-5 text-[12px] mute">7-day trial · no card · cancel any time</p>
      </div>
    </section>
  );
}

// ── Footer ───────────────────────────────────────────────────────────────

function Footer({ platform }) {
  const isWin = platform.id === "windows";
  const groups = [
    { t: "Noah",  links: ["What I fix", "How it works", "Pricing", "Changelog"] },
    { t: "Trust", links: ["Privacy", "Security", `What I read on ${platform.osDescriptor}`, "Action Log"] },
    { t: "Help",  links: ["Common fixes", "Email support", "Community", "Bug reports"] },
  ];
  return (
    <footer className="py-14" style={{ borderTop: "1px solid var(--line)" }}>
      <div className="max-w-[1180px] mx-auto px-6 grid md:grid-cols-12 gap-8">
        <div className="md:col-span-4">
          <a href="#" className="flex items-center gap-2.5 ink">
            <NoahLogo size={32} radius={10} />
            <span style={{ fontWeight: 700, letterSpacing: "-0.015em", fontSize: 16 }}>Noah</span>
          </a>
          <p className="mt-4 text-[13px] mute max-w-[280px]" style={{ textWrap: "pretty" }}>
            For {platform.osDescriptor}. Find the cause, see the plan, approve the fix.
          </p>
          <div className="mt-4 flex items-center gap-2 text-[12px]">
            <a href={isWin ? "/" : "/windows"} className="mute hover:text-[var(--ink)]" style={{ textDecoration: "underline" }}>
              {isWin ? "Get the Mac version →" : "Get the Windows version →"}
            </a>
          </div>
        </div>
        {groups.map((g) => (
          <div key={g.t} className="md:col-span-2">
            <div className="eyebrow mb-3">{g.t}</div>
            <ul className="space-y-2 text-[13px] ink-2">
              {g.links.map((l) => <li key={l}><a href="#" className="hover:text-[var(--ink)]">{l}</a></li>)}
            </ul>
          </div>
        ))}
        <div className="md:col-span-2">
          <div className="eyebrow mb-3">Languages</div>
          <p className="text-[13px] ink-2">English · Español · 中文</p>
        </div>
      </div>
      <div className="max-w-[1180px] mx-auto px-6 mt-12 flex items-center justify-between text-[11px] mute">
        <span>© 2026 Noah · onnoah.app</span>
        <span>{platform.footerLine}</span>
      </div>
    </footer>
  );
}

// ── App ──────────────────────────────────────────────────────────────────

function App() {
  const [t, setTweak] = useTweaks(window.TWEAK_DEFAULTS);
  const platform = usePlatform();

  useEffect(() => {
    document.documentElement.classList.toggle("dark", !!t.dark);
  }, [t.dark]);

  // Production render. The designer's <TweaksPanel> (Hero variant +
  // Headline picker + Dark-mode toggle) is an in-design-mode preview
  // affordance, not a user-facing control — gated behind
  // window.NOAH_SHOW_TWEAKS so we can flip it on for design reviews
  // without redeploying. Defaults set via window.TWEAK_DEFAULTS in
  // index.html drive the live page.
  const showTweaks = typeof window !== "undefined" && window.NOAH_SHOW_TWEAKS;

  return (
    <div className="relative">
      <Nav platform={platform} />
      <Hero tweaks={t} platform={platform} />
      <WhatIFix platform={platform} />
      <HowItWorks />
      <ConversationBlock />
      <WhyNoah />
      <Pricing platform={platform} />
      <FAQ platform={platform} />
      <DownloadCTA platform={platform} />
      <Footer platform={platform} />

      {showTweaks && (
        <TweaksPanel>
          <TweakSection label="Hero" />
          <TweakRadio label="Visual" value={t.hero}
            options={[
              { value: "minimal", label: "Editorial" },
              { value: "picker",  label: "Picker"   },
              { value: "chat",    label: "Chat"     },
            ]}
            onChange={(v) => setTweak("hero", v)} />
          <TweakSelect label="Headline" value={t.headline}
            options={[
              { value: "meeting",       label: "Your {device}, fixed before your next meeting." },
              { value: "stop-googling", label: "Stop googling “why is my {device} slow.”" },
              { value: "describe-it",   label: "Describe the problem. Noah finds it. You approve the fix." },
            ]}
            onChange={(v) => setTweak("headline", v)} />

          <TweakSection label="Theme" />
          <TweakToggle label="Dark mode" value={!!t.dark} onChange={(v) => setTweak("dark", v)} />
        </TweaksPanel>
      )}
    </div>
  );
}

ReactDOM.createRoot(document.getElementById("root")).render(<App />);
