---
version: alpha
name: Boxwood Ballast
description: "Institutional, high-readability UI for marketing agencies: one deep green action color on true-neutral surfaces, with Newsreader for headings."
colors:
  background: "#fafafa"
  foreground: "#0a0a0a"
  card: "#ffffff"
  card-foreground: "#0a0a0a"
  popover: "#ffffff"
  popover-foreground: "#0a0a0a"
  primary: "#2d7752"
  primary-foreground: "#ffffff"
  secondary: "#f5f5f5"
  secondary-foreground: "#171717"
  muted: "#f5f5f5"
  muted-foreground: "#525252"
  accent: "#dcefe4"
  accent-foreground: "#123721"
  destructive: "#bd2c55"
  destructive-foreground: "#ffffff"
  success: "#1b635b"
  success-foreground: "#ffffff"
  warning: "#fbe08f"
  warning-foreground: "#3b2c08"
  border: "#e5e5e5"
  input: "#d4d4d4"
  ring: "#3f9268"
  dark-background: "#0a0a0a"
  dark-foreground: "#f5f5f5"
  dark-card: "#171717"
  dark-card-foreground: "#f5f5f5"
  dark-popover: "#171717"
  dark-popover-foreground: "#f5f5f5"
  dark-primary: "#5fb085"
  dark-primary-foreground: "#0a2215"
  dark-secondary: "#262626"
  dark-secondary-foreground: "#f5f5f5"
  dark-muted: "#262626"
  dark-muted-foreground: "#a3a3a3"
  dark-accent: "#123721"
  dark-accent-foreground: "#dcefe4"
  dark-destructive: "#f0607f"
  dark-destructive-foreground: "#3a0a1a"
  dark-success: "#45b3a3"
  dark-success-foreground: "#0a2624"
  dark-warning: "#d9ac2c"
  dark-warning-foreground: "#241b04"
  dark-border: "#262626"
  dark-input: "#404040"
  dark-ring: "#5fb085"
typography:
  display-lg:
    fontFamily: Newsreader
    fontSize: 49px
    fontWeight: 600
    lineHeight: 1.08
    letterSpacing: -0.022em
  display-md:
    fontFamily: Newsreader
    fontSize: 39px
    fontWeight: 600
    lineHeight: 1.12
    letterSpacing: -0.018em
  heading-lg:
    fontFamily: Newsreader
    fontSize: 25px
    fontWeight: 500
    lineHeight: 1.24
    letterSpacing: -0.012em
  heading-md:
    fontFamily: Public Sans
    fontSize: 20px
    fontWeight: 600
    lineHeight: 1.3
    letterSpacing: -0.008em
  heading-sm:
    fontFamily: Public Sans
    fontSize: 16px
    fontWeight: 600
    lineHeight: 1.4
    letterSpacing: -0.002em
  body-lg:
    fontFamily: Public Sans
    fontSize: 18px
    fontWeight: 400
    lineHeight: 1.65
  body-md:
    fontFamily: Public Sans
    fontSize: 16px
    fontWeight: 400
    lineHeight: 1.6
  body-sm:
    fontFamily: Public Sans
    fontSize: 14px
    fontWeight: 400
    lineHeight: 1.55
  label:
    fontFamily: Public Sans
    fontSize: 14px
    fontWeight: 500
    lineHeight: 1.25
    letterSpacing: 0.005em
  caption:
    fontFamily: Public Sans
    fontSize: 12px
    fontWeight: 500
    lineHeight: 1.4
    letterSpacing: 0.012em
  code:
    fontFamily: IBM Plex Mono
    fontSize: 14px
    fontWeight: 400
    lineHeight: 1.5
