feat: design system v1.0.0 — reconcile tokens from cross-repo audit

Extracted real production usage from 8 KDC repos and consolidated the
consensus (kdcsurveyadd / kdcvault / kdc_void_planner) into the canonical
design.md + tokens.

Highlights:
- brand.ink #000000 -> #1A1530 (purple-tinted, matches real usage)
- brand.canvas #F5F4F0 -> #F7F4ED (warm)
- neutral ramp rebuilt around ink (purple-tinted, not cold slate)
- semantic palette retuned for warm canvas + soft tints
- elevation shadows retinted with brand-ink rgb
- new accent.gold (product) and accent.mint (marketing) tokens
- real themes/light, themes/dark, themes/high-contrast
- fleshed out every component + foundation README
- docs/consolidation-2026-05.md captures the full audit + drift inventory

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Paul Roberts
2026-05-17 17:51:39 +00:00
parent 5c6d703774
commit 6593bdf689
28 changed files with 904 additions and 247 deletions
+108 -43
View File
@@ -1,34 +1,60 @@
---
version: beta
version: 1.0.0
name: Kode Design Consultants Ltd Design System
description: The official design system for Kode Design Consultants — tokens, components, and guidelines for building consistent KDC product and brand experiences.
description: The official design system for Kode Design Consultants — tokens, components, and guidelines for building consistent KDC product and brand experiences. Reconciled 2026-05-17 from production usage across kdcsurveyadd, kdcvault, kdc_void_planner and k-d-c-workspace.
colors:
brand.primary: "#6B35A7"
brand.primaryHover: "#582A8D"
brand.primary: "#6B35A7"
brand.primaryHover: "#5C2D90"
brand.primaryPressed: "#45216E"
brand.ink: "#000000"
brand.canvas: "#F5F4F0"
neutral.0: "#FFFFFF"
neutral.50: "#F5F4F0"
neutral.100: "#EDEFF3"
neutral.200: "#D9DCE3"
neutral.300: "#B8BDC9"
neutral.500: "#6B7280"
neutral.700: "#374151"
neutral.900: "#111827"
brand.primaryLight: "#8456C2"
brand.primarySoft: "#F1E9F8"
brand.ink: "#1A1530"
brand.canvas: "#F7F4ED"
brand.canvasCool: "#F7F6FB"
accent.gold: "#C9892B"
accent.goldStrong: "#A86F1F"
accent.goldSoft: "#F5E9D2"
accent.mint: "#46C194"
neutral.0: "#FFFFFF"
neutral.50: "#FBF8F1"
neutral.100: "#F7F4ED"
neutral.150: "#ECE9F3"
neutral.200: "#E6E0D2"
neutral.300: "#D4CCB8"
neutral.400: "#A39DB0"
neutral.500: "#8C869C"
neutral.600: "#6B647A"
neutral.700: "#4A4360"
neutral.800: "#3A2D5A"
neutral.900: "#1A1530"
neutral.1000: "#000000"
semantic.success: "#16A34A"
semantic.warning: "#F59E0B"
semantic.danger: "#DC2626"
semantic.info: "#0EA5E9"
semantic.success: "#2F7A5A"
semantic.successSoft: "#E2F0E8"
semantic.warning: "#C9892B"
semantic.warningSoft: "#F5E9D2"
semantic.danger: "#B0382F"
semantic.dangerSoft: "#F7E4E1"
semantic.info: "#5C2D90"
surface.background: "{colors.neutral.0}"
surface.subtle: "{colors.neutral.50}"
surface.muted: "{colors.neutral.100}"
text.default: "{colors.neutral.900}"
text.muted: "{colors.neutral.500}"
text.inverse: "{colors.neutral.0}"
border.default: "{colors.neutral.200}"
border.strong: "{colors.neutral.300}"
surface.canvas: "{colors.brand.canvas}"
surface.subtle: "{colors.neutral.50}"
surface.muted: "{colors.brand.primarySoft}"
text.default: "{colors.brand.ink}"
text.soft: "{colors.neutral.700}"
text.muted: "{colors.neutral.600}"
text.disabled: "{colors.neutral.400}"
text.inverse: "{colors.neutral.0}"
text.brand: "{colors.brand.primary}"
border.default: "{colors.neutral.200}"
border.strong: "{colors.neutral.300}"
border.subtle: "{colors.neutral.150}"
elevation:
"0": "none"
"1": "0 1px 2px rgba(26,21,48,0.04)"
"2": "0 4px 12px -4px rgba(26,21,48,0.08)"
"3": "0 16px 40px -16px rgba(26,21,48,0.18)"
"4": "0 24px 80px -24px rgba(26,21,48,0.22)"
focusRing: "0 0 0 3px rgba(107,53,167,0.18)"
typography:
display:
fontFamily: "Opificio"
@@ -117,53 +143,90 @@ components:
textColor: "{colors.text.inverse}"
typography: "{typography.bodyM}"
rounded: "{rounded.md}"
padding: "12px 20px"
padding: "10px 16px"
height: "40px"
shadow: "{elevation.1}"
button.primaryHover:
backgroundColor: "{colors.brand.primaryHover}"
textColor: "{colors.text.inverse}"
button.primaryPressed:
backgroundColor: "{colors.brand.primaryPressed}"
textColor: "{colors.text.inverse}"
button.accent:
backgroundColor: "{colors.accent.gold}"
textColor: "{colors.text.inverse}"
typography: "{typography.bodyM}"
rounded: "{rounded.md}"
padding: "10px 16px"
height: "40px"
description: "Submit / emphasis button. Used sparingly — one per surface."
button.secondary:
backgroundColor: "{colors.surface.subtle}"
textColor: "{colors.text.default}"
borderColor: "{colors.border.default}"
typography: "{typography.bodyM}"
rounded: "{rounded.md}"
padding: "12px 20px"
padding: "10px 16px"
height: "40px"
button.ghost:
backgroundColor: "transparent"
textColor: "{colors.brand.primary}"
typography: "{typography.bodyM}"
rounded: "{rounded.md}"
padding: "12px 20px"
padding: "10px 16px"
height: "40px"
button.outline:
backgroundColor: "transparent"
textColor: "{colors.text.default}"
borderColor: "{colors.border.strong}"
typography: "{typography.bodyM}"
rounded: "{rounded.md}"
padding: "10px 16px"
height: "40px"
input.default:
backgroundColor: "{colors.surface.background}"
textColor: "{colors.text.default}"
borderColor: "{colors.border.default}"
typography: "{typography.bodyM}"
rounded: "{rounded.md}"
padding: "10px 12px"
padding: "8px 12px"
height: "40px"
focusRing: "{elevation.focusRing}"
card.default:
backgroundColor: "{colors.surface.background}"
textColor: "{colors.text.default}"
borderColor: "{colors.border.default}"
rounded: "{rounded.lg}"
padding: "24px"
shadow: "{elevation.1}"
card.elevated:
backgroundColor: "{colors.surface.background}"
rounded: "{rounded.xl}"
padding: "28px"
shadow: "{elevation.3}"
badge.default:
backgroundColor: "{colors.surface.muted}"
textColor: "{colors.text.default}"
backgroundColor: "{colors.brand.primarySoft}"
textColor: "{colors.brand.primaryHover}"
typography: "{typography.caption}"
rounded: "{rounded.full}"
padding: "2px 8px"
height: "20px"
padding: "2px 10px"
height: "22px"
badge.success:
backgroundColor: "{colors.semantic.successSoft}"
textColor: "{colors.semantic.success}"
badge.warning:
backgroundColor: "{colors.semantic.warningSoft}"
textColor: "{colors.semantic.warning}"
badge.danger:
backgroundColor: "{colors.semantic.dangerSoft}"
textColor: "{colors.semantic.danger}"
modal.default:
backgroundColor: "{colors.surface.background}"
textColor: "{colors.text.default}"
rounded: "{rounded.xl}"
padding: "24px"
width: "480px"
shadow: "{elevation.4}"
---
## Overview
@@ -180,13 +243,14 @@ KDS targets WCAG 2.2 AA at minimum across all components and themes.
## Colors
Color is organized in three layers:
Color is organized in four layers:
1. **Brand**the four-color brand palette: `brand.primary` (`#6B35A7` purple), `brand.ink` (`#000000`), `neutral.0` (`#FFFFFF`), and `brand.canvas` (`#F5F4F0` off-white).
2. **Neutral**a 12-step gray ramp powering surfaces, text, and borders. `neutral.50` is set to `brand.canvas` so the off-white reads as the natural page surface.
3. **Semantic** — meaning-bearing colors for status: success, warning, danger, info. These sit alongside the brand palette but are not part of brand identity.
1. **Brand**Kode purple (`brand.primary` `#6B35A7`) plus its hover / pressed / light / soft variants, anchored by a purple-tinted ink (`brand.ink` `#1A1530` — never pure black) and the warm off-white canvas (`brand.canvas` `#F7F4ED`).
2. **Accent**`accent.gold` (`#C9892B`) is the product emphasis colour for submit / commit actions; `accent.mint` (`#46C194`) is reserved for marketing surfaces (workspace dashboard, decks). Use one accent per surface — never both.
3. **Neutral** — a purple-tinted 13-step ramp (`neutral.0``neutral.1000`). The ramp deliberately walks toward the brand ink rather than a cold grey, so muted text and borders stay on-brand. `neutral.50` is a warm inset surface, `neutral.100` aliases `brand.canvas`, `neutral.900` aliases `brand.ink`.
4. **Semantic**`success` / `warning` / `danger` / `info` plus matching `*Soft` background tints, tuned to sit calmly on the warm canvas (e.g. `success` is `#2F7A5A`, not the louder `#16A34A`).
Always reference *role* tokens (`text.default`, `surface.subtle`, `border.default`) in product code rather than raw palette values, so themes can swap without churn.
Always reference *role* tokens (`text.default`, `surface.canvas`, `border.default`) in product code — never raw palette values so themes can swap without churn.
Contrast minimums:
@@ -238,12 +302,13 @@ Elevation is conveyed through a small set of layered shadows plus subtle backgro
| Level | Use | Shadow |
|-------|-----|--------|
| 0 | flush surfaces, page background | none |
| 1 | cards, list rows | `0 1px 2px rgba(17,24,39,0.06)` |
| 2 | dropdowns, popovers | `0 4px 12px rgba(17,24,39,0.10)` |
| 3 | modals, dialogs | `0 16px 32px rgba(17,24,39,0.16)` |
| 4 | toasts, command bars | `0 24px 48px rgba(17,24,39,0.20)` |
| 1 | cards, list rows, buttons | `0 1px 2px rgba(26,21,48,0.04)` |
| 2 | dropdowns, popovers | `0 4px 12px -4px rgba(26,21,48,0.08)` |
| 3 | modals, dialogs | `0 16px 40px -16px rgba(26,21,48,0.18)` |
| 4 | toasts, command bars | `0 24px 80px -24px rgba(26,21,48,0.22)` |
| focusRing | any focusable element | `0 0 0 3px rgba(107,53,167,0.18)` |
In dark theme, shadows are de-emphasized and elevation is communicated primarily through lighter surface tints.
Shadows are tinted with the brand ink (`rgb(26 21 48)`) — not cold slate — so they read warm against the canvas. In dark theme, shadows are de-emphasized and elevation is communicated primarily through lighter surface tints.
## Shapes