/* Phasor — main app + BYO-LLM, feature slab, proof, footer */

const { useState: useS, useEffect: useE, useRef: useR, useMemo: useM } = React;

// ---- Local Reveal (the one in sections.jsx is fine but we re-import) ----
const RevealA = window.SectionsA.Reveal;
const SectionHeaderA = window.SectionsA.SectionHeader;
const II = window.SectionsA.I;

// ============================================================
// 4) BYO-LLM — typewriter editor + live-rendering canvas that
//    morphs as code "types".
// ============================================================

const VIZ_SNIPPET = `// my-visualizer.ts
import { Visualizer, MIDI, GL } from "@phasor/spec";

export default {
  name: "echo-grid",
  uniforms: {
    bpm: 124,
    chroma: 0.4,
    decay: 0.92,
  },
  onNote(n: MIDI.Note, gl: GL) {
    const x = (n.note % 12) / 12;
    const y = Math.floor(n.note / 12) / 8;
    gl.splat(x, y, n.velocity * 0.8, palette(n));
  },
  render(gl: GL, t: number) {
    gl.clear(0.02);
    gl.feedback(this.uniforms.decay);
    gl.bloom(0.6 + 0.4 * Math.sin(t * Math.PI));
  },
};
`;

const TypewriterEditor = ({ progress }) => {
  const len = Math.floor(VIZ_SNIPPET.length * progress);
  const visible = VIZ_SNIPPET.slice(0, len);
  // syntax highlight by tokenizing
  const tokens = useM(() => {
    const KW = /\b(import|from|export|default|const|let|return|function|new|this|if|for|of|in)\b/g;
    const TY = /\b(Visualizer|MIDI|GL|Note|number|string|boolean)\b/g;
    const STR = /(["'`])(?:\\.|(?!\1).)*\1/g;
    const NUM = /\b\d+(\.\d+)?\b/g;
    const COM = /(\/\/[^\n]*)/g;
    return { KW, TY, STR, NUM, COM };
  }, []);

  const colorize = (text) => {
    // Build a structure of spans
    const ranges = [];
    const push = (re, cls) => {
      let m;
      const r = new RegExp(re.source, re.flags);
      while ((m = r.exec(text)) !== null) {
        ranges.push({ s: m.index, e: m.index + m[0].length, cls });
      }
    };
    push(tokens.COM, 'text-dim italic');
    push(tokens.STR, 'text-[#7cffb4]');
    push(tokens.KW, 'text-[#ff5fd0]');
    push(tokens.TY, 'text-[#7ad7ff]');
    push(tokens.NUM, 'text-[#c4a3ff]');
    // sort and merge non-overlapping by priority (comments win, then strings, then KW)
    ranges.sort((a,b) => a.s - b.s || a.e - b.e);
    const out = [];
    let i = 0;
    let used = new Array(text.length).fill(null);
    // mark, comments first
    const apply = (cls) => ranges.filter(r => r.cls === cls).forEach(({s,e}) => {
      for (let k = s; k < e; k++) if (used[k] === null) used[k] = cls;
    });
    apply('text-dim italic');
    apply('text-[#7cffb4]');
    apply('text-[#ff5fd0]');
    apply('text-[#7ad7ff]');
    apply('text-[#c4a3ff]');
    let cur = used[0]; let buf = '';
    for (let k = 0; k < text.length; k++) {
      const c = used[k];
      if (c !== cur) { out.push({ cls: cur, txt: buf }); buf = ''; cur = c; }
      buf += text[k];
    }
    if (buf.length) out.push({ cls: cur, txt: buf });
    return out;
  };

  const lines = visible.split('\n');
  return (
    <div className="font-mono text-[12.5px] leading-[1.65] text-ink">
      {lines.map((line, idx) => {
        const parts = colorize(line);
        const last = idx === lines.length - 1;
        return (
          <div key={idx} className="flex">
            <span className="select-none w-8 text-right pr-3 text-dim">{String(idx+1).padStart(2,' ')}</span>
            <span className="whitespace-pre">
              {parts.map((p, j) => (
                <span key={j} className={p.cls || ''}>{p.txt}</span>
              ))}
              {last && <span className="caret inline-block w-[7px] h-[14px] -mb-[2px] bg-ink ml-[1px] align-middle" />}
            </span>
          </div>
        );
      })}
    </div>
  );
};

// Live canvas that morphs based on typewriter progress (no audio)
const MorphCanvas = ({ progress }) => {
  const ref = useR(null);
  const stateRef = useR({ visible: true, progress: 0 });
  useE(() => { stateRef.current.progress = progress; }, [progress]);
  useE(() => {
    const c = ref.current; if (!c) return;
    const gl = c.getContext('webgl2'); if (!gl) return;
    const dpr = Math.min(window.devicePixelRatio || 1, 1.25);
    const resize = () => { c.width = Math.floor(c.clientWidth*dpr); c.height = Math.floor(c.clientHeight*dpr); gl.viewport(0,0,c.width,c.height); };
    resize();
    const ro = new ResizeObserver(resize); ro.observe(c);
    const io = new IntersectionObserver(([e]) => { stateRef.current.visible = e.isIntersecting; }, { threshold: 0.01 });
    io.observe(c);

    const vs = `#version 300 es
      in vec2 p; out vec2 uv;
      void main(){ uv = p*0.5+0.5; gl_Position = vec4(p,0.0,1.0); }`;
    const fs = `#version 300 es
      precision highp float; in vec2 uv; out vec4 fc;
      uniform float t; uniform float prog; uniform vec2 res;
      float h(vec2 p){ p = fract(p*vec2(123.34, 456.21)); p += dot(p, p+45.32); return fract(p.x * p.y); }
      float vnoise(vec2 p){
        vec2 i = floor(p), f = fract(p);
        float a = h(i), b = h(i+vec2(1,0)), c2 = h(i+vec2(0,1)), d = h(i+vec2(1,1));
        vec2 u = f*f*(3.0-2.0*f);
        return mix(mix(a,b,u.x), mix(c2,d,u.x), u.y);
      }
      float fbm(vec2 p){ float s=0.0, a=0.5; for (int i=0;i<5;i++){ s+=a*vnoise(p); p*=2.04; a*=0.5; } return s; }

      // stages: 0..0.25 sparse particles; 0.25..0.5 grid attractor; 0.5..0.75 noise warp; 0.75..1.0 full bloom
      void main(){
        vec2 q = (uv - 0.5) * vec2(res.x/res.y, 1.0) * 2.0;
        float r = length(q);
        // Stage A: dot grid
        float gx = abs(fract(q.x * 6.0) - 0.5);
        float gy = abs(fract(q.y * 6.0) - 0.5);
        float dots = smoothstep(0.46, 0.49, max(gx, gy));
        vec3 stageA = vec3(0.6, 0.2, 0.9) * (1.0 - dots) * 0.6;

        // Stage B: lit grid with sweeping cursor
        float sweep = smoothstep(0.04, 0.0, abs(q.x + sin(t*1.5)*1.2));
        vec3 stageB = vec3(0.0, 0.55, 0.85) * sweep + vec3(0.05, 0.1, 0.2);

        // Stage C: warped noise
        vec2 w = vec2(fbm(q + t*0.2), fbm(q*1.3 + 5.2 + t*0.18));
        float n = fbm(q*1.5 + 3.0*w);
        vec3 stageC = mix(vec3(0.05,0.0,0.15), vec3(0.85,0.1,0.55), smoothstep(0.3,0.7,n));
        stageC = mix(stageC, vec3(0.0,0.55,0.85), smoothstep(0.6,0.95,n)*0.7);

        // Stage D: full plasma + bloom
        float p1 = sin(q.x*4.0 + t*1.6);
        float p2 = sin(q.y*4.4 + t*1.3);
        float p3 = sin(length(q)*5.0 - t*2.0);
        float pp = (p1+p2+p3)/3.0;
        vec3 stageD = 0.5 + 0.5*sin(pp*3.14 + vec3(0.0, 2.0, 4.0));
        stageD *= smoothstep(1.6, 0.0, r);

        float a = smoothstep(0.0, 0.25, prog) - smoothstep(0.25, 0.4, prog);
        float b = smoothstep(0.25, 0.5, prog) - smoothstep(0.5, 0.65, prog);
        float c1 = smoothstep(0.5, 0.75, prog) - smoothstep(0.75, 0.9, prog);
        float d = smoothstep(0.7, 1.0, prog);
        vec3 col = stageA*a + stageB*b + stageC*c1 + stageD*d;

        // accent ring synced to "beat"
        float beat = 0.5 + 0.5*sin(t*6.4);
        col += vec3(0.5,0.1,0.8) * beat * smoothstep(0.05, 0.0, abs(r - 0.55 - 0.1*sin(t*0.7))) * d;

        // vignette
        col *= smoothstep(1.6, 0.2, r);
        // scanlines hint (very subtle)
        col *= 0.96 + 0.04*sin(uv.y*res.y*0.5);
        fc = vec4(col, 1.0);
      }`;
    function compile(type, src){ const s=gl.createShader(type); gl.shaderSource(s,src); gl.compileShader(s); if(!gl.getShaderParameter(s,gl.COMPILE_STATUS)) console.error(gl.getShaderInfoLog(s)); return s; }
    const prog = gl.createProgram();
    gl.attachShader(prog, compile(gl.VERTEX_SHADER, vs));
    gl.attachShader(prog, compile(gl.FRAGMENT_SHADER, fs));
    gl.linkProgram(prog); gl.useProgram(prog);
    const buf = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, buf);
    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([-1,-1, 3,-1, -1,3]), gl.STATIC_DRAW);
    const ploc = gl.getAttribLocation(prog, 'p');
    gl.enableVertexAttribArray(ploc); gl.vertexAttribPointer(ploc, 2, gl.FLOAT, false, 0, 0);
    const uT = gl.getUniformLocation(prog, 't');
    const uP = gl.getUniformLocation(prog, 'prog');
    const uR = gl.getUniformLocation(prog, 'res');
    let raf = 0; const start = performance.now();
    const loop = (now) => {
      raf = requestAnimationFrame(loop);
      if (!stateRef.current.visible) return;
      gl.useProgram(prog);
      gl.uniform1f(uT, (now-start)/1000);
      gl.uniform1f(uP, stateRef.current.progress);
      gl.uniform2f(uR, c.width, c.height);
      gl.drawArrays(gl.TRIANGLES, 0, 3);
    };
    raf = requestAnimationFrame(loop);
    return () => { cancelAnimationFrame(raf); ro.disconnect(); io.disconnect(); };
  }, []);
  return <canvas ref={ref} className="block w-full h-full cursor-cross" />;
};

