/* ==========================================================================
   Algo Resize — Animations
   Kept deliberately minimal: motion is used only to confirm an action
   (upload, resize, toast) or ease a state change — never as decoration.
   ========================================================================== */

@keyframes fadeUp {
  from { opacity: 0; transform: translateY(8px); }
  to { opacity: 1; transform: translateY(0); }
}
@keyframes fadeIn {
  from { opacity: 0; }
  to { opacity: 1; }
}
@keyframes shimmer {
  0% { background-position: 200% 0; }
  100% { background-position: -200% 0; }
}
@keyframes slideInRight {
  from { opacity: 0; transform: translateX(20px); }
  to { opacity: 1; transform: translateX(0); }
}
@keyframes slideOutRight {
  from { opacity: 1; transform: translateX(0); }
  to { opacity: 0; transform: translateX(20px); }
}
@keyframes spin {
  to { transform: rotate(360deg); }
}

.hero { animation: fadeUp var(--dur-slow) var(--ease-out) both; }

.card { animation: fadeIn var(--dur-base) var(--ease-out) both; }

.skeleton { animation: shimmer 1.4s linear infinite; }

.toast { animation: slideInRight var(--dur-base) var(--ease-out) both; }
.toast.is-leaving { animation: slideOutRight var(--dur-fast) var(--ease-out) both; }

.spinner {
  width: 18px; height: 18px;
  border-radius: 50%;
  border: 2.5px solid color-mix(in srgb, currentColor 25%, transparent);
  border-top-color: currentColor;
  animation: spin 0.7s linear infinite;
  display: inline-block;
}

.view-transition { animation: fadeIn var(--dur-fast) var(--ease-out) both; }
