Files
cinny/src/app/features/lotus/backgrounds/blueprint.ts
T
jared 02b2ce8109 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>
2026-06-30 20:23:54 -04:00

86 lines
4.7 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { ChatBgVariants } from './types';
// blueprint — an engineering / architectural drafting sheet.
//
// Layers (painted top-to-bottom):
// 1. SVG draftsman tick-marks + a centred crosshair accent (96px tile — lands
// exactly on the major grid; corner quarter-arms tile into a full "+" on
// every major intersection).
// 2. Major grid lines (heavier) — 96px.
// 3. Minor grid lines (fine, fainter) — 16px (96 = 6 × 16, so it nests
// seamlessly inside the major grid with no beat/moiré).
// 4. A soft radial vignette + a gentle sheet-glow so the surface reads like a
// real drafting sheet with subtle dimension rather than a flat tile.
//
// Everything is kept at low alpha (~0.030.16) so the motif is felt, not read:
// crisp message text sits comfortably above it in both themes (WCAG-AA safe).
const DARK_TICKS =
'url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2296%22%20height%3D%2296%22%3E%3Cg%20stroke%3D%22oklch%280.72%200.11%20230%20%2F%200.32%29%22%20stroke-width%3D%221%22%3E%3Cpath%20d%3D%22M0%200%20H7%20M0%200%20V7%22%2F%3E%3Cpath%20d%3D%22M96%200%20H89%20M96%200%20V7%22%2F%3E%3Cpath%20d%3D%22M0%2096%20H7%20M0%2096%20V89%22%2F%3E%3Cpath%20d%3D%22M96%2096%20H89%20M96%2096%20V89%22%2F%3E%3C%2Fg%3E%3Cg%20stroke%3D%22oklch%280.72%200.11%20230%20%2F%200.18%29%22%20stroke-width%3D%221%22%3E%3Cpath%20d%3D%22M48%2044%20V52%20M44%2048%20H52%22%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E")';
const LIGHT_TICKS =
'url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2296%22%20height%3D%2296%22%3E%3Cg%20stroke%3D%22oklch%280.48%200.13%20250%20%2F%200.38%29%22%20stroke-width%3D%221%22%3E%3Cpath%20d%3D%22M0%200%20H7%20M0%200%20V7%22%2F%3E%3Cpath%20d%3D%22M96%200%20H89%20M96%200%20V7%22%2F%3E%3Cpath%20d%3D%22M0%2096%20H7%20M0%2096%20V89%22%2F%3E%3Cpath%20d%3D%22M96%2096%20H89%20M96%2096%20V89%22%2F%3E%3C%2Fg%3E%3Cg%20stroke%3D%22oklch%280.48%200.13%20250%20%2F%200.22%29%22%20stroke-width%3D%221%22%3E%3Cpath%20d%3D%22M48%2044%20V52%20M44%2048%20H52%22%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E")';
export const blueprint: ChatBgVariants = {
// Cyan-blue lines on a deep navy sheet.
dark: {
backgroundColor: 'oklch(0.22 0.05 250)',
backgroundImage: [
// 1. draftsman ticks + centre crosshair
DARK_TICKS,
// 4a. sheet-glow: a faint cooler highlight drifting off the top-left,
// giving the flat navy some dimension.
'radial-gradient(120% 120% at 18% 8%, oklch(0.30 0.06 245 / 0.55) 0%, transparent 55%)',
// 4b. vignette: gently darkens the corners like a drafting sheet edge.
'radial-gradient(140% 140% at 50% 42%, transparent 58%, oklch(0.14 0.04 255 / 0.5) 100%)',
// 2. major grid (heavier)
'linear-gradient(oklch(0.72 0.12 230 / 0.13) 1px, transparent 1px)',
'linear-gradient(90deg, oklch(0.72 0.12 230 / 0.13) 1px, transparent 1px)',
// 3. minor grid (fine, fainter)
'linear-gradient(oklch(0.72 0.12 230 / 0.05) 1px, transparent 1px)',
'linear-gradient(90deg, oklch(0.72 0.12 230 / 0.05) 1px, transparent 1px)',
].join(','),
backgroundSize: [
'96px 96px', // ticks
'100% 100%', // sheet-glow
'100% 100%', // vignette
'96px 96px', // major V
'96px 96px', // major H
'16px 16px', // minor V
'16px 16px', // minor H
].join(','),
// All layers share the default top-left (0 0) origin so the tick tile, the
// 96px major grid and the 16px minor grid stay phase-locked (96 = 6 × 16) —
// no drift, no visible seams. (A per-layer `center` would let the differently
// sized tiles center independently and fall out of alignment.)
},
// Blue lines on a cool paper-white sheet.
light: {
backgroundColor: 'oklch(0.97 0.01 240)',
backgroundImage: [
LIGHT_TICKS,
// sheet-glow: a hint of brighter paper toward the top-left.
'radial-gradient(120% 120% at 18% 8%, oklch(0.99 0.008 240 / 0.7) 0%, transparent 55%)',
// vignette: soft cool shading into the corners.
'radial-gradient(140% 140% at 50% 42%, transparent 60%, oklch(0.90 0.02 245 / 0.55) 100%)',
// major grid (heavier)
'linear-gradient(oklch(0.48 0.13 250 / 0.15) 1px, transparent 1px)',
'linear-gradient(90deg, oklch(0.48 0.13 250 / 0.15) 1px, transparent 1px)',
// minor grid (fine, fainter)
'linear-gradient(oklch(0.48 0.13 250 / 0.06) 1px, transparent 1px)',
'linear-gradient(90deg, oklch(0.48 0.13 250 / 0.06) 1px, transparent 1px)',
].join(','),
backgroundSize: [
'96px 96px',
'100% 100%',
'100% 100%',
'96px 96px',
'96px 96px',
'16px 16px',
'16px 16px',
].join(','),
// Shared top-left origin keeps the tick tile and both grids phase-locked.
},
};