@bsuite/theme 0.7.0 → 0.7.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +2 -2
- package/src/css/braden.css +196 -201
- package/src/css/vars.css +64 -12
- package/src/preset-v4.css +5 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bsuite/theme",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
6
|
"publishConfig": {
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
"url": "https://github.com/GaryOcean428/bsuite.git",
|
|
12
12
|
"directory": "packages/theme"
|
|
13
13
|
},
|
|
14
|
-
"description": "BSuite Universal theme
|
|
14
|
+
"description": "BSuite Universal theme — D2C Neon Electric + Braden Corporate baselines. Tailwind v4 preset, CSS vars (5-layer), role aliases, colourblind-safe tokens, eye-strain-safe text scale, BrandingProvider (runtime white-label). Used by BSU, CRM7, conduit, R80.3, throughput (D2C) and braden.com.au (Corporate).",
|
|
15
15
|
"files": [
|
|
16
16
|
"dist",
|
|
17
17
|
"src/css",
|
package/src/css/braden.css
CHANGED
|
@@ -1,230 +1,225 @@
|
|
|
1
1
|
/*
|
|
2
2
|
* @bsuite/theme — Braden Corporate brand baseline
|
|
3
|
-
* Version 0.
|
|
3
|
+
* Version 0.4.0
|
|
4
4
|
*
|
|
5
5
|
* Usage (braden.com.au only):
|
|
6
6
|
* @import '@bsuite/theme/braden-css';
|
|
7
7
|
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
8
|
+
* EXCLUSIVELY for the braden.com.au Corporate brand. Never import this into a
|
|
9
|
+
* D2C app (crm7, conduit, BSU, R80.3, throughput), and never put Neon Electric
|
|
10
|
+
* colours on a Corporate surface.
|
|
11
11
|
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
12
|
+
* GENERATED FROM THE CONTRACT, NOT HAND-TUNED.
|
|
13
|
+
* Every value below is copied from
|
|
14
|
+
* packages/theme/docs/braden-corporate-theme-source-of-truth.html
|
|
15
|
+
* which is authoritative. Operator ruling 2026-08-03: only colours present in
|
|
16
|
+
* the two source-of-truth documents are permitted in packages/. Verify with
|
|
17
|
+
* scripts/audit-palette-whitelist.py
|
|
18
18
|
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
19
|
+
* WHAT CHANGED IN 0.4.0 AND WHY IT MATTERED
|
|
20
|
+
* 0.3.0 carried its own hand-built red/gold/navy ramps. 52 of its values
|
|
21
|
+
* appeared nowhere in the Corporate contract — close to the brand, but not the
|
|
22
|
+
* brand, and drifting further with every edit. This file also shipped a header
|
|
23
|
+
* asserting "purple error is a cross-brand system requirement", which was
|
|
24
|
+
* already false twice over: the 0.7.0 separation-first contract retired purple
|
|
25
|
+
* for semantics, and the Corporate contract binds error to --braden-indigo.
|
|
22
26
|
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
* supported Tailwind engine for BSuite consumers.
|
|
27
|
+
* ERROR IS INDIGO HERE, NOT RED — deliberately, and for the opposite reason to
|
|
28
|
+
* D2C. D2C's primary is blue, so error must be red to separate from it.
|
|
29
|
+
* Corporate's primary IS red, so a red error would collide with the brand's
|
|
30
|
+
* own primary action colour. Same rule, inverted inputs.
|
|
28
31
|
*/
|
|
29
32
|
|
|
30
|
-
/* ============================================================
|
|
31
|
-
LAYER 1 — BRADEN CORPORATE PALETTE PRIMITIVES
|
|
32
|
-
============================================================ */
|
|
33
|
-
:root {
|
|
34
|
-
/* Primary — Braden Red scale */
|
|
35
|
-
--braden-red-50: oklch(0.965 0.015 17);
|
|
36
|
-
--braden-red-100: oklch(0.930 0.035 17);
|
|
37
|
-
--braden-red-200: oklch(0.870 0.070 18);
|
|
38
|
-
--braden-red-300: oklch(0.780 0.110 18);
|
|
39
|
-
--braden-red-400: oklch(0.660 0.145 18);
|
|
40
|
-
--braden-red-500: oklch(0.550 0.175 18); /* main brand red */
|
|
41
|
-
--braden-red-600: oklch(0.488 0.170 17.6); /* canonical –- oklch spec */
|
|
42
|
-
--braden-red-700: oklch(0.420 0.150 17);
|
|
43
|
-
--braden-red-800: oklch(0.340 0.120 16);
|
|
44
|
-
--braden-red-900: oklch(0.260 0.090 15);
|
|
45
|
-
|
|
46
|
-
/* Accent — Braden Gold scale */
|
|
47
|
-
--braden-gold-50: oklch(0.980 0.015 88);
|
|
48
|
-
--braden-gold-100: oklch(0.955 0.035 89);
|
|
49
|
-
--braden-gold-200: oklch(0.910 0.060 90);
|
|
50
|
-
--braden-gold-300: oklch(0.860 0.078 91);
|
|
51
|
-
--braden-gold-400: oklch(0.829 0.073 91.8); /* light gold */
|
|
52
|
-
--braden-gold-500: oklch(0.769 0.096 90.9); /* canonical accent */
|
|
53
|
-
--braden-gold-600: oklch(0.711 0.115 89.5); /* bronze */
|
|
54
|
-
--braden-gold-700: oklch(0.630 0.110 88);
|
|
55
|
-
--braden-gold-800: oklch(0.520 0.090 86);
|
|
56
|
-
--braden-gold-900: oklch(0.400 0.065 84);
|
|
57
|
-
|
|
58
|
-
/* Navy — secondary brand colour */
|
|
59
|
-
--braden-navy-50: oklch(0.960 0.008 249);
|
|
60
|
-
--braden-navy-100: oklch(0.920 0.015 249);
|
|
61
|
-
--braden-navy-200: oklch(0.840 0.025 249);
|
|
62
|
-
--braden-navy-300: oklch(0.720 0.030 249);
|
|
63
|
-
--braden-navy-400: oklch(0.580 0.033 249);
|
|
64
|
-
--braden-navy-500: oklch(0.450 0.035 249);
|
|
65
|
-
--braden-navy-600: oklch(0.356 0.039 249); /* canonical navy */
|
|
66
|
-
--braden-navy-700: oklch(0.280 0.030 248);
|
|
67
|
-
--braden-navy-800: oklch(0.200 0.022 248);
|
|
68
|
-
--braden-navy-900: oklch(0.130 0.015 248);
|
|
69
|
-
|
|
70
|
-
/* Neutrals */
|
|
71
|
-
--braden-slate: oklch(0.710 0.018 201.5);
|
|
72
|
-
--braden-sky: oklch(0.653 0.135 242.7);
|
|
73
|
-
--braden-forest: oklch(0.663 0.160 152.4);
|
|
74
|
-
--braden-lavender:oklch(0.577 0.153 315.3);
|
|
75
|
-
|
|
76
|
-
/* ============================================================
|
|
77
|
-
LAYER 2 — BRADEN SURFACE PRIMITIVES (light mode)
|
|
78
|
-
============================================================ */
|
|
79
|
-
--braden-light-bg-body: oklch(0.980 0.002 50); /* warm white */
|
|
80
|
-
--braden-light-bg-surface: oklch(0.996 0.001 50); /* near white */
|
|
81
|
-
--braden-light-bg-panel: oklch(0.994 0.002 250); /* near-white; pure white is banned in every role */
|
|
82
|
-
--braden-light-bg-input: oklch(0.972 0.003 250); /* cool light grey */
|
|
83
|
-
|
|
84
|
-
/* Braden light text scale — hue 250 (navy cast), capped L=0.22 */
|
|
85
|
-
--braden-light-text-primary: oklch(0.22 0.020 250); /* 13.2:1 ✓ AAA */
|
|
86
|
-
--braden-light-text-secondary: oklch(0.38 0.018 250); /* 8.1:1 ✓ AAA */
|
|
87
|
-
--braden-light-text-muted: oklch(0.52 0.018 250); /* 4.9:1 ✓ AA */
|
|
88
|
-
--braden-light-text-subtle: oklch(0.60 0.012 250); /* 3.8:1 ✓ AA large */
|
|
89
|
-
--braden-light-text-disabled: oklch(0.72 0.010 250);
|
|
90
33
|
|
|
91
|
-
|
|
92
|
-
--braden-light-hover: oklch(0.950 0.005 248);
|
|
34
|
+
:root {
|
|
93
35
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
--
|
|
100
|
-
--
|
|
101
|
-
--
|
|
36
|
+
/* ============================================================
|
|
37
|
+
LAYER 1 — BRAND PALETTE
|
|
38
|
+
Raw brand colours. Consumers must never bind to these directly.
|
|
39
|
+
============================================================ */
|
|
40
|
+
--braden-red: oklch(0.488 0.170 17.6);
|
|
41
|
+
--braden-red-light: oklch(0.572 0.201 17.9);
|
|
42
|
+
--braden-red-dark: oklch(0.400 0.137 16.8);
|
|
43
|
+
--braden-gold: oklch(0.758 0.092 89.9);
|
|
44
|
+
--braden-gold-light: oklch(0.818 0.070 90.0);
|
|
45
|
+
--braden-bronze: oklch(0.698 0.110 89.2);
|
|
46
|
+
--braden-navy: oklch(0.356 0.039 249.0);
|
|
47
|
+
--braden-slate: oklch(0.710 0.018 201.3);
|
|
48
|
+
--braden-sky: oklch(0.653 0.135 242.7);
|
|
49
|
+
--braden-forest: oklch(0.663 0.160 152.4);
|
|
50
|
+
--braden-lavender: oklch(0.577 0.152 315.3);
|
|
51
|
+
--braden-indigo: oklch(0.400 0.200 270);
|
|
52
|
+
--braden-teal-deep: oklch(0.500 0.140 220);
|
|
53
|
+
--braden-aqua: oklch(0.800 0.130 198);
|
|
102
54
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
--role-
|
|
107
|
-
--role-
|
|
108
|
-
--role-
|
|
55
|
+
/* ============================================================
|
|
56
|
+
LAYER 2 — SURFACES AND BORDERS
|
|
57
|
+
============================================================ */
|
|
58
|
+
--role-bg-body: oklch(0.980 0.002 50);
|
|
59
|
+
--role-bg-surface: oklch(0.968 0.004 55);
|
|
60
|
+
--role-bg-panel: oklch(0.994 0.001 50);
|
|
61
|
+
--role-bg-input: oklch(0.972 0.003 250);
|
|
62
|
+
--role-bg-sunken: oklch(0.952 0.005 250);
|
|
63
|
+
--role-border: oklch(0.900 0.008 248);
|
|
64
|
+
--role-border-strong: oklch(0.840 0.012 248);
|
|
109
65
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
--role-
|
|
114
|
-
--role-
|
|
115
|
-
--role-
|
|
116
|
-
--role-
|
|
66
|
+
/* ============================================================
|
|
67
|
+
LAYER 3 — HEADING RAMP (six levels, per the contract)
|
|
68
|
+
============================================================ */
|
|
69
|
+
--role-h1: oklch(0.20 0.028 252);
|
|
70
|
+
--role-h2: oklch(0.25 0.034 250);
|
|
71
|
+
--role-h3: oklch(0.30 0.040 246);
|
|
72
|
+
--role-h4: oklch(0.35 0.046 240);
|
|
73
|
+
--role-h5: oklch(0.40 0.052 232);
|
|
74
|
+
--role-h6: oklch(0.44 0.058 224);
|
|
117
75
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
--role-
|
|
122
|
-
--role-
|
|
123
|
-
--role-
|
|
76
|
+
/* ============================================================
|
|
77
|
+
LAYER 3 — TEXT AND LINKS
|
|
78
|
+
============================================================ */
|
|
79
|
+
--role-text-heading: var(--role-h1);
|
|
80
|
+
--role-text-body: oklch(0.22 0.020 250);
|
|
81
|
+
--role-text-secondary: oklch(0.38 0.018 250);
|
|
82
|
+
--role-text-muted: oklch(0.52 0.018 250);
|
|
83
|
+
--role-text-subtle: oklch(0.60 0.012 250);
|
|
84
|
+
--role-text-disabled: oklch(0.72 0.010 250);
|
|
85
|
+
--role-text-strong: oklch(0.16 0.024 252);
|
|
86
|
+
--role-text-emphasis: oklch(0.42 0.070 240);
|
|
87
|
+
--role-link: oklch(0.480 0.140 245);
|
|
88
|
+
--role-link-hover: oklch(0.400 0.150 250);
|
|
89
|
+
--role-link-visited: oklch(0.450 0.120 300);
|
|
124
90
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
--
|
|
129
|
-
--
|
|
130
|
-
--
|
|
91
|
+
/* ============================================================
|
|
92
|
+
LAYER 3 — EDITORIAL (code, quote, mark, kbd)
|
|
93
|
+
============================================================ */
|
|
94
|
+
--role-code-text: oklch(0.400 0.090 230);
|
|
95
|
+
--role-code-bg: oklch(0.950 0.010 235);
|
|
96
|
+
--role-quote-text: oklch(0.400 0.060 25);
|
|
97
|
+
--role-quote-rule: var(--braden-gold);
|
|
98
|
+
--role-mark-bg: oklch(0.930 0.060 90);
|
|
99
|
+
--role-mark-text: oklch(0.24 0.040 60);
|
|
100
|
+
--role-kbd-bg: oklch(0.962 0.004 250);
|
|
101
|
+
--role-kbd-border: oklch(0.870 0.010 250);
|
|
131
102
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
--
|
|
137
|
-
--
|
|
138
|
-
--
|
|
139
|
-
--
|
|
140
|
-
--
|
|
141
|
-
--
|
|
142
|
-
--
|
|
143
|
-
--
|
|
144
|
-
--secondary-foreground: oklch(0.99 0 0);
|
|
145
|
-
--muted: var(--braden-light-bg-input);
|
|
146
|
-
--muted-foreground: var(--braden-light-text-muted);
|
|
147
|
-
--accent: var(--braden-gold-500);
|
|
148
|
-
--accent-foreground: oklch(0.17 0.02 250);
|
|
149
|
-
--destructive: oklch(0.568 0.202 283.1);
|
|
150
|
-
--destructive-foreground: oklch(0.99 0 0);
|
|
151
|
-
--border: var(--braden-light-border);
|
|
152
|
-
--input: var(--braden-light-border);
|
|
153
|
-
--ring: var(--braden-red-600);
|
|
103
|
+
/* ============================================================
|
|
104
|
+
LAYER 3 — SEMANTIC ROLES
|
|
105
|
+
error = --braden-indigo: Corporate primary is RED, so error cannot be.
|
|
106
|
+
============================================================ */
|
|
107
|
+
--role-primary: var(--braden-red);
|
|
108
|
+
--role-secondary: var(--braden-navy);
|
|
109
|
+
--role-accent: var(--braden-gold);
|
|
110
|
+
--role-error: var(--braden-indigo);
|
|
111
|
+
--role-destructive: var(--braden-indigo);
|
|
112
|
+
--role-warning: var(--braden-gold);
|
|
113
|
+
--role-success: var(--braden-aqua);
|
|
114
|
+
--role-info: var(--braden-teal-deep);
|
|
154
115
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
--
|
|
116
|
+
/* ============================================================
|
|
117
|
+
LAYER 3 — AA-SAFE TEXT RENDERINGS OF THE SATURATED ROLES
|
|
118
|
+
A saturated fill colour is not a legible text colour.
|
|
119
|
+
============================================================ */
|
|
120
|
+
--role-primary-text: oklch(0.566 0.170 17.6);
|
|
121
|
+
--role-accent-text: oklch(0.544 0.092 89.9);
|
|
122
|
+
--role-error-text: oklch(0.562 0.200 270);
|
|
123
|
+
--role-warning-text: oklch(0.544 0.092 89.9);
|
|
124
|
+
--role-success-text: oklch(0.515 0.130 198);
|
|
125
|
+
--role-info-text: oklch(0.519 0.140 220);
|
|
160
126
|
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
--
|
|
165
|
-
--
|
|
166
|
-
--
|
|
127
|
+
/* ============================================================
|
|
128
|
+
LAYER 3 — INVERSE TEXT ON COLOURED FILLS
|
|
129
|
+
============================================================ */
|
|
130
|
+
--text-on-light-fill: oklch(0.980 0.006 50);
|
|
131
|
+
--text-on-dark-fill: oklch(0.190 0.020 250);
|
|
132
|
+
--text-on-primary: var(--text-on-light-fill);
|
|
133
|
+
--text-on-error: var(--text-on-light-fill);
|
|
134
|
+
--text-on-accent: var(--text-on-dark-fill);
|
|
135
|
+
--text-on-warning: var(--text-on-dark-fill);
|
|
136
|
+
--text-on-success: var(--text-on-dark-fill);
|
|
137
|
+
--text-on-info: var(--text-on-light-fill);
|
|
167
138
|
|
|
168
|
-
|
|
169
|
-
|
|
139
|
+
/* ============================================================
|
|
140
|
+
DECORATION — shadow, glow, dot and grid
|
|
141
|
+
============================================================ */
|
|
142
|
+
--gradient-accent: linear-gradient(135deg, var(--braden-red), var(--braden-gold));
|
|
143
|
+
--shadow-xs: 0 1px 2px oklch(0.30 0.03 250 / 0.06);
|
|
144
|
+
--shadow-sm: 0 1px 3px oklch(0.30 0.03 250 / 0.08), 0 1px 2px oklch(0.30 0.03 250 / 0.04);
|
|
145
|
+
--shadow-md: 0 4px 10px -3px oklch(0.30 0.03 250 / 0.10), 0 2px 4px -2px oklch(0.30 0.03 250 / 0.06);
|
|
146
|
+
--shadow-lg: 0 14px 26px -8px oklch(0.28 0.04 250 / 0.14), 0 5px 10px -5px oklch(0.28 0.04 250 / 0.07);
|
|
170
147
|
--glow-card: none;
|
|
171
148
|
--glow-card-hover: none;
|
|
149
|
+
--panel-hairline: transparent;
|
|
150
|
+
--dot-color: oklch(0.42 0.030 250 / 0.14);
|
|
151
|
+
--dot-size: 16px;
|
|
152
|
+
--dot-radius: 1px;
|
|
153
|
+
--grid-color: oklch(0.40 0.030 250 / 0.07);
|
|
154
|
+
--grid-size: 32px;
|
|
155
|
+
|
|
156
|
+
/* ============================================================
|
|
157
|
+
TYPOGRAPHY AND GEOMETRY
|
|
158
|
+
============================================================ */
|
|
159
|
+
--font-display: 'Open Sans', system-ui, sans-serif;
|
|
160
|
+
--font-heading: Lato, 'Open Sans', system-ui, sans-serif;
|
|
161
|
+
--font-body: 'Open Sans', system-ui, sans-serif;
|
|
162
|
+
--font-mono: 'JetBrains Mono', ui-monospace, monospace;
|
|
163
|
+
--track-display: -0.018em;
|
|
164
|
+
--track-heading: -0.008em;
|
|
165
|
+
--track-body: 0em;
|
|
166
|
+
--track-eyebrow: 0.10em;
|
|
167
|
+
--radius-sm: 4px;
|
|
168
|
+
--radius: 6px;
|
|
169
|
+
--radius-lg: 10px;
|
|
170
|
+
--row-pad: 11px;
|
|
172
171
|
}
|
|
173
172
|
|
|
174
173
|
/* ============================================================
|
|
175
|
-
|
|
174
|
+
DARK MODE — the contract's .dark block, verbatim.
|
|
175
|
+
Only tokens the contract actually flips appear here; anything
|
|
176
|
+
absent is mode-independent by design, not by omission.
|
|
176
177
|
============================================================ */
|
|
177
178
|
.dark {
|
|
178
|
-
|
|
179
|
-
--
|
|
180
|
-
--
|
|
181
|
-
--
|
|
182
|
-
--
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
--
|
|
186
|
-
--
|
|
187
|
-
--
|
|
188
|
-
--
|
|
189
|
-
--
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
--role-text-
|
|
193
|
-
--role-text-
|
|
194
|
-
--role-text-
|
|
195
|
-
--role-text-
|
|
196
|
-
--role-text-
|
|
197
|
-
--role-text-
|
|
198
|
-
|
|
199
|
-
--role-
|
|
200
|
-
--role-
|
|
201
|
-
--role-
|
|
202
|
-
--role-bg
|
|
203
|
-
--role-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
--
|
|
207
|
-
--
|
|
208
|
-
--
|
|
209
|
-
--
|
|
210
|
-
--
|
|
211
|
-
--
|
|
212
|
-
--
|
|
213
|
-
--
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
*/
|
|
225
|
-
--card-glow-source: var(--app-accent, var(--braden-gold-500));
|
|
226
|
-
--glow-card: 0 0 0 1px color-mix(in oklch, var(--card-glow-source) 18%, transparent),
|
|
227
|
-
0 0 10px -4px color-mix(in oklch, var(--card-glow-source) 20%, transparent);
|
|
228
|
-
--glow-card-hover: 0 0 0 1px color-mix(in oklch, var(--card-glow-source) 26%, transparent),
|
|
229
|
-
0 0 14px -4px color-mix(in oklch, var(--card-glow-source) 28%, transparent);
|
|
179
|
+
--role-bg-body: oklch(0.140 0.012 252);
|
|
180
|
+
--role-bg-surface: oklch(0.180 0.016 251);
|
|
181
|
+
--role-bg-panel: oklch(0.205 0.018 250);
|
|
182
|
+
--role-bg-input: oklch(0.245 0.020 250);
|
|
183
|
+
--role-bg-sunken: oklch(0.120 0.010 252);
|
|
184
|
+
--role-border: oklch(0.320 0.020 250);
|
|
185
|
+
--role-border-strong: oklch(0.420 0.024 250);
|
|
186
|
+
--role-h1: oklch(0.95 0.014 250);
|
|
187
|
+
--role-h2: oklch(0.92 0.018 250);
|
|
188
|
+
--role-h3: oklch(0.88 0.024 244);
|
|
189
|
+
--role-h4: oklch(0.84 0.032 236);
|
|
190
|
+
--role-h5: oklch(0.80 0.040 228);
|
|
191
|
+
--role-h6: oklch(0.75 0.048 220);
|
|
192
|
+
--role-text-body: oklch(0.93 0.014 250);
|
|
193
|
+
--role-text-secondary: oklch(0.80 0.016 250);
|
|
194
|
+
--role-text-muted: oklch(0.66 0.018 250);
|
|
195
|
+
--role-text-subtle: oklch(0.55 0.015 250);
|
|
196
|
+
--role-text-disabled: oklch(0.43 0.010 250);
|
|
197
|
+
--role-text-strong: oklch(0.97 0.010 250);
|
|
198
|
+
--role-text-emphasis: oklch(0.85 0.050 235);
|
|
199
|
+
--role-link: oklch(0.780 0.110 240);
|
|
200
|
+
--role-link-hover: oklch(0.860 0.095 225);
|
|
201
|
+
--role-link-visited: oklch(0.770 0.080 300);
|
|
202
|
+
--role-code-text: oklch(0.850 0.070 215);
|
|
203
|
+
--role-code-bg: oklch(0.250 0.026 230);
|
|
204
|
+
--role-quote-text: oklch(0.840 0.045 40);
|
|
205
|
+
--role-quote-rule: var(--braden-gold);
|
|
206
|
+
--role-mark-bg: oklch(0.360 0.060 85);
|
|
207
|
+
--role-mark-text: oklch(0.94 0.030 85);
|
|
208
|
+
--role-kbd-bg: oklch(0.250 0.020 250);
|
|
209
|
+
--role-kbd-border: oklch(0.400 0.022 250);
|
|
210
|
+
--role-primary-text: oklch(0.704 0.170 17.6);
|
|
211
|
+
--role-accent-text: oklch(0.683 0.092 89.9);
|
|
212
|
+
--role-error-text: oklch(0.711 0.200 270);
|
|
213
|
+
--role-warning-text: oklch(0.683 0.092 89.9);
|
|
214
|
+
--role-success-text: oklch(0.662 0.130 198);
|
|
215
|
+
--role-info-text: oklch(0.667 0.140 220);
|
|
216
|
+
--shadow-xs: 0 1px 2px oklch(0.07 0.01 252 / 0.5);
|
|
217
|
+
--shadow-sm: 0 1px 3px oklch(0.07 0.01 252 / 0.55);
|
|
218
|
+
--shadow-md: 0 6px 16px -6px oklch(0.07 0.01 252 / 0.6);
|
|
219
|
+
--shadow-lg: 0 18px 34px -12px oklch(0.07 0.01 252 / 0.68);
|
|
220
|
+
--glow-card: 0 0 0 1px color-mix(in oklch, var(--braden-gold) 18%, transparent), 0 0 10px -4px color-mix(in oklch, var(--braden-gold) 20%, transparent);
|
|
221
|
+
--glow-card-hover: 0 0 0 1px color-mix(in oklch, var(--braden-gold) 30%, transparent), 0 0 16px -4px color-mix(in oklch, var(--braden-gold) 32%, transparent);
|
|
222
|
+
--panel-hairline: color-mix(in oklch, var(--braden-gold) 26%, transparent);
|
|
223
|
+
--dot-color: oklch(0.72 0.060 90 / 0.16);
|
|
224
|
+
--grid-color: oklch(0.82 0.020 250 / 0.055);
|
|
230
225
|
}
|
package/src/css/vars.css
CHANGED
|
@@ -30,7 +30,8 @@
|
|
|
30
30
|
* Pure white (L=1.0) and pure black (L=0) are BANNED in EVERY role —
|
|
31
31
|
* text, surface, border, ring and shadow alike (operator ruling
|
|
32
32
|
* 2026-08-02). The prior text-only scoping of this rule is what let
|
|
33
|
-
* --light-bg-accent ship as oklch(1 0 0.5)
|
|
33
|
+
* --light-bg-accent ship as oklch(1 0 0.5) — theme-audit-ok: naming the
|
|
34
|
+
* value that was REMOVED — and render every shadcn card
|
|
34
35
|
* and popover pure white. "White" here means oklch(0.982 0.002 248)
|
|
35
36
|
* (#f8f9fa); the lightest surface is bg-panel at L=0.994.
|
|
36
37
|
*
|
|
@@ -74,7 +75,7 @@
|
|
|
74
75
|
--light-bg-primary: oklch(0.961 0 0.5);
|
|
75
76
|
--light-bg-secondary: oklch(0.982 0.002 248);
|
|
76
77
|
--light-bg-tertiary: oklch(0.963 0.003 228.9);
|
|
77
|
-
/* bg-panel. Was oklch(1 0 0.5) — pure white, and since --card and
|
|
78
|
+
/* bg-panel. theme-audit-ok: prose. Was oklch(1 0 0.5) — pure white, and since --card and
|
|
78
79
|
--popover bridge to it, every shadcn card and popover in all five D2C
|
|
79
80
|
apps rendered pure white in light mode from this one line. */
|
|
80
81
|
--light-bg-accent: oklch(0.994 0.002 260);
|
|
@@ -138,7 +139,18 @@
|
|
|
138
139
|
/* Text roles — six-tier scale (W3 §3.1 contract). Every tier below is
|
|
139
140
|
measured against --role-bg-body (the conservative floor); all tiers
|
|
140
141
|
score HIGHER against --role-bg-panel/--role-bg-surface. */
|
|
141
|
-
|
|
142
|
+
/* Six-level heading ramp — contract §heading-ramp. Each level shifts hue as
|
|
143
|
+
well as lightness, so the hierarchy reads in greyscale and under both
|
|
144
|
+
dichromacies, not only by size. --role-text-heading is h1 by definition;
|
|
145
|
+
it used to carry its own literal (chroma 0.018 against the contract's
|
|
146
|
+
0.020) which is how a token drifts off-palette one hair at a time. */
|
|
147
|
+
--role-h1: oklch(0.20 0.020 263);
|
|
148
|
+
--role-h2: oklch(0.26 0.026 258);
|
|
149
|
+
--role-h3: oklch(0.31 0.034 248);
|
|
150
|
+
--role-h4: oklch(0.36 0.042 236);
|
|
151
|
+
--role-h5: oklch(0.41 0.050 222);
|
|
152
|
+
--role-h6: oklch(0.45 0.058 208);
|
|
153
|
+
--role-text-heading: var(--role-h1); /* 16.17:1 ✓ AAA */
|
|
142
154
|
--role-text-body: var(--light-text-primary); /* 15.46:1 ✓ AAA */
|
|
143
155
|
--role-text-secondary: var(--light-text-secondary); /* 8.94:1 ✓ AAA */
|
|
144
156
|
--role-text-muted: var(--light-text-muted); /* 4.92:1 ✓ AA normal */
|
|
@@ -154,6 +166,32 @@
|
|
|
154
166
|
--role-border: var(--light-border);
|
|
155
167
|
--role-border-strong: oklch(0.880 0.008 250);
|
|
156
168
|
|
|
169
|
+
/* Scrim — the veil behind a modal, and the reason `bg-black/N` survived theme-audit-ok: prose
|
|
170
|
+
everywhere else. It was the single most duplicated pure endpoint in the
|
|
171
|
+
tree (9 sites across nav-core, page-builder and schema-builder) for one
|
|
172
|
+
reason: no overlay role existed, so every author reached for the only
|
|
173
|
+
thing that was always available. A banned value with no sanctioned
|
|
174
|
+
replacement does not get obeyed, it gets re-typed.
|
|
175
|
+
|
|
176
|
+
VALUE AND SHAPE ADOPTED FROM crm7, which had already solved this locally
|
|
177
|
+
(crm7/src/index.css --color-overlay, with the note "pure black banned").
|
|
178
|
+
Lifting their value rather than minting a competing one is the whole
|
|
179
|
+
point: two scrim tokens with different values is the duplication this
|
|
180
|
+
change exists to remove, and theirs was here first.
|
|
181
|
+
|
|
182
|
+
OPAQUE — the alpha belongs at the CALL SITE, not in the token. I first
|
|
183
|
+
baked 0.55 in to stop the /40-vs-/50 drift between page-builder and
|
|
184
|
+
schema-builder, which would have silently halved crm7's existing
|
|
185
|
+
`bg-overlay/50` to 0.275 by compounding. Call-site alpha is also simply
|
|
186
|
+
more useful: a full-page modal scrim and a caption strip over a photo
|
|
187
|
+
want the same colour at different strengths.
|
|
188
|
+
|
|
189
|
+
Declared ONCE — no .dark override. A scrim is not a surface: it veils
|
|
190
|
+
whatever is behind it, and the dialog above it is --role-bg-panel, which
|
|
191
|
+
already flips. Giving it a dark twin would move the veil and the panel
|
|
192
|
+
together and cancel out the separation this exists to create. */
|
|
193
|
+
--role-overlay: oklch(0.145 0.022 268);
|
|
194
|
+
|
|
157
195
|
/* Inverse text on coloured fills. Two values only — the fill is either
|
|
158
196
|
light enough to need dark text, or dark enough to need light text.
|
|
159
197
|
Neither is a pure endpoint. */
|
|
@@ -162,6 +200,10 @@
|
|
|
162
200
|
--text-on-primary: var(--text-on-light-fill); /* on blue L≈0.55 — 4.88:1 ✓ AA */
|
|
163
201
|
--text-on-error: var(--text-on-light-fill); /* on red L≈0.58 — 4.55:1 ✓ AA */
|
|
164
202
|
--text-on-accent: var(--text-on-dark-fill); /* on cyan L≈0.77 — 9.38:1 ✓ AAA */
|
|
203
|
+
--text-on-overlay: var(--text-on-light-fill); /* on scrim L≈0.15 — the scrim is dark in BOTH modes,
|
|
204
|
+
so this never flips. crm7 declared it as a bare
|
|
205
|
+
oklch(0.99 0 0); routed through the shared token
|
|
206
|
+
instead so there is one near-white, not two. */
|
|
165
207
|
--text-on-warning: var(--text-on-dark-fill); /* on amber L≈0.80 — 9.68:1 ✓ AAA */
|
|
166
208
|
--text-on-success: var(--text-on-dark-fill); /* on teal L≈0.60 — 5.17:1 ✓ AA */
|
|
167
209
|
|
|
@@ -271,7 +313,7 @@
|
|
|
271
313
|
NO sRGB FALLBACK — DELIBERATELY REMOVED 2026-08-02.
|
|
272
314
|
Precedent: precedent__bsuite__20260802__theme_conformance_is_absolute.
|
|
273
315
|
|
|
274
|
-
The `@supports not (color: oklch(0 0 0))` block that stood here shipped
|
|
316
|
+
theme-audit-ok: prose. The `@supports not (color: oklch(0 0 0))` block that stood here shipped
|
|
275
317
|
a parallel hex palette. It is gone, and must not be reinstated:
|
|
276
318
|
|
|
277
319
|
· OKLCH has been Baseline-available in every evergreen engine since
|
|
@@ -290,12 +332,13 @@
|
|
|
290
332
|
DARK MODE — Layer 2 surface overrides + Layer 3 role rebind
|
|
291
333
|
============================================================ */
|
|
292
334
|
.dark {
|
|
293
|
-
/* Dark surface primitives
|
|
335
|
+
/* Dark surface primitives.
|
|
336
|
+
--dark-bg-tertiary, -quaternary, -accent and --dark-hover were DELETED
|
|
337
|
+
2026-08-03: four tokens, zero consumers anywhere in the monorepo or the
|
|
338
|
+
five apps, and none of their values appears in the contract. A palette
|
|
339
|
+
entry nobody binds to is not a spare part — it is a second source of
|
|
340
|
+
truth waiting for someone to reach for it. */
|
|
294
341
|
--dark-bg-primary: oklch(0.166 0.026 269.4);
|
|
295
|
-
--dark-bg-secondary: oklch(0.242 0.03 269.9);
|
|
296
|
-
--dark-bg-tertiary: oklch(0.326 0.036 266.7);
|
|
297
|
-
--dark-bg-quaternary: oklch(0.39 0.035 265);
|
|
298
|
-
--dark-bg-accent: oklch(0.292 0.034 270);
|
|
299
342
|
|
|
300
343
|
/* D2C dark text scale — hue 260, capped L=0.94.
|
|
301
344
|
Pure white (L=1.0) is BANNED as a text token.
|
|
@@ -312,10 +355,19 @@
|
|
|
312
355
|
--dark-text-disabled: oklch(0.44 0.010 260); /* disabled — 2.48:1 ✗ fails AA at any size — MUST pair with icon cue */
|
|
313
356
|
|
|
314
357
|
--dark-border: oklch(0.428 0.015 248.2);
|
|
315
|
-
|
|
358
|
+
|
|
359
|
+
/* Six-level heading ramp — contract §heading-ramp. Every level is a
|
|
360
|
+
DIFFERENT hue as well as a different lightness, so the hierarchy survives
|
|
361
|
+
greyscale and both dichromacies rather than relying on size alone. */
|
|
362
|
+
--role-h1: oklch(0.95 0.016 262);
|
|
363
|
+
--role-h2: oklch(0.92 0.018 264);
|
|
364
|
+
--role-h3: oklch(0.88 0.026 240);
|
|
365
|
+
--role-h4: oklch(0.84 0.040 220);
|
|
366
|
+
--role-h5: oklch(0.80 0.052 200);
|
|
367
|
+
--role-h6: oklch(0.75 0.062 195);
|
|
316
368
|
|
|
317
369
|
/* Rebind roles to dark-mode surface values — six-tier scale (W3 §3.1). */
|
|
318
|
-
--role-text-heading:
|
|
370
|
+
--role-text-heading: var(--role-h1);
|
|
319
371
|
--role-text-body: var(--dark-text-primary); /* 16.16:1 ✓ AAA */
|
|
320
372
|
--role-text-secondary: var(--dark-text-secondary); /* 11.04:1 ✓ AAA */
|
|
321
373
|
--role-text-muted: var(--dark-text-muted); /* 6.69:1 ✓ AA normal */
|
|
@@ -323,7 +375,7 @@
|
|
|
323
375
|
--role-text-disabled: var(--dark-text-disabled); /* 2.48:1 ✗ icon cue required */
|
|
324
376
|
|
|
325
377
|
--role-bg-body: var(--dark-bg-primary);
|
|
326
|
-
--role-bg-surface:
|
|
378
|
+
--role-bg-surface: oklch(0.212 0.028 269);
|
|
327
379
|
--role-bg-panel: oklch(0.190 0.020 260);
|
|
328
380
|
--role-bg-input: oklch(0.240 0.020 260);
|
|
329
381
|
--role-bg-sunken: oklch(0.145 0.022 268);
|
package/src/preset-v4.css
CHANGED
|
@@ -129,6 +129,11 @@
|
|
|
129
129
|
--color-border: var(--role-border);
|
|
130
130
|
--color-input: var(--role-border);
|
|
131
131
|
--color-ring: var(--role-primary);
|
|
132
|
+
/* Modal scrim. OPAQUE — always write an explicit alpha at the call site
|
|
133
|
+
(`bg-overlay/50`), never bare `bg-overlay`, which would hide the page
|
|
134
|
+
entirely. Pairs with `text-text-on-overlay`. */
|
|
135
|
+
--color-overlay: var(--role-overlay);
|
|
136
|
+
--color-text-on-overlay: var(--text-on-overlay);
|
|
132
137
|
|
|
133
138
|
/* ============================================================
|
|
134
139
|
LAYER 5 — Inverse text on coloured fills
|