const ByoLLM = () => {
  const [progress, setProgress] = useS(0);
  const [running, setRunning] = useS(true);
  const sectionRef = useR(null);

  useE(() => {
    let raf = 0;
    let start = performance.now();
    const TOTAL = 9000; // 9s typing
    const loop = (now) => {
      raf = requestAnimationFrame(loop);
      if (!running) return;
      const t = (now - start) % (TOTAL + 2000); // pause briefly when full
      const p = Math.min(1, t / TOTAL);
      setProgress(p);
    };
    raf = requestAnimationFrame(loop);
    return () => cancelAnimationFrame(raf);
  }, [running]);

  // pause when offscreen
  useE(() => {
    const el = sectionRef.current; if (!el) return;
    const io = new IntersectionObserver(([e]) => setRunning(e.isIntersecting), { threshold: 0.05 });
    io.observe(el);
    return () => io.disconnect();
  }, []);

  return (
    <section id="byo" ref={sectionRef} className="relative bg-black border-t border-line py-32">
      <div className="max-w-[1440px] mx-auto px-8">
        <SectionHeaderA
          index="04 / BYO-LLM"
          kicker="Out of visualizers? Make one."
          title={<>Paste our spec into your LLM. <span className="text-mid">Drop the result into Phasor.</span></>}
          subtitle="No rebuild. No PR. Yours. The visualizer API is a single TypeScript module with three lifecycle hooks. Anything you can express in a shader, you can ship in a set."
        />

        <div className="grid grid-cols-1 lg:grid-cols-2 gap-px bg-line hairline">
          {/* Editor */}
          <div className="bg-surface relative">
            {/* editor chrome */}
            <div className="border-b border-line h-9 px-3 flex items-center justify-between font-mono text-[10.5px] uppercase tracking-[0.18em]">
              <div className="flex items-center gap-2 text-mid">
                <span className="inline-block w-2 h-2 rounded-full bg-[#3a3a3a]" />
                <span className="inline-block w-2 h-2 rounded-full bg-[#3a3a3a]" />
                <span className="inline-block w-2 h-2 rounded-full bg-[#3a3a3a]" />
                <span className="ml-3">my-visualizer.ts</span>
              </div>
              <div className="flex items-center gap-3 text-dim">
                <span>typescript</span>
                <span className="w-px h-3 bg-line" />
                <span>{Math.floor(progress * 100)}%</span>
              </div>
            </div>
            <div className="p-6 min-h-[460px]">
              <TypewriterEditor progress={progress} />
            </div>
            <div className="border-t border-line h-9 px-3 flex items-center justify-between font-mono text-[10.5px] uppercase tracking-[0.18em] text-dim">
              <span>watching · hot-swap on save</span>
              <span className="text-[#7cffb4]">▲ compiled · 0 errors</span>
            </div>
          </div>
          {/* Live canvas */}
          <div className="bg-black relative aspect-square lg:aspect-auto lg:min-h-[540px]">
            <MorphCanvas progress={progress} />
            <div className="absolute inset-0 pointer-events-none">
              {/* overlay chrome */}
              <div className="absolute top-0 left-0 right-0 h-9 px-3 flex items-center justify-between font-mono text-[10.5px] uppercase tracking-[0.18em] text-mid bg-gradient-to-b from-black/70 to-transparent">
                <span>echo-grid · live</span>
                <span className="flex items-center gap-2"><span className="inline-block w-1.5 h-1.5 rounded-full bg-[#ff5fd0]" /> rendering</span>
              </div>
              <div className="absolute bottom-0 left-0 right-0 h-9 px-3 flex items-center justify-between font-mono text-[10.5px] uppercase tracking-[0.18em] text-dim bg-gradient-to-t from-black/70 to-transparent">
                <span>uniforms · {Math.floor(progress * 3)} bound</span>
                <span>16.6 ms</span>
              </div>
            </div>
          </div>
        </div>

        {/* caption row */}
        <div className="mt-10 max-w-[860px] grid grid-cols-1 md:grid-cols-3 gap-8">
          <Caption k="01" t="Paste the spec" b="A 6-page contract: hooks, GL helpers, MIDI events. Hand it to any model that writes TS." />
          <Caption k="02" t="Drop in the file" b="Phasor watches a folder. Save, and your visualizer is in the dropdown — even mid-set." />
          <Caption k="03" t="Map it. Perform." b="Bind any uniform to any control. The shader is yours; the wiring is one line." />
        </div>
      </div>
    </section>
  );
};

