---
version: alpha
name: Understory Array
description: "Dense, dark-first UI for climate data teams: 1px borders, tabular figures, 4px-grid spacing and one signal-green action color."
colors:
  background: "#f2f6f6"
  foreground: "#0d1415"
  card: "#ffffff"
  card-foreground: "#0d1415"
  popover: "#ffffff"
  popover-foreground: "#0d1415"
  primary: "#0f7144"
  primary-foreground: "#ffffff"
  secondary: "#e5ecec"
  secondary-foreground: "#1a2425"
  muted: "#e5ecec"
  muted-foreground: "#3d4c4d"
  accent: "#d3f8e0"
  accent-foreground: "#0d4630"
  destructive: "#c7283f"
  destructive-foreground: "#ffffff"
  success: "#0a6458"
  success-foreground: "#ffffff"
  warning: "#fcdb7f"
  warning-foreground: "#432e00"
  border: "#aebcbc"
  input: "#6a7c7d"
  ring: "#129054"
  dark-background: "#0d1415"
  dark-foreground: "#f2f6f6"
  dark-card: "#1a2425"
  dark-card-foreground: "#f2f6f6"
  dark-popover: "#1a2425"
  dark-popover-foreground: "#f2f6f6"
  dark-primary: "#3ecf82"
  dark-primary-foreground: "#04271a"
  dark-secondary: "#2a3738"
  dark-secondary-foreground: "#e5ecec"
  dark-muted: "#2a3738"
  dark-muted-foreground: "#aebcbc"
  dark-accent: "#0d4630"
  dark-accent-foreground: "#d3f8e0"
  dark-destructive: "#f96a7c"
  dark-destructive-foreground: "#3d0310"
  dark-success: "#22bb9f"
  dark-success-foreground: "#03231f"
  dark-warning: "#e0a617"
  dark-warning-foreground: "#2a1c00"
  dark-border: "#2a3738"
  dark-input: "#6a7c7d"
  dark-ring: "#3ecf82"
typography:
  display-lg:
    fontFamily: Atkinson Hyperlegible
    fontSize: 36px
    fontWeight: 700
    lineHeight: 1.11
    letterSpacing: -0.022em
  display-md:
    fontFamily: Atkinson Hyperlegible
    fontSize: 28px
    fontWeight: 700
    lineHeight: 1.14
    letterSpacing: -0.018em
  heading-lg:
    fontFamily: Atkinson Hyperlegible
    fontSize: 22px
    fontWeight: 700
    lineHeight: 1.27
    letterSpacing: -0.012em
  heading-md:
    fontFamily: Atkinson Hyperlegible
    fontSize: 18px
    fontWeight: 700
    lineHeight: 1.33
    letterSpacing: -0.006em
  heading-sm:
    fontFamily: Atkinson Hyperlegible
    fontSize: 14px
    fontWeight: 700
    lineHeight: 1.43
  body-lg:
    fontFamily: Atkinson Hyperlegible
    fontSize: 16px
    fontWeight: 400
    lineHeight: 1.5
  body-md:
    fontFamily: Atkinson Hyperlegible
    fontSize: 14px
    fontWeight: 400
    lineHeight: 1.43
  body-sm:
    fontFamily: Atkinson Hyperlegible
    fontSize: 13px
    fontWeight: 400
    lineHeight: 1.38
  label:
    fontFamily: Atkinson Hyperlegible
    fontSize: 13px
    fontWeight: 700
    lineHeight: 1.23
    letterSpacing: 0.005em
  caption:
    fontFamily: Atkinson Hyperlegible
    fontSize: 12px
    fontWeight: 400
    lineHeight: 1.33
    letterSpacing: 0.01em
  code:
    fontFamily: JetBrains Mono
    fontSize: 13px
    fontWeight: 400
    lineHeight: 1.54
rounded:
  sm: 2px
  md: 4px
  lg: 6px
  xl: 10px
  full: 9999px
spacing:
  xs: 4px
  sm: 8px
  md: 16px
  lg: 24px
  xl: 32px
  2xl: 48px
  3xl: 64px
