/* ==========================================================================
   Tahoorestan — motion layer
   Everything here is *additive polish* over the measured clone in styles.css.
   The rule that keeps it honest: every effect resolves to the clone's own
   resting state.  Reveals end at `transform:none / opacity:1` and their marker
   classes are stripped once they finish, hovers only extend the hover language
   styles.css already defines, and the ambient loops touch nothing that was
   measured against the export.

   The whole file is gated behind `html.fx-on`, which:
     * a 4-line script in <head> sets, and only when the visitor has not asked
       for reduced motion and `?fx=off` is absent,
     * that same script removes again if fx.js has not confirmed within 3s,
       so a missing or broken script can never leave content hidden.
   Drop the class (or the <link>) and the page is the clone again, pixel for
   pixel — which is also how .clone-ui's measuring tools should run it.
   ========================================================================== */

/* ─────────────────────── 1. scroll reveal ───────────────────────
   fx.js tags elements with .fx + a variant; the variant supplies the "from"
   transform, .is-in returns to rest, and the class pair is removed on
   transitionend so nothing stays declared over the clone. */
:root{--fx-e:cubic-bezier(.22,.68,.26,1)}

.fx-on .fx{
  opacity:0;
  will-change:opacity,transform;
  transition:
    opacity   .68s var(--fx-e) var(--fx-d,0ms),
    transform .68s var(--fx-e) var(--fx-d,0ms),
    translate .68s var(--fx-e) var(--fx-d,0ms),
    filter    .68s var(--fx-e) var(--fx-d,0ms);
}

/* ── the "from" states ── */
.fx-on .fx--up   {transform:translateY(26px)}
.fx-on .fx--down {transform:translateY(-20px)}
.fx-on .fx--pop  {transform:translateY(16px) scale(.94)}
.fx-on .fx--zoom {transform:scale(1.05)}
/* comes in from the inline-start edge — the right, in RTL */
.fx-on .fx--start{transform:translateX(var(--fx-sx,-38px))}
[dir=rtl] .fx--start{--fx-sx:38px}
/* `lift` drives the individual `translate` property instead, so it composes
   with an element the clone already offsets by hand (.hero__title is nudged
   -7.5px, .count and .plate__sub--green by 8px) rather than wiping it. */
.fx-on .fx--lift {translate:0 26px}
/* `soft` moves no geometry at all, for a carousel slide: Carousel reads slide
   offsets with getBoundingClientRect(), which a transform would skew. */
.fx-on .fx--soft {filter:blur(9px)}

/* ── ...and back to rest, each variant resetting only what it set, so a
      base `transform` / `translate` / `filter` of the clone's own survives ── */
.fx-on .fx.is-in{opacity:1}
.fx-on .fx--up.is-in,.fx-on .fx--down.is-in,.fx-on .fx--pop.is-in,
.fx-on .fx--zoom.is-in,.fx-on .fx--start.is-in{transform:none}
.fx-on .fx--lift.is-in{translate:none}
.fx-on .fx--soft.is-in{filter:none}

/* ───────────────────────── 2. hero ─────────────────────────
   Two ambient layers inside .hero__bg, which already clips (overflow:hidden):
   a slow aurora drift and a sheen that crosses every ~10s.  Both are paused
   the moment the hero leaves the viewport — see .is-rest, set by fx.js. */
.fx-on .hero__bg{
  /* parallax: only the lattice moves, the flat green underneath does not */
  background-position:center calc(50% + var(--hero-par,0px));
}
.fx-on .hero__bg::after{
  content:"";position:absolute;inset:-22%;pointer-events:none;
  background:
    radial-gradient(38% 46% at 24% 30%,rgba(255,255,255,.15),transparent 62%),
    radial-gradient(34% 42% at 78% 66%,rgba(241,183,9,.18),transparent 64%),
    radial-gradient(30% 36% at 56% 10%,rgba(255,255,255,.10),transparent 60%);
  animation:fxAurora 21s ease-in-out infinite alternate;
}
.fx-on .hero__bg::before{
  content:"";position:absolute;top:-30%;bottom:-30%;left:-40%;width:36%;
  pointer-events:none;
  background:linear-gradient(90deg,transparent,rgba(255,255,255,.13) 44%,
             rgba(255,255,255,.22) 50%,rgba(255,255,255,.13) 56%,transparent);
  animation:fxSheen 10s ease-in-out 2.4s infinite;
}
.fx-on .hero.is-rest .hero__bg::before,
.fx-on .hero.is-rest .hero__bg::after,
.fx-on .hero.is-rest .shield{animation-play-state:paused}

@keyframes fxAurora{
  0%  {transform:translate3d(-2%,-1%,0) scale(1)}
  50% {transform:translate3d(2%,2.5%,0) scale(1.07)}
  100%{transform:translate3d(-1%,1.5%,0) scale(1.02)}
}
@keyframes fxSheen{
  0%,68%{transform:translateX(0) skewX(-14deg)}
  100%  {transform:translateX(390%) skewX(-14deg)}
}

