tyrell-components 1.0.0-TC23 → 1.0.0-TC25

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.
Files changed (59) hide show
  1. package/css/tyrell-brand.css +176 -78
  2. package/css/tyrell-simple.css +257 -0
  3. package/css/tyrell.css +34 -20
  4. package/dist/tyrell-brand.css +176 -78
  5. package/dist/tyrell.css +34 -20
  6. package/dist/tyrell.js +1 -1
  7. package/lib/base/ty-component.d.ts +7 -0
  8. package/lib/base/ty-component.d.ts.map +1 -1
  9. package/lib/base/ty-component.js +27 -0
  10. package/lib/base/ty-component.js.map +1 -1
  11. package/lib/components/checkbox.d.ts +2 -0
  12. package/lib/components/checkbox.d.ts.map +1 -1
  13. package/lib/components/checkbox.js +20 -0
  14. package/lib/components/checkbox.js.map +1 -1
  15. package/lib/components/input.d.ts +8 -0
  16. package/lib/components/input.d.ts.map +1 -1
  17. package/lib/components/input.js +50 -4
  18. package/lib/components/input.js.map +1 -1
  19. package/lib/components/radio.d.ts.map +1 -1
  20. package/lib/components/radio.js +2 -0
  21. package/lib/components/radio.js.map +1 -1
  22. package/lib/components/scroll-container.d.ts +16 -0
  23. package/lib/components/scroll-container.d.ts.map +1 -1
  24. package/lib/components/scroll-container.js +105 -1
  25. package/lib/components/scroll-container.js.map +1 -1
  26. package/lib/components/switch.d.ts +2 -0
  27. package/lib/components/switch.d.ts.map +1 -1
  28. package/lib/components/switch.js +18 -0
  29. package/lib/components/switch.js.map +1 -1
  30. package/lib/components/textarea.d.ts +3 -0
  31. package/lib/components/textarea.d.ts.map +1 -1
  32. package/lib/components/textarea.js +61 -6
  33. package/lib/components/textarea.js.map +1 -1
  34. package/lib/styles/button.d.ts +5 -2
  35. package/lib/styles/button.d.ts.map +1 -1
  36. package/lib/styles/button.js +35 -71
  37. package/lib/styles/button.js.map +1 -1
  38. package/lib/styles/calendar-month.d.ts +1 -1
  39. package/lib/styles/calendar-month.d.ts.map +1 -1
  40. package/lib/styles/calendar-month.js +26 -58
  41. package/lib/styles/calendar-month.js.map +1 -1
  42. package/lib/styles/calendar-navigation.d.ts +1 -1
  43. package/lib/styles/calendar-navigation.d.ts.map +1 -1
  44. package/lib/styles/calendar-navigation.js +10 -32
  45. package/lib/styles/calendar-navigation.js.map +1 -1
  46. package/lib/styles/scroll-container.d.ts +1 -1
  47. package/lib/styles/scroll-container.d.ts.map +1 -1
  48. package/lib/styles/scroll-container.js +6 -0
  49. package/lib/styles/scroll-container.js.map +1 -1
  50. package/lib/styles/tag.d.ts +1 -1
  51. package/lib/styles/tag.d.ts.map +1 -1
  52. package/lib/styles/tag.js +5 -5
  53. package/lib/styles/textarea.d.ts +1 -1
  54. package/lib/styles/textarea.d.ts.map +1 -1
  55. package/lib/styles/textarea.js +67 -33
  56. package/lib/styles/textarea.js.map +1 -1
  57. package/lib/version.d.ts +1 -1
  58. package/lib/version.js +1 -1
  59. package/package.json +10 -2
@@ -54,15 +54,19 @@
54
54
  * FILE LAYOUT
55
55
  * =====================================================================
56
56
  *
57
- * SECTION 1 — KNOBS (~lines 80–225)
58
- * The variables you might want to override. Five tiers from drop-in
59
- * rebrand (Tier 1) to surgical per-flavor tweak (Tier 5).
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).
60
61
  *
61
62
  * SECTION 2 — IMPLEMENTATION
62
63
  * The oklch() expressions that wire the knobs through to the actual
63
64
  * color tokens. Rarely needs editing — Section 1 is the contract.
64
65
  *
