import { keyframes } from '@vanilla-extract/css'; /** * Snowfall — a flake drifts downward while swaying horizontally and slowly * rotating. GPU-only: animates transform + opacity exclusively. The vertical * travel uses a tall translateY so a single keyframe set serves all flakes; * per-flake duration/delay/scale create the parallax variety. */ export const animSnowFall = keyframes({ '0%': { transform: 'translate3d(0, -8vh, 0) rotate(0deg)', opacity: '0' }, '8%': { opacity: '1' }, '50%': { transform: 'translate3d(14px, 50vh, 0) rotate(180deg)' }, '92%': { opacity: '0.85' }, '100%': { transform: 'translate3d(-10px, 112vh, 0) rotate(360deg)', opacity: '0' }, }); /** * Gentle lateral sway applied to a flake's wrapper so the drift reads as wind, * decoupled from the fall so the two combine into an organic path. */ export const animSnowSway = keyframes({ '0%': { transform: 'translate3d(0, 0, 0)' }, '50%': { transform: 'translate3d(18px, 0, 0)' }, '100%': { transform: 'translate3d(0, 0, 0)' }, }); /** * String-light breathing — bokeh orbs softly pulse in brightness and scale, * like incandescent bulbs warming and cooling. Opacity + transform only. */ export const animBulbBreathe = keyframes({ '0%': { transform: 'scale(0.92)', opacity: '0.55' }, '50%': { transform: 'scale(1.08)', opacity: '0.95' }, '100%': { transform: 'scale(0.92)', opacity: '0.55' }, }); /** * Aurora shimmer — a wide soft band high in the scene slowly slides and * breathes. Uses translateX + opacity (never background-position) so it stays * on the compositor. */ export const animAurora = keyframes({ '0%': { transform: 'translate3d(-6%, 0, 0) scaleY(1)', opacity: '0.5' }, '50%': { transform: 'translate3d(6%, 0, 0) scaleY(1.08)', opacity: '0.8' }, '100%': { transform: 'translate3d(-6%, 0, 0) scaleY(1)', opacity: '0.5' }, }); /** * Vignette frost — a barely-there breathing of the cold frame so the static * tint feels alive without distracting motion. */ export const animFrostPulse = keyframes({ '0%': { opacity: '0.85' }, '50%': { opacity: '1' }, '100%': { opacity: '0.85' }, });