/* the shield row rides the arc — give it a slow, phase-shifted float */
.fx-on .shield.fx-live{animation:fxBob 5.6s ease-in-out infinite;
  animation-delay:calc(var(--fx-i,0) * -.94s)}
.fx-on .shield:hover,.fx-on .shield:focus-within{animation-play-state:paused}
.fx-on .shield__f{transition:background .2s,transform .28s cubic-bezier(.3,1.2,.5,1)}
.fx-on .shield__f:hover,.fx-on .shield__f:focus-visible{transform:translateY(-4px)}
@keyframes fxBob{0%,100%{transform:translateY(0)}50%{transform:translateY(-5px)}}

/* ───────────── 3. headings: gilt sweep + swash draw ─────────────
   .g-grad is `background-clip:text`, so an extra background layer is clipped
   to the glyphs too — that is the sweep.  .is-lit is one-shot and removed
   afterwards, which restores the clone's exact two-stop gradient. */
.fx-on .g-grad.is-lit{
  background-image:
    linear-gradient(105deg,transparent 38%,rgba(255,255,255,.9) 50%,transparent 62%),
    linear-gradient(90deg,var(--gold) 0%,var(--gold) 26%,var(--green) 78%);
  background-size:230% 100%,auto;
  background-position:-130% 0,0 0;
  animation:fxGilt 1.45s cubic-bezier(.3,.6,.25,1) forwards;
}
@keyframes fxGilt{to{background-position:230% 0,0 0}}

/* the gold swash under a section heading draws out from its inline-start end */
.fx-on .sec__h .swash{transform:scaleX(0);transform-origin:100% 50%;
  transition:transform .6s cubic-bezier(.22,.68,.26,1) .22s}
.fx-on .sec__h.is-in .swash{transform:none}

/* The plate's leaves settle in rather than appearing flat.  One rule covers
   both: .plate__leaf--l carries `scale:-1 1`, and because the individual
   `scale` property is applied *after* `transform`, the same local translate
   reads outward on each side. */
.fx-on .plate__title .plate__leaf{opacity:0;transform:translateX(14px) rotate(6deg);
  transition:opacity .6s ease .18s,transform .6s cubic-bezier(.22,.68,.26,1) .18s}
.fx-on .plate__title.is-in .plate__leaf{opacity:.9;transform:none}

/* ───────────────────── 4. countdown tick ─────────────────────
   fx.js watches #count for text changes and flags the box that moved. */
.fx-on .count__b.is-tick{animation:fxTick .5s cubic-bezier(.3,1.25,.5,1)}
@keyframes fxTick{
  0%  {transform:translateY(-7px) scale(.9);opacity:.35}
  55% {transform:translateY(1px) scale(1.03);opacity:1}
  100%{transform:none;opacity:1}
}

/* ──────────────── 5. cards: pointer spotlight ────────────────
   A radial highlight that tracks the pointer.  Opacity only — no transform —
   so it composes with the --card-lift hover styles.css already owns. */
.fx-on .pcard::after,.fx-on .scard::after,.fx-on .bcard::after,
.fx-on .promo::after{
  content:"";position:absolute;inset:0;z-index:3;pointer-events:none;
  border-radius:inherit;opacity:0;transition:opacity .35s;
  background:radial-gradient(260px circle at var(--mx,50%) var(--my,50%),
             rgba(103,164,53,.13),transparent 62%);
}
.fx-on .bcard::after,.fx-on .promo::after{
  background:radial-gradient(240px circle at var(--mx,50%) var(--my,50%),
             rgba(255,255,255,.34),transparent 60%);
}
.fx-on .pcard:hover::after,.fx-on .scard:hover::after,
.fx-on .bcard:hover::after,.fx-on .promo:hover::after{opacity:1}

/* promo artwork breaks out of its box by design, so it floats rather than
   scaling inside a crop */
.fx-on .promo__img{transition:transform .35s cubic-bezier(.33,.9,.32,1)}
.fx-on .promo:hover .promo__img{transform:translateY(-5px) scale(1.035)}

/* ─────────────── 6. buttons: sheen + ripple ───────────────
   Restricted to the green/gold CTAs, where a white sweep actually reads. */
.fx-on .atc,.fx-on .ncard__cart,.fx-on .search__btn,
.fx-on .track__btn,.fx-on .bcard__go{
  position:relative;overflow:hidden;
}
.fx-on .atc::before,.fx-on .ncard__cart::before,.fx-on .search__btn::before,
.fx-on .track__btn::before,.fx-on .bcard__go::before{
  content:"";position:absolute;top:-60%;bottom:-60%;left:-45%;width:34%;
  pointer-events:none;opacity:0;
  background:linear-gradient(90deg,transparent,rgba(255,255,255,.5),transparent);
  transform:skewX(-18deg);
}
.fx-on .atc:hover::before,.fx-on .ncard__cart:hover::before,
.fx-on .search__btn:hover::before,.fx-on .track__btn:hover::before,
.fx-on .bcard__go:hover::before{opacity:1;animation:fxBtnSheen .72s ease-out}
@keyframes fxBtnSheen{
  from{transform:translateX(0) skewX(-18deg)}
  to  {transform:translateX(430%) skewX(-18deg)}
}

