/* ============================================================
   Animations — kept separate for clarity
   ============================================================ */

/* Reveal on scroll — see main.css .reveal */

/* ============================================================
   Nebula reveal — text emerges from golden dust
   Apply via JS by wrapping each char of a target heading.
   ============================================================ */
.nebula {
  display: inline;
  position: relative;
}
.nebula .word {
  display: inline-block;
  white-space: nowrap;
  position: relative;
}
.nebula .ch {
  display: inline-block;
  opacity: 0;
  filter: blur(14px);
  color: oklch(78% 0.150 82);
  text-shadow:
    0 0 18px oklch(78% 0.150 82 / 0.7),
    0 0 36px oklch(78% 0.150 82 / 0.4);
  transform: translateY(8px) scale(1.04);
  transition:
    opacity 1100ms cubic-bezier(0.16, 1, 0.3, 1),
    filter 1100ms cubic-bezier(0.16, 1, 0.3, 1),
    color 1400ms cubic-bezier(0.16, 1, 0.3, 1) 200ms,
    text-shadow 1600ms cubic-bezier(0.16, 1, 0.3, 1) 200ms,
    transform 1100ms cubic-bezier(0.16, 1, 0.3, 1);
  transition-delay: var(--ch-delay, 0ms);
}
.nebula.in .ch {
  opacity: 1;
  filter: none;
  color: inherit;
  /* clean rest state — no permanent halo */
  text-shadow: none;
  transform: translateY(0) scale(1);
}

/* ------------------------------------------------------------
   Mobile: stable, jump-free nebula reveal.
   Root cause of the end-of-animation "jump" on mobile was the
   per-character scale(1.04) → scale(1) + blur() animation. Each
   <span class="ch"> was ~4% wider mid-animation, then snapped
   back to its true width at the end. Combined with text-wrap:
   balance/pretty on h1/h2, the browser re-balanced the line
   break right at the end, producing the visible reflow.

   We strip mobile down to opacity + a small translate3d only,
   shorten the per-prop transitions (no color/text-shadow/blur),
   and keep font metrics 100% identical from 0% → 100%.
   Desktop keeps the rich nebula effect untouched.
   ------------------------------------------------------------ */
@media (max-width: 640px) {
  .nebula .ch {
    /* No blur, no scale, no halo glow — purely opacity + Y shift. */
    filter: none;
    color: inherit;
    text-shadow: none;
    transform: translate3d(0, 6px, 0);
    transition:
      opacity 700ms cubic-bezier(0.22, 0.7, 0.25, 1),
      transform 700ms cubic-bezier(0.22, 0.7, 0.25, 1);
    transition-delay: var(--ch-delay, 0ms);
    will-change: opacity, transform;
  }
  .nebula.in .ch {
    opacity: 1;
    transform: translate3d(0, 0, 0);
    text-shadow: none;
  }
  /* Hide the dust canvas overlay on mobile — it can trigger
     repaints that subtly nudge the heading box. */
  .nebula-dust { display: none !important; }
}

/* Golden dust canvas overlay */
.nebula-dust {
  position: absolute;
  left: 0;
  top: 0;
  pointer-events: none;
  z-index: 1;
  opacity: 0;
  transition: opacity 800ms ease-out;
}
.nebula.in .nebula-dust { opacity: 1; }

/* Number counter animation */
.count-up {
  display: inline-block;
  font-variant-numeric: tabular-nums;
}

/* Workflow particle stream */
.particle {
  position: absolute;
  width: 4px;
  height: 4px;
  background: var(--gold-500);
  border-radius: 50%;
  box-shadow: 0 0 8px var(--gold-500);
  pointer-events: none;
  opacity: 0;
}

@keyframes particle-flow {
  0% { opacity: 0; transform: translateX(0); }
  10% { opacity: 1; }
  90% { opacity: 1; }
  100% { opacity: 0; transform: translateX(var(--travel)); }
}

/* Subtle glow pulse */
@keyframes glow-pulse {
  0%, 100% { box-shadow: 0 0 0 0 var(--accent-soft); }
  50% { box-shadow: 0 0 0 8px transparent; }
}

/* Caret blink for terminal accents */
.caret::after {
  content: "▎";
  display: inline-block;
  margin-left: 0.05em;
  color: var(--gold-500);
  animation: blink 1.1s step-end infinite;
}
@keyframes blink {
  50% { opacity: 0; }
}

/* Hero scroll cue */
.scroll-cue {
  position: absolute;
  bottom: 2rem;
  left: 50%;
  transform: translateX(-50%);
  font-family: var(--font-mono);
  font-size: 0.7rem;
  color: var(--bone-500);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.6rem;
  opacity: calc(0.7 * var(--tw-motion, 1));
}
.scroll-cue::after {
  content: "";
  width: 1px; height: 32px;
  background: linear-gradient(to bottom, var(--gold-500), transparent);
  animation: cue-down 2s ease-in-out infinite;
}
@keyframes cue-down {
  0% { transform: translateY(-12px); opacity: 0; }
  50% { opacity: 1; }
  100% { transform: translateY(12px); opacity: 0; }
}

/* Sparkline animation */
.spark-line {
  stroke-dasharray: 1000;
  stroke-dashoffset: 1000;
  animation: draw-line 2.4s var(--ease-out) forwards;
}
@keyframes draw-line {
  to { stroke-dashoffset: 0; }
}

/* Live row insertion */
@keyframes row-in {
  from { opacity: 0; transform: translateY(-8px); background: var(--accent-soft); }
  to { opacity: 1; transform: translateY(0); background: transparent; }
}
.feed-row.fresh { animation: row-in 800ms var(--ease-out); }
