/* Default-Tuning (kannst du per style="" am Element überschreiben) */
.scrub-reveal {
  position: relative;
  display: inline-block;
  white-space: normal;
  word-break: normal;
  overflow-wrap: normal;
  hyphens: none;

  /* Tuning-Variablen */
  --blur: 10px;
  /* Start-Unschärfe */
  --shift: 14px;
  /* Start-Versatz nach oben (px) */
  --spread: 0.25;
  /* Wellenbreite (0.15–0.4 typ.) */
  --progress: 0;
  /* wird per JS 0..1 gesetzt */
  --count: 0;
  /* wird per JS gesetzt (Zeichenanzahl) */
}

/* Wort als „atomare“ Einheit; Umbrüche nur an echten Spaces */
.scrub-reveal .w {
  display: inline-block;
  white-space: nowrap;
}

/* Einzelne Zeichen (werden scrubbend animiert, nicht zeitbasiert) */
.scrub-reveal .ch {
  display: inline-block;
  will-change: opacity, transform, filter;

  /* Index wird per JS als --i gesetzt (0..count-1) */
  --t-raw: calc(((var(--progress) * max(1, var(--count) - 1)) - var(--i)) / var(--spread));
  --t: max(0, min(1, var(--t-raw)));

  opacity: var(--t);
  transform: translateY(calc((1 - var(--t)) * -1 * var(--shift)));
  filter: blur(calc((1 - var(--t)) * var(--blur)));
  transition: none;
}
