/* ArticAir motion layer v3. Everything hidden here only applies under html.js-motion,
   which an inline head script sets (never under prefers-reduced-motion) and which
   js/motion.js removes again if it cannot run. Without it all content is visible.
   Technique: IntersectionObserver reveals, opacity 0 to 1 plus translateY 24px, 450ms outQuart,
   siblings staggered; hovers 200-300ms (in style.css). No scroll hijack, no custom cursor. */

:root { --mo-ease: cubic-bezier(.165, .84, .44, 1); --mo-dur: 450ms; }

html:not(.js) .show-img:first-child { opacity: 1; }

/* Reveal */
.js-motion [data-reveal]:not(.is-in) { opacity: 0; transform: translate3d(0, 24px, 0); }
.js-motion [data-reveal] { transition: opacity var(--mo-dur) var(--mo-ease), transform var(--mo-dur) var(--mo-ease); transition-delay: var(--d, 0ms); }
.js-motion [data-reveal].is-in { opacity: 1; transform: none; }
/* Elements scrolled past before they animated: no transition */
.js-motion .mo-instant, .js-motion .mo-instant * { transition: none !important; }

/* Home hero panel (one orchestrated moment). motion.js adds .is-on when the panel is about a third in view:
   the unit switches on (light, louvre opens), cool air starts pouring, the room readout eases 31 to 24 and the
   panel turns from warm grey to cool navy. Air then keeps flowing; .is-paused (off screen) stops it.
   Transform and opacity only, apart from the readout number. */
.js-motion .gp-warm { transition: opacity 3.4s cubic-bezier(.45, 0, .25, 1) .35s; }
.js-motion .glow-panel:not(.is-on) .gp-warm { opacity: 1; }
.js-motion .ac-temp-n { transition: --t 3.4s cubic-bezier(.3, 0, .2, 1) .35s; }
.js-motion .glow-panel:not(.is-on) .ac-temp-n { --t: 31; }
.js-motion .ac-led { transition: opacity .4s var(--mo-ease); }
.js-motion .glow-panel:not(.is-on) .ac-led { opacity: .15; }
.js-motion .ac-louvre { transition: transform 1s var(--mo-ease) .15s; }
.js-motion .glow-panel:not(.is-on) .ac-louvre { transform: scaleY(.55); }
.js-motion .ac-flow { transition: opacity 1.6s var(--mo-ease) .5s; }
.js-motion .glow-panel:not(.is-on) .ac-flow { opacity: 0; }
.js-motion .ac-air { opacity: 0; animation: ac-pour 4.8s linear infinite; }
.js-motion .ac-air:nth-child(2) { animation-delay: -1.6s; }
.js-motion .ac-air:nth-child(3) { animation-delay: -3.2s; }
.js-motion .ac-dot { opacity: 1; animation: ac-dx var(--d) cubic-bezier(.2, .6, .4, 1) var(--w) infinite; }
.js-motion .ac-dot i { opacity: 0; animation: ac-dy var(--d) cubic-bezier(.55, 0, .8, .6) var(--w) infinite; }
.js-motion .glow-panel:not(.is-on) :is(.ac-air, .ac-dot, .ac-dot i),
.js-motion .glow-panel.is-paused :is(.ac-air, .ac-dot, .ac-dot i),
.js-motion #hero-3d.is-3d :is(.ac-air, .ac-dot, .ac-dot i) { animation-play-state: paused; }
@keyframes ac-pour {
  0% { opacity: 0; transform: translateY(-1.5%) scale(.9, .8); }
  22% { opacity: .95; }
  65% { opacity: .55; }
  100% { opacity: 0; transform: translateY(4%) scale(1.07, 1.14); }
}
@keyframes ac-dx { to { transform: translateX(var(--dx)); } }
@keyframes ac-dy {
  0% { opacity: 0; transform: none; }
  15% { opacity: .85; }
  70% { opacity: .45; }
  100% { opacity: 0; transform: translateY(var(--dy)); }
}

/* WebGL (js/scene3d.js): the canvas fades in over the SVG unit and air; the readout and panel colour stay in the DOM */
#hero-3d .ac { transition: opacity 700ms var(--mo-ease), visibility 0s 700ms; }
#hero-3d.is-3d .ac { opacity: 0; visibility: hidden; }
#hero-3d canvas.scene3d { opacity: 0; transition: opacity 900ms var(--mo-ease); pointer-events: none; }
#hero-3d.is-3d canvas.scene3d { opacity: 1; }

/* Reduced motion: show everything, no movement, hero panel as one still frame */
@media (prefers-reduced-motion: reduce) {
  [data-reveal] { opacity: 1 !important; transform: none !important; transition: none !important; animation: none !important; }
  #hero-3d canvas.scene3d { display: none; }
  #hero-3d .ac { opacity: 1 !important; visibility: visible !important; }
  .ac-air, .ac-dot, .ac-dot i { animation: none !important; }
}

/* Failsafe (pure CSS, no JS or observers needed): above-the-fold hero content is always visible
   by about 1.5s even if reveal scripts or timers fail. */
@keyframes mo-failsafe { to { opacity: 1; transform: none; } }
.js-motion .hero [data-reveal]:not(.is-in),
.js-motion .hero [data-split]:not(.is-in),
.js-motion .glow-panel:not(.is-in) { animation: mo-failsafe .2s linear 1.5s forwards; }

/* Hero is never hidden at first paint (screenshots, slow loads, link previews): content is
   visible immediately; only decorative parts animate. */
.js-motion .hero [data-reveal]:not(.is-in),
.js-motion .hero [data-split]:not(.is-in),
.js-motion .glow-panel:not(.is-in) { opacity: 1; transform: none; animation: none; }

/* Inner page heroes (.hero-sub) follow the same rule: visible at first paint */
.js-motion .hero-sub [data-reveal]:not(.is-in),
.js-motion .hero-sub [data-split]:not(.is-in) { opacity: 1; transform: none; animation: none; clip-path: none; }
