---
name: svg-ui-panel-conventions
source: https://app.decimal.ai/s/svg-ui-panel-conventions@1/SKILL.md
source_sha256: f8b2ab120c4e
---

# SVG UI Panel House Style

## Contract
When you emit an SVG information panel (a list/table panel, a task checklist, a
pipeline/dependency status diagram, or a rich-text report layout), every numeric
constant and hex code below is **fixed**. Do not substitute "equivalent" values,
near-shades, or system defaults — the house style is the deliverable.

## Rules (the complete spec)

### R1 — Canvas
- Root element is `<svg viewBox="0 0 1200 H" ...>`. The viewBox **width is always
  1200** (landscape, ~16:9). Only the height `H` varies with content.
- Outer content margin is **40px** on all sides.

### R2 — Font
- Every `<text>` carries, in this exact order:
  `font-family="'Inter','Helvetica Neue','Microsoft YaHei',sans-serif"`.
- Never reorder, never drop a face, never substitute Arial / Roboto / Helvetica
  alone / system-ui. The `'Microsoft YaHei'` fallback is what renders CJK on
  Windows — dropping it is a bug, not a simplification.

### R3 — Status colors (exact hex, by meaning)
| Meaning | Hex |
|---|---|
| done / success / pass / healthy | `#43A047` |
| in-progress / warning / running / degraded / pending-review | `#FF8F00` |
| not-started / neutral / disabled / pending / todo / off | `#90A4AE` |
| error / failed / blocked / down | `#E53935` |
| info / highlighted metric / KPI accent | `#1565C0` |

Pick the color by the item's *meaning*, never by aesthetic preference. A "done"
item is `#43A047`; a "failed" stage is `#E53935`; a "not started" item is
`#90A4AE`.

### R4 — Header band color (per template)
The title band at the top of each panel uses a fixed deep accent per template:
| Template | Header hex |
|---|---|
| list-panel | `#1A237E` (Indigo) |
| checklist-panel | `#004D40` (Teal) |
| pipeline-status | `#311B92` (Deep Purple) |
| richtext-layout | `#263238` (Blue Grey) |

### R5 — Shadow
- Define `<filter id="cardShadow">` **once** inside `<defs>`.
- Every card/panel `<rect>` references it via `filter="url(#cardShadow)"`. No card
  ships without the shadow; there is exactly one filter, reused.

### R6 — Row spacing
- **list-panel** rows stack with a **+56px** vertical y-offset per row.
- **checklist-panel** rows stack with a **+60px** vertical y-offset per row.
- These two numbers are different on purpose; do not unify them.

### R7 — Corner radius
- Large cards/panels: `rx="8"`.
- Small elements (chips, status boxes, inline tags): `rx="4"`–`rx="6"`.
- Pill buttons: `rx` = half the element height (a full capsule).

### R8 — Text size hierarchy
- Panel title: `font-size="20"` bold.
- Section/column heading: `font-size="14"`–`16` bold.
- Body text: `font-size="13"`.
- Annotation/footnote: `font-size="11"`–`12`.

### R9 — Checklist state glyphs
Each checklist item shows a leading status box plus styled text:
- done: green (`#43A047`) **filled** box + **strikethrough** label.
- in-progress: amber (`#FF8F00`) border + light highlight behind the label.
- todo/not-started: grey (`#90A4AE`) **empty** box.
- blocked: red (`#E53935`) **dashed** border + red-tinted row background.

### R10 — PNG conversion
- Rasterize with cairosvg at **`output_width=2400`**:
  `python3 -c "import cairosvg; cairosvg.svg2png(url='in.svg', write_to='out.png', output_width=2400)"`

## Worked examples (before → after)

**R1 Canvas** — base picks an arbitrary width.
- BEFORE: `<svg viewBox="0 0 800 400">`
- AFTER: `<svg viewBox="0 0 1200 400">`

**R2 Font** — base reaches for Arial.
- BEFORE: `<text font-family="Arial, sans-serif">Build</text>`
- AFTER: `<text font-family="'Inter','Helvetica Neue','Microsoft YaHei',sans-serif">Build</text>`

**R3 Status color** — base uses Material's default green `#4CAF50`.
- BEFORE: `<circle cx="1120" cy="50" r="8" fill="#4CAF50"/> <!-- done -->`
- AFTER: `<circle cx="1120" cy="50" r="8" fill="#43A047"/> <!-- done -->`

**R3 Info accent** — base colors a KPI the same green as "done".
- BEFORE: `<rect ... fill="#43A047"/> <text>Revenue $4.2M</text>`
- AFTER: `<rect ... fill="#1565C0"/> <text>Revenue $4.2M</text>` (KPI = info blue)

