/* PortionPilot Animation System - Health & Nutrition Focused */

:root {
  /* Timing System - Calm, trustworthy animations for health apps */
  --animation-instant: 100ms;
  --animation-fast: 200ms;
  --animation-normal: 400ms;
  --animation-slow: 600ms;
  --animation-extra-slow: 1000ms;

  /* Easing - Natural, organic curves for health/wellness */
  --ease-organic: cubic-bezier(0.25, 0.46, 0.45, 0.94);
  --ease-bounce-soft: cubic-bezier(0.68, -0.55, 0.265, 1.55);
  --ease-nutrition: cubic-bezier(0.4, 0, 0.2, 1);
  --ease-smooth: cubic-bezier(0.37, 0, 0.63, 1);

  /* Shadow System */
  --shadow-soft: 0 2px 8px rgba(0, 0, 0, 0.08);
  --shadow-medium: 0 4px 12px rgba(0, 0, 0, 0.1);
  --shadow-strong: 0 6px 20px rgba(0, 0, 0, 0.15);
}

/* Base Animation Classes - Performance Optimized */
.fade-animation {
  opacity: 0;
  transform: translateZ(0); /* Force GPU layer */
  transition: opacity var(--animation-normal) var(--ease-nutrition);
  will-change: opacity;
  contain: layout;
}

.fade-animation.show {
  opacity: 1;
  will-change: auto; /* Remove after animation */
}

.fade-animation.delay-200 {
  transition-delay: 200ms;
}
.fade-animation.delay-400 {
  transition-delay: 400ms;
}
.fade-animation.delay-600 {
  transition-delay: 600ms;
}
.fade-animation.delay-800 {
  transition-delay: 800ms;
}

/* Slide Animations - GPU Optimized */
.slide-up {
  opacity: 0;
  transform: translate3d(0, 50px, 0);
  transition:
    opacity var(--animation-slow) var(--ease-nutrition),
    transform var(--animation-slow) var(--ease-nutrition);
  will-change: transform, opacity;
  contain: layout;
}

.slide-up.show {
  opacity: 1;
  transform: translate3d(0, 0, 0);
  will-change: auto;
}

.slide-left {
  opacity: 0;
  transform: translate3d(50px, 0, 0);
  transition:
    opacity var(--animation-slow) var(--ease-nutrition),
    transform var(--animation-slow) var(--ease-nutrition);
  will-change: transform, opacity;
  contain: layout;
}

.slide-left.show {
  opacity: 1;
  transform: translate3d(0, 0, 0);
  will-change: auto;
}

/* Scale Animations - GPU Optimized */
.scale-in {
  opacity: 0;
  transform: translate3d(0, 0, 0) scale(0.7);
  transition:
    opacity var(--animation-slow) var(--ease-bounce-soft),
    transform var(--animation-slow) var(--ease-bounce-soft);
  will-change: transform, opacity;
  contain: layout;
}

.scale-in.show {
  opacity: 1;
  transform: translate3d(0, 0, 0) scale(1);
  will-change: auto;
}

/* Macro-Specific Animations */
.macro-reveal {
  opacity: 0;
  transform: scale(0.8) translateY(20px);
  animation: macroReveal var(--animation-slow) var(--ease-organic) forwards;
}

.macro-reveal.protein {
  animation-delay: 0ms;
}
.macro-reveal.carbs {
  animation-delay: 200ms;
}
.macro-reveal.fats {
  animation-delay: 400ms;
}

@keyframes macroReveal {
  to {
    opacity: 1;
    transform: scale(1) translateY(0);
  }
}

/* Macro Selection Animation */
.macro-selected {
  animation: macroSelect var(--animation-slow) var(--ease-bounce-soft);
}

@keyframes macroSelect {
  0% {
    transform: scale(1);
  }
  50% {
    transform: scale(1.1);
  }
  100% {
    transform: scale(1);
  }
}

/* Food Item Animations */
.food-item-enter {
  opacity: 0;
  transform: translateX(-30px);
  animation: slideInLeft var(--animation-normal) var(--ease-nutrition) forwards;
}

@keyframes slideInLeft {
  to {
    opacity: 1;
    transform: translateX(0);
  }
}

/* Loading States - Performance Optimized */
.calculation-pulse {
  position: relative;
  transform: translateZ(0);
  contain: layout;
}

.calculation-pulse::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: inherit;
  opacity: 0.3;
  transform: scale(1);
  animation: nutritionPulse 2s var(--ease-organic) infinite;
  pointer-events: none;
}

