/* =================================================================
   LEGEND.DEV  —  animations.css
   Restraint first: scroll reveals + the terminal pulse are the
   main motions. Everything respects prefers-reduced-motion
   (handled in styles.css).
   ================================================================= */

/* ---------- SCROLL REVEAL ----------
   Elements tagged .reveal start hidden and animate in when
   animations.js adds .is-visible (via IntersectionObserver). */
.reveal {
  opacity: 0;
  transform: translateY(22px);
  transition: opacity 0.7s var(--ease), transform 0.7s var(--ease);
  will-change: opacity, transform;
}
.reveal.is-visible {
  opacity: 1;
  transform: translateY(0);
}

/* Stagger children inside a grid: each card comes in slightly after the last.
   animations.js sets --reveal-delay per element. */
.reveal { transition-delay: var(--reveal-delay, 0ms); }

/* ---------- HERO ENTRANCE ----------
   On first load the hero content rises in a gentle sequence.
   These run once; they don't loop. */
@keyframes fadeUp {
  from { opacity: 0; transform: translateY(18px); }
  to   { opacity: 1; transform: translateY(0); }
}

/* ---------- TERMINAL ---------- */
@keyframes pulse {
  0%   { box-shadow: 0 0 0 0 rgba(34, 211, 238, 0.6); }
  70%  { box-shadow: 0 0 0 8px rgba(34, 211, 238, 0); }
  100% { box-shadow: 0 0 0 0 rgba(34, 211, 238, 0); }
}

/* Blinking cursor appended to the last terminal line while "typing" */
.terminal__cursor {
  display: inline-block;
  width: 8px; height: 1em;
  background: var(--cyan);
  margin-left: 2px;
  vertical-align: text-bottom;
  animation: blink 1.05s steps(1) infinite;
}
@keyframes blink { 50% { opacity: 0; } }

/* New terminal lines fade in as they're added by main.js */
.terminal__line {
  animation: lineIn 0.35s var(--ease) both;
}
@keyframes lineIn {
  from { opacity: 0; transform: translateY(4px); }
  to   { opacity: 1; transform: translateY(0); }
}

/* ---------- LINK ARROW NUDGE ----------
   The "Live demo →" arrows nudge right on hover. The arrow glyph
   is part of the text, so we animate letter-spacing subtly. */
.link-arrow { display: inline-block; }
.link-arrow:hover { transform: translateX(2px); }

/* ---------- BUTTON SHIMMER (primary) ----------
   A faint sheen sweeps across primary buttons on hover. Subtle. */
.btn--primary { position: relative; overflow: hidden; }
.btn--primary::after {
  content: "";
  position: absolute; top: 0; left: -120%;
  width: 60%; height: 100%;
  background: linear-gradient(100deg, transparent, rgba(255, 255, 255, 0.35), transparent);
  transform: skewX(-18deg);
  transition: left 0.6s var(--ease);
}
.btn--primary:hover::after { left: 140%; }

/* ---------- LOGO MARK BREATHE ----------
   Tiny ambient glow shift so the brand mark feels "alive" without
   being distracting. Very low intensity. */
.nav__logo-mark { animation: breathe 4.5s ease-in-out infinite; }
@keyframes breathe {
  0%, 100% { box-shadow: 0 0 18px -4px rgba(124, 92, 255, 0.5); }
  50%      { box-shadow: 0 0 26px -2px rgba(34, 211, 238, 0.55); }
}

/* Pause ambient/looping motion when the user prefers reduced motion.
   (Global reduction is in styles.css; this explicitly stops loops.) */
@media (prefers-reduced-motion: reduce) {
  .nav__logo-mark, .terminal__pulse, .terminal__cursor { animation: none !important; }
  .reveal { opacity: 1 !important; transform: none !important; }
}