Visual catalog of 17 animations used in the Orbuculum onboarding prototype
@keyframes blurIn {
0% {
opacity: 0;
filter: blur(16px);
transform: scale(0.96);
}
100% {
opacity: 1;
filter: blur(0px);
transform: scale(1);
}
}
@keyframes fadeIn {
0% {
opacity: 0;
filter: blur(8px);
transform: scale(0.95);
}
70% {
transform: scale(1.02);
}
100% {
opacity: 1;
filter: blur(0px);
transform: scale(1);
}
}
@keyframes welcomeOut {
0% {
opacity: 1;
transform: scale(1);
filter: blur(0px);
}
100% {
opacity: 0;
transform: scale(1.03);
filter: blur(10px);
}
}
@keyframes messageIn {
0% {
opacity: 0;
transform: translateY(16px) scale(0.98);
filter: blur(3px);
}
100% {
opacity: 1;
transform: translateY(0) scale(1);
filter: blur(0px);
}
}
@keyframes userMessageIn {
0% {
opacity: 0;
transform: translateX(12px) scale(0.98);
}
100% {
opacity: 1;
transform: translateX(0) scale(1);
}
}
@keyframes typingDot {
0%, 60%, 100% {
opacity: 0.3;
transform: translateY(0);
}
30% {
opacity: 1;
transform: translateY(-4px);
}
}
/* Stagger delays */
span:nth-child(2) { animation-delay: 0.2s; }
span:nth-child(3) { animation-delay: 0.4s; }
@keyframes chatIn {
0% {
opacity: 0;
transform: translateY(20px);
}
100% {
opacity: 1;
transform: translateY(0);
}
}
@keyframes tabSlideIn {
0% {
opacity: 0;
transform: translateX(20px);
filter: blur(4px);
}
100% {
opacity: 1;
transform: translateX(0);
filter: blur(0);
}
}
@keyframes fadeSlideIn {
0% {
opacity: 0;
transform: translateY(12px) scale(0.97);
}
100% {
opacity: 0.7;
transform: translateY(0) scale(1);
}
}
@keyframes insightPop {
0% { transform: scale(0); opacity: 0; }
50% { transform: scale(1.5); }
100%{ transform: scale(1); opacity: 1; }
}
/* Standard spinner */
.file-loader {
width: 12px;
height: 12px;
border: 2px solid #2aa7ee;
border-bottom-color: rgba(42, 167, 238, 0.2);
border-radius: 50%;
animation: spin 0.8s linear infinite;
}
@keyframes spin {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
@keyframes progressBar {
from { width: 0; }
to { width: 100%; }
}
.action-btn {
transition: all 0.2s;
}
.action-btn:hover {
background: var(--blue-primary);
color: white;
transform: translateY(-1px);
}
.avatar-circle {
transition: all 0.2s;
}
.avatar-circle:hover {
transform: scale(1.15);
}
.currency-chip.removing {
opacity: 0;
transform: scale(0.8);
transition: all 0.25s ease;
}
.drop-zone {
border: 1px dashed var(--text-dimmed);
transition: all 0.2s;
}
.drop-zone:hover {
border-color: var(--blue-primary);
background: rgba(42,167,238,0.05);
}
function easeInOutCubic(t) {
return t < 0.5
? 4 * t * t * t
: 1 - Math.pow(-2 * t + 2, 3) / 2;
}
// Used in animateScroll(target, 1200)
function animateStats(from, to, dur) {
const start = performance.now();
function tick(now) {
const p = Math.min((now - start) / dur, 1);
const eased = 1 - Math.pow(1 - p, 3);
// easeOutCubic
el.textContent = Math.round(
from + (to - from) * eased
);
if (p < 1) requestAnimationFrame(tick);
}
requestAnimationFrame(tick);
}
@property --grad-angle {
syntax: '<angle>';
initial-value: 94deg;
inherits: false;
}
@keyframes spin-main-gradient {
from { --grad-angle: 94deg; }
to { --grad-angle: 454deg; }
}
.choice-btn.is-active {
border: 1px solid transparent;
background:
linear-gradient(var(--bg), var(--bg)) padding-box,
linear-gradient(var(--grad-angle), #00f0ff 0%, #1da5f1 100%) border-box;
}
.choice-btn.is-active:hover {
animation: spin-main-gradient 3s linear infinite;
}
.choice-btn:hover {
transform: scale(1.02);
}
overflow: visible on the parent prevents the rotating shackle from being clipped by the viewBox..welcome-lock {
perspective: 600px;
transform-style: preserve-3d;
overflow: visible;
}
.welcome-lock .lock-shackle {
transform-origin: 100% 50%;
transform-box: fill-box;
}
@keyframes lockShackleOpen {
0% { transform: translateY(0) rotateY(0); }
30% { transform: translateY(-4px) rotateY(0); }
100% { transform: translateY(-4px) rotateY(45deg); }
}
@keyframes lockBodyPulse {
0% { transform: scale(1); }
30% { transform: scale(1); }
45% { transform: scale(1.06); }
100% { transform: scale(1); }
}
.welcome-lock.animate-in .lock-shackle {
animation: lockShackleOpen 1.4s cubic-bezier(0.22, 1, 0.36, 1) 0.3s forwards;
}
.welcome-lock.animate-in .lock-body {
animation: lockBodyPulse 1.4s cubic-bezier(0.22, 1, 0.36, 1) 0.3s forwards;
}