Veritas-AI / ui_implementation_plan.md
Aditya-Jadhav150
feat: implement AEGIS-AI v4 MSCVN 5-stream engine & UI/UX modular overhaul
f5125ca
|
Raw History Blame Contribute Delete
19.5 kB
# AEGIS-AI UI/UX Overhaul Plan
## Scope
Frontend-only changes. **Zero changes** to `core/`, `aegis/`, `app.py` routes, or the detection engine. The API contract (`/api/predict` JSON response) stays identical.
---
## Current Problems
| # | Problem | Impact |
|---|---|---|
| 1 | **83KB monolithic `index.html`** β€” 2,029 lines mixing HTML, CSS (~870 lines), and JS (~500 lines) | Unmaintainable, impossible to iterate on |
| 2 | **Fake 5.1-second scanning delay** β€” hardcoded `setTimeout` stages even if backend returns instantly | Users wait for nothing, feels sluggish |
| 3 | **Broken video preview** β€” video files assigned to `<img>` tag, shows broken icon | Critical bug |
| 4 | **Vertical scroll wall** β€” all result cards stacked in one endless column | Overwhelming, key findings buried |
| 5 | **Static heatmaps** β€” ELA/FFT/Attention shown as plain images in tabs | No comparison with original, hard to interpret |
| 6 | **No export capability** β€” no PDF report, no JSON download, no share link | Useless for actual forensic workflows |
| 7 | **No audio visualization** β€” just text numbers for audio analysis | Misses opportunity to show spectrogram |
| 8 | **Orphaned `main.css`** β€” 379-line stylesheet exists but is never linked | Wasted work |
| 9 | **XGBoost Fusion badge in nav** β€” references old pipeline, misleading | Outdated branding |
---
## Design Direction
Keep the **cyberpunk glassmorphism dark theme** β€” it's striking and fits a security/forensics tool. But refine it:
- **Reduce visual noise**: Fewer glowing borders, more whitespace between sections
- **Information hierarchy**: Verdict + evidence summary visible immediately, deep metrics available on demand
- **Progressive disclosure**: Collapsed sections that expand, not a wall of everything at once
- **Interactivity**: Heatmap overlays, audio waveforms, video timeline β€” make the data explorable
---
## Proposed Changes
### 1. Modularize the Codebase
Split the monolithic `index.html` into clean, maintainable files:
```
templates/
└── index.html # Clean HTML structure only (~300 lines)
static/
β”œβ”€β”€ css/
β”‚ β”œβ”€β”€ variables.css # CSS custom properties (colors, spacing, fonts)
β”‚ β”œβ”€β”€ base.css # Reset, typography, layout grid
β”‚ β”œβ”€β”€ components.css # Cards, badges, buttons, modals, toasts
β”‚ β”œβ”€β”€ upload.css # Drop zone, preview, scan overlay
β”‚ β”œβ”€β”€ results.css # Verdict, heatmaps, metrics, evidence
β”‚ └── responsive.css # Media queries (900px, 768px, 600px, 480px)
β”‚
└── js/
β”œβ”€β”€ upload.js # File handling, drag-drop, preview rendering
β”œβ”€β”€ analysis.js # API call, progress tracking, result rendering
β”œβ”€β”€ heatmap-viewer.js # Interactive heatmap overlay slider
β”œβ”€β”€ audio-viewer.js # Audio waveform + spectrogram canvas
β”œβ”€β”€ video-timeline.js # Video frame scrubber with risk bars
β”œβ”€β”€ export.js # PDF/JSON report generation
β”œβ”€β”€ settings.js # Profile, username, opt-in toggles
└── utils.js # Toast system, metric scaling, helpers
```
> [!IMPORTANT]
> The HTML goes from **2,029 lines β†’ ~300 lines**. Each JS/CSS file has a single responsibility.
---
### 2. Fix Video Preview Bug
**Current**: `FileReader.readAsDataURL` feeds into `<img>` tag β†’ broken for video.
**Fix**: Detect media type from file, dynamically create `<video>` or `<img>`:
```javascript
// upload.js
if (file.type.startsWith('video/')) {
const videoEl = document.createElement('video');
videoEl.src = URL.createObjectURL(file);
videoEl.muted = true;
videoEl.autoplay = true;
videoEl.loop = true;
previewContainer.replaceChild(videoEl, previewImg);
} else if (file.type.startsWith('audio/')) {
// Show audio waveform preview (Web Audio API)
} else {
previewImg.src = URL.createObjectURL(file);
}
```
---
### 3. Replace Fake Delay with Real Progress Tracking
**Current**: 6 hardcoded `setTimeout` stages (total 5.1s) regardless of actual backend speed.
**Fix**: Use **Server-Sent Events (SSE)** or a simple polling approach. But since the backend is a single POST request, we'll do this:
- Show a **single clean progress indicator** (not 6 fake stages)
- Start a real timer showing actual elapsed time
- Display the result **immediately** when the backend responds
- If the backend takes >2 seconds, show a pulsing "Analyzing..." state with the real elapsed time
```javascript
// analysis.js
const startTime = performance.now();
const timerInterval = setInterval(() => {
elapsed.textContent = ((performance.now() - startTime) / 1000).toFixed(1) + 's';
}, 100);
const response = await fetch('/api/predict', { ... });
clearInterval(timerInterval);
renderResults(await response.json()); // Instant β€” no fake delay
```
---
### 4. Redesign Results Layout β€” Progressive Disclosure
**Current**: 11 cards stacked vertically β€” overwhelming scroll wall.
**New layout**: **3-tier progressive disclosure**
```
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ TIER 1: VERDICT (always visible) β”‚
β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
β”‚ β”‚ DEEPFAKE DETECTED 97% HIGH RISK β”‚ β”‚
β”‚ β”‚ Evidence: "Primary ViT: 96.5% fake probability" β”‚ β”‚
β”‚ β”‚ [Download Report] [Share] [Analyze Another] β”‚ β”‚
β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ TIER 2: VISUAL EVIDENCE (expandable, open by default) β”‚
β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
β”‚ β”‚ Original β”‚ β”‚ Aligned β”‚ β”‚ Heatmap β”‚ β”‚
β”‚ β”‚ Preview β”‚ β”‚ Face Crop β”‚ β”‚ Overlay β”‚ β”‚
β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ [Slider] β”‚ β”‚
β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
β”‚ β”‚
β”‚ Confidence Breakdown (animated bars) β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ TIER 3: DEEP FORENSICS (collapsed by default, expandable) β”‚
β”‚ β”‚
β”‚ β–Έ Ensemble Model Breakdown β”‚
β”‚ β–Έ Metadata & Provenance Analysis β”‚
β”‚ β–Έ 9 Forensic Metrics β”‚
β”‚ β–Έ Audio Analysis (only if audio exists) β”‚
β”‚ β–Έ Temporal / Video Analysis (only if video) β”‚
β”‚ β–Έ Processing Performance Stats β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
```
- **Tier 1** answers "is it fake?" in 1 second of reading
- **Tier 2** shows visual proof β€” the heatmaps and confidence bars
- **Tier 3** is for deep investigation β€” collapsed by default, click to expand any section
---
### 5. Interactive Heatmap Overlay Slider
**Current**: Static images in tabs (ELA, Frequency, Attention).
**New**: A **before/after slider** that lets users drag to compare original vs heatmap:
```
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Original ◄═══β•ͺ═══► ELA β”‚
β”‚ drag slider β”‚
β”‚ [ELA] [FFT] [Attention] β”‚
β”‚ Opacity: β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–‘β–‘ 80% β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
```
- **Drag slider** reveals original on left, heatmap on right
- **Opacity control** lets user blend heatmap over original
- **Tab switching** swaps between ELA / FFT / Attention
- Pure CSS + JS β€” no library needed (CSS `clip-path` on drag)
---
### 6. Forensic Report Export
Add export capabilities β€” critical for a real forensic tool:
#### A. JSON Download
```javascript
// export.js
function downloadJSON(data) {
const blob = new Blob([JSON.stringify(data, null, 2)], { type: 'application/json' });
const url = URL.createObjectURL(blob);
// trigger download: AEGIS_Report_2026-08-18_142305.json
}
```
#### B. PDF Report (client-side via html2canvas + jsPDF)
```
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ AEGIS-AI FORENSIC ANALYSIS REPORT β”‚
β”‚ Date: 2026-08-18 14:23:05 IST β”‚
β”‚ File: suspicious_image.jpg β”‚
β”‚ SHA-256: a3f2b1c9... β”‚
β”‚ β”‚
β”‚ VERDICT: DEEPFAKE DETECTED (97%) β”‚
β”‚ Risk Level: HIGH β”‚
β”‚ β”‚
β”‚ Evidence Summary: β”‚
β”‚ β€’ Primary ViT: 96.5% fake β”‚
β”‚ β€’ Metadata: Midjourney signature β”‚
β”‚ β”‚
β”‚ [Heatmap images embedded] β”‚
β”‚ [Confidence breakdown chart] β”‚
β”‚ [9 forensic metrics table] β”‚
β”‚ β”‚
β”‚ Generated by AEGIS-AI v4 β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
```
#### C. Share Link (copy to clipboard)
- Encode verdict + score into a shareable URL hash
- Not the full report β€” just a summary card
---
### 7. Audio Waveform & Spectrogram Visualizer
**Current**: Plain text showing "Audio Verdict: FAKE, Confidence: 88.5%".
**New**: Interactive audio player with visual waveform:
```
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ πŸ”Š Audio Analysis β”‚
β”‚ β”‚
β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
β”‚ β”‚ β–β–‚β–ƒβ–…β–‡β–ˆβ–‡β–…β–ƒβ–‚β–β–‚β–ƒβ–…β–‡β–ˆβ–‡β–…β–ƒβ–‚β–β–‚β–ƒβ–…β–‡ β”‚ β”‚
β”‚ β”‚ ◄━━━━━━━━━━━━━━━━━━━━━━━━━━► β”‚ β”‚
β”‚ β”‚ 0:00 0:05 β”‚ β”‚
β”‚ β”‚ [β–Ά Play] [Pause] β”‚ β”‚
β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
β”‚ β”‚
β”‚ Verdict: SYNTHETIC VOICE DETECTED β”‚
β”‚ Confidence: 88.5% β”‚
β”‚ Segments Analyzed: 3 β”‚
β”‚ Synthetic segments highlighted in red ━━ β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
```
- Uses **Web Audio API** + `<canvas>` for waveform rendering
- Color-coded segments: green (real) vs red (synthetic)
- Requires backend to return the extracted audio file path (already does via `ffmpeg`)
---
### 8. Video Timeline Scrubber
**Current**: Video results show aggregate stats only β€” no per-frame view.
**New**: Color-coded timeline bar showing per-frame risk:
```
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ 🎬 Video Temporal Analysis β”‚
β”‚ β”‚
β”‚ Frame Risk Timeline: β”‚
β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
β”‚ β”‚ β–ˆβ–ˆβ–‘β–‘β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–‘β–‘β–‘β–‘β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–‘β–‘β–‘β–‘β–‘β–‘β–ˆβ–ˆβ–ˆβ–ˆ β”‚ β”‚
β”‚ β”‚ β–² green=real red=fake β”‚ β”‚
β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
β”‚ Frame 7/12 | Fake Prob: 92.4% β”‚
β”‚ β”‚
β”‚ Identity Tracking: β”‚
β”‚ β”Œβ”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
β”‚ β”‚ ID β”‚ Frames β”‚ Prob β”‚ Verdict β”‚ β”‚
β”‚ β”œβ”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ β”‚
β”‚ β”‚ 1 β”‚ 10 β”‚ 92% β”‚ FAKE β”‚ β”‚
β”‚ β””β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
```
- Clickable timeline bar β€” click any segment to jump to that frame's analysis
- Color gradient from green (real) to red (fake) per frame
- Uses existing `temporal_analysis.identities` data from API
---
### 9. Visual Polish & Micro-Interactions
| Change | Detail |
|---|---|
| **Remove XGBoost badge** | Replace with `MSCVN Engine` or just `v4` when new model ships |
| **Smooth card transitions** | Cards slide in with staggered `animation-delay` on result load |
| **Skeleton loading states** | Show grey pulsing placeholder cards while waiting for results |
| **Verdict animation** | Score counts up from 0% to final value (CSS counter animation) |
| **Tooltip cleanup** | Standardize all 9 metric tooltips with consistent formatting |
| **Scroll-to-verdict** | Auto-scroll right panel to verdict banner when results arrive |
| **Keyboard shortcuts** | `Ctrl+U` = upload, `Ctrl+E` = export, `Escape` = discard |
| **File size limit indicator** | Show max upload size and file type icons in drop zone |
---
### 10. Updated Nav Branding
```
Before: πŸ” AEGIS-AI [XGBoost Fusion]
After: πŸ›‘οΈ AEGIS-AI [Forensic Engine v4]
```
- Update badge text to reflect current/new engine
- Keep the admin link and operator pill unchanged
---
## Files Changed
| File | Action | Description |
|---|---|---|
| `templates/index.html` | **REWRITE** | Strip down to ~300 lines of clean HTML structure |
| `static/css/variables.css` | **NEW** | CSS custom properties |
| `static/css/base.css` | **NEW** | Reset, typography, grid layout |
| `static/css/components.css` | **NEW** | Cards, badges, buttons, modals |
| `static/css/upload.css` | **NEW** | Drop zone, preview states |
| `static/css/results.css` | **NEW** | Verdict, heatmaps, metrics, evidence |
| `static/css/responsive.css` | **NEW** | Mobile breakpoints |
| `static/js/upload.js` | **NEW** | File handling, drag-drop, preview |
| `static/js/analysis.js` | **NEW** | API call, real progress, result rendering |
| `static/js/heatmap-viewer.js` | **NEW** | Interactive overlay slider |
| `static/js/audio-viewer.js` | **NEW** | Waveform + spectrogram canvas |
| `static/js/video-timeline.js` | **NEW** | Timeline scrubber with risk bars |
| `static/js/export.js` | **NEW** | PDF + JSON report generation |
| `static/js/settings.js` | **NEW** | Profile modal logic |
| `static/js/utils.js` | **NEW** | Toasts, metric scaling, helpers |
| `static/css/main.css` | **DELETE** | Orphaned file, never linked |
| `templates/login.html` | **MINOR** | Link to new CSS variables for consistency |
| `templates/admin.html` | **MINOR** | Link to new CSS variables for consistency |
| `app.py` | **NO CHANGE** | Zero backend changes |
| `core/*` | **NO CHANGE** | Zero detection engine changes |
---
## What This Does NOT Change
- ❌ No changes to `app.py` routes or API contract
- ❌ No changes to `core/` detection modules
- ❌ No changes to the model or inference pipeline
- ❌ No changes to database schema or auth flow
- ❌ No changes to `Dockerfile` or `requirements.txt`
---
## Build Order
### Step 1 β€” Extract & Modularize (Foundation)
- [ ] Create CSS files from inline styles in `index.html`
- [ ] Create JS files from inline scripts
- [ ] Rewrite `index.html` as clean HTML linking external CSS/JS
- [ ] Verify everything renders identically to current state
### Step 2 β€” Fix Critical Bugs
- [ ] Fix video preview (use `<video>` element for video files)
- [ ] Remove fake scanning delay β€” show real elapsed time
- [ ] Fix orphaned `main.css` (delete it)
### Step 3 β€” Results Layout Redesign
- [ ] Implement 3-tier progressive disclosure layout
- [ ] Add collapsible accordion sections for Tier 3
- [ ] Smooth card entrance animations
- [ ] Skeleton loading states
- [ ] Score count-up animation
### Step 4 β€” Interactive Heatmap Viewer
- [ ] Build before/after drag slider component
- [ ] Add opacity blend control
- [ ] Tab switching between ELA / FFT / Attention
### Step 5 β€” Export & Reporting
- [ ] JSON download button
- [ ] PDF report generation (html2canvas + jsPDF)
- [ ] Copy-to-clipboard share summary
### Step 6 β€” Audio & Video Enhancements
- [ ] Audio waveform canvas renderer (Web Audio API)
- [ ] Color-coded synthetic segment highlighting
- [ ] Video timeline scrubber with per-frame risk bars
- [ ] Clickable frame selection
### Step 7 β€” Polish & Ship
- [ ] Update nav branding
- [ ] Keyboard shortcuts
- [ ] Final responsive testing (mobile, tablet, desktop)
- [ ] Cross-browser testing (Chrome, Firefox, Edge)
- [ ] Push to GitHub β†’ Deploy to HF Spaces
---
## Verification Plan
### Visual Testing
- Upload a known real image β†’ verify REAL verdict renders correctly with green theme
- Upload a known fake image β†’ verify FAKE verdict renders with red theme + all heatmaps
- Upload a video β†’ verify video preview, temporal timeline, identity table
- Upload an audio file β†’ verify waveform visualization renders
- Test on mobile viewport (Chrome DevTools responsive mode)
### Functional Testing
- Heatmap slider: drag left/right, verify clip-path updates smoothly
- Export JSON: download and verify JSON matches API response
- Export PDF: generate and verify all sections render in PDF
- Collapsible sections: expand/collapse each Tier 3 section
- Keyboard shortcuts: `Ctrl+U`, `Ctrl+E`, `Escape`
### Regression Testing
- Verify `/api/predict` response is consumed correctly (no JSON key mismatches)
- Verify login/logout flow unchanged
- Verify admin panel unchanged
- Verify settings modal (username change, opt-in toggle) works