/**
 * SMB Image Effects — live CSS animations for images in pages/posts.
 *
 * Mirrors the effect set from the companion desktop GIF/video tool, but
 * runs as real browser animation on the actual <img> element instead of
 * baking frames into a file.
 *
 * USAGE
 * -----
 * Add `rgos-fx` plus one effect class to any image, e.g. via the block
 * editor's "Additional CSS class(es)" field:
 *
 *     rgos-fx rgos-fx-pulse
 *
 * That alone makes the image animate continuously, forever, from the
 * moment the page loads — no JavaScript required.
 *
 * To instead have it play only when scrolled into view (and optionally
 * only once), add the `rgos-fx-onscroll` class too; assets/js/image-effects.js
 * handles the rest. See the shortcode/plugin settings page for details.
 *
 * Effect classes: rgos-fx-pulse, rgos-fx-spin, rgos-fx-swing,
 * rgos-fx-shake, rgos-fx-bounce, rgos-fx-blur-pulse, rgos-fx-grayscale-pop,
 * rgos-fx-invert-pulse, rgos-fx-sepia-pulse, rgos-fx-vignette-pulse,
 * rgos-fx-fade, rgos-fx-zoom-pan, rgos-fx-rainbow, rgos-fx-flicker,
 * rgos-fx-wipe-reveal, rgos-fx-flip-horizontal, rgos-fx-scanlines,
 * rgos-fx-glitch, rgos-fx-fade-rise, rgos-fx-color-reveal, rgos-fx-focus-in,
 * rgos-fx-gentle-lift
 */

.rgos-fx {
    display: inline-block;
    transform-origin: center center;
    /* backface-visibility: hidden was deliberately removed here. It only
       matters for elements using 3D rotation (rotateX/rotateY), which none
       of these effects use — everything here is 2D (scale, Z-axis rotate,
       translate). On some GPU/driver combinations it's known to cause
       transform-based CSS animations to silently freeze (filter-based
       effects are unaffected since they never touch `transform`), so it's
       pure downside with no benefit for this stylesheet. */
}

/* Directional/entrance effects look wrong repeating forever by default,
   so they default to a single play that holds on the final frame. All
   others default to an infinite, seamless loop. */
.rgos-fx-zoom-pan,
.rgos-fx-wipe-reveal,
.rgos-fx-fade-rise,
.rgos-fx-color-reveal,
.rgos-fx-focus-in,
.rgos-fx-gentle-lift,
.rgos-fx-slide-in,
.rgos-fx-settle {
    animation-iteration-count: 1;
    animation-fill-mode: forwards;
}

/* Respect the visitor's OS-level motion preference across every effect. */
/* The prefers-reduced-motion rule that used to live here is now added
   conditionally as inline CSS by RGOS_Image_Effects::enqueue_assets(),
   controlled by the "Reduced motion" setting on the settings page. This
   keeps a site owner's choice to disable it a one-file, one-source-of-truth
   change instead of static CSS that always applies regardless of setting. */

/* ---------- pulse: gentle breathing scale ---------- */
.rgos-fx-pulse {
    animation-name: rgosfx-pulse;
    animation-duration: var(--rgos-fx-duration, 1.6s);
    animation-timing-function: ease-in-out;
    animation-iteration-count: infinite;
}
@keyframes rgosfx-pulse {
    0%, 100% { transform: scale(1); }
    50%      { transform: scale(1.08); }
}

/* ---------- spin: continuous 360-degree rotation ---------- */
.rgos-fx-spin {
    animation-name: rgosfx-spin;
    animation-duration: var(--rgos-fx-duration, 2.2s);
    animation-timing-function: linear;
    animation-iteration-count: infinite;
}
@keyframes rgosfx-spin {
    from { transform: rotate(0deg); }
    to   { transform: rotate(360deg); }
}

/* ---------- swing: pendulum-style rocking ---------- */
.rgos-fx-swing {
    animation-name: rgosfx-swing;
    animation-duration: var(--rgos-fx-duration, 2s);
    animation-timing-function: ease-in-out;
    animation-iteration-count: infinite;
}
@keyframes rgosfx-swing {
    0%, 100% { transform: rotate(0deg); }
    25%      { transform: rotate(15deg); }
    75%      { transform: rotate(-15deg); }
}

