/* ---------------- SCROLL REVEAL (index, 2026-10-25) -----------------------------
   Headings and key blocks below the hero fly in like the intro words (small
   offset, tilted, settle with a soft ease, no bounce) and headings additionally
   "glitch in" for ~420 ms: two colour copies of the text (::before red, ::after
   blue) show as offset horizontal slices while the text itself briefly loses a
   band. Everything is transform / opacity / clip-path only.

   Nothing here applies without JS: js/scroll-reveal.js adds .lx-pre (hidden),
   then .lx-in (reveal, once per element), then removes both when the motion
   is over, so the element is back to its plain stylesheet state. */

.lx-pre { opacity: 0; transform: translate(-22px, 30px) rotate(-7deg); transform-origin: 50% 100%; will-change: transform, opacity; }
.lx-pre.lx-in { opacity: 1; transform: none;
  transition: opacity .55s ease-out var(--lx-d, 0s), transform .9s cubic-bezier(.22, 1, .36, 1) var(--lx-d, 0s); }

/* Glitch-in: text copies as RGB-split slices + a brief band cut on the text itself */
.lx-glitch { position: relative; }
.lx-glitch.lx-in { animation: lx-cut .42s steps(1, end) var(--lx-d, 0s) both; }
.lx-glitch.lx-in::before,
.lx-glitch.lx-in::after {
  content: attr(data-text);
  position: absolute; inset: 0; pointer-events: none; white-space: inherit;
  background: none; opacity: 0;
  animation-duration: .42s; animation-timing-function: steps(1, end); animation-delay: var(--lx-d, 0s); animation-fill-mode: both;
}
.lx-glitch.lx-in::before { color: #e2313b; -webkit-text-fill-color: #e2313b; animation-name: lx-rgb-a; }
.lx-glitch.lx-in::after  { color: #3b8dff; -webkit-text-fill-color: #3b8dff; animation-name: lx-rgb-b; }

@keyframes lx-cut {
  0%, 18%  { clip-path: inset(0 0 0 0); }
  18.1%, 26% { clip-path: inset(0 0 58% 0); }    /* lower part drops out */
  26.1%, 44% { clip-path: inset(0 0 0 0); }
  44.1%, 52% { clip-path: inset(38% 0 0 0); }    /* upper part drops out */
  52.1%, 66% { clip-path: inset(0 0 0 0); }
  66.1%, 72% { clip-path: inset(0 0 30% 0); }
  72.1%, 100% { clip-path: inset(0 0 0 0); }
}
@keyframes lx-rgb-a {
  0%   { opacity: .9; clip-path: inset(10% 0 55% 0); transform: translateX(-9px); }
  18%  { opacity: .9; clip-path: inset(42% 0 20% 0); transform: translateX(7px); }
  34%  { opacity: .9; clip-path: inset(0 0 66% 0);  transform: translateX(-5px); }
  52%  { opacity: .8; clip-path: inset(60% 0 8% 0);  transform: translateX(8px); }
  70%  { opacity: .7; clip-path: inset(22% 0 48% 0); transform: translateX(-3px); }
  84%  { opacity: .5; clip-path: inset(0 0 80% 0);  transform: translateX(2px); }
  100% { opacity: 0;  clip-path: inset(0 0 100% 0); transform: none; }
}
@keyframes lx-rgb-b {
  0%   { opacity: .9; clip-path: inset(50% 0 12% 0); transform: translateX(8px); }
  18%  { opacity: .9; clip-path: inset(0 0 70% 0);   transform: translateX(-6px); }
  34%  { opacity: .9; clip-path: inset(30% 0 36% 0); transform: translateX(6px); }
  52%  { opacity: .8; clip-path: inset(6% 0 62% 0);  transform: translateX(-8px); }
  70%  { opacity: .7; clip-path: inset(66% 0 4% 0);  transform: translateX(3px); }
  84%  { opacity: .5; clip-path: inset(84% 0 0 0);   transform: translateX(-2px); }
  100% { opacity: 0;  clip-path: inset(100% 0 0 0);  transform: none; }
}

/* Reduced motion and low-power: plain fade only, no tilt, no glitch */
@media (prefers-reduced-motion: reduce) {
  .lx-pre { transform: none; }
  .lx-pre.lx-in { transition: opacity .5s ease; }
  .lx-glitch.lx-in { animation: none; }
  .lx-glitch.lx-in::before, .lx-glitch.lx-in::after { content: none; animation: none; }
}
html.low-power .lx-pre { transform: none; }
html.low-power .lx-glitch.lx-in::before, html.low-power .lx-glitch.lx-in::after { content: none; }