.fx-ripple{position:absolute;border-radius:50%;pointer-events:none;
  background:rgba(255,255,255,.42);transform:scale(0);opacity:.85;
  animation:fxRipple .58s cubic-bezier(.25,.8,.3,1) forwards}
@keyframes fxRipple{to{transform:scale(1);opacity:0}}

/* ───────────── 7. the ghost that flies into the cart ───────────── */
.fx-fly{position:fixed;z-index:120;pointer-events:none;
  object-fit:contain;filter:drop-shadow(0 10px 22px rgba(40,60,20,.3))}

/* ───────────────── 8. scroll progress + ring ─────────────────
   Both elements are built by fx.js, so index.html keeps only the clone's
   own markup. */
.fxprog{position:fixed;top:0;inset-inline:0;height:3px;z-index:41;
  pointer-events:none;background:rgba(103,164,53,.10);
  opacity:0;transition:opacity .3s}
.fxprog.is-on{opacity:1}
.fxprog i{display:block;height:100%;transform-origin:0 50%;
  transform:scaleX(var(--p,0));
  background:linear-gradient(90deg,var(--green),var(--gold))}
[dir=rtl] .fxprog i{transform-origin:100% 50%}

.fxring{position:absolute;inset:0;width:100%;height:100%;
  transform:rotate(-90deg);pointer-events:none;overflow:visible}
.fxring circle{fill:none;stroke-width:5;stroke-linecap:round}
.fxring__t{stroke:rgba(103,164,53,.2)}
.fxring__p{stroke:var(--gold);
  stroke-dasharray:289;
  stroke-dashoffset:calc(289px * (1 - var(--p,0)))}
.fx-on .dock__top .ic{position:relative;z-index:1}
/* The tip is already position:absolute in styles.css, and an absolute box
   takes z-index on its own — so it only needs lifting over the ring here.
   It must NOT be made position:relative: that returns it to the button's
   grid flow, which then lays out a second row for it and widens the column
   to the label's ~75px, knocking the arrow off centre and outside the
   circle.  The ring is absolute for the same reason. */
.fx-on .dock__top .dock__tip{z-index:1}

/* ─────────────────── 9. header + nav polish ─────────────────── */
.fx-on .hdr.is-stuck::before{
  background:rgba(255,255,255,.84);
  -webkit-backdrop-filter:blur(12px) saturate(1.35);
  backdrop-filter:blur(12px) saturate(1.35);
}
.fx-on .nav__a{position:relative}
.fx-on .nav__a::after{
  content:"";position:absolute;inset-inline:2px;bottom:0;height:2px;border-radius:2px;
  background:var(--green);transform:scaleX(0);transform-origin:100% 50%;
  transition:transform .28s cubic-bezier(.22,.68,.26,1);
}
[dir=ltr] .fx-on .nav__a::after{transform-origin:0 50%}
.fx-on .nav__a:hover::after,.fx-on .nav__a:focus-visible::after,
.fx-on .nav__a.is-active::after{transform:scaleX(1)}

/* ─────────────────── 10. small hover extras ─────────────────── */
.fx-on .feat__ic{transition:transform .34s cubic-bezier(.3,1.2,.5,1)}
.fx-on .feat__i:hover .feat__ic{transform:translateY(-5px) rotate(-5deg)}
/* the about cartouche's outline echo breathes, very slowly */
.fx-on .slider__ring{animation:fxBreathe 9s ease-in-out infinite}
@keyframes fxBreathe{0%,100%{transform:scale(1)}50%{transform:scale(1.018)}}
/* parallax drift for the purely decorative ornaments */
.fx-on [data-par]{transform:translate3d(0,var(--par,0px),0)}
/* ...except the two that are already mirrored with the `scale` property,
   which composes with `transform` rather than replacing it */
.fx-on .trust{transition:transform .25s,box-shadow .2s}
.fx-on .trust:hover{transform:translateY(-3px)}

/* ─────────────────────── 11. the off switch ───────────────────────
   Belt and braces: styles.css already flattens every transition under
   prefers-reduced-motion, and this kills the ambient loops and the reveal
   "from" states outright, whatever set them. */
@media (prefers-reduced-motion:reduce){
  .fx,.fx--up,.fx--down,.fx--pop,.fx--zoom,.fx--start,.fx--lift,.fx--soft{
    opacity:1!important;transform:none!important;translate:none!important;
    filter:none!important}
  .fx-on .hero__bg::before,.fx-on .hero__bg::after,
  .fx-on .shield,.fx-on .slider__ring{animation:none!important}
  .fx-on .sec__h .swash,.fx-on .plate__title .plate__leaf{
    transform:none!important;opacity:.9}
  .fx-on .sec__h .swash{opacity:1}
  .fxprog,.fxring{display:none}
}
