Deepen TDS integration: full terminal CSS coverage + 3 new backgrounds

Terminal Mode:
- Text selection: orange highlight rgba(255,107,0,0.28)
- Links: cyan (#00D4FF) with orange hover glow (#FF6B00)
- Code/pre: TDS green (#00FF88) on terminal bg, left green border
- Strong/b → orange, em/i → cyan, mark → amber, del → red
- Blockquote: orange left border (matches chat reply quotes)
- HR: cyan border with dim glow
- Input/textarea/[contenteditable] focus: orange glow ring
- Tables: TDS headers (orange+uppercase), cyan borders, hover rows
- List markers: cyan ▸ for ul, orange for ol
- Boot box-drawing alignment fixed (51→52 ═)
- data-theme=\"dark\" set on html element when terminal active
- Updated description: correct TDS palette names
- ▶ Boot replay button in settings (visible when terminal on)

Chat backgrounds (+3):
- Tactical: LotusGuild TDS exact cyan dot-grid (28px)
- Circuit: green grid + node dots on dark terminal bg
- Hex Grid: isometric cyan hexagonal outlines

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
root
2026-05-13 22:44:34 -04:00
parent 9ebce5b00c
commit c6b1a9d75f
6 changed files with 240 additions and 7 deletions
+60
View File
@@ -13,6 +13,9 @@ export const BG_OPTIONS: { value: ChatBackground; label: string }[] = [
{ value: 'polka', label: 'Polka' },
{ value: 'triangles', label: 'Triangles' },
{ value: 'plaid', label: 'Plaid' },
{ value: 'tactical', label: 'Tactical' },
{ value: 'circuit', label: 'Circuit' },
{ value: 'hexgrid', label: 'Hex Grid' },
];
const DARK: Record<ChatBackground, CSSProperties> = {
@@ -118,6 +121,36 @@ const DARK: Record<ChatBackground, CSSProperties> = {
'repeating-linear-gradient(90deg, transparent, transparent 7px, rgba(152,0,0,0.08) 7px, rgba(152,0,0,0.08) 8px)',
].join(','),
},
// LotusGuild TDS exact dot-grid
tactical: {
backgroundColor: '#030508',
backgroundImage: 'radial-gradient(circle, rgba(0,212,255,0.055) 1px, transparent 1px)',
backgroundSize: '28px 28px',
},
// Circuit board — green grid with node dots
circuit: {
backgroundColor: '#040a04',
backgroundImage: [
'linear-gradient(rgba(0,255,136,0.045) 1px, transparent 1px)',
'linear-gradient(90deg, rgba(0,255,136,0.045) 1px, transparent 1px)',
'radial-gradient(circle, rgba(0,255,136,0.20) 1.5px, transparent 1.5px)',
].join(','),
backgroundSize: '40px 40px, 40px 40px, 40px 40px',
backgroundPosition: '0 0, 0 0, 20px 20px',
},
// Isometric hex grid — cyan outlines
hexgrid: {
backgroundColor: '#060c14',
backgroundImage: [
'linear-gradient(60deg, rgba(0,212,255,0.07) 25%, transparent 25%, transparent 75%, rgba(0,212,255,0.07) 75%)',
'linear-gradient(120deg, rgba(0,212,255,0.07) 25%, transparent 25%, transparent 75%, rgba(0,212,255,0.07) 75%)',
].join(','),
backgroundSize: '30px 52px',
backgroundPosition: '0 0, 15px 26px',
},
};
const LIGHT: Record<ChatBackground, CSSProperties> = {
@@ -220,6 +253,33 @@ const LIGHT: Record<ChatBackground, CSSProperties> = {
'repeating-linear-gradient(90deg, transparent, transparent 7px, rgba(200,0,0,0.09) 7px, rgba(200,0,0,0.09) 8px)',
].join(','),
},
tactical: {
backgroundColor: '#f0f4fa',
backgroundImage: 'radial-gradient(circle, rgba(0,100,200,0.08) 1px, transparent 1px)',
backgroundSize: '28px 28px',
},
circuit: {
backgroundColor: '#f0f8f0',
backgroundImage: [
'linear-gradient(rgba(0,160,80,0.06) 1px, transparent 1px)',
'linear-gradient(90deg, rgba(0,160,80,0.06) 1px, transparent 1px)',
'radial-gradient(circle, rgba(0,160,80,0.22) 1.5px, transparent 1.5px)',
].join(','),
backgroundSize: '40px 40px, 40px 40px, 40px 40px',
backgroundPosition: '0 0, 0 0, 20px 20px',
},
hexgrid: {
backgroundColor: '#f4f8ff',
backgroundImage: [
'linear-gradient(60deg, rgba(50,100,220,0.08) 25%, transparent 25%, transparent 75%, rgba(50,100,220,0.08) 75%)',
'linear-gradient(120deg, rgba(50,100,220,0.08) 25%, transparent 25%, transparent 75%, rgba(50,100,220,0.08) 75%)',
].join(','),
backgroundSize: '30px 52px',
backgroundPosition: '0 0, 15px 26px',
},
};
export const getChatBg = (bg: ChatBackground, isDark: boolean): CSSProperties =>
+28 -2
View File
@@ -48,6 +48,7 @@ import {
} from '../../../hooks/useTheme';
import { stopPropagation } from '../../../utils/keyboard';
import { BG_OPTIONS, getChatBg } from '../../lotus/chatBackground';
import { resetBootSequence, runLotusBootSequence } from '../../../../lotus-boot';
import { useMessageLayoutItems } from '../../../hooks/useMessageLayout';
import { useMessageSpacingItems } from '../../../hooks/useMessageSpacing';
import { useDateFormatItems } from '../../../hooks/useDateFormat';
@@ -375,8 +376,33 @@ function Appearance() {
<SequenceCard className={SequenceCardStyle} variant="SurfaceVariant" direction="Column">
<SettingTile
title="Lotus Terminal Mode"
description="Red phosphor color scheme, monospace font, and retro CRT scanlines. A full visual overhaul."
after={<Switch variant="Primary" value={lotusTerminal} onChange={setLotusTerminal} />}
description="LotusGuild Terminal Design System: Anduril Orange + Ice Cyan + Matrix Green, dot-grid background, CRT scanlines, and boot sequence animation."
after={
<Box direction="Row" gap="200" align="Center">
{lotusTerminal && (
<button
type="button"
onClick={() => { resetBootSequence(); runLotusBootSequence(true); }}
title="Replay boot sequence"
style={{
background: 'transparent',
border: '1px solid rgba(255,107,0,0.35)',
color: '#FF6B00',
fontSize: '0.65rem',
padding: '0.2rem 0.6rem',
cursor: 'pointer',
fontFamily: 'inherit',
letterSpacing: '0.1em',
textTransform: 'uppercase',
whiteSpace: 'nowrap',
}}
>
Boot
</button>
)}
<Switch variant="Primary" value={lotusTerminal} onChange={setLotusTerminal} />
</Box>
}
/>
</SequenceCard>
</Box>
+10 -3
View File
@@ -22,12 +22,16 @@ export function UnAuthRouteThemeManager() {
document.body.className = '';
document.body.classList.add(configClass, varsClass);
if (lotusTerminal) {
document.documentElement.setAttribute('data-theme', 'dark');
document.body.classList.add(...LotusTerminalTheme.classNames);
document.body.classList.add(lotusTerminalBodyClass);
} else if (systemThemeKind === ThemeKind.Dark) {
document.body.classList.add(...DarkTheme.classNames);
} else {
document.body.classList.add(...LightTheme.classNames);
document.documentElement.removeAttribute('data-theme');
if (systemThemeKind === ThemeKind.Dark) {
document.body.classList.add(...DarkTheme.classNames);
} else {
document.body.classList.add(...LightTheme.classNames);
}
}
}, [systemThemeKind, lotusTerminal]);
@@ -46,8 +50,11 @@ export function AuthRouteThemeManager({ children }: { children: ReactNode }) {
document.body.classList.add(configClass, varsClass);
document.body.classList.add(...effectiveTheme.classNames);
if (lotusTerminal) {
document.documentElement.setAttribute('data-theme', 'dark');
document.body.classList.add(lotusTerminalBodyClass);
runLotusBootSequence();
} else {
document.documentElement.removeAttribute('data-theme');
}
if (monochromeMode && !lotusTerminal) {
document.body.style.filter = 'grayscale(1)';
+1 -1
View File
@@ -3,7 +3,7 @@ import { atom } from 'jotai';
const STORAGE_KEY = 'settings';
export type DateFormat = 'D MMM YYYY' | 'DD/MM/YYYY' | 'MM/DD/YYYY' | 'YYYY/MM/DD' | '';
export type MessageSpacing = '0' | '100' | '200' | '300' | '400' | '500';
export type ChatBackground = 'none' | 'blueprint' | 'carbon' | 'stars' | 'topographic' | 'herringbone' | 'crosshatch' | 'chevron' | 'polka' | 'triangles' | 'plaid';
export type ChatBackground = 'none' | 'blueprint' | 'carbon' | 'stars' | 'topographic' | 'herringbone' | 'crosshatch' | 'chevron' | 'polka' | 'triangles' | 'plaid' | 'tactical' | 'circuit' | 'hexgrid';
export enum MessageLayout {
Modern = 0,
Compact = 1,