components:
  button-primary:
    backgroundColor: "{colors.primary}"
    textColor: "{colors.primary-foreground}"
    typography: "{typography.label}"
    rounded: "{rounded.md}"
    padding: 0 12px
    height: 32px
  button-secondary:
    backgroundColor: "{colors.secondary}"
    textColor: "{colors.secondary-foreground}"
    typography: "{typography.label}"
    rounded: "{rounded.md}"
    padding: 0 12px
    height: 32px
  button-destructive:
    backgroundColor: "{colors.destructive}"
    textColor: "{colors.destructive-foreground}"
    typography: "{typography.label}"
    rounded: "{rounded.md}"
    padding: 0 12px
    height: 32px
  input:
    backgroundColor: "{colors.background}"
    textColor: "{colors.foreground}"
    typography: "{typography.body-sm}"
    rounded: "{rounded.md}"
    padding: 0 8px
    height: 32px
  card:
    backgroundColor: "{colors.card}"
    textColor: "{colors.card-foreground}"
    rounded: "{rounded.lg}"
    padding: 16px
  popover:
    backgroundColor: "{colors.popover}"
    textColor: "{colors.popover-foreground}"
    rounded: "{rounded.lg}"
    padding: 12px
  helper-text:
    backgroundColor: "{colors.background}"
    textColor: "{colors.muted-foreground}"
    typography: "{typography.body-sm}"
  table-row-alt:
    backgroundColor: "{colors.muted}"
    textColor: "{colors.muted-foreground}"
    typography: "{typography.body-sm}"
    height: 44px
  badge:
    backgroundColor: "{colors.accent}"
    textColor: "{colors.accent-foreground}"
    typography: "{typography.caption}"
    rounded: "{rounded.sm}"
    padding: 0 6px
    height: 20px
  badge-success:
    backgroundColor: "{colors.success}"
    textColor: "{colors.success-foreground}"
    typography: "{typography.caption}"
    rounded: "{rounded.sm}"
    padding: 0 6px
    height: 20px
  badge-warning:
    backgroundColor: "{colors.warning}"
    textColor: "{colors.warning-foreground}"
    typography: "{typography.caption}"
    rounded: "{rounded.sm}"
    padding: 0 6px
    height: 20px
  badge-destructive:
    backgroundColor: "{colors.destructive}"
    textColor: "{colors.destructive-foreground}"
    typography: "{typography.caption}"
    rounded: "{rounded.sm}"
    padding: 0 6px
    height: 20px
  button-primary-dark:
    backgroundColor: "{colors.dark-primary}"
    textColor: "{colors.dark-primary-foreground}"
    typography: "{typography.label}"
    rounded: "{rounded.md}"
    padding: 0 12px
    height: 32px
  button-secondary-dark:
    backgroundColor: "{colors.dark-secondary}"
    textColor: "{colors.dark-secondary-foreground}"
    typography: "{typography.label}"
    rounded: "{rounded.md}"
    padding: 0 12px
    height: 32px
  button-destructive-dark:
    backgroundColor: "{colors.dark-destructive}"
    textColor: "{colors.dark-destructive-foreground}"
    typography: "{typography.label}"
    rounded: "{rounded.md}"
    padding: 0 12px
    height: 32px
  input-dark:
    backgroundColor: "{colors.dark-background}"
    textColor: "{colors.dark-foreground}"
    typography: "{typography.body-sm}"
    rounded: "{rounded.md}"
    padding: 0 8px
    height: 32px
  card-dark:
    backgroundColor: "{colors.dark-card}"
    textColor: "{colors.dark-card-foreground}"
    rounded: "{rounded.lg}"
    padding: 16px
  popover-dark:
    backgroundColor: "{colors.dark-popover}"
    textColor: "{colors.dark-popover-foreground}"
    rounded: "{rounded.lg}"
    padding: 12px
  helper-text-dark:
    backgroundColor: "{colors.dark-background}"
    textColor: "{colors.dark-muted-foreground}"
    typography: "{typography.body-sm}"
  table-row-alt-dark:
    backgroundColor: "{colors.dark-muted}"
    textColor: "{colors.dark-muted-foreground}"
    typography: "{typography.body-sm}"
    height: 44px
  badge-dark:
    backgroundColor: "{colors.dark-accent}"
    textColor: "{colors.dark-accent-foreground}"
    typography: "{typography.caption}"
    rounded: "{rounded.sm}"
    padding: 0 6px
    height: 20px
  badge-success-dark:
    backgroundColor: "{colors.dark-success}"
    textColor: "{colors.dark-success-foreground}"
    typography: "{typography.caption}"
    rounded: "{rounded.sm}"
    padding: 0 6px
    height: 20px
  badge-warning-dark:
    backgroundColor: "{colors.dark-warning}"
    textColor: "{colors.dark-warning-foreground}"
    typography: "{typography.caption}"
    rounded: "{rounded.sm}"
    padding: 0 6px
    height: 20px
  badge-destructive-dark:
    backgroundColor: "{colors.dark-destructive}"
    textColor: "{colors.dark-destructive-foreground}"
    typography: "{typography.caption}"
    rounded: "{rounded.sm}"
    padding: 0 6px
    height: 20px
