/* ============================================================
   ANIMATIONS.CSS — Premium Portfolio Animation System
   Pure CSS animations for a warm-gradient portfolio site.
   All animations use transform/opacity for GPU acceleration.
   ============================================================ */

/* ------------------------------------------------------------
   0. CUSTOM PROPERTIES (Animation Tokens)
   ------------------------------------------------------------ */
:root {
  /* Durations */
  --anim-fast: 200ms;
  --anim-base: 400ms;
  --anim-slow: 600ms;
  --anim-slower: 900ms;
  --anim-hero: 1200ms;

  /* Easings — premium cubic-beziers */
  --ease-out-expo: cubic-bezier(0.16, 1, 0.3, 1);
  --ease-out-quart: cubic-bezier(0.25, 1, 0.5, 1);
  --ease-out-back: cubic-bezier(0.34, 1.56, 0.64, 1);
  --ease-in-out-smooth: cubic-bezier(0.45, 0, 0.15, 1);

  /* Distances */
  --slide-distance: 40px;
  --slide-distance-lg: 80px;

  /* Aurora palette (low-opacity brand-blue gradients) */
  --aurora-pink: rgba(33, 150, 243, 0.13);
  --aurora-orange: rgba(66, 165, 245, 0.12);
  --aurora-purple: rgba(21, 101, 192, 0.10);
  --aurora-peach: rgba(227, 242, 253, 0.18);

  /* Scroll progress */
  --scroll-progress: 0;
}


/* ============================================================
   1. AURORA / GRADIENT MESH BACKGROUND
   Subtle, always-on animated gradient behind the hero.
   Usage: <div class="aurora-bg"></div> inside hero section.
   ============================================================ */

.aurora-bg {
  position: absolute;
  inset: 0;
  overflow: hidden;
  z-index: 0;
  pointer-events: none;
}

.aurora-bg::before,
.aurora-bg::after {
  content: "";
  position: absolute;
  border-radius: 50%;
  filter: blur(80px);
  will-change: transform;
  animation-timing-function: var(--ease-in-out-smooth);
  animation-iteration-count: infinite;
  animation-direction: alternate;
}

/* Primary blob — pink → orange drift */
.aurora-bg::before {
  width: 60%;
  height: 60%;
  top: -10%;
  left: -5%;
  background: radial-gradient(
    ellipse at 40% 50%,
    var(--aurora-pink),
    var(--aurora-orange) 60%,
    transparent 80%
  );
  animation: aurora-drift-1 23s infinite alternate ease-in-out;
}

/* Secondary blob — purple → peach drift */
.aurora-bg::after {
  width: 55%;
  height: 55%;
  bottom: -15%;
  right: -10%;
  background: radial-gradient(
    ellipse at 60% 50%,
    var(--aurora-purple),
    var(--aurora-peach) 60%,
    transparent 80%
  );
  animation: aurora-drift-2 29s infinite alternate ease-in-out;
}

/* Third blob via a child element */
.aurora-blob {
  position: absolute;
  width: 45%;
  height: 50%;
  top: 20%;
  left: 30%;
  border-radius: 50%;
  filter: blur(90px);
  pointer-events: none;
  background: radial-gradient(
    ellipse at 50% 50%,
    var(--aurora-orange),
    var(--aurora-purple) 50%,
    transparent 80%
  );
  animation: aurora-drift-3 37s infinite alternate ease-in-out;
  will-change: transform;
}

@keyframes aurora-drift-1 {
  0%   { transform: translate(0, 0) scale(1) rotate(0deg); }
  20%  { transform: translate(15%, 10%) scale(1.1) rotate(5deg); }
  40%  { transform: translate(-10%, 20%) scale(0.9) rotate(-3deg); }
  60%  { transform: translate(20%, -15%) scale(1.15) rotate(4deg); }
  80%  { transform: translate(-15%, -10%) scale(0.95) rotate(-5deg); }
  100% { transform: translate(10%, 5%) scale(1.05) rotate(2deg); }
}

@keyframes aurora-drift-2 {
  0%   { transform: translate(0, 0) scale(1) rotate(0deg); }
  25%  { transform: translate(-15%, -15%) scale(1.1) rotate(-4deg); }
  50%  { transform: translate(20%, -5%) scale(0.9) rotate(3deg); }
  75%  { transform: translate(-5%, 25%) scale(1.15) rotate(-2deg); }
  100% { transform: translate(10%, -10%) scale(1.05) rotate(1deg); }
}