/* ---------- shake: small jittery wobble ---------- */
.rgos-fx-shake {
    animation-name: rgosfx-shake;
    animation-duration: var(--rgos-fx-duration, 0.6s);
    animation-timing-function: ease-in-out;
    animation-iteration-count: infinite;
}
@keyframes rgosfx-shake {
    0%, 100% { transform: translate(0, 0); }
    20%      { transform: translate(-4px, 2px); }
    40%      { transform: translate(4px, -2px); }
    60%      { transform: translate(-3px, -3px); }
    80%      { transform: translate(3px, 3px); }
}

/* ---------- bounce: drop-and-settle vertical bounce ---------- */
.rgos-fx-bounce {
    animation-name: rgosfx-bounce;
    animation-duration: var(--rgos-fx-duration, 1.1s);
    animation-timing-function: ease-in-out;
    animation-iteration-count: infinite;
}
@keyframes rgosfx-bounce {
    0%, 100% { transform: translateY(0); }
    30%      { transform: translateY(-18%); }
    50%      { transform: translateY(0); }
    65%      { transform: translateY(-6%); }
    80%      { transform: translateY(0); }
}

/* ---------- blur_pulse: racking focus ---------- */
.rgos-fx-blur-pulse {
    animation-name: rgosfx-blur-pulse;
    animation-duration: var(--rgos-fx-duration, 2.4s);
    animation-timing-function: ease-in-out;
    animation-iteration-count: infinite;
}
@keyframes rgosfx-blur-pulse {
    0%, 100% { filter: blur(0px); }
    50%      { filter: blur(6px); }
}

/* ---------- grayscale_pop: pops to grayscale and back ---------- */
.rgos-fx-grayscale-pop {
    animation-name: rgosfx-grayscale-pop;
    animation-duration: var(--rgos-fx-duration, 2.4s);
    animation-timing-function: ease-in-out;
    animation-iteration-count: infinite;
}
@keyframes rgosfx-grayscale-pop {
    0%, 100% { filter: grayscale(0%); }
    50%      { filter: grayscale(100%); }
}

/* ---------- invert_pulse: flashes toward inverted colors ---------- */
.rgos-fx-invert-pulse {
    animation-name: rgosfx-invert-pulse;
    animation-duration: var(--rgos-fx-duration, 1.8s);
    animation-timing-function: ease-in-out;
    animation-iteration-count: infinite;
}
@keyframes rgosfx-invert-pulse {
    0%, 100% { filter: invert(0%); }
    50%      { filter: invert(100%); }
}

/* ---------- sepia_pulse: fades to warm sepia and back ---------- */
.rgos-fx-sepia-pulse {
    animation-name: rgosfx-sepia-pulse;
    animation-duration: var(--rgos-fx-duration, 2.6s);
    animation-timing-function: ease-in-out;
    animation-iteration-count: infinite;
}
@keyframes rgosfx-sepia-pulse {
    0%, 100% { filter: sepia(0%); }
    50%      { filter: sepia(100%); }
}

/* ---------- vignette_pulse: darkened edges breathing in/out ---------- */
.rgos-fx-vignette-pulse {
    animation-name: rgosfx-vignette-pulse;
    animation-duration: var(--rgos-fx-duration, 2.4s);
    animation-timing-function: ease-in-out;
    animation-iteration-count: infinite;
}
@keyframes rgosfx-vignette-pulse {
    0%, 100% { box-shadow: inset 0 0 0 0 rgba(0, 0, 0, 0); }
    50%      { box-shadow: inset 0 0 60px 20px rgba(0, 0, 0, 0.65); }
}

/* ---------- fade: fades out and back in ---------- */
.rgos-fx-fade {
    animation-name: rgosfx-fade;
    animation-duration: var(--rgos-fx-duration, 2s);
    animation-timing-function: ease-in-out;
    animation-iteration-count: infinite;
}
@keyframes rgosfx-fade {
    0%, 100% { opacity: 1; }
    50%      { opacity: 0.1; }
}

/* ---------- zoom_pan: slow directional Ken Burns zoom ---------- */
.rgos-fx-zoom-pan {
    animation-name: rgosfx-zoom-pan;
    animation-duration: var(--rgos-fx-duration, 6s);
    animation-timing-function: ease-out;
}
@keyframes rgosfx-zoom-pan {
    from { transform: scale(1) translate(0, 0); }
    to   { transform: scale(1.15) translate(-2%, -2%); }
}

