Goal: Create a "Tilt 3D" button animation using Framer Motion.
Visual behavior: As the cursor moves across the button, it rotates in 3D perspective — tilting toward the cursor using rotateX/rotateY. A blurred white orb (the "sheen") follows the cursor inside the button as a specular highlight. On hover, a deep purple drop-shadow expands beneath the button giving it depth. On leave, everything springs back to neutral.
Technique: Use useMotionValue for rawX/rawY (normalized -0.5 to 0.5 relative to button center). useTransform maps rawX → rotateY (-14 to 14 deg) and rawY → rotateX (14 to -14 deg). useSpring smooths the rotation (stiffness: 200, damping: 20). A motion.span inside the button uses the same rawX/rawY mapped to left/top via useTransform to position the sheen orb. The button uses transformPerspective: 600 and transformStyle: 'preserve-3d'. Wrap sheen visibility with a hovered state (useState). Disable all transforms via useReducedMotion.
Accessibility: useReducedMotion from framer-motion disables rotateX, rotateY, and the sheen when prefers-reduced-motion is set.
My stack: {{USER_STACK}}
My styling: {{USER_STYLING}}
My constraints: {{USER_CONSTRAINTS}}
Return a single self-contained component. Requires framer-motion.
Paste into Claude, ChatGPT, or Cursor. Edit YOUR_STACK /
YOUR_STYLING / YOUR_CONSTRAINTS before sending.