---
version: alpha
name: Observable Analytics Lab Interface
description: "A chart-first analytics and research interface derived from Observable Plot, Observable Framework, D3, and public-data visualization guidance. It uses a quiet off-white canvas, ink-heavy explanatory typography, compact chart cards, notebook-like evidence blocks, visible data provenance, legends, annotations, and accessible table fallbacks. The system is for dashboards, research notes, public-data portals, data stories, and analyst workspaces where users need to inspect evidence rather than admire dashboard chrome."

colors:
  primary: "#4269d0"
  primary-hover: "#2f4d9a"
  on-primary: "#ffffff"
  accent: "#efb118"
  accent-soft: "#fff4d0"
  canvas: "#fbfaf7"
  surface: "#ffffff"
  surface-card: "#ffffff"
  surface-soft: "#f5f3ee"
  surface-inset: "#eeebe3"
  ink: "#171717"
  body: "#373737"
  muted: "#6d6a63"
  subtle: "#9b968c"
  hairline: "#ded9ce"
  gridline: "#e8e2d7"
  success: "#198754"
  warning: "#b7791f"
  danger: "#c2410c"
  series-blue: "#4269d0"
  series-orange: "#efb118"
  series-green: "#3ca951"
  series-red: "#ff725c"
  series-violet: "#6b4fd8"
  series-gray: "#8f8b82"
  inverse-canvas: "#111214"
  inverse-surface: "#191b1f"
  inverse-ink: "#f5f3ee"

typography:
  display-xl:
    fontFamily: "Source Serif 4, Fraunces, Georgia, serif"
    fontSize: 58px
    fontWeight: 620
    lineHeight: 1.03
    letterSpacing: 0
  display-lg:
    fontFamily: "Source Serif 4, Fraunces, Georgia, serif"
    fontSize: 42px
    fontWeight: 620
    lineHeight: 1.08
    letterSpacing: 0
  heading-md:
    fontFamily: "Inter, ui-sans-serif, system-ui, sans-serif"
    fontSize: 22px
    fontWeight: 680
    lineHeight: 1.22
    letterSpacing: 0
  heading-sm:
    fontFamily: "Inter, ui-sans-serif, system-ui, sans-serif"
    fontSize: 16px
    fontWeight: 680
    lineHeight: 1.32
    letterSpacing: 0
  body:
    fontFamily: "Inter, ui-sans-serif, system-ui, sans-serif"
    fontSize: 15px
    fontWeight: 430
    lineHeight: 1.58
    letterSpacing: 0
  body-sm:
    fontFamily: "Inter, ui-sans-serif, system-ui, sans-serif"
    fontSize: 13px
    fontWeight: 430
    lineHeight: 1.48
    letterSpacing: 0
  caption:
    fontFamily: "Inter, ui-sans-serif, system-ui, sans-serif"
    fontSize: 12px
    fontWeight: 650
    lineHeight: 1.35
    letterSpacing: 0
  mono:
    fontFamily: "JetBrains Mono, ui-monospace, SFMono-Regular, Menlo, Consolas, monospace"
    fontSize: 12px
    fontWeight: 500
    lineHeight: 1.48
    letterSpacing: 0
    fontVariantNumeric: "tabular-nums"

rounded:
  xs: 3px
  sm: 5px
  md: 8px
  lg: 10px
  xl: 14px
  pill: 9999px

spacing:
  base: 8px
  xxs: 4px
  xs: 8px
  sm: 12px
  md: 16px
  lg: 24px
  xl: 36px
  xxl: 56px
  section: 84px

components:
  button-primary:
    backgroundColor: "{colors.primary}"
    textColor: "{colors.on-primary}"
    typography: "{typography.body-sm}"
    rounded: "{rounded.md}"
    padding: 10px 14px
  insight-card:
    backgroundColor: "{colors.surface}"
    textColor: "{colors.body}"
    typography: "{typography.body-sm}"
    rounded: "{rounded.lg}"
    padding: 18px
  chart-frame:
    backgroundColor: "{colors.surface}"
    textColor: "{colors.ink}"
    typography: "{typography.body-sm}"
    rounded: "{rounded.md}"
    padding: 16px
  notebook-cell:
    backgroundColor: "{colors.surface-soft}"
    textColor: "{colors.body}"
    typography: "{typography.mono}"
    rounded: "{rounded.md}"
    padding: 14px
  data-badge:
    backgroundColor: "{colors.surface-inset}"
    textColor: "{colors.muted}"
    typography: "{typography.caption}"
    rounded: "{rounded.sm}"
    padding: 4px 7px
  annotation:
    backgroundColor: "{colors.accent-soft}"
    textColor: "{colors.body}"
    typography: "{typography.body-sm}"
    rounded: "{rounded.sm}"
    padding: 8px 10px

