Claude Skill

visual-explainer

Generate beautiful, self-contained HTML pages that visually explain systems, code changes, plans, and data. Use when the user asks for a diagram, architecture overview, diff review, plan review, project recap, comparison table, or any visual explanation of technical concepts. Als

LLM Mart · 0 points · 0 views 0 listing impressions 0 install-command copies
Virus-scanned Reviewed automatically before listing.

Full trust report

Download szoloth-skill-pack-skills_visual-explainer-7427c15.zip · 1203 KB
Part of szoloth/skill-pack — 19 skills

Install

skills CLI npx skills add https://github.com/SZoloth/skill-pack/tree/main/skills/visual-explainer
Claude Code claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install szoloth-skill-pack@llmmart
Git git clone https://github.com/SZoloth/skill-pack.git

The skills CLI installs just this skill, for any of its supported agents. Claude Code installs the whole szoloth/skill-pack collection as a plugin from our marketplace. Git is the plain clone.

README

visual-explainer

visual-explainer

An agent skill that turns complex terminal output into styled HTML pages you actually want to read.

License: MIT

Ask your agent to explain a system architecture, review a diff, or compare requirements against a plan. Instead of ASCII art and box-drawing tables, it generates a self-contained HTML page and opens it in your browser:

> draw a diagram of our authentication flow
> /diff-review
> /plan-review ~/docs/refactor-plan.md

Each one produces a single .html file with real typography, dark/light theme support, and interactive Mermaid diagrams with zoom and pan. No build step, no dependencies beyond a browser.

https://github.com/user-attachments/assets/55ebc81b-8732-40f6-a4b1-7c3781aa96ec

Why

Every coding agent defaults to ASCII art when you ask for a diagram. Box-drawing characters, monospace alignment hacks, text arrows. It works for trivial cases, but anything beyond a 3-box flowchart turns into an unreadable mess that nobody would put in a presentation or share with a team.

Tables are worse. Ask the agent to compare 15 requirements against a plan and you get a wall of pipes and dashes that wraps and breaks in the terminal. The data is there but it's painful to read.

Install

The skill follows the Agent Skills specification. Clone it into your agent's skills directory:

# Pi
git clone https://github.com/nicobailon/visual-explainer.git ~/.pi/agent/skills/visual-explainer

# Claude Code
git clone https://github.com/nicobailon/visual-explainer.git ~/.claude/skills/visual-explainer

# Other agents — point at the directory containing SKILL.md,
# or paste its contents into your system prompt

For Pi, restart after cloning. To get the slash commands (/diff-review, /plan-review, etc.), copy the prompt templates:

cp ~/.pi/agent/skills/visual-explainer/prompts/*.md ~/.pi/agent/prompts/

If you have surf-cli installed, the skill can also generate illustrations via Gemini Nano Banana Pro and embed them in pages. The agent detects surf automatically and skips image generation if it's not there.

Usage

The agent loads the skill when you mention diagrams, architecture, flowcharts, schemas, or visualizations. It also kicks in automatically when it's about to dump a complex table in the terminal (4+ rows or 3+ columns) — it renders HTML instead and opens it in the browser. Output goes to ~/.agent/diagrams/.

The skill ships with five prompt templates:

Command What it does
/generate-web-diagram Generate an HTML diagram for any topic
/diff-review Visual diff review with architecture comparison, code review, decision log
/plan-review Compare a plan against the codebase with risk assessment
/project-recap Mental model snapshot for context-switching back to a project
/fact-check Verify accuracy of a review page or plan doc against actual code

/diff-review is probably the most useful. Run it with no arguments to diff against main, or pass any git ref:

/diff-review                   # feature branch vs main (default)
/diff-review abc123            # single commit
/diff-review main..HEAD        # committed changes only
/diff-review #42               # pull request

It generates a full page with before/after architecture diagrams, KPI dashboard, structured Good/Bad/Ugly code review, decision log with confidence indicators, and re-entry context for your future self.

/plan-review does something similar but for implementation plans — pass it a plan file and it cross-references every claim against the actual codebase, produces current vs. planned architecture diagrams, and flags risks and gaps:

/plan-review ~/docs/refactor-plan.md

/project-recap is designed for context-switching back to a project after days away. It scans recent git activity and produces an architecture snapshot, decision log, and cognitive debt hotspots. /fact-check takes any document that makes claims about code and verifies every one of them.

How It Works

SKILL.md (workflow + design principles)
    ↓
references/           ← agent reads before each generation
├── css-patterns.md   (layouts, animations, theming, depth tiers)
├── libraries.md      (Mermaid theming, Chart.js, anime.js, font pairings)
└── responsive-nav.md (sticky sidebar TOC for multi-section pages)
    ↓
templates/            ← agent reads the matching reference template
├── architecture.html (CSS Grid cards — terracotta/sage palette)
├── mermaid-flowchart.html (Mermaid + ELK + handDrawn — teal/cyan palette)
└── data-table.html   (tables with KPIs and badges — rose/cranberry palette)
    ↓
~/.agent/diagrams/filename.html → opens in browser

The agent picks an aesthetic direction, reads the right reference template, generates a self-contained HTML file with both light and dark themes, and opens it. The three templates use deliberately different palettes so the agent learns variety rather than defaulting to one look. The skill handles 11 diagram types — Mermaid for anything with connections (flowcharts, sequences, ER, state machines, mind maps), CSS Grid for text-heavy architecture overviews, HTML tables for data, Chart.js for dashboards — and routes to the right approach automatically.

To customize the output directory, browser command, or add your own diagram types and CSS patterns, edit the files directly. The agent reads them fresh each time.

Limitations

  • Requires a browser to view — no inline terminal rendering
  • Switching OS theme requires a page refresh for Mermaid SVGs (CSS-styled elements respond instantly)
  • Results vary by model capability — the skill provides design guidance, not pixel-perfect specs

Credits

Borrows ideas from Anthropic's frontend-design skill and interface-design, adapted for one-shot diagram generation.

License

MIT

Skill manifest

Visual Explainer

Generate self-contained HTML files for technical diagrams, visualizations, and data tables. Always open the result in the browser. Never fall back to ASCII art when this skill is loaded.

Proactive table rendering. When you're about to present tabular data as an ASCII box-drawing table in the terminal (comparisons, audits, feature matrices, status reports, any structured rows/columns), generate an HTML page instead. The threshold: if the table has 4+ rows or 3+ columns, it belongs in the browser. Don't wait for the user to ask — render it as HTML automatically and tell them the file path. You can still include a brief text summary in the chat, but the table itself should be the HTML page.

Workflow

1. Think (5 seconds, not 5 minutes)

Before writing HTML, commit to a direction. Don't default to "dark theme with blue accents" every time.

Who is looking? A developer understanding a system? A PM seeing the big picture? A team reviewing a proposal? This shapes information density and visual complexity.

What type of diagram? Architecture, flowchart, sequence, data flow, schema/ER, state machine, mind map, data table, timeline, or dashboard. Each has distinct layout needs and rendering approaches (see Diagram Types below).

What aesthetic? Pick one and commit:

  • Monochrome terminal (green/amber on black, monospace everything)
  • Editorial (serif headlines, generous whitespace, muted palette)
  • Blueprint (technical drawing feel, grid lines, precise)
  • Neon dashboard (saturated accents on deep dark, glowing edges)
  • Paper/ink (warm cream background, hand-drawn feel, sketchy borders)
  • Hand-drawn / sketch (Mermaid handDrawn mode, wiggly lines, informal whiteboard feel)
  • IDE-inspired (borrow a real color scheme: Dracula, Nord, Catppuccin, Solarized, Gruvbox, One Dark)
  • Data-dense (small type, tight spacing, maximum information)
  • Gradient mesh (bold gradients, glassmorphism, modern SaaS feel)

Vary the choice each time. If the last diagram was dark and technical, make the next one light and editorial. The swap test: if you replaced your styling with a generic dark theme and nobody would notice the difference, you haven't designed anything.

2. Structure

Read the reference template before generating. Don't memorize it — read it each time to absorb the patterns.

  • For text-heavy architecture overviews (card content matters more than topology): read ./templates/architecture.html
  • For flowcharts, sequence diagrams, ER, state machines, mind maps: read ./templates/mermaid-flowchart.html
  • For data tables, comparisons, audits, feature matrices: read ./templates/data-table.html

For CSS/layout patterns and SVG connectors, read ./references/css-patterns.md.

For pages with 4+ sections (reviews, recaps, dashboards), also read ./references/responsive-nav.md for section navigation with sticky sidebar TOC on desktop and horizontal scrollable bar on mobile.

Choosing a rendering approach:

Diagram type Approach Why
Architecture (text-heavy) CSS Grid cards + flow arrows Rich card content (descriptions, code, tool lists) needs CSS control
Architecture (topology-focused) Mermaid Visible connections between components need automatic edge routing
Flowchart / pipeline Mermaid Automatic node positioning and edge routing; hand-drawn mode available
Sequence diagram Mermaid Lifelines, messages, and activation boxes need automatic layout
Data flow Mermaid with edge labels Connections and data descriptions need automatic edge routing
ER / schema diagram Mermaid Relationship lines between many entities need auto-routing
State machine Mermaid State transitions with labeled edges need automatic layout
Mind map Mermaid Hierarchical branching needs automatic positioning
Data table HTML <table> Semantic markup, accessibility, copy-paste behavior
Timeline CSS (central line + cards) Simple linear layout doesn't need a layout engine
Dashboard CSS Grid + Chart.js Card grid with embedded charts

Mermaid theming: Always use theme: 'base' with custom themeVariables so colors match your page palette. Use look: 'handDrawn' for sketch aesthetic or look: 'classic' for clean lines. Use layout: 'elk' for complex graphs (requires the @mermaid-js/layout-elk package — see ./references/libraries.md for the CDN import). Override Mermaid's SVG classes with CSS for pixel-perfect control. See ./references/libraries.md for full theming guide.

Mermaid zoom controls: Always add zoom controls (+/−/reset buttons) to every .mermaid-wrap container. Complex diagrams render at small sizes and need zoom to be readable. Include Ctrl/Cmd+scroll zoom on the container. See the zoom controls pattern in ./references/css-patterns.md and the reference template at ./templates/mermaid-flowchart.html.

AI-generated illustrations (optional). If surf-cli is available, you can generate images via Gemini and embed them in the page for creative, illustrative, explanatory, educational, or decorative purposes. Check availability with which surf. If available:

# Generate to a temp file (use --aspect-ratio for control)
surf gemini "descriptive prompt" --generate-image /tmp/ve-img.png --aspect-ratio 16:9

# Base64 encode for self-containment (macOS)
IMG=$(base64 -i /tmp/ve-img.png)
# Linux: IMG=$(base64 -w 0 /tmp/ve-img.png)

# Embed in HTML and clean up
# <img src="data:image/png;base64,${IMG}" alt="descriptive alt text">
rm /tmp/ve-img.png

See ./references/css-patterns.md for image container styles (hero banners, inline illustrations, captions).

When to use: Hero banners that establish the page's visual tone. Conceptual illustrations for abstract systems that Mermaid can't express (physical infrastructure, user journeys, mental models). Educational diagrams that benefit from artistic or photorealistic rendering. Decorative accents that reinforce the aesthetic.

When to skip: Anything Mermaid or CSS handles well. Generic decoration that doesn't convey meaning. Data-heavy pages where images would distract. Always degrade gracefully — if surf isn't available, skip images without erroring. The page should stand on its own with CSS and typography alone.

Prompt craft: Match the image to the page's palette and aesthetic direction. Specify the style (3D render, technical illustration, watercolor, isometric, flat vector, etc.) and mention dominant colors from your CSS variables. Use --aspect-ratio 16:9 for hero banners, --aspect-ratio 1:1 for inline illustrations. Keep prompts specific — "isometric illustration of a message queue with cyan nodes on dark navy background" beats "a diagram of a queue."

3. Style

Apply these principles to every diagram:

Typography is the diagram. Pick a distinctive font pairing from Google Fonts. A display/heading font with character, plus a mono font for technical labels. Never use Inter, Roboto, Arial, or system-ui as the primary font. Load via <link> in <head>. Include a system font fallback in the font-family stack for offline resilience.

Color tells a story. Use CSS custom properties for the full palette. Define at minimum: --bg, --surface, --border, --text, --text-dim, and 3-5 accent colors. Each accent should have a full and a dim variant (for backgrounds). Name variables semantically when possible (--pipeline-step not --blue-3). Support both themes. Put your primary aesthetic in :root and the alternate in the media query:

/* Light-first (editorial, paper/ink, blueprint): */
:root { /* light values */ }
@media (prefers-color-scheme: dark) { :root { /* dark values */ } }

/* Dark-first (neon, IDE-inspired, terminal): */
:root { /* dark values */ }
@media (prefers-color-scheme: light) { :root { /* light values */ } }

Surfaces whisper, they don't shout. Build depth through subtle lightness shifts (2-4% between levels), not dramatic color changes. Borders should be low-opacity rgba (rgba(255,255,255,0.08) in dark mode, rgba(0,0,0,0.08) in light) — visible when you look, invisible when you don't.

Backgrounds create atmosphere. Don't use flat solid colors for the page background. Subtle gradients, faint grid patterns via CSS, or gentle radial glows behind focal areas. The background should feel like a space, not a void.

Visual weight signals importance. Not every section deserves equal visual treatment. Executive summaries and key metrics should dominate the viewport on load (larger type, more padding, subtle accent-tinted background zone). Reference sections (file maps, dependency lists, decision logs) should be compact and stay out of the way. Use <details>/<summary> for sections that are useful but not primary — the collapsible pattern is in ./references/css-patterns.md.

Surface depth creates hierarchy. Vary card depth to signal what matters. Hero sections get elevated shadows and accent-tinted backgrounds (node--hero pattern). Body content stays flat (default .node). Code blocks and secondary content feel recessed (node--recessed). See the depth tiers in ./references/css-patterns.md. Don't make everything elevated — when everything pops, nothing does.

Animation earns its place. Staggered fade-ins on page load are almost always worth it — they guide the eye through the diagram's hierarchy. Mix animation types by role: fadeUp for cards, fadeScale for KPIs and badges, drawIn for SVG connectors, countUp for hero numbers. Hover transitions on interactive-feeling elements make the diagram feel alive. Always respect prefers-reduced-motion. CSS transitions and keyframes handle most cases. For orchestrated multi-element sequences, anime.js via CDN is available (see ./references/libraries.md).

4. Deliver

Output location: Write to ~/.agent/diagrams/. Use a descriptive filename based on content: modem-architecture.html, pipeline-flow.html, schema-overview.html. The directory persists across sessions.

Open in browser:

  • macOS: open ~/.agent/diagrams/filename.html
  • Linux: xdg-open ~/.agent/diagrams/filename.html

Tell the user the file path so they can re-open or share it.

Diagram Types

Architecture / System Diagrams

Two approaches depending on what matters more:

Text-heavy overviews (card content matters more than connections): CSS Grid with explicit row/column placement. Sections as rounded cards with colored borders and monospace labels. Vertical flow arrows between sections. Nested grids for subsystems. The reference template at ./templates/architecture.html demonstrates this pattern. Use when cards need descriptions, code references, tool lists, or other rich content that Mermaid nodes can't hold.

Topology-focused diagrams (connections matter more than card content): Use Mermaid. A graph TD or graph LR with custom themeVariables produces proper diagrams with automatic edge routing. Use look: 'handDrawn' for informal feel or look: 'classic' for clean lines. Use when the point is showing how components connect rather than describing what each component does in detail.

Flowcharts / Pipelines

Use Mermaid. Automatic node positioning and edge routing produces proper diagrams with connecting lines, decision diamonds, and parallel branches — dramatically better than CSS flexbox with arrow characters. Use graph TD for top-down or graph LR for left-right. Use look: 'handDrawn' for sketch aesthetic. Color-code node types with Mermaid's classDef or rely on themeVariables for automatic styling.

Sequence Diagrams

Use Mermaid. Lifelines, messages, activation boxes, notes, and loops all need automatic layout. Use Mermaid's sequenceDiagram syntax. Style actors and messages via CSS overrides on .actor, .messageText, .activation classes.

Data Flow Diagrams