const Caption = ({ k, t, b }) => (
  <RevealA>
    <div className="flex flex-col gap-2">
      <span className="font-mono text-[10.5px] uppercase tracking-[0.22em] text-dim">{k}</span>
      <h4 className="font-display text-[18px] tracking-tight">{t}</h4>
      <p className="text-[14px] leading-[1.55] text-mid">{b}</p>
    </div>
  </RevealA>
);

// ============================================================
// 5) FEATURE SLAB — dense mono grid, no bullets
// ============================================================

const FEATURES = [
  ['Web MIDI',                'Native, zero driver'],
  ['Tone.js audio engine',    'Optional, sidecar tap'],
  ['GLSL shader pipeline',    'WebGL2 · half-float'],
  ['Custom visualizers',      'Pure TypeScript module'],
  ['Zero-install',            'It is a URL'],
  ['Hot-swap at 60fps',       'No reload, no glitch'],
  ['Open spec',               'MIT · 6-page contract'],
  ['Multi-output',            'NDI · Spout · Syphon'],
  ['Sysex support',           'Yes, even your weird one'],
  ['Frame-locked timing',     'Sample-accurate beats'],
  ['Macro mapping',           'CC → uniform · 1:1 or 1:N'],
  ['Set save / recall',       'JSON, version-controlled'],
];

