/* ==========================================================================
   Animation layer — ambient scene, scroll reveals, micro-interactions.
   Everything here degrades gracefully: no JS → content visible,
   prefers-reduced-motion → motion removed.
   ========================================================================== */

/* ------------------------------------------------------------------
   Ambient background scene (canvas + aurora orbs + grid)
   ------------------------------------------------------------------ */
.bg-scene {
  position: fixed;
  inset: 0;
  z-index: var(--z-bg);
  overflow: hidden;
  pointer-events: none;
  background: var(--color-bg);
  transition: background var(--transition-duration);
}

.bg-scene::after {
  /* vignette that anchors content against the scene */
  content: "";
  position: absolute;
  inset: 0;
  background: radial-gradient(ellipse 120% 90% at 50% 0%, transparent 55%, var(--color-bg-deep) 100%);
}

#bg-canvas {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}

.bg-aurora {
  position: absolute;
  inset: 0;
  filter: blur(70px);
}

.bg-aurora__orb {
  position: absolute;
  border-radius: 50%;
  will-change: transform;
}

.bg-aurora__orb--1 {
  width: 44vw;
  height: 44vw;
  top: -12vw;
  left: -8vw;
  background: var(--aurora-1);
  animation: orb-drift-1 26s ease-in-out infinite alternate;
}

.bg-aurora__orb--2 {
  width: 38vw;
  height: 38vw;
  top: 8vh;
  right: -10vw;
  background: var(--aurora-2);
  animation: orb-drift-2 32s ease-in-out infinite alternate;
}

.bg-aurora__orb--3 {
  width: 34vw;
  height: 34vw;
  bottom: -14vw;
  left: 28vw;
  background: var(--aurora-3);
  animation: orb-drift-3 38s ease-in-out infinite alternate;
}

@keyframes orb-drift-1 {
  from { transform: translate3d(0, 0, 0) scale(1); }
  to   { transform: translate3d(10vw, 8vh, 0) scale(1.15); }
}

@keyframes orb-drift-2 {
  from { transform: translate3d(0, 0, 0) scale(1.1); }
  to   { transform: translate3d(-8vw, 12vh, 0) scale(0.95); }
}

@keyframes orb-drift-3 {
  from { transform: translate3d(0, 0, 0) scale(0.95); }
  to   { transform: translate3d(6vw, -10vh, 0) scale(1.12); }
}

.bg-grid {
  position: absolute;
  inset: -1px;
  background-image:
    linear-gradient(var(--grid-line) 1px, transparent 1px),
    linear-gradient(90deg, var(--grid-line) 1px, transparent 1px);
  background-size: 56px 56px;
  mask-image: radial-gradient(ellipse 90% 70% at 50% 0%, black 30%, transparent 80%);
  -webkit-mask-image: radial-gradient(ellipse 90% 70% at 50% 0%, black 30%, transparent 80%);
}

/* ------------------------------------------------------------------
   Scroll reveal system — motion.js toggles .is-visible
   Initial hidden state only applies when JS is running (html.js)
   and motion is allowed.
   ------------------------------------------------------------------ */
@media (prefers-reduced-motion: no-preference) {
  html.js [data-reveal] {
    opacity: 0;
    transform: translateY(28px);
    filter: blur(6px);
    transition:
      opacity 0.8s var(--ease-out),
      transform 0.8s var(--ease-out),
      filter 0.8s var(--ease-out);
    transition-delay: var(--reveal-delay, 0s);
  }

  html.js [data-reveal="left"]  { transform: translateX(-40px); }
  html.js [data-reveal="right"] { transform: translateX(40px); }
  html.js [data-reveal="scale"] { transform: scale(0.92); }

  html.js [data-reveal].is-visible {
    opacity: 1;
    transform: none;
    filter: blur(0);
  }
}

/* ------------------------------------------------------------------
   Hero entrance (plays once on load, CSS only)
   ------------------------------------------------------------------ */
