/* global React, ReactDOM, useTweaks, TweaksPanel, TweakSection, TweakRadio */
const { useState, useEffect, useRef, useCallback } = React;

/* ────────────────────────────────────────────────────────────
   Hero / install
   ──────────────────────────────────────────────────────────── */
function InstallBar() {
  const [copied, setCopied] = useState(false);
  const cmd = "npx create-binsby@latest";
  const onCopy = () => {
    try { navigator.clipboard.writeText(cmd); } catch (e) {}
    setCopied(true);
    setTimeout(() => setCopied(false), 1400);
  };
  return (
    <div className="install" role="group" aria-label="install command">
      <div className="cmd"><span className="pr">$</span>{cmd}</div>
      <button className={"copy " + (copied ? "copied" : "")} onClick={onCopy} aria-label="copy install command">
        {copied ? "✓ copied" : "copy"}
      </button>
    </div>
  );
}

function Hero() {
  return (
    <section className="hero">
      <span className="pre">
        <span className="badge-dot" style={{ width: 6, height: 6, borderRadius: 999, background: "var(--green)", boxShadow: "0 0 8px var(--green)", display: "inline-block" }}></span>
        v0.1.0 · public alpha
      </span>
      <h1>
        Ship real HTML.<br />
        Hydrate <span className="accent">on purpose.</span>
      </h1>
      <p className="sub">
        Binsby is a server-first React framework built around one constraint:
        the server ships real HTML; the browser only runs what you explicitly allow.
      </p>
      <div className="cta">
        <a className="btn btn-primary btn-lg" href="#install">Get started →</a>
        <a className="btn btn-outline btn-lg" href="#why">Why Binsby?</a>
      </div>
      <div id="install"><InstallBar /></div>
    </section>
  );
}

/* ────────────────────────────────────────────────────────────
   Why / principles
   ──────────────────────────────────────────────────────────── */
const PRINCIPLES = [
  { k: "01 / SSR by default", t: "Output is ordinary HTML",
    p: "No edge magic, no virtual streaming protocol. The server renders, the browser receives HTML — same as it ever was." },
  { k: "02 / Islands, not oceans", t: "Hydration is opt-in",
    p: "Mark a component as an island and it ships JS. Don’t, and it doesn’t. There is no global hydrate; there’s no blanket tax." },
  { k: "03 / The registry", t: "An allowlist for the browser",
    p: "Every island lands in a registry you maintain. Auditing what can execute client-side is one file, not a vibe check." },
  { k: "04 / Don’t fight the tools", t: "Vite stays Vite, React stays React",
    p: "No bespoke compiler tricks. No file conventions you can’t grep for. If you know React + Vite, you already know Binsby." },
];

function Why() {
  return (
    <section className="section" id="why">
      <div className="section-head">
        <span className="num">01 / WHY</span>
        <h2>Less framework, more web.</h2>
        <span className="rule"></span>
      </div>
      <p style={{ color: "var(--fg-3)", maxWidth: 640, fontSize: 14, marginTop: -16, marginBottom: 28 }}>
        Built because meta-framework convenience kept turning into cleverness — hidden conventions,
        implicit data flow, global hydration by default. Stuff that makes simple work feel like archaeology
        once the app grows.
      </p>
      <div className="principles">
        {PRINCIPLES.map((x) => (
          <div className="principle" key={x.k}>
            <div className="k">{x.k}</div>
            <h3>{x.t}</h3>
            <p>{x.p}</p>
          </div>
        ))}
      </div>
    </section>
  );
}

/* ────────────────────────────────────────────────────────────
   Feature grid
   ──────────────────────────────────────────────────────────── */
const FEATURES = [
  { i: "</>", t: "Real HTML", p: "Routes return strings. View source actually shows your page." },
  { i: "◇",   t: "Islands",   p: "Opt-in interactivity per component. The default is zero JS." },
  { i: "✓",   t: "Registry",  p: "One file lists everything that may run in the browser." },
  { i: "⌁",   t: "Streaming", p: "Server renders progressively. The shell arrives in milliseconds." },
  { i: "⚡",   t: "Vite-native", p: "HMR, plugins, build pipeline — your existing Vite config still works." },
  { i: "△",   t: "Edge-friendly", p: "Deploy to Node, Bun, Deno, Workers. The runtime is small on purpose." },
  { i: "≡",   t: "Forms first", p: "Progressive enhancement is the default. Forms work without JS, then upgrade." },
  { i: "↺",   t: "Resumable nav", p: "Client router takes over after first paint, only when an island says so." },
  { i: "⌘",   t: "TypeScript native", p: "End-to-end types from loaders to islands. No codegen step." },
];

