// ARC Proofing — landing page app. Monotone restyle of the original stacked
// Provenance landing, with the cycling backronym masthead as the hero.
const { useState: useS, useEffect: useE, useRef: useR, useLayoutEffect: useLE } = React;

const MAST_WORDS = ['Conception', 'Custody', 'Compliance', 'Creation'];

// Globe arcs — global anchoring routes (monotone, decorative).
const ARCS_DATA = [
  { startLat: 37.7749, startLng: -122.4194, endLat: 51.5074, endLng: -0.1278 },
  { startLat: 35.6762, startLng: 139.6503, endLat: -33.8688, endLng: 151.2093 },
  { startLat: 52.5200, startLng: 13.4050, endLat: 1.3521, endLng: 103.8198 },
  { startLat: 40.7128, startLng: -74.0060, endLat: -23.5505, endLng: -46.6333 },
  { startLat: 48.8566, startLng: 2.3522, endLat: 25.2048, endLng: 55.2708 },
  { startLat: -33.9249, startLng: 18.4241, endLat: 55.7558, endLng: 37.6173 },
];
const GEOJSON_URL = 'https://raw.githubusercontent.com/vasturiano/react-globe.gl/master/example/datasets/ne_110m_admin_0_countries.geojson';

async function fetchBlockHeight() {
  try {
    const r = await fetch('https://mempool.space/api/blocks/tip/height');
    if (!r.ok) throw new Error('primary failed');
    return parseInt(await r.text(), 10);
  } catch {
    try {
      const r = await fetch('https://blockstream.info/api/blocks/tip/height');
      return parseInt(await r.text(), 10);
    } catch {
      return 879234; // offline fallback
    }
  }
}

// Masthead showpiece: monotone dotted globe behind a live Bitcoin block-height
// card, ringed by orbiting nodes. Ported from the original BitcoinVisualization.
function BitcoinShowpiece() {
  const mountRef = useR(null);
  const [height, setHeight] = useS(null);
  const [display, setDisplay] = useS(0);

  // build + auto-rotate the globe via the global globe.gl UMD build
  useE(() => {
    const el = mountRef.current;
    if (!el || typeof Globe === 'undefined') return;
    const g = Globe()(el)
      .width(380).height(380)
      .backgroundColor('rgba(0,0,0,0)')
      .showGlobe(false)
      .showAtmosphere(true)
      .atmosphereColor('#727272')
      .atmosphereAltitude(0.18)
      .hexPolygonResolution(3)
      .hexPolygonMargin(0.7)
      .hexPolygonUseDots(true)
      .hexPolygonColor(() => 'rgba(240, 240, 240, 0.82)')
      .arcsData(ARCS_DATA)
      .arcColor(() => ['rgba(61,158,95,0.9)', 'rgba(61,158,95,0.15)'])
      .arcDashLength(0.4)
      .arcDashGap(2)
      .arcDashAnimateTime(2000)
      .arcStroke(0.5)
      .arcAltitudeAutoScale(0.3);
    const c = g.controls();
    c.autoRotate = true;
    c.autoRotateSpeed = 0.4;
    c.enableZoom = false;
    c.enablePan = false;
    c.enableRotate = false;
    g.pointOfView({ lat: 20, lng: 0, altitude: 2.5 });
    fetch(GEOJSON_URL)
      .then((r) => r.json())
      .then((d) => g.hexPolygonsData(d.features))
      .catch(() => {});
    return () => {
      try { g._destructor && g._destructor(); } catch (e) {}
      if (el) el.innerHTML = '';
    };
  }, []);

  useE(() => { fetchBlockHeight().then(setHeight); }, []);

  // ease-out count-up to the live height
  useE(() => {
    if (!height) return;
    let raf;
    const dur = 1800;
    const t0 = performance.now();
    const tick = (now) => {
      const p = Math.min(1, (now - t0) / dur);
      const eased = 1 - Math.pow(1 - p, 3);
      setDisplay(Math.floor(eased * height));
      if (p < 1) raf = requestAnimationFrame(tick);
      else setDisplay(height);
    };
    raf = requestAnimationFrame(tick);
    return () => cancelAnimationFrame(raf);
  }, [height]);

  return (
    <div className="showpiece" aria-hidden="true">
      <div className="globe-stage">
        <div className="ring r1" />
        <div className="ring r2" />
        <div className="ring r3" />
        <div className="ring r4" />
        <div className="globe-mount" ref={mountRef} />
        {[
          { r: 128, dur: 28, lit: true, delay: 0 },
          { r: 168, dur: 38, lit: false, delay: -6 },
          { r: 208, dur: 48, lit: true, delay: -3 },
          { r: 208, dur: 44, lit: false, delay: -22 },
          { r: 248, dur: 60, lit: false, delay: -12 },
        ].map((n, i) => (
          <div
            key={i}
            className="orbit-track"
            style={{ animation: `orbit ${n.dur}s linear ${n.delay}s infinite` }}
          >
            <span className={'node' + (n.lit ? ' lit' : '')} style={{ left: `${n.r}px` }} />
          </div>
        ))}
        <div className="bh-tag t-sha"><span className="k">SHA-256</span><span className="v mono">8f3a2b1c9d4e…</span></div>
        <div className="bh-tag t-merkle"><span className="k">Merkle Root</span><span className="v mono">a7b2c3d4e5f6…</span></div>
        <div className="bh-tag t-conf"><span className="k">Confirmations</span><span className="v mono">1,247</span></div>
      </div>
      <div className="bh-readout">
        <div className={'bh-val mono' + (height ? '' : ' loading')}>
          {height ? display.toLocaleString() : '···'}
        </div>
        <div className="bh-label"><span className="d" />Block Height</div>
      </div>
    </div>
  );
}

