{
  "$schema": "https://uipkge.dev/schema/registry-item.json",
  "name": "payment-card",
  "title": "Payment Card",
  "type": "registry:ui",
  "files": [
    {
      "path": "packages/registry-svelte/components/payment-card/PaymentCard.svelte",
      "content": "<script lang=\"ts\" module>\n  import type { HTMLAttributes } from 'svelte/elements'\n\n  export type CardBrand = 'visa' | 'mastercard' | 'amex' | 'discover' | 'unknown'\n\n  export interface PaymentCardProps extends HTMLAttributes<HTMLDivElement> {\n    number?: string\n    name?: string\n    expiry?: string\n    cvc?: string\n    brand?: CardBrand | 'auto'\n    flipped?: boolean\n    variant?: 'default' | 'compact'\n    tilt?: boolean\n    shimmer?: boolean\n    flip?: boolean\n    size?: 'sm' | 'md' | 'lg'\n    ref?: HTMLDivElement | null\n  }\n\n  export function detectBrand(raw: string): CardBrand {\n    const n = raw.replace(/\\D/g, '')\n    if (!n) return 'unknown'\n    if (/^4/.test(n)) return 'visa'\n    if (/^(5[1-5]|2[2-7])/.test(n)) return 'mastercard'\n    if (/^3[47]/.test(n)) return 'amex'\n    if (/^(6011|65|64[4-9])/.test(n)) return 'discover'\n    return 'unknown'\n  }\n\n  export function formatMasked(raw: string, brand: CardBrand): string {\n    const digits = raw.replace(/\\D/g, '').slice(0, brand === 'amex' ? 15 : 16)\n    const groups = brand === 'amex' ? [4, 6, 5] : [4, 4, 4, 4]\n    const total = groups.reduce((a, b) => a + b, 0)\n    const padded = (digits + '••••••••••••••••').slice(0, total)\n    let i = 0\n    return groups\n      .map((g) => {\n        const slice = padded.slice(i, i + g)\n        i += g\n        return slice\n      })\n      .join(' ')\n  }\n\n  export interface BrandVisual {\n    cardClass: string\n    accentGlow: string\n    foilSheen: string\n    guillocheColor: string\n    textColor: string\n    subtextColor: string\n    embossStyle: string\n    chipType: 'gold' | 'silver'\n  }\n\n  export const BRAND_VISUALS: Record<CardBrand, BrandVisual> = {\n    visa: {\n      cardClass:\n        'bg-[radial-gradient(ellipse_at_top_right,#1e3a8a_0%,#0f2252_45%,#08122c_85%,#040a18_100%)] text-white shadow-[0_22px_45px_-12px_rgba(15,34,82,0.65),0_8px_16px_-8px_rgba(0,0,0,0.5)]',\n      accentGlow: 'from-blue-400/20 via-indigo-500/10 to-transparent',\n      foilSheen: 'from-white/20 via-blue-200/5 to-transparent',\n      guillocheColor: 'rgba(96, 165, 250, 0.12)',\n      textColor: 'text-white',\n      subtextColor: 'text-blue-200/60',\n      embossStyle: 'text-white drop-shadow-[0_1px_1px_rgba(0,0,0,0.8)]',\n      chipType: 'gold',\n    },\n    mastercard: {\n      cardClass:\n        'bg-[radial-gradient(ellipse_at_top_right,#2a0808_0%,#180608_35%,#0f0506_70%,#09090b_100%)] text-white shadow-[0_22px_45px_-12px_rgba(220,38,38,0.35),0_8px_16px_-8px_rgba(0,0,0,0.6)]',\n      accentGlow: 'from-red-500/25 via-amber-500/15 to-transparent',\n      foilSheen: 'from-white/20 via-orange-300/10 to-transparent',\n      guillocheColor: 'rgba(239, 68, 68, 0.1)',\n      textColor: 'text-white',\n      subtextColor: 'text-zinc-400',\n      embossStyle: 'text-zinc-100 drop-shadow-[0_1px_2px_rgba(0,0,0,0.9)]',\n      chipType: 'gold',\n    },\n    amex: {\n      cardClass:\n        'bg-[radial-gradient(ellipse_at_top_right,#1e293b_0%,#0f172a_40%,#090d16_80%,#020617_100%)] text-slate-100 shadow-[0_22px_45px_-12px_rgba(15,23,42,0.7),0_8px_16px_-8px_rgba(0,0,0,0.6)]',\n      accentGlow: 'from-slate-300/20 via-teal-500/10 to-transparent',\n      foilSheen: 'from-white/25 via-cyan-100/10 to-transparent',\n      guillocheColor: 'rgba(148, 163, 184, 0.12)',\n      textColor: 'text-slate-100',\n      subtextColor: 'text-slate-400',\n      embossStyle: 'text-slate-100 drop-shadow-[0_1px_2px_rgba(0,0,0,0.9)]',\n      chipType: 'silver',\n    },\n    discover: {\n      cardClass:\n        'bg-[radial-gradient(ellipse_at_top_right,#431407_0%,#270d04_45%,#1c0903_80%,#0c0401_100%)] text-white shadow-[0_22px_45px_-12px_rgba(194,65,12,0.45),0_8px_16px_-8px_rgba(0,0,0,0.6)]',\n      accentGlow: 'from-orange-400/25 via-amber-600/15 to-transparent',\n      foilSheen: 'from-white/20 via-amber-200/10 to-transparent',\n      guillocheColor: 'rgba(251, 146, 60, 0.12)',\n      textColor: 'text-white',\n      subtextColor: 'text-amber-200/60',\n      embossStyle: 'text-white drop-shadow-[0_1px_2px_rgba(0,0,0,0.9)]',\n      chipType: 'gold',\n    },\n    unknown: {\n      cardClass:\n        'bg-[radial-gradient(ellipse_at_top_right,#27272a_0%,#18181b_40%,#09090b_85%,#000000_100%)] text-white shadow-[0_22px_45px_-12px_rgba(0,0,0,0.7),0_8px_16px_-8px_rgba(0,0,0,0.5)]',\n      accentGlow: 'from-zinc-400/15 via-zinc-600/10 to-transparent',\n      foilSheen: 'from-white/18 via-zinc-300/5 to-transparent',\n      guillocheColor: 'rgba(255, 255, 255, 0.06)',\n      textColor: 'text-white',\n      subtextColor: 'text-zinc-400',\n      embossStyle: 'text-zinc-100 drop-shadow-[0_1px_2px_rgba(0,0,0,0.9)]',\n      chipType: 'silver',\n    },\n  }\n</script>\n\n<script lang=\"ts\">\n  import { cn } from '$lib/utils'\n\n  let {\n    number = '',\n    name = '',\n    expiry = '',\n    cvc = '',\n    brand = 'auto',\n    flipped = false,\n    variant = 'default',\n    tilt = false,\n    shimmer = false,\n    flip = true,\n    size = 'md',\n    class: className,\n    ref = $bindable(null),\n    ...restProps\n  }: PaymentCardProps = $props()\n\n  const detectedBrand = $derived<CardBrand>(brand !== 'auto' ? brand : detectBrand(number))\n  const displayNumber = $derived(formatMasked(number, detectedBrand))\n  const displayName = $derived((name.trim() || 'CARDHOLDER NAME').toUpperCase())\n  const displayExpiry = $derived.by(() => {\n    const raw = expiry.replace(/\\D/g, '').slice(0, 4)\n    if (!raw) return 'MM/YY'\n    if (raw.length <= 2) return raw + '/YY'\n    return `${raw.slice(0, 2)}/${raw.slice(2, 4)}`\n  })\n  const displayCvc = $derived.by(() => {\n    const max = detectedBrand === 'amex' ? 4 : 3\n    const digits = cvc.replace(/\\D/g, '').slice(0, max)\n    return digits || '•••'\n  })\n  const displayChars = $derived(displayNumber.split(''))\n  const ariaLabel = $derived(\n    `${detectedBrand === 'unknown' ? 'Card' : detectedBrand} ending ${displayNumber.replace(/[•\\s]/g, '').slice(-4) || '••••'}, ${displayName}, expires ${displayExpiry}`,\n  )\n\n  // Character pop-in animation tracking (immutable Set swaps keep $state reactive).\n  let prevDigits = $state('')\n  let poppedIndexes = $state<ReadonlySet<number>>(new Set())\n  let popClearTimer: ReturnType<typeof setTimeout> | null = null\n\n  $effect(() => {\n    const nextDigits = number.replace(/\\D/g, '')\n    const prev = prevDigits\n    if (nextDigits.length > prev.length) {\n      poppedIndexes = new Set([...poppedIndexes, nextDigits.length - 1])\n      if (popClearTimer) clearTimeout(popClearTimer)\n      popClearTimer = setTimeout(() => {\n        poppedIndexes = new Set()\n      }, 400)\n    }\n    prevDigits = nextDigits\n  })\n\n  function shouldPop(charIndex: number, ch: string): boolean {\n    if (ch === '•' || ch === ' ') return false\n    const strUpTo = displayNumber.slice(0, charIndex + 1)\n    const digitCount = (strUpTo.match(/\\d/g) || []).length\n    return poppedIndexes.has(digitCount - 1)\n  }\n\n  // 3D parallax tilt.\n  let tiltX = $state(0)\n  let tiltY = $state(0)\n  let isHovering = $state(false)\n\n  function onMove(e: MouseEvent) {\n    if (!tilt || !ref) return\n    const rect = ref.getBoundingClientRect()\n    const x = e.clientX - rect.left\n    const y = e.clientY - rect.top\n    const px = (x / rect.width - 0.5) * 2\n    const py = (y / rect.height - 0.5) * 2\n    tiltX = -py * 10\n    tiltY = px * 12\n    isHovering = true\n  }\n\n  function onLeave() {\n    if (!tilt) return\n    tiltX = 0\n    tiltY = 0\n    isHovering = false\n  }\n\n  const innerTransform = $derived.by(() => {\n    const flipDeg = flipped ? 180 : 0\n    if (tilt && isHovering) {\n      return `perspective(1200px) rotateX(${tiltX}deg) rotateY(${tiltY + flipDeg}deg) scale3d(1.02, 1.02, 1.02)`\n    }\n    return `perspective(1200px) rotateY(${flipDeg}deg)`\n  })\n\n  const sizeClass = $derived.by(() => {\n    if (variant === 'compact') return 'w-[120px]'\n    switch (size) {\n      case 'sm':\n        return 'w-[280px]'\n      case 'lg':\n        return 'w-[420px]'\n      case 'md':\n      default:\n        return 'w-[360px]'\n    }\n  })\n\n  const theme = $derived(BRAND_VISUALS[detectedBrand])\n  const tierLabel = $derived(\n    detectedBrand === 'amex' ? 'PLATINUM' : detectedBrand === 'mastercard' ? 'WORLD ELITE' : 'SIGNATURE',\n  )\n</script>\n\n<div\n  bind:this={ref}\n  data-uipkge\n  data-slot=\"payment-card\"\n  role=\"img\"\n  aria-label={ariaLabel}\n  class={cn('group relative inline-block [perspective:1200px] select-none', sizeClass, className)}\n  onmousemove={onMove}\n  onmouseleave={onLeave}\n  {...restProps}\n>\n  <div\n    class={cn(\n      'relative aspect-[85.6/53.98] w-full transition-transform [transform-style:preserve-3d]',\n      flip ? 'duration-[650ms] ease-[cubic-bezier(0.22,1,0.36,1)]' : 'duration-300',\n    )}\n    style:transform={innerTransform}\n  >\n    <!-- ================================= FRONT FACE ================================= -->\n    <div\n      class={cn(\n        'pay-card-face absolute inset-0 overflow-hidden rounded-[16px] border border-white/15 [backface-visibility:hidden]',\n        theme.cardClass,\n      )}\n    >\n      <!-- Fine Guilloché & Security Geometric Wave Pattern -->\n      <svg\n        class=\"pointer-events-none absolute inset-0 size-full opacity-60 mix-blend-screen\"\n        xmlns=\"http://www.w3.org/2000/svg\"\n        viewBox=\"0 0 360 227\"\n        fill=\"none\"\n        aria-hidden=\"true\"\n      >\n        <g stroke={theme.guillocheColor} stroke-width=\"0.75\" stroke-opacity=\"0.7\">\n          <path d=\"M-40 40 C 60 180, 180 -40, 400 120\" />\n          <path d=\"M-40 55 C 60 195, 180 -25, 400 135\" />\n          <path d=\"M-40 70 C 60 210, 180 -10, 400 150\" />\n          <path d=\"M-40 85 C 60 225, 180 5, 400 165\" />\n          <path d=\"M-40 100 C 60 240, 180 20, 400 180\" />\n          <path d=\"M-40 115 C 60 255, 180 35, 400 195\" />\n          <circle cx=\"280\" cy=\"80\" r=\"90\" stroke-width=\"0.5\" stroke-dasharray=\"2 3\" />\n          <circle cx=\"280\" cy=\"80\" r=\"60\" stroke-width=\"0.5\" stroke-dasharray=\"1 2\" />\n        </g>\n      </svg>\n\n      <!-- Brushed Metallic Sheen & Specular Lighting -->\n      <div\n        class=\"pointer-events-none absolute inset-0 bg-gradient-to-tr from-transparent via-white/[0.07] to-transparent opacity-80\"\n      ></div>\n      <div\n        class={cn(\n          'pointer-events-none absolute -inset-y-8 -left-1/3 w-1/2 rotate-12 bg-gradient-to-r opacity-70',\n          theme.foilSheen,\n        )}\n      ></div>\n      <!-- Ambient Corner Highlights -->\n      <div\n        class={cn(\n          'pointer-events-none absolute -top-12 -right-12 h-44 w-44 rounded-full bg-gradient-to-br blur-2xl',\n          theme.accentGlow,\n        )}\n      ></div>\n      <div class=\"pointer-events-none absolute -bottom-10 -left-10 h-36 w-36 rounded-full bg-black/40 blur-2xl\"></div>\n\n      <!-- Outer Bevel Perimeter Ring -->\n      <div\n        class=\"pointer-events-none absolute inset-0 rounded-[16px] shadow-[inset_0_1px_1px_rgba(255,255,255,0.35),inset_0_-1px_1px_rgba(0,0,0,0.5)]\"\n      ></div>\n\n      <!-- Shimmer sweep (opt-in) -->\n      {#if shimmer}\n        <div\n          class=\"pointer-events-none absolute -inset-x-full inset-y-0 bg-gradient-to-r from-transparent via-white/25 to-transparent\"\n          style=\"animation: payment-card-shimmer 2.5s linear infinite\"\n        ></div>\n      {/if}\n\n      <!-- Content Structure -->\n      <div class={cn('absolute inset-0 flex flex-col justify-between', variant === 'compact' ? 'p-2' : 'p-5')}>\n        <!-- TOP ROW: Bank Watermark / Card Tier & Brand Logo -->\n        <div class=\"flex items-center justify-between\">\n          <!-- Left: Card Tier / Bank label -->\n          <div class=\"flex items-center gap-1.5\">\n            {#if variant !== 'compact'}\n              <span class=\"font-mono text-xs font-semibold tracking-[0.25em] text-white/70 uppercase\">\n                {tierLabel}\n              </span>\n            {:else}\n              <span class=\"font-mono text-xs font-bold tracking-widest text-white/70 uppercase\"> CARD </span>\n            {/if}\n          </div>\n\n          <!-- Right: Authentic Brand Logo -->\n          <div class=\"flex items-center justify-end\" style=\"perspective: 600px\">\n            {#key detectedBrand}\n              <!-- .brand-pop replays the enter animation on every brand change (the Vue <Transition> equivalent). -->\n              <div class=\"brand-pop\">\n                {#if detectedBrand === 'visa'}\n                  <!-- VISA -->\n                  <div class=\"flex items-center\">\n                    <svg\n                      class={variant === 'compact' ? 'h-3 w-auto' : 'h-6 w-auto'}\n                      viewBox=\"0 0 78 24\"\n                      fill=\"none\"\n                      xmlns=\"http://www.w3.org/2000/svg\"\n                      aria-label=\"Visa\"\n                    >\n                      <path\n                        d=\"M29.5 23.2H23.9L27.4 1.8H33L29.5 23.2ZM52.4 2.3C51.3 1.9 49.5 1.5 47.3 1.5C41.8 1.5 37.9 4.4 37.8 8.6C37.7 11.7 40.5 13.4 42.6 14.4C44.8 15.5 45.5 16.2 45.5 17.1C45.5 18.6 43.7 19.2 42.1 19.2C39.8 19.2 38.5 18.9 36.8 18.1L36 17.7L35.1 23C36.6 23.7 39.2 24.2 41.8 24.2C47.7 24.2 51.5 21.3 51.6 16.9C51.7 13.4 49.6 11.7 47 10.4C45.2 9.5 44.1 8.9 44.1 8C44.1 7.2 45 6.4 46.8 6.4C48.3 6.4 49.6 6.7 50.8 7.2L51.3 7.5L52.4 2.3ZM67.5 1.8H63.2C61.8 1.8 60.8 2.2 60.2 3.6L51.4 23.2H57.3L58.5 19.9H65.7L66.4 23.2H71.6L67.5 1.8ZM60.1 15.5C60.6 14.2 62.5 8.9 62.5 8.9C62.5 8.9 63 7.6 63.3 6.7L63.8 8.7C63.8 8.7 64.9 14.1 65.2 15.5H60.1ZM18.7 1.8L13.2 16.4L12.6 13.4C11.6 10 8.7 6.3 5.4 4.5L10.3 23.2H16.3L25.1 1.8H18.7ZM8.3 1.8H0.2L0 2.3C6.3 3.9 10.4 7.7 12.1 12.4L10.4 3.7C10.1 2.4 9.3 1.9 8.3 1.8H0.2L0 2.3C6.3 3.9 10.4 7.7 12.1 12.4Z\"\n                        fill=\"white\"\n                      />\n                      <path\n                        d=\"M12.1 12.4L10.4 3.7C10.1 2.4 9.3 1.9 8.3 1.8H0.2L0 2.3C6.3 3.9 10.4 7.7 12.1 12.4Z\"\n                        fill=\"#F9A01B\"\n                      />\n                    </svg>\n                  </div>\n                {:else if detectedBrand === 'mastercard'}\n                  <!-- MASTERCARD -->\n                  <div class=\"flex items-center gap-1.5\">\n                    <svg\n                      class={variant === 'compact' ? 'h-3.5 w-auto' : 'h-7 w-auto'}\n                      viewBox=\"0 0 48 30\"\n                      fill=\"none\"\n                      xmlns=\"http://www.w3.org/2000/svg\"\n                      aria-label=\"Mastercard\"\n                    >\n                      <circle cx=\"15\" cy=\"15\" r=\"15\" fill=\"#EB001B\" />\n                      <circle cx=\"33\" cy=\"15\" r=\"15\" fill=\"#F79E1B\" fill-opacity=\"0.92\" />\n                      <path\n                        d=\"M24 4.5C27.5 7.1 29.8 11.2 29.8 16C29.8 20.8 27.5 24.9 24 27.5C20.5 24.9 18.2 20.8 18.2 16C18.2 11.2 20.5 7.1 24 4.5Z\"\n                        fill=\"#FF5F00\"\n                      />\n                    </svg>\n                    {#if variant !== 'compact'}\n                      <span\n                        class=\"font-mono text-xs font-bold tracking-tight text-white lowercase\"\n                        style=\"letter-spacing: -0.05em\"\n                      >\n                        mastercard\n                      </span>\n                    {/if}\n                  </div>\n                {:else if detectedBrand === 'amex'}\n                  <!-- AMEX -->\n                  <div class=\"flex items-center\">\n                    <div\n                      class={cn(\n                        'flex items-center justify-center rounded-sm bg-[#006fcf] font-sans font-bold tracking-tighter text-white shadow-xs',\n                        variant === 'compact' ? 'px-1 py-0.5 text-xs' : 'px-2 py-1 text-xs',\n                      )}\n                    >\n                      AMEX\n                    </div>\n                  </div>\n                {:else if detectedBrand === 'discover'}\n                  <!-- DISCOVER -->\n                  <div class=\"flex items-center gap-0.5 text-xs font-bold tracking-wider text-white\">\n                    <span>DISC</span>\n                    <span\n                      class={cn(\n                        'inline-block rounded-full bg-gradient-to-br from-amber-400 to-orange-600 shadow-xs',\n                        variant === 'compact' ? 'size-2' : 'size-3.5',\n                      )}\n                    ></span>\n                    <span>VER</span>\n                  </div>\n                {:else}\n                  <!-- UNKNOWN / SLEEK DEFAULT -->\n                  <div class=\"flex items-center gap-1 opacity-80\">\n                    <div class=\"size-2 rounded-full bg-white/60\"></div>\n                    <div class=\"size-2 rounded-full bg-white/30\"></div>\n                    <span class=\"font-mono text-xs font-bold tracking-widest text-white/80 uppercase\"> PREMIUM </span>\n                  </div>\n                {/if}\n              </div>\n            {/key}\n          </div>\n        </div>\n\n        <!-- MIDDLE ROW: EMV Chip + Contactless Symbol -->\n        <div class=\"flex items-center justify-between\">\n          <div class=\"flex items-center gap-3\">\n            <!-- Ultra-Realistic Metallic EMV Chip -->\n            <div\n              class={cn(\n                'relative overflow-hidden rounded-[5px] border border-amber-950/40 shadow-[0_2px_5px_rgba(0,0,0,0.5),inset_0_1px_0_rgba(255,255,255,0.6)]',\n                theme.chipType === 'silver'\n                  ? 'bg-gradient-to-br from-slate-200 via-slate-300 to-slate-400'\n                  : 'bg-gradient-to-br from-[#ffe082] via-[#ffb300] to-[#ff8f00]',\n                variant === 'compact' ? 'h-3.5 w-5' : 'h-8 w-11',\n              )}\n            >\n              <!-- Authentic Chip Circuit Etching Lines -->\n              <div class=\"absolute inset-[2px] rounded-[3px] border border-black/25\"></div>\n              <div class=\"absolute inset-x-0 top-1/2 h-px -translate-y-1/2 bg-black/30\"></div>\n              <div class=\"absolute inset-y-0 left-1/3 w-px bg-black/30\"></div>\n              <div class=\"absolute inset-y-0 right-1/3 w-px bg-black/30\"></div>\n              <div\n                class=\"absolute top-1/4 right-1/3 left-1/3 h-1/2 rounded-[2px] border border-black/25 bg-black/10\"\n              ></div>\n              <!-- Metallic Glint Reflection -->\n              <div\n                class=\"pointer-events-none absolute inset-0 bg-gradient-to-tr from-transparent via-white/40 to-transparent\"\n              ></div>\n            </div>\n\n            <!-- Contactless NFC Radio Waves -->\n            {#if variant !== 'compact'}\n              <svg\n                viewBox=\"0 0 24 24\"\n                class=\"h-5 w-auto text-white/70 drop-shadow-sm\"\n                fill=\"none\"\n                stroke=\"currentColor\"\n                stroke-width=\"1.75\"\n                stroke-linecap=\"round\"\n                aria-hidden=\"true\"\n              >\n                <path d=\"M6.5 8a6 6 0 0 1 0 8\" />\n                <path d=\"M10 6a9.5 9.5 0 0 1 0 12\" />\n                <path d=\"M13.5 4a13 13 0 0 1 0 16\" />\n              </svg>\n            {/if}\n          </div>\n\n          <!-- Holographic Security Stamp (Optional realistic detail) -->\n          {#if variant !== 'compact'}\n            <div class=\"pay-card-holo h-7 w-9 rounded-[4px] opacity-75 shadow-xs\"></div>\n          {/if}\n        </div>\n\n        <!-- CARD NUMBER (Authentic Embossed Raised Digits) -->\n        <div\n          class={cn(\n            'flex flex-nowrap items-center font-mono font-bold tracking-[0.18em] tabular-nums',\n            theme.embossStyle,\n            variant === 'compact' ? 'my-0.5 text-xs' : 'my-1 text-base sm:text-lg',\n          )}\n        >\n          <span class=\"sr-only\">{displayNumber}</span>\n          {#each displayChars as ch, i (`${i}-${ch}`)}\n            <span\n              class={cn(\n                'inline-block origin-bottom tabular-nums transition-transform',\n                ch === '•' && 'text-[0.85em] opacity-50',\n                shouldPop(i, ch) && 'pay-char-pop',\n              )}\n              aria-hidden=\"true\"\n            >\n              {ch === ' ' ? ' ' : ch}\n            </span>\n          {/each}\n        </div>\n\n        <!-- BOTTOM ROW: Cardholder Name + Expiry Date -->\n        <div class=\"flex items-end justify-between gap-3\">\n          <!-- Cardholder Name -->\n          <div class=\"min-w-0 flex-1\">\n            {#if variant !== 'compact'}\n              <div class={cn('text-xs font-semibold tracking-[0.2em] uppercase', theme.subtextColor)}>\n                CARDHOLDER NAME\n              </div>\n            {/if}\n            <div\n              class={cn(\n                'truncate font-semibold tracking-wider uppercase',\n                theme.embossStyle,\n                variant === 'compact' ? 'text-xs' : 'text-xs',\n              )}\n            >\n              {displayName}\n            </div>\n          </div>\n\n          <!-- Expiry Date -->\n          <div class=\"shrink-0 text-right\">\n            {#if variant !== 'compact'}\n              <div\n                class={cn(\n                  'flex items-center justify-end gap-1 text-xs font-semibold tracking-wider uppercase',\n                  theme.subtextColor,\n                )}\n              >\n                <span class=\"text-[6px] leading-tight\">GOOD<br />THRU</span>\n                <span>MONTH/YEAR</span>\n              </div>\n            {/if}\n            <div\n              class={cn(\n                'font-mono font-semibold tracking-wider whitespace-nowrap',\n                theme.embossStyle,\n                variant === 'compact' ? 'text-xs' : 'text-xs',\n              )}\n            >\n              {displayExpiry}\n            </div>\n          </div>\n        </div>\n      </div>\n    </div>\n\n    <!-- ================================= BACK FACE ================================= -->\n    <div\n      class={cn(\n        'pay-card-face absolute inset-0 [transform:rotateY(180deg)] overflow-hidden rounded-[16px] border border-white/15 [backface-visibility:hidden]',\n        theme.cardClass,\n      )}\n    >\n      <!-- Specular Bevel Perimeter -->\n      <div\n        class=\"pointer-events-none absolute inset-0 rounded-[16px] shadow-[inset_0_1px_1px_rgba(255,255,255,0.35),inset_0_-1px_1px_rgba(0,0,0,0.5)]\"\n      ></div>\n\n      <!-- Full-Width Deep Matte Magnetic Stripe -->\n      <div\n        class={cn(\n          'w-full bg-gradient-to-b from-neutral-950 via-black to-neutral-900 shadow-[inset_0_1px_0_rgba(255,255,255,0.1),inset_0_-1px_0_rgba(0,0,0,0.8)]',\n          variant === 'compact' ? 'mt-2 h-4' : 'mt-4 h-10',\n        )}\n      ></div>\n\n      <div class={cn('relative flex flex-col justify-between', variant === 'compact' ? 'p-2' : 'p-4')}>\n        <!-- Signature Panel + CVV Code -->\n        <div class={cn('flex items-stretch gap-2', variant === 'compact' ? 'mt-1' : 'mt-2')}>\n          <!-- White Security Hatched Signature Strip -->\n          <div\n            class={cn(\n              'relative flex-1 overflow-hidden rounded-[3px] border border-slate-300/80 bg-white/95 px-2 py-1',\n              variant === 'compact' ? 'h-4' : 'h-8',\n            )}\n            style=\"background-image: repeating-linear-gradient(-45deg, rgba(0, 0, 0, 0.05) 0px, rgba(0, 0, 0, 0.05) 2px, transparent 2px, transparent 6px);\"\n          >\n            {#if variant !== 'compact'}\n              <div class=\"font-mono text-xs font-semibold tracking-wider text-slate-400 uppercase\">\n                AUTHORIZED SIGNATURE\n              </div>\n            {/if}\n          </div>\n\n          <!-- Printed CVV Code Box -->\n          <div\n            class={cn(\n              'flex flex-col items-center justify-center rounded-[3px] border border-slate-300 bg-white font-mono font-bold text-slate-950 shadow-inner',\n              variant === 'compact' ? 'px-1 text-xs' : 'px-3 text-xs',\n            )}\n          >\n            {#if variant !== 'compact'}\n              <span class=\"text-[6px] font-bold tracking-widest text-slate-400 uppercase\"> CVV </span>\n            {/if}\n            <span class=\"leading-none tracking-widest italic\">{displayCvc}</span>\n          </div>\n        </div>\n\n        <!-- Microtext Disclaimer & Regulatory Compliance Marks -->\n        {#if variant !== 'compact'}\n          <div class=\"mt-3 space-y-1.5\">\n            <p class=\"text-[7.5px] leading-snug text-white/50\">\n              This card is property of the issuing bank and must be returned upon request. Use is subject to the\n              cardholder agreement.\n            </p>\n            <div\n              class=\"flex items-center justify-between border-t border-white/10 pt-2 text-xs font-medium text-white/60\"\n            >\n              <span>24/7 Support: 1-800-555-0199</span>\n              <span class=\"font-mono font-bold tracking-wider text-white/75\">CIRRUS · PLUS · STAR</span>\n            </div>\n          </div>\n        {/if}\n      </div>\n    </div>\n  </div>\n</div>\n\n<style>\n  @keyframes payment-card-shimmer {\n    0% {\n      transform: translateX(-100%);\n    }\n    100% {\n      transform: translateX(200%);\n    }\n  }\n\n  @keyframes pay-char-pop {\n    0% {\n      opacity: 0;\n      transform: translateY(8px) scale(0.6);\n    }\n    50% {\n      opacity: 1;\n      transform: translateY(-2px) scale(1.15);\n    }\n    100% {\n      opacity: 1;\n      transform: translateY(0) scale(1);\n    }\n  }\n\n  .pay-char-pop {\n    animation: pay-char-pop 360ms cubic-bezier(0.22, 1.4, 0.36, 1) both;\n  }\n\n  .pay-card-holo {\n    background: linear-gradient(\n      135deg,\n      rgba(255, 255, 255, 0.2) 0%,\n      rgba(56, 189, 248, 0.6) 25%,\n      rgba(168, 85, 247, 0.6) 50%,\n      rgba(251, 146, 60, 0.55) 75%,\n      rgba(74, 222, 128, 0.5) 100%\n    );\n    box-shadow:\n      inset 0 0 0 1px rgba(255, 255, 255, 0.35),\n      0 2px 6px rgba(0, 0, 0, 0.3);\n  }\n\n  /* Replays on every brand change via {#key} — the Vue <Transition name=\"brand-pop\"> equivalent. */\n  @keyframes brand-pop-in {\n    from {\n      opacity: 0;\n      transform: scale(0.7) rotateY(-90deg);\n    }\n    to {\n      opacity: 1;\n      transform: scale(1) rotateY(0deg);\n    }\n  }\n\n  .brand-pop {\n    animation: brand-pop-in 300ms cubic-bezier(0.22, 1, 0.36, 1) both;\n    transform-style: preserve-3d;\n    backface-visibility: hidden;\n  }\n\n  @media (prefers-reduced-motion: reduce) {\n    [data-slot='payment-card'] [class*='transition-'] {\n      transition-duration: 0ms !important;\n    }\n    [data-slot='payment-card'] [style*='payment-card-shimmer'] {\n      animation: none !important;\n    }\n    .pay-char-pop {\n      animation: none !important;\n    }\n    .brand-pop {\n      animation: none !important;\n    }\n  }\n</style>\n",
      "type": "registry:ui",
      "target": "~/src/lib/components/ui/payment-card/PaymentCard.svelte"
    },
    {
      "path": "packages/registry-svelte/components/payment-card/index.ts",
      "content": "export { default as PaymentCard, detectBrand, formatMasked, BRAND_VISUALS } from './PaymentCard.svelte'\nexport type { PaymentCardProps, CardBrand, BrandVisual } from './PaymentCard.svelte'\n",
      "type": "registry:ui",
      "target": "~/src/lib/components/ui/payment-card/index.ts"
    }
  ],
  "dependencies": [],
  "devDependencies": [],
  "registryDependencies": [],
  "description": "Premium metallic credit-card visual with embossed type, holographic foil, and per-digit typing animation. Auto-detects brand (Visa, Mastercard, Amex, Discover), flips in 3D, and supports opt-in mouse-parallax tilt and shimmer. Pure presentational — pass typed values in via props.",
  "categories": [
    "data-display"
  ]
}