function Methodology() {
  const { t } = window.useT();
  const STEP_COLORS = ['#FF8A3D', '#FFC93C', '#52CCA0', '#3DA9FF'];

  // Refs to the four moving pieces inside Roby
  const sceneRef    = React.useRef(null);    // hover-target scene container
  const eyesRef     = React.useRef(null);    // pupils group
  const antennaRef  = React.useRef(null);    // antenna group
  const waveRef     = React.useRef(null);    // right-arm group
  const jumpRef     = React.useRef(null);    // wrapper for click jump

  // Refs that the rAF loop reads each frame (no re-renders triggered by these)
  const mouseRef    = React.useRef({ x: 0, y: 0 });
  const moodRef     = React.useRef('idle');

  // React state — drives mouth/cheeks/chest visuals only
  const [mood, setMood]     = React.useState('idle'); // 'idle' | 'hover' | 'click'
  const [bursts, setBursts] = React.useState([]);
  const [popMsg, setPopMsg] = React.useState(null);

  React.useEffect(() => { moodRef.current = mood; }, [mood]);

  // ───────── Single rAF loop drives every continuous motion ─────────
  React.useEffect(() => {
    let raf;
    let curX = 0, curY = 0;          // eased cursor coordinates
    let waveAngle = 0;               // current arm rotation
    let waveT = 0;                   // wave-time accumulator (in frames)

    const tick = () => {
      const target = mouseRef.current;
      // Ease the cursor — natural follow-through, never snap
      curX += (target.x - curX) * 0.20;
      curY += (target.y - curY) * 0.20;

      // 1) Pupils — pure translate inside the white sclera
      if (eyesRef.current) {
        const dx = Math.max(-1, Math.min(1, curX)) * 6;
        const dy = Math.max(-1, Math.min(1, curY)) * 5;
        eyesRef.current.setAttribute('transform', `translate(${dx.toFixed(2)} ${dy.toFixed(2)})`);
      }

      // 2) Antenna — rotate around its base point (160, 58)
      if (antennaRef.current) {
        const tilt = Math.max(-1, Math.min(1, curX)) * 16;
        antennaRef.current.setAttribute('transform', `rotate(${tilt.toFixed(2)} 160 58)`);
      }

      // 3) Right arm — sine wave when hovered/clicked, eases back when idle.
      //    Pivot is the shoulder (228, 222) in viewBox coordinates.
      const isHappy = moodRef.current === 'hover' || moodRef.current === 'click';
      if (isHappy) {
        waveT += 1;
        const amp = moodRef.current === 'click' ? 26 : 18;
        const sineTarget = Math.sin(waveT * 0.16) * amp;
        waveAngle += (sineTarget - waveAngle) * 0.35;
      } else {
        waveAngle += (0 - waveAngle) * 0.18;
        waveT = 0;
      }
      if (waveRef.current) {
        waveRef.current.setAttribute('transform', `rotate(${waveAngle.toFixed(2)} 228 222)`);
      }

      raf = requestAnimationFrame(tick);
    };
    raf = requestAnimationFrame(tick);
    return () => cancelAnimationFrame(raf);
  }, []);

  // ───────── Cursor → -1..1 vector relative to Roby's centre ─────────
  const handleMove = (e) => {
    const el = sceneRef.current; if (!el) return;
    const rect = el.getBoundingClientRect();
    const cx = rect.left + rect.width  * 0.5;
    const cy = rect.top  + rect.height * 0.42;   // mascot sits a bit above mid
    const range = 280;
    mouseRef.current = {
      x: (e.clientX - cx) / range,
      y: (e.clientY - cy) / range,
    };
  };
  const handleLeave = () => {
    mouseRef.current = { x: 0, y: 0 };  // ease back to centre
    setMood('idle');
  };

  const handleRobotEnter = () => { if (mood !== 'click') setMood('hover'); };
  const handleRobotLeave = () => { if (mood !== 'click') setMood('idle'); };

  // ───────── Click reaction: jump + emoji burst + speech bubble ─────
  const handleClick = () => {
    setMood('click');

    // Re-trigger the jump CSS animation by clearing then resetting it
    if (jumpRef.current) {
      jumpRef.current.style.animation = 'none';
      void jumpRef.current.offsetHeight;        // force reflow
      jumpRef.current.style.animation = 'roby-jump 0.6s cubic-bezier(.34,1.56,.64,1)';
    }

    const id = Date.now();
    const emojis = ['✨', '⭐', '💫', '🎉', '🧱', '⚡', '💜', '🎊', '🤖', '🚀'];
    const newBursts = Array.from({ length: 16 }).map((_, i) => ({
      id: id + i,
      angle: (i / 16) * Math.PI * 2 + (Math.random() - 0.5) * 0.4,
      dist:  90 + Math.random() * 70,
      rot:   (Math.random() - 0.5) * 1080,
      delay: Math.floor(Math.random() * 120),
      emoji: emojis[Math.floor(Math.random() * emojis.length)],
      size:  18 + Math.floor(Math.random() * 16),
    }));
    setBursts(b => [...b, ...newBursts]);

    const messages = [t.method.tryIt, t.method.iterate, t.method.make, '👋', '🎉'];
    setPopMsg({ id, text: messages[Math.floor(Math.random() * messages.length)] });

    setTimeout(() => setMood(prev => prev === 'click' ? 'hover' : prev), 600);
    setTimeout(() => setPopMsg(p => p && p.id === id ? null : p), 1400);
    setTimeout(() => setBursts(b => b.filter(x => !newBursts.find(n => n.id === x.id))), 1600);
  };

  return (
    <section id="methodology" className="relative px-4 sm:px-8 py-20 sm:py-28 overflow-hidden">
      <style>{`
        /* One-shot jump, triggered on click via JS */
        @keyframes roby-jump {
          0%   { transform: translateY(0)    scale(1); }
          30%  { transform: translateY(-14px) scale(1.05); }
          60%  { transform: translateY(0)    scale(0.97); }
          100% { transform: translateY(0)    scale(1); }
        }

        /* Click burst — emojis explode outward in random directions */
        @keyframes roby-burst {
          0%   { transform: translate(-50%, -50%) scale(0.4) rotate(0deg); opacity: 0; }
          12%  { opacity: 1; }
          100% { transform: translate(calc(-50% + var(--dx)), calc(-50% + var(--dy))) scale(1.1) rotate(var(--rot)); opacity: 0; }
        }

        /* Speech bubble pops up over the antenna */
        @keyframes roby-pop {
          0%   { transform: translate(-50%, 8px)   scale(0.4); opacity: 0; }
          18%  { transform: translate(-50%, -8px)  scale(1.15); opacity: 1; }
          75%  { transform: translate(-50%, -28px) scale(1);    opacity: 1; }
          100% { transform: translate(-50%, -48px) scale(0.95); opacity: 0; }
        }

        /* Tiny press feedback */
        .roby-press         { transition: transform .12s cubic-bezier(.34,1.56,.64,1); }
        .roby-press:active  { transform: scale(0.95); }
      `}</style>

      <div aria-hidden className="absolute inset-0 -z-10">
        <div className="absolute top-1/3 left-1/2 -translate-x-1/2 w-[700px] h-[700px] rounded-full opacity-50" style={{background:'radial-gradient(circle, #E5D2FB 0%, transparent 60%)'}}/>
      </div>

      <div className="mx-auto max-w-7xl grid lg:grid-cols-[0.95fr_1.05fr] gap-12 lg:gap-16 items-center">
        <div className="relative">
          <div
            ref={sceneRef}
            onMouseMove={handleMove}
            onMouseLeave={handleLeave}
            className="relative rounded-blob bg-gradient-to-br from-brand-100 via-cream to-tang-300/40 border-2 border-brand-100 p-6 sm:p-8 shadow-card overflow-hidden"
            style={{minHeight: 520}}
          >
            <div className="absolute top-0 inset-x-0 h-3.5 studs" style={{ background: 'radial-gradient(circle at 50% 50%, #FFC93C 22%, transparent 23%) 0 0/24px 24px, #FFC93C' }}/>

            {/* concentric ground rings */}
            <div aria-hidden className="absolute inset-x-0 bottom-10 flex items-end justify-center">
              <div className="relative w-[420px] h-[180px]">
                <div className="absolute left-1/2 -translate-x-1/2 bottom-0 w-[420px] h-[60px] rounded-[50%] bg-brand-200/40"/>
                <div className="absolute left-1/2 -translate-x-1/2 bottom-3 w-[340px] h-[48px] rounded-[50%] bg-brand-200/55"/>
                <div className="absolute left-1/2 -translate-x-1/2 bottom-6 w-[260px] h-[36px] rounded-[50%] bg-brand-300/40"/>
                <div className="absolute left-1/2 -translate-x-1/2 bottom-9 w-[180px] h-[24px] rounded-[50%] bg-brand-400/30"/>
              </div>
            </div>

            {/* ambient floating dots */}
            <div aria-hidden className="absolute inset-0 pointer-events-none">
              <div className="absolute top-10 left-10 w-2 h-2 rounded-full bg-sun-400 float-slow"/>
              <div className="absolute top-20 right-16 w-3 h-3 rounded-full bg-tang-400 float-med"/>
              <div className="absolute bottom-32 left-14 w-2.5 h-2.5 rounded-full bg-mint-400 float-fast"/>
              <div className="absolute top-32 left-1/2 w-1.5 h-1.5 rounded-full bg-sky-400 float-slow"/>
              <div className="absolute bottom-20 right-12 w-2 h-2 rounded-full bg-sun-400 float-med"/>
            </div>

            {/* Roby + interaction overlay */}
            <div className="relative flex justify-center pt-6">
              <div className="relative" style={{ width: 300, height: 320 }}>
                {/* Single wrapper — only used for the one-shot click jump */}
                <div ref={jumpRef} className="w-full h-full">
                  <div
                    onMouseEnter={handleRobotEnter}
                    onMouseLeave={handleRobotLeave}
                    onClick={handleClick}
                    className="roby-press cursor-pointer select-none w-full h-full"
                    style={{ touchAction: 'manipulation' }}
                    role="button"
                    aria-label="Click Roby!"
                  >
                    <Mascot
                      size={300}
                      eyesRef={eyesRef}
                      antennaRef={antennaRef}
                      waveRef={waveRef}
                      mood={mood}
                    />
                  </div>
                </div>

                {/* Floating speech popup on click */}
                {popMsg && (
                  <div
                    key={popMsg.id}
                    className="absolute left-1/2 top-0 z-20 pointer-events-none font-display font-extrabold text-[15px] text-brand-800 bg-cream border-2 border-brand-800 rounded-full px-3.5 py-1.5 shadow-pop whitespace-nowrap"
                    style={{ animation: 'roby-pop 1.4s ease-out forwards' }}
                  >
                    {popMsg.text}
                  </div>
                )}

                {/* Emoji burst */}
                {bursts.map(b => (
                  <span
                    key={b.id}
                    className="absolute left-1/2 top-1/2 z-10 pointer-events-none select-none"
                    style={{
                      fontSize: `${b.size}px`,
                      lineHeight: 1,
                      ['--dx']: `${Math.cos(b.angle) * b.dist}px`,
                      ['--dy']: `${Math.sin(b.angle) * b.dist}px`,
                      ['--rot']: `${b.rot}deg`,
                      animation: 'roby-burst 1.3s cubic-bezier(.18,.7,.2,1) forwards',
                      animationDelay: `${b.delay}ms`,
                    }}
                  >
                    {b.emoji}
                  </span>
                ))}
              </div>
            </div>

            {/* greeting bubble (i18n) */}
            <div className="relative z-10 mt-2 mx-auto max-w-[260px] bg-cream rounded-2xl border-2 border-brand-800 px-4 py-3 text-center shadow-pop">
              <div className="font-display font-extrabold text-brand-800 text-xl leading-tight">{t.method.hi}</div>
              <div className="text-brand-700/70 font-semibold text-[12px] mt-0.5">{t.method.roby}</div>
            </div>

            {/* corner sticker badges */}
            <div className="absolute top-16 left-3 sm:left-5 float-med rotate-[-8deg] pointer-events-none">
              <div className="bg-sky-400 text-cream font-extrabold text-xs px-3 py-1.5 rounded-xl shadow-pop border-2 border-brand-800">{t.method.tryIt}</div>
            </div>
            <div className="absolute top-24 right-3 sm:right-5 float-slow rotate-[10deg] pointer-events-none">
              <div className="bg-mint-400 text-brand-800 font-extrabold text-xs px-3 py-1.5 rounded-xl shadow-pop border-2 border-brand-800">{t.method.iterate}</div>
            </div>
            <div className="absolute bottom-28 left-2 sm:left-4 float-fast rotate-[6deg] hidden sm:block pointer-events-none">
              <div className="bg-tang-400 text-cream font-extrabold text-xs px-3 py-1.5 rounded-xl shadow-pop border-2 border-brand-800">{t.method.make}</div>
            </div>
          </div>
        </div>

        <div>
          <div className="inline-flex items-center gap-2 rounded-full bg-brand-600/10 px-3.5 py-1.5 mb-4 border border-brand-200">
            <span className="text-brand-700 font-extrabold text-[12px] tracking-wider uppercase">{t.method.pill}</span>
          </div>
          <h2 className="font-display font-extrabold text-brand-800 text-[40px] sm:text-[52px] leading-[1.0] tracking-tight">
            {t.method.title1} <br/>
            <span className="relative inline-block">
              <span className="absolute inset-0 -inset-x-2 bg-tang-300/60 -rotate-1 rounded-2xl -z-10"/>
              {t.method.title2}
            </span> {t.method.title3}
          </h2>
          <p className="mt-5 text-brand-700/80 text-[17px] font-semibold leading-relaxed max-w-xl">
            {t.method.body1} <b className="text-brand-800">{t.method.bodyBold}</b>{t.method.body2}
          </p>

          <ol className="mt-10 grid sm:grid-cols-2 gap-4">
            {t.method.steps.map((s, i) => (
              <li key={i} className="relative bg-cream border-2 border-brand-100 rounded-2xl p-5 hover:-translate-y-1 hover:shadow-pop transition group">
                <div className="flex items-start gap-3">
                  <div className="font-display font-extrabold text-3xl leading-none" style={{color: STEP_COLORS[i]}}>{String(i+1).padStart(2,'0')}</div>
                  <div>
                    <div className="font-display font-extrabold text-brand-800 text-lg leading-tight">{s.title}</div>
                    <p className="text-brand-700/75 text-[14px] mt-1 font-medium leading-snug">{s.desc}</p>
                  </div>
                </div>
                <span className="absolute bottom-3 end-3 w-2 h-2 rounded-full opacity-40 group-hover:opacity-100 transition" style={{background:STEP_COLORS[i]}}/>
              </li>
            ))}
          </ol>
        </div>
      </div>
    </section>
  );
}
window.Methodology = Methodology;