// reveal-on-scroll (sets inline styles directly — beats any stylesheet rule)
function useReveal() {
  // Hero entrance — useLayoutEffect fires before first paint so gsap.from() has no flash
  useLE(() => {
    const gsap = window.gsap;
    if (!gsap) return;
    const tl = gsap.timeline({
      defaults: { ease: 'power3.out' },
      // clean up all inline styles when done so nothing lingers
      onComplete() { gsap.set(tl.getChildren().map(t => t.targets()).flat(), { clearProps: 'all' }); },
    });
    tl.from('.nav',          { y: -18, opacity: 0, duration: 0.55 }, 0.05)
      .from('.mast-eyebrow', { y: 28,  opacity: 0, duration: 0.65 }, 0.18)
      .from('.mast-h1 .fixed',{ y: 24, opacity: 0, duration: 0.65 }, 0.30)
      .from('.mast-stack',   { y: 24,  opacity: 0, duration: 0.65 }, 0.38)
      .from('.mast-url',     { y: 18,  opacity: 0, duration: 0.55 }, 0.54)
      .from('.mast-lead',    { y: 16,  opacity: 0, duration: 0.55 }, 0.62)
      .from('.mast-cta',     { y: 14,  opacity: 0, duration: 0.50 }, 0.72)
      .from('.trust .ti',    { y: 10,  opacity: 0, duration: 0.40, stagger: 0.10 }, 0.84)
      .from('.showpiece',    { x: 32,  opacity: 0, duration: 0.90 }, 0.28);
    // if the tab starts hidden, force-complete when the user returns
    const onVisible = () => { if (document.visibilityState === 'visible') { tl.progress(1); document.removeEventListener('visibilitychange', onVisible); } };
    if (document.visibilityState !== 'visible') document.addEventListener('visibilitychange', onVisible);
  }, []);

  // Scroll reveals — ScrollTrigger.batch groups nearby elements for natural stagger
  useE(() => {
    const gsap = window.gsap;
    const ST   = window.ScrollTrigger;

    // CSS fallback if GSAP didn't load
    if (!gsap || !ST) {
      document.querySelectorAll('.rv').forEach(el => {
        el.style.opacity = '1';
        el.style.transform = 'none';
      });
      return;
    }

    gsap.registerPlugin(ST);

    ST.batch('.rv', {
      interval: 0.1,   // group elements entering within 100ms → natural stagger on grids
      batchMax:  6,
      onEnter: batch => gsap.to(batch, {
        opacity:   1,
        y:         0,
        duration:  0.75,
        ease:      'power3.out',
        stagger:   0.09,
        overwrite: true,
      }),
      once:  true,
      start: 'top 91%',
    });

    // Refresh once layout is settled
    ST.refresh();
    return () => ST.getAll().forEach(t => t.kill());
  }, []);
}