function Features() {
  return (
    <section className="section">
      <div className="section-head">
        <span className="num">02 / FEATURES</span>
        <h2>The whole framework, on one page.</h2>
        <span className="rule"></span>
      </div>
      <div className="features">
        {FEATURES.map((f) => (
          <div className="feature" key={f.t}>
            <div className="icon">{f.i}</div>
            <h3>{f.t}</h3>
            <p>{f.p}</p>
          </div>
        ))}
      </div>
    </section>
  );
}

/* ────────────────────────────────────────────────────────────
   Tabbed code example
   ──────────────────────────────────────────────────────────── */
const TABS = [
  {
    id: "page",
    name: "app/routes/index.tsx",
    badge: null,
    code: (
<>
<span className="ln">1</span><span className="c">// Server component. No "use client". No hydration.</span>{"\n"}
<span className="ln">2</span><span className="k">import</span> Counter <span className="k">from</span> <span className="s">"./Counter.island"</span>{"\n"}
<span className="ln">3</span><span className="k">import</span> {"{"} getStats {"}"} <span className="k">from</span> <span className="s">"~/lib/stats"</span>{"\n"}
<span className="ln">4</span>{"\n"}
<span className="ln">5</span><span className="k">export default async function</span> <span className="p">Page</span>() {"{"}
{"\n"}<span className="ln">6</span>  <span className="k">const</span> stats = <span className="k">await</span> getStats();{"\n"}
<span className="ln">7</span>  <span className="k">return</span> ({"\n"}
<span className="ln">8</span>    &lt;<span className="t">main</span>&gt;{"\n"}
<span className="ln">9</span>      &lt;<span className="t">h1</span>&gt;Hello, server.&lt;/<span className="t">h1</span>&gt;{"\n"}
<span className="ln">10</span>     &lt;<span className="t">p</span>&gt;{"{stats.requests} reqs/s · 0 KB JS shipped"}&lt;/<span className="t">p</span>&gt;{"\n"}
<span className="ln">11</span>     &lt;<span className="t">Counter</span> initial={"{0}"} /&gt;  <span className="c">{"// ← only this hydrates"}</span>{"\n"}
<span className="ln">12</span>   &lt;/<span className="t">main</span>&gt;{"\n"}
<span className="ln">13</span> );{"\n"}
<span className="ln">14</span>{"}"}
</>
    )
  },
  {
    id: "island",
    name: "app/routes/Counter.island.tsx",
    badge: "island",
    code: (
<>
<span className="ln">1</span><span className="c">// .island.tsx suffix = ships to the browser.</span>{"\n"}
<span className="ln">2</span><span className="k">import</span> {"{"} useState {"}"} <span className="k">from</span> <span className="s">"react"</span>{"\n"}
<span className="ln">3</span>{"\n"}
<span className="ln">4</span><span className="k">export default function</span> <span className="p">Counter</span>({"{"} initial {"}"}: {"{"} initial: <span className="t">number</span> {"}"}) {"{"}
{"\n"}<span className="ln">5</span>  <span className="k">const</span> [n, setN] = useState(initial);{"\n"}
<span className="ln">6</span>  <span className="k">return</span> ({"\n"}
<span className="ln">7</span>    &lt;<span className="t">button</span> onClick={"{() => setN(n + 1)}"}&gt;{"\n"}
<span className="ln">8</span>      Clicked {"{n}"} times{"\n"}
<span className="ln">9</span>    &lt;/<span className="t">button</span>&gt;{"\n"}
<span className="ln">10</span> );{"\n"}
<span className="ln">11</span>{"}"}
</>
    )
  },
  {
    id: "registry",
    name: "binsby.config.ts",
    badge: null,
    code: (
<>
<span className="ln">1</span><span className="c">// The allowlist. If it's not here, it can't hydrate.</span>{"\n"}
<span className="ln">2</span><span className="k">import</span> {"{"} defineRegistry {"}"} <span className="k">from</span> <span className="s">"binsby"</span>{"\n"}
<span className="ln">3</span>{"\n"}
<span className="ln">4</span><span className="k">export default</span> defineRegistry({"{"}
{"\n"}<span className="ln">5</span>  islands: {"{"}
{"\n"}<span className="ln">6</span>    Counter:      () =&gt; <span className="k">import</span>(<span className="s">"~/routes/Counter.island"</span>),{"\n"}
<span className="ln">7</span>    ThemeToggle:  () =&gt; <span className="k">import</span>(<span className="s">"~/components/ThemeToggle.island"</span>),{"\n"}
<span className="ln">8</span> {"},"}{"\n"}
<span className="ln">9</span>  ssr: {"{"} streaming: <span className="p">true</span> {"},"}{"\n"}
<span className="ln">10</span>{"});"}
</>
    )
  },
];

function CodeTabs() {
  const [active, setActive] = useState("page");
  const cur = TABS.find(t => t.id === active);
  const isIsland = active === "island";
  return (
    <section className="section">
      <div className="section-head">
        <span className="num">03 / CODE</span>
        <h2>Three files. That’s the whole shape.</h2>
        <span className="rule"></span>
      </div>
      <div className="codecard">
        <div className="tabs">
          {TABS.map(t => (
            <button
              key={t.id}
              className={"tab " + (t.id === active ? "active " : "") + (t.id === "island" ? "island" : "")}
              onClick={() => setActive(t.id)}
            >
              <span className="dot"></span>
              {t.name}
              {t.badge && <span className="code-island-flag">↯ {t.badge}</span>}
            </button>
          ))}
          <span className="tabspace"></span>
          <span className="right-meta">
            {isIsland
              ? <><span style={{color: "var(--cyan)"}}>●</span> ships to browser</>
              : <><span style={{color: "var(--green)"}}>●</span> server-only · 0 KB</>}
          </span>
        </div>
        <pre>{cur.code}</pre>
      </div>
      <p style={{ color: "var(--fg-3)", fontSize: 13, marginTop: 14, fontFamily: "var(--mono)" }}>
        // No <span style={{color:"var(--fg-1)"}}>"use client"</span> directives. No
        invisible boundaries. The <span style={{color:"var(--cyan)"}}>.island.tsx</span> suffix and the registry are the contract.
      </p>
    </section>
  );
}

/* ────────────────────────────────────────────────────────────
   Architecture diagram (3-step animation)
   ──────────────────────────────────────────────────────────── */
function Diagram() {
  const [step, setStep] = useState(0);
  const [playing, setPlaying] = useState(true);
  const timer = useRef(null);

  useEffect(() => {
    if (!playing) return;
    timer.current = setInterval(() => setStep(s => (s + 1) % 3), 2200);
    return () => clearInterval(timer.current);
  }, [playing]);

  const stepNames = ["server renders", "html arrives", "island hydrates"];

  return (
    <section className="section">
      <div className="section-head">
        <span className="num">04 / ARCHITECTURE</span>
        <h2>Server → HTML → island.</h2>
        <span className="rule"></span>
      </div>

      <div className="diagram-frame">
        {/* arrows */}
        <div className={"flow-arrow " + (step >= 1 ? "lit" : "")} style={{ left: "calc(33.33% + 0px)", marginLeft: -10 }}></div>
        <div className={"flow-arrow " + (step >= 2 ? "cyan" : "")} style={{ left: "calc(66.66% + 0px)", marginLeft: -10 }}></div>

        {/* node 1: server */}
        <div className={"dnode " + (step === 0 ? "flash" : "")}>
          <div className="lbl">◇ server · routes/index.tsx</div>
          <div className="body">
            <div><span className="com">{"// async, has db access"}</span></div>
            <div><span className="tag">&lt;Page&gt;</span></div>
            <div>&nbsp;&nbsp;<span className="tag">&lt;h1&gt;</span>Hello.<span className="tag">&lt;/h1&gt;</span></div>
            <div>&nbsp;&nbsp;<span className="tag">&lt;Counter</span> initial=<span className="str">{"{0}"}</span><span className="tag">/&gt;</span></div>
            <div><span className="tag">&lt;/Page&gt;</span></div>
            <div style={{ marginTop: 14 }}><span className="com">// renderToString()</span></div>
          </div>
        </div>

        {/* node 2: html on the wire */}
        <div className={"dnode " + (step === 1 ? "flash" : "")}>
          <div className="lbl">→ html on the wire</div>
          <div className="body">
            <div><span className="com">&lt;!doctype html&gt;</span></div>
            <div><span className="tag">&lt;main&gt;</span></div>
            <div>&nbsp;&nbsp;<span className="tag">&lt;h1&gt;</span>Hello.<span className="tag">&lt;/h1&gt;</span></div>
            <div>&nbsp;&nbsp;<span className="island-mark">↯ island id=<span className="str">"Counter"</span></span></div>
            <div>&nbsp;&nbsp;<span className="tag">&lt;button&gt;</span>Clicked 0 times<span className="tag">&lt;/button&gt;</span></div>
            <div>&nbsp;&nbsp;<span className="island-mark">↯ /island</span></div>
            <div><span className="tag">&lt;/main&gt;</span></div>
            <div style={{ marginTop: 14 }}><span className="com">{"// 0.4 KB · gzip"}</span></div>
          </div>
        </div>

        {/* node 3: island hydrates */}
        <div className={"dnode " + (step === 2 ? "flash-cyan" : "")}>
          <div className="lbl" style={{ color: step === 2 ? "var(--cyan)" : undefined }}>↯ browser · registry lookup</div>
          <div className="body">
            <div><span className="com">// registry["Counter"]</span></div>
            <div><span className="tag">import</span>(<span className="str">"./Counter.island"</span>)</div>
            <div>&nbsp;&nbsp;.then(<span className="str">hydrate</span>)</div>
            <div style={{ marginTop: 10 }}><span className="island-mark" style={{ borderStyle: "solid" }}>↯ Counter · hydrated</span></div>
            <div style={{ marginTop: 12 }}><span className="com">// page total: 4.2 KB</span></div>
            <div><span className="com">// other components: never load</span></div>
          </div>
        </div>
      </div>

      <div className="diagram-controls">
        <div>
          <button className="play" onClick={() => setPlaying(p => !p)}>
            {playing ? "❚❚ pause" : "▶ play"}
          </button>
          <span style={{ marginLeft: 14 }}>step {step + 1} / 3 · {stepNames[step]}</span>
        </div>
        <div className="steps">
          {[0,1,2].map(i => (
            <div key={i}
              className={"step " + (i === step ? "active" : "")}
              onClick={() => { setStep(i); setPlaying(false); }}
            ></div>
          ))}
        </div>
      </div>
    </section>
  );
}

/* ────────────────────────────────────────────────────────────
   Live island demo
   ──────────────────────────────────────────────────────────── */
function IslandDemo() {
  const [count, setCount] = useState(0);
  const [bytes, setBytes] = useState(0);
  const [hydratedAt, setHydratedAt] = useState(null);

  useEffect(() => {
    // simulate hydration cost on mount, once
    const t = setTimeout(() => {
      setBytes(412);
      setHydratedAt(Date.now());
    }, 220);
    return () => clearTimeout(t);
  }, []);

  return (
    <section className="section">
      <div className="section-head">
        <span className="num">05 / LIVE</span>
        <h2>One island. Everything else is HTML.</h2>
        <span className="rule"></span>
      </div>
      <div className="island-demo">
        <div className="preview">
          <div className="label-strip">
            <span>preview · view-source view</span>
            <span style={{ color: "var(--fg-4)" }}>app/routes/index.tsx</span>
          </div>
          <div className="faux-html">
            <div className="static">&lt;main&gt;</div>
            <div className="static">&nbsp;&nbsp;&lt;h1&gt;Hello, server.&lt;/h1&gt;</div>
            <div className="static">&nbsp;&nbsp;&lt;p&gt;Real HTML. No JS yet.&lt;/p&gt;</div>
            <div className="island-zone hydrated" style={{ marginLeft: 20 }}>
              <span className="island-tag">↯ island · Counter · hydrated {hydratedAt ? "•" : "…"}</span>
              <div className="counter">
                <button onClick={() => setCount(c => Math.max(0, c - 1))} aria-label="decrement">−</button>
                <span className="val">{count}</span>
                <button onClick={() => setCount(c => c + 1)} aria-label="increment">+</button>
                <button className="reset" onClick={() => setCount(0)}>reset</button>
              </div>
            </div>
            <div className="static">&nbsp;&nbsp;&lt;footer&gt;Still HTML.&lt;/footer&gt;</div>
            <div className="static">&lt;/main&gt;</div>
          </div>
        </div>
        <div className="panel">
          <div className="metric">
            <span className="k">JS shipped to browser</span>
            <span className="v cyan">{bytes ? bytes + " B" : "…"}</span>
          </div>
          <div className="metric">
            <span className="k">Components hydrated</span>
            <span className="v">1 / <span style={{ color: "var(--fg-3)" }}>47</span></span>
          </div>
          <div className="metric">
            <span className="k">SSR time</span>
            <span className="v green">14 ms</span>
          </div>
          <div className="metric">
            <span className="k">Counter clicks (state)</span>
            <span className="v amber">{count}</span>
          </div>
          <div className="registry-block">
            <div className="lbl">binsby.config.ts · registry</div>
            <div className="item"><span className="name">Counter</span><span className="ok">↯ hydrated</span></div>
            <div className="item"><span className="name">ThemeToggle</span><span className="pending">— idle</span></div>
            <div className="item"><span className="name">Search</span><span className="pending">— idle</span></div>
          </div>
          <p style={{ fontSize: 12, color: "var(--fg-3)", margin: "6px 4px 0", fontFamily: "var(--mono)", lineHeight: 1.6 }}>
            // click +/−. notice no other component on this page<br />
            // ever downloaded its JS. that's the point.
          </p>
        </div>
      </div>
    </section>
  );
}

/* ────────────────────────────────────────────────────────────
   Comparison
   ──────────────────────────────────────────────────────────── */
const ROWS = [
  { l: "Hydration model", s: "How JS reaches the browser",
    binsby: ["yes", "Islands · opt-in"], next: ["opt", "RSC + 'use client'"], remix: ["no", "Full hydration"] },
  { l: "Default JS per route", s: "Empty page baseline",
    binsby: ["yes", "0 KB"],            next: ["opt", "~80 KB"],          remix: ["no", "~70 KB"] },
  { l: "Client allowlist", s: "Auditable registry of what may run",
    binsby: ["yes", "binsby.config.ts"], next: ["no", "Implicit"],        remix: ["no", "Implicit"] },
  { l: "File conventions", s: "How routes are discovered",
    binsby: ["yes", "Explicit imports"], next: ["opt", "Folder magic"],   remix: ["opt", "Folder magic"] },
  { l: "Build tool", s: "What ships you the bundle",
    binsby: ["yes", "Vite"],            next: ["no", "Turbopack/webpack"], remix: ["yes", "Vite"] },
  { l: "RSC", s: "React Server Components",
    binsby: ["no",  "Not used"],        next: ["yes", "Required"],        remix: ["no", "Not used"] },
  { l: "Forms without JS", s: "Progressive enhancement",
    binsby: ["yes", "Default"],         next: ["opt", "With effort"],     remix: ["yes", "Default"] },
  { l: "Lines in core runtime", s: "Approximate, audit-time",
    binsby: ["yes", "~2k"],             next: ["no", "huge"],             remix: ["opt", "medium"] },
];

function Comparison() {
  const cell = (v) => {
    const [k, txt] = v;
    const sym = k === "yes" ? "●" : k === "opt" ? "◐" : "○";
    return <span className={"v " + k}>{sym}<span style={{ color: "var(--fg-1)" }}>{txt}</span></span>;
  };
  return (
    <section className="section">
      <div className="section-head">
        <span className="num">06 / COMPARISON</span>
        <h2>How it differs.</h2>
        <span className="rule"></span>
      </div>
      <table className="compare">
        <thead>
          <tr>
            <th></th>
            <th className="us">Binsby</th>
            <th>Next.js</th>
            <th>Remix</th>
          </tr>
        </thead>
        <tbody>
          {ROWS.map(r => (
            <tr key={r.l}>
              <td className="row-label">{r.l}<small>{r.s}</small></td>
              <td className="col-us">{cell(r.binsby)}</td>
              <td>{cell(r.next)}</td>
              <td>{cell(r.remix)}</td>
            </tr>
          ))}
        </tbody>
      </table>
      <p style={{ color: "var(--fg-4)", fontSize: 11, marginTop: 12, fontFamily: "var(--mono)" }}>
        // ● yes · ◐ partial / opt-in · ○ no — comparison written by Binsby; mileage may vary
      </p>
    </section>
  );
}

/* ────────────────────────────────────────────────────────────
   CTA + Footer
   ──────────────────────────────────────────────────────────── */
function CTA() {
  return (
    <section className="section" style={{ paddingTop: 60, paddingBottom: 80 }}>
      <div style={{
        background: "var(--bg-1)",
        border: "1px solid var(--accent-line)",
        borderRadius: 12, padding: "48px 40px",
        textAlign: "center",
        backgroundImage: "radial-gradient(ellipse 60% 100% at 50% 0%, rgba(167,139,250,0.10), transparent 70%)"
      }}>
        <div style={{ fontFamily: "var(--mono)", fontSize: 12, color: "var(--accent)", letterSpacing: ".14em", textTransform: "uppercase" }}>
          ◇ ship something small
        </div>
        <h2 style={{ fontSize: 36, margin: "12px 0 14px", letterSpacing: "-.02em", color: "var(--fg)" }}>
          Stop hydrating things you didn’t ask to.
        </h2>
        <p style={{ color: "var(--fg-2)", maxWidth: 520, margin: "0 auto 28px", fontSize: 15 }}>
          Five-minute starter, no account, no telemetry. The whole runtime fits in a long-ish file.
        </p>
        <div style={{ display: "flex", gap: 10, justifyContent: "center", flexWrap: "wrap" }}>
          <a href="#install" className="btn btn-accent btn-lg">npx create-binsby</a>
          <a href="#" className="btn btn-outline btn-lg">Read the docs →</a>
        </div>
      </div>
    </section>
  );
}

function Footer() {
  return (
    <footer className="foot">
      <div className="inner">
        <div>
          <div className="lockup">[ binsby<span className="br">_</span> ]</div>
          <p className="blurb">
            A server-first React framework. SSR is the baseline; islands are opt-in;
            the client is an allowlist.
          </p>
        </div>
        <div>
          <h4>docs</h4>
          <ul>
            <li><a href="#">Getting started</a></li>
            <li><a href="#">Routing</a></li>
            <li><a href="#">Islands</a></li>
            <li><a href="#">Registry</a></li>
            <li><a href="#">Deployment</a></li>
          </ul>
        </div>
        <div>
          <h4>project</h4>
          <ul>
            <li><a href="#">GitHub ↗</a></li>
            <li><a href="#">Changelog</a></li>
            <li><a href="#">Roadmap</a></li>
            <li><a href="#">RFCs</a></li>
          </ul>
        </div>
        <div>
          <h4>community</h4>
          <ul>
            <li><a href="#">Discord</a></li>
            <li><a href="#">Bluesky</a></li>
            <li><a href="#">Examples</a></li>
            <li><a href="#">Contribute</a></li>
          </ul>
        </div>
      </div>
      <div className="meta-row">
        <div>© 2026 binsby contributors · MIT</div>
        <div>built with binsby · 0 KB shipped</div>
      </div>
    </footer>
  );
}

/* ────────────────────────────────────────────────────────────
   App + Tweaks
   ──────────────────────────────────────────────────────────── */
function App() {
  const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
    "background": "grid"
  }/*EDITMODE-END*/;

  const [tweaks, setTweak] = useTweaks(TWEAK_DEFAULTS);

  useEffect(() => {
    document.body.dataset.bg = tweaks.background;
  }, [tweaks.background]);

  return (
    <>
      <div className="bg-layer"></div>
      <div className="page-wrap">
        <nav className="nav">
          <div className="lockup">
            [ binsby<span className="br">_</span> ]
            <span className="v">v0.1.0</span>
          </div>
          <div className="links">
            <a href="#why">Why</a>
            <a href="#">Docs</a>
            <a href="#">Examples</a>
            <a href="#">Blog</a>
            <a href="#">GitHub ↗</a>
          </div>
          <div className="right">
            <a className="btn btn-ghost btn-sm" href="#">Star · 1.2k</a>
            <a className="btn btn-primary btn-sm" href="#install">Get started</a>
          </div>
        </nav>
        <Hero />
        <Why />
        <Features />
        <CodeTabs />
        <Diagram />
        <IslandDemo />
        <Comparison />
        <CTA />
        <Footer />
      </div>

      <TweaksPanel>
        <TweakSection label="Background" />
        <TweakRadio
          label="Treatment"
          value={tweaks.background}
          options={["flat", "grid", "noise", "gradient"]}
          onChange={(v) => setTweak("background", v)}
        />
      </TweaksPanel>
    </>
  );
}

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