import { keyframes } from '@vanilla-extract/css'; /** * Lunar New Year overlay keyframes — red paper lanterns, drifting gold plum * blossoms, and a coiling dragon. Every animation touches ONLY `transform` and * `opacity`, so the compositor runs them on the GPU with zero layout/paint. * keyframes() returns the generated animation-name string, applied inline by the * component. Static structure (gradients, SVG data-URIs, geometry) lives in the * component; this module is motion only. */ /** * Lantern bob — a hung lantern rises a touch and sinks again on a long, lazy * cycle, as if buoyed by warm air. translateY + a whisper of scale only; the * per-lantern duration/delay desynchronise the swarm. */ export const animLanternBob = keyframes({ '0%': { transform: 'translate3d(0, 0, 0) scale(1)' }, '50%': { transform: 'translate3d(0, -2.2vh, 0) scale(1.015)' }, '100%': { transform: 'translate3d(0, 0, 0) scale(1)' }, }); /** * Lantern pendulum — a gentle rotational sway about the top mount, so each * lantern rocks like it hangs from a string. Pairs with the bob on a different * period to read as organic drift rather than a metronome. */ export const animLanternSway = keyframes({ '0%': { transform: 'rotate(-2.4deg)' }, '50%': { transform: 'rotate(2.4deg)' }, '100%': { transform: 'rotate(-2.4deg)' }, }); /** * Tassel sway — the silk tassel under a lantern trails its parent's motion with * a wider, slightly lagging swing. transformOrigin is the top of the tassel. */ export const animTasselSway = keyframes({ '0%': { transform: 'rotate(5deg)' }, '50%': { transform: 'rotate(-5deg)' }, '100%': { transform: 'rotate(5deg)' }, }); /** * Lantern inner glow — the warm light inside each lantern swells and dims, like * a candle breathing. Opacity + scale only. */ export const animGlowBreathe = keyframes({ '0%': { transform: 'scale(0.94)', opacity: '0.55' }, '50%': { transform: 'scale(1.06)', opacity: '0.9' }, '100%': { transform: 'scale(0.94)', opacity: '0.55' }, }); /** * Petal drift — a gold plum-blossom petal falls the full height while spinning * and swaying. A tall translateY lets one keyframe set serve every petal; * per-petal duration/delay/scale create the parallax variety. */ export const animPetalFall = keyframes({ '0%': { transform: 'translate3d(0, -10vh, 0) rotateZ(0deg) rotateY(0deg)', opacity: '0' }, '10%': { opacity: '0.9' }, '50%': { transform: 'translate3d(3vw, 52vh, 0) rotateZ(190deg) rotateY(180deg)' }, '90%': { opacity: '0.8' }, '100%': { transform: 'translate3d(-2.4vw, 114vh, 0) rotateZ(380deg) rotateY(360deg)', opacity: '0', }, }); /** * Lateral petal sway on the wrapper, decoupled from the fall so the two combine * into an organic wind-borne path rather than a straight drop. */ export const animPetalSway = keyframes({ '0%': { transform: 'translate3d(0, 0, 0)' }, '50%': { transform: 'translate3d(2.8vw, 0, 0)' }, '100%': { transform: 'translate3d(0, 0, 0)' }, }); /** * Dragon drift — the gold dragon silhouette breathes and undulates almost * imperceptibly across the scene. translate + scale + opacity only, very slow. */ export const animDragonDrift = keyframes({ '0%': { transform: 'translate3d(-2%, 0, 0) scale(1)', opacity: '0.42' }, '50%': { transform: 'translate3d(2%, -1%, 0) scale(1.04)', opacity: '0.6' }, '100%': { transform: 'translate3d(-2%, 0, 0) scale(1)', opacity: '0.42' }, }); /** * Lacquer-tint breathing — a barely-there pulse of the warm red ambient wash so * the static base feels alive without distracting motion. */ export const animLacquerPulse = keyframes({ '0%': { opacity: '0.82' }, '50%': { opacity: '1' }, '100%': { opacity: '0.82' }, }); /** * Gold ember rise — tiny sparks of lantern light float gently upward and fade, * like motes drifting off the flames. translateY + opacity only. */ export const animEmberRise = keyframes({ '0%': { transform: 'translate3d(0, 0, 0) scale(0.6)', opacity: '0' }, '15%': { opacity: '0.85' }, '80%': { opacity: '0.5' }, '100%': { transform: 'translate3d(0.6vw, -26vh, 0) scale(1)', opacity: '0' }, });