function Masthead() {
  const [hi, setHi] = useS(0);
  useE(() => {
    const id = setInterval(() => setHi((h) => (h + 1) % MAST_WORDS.length), 1150);
    return () => clearInterval(id);
  }, []);
  const sub = MAST_WORDS[hi].toLowerCase();
  return (
    <section className="mast lp-wrap">
      <div className="mast-grid">
        <div className="mast-copy">
          <p className="mast-eyebrow">Bitcoin-Anchored Authenticity</p>
          <h1 className="mast-h1">
            <span className="fixed">A Record of</span>
            <span className="mast-stack">
              {MAST_WORDS.map((w, i) => (
                <span key={w} className={'mast-line' + (i === hi ? ' on' : '')}>{w}.</span>
              ))}
            </span>
          </h1>
          <p className="mast-url mono">
            <span className="arrow">→</span><span className="host">{sub}.arcproof.ing</span>
          </p>
          <p className="mast-lead">
            No trusted intermediaries. No certificates that expire. No single point of failure.
            Bitcoin-anchored cryptographic proof, verifiable by anyone, forever.
          </p>
          <div className="mast-cta">
            <a className="btn-fill" href="app.html">Explore the Verticals <span aria-hidden="true">→</span></a>
            <a className="btn-ghost" href="#verify">Verify a Record</a>
          </div>
          <div className="trust">
            <span className="ti"><span className="d" />2.4M records anchored</span>
            <span className="ti"><span className="d" />Open-source protocol</span>
          </div>
        </div>
        <BitcoinShowpiece />
      </div>
    </section>
  );
}

function VerticalStrip({ onCompare }) {
  const verticals = window.ARC_VERTICALS;
  const [hover, setHover] = useS(null);
  return (
    <section className="lp-sec lp-wrap">
      <div className="vstrip-head rv">
        <p className="lp-eyebrow">Every Compliance Framework</p>
        <h2 className="lp-h2">One protocol. <span className="dim">Every compliance framework.</span></h2>
        <p className="lp-lead">
          Patent priority. Legal evidence. FDA compliance. Research integrity. Trade secrets.
          Contract execution. One cryptographic timestamp satisfies them all.
        </p>
      </div>
      <div className="vpills rv" onMouseLeave={() => setHover(null)}>
        {verticals.map((v) => (
          <a
            key={v.slug}
            className={'vpill' + (hover && hover.slug === v.slug ? ' on' : '')}
            href="app.html"
            onMouseEnter={() => setHover(v)}
            onFocus={() => setHover(v)}
            onBlur={() => setHover(null)}
          >
            {v.word}<span className="ar">↗</span>
          </a>
        ))}
      </div>
      <div className={'vdesc' + (hover ? ' on' : '')} aria-live="polite">
        {hover ? (
          <div className="vd-card" key={hover.slug}>
            <p className="vd-url mono">{hover.subdomain}</p>
            <p className="vd-tag">{hover.tagline}</p>
            <p className="vd-desc">{hover.description}</p>
          </div>
        ) : (
          <p className="vd-hint">Hover a vertical to see what it proves.</p>
        )}
      </div>
      <button className="cmp-link rv" onClick={onCompare}>
        Compare every plan<span className="ar" aria-hidden="true">→</span>
      </button>
    </section>
  );
}