const FeatureSlab = () => (
  <section className="relative bg-black border-t border-line py-32">
    <div className="max-w-[1440px] mx-auto px-8">
      <div className="flex items-end justify-between mb-12 max-w-[1100px]">
        <div className="flex flex-col gap-6">
          <RevealA>
            <div className="font-mono text-[11px] uppercase tracking-[0.22em] text-mid flex items-center gap-3">
              <span>05 / Spec</span>
              <span className="inline-block w-6 h-px bg-mid/60" />
              <span>What is in the box</span>
            </div>
          </RevealA>
          <RevealA delay={40}>
            <h2 className="font-display font-bold text-[44px] leading-[0.95] tracking-[-0.025em]">
              Twelve things, no fluff.
            </h2>
          </RevealA>
        </div>
      </div>
      <div className="grid grid-cols-2 md:grid-cols-4 gap-px bg-line hairline">
        {FEATURES.map(([label, sub], i) => (
          <RevealA key={label} delay={(i % 4) * 30}>
            <div className="bg-black p-6 min-h-[120px] flex flex-col justify-between hover:bg-surface ease-phasor transition-colors duration-200">
              <span className="font-mono text-[10.5px] uppercase tracking-[0.22em] text-dim">{String(i+1).padStart(2,'0')}</span>
              <div className="mt-4">
                <div className="font-mono text-[14px] text-ink">{label}</div>
                <div className="font-mono text-[11.5px] text-mid mt-1">{sub}</div>
              </div>
            </div>
          </RevealA>
        ))}
      </div>
    </div>
  </section>
);

