/* Scroll reveal. The hidden state is applied by JS, so the page stays readable
   if the script never runs. */
.reveal{opacity:0;transform:translateY(16px);transition:opacity .62s cubic-bezier(.22,.61,.36,1),transform .62s cubic-bezier(.22,.61,.36,1)}
.reveal.is-revealed{opacity:1;transform:none}
.reveal-delay-1{transition-delay:.07s}
.reveal-delay-2{transition-delay:.14s}
.reveal-delay-3{transition-delay:.21s}

/* Hover lift: enough to feel alive, not enough to shift the reading line. */
@media(hover:hover){
.home-products article,.home-research-grid article,.os-architecture-grid article,.app-card{transition:transform .3s cubic-bezier(.22,.61,.36,1)}
.home-products article:hover,.home-research-grid article:hover,.os-architecture-grid article:hover,.app-card:hover{transform:translateY(-4px)}
.detail-link span,.quiet-link span{display:inline-block;transition:transform .28s cubic-bezier(.22,.61,.36,1)}
.detail-link:hover span,.quiet-link:hover span{transform:translateX(4px)}
}

/* Anyone who asked for less motion gets none of it. */
@media(prefers-reduced-motion:reduce){
.reveal,.reveal.is-revealed{opacity:1;transform:none;transition:none}
.home-products article,.home-research-grid article,.os-architecture-grid article,.app-card,
.detail-link span,.quiet-link span{transition:none}
.home-products article:hover,.home-research-grid article:hover,.os-architecture-grid article:hover,.app-card:hover,
.detail-link:hover span,.quiet-link:hover span{transform:none}
}