layout:
  content-width: "1120px for dashboard and report pages; 760px for narrative notes."
  grid: "12-column desktop grid. Charts span 4, 6, 8, or 12 columns; text evidence should stay between 56 and 78 characters per line."
  density: "Medium density. Charts may be compact, but every chart keeps title, takeaway, unit, source, and fallback."
  chart-language: "Use direct labels, light gridlines, compact legends, clear axes, and annotations. Color is never the only encoding."

guidance:
  do:
    - "Start every visualization section with the question users are answering."
    - "Use chart titles as conclusions, not only dataset names."
    - "Keep data source, updated time, sample size, and known caveats visible near each chart."
    - "Pair charts with accessible summaries and table fallbacks."
    - "Use notebook cells for reproducible data transforms, not decorative code blocks."
  dont:
    - "Do not fill the first viewport with KPI cards when the user needs explanation."
    - "Do not use map, radar, donut, or 3D chart forms just because they look advanced."
    - "Do not hide the raw data path, source, unit, or timestamp."
    - "Do not rely on hover-only tooltips or color-only series encoding."

caseStudy:
  source: "Observable Plot, Observable Framework, D3, FT Visual Vocabulary, and USWDS data visualization guidance"
  urls:
    - "https://github.com/observablehq/plot"
    - "https://github.com/observablehq/framework"
    - "https://d3js.org/"
    - "https://ft-interactive.github.io/visual-vocabulary/"
    - "https://designsystem.digital.gov/components/data-visualizations/"
  analysis: "Observable Plot emphasizes concise layered marks for tabular data; Observable Framework frames data apps as reports and dashboards with build-time data loaders; D3 supplies bespoke visualization flexibility; FT Visual Vocabulary classifies charts by the question being answered; USWDS reminds teams that usability and accessibility are complementary. This interface extracts the reusable design language: question-first sections, visible provenance, modest chart chrome, evidence notes, and accessible alternatives."
---

# Observable Analytics Lab Interface

Use this system for research dashboards, public data portals, analytics notebooks, product metric reports, climate or civic data stories, internal experiment reviews, and analyst workspaces.

The posture is evidence-first. The interface should feel like a careful research table: quiet surfaces, strong labels, precise chart frames, visible assumptions, and readable notes. It should not feel like a sales dashboard full of decorative gradients, unexplained metrics, and hover-only surprises.

## Overview

The core idea is explainable data. A page should reveal what question is being answered, what data supports the answer, what changed, and what the user can inspect next. Charts are not decorative cards. Each one is a claim that needs title, unit, source, timestamp, and fallback.

The first viewport should show the analysis object: a trend, cohort, map/list comparison, experiment result, or report status. Avoid oversized marketing copy. If a hero exists, it should include a real chart, query, notebook cell, or report summary.

## Colors

### Surface