// ============================================================
// 6) PROOF — three large procedural mockups of Phasor running
// ============================================================

const PhasorMockup = ({ Viz, name, set, channel, latency, height = 460 }) => {
  return (
    <div className="hairline bg-surface overflow-hidden flex flex-col" style={{ minHeight: height }}>
      {/* toolbar */}
      <div className="h-10 border-b border-line px-3 flex items-center justify-between font-mono text-[10.5px] uppercase tracking-[0.18em]">
        <div className="flex items-center gap-2 text-mid">
          <span className="inline-block w-2 h-2 rounded-full bg-[#3a3a3a]" />
          <span className="inline-block w-2 h-2 rounded-full bg-[#3a3a3a]" />
          <span className="inline-block w-2 h-2 rounded-full bg-[#3a3a3a]" />
          <span className="ml-3 flex items-center gap-2">
            <span className="text-ink">phasor</span>
            <span className="text-dim">/</span>
            <span>{set}</span>
          </span>
        </div>
        <div className="flex items-center gap-4 text-dim">
          <span className="flex items-center gap-1.5"><span className="inline-block w-1.5 h-1.5 rounded-full bg-[#7cffb4]" /> live</span>
          <span>ch {channel}</span>
          <span>{latency} ms</span>
          <span>1080p · 60</span>
        </div>
      </div>
      <div className="flex-1 grid grid-cols-[200px_1fr_180px]">
        {/* left rail: visualizer list */}
        <div className="border-r border-line p-3 flex flex-col gap-1 font-mono text-[11px]">
          <div className="text-dim uppercase tracking-[0.18em] text-[10px] mb-2">visualizers</div>
          {['particle-field','oscilloscope','hex-floor','chladni','plasma-sphere','marbled','echo-grid','user/gridlock'].map((n, i) => {
            const active = n === name;
            return (
              <div key={n} className={`flex items-center justify-between px-2 py-1.5 ${active ? 'bg-[#1a1a1a] text-ink' : 'text-mid'}`}>
                <span className="truncate">{n}</span>
                {active && <span className="text-[#7cffb4]">●</span>}
              </div>
            );
          })}
          <div className="mt-4 text-dim uppercase tracking-[0.18em] text-[10px]">midi in</div>
          <div className="text-mid px-2 py-1">launchkey · port 01</div>
          <div className="text-mid px-2 py-1">moog · port 02</div>
        </div>
        {/* main canvas */}
        <div className="relative bg-black">
          <Viz active={true} />
          {/* HUD top-left */}
          <div className="absolute top-3 left-3 font-mono text-[10.5px] uppercase tracking-[0.18em] text-ink">
            <div>{name}</div>
            <div className="text-dim mt-0.5">{set}</div>
          </div>
          {/* event log bottom */}
          <div className="absolute bottom-0 left-0 right-0 h-8 bg-black/60 backdrop-blur-sm border-t border-line px-3 flex items-center gap-3 font-mono text-[10px] uppercase tracking-[0.18em] text-dim overflow-hidden">
            {['note 64 v118','cc 74 = 0.83','note 71 v096','cc 1 = 0.42','note 60 v127','clock','note 68 v104'].map((e, i) => (
              <span key={i} className={i === 0 ? 'text-[#7cffb4]' : ''}>{e}</span>
            ))}
          </div>
        </div>
        {/* right rail: macros */}
        <div className="border-l border-line p-3 flex flex-col gap-3 font-mono text-[11px]">
          <div className="text-dim uppercase tracking-[0.18em] text-[10px]">macros</div>
          {[
            { l: 'bloom', v: 0.72 },
            { l: 'chroma', v: 0.41 },
            { l: 'decay',  v: 0.92 },
            { l: 'chaos',  v: 0.28 },
            { l: 'feedback', v: 0.66 },
          ].map(m => (
            <div key={m.l}>
              <div className="flex items-center justify-between text-mid mb-1">
                <span>{m.l}</span>
                <span className="text-ink">{m.v.toFixed(2)}</span>
              </div>
              <div className="h-[2px] bg-line"><div className="h-full bg-ink" style={{ width: `${m.v*100}%` }} /></div>
            </div>
          ))}
          <div className="mt-2 text-dim uppercase tracking-[0.18em] text-[10px]">output</div>
          <div className="text-mid">spout · syphon</div>
        </div>
      </div>
    </div>
  );
};

