@tangle-network/brand 1.6.0 → 1.8.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 CHANGED
@@ -1,5 +1,23 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.8.0
4
+
5
+ ### Minor Changes
6
+
7
+ - bddb32c: Add `--chart-*` tokens for benchmark charts, dark and light: ink, muted ink, one accent, one muted mark, grid, table rule, row shade and an ordinal App Grade tier ramp (C, B, A, S). Aliases re-resolve on every theme scope; named light themes get the light accent and ramp.
8
+
9
+ ## 1.7.0
10
+
11
+ ### Minor Changes
12
+
13
+ - 1eff8ab: Add opt-in colour ladders and a semantic token layer.
14
+
15
+ `@tangle-network/brand/styles/ladders.css` defines 12 ramps of 12 steps, light and dark, from Radix Colors 3.0.0, with role aliases (`--gray-*`, `--accent-*`, `--success-*`, `--warning-*`, `--danger-*`, `--info-*`) and a per-domain ramp under `[data-domain]`.
16
+
17
+ `@tangle-network/brand/styles/system.css` maps every `tokens.css` family onto a ladder step and adds semantic tokens, role radii, type roles, motion and three shadow levels. Light pages become white and dark becomes a neutral mauve ladder. It is opt in: nothing changes for an app that does not import it.
18
+
19
+ `scripts/gen-ladders.mjs` generates both files; `pnpm --filter @tangle-network/brand gen:ladders` rewrites them.
20
+
3
21
  ## 1.6.0
4
22
 
5
23
  ### Minor Changes
package/README.md CHANGED
@@ -39,6 +39,27 @@ Fonts are **not** bundled — see [Fonts](#fonts) below.
39
39
  @import "@tangle-network/brand/styles/globals";
40
40
  ```
41
41
 
42
+ ### Colour ladders (opt in)
43
+
44
+ ```css
45
+ @import "@tangle-network/brand/styles";
46
+ @import "@tangle-network/brand/styles/ladders.css";
47
+ @import "@tangle-network/brand/styles/system.css";
48
+ ```
49
+
50
+ `ladders.css` defines 12 ramps of 12 steps each, in light and dark, from Radix Colors 3.0.0: mauve (neutral), iris (brand), green, amber, red and blue (status), and plum, orange, grass, bronze, crimson and olive (domains).
51
+ Each step has one job: 1–2 backgrounds, 3–5 control fills, 6–8 borders, 9–10 solid fills, 11 secondary text and 12 primary text.
52
+ Role aliases (`--gray-*`, `--accent-*`, `--success-*`, `--warning-*`, `--danger-*`, `--info-*`) point at the ramps.
53
+ Setting `data-domain="tax"` (or another domain key) on an element gives its subtree `--domain-1..12`.
54
+
55
+ `system.css` maps every token family in `tokens.css` onto a ladder step and adds semantic tokens (`--bg-page`, `--line`, `--fg-muted`, `--accent-text`, `--ink`), role radii, type roles, motion and three shadow levels.
56
+ Light pages become white, and dark becomes a neutral mauve ladder.
57
+ Import it after `tokens.css`; it is opt in because it changes every surface of the app that loads it.
58
+
59
+ Both files are generated.
60
+ Change a value in `scripts/gen-ladders.mjs` or `scripts/radix-ramps.json`, then run `pnpm --filter @tangle-network/brand gen:ladders`.
61
+ An app that ships ahead of a release copies the two generated files verbatim, so its copy stays identical.
62
+
42
63
  ### Logo
43
64
 
44
65
  ```tsx
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tangle-network/brand",
3
- "version": "1.6.0",
3
+ "version": "1.8.0",
4
4
  "description": "Tangle brand system — design tokens, logo, Tailwind v4 theme. Single source of truth for every Tangle app.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -36,7 +36,9 @@
36
36
  "./styles/tokens.css": "./src/styles/tokens.css",
37
37
  "./styles/globals.css": "./src/styles/globals.css",
38
38
  "./styles/theme.css": "./src/styles/theme.css",
39
- "./styles/named-themes.css": "./src/styles/named-themes.css"
39
+ "./styles/named-themes.css": "./src/styles/named-themes.css",
40
+ "./styles/ladders.css": "./src/styles/ladders.css",
41
+ "./styles/system.css": "./src/styles/system.css"
40
42
  },
41
43
  "peerDependencies": {
42
44
  "react": ">=18"
@@ -62,6 +64,7 @@
62
64
  ],
63
65
  "scripts": {
64
66
  "build": "tsup src/index.ts --format esm --dts --clean",
67
+ "gen:ladders": "node scripts/gen-ladders.mjs",
65
68
  "dev": "tsup src/index.ts --format esm --dts --watch"
66
69
  }
67
70
  }
