From db57cc202ee1cc8bb72f8cc2cb38b3ab8abb8773 Mon Sep 17 00:00:00 2001 From: root Date: Wed, 13 May 2026 22:36:48 -0400 Subject: [PATCH] Implement LotusGuild TDS v1.2 terminal mode - Rewrite lotus-terminal.css.ts: TDS-exact dot-grid bg, scanlines, vignette, glitch keyframes, orange caret, cyan scrollbars, all --lt-* CSS vars - Fix lotusTerminalTheme in colors.css.ts: full TDS color palette (Orange primary, Cyan secondary, Green success, Amber warning, Red critical) - Add lotus-boot.ts: matrix boot sequence at 65ms intervals, green phosphor glow - Update ThemeManager.tsx: call runLotusBootSequence on terminal mode activate, UnAuthRouteThemeManager now supports lotusTerminal setting - Update index.html: add JetBrains Mono + VT323 from Google Fonts --- index.html | 3 + src/app/pages/ThemeManager.tsx | 13 ++- src/colors.css.ts | 134 +++++++++++++-------------- src/lotus-boot.ts | 74 +++++++++++++++ src/lotus-terminal.css.ts | 163 +++++++++++++++++++++++++++++---- 5 files changed, 300 insertions(+), 87 deletions(-) create mode 100644 src/lotus-boot.ts diff --git a/index.html b/index.html index 26c632d9e..6854c5abc 100644 --- a/index.html +++ b/index.html @@ -25,6 +25,9 @@ /> + + + diff --git a/src/app/pages/ThemeManager.tsx b/src/app/pages/ThemeManager.tsx index dbbff60fd..8c1e028db 100644 --- a/src/app/pages/ThemeManager.tsx +++ b/src/app/pages/ThemeManager.tsx @@ -12,20 +12,24 @@ import { import { lotusTerminalBodyClass } from '../../lotus-terminal.css'; import { useSetting } from '../state/hooks/settings'; import { settingsAtom } from '../state/settings'; +import { runLotusBootSequence } from '../../lotus-boot'; export function UnAuthRouteThemeManager() { const systemThemeKind = useSystemThemeKind(); + const [lotusTerminal] = useSetting(settingsAtom, 'lotusTerminal'); useEffect(() => { document.body.className = ''; document.body.classList.add(configClass, varsClass); - if (systemThemeKind === ThemeKind.Dark) { + if (lotusTerminal) { + document.body.classList.add(...LotusTerminalTheme.classNames); + document.body.classList.add(lotusTerminalBodyClass); + } else if (systemThemeKind === ThemeKind.Dark) { document.body.classList.add(...DarkTheme.classNames); - } - if (systemThemeKind === ThemeKind.Light) { + } else { document.body.classList.add(...LightTheme.classNames); } - }, [systemThemeKind]); + }, [systemThemeKind, lotusTerminal]); return null; } @@ -43,6 +47,7 @@ export function AuthRouteThemeManager({ children }: { children: ReactNode }) { document.body.classList.add(...effectiveTheme.classNames); if (lotusTerminal) { document.body.classList.add(lotusTerminalBodyClass); + runLotusBootSequence(); } if (monochromeMode && !lotusTerminal) { document.body.style.filter = 'grayscale(1)'; diff --git a/src/colors.css.ts b/src/colors.css.ts index 09fb20c40..10890529f 100644 --- a/src/colors.css.ts +++ b/src/colors.css.ts @@ -239,97 +239,97 @@ export const butterTheme = createTheme(color, { export const lotusTerminalTheme = createTheme(color, { Background: { - Container: '#0a0000', - ContainerHover: '#140500', - ContainerActive: '#1e0800', - ContainerLine: '#2a0b00', - OnContainer: '#ffd0b8', + Container: '#030508', + ContainerHover: '#060c14', + ContainerActive: '#0d1520', + ContainerLine: '#07101a', + OnContainer: '#c4d9ee', }, Surface: { - Container: '#140500', - ContainerHover: '#1e0800', - ContainerActive: '#2a0b00', - ContainerLine: '#360e00', - OnContainer: '#ffd0b8', + Container: '#060c14', + ContainerHover: '#0d1520', + ContainerActive: '#07101a', + ContainerLine: '#111d2b', + OnContainer: '#c4d9ee', }, SurfaceVariant: { - Container: '#1e0800', - ContainerHover: '#2a0b00', - ContainerActive: '#360e00', - ContainerLine: '#421100', - OnContainer: '#ffd0b8', + Container: '#0d1520', + ContainerHover: '#07101a', + ContainerActive: '#111d2b', + ContainerLine: '#162436', + OnContainer: '#c4d9ee', }, Primary: { - Main: '#ff3300', - MainHover: '#ff4d1a', - MainActive: '#ff5c2e', - MainLine: '#ff6640', - OnMain: '#0a0000', - Container: '#3d0d00', - ContainerHover: '#4a1000', - ContainerActive: '#571300', - ContainerLine: '#641600', - OnContainer: '#ffb399', + Main: '#FF6B00', + MainHover: '#FF8C2B', + MainActive: '#FF9940', + MainLine: '#FFA655', + OnMain: '#030508', + Container: '#2a1200', + ContainerHover: '#3a1a00', + ContainerActive: '#4a2200', + ContainerLine: '#5a2a00', + OnContainer: '#FFB87A', }, Secondary: { - Main: '#00dd66', - MainHover: '#00c75c', - MainActive: '#00b352', - MainLine: '#009e49', - OnMain: '#0a0000', - Container: '#003318', - ContainerHover: '#00401e', - ContainerActive: '#004d24', - ContainerLine: '#005a2a', - OnContainer: '#99ffcc', + Main: '#00D4FF', + MainHover: '#33DFFF', + MainActive: '#4DE5FF', + MainLine: '#66EBFF', + OnMain: '#030508', + Container: '#001a22', + ContainerHover: '#002233', + ContainerActive: '#002a3d', + ContainerLine: '#003347', + OnContainer: '#99E8FF', }, Success: { - Main: '#00dd66', - MainHover: '#00c75c', - MainActive: '#00b352', - MainLine: '#009e49', - OnMain: '#0a0000', - Container: '#003318', - ContainerHover: '#00401e', - ContainerActive: '#004d24', - ContainerLine: '#005a2a', - OnContainer: '#99ffcc', + Main: '#00FF88', + MainHover: '#33FFAA', + MainActive: '#4DFFB8', + MainLine: '#66FFC6', + OnMain: '#030508', + Container: '#002211', + ContainerHover: '#002a16', + ContainerActive: '#00331b', + ContainerLine: '#003b20', + OnContainer: '#99FFCC', }, Warning: { - Main: '#ffaa00', - MainHover: '#e69900', - MainActive: '#cc8800', - MainLine: '#b37700', - OnMain: '#0a0000', - Container: '#332200', - ContainerHover: '#402b00', - ContainerActive: '#4d3300', - ContainerLine: '#5a3c00', - OnContainer: '#ffd980', + Main: '#FFB300', + MainHover: '#FFC233', + MainActive: '#FFCC4D', + MainLine: '#FFD566', + OnMain: '#030508', + Container: '#221900', + ContainerHover: '#2a2000', + ContainerActive: '#332800', + ContainerLine: '#3b2e00', + OnContainer: '#FFE08A', }, Critical: { - Main: '#ff6666', - MainHover: '#ff5252', - MainActive: '#ff3d3d', - MainLine: '#ff2929', - OnMain: '#0a0000', - Container: '#3d0000', - ContainerHover: '#4a0000', - ContainerActive: '#570000', - ContainerLine: '#640000', - OnContainer: '#ffb3b3', + Main: '#FF2D55', + MainHover: '#FF4D6D', + MainActive: '#FF6080', + MainLine: '#FF7390', + OnMain: '#030508', + Container: '#22000d', + ContainerHover: '#2a0011', + ContainerActive: '#330015', + ContainerLine: '#3b0019', + OnContainer: '#FF99AA', }, Other: { - FocusRing: 'rgba(255, 51, 0, 0.6)', + FocusRing: 'rgba(0, 212, 255, 0.5)', Shadow: 'rgba(0, 0, 0, 1)', - Overlay: 'rgba(0, 0, 0, 0.85)', + Overlay: 'rgba(3, 5, 8, 0.94)', }, }); diff --git a/src/lotus-boot.ts b/src/lotus-boot.ts new file mode 100644 index 000000000..4c101a197 --- /dev/null +++ b/src/lotus-boot.ts @@ -0,0 +1,74 @@ +const BOOT_MESSAGES = [ + '╔═══════════════════════════════════════════════════╗', + '║ LOTUS CHAT — LOTUSGUILD PLATFORM ║', + '║ SECURE MATRIX CLIENT — TERMINAL MODE ACTIVE ║', + '╚════════════════════════════════════════════════════╝', + '', + '[ OK ] Kernel modules loaded', + '[ OK ] Filesystem mounted read-write', + '[ OK ] Network interfaces configured', + '[ OK ] Matrix homeserver connection established', + '[ OK ] End-to-end encryption initialized', + '[ OK ] Authentication service started', + '[ OK ] Security headers applied', + '[ OK ] Room state synchronized', + '[ OK ] Terminal interface rendered', + '', + '> ALL SYSTEMS NOMINAL — LOTUS CHAT', + '', +]; + +const STORAGE_KEY = 'lt_booted_lotus-chat'; + +export function resetBootSequence(): void { + sessionStorage.removeItem(STORAGE_KEY); +} + +export function runLotusBootSequence(force = false): void { + if (!force && sessionStorage.getItem(STORAGE_KEY)) return; + sessionStorage.setItem(STORAGE_KEY, '1'); + + const overlay = document.createElement('div'); + overlay.id = 'lt-boot'; + overlay.style.cssText = [ + 'position:fixed', + 'inset:0', + 'background:#000', + 'z-index:10100', + 'display:flex', + 'align-items:flex-start', + 'justify-content:flex-start', + 'padding:3rem', + "font-family:'JetBrains Mono','Fira Code','Courier New',monospace", + ].join(';'); + + const pre = document.createElement('pre'); + pre.style.cssText = [ + 'font-family:inherit', + 'font-size:0.78rem', + 'color:#00FF88', + 'text-shadow:0 0 6px #00FF88,0 0 16px rgba(0,255,136,0.45)', + 'line-height:1.7', + 'white-space:pre-wrap', + 'overflow:hidden', + ].join(';'); + overlay.appendChild(pre); + document.body.appendChild(overlay); + + let i = 0; + let text = ''; + const interval = setInterval(() => { + if (i >= BOOT_MESSAGES.length) { + clearInterval(interval); + setTimeout(() => { + overlay.style.transition = 'opacity 0.5s ease'; + overlay.style.opacity = '0'; + setTimeout(() => overlay.remove(), 500); + }, 500); + return; + } + text += BOOT_MESSAGES[i] + '\n'; + pre.textContent = text; + i++; + }, 65); +} diff --git a/src/lotus-terminal.css.ts b/src/lotus-terminal.css.ts index da61590ab..eaafa3428 100644 --- a/src/lotus-terminal.css.ts +++ b/src/lotus-terminal.css.ts @@ -1,28 +1,159 @@ -import { globalStyle, style } from '@vanilla-extract/css'; +import { globalStyle, keyframes, style } from '@vanilla-extract/css'; -export const lotusTerminalBodyClass = style({}); - -globalStyle(`body.${lotusTerminalBodyClass}`, { - fontFamily: "'JetBrains Mono', 'Fira Code', 'Cascadia Code', Consolas, 'Courier New', monospace", - letterSpacing: '0.01em', +const glitch1 = keyframes({ + '0%, 90%, 100%': { clipPath: 'inset(0)', transform: 'skewX(0)' }, + '92%': { clipPath: 'inset(15% 0 72% 0)', transform: 'skewX(-4deg)' }, + '94%': { clipPath: 'inset(54% 0 22% 0)', transform: 'skewX(3deg)' }, + '96%': { clipPath: 'inset(30% 0 48% 0)', transform: 'skewX(-2deg)' }, }); +const glitch2 = keyframes({ + '0%, 90%, 100%': { clipPath: 'inset(0)', transform: 'skewX(0)' }, + '92%': { clipPath: 'inset(60% 0 8% 0)', transform: 'skewX(3deg)' }, + '94%': { clipPath: 'inset(8% 0 68% 0)', transform: 'skewX(-3deg)' }, + '96%': { clipPath: 'inset(42% 0 38% 0)', transform: 'skewX(1deg)' }, +}); + +export const lotusTerminalBodyClass = style({ + fontFamily: "'JetBrains Mono', 'Fira Code', 'Cascadia Code', 'Courier New', monospace", + letterSpacing: '0.02em', + // Dot-grid background — TDS exact (on body since we're scoped to body class) + backgroundColor: '#030508', + backgroundImage: 'radial-gradient(circle, rgba(0,212,255,0.055) 1px, transparent 1px)', + backgroundSize: '28px 28px', + vars: { + // Backgrounds + '--lt-bg-primary': '#030508', + '--lt-bg-secondary': '#060c14', + '--lt-bg-tertiary': '#0d1520', + '--lt-bg-card': '#07101a', + '--lt-bg-terminal': '#010304', + // Accent — Orange + '--lt-accent-orange': '#FF6B00', + '--lt-accent-orange-bright': '#FF8C2B', + '--lt-accent-orange-dim': 'rgba(255,107,0,0.12)', + '--lt-accent-orange-border': 'rgba(255,107,0,0.35)', + // Accent — Amber + '--lt-accent-amber': '#FFB300', + '--lt-accent-amber-dim': 'rgba(255,179,0,0.10)', + // Accent — Cyan + '--lt-accent-cyan': '#00D4FF', + '--lt-accent-cyan-bright': '#33DFFF', + '--lt-accent-cyan-dim': 'rgba(0,212,255,0.10)', + '--lt-accent-cyan-border': 'rgba(0,212,255,0.22)', + // Accent — Green + '--lt-accent-green': '#00FF88', + '--lt-accent-green-bright': '#33FFAA', + '--lt-accent-green-dim': 'rgba(0,255,136,0.10)', + '--lt-accent-green-border': 'rgba(0,255,136,0.22)', + // Accent — Red + '--lt-accent-red': '#FF2D55', + '--lt-accent-red-dim': 'rgba(255,45,85,0.12)', + // Accent — Gold + '--lt-accent-gold': '#FFD700', + '--lt-accent-gold-dim': 'rgba(255,215,0,0.10)', + // Accent — Purple + '--lt-accent-purple': '#BF5FFF', + '--lt-accent-purple-dim': 'rgba(191,95,255,0.10)', + // Text + '--lt-text-primary': '#c4d9ee', + '--lt-text-secondary': '#7fa3bf', + '--lt-text-muted': '#3e607a', + '--lt-text-dim': '#1e3347', + // Borders + '--lt-border-color': 'rgba(0,212,255,0.16)', + '--lt-border-color-hi': '#00D4FF', + '--lt-border-color-dim': 'rgba(0,212,255,0.07)', + // Glows — text + '--lt-glow-orange': '0 0 6px #FF6B00, 0 0 16px rgba(255,107,0,0.55)', + '--lt-glow-orange-intense':'0 0 8px #FF6B00, 0 0 22px #FF6B00, 0 0 40px rgba(255,107,0,0.45)', + '--lt-glow-cyan': '0 0 6px #00D4FF, 0 0 16px rgba(0,212,255,0.45)', + '--lt-glow-cyan-intense': '0 0 8px #00D4FF, 0 0 22px #00D4FF, 0 0 38px rgba(0,212,255,0.35)', + '--lt-glow-green': '0 0 6px #00FF88, 0 0 16px rgba(0,255,136,0.45)', + '--lt-glow-green-intense': '0 0 8px #00FF88, 0 0 22px #00FF88, 0 0 36px rgba(0,255,136,0.35)', + '--lt-glow-amber': '0 0 6px #FFB300, 0 0 14px rgba(255,179,0,0.40)', + '--lt-glow-amber-intense': '0 0 8px #FFB300, 0 0 20px #FFB300, 0 0 34px rgba(255,179,0,0.45)', + '--lt-glow-red': '0 0 6px #FF2D55, 0 0 16px rgba(255,45,85,0.45)', + // Glows — box + '--lt-box-glow-orange': '0 0 18px rgba(255,107,0,0.22), 0 0 36px rgba(255,107,0,0.08)', + '--lt-box-glow-cyan': '0 0 18px rgba(0,212,255,0.18), 0 0 36px rgba(0,212,255,0.06)', + '--lt-box-glow-green': '0 0 18px rgba(0,255,136,0.18), 0 0 36px rgba(0,255,136,0.06)', + '--lt-box-glow-red': '0 0 18px rgba(255,45,85,0.22), 0 0 36px rgba(255,45,85,0.08)', + '--lt-box-glow-amber': '0 0 18px rgba(255,179,0,0.18), 0 0 36px rgba(255,179,0,0.06)', + // Fonts + '--lt-font-mono': "'JetBrains Mono', 'Fira Code', 'Cascadia Code', 'Courier New', monospace", + '--lt-font-display': "'JetBrains Mono', 'Fira Code', 'Courier New', monospace", + '--lt-font-crt': "'VT323', 'Courier New', monospace", + } as any, +}); + +// Font on all descendants globalStyle(`body.${lotusTerminalBodyClass} *`, { - fontFamily: "'JetBrains Mono', 'Fira Code', 'Cascadia Code', Consolas, 'Courier New', monospace !important" as any, + fontFamily: "'JetBrains Mono', 'Fira Code', 'Cascadia Code', 'Courier New', monospace", }); -globalStyle(`body.${lotusTerminalBodyClass}::after`, { - content: '""', +// Scanlines — EXACT from TDS body::before +globalStyle(`body.${lotusTerminalBodyClass}::before`, { + content: "''", position: 'fixed', - top: 0, - left: 0, - right: 0, - bottom: 0, + inset: 0, + background: 'repeating-linear-gradient(0deg, rgba(0,0,0,0.07) 0px, rgba(0,0,0,0.07) 1px, transparent 1px, transparent 3px)', pointerEvents: 'none', zIndex: 9999, - backgroundImage: 'repeating-linear-gradient(0deg, transparent, transparent 2px, rgba(0,0,0,0.12) 2px, rgba(0,0,0,0.12) 4px)', }); -globalStyle(`body.${lotusTerminalBodyClass} input, body.${lotusTerminalBodyClass} textarea`, { - caretColor: '#ff3300', +// Vignette — EXACT from TDS body::after +globalStyle(`body.${lotusTerminalBodyClass}::after`, { + content: "''", + position: 'fixed', + inset: 0, + background: 'radial-gradient(ellipse at center, transparent 55%, rgba(0,0,0,0.60) 100%)', + pointerEvents: 'none', + zIndex: 9998, +}); + +// Orange caret +globalStyle(`body.${lotusTerminalBodyClass} input, body.${lotusTerminalBodyClass} textarea`, { + caretColor: '#FF6B00', +}); + +// Glitch class support +globalStyle(`body.${lotusTerminalBodyClass} .lt-glitch`, { position: 'relative' }); + +globalStyle( + `body.${lotusTerminalBodyClass} .lt-glitch::before, body.${lotusTerminalBodyClass} .lt-glitch::after`, + { + content: 'attr(data-text)' as any, + position: 'absolute', + top: 0, + left: 0, + width: '100%', + overflow: 'hidden', + } +); + +globalStyle(`body.${lotusTerminalBodyClass} .lt-glitch::before`, { + color: '#00D4FF', + opacity: 0.65, + animationName: glitch1, + animationDuration: '4s', + animationIterationCount: 'infinite', +}); + +globalStyle(`body.${lotusTerminalBodyClass} .lt-glitch::after`, { + color: '#FF6B00', + animationName: glitch2, + animationDuration: '4s', + animationIterationCount: 'infinite', +}); + +// Scrollbar styling — matching TDS +globalStyle(`body.${lotusTerminalBodyClass} ::-webkit-scrollbar`, { width: '6px', height: '6px' }); +globalStyle(`body.${lotusTerminalBodyClass} ::-webkit-scrollbar-track`, { background: '#030508' }); +globalStyle(`body.${lotusTerminalBodyClass} ::-webkit-scrollbar-thumb`, { + background: 'rgba(0,212,255,0.25)', + borderRadius: '3px', +}); +globalStyle(`body.${lotusTerminalBodyClass} ::-webkit-scrollbar-thumb:hover`, { + background: 'rgba(0,212,255,0.50)', });