# Design Decisions Log

A running record of intentional design choices, rule changes, and component philosophy shifts.
Entries are ordered newest-first. Each entry records what changed, why, and how to apply it.

---

## 2026-05-22 — Agents may generate scientific visuals with domain renderers

Downstream agents using the design system may have enough local context to generate real scientific visuals, not just arrange provided images. This is desirable when the visual has a canonical domain renderer. A report agent generated 2D molecular structures server-side with RDKit from SMILES, computed 2D coordinates, rendered inline SVG, and embedded the SVG directly in the HTML. That was the right choice: the report stayed self-contained, print-safe, and scientifically faithful without shipping a large client-side renderer.

### Rule

- Prefer trusted domain renderers over hand-drawn approximations for scientific visuals when structured input is available.
- For 2D chemical structures, RDKit/OpenBabel/Indigo/ChemDraw/Ketcher-style renderer output is content. Inline SVG from RDKit is a strong default for static reports with dozens of molecules.
- Element-colored CPK/Jmol output and black-and-white publication-style renderer output are both valid. Do not post-process rendered atom/bond colors into Fractal tokens.
- Apply Fractal styling to the surrounding container, caption, table, card, or report layout, not to the scientific content inside the rendered structure.

### How to apply

See `data-visualization/data-visualization-guide.md` for the domain-generated scientific visuals rule and `color/color-guide.md` for the hard rule against recoloring 2D chemical structure drawings.

---

## 2026-05-22 — Report geometry and table chrome must read as intentional

Summary-layout v5 exposed three polish failures that were all alignment issues: an SVG mechanism arrow crossed its `MAPK off` label, a framed table header left an unpainted strip above its grey band, and a data table showed internal dividers without an outer perimeter. These are not content errors; they make otherwise useful reports feel mechanically generated.

### Rule

- SVG diagrams must be collision-free. Connectors, arrowheads, labels, and node boundaries need visible clearance; no line should pass through text.
- Painted header bands inside framed cards/tables must fill the top of the container edge-to-edge. Use padding inside the band and reset heading/paragraph margins.
- Data tables need a 1px `--border-subtle` external perimeter around the table or scroll wrapper, plus internal row/column dividers. "Line-separated, never boxed" applies to rows and cells, not to the table's outer boundary.

### How to apply

See `data-visualization/data-visualization-guide.md` and `layout/summary-layout-guide.md` for SVG geometry rules. See `components/component-guide.md` for table perimeter and framed header-band rules.

---

## 2026-05-22 — Low-level tinted surfaces need containment; dense data marks may stay subtle

Tinted UI/report surfaces using a chromatic `50` or `100` background need a tone-matched `200` border. A pale yellow callout on the page canvas and a neutral card nested inside a blue-50 region both failed to read as distinct surfaces during summary-layout eval review. The fix is a color-system rule, not a one-off layout patch: low-level chromatic surfaces need visible containment.

Dense data visualization is the exception. Heatmaps, incidence matrices, distribution bins, and other compact quantitative encodings often need many subtle hierarchy levels. Low-contrast adjacent color steps are useful there because they preserve quantitative rank without overpowering labels. Do not force borders around every dense data mark.

### Rule

- Standalone UI/report surfaces using chromatic `50` or `100` fills get a 1px border from the same scale's `200` stop.
- Neutral/white cards nested on tinted `50`/`100` canvases need stronger contrast or an explicit border.
- Dense data marks may use subtle adjacent low-level stops without borders when those stops encode quantitative rank.
- Chromatic ramps should use real palette stops. Do not treat plain white as a fake first chromatic bucket; start the lowest chromatic bucket at the `50` stop and use `100` for low nonzero values.

### How to apply

See `color/color-guide.md` for the canonical surface-separation rule and `data-visualization/data-visualization-guide.md` for the dense quantitative hierarchy exception.

---

## 2026-05-11 — Two-accent system: blue primary, orange secondary; charts single-color by default

The page uses exactly two chromatic accents to express rank. **Blue (`--blue-500` family) marks the primary thing** — the headline finding, the winning entity, the load-bearing inline phrase, the lead asset. **Orange (`--orange-500` family) marks the secondary thing** — the comparator next to a primary entity, a runner-up metric, a callout that supports rather than carries the headline. Everything else stays in greyscale.

### What triggered this

