{
  "name": "dither-prism-hero",
  "type": "registry:ui",
  "title": "Dither Prism Hero",
  "dependencies": [
    "@react-three/fiber",
    "@react-three/drei",
    "three",
    "framer-motion"
  ],
  "devDependencies": [
    "@types/three"
  ],
  "registryDependencies": [],
  "description": "A stunning WebGL hero background featuring advanced dithering patterns, prismatic color refraction, holographic iridescence, and center-focused ripple energy.",
  "files": [
    {
      "path": "components/ui/dither-prism-hero.tsx",
      "content": "\"use client\";\n\n/* eslint-disable react/no-unknown-property */\nimport { useRef, useMemo, useEffect, useState } from \"react\";\nimport { Canvas, useFrame, ThreeElements, useThree } from \"@react-three/fiber\";\nimport * as THREE from \"three\";\nimport { motion } from \"framer-motion\";\n\nimport { cn } from \"@/lib/utils\";\nimport { WebGLErrorBoundary, WebGLFallback } from \"./webgl-error-boundary\";\n\n// Type augmentation for R3F\ndeclare global {\n    // eslint-disable-next-line @typescript-eslint/no-namespace\n    namespace JSX {\n        type IntrinsicElements = ThreeElements;\n    }\n}\n\n// ═══════════════════════════════════════════════════════════════════════════════\n// VERTEX SHADER\n// ═══════════════════════════════════════════════════════════════════════════════\nconst vertexShader = `\nvarying vec2 vUv;\nvarying vec3 vPosition;\n\nvoid main() {\n  vUv = uv;\n  vPosition = position;\n  gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);\n}\n`;\n\n// ═══════════════════════════════════════════════════════════════════════════════\n// FRAGMENT SHADER - The magic happens here!\n// ═══════════════════════════════════════════════════════════════════════════════\nconst fragmentShader = `\nuniform float uTime;\nuniform vec2 uResolution;\nuniform vec2 uMouse;\nuniform float uMouseIntensity;\nuniform vec3 uColor1;\nuniform vec3 uColor2;\nuniform vec3 uColor3;\nuniform float uDitherIntensity;\nuniform float uPrismIntensity;\nvarying vec2 vUv;\nvarying vec3 vPosition;\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Hash functions for procedural noise\n// ─────────────────────────────────────────────────────────────────────────────\nfloat hash(vec2 p) {\n  return fract(sin(dot(p, vec2(127.1, 311.7))) * 43758.5453);\n}\n\nfloat hash3(vec3 p) {\n  return fract(sin(dot(p, vec3(127.1, 311.7, 74.7))) * 43758.5453);\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Simplex 2D Noise\n// ─────────────────────────────────────────────────────────────────────────────\nvec3 permute(vec3 x) { return mod(((x*34.0)+1.0)*x, 289.0); }\n\nfloat snoise(vec2 v) {\n  const vec4 C = vec4(0.211324865405187, 0.366025403784439,\n           -0.577350269189626, 0.024390243902439);\n  vec2 i  = floor(v + dot(v, C.yy));\n  vec2 x0 = v -   i + dot(i, C.xx);\n  vec2 i1;\n  i1 = (x0.x > x0.y) ? vec2(1.0, 0.0) : vec2(0.0, 1.0);\n  vec4 x12 = x0.xyxy + C.xxzz;\n  x12.xy -= i1;\n  i = mod(i, 289.0);\n  vec3 p = permute( permute( i.y + vec3(0.0, i1.y, 1.0))\n  + i.x + vec3(0.0, i1.x, 1.0));\n  vec3 m = max(0.5 - vec3(dot(x0,x0), dot(x12.xy,x12.xy), dot(x12.zw,x12.zw)), 0.0);\n  m = m*m;\n  m = m*m;\n  vec3 x = 2.0 * fract(p * C.www) - 1.0;\n  vec3 h = abs(x) - 0.5;\n  vec3 ox = floor(x + 0.5);\n  vec3 a0 = x - ox;\n  m *= 1.79284291400159 - 0.85373472095314 * (a0*a0 + h*h);\n  vec3 g;\n  g.x  = a0.x  * x0.x  + h.x  * x0.y;\n  g.yz = a0.yz * x12.xz + h.yz * x12.yw;\n  return 130.0 * dot(m, g);\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// FBM (Fractal Brownian Motion) for layered noise\n// ─────────────────────────────────────────────────────────────────────────────\nfloat fbm(vec2 p, int octaves) {\n  float value = 0.0;\n  float amplitude = 0.5;\n  float frequency = 1.0;\n  for (int i = 0; i < 6; i++) {\n    if (i >= octaves) break;\n    value += amplitude * snoise(p * frequency);\n    frequency *= 2.0;\n    amplitude *= 0.5;\n  }\n  return value;\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Advanced 8x8 Bayer Matrix for ordered dithering\n// ─────────────────────────────────────────────────────────────────────────────\nfloat bayer8x8(vec2 uv) {\n  ivec2 p = ivec2(mod(uv, 8.0));\n  int matrix[64];\n  matrix[0] = 0;  matrix[1] = 32; matrix[2] = 8;  matrix[3] = 40; matrix[4] = 2;  matrix[5] = 34; matrix[6] = 10; matrix[7] = 42;\n  matrix[8] = 48; matrix[9] = 16; matrix[10] = 56; matrix[11] = 24; matrix[12] = 50; matrix[13] = 18; matrix[14] = 58; matrix[15] = 26;\n  matrix[16] = 12; matrix[17] = 44; matrix[18] = 4; matrix[19] = 36; matrix[20] = 14; matrix[21] = 46; matrix[22] = 6; matrix[23] = 38;\n  matrix[24] = 60; matrix[25] = 28; matrix[26] = 52; matrix[27] = 20; matrix[28] = 62; matrix[29] = 30; matrix[30] = 54; matrix[31] = 22;\n  matrix[32] = 3;  matrix[33] = 35; matrix[34] = 11; matrix[35] = 43; matrix[36] = 1;  matrix[37] = 33; matrix[38] = 9;  matrix[39] = 41;\n  matrix[40] = 51; matrix[41] = 19; matrix[42] = 59; matrix[43] = 27; matrix[44] = 49; matrix[45] = 17; matrix[46] = 57; matrix[47] = 25;\n  matrix[48] = 15; matrix[49] = 47; matrix[50] = 7; matrix[51] = 39; matrix[52] = 13; matrix[53] = 45; matrix[54] = 5; matrix[55] = 37;\n  matrix[56] = 63; matrix[57] = 31; matrix[58] = 55; matrix[59] = 23; matrix[60] = 61; matrix[61] = 29; matrix[62] = 53; matrix[63] = 21;\n  return float(matrix[p.y * 8 + p.x]) / 64.0;\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Blue Noise approximation for organic dithering\n// ─────────────────────────────────────────────────────────────────────────────\nfloat blueNoise(vec2 uv, float time) {\n  float n1 = hash(uv + vec2(time * 0.1, 0.0));\n  float n2 = hash(uv * 2.1 + vec2(0.0, time * 0.13));\n  float n3 = hash(uv * 4.3 + vec2(time * 0.07, time * 0.11));\n  return fract(n1 + n2 * 0.5 + n3 * 0.25);\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Prismatic color refraction - creates rainbow light scattering\n// ─────────────────────────────────────────────────────────────────────────────\nvec3 prism(vec2 uv, float time, float intensity) {\n  float angle = atan(uv.y - 0.5, uv.x - 0.5);\n  float dist = length(uv - 0.5);\n  \n  // Create rotating prismatic effect\n  float prismAngle = angle + time * 0.3 + dist * 3.0;\n  \n  // RGB separation based on angle\n  float r = 0.5 + 0.5 * sin(prismAngle);\n  float g = 0.5 + 0.5 * sin(prismAngle + 2.094); // 120 degrees\n  float b = 0.5 + 0.5 * sin(prismAngle + 4.188); // 240 degrees\n  \n  return vec3(r, g, b) * intensity;\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Holographic iridescence effect\n// ─────────────────────────────────────────────────────────────────────────────\nvec3 iridescence(vec2 uv, float time) {\n  float t = time * 0.5;\n  vec2 p = uv * 3.0;\n  \n  float n1 = snoise(p + vec2(t, 0.0));\n  float n2 = snoise(p * 1.3 + vec2(0.0, t * 0.7));\n  float n3 = snoise(p * 0.7 + vec2(t * 0.5, t * 0.3));\n  \n  vec3 col1 = vec3(0.5 + 0.5 * sin(n1 * 3.14159 + t));\n  vec3 col2 = vec3(0.5 + 0.5 * sin(n2 * 3.14159 + t * 1.3 + 2.0));\n  vec3 col3 = vec3(0.5 + 0.5 * sin(n3 * 3.14159 + t * 0.7 + 4.0));\n  \n  return (col1 + col2 + col3) / 3.0;\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Geometrically morphing shapes - creates flowing crystal/diamond patterns\n// ─────────────────────────────────────────────────────────────────────────────\nfloat diamond(vec2 p) {\n  return abs(p.x) + abs(p.y);\n}\n\nfloat morphShape(vec2 uv, float time) {\n  float morph = sin(time * 0.4) * 0.5 + 0.5;\n  \n  vec2 p = uv * 4.0 - 2.0;\n  p = p + vec2(sin(time * 0.3), cos(time * 0.4)) * 0.5;\n  \n  // Morphing between circle and diamond\n  float circle = length(p) - 1.0;\n  float diam = diamond(p) - 1.4;\n  \n  float shape = mix(circle, diam, morph);\n  \n  // Create multiple copies\n  vec2 q = mod(uv * 8.0, 2.0) - 1.0;\n  float multiShape = mix(length(q), diamond(q), morph) - 0.3;\n  \n  return min(shape, multiShape);\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Mouse interaction - creates DRAMATIC ripple effect from cursor\n// ─────────────────────────────────────────────────────────────────────────────\nfloat mouseRipple(vec2 uv, vec2 mouse, float time, float intensity) {\n  float dist = length(uv - mouse);\n  // Multiple concentric ripples\n  float ripple1 = sin(dist * 40.0 - time * 5.0) * exp(-dist * 3.0);\n  float ripple2 = sin(dist * 25.0 - time * 3.5 + 1.0) * exp(-dist * 4.0);\n  float ripple3 = sin(dist * 60.0 - time * 7.0) * exp(-dist * 5.0);\n  return (ripple1 + ripple2 * 0.5 + ripple3 * 0.3) * intensity;\n}\n\n// Mouse glow - creates bright aura around cursor\nvec3 mouseGlow(vec2 uv, vec2 mouse, float time, float intensity, vec3 glowColor) {\n  float dist = length(uv - mouse);\n  \n  // Inner bright core\n  float core = exp(-dist * 15.0) * 1.5;\n  \n  // Outer soft glow\n  float outer = exp(-dist * 5.0) * 0.8;\n  \n  // Pulsing effect\n  float pulse = 0.8 + 0.2 * sin(time * 3.0);\n  \n  // Rainbow chromatic aberration around cursor\n  float chromatic = sin(dist * 30.0 + time * 2.0) * exp(-dist * 8.0);\n  vec3 rainbow = vec3(\n    sin(time * 2.0) * 0.5 + 0.5,\n    sin(time * 2.0 + 2.094) * 0.5 + 0.5,\n    sin(time * 2.0 + 4.188) * 0.5 + 0.5\n  );\n  \n  vec3 glow = glowColor * (core + outer) * pulse * intensity;\n  glow += rainbow * chromatic * intensity * 0.5;\n  \n  return glow;\n}\n\n// Lens distortion around cursor\nvec2 mouseLensDistort(vec2 uv, vec2 mouse, float intensity) {\n  vec2 delta = uv - mouse;\n  float dist = length(delta);\n  float distortion = exp(-dist * 6.0) * intensity * 0.15;\n  return uv + normalize(delta + 0.001) * distortion;\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// MAIN SHADER\n// ─────────────────────────────────────────────────────────────────────────────\nvoid main() {\n  vec2 uv = vUv;\n  vec2 pixelCoord = gl_FragCoord.xy;\n  float time = uTime;\n  \n  // ═══════════════════════════════════════════════════════════════════\n  // Layer 0: Apply mouse lens distortion to UV coordinates FIRST\n  // ═══════════════════════════════════════════════════════════════════\n  vec2 distortedUv = mouseLensDistort(uv, uMouse, uMouseIntensity);\n  \n  // ═══════════════════════════════════════════════════════════════════\n  // Layer 1: Base flowing gradient with noise (using distorted UVs)\n  // ═══════════════════════════════════════════════════════════════════\n  float noise1 = fbm(distortedUv * 2.0 + vec2(time * 0.05, time * 0.03), 4);\n  float noise2 = fbm(distortedUv * 3.0 + vec2(-time * 0.04, time * 0.06), 3);\n  \n  float diagonal = (distortedUv.x + distortedUv.y) * 0.5;\n  float flow = diagonal + noise1 * 0.3 + noise2 * 0.2;\n  flow += sin(time * 0.2) * 0.1;\n  \n  // ═══════════════════════════════════════════════════════════════════\n  // Layer 2: Color mixing with tri-color gradient\n  // ═══════════════════════════════════════════════════════════════════\n  vec3 col;\n  float t1 = smoothstep(0.0, 0.5, flow);\n  float t2 = smoothstep(0.5, 1.0, flow);\n  \n  col = mix(uColor1, uColor2, t1);\n  col = mix(col, uColor3, t2);\n  \n  // ═══════════════════════════════════════════════════════════════════\n  // Layer 3: Prismatic light refraction\n  // ═══════════════════════════════════════════════════════════════════\n  vec3 prismColor = prism(distortedUv, time, uPrismIntensity);\n  \n  // Apply prism only at edges/transitions\n  float edgeMask = abs(fract(flow * 5.0) - 0.5) * 2.0;\n  edgeMask = smoothstep(0.3, 0.7, edgeMask);\n  col += prismColor * edgeMask * 0.4;\n  \n  // ═══════════════════════════════════════════════════════════════════\n  // Layer 4: Iridescent holographic overlay\n  // ═══════════════════════════════════════════════════════════════════\n  vec3 iris = iridescence(distortedUv, time);\n  float irisMask = snoise(distortedUv * 5.0 + time * 0.1);\n  irisMask = smoothstep(-0.2, 0.8, irisMask) * 0.15;\n  col = mix(col, iris, irisMask);\n  \n  // ═══════════════════════════════════════════════════════════════════\n  // Layer 5: Geometric crystal patterns\n  // ═══════════════════════════════════════════════════════════════════\n  float shape = morphShape(distortedUv, time);\n  float shapeMask = 1.0 - smoothstep(-0.1, 0.1, shape);\n  col = mix(col, col * 1.15 + vec3(0.08), shapeMask * 0.3);\n  \n  // ═══════════════════════════════════════════════════════════════════\n  // Layer 6: VISIBLE Mouse interaction - ripples + glow + color shift\n  // ═══════════════════════════════════════════════════════════════════\n  float ripple = mouseRipple(uv, uMouse, time, uMouseIntensity);\n  \n  // Add dramatic ripple color changes\n  col += ripple * prismColor * 1.2;\n  col += ripple * vec3(0.3, 0.2, 0.4);\n  \n  // Add bright glowing cursor aura\n  vec3 glow = mouseGlow(uv, uMouse, time, uMouseIntensity, vec3(1.0, 0.8, 1.0));\n  col += glow;\n  \n  // Color shift near cursor - make area around mouse more vibrant\n  float mouseDist = length(uv - uMouse);\n  float proximityBoost = exp(-mouseDist * 4.0) * uMouseIntensity;\n  col = mix(col, col * 1.5 + prismColor * 0.3, proximityBoost);\n  \n  // ═══════════════════════════════════════════════════════════════════\n  // Layer 7: ADVANCED DITHERING - The signature look!\n  // ═══════════════════════════════════════════════════════════════════\n  \n  // 8x8 Bayer ordered dithering\n  float bayer = bayer8x8(pixelCoord);\n  \n  // Animated blue noise\n  float blue = blueNoise(pixelCoord * 0.1, time);\n  \n  // Combine dithering patterns\n  float ditherPattern = mix(bayer, blue, 0.3 + 0.2 * sin(time * 0.5));\n  \n  // Apply dithering to create the signature grainy/retro look\n  vec3 ditherOffset = (vec3(ditherPattern) - 0.5) * uDitherIntensity;\n  col += ditherOffset;\n  \n  // Quantize colors for retro dithered appearance\n  float levels = 16.0;\n  vec3 quantized = floor(col * levels + ditherPattern) / levels;\n  col = mix(col, quantized, uDitherIntensity * 0.5);\n  \n  // ═══════════════════════════════════════════════════════════════════\n  // Layer 8: Scanline effect for extra depth\n  // ═══════════════════════════════════════════════════════════════════\n  float scanline = sin(pixelCoord.y * 2.0 + time * 2.0) * 0.02;\n  col += scanline * uDitherIntensity;\n  \n  // ═══════════════════════════════════════════════════════════════════\n  // Layer 9: Vignette for cinematic depth\n  // ═══════════════════════════════════════════════════════════════════\n  float vignette = 1.0 - length((uv - 0.5) * 1.2);\n  vignette = smoothstep(0.0, 0.7, vignette);\n  col *= 0.85 + vignette * 0.15;\n  \n  // ═══════════════════════════════════════════════════════════════════\n  // Final output\n  // ═══════════════════════════════════════════════════════════════════\n  col = clamp(col, 0.0, 1.0);\n  gl_FragColor = vec4(col, 1.0);\n}\n`;\n\n// ═══════════════════════════════════════════════════════════════════════════════\n// The WebGL Plane Component\n// ═══════════════════════════════════════════════════════════════════════════════\nconst DitherPrismPlane = ({\n    color1,\n    color2,\n    color3,\n    speed = 1,\n    ditherIntensity = 0.15,\n    prismIntensity = 0.5,\n}: {\n    color1: string;\n    color2: string;\n    color3: string;\n    speed?: number;\n    ditherIntensity?: number;\n    prismIntensity?: number;\n}) => {\n    const meshRef = useRef<THREE.Mesh>(null);\n    const { size } = useThree();\n\n    const uniforms = useMemo(\n        () => ({\n            uTime: { value: 0 },\n            uResolution: { value: new THREE.Vector2(1000, 1000) },\n            uMouse: { value: new THREE.Vector2(0.5, 0.5) },\n            uMouseIntensity: { value: 0.8 },\n            uColor1: { value: new THREE.Color(color1) },\n            uColor2: { value: new THREE.Color(color2) },\n            uColor3: { value: new THREE.Color(color3) },\n            uDitherIntensity: { value: ditherIntensity },\n            uPrismIntensity: { value: prismIntensity },\n        }),\n        // eslint-disable-next-line react-hooks/exhaustive-deps\n        [] // Depend on nothing to keep reference stable\n    );\n\n    useFrame((state) => {\n        const { clock } = state;\n\n        uniforms.uTime.value = clock.getElapsedTime() * speed;\n        uniforms.uResolution.value.set(size.width, size.height);\n        uniforms.uMouse.value.set(0.5, 0.5);\n        uniforms.uMouseIntensity.value = 0.8;\n        uniforms.uColor1.value.set(color1);\n        uniforms.uColor2.value.set(color2);\n        uniforms.uColor3.value.set(color3);\n        uniforms.uDitherIntensity.value = ditherIntensity;\n        uniforms.uPrismIntensity.value = prismIntensity;\n    });\n\n    return (\n        <mesh ref={meshRef} scale={[2, 2, 1]}>\n            <planeGeometry args={[2, 2]} />\n            <shaderMaterial\n                vertexShader={vertexShader}\n                fragmentShader={fragmentShader}\n                uniforms={uniforms}\n                transparent={true}\n                depthWrite={false}\n                depthTest={false}\n            />\n        </mesh>\n    );\n};\n\n// ═══════════════════════════════════════════════════════════════════════════════\n// Floating Particles Layer - Adds depth and interactivity\n// ═══════════════════════════════════════════════════════════════════════════════\nconst FloatingParticles = ({\n    count = 50,\n    color = \"#ffffff\",\n}: {\n    count?: number;\n    color?: string;\n}) => {\n    const pointsRef = useRef<THREE.Points>(null);\n\n    const particles = useMemo(() => {\n        const positions = new Float32Array(count * 3);\n        const sizes = new Float32Array(count);\n        const phases = new Float32Array(count);\n\n        for (let i = 0; i < count; i++) {\n            positions[i * 3] = (Math.random() - 0.5) * 4;\n            positions[i * 3 + 1] = (Math.random() - 0.5) * 4;\n            positions[i * 3 + 2] = (Math.random() - 0.5) * 2;\n            sizes[i] = Math.random() * 3 + 1;\n            phases[i] = Math.random() * Math.PI * 2;\n        }\n\n        return { positions, sizes, phases };\n    }, [count]);\n\n    useFrame(({ clock }) => {\n        if (!pointsRef.current?.geometry?.attributes?.position) return;\n        const time = clock.getElapsedTime();\n        const positionAttr = pointsRef.current.geometry.attributes.position;\n        const positions = positionAttr.array as Float32Array;\n\n        for (let i = 0; i < count; i++) {\n            const phase = particles.phases[i] ?? 0;\n            const yIdx = i * 3 + 1;\n            const xIdx = i * 3;\n            positions[yIdx] = (positions[yIdx] ?? 0) + Math.sin(time + phase) * 0.001;\n            positions[xIdx] = (positions[xIdx] ?? 0) + Math.cos(time * 0.5 + phase) * 0.0005;\n\n            // Wrap particles\n            if ((positions[yIdx] ?? 0) > 2) positions[yIdx] = -2;\n            if ((positions[yIdx] ?? 0) < -2) positions[yIdx] = 2;\n        }\n\n        positionAttr.needsUpdate = true;\n    });\n\n    return (\n        <points ref={pointsRef}>\n            <bufferGeometry>\n                <bufferAttribute\n                    attach=\"attributes-position\"\n                    args={[particles.positions, 3]}\n                    count={count}\n                />\n                <bufferAttribute\n                    attach=\"attributes-size\"\n                    args={[particles.sizes, 1]}\n                    count={count}\n                />\n            </bufferGeometry>\n            <pointsMaterial\n                color={color}\n                size={0.02}\n                transparent\n                opacity={0.6}\n                sizeAttenuation\n                blending={THREE.AdditiveBlending}\n            />\n        </points>\n    );\n};\n\n// ═══════════════════════════════════════════════════════════════════════════════\n// Main Component Props\n// ═══════════════════════════════════════════════════════════════════════════════\ninterface DitherPrismHeroProps extends React.HTMLAttributes<HTMLDivElement> {\n    /** First line of headline */\n    title1?: string;\n    /** Second line of headline */\n    title2?: string;\n    /** Primary color (deep/dark) */\n    color1?: string;\n    /** Secondary color (mid) */\n    color2?: string;\n    /** Tertiary color (light/accent) */\n    color3?: string;\n    /** Animation speed multiplier */\n    speed?: number;\n    /** Dithering intensity (0-1) */\n    ditherIntensity?: number;\n    /** Prismatic refraction intensity (0-1) */\n    prismIntensity?: number;\n    /** Number of floating particles */\n    particleCount?: number;\n    /** Show floating particles */\n    showParticles?: boolean;\n    /** Particle color */\n    particleColor?: string;\n    /** Children to render on top */\n    children?: React.ReactNode;\n}\n\nconst HERO_HEADLINE_CLASS =\n    \"pb-[0.08em] text-[12cqi] md:text-[8cqi] lg:text-[6cqi] leading-[0.96] tracking-tighter font-bold text-transparent bg-clip-text bg-gradient-to-b from-zinc-900 via-zinc-500 to-zinc-800\";\n\n// ═══════════════════════════════════════════════════════════════════════════════\n// Main Export Component\n// ═══════════════════════════════════════════════════════════════════════════════\nexport default function DitherPrismHero({\n    title1,\n    title2,\n    color1 = \"#0f0f23\",\n    color2 = \"#6366f1\",\n    color3 = \"#ec4899\",\n    speed = 1,\n    ditherIntensity = 0.15,\n    prismIntensity = 0.5,\n    particleCount = 50,\n    showParticles = true,\n    particleColor = \"#ffffff\",\n    className,\n    children,\n    style,\n    ...props\n}: DitherPrismHeroProps) {\n    const [mounted, setMounted] = useState(false);\n\n    useEffect(() => {\n        setMounted(true);\n    }, []);\n\n    return (\n        <div\n            className={cn(\n                \"relative w-full min-h-screen flex flex-col items-center overflow-hidden text-gray-900\",\n                className\n            )}\n            style={{ containerType: \"size\", ...style }}\n            {...props}\n        >\n            {/* WebGL Background */}\n            {mounted && (\n                <div className=\"absolute top-0 left-0 w-full h-full z-0\">\n                    <WebGLErrorBoundary fallback={<WebGLFallback className=\"absolute inset-0 h-full w-full\" />}>\n                        <Canvas\n                            camera={{ position: [0, 0, 1] }}\n                            dpr={[1, 2]}\n                            gl={{\n                                antialias: false,\n                                alpha: true,\n                                powerPreference: \"high-performance\",\n                            }}\n                        >\n                            <DitherPrismPlane\n                                color1={color1}\n                                color2={color2}\n                                color3={color3}\n                                speed={speed}\n                                ditherIntensity={ditherIntensity}\n                                prismIntensity={prismIntensity}\n                            />\n                            {showParticles && (\n                                <FloatingParticles count={particleCount} color={particleColor} />\n                            )}\n                        </Canvas>\n                    </WebGLErrorBoundary>\n                </div>\n            )}\n\n            {/* Content Overlay */}\n            {(title1 || title2 || children) && (\n                <div className=\"relative z-10 w-full flex-1 flex flex-col items-center justify-center pt-8 pb-8 md:pt-20 md:pb-20\">\n                    <div className=\"w-full max-w-[1200px] px-6 flex flex-col items-center\">\n                        {/* Headline */}\n                        {(title1 || title2) && (\n                            <div className=\"flex flex-col items-center text-center gap-2 md:gap-4 mb-8 md:mb-12\">\n                                {title1 && (\n                                    <div className=\"overflow-hidden\">\n                                        <motion.h1\n                                            initial={{ y: \"100%\", opacity: 0 }}\n                                            animate={{ y: \"0%\", opacity: 1 }}\n                                            transition={{\n                                                duration: 1,\n                                                ease: [0.16, 1, 0.3, 1],\n                                                delay: 0.2,\n                                            }}\n                                            className={HERO_HEADLINE_CLASS}\n                                        >\n                                            <span>\n                                                {title1}\n                                            </span>\n                                        </motion.h1>\n                                    </div>\n                                )}\n                                {title2 && (\n                                    <div className=\"overflow-hidden\">\n                                        <motion.h1\n                                            initial={{ y: \"100%\", opacity: 0 }}\n                                            animate={{ y: \"0%\", opacity: 1 }}\n                                            transition={{\n                                                duration: 1,\n                                                ease: [0.16, 1, 0.3, 1],\n                                                delay: 0.35,\n                                            }}\n                                            className={HERO_HEADLINE_CLASS}\n                                        >\n                                            {title2}\n                                        </motion.h1>\n                                    </div>\n                                )}\n                            </div>\n                        )}\n\n                        {/* Custom Children */}\n                        {children && (\n                            <motion.div\n                                initial={{ opacity: 0, y: 20 }}\n                                animate={{ opacity: 1, y: 0 }}\n                                transition={{ duration: 0.8, delay: 0.7, ease: \"easeOut\" }}\n                            >\n                                {children}\n                            </motion.div>\n                        )}\n                    </div>\n                </div>\n            )}\n        </div>\n    );\n}\n\n// Named export for easier imports\nexport { DitherPrismHero };\n",
      "type": "registry:ui"
    },
    {
      "path": "components/ui/webgl-error-boundary.tsx",
      "content": "\"use client\";\n\nimport { cn } from \"@/lib/utils\";\nimport * as React from \"react\";\n\ninterface WebGLErrorBoundaryProps {\n  children: React.ReactNode;\n  fallback?: React.ReactNode;\n  onError?: (error: Error, errorInfo: React.ErrorInfo) => void;\n}\n\ninterface WebGLErrorBoundaryState {\n  hasError: boolean;\n}\n\nexport class WebGLErrorBoundary extends React.Component<\n  WebGLErrorBoundaryProps,\n  WebGLErrorBoundaryState\n> {\n  public state: WebGLErrorBoundaryState = { hasError: false };\n\n  static getDerivedStateFromError(): WebGLErrorBoundaryState {\n    return { hasError: true };\n  }\n\n  componentDidCatch(error: Error, errorInfo: React.ErrorInfo) {\n    this.props.onError?.(error, errorInfo);\n  }\n\n  render() {\n    if (this.state.hasError) {\n      return this.props.fallback ?? <WebGLFallback />;\n    }\n    return this.props.children;\n  }\n}\n\ninterface WebGLFallbackProps {\n  className?: string;\n  message?: string;\n}\n\nexport function WebGLFallback({\n  className,\n  message = \"Interactive WebGL content is unavailable on this device/browser.\",\n}: WebGLFallbackProps) {\n  return (\n    <div\n      className={cn(\n        \"flex h-full w-full items-center justify-center bg-gradient-to-br from-zinc-950 via-slate-900 to-zinc-900 px-4 text-center text-sm text-white/75\",\n        className,\n      )}\n      role=\"status\"\n      aria-live=\"polite\"\n    >\n      <p>{message}</p>\n    </div>\n  );\n}\n",
      "type": "registry:ui"
    }
  ],
  "$schema": "https://ui.shadcn.com/schema/registry-item.json"
}