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>
117 lines
4.8 KiB
TypeScript
117 lines
4.8 KiB
TypeScript
import { ChatBgVariants } from './types';
|
||
|
||
// circuit — an elegant printed-circuit board.
|
||
//
|
||
// Concept: thin right-angle copper traces route between small pads / vias and
|
||
// the occasional solder-junction dot, over a deep board base. It reads as an
|
||
// authentic PCB rather than a plain grid: the routing turns corners, dead-ends
|
||
// at through-hole pads, and picks up faint via-glows — but stays sparse, with
|
||
// generous negative space so message text always wins the contrast fight.
|
||
//
|
||
// The trace network is a single inline SVG data-URI (encodeURIComponent, NOT
|
||
// base64 — CSP / Tauri-safe) so the geometry can be real right-angle routing
|
||
// instead of gradient fakery. It is layered over a subtle board-base gradient.
|
||
//
|
||
// SEAMLESS TILING — the 120×120 tile is authored so every trace that leaves an
|
||
// edge re-enters at the identical coordinate on the OPPOSITE edge, so the copper
|
||
// runs continuously across tile boundaries with no visible seam:
|
||
// • horizontal runs cross the left/right edges at y = 30 and y = 90
|
||
// • vertical runs cross the top/bottom edges at x = 40 and x = 88
|
||
// backgroundSize is set to the tile size (120px) so those crossings line up
|
||
// exactly on repeat.
|
||
//
|
||
// Two hand-tuned SVGs (dark / light) differ only in stroke/fill colour + alpha.
|
||
// Alphas stay low (≈0.05–0.5 on the accents, traces ~0.1–0.16) so the pattern is
|
||
// felt, not read — crisp text sits comfortably above it in both themes.
|
||
|
||
// Shared geometry, colour-parameterised so the two themes stay pixel-identical
|
||
// in layout and only diverge in palette.
|
||
const tile = (
|
||
trace: string, // trace stroke colour
|
||
traceW: string, // trace stroke-width
|
||
pad: string, // pad ring colour
|
||
padFill: string, // pad centre / board-coloured hole
|
||
via: string, // via glow colour
|
||
junction: string, // filled junction-dot colour
|
||
): string => {
|
||
const svg = `<svg xmlns='http://www.w3.org/2000/svg' width='120' height='120' viewBox='0 0 120 120'>
|
||
<g fill='none' stroke='${trace}' stroke-width='${traceW}' stroke-linecap='round' stroke-linejoin='round'>
|
||
<path d='M0 30 H26 V58 H60'/>
|
||
<path d='M60 58 V90 H120'/>
|
||
<path d='M0 90 H40 V120'/>
|
||
<path d='M40 0 V22 H88'/>
|
||
<path d='M88 0 V44 H104'/>
|
||
<path d='M104 44 V90 H120'/>
|
||
<path d='M88 120 V90'/>
|
||
<path d='M60 30 H120'/>
|
||
<path d='M60 30 V58'/>
|
||
<path d='M26 58 V90'/>
|
||
</g>
|
||
<g fill='none' stroke='${pad}' stroke-width='${traceW}'>
|
||
<circle cx='26' cy='58' r='3.4'/>
|
||
<circle cx='40' cy='90' r='3.4'/>
|
||
<circle cx='88' cy='22' r='3.4'/>
|
||
<circle cx='104' cy='44' r='3.4'/>
|
||
</g>
|
||
<g fill='${padFill}'>
|
||
<circle cx='26' cy='58' r='1.3'/>
|
||
<circle cx='40' cy='90' r='1.3'/>
|
||
<circle cx='88' cy='22' r='1.3'/>
|
||
<circle cx='104' cy='44' r='1.3'/>
|
||
</g>
|
||
<g fill='${junction}'>
|
||
<circle cx='60' cy='58' r='2'/>
|
||
<circle cx='60' cy='30' r='2'/>
|
||
<circle cx='104' cy='90' r='2'/>
|
||
</g>
|
||
<g fill='${via}'>
|
||
<circle cx='26' cy='58' r='7'/>
|
||
<circle cx='88' cy='22' r='7'/>
|
||
<circle cx='104' cy='44' r='7'/>
|
||
</g>
|
||
</svg>`;
|
||
return `url("data:image/svg+xml,${encodeURIComponent(svg)}")`;
|
||
};
|
||
|
||
export const circuit: ChatBgVariants = {
|
||
// Faint teal/green copper with dim cyan via-glows on a near-black board.
|
||
dark: {
|
||
backgroundColor: 'oklch(0.17 0.02 165)',
|
||
backgroundImage: [
|
||
tile(
|
||
'oklch(0.7 0.1 165 / 0.16)', // traces — faint teal-green copper
|
||
'1',
|
||
'oklch(0.72 0.11 175 / 0.32)', // pad rings — slightly brighter
|
||
'oklch(0.17 0.02 165)', // pad holes — board colour (drilled look)
|
||
'oklch(0.78 0.13 200 / 0.14)', // via glow — dim cyan halo
|
||
'oklch(0.74 0.12 170 / 0.4)', // junction dots — solid copper
|
||
),
|
||
// board-base: a gentle diagonal sheen so the flat near-black gains depth.
|
||
'radial-gradient(130% 130% at 20% 12%, oklch(0.22 0.03 170 / 0.6) 0%, transparent 58%)',
|
||
// vignette: barely darkens the corners like a laminated board edge.
|
||
'radial-gradient(140% 140% at 50% 45%, transparent 62%, oklch(0.12 0.02 165 / 0.55) 100%)',
|
||
].join(','),
|
||
backgroundSize: ['120px 120px', '100% 100%', '100% 100%'].join(','),
|
||
},
|
||
|
||
// Soft green-grey traces on a pale board.
|
||
light: {
|
||
backgroundColor: 'oklch(0.96 0.012 160)',
|
||
backgroundImage: [
|
||
tile(
|
||
'oklch(0.55 0.07 165 / 0.24)', // traces — soft green-grey copper
|
||
'1',
|
||
'oklch(0.5 0.08 170 / 0.4)', // pad rings
|
||
'oklch(0.96 0.012 160)', // pad holes — board colour
|
||
'oklch(0.6 0.09 200 / 0.1)', // via glow — faint cool halo
|
||
'oklch(0.5 0.08 165 / 0.42)', // junction dots
|
||
),
|
||
// board-base: a hint of brighter laminate toward the top-left.
|
||
'radial-gradient(130% 130% at 20% 12%, oklch(0.99 0.008 160 / 0.7) 0%, transparent 58%)',
|
||
// vignette: soft green-grey shading into the corners.
|
||
'radial-gradient(140% 140% at 50% 45%, transparent 62%, oklch(0.9 0.02 160 / 0.5) 100%)',
|
||
].join(','),
|
||
backgroundSize: ['120px 120px', '100% 100%', '100% 100%'].join(','),
|
||
},
|
||
};
|