/* Reveal: hidden only when JS is present; GSAP animates in. No JS = everything visible. */
.js .reveal { opacity: 0; transform: translateY(24px); }
.js .reveal.is-inview { opacity: 1; transform: none; transition: opacity 700ms var(--ease), transform 700ms var(--ease); }

/* Hero entrance: pure CSS stagger so it works before GSAP loads */
.js .hero__copy > * { opacity: 0; transform: translateY(16px); animation: rise 800ms var(--ease) forwards; }
.js .hero__copy > :nth-child(1) { animation-delay: 60ms; }
.js .hero__copy > :nth-child(2) { animation-delay: 140ms; }
.js .hero__copy > :nth-child(3) { animation-delay: 240ms; }
.js .hero__copy > :nth-child(4) { animation-delay: 320ms; }
.js .hero__copy > :nth-child(5) { animation-delay: 400ms; }
.js .hero__visual { opacity: 0; transform: translateY(28px) scale(.985); animation: rise 1000ms var(--ease) 260ms forwards; }
@keyframes rise { to { opacity: 1; transform: none; } }

/* Hero mock: fallback CSS loops when GSAP is absent or fails (overridden by JS via .has-gsap) */
.js .app:not(.has-gsap) [data-toast] { animation: toastIn 12s var(--ease) 2s infinite; }
.js .app:not(.has-gsap) [data-accepted] { animation: toastIn 12s var(--ease) 6s infinite; }
@keyframes toastIn { 0%, 6% { opacity: 0; visibility: hidden; transform: translateY(8px); } 10%, 45% { opacity: 1; visibility: visible; transform: none; } 50%, 100% { opacity: 0; visibility: hidden; transform: translateY(-6px); } }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .js .reveal, .js .hero__copy > *, .js .hero__visual { opacity: 1; transform: none; animation: none; transition: none; }
  .js .app [data-toast], .js .app [data-accepted] { animation: none; opacity: 1; visibility: visible; }
  .ai__type::after { animation: none; }
  .replace__item::after, .tile__mock--gantt i::after { transition: none; }
  .btn, .tile { transition: none; }
}
