# Adom Viewer

The Adom Viewer (AV) lets you send visual content from the Docker container to the Adom App front-end so the user can see it in their browser. Content appears in an iframe panel with tabs, dark theme, and auto-reconnecting WebSocket.

## Supported content types

| Type | Extensions / format | Notes |
|------|-------------------|-------|
| SVG | `.svg`, raw SVG markup | Vector graphics, diagrams, schematics |
| Images | `.png`, `.jpg`, `.jpeg`, `.gif`, `.webp` | Raster images |
| HTML | `.html`, `.htm` | Interactive HTML with `<script>` tags runs in an iframe |
| Markdown | `.md`, `.markdown` | Rendered client-side in the viewer |

## How to display content

### Option A: Display an existing file

Use the `av_display_file` MCP tool:

```
mcp__adom-viewer__av_display_file({ file_path: '/absolute/path/to/file.svg', title: 'My Diagram' })
```

This auto-detects the content type from the file extension.

### Option B: Display generated content

Use the `av_display` MCP tool:

```
mcp__adom-viewer__av_display({
  content_type: 'html_interactive',
  content: '<html>...</html>',
  title: 'My Visualization'
})
```

For images, provide a data URI: `data:image/png;base64,...`

### Option C: Internal HTTP API fallback

If MCP tools are not available, POST directly to the AV internal API:

```javascript
const http = require('http');
const crypto = require('crypto');

const payload = JSON.stringify({
  action: 'display',
  content: {
    contentType: 'svg',
    content: '<svg>...</svg>',
    title: 'My Diagram',
    id: crypto.randomUUID(),
    source: 'av_display',
    skill: 'av-creator',
    author: 'Your Name'
  }
});

const req = http.request({
  hostname: '127.0.0.1',
  port: 8771,
  method: 'POST',
  headers: { 'Content-Type': 'application/json' }
}, (res) => {
  let data = '';
  res.on('data', c => data += c);
  res.on('end', () => console.log(res.statusCode, data));
});
req.write(payload);
req.end();
```

The `source`, `skill`, and `author` fields appear in a tooltip when the user hovers over the tab. Always include them.

## MCP Tools

| Tool | Purpose |
|------|---------|
| `av_display` | Display generated content (HTML, SVG, markdown, images) |
| `av_display_file` | Display an existing file by path |
| `av_3d_display` | Display a GLB 3D model in the Babylon.js viewer |
| `av_symbol_3d_display` | Split-pane symbol SVG + 3D model |
| `av_library_review` | 3-pane library review (symbol + footprint + 3D) |
| `av_screenshot_paste` | Open clipboard screenshot paste utility |
| `av_file_explorer` | Browse files in the viewer |
| `av_symbol_prefs` | Configure symbol generation preferences |
| `av_clear` | Clear all displayed content |
| `av_status` | Check if the viewer is connected |
| `av_reload` | Force browser to reload the AV page (survives server restarts) |
| `av_capture` | Capture a screenshot of just the AV panel content |
| `av_tab_capture` | Capture full browser tab via Screen Capture API |
| `av_set_camera` | Set the 3D camera position |
| `av_set_view` | Set a named camera preset (front, back, top, etc.) |
| `av_set_bottom_light` | Toggle the bottom light for underside inspection |
| `av_stop_tour` | Stop the cinematic camera tour |

## Screenshot Paste

The `av_screenshot_paste` MCP tool opens an interactive paste widget in AV. Users paste screenshots from their clipboard and the system automatically:

- **Resizes** images to Claude's ideal 1568px max dimension (skips if already small enough — shows "Original still in clipboard")
- **Compresses** PNGs with sharp (level 9) for minimal file size
- **AI names** files via Haiku with descriptive kebab-case names including dimensions (e.g. `dart-green-line-route-editor-1568x975.png`)
- **Saves both** Claude-optimized and original versions to `screenshots/sp/`
- **Shows right-click copy hint** when clipboard write is unavailable (VS Code webview limitation) — auto-opens fullscreen preview with "Right-click → Copy image" for resized images

### Widget UX

- **Focus tracking**: Teal border + "READY FOR PASTE" label when focused. Click anywhere in the widget to focus.
- **Paste detection**: Immediate teal flash animation + status bar update on every paste event
- **Two-card UI**: Claude (resized) and Original side-by-side with click-to-preview
- **Smart badges**: "Original still in clipboard" (no resize), "Clipboard updated" (success), or "Right-click preview to copy" (resize + clipboard unavailable)
- **Tab icon**: Clipboard icon via `skill: 'screenshot-paste'` metadata

### Architecture

- Widget: `screenshot-paste.js` generates HTML served fresh via `GET /screenshot-paste`
- Rendering: Non-sandboxed `<iframe srcdoc>` with `allow="clipboard-write"`
- Storage: `project-content/screenshots/sp/` (isolated from avShot/tabShot/deskShot)
- Server: `handleScreenshot()` in `server.js` handles resize, sharp compression, save, AI naming via Haiku

## Management Relay (port 8772)

A separate lightweight server runs on port 8772, independent of the main AV server (8770/8771). The browser connects to BOTH WebSockets. This solves two problems:

1. **Forced reload after server restart** — when you restart the main AV server (for HTML/JS changes), the main WS breaks. The mgmt relay stays alive, so `av_reload` can tell the browser to reload.

2. **AI-initiated screenshot capture** — `av_capture` asks the browser to screenshot whatever it's showing and returns the image.

## Tab Capture (Screen Capture API)

`av_tab_capture` captures the **entire browser tab** as a pixel-perfect screenshot using the browser's Screen Capture API.

- `av_capture` — captures just the AV panel. Fast, no setup. But fails on multi-iframe layouts.
- `av_tab_capture` — captures the full browser tab. Works on all content including nested iframes. Requires one-time user setup.

**Setup:** Click the camera button in AV → opens the capture companion tab → click "Share This Tab" → select the IDE tab.

## 3D Model Display

Use `av_3d_display` to display GLB files in the built-in Babylon.js 3D view. Includes orbit camera, ground plane, skybox, and laser-etched chip markings.

`av_3d_display` blocks until the model is fully loaded (up to 15s). Call `av_capture` immediately after — no sleep needed.

### Camera controls

- `alpha` = azimuth (0 = front, π/2 = right side)
- `beta` = elevation (0 = top-down, π/2 = eye-level, π = bottom-up)
- `radius` = zoom multiplier
- Bottom light: illuminates underside for inspecting board pads and heatsink copper

## Adom Theme

All AV widgets MUST use the Adom theme (`viewer/adom-theme.js`).

### Key color tokens

| Token | Value | Usage |
|-------|-------|-------|
| `bg` | `#0d1117` | Page background |
| `bgSurface` | `#161b22` | Cards, panels |
| `border` | `#30363d` | Standard borders |
| `text` | `#e6edf3` | Primary text |
| `textSecondary` | `#8b949e` | Labels |
| `accent` | `#00b8b0` | Primary teal accent |
| `accentBright` | `#00e6dc` | Hover/focus |
| `success` | `#3fb950` | Success |
| `warning` | `#d29922` | Warning |
| `danger` | `#f85149` | Error |

## Ports

| Port | Purpose |
|------|---------|
| 8770 | HTTP server + WebSocket (public) |
| 8771 | Internal API (localhost only) |
| 8772 | Management relay (reload, capture) |
