{
	"$schema": "https://ui.shadcn.com/schema/registry-item.json",
	"name": "ProfileCard-JS-CSS",
	"title": "ProfileCard",
	"description": "Animated profile card glare with 3D hover effect.",
	"type": "registry:component",
	"files": [
		{
			"type": "registry:file",
			"path": "ProfileCard.css",
			"target": "@components/ProfileCard.css",
			"content": ":root {\n  --pointer-x: 50%;\n  --pointer-y: 50%;\n  --pointer-from-center: 0;\n  --pointer-from-top: 0.5;\n  --pointer-from-left: 0.5;\n  --card-opacity: 0;\n  --rotate-x: 0deg;\n  --rotate-y: 0deg;\n  --background-x: 50%;\n  --background-y: 50%;\n  --grain: none;\n  --icon: none;\n  --behind-gradient: none;\n  --behind-glow-color: rgba(125, 190, 255, 0.67);\n  --behind-glow-size: 25%;\n  --inner-gradient: none;\n  --sunpillar-1: hsl(2, 100%, 73%);\n  --sunpillar-2: hsl(53, 100%, 69%);\n  --sunpillar-3: hsl(93, 100%, 69%);\n  --sunpillar-4: hsl(176, 100%, 76%);\n  --sunpillar-5: hsl(228, 100%, 74%);\n  --sunpillar-6: hsl(283, 100%, 73%);\n  --sunpillar-clr-1: var(--sunpillar-1);\n  --sunpillar-clr-2: var(--sunpillar-2);\n  --sunpillar-clr-3: var(--sunpillar-3);\n  --sunpillar-clr-4: var(--sunpillar-4);\n  --sunpillar-clr-5: var(--sunpillar-5);\n  --sunpillar-clr-6: var(--sunpillar-6);\n  --card-radius: 30px;\n}\n\n.pc-card-wrapper {\n  perspective: 500px;\n  transform: translate3d(0, 0, 0.1px);\n  position: relative;\n  touch-action: none;\n}\n\n.pc-behind {\n  position: absolute;\n  inset: 0;\n  z-index: 0;\n  pointer-events: none;\n  background: radial-gradient(\n    circle at var(--pointer-x) var(--pointer-y),\n    var(--behind-glow-color) 0%,\n    transparent var(--behind-glow-size)\n  );\n  filter: blur(50px) saturate(1.1);\n  opacity: calc(0.8 * var(--card-opacity));\n  transition: opacity 200ms ease;\n}\n\n.pc-card-wrapper:hover,\n.pc-card-wrapper.active {\n  --card-opacity: 1;\n}\n\n.pc-card {\n  height: 80svh;\n  max-height: 540px;\n  display: grid;\n  aspect-ratio: 0.718;\n  border-radius: var(--card-radius);\n  position: relative;\n  background-blend-mode: color-dodge, normal, normal, normal;\n  animation: glow-bg 12s linear infinite;\n  box-shadow: rgba(0, 0, 0, 0.8) calc((var(--pointer-from-left) * 10px) - 3px)\n    calc((var(--pointer-from-top) * 20px) - 6px) 20px -5px;\n  transition: transform 1s ease;\n  transform: translateZ(0) rotateX(0deg) rotateY(0deg);\n  background: rgba(0, 0, 0, 0.9);\n  backface-visibility: hidden;\n  overflow: hidden;\n}\n\n.pc-card:hover,\n.pc-card.active {\n  transition: none;\n  transform: translateZ(0) rotateX(var(--rotate-y)) rotateY(var(--rotate-x));\n}\n\n.pc-card-shell.entering .pc-card {\n  transition: transform 180ms ease-out;\n}\n\n.pc-card-shell {\n  position: relative;\n  z-index: 1;\n}\n\n.pc-card * {\n  display: grid;\n  grid-area: 1/-1;\n  border-radius: var(--card-radius);\n  pointer-events: none;\n}\n\n.pc-inside {\n  inset: 0;\n  position: absolute;\n  background-image: var(--inner-gradient);\n  background-color: rgba(0, 0, 0, 0.9);\n  transform: none;\n}\n\n.pc-shine {\n  mask-image: var(--icon);\n  mask-mode: luminance;\n  mask-repeat: repeat;\n  mask-size: 150%;\n  mask-position: top calc(200% - (var(--background-y) * 5)) left calc(100% - var(--background-x));\n  transition: filter 0.8s ease;\n  filter: brightness(0.66) contrast(1.33) saturate(0.33) opacity(0.5);\n  animation: holo-bg 18s linear infinite;\n  animation-play-state: running;\n  mix-blend-mode: color-dodge;\n}\n\n.pc-shine,\n.pc-shine::after {\n  --space: 5%;\n  --angle: -45deg;\n  transform: translate3d(0, 0, 1px);\n  overflow: hidden;\n  z-index: 3;\n  background: transparent;\n  background-size: cover;\n  background-position: center;\n  background-image:\n    repeating-linear-gradient(\n      0deg,\n      var(--sunpillar-clr-1) calc(var(--space) * 1),\n      var(--sunpillar-clr-2) calc(var(--space) * 2),\n      var(--sunpillar-clr-3) calc(var(--space) * 3),\n      var(--sunpillar-clr-4) calc(var(--space) * 4),\n      var(--sunpillar-clr-5) calc(var(--space) * 5),\n      var(--sunpillar-clr-6) calc(var(--space) * 6),\n      var(--sunpillar-clr-1) calc(var(--space) * 7)\n    ),\n    repeating-linear-gradient(\n      var(--angle),\n      #0e152e 0%,\n      hsl(180, 10%, 60%) 3.8%,\n      hsl(180, 29%, 66%) 4.5%,\n      hsl(180, 10%, 60%) 5.2%,\n      #0e152e 10%,\n      #0e152e 12%\n    ),\n    radial-gradient(\n      farthest-corner circle at var(--pointer-x) var(--pointer-y),\n      hsla(0, 0%, 0%, 0.1) 12%,\n      hsla(0, 0%, 0%, 0.15) 20%,\n      hsla(0, 0%, 0%, 0.25) 120%\n    );\n  background-position:\n    0 var(--background-y),\n    var(--background-x) var(--background-y),\n    center;\n  background-blend-mode: color, hard-light;\n  background-size:\n    500% 500%,\n    300% 300%,\n    200% 200%;\n  background-repeat: repeat;\n}\n\n.pc-shine::before,\n.pc-shine::after {\n  content: '';\n  background-position: center;\n  background-size: cover;\n  grid-area: 1/1;\n  opacity: 0;\n  transition: opacity 0.8s ease;\n}\n\n.pc-card:hover .pc-shine,\n.pc-card.active .pc-shine {\n  filter: brightness(0.85) contrast(1.5) saturate(0.5);\n  animation-play-state: paused;\n}\n\n.pc-card:hover .pc-shine::before,\n.pc-card.active .pc-shine::before,\n.pc-card:hover .pc-shine::after,\n.pc-card.active .pc-shine::after {\n  opacity: 1;\n}\n\n.pc-shine::before {\n  background-image:\n    linear-gradient(\n      45deg,\n      var(--sunpillar-4),\n      var(--sunpillar-5),\n      var(--sunpillar-6),\n      var(--sunpillar-1),\n      var(--sunpillar-2),\n      var(--sunpillar-3)\n    ),\n    radial-gradient(circle at var(--pointer-x) var(--pointer-y), hsl(0, 0%, 70%) 0%, hsla(0, 0%, 30%, 0.2) 90%),\n    var(--grain);\n  background-size:\n    250% 250%,\n    100% 100%,\n    220px 220px;\n  background-position:\n    var(--pointer-x) var(--pointer-y),\n    center,\n    calc(var(--pointer-x) * 0.01) calc(var(--pointer-y) * 0.01);\n  background-blend-mode: color-dodge;\n  filter: brightness(calc(2 - var(--pointer-from-center))) contrast(calc(var(--pointer-from-center) + 2))\n    saturate(calc(0.5 + var(--pointer-from-center)));\n  mix-blend-mode: luminosity;\n}\n\n.pc-shine::after {\n  background-position:\n    0 var(--background-y),\n    calc(var(--background-x) * 0.4) calc(var(--background-y) * 0.5),\n    center;\n  background-size:\n    200% 300%,\n    700% 700%,\n    100% 100%;\n  mix-blend-mode: difference;\n  filter: brightness(0.8) contrast(1.5);\n}\n\n.pc-glare {\n  transform: translate3d(0, 0, 1.1px);\n  overflow: hidden;\n  background-image: radial-gradient(\n    farthest-corner circle at var(--pointer-x) var(--pointer-y),\n    hsl(248, 25%, 80%) 12%,\n    hsla(207, 40%, 30%, 0.8) 90%\n  );\n  mix-blend-mode: overlay;\n  filter: brightness(0.8) contrast(1.2);\n  z-index: 4;\n}\n\n.pc-avatar-content {\n  mix-blend-mode: luminosity;\n  overflow: visible;\n  transform: translateZ(2);\n  backface-visibility: hidden;\n}\n\n.pc-avatar-content .avatar {\n  width: 100%;\n  position: absolute;\n  left: 50%;\n  transform-origin: 50% 100%;\n  transform: translateX(calc(-50% + (var(--pointer-from-left) - 0.5) * 6px)) translateZ(0)\n    scaleY(calc(1 + (var(--pointer-from-top) - 0.5) * 0.02)) scaleX(calc(1 + (var(--pointer-from-left) - 0.5) * 0.01));\n  bottom: -1px;\n  backface-visibility: hidden;\n  will-change: transform;\n  transition: transform 120ms ease-out;\n}\n\n.pc-avatar-content::before {\n  content: '';\n  position: absolute;\n  inset: 0;\n  z-index: 1;\n  backdrop-filter: none;\n  pointer-events: none;\n}\n\n.pc-user-info {\n  position: absolute;\n  --ui-inset: 20px;\n  --ui-radius-bias: 6px;\n  bottom: var(--ui-inset);\n  left: var(--ui-inset);\n  right: var(--ui-inset);\n  z-index: 2;\n  display: flex;\n  align-items: center;\n  justify-content: space-between;\n  background: rgba(255, 255, 255, 0.1);\n  backdrop-filter: blur(30px);\n  border: 1px solid rgba(255, 255, 255, 0.1);\n  border-radius: calc(max(0px, var(--card-radius) - var(--ui-inset) + var(--ui-radius-bias)));\n  padding: 12px 14px;\n  pointer-events: auto;\n}\n\n.pc-user-details {\n  display: flex;\n  align-items: center;\n  gap: 12px;\n}\n\n.pc-mini-avatar {\n  width: 48px;\n  height: 48px;\n  border-radius: 50%;\n  overflow: hidden;\n  border: 1px solid rgba(255, 255, 255, 0.1);\n  flex-shrink: 0;\n}\n\n.pc-mini-avatar img {\n  width: 100%;\n  height: 100%;\n  object-fit: cover;\n  border-radius: 50%;\n}\n\n.pc-user-text {\n  display: flex;\n  align-items: flex-start;\n  flex-direction: column;\n  gap: 6px;\n}\n\n.pc-handle {\n  font-size: 14px;\n  font-weight: 500;\n  color: rgba(255, 255, 255, 0.9);\n  line-height: 1;\n}\n\n.pc-status {\n  font-size: 14px;\n  color: rgba(255, 255, 255, 0.7);\n  line-height: 1;\n}\n\n.pc-contact-btn {\n  border: 1px solid rgba(255, 255, 255, 0.1);\n  border-radius: 8px;\n  padding: 12px 16px;\n  font-size: 12px;\n  font-weight: 600;\n  color: rgba(255, 255, 255, 0.9);\n  cursor: pointer;\n  transition: all 0.2s ease;\n  backdrop-filter: blur(10px);\n}\n\n.pc-contact-btn:hover {\n  border-color: rgba(255, 255, 255, 0.4);\n  transform: translateY(-1px);\n  transition: all 0.2s ease;\n}\n\n.pc-content:not(.pc-avatar-content) {\n  max-height: 100%;\n  overflow: hidden;\n  text-align: center;\n  position: relative;\n  transform: translate3d(\n    calc(var(--pointer-from-left) * -6px + 3px),\n    calc(var(--pointer-from-top) * -6px + 3px),\n    0.1px\n  );\n  z-index: 5;\n  mix-blend-mode: luminosity;\n}\n\n.pc-details {\n  width: 100%;\n  position: absolute;\n  top: 3em;\n  display: flex;\n  flex-direction: column;\n}\n\n.pc-details h3 {\n  font-weight: 600;\n  margin: 0;\n  font-size: min(5svh, 3em);\n  margin: 0;\n  background-image: linear-gradient(to bottom, #fff, #6f6fbe);\n  background-size: 1em 1.5em;\n  -webkit-text-fill-color: transparent;\n  background-clip: text;\n  -webkit-background-clip: text;\n}\n\n.pc-details p {\n  font-weight: 600;\n  position: relative;\n  top: -12px;\n  white-space: nowrap;\n  font-size: 16px;\n  margin: 0 auto;\n  width: min-content;\n  background-image: linear-gradient(to bottom, #fff, #4a4ac0);\n  background-size: 1em 1.5em;\n  -webkit-text-fill-color: transparent;\n  background-clip: text;\n  -webkit-background-clip: text;\n}\n\n@keyframes glow-bg {\n  0% {\n    --bgrotate: 0deg;\n  }\n\n  100% {\n    --bgrotate: 360deg;\n  }\n}\n\n@keyframes holo-bg {\n  0% {\n    background-position:\n      0 var(--background-y),\n      0 0,\n      center;\n  }\n\n  100% {\n    background-position:\n      0 var(--background-y),\n      90% 90%,\n      center;\n  }\n}\n\n@media (max-width: 768px) {\n  .pc-card {\n    height: 70svh;\n    max-height: 450px;\n  }\n\n  .pc-details {\n    top: 2em;\n  }\n\n  .pc-details h3 {\n    font-size: min(4svh, 2.5em);\n  }\n\n  .pc-details p {\n    font-size: 14px;\n  }\n\n  .pc-user-info {\n    --ui-inset: 15px;\n    padding: 10px 12px;\n  }\n\n  .pc-mini-avatar {\n    width: 28px;\n    height: 28px;\n  }\n\n  .pc-user-details {\n    gap: 10px;\n  }\n\n  .pc-handle {\n    font-size: 13px;\n  }\n\n  .pc-status {\n    font-size: 10px;\n  }\n\n  .pc-contact-btn {\n    padding: 6px 12px;\n    font-size: 11px;\n  }\n}\n\n@media (max-width: 480px) {\n  .pc-card {\n    height: 60svh;\n    max-height: 380px;\n  }\n\n  .pc-details {\n    top: 1.5em;\n  }\n\n  .pc-details h3 {\n    font-size: min(3.5svh, 2em);\n  }\n\n  .pc-details p {\n    font-size: 12px;\n    top: -8px;\n  }\n\n  .pc-user-info {\n    --ui-inset: 12px;\n    padding: 8px 10px;\n  }\n\n  .pc-mini-avatar {\n    width: 24px;\n    height: 24px;\n  }\n\n  .pc-user-details {\n    gap: 8px;\n  }\n\n  .pc-handle {\n    font-size: 12px;\n  }\n\n  .pc-status {\n    font-size: 9px;\n  }\n\n  .pc-contact-btn {\n    padding: 5px 10px;\n    font-size: 10px;\n    border-radius: 50px;\n  }\n}\n\n@media (max-width: 320px) {\n  .pc-card {\n    height: 55svh;\n    max-height: 320px;\n  }\n\n  .pc-details h3 {\n    font-size: min(3svh, 1.5em);\n  }\n\n  .pc-details p {\n    font-size: 11px;\n  }\n\n  .pc-user-info {\n    padding: 6px 8px;\n  }\n\n  .pc-mini-avatar {\n    width: 20px;\n    height: 20px;\n  }\n\n  .pc-user-details {\n    gap: 6px;\n  }\n\n  .pc-handle {\n    font-size: 11px;\n  }\n\n  .pc-status {\n    font-size: 8px;\n  }\n\n  .pc-contact-btn {\n    padding: 4px 8px;\n    font-size: 9px;\n    border-radius: 50px;\n  }\n}\n"
		},
		{
			"type": "registry:component",
			"path": "ProfileCard.jsx",
			"content": "import React, { useEffect, useRef, useCallback, useMemo } from 'react';\nimport './ProfileCard.css';\n\nconst DEFAULT_INNER_GRADIENT = 'linear-gradient(145deg,#60496e8c 0%,#71C4FF44 100%)';\n\nconst ANIMATION_CONFIG = {\n  INITIAL_DURATION: 1200,\n  INITIAL_X_OFFSET: 70,\n  INITIAL_Y_OFFSET: 60,\n  DEVICE_BETA_OFFSET: 20,\n  ENTER_TRANSITION_MS: 180\n};\n\nconst clamp = (v, min = 0, max = 100) => Math.min(Math.max(v, min), max);\nconst round = (v, precision = 3) => parseFloat(v.toFixed(precision));\nconst adjust = (v, fMin, fMax, tMin, tMax) => round(tMin + ((tMax - tMin) * (v - fMin)) / (fMax - fMin));\n\nconst ProfileCardComponent = ({\n  avatarUrl = '<Placeholder for avatar URL>',\n  iconUrl = '<Placeholder for icon URL>',\n  grainUrl = '<Placeholder for grain URL>',\n  innerGradient,\n  behindGlowEnabled = true,\n  behindGlowColor,\n  behindGlowSize,\n  className = '',\n  enableTilt = true,\n  enableMobileTilt = false,\n  mobileTiltSensitivity = 5,\n  miniAvatarUrl,\n  name = 'Javi A. Torres',\n  title = 'Software Engineer',\n  handle = 'javicodes',\n  status = 'Online',\n  contactText = 'Contact',\n  showUserInfo = true,\n  onContactClick\n}) => {\n  const wrapRef = useRef(null);\n  const shellRef = useRef(null);\n\n  const enterTimerRef = useRef(null);\n  const leaveRafRef = useRef(null);\n\n  const tiltEngine = useMemo(() => {\n    if (!enableTilt) return null;\n\n    let rafId = null;\n    let running = false;\n    let lastTs = 0;\n\n    let currentX = 0;\n    let currentY = 0;\n    let targetX = 0;\n    let targetY = 0;\n\n    const DEFAULT_TAU = 0.14;\n    const INITIAL_TAU = 0.6;\n    let initialUntil = 0;\n\n    const setVarsFromXY = (x, y) => {\n      const shell = shellRef.current;\n      const wrap = wrapRef.current;\n      if (!shell || !wrap) return;\n\n      const width = shell.clientWidth || 1;\n      const height = shell.clientHeight || 1;\n\n      const percentX = clamp((100 / width) * x);\n      const percentY = clamp((100 / height) * y);\n\n      const centerX = percentX - 50;\n      const centerY = percentY - 50;\n\n      const properties = {\n        '--pointer-x': `${percentX}%`,\n        '--pointer-y': `${percentY}%`,\n        '--background-x': `${adjust(percentX, 0, 100, 35, 65)}%`,\n        '--background-y': `${adjust(percentY, 0, 100, 35, 65)}%`,\n        '--pointer-from-center': `${clamp(Math.hypot(percentY - 50, percentX - 50) / 50, 0, 1)}`,\n        '--pointer-from-top': `${percentY / 100}`,\n        '--pointer-from-left': `${percentX / 100}`,\n        '--rotate-x': `${round(-(centerX / 5))}deg`,\n        '--rotate-y': `${round(centerY / 4)}deg`\n      };\n\n      for (const [k, v] of Object.entries(properties)) wrap.style.setProperty(k, v);\n    };\n\n    const step = ts => {\n      if (!running) return;\n      if (lastTs === 0) lastTs = ts;\n      const dt = (ts - lastTs) / 1000;\n      lastTs = ts;\n\n      const tau = ts < initialUntil ? INITIAL_TAU : DEFAULT_TAU;\n      const k = 1 - Math.exp(-dt / tau);\n\n      currentX += (targetX - currentX) * k;\n      currentY += (targetY - currentY) * k;\n\n      setVarsFromXY(currentX, currentY);\n\n      const stillFar = Math.abs(targetX - currentX) > 0.05 || Math.abs(targetY - currentY) > 0.05;\n\n      if (stillFar || document.hasFocus()) {\n        rafId = requestAnimationFrame(step);\n      } else {\n        running = false;\n        lastTs = 0;\n        if (rafId) {\n          cancelAnimationFrame(rafId);\n          rafId = null;\n        }\n      }\n    };\n\n    const start = () => {\n      if (running) return;\n      running = true;\n      lastTs = 0;\n      rafId = requestAnimationFrame(step);\n    };\n\n    return {\n      setImmediate(x, y) {\n        currentX = x;\n        currentY = y;\n        setVarsFromXY(currentX, currentY);\n      },\n      setTarget(x, y) {\n        targetX = x;\n        targetY = y;\n        start();\n      },\n      toCenter() {\n        const shell = shellRef.current;\n        if (!shell) return;\n        this.setTarget(shell.clientWidth / 2, shell.clientHeight / 2);\n      },\n      beginInitial(durationMs) {\n        initialUntil = performance.now() + durationMs;\n        start();\n      },\n      getCurrent() {\n        return { x: currentX, y: currentY, tx: targetX, ty: targetY };\n      },\n      cancel() {\n        if (rafId) cancelAnimationFrame(rafId);\n        rafId = null;\n        running = false;\n        lastTs = 0;\n      }\n    };\n  }, [enableTilt]);\n\n  const getOffsets = (evt, el) => {\n    const rect = el.getBoundingClientRect();\n    return { x: evt.clientX - rect.left, y: evt.clientY - rect.top };\n  };\n\n  const handlePointerMove = useCallback(\n    event => {\n      const shell = shellRef.current;\n      if (!shell || !tiltEngine) return;\n      const { x, y } = getOffsets(event, shell);\n      tiltEngine.setTarget(x, y);\n    },\n    [tiltEngine]\n  );\n\n  const handlePointerEnter = useCallback(\n    event => {\n      const shell = shellRef.current;\n      if (!shell || !tiltEngine) return;\n\n      shell.classList.add('active');\n      shell.classList.add('entering');\n      if (enterTimerRef.current) window.clearTimeout(enterTimerRef.current);\n      enterTimerRef.current = window.setTimeout(() => {\n        shell.classList.remove('entering');\n      }, ANIMATION_CONFIG.ENTER_TRANSITION_MS);\n\n      const { x, y } = getOffsets(event, shell);\n      tiltEngine.setTarget(x, y);\n    },\n    [tiltEngine]\n  );\n\n  const handlePointerLeave = useCallback(() => {\n    const shell = shellRef.current;\n    if (!shell || !tiltEngine) return;\n\n    tiltEngine.toCenter();\n\n    const checkSettle = () => {\n      const { x, y, tx, ty } = tiltEngine.getCurrent();\n      const settled = Math.hypot(tx - x, ty - y) < 0.6;\n      if (settled) {\n        shell.classList.remove('active');\n        leaveRafRef.current = null;\n      } else {\n        leaveRafRef.current = requestAnimationFrame(checkSettle);\n      }\n    };\n    if (leaveRafRef.current) cancelAnimationFrame(leaveRafRef.current);\n    leaveRafRef.current = requestAnimationFrame(checkSettle);\n  }, [tiltEngine]);\n\n  const handleDeviceOrientation = useCallback(\n    event => {\n      const shell = shellRef.current;\n      if (!shell || !tiltEngine) return;\n\n      const { beta, gamma } = event;\n      if (beta == null || gamma == null) return;\n\n      const centerX = shell.clientWidth / 2;\n      const centerY = shell.clientHeight / 2;\n      const x = clamp(centerX + gamma * mobileTiltSensitivity, 0, shell.clientWidth);\n      const y = clamp(\n        centerY + (beta - ANIMATION_CONFIG.DEVICE_BETA_OFFSET) * mobileTiltSensitivity,\n        0,\n        shell.clientHeight\n      );\n\n      tiltEngine.setTarget(x, y);\n    },\n    [tiltEngine, mobileTiltSensitivity]\n  );\n\n  useEffect(() => {\n    if (!enableTilt || !tiltEngine) return;\n\n    const shell = shellRef.current;\n    if (!shell) return;\n\n    const pointerMoveHandler = handlePointerMove;\n    const pointerEnterHandler = handlePointerEnter;\n    const pointerLeaveHandler = handlePointerLeave;\n    const deviceOrientationHandler = handleDeviceOrientation;\n\n    shell.addEventListener('pointerenter', pointerEnterHandler);\n    shell.addEventListener('pointermove', pointerMoveHandler);\n    shell.addEventListener('pointerleave', pointerLeaveHandler);\n\n    const handleClick = () => {\n      if (!enableMobileTilt || location.protocol !== 'https:') return;\n      const anyMotion = window.DeviceMotionEvent;\n      if (anyMotion && typeof anyMotion.requestPermission === 'function') {\n        anyMotion\n          .requestPermission()\n          .then(state => {\n            if (state === 'granted') {\n              window.addEventListener('deviceorientation', deviceOrientationHandler);\n            }\n          })\n          .catch(console.error);\n      } else {\n        window.addEventListener('deviceorientation', deviceOrientationHandler);\n      }\n    };\n    shell.addEventListener('click', handleClick);\n\n    const initialX = (shell.clientWidth || 0) - ANIMATION_CONFIG.INITIAL_X_OFFSET;\n    const initialY = ANIMATION_CONFIG.INITIAL_Y_OFFSET;\n    tiltEngine.setImmediate(initialX, initialY);\n    tiltEngine.toCenter();\n    tiltEngine.beginInitial(ANIMATION_CONFIG.INITIAL_DURATION);\n\n    return () => {\n      shell.removeEventListener('pointerenter', pointerEnterHandler);\n      shell.removeEventListener('pointermove', pointerMoveHandler);\n      shell.removeEventListener('pointerleave', pointerLeaveHandler);\n      shell.removeEventListener('click', handleClick);\n      window.removeEventListener('deviceorientation', deviceOrientationHandler);\n      if (enterTimerRef.current) window.clearTimeout(enterTimerRef.current);\n      if (leaveRafRef.current) cancelAnimationFrame(leaveRafRef.current);\n      tiltEngine.cancel();\n      shell.classList.remove('entering');\n    };\n  }, [\n    enableTilt,\n    enableMobileTilt,\n    tiltEngine,\n    handlePointerMove,\n    handlePointerEnter,\n    handlePointerLeave,\n    handleDeviceOrientation\n  ]);\n\n  const cardStyle = useMemo(\n    () => ({\n      '--icon': iconUrl ? `url(${iconUrl})` : 'none',\n      '--grain': grainUrl ? `url(${grainUrl})` : 'none',\n      '--inner-gradient': innerGradient ?? DEFAULT_INNER_GRADIENT,\n      '--behind-glow-color': behindGlowColor ?? 'rgba(125, 190, 255, 0.67)',\n      '--behind-glow-size': behindGlowSize ?? '50%'\n    }),\n    [iconUrl, grainUrl, innerGradient, behindGlowColor, behindGlowSize]\n  );\n\n  const handleContactClick = useCallback(() => {\n    onContactClick?.();\n  }, [onContactClick]);\n\n  return (\n    <div ref={wrapRef} className={`pc-card-wrapper ${className}`.trim()} style={cardStyle}>\n      {behindGlowEnabled && <div className=\"pc-behind\" />}\n      <div ref={shellRef} className=\"pc-card-shell\">\n        <section className=\"pc-card\">\n          <div className=\"pc-inside\">\n            <div className=\"pc-shine\" />\n            <div className=\"pc-glare\" />\n            <div className=\"pc-content pc-avatar-content\">\n              <img\n                className=\"avatar\"\n                src={avatarUrl}\n                alt={`${name || 'User'} avatar`}\n                loading=\"lazy\"\n                onError={e => {\n                  const t = e.target;\n                  t.style.display = 'none';\n                }}\n              />\n              {showUserInfo && (\n                <div className=\"pc-user-info\">\n                  <div className=\"pc-user-details\">\n                    <div className=\"pc-mini-avatar\">\n                      <img\n                        src={miniAvatarUrl || avatarUrl}\n                        alt={`${name || 'User'} mini avatar`}\n                        loading=\"lazy\"\n                        onError={e => {\n                          const t = e.target;\n                          t.style.opacity = '0.5';\n                          t.src = avatarUrl;\n                        }}\n                      />\n                    </div>\n                    <div className=\"pc-user-text\">\n                      <div className=\"pc-handle\">@{handle}</div>\n                      <div className=\"pc-status\">{status}</div>\n                    </div>\n                  </div>\n                  <button\n                    className=\"pc-contact-btn\"\n                    onClick={handleContactClick}\n                    style={{ pointerEvents: 'auto' }}\n                    type=\"button\"\n                    aria-label={`Contact ${name || 'user'}`}\n                  >\n                    {contactText}\n                  </button>\n                </div>\n              )}\n            </div>\n            <div className=\"pc-content\">\n              <div className=\"pc-details\">\n                <h3>{name}</h3>\n                <p>{title}</p>\n              </div>\n            </div>\n          </div>\n        </section>\n      </div>\n    </div>\n  );\n};\n\nconst ProfileCard = React.memo(ProfileCardComponent);\nexport default ProfileCard;\n"
		}
	],
	"registryDependencies": [],
	"dependencies": []
}