46 lines
2.4 KiB
TypeScript
46 lines
2.4 KiB
TypeScript
|
|
import { keyframes } from '@vanilla-extract/css';
|
||
|
|
|
||
|
|
// Fireflies — a slow, gentle PAN of sparse glowing motes across a warm summer
|
||
|
|
// dusk. The scene in animFireflies.ts stacks these background layers:
|
||
|
|
// 1. large bright motes — tile 227x227, brightest core+halo, drifts FASTEST
|
||
|
|
// 2. medium motes — tile 293x293, dimmer, medium drift
|
||
|
|
// 3. tiny far sparks — tile 179x179, faintest, drifts SLOWEST (small step)
|
||
|
|
// 4. center vignette (100% 100%) — STATIC
|
||
|
|
// 5. warm dusk wash A (100% 100%) — STATIC
|
||
|
|
// 6. warm dusk wash B (100% 100%) — STATIC
|
||
|
|
//
|
||
|
|
// Seamless drift: the single `animation` shorthand shares ONE duration across all
|
||
|
|
// layers, so the differing apparent speeds come purely from how FAR each layer
|
||
|
|
// travels. For a jump-free loop every mote layer must translate by an EXACT
|
||
|
|
// integer multiple of its own tile period in BOTH axes, so the mote re-entering
|
||
|
|
// at the wrap is identical to the one that left. Each layer moves exactly one
|
||
|
|
// full tile:
|
||
|
|
// large : -227 / -227 (1 x 227)
|
||
|
|
// medium: -293 / -293 (1 x 293) — bigger tile, same 1-tile move => SLOWER look
|
||
|
|
// far : -179 / -179 (1 x 179) — smallest tile, damped by low opacity so it
|
||
|
|
// reads as the calm distant layer
|
||
|
|
// Because tile sizes differ, one shared 1-tile translation yields three distinct
|
||
|
|
// apparent speeds — the wandering-firefly parallax — while every layer lands back
|
||
|
|
// on an identical phase at 100% for a perfectly seamless repeat.
|
||
|
|
//
|
||
|
|
// The diagonal component (both x and y shift) makes motes feel like they wander
|
||
|
|
// through the meadow rather than slide flatly. The three static layers (vignette
|
||
|
|
// and the two dusk washes) are pinned at '0 0' every frame so the warm ambient
|
||
|
|
// glow and the calm reading center never move under the text.
|
||
|
|
//
|
||
|
|
// The '0%' frame MUST match the static backgroundPosition authored in
|
||
|
|
// animFireflies.ts, so when getChatBg STRIPS this animation for
|
||
|
|
// prefers-reduced-motion the finished scene of glowing motes shows without a jump.
|
||
|
|
export const firefliesDrift = keyframes({
|
||
|
|
'0%': {
|
||
|
|
// large, medium, far, vignette, wash A, wash B
|
||
|
|
backgroundPosition: '0 0, 83px 47px, 131px 101px, 0 0, 0 0, 0 0',
|
||
|
|
},
|
||
|
|
'100%': {
|
||
|
|
// large: 0-227 / 0-227
|
||
|
|
// medium: 83-293 / 47-293
|
||
|
|
// far: 131-179 / 101-179
|
||
|
|
backgroundPosition: '-227px -227px, -210px -246px, -48px -78px, 0 0, 0 0, 0 0',
|
||
|
|
},
|
||
|
|
});
|