Early v2 outputs treated blue as the only accent. Comparison pages (2 methods, 2 species, 2 drugs) read with the comparator either tinted blue (same color as the primary, confusing) or left on canvas (no visual distinction at all). Charts that were genuinely comparisons (drug A vs drug B PK overlay) used grey + blue, which at thumbnail scale collapsed to "one prominent line and one faint line" — not "two things being compared."

orange was already declared as the system's secondary highlight in `philosophy.md` line 169, but no rule said *when* to use it. This entry makes that rule explicit and ties it to comparison semantics.

### Rule

- **Blue = primary.** Use `--blue-500` (and the `--blue-50` / `--blue-100` / `--blue-200` family) for the single most important thing in a region: the page's headline finding, the lead entity's tile or row, the load-bearing inline phrase. Max one blue accent per visible region; max two on the page total.
- **Orange = secondary.** Use `--orange-500` (and the `--orange-50` / `--orange-100` / `--orange-200` family) for the second-rank thing — the comparator in a comparison, a runner-up metric, a complementary call-out. Max one orange accent per visible region. Never use orange as decorative variety when there is no second-rank thing.
- **Comparisons (2 entities) use blue + orange.** When the page exists to compare two things — two methods, two drugs, two species, two cohorts — one entity gets blue tinting and the other gets orange tinting (50 bg, 100 head, 500 lead values). Blue is the primary / lead / winner / recommended / treatment arm; orange is the comparator / control / competitor. The asymmetry IS the visual encoding; reversing it because both entities feel "equal" defeats the point.
- **Charts default to a single color.** A bar chart, a dose-response curve, a heatmap, a distribution — one color across all points (light grey from the `--grey-200`–`--grey-400` range, with the page-level accent on a single highlighted point). Reach for blue OR orange only when the chart *is* a comparison or categorical differentiation (drug A vs drug B PK overlay, treatment vs control). In those cases use blue for the primary series and orange for the secondary series; never two greys for two series — at thumbnail scale the reader can't tell them apart.
- **Thumbnail test.** A page should read as mostly grey with at most one blue moment and one orange moment visible at a time. Two blues or two oranges in the same viewport means one of them is decorative — strip it.

### How to apply

- Always assign blue first. If you find yourself adding orange before blue, the page has no primary thing — fix that, not the color.
- Don't tint the primary column in blue *and* call out a value inside it in blue too — that's double-emphasis on the same thing. The column tint already encodes "this is primary."
- For status meanings (success / warning / error), the green / yellow / red status palette still governs — orange is *not* a status color, it's the secondary emphasis color. Don't use orange for warning chips (use yellow per the Status accent pattern in `philosophy.md`).

---

## 2026-05-11 — Layout follows content, not the report-type label

A summary website's layout should be chosen based on what the reader needs to **do** on the page — compare, scan, follow a sequence, find a single fact, read narrative — not based on the prompt's stated `expected_report_type` or the source format. The dataset's report-type field is a hint, not a binding.

### What triggered this

The v1 eval outputs in `evals/pipelines/summary-layout/outputs/v1/` all reduced to the same shell — left outline rail + center body + sometimes a resources rail on the right — regardless of whether the prompt was a paper summary, a clinical trial readout, a market landscape, or a recipe. The v1 scoring flagged **structural variety** (3.60) and **aesthetic fit** (3.60) as the two weakest dimensions. The cause was upstream: there was no guidance telling generators that different content shapes should look fundamentally different.

A first attempt to fix this with a closed taxonomy of 8 fixed templates was rejected as too rigid — it would re-create the same-skeleton problem in a different form. The fix is a **device vocabulary**, not a template list.

### Rule

- Read `layout/summary-layout-guide.md` before composing any summary website. It defines the layout principles, the device palette (~9 visually distinct primitives — prose-with-inline-figures, KPI tile grid, chart cluster, sticky infobox, wide comparison table, 2D positioning chart, parallel columns, timeline rail, structure gallery), and a handful of illustrative archetype compositions.
- Compose **2–4 devices** per page: one hero that the reader's eye lands on first, plus supporting devices below.
- Do not default to the v1 "left outline + center body + right rail" shell unless the content genuinely calls for prose-with-inline-figures (a long-form paper summary). The outline rail decision below still applies.
- Vary across outputs in a batch. If your last three outputs all reduced to the same shell, the fourth probably shouldn't.

### How to apply

- When generating a new summary website, first identify the reader's primary job (compare? scan? sequence? lookup? read?) — not the report-type label.
- Pick the hero device from the palette that best serves that job.
- Compose 1–3 supporting devices around the hero. Confirm against the anti-patterns section in `summary-layout-guide.md` (no hero competition, no skeleton mismatch, no device stacking without intent).
- Cell-level rules (Visual Hierarchy in `philosophy.md`, Cell Roles in `components/component-guide.md`) still apply unchanged *inside* every device.