@keyframes rise-in {
  from {
    opacity: 0;
    transform: translateY(32px);
    filter: blur(8px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
    filter: blur(0);
  }
}

@media (prefers-reduced-motion: no-preference) {
  .anim-rise {
    animation: rise-in 0.9s var(--ease-out) both;
    animation-delay: var(--rise-delay, 0s);
  }
}

/* ------------------------------------------------------------------
   Gradient text shimmer
   ------------------------------------------------------------------ */
.text-gradient {
  background: var(--gradient-brand);
  background-size: 200% auto;
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  -webkit-text-fill-color: transparent;
}

@media (prefers-reduced-motion: no-preference) {
  .text-gradient--animated {
    animation: gradient-pan 6s linear infinite;
  }
}

@keyframes gradient-pan {
  to { background-position: 200% center; }
}

/* ------------------------------------------------------------------
   Floating / pulsing decorations
   ------------------------------------------------------------------ */
@keyframes float-y {
  0%, 100% { transform: translateY(0); }
  50%      { transform: translateY(-12px); }
}

@keyframes pulse-dot {
  0%, 100% { opacity: 1; box-shadow: 0 0 0 0 rgba(74, 222, 128, 0.5); }
  50%      { opacity: 0.7; box-shadow: 0 0 0 6px rgba(74, 222, 128, 0); }
}

@keyframes spin-slow {
  to { transform: rotate(360deg); }
}

@media (prefers-reduced-motion: no-preference) {
  .anim-float { animation: float-y 6s ease-in-out infinite; }
}

/* ------------------------------------------------------------------
   Typewriter caret
   ------------------------------------------------------------------ */
.typewriter__caret {
  display: inline-block;
  width: 2px;
  height: 1.1em;
  margin-left: 2px;
  vertical-align: text-bottom;
  background: var(--color-primary);
  box-shadow: 0 0 8px var(--color-primary);
}

@media (prefers-reduced-motion: no-preference) {
  .typewriter__caret { animation: caret-blink 1s step-end infinite; }
}

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

/* ------------------------------------------------------------------
   Marquee (skills ribbon) — duplicated track scrolls seamlessly
   ------------------------------------------------------------------ */
.marquee {
  overflow: hidden;
  mask-image: linear-gradient(90deg, transparent, black 12%, black 88%, transparent);
  -webkit-mask-image: linear-gradient(90deg, transparent, black 12%, black 88%, transparent);
}

.marquee__inner {
  display: flex;
  width: max-content;
  gap: 1rem;
}

@media (prefers-reduced-motion: no-preference) {
  .marquee__inner {
    animation: marquee-scroll 28s linear infinite;
  }

  .marquee:hover .marquee__inner {
    animation-play-state: paused;
  }
}

@keyframes marquee-scroll {
  to { transform: translateX(calc(-50% - 0.5rem)); }
}

/* Reduced motion / no JS: wrap chips statically instead of scrolling */
@media (prefers-reduced-motion: reduce) {
  .marquee {
    mask-image: none;
    -webkit-mask-image: none;
  }

  .marquee__inner {
    flex-wrap: wrap;
    justify-content: center;
    width: auto;
  }

  .marquee__inner[aria-hidden="true"] {
    display: none;
  }
}

/* ------------------------------------------------------------------
   Spotlight cards — motion.js feeds --mx / --my per card
   ------------------------------------------------------------------ */
.spotlight {
  position: relative;
}

.spotlight::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: radial-gradient(360px circle at var(--mx, 50%) var(--my, 50%), var(--spotlight-color), transparent 65%);
  opacity: 0;
  transition: opacity 0.4s ease;
  pointer-events: none;
  z-index: 1;
}

.spotlight:hover::before,
.spotlight:focus-within::before {
  opacity: 1;
}

/* ------------------------------------------------------------------
   Button shine sweep
   ------------------------------------------------------------------ */
.btn--shine {
  position: relative;
  overflow: hidden;
}

.btn--shine::after {
  content: "";
  position: absolute;
  top: 0;
  left: -80%;
  width: 50%;
  height: 100%;
  background: linear-gradient(105deg, transparent, rgba(255, 255, 255, 0.35), transparent);
  transform: skewX(-20deg);
  transition: left 0.6s var(--ease-out);
  pointer-events: none;
}

.btn--shine:hover::after,
.btn--shine:focus-visible::after {
  left: 130%;
}

/* ------------------------------------------------------------------
   Scroll cue (hero)
   ------------------------------------------------------------------ */
@keyframes scroll-cue {
  0%   { transform: translateY(0); opacity: 1; }
  70%  { transform: translateY(10px); opacity: 0; }
  100% { transform: translateY(0); opacity: 0; }
}

/* ------------------------------------------------------------------
   View transitions between pages — subtle fade + lift
   ------------------------------------------------------------------ */
@view-transition {
  navigation: auto;
}

@media (prefers-reduced-motion: no-preference) {
  ::view-transition-old(root) {
    animation: vt-out 0.25s ease-in forwards;
  }

  ::view-transition-new(root) {
    animation: vt-in 0.45s var(--ease-out) forwards;
  }
}

@keyframes vt-out {
  to { opacity: 0; transform: translateY(-12px); }
}

@keyframes vt-in {
  from { opacity: 0; transform: translateY(16px); }
  to   { opacity: 1; transform: translateY(0); }
}

/* ------------------------------------------------------------------
   Global reduced-motion kill switch
   ------------------------------------------------------------------ */
@media (prefers-reduced-motion: reduce) {
  .bg-aurora__orb,
  .anim-rise,
  .anim-float {
    animation: none !important;
  }

  #bg-canvas {
    display: none;
  }

  *,
  *::before,
  *::after {
    transition-duration: 0.01ms !important;
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
  }
}
