feat: oklch color system, hamburger nav, theme toggle, footer, CSS fixes

Color system:
- Replace all --color-N references in dark mode with oklch()
- Fine-grained surface steps (12%→15%→18%→21%→22%)
- Smooth text gradient (92%→78%→62%→48%)
- Heading hierarchy (95%→65%)
- All palette-driven via --palette-hue and --palette-chroma

Navigation:
- Hamburger menu for mobile (data-nav-toggle + JS)
- Theme toggle button (sun/moon, localStorage persistence)
- data-theme="light|dark" override on <html>
- Cleaned nav CSS, removed old dropdown conflicts

Footer:
- Three-column nav grid (Framework, Resources, Project)
- Branding header + tagline
- Proper semantic structure (header + 3 nav + p)

Fixes:
- Sidebar: compact spacing, --sidebar-link-max token
- TOC: compact, scroll spy with IntersectionObserver
- Prev/next: inline arrows, data-role="prev-next" restored
- Section dividers scoped to article/main only
- Grid columns use tokens not hardcoded values

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Ludo 2026-04-11 20:43:56 +02:00
parent e0bda45953
commit 6d654e884b
Signed by: ludo
GPG key ID: F6E479DEFAB84D6E
12 changed files with 390 additions and 195 deletions

View file

@ -52,28 +52,31 @@
--palette-hue: 250; /* blue-violet default */
--palette-chroma: 0.15;
/* ── Surfaces — dark end of the 16-step scale ─────────────────── */
/* ── Surfaces — oklch for fine-grained dark steps ────────────── */
/* Open Props' 16-step scale is too coarse in the dark end.
We use oklch directly with palette-hue for precise control. */
--surface: var(--color-14); /* ~10% lightness */
--surface-1: var(--color-13); /* ~16% */
--surface-2: var(--color-11); /* ~20% */
--surface: oklch(12% 0.02 var(--palette-hue));
--surface-1: oklch(15% 0.02 var(--palette-hue));
--surface-2: oklch(18% 0.02 var(--palette-hue));
--surface-3: oklch(21% 0.02 var(--palette-hue));
--surface-card: var(--surface-1);
--surface-hover: var(--surface-2);
--surface-hover: oklch(22% 0.03 var(--palette-hue));
/* ── Text — light end of the scale ────────────────────────────── */
/* ── Text — smooth gradient from bright to muted ────────────── */
--text: var(--color-6); /* 93% lightness */
--text-2: var(--color-5); /* 80% */
--text-3: var(--color-7); /* 66% */
--text-dim: var(--color-9); /* 53% */
--text: oklch(92% 0.02 var(--palette-hue));
--text-2: oklch(78% 0.03 var(--palette-hue));
--text-3: oklch(62% 0.03 var(--palette-hue));
--text-dim: oklch(48% 0.03 var(--palette-hue));
/* ── Accent — peak chroma step, palette-driven ─────────────────── */
/* ── Accent — peak chroma, palette-driven ─────────────────────── */
--accent: var(--color-8); /* 58%, peak chroma */
--accent-hover: var(--color-7); /* 66% */
--on-accent: var(--color-16);
--accent-focus: oklch(58% 0.15 var(--palette-hue) / 0.35);
--accent-subtle: oklch(58% 0.15 var(--palette-hue) / 0.10);
--accent: oklch(65% var(--palette-chroma) var(--palette-hue));
--accent-hover: oklch(72% var(--palette-chroma) var(--palette-hue));
--on-accent: oklch(5% 0.02 var(--palette-hue));
--accent-focus: oklch(65% var(--palette-chroma) var(--palette-hue) / 0.35);
--accent-subtle: oklch(65% var(--palette-chroma) var(--palette-hue) / 0.10);
/* Links fixed blue hue, not palette-driven
Blue is the web convention. Accent is palette-tinted UI chrome. */
@ -85,14 +88,14 @@
--link-focus: oklch(65% 0.06 250);
/* Secondary accents — fixed hues, not palette-driven */
--accent-blue: oklch(65% 0.15 250); /* matches --link */
--accent-red: oklch(65% 0.18 25); /* matches --error */
--accent-orange: oklch(75% 0.15 80); /* matches --warn */
--accent-blue: oklch(65% 0.15 250);
--accent-red: oklch(65% 0.18 25);
--accent-orange: oklch(75% 0.15 80);
/* ── Border ────────────────────────────────────────────────────── */
/* ── Border — subtle steps between surfaces ────────────────────── */
--border: var(--color-14); /* ~20% lightness */
--border-subtle: var(--color-15); /* ~16% lightness */
--border: oklch(25% 0.03 var(--palette-hue));
--border-subtle: oklch(20% 0.02 var(--palette-hue));
--border-width: 1px;
--outline-width: 2px;
@ -131,12 +134,12 @@
--h5-weight: var(--font-weight-6); /* 600 */
--h6-weight: var(--font-weight-6);
--h1-color: var(--color-2);
--h2-color: var(--color-3);
--h3-color: var(--color-3);
--h4-color: var(--color-5);
--h5-color: var(--color-5);
--h6-color: var(--color-7);
--h1-color: oklch(95% 0.02 var(--palette-hue));
--h2-color: oklch(90% 0.02 var(--palette-hue));
--h3-color: oklch(85% 0.03 var(--palette-hue));
--h4-color: oklch(78% 0.03 var(--palette-hue));
--h5-color: oklch(72% 0.03 var(--palette-hue));
--h6-color: oklch(65% 0.03 var(--palette-hue));
/* Spacing aliases
Open Props sizes: --size-1 (.25rem), --size-2 (.5rem), --size-3 (1rem),
@ -171,8 +174,11 @@
--container-padding: var(--space-4); /* inline padding at small viewports */
/* Structural dimensions */
--sidebar-width: 220px; /* docs sidebar column */
--toc-width: 200px; /* docs TOC column */
--sidebar-link-max: var(--size-12); /* max-width for sidebar nav links */
--sidebar-min: 10rem; /* docs sidebar column min */
--sidebar-max: 14rem; /* docs sidebar column max */
--toc-min: 10rem; /* docs TOC column min */
--toc-max: 13rem; /* docs TOC column max */
--nav-height: 60px; /* sticky nav offset */
--docs-max-width: 1400px; /* docs layout outer cap */
--card-min-width: 280px; /* card-grid minmax floor */
@ -227,7 +233,7 @@
--kbd-bg: var(--text);
--kbd-color: var(--surface);
--code-color: var(--text-2);
--table-stripe: color-mix(in oklch, var(--color-15) 50%, transparent);
--table-stripe: oklch(8% 0.01 var(--palette-hue) / 0.50);
/* ── Form tokens ─────────────────────────────────────────────────── */
@ -245,7 +251,7 @@
--warn: oklch(75% 0.15 80); /* amber */
--error: oklch(75% 0.15 25); /* red */
--info: oklch(75% 0.15 250); /* blue */
--blocked: var(--color-9);
--blocked: oklch(48% 0.03 var(--palette-hue));
--error-active: oklch(65% 0.18 25);
--error-focus: oklch(65% 0.06 25);
@ -253,7 +259,7 @@
/* ── Component tokens ─────────────────────────────────────────────── */
--track-bg: var(--surface-2); /* progress / meter background */
--modal-overlay: color-mix(in oklch, var(--color-16) 80%, transparent);
--modal-overlay: oklch(5% 0.01 var(--palette-hue) / 0.80);
--modal-backdrop: blur(0.375rem);
--accordion-active: var(--accent-hover);
@ -287,8 +293,8 @@
Hues are FIXED (like state colors) not palette-driven.
*/
--syntax-comment: var(--color-9); /* muted — same as --text-dim */
--syntax-punctuation: var(--color-9); /* same muted level */
--syntax-comment: oklch(48% 0.03 var(--palette-hue)); /* same as --text-dim */
--syntax-punctuation: oklch(48% 0.03 var(--palette-hue)); /* same muted level */
--syntax-string: oklch(75% 0.15 145); /* green — same as --ok */
--syntax-keyword: oklch(72% 0.15 250); /* blue — close to --link-hover */
--syntax-property: oklch(65% 0.15 250); /* blue — same as --link */
@ -372,6 +378,73 @@
}
/*
MANUAL THEME OVERRIDE data-theme attribute on <html>
Mirrors the prefers-color-scheme block above.
Set by the theme toggle button + persisted in localStorage.
*/
:root[data-theme="light"] {
color-scheme: light;
--surface: var(--color-1);
--surface-1: var(--color-2);
--surface-2: var(--color-3);
--surface-card: var(--color-1);
--surface-hover: var(--color-2);
--text: var(--color-14);
--text-2: var(--color-12);
--text-3: var(--color-10);
--text-dim: var(--color-8);
--accent: var(--color-9);
--accent-hover: var(--color-10);
--on-accent: var(--color-1);
--border: var(--color-4);
--border-subtle: var(--color-3);
--link: oklch(45% 0.15 250);
--link-hover: oklch(38% 0.15 250);
--link-underline: oklch(45% 0.08 250);
--link-hover-underline: oklch(38% 0.10 250);
--link-focus: oklch(45% 0.06 250);
--h1-color: var(--color-16);
--h2-color: var(--color-15);
--h3-color: var(--color-14);
--h4-color: var(--color-13);
--h5-color: var(--color-12);
--h6-color: var(--color-11);
--ok: oklch(40% 0.15 145);
--warn: oklch(40% 0.15 80);
--error: oklch(40% 0.15 25);
--info: oklch(40% 0.15 250);
--mark-bg: oklch(92% 0.08 80);
--mark-color: var(--color-15);
--selection: oklch(80% 0.06 250);
--syntax-comment: var(--color-8);
--syntax-punctuation: var(--color-10);
--syntax-string: oklch(40% 0.15 145);
--syntax-keyword: oklch(38% 0.15 250);
--syntax-property: oklch(45% 0.15 250);
--syntax-variable: oklch(40% 0.15 80);
--syntax-deleted: oklch(40% 0.15 25);
--syntax-inserted: oklch(40% 0.15 145);
--syntax-namespace: oklch(40% 0.15 80);
--syntax-url: var(--link);
}
/* Force dark when OS is light but user chose dark */
:root[data-theme="dark"] {
color-scheme: dark;
}
/*
RESPONSIVE FONT SCALING
Subtle upscaling at large viewports all rem values follow.