const PILLARS = [
  { glyph: '◉', title: 'Capture', sub: 'Mobile-first with GPS, accelerometer, and device attestation. Every detail recorded.', enter: true },
  { glyph: '◈', title: 'Anchor', sub: 'Cryptographically committed to Bitcoin — the most secure blockchain on Earth.', enter: false },
  { glyph: '◇', title: 'Verify', sub: 'Public verification anyone can perform. No account, no trust required.', enter: true },
];

function Pillars() {
  return (
    <section className="lp-sec lp-wrap" id="features">
      <div className="pillars rv">
        {PILLARS.map((p) => (
          <div className="pillar" key={p.title}>
            <div className="glyph">{p.glyph}</div>
            <h3>{p.title}</h3>
            <p>{p.sub}</p>
            {p.enter && <div className="enter">Enter <span className="ar" aria-hidden="true">→</span></div>}
          </div>
        ))}
      </div>
    </section>
  );
}

function Legal() {
  return (
    <section className="lp-sec lp-wrap">
      <p className="lp-eyebrow rv">Legal Acceptance</p>
      <h2 className="lp-h2 rv">Courts have already decided.</h2>
      <div className="legal-grid">
        <div className="lcard rv">
          <p className="when">France · March 2025</p>
          <p className="court">Tribunal Judiciaire de Marseille</p>
          <p className="what">Accepted blockchain timestamps as legal evidence of document existence and integrity.</p>
        </div>
        <div className="lcard rv">
          <p className="when">Italy · June 2025</p>
          <p className="court">Tribunale di Milano</p>
          <p className="what">Blockchain timestamps recognized as admissible evidence under the Italian Civil Code.</p>
        </div>
        <div className="lcard ghost rv">
          <p className="when">Jurisdiction · TBD</p>
          <p className="court">Undisclosed at counsel’s request</p>
          <p className="what">Proceedings ongoing. Details to be published upon judgment.</p>
        </div>
      </div>
    </section>
  );
}

const SCENARIOS = [
  { t: 'Accident scene', d: 'Cars will move. Weather will change. Capture before the tow truck arrives.' },
  { t: 'Move-in', d: 'Every scuff, every stain. Timestamped before the tenant gets keys.' },
  { t: 'The finished piece', d: 'Your art, your studio, your timestamp — before it hits the internet.' },
  { t: 'On the ground', d: 'Prove you were there. Prove when. Prove the photo wasn\u2019t generated.' },
];
const META = [
  { l: 'GPS Coordinates', d: 'Within 4 meters' },
  { l: 'NTP-Verified Time', d: 'Atomic-clock synced' },
  { l: 'Device Attestation', d: 'Hardware-signed' },
  { l: 'Motion Data', d: 'Handheld vs. staged' },
];

