/* ============================================================
   split-text · styles
   Keyed off the .st-* wrappers + the .is-in class the JS toggles
   when the host scrolls into view. Brand-neutral; override the
   --st-* custom properties to retune timing/motion.
   ============================================================ */

:root {
  --st-duration: 0.7s;             /* per-unit transition duration */
  --st-ease: cubic-bezier(0.22, 1, 0.36, 1);   /* expo-ish ease-out */
  --st-rise: 1.1em;                /* travel for the "up" mask reveal */
}

/* The host element. inline-block keeps offsetTop line-grouping sane;
   override to block/flex in your own CSS if you need to. */
.st {
  display: inline-block;
}

/* Words ride on their own baseline; keep them from breaking apart. */
.st-word {
  display: inline-block;
  white-space: nowrap;
}

/* Chars need to be inline-block so transform/opacity apply per glyph. */
.st-char {
  display: inline-block;
  will-change: transform, opacity;
}

/* Lines are the mask for the "up" reveal: the overflow clip hides the
   units while they sit below their resting position. */
.st-line {
  display: block;
  overflow: hidden;
}

/* ---- reveal: up (mask + rise) ------------------------------ */
/* Units start pushed down + invisible, then settle to 0 / 1. */
.st-reveal-up .st-char,
.st-reveal-up .st-word,
.st-reveal-up .st-line {
  transform: translateY(var(--st-rise));
  opacity: 0;
  transition:
    transform var(--st-duration) var(--st-ease),
    opacity var(--st-duration) var(--st-ease);
}
.st-reveal-up.is-in .st-char,
.st-reveal-up.is-in .st-word,
.st-reveal-up.is-in .st-line {
  transform: translateY(0);
  opacity: 1;
}

/* ---- reveal: fade (opacity only) --------------------------- */
.st-reveal-fade .st-char,
.st-reveal-fade .st-word,
.st-reveal-fade .st-line {
  opacity: 0;
  transition: opacity var(--st-duration) var(--st-ease);
}
.st-reveal-fade.is-in .st-char,
.st-reveal-fade.is-in .st-word,
.st-reveal-fade.is-in .st-line {
  opacity: 1;
}

/* ---- reveal: flicker (opacity stutters, then resolves) ----- */
/* Each unit runs a short keyframe flicker; the per-unit stagger is
   applied as an animation-delay (mirrored from transition-delay). */
.st-reveal-flicker .st-char,
.st-reveal-flicker .st-word,
.st-reveal-flicker .st-line {
  opacity: 0;
}
.st-reveal-flicker.is-in .st-char,
.st-reveal-flicker.is-in .st-word,
.st-reveal-flicker.is-in .st-line {
  /* animation-delay is set inline by the JS, mirroring the stagger */
  animation: st-flicker var(--st-duration) var(--st-ease) forwards;
}

@keyframes st-flicker {
  0%   { opacity: 0; }
  10%  { opacity: 1; }
  20%  { opacity: 0; }
  40%  { opacity: 1; }
  55%  { opacity: 0.2; }
  70%  { opacity: 1; }
  85%  { opacity: 0.5; }
  100% { opacity: 1; }
}

/* ---- reduced motion: everything just shows ----------------- */
@media (prefers-reduced-motion: reduce) {
  .st-char, .st-word, .st-line {
    transform: none !important;
    opacity: 1 !important;
    animation: none !important;
    transition: none !important;
  }
}
