:root {
  /* CSS linear() spring: real physics, no npm, Baseline since 2024
     Mass/stiffness/damping sampled into keyframes. Values >1 = overshoot.
     Produces feel more fluid than Slint easings (§6). */
  --spring: linear(0, 0.006, 0.219 6%, 0.678, 1.176 24%, 1.259, 1.257,
                   1.18, 1.056, 0.968 46%, 0.938, 0.948, 0.988, 1.02, 1.028,
                   1.014 78%, 0.998, 0.996, 1);
}

/* Gear-5 pop (hover interaction) */
.pop {
  transition: transform 620ms var(--spring);
}

.pop:hover {
  transform: scale(1.12, 0.9);  /* squash-and-stretch: x expands, y compresses */
}

/* Card pop-in on load */
@keyframes pop-in {
  0% {
    opacity: 0;
    transform: scale(0.85, 1.15);  /* pop out of bounds by squash-stretch */
  }
  100% {
    opacity: 1;
    transform: scale(1, 1);
  }
}

.feature {
  animation: pop-in 700ms var(--spring);
}

/* Staggered pop-in for multiple features */
.feature:nth-child(1) { animation-delay: 0ms; }
.feature:nth-child(2) { animation-delay: 100ms; }
.feature:nth-child(3) { animation-delay: 200ms; }

/* Text magnify wave (pretext-driven; opt in with data-wave — see js/textwave.js) */
[data-wave] .tw-word { display: inline-block; white-space: nowrap; }
.tw-ch { display: inline-block; transform-origin: 50% 100%; will-change: transform; }
@keyframes tw-magnify {
  0%   { transform: scale(1); }
  45%  { transform: scale(1.5); }
  100% { transform: scale(1); }
}
.tw-ch.tw-rip { animation: tw-magnify 620ms ease-in-out both; }

/* Reduced motion: disable all springs */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-delay: 0 !important;
    transition-duration: .01ms !important;
  }
}