function Phone() {
  const [time, setTime] = useS(() => new Date().toTimeString().slice(0, 8));
  const [coords, setCoords] = useS({ lat: '37.7749°N', lng: '122.4194°W' });
  useE(() => {
    const id = setInterval(() => setTime(new Date().toTimeString().slice(0, 8)), 1000);
    return () => clearInterval(id);
  }, []);
  useE(() => {
    fetch('https://ipapi.co/json/').then((r) => r.json()).then((d) => {
      const lat = parseFloat(d.latitude), lng = parseFloat(d.longitude);
      if (!isNaN(lat) && !isNaN(lng)) setCoords({
        lat: `${Math.abs(lat).toFixed(4)}°${lat >= 0 ? 'N' : 'S'}`,
        lng: `${Math.abs(lng).toFixed(4)}°${lng >= 0 ? 'E' : 'W'}`,
      });
    }).catch(() => {});
  }, []);
  // 3D tilt toward the cursor (ported from the original PhoneMockup)
  const [tilt, setTilt] = useS({ rx: 0, ry: 0 });
  const onMove = (e) => {
    const r = e.currentTarget.getBoundingClientRect();
    const clamp = (v) => Math.max(-150, Math.min(150, v));
    const dx = clamp(e.clientX - (r.left + r.width / 2));
    const dy = clamp(e.clientY - (r.top + r.height / 2));
    setTilt({ rx: (dy / 150) * -8, ry: (dx / 150) * 8 });
  };
  const onLeave = () => setTilt({ rx: 0, ry: 0 });
  return (
    <div className="phone-wrap" onMouseMove={onMove} onMouseLeave={onLeave}>
      <div className="phone" style={{ transform: `rotateX(${tilt.rx}deg) rotateY(${tilt.ry}deg)` }}>
        <div className="notch" />
        <div className="screen">
          <div className="viewfinder" />
          <div className="grid-l">
            <i style={{ left: '33.3%', top: 0, bottom: 0, width: '1px' }} />
            <i style={{ right: '33.3%', top: 0, bottom: 0, width: '1px' }} />
            <i style={{ top: '33.3%', left: 0, right: 0, height: '1px' }} />
            <i style={{ bottom: '33.3%', left: 0, right: 0, height: '1px' }} />
          </div>
          <div className="topbar">
            <span className="gps"><span className="d" />GPS LOCKED</span>
            <span className="clk">{time}</span>
          </div>
          <div className="focus"><i /></div>
          <div className="readout">
            <div className="r"><span className="k">LAT</span><span className="v">{coords.lat}</span></div>
            <div className="r"><span className="k">LNG</span><span className="v">{coords.lng}</span></div>
            <div className="r"><span className="k">ACC</span><span className="v">±4m</span></div>
            <div className="r"><span className="k">NTP</span><span className="v">SYNCED</span></div>
            <div className="r"><span className="k">MOTION</span><span className="v">STABLE</span></div>
          </div>
          <div className="shutter"><i /></div>
          <div className="flash" />
        </div>
        <div className="sbtn" style={{ right: 0, top: '128px', width: '3px', height: '48px', borderRadius: '3px 0 0 3px' }} />
        <div className="sbtn" style={{ left: 0, top: '112px', width: '3px', height: '32px', borderRadius: '0 3px 3px 0' }} />
        <div className="sbtn" style={{ left: 0, top: '160px', width: '3px', height: '48px', borderRadius: '0 3px 3px 0' }} />
      </div>
      <div className="phone-glow" />
    </div>
  );
}

function InTheField() {
  return (
    <section className="lp-sec lp-wrap">
      <div className="field-grid">
        <Phone />
        <div className="field-copy">
          <p className="lp-eyebrow rv">In the Field</p>
          <h2 className="lp-h2 rv">Evidence doesn’t wait.</h2>
          <p className="lp-lead rv">
            Some moments can’t be recreated. Your phone becomes a notary — GPS, timestamp,
            motion data, device attestation — captured before you leave the scene.
          </p>
          <div className="scen-grid rv">
            {SCENARIOS.map((s) => (
              <div className="scen" key={s.t}><h4>{s.t}</h4><p>{s.d}</p></div>
            ))}
          </div>
          <div className="meta-grid rv">
            {META.map((m) => (
              <div className="meta" key={m.l}><p className="ml">{m.l}</p><p className="md">{m.d}</p></div>
            ))}
          </div>
          <p className="field-foot rv">EXIF data can be edited. ARC Proof captures can’t.</p>
        </div>
      </div>
    </section>
  );
}

const STEPS = [
  { n: '01', t: 'Capture', d: 'Open Builder on any device. Capture photo, video, document, or audio with full sensor data.' },
  { n: '02', t: 'Hash', d: 'SHA-256 fingerprint computed locally. Your file never leaves your device.' },
  { n: '03', t: 'Anchor', d: 'Hash submitted to Bitcoin via OpenTimestamps. Batched with thousands of others.' },
  { n: '04', t: 'Confirm', d: 'Within hours, your ARC Proof is permanently anchored to Bitcoin. Verifiable forever.' },
];

