/* ==========================================================================
   hero.css: platform cards: first-load build, live cycle, scroll parallax.
   Owns the three .hv-card elements only. Everything animated here is
   transform or opacity; hero.js writes the cards' scroll/pointer transform
   inline from one eased rAF loop, so motion never touches layout.
   Without JS the cards render in their final state.
   ========================================================================== */

.hero-visual { --ease-hv: cubic-bezier(.22, 1, .36, 1); }

/* Initial state, only once JS has claimed the hero */
.hero-js .hv-card {
  opacity: 0;
  transform: translateY(28px);
  will-change: transform, opacity;
}

/* Build: staggered rise (0.3s / 0.5s / 0.7s) */
.hero-build .hv-card { animation: hvRise .8s var(--ease-hv) both; }
.hero-build .hv-summary { animation-delay: .3s; }
.hero-build .hv-report  { animation-delay: .5s; }
.hero-build .hv-alert   { animation-delay: .7s; }
@keyframes hvRise {
  from { opacity: 0; transform: translateY(28px); }
  to   { opacity: 1; transform: translateY(0); }
}

/* Settled: animation released so hero.js's inline transform takes over */
.hero-js .hv-card.hv-in { animation: none; opacity: 1; transform: none; }

/* Bars: full width, scaled from the left; hero.js sets transform + delay */
.hero-js [data-bar] {
  width: 100% !important;
  transform-origin: left center;
  transform: scaleX(0);
}
.hero-build [data-bar] { transition: transform 1.2s var(--ease-hv); } /* enabled only after the start state is committed */
.hero-js [data-bar].warn { background: var(--warn); }
.hero-js [data-bar].good { background: var(--good); }
.hero-js [data-bar].base { background: var(--accent); }
.hero-js .pct.base { color: var(--accent); }

/* Count-ups reserve two digits, so 0 → 93 never changes the figure's width (no layout shift) */
.hero-visual .figure [data-count] { display: inline-block; min-width: 2ch; text-align: right; }

/* Warning pill waits for the 93% count to finish */
.hero-js [data-pill] { opacity: 0; }
.hero-build [data-pill] { transition: opacity .4s ease; }
.hero-js [data-pill].is-in { opacity: 1; }

/* Alert chip: the box never resizes (fixed width, ellipsis); only its text
   block slides out left and back in from the right on each swap. */
.hv-alert { width: 334px; max-width: 100%; padding-left: 14px; padding-right: 14px; }
.hv-alert > div { flex: 1; min-width: 0; transition: transform .3s var(--ease-hv), opacity .3s ease; }
.hv-alert b, .hv-alert small { display: block; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.hv-alert > div.hv-out  { transform: translateX(-14px); opacity: 0; transition-duration: .24s; }
.hv-alert > div.hv-from { transform: translateX(14px);  opacity: 0; transition: none; }

/* Optional hero video, crossfaded to the live cards on `ended` */
.hero-video {
  position: absolute; inset: 0; z-index: 2;
  width: 100%; height: 100%; object-fit: cover;
  border-radius: 16px; background: #0B1628;
  opacity: 1; transition: opacity .6s ease;
}
.hero-video.is-fading, .hero-video.is-hidden { opacity: 0; pointer-events: none; }
.hero-video.is-hidden { display: none; }

/* Reduced motion: final state, immediately */
@media (prefers-reduced-motion: reduce) {
  .hero-js .hv-card, .hero-build .hv-card {
    animation: none !important; opacity: 1 !important; transform: none !important; will-change: auto; transition: none !important;
  }
  .hero-js [data-bar] { transition: none !important; }
  .hero-js [data-pill] { opacity: 1; transition: none; }
  .hero-video { display: none; }
}
