tyrell-components 1.0.0-TC22 → 1.0.0-TC24

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.
@@ -12,79 +12,128 @@
12
12
  * --ty-brand-chroma: 0.13;
13
13
  * }
14
14
  *
15
- * Primary, secondary, neutral, surfaces, inputs, solid buttons all retint.
16
- * Success / danger / warning stay semantic (green / red / amber) — override
17
- * their *-hue/*-chroma seeds if you want them to follow the brand too.
15
+ * =====================================================================
16
+ * THE FORMULA
17
+ * =====================================================================
18
+ *
19
+ * Every color in the library is one formula on five axes:
20
+ *
21
+ * oklch(
22
+ * L = L-curve[shade] × flavor-l-factor ← Tier 3 × Tier 5
23
+ * C = flavor-chroma × saturation-curve[shade] ← Tier 2 × Tier 4
24
+ * H = flavor-hue ← Tier 2
25
+ * )
26
+ *
27
+ * Pick a flavor (primary / secondary / success / warning / danger /
28
+ * neutral). Pick a shade (strong / bold / base / soft / faint). That's
29
+ * the cell; the formula gives you its color.
30
+ *
31
+ * FLAVOR axis — which semantic role (carries its own hue, chroma,
32
+ * l-factor seeds)
33
+ * SHADE axis — 5 emphasis stops shared across flavors
34
+ * (strong / bold / base / soft / faint)
35
+ * HUE axis — what color family (0°–360°)
36
+ * CHROMA axis — how saturated (0 = grey, ~0.4 = max vivid)
37
+ * L axis — how dark or light (0 = black, 1 = white)
38
+ * Light mode: low L = more emphasis.
39
+ * Dark mode: high L = more emphasis (curve flips).
40
+ *
41
+ * Worked example — `--ty-color-warning-bold` in LIGHT mode:
42
+ *
43
+ * L = 0.46 × 1 = 0.46 ← l-bold × warning-l-factor
44
+ * C = 0.26 × 1.00 = 0.26 ← warning-chroma × c-bold-mult
45
+ * H = 75° ← warning-hue
46
+ * → oklch(0.46 0.26 75) (a punchy amber for +1 emphasis text)
47
+ *
48
+ * Want warning a notch darker without touching anything else? Set
49
+ * `--ty-warning-l-factor: 0.85` and the new L becomes 0.46 × 0.85 =
50
+ * 0.39. Every warning shade shifts in step; primary / success / danger
51
+ * are untouched.
52
+ *
53
+ * =====================================================================
54
+ * FILE LAYOUT
55
+ * =====================================================================
18
56
  *
19
- * Three layers of knobs you can override at :root (or html.dark for
20
- * per-mode tuning):
57
+ * SECTION 1 KNOBS
58
+ * The variables you might want to override. Six tiers from drop-in
59
+ * rebrand (Tier 1) to surgical per-flavor tweak (Tier 5) plus solid
60
+ * buttons (Tier 6).
21
61
  *
22
- * 1. SEEDSper-flavor hue + chroma.
23
- * --ty-brand-hue, --ty-brand-chroma
24
- * --ty-secondary-hue, --ty-secondary-chroma (default: brand + 60°)
25
- * --ty-success-hue, --ty-success-chroma (default: 145°)
26
- * --ty-danger-hue, --ty-danger-chroma (default: 25°)
27
- * --ty-warning-hue, --ty-warning-chroma (default: 75°)
28
- * --ty-neutral-hue, --ty-neutral-chroma (default: brand-hue, 0.005)
62
+ * SECTION 2IMPLEMENTATION
63
+ * The oklch() expressions that wire the knobs through to the actual
64
+ * color tokens. Rarely needs editing — Section 1 is the contract.
29
65
  *
30
- * 2. L-CURVE lightness stops shared by every flavor.
31
- * --ty-l-strong, --ty-l-bold, --ty-l-base, --ty-l-soft, --ty-l-faint
32
- * --ty-l-bg-base, --ty-l-bg-bold, --ty-l-bg-soft
33
- * Defaults in `:root` are tuned for light mode (lower L = more
34
- * emphasis). The `html.dark` block redefines them with inverted
35
- * values. Override either block to compress / expand the ladder.
66
+ * Browser support: oklch() is in every evergreen browser since mid-2023.
67
+ * Tier 6 (solid) additionally uses OKLCH relative color — oklch(from …) —
68
+ * which lands later: Chrome 119, Safari 16.4, Firefox 128 (mid-2024).
69
+ * Solid fills have no fallback below those versions.
36
70
  *
37
- * 3. SATURATION CURVE — chroma multipliers per shade.
38
- * --ty-c-strong-mult, --ty-c-bold-mult, --ty-c-base-mult,
39
- * --ty-c-soft-mult, --ty-c-faint-mult
40
- * --ty-c-bg-base-mult, --ty-c-bg-bold-mult, --ty-c-bg-soft-mult
41
- * Multiplied against the flavor chroma seed. Bump --ty-c-bold-mult
42
- * to 1.2 to make `+`-emphasis text more saturated; drop
43
- * --ty-c-faint-mult to 0.2 for whisper-quiet placeholders.
71
+ * ===================================================================== */
72
+
73
+ /* =====================================================================
74
+ * SECTION 1 — KNOBS
75
+ * =====================================================================
44
76
  *
45
- * Browser support: OKLCH is in every evergreen browser since mid-2023.
77
+ * Five tiers, ordered by how often you'd touch them. Override any of
78
+ * these in your own `:root` (or `html.dark` for per-mode tuning) —
79
+ * your declaration wins by source order.
46
80
  *
81
+ * Tier 1 — SEEDS brand-hue + chroma. Rebrand in 2 lines.
82
+ * Tier 2 — PER-FLAVOR ANCHORS each flavor's hue + chroma.
83
+ * Tier 3 — L-CURVE 5 lightness stops for the emphasis ramp.
84
+ * Tier 4 — SATURATION CURVE per-shade chroma multipliers.
85
+ * Tier 5 — PER-FLAVOR L-FACTOR per-flavor lightness multiplier — push
86
+ * one flavor up or down without touching
87
+ * the others. Default 1.
88
+ * Tier 6 — SOLID FILLS solid-button system: hover/active/tone
89
+ * L offsets + per-theme dim/desaturate.
47
90
  * ===================================================================== */
48
91
 