function HowItWorks() {
  return (
    <section className="lp-sec lp-wrap" id="how-it-works">
      <div className="steps-head rv">
        <p className="lp-eyebrow">How It Works</p>
        <h2 className="lp-h2">From capture to confirmation in four steps.</h2>
      </div>
      <div className="steps rv">
        <div className="rail" />
        <div className="steps-grid">
          {STEPS.map((s) => (
            <div className="step" key={s.n}>
              <div className="num">{s.n}</div>
              <div className="node" />
              <h3>{s.t}</h3>
              <p>{s.d}</p>
            </div>
          ))}
        </div>
      </div>
    </section>
  );
}

const UCASES = [
  { m: '01', stat: '$3M+', sl: 'avg. cost to defend a patent lawsuit', t: 'Legal', d: 'Document incidents, preserve chain of custody, authenticate evidence for litigation.' },
  { m: '02', stat: '3,000%', sl: 'rise in deepfake fraud cases in 2023', t: 'Media', d: 'Combat deepfakes. Prove when and where photos and videos were actually captured.' },
  { m: '03', stat: '$225B', sl: 'annual IP theft cost to US economy', t: 'IP & Research', d: 'Establish prior art, protect trade secrets, document R&D timelines.' },
  { m: '04', stat: '16%', sl: 'of homeowners insurance claims denied outright', t: 'Risk Management', d: 'Capture conditions before the claim is filed. Documentation that can\u2019t be disputed.' },
  { m: '05', stat: '5B+', sl: 'images scraped to train AI without consent', t: 'Artists & Creators', d: 'Prove you made it before the AI scraped it. Your work, your timestamp.' },
  { m: '06', stat: '$42.8M', sl: 'avg. construction dispute value (2023)', t: 'Construction', d: 'Site conditions documented before the subcontractor disputes it.' },
];

function UseCases() {
  return (
    <section className="lp-sec lp-wrap" id="use-cases">
      <div className="ucases-head rv">
        <p className="lp-eyebrow">Use Cases</p>
        <h2 className="lp-h2">Trusted by those who can’t afford doubt.</h2>
      </div>
      <div className="ucases">
        {UCASES.map((u) => (
          <div className="ucard rv" key={u.m}>
            <div className="utop">
              <span className="umark">{u.m}</span>
              <div className="ustat"><div className="sv">{u.stat}</div><div className="sl">{u.sl}</div></div>
            </div>
            <h3>{u.t}</h3>
            <p>{u.d}</p>
          </div>
        ))}
      </div>
    </section>
  );
}

