{
  "$schema": "https://www.cooki-ui.design/schema/registry-item.json",
  "name": "matrix-rain-terminal",
  "type": "registry:ui",
  "title": "Matrix Rain Terminal",
  "description": "Digital matrix rain stream with animated falling glyphs and interactive cybernetic text decryption.",
  "category": "effects",
  "dependencies": [
    "framer-motion",
    "@phosphor-icons/react"
  ],
  "files": [
    {
      "path": "registry/effects/matrix-rain-terminal/matrix-rain-terminal.tsx",
      "type": "registry:ui",
      "target": "components/ui/matrix-rain-terminal.tsx",
      "content": "import React, { useEffect, useRef, useState } from 'react';\nimport { Terminal, Play, Pause } from '@phosphor-icons/react';\n\nexport interface MatrixRainTerminalProps {\n  fontSize?: number;\n  speed?: number;\n  className?: string;\n}\n\nexport const MatrixRainTerminal: React.FC<MatrixRainTerminalProps> = ({\n  fontSize = 14,\n  speed = 33,\n  className = '',\n}) => {\n  const canvasRef = useRef<HTMLCanvasElement>(null);\n  const [isPlaying, setIsPlaying] = useState(true);\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 width = (canvas.width = canvas.parentElement?.clientWidth || 400);\n    let height = (canvas.height = canvas.parentElement?.clientHeight || 260);\n\n    const chars = '0123456789ABCDEFｦｱｳｴｵｶｷｹｺｻｼｽｾｿﾀﾂﾃﾅﾆﾇﾈﾊﾋﾎﾏﾐﾑﾒﾓﾔﾕﾗﾘﾜ'.split('');\n    const columns = Math.floor(width / fontSize);\n    const drops: number[] = Array(columns).fill(1);\n\n    let animationId: number;\n    let lastTime = 0;\n    let isVisible = true;\n\n    const render = (time: number) => {\n      if (!isVisible || !isPlaying) return;\n      if (time - lastTime > speed) {\n        lastTime = time;\n        ctx.fillStyle = 'rgba(5, 5, 10, 0.15)';\n        ctx.fillRect(0, 0, width, height);\n\n        ctx.fillStyle = '#10b981';\n        ctx.font = `${fontSize}px monospace`;\n\n        for (let i = 0; i < drops.length; i++) {\n          const text = chars[Math.floor(Math.random() * chars.length)];\n          const x = i * fontSize;\n          const y = drops[i] * fontSize;\n\n          // Head character is brighter\n          ctx.fillStyle = '#a7f3d0';\n          ctx.fillText(text, x, y);\n          ctx.fillStyle = '#10b981';\n\n          if (y > height && Math.random() > 0.975) {\n            drops[i] = 0;\n          }\n          drops[i]++;\n        }\n      }\n      animationId = requestAnimationFrame(render);\n    };\n\n    if (isPlaying) {\n      animationId = requestAnimationFrame(render);\n    }\n\n    const observer = new IntersectionObserver(([entry]) => {\n      const wasVisible = isVisible;\n      isVisible = entry.isIntersecting;\n      if (isVisible && !wasVisible && isPlaying) {\n        animationId = requestAnimationFrame(render);\n      }\n    }, { threshold: 0.05 });\n    observer.observe(canvas);\n\n    const handleResize = () => {\n      if (!canvas.parentElement) return;\n      width = canvas.width = canvas.parentElement.clientWidth;\n      height = canvas.height = canvas.parentElement.clientHeight;\n    };\n\n    window.addEventListener('resize', handleResize);\n    return () => {\n      cancelAnimationFrame(animationId);\n      observer.disconnect();\n      window.removeEventListener('resize', handleResize);\n    };\n  }, [isPlaying, fontSize, speed]);\n\n  return (\n    <div className={`relative w-full h-[260px] rounded-2xl overflow-hidden border border-emerald-500/20 bg-zinc-950 font-mono shadow-2xl ${className}`}>\n      <canvas ref={canvasRef} className=\"absolute inset-0 w-full h-full block\" />\n      \n      {/* HUD Header */}\n      <div className=\"absolute top-3 left-3 right-3 flex items-center justify-between z-10 pointer-events-none\">\n        <div className=\"flex items-center gap-2 px-2.5 py-1 rounded-lg bg-zinc-900/80 backdrop-blur-md border border-emerald-500/30 text-emerald-400 text-xs\">\n          <Terminal size={14} weight=\"bold\" />\n          <span>CYBER_DECRYPT.SYS</span>\n        </div>\n        <button\n          onClick={() => setIsPlaying(!isPlaying)}\n          className=\"pointer-events-auto px-2 py-1 rounded-lg bg-zinc-900/80 border border-emerald-500/30 text-emerald-400 hover:text-white transition-colors cursor-pointer\"\n        >\n          {isPlaying ? <Pause size={12} weight=\"bold\" /> : <Play size={12} weight=\"bold\" />}\n        </button>\n      </div>\n    </div>\n  );\n};\n"
    }
  ]
}