$npx -y skills add dembrandt/dembrandt-skills --skill algorithmic-color-paletteDerive a full UI colour palette algorithmically from one or two brand colours. Darker and lighter variants for interactive states, desaturated greys from the brand hue for borders and backgrounds, and semantic colours that feel coherent with the brand rather than generic. Use whe
| 1 | # Algorithmic Colour Palette |
| 2 | |
| 3 | A brand palette of 2–3 colours is not enough for a UI. You need shades for states (hover, active, disabled), neutrals for backgrounds and borders, and semantic colours for status. Deriving these algorithmically from the brand colours produces a palette that feels coherent — everything is visually related to the brand rather than pulled from a generic grey or a stock colour library. |
| 4 | |
| 5 | > **Don't guess the seed colours — extract them (dembrandt engine, optional).** If the brand already exists on the web, pull its *real* palette off the live site instead of eyeballing a hex: `get_color_palette` (or the `extract-design` skill) returns the actual computed brand and neutral colours from the DOM, which you then expand with the methods below. See [`extract-design`](../extract-design/SKILL.md) for setup. |
| 6 | |
| 7 | ## Deriving Interactive State Colours |
| 8 | |
| 9 | From each brand colour, generate at minimum three variants: base, darker (hover/active), lighter (tint/background). |
| 10 | |
| 11 | ### Method: HSL adjustment |
| 12 | |
| 13 | ``` |
| 14 | base: hsl(H, S%, L%) |
| 15 | hover: hsl(H, S%, L% - 8%) ← darken by reducing lightness |
| 16 | active: hsl(H, S%, L% - 14%) ← darken further |
| 17 | tint: hsl(H, S%, L% + 40%) ← lighten significantly for backgrounds |
| 18 | subtle: hsl(H, S% * 0.3, L% + 45%) ← heavily desaturated, near-white |
| 19 | ``` |
| 20 | |
| 21 | ### Example: brand primary `#133174` (hsl 224, 70%, 27%) |
| 22 | |
| 23 | ```css |
| 24 | --color-primary-subtle: hsl(224, 21%, 94%); /* background tint */ |
| 25 | --color-primary-tint: hsl(224, 70%, 67%); /* light variant */ |
| 26 | --color-primary: hsl(224, 70%, 27%); /* base */ |
| 27 | --color-primary-hover: hsl(224, 70%, 19%); /* hover: -8% lightness */ |
| 28 | --color-primary-active: hsl(224, 70%, 13%); /* active: -14% lightness */ |
| 29 | ``` |
| 30 | |
| 31 | ### Example: success green derived from a teal brand colour |
| 32 | |
| 33 | If the brand has a green or teal, shift it toward a clearer success green: |
| 34 | |
| 35 | ```css |
| 36 | --color-success-subtle: hsl(142, 20%, 94%); |
| 37 | --color-success: hsl(142, 60%, 35%); |
| 38 | --color-success-hover: hsl(142, 60%, 27%); |
| 39 | ``` |
| 40 | |
| 41 | ## Deriving Brand-Tinted Greys |
| 42 | |
| 43 | Generic greys (`#666`, `#999`, `#eee`) feel disconnected from the brand. Desaturating the brand hue produces greys that are subtly tinted — warm, cool, or neutral depending on the brand — and feel like they belong to the same palette. |
| 44 | |
| 45 | ### Optical Comfort: Avoiding Pure Black on White |
| 46 | Extreme contrast (pure black `#000000` on pure white `#FFFFFF`) can cause "halation" and eye strain. To create a more comfortable reading experience: |
| 47 | - **Use "Near-Black" for text:** Use a very dark grey (e.g., `#222222` or your `grey-900` token) instead of pure black. |
| 48 | - **Use "Off-White" for backgrounds:** A slightly muted white (e.g., `#EEEEEE` or your `grey-50` token) is softer on the eyes than pure `#FFFFFF`. |
| 49 | |
| 50 | This "softened contrast" remains highly accessible (passing WCAG AA/AAA) but feels more professional and less harsh. |
| 51 | |
| 52 | ### Method: desaturate + adjust lightness |
| 53 | |
| 54 | ``` |
| 55 | brand hue H |
| 56 | grey-900: hsl(H, 12%, 10%) ← near-black, text |
| 57 | grey-700: hsl(H, 10%, 30%) ← dark text, icons |
| 58 | grey-500: hsl(H, 8%, 50%) ← secondary text, placeholders |
| 59 | grey-300: hsl(H, 6%, 70%) ← disabled text, subtle labels |
| 60 | grey-200: hsl(H, 5%, 82%) ← borders, dividers |
| 61 | grey-100: hsl(H, 4%, 92%) ← input backgrounds, table stripes |
| 62 | grey-50: hsl(H, 3%, 96%) ← page background, subtle fills |
| 63 | ``` |
| 64 | |
| 65 | ### Example: brand primary `#133174` (H = 224, blue-tinted) |
| 66 | |
| 67 | ```css |
| 68 | --color-grey-900: hsl(224, 12%, 10%); /* #16171f — slightly blue-black */ |
| 69 | --color-grey-500: hsl(224, 8%, 50%); /* #7b7e8a — cool grey */ |
| 70 | --color-grey-200: hsl(224, 5%, 82%); /* #cfd0d5 — cool light bor |