// Monochrome ray-marched SDF backdrop for the Security section.
//
// Adapted from "RayMarching starting point" by Martijn Steinrucken aka
// The Art of Code / BigWings — 2020 (countfrolic@gmail.com, @The_ArtOfCode).
// Licensed under the MIT License. The above copyright notice and this
// permission notice are included per the MIT terms; the software is provided
// "as is", without warranty of any kind.
//
// Adaptations: stripped the blue palette (pal()) and the iChannel0 texture
// reflection — replaced with a procedural grayscale environment — and reduced
// MAX_STEPS, to fit the locked monotone aesthetic and run in-browser. See
// landing.css .sec-shader.
const SDF_FRAG = `
precision highp float;
uniform vec2 iResolution;
uniform float iTime;

#define MAX_STEPS 200
#define MAX_DIST 10.
#define SURF_DIST .001

mat2 Rot(float a){ float s=sin(a),c=cos(a); return mat2(c,-s,s,c); }

float GetDist(vec3 p){
  vec2 uv = p.xz;
  uv.x = abs(uv.x);
  float time = 12. + iTime;
  vec2 q = vec2(1,0);
  float th = 0.4*p.y - 0.6*time;
  float m = 1.8;
  for(int i=0;i<9;i++){
    uv -= m*q;
    th += 0.5*p.y + 0.05*time;
    uv = Rot(th)*uv;
    uv.x = abs(uv.x);
    m *= 0.05*cos(8.*length(uv)) + 0.55;
  }
  float d = length(uv) - 2.*m;
  return 0.5*d;
}

float RayMarch(vec3 ro, vec3 rd){
  float dO=0.;
  for(int i=0;i<MAX_STEPS;i++){
    vec3 p = ro + rd*dO;
    float dS = GetDist(p);
    dO += dS;
    if(dO>MAX_DIST || abs(dS)<SURF_DIST) break;
  }
  return dO;
}

vec3 GetNormal(vec3 p){
  float d = GetDist(p);
  vec2 e = vec2(.001,0);
  vec3 n = d - vec3(GetDist(p-e.xyy), GetDist(p-e.yxy), GetDist(p-e.yyx));
  return normalize(n);
}

vec3 GetRayDir(vec2 uv, vec3 p, vec3 l, float z){
  vec3 f = normalize(l-p),
       r = normalize(cross(vec3(0,1,0), f)),
       u = cross(f,r),
       c = f*z,
       i = c + uv.x*r + uv.y*u,
       d = normalize(i);
  return d;
}

void mainImage(out vec4 fragColor, in vec2 fragCoord){
  vec2 uv = (fragCoord-.5*iResolution.xy)/iResolution.y;
  float rad = 5.5;
  vec3 ro = vec3(rad, 0.1*iTime, 0.0);
  vec3 rd = GetRayDir(uv, ro, vec3(0,0.1*iTime,0), 2.);
  vec3 col = vec3(0);
  float d = RayMarch(ro, rd);
  if(d<MAX_DIST){
    vec3 p = ro + rd*d;
    vec3 n = GetNormal(p);
    vec3 refl = reflect(rd, n);
    float ambient = .3;
    float difPower = .4;
    float dif = max(dot(n, normalize(vec3(1,2,3))), 0.);
    col = vec3(dif*difPower + ambient);
    // procedural grayscale environment in place of iChannel0
    float env = 0.35 + 0.65*smoothstep(-0.6, 0.9, refl.y);
    col *= vec3(env);
    col *= 1. + refl.y;
    col = clamp(col, 0., 1.);
  }
  col = pow(col, vec3(.4545)); // gamma
  fragColor = vec4(col, 1.0);
}

void main(){
  vec4 c;
  mainImage(c, gl_FragCoord.xy);
  gl_FragColor = c;
}
`;

function ShaderBackdrop() {
  const ref = useR(null);
  useE(() => {
    const canvas = ref.current;
    if (!canvas) return;
    const gl = canvas.getContext('webgl', { antialias: false, alpha: false });
    if (!gl) return;
    const reduce = window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches;

    const 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 vs = compile(gl.VERTEX_SHADER, 'attribute vec2 p;void main(){gl_Position=vec4(p,0.,1.);}');
    const fs = compile(gl.FRAGMENT_SHADER, SDF_FRAG);
    const prog = gl.createProgram();
    gl.attachShader(prog, vs);
    gl.attachShader(prog, fs);
    gl.linkProgram(prog);
    if (!gl.getProgramParameter(prog, gl.LINK_STATUS)) { console.error(gl.getProgramInfoLog(prog)); return; }
    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 loc = gl.getAttribLocation(prog, 'p');
    gl.enableVertexAttribArray(loc);
    gl.vertexAttribPointer(loc, 2, gl.FLOAT, false, 0, 0);

    const uRes = gl.getUniformLocation(prog, 'iResolution');
    const uTime = gl.getUniformLocation(prog, 'iTime');

    let w = 0, h = 0;
    const SCALE = 0.5; // render at half CSS resolution and upscale — it's a soft backdrop
    const resize = () => {
      const r = canvas.getBoundingClientRect();
      const nw = Math.max(1, Math.round(r.width * SCALE));
      const nh = Math.max(1, Math.round(r.height * SCALE));
      if (nw === w && nh === h) return;
      w = nw; h = nh;
      canvas.width = w; canvas.height = h;
      gl.viewport(0, 0, w, h);
    };

    let raf = 0, running = false;
    const t0 = performance.now();
    const draw = () => {
      resize();
      gl.uniform2f(uRes, w, h);
      gl.uniform1f(uTime, (performance.now() - t0) / 1000);
      gl.drawArrays(gl.TRIANGLES, 0, 3);
    };
    const loop = () => { draw(); raf = requestAnimationFrame(loop); };
    const startLoop = () => { if (running) return; running = true; reduce ? draw() : (raf = requestAnimationFrame(loop)); };
    const stopLoop = () => { running = false; cancelAnimationFrame(raf); };

    const io = new IntersectionObserver((ents) => {
      ents.forEach((e) => (e.isIntersecting ? startLoop() : stopLoop()));
    }, { threshold: 0.01 });
    io.observe(canvas);
    window.addEventListener('resize', draw);

    return () => {
      stopLoop();
      io.disconnect();
      window.removeEventListener('resize', draw);
      const ext = gl.getExtension('WEBGL_lose_context');
      if (ext) ext.loseContext();
    };
  }, []);
  return <canvas className="shader-canvas" ref={ref} aria-hidden="true" />;
}

