Foundations

The rule sets every language, chart, and page builds on. Numbered, permanent, cited where perception research backs a law.

FN-01 . Token contract  |  FN-02 . Canvas and spacing grid  |  FN-03 . Type scale  |  FN-04 . Contrast and color use  |  FN-05 . Numbers, units, and scales  |  FN-06 . Perceptual foundations

FN-01 . Token contract

The rule that makes the whole catalogue themeable and deterministic:

Chart and component specs reference color ROLES, never hex values. Design languages (DL files) bind roles to hex. Rebranding = swapping the DL token file. No spec changes, no re-authoring.

Required roles (every DL must bind all of these)

RoleMeaning
backgroundpage/canvas fill
inkheadings, key numbers, strongest text
bodysupporting text, labels, sources
primarythe one accent; highlights, key series
mutedcontext series, de-emphasized marks
gridlinechart gridlines
hairlinerules, baselines, separators
positivegood deltas (always paired with a word, never alone)
negativebad deltas (same)

Optional roles a DL may add: panel, benchmark, warning, primaryDark, and others. Specs that want an optional role declare a fallback chain, for example "context": ["benchmark", "muted"]: first role present in the palette wins. The renderer resolves the chain, so a spec never breaks on a DL that lacks an optional role.

Rules

  1. Hex values live in tokens/DL-xx.json only. A hex value inside a chart spec or component spec fails validation on sight.
  2. All hex is #RRGGBB uppercase. Enforced by schema/dl.schema.json and tools/validate.py.
  3. ink and body must reach 4.5:1 contrast on background (WCAG AA). Enforced by tools/validate.py.
  4. Fonts follow the same contract: specs reference display or body, the DL binds each to a family stack whose last entries are installed-everywhere fallbacks.

FN-02 . Canvas and spacing grid

Canvases

TargetSizeUse
Chart entry golden render960 x 540 pxevery CH-xx golden
Full slide (16:9)1280 x 720 pxrecipes (DL/CH/CP combinations)

All positions and sizes in specs are exact pixels on these canvases. Adjectives ("comfortable margin", "medium bar") are banned in specs; a value the renderer cannot consume is not a spec.

The 8px grid

Every structural distance is a multiple of 8: margins, offsets, bar heights, gaps, plot bounds.

DistanceValue
Canvas edge to content32 px
Title block to plot area>= 40 px
Bar height / bar gap (CH-01)32 / 16 px
Label offset from mark8 or 16 px

Text sizes are exempt from the 8-multiple (they follow FN-03) but their anchor positions are not.

Fixed furniture on every chart canvas


FN-03 . Type scale

Sizes are fixed per text role on the 960x540 chart canvas. A DL changes the family and weight, never the size or position (those belong to the chart spec).

Text roleSizeFont slotNotes
Title24 pxdisplayfull sentence, states the finding with a number
Eyebrow11 pxbody, weight 600CAPS, letter-spacing 2, only if DL chrome
Category / series label13 pxbodyweight 600 only on the highlighted item
Value label13 pxbodyweight 600 only on the highlighted item
Tick label11 pxbody
X-axis label11 pxbody
Annotation12 pxbody, italic
Source line11 pxbody

Rules

  1. Two font slots only: display (titles) and body (everything else). A third slot (mono for IDs and timestamps) is reserved for DLs that declare it; no spec may require it.
  2. Every DL family stack ends in an installed-everywhere fallback (Segoe UI, Arial, Georgia, Consolas). Silent substitution with a different metric font is the failure mode this prevents.
  3. Nothing below 11 px on the 960x540 canvas. On the 1280x720 slide canvas the floor is 12 px.
  4. Emphasis is weight (400 to 600), never a size bump, never underline.

FN-04 . Contrast and color use

Hard limits (validated, not advisory)

  1. ink and body reach 4.5:1 on background (WCAG AA body text). tools/validate.py computes this from the DL token file and blocks on failure.
  2. Meaning is never carried by color alone. Status, deltas, and exceptions always pair color with a word or a number.
  3. One saturated highlight per chart. The primary role appears on the one mark the title talks about; everything else uses muted or benchmark.

Discipline

The banned list (applies to every DL, every chart)


FN-05 . Numbers, units, and scales

Numbers

  1. Tabular (monospaced-figure) rendering wherever numbers stack in columns; right-aligned in tables.
  2. Units appear ONCE per chart, not per value: - bar charts: on the first (largest) value label ("34 items", then "28", "21", ...) - line charts: on the top y tick label ("80%", then "60", "40", ...)
  3. Missing value = "-" (hyphen nil marker), never zero, never a guess.
  4. Titles state the finding with a number. "Backlog overview" fails QA; "Electrical holds 34 of 109 open items" passes.

Scales (deterministic by construction)

Bars start at zero, always, no exceptions. Line charts start at zero by default; a non-zero baseline requires a written justification in the entry that uses it.

Tick generation is an algorithm, not taste, so two renders can never disagree:

raw  = max_value / target_ticks        (target_ticks = 5)
mag  = 10 ^ floor(log10(raw))
step = first of {1, 2, 5, 10} * mag that is >= raw
top  = ceil(max_value / step) * step
ticks = 0, step, 2*step, ... top

Direct-label bar charts skip the axis entirely and scale bars to the max value; the labels carry the numbers.

Float formatting in renders

All coordinates format as max-2-decimal, trailing zeros stripped, "-0" normalized to "0". This is what makes byte-identical re-renders possible across machines.


FN-06 . Perceptual foundations

Every OVP rule traces to a named finding in visual perception research, not to taste. This entry is the trace, one line per rule family. It is deliberately one page: OVP cites the science, it does not rewrite it.

OVP rulePerceptual basis
One primary highlight per chart (FN-04)Preattentive pop-out: one distinct hue is found in constant time; two or more force serial search (Treisman; Ware)
Bars and positions over pies and areas (CH family design)Graphical perception hierarchy: position and length are decoded far more accurately than angle and area (Cleveland & McGill)
Pie capped at 3 slices, warn status (CH-PTW-03/04)Angle judgment error grows with slice count; under ~15% differences angles are unreadable (Cleveland & McGill)
Max 4 stacked segments, max 5 KPI cardsWorking-memory span: ~4 chunks held reliably (Cowan; Miller)
Direct labels and line-end labels, never legendsEvery legend lookup is a saccade round-trip that reloads working memory (Ware; Few)
Annotation anchored at the data (CH-TIM rules)Attention follows pointers; unanchored commentary is ignored under load (Ware)
8px grid, gaps group related elements (FN-02)Gestalt proximity and common region: spacing IS structure
Status word + color, never color alone (FN-04)~8% of men have deficient color vision; hue is not a channel you can require (accessibility canon)
Zero baselines on bars and areas (FN-05)Length encoding lies when truncated; the lie compounds with fill (Tufte's lie factor)
Muted context + one saturated seriesContrast drives salience; salience should follow the message, not the palette (Ware; Few)
Action titles stating the finding (CORE rule 1)Assertion-evidence structure improves recall and decision agreement versus topic titles (presentation research canon)
Tabular figures, right-aligned numbers (FN-05)Digit alignment enables column scanning as a single visual object

Canon referenced: Bertin (Semiologie graphique), Cleveland & McGill (graphical perception experiments), Ware (Information Visualization), Munzner (Visualization Analysis and Design), Tufte (VDQI), Few (Show Me the Numbers), Treisman (preattentive processing), Cowan/Miller (working memory), Kahneman (attention and effort).

Rule for extending OVP: a new rule that cannot cite a row here, or add one, is a preference, and preferences do not enter the protocol.