{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "math-curve-background",
  "title": "Math Curve Background",
  "description": "Ambient animated mathematical curve background layer with neubrutalism aesthetics — wraps content with a slow-moving curve animation",
  "dependencies": [
    "@radix-ui/react-slot"
  ],
  "registryDependencies": [
    "@boldkit/utils",
    "@boldkit/math-curves",
    "@boldkit/error-boundary"
  ],
  "files": [
    {
      "path": "registry/default/ui/math-curve-background.tsx",
      "content": "import * as React from 'react'\nimport { cn } from '@/lib/utils'\nimport { ErrorBoundary } from '@/components/ErrorBoundary'\nimport {\n  buildPath,\n  getPoint,\n  getAngle,\n  getDetailScale,\n  getCurvePulseDuration,\n  type BackgroundCurveKey,\n} from '@/lib/math-curves'\n\nconst SPEED_DURATION: Record<string, number> = {\n  slow: 9000,\n  normal: 5500,\n  fast: 3000,\n}\n\nexport interface MathCurveBackgroundProps extends React.HTMLAttributes<HTMLDivElement> {\n  curve?: BackgroundCurveKey\n  speed?: 'slow' | 'normal' | 'fast'\n  opacity?: number\n  trackColor?: string\n  headColor?: string\n  strokeWidth?: number\n  children?: React.ReactNode\n}\n\nconst MathCurveBackground = React.forwardRef<HTMLDivElement, MathCurveBackgroundProps>(\n  (\n    {\n      className,\n      curve = 'rose',\n      speed = 'slow',\n      opacity = 0.15,\n      trackColor,\n      headColor,\n      strokeWidth = 2,\n      children,\n      ...props\n    },\n    ref\n  ) => {\n    const pathRef = React.useRef<SVGPathElement>(null)\n    const rectRef = React.useRef<SVGRectElement>(null)\n    const rafRef = React.useRef<number>(0)\n    const startTimeRef = React.useRef<number>(performance.now())\n\n    const durationMs = SPEED_DURATION[speed] ?? SPEED_DURATION.slow\n    const HEAD_SIZE = 8\n\n    const initialTrackPath = React.useMemo(() => buildPath(curve, 1.0), [curve])\n\n    React.useEffect(() => {\n      startTimeRef.current = performance.now()\n\n      const tick = () => {\n        const now = performance.now()\n        const elapsed = (now - startTimeRef.current) % durationMs\n        const progress = elapsed / durationMs\n        const detailScale = getDetailScale(now, getCurvePulseDuration(curve))\n\n        const { x, y } = getPoint(curve, progress, detailScale)\n        const angle = getAngle(curve, progress, detailScale)\n\n        if (pathRef.current) {\n          pathRef.current.setAttribute('d', buildPath(curve, detailScale))\n        }\n\n        if (rectRef.current) {\n          const cx = x\n          const cy = y\n          rectRef.current.setAttribute('x', String(cx - HEAD_SIZE / 2))\n          rectRef.current.setAttribute('y', String(cy - HEAD_SIZE / 2))\n          rectRef.current.setAttribute('transform', `rotate(${angle} ${cx} ${cy})`)\n        }\n\n        rafRef.current = requestAnimationFrame(tick)\n      }\n\n      rafRef.current = requestAnimationFrame(tick)\n\n      return () => {\n        cancelAnimationFrame(rafRef.current)\n      }\n    }, [curve, speed, durationMs, strokeWidth])\n\n    const resolvedTrackStroke = trackColor ?? 'currentColor'\n    const resolvedHeadFill = headColor ?? 'hsl(var(--primary))'\n\n    return (\n      <ErrorBoundary>\n        <div\n          ref={ref}\n          className={cn('relative', className)}\n          {...props}\n        >\n          {/* Animated SVG background layer */}\n          <svg\n            viewBox=\"0 0 100 100\"\n            xmlns=\"http://www.w3.org/2000/svg\"\n            preserveAspectRatio=\"xMidYMid slice\"\n            aria-hidden=\"true\"\n            opacity={opacity}\n            style={{\n              position: 'absolute',\n              inset: 0,\n              width: '100%',\n              height: '100%',\n              zIndex: 0,\n              overflow: 'hidden',\n              pointerEvents: 'none',\n            }}\n          >\n            <path\n              ref={pathRef}\n              d={initialTrackPath}\n              fill=\"none\"\n              stroke={resolvedTrackStroke}\n              strokeWidth={strokeWidth}\n              strokeLinecap=\"square\"\n              strokeLinejoin=\"miter\"\n              className=\"transition-[stroke-opacity] duration-200\"\n            />\n            <rect\n              ref={rectRef}\n              width={HEAD_SIZE}\n              height={HEAD_SIZE}\n              x={50 - HEAD_SIZE / 2}\n              y={50 - HEAD_SIZE / 2}\n              fill={resolvedHeadFill}\n              stroke=\"currentColor\"\n              strokeWidth={1.5}\n            />\n          </svg>\n          {/* Children sit above the SVG */}\n          <div style={{ position: 'relative', zIndex: 1 }}>{children}</div>\n        </div>\n      </ErrorBoundary>\n    )\n  }\n)\nMathCurveBackground.displayName = 'MathCurveBackground'\n\nexport { MathCurveBackground }\n",
      "type": "registry:ui",
      "target": "components/ui/math-curve-background.tsx"
    }
  ],
  "type": "registry:ui"
}