{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "virtual-card-manager",
  "title": "Virtual Card Manager",
  "type": "registry:block",
  "files": [
    {
      "path": "packages/registry-react/blocks/virtual-card-manager/VirtualCardManager.tsx",
      "content": "'use client'\n\nimport * as React from 'react'\nimport {\n  Check,\n  Copy,\n  CreditCard,\n  Eye,\n  EyeOff,\n  Plus,\n  Radio,\n  ShieldCheck,\n  SlidersHorizontal,\n  Snowflake,\n  CheckCircle2,\n  Trash2,\n  Zap,\n} from 'lucide-react'\nimport { cn } from '@/lib/utils'\nimport { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar'\nimport { Badge } from '@/components/ui/badge'\nimport { Button } from '@/components/ui/button'\nimport { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'\nimport { Progress } from '@/components/ui/progress'\nimport { Switch } from '@/components/ui/switch'\n\ninterface VirtualCard {\n  id: string\n  name: string\n  brand: 'mastercard' | 'visa'\n  last4: string\n  fullNumber: string\n  holder: string\n  avatar: string\n  initials: string\n  expiry: string\n  cvv: string\n  spent: number\n  limit: number\n  type: 'Monthly Recurring' | 'Single-use'\n  status: 'Active' | 'Frozen'\n  billingCycle: string\n  purpose: string\n}\n\nconst initialCards: VirtualCard[] = [\n  {\n    id: 'vc-1',\n    name: 'AWS & Cloud Infrastructure',\n    brand: 'mastercard',\n    last4: '8492',\n    fullNumber: '5532 8920 4108 8492',\n    holder: 'Elena Rostova',\n    avatar: 'https://images.unsplash.com/photo-1534528741775-53994a69daeb?w=100&auto=format&fit=crop&q=80',\n    initials: 'ER',\n    expiry: '08/29',\n    cvv: '482',\n    spent: 4200,\n    limit: 5000,\n    type: 'Monthly Recurring',\n    status: 'Active',\n    billingCycle: 'Resets on 1st of month',\n    purpose: 'Cloud compute, S3 buckets, and RDS instances',\n  },\n  {\n    id: 'vc-2',\n    name: 'Marketing & Ad Spend',\n    brand: 'visa',\n    last4: '3190',\n    fullNumber: '4012 8831 9204 3190',\n    holder: 'Marcus Chen',\n    avatar: 'https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?w=100&auto=format&fit=crop&q=80',\n    initials: 'MC',\n    expiry: '11/28',\n    cvv: '915',\n    spent: 8750,\n    limit: 10000,\n    type: 'Monthly Recurring',\n    status: 'Active',\n    billingCycle: 'Resets on 1st of month',\n    purpose: 'Google Ads, LinkedIn campaigns, and Meta Ads',\n  },\n  {\n    id: 'vc-3',\n    name: 'Travel & Conferences',\n    brand: 'visa',\n    last4: '6021',\n    fullNumber: '4111 5900 1284 6021',\n    holder: 'Sarah Jenkins',\n    avatar: 'https://images.unsplash.com/photo-1494790108377-be9c29b29330?w=100&auto=format&fit=crop&q=80',\n    initials: 'SJ',\n    expiry: '03/27',\n    cvv: '304',\n    spent: 1850,\n    limit: 2500,\n    type: 'Single-use',\n    status: 'Frozen',\n    billingCycle: 'Single event allowance',\n    purpose: 'Q3 Design Systems Summit flights and lodging',\n  },\n  {\n    id: 'vc-4',\n    name: 'SaaS Subscriptions',\n    brand: 'mastercard',\n    last4: '9455',\n    fullNumber: '5241 7719 3302 9455',\n    holder: 'Elena Rostova',\n    avatar: 'https://images.unsplash.com/photo-1534528741775-53994a69daeb?w=100&auto=format&fit=crop&q=80',\n    initials: 'ER',\n    expiry: '05/29',\n    cvv: '729',\n    spent: 620,\n    limit: 1200,\n    type: 'Monthly Recurring',\n    status: 'Active',\n    billingCycle: 'Resets on 1st of month',\n    purpose: 'GitHub Enterprise, Figma, and Slack licenses',\n  },\n]\n\nexport interface VirtualCardManagerProps {\n  className?: string\n}\n\nexport function VirtualCardManager({ className }: VirtualCardManagerProps) {\n  const [cards, setCards] = React.useState<VirtualCard[]>(initialCards)\n  const [selectedId, setSelectedId] = React.useState<string>('vc-1')\n  const [showDetails, setShowDetails] = React.useState<boolean>(false)\n  const [copied, setCopied] = React.useState<boolean>(false)\n  const [actionFeedback, setActionFeedback] = React.useState<string | null>(null)\n\n  const selectedCard = cards.find((c) => c.id === selectedId) ?? cards[0]\n  const isSelectedFrozen = selectedCard?.status === 'Frozen'\n  const selectedPercent =\n    selectedCard && selectedCard.limit > 0\n      ? Math.min(100, Math.round((selectedCard.spent / selectedCard.limit) * 100))\n      : 0\n\n  const showFeedback = React.useCallback((msg: string) => {\n    setActionFeedback(msg)\n    setTimeout(() => {\n      setActionFeedback((prev) => (prev === msg ? null : prev))\n    }, 3000)\n  }, [])\n\n  const toggleFreeze = React.useCallback((id: string) => {\n    setCards((prev) =>\n      prev.map((c) => {\n        if (c.id === id) {\n          const nextStatus = c.status === 'Active' ? 'Frozen' : 'Active'\n          return { ...c, status: nextStatus }\n        }\n        return c\n      }),\n    )\n  }, [])\n\n  const handleCopyNumber = React.useCallback(() => {\n    if (!selectedCard) return\n    if (typeof navigator !== 'undefined' && navigator.clipboard) {\n      navigator.clipboard.writeText(selectedCard.fullNumber.replace(/\\s+/g, ''))\n    }\n    setCopied(true)\n    setTimeout(() => setCopied(false), 2000)\n  }, [selectedCard])\n\n  const adjustLimit = React.useCallback(\n    (cardId: string) => {\n      setCards((prev) =>\n        prev.map((c) => {\n          if (c.id === cardId) {\n            const newLimit = c.limit === 5000 ? 7500 : c.limit === 10000 ? 12000 : c.limit + 1000\n            return { ...c, limit: newLimit }\n          }\n          return c\n        }),\n      )\n      const current = cards.find((c) => c.id === cardId)\n      const newLimit = current\n        ? current.limit === 5000\n          ? 7500\n          : current.limit === 10000\n            ? 12000\n            : current.limit + 1000\n        : 0\n      showFeedback(`Limit updated to $${newLimit.toLocaleString()}`)\n    },\n    [cards, showFeedback],\n  )\n\n  const terminateCard = React.useCallback(\n    (cardId: string) => {\n      if (cards.length <= 1) {\n        showFeedback('Cannot terminate the last remaining card')\n        return\n      }\n      const remaining = cards.filter((c) => c.id !== cardId)\n      setCards(remaining)\n      if (selectedId === cardId) {\n        setSelectedId(remaining[0].id)\n      }\n      showFeedback('Card terminated permanently')\n    },\n    [cards, selectedId, showFeedback],\n  )\n\n  const issueNewCard = React.useCallback(() => {\n    const newId = `vc-${Date.now().toString().slice(-4)}`\n    const newLast4 = Math.floor(1000 + Math.random() * 9000).toString()\n    const newCard: VirtualCard = {\n      id: newId,\n      name: 'AI & API Workloads',\n      brand: 'visa',\n      last4: newLast4,\n      fullNumber: `4400 1284 9912 ${newLast4}`,\n      holder: 'Elena Rostova',\n      avatar: 'https://images.unsplash.com/photo-1534528741775-53994a69daeb?w=100&auto=format&fit=crop&q=80',\n      initials: 'ER',\n      expiry: '09/30',\n      cvv: '814',\n      spent: 0,\n      limit: 3000,\n      type: 'Monthly Recurring',\n      status: 'Active',\n      billingCycle: 'Resets on 1st of month',\n      purpose: 'OpenAI, Anthropic, and Vector DB infrastructure',\n    }\n    setCards((prev) => [newCard, ...prev])\n    setSelectedId(newId)\n    showFeedback('New virtual card issued successfully')\n  }, [showFeedback])\n\n  return (\n    <div data-slot=\"virtual-card-manager\" className={cn('mx-auto w-full max-w-6xl space-y-6', className)}>\n      {/* Header */}\n      <div className=\"flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between\">\n        <div className=\"space-y-1\">\n          <div className=\"flex items-center gap-2.5\">\n            <h2 className=\"text-foreground text-xl font-semibold tracking-tight sm:text-2xl\">Virtual Cards</h2>\n            <Badge wrap variant=\"secondary\" className=\"font-mono text-xs tabular-nums\">\n              {cards.length} Cards\n            </Badge>\n          </div>\n          <p className=\"text-muted-foreground text-sm\">\n            Generate instant corporate cards for subscriptions, vendors, and team expense limits.\n          </p>\n        </div>\n\n        <div className=\"flex items-center gap-2\">\n          <Button size=\"sm\" className=\"gap-1.5 shadow-xs\" onClick={issueNewCard}>\n            <Plus className=\"size-4\" />\n            Issue New Card\n          </Button>\n        </div>\n      </div>\n\n      {/* Notification / Action feedback */}\n      {actionFeedback && (\n        <div className=\"bg-primary/10 text-primary border-primary/20 flex items-center justify-between rounded-lg border px-4 py-2.5 text-xs font-medium transition-colors\">\n          <div className=\"flex items-center gap-2\">\n            <CheckCircle2 className=\"size-4 shrink-0\" />\n            <span>{actionFeedback}</span>\n          </div>\n          <Button\n            aria-label=\"Dismiss notification\"\n            variant=\"ghost\"\n            size=\"xs\"\n            className=\"h-6 px-2 text-xs\"\n            onClick={() => setActionFeedback(null)}\n          >\n            Dismiss\n          </Button>\n        </div>\n      )}\n\n      {/* Virtual Card Visual Hero */}\n      <Card className=\"border-border bg-card shadow-xs\">\n        <CardHeader className=\"border-b pb-4\">\n          <div className=\"flex flex-wrap items-center justify-between gap-2\">\n            <div>\n              <div className=\"flex items-center gap-2\">\n                <CardTitle className=\"text-base font-semibold\">{selectedCard.name}</CardTitle>\n                <Badge wrap variant={selectedCard.status === 'Active' ? 'success' : 'warning'} className=\"text-xs\">\n                  {selectedCard.status}\n                </Badge>\n              </div>\n              <CardDescription className=\"mt-0.5 text-xs\">\n                {selectedCard.purpose} · {selectedCard.billingCycle}\n              </CardDescription>\n            </div>\n            <Badge wrap variant=\"outline\" className=\"font-mono text-xs\">\n              Ending in {selectedCard.last4}\n            </Badge>\n          </div>\n        </CardHeader>\n\n        <CardContent className=\"pt-6\">\n          <div className=\"grid gap-6 lg:grid-cols-12 lg:items-center\">\n            {/* Stylized Dark Credit Card Container */}\n            <div className=\"lg:col-span-6 xl:col-span-5\">\n              <div\n                className={cn(\n                  'relative aspect-[1.586/1] w-full rounded-2xl p-6 text-white transition-[filter] duration-300 lg:max-w-[420px]',\n                  'border border-zinc-700/60 bg-gradient-to-br from-zinc-900 via-neutral-900 to-zinc-950 shadow-xl',\n                  isSelectedFrozen && 'contrast-95 grayscale filter',\n                )}\n              >\n                {/* Ambient light accents */}\n                <div\n                  className=\"bg-chart-1/15 pointer-events-none absolute -top-16 -right-16 size-48 rounded-full blur-2xl\"\n                  aria-hidden=\"true\"\n                />\n                <div\n                  className=\"bg-success/10 pointer-events-none absolute -bottom-16 -left-16 size-48 rounded-full blur-2xl\"\n                  aria-hidden=\"true\"\n                />\n\n                {/* Frozen watermark overlay */}\n                {isSelectedFrozen && (\n                  <div className=\"absolute inset-0 z-20 flex flex-col items-center justify-center gap-2 rounded-2xl bg-zinc-950/70 backdrop-blur-xs\">\n                    <div className=\"border-warning/40 bg-warning/20 text-warning inline-flex items-center gap-1.5 rounded-full border px-3 py-1 text-xs font-semibold tracking-wider uppercase\">\n                      <Snowflake className=\"size-3.5\" />\n                      Card Frozen\n                    </div>\n                    <p className=\"text-muted-foreground text-xs\">Transactions are currently blocked</p>\n                  </div>\n                )}\n\n                {/* Top Row: Chip & Contactless + Brand Logo */}\n                <div className=\"relative z-10 flex items-center justify-between\">\n                  <div className=\"flex items-center gap-3\">\n                    {/* Metallic EMV Chip */}\n                    <div\n                      className=\"border-warning/20/40 relative flex h-8 w-11 items-center justify-center rounded-md border bg-gradient-to-br from-amber-200/30 via-amber-400/20 to-amber-600/30 shadow-inner\"\n                      aria-hidden=\"true\"\n                    >\n                      <div className=\"border-warning/20/30 absolute inset-0 grid grid-cols-3 grid-rows-2\">\n                        <div className=\"border-warning/30 border-r border-b\" />\n                        <div className=\"border-warning/30 border-r border-b\" />\n                        <div className=\"border-warning/30 border-b\" />\n                        <div className=\"border-warning/30 border-r\" />\n                        <div className=\"border-warning/30 border-r\" />\n                        <div />\n                      </div>\n                    </div>\n\n                    {/* NFC Wave icon */}\n                    <div className=\"text-muted-foreground/80 rotate-90\" aria-hidden=\"true\">\n                      <Radio className=\"size-4\" />\n                    </div>\n                  </div>\n\n                  {/* Brand Indicator */}\n                  <div className=\"flex items-center gap-2\">\n                    <span className=\"text-muted-foreground font-mono text-xs font-medium tracking-wider uppercase\">\n                      Virtual\n                    </span>\n                    {selectedCard.brand === 'mastercard' ? (\n                      <div className=\"flex -space-x-2\" aria-label=\"Mastercard\">\n                        <div className=\"bg-destructive/90 size-6 rounded-full\" />\n                        <div className=\"bg-warning/90 size-6 rounded-full mix-blend-screen\" />\n                      </div>\n                    ) : (\n                      <div className=\"text-base font-bold tracking-widest text-zinc-100 italic\" aria-label=\"Visa\">\n                        VISA\n                      </div>\n                    )}\n                  </div>\n                </div>\n\n                {/* Middle Row: Card Number & Quick Actions */}\n                <div className=\"relative z-10 my-auto pt-4\">\n                  <div className=\"flex items-center justify-between gap-2\">\n                    <p className=\"font-mono text-lg font-medium tracking-[0.16em] text-zinc-100 tabular-nums drop-shadow-sm sm:text-xl\">\n                      {showDetails ? selectedCard.fullNumber : `•••• •••• •••• ${selectedCard.last4}`}\n                    </p>\n                    <div className=\"flex items-center gap-1\">\n                      <Button\n                        variant=\"ghost\"\n                        size=\"icon-sm\"\n                        className=\"size-7 text-zinc-300 hover:bg-white/10 hover:text-white\"\n                        aria-label={showDetails ? 'Hide card number' : 'Reveal card number'}\n                        onClick={() => setShowDetails(!showDetails)}\n                      >\n                        {showDetails ? <EyeOff className=\"size-3.5\" /> : <Eye className=\"size-3.5\" />}\n                      </Button>\n                      <Button\n                        variant=\"ghost\"\n                        size=\"icon-sm\"\n                        className=\"size-7 text-zinc-300 hover:bg-white/10 hover:text-white\"\n                        aria-label=\"Copy card number\"\n                        onClick={handleCopyNumber}\n                      >\n                        {copied ? <Check className=\"text-success size-3.5\" /> : <Copy className=\"size-3.5\" />}\n                      </Button>\n                    </div>\n                  </div>\n                </div>\n\n                {/* Bottom Row: Cardholder, Expiry, CVV */}\n                <div className=\"relative z-10 flex items-end justify-between pt-2\">\n                  <div className=\"space-y-0.5\">\n                    <p className=\"text-muted-foreground font-mono text-xs tracking-wider uppercase\">Cardholder</p>\n                    <p className=\"max-w-[140px] truncate text-xs font-semibold tracking-wide text-zinc-200 uppercase\">\n                      {selectedCard.holder}\n                    </p>\n                  </div>\n\n                  <div className=\"space-y-0.5\">\n                    <p className=\"text-muted-foreground font-mono text-xs tracking-wider uppercase\">Expires</p>\n                    <p className=\"font-mono text-xs font-medium text-zinc-200 tabular-nums\">{selectedCard.expiry}</p>\n                  </div>\n\n                  <div className=\"space-y-0.5 text-right\">\n                    <p className=\"text-muted-foreground font-mono text-xs tracking-wider uppercase\">CVV</p>\n                    <p className=\"font-mono text-xs font-medium text-zinc-200 tabular-nums\">\n                      {showDetails ? selectedCard.cvv : '•••'}\n                    </p>\n                  </div>\n                </div>\n              </div>\n            </div>\n\n            {/* Card Controls & Spending Breakdown */}\n            <div className=\"space-y-6 lg:col-span-6 xl:col-span-7\">\n              {/* Spending Limit Meter */}\n              <div className=\"border-border bg-muted/30 space-y-3 rounded-lg border p-4\">\n                <div className=\"flex items-center justify-between\">\n                  <span className=\"text-sm font-medium\">Monthly Spending Limit</span>\n                  <span className=\"text-muted-foreground font-mono text-xs tabular-nums\">\n                    ${selectedCard.spent.toLocaleString()} / ${selectedCard.limit.toLocaleString()}\n                  </span>\n                </div>\n\n                <Progress value={selectedPercent} className=\"h-2\" />\n\n                <div className=\"text-muted-foreground flex items-center justify-between text-xs\">\n                  <span className=\"text-foreground font-medium tabular-nums\">\n                    ${Math.max(0, selectedCard.limit - selectedCard.spent).toLocaleString()} available\n                  </span>\n                  <span className=\"font-medium tabular-nums\">{selectedPercent}% utilized</span>\n                </div>\n              </div>\n\n              {/* Card Controls Row */}\n              <div className=\"grid gap-3 sm:grid-cols-3\">\n                {/* Freeze Card Toggle */}\n                <div className=\"border-border bg-card flex items-center justify-between rounded-lg border p-3 sm:flex-col sm:items-start sm:justify-between sm:gap-2\">\n                  <div className=\"space-y-0.5\">\n                    <p className=\"text-foreground text-xs font-medium\">Freeze Card</p>\n                    <p className=\"text-muted-foreground text-xs\">Block charges</p>\n                  </div>\n                  <Switch\n                    checked={isSelectedFrozen}\n                    size=\"sm\"\n                    aria-label=\"Toggle card freeze status\"\n                    onCheckedChange={() => toggleFreeze(selectedCard.id)}\n                  />\n                </div>\n\n                {/* Change Limit Button */}\n                <Button\n                  variant=\"outline\"\n                  size=\"sm\"\n                  className=\"h-auto flex-col items-start gap-1 p-3 text-left\"\n                  onClick={() => adjustLimit(selectedCard.id)}\n                >\n                  <div className=\"flex w-full items-center justify-between\">\n                    <span className=\"text-foreground text-xs font-medium\">Adjust Limit</span>\n                    <SlidersHorizontal className=\"text-muted-foreground size-3.5\" />\n                  </div>\n                  <span className=\"text-muted-foreground text-xs font-normal\">Edit monthly cap</span>\n                </Button>\n\n                {/* Terminate Card Button */}\n                <Button\n                  variant=\"outline\"\n                  size=\"sm\"\n                  className=\"text-destructive hover:text-destructive hover:bg-destructive/10 border-border h-auto flex-col items-start gap-1 p-3 text-left\"\n                  onClick={() => terminateCard(selectedCard.id)}\n                >\n                  <div className=\"flex w-full items-center justify-between\">\n                    <span className=\"text-xs font-medium\">Terminate</span>\n                    <Trash2 className=\"size-3.5\" />\n                  </div>\n                  <span className=\"text-muted-foreground text-xs font-normal\">Close permanently</span>\n                </Button>\n              </div>\n\n              {/* Card Meta Specs */}\n              <div className=\"grid grid-cols-2 gap-3 pt-1 sm:grid-cols-3\">\n                <div className=\"space-y-0.5\">\n                  <span className=\"text-muted-foreground text-xs\">Cardholder</span>\n                  <div className=\"flex items-center gap-1.5 pt-0.5\">\n                    <Avatar size=\"xs\" className=\"size-4.5\">\n                      <AvatarImage src={selectedCard.avatar} alt={selectedCard.holder} />\n                      <AvatarFallback className=\"text-xs\">{selectedCard.initials}</AvatarFallback>\n                    </Avatar>\n                    <span className=\"truncate text-xs font-medium\">{selectedCard.holder}</span>\n                  </div>\n                </div>\n\n                <div className=\"space-y-0.5\">\n                  <span className=\"text-muted-foreground text-xs\">Card Type</span>\n                  <p className=\"text-foreground text-xs font-medium\">{selectedCard.type}</p>\n                </div>\n\n                <div className=\"space-y-0.5\">\n                  <span className=\"text-muted-foreground text-xs\">Fraud Protection</span>\n                  <div className=\"text-success flex items-center gap-1 text-xs font-medium\">\n                    <ShieldCheck className=\"size-3.5\" />\n                    <span>3D Secure Active</span>\n                  </div>\n                </div>\n              </div>\n            </div>\n          </div>\n        </CardContent>\n      </Card>\n\n      {/* Active Cards Grid / Table */}\n      <Card className=\"border-border bg-card shadow-xs\">\n        <CardHeader className=\"border-b pb-4\">\n          <div className=\"flex items-center justify-between\">\n            <div>\n              <CardTitle className=\"text-base font-semibold\">Active Cards List</CardTitle>\n              <CardDescription className=\"mt-0.5 text-xs\">\n                All company virtual cards currently assigned to team members and services.\n              </CardDescription>\n            </div>\n            <Badge wrap variant=\"outline\" className=\"font-mono text-xs tabular-nums\">\n              {cards.length} Issued\n            </Badge>\n          </div>\n        </CardHeader>\n\n        <CardContent className=\"p-0\">\n          <div className=\"divide-border divide-y\">\n            {cards.map((card) => (\n              <div\n                key={card.id}\n                className={cn(\n                  'group flex flex-col gap-4 p-4 transition-colors sm:flex-row sm:items-center sm:justify-between',\n                  selectedId === card.id ? 'bg-muted/40' : 'hover:bg-muted/20',\n                )}\n              >\n                {/* Card Identity & Number */}\n                <div className=\"flex min-w-0 items-center gap-3.5 sm:w-1/3\">\n                  <div\n                    className={cn(\n                      'border-border flex size-10 shrink-0 items-center justify-center rounded-lg border shadow-xs transition-transform',\n                      card.status === 'Frozen' ? 'bg-muted/60 text-muted-foreground' : 'bg-primary/10 text-primary',\n                    )}\n                  >\n                    <CreditCard className=\"size-5\" />\n                  </div>\n\n                  <div className=\"min-w-0 flex-1 space-y-0.5\">\n                    <div className=\"flex items-center gap-2\">\n                      <p className=\"text-foreground truncate text-sm font-medium\">{card.name}</p>\n                    </div>\n                    <div className=\"text-muted-foreground flex items-center gap-2 text-xs\">\n                      <span className=\"font-mono tabular-nums\">•••• {card.last4}</span>\n                      <span>·</span>\n                      <span className=\"uppercase\">{card.brand}</span>\n                    </div>\n                  </div>\n                </div>\n\n                {/* Cardholder Avatar & Name */}\n                <div className=\"flex items-center gap-2 sm:w-1/5\">\n                  <Avatar size=\"sm\">\n                    <AvatarImage src={card.avatar} alt={card.holder} />\n                    <AvatarFallback>{card.initials}</AvatarFallback>\n                  </Avatar>\n                  <div className=\"min-w-0\">\n                    <p className=\"text-foreground truncate text-xs font-medium\">{card.holder}</p>\n                    <p className=\"text-muted-foreground truncate text-xs\">{card.type}</p>\n                  </div>\n                </div>\n\n                {/* Spending Limit & Progress */}\n                <div className=\"space-y-1.5 sm:w-1/4\">\n                  <div className=\"flex items-center justify-between text-xs\">\n                    <span className=\"text-foreground font-mono font-medium tabular-nums\">\n                      ${card.spent.toLocaleString()} / ${card.limit.toLocaleString()}\n                    </span>\n                    <span className=\"text-muted-foreground font-mono tabular-nums\">\n                      {Math.round((card.spent / card.limit) * 100)}%\n                    </span>\n                  </div>\n                  <Progress value={Math.min(100, Math.round((card.spent / card.limit) * 100))} className=\"h-1.5\" />\n                </div>\n\n                {/* Status Badge & Actions */}\n                <div className=\"flex items-center justify-between gap-3 sm:justify-end\">\n                  <Badge wrap variant={card.status === 'Active' ? 'success' : 'warning'} className=\"text-xs\">\n                    {card.status}\n                  </Badge>\n\n                  <div className=\"flex items-center gap-1.5\">\n                    <Button\n                      variant={selectedId === card.id ? 'secondary' : 'ghost'}\n                      size=\"sm\"\n                      className=\"text-xs\"\n                      onClick={() => setSelectedId(card.id)}\n                    >\n                      {selectedId === card.id ? 'Viewing' : 'View Card'}\n                    </Button>\n\n                    <Button\n                      variant=\"ghost\"\n                      size=\"icon-sm\"\n                      aria-label={card.status === 'Active' ? 'Freeze card' : 'Unfreeze card'}\n                      onClick={() => toggleFreeze(card.id)}\n                    >\n                      {card.status === 'Active' ? (\n                        <Snowflake className=\"text-muted-foreground size-4\" />\n                      ) : (\n                        <Zap className=\"text-warning size-4\" />\n                      )}\n                    </Button>\n                  </div>\n                </div>\n              </div>\n            ))}\n          </div>\n        </CardContent>\n      </Card>\n    </div>\n  )\n}\n",
      "type": "registry:block",
      "target": "~/components/blocks/VirtualCardManager.tsx"
    }
  ],
  "dependencies": [
    "lucide-react"
  ],
  "devDependencies": [],
  "registryDependencies": [
    "https://uipkge.dev/r/react/avatar.json",
    "https://uipkge.dev/r/react/badge.json",
    "https://uipkge.dev/r/react/button.json",
    "https://uipkge.dev/r/react/card.json",
    "https://uipkge.dev/r/react/progress.json",
    "https://uipkge.dev/r/react/switch.json"
  ],
  "description": "Mercury/Ramp-style corporate virtual card manager: interactive dark credit card visual hero with EMV chip, revealable credentials, live spending limit progress bar, instant freeze toggles, limit adjusters, and an active virtual cards table.",
  "categories": [
    "finance",
    "app",
    "billing"
  ]
}