/* ============================================================
   TEXT REVEAL · masked line rise, site-wide
   Paired with text-reveal.js, which does the splitting and the timing.

   The recipe is the Overide hero heading (overide-hero.liquid, "masked line
   reveal"), measured off its reference frame by frame: each line sits in a
   clipping mask and rises from below on a 7deg tilt that levels out as
   it lands, opacity 0 to 1 alongside, ~1s on a quad-out curve, 130ms stagger
   per line. Whole lines move, never characters.

   Two treatments:
     .tr-mask / .tr-line   headings, prose, labels — built by the splitter
     .tr-rise              buttons and small one-off items — the element itself
                           rises out of a gradient mask, no DOM change
                           (Overide's "text rise" for its overline and buttons)

   Every hidden state here is only ever applied by JS. With no JS the text is
   plain and visible, so nothing can be lost to a failed script.
   ============================================================ */

:root {
  --tr-line-ms: 1000ms;
  --tr-stagger: 130ms;
  --tr-ease: cubic-bezier(0.4, 1, 0.7, 1);        /* quad/cubic-out, as measured */
  --tr-rise-ms: 900ms;
  --tr-rise-ease: cubic-bezier(0.25, 1, 0.5, 1);  /* quart-out */
}

/* ── Lines ─────────────────────────────────────────────────
   The mask clips the rising line. Headroom is needed so a tight line-height
   cannot shave ascenders or descenders at the clip edge (this site sets
   Playfair at 0.9 to 0.95 with real descenders), and it comes from a
   clip-path with NEGATIVE insets: the clip region reaches 0.25em past the box
   while the box itself is exactly the line, so layout is untouched.

   Not `overflow: hidden` with `padding: 0.25em; margin: -0.25em` (Overide's
   version). That only cancels out for a single mask: between two stacked
   masks the two negative margins COLLAPSE into one, so half the padding
   survives and every line gap grows by 0.25em. The lines then landed 20 to
   40px below their authored position and jumped up when the markup was
   restored — read as the text stopping and then finishing. The line starts at
   125% so nothing peeks through the headroom before it moves. */
.tr-mask {
  display: block;
  -webkit-clip-path: inset(-0.25em 0);
          clip-path: inset(-0.25em 0);
}

.tr-line {
  display: block;
  opacity: 0;
  transform: translateY(125%) rotate(7deg);
  transform-origin: 0% 100%;   /* far end swings up into place */
  will-change: transform, opacity;
}

.tr-in .tr-line {
  animation: tr-line-in var(--tr-line-ms) var(--tr-ease) calc(var(--li, 0) * var(--tr-stagger)) both;
}

@keyframes tr-line-in {
  from { opacity: 0; transform: translateY(125%) rotate(7deg); }
  to   { opacity: 1; transform: translateY(0) rotate(0deg); }
}

/* ── Rise ──────────────────────────────────────────────────
   A gradient mask whose height grows from nothing to past the element, so it
   is unveiled bottom-up while lifting 24px. The mask sits on the element
   itself: buttons keep their icon, gap and padding untouched. */
.tr-rise {
  opacity: 0;
  -webkit-mask-image: linear-gradient(to top, transparent 0%, #000 22%);
          mask-image: linear-gradient(to top, transparent 0%, #000 22%);
  -webkit-mask-repeat: no-repeat;
          mask-repeat: no-repeat;
  -webkit-mask-size: 100% 0%;
          mask-size: 100% 0%;
  -webkit-mask-position: top;
          mask-position: top;
}

.tr-rise.tr-in {
  animation: tr-rise-in var(--tr-rise-ms) var(--tr-rise-ease) calc(var(--li, 0) * var(--tr-stagger)) both;
}

@keyframes tr-rise-in {
  0% {
    -webkit-mask-size: 100% 0%;
            mask-size: 100% 0%;
    transform: translateY(24px);
    opacity: 0;
  }
  100% {
    -webkit-mask-size: 100% 140%;
            mask-size: 100% 140%;
    transform: translateY(0);
    opacity: 1;
  }
}

/* ── Reduced motion ────────────────────────────────────────
   text-reveal.js does not run at all for these visitors, so nothing below is
   ever applied; kept as a belt to the braces in case a class survives. */
@media (prefers-reduced-motion: reduce) {
  .tr-line, .tr-rise {
    opacity: 1 !important;
    transform: none !important;
    animation: none !important;
    -webkit-mask-image: none !important;
            mask-image: none !important;
  }
}