65
- * Browser support: OKLCH is in every evergreen browser since mid-2023.
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.
66
70
  *
67
71
  * ===================================================================== */
68
72
 
@@ -81,6 +85,8 @@
81
85
  * Tier 5 — PER-FLAVOR L-FACTOR per-flavor lightness multiplier — push
82
86
  * one flavor up or down without touching
83
87
  * the others. Default 1.
88
+ * Tier 6 — SOLID FILLS solid-button system: hover/active/tone
89
+ * L offsets + per-theme dim/desaturate.
84
90
  * ===================================================================== */
85
91
 
86
92
  :root {
@@ -91,7 +97,7 @@
91
97
  * --------------------------------------------------------------*/
92
98
 
93
99
  --ty-brand-hue: 230;
94
- --ty-brand-chroma: 0.13;
100
+ --ty-brand-chroma: 0.2;
95
101
 
96
102
  /* Secondary rotates from brand by an exposed offset. Default +60°
97
103
  * (sibling accent). Try 30° for a close sibling, 120° for triadic,
@@ -180,6 +186,33 @@
180
186
  --ty-warning-l-factor: 1.15;
181
187
  --ty-danger-l-factor: 1;
182
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) */
183
216
  }
184
217
 
185
218
  /* Dark mode overrides for the L-curve and saturation curve. Tier 1 + 2
@@ -188,8 +221,8 @@ html.dark,
188
221
  html[data-theme="dark"] {
189
222
  /* Tier 3 dark — inverted curve. Higher L = lighter text = more
190
223
  * emphasis on a dark background. */
191
- --ty-l-strong: 0.86;
192
- --ty-l-bold: 0.74;
224
+ --ty-l-strong: 0.72;
225
+ --ty-l-bold: 0.66;
193
226
  --ty-l-base: 0.62;
194
227
  --ty-l-soft: 0.46;
195
228
  --ty-l-faint: 0.3;
@@ -209,6 +242,18 @@ html[data-theme="dark"] {
209
242
  --ty-c-bg-base-mult: 0.38;
210
243
  --ty-c-bg-bold-mult: 0.54;
211
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 */
212
257
  }
213
258
 
214
259
  /* =====================================================================
@@ -529,48 +574,137 @@ html[data-theme="dark"] {
529
574
  var(--ty-color-primary) 5%,
530
575
  transparent
531
576
  );
577
+ }
532
578
 
533
- /* ----------------------------------------------------------------
534
- * Solid buttonsre-route through --ty-color-*.
535
- * --------------------------------------------------------------*/
536
- --ty-solid-primary: var(--ty-color-primary);
537
- --ty-solid-primary-strong: var(--ty-color-primary-bold);
538
- --ty-solid-primary-soft: var(--ty-color-primary-soft);
539
- --ty-solid-primary-fg: white;
579
+ /* ----------------------------------------------------------------
580
+ * Tier 6SOLID (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
+ );
540
623
 
541
- --ty-solid-secondary: var(--ty-color-secondary);
542
- --ty-solid-secondary-strong: var(--ty-color-secondary-bold);
543
- --ty-solid-secondary-soft: var(--ty-color-secondary-soft);
624
+ --ty-solid-primary-fg: white;
544
625
  --ty-solid-secondary-fg: white;
545
-
546
- --ty-solid-success: var(--ty-color-success);
547
- --ty-solid-success-strong: var(--ty-color-success-bold);
548
- --ty-solid-success-soft: var(--ty-color-success-soft);
549
626
  --ty-solid-success-fg: white;
550
-
551
- --ty-solid-danger: var(--ty-color-danger);
552
- --ty-solid-danger-strong: var(--ty-color-danger-bold);
553
- --ty-solid-danger-soft: var(--ty-color-danger-soft);
554
627
  --ty-solid-danger-fg: white;
555
-
556
- --ty-solid-warning: var(--ty-color-warning);
557
- --ty-solid-warning-strong: var(--ty-color-warning-bold);
558
- --ty-solid-warning-soft: var(--ty-color-warning-soft);
559
628
  --ty-solid-warning-fg: white;
629
+ --ty-solid-neutral-fg: white;
560
630
 
561
- /* Solid neutral routes to a darker shade than neutral-base. The "soft"
562
- * solid-neutral softens to a mid-grey for inactive states. */
563
- --ty-solid-neutral-soft: oklch(
564
- 0.6 calc(var(--ty-neutral-chroma) * var(--ty-c-strong-mult))
565
- var(--ty-neutral-hue)
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
566
634
  );