Use Mermaid. Data flow diagrams emphasize connections over boxes — exactly what Mermaid excels at. Use graph LR or graph TD with edge labels for data descriptions. Thicker, colored edges for primary flows. Source/sink nodes styled differently from transform nodes via Mermaid's classDef.

Schema / ER Diagrams

Use Mermaid. Relationship lines between entities need automatic routing. Use Mermaid's erDiagram syntax with entity attributes. Style via themeVariables and CSS overrides on .er.entityBox and .er.relationshipLine.

State Machines / Decision Trees

Use Mermaid. Use stateDiagram-v2 for states with labeled transitions. Supports nested states, forks, joins, and notes. Use look: 'handDrawn' for informal state diagrams. Decision trees can use graph TD with diamond decision nodes.

stateDiagram-v2 label caveat: Transition labels have a strict parser — colons, parentheses, <br/>, HTML entities, and most special characters cause silent parse failures ("Syntax error in text"). If your labels need any of these (e.g., cancel(), curate: true, multi-line labels), use flowchart LR instead with rounded nodes and quoted edge labels (|"label text"|). Flowcharts handle all special characters and support <br/> for line breaks. Reserve stateDiagram-v2 for simple single-word or plain-text labels.

Mind Maps / Hierarchical Breakdowns

Use Mermaid. Use mindmap syntax for hierarchical branching from a root node. Mermaid handles the radial layout automatically. Style with themeVariables to control node colors at each depth level.

Data Tables / Comparisons / Audits

Use a real <table> element — not CSS Grid pretending to be a table. Tables get accessibility, copy-paste behavior, and column alignment for free. The reference template at ./templates/data-table.html demonstrates all patterns below.

Use proactively. Any time you'd render an ASCII box-drawing table in the terminal, generate an HTML table instead. This includes: requirement audits (request vs plan), feature comparisons, status reports, configuration matrices, test result summaries, dependency lists, permission tables, API endpoint inventories — any structured rows and columns.

Layout patterns:

  • Sticky <thead> so headers stay visible when scrolling long tables
  • Alternating row backgrounds via tr:nth-child(even) (subtle, 2-3% lightness shift)
  • First column optionally sticky for wide tables with horizontal scroll
  • Responsive wrapper with overflow-x: auto for tables wider than the viewport
  • Column width hints via <colgroup> or th widths — let text-heavy columns breathe
  • Row hover highlight for scanability

Status indicators (use styled <span> elements, never emoji):

  • Match/pass/yes: colored dot or checkmark with green background
  • Gap/fail/no: colored dot or cross with red background
  • Partial/warning: amber indicator
  • Neutral/info: dim text or muted badge

Cell content:

  • Wrap long text naturally — don't truncate or force single-line
  • Use <code> for technical references within cells
  • Secondary detail text in <small> with dimmed color
  • Keep numeric columns right-aligned with tabular-nums

Timeline / Roadmap Views

Vertical or horizontal timeline with a central line (CSS pseudo-element). Phase markers as circles on the line. Content cards branching left/right (alternating) or all to one side. Date labels on the line. Color progression from past (muted) to future (vivid).

Dashboard / Metrics Overview

Card grid layout. Hero numbers large and prominent. Sparklines via inline SVG <polyline>. Progress bars via CSS linear-gradient on a div. For real charts (bar, line, pie), use Chart.js via CDN (see ./references/libraries.md). KPI cards with trend indicators (up/down arrows, percentage deltas).

File Structure

Every diagram is a single self-contained .html file. No external assets except CDN links (fonts, optional libraries). Structure:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Descriptive Title</title>
  <link href="https://fonts.googleapis.com/css2?family=...&display=swap" rel="stylesheet">
  <style>
    /* CSS custom properties, theme, layout, components — all inline */
  </style>
</head>
<body>
  <!-- Semantic HTML: sections, headings, lists, tables, inline SVG -->
  <!-- No script needed for static CSS-only diagrams -->
  <!-- Optional: <script> for Mermaid, Chart.js, or anime.js when used -->
</body>
</html>

Quality Checks

Before delivering, verify:

  • The squint test: Blur your eyes. Can you still perceive hierarchy? Are sections visually distinct?
  • The swap test: Would replacing your fonts and colors with a generic dark theme make this indistinguishable from a template? If yes, push the aesthetic further.
  • Both themes: Toggle your OS between light and dark mode. Both should look intentional, not broken.
  • Information completeness: Does the diagram actually convey what the user asked for? Pretty but incomplete is a failure.
  • No overflow: Resize the browser to different widths. No content should clip or escape its container. Every grid and flex child needs min-width: 0. Side-by-side panels need overflow-wrap: break-word. Never use display: flex on <li> for marker characters — it creates anonymous flex items that can't shrink, causing lines with many inline <code> badges to overflow. Use absolute positioning for markers instead. See the Overflow Protection section in ./references/css-patterns.md.
  • Mermaid zoom controls: Every .mermaid-wrap container must have zoom controls (+/−/reset buttons), Ctrl/Cmd+scroll zoom, and click-and-drag panning. Complex diagrams render too small without them. The cursor should change to grab when zoomed in and grabbing while dragging. See ./references/css-patterns.md for the full pattern.
  • File opens cleanly: No console errors, no broken font loads, no layout shifts.
