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,135 @@
|
||||
import { CSSProperties } from 'react';
|
||||
import { ChatBgVariants } from './types';
|
||||
|
||||
// plaid — an authentic woven tartan, muted to a heather-wool hush.
|
||||
//
|
||||
// Real tartan is not a grid of lines: it is a *sett* — a repeating sequence of
|
||||
// coloured bands of different widths — thrown in BOTH warp (vertical) and weft
|
||||
// (horizontal) directions with the SAME sequence. Where a warp band crosses a
|
||||
// weft band of the same colour the yarn density doubles and the colour visibly
|
||||
// deepens; that reinforced overlap at every crossing is exactly what makes cloth
|
||||
// read as woven rather than printed. We reproduce that physically with
|
||||
// semi-transparent bands: a vertical band at alpha a and a horizontal band at
|
||||
// alpha a stack to ~2a where they cross (over transparent to 1x elsewhere), so
|
||||
// the crossings darken on their own with no extra layer.
|
||||
//
|
||||
// THE SETT (band widths across one tile)
|
||||
// We use a few closely-related widths for a wool-flannel rhythm rather than a
|
||||
// clean check: a wide ground band, a medium companion, and a thin accent
|
||||
// over-stripe of a warmer hue (the classic single guard line). The identical
|
||||
// sequence in warp and weft yields the tartan lattice. A faint diagonal twill
|
||||
// hatch sits on top at very low alpha to suggest the 2/2 twill thread angle of
|
||||
// woven wool. A soft central wash lifts the reading zone and a gentle vignette
|
||||
// settles the corners.
|
||||
//
|
||||
// SEAMLESS TILING
|
||||
// Every band layer is a `repeating-linear-gradient` whose stop sequence is
|
||||
// expressed in px and whose period divides the tile exactly (dark tile 96px:
|
||||
// wide=48, medium=24, accent=96; light tile 88px similarly). Warp layers repeat
|
||||
// at 0deg-across (90deg gradient) and weft at 0deg, sharing one square
|
||||
// `backgroundSize`, so the sett closes on itself with no seam in either axis.
|
||||
// The twill hatch is a repeating-linear-gradient on a small square tile that
|
||||
// divides the main tile. Wash and vignette are single non-repeating gradients
|
||||
// at 100% 100%, so they never seam.
|
||||
|
||||
const dark: CSSProperties = {
|
||||
// Deep muted forest-charcoal ground.
|
||||
backgroundColor: 'oklch(0.19 0.018 155)',
|
||||
backgroundImage: [
|
||||
// Twill hatch — whisper-faint diagonal thread angle of the weave itself.
|
||||
'repeating-linear-gradient(45deg,' +
|
||||
' oklch(0.55 0.03 155 / 0.03) 0px, oklch(0.55 0.03 155 / 0.03) 1px,' +
|
||||
' transparent 1px, transparent 4px)',
|
||||
|
||||
// WEFT (horizontal bands) --------------------------------------------
|
||||
// Wide muted-forest ground band.
|
||||
'repeating-linear-gradient(0deg,' +
|
||||
' oklch(0.45 0.05 150 / 0.14) 0px, oklch(0.45 0.05 150 / 0.14) 22px,' +
|
||||
' transparent 22px, transparent 48px)',
|
||||
// Medium companion band (cooler, offset into the ground gap).
|
||||
'repeating-linear-gradient(0deg,' +
|
||||
' transparent 0px, transparent 60px,' +
|
||||
' oklch(0.42 0.035 175 / 0.11) 60px, oklch(0.42 0.035 175 / 0.11) 72px,' +
|
||||
' transparent 72px, transparent 96px)',
|
||||
// Thin warm amber guard line — the single accent over-stripe.
|
||||
'repeating-linear-gradient(0deg,' +
|
||||
' transparent 0px, transparent 36px,' +
|
||||
' oklch(0.60 0.08 40 / 0.13) 36px, oklch(0.60 0.08 40 / 0.13) 38px,' +
|
||||
' transparent 38px, transparent 96px)',
|
||||
|
||||
// WARP (vertical bands, identical sett) -------------------------------
|
||||
'repeating-linear-gradient(90deg,' +
|
||||
' oklch(0.45 0.05 150 / 0.14) 0px, oklch(0.45 0.05 150 / 0.14) 22px,' +
|
||||
' transparent 22px, transparent 48px)',
|
||||
'repeating-linear-gradient(90deg,' +
|
||||
' transparent 0px, transparent 60px,' +
|
||||
' oklch(0.42 0.035 175 / 0.11) 60px, oklch(0.42 0.035 175 / 0.11) 72px,' +
|
||||
' transparent 72px, transparent 96px)',
|
||||
'repeating-linear-gradient(90deg,' +
|
||||
' transparent 0px, transparent 36px,' +
|
||||
' oklch(0.60 0.08 40 / 0.13) 36px, oklch(0.60 0.08 40 / 0.13) 38px,' +
|
||||
' transparent 38px, transparent 96px)',
|
||||
|
||||
// Tonal wash — soft warm-green lift through the reading centre.
|
||||
'radial-gradient(ellipse 92% 78% at 50% 42%, oklch(0.27 0.03 150 / 0.38) 0%, transparent 62%)',
|
||||
// Vignette — feather the corners into deeper forest-charcoal.
|
||||
'radial-gradient(ellipse 122% 132% at 50% 45%, transparent 58%, oklch(0.14 0.016 155 / 0.55) 100%)',
|
||||
].join(','),
|
||||
backgroundSize:
|
||||
'8px 8px,' + // twill (multiple of 4px hatch period → seamless)
|
||||
'96px 96px, 96px 96px, 96px 96px,' + // weft: wide, medium, accent
|
||||
'96px 96px, 96px 96px, 96px 96px,' + // warp: wide, medium, accent
|
||||
'100% 100%, 100% 100%', // wash, vignette
|
||||
};
|
||||
|
||||
const light: CSSProperties = {
|
||||
// Warm off-white paper ground.
|
||||
backgroundColor: 'oklch(0.965 0.007 85)',
|
||||
backgroundImage: [
|
||||
// Twill hatch — faint diagonal weave angle on paper.
|
||||
'repeating-linear-gradient(45deg,' +
|
||||
' oklch(0.45 0.03 250 / 0.025) 0px, oklch(0.45 0.03 250 / 0.025) 1px,' +
|
||||
' transparent 1px, transparent 4px)',
|
||||
|
||||
// WEFT (horizontal bands) --------------------------------------------
|
||||
// Wide dusty-blue ground band.
|
||||
'repeating-linear-gradient(0deg,' +
|
||||
' oklch(0.60 0.045 245 / 0.12) 0px, oklch(0.60 0.045 245 / 0.12) 20px,' +
|
||||
' transparent 20px, transparent 44px)',
|
||||
// Medium greige companion band.
|
||||
'repeating-linear-gradient(0deg,' +
|
||||
' transparent 0px, transparent 55px,' +
|
||||
' oklch(0.62 0.018 90 / 0.11) 55px, oklch(0.62 0.018 90 / 0.11) 66px,' +
|
||||
' transparent 66px, transparent 88px)',
|
||||
// Thin warm sand guard line — the single accent over-stripe.
|
||||
'repeating-linear-gradient(0deg,' +
|
||||
' transparent 0px, transparent 33px,' +
|
||||
' oklch(0.68 0.06 55 / 0.12) 33px, oklch(0.68 0.06 55 / 0.12) 35px,' +
|
||||
' transparent 35px, transparent 88px)',
|
||||
|
||||
// WARP (vertical bands, identical sett) -------------------------------
|
||||
'repeating-linear-gradient(90deg,' +
|
||||
' oklch(0.60 0.045 245 / 0.12) 0px, oklch(0.60 0.045 245 / 0.12) 20px,' +
|
||||
' transparent 20px, transparent 44px)',
|
||||
'repeating-linear-gradient(90deg,' +
|
||||
' transparent 0px, transparent 55px,' +
|
||||
' oklch(0.62 0.018 90 / 0.11) 55px, oklch(0.62 0.018 90 / 0.11) 66px,' +
|
||||
' transparent 66px, transparent 88px)',
|
||||
'repeating-linear-gradient(90deg,' +
|
||||
' transparent 0px, transparent 33px,' +
|
||||
' oklch(0.68 0.06 55 / 0.12) 33px, oklch(0.68 0.06 55 / 0.12) 35px,' +
|
||||
' transparent 35px, transparent 88px)',
|
||||
|
||||
// Tonal wash — warm paper highlight through the reading centre.
|
||||
'radial-gradient(ellipse 92% 78% at 50% 42%, oklch(0.99 0.008 85 / 0.55) 0%, transparent 62%)',
|
||||
// Vignette — settle the corners into a slightly deeper dusty tone.
|
||||
'radial-gradient(ellipse 122% 132% at 50% 45%, transparent 58%, oklch(0.90 0.014 245 / 0.40) 100%)',
|
||||
].join(','),
|
||||
backgroundSize:
|
||||
'8px 8px,' + // twill (multiple of 4px hatch period → seamless)
|
||||
'88px 88px, 88px 88px, 88px 88px,' + // weft: wide, medium, accent
|
||||
'88px 88px, 88px 88px, 88px 88px,' + // warp: wide, medium, accent
|
||||
'100% 100%, 100% 100%', // wash, vignette
|
||||
};
|
||||
|
||||
export const plaid: ChatBgVariants = { dark, light };
|
||||
Reference in New Issue
Block a user