/* ==========================================================================
   WD ART AND DESIGN — motion
   All hidden initial states are scoped to `.js` so the site stays fully
   readable when JavaScript is unavailable.
   ========================================================================== */

/* Page load ---------------------------------------------------------------- */
.js .site-header { opacity: 0; transform: translateY(-14px); }
.is-loaded .site-header { opacity: 1; transform: none; transition: opacity 0.8s 0.1s, transform 1s var(--ease) 0.1s, background-color 0.4s, border-color 0.4s; }

.js [data-load] { opacity: 0; transform: translateY(22px); }
.is-loaded [data-load] { opacity: 1; transform: none; transition: opacity 0.9s, transform 1.1s var(--ease); transition-delay: var(--d, 0s); }

.js .line > span { transform: translateY(108%); }
.is-loaded .line > span { transform: none; transition: transform 1.2s var(--ease); transition-delay: calc(0.2s + var(--i, 0) * 0.11s); }

.js .hero__character { opacity: 0; transform: translateY(46px) scale(0.965); }
.is-loaded .hero__character { opacity: 1; transform: none; transition: opacity 1.4s 0.35s, transform 1.8s var(--ease) 0.35s; }
.js .hero__ring, .js .hero__slab { opacity: 0; }
.is-loaded .hero__ring, .is-loaded .hero__slab { opacity: 1; transition: opacity 1.6s 0.7s; }
.js .hero__label { opacity: 0; }
.is-loaded .hero__label { opacity: 1; transition: opacity 0.9s calc(1.2s + var(--i, 0) * 0.18s); animation: float 7s ease-in-out calc(var(--i, 0) * -2.2s) infinite; }

/* Scroll reveal (IntersectionObserver adds .is-in) -------------------------- */
.js [data-reveal] { opacity: 0; transform: translateY(30px); transition: opacity 0.9s, transform 1.1s var(--ease); transition-delay: var(--d, 0s); }
.js [data-reveal="left"] { transform: translateX(-44px); }
.js [data-reveal="right"] { transform: translateX(44px); }
.js [data-reveal="scale"] { transform: scale(0.94); }
/* "clip" wipes the image in. The clip sits on the <img>, not the observed
   element — a fully clipped target never reports as intersecting. */
.js [data-reveal="clip"] { opacity: 1; transform: none; background: transparent; }
.js [data-reveal="clip"] img { clip-path: inset(0 0 100% 0); transform: scale(1.14); transition: clip-path 1.3s var(--ease), transform 1.6s var(--ease); transition-delay: var(--d, 0s); }
.js [data-reveal].is-in { opacity: 1; transform: none; }
.js [data-reveal="clip"].is-in img { clip-path: inset(0 0 0 0); transform: none; }

/* Keyframes ---------------------------------------------------------------- */
@keyframes float { 0%, 100% { translate: 0 0; } 50% { translate: 0 -9px; } }
@keyframes marquee { to { transform: translateX(-50%); } }
@keyframes cue { 0% { transform: translateY(-100%); } 55%, 100% { transform: translateY(100%); } }
@keyframes modal-in { from { opacity: 0; transform: translateY(26px) scale(0.98); } }
@keyframes shake { 20%, 60% { transform: translateX(-5px); } 40%, 80% { transform: translateX(5px); } }

.marquee__track { animation: marquee 38s linear infinite; }
.marquee:hover .marquee__track { animation-play-state: paused; }
.scroll-cue i::after { animation: cue 2.4s var(--ease) infinite; }
.form-shake { animation: shake 0.45s; }

/* Reduced motion: keep everything visible, drop the movement ---------------- */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after { animation-duration: 0.001ms !important; animation-iteration-count: 1 !important; transition-duration: 0.001ms !important; transition-delay: 0s !important; }
  .js [data-reveal], .js [data-load], .js .line > span, .js .hero__character, .js .site-header, .js .hero__label, .js .hero__ring, .js .hero__slab { opacity: 1 !important; transform: none !important; }
  .js [data-reveal="clip"] img { transform: none !important; clip-path: none !important; }
  .marquee__track { animation: none; }
  .timeline::after { transform: scaleX(1); }
  .cursor, .hero__particles { display: none !important; }
}