**R4 Header band** — base uses one neutral header everywhere.
- BEFORE (a pipeline panel): `<rect x="0" y="0" width="1200" height="72" fill="#333"/>`
- AFTER: `<rect x="0" y="0" width="1200" height="72" fill="#311B92"/>` (pipeline = Deep Purple)

**R5 Shadow** — base draws flat cards.
- BEFORE: `<rect x="20" y="20" width="1160" height="60" fill="#fff"/>`
- AFTER:
  ```svg
  <defs><filter id="cardShadow"><feDropShadow dx="0" dy="2" stdDeviation="3"/></filter></defs>
  <rect x="20" y="20" width="1160" height="60" fill="#fff" filter="url(#cardShadow)"/>
  ```

**R6 Row spacing** — base eyeballs ~50px between rows.
- BEFORE (list): row1 `y="120"`, row2 `y="170"` (+50).
- AFTER (list): row1 `y="120"`, row2 `y="176"` (+56). Checklist would be +60.

**R7 Corner radius** — base leaves rects sharp.
- BEFORE: `<rect ... />` (no rx)
- AFTER: `<rect ... rx="8"/>` for a card; `rx="4"` for an inline status chip.

**R8 Text sizes** — base uses one font size for everything.
- BEFORE: title and body both `font-size="14"`.
- AFTER: title `font-size="20"` bold, body `font-size="13"`.

**R9 Checklist glyph** — base just colors the text and skips the box.
- BEFORE: `<text fill="#43A047">Build image</text>`
- AFTER:
  ```svg
  <rect x="40" y="100" width="18" height="18" rx="4" fill="#43A047"/>
  <text x="68" y="114" text-decoration="line-through" font-family="'Inter','Helvetica Neue','Microsoft YaHei',sans-serif">Build image</text>
  ```

**R10 PNG** — base downsizes for messaging.
- BEFORE: `cairosvg.svg2png(url='in.svg', write_to='out.png', output_width=800)`
- AFTER: `cairosvg.svg2png(url='in.svg', write_to='out.png', output_width=2400)`

## Edge cases & exceptions
- **Mixed states in one panel:** color each element by its own meaning. A
  checklist with done + blocked + todo items uses `#43A047`, `#E53935`, and
  `#90A4AE` in the same panel — never one color for the whole panel.
- **"Pending review" vs "not started":** pending-review is *active waiting* →
  amber `#FF8F00`. Not-started is *untouched* → grey `#90A4AE`. They are
  different states, different colors.
- **Tall content overflowing the default height:** grow `H` in the viewBox; never
  shrink width below 1200 to "fit" — width is locked.
- **A pipeline status that is both running and at-risk:** status color tracks the
  execution state (running → `#FF8F00`); the risk goes in a separate `RISK_NOTE`,
  not by recoloring the node red.
- **Metrics/KPIs are not statuses:** a highlighted number uses info blue
  `#1565C0`, not the green success color, even when the number is "good".

## Do / Don't
- DON'T set viewBox width to 800/1000/anything. ALWAYS `1200`.
- DON'T write `font-family="Arial"`. ALWAYS the full 4-face stack in order.
- DON'T use `#4CAF50`/`#F44336`/`#9E9E9E` (Material defaults). ALWAYS the house
  hex `#43A047`/`#E53935`/`#90A4AE`.
- DON'T color a KPI with the success green. ALWAYS info blue `#1565C0` for metrics.
- DON'T draw flat cards. ALWAYS one `<filter id="cardShadow">` + `filter="url(#cardShadow)"` on each card.
- DON'T reuse +56 for checklists. ALWAYS +56 list / +60 checklist.
- DON'T give every template the same header color. ALWAYS the per-template accent.

## Common mistakes (base defaults to watch)
- Defaulting viewBox to `0 0 800 600` or the content's natural size.
- Emitting `font-family="Arial, sans-serif"` or `"Helvetica, sans-serif"`.
- Reaching for Material's `#4CAF50` (green) / `#FFC107` (amber) / `#F44336` (red)
  instead of the house `#43A047` / `#FF8F00` / `#E53935`.
- Skipping the drop-shadow filter entirely (flat rects).
- Using one row pitch for both list and checklist panels.
- Coloring metric/info accents with the success green.

## Quick checklist
- [ ] `viewBox="0 0 1200 H"` (width 1200)
- [ ] every `<text>` → the exact 4-face font stack
- [ ] status hex by meaning: `#43A047` / `#FF8F00` / `#90A4AE` / `#E53935`; info `#1565C0`
- [ ] header band color matches the template
- [ ] one `<filter id="cardShadow">`, applied to every card
- [ ] list rows +56px, checklist rows +60px
- [ ] rx=8 cards / rx=4–6 small / pill = half-height
- [ ] PNG via cairosvg `output_width=2400`
