{
  "$schema": "https://www.cooki-ui.design/schema/registry-item.json",
  "name": "flowing-lines-wave-background",
  "type": "registry:ui",
  "title": "Mathematical Flowing Lines Wave",
  "description": "Continuous algorithmic bezier ribbon canvas drawing undulating sine wave threads across deep space.",
  "category": "backgrounds",
  "dependencies": [],
  "files": [
    {
      "path": "registry/backgrounds/flowing-lines-wave-background/flowing-lines-wave-background.tsx",
      "type": "registry:ui",
      "target": "components/ui/flowing-lines-wave-background.tsx",
      "content": "import React, { useRef, useEffect } from 'react';\n\nexport const FlowingLinesWaveBackground: 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 step = 0;\n    let isVisible = true;\n\n    const render = () => {\n      if (!isVisible) return;\n      ctx.fillStyle = 'rgba(5, 5, 8, 0.2)';\n      ctx.fillRect(0, 0, canvas.width, canvas.height);\n\n      const lines = 7;\n      for (let i = 0; i < lines; i++) {\n        ctx.beginPath();\n        ctx.lineWidth = 1.2;\n        ctx.strokeStyle = `hsla(${230 + i * 15}, 85%, 65%, 0.45)`;\n\n        for (let x = 0; x < canvas.width; x += 5) {\n          const y =\n            canvas.height / 2 +\n            Math.sin((x * 0.008) + step + i * 0.4) * 45 +\n            Math.cos((x * 0.004) - step) * 20;\n          if (x === 0) ctx.moveTo(x, y);\n          else ctx.lineTo(x, y);\n        }\n        ctx.stroke();\n      }\n\n      step += 0.025;\n      animId = requestAnimationFrame(render);\n    };\n\n    animId = requestAnimationFrame(render);\n\n    const handleResize = () => {\n      const rect = canvas.getBoundingClientRect();\n      if (rect.width > 0 && rect.height > 0) {\n        canvas.width = rect.width;\n        canvas.height = rect.height;\n      }\n    };\n    handleResize();\n    const resizeObserver = new ResizeObserver(handleResize);\n    resizeObserver.observe(canvas);\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      resizeObserver.disconnect();\n    };\n  }, []);\n\n  return (\n    <div className=\"relative w-full h-56 rounded-2xl overflow-hidden bg-black border border-white/10 flex items-center justify-center\">\n      <canvas ref={canvasRef} className=\"w-full h-full\" />\n      <span className=\"absolute z-10 px-3 py-1 rounded-full bg-zinc-900/80 text-white text-[10px] font-mono border border-white/10 backdrop-blur-md\">\n        SINUSOIDAL RIBBON THREADS\n      </span>\n    </div>\n  );\n};\n"
    }
  ]
}