// ==== Hero — editorial restatement ===================================
// Three.js scene: a slow rotating 3D dot constellation. ONE colour
// (champagne, derived from --accent). No rainbow cycling, no aurora curtains.
// The dots are a manifold — denser near the equator, sparse at poles —
// and breathe with a subtle scroll-driven scale.

function initBackgroundScene() {
  if (window.__bgScene) return window.__bgScene;
  if (!window.THREE) return null;

  const canvas = document.getElementById("bg-canvas");
  if (!canvas) return null;

  const renderer = new THREE.WebGLRenderer({
    canvas,
    antialias: true,
    alpha: true,
    powerPreference: "high-performance",
  });
  renderer.setPixelRatio(Math.min(window.devicePixelRatio || 1, 1.8));
  renderer.setClearColor(0x000000, 0);

  const scene = new THREE.Scene();
  const camera = new THREE.PerspectiveCamera(35, 1, 0.1, 100);
  camera.position.set(0, 0, 7);

  // -------- The dot constellation --------
  // Sample points on a deformed sphere; project into a particle cloud.
  const COUNT = window.matchMedia("(max-width: 880px)").matches ? 1400 : 2400;
  const positions = new Float32Array(COUNT * 3);
  const seeds     = new Float32Array(COUNT);          // per-particle phase
  const sizes     = new Float32Array(COUNT);

  // Champagne (matches CSS --accent in linear-ish RGB)
  const accentColor = new THREE.Color(0xD4AE74);

  for (let i = 0; i < COUNT; i++) {
    // Fibonacci sphere — even distribution, then perturbed for organic feel
    const t = i / (COUNT - 1);
    const phi = Math.acos(1 - 2 * t);
    const theta = Math.PI * (1 + Math.sqrt(5)) * i;

    // Radius modulated by low-freq noise so the surface "breathes"
    const r = 3.4 + Math.sin(theta * 0.7) * 0.32 + Math.cos(phi * 1.3) * 0.24;

    positions[i * 3]     = r * Math.sin(phi) * Math.cos(theta);
    positions[i * 3 + 1] = r * Math.sin(phi) * Math.sin(theta) * 0.78;  // squash for cinematic ratio
    positions[i * 3 + 2] = r * Math.cos(phi) * 0.9;

    seeds[i] = Math.random();
    sizes[i] = 0.45 + Math.random() * 0.55;
  }

  const geom = new THREE.BufferGeometry();
  geom.setAttribute("position", new THREE.BufferAttribute(positions, 3));
  geom.setAttribute("aSeed",    new THREE.BufferAttribute(seeds, 1));
  geom.setAttribute("aSize",    new THREE.BufferAttribute(sizes, 1));

  const uniforms = {
    uTime:   { value: 0 },
    uScroll: { value: 0 },
    uMouse:  { value: new THREE.Vector2(0, 0) },
    uPixel:  { value: renderer.getPixelRatio() },
    uColor:  { value: accentColor },
  };

  const material = new THREE.ShaderMaterial({
    transparent: true,
    depthWrite: false,
    blending: THREE.NormalBlending,
    uniforms,
    vertexShader: /* glsl */`
      attribute float aSeed;
      attribute float aSize;
      uniform float uTime;
      uniform float uScroll;
      uniform vec2  uMouse;
      uniform float uPixel;
      varying float vAlpha;
      varying float vDepth;

      void main() {
        vec3 p = position;

        // Slow breathing — every particle shifts radially on a low-freq sine
        float breathe = sin(uTime * 0.18 + aSeed * 6.28) * 0.04;
        p *= 1.0 + breathe;

        // Mouse parallax — feather-light
        p.x += uMouse.x * 0.2 * (0.4 + aSeed * 0.6);
        p.y += uMouse.y * 0.2 * (0.4 + aSeed * 0.6);

        // Scroll-driven zoom-out (camera-space)
        vec4 mv = modelViewMatrix * vec4(p, 1.0);
        mv.z -= uScroll * 1.2;
        gl_Position = projectionMatrix * mv;

        // Size + perspective-correct attenuation
        float size = aSize * (90.0 / -mv.z) * uPixel;
        gl_PointSize = size;

        // Carve a quiet hole in the middle of the screen for text readability.
        // Compute screen-space distance from centre after projection.
        vec2 ndc = gl_Position.xy / gl_Position.w;
        // Asymmetric hole: text is left-aligned, so carve out the left 2/3 more aggressively.
        vec2 carve = ndc * vec2(0.7, 1.3);
        float centerMask = smoothstep(0.35, 0.95, length(carve));

        // Depth-based alpha (front bright, back fades)
        vDepth = clamp((-mv.z - 4.0) / 8.0, 0.0, 1.0);
        vAlpha = mix(0.32, 0.06, vDepth) * centerMask;

        // Equatorial brightness boost — denser middle band
        float eq = 1.0 - abs(position.y / 2.6);
        vAlpha *= mix(0.45, 1.0, smoothstep(0.0, 0.7, eq));
      }
    `,
    fragmentShader: /* glsl */`
      precision highp float;
      uniform vec3 uColor;
      varying float vAlpha;
      varying float vDepth;

      void main() {
        // Disc with soft edge — no hard squares
        vec2 c = gl_PointCoord - 0.5;
        float d = length(c);
        float disk = smoothstep(0.5, 0.05, d);

        // Slight warmth shift on back-particles (cooler when far)
        vec3 col = mix(uColor * 1.0, uColor * 0.65, vDepth);

        float a = disk * vAlpha;
        gl_FragColor = vec4(col, a);
      }
    `,
  });

  const points = new THREE.Points(geom, material);
  scene.add(points);

  // Subtle haze plane behind the dots — very faint warm vignette
  const hazeGeom = new THREE.PlaneGeometry(40, 24);
  const hazeMat = new THREE.ShaderMaterial({
    transparent: true,
    depthWrite: false,
    uniforms: { uColor: { value: accentColor } },
    vertexShader: `varying vec2 vUv; void main(){ vUv = uv; gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0); }`,
    fragmentShader: `
      varying vec2 vUv;
      uniform vec3 uColor;
      void main(){
        vec2 c = vUv - 0.5;
        float r = length(c) * 1.7;
        float halo = smoothstep(0.95, 0.35, r) * 0.025;
        gl_FragColor = vec4(uColor, halo);
      }
    `,
  });
  const haze = new THREE.Mesh(hazeGeom, hazeMat);
  haze.position.z = -4.0;
  scene.add(haze);

  function resize() {
    const w = window.innerWidth;
    const h = window.innerHeight;
    renderer.setSize(w, h, false);
    camera.aspect = w / h;
    camera.updateProjectionMatrix();
  }
  resize();
  window.addEventListener("resize", resize);

  // Live mouse — damped
  const liveMouse = { x: 0, y: 0 };
  window.addEventListener("pointermove", (e) => {
    liveMouse.x = (e.clientX / window.innerWidth) * 2 - 1;
    liveMouse.y = -((e.clientY / window.innerHeight) * 2 - 1);
  }, { passive: true });

  let scrollAmt = 0;
  function onScroll() {
    const max = (document.documentElement.scrollHeight - window.innerHeight) || 1;
    scrollAmt = Math.min(1, Math.max(0, window.scrollY / max));
  }
  window.addEventListener("scroll", onScroll, { passive: true });
  onScroll();

  const start = performance.now();
  function loop() {
    const t = (performance.now() - start) / 1000;
    uniforms.uTime.value = t;
    uniforms.uScroll.value = scrollAmt;
    uniforms.uMouse.value.x += (liveMouse.x - uniforms.uMouse.value.x) * 0.04;
    uniforms.uMouse.value.y += (liveMouse.y - uniforms.uMouse.value.y) * 0.04;

    // Slow signature rotation — full revolution every ~110s
    points.rotation.y = t * 0.058 + uniforms.uMouse.value.x * 0.12;
    points.rotation.x = Math.sin(t * 0.05) * 0.18 + uniforms.uMouse.value.y * 0.08;

    renderer.render(scene, camera);
    requestAnimationFrame(loop);
  }
  loop();

  window.__bgScene = { scene, renderer, camera, material };
  return window.__bgScene;
}

