import { keyframes } from '@vanilla-extract/css'; /** * New Year overlay keyframes — a midnight celebration. Every animation touches * ONLY `transform` and `opacity` so the compositor runs them on the GPU with no * layout/paint. keyframes() returns the generated animation-name string, which * is applied inline by the component. Heavy/static structure (gradients, SVG * data-URIs, geometry) lives in the component; this module is motion only. */ /** * Firework burst — a thin spark ring expands from a pinpoint, brightens, then * fades as it grows. Scale + opacity only; the ring is a radial-gradient border * supplied inline. Long pauses between bursts come from a low keyframe-duty: * the ring spends most of the cycle collapsed and invisible. */ export const animBurst = keyframes({ '0%': { transform: 'scale(0.05)', opacity: '0' }, '4%': { transform: 'scale(0.12)', opacity: '0.95' }, '22%': { transform: 'scale(1)', opacity: '0.55' }, '34%': { transform: 'scale(1.25)', opacity: '0' }, '100%': { transform: 'scale(1.25)', opacity: '0' }, }); /** * Burst core flash — the bright pinpoint at a firework's origin pops just before * the ring blooms, then quickly dims. Pairs with animBurst on the same cadence. */ export const animCoreFlash = keyframes({ '0%': { transform: 'scale(0.2)', opacity: '0' }, '3%': { transform: 'scale(1)', opacity: '1' }, '14%': { transform: 'scale(0.6)', opacity: '0' }, '100%': { transform: 'scale(0.6)', opacity: '0' }, }); /** * Champagne shimmer sweep — a wide soft gold band glides diagonally across the * scene and breathes in brightness. translateX + opacity (never * background-position) keep it on the compositor. */ export const animShimmer = keyframes({ '0%': { transform: 'translate3d(-120%, 0, 0) skewX(-12deg)', opacity: '0' }, '12%': { opacity: '0.7' }, '50%': { opacity: '0.5' }, '88%': { opacity: '0.6' }, '100%': { transform: 'translate3d(120%, 0, 0) skewX(-12deg)', opacity: '0' }, }); /** * Confetti fall — a small sliver tumbles the full height while spinning on two * axes, fading in at the top and out at the bottom. A tall translateY lets one * keyframe set serve every sliver; per-piece duration/delay/scale add variety. */ export const animConfettiFall = keyframes({ '0%': { transform: 'translate3d(0, -10vh, 0) rotateZ(0deg) rotateX(0deg)', opacity: '0' }, '8%': { opacity: '0.9' }, '50%': { transform: 'translate3d(2.2vw, 52vh, 0) rotateZ(220deg) rotateX(180deg)' }, '92%': { opacity: '0.85' }, '100%': { transform: 'translate3d(-1.8vw, 114vh, 0) rotateZ(440deg) rotateX(360deg)', opacity: '0', }, }); /** * Lateral confetti sway on the wrapper, decoupled from the fall so the two * combine into an organic drifting path rather than a straight drop. */ export const animConfettiSway = keyframes({ '0%': { transform: 'translate3d(0, 0, 0)' }, '50%': { transform: 'translate3d(2.4vw, 0, 0)' }, '100%': { transform: 'translate3d(0, 0, 0)' }, }); /** Star twinkle — a sparkle pulses in brightness and size, like a glint. */ export const animTwinkle = keyframes({ '0%': { transform: 'scale(0.5) rotate(0deg)', opacity: '0.2' }, '50%': { transform: 'scale(1) rotate(45deg)', opacity: '0.95' }, '100%': { transform: 'scale(0.5) rotate(0deg)', opacity: '0.2' }, }); /** Barely-there breathing of the midnight tint so the static base feels alive. */ export const animSkyPulse = keyframes({ '0%': { opacity: '0.82' }, '50%': { opacity: '1' }, '100%': { opacity: '0.82' }, });