49
92
  :root {
50
93
  /* ----------------------------------------------------------------
51
- * SEEDS
94
+ * Tier 1 — SEEDS
95
+ * Brand-hue + chroma drive primary, neutral, surfaces, inputs,
96
+ * solid buttons. One slider rebrands the page.
52
97
  * --------------------------------------------------------------*/
53
98
 
54
99
  --ty-brand-hue: 230;
55
- --ty-brand-chroma: 0.13;
100
+ --ty-brand-chroma: 0.2;
56
101
 
57
- /* Every flavor's chroma tracks --ty-brand-chroma by default, at a
58
- * proportion that preserves the relative saturation hierarchy (danger
59
- * punchier than primary, neutral near-grey). Drag --ty-brand-chroma to
60
- * 0 → everything goes greyscale; push to 0.30 → everything goes vibrant.
61
- *
62
- * Pin any flavor independently by setting --ty-{flavor}-chroma to a
63
- * literal number (e.g. --ty-success-chroma: 0.14;). The multiplier
64
- * relationship breaks for that one flavor only. */
65
-
66
- /* Secondary rotates from brand by an exposed offset. Defaults to +60°
102
+ /* Secondary rotates from brand by an exposed offset. Default +60°
67
103
  * (sibling accent). Try 30° for a close sibling, 120° for triadic,
68
- * 180° for complement. Set --ty-secondary-hue to a literal number to
69
- * detach completely. */
104
+ * 180° for complement. Set --ty-secondary-hue to a literal number
105
+ * to detach completely. */
70
106
  --ty-secondary-offset: 60;
107
+
108
+ /* ----------------------------------------------------------------
109
+ * Tier 2 — PER-FLAVOR ANCHORS
110
+ * Semantic colors (success/warning/danger/neutral) have their own
111
+ * hue + chroma seeds so they keep meaning across brand changes.
112
+ * Override any individually:
113
+ * --ty-success-hue: 160; (more teal)
114
+ * --ty-warning-chroma: 0.2; (more vivid)
115
+ * --------------------------------------------------------------*/
116
+
71
117
  --ty-secondary-hue: calc(var(--ty-brand-hue) + var(--ty-secondary-offset));
72
118
  --ty-secondary-chroma: var(--ty-brand-chroma);
73
119
 
74
120
  --ty-success-hue: 145;
75
121
  --ty-success-chroma: calc(var(--ty-brand-chroma) * 1.08);
76
122
 
123
+ --ty-warning-hue: 75;
124
+ --ty-warning-chroma: calc(var(--ty-brand-chroma) * 2);
125
+
77
126
  --ty-danger-hue: 25;
78
127
  --ty-danger-chroma: calc(var(--ty-brand-chroma) * 1.31);
79
128
 
80
- --ty-warning-hue: 75;
81
- --ty-warning-chroma: calc(var(--ty-brand-chroma) * 1.15);
82
-
83
129
  --ty-neutral-hue: var(--ty-brand-hue);
84
130
  --ty-neutral-chroma: calc(var(--ty-brand-chroma) * 0.04);
85
131
 
86
132
  /* ----------------------------------------------------------------
87
- * L-CURVE light mode. Lower L = more emphasis.
133
+ * Tier 3 — L-CURVE (light mode)
134
+ * 5 lightness stops per flavor for the emphasis ramp.
135
+ * Lower L = darker = more emphasis in light mode.
136
+ * Plus 3 bg L stops for the soft-tint backgrounds.
88
137
  * --------------------------------------------------------------*/
89
138
 
90
139
  --ty-l-strong: 0.38; /* ++ max emphasis */
@@ -98,8 +147,10 @@
98
147
  --ty-l-bg-soft: 0.98;
99
148
 
100
149
  /* ----------------------------------------------------------------
101
- * SATURATION CURVEper-shade chroma multipliers.
102
- * Each shade's chroma = flavor-chroma × multiplier.
150
+ * Tier 4SATURATION CURVE
151
+ * Per-shade chroma multipliers. Each shade's chroma =
152
+ * flavor-chroma × multiplier. Drops near the extremes so
153
+ * near-white and near-black can hold their tint.
103
154
  * --------------------------------------------------------------*/
104
155
 
105
156
  --ty-c-strong-mult: 0.77;
@@ -112,80 +163,203 @@
112
163
  --ty-c-bg-bold-mult: 0.38;
113
164
  --ty-c-bg-soft-mult: 0.08;
114
165
 
115
- /* ================================================================
116
- * LIGHT MODEderived tokens. The math is the same for every
117
- * flavor; only the seed (hue + chroma) differs.
118
- * ================================================================ */
166
+ /* ----------------------------------------------------------------
167
+ * Tier 5PER-FLAVOR L-FACTOR
168
+ * Multiplies the L-curve values for that flavor only. Default 1 =
169
+ * no change. Useful when one flavor's brand-default sits too close
170
+ * to brand-hue on the wheel and the buttons blend.
171
+ *
172
+ * Example: brand-hue: 47° (gold). Warning sits at 75° (amber).
173
+ * Both render as similar warm browns at brand-chroma. Drop warning
174
+ * a notch and it darkens enough to stand apart:
175
+ * --ty-warning-l-factor: 0.85;
176
+ *
177
+ * NOTE: the L-curve flips between light and dark mode, so a factor
178
+ * < 1 darkens in light mode but DIMS in dark mode. If you want
179
+ * symmetric "more emphatic" in both modes, set the factor here for
180
+ * light AND set its inverse (1 / factor, roughly) in `html.dark`.
181
+ * --------------------------------------------------------------*/
182
+
183
+ --ty-primary-l-factor: 1;
184
+ --ty-secondary-l-factor: 1;
185
+ --ty-success-l-factor: 1;
186
+ --ty-warning-l-factor: 1.15;
187
+ --ty-danger-l-factor: 1;
188
+ --ty-neutral-l-factor: 1;
189
+
190
+ /* ----------------------------------------------------------------
191
+ * Tier 6 — SOLID FILLS
192
+ * Solid buttons are their OWN system, not the emphasis ramp. Each
193
+ * flavor's fill defaults to --ty-color-{flavor}; the knobs below
194
+ * derive its hover / active / tone+ / tone- and per-theme adjust.
195
+ * Math lives in SECTION 2 (search "Tier 6 — SOLID"); these are the
196
+ * dials.
197
+ *
198
+ * Axis A — interaction & tone, OKLCH L offsets on the fill.
199
+ * Axis B — per-theme adjust applied to the base fill (dim/desaturate).
200
+ *
201
+ * NOTE: like Tier 5, the emphasis curve flips for dark, so these L
202
+ * offsets are sign-flipped in `html.dark` below (darken in light =
203
+ * lighten in dark). Keep the two blocks in sync.
204
+ * --------------------------------------------------------------*/
205
+
206
+ /* Axis A — interaction (light: darken on press, so offsets are negative) */
207
+ --ty-solid-hover-l: -0.04; /* :hover */
208
+ --ty-solid-active-l: -0.08; /* :active */
209
+ --ty-solid-strong-l: -0.06; /* tone+ */
210
+ --ty-solid-soft-l: 0.1; /* tone- */
211
+
212
+ /* Axis B — per-theme adjust (light reads fine → identity) */
213
+ --ty-solid-l: 0; /* lightness offset — negative dims */
214
+ --ty-solid-c: 1; /* chroma multiplier — <1 desaturates */
215
+ --ty-solid-h: 0; /* hue offset (deg) */
216
+ }
217
+
218
+ /* Dark mode overrides for the L-curve and saturation curve. Tier 1 + 2
219
+ * seeds and Tier 5 L-factors carry through unchanged from :root. */
220
+ html.dark,
221
+ html[data-theme="dark"] {
222
+ /* Tier 3 dark — inverted curve. Higher L = lighter text = more
223
+ * emphasis on a dark background. */
224
+ --ty-l-strong: 0.72;
225
+ --ty-l-bold: 0.66;
226
+ --ty-l-base: 0.62;
227
+ --ty-l-soft: 0.46;
228
+ --ty-l-faint: 0.3;
229
+
230
+ --ty-l-bg-base: 0.22;
231
+ --ty-l-bg-bold: 0.26;
232
+ --ty-l-bg-soft: 0.19;
233
+
234
+ /* Tier 4 dark — dim shades hold more chroma so they don't grey out;
235
+ * strong shades trim chroma so bright tones don't over-pop. */
236
+ --ty-c-strong-mult: 0.77;
237
+ --ty-c-bold-mult: 1;
238
+ --ty-c-base-mult: 0.92;
239
+ --ty-c-soft-mult: 0.77;
240
+ --ty-c-faint-mult: 0.5;
241
+
242
+ --ty-c-bg-base-mult: 0.38;
243
+ --ty-c-bg-bold-mult: 0.54;
244
+ --ty-c-bg-soft-mult: 0.23;
245
+
246
+ /* Tier 6 dark — interaction offsets flip sign (press LIGHTENS on dark),
247
+ * and the per-theme adjust dims + desaturates the fills against the
248
+ * dark canvas. (Computed solid tokens live in SECTION 2 DARK.) */
249
+ --ty-solid-hover-l: 0.04; /* :hover */
250
+ --ty-solid-active-l: 0.08; /* :active */
251
+ --ty-solid-strong-l: 0.06; /* tone+ */
252
+ --ty-solid-soft-l: -0.1; /* tone- */
253
+
254
+ --ty-solid-l: -0.25; /* dim against dark canvas */
255
+ --ty-solid-c: 0.65; /* desaturate against dark canvas */
256
+ --ty-solid-h: 0; /* hue offset */
257
+ }
258
+
259
+ /* =====================================================================
260
+ * SECTION 2 — IMPLEMENTATION
261
+ * =====================================================================
262
+ *
263
+ * The oklch() expressions that turn Section 1's knobs into the actual
264
+ * --ty-color-*, --ty-bg-*, --ty-border-*, --ty-surface-*, --ty-input-*,
265
+ * and --ty-solid-* tokens that components read.
266
+ *
267
+ * Pattern for each flavor's 5-shade fg ramp + 3-shade bg ramp:
268
+ *
269
+ * --ty-color-{flavor}-{shade}: oklch(
270
+ * calc(var(--ty-l-{shade}) * var(--ty-{flavor}-l-factor)) ← L
271
+ * calc(var(--ty-{flavor}-chroma) * var(--ty-c-{shade}-mult)) ← C
272
+ * var(--ty-{flavor}-hue) ← H
273
+ * );
274
+ *
275
+ * Computed tokens are declared in BOTH `:root` and `html.dark` blocks
276
+ * because tyrell.css ships hardcoded dark-mode hexes at html.dark
277
+ * specificity (0,1,1); our brand-layer `:root` (0,1,0) would lose
278
+ * source-order otherwise. Same math both blocks — just different L/C
279
+ * inputs from Tier 3/4.
280
+ * ===================================================================== */
281
+
282
+ :root {
283
+ /* ----------------------------------------------------------------
284
+ * Flavor color ramps (fg + bg + border)
285
+ * --------------------------------------------------------------*/
119
286
 
120
287
  /* Primary */
121
288
  --ty-color-primary-strong: oklch(
122
- var(--ty-l-strong) calc(var(--ty-brand-chroma) * var(--ty-c-strong-mult))
123
- var(--ty-brand-hue)
289
+ calc(var(--ty-l-strong) * var(--ty-primary-l-factor))
290
+ calc(var(--ty-brand-chroma) * var(--ty-c-strong-mult)) var(--ty-brand-hue)
124
291
  );
125
292
  --ty-color-primary-bold: oklch(
126
- var(--ty-l-bold) calc(var(--ty-brand-chroma) * var(--ty-c-bold-mult))
127
- var(--ty-brand-hue)
293
+ calc(var(--ty-l-bold) * var(--ty-primary-l-factor))
294
+ calc(var(--ty-brand-chroma) * var(--ty-c-bold-mult)) var(--ty-brand-hue)
128
295
  );
129
296
  --ty-color-primary: oklch(
130
- var(--ty-l-base) calc(var(--ty-brand-chroma) * var(--ty-c-base-mult))
131
- var(--ty-brand-hue)
297
+ calc(var(--ty-l-base) * var(--ty-primary-l-factor))
298
+ calc(var(--ty-brand-chroma) * var(--ty-c-base-mult)) var(--ty-brand-hue)
132
299
  );
133
300
  --ty-color-primary-soft: oklch(
134
- var(--ty-l-soft) calc(var(--ty-brand-chroma) * var(--ty-c-soft-mult))
135
- var(--ty-brand-hue)
301
+ calc(var(--ty-l-soft) * var(--ty-primary-l-factor))
302
+ calc(var(--ty-brand-chroma) * var(--ty-c-soft-mult)) var(--ty-brand-hue)
136
303
  );
137
304
  --ty-color-primary-faint: oklch(
138
- var(--ty-l-faint) calc(var(--ty-brand-chroma) * var(--ty-c-faint-mult))
139
- var(--ty-brand-hue)
305
+ calc(var(--ty-l-faint) * var(--ty-primary-l-factor))
306
+ calc(var(--ty-brand-chroma) * var(--ty-c-faint-mult)) var(--ty-brand-hue)
140
307
  );
141
308
  --ty-bg-primary: oklch(
142
- var(--ty-l-bg-base) calc(var(--ty-brand-chroma) * var(--ty-c-bg-base-mult))
309
+ calc(var(--ty-l-bg-base) * var(--ty-primary-l-factor))
310
+ calc(var(--ty-brand-chroma) * var(--ty-c-bg-base-mult))
143
311
  var(--ty-brand-hue)
144
312
  );
145
313
  --ty-bg-primary-bold: oklch(
146
- var(--ty-l-bg-bold) calc(var(--ty-brand-chroma) * var(--ty-c-bg-bold-mult))
314
+ calc(var(--ty-l-bg-bold) * var(--ty-primary-l-factor))
315
+ calc(var(--ty-brand-chroma) * var(--ty-c-bg-bold-mult))
147
316
  var(--ty-brand-hue)
148
317
  );
149
318
  --ty-bg-primary-soft: oklch(
150
- var(--ty-l-bg-soft) calc(var(--ty-brand-chroma) * var(--ty-c-bg-soft-mult))
319
+ calc(var(--ty-l-bg-soft) * var(--ty-primary-l-factor))
320
+ calc(var(--ty-brand-chroma) * var(--ty-c-bg-soft-mult))
151
321
  var(--ty-brand-hue)
152
322
  );
153
323
  --ty-border-primary: var(--ty-color-primary-soft);
154
324
 
155
325
  /* Secondary */
156
326
  --ty-color-secondary-strong: oklch(
157
- var(--ty-l-strong)
327
+ calc(var(--ty-l-strong) * var(--ty-secondary-l-factor))
158
328
  calc(var(--ty-secondary-chroma) * var(--ty-c-strong-mult))
159
329
  var(--ty-secondary-hue)
160
330
  );
161
331
  --ty-color-secondary-bold: oklch(
162
- var(--ty-l-bold) calc(var(--ty-secondary-chroma) * var(--ty-c-bold-mult))
332
+ calc(var(--ty-l-bold) * var(--ty-secondary-l-factor))
333
+ calc(var(--ty-secondary-chroma) * var(--ty-c-bold-mult))
163
334
  var(--ty-secondary-hue)
164
335
  );
165
336
  --ty-color-secondary: oklch(
166
- var(--ty-l-base) calc(var(--ty-secondary-chroma) * var(--ty-c-base-mult))
337
+ calc(var(--ty-l-base) * var(--ty-secondary-l-factor))
338
+ calc(var(--ty-secondary-chroma) * var(--ty-c-base-mult))
167
339
  var(--ty-secondary-hue)
168
340
  );
169
341
  --ty-color-secondary-soft: oklch(
170
- var(--ty-l-soft) calc(var(--ty-secondary-chroma) * var(--ty-c-soft-mult))
342
+ calc(var(--ty-l-soft) * var(--ty-secondary-l-factor))
343
+ calc(var(--ty-secondary-chroma) * var(--ty-c-soft-mult))
171
344
  var(--ty-secondary-hue)
172
345
  );
173
346
  --ty-color-secondary-faint: oklch(
174
- var(--ty-l-faint) calc(var(--ty-secondary-chroma) * var(--ty-c-faint-mult))
347
+ calc(var(--ty-l-faint) * var(--ty-secondary-l-factor))
348
+ calc(var(--ty-secondary-chroma) * var(--ty-c-faint-mult))
175
349
  var(--ty-secondary-hue)
176
350
  );
177
351
  --ty-bg-secondary: oklch(
178
- var(--ty-l-bg-base)
352
+ calc(var(--ty-l-bg-base) * var(--ty-secondary-l-factor))
179
353
  calc(var(--ty-secondary-chroma) * var(--ty-c-bg-base-mult))
180
354
  var(--ty-secondary-hue)
181
355
  );
182
356
  --ty-bg-secondary-bold: oklch(
183
- var(--ty-l-bg-bold)
357
+ calc(var(--ty-l-bg-bold) * var(--ty-secondary-l-factor))
184
358
  calc(var(--ty-secondary-chroma) * var(--ty-c-bg-bold-mult))
185
359
  var(--ty-secondary-hue)
186
360
  );
187
361
  --ty-bg-secondary-soft: oklch(
188
- var(--ty-l-bg-soft)
362
+ calc(var(--ty-l-bg-soft) * var(--ty-secondary-l-factor))
189
363
  calc(var(--ty-secondary-chroma) * var(--ty-c-bg-soft-mult))
190
364
  var(--ty-secondary-hue)
191
365
  );
@@ -193,37 +367,42 @@
193
367
 
194
368
  /* Success */
195
369
  --ty-color-success-strong: oklch(
196
- var(--ty-l-strong) calc(var(--ty-success-chroma) * var(--ty-c-strong-mult))
370
+ calc(var(--ty-l-strong) * var(--ty-success-l-factor))
371
+ calc(var(--ty-success-chroma) * var(--ty-c-strong-mult))
197
372
  var(--ty-success-hue)
198
373
  );
199
374
  --ty-color-success-bold: oklch(
200
- var(--ty-l-bold) calc(var(--ty-success-chroma) * var(--ty-c-bold-mult))
375
+ calc(var(--ty-l-bold) * var(--ty-success-l-factor))
376
+ calc(var(--ty-success-chroma) * var(--ty-c-bold-mult))
201
377
  var(--ty-success-hue)
202
378
  );
203
379
  --ty-color-success: oklch(
204
- var(--ty-l-base) calc(var(--ty-success-chroma) * var(--ty-c-base-mult))
380
+ calc(var(--ty-l-base) * var(--ty-success-l-factor))
381
+ calc(var(--ty-success-chroma) * var(--ty-c-base-mult))
205
382
  var(--ty-success-hue)
206
383
  );
207
384
  --ty-color-success-soft: oklch(
208
- var(--ty-l-soft) calc(var(--ty-success-chroma) * var(--ty-c-soft-mult))
385
+ calc(var(--ty-l-soft) * var(--ty-success-l-factor))
386
+ calc(var(--ty-success-chroma) * var(--ty-c-soft-mult))
209
387
  var(--ty-success-hue)
210
388
  );
211
389
  --ty-color-success-faint: oklch(
212
- var(--ty-l-faint) calc(var(--ty-success-chroma) * var(--ty-c-faint-mult))
390
+ calc(var(--ty-l-faint) * var(--ty-success-l-factor))
391
+ calc(var(--ty-success-chroma) * var(--ty-c-faint-mult))
213
392
  var(--ty-success-hue)
214
393
  );
215
394
  --ty-bg-success: oklch(
216
- var(--ty-l-bg-base)
395
+ calc(var(--ty-l-bg-base) * var(--ty-success-l-factor))
217
396
  calc(var(--ty-success-chroma) * var(--ty-c-bg-base-mult))
218
397
  var(--ty-success-hue)
219
398
  );
220
399
  --ty-bg-success-bold: oklch(
221
- var(--ty-l-bg-bold)
400
+ calc(var(--ty-l-bg-bold) * var(--ty-success-l-factor))
222
401
  calc(var(--ty-success-chroma) * var(--ty-c-bg-bold-mult))
223
402
  var(--ty-success-hue)
224
403
  );
225
404
  --ty-bg-success-soft: oklch(
226
- var(--ty-l-bg-soft)
405
+ calc(var(--ty-l-bg-soft) * var(--ty-success-l-factor))
227
406
  calc(var(--ty-success-chroma) * var(--ty-c-bg-soft-mult))
228
407
  var(--ty-success-hue)
229
408
  );
@@ -231,72 +410,82 @@
231
410
 
232
411
  /* Danger */
233
412
  --ty-color-danger-strong: oklch(
234
- var(--ty-l-strong) calc(var(--ty-danger-chroma) * var(--ty-c-strong-mult))
413
+ calc(var(--ty-l-strong) * var(--ty-danger-l-factor))
414
+ calc(var(--ty-danger-chroma) * var(--ty-c-strong-mult))
235
415
  var(--ty-danger-hue)
236
416
  );
237
417
  --ty-color-danger-bold: oklch(
238
- var(--ty-l-bold) calc(var(--ty-danger-chroma) * var(--ty-c-bold-mult))
239
- var(--ty-danger-hue)
418
+ calc(var(--ty-l-bold) * var(--ty-danger-l-factor))
419
+ calc(var(--ty-danger-chroma) * var(--ty-c-bold-mult)) var(--ty-danger-hue)
240
420
  );
241
421
  --ty-color-danger: oklch(
242
- var(--ty-l-base) calc(var(--ty-danger-chroma) * var(--ty-c-base-mult))
243
- var(--ty-danger-hue)
422
+ calc(var(--ty-l-base) * var(--ty-danger-l-factor))
423
+ calc(var(--ty-danger-chroma) * var(--ty-c-base-mult)) var(--ty-danger-hue)
244
424
  );
245
425
  --ty-color-danger-soft: oklch(
246
- var(--ty-l-soft) calc(var(--ty-danger-chroma) * var(--ty-c-soft-mult))
247
- var(--ty-danger-hue)
426
+ calc(var(--ty-l-soft) * var(--ty-danger-l-factor))
427
+ calc(var(--ty-danger-chroma) * var(--ty-c-soft-mult)) var(--ty-danger-hue)
248
428
  );
249
429
  --ty-color-danger-faint: oklch(
250
- var(--ty-l-faint) calc(var(--ty-danger-chroma) * var(--ty-c-faint-mult))
430
+ calc(var(--ty-l-faint) * var(--ty-danger-l-factor))
431
+ calc(var(--ty-danger-chroma) * var(--ty-c-faint-mult))
251
432
  var(--ty-danger-hue)
252
433
  );
253
434
  --ty-bg-danger: oklch(
254
- var(--ty-l-bg-base) calc(var(--ty-danger-chroma) * var(--ty-c-bg-base-mult))
435
+ calc(var(--ty-l-bg-base) * var(--ty-danger-l-factor))
436
+ calc(var(--ty-danger-chroma) * var(--ty-c-bg-base-mult))
255
437
  var(--ty-danger-hue)
256
438
  );
257
439
  --ty-bg-danger-bold: oklch(
258
- var(--ty-l-bg-bold) calc(var(--ty-danger-chroma) * var(--ty-c-bg-bold-mult))
440
+ calc(var(--ty-l-bg-bold) * var(--ty-danger-l-factor))
441
+ calc(var(--ty-danger-chroma) * var(--ty-c-bg-bold-mult))
259
442
  var(--ty-danger-hue)
260
443
  );
261
444
  --ty-bg-danger-soft: oklch(
262
- var(--ty-l-bg-soft) calc(var(--ty-danger-chroma) * var(--ty-c-bg-soft-mult))
445
+ calc(var(--ty-l-bg-soft) * var(--ty-danger-l-factor))
446
+ calc(var(--ty-danger-chroma) * var(--ty-c-bg-soft-mult))
263
447
  var(--ty-danger-hue)
264
448
  );
265
449
  --ty-border-danger: var(--ty-color-danger-soft);
266
450
 
267
451
  /* Warning */
268
452
  --ty-color-warning-strong: oklch(
269
- var(--ty-l-strong) calc(var(--ty-warning-chroma) * var(--ty-c-strong-mult))
453
+ calc(var(--ty-l-strong) * var(--ty-warning-l-factor))
454
+ calc(var(--ty-warning-chroma) * var(--ty-c-strong-mult))
270
455
  var(--ty-warning-hue)
271
456
  );
272
457
  --ty-color-warning-bold: oklch(
273
- var(--ty-l-bold) calc(var(--ty-warning-chroma) * var(--ty-c-bold-mult))
458
+ calc(var(--ty-l-bold) * var(--ty-warning-l-factor))
459
+ calc(var(--ty-warning-chroma) * var(--ty-c-bold-mult))
274
460
  var(--ty-warning-hue)
275
461
  );
276
462
  --ty-color-warning: oklch(
277
- var(--ty-l-base) calc(var(--ty-warning-chroma) * var(--ty-c-base-mult))
463
+ calc(var(--ty-l-base) * var(--ty-warning-l-factor))
464
+ calc(var(--ty-warning-chroma) * var(--ty-c-base-mult))
278
465
  var(--ty-warning-hue)
279
466
  );
280
467
  --ty-color-warning-soft: oklch(
281
- var(--ty-l-soft) calc(var(--ty-warning-chroma) * var(--ty-c-soft-mult))
468
+ calc(var(--ty-l-soft) * var(--ty-warning-l-factor))
469
+ calc(var(--ty-warning-chroma) * var(--ty-c-soft-mult))
282
470
  var(--ty-warning-hue)
283
471
  );
284
472
  --ty-color-warning-faint: oklch(
285
- var(--ty-l-faint) calc(var(--ty-warning-chroma) * var(--ty-c-faint-mult))
473
+ calc(var(--ty-l-faint) * var(--ty-warning-l-factor))
474
+ calc(var(--ty-warning-chroma) * var(--ty-c-faint-mult))
286
475
  var(--ty-warning-hue)
287
476
  );
288
477
  --ty-bg-warning: oklch(
289
- var(--ty-l-bg-base)
478
+ calc(var(--ty-l-bg-base) * var(--ty-warning-l-factor))
290
479
  calc(var(--ty-warning-chroma) * var(--ty-c-bg-base-mult))
291
480
  var(--ty-warning-hue)
292
481
  );
293
482
  --ty-bg-warning-bold: oklch(
294
- var(--ty-l-bg-bold)
483
+ calc(var(--ty-l-bg-bold) * var(--ty-warning-l-factor))
295
484
  calc(var(--ty-warning-chroma) * var(--ty-c-bg-bold-mult))
296
485
  var(--ty-warning-hue)
297
486
  );
298
487
  --ty-bg-warning-soft: oklch(
299
- var(--ty-l-bg-soft)
488
+ calc(var(--ty-l-bg-soft) * var(--ty-warning-l-factor))
300
489
  calc(var(--ty-warning-chroma) * var(--ty-c-bg-soft-mult))
301
490
  var(--ty-warning-hue)
302
491
  );
@@ -304,37 +493,42 @@
304
493
 
305
494
  /* Neutral — same L curve, near-zero chroma so the grey scale stays grey. */
306
495
  --ty-color-neutral-strong: oklch(
307
- var(--ty-l-strong) calc(var(--ty-neutral-chroma) * var(--ty-c-strong-mult))
496
+ calc(var(--ty-l-strong) * var(--ty-neutral-l-factor))
497
+ calc(var(--ty-neutral-chroma) * var(--ty-c-strong-mult))
308
498
  var(--ty-neutral-hue)
309
499
  );
310
500
  --ty-color-neutral-bold: oklch(
311
- var(--ty-l-bold) calc(var(--ty-neutral-chroma) * var(--ty-c-bold-mult))
501
+ calc(var(--ty-l-bold) * var(--ty-neutral-l-factor))
502
+ calc(var(--ty-neutral-chroma) * var(--ty-c-bold-mult))
312
503
  var(--ty-neutral-hue)
313
504
  );
314
505
  --ty-color-neutral: oklch(
315
- var(--ty-l-base) calc(var(--ty-neutral-chroma) * var(--ty-c-base-mult))
506
+ calc(var(--ty-l-base) * var(--ty-neutral-l-factor))
507
+ calc(var(--ty-neutral-chroma) * var(--ty-c-base-mult))
316
508
  var(--ty-neutral-hue)
317
509
  );
318
510
  --ty-color-neutral-soft: oklch(
319
- var(--ty-l-soft) calc(var(--ty-neutral-chroma) * var(--ty-c-soft-mult))
511
+ calc(var(--ty-l-soft) * var(--ty-neutral-l-factor))
512
+ calc(var(--ty-neutral-chroma) * var(--ty-c-soft-mult))
320
513
  var(--ty-neutral-hue)
321
514
  );
322
515
  --ty-color-neutral-faint: oklch(
323
- var(--ty-l-faint) calc(var(--ty-neutral-chroma) * var(--ty-c-faint-mult))
516
+ calc(var(--ty-l-faint) * var(--ty-neutral-l-factor))
517
+ calc(var(--ty-neutral-chroma) * var(--ty-c-faint-mult))
324
518
  var(--ty-neutral-hue)
325
519
  );
326
520
  --ty-bg-neutral: oklch(
327
- var(--ty-l-bg-base)
521
+ calc(var(--ty-l-bg-base) * var(--ty-neutral-l-factor))
328
522
  calc(var(--ty-neutral-chroma) * var(--ty-c-bg-base-mult))
329
523
  var(--ty-neutral-hue)
330
524
  );
331
525
  --ty-bg-neutral-bold: oklch(
332
- var(--ty-l-bg-bold)
526
+ calc(var(--ty-l-bg-bold) * var(--ty-neutral-l-factor))
333
527
  calc(var(--ty-neutral-chroma) * var(--ty-c-bg-bold-mult))
334
528
  var(--ty-neutral-hue)
335
529
  );
336
530
  --ty-bg-neutral-soft: oklch(
337
- var(--ty-l-bg-soft)
531
+ calc(var(--ty-l-bg-soft) * var(--ty-neutral-l-factor))
338
532
  calc(var(--ty-neutral-chroma) * var(--ty-c-bg-soft-mult))
339
533
  var(--ty-neutral-hue)
340
534
  );
@@ -345,21 +539,27 @@
345
539
  0.99 calc(var(--ty-neutral-chroma) * 0.4) var(--ty-neutral-hue)
346
540
  );
