/* ZaviFx cinematic hero — dark stage, kinetic editorial headline, 3D brand sphere.
   Intentional dark component (like the footer / ink product card), not a dark theme. */
const { Button, Badge } = window.ZaviFxDesignSystem_f15c31;

const ROTATING = ['systems.', 'engines.', 'websites.', 'brands.'];

/* ---------- scroll-reveal helper used by the whole page ---------- */
function useReveal() {
  React.useEffect(() => {
    if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) {
      document.querySelectorAll('[data-reveal]').forEach((el) => el.setAttribute('data-shown', ''));
      return;
    }
    const io = new IntersectionObserver((entries) => {
      entries.forEach((e) => { if (e.isIntersecting) { e.target.setAttribute('data-shown', ''); io.unobserve(e.target); } });
    }, { rootMargin: '0px 0px -12% 0px', threshold: 0.08 });
    const scan = () => document.querySelectorAll('[data-reveal]:not([data-shown])').forEach((el) => io.observe(el));
    scan();
    const t = setInterval(scan, 600);
    return () => { clearInterval(t); io.disconnect(); };
  }, []);
}

/* ---------- three.js sphere, hero-scale ---------- */
function HeroSphere3D({ intensity = 1 }) {
  const mount = React.useRef(null);
  const [fallback, setFallback] = React.useState(false);
  const reduce = typeof window.matchMedia === 'function' && window.matchMedia('(prefers-reduced-motion: reduce)').matches;

  React.useEffect(() => {
    if (reduce || !window.THREE || !mount.current) { setFallback(true); return; }
    const THREE = window.THREE, el = mount.current;
    let w = el.clientWidth, h = el.clientHeight;
    const mobile = w < 720;
    const scene = new THREE.Scene();
    const camera = new THREE.PerspectiveCamera(36, w / h, 0.1, 100);
    camera.position.set(0, 0.2, 6.4);
    const renderer = new THREE.WebGLRenderer({ antialias: !mobile, alpha: true, powerPreference: 'high-performance' });
    renderer.setPixelRatio(Math.min(window.devicePixelRatio, mobile ? 1.5 : 2));
    renderer.setSize(w, h);
    el.appendChild(renderer.domElement);

    const tex = new THREE.TextureLoader().load(window.ASSETS + 'sphere-zavifx-texture.png');
    tex.anisotropy = 8;
    const ball = new THREE.Mesh(
      new THREE.SphereGeometry(1.5, mobile ? 56 : 128, mobile ? 36 : 80),
      new THREE.MeshStandardMaterial({ map: tex, emissiveMap: tex, emissive: new THREE.Color('#ffffff'), emissiveIntensity: 0.3, roughness: 0.22, metalness: 0.1 })
    );
    scene.add(ball);

    const halo = new THREE.Mesh(
      new THREE.SphereGeometry(1.95, 48, 32),
      new THREE.MeshBasicMaterial({ color: new THREE.Color('#FF7A2F'), transparent: true, opacity: 0.07 })
    );
    scene.add(halo);

    /* orbiting particle field — subtle, not decorative noise */
    const N = mobile ? 240 : 620;
    const pos = new Float32Array(N * 3);
    for (let i = 0; i < N; i++) {
      const r = 2.3 + Math.random() * 2.6, a = Math.random() * Math.PI * 2, b = (Math.random() - 0.5) * 1.1;
      pos[i * 3] = Math.cos(a) * r; pos[i * 3 + 1] = b * r * 0.42; pos[i * 3 + 2] = Math.sin(a) * r;
    }
    const pg = new THREE.BufferGeometry();
    pg.setAttribute('position', new THREE.BufferAttribute(pos, 3));
    const dust = new THREE.Points(pg, new THREE.PointsMaterial({ color: 0xffb277, size: 0.018, transparent: true, opacity: 0.5, sizeAttenuation: true }));
    scene.add(dust);

    scene.add(new THREE.HemisphereLight(0xffffff, 0x552200, 1.0));
    const key = new THREE.DirectionalLight(0xffffff, 2.4); key.position.set(3, 3.5, 4); scene.add(key);
    const rim = new THREE.PointLight(0xffb066, 4.0, 16); rim.position.set(-3.6, -1.4, 2.4); scene.add(rim);
    const cool = new THREE.PointLight(0x7fa8ff, 1.6, 16); cool.position.set(2.8, -2.4, -2.6); scene.add(cool);

    let raf = 0, t = 0, px = 0, py = 0, tx = 0, ty = 0, live = true, scroll = 0;
    const onPointer = (e) => {
      const r = el.getBoundingClientRect();
      tx = ((e.clientX - r.left) / r.width - 0.5) * 0.6;
      ty = ((e.clientY - r.top) / r.height - 0.5) * 0.34;
    };
    if (!mobile) window.addEventListener('pointermove', onPointer);
    const onScroll = () => { scroll = window.scrollY; };
    window.addEventListener('scroll', onScroll, { passive: true });

    const io = new IntersectionObserver(([e]) => { live = e.isIntersecting; }, { threshold: 0.02 });
    io.observe(el);

    const tick = () => {
      raf = requestAnimationFrame(tick);
      if (!live) return;
      t += 0.0055;
      px += (tx - px) * 0.045; py += (ty - py) * 0.045;
      const s = Math.min(scroll / 900, 1);
      ball.rotation.y = t * 1.35;
      ball.rotation.z = -0.2 + Math.sin(t * 0.55) * 0.05;
      ball.position.x = Math.sin(t * 0.45) * 0.22 + px * 1.5;
      ball.position.y = Math.sin(t * 0.95) * 0.05 - py - s * 0.9;
      ball.scale.setScalar(1 - s * 0.12);
      halo.position.copy(ball.position);
      halo.scale.setScalar(1 + Math.sin(t * 1.6) * 0.012);
      dust.rotation.y = -t * 0.42;
      dust.rotation.x = 0.16 + py * 0.3;
      dust.position.y = -s * 0.5;
      camera.position.x = px * 0.55;
      camera.lookAt(0, -s * 0.4, 0);
      renderer.render(scene, camera);
    };
    tick();

    const onResize = () => {
      w = el.clientWidth; h = el.clientHeight;
      camera.aspect = w / h; camera.updateProjectionMatrix(); renderer.setSize(w, h);
    };
    window.addEventListener('resize', onResize);

    return () => {
      cancelAnimationFrame(raf); io.disconnect();
      window.removeEventListener('resize', onResize);
      window.removeEventListener('pointermove', onPointer);
      window.removeEventListener('scroll', onScroll);
      ball.geometry.dispose(); ball.material.dispose(); tex.dispose();
      halo.geometry.dispose(); halo.material.dispose();
      pg.dispose(); dust.material.dispose();
      renderer.dispose();
      if (renderer.domElement.parentNode === el) el.removeChild(renderer.domElement);
    };
  }, [reduce]);

  const orbRef = React.useRef(null);
  const onOrbMove = (e) => {
    const el = orbRef.current || e.currentTarget;
    orbRef.current = el;
    const r = el.getBoundingClientRect();
    el.style.setProperty('--mx', (((e.clientX - r.left) / r.width) * 100).toFixed(2) + '%');
    el.style.setProperty('--my', (((e.clientY - r.top) / r.height) * 100).toFixed(2) + '%');
    el.dataset.reveal = '';
  };
  const onOrbLeave = (e) => { delete e.currentTarget.dataset.reveal; };

  return (
    <div aria-hidden="true" className="zx-hero__stage">
      <span className="zx-hero__bloom" />
      <span className="zx-orb__dustfield">
        {Array.from({ length: 26 }).map((_, n) => (
          <i key={n} className="zx-dust" style={{ '--a': (n * 13.8) + 'deg', '--r': (34 + (n % 7) * 9) + '%', '--d': (9 + (n % 5) * 3.4) + 's', '--s': (n % 4 === 0 ? 3 : 2) + 'px', animationDelay: (-n * 0.7) + 's' }} />
        ))}
      </span>
      <span className="zx-orb" onPointerMove={onOrbMove} onPointerLeave={onOrbLeave} onPointerEnter={onOrbMove}>
        <span className="zx-orb__ring zx-orb__ring--a" />
        <span className="zx-orb__ring zx-orb__ring--b" />
        <span className="zx-orb__ball">
          <span className="zx-orb__sheen" />
          <span className="zx-orb__dots" />
          <span className="zx-orb__scan" />
          <span className="zx-orb__shade" />
          <span className="zx-orb__spark">
            {Array.from({ length: 14 }).map((_, n) => (
              <i key={n} style={{ '--a': (n * 25.7) + 'deg', animationDelay: (n * 0.09) + 's' }} />
            ))}
          </span>
          <img src={window.ASSETS + 'logo-zavifx-white.png'} alt="" className="zx-orb__mark" />
        </span>
        <span className="zx-orb__sat zx-orb__sat--1" />
        <span className="zx-orb__sat zx-orb__sat--2" />
      </span>
      {!fallback && <div ref={mount} className="zx-hero__gl" />}
    </div>
  );
}

