{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "hero-neurix",
  "title": "Hero · Neurix",
  "description": "Hero · Neurix section.",
  "dependencies": [
    "lucide-react",
    "ogl"
  ],
  "files": [
    {
      "path": "registry/talizen/hero/hero-neurix/hero-neurix.tsx",
      "content": "import { Menu, X } from \"lucide-react\"\nimport { useState } from \"react\"\n\nimport GradientBlinds from \"./GradientBlinds\"\n\nexport function HeroNeurix() {\n  const navItems = [\"HOME\", \"FEATURES\", \"RESOURCES\", \"PRICING\"]\n  const [menuOpen, setMenuOpen] = useState(false)\n  const MenuIcon = menuOpen ? X : Menu\n\n  return (\n    <div className=\"relative flex min-h-screen w-full flex-col overflow-hidden bg-[#050505] font-sans text-white\">\n      <nav className=\"relative z-10 mx-auto grid w-full max-w-7xl grid-cols-[minmax(0,1fr)_auto] items-center gap-3 px-5 py-5 sm:px-8 md:grid-cols-[auto_minmax(0,1fr)_auto] md:py-6\">\n        <div className=\"flex items-center gap-2\">\n          <span className=\"text-xl font-bold tracking-tighter\">NEURIX</span>\n        </div>\n\n        <div className=\"hidden items-center justify-center gap-8 text-sm font-medium text-gray-400 md:flex\">\n          {navItems.map((item) => (\n            <a key={item} href=\"#\" className=\"transition-colors hover:text-white\">\n              {item}\n            </a>\n          ))}\n        </div>\n\n        <div className=\"flex items-center justify-end gap-2 text-sm font-medium sm:gap-4\">\n          <a href=\"#\" className=\"hidden text-gray-400 transition-colors hover:text-white sm:inline\">\n            Log in\n          </a>\n          <a\n            href=\"#\"\n            className=\"group hidden items-center gap-2 rounded-lg border border-zinc-700 bg-zinc-800 px-4 py-2 text-white transition-all hover:bg-zinc-700 min-[430px]:flex sm:px-5\"\n          >\n            Start Free\n            <svg\n              className=\"h-4 w-4 transition-transform group-hover:-translate-y-0.5 group-hover:translate-x-0.5\"\n              viewBox=\"0 0 24 24\"\n              fill=\"none\"\n              stroke=\"currentColor\"\n              strokeWidth=\"2\"\n              strokeLinecap=\"round\"\n              strokeLinejoin=\"round\"\n              aria-hidden=\"true\"\n            >\n              <line x1=\"7\" y1=\"17\" x2=\"17\" y2=\"7\" />\n              <polyline points=\"7 7 17 7 17 17\" />\n            </svg>\n          </a>\n          <button\n            type=\"button\"\n            onClick={() => setMenuOpen((open) => !open)}\n            aria-label={menuOpen ? \"Close menu\" : \"Open menu\"}\n            aria-expanded={menuOpen}\n            aria-controls=\"neurix-mobile-menu\"\n            className=\"inline-grid size-10 place-items-center rounded-lg border border-zinc-700 bg-zinc-800 text-white transition-all hover:bg-zinc-700 md:hidden\"\n          >\n            <MenuIcon className=\"size-5\" aria-hidden=\"true\" />\n          </button>\n        </div>\n\n        <div\n          id=\"neurix-mobile-menu\"\n          className={`absolute left-5 right-5 top-[calc(100%+8px)] z-30 overflow-hidden rounded-xl border border-zinc-800 bg-zinc-950/90 p-2 shadow-[0_24px_80px_rgba(0,0,0,0.42)] backdrop-blur-xl transition duration-200 md:hidden ${\n            menuOpen ? \"translate-y-0 opacity-100\" : \"pointer-events-none -translate-y-2 opacity-0\"\n          }`}\n        >\n          <div className=\"grid text-sm font-medium text-gray-400\">\n            {navItems.map((item) => (\n              <a\n                key={item}\n                href=\"#\"\n                onClick={() => setMenuOpen(false)}\n                className=\"rounded-lg px-4 py-3 transition hover:bg-white/8 hover:text-white\"\n              >\n                {item}\n              </a>\n            ))}\n          </div>\n          <a\n            href=\"#\"\n            onClick={() => setMenuOpen(false)}\n            className=\"mt-2 flex min-h-10 items-center justify-center rounded-lg border border-zinc-700 bg-zinc-800 px-4 text-sm font-medium text-white transition-all hover:bg-zinc-700 sm:hidden\"\n          >\n            Log in\n          </a>\n          <a\n            href=\"#\"\n            onClick={() => setMenuOpen(false)}\n            className=\"mt-2 flex min-h-10 items-center justify-center rounded-lg bg-white px-4 text-sm font-semibold text-black transition-all hover:bg-zinc-200 min-[430px]:hidden\"\n          >\n            Start Free\n          </a>\n        </div>\n      </nav>\n\n      <main className=\"relative z-10 mx-auto flex max-w-4xl flex-1 flex-col items-center justify-center px-4 pb-12 pt-12 text-center md:pt-24\">\n        <div className=\"mb-8 flex items-center gap-2 rounded-full border border-zinc-800 bg-zinc-900/50 px-3 py-1 pr-4 text-[10px] backdrop-blur-sm sm:text-xs\">\n          <span className=\"scale-90 rounded-full bg-white px-2 py-0.5 text-[9px] font-bold text-black\">\n            UPDATE\n          </span>\n          <span className=\"font-medium tracking-wide text-zinc-400\">CUSTOMIZABLE AI LOGIC</span>\n        </div>\n\n        <h1 className=\"mb-6 text-[2.6rem] font-semibold leading-[1.1] tracking-tight sm:text-6xl md:text-7xl\">\n          AI That Thinks With You <br />\n          <span>Not For You</span>\n        </h1>\n\n        <p className=\"mx-auto mb-12 max-w-2xl text-base leading-relaxed text-zinc-400 md:text-lg\">\n          Neurix helps teams turn scattered data into confident decisions using adaptive AI\n          workflows built for speed, clarity, and scale.\n        </p>\n\n        <div className=\"group relative w-full max-w-2xl\">\n          <div className=\"absolute -inset-0.5 rounded-2xl bg-gradient-to-r from-zinc-700 to-zinc-800 opacity-25 blur transition duration-1000 group-hover:opacity-50 group-hover:duration-200\" />\n          <div className=\"relative rounded-2xl border border-zinc-800 bg-zinc-900/90 p-4 shadow-2xl backdrop-blur-xl\">\n            <textarea\n              className=\"h-24 w-full resize-none border-none bg-transparent text-base text-zinc-300 outline-none placeholder:text-zinc-600 focus:ring-0\"\n              placeholder=\"Ask Neurix anything...\"\n            />\n            <div className=\"mt-4 flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between\">\n              <div className=\"flex flex-wrap items-center gap-3\">\n                <button className=\"flex items-center gap-1.5 rounded-lg border border-zinc-700/50 bg-zinc-800/50 px-3 py-1.5 text-xs text-zinc-400 transition-colors hover:bg-zinc-800\">\n                  <svg\n                    className=\"h-3.5 w-3.5\"\n                    viewBox=\"0 0 24 24\"\n                    fill=\"none\"\n                    stroke=\"currentColor\"\n                    strokeWidth=\"2\"\n                    strokeLinecap=\"round\"\n                    strokeLinejoin=\"round\"\n                    aria-hidden=\"true\"\n                  >\n                    <path d=\"m21.44 11.05-9.19 9.19a6 6 0 0 1-8.49-8.49l8.57-8.57A4 4 0 1 1 18 8.84l-8.59 8.51a2 2 0 0 1-2.83-2.83l8.49-8.48\" />\n                  </svg>\n                  Attach\n                </button>\n                <div className=\"flex items-center gap-1.5 rounded-lg border border-zinc-700/50 bg-zinc-800/50 px-3 py-1.5 text-xs text-zinc-400\">\n                  Select style\n                  <svg\n                    className=\"h-3 w-3 opacity-50\"\n                    viewBox=\"0 0 24 24\"\n                    fill=\"none\"\n                    stroke=\"currentColor\"\n                    strokeWidth=\"2\"\n                    strokeLinecap=\"round\"\n                    strokeLinejoin=\"round\"\n                    aria-hidden=\"true\"\n                  >\n                    <path d=\"m6 9 6 6 6-6\" />\n                  </svg>\n                </div>\n              </div>\n              <button className=\"self-end rounded-lg bg-white p-2 text-black transition-colors hover:bg-zinc-200 sm:self-auto\">\n                <svg\n                  className=\"h-4 w-4\"\n                  viewBox=\"0 0 24 24\"\n                  fill=\"none\"\n                  stroke=\"currentColor\"\n                  strokeWidth=\"3\"\n                  strokeLinecap=\"round\"\n                  strokeLinejoin=\"round\"\n                  aria-hidden=\"true\"\n                >\n                  <path d=\"m5 12 7-7 7 7\" />\n                  <path d=\"M12 19V5\" />\n                </svg>\n              </button>\n            </div>\n          </div>\n        </div>\n\n        <div className=\"mt-24 flex w-full flex-col items-center gap-8 md:mt-32\">\n          <p className=\"text-[10px] font-semibold uppercase tracking-[0.2em] text-zinc-500\">\n            Trusted by experts at\n          </p>\n          <div className=\"flex flex-wrap items-center justify-center gap-x-8 gap-y-5 opacity-40 grayscale contrast-125 sm:gap-x-12\">\n            <span className=\"text-xl font-bold tracking-tight\">Google</span>\n            <span className=\"text-xl font-bold tracking-tight\">Microsoft</span>\n            <span className=\"text-xl font-bold tracking-tight\">stripe</span>\n            <span className=\"text-xl font-bold tracking-tight\">amazon</span>\n          </div>\n        </div>\n      </main>\n\n      <div className=\"pointer-events-none absolute left-0 top-0 z-0 h-full w-full opacity-80\">\n        <GradientBlinds\n          gradientColors={[\"#FFFFFF\", \"#F472B6\", \"#3B82F6\", \"#1E3A8A\", \"#050505\"]}\n          gradientColorsSecondary={[\"#FDF2F8\", \"#EC4899\", \"#2563EB\", \"#172554\", \"#050505\"]}\n          angle={0}\n          noise={0.8}\n          blindCount={16}\n          blindMinWidth={60}\n          spotlightRadius={0.7}\n          spotlightSoftness={1.2}\n          spotlightOpacity={1}\n          distortAmount={0}\n          mouseDampening={0.15}\n          shineDirection=\"right\"\n          mirrorGradient\n          mixBlendMode=\"screen\"\n        />\n      </div>\n\n      <div className=\"pointer-events-none fixed bottom-0 left-0 right-0 z-20 h-32 bg-gradient-to-t from-[#050505] to-transparent\" />\n    </div>\n  )\n}\n\nexport default HeroNeurix\n",
      "type": "registry:component"
    },
    {
      "path": "registry/talizen/hero/hero-neurix/GradientBlinds.tsx",
      "content": "import React, { useEffect, useRef } from 'react';\nimport { Renderer, Program, Mesh, Triangle } from 'ogl';\n\nexport interface GradientBlindsProps {\n  className?: string;\n  dpr?: number;\n  paused?: boolean;\n  gradientColors?: string[];\n  gradientColorsSecondary?: string[];\n  angle?: number;\n  noise?: number;\n  blindCount?: number;\n  blindMinWidth?: number;\n  mouseDampening?: number;\n  mirrorGradient?: boolean;\n  spotlightRadius?: number;\n  spotlightSoftness?: number;\n  spotlightOpacity?: number;\n  distortAmount?: number;\n  shineDirection?: 'left' | 'right';\n  mixBlendMode?: string;\n}\n\nconst MAX_COLORS = 8;\nconst hexToRGB = (hex: string): [number, number, number] => {\n  const c = hex.replace('#', '').padEnd(6, '0');\n  const r = parseInt(c.slice(0, 2), 16) / 255;\n  const g = parseInt(c.slice(2, 4), 16) / 255;\n  const b = parseInt(c.slice(4, 6), 16) / 255;\n  return [r, g, b];\n};\nconst prepStops = (stops?: string[]) => {\n  const base = (stops && stops.length ? stops : ['#FF9FFC', '#5227FF']).slice(0, MAX_COLORS);\n  if (base.length === 1) base.push(base[0]);\n  while (base.length < MAX_COLORS) base.push(base[base.length - 1]);\n  const arr: [number, number, number][] = [];\n  for (let i = 0; i < MAX_COLORS; i++) arr.push(hexToRGB(base[i]));\n  const count = Math.max(2, Math.min(MAX_COLORS, stops?.length ?? 2));\n  return { arr, count };\n};\n\nconst GradientBlinds: React.FC<GradientBlindsProps> = ({\n  className,\n  dpr,\n  paused = false,\n  gradientColors,\n  gradientColorsSecondary,\n  angle = 0,\n  noise = 0.3,\n  blindCount = 16,\n  blindMinWidth = 60,\n  mouseDampening = 0.15,\n  mirrorGradient = false,\n  spotlightRadius = 0.5,\n  spotlightSoftness = 1,\n  spotlightOpacity = 1,\n  distortAmount = 0,\n  shineDirection = 'left',\n  mixBlendMode = 'lighten'\n}) => {\n  const containerRef = useRef<HTMLDivElement | null>(null);\n  const rafRef = useRef<number | null>(null);\n  const programRef = useRef<Program | null>(null);\n  const meshRef = useRef<Mesh<Triangle> | null>(null);\n  const geometryRef = useRef<Triangle | null>(null);\n  const rendererRef = useRef<Renderer | null>(null);\n  const mouseTargetRef = useRef<[number, number]>([0, 0]);\n  const lastTimeRef = useRef<number>(0);\n  const firstResizeRef = useRef<boolean>(true);\n\n  useEffect(() => {\n    const container = containerRef.current;\n    if (!container) return;\n\n    let renderer: Renderer;\n    try {\n      renderer = new Renderer({\n        dpr: dpr ?? (typeof window !== 'undefined' ? window.devicePixelRatio || 1 : 1),\n        alpha: true,\n        antialias: true\n      });\n    } catch {\n      return;\n    }\n    rendererRef.current = renderer;\n    const gl = renderer.gl;\n    const canvas = gl.canvas as HTMLCanvasElement;\n\n    canvas.style.width = '100%';\n    canvas.style.height = '100%';\n    canvas.style.display = 'block';\n    container.appendChild(canvas);\n\n    const vertex = `\nattribute vec2 position;\nattribute vec2 uv;\nvarying vec2 vUv;\n\nvoid main() {\n  vUv = uv;\n  gl_Position = vec4(position, 0.0, 1.0);\n}\n`;\n\n    const fragment = `\n#ifdef GL_ES\nprecision mediump float;\n#endif\n\nuniform vec3  iResolution;\nuniform vec2  iMouse;\nuniform float iTime;\n\nuniform float uAngle;\nuniform float uNoise;\nuniform float uBlindCount;\nuniform float uSpotlightRadius;\nuniform float uSpotlightSoftness;\nuniform float uSpotlightOpacity;\nuniform float uMirror;\nuniform float uDistort;\nuniform float uShineFlip;\nuniform vec3  uColor0;\nuniform vec3  uColor1;\nuniform vec3  uColor2;\nuniform vec3  uColor3;\nuniform vec3  uColor4;\nuniform vec3  uColor5;\nuniform vec3  uColor6;\nuniform vec3  uColor7;\nuniform int   uColorCount;\n\nuniform vec3  uColorS0;\nuniform vec3  uColorS1;\nuniform vec3  uColorS2;\nuniform vec3  uColorS3;\nuniform vec3  uColorS4;\nuniform vec3  uColorS5;\nuniform vec3  uColorS6;\nuniform vec3  uColorS7;\nuniform int   uColorCountS;\n\nvarying vec2 vUv;\n\nfloat rand(vec2 co){\n  return fract(sin(dot(co, vec2(12.9898,78.233))) * 43758.5453);\n}\n\nvec2 rotate2D(vec2 p, float a){\n  float c = cos(a);\n  float s = sin(a);\n  return mat2(c, -s, s, c) * p;\n}\n\nvec3 getGradientColor(float t){\n  float tt = clamp(t, 0.0, 1.0);\n  int count = uColorCount;\n  if (count < 2) count = 2;\n  float scaled = tt * float(count - 1);\n  float seg = floor(scaled);\n  float f = fract(scaled);\n\n  if (seg < 1.0) return mix(uColor0, uColor1, f);\n  if (seg < 2.0 && count > 2) return mix(uColor1, uColor2, f);\n  if (seg < 3.0 && count > 3) return mix(uColor2, uColor3, f);\n  if (seg < 4.0 && count > 4) return mix(uColor3, uColor4, f);\n  if (seg < 5.0 && count > 5) return mix(uColor4, uColor5, f);\n  if (seg < 6.0 && count > 6) return mix(uColor5, uColor6, f);\n  if (seg < 7.0 && count > 7) return mix(uColor6, uColor7, f);\n  if (count > 7) return uColor7;\n  if (count > 6) return uColor6;\n  if (count > 5) return uColor5;\n  if (count > 4) return uColor4;\n  if (count > 3) return uColor3;\n  if (count > 2) return uColor2;\n  return uColor1;\n}\n\nvec3 getGradientColorS(float t){\n  float tt = clamp(t, 0.0, 1.0);\n  int count = uColorCountS;\n  if (count < 2) count = 2;\n  float scaled = tt * float(count - 1);\n  float seg = floor(scaled);\n  float f = fract(scaled);\n\n  if (seg < 1.0) return mix(uColorS0, uColorS1, f);\n  if (seg < 2.0 && count > 2) return mix(uColorS1, uColorS2, f);\n  if (seg < 3.0 && count > 3) return mix(uColorS2, uColorS3, f);\n  if (seg < 4.0 && count > 4) return mix(uColorS3, uColorS4, f);\n  if (seg < 5.0 && count > 5) return mix(uColorS4, uColorS5, f);\n  if (seg < 6.0 && count > 6) return mix(uColorS5, uColorS6, f);\n  if (seg < 7.0 && count > 7) return mix(uColorS6, uColorS7, f);\n  if (count > 7) return uColorS7;\n  if (count > 6) return uColorS6;\n  if (count > 5) return uColorS5;\n  if (count > 4) return uColorS4;\n  if (count > 3) return uColorS3;\n  if (count > 2) return uColorS2;\n  return uColorS1;\n}\n\n\nvoid mainImage( out vec4 fragColor, in vec2 fragCoord )\n{\n    vec2 uvraw = fragCoord.xy / iResolution.xy;\n    float aspect = iResolution.x / iResolution.y;\n    \n    vec2 p = uvraw * 2.0 - 1.0;\n    p.x *= aspect;\n    vec2 pr = rotate2D(p, uAngle);\n    pr.x /= aspect;\n    vec2 uv = pr * 0.5 + 0.5;\n\n    // t: 0 at top, 1 at bottom\n    float t = uv.y;\n    \n    float t_h = uv.x;\n    if (uMirror > 0.5) {\n      t_h = 1.0 - abs(1.0 - 2.0 * fract(t_h));\n    }\n    \n    // Base color from vertical gradient mixed with secondary horizontal gradient\n    vec3 base = mix(getGradientColor(t), getGradientColorS(t), t_h);\n\n    // Column logic\n    float grid = uv.x * uBlindCount;\n    float stripe = fract(grid);\n    if (uShineFlip > 0.5) stripe = 1.0 - stripe;\n\n    // Gentle \"stepped\" V-shape top boundary\n    float colID = floor(grid);\n    float colCenter = (colID + 0.5) / uBlindCount;\n    float dx = colCenter - 0.5;\n    float vHeight = 0.48 + (dx * dx) * 1.8; // Quadratic curve for gentler center\n    float hJitter = (rand(vec2(colID, 13.37)) - 0.5) * 0.1; // Add subtle organic unevenness\n    float topClip = 1.0 - smoothstep(vHeight + hJitter - 0.01, vHeight + hJitter + 0.01, uvraw.y);\n    \n    // Pillar shape with \"Crease\" (折痕) effect\n    // We use a sharper transition at 0.5 of the stripe\n    float crease = stripe < 0.5 ? mix(0.8, 1.0, stripe * 2.0) : mix(1.0, 0.7, (stripe - 0.5) * 2.0);\n    float pillar = smoothstep(0.0, 0.05, stripe) * smoothstep(1.0, 0.95, stripe) * crease;\n    \n    // Random brightness per column\n    float pRand = rand(vec2(colID, 42.0));\n    float brightness = 0.7 + 0.5 * pRand;\n    \n    // Base Pillar Color\n    vec3 col = base * pillar * brightness;\n\n    // Mouse/Spotlight Glow\n    vec2 mouseUV = iMouse.xy / iResolution.xy;\n    float dist = length(uvraw - mouseUV);\n    float spot = pow(max(0.0, 1.0 - dist / uSpotlightRadius), uSpotlightSoftness) * uSpotlightOpacity;\n    col += base * spot * 0.5; // Additive glow using base color\n\n    // Apply the V-shape clip\n    col *= topClip;\n\n    // Grain - very important for this look\n    col += (rand(uvraw + iTime * 0.01) - 0.5) * uNoise;\n\n    fragColor = vec4(max(vec3(0.0), col), 1.0);\n}\n\nvoid main() {\n    vec4 color;\n    mainImage(color, vUv * iResolution.xy);\n    gl_FragColor = color;\n}\n`;\n\n    const { arr: colorArr, count: colorCount } = prepStops(gradientColors);\n    const { arr: colorArrS, count: colorCountS } = prepStops(gradientColorsSecondary || gradientColors);\n    const uniforms: {\n      iResolution: { value: [number, number, number] };\n      iMouse: { value: [number, number] };\n      iTime: { value: number };\n      uAngle: { value: number };\n      uNoise: { value: number };\n      uBlindCount: { value: number };\n      uSpotlightRadius: { value: number };\n      uSpotlightSoftness: { value: number };\n      uSpotlightOpacity: { value: number };\n      uMirror: { value: number };\n      uDistort: { value: number };\n      uShineFlip: { value: number };\n      uColor0: { value: [number, number, number] };\n      uColor1: { value: [number, number, number] };\n      uColor2: { value: [number, number, number] };\n      uColor3: { value: [number, number, number] };\n      uColor4: { value: [number, number, number] };\n      uColor5: { value: [number, number, number] };\n      uColor6: { value: [number, number, number] };\n      uColor7: { value: [number, number, number] };\n      uColorCount: { value: number };\n      uColorS0: { value: [number, number, number] };\n      uColorS1: { value: [number, number, number] };\n      uColorS2: { value: [number, number, number] };\n      uColorS3: { value: [number, number, number] };\n      uColorS4: { value: [number, number, number] };\n      uColorS5: { value: [number, number, number] };\n      uColorS6: { value: [number, number, number] };\n      uColorS7: { value: [number, number, number] };\n      uColorCountS: { value: number };\n    } = {\n      iResolution: {\n        value: [gl.drawingBufferWidth, gl.drawingBufferHeight, 1]\n      },\n      iMouse: { value: [0, 0] },\n      iTime: { value: 0 },\n      uAngle: { value: (angle * Math.PI) / 180 },\n      uNoise: { value: noise },\n      uBlindCount: { value: Math.max(1, blindCount) },\n      uSpotlightRadius: { value: spotlightRadius },\n      uSpotlightSoftness: { value: spotlightSoftness },\n      uSpotlightOpacity: { value: spotlightOpacity },\n      uMirror: { value: mirrorGradient ? 1 : 0 },\n      uDistort: { value: distortAmount },\n      uShineFlip: { value: shineDirection === 'right' ? 1 : 0 },\n      uColor0: { value: colorArr[0] },\n      uColor1: { value: colorArr[1] },\n      uColor2: { value: colorArr[2] },\n      uColor3: { value: colorArr[3] },\n      uColor4: { value: colorArr[4] },\n      uColor5: { value: colorArr[5] },\n      uColor6: { value: colorArr[6] },\n      uColor7: { value: colorArr[7] },\n      uColorCount: { value: colorCount },\n      uColorS0: { value: colorArrS[0] },\n      uColorS1: { value: colorArrS[1] },\n      uColorS2: { value: colorArrS[2] },\n      uColorS3: { value: colorArrS[3] },\n      uColorS4: { value: colorArrS[4] },\n      uColorS5: { value: colorArrS[5] },\n      uColorS6: { value: colorArrS[6] },\n      uColorS7: { value: colorArrS[7] },\n      uColorCountS: { value: colorCountS }\n    };\n\n    const program = new Program(gl, {\n      vertex,\n      fragment,\n      uniforms\n    });\n    programRef.current = program;\n\n    const geometry = new Triangle(gl);\n    geometryRef.current = geometry;\n    const mesh = new Mesh(gl, { geometry, program });\n    meshRef.current = mesh;\n\n    const resize = () => {\n      const rect = container.getBoundingClientRect();\n      renderer.setSize(rect.width, rect.height);\n      uniforms.iResolution.value = [gl.drawingBufferWidth, gl.drawingBufferHeight, 1];\n\n      if (blindMinWidth && blindMinWidth > 0) {\n        const maxByMinWidth = Math.max(1, Math.floor(rect.width / blindMinWidth));\n\n        const effective = blindCount ? Math.min(blindCount, maxByMinWidth) : maxByMinWidth;\n        uniforms.uBlindCount.value = Math.max(1, effective);\n      } else {\n        uniforms.uBlindCount.value = Math.max(1, blindCount);\n      }\n\n      if (firstResizeRef.current) {\n        firstResizeRef.current = false;\n        const cx = gl.drawingBufferWidth / 2;\n        const cy = gl.drawingBufferHeight / 2;\n        uniforms.iMouse.value = [cx, cy];\n        mouseTargetRef.current = [cx, cy];\n      }\n    };\n\n    resize();\n    const ro = new ResizeObserver(resize);\n    ro.observe(container);\n\n    const onPointerMove = (e: PointerEvent) => {\n      const rect = canvas.getBoundingClientRect();\n      const scale = (renderer as unknown as { dpr?: number }).dpr || 1;\n      const x = (e.clientX - rect.left) * scale;\n      const y = (rect.height - (e.clientY - rect.top)) * scale;\n      mouseTargetRef.current = [x, y];\n      if (mouseDampening <= 0) {\n        uniforms.iMouse.value = [x, y];\n      }\n    };\n    canvas.addEventListener('pointermove', onPointerMove);\n\n    const loop = (t: number) => {\n      rafRef.current = requestAnimationFrame(loop);\n      uniforms.iTime.value = t * 0.001;\n      if (mouseDampening > 0) {\n        if (!lastTimeRef.current) lastTimeRef.current = t;\n        const dt = (t - lastTimeRef.current) / 1000;\n        lastTimeRef.current = t;\n        const tau = Math.max(1e-4, mouseDampening);\n        let factor = 1 - Math.exp(-dt / tau);\n        if (factor > 1) factor = 1;\n        const target = mouseTargetRef.current;\n        const cur = uniforms.iMouse.value;\n        cur[0] += (target[0] - cur[0]) * factor;\n        cur[1] += (target[1] - cur[1]) * factor;\n      } else {\n        lastTimeRef.current = t;\n      }\n      if (!paused && programRef.current && meshRef.current) {\n        try {\n          renderer.render({ scene: meshRef.current });\n        } catch (e) {\n          console.error(e);\n        }\n      }\n    };\n    rafRef.current = requestAnimationFrame(loop);\n\n    return () => {\n      if (rafRef.current) cancelAnimationFrame(rafRef.current);\n      canvas.removeEventListener('pointermove', onPointerMove);\n      ro.disconnect();\n      if (canvas.parentElement === container) {\n        container.removeChild(canvas);\n      }\n      const callIfFn = <T extends object, K extends keyof T>(obj: T | null, key: K) => {\n        if (obj && typeof obj[key] === 'function') {\n          (obj[key] as unknown as () => void).call(obj);\n        }\n      };\n      callIfFn(programRef.current, 'remove');\n      callIfFn(geometryRef.current, 'remove');\n      callIfFn(meshRef.current as unknown as { remove?: () => void }, 'remove');\n      callIfFn(rendererRef.current as unknown as { destroy?: () => void }, 'destroy');\n      programRef.current = null;\n      geometryRef.current = null;\n      meshRef.current = null;\n      rendererRef.current = null;\n    };\n  }, [\n    dpr,\n    paused,\n    gradientColors,\n    gradientColorsSecondary,\n    angle,\n    noise,\n    blindCount,\n    blindMinWidth,\n    mouseDampening,\n    mirrorGradient,\n    spotlightRadius,\n    spotlightSoftness,\n    spotlightOpacity,\n    distortAmount,\n    shineDirection\n  ]);\n\n  return (\n    <div\n      ref={containerRef}\n      className={`w-full h-full overflow-hidden relative ${className}`}\n      style={{\n        ...(mixBlendMode && {\n          mixBlendMode: mixBlendMode as React.CSSProperties['mixBlendMode']\n        })\n      }}\n    />\n  );\n};\n\nexport default GradientBlinds;\n",
      "type": "registry:component"
    }
  ],
  "categories": [
    "hero"
  ],
  "type": "registry:block"
}