function Hero() {
  useEffect(() => {
    requestAnimationFrame(initBackgroundScene);
  }, []);

  return (
    <section id="hero" data-screen-label="01 Hero">
      <div className="hero-wrap">
        <div className="hero-eyebrow">
          <span className="dot" /> Bangalore · open to relocation
        </div>

        <h1 className="hero-name">
          <span className="n-first">Ayush</span>
          <span className="n-last">Kumar<span className="n-stop">.</span></span>
        </h1>

        <p className="hero-statement">
          I build the systems that let AI agents do <em>real work</em> in real companies —
          without leaking secrets, hallucinating into production, or holding more
          autonomy than a junior analyst.
        </p>

        <div className="hero-row">
          <button className="btn primary" onClick={() => scrollToId("projects")}>
            See the work <span className="arr">→</span>
          </button>
          <button className="btn" onClick={() => scrollToId("contact")}>
            Get in touch
          </button>
        </div>

        <div className="hero-sig">
          <div className="sig-line">
            <span className="sig-k">Now</span>
            <span className="sig-v">Lead Architect &mdash; Agentic AI &amp; Security, <b>Eli Lilly</b></span>
          </div>
          <div className="sig-line">
            <span className="sig-k">Before</span>
            <span className="sig-v">Founding engineer, <b>SuperAGI</b> &middot; 21k&#9733; on GitHub</span>
          </div>
          <div className="sig-line">
            <span className="sig-k">2025</span>
            <span className="sig-v">NullCon <b>AI Paper of the Year</b></span>
          </div>
        </div>
      </div>

      <div className="hero-scroll-cue" aria-hidden="true">
        <span className="cue-bar" />
        <span className="cue-lbl">Scroll</span>
      </div>
    </section>
  );
}

Object.assign(window, { Hero, initBackgroundScene });