const Proof = () => (
  <section id="spec" className="relative bg-black border-t border-line py-32">
    <div className="max-w-[1440px] mx-auto px-8">
      <SectionHeaderA
        index="06 / In situ"
        kicker="Three sets · three visualizers"
        title={<>What it actually looks like <span className="text-mid">on the night.</span></>}
      />
      <div className="flex flex-col gap-8">
        <RevealA><PhasorMockup Viz={window.MiniViz.Marbled} name="marbled" set="berghain.b2b · sat 03:40" channel="01" latency="3.4" /></RevealA>
        <RevealA><PhasorMockup Viz={window.MiniViz.HexFloor} name="hex-floor" set="ambient.set · long-form" channel="02" latency="2.8" /></RevealA>
        <RevealA><PhasorMockup Viz={window.MiniViz.PlasmaSphere} name="plasma-sphere" set="modular.live · 808 + voltage" channel="01" latency="4.1" /></RevealA>
      </div>
    </div>
  </section>
);

// ============================================================
// 7) FOOTER
// ============================================================

const Footer = () => (
  <footer className="relative bg-black border-t border-line">
    <div className="max-w-[1440px] mx-auto px-8 py-16">
      <div className="flex flex-col gap-12">
        <div className="flex items-end justify-between flex-wrap gap-8">
          <div>
            <div className="font-mono text-[12px] uppercase tracking-[0.22em] text-mid mb-3">
              <span className="inline-block w-6 h-px bg-mid/60 mr-3 align-middle" />
              Phasor v0.4
            </div>
            <p className="font-display text-[44px] leading-[0.95] tracking-[-0.025em] max-w-[760px]">
              Built for musicians.
            </p>
          </div>
          <a href="/player" target="_top" className="inline-flex items-center gap-3 h-11 px-5 bg-ink text-black font-mono text-[12px] uppercase tracking-[0.18em] hover:bg-white transition-colors duration-150">
            Open in browser <II.Arrow className="w-4 h-4" />
          </a>
        </div>

        <div className="div-x" />

        <div className="grid grid-cols-2 md:grid-cols-4 gap-8 font-mono text-[12px]">
          <FCol title="Phasor" links={['GitHub', 'Releases', 'Roadmap']} />
          <FCol title="Spec" links={['Visualizer API', 'MIDI events', 'GL helpers', 'Examples']} />
          <FCol title="Devices" links={['MIDI device guide', 'Modular bridges', 'DAW setup']} />
          <FCol title="Community" links={['Discord', 'Mastodon', 'Matrix']} />
        </div>

        <div className="div-x" />

        <div className="flex items-center justify-between flex-wrap gap-3 font-mono text-[10.5px] uppercase tracking-[0.22em] text-dim">
          <div className="flex items-center gap-2">
            <window.SectionsA.PhasorMark size={14} />
            <span>phasor</span>
          </div>
          <div className="flex items-center gap-4">
            <span>mit · open source</span>
            <span className="w-px h-3 bg-line" />
            <span>made in berlin</span>
            <span className="w-px h-3 bg-line" />
            <span>© 2026</span>
          </div>
        </div>
      </div>
    </div>
  </footer>
);

const FCol = ({ title, links }) => (
  <div>
    <div className="text-dim uppercase tracking-[0.22em] text-[10.5px] mb-3">{title}</div>
    <ul className="flex flex-col gap-2">
      {links.map(l => (
        <li key={l}><a href="#" className="text-ink hover:text-[#7cffb4] transition-colors duration-150">{l}</a></li>
      ))}
    </ul>
  </div>
);

// ============================================================
// APP
// ============================================================

const App = () => {
  return (
    <main className="bg-black text-ink min-h-screen">
      <window.SectionsA.Header />
      <window.SectionsA.Hero />
      <window.SectionsA.LiveGrid />
      <window.SectionsA.HowItWorks />
      <ByoLLM />
      <FeatureSlab />
      <Proof />
      <Footer />
    </main>
  );
};

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<App />);
