/* Split-text rise. Measured from Heron AI's SplitTextReveal + RevealGroup (teardown 09-30), rewritten with our
   names and no GSAP. Every word sits in its own clipped box and rises one full line height while fading in;
   words follow each other by 20ms, and the blocks of one group (label, title, sub) follow each other by 100ms.
   Knobs live on :root so any ancestor (a group, a section) can override them. Tilt mode (Mova) is at the end. */
:root {
  --rise-duration: .8s;                                /* per word */
  --rise-stagger: .02s;                                /* between words (or lines) inside one block */
  --rise-ease: cubic-bezier(.215, .61, .355, 1);       /* GSAP power2.out (cubic out) */
  --rise-y: 100%;                                      /* travel, in % of the word's own line box */
  --rise-bleed: .1em;                                  /* ours: widens the clip so descenders and tight
                                                          headings are not cut; set 0 for the raw source mask */
  --rise-group-stagger: .1;                            /* seconds between blocks of a group (read by part.js) */
  --rise-start: .55;                                   /* play when this fraction of the group is above the
                                                          viewport's bottom edge (read by part.js) */
}

/* Hide only what part.js is about to split, so there is no flash of unsplit text. No JS = plain text. */
.rise-js [data-rise]:not([data-rise-state]) { visibility: hidden; }

.rise-mask {
  display: inline-block;
  vertical-align: top;
  overflow: clip;
  padding-block: var(--rise-bleed);
  margin-block: calc(-1 * var(--rise-bleed));        /* layout neutral: the bleed only widens the clip */
}
.rise-word {
  display: inline-block;
  opacity: 0;
  transform: translateY(calc(var(--rise-y) + 2 * var(--rise-bleed)));
  transition: transform var(--rise-duration) var(--rise-ease), opacity var(--rise-duration) var(--rise-ease);
  transition-delay: calc(var(--rise-at, 0s) + var(--i, 0) * var(--rise-stagger));
}
[data-rise-state="on"] .rise-word { opacity: 1; transform: none; }

/* Tilt mode, data-rise="tilt" (Mova's titleGlobalAnim, teardown 10-05): whole lines, each in its own clip, start
   130% down and tilted 20deg about the line's LEFT edge, and swing up level over 1.4s power3.out, .1s apart. No fade.
   The block swaps the word knobs for the tilt knobs, so play() times the un-split from the same variables. */
:root {
  --rise-tilt-angle: 20deg;                            /* start tilt, pivoting on each line's left edge */
  --rise-tilt-y: 130%;                                 /* start drop, in % of the line's own box */
  --rise-tilt-duration: 1.4s;
  --rise-tilt-stagger: .1s;                            /* between lines */
  /* GSAP power3.out = 1-(1-t)^4, sampled (17 stops, max error .002) */
  --rise-tilt-ease: linear(0, 0.1335 3.52%, 0.2491 6.91%, 0.3494 10.19%, 0.4565 14.14%, 0.546 17.91%, 0.6379 22.43%,
    0.7112 26.69%, 0.7828 31.73%, 0.8366 36.42%, 0.8859 41.88%, 0.9276 48.12%, 0.9593 55.09%, 0.9805 62.62%,
    0.9942 72.42%, 0.9999 90.07%, 1);
  --rise-tilt-bleed: 10px;                             /* clip room above the line (source: padding-top 10px, margin -10px) */
  --rise-tilt-bleed-bottom: 0px;                       /* ours: room for descenders below a tight line-height */
  --rise-tilt-start: 100px;                            /* play when the block's top is this far above the window bottom
                                                          (read by part.js; ScrollTrigger "100px bottom") */
}
@supports not (transition-timing-function: linear(0, 1)) {
  :root { --rise-tilt-ease: cubic-bezier(.165, .84, .44, 1); }   /* easeOutQuart, max error .044 */
}
[data-rise="tilt"] {
  --rise-duration: var(--rise-tilt-duration);
  --rise-stagger: var(--rise-tilt-stagger);
  --rise-ease: var(--rise-tilt-ease);
}
.rise-line {
  display: inline-flex;
  overflow: hidden;
  overflow: clip;
  padding-top: var(--rise-tilt-bleed);
  margin-top: calc(-1 * var(--rise-tilt-bleed));
  padding-bottom: var(--rise-tilt-bleed-bottom);
  margin-bottom: calc(-1 * var(--rise-tilt-bleed-bottom));
}
.rise-line > .rise-word {
  white-space: nowrap;
  opacity: 1;
  transform: translateY(var(--rise-tilt-y)) rotate(var(--rise-tilt-angle));
  transform-origin: 0 50%;
  transition-property: transform;
}
[data-rise-state="on"] .rise-line > .rise-word { transform: none; }