567
- --ty-solid-neutral: oklch(
568
- 0.4 calc(var(--ty-neutral-chroma) * var(--ty-c-strong-mult))
569
- var(--ty-neutral-hue)
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
+ );
644
+
645
+ --ty-solid-secondary-hover: oklch(
646
+ from var(--ty-solid-secondary) calc(l + var(--ty-solid-hover-l)) c h
647
+ );
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
695
+ );
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
570
702
  );
571
703
  --ty-solid-neutral-strong: oklch(
572
- 0.2 calc(var(--ty-neutral-chroma) * var(--ty-c-strong-mult))
573
- 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
574
708
  );
575
709
  }
576
710
 
@@ -856,7 +990,7 @@ html[data-theme="dark"] {
856
990
  --ty-input-bg: var(--ty-surface-input);
857
991
  --ty-input-color: var(--ty-color-neutral-strong);
858
992
  --ty-input-border: var(--ty-color-neutral-faint);
859
- --ty-input-border-hover: var(--ty-color-neutral-bold);
993
+ --ty-input-border-hover: var(--ty-color-neutral-soft);
860
994
  --ty-input-border-focus: var(--ty-color-primary);
861
995
  --ty-input-placeholder: var(--ty-color-neutral-soft);
862
996
  --ty-input-disabled-bg: var(--ty-color-neutral-faint);
@@ -868,46 +1002,10 @@ html[data-theme="dark"] {
868
1002
  transparent
869
1003
  );
870
1004
 
871
- /* Solid buttons */
872
- --ty-solid-primary: var(--ty-color-primary);
873
- --ty-solid-primary-strong: var(--ty-color-primary-bold);
874
- --ty-solid-primary-soft: var(--ty-color-primary-soft);
875
- --ty-solid-primary-fg: white;
876
-
877
- --ty-solid-secondary: var(--ty-color-secondary);
878
- --ty-solid-secondary-strong: var(--ty-color-secondary-bold);
879
- --ty-solid-secondary-soft: var(--ty-color-secondary-soft);
880
- --ty-solid-secondary-fg: white;
881
-
882
- --ty-solid-success: var(--ty-color-success);
883
- --ty-solid-success-strong: var(--ty-color-success-bold);
884
- --ty-solid-success-soft: var(--ty-color-success-soft);
885
- --ty-solid-success-fg: white;
886
-
887
- --ty-solid-danger: var(--ty-color-danger);
888
- --ty-solid-danger-strong: var(--ty-color-danger-bold);
889
- --ty-solid-danger-soft: var(--ty-color-danger-soft);
890
- --ty-solid-danger-fg: white;
891
-
892
- --ty-solid-warning: var(--ty-color-warning);
893
- --ty-solid-warning-strong: var(--ty-color-warning-bold);
894
- --ty-solid-warning-soft: var(--ty-color-warning-soft);
895
- --ty-solid-warning-fg: white;
896
-
897
- /* Solid neutral — in dark mode, "dark grey" lives at the other end
898
- * of the ramp. Both modes get a shade darker than the page surface
899
- * for a punchy default action. */
900
- --ty-solid-neutral-soft: oklch(
901
- 0.2 calc(var(--ty-neutral-chroma) * var(--ty-c-strong-mult))
902
- var(--ty-neutral-hue)
903
- );
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. */
904
1007
  --ty-solid-neutral: oklch(
905
1008
  0.3 calc(var(--ty-neutral-chroma) * var(--ty-c-strong-mult))
906
1009
  var(--ty-neutral-hue)
907
1010
  );
908
- --ty-solid-neutral-strong: oklch(
909
- 0.4 calc(var(--ty-neutral-chroma) * var(--ty-c-strong-mult))
910
- var(--ty-neutral-hue)
911
- );
912
- --ty-solid-neutral-fg: white;
913
1011
  }