- `canvas` (#fbfaf7) is a warm research paper floor.
- `surface` (#ffffff) is used for chart frames and cards.
- `surface-soft` (#f5f3ee) supports notebook cells, source callouts, and grouped filters.
- `surface-inset` (#eeebe3) is for badges, filter chips, and table headers.

### Text

- `ink` (#171717) is for chart titles, report headings, and key numbers.
- `body` (#373737) is the reading color.
- `muted` (#6d6a63) and `subtle` (#9b968c) are for metadata, source notes, axis helpers, and timestamps.

### Data Series

Use the series palette sparingly. Two to four series are ideal. When more series are necessary, prefer direct labels, small multiples, filtering, or table views.

Color must never be the only encoding. Pair color with labels, line style, shape, texture, or direct annotation.

## Typography

Use serif display type for report titles and narrative claims. Use sans-serif for UI, filters, legends, captions, tables, and chart labels. Use mono only for code, query names, sample IDs, commit hashes, timestamps, or reproducible data transforms.

Do not scale type with viewport width. Use responsive layout changes instead.

## Layout

Desktop pages use a 12-column grid. A report may combine a 4-column narrative rail and an 8-column chart rail. Dashboards can use 4/6/8/12 column chart spans, but dense charts must keep enough breathing room for axis labels and legends.

Mobile pages become a single column. Filter controls collapse into a sheet or stacked block, but the result count and active filters remain visible.

## Elevation & Depth

Depth should stay analytical, not decorative. Most hierarchy comes from surface color, hairlines, direct labels, and spatial grouping. Use shadows only for temporary overlays such as filter sheets, data inspectors, menus, and disclosure panels.

Chart frames should sit on `surface` with a clear `hairline`; notebook cells use `surface-soft`; provenance badges use `surface-inset`. Avoid large soft shadows around every chart because they make evidence cards feel like generic SaaS widgets.

## Shapes

Use 3px to 10px radii. Small badges and annotations use 3px or 5px. Chart frames use 8px. Larger report panels can use 10px or 14px only when they contain multiple related evidence blocks. Pill radius is allowed for compact filter chips, but not for chart containers.

## Components

### Chart Frame

Every chart frame contains:

1. Takeaway title.
2. Unit and time range.
3. Chart area with direct labels or nearby legend.
4. Source and updated timestamp.
5. Optional annotation.
6. Link or disclosure to table fallback.

### Notebook Cell

Notebook cells show a short query, transform, or assumption. They should be short enough to read, not long pasted scripts. If the transform is essential, include a plain-language explanation above it.

### Data Table Fallback

Charts that represent user-facing decisions need a table fallback or summary. The fallback can be collapsible, but it must be reachable by keyboard and labeled clearly.

### Interaction

Hover can enrich, but it cannot be the only way to inspect data. Tooltips need keyboard and touch alternatives. Filters update visible result counts. Loading states should preserve the last known chart where possible and label stale data.

### Implementation Notes

- Use Observable Plot for concise layered charts.
- Use D3 only when the mark, layout, or interaction is too bespoke for Plot/Recharts/ECharts.
- Use SVG charts when labels and inspection matter; use Canvas/WebGL only with explicit accessibility and table fallback.
- Keep chart data and transformed data inspectable during development.
- Add `prefers-reduced-motion` for animated charts and avoid long intro animations.
- Record source, license, update time, and caveats in code comments or data metadata near the chart component.

## Do's and Don'ts

Do:

- Write the chart question before choosing the chart type.
- Prefer common chart types when audience data literacy is unknown.
- Use small multiples instead of overstuffed legends.
- Put annotations near the data they explain.
- Show uncertainty, sample size, missing data, and caveats.

Don't:

- Use maps for non-geographic ranking questions.
- Use radial, 3D, or decorative chart types without a strong reason.
- Hide legends, sources, and units to make cards look cleaner.
- Let a chart card resize unpredictably when labels load.
- Use hover-only data inspection.

## Responsive Behavior

On mobile, chart height and label density must be recalculated. Rotate nothing by default. Prefer fewer ticks, direct summary text, and a table fallback. If a chart cannot remain legible on mobile, replace it with a summary card plus "view table" or "open full chart" action.

## Iteration Guide

1. Write the analysis question and user decision before choosing the chart type.
2. Pick the simplest chart form that answers the question and define the source, unit, timestamp, and caveat.
3. Design the chart frame with title, annotation, legend/direct labels, source metadata, and table fallback.
4. Map colors through semantic or series tokens and verify color is not the only encoding.
5. Test desktop and mobile label density, keyboard inspection, reduced motion, loading, empty, stale, and error states.
6. Keep transformed data inspectable in code so future agents can audit provenance.

## Known Gaps

This resource does not prescribe one chart library for every project. It is a design and implementation language. The agent must still choose D3, Observable Plot, Vega-Lite, ECharts, Recharts, Chart.js, or MapLibre based on data structure, interaction, performance, and accessibility needs.
