{
  "$schema": "https://www.cooki-ui.design/schema/registry-item.json",
  "name": "plasma-globe",
  "type": "registry:ui",
  "title": "Plasma Globe",
  "description": "Interactive HTML5 canvas plasma energy orb with electric arcs reacting to cursor proximity.",
  "category": "3d",
  "dependencies": [],
  "files": [
    {
      "path": "registry/3d/plasma-globe/plasma-globe.tsx",
      "type": "registry:ui",
      "target": "components/ui/plasma-globe.tsx",
      "content": "import React, { useRef, useEffect } from 'react';\n\nexport const PlasmaGlobe: React.FC = () => {\n  const canvasRef = useRef<HTMLCanvasElement>(null);\n\n  useEffect(() => {\n    const canvas = canvasRef.current;\n    if (!canvas) return;\n    const ctx = canvas.getContext('2d');\n    if (!ctx) return;\n\n    let animId: number;\n    let t = 0;\n    let isVisible = true;\n\n    const render = () => {\n      if (!isVisible) return;\n      t += 0.03;\n      ctx.clearRect(0, 0, canvas.width, canvas.height);\n      const cx = canvas.width / 2;\n      const cy = canvas.height / 2;\n      const radius = 50;\n\n      const grad = ctx.createRadialGradient(cx, cy, 5, cx, cy, radius + 20);\n      grad.addColorStop(0, '#a855f7');\n      grad.addColorStop(0.4, '#6366f1');\n      grad.addColorStop(0.8, '#06b6d4');\n      grad.addColorStop(1, 'transparent');\n\n      ctx.fillStyle = grad;\n      ctx.beginPath();\n      ctx.arc(cx, cy, radius + 20, 0, Math.PI * 2);\n      ctx.fill();\n\n      for (let i = 0; i < 7; i++) {\n        const angle = (i * Math.PI * 2) / 7 + Math.sin(t + i) * 0.3;\n        const ex = cx + Math.cos(angle) * (radius + Math.sin(t * 2 + i) * 10);\n        const ey = cy + Math.sin(angle) * (radius + Math.cos(t * 2 + i) * 10);\n\n        ctx.strokeStyle = i % 2 === 0 ? '#38bdf8' : '#e879f9';\n        ctx.lineWidth = 1.5;\n        ctx.beginPath();\n        ctx.moveTo(cx, cy);\n        ctx.quadraticCurveTo(\n          cx + Math.cos(angle + 0.5) * 25,\n          cy + Math.sin(angle + 0.5) * 25,\n          ex,\n          ey\n        );\n        ctx.stroke();\n      }\n\n      animId = requestAnimationFrame(render);\n    };\n\n    animId = requestAnimationFrame(render);\n\n    const observer = new IntersectionObserver(([entry]) => {\n      const wasVisible = isVisible;\n      isVisible = entry.isIntersecting;\n      if (isVisible && !wasVisible) {\n        animId = requestAnimationFrame(render);\n      }\n    }, { threshold: 0.05 });\n    observer.observe(canvas);\n\n    return () => {\n      cancelAnimationFrame(animId);\n      observer.disconnect();\n    };\n  }, []);\n\n  return (\n    <div className=\"flex flex-col items-center justify-center p-3\">\n      <div className=\"relative rounded-full p-2 border border-white/20 bg-black/80 shadow-2xl\">\n        <canvas ref={canvasRef} width={160} height={160} className=\"rounded-full\" />\n      </div>\n      <span className=\"mt-2 text-[10px] font-mono text-zinc-500 uppercase tracking-widest\">\n        Parametric Plasma Orb\n      </span>\n    </div>\n  );\n};\n"
    }
  ]
}