347
541
 
348
- /* Global neutral borders — read off the neutral color ramp. */
542
+ /* ----------------------------------------------------------------
543
+ * Global neutral borders — read off the neutral color ramp.
544
+ * --------------------------------------------------------------*/
349
545
  --ty-border-strong: var(--ty-color-neutral-bold);
350
546
  --ty-border: var(--ty-color-neutral-soft);
351
547
  --ty-border-bold: var(--ty-color-neutral-soft);
352
548
  --ty-border-soft: var(--ty-color-neutral-faint);
353
549
  --ty-border-faint: var(--ty-color-neutral-faint);
354
550
 
355
- /* Surfaces — canvas tinted slightly toward brand for warmth. */
551
+ /* ----------------------------------------------------------------
552
+ * Surfaces — canvas tinted slightly toward brand for warmth.
553
+ * --------------------------------------------------------------*/
356
554
  --ty-surface-canvas: oklch(0.985 0.005 var(--ty-brand-hue));
357
555
  --ty-surface-content: oklch(1 0 0);
358
556
  --ty-surface-elevated: oklch(1 0 0);
359
557
  --ty-surface-floating: oklch(1 0 0);
360
558
  --ty-surface-input: oklch(1 0 0);
361
559
 
362
- /* Inputs — tied to neutral ramp so form controls retint with brand. */
560
+ /* ----------------------------------------------------------------
561
+ * Inputs — tied to neutral ramp so form controls retint with brand.
562
+ * --------------------------------------------------------------*/
363
563
  --ty-input-bg: var(--ty-surface-input);
