{# Narrative Report theme — Theme C root layout (QA-020). Stripe Press / Linear-changelog vibe but INTERACTIVE. Headline-then-evidence flow with collapsible
sections and inline radar / bar charts. Light theme by default; flips via `prefers-color-scheme: dark`. The 21 data-live SSE keys from the Editorial baseline are mirrored on equivalent nodes so /scans//live patches Narrative identically. This template is self-contained (does NOT extend base.html) so the editorial serif chrome stays scoped to .nr-*. Sections (in order): 1. Topbar (brand + scan-id pill + theme switcher + locality) 2. Body grid: sticky TOC | main column 3. Main column: a. Headline (eyebrow + italic serif headline + byline + lede) b. Overview tile strip (score / findings / asi / duration) c. Reconnaissance + ASI breakdown (radar chart inline) d. Attack timeline (severity bar chart inline) e. Findings (one card per finding, evidence trail nested) f. Reproducibility receipt + footnotes 4. Footer (version + license + locality reminder) The shared view-model feeds every section — see dashboard_view.py for the full payload contract. Theme-only fields (`active_theme`, `theme_choices`) are enriched by the route handler. Chart.js v4 is loaded from CDN with `defer` so the partials can include nodes that narrative_charts.js reads on DOMContentLoaded. #} {{ page_title }} · Narrative Report · AgentGuardian {# Chart.js v4 — plain script include, no bundler step. narrative_charts.js reads window.Chart on DOMContentLoaded. Both are defer-loaded so the DOM is parsed before the chart initialisers run. #} Skip to report {# ============== TOPBAR ============== #} {# ============== SHELL (TOC + main column) ============== #}
{% include "dashboard/narrative/_headline.html" %}

Overview

At-a-glance picture of the scan's footprint. Every number below is a deep-link into the section that explains it.

Score
{{ aivss_label }}
{{ band_label }}
Findings
{{ findings_total }}
{{ counts.critical | default(0) }} critical, {{ counts.high | default(0) }} high
ASI covered
{{ asi_covered }} / 10
categories exercised
Duration
{{ elapsed_label }}
{{ usd_label }}
{% include "dashboard/narrative/_section_recon.html" %} {% include "dashboard/narrative/_section_attacks.html" %} {% include "dashboard/narrative/_section_findings.html" %} {% include "dashboard/narrative/_section_reproducibility.html" %}
{# ============== FOOTER ============== #}
AgentGuardian v{{ version }} Apache-2.0 {{ locality_label }}
{# Hidden mirror — surfaces every Editorial data-live key that isn't otherwise visible in the Narrative chrome, so the existing /scans//live SSE patcher keeps all 21 keys in sync without theme-specific code paths. The visible nodes above carry their own data-live attributes. #} {# Live SSE patcher — same shape as Editorial, just scoped to Narrative selectors. Subscribes to /scans//live and mutates data-live nodes in place. Stops on the scan_done event or when the scan is terminal. #}