spb/ultra-sharp-agent-skills Public
Ultra-Sharp Agent Skills — a research-first skill-authoring system + 72 production-ready skills for AI agents.
Python 100%
1<!--2Author: Simon-Pierre Boucher3Contact: contact@spboucher.ai4-->56# Patterns — Design Tokens & Theming78## Contents9- Starter token sheet (primitives)10- Semantic tokens, light + dark11- Component tier example12- Theme toggle (no-flash)13- Contrast quick-check14- Gotchas1516## Starter token sheet (primitives)1718```css19:root {20 /* Neutral ramp (5 steps is enough to start) */21 --gray-50: #f8fafc;22 --gray-200: #e2e8f0;23 --gray-500: #64748b;24 --gray-800: #1e293b;25 --gray-950: #0b1220;2627 /* Accent ramp */28 --blue-400: #60a5fa;29 --blue-600: #2563eb;30 --blue-700: #1d4ed8;3132 /* Status */33 --green-600: #16a34a;34 --amber-600: #d97706;35 --red-600: #dc2626;3637 /* Spacing — base-4 scale */38 --space-1: 0.25rem; --space-2: 0.5rem; --space-3: 0.75rem;39 --space-4: 1rem; --space-6: 1.5rem; --space-8: 2rem;40 --space-12: 3rem; --space-16: 4rem;4142 /* Radius & shadows — 3 levels each */43 --radius-sm: 0.25rem; --radius-md: 0.5rem; --radius-full: 9999px;44 --shadow-1: 0 1px 2px rgb(0 0 0 / 0.06);45 --shadow-2: 0 4px 8px rgb(0 0 0 / 0.10);46 --shadow-3: 0 12px 24px rgb(0 0 0 / 0.14);4748 color-scheme: light dark;49}50```5152## Semantic tokens, light + dark5354```css55/* Light (default) */56:root, [data-theme="light"] {57 --color-bg-page: var(--gray-50);58 --color-bg-surface: #ffffff;59 --color-text: var(--gray-800); /* on bg-page: 12.6:1 ✓ */60 --color-text-muted: var(--gray-500); /* on surface: 4.8:1 ✓ */61 --color-border: var(--gray-200);62 --color-accent: var(--blue-600); /* as text on surface: 5.2:1 ✓ */63 --color-accent-hover: var(--blue-700);64 --color-danger: var(--red-600);65}6667/* Dark via system preference (only when no explicit choice) */68@media (prefers-color-scheme: dark) {69 :root:not([data-theme]) {70 --color-bg-page: var(--gray-950);71 --color-bg-surface: var(--gray-800);72 --color-text: var(--gray-50);73 --color-text-muted: #94a3b8; /* on gray-800: 5.9:1 ✓ */74 --color-border: #334155;75 --color-accent: var(--blue-400); /* lighter accent for dark bg: 6.6:1 ✓ */76 --color-accent-hover: #93c5fd;77 }78}7980/* Dark via explicit user choice — identical block, attribute-scoped */81[data-theme="dark"] {82 --color-bg-page: var(--gray-950);83 --color-bg-surface: var(--gray-800);84 --color-text: var(--gray-50);85 --color-text-muted: #94a3b8;86 --color-border: #334155;87 --color-accent: var(--blue-400);88 --color-accent-hover: #93c5fd;89}90```9192## Component tier example9394```css95.button-primary {96 background: var(--color-accent);97 color: var(--color-bg-surface);98 padding: var(--space-2) var(--space-4);99 border-radius: var(--radius-md);100 box-shadow: var(--shadow-1);101}102.button-primary:hover { background: var(--color-accent-hover); }103104.card {105 background: var(--color-bg-surface);106 border: 1px solid var(--color-border);107 border-radius: var(--radius-md);108 padding: var(--space-6);109}110```111112## Theme toggle (no-flash)113114```html115<!-- In <head>, BEFORE any stylesheet, so first paint is themed -->116<script>117 const t = localStorage.getItem("theme"); // "light" | "dark" | null118 if (t) document.documentElement.dataset.theme = t; // absent = follow system119</script>120```121122```js123function setTheme(next) { // next: "light" | "dark" | "system"124 if (next === "system") {125 delete document.documentElement.dataset.theme;126 localStorage.removeItem("theme");127 } else {128 document.documentElement.dataset.theme = next;129 localStorage.setItem("theme", next);130 }131}132```133134## Contrast quick-check135136Compute ratio = (L1 + 0.05) / (L2 + 0.05) with relative luminance, or verify in137devtools (element → color picker shows the ratio). Thresholds to enforce **in138the token sheet**:139140| Pair | Minimum |141|---|---|142| Body/label text on its background | 4.5:1 (AA) |143| Large text ≥24px (or 18.7px bold) | 3:1 |144| UI component borders, icons, focus rings | 3:1 |145146## Gotchas147148- **`prefers-color-scheme` block must exclude explicit choices** — scope it with `:root:not([data-theme])` or a user who picked "light" gets system-dark anyway.149- **Forgetting `color-scheme: light dark`** leaves scrollbars, form controls, and default UA styles stuck in light mode.150- **Muted text is the #1 AA failure** — grays around `#999` fail on white (2.8:1). Nothing lighter than `#767676` for body-size text on white.151- **Same accent in both themes usually fails one of them** — accents need a per-theme value (darker for light bg, lighter for dark bg).152- **`rgb(0 0 0 / 0.5)`-style translucent text** has no fixed contrast ratio (depends on what's behind) — use opaque token colors for text.153- **Tokens in shadows:** define whole shadows as tokens, not just colors — dark themes often need different alpha, not different hue.154