@keyframes aurora-drift-3 {
  0%   { transform: translate(0, 0) scale(1) rotate(0deg); }
  20%  { transform: translate(-20%, 15%) scale(1.1) rotate(-5deg); }
  40%  { transform: translate(15%, -20%) scale(0.9) rotate(4deg); }
  60%  { transform: translate(25%, 10%) scale(1.15) rotate(-3deg); }
  80%  { transform: translate(-10%, -25%) scale(0.95) rotate(2deg); }
  100% { transform: translate(5%, 15%) scale(1.05) rotate(-1deg); }
}


/* ============================================================
   2. SCROLL-TRIGGERED ANIMATIONS
   Apply these classes to elements; JS adds `.is-visible`
   when they enter the viewport via IntersectionObserver.
   ============================================================ */

/* --- Fade In Up ------------------------------------------- */
.animate-fade-up,
.fade-in {
  opacity: 0;
  transform: translateY(var(--slide-distance));
  transition:
    opacity var(--anim-slow) var(--ease-out-expo),
    transform var(--anim-slow) var(--ease-out-expo);
}
.animate-fade-up.is-visible,
.fade-in.is-visible {
  opacity: 1;
  transform: translateY(0);
}

/* --- Fade In Down ----------------------------------------- */
.animate-fade-down {
  opacity: 0;
  transform: translateY(calc(-1 * var(--slide-distance)));
  transition:
    opacity var(--anim-slow) var(--ease-out-expo),
    transform var(--anim-slow) var(--ease-out-expo);
}
.animate-fade-down.is-visible {
  opacity: 1;
  transform: translateY(0);
}

/* --- Fade In (no movement) -------------------------------- */
.animate-fade-in {
  opacity: 0;
  transition: opacity var(--anim-slow) var(--ease-out-expo);
}
.animate-fade-in.is-visible {
  opacity: 1;
}

/* --- Scale In --------------------------------------------- */
.animate-scale-in {
  opacity: 0;
  transform: scale(0.8);
  transition:
    opacity var(--anim-slow) var(--ease-out-back),
    transform var(--anim-slow) var(--ease-out-back);
}
.animate-scale-in.is-visible {
  opacity: 1;
  transform: scale(1);
}

/* --- Slide In Left ---------------------------------------- */
.animate-slide-left {
  opacity: 0;
  transform: translateX(calc(-1 * var(--slide-distance-lg)));
  transition:
    opacity var(--anim-slow) var(--ease-out-expo),
    transform var(--anim-slow) var(--ease-out-expo);
}
.animate-slide-left.is-visible {
  opacity: 1;
  transform: translateX(0);
}

/* --- Slide In Right --------------------------------------- */
.animate-slide-right {
  opacity: 0;
  transform: translateX(var(--slide-distance-lg));
  transition:
    opacity var(--anim-slow) var(--ease-out-expo),
    transform var(--anim-slow) var(--ease-out-expo);
}
.animate-slide-right.is-visible {
  opacity: 1;
  transform: translateX(0);
}

/* --- Blur In (fade + unblur — modern hero/card reveal) ----- */
.animate-blur-in {
  opacity: 0;
  filter: blur(14px);
  transform: translateY(24px);
  transition:
    opacity 0.9s var(--ease-out-expo),
    filter 0.9s var(--ease-out-expo),
    transform 0.9s var(--ease-out-expo);
}
.animate-blur-in.is-visible {
  opacity: 1;
  filter: blur(0);
  transform: translateY(0);
}

/* --- Image Settle (image stays visible, gently zooms out) --- */
/* The image is fully visible from the start; on entering the
   viewport it eases from a slight zoom back to its natural size. */
.animate-clip-reveal img {
  transform: scale(1.12);
  transition: transform 1.6s var(--ease-out-expo);
}
.animate-clip-reveal.is-visible img {
  transform: scale(1);
}

/* --- Stagger Container ------------------------------------ */
/* Add .animate-stagger to a parent. Children are hidden by
   default; JS assigns an inline transition-delay per child,
   adds .is-visible, then clears the delay so hover states
   stay snappy afterwards.                                     */
.animate-stagger > * {
  opacity: 0;
  transform: translateY(32px);
  transition:
    opacity 0.7s var(--ease-out-expo),
    transform 0.7s var(--ease-out-expo);
}
.animate-stagger > *.is-visible {
  opacity: 1;
  transform: translateY(0);
}



/* ============================================================
   3. MICRO-INTERACTIONS
   ============================================================ */