@keyframes nutritionPulse {
  0%,
  100% {
    transform: scale(1);
    opacity: 0.3;
  }
  50% {
    transform: scale(1.05);
    opacity: 0.1;
  }
}

/* Progress Indicators */
.progress-dot {
  width: 12px;
  height: 12px;
  border-radius: 50%;
  background: var(--fs-border-default);
  transition: all var(--animation-fast) var(--ease-nutrition);
}

.progress-dot.completed {
  background: var(--fs-primary);
  transform: scale(1.2);
  animation: dotComplete var(--animation-normal) var(--ease-bounce-soft);
}

@keyframes dotComplete {
  0% {
    transform: scale(1);
  }
  50% {
    transform: scale(1.4);
  }
  100% {
    transform: scale(1.2);
  }
}

/* Success Celebrations - Performance Optimized */
.success-celebration {
  position: relative;
  transform: translateZ(0);
  contain: layout;
}

.success-celebration::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: radial-gradient(
    circle at center,
    var(--fs-success-a30) 0%,
    var(--fs-success-a10) 50%,
    transparent 100%
  );
  opacity: 0;
  transform: scale(1.1);
  animation: successPulse 1.5s var(--ease-organic);
  pointer-events: none;
}

@keyframes successPulse {
  0% {
    transform: scale(1.1);
    opacity: 0;
  }
  25% {
    transform: scale(1);
    opacity: 1;
  }
  50% {
    transform: scale(1.02);
    opacity: 0.8;
  }
  100% {
    transform: scale(1);
    opacity: 0;
  }
}

/* MudBlazor Component Enhancements */
.mud-button.nutrition-primary {
  transition: all var(--animation-fast) var(--ease-nutrition);
  position: relative;
  overflow: hidden;
}

.mud-button.nutrition-primary::before {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  width: 0;
  height: 0;
  background: rgba(255, 255, 255, 0.2);
  border-radius: 50%;
  transform: translate(-50%, -50%);
  transition:
    width var(--animation-normal),
    height var(--animation-normal);
}

.mud-button.nutrition-primary:hover::before {
  width: 120%;
  height: 120%;
}

/* Dropdown Animations */
.dropdown-slide {
  animation: dropdownSlide var(--animation-fast) var(--ease-nutrition);
  transform-origin: top center;
}

@keyframes dropdownSlide {
  from {
    opacity: 0;
    transform: scaleY(0.8) translateY(-10px);
  }
  to {
    opacity: 1;
    transform: scaleY(1) translateY(0);
  }
}

/* Card Reveal Animations */
.card-reveal {
  opacity: 0;
  transform: translateY(30px) scale(0.98);
  transition: all var(--animation-slow) var(--ease-organic);
}

.card-reveal.show {
  opacity: 1;
  transform: translateY(0) scale(1);
}

/* Stagger Animation Classes */
.stagger-item {
  opacity: 0;
  transform: translateY(20px);
  transition: all var(--animation-normal) var(--ease-nutrition);
}

.stagger-item.show {
  opacity: 1;
  transform: translateY(0);
}

.stagger-item:nth-child(1) {
  transition-delay: 0ms;
}
.stagger-item:nth-child(2) {
  transition-delay: 100ms;
}
.stagger-item:nth-child(3) {
  transition-delay: 200ms;
}
.stagger-item:nth-child(4) {
  transition-delay: 300ms;
}
.stagger-item:nth-child(5) {
  transition-delay: 400ms;
}

/* Nutrition Value Animations */
.nutrition-value-update {
  animation: valueUpdate var(--animation-fast) var(--ease-bounce-soft);
}

@keyframes valueUpdate {
  0% {
    transform: scale(1);
  }
  50% {
    transform: scale(1.15);
    color: var(--fs-primary-text);
  }
  100% {
    transform: scale(1);
  }
}