@@ -0,0 +1,595 @@
1
+ /* Colour ladders. Generated by scripts/gen-ladders.mjs from @radix-ui/colors 3.0.0; do not edit by hand.
2
+ *
3
+ * Every ramp has 12 steps, and each step has one job:
4
+ * 1-2 app backgrounds
5
+ * 3-5 control fills: rest, hover, pressed
6
+ * 6-8 borders: subtle, default, hover
7
+ * 9-10 solid fills
8
+ * 11 readable secondary text
9
+ * 12 readable primary text
10
+ * Light and dark use the same names, so a component written against a step
11
+ * works in both themes. Dark is the :root default and light wins by source
12
+ * order, the same as tokens.css. The role aliases repeat in both blocks because
13
+ * a var() resolves where it is declared. */
14
+ :root,
15
+ [data-sandbox-ui],
16
+ [data-theme="dark"],
17
+ .dark {
18
+ --mauve-1: #121113;
19
+ --mauve-2: #1a191b;
20
+ --mauve-3: #232225;
21
+ --mauve-4: #2b292d;
22
+ --mauve-5: #323035;
23
+ --mauve-6: #3c393f;
24
+ --mauve-7: #49474e;
25
+ --mauve-8: #625f69;
26
+ --mauve-9: #6f6d78;
27
+ --mauve-10: #7c7a85;
28
+ --mauve-11: #b5b2bc;
29
+ --mauve-12: #eeeef0;
30
+ --iris-1: #13131e;
31
+ --iris-2: #171625;
32
+ --iris-3: #202248;
33
+ --iris-4: #262a65;
34
+ --iris-5: #303374;
35
+ --iris-6: #3d3e82;
36
+ --iris-7: #4a4a95;
37
+ --iris-8: #5958b1;
38
+ --iris-9: #5b5bd6;
39
+ --iris-10: #6e6ade;
40
+ --iris-11: #b1a9ff;
41
+ --iris-12: #e0dffe;
42
+ --green-1: #0e1512;
43
+ --green-2: #121b17;
44
+ --green-3: #132d21;
45
+ --green-4: #113b29;
46
+ --green-5: #174933;
47
+ --green-6: #20573e;
48
+ --green-7: #28684a;
49
+ --green-8: #2f7c57;
50
+ --green-9: #30a46c;
51
+ --green-10: #33b074;
52
+ --green-11: #3dd68c;
53
+ --green-12: #b1f1cb;
54
+ --amber-1: #16120c;
55
+ --amber-2: #1d180f;
56
+ --amber-3: #302008;
57
+ --amber-4: #3f2700;
58
+ --amber-5: #4d3000;
59
+ --amber-6: #5c3d05;
60
+ --amber-7: #714f19;
61
+ --amber-8: #8f6424;
62
+ --amber-9: #ffc53d;
63
+ --amber-10: #ffd60a;
64
+ --amber-11: #ffca16;
65
+ --amber-12: #ffe7b3;
66
+ --red-1: #191111;
67
+ --red-2: #201314;
68
+ --red-3: #3b1219;
69
+ --red-4: #500f1c;
70
+ --red-5: #611623;
71
+ --red-6: #72232d;
72
+ --red-7: #8c333a;
73
+ --red-8: #b54548;
74
+ --red-9: #e5484d;
75
+ --red-10: #ec5d5e;
76
+ --red-11: #ff9592;
77
+ --red-12: #ffd1d9;
78
+ --blue-1: #0d1520;
79
+ --blue-2: #111927;
80
+ --blue-3: #0d2847;
81
+ --blue-4: #003362;
82
+ --blue-5: #004074;
83
+ --blue-6: #104d87;
84
+ --blue-7: #205d9e;
85
+ --blue-8: #2870bd;
86
+ --blue-9: #0090ff;
87
+ --blue-10: #3b9eff;
88
+ --blue-11: #70b8ff;
89
+ --blue-12: #c2e6ff;
90
+ --plum-1: #181118;
91
+ --plum-2: #201320;
92
+ --plum-3: #351a35;
93
+ --plum-4: #451d47;
94
+ --plum-5: #512454;
95
+ --plum-6: #5e3061;
96
+ --plum-7: #734079;
97
+ --plum-8: #92549c;
98
+ --plum-9: #ab4aba;
99
+ --plum-10: #b658c4;
100
+ --plum-11: #e796f3;
101
+ --plum-12: #f4d4f4;
102
+ --orange-1: #17120e;
103
+ --orange-2: #1e160f;
104
+ --orange-3: #331e0b;
105
+ --orange-4: #462100;
106
+ --orange-5: #562800;
107
+ --orange-6: #66350c;
108
+ --orange-7: #7e451d;
109
+ --orange-8: #a35829;
110
+ --orange-9: #f76b15;
111
+ --orange-10: #ff801f;
112
+ --orange-11: #ffa057;
113
+ --orange-12: #ffe0c2;
114
+ --grass-1: #0e1511;
115
+ --grass-2: #141a15;
116
+ --grass-3: #1b2a1e;
117
+ --grass-4: #1d3a24;
118
+ --grass-5: #25482d;
119
+ --grass-6: #2d5736;
120
+ --grass-7: #366740;
121
+ --grass-8: #3e7949;
122
+ --grass-9: #46a758;
123
+ --grass-10: #53b365;
124
+ --grass-11: #71d083;
125
+ --grass-12: #c2f0c2;
126
+ --bronze-1: #141110;
127
+ --bronze-2: #1c1917;
128
+ --bronze-3: #262220;
129
+ --bronze-4: #302a27;
130
+ --bronze-5: #3b3330;
131
+ --bronze-6: #493e3a;
132
+ --bronze-7: #5a4c47;
133
+ --bronze-8: #6f5f58;
134
+ --bronze-9: #a18072;
135
+ --bronze-10: #ae8c7e;
136
+ --bronze-11: #d4b3a5;
137
+ --bronze-12: #ede0d9;
138
+ --crimson-1: #191114;
139
+ --crimson-2: #201318;
140
+ --crimson-3: #381525;
141
+ --crimson-4: #4d122f;
142
+ --crimson-5: #5c1839;
143
+ --crimson-6: #6d2545;
144
+ --crimson-7: #873356;
145
+ --crimson-8: #b0436e;
146
+ --crimson-9: #e93d82;
147
+ --crimson-10: #ee518a;
148
+ --crimson-11: #ff92ad;
149
+ --crimson-12: #fdd3e8;
150
+ --olive-1: #111210;
151
+ --olive-2: #181917;
152
+ --olive-3: #212220;
153
+ --olive-4: #282a27;
154
+ --olive-5: #2f312e;
155
+ --olive-6: #383a36;
156
+ --olive-7: #454843;
157
+ --olive-8: #5c625b;
158
+ --olive-9: #687066;
159
+ --olive-10: #767d74;
160
+ --olive-11: #afb5ad;
161
+ --olive-12: #eceeec;
162
+ --gray-1: var(--mauve-1);
163
+ --gray-2: var(--mauve-2);
164
+ --gray-3: var(--mauve-3);
165
+ --gray-4: var(--mauve-4);
166
+ --gray-5: var(--mauve-5);
167
+ --gray-6: var(--mauve-6);
168
+ --gray-7: var(--mauve-7);
169
+ --gray-8: var(--mauve-8);
170
+ --gray-9: var(--mauve-9);
171
+ --gray-10: var(--mauve-10);
172
+ --gray-11: var(--mauve-11);
173
+ --gray-12: var(--mauve-12);
174
+ --accent-1: var(--iris-1);
175
+ --accent-2: var(--iris-2);
176
+ --accent-3: var(--iris-3);
177
+ --accent-4: var(--iris-4);
178
+ --accent-5: var(--iris-5);
179
+ --accent-6: var(--iris-6);
180
+ --accent-7: var(--iris-7);
181
+ --accent-8: var(--iris-8);
182
+ --accent-9: var(--iris-9);
183
+ --accent-10: var(--iris-10);
184
+ --accent-11: var(--iris-11);
185
+ --accent-12: var(--iris-12);
186
+ --success-1: var(--green-1);
187
+ --success-2: var(--green-2);
188
+ --success-3: var(--green-3);
189
+ --success-4: var(--green-4);
190
+ --success-5: var(--green-5);
191
+ --success-6: var(--green-6);
192
+ --success-7: var(--green-7);
193
+ --success-8: var(--green-8);
194
+ --success-9: var(--green-9);
195
+ --success-10: var(--green-10);
196
+ --success-11: var(--green-11);
197
+ --success-12: var(--green-12);
198
+ --warning-1: var(--amber-1);
199
+ --warning-2: var(--amber-2);
200
+ --warning-3: var(--amber-3);
201
+ --warning-4: var(--amber-4);
202
+ --warning-5: var(--amber-5);
203
+ --warning-6: var(--amber-6);
204
+ --warning-7: var(--amber-7);
205
+ --warning-8: var(--amber-8);
206
+ --warning-9: var(--amber-9);
207
+ --warning-10: var(--amber-10);
208
+ --warning-11: var(--amber-11);
209
+ --warning-12: var(--amber-12);
210
+ --danger-1: var(--red-1);
211
+ --danger-2: var(--red-2);
212
+ --danger-3: var(--red-3);
213
+ --danger-4: var(--red-4);
214
+ --danger-5: var(--red-5);
215
+ --danger-6: var(--red-6);
216
+ --danger-7: var(--red-7);
217
+ --danger-8: var(--red-8);
218
+ --danger-9: var(--red-9);
219
+ --danger-10: var(--red-10);
220
+ --danger-11: var(--red-11);
221
+ --danger-12: var(--red-12);
222
+ --info-1: var(--blue-1);
223
+ --info-2: var(--blue-2);
224
+ --info-3: var(--blue-3);
225
+ --info-4: var(--blue-4);
226
+ --info-5: var(--blue-5);
227
+ --info-6: var(--blue-6);
228
+ --info-7: var(--blue-7);
229
+ --info-8: var(--blue-8);
230
+ --info-9: var(--blue-9);
231
+ --info-10: var(--blue-10);
232
+ --info-11: var(--blue-11);
233
+ --info-12: var(--blue-12);
234
+ }
235
+ [data-sandbox-theme="vault"],
236
+ [data-theme="light"],
237
+ .light {
238
+ --mauve-1: #fdfcfd;
239
+ --mauve-2: #faf9fb;
240
+ --mauve-3: #f2eff3;
241
+ --mauve-4: #eae7ec;
242
+ --mauve-5: #e3dfe6;
243
+ --mauve-6: #dbd8e0;
244
+ --mauve-7: #d0cdd7;
245
+ --mauve-8: #bcbac7;
246
+ --mauve-9: #8e8c99;
247
+ --mauve-10: #84828e;
248
+ --mauve-11: #65636d;
249
+ --mauve-12: #211f26;
250
+ --iris-1: #fdfdff;
251
+ --iris-2: #f8f8ff;
252
+ --iris-3: #f0f1fe;
253
+ --iris-4: #e6e7ff;
254
+ --iris-5: #dadcff;
255
+ --iris-6: #cbcdff;
256
+ --iris-7: #b8baf8;
257
+ --iris-8: #9b9ef0;
258
+ --iris-9: #5b5bd6;
259
+ --iris-10: #5151cd;
260
+ --iris-11: #5753c6;
261
+ --iris-12: #272962;
262
+ --green-1: #fbfefc;
263
+ --green-2: #f4fbf6;
264
+ --green-3: #e6f6eb;
265
+ --green-4: #d6f1df;
266
+ --green-5: #c4e8d1;
267
+ --green-6: #adddc0;
268
+ --green-7: #8eceaa;
269
+ --green-8: #5bb98b;
270
+ --green-9: #30a46c;
271
+ --green-10: #2b9a66;
272
+ --green-11: #218358;
273
+ --green-12: #193b2d;
274
+ --amber-1: #fefdfb;
275
+ --amber-2: #fefbe9;
276
+ --amber-3: #fff7c2;
277
+ --amber-4: #ffee9c;
278
+ --amber-5: #fbe577;
279
+ --amber-6: #f3d673;
280
+ --amber-7: #e9c162;
281
+ --amber-8: #e2a336;
282
+ --amber-9: #ffc53d;
283
+ --amber-10: #ffba18;
284
+ --amber-11: #ab6400;
285
+ --amber-12: #4f3422;
286
+ --red-1: #fffcfc;
287
+ --red-2: #fff7f7;
288
+ --red-3: #feebec;
289
+ --red-4: #ffdbdc;
290
+ --red-5: #ffcdce;
291
+ --red-6: #fdbdbe;
292
+ --red-7: #f4a9aa;
293
+ --red-8: #eb8e90;
294
+ --red-9: #e5484d;
295
+ --red-10: #dc3e42;
296
+ --red-11: #ce2c31;
297
+ --red-12: #641723;
298
+ --blue-1: #fbfdff;
299
+ --blue-2: #f4faff;
300
+ --blue-3: #e6f4fe;
301
+ --blue-4: #d5efff;
302
+ --blue-5: #c2e5ff;
303
+ --blue-6: #acd8fc;
304
+ --blue-7: #8ec8f6;
305
+ --blue-8: #5eb1ef;
306
+ --blue-9: #0090ff;
307
+ --blue-10: #0588f0;
308
+ --blue-11: #0d74ce;
309
+ --blue-12: #113264;
310
+ --plum-1: #fefcff;
311
+ --plum-2: #fdf7fd;
312
+ --plum-3: #fbebfb;
313
+ --plum-4: #f7def8;
314
+ --plum-5: #f2d1f3;
315
+ --plum-6: #e9c2ec;
316
+ --plum-7: #deade3;
317
+ --plum-8: #cf91d8;
318
+ --plum-9: #ab4aba;
319
+ --plum-10: #a144af;
320
+ --plum-11: #953ea3;
321
+ --plum-12: #53195d;
322
+ --orange-1: #fefcfb;
323
+ --orange-2: #fff7ed;
324
+ --orange-3: #ffefd6;
325
+ --orange-4: #ffdfb5;
326
+ --orange-5: #ffd19a;
327
+ --orange-6: #ffc182;
328
+ --orange-7: #f5ae73;
329
+ --orange-8: #ec9455;
330
+ --orange-9: #f76b15;
331
+ --orange-10: #ef5f00;
332
+ --orange-11: #cc4e00;
333
+ --orange-12: #582d1d;
334
+ --grass-1: #fbfefb;
335
+ --grass-2: #f5fbf5;
336
+ --grass-3: #e9f6e9;
337
+ --grass-4: #daf1db;
338
+ --grass-5: #c9e8ca;
339
+ --grass-6: #b2ddb5;
340
+ --grass-7: #94ce9a;
341
+ --grass-8: #65ba74;
342
+ --grass-9: #46a758;
343
+ --grass-10: #3e9b4f;
344
+ --grass-11: #2a7e3b;
345
+ --grass-12: #203c25;
346
+ --bronze-1: #fdfcfc;
347
+ --bronze-2: #fdf7f5;
348
+ --bronze-3: #f6edea;
349
+ --bronze-4: #efe4df;
350
+ --bronze-5: #e7d9d3;
351
+ --bronze-6: #dfcdc5;
352
+ --bronze-7: #d3bcb3;
353
+ --bronze-8: #c2a499;
354
+ --bronze-9: #a18072;
355
+ --bronze-10: #957468;
356
+ --bronze-11: #7d5e54;
357
+ --bronze-12: #43302b;
358
+ --crimson-1: #fffcfd;
359
+ --crimson-2: #fef7f9;
360
+ --crimson-3: #ffe9f0;
361
+ --crimson-4: #fedce7;
362
+ --crimson-5: #facedd;
363
+ --crimson-6: #f3bed1;
364
+ --crimson-7: #eaacc3;
365
+ --crimson-8: #e093b2;
366
+ --crimson-9: #e93d82;
367
+ --crimson-10: #df3478;
368
+ --crimson-11: #cb1d63;
369
+ --crimson-12: #621639;
370
+ --olive-1: #fcfdfc;
371
+ --olive-2: #f8faf8;
372
+ --olive-3: #eff1ef;
373
+ --olive-4: #e7e9e7;
374
+ --olive-5: #dfe2df;
375
+ --olive-6: #d7dad7;
376
+ --olive-7: #cccfcc;
377
+ --olive-8: #b9bcb8;
378
+ --olive-9: #898e87;
379
+ --olive-10: #7f847d;
380
+ --olive-11: #60655f;
381
+ --olive-12: #1d211c;
382
+ --gray-1: var(--mauve-1);
383
+ --gray-2: var(--mauve-2);
384
+ --gray-3: var(--mauve-3);
385
+ --gray-4: var(--mauve-4);
386
+ --gray-5: var(--mauve-5);
387
+ --gray-6: var(--mauve-6);
388
+ --gray-7: var(--mauve-7);
389
+ --gray-8: var(--mauve-8);
390
+ --gray-9: var(--mauve-9);
391
+ --gray-10: var(--mauve-10);
392
+ --gray-11: var(--mauve-11);
393
+ --gray-12: var(--mauve-12);
394
+ --accent-1: var(--iris-1);
395
+ --accent-2: var(--iris-2);
396
+ --accent-3: var(--iris-3);
397
+ --accent-4: var(--iris-4);
398
+ --accent-5: var(--iris-5);
399
+ --accent-6: var(--iris-6);
400
+ --accent-7: var(--iris-7);
401
+ --accent-8: var(--iris-8);
402
+ --accent-9: var(--iris-9);
403
+ --accent-10: var(--iris-10);
404
+ --accent-11: var(--iris-11);
405
+ --accent-12: var(--iris-12);
406
+ --success-1: var(--green-1);
407
+ --success-2: var(--green-2);
408
+ --success-3: var(--green-3);
409
+ --success-4: var(--green-4);
410
+ --success-5: var(--green-5);
411
+ --success-6: var(--green-6);
412
+ --success-7: var(--green-7);
413
+ --success-8: var(--green-8);
414
+ --success-9: var(--green-9);
415
+ --success-10: var(--green-10);
416
+ --success-11: var(--green-11);
417
+ --success-12: var(--green-12);
418
+ --warning-1: var(--amber-1);
419
+ --warning-2: var(--amber-2);
420
+ --warning-3: var(--amber-3);
421
+ --warning-4: var(--amber-4);
422
+ --warning-5: var(--amber-5);
423
+ --warning-6: var(--amber-6);
424
+ --warning-7: var(--amber-7);
425
+ --warning-8: var(--amber-8);
426
+ --warning-9: var(--amber-9);
427
+ --warning-10: var(--amber-10);
428
+ --warning-11: var(--amber-11);
429
+ --warning-12: var(--amber-12);
430
+ --danger-1: var(--red-1);
431
+ --danger-2: var(--red-2);
432
+ --danger-3: var(--red-3);
433
+ --danger-4: var(--red-4);
434
+ --danger-5: var(--red-5);
435
+ --danger-6: var(--red-6);
436
+ --danger-7: var(--red-7);
437
+ --danger-8: var(--red-8);
438
+ --danger-9: var(--red-9);
439
+ --danger-10: var(--red-10);
440
+ --danger-11: var(--red-11);
441
+ --danger-12: var(--red-12);
442
+ --info-1: var(--blue-1);
443
+ --info-2: var(--blue-2);
444
+ --info-3: var(--blue-3);
445
+ --info-4: var(--blue-4);
446
+ --info-5: var(--blue-5);
447
+ --info-6: var(--blue-6);
448
+ --info-7: var(--blue-7);
449
+ --info-8: var(--blue-8);
450
+ --info-9: var(--blue-9);
451
+ --info-10: var(--blue-10);
452
+ --info-11: var(--blue-11);
453
+ --info-12: var(--blue-12);
454
+ }
455
+
456
+ /* Domain ramp. Set data-domain on a cover, tile, avatar or listing and read
457
+ * --domain-1..12. An unknown domain gets the brand ramp. --domain-bubble is the
458
+ * light step 11 in both themes: white text on it passes 4.5:1 for every domain.
459
+ * A step 9 fill never carries text (white on orange 9 is 2.97:1). */
460
+ :root,
461
+ [data-domain] {
462
+ --domain-1: var(--iris-1);
463
+ --domain-2: var(--iris-2);
464
+ --domain-3: var(--iris-3);
465
+ --domain-4: var(--iris-4);
466
+ --domain-5: var(--iris-5);
467
+ --domain-6: var(--iris-6);
468
+ --domain-7: var(--iris-7);
469
+ --domain-8: var(--iris-8);
470
+ --domain-9: var(--iris-9);
471
+ --domain-10: var(--iris-10);
472
+ --domain-11: var(--iris-11);
473
+ --domain-12: var(--iris-12);
474
+ --domain-bubble: #5753c6;
475
+ }
476
+ [data-domain="personal"] {
477
+ --domain-1: var(--plum-1);
478
+ --domain-2: var(--plum-2);
479
+ --domain-3: var(--plum-3);
480
+ --domain-4: var(--plum-4);
481
+ --domain-5: var(--plum-5);
482
+ --domain-6: var(--plum-6);
483
+ --domain-7: var(--plum-7);
484
+ --domain-8: var(--plum-8);
485
+ --domain-9: var(--plum-9);
486
+ --domain-10: var(--plum-10);
487
+ --domain-11: var(--plum-11);
488
+ --domain-12: var(--plum-12);
489
+ --domain-bubble: #953ea3;
490
+ }
491
+ [data-domain="hospitality"] {
492
+ --domain-1: var(--orange-1);
493
+ --domain-2: var(--orange-2);
494
+ --domain-3: var(--orange-3);
495
+ --domain-4: var(--orange-4);
496
+ --domain-5: var(--orange-5);
497
+ --domain-6: var(--orange-6);
498
+ --domain-7: var(--orange-7);
499
+ --domain-8: var(--orange-8);
500
+ --domain-9: var(--orange-9);
501
+ --domain-10: var(--orange-10);
502
+ --domain-11: var(--orange-11);
503
+ --domain-12: var(--orange-12);
504
+ --domain-bubble: #cc4e00;
505
+ }
506
+ [data-domain="tax"] {
507
+ --domain-1: var(--grass-1);
508
+ --domain-2: var(--grass-2);
509
+ --domain-3: var(--grass-3);
510
+ --domain-4: var(--grass-4);
511
+ --domain-5: var(--grass-5);
512
+ --domain-6: var(--grass-6);
513
+ --domain-7: var(--grass-7);
514
+ --domain-8: var(--grass-8);
515
+ --domain-9: var(--grass-9);
516
+ --domain-10: var(--grass-10);
517
+ --domain-11: var(--grass-11);
518
+ --domain-12: var(--grass-12);
519
+ --domain-bubble: #2a7e3b;
520
+ }
521
+ [data-domain="law"] {
522
+ --domain-1: var(--blue-1);
523
+ --domain-2: var(--blue-2);
524
+ --domain-3: var(--blue-3);
525
+ --domain-4: var(--blue-4);
526
+ --domain-5: var(--blue-5);
527
+ --domain-6: var(--blue-6);
528
+ --domain-7: var(--blue-7);
529
+ --domain-8: var(--blue-8);
530
+ --domain-9: var(--blue-9);
531
+ --domain-10: var(--blue-10);
532
+ --domain-11: var(--blue-11);
533
+ --domain-12: var(--blue-12);
534
+ --domain-bubble: #0d74ce;
535
+ }
536
+ [data-domain="procurement"] {
537
+ --domain-1: var(--bronze-1);
538
+ --domain-2: var(--bronze-2);
539
+ --domain-3: var(--bronze-3);
540
+ --domain-4: var(--bronze-4);
541
+ --domain-5: var(--bronze-5);
542
+ --domain-6: var(--bronze-6);
543
+ --domain-7: var(--bronze-7);
544
+ --domain-8: var(--bronze-8);
545
+ --domain-9: var(--bronze-9);
546
+ --domain-10: var(--bronze-10);
547
+ --domain-11: var(--bronze-11);
548
+ --domain-12: var(--bronze-12);
549
+ --domain-bubble: #7d5e54;
550
+ }
551
+ [data-domain="negotiation"] {
552
+ --domain-1: var(--crimson-1);
553
+ --domain-2: var(--crimson-2);
554
+ --domain-3: var(--crimson-3);
555
+ --domain-4: var(--crimson-4);
556
+ --domain-5: var(--crimson-5);
557
+ --domain-6: var(--crimson-6);
558
+ --domain-7: var(--crimson-7);
559
+ --domain-8: var(--crimson-8);
560
+ --domain-9: var(--crimson-9);
561
+ --domain-10: var(--crimson-10);
562
+ --domain-11: var(--crimson-11);
563
+ --domain-12: var(--crimson-12);
564
+ --domain-bubble: #cb1d63;
565
+ }
566
+ [data-domain="logistics"] {
567
+ --domain-1: var(--amber-1);
568
+ --domain-2: var(--amber-2);
569
+ --domain-3: var(--amber-3);
570
+ --domain-4: var(--amber-4);
571
+ --domain-5: var(--amber-5);
572
+ --domain-6: var(--amber-6);
573
+ --domain-7: var(--amber-7);
574
+ --domain-8: var(--amber-8);
575
+ --domain-9: var(--amber-9);
576
+ --domain-10: var(--amber-10);
577
+ --domain-11: var(--amber-11);
578
+ --domain-12: var(--amber-12);
579
+ --domain-bubble: #ab6400;
580
+ }
581
+ [data-domain="defense"] {
582
+ --domain-1: var(--olive-1);
583
+ --domain-2: var(--olive-2);
584
+ --domain-3: var(--olive-3);
585
+ --domain-4: var(--olive-4);
586
+ --domain-5: var(--olive-5);
587
+ --domain-6: var(--olive-6);
588
+ --domain-7: var(--olive-7);
589
+ --domain-8: var(--olive-8);
590
+ --domain-9: var(--olive-9);
591
+ --domain-10: var(--olive-10);
592
+ --domain-11: var(--olive-11);
593
+ --domain-12: var(--olive-12);
594
+ --domain-bubble: #60655f;
595
+ }
@@ -0,0 +1,427 @@
1
+ /* Semantic layer. Generated by scripts/gen-ladders.mjs; edit the MAP there, not this file.
2
+ *
3
+ * Requires ladders.css. Every token family (hsl, md3, depth, bg, text, border,
4
+ * surface, status, btn) points at a ladder step, so components built on these
5
+ * tokens re-skin without edits. Light pages are white and cards separate from
6
+ * them by shadow and media. Dark steps surfaces up in small lightness
7
+ * increments, draws hairline edges, and casts a shadow only under floating
8
+ * layers. Chrome is neutral (mauve); colour belongs to content and to one
9
+ * call to action per page. */
10
+ :root,
11
+ [data-sandbox-ui],
12
+ [data-theme="dark"],
13
+ .dark {
14
+ --bg-page: var(--mauve-1);
15
+ --bg-subtle: var(--mauve-2);
16
+ --bg-card: var(--mauve-2);
17
+ --bg-raised: var(--mauve-3);
18
+ --bg-control: var(--mauve-3);
19
+ --bg-control-hover: var(--mauve-4);
20
+ --bg-control-active: var(--mauve-5);
21
+ --line-subtle: var(--mauve-6);
22
+ --line: var(--mauve-7);
23
+ --line-strong: var(--mauve-8);
24
+ --line-field: var(--mauve-9);
25
+ --fg: var(--mauve-12);
26
+ --fg-muted: var(--mauve-11);
27
+ --fg-faint: var(--mauve-10);
28
+ --ink: var(--mauve-12);
29
+ --on-ink: var(--mauve-1);
30
+ --accent-solid: var(--iris-9);
31
+ --accent-solid-hover: var(--iris-10);
32
+ --accent-text: var(--iris-11);
33
+ --accent-soft: var(--iris-3);
34
+ --accent-soft-hover: var(--iris-4);
35
+ --accent-line: var(--iris-7);
36
+ --hsl-background: 270 5.6% 7.1%;
37
+ --hsl-foreground: 240 6.2% 93.7%;
38
+ --hsl-card: 270 3.8% 10.2%;
39
+ --hsl-card-foreground: 240 6.2% 93.7%;
40
+ --hsl-popover: 260 4.2% 13.9%;
41
+ --hsl-popover-foreground: 240 6.2% 93.7%;
42
+ --hsl-primary: 240 60% 59.8%;
43
+ --hsl-primary-foreground: 0 0% 100%;
44
+ --hsl-secondary: 260 4.2% 13.9%;
45
+ --hsl-secondary-foreground: 240 6.2% 93.7%;
46
+ --hsl-muted: 260 4.2% 13.9%;
47
+ --hsl-muted-foreground: 258 6.9% 71.8%;
48
+ --hsl-accent: 270 4.7% 16.9%;
49
+ --hsl-accent-foreground: 240 6.2% 93.7%;
50
+ --hsl-destructive: 348 68.4% 18.6%;
51
+ --hsl-destructive-foreground: 350 100% 91%;
52
+ --hsl-border: 270 5% 23.5%;
53
+ --hsl-input: 251 4.8% 44.9%;
54
+ --hsl-ring: 242 63.7% 64.3%;
55
+ --hsl-success: 151 54.7% 41.6%;
56
+ --hsl-warning: 42 100% 62%;
57
+ --hsl-info: 206 100% 50%;
58
+ --sidebar-background: 270 3.8% 10.2%;
59
+ --sidebar-foreground: 240 6.2% 93.7%;
60
+ --sidebar-primary: 240 60% 59.8%;
61
+ --sidebar-primary-foreground: 0 0% 100%;
62
+ --sidebar-accent: 270 4.7% 16.9%;
63
+ --sidebar-accent-foreground: 240 6.2% 93.7%;
64
+ --sidebar-border: 270 5% 23.5%;
65
+ --sidebar-ring: 242 63.7% 64.3%;
66
+ --md3-surface: var(--mauve-1);
67
+ --md3-surface-dim: var(--mauve-1);
68
+ --md3-surface-bright: var(--mauve-5);
69
+ --md3-surface-container-lowest: var(--mauve-1);
70
+ --md3-surface-container-low: var(--mauve-2);
71
+ --md3-surface-container: var(--mauve-2);
72
+ --md3-surface-container-high: var(--mauve-3);
73
+ --md3-surface-container-highest: var(--mauve-4);
74
+ --md3-surface-variant: var(--mauve-3);
75
+ --md3-on-surface: var(--mauve-12);
76
+ --md3-on-surface-variant: var(--mauve-11);
77
+ --md3-primary: var(--iris-11);
78
+ --md3-primary-dim: var(--iris-10);
79
+ --md3-primary-container: var(--iris-9);
80
+ --md3-on-primary: #ffffff;
81
+ --md3-on-primary-container: #ffffff;
82
+ --md3-outline: var(--mauve-9);
83
+ --md3-outline-variant: var(--mauve-6);
84
+ --md3-error: var(--red-11);
85
+ --md3-error-container: var(--red-3);
86
+ --md3-on-error-container: var(--red-12);
87
+ --depth-1: var(--mauve-1);
88
+ --depth-2: var(--mauve-2);
89
+ --depth-3: var(--mauve-3);
90
+ --depth-4: var(--mauve-4);
91
+ --bg-root: var(--mauve-1);
92
+ --bg-dark: var(--mauve-1);
93
+ --bg-elevated: var(--mauve-3);
94
+ --bg-section: var(--mauve-1);
95
+ --bg-input: var(--mauve-2);
96
+ --bg-hover: var(--mauve-3);
97
+ --bg-selection: var(--iris-5);
98
+ --text-primary: var(--mauve-12);
99
+ --text-secondary: var(--mauve-12);
100
+ --text-muted: var(--mauve-11);
101
+ --text-dim: var(--mauve-11);
102
+ --border-subtle: var(--mauve-6);
103
+ --border-default: var(--mauve-7);
104
+ --border-hover: var(--mauve-8);
105
+ --border-accent: var(--iris-7);
106
+ --border-accent-hover: var(--iris-8);
107
+ --btn-primary-bg: var(--iris-9);
108
+ --btn-primary-hover: var(--iris-10);
109
+ --btn-primary-text: #ffffff;
110
+ --btn-cta-bg: var(--iris-9);
111
+ --btn-cta-text: #ffffff;
112
+ --accent-surface-soft: var(--iris-2);
113
+ --accent-surface-strong: var(--iris-4);
114
+ --surface-success-bg: var(--green-3);
115
+ --surface-success-border: var(--green-6);
116
+ --surface-success-text: var(--green-11);
117
+ --surface-warning-bg: var(--amber-3);
118
+ --surface-warning-border: var(--amber-6);
119
+ --surface-warning-text: var(--amber-11);
120
+ --surface-danger-bg: var(--red-3);
121
+ --surface-danger-border: var(--red-6);
122
+ --surface-danger-text: var(--red-11);
123
+ --surface-info-bg: var(--blue-3);
124
+ --surface-info-border: var(--blue-6);
125
+ --surface-info-text: var(--blue-11);
126
+ --surface-violet-bg: var(--iris-3);
127
+ --surface-violet-border: var(--iris-6);
128
+ --surface-violet-text: var(--iris-11);
129
+ --surface-orange-bg: var(--orange-3);
130
+ --surface-orange-border: var(--orange-6);
131
+ --surface-orange-text: var(--orange-11);
132
+ --surface-teal-bg: var(--grass-3);
133
+ --surface-teal-border: var(--grass-6);
134
+ --surface-teal-text: var(--grass-11);
135
+ --surface-neutral-bg: var(--mauve-3);
136
+ --surface-neutral-border: var(--mauve-6);
137
+ --surface-neutral-text: var(--mauve-11);
138
+ --status-running: var(--green-11);
139
+ --status-creating: var(--iris-11);
140
+ --status-stopped: var(--amber-11);
141
+ --status-warm: var(--orange-11);
142
+ --status-cold: var(--blue-11);
143
+ --status-error: var(--red-11);
144
+ --status-deleted: var(--mauve-11);
145
+ --brand-primary: var(--iris-9);
146
+ --brand-strong: var(--iris-3);
147
+ --brand-vibrant: var(--iris-9);
148
+ /* The brand call to action. Use it once per page, on the primary consumer
149
+ * action. White text passes on every stop (5.37, 5.39 and 5.18:1). */
150
+ --cta: linear-gradient(90deg, #5b5bd6 0%, #6e56cf 55%, #8e4ec6 100%);
151
+ --cta-hover: linear-gradient(90deg, #5151cd 0%, #654dc4 55%, #8347b9 100%);
152
+ /* Radius by role. The numeric --radius-sm..xl scale is unchanged, so no
153
+ * existing surface re-rounds; new surfaces pick the role they play. */
154
+ --radius-tag: 4px;
155
+ --radius-chip: 8px;
156
+ --radius-field: 12px;
157
+ --radius-panel: 16px;
158
+ --radius-cover: 20px;
159
+ --radius-sheet: 24px;
160
+ --radius-pill: 999px;
161
+ /* Motion. */
162
+ --ease-standard: cubic-bezier(0.2, 0, 0, 1);
163
+ --ease-emphasized: cubic-bezier(0.32, 0.72, 0, 1);
164
+ --dur-press: 120ms;
165
+ --dur-hover: 200ms;
166
+ --dur-card: 250ms;
167
+ --dur-sheet: 320ms;
168
+ --dur-reveal: 450ms;
169
+ /* Type. 12 px is the floor. */
170
+ --font-size-xs: 0.75rem;
171
+ --text-display: clamp(2.5rem, 2rem + 3vw, 4rem);
172
+ --text-display--line-height: 1.02;
173
+ --text-display--letter-spacing: -0.035em;
174
+ --text-display--font-weight: 650;
175
+ --text-hero: clamp(2.25rem, 2.2rem + 1.6vw, 3.5rem);
176
+ --text-hero--line-height: 1.05;
177
+ --text-hero--letter-spacing: -0.03em;
178
+ --text-hero--font-weight: 650;
179
+ --text-title: 2rem;
180
+ --text-title--line-height: 2.25rem;
181
+ --text-title--letter-spacing: -0.03em;
182
+ --text-title--font-weight: 600;
183
+ --text-page: 1.625rem;
184
+ --text-page--line-height: 1.875rem;
185
+ --text-page--letter-spacing: -0.02em;
186
+ --text-page--font-weight: 600;
187
+ --text-section: 1.375rem;
188
+ --text-section--line-height: 1.625rem;
189
+ --text-section--letter-spacing: -0.02em;
190
+ --text-section--font-weight: 600;
191
+ --text-lead: 1.125rem;
192
+ --text-lead--line-height: 1.5rem;
193
+ --text-lead--letter-spacing: 0em;
194
+ --text-lead--font-weight: 600;
195
+ --text-chat: 0.9375rem;
196
+ --text-chat--line-height: 1.375rem;
197
+ --text-chat--letter-spacing: 0em;
198
+ --text-chat--font-weight: 400;
199
+ --text-figure: 2.75rem;
200
+ --text-figure--line-height: 2.75rem;
201
+ --text-figure--letter-spacing: -0.02em;
202
+ --text-figure--font-weight: 600;
203
+ /* Elevation. In dark, a white hairline states the edge; only floating layers cast a shadow. */
204
+ --shadow-1: inset 0 0 0 1px rgb(255 255 255 / 0.06);
205
+ --shadow-2: inset 0 0 0 1px rgb(255 255 255 / 0.08), 0 8px 24px rgb(0 0 0 / 0.5);
206
+ --shadow-3: inset 0 0 0 1px rgb(255 255 255 / 0.1), 0 16px 48px rgb(0 0 0 / 0.6);
207
+ --shadow-card: var(--shadow-1);
208
+ --shadow-dropdown: var(--shadow-2);
209
+ --shadow-overlay: var(--shadow-3);
210
+ color-scheme: dark;
211
+ }
212
+ [data-sandbox-theme="vault"],
213
+ [data-theme="light"],
214
+ .light {
215
+ --bg-page: #ffffff;
216
+ --bg-subtle: var(--mauve-2);
217
+ --bg-card: #ffffff;
218
+ --bg-raised: #ffffff;
219
+ --bg-control: var(--mauve-3);
220
+ --bg-control-hover: var(--mauve-4);
221
+ --bg-control-active: var(--mauve-5);
222
+ --line-subtle: var(--mauve-6);
223
+ --line: var(--mauve-7);
224
+ --line-strong: var(--mauve-8);
225
+ --line-field: var(--mauve-9);
226
+ --fg: var(--mauve-12);
227
+ --fg-muted: var(--mauve-11);
228
+ --fg-faint: var(--mauve-10);
229
+ --ink: var(--mauve-12);
230
+ --on-ink: #ffffff;
231
+ --accent-solid: var(--iris-9);
232
+ --accent-solid-hover: var(--iris-10);
233
+ --accent-text: var(--iris-11);
234
+ --accent-soft: var(--iris-3);
235
+ --accent-soft-hover: var(--iris-4);
236
+ --accent-line: var(--iris-7);
237
+ --hsl-background: 0 0% 100%;
238
+ --hsl-foreground: 257 10.1% 13.5%;
239
+ --hsl-card: 0 0% 100%;
240
+ --hsl-card-foreground: 257 10.1% 13.5%;
241
+ --hsl-popover: 0 0% 100%;
242
+ --hsl-popover-foreground: 257 10.1% 13.5%;
243
+ --hsl-primary: 240 60% 59.8%;
244
+ --hsl-primary-foreground: 0 0% 100%;
245
+ --hsl-secondary: 285 14.3% 94.5%;
246
+ --hsl-secondary-foreground: 257 10.1% 13.5%;
247
+ --hsl-muted: 285 14.3% 94.5%;
248
+ --hsl-muted-foreground: 252 4.8% 40.8%;
249
+ --hsl-accent: 276 11.6% 91.6%;
250
+ --hsl-accent-foreground: 257 10.1% 13.5%;
251
+ --hsl-destructive: 358 64.8% 49%;
252
+ --hsl-destructive-foreground: 0 0% 100%;
253
+ --hsl-border: 262 11.4% 86.3%;
254
+ --hsl-input: 249 6% 57.5%;
255
+ --hsl-ring: 240 60% 59.8%;
256
+ --hsl-success: 151 54.7% 41.6%;
257
+ --hsl-warning: 42 100% 62%;
258
+ --hsl-info: 206 100% 50%;
259
+ --sidebar-background: 270 20% 98%;
260
+ --sidebar-foreground: 257 10.1% 13.5%;
261
+ --sidebar-primary: 240 60% 59.8%;
262
+ --sidebar-primary-foreground: 0 0% 100%;
263
+ --sidebar-accent: 276 11.6% 91.6%;
264
+ --sidebar-accent-foreground: 257 10.1% 13.5%;
265
+ --sidebar-border: 262 11.4% 86.3%;
266
+ --sidebar-ring: 240 60% 59.8%;
267
+ --md3-surface: #ffffff;
268
+ --md3-surface-dim: var(--mauve-2);
269
+ --md3-surface-bright: #ffffff;
270
+ --md3-surface-container-lowest: #ffffff;
271
+ --md3-surface-container-low: var(--mauve-2);
272
+ --md3-surface-container: #ffffff;
273
+ --md3-surface-container-high: var(--mauve-3);
274
+ --md3-surface-container-highest: #ffffff;
275
+ --md3-surface-variant: var(--mauve-3);
276
+ --md3-on-surface: var(--mauve-12);
277
+ --md3-on-surface-variant: var(--mauve-11);
278
+ --md3-primary: var(--iris-11);
279
+ --md3-primary-dim: var(--iris-10);
280
+ --md3-primary-container: var(--iris-9);
281
+ --md3-on-primary: #ffffff;
282
+ --md3-on-primary-container: #ffffff;
283
+ --md3-outline: var(--mauve-9);
284
+ --md3-outline-variant: var(--mauve-6);
285
+ --md3-error: var(--red-11);
286
+ --md3-error-container: var(--red-3);
287
+ --md3-on-error-container: var(--red-12);
288
+ --depth-1: #ffffff;
289
+ --depth-2: #ffffff;
290
+ --depth-3: var(--mauve-2);
291
+ --depth-4: #ffffff;
292
+ --bg-root: #ffffff;
293
+ --bg-dark: var(--mauve-2);
294
+ --bg-elevated: #ffffff;
295
+ --bg-section: var(--mauve-2);
296
+ --bg-input: #ffffff;
297
+ --bg-hover: var(--mauve-3);
298
+ --bg-selection: var(--iris-4);
299
+ --text-primary: var(--mauve-12);
300
+ --text-secondary: var(--mauve-12);
301
+ --text-muted: var(--mauve-11);
302
+ --text-dim: var(--mauve-11);
303
+ --border-subtle: var(--mauve-6);
304
+ --border-default: var(--mauve-7);
305
+ --border-hover: var(--mauve-8);
306
+ --border-accent: var(--iris-7);
307
+ --border-accent-hover: var(--iris-8);
308
+ --btn-primary-bg: var(--iris-9);
309
+ --btn-primary-hover: var(--iris-10);
310
+ --btn-primary-text: #ffffff;
311
+ --btn-cta-bg: var(--iris-9);
312
+ --btn-cta-text: #ffffff;
313
+ --accent-surface-soft: var(--iris-2);
314
+ --accent-surface-strong: var(--iris-4);
315
+ --surface-success-bg: var(--green-3);
316
+ --surface-success-border: var(--green-6);
317
+ --surface-success-text: var(--green-12);
318
+ --surface-warning-bg: var(--amber-3);
319
+ --surface-warning-border: var(--amber-6);
320
+ --surface-warning-text: var(--amber-12);
321
+ --surface-danger-bg: var(--red-3);
322
+ --surface-danger-border: var(--red-6);
323
+ --surface-danger-text: var(--red-12);
324
+ --surface-info-bg: var(--blue-3);
325
+ --surface-info-border: var(--blue-6);
326
+ --surface-info-text: var(--blue-12);
327
+ --surface-violet-bg: var(--iris-3);
328
+ --surface-violet-border: var(--iris-6);
329
+ --surface-violet-text: var(--iris-12);
330
+ --surface-orange-bg: var(--orange-3);
331
+ --surface-orange-border: var(--orange-6);
332
+ --surface-orange-text: var(--orange-12);
333
+ --surface-teal-bg: var(--grass-3);
334
+ --surface-teal-border: var(--grass-6);
335
+ --surface-teal-text: var(--grass-12);
336
+ --surface-neutral-bg: var(--mauve-3);
337
+ --surface-neutral-border: var(--mauve-6);
338
+ --surface-neutral-text: var(--mauve-11);
339
+ --status-running: var(--green-11);
340
+ --status-creating: var(--iris-11);
341
+ --status-stopped: var(--amber-11);
342
+ --status-warm: var(--orange-11);
343
+ --status-cold: var(--blue-11);
344
+ --status-error: var(--red-11);
345
+ --status-deleted: var(--mauve-11);
346
+ --brand-primary: var(--iris-9);
347
+ --brand-strong: var(--iris-12);
348
+ --brand-vibrant: var(--iris-9);
349
+ /* The brand call to action. Use it once per page, on the primary consumer
350
+ * action. White text passes on every stop (5.37, 5.39 and 5.18:1). */
351
+ --cta: linear-gradient(90deg, #5b5bd6 0%, #6e56cf 55%, #8e4ec6 100%);
352
+ --cta-hover: linear-gradient(90deg, #5151cd 0%, #654dc4 55%, #8347b9 100%);
353
+ /* Radius by role. The numeric --radius-sm..xl scale is unchanged, so no
354
+ * existing surface re-rounds; new surfaces pick the role they play. */
355
+ --radius-tag: 4px;
356
+ --radius-chip: 8px;
357
+ --radius-field: 12px;
358
+ --radius-panel: 16px;
359
+ --radius-cover: 20px;
360
+ --radius-sheet: 24px;
361
+ --radius-pill: 999px;
362
+ /* Motion. */
363
+ --ease-standard: cubic-bezier(0.2, 0, 0, 1);
364
+ --ease-emphasized: cubic-bezier(0.32, 0.72, 0, 1);
365
+ --dur-press: 120ms;
366
+ --dur-hover: 200ms;
367
+ --dur-card: 250ms;
368
+ --dur-sheet: 320ms;
369
+ --dur-reveal: 450ms;
370
+ /* Type. 12 px is the floor. */
371
+ --font-size-xs: 0.75rem;
372
+ --text-display: clamp(2.5rem, 2rem + 3vw, 4rem);
373
+ --text-display--line-height: 1.02;
374
+ --text-display--letter-spacing: -0.035em;
375
+ --text-display--font-weight: 650;
376
+ --text-hero: clamp(2.25rem, 2.2rem + 1.6vw, 3.5rem);
377
+ --text-hero--line-height: 1.05;
378
+ --text-hero--letter-spacing: -0.03em;
379
+ --text-hero--font-weight: 650;
380
+ --text-title: 2rem;
381
+ --text-title--line-height: 2.25rem;
382
+ --text-title--letter-spacing: -0.03em;
383
+ --text-title--font-weight: 600;
384
+ --text-page: 1.625rem;
385
+ --text-page--line-height: 1.875rem;
386
+ --text-page--letter-spacing: -0.02em;
387
+ --text-page--font-weight: 600;
388
+ --text-section: 1.375rem;
389
+ --text-section--line-height: 1.625rem;
390
+ --text-section--letter-spacing: -0.02em;
391
+ --text-section--font-weight: 600;
392
+ --text-lead: 1.125rem;
393
+ --text-lead--line-height: 1.5rem;
394
+ --text-lead--letter-spacing: 0em;
395
+ --text-lead--font-weight: 600;
396
+ --text-chat: 0.9375rem;
397
+ --text-chat--line-height: 1.375rem;
398
+ --text-chat--letter-spacing: 0em;
399
+ --text-chat--font-weight: 400;
400
+ --text-figure: 2.75rem;
401
+ --text-figure--line-height: 2.75rem;
402
+ --text-figure--letter-spacing: -0.02em;
403
+ --text-figure--font-weight: 600;
404
+ /* Elevation. In light, shadow separates a card from the white page. */
405
+ --shadow-1: 0 0 0 1px rgb(33 31 38 / 0.03), 0 2px 6px rgb(33 31 38 / 0.05), 0 4px 8px rgb(33 31 38 / 0.08);
406
+ --shadow-2: 0 0 0 1px rgb(33 31 38 / 0.04), 0 6px 16px rgb(33 31 38 / 0.12);
407
+ --shadow-3: 0 8px 28px rgb(33 31 38 / 0.28);
408
+ --shadow-card: var(--shadow-1);
409
+ --shadow-dropdown: var(--shadow-2);
410
+ --shadow-overlay: var(--shadow-3);
411
+ color-scheme: light;
412
+ }
413
+ @media (prefers-reduced-motion: reduce) {
414
+ :root,
415
+ [data-sandbox-ui],
416
+ [data-theme="dark"],
417
+ .dark,
418
+ [data-sandbox-theme="vault"],
419
+ [data-theme="light"],
420
+ .light {
421
+ --dur-press: 0ms;
422
+ --dur-hover: 0ms;
423
+ --dur-card: 0ms;
424
+ --dur-sheet: 0ms;
425
+ --dur-reveal: 0ms;
426
+ }
427
+ }
@@ -718,3 +718,54 @@
718
718
  * paper, lighter on a dark card, never tinted. */
719
719
  --border-strong: color-mix(in srgb, hsl(var(--hsl-border)), hsl(var(--hsl-foreground)) 20%);
720
720
  }
721
+
722
+ /* Chart marks — the palette behind @tangle-network/charts.
723
+ *
724
+ * One accent marks the measure a reader decides on (a rate bar, a frontier
725
+ * point, a solved attempt). One muted grey marks everything secondary. An
726
+ * ordinal indigo ramp marks App Grade tiers C < B < A < S; F has no fill and
727
+ * draws as a --chart-muted outline, the same mark as an unsolved attempt. No
728
+ * categorical palette ships: identity is carried by direct labels.
729
+ *
730
+ * Contrast against the dark canvas (#151523) and white paper, checked with the
731
+ * dataviz palette validator and WCAG ratios:
732
+ * ink 14.45 / 13.70, ink-muted 7.34 / 5.56, accent 6.05 / 7.41,
733
+ * muted 5.54 / 4.41, grid 1.46 / 1.12 (recessive by design).
734
+ * Tiers pass the ordinal checks in both modes: one hue, monotone lightness,
735
+ * visible steps. They are iris ladder steps (ladders.css) except #8b87f0 dark
736
+ * and #7c7fe3 light, which sit between two steps to keep the gaps even.
737
+ *
738
+ * The aliases re-resolve on every theme scope, as the focus rule above does,
739
+ * so a named theme's ink and hairlines carry into its charts. */
740
+ :root,
741
+ .dark,
742
+ .light,
743
+ [data-sandbox-ui],
744
+ [data-sandbox-theme],
745
+ [data-theme] {
746
+ --chart-ink: var(--text-primary);
747
+ --chart-ink-muted: var(--text-dim);
748
+ --chart-muted: var(--md3-outline);
749
+ --chart-grid: var(--md3-surface-container-high);
750
+ --chart-rule: var(--md3-outline-variant);
751
+ --chart-shade: var(--bg-hover);
752
+ --chart-accent: var(--brand-cool);
753
+ --chart-tier-c: #4a4a95;
754
+ --chart-tier-b: #5b5bd6;
755
+ --chart-tier-a: #8b87f0;
756
+ --chart-tier-s: #b1a9ff;
757
+ }
758
+
759
+ /* Light: the accent is the indigo fill (#4c3fc6, 7.41:1 on white) and the tier
760
+ * ramp runs light to dark. `[data-theme$="-light"]` covers the named light
761
+ * themes, which would otherwise inherit the dark ramp from :root. */
762
+ [data-sandbox-theme="vault"],
763
+ [data-theme="light"],
764
+ .light,
765
+ [data-theme$="-light"] {
766
+ --chart-accent: hsl(var(--hsl-primary));
767
+ --chart-tier-c: #9b9ef0;
768
+ --chart-tier-b: #7c7fe3;
769
+ --chart-tier-a: #5b5bd6;
770
+ --chart-tier-s: #272962;
771
+ }