# How Diagram Design Ensures WCAG AA Contrast During Brand Onboarding

> Diagram Design automatically validates brand colors against WCAG AA contrast standards during onboarding, ensuring accessibility for all.

- Repository: [Cathryn Lavery/diagram-design](https://github.com/cathrynlavery/diagram-design)
- Tags: best-practices
- Published: 2026-08-22

---

**Diagram Design automatically validates extracted brand colors against WCAG AA standards during onboarding, blocking diagram generation until the ink-to-paper ratio hits 3:1 and muted text meets 4.5:1.**

The `cathrynlavery/diagram-design` repository implements a fail-fast accessibility pipeline that integrates WCAG AA contrast verification directly into the brand onboarding workflow. When a new brand is registered, the system extracts the color palette from the brand's website and runs mathematical luminance checks before persisting any design tokens, guaranteeing that every diagram produced meets accessibility standards by default.

## Step 1: Extracting the Brand Palette and Typography

During the initial onboarding phase, the skill fetches the brand's homepage and parses the dominant visual elements. The extraction logic identifies four semantic color tokens—**paper** (background), **ink** (primary text), **muted** (secondary text), and **accent** (highlights)—along with the primary font families. These raw values are held in memory as candidate tokens before being written to the style guide, creating an opportunity for accessibility validation.

## Step 2: Automated Contrast Verification

Before any tokens are persisted, the onboarding script invokes the `contrast()` helper defined in **[`scripts/verify-dumbbell.py`](https://github.com/cathrynlavery/diagram-design/blob/main/scripts/verify-dumbbell.py)** to compute the WCAG luminance ratio. The function converts hex colors to RGB, calculates relative luminance, and applies the standard WCAG formula: `(L1 + 0.05) / (L2 + 0.05)`.

The verification enforces two specific thresholds defined in **[`skills/diagram-design/references/style-guide.md`](https://github.com/cathrynlavery/diagram-design/blob/main/skills/diagram-design/references/style-guide.md)** under the **Constraints** section:

- **Ink on Paper**: Must achieve a minimum **3:1** ratio for non-text graphical objects
- **Muted on Paper**: Must achieve **4.5:1** for text elements at 11px or larger

```python

# scripts/verify-dumbbell.py – contrast helper used during onboarding

def contrast(foreground: str, background: str) -> float:
    """Return the WCAG contrast ratio between two hex colours."""
    fg = rgb(foreground)      # convert "#rrggbb" → (r, g, b)

    bg = rgb(background)
    lum_fg = relative_luminance(fg)
    lum_bg = relative_luminance(bg)
    # WCAG formula: (L1 + 0.05) / (L2 + 0.05)

    return (max(lum_fg, lum_bg) + 0.05) / (min(lum_fg, lum_bg) + 0.05)

# Onboarding snippet (simplified)

ink_ratio = contrast(brand_ink, brand_paper)
if ink_ratio < 3.0:
    # propose a lighter/darker ink that reaches 3:1

    adjusted_ink = suggest_adjustment(brand_ink, brand_paper, target=3.0)
    print(f"⚠️ Ink colour fails AA ({ink_ratio:.2f}); using {adjusted_ink} instead.")
    brand_ink = adjusted_ink

```

## Step 3: Automatic Color Adjustment

If the extracted colors fail to meet the required WCAG AA contrast ratios, the onboarding script does not reject the brand outright. Instead, it programmatically suggests a corrected shade—lightening or darkening the offending color—and presents the adjustment to the user with an explanation of the accessibility improvement. The system only writes the final, verified tokens to **[`skills/diagram-design/references/style-guide.md`](https://github.com/cathrynlavery/diagram-design/blob/main/skills/diagram-design/references/style-guide.md)** after explicit user acceptance of any proposed changes.

## Step 4: The First-Run Gate

According to the source documentation in **[`README.md`](https://github.com/cathrynlavery/diagram-design/blob/main/README.md)** (lines 206-210), the onboarding process is protected by a **"first-run gate"** that blocks all diagram generation until the contrast check passes. This architectural constraint ensures that no inaccessible color combinations can leak into production diagrams. The gate operates as a hard dependency: if `ink` does not hit WCAG AA on `paper`, or if `muted` fails the 4.5:1 threshold for small text, the onboarding workflow cannot complete.

## Summary

- **WCAG AA contrast compliance** is enforced during brand onboarding in `cathrynlavery/diagram-design` through a four-stage pipeline.
- The **`contrast()` function** in [`scripts/verify-dumbbell.py`](https://github.com/cathrynlavery/diagram-design/blob/main/scripts/verify-dumbbell.py) calculates luminance ratios using the standard WCAG formula.
- The system validates **3:1 for ink on paper** (graphical objects) and **4.5:1 for muted text at 11px+**.
- Failed colors trigger **automatic adjustment suggestions** rather than silent failures.
- A **first-run gate** prevents diagram generation until all accessibility checks pass, guaranteeing compliant output by default.

## Frequently Asked Questions

### What specific WCAG AA contrast ratios does Diagram Design enforce?

Diagram Design enforces two distinct thresholds from the WCAG 2.1 guidelines. According to [`skills/diagram-design/references/style-guide.md`](https://github.com/cathrynlavery/diagram-design/blob/main/skills/diagram-design/references/style-guide.md), the `ink` color must achieve a minimum 3:1 contrast ratio against the `paper` background for non-text elements, while the `muted` color must meet the stricter 4.5:1 ratio when used for text at 11 pixels or larger. These values align with WCAG AA requirements for graphical objects and normal text respectively.

### How is the contrast ratio mathematically calculated?

The calculation uses relative luminance as defined in the WCAG specification. The `contrast()` function in [`scripts/verify-dumbbell.py`](https://github.com/cathrynlavery/diagram-design/blob/main/scripts/verify-dumbbell.py) converts hex colors to RGB tuples, calculates luminance for each channel, then applies the formula `(L1 + 0.05) / (L2 + 0.05)` where L1 is the lighter color's luminance. This produces a ratio where 1:1 represents no contrast and 21:1 represents maximum contrast between pure black and pure white.

### What happens if a brand's extracted colors fail the contrast check?

Rather than failing the onboarding process, the system enters an adjustment phase. The onboarding script calculates the delta between the current ratio and the target ratio (3.0 or 4.5), then generates a suggested modification to the color value. The user receives a notification explaining the original failure and the proposed accessible alternative. Only upon user acceptance are the adjusted values written to the style guide's token table.

### Where are the accessibility constraints documented in the codebase?

The definitive rules reside in **[`skills/diagram-design/references/style-guide.md`](https://github.com/cathrynlavery/diagram-design/blob/main/skills/diagram-design/references/style-guide.md)** under the Constraints subsection, which explicitly states that ink must hit WCAG AA on paper and muted must hit AA on paper for 11px+ text. Additional context about the onboarding flow and contrast verification appears in **[`skills/diagram-design/references/onboarding.md`](https://github.com/cathrynlavery/diagram-design/blob/main/skills/diagram-design/references/onboarding.md)** and the repository's **[`README.md`](https://github.com/cathrynlavery/diagram-design/blob/main/README.md)**, which describes the first-run gate mechanism that enforces these rules programmatically.