---

# Understory Array

## Overview

Understory Array is for analysts, researchers and operators who watch emissions, sensor networks and energy models for hours at a time. It is dark-first because dashboards stay open on secondary screens. It is compact because the job is comparing many numbers at once: 32px controls, 28–32px table rows, 16px card padding. The target feel is an instrument panel: exact, quiet, and legible at 12–14px.

Moods: technical, precise, focused, calm. Built for: climate, environmental-monitoring, energy-analytics. Density: compact.

Every color has a light value and a dark value. Tokens named `dark-*` are the dark-mode counterparts of the token with the same role name.

## Colors

One action color, Signal Green (OKLCH hue ≈150), carries primary, ring and selected states. Light mode uses brand.700 #0f7144 (6.1:1 with white primary-foreground, 5.5:1 on background) and dark mode uses brand.400 #3ecf82 with brand.950 text (8:1). Brand.400 is bright but not neon. Neutrals are blue-green slates at hue ≈195 with low, even chroma, so green accents and chart series sit on a related ground. Success is teal-green (hue ≈175), close in temperature to the brand but separate from primary. Warning is amber, and destructive is crimson (danger.600 light, danger.400 dark). Destructive sits at hue ≈15, far from primary green in both modes. Input borders use neutral.500 in both modes so field edges reach 3:1 against the page. Dark mode is the reference design: neutral.950 page, neutral.900 card, neutral.800 muted and secondary.

- **Primary** `#0f7144` / dark `#3ecf82`: the single action color. Primary buttons, links, focus ring.
- **Background / Foreground** `#f2f6f6` / dark `#0d1415` on `#0d1415` / dark `#f2f6f6`: page surface and body text.
- **Card** `#ffffff` / dark `#1a2425`: raised surfaces.
- **Secondary** `#e5ecec` / dark `#2a3738`: secondary buttons and quiet controls.
- **Muted** `#e5ecec` / dark `#2a3738` with **muted-foreground** `#3d4c4d` / dark `#aebcbc`: helper text, table stripes, disabled-looking surfaces.
- **Accent** `#d3f8e0` / dark `#0d4630`: highlights, selected rows, badges.
- **Destructive** `#c7283f` / dark `#f96a7c`, **Success** `#0a6458` / dark `#22bb9f`, **Warning** `#fcdb7f` / dark `#e0a617`: status only, always paired with an icon or label.
- **Border** `#aebcbc` / dark `#2a3738`, **Input** `#6a7c7d` / dark `#6a7c7d`, **Ring** `#129054` / dark `#3ecf82`.

All text/background pairs above pass WCAG AA (4.5:1) in both modes; this is checked automatically at build time.

## Typography

Atkinson Hyperlegible is used for display and UI text. Its distinct 1/l/I and 0/O shapes stay clear in dense tables. Use only its shipped weights, 400 and 700. JetBrains Mono at 400/500 sets sensor IDs, coordinates, units and code. The scale steps by about 1.25 from a 14px body: 12, 13, 14, 16, 18, 22, 28, 36. Every line height lands on the 4px grid: body-md 14/20, body-lg 16/24, heading-md 18/24, heading-lg 22/28, display-md 28/32, display-lg 36/40. Letter spacing tightens as size grows, from -0.022em at 36px to 0 at 14px and below. Caption opens up to +0.01em. Enable tabular figures on every numeric column.

- Display: **Atkinson Hyperlegible** (fallback system-ui, sans-serif)
- Interface: **Atkinson Hyperlegible** (fallback system-ui, sans-serif)
- Mono: **JetBrains Mono** (fallback ui-monospace, monospace)

