- layout: _PAD_BOTTOM 100→160, _PAD_LEFT 120→160 to prevent label clipping
- axes: fix _format_tick float-comparison bug (1.1→"1.1" not "1.10");
add auto-rotation for categorical x-axis labels when they overflow slot width
- engine: tick guard (>20 ticks falls back to nice_ticks); stacked_bar falls
back to bar instead of crashing; extend _find_date_column keywords
- series: bar width uses 25th-percentile gap instead of min to avoid invisible bars
- legend: line series use line swatch with dash pattern; proportional square size
- export: @font-face injected in HTML <head> for PDF to prevent T3Font in InDesign
- prompts: add categorical bar chart few-shot example; ban stacked_bar; improve
tick_interval guidance; add bar chart refine examples
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Issue 1 – Bar charts blank/lines only:
- Silent fall-through on unsupported chart_types (donut, stacked_bar, area)
now raises ValueError instead of producing axes-only output
- Zero-width bars on duplicate/single dates fixed via sorted-gap calculation
- Donut chart type added (ring with percentage labels)
- Pie/donut routing now triggers on any() instead of all()
Issue 2 – Axis controls not applying:
- AxisSpec gains date_min/date_max (x-axis clamping via prompts)
- y-bounds no longer silently widened when user sets min_val/max_val
- Tick clamping: ticks outside user range are dropped not widened
- New dual_y_axis layout with independent left/right Y-axes and y_axis_side per series
- Endpoint Y-axis labels (min/max) always render even when spacing is tight
Issue 3+4 – Font fallback & InDesign compatibility:
- Replace CairoSVG with Playwright/headless Chromium for PNG and PDF export
- Chromium honours @font-face base64 data URIs → Roboto Condensed in all exports
- PDF output contains embedded TTF subsets and real text operators (selectable
in InDesign/Illustrator, no path-outlining, consistent across regions)
- FastAPI lifespan manages persistent Playwright browser instance
Issue 5 – Stroke weight drift:
- All stroke_width values now carry explicit "px" unit suffix
- SVG root gets width="…px" height="…px" so 1 SVG px = 0.75 PDF pt exactly
AI improvements:
- Prompts document date_min/date_max, scale_kind, dual_y_axis, donut
- Rule 9 softened: user-specified ranges are honoured even if they crop data
- Refinement uses deep-merge so tick_interval/min_val/date_min are never
accidentally reset to None when Claude modifies unrelated fields
- New donut few-shot example added
Library upgrades: anthropic 0.84→0.97, fastapi 0.135→0.136,
pandas 3.0.1→3.0.2, pydantic 2.12→2.13, uvicorn 0.41→0.46;
cairosvg removed, playwright 1.58.0 added.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add RobotoCondensed-Bold.ttf and RobotoCondensed-Light.ttf; embed all three
weights (300/normal/bold) in SVG @font-face for correct browser preview
- Dockerfile: install fontconfig and register fonts as system fonts so
CairoSVG/Pango resolves Roboto Condensed in PNG/PDF exports (not a fallback)
- Export PNG/PDF at dpi=150 for higher quality output
- Add SVG <clipPath> per panel so data series cannot overflow axis boundaries
- Replace np.arange tick generation with safe while-loop (no float artifacts)
- Legend: multi-row wrapping when items exceed chart width; improved per-char
text width estimation; legend_row_count() helper for dynamic layout
- Dynamic pad_top in compute_layout() based on legend rows + subtitle presence,
preventing title/subtitle/legend overlap regardless of series count
- Y-axis: skip overlapping labels (gridlines always drawn); adaptive tick
precision so -0.0042% shows correctly instead of -0.00%
- transformer.py: strip % signs from string-formatted percentages before
pd.to_numeric; handle pandas 2.x StringDtype; expand date column detection
to cover Year, Quarter, report_date, substring matches (start_datetime etc.)
- Sync _find_date_column() in engine.py with transformer.py detection logic
- prompts.py: enforce Roboto Condensed for all text; add axis range, label
length, and decimal-percentage guidance rules
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- X-axis labels now rotate -90° when spacing < 96px, with overlap skipping
- Legend is horizontal (top-right) for line/bar charts, vertical (right) for pie
- Fix pie chart legend which previously showed nothing
- Set 15px outer image margins (blank whitespace around entire image)
- Add PNG and PDF export via cairosvg alongside SVG
- Add Download PNG and Download PDF buttons to preview template
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Wrap pd.to_datetime() in try-except in transformer.py to handle
non-standard strings like '*M 199901 Interpolate' that pandas 3.x
raises on even with errors="coerce"
- Fix 'int object has no attribute lower' in analyzer.py by using
str(col).lower() for numeric column names from Excel files
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- 10-color palette replacing old 5-color set
- Title 46pt bold, axis labels 42pt Roboto Condensed light (weight 300)
- Gridlines 2pt (#53565A), zero-axis 4pt, line weight 15pt
- Legend: vertical right-side layout with colored squares
- Right margin widened to 300px to accommodate legend
- Y-axis label auto-rotation when ticks are close together
- New pie chart renderer (app/renderer/pie.py) with SVG arc paths
- Font embedding updated with bold weight variant + synthesis note
- AI prompts updated with full 10-color palette (indices 0-9)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- msal_shell.html: show "Sign in with Microsoft" button on fresh load instead of auto-redirecting
- upload.html, preview.html: prefix HTMX POST paths with root_path to fix 404s under /Pimco-charts
- middleware.py: exempt /static/ paths from auth check so CSS/fonts load unauthenticated
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Azure AD redirect URI is registered as /Pimco-charts (no /auth/callback),
so handle the code exchange in the index route and exempt root with ?code= in middleware.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Azure AD authentication via MSAL PublicClientApplication with PKCE flow
- Session middleware, auth middleware, login/callback/logout routes
- Dockerfile, docker-compose.yml for port 8569, output volume
- Idempotent deploy.sh with static file copy and health wait
- User nav bar in base template with Sign Out link
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
AI-powered tool that generates publication-quality SVG charts matching
PIMCO's InDesign style. Upload Excel/CSV data, write a plain-English
brief, then iterate with natural language edits until the chart is
exactly right.
- Claude Opus 4.6 interprets briefs into structured ChartSpec JSON
- Deterministic SVG renderer via drawsvg (no visual hallucinations)
- Roboto/Roboto Condensed fonts base64-embedded in SVG
- FastAPI + HTMX web frontend with live preview
- Conversational refinement: "make lines thicker", "change title", etc.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>