Files (skill-pack)
  • prompts
    • diff-review.md 8.2 KB
      ---
      description: Generate a visual HTML diff review — before/after architecture comparison with code review analysis
      ---
      Load the visual-explainer skill, then generate a comprehensive visual diff review as a self-contained HTML page.
      
      Follow the visual-explainer skill workflow. Read the reference template, CSS patterns, and mermaid theming references before generating. Use a GitHub-diff-inspired aesthetic with red/green before/after panels, but vary fonts and palette from previous diagrams.
      
      **Scope detection** — determine what to diff based on `$1`:
      - Branch name (e.g. `main`, `develop`): working tree vs that branch
      - Commit hash: that specific commit's diff (`git show <hash>`)
      - `HEAD`: uncommitted changes only (`git diff` and `git diff --staged`)
      - PR number (e.g. `#42`): `gh pr diff 42`
      - Range (e.g. `abc123..def456`): diff between two commits
      - No argument: default to `main`
      
      **Data gathering phase** — run these first to understand the full scope:
      - `git diff --stat <ref>` for file-level overview
      - `git diff --name-status <ref> --` for new/modified/deleted files (separate src from tests)
      - Line counts: compare key files between `<ref>` and working tree (`git show <ref>:file | wc -l` vs `wc -l`)
      - New public API surface: grep added lines for exported symbols, public functions, classes, interfaces (adapt the pattern to the project's language — `export`/`function`/`class`/`interface` for TS/JS, `def`/`class` for Python, `func`/`type` for Go, etc.)
      - Feature inventory: grep for new actions, keybindings, config fields, event types on both sides
      - Read all changed files in full — include surrounding code paths needed to validate behavior
      - Check whether `CHANGELOG.md` has an entry for these changes
      - Check whether `README.md` or `docs/*.md` need updates given any new or changed features
      - Reconstruct decision rationale: if this work was done in the current session, mine the conversation for approaches discussed, alternatives rejected, and trade-offs made. Check for progress docs (`~/.agent/memory/{project}/progress.md`, `~/.pi/agent/memory/{project}/progress.md`) or plan files that may contain reasoning. For committed changes, read commit messages and PR descriptions.
      
      **Verification checkpoint** — before generating HTML, produce a structured fact sheet of every claim you will present in the review:
      - Every quantitative figure: line counts, file counts, function counts, test counts
      - Every function, type, and module name you will reference
      - Every behavior description: what code does, what changed, before vs. after
      - For each, cite the source: the git command output that produced it, or the file:line where you read it
      Verify each claim against the code. If something cannot be verified, mark it as uncertain rather than stating it as fact. This fact sheet is your source of truth during HTML generation — do not deviate from it.
      
      **Diagram structure** — the page should include:
      1. **Executive summary** — not just a dry before/after. Lead with the *intuition*: why do these changes exist? What problem were they solving, what was the core insight? Then the factual scope (X files, Y lines, Z new modules). Aim for "aha moment" clarity — a reader who only sees this section should understand the essence of the change. *Visual treatment: this is the visual anchor — use hero depth (larger type 20-24px, subtle accent-tinted background, more padding than other sections).*
      2. **KPI dashboard** — lines added/removed, files changed, new modules, test counts. Include a **housekeeping** indicator: whether CHANGELOG.md was updated (green/red badge) and whether docs need changes (green/yellow/red).
      3. **Module architecture** — how the file structure changed, with a Mermaid dependency graph of the current state. Wrap in `.mermaid-wrap` with zoom controls (+/−/reset buttons), Ctrl/Cmd+scroll zoom, and click-and-drag panning (grab/grabbing cursors). See css-patterns.md "Mermaid Zoom Controls" for the full pattern.
      4. **Major feature comparisons** — side-by-side before/after panels for each significant area of change (UI, data flow, API surface, config, etc.). Overflow prevention: apply `min-width: 0` on all grid/flex children and `overflow-wrap: break-word` on panels. Never use `display: flex` on `<li>` for marker characters — use absolute positioning instead (see css-patterns.md Overflow Protection).
      5. **Flow diagrams** — Mermaid flowchart, sequence, or state diagrams for any new lifecycle/pipeline/interaction patterns. Same zoom controls as section 3.
      6. **File map** — full tree with color-coded new/modified/deleted indicators. *Visual treatment: compact — consider `<details>` collapsed by default for pages with many sections.*
      7. **Test coverage** — before/after test file counts and what's covered
      8. **Code review** — structured Good/Bad/Ugly analysis of the changes:
         - **Good**: Solid choices, improvements, clean patterns worth calling out
         - **Bad**: Concrete issues — bugs, regressions, missing error handling, logic errors
         - **Ugly**: Subtle problems — tech debt introduced, maintainability concerns, things that work now but will bite later
         - **Questions**: Anything unclear or that needs the author's clarification
         - Use styled cards with green/red/amber/blue left-border accents matching the diff color language. Each item should reference specific files and line ranges. If nothing to flag in a category, say "None found" rather than omitting the section.
      9. **Decision log** — for each significant design choice in the diff, a styled card with:
         - **Decision**: one-line summary of what was decided (e.g., "Promise-based deferred resolution instead of event emitters for cleanup signaling")
         - **Rationale**: why this approach — constraints, trade-offs, what it enables. Pull from conversation context if available, infer from code structure if not.
         - **Alternatives considered**: what was rejected and why, if recoverable
         - **Confidence**: whether this rationale was explicitly discussed (high — sourced from conversation/docs) or inferred from the code (medium — flagged as inference). Low confidence means the rationale couldn't be recovered at all.
         - Visual treatment by confidence level — use left-border accent colors consistent with the diff color language: **High** (sourced from conversation/docs): green left border. **Medium** (inferred from code): blue left border, labeled "inferred." **Low** (not recoverable): amber left border, "rationale not recoverable — document before committing" warning. Low-confidence cards are cognitive debt hotspots — tell the user to document the reasoning before committing.
      10. **Re-entry context** — a concise "note from present-you to future-you" covering the following. *Visual treatment: compact — consider `<details>` collapsed by default for pages with many sections.*
         - **Key invariants**: assumptions the changed code relies on that aren't enforced by types or tests (e.g., "cleanup must be called before session switch or artifacts leak")
         - **Non-obvious coupling**: files or behaviors that are connected in ways that aren't visible from imports alone (e.g., "the feed renderer reads events written by the overlay — changing the event schema requires updating both")
         - **Gotchas**: things that would surprise someone modifying this code in two weeks. Edge cases, ordering dependencies, implicit contracts.
         - **Don't forget**: if the changes require follow-up work (migration, config update, docs), list it here.
      
      **Visual hierarchy**: Sections 1-3 should dominate the viewport on load (hero depth, larger type, more padding). Sections 6+ are reference material and should feel lighter (flat or recessed depth, compact layout, collapsible where appropriate).
      
      **Optional illustrations** — if `surf` CLI is available (`which surf`), consider generating a hero banner or conceptual illustration via `surf gemini --generate-image` when it would enhance the page. Embed as base64 data URI. See css-patterns.md "Generated Images" for container styles. Skip if surf isn't available or the diff is purely structural.
      
      Include responsive section navigation. Use diff-style visual language throughout: red for removed/before, green for added/after, yellow for modified, blue for neutral context. Write to `~/.agent/diagrams/` and open in browser.
      
      Ultrathink.
      
      $@
      
    • fact-check.md 4.6 KB
      ---
      description: Verify the factual accuracy of a document against the actual codebase, correct inaccuracies in place
      ---
      Load the visual-explainer skill, then verify the factual accuracy of a document that makes claims about a codebase. Read the file, extract every verifiable claim, check each against the actual code and git history, correct inaccuracies in place, and add a verification summary.
      
      For HTML files: read `./references/css-patterns.md` to match the existing page's styling when inserting the verification summary.
      
      **Target file** — determine what to verify from `$1`:
      - Explicit path: verify that specific file (`.html`, `.md`, or any text document)
      - No argument: verify the most recently modified `.html` file in `~/.agent/diagrams/` (`ls -t ~/.agent/diagrams/*.html | head -1`)
      
      Auto-detect the document type and adjust the verification strategy:
      - **HTML review pages** (diff-review, plan-review, project-recap): detect from page content, verify against the git ref or plan file the review was based on
      - **Plan/spec documents** (markdown): verify file references, function/type names, behavior descriptions, and architecture claims against the current codebase
      - **Any other document**: extract and verify whatever factual claims about code it contains
      
      **Phase 1: Extract claims.** Read the file. Extract every verifiable factual claim:
      - **Quantitative**: line counts, file counts, function counts, module counts, test counts, any numeric metrics
      - **Naming**: function names, type names, module names, file paths referenced in the document
      - **Behavioral**: descriptions of what code does, how things work, before/after comparisons
      - **Structural**: architecture claims, dependency relationships, import chains, module boundaries
      - **Temporal**: git history claims, commit attributions, timeline entries
      
      Skip subjective analysis (opinions, design judgments, readability assessments) — these aren't verifiable facts.
      
      **Phase 2: Verify against source.** For each extracted claim, go to the source:
      - Re-read every file referenced in the document — check function signatures, type definitions, behavior descriptions against the actual code
      - For claims about git history: re-run git commands (`git diff --stat`, `git log`, `git diff --name-status`, etc.) and compare output against the document's numbers
      - For diff-reviews: read both the ref version (`git show <ref>:file`) and working tree version to verify before/after claims aren't swapped or fabricated
      - For plan docs: verify that files, functions, and types the plan references actually exist and behave as described
      - For project-recaps: re-run `git log` commands to verify activity narrative and timeline
      
      Classify each claim:
      - **Confirmed**: claim matches the code/output exactly
      - **Corrected**: claim was inaccurate — note what was wrong and what the correct value is
      - **Unverifiable**: claim can't be checked (e.g., references a file that doesn't exist, or a behavior that requires runtime testing)
      
      **Phase 3: Correct in place.** Edit the file directly using surgical text replacements:
      - Fix incorrect numbers, function names, file paths, behavior descriptions
      - Fix before/after swaps (a common error class in review pages)
      - If a section is fundamentally wrong (not just a detail error), rewrite that section's content while preserving the surrounding structure
      - For HTML: preserve layout, CSS, animations, Mermaid diagrams (unless they contain factual errors in node labels or edge descriptions)
      - For markdown: preserve heading structure, formatting, and document organization
      
      **Phase 4: Add verification summary.**
      - **HTML files**: insert a verification section as a banner at the top or final section, matching the page's existing styling. Use a subtle card with muted colors.
      - **Markdown files**: append a `## Verification Summary` section at the end of the document.
      
      Include in the summary:
      - Total claims checked
      - Claims confirmed (with count)
      - Corrections made (with brief list of what was fixed: "Changed `processCleanup` to `runCleanup` to match actual function name in `worker.ts:45`")
      - Unverifiable claims flagged (if any)
      
      **Phase 5: Report.** Tell the user what was checked, what was corrected, and open the file (HTML in browser, markdown path in chat). If nothing needed correction, say so — the verification still has value as confirmation.
      
      This is not a re-review. It does not second-guess analysis, opinions, or design judgments. It does not change the document's structure or organization. It is a fact-checker — it verifies that the data presented matches reality, corrects what doesn't, and leaves everything else alone.
      
      Write corrections to the original file.
      
      Ultrathink.
      
      $@
      
    • generate-web-diagram.md 913 B
      ---
      description: Generate a beautiful standalone HTML diagram and open it in the browser
      ---
      Load the visual-explainer skill, then generate an HTML diagram for: $@
      
      Follow the visual-explainer skill workflow. Read the reference template and CSS patterns before generating. Pick a distinctive aesthetic that fits the content — vary fonts, palette, and layout style from previous diagrams.
      
      If `surf` CLI is available (`which surf`), consider generating an AI illustration via `surf gemini --generate-image` when an image would genuinely enhance the page — a hero banner, conceptual illustration, or educational diagram that Mermaid can't express. Match the image style to the page's palette. Embed as base64 data URI. See css-patterns.md "Generated Images" for container styles. Skip images when the topic is purely structural or data-driven.
      
      Write to `~/.agent/diagrams/` and open the result in the browser.
      
    • plan-review.md 9 KB
      ---
      description: Generate a visual HTML plan review — current codebase state vs. proposed implementation plan
      ---
      Load the visual-explainer skill, then generate a comprehensive visual plan review as a self-contained HTML page, comparing the current codebase against a proposed implementation plan.
      
      Follow the visual-explainer skill workflow. Read the reference template, CSS patterns, and mermaid theming references before generating. Use a blueprint/editorial aesthetic with current-state vs. planned-state panels, but vary fonts and palette from previous diagrams.
      
      **Inputs:**
      - Plan file: `$1` (path to a markdown plan, spec, or RFC document)
      - Codebase: `$2` if provided, otherwise the current working directory
      
      **Data gathering phase** — read and cross-reference these before generating:
      
      1. **Read the plan file in full.** Extract:
         - The problem statement and motivation
         - Each proposed change (files to modify, new files, deletions)
         - Rejected alternatives and their reasoning
         - Any explicit scope boundaries or non-goals
      
      2. **Read every file the plan references.** For each file mentioned in the plan, read the current version in full. Also read files that import or depend on those files — the plan may not mention all ripple effects.
      
      3. **Map the blast radius.** From the codebase, identify:
         - What imports/requires the files being changed (grep for import paths)
         - What tests exist for the affected files (look for corresponding `.test.*` / `.spec.*` files)
         - Config files, types, or schemas that might need updates
         - Public API surface that callers depend on
      
      4. **Cross-reference plan vs. code.** For each change the plan proposes, verify:
         - Does the file/function/type the plan references actually exist in the current code?
         - Does the plan's description of current behavior match what the code actually does?
         - Are there implicit assumptions about code structure that don't hold?
      
      **Verification checkpoint** — before generating HTML, produce a structured fact sheet of every claim you will present in the review:
      - Every quantitative figure: file counts, estimated lines, function counts, test counts
      - Every function, type, and module name you will reference from both the plan and the codebase
      - Every behavior description: what the code currently does vs. what the plan proposes
      - For each, cite the source: the plan section or the file:line where you read it
      Verify each claim against the code and the plan. If something cannot be verified, mark it as uncertain rather than stating it as fact. This fact sheet is your source of truth during HTML generation — do not deviate from it.
      
      **Diagram structure** — the page should include:
      
      1. **Plan summary** — lead with the *intuition*: what problem does this plan solve, and what's the core insight behind the approach? Then the scope: how many files touched, estimated scale of changes, new modules or tests planned. A reader who only sees this section should understand the plan's essence. *Visual treatment: this is the visual anchor — use hero depth (larger type 20-24px, subtle accent-tinted background, more padding than other sections).*
      
      2. **Impact dashboard** — files to modify, files to create, files to delete, estimated lines added/removed, new test files planned, dependencies affected. Include a **completeness** indicator: whether the plan covers tests (green/red), docs updates (green/yellow/red), and migration/rollback (green/grey for N/A).
      
      3. **Current architecture** — Mermaid diagram of how the affected subsystem works *today*. Focus only on the parts the plan touches — don't diagram the entire codebase. Show the data flow, dependencies, and call paths that will change. Wrap in `.mermaid-wrap` with zoom controls (+/−/reset buttons), Ctrl/Cmd+scroll zoom, and click-and-drag panning (grab/grabbing cursors). See css-patterns.md "Mermaid Zoom Controls" for the full pattern. *Visual treatment: use matching Mermaid layout direction and node names as section 4 so the visual diff is obvious.*
      
      4. **Planned architecture** — Mermaid diagram of how the subsystem will work *after* the plan is implemented. Use the same node names and layout direction as the current architecture diagram so the differences are visually obvious. Same zoom controls as section 3. *Highlight new nodes with a glow or accent border, removed nodes with strikethrough or reduced opacity, changed edges with a different stroke color.*
      
      5. **Change-by-change breakdown** — for each change in the plan, a side-by-side panel. Overflow prevention: apply `min-width: 0` on all grid/flex children and `overflow-wrap: break-word` on panels. Never use `display: flex` on `<li>` for marker characters — use absolute positioning instead (see css-patterns.md Overflow Protection).
         - **Left (current):** what the code does now, with relevant snippets or function signatures
         - **Right (planned):** what the plan proposes, with the plan's own code examples if provided
         - **Rationale:** below each side-by-side panel, extract _why_ the plan chose this approach. Pull from the plan's reasoning, rejected alternatives section, or inline justifications. If the plan includes a "rejected alternatives" section, map those rejections to the specific changes they apply to. Flag changes where the plan says _what_ to do but not _why_ — these are pre-implementation cognitive debt.
         - Flag any discrepancies where the plan's description of current behavior doesn't match the actual code
      
      6. **Dependency & ripple analysis** — *visual treatment: compact — consider `<details>` collapsed by default for pages with many sections.* What other code depends on the files being changed. Table or Mermaid graph showing callers, importers, and downstream effects the plan may not explicitly address. Color-code: covered by plan (green), not mentioned but likely affected (amber), definitely missed (red).
      
      7. **Risk assessment** — styled cards for:
         - **Edge cases** the plan doesn't address
         - **Assumptions** the plan makes about the codebase that should be verified
         - **Ordering risks** if changes need to be applied in a specific sequence
         - **Rollback complexity** if things go wrong
         - **Cognitive complexity** — areas where the plan introduces non-obvious coupling, action-at-a-distance behavior, implicit ordering requirements, or contracts that exist only in the developer's memory. Distinct from bug risk — these are "you'll forget how this works in a month" risks. Each cognitive complexity flag gets a brief mitigation suggestion (e.g., "add a comment explaining the ordering requirement" or "consider a runtime assertion that validates the invariant"). Note: cognitive complexity flags belong here when they're about specific code patterns; broader concerns about the plan's overall approach (overengineering, lock-in, maintenance burden) belong in section 8's Ugly category.
         - Each risk gets a severity indicator (low/medium/high)
      
      8. **Plan review** — structured Good/Bad/Ugly analysis of the plan itself:
         - **Good**: Solid design decisions, things the plan gets right, well-reasoned tradeoffs
         - **Bad**: Gaps in the plan — missing files, unaddressed edge cases, incorrect assumptions about current code
         - **Ugly**: Subtle concerns — complexity being introduced, maintenance burden, things that will work initially but cause problems at scale
         - **Questions**: Ambiguities that need the plan author's clarification before implementation begins
         - Use styled cards with green/red/amber/blue left-border accents. Each item should reference specific plan sections and code files. If nothing to flag in a category, say "None found" rather than omitting the section.
      9. **Understanding gaps** — a closing dashboard that rolls up decision-rationale gaps from section 5 and cognitive complexity flags from section 7:
         - Count of changes with clear rationale vs. missing rationale (visual bar chart or progress indicator)
         - List of cognitive complexity flags with severity
         - Explicit recommendations: "Before implementing, document the rationale for changes X and Y — the plan doesn't explain why these approaches were chosen over alternatives"
         - This section makes cognitive debt visible _before_ the work starts, when it's cheapest to address.
      
      **Visual hierarchy**: Sections 1-4 should dominate the viewport on load (hero depth for summary, elevated for architecture diagrams). Sections 6+ are reference material and should feel lighter (flat or recessed depth, compact layout, collapsible where appropriate).
      
      **Optional illustrations** — if `surf` CLI is available (`which surf`), consider generating a conceptual illustration of the planned system via `surf gemini --generate-image` when it would help the reader visualize the change. Embed as base64 data URI. See css-patterns.md "Generated Images" for container styles. Skip if surf isn't available or the plan is purely structural.
      
      Include responsive section navigation. Use a current-vs-planned visual language throughout: blue/neutral for current state, green/purple for planned additions, amber for areas of concern, red for gaps or risks. Write to `~/.agent/diagrams/` and open in browser.
      
      Ultrathink.
      
      $@
      
    • project-recap.md 7 KB
      ---
      description: Generate a visual HTML project recap — rebuild mental model of a project's current state, recent decisions, and cognitive debt hotspots
      ---
      Load the visual-explainer skill, then generate a comprehensive visual project recap as a self-contained HTML page.
      
      Follow the visual-explainer skill workflow. Read the reference template, CSS patterns, and mermaid theming references before generating. Use a warm editorial or paper/ink aesthetic with muted blues and greens, but vary fonts and palette from previous diagrams.
      
      **Time window** — determine the recency window from `$1`:
      - Shorthand like `2w`, `30d`, `3m`: parse to git's `--since` format (`2w` → `"2 weeks ago"`, `30d` → `"30 days ago"`, `3m` → `"3 months ago"`)
      - If `$1` doesn't match a time pattern, treat it as free-form context and use the default window
      - No argument: default to `2w` (2 weeks)
      
      **Data gathering phase** — run these first to understand the project:
      
      1. **Project identity.** Read `README.md`, `CHANGELOG.md`, `package.json` / `Cargo.toml` / `pyproject.toml` / `go.mod` for name, description, version, dependencies. Read the top-level file structure.
      
      2. **Recent activity.** `git log --oneline --since=<window>` for commit history. `git log --stat --since=<window>` for file-level change scope. `git shortlog -sn --since=<window>` for contributor activity. Identify which areas of the codebase were most active.
      
      3. **Current state.** Check for uncommitted changes (`git status`). Check for stale branches (`git branch --no-merged`). Look for TODO/FIXME comments in recently changed files. Read progress docs if they exist (`~/.agent/memory/{project}/progress.md`, `~/.pi/agent/memory/{project}/progress.md`, `.pi/todos/`, or similar).
      
      4. **Decision context.** Read recent commit messages for rationale. If running in the same session as recent work, mine the conversation history. Read any plan docs, RFCs, or ADRs in the project directory.
      
      5. **Architecture scan.** Read key source files to understand the module structure and dependencies. Focus on entry points, public API surface, and the files most frequently changed in the time window.
      
      **Verification checkpoint** — before generating HTML, produce a structured fact sheet of every claim you will present in the recap:
      - Every quantitative figure: commit counts, file counts, line counts, branch counts
      - Every module, function, and type name you will reference
      - Every behavior and architecture description
      - For each, cite the source: the git command output that produced it, or the file:line where you read it
      Verify each claim against the code. If something cannot be verified, mark it as uncertain rather than stating it as fact. This fact sheet is your source of truth during HTML generation — do not deviate from it.
      
      **Optional hero image** — if `surf` CLI is available (`which surf`), generate a hero banner via `surf gemini --generate-image --aspect-ratio 16:9` that visually captures the project's identity or domain. Match the style to the page's palette. Embed as base64 data URI using the `.hero-img-wrap` pattern from css-patterns.md. Place above or just below the title. Skip if surf isn't available — the page should stand on its own.
      
      **Diagram structure** — the page should include:
      1. **Project identity** — not the README blurb. A *current-state* summary: what this project does, who uses it, what stage it's at (early dev, stable, actively shipping features). Include version, key dependencies, and the one-sentence "elevator pitch" for someone who forgot what they were building.
      2. **Architecture snapshot** — Mermaid diagram of the system as it exists today. Focus on the conceptual modules and their relationships, not every file. Label nodes with what they do, not just file names. Wrap in `.mermaid-wrap` with zoom controls (+/−/reset buttons), Ctrl/Cmd+scroll zoom, and click-and-drag panning (grab/grabbing cursors). See css-patterns.md "Mermaid Zoom Controls" for the full pattern. *Visual treatment: this is the visual anchor — use hero depth (elevated container, larger padding, subtle accent-tinted background). The rest of the page hangs off this diagram.*
      3. **Recent activity** — not raw git log. A human-readable narrative grouped by theme: feature work, bug fixes, refactors, infrastructure. Timeline visualization with the most significant changes called out. For each theme, a one-sentence summary of what happened and why it mattered.
      4. **Decision log** — key design decisions from the time window. Extracted from commit messages, conversation history, plan docs, progress docs. Each entry: what was decided, why, what was considered. This is the highest-value section for fighting cognitive debt — the reasoning that evaporates first.
      5. **State of things** — *visual treatment: use the KPI card pattern from css-patterns.md — large hero numbers for working/broken/blocked/in-progress counts, with color-coded trend indicators.* A dashboard of:
         - What's working (stable, shipped, tested)
         - What's in progress (uncommitted work, open branches, active TODOs)
         - What's broken or degraded (known bugs, failing tests, tech debt items)
         - What's blocked (waiting on external input, dependencies, decisions)
      6. **Mental model essentials** — the 5-10 things you need to hold in your head to work on this project effectively:
         - Key invariants and contracts (what must always be true)
         - Non-obvious coupling (things connected in ways you wouldn't guess from the file tree)
         - Gotchas (common mistakes, easy-to-forget requirements, things that break silently)
         - Naming conventions or patterns the codebase follows
      7. **Cognitive debt hotspots** — *visual treatment: use amber-tinted cards with severity indicators (colored left border: red for high, amber for medium, blue for low).* Areas where understanding is weakest:
         - Code that changed recently but has no documented rationale
         - Complex modules with no tests
         - Areas where multiple people (or agents) made overlapping changes
         - Files that are frequently modified but poorly understood
         - Flag each with a severity and a concrete suggestion (e.g., "add a doc comment to `buildCoordinationInstructions` explaining the 4 coordination levels — this function is called from 3 places and the behavior is non-obvious")
      8. **Next steps** — inferred from recent activity, open TODOs, project trajectory. Not prescriptive — just "here's where the momentum was pointing when you left." Include any explicit next-step notes from progress docs or plan files.
      
      Include responsive section navigation. Use a warm, approachable visual language: muted blues and greens for architecture, amber callouts for cognitive debt hotspots, green/blue/amber/red for state-of-things status. Overflow prevention on any side-by-side or grid-based sections: apply `min-width: 0` on all grid/flex children and `overflow-wrap: break-word`. Never use `display: flex` on `<li>` for marker characters — use absolute positioning instead (see css-patterns.md Overflow Protection). Write to `~/.agent/diagrams/` and open in browser.
      
      Ultrathink.
      
      $@
      
  • references
    • css-patterns.md 27 KB
      # CSS Patterns for Diagrams
      
      Reusable patterns for layout, connectors, theming, and visual effects in self-contained HTML diagrams.
      
      ## Theme Setup
      
      Always define both light and dark palettes via custom properties. Start with whichever fits the chosen aesthetic, ensure both work.
      
      ```css
      :root {
        --font-body: 'Outfit', system-ui, sans-serif;
        --font-mono: 'Space Mono', 'SF Mono', Consolas, monospace;
      
        --bg: #f8f9fa;
        --surface: #ffffff;
        --surface-elevated: #ffffff;
        --border: rgba(0, 0, 0, 0.08);
        --border-bright: rgba(0, 0, 0, 0.15);
        --text: #1a1a2e;
        --text-dim: #6b7280;
        --accent: #0891b2;
        --accent-dim: rgba(8, 145, 178, 0.1);
        /* Semantic accents for diagram elements */
        --node-a: #0891b2;
        --node-a-dim: rgba(8, 145, 178, 0.1);
        --node-b: #059669;
        --node-b-dim: rgba(5, 150, 105, 0.1);
        --node-c: #d97706;
        --node-c-dim: rgba(217, 119, 6, 0.1);
      }
      
      @media (prefers-color-scheme: dark) {
        :root {
          --bg: #0d1117;
          --surface: #161b22;
          --surface-elevated: #1c2333;
          --border: rgba(255, 255, 255, 0.06);
          --border-bright: rgba(255, 255, 255, 0.12);
          --text: #e6edf3;
          --text-dim: #8b949e;
          --accent: #22d3ee;
          --accent-dim: rgba(34, 211, 238, 0.12);
          --node-a: #22d3ee;
          --node-a-dim: rgba(34, 211, 238, 0.12);
          --node-b: #34d399;
          --node-b-dim: rgba(52, 211, 153, 0.12);
          --node-c: #fbbf24;
          --node-c-dim: rgba(251, 191, 36, 0.12);
        }
      }
      ```
      
      ## Background Atmosphere
      
      Flat backgrounds feel dead. Use subtle gradients or patterns.
      
      ```css
      /* Radial glow behind focal area */
      body {
        background: var(--bg);
        background-image: radial-gradient(ellipse at 50% 0%, var(--accent-dim) 0%, transparent 60%);
      }
      
      /* Faint dot grid */
      body {
        background-color: var(--bg);
        background-image: radial-gradient(circle, var(--border) 1px, transparent 1px);
        background-size: 24px 24px;
      }
      
      /* Diagonal subtle lines */
      body {
        background-color: var(--bg);
        background-image: repeating-linear-gradient(
          -45deg, transparent, transparent 40px,
          var(--border) 40px, var(--border) 41px
        );
      }
      
      /* Gradient mesh (pick 2-3 positioned radials) */
      body {
        background: var(--bg);
        background-image:
          radial-gradient(at 20% 20%, var(--node-a-dim) 0%, transparent 50%),
          radial-gradient(at 80% 60%, var(--node-b-dim) 0%, transparent 50%);
      }
      ```
      
      ## Section / Node Cards
      
      The fundamental building block. A colored card representing a system component, pipeline step, or data entity.
      
      ```css
      .node {
        background: var(--surface);
        border: 1px solid var(--border);
        border-radius: 10px;
        padding: 16px 20px;
        position: relative;
      }
      
      /* Colored accent border (left or top) */
      .node--accent-a {
        border-left: 3px solid var(--node-a);
      }
      
      /* --- Depth tiers: vary card depth to signal importance --- */
      
      /* Elevated: KPIs, key sections, anything that should pop */
      .node--elevated {
        background: var(--surface-elevated);
        box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08), 0 1px 2px rgba(0, 0, 0, 0.04);
      }
      
      /* Recessed: code blocks, secondary content, detail panels */
      .node--recessed {
        background: color-mix(in srgb, var(--bg) 70%, var(--surface) 30%);
        box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.06);
        border-color: var(--border);
      }
      
      /* Hero: executive summaries, focal elements — demands attention */
      .node--hero {
        background: color-mix(in srgb, var(--surface) 92%, var(--accent) 8%);
        box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08), 0 1px 3px rgba(0, 0, 0, 0.04);
        border-color: color-mix(in srgb, var(--border) 50%, var(--accent) 50%);
      }
      
      /* Glass: special-occasion overlay effect (use sparingly) */
      .node--glass {
        background: color-mix(in srgb, var(--surface) 60%, transparent 40%);
        backdrop-filter: blur(12px);
        -webkit-backdrop-filter: blur(12px);
        border-color: rgba(255, 255, 255, 0.1);
      }
      
      /* Section label (monospace, uppercase, small) */
      .node__label {
        font-family: var(--font-mono);
        font-size: 10px;
        font-weight: 600;
        text-transform: uppercase;
        letter-spacing: 1.5px;
        color: var(--node-a);
        margin-bottom: 10px;
        display: flex;
        align-items: center;
        gap: 8px;
      }
      
      /* Colored dot indicator */
      .node__label::before {
        content: '';
        width: 8px;
        height: 8px;
        border-radius: 50%;
        background: currentColor;
      }
      ```
      
      ## Overflow Protection
      
      Grid and flex children default to `min-width: auto`, which prevents them from shrinking below their content width. Long text, inline code badges, and non-wrapping elements will blow out containers.
      
      ### Global rules
      
      ```css
      /* Every grid/flex child must be able to shrink */
      .grid > *, .flex > *,
      [style*="display: grid"] > *,
      [style*="display: flex"] > * {
        min-width: 0;
      }
      
      /* Long text wraps instead of overflowing */
      body {
        overflow-wrap: break-word;
      }
      ```
      
      ### Side-by-side comparison panels
      
      ```css
      .comparison {
        display: grid;
        grid-template-columns: 1fr 1fr;
        gap: 16px;
      }
      
      .comparison > * {
        min-width: 0;
        overflow-wrap: break-word;
      }
      
      @media (max-width: 768px) {
        .comparison { grid-template-columns: 1fr; }
      }
      ```
      
      ### Never use `display: flex` on `<li>` for marker characters
      
      Using `display: flex` on a list item to position a `::before` marker creates an anonymous flex item for the remaining text content. That anonymous flex item gets `min-width: auto` and you **cannot** set `min-width: 0` on anonymous boxes. Lines with many inline `<code>` badges will overflow their container with no CSS fix possible.
      
      Use absolute positioning for markers instead:
      
      ```css
      /* WRONG — causes overflow with inline code badges */
      li {
        display: flex;
        align-items: baseline;
        gap: 6px;
      }
      li::before {
        content: '›';
        flex-shrink: 0;
      }
      
      /* RIGHT — text wraps normally */
      li {
        padding-left: 14px;
        position: relative;
      }
      li::before {
        content: '›';
        position: absolute;
        left: 0;
      }
      ```
      
      ## Mermaid Zoom Controls
      
      Mermaid diagrams are often too small to read comfortably, especially complex flowcharts and sequence diagrams. Add zoom controls to every `.mermaid-wrap` container.
      
      ### CSS
      
      ```css
      .mermaid-wrap {
        position: relative;
        background: var(--surface);
        border: 1px solid var(--border);
        border-radius: 12px;
        padding: 32px 24px;
        overflow: auto;
        scrollbar-width: thin;
        scrollbar-color: var(--border) transparent;
      }
      .mermaid-wrap::-webkit-scrollbar { width: 6px; height: 6px; }
      .mermaid-wrap::-webkit-scrollbar-track { background: transparent; }
      .mermaid-wrap::-webkit-scrollbar-thumb { background: var(--border); border-radius: 3px; }
      .mermaid-wrap::-webkit-scrollbar-thumb:hover { background: var(--text-dim); }
      
      .mermaid-wrap .mermaid {
        transition: transform 0.2s ease;
        transform-origin: top center;
      }
      
      .zoom-controls {
        position: absolute;
        top: 8px;
        right: 8px;
        display: flex;
        gap: 2px;
        z-index: 10;
        background: var(--surface);
        border: 1px solid var(--border);
        border-radius: 6px;
        padding: 2px;
      }
      
      .zoom-controls button {
        width: 28px;
        height: 28px;
        border: none;
        background: transparent;
        color: var(--text-dim);
        font-family: var(--font-mono);
        font-size: 14px;
        cursor: pointer;
        border-radius: 4px;
        display: flex;
        align-items: center;
        justify-content: center;
        transition: background 0.15s ease, color 0.15s ease;
      }
      
      .zoom-controls button:hover {
        background: var(--border);
        color: var(--text);
      }
      
      .mermaid-wrap.is-zoomed { cursor: grab; }
      .mermaid-wrap.is-panning { cursor: grabbing; user-select: none; }
      
      @media (prefers-reduced-motion: reduce) {
        .mermaid-wrap .mermaid { transition: none; }
      }
      ```
      
      ### HTML
      
      ```html
      <div class="mermaid-wrap">
        <div class="zoom-controls">
          <button onclick="zoomDiagram(this, 1.2)" title="Zoom in">+</button>
          <button onclick="zoomDiagram(this, 0.8)" title="Zoom out">&minus;</button>
          <button onclick="resetZoom(this)" title="Reset zoom">&#8634;</button>
        </div>
        <pre class="mermaid">
          graph TD
            A --> B
        </pre>
      </div>
      ```
      
      ### JavaScript
      
      Add once at the end of the page. Handles button clicks and scroll-to-zoom on all `.mermaid-wrap` containers:
      
      ```javascript
      function updateZoomState(wrap) {
        var target = wrap.querySelector('.mermaid');
        var zoom = parseFloat(target.dataset.zoom || '1');
        wrap.classList.toggle('is-zoomed', zoom > 1);
      }
      
      function zoomDiagram(btn, factor) {
        var wrap = btn.closest('.mermaid-wrap');
        var target = wrap.querySelector('.mermaid');
        var current = parseFloat(target.dataset.zoom || '1');
        var next = Math.min(Math.max(current * factor, 0.3), 5);
        target.dataset.zoom = next;
        target.style.transform = 'scale(' + next + ')';
        updateZoomState(wrap);
      }
      
      function resetZoom(btn) {
        var wrap = btn.closest('.mermaid-wrap');
        var target = wrap.querySelector('.mermaid');
        target.dataset.zoom = '1';
        target.style.transform = 'scale(1)';
        updateZoomState(wrap);
      }
      
      document.querySelectorAll('.mermaid-wrap').forEach(function(wrap) {
        // Ctrl/Cmd + scroll to zoom
        wrap.addEventListener('wheel', function(e) {
          if (!e.ctrlKey && !e.metaKey) return;
          e.preventDefault();
          var target = wrap.querySelector('.mermaid');
          var current = parseFloat(target.dataset.zoom || '1');
          var factor = e.deltaY < 0 ? 1.1 : 0.9;
          var next = Math.min(Math.max(current * factor, 0.3), 5);
          target.dataset.zoom = next;
          target.style.transform = 'scale(' + next + ')';
          updateZoomState(wrap);
        }, { passive: false });
      
        // Click-and-drag to pan when zoomed
        var startX, startY, scrollL, scrollT;
        wrap.addEventListener('mousedown', function(e) {
          if (e.target.closest('.zoom-controls')) return;
          var target = wrap.querySelector('.mermaid');
          if (parseFloat(target.dataset.zoom || '1') <= 1) return;
          wrap.classList.add('is-panning');
          startX = e.clientX;
          startY = e.clientY;
          scrollL = wrap.scrollLeft;
          scrollT = wrap.scrollTop;
        });
        window.addEventListener('mousemove', function(e) {
          if (!wrap.classList.contains('is-panning')) return;
          wrap.scrollLeft = scrollL - (e.clientX - startX);
          wrap.scrollTop = scrollT - (e.clientY - startY);
        });
        window.addEventListener('mouseup', function() {
          wrap.classList.remove('is-panning');
        });
      });
      ```
      
      Scroll-to-zoom requires Ctrl/Cmd+scroll to avoid hijacking normal page scroll. Click-and-drag panning activates only when zoomed in (zoom > 1). Cursor changes to `grab`/`grabbing` to signal the behavior. The zoom range is capped at 0.3x–5x.
      
      ## Grid Layouts
      
      ### Architecture Diagram (2-column with sidebar)
      ```css
      .arch-grid {
        display: grid;
        grid-template-columns: 260px 1fr;
        grid-template-rows: auto;
        gap: 20px;
        max-width: 1100px;
        margin: 0 auto;
      }
      
      .arch-grid__sidebar { grid-column: 1; }
      .arch-grid__main { grid-column: 2; }
      .arch-grid__full { grid-column: 1 / -1; }
      ```
      
      ### Pipeline (horizontal steps)
      ```css
      .pipeline {
        display: flex;
        align-items: stretch;
        gap: 0;
        overflow-x: auto;
        padding-bottom: 8px;
      }
      
      .pipeline__step {
        min-width: 130px;
        flex-shrink: 0;
      }
      
      .pipeline__arrow {
        display: flex;
        align-items: center;
        padding: 0 4px;
        color: var(--border-bright);
        font-size: 18px;
        flex-shrink: 0;
      }
      
      /* Parallel branch within a pipeline */
      .pipeline__parallel {
        display: flex;
        flex-direction: column;
        gap: 6px;
      }
      ```
      
      ### Card Grid (dashboard / metrics)
      ```css
      .card-grid {
        display: grid;
        grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
        gap: 16px;
      }
      ```
      
      ### Data Tables
      
      Use real `<table>` elements for tabular data. Wrap in a scrollable container for wide tables.
      
      ```css
      /* Scrollable wrapper for wide tables */
      .table-wrap {
        background: var(--surface);
        border: 1px solid var(--border);
        border-radius: 12px;
        overflow: hidden;
      }
      
      .table-scroll {
        overflow-x: auto;
        -webkit-overflow-scrolling: touch;
      }
      
      /* Base table */
      .data-table {
        width: 100%;
        border-collapse: collapse;
        font-size: 13px;
        line-height: 1.5;
      }
      
      /* Header */
      .data-table thead {
        position: sticky;
        top: 0;
        z-index: 2;
      }
      
      .data-table th {
        background: var(--surface-elevated, var(--surface2, var(--surface)));
        font-family: var(--font-mono);
        font-size: 11px;
        font-weight: 600;
        text-transform: uppercase;
        letter-spacing: 1px;
        color: var(--text-dim);
        text-align: left;
        padding: 12px 16px;
        border-bottom: 2px solid var(--border-bright);
        white-space: nowrap;
      }
      
      /* Cells */
      .data-table td {
        padding: 12px 16px;
        border-bottom: 1px solid var(--border);
        vertical-align: top;
        color: var(--text);
      }
      
      /* Let text-heavy columns wrap naturally */
      .data-table .wide {
        min-width: 200px;
        max-width: 500px;
      }
      
      /* Right-align numeric columns */
      .data-table td.num,
      .data-table th.num {
        text-align: right;
        font-variant-numeric: tabular-nums;
        font-family: var(--font-mono);
      }
      
      /* Alternating rows */
      .data-table tbody tr:nth-child(even) {
        background: var(--accent-dim);
      }
      
      /* Row hover */
      .data-table tbody tr {
        transition: background 0.15s ease;
      }
      
      .data-table tbody tr:hover {
        background: var(--border);
      }
      
      /* Last row: no bottom border (container handles it) */
      .data-table tbody tr:last-child td {
        border-bottom: none;
      }
      
      /* Code inside cells */
      .data-table code {
        font-family: var(--font-mono);
        font-size: 11px;
        background: var(--accent-dim);
        color: var(--accent);
        padding: 1px 5px;
        border-radius: 3px;
      }
      
      /* Secondary detail text */
      .data-table small {
        display: block;
        color: var(--text-dim);
        font-size: 11px;
        margin-top: 2px;
      }
      ```
      
      #### Status Indicators
      
      Styled spans for match/gap/warning states. Never use emoji.
      
      ```css
      .status {
        display: inline-flex;
        align-items: center;
        gap: 6px;
        font-family: var(--font-mono);
        font-size: 11px;
        font-weight: 500;
        padding: 3px 10px;
        border-radius: 6px;
        white-space: nowrap;
      }
      
      .status--match {
        background: var(--green-dim, rgba(5, 150, 105, 0.1));
        color: var(--green, #059669);
      }
      
      .status--gap {
        background: var(--red-dim, rgba(239, 68, 68, 0.1));
        color: var(--red, #ef4444);
      }
      
      .status--warn {
        background: var(--orange-dim, rgba(217, 119, 6, 0.1));
        color: var(--orange, #d97706);
      }
      
      .status--info {
        background: var(--accent-dim);
        color: var(--accent);
      }
      
      /* Dot variant (compact, no text) */
      .status-dot {
        width: 8px;
        height: 8px;
        border-radius: 50%;
        display: inline-block;
      }
      
      .status-dot--match { background: var(--green, #059669); }
      .status-dot--gap { background: var(--red, #ef4444); }
      .status-dot--warn { background: var(--orange, #d97706); }
      ```
      
      Usage in table cells:
      ```html
      <td><span class="status status--match">Match</span></td>
      <td><span class="status status--gap">Gap</span></td>
      <td><span class="status status--warn">Partial</span></td>
      ```
      
      #### Table Summary Row
      
      For totals, counts, or aggregate status at the bottom:
      
      ```css
      .data-table tfoot td {
        background: var(--surface-elevated, var(--surface2, var(--surface)));
        font-weight: 600;
        font-size: 12px;
        border-top: 2px solid var(--border-bright);
        border-bottom: none;
        padding: 12px 16px;
      }
      ```
      
      #### Sticky First Column (for very wide tables)
      
      ```css
      .data-table th:first-child,
      .data-table td:first-child {
        position: sticky;
        left: 0;
        z-index: 1;
        background: var(--surface);
      }
      
      .data-table tbody tr:nth-child(even) td:first-child {
        background: color-mix(in srgb, var(--surface) 95%, var(--accent) 5%);
      }
      ```
      
      ## Connectors
      
      ### CSS Arrow (vertical, between stacked sections)
      ```css
      .flow-arrow {
        display: flex;
        justify-content: center;
        align-items: center;
        gap: 8px;
        color: var(--text-dim);
        font-family: var(--font-mono);
        font-size: 12px;
        padding: 6px 0;
      }
      
      /* Down arrow via SVG icon */
      .flow-arrow svg {
        width: 20px;
        height: 20px;
        fill: none;
        stroke: var(--border-bright);
        stroke-width: 2;
        stroke-linecap: round;
        stroke-linejoin: round;
      }
      ```
      
      Down arrow SVG (reuse inline):
      ```html
      <svg viewBox="0 0 20 20"><path d="M10 4 L10 16 M6 12 L10 16 L14 12"/></svg>
      ```
      
      ### CSS Arrow (horizontal, between inline steps)
      Use `::after` or a literal arrow character:
      ```css
      .h-arrow::after {
        content: '→';
        color: var(--border-bright);
        font-size: 18px;
        padding: 0 4px;
      }
      ```
      
      ### SVG Curved Connector (between arbitrary nodes)
      For connections that aren't simple vertical/horizontal, use an absolutely positioned SVG overlay:
      ```html
      <svg class="connectors" style="position:absolute;inset:0;width:100%;height:100%;pointer-events:none;">
        <path d="M 150,100 C 150,200 350,100 350,200" fill="none" stroke="var(--accent)" stroke-width="1.5" stroke-dasharray="4 3"/>
        <!-- Arrowhead -->
        <polygon points="348,195 352,205 356,195" fill="var(--accent)"/>
      </svg>
      ```
      
      Position the parent container as `position: relative` to scope the SVG overlay.
      
      ## Animations
      
      ### Staggered Fade-In on Load
      
      Define the keyframe once, then stagger via a `--i` CSS variable set per element. This approach works regardless of DOM nesting or interleaved non-animated elements (unlike `nth-child` which breaks when siblings aren't all the same type).
      
      ```css
      @keyframes fadeUp {
        from { opacity: 0; transform: translateY(12px); }
        to { opacity: 1; transform: translateY(0); }
      }
      
      .node {
        animation: fadeUp 0.4s ease-out both;
        animation-delay: calc(var(--i, 0) * 0.05s);
      }
      ```
      
      Set `--i` per element in the HTML to control stagger order:
      
      ```html
      <div class="node" style="--i: 0">First</div>
      <div class="connector">...</div>
      <div class="node" style="--i: 1">Second</div>
      <div class="connector">...</div>
      <div class="node" style="--i: 2">Third</div>
      ```
      
      ### Hover Lift
      ```css
      .node {
        transition: transform 0.2s ease, box-shadow 0.2s ease;
      }
      
      .node:hover {
        transform: translateY(-2px);
        box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
      }
      ```
      
      ### Scale-Fade (for KPI cards, badges, status indicators)
      
      ```css
      @keyframes fadeScale {
        from { opacity: 0; transform: scale(0.92); }
        to { opacity: 1; transform: scale(1); }
      }
      
      .kpi-card {
        animation: fadeScale 0.35s ease-out both;
        animation-delay: calc(var(--i, 0) * 0.06s);
      }
      ```
      
      ### SVG Draw-In (for connectors, progress rings, path elements)
      
      ```css
      @keyframes drawIn {
        from { stroke-dashoffset: var(--path-length); }
        to { stroke-dashoffset: 0; }
      }
      
      /* Set --path-length to the path's getTotalLength() value */
      .connector path {
        stroke-dasharray: var(--path-length);
        animation: drawIn 0.8s ease-in-out both;
        animation-delay: calc(var(--i, 0) * 0.1s);
      }
      ```
      
      ### CSS Counter (for hero numbers without JS)
      
      Uses `@property` to animate a custom property as an integer, then display it via `counter()`. No JS required. Falls back to showing the final value immediately in browsers without `@property` support.
      
      ```css
      @property --count {
        syntax: '<integer>';
        initial-value: 0;
        inherits: false;
      }
      
      @keyframes countUp {
        to { --count: var(--target); }
      }
      
      .kpi-card__value--animated {
        --target: 247;
        counter-reset: val var(--count);
        animation: countUp 1.2s ease-out forwards;
      }
      
      .kpi-card__value--animated::after {
        content: counter(val);
      }
      ```
      
      ### Choreography
      
      Don't use the same animation for everything. Mix types by element role, with easing stagger (fast-then-slow, not linear):
      
      - **Cards**: `fadeUp` — the default entrance, reliable and subtle
      - **KPI / badges**: `fadeScale` — scale draws the eye to important numbers
      - **SVG connectors**: `drawIn` — reveals flow direction, pairs with card stagger
      - **Hero numbers**: `countUp` — counting motion signals "this number matters"
      - **Stagger timing**: `calc(var(--i) * 0.06s)` with lower `--i` values on important elements so they appear first
      
      ### Respect Reduced Motion
      ```css
      @media (prefers-reduced-motion: reduce) {
        *, *::before, *::after {
          animation-duration: 0.01ms !important;
          animation-iteration-count: 1 !important;
          transition-duration: 0.01ms !important;
        }
      }
      ```
      
      ## Sparklines and Simple Charts (Pure SVG)
      
      For simple inline visualizations without a library:
      
      ```html
      <!-- Sparkline -->
      <svg viewBox="0 0 100 30" style="width:100px;height:30px;">
        <polyline points="0,25 15,20 30,22 45,10 60,15 75,5 90,12 100,8"
          fill="none" stroke="var(--accent)" stroke-width="1.5" stroke-linecap="round"/>
      </svg>
      
      <!-- Progress bar -->
      <div style="height:6px;background:var(--border);border-radius:3px;overflow:hidden;">
        <div style="height:100%;width:72%;background:var(--accent);border-radius:3px;"></div>
      </div>
      ```
      
      ## Responsive Breakpoint
      
      Include a single breakpoint for narrow viewports:
      
      ```css
      @media (max-width: 768px) {
        .arch-grid { grid-template-columns: 1fr; }
        .pipeline { flex-wrap: wrap; gap: 8px; }
        .pipeline__arrow { display: none; }
        body { padding: 16px; }
      }
      ```
      
      ## Badges and Tags
      
      Small inline labels for categorizing elements:
      
      ```css
      .tag {
        font-family: var(--font-mono);
        font-size: 10px;
        font-weight: 500;
        padding: 2px 7px;
        border-radius: 4px;
        background: var(--node-a-dim);
        color: var(--node-a);
      }
      ```
      
      ## Lists Inside Nodes
      
      For tool listings, feature lists, table columns:
      
      ```css
      .node-list {
        list-style: none;
        padding: 0;
        margin: 0;
        font-size: 12px;
        line-height: 1.8;
      }
      
      .node-list li {
        padding-left: 14px;
        position: relative;
      }
      
      .node-list li::before {
        content: '›';
        color: var(--text-dim);
        font-weight: 600;
        position: absolute;
        left: 0;
      }
      
      .node-list code {
        font-family: var(--font-mono);
        font-size: 11px;
        background: var(--accent-dim);
        color: var(--accent);
        padding: 1px 5px;
        border-radius: 3px;
      }
      ```
      
      ## KPI / Metric Cards
      
      Large hero number with trend indicator and label. For dashboards, review summaries, and impact sections.
      
      ```css
      .kpi-row {
        display: grid;
        grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
        gap: 16px;
      }
      
      .kpi-card {
        background: var(--surface-elevated);
        border: 1px solid var(--border);
        border-radius: 10px;
        padding: 20px;
        box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
      }
      
      .kpi-card__value {
        font-size: 36px;
        font-weight: 700;
        letter-spacing: -1px;
        line-height: 1.1;
        font-variant-numeric: tabular-nums;
      }
      
      .kpi-card__label {
        font-family: var(--font-mono);
        font-size: 10px;
        font-weight: 600;
        text-transform: uppercase;
        letter-spacing: 1.5px;
        color: var(--text-dim);
        margin-top: 6px;
      }
      
      .kpi-card__trend {
        font-family: var(--font-mono);
        font-size: 12px;
        margin-top: 4px;
      }
      
      .kpi-card__trend--up { color: var(--node-b, #059669); }
      .kpi-card__trend--down { color: var(--red, #ef4444); }
      ```
      
      ```html
      <div class="kpi-row">
        <div class="kpi-card">
          <div class="kpi-card__value">247</div>
          <div class="kpi-card__label">Lines Added</div>
          <div class="kpi-card__trend kpi-card__trend--up">+34%</div>
        </div>
        <!-- ... more cards -->
      </div>
      ```
      
      ## Before / After Panels
      
      Two-column comparison with diff-colored headers. For review pages, migration docs, and feature comparisons.
      
      ```css
      .diff-panels {
        display: grid;
        grid-template-columns: 1fr 1fr;
        gap: 0;
        border: 1px solid var(--border);
        border-radius: 10px;
        overflow: hidden;
      }
      
      .diff-panels > * { min-width: 0; overflow-wrap: break-word; }
      
      .diff-panel__header {
        font-family: var(--font-mono);
        font-size: 11px;
        font-weight: 600;
        text-transform: uppercase;
        letter-spacing: 1px;
        padding: 10px 16px;
      }
      
      .diff-panel__header--before {
        background: var(--red-dim, rgba(239, 68, 68, 0.08));
        color: var(--red, #ef4444);
        border-bottom: 2px solid var(--red, #ef4444);
      }
      
      .diff-panel__header--after {
        background: var(--green-dim, rgba(5, 150, 105, 0.08));
        color: var(--green, #059669);
        border-bottom: 2px solid var(--green, #059669);
      }
      
      .diff-panel__body {
        padding: 16px;
        background: var(--surface);
        font-size: 13px;
        line-height: 1.6;
      }
      
      /* Highlight changed items within a panel */
      .diff-changed {
        background: var(--accent-dim);
        border-radius: 3px;
        padding: 0 3px;
      }
      
      @media (max-width: 768px) {
        .diff-panels { grid-template-columns: 1fr; }
      }
      ```
      
      ```html
      <div class="diff-panels">
        <div class="diff-panel__header diff-panel__header--before">Before</div>
        <div class="diff-panel__header diff-panel__header--after">After</div>
        <div class="diff-panel__body">Previous implementation...</div>
        <div class="diff-panel__body">New implementation...</div>
      </div>
      ```
      
      ## Collapsible Sections
      
      Native `<details>/<summary>` with styled disclosure. Zero JS, accessible. For lower-priority content: file maps, decision logs, reference sections.
      
      ```css
      details.collapsible {
        border: 1px solid var(--border);
        border-radius: 10px;
        overflow: hidden;
      }
      
      details.collapsible summary {
        padding: 14px 20px;
        background: var(--surface);
        font-family: var(--font-mono);
        font-size: 12px;
        font-weight: 600;
        cursor: pointer;
        list-style: none;
        display: flex;
        align-items: center;
        gap: 8px;
        color: var(--text);
        transition: background 0.15s ease;
      }
      
      details.collapsible summary:hover {
        background: var(--surface-elevated, var(--surface));
      }
      
      details.collapsible summary::-webkit-details-marker { display: none; }
      
      /* Chevron indicator */
      details.collapsible summary::before {
        content: '▸';
        font-size: 11px;
        color: var(--text-dim);
        transition: transform 0.15s ease;
      }
      
      details.collapsible[open] summary::before {
        transform: rotate(90deg);
      }
      
      details.collapsible .collapsible__body {
        padding: 16px 20px;
        border-top: 1px solid var(--border);
        font-size: 13px;
        line-height: 1.6;
      }
      ```
      
      ```html
      <details class="collapsible">
        <summary>File Map (14 files changed)</summary>
        <div class="collapsible__body">
          <!-- content here -->
        </div>
      </details>
      ```
      
      ## Generated Images
      
      For AI-generated illustrations embedded as base64 data URIs via `surf gemini --generate-image`. Use sparingly — hero banners, conceptual illustrations, educational diagrams, decorative accents.
      
      ### Hero Banner
      
      Full-width image cropped to a fixed height with a gradient fade into the page background. Place at the top of the page before the title, or between the title and the first content section.
      
      ```css
      .hero-img-wrap {
        position: relative;
        border-radius: 12px;
        overflow: hidden;
        margin-bottom: 24px;
      }
      
      .hero-img-wrap img {
        width: 100%;
        height: 240px;
        object-fit: cover;
        display: block;
      }
      
      /* Gradient fade into page background */
      .hero-img-wrap::after {
        content: '';
        position: absolute;
        bottom: 0;
        left: 0;
        right: 0;
        height: 50%;
        background: linear-gradient(to top, var(--bg), transparent);
        pointer-events: none;
      }
      ```
      
      ```html
      <div class="hero-img-wrap">
        <img src="data:image/png;base64,..." alt="Descriptive alt text">
      </div>
      ```
      
      Generate with `--aspect-ratio 16:9` for hero banners.
      
      ### Inline Illustration
      
      Centered image with border, shadow, and optional caption. Use within content sections for conceptual or educational illustrations.
      
      ```css
      .illus {
        text-align: center;
        margin: 24px 0;
      }
      
      .illus img {
        max-width: 480px;
        width: 100%;
        border-radius: 10px;
        border: 1px solid var(--border);
        box-shadow: 0 2px 12px rgba(0, 0, 0, 0.08);
      }
      
      .illus figcaption {
        font-family: var(--font-mono);
        font-size: 11px;
        color: var(--text-dim);
        margin-top: 8px;
      }
      ```
      
      ```html
      <figure class="illus">
        <img src="data:image/png;base64,..." alt="Descriptive alt text">
        <figcaption>How the message queue routes events between services</figcaption>
      </figure>
      ```
      
      Generate with `--aspect-ratio 1:1` or `--aspect-ratio 4:3` for inline illustrations.
      
      ### Side Accent
      
      Small image floated beside a section. Use when the illustration supports but doesn't dominate the content.
      
      ```css
      .accent-img {
        float: right;
        max-width: 200px;
        margin: 0 0 16px 24px;
        border-radius: 10px;
        border: 1px solid var(--border);
        box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
      }
      
      @media (max-width: 768px) {
        .accent-img {
          float: none;
          max-width: 100%;
          margin: 0 0 16px 0;
        }
      }
      ```
      
      ```html
      <img class="accent-img" src="data:image/png;base64,..." alt="Descriptive alt text">
      ```
      
    • libraries.md 15.1 KB
      # External Libraries (CDN)
      
      Optional CDN libraries for cases where pure CSS/HTML isn't enough. Only include what the diagram actually needs — most diagrams need zero external JS.
      
      ## Mermaid.js — Diagramming Engine
      
      Use for flowcharts, sequence diagrams, ER diagrams, state machines, mind maps, class diagrams, and any diagram where automatic node positioning and edge routing saves effort. Mermaid handles layout — you handle theming.
      
      Do NOT use for dashboards — CSS Grid card layouts with Chart.js look better for those. Data tables use `<table>` elements.
      
      **CDN:**
      ```html
      <script type="module">
        import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.esm.min.mjs';
      
        mermaid.initialize({ startOnLoad: true, /* ... */ });
      </script>
      ```
      
      **With ELK layout** (required for `layout: 'elk'` — it's a separate package, not bundled in core):
      ```html
      <script type="module">
        import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.esm.min.mjs';
        import elkLayouts from 'https://cdn.jsdelivr.net/npm/@mermaid-js/layout-elk/dist/mermaid-layout-elk.esm.min.mjs';
      
        mermaid.registerLayoutLoaders(elkLayouts);
        mermaid.initialize({ startOnLoad: true, layout: 'elk', /* ... */ });
      </script>
      ```
      
      Without the ELK import and registration, `layout: 'elk'` silently falls back to dagre. Only import ELK when you actually need it — it adds significant bundle weight. Most simple diagrams render fine with dagre.
      
      ### Deep Theming
      
      Always use `theme: 'base'` — it's the only theme where all `themeVariables` are fully customizable. The built-in themes (`default`, `dark`, `forest`, `neutral`) ignore most variable overrides.
      
      ```html
      <script type="module">
        import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.esm.min.mjs';
      
        const isDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
        mermaid.initialize({
          startOnLoad: true,
          theme: 'base',
          look: 'classic',
          themeVariables: {
            // Background and surfaces
            primaryColor: isDark ? '#2d1b69' : '#ede9fe',
            primaryBorderColor: isDark ? '#7c3aed' : '#8b5cf6',
            primaryTextColor: isDark ? '#e6edf3' : '#1a1a2e',
            secondaryColor: isDark ? '#1c2333' : '#f0fdf4',
            secondaryBorderColor: isDark ? '#059669' : '#16a34a',
            secondaryTextColor: isDark ? '#e6edf3' : '#1a1a2e',
            tertiaryColor: isDark ? '#27201a' : '#fef3c7',
            tertiaryBorderColor: isDark ? '#d97706' : '#f59e0b',
            tertiaryTextColor: isDark ? '#e6edf3' : '#1a1a2e',
            // Lines and edges
            lineColor: isDark ? '#6b7280' : '#9ca3af',
            // Text
            // Global default — CSS overrides on .nodeLabel/.edgeLabel win when present
            fontSize: '16px',
            fontFamily: 'var(--font-body)',
            // Notes and labels
            noteBkgColor: isDark ? '#1c2333' : '#fefce8',
            noteTextColor: isDark ? '#e6edf3' : '#1a1a2e',
            noteBorderColor: isDark ? '#fbbf24' : '#d97706',
          }
        });
      </script>
      ```
      
      ### Hand-Drawn Mode
      
      Add `look: 'handDrawn'` for a sketchy, whiteboard-style aesthetic. Combines well with the `elk` layout engine for better positioning (requires the ELK import — see CDN section above):
      
      ```html
      <script type="module">
        import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.esm.min.mjs';
        import elkLayouts from 'https://cdn.jsdelivr.net/npm/@mermaid-js/layout-elk/dist/mermaid-layout-elk.esm.min.mjs';
      
        mermaid.registerLayoutLoaders(elkLayouts);
        mermaid.initialize({
          startOnLoad: true,
          theme: 'base',
          look: 'handDrawn',
          layout: 'elk',
          themeVariables: { /* same as above */ }
        });
      </script>
      ```
      
      Or set it per-diagram via frontmatter:
      ```
      ---
      config:
        look: handDrawn
        layout: elk
      ---
      graph TD
        A[User Request] --> B{Auth Check}
        B -->|Valid| C[Process]
        B -->|Invalid| D[Reject]
      ```
      
      ### CSS Overrides on Mermaid SVG
      
      Mermaid renders SVG. Override its classes for pixel-perfect control that `themeVariables` can't reach:
      
      ```css
      /* Container — see css-patterns.md "Mermaid Zoom Controls" for the full zoom pattern */
      .mermaid-wrap {
        position: relative;
        background: var(--surface);
        border: 1px solid var(--border);
        border-radius: 12px;
        padding: 24px;
        overflow: auto;
      }
      
      /* CRITICAL: Force node/edge text to follow the page's color scheme.
         Without this, themeVariables.primaryTextColor works for DEFAULT nodes,
         but any classDef that sets color: will hardcode a single value that
         breaks in the opposite color scheme. Fix: never set color: in classDef,
         and always include these CSS overrides. */
      .mermaid .nodeLabel { color: var(--text) !important; }
      .mermaid .edgeLabel { color: var(--text-dim) !important; background-color: var(--bg) !important; }
      .mermaid .edgeLabel rect { fill: var(--bg) !important; }
      
      /* Node shapes */
      .mermaid .node rect,
      .mermaid .node circle,
      .mermaid .node polygon {
        stroke-width: 1.5px;
      }
      
      /* Edge paths */
      .mermaid .edge-pattern-solid {
        stroke-width: 1.5px;
      }
      
      /* Edge labels — smaller than node labels for visual hierarchy */
      .mermaid .edgeLabel {
        font-family: var(--font-mono) !important;
        font-size: 13px !important;
      }
      
      /* Node labels — 16px default; drop to 14px for complex diagrams (20+ nodes) */
      .mermaid .nodeLabel {
        font-family: var(--font-body) !important;
        font-size: 16px !important;
      }
      
      /* Sequence diagram actors */
      .mermaid .actor {
        stroke-width: 1.5px;
      }
      
      /* Sequence diagram messages */
      .mermaid .messageText {
        font-family: var(--font-mono) !important;
        font-size: 12px !important;
      }
      
      /* ER diagram entities */
      .mermaid .er.entityBox {
        stroke-width: 1.5px;
      }
      
      /* Mind map nodes */
      .mermaid .mindmap-node rect {
        stroke-width: 1.5px;
      }
      ```
      
      ### classDef Gotchas
      
      `classDef` values are static text inside `<pre>` — they can't use CSS variables or JS ternaries. Two rules:
      
      1. **Never set `color:` in classDef.** It hardcodes a text color that breaks in the opposite color scheme. Let the CSS overrides above handle text color via `var(--text)`.
      
      2. **Use semi-transparent fills (8-digit hex) for node backgrounds.** They layer over whatever Mermaid's base theme background is, producing a tint that works in both light and dark modes. Use `20`–`44` alpha for subtle, `55`–`77` for prominent:
      
      ```
      classDef highlight fill:#b5761433,stroke:#b57614,stroke-width:2px
      classDef muted fill:#7c6f6411,stroke:#7c6f6444,stroke-width:1px
      ```
      
      Avoid opaque light fills like `fill:#fefce8` — they render as bright boxes in dark mode.
      
      ### stateDiagram-v2 Label Limitations
      
      State diagram transition labels have a strict parser. Avoid:
      - `<br/>` — only works in flowcharts; causes a parse error in state diagrams
      - Parentheses in labels — `cancel()` can confuse the parser
      - Multiple colons — the first `:` is the label delimiter; extra colons in the label text may break parsing
      
      If you need multi-line labels or special characters, use a `flowchart` instead of `stateDiagram-v2`. Flowcharts support quoted labels (`|"label with: special chars"|`) and `<br/>` for line breaks.
      
      ### Writing Valid Mermaid
      
      Most Mermaid failures come from a few recurring issues. Follow these rules to avoid invalid diagrams:
      
      **Quote labels with special characters.** Parentheses, colons, commas, brackets, and ampersands break the parser when unquoted. Wrap any label containing special characters in double quotes:
      
      ```
      A["handleRequest(ctx)"] --> B["DB: query users"]
      A[handleRequest] --> B[query users]
      ```
      
      **Keep IDs simple.** Node IDs should be alphanumeric with no spaces or punctuation. Put the readable name in the label, not the ID:
      
      ```
      userSvc["User Service"] --> authSvc["Auth Service"]
      ```
      
      **Max 15-20 nodes per diagram.** Beyond that, readability collapses even with ELK layout. Use `subgraph` blocks to group related nodes, or split into multiple diagrams:
      
      ```
      subgraph Auth
        login --> validate --> token
      end
      subgraph API
        gateway --> router --> handler
      end
      Auth --> API
      ```
      
      **Arrow styles for semantic meaning:**
      
      | Arrow | Meaning | Use for |
      |-------|---------|---------|
      | `-->` | Solid | Primary flow |
      | `-.->` | Dotted | Optional, async, or fallback paths |
      | `==>` | Thick | Critical or highlighted path |
      | `--x` | Cross | Rejected or blocked |
      | `-->\|label\|` | Labeled | Decision branches, data descriptions |
      
      **Escape pipes in labels.** If a label contains a literal `|`, use `#124;` (HTML entity) or rephrase to avoid it — pipes delimit edge labels in flowcharts.
      
      **Don't mix diagram syntax.** Each diagram type has its own syntax. `-->` works in flowcharts but not in sequence diagrams (`->>` instead). `:::className` works in flowcharts but not in ER diagrams. When in doubt, check the examples below for correct syntax per type.
      
      ### Diagram Type Examples
      
      **Flowchart with decisions:**
      ```html
      <pre class="mermaid">
      graph TD
        A[Request] --> B{Authenticated?}
        B -->|Yes| C[Load Dashboard]
        B -->|No| D[Login Page]
        D --> E[Submit Credentials]
        E --> B
        C --> F{Role?}
        F -->|Admin| G[Admin Panel]
        F -->|User| H[User Dashboard]
      </pre>
      ```
      
      **Sequence diagram:**
      ```html
      <pre class="mermaid">
      sequenceDiagram
        participant C as Client
        participant G as Gateway
        participant S as Service
        participant D as Database
        C->>G: POST /api/data
        G->>G: Validate JWT
        G->>S: Forward request
        S->>D: Query
        D-->>S: Results
        S-->>G: Response
        G-->>C: 200 OK
      </pre>
      ```
      
      **ER diagram:**
      ```html
      <pre class="mermaid">
      erDiagram
        USERS ||--o{ ORDERS : places
        ORDERS ||--|{ LINE_ITEMS : contains
        LINE_ITEMS }o--|| PRODUCTS : references
        USERS { string email PK }
        ORDERS { int id PK }
        LINE_ITEMS { int quantity }
        PRODUCTS { string name }
      </pre>
      ```
      
      **State diagram:**
      ```html
      <pre class="mermaid">
      stateDiagram-v2
        [*] --> Draft
        Draft --> Review : submit
        Review --> Approved : approve
        Review --> Draft : request_changes
        Approved --> Published : publish
        Published --> Archived : archive
        Archived --> [*]
      </pre>
      ```
      
      **Mind map:**
      ```html
      <pre class="mermaid">
      mindmap
        root((Project))
          Frontend
            React
            Next.js
            Tailwind
          Backend
            Node.js
            PostgreSQL
            Redis
          Infrastructure
            AWS
            Docker
            Terraform
      </pre>
      ```
      
      ### Dark Mode Handling
      
      Mermaid initializes once — it can't reactively switch themes. Read the preference at load time inside your `<script type="module">`:
      
      ```javascript
      const isDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
      // Use isDark to pick light or dark values in themeVariables
      ```
      
      The CSS overrides on the container (`.mermaid-wrap`) and page will still respond to `prefers-color-scheme` normally — only the Mermaid SVG internals are static.
      
      ## Chart.js — Data Visualizations
      
      Use for bar charts, line charts, pie/doughnut charts, radar charts, and other data-driven visualizations in dashboard-type diagrams. Overkill for static numbers — use pure SVG/CSS for simple progress bars and sparklines.
      
      ```html
      <script src="https://cdn.jsdelivr.net/npm/chart.js@4/dist/chart.umd.min.js"></script>
      
      <canvas id="myChart" width="600" height="300"></canvas>
      
      <script>
        const isDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
        const textColor = isDark ? '#8b949e' : '#6b7280';
        const gridColor = isDark ? 'rgba(255,255,255,0.06)' : 'rgba(0,0,0,0.06)';
        const fontFamily = getComputedStyle(document.documentElement)
          .getPropertyValue('--font-body').trim() || 'system-ui, sans-serif';
      
        new Chart(document.getElementById('myChart'), {
          type: 'bar',
          data: {
            labels: ['Jan', 'Feb', 'Mar', 'Apr', 'May'],
            datasets: [{
              label: 'Feedback Items',
              data: [45, 62, 78, 91, 120],
              backgroundColor: isDark ? 'rgba(129, 140, 248, 0.6)' : 'rgba(79, 70, 229, 0.6)',
              borderColor: isDark ? '#818cf8' : '#4f46e5',
              borderWidth: 1,
              borderRadius: 4,
            }]
          },
          options: {
            responsive: true,
            plugins: {
              legend: { labels: { color: textColor, font: { family: fontFamily } } },
            },
            scales: {
              x: { ticks: { color: textColor, font: { family: fontFamily } }, grid: { color: gridColor } },
              y: { ticks: { color: textColor, font: { family: fontFamily } }, grid: { color: gridColor } },
            }
          }
        });
      </script>
      ```
      
      Wrap the canvas in a styled container:
      ```css
      .chart-container {
        background: var(--surface);
        border: 1px solid var(--border);
        border-radius: 10px;
        padding: 20px;
        position: relative;
      }
      
      .chart-container canvas {
        max-height: 300px;
      }
      ```
      
      ## anime.js — Orchestrated Animations
      
      Use when a diagram has 10+ elements and you want a choreographed entrance sequence (staggered reveals, path drawing, count-up numbers). For simpler diagrams, CSS `animation-delay` staggering is sufficient.
      
      ```html
      <script src="https://cdn.jsdelivr.net/npm/animejs@3.2.2/lib/anime.min.js"></script>
      
      <script>
        const prefersReduced = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
      
        if (!prefersReduced) {
          anime({
            targets: '.node',
            opacity: [0, 1],
            translateY: [20, 0],
            delay: anime.stagger(80, { start: 200 }),
            easing: 'easeOutCubic',
            duration: 500,
          });
      
          anime({
            targets: '.connector path',
            strokeDashoffset: [anime.setDashoffset, 0],
            easing: 'easeInOutCubic',
            duration: 800,
            delay: anime.stagger(150, { start: 600 }),
          });
      
          document.querySelectorAll('[data-count]').forEach(el => {
            anime({
              targets: { val: 0 },
              val: parseInt(el.dataset.count),
              round: 1,
              duration: 1200,
              delay: 400,
              easing: 'easeOutExpo',
              update: (anim) => { el.textContent = anim.animations[0].currentValue; }
            });
          });
        }
      </script>
      ```
      
      When using anime.js, set initial opacity to 0 in CSS so elements don't flash before the animation:
      ```css
      .node { opacity: 0; }
      
      @media (prefers-reduced-motion: reduce) {
        .node { opacity: 1 !important; }
      }
      ```
      
      ## Google Fonts — Typography
      
      Always load with `display=swap` for fast rendering. Pick a distinctive pairing — body + mono at minimum, optionally a display font for the title.
      
      ```html
      <link rel="preconnect" href="https://fonts.googleapis.com">
      <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
      <link href="https://fonts.googleapis.com/css2?family=Space+Mono:wght@400;700&family=Outfit:wght@400;500;600;700&display=swap" rel="stylesheet">
      ```
      
      Define as CSS variables for easy reference:
      ```css
      :root {
        --font-body: 'Outfit', system-ui, sans-serif;
        --font-mono: 'Space Mono', 'SF Mono', Consolas, monospace;
      }
      ```
      
      **Font suggestions** (rotate — never use the same pairing twice in a row):
      
      | Body / Headings | Mono / Labels | Feel |
      |---|---|---|
      | Outfit | Space Mono | Clean geometric, modern |
      | Instrument Serif | JetBrains Mono | Editorial, refined |
      | Sora | IBM Plex Mono | Technical, precise |
      | DM Sans | Fira Code | Friendly, developer |
      | Fraunces | Source Code Pro | Warm, distinctive |
      | Libre Franklin | Inconsolata | Classic, reliable |
      | Manrope | Martian Mono | Soft, contemporary |
      | Playfair Display | Roboto Mono | Elegant contrast |
      | Bricolage Grotesque | Fragment Mono | Bold, characterful |
      | Geist | Geist Mono | Vercel-inspired, sharp |
      | Crimson Pro | Noto Sans Mono | Scholarly, serious |
      | Red Hat Display | Red Hat Mono | Cohesive family |
      | Plus Jakarta Sans | Azeret Mono | Rounded, approachable |
      
      Never default to Inter, Roboto, Arial, or system-ui as the primary choice.
      
    • responsive-nav.md 5.7 KB
      # Responsive Section Navigation
      
      Navigation pattern for multi-section pages (reviews, recaps, dashboards). Provides a sticky sidebar TOC on desktop and a sticky horizontal scrollable bar on mobile.
      
      ## Layout Structure
      
      The page uses a two-column CSS Grid: sidebar (TOC) + main content. On mobile it collapses to single-column with the TOC becoming a horizontal bar.
      
      ```html
      <body>
      <div class="wrap">
      
        <nav class="toc" id="toc">
          <div class="toc-title">Contents</div>
          <a href="#s1">1. First Section</a>
          <a href="#s2">2. Second Section</a>
          <!-- one link per section -->
        </nav>
      
        <div class="main">
          <h1>Page Title</h1>
          <p class="subtitle">Subtitle text</p>
      
          <div id="s1" class="sec-head ...">1 — First Section</div>
          <!-- section content -->
      
          <div id="s2" class="sec-head ...">2 — Second Section</div>
          <!-- section content -->
        </div><!-- /main -->
      
      </div><!-- /wrap -->
      </body>
      ```
      
      Key structural rules:
      - `<nav class="toc">` is the **first child** of `.wrap`
      - All page content goes inside `<div class="main">`
      - Every section heading gets an `id="s1"`, `id="s2"`, etc.
      - TOC links use `href="#s1"` matching those IDs
      - Keep TOC link text short (truncate long section names)
      
      ## CSS
      
      ### Wrap (grid layout)
      
      ```css
      .wrap {
        max-width: 1400px;
        margin: 0 auto;
        display: grid;
        grid-template-columns: 170px 1fr;
        gap: 0 40px;
      }
      .main { min-width: 0; }
      ```
      
      ### TOC — Desktop (sticky sidebar)
      
      ```css
      .toc {
        position: sticky;
        top: 24px;
        align-self: start;
        padding: 14px 0;
        grid-row: 1 / -1;
        max-height: calc(100dvh - 48px);
        overflow-y: auto;
      }
      .toc::-webkit-scrollbar { width: 3px; }
      .toc::-webkit-scrollbar-thumb { background: var(--surface-elevated); border-radius: 2px; }
      
      .toc-title {
        font-family: var(--font-mono);
        font-size: 9px;
        font-weight: 700;
        text-transform: uppercase;
        letter-spacing: 2px;
        color: var(--text-dim);
        padding: 0 0 10px;
        margin-bottom: 8px;
        border-bottom: 1px solid var(--border);
      }
      
      .toc a {
        display: block;
        font-size: 11px;
        color: var(--text-dim);
        text-decoration: none;
        padding: 4px 8px;
        border-radius: 5px;
        border-left: 2px solid transparent;
        transition: all 0.15s;
        line-height: 1.4;
        margin-bottom: 1px;
      }
      .toc a:hover { color: var(--text); background: var(--surface2); }
      .toc a.active { color: var(--text); border-left-color: var(--accent); }
      ```
      
      Replace `var(--accent)` with your page's primary accent color variable (e.g., `var(--orange)`, `var(--blue)`).
      
      ### TOC — Mobile (sticky horizontal bar)
      
      ```css
      @media (max-width: 1000px) {
        .wrap { grid-template-columns: 1fr; padding-top: 0; }
        body { padding-top: 0; }
      
        .toc {
          position: sticky;
          top: 0;
          z-index: 200;
          max-height: none;
          display: flex;
          gap: 4px;
          align-items: center;
          overflow-x: auto;
          -webkit-overflow-scrolling: touch;
          background: var(--bg);
          border-bottom: 1px solid var(--border);
          padding: 10px 0;
          margin: 0 -40px;
          padding-left: 40px;
          padding-right: 40px;
          grid-row: auto;
        }
        .toc::-webkit-scrollbar { display: none; }
        .toc-title { display: none; }
      
        .toc a {
          white-space: nowrap;
          flex-shrink: 0;
          border-left: none;
          border-bottom: 2px solid transparent;
          border-radius: 4px 4px 0 0;
          padding: 6px 10px;
          font-size: 10px;
        }
        .toc a.active {
          border-left: none;
          border-bottom-color: var(--accent);
          background: var(--surface);
        }
      
        .main { padding-top: 20px; }
      
        /* Offset scroll target so headings clear the sticky bar */
        .sec-head { scroll-margin-top: 52px; }
      }
      ```
      
      Adjust `margin: 0 -40px` and `padding-left/right: 40px` to match your `body` padding so the bar bleeds edge-to-edge.
      
      ## JavaScript — Scroll Spy
      
      Place before `</body>`, after any Mermaid init:
      
      ```html
      <script>
      (function() {
        const toc = document.getElementById('toc');
        const links = toc.querySelectorAll('a');
        const sections = [];
      
        links.forEach(link => {
          const id = link.getAttribute('href').slice(1);
          const el = document.getElementById(id);
          if (el) sections.push({ id, el, link });
        });
      
        const observer = new IntersectionObserver(entries => {
          entries.forEach(entry => {
            if (entry.isIntersecting) {
              links.forEach(l => l.classList.remove('active'));
              const match = sections.find(s => s.el === entry.target);
              if (match) {
                match.link.classList.add('active');
                // On mobile, auto-scroll the active tab into view
                if (window.innerWidth <= 1000) {
                  match.link.scrollIntoView({
                    behavior: 'smooth', block: 'nearest', inline: 'center'
                  });
                }
              }
            }
          });
        }, { rootMargin: '-10% 0px -80% 0px' });
      
        sections.forEach(s => observer.observe(s.el));
      
        links.forEach(link => {
          link.addEventListener('click', e => {
            e.preventDefault();
            const id = link.getAttribute('href').slice(1);
            const el = document.getElementById(id);
            if (el) {
              el.scrollIntoView({ behavior: 'smooth', block: 'start' });
              history.replaceState(null, '', '#' + id);
            }
          });
        });
      })();
      </script>
      ```
      
      ## Adaptation Notes
      
      - The `.toc-title` text, link labels, accent color, and section IDs change per page. Everything else is copy-paste.
      - For pages with fewer than 4 sections, skip the TOC entirely — it adds clutter without value.
      - The `grid-template-columns: 170px 1fr` width works for most TOCs. If section names are longer, go up to `200px`.
      - The `rootMargin: '-10% 0px -80% 0px'` means a section is "active" when its heading enters the top 10-20% of the viewport. This works well with sticky headers.
      - On mobile, the horizontal bar uses `overflow-x: auto` with hidden scrollbar. The active tab auto-scrolls into the center of the bar as the user scrolls the page.
      
  • templates
    • architecture.html 17.1 KB · in bundle
    • data-table.html 15.9 KB · in bundle
    • mermaid-flowchart.html 13 KB · in bundle
  • .gitignore 10 B · in bundle
  • banner.png 1.1 MB · in bundle
  • CHANGELOG.md 2.7 KB
    # Changelog
    
    ## [0.1.1] - 2026-02-19
    
    - Prompts no longer require the `pi-prompt-template-model` extension — each prompt now explicitly loads the skill itself
    - Added "Writing Valid Mermaid" section to `libraries.md` (quoting special chars, simple IDs, max node count, arrow styles, pipe escaping)
    - Fixed mobile scroll offset in `responsive-nav.md` — section headings now clear the sticky nav bar via `scroll-margin-top`
    - Added video preview to README
    
    ## [0.1.0] - 2026-02-16
    
    Initial release.
    
    ### Skill
    - Core workflow: Think (pick aesthetic) → Structure (read template) → Style (apply design) → Deliver (write + open)
    - 11 diagram types with rendering approach routing (Mermaid, CSS Grid, HTML tables, Chart.js)
    - 9 aesthetic directions (monochrome terminal, editorial, blueprint, neon, paper/ink, sketch, IDE-inspired, data-dense, gradient mesh)
    - Mermaid deep theming with `theme: 'base'` + `themeVariables`, hand-drawn mode, ELK layout
    - Zoom controls (buttons, scroll-to-zoom, drag-to-pan) required on all Mermaid containers
    - Proactive table rendering — agent generates HTML instead of ASCII for complex tables
    - Optional AI-generated illustrations via surf-cli + Gemini Nano Banana Pro
    - Both light and dark themes via CSS custom properties and `prefers-color-scheme`
    - Quality checks: squint test, swap test, overflow protection, zoom controls verification
    
    ### References
    - `css-patterns.md` — theme setup, depth tiers, node cards, grid layouts, data tables, status badges, KPI cards, before/after panels, connectors, animations (fadeUp, fadeScale, drawIn, countUp), collapsible sections, overflow protection, generated image containers
    - `libraries.md` — Mermaid (CDN, ELK, deep theming, hand-drawn mode, CSS overrides, diagram examples), Chart.js, anime.js, Google Fonts with 13 font pairings
    - `responsive-nav.md` — sticky sidebar TOC on desktop, horizontal scrollable bar on mobile, scroll spy
    
    ### Templates
    - `architecture.html` — CSS Grid card layout, terracotta/sage palette, depth tiers, flow arrows, pipeline with parallel branches
    - `mermaid-flowchart.html` — Mermaid flowchart with ELK + handDrawn mode, teal/cyan palette, zoom controls
    - `data-table.html` — HTML table with KPI cards, status badges, collapsible details, rose/cranberry palette
    
    ### Prompt Templates
    - `/generate-web-diagram` — generate a diagram for any topic
    - `/diff-review` — visual diff review with architecture comparison, KPI dashboard, code review, decision log
    - `/plan-review` — plan vs. codebase with current/planned architecture, risk assessment, understanding gaps
    - `/project-recap` — project mental model snapshot for context-switching
    - `/fact-check` — verify factual accuracy of review pages and plan docs against actual code
    
  • LICENSE 1 KB · in bundle
  • README.md 6.1 KB
    <p>
      <img src="banner.png" alt="visual-explainer" width="1100">
    </p>
    
    # visual-explainer
    
    **An agent skill that turns complex terminal output into styled HTML pages you actually want to read.**
    
    [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg?style=for-the-badge)](LICENSE)
    
    Ask your agent to explain a system architecture, review a diff, or compare requirements against a plan. Instead of ASCII art and box-drawing tables, it generates a self-contained HTML page and opens it in your browser:
    
    ```
    > draw a diagram of our authentication flow
    > /diff-review
    > /plan-review ~/docs/refactor-plan.md
    ```
    
    Each one produces a single `.html` file with real typography, dark/light theme support, and interactive Mermaid diagrams with zoom and pan. No build step, no dependencies beyond a browser.
    
    https://github.com/user-attachments/assets/55ebc81b-8732-40f6-a4b1-7c3781aa96ec
    
    ## Why
    
    Every coding agent defaults to ASCII art when you ask for a diagram. Box-drawing characters, monospace alignment hacks, text arrows. It works for trivial cases, but anything beyond a 3-box flowchart turns into an unreadable mess that nobody would put in a presentation or share with a team.
    
    Tables are worse. Ask the agent to compare 15 requirements against a plan and you get a wall of pipes and dashes that wraps and breaks in the terminal. The data is there but it's painful to read.
    
    ## Install
    
    The skill follows the [Agent Skills specification](https://agentskills.io/specification). Clone it into your agent's skills directory:
    
    ```bash
    # Pi
    git clone https://github.com/nicobailon/visual-explainer.git ~/.pi/agent/skills/visual-explainer
    
    # Claude Code
    git clone https://github.com/nicobailon/visual-explainer.git ~/.claude/skills/visual-explainer
    
    # Other agents — point at the directory containing SKILL.md,
    # or paste its contents into your system prompt
    ```
    
    For Pi, restart after cloning. To get the slash commands (`/diff-review`, `/plan-review`, etc.), copy the prompt templates:
    
    ```bash
    cp ~/.pi/agent/skills/visual-explainer/prompts/*.md ~/.pi/agent/prompts/
    ```
    
    If you have [surf-cli](https://github.com/nicobailon/surf-cli) installed, the skill can also generate illustrations via Gemini Nano Banana Pro and embed them in pages. The agent detects surf automatically and skips image generation if it's not there.
    
    ## Usage
    
    The agent loads the skill when you mention diagrams, architecture, flowcharts, schemas, or visualizations. It also kicks in automatically when it's about to dump a complex table in the terminal (4+ rows or 3+ columns) — it renders HTML instead and opens it in the browser. Output goes to `~/.agent/diagrams/`.
    
    The skill ships with five prompt templates:
    
    | Command | What it does |
    |---------|-------------|
    | `/generate-web-diagram` | Generate an HTML diagram for any topic |
    | `/diff-review` | Visual diff review with architecture comparison, code review, decision log |
    | `/plan-review` | Compare a plan against the codebase with risk assessment |
    | `/project-recap` | Mental model snapshot for context-switching back to a project |
    | `/fact-check` | Verify accuracy of a review page or plan doc against actual code |
    
    `/diff-review` is probably the most useful. Run it with no arguments to diff against `main`, or pass any git ref:
    
    ```
    /diff-review                   # feature branch vs main (default)
    /diff-review abc123            # single commit
    /diff-review main..HEAD        # committed changes only
    /diff-review #42               # pull request
    ```
    
    It generates a full page with before/after architecture diagrams, KPI dashboard, structured Good/Bad/Ugly code review, decision log with confidence indicators, and re-entry context for your future self.
    
    `/plan-review` does something similar but for implementation plans — pass it a plan file and it cross-references every claim against the actual codebase, produces current vs. planned architecture diagrams, and flags risks and gaps:
    
    ```
    /plan-review ~/docs/refactor-plan.md
    ```
    
    `/project-recap` is designed for context-switching back to a project after days away. It scans recent git activity and produces an architecture snapshot, decision log, and cognitive debt hotspots. `/fact-check` takes any document that makes claims about code and verifies every one of them.
    
    ## How It Works
    
    ```
    SKILL.md (workflow + design principles)
        ↓
    references/           ← agent reads before each generation
    ├── css-patterns.md   (layouts, animations, theming, depth tiers)
    ├── libraries.md      (Mermaid theming, Chart.js, anime.js, font pairings)
    └── responsive-nav.md (sticky sidebar TOC for multi-section pages)
        ↓
    templates/            ← agent reads the matching reference template
    ├── architecture.html (CSS Grid cards — terracotta/sage palette)
    ├── mermaid-flowchart.html (Mermaid + ELK + handDrawn — teal/cyan palette)
    └── data-table.html   (tables with KPIs and badges — rose/cranberry palette)
        ↓
    ~/.agent/diagrams/filename.html → opens in browser
    ```
    
    The agent picks an aesthetic direction, reads the right reference template, generates a self-contained HTML file with both light and dark themes, and opens it. The three templates use deliberately different palettes so the agent learns variety rather than defaulting to one look. The skill handles 11 diagram types — Mermaid for anything with connections (flowcharts, sequences, ER, state machines, mind maps), CSS Grid for text-heavy architecture overviews, HTML tables for data, Chart.js for dashboards — and routes to the right approach automatically.
    
    To customize the output directory, browser command, or add your own diagram types and CSS patterns, edit the files directly. The agent reads them fresh each time.
    
    ## Limitations
    
    - Requires a browser to view — no inline terminal rendering
    - Switching OS theme requires a page refresh for Mermaid SVGs (CSS-styled elements respond instantly)
    - Results vary by model capability — the skill provides design guidance, not pixel-perfect specs
    
    ## Credits
    
    Borrows ideas from [Anthropic's frontend-design skill](https://github.com/anthropics/skills) and [interface-design](https://github.com/Dammyjay93/interface-design), adapted for one-shot diagram generation.
    
    ## License
    
    MIT
    
  • SKILL.md 18.3 KB
    ---
    name: visual-explainer
    description: Generate beautiful, self-contained HTML pages that visually explain systems, code changes, plans, and data. Use when the user asks for a diagram, architecture overview, diff review, plan review, project recap, comparison table, or any visual explanation of technical concepts. Also use proactively when you are about to render a complex ASCII table (4+ rows or 3+ columns) — present it as a styled HTML page instead.
    license: MIT
    compatibility: Requires a browser to view generated HTML files. Optional surf-cli for AI image generation.
    metadata:
      author: nicobailon
      version: "0.1.1"
    ---
    
    # Visual Explainer
    
    Generate self-contained HTML files for technical diagrams, visualizations, and data tables. Always open the result in the browser. Never fall back to ASCII art when this skill is loaded.
    
    **Proactive table rendering.** When you're about to present tabular data as an ASCII box-drawing table in the terminal (comparisons, audits, feature matrices, status reports, any structured rows/columns), generate an HTML page instead. The threshold: if the table has 4+ rows or 3+ columns, it belongs in the browser. Don't wait for the user to ask — render it as HTML automatically and tell them the file path. You can still include a brief text summary in the chat, but the table itself should be the HTML page.
    
    ## Workflow
    
    ### 1. Think (5 seconds, not 5 minutes)
    
    Before writing HTML, commit to a direction. Don't default to "dark theme with blue accents" every time.
    
    **Who is looking?** A developer understanding a system? A PM seeing the big picture? A team reviewing a proposal? This shapes information density and visual complexity.
    
    **What type of diagram?** Architecture, flowchart, sequence, data flow, schema/ER, state machine, mind map, data table, timeline, or dashboard. Each has distinct layout needs and rendering approaches (see Diagram Types below).
    
    **What aesthetic?** Pick one and commit:
    - Monochrome terminal (green/amber on black, monospace everything)
    - Editorial (serif headlines, generous whitespace, muted palette)
    - Blueprint (technical drawing feel, grid lines, precise)
    - Neon dashboard (saturated accents on deep dark, glowing edges)
    - Paper/ink (warm cream background, hand-drawn feel, sketchy borders)
    - Hand-drawn / sketch (Mermaid `handDrawn` mode, wiggly lines, informal whiteboard feel)
    - IDE-inspired (borrow a real color scheme: Dracula, Nord, Catppuccin, Solarized, Gruvbox, One Dark)
    - Data-dense (small type, tight spacing, maximum information)
    - Gradient mesh (bold gradients, glassmorphism, modern SaaS feel)
    
    Vary the choice each time. If the last diagram was dark and technical, make the next one light and editorial. The swap test: if you replaced your styling with a generic dark theme and nobody would notice the difference, you haven't designed anything.
    
    ### 2. Structure
    
    **Read the reference template** before generating. Don't memorize it — read it each time to absorb the patterns.
    - For text-heavy architecture overviews (card content matters more than topology): read `./templates/architecture.html`
    - For flowcharts, sequence diagrams, ER, state machines, mind maps: read `./templates/mermaid-flowchart.html`
    - For data tables, comparisons, audits, feature matrices: read `./templates/data-table.html`
    
    **For CSS/layout patterns and SVG connectors**, read `./references/css-patterns.md`.
    
    **For pages with 4+ sections** (reviews, recaps, dashboards), also read `./references/responsive-nav.md` for section navigation with sticky sidebar TOC on desktop and horizontal scrollable bar on mobile.
    
    **Choosing a rendering approach:**
    
    | Diagram type | Approach | Why |
    |---|---|---|
    | Architecture (text-heavy) | CSS Grid cards + flow arrows | Rich card content (descriptions, code, tool lists) needs CSS control |
    | Architecture (topology-focused) | **Mermaid** | Visible connections between components need automatic edge routing |
    | Flowchart / pipeline | **Mermaid** | Automatic node positioning and edge routing; hand-drawn mode available |
    | Sequence diagram | **Mermaid** | Lifelines, messages, and activation boxes need automatic layout |
    | Data flow | **Mermaid** with edge labels | Connections and data descriptions need automatic edge routing |
    | ER / schema diagram | **Mermaid** | Relationship lines between many entities need auto-routing |
    | State machine | **Mermaid** | State transitions with labeled edges need automatic layout |
    | Mind map | **Mermaid** | Hierarchical branching needs automatic positioning |
    | Data table | HTML `<table>` | Semantic markup, accessibility, copy-paste behavior |
    | Timeline | CSS (central line + cards) | Simple linear layout doesn't need a layout engine |
    | Dashboard | CSS Grid + Chart.js | Card grid with embedded charts |
    
    **Mermaid theming:** Always use `theme: 'base'` with custom `themeVariables` so colors match your page palette. Use `look: 'handDrawn'` for sketch aesthetic or `look: 'classic'` for clean lines. Use `layout: 'elk'` for complex graphs (requires the `@mermaid-js/layout-elk` package — see `./references/libraries.md` for the CDN import). Override Mermaid's SVG classes with CSS for pixel-perfect control. See `./references/libraries.md` for full theming guide.
    
    **Mermaid zoom controls:** Always add zoom controls (+/−/reset buttons) to every `.mermaid-wrap` container. Complex diagrams render at small sizes and need zoom to be readable. Include Ctrl/Cmd+scroll zoom on the container. See the zoom controls pattern in `./references/css-patterns.md` and the reference template at `./templates/mermaid-flowchart.html`.
    
    **AI-generated illustrations (optional).** If [surf-cli](https://github.com/nicobailon/surf-cli) is available, you can generate images via Gemini and embed them in the page for creative, illustrative, explanatory, educational, or decorative purposes. Check availability with `which surf`. If available:
    
    ```bash
    # Generate to a temp file (use --aspect-ratio for control)
    surf gemini "descriptive prompt" --generate-image /tmp/ve-img.png --aspect-ratio 16:9
    
    # Base64 encode for self-containment (macOS)
    IMG=$(base64 -i /tmp/ve-img.png)
    # Linux: IMG=$(base64 -w 0 /tmp/ve-img.png)
    
    # Embed in HTML and clean up
    # <img src="data:image/png;base64,${IMG}" alt="descriptive alt text">
    rm /tmp/ve-img.png
    ```
    
    See `./references/css-patterns.md` for image container styles (hero banners, inline illustrations, captions).
    
    **When to use:** Hero banners that establish the page's visual tone. Conceptual illustrations for abstract systems that Mermaid can't express (physical infrastructure, user journeys, mental models). Educational diagrams that benefit from artistic or photorealistic rendering. Decorative accents that reinforce the aesthetic.
    
    **When to skip:** Anything Mermaid or CSS handles well. Generic decoration that doesn't convey meaning. Data-heavy pages where images would distract. Always degrade gracefully — if surf isn't available, skip images without erroring. The page should stand on its own with CSS and typography alone.
    
    **Prompt craft:** Match the image to the page's palette and aesthetic direction. Specify the style (3D render, technical illustration, watercolor, isometric, flat vector, etc.) and mention dominant colors from your CSS variables. Use `--aspect-ratio 16:9` for hero banners, `--aspect-ratio 1:1` for inline illustrations. Keep prompts specific — "isometric illustration of a message queue with cyan nodes on dark navy background" beats "a diagram of a queue."
    
    ### 3. Style
    
    Apply these principles to every diagram:
    
    **Typography is the diagram.** Pick a distinctive font pairing from Google Fonts. A display/heading font with character, plus a mono font for technical labels. Never use Inter, Roboto, Arial, or system-ui as the primary font. Load via `<link>` in `<head>`. Include a system font fallback in the `font-family` stack for offline resilience.
    
    **Color tells a story.** Use CSS custom properties for the full palette. Define at minimum: `--bg`, `--surface`, `--border`, `--text`, `--text-dim`, and 3-5 accent colors. Each accent should have a full and a dim variant (for backgrounds). Name variables semantically when possible (`--pipeline-step` not `--blue-3`). Support both themes. Put your primary aesthetic in `:root` and the alternate in the media query:
    
    ```css
    /* Light-first (editorial, paper/ink, blueprint): */
    :root { /* light values */ }
    @media (prefers-color-scheme: dark) { :root { /* dark values */ } }
    
    /* Dark-first (neon, IDE-inspired, terminal): */
    :root { /* dark values */ }
    @media (prefers-color-scheme: light) { :root { /* light values */ } }
    ```
    
    **Surfaces whisper, they don't shout.** Build depth through subtle lightness shifts (2-4% between levels), not dramatic color changes. Borders should be low-opacity rgba (`rgba(255,255,255,0.08)` in dark mode, `rgba(0,0,0,0.08)` in light) — visible when you look, invisible when you don't.
    
    **Backgrounds create atmosphere.** Don't use flat solid colors for the page background. Subtle gradients, faint grid patterns via CSS, or gentle radial glows behind focal areas. The background should feel like a space, not a void.
    
    **Visual weight signals importance.** Not every section deserves equal visual treatment. Executive summaries and key metrics should dominate the viewport on load (larger type, more padding, subtle accent-tinted background zone). Reference sections (file maps, dependency lists, decision logs) should be compact and stay out of the way. Use `<details>/<summary>` for sections that are useful but not primary — the collapsible pattern is in `./references/css-patterns.md`.
    
    **Surface depth creates hierarchy.** Vary card depth to signal what matters. Hero sections get elevated shadows and accent-tinted backgrounds (`node--hero` pattern). Body content stays flat (default `.node`). Code blocks and secondary content feel recessed (`node--recessed`). See the depth tiers in `./references/css-patterns.md`. Don't make everything elevated — when everything pops, nothing does.
    
    **Animation earns its place.** Staggered fade-ins on page load are almost always worth it — they guide the eye through the diagram's hierarchy. Mix animation types by role: `fadeUp` for cards, `fadeScale` for KPIs and badges, `drawIn` for SVG connectors, `countUp` for hero numbers. Hover transitions on interactive-feeling elements make the diagram feel alive. Always respect `prefers-reduced-motion`. CSS transitions and keyframes handle most cases. For orchestrated multi-element sequences, anime.js via CDN is available (see `./references/libraries.md`).
    
    ### 4. Deliver
    
    **Output location:** Write to `~/.agent/diagrams/`. Use a descriptive filename based on content: `modem-architecture.html`, `pipeline-flow.html`, `schema-overview.html`. The directory persists across sessions.
    
    **Open in browser:**
    - macOS: `open ~/.agent/diagrams/filename.html`
    - Linux: `xdg-open ~/.agent/diagrams/filename.html`
    
    **Tell the user** the file path so they can re-open or share it.
    
    ## Diagram Types
    
    ### Architecture / System Diagrams
    Two approaches depending on what matters more:
    
    **Text-heavy overviews** (card content matters more than connections): CSS Grid with explicit row/column placement. Sections as rounded cards with colored borders and monospace labels. Vertical flow arrows between sections. Nested grids for subsystems. The reference template at `./templates/architecture.html` demonstrates this pattern. Use when cards need descriptions, code references, tool lists, or other rich content that Mermaid nodes can't hold.
    
    **Topology-focused diagrams** (connections matter more than card content): **Use Mermaid.** A `graph TD` or `graph LR` with custom `themeVariables` produces proper diagrams with automatic edge routing. Use `look: 'handDrawn'` for informal feel or `look: 'classic'` for clean lines. Use when the point is showing how components connect rather than describing what each component does in detail.
    
    ### Flowcharts / Pipelines
    **Use Mermaid.** Automatic node positioning and edge routing produces proper diagrams with connecting lines, decision diamonds, and parallel branches — dramatically better than CSS flexbox with arrow characters. Use `graph TD` for top-down or `graph LR` for left-right. Use `look: 'handDrawn'` for sketch aesthetic. Color-code node types with Mermaid's `classDef` or rely on `themeVariables` for automatic styling.
    
    ### Sequence Diagrams
    **Use Mermaid.** Lifelines, messages, activation boxes, notes, and loops all need automatic layout. Use Mermaid's `sequenceDiagram` syntax. Style actors and messages via CSS overrides on `.actor`, `.messageText`, `.activation` classes.
    
    ### Data Flow Diagrams
    **Use Mermaid.** Data flow diagrams emphasize connections over boxes — exactly what Mermaid excels at. Use `graph LR` or `graph TD` with edge labels for data descriptions. Thicker, colored edges for primary flows. Source/sink nodes styled differently from transform nodes via Mermaid's `classDef`.
    
    ### Schema / ER Diagrams
    **Use Mermaid.** Relationship lines between entities need automatic routing. Use Mermaid's `erDiagram` syntax with entity attributes. Style via `themeVariables` and CSS overrides on `.er.entityBox` and `.er.relationshipLine`.
    
    ### State Machines / Decision Trees
    **Use Mermaid.** Use `stateDiagram-v2` for states with labeled transitions. Supports nested states, forks, joins, and notes. Use `look: 'handDrawn'` for informal state diagrams. Decision trees can use `graph TD` with diamond decision nodes.
    
    **`stateDiagram-v2` label caveat:** Transition labels have a strict parser — colons, parentheses, `<br/>`, HTML entities, and most special characters cause silent parse failures ("Syntax error in text"). If your labels need any of these (e.g., `cancel()`, `curate: true`, multi-line labels), use `flowchart LR` instead with rounded nodes and quoted edge labels (`|"label text"|`). Flowcharts handle all special characters and support `<br/>` for line breaks. Reserve `stateDiagram-v2` for simple single-word or plain-text labels.
    
    ### Mind Maps / Hierarchical Breakdowns
    **Use Mermaid.** Use `mindmap` syntax for hierarchical branching from a root node. Mermaid handles the radial layout automatically. Style with `themeVariables` to control node colors at each depth level.
    
    ### Data Tables / Comparisons / Audits
    Use a real `<table>` element — not CSS Grid pretending to be a table. Tables get accessibility, copy-paste behavior, and column alignment for free. The reference template at `./templates/data-table.html` demonstrates all patterns below.
    
    **Use proactively.** Any time you'd render an ASCII box-drawing table in the terminal, generate an HTML table instead. This includes: requirement audits (request vs plan), feature comparisons, status reports, configuration matrices, test result summaries, dependency lists, permission tables, API endpoint inventories — any structured rows and columns.
    
    Layout patterns:
    - Sticky `<thead>` so headers stay visible when scrolling long tables
    - Alternating row backgrounds via `tr:nth-child(even)` (subtle, 2-3% lightness shift)
    - First column optionally sticky for wide tables with horizontal scroll
    - Responsive wrapper with `overflow-x: auto` for tables wider than the viewport
    - Column width hints via `<colgroup>` or `th` widths — let text-heavy columns breathe
    - Row hover highlight for scanability
    
    Status indicators (use styled `<span>` elements, never emoji):
    - Match/pass/yes: colored dot or checkmark with green background
    - Gap/fail/no: colored dot or cross with red background
    - Partial/warning: amber indicator
    - Neutral/info: dim text or muted badge
    
    Cell content:
    - Wrap long text naturally — don't truncate or force single-line
    - Use `<code>` for technical references within cells
    - Secondary detail text in `<small>` with dimmed color
    - Keep numeric columns right-aligned with `tabular-nums`
    
    ### Timeline / Roadmap Views
    Vertical or horizontal timeline with a central line (CSS pseudo-element). Phase markers as circles on the line. Content cards branching left/right (alternating) or all to one side. Date labels on the line. Color progression from past (muted) to future (vivid).
    
    ### Dashboard / Metrics Overview
    Card grid layout. Hero numbers large and prominent. Sparklines via inline SVG `<polyline>`. Progress bars via CSS `linear-gradient` on a div. For real charts (bar, line, pie), use **Chart.js via CDN** (see `./references/libraries.md`). KPI cards with trend indicators (up/down arrows, percentage deltas).
    
    ## File Structure
    
    Every diagram is a single self-contained `.html` file. No external assets except CDN links (fonts, optional libraries). Structure:
    
    ```html
    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>Descriptive Title</title>
      <link href="https://fonts.googleapis.com/css2?family=...&display=swap" rel="stylesheet">
      <style>
        /* CSS custom properties, theme, layout, components — all inline */
      </style>
    </head>
    <body>
      <!-- Semantic HTML: sections, headings, lists, tables, inline SVG -->
      <!-- No script needed for static CSS-only diagrams -->
      <!-- Optional: <script> for Mermaid, Chart.js, or anime.js when used -->
    </body>
    </html>
    ```
    
    ## Quality Checks
    
    Before delivering, verify:
    - **The squint test**: Blur your eyes. Can you still perceive hierarchy? Are sections visually distinct?
    - **The swap test**: Would replacing your fonts and colors with a generic dark theme make this indistinguishable from a template? If yes, push the aesthetic further.
    - **Both themes**: Toggle your OS between light and dark mode. Both should look intentional, not broken.
    - **Information completeness**: Does the diagram actually convey what the user asked for? Pretty but incomplete is a failure.
    - **No overflow**: Resize the browser to different widths. No content should clip or escape its container. Every grid and flex child needs `min-width: 0`. Side-by-side panels need `overflow-wrap: break-word`. Never use `display: flex` on `<li>` for marker characters — it creates anonymous flex items that can't shrink, causing lines with many inline `<code>` badges to overflow. Use absolute positioning for markers instead. See the Overflow Protection section in `./references/css-patterns.md`.
    - **Mermaid zoom controls**: Every `.mermaid-wrap` container must have zoom controls (+/−/reset buttons), Ctrl/Cmd+scroll zoom, and click-and-drag panning. Complex diagrams render too small without them. The cursor should change to `grab` when zoomed in and `grabbing` while dragging. See `./references/css-patterns.md` for the full pattern.
    - **File opens cleanly**: No console errors, no broken font loads, no layout shifts.
    

Comments (0)

Sign in to join the conversation.

No comments yet.

Reviews (0)

No reviews yet.

Related