La fonction splitText(element, text, delayStep) découpe la chaîne caractère par caractère. Les espaces sont préservés en texte brut ; chaque lettre est enveloppée dans un <span style="animation-delay: Ns">, le délai étant égal à l'indice du caractère multiplié par delayStep (0,05 s dans la signature, 0,08 s dans initFadeIn()). Le résultat est injecté en innerHTML de l'élément cible.
Le CSS assure toute l'animation : .text-fade-in span démarre à opacity: 0 et exécute @keyframes fadeInLetter (opacity: 1 à 100 %) en 0,5 s, easing ease, fill-mode: forwards — chaque lettre reste visible une fois son animation terminée. Les délais décalés produisent mécaniquement la cascade de révélation.
La fonction replayFadeIn() vide le innerHTML, attend 50 ms (pour que le navigateur retire les styles d'animation figés), puis rappelle initFadeIn(). Ce délai minimal est nécessaire : une keyframe forwards reste bloquée sur son état final tant que le nœud existe — vider puis ré-injecter le DOM est le moyen le plus fiable de repartir de zéro.
L'effet est 100 % CSS pour l'animation : aucun requestAnimationFrame, aucun canvas, aucune librairie externe. Le JS sert uniquement à construire le DOM initial et à gérer le replay. La fonction splitText() est générique : elle accepte n'importe quel élément et n'importe quelle chaîne, et peut être appelée plusieurs fois pour animer plusieurs zones de texte indépendantes.
Si JS est désactivé, la structure HTML statique préserve les <code><span></code> et l'animation CSS fonctionne toujours. Si les animations CSS sont désactivées côté navigateur, les lettres s'affichent directement à <code>opacity: 1</code> — aucune erreur, le texte reste lisible.