/* --- Button Hover: scale + shadow lift -------------------- */
.btn-hover,
button[class*="btn"],
a[class*="btn"] {
  transition:
    transform var(--anim-fast) var(--ease-out-quart),
    box-shadow var(--anim-fast) var(--ease-out-quart);
  will-change: transform;
}
.btn-hover:hover,
button[class*="btn"]:hover,
a[class*="btn"]:hover {
  transform: translateY(-2px) scale(1.02);
  box-shadow:
    0 8px 24px rgba(0, 0, 0, 0.08),
    0 2px 8px rgba(0, 0, 0, 0.04);
}
.btn-hover:active,
button[class*="btn"]:active,
a[class*="btn"]:active {
  transform: translateY(0) scale(0.98);
  box-shadow:
    0 2px 8px rgba(0, 0, 0, 0.06);
  transition-duration: 80ms;
}

/* --- Card Hover: 3D tilt + shadow expansion --------------- */
/* The tilt is driven by JS (mousemove sets --rx, --ry).
   CSS applies the transform + shadow transition.              */
.card-hover {
  --rx: 0deg;
  --ry: 0deg;
  transition:
    transform var(--anim-base) var(--ease-out-quart),
    box-shadow var(--anim-base) var(--ease-out-quart);
  transform-style: preserve-3d;
  will-change: transform;
}
.card-hover:hover {
  transform: perspective(800px) rotateX(var(--rx)) rotateY(var(--ry));
  box-shadow:
    0 16px 40px rgba(0, 0, 0, 0.08),
    0 4px 12px rgba(0, 0, 0, 0.04);
}

/* When JS is not available, provide a simple lift */
.card-hover:hover {
  --rx: 0deg;
  --ry: 0deg;
}

/* Card inner content subtle z-shift */
.card-hover:hover .card-hover-content {
  transform: translateZ(20px);
}
.card-hover .card-hover-content {
  transition: transform var(--anim-base) var(--ease-out-quart);
}

/* --- Link Underline: slide-in from left ------------------- */
.link-underline {
  position: relative;
  text-decoration: none;
}
.link-underline::after {
  content: "";
  position: absolute;
  left: 0;
  bottom: -2px;
  width: 100%;
  height: 2px;
  background: currentColor;
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform var(--anim-base) var(--ease-out-expo);
  border-radius: 1px;
}
.link-underline:hover::after {
  transform: scaleX(1);
}