/* ---------- rainbow: cycles hue across the whole image ---------- */
.rgos-fx-rainbow {
    animation-name: rgosfx-rainbow;
    animation-duration: var(--rgos-fx-duration, 3s);
    animation-timing-function: linear;
    animation-iteration-count: infinite;
}
@keyframes rgosfx-rainbow {
    from { filter: hue-rotate(0deg); }
    to   { filter: hue-rotate(360deg); }
}

/* ---------- flicker: unstable brightness flicker ---------- */
.rgos-fx-flicker {
    animation-name: rgosfx-flicker;
    animation-duration: var(--rgos-fx-duration, 1.4s);
    animation-timing-function: steps(1, end);
    animation-iteration-count: infinite;
}
@keyframes rgosfx-flicker {
    0%   { filter: brightness(1); }
    10%  { filter: brightness(0.7); }
    20%  { filter: brightness(1.2); }
    35%  { filter: brightness(0.85); }
    50%  { filter: brightness(1.3); }
    65%  { filter: brightness(0.75); }
    80%  { filter: brightness(1.1); }
    100% { filter: brightness(1); }
}

/* ---------- wipe_reveal: wipes in left-to-right over black ---------- */
.rgos-fx-wipe-reveal {
    animation-name: rgosfx-wipe-reveal;
    animation-duration: var(--rgos-fx-duration, 1.4s);
    animation-timing-function: ease-out;
}
@keyframes rgosfx-wipe-reveal {
    from { clip-path: inset(0 100% 0 0); }
    to   { clip-path: inset(0 0 0 0); }
}
/* Onscroll wrapper for wipe-reveal specifically — see build_html()'s
   $needs_observe_wrap and the long comment there for why this exists.
   The <img> itself no longer carries rgos-fx-onscroll in this case (that
   would make it a target IntersectionObserver measures directly, which
   is exactly the zero-area trap being avoided), so it needs its own
   "start paused" rule keyed off the wrapper ancestor instead of the
   usual .rgos-fx.rgos-fx-onscroll rule below. JS still plays/pauses/
   restarts the <img> directly via inline styles once triggered — this
   only supplies the *initial* paused state before that happens. */
.rgos-fx-observe-wrap.rgos-fx-onscroll > .rgos-fx {
    animation-play-state: paused;
}

/* ---------- fade-rise: fades in while sliding up slightly ---------- */
/* A restrained, standard "professional entrance" animation — the kind
   seen across most business/marketing/SaaS sites. Single-play, holds on
   its final (fully visible, in-place) frame. */
.rgos-fx-fade-rise {
    animation-name: rgosfx-fade-rise;
    animation-duration: var(--rgos-fx-duration, 0.8s);
    animation-timing-function: ease-out;
}
@keyframes rgosfx-fade-rise {
    from { opacity: 0; transform: translateY(24px); }
    to   { opacity: 1; transform: translateY(0); }
}

/* ---------- color-reveal: grayscale to full color ---------- */
/* A tasteful storytelling effect common on team/about pages and case
   studies — the image "comes to life" in color as it's scrolled to.
   Single-play, holds on full color. */
.rgos-fx-color-reveal {
    animation-name: rgosfx-color-reveal;
    animation-duration: var(--rgos-fx-duration, 1.6s);
    animation-timing-function: ease-in;
}
@keyframes rgosfx-color-reveal {
    from { filter: grayscale(100%); }
    to   { filter: grayscale(0%); }
}

/* ---------- focus-in: starts blurred, sharpens into focus ---------- */
/* Reads as a polished, deliberate reveal rather than a gimmick. Single-
   play, holds sharp. */
.rgos-fx-focus-in {
    animation-name: rgosfx-focus-in;
    animation-duration: var(--rgos-fx-duration, 0.9s);
    animation-timing-function: ease-out;
}
@keyframes rgosfx-focus-in {
    from { filter: blur(10px); }
    to   { filter: blur(0); }
}

/* ---------- gentle-lift: shadow deepens, image scales up slightly --- */
/* Reads like a card lifting subtly off the page — suits feature/product
   images. Single-play, holds "lifted". The image needs to not already be
   flush against something with no room for a shadow to show; that's a
   layout concern for the page, not this effect. */
