/* Spectra: type-fx (js/type-fx.js). Two opt-in text effects ported from the About page: data-fx="lens" and data-fx="sweep".
   The module only adds spans; every heading keeps its own font, size and layout. Text stays real: a visually hidden
   copy (.fx-sr) is read by screen readers, the letter spans are aria-hidden. */
.fx-sr{position:absolute!important;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}
.fx-w{display:inline-block;white-space:nowrap}

/* ---------- lens: white light refracts into colour under the cursor, then settles (About's `flare`) ---------- */
.fx-lens .fx-l{display:inline-block;position:relative}
@keyframes fx-flare{
  0%{text-shadow:0 0 0 rgba(251,26,8,0),0 0 0 rgba(48,69,224,0)}
  35%{color:var(--lc);text-shadow:-.06em 0 rgba(251,26,8,.75),.06em 0 rgba(48,69,224,.75)}
  100%{text-shadow:0 0 0 rgba(251,26,8,0),0 0 0 rgba(48,69,224,0)}
}
.fx-lens .fx-l.hot{animation:fx-flare .9s var(--ease,cubic-bezier(.2,.8,.2,1)) 1}
/* no hover (touch): one slow pass across the letters, first time the heading scrolls in */
@media (hover:none){
  .fx-lens .fx-l.pass{animation:fx-flare 1.5s var(--ease,cubic-bezier(.2,.8,.2,1)) 1;animation-delay:calc(var(--n)*70ms + 200ms)}
}

/* ---------- sweep: dim, then red > orange > cream, then white and settled. Driven by scroll (--o, --w per letter) ---------- */
.fx-sweep .fx-l{color:color-mix(in srgb,var(--lc) calc(var(--w,0)*100%),var(--ink,#fcfcfc));opacity:var(--o,1)}

@media (prefers-reduced-motion:reduce){
  .fx-lens .fx-l{animation:none!important}
  .fx-sweep .fx-l{color:inherit!important;opacity:1!important}
}
