/* =========================================================================
   ZRently Sites — motion + loading styles. Shared across all themes.
   Themes opt in by adding `data-zrently-anim="..."` to elements; no theme
   class names are referenced here so themes can layer their own styles
   on top without conflict.

   Pairs with sites_motion.js, which toggles the `is-visible` class when
   the element scrolls into view.

   prefers-reduced-motion: zeroes out every transition + transform so
   motion-sensitive users see no movement (matches existing per-theme
   kill switches).
   ========================================================================= */

/* Initial state for any opt-in element. The `html.js` scope is critical:
   without JS, these elements render at full opacity, never invisible.
   With JS, sites_motion.js toggles `is-visible` when scrolled into view. */
html.js [data-zrently-anim] {
  opacity: 0;
  transition:
    opacity   0.55s cubic-bezier(0.16, 0.7, 0.3, 1),
    transform 0.55s cubic-bezier(0.16, 0.7, 0.3, 1);
  will-change: opacity, transform;
}

/* fade-up: rise 16px while fading in. The default — most "content
   block" reveals look right with this. */
html.js [data-zrently-anim="fade-up"] {
  transform: translate3d(0, 16px, 0);
}

/* fade-in: opacity only. Use on hero copy + anything where translation
   would visibly shift the layout focus. */
html.js [data-zrently-anim="fade-in"] {
  transform: none;
}

/* slide-up: bigger lift (28px) for hero / banner sections. */
html.js [data-zrently-anim="slide-up"] {
  transform: translate3d(0, 28px, 0);
}

/* fade-left / fade-right: subtle horizontal motion for two-column hero
   compositions. */
html.js [data-zrently-anim="fade-left"] {
  transform: translate3d(-16px, 0, 0);
}
html.js [data-zrently-anim="fade-right"] {
  transform: translate3d(16px, 0, 0);
}

/* Final / visible state — toggled by sites_motion.js. */
html.js [data-zrently-anim].is-visible {
  opacity: 1;
  transform: translate3d(0, 0, 0);
}

/* ── Image fade-in on load ──────────────────────────────────────────
   Applies to every <img> in the bundle when JS is alive (sites_motion.js
   adds `js` to <html> and `is-loaded` to each image as it decodes). The
   `html.js` scoping is critical: if JS fails to load, images render
   normally — never invisibly. */
html.js img {
  opacity: 0;
  transition: opacity 0.45s ease-out;
}
html.js img.is-loaded {
  opacity: 1;
}

/* ── Counter (data-zrently-counter) ─────────────────────────────────
   Counters animate INSIDE the same fade-up that contains them — the
   element is just a number, no extra positioning needed. The text
   change is handled by JS; CSS doesn't need to do anything special. */

/* ── Reduced motion: zero everything out. ───────────────────────────
   Per-theme @media blocks already disable animation/transition durations,
   but spell it out here too so the shared motion module behaves correctly
   even if a theme forgets to ship the kill-switch. */
@media (prefers-reduced-motion: reduce) {
  html.js [data-zrently-anim] {
    opacity: 1 !important;
    transform: none !important;
    transition: none !important;
  }
  html.js img {
    opacity: 1 !important;
    transition: none !important;
  }
}
