From 9b1dcdab6eb9dfe9566a25468777f8878a3788ec Mon Sep 17 00:00:00 2001 From: Vigilio Desto Date: Fri, 10 Apr 2026 19:43:55 +0200 Subject: [PATCH] M3: migrate 01-asw.css to oklch --color-N palette system MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Surfaces and text now use Open Props --color-1 through --color-16. Change --palette-hue to retheme entire site from one value. Links stay fixed blue (oklch hue 250). State colors (ok/warn/error/info) use harmonized oklch at fixed hues — same lightness/chroma, independent of palette. Light mode flips the --color-N mapping. Removes all color-mix() accent variants — direct oklch values instead. --- assets/css/layers/01-asw.css | 237 +++++++++++++++++------------------ 1 file changed, 116 insertions(+), 121 deletions(-) diff --git a/assets/css/layers/01-asw.css b/assets/css/layers/01-asw.css index 5f188ce..2952f2c 100644 --- a/assets/css/layers/01-asw.css +++ b/assets/css/layers/01-asw.css @@ -3,6 +3,7 @@ * ASW semantic layer — builds on Open Props * * Open Props (imported in main.css) provides the base scales: + * --color-1…16 (oklch, palette-hue-tinted — the primary color scale) * --gray-0…15, --green-0…12, --blue-0…12, --red-0…12, --yellow-0…12 * --size-1…15, --font-size-0…8, --font-weight-1…9 * --font-lineheight-0…5, --radius-1…6, --shadow-1…6 @@ -16,8 +17,8 @@ * 4. A handful of precise values without direct OP equivalents * * To theme ASW: - * Override semantic aliases at :root in your own CSS. - * Use Open Props base tokens (--gray-*, --green-*, --size-*) as values. + * Set --palette-hue in your own CSS to shift all color-N surfaces/text. + * Override semantic aliases at :root for finer control. * * Lineage: absorbed patterns from Pico CSS, Open Props, Charts.css. */ @@ -31,57 +32,64 @@ /* ══════════════════════════════════════════════════════════════════ DARK THEME (default) - Using Open Props oklch gray scale — perceptually uniform steps. - Set --gray-hue to tint all surfaces. Example: - Trentuna: --gray-hue: 45 (warm amber tint) - vigilio-garden: --gray-hue: 150 (subtle green tint) + Using Open Props oklch --color-N 16-step palette. + Set --palette-hue to tint all surfaces and text. Example: + Trentuna: --palette-hue: 45 (warm amber tint) + vigilio-garden: --palette-hue: 150 (subtle green tint) ══════════════════════════════════════════════════════════════════ */ :root { - /* ── Surfaces ──────────────────────────────────────────────────── */ + /* ── Palette controls ─────────────────────────────────────────────── + --color-1 (lightest) through --color-16 (darkest) follow this hue. + Change --palette-hue to retheme all surfaces and text in one place. + ─────────────────────────────────────────────────────────────────── */ + --palette-hue: 250; /* blue-violet default */ + --palette-chroma: 0.15; - --surface: var(--gray-12); /* deepest background (oklch 10%) */ - --surface-1: var(--gray-11); /* cards, sidebars (oklch 18%) */ - --surface-2: var(--gray-10); /* hover, raised elements (oklch 25%) */ + /* ── Surfaces — dark end of the 16-step scale ─────────────────── */ + + --surface: var(--color-16); /* ~10% lightness */ + --surface-1: var(--color-15); /* ~16% */ + --surface-2: var(--color-14); /* ~20% */ --surface-card: var(--surface-1); --surface-hover: var(--surface-2); - /* ── Text ──────────────────────────────────────────────────────── */ + /* ── Text — light end of the scale ────────────────────────────── */ - --text: var(--gray-1); /* primary (95% lightness) */ - --text-2: var(--gray-3); /* secondary (80%) */ - --text-3: var(--gray-5); /* muted (68%) */ - --text-dim: var(--gray-7); /* dim (58%) */ + --text: var(--color-3); /* 93% lightness */ + --text-2: var(--color-5); /* 80% */ + --text-3: var(--color-7); /* 66% */ + --text-dim: var(--color-9); /* 53% */ - /* ── Accent ────────────────────────────────────────────────────── */ + /* ── Accent — peak chroma step, palette-driven ─────────────────── */ - --accent: var(--green-5); - --accent-hover: var(--green-4); - --on-accent: var(--gray-12); - --accent-focus: color-mix(in oklch, var(--green-5) 35%, transparent); - --accent-subtle: color-mix(in oklch, var(--green-5) 10%, transparent); - --accent-underline: color-mix(in oklch, var(--green-5) 45%, transparent); - --accent-hover-underline: color-mix(in oklch, var(--green-5) 55%, transparent); + --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-underline: oklch(58% 0.15 var(--palette-hue) / 0.45); + --accent-hover-underline: oklch(66% 0.15 var(--palette-hue) / 0.55); - /* ── Links ─────────────────────────────────────────────────────── */ - /* Blue — web convention. Accent (green) reserved for UI chrome. */ + /* ── Links — fixed blue hue, not palette-driven ───────────────── + Blue is the web convention. Accent is palette-tinted UI chrome. */ - --link: var(--blue-5); /* #339af0 */ - --link-hover: var(--blue-4); /* #4dabf7 */ - --link-underline: color-mix(in oklch, var(--blue-5) 40%, transparent); - --link-hover-underline: color-mix(in oklch, var(--blue-5) 55%, transparent); - --link-focus: color-mix(in oklch, var(--blue-5) 35%, transparent); + --link: oklch(65% 0.15 250); + --link-hover: oklch(72% 0.15 250); + --link-underline: oklch(65% 0.08 250); + --link-hover-underline: oklch(72% 0.10 250); + --link-focus: oklch(65% 0.06 250); - /* Secondary accents — reachable as named aliases */ - --accent-blue: var(--blue-5); - --accent-red: var(--red-7); - --accent-orange: var(--yellow-6); + /* 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 */ /* ── Border ────────────────────────────────────────────────────── */ - --border: var(--gray-11); /* 37% lightness — visible against 10% bg */ - --border-subtle: var(--gray-12); /* 31% lightness — very subtle */ + --border: var(--color-14); /* ~20% lightness */ + --border-subtle: var(--color-15); /* ~16% lightness */ --border-width: 1px; --outline-width: 2px; @@ -121,12 +129,12 @@ --h5-weight: var(--font-weight-6); /* 600 */ --h6-weight: var(--font-weight-6); - --h1-color: var(--text); - --h2-color: var(--text); - --h3-color: var(--text); - --h4-color: var(--text-2); - --h5-color: var(--text-2); - --h6-color: var(--text-3); + --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); /* ── Spacing aliases ───────────────────────────────────────────── Open Props sizes: --size-1 (.25rem), --size-2 (.5rem), --size-3 (1rem), @@ -174,16 +182,16 @@ /* ── Diff viewer tokens ──────────────────────────────────────────── */ - --diff-add-bg: color-mix(in oklch, var(--green-5) 10%, transparent); - --diff-remove-bg: color-mix(in oklch, var(--red-7) 10%, transparent); - --diff-remove-text: var(--red-2); - --diff-hunk-bg: color-mix(in oklch, var(--blue-4) 7%, transparent); + --diff-add-bg: color-mix(in oklch, var(--ok) 10%, transparent); + --diff-remove-bg: color-mix(in oklch, var(--error) 10%, transparent); + --diff-remove-text: oklch(88% 0.06 25); + --diff-hunk-bg: color-mix(in oklch, var(--info) 7%, transparent); /* ── AI-disclosure border tokens ────────────────────────────────── */ - --ai-generated-border: color-mix(in oklch, var(--green-5) 25%, transparent); - --ai-assisted-border: color-mix(in oklch, var(--blue-4) 20%, transparent); - --ai-mixed-border: color-mix(in oklch, var(--yellow-6) 30%, transparent); + --ai-generated-border: color-mix(in oklch, var(--ok) 25%, transparent); + --ai-assisted-border: color-mix(in oklch, var(--info) 20%, transparent); + --ai-mixed-border: color-mix(in oklch, var(--warn) 30%, transparent); /* ── Rhythm ─────────────────────────────────────────────────────── */ @@ -207,39 +215,39 @@ /* ── Inline element tokens ─────────────────────────────────────── */ - --selection: color-mix(in oklch, var(--blue-4) 25%, transparent); - --mark-bg: color-mix(in oklch, var(--yellow-6) 20%, transparent); - --mark-color: var(--accent-orange); - --kbd-bg: var(--text); - --kbd-color: var(--surface); - --code-color: var(--text-2); - --table-stripe: color-mix(in oklch, var(--gray-11) 50%, transparent); + --selection: oklch(65% 0.08 250 / 0.30); + --mark-bg: oklch(45% 0.10 80 / 0.40); + --mark-color: var(--accent-orange); + --kbd-bg: var(--text); + --kbd-color: var(--surface); + --code-color: var(--text-2); + --table-stripe: color-mix(in oklch, var(--color-15) 50%, transparent); /* ── Form tokens ─────────────────────────────────────────────────── */ --input-bg: var(--surface-1); --input-border: var(--border); --input-active-bg: var(--surface); - --input-selected: color-mix(in oklch, var(--green-5) 20%, transparent); + --input-selected: color-mix(in oklch, var(--accent) 20%, transparent); --input-px: var(--space-4); --input-py: var(--space-3); --disabled-opacity: 0.5; - /* ── State colors ─────────────────────────────────────────────────── */ + /* ── State colors — fixed hues, harmonized oklch ─────────────────── */ - --ok: var(--green-5); - --warn: var(--yellow-5); - --error: var(--red-7); - --info: var(--blue-5); - --blocked: var(--gray-5); + --ok: oklch(75% 0.15 145); /* green */ + --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); - --error-active: var(--red-9); - --error-focus: color-mix(in oklch, var(--red-7) 38%, transparent); + --error-active: oklch(65% 0.18 25); + --error-focus: oklch(65% 0.06 25); /* ── Component tokens ─────────────────────────────────────────────── */ --track-bg: var(--surface-2); /* progress / meter background */ - --modal-overlay: color-mix(in oklch, var(--gray-12) 80%, transparent); + --modal-overlay: color-mix(in oklch, var(--color-16) 80%, transparent); --modal-backdrop: blur(0.375rem); --accordion-active: var(--accent-hover); @@ -252,19 +260,19 @@ Propose additions to Open Props: data-task, data-callout, data-session. ══════════════════════════════════════════════════════════════════ */ - --task-done: var(--green-5); - --task-blocked: var(--red-5); - --task-wip: var(--yellow-5); - --task-todo: var(--gray-5); + --task-done: var(--ok); + --task-blocked: var(--error); + --task-wip: var(--warn); + --task-todo: var(--color-9); - --callout-info: var(--blue-5); - --callout-warn: var(--yellow-5); - --callout-error: var(--red-5); - --callout-note: var(--gray-5); + --callout-info: var(--info); + --callout-warn: var(--warn); + --callout-error: var(--error); + --callout-note: var(--color-9); --session-bg: var(--surface-1); - --wikilink: var(--blue-4); - --redacted: var(--gray-8); + --wikilink: var(--link); + --redacted: var(--color-11); } @@ -277,58 +285,45 @@ :root { color-scheme: light; - --surface: var(--gray-0); /* 99% lightness */ - --surface-1: var(--gray-1); /* 95% */ - --surface-2: var(--gray-2); /* 88% */ - --surface-card: var(--gray-0); - --surface-hover: var(--gray-1); + --surface: var(--color-1); /* 98% */ + --surface-1: var(--color-2); /* 97% */ + --surface-2: var(--color-3); /* 93% */ + --surface-card: var(--color-1); + --surface-hover: var(--color-2); - --text: var(--gray-11); /* 18% — dark but not pure black */ - --text-2: var(--gray-11); /* 37% */ - --text-3: var(--gray-8); /* 53% */ - --text-dim: var(--gray-6); /* 63% */ + --text: var(--color-14); /* 20% */ + --text-2: var(--color-12); /* 35% */ + --text-3: var(--color-10); /* 49% */ + --text-dim: var(--color-8); /* 58% */ - --accent: var(--green-8); - --accent-hover: var(--green-9); - --on-accent: var(--gray-0); - --accent-focus: color-mix(in oklch, var(--green-8) 35%, transparent); - --accent-subtle: color-mix(in oklch, var(--green-8) 10%, transparent); + --accent: var(--color-9); /* 53% — slightly darker for contrast on light */ + --accent-hover: var(--color-10); + --on-accent: var(--color-1); - --border: var(--gray-3); /* 80% — visible on near-white */ - --border-subtle: var(--gray-2); /* 88% — very subtle */ + --border: var(--color-4); /* 84% */ + --border-subtle: var(--color-3); /* 93% */ - --link: var(--blue-8); /* #1971c2 */ - --link-hover: var(--blue-7); /* #1c7ed6 */ - --link-underline: color-mix(in oklch, var(--blue-8) 40%, transparent); - --link-hover-underline: color-mix(in oklch, var(--blue-8) 55%, transparent); - --link-focus: color-mix(in oklch, var(--blue-8) 35%, transparent); + --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(--gray-12); - --h2-color: var(--gray-11); - --h3-color: var(--gray-10); - --h4-color: var(--gray-12); - --h5-color: var(--gray-11); - --h6-color: var(--gray-10); + --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); - --mark-bg: color-mix(in oklch, var(--yellow-6) 15%, var(--surface)); - --mark-color: var(--gray-12); - --selection: color-mix(in oklch, var(--blue-8) 20%, transparent); + --ok: oklch(40% 0.15 145); + --warn: oklch(40% 0.15 80); + --error: oklch(40% 0.15 25); + --info: oklch(40% 0.15 250); - --code-color: var(--text-3); - --table-stripe: color-mix(in oklch, var(--gray-8) 4%, transparent); - - --input-bg: var(--gray-0); - --input-border: var(--gray-4); - --input-active-bg: var(--gray-0); - --input-selected: var(--gray-2); - - --track-bg: var(--gray-3); - --modal-overlay: color-mix(in oklch, var(--gray-2) 75%, transparent); - - --error: oklch(50% 0.17 20); - --error-active: oklch(44% 0.18 20); - - --session-bg: var(--surface-1); + --mark-bg: oklch(92% 0.08 80); + --mark-color: var(--color-15); + --selection: oklch(80% 0.06 250); } }