@keyframes dhikrBump {
  0% { transform: scale(1); }
  30% { transform: scale(1.06); }
  100% { transform: scale(1); }
}
@keyframes numberBurst {
  0% { transform: scale(1.25); opacity: .4; }
  100% { transform: scale(1); opacity: 1; }
}
@keyframes ripple {
  0% { transform: scale(.3); opacity: .5; }
  100% { transform: scale(1.7); opacity: 0; }
}
@keyframes breathe {
  0%, 100% { transform: scale(1); }
  50% { transform: scale(1.015); }
}
@keyframes ambientFloat {
  0%, 100% { transform: translate(0, 0); }
  50% { transform: translate(10px, -14px); }
}
@keyframes heatmapFadeIn {
  from { opacity: 0; transform: scale(.6); }
  to { opacity: 1; transform: scale(1); }
}
@keyframes screenFade {
  from { opacity: 0; transform: translateY(6px); }
  to { opacity: 1; transform: translateY(0); }
}
@keyframes slideUp {
  from { opacity: 0; transform: translateY(16px); }
  to { opacity: 1; transform: translateY(0); }
}

.anim-bump { animation: dhikrBump .3s ease; }
.anim-burst { animation: numberBurst .25s ease; }
.anim-breathe { animation: breathe 4s ease-in-out infinite; }
.anim-float { animation: ambientFloat 24s ease-in-out infinite; }
.screen-enter { animation: screenFade .2s ease; }
.install-banner { animation: slideUp .3s ease; }

@media (prefers-reduced-motion: reduce) {
  .anim-breathe, .anim-float { animation: none; }
  .screen-enter, .install-banner { animation: none; }
}
