{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "card-stack",
  "title": "Card Stack",
  "description": "Deck that shuffles the top card to the back on a timer.",
  "dependencies": [
    "motion"
  ],
  "registryDependencies": [
    "utils"
  ],
  "files": [
    {
      "path": "src/components/velora/card-stack.tsx",
      "content": "\"use client\";\n\nimport { useEffect, useRef, useState } from \"react\";\nimport { motion, useReducedMotion } from \"motion/react\";\n\nimport { cn } from \"@/lib/utils\";\n\ninterface CardStackProps {\n  /** Each entry becomes one card; the first is on top */\n  items: { id: string | number; content: React.ReactNode }[];\n  /** Seconds between automatic shuffles; 0 disables */\n  interval?: number;\n  /** Vertical offset per card, in px */\n  offset?: number;\n  className?: string;\n}\n\n/**\n * Deck of cards that shuffles the top card to the back. Good for rotating\n * quotes or tips in a fixed-height slot.\n */\nexport function CardStack({\n  items,\n  interval = 4,\n  offset = 12,\n  className,\n}: CardStackProps) {\n  // Rotation is a single counter, so card order stays derived from props —\n  // no copy of `items` in state to keep in sync.\n  const [shift, setShift] = useState(0);\n  const reducedMotion = useReducedMotion();\n  const count = items.length;\n  // Held while hovered or focused so the top card can be read (WCAG 2.2.2).\n  const paused = useRef(false);\n\n  useEffect(() => {\n    // Reduced motion: no auto-shuffle, the first card stays on top.\n    if (!interval || count < 2 || reducedMotion !== false) return;\n    const id = window.setInterval(() => {\n      if (paused.current || document.hidden) return;\n      setShift((value) => value + 1);\n    }, interval * 1000);\n    return () => window.clearInterval(id);\n  }, [interval, count, reducedMotion]);\n\n  const pause = () => {\n    paused.current = true;\n  };\n  const resume = () => {\n    paused.current = false;\n  };\n\n  return (\n    <div\n      data-slot=\"card-stack\"\n      onMouseEnter={pause}\n      onMouseLeave={resume}\n      onFocus={pause}\n      onBlur={resume}\n      className={cn(\"relative h-56 w-full max-w-sm\", className)}\n    >\n      {items.map((card, i) => {\n        // Where this card currently sits in the deck, 0 = on top.\n        const depth = (i - (shift % count) + count) % count;\n        return (\n          <motion.div\n            key={card.id}\n            initial={false}\n            animate={{\n              top: depth * -offset,\n              scale: 1 - depth * 0.05,\n              zIndex: count - depth,\n            }}\n            transition={\n              reducedMotion\n                ? { duration: 0 }\n                : { type: \"spring\", stiffness: 260, damping: 26 }\n            }\n            className=\"absolute inset-x-0 flex h-56 flex-col justify-between rounded-2xl border bg-card p-5 shadow-xl shadow-foreground/5\"\n          >\n            {card.content}\n          </motion.div>\n        );\n      })}\n    </div>\n  );\n}\n",
      "type": "registry:ui",
      "target": "components/velora/card-stack.tsx"
    }
  ],
  "type": "registry:ui"
}