function Thread() {
  const [progress, setProgress] = React.useState(0);
  const [docH, setDocH] = React.useState(0);
  const [vh, setVh] = React.useState(900);
  const [headPt, setHeadPt] = React.useState({ x: 80, y: 60 });
  const pathRef = React.useRef(null);

  // Path drawn through the major scenes — viewBox 1440 x 7000.
  // Height stretches to docH so anchors map proportionally to scenes.
  const pathD = [
    "M 60 240",
    "C 220 360, 520 540, 1180 700",          // hero → cube (starts mid-hero, visible immediately)
    "S 1320 1080, 880 1300",                  // cube → marquee
    "S 180 1720, 560 2000",                   // marquee → promotion
    "S 1300 2400, 1100 2700",                 // promotion poster (lit center)
    "C 1320 2900, 1340 3060, 1320 3200",      // dive down along right edge of LLM card
    "C 1280 3290, 1100 3320, 1000 3350",      // sweep left through CREATIVE card
    "C 860 3390, 720 3410, 620 3430",         // hook into AI mark — end with spark
    "S 1300 3700, 720 4000",                  // ai → clients (sweep)
    "S 180 4400, 1100 4720",                  // clients diagonal
    "S 580 5120, 1120 5400",                  // → cases (focused frame)
    "S 220 5760, 800 6020",                   // cases → cta
    "C 1320 6200, 1280 6480, 720 6520",       // cta swirl approach
    "C 600 6560, 880 6620, 720 6800",         // tiny curl into footer ©
  ].join(" ");

  // Anchors in viewBox coords — moments where the thread "touches" main objects
  const anchors = React.useMemo(() => [
    { x: 1180, y: 700,  k: "cube",      r: 56 },
    { x: 880,  y: 1300, k: "marquee",   r: 38 },
    { x: 1100, y: 2700, k: "poster",    r: 64 },
    { x: 620,  y: 3430, k: "ai",        r: 80 },
    { x: 1100, y: 5400, k: "case",      r: 44 },
    { x: 720,  y: 6500, k: "cta",       r: 70 },
  ], []);

  React.useEffect(() => {
    const measure = () => {
      setDocH(document.documentElement.scrollHeight);
      setVh(window.innerHeight);
    };
    const onScroll = () => {
      const h = document.documentElement.scrollHeight - window.innerHeight;
      setProgress(Math.min(1, Math.max(0, window.scrollY / Math.max(1, h))));
    };
    measure();
    onScroll();
    // Re-measure after fonts/layout settle
    const t1 = setTimeout(measure, 600);
    const t2 = setTimeout(measure, 1800);
    window.addEventListener("scroll", onScroll, { passive: true });
    window.addEventListener("resize", measure);
    return () => {
      clearTimeout(t1); clearTimeout(t2);
      window.removeEventListener("scroll", onScroll);
      window.removeEventListener("resize", measure);
    };
  }, []);

  // Update the traveling head along the path
  React.useEffect(() => {
    if (!pathRef.current) return;
    try {
      const len = pathRef.current.getTotalLength();
      if (!len) return;
      const pt = pathRef.current.getPointAtLength(progress * len);
      setHeadPt({ x: pt.x, y: pt.y });
    } catch (e) {}
  }, [progress, docH]);

  const scrollPx = progress * Math.max(1, docH - vh);

  return (
    <>
      {/* BACK layer — sits behind <main>; weaves "under" cards */}
      <div className="sp-thread-layer back" style={{ height: docH || "100%" }}>
        <svg
          className="sp-thread"
          viewBox="0 0 1440 7000"
          preserveAspectRatio="none"
          style={{ height: docH || 7000 }}
          aria-hidden="true"
        >
          <defs>
            <filter id="paper-thread">
              <feTurbulence baseFrequency="0.9" numOctaves="2" seed="3" />
              <feDisplacementMap in="SourceGraphic" scale="1.6" />
            </filter>
            <linearGradient id="thread-grad" x1="0" y1="0" x2="0" y2="1">
              <stop offset="0%" stopColor="#F5F5F2" stopOpacity="1" />
              <stop offset="50%" stopColor="#F5F5F2" stopOpacity="0.6" />
              <stop offset="100%" stopColor="#F5F5F2" stopOpacity="0.85" />
            </linearGradient>
          </defs>
          {/* primary stroke — drawn-on-scroll */}
          <path
            ref={pathRef}
            d={pathD}
            stroke="url(#thread-grad)"
            strokeWidth="1.8"
            fill="none"
            strokeLinecap="round"
            filter="url(#paper-thread)"
            pathLength="1"
            strokeDasharray="1"
            strokeDashoffset={1 - progress}
          />
          {/* echo — paler second pencil pass, slight lag */}
          <path
            d={pathD}
            stroke="#F5F5F2"
            strokeWidth="0.6"
            fill="none"
            strokeOpacity="0.35"
            filter="url(#paper-thread)"
            pathLength="1"
            strokeDasharray="1"
            strokeDashoffset={Math.max(0, 1.05 - progress)}
          />
          {/* tick marks at anchors — small cross-hatches */}
          {anchors.map((a, i) => (
            <g key={i} className="thread-tick">
              <line x1={a.x - 12} y1={a.y} x2={a.x + 12} y2={a.y}
                stroke="#F5F5F2" strokeWidth="1" strokeOpacity="0.45" />
            </g>
          ))}
        </svg>
      </div>

      {/* FRONT layer — sparks + traveling head pop OVER main content */}
      <div className="sp-thread-layer front" style={{ height: docH || "100%" }}>
        {anchors.map((a, i) => {
          const anchorPx = (a.y / 7000) * docH;
          const active = scrollPx + vh * 0.45 > anchorPx;
          return (
            <div
              key={i}
              className={"thread-anchor " + (active ? "active" : "")}
              style={{
                left: `${(a.x / 1440) * 100}%`,
                top: `${(a.y / 7000) * 100}%`,
                ['--r']: `${a.r}px`,
              }}
            >
              <span className="anchor-glow"></span>
              <span className="anchor-ring"></span>
              <span className="anchor-dot"></span>
              <span className="anchor-label">{a.k}</span>
            </div>
          );
        })}
        {/* Traveling head — follows current scroll position along the path */}
        <div
          className="thread-head"
          style={{
            left: `${(headPt.x / 1440) * 100}%`,
            top: `${(headPt.y / 7000) * 100}%`,
            opacity: progress > 0.01 && progress < 0.99 ? 1 : 0,
          }}
        >
          <span className="head-glow"></span>
          <span className="head-dot"></span>
        </div>
      </div>
    </>
  );
}
window.Thread = Thread;
