# NERV Theme (Tactical Console Aesthetic)

[Top](../README.md) | [Shaders & Window](guide_shaders_and_window.md) | [Architecture](guide_architecture.md)

---

## 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:

1. **Design Philosophy** — Why NERV looks the way it does
2. **Visual Components** — Palette, geometry, typography, effects
3. **Implementation** — The `theme_nerv.py` and `theme_nerv_fx.py` modules
4. **Configuration** — `config.toml` keys
5. **Performance** — Cost of FX rendering
6. **Testing** — Visual verification

---

## Design Philosophy

The NERV theme is built around three principles:

1. **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.
2. **Zero-Rounding Geometry** — No rounded corners on panels, buttons, frames, or separators. Sharp rectangles convey "instrumentation," not "consumer app."
3. **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

| Role | Hex | Usage |
|---|---|---|
| **Background** | `#000000` | Primary window background |
| **Panel** | `#0A0A0A` | Panel and group backgrounds |
| **Text Primary** | `#E0E0E0` | Body text, labels |
| **Text Secondary** | `#A0A0A0` | Subdued text, hints |
| **Accent (NERV Orange)** | `#FF6B00` | Primary action color, active state |
| **Accent (NERV Red)** | `#E50000` | Error, blocked, abort state |
| **Accent (NERV Green)** | `#00C800` | Success, completed state |
| **Accent (NERV Blue)** | `#0080FF` | Information, in-progress state |
| **Border** | `#1A1A1A` | Panel and window borders |
| **Border Active** | `#FF6B00` | Active focus indicator |

The accent colors are the iconic NERV orange, red, green, and blue — visible against the black void without being saturated to the point of eye strain.

### 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 active tier indicator in the MMA Dashboard, and other "operational status" elements, flicker at a low frequency (default: 0.5 Hz, configurable). The flicker is implemented as a sine wave on the alpha channel:

```python
alpha = 0.7 + 0.3 * math.sin(time.monotonic() * 2 * math.pi * 0.5)
```

This creates a subtle "tactical display" effect without being distracting.

### CRT Scanlines

A repeating horizontal line overlay applied via the `custom_background` callback. The scanlines are drawn at 2-pixel intervals, with the scanline alpha at ~30% by default (configurable).

**Implementation**: Uses the FBO pipeline described in [guide_shaders_and_window.md#1-shader-injection-strategy](guide_shaders_and_window.md#1-shader-injection-strategy). The scanline pass is a fragment shader that modulates output color based on the screen-space Y coordinate.

**Performance cost**: ~1-2ms per frame on a 1920×1080 display with default settings.

### Alert Animations

When MMA state transitions to `"blocked"` or `"error"`, a red border pulse animation runs for ~1.5 seconds:

1. At t=0, the border alpha spikes to 1.0.
2. Over 1.5 seconds, the alpha decays exponentially to 0.1.
3. The border color is the NERV red (`#E50000`).

This makes operational failures immediately visible without requiring the user to look at a specific panel.

---

## Implementation

### `src/theme_nerv.py` — Base Theme

Defines the color palette, geometry overrides, and font selection. The application function applies these to the active ImGui style.

```python
def apply_nerv() -> None:
    style = imgui.get_style()
    style.colors[imgui.Col_.window_bg] = (0.0, 0.0, 0.0, 1.0)
    style.colors[imgui.Col_.text] = (0.88, 0.88, 0.88, 1.0)
    # ... (all other colors per the palette table)
    style.window_rounding = 0.0
    style.frame_rounding = 0.0
    style.child_rounding = 0.0
    # ... (geometry overrides)
    # Apply fonts
```

### `src/theme_nerv_fx.py` — Visual Effects

Implements the per-frame effects that go beyond static styling:

- **Status flickering**: Sine-wave alpha modulation for active-state indicators.
- **CRT scanlines**: Custom background shader (delegated to `bg_shader.py`).
- **Alert animations**: Time-based border pulse on state transitions.

```python
def render_nerv_fx(fx_state: dict) -> None:
    """Per-frame NERV FX. Called from the main render loop when NERV is active."""
    if not fx_state.get("fx_enabled", True):
        return
    render_scanlines(fx_state.get("scanline_alpha", 0.3))
    render_status_flicker(fx_state.get("flicker_rate_hz", 0.5))
    render_alert_pulse(fx_state.get("alert_state"))
```

### `src/bg_shader.py` — Background Shader

The custom background shader (used for scanlines) is in `src/bg_shader.py`. It uses the FBO pipeline described in the Shaders & Window guide.

### Activation

The NERV theme is activated via the GUI's theme picker:

```
User Menu → Theme → NERV
```

Or programmatically:

```python
from src.theme_nerv import apply_nerv
apply_nerv()
```

When activated, the active color set, geometry style, and font are swapped. The FX layer is enabled/disabled via the `[nerv].fx_enabled` config flag (default: enabled).

---

## Configuration

`config.toml`:

```toml
[nerv]
fx_enabled = true                 # Master toggle for all FX
scanline_alpha = 0.3              # 0.0 (none) to 1.0 (opaque)
flicker_rate_hz = 0.5             # Flicker frequency for active-state indicators
alert_pulse_duration_seconds = 1.5 # How long the red border pulse runs
alert_pulse_color = "#E50000"      # Hex color for the alert pulse
```

| Key | Default | Description |
|---|---|---|
| `fx_enabled` | `true` | Master toggle. When `false`, no scanlines, no flickering, no alerts. |
| `scanline_alpha` | `0.3` | Alpha of the scanline overlay. `0.0` disables scanlines; `1.0` makes them solid (usually too aggressive). |
| `flicker_rate_hz` | `0.5` | Frequency of status flickering. `0.0` disables. Values > `2.0` become seizure-inducing. |
| `alert_pulse_duration_seconds` | `1.5` | How long the red border pulse runs on errors. `0.0` disables. |
| `alert_pulse_color` | `"#E50000"` | Hex color of the alert pulse. |

### Per-Project Override

Projects can override the NERV settings in `manual_slop.toml` under a `[theme_nerv]` section (with the same keys). The project override wins over the global `config.toml`.

---

## 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:

```python
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

1. **Scanlines Are Static**: The current implementation uses a fixed scanline pattern. Animated scanlines (slow vertical scroll) are not implemented.

2. **No Color Customization in GUI**: The NERV palette is hardcoded. To customize colors, edit `src/theme_nerv.py` directly (no GUI editor for NERV-specific colors).

3. **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").

4. **Performance Cost on Low-End GPUs**: The FBO scanline pass may be too expensive on integrated graphics or older GPUs. The `fx_enabled` flag is the workaround.

5. **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](guide_shaders_and_window.md) for the underlying shader and window frame infrastructure.
