{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "accordion-fold",
  "description": "A paper map of hinged panels that folds itself up like an accordion and flattens back out.",
  "dependencies": [
    "framer-motion"
  ],
  "files": [
    {
      "path": "registry/new-york/perspective/accordion-fold.tsx",
      "content": "/**\n * A paper map of hinged panels that folds itself up like an accordion and flattens back out.\n */\n\"use client\";\n\nimport { motion, useReducedMotion, type Transition } from \"framer-motion\";\nimport type { ReactNode } from \"react\";\n\nconst PANEL_COUNT = 5;\nconst PANEL_WIDTH = 44;\nconst PANEL_HEIGHT = 104;\nconst FOLD_ANGLE = 80;\n\nconst foldTransition: Transition = {\n  duration: 3.2,\n  ease: \"easeInOut\",\n  repeat: Infinity,\n  repeatDelay: 0.6,\n};\n\nconst PanelArt = ({ index }: { index: number }) => (\n  <div className=\"pointer-events-none absolute inset-0 p-1.5\">\n    <div className=\"h-full w-full border border-dashed border-foreground/20\" />\n    <div\n      className=\"absolute size-1.5 rounded-full bg-foreground/50\"\n      style={{\n        left: `${25 + ((index * 37) % 50)}%`,\n        top: `${20 + ((index * 53) % 60)}%`,\n      }}\n    />\n  </div>\n);\n\nconst AccordionFold = () => {\n  const shouldReduceMotion = useReducedMotion();\n\n  // build the hinge chain from the last panel inward — each panel folds\n  // relative to the previous one\n  let chain: ReactNode = null;\n  for (let i = PANEL_COUNT - 1; i >= 1; i--) {\n    const angle = i % 2 ? -FOLD_ANGLE : FOLD_ANGLE;\n    chain = (\n      <motion.div\n        className=\"absolute top-0 border border-foreground/25 bg-muted\"\n        style={{\n          left: \"100%\",\n          width: PANEL_WIDTH,\n          height: PANEL_HEIGHT,\n          transformOrigin: \"left center\",\n          transformStyle: \"preserve-3d\",\n        }}\n        animate={shouldReduceMotion ? undefined : { rotateY: [0, angle, 0] }}\n        transition={foldTransition}\n      >\n        <PanelArt index={i} />\n        <motion.div\n          className=\"pointer-events-none absolute inset-0 bg-black\"\n          animate={\n            shouldReduceMotion\n              ? undefined\n              : { opacity: [0, i % 2 ? 0.25 : 0.1, 0] }\n          }\n          initial={{ opacity: 0 }}\n          transition={foldTransition}\n        />\n        {chain}\n      </motion.div>\n    );\n  }\n\n  return (\n    <div style={{ perspective: 900 }}>\n      <div\n        style={{\n          transform: `translateX(-${(PANEL_WIDTH * (PANEL_COUNT - 1)) / 2}px) rotateX(12deg) rotateY(-16deg)`,\n          transformStyle: \"preserve-3d\",\n        }}\n      >\n        <div\n          className=\"relative border border-foreground/25 bg-muted\"\n          style={{\n            width: PANEL_WIDTH,\n            height: PANEL_HEIGHT,\n            transformStyle: \"preserve-3d\",\n          }}\n        >\n          <PanelArt index={0} />\n          {chain}\n        </div>\n      </div>\n    </div>\n  );\n};\n\nexport default AccordionFold;\n",
      "type": "registry:component",
      "target": "components/pixel-perfect/accordion-fold.tsx"
    }
  ],
  "type": "registry:block"
}