feat(chat-bg): redesign 19 chat backgrounds as modular per-pattern files
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>
This commit is contained in:
@@ -0,0 +1,98 @@
|
||||
import { ChatBgVariants } from './types';
|
||||
import { firefliesDrift } from './animFireflies.css';
|
||||
|
||||
// Fireflies — a warm summer-dusk meadow. A few soft golden-green motes drift over
|
||||
// a deep base, each mote a bright core melting into a warm halo. Sparse by design
|
||||
// so the reading column stays clear; the motion is a slow, gentle background-
|
||||
// position PAN (see animFireflies.css.ts) that reads as fireflies wandering.
|
||||
//
|
||||
// Layer stacking order (topmost first — CSS paints image #1 on top):
|
||||
// 1. large bright motes — crisp warm core -> warm halo, sparse, largest step
|
||||
// 2. medium motes — dimmer, smaller, more of them
|
||||
// 3. tiny far sparks — faintest, smallest tile, calm distant layer
|
||||
// 4. center vignette — keeps the reading center the calmest area
|
||||
// 5. warm dusk wash A — ambient glow, upper
|
||||
// 6. warm dusk wash B — ambient glow, lower
|
||||
// Mote tiles use coprime-ish sizes (227/293/179) so their repeats never line up
|
||||
// and the field reads as scattered, not gridded.
|
||||
//
|
||||
// getChatBg STRIPS the `animation` for prefers-reduced-motion / pause, so the
|
||||
// authored backgroundPosition already composes a finished, gorgeous still scene
|
||||
// of glowing motes on its own — the animation only sets them gently adrift.
|
||||
export const animFireflies: ChatBgVariants = {
|
||||
// Dark: warm gold-green glows on a deep forest-navy base with a soft vignette.
|
||||
// Cores sit near oklch(0.85 0.13 110); halos fall to a warm amber-green. All
|
||||
// opacities are kept low so message text stays crisp (WCAG-AA) over the field.
|
||||
dark: {
|
||||
backgroundColor: 'oklch(0.17 0.035 175)',
|
||||
backgroundImage: [
|
||||
// 1. large bright motes — golden-green core fading through a warm halo
|
||||
'radial-gradient(circle at center, oklch(0.85 0.13 110 / 0.55) 1.4px, oklch(0.72 0.14 95 / 0.16) 3px, transparent 6px)',
|
||||
// 2. medium motes — a touch cooler-green, dimmer, more numerous
|
||||
'radial-gradient(circle at center, oklch(0.82 0.13 128 / 0.40) 1.1px, oklch(0.70 0.12 110 / 0.12) 2.4px, transparent 5px)',
|
||||
// 3. tiny far sparks — faint warm pinpoints, the calm distant layer
|
||||
'radial-gradient(circle at center, oklch(0.88 0.11 100 / 0.28) 0.8px, transparent 2.4px)',
|
||||
// 4. center vignette — darkens the edges, keeps reading center calmest
|
||||
'radial-gradient(ellipse 125% 95% at 50% 44%, transparent 40%, oklch(0.10 0.03 175 / 0.55) 100%)',
|
||||
// 5. warm dusk wash A — a low amber-green glow drifting in from upper-right
|
||||
'radial-gradient(ellipse 140% 120% at 80% 10%, oklch(0.30 0.07 120 / 0.45) 0%, transparent 58%)',
|
||||
// 6. warm dusk wash B — deep teal-navy pooling into the lower-left
|
||||
'radial-gradient(ellipse 135% 115% at 16% 94%, oklch(0.22 0.05 190 / 0.50) 0%, transparent 60%)',
|
||||
].join(','),
|
||||
backgroundSize: [
|
||||
'227px 227px', // large motes
|
||||
'293px 293px', // medium motes
|
||||
'179px 179px', // far sparks
|
||||
'100% 100%', // vignette
|
||||
'100% 100%', // wash A
|
||||
'100% 100%', // wash B
|
||||
].join(','),
|
||||
backgroundPosition: [
|
||||
'0 0', // large (matches firefliesDrift 0%)
|
||||
'83px 47px', // medium (offset breaks alignment)
|
||||
'131px 101px', // far (offset again)
|
||||
'0 0', // vignette (static)
|
||||
'0 0', // wash A (static)
|
||||
'0 0', // wash B (static)
|
||||
].join(','),
|
||||
animation: `${firefliesDrift} 44s linear infinite`,
|
||||
},
|
||||
|
||||
// Light: a cozy warm dim-dusk. No harsh dots on white — soft amber motes with
|
||||
// gentle halos float on a warm blush->honey gradient. Contrast stays low so the
|
||||
// reading area is comfortable and text remains crisp (WCAG-AA).
|
||||
light: {
|
||||
backgroundColor: 'oklch(0.955 0.02 85)',
|
||||
backgroundImage: [
|
||||
// 1. large amber motes — warm honey core into a soft amber halo
|
||||
'radial-gradient(circle at center, oklch(0.80 0.11 80 / 0.30) 1.4px, oklch(0.85 0.09 70 / 0.12) 3px, transparent 6px)',
|
||||
// 2. medium motes — slightly greener-gold, softer
|
||||
'radial-gradient(circle at center, oklch(0.78 0.10 95 / 0.22) 1.1px, oklch(0.86 0.08 85 / 0.10) 2.4px, transparent 5px)',
|
||||
// 3. tiny far sparks — faint warm pinpoints for texture, never noise
|
||||
'radial-gradient(circle at center, oklch(0.75 0.10 75 / 0.16) 0.8px, transparent 2.4px)',
|
||||
// 4. center vignette — brightens the calm reading center a touch
|
||||
'radial-gradient(ellipse 125% 95% at 50% 44%, oklch(1 0 0 / 0.40) 30%, transparent 100%)',
|
||||
// 5. warm dusk wash A — honey glow from the upper-right
|
||||
'radial-gradient(ellipse 140% 120% at 80% 8%, oklch(0.92 0.06 85 / 0.55) 0%, transparent 60%)',
|
||||
// 6. warm dusk wash B — soft rose blush pooling lower-left
|
||||
'radial-gradient(ellipse 135% 115% at 15% 95%, oklch(0.93 0.05 40 / 0.45) 0%, transparent 62%)',
|
||||
].join(','),
|
||||
backgroundSize: [
|
||||
'227px 227px', // large motes
|
||||
'293px 293px', // medium motes
|
||||
'179px 179px', // far sparks
|
||||
'100% 100%', // vignette
|
||||
'100% 100%', // wash A
|
||||
'100% 100%', // wash B
|
||||
].join(','),
|
||||
backgroundPosition: [
|
||||
'0 0', // large (matches firefliesDrift 0%)
|
||||
'83px 47px', // medium
|
||||
'131px 101px', // far
|
||||
'0 0', // vignette (static)
|
||||
'0 0', // wash A (static)
|
||||
'0 0', // wash B (static)
|
||||
].join(','),
|
||||
animation: `${firefliesDrift} 44s linear infinite`,
|
||||
},
|
||||
};
|
||||
Reference in New Issue
Block a user