.rgos-fx-gentle-lift {
    animation-name: rgosfx-gentle-lift;
    animation-duration: var(--rgos-fx-duration, 0.6s);
    animation-timing-function: ease-out;
}
@keyframes rgosfx-gentle-lift {
    from {
        transform: scale(1);
        box-shadow: 0 0 0 rgba(0, 0, 0, 0);
    }
    to {
        transform: scale(1.03);
        box-shadow: 0 12px 24px rgba(0, 0, 0, 0.18);
    }
}

/* ---------- slide-in: fades/slides in from the left ---------- */
/* A directional companion to fade-rise (vertical) — useful for varying
   the entrance direction across a page of feature images without
   repeating the same motion each time. Single-play, holds in place. */
.rgos-fx-slide-in {
    animation-name: rgosfx-slide-in;
    animation-duration: var(--rgos-fx-duration, 0.8s);
    animation-timing-function: ease-out;
}
@keyframes rgosfx-slide-in {
    from { opacity: 0; transform: translateX(-28px); }
    to   { opacity: 1; transform: translateX(0); }
}

/* ---------- settle: scales down and fades in, "settles into place" -- */
/* Distinct from zoom-pan (a continuous slow pan/zoom) and gentle-lift (a
   hover-style lift accent) — this is a one-time entrance that reads as
   the image gently arriving at its resting size. Single-play. */
.rgos-fx-settle {
    animation-name: rgosfx-settle;
    animation-duration: var(--rgos-fx-duration, 0.7s);
    animation-timing-function: ease-out;
}
@keyframes rgosfx-settle {
    from { opacity: 0; transform: scale(1.06); }
    to   { opacity: 1; transform: scale(1); }
}

/* ---------- soft-sheen: barely-there ambient brightness breathing ---- */
/* Much more restrained than `pulse` (which scales the whole image) —
   this only nudges brightness a few percent, slowly, for hero images or
   banners that should feel subtly "alive" without drawing attention to
   the fact that they're animating at all. Continuous loop (the default;
   not added to the single-play group below). */
.rgos-fx-soft-sheen {
    animation-name: rgosfx-soft-sheen;
    animation-duration: var(--rgos-fx-duration, 3.2s);
    animation-timing-function: ease-in-out;
}
@keyframes rgosfx-soft-sheen {
    0%, 100% { filter: brightness(1); }
    50%      { filter: brightness(1.04); }
}

/* ---------- bob: gentle floating up/down loop ---------- */
/* Calmer and smaller-amplitude than `bounce` (which has an elastic,
   springy character) — this is a slow, smooth float, like something
   gently bobbing on water. A touch of personality without demanding
   attention. */
.rgos-fx-bob {
    animation-name: rgosfx-bob;
    animation-duration: var(--rgos-fx-duration, 2.4s);
    animation-timing-function: ease-in-out;
}
@keyframes rgosfx-bob {
    0%, 100% { transform: translateY(0); }
    50%      { transform: translateY(-6px); }
}

/* ---------- wave: gentle shear ripple ---------- */
/* Distinct from `swing` (a full ±15° pendulum rotation) — this uses a
   small-amplitude skew instead of a rotation, reading as a soft ripple
   or flutter rather than a full tilt. */
.rgos-fx-wave {
    animation-name: rgosfx-wave;
    animation-duration: var(--rgos-fx-duration, 2.6s);
    animation-timing-function: ease-in-out;
}
@keyframes rgosfx-wave {
    0%, 100% { transform: skewX(0deg); }
    25%      { transform: skewX(3deg); }
    75%      { transform: skewX(-3deg); }
}

/* ---------- flip_horizontal: 3D-style card flip ---------- */
.rgos-fx-flip-horizontal {
    animation-name: rgosfx-flip-horizontal;
    animation-duration: var(--rgos-fx-duration, 1.6s);
    animation-timing-function: ease-in-out;
    animation-iteration-count: infinite;
}
@keyframes rgosfx-flip-horizontal {
    0%, 100% { transform: scaleX(1); }
    25%      { transform: scaleX(0); }
    50%      { transform: scaleX(-1); }
    75%      { transform: scaleX(0); }
}