/* Accessibility Support */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }

  .fade-animation,
  .slide-up,
  .slide-left,
  .scale-in {
    opacity: 1 !important;
    transform: none !important;
  }
  /* Loading indicators are EXEMPT from the catch-all above. Reduced motion means "remove gratuitous
     motion", not "remove the only evidence the app is working" — and for a spinner those are the same
     thing. MQ Level 5 defines `reduce` as removing NON-ESSENTIAL movement. WCAG 2.2 SC 2.2.2 Note 4 is
     adjacent support rather than direct authority (it governs pause mechanisms, not this media feature),
     but it describes #259 exactly: an animation in a preload phase "can be considered essential if
     interaction cannot occur during that phase for all users AND if not indicating progress could
     confuse users or cause them to think that content was frozen or broken".

     The catch-all was doing exactly that. `animation-iteration-count: 1` overrides `infinite`, so every
     Bootstrap spinner completed a single rotation in 0.01ms and stopped. Bootstrap ships its own
     reduced-motion value (1.5s, via --bs-spinner-animation-speed) but consumes it through a
     non-!important shorthand, so ours always won. 1.5s here is Bootstrap's number, not one invented.

     .spinner-grow is included because freezing it renders LITERALLY NOTHING — Bootstrap rests it at
     opacity 0 and the animation is what reveals it.

     .loading-spinner is matched ONLY when empty, and that is not fussiness. The class is used two ways:
     as the ring itself (TomSelectDropdown.razor:9, an empty div) and as a WRAPPER around the loading
     text (LoadingIndicators.razor:4). Exempting it unconditionally spins a block of prose forever for
     the one cohort that asked for less motion; excluding it entirely leaves TomSelect's bare ring frozen
     beside an sr-only label a sighted user cannot read. :empty separates the two by what they contain.

     ⚠️ `html` is load-bearing, not decoration. Blazor rewrites a scoped `*` to `*[b-xxxxxxx]`, which is
     specificity (0,1,0) — an exact TIE with a bare `.spinner-border`, and four .razor.css files ship
     exactly that freeze (SignUp, Login, FoodSelection, PasswordGenerationModal). At a tie the cascade
     falls through to source order, and the scoped bundle only happens to link before this file
     (App.razor:122 vs :145). `html .spinner-border` is (0,1,1) and wins outright, so moving a <link>
     cannot silently reintroduce #259. An earlier version of this comment claimed specificity settled
     it "from any file at any position"; that was true only of the GLOBAL freezes, and false for the
     scoped ones. Verified in Chromium with the scoped freeze loading last.

     Guarded by ReducedMotionSpinnerGuardTests. */
  html .spinner-border,
  html .spinner-border-sm,
  html .spinner-grow,
  html .spinner-grow-sm,
  html .spinner,
  html .loading-spinner:empty {
    animation-duration: 1.5s !important;
    animation-iteration-count: infinite !important;
  }

  /* The dashboard loading screen's three status dots (#4490, DashboardLoadingScreen). Under reduced
     motion the raccoon and the planner outline hold still, so these dots are the only sign the app is
     working. They do NOT keep their motion: the staggered ripple is dropped and what survives is all
     three fading together in place (pp-dot-still), which is not vestibular motion. Without this
     exemption the catch-all clamps that fade to a single 0.01ms cycle and the whole screen rests
     static, which reads as stuck.

     2s, not the spinners' 1.5s, because a slow fade reads as breathing rather than blinking. This
     declaration OWNS the duration: the component's own 2s (--pp-dot-dur) is overridden by this
     !important and is inert; retune here.

     `html` gives (0,2,2) over the scoped `.pp-dots span[b-xxxxx]` rule and over the scoped
     `*[b-xxxxx]` freezes described above, whatever the link order.

     Guarded by ReducedMotionSpinnerGuardTests: deleting this rule fails the suite rather than silently
     freezing the dots. */
  html .pp-dots span {
    animation-duration: 2s !important;
    animation-iteration-count: infinite !important;
  }
}

/* High Contrast Mode Support */
@media (prefers-contrast: high) {
  .macro-reveal,
  .card-reveal,
  .stagger-item {
    border: 2px solid currentColor;
    outline-offset: 2px;
  }

  .progress-dot {
    border: 2px solid currentColor;
  }

  .progress-dot.completed {
    background: currentColor;
  }
}

/* Smooth Scrolling for Nutrition Apps */
.smooth-scroll {
  scroll-behavior: smooth;
  scroll-padding-top: 80px;
}

/* Error State Animations */
.error-shake {
  animation: errorShake var(--animation-fast) var(--ease-bounce-soft);
}

@keyframes errorShake {
  0%,
  100% {
    transform: translateX(0);
  }
  25% {
    transform: translateX(-10px);
  }
  75% {
    transform: translateX(10px);
  }
}

/* Nutrition Result Celebration */
.nutrition-result-celebrate {
  animation: resultCelebrate 2s var(--ease-organic);
}

@keyframes resultCelebrate {
  0% {
    transform: scale(1) rotate(0deg);
    opacity: 1;
  }
  25% {
    transform: scale(1.1) rotate(1deg);
  }
  50% {
    transform: scale(1.05) rotate(-1deg);
  }
  75% {
    transform: scale(1.08) rotate(0.5deg);
  }
  100% {
    transform: scale(1) rotate(0deg);
    opacity: 1;
  }
}
