{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "ai-badge",
  "title": "AI Badge",
  "description": "Interactive 3D badge component with Atropos effect, customizable branding, QR code, and AI avatar support",
  "dependencies": [
    "atropos",
    "qrcode"
  ],
  "devDependencies": [
    "@types/qrcode"
  ],
  "registryDependencies": [],
  "files": [
    {
      "path": "registry/default/blocks/badges/ai-badge/components/elements/ai-badge.tsx",
      "content": "\"use client\";\n\nimport Atropos from \"atropos/react\";\nimport \"atropos/css\";\n\nimport { forwardRef } from \"react\";\n\nimport { cn } from \"@/lib/utils\";\n\nimport {\n  type BadgeBackground,\n  type BadgeBranding,\n  type BadgeColors,\n  type BadgePatternType,\n  BadgePreview,\n} from \"./badge-preview\";\n\nexport type { BadgeColors, BadgeBranding, BadgeBackground, BadgePatternType };\n\nexport interface AIBadgeProps {\n  /** URL of the profile picture (can be AI-generated) */\n  profilePictureUrl?: string | null;\n  /** Badge/member number (e.g., \"#001\") */\n  badgeNumber: string;\n  /** First name */\n  firstName: string;\n  /** Last name */\n  lastName?: string;\n  /** Role or title displayed on badge */\n  jobTitle: string;\n  /** Custom URL for QR code (defaults to current origin + /p/{number}) */\n  qrCodeUrl?: string;\n  /** Custom color palette */\n  colors?: Partial<BadgeColors>;\n  /** Custom branding (title, subtitle, logo) */\n  branding?: BadgeBranding;\n  /** Custom background (pattern, image, gradient) */\n  background?: BadgeBackground;\n  /** Additional CSS classes */\n  className?: string;\n}\n\nexport const AIBadge = forwardRef<SVGSVGElement, AIBadgeProps>(function AIBadge(\n  {\n    profilePictureUrl,\n    badgeNumber,\n    firstName,\n    lastName,\n    jobTitle,\n    qrCodeUrl,\n    colors,\n    branding,\n    background,\n    className,\n  },\n  ref,\n) {\n  return (\n    <div data-slot=\"ai-badge\" className={cn(\"w-full\", className)}>\n      <Atropos\n        className=\"atropos-badge w-full\"\n        activeOffset={40}\n        shadowScale={1.05}\n        rotateXMax={15}\n        rotateYMax={15}\n        shadow={true}\n        highlight={true}\n      >\n        {/* Outer glass frame - furthest back */}\n        <div\n          data-atropos-offset=\"-3\"\n          className=\"absolute inset-0 rounded-2xl\"\n          style={{\n            background:\n              \"linear-gradient(135deg, rgba(255,255,255,0.1) 0%, rgba(255,255,255,0.05) 100%)\",\n            boxShadow:\n              \"0 25px 80px rgba(0, 0, 0, 0.4), inset 1px 1px 2px rgba(255,255,255,0.1)\",\n            border: \"1px solid rgba(255,255,255,0.15)\",\n          }}\n        />\n\n        {/* Badge content - middle layer */}\n        <div\n          data-atropos-offset=\"0\"\n          className=\"relative rounded-xl overflow-hidden\"\n          style={{\n            boxShadow: \"0 10px 40px rgba(0, 0, 0, 0.3)\",\n          }}\n        >\n          <BadgePreview\n            ref={ref}\n            profilePictureUrl={profilePictureUrl}\n            badgeNumber={badgeNumber}\n            firstName={firstName}\n            lastName={lastName}\n            jobTitle={jobTitle}\n            qrCodeUrl={qrCodeUrl}\n            colors={colors}\n            branding={branding}\n            background={background}\n          />\n        </div>\n      </Atropos>\n\n      <style jsx global>{`\n          .atropos-badge {\n            perspective: 1200px;\n          }\n          .atropos-badge .atropos-scale,\n          .atropos-badge .atropos-rotate {\n            transform-style: preserve-3d;\n          }\n          .atropos-badge .atropos-inner {\n            transform-style: preserve-3d;\n          }\n          .atropos-badge .atropos-shadow {\n            filter: blur(30px);\n            background: radial-gradient(\n              ellipse at center,\n              rgba(0, 0, 0, 0.35) 0%,\n              transparent 70%\n            );\n          }\n          .atropos-badge .atropos-highlight {\n            background: radial-gradient(\n              ellipse at center,\n              rgba(255, 255, 255, 0.15) 0%,\n              transparent 60%\n            );\n          }\n        `}</style>\n    </div>\n  );\n});\n",
      "type": "registry:component"
    },
    {
      "path": "registry/default/blocks/badges/ai-badge/components/elements/badge-preview.tsx",
      "content": "\"use client\";\n\nimport { forwardRef, useEffect, useState } from \"react\";\n\nimport QRCode from \"qrcode\";\n\nimport { cn } from \"@/lib/utils\";\n\nexport interface BadgeColors {\n  background: string;\n  foreground: string;\n  primary: string;\n  muted: string;\n  mutedForeground: string;\n}\n\nexport interface BadgeBranding {\n  title: string;\n  subtitle: string;\n  logo?: React.ReactNode;\n  organizationName?: string;\n  organizationSubtitle?: string;\n}\n\nexport type BadgePatternType =\n  | \"none\"\n  | \"radial\"\n  | \"grid\"\n  | \"dots\"\n  | \"waves\"\n  | \"hexagons\"\n  | \"circuits\";\n\nexport interface BadgeBackground {\n  /** Background pattern type */\n  pattern?: BadgePatternType;\n  /** Pattern opacity (0-1) */\n  patternOpacity?: number;\n  /** Pattern color (defaults to foreground) */\n  patternColor?: string;\n  /** Custom background image URL */\n  imageUrl?: string;\n  /** Background image opacity (0-1) */\n  imageOpacity?: number;\n  /** Gradient stops (e.g., [\"#ff0000\", \"#0000ff\"]) */\n  gradient?: string[];\n  /** Gradient direction in degrees (default: 135) */\n  gradientAngle?: number;\n}\n\nexport interface BadgePreviewProps {\n  profilePictureUrl?: string | null;\n  badgeNumber: string;\n  firstName: string;\n  lastName?: string;\n  jobTitle: string;\n  qrCodeUrl?: string;\n  colors?: Partial<BadgeColors>;\n  branding?: BadgeBranding;\n  background?: BadgeBackground;\n  className?: string;\n}\n\nconst DEFAULT_COLORS: BadgeColors = {\n  background: \"#FAFAFA\",\n  foreground: \"#0A0A0A\",\n  primary: \"#00FF7F\",\n  muted: \"#666666\",\n  mutedForeground: \"#999999\",\n};\n\nconst DEFAULT_BRANDING: BadgeBranding = {\n  title: \"100 DAYS\",\n  subtitle: \"OF SHIPPING\",\n};\n\nconst DEFAULT_BACKGROUND: BadgeBackground = {\n  pattern: \"radial\",\n  patternOpacity: 0.08,\n};\n\n// Badge dimensions - square photo area\nconst BADGE_WIDTH = 1080;\nconst BADGE_HEIGHT = 1600;\nconst PHOTO_SIZE = 960;\n\n// Pre-calculate radial line endpoints to avoid hydration mismatches\nconst RADIAL_LINES = Array.from({ length: 24 }).map((_, i) => ({\n  key: `radial-${i}`,\n  x2: Math.round(BADGE_WIDTH / 2 + Math.cos((i * 15 * Math.PI) / 180) * 1400),\n  y2: Math.round(BADGE_HEIGHT / 2 + Math.sin((i * 15 * Math.PI) / 180) * 1400),\n}));\n\n// Pre-calculate octagon points\nconst OCTAGON_POINTS = [200, 400, 600, 800, 1000, 1200].map((size, idx) => ({\n  key: `octagon-${idx}`,\n  points: Array.from({ length: 8 })\n    .map((_, i) => {\n      const angle = (i * 45 - 22.5) * (Math.PI / 180);\n      const x = Math.round(BADGE_WIDTH / 2 + Math.cos(angle) * size);\n      const y = Math.round(BADGE_HEIGHT / 2 + Math.sin(angle) * size);\n      return `${x},${y}`;\n    })\n    .join(\" \"),\n}));\n\n// Pre-calculate hexagon positions\nconst HEXAGON_DATA = Array.from({ length: 12 }).flatMap((_, row) =>\n  Array.from({ length: 10 }).map((_, col) => {\n    const size = 60;\n    const xOffset = row % 2 === 0 ? 0 : size * 0.866;\n    const x = Math.round(col * size * 1.732 + xOffset);\n    const y = Math.round(row * size * 1.5);\n    const points = Array.from({ length: 6 })\n      .map((_, i) => {\n        const angle = (i * 60 - 30) * (Math.PI / 180);\n        return `${Math.round(x + Math.cos(angle) * size)},${Math.round(y + Math.sin(angle) * size)}`;\n      })\n      .join(\" \");\n    return { key: `hex-${row}-${col}`, points };\n  }),\n);\n\n// Pre-calculate wave paths\nconst WAVE_PATHS = Array.from({ length: 20 }).map((_, i) => ({\n  key: `wave-${i}`,\n  d: `M 0 ${i * 80 + 40} Q ${BADGE_WIDTH / 4} ${i * 80} ${BADGE_WIDTH / 2} ${i * 80 + 40} T ${BADGE_WIDTH} ${i * 80 + 40}`,\n}));\n\n// Pre-calculate grid lines\nconst GRID_VERTICAL = Array.from({ length: 22 }).map((_, i) => ({\n  key: `v-${i}`,\n  x: i * 50,\n}));\n\nconst GRID_HORIZONTAL = Array.from({ length: 33 }).map((_, i) => ({\n  key: `h-${i}`,\n  y: i * 50,\n}));\n\n// Pre-calculate dots\nconst DOTS_DATA = Array.from({ length: 22 }).flatMap((_, i) =>\n  Array.from({ length: 33 }).map((_, j) => ({\n    key: `dot-${i}-${j}`,\n    cx: i * 50 + 25,\n    cy: j * 50 + 25,\n  })),\n);\n\n// Pre-calculate circuit pattern\nconst CIRCUIT_VERTICAL = Array.from({ length: 15 }).map((_, i) => ({\n  key: `circuit-v-${i}`,\n  x: (i * 75) % BADGE_WIDTH,\n  nodes: Array.from({ length: 8 }).map((_, j) => ({\n    key: `node-${i}-${j}`,\n    cy: j * 200 + 100,\n  })),\n}));\n\nconst CIRCUIT_HORIZONTAL = Array.from({ length: 10 }).map((_, i) => ({\n  key: `h-circuit-${i}`,\n  y: i * 160 + 80,\n}));\n\n// Pre-calculate gradient stops helper\nconst getGradientStops = (colors: string[]) =>\n  colors.map((color, i) => ({\n    key: `stop-${i}`,\n    offset: `${(i / (colors.length - 1)) * 100}%`,\n    color,\n  }));\n\nfunction BackgroundPattern({\n  type,\n  color,\n  opacity,\n}: {\n  type: BadgePatternType;\n  color: string;\n  opacity: number;\n}) {\n  if (type === \"none\") return null;\n\n  return (\n    <g clipPath=\"url(#bgClip)\" opacity={opacity}>\n      {type === \"radial\" && (\n        <>\n          {/* Radial lines from center */}\n          {RADIAL_LINES.map((line) => (\n            <line\n              key={line.key}\n              x1={BADGE_WIDTH / 2}\n              y1={BADGE_HEIGHT / 2}\n              x2={line.x2}\n              y2={line.y2}\n              stroke={color}\n              strokeWidth=\"2\"\n            />\n          ))}\n          {/* Concentric octagons */}\n          {OCTAGON_POINTS.map((octagon) => (\n            <polygon\n              key={octagon.key}\n              points={octagon.points}\n              fill=\"none\"\n              stroke={color}\n              strokeWidth=\"1.5\"\n            />\n          ))}\n        </>\n      )}\n\n      {type === \"grid\" && (\n        <>\n          {/* Vertical lines */}\n          {GRID_VERTICAL.map((line) => (\n            <line\n              key={line.key}\n              x1={line.x}\n              y1={0}\n              x2={line.x}\n              y2={BADGE_HEIGHT}\n              stroke={color}\n              strokeWidth=\"1\"\n            />\n          ))}\n          {/* Horizontal lines */}\n          {GRID_HORIZONTAL.map((line) => (\n            <line\n              key={line.key}\n              x1={0}\n              y1={line.y}\n              x2={BADGE_WIDTH}\n              y2={line.y}\n              stroke={color}\n              strokeWidth=\"1\"\n            />\n          ))}\n        </>\n      )}\n\n      {type === \"dots\" &&\n        DOTS_DATA.map((dot) => (\n          <circle key={dot.key} cx={dot.cx} cy={dot.cy} r=\"3\" fill={color} />\n        ))}\n\n      {type === \"waves\" &&\n        WAVE_PATHS.map((wave) => (\n          <path\n            key={wave.key}\n            d={wave.d}\n            fill=\"none\"\n            stroke={color}\n            strokeWidth=\"1.5\"\n          />\n        ))}\n\n      {type === \"hexagons\" &&\n        HEXAGON_DATA.map((hex) => (\n          <polygon\n            key={hex.key}\n            points={hex.points}\n            fill=\"none\"\n            stroke={color}\n            strokeWidth=\"1\"\n          />\n        ))}\n\n      {type === \"circuits\" && (\n        <>\n          {/* Circuit-like pattern */}\n          {CIRCUIT_VERTICAL.map((circuit) => (\n            <g key={circuit.key}>\n              <line\n                x1={circuit.x}\n                y1={0}\n                x2={circuit.x}\n                y2={BADGE_HEIGHT}\n                stroke={color}\n                strokeWidth=\"1\"\n                strokeDasharray=\"10,20\"\n              />\n              {circuit.nodes.map((node) => (\n                <circle\n                  key={node.key}\n                  cx={circuit.x}\n                  cy={node.cy}\n                  r=\"4\"\n                  fill={color}\n                />\n              ))}\n            </g>\n          ))}\n          {CIRCUIT_HORIZONTAL.map((line) => (\n            <line\n              key={line.key}\n              x1={0}\n              y1={line.y}\n              x2={BADGE_WIDTH}\n              y2={line.y}\n              stroke={color}\n              strokeWidth=\"1\"\n              strokeDasharray=\"15,25\"\n            />\n          ))}\n        </>\n      )}\n    </g>\n  );\n}\n\nexport const BadgePreview = forwardRef<SVGSVGElement, BadgePreviewProps>(\n  function BadgePreview(\n    {\n      profilePictureUrl,\n      badgeNumber,\n      firstName,\n      lastName = \"\",\n      jobTitle,\n      qrCodeUrl,\n      colors: customColors,\n      branding: customBranding,\n      background: customBackground,\n      className,\n    },\n    ref,\n  ) {\n    const [qrCodeDataUrl, setQrCodeDataUrl] = useState<string>(\"\");\n    const colors = { ...DEFAULT_COLORS, ...customColors };\n    const branding = { ...DEFAULT_BRANDING, ...customBranding };\n    const background = { ...DEFAULT_BACKGROUND, ...customBackground };\n\n    useEffect(() => {\n      const generateQR = async () => {\n        try {\n          const numberOnly = badgeNumber.replace(\"#\", \"\");\n          const url =\n            qrCodeUrl ||\n            (typeof window !== \"undefined\"\n              ? `${window.location.origin}/p/${numberOnly}`\n              : \"\");\n\n          if (!url) return;\n\n          const qrDataUrl = await QRCode.toDataURL(url, {\n            width: 120,\n            margin: 0,\n            color: {\n              dark: colors.foreground,\n              light: colors.background,\n            },\n          });\n          setQrCodeDataUrl(qrDataUrl);\n        } catch (error) {\n          console.error(\"Error generating QR code:\", error);\n        }\n      };\n\n      generateQR();\n    }, [badgeNumber, qrCodeUrl, colors.foreground, colors.background]);\n\n    const getNameFontSize = (name: string) => {\n      if (name.length > 12) return \"52\";\n      if (name.length > 8) return \"64\";\n      return \"72\";\n    };\n\n    const gradientId = \"badgeGradient\";\n    const hasGradient = background.gradient && background.gradient.length >= 2;\n\n    return (\n      <div\n        data-slot=\"badge-preview\"\n        className={cn(\"w-full overflow-hidden\", className)}\n      >\n        <div\n          className=\"relative w-full overflow-hidden\"\n          style={{ aspectRatio: `${BADGE_WIDTH}/${BADGE_HEIGHT}` }}\n        >\n          <svg\n            ref={ref}\n            width={BADGE_WIDTH}\n            height={BADGE_HEIGHT}\n            viewBox={`0 0 ${BADGE_WIDTH} ${BADGE_HEIGHT}`}\n            className=\"absolute top-0 left-0 w-full h-full\"\n            preserveAspectRatio=\"xMidYMid meet\"\n            style={{ overflow: \"hidden\" }}\n            role=\"img\"\n            aria-labelledby=\"badge-title\"\n          >\n            <title id=\"badge-title\">{`${firstName} ${lastName} - ${branding.title} Badge`}</title>\n            <defs>\n              <filter id=\"grayscale\">\n                <feColorMatrix\n                  type=\"matrix\"\n                  values=\"0.33 0.33 0.33 0 0\n                          0.33 0.33 0.33 0 0\n                          0.33 0.33 0.33 0 0\n                          0 0 0 1 0\"\n                />\n              </filter>\n\n              <clipPath id=\"photoClip\">\n                <rect x=\"60\" y=\"60\" width={PHOTO_SIZE} height={PHOTO_SIZE} />\n              </clipPath>\n\n              <clipPath id=\"bgClip\">\n                <rect width={BADGE_WIDTH} height={BADGE_HEIGHT} />\n              </clipPath>\n\n              {/* Gradient definition */}\n              {hasGradient && (\n                <linearGradient\n                  id={gradientId}\n                  x1=\"0%\"\n                  y1=\"0%\"\n                  x2=\"100%\"\n                  y2=\"100%\"\n                  gradientTransform={`rotate(${background.gradientAngle || 135}, 0.5, 0.5)`}\n                >\n                  {getGradientStops(background.gradient || []).map((stop) => (\n                    <stop\n                      key={stop.key}\n                      offset={stop.offset}\n                      stopColor={stop.color}\n                    />\n                  ))}\n                </linearGradient>\n              )}\n            </defs>\n\n            {/* Background - solid color or gradient */}\n            <rect\n              width={BADGE_WIDTH}\n              height={BADGE_HEIGHT}\n              fill={hasGradient ? `url(#${gradientId})` : colors.background}\n            />\n\n            {/* Custom background image */}\n            {background.imageUrl && (\n              <image\n                href={background.imageUrl}\n                x=\"0\"\n                y=\"0\"\n                width={BADGE_WIDTH}\n                height={BADGE_HEIGHT}\n                preserveAspectRatio=\"xMidYMid slice\"\n                opacity={background.imageOpacity ?? 0.3}\n              />\n            )}\n\n            {/* Background pattern */}\n            <BackgroundPattern\n              type={background.pattern || \"radial\"}\n              color={background.patternColor || colors.foreground}\n              opacity={background.patternOpacity ?? 0.08}\n            />\n\n            {/* Photo area background */}\n            <rect\n              x=\"60\"\n              y=\"60\"\n              width={PHOTO_SIZE}\n              height={PHOTO_SIZE}\n              fill=\"#E5E5E5\"\n            />\n\n            {/* Profile picture */}\n            {profilePictureUrl && (\n              <image\n                href={profilePictureUrl}\n                x=\"60\"\n                y=\"60\"\n                width={PHOTO_SIZE}\n                height={PHOTO_SIZE}\n                filter=\"url(#grayscale)\"\n                preserveAspectRatio=\"xMidYMid slice\"\n                clipPath=\"url(#photoClip)\"\n              />\n            )}\n\n            {/* L-Bracket frame element */}\n            <path\n              d=\"M60 1020 L60 1260 L200 1260\"\n              fill=\"none\"\n              stroke={colors.foreground}\n              strokeWidth=\"16\"\n            />\n\n            {/* Badge Number */}\n            <text\n              x=\"100\"\n              y=\"1080\"\n              fill={colors.muted}\n              fontSize=\"28\"\n              fontFamily=\"'Geist Mono', monospace\"\n              letterSpacing=\"0.15em\"\n            >\n              {badgeNumber}\n            </text>\n\n            {/* First Name */}\n            <text\n              x=\"100\"\n              y=\"1160\"\n              fill={colors.foreground}\n              fontSize={getNameFontSize(firstName)}\n              fontWeight=\"700\"\n              fontFamily=\"'Geist', 'Geist Mono', monospace\"\n              letterSpacing=\"-0.02em\"\n            >\n              {firstName.toUpperCase()}\n            </text>\n\n            {/* Last Name */}\n            {lastName && (\n              <text\n                x=\"100\"\n                y=\"1240\"\n                fill={colors.foreground}\n                fontSize={getNameFontSize(lastName)}\n                fontWeight=\"700\"\n                fontFamily=\"'Geist', 'Geist Mono', monospace\"\n                letterSpacing=\"-0.02em\"\n              >\n                {lastName.toUpperCase()}\n              </text>\n            )}\n\n            {/* Role */}\n            <text\n              x=\"100\"\n              y={lastName ? \"1300\" : \"1220\"}\n              fill={colors.muted}\n              fontSize=\"24\"\n              fontFamily=\"'Geist Mono', monospace\"\n              letterSpacing=\"0.1em\"\n            >\n              → {jobTitle.toUpperCase()}\n            </text>\n\n            {/* Organization branding - right side */}\n            {(branding.organizationName || branding.logo) && (\n              <g transform=\"translate(1020, 1060)\">\n                {branding.logo}\n                {branding.organizationName && (\n                  <>\n                    <text\n                      x=\"0\"\n                      y=\"60\"\n                      fill={colors.muted}\n                      fontSize=\"20\"\n                      fontFamily=\"'Geist Mono', monospace\"\n                      letterSpacing=\"0.1em\"\n                      textAnchor=\"end\"\n                    >\n                      {branding.organizationName.toUpperCase()}\n                    </text>\n                    {branding.organizationSubtitle && (\n                      <text\n                        x=\"0\"\n                        y=\"88\"\n                        fill={colors.foreground}\n                        fontSize=\"20\"\n                        fontWeight=\"700\"\n                        fontFamily=\"'Geist Mono', monospace\"\n                        letterSpacing=\"0.1em\"\n                        textAnchor=\"end\"\n                      >\n                        {branding.organizationSubtitle.toUpperCase()}\n                      </text>\n                    )}\n                  </>\n                )}\n              </g>\n            )}\n\n            {/* Bottom divider line */}\n            <line\n              x1=\"60\"\n              y1=\"1360\"\n              x2=\"1020\"\n              y2=\"1360\"\n              stroke={colors.foreground}\n              strokeWidth=\"2\"\n            />\n\n            {/* Brand title */}\n            <text\n              x=\"100\"\n              y=\"1460\"\n              fill={colors.foreground}\n              fontSize=\"56\"\n              fontWeight=\"700\"\n              fontFamily=\"'Geist', 'Geist Mono', monospace\"\n              letterSpacing=\"-0.02em\"\n            >\n              {branding.title}\n            </text>\n\n            {/* Accent square next to brand */}\n            <rect\n              x=\"460\"\n              y=\"1418\"\n              width=\"48\"\n              height=\"48\"\n              fill={colors.primary}\n            />\n\n            {/* Brand subtitle */}\n            <text\n              x=\"100\"\n              y=\"1520\"\n              fill={colors.muted}\n              fontSize=\"20\"\n              fontFamily=\"'Geist Mono', monospace\"\n              letterSpacing=\"0.2em\"\n            >\n              {branding.subtitle}\n            </text>\n\n            {/* QR Code */}\n            {qrCodeDataUrl && (\n              <image\n                href={qrCodeDataUrl}\n                x=\"900\"\n                y=\"1420\"\n                width=\"120\"\n                height=\"120\"\n              />\n            )}\n\n            {/* Corner accents - top left */}\n            <rect x=\"60\" y=\"60\" width=\"8\" height=\"40\" fill={colors.primary} />\n            <rect x=\"60\" y=\"60\" width=\"40\" height=\"8\" fill={colors.primary} />\n\n            {/* Corner accents - top right */}\n            <rect x=\"1012\" y=\"60\" width=\"8\" height=\"40\" fill={colors.primary} />\n            <rect x=\"980\" y=\"60\" width=\"40\" height=\"8\" fill={colors.primary} />\n\n            {/* Corner accents - bottom left of photo */}\n            <rect x=\"60\" y=\"980\" width=\"8\" height=\"40\" fill={colors.primary} />\n            <rect x=\"60\" y=\"1012\" width=\"40\" height=\"8\" fill={colors.primary} />\n\n            {/* Corner accents - bottom right of photo */}\n            <rect\n              x=\"1012\"\n              y=\"980\"\n              width=\"8\"\n              height=\"40\"\n              fill={colors.primary}\n            />\n            <rect\n              x=\"980\"\n              y=\"1012\"\n              width=\"40\"\n              height=\"8\"\n              fill={colors.primary}\n            />\n          </svg>\n        </div>\n      </div>\n    );\n  },\n);\n",
      "type": "registry:component"
    }
  ],
  "docs": "A 3D badge component with tilt effects powered by Atropos. Supports custom colors, branding, and AI-generated avatars. Perfect for conference badges, member cards, and achievement displays.",
  "categories": [
    "badges"
  ],
  "type": "registry:block"
}