/* ---------- scanlines: CRT-style scrolling scanlines overlay ---------- */
/* IMPORTANT: this effect's overlay is generated content (::after), and
   browsers do not paint ::before/::after on <img> — it's a "replaced
   element" per the CSS spec, so generated content is simply never
   rendered on it, no matter how correct the rule is otherwise. This
   silently "worked" in DevTools (getComputedStyle still reports values
   for a rule that matches, whether or not it's actually paintable) while
   showing nothing on screen — a very easy trap to fall into.
   Fix: RGOS_Image_Effects::build_html() now wraps the <img> in a
   `.rgos-fx-scanlines-wrap` <span> for this effect specifically, and the
   overlay lives on the wrapper instead of the image. The
   `.rgos-fx.rgos-fx-scanlines` selector below is kept alongside it only
   for non-<img> elements (e.g. the admin Effect Gallery's <div> preview
   tiles, or a class added by hand to a <figure>/<div>) — those aren't
   replaced elements, so the overlay paints on them directly with no
   wrapper needed. */
.rgos-fx-scanlines-wrap,
.rgos-fx.rgos-fx-scanlines {
    position: relative;
    display: inline-block;
    overflow: hidden;
    line-height: 0; /* avoid extra inline-box whitespace gap under the image */
}
.rgos-fx-scanlines-wrap::after,
.rgos-fx.rgos-fx-scanlines::after {
    content: "";
    position: absolute;
    inset: 0;
    pointer-events: none;
    background: repeating-linear-gradient(
        to bottom,
        rgba(0, 0, 0, 0.35) 0px,
        rgba(0, 0, 0, 0.35) 1px,
        transparent 1px,
        transparent 4px
    );
    animation-name: rgosfx-scanlines;
    animation-duration: var(--rgos-fx-duration, 1s);
    animation-timing-function: linear;
    animation-iteration-count: infinite;
}
@keyframes rgosfx-scanlines {
    from { background-position: 0 0; }
    to   { background-position: 0 4px; }
}
/* Onscroll support for scanlines specifically: JS can set inline styles
   on a real element but never on its ::after, so unlike every other
   onscroll-capable effect (which the JS pauses/resumes via
   el.style.animationPlayState directly), this has to go through class
   toggles the CSS below reacts to instead. See image-effects.js. */
.rgos-fx-scanlines-wrap.rgos-fx-onscroll::after {
    animation-play-state: paused;
}
.rgos-fx-scanlines-wrap.rgos-fx-onscroll.rgos-fx-visible::after {
    animation-play-state: running;
}
.rgos-fx-scanlines-wrap.rgos-fx-restarting::after {
    animation: none !important;
}

/* ---------- shine-sweep: soft diagonal light gleam, periodic -------- */
/* A tasteful "premium product shot" sheen — a soft highlight sweeps once
   across the image, then rests for a few seconds before repeating.
   Genuinely playful/eye-catching without being loud or continuous.
   Same replaced-element constraint as scanlines (generated content
   doesn't paint on an <img>), so this needs the same wrapper treatment —
   see build_html()'s $paint_wrap_classes and the scanlines comment above
   for the full explanation. The `.rgos-fx.rgos-fx-shine-sweep::after`
   selector below is the same non-<img>-element fallback scanlines has
   (used by the admin Effect Gallery's <div> preview tiles). */
.rgos-fx-shine-wrap,
.rgos-fx.rgos-fx-shine-sweep {
    position: relative;
    display: inline-block;
    overflow: hidden;
    line-height: 0;
}
.rgos-fx-shine-wrap::after,
.rgos-fx.rgos-fx-shine-sweep::after {
    content: "";
    position: absolute;
    inset: 0;
    pointer-events: none;
    background: linear-gradient(
        115deg,
        transparent 40%,
        rgba(255, 255, 255, 0.55) 50%,
        transparent 60%
    );
    background-size: 250% 250%;
    animation-name: rgosfx-shine-sweep;
    animation-duration: var(--rgos-fx-duration, 3.2s);
    animation-timing-function: ease-in-out;
    animation-iteration-count: infinite;
}
@keyframes rgosfx-shine-sweep {
    /* Sweeps across in roughly the first fifth of the duration, then
       rests (the gradient's edges are transparent, so holding position
       here shows nothing extra) for the remainder before repeating —
       a periodic gleam rather than a constant, distracting shimmer. */
    0%   { background-position: -60% -60%; }
    18%  { background-position: 160% 160%; }
    100% { background-position: 160% 160%; }
}
/* Onscroll support: same class-toggle approach as scanlines (JS can't
   set inline styles on a ::after) — see image-effects.js. */