---

## 2026-05-11 — Outline / table-of-contents sidebar: only on long pages

A left-rail outline navigation (anchored links to in-page sections, like the Elsevier-style outline on a journal article page) is only justified when the page is long enough that a reader genuinely needs jump-to-section help.

### Rule

- **Default: no outline rail.** Most pages — including most Axon summary websites — fit in a single screen or scroll comfortably enough that the rail adds chrome without value.
- **Add an outline rail** only when the page has roughly **six or more substantive sections** AND total length significantly exceeds the viewport (multiple screens of scrolling). A literature review of a long primary research paper qualifies; a one-page report of three findings does not.
- The rail must be in-page navigation (anchored links to sections), not a global site nav. If you find yourself adding global nav buttons to it, the rail is doing the wrong job — remove it.

### How to apply

- When generating a new summary website, first draft the body. Then decide: would a reader scroll past content they want to come back to? If yes, add the rail. If no, leave the page as a centered single-column read.
- When the rail is present, it owns one job — page navigation. Do not bolt unrelated affordances onto it (see the "don't mirror source-format chrome" decision below).

---

## 2026-05-11 — Don't fabricate resource existence in generated summaries

When generating a summary website from a source paper, every linked resource (paper PDF, code repo, dataset, supplementary materials, related work) must correspond to a verified artifact. Do not invent affordances on the assumption that "papers of this type usually have X."

### What triggered this

The ComDock literature-summary testing page asserted in five different places that the paper had a public MIT-licensed code release — a "Find code" button, a "Reference implementation" card, an "Open source" chip, a highlight bullet, and a "Code released: Yes" metric — without any evidence the release existed. The user called this out: "what does the Find code button even do? there is no code to find."

### Rule

- Do not add resource-affordances (links, buttons, cards, chips, metrics) for artifacts whose existence has not been verified against the source. "Computational papers usually release code" is not verification.
- If a resource's existence is genuinely uncertain, **omit the affordance** rather than pointing it at a search URL or a plausible-looking placeholder repo.
- Claims propagate. If you mention an artifact in the highlights, expect to see it surface in the chip strip, the resources grid, and the right-rail metadata. When the claim is removed from one place, strip every other place it appears.

---

## 2026-05-11 — Don't mirror source-format chrome in summary websites

When the source material is a journal article, GitHub README, or other published website, do not copy that page's chrome into the Axon summary just because it looks like part of the format. Each affordance must justify itself in the actual reading context — HTML in a browser, no logged-in account ecosystem.

### What triggered this

The ComDock testing page initially had a left-rail "Actions" block with Save / Share / Cite buttons, copied from the Elsevier article-page convention. None of them survived scrutiny:

- **Save** — save to where? Axon has no save store, and browsers bookmark.
- **Share** — sharing what? The URL is the share mechanism.
- **Cite** — ambiguous (cite the summary or the paper?), and if the latter, citation belongs adjacent to the paper info, not a freestanding left-rail button.

### Rule

- Before adding any button/action to a generated summary, ask: in the reader's context, what does this actually do? If the answer is "duplicates browser-native behavior" or "nothing meaningful," drop it.
- Toolbar-style chrome (Save / Share / Cite / Bookmark / Print / Export) copied from publisher templates is almost always wrong — most of it presumes a logged-in account ecosystem the summary does not live in.
- Place citation/export affordances next to the thing being cited or exported (e.g., a "Copy citation" button beside the paper metadata in the right rail), not as a freestanding left-rail toolbar.

---

## 2026-05-11 — Cards convey information; buttons carry the action verb

In a resource grid (or any card that points to an external artifact), the **card** describes what the resource is and the **button** inside it carries the action.

### Rule

- **Card title** = noun, what the resource is. "ComDock — full article", "Supplementary materials", "ENCODE dataset". Not "Read the paper", "Download data", "Open dataset".
- **Card description** = one or two lines of substantive context — journal/volume, what's in the artifact, license, size, etc. Not an instruction.
- **A `<Button>` inside the card** carries the action verb: "Read paper", "Download CSV", "Open on ScienceDirect". This is the visible "pressable" affordance.
- The whole card MAY be clickable as a convenience (with `role="link"` for accessibility and a hover background shift), but the button is the unambiguous cue. The button's onClick must `stopPropagation` so a button click doesn't double-fire the card's handler.

