Sentinel Frontend — Design System
CSS tokens, typography, theme configuration, and utility reference for Pencil v2 alignment.
Typography
Font Stack
Four Google Fonts loaded via next/font/google in app/src/app/layout.tsx with CSS variable injection:
| Font |
Variable |
CSS Alias |
Role |
Weights |
| Inter |
--font-inter |
font-sans |
UI: buttons, labels, navigation, body text |
400 (default) |
| Cormorant Garamond |
--font-cormorant |
font-display |
Display: page titles, section headers |
400, 500, 600 |
| IBM Plex Mono |
--font-ibm-mono |
font-data, font-mono |
Data: metrics, financial values, code |
400, 500, 600, 700 |
| DM Sans |
--font-dm-sans |
font-body |
Body: descriptions, paragraphs |
400, 500, 600, 700 |
Font Resolution Chain
--font-display: var(--font-cormorant, 'Cormorant Garamond'), Georgia, serif;
--font-sans: var(--font-inter, 'Inter'), system-ui, -apple-system, sans-serif;
--font-mono: var(--font-ibm-mono, 'IBM Plex Mono'), 'JetBrains Mono', monospace;
--font-data: var(--font-ibm-mono, 'IBM Plex Mono'), 'JetBrains Mono', monospace;
--font-body: var(--font-dm-sans, 'DM Sans'), var(--font-inter, 'Inter'), sans-serif;
Typography Utility Classes
| Class |
Font Family |
Extra Properties |
Usage |
font-display |
var(--font-display) |
— |
Page titles, hero text |
font-body |
var(--font-body) |
— |
Descriptions, paragraphs |
font-data |
var(--font-data) |
'tnum' 1, 'lnum' 1 |
Financial values, metrics |
font-terminal |
JetBrains Mono stack |
'liga' 1, 'calt' 1 |
Terminal theme text |
text-display |
var(--font-display) |
letter-spacing: -0.01em |
Tight-tracked display text |
tracking-metrics |
— |
letter-spacing: -0.02em |
Metrics with tight tracking |
section-header |
var(--font-display) |
text-2xl font-semibold tracking-tight |
Section headers |
metric-value |
var(--font-data) |
'tnum' 1, 'lnum' 1, leading-none |
Large metric displays |
ticker-label |
var(--font-data) |
uppercase tracking-widest text-xs |
Ticker-style labels |
data-cell |
var(--font-data) |
text-sm tabular-nums |
Data grid cells |
keyword-tag |
var(--font-data) |
px-2 py-0.5 rounded-sm text-xs |
Financial keyword tags |
tabular-nums |
— |
tabular-nums lining-nums |
Aligned numeric columns |
Usage Guidelines
Page Title → font-display text-2xl+ font-semibold
Section Header → section-header (or font-display manually)
Body Text → font-body (or default font-sans)
Metric Value → metric-value (or font-data manually)
Button / Label → font-sans (Inter, default)
Code / Terminal → font-mono or font-terminal
Theme System
Service Detection
Route-based service detection in theme-provider.tsx:
URL path starts with /zen/* → Service: 'zen'
Otherwise → Service: 'nexus'
Mode Resolution
| Mode |
Nexus Service |
Zen Service |
auto |
Light |
Dark |
light |
Light |
Light |
dark |
Dark |
Dark |
terminal |
Terminal |
Terminal |
Persistence: localStorage key sentinel-theme-mode.
CSS Class Application
| Color Scheme |
HTML/Body Classes |
Activated By |
| Light |
light nexus |
:root (default) |
| Dark |
dark zen |
.dark, .zen selector |
| Terminal |
dark terminal |
.terminal selector (extends .dark) |
Theme Hooks
| Hook |
Return Type |
Purpose |
useTheme() |
Full context |
Mode, scheme, service, setMode, forceTheme |
useService() |
'nexus' \| 'zen' |
Current service |
useIsZen() |
boolean |
Zen service or dark scheme |
useIsNexus() |
boolean |
Nexus service AND light scheme |
useIsTerminal() |
boolean |
Terminal mode active |
useThemeClass() |
Helper function |
Theme-conditional class names |
useThemeVariable() |
Getter function |
Read computed CSS variable |
Theme-Conditional Classes
const tc = useThemeClass();
<div className={tc({
nexus: 'bg-white text-gray-900',
zen: 'bg-slate-800 text-white',
terminal: 'bg-black text-green-400',
both: 'rounded-lg p-4', // applied in all themes
})} />
Color Tokens
Nexus (Light) — :root
| Token |
Value |
Usage |
--primary |
#2563EB |
Primary blue |
--primary-foreground |
#FFFFFF |
Text on primary |
--background |
#F9FAFB |
Page background |
--foreground |
#111827 |
Primary text |
--card |
#FFFFFF |
Card background |
--card-foreground |
#111827 |
Card text |
--secondary |
#F3F4F6 |
Secondary surfaces |
--secondary-foreground |
#374151 |
Secondary text |
--muted |
#F3F4F6 |
Muted surfaces |
--muted-foreground |
#6B7280 |
Muted text |
--accent |
#EFF6FF |
Accent highlight |
--accent-foreground |
#1D4ED8 |
Accent text |
--destructive |
#EF4444 |
Error / danger |
--border |
#E5E7EB |
Border color |
--input |
#E5E7EB |
Input border |
--ring |
#2563EB |
Focus ring |
Zen (Dark) — .dark, .zen
| Token |
Value |
Usage |
--primary |
#3B82F6 |
Primary blue (lighter for dark bg) |
--primary-foreground |
#FFFFFF |
Text on primary |
--background |
#0F172A |
Deep slate background |
--foreground |
#F8FAFC |
Light text |
--card |
#1E293B |
Elevated surface |
--card-foreground |
#F1F5F9 |
Card text |
--secondary |
#334155 |
Secondary surface |
--secondary-foreground |
#E2E8F0 |
Secondary text |
--muted |
#334155 |
Muted surface |
--muted-foreground |
#94A3B8 |
Muted text |
--accent |
#8B5CF6 |
Purple accent (agent badges) |
--accent-foreground |
#FFFFFF |
Accent text |
--destructive |
#F87171 |
Error (lighter for dark bg) |
--border |
#475569 |
Border color |
--input |
#475569 |
Input border |
--ring |
#3B82F6 |
Focus ring |
Terminal — .terminal
| Token |
Value |
Usage |
--primary |
var(--terminal-green) = #00FF88 |
Neon green |
--primary-foreground |
#0A0E14 |
Dark text on green |
--background |
#0A0E14 |
Deep black |
--foreground |
#E8E8E8 |
Light gray text |
--card |
#0D1117 |
Slightly elevated |
--secondary |
#161B22 |
Layer 2 surface |
--muted |
#21262D |
Layer 3 surface |
--muted-foreground |
#8B949E |
Dim text |
--accent |
var(--terminal-cyan) = #00FFFF |
Cyan highlight |
--destructive |
var(--terminal-red) = #FF3B3B |
Neon red |
--border |
#30363D |
Subtle border |
--radius |
0.25rem |
Sharper corners (vs 0.5rem) |
Terminal Neon Colors
| Variable |
Value |
Dim |
Glow |
--terminal-green |
#00FF88 |
#00CC6A |
rgba(0,255,136,0.5) |
--terminal-cyan |
#00FFFF |
#00CCCC |
rgba(0,255,255,0.5) |
--terminal-amber |
#FFB800 |
#CC9200 |
rgba(255,184,0,0.5) |
--terminal-magenta |
#FF00FF |
#CC00CC |
rgba(255,0,255,0.5) |
--terminal-red |
#FF3B3B |
#CC2F2F |
rgba(255,59,59,0.5) |
--terminal-blue |
#3B82F6 |
— |
rgba(59,130,246,0.5) |
--terminal-white |
#E8E8E8 |
— |
— |
--terminal-gray |
#888888 |
— |
— |
Status Colors
| Token |
Nexus |
Zen |
Terminal |
--success |
#10B981 |
#34D399 |
var(--terminal-green) |
--warning |
#F59E0B |
#FBBF24 |
var(--terminal-amber) |
--info |
#3B82F6 |
#60A5FA |
var(--terminal-cyan) |
--destructive |
#EF4444 |
#F87171 |
var(--terminal-red) |
Chart Palette
| Token |
Nexus |
Zen |
Terminal |
--chart-1 |
#2563EB |
#3B82F6 |
var(--terminal-green) |
--chart-2 |
#10B981 |
#34D399 |
var(--terminal-cyan) |
--chart-3 |
#F59E0B |
#FBBF24 |
var(--terminal-amber) |
--chart-4 |
#8B5CF6 |
#A78BFA |
var(--terminal-magenta) |
--chart-5 |
#EF4444 |
#F87171 |
var(--terminal-red) |
| Token |
Nexus |
Zen |
Terminal |
--sidebar |
#FFFFFF |
#1E293B |
#0D1117 |
--sidebar-foreground |
#111827 |
#F1F5F9 |
#E8E8E8 |
--sidebar-primary |
#2563EB |
#3B82F6 |
var(--terminal-green) |
--sidebar-border |
#E5E7EB |
#475569 |
#30363D |
Radius Tokens
| Token |
Computation |
--radius |
0.5rem (Nexus/Zen), 0.25rem (Terminal) |
--radius-sm |
calc(var(--radius) - 4px) |
--radius-md |
calc(var(--radius) - 2px) |
--radius-lg |
var(--radius) |
--radius-xl |
calc(var(--radius) + 4px) |
--radius-2xl |
calc(var(--radius) + 8px) |
--radius-3xl |
calc(var(--radius) + 12px) |
--radius-4xl |
calc(var(--radius) + 16px) |
Custom Utilities
Glass Morphism
| Class |
Theme |
Properties |
glass-card |
Light |
backdrop-filter: blur(24px), white 70% opacity, soft shadow |
glass-card-dark |
Dark |
backdrop-filter: blur(24px), white 3% opacity, deep shadow |
Financial Data
| Class |
Purpose |
value-positive |
Green + + prefix for gains |
value-negative |
Red for losses |
value-neutral |
Gray for unchanged |
audience-tag |
Financial audience badges (WM, FO, PE, AIF) |
market-badge |
Market session time badges |
Chat Bubbles
| Class |
Style |
chat-bubble-user |
Primary bg, rounded with bottom-right notch |
chat-bubble-assistant |
Secondary bg, rounded with bottom-left notch |
Confidence Indicators
| Class |
Color |
confidence-high |
Green 500 |
confidence-medium |
Yellow 500 |
confidence-low |
Red 500 |
Status Dots
| Class |
Color |
status-dot-success |
Emerald 500 |
status-dot-warning |
Amber 500 |
status-dot-error |
Red 500 |
status-dot-info |
Blue 500 |
status-dot-processing |
Blue 500 + pulse animation |
| Class |
Behavior |
scrollbar-hide |
Hidden scrollbar (still scrollable) |
scrollbar-thin |
8px thin scrollbar with slate-600 thumb |
Terminal Effects
Text Glow
| Class |
Color |
glow-green |
Green neon text-shadow |
glow-cyan |
Cyan neon text-shadow |
glow-amber |
Amber neon text-shadow |
glow-magenta |
Magenta neon text-shadow |
glow-red |
Red neon text-shadow |
Box Glow
| Class |
Color |
box-glow-green |
Green neon box-shadow + inset |
box-glow-cyan |
Cyan neon box-shadow + inset |
box-glow-amber |
Amber neon box-shadow + inset |
CRT Effects
| Class |
Effect |
scanlines |
Repeating horizontal lines overlay |
crt-effect |
Radial vignette overlay |
terminal-flicker |
Subtle opacity flicker (5s cycle) |
glow-pulse |
Brightness oscillation (2s cycle) |
cursor-blink |
Blinking block cursor |
terminal-prompt |
❯ prefix in terminal green |
matrix-bg |
SVG binary digit background pattern |
data-stream |
Vertical gradient animation |
Terminal Components
| Class |
Purpose |
terminal-input |
Input with green underline and caret |
progress-terminal |
Progress bar with green glow |
code-block |
Syntax-highlighted code block |
table-terminal |
Monospace table with cyan headers |
kbd |
Keyboard shortcut badge |
kbd-primary |
Highlighted keyboard shortcut |
status-online |
Green pulsing dot indicator |
status-offline |
Red static dot indicator |
status-warning |
Amber fast-pulsing dot |
typing-dots |
Bouncing triple-dot animation |
Animations
Brand Animations
| Class |
Duration |
Effect |
animate-sentinel-float |
3s |
Gentle Y-axis bob |
animate-sentinel-rotate |
6s |
Subtle 3D rotation |
animate-sentinel-pulse |
1.8s |
Width expansion pulse |
animate-sentinel-stagger-in |
0.5s |
Slide-up entrance |
animate-sentinel-fade-scale |
0.4s |
Scale-up fade entrance |
Terminal Animations
| Keyframe |
Duration |
Effect |
blink |
1s |
Step-end opacity toggle |
pulse-glow |
∞ |
Opacity + box-shadow pulse |
stream |
2s |
Vertical gradient scroll |
typing-bounce |
1.4s |
Staggered dot bounce |
terminal-flicker |
5s |
CRT-style flicker |
glow-pulse |
2s |
Brightness oscillation |
slide-in-up |
0.3s |
Y-offset entrance |
fade-in |
0.2s |
Opacity entrance |
Tailwind Custom Variants
@custom-variant dark (&:is(.dark *)); /* Dark mode variant */
@custom-variant zen (&:is(.zen *)); /* Zen-specific variant */
@custom-variant terminal (&:is(.terminal *)); /* Terminal-specific variant */
Usage in components:
<div className="bg-white dark:bg-slate-900 terminal:bg-black" />
Theme Constants
Exported from theme-provider.tsx for programmatic use:
THEME_COLORS.nexus // { primary: '#2563EB', background: '#FAFBFC', surface: '#FFFFFF', ... }
THEME_COLORS.zen // { primary: '#3B82F6', background: '#0B1120', surface: '#141B2D', ... }
THEME_COLORS.terminal // { primary: '#00FF88', background: '#0A0E14', surface: '#0D1117', ... }
Token Usage Rules
Do
// Use CSS variable tokens
<div className="bg-background text-foreground" />
<div className="bg-card border-border" />
<div className="text-muted-foreground" />
<button className="bg-primary text-primary-foreground hover:bg-primary/90" />
Don’t
// Never hardcode colors
<div className="bg-white text-gray-900" /> // ✗ Use bg-card text-foreground
<div className="bg-[#2563EB]" /> // ✗ Use bg-primary
<div className="text-gray-500" /> // ✗ Use text-muted-foreground
<div className="border-gray-200" /> // ✗ Use border-border
Source Files
| File |
Purpose |
app/src/app/globals.css |
All CSS tokens, utilities, animations |
app/src/app/layout.tsx |
Font loading (4 Google Fonts) |
app/src/lib/theme-provider.tsx |
Theme context, service detection, mode resolution |
app/src/components/common/theme-switcher.tsx |
UI for mode selection |
Last updated: 2026-02-03