/* ============================================================
   TEXT REVEAL EFFECT
   Splits text into word/char spans and animates them in.

   Usage:
     <h1 class="text-reveal" data-text-reveal
         data-split="word"          word | char
         data-effect="revealY"      revealX | revealY | revealXY |
                                    revealXReverse | revealYReverse |
                                    revealXYReverse | scale
         data-duration="500"        ms
         data-stagger="100"         ms between items
         data-blur="10"             starting blur in px
         data-word-spacing="1"      multiplier (×10px)
         data-char-spacing="1"      multiplier (×10px / letter-spacing)
         data-trigger="load"        load | inview
     >
       Your headline text
     </h1>
   ============================================================ */

.text-reveal {
  display: flex;
  flex-wrap: wrap;
  gap: 0.25em;
}

.text-reveal__item {
  display: inline-block;
  will-change: transform, opacity, filter;
  opacity: 0;
}

.text-reveal__space {
  display: inline-block;
  flex-shrink: 0;
}

.text-reveal.is-revealed .text-reveal__item {
  animation-fill-mode: forwards;
  animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1); /* power2.out */
}

/* ---- Effects ---- */
@keyframes tr-revealX           { from { transform: translateX(20px);                opacity: 0; filter: blur(var(--tr-blur, 10px)); }
                                  to   { transform: translateX(0);                   opacity: 1; filter: blur(0); } }
@keyframes tr-revealY           { from { transform: translateY(20px);                opacity: 0; filter: blur(var(--tr-blur, 10px)); }
                                  to   { transform: translateY(0);                   opacity: 1; filter: blur(0); } }
@keyframes tr-revealXY          { from { transform: translate(20px, 20px);           opacity: 0; filter: blur(var(--tr-blur, 10px)); }
                                  to   { transform: translate(0, 0);                 opacity: 1; filter: blur(0); } }
@keyframes tr-revealXReverse    { from { transform: translateX(-20px);               opacity: 0; filter: blur(var(--tr-blur, 10px)); }
                                  to   { transform: translateX(0);                   opacity: 1; filter: blur(0); } }
@keyframes tr-revealYReverse    { from { transform: translateY(-20px);               opacity: 0; filter: blur(var(--tr-blur, 10px)); }
                                  to   { transform: translateY(0);                   opacity: 1; filter: blur(0); } }
@keyframes tr-revealXYReverse   { from { transform: translate(-20px, -20px);         opacity: 0; filter: blur(var(--tr-blur, 10px)); }
                                  to   { transform: translate(0, 0);                 opacity: 1; filter: blur(0); } }
@keyframes tr-scale             { from { transform: scale(0.5);                      opacity: 0; filter: blur(var(--tr-blur, 10px)); }
                                  to   { transform: scale(1);                        opacity: 1; filter: blur(0); } }

@media (prefers-reduced-motion: reduce) {
  .text-reveal__item { opacity: 1 !important; animation: none !important; transform: none !important; filter: none !important; }
}