/* ---------- rotating word ---------- */
function WordSwap() {
  const [i, setI] = React.useState(0);
  React.useEffect(() => {
    if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) return;
    const id = setInterval(() => setI((n) => (n + 1) % ROTATING.length), 2400);
    return () => clearInterval(id);
  }, []);
  return (
    <span className="zx-swap zx-swap--chip" tabIndex={0}>
      <span className="zx-swap__ghost">websites.</span>
      {ROTATING.map((w, n) => (
        <span key={w} className="zx-swap__word" data-on={n === i ? '' : undefined}>{w}</span>
      ))}
    </span>
  );
}

function HeroCinematic({ go }) {
  const stage = React.useRef(null);
  const [tick, setTick] = React.useState(0);
  React.useEffect(() => {
    if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) return;
    const id = setInterval(() => setTick((n) => n + 1), 3200);
    return () => clearInterval(id);
  }, []);
  const trail = (e) => {
    const el = stage.current; if (!el) return;
    const r = el.getBoundingClientRect();
    el.style.setProperty('--cx', (((e.clientX - r.left) / r.width) * 100).toFixed(1) + '%');
    el.style.setProperty('--cy', (((e.clientY - r.top) / r.height) * 100).toFixed(1) + '%');
  };
  const proof = [['37+', 'websites shipped'], ['12', 'disciplines in-house'], ['48h', 'proposal turnaround'], ['1', 'point of contact']];

  return (
    <section className="zx-hero zx-hero--v2" ref={stage} onMouseMove={trail}>
      <span className="zx-hero__matrix" aria-hidden="true" />
      <span className="zx-hero__beam" aria-hidden="true" />
      <span className="zx-hero__torch" aria-hidden="true" />

      <div className="zx-hero__rail zx-hero__rail--l" aria-hidden="true">
        <span>ZaviFx</span><i /><span>Hyderabad · IN</span>
      </div>
      <div className="zx-hero__rail zx-hero__rail--r" aria-hidden="true">
        <div className="zx-hero__vmarq">
          <div className="zx-hero__vset">
            {['SEO', 'WordPress', 'UI/UX', 'Branding', 'Performance', 'Content', 'Social'].map((w) => <span key={w}>{w}</span>)}
          </div>
          <div className="zx-hero__vset">
            {['SEO', 'WordPress', 'UI/UX', 'Branding', 'Performance', 'Content', 'Social'].map((w) => <span key={w + 'b'}>{w}</span>)}
          </div>
        </div>
      </div>

      <div className="zx-container zx-hero__inner">
        <HeroSphere3D />

        <div className="zx-hero__eyebrow" data-reveal>
          <span className="zx-hero__dot" aria-hidden="true" />
          Digital &amp; creative technology · Hyderabad
        </div>

        <h1 className="zx-hero__title zx-hero__title--v2">
          <span className="zx-line"><span className="zx-line__in" style={{ animationDelay: '.10s' }}>Digital experiences</span></span>
          <span className="zx-line"><span className="zx-line__in" style={{ animationDelay: '.22s' }}>built to drive</span></span>
          <span className="zx-line">
            <span className="zx-line__in zx-hero__outline" style={{ animationDelay: '.34s' }} data-text="real growth.">real growth.</span>
          </span>
        </h1>

        <p className="zx-hero__sub" data-reveal>
          Strategy, design, engineering and performance marketing. One team, one brief, building growth <WordSwap />
        </p>

        <div className="zx-hero__cta" data-reveal>
          <button type="button" className="zx-hero__primary" onClick={() => go('contact')} data-magnetic>
            <span>Book a Free Consultation</span>
            <svg width="17" height="17" viewBox="0 0 16 16" fill="none" aria-hidden="true"><path d="M3.5 8h9M8.5 4l4 4-4 4" stroke="currentColor" strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round"/></svg>
          </button>
          <button type="button" className="zx-ghostbtn" onClick={() => go('work')}>
            <span className="zx-ghostbtn__ring" aria-hidden="true">
              <svg width="14" height="14" viewBox="0 0 16 16" fill="none"><path d="M3.5 8h9M8.5 4l4 4-4 4" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round"/></svg>
            </span>
            View Our Work
          </button>
        </div>

        <div className="zx-hero__proof" data-reveal>
          {proof.map(([v, k], n) => (
            <div key={k} className="zx-hero__pcell" data-on={tick % proof.length === n ? '' : undefined}>
              <strong>{v}</strong><span>{k}</span>
            </div>
          ))}
        </div>
      </div>

      <div className="zx-hero__scroll" aria-hidden="true">
        <span className="zx-hero__scrollword">Scroll</span>
        <span className="zx-hero__scrollline" />
      </div>
    </section>
  );
}

Object.assign(window, { HeroCinematic, useReveal, HeroSphere3D });