rounded:
  sm: 4px
  md: 8px
  lg: 12px
  xl: 16px
  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 16px
    height: 40px
  button-secondary:
    backgroundColor: "{colors.secondary}"
    textColor: "{colors.secondary-foreground}"
    typography: "{typography.label}"
    rounded: "{rounded.md}"
    padding: 0 16px
    height: 40px
  button-destructive:
    backgroundColor: "{colors.destructive}"
    textColor: "{colors.destructive-foreground}"
    typography: "{typography.label}"
    rounded: "{rounded.md}"
    padding: 0 16px
    height: 40px
  input:
    backgroundColor: "{colors.background}"
    textColor: "{colors.foreground}"
    typography: "{typography.body-sm}"
    rounded: "{rounded.md}"
    padding: 0 12px
    height: 40px
  card:
    backgroundColor: "{colors.card}"
    textColor: "{colors.card-foreground}"
    rounded: "{rounded.lg}"
    padding: 24px
  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.full}"
    padding: 0 8px
    height: 22px
  badge-success:
    backgroundColor: "{colors.success}"
    textColor: "{colors.success-foreground}"
    typography: "{typography.caption}"
    rounded: "{rounded.full}"
    padding: 0 8px
    height: 22px
  badge-warning:
    backgroundColor: "{colors.warning}"
    textColor: "{colors.warning-foreground}"
    typography: "{typography.caption}"
    rounded: "{rounded.full}"
    padding: 0 8px
    height: 22px
  badge-destructive:
    backgroundColor: "{colors.destructive}"
    textColor: "{colors.destructive-foreground}"
    typography: "{typography.caption}"
    rounded: "{rounded.full}"
    padding: 0 8px
    height: 22px
  button-primary-dark:
    backgroundColor: "{colors.dark-primary}"
    textColor: "{colors.dark-primary-foreground}"
    typography: "{typography.label}"
    rounded: "{rounded.md}"
    padding: 0 16px
    height: 40px
  button-secondary-dark:
    backgroundColor: "{colors.dark-secondary}"
    textColor: "{colors.dark-secondary-foreground}"
    typography: "{typography.label}"
    rounded: "{rounded.md}"
    padding: 0 16px
    height: 40px
  button-destructive-dark:
    backgroundColor: "{colors.dark-destructive}"
    textColor: "{colors.dark-destructive-foreground}"
    typography: "{typography.label}"
    rounded: "{rounded.md}"
    padding: 0 16px
    height: 40px
  input-dark:
    backgroundColor: "{colors.dark-background}"
    textColor: "{colors.dark-foreground}"
    typography: "{typography.body-sm}"
    rounded: "{rounded.md}"
    padding: 0 12px
    height: 40px
  card-dark:
    backgroundColor: "{colors.dark-card}"
    textColor: "{colors.dark-card-foreground}"
    rounded: "{rounded.lg}"
    padding: 24px
  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.full}"
    padding: 0 8px
    height: 22px
  badge-success-dark:
    backgroundColor: "{colors.dark-success}"
    textColor: "{colors.dark-success-foreground}"
    typography: "{typography.caption}"
    rounded: "{rounded.full}"
    padding: 0 8px
    height: 22px
  badge-warning-dark:
    backgroundColor: "{colors.dark-warning}"
    textColor: "{colors.dark-warning-foreground}"
    typography: "{typography.caption}"
    rounded: "{rounded.full}"
    padding: 0 8px
    height: 22px
  badge-destructive-dark:
    backgroundColor: "{colors.dark-destructive}"
    textColor: "{colors.dark-destructive-foreground}"
    typography: "{typography.caption}"
    rounded: "{rounded.full}"
    padding: 0 8px
    height: 22px
---

# Boxwood Ballast

## Overview

Boxwood Ballast is for agency leadership, account managers and client-facing teams. They need tools that look as dependable as the work they sell. The system relies on restraint. One deep green (brand.600 in light mode, brand.400 in dark) marks every interactive element. Zero-chroma neutral surfaces leave client work unaltered. Comfortable spacing on a 4px grid keeps long briefs and reports readable.

Moods: institutional, stable, precise, calm. Built for: marketing-agency, professional-services, agency-operations. Density: comfortable.

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

Keel (the brand ramp, hue around 150) is the only action color. It is used for primary buttons, selected states and the focus ring (ring = brand.500 light / brand.400 dark, ≥3.6:1 against background). The neutral ramp has zero chroma by design, so client brand colors shown inside the product are never shifted by the chrome around them. This is the one deliberate exception to tinting. The status ramps share the brand's cool temperature and its chroma curve, which is low at 50–100, peaks at 400–600 and recedes at 900–950. Success sits in teal (hue around 175), so a success badge never reads as a Keel button. Warning is a muted amber. Destructive is a cool crimson with a magenta cast, far from Keel in hue in both modes. Light-mode pairs: primary/white 5.4:1, destructive/white 5.6:1, success/white 7.0:1, muted-foreground/muted 7.2:1. Dark-mode pairs: primary/brand.950 6.4:1, destructive/danger.950 5.4:1, success/success.950 6.3:1, muted-foreground/muted 6.0:1.

- **Primary** `#2d7752` / dark `#5fb085`: the single action color. Primary buttons, links, focus ring.
- **Background / Foreground** `#fafafa` / dark `#0a0a0a` on `#0a0a0a` / dark `#f5f5f5`: page surface and body text.
- **Card** `#ffffff` / dark `#171717`: raised surfaces.
- **Secondary** `#f5f5f5` / dark `#262626`: secondary buttons and quiet controls.
- **Muted** `#f5f5f5` / dark `#262626` with **muted-foreground** `#525252` / dark `#a3a3a3`: helper text, table stripes, disabled-looking surfaces.
- **Accent** `#dcefe4` / dark `#123721`: highlights, selected rows, badges.
- **Destructive** `#bd2c55` / dark `#f0607f`, **Success** `#1b635b` / dark `#45b3a3`, **Warning** `#fbe08f` / dark `#d9ac2c`: status only, always paired with an icon or label.
- **Border** `#e5e5e5` / dark `#262626`, **Input** `#d4d4d4` / dark `#404040`, **Ring** `#3f9268` / dark `#5fb085`.

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