| Token | Font | Size | Line height | Weight |
|---|---|---|---|---|
| display-lg | Atkinson Hyperlegible | 36px | 1.11 | 700 |
| display-md | Atkinson Hyperlegible | 28px | 1.14 | 700 |
| heading-lg | Atkinson Hyperlegible | 22px | 1.27 | 700 |
| heading-md | Atkinson Hyperlegible | 18px | 1.33 | 700 |
| heading-sm | Atkinson Hyperlegible | 14px | 1.43 | 700 |
| body-lg | Atkinson Hyperlegible | 16px | 1.5 | 400 |
| body-md | Atkinson Hyperlegible | 14px | 1.43 | 400 |
| body-sm | Atkinson Hyperlegible | 13px | 1.38 | 400 |
| label | Atkinson Hyperlegible | 13px | 1.23 | 700 |
| caption | Atkinson Hyperlegible | 12px | 1.33 | 400 |
| code | JetBrains Mono | 13px | 1.54 | 400 |

## Layout

Compact density on a 4px base grid. Controls are 32px tall and table rows are 28–32px. Cells use space.2 (8px) padding and cards use space.4 (16px). Divide regions with 1px border lines instead of extra whitespace. Page content can run full width with 12–16px gutters.

Spacing uses a 4px base: xs = 4px, sm = 8px, md = 16px, lg = 24px, xl = 32px, 2xl = 48px, 3xl = 64px.

## Elevation & Depth

Almost flat. Surfaces step up in neutral value: 950 page, 900 card, 800 raised and muted. They are separated by 1px border. Cards use only shadow.sm. Use shadow.md for menus and popovers and shadow.lg for dialogs. All shadows are dark and tight.

- sm: `0 1px 2px rgba(0, 0, 0, 0.30)`
- md: `0 4px 10px -2px rgba(0, 0, 0, 0.40)`
- lg: `0 12px 32px -6px rgba(0, 0, 0, 0.55)`

## Shapes

Small radii keep edges crisp: radius.sm 2px for badges and chips, radius.md 4px for buttons and inputs, radius.lg 6px for cards. radius.xl 10px is for dialogs only. radius.full is only for status dots and count badges.

Radius scale: sm 2px, md 4px, lg 6px, xl 10px, full 9999px.

## Components

Components ending in `-dark` are the dark-mode versions. Button: 32px tall, 12px horizontal padding, label type. Input: 32px tall with a 1px input-colored border; focus shows a 2px ring in the ring color. Card: 16px padding, 1px border, sm shadow. Badge: pill, caption type.

## Do's and Don'ts

- **Do:** Design in dark mode first, then verify light. Use background (neutral.950) for the page, card (neutral.900) for cards and muted (neutral.800) for table header rows.
- **Do:** Apply font-variant-numeric: tabular-nums to every number in tables, stat tiles and chart axis labels. Right-align numeric columns.
- **Do:** Keep button and input at 32px height and table rows at 28–32px. Use space.2 (8px) horizontal padding inside cells.
- **Do:** Separate regions with a 1px border token instead of extra padding or shadow.
- **Do:** Use one primary button (brand.700 light, brand.400 dark) per view. Make other actions secondary or ghost.
- **Do:** Show focus with a 2px ring token outline at 2px offset on every interactive element, including table rows that open detail panels.
- **Do:** Set sensor IDs, coordinates and units in JetBrains Mono using the code style (13/20, weight 400). Use weight 500 only for the selected or active value.
- **Do:** Use display-lg (36px) only for single headline KPIs. Page titles use heading-lg (22px) and card titles use heading-sm (14px, weight 700).
- **Don't:** Don't use primary green to mean 'good' or 'low emissions'. Use the success token (teal-green) with a label.
- **Don't:** Don't put shadow.md or shadow.lg on cards. Use shadow.md for menus and popovers and shadow.lg for dialogs.
- **Don't:** Don't use radius above radius.lg (6px) on cards or controls. Only badges and status dots may use radius.full.
- **Don't:** Don't set body text below 13px (body-sm) or captions below 12px. Use Atkinson Hyperlegible at weights 400 and 700 only.
- **Don't:** Don't use pure black (#000) backgrounds. Use neutral.950 so neutral.800 borders and neutral.900 cards stay visible.
- **Don't:** Don't use destructive crimson for warnings. Warnings use warning tokens: warning.200 fill in light, warning.400 fill in dark.
- **Don't:** Don't use input borders lighter than neutral.500. Field edges must stay at 3:1 or more against background.
- **Don't:** Don't rely on proportional figures in data columns. They misalign digits across rows.
