// Kinetics.jsx — the offbeat motion layer.
// (1) Decode-text: section titles scramble through glyphs then resolve.
// (2) Scroll-velocity skew: content leans with scroll speed.
// (3) Kinetic side-rail: vertical progress + rotated live section label.
// (4) 3D cursor-tilt on cards.
function Kinetics({ active }) {
  const reduce = (typeof window !== 'undefined' && window.matchMedia)
    ? window.matchMedia('(prefers-reduced-motion: reduce)').matches : false;

  /* ---------- (1) DECODE-TEXT on section titles ---------- */
  React.useEffect(() => {
    if (reduce) return;
    const GLYPHS = '01<>{}[]/\\#%&*+=$@!?·';
    const decode = (el) => {
      if (el.__decoded) return; el.__decoded = true;
      const nodes = [];
      const w = document.createTreeWalker(el, NodeFilter.SHOW_TEXT);
      let n; while ((n = w.nextNode())) { if (n.nodeValue.trim()) nodes.push(n); }
      if (!nodes.length) return;
      const orig = nodes.map(t => t.nodeValue);
      const total = orig.reduce((a, s) => a + s.length, 0);
      el.classList.add('w-decoding');
      const FRAMES = 26; let frame = 0;
      const id = setInterval(() => {
        frame++;
        const revealed = Math.floor((frame / FRAMES) * total);
        let count = 0;
        nodes.forEach((t, i) => {
          const s = orig[i]; let out = '';
          for (let c = 0; c < s.length; c++) {
            if (s[c] === ' ' || s[c] === '\u00A0') { out += s[c]; count++; continue; }
            out += (count < revealed) ? s[c] : GLYPHS[(Math.random() * GLYPHS.length) | 0];
            count++;
          }
          t.nodeValue = out;
        });
        if (frame >= FRAMES) {
          clearInterval(id);
          nodes.forEach((t, i) => { t.nodeValue = orig[i]; });
          el.classList.remove('w-decoding');
          el.classList.add('w-decoded');
        }
      }, 30);
    };
    const titles = Array.from(document.querySelectorAll('.w-section__title, .w-contact__aside-h'));
    const io = new IntersectionObserver((ents) => {
      ents.forEach(e => { if (e.isIntersecting) { decode(e.target); io.unobserve(e.target); } });
    }, { threshold: 0.55 });
    titles.forEach(t => io.observe(t));
    // safety: never leave a title scrambled
    const safety = setTimeout(() => titles.forEach(t => { if (!t.__decoded) decode(t); }), 6000);
    return () => { io.disconnect(); clearTimeout(safety); };
  }, [reduce]);

  /* (2) scroll-velocity skew removed — it was disorienting, not delightful */

  /* ---------- (4) 3D CURSOR-TILT on cards ---------- */
  React.useEffect(() => {
    if (reduce || !(window.matchMedia && window.matchMedia('(pointer: fine)').matches)) return;
    const wire = () => {
      document.querySelectorAll('.w-why__card, .w-approach__card, .w-bento__cell').forEach(el => {
        if (el.__tilt) return; el.__tilt = true;
        el.style.transformStyle = 'preserve-3d';
        const onMove = (e) => {
          const r = el.getBoundingClientRect();
          const px = (e.clientX - r.left) / r.width - 0.5;
          const py = (e.clientY - r.top) / r.height - 0.5;
          el.style.setProperty('--tx', (-py * 7).toFixed(2) + 'deg');
          el.style.setProperty('--ty', (px * 7).toFixed(2) + 'deg');
          el.classList.add('w-tilt');
        };
        const reset = () => { el.classList.remove('w-tilt'); el.style.removeProperty('--tx'); el.style.removeProperty('--ty'); };
        el.addEventListener('mousemove', onMove);
        el.addEventListener('mouseleave', reset);
      });
    };
    wire();
    const mo = new MutationObserver(wire); mo.observe(document.body, { childList: true, subtree: true });
    return () => mo.disconnect();
  }, [reduce]);

  /* ---------- (3) KINETIC SIDE-RAIL ---------- */
  const [pct, setPct] = React.useState(0);
  React.useEffect(() => {
    const onScroll = () => {
      const h = document.documentElement.scrollHeight - window.innerHeight;
      setPct(h > 0 ? Math.min(100, Math.max(0, (window.scrollY / h) * 100)) : 0);
    };
    onScroll();
    window.addEventListener('scroll', onScroll, { passive: true });
    window.addEventListener('resize', onScroll);
    return () => { window.removeEventListener('scroll', onScroll); window.removeEventListener('resize', onScroll); };
  }, []);
  const labels = { services: 'What we do', why: 'Why Myra', approach: 'How we work', faq: 'Questions', contact: 'Say hello' };

  return (
    <aside className="w-rail" aria-hidden="true">
      <div className="w-rail__top">
        <span className="w-rail__idx">{String(pct | 0).padStart(2, '0')}</span>
        <span className="w-rail__pct">%</span>
      </div>
      <div className="w-rail__track"><span className="w-rail__fill" style={{ height: pct + '%' }} /></div>
      <div className="w-rail__label">{labels[active] || 'Myra'}</div>
    </aside>
  );
}
Object.assign(window, { Kinetics });
