/* ==========================================================================
   FX - fluid scroll animation layer (loads on every public page)
   Everything is gated by html.fx, which only stays on if fx.js runs and the
   visitor has not asked for reduced motion. Without it the site looks as before.
   ========================================================================== */
html.fx-glide { scroll-behavior: auto !important; }

/* 1. Upgraded reveal for existing .animate-on-scroll elements */
html.fx :where(.animate-on-scroll) {
    translate: 0 28px; filter: blur(8px);
    transition: opacity 1s cubic-bezier(.16,1,.3,1), transform 1.1s cubic-bezier(.16,1,.3,1),
                translate 1.1s cubic-bezier(.16,1,.3,1), filter 1s cubic-bezier(.16,1,.3,1);
}
html.fx .animate-on-scroll.in-view { translate: 0 0; filter: none; }

/* 2. Word-by-word headings */
.fx-w { display: inline-block; overflow: hidden; vertical-align: top; padding-bottom: .14em; margin-bottom: -.14em; }
.fx-w > i { display: inline-block; font-style: normal; transform: translateY(120%);
            transition: transform 1s cubic-bezier(.16,1,.3,1); }
.fx-in .fx-w > i { transform: none; }
html.fx .fx-words, html.fx .fx-lit { opacity: 1 !important; transform: none !important; filter: none !important;
            translate: none !important; transition: none !important; }

/* 3. Scroll-lit words */
.fx-lw { opacity: .16; transition: opacity .25s linear; }

/* 4. Curtain image reveal */
html.fx .fx-cur { clip-path: inset(0 0 100% 0); transition: clip-path 1.2s cubic-bezier(.77,0,.18,1); }
html.fx .fx-cur.fx-in { clip-path: inset(0 0 0 0); }

/* 5. Progress line and cursor blob */
.fx-bar { position: fixed; top: 0; left: 0; width: 100%; height: 3px; transform: scaleX(0); transform-origin: 0 50%;
          background: var(--color-accent, #1e90ff); z-index: 10000; pointer-events: none; }
.fx-blob { position: fixed; left: 0; top: 0; width: 26px; height: 26px; margin: -13px 0 0 -13px; border-radius: 50%;
           background: #fff; mix-blend-mode: difference; pointer-events: none; z-index: 10001; opacity: 0; transition: opacity .3s; }
.fx-blob.on { opacity: 1; }

/* 6. Page-change curtain (replaces the old fade) */
.page-transition { opacity: 1 !important; background: #0b0b0c !important; transform: translateY(-100%);
                   transition: transform .6s cubic-bezier(.77,0,.18,1) !important; }
.page-transition.fade-in { transform: translateY(0); }
.page-transition.fade-out { transform: translateY(-100%); }
html.fx-arrive body::after { content: ""; position: fixed; inset: 0; background: #0b0b0c; z-index: 9998;
                             pointer-events: none; animation: fxUp .8s .08s cubic-bezier(.77,0,.18,1) forwards; }
@keyframes fxUp { to { transform: translateY(-100%); } }
