02b2ce8109
Same treatment as the seasonal themes: split the 502-line chatBackground.ts Record into one premium module per background under lotus/backgrounds/ (each exposes a tuned dark + light ChatBgVariants), one Opus agent per background against a shared brief. chatBackground.ts now assembles DARK/LIGHT from the modules; getChatBg is unchanged. Carbon + Aurora are kept inline as-is (user favorites); none stays the empty layer. Every redesign: layered oklch palettes, seamless tiling with worked-out tile math (integer-multiple periods; edge-wrapping inline-SVG data-URIs for circuit/hexgrid/waves/herringbone/chevron/tactical), independently-tuned dark+light (not a recolor), and low "felt-not-read" opacity so chat text stays WCAG-AA legible. The 5 animated backgrounds (rain, star drift, grid pulse, aurora flow, fireflies) each colocate a vanilla-extract keyframe .css.ts, animate only background-position for a jump-free loop, and — since getChatBg strips animation for reduced-motion — render a finished static frame too. Redesigned: blueprint, stars, topographic, herringbone, crosshatch, chevron, polka, triangles, plaid, tactical, circuit, hexgrid, waves, neon, anim-rain, anim-stars, anim-pulse, anim-aurora, anim-fireflies. Gates: tsc clean, ESLint clean, Prettier clean, build OK, 551 tests pass. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
40 lines
2.0 KiB
TypeScript
40 lines
2.0 KiB
TypeScript
import { keyframes } from '@vanilla-extract/css';
|
|
|
|
// Star Drift — a slow, serene PAN of a deep-space starfield with real parallax.
|
|
//
|
|
// The starfield in animStars.ts stacks six background layers:
|
|
// 1. near stars — tile 137x137, brighter, drifts FASTEST
|
|
// 2. mid stars — tile 191x191, medium
|
|
// 3. far dust — tile 233x233, dimmest, drifts SLOWEST
|
|
// 4. center vignette (100% 100%) — STATIC
|
|
// 5. nebula wash A (100% 100%) — STATIC
|
|
// 6. nebula wash B (100% 100%) — STATIC
|
|
//
|
|
// Seamless parallax: the single `animation` shorthand shares ONE duration across
|
|
// all layers, so speed differences are produced purely by how FAR each layer
|
|
// travels in the keyframe. For a perfectly seamless loop each star layer must
|
|
// translate by an EXACT integer multiple of its own tile period, so the pixel
|
|
// re-entering at the wrap is identical to the one that left. We move:
|
|
// near : -274px = 2 x 137 (two tiles -> fastest apparent drift)
|
|
// mid : -191px = 1 x 191 (one tile -> medium)
|
|
// far : -233px = 1 x 233 (one tile, but larger tile => slowest apparent)
|
|
// so near/mid/far read as three depths sliding past each other, yet every layer
|
|
// lands back on an identical phase at 100% for a jump-free repeat.
|
|
//
|
|
// A diagonal component (both x and y shift) makes the drift feel like gentle
|
|
// motion through space rather than a flat slide. The static layers are pinned at
|
|
// '0 0' every frame so the vignette and nebula never move under the text.
|
|
//
|
|
// The start frame ('0%') MUST match the static backgroundPosition authored in
|
|
// animStars.ts, so that when getChatBg STRIPS this animation for
|
|
// prefers-reduced-motion the finished starfield shows without a jump.
|
|
export const starDrift = keyframes({
|
|
'0%': {
|
|
backgroundPosition: '0 0, 61px 43px, 113px 97px, 0 0, 0 0, 0 0',
|
|
},
|
|
'100%': {
|
|
// near: -274/-274 (2 tiles), mid: 61-191/43-191, far: 113-233/97-233
|
|
backgroundPosition: '-274px -274px, -130px -148px, -120px -136px, 0 0, 0 0, 0 0',
|
|
},
|
|
});
|