Files
vue-bits/public/r/ProfileCard.json
David Haz e621971723 jsrepo v3
2025-12-15 23:50:24 +02:00

1 line
22 KiB
JSON

{"name":"ProfileCard","title":"ProfileCard","description":"Animated profile card glare with 3D hover effect.","type":"registry:component","add":"when-added","files":[{"type":"registry:component","role":"file","content":"<template>\n <div ref=\"wrapRef\" :class=\"`pc-card-wrapper ${className}`.trim()\" :style=\"cardStyle\">\n <section ref=\"cardRef\" class=\"pc-card\">\n <div class=\"pc-inside\">\n <div class=\"pc-shine\" />\n\n <div class=\"pc-glare\" />\n\n <div class=\"pc-content pc-avatar-content\">\n <img\n class=\"avatar\"\n :src=\"avatarUrl\"\n :alt=\"`${name || 'User'} avatar`\"\n loading=\"lazy\"\n @error=\"handleAvatarError\"\n />\n\n <div v-if=\"showUserInfo\" class=\"pc-user-info\">\n <div class=\"pc-user-details\">\n <div class=\"pc-mini-avatar\">\n <img\n :src=\"miniAvatarUrl || avatarUrl\"\n :alt=\"`${name || 'User'} mini avatar`\"\n loading=\"lazy\"\n @error=\"handleMiniAvatarError\"\n />\n </div>\n\n <div class=\"pc-user-text\">\n <div class=\"pc-handle\">@{{ handle }}</div>\n\n <div class=\"pc-status\">{{ status }}</div>\n </div>\n </div>\n\n <button\n class=\"pc-contact-btn\"\n @click=\"handleContactClick\"\n style=\"pointer-events: auto\"\n type=\"button\"\n :aria-label=\"`Contact ${name || 'user'}`\"\n >\n {{ contactText }}\n </button>\n </div>\n </div>\n\n <div class=\"pc-content\">\n <div class=\"pc-details\">\n <h3>{{ name }}</h3>\n\n <p>{{ title }}</p>\n </div>\n </div>\n </div>\n </section>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { computed, onMounted, onUnmounted, useTemplateRef } from 'vue';\n\ninterface Props {\n avatarUrl?: string;\n iconUrl?: string;\n grainUrl?: string;\n behindGradient?: string;\n innerGradient?: string;\n showBehindGradient?: boolean;\n className?: string;\n enableTilt?: boolean;\n miniAvatarUrl?: string;\n name?: string;\n title?: string;\n handle?: string;\n status?: string;\n contactText?: string;\n showUserInfo?: boolean;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n avatarUrl: '<Placeholder for avatar URL>',\n iconUrl: '<Placeholder for icon URL>',\n grainUrl: '<Placeholder for grain URL>',\n behindGradient: undefined,\n innerGradient: undefined,\n showBehindGradient: true,\n className: '',\n enableTilt: true,\n miniAvatarUrl: undefined,\n name: 'Javi A. Torres',\n title: 'Software Engineer',\n handle: 'javicodes',\n status: 'Online',\n contactText: 'Contact',\n showUserInfo: true\n});\n\nconst emit = defineEmits<{\n contactClick: [];\n}>();\n\nconst wrapRef = useTemplateRef<HTMLDivElement>('wrapRef');\nconst cardRef = useTemplateRef<HTMLElement>('cardRef');\n\nconst DEFAULT_BEHIND_GRADIENT =\n 'radial-gradient(farthest-side circle at var(--pointer-x) var(--pointer-y),hsla(266,100%,90%,var(--card-opacity)) 4%,hsla(266,50%,80%,calc(var(--card-opacity)*0.75)) 10%,hsla(266,25%,70%,calc(var(--card-opacity)*0.5)) 50%,hsla(266,0%,60%,0) 100%),radial-gradient(35% 52% at 55% 20%,#00ffaac4 0%,#073aff00 100%),radial-gradient(100% 100% at 50% 50%,#00c1ffff 1%,#073aff00 76%),conic-gradient(from 124deg at 50% 50%,#c137ffff 0%,#07c6ffff 40%,#07c6ffff 60%,#c137ffff 100%)';\n\nconst DEFAULT_INNER_GRADIENT = 'linear-gradient(145deg,#60496e8c 0%,#71C4FF44 100%)';\n\nconst ANIMATION_CONFIG = {\n SMOOTH_DURATION: 600,\n INITIAL_DURATION: 1500,\n INITIAL_X_OFFSET: 70,\n INITIAL_Y_OFFSET: 60\n} as const;\n\nconst clamp = (value: number, min = 0, max = 100): number => Math.min(Math.max(value, min), max);\n\nconst round = (value: number, precision = 3): number => parseFloat(value.toFixed(precision));\n\nconst adjust = (value: number, fromMin: number, fromMax: number, toMin: number, toMax: number): number =>\n round(toMin + ((toMax - toMin) * (value - fromMin)) / (fromMax - fromMin));\n\nconst easeInOutCubic = (x: number): number => (x < 0.5 ? 4 * x * x * x : 1 - Math.pow(-2 * x + 2, 3) / 2);\n\nlet rafId: number | null = null;\n\nconst updateCardTransform = (offsetX: number, offsetY: number, card: HTMLElement, wrap: HTMLElement) => {\n const width = card.clientWidth;\n const height = card.clientHeight;\n\n const percentX = clamp((100 / width) * offsetX);\n const percentY = clamp((100 / height) * offsetY);\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 Object.entries(properties).forEach(([property, value]) => {\n wrap.style.setProperty(property, value);\n });\n};\n\nconst createSmoothAnimation = (\n duration: number,\n startX: number,\n startY: number,\n card: HTMLElement,\n wrap: HTMLElement\n) => {\n const startTime = performance.now();\n const targetX = wrap.clientWidth / 2;\n const targetY = wrap.clientHeight / 2;\n\n const animationLoop = (currentTime: number) => {\n const elapsed = currentTime - startTime;\n const progress = clamp(elapsed / duration);\n const easedProgress = easeInOutCubic(progress);\n\n const currentX = adjust(easedProgress, 0, 1, startX, targetX);\n const currentY = adjust(easedProgress, 0, 1, startY, targetY);\n\n updateCardTransform(currentX, currentY, card, wrap);\n\n if (progress < 1) {\n rafId = requestAnimationFrame(animationLoop);\n }\n };\n\n rafId = requestAnimationFrame(animationLoop);\n};\n\nconst cancelAnimation = () => {\n if (rafId) {\n cancelAnimationFrame(rafId);\n rafId = null;\n }\n};\n\nconst handlePointerMove = (event: PointerEvent) => {\n const card = cardRef.value;\n const wrap = wrapRef.value;\n\n if (!card || !wrap || !props.enableTilt) return;\n\n const rect = card.getBoundingClientRect();\n updateCardTransform(event.clientX - rect.left, event.clientY - rect.top, card, wrap);\n};\n\nconst handlePointerEnter = () => {\n const card = cardRef.value;\n const wrap = wrapRef.value;\n\n if (!card || !wrap || !props.enableTilt) return;\n\n cancelAnimation();\n wrap.classList.add('active');\n card.classList.add('active');\n};\n\nconst handlePointerLeave = (event: PointerEvent) => {\n const card = cardRef.value;\n const wrap = wrapRef.value;\n\n if (!card || !wrap || !props.enableTilt) return;\n\n createSmoothAnimation(ANIMATION_CONFIG.SMOOTH_DURATION, event.offsetX, event.offsetY, card, wrap);\n wrap.classList.remove('active');\n card.classList.remove('active');\n};\n\nconst cardStyle = computed(() => ({\n '--icon': props.iconUrl ? `url(${props.iconUrl})` : 'none',\n '--grain': props.grainUrl ? `url(${props.grainUrl})` : 'none',\n '--behind-gradient': props.showBehindGradient ? (props.behindGradient ?? DEFAULT_BEHIND_GRADIENT) : 'none',\n '--inner-gradient': props.innerGradient ?? DEFAULT_INNER_GRADIENT\n}));\n\nconst handleContactClick = () => {\n emit('contactClick');\n};\n\nconst handleAvatarError = (event: Event) => {\n const target = event.target as HTMLImageElement;\n target.style.display = 'none';\n};\n\nconst handleMiniAvatarError = (event: Event) => {\n const target = event.target as HTMLImageElement;\n target.style.opacity = '0.5';\n target.src = props.avatarUrl;\n};\n\nonMounted(() => {\n if (!props.enableTilt) return;\n\n const card = cardRef.value;\n const wrap = wrapRef.value;\n\n if (!card || !wrap) return;\n\n card.addEventListener('pointerenter', handlePointerEnter);\n card.addEventListener('pointermove', handlePointerMove);\n card.addEventListener('pointerleave', handlePointerLeave);\n\n const initialX = wrap.clientWidth - ANIMATION_CONFIG.INITIAL_X_OFFSET;\n const initialY = ANIMATION_CONFIG.INITIAL_Y_OFFSET;\n\n updateCardTransform(initialX, initialY, card, wrap);\n createSmoothAnimation(ANIMATION_CONFIG.INITIAL_DURATION, initialX, initialY, card, wrap);\n});\n\nonUnmounted(() => {\n const card = cardRef.value;\n\n if (card) {\n card.removeEventListener('pointerenter', handlePointerEnter);\n card.removeEventListener('pointermove', handlePointerMove);\n card.removeEventListener('pointerleave', handlePointerLeave);\n }\n\n cancelAnimation();\n});\n</script>\n\n<style scoped>\n.pc-card-wrapper {\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 --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-card-wrapper::before {\n content: '';\n position: absolute;\n inset: -10px;\n background: inherit;\n background-position: inherit;\n border-radius: inherit;\n transition: all 0.5s ease;\n filter: contrast(2) saturate(2) blur(36px);\n transform: scale(0.8) translate3d(0, 0, 0.1px);\n background-size: 100% 100%;\n background-image: var(--behind-gradient);\n}\n\n.pc-card-wrapper:hover,\n.pc-card-wrapper.active {\n --card-opacity: 1;\n}\n\n.pc-card-wrapper:hover::before,\n.pc-card-wrapper.active::before {\n filter: contrast(1) saturate(2) blur(40px) opacity(1);\n transform: scale(0.9) translate3d(0, 0, 0.1px);\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: translate3d(0, 0, 0.1px) rotateX(0deg) rotateY(0deg);\n background-size: 100% 100%;\n background-position:\n 0 0,\n 0 0,\n 50% 50%,\n 0 0;\n background-image:\n radial-gradient(\n farthest-side circle at var(--pointer-x) var(--pointer-y),\n hsla(266, 100%, 90%, var(--card-opacity)) 4%,\n hsla(266, 50%, 80%, calc(var(--card-opacity) * 0.75)) 10%,\n hsla(266, 25%, 70%, calc(var(--card-opacity) * 0.5)) 50%,\n hsla(266, 0%, 60%, 0) 100%\n ),\n radial-gradient(35% 52% at 55% 20%, #00ffaac4 0%, #073aff00 100%),\n radial-gradient(100% 100% at 50% 50%, #00c1ffff 1%, #073aff00 76%),\n conic-gradient(from 124deg at 50% 50%, #c137ffff 0%, #07c6ffff 40%, #07c6ffff 60%, #c137ffff 100%);\n overflow: hidden;\n}\n\n.pc-card:hover,\n.pc-card.active {\n transition: none;\n transform: translate3d(0, 0, 0.1px) rotateX(var(--rotate-y)) rotateY(var(--rotate-x));\n}\n\n.pc-card * {\n display: grid;\n grid-area: 1/-1;\n border-radius: var(--card-radius);\n transform: translate3d(0, 0, 0.1px);\n pointer-events: none;\n}\n\n.pc-inside {\n inset: 1px;\n position: absolute;\n background-image: var(--inner-gradient);\n background-color: rgba(0, 0, 0, 0.9);\n transform: translate3d(0, 0, 0.01px);\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 -webkit-mask-image: var(--icon);\n -webkit-mask-mode: luminance;\n -webkit-mask-repeat: repeat;\n -webkit-mask-size: 150%;\n -webkit-mask-position: top calc(200% - (var(--background-y) * 5)) left calc(100% - var(--background-x));\n transition: filter 0.6s ease;\n filter: brightness(0.66) contrast(1.33) saturate(0.33) opacity(0.5);\n animation: holo-bg 18s linear infinite;\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}\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: none;\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 content: '';\n background-image:\n repeating-linear-gradient(\n 0deg,\n var(--sunpillar-clr-1) calc(5% * 1),\n var(--sunpillar-clr-2) calc(5% * 2),\n var(--sunpillar-clr-3) calc(5% * 3),\n var(--sunpillar-clr-4) calc(5% * 4),\n var(--sunpillar-clr-5) calc(5% * 5),\n var(--sunpillar-clr-6) calc(5% * 6),\n var(--sunpillar-clr-1) calc(5% * 7)\n ),\n repeating-linear-gradient(\n -45deg,\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 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: screen;\n overflow: hidden;\n}\n\n.pc-avatar-content .avatar {\n width: 100%;\n position: absolute;\n left: 50%;\n transform: translateX(-50%) scale(1);\n bottom: 2px;\n opacity: calc(1.75 - var(--pointer-from-center));\n}\n\n.pc-avatar-content::before {\n content: '';\n position: absolute;\n inset: 0;\n z-index: 1;\n backdrop-filter: blur(30px);\n mask: linear-gradient(\n to bottom,\n rgba(0, 0, 0, 0) 0%,\n rgba(0, 0, 0, 0) 60%,\n rgba(0, 0, 0, 1) 90%,\n rgba(0, 0, 0, 1) 100%\n );\n pointer-events: none;\n}\n\n.pc-user-info {\n position: absolute;\n bottom: 20px;\n left: 20px;\n right: 20px;\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: 15px;\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: 8px 16px;\n font-size: 14px;\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 background: transparent;\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 {\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 ) !important;\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 bottom: 15px;\n left: 15px;\n right: 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 bottom: 12px;\n left: 12px;\n right: 12px;\n padding: 8px 10px;\n border-radius: 50px;\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 border-radius: 50px;\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</style>\n","path":"ProfileCard/ProfileCard.vue","_imports_":[],"registryDependencies":[],"dependencies":[],"devDependencies":[]}],"registryDependencies":[],"dependencies":[],"devDependencies":[],"categories":["Components"]}