@@ -0,0 +1,257 @@
1
+ /* =====================================================================
2
+ * tyrell-simple.css — the lightweight color-mix theme engine for Tyrell
3
+ * =====================================================================
4
+ *
5
+ * EXPERIMENTAL, opt-in. The SIMPLE counterpart to tyrell-brand.css (the
6
+ * complex OKLCH engine). Same job — fill the color-token contract — with
7
+ * far fewer moving parts. Load it INSTEAD of tyrell-brand.css:
8
+ *
9
+ * <link rel="stylesheet" href=".../tyrell.css"> <!-- structure + default colors -->
10
+ * <link rel="stylesheet" href=".../tyrell-simple.css"> <!-- overrides colors -->
11
+ *
12
+ * THE WHOLE MODEL
13
+ * ---------------
14
+ * Every color is one expression:
15
+ * color-mix(in oklch, <ink>, var(--ty-bg) STOP%)
16
+ * - --ty-bg the page/background pole
17
+ * - --ty-ink-{role} the saturated emphasis pole for each role
18
+ * - STOP how far toward the background (shared, see below)
19
+ *
20
+ * Inputs are ~7 anchors per theme (page bg + 6 inks). Everything else is
21
+ * derived ONCE in :root. Dark mode only re-points those anchors — the
22
+ * whole palette falls out. No second curve, no sign-flips, no duplication.
23
+ *
24
+ * Rebrand: change the 6 inks. Retune contrast: change the STOP percentages.
25
+ *
26
+ * Needs oklch() + color-mix() + relative color (oklch(from …)) for solids:
27
+ * Chrome 119 / Safari 16.4 / Firefox 128 (mid-2024).
28
+ * ===================================================================== */
29
+
30
+ :root {
31
+ /* ---- shared emphasis stops (% toward --ty-bg). One curve, both themes. ---- */
32
+ --ty-s-strong: 0%;
33
+ --ty-s-bold: 16%;
34
+ --ty-s-base: 32%;
35
+ --ty-s-soft: 56%;
36
+ --ty-s-faint: 78%;
37
+ /* background tints: mostly bg, a breath of ink */
38
+ --ty-bgs-bold: 82%;
39
+ --ty-bgs-base: 88%;
40
+ --ty-bgs-soft: 94%;
41
+
42
+ /* ====================== ANCHORS (light) ====================== */
43
+ --ty-bg: oklch(0.99 0.003 250); /* page pole */
44
+ --ty-ink-primary: oklch(0.55 0.15 250);
45
+ --ty-ink-secondary: oklch(0.55 0.16 300);
46
+ --ty-ink-success: oklch(0.55 0.13 150);
47
+ --ty-ink-danger: oklch(0.55 0.17 25);
48
+ --ty-ink-warning: oklch(0.68 0.15 75);
49
+ --ty-ink-neutral: oklch(0.30 0.012 250);
50
+
51
+ /* ====================== DERIVED — everything below references anchors ===== */
52
+
53
+ /* ---- flavor color ramps ---- */
54
+ --ty-color-primary-strong: color-mix(in oklch, var(--ty-ink-primary), var(--ty-bg) var(--ty-s-strong));
55
+ --ty-color-primary-bold: color-mix(in oklch, var(--ty-ink-primary), var(--ty-bg) var(--ty-s-bold));
56
+ --ty-color-primary: color-mix(in oklch, var(--ty-ink-primary), var(--ty-bg) var(--ty-s-base));
57
+ --ty-color-primary-soft: color-mix(in oklch, var(--ty-ink-primary), var(--ty-bg) var(--ty-s-soft));
58
+ --ty-color-primary-faint: color-mix(in oklch, var(--ty-ink-primary), var(--ty-bg) var(--ty-s-faint));
59
+
60
+ --ty-color-secondary-strong: color-mix(in oklch, var(--ty-ink-secondary), var(--ty-bg) var(--ty-s-strong));
61
+ --ty-color-secondary-bold: color-mix(in oklch, var(--ty-ink-secondary), var(--ty-bg) var(--ty-s-bold));
62
+ --ty-color-secondary: color-mix(in oklch, var(--ty-ink-secondary), var(--ty-bg) var(--ty-s-base));
63
+ --ty-color-secondary-soft: color-mix(in oklch, var(--ty-ink-secondary), var(--ty-bg) var(--ty-s-soft));
64
+ --ty-color-secondary-faint: color-mix(in oklch, var(--ty-ink-secondary), var(--ty-bg) var(--ty-s-faint));
65
+
66
+ --ty-color-success-strong: color-mix(in oklch, var(--ty-ink-success), var(--ty-bg) var(--ty-s-strong));
67
+ --ty-color-success-bold: color-mix(in oklch, var(--ty-ink-success), var(--ty-bg) var(--ty-s-bold));
68
+ --ty-color-success: color-mix(in oklch, var(--ty-ink-success), var(--ty-bg) var(--ty-s-base));
69
+ --ty-color-success-soft: color-mix(in oklch, var(--ty-ink-success), var(--ty-bg) var(--ty-s-soft));
70
+ --ty-color-success-faint: color-mix(in oklch, var(--ty-ink-success), var(--ty-bg) var(--ty-s-faint));
71
+
72
+ --ty-color-danger-strong: color-mix(in oklch, var(--ty-ink-danger), var(--ty-bg) var(--ty-s-strong));
73
+ --ty-color-danger-bold: color-mix(in oklch, var(--ty-ink-danger), var(--ty-bg) var(--ty-s-bold));
74
+ --ty-color-danger: color-mix(in oklch, var(--ty-ink-danger), var(--ty-bg) var(--ty-s-base));
75
+ --ty-color-danger-soft: color-mix(in oklch, var(--ty-ink-danger), var(--ty-bg) var(--ty-s-soft));
76
+ --ty-color-danger-faint: color-mix(in oklch, var(--ty-ink-danger), var(--ty-bg) var(--ty-s-faint));
77
+
78
+ --ty-color-warning-strong: color-mix(in oklch, var(--ty-ink-warning), var(--ty-bg) var(--ty-s-strong));
79
+ --ty-color-warning-bold: color-mix(in oklch, var(--ty-ink-warning), var(--ty-bg) var(--ty-s-bold));
80
+ --ty-color-warning: color-mix(in oklch, var(--ty-ink-warning), var(--ty-bg) var(--ty-s-base));
81
+ --ty-color-warning-soft: color-mix(in oklch, var(--ty-ink-warning), var(--ty-bg) var(--ty-s-soft));
82
+ --ty-color-warning-faint: color-mix(in oklch, var(--ty-ink-warning), var(--ty-bg) var(--ty-s-faint));
83
+
84
+ --ty-color-neutral-strong: var(--ty-ink-neutral);
85
+ --ty-color-neutral-bold: color-mix(in oklch, var(--ty-ink-neutral), var(--ty-bg) 8%);
86
+ --ty-color-neutral: color-mix(in oklch, var(--ty-ink-neutral), var(--ty-bg) 18%);
87
+ --ty-color-neutral-soft: color-mix(in oklch, var(--ty-ink-neutral), var(--ty-bg) 45%);
88
+ --ty-color-neutral-faint: color-mix(in oklch, var(--ty-ink-neutral), var(--ty-bg) 70%);
89
+
90
+ /* ---- text hierarchy (neutral ink → bg) ---- */
91
+ --ty-text-strong: var(--ty-ink-neutral);
92
+ --ty-text-bold: color-mix(in oklch, var(--ty-ink-neutral), var(--ty-bg) 8%);
93
+ --ty-text: color-mix(in oklch, var(--ty-ink-neutral), var(--ty-bg) 16%);
94
+ --ty-text-soft: color-mix(in oklch, var(--ty-ink-neutral), var(--ty-bg) 40%);
95
+ --ty-text-faint: color-mix(in oklch, var(--ty-ink-neutral), var(--ty-bg) 60%);
96
+
97
+ /* ---- soft background tints per flavor ---- */
98
+ --ty-bg-primary-bold: color-mix(in oklch, var(--ty-ink-primary), var(--ty-bg) var(--ty-bgs-bold));
99
+ --ty-bg-primary: color-mix(in oklch, var(--ty-ink-primary), var(--ty-bg) var(--ty-bgs-base));
100
+ --ty-bg-primary-soft: color-mix(in oklch, var(--ty-ink-primary), var(--ty-bg) var(--ty-bgs-soft));
101
+
102
+ --ty-bg-secondary-bold: color-mix(in oklch, var(--ty-ink-secondary), var(--ty-bg) var(--ty-bgs-bold));
103
+ --ty-bg-secondary: color-mix(in oklch, var(--ty-ink-secondary), var(--ty-bg) var(--ty-bgs-base));
104
+ --ty-bg-secondary-soft: color-mix(in oklch, var(--ty-ink-secondary), var(--ty-bg) var(--ty-bgs-soft));
105
+
106
+ --ty-bg-success-bold: color-mix(in oklch, var(--ty-ink-success), var(--ty-bg) var(--ty-bgs-bold));
107
+ --ty-bg-success: color-mix(in oklch, var(--ty-ink-success), var(--ty-bg) var(--ty-bgs-base));
108
+ --ty-bg-success-soft: color-mix(in oklch, var(--ty-ink-success), var(--ty-bg) var(--ty-bgs-soft));
109
+
110
+ --ty-bg-danger-bold: color-mix(in oklch, var(--ty-ink-danger), var(--ty-bg) var(--ty-bgs-bold));
111
+ --ty-bg-danger: color-mix(in oklch, var(--ty-ink-danger), var(--ty-bg) var(--ty-bgs-base));
112
+ --ty-bg-danger-soft: color-mix(in oklch, var(--ty-ink-danger), var(--ty-bg) var(--ty-bgs-soft));
113
+
114
+ --ty-bg-warning-bold: color-mix(in oklch, var(--ty-ink-warning), var(--ty-bg) var(--ty-bgs-bold));
115
+ --ty-bg-warning: color-mix(in oklch, var(--ty-ink-warning), var(--ty-bg) var(--ty-bgs-base));
116
+ --ty-bg-warning-soft: color-mix(in oklch, var(--ty-ink-warning), var(--ty-bg) var(--ty-bgs-soft));
117
+
118
+ --ty-bg-neutral-bold: color-mix(in oklch, var(--ty-ink-neutral), var(--ty-bg) var(--ty-bgs-bold));
119
+ --ty-bg-neutral: color-mix(in oklch, var(--ty-ink-neutral), var(--ty-bg) var(--ty-bgs-base));
120
+ --ty-bg-neutral-soft: color-mix(in oklch, var(--ty-ink-neutral), var(--ty-bg) var(--ty-bgs-soft));
121
+
122
+ /* ---- generic bg / elevation ---- */
123
+ --ty-bg-faint: var(--ty-bg);
124
+ --ty-bg-soft: color-mix(in oklch, var(--ty-bg), var(--ty-ink-neutral) 4%);
125
+ --ty-bg-bold: color-mix(in oklch, var(--ty-bg), var(--ty-ink-neutral) 8%);
126
+ --ty-bg-strong: color-mix(in oklch, var(--ty-bg), var(--ty-ink-neutral) 16%);
127
+ --ty-focus-ring-gap: var(--ty-bg);
128
+
129
+ /* ---- surfaces (elevate toward white in both themes) ---- */
130
+ --ty-surface-canvas: var(--ty-bg);
131
+ --ty-surface-content: color-mix(in oklab, var(--ty-bg), white 25%);
132
+ --ty-surface-elevated: color-mix(in oklab, var(--ty-bg), white 45%);
133
+ --ty-surface-floating: color-mix(in oklab, var(--ty-bg), white 60%);
134
+ --ty-surface-input: color-mix(in oklab, var(--ty-bg), white 30%);
135
+
136
+ /* ---- borders ---- */
137
+ --ty-border-strong: color-mix(in oklch, var(--ty-bg), var(--ty-ink-neutral) 40%);
138
+ --ty-border-bold: color-mix(in oklch, var(--ty-bg), var(--ty-ink-neutral) 22%);
139
+ --ty-border: color-mix(in oklch, var(--ty-bg), var(--ty-ink-neutral) 14%);
140
+ --ty-border-soft: color-mix(in oklch, var(--ty-bg), var(--ty-ink-neutral) 8%);
141
+ --ty-border-faint: color-mix(in oklch, var(--ty-bg), var(--ty-ink-neutral) 4%);
142
+
143
+ --ty-border-primary: var(--ty-color-primary-soft);
144
+ --ty-border-secondary: var(--ty-color-secondary-soft);
145
+ --ty-border-success: var(--ty-color-success-soft);
146
+ --ty-border-danger: var(--ty-color-danger-soft);
147
+ --ty-border-warning: var(--ty-color-warning-soft);
148
+ --ty-border-neutral: var(--ty-color-neutral);
149
+
150
+ --ty-elevated-border: var(--ty-border);
151
+ --ty-floating-border: var(--ty-border);
152
+ --ty-content-border: var(--ty-border);
153
+ --ty-canvas-border: transparent;
154
+
155
+ /* ---- scrollbar (neutral ink → transparent; auto-flips) ---- */
156
+ --ty-scrollbar-thumb: color-mix(in srgb, var(--ty-ink-neutral) 35%, transparent);
157
+ --ty-scrollbar-thumb-hover: color-mix(in srgb, var(--ty-ink-neutral) 50%, transparent);
158
+ --ty-scrollbar-thumb-active: color-mix(in srgb, var(--ty-ink-neutral) 60%, transparent);
159
+ --ty-scrollbar-track: transparent;
160
+ --ty-scrollbar-track-hover: color-mix(in srgb, var(--ty-ink-neutral) 8%, transparent);
161
+
162
+ /* ---- modal ---- */
163
+ --ty-modal-bg: var(--ty-surface-floating);
164
+ --ty-modal-color: var(--ty-text);
165
+ --ty-modal-border: var(--ty-border);
166
+ --ty-modal-backdrop: color-mix(in oklab, black 50%, transparent);
167
+ --ty-modal-shadow: var(--ty-shadow-xl);
168
+
169
+ /* ---- inputs ---- */
170
+ --ty-input-bg: var(--ty-surface-input);
171
+ --ty-input-color: var(--ty-text);
172
+ --ty-input-border: var(--ty-border-bold);
173
+ --ty-input-border-hover: var(--ty-border-strong);
174
+ --ty-input-border-focus: var(--ty-color-primary);
175
+ --ty-input-shadow-focus: color-mix(in srgb, var(--ty-color-primary) 12%, transparent);
176
+ --ty-input-placeholder: var(--ty-text-faint);
177
+ --ty-input-disabled-bg: var(--ty-bg-soft);
178
+ --ty-input-disabled-border: var(--ty-border);
179
+ --ty-input-disabled-color: var(--ty-text-faint);
180
+ --ty-label-color: var(--ty-text-soft);
181
+ --ty-input-success-border: var(--ty-color-success);
182
+ --ty-input-danger-border: var(--ty-color-danger);
183
+ --ty-input-warning-border: var(--ty-color-warning);
184
+
185
+ /* ====================== SOLID ====================== */
186
+ /* base fill = flavor ink; states via OKLCH L offsets (same axes as the
187
+ other engines). theme dim/desaturate via the dark block re-points ink. */
188
+ --ty-solid-hover-l: -0.04;
189
+ --ty-solid-active-l: -0.08;
190
+ --ty-solid-strong-l: -0.06;
191
+ --ty-solid-soft-l: 0.1;
192
+ /* solid fill lightness — PINNED, not the text ink (which flips light on dark).
193
+ Keeps fills a saturated mid so white fg stays legible in both themes. */
194
+ --ty-solid-base-l: 0.55;
195
+
196
+ --ty-solid-primary: oklch(from var(--ty-ink-primary) var(--ty-solid-base-l) c h);
197
+ --ty-solid-secondary: oklch(from var(--ty-ink-secondary) var(--ty-solid-base-l) c h);
198
+ --ty-solid-success: oklch(from var(--ty-ink-success) var(--ty-solid-base-l) c h);
199
+ --ty-solid-danger: oklch(from var(--ty-ink-danger) var(--ty-solid-base-l) c h);
200
+ --ty-solid-warning: oklch(from var(--ty-ink-warning) var(--ty-solid-base-l) c h);
201
+ --ty-solid-neutral: oklch(from var(--ty-ink-neutral) 0.4 c h);
202
+
203
+ --ty-solid-primary-fg: white;
204
+ --ty-solid-secondary-fg: white;
205
+ --ty-solid-success-fg: white;
206
+ --ty-solid-danger-fg: white;
207
+ --ty-solid-warning-fg: white;
208
+ --ty-solid-neutral-fg: white;
209
+
210
+ --ty-solid-primary-hover: oklch(from var(--ty-solid-primary) calc(l + var(--ty-solid-hover-l)) c h);
211
+ --ty-solid-primary-active: oklch(from var(--ty-solid-primary) calc(l + var(--ty-solid-active-l)) c h);
212
+ --ty-solid-primary-strong: oklch(from var(--ty-solid-primary) calc(l + var(--ty-solid-strong-l)) c h);
213
+ --ty-solid-primary-soft: oklch(from var(--ty-solid-primary) calc(l + var(--ty-solid-soft-l)) c h);
214
+
215
+ --ty-solid-secondary-hover: oklch(from var(--ty-solid-secondary) calc(l + var(--ty-solid-hover-l)) c h);
216
+ --ty-solid-secondary-active: oklch(from var(--ty-solid-secondary) calc(l + var(--ty-solid-active-l)) c h);
217
+ --ty-solid-secondary-strong: oklch(from var(--ty-solid-secondary) calc(l + var(--ty-solid-strong-l)) c h);
218
+ --ty-solid-secondary-soft: oklch(from var(--ty-solid-secondary) calc(l + var(--ty-solid-soft-l)) c h);
219
+
220
+ --ty-solid-success-hover: oklch(from var(--ty-solid-success) calc(l + var(--ty-solid-hover-l)) c h);
221
+ --ty-solid-success-active: oklch(from var(--ty-solid-success) calc(l + var(--ty-solid-active-l)) c h);
222
+ --ty-solid-success-strong: oklch(from var(--ty-solid-success) calc(l + var(--ty-solid-strong-l)) c h);
223
+ --ty-solid-success-soft: oklch(from var(--ty-solid-success) calc(l + var(--ty-solid-soft-l)) c h);
224
+
225
+ --ty-solid-danger-hover: oklch(from var(--ty-solid-danger) calc(l + var(--ty-solid-hover-l)) c h);
226
+ --ty-solid-danger-active: oklch(from var(--ty-solid-danger) calc(l + var(--ty-solid-active-l)) c h);
227
+ --ty-solid-danger-strong: oklch(from var(--ty-solid-danger) calc(l + var(--ty-solid-strong-l)) c h);
228
+ --ty-solid-danger-soft: oklch(from var(--ty-solid-danger) calc(l + var(--ty-solid-soft-l)) c h);
229
+
230
+ --ty-solid-warning-hover: oklch(from var(--ty-solid-warning) calc(l + var(--ty-solid-hover-l)) c h);
231
+ --ty-solid-warning-active: oklch(from var(--ty-solid-warning) calc(l + var(--ty-solid-active-l)) c h);
232
+ --ty-solid-warning-strong: oklch(from var(--ty-solid-warning) calc(l + var(--ty-solid-strong-l)) c h);
233
+ --ty-solid-warning-soft: oklch(from var(--ty-solid-warning) calc(l + var(--ty-solid-soft-l)) c h);
234
+
235
+ --ty-solid-neutral-hover: oklch(from var(--ty-solid-neutral) calc(l + var(--ty-solid-hover-l)) c h);
236
+ --ty-solid-neutral-active: oklch(from var(--ty-solid-neutral) calc(l + var(--ty-solid-active-l)) c h);
237
+ --ty-solid-neutral-strong: oklch(from var(--ty-solid-neutral) calc(l + var(--ty-solid-strong-l)) c h);
238
+ --ty-solid-neutral-soft: oklch(from var(--ty-solid-neutral) calc(l + var(--ty-solid-soft-l)) c h);
239
+ }
240
+
241
+ /* =====================================================================
242
+ * DARK — re-point the anchors ONLY. The whole palette above re-derives.
243
+ * Inks go lighter (emphasis inverts); page goes dark.
244
+ * ===================================================================== */
245
+ html.dark,
246
+ html[data-theme="dark"] {
247
+ --ty-bg: oklch(0.16 0.012 250);
248
+ --ty-ink-primary: oklch(0.80 0.12 250);
249
+ --ty-ink-secondary: oklch(0.80 0.13 300);
250
+ --ty-ink-success: oklch(0.80 0.11 150);
251
+ --ty-ink-danger: oklch(0.78 0.14 25);
252
+ --ty-ink-warning: oklch(0.84 0.13 75);
253
+ --ty-ink-neutral: oklch(0.88 0.008 250);
254
+
255
+ /* solids: dim the pinned fill slightly against the dark canvas */
256
+ --ty-solid-base-l: 0.50;
257
+ }