.rgos-fx-shine-wrap.rgos-fx-onscroll::after {
    animation-play-state: paused;
}
.rgos-fx-shine-wrap.rgos-fx-onscroll.rgos-fx-visible::after {
    animation-play-state: running;
}
.rgos-fx-shine-wrap.rgos-fx-restarting::after {
    animation: none !important;
}

/* ---------- glitch: stylized jitter/chroma-shift approximation ----------
   Note: unlike the desktop tool's glitch_rgb (a true per-channel pixel
   split), this is a CSS-only stylized approximation combining jitter,
   contrast jumps, and hue shift — genuine RGB channel splitting isn't
   practical in pure CSS on a single raster image. */
.rgos-fx-glitch {
    animation-name: rgosfx-glitch;
    animation-duration: var(--rgos-fx-duration, 1.2s);
    animation-timing-function: steps(1, end);
    animation-iteration-count: infinite;
}
@keyframes rgosfx-glitch {
    0%   { transform: translate(0, 0); filter: hue-rotate(0deg) contrast(1); }
    10%  { transform: translate(-3px, 1px); filter: hue-rotate(15deg) contrast(1.3); }
    20%  { transform: translate(3px, -1px); filter: hue-rotate(-15deg) contrast(1); }
    30%  { transform: translate(0, 0); filter: hue-rotate(0deg) contrast(1); }
    55%  { transform: translate(-2px, 2px); filter: hue-rotate(20deg) contrast(1.4); }
    70%  { transform: translate(2px, -2px); filter: hue-rotate(-10deg) contrast(1); }
    100% { transform: translate(0, 0); filter: hue-rotate(0deg) contrast(1); }
}

/* ---------- combinations ----------
   Individual effect classes can't simply be combined (e.g.
   `rgos-fx-pulse rgos-fx-rainbow` together) because each sets the whole
   `animation` shorthand, so the later class in the cascade wins outright
   rather than merging. These curated combo classes pair a transform-based
   effect with a filter-based one (which animate different CSS properties,
   so they genuinely can run simultaneously) via a single multi-value
   `animation` declaration. */
.rgos-fx-combo-pulse-rainbow {
    animation-name: rgosfx-pulse, rgosfx-rainbow;
    animation-duration: var(--rgos-fx-duration, 1.6s), 3s;
    animation-timing-function: ease-in-out, linear;
    animation-iteration-count: infinite, infinite;
}
.rgos-fx-combo-spin-invert {
    animation-name: rgosfx-spin, rgosfx-invert-pulse;
    animation-duration: var(--rgos-fx-duration, 2.2s), 1.8s;
    animation-timing-function: linear, ease-in-out;
    animation-iteration-count: infinite, infinite;
}
.rgos-fx-combo-swing-sepia {
    animation-name: rgosfx-swing, rgosfx-sepia-pulse;
    animation-duration: var(--rgos-fx-duration, 2s), 2.6s;
    animation-timing-function: ease-in-out, ease-in-out;
    animation-iteration-count: infinite, infinite;
}
.rgos-fx-combo-bounce-grayscale {
    animation-name: rgosfx-bounce, rgosfx-grayscale-pop;
    animation-duration: var(--rgos-fx-duration, 1.1s), 2.4s;
    animation-timing-function: ease-in-out, ease-in-out;
    animation-iteration-count: infinite, infinite;
}
.rgos-fx-combo-zoompan-vignette {
    animation-name: rgosfx-zoom-pan, rgosfx-vignette-pulse;
    animation-duration: var(--rgos-fx-duration, 6s), 2.4s;
    animation-timing-function: ease-out, ease-in-out;
    animation-iteration-count: 1, infinite;
    animation-fill-mode: forwards, none;
}

/* When JS-driven scroll-triggering is requested, the animation starts
   paused; assets/js/image-effects.js flips it to running on intersection.
   Declared last, with two classes chained (higher specificity than any
   single-class effect rule above), so it reliably wins the cascade even
   though every effect rule also sets the `animation` shorthand — which
   would otherwise silently reset play-state back to its default. */
.rgos-fx.rgos-fx-onscroll {
    animation-play-state: paused;
}
