14 KiB
NERV Theme (Tactical Console Aesthetic)
Top | Shaders & Window | Architecture
Overview
The NERV Theme is a selectable high-density visual variant inspired by the NERV tactical consoles from the Neon Genesis Evangelion anime. It uses sharp geometry, a near-black palette, CRT-style scanlines, status flickering, and alert animations to produce a "tactical command center" aesthetic that emphasizes information density and operational urgency.
This guide covers:
- Design Philosophy — Why NERV looks the way it does
- Visual Components — Palette, geometry, typography, effects
- Implementation — The
theme_nerv.pyandtheme_nerv_fx.pymodules - Configuration —
config.tomlkeys - Performance — Cost of FX rendering
- Testing — Visual verification
Design Philosophy
The NERV theme is built around three principles:
- Black Void Background — The dominant color is near-black (0,0,0 to 8,8,8 range). This reduces visual noise and lets accent colors pop.
- Zero-Rounding Geometry — No rounded corners on panels, buttons, frames, or separators. Sharp rectangles convey "instrumentation," not "consumer app."
- Operational Urgency — Status indicators flicker (subtle, low frequency). Errors trigger red border pulses. This is intentional: it makes operational state changes immediately visible to the operator.
The theme is opt-in, not the default. Most users will use the standard dark or light themes. NERV is for users who want maximum information density and a "tactical" feel.
Visual Components
Color Palette
The palette constants in src/theme_nerv.py:8-13 (computed from RGB triples via _c()):
| Constant | RGB (0-255) | Hex | Usage |
|---|---|---|---|
BLACK |
(0, 0, 0) | #000000 |
Primary window, panel, popup, frame, title, menu, scrollbar, button, tab backgrounds |
STEEL |
(224, 224, 216) | #E0E0D8 |
Text, separator, scrollbar-grab-hovered, resize-grip-hovered |
NERV_ORANGE |
(255, 152, 48) | #FF9830 |
Border, scrollbar-grab, resize-grip, nav-cursor, border-shadow alpha=0 |
ALERT_RED |
(255, 72, 64) | #FF4840 |
Used as 1.0,0.0,0.0 with sin-pulsed alpha in AlertPulsing.render (not as a steady color in NERV_PALETTE) |
DATA_GREEN |
(80, 255, 80) | #50FF50 |
Check-mark, slider-grab-active, plot-histogram, drag-drop-target, nav-windowing-highlight |
WIRE_CYAN |
(32, 240, 255) | #20F0FF |
Scrollbar-grab-active, slider-grab, plot-lines, separator-hovered, resize-grip-active |
The full NERV_PALETTE dict (47 imgui.Col_ entries, src/theme_nerv.py:15-63) maps each constant to the relevant imgui style color. The "header/header-hovered/header-active" colors are semi-transparent NERV orange (alphas 60, 100, 140) used for table-header and tree-node selection.
Geometry
- Window corners: Square (0px rounding)
- Panel corners: Square
- Button corners: Square
- Frame rounding: Disabled (
ImGuiStyle.FrameRounding = 0) - Window rounding: Disabled (
ImGuiStyle.WindowRounding = 0) - Child rounding: Disabled
This produces a "military hardware" feel that contrasts with consumer-app aesthetics.
Typography
- Primary font:
Inter(already used by other themes) - Monospace font:
Maple Mono(for code, telemetry, logs) - Font sizes: Slightly smaller than the default theme to maximize information density
- Font weights: Medium for body, Bold for headers
Status Flickering
The StatusFlicker.get_alpha() method in src/theme_nerv_fx.py:67-73 returns a value in the range [0.7, 1.0] from a sine wave:
return 0.85 + 0.15 * math.sin(time.time() * 20.0)
The angular frequency is hard-coded (20.0 rad/s ≈ 3.18 Hz, not 0.5 Hz) and the method is currently a utility — there is no production caller wiring it into a tier indicator at the time of writing.
CRT Scanlines
CRTFilter.render(width, height) in src/theme_nerv_fx.py:8-65 is invoked once per frame from theme_2.render_post_fx() (at src/theme_2.py:400-408) when NERV is active. The render method:
- Draws 1.2px (major, every 4 lines) and 0.8px (minor, every 2 lines) horizontal black lines at alphas 0.08 / 0.04
- Draws 1.0px vertical black lines every 3px at alpha 0.05 (simulated aperture-grille shadow mask)
- Draws 20 nested rounded-rectangle outlines with exponentially increasing alpha (max 0.25) for vignette/tube-curvature
- Adds 40 small white noise pixels per frame with flickering alpha (0.01-0.04) modulated by a 60 Hz sin wave
The scanline alphas and noise density are hard-coded in the FX source — there is no config knob for them.
Performance cost: ~1-2ms per frame on a 1920×1080 display with default settings (per the original 2026-05 design estimate; the new shader-less draw-list implementation in src/theme_nerv_fx.py may be faster).
Alert Animations
AlertPulsing in src/theme_nerv_fx.py:75-97 is a stateful on/off border overlay:
update(status: str)at:79-83setsself.active = status.lower().startswith("error")— i.e. any AI status string that begins with"error"(case-insensitive) triggers the pulse. There is no MMA-specific state-machine check; the call site atsrc/theme_2.py:405passes the liveai_statusfrom the controller.render(width, height)at:85-97is a no-op whilenot self.active. When active, it draws a full-screen red rectangle with alpha pulsing at0.05 + 0.15 * (sin(t·4) + 1) / 2(so alpha oscillates 0.05 ↔ 0.20 at ~0.64 Hz, no decay).- The pulse persists for the entire duration that
ai_statusstarts with"error"; it does not have a 1.5-second auto-decay. There is noalert_pulse_duration_secondsconfig.
The color is the constant (1.0, 0.0, 0.0) in src/theme_nerv_fx.py:96 (pure red, not the ALERT_RED constant), and the thickness is 10px.
Implementation
src/theme_nerv.py — Base Theme (88 lines)
Defines the 6 color constants (lines 8-13), the NERV_PALETTE dict (lines 15-63, 47 imgui.Col_ entries), and the apply_nerv() function (lines 65-87). The actual apply_nerv() is a tight loop over the palette dict, not a hand-written sequence of style.colors[col] = ... assignments:
def apply_nerv() -> None:
style = imgui.get_style()
for col_enum, rgba in NERV_PALETTE.items():
style.set_color_(col_enum, imgui.ImVec4(*rgba))
# Hard Edges
style.window_rounding = 0.0
style.child_rounding = 0.0
style.frame_rounding = 0.0
style.popup_rounding = 0.0
style.scrollbar_rounding = 0.0
style.grab_rounding = 0.0
style.tab_rounding = 0.0
# Border sizes
style.window_border_size = 1.0
style.frame_border_size = 1.0
style.popup_border_size = 1.0
style.child_border_size = 1.0
style.tab_border_size = 1.0
src/theme_nerv_fx.py — Visual Effects (97 lines)
Three classes, no module-level entry point:
CRTFilter(lines 8-65) —__init__(self)setsself.enabled = True;render(self, width, height)is the scanline/vignette/noise overlay. Theenabledflag is the only runtime toggle; the GUI controls it via thecrt_enabledparameter totheme_2.render_post_fx().StatusFlicker(lines 67-73) —get_alpha(self)returns a hard-coded 3.18 Hz sine. Currently a utility; no production caller (see §"Status Flickering" above).AlertPulsing(lines 75-97) —__init__(self)setsself.active = False;update(self, status)enables the pulse ifstatus.lower().startswith("error");render(self, width, height)is the no-op-or-pulse draw.
There is no render_nerv_fx(fx_state: dict) aggregator. The actual entry point that wires the FX layer into the GUI is theme_2.render_post_fx(width, height, ai_status, crt_enabled) at src/theme_2.py:400-408:
def render_post_fx(width: float, height: float, ai_status: str, crt_enabled: bool) -> None:
"""Updates and renders the alert and CRT filters."""
theme_nerv_fx = _require_warmed("src.theme_nerv_fx")
alert_pulsing = theme_nerv_fx.AlertPulsing()
crt_filter = theme_nerv_fx.CRTFilter()
alert_pulsing.update(ai_status)
alert_pulsing.render(width, height)
crt_filter.enabled = crt_enabled
crt_filter.render(width, height)
Note: theme_2.py:111 has a code comment saying "NERV FX objects (CRTFilter, AlertPulsing, StatusFlicker) are now created [in render_post_fx]" — this confirms the per-frame create-and-discard pattern. The previous design (FX as long-lived module-level singletons) is no longer in use.
Activation
The NERV theme is activated via the GUI's theme picker (NERV is one of the 4 built-in syntax palettes selectable via the multi-theme TOML system). The apply_nerv() call is wired into the theme-switch path of theme_2.py. To switch programmatically:
from src.theme_nerv import apply_nerv
apply_nerv()
The FX layer's CRTFilter.enabled is set per-frame by the caller of theme_2.render_post_fx(crt_enabled=...) — there is no [nerv].fx_enabled config key (see §"Configuration" below for why).
Configuration
There is no [nerv] config section in config.toml. As of 2026-06-10, the NERV FX layer's parameters (scanline alpha, flicker frequency, alert pulse color, alert pulse duration) are all hard-coded in src/theme_nerv_fx.py and have no TOML or env-var override. The only runtime toggles are:
CRTFilter.enabled— set per-frame by the caller oftheme_2.render_post_fx(crt_enabled=...); the GUI uses the NERV theme's "FX enabled" toggle to drive this.AlertPulsing.active— set automatically byupdate(ai_status)toTrueifai_status.lower().startswith("error").
Earlier versions of this guide (pre-2026-06-10) documented a [nerv] section with fx_enabled, scanline_alpha, flicker_rate_hz, alert_pulse_duration_seconds, and alert_pulse_color keys. None of those keys were ever wired into the source code — they were aspirational documentation, not configuration. This is the "stale doc" that the docs-sync track on 2026-06-10 surfaced and removed.
Performance
| Effect | Cost (1920×1080) | Cost (4K) | Notes |
|---|---|---|---|
| Scanlines (FBO) | 1-2ms/frame | 4-8ms/frame | Scales with resolution. |
| Status flicker | <0.1ms/frame | <0.1ms/frame | Per-element alpha calc, trivial. |
| Alert pulse | <0.1ms/frame | <0.1ms/frame | Per-frame interpolation, trivial. |
Total NERV overhead: ~1-2ms/frame on a 1920×1080 display with default settings. For a 60 FPS target (16.67ms/frame), this leaves 14+ ms for the rest of the GUI.
Lower-end GPU: Reduce scanline_alpha (cheaper blending) or disable FX entirely (fx_enabled = false). The base NERV theme (colors, geometry, fonts) has no measurable GPU cost.
Latency impact: None. The FX layer is purely visual; it doesn't block the main render thread.
Interaction with Other Subsystems
MMA Dashboard
The NERV theme enhances the MMA Dashboard with:
- Color-coded tier indicators (using the NERV accent colors)
- Status flickering on the active tier
- Red border pulse on "blocked" / "error" states
Diagnostics Panel
The FPS / CPU / Input Lag display uses the NERV palette. Performance warnings (FPS < 30, CPU > 80%) flash in NERV red.
Approval Modal
When the Execution Clutch suspends on a destructive action, the approval modal uses the NERV orange for the "Approve" button and the standard gray for "Reject". This makes the destructive action visually distinct.
Testing
Unit Tests
tests/test_theme_nerv.py—apply_nerv()correctly sets all colors, geometry, and fonts.tests/test_theme_nerv_fx.py— FX rendering functions don't raise, produce expected output dimensions.tests/test_theme_nerv_alert.py— Alert pulse animation runs for the configured duration and decays correctly.
Visual Verification
The NERV theme is primarily a visual feature; functional tests are limited. The [nerv] config keys are read at theme application time; a misconfigured key defaults gracefully.
For visual verification in live_gui tests:
def test_nerv_theme_active(live_gui):
# Activate NERV theme
client.activate_theme("nerv")
# Verify the active theme
status = client.get_ui_performance() # Or a theme-specific endpoint
assert "theme" in status
assert status["theme"] == "nerv"
The visual appearance (colors, scanlines) is best verified manually by a human reviewer.
Limitations
-
Scanlines Are Static: The current implementation uses a fixed scanline pattern. Animated scanlines (slow vertical scroll) are not implemented.
-
No Color Customization in GUI: The NERV palette is hardcoded. To customize colors, edit
src/theme_nerv.pydirectly (no GUI editor for NERV-specific colors). -
No Theme Mixing: The NERV theme is a single selectable theme. It cannot be mixed with other themes (e.g., "NERV colors but default rounding").
-
Performance Cost on Low-End GPUs: The FBO scanline pass may be too expensive on integrated graphics or older GPUs. The
fx_enabledflag is the workaround. -
Accessibility: The black void palette with high-contrast accents is not WCAG AA compliant for text contrast in all combinations. The active state color (NERV orange) on black meets AA, but secondary text (gray on black) is borderline. Users with low vision may need a different theme.
Future Work
- CRT Curvature: A more advanced shader could apply screen-space curvature to mimic CRT monitors. Currently planned but not implemented.
- Bloom Effect: For high-saturation accent colors, a subtle bloom could make the NERV orange "glow." Adds GPU cost.
- Animated Scanlines: Slow vertical scroll of the scanline pattern for a more "active" CRT feel.
- Custom Palette Editor: Allow the user to override individual NERV colors via the GUI.
- Hybrid Themes: Allow partial NERV adoption (e.g., NERV colors but default rounding).
See guide_shaders_and_window.md for the underlying shader and window frame infrastructure.