feat: polish motion with stronger easing, press feedback and reduced motion

- Override Tailwind ease-out/ease-in-out with stronger curves, add ease-drawer
- hoverOnlyWhenSupported so hover styles never stick on touch devices
- Replace transition-all with explicit properties across the public UI
- Press feedback via active:scale-[0.97] instead of hover:scale-105
- Global prefers-reduced-motion handling (CSS + MotionConfig reducedMotion="user")
- Mobile menu is a real drawer: stays mounted, inert when closed, Escape closes
- Progress and music bars animate scaleX/scaleY instead of width/height
- Fix undefined animate-spin-slow, contain hero CTA shine with overflow-hidden

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
denshooter
2026-10-15 18:31:58 +02:00
parent 8c3c4ec1d0
commit c847a456a3
20 changed files with 178 additions and 123 deletions
+23 -4
View File
@@ -4,6 +4,11 @@ import type { Config } from "tailwindcss";
// tailwind.config.js
export default {
darkMode: "class", // Enables class-based dark mode
// Touch devices fire :hover on tap and keep it stuck; only apply hover styles
// where a real pointer exists.
future: {
hoverOnlyWhenSupported: true,
},
content: [
"./app/**/*.{js,ts,jsx,tsx}",
"./app/components/**/*.{js,ts,jsx,tsx}",
@@ -11,19 +16,33 @@ export default {
],
theme: {
extend: {
// Stronger curves than the CSS defaults. Overriding `out` and `in-out`
// upgrades every existing `ease-out` / `ease-in-out` utility at once.
transitionTimingFunction: {
out: "cubic-bezier(0.23, 1, 0.32, 1)",
"in-out": "cubic-bezier(0.77, 0, 0.175, 1)",
drawer: "cubic-bezier(0.32, 0.72, 0, 1)",
},
keyframes: {
fadeIn: {
"0%": { opacity: "0", transform: "translateY(10px)" },
"0%": { opacity: "0", transform: "translateY(8px)" },
"100%": { opacity: "1", transform: "translateY(0)" },
},
slideDown: {
"0%": { opacity: "0", transform: "translateY(-20px)" },
"0%": { opacity: "0", transform: "translateY(-12px)" },
"100%": { opacity: "1", transform: "translateY(0)" },
},
scrollHint: {
"0%": { opacity: "0", transform: "scaleY(0.4)" },
"40%": { opacity: "1", transform: "scaleY(1)" },
"100%": { opacity: "0", transform: "scaleY(1)" },
},
},
animation: {
"fade-in": "fadeIn 0.5s ease-out",
"slide-down": "slideDown 0.4s ease-out",
"fade-in": "fadeIn 600ms cubic-bezier(0.23, 1, 0.32, 1) both",
"slide-down": "slideDown 500ms cubic-bezier(0.23, 1, 0.32, 1) both",
"scroll-hint": "scrollHint 2.4s cubic-bezier(0.77, 0, 0.175, 1) infinite",
"spin-slow": "spin 4s linear infinite",
},
colors: {
background: "var(--background)",