/* Gradient underline variant */
.link-underline-gradient::after {
  background: linear-gradient(90deg, #1565C0, #2196F3, #42A5F5);
}

/* --- Nav Link Active Indicator (dot) ---------------------- */
.nav-link {
  position: relative;
}
.nav-link::after {
  content: "";
  position: absolute;
  bottom: -6px;
  left: 50%;
  width: 4px;
  height: 4px;
  border-radius: 50%;
  background: linear-gradient(135deg, #2196F3, #42A5F5);
  transform: translateX(-50%) scale(0);
  transition: transform var(--anim-base) var(--ease-out-back);
}
.nav-link:hover::after,
.nav-link.active::after {
  transform: translateX(-50%) scale(1);
}


/* ============================================================
   4. TEXT ANIMATIONS
   ============================================================ */

/* --- Hero Title: Word-by-word reveal ---------------------- */
/* JS wraps each word in <span class="word-reveal">.
   A stagger delay is applied via --word-index.                */
.word-reveal {
  display: inline-block;
  overflow: hidden;
}
.word-reveal > span {
  display: inline-block;
  transform: translateY(110%);
  opacity: 0;
  transition:
    transform var(--anim-hero) var(--ease-out-expo),
    opacity var(--anim-slow) var(--ease-out-expo);
  transition-delay: calc(var(--word-index, 0) * 80ms + 400ms);
}
.word-reveal.is-visible > span,
.hero-loaded .word-reveal > span {
  transform: translateY(0);
  opacity: 1;
}

/* --- Typing Effect ---------------------------------------- */
/* Apply .typing-effect. JS handles character reveal.
   The cursor blinks via CSS.                                  */
.typing-cursor::after {
  content: "|";
  display: inline-block;
  margin-left: 2px;
  animation: cursor-blink 0.7s steps(1) infinite;
  color: #2196F3;
  font-weight: 300;
}

@keyframes cursor-blink {
  0%, 50% { opacity: 1; }
  51%, 100% { opacity: 0; }
}

/* --- Counter (number count-up) ---------------------------- */
/* The actual counting is JS. CSS handles the scale-in feel.   */
.counter-value {
  display: inline-block;
  transition:
    transform var(--anim-slow) var(--ease-out-back),
    opacity var(--anim-slow) var(--ease-out-expo);
}


/* ============================================================
   5. LOADING / PAGE ENTRANCE ANIMATION
   ============================================================ */

/* --- Page fade-in ----------------------------------------- */
body {
  opacity: 0;
  animation: page-fade-in 0.6s var(--ease-out-expo) 0.1s forwards;
}

@keyframes page-fade-in {
  to { opacity: 1; }
}

/* --- Navbar slide-down ------------------------------------ */
.navbar-animate {
  transform: translateY(-100%);
  opacity: 0;
  animation: navbar-enter 0.6s var(--ease-out-expo) 0.25s forwards;
}

@keyframes navbar-enter {
  to {
    transform: translateY(0);
    opacity: 1;
  }
}

/* --- Hero content stagger entrance ------------------------ */
/* Apply .hero-animate to each hero element.
   Use --hero-index for stagger order.                         */
.hero-animate {
  opacity: 0;
  transform: translateY(30px);
  animation: hero-enter var(--anim-slower) var(--ease-out-expo) forwards;
  animation-delay: calc(var(--hero-index, 0) * 120ms + 500ms);
}

@keyframes hero-enter {
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

/* Hero stagger index helpers */
.hero-animate:nth-child(1) { --hero-index: 0; }
.hero-animate:nth-child(2) { --hero-index: 1; }
.hero-animate:nth-child(3) { --hero-index: 2; }
.hero-animate:nth-child(4) { --hero-index: 3; }
.hero-animate:nth-child(5) { --hero-index: 4; }
.hero-animate:nth-child(6) { --hero-index: 5; }


/* ============================================================
   6. PARALLAX (CSS support)
   JS sets --parallax-y on .parallax-element via scroll.
   CSS applies the transform.
   ============================================================ */
.parallax-element {
  will-change: transform;
  transition: transform 0.1s linear;
  transform: translateY(calc(var(--parallax-y, 0) * 1px));
}

/* Parallax speed modifiers */
.parallax-slow   { --parallax-speed: 0.03; }
.parallax-medium { --parallax-speed: 0.06; }
.parallax-fast   { --parallax-speed: 0.1; }


/* ============================================================
   7. SCROLL PROGRESS BAR
   ============================================================ */
.scroll-progress {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 3px;
  z-index: 9999;
  pointer-events: none;
  background: transparent;
}
.scroll-progress::after {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  height: 100%;
  width: 100%;
  background: linear-gradient(90deg, #1565C0, #2196F3, #42A5F5);
  transform: scaleX(var(--scroll-progress, 0));
  transform-origin: left center;
  transition: transform 60ms linear;
  border-radius: 0 2px 2px 0;
}


/* ============================================================
   8. UTILITY CLASSES
   ============================================================ */

/* Delay utilities */
.delay-100 { transition-delay: 100ms !important; animation-delay: 100ms !important; }
.delay-200 { transition-delay: 200ms !important; animation-delay: 200ms !important; }
.delay-300 { transition-delay: 300ms !important; animation-delay: 300ms !important; }
.delay-400 { transition-delay: 400ms !important; animation-delay: 400ms !important; }
.delay-500 { transition-delay: 500ms !important; animation-delay: 500ms !important; }
.delay-600 { transition-delay: 600ms !important; animation-delay: 600ms !important; }
.delay-700 { transition-delay: 700ms !important; animation-delay: 700ms !important; }
.delay-800 { transition-delay: 800ms !important; animation-delay: 800ms !important; }

/* Duration utilities */
.duration-fast   { transition-duration: var(--anim-fast) !important; }
.duration-base   { transition-duration: var(--anim-base) !important; }
.duration-slow   { transition-duration: var(--anim-slow) !important; }
.duration-slower { transition-duration: var(--anim-slower) !important; }


/* ============================================================
   9. ACCESSIBILITY — prefers-reduced-motion
   Disable all animations and transitions for users who
   prefer reduced motion.
   ============================================================ */
@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;
  }

  body {
    opacity: 1;
  }

  .navbar-animate {
    transform: none;
    opacity: 1;
  }

  .hero-animate {
    opacity: 1;
    transform: none;
  }

  .animate-fade-up,
  .animate-fade-down,
  .animate-fade-in,
  .animate-scale-in,
  .animate-slide-left,
  .animate-slide-right,
  .animate-blur-in,
  .animate-stagger > *,
  .fade-in {
    opacity: 1;
    transform: none;
    filter: none;
  }

  .animate-clip-reveal img {
    transform: none;
  }

  .word-reveal > span {
    transform: none;
    opacity: 1;
  }

  .aurora-bg::before,
  .aurora-bg::after,
  .aurora-blob {
    animation: none;
  }

  .scroll-progress {
    display: none;
  }

  .parallax-element {
    transform: none !important;
  }
}