### Why

A card whose title is an imperative ("Read the paper") collapses the information and the action onto a single signal, so the reader can't see *what* the resource is without committing to the action. Splitting them lets the reader scan card content (assess relevance) and then commit (click the button) as two distinct moves. It also keeps button styling — the only element in the design system that explicitly signals "press me" — as the singular affordance for action.

### Reference implementation

See `ResourceCard` helper in `src/testing-pages/TestingPages.stories.tsx` (the ComDock literature summary). The same pattern should be used for any card-and-resource grid in a generated summary.

---

## 2026-05-11 — Testing Pages use case: Axon summary websites

The full-page layouts under `Testing Pages` in Storybook (SAR Report, Compound Efficacy Report, Clinical Trial Dashboard, etc.) are reference designs for a specific Axon output format: the **summary website**.

### What this format is

When a user asks Axon to *condense, summarize, compile, distill, brief, or report on* a body of source material — e.g.:

- A research paper or preprint (PDF, arXiv, bioRxiv)
- A journal article or literature set (PubMed, Nature, Cell, etc.)
- A public website or documentation site
- A GitHub repository or its README/wiki/pages
- Patent filings, clinical trial registries, internal lab notebooks
- A multi-source synthesis across any combination of the above

…the deliverable is a **standalone interactive website**, not a Markdown document, slide deck, or static PDF. The testing pages are the visual reference for what that website looks like — components, layout density, hierarchy, chart treatment, and chrome.

### Why a website (not a doc or PDF)

- **Interactivity is the differentiating value.** A summary that the reader can drill into beats a summary that is fixed. Charts reveal underlying values on hover. Tables expose row detail on click. Citations open the source in context.
- **Hyperlinks make the summary a navigation surface back to the primary literature**, not a replacement for it. Every claim should be traceable.
- **Progressive disclosure** lets the same page serve the skim-reader and the deep-reader simultaneously — the headline is on the surface, the supporting data is one interaction away.

### Required ingredients

Every Axon summary website must include:

1. **Clear visual hierarchy** — section labels, headings, body, metadata follow the type tier system. The reader can find the key finding in under five seconds.
2. **Key information surfaced first** — a header with title + authors/source + key metrics as stat panels (IC₅₀, n=, p-value, etc.) before any narrative prose.
3. **Hyperlinks throughout** — every cited paper, dataset, repository, compound ID, gene/protein name, or external resource is a link. Inline links use the standard link treatment; "explore further" actions use buttons.
4. **Interactive graphs and tables**:
   - Charts: hover reveals exact values, series labels, and units; click (where appropriate) drills to underlying data or filters peer charts.
   - Tables: rows are hoverable for emphasis and clickable to expand into per-row detail or open the cited source.
5. **Resource links and downloads** — PDFs of source papers, raw data files, supplementary materials, related GitHub repos, and follow-on reading are linked as buttons or a sidebar resource list.
6. **A traceable source list** — every input the summary was built from is enumerated at the bottom (or in a sidebar) with a permanent link.

### Visual constraints

- Use the existing component library only — no new component patterns introduced ad hoc per report.
- Follow the cascade: every section conforms to `philosophy.md` (border-first, 1px strokes, greyscale-with-targeted-accent, no decorative gradients).
- Color is used to *direct attention*, not to decorate. A summary website that reads as colorful is wrong; one that reads as quiet greyscale with a few precise accents is right.
- Density is **comfortable**, matching the testing pages — not dashboard-tight, not marketing-airy.

### How to apply

- When adding a new testing page, treat it as a candidate Axon output: pick a realistic source-material scenario (paper, repo, lit set) and design the summary website you would want to receive.
- When the design system gains a new component, audit the testing pages and add it where it would have been used had it existed — the pages must stay in sync with the library.
- When Axon generates a summary website at runtime, it should look indistinguishable in style from the testing pages. The testing pages are the contract.

---

## 2026-05-07 — Cards are separators, not wrappers

Cards (border + background) exist to visually separate discrete, peer-level content blocks — not to wrap every section of a page for decoration. Normal layout cards stay flat; shadows are reserved for floating UI such as menus, popovers, tooltips, and modals.

### Rule

- **Use a card** when the content is a self-contained unit that needs visual separation from adjacent peer content: stat panels, chart containers, data tables, feature summaries in a grid.
- **Do not use a card** for flowing prose that belongs to the page's natural reading order: abstracts, introductions, body copy, section descriptions. These sit directly on the canvas (`--bg-canvas`) with only typographic hierarchy to separate them from what comes before.

