diff --git a/core/base.css b/core/base.css index cc4af6f5..d297c28f 100644 --- a/core/base.css +++ b/core/base.css @@ -35,6 +35,31 @@ --sf-color-error: var(--sf-color-error-dark); --sf-color-info: var(--sf-color-info-dark); --sf-color-danger: var(--sf-color-danger-dark); + + /* Text — inverted direction for dark backgrounds, clamped for any neutral value */ + --sf-color-text: oklch(from var(--sf-color-neutral) clamp(0.70, calc(l + 0.25), 1) c h); + --sf-color-text--secondary: oklch(from var(--sf-color-neutral) clamp(0.55, calc(l + 0.1), 0.90) c h); + --sf-color-text--placeholder: oklch(from var(--sf-color-neutral) clamp(0.35, calc(l - 0.1), 0.65) c h); + --sf-color-text--disabled: oklch(from var(--sf-color-neutral) clamp(0.25, calc(l - 0.2), 0.55) c h); + --sf-color-text--inverse: oklch(from var(--sf-color-neutral) calc(l - 0.4) c h); + --sf-color-heading: oklch(from var(--sf-color-neutral) clamp(0.70, calc(l + 0.25), 1) c h); + + /* Borders — adjusted for dark backgrounds, clamped for any neutral value */ + --sf-color-border: oklch(from var(--sf-color-neutral) clamp(0.25, calc(l - 0.3), 0.55) 0.005 h); + --sf-color-border--subtle: oklch(from var(--sf-color-neutral) clamp(0.20, calc(l - 0.38), 0.45) 0.005 h); + --sf-color-border--strong: oklch(from var(--sf-color-neutral) clamp(0.38, calc(l - 0.1), 0.65) 0.02 h); + --sf-color-border--disabled: oklch(from var(--sf-color-neutral) clamp(0.25, calc(l - 0.3), 0.55) 0.005 h); + --sf-color-border--translucent: oklch(from var(--sf-color-neutral) l c h / 0.15); + + /* Shadow strength — more visible on dark surfaces */ + --sf-shadow-strength: 0.25; + + /* Status text — lightened for dark backgrounds, clamped */ + --sf-status-success-text: oklch(from var(--sf-color-success) clamp(0.70, calc(l + 0.15), 1) c h); + --sf-status-warning-text: oklch(from var(--sf-color-warning) clamp(0.70, calc(l + 0.05), 1) c h); + --sf-status-error-text: oklch(from var(--sf-color-error) clamp(0.70, calc(l + 0.15), 1) c h); + --sf-status-info-text: oklch(from var(--sf-color-info) clamp(0.70, calc(l + 0.15), 1) c h); + --sf-status-danger-text: var(--sf-status-error-text); } } @@ -49,6 +74,11 @@ /* ---------------------------------------------------------- Dark mode — swap brand & status colors to -dark variants. Works on :root (whole page) or any element (section-level). + + NOTE: The derived semantic overrides (text, border, shadow, + status text) are duplicated in the @media block above. + CSS has no syntax to share declarations across a media + condition and a selector — keep both blocks in sync. ---------------------------------------------------------- */ [data-theme="dark"] { @@ -64,6 +94,31 @@ --sf-color-error: var(--sf-color-error-dark); --sf-color-info: var(--sf-color-info-dark); --sf-color-danger: var(--sf-color-danger-dark); + + /* Text — inverted direction for dark backgrounds, clamped for any neutral value */ + --sf-color-text: oklch(from var(--sf-color-neutral) clamp(0.70, calc(l + 0.25), 1) c h); + --sf-color-text--secondary: oklch(from var(--sf-color-neutral) clamp(0.55, calc(l + 0.1), 0.90) c h); + --sf-color-text--placeholder: oklch(from var(--sf-color-neutral) clamp(0.35, calc(l - 0.1), 0.65) c h); + --sf-color-text--disabled: oklch(from var(--sf-color-neutral) clamp(0.25, calc(l - 0.2), 0.55) c h); + --sf-color-text--inverse: oklch(from var(--sf-color-neutral) calc(l - 0.4) c h); + --sf-color-heading: oklch(from var(--sf-color-neutral) clamp(0.70, calc(l + 0.25), 1) c h); + + /* Borders — adjusted for dark backgrounds, clamped for any neutral value */ + --sf-color-border: oklch(from var(--sf-color-neutral) clamp(0.25, calc(l - 0.3), 0.55) 0.005 h); + --sf-color-border--subtle: oklch(from var(--sf-color-neutral) clamp(0.20, calc(l - 0.38), 0.45) 0.005 h); + --sf-color-border--strong: oklch(from var(--sf-color-neutral) clamp(0.38, calc(l - 0.1), 0.65) 0.02 h); + --sf-color-border--disabled: oklch(from var(--sf-color-neutral) clamp(0.25, calc(l - 0.3), 0.55) 0.005 h); + --sf-color-border--translucent: oklch(from var(--sf-color-neutral) l c h / 0.15); + + /* Shadow strength — more visible on dark surfaces */ + --sf-shadow-strength: 0.25; + + /* Status text — lightened for dark backgrounds, clamped */ + --sf-status-success-text: oklch(from var(--sf-color-success) clamp(0.70, calc(l + 0.15), 1) c h); + --sf-status-warning-text: oklch(from var(--sf-color-warning) clamp(0.70, calc(l + 0.05), 1) c h); + --sf-status-error-text: oklch(from var(--sf-color-error) clamp(0.70, calc(l + 0.15), 1) c h); + --sf-status-info-text: oklch(from var(--sf-color-info) clamp(0.70, calc(l + 0.15), 1) c h); + --sf-status-danger-text: var(--sf-status-error-text); } /* ---------------------------------------------------------- diff --git a/core/layout.css b/core/layout.css index 9dbc9b67..43c8696d 100644 --- a/core/layout.css +++ b/core/layout.css @@ -104,6 +104,7 @@ .sf-cluster--2xs { gap: var(--sf-space-2xs); } .sf-cluster--xs { gap: var(--sf-space-xs); } .sf-cluster--s { gap: var(--sf-space-s); } + .sf-cluster--m { gap: var(--sf-space-m); } .sf-cluster--l { gap: var(--sf-space-l); } .sf-cluster--xl { gap: var(--sf-space-xl); } diff --git a/core/tokens.css b/core/tokens.css index 9e31b460..a9527fbf 100644 --- a/core/tokens.css +++ b/core/tokens.css @@ -63,41 +63,46 @@ /* ---------------------------------------------------------- Text — derived from --sf-color-neutral + clamp() ensures safe output for any neutral value. ---------------------------------------------------------- */ - --sf-color-text: oklch(from var(--sf-color-neutral) calc(l - 0.4) c h); - --sf-color-text--secondary: oklch(from var(--sf-color-neutral) calc(l - 0.25) c h); + --sf-color-text: oklch(from var(--sf-color-neutral) clamp(0.05, calc(l - 0.4), 0.35) c h); + --sf-color-text--secondary: oklch(from var(--sf-color-neutral) clamp(0.15, calc(l - 0.25), 0.45) c h); --sf-color-text--muted: var(--sf-color-neutral); - --sf-color-text--placeholder: oklch(from var(--sf-color-neutral) calc(l + 0.15) c h); - --sf-color-text--disabled: oklch(from var(--sf-color-neutral) calc(l + 0.25) c h); + --sf-color-text--placeholder: oklch(from var(--sf-color-neutral) clamp(0.45, calc(l + 0.15), 0.75) c h); + --sf-color-text--disabled: oklch(from var(--sf-color-neutral) clamp(0.55, calc(l + 0.25), 0.82) c h); --sf-color-text--inverse: oklch(from var(--sf-color-neutral) calc(l + 0.4) c h); - --sf-color-heading: oklch(from var(--sf-color-neutral) calc(l - 0.4) c h); + --sf-color-heading: oklch(from var(--sf-color-neutral) clamp(0.05, calc(l - 0.4), 0.35) c h); /* ---------------------------------------------------------- - Text-on-color — white or dark based on luminance + Text-on-color — auto white or dark based on source luminance. + sign(0.6 - l): +1 when dark bg (l<0.6) → light text (0.95), + -1 when light bg (l>0.6) → dark text (0.10). + Works automatically in dark mode: tokens reference the active + color which is already swapped to its -dark variant. ---------------------------------------------------------- */ - --sf-color-text--on-primary: oklch(1 0 0); - --sf-color-text--on-secondary: oklch(0.97 0.005 260); - --sf-color-text--on-tertiary: oklch(1 0 0); - --sf-color-text--on-action: oklch(1 0 0); - --sf-color-text--on-neutral: oklch(1 0 0); + --sf-color-text--on-primary: oklch(from var(--sf-color-primary) clamp(0.1, sign(0.6 - l) * 999, 0.95) 0 0); + --sf-color-text--on-secondary: oklch(from var(--sf-color-secondary) clamp(0.1, sign(0.6 - l) * 999, 0.95) 0 0); + --sf-color-text--on-tertiary: oklch(from var(--sf-color-tertiary) clamp(0.1, sign(0.6 - l) * 999, 0.95) 0 0); + --sf-color-text--on-action: oklch(from var(--sf-color-action) clamp(0.1, sign(0.6 - l) * 999, 0.95) 0 0); + --sf-color-text--on-neutral: oklch(from var(--sf-color-neutral) clamp(0.1, sign(0.6 - l) * 999, 0.95) 0 0); --sf-color-text--on-base: var(--sf-color-text); --sf-color-text--on-inverse: var(--sf-color-text--inverse); - --sf-color-text--on-success: oklch(1 0 0); - --sf-color-text--on-warning: oklch(0.2 0.02 70); - --sf-color-text--on-error: oklch(1 0 0); - --sf-color-text--on-info: oklch(1 0 0); - --sf-color-text--on-danger: oklch(1 0 0); + --sf-color-text--on-success: oklch(from var(--sf-color-success) clamp(0.1, sign(0.6 - l) * 999, 0.95) 0 0); + --sf-color-text--on-warning: oklch(from var(--sf-color-warning) clamp(0.1, sign(0.6 - l) * 999, 0.95) 0 0); + --sf-color-text--on-error: oklch(from var(--sf-color-error) clamp(0.1, sign(0.6 - l) * 999, 0.95) 0 0); + --sf-color-text--on-info: oklch(from var(--sf-color-info) clamp(0.1, sign(0.6 - l) * 999, 0.95) 0 0); + --sf-color-text--on-danger: oklch(from var(--sf-color-danger) clamp(0.1, sign(0.6 - l) * 999, 0.95) 0 0); /* ---------------------------------------------------------- Borders — derived from --sf-color-neutral ---------------------------------------------------------- */ - --sf-color-border: oklch(from var(--sf-color-neutral) calc(l + 0.35) 0.005 h); - --sf-color-border--subtle: oklch(from var(--sf-color-neutral) calc(l + 0.4) 0.005 h); - --sf-color-border--strong: oklch(from var(--sf-color-neutral) calc(l + 0.1) 0.02 h); + --sf-color-border: oklch(from var(--sf-color-neutral) clamp(0.70, calc(l + 0.35), 0.95) 0.005 h); + --sf-color-border--subtle: oklch(from var(--sf-color-neutral) clamp(0.75, calc(l + 0.4), 0.97) 0.005 h); + --sf-color-border--strong: oklch(from var(--sf-color-neutral) clamp(0.55, calc(l + 0.1), 0.85) 0.02 h); --sf-color-border--focus: var(--sf-color-action); - --sf-color-border--disabled: oklch(from var(--sf-color-neutral) calc(l + 0.35) 0.005 h); + --sf-color-border--disabled: oklch(from var(--sf-color-neutral) clamp(0.70, calc(l + 0.35), 0.95) 0.005 h); --sf-color-border--translucent: oklch(from var(--sf-color-neutral) l c h / 0.15); diff --git a/docs/demo.html b/docs/demo.html index e750e50a..088410d3 100644 --- a/docs/demo.html +++ b/docs/demo.html @@ -83,7 +83,6 @@ } #main { - flex: 1; min-width: 0; } @@ -188,8 +187,8 @@ /* ── radius swatches ──────────────────────────────────── */ .demo-radius-swatch { - width: 4.5rem; - height: 4.5rem; + width: 6rem; + height: 5rem; background: var(--sf-color-primary-200, color-mix(in oklch, var(--sf-color-primary) 25%, var(--sf-color-bg))); border: 2px solid var(--sf-color-primary); display: flex; @@ -233,11 +232,12 @@ background: var(--sf-color-primary); position: absolute; top: 0; + left: 0; } @keyframes demo-slide { - from { translate: 0; } - to { translate: calc(100% - 2rem); } + from { left: 0; } + to { left: calc(100% - 2rem); } } .demo-motion-warning { @@ -395,7 +395,7 @@
-