
// ScrollJourney.jsx — Organic-minimal abstract scroll scene
// Aesthetic: Linear/Vercel/Stripe — breathing geometry, gradient meshes, no space/particles

const CHAPTERS = [
  {
    id: 0, label: "Origin",
    headline: "Your website is your conversion hub",
    body: "Every visitor is a potential customer. Your site should be engineered to earn their trust — not just fill a page.",
    accentColor: '#3B82F6',
    accentHex:   0x3B82F6,
    clearColor:  0x080f1e,
    fogColor:    0x080f1e,
  },
  {
    id: 1, label: "Problem",
    headline: "Most websites leak revenue",
    body: "Slow loads. Weak copy. No AI visibility. The average site loses 70% of potential customers before they ever reach a CTA.",
    accentColor: '#64748B',
    accentHex:   0x64748B,
    clearColor:  0x0a0a0e,
    fogColor:    0x0a0a0e,
  },
  {
    id: 2, label: "Solution",
    headline: "Built to win trust instantly",
    body: "We engineer trust signals, conversion flows, and messaging hierarchies that turn cold traffic into committed buyers.",
    accentColor: '#00b4ff',
    accentHex:   0x00b4ff,
    clearColor:  0x040e18,
    fogColor:    0x040e18,
  },
  {
    id: 3, label: "AEO",
    headline: "Get cited by every AI",
    body: "ChatGPT, Gemini, Claude — they all recommend sites they understand. We structure your content so AI recommends you first.",
    accentColor: '#9333EA',
    accentHex:   0x9333EA,
    clearColor:  0x0a0514,
    fogColor:    0x0a0514,
  },
  {
    id: 4, label: "Destination",
    headline: "Enter the Next World",
    body: "Websites that don't just exist — they thrive. Built for the AI era, optimised for humans, ready to grow your business.",
    accentColor: '#ADFF2F',
    accentHex:   0xADFF2F,
    clearColor:  0x040a02,
    fogColor:    0x040a02,
  },
];

// Each chapter gets equal scroll dwell: totalScroll / CHAPTERS.length
// progress 0→1 maps across all chapters with chapter 5 fully visible
const CHAPTER_COUNT = CHAPTERS.length;

const easeInOut3 = t => t < 0.5 ? 4*t*t*t : 1-Math.pow(-2*t+2,3)/2;
const lerp = (a, b, t) => a + (b - a) * t;
const clamp = (v, lo, hi) => Math.max(lo, Math.min(hi, v));