function Security() {
  return (
    <section className="lp-sec sec-shader" id="security">
      <ShaderBackdrop />
      <div className="sec-veil" />
      <div className="lp-wrap sec-inner">
        <div className="sec-grid">
          <div className="sec-copy">
            <p className="lp-eyebrow rv">Security Model</p>
            <h2 className="lp-h2 rv">Protected by $500B in computational work.</h2>
            <p className="lp-lead rv">
              Bitcoin’s proof-of-work isn’t just currency infrastructure — it’s the most secure
              timestamping system ever created. To forge an ARC Proof record, an attacker would need
              to re-mine every subsequent block, requiring more energy than many nations consume.
            </p>
            <div className="sec-points rv">
              {['No trusted third party required', 'No certificates that expire', 'No single point of failure'].map((p) => (
                <div className="p" key={p}><span className="d" />{p}</div>
              ))}
            </div>
          </div>
          <div className="metrics rv">
            <div className="metric"><p className="mk">Network Hash Rate</p><div className="mv">850 EH/s</div><p className="ms">Exahashes per second</p></div>
            <div className="div" />
            <div className="metric"><p className="mk">Energy to Attack (1 hour)</p><div className="mv">~7.3 GW</div><p className="ms">More than Switzerland consumes</p></div>
            <div className="div" />
            <div className="metric"><p className="mk">Cost to Forge (6 confirmations)</p><div className="mv em">Impractical</div><p className="ms">~$10B+ in hardware and energy</p></div>
          </div>
        </div>
      </div>
    </section>
  );
}

const STATS = [
  { v: '2.4M', l: 'Records Anchored' },
  { v: '2', l: 'Countries — Legally Accepted' },
  { v: '99.97%', l: 'Confirmation Rate' },
  { v: '< 0.01¢', l: 'Per Record' },
];

function StatsBar() {
  return (
    <section className="statsbar">
      <div className="lp-wrap stats-grid rv">
        {STATS.map((s) => (
          <div className="stat" key={s.l}><div className="sv">{s.v}</div><div className="sl">{s.l}</div></div>
        ))}
      </div>
    </section>
  );
}

function FinalCTA() {
  return (
    <section className="lp-final lp-wrap rv" id="verify">
      <h2>Ready to establish proof?</h2>
      <p>Join legal professionals, IP counsel, researchers, and creators who trust mathematics over institutions.</p>
      <div className="lp-cta">
        <a className="btn-fill" href="app.html">ARC Proof it. <span aria-hidden="true">→</span></a>
        <a className="btn-ghost" href="app.html">Verify a Record</a>
      </div>
    </section>
  );
}

function Landing() {
  useReveal();
  const [compareOpen, setCompareOpen] = useS(false);
  return (
    <div className="lp">
      <Nav />
      <Masthead />
      <VerticalStrip onCompare={() => setCompareOpen(true)} />
      <Pillars />
      <Legal />
      <InTheField />
      <HowItWorks />
      <UseCases />
      <Security />
      <StatsBar />
      <FinalCTA />
      <Footer />
      <ComparisonModal open={compareOpen} onClose={() => setCompareOpen(false)} />
    </div>
  );
}

ReactDOM.createRoot(document.getElementById('root')).render(<Landing />);