### Test

Ask: *would removing the card border and background make this content harder to distinguish from adjacent content?* If yes, keep the card. If the content is already separated by whitespace, a section label, and reading flow — drop the card.

### Examples

| Content | Card? |
|---|---|
| Abstract / introduction paragraph | No — flows with the page |
| Stat metric (IC₅₀, enrollment count) | Yes — peer panel in a grid |
| SVG chart or data table | Yes — distinct content block |
| Section body copy below a heading | No — typographic hierarchy is enough |
| Safety summary (dose mod, SAE count) | Yes — discrete peer item in a grid |

---

## 2026-05-07 — Chemical structure rendering is semantic, not stylistic

2D chemical structures (ChemDraw, Ketcher, RDKit, or any SMILES/MOL renderer output, or hand-drawn SVGs) are content, not styling. Element-colored structures use the **CPK/Jmol convention** to encode atomic identity. Black-and-white publication-style structures are also valid chemical renderer output. Treat both with the same fidelity as axis labels on a chart — altering them after rendering changes or degrades meaning.

### Hard rules

- **Never** change the element-to-hue mapping to match a theme, brand palette, dark mode, or contrast preference.
- **Never** desaturate, invert, monochrome, or "tone down" an already-rendered structure for visual harmony.
- **Never** apply CSS filters (`filter`, `mix-blend-mode`, `invert()`, `hue-rotate()`) to elements containing rendered structures.
- If a structure renderer exposes a color theme config (e.g. Ketcher's `atomColoring`, RDKit's `MolDrawOptions`), use either the renderer's standard CPK/Jmol element palette or its standard black-and-white publication mode. Do not override per-element with Fractal colors.

### Bond coloring rule (hand-drawn SVGs)

Bond lines connecting to a heteroatom take the CPK color of that heteroatom. This is the standard behavior of ChemDraw, Ketcher, and MarvinSketch in element-color mode.

| Bond type | Line color |
|---|---|
| C–C | `var(--fg-primary)` (dark) |
| C–N | `#3050F8` (blue) |
| C–O | `#FF0D0D` (red) |
| C–F | `#90E050` (green) |
| C–Cl | `#1FF01F` (green) |
| C–S | `#FFFF30` (yellow) |
| C–Br | `#A62929` (dark red) |
| N–C=O (amide) | exocyclic C=O double bond → red; ring N–C bonds → blue |

Apply this in SVG by giving each `<line>` its own `stroke` attribute (not a group-level stroke). Place a white `<rect>` under each heteroatom label so the colored bond line does not visually bleed through the text. Aromatic C–C bonds in a benzene ring remain dark; indicate aromaticity with an inner `<circle>`.

### The mapping (Jmol convention)

| Element | Color | Hex |
|---|---|---|
| C | dark gray / near-black | `#222` (light bg) / `#DDD` (dark bg) |
| H | white / light gray | `#FFF` / `#E0E0E0` |
| N | blue | `#3050F8` |
| O | red | `#FF0D0D` |
| S | yellow | `#FFFF30` |
| P | orange | `#FF8000` |
| F | green | `#90E050` |
| Cl | green | `#1FF01F` |
| Br | dark red / brown | `#A62929` |
| I | dark purple | `#940094` |
| B | salmon | `#FFB5B5` |
| Si | tan | `#F0C8A0` |
| Metals | per Jmol table | — |

### Dark mode

Carbon and hydrogen are the only atoms whose luminance may shift between light and dark backgrounds (carbon: dark on light, light on dark). All other element hues remain fixed. You may marginally increase saturation or brightness on dark backgrounds for legibility, but the **hue must not shift** — red stays red, blue stays blue. Oxygen never becomes pink. Nitrogen never becomes cyan.

### What you may style freely

- The container, panel, background, border, and chrome around the structure
- Selection highlights, hover states, focus rings (use accent colors here, not on atoms)
- Toolbar, controls, labels *outside* the structure canvas
- Bond stroke width and atom label font, within the renderer's supported config

### When in doubt

Ask before touching any color inside a structure renderer. Defaulting to "leave it alone" is correct.

---

## 2026-05-07 — Clinical Trial Dashboard: safety summary cards use FeatureCard component

**What changed:**
The three safety summary cards in the `ClinicalTrialDashboard` testing page (Dose Modifications, Grade 3 SAEs, No Treatment Deaths) were previously rendered as `<Alert>` components. They are now rendered using `<FeatureCard>` with Carbon icons (`Information`, `Warning`, `CheckmarkFilled` at 24px).

