import { keyframes } from '@vanilla-extract/css'; // Grid Pulse — a slow "energy" glow that sweeps across a static tech grid. // // The motif is a crisp thin grid that pulses. Rather than scaling the grid // (which shifts every line and reads as a jitter behind text), we keep the grid // perfectly still and PAN a single soft radial "bloom" layer diagonally across // it. As the bloom drifts, the grid lines it passes over appear to brighten and // then settle — a calm travelling pulse, never a flash. // // Layer mapping (see animPulse.ts — one background-position value per layer): // 0. grid core lines (vertical) — STATIC ('0 0') // 1. grid core lines (horizontal) — STATIC ('0 0') // 2. grid fine sub-lines (V) — STATIC ('0 0') // 3. grid fine sub-lines (H) — STATIC ('0 0') // 4. TRAVELLING BLOOM — panned here (the only moving layer) // 5. base wash / centre glow — STATIC ('0 0') // 6. vignette — STATIC ('0 0') // // Seamless loop: the bloom layer is authored to tile (its backgroundSize in // animPulse.ts is 480px — an exact 4x multiple of the 120px grid module, and // 8x of the 60px sub-grid). Panning it by EXACTLY one bloom-tile (480px on both // axes) returns every pixel to an identical neighbouring tile, so the wrap at // 100% is invisible. Diagonal travel (both axes move together) makes the sweep // feel organic while still landing on a whole-tile offset. // // getChatBg adds `willChange: 'background-position'` for the animated case, so a // background-position pulse is exactly what the compositor is hinted for. It // STRIPS this whole `animation` for prefers-reduced-motion / pause-animations, // at which point the static bloom position authored in animPulse.ts is what // shows — a finished, gently glowing grid. export const gridPulse = keyframes({ '0%': { backgroundPosition: '0 0, 0 0, 0 0, 0 0, 0px 0px, 0 0, 0 0', }, '100%': { backgroundPosition: '0 0, 0 0, 0 0, 0 0, 480px 480px, 0 0, 0 0', }, });