## Typography

The type scale uses a major third (1.25) on a 16px base, rounded to whole pixels: heading-sm 16, heading-md 20, heading-lg 25, display-md 39, display-lg 49. display-md sits two steps (1.25²) above heading-lg so page titles separate clearly from section titles. Newsreader (500/600) is used only for heading-lg and above, where letterSpacing tightens from -0.012em to -0.022em as size grows. Public Sans (400/500/600) handles navigation, tables, forms and buttons. Its body styles use line heights of 1.55–1.65. IBM Plex Mono (400/500) is reserved for campaign IDs, UTM parameters and code snippets.

- Display: **Newsreader** (fallback Georgia, serif)
- Interface: **Public Sans** (fallback system-ui, sans-serif)
- Mono: **IBM Plex Mono** (fallback ui-monospace, monospace)

| Token | Font | Size | Line height | Weight |
|---|---|---|---|---|
| display-lg | Newsreader | 49px | 1.08 | 600 |
| display-md | Newsreader | 39px | 1.12 | 600 |
| heading-lg | Newsreader | 25px | 1.24 | 500 |
| heading-md | Public Sans | 20px | 1.3 | 600 |
| heading-sm | Public Sans | 16px | 1.4 | 600 |
| body-lg | Public Sans | 18px | 1.65 | 400 |
| body-md | Public Sans | 16px | 1.6 | 400 |
| body-sm | Public Sans | 14px | 1.55 | 400 |
| label | Public Sans | 14px | 1.25 | 500 |
| caption | Public Sans | 12px | 1.4 | 500 |
| code | IBM Plex Mono | 14px | 1.5 | 400 |

## Layout

Comfortable density on a 4px base grid with half-steps at 2px and 6px for icon gaps. Content columns cap at 1200px, and long-form reading blocks cap at about 72ch of body-md. Table rows are at least 44px tall so budget and performance figures can be scanned without strain.

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

## Elevation & Depth

Mostly flat and structural. Cards separate from the page with a 1px border token and shadow.sm. shadow.md is reserved for popovers and menus, and shadow.lg for dialogs. In dark mode, depth comes from surface steps instead: background is neutral.950 and card/popover are neutral.900, one step lighter.

- sm: `0 1px 2px rgba(0, 0, 0, 0.06)`
- md: `0 4px 12px -2px rgba(0, 0, 0, 0.12)`
- lg: `0 16px 40px -8px rgba(0, 0, 0, 0.20)`

## Shapes

Rounding is measured. Buttons and inputs use radius.md (8px) and cards use radius.lg (12px). radius.full is reserved for status badges, so a pill shape always means status, never action.

Radius scale: sm 4px, md 8px, lg 12px, xl 16px, full 9999px.

## Components

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

## Do's and Don'ts

- **Do:** Use one primary button (primary / primary-foreground, 40px, radius.md) per view. Render other actions as secondary or ghost buttons at the same 40px height.
- **Do:** Set budget and metric figures in body-sm or body-md with font-feature-settings: 'tnum', and right-align them in table columns.
- **Do:** Use Newsreader only for heading-lg (25px) and above. Use the Public Sans styles for heading-md, heading-sm, body, label and caption.
- **Do:** Pair every success, warning and destructive badge or alert with an icon or text label, so meaning never relies on color alone.
- **Do:** Keep table rows at least 44px tall. On tables longer than 10 rows, stripe alternate rows with the muted token and keep row text at foreground, not muted-foreground.
- **Do:** Show keyboard focus as a 2px ring token outline with a 2px offset on buttons, inputs and selectable rows, in both modes.
- **Don't:** Don't use primary for errors, negative variances or destructive confirmations. Use destructive, and confirm in a dialog with shadow.lg.
- **Don't:** Don't use success where primary is meant. The teal success ramp is for completed or positive states, never for calls to action.
- **Don't:** Don't set body text longer than two lines on the accent surface. Accent is for highlighted and selected rows only.
- **Don't:** Don't use shadow.md or shadow.lg on cards. Card separation comes from the 1px border token and shadow.sm.
- **Don't:** Don't tint the neutral ramp or build custom grays. Use neutral.50–950 so client colors displayed in the product stay unaltered.
- **Don't:** Don't set Newsreader below 24px, in all caps, or at weights other than 500 and 600.
