{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "organic-card-small",
  "type": "registry:ui",
  "description": "Compact card with SVG silhouette, category and date, motion morph on hover, and optional link",
  "dependencies": [
    "lucide-react",
    "motion"
  ],
  "files": [
    {
      "path": "registry/default/ui/organic-card-small.tsx",
      "content": "\"use client\"\n\nimport { useId, useState } from \"react\"\nimport Image from \"next/image\"\nimport { ArrowRight } from \"lucide-react\"\nimport { motion, useReducedMotion } from \"motion/react\"\n\nimport { cn } from \"@/lib/utils\"\n\nconst PATH_IDLE =\n  \"M670 0H0V91C0 102.046 8.9543 111 20 111H518.641C526.216 111 533.14 106.721 536.529 99.9469L570.988 31.0531C574.377 24.2789 581.301 20 588.875 20H650C661.046 20 670 11.0457 670 0Z\"\nconst PATH_HOVER =\n  \"M670 0H0V91C0 102.046 8.9543 111 20 111H518.641C526.216 111 533.14 111 536.529 111L570.988 111C574.377 111 581.301 111 588.875 111H650C661.046 111 670 102.046 670 91Z\"\n\nconst SURFACE = \"#f0eee9\"\n\n/** drop-shadow follows painted alpha (organic cutout); box-shadow only follows the border box. */\nconst SILHOUETTE_SHADOW =\n  \"drop-shadow(0px 0px 0px rgba(0,0,0,0.06)) drop-shadow(0px 1px 2px -1px rgba(0,0,0,0.06)) drop-shadow(0px 2px 4px 0px rgba(0,0,0,0.04))\"\nconst SILHOUETTE_SHADOW_HOVER =\n  \"drop-shadow(0px 0px 0px rgba(0,0,0,0.08)) drop-shadow(0px 2px 4px -1px rgba(0,0,0,0.08)) drop-shadow(0px 4px 8px 0px rgba(0,0,0,0.06))\"\n\ninterface OrganicCardSmallProps {\n  image: string\n  imageAlt?: string\n  category: string\n  date: string\n  title: string\n  href?: string\n  className?: string\n  /** Card body + band fill (defaults to stone) */\n  surfaceColor?: string\n}\n\nexport function OrganicCardSmall({\n  image,\n  imageAlt = \"Card image\",\n  category,\n  date,\n  title,\n  href = \"#\",\n  className,\n  surfaceColor = SURFACE,\n}: OrganicCardSmallProps) {\n  const reduceMotion = useReducedMotion()\n  const cutoutTitleId = useId()\n  const [pointerOver, setPointerOver] = useState(false)\n  const [focused, setFocused] = useState(false)\n  /** Cutout + arrow read as “active” for pointer hover or keyboard focus (not only one). */\n  const interactiveActive = pointerOver || focused\n\n  const pathTransition = reduceMotion\n    ? { duration: 0.12, ease: [0.23, 1, 0.32, 1] as const }\n    : { type: \"spring\" as const, duration: 0.38, bounce: 0 }\n\n  return (\n    <motion.a\n      aria-labelledby={cutoutTitleId}\n      className={cn(\n        \"group/calloutCard relative flex h-full w-full max-w-[617px] flex-col rounded-2xl\",\n        \"cursor-pointer outline-none\",\n        \"focus-visible:outline-2 focus-visible:outline-ring focus-visible:outline-offset-2\",\n        className\n      )}\n      data-state={interactiveActive ? \"active\" : \"idle\"}\n      href={href}\n      onBlur={() => setFocused(false)}\n      onFocus={() => setFocused(true)}\n      onMouseEnter={() => setPointerOver(true)}\n      onMouseLeave={() => setPointerOver(false)}\n      transition={{ type: \"spring\", duration: 0.28, bounce: 0 }}\n      whileTap={reduceMotion ? undefined : { scale: 0.98 }}\n    >\n      {/* Shadow on this shell only — filter drop-shadow follows opaque pixels (incl. cutout curve), not a rounded rect */}\n      <div\n        className={cn(\n          \"isolate w-full transition-[filter] duration-200 ease-out\",\n          reduceMotion && \"transition-none\"\n        )}\n        style={{\n          filter: interactiveActive\n            ? SILHOUETTE_SHADOW_HOVER\n            : SILHOUETTE_SHADOW,\n        }}\n      >\n        <div\n          className=\"flex w-full flex-1 flex-col justify-between rounded-t-2xl p-4 text-stone-900\"\n          style={{ backgroundColor: SURFACE }}\n        >\n          <div>\n            <div className=\"relative mb-5 overflow-hidden rounded-lg\">\n              <Image\n                alt={imageAlt}\n                className={cn(\n                  \"h-[138px] w-full origin-center object-cover sm:h-[168px]\",\n                  \"[outline-offset:-1px] [outline:1px_solid_rgba(0,0,0,0.08)]\",\n                  \"transition-transform duration-[220ms] ease-out\",\n                  \"motion-reduce:scale-100 motion-reduce:transition-none\",\n                  \"[@media(hover:hover)]:group-data-[state=active]/calloutCard:scale-[1.02]\"\n                )}\n                height={208}\n                src={image}\n                width={670}\n              />\n            </div>\n            <p className=\"mb-5 font-medium text-stone-600 text-xs uppercase tracking-wider\">\n              <span className=\"text-pretty\">\n                {category}\n                {\" — \"}\n                <time className=\"tabular-nums\">{date}</time>\n              </span>\n            </p>\n            <h3\n              className=\"mb-2 text-balance font-normal text-xl lg:text-2xl\"\n              id={cutoutTitleId}\n            >\n              {title}\n            </h3>\n          </div>\n        </div>\n\n        <svg\n          aria-hidden\n          className=\"-mt-px -mr-px h-[80px] w-full shrink-0 sm:h-[111px]\"\n          preserveAspectRatio=\"none\"\n          viewBox=\"0 0 670 111\"\n          xmlns=\"http://www.w3.org/2000/svg\"\n        >\n          <title>Card footer cutout background</title>\n          <motion.path\n            animate={{ d: interactiveActive ? PATH_HOVER : PATH_IDLE }}\n            fill={surfaceColor}\n            initial={false}\n            transition={pathTransition}\n          />\n        </svg>\n      </div>\n\n      <div className=\"pointer-events-none absolute bottom-3 left-4 md:bottom-4\">\n        <p className=\"text-base text-stone-900 lg:text-lg\">Read more</p>\n      </div>\n\n      <div className=\"pointer-events-none absolute right-4 bottom-4\">\n        <motion.span\n          animate={\n            reduceMotion\n              ? { x: 0, opacity: 1 }\n              : { x: interactiveActive ? 4 : 0, opacity: 1 }\n          }\n          className=\"inline-flex\"\n          transition={\n            reduceMotion\n              ? { duration: 0.12 }\n              : { type: \"spring\", duration: 0.32, bounce: 0 }\n          }\n        >\n          <ArrowRight\n            aria-hidden\n            className=\"h-5 w-5 text-stone-900\"\n            strokeWidth={2}\n          />\n        </motion.span>\n      </div>\n    </motion.a>\n  )\n}\n",
      "type": "registry:ui"
    }
  ]
}