**Why:**
`Alert` is a compact banner pattern suited for inline notifications — colored backgrounds, small icon circles, tight padding. These three items are equal-weight dashboard summaries in a 3-column grid; they read as content panels, not system messages. `FeatureCard` gives them the correct treatment: white/neutral background (`--bg-canvas`), `--border-subtle` border, `--radius-xl`, generous padding (40px), icon stacked above title, and secondary-colored description — matching the component library's card visual language rather than the alert visual language.

**Rule — Alert vs. FeatureCard in dashboards:**
- Use `<Alert>` for inline system feedback: form validation, operation results, status banners that appear contextually.
- Use `<FeatureCard>` (or `<Card>`) for any content panel that lives as a peer in a grid — summaries, key findings, category tiles.
- Never use `<Alert>` colored variants purely for visual grouping in a dashboard grid.

---

## 2026-05-07 — Badge: greyscale-first + mono chip variant

**What changed:**
- `Badge` default theme is now `neutral` (light grey background, `--bg-surface-1`, with a `--border-subtle` outline).
- Added `font="mono"` prop. When set, the badge renders in Geist Mono at 11px/400wt — use for IDs, codes, phase labels, and metadata.
- Neutral subtle badge now has a 1px border (`--border-subtle`) so it reads clearly on white canvas without a filled background.

**Rule — colour in chips is opt-in, not default:**
Websites, dashboards, and reports generated from this system must default to neutral/grey for all label badges (categories, phases, metadata, identifiers). Colour badges are reserved for semantic status only:

| Use colour | Stay neutral |
|---|---|
| Trial status (Active / On Hold / Discontinued) | Phase number (Phase II) |
| Assay activity (Active / Inactive) | Report ID / trial number |
| Severity (Grade 1–4) | Section category tags |
| Alert type (warning, error) | Author / institution labels |

**Affected components:** `Badge`, `TestingPages` stories.

---

## 2026-05-07 — Testing Pages story category added

**What changed:**
Two full-page pharmaceutical research layouts added under `Testing Pages` in Storybook:
1. **Compound Efficacy Report** — preclinical report for MRP-447 (EGFR inhibitor). Includes dose-response SVG chart, kinase selectivity DataTable, cell viability chart, safety panel, conclusions card.
2. **Clinical Trial Dashboard** — Phase II interim analysis for ONCOL-2024-47. Includes enrollment bar chart, waterfall plot, RECIST response table, subgroup analysis, adverse events DataTable.

**Purpose:** Reference layouts to validate component system at full-page scale. Should be kept in sync as the design system evolves.

---

## 2026-05-07 — FolderCard replaces ProjectCard; Carbon icon integration

**What changed:**
- `ProjectCard` renamed to `FolderCard` across all files.
- Inline SVG folder icon replaced with `Folder` from `@carbon/icons-react` (16px, `--fg-secondary` colour).
- Source of truth: Synapse `ProjectTile.tsx` — same icon, same `role="button"` div pattern, same `--accent-default` selected border.

**Rule:** Folder-style navigation tiles always use the Carbon `Folder` icon at 16px. Do not substitute with inline SVGs.

---

## 2026-05-07 — DataTable visual language: grey header + line separators

**What changed:**
- Header row: `--bg-surface-1` (neutral grey), bordered top/bottom/sides — reads as a distinct "shelf", not a coloured block.
- Data rows: white (`--bg-canvas`), separated by a single `border-top: 1px solid var(--border-subtle)` on the `td` — not wrapped in card borders.
- Rows must not look like individual cards. Separation is purely typographic (line), not structural (box).

**Rule:** DataTable rows are always line-separated, never boxed. The table itself still needs a clear 1px `--border-subtle` outer perimeter, either on the table or on its scroll wrapper. Use card chrome only for a broader section container when the table is one piece of a larger content block.

---

## 2026-05-07 — Color tokens added: expressive schemes + palette fills

**What changed:**
Added to `design/color/colors.css`:
- `--scheme-[color]-bg / -border / -surface` — vivid backgrounds for themed sections (blue, pink, green, orange, yellow).
- `--pl-[color]-strong / -strong-hover / -md / -light` — palette fills for solid buttons and subtle badges (blue, pink, green, orange, yellow, red).

**Rule:** Never use primitive colour values (e.g. `--blue-500`) directly in components. Always go through a semantic or palette token.