364
564
  --ty-input-color: var(--ty-color-neutral-strong);
365
565
  --ty-input-border: var(--ty-color-neutral-soft);
@@ -374,161 +574,225 @@
374
574
  var(--ty-color-primary) 5%,
375
575
  transparent
376
576
  );
577
+ }
377
578
 
378
- /* Solid buttons — re-route through --ty-color-*. */
379
- --ty-solid-primary: var(--ty-color-primary);
380
- --ty-solid-primary-strong: var(--ty-color-primary-bold);
381
- --ty-solid-primary-soft: var(--ty-color-primary-soft);
382
- --ty-solid-primary-fg: white;
579
+ /* ----------------------------------------------------------------
580
+ * Tier 6 — SOLID (implementation)
581
+ * Solid is its OWN system, NOT the text/emphasis ramp. The dials
582
+ * (--ty-solid-hover-l / -active-l / -strong-l / -soft-l and
583
+ * --ty-solid-l / -c / -h) live in SECTION 1, Tier 6. Below is the
584
+ * derivation only: base fill bakes in the per-theme adjust (Axis B);
585
+ * hover/active/strong/soft offset the base by Axis A. Override any
586
+ * single --ty-solid-{flavor}-{state} to recolor just that segment.
587
+ *
588
+ * Declared at `html:root` (specificity 0,1,1) — NOT plain `:root` (0,1,0) —
589
+ * on purpose: it must out-rank tyrell.css's hardcoded dark solids at
590
+ * `html.dark` (0,1,1). It wins light by specificity over base's `html{}`,
591
+ * and wins dark by source order over base's `html.dark` (brand loads after).
592
+ * That's what lets dark solids re-tint with --ty-brand-hue. Declared ONCE —
593
+ * the oklch(from var(--ty-color-*)) formulas resolve per-mode automatically,
594
+ * so no dark duplicate is needed.
595
+ * --------------------------------------------------------------*/
596
+ html:root {
597
+ /* base fill per flavor (= flavor color, theme-adjusted by Axis B) */
598
+ --ty-solid-primary: oklch(
599
+ from var(--ty-color-primary) calc(l + var(--ty-solid-l))
600
+ calc(c * var(--ty-solid-c)) calc(h + var(--ty-solid-h))
601
+ );
602
+ --ty-solid-secondary: oklch(
603
+ from var(--ty-color-secondary) calc(l + var(--ty-solid-l))
604
+ calc(c * var(--ty-solid-c)) calc(h + var(--ty-solid-h))
605
+ );
606
+ --ty-solid-success: oklch(
607
+ from var(--ty-color-success) calc(l + var(--ty-solid-l))
608
+ calc(c * var(--ty-solid-c)) calc(h + var(--ty-solid-h))
609
+ );
610
+ --ty-solid-danger: oklch(
611
+ from var(--ty-color-danger) calc(l + var(--ty-solid-l))
612
+ calc(c * var(--ty-solid-c)) calc(h + var(--ty-solid-h))
613
+ );
614
+ --ty-solid-warning: oklch(
615
+ from var(--ty-color-warning) calc(l + var(--ty-solid-l))
616
+ calc(c * var(--ty-solid-c)) calc(h + var(--ty-solid-h))
617
+ );
618
+ /* neutral is a deliberate dark grey fill, not the neutral text color */
619
+ --ty-solid-neutral: oklch(
620
+ 0.4 calc(var(--ty-neutral-chroma) * var(--ty-c-strong-mult))
621
+ var(--ty-neutral-hue)
622
+ );
383
623
 
384
- --ty-solid-secondary: var(--ty-color-secondary);
385
- --ty-solid-secondary-strong: var(--ty-color-secondary-bold);
386
- --ty-solid-secondary-soft: var(--ty-color-secondary-soft);
624
+ --ty-solid-primary-fg: white;
387
625
  --ty-solid-secondary-fg: white;
388
-
389
- --ty-solid-success: var(--ty-color-success);
390
- --ty-solid-success-strong: var(--ty-color-success-bold);
391
- --ty-solid-success-soft: var(--ty-color-success-soft);
392
626
  --ty-solid-success-fg: white;
393
-
394
- --ty-solid-danger: var(--ty-color-danger);
395
- --ty-solid-danger-strong: var(--ty-color-danger-bold);
396
- --ty-solid-danger-soft: var(--ty-color-danger-soft);
397
627
  --ty-solid-danger-fg: white;
398
-
399
- --ty-solid-warning: var(--ty-color-warning);
400
- --ty-solid-warning-strong: var(--ty-color-warning-bold);
401
- --ty-solid-warning-soft: var(--ty-color-warning-soft);
402
628
  --ty-solid-warning-fg: white;
629
+ --ty-solid-neutral-fg: white;
403
630
 
404
- /* Solid neutral routes to neutral-strong rather than neutral-base.
405
- * Neutral-base (L_base) reads as a washy mid-grey on white surfaces;
406
- * neutral-strong gives the dark-grey "default action" weight that
407
- * design systems typically use for neutral buttons. The "strong"
408
- * solid variant clamps higher emphasis (same shade, kept for the
409
- * solid-* API shape); "soft" softens to neutral-bold for inactive
410
- * states. */
631
+ /* derived states axis 2 offsets on each base fill */
632
+ --ty-solid-primary-hover: oklch(
633
+ from var(--ty-solid-primary) calc(l + var(--ty-solid-hover-l)) c h
634
+ );
635
+ --ty-solid-primary-active: oklch(
636
+ from var(--ty-solid-primary) calc(l + var(--ty-solid-active-l)) c h
637
+ );
638
+ --ty-solid-primary-strong: oklch(
639
+ from var(--ty-solid-primary) calc(l + var(--ty-solid-strong-l)) c h
640
+ );
641
+ --ty-solid-primary-soft: oklch(
642
+ from var(--ty-solid-primary) calc(l + var(--ty-solid-soft-l)) c h
643
+ );
411
644
 
412
- --ty-solid-neutral-soft: oklch(
413
- 0.6 calc(var(--ty-neutral-chroma) * var(--ty-c-strong-mult))
414
- var(--ty-neutral-hue)
645
+ --ty-solid-secondary-hover: oklch(
646
+ from var(--ty-solid-secondary) calc(l + var(--ty-solid-hover-l)) c h
415
647
  );
416
- --ty-solid-neutral: oklch(
417
- 0.4 calc(var(--ty-neutral-chroma) * var(--ty-c-strong-mult))
418
- var(--ty-neutral-hue)
648
+ --ty-solid-secondary-active: oklch(
649
+ from var(--ty-solid-secondary) calc(l + var(--ty-solid-active-l)) c h
650
+ );
651
+ --ty-solid-secondary-strong: oklch(
652
+ from var(--ty-solid-secondary) calc(l + var(--ty-solid-strong-l)) c h
653
+ );
654
+ --ty-solid-secondary-soft: oklch(
655
+ from var(--ty-solid-secondary) calc(l + var(--ty-solid-soft-l)) c h
656
+ );
657
+
658
+ --ty-solid-success-hover: oklch(
659
+ from var(--ty-solid-success) calc(l + var(--ty-solid-hover-l)) c h
660
+ );
661
+ --ty-solid-success-active: oklch(
662
+ from var(--ty-solid-success) calc(l + var(--ty-solid-active-l)) c h
663
+ );
664
+ --ty-solid-success-strong: oklch(
665
+ from var(--ty-solid-success) calc(l + var(--ty-solid-strong-l)) c h
666
+ );
667
+ --ty-solid-success-soft: oklch(
668
+ from var(--ty-solid-success) calc(l + var(--ty-solid-soft-l)) c h
669
+ );
670
+
671
+ --ty-solid-danger-hover: oklch(
672
+ from var(--ty-solid-danger) calc(l + var(--ty-solid-hover-l)) c h
673
+ );
674
+ --ty-solid-danger-active: oklch(
675
+ from var(--ty-solid-danger) calc(l + var(--ty-solid-active-l)) c h
676
+ );
677
+ --ty-solid-danger-strong: oklch(
678
+ from var(--ty-solid-danger) calc(l + var(--ty-solid-strong-l)) c h
679
+ );
680
+ --ty-solid-danger-soft: oklch(
681
+ from var(--ty-solid-danger) calc(l + var(--ty-solid-soft-l)) c h
682
+ );
683
+
684
+ --ty-solid-warning-hover: oklch(
685
+ from var(--ty-solid-warning) calc(l + var(--ty-solid-hover-l)) c h
686
+ );
687
+ --ty-solid-warning-active: oklch(
688
+ from var(--ty-solid-warning) calc(l + var(--ty-solid-active-l)) c h
689
+ );
690
+ --ty-solid-warning-strong: oklch(
691
+ from var(--ty-solid-warning) calc(l + var(--ty-solid-strong-l)) c h
692
+ );
693
+ --ty-solid-warning-soft: oklch(
694
+ from var(--ty-solid-warning) calc(l + var(--ty-solid-soft-l)) c h
419
695
  );
420
696
 
697
+ --ty-solid-neutral-hover: oklch(
698
+ from var(--ty-solid-neutral) calc(l + var(--ty-solid-hover-l)) c h
699
+ );
700
+ --ty-solid-neutral-active: oklch(
701
+ from var(--ty-solid-neutral) calc(l + var(--ty-solid-active-l)) c h
702
+ );
421
703
  --ty-solid-neutral-strong: oklch(
422
- 0.2 calc(var(--ty-neutral-chroma) * var(--ty-c-strong-mult))
423
- var(--ty-neutral-hue)
704
+ from var(--ty-solid-neutral) calc(l + var(--ty-solid-strong-l)) c h
705
+ );
706
+ --ty-solid-neutral-soft: oklch(
707
+ from var(--ty-solid-neutral) calc(l + var(--ty-solid-soft-l)) c h
424
708
  );
425
709
  }
426
710
 
427
711
  /* =====================================================================
428
- * DARK MODE L-curve and saturation-curve overridden. Same flavor
429
- * seeds drive both modes; only the L and chroma multipliers change.
712
+ * SECTION 2 DARK — same computations re-declared so html.dark (0,1,1)
713
+ * matches tyrell.css's hardcoded dark-mode hexes at source-order
714
+ * specificity. The math is identical to the :root block above; only
715
+ * the L/C inputs differ (from html.dark's Tier 3/4 overrides).
430
716
  * ===================================================================== */
431
717
 
432
718
  html.dark,
433
719
  html[data-theme="dark"] {
434
- --ty-l-strong: 0.86; /* ++ max emphasis in dark = brightest */
435
- --ty-l-bold: 0.74;
436
- --ty-l-base: 0.62;
437
- --ty-l-soft: 0.46;
438
- --ty-l-faint: 0.3; /* -- min emphasis = darkest */
439
-
440
- --ty-l-bg-base: 0.22;
441
- --ty-l-bg-bold: 0.26;
442
- --ty-l-bg-soft: 0.19;
443
-
444
- /* Saturation curve — dark pushes faint chroma up so dim shades don't
445
- * collapse into grey, and trims strong so bright tones don't over-pop. */
446
- --ty-c-strong-mult: 0.77;
447
- --ty-c-bold-mult: 1;
448
- --ty-c-base-mult: 0.92;
449
- --ty-c-soft-mult: 0.77;
450
- --ty-c-faint-mult: 0.5;
451
-
452
- --ty-c-bg-base-mult: 0.38;
453
- --ty-c-bg-bold-mult: 0.54;
454
- --ty-c-bg-soft-mult: 0.23;
455
-
456
- /* Color tokens re-declared here so we match tyrell.css's `html.dark` block
457
- * at the same selector specificity (0,1,1). Without these, tyrell.css's
458
- * hardcoded dark-mode hexes out-rank the brand-layer ':root' definitions
459
- * and the brand-hue slider does nothing in dark mode. The math is the
460
- * same as the light block — just uses the dark L-curve / chroma curve
461
- * defined above. */
462
-
463
720
  /* Primary */
464
721
  --ty-color-primary-strong: oklch(
465
- var(--ty-l-strong) calc(var(--ty-brand-chroma) * var(--ty-c-strong-mult))
466
- var(--ty-brand-hue)
722
+ calc(var(--ty-l-strong) * var(--ty-primary-l-factor))
723
+ calc(var(--ty-brand-chroma) * var(--ty-c-strong-mult)) var(--ty-brand-hue)
467
724
  );
468
725
  --ty-color-primary-bold: oklch(
469
- var(--ty-l-bold) calc(var(--ty-brand-chroma) * var(--ty-c-bold-mult))
470
- var(--ty-brand-hue)
726
+ calc(var(--ty-l-bold) * var(--ty-primary-l-factor))
727
+ calc(var(--ty-brand-chroma) * var(--ty-c-bold-mult)) var(--ty-brand-hue)
471
728
  );
472
729
  --ty-color-primary: oklch(
473
- var(--ty-l-base) calc(var(--ty-brand-chroma) * var(--ty-c-base-mult))
474
- var(--ty-brand-hue)
730
+ calc(var(--ty-l-base) * var(--ty-primary-l-factor))
731
+ calc(var(--ty-brand-chroma) * var(--ty-c-base-mult)) var(--ty-brand-hue)
475
732
  );
476
733
  --ty-color-primary-soft: oklch(
477
- var(--ty-l-soft) calc(var(--ty-brand-chroma) * var(--ty-c-soft-mult))
478
- var(--ty-brand-hue)
734
+ calc(var(--ty-l-soft) * var(--ty-primary-l-factor))
735
+ calc(var(--ty-brand-chroma) * var(--ty-c-soft-mult)) var(--ty-brand-hue)
479
736
  );
480
737
  --ty-color-primary-faint: oklch(
481
- var(--ty-l-faint) calc(var(--ty-brand-chroma) * var(--ty-c-faint-mult))
482
- var(--ty-brand-hue)
738
+ calc(var(--ty-l-faint) * var(--ty-primary-l-factor))
739
+ calc(var(--ty-brand-chroma) * var(--ty-c-faint-mult)) var(--ty-brand-hue)
483
740
  );
484
741
  --ty-bg-primary: oklch(
485
- var(--ty-l-bg-base) calc(var(--ty-brand-chroma) * var(--ty-c-bg-base-mult))
742
+ calc(var(--ty-l-bg-base) * var(--ty-primary-l-factor))
743
+ calc(var(--ty-brand-chroma) * var(--ty-c-bg-base-mult))
486
744
  var(--ty-brand-hue)
487
745
  );
488
746
  --ty-bg-primary-bold: oklch(
489
- var(--ty-l-bg-bold) calc(var(--ty-brand-chroma) * var(--ty-c-bg-bold-mult))
747
+ calc(var(--ty-l-bg-bold) * var(--ty-primary-l-factor))
748
+ calc(var(--ty-brand-chroma) * var(--ty-c-bg-bold-mult))
490
749
  var(--ty-brand-hue)
491
750
  );
492
751
  --ty-bg-primary-soft: oklch(
493
- var(--ty-l-bg-soft) calc(var(--ty-brand-chroma) * var(--ty-c-bg-soft-mult))
752
+ calc(var(--ty-l-bg-soft) * var(--ty-primary-l-factor))
753
+ calc(var(--ty-brand-chroma) * var(--ty-c-bg-soft-mult))
494
754
  var(--ty-brand-hue)
495
755
  );
496
756
  --ty-border-primary: var(--ty-color-primary-soft);
497
757
 
498
758
  /* Secondary */
499
759
  --ty-color-secondary-strong: oklch(
500
- var(--ty-l-strong)
760
+ calc(var(--ty-l-strong) * var(--ty-secondary-l-factor))
501
761
  calc(var(--ty-secondary-chroma) * var(--ty-c-strong-mult))
502
762
  var(--ty-secondary-hue)
503
763
  );
504
764
  --ty-color-secondary-bold: oklch(
505
- var(--ty-l-bold) calc(var(--ty-secondary-chroma) * var(--ty-c-bold-mult))
765
+ calc(var(--ty-l-bold) * var(--ty-secondary-l-factor))
766
+ calc(var(--ty-secondary-chroma) * var(--ty-c-bold-mult))
506
767
  var(--ty-secondary-hue)
507
768
  );
508
769
  --ty-color-secondary: oklch(
509
- var(--ty-l-base) calc(var(--ty-secondary-chroma) * var(--ty-c-base-mult))
770
+ calc(var(--ty-l-base) * var(--ty-secondary-l-factor))
771
+ calc(var(--ty-secondary-chroma) * var(--ty-c-base-mult))
510
772
  var(--ty-secondary-hue)
511
773
  );
512
774
  --ty-color-secondary-soft: oklch(
513
- var(--ty-l-soft) calc(var(--ty-secondary-chroma) * var(--ty-c-soft-mult))
775
+ calc(var(--ty-l-soft) * var(--ty-secondary-l-factor))
776
+ calc(var(--ty-secondary-chroma) * var(--ty-c-soft-mult))
514
777
  var(--ty-secondary-hue)
515
778
  );
516
779
  --ty-color-secondary-faint: oklch(
517
- var(--ty-l-faint) calc(var(--ty-secondary-chroma) * var(--ty-c-faint-mult))
780
+ calc(var(--ty-l-faint) * var(--ty-secondary-l-factor))
781
+ calc(var(--ty-secondary-chroma) * var(--ty-c-faint-mult))
518
782
  var(--ty-secondary-hue)
519
783
  );
520
784
  --ty-bg-secondary: oklch(
521
- var(--ty-l-bg-base)
785
+ calc(var(--ty-l-bg-base) * var(--ty-secondary-l-factor))
522
786
  calc(var(--ty-secondary-chroma) * var(--ty-c-bg-base-mult))
523
787
  var(--ty-secondary-hue)
524
788
  );
525
789
  --ty-bg-secondary-bold: oklch(
526
- var(--ty-l-bg-bold)
790
+ calc(var(--ty-l-bg-bold) * var(--ty-secondary-l-factor))
527
791
  calc(var(--ty-secondary-chroma) * var(--ty-c-bg-bold-mult))
528
792
  var(--ty-secondary-hue)
529
793
  );
530
794
  --ty-bg-secondary-soft: oklch(
531
- var(--ty-l-bg-soft)
795
+ calc(var(--ty-l-bg-soft) * var(--ty-secondary-l-factor))
532
796
  calc(var(--ty-secondary-chroma) * var(--ty-c-bg-soft-mult))
533
797
  var(--ty-secondary-hue)
534
798
  );
@@ -536,37 +800,42 @@ html[data-theme="dark"] {
536
800
 
537
801
  /* Success */
538
802
  --ty-color-success-strong: oklch(
539
- var(--ty-l-strong) calc(var(--ty-success-chroma) * var(--ty-c-strong-mult))
803
+ calc(var(--ty-l-strong) * var(--ty-success-l-factor))
804
+ calc(var(--ty-success-chroma) * var(--ty-c-strong-mult))
540
805
  var(--ty-success-hue)
541
806
  );
542
807
  --ty-color-success-bold: oklch(
543
- var(--ty-l-bold) calc(var(--ty-success-chroma) * var(--ty-c-bold-mult))
808
+ calc(var(--ty-l-bold) * var(--ty-success-l-factor))
809
+ calc(var(--ty-success-chroma) * var(--ty-c-bold-mult))
544
810
  var(--ty-success-hue)
545
811
  );
546
812
  --ty-color-success: oklch(
547
- var(--ty-l-base) calc(var(--ty-success-chroma) * var(--ty-c-base-mult))
813
+ calc(var(--ty-l-base) * var(--ty-success-l-factor))
814
+ calc(var(--ty-success-chroma) * var(--ty-c-base-mult))
548
815
  var(--ty-success-hue)
549
816
  );
550
817
  --ty-color-success-soft: oklch(
551
- var(--ty-l-soft) calc(var(--ty-success-chroma) * var(--ty-c-soft-mult))
818
+ calc(var(--ty-l-soft) * var(--ty-success-l-factor))
819
+ calc(var(--ty-success-chroma) * var(--ty-c-soft-mult))
552
820
  var(--ty-success-hue)
553
821
  );
554
822
  --ty-color-success-faint: oklch(
555
- var(--ty-l-faint) calc(var(--ty-success-chroma) * var(--ty-c-faint-mult))
823
+ calc(var(--ty-l-faint) * var(--ty-success-l-factor))
824
+ calc(var(--ty-success-chroma) * var(--ty-c-faint-mult))
556
825
  var(--ty-success-hue)
557
826
  );
558
827
  --ty-bg-success: oklch(
559
- var(--ty-l-bg-base)
828
+ calc(var(--ty-l-bg-base) * var(--ty-success-l-factor))
560
829
  calc(var(--ty-success-chroma) * var(--ty-c-bg-base-mult))
561
830
  var(--ty-success-hue)
562
831
  );
563
832
  --ty-bg-success-bold: oklch(
564
- var(--ty-l-bg-bold)
833
+ calc(var(--ty-l-bg-bold) * var(--ty-success-l-factor))
565
834
  calc(var(--ty-success-chroma) * var(--ty-c-bg-bold-mult))
566
835
  var(--ty-success-hue)
567
836
  );
568
837
  --ty-bg-success-soft: oklch(
569
- var(--ty-l-bg-soft)
838
+ calc(var(--ty-l-bg-soft) * var(--ty-success-l-factor))
570
839
  calc(var(--ty-success-chroma) * var(--ty-c-bg-soft-mult))
571
840
  var(--ty-success-hue)
572
841
  );
@@ -574,72 +843,82 @@ html[data-theme="dark"] {
574
843
 
575
844
  /* Danger */
576
845
  --ty-color-danger-strong: oklch(
577
- var(--ty-l-strong) calc(var(--ty-danger-chroma) * var(--ty-c-strong-mult))
846
+ calc(var(--ty-l-strong) * var(--ty-danger-l-factor))
847
+ calc(var(--ty-danger-chroma) * var(--ty-c-strong-mult))
578
848
  var(--ty-danger-hue)
579
849
  );
580
850
  --ty-color-danger-bold: oklch(
581
- var(--ty-l-bold) calc(var(--ty-danger-chroma) * var(--ty-c-bold-mult))
582
- var(--ty-danger-hue)
851
+ calc(var(--ty-l-bold) * var(--ty-danger-l-factor))
852
+ calc(var(--ty-danger-chroma) * var(--ty-c-bold-mult)) var(--ty-danger-hue)
583
853
  );
584
854
  --ty-color-danger: oklch(
585
- var(--ty-l-base) calc(var(--ty-danger-chroma) * var(--ty-c-base-mult))
586
- var(--ty-danger-hue)
855
+ calc(var(--ty-l-base) * var(--ty-danger-l-factor))
856
+ calc(var(--ty-danger-chroma) * var(--ty-c-base-mult)) var(--ty-danger-hue)
587
857
  );
588
858
  --ty-color-danger-soft: oklch(
589
- var(--ty-l-soft) calc(var(--ty-danger-chroma) * var(--ty-c-soft-mult))
590
- var(--ty-danger-hue)
859
+ calc(var(--ty-l-soft) * var(--ty-danger-l-factor))
860
+ calc(var(--ty-danger-chroma) * var(--ty-c-soft-mult)) var(--ty-danger-hue)
591
861
  );
592
862
  --ty-color-danger-faint: oklch(
593
- var(--ty-l-faint) calc(var(--ty-danger-chroma) * var(--ty-c-faint-mult))
863
+ calc(var(--ty-l-faint) * var(--ty-danger-l-factor))
864
+ calc(var(--ty-danger-chroma) * var(--ty-c-faint-mult))
594
865
  var(--ty-danger-hue)
595
866
  );
596
867
  --ty-bg-danger: oklch(
597
- var(--ty-l-bg-base) calc(var(--ty-danger-chroma) * var(--ty-c-bg-base-mult))
868
+ calc(var(--ty-l-bg-base) * var(--ty-danger-l-factor))
869
+ calc(var(--ty-danger-chroma) * var(--ty-c-bg-base-mult))
598
870
  var(--ty-danger-hue)
599
871
  );
600
872
  --ty-bg-danger-bold: oklch(
601
- var(--ty-l-bg-bold) calc(var(--ty-danger-chroma) * var(--ty-c-bg-bold-mult))
873
+ calc(var(--ty-l-bg-bold) * var(--ty-danger-l-factor))
874
+ calc(var(--ty-danger-chroma) * var(--ty-c-bg-bold-mult))
602
875
  var(--ty-danger-hue)
603
876
  );
604
877
  --ty-bg-danger-soft: oklch(
605
- var(--ty-l-bg-soft) calc(var(--ty-danger-chroma) * var(--ty-c-bg-soft-mult))
878
+ calc(var(--ty-l-bg-soft) * var(--ty-danger-l-factor))
879
+ calc(var(--ty-danger-chroma) * var(--ty-c-bg-soft-mult))
606
880
  var(--ty-danger-hue)
607
881
  );
608
882
  --ty-border-danger: var(--ty-color-danger-soft);
609
883
 
610
884
  /* Warning */
611
885
  --ty-color-warning-strong: oklch(
612
- var(--ty-l-strong) calc(var(--ty-warning-chroma) * var(--ty-c-strong-mult))
886
+ calc(var(--ty-l-strong) * var(--ty-warning-l-factor))
887
+ calc(var(--ty-warning-chroma) * var(--ty-c-strong-mult))
613
888
  var(--ty-warning-hue)
614
889
  );
615
890
  --ty-color-warning-bold: oklch(
616
- var(--ty-l-bold) calc(var(--ty-warning-chroma) * var(--ty-c-bold-mult))
891
+ calc(var(--ty-l-bold) * var(--ty-warning-l-factor))
892
+ calc(var(--ty-warning-chroma) * var(--ty-c-bold-mult))
617
893
  var(--ty-warning-hue)
618
894
  );
619
895
  --ty-color-warning: oklch(
620
- var(--ty-l-base) calc(var(--ty-warning-chroma) * var(--ty-c-base-mult))
896
+ calc(var(--ty-l-base) * var(--ty-warning-l-factor))
897
+ calc(var(--ty-warning-chroma) * var(--ty-c-base-mult))
621
898
  var(--ty-warning-hue)
622
899
  );
623
900
  --ty-color-warning-soft: oklch(
624
- var(--ty-l-soft) calc(var(--ty-warning-chroma) * var(--ty-c-soft-mult))
901
+ calc(var(--ty-l-soft) * var(--ty-warning-l-factor))
902
+ calc(var(--ty-warning-chroma) * var(--ty-c-soft-mult))
625
903
  var(--ty-warning-hue)
626
904
  );
627
905
  --ty-color-warning-faint: oklch(
628
- var(--ty-l-faint) calc(var(--ty-warning-chroma) * var(--ty-c-faint-mult))
906
+ calc(var(--ty-l-faint) * var(--ty-warning-l-factor))
907
+ calc(var(--ty-warning-chroma) * var(--ty-c-faint-mult))
629
908
  var(--ty-warning-hue)
630
909
  );
631
910
  --ty-bg-warning: oklch(
632
- var(--ty-l-bg-base)
911
+ calc(var(--ty-l-bg-base) * var(--ty-warning-l-factor))
633
912
  calc(var(--ty-warning-chroma) * var(--ty-c-bg-base-mult))
634
913
  var(--ty-warning-hue)
635
914
  );
636
915
  --ty-bg-warning-bold: oklch(
637
- var(--ty-l-bg-bold)
916
+ calc(var(--ty-l-bg-bold) * var(--ty-warning-l-factor))
638
917
  calc(var(--ty-warning-chroma) * var(--ty-c-bg-bold-mult))
639
918
  var(--ty-warning-hue)
640
919
  );
641
920
  --ty-bg-warning-soft: oklch(
642
- var(--ty-l-bg-soft)
921
+ calc(var(--ty-l-bg-soft) * var(--ty-warning-l-factor))
643
922
  calc(var(--ty-warning-chroma) * var(--ty-c-bg-soft-mult))
644
923
  var(--ty-warning-hue)
645
924
  );
@@ -647,37 +926,42 @@ html[data-theme="dark"] {
647
926
 
648
927
  /* Neutral */
649
928
  --ty-color-neutral-strong: oklch(
650
- var(--ty-l-strong) calc(var(--ty-neutral-chroma) * var(--ty-c-strong-mult))
929
+ calc(var(--ty-l-strong) * var(--ty-neutral-l-factor))
930
+ calc(var(--ty-neutral-chroma) * var(--ty-c-strong-mult))
651
931
  var(--ty-neutral-hue)
652
932
  );
653
933
  --ty-color-neutral-bold: oklch(
654
- var(--ty-l-bold) calc(var(--ty-neutral-chroma) * var(--ty-c-bold-mult))
934
+ calc(var(--ty-l-bold) * var(--ty-neutral-l-factor))
935
+ calc(var(--ty-neutral-chroma) * var(--ty-c-bold-mult))
655
936
  var(--ty-neutral-hue)
656
937
  );
657
938
  --ty-color-neutral: oklch(
658
- var(--ty-l-base) calc(var(--ty-neutral-chroma) * var(--ty-c-base-mult))
939
+ calc(var(--ty-l-base) * var(--ty-neutral-l-factor))
940
+ calc(var(--ty-neutral-chroma) * var(--ty-c-base-mult))
659
941
  var(--ty-neutral-hue)
660
942
  );
661
943
  --ty-color-neutral-soft: oklch(
662
- var(--ty-l-soft) calc(var(--ty-neutral-chroma) * var(--ty-c-soft-mult))
944
+ calc(var(--ty-l-soft) * var(--ty-neutral-l-factor))
945
+ calc(var(--ty-neutral-chroma) * var(--ty-c-soft-mult))
663
946
  var(--ty-neutral-hue)
664
947
  );
665
948
  --ty-color-neutral-faint: oklch(
666
- var(--ty-l-faint) calc(var(--ty-neutral-chroma) * var(--ty-c-faint-mult))
949
+ calc(var(--ty-l-faint) * var(--ty-neutral-l-factor))
950
+ calc(var(--ty-neutral-chroma) * var(--ty-c-faint-mult))
667
951
  var(--ty-neutral-hue)
668
952
  );
669
953
  --ty-bg-neutral: oklch(
670
- var(--ty-l-bg-base)
954
+ calc(var(--ty-l-bg-base) * var(--ty-neutral-l-factor))
671
955
  calc(var(--ty-neutral-chroma) * var(--ty-c-bg-base-mult))
672
956
  var(--ty-neutral-hue)
673
957
  );
674
958
  --ty-bg-neutral-bold: oklch(
675
- var(--ty-l-bg-bold)
959
+ calc(var(--ty-l-bg-bold) * var(--ty-neutral-l-factor))
676
960
  calc(var(--ty-neutral-chroma) * var(--ty-c-bg-bold-mult))
677
961
  var(--ty-neutral-hue)
678
962
  );
679
963
  --ty-bg-neutral-soft: oklch(
680
- var(--ty-l-bg-soft)
964
+ calc(var(--ty-l-bg-soft) * var(--ty-neutral-l-factor))
681
965
  calc(var(--ty-neutral-chroma) * var(--ty-c-bg-soft-mult))
682
966
  var(--ty-neutral-hue)
683
967
  );
@@ -702,13 +986,11 @@ html[data-theme="dark"] {
702
986
  --ty-surface-floating: oklch(0.22 0.015 var(--ty-brand-hue));
703
987
  --ty-surface-input: oklch(0.18 0.012 var(--ty-brand-hue));
704
988
 
705
- /* Inputs — re-declared so tyrell.css's hardcoded dark values don't
706
- * out-rank our brand-derived ones (same selector specificity, source
707
- * order wins). */
989
+ /* Inputs — re-declared at html.dark specificity. */
708
990
  --ty-input-bg: var(--ty-surface-input);
709
991
  --ty-input-color: var(--ty-color-neutral-strong);
710
992
  --ty-input-border: var(--ty-color-neutral-faint);
711
- --ty-input-border-hover: var(--ty-color-neutral-bold);
993
+ --ty-input-border-hover: var(--ty-color-neutral-soft);
712
994
  --ty-input-border-focus: var(--ty-color-primary);
713
995
  --ty-input-placeholder: var(--ty-color-neutral-soft);
714
996
  --ty-input-disabled-bg: var(--ty-color-neutral-faint);
@@ -720,48 +1002,10 @@ html[data-theme="dark"] {
720
1002
  transparent
721
1003
  );
722
1004
 
723
- /* Solid buttonssame reason. */
724
- --ty-solid-primary: var(--ty-color-primary);
725
- --ty-solid-primary-strong: var(--ty-color-primary-bold);
726
- --ty-solid-primary-soft: var(--ty-color-primary-soft);
727
- --ty-solid-primary-fg: white;
728
-
729
- --ty-solid-secondary: var(--ty-color-secondary);
730
- --ty-solid-secondary-strong: var(--ty-color-secondary-bold);
731
- --ty-solid-secondary-soft: var(--ty-color-secondary-soft);
732
- --ty-solid-secondary-fg: white;
733
-
734
- --ty-solid-success: var(--ty-color-success);
735
- --ty-solid-success-strong: var(--ty-color-success-bold);
736
- --ty-solid-success-soft: var(--ty-color-success-soft);
737
- --ty-solid-success-fg: white;
738
-
739
- --ty-solid-danger: var(--ty-color-danger);
740
- --ty-solid-danger-strong: var(--ty-color-danger-bold);
741
- --ty-solid-danger-soft: var(--ty-color-danger-soft);
742
- --ty-solid-danger-fg: white;
743
-
744
- --ty-solid-warning: var(--ty-color-warning);
745
- --ty-solid-warning-strong: var(--ty-color-warning-bold);
746
- --ty-solid-warning-soft: var(--ty-color-warning-soft);
747
- --ty-solid-warning-fg: white;
748
-
749
- /* Solid neutral — see comment in the :root block. In dark mode the
750
- * "dark grey" position lives at the OTHER end of the ramp (faint),
751
- * because the L-curve inverts. Both modes get "a darker shade than
752
- * the page surface" for a punchy default action. */
753
- --ty-solid-neutral-soft: oklch(
754
- 0.2 calc(var(--ty-neutral-chroma) * var(--ty-c-strong-mult))
755
- var(--ty-neutral-hue)
756
- );
1005
+ /* Tier 6 dark solid dials live in SECTION 1's html.dark block.
1006
+ * neutral is hand-pinned (it ignores Axis B); dim it per theme here. */
757
1007
  --ty-solid-neutral: oklch(
758
1008
  0.3 calc(var(--ty-neutral-chroma) * var(--ty-c-strong-mult))
759
1009
  var(--ty-neutral-hue)
760
1010
  );
761
-
762
- --ty-solid-neutral-strong: oklch(
763
- 0.4 calc(var(--ty-neutral-chroma) * var(--ty-c-strong-mult))
764
- var(--ty-neutral-hue)
765
- );
766
- --ty-solid-neutral-fg: white;
767
1011
  }