const ScrollJourney = () => {
  const mountRef     = React.useRef(null);
  const containerRef = React.useRef(null);
  const sceneRef     = React.useRef({});
  const progressRef  = React.useRef(0);
  const [activeChapter, setActiveChapter]     = React.useState(0);
  const [chapterProgress, setChapterProgress] = React.useState(0);
  const [textVisible, setTextVisible]         = React.useState(true);
  const [cardTilt, setCardTilt]               = React.useState({ x: 0, y: 0 });
  const [cardHovered, setCardHovered]         = React.useState(false);
  const cardRef                               = React.useRef(null);

  const handleCardMouseMove = React.useCallback((e) => {
    const card = cardRef.current;
    if (!card) return;
    const rect = card.getBoundingClientRect();
    const x = ((e.clientX - rect.left) / rect.width  - 0.5) * 2;
    const y = ((e.clientY - rect.top)  / rect.height - 0.5) * 2;
    setCardTilt({ x: -y * 7, y: x * 7 });
  }, []);

  const handleCardMouseLeave = React.useCallback(() => {
    setCardHovered(false);
    setCardTilt({ x: 0, y: 0 });
  }, []);

  React.useEffect(() => {
    if (!mountRef.current || typeof THREE === 'undefined') return;
    const el = mountRef.current;
    const W = el.clientWidth, H = el.clientHeight;

    // ── Renderer ──────────────────────────────────────────────────────────────
    const renderer = new THREE.WebGLRenderer({ antialias: true, alpha: false });
    renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
    renderer.setSize(W, H);
    renderer.setClearColor(CHAPTERS[0].clearColor, 1);
    el.appendChild(renderer.domElement);

    const scene = new THREE.Scene();
    scene.fog = new THREE.Fog(CHAPTERS[0].fogColor, 10, 90);

    const camera = new THREE.PerspectiveCamera(55, W/H, 0.1, 200);
    camera.position.set(0, 0, 18);
    camera.lookAt(0, 0, 0);

    // ── Lights ────────────────────────────────────────────────────────────────
    const ambientLight = new THREE.AmbientLight(0xffffff, 0.15);
    scene.add(ambientLight);

    // Main key light — color shifts per chapter
    const keyLight = new THREE.PointLight(CHAPTERS[0].accentHex, 3.5, 80);
    keyLight.position.set(8, 6, 12);
    scene.add(keyLight);

    // Rim / fill
    const rimLight = new THREE.PointLight(0xffffff, 0.8, 60);
    rimLight.position.set(-10, -4, 8);
    scene.add(rimLight);

    const backLight = new THREE.PointLight(CHAPTERS[0].accentHex, 1.2, 50);
    backLight.position.set(0, -8, -10);
    scene.add(backLight);

    // ── Background gradient mesh ───────────────────────────────────────────────
    // 4 large quads with additive blending create a gradient mesh feel
    const bgGroup = new THREE.Group();
    bgGroup.position.z = -30;
    scene.add(bgGroup);

    const bgPlanes = [];
    const bgConfigs = [
      { x:  12, y:  8, s: 35, opacity: 0.05 },
      { x: -10, y: -6, s: 28, opacity: 0.04 },
      { x:   2, y: 12, s: 40, opacity: 0.03 },
      { x:  -8, y:  4, s: 22, opacity: 0.04 },
    ];
    bgConfigs.forEach(cfg => {
      const geo = new THREE.PlaneGeometry(cfg.s, cfg.s);
      const mat = new THREE.MeshBasicMaterial({
        color: CHAPTERS[0].accentHex,
        transparent: true, opacity: cfg.opacity,
        depthWrite: false, blending: THREE.AdditiveBlending,
        side: THREE.DoubleSide,
      });
      const mesh = new THREE.Mesh(geo, mat);
      mesh.position.set(cfg.x, cfg.y, 0);
      mesh.rotation.z = Math.random() * Math.PI;
      bgGroup.add(mesh);
      bgPlanes.push({ mesh, mat, baseCfg: cfg });
    });

    // ── Chapter abstract forms ────────────────────────────────────────────────
    // Each chapter gets ONE hero geometry — minimal, deliberate

    // Ch 0 — Origin: Torus knot (flowing, connected, foundational)
    const ch0Group = new THREE.Group();
    const torusKnotGeo = new THREE.TorusKnotGeometry(3.2, 0.55, 200, 20, 2, 3);
    const ch0Mat = new THREE.MeshPhongMaterial({
      color: 0x0a1a3e,
      emissive: new THREE.Color(0x3B82F6),
      emissiveIntensity: 0.15,
      shininess: 120,
      specular: new THREE.Color(0x3B82F6),
      transparent: true, opacity: 0.92,
      wireframe: false,
    });
    const torusKnot = new THREE.Mesh(torusKnotGeo, ch0Mat);
    ch0Group.add(torusKnot);
    // Wireframe overlay
    const ch0WireMat = new THREE.MeshBasicMaterial({ color: 0x3B82F6, wireframe: true, transparent: true, opacity: 0.08 });
    ch0Group.add(new THREE.Mesh(torusKnotGeo, ch0WireMat));
    scene.add(ch0Group);

    // Ch 1 — Problem: Fractured icosahedron (broken, leaking)
    const ch1Group = new THREE.Group();
    const ch1Geo = new THREE.IcosahedronGeometry(4, 1);
    // Displace vertices outward randomly to "fragment" it
    const ch1Pos = ch1Geo.attributes.position;
    const ch1Displace = new Float32Array(ch1Pos.count);
    for (let i = 0; i < ch1Pos.count; i++) {
      ch1Displace[i] = (Math.random() - 0.5) * 1.2;
      const x = ch1Pos.getX(i), y = ch1Pos.getY(i), z = ch1Pos.getZ(i);
      const len = Math.sqrt(x*x+y*y+z*z);
      ch1Pos.setXYZ(i, x + (x/len)*ch1Displace[i], y + (y/len)*ch1Displace[i], z + (z/len)*ch1Displace[i]);
    }
    ch1Geo.computeVertexNormals();
    const ch1Mat = new THREE.MeshPhongMaterial({
      color: 0x111318,
      emissive: new THREE.Color(0x2a3040),
      emissiveIntensity: 0.18,
      shininess: 20,
      specular: new THREE.Color(0x64748B),
      transparent: true, opacity: 0.88,
    });
    ch1Group.add(new THREE.Mesh(ch1Geo, ch1Mat));
    const ch1WireMat = new THREE.MeshBasicMaterial({ color: 0x64748B, wireframe: true, transparent: true, opacity: 0.12 });
    ch1Group.add(new THREE.Mesh(ch1Geo, ch1WireMat));
    scene.add(ch1Group);

    // Ch 2 — Solution: Smooth subdivided octahedron (transforming, trustworthy)
    const ch2Group = new THREE.Group();
    const ch2Geo = new THREE.OctahedronGeometry(3.8, 3);
    const ch2Mat = new THREE.MeshPhongMaterial({
      color: 0x001830,
      emissive: new THREE.Color(0x0055aa),
      emissiveIntensity: 0.20,
      shininess: 160,
      specular: new THREE.Color(0x00b4ff),
      transparent: true, opacity: 0.9,
    });
    ch2Group.add(new THREE.Mesh(ch2Geo, ch2Mat));
    // Glowing edges
    const ch2WireMat = new THREE.MeshBasicMaterial({ color: 0x00b4ff, wireframe: true, transparent: true, opacity: 0.14 });
    ch2Group.add(new THREE.Mesh(ch2Geo, ch2WireMat));
    scene.add(ch2Group);

    // Ch 3 — AEO: Interconnected double torus (network, signal)
    const ch3Group = new THREE.Group();
    const torusGeoA = new THREE.TorusGeometry(3.5, 0.35, 32, 120);
    const torusGeoB = new THREE.TorusGeometry(3.5, 0.35, 32, 120);
    const ch3Mat = new THREE.MeshPhongMaterial({
      color: 0x120820,
      emissive: new THREE.Color(0x5511aa),
      emissiveIntensity: 0.22,
      shininess: 200,
      specular: new THREE.Color(0x9333EA),
      transparent: true, opacity: 0.9,
    });
    const torusA = new THREE.Mesh(torusGeoA, ch3Mat);
    const torusB = new THREE.Mesh(torusGeoB, ch3Mat.clone());
    torusB.rotation.x = Math.PI / 2;
    torusB.rotation.z = Math.PI / 3;
    ch3Group.add(torusA);
    ch3Group.add(torusB);
    // Third ring at different angle
    const torusGeoC = new THREE.TorusGeometry(3.5, 0.2, 24, 100);
    const torusC = new THREE.Mesh(torusGeoC, new THREE.MeshPhongMaterial({
      color: 0x200a38, emissive: new THREE.Color(0x7722cc), emissiveIntensity: 0.35,
      shininess: 180, specular: new THREE.Color(0x9333EA), transparent: true, opacity: 0.7,
    }));
    torusC.rotation.y = Math.PI / 4;
    torusC.rotation.z = Math.PI / 5;
    ch3Group.add(torusC);
    scene.add(ch3Group);

    // Ch 4 — Destination: Expanding icosphere with inner glow shell (thriving)
    const ch4Group = new THREE.Group();
    const ch4GeoOuter = new THREE.IcosahedronGeometry(4.2, 4);
    const ch4MatOuter = new THREE.MeshPhongMaterial({
      color: 0x061002,
      emissive: new THREE.Color(0x335500),
      emissiveIntensity: 0.22,
      shininess: 100,
      specular: new THREE.Color(0xADFF2F),
      transparent: true, opacity: 0.88,
    });
    ch4Group.add(new THREE.Mesh(ch4GeoOuter, ch4MatOuter));
    // Inner glow sphere
    const ch4GeoInner = new THREE.IcosahedronGeometry(2.8, 3);
    const ch4MatInner = new THREE.MeshBasicMaterial({
      color: 0xADFF2F, transparent: true, opacity: 0.12, depthWrite: false, blending: THREE.AdditiveBlending,
      side: THREE.BackSide,
    });
    ch4Group.add(new THREE.Mesh(ch4GeoInner, ch4MatInner));
    // Wireframe
    const ch4WireMat = new THREE.MeshBasicMaterial({ color: 0xADFF2F, wireframe: true, transparent: true, opacity: 0.10 });
    ch4Group.add(new THREE.Mesh(ch4GeoOuter, ch4WireMat));
    // Outer glow shells
    for (let s = 0; s < 3; s++) {
      const shellGeo = new THREE.IcosahedronGeometry(4.2 + s * 0.8, 2);
      const shellMat = new THREE.MeshBasicMaterial({
        color: 0xADFF2F, transparent: true, opacity: 0.04 - s * 0.01,
        depthWrite: false, blending: THREE.AdditiveBlending, side: THREE.BackSide,
      });
      ch4Group.add(new THREE.Mesh(shellGeo, shellMat));
    }
    scene.add(ch4Group);

    // ── Group refs for animation ──────────────────────────────────────────────
    const chapterGroups = [ch0Group, ch1Group, ch2Group, ch3Group, ch4Group];

    // Initialize z positions and opacity — ch0 at center, rest far away
    chapterGroups.forEach((g, i) => {
      g.scale.setScalar(1);
      g.position.z = i === 0 ? 0 : -100;
      if (i !== 0) {
        g.traverse(child => {
          if (child.isMesh && child.material && child.material.transparent) {
            child.material.opacity = 0;
          }
        });
      }
    });

    sceneRef.current = { renderer, scene, camera, chapterGroups, keyLight, rimLight, backLight, bgPlanes };

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

    // ── Color state for smooth lerping ────────────────────────────────────────
    const currentClear = new THREE.Color(CHAPTERS[0].clearColor);
    const currentFog   = new THREE.Color(CHAPTERS[0].fogColor);
    const currentKey   = new THREE.Color(CHAPTERS[0].accentHex);
    const currentBack  = new THREE.Color(CHAPTERS[0].accentHex);

    // ── Animation loop ────────────────────────────────────────────────────────
    let animId, t = 0;

    const animate = () => {
      animId = requestAnimationFrame(animate);
      t += 0.008;

      // Progress-based chapter calculation
      // Give each chapter equal time: split 0→1 into N equal bands
      // We add 0.5 extra band so chapter 5 has full dwell
      const prog = progressRef.current;
      // chapterFloat: 0 at start of ch0, 4 at start of ch4, 4.999 at end
      const chapterFloat = prog * CHAPTER_COUNT;
      const chIdx = clamp(Math.floor(chapterFloat), 0, CHAPTER_COUNT - 1);
      const chT   = chapterFloat - chIdx; // 0→1 within chapter

      const ch = CHAPTERS[chIdx];
      const nextCh = chIdx < CHAPTER_COUNT - 1 ? CHAPTERS[chIdx + 1] : null;

      // Smooth color lerp
      const targetClear = new THREE.Color(ch.clearColor);
      const targetFog   = new THREE.Color(ch.fogColor);
      const targetKey   = new THREE.Color(ch.accentHex);

      currentClear.lerp(targetClear, 0.06);
      currentFog.lerp(targetFog, 0.06);
      currentKey.lerp(targetKey, 0.06);
      currentBack.lerp(targetKey, 0.04);

      renderer.setClearColor(currentClear, 1);
      scene.fog.color.copy(currentFog);
      keyLight.color.copy(currentKey);
      backLight.color.copy(currentBack);

      // Background gradient planes color
      bgPlanes.forEach(({ mesh, mat }) => {
        const c = new THREE.Color(ch.accentHex);
        if (nextCh) c.lerp(new THREE.Color(nextCh.accentHex), chT * 0.5);
        mat.color.copy(c);
      });

      // ── Z-depth travel: each form flies in from far, rests, then recedes ────
      // chapterFloat = 0 at ch0, 1 at ch1, 2 at ch2, etc.
      // When chapterFloat = i, form i is at center (z=0)
      // Before: form comes from z=-100 (distant, small)
      // After:  form recedes to z=+55 (close, large, fading out)
      const Z_FAR   = -100;  // incoming depth
      const Z_CENTER =   0;  // active position
      const Z_NEAR  =  55;   // receding depth

      chapterGroups.forEach((group, i) => {
        // signed distance: negative = not yet reached, positive = passed
        const signedDist = chapterFloat - i;

        let targetZ, targetOpacity;

        if (signedDist < -0.01) {
          // Incoming — travelling from far to center
          // signedDist: -∞ → 0, map [-1,0] → [Z_FAR, Z_CENTER]
          const t01 = clamp(signedDist + 1, 0, 1); // 0 when 1 chapter away, 1 when at center
          const eased = easeInOut3(t01);
          targetZ = lerp(Z_FAR, Z_CENTER, eased);
          targetOpacity = clamp(t01 * 2.5, 0, 1); // fade in during last 40% of approach
        } else {
          // Receding — travelling from center to near
          // signedDist: 0 → +1, map [0,1] → [Z_CENTER, Z_NEAR]
          const t01 = clamp(signedDist, 0, 1);
          const eased = easeInOut3(t01);
          targetZ = lerp(Z_CENTER, Z_NEAR, eased);
          targetOpacity = clamp(1 - t01 * 2.0, 0, 1); // fade out quickly
        }

        // Smooth z position — slower lerp = more cinematic transitions
        group.position.z = lerp(group.position.z, targetZ, 0.08);

        // Apply opacity to all materials
        group.traverse(child => {
          if (child.isMesh && child.material && child.material.transparent) {
            const baseOpacity = child.material.wireframe ? 0.14 : (i === 1 ? 0.88 : 0.92);
            child.material.opacity = lerp(child.material.opacity, targetOpacity * baseOpacity, 0.12);
          }
        });
      });

      // ── Per-chapter unique animations (rotation + breathing) ──────────────

      // Ch 0: Torus knot slow tumble + breathing
      ch0Group.rotation.x = t * 0.18;
      ch0Group.rotation.y = t * 0.12;
      ch0Group.rotation.z = t * 0.07;
      const breathe0 = 1 + Math.sin(t * 0.9) * 0.06;
      ch0Group.scale.setScalar(breathe0);

      // Ch 1: Icosahedron slow heavy rotation
      ch1Group.rotation.x = t * 0.07;
      ch1Group.rotation.y = t * 0.05;
      ch1Group.rotation.z = t * 0.03;
      ch1Group.children.forEach(child => {
        if (child.isMesh && child.material && !child.material.wireframe) {
          child.material.emissiveIntensity = 0.25 + Math.sin(t * 1.2) * 0.08;
        }
      });

      // Ch 2: Octahedron smooth confident rotation
      ch2Group.rotation.x = t * 0.22;
      ch2Group.rotation.y = t * 0.16;
      const breathe2 = 1 + Math.sin(t * 1.1) * 0.05;
      ch2Group.scale.setScalar(breathe2);

      // Ch 3: Three rings rotate at different speeds
      if (ch3Group.children.length >= 3) {
        ch3Group.children[0].rotation.z = t * 0.28;
        ch3Group.children[1].rotation.x = t * 0.20;
        ch3Group.children[1].rotation.y = t * 0.12;
        ch3Group.children[2].rotation.x = t * 0.15;
        ch3Group.children[2].rotation.z = t * 0.22;
      }
      ch3Group.rotation.y = t * 0.08;
      ch3Group.traverse(child => {
        if (child.isMesh && child.material && !child.material.wireframe && child.material.emissive) {
          child.material.emissiveIntensity = 0.4 + Math.sin(t * 2.0) * 0.15;
        }
      });

      // Ch 4: Icosphere gentle expansion pulse + rotation
      ch4Group.rotation.x = t * 0.10;
      ch4Group.rotation.y = t * 0.14;
      const breathe4 = 1 + Math.sin(t * 0.7) * 0.09;
      ch4Group.scale.setScalar(breathe4);
      ch4Group.children.forEach((child, ci) => {
        if (ci >= 3) child.scale.setScalar(1 + Math.sin(t * 0.5 + ci * 0.8) * 0.06);
      });

      // Camera gentle drift — offset lookAt left so geometry sits in the right half
      camera.position.x = Math.sin(t * 0.3) * 0.3;
      camera.position.y = Math.cos(t * 0.22) * 0.25;
      camera.lookAt(-2.5, 0, 0);

      // Background planes gentle drift
      bgPlanes.forEach(({ mesh }, idx) => {
        mesh.rotation.z += 0.0008 * (idx % 2 === 0 ? 1 : -1);
        mesh.position.x += Math.sin(t * 0.2 + idx) * 0.01;
        mesh.position.y += Math.cos(t * 0.15 + idx) * 0.008;
      });

      renderer.render(scene, camera);
    };
    animate();

    return () => {
      cancelAnimationFrame(animId);
      window.removeEventListener('resize', onResize);
      renderer.dispose();
      if (el.contains(renderer.domElement)) el.removeChild(renderer.domElement);
    };
  }, []);

  // ── Scroll handler ────────────────────────────────────────────────────────
  React.useEffect(() => {
    const handleScroll = () => {
      const container = containerRef.current;
      if (!container) return;

      const rect = container.getBoundingClientRect();
      const scrolled = -rect.top;
      const totalScroll = container.offsetHeight - window.innerHeight;
      // Remap: give each chapter equal dwell, ch5 fully completes
      // progress 0→1 over the full scroll range
      const progress = clamp(scrolled / totalScroll, 0, 1);
      progressRef.current = progress;

      // Each chapter occupies 1/CHAPTER_COUNT of total progress
      // ch0: 0.0→0.2, ch1: 0.2→0.4, ..., ch4: 0.8→1.0
      const chapterFloat = progress * CHAPTER_COUNT;
      const chapterIdx = clamp(Math.floor(chapterFloat), 0, CHAPTER_COUNT - 1);
      const chapterT = chapterFloat - chapterIdx;

      setActiveChapter(chapterIdx);
      setChapterProgress(chapterT);
      // Show text for most of each chapter, only briefly hide during fast transitions
      setTextVisible(chapterT > 0.06 && chapterT < 0.91);
    };

    window.addEventListener('scroll', handleScroll, { passive: true });
    handleScroll(); // init
    return () => window.removeEventListener('scroll', handleScroll);
  }, []);

  const ch = CHAPTERS[activeChapter];

  return (
    <div ref={containerRef} style={{ height: '800vh', position: 'relative' }}>
      <div style={{ position: 'sticky', top: 0, height: '100vh', width: '100%', overflow: 'hidden' }}>

        {/* Three.js mount */}
        <div ref={mountRef} style={{ position: 'absolute', inset: 0 }} />

        {/* Left-side contrast gradient — ensures text card always readable */}
        <div style={{
          position: 'absolute', inset: 0, zIndex: 6, pointerEvents: 'none',
          background: 'linear-gradient(105deg, rgba(4,8,18,0.75) 0%, rgba(4,8,18,0.4) 45%, transparent 70%)',
        }} />

        {/* Soft radial vignette */}
        <div style={{
          position: 'absolute', inset: 0, zIndex: 5, pointerEvents: 'none',
          background: 'radial-gradient(ellipse 80% 80% at 50% 50%, transparent 35%, rgba(8,10,18,0.7) 100%)',
        }} />

        {/* Bottom fade */}
        <div style={{
          position: 'absolute', bottom: 0, left: 0, right: 0, height: '160px', zIndex: 6, pointerEvents: 'none',
          background: 'linear-gradient(to bottom, transparent, rgba(11,18,34,0.98))',
        }} />

        {/* HUD text — frosted glass card with 3D headline */}
        <div style={{
          position: 'absolute', inset: 0, zIndex: 10, pointerEvents: 'none',
          display: 'flex', flexDirection: 'column', justifyContent: 'center',
          padding: '0 6vw',
        }}>
          <div
            ref={cardRef}
            onMouseMove={handleCardMouseMove}
            onMouseEnter={() => setCardHovered(true)}
            onMouseLeave={handleCardMouseLeave}
            style={{
              maxWidth: '560px',
              padding: 'clamp(28px, 4vw, 44px) clamp(24px, 4vw, 40px)',
              borderRadius: '20px',
              background: 'rgba(6, 10, 20, 0.72)',
              backdropFilter: 'blur(24px) saturate(160%)',
              WebkitBackdropFilter: 'blur(24px) saturate(160%)',
              border: `1px solid ${ch.accentColor}22`,
              boxShadow: `0 2px 0 rgba(255,255,255,0.04) inset, 0 32px 80px rgba(0,0,0,0.6), 0 0 0 1px rgba(0,0,0,0.3)`,
              opacity: textVisible ? 1 : 0,
              transform: textVisible
                ? `perspective(900px) rotateX(${cardTilt.x}deg) rotateY(${cardTilt.y}deg) translateY(0)`
                : 'perspective(900px) rotateX(2deg) rotateY(0deg) translateY(16px)',
              transformStyle: 'preserve-3d',
              transition: cardHovered
                ? 'opacity 0.55s ease, transform 0.08s ease-out, border-color 0.6s ease, box-shadow 0.6s ease'
                : 'opacity 0.55s ease, transform 0.6s cubic-bezier(0.2, 0.8, 0.2, 1), border-color 0.6s ease, box-shadow 0.6s ease',
              pointerEvents: 'auto',
              willChange: 'transform',
              cursor: 'default',
            }}
          >
            {/* Chapter label */}
            <div style={{ marginBottom: '18px', display: 'flex', alignItems: 'center', gap: '10px' }}>
              <span style={{
                display: 'inline-block', width: '6px', height: '6px', borderRadius: '50%',
                background: ch.accentColor,
                boxShadow: `0 0 8px ${ch.accentColor}, 0 0 16px ${ch.accentColor}66`,
                flexShrink: 0,
              }} />
              <span style={{
                fontSize: '0.6rem', letterSpacing: '0.22em', textTransform: 'uppercase',
                color: ch.accentColor, fontFamily: "'DM Sans', sans-serif", fontWeight: 600,
              }}>
                {String(activeChapter + 1).padStart(2, '0')} / {CHAPTER_COUNT} — {ch.label}
              </span>
            </div>

            {/* 3D Headline */}
            <h2 key={activeChapter} style={{
              fontFamily: "'Syne', sans-serif",
              fontSize: 'clamp(1.7rem, 4.2vw, 4rem)',
              fontWeight: 400,
              lineHeight: 1.08,
              letterSpacing: '-0.03em',
              margin: '0 0 18px',
              perspective: '600px',
              perspectiveOrigin: '50% 50%',
              // 3D depth via layered text-shadow
              textShadow: `
                0 1px 0 rgba(255,255,255,0.08),
                0 2px 0 rgba(0,0,0,0.4),
                0 4px 8px rgba(0,0,0,0.5),
                0 8px 20px rgba(0,0,0,0.3)
              `,
              color: '#f0f4ff',
            }}>
              {/* Accent first word with glow + color */}
              <span style={{
                color: ch.accentColor,
                textShadow: `
                  0 0 20px ${ch.accentColor}88,
                  0 0 40px ${ch.accentColor}44,
                  0 2px 0 rgba(0,0,0,0.5),
                  0 4px 12px rgba(0,0,0,0.4)
                `,
                display: 'inline-block',
                transform: 'translateZ(4px)',
              }}>
                {ch.headline.split(' ')[0]}
              </span>
              {' '}
              <span style={{
                display: 'inline',
                color: '#f0f4ff',
              }}>
                {ch.headline.split(' ').slice(1).join(' ')}
              </span>
            </h2>

            {/* Divider */}
            <div style={{
              width: '40px', height: '1px',
              background: `linear-gradient(90deg, ${ch.accentColor}88, transparent)`,
              marginBottom: '16px',
              transition: 'background 0.6s ease',
            }} />

            {/* Body */}
            <p style={{
              fontFamily: "'DM Sans', sans-serif",
              fontSize: 'clamp(0.85rem, 1.6vw, 0.98rem)',
              color: 'rgba(200, 210, 230, 0.82)',
              lineHeight: 1.75,
              margin: 0,
              fontWeight: 400,
            }}>
              {ch.body}
            </p>

          </div>
        </div>

        {/* Side dot nav */}
        <div style={{
          position: 'absolute', right: '28px', top: '50%', transform: 'translateY(-50%)',
          zIndex: 20, display: 'flex', flexDirection: 'column', gap: '14px', alignItems: 'center',
        }}>
          {CHAPTERS.map((c, i) => (
            <div key={i} style={{
              width: i === activeChapter ? '8px' : '4px',
              height: i === activeChapter ? '8px' : '4px',
              borderRadius: '50%',
              background: i === activeChapter ? c.accentColor : 'rgba(255,255,255,0.18)',
              boxShadow: i === activeChapter ? `0 0 10px ${c.accentColor}, 0 0 22px ${c.accentColor}55` : 'none',
              transition: 'all 0.35s ease',
            }} title={c.label} />
          ))}
        </div>

        {/* Progress bar */}
        <div style={{ position: 'absolute', bottom: 0, left: 0, right: 0, height: '2px', background: 'rgba(255,255,255,0.04)', zIndex: 20 }}>
          <div style={{
            height: '100%',
            background: `linear-gradient(90deg, #3B82F6, ${ch.accentColor})`,
            width: `${((activeChapter + chapterProgress) / (CHAPTER_COUNT - 1)) * 100}%`,
            transition: 'width 0.08s linear',
            boxShadow: `0 0 10px ${ch.accentColor}`,
          }} />
        </div>
      </div>
    </div>
  );
};

Object.assign(window, { ScrollJourney, CHAPTERS });
