Plan: Fix Markdown Mobile Overflow
Objective
Eliminate page-level horizontal overflow in the Markdown viewer on mobile while preserving readable tables, inline code, fenced code blocks, Mermaid diagrams, toolbar behavior, and desktop layout.
Evidence
The affected deployed page was tested at several viewport widths:
| Viewport | Document width | Result |
|---|---|---|
| 320 px | 569 px | Page-level horizontal overflow |
| 375 px | 569 px | Page-level horizontal overflow |
| 390 px | 569 px | Page-level horizontal overflow |
| 768 px | 768 px | No overflow |
The deployed stylesheet fingerprint matches the local app/static/viewer.css, so there is no deployment drift.
Root causes
1. Tables escape the article width
Markdown tables use width: 100%, but intrinsic column widths can force the rendered table beyond its container. On the inspected page, two of four tables overflow at mobile widths.
2. Long inline-code tokens cannot wrap
Inline values such as:
agents.list[].models["provider/model"].agentRuntime
have no natural break points. They expand list items and the article beyond the viewport.
Already working correctly
- Fenced code blocks use local horizontal scrolling.
- Mermaid diagrams are constrained to the content width and rendered as responsive static images.
- The toolbar title truncates with an ellipsis.
- The issue disappears at the 768 px viewport.
Implementation plan
Step 1 — Contain wide tables
Update app/static/viewer.css so Markdown tables:
- remain constrained to
max-width: 100%; - become their own horizontal scroll region when their columns need more space;
- retain the existing borders, cell padding, and semantic
<table>markup; - do not increase the width of the article or document.
The intended behavior is local table scrolling: users can swipe across a wide table without horizontally moving the entire page.
Step 2 — Allow prose tokens to break safely
Add narrowly scoped wrapping rules for:
- inline code outside
<pre>blocks; - long URLs or unbroken words in paragraphs and list items.
Use emergency wrapping only where necessary. Explicitly preserve the current behavior of fenced code blocks: they must remain unwrapped and horizontally scrollable.
Step 3 — Add regression coverage
Extend tests/test_viewer_css.py with focused assertions that verify:
- Markdown tables are width-constrained;
- tables provide local horizontal overflow;
- inline code permits emergency wrapping;
- fenced code blocks retain horizontal scrolling;
- Mermaid responsiveness rules remain unchanged.
Keep the renderer and sanitizer unchanged because this is a presentation-layer defect.
Step 4 — Run automated verification
Run the relevant viewer tests, followed by the complete suite:
python -m pytest tests/test_viewer_css.py tests/test_viewer_smoke.py
python -m pytest
Step 5 — Validate real layout behavior
Test a representative Markdown page containing:
- a three-column table with long cell content;
- long inline-code tokens in paragraphs and ordered lists;
- a wide fenced code block;
- a Mermaid diagram.
Check at 320, 375, 390, and 768 px in System, Light, and Dark themes.
Acceptance criteria
document.documentElement.scrollWidth === document.documentElement.clientWidthat 320, 375, and 390 px.- The page cannot be horizontally panned.
- Every table column remains reachable through table-local scrolling.
- Long inline code wraps without clipping or obscuring adjacent content.
- Long prose links and tokens cannot widen the document.
- Fenced code blocks remain horizontally scrollable and do not wrap.
- Mermaid diagrams and their source fallback remain contained.
- Toolbar behavior and title ellipsis remain unchanged.
- The 768 px and desktop layouts show no visual regression.
- Existing security boundaries, sanitizer behavior, CSP, and sandboxing remain unchanged.
Files expected to change
app/static/viewer.csstests/test_viewer_css.py
No template, Markdown renderer, sanitizer, JavaScript, API, storage, or MCP changes should be necessary.
Risk assessment
This is a low-risk CSS change. The main regression risk is accidentally wrapping fenced code or making tables compress into unreadable columns. The scoped selectors and viewport verification above directly cover those risks.