@tangle-network/brand 1.0.0 → 1.3.0
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/CHANGELOG.md +30 -0
- package/package.json +5 -4
- package/src/styles/css-test-utils.test.ts +79 -0
- package/src/styles/css-test-utils.ts +186 -0
- package/src/styles/index.css +1 -1
- package/src/styles/{themes.css → named-themes.css} +93 -3
- package/src/styles/named-themes.test.ts +304 -0
- package/src/styles/tokens.css +231 -141
- package/src/styles/tokens.test.ts +314 -0
package/src/styles/tokens.css
CHANGED
|
@@ -1,29 +1,60 @@
|
|
|
1
|
-
/* Tangle
|
|
2
|
-
|
|
1
|
+
/* Tangle design tokens — the single palette every Tangle surface renders from.
|
|
2
|
+
*
|
|
3
|
+
* The surface ladder is NEUTRAL GREY and the indigo is trim — accent, never
|
|
4
|
+
* field. It steps in even lightness increments so a card, a nested panel and an
|
|
5
|
+
* overlay each read as a distinct plane by their own fill, and carries a crisp
|
|
6
|
+
* hairline (1.6:1 against the card in dark) because shadow does no work on a dark
|
|
7
|
+
* canvas. Light mirrors it: white paper on a grey canvas, never white-on-white.
|
|
8
|
+
*
|
|
9
|
+
* Apps consume this spine as-is. If a product needs its own accent identity,
|
|
10
|
+
* add a named theme in named-themes.css (`data-theme="<name>"`) — do NOT re-declare
|
|
11
|
+
* these tokens in the app, or its surfaces silently stop tracking the brand. */
|
|
3
12
|
|
|
4
13
|
/* MD3 surface hierarchy */
|
|
5
14
|
/* Dark is the default theme (`:root`/`[data-sandbox-ui]`). It also responds to
|
|
6
15
|
* the standard `[data-theme="dark"]` / `.dark` switch so any consumer can pin or
|
|
7
16
|
* toggle a theme without inventing an ad-hoc `data-sandbox-theme` name. */
|
|
17
|
+
/*
|
|
18
|
+
* Surfaces are NEUTRAL GREY and the indigo is trim.
|
|
19
|
+
*
|
|
20
|
+
* Colour in the surface competes with colour in the accent: on an indigo-cast
|
|
21
|
+
* ladder the indigo nav pill, link and focus ring are one more indigo thing on
|
|
22
|
+
* an indigo page, and the eye stops finding them. Neutral planes give the brand
|
|
23
|
+
* a field to sit on, so a single accent does all the signalling.
|
|
24
|
+
*
|
|
25
|
+
* The canvas sits OFF pure black (#151523). A near-black page under near-white
|
|
26
|
+
* ink is the glare end of the range, and it is the reading surface for long
|
|
27
|
+
* sessions.
|
|
28
|
+
*
|
|
29
|
+
* Elevation is carried by surface lightness plus a hairline that can actually be
|
|
30
|
+
* seen — a black shadow on a dark canvas renders as nothing, so shadow does no
|
|
31
|
+
* work here. The hairline is 1.6:1 against the resting card — quiet by design,
|
|
32
|
+
* enough to state an edge without drawing a box around every panel.
|
|
33
|
+
*/
|
|
8
34
|
:root,
|
|
9
35
|
[data-sandbox-ui],
|
|
10
36
|
[data-theme="dark"],
|
|
11
37
|
.dark {
|
|
12
|
-
--md3-surface: #
|
|
13
|
-
--md3-surface-dim: #
|
|
14
|
-
--md3-surface-bright: #
|
|
15
|
-
--md3-surface-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
--md3-surface-
|
|
21
|
-
--md3-
|
|
22
|
-
--md3-
|
|
23
|
-
|
|
24
|
-
--md3-
|
|
25
|
-
--md3-
|
|
26
|
-
--md3-
|
|
38
|
+
--md3-surface: #151523; /* L0 page canvas */
|
|
39
|
+
--md3-surface-dim: #0f0f1a; /* recessed page */
|
|
40
|
+
--md3-surface-bright: #434365;
|
|
41
|
+
/* Same value as --md3-surface-dim by design, not by drift: both name the floor
|
|
42
|
+
* of the ladder, and dark has no plane below it to give them. They stay two
|
|
43
|
+
* tokens because the roles diverge in light, where the well is paper (#ffffff)
|
|
44
|
+
* and the recessed page is grey (#d9d9e6) — a consumer binding to the wrong one
|
|
45
|
+
* there gets the wrong surface. */
|
|
46
|
+
--md3-surface-container-lowest: #0f0f1a; /* L-1 terminal/code well */
|
|
47
|
+
--md3-surface-container-low: #222235; /* L1 chrome, field wells */
|
|
48
|
+
--md3-surface-container: #2d2e43; /* L2 resting card */
|
|
49
|
+
--md3-surface-container-high: #363654; /* L3 nested / hover */
|
|
50
|
+
--md3-surface-container-highest: #434365; /* L4 overlay */
|
|
51
|
+
--md3-surface-variant: #363654;
|
|
52
|
+
--md3-on-surface: #e3e6ed;
|
|
53
|
+
--md3-on-surface-variant: #a5abbb;
|
|
54
|
+
|
|
55
|
+
--md3-primary: #A5B4FC;
|
|
56
|
+
--md3-primary-dim: #7C6CF6;
|
|
57
|
+
--md3-primary-container: #4C3FC5;
|
|
27
58
|
--md3-on-primary: #ffffff;
|
|
28
59
|
--md3-on-primary-container: #E0E7FF;
|
|
29
60
|
--md3-primary-fixed: #A5AAFC;
|
|
@@ -36,8 +67,8 @@
|
|
|
36
67
|
--md3-on-secondary-container: #E8E5FF;
|
|
37
68
|
|
|
38
69
|
--md3-tertiary: #10B981;
|
|
39
|
-
--md3-outline: #
|
|
40
|
-
--md3-outline-variant: #
|
|
70
|
+
--md3-outline: #898da9;
|
|
71
|
+
--md3-outline-variant: #474a6b;
|
|
41
72
|
|
|
42
73
|
--md3-error: #ff5277;
|
|
43
74
|
--md3-error-dim: #eb2855;
|
|
@@ -46,30 +77,43 @@
|
|
|
46
77
|
--md3-on-error-container: #ffbdf2;
|
|
47
78
|
|
|
48
79
|
--md3-inverse-surface: #fdfdfd;
|
|
49
|
-
--md3-inverse-primary: #
|
|
80
|
+
--md3-inverse-primary: #4C3FC5;
|
|
50
81
|
--md3-inverse-on-surface: #000000;
|
|
51
|
-
--md3-surface-tint: #
|
|
52
|
-
|
|
53
|
-
/* Semantic HSL bridge —
|
|
54
|
-
--hsl-background: 240
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
--hsl-
|
|
59
|
-
--hsl-
|
|
60
|
-
--hsl-
|
|
82
|
+
--md3-surface-tint: #A5B4FC;
|
|
83
|
+
|
|
84
|
+
/* Semantic HSL bridge — the neutral-grey surface ladder */
|
|
85
|
+
--hsl-background: 240 24% 11%; /* L0 canvas #151523 */
|
|
86
|
+
/* 92% L, not pure white: near-white ink on the canvas is the glare end of the
|
|
87
|
+
* range, and the tiers below it need room to separate. 91% holds 10.6:1 on the
|
|
88
|
+
* card — AAA with headroom — and leaves four ink steps the eye can tell apart. */
|
|
89
|
+
--hsl-foreground: 225 22% 91%; /* #e3e6ed */
|
|
90
|
+
--hsl-card: 238 20% 22%; /* L2 card #2d2e43 */
|
|
91
|
+
--hsl-card-foreground: 225 22% 91%;
|
|
92
|
+
--hsl-popover: 240 22% 27%; /* L4 overlay */
|
|
93
|
+
--hsl-popover-foreground: 225 22% 91%;
|
|
94
|
+
/* The fill indigo, NOT the bright one: `.btn-primary` puts white on this, and
|
|
95
|
+
* #6366F1 carries white at only 4.47:1. This clears the floor at 7.4:1. The
|
|
96
|
+
* bright indigo stays available for accent TEXT via --accent-text. */
|
|
97
|
+
--hsl-primary: 246 54% 51%; /* #4c3fc6 */
|
|
61
98
|
--hsl-primary-foreground: 0 0% 100%;
|
|
62
|
-
--hsl-secondary: 240
|
|
63
|
-
--hsl-secondary-foreground:
|
|
64
|
-
--hsl-muted: 240
|
|
65
|
-
--hsl-muted-foreground:
|
|
66
|
-
|
|
67
|
-
|
|
99
|
+
--hsl-secondary: 240 22% 27%; /* L3 #363654 */
|
|
100
|
+
--hsl-secondary-foreground: 225 22% 91%;
|
|
101
|
+
--hsl-muted: 240 22% 27%; /* L3 hover well */
|
|
102
|
+
--hsl-muted-foreground: 223 14% 69%; /* #a5abbb — high enough that the
|
|
103
|
+
reduced-opacity caption derivatives (/70, /60) still clear the large-text
|
|
104
|
+
contrast floor against the L2 card. */
|
|
105
|
+
--hsl-accent: 240 22% 27%; /* neutral hover (indigo lives in accent-surface-strong) */
|
|
106
|
+
--hsl-accent-foreground: 225 22% 91%;
|
|
68
107
|
--hsl-destructive: 348 74% 48%;
|
|
69
108
|
--hsl-destructive-foreground: 0 0% 100%;
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
--hsl-
|
|
109
|
+
/* Quiet on purpose: 1.6:1 against the resting card. Shadow does no work on a
|
|
110
|
+
* dark canvas, so the hairline is what states where a plane ends. */
|
|
111
|
+
--hsl-border: 236 20% 35%; /* #474a6b = --md3-outline-variant */
|
|
112
|
+
--hsl-input: 240 24% 15%; /* recessed field well */
|
|
113
|
+
/* Brighter than --primary on purpose: the ring is NON-TEXT and has to clear
|
|
114
|
+
* 3:1 against BOTH canvas and card. The fill indigo is tuned to carry white
|
|
115
|
+
* text instead, so the two cannot be the same value. */
|
|
116
|
+
--hsl-ring: 233 100% 87%;
|
|
73
117
|
--hsl-success: 160 84% 39%;
|
|
74
118
|
--hsl-warning: 40 94% 56%;
|
|
75
119
|
--hsl-info: 200 88% 56%;
|
|
@@ -92,6 +136,11 @@
|
|
|
92
136
|
--destructive: var(--hsl-destructive);
|
|
93
137
|
--destructive-foreground: var(--hsl-destructive-foreground);
|
|
94
138
|
--border: var(--hsl-border);
|
|
139
|
+
/* shadcn's `--input` is the input BORDER and the Switch's off-track — a
|
|
140
|
+
* mid-tone that has to stay visible AGAINST a surface. It is deliberately NOT
|
|
141
|
+
* the field fill: pointing it at the recessed well would tint a border and a
|
|
142
|
+
* track the same color as the plane behind them, and both would vanish. The
|
|
143
|
+
* field fill is --hsl-input / --bg-input below. */
|
|
95
144
|
--input: var(--hsl-muted-foreground);
|
|
96
145
|
--ring: var(--hsl-ring);
|
|
97
146
|
--success: var(--hsl-success);
|
|
@@ -99,25 +148,26 @@
|
|
|
99
148
|
--error: var(--hsl-destructive);
|
|
100
149
|
--info: var(--hsl-info);
|
|
101
150
|
|
|
102
|
-
/* Sidebar tokens —
|
|
103
|
-
|
|
104
|
-
--sidebar-
|
|
105
|
-
--sidebar-
|
|
151
|
+
/* Sidebar tokens — L1 chrome: one step BELOW the canvas here, so the nav reads
|
|
152
|
+
* as chrome the content sits in front of rather than as another card. */
|
|
153
|
+
--sidebar-background: 242 26% 8%; /* L1 chrome #0f0f1a */
|
|
154
|
+
--sidebar-foreground: 225 22% 91%;
|
|
155
|
+
--sidebar-primary: 246 54% 51%;
|
|
106
156
|
--sidebar-primary-foreground: 0 0% 100%;
|
|
107
|
-
--sidebar-accent: 240
|
|
108
|
-
--sidebar-accent-foreground:
|
|
109
|
-
--sidebar-border:
|
|
110
|
-
--sidebar-ring:
|
|
157
|
+
--sidebar-accent: 240 22% 27%; /* L3 hover well */
|
|
158
|
+
--sidebar-accent-foreground: 225 22% 91%;
|
|
159
|
+
--sidebar-border: 236 20% 35%;
|
|
160
|
+
--sidebar-ring: 233 100% 87%;
|
|
111
161
|
|
|
112
|
-
/* Depth scale —
|
|
113
|
-
--depth-1: #
|
|
114
|
-
--depth-2: #
|
|
115
|
-
--depth-3: #
|
|
116
|
-
--depth-4: #
|
|
162
|
+
/* Depth scale — tracks the MD3 ladder (canvas / card / nested / overlay) */
|
|
163
|
+
--depth-1: #151523;
|
|
164
|
+
--depth-2: #2d2e43;
|
|
165
|
+
--depth-3: #363654;
|
|
166
|
+
--depth-4: #434365;
|
|
117
167
|
|
|
118
168
|
/* Status colors */
|
|
119
169
|
--status-running: #10B981;
|
|
120
|
-
--status-creating: #
|
|
170
|
+
--status-creating: #A5B4FC;
|
|
121
171
|
--status-stopped: #FFB800;
|
|
122
172
|
--status-warm: #FF8A4C;
|
|
123
173
|
--status-cold: #4AABFF;
|
|
@@ -157,38 +207,45 @@
|
|
|
157
207
|
--glass-border-hover: var(--border-default);
|
|
158
208
|
--glass-blur: 0px;
|
|
159
209
|
|
|
160
|
-
/* Mesh glows —
|
|
210
|
+
/* Mesh glows — off; depth comes from the ladder, not from glow */
|
|
161
211
|
--mesh-teal: transparent;
|
|
162
212
|
--mesh-violet: transparent;
|
|
163
213
|
--mesh-blue: transparent;
|
|
164
214
|
|
|
165
215
|
/* Brand gradients — the indigo spark, kept ONLY for the logo mark + send button */
|
|
166
|
-
--tangle-gradient: linear-gradient(135deg, #
|
|
167
|
-
--tangle-gradient-text: linear-gradient(135deg, #
|
|
168
|
-
--accent-gradient-strong: linear-gradient(135deg, #
|
|
216
|
+
--tangle-gradient: linear-gradient(135deg, #4C3FC5, #A5B4FC);
|
|
217
|
+
--tangle-gradient-text: linear-gradient(135deg, #C7D2FE, #A5B4FC);
|
|
218
|
+
--accent-gradient-strong: linear-gradient(135deg, #4C3FC5, #7C6CF6);
|
|
169
219
|
/* Accent wells — soft = hover neutral, strong = active/selected row (indigo) */
|
|
170
|
-
--accent-surface-soft: rgba(
|
|
171
|
-
--accent-surface-strong: rgba(
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
220
|
+
--accent-surface-soft: rgba(165, 180, 252, 0.07);
|
|
221
|
+
--accent-surface-strong: rgba(76, 63, 197, 0.30);
|
|
222
|
+
/* The BRIGHT indigo, and only ever as text: --primary is the fill (it carries
|
|
223
|
+
* white), and at 6.7:1 on the card this is the one that stays legible as ink. */
|
|
224
|
+
--accent-text: #A5B4FC;
|
|
225
|
+
|
|
226
|
+
/* Surfaces — solid fills off the ladder (no radial mesh) */
|
|
227
|
+
--bg-root: #151523;
|
|
176
228
|
--bg-dark: var(--depth-1);
|
|
177
229
|
--bg-card: var(--depth-2);
|
|
178
230
|
--bg-elevated: var(--depth-4);
|
|
179
231
|
--bg-section: var(--depth-1);
|
|
180
|
-
--bg-input: var(--
|
|
181
|
-
--bg-hover: rgba(
|
|
182
|
-
--bg-selection: rgba(
|
|
232
|
+
--bg-input: hsl(var(--hsl-input)); /* the field well — same color, hex-free */
|
|
233
|
+
--bg-hover: rgba(165, 180, 252, 0.07);
|
|
234
|
+
--bg-selection: rgba(124, 108, 246, 0.28);
|
|
183
235
|
|
|
184
236
|
/* Text — neutral */
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
237
|
+
/* Four steps the eye can actually separate: 10.6 / 7.5 / 5.8 / 4.7 against the
|
|
238
|
+
* L2 card. --text-dim is the faintest tier but it is still TEXT, so it clears
|
|
239
|
+
* the 4.5:1 body floor rather than only the 3:1 large-text one — asserted in
|
|
240
|
+
* tokens.test.ts against both the card and the canvas, since the tier is
|
|
241
|
+
* solved against one surface and rendered on both. */
|
|
242
|
+
--text-primary: #e3e6ed;
|
|
243
|
+
--text-secondary: #bec3d0;
|
|
244
|
+
--text-muted: #a5abbb;
|
|
245
|
+
--text-dim: #9299ab;
|
|
189
246
|
|
|
190
247
|
/* Brand accents — Tangle */
|
|
191
|
-
--brand-primary: #
|
|
248
|
+
--brand-primary: #7C6CF6;
|
|
192
249
|
--brand-strong: #2E2A5E;
|
|
193
250
|
--brand-strong-text: #ffffff;
|
|
194
251
|
--brand-strong-text-muted: rgba(255, 255, 255, 0.7);
|
|
@@ -200,17 +257,17 @@
|
|
|
200
257
|
--brand-emerald: #10B981;
|
|
201
258
|
|
|
202
259
|
/* Borders — neutral hairlines */
|
|
203
|
-
--border-subtle: rgba(
|
|
204
|
-
--border-default: rgba(
|
|
205
|
-
--border-hover: rgba(
|
|
206
|
-
--border-accent: rgba(129, 140, 248, 0.
|
|
207
|
-
--border-accent-hover: rgba(129, 140, 248, 0.
|
|
260
|
+
--border-subtle: rgba(165, 180, 252, 0.10);
|
|
261
|
+
--border-default: rgba(165, 180, 252, 0.16);
|
|
262
|
+
--border-hover: rgba(165, 180, 252, 0.28);
|
|
263
|
+
--border-accent: rgba(129, 140, 248, 0.35);
|
|
264
|
+
--border-accent-hover: rgba(129, 140, 248, 0.50);
|
|
208
265
|
|
|
209
266
|
/* Buttons */
|
|
210
|
-
--btn-primary-bg: #
|
|
211
|
-
--btn-primary-hover: #
|
|
267
|
+
--btn-primary-bg: #4C3FC5;
|
|
268
|
+
--btn-primary-hover: #5A50D6;
|
|
212
269
|
--btn-primary-text: #ffffff;
|
|
213
|
-
--btn-cta-bg: #
|
|
270
|
+
--btn-cta-bg: #4C3FC5;
|
|
214
271
|
--btn-cta-text: #FFFFFF;
|
|
215
272
|
|
|
216
273
|
/* Code / runtime syntax */
|
|
@@ -319,17 +376,23 @@
|
|
|
319
376
|
/* Light theme — clean professional, warm purple accents */
|
|
320
377
|
|
|
321
378
|
/* MD3 surface hierarchy */
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
--md3-surface
|
|
329
|
-
--md3-surface-
|
|
330
|
-
--md3-surface-
|
|
331
|
-
--md3-
|
|
332
|
-
--md3-
|
|
379
|
+
/* The light ladder ALTERNATES; it is not monotonic, and that is deliberate.
|
|
380
|
+
* On a tinted canvas, a raised plane is PAPER (white) and a recessed one is a
|
|
381
|
+
* tinted WELL. So card and overlay are both white and separate from each other
|
|
382
|
+
* by shadow and ring, not by fill — which is how light-mode elevation actually
|
|
383
|
+
* reads. Forcing a strictly-darkening ladder here is what produced the
|
|
384
|
+
* white-on-white flatness this palette replaced. Pinned in tokens.test.ts. */
|
|
385
|
+
--md3-surface: #e9e9f1; /* L0 page canvas — neutral grey, BELOW the wells */
|
|
386
|
+
--md3-surface-dim: #d9d9e6;
|
|
387
|
+
--md3-surface-bright: #ffffff;
|
|
388
|
+
--md3-surface-container-lowest: #ffffff; /* insets read as paper */
|
|
389
|
+
--md3-surface-container-low: #f7f7fa; /* L1 chrome, field wells — well */
|
|
390
|
+
--md3-surface-container: #ffffff; /* L2 resting card — paper */
|
|
391
|
+
--md3-surface-container-high: #f2f2f7; /* L3 nested / hover — well */
|
|
392
|
+
--md3-surface-container-highest: #ffffff; /* L4 overlay — paper + shadow */
|
|
393
|
+
--md3-surface-variant: #f2f2f7;
|
|
394
|
+
--md3-on-surface: #2b2c3e;
|
|
395
|
+
--md3-on-surface-variant: #494b5d;
|
|
333
396
|
|
|
334
397
|
--md3-primary: #3E349E;
|
|
335
398
|
--md3-primary-dim: #352B88;
|
|
@@ -347,8 +410,8 @@
|
|
|
347
410
|
|
|
348
411
|
--md3-tertiary: #065F46;
|
|
349
412
|
--md3-tertiary-container: #D1FAE5;
|
|
350
|
-
--md3-outline: #
|
|
351
|
-
--md3-outline-variant: #
|
|
413
|
+
--md3-outline: #737696;
|
|
414
|
+
--md3-outline-variant: #cecfde;
|
|
352
415
|
|
|
353
416
|
--md3-error: #ba1a1a;
|
|
354
417
|
--md3-error-dim: #93000a;
|
|
@@ -361,34 +424,47 @@
|
|
|
361
424
|
--md3-inverse-on-surface: #f0f1f4;
|
|
362
425
|
--md3-surface-tint: #6366F1;
|
|
363
426
|
|
|
364
|
-
/* Semantic HSL bridge —
|
|
365
|
-
--hsl-background:
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
427
|
+
/* Semantic HSL bridge — white paper on a neutral-grey canvas */
|
|
428
|
+
--hsl-background: 240 24% 93%; /* L0 canvas #e9e9f1 */
|
|
429
|
+
/* Ink, not black. Pure #0d0d0d on white paper measures 19.5:1 — a hair off the
|
|
430
|
+
* 21:1 ceiling — and that maximum is what reads as glare rather than as
|
|
431
|
+
* legibility. 20.5% L lands 13.7:1 on the card and 11.4:1 on the canvas: AAA with
|
|
432
|
+
* headroom in both places, and a step the eye reads as text instead of as a
|
|
433
|
+
* hole. */
|
|
434
|
+
--hsl-foreground: 235 18% 20.5%; /* #2b2c3e */
|
|
435
|
+
--hsl-card: 0 0% 100%; /* L2 card = white paper */
|
|
436
|
+
--hsl-card-foreground: 235 18% 20.5%;
|
|
369
437
|
--hsl-popover: 0 0% 100%;
|
|
370
|
-
--hsl-popover-foreground:
|
|
371
|
-
--hsl-primary:
|
|
438
|
+
--hsl-popover-foreground: 235 18% 20.5%;
|
|
439
|
+
--hsl-primary: 246 54% 51%; /* #4c3fc6 — carries white at 7.4:1 */
|
|
372
440
|
--hsl-primary-foreground: 0 0% 100%;
|
|
373
|
-
--hsl-secondary: 240
|
|
374
|
-
--hsl-secondary-foreground:
|
|
375
|
-
--hsl-muted: 240
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
441
|
+
--hsl-secondary: 240 26% 96%; /* L3 #f2f2f7 */
|
|
442
|
+
--hsl-secondary-foreground: 235 18% 20.5%;
|
|
443
|
+
--hsl-muted: 240 26% 96%; /* L3 hover well */
|
|
444
|
+
/* 34% L: the shared components fade captions with /70 and /60, and a
|
|
445
|
+
* translucent foreground renders as the token COMPOSITED over the plane behind
|
|
446
|
+
* it. Against white paper that compositing is brutal — a lighter value puts the
|
|
447
|
+
* /60 caption under the 3:1 large-text floor. This holds 3.0:1 there and 8.6:1
|
|
448
|
+
* at full strength, still a clear step below the 13.7:1 body ink. */
|
|
449
|
+
--hsl-muted-foreground: 235 12% 32.5%; /* #494b5d text-muted */
|
|
450
|
+
--hsl-accent: 240 26% 96%; /* neutral hover */
|
|
451
|
+
--hsl-accent-foreground: 235 18% 20.5%;
|
|
379
452
|
--hsl-destructive: 0 72% 41%;
|
|
380
453
|
--hsl-destructive-foreground: 0 0% 100%;
|
|
381
|
-
--hsl-border:
|
|
382
|
-
--hsl-input: 240
|
|
383
|
-
--hsl-ring:
|
|
454
|
+
--hsl-border: 238 20% 84%; /* #cecfde = --md3-outline-variant */
|
|
455
|
+
--hsl-input: 240 30% 97%; /* field well */
|
|
456
|
+
--hsl-ring: 246 54% 51%;
|
|
384
457
|
--hsl-success: 160 84% 30%;
|
|
385
458
|
--hsl-warning: 41 96% 50%;
|
|
386
459
|
--hsl-info: 212 80% 50%;
|
|
387
460
|
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
--depth-
|
|
461
|
+
/* depth-2 (card) and depth-4 (elevated) are BOTH paper, on purpose: in light,
|
|
462
|
+
* a popover does not out-lighten a white card — it lifts by shadow. See the
|
|
463
|
+
* ladder note above. */
|
|
464
|
+
--depth-1: #e9e9f1; /* canvas */
|
|
465
|
+
--depth-2: #ffffff; /* card — paper */
|
|
466
|
+
--depth-3: #f2f2f7; /* nested well */
|
|
467
|
+
--depth-4: #ffffff; /* elevated — paper, separated by shadow */
|
|
392
468
|
|
|
393
469
|
--status-running: #059669;
|
|
394
470
|
--status-creating: #3E349E;
|
|
@@ -430,33 +506,47 @@
|
|
|
430
506
|
--surface-neutral-text: var(--text-muted);
|
|
431
507
|
|
|
432
508
|
/* Sidebar — light, flat surface + hairline */
|
|
433
|
-
--sidebar-background:
|
|
434
|
-
--sidebar-foreground:
|
|
435
|
-
--sidebar-primary:
|
|
509
|
+
--sidebar-background: 0 0% 100%; /* white paper */
|
|
510
|
+
--sidebar-foreground: 235 18% 20.5%;
|
|
511
|
+
--sidebar-primary: 246 54% 51%; /* #4c3fc6 */
|
|
436
512
|
--sidebar-primary-foreground: 0 0% 100%;
|
|
437
|
-
--sidebar-accent: 240
|
|
438
|
-
--sidebar-accent-foreground:
|
|
439
|
-
--sidebar-border:
|
|
440
|
-
--sidebar-ring:
|
|
513
|
+
--sidebar-accent: 240 26% 96%; /* L3 hover well */
|
|
514
|
+
--sidebar-accent-foreground: 235 18% 20.5%;
|
|
515
|
+
--sidebar-border: 238 20% 84%; /* = --md3-outline-variant */
|
|
516
|
+
--sidebar-ring: 246 54% 51%;
|
|
441
517
|
|
|
442
518
|
--mesh-teal: transparent;
|
|
443
519
|
--mesh-violet: transparent;
|
|
444
520
|
--mesh-blue: transparent;
|
|
445
521
|
|
|
446
522
|
/* Surfaces — flat single-neutral light */
|
|
447
|
-
--bg-root: #
|
|
448
|
-
--bg-dark:
|
|
449
|
-
--bg-card:
|
|
450
|
-
--bg-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
--
|
|
457
|
-
--
|
|
458
|
-
--
|
|
459
|
-
--
|
|
523
|
+
--bg-root: #e9e9f1;
|
|
524
|
+
--bg-dark: var(--depth-1);
|
|
525
|
+
--bg-card: var(--depth-2);
|
|
526
|
+
/* Paper, exactly like --bg-card: in light you cannot raise a plane by making it
|
|
527
|
+
* lighter than white, so an overlay lifts by SHADOW. A consumer that fills with
|
|
528
|
+
* --bg-elevated and applies no shadow gets no separation from a card — that is
|
|
529
|
+
* the contract, not an oversight (--hsl-popover is white for the same reason).
|
|
530
|
+
* Pair it with --shadow-dropdown. */
|
|
531
|
+
--bg-elevated: var(--depth-4);
|
|
532
|
+
--bg-section: var(--depth-1);
|
|
533
|
+
--bg-input: hsl(var(--hsl-input)); /* the field well — same color, hex-free */
|
|
534
|
+
--bg-hover: rgba(76, 63, 198, 0.06);
|
|
535
|
+
--bg-selection: rgba(76, 63, 198, 0.16);
|
|
536
|
+
|
|
537
|
+
/* Mirrors the dark ramp's spacing: 13.7 / 10.5 / 8.6 / 5.6 against white paper.
|
|
538
|
+
* Every step carries the 240 cast so the ink belongs to the palette.
|
|
539
|
+
*
|
|
540
|
+
* --text-dim is pinned from the CANVAS (#e9e9f1), not the white card: it is
|
|
541
|
+
* the faintest tier, so the tinted L0 is the surface that binds it, and a
|
|
542
|
+
* value chosen against paper alone sits under the 4.5:1 body floor there.
|
|
543
|
+
* 4.6 on the canvas, 5.6 on the card — both floors are asserted in
|
|
544
|
+
* tokens.test.ts, because a ratio quoted in a comment drifts the moment a
|
|
545
|
+
* surface moves and nothing catches it. */
|
|
546
|
+
--text-primary: #2b2c3e;
|
|
547
|
+
--text-secondary: #3d3e52;
|
|
548
|
+
--text-muted: #494b5d;
|
|
549
|
+
--text-dim: #65677b;
|
|
460
550
|
|
|
461
551
|
--brand-primary: #6366F1;
|
|
462
552
|
--brand-strong: #2E2A5E;
|
|
@@ -469,16 +559,16 @@
|
|
|
469
559
|
--brand-vibrant: #6366F1;
|
|
470
560
|
--brand-emerald: #059669;
|
|
471
561
|
|
|
472
|
-
--border-subtle: rgba(
|
|
473
|
-
--border-default: rgba(
|
|
474
|
-
--border-hover: rgba(
|
|
562
|
+
--border-subtle: rgba(60, 52, 140, 0.10);
|
|
563
|
+
--border-default: rgba(60, 52, 140, 0.14);
|
|
564
|
+
--border-hover: rgba(60, 52, 140, 0.24);
|
|
475
565
|
--border-accent: rgba(91, 78, 212, 0.18);
|
|
476
566
|
--border-accent-hover: rgba(91, 78, 212, 0.35);
|
|
477
567
|
|
|
478
|
-
--btn-primary-bg: #
|
|
479
|
-
--btn-primary-hover: #
|
|
568
|
+
--btn-primary-bg: #4C3FC5;
|
|
569
|
+
--btn-primary-hover: #5A50D6;
|
|
480
570
|
--btn-primary-text: #ffffff;
|
|
481
|
-
--btn-cta-bg: #
|
|
571
|
+
--btn-cta-bg: #4C3FC5;
|
|
482
572
|
--btn-cta-text: #ffffff;
|
|
483
573
|
|
|
484
574
|
--code-keyword: #3E349E;
|
|
@@ -499,9 +589,9 @@
|
|
|
499
589
|
--tangle-gradient: linear-gradient(135deg, #4F46E5, #5B4ED4);
|
|
500
590
|
--tangle-gradient-text: linear-gradient(135deg, #4F46E5, #5B4ED4);
|
|
501
591
|
--accent-gradient-strong: linear-gradient(135deg, #4F46E5, #5B4ED4);
|
|
502
|
-
--accent-surface-soft: rgba(
|
|
503
|
-
--accent-surface-strong: rgba(
|
|
504
|
-
--accent-text: #
|
|
592
|
+
--accent-surface-soft: rgba(76, 63, 198, 0.05);
|
|
593
|
+
--accent-surface-strong: rgba(76, 63, 198, 0.13);
|
|
594
|
+
--accent-text: #5047eb;
|
|
505
595
|
|
|
506
596
|
/* Typography — unified on Inter */
|
|
507
597
|
--font-sans: "Inter", "Geist", ui-sans-serif, system-ui, -apple-system, sans-serif;
|