Commit 02573701 authored by Mahmoud Aglan's avatar Mahmoud Aglan

feat: game-feel animations — bounce, shake, pop, coin fly, slide up

- Scene transitions: scale+slide (game-like) instead of horizontal slide (web-like)
- Buttons: more aggressive scale on press (0.92 in 50ms)
- Cards: snappier press response (0.96 in 80ms)
- New animation classes: .shake, .pop-in, .bounce-in, .slide-up
- Toast: spring bounce entrance, reward/error variants
- Keyframes: coinFly, bounceIn, popIn, shake for game events
Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
parent 8a856349
......@@ -80,15 +80,18 @@ html, body {
padding: var(--s-3) var(--s-4);
color: var(--text-primary);
font-size: 14px;
box-shadow: var(--shadow-md);
animation: toastIn var(--dur-normal) var(--ease-spring);
font-weight: 600;
box-shadow: var(--shadow-lg);
animation: toastIn 0.4s cubic-bezier(0.34, 1.56, 0.64, 1);
pointer-events: all;
}
.toast.out { animation: toastOut var(--dur-fast) ease-in forwards; }
.toast.out { animation: toastOut 0.2s ease-in forwards; }
.toast.reward { background: linear-gradient(135deg, #1a2440, #2a1a40); border-color: var(--gold); }
.toast.error { border-color: var(--error); }
@keyframes toastIn { from { opacity: 0; transform: translateY(-20px) scale(0.9); } }
@keyframes toastOut { to { opacity: 0; transform: translateY(-10px) scale(0.95); } }
@keyframes toastIn { from { opacity: 0; transform: translateY(-30px) scale(0.8); } }
@keyframes toastOut { to { opacity: 0; transform: translateY(-15px) scale(0.9); } }
/* Tab Bar */
.tab-bar {
......@@ -130,7 +133,7 @@ html, body {
fill: currentColor;
}
/* Scene transitions */
/* Scene transitions - game feel */
.scene {
position: absolute;
inset: 0;
......@@ -141,16 +144,11 @@ html, body {
-webkit-overflow-scrolling: touch;
}
.scene-enter { animation: sceneIn var(--dur-normal) var(--ease-out); }
.scene-exit { animation: sceneOut var(--dur-fast) ease-in forwards; }
@keyframes sceneIn { from { opacity: 0; transform: translateX(-30px); } }
@keyframes sceneOut { to { opacity: 0; transform: translateX(30px); } }
.scene-enter { animation: sceneIn 0.35s cubic-bezier(0.16, 1, 0.3, 1); }
.scene-exit { animation: sceneOut 0.2s ease-in forwards; }
[dir="rtl"] .scene-enter { animation-name: sceneInRtl; }
[dir="rtl"] .scene-exit { animation-name: sceneOutRtl; }
@keyframes sceneInRtl { from { opacity: 0; transform: translateX(30px); } }
@keyframes sceneOutRtl { to { opacity: 0; transform: translateX(-30px); } }
@keyframes sceneIn { from { opacity: 0; transform: scale(0.95) translateY(20px); } }
@keyframes sceneOut { to { opacity: 0; transform: scale(1.02); } }
/* Cards */
.card {
......@@ -162,7 +160,7 @@ html, body {
transition: transform var(--dur-fast) var(--ease-spring), box-shadow var(--dur-fast);
}
.card:active { transform: scale(0.97); box-shadow: var(--shadow-md); }
.card:active { transform: scale(0.96); box-shadow: var(--shadow-md); transition-duration: 80ms; }
/* Buttons */
.btn {
......@@ -181,7 +179,7 @@ html, body {
min-height: 44px;
}
.btn:active { transform: scale(0.95); }
.btn:active { transform: scale(0.92); transition-duration: 50ms; }
.btn-primary {
background: linear-gradient(135deg, var(--gold), var(--gold-soft));
......@@ -313,13 +311,22 @@ html, body {
@keyframes shimmer { 0% { background-position: 200% 0; } 100% { background-position: -200% 0; } }
/* Pulse animation for "always alive" */
/* Game-feel animations */
@keyframes pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.6; } }
@keyframes float { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-4px); } }
@keyframes float { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-6px); } }
@keyframes glow { 0%, 100% { box-shadow: 0 0 5px var(--gold); } 50% { box-shadow: 0 0 20px var(--gold); } }
@keyframes shake { 0%,100% { transform: translateX(0); } 20% { transform: translateX(-3px); } 40% { transform: translateX(3px); } 60% { transform: translateX(-2px); } 80% { transform: translateX(2px); } }
@keyframes popIn { 0% { transform: scale(0); opacity: 0; } 60% { transform: scale(1.15); } 100% { transform: scale(1); opacity: 1; } }
@keyframes coinFly { 0% { transform: translateY(0) scale(1); opacity: 1; } 100% { transform: translateY(-60px) scale(0.5); opacity: 0; } }
@keyframes slideUp { from { transform: translateY(100%); } to { transform: translateY(0); } }
@keyframes bounceIn { 0% { transform: scale(0.3); opacity: 0; } 50% { transform: scale(1.1); } 70% { transform: scale(0.9); } 100% { transform: scale(1); opacity: 1; } }
.pulse { animation: pulse 2s ease-in-out infinite; }
.float { animation: float 3s ease-in-out infinite; }
.shake { animation: shake 0.4s ease; }
.pop-in { animation: popIn 0.4s cubic-bezier(0.34, 1.56, 0.64, 1); }
.bounce-in { animation: bounceIn 0.5s cubic-bezier(0.34, 1.56, 0.64, 1); }
.slide-up { animation: slideUp 0.3s cubic-bezier(0.16, 1, 0.3, 1); }
/* Scrollbar */
::-webkit-scrollbar { width: 4px; }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment