/* ==========================================================================
   motion-effects.css — Reusable animation & interaction library
   --------------------------------------------------------------------------
   A standalone, content-free effects library recreating the *types* of
   motion found on modern corporate sites (scroll reveals, clip reveals,
   counters, sticky smart header, crossfade slider, hover effects...).

   Pair with motion-effects.js. No frameworks, no dependencies.

   USAGE (quick reference — see README for full docs):
     Scroll reveals .... <div data-fx="fade-up">            (JS + CSS)
     Group stagger ..... <ul data-fx-group="fade-up" data-fx-stagger="0.15">
     Clip reveal ....... <figure data-fx="clip-reveal"><img ...></figure>
     Text lines ........ <h2 data-fx="lines">Your headline</h2>
     Counter ........... <span data-fx-counter="12500"></span>
     Parallax .......... <div data-fx-parallax="0.25">
     Grow (scrub) ...... <div data-fx="grow">
     Smart header ...... <header class="fx-header">
     Slider ............ <div class="fx-slider"> ... (see README)
     Marquee ........... <div class="fx-marquee"><div class="fx-marquee__track">...
     Hover FX .......... .fx-hover-zoom  .fx-hover-lift  .fx-underline
                         .fx-btn-sweep   .fx-hover-shift .fx-hover-rotate
     Overlay ........... <button data-fx-toggle="#panel"> + .fx-overlay
   ========================================================================== */

:root {
  /* Tweak these to re-theme every effect at once */
  --fx-duration: 1s;              /* default reveal duration   */
  --fx-ease: cubic-bezier(.455, .03, .515, .955);  /* easeInOut  */
  --fx-ease-out: cubic-bezier(.25, .46, .45, .94); /* easeOut    */
  --fx-distance: 40px;            /* reveal travel distance    */
  --fx-hover-speed: .3s;          /* hover transition speed    */
  --fx-accent: #2551a3;           /* accent used by hover fx   */
  --fx-header-speed: .35s;        /* header hide/show speed    */
  --fx-zoom-scale: 1.12;          /* image zoom-on-hover scale */
}

/* ==========================================================================
   1. SCROLL REVEALS
   Elements start hidden; JS adds .fx-in when they enter the viewport.
   ========================================================================== */

[data-fx] {
  opacity: 0;
  transition:
    opacity var(--fx-duration) var(--fx-ease),
    transform var(--fx-duration) var(--fx-ease),
    clip-path var(--fx-duration) var(--fx-ease),
    filter var(--fx-duration) var(--fx-ease);
  transition-delay: var(--fx-delay, 0s);
  will-change: opacity, transform;
}

[data-fx="fade-up"]    { transform: translate3d(0,  var(--fx-distance), 0); }
[data-fx="fade-down"]  { transform: translate3d(0, calc(var(--fx-distance) * -1), 0); }
[data-fx="fade-left"]  { transform: translate3d(calc(var(--fx-distance) * -1), 0, 0); }
[data-fx="fade-right"] { transform: translate3d(var(--fx-distance), 0, 0); }
[data-fx="fade-in"]    { transform: none; }
[data-fx="zoom-in"]    { transform: scale(.8); }
[data-fx="zoom-out"]   { transform: scale(1.2); }
[data-fx="blur-in"]    { filter: blur(12px); transform: none; }

/* Revealed state */
[data-fx].fx-in {
  opacity: 1;
  transform: none;
  filter: none;
  clip-path: inset(0 0 0 0);
}

/* --- Clip reveal: mask wipes open while the image settles from a zoom --- */
[data-fx="clip-reveal"] {
  opacity: 1;                                   /* the mask does the hiding */
  /* 1px sliver kept visible so IntersectionObserver can still fire */
  clip-path: inset(0 0 calc(100% - 1px) 0);     /* hidden: wiped up          */
  overflow: hidden;
  display: block;
}
[data-fx="clip-reveal"][data-fx-direction="left"]  { clip-path: inset(0 calc(100% - 1px) 0 0); }
[data-fx="clip-reveal"][data-fx-direction="right"] { clip-path: inset(0 0 0 calc(100% - 1px)); }
[data-fx="clip-reveal"][data-fx-direction="up"]    { clip-path: inset(calc(100% - 1px) 0 0 0); }
[data-fx="clip-reveal"] > img,
[data-fx="clip-reveal"] > picture img,
[data-fx="clip-reveal"] > .fx-clip-inner {
  display: block;
  width: 100%;
  transform: scale(1.4);                        /* matches the 1.4 -> 1 settle */
  transition: transform calc(var(--fx-duration) * 1.4) var(--fx-ease);
  transition-delay: var(--fx-delay, 0s);
}
[data-fx="clip-reveal"].fx-in > img,
[data-fx="clip-reveal"].fx-in > picture img,
[data-fx="clip-reveal"].fx-in > .fx-clip-inner { transform: scale(1); }

/* --- Line / word reveal (JS wraps content in .fx-line / .fx-word) --- */
[data-fx="lines"], [data-fx="words"] { opacity: 1; transform: none; }
.fx-line-mask { display: block; overflow: hidden; }
.fx-line, .fx-word {
  display: inline-block;
  transform: translate3d(0, 110%, 0);
  opacity: 0;
  transition:
    transform .6s cubic-bezier(.075, .82, .165, 1),   /* circ.out feel */
    opacity   .6s cubic-bezier(.075, .82, .165, 1);
  transition-delay: var(--fx-delay, 0s);
}
.fx-word { transform: translate3d(0, 100%, 0); margin-right: .28em; }
.fx-in .fx-line, .fx-in .fx-word { transform: translate3d(0, 0, 0); opacity: 1; }

/* --- Grow: scrub-style scale-up driven by scroll progress (JS sets var) --- */
[data-fx="grow"] {
  opacity: 1;
  transition: none;
  transform: scale(calc(.82 + .18 * var(--fx-progress, 0)));
  transform-origin: center center;
}

/* Parallax elements are driven entirely by JS */
[data-fx-parallax] { will-change: transform; }

/* ==========================================================================
   2. SMART STICKY HEADER
   .fx-header--scrolled  -> page is scrolled past threshold (style hook)
   .fx-header--hidden    -> scrolling down: slide the header away
   ========================================================================== */

.fx-header {
  position: fixed;
  top: 0; left: 0; right: 0;
  z-index: 1000;
  transition:
    transform var(--fx-header-speed) ease-out,
    box-shadow var(--fx-header-speed) ease-out,
    background-color var(--fx-header-speed) ease-out;
}
.fx-header--hidden { transform: translateY(-110%); }
.fx-header--scrolled { box-shadow: 0 6px 24px rgba(0, 0, 0, .12); }

/* ==========================================================================
   3. CROSSFADE SLIDER  (hero-style: fading slides + re-animating captions)
   Markup:
   <div class="fx-slider" data-fx-autoplay="7000" data-fx-speed="1200">
     <div class="fx-slide">
       <img class="fx-slide__bg" src="...">
       <div class="fx-slide__content">
         <h1 data-fx-caption>Title</h1>
         <p data-fx-caption>Subtitle</p>
         <a  data-fx-caption href="#">Call to action</a>
       </div>
     </div>
     ...more .fx-slide...
   </div>
   Pagination (progress lines) is generated automatically.
   ========================================================================== */

.fx-slider { position: relative; overflow: hidden; }
.fx-slide {
  position: absolute;
  inset: 0;
  opacity: 0;
  transition: opacity var(--fx-slider-speed, 1.2s) ease;
  pointer-events: none;
}
.fx-slide.is-active { opacity: 1; pointer-events: auto; z-index: 1; }
.fx-slide:first-child { position: relative; } /* gives the slider height */
.fx-slide__bg {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
}
.fx-slide__content { position: relative; z-index: 2; }

/* Captions: slide out upward on leave, in from below on enter (staggered) */
[data-fx-caption] {
  opacity: 0;
  transform: translate3d(0, 40px, 0);
  transition:
    opacity .8s var(--fx-ease-out),
    transform .8s var(--fx-ease-out);
}
.fx-slide.is-active [data-fx-caption] {
  opacity: 1;
  transform: none;
  transition-delay: calc(.35s + var(--fx-i, 0) * .15s); /* 0.15s stagger */
}
.fx-slide.is-leaving [data-fx-caption] {
  opacity: 0;
  transform: translate3d(0, -40px, 0);                  /* exit upward */
  transition:
    opacity .4s cubic-bezier(.55, .085, .68, .53),
    transform .4s cubic-bezier(.55, .085, .68, .53);
  transition-delay: calc(var(--fx-i, 0) * .05s);
}

/* Progress-line pagination (thin bars, active bar fills) */
.fx-slider__pagination {
  position: absolute;
  left: 0; right: 0; bottom: 28px;
  display: flex; gap: 14px;
  justify-content: flex-start;
  padding: 0 6%;
  z-index: 3;
}
.fx-slider__bullet {
  width: 44px; height: 3px;
  border: 0; padding: 0;
  background: rgba(255, 255, 255, .35);
  cursor: pointer;
  position: relative;
  overflow: hidden;
  transition: background var(--fx-hover-speed) ease-out;
}
.fx-slider__bullet::after {
  content: "";
  position: absolute; inset: 0;
  background: #fff;
  transform: scaleX(0);
  transform-origin: left center;
}
.fx-slider__bullet.is-active::after {
  transform: scaleX(1);
  transition: transform var(--fx-slider-delay, 7s) linear;
}
.fx-slider__bullet:hover { background: rgba(255, 255, 255, .6); }

/* ==========================================================================
   4. HOVER EFFECTS (pure CSS)
   ========================================================================== */

/* Image zoom: <a class="fx-hover-zoom"><img ...></a> */
.fx-hover-zoom { display: block; overflow: hidden; }
.fx-hover-zoom img {
  display: block; width: 100%;
  transition: transform .6s var(--fx-ease-out);
  will-change: transform;
}
.fx-hover-zoom:hover img { transform: scale(var(--fx-zoom-scale)); }

/* Card lift */
.fx-hover-lift {
  transition:
    transform var(--fx-hover-speed) ease-out,
    box-shadow var(--fx-hover-speed) ease-out;
}
.fx-hover-lift:hover {
  transform: translateY(-6px);
  box-shadow: 0 18px 40px rgba(0, 0, 0, .16);
}

/* Animated underline that slides in from the left */
.fx-underline {
  position: relative;
  text-decoration: none;
  background-image: linear-gradient(currentColor, currentColor);
  background-repeat: no-repeat;
  background-position: left 100%;
  background-size: 0% 2px;
  transition: background-size .35s var(--fx-ease-out);
}
.fx-underline:hover { background-size: 100% 2px; }

/* Button color-sweep: background fills from the left on hover */
.fx-btn-sweep {
  position: relative;
  display: inline-block;
  overflow: hidden;
  isolation: isolate;
  transition: color var(--fx-hover-speed) ease-out;
}
.fx-btn-sweep::before {
  content: "";
  position: absolute; inset: 0;
  background: var(--fx-accent);
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform var(--fx-hover-speed) ease-out;
  z-index: -1;
}
.fx-btn-sweep:hover { color: #fff; }
.fx-btn-sweep:hover::before { transform: scaleX(1); }

/* Simple color/bg swap (the classic .3s ease-out) */
.fx-btn-swap {
  transition:
    background-color var(--fx-hover-speed) ease-out,
    color var(--fx-hover-speed) ease-out,
    border-color var(--fx-hover-speed) ease-out;
}
.fx-btn-swap:hover {
  background-color: var(--fx-accent);
  color: #fff;
  border-color: var(--fx-accent);
}

/* Nav-link shift: text nudges right & recolors (menu-item hover) */
.fx-hover-shift {
  transition:
    padding-left var(--fx-hover-speed) ease-out,
    color var(--fx-hover-speed) ease-out;
}
.fx-hover-shift:hover { padding-left: 10px; color: var(--fx-accent); }

/* Icon rotate (e.g. a "+" turning into an "x", arrows tilting) */
.fx-hover-rotate { transition: transform var(--fx-hover-speed) ease-out; display: inline-block; }
.fx-hover-rotate:hover,
.is-open .fx-hover-rotate,
.fx-hover-rotate.is-open { transform: rotate(45deg); }

/* Arrow nudge: child .fx-arrow slides right on parent hover */
.fx-arrow { display: inline-block; transition: transform var(--fx-hover-speed) ease-out; }
a:hover > .fx-arrow, button:hover > .fx-arrow { transform: translateX(6px); }

/* Image tint / darken on hover (for cards with text over images) */
.fx-hover-tint { position: relative; display: block; overflow: hidden; }
.fx-hover-tint::after {
  content: "";
  position: absolute; inset: 0;
  background: rgba(0, 0, 0, 0);
  transition: background var(--fx-hover-speed) ease-out;
  pointer-events: none;
}
.fx-hover-tint:hover::after { background: rgba(0, 0, 0, .35); }

/* ==========================================================================
   5. MARQUEE / TICKER
   <div class="fx-marquee" data-fx-marquee-speed="60">
     <div class="fx-marquee__track"> ...items... </div>
   </div>
   JS duplicates the track for a seamless loop.
   ========================================================================== */

.fx-marquee { overflow: hidden; display: flex; }
.fx-marquee__track {
  display: flex;
  flex-shrink: 0;
  align-items: center;
  gap: var(--fx-marquee-gap, 48px);
  padding-right: var(--fx-marquee-gap, 48px);
  animation: fx-marquee var(--fx-marquee-duration, 20s) linear infinite;
}
.fx-marquee:hover .fx-marquee__track { animation-play-state: paused; }
@keyframes fx-marquee {
  from { transform: translateX(0); }
  to   { transform: translateX(-100%); }
}

/* ==========================================================================
   6. OVERLAY PANEL (fullscreen search / menu pattern)
   <button data-fx-toggle="#search">open</button>
   <div class="fx-overlay" id="search"> ... <button data-fx-close>×</button></div>
   ========================================================================== */

.fx-overlay {
  position: fixed; inset: 0;
  z-index: 2000;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(10, 10, 14, .96);
  opacity: 0;
  visibility: hidden;
  transform: scale(1.04);
  transition:
    opacity .45s ease-out,
    transform .45s ease-out,
    visibility 0s linear .45s;
}
.fx-overlay.is-open {
  opacity: 1;
  visibility: visible;
  transform: scale(1);
  transition:
    opacity .45s ease-out,
    transform .45s ease-out,
    visibility 0s;
}
/* children rise as the overlay opens */
.fx-overlay > * {
  transform: translateY(24px);
  opacity: 0;
  transition: transform .5s var(--fx-ease-out) .15s, opacity .5s var(--fx-ease-out) .15s;
}
.fx-overlay.is-open > * { transform: none; opacity: 1; }

/* ==========================================================================
   7. DROPDOWN / MEGA-MENU reveal (pure CSS, hover or .is-open)
   ========================================================================== */

.fx-dropdown { position: relative; }
.fx-dropdown__panel {
  position: absolute;
  top: 100%; left: 0;
  opacity: 0;
  visibility: hidden;
  transform: translateY(12px);
  transition:
    opacity var(--fx-hover-speed) ease-out,
    transform var(--fx-hover-speed) ease-out,
    visibility 0s linear var(--fx-hover-speed);
}
.fx-dropdown:hover > .fx-dropdown__panel,
.fx-dropdown:focus-within > .fx-dropdown__panel,
.fx-dropdown.is-open > .fx-dropdown__panel {
  opacity: 1;
  visibility: visible;
  transform: translateY(0);
  transition:
    opacity var(--fx-hover-speed) ease-out,
    transform var(--fx-hover-speed) ease-out,
    visibility 0s;
}

/* ==========================================================================
   8. ACCESSIBILITY — respect reduced-motion preferences
   ========================================================================== */

@media (prefers-reduced-motion: reduce) {
  [data-fx],
  [data-fx="clip-reveal"] > img,
  .fx-line, .fx-word,
  [data-fx-caption],
  .fx-marquee__track,
  .fx-hover-zoom img,
  .fx-hover-lift, .fx-overlay {
    transition: none !important;
    animation: none !important;
  }
  [data-fx] { opacity: 1; transform: none; filter: none; clip-path: none; }
  .fx-line, .fx-word, [data-fx-caption] { opacity: 1; transform: none; }
}
