---
name: "color_theory_basics"
description: "Choose colors for websites, slides, brand materials, or app UI: build a palette from a base color using harmony rules, assign usage roles, and verify WCAG contrast ratios. Triggers on: pick a color palette, brand colors, what colors go together, accessible color combinations, text contrast check, analogous vs complementary colors."
metadata: { "includeInPrompt": true }
---

# Color Theory Basics

## Purpose
Pick colors that work together for any visual deliverable: site, deck, brand kit, app UI. Covers the color wheel, harmony rules, palette building, and contrast checks. It does not cover video color grading (LUTs, vectorscopes, shot matching); the catalog's separate `color-grading` skill owns that.

## Workflow
1. Start from one base color the client likes or the brand already has. If none exists, ask for a mood word (calm, bold, premium, playful) and propose one hex.
2. Pick a harmony rule for the palette:
   - Monochromatic: base color plus tints (mix toward white) and shades (mix toward black). Safest default; use when in doubt.
   - Analogous: base plus the two hues next to it on the wheel (within ~30-60 degrees). Calm and cohesive; good for backgrounds and secondary UI.
   - Complementary: base plus the hue opposite on the wheel (~180 degrees). High energy; reserve the complement for accents and calls to action, not large areas.
   - Triadic: base plus two hues evenly spaced (~120 degrees apart). Lively but balanced; keep one dominant and the other two as accents.
3. Build the palette: 1 dominant color (60% of the surface), 1-2 secondary colors (30%), 1 accent (10%). Stop adding colors when every role is filled; most designs need 3-4 colors total, 5 at most.
4. Assign roles explicitly: background, primary text, secondary text, primary button/link, accent/highlight, success/error (stick with green/red conventions here unless told otherwise).
5. Check contrast with the script below for every text/background pair and every meaningful icon or form-field border. Targets: 4.5:1 for normal text, 3:1 for large text (18pt+ or 14pt+ bold). Treat those as floors, not aspirations; aim a bit above them.
6. Sanity pass: view the palette at small sizes and on the actual device if possible. Convert it to grayscale; if two elements that must be distinguishable become identical, the hue difference is doing all the work and you need a lightness gap too. Never rely on color alone to convey meaning (errors, statuses); pair it with text or an icon.

### Contrast ratio calculator (self-contained)
Save as `contrast_check.py` and run with `python3 contrast_check.py <fg-hex> <bg-hex>`, e.g. `python3 contrast_check.py "#1a1a1a" "#ffffff"`. Verified working on python3 with standard library only.

```python
import sys

def lin(c):
    c = c / 255.0
    return c / 12.92 if c <= 0.03928 else ((c + 0.055) / 1.055) ** 2.4

def luminance(hex):
    hex = hex.strip().lstrip('#')
    r, g, b = int(hex[0:2], 16), int(hex[2:4], 16), int(hex[4:6], 16)
    return 0.2126 * lin(r) + 0.7152 * lin(g) + 0.0722 * lin(b)

def ratio(h1, h2):
    l1, l2 = luminance(h1), luminance(h2)
    hi, lo = max(l1, l2), min(l1, l2)
    return (hi + 0.05) / (lo + 0.05)

if __name__ == '__main__':
    fg, bg = sys.argv[1], sys.argv[2]
    r = ratio(fg, bg)
    def verdict(t):
        return 'PASS' if r >= t else 'FAIL'
    print(f"{fg} on {bg}: {r:.2f}:1")
    print(f"  normal text (>=4.5): {verdict(4.5)}")
    print(f"  large text (>=3.0):  {verdict(3.0)}")
```

## Output Contract
Deliver: the palette as named colors with hex values, each color's role (background, text, button, accent, status), and a contrast table showing each text/background pair's ratio and PASS/FAIL against the 4.5:1 and 3:1 floors. Include the harmony rule you used and one sentence on why it fits the brief. If a pair fails, say which color to darken or lighten and by how much (a rough hex adjustment is fine).

## Operating Rules
1. Defaults with exceptions: monochromatic is the default palette shape, complementary accents are the default for energy, the 60/30/10 split is the default distribution. Break any of these when the brief clearly calls for it; say why in one sentence.
2. Always assign roles before finalizing; a pretty palette with no role assignments is unfinished work.
3. Contrast floors are non-negotiable for text that must be read (4.5:1 normal, 3:1 large). Decorative elements that carry no information may sit below the floors; say so explicitly when you allow it.
4. Keep palettes small: 3-4 colors beats 7. Every extra color needs a job.
5. Do not quote WCAG levels (AA/AAA) or ratio numbers beyond the two floors without verifying them fresh; the floors above are the stable, long-standing values.
