136 lines
6.9 KiB
TypeScript
136 lines
6